aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
committerThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
commitafae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch)
treed632cc867d10410ba9fb750523be790b86846ac4 /gcc
parent9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff)
parentd2eb616a0f7bea78164912aa438c29fe1ef5774a (diff)
downloadgcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.zip
gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.gz
gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.bz2
Merge branch 'master' into devel/coarray_native
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8026
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in48
-rw-r--r--gcc/ada/ChangeLog3131
-rw-r--r--gcc/ada/Makefile.rtl84
-rw-r--r--gcc/ada/ada_get_targ.adb32
-rw-r--r--gcc/ada/adabkend.adb3
-rw-r--r--gcc/ada/adaint.c31
-rw-r--r--gcc/ada/adaint.h10
-rw-r--r--gcc/ada/ali-util.adb10
-rw-r--r--gcc/ada/ali.adb10
-rw-r--r--gcc/ada/ali.ads4
-rw-r--r--gcc/ada/aspects.adb28
-rw-r--r--gcc/ada/aspects.ads50
-rw-r--r--gcc/ada/bindo-writers.adb2
-rw-r--r--gcc/ada/checks.adb252
-rw-r--r--gcc/ada/checks.ads16
-rw-r--r--gcc/ada/contracts.adb534
-rw-r--r--gcc/ada/contracts.ads15
-rw-r--r--gcc/ada/cstand.adb12
-rw-r--r--gcc/ada/debug.adb7
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst2
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst35
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst30
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst52
-rw-r--r--gcc/ada/doc/gnat_rm/intrinsic_subprograms.rst4
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst15
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst2
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst4
-rw-r--r--gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst4
-rw-r--r--gcc/ada/einfo.adb178
-rw-r--r--gcc/ada/einfo.ads50
-rw-r--r--gcc/ada/errout.adb25
-rw-r--r--gcc/ada/errout.ads16
-rw-r--r--gcc/ada/exp_aggr.adb68
-rw-r--r--gcc/ada/exp_attr.adb330
-rw-r--r--gcc/ada/exp_ch11.adb85
-rw-r--r--gcc/ada/exp_ch13.adb5
-rw-r--r--gcc/ada/exp_ch2.adb44
-rw-r--r--gcc/ada/exp_ch3.adb218
-rw-r--r--gcc/ada/exp_ch4.adb440
-rw-r--r--gcc/ada/exp_ch5.adb74
-rw-r--r--gcc/ada/exp_ch6.adb213
-rw-r--r--gcc/ada/exp_ch7.adb850
-rw-r--r--gcc/ada/exp_ch7.ads7
-rw-r--r--gcc/ada/exp_ch8.adb12
-rw-r--r--gcc/ada/exp_ch9.adb25
-rw-r--r--gcc/ada/exp_dbug.adb32
-rw-r--r--gcc/ada/exp_disp.adb2
-rw-r--r--gcc/ada/exp_dist.adb2
-rw-r--r--gcc/ada/exp_fixd.adb385
-rw-r--r--gcc/ada/exp_imgv.adb334
-rw-r--r--gcc/ada/exp_intr.adb15
-rw-r--r--gcc/ada/exp_pakd.adb11
-rw-r--r--gcc/ada/exp_prag.adb34
-rw-r--r--gcc/ada/exp_sel.adb18
-rw-r--r--gcc/ada/exp_sel.ads9
-rw-r--r--gcc/ada/exp_spark.adb260
-rw-r--r--gcc/ada/exp_strm.adb30
-rw-r--r--gcc/ada/exp_tss.adb42
-rw-r--r--gcc/ada/exp_tss.ads1
-rw-r--r--gcc/ada/exp_unst.adb25
-rw-r--r--gcc/ada/exp_util.adb975
-rw-r--r--gcc/ada/exp_util.ads54
-rw-r--r--gcc/ada/expect.c8
-rw-r--r--gcc/ada/freeze.adb254
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in13
-rw-r--r--gcc/ada/gcc-interface/Makefile.in13
-rw-r--r--gcc/ada/gcc-interface/decl.c93
-rw-r--r--gcc/ada/gcc-interface/gigi.h2
-rw-r--r--gcc/ada/gcc-interface/misc.c16
-rw-r--r--gcc/ada/gcc-interface/trans.c157
-rw-r--r--gcc/ada/gcc-interface/utils.c82
-rw-r--r--gcc/ada/gcc-interface/utils2.c32
-rw-r--r--gcc/ada/get_targ.adb32
-rw-r--r--gcc/ada/get_targ.ads4
-rw-r--r--gcc/ada/gnat1drv.adb27
-rw-r--r--gcc/ada/gnat_rm.texi1097
-rw-r--r--gcc/ada/gnat_ugn.texi39
-rw-r--r--gcc/ada/impunit.adb2
-rw-r--r--gcc/ada/inline.adb46
-rw-r--r--gcc/ada/inline.ads14
-rw-r--r--gcc/ada/lib-load.adb4
-rw-r--r--gcc/ada/lib-writ.adb13
-rw-r--r--gcc/ada/lib-xref.adb2
-rw-r--r--gcc/ada/lib.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__solaris.ads3
-rw-r--r--gcc/ada/libgnarl/s-tasren.adb14
-rw-r--r--gcc/ada/libgnarl/s-tassta.adb11
-rw-r--r--gcc/ada/libgnarl/s-tpobop.adb10
-rw-r--r--gcc/ada/libgnarl/s-tporft.adb1
-rw-r--r--gcc/ada/libgnat/a-cbdlli.adb10
-rw-r--r--gcc/ada/libgnat/a-cbdlli.ads6
-rw-r--r--gcc/ada/libgnat/a-cbhase.adb2
-rw-r--r--gcc/ada/libgnat/a-cbmutr.ads2
-rw-r--r--gcc/ada/libgnat/a-cborse.adb2
-rw-r--r--gcc/ada/libgnat/a-cbsyqu.ads10
-rw-r--r--gcc/ada/libgnat/a-cdlili.adb10
-rw-r--r--gcc/ada/libgnat/a-cdlili.ads6
-rw-r--r--gcc/ada/libgnat/a-cidlli.adb10
-rw-r--r--gcc/ada/libgnat/a-cidlli.ads6
-rw-r--r--gcc/ada/libgnat/a-cihama.adb2
-rw-r--r--gcc/ada/libgnat/a-cobove.adb73
-rw-r--r--gcc/ada/libgnat/a-cobove.ads44
-rw-r--r--gcc/ada/libgnat/a-cohama.adb2
-rw-r--r--gcc/ada/libgnat/a-cohase.adb2
-rw-r--r--gcc/ada/libgnat/a-coinve.adb64
-rw-r--r--gcc/ada/libgnat/a-coinve.ads43
-rw-r--r--gcc/ada/libgnat/a-convec.adb80
-rw-r--r--gcc/ada/libgnat/a-convec.ads78
-rw-r--r--gcc/ada/libgnat/a-decima__128.ads69
-rw-r--r--gcc/ada/libgnat/a-except.adb30
-rw-r--r--gcc/ada/libgnat/a-nbnbin.adb193
-rw-r--r--gcc/ada/libgnat/a-nbnbin.ads2
-rw-r--r--gcc/ada/libgnat/a-nbnbre.adb247
-rw-r--r--gcc/ada/libgnat/a-nbnbre.ads4
-rw-r--r--gcc/ada/libgnat/a-strfix.ads894
-rw-r--r--gcc/ada/libgnat/a-strmap.ads179
-rw-r--r--gcc/ada/libgnat/a-stzhas.adb14
-rw-r--r--gcc/ada/libgnat/a-stzhas.ads6
-rw-r--r--gcc/ada/libgnat/a-tags.adb44
-rw-r--r--gcc/ada/libgnat/a-tags.ads50
-rw-r--r--gcc/ada/libgnat/a-ticoau.adb23
-rw-r--r--gcc/ada/libgnat/a-ticoau.ads35
-rw-r--r--gcc/ada/libgnat/a-ticoio.adb94
-rw-r--r--gcc/ada/libgnat/a-tideau.adb188
-rw-r--r--gcc/ada/libgnat/a-tideau.ads74
-rw-r--r--gcc/ada/libgnat/a-tideio.adb58
-rw-r--r--gcc/ada/libgnat/a-tideio__128.adb177
-rw-r--r--gcc/ada/libgnat/a-tifiau.adb159
-rw-r--r--gcc/ada/libgnat/a-tifiau.ads97
-rw-r--r--gcc/ada/libgnat/a-tifiio.adb737
-rw-r--r--gcc/ada/libgnat/a-tifiio.ads2
-rw-r--r--gcc/ada/libgnat/a-tifiio__128.adb436
-rw-r--r--gcc/ada/libgnat/a-tiflau.adb125
-rw-r--r--gcc/ada/libgnat/a-tiflau.ads31
-rw-r--r--gcc/ada/libgnat/a-tiflio.adb74
-rw-r--r--gcc/ada/libgnat/a-tiflio.ads2
-rw-r--r--gcc/ada/libgnat/a-tigeau.adb100
-rw-r--r--gcc/ada/libgnat/a-tigeau.ads6
-rw-r--r--gcc/ada/libgnat/a-wtcoau.adb23
-rw-r--r--gcc/ada/libgnat/a-wtcoau.ads45
-rw-r--r--gcc/ada/libgnat/a-wtcoio.adb95
-rw-r--r--gcc/ada/libgnat/a-wtcoio.ads16
-rw-r--r--gcc/ada/libgnat/a-wtdeau.adb192
-rw-r--r--gcc/ada/libgnat/a-wtdeau.ads75
-rw-r--r--gcc/ada/libgnat/a-wtdeio.adb73
-rw-r--r--gcc/ada/libgnat/a-wtdeio__128.adb190
-rw-r--r--gcc/ada/libgnat/a-wtenau.adb15
-rw-r--r--gcc/ada/libgnat/a-wtenio.adb4
-rw-r--r--gcc/ada/libgnat/a-wtfiau.adb159
-rw-r--r--gcc/ada/libgnat/a-wtfiau.ads97
-rw-r--r--gcc/ada/libgnat/a-wtfiio.adb171
-rw-r--r--gcc/ada/libgnat/a-wtfiio__128.adb326
-rw-r--r--gcc/ada/libgnat/a-wtflau.adb131
-rw-r--r--gcc/ada/libgnat/a-wtflau.ads39
-rw-r--r--gcc/ada/libgnat/a-wtflio.adb86
-rw-r--r--gcc/ada/libgnat/a-wtgeau.adb100
-rw-r--r--gcc/ada/libgnat/a-wtgeau.ads6
-rw-r--r--gcc/ada/libgnat/a-wtinio.adb15
-rw-r--r--gcc/ada/libgnat/a-wtinio__128.adb19
-rw-r--r--gcc/ada/libgnat/a-wtmoio.adb15
-rw-r--r--gcc/ada/libgnat/a-wtmoio__128.adb15
-rw-r--r--gcc/ada/libgnat/a-ztcoau.adb23
-rw-r--r--gcc/ada/libgnat/a-ztcoau.ads41
-rw-r--r--gcc/ada/libgnat/a-ztcoio.adb96
-rw-r--r--gcc/ada/libgnat/a-ztcoio.ads14
-rw-r--r--gcc/ada/libgnat/a-ztdeau.adb190
-rw-r--r--gcc/ada/libgnat/a-ztdeau.ads75
-rw-r--r--gcc/ada/libgnat/a-ztdeio.adb82
-rw-r--r--gcc/ada/libgnat/a-ztdeio__128.adb190
-rw-r--r--gcc/ada/libgnat/a-ztenau.adb15
-rw-r--r--gcc/ada/libgnat/a-ztenio.adb4
-rw-r--r--gcc/ada/libgnat/a-ztfiau.adb159
-rw-r--r--gcc/ada/libgnat/a-ztfiau.ads97
-rw-r--r--gcc/ada/libgnat/a-ztfiio.adb171
-rw-r--r--gcc/ada/libgnat/a-ztfiio__128.adb327
-rw-r--r--gcc/ada/libgnat/a-ztflau.adb133
-rw-r--r--gcc/ada/libgnat/a-ztflau.ads39
-rw-r--r--gcc/ada/libgnat/a-ztflio.adb85
-rw-r--r--gcc/ada/libgnat/a-ztgeau.adb100
-rw-r--r--gcc/ada/libgnat/a-ztgeau.ads6
-rw-r--r--gcc/ada/libgnat/a-ztinio.adb15
-rw-r--r--gcc/ada/libgnat/a-ztinio__128.adb19
-rw-r--r--gcc/ada/libgnat/a-ztmoio.adb15
-rw-r--r--gcc/ada/libgnat/a-ztmoio__128.adb15
-rw-r--r--gcc/ada/libgnat/g-diopit.adb5
-rw-r--r--gcc/ada/libgnat/g-diopit.ads2
-rw-r--r--gcc/ada/libgnat/g-expect.adb6
-rw-r--r--gcc/ada/libgnat/g-rannum.adb86
-rw-r--r--gcc/ada/libgnat/g-rannum.ads2
-rw-r--r--gcc/ada/libgnat/g-sercom__linux.adb92
-rw-r--r--gcc/ada/libgnat/g-socket.adb75
-rw-r--r--gcc/ada/libgnat/g-socpol.adb3
-rw-r--r--gcc/ada/libgnat/g-spogwa.adb6
-rw-r--r--gcc/ada/libgnat/memtrack.adb33
-rw-r--r--gcc/ada/libgnat/s-arit32.adb182
-rw-r--r--gcc/ada/libgnat/s-arit32.ads55
-rw-r--r--gcc/ada/libgnat/s-bitfie.ads6
-rw-r--r--gcc/ada/libgnat/s-bituti.adb1
-rw-r--r--gcc/ada/libgnat/s-dwalin.adb21
-rw-r--r--gcc/ada/libgnat/s-fatgen.adb682
-rw-r--r--gcc/ada/libgnat/s-fatgen.ads15
-rw-r--r--gcc/ada/libgnat/s-fatsfl.ads47
-rw-r--r--gcc/ada/libgnat/s-finmas.adb14
-rw-r--r--gcc/ada/libgnat/s-finmas.ads4
-rw-r--r--gcc/ada/libgnat/s-fode128.ads48
-rw-r--r--gcc/ada/libgnat/s-fode32.ads48
-rw-r--r--gcc/ada/libgnat/s-fode64.ads48
-rw-r--r--gcc/ada/libgnat/s-fofi128.ads50
-rw-r--r--gcc/ada/libgnat/s-fofi32.ads50
-rw-r--r--gcc/ada/libgnat/s-fofi64.ads50
-rw-r--r--gcc/ada/libgnat/s-fore.adb56
-rw-r--r--gcc/ada/libgnat/s-fore.ads41
-rw-r--r--gcc/ada/libgnat/s-fore_d.adb62
-rw-r--r--gcc/ada/libgnat/s-fore_d.ads47
-rw-r--r--gcc/ada/libgnat/s-fore_f.adb136
-rw-r--r--gcc/ada/libgnat/s-fore_f.ads54
-rw-r--r--gcc/ada/libgnat/s-forrea.adb57
-rw-r--r--gcc/ada/libgnat/s-forrea.ads42
-rw-r--r--gcc/ada/libgnat/s-genbig.adb26
-rw-r--r--gcc/ada/libgnat/s-genbig.ads4
-rw-r--r--gcc/ada/libgnat/s-imaged.adb81
-rw-r--r--gcc/ada/libgnat/s-imaged.ads72
-rw-r--r--gcc/ada/libgnat/s-imagef.adb362
-rw-r--r--gcc/ada/libgnat/s-imagef.ads88
-rw-r--r--gcc/ada/libgnat/s-imagei.adb47
-rw-r--r--gcc/ada/libgnat/s-imageu.adb39
-rw-r--r--gcc/ada/libgnat/s-imde128.ads63
-rw-r--r--gcc/ada/libgnat/s-imde32.ads63
-rw-r--r--gcc/ada/libgnat/s-imde64.ads63
-rw-r--r--gcc/ada/libgnat/s-imfi128.ads69
-rw-r--r--gcc/ada/libgnat/s-imfi32.ads69
-rw-r--r--gcc/ada/libgnat/s-imfi64.ads69
-rw-r--r--gcc/ada/libgnat/s-imgdec.adb454
-rw-r--r--gcc/ada/libgnat/s-imgdec.ads83
-rw-r--r--gcc/ada/libgnat/s-imglld.adb82
-rw-r--r--gcc/ada/libgnat/s-imglld.ads67
-rw-r--r--gcc/ada/libgnat/s-imgrea.adb44
-rw-r--r--gcc/ada/libgnat/s-imgrea.ads7
-rw-r--r--gcc/ada/libgnat/s-imguti.adb403
-rw-r--r--gcc/ada/libgnat/s-imguti.ads61
-rw-r--r--gcc/ada/libgnat/s-objrea.adb4
-rw-r--r--gcc/ada/libgnat/s-objrea.ads5
-rw-r--r--gcc/ada/libgnat/s-os_lib.adb25
-rw-r--r--gcc/ada/libgnat/s-powflt.ads85
-rw-r--r--gcc/ada/libgnat/s-powlfl.ads355
-rw-r--r--gcc/ada/libgnat/s-powllf.ads70
-rw-r--r--gcc/ada/libgnat/s-powtab.ads70
-rw-r--r--gcc/ada/libgnat/s-rannum.adb35
-rw-r--r--gcc/ada/libgnat/s-rident.ads2
-rw-r--r--gcc/ada/libgnat/s-secsta.adb15
-rw-r--r--gcc/ada/libgnat/s-stratt.adb210
-rw-r--r--gcc/ada/libgnat/s-stratt.ads107
-rw-r--r--gcc/ada/libgnat/s-trasym.ads3
-rw-r--r--gcc/ada/libgnat/s-vade128.ads60
-rw-r--r--gcc/ada/libgnat/s-vade32.ads58
-rw-r--r--gcc/ada/libgnat/s-vade64.ads60
-rw-r--r--gcc/ada/libgnat/s-vafi128.ads60
-rw-r--r--gcc/ada/libgnat/s-vafi32.ads60
-rw-r--r--gcc/ada/libgnat/s-vafi64.ads60
-rw-r--r--gcc/ada/libgnat/s-valdec.adb68
-rw-r--r--gcc/ada/libgnat/s-valdec.ads80
-rw-r--r--gcc/ada/libgnat/s-valflt.ads57
-rw-r--r--gcc/ada/libgnat/s-vallfl.ads57
-rw-r--r--gcc/ada/libgnat/s-vallld.adb70
-rw-r--r--gcc/ada/libgnat/s-vallld.ads81
-rw-r--r--gcc/ada/libgnat/s-valllf.ads57
-rw-r--r--gcc/ada/libgnat/s-valrea.adb641
-rw-r--r--gcc/ada/libgnat/s-valrea.ads19
-rw-r--r--gcc/ada/libgnat/s-valued.adb263
-rw-r--r--gcc/ada/libgnat/s-valued.ads90
-rw-r--r--gcc/ada/libgnat/s-valuef.adb368
-rw-r--r--gcc/ada/libgnat/s-valuef.ads94
-rw-r--r--gcc/ada/libgnat/s-valuei.adb2
-rw-r--r--gcc/ada/libgnat/s-valuer.adb685
-rw-r--r--gcc/ada/libgnat/s-valuer.ads101
-rw-r--r--gcc/ada/libgnat/system-aix.ads4
-rw-r--r--gcc/ada/libgnat/system-darwin-arm.ads4
-rw-r--r--gcc/ada/libgnat/system-darwin-ppc.ads4
-rw-r--r--gcc/ada/libgnat/system-darwin-x86.ads4
-rw-r--r--gcc/ada/libgnat/system-djgpp.ads4
-rw-r--r--gcc/ada/libgnat/system-dragonfly-x86_64.ads4
-rw-r--r--gcc/ada/libgnat/system-freebsd.ads4
-rw-r--r--gcc/ada/libgnat/system-hpux-ia64.ads4
-rw-r--r--gcc/ada/libgnat/system-hpux.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-alpha.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-arm.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-hppa.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-ia64.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-m68k.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-mips.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-ppc.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-riscv.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-s390.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-sh4.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-sparc.ads4
-rw-r--r--gcc/ada/libgnat/system-linux-x86.ads4
-rw-r--r--gcc/ada/libgnat/system-lynxos178-ppc.ads6
-rw-r--r--gcc/ada/libgnat/system-lynxos178-x86.ads6
-rw-r--r--gcc/ada/libgnat/system-mingw.ads4
-rw-r--r--gcc/ada/libgnat/system-qnx-aarch64.ads4
-rw-r--r--gcc/ada/libgnat/system-rtems.ads4
-rw-r--r--gcc/ada/libgnat/system-solaris-sparc.ads4
-rw-r--r--gcc/ada/libgnat/system-solaris-x86.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-arm-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-arm-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-arm.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-e500-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-e500-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-e500-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-e500-vthread.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc-vthread.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-ppc.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-x86-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-x86-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-x86-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-x86-vthread.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks-x86.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-aarch64-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-aarch64.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-arm-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-arm.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-e500-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-e500-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-e500-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-ppc-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-ppc-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-ppc-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-ppc64-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-ppc64-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-x86-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-x86-rtp-smp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-x86-rtp.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-x86_64-kernel.ads4
-rw-r--r--gcc/ada/libgnat/system-vxworks7-x86_64-rtp-smp.ads4
-rw-r--r--gcc/ada/make.adb20
-rw-r--r--gcc/ada/opt.ads17
-rw-r--r--gcc/ada/osint-c.adb8
-rw-r--r--gcc/ada/par-ch10.adb13
-rw-r--r--gcc/ada/par-ch11.adb5
-rw-r--r--gcc/ada/par-ch12.adb76
-rw-r--r--gcc/ada/par-ch13.adb36
-rw-r--r--gcc/ada/par-ch3.adb113
-rw-r--r--gcc/ada/par-ch4.adb90
-rw-r--r--gcc/ada/par-ch5.adb28
-rw-r--r--gcc/ada/par-ch6.adb41
-rw-r--r--gcc/ada/par-ch9.adb27
-rw-r--r--gcc/ada/par-load.adb2
-rw-r--r--gcc/ada/par-prag.adb9
-rw-r--r--gcc/ada/par-tchk.adb1
-rw-r--r--gcc/ada/par.adb4
-rw-r--r--gcc/ada/repinfo.adb80
-rw-r--r--gcc/ada/repinfo.ads88
-rw-r--r--gcc/ada/rtsfind.adb2
-rw-r--r--gcc/ada/rtsfind.ads152
-rw-r--r--gcc/ada/s-oscons-tmplt.c38
-rw-r--r--gcc/ada/sa_messages.ads2
-rw-r--r--gcc/ada/scng.adb19
-rw-r--r--gcc/ada/sem_aggr.adb183
-rw-r--r--gcc/ada/sem_attr.adb478
-rw-r--r--gcc/ada/sem_aux.adb116
-rw-r--r--gcc/ada/sem_aux.ads25
-rw-r--r--gcc/ada/sem_cat.adb9
-rw-r--r--gcc/ada/sem_ch10.adb16
-rw-r--r--gcc/ada/sem_ch11.adb2
-rw-r--r--gcc/ada/sem_ch12.adb98
-rw-r--r--gcc/ada/sem_ch13.adb1143
-rw-r--r--gcc/ada/sem_ch13.ads37
-rw-r--r--gcc/ada/sem_ch3.adb191
-rw-r--r--gcc/ada/sem_ch4.adb20
-rw-r--r--gcc/ada/sem_ch5.adb126
-rw-r--r--gcc/ada/sem_ch6.adb333
-rw-r--r--gcc/ada/sem_ch8.adb93
-rw-r--r--gcc/ada/sem_ch9.adb20
-rw-r--r--gcc/ada/sem_disp.adb2
-rw-r--r--gcc/ada/sem_elab.adb18
-rw-r--r--gcc/ada/sem_eval.adb325
-rw-r--r--gcc/ada/sem_eval.ads5
-rw-r--r--gcc/ada/sem_prag.adb475
-rw-r--r--gcc/ada/sem_res.adb361
-rw-r--r--gcc/ada/sem_type.adb118
-rw-r--r--gcc/ada/sem_util.adb914
-rw-r--r--gcc/ada/sem_util.ads60
-rw-r--r--gcc/ada/sem_warn.adb39
-rw-r--r--gcc/ada/sinfo.adb16
-rw-r--r--gcc/ada/sinfo.ads18
-rw-r--r--gcc/ada/snames.ads-tmpl191
-rw-r--r--gcc/ada/spark_xrefs.ads3
-rw-r--r--gcc/ada/stand.ads9
-rw-r--r--gcc/ada/switch-c.adb6
-rw-r--r--gcc/ada/symbols.adb90
-rw-r--r--gcc/ada/symbols.ads115
-rw-r--r--gcc/ada/targparm.adb16
-rw-r--r--gcc/ada/targparm.ads10
-rw-r--r--gcc/ada/terminals.c2
-rw-r--r--gcc/ada/tracebak.c7
-rw-r--r--gcc/ada/ttypes.ads31
-rw-r--r--gcc/ada/uintp.ads12
-rw-r--r--gcc/ada/urealp.adb168
-rw-r--r--gcc/ada/urealp.ads32
-rw-r--r--gcc/ada/validsw.adb50
-rw-r--r--gcc/ada/validsw.ads13
-rw-r--r--gcc/ada/vxworks7-cert-rtp-link.spec9
-rw-r--r--gcc/ada/xsnamest.adb9
-rw-r--r--gcc/analyzer/ChangeLog229
-rw-r--r--gcc/analyzer/analyzer-pass.cc21
-rw-r--r--gcc/analyzer/analyzer.h16
-rw-r--r--gcc/analyzer/analyzer.opt8
-rw-r--r--gcc/analyzer/checker-path.cc9
-rw-r--r--gcc/analyzer/checker-path.h10
-rw-r--r--gcc/analyzer/complexity.cc95
-rw-r--r--gcc/analyzer/complexity.h51
-rw-r--r--gcc/analyzer/constraint-manager.cc33
-rw-r--r--gcc/analyzer/constraint-manager.h3
-rw-r--r--gcc/analyzer/diagnostic-manager.cc37
-rw-r--r--gcc/analyzer/engine.cc191
-rw-r--r--gcc/analyzer/pending-diagnostic.h23
-rw-r--r--gcc/analyzer/program-point.cc27
-rw-r--r--gcc/analyzer/program-point.h3
-rw-r--r--gcc/analyzer/program-state.cc145
-rw-r--r--gcc/analyzer/program-state.h8
-rw-r--r--gcc/analyzer/region-model-manager.cc41
-rw-r--r--gcc/analyzer/region-model-reachability.cc107
-rw-r--r--gcc/analyzer/region-model-reachability.h3
-rw-r--r--gcc/analyzer/region-model.cc117
-rw-r--r--gcc/analyzer/region-model.h2120
-rw-r--r--gcc/analyzer/region.cc30
-rw-r--r--gcc/analyzer/region.h1017
-rw-r--r--gcc/analyzer/sm-malloc.cc8
-rw-r--r--gcc/analyzer/state-purge.cc10
-rw-r--r--gcc/analyzer/store.cc82
-rw-r--r--gcc/analyzer/store.h8
-rw-r--r--gcc/analyzer/supergraph.cc9
-rw-r--r--gcc/analyzer/svalue.cc240
-rw-r--r--gcc/analyzer/svalue.h1150
-rw-r--r--gcc/asan.c1034
-rw-r--r--gcc/asan.h45
-rw-r--r--gcc/attr-fnspec.h133
-rw-r--r--gcc/bitmap.c5
-rw-r--r--gcc/brig/ChangeLog17
-rw-r--r--gcc/brig/Make-lang.in10
-rw-r--r--gcc/brig/lang.opt2
-rw-r--r--gcc/builtin-attrs.def6
-rw-r--r--gcc/builtin-types.def5
-rw-r--r--gcc/builtins.c2158
-rw-r--r--gcc/builtins.def38
-rw-r--r--gcc/builtins.h133
-rw-r--r--gcc/c-family/ChangeLog406
-rw-r--r--gcc/c-family/c-ada-spec.c31
-rw-r--r--gcc/c-family/c-attribs.c603
-rw-r--r--gcc/c-family/c-common.c126
-rw-r--r--gcc/c-family/c-common.h36
-rw-r--r--gcc/c-family/c-cppbuiltin.c43
-rw-r--r--gcc/c-family/c-indentation.c70
-rw-r--r--gcc/c-family/c-lex.c84
-rw-r--r--gcc/c-family/c-objc.h75
-rw-r--r--gcc/c-family/c-omp.c282
-rw-r--r--gcc/c-family/c-opts.c48
-rw-r--r--gcc/c-family/c-pch.c44
-rw-r--r--gcc/c-family/c-ppoutput.c158
-rw-r--r--gcc/c-family/c-pragma.c22
-rw-r--r--gcc/c-family/c-pragma.h2
-rw-r--r--gcc/c-family/c-pretty-print.c2
-rw-r--r--gcc/c-family/c-warn.c33
-rw-r--r--gcc/c-family/c.opt136
-rw-r--r--gcc/c-family/stub-objc.c25
-rw-r--r--gcc/c/ChangeLog200
-rw-r--r--gcc/c/Make-lang.in3
-rw-r--r--gcc/c/c-aux-info.c1
-rw-r--r--gcc/c/c-decl.c52
-rw-r--r--gcc/c/c-parser.c646
-rw-r--r--gcc/c/c-typeck.c235
-rw-r--r--gcc/c/gimple-parser.c2
-rw-r--r--gcc/calls.c55
-rw-r--r--gcc/calls.h1
-rw-r--r--gcc/cfg.c65
-rw-r--r--gcc/cfg.h4
-rw-r--r--gcc/cfgexpand.c270
-rw-r--r--gcc/cfgloop.h2
-rw-r--r--gcc/cfgrtl.c60
-rw-r--r--gcc/cfgrtl.h1
-rw-r--r--gcc/cgraph.c121
-rw-r--r--gcc/cgraph.h79
-rw-r--r--gcc/cgraphclones.c55
-rw-r--r--gcc/cgraphunit.c3
-rw-r--r--gcc/combine.c54
-rw-r--r--gcc/common.opt630
-rw-r--r--gcc/common/config/i386/cpuinfo.h55
-rw-r--r--gcc/common/config/i386/i386-common.c120
-rw-r--r--gcc/common/config/i386/i386-cpuinfo.h6
-rw-r--r--gcc/common/config/i386/i386-isas.h4
-rw-r--r--gcc/common/config/riscv/riscv-common.c554
-rw-r--r--gcc/config.gcc161
-rw-r--r--gcc/config.in71
-rw-r--r--gcc/config/aarch64/aarch64-bti-insert.c2
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c13
-rw-r--r--gcc/config/aarch64/aarch64-cores.def1
-rw-r--r--gcc/config/aarch64/aarch64-linux.h2
-rw-r--r--gcc/config/aarch64/aarch64-modes.def4
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def6
-rw-r--r--gcc/config/aarch64/aarch64-protos.h42
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def252
-rw-r--r--gcc/config/aarch64/aarch64-simd.md181
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-base.cc11
-rw-r--r--gcc/config/aarch64/aarch64-sve.md338
-rw-r--r--gcc/config/aarch64/aarch64-sve2.md78
-rw-r--r--gcc/config/aarch64/aarch64-tune.md2
-rw-r--r--gcc/config/aarch64/aarch64-vxworks.h12
-rw-r--r--gcc/config/aarch64/aarch64.c902
-rw-r--r--gcc/config/aarch64/aarch64.h41
-rw-r--r--gcc/config/aarch64/aarch64.md39
-rw-r--r--gcc/config/aarch64/aarch64.opt20
-rw-r--r--gcc/config/aarch64/arm_bf16.h7
-rw-r--r--gcc/config/aarch64/arm_neon.h659
-rw-r--r--gcc/config/aarch64/falkor.md2
-rw-r--r--gcc/config/aarch64/iterators.md58
-rw-r--r--gcc/config/aarch64/predicates.md2
-rw-r--r--gcc/config/aarch64/saphira.md2
-rw-r--r--gcc/config/aarch64/thunderx.md2
-rw-r--r--gcc/config/aarch64/thunderx2t99.md2
-rw-r--r--gcc/config/aarch64/thunderx3t110.md4
-rw-r--r--gcc/config/aarch64/tsv110.md2
-rw-r--r--gcc/config/alpha/alpha.opt38
-rw-r--r--gcc/config/arc/arc-protos.h3
-rw-r--r--gcc/config/arc/arc.c136
-rw-r--r--gcc/config/arc/arc.h2
-rw-r--r--gcc/config/arc/arc.md293
-rw-r--r--gcc/config/arc/arc.opt110
-rw-r--r--gcc/config/arc/constraints.md5
-rw-r--r--gcc/config/arc/simdext.md92
-rw-r--r--gcc/config/arm/aarch-common.c2
-rw-r--r--gcc/config/arm/aarch-cost-tables.h103
-rw-r--r--gcc/config/arm/arm-builtins.c3
-rw-r--r--gcc/config/arm/arm-cpus.in11
-rw-r--r--gcc/config/arm/arm-fixed.md2
-rw-r--r--gcc/config/arm/arm-protos.h3
-rw-r--r--gcc/config/arm/arm-tables.opt3
-rw-r--r--gcc/config/arm/arm-tune.md10
-rw-r--r--gcc/config/arm/arm.c427
-rw-r--r--gcc/config/arm/arm.md31
-rw-r--r--gcc/config/arm/arm.opt66
-rw-r--r--gcc/config/arm/arm1020e.md2
-rw-r--r--gcc/config/arm/arm1026ejs.md2
-rw-r--r--gcc/config/arm/arm1136jfs.md2
-rw-r--r--gcc/config/arm/arm926ejs.md2
-rw-r--r--gcc/config/arm/arm_mve.h70
-rw-r--r--gcc/config/arm/arm_mve_builtins.def26
-rw-r--r--gcc/config/arm/arm_neon.h290
-rw-r--r--gcc/config/arm/arm_neon_builtins.def47
-rw-r--r--gcc/config/arm/common.md41
-rw-r--r--gcc/config/arm/constraints.md2
-rw-r--r--gcc/config/arm/cortex-a15.md2
-rw-r--r--gcc/config/arm/cortex-a17.md2
-rw-r--r--gcc/config/arm/cortex-a5.md2
-rw-r--r--gcc/config/arm/cortex-a53.md2
-rw-r--r--gcc/config/arm/cortex-a57.md2
-rw-r--r--gcc/config/arm/cortex-a7.md2
-rw-r--r--gcc/config/arm/cortex-a8.md2
-rw-r--r--gcc/config/arm/cortex-a9.md2
-rw-r--r--gcc/config/arm/cortex-m4.md2
-rw-r--r--gcc/config/arm/cortex-m7.md2
-rw-r--r--gcc/config/arm/cortex-r4.md2
-rw-r--r--gcc/config/arm/exynos-m1.md2
-rw-r--r--gcc/config/arm/fa526.md2
-rw-r--r--gcc/config/arm/fa606te.md2
-rw-r--r--gcc/config/arm/fa626te.md2
-rw-r--r--gcc/config/arm/fa726te.md2
-rw-r--r--gcc/config/arm/fmp626.md2
-rw-r--r--gcc/config/arm/iterators.md42
-rw-r--r--gcc/config/arm/marvell-pj4.md8
-rw-r--r--gcc/config/arm/mve.md297
-rw-r--r--gcc/config/arm/neon.md22
-rw-r--r--gcc/config/arm/predicates.md6
-rw-r--r--gcc/config/arm/t-rtems5
-rw-r--r--gcc/config/arm/thumb1.md74
-rw-r--r--gcc/config/arm/thumb2.md6
-rw-r--r--gcc/config/arm/types.md67
-rw-r--r--gcc/config/arm/unspecs.md34
-rw-r--r--gcc/config/arm/vec-common.md43
-rw-r--r--gcc/config/arm/xgene1.md2
-rw-r--r--gcc/config/avr/avr.opt52
-rw-r--r--gcc/config/bfin/bfin.opt34
-rw-r--r--gcc/config/bpf/bpf.opt6
-rw-r--r--gcc/config/c6x/c6x.c7
-rw-r--r--gcc/config/c6x/c6x.opt6
-rw-r--r--gcc/config/cr16/cr16.opt4
-rw-r--r--gcc/config/cris/cris.opt64
-rw-r--r--gcc/config/cris/elf.opt2
-rw-r--r--gcc/config/csky/csky.c7
-rw-r--r--gcc/config/csky/csky.opt60
-rw-r--r--gcc/config/darwin-c.c19
-rw-r--r--gcc/config/darwin-d.c49
-rw-r--r--gcc/config/darwin-driver.c57
-rw-r--r--gcc/config/darwin-protos.h1
-rw-r--r--gcc/config/darwin.c11
-rw-r--r--gcc/config/darwin.h7
-rw-r--r--gcc/config/darwin.opt24
-rw-r--r--gcc/config/dragonfly-d.c37
-rw-r--r--gcc/config/elfos.h6
-rw-r--r--gcc/config/fr30/fr30.opt2
-rw-r--r--gcc/config/freebsd-d.c42
-rw-r--r--gcc/config/frv/frv.opt62
-rw-r--r--gcc/config/ft32/ft32.md6
-rw-r--r--gcc/config/ft32/ft32.opt12
-rw-r--r--gcc/config/gcn/gcn.opt12
-rw-r--r--gcc/config/gcn/mkoffload.c15
-rw-r--r--gcc/config/glibc-d.c16
-rw-r--r--gcc/config/gnu-user.h8
-rw-r--r--gcc/config/h8300/addsub.md188
-rw-r--r--gcc/config/h8300/bitfield.md564
-rw-r--r--gcc/config/h8300/combiner.md901
-rw-r--r--gcc/config/h8300/constraints.md6
-rw-r--r--gcc/config/h8300/divmod.md127
-rw-r--r--gcc/config/h8300/extensions.md136
-rw-r--r--gcc/config/h8300/genmova.sh18
-rw-r--r--gcc/config/h8300/h8300-modes.def21
-rw-r--r--gcc/config/h8300/h8300-protos.h12
-rw-r--r--gcc/config/h8300/h8300.c370
-rw-r--r--gcc/config/h8300/h8300.h14
-rw-r--r--gcc/config/h8300/h8300.md40
-rw-r--r--gcc/config/h8300/jumpcall.md132
-rw-r--r--gcc/config/h8300/logical.md240
-rw-r--r--gcc/config/h8300/mova.md249
-rw-r--r--gcc/config/h8300/movepush.md180
-rw-r--r--gcc/config/h8300/multiply.md131
-rw-r--r--gcc/config/h8300/other.md15
-rw-r--r--gcc/config/h8300/peepholes.md104
-rw-r--r--gcc/config/h8300/predicates.md9
-rw-r--r--gcc/config/h8300/proepi.md12
-rw-r--r--gcc/config/h8300/shiftrotate.md262
-rw-r--r--gcc/config/h8300/testcompare.md275
-rw-r--r--gcc/config/host-darwin.c5
-rw-r--r--gcc/config/i386/avx512vnnivlintrin.h88
-rw-r--r--gcc/config/i386/avxvnniintrin.h113
-rw-r--r--gcc/config/i386/cet.c76
-rw-r--r--gcc/config/i386/cpuid.h8
-rw-r--r--gcc/config/i386/cygming.opt6
-rw-r--r--gcc/config/i386/driver-i386.c5
-rw-r--r--gcc/config/i386/gnu-property.c124
-rw-r--r--gcc/config/i386/i386-builtin-types.def7
-rw-r--r--gcc/config/i386/i386-builtin.def31
-rw-r--r--gcc/config/i386/i386-builtins.c4
-rw-r--r--gcc/config/i386/i386-c.c13
-rw-r--r--gcc/config/i386/i386-expand.c839
-rw-r--r--gcc/config/i386/i386-features.c27
-rw-r--r--gcc/config/i386/i386-options.c90
-rw-r--r--gcc/config/i386/i386-protos.h4
-rw-r--r--gcc/config/i386/i386.c416
-rw-r--r--gcc/config/i386/i386.h68
-rw-r--r--gcc/config/i386/i386.md534
-rw-r--r--gcc/config/i386/i386.opt323
-rw-r--r--gcc/config/i386/i386elf.h62
-rw-r--r--gcc/config/i386/immintrin.h4
-rw-r--r--gcc/config/i386/keylockerintrin.h129
-rw-r--r--gcc/config/i386/linux-common.h7
-rw-r--r--gcc/config/i386/msformat-c.c53
-rw-r--r--gcc/config/i386/predicates.md124
-rw-r--r--gcc/config/i386/sse.md689
-rw-r--r--gcc/config/i386/t-cet21
-rw-r--r--gcc/config/i386/t-gnu-property21
-rw-r--r--gcc/config/i386/t-vxworks19
-rw-r--r--gcc/config/i386/uintrintrin.h3
-rw-r--r--gcc/config/i386/vxworks.h96
-rw-r--r--gcc/config/i386/x86-tune-sched.c2
-rw-r--r--gcc/config/i386/x86-tune.def2
-rw-r--r--gcc/config/i386/znver1.md353
-rw-r--r--gcc/config/ia64/ia64.opt68
-rw-r--r--gcc/config/ia64/ilp32.opt4
-rw-r--r--gcc/config/linux-android.opt2
-rw-r--r--gcc/config/linux.opt8
-rw-r--r--gcc/config/lm32/lm32.opt10
-rw-r--r--gcc/config/m32r/m32r.opt14
-rw-r--r--gcc/config/m68k/linux.h8
-rw-r--r--gcc/config/m68k/m68k.opt24
-rw-r--r--gcc/config/mcore/mcore.opt22
-rw-r--r--gcc/config/mcore/t-mcore2
-rw-r--r--gcc/config/microblaze/microblaze.opt8
-rw-r--r--gcc/config/mips/mips.c4
-rw-r--r--gcc/config/mips/mips.opt164
-rw-r--r--gcc/config/mmix/mmix.opt34
-rw-r--r--gcc/config/mn10300/mn10300.opt10
-rw-r--r--gcc/config/moxie/moxie.opt6
-rw-r--r--gcc/config/msp430/msp430-protos.h5
-rw-r--r--gcc/config/msp430/msp430.c981
-rw-r--r--gcc/config/msp430/msp430.h18
-rw-r--r--gcc/config/msp430/msp430.md498
-rw-r--r--gcc/config/msp430/msp430.opt34
-rw-r--r--gcc/config/msp430/predicates.md13
-rw-r--r--gcc/config/nds32/nds32.opt40
-rw-r--r--gcc/config/nios2/elf.opt4
-rw-r--r--gcc/config/nios2/nios2.opt258
-rw-r--r--gcc/config/nvptx/nvptx.opt16
-rw-r--r--gcc/config/pa/pa.opt26
-rw-r--r--gcc/config/pdp11/pdp11.md4
-rw-r--r--gcc/config/pdp11/pdp11.opt24
-rw-r--r--gcc/config/pru/alu-zext.md51
-rw-r--r--gcc/config/pru/pru.c62
-rw-r--r--gcc/config/pru/pru.h3
-rw-r--r--gcc/config/pru/pru.md40
-rw-r--r--gcc/config/pru/pru.opt6
-rwxr-xr-xgcc/config/riscv/arch-canonicalize102
-rwxr-xr-xgcc/config/riscv/multilib-generator93
-rw-r--r--gcc/config/riscv/riscv-opts.h16
-rw-r--r--gcc/config/riscv/riscv.c39
-rw-r--r--gcc/config/riscv/riscv.h24
-rw-r--r--gcc/config/riscv/riscv.md5
-rw-r--r--gcc/config/riscv/riscv.opt40
-rw-r--r--gcc/config/riscv/t-withmultilib-generator2
-rw-r--r--gcc/config/riscv/withmultilib.h51
-rw-r--r--gcc/config/rl78/rl78.opt18
-rw-r--r--gcc/config/rs6000/aix64.opt6
-rw-r--r--gcc/config/rs6000/altivec.h25
-rw-r--r--gcc/config/rs6000/altivec.md104
-rw-r--r--gcc/config/rs6000/dfp.md22
-rw-r--r--gcc/config/rs6000/freebsd64.h17
-rw-r--r--gcc/config/rs6000/linux64.opt2
-rw-r--r--gcc/config/rs6000/mma.md451
-rw-r--r--gcc/config/rs6000/predicates.md12
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def81
-rw-r--r--gcc/config/rs6000/rs6000-call.c283
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def10
-rw-r--r--gcc/config/rs6000/rs6000-modes.def10
-rw-r--r--gcc/config/rs6000/rs6000-protos.h3
-rw-r--r--gcc/config/rs6000/rs6000-string.c6
-rw-r--r--gcc/config/rs6000/rs6000.c479
-rw-r--r--gcc/config/rs6000/rs6000.h24
-rw-r--r--gcc/config/rs6000/rs6000.md83
-rw-r--r--gcc/config/rs6000/rs6000.opt129
-rw-r--r--gcc/config/rs6000/sysv4.opt32
-rw-r--r--gcc/config/rs6000/vector.md4
-rw-r--r--gcc/config/rs6000/vsx.md4
-rw-r--r--gcc/config/rs6000/vxworks.h20
-rw-r--r--gcc/config/rs6000/xcoff.h4
-rw-r--r--gcc/config/rx/elf.opt2
-rw-r--r--gcc/config/rx/rx.c8
-rw-r--r--gcc/config/rx/rx.md1
-rw-r--r--gcc/config/rx/rx.opt26
-rw-r--r--gcc/config/s390/s390-modes.def5
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c147
-rw-r--r--gcc/config/s390/s390.h36
-rw-r--r--gcc/config/s390/s390.md245
-rw-r--r--gcc/config/s390/s390.opt73
-rw-r--r--gcc/config/s390/tpf.opt14
-rw-r--r--gcc/config/s390/vector.md553
-rw-r--r--gcc/config/s390/vx-builtins.md86
-rw-r--r--gcc/config/sh/sh.opt38
-rw-r--r--gcc/config/sol2-d.c12
-rw-r--r--gcc/config/sol2.h3
-rw-r--r--gcc/config/sol2.opt4
-rw-r--r--gcc/config/sparc/long-double-switch.opt4
-rw-r--r--gcc/config/sparc/predicates.md2
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c85
-rw-r--r--gcc/config/sparc/sparc.md183
-rw-r--r--gcc/config/sparc/sparc.opt60
-rw-r--r--gcc/config/t-darwin3
-rw-r--r--gcc/config/t-dragonfly21
-rw-r--r--gcc/config/t-freebsd21
-rw-r--r--gcc/config/tilegx/tilegx.c4
-rw-r--r--gcc/config/tilegx/tilegx.opt8
-rw-r--r--gcc/config/tilepro/tilepro.c4
-rw-r--r--gcc/config/tilepro/tilepro.opt2
-rw-r--r--gcc/config/v850/v850.opt48
-rw-r--r--gcc/config/vax/builtins.md269
-rw-r--r--gcc/config/vax/constraints.md4
-rw-r--r--gcc/config/vax/elf.h13
-rw-r--r--gcc/config/vax/netbsd-elf.h4
-rw-r--r--gcc/config/vax/predicates.md70
-rw-r--r--gcc/config/vax/vax-modes.def11
-rw-r--r--gcc/config/vax/vax-protos.h4
-rw-r--r--gcc/config/vax/vax.c402
-rw-r--r--gcc/config/vax/vax.h41
-rw-r--r--gcc/config/vax/vax.md2036
-rw-r--r--gcc/config/visium/visium.opt6
-rw-r--r--gcc/config/vms/vms.opt6
-rw-r--r--gcc/config/vxworks.c24
-rw-r--r--gcc/config/vxworks.h23
-rw-r--r--gcc/config/vxworks.opt2
-rw-r--r--gcc/config/xtensa/predicates.md5
-rw-r--r--gcc/config/xtensa/xtensa.c15
-rw-r--r--gcc/config/xtensa/xtensa.md101
-rw-r--r--gcc/config/xtensa/xtensa.opt12
-rwxr-xr-xgcc/configure660
-rw-r--r--gcc/configure.ac390
-rw-r--r--gcc/coretypes.h30
-rw-r--r--gcc/coverage.c28
-rw-r--r--gcc/cp/ChangeLog1754
-rw-r--r--gcc/cp/Make-lang.in21
-rw-r--r--gcc/cp/call.c155
-rw-r--r--gcc/cp/class.c95
-rw-r--r--gcc/cp/config-lang.in2
-rw-r--r--gcc/cp/constexpr.c597
-rw-r--r--gcc/cp/constraint.cc743
-rw-r--r--gcc/cp/coroutines.cc2
-rw-r--r--gcc/cp/cp-gimplify.c48
-rw-r--r--gcc/cp/cp-lang.c38
-rw-r--r--gcc/cp/cp-objcp-common.c22
-rw-r--r--gcc/cp/cp-objcp-common.h4
-rw-r--r--gcc/cp/cp-tree.def6
-rw-r--r--gcc/cp/cp-tree.h439
-rw-r--r--gcc/cp/cvt.c41
-rw-r--r--gcc/cp/cxx-pretty-print.c21
-rw-r--r--gcc/cp/decl.c414
-rw-r--r--gcc/cp/decl2.c269
-rw-r--r--gcc/cp/error.c58
-rw-r--r--gcc/cp/except.c26
-rw-r--r--gcc/cp/g++spec.c107
-rw-r--r--gcc/cp/init.c12
-rw-r--r--gcc/cp/lambda.c8
-rw-r--r--gcc/cp/lang-specs.h57
-rw-r--r--gcc/cp/lex.c223
-rw-r--r--gcc/cp/logic.cc22
-rw-r--r--gcc/cp/mangle.c121
-rw-r--r--gcc/cp/mapper-client.cc373
-rw-r--r--gcc/cp/mapper-client.h63
-rw-r--r--gcc/cp/mapper-resolver.cc31
-rw-r--r--gcc/cp/method.c228
-rw-r--r--gcc/cp/module.cc19947
-rw-r--r--gcc/cp/name-lookup.c2576
-rw-r--r--gcc/cp/name-lookup.h174
-rw-r--r--gcc/cp/optimize.c2
-rw-r--r--gcc/cp/parser.c1526
-rw-r--r--gcc/cp/parser.h3
-rw-r--r--gcc/cp/pt.c680
-rw-r--r--gcc/cp/ptree.c74
-rw-r--r--gcc/cp/rtti.c134
-rw-r--r--gcc/cp/search.c11
-rw-r--r--gcc/cp/semantics.c381
-rw-r--r--gcc/cp/tree.c222
-rw-r--r--gcc/cp/typeck.c214
-rw-r--r--gcc/cp/typeck2.c170
-rw-r--r--gcc/cppbuiltin.c3
-rw-r--r--gcc/cppdefault.c5
-rw-r--r--gcc/cppdefault.h7
-rw-r--r--gcc/d/ChangeLog119
-rw-r--r--gcc/d/Make-lang.in5
-rw-r--r--gcc/d/d-builtins.cc17
-rw-r--r--gcc/d/d-codegen.cc5
-rw-r--r--gcc/d/d-compiler.cc4
-rw-r--r--gcc/d/d-frontend.cc2
-rw-r--r--gcc/d/d-lang.cc17
-rw-r--r--gcc/d/d-target.cc19
-rw-r--r--gcc/d/d-target.def33
-rw-r--r--gcc/d/d-tree.h2
-rw-r--r--gcc/d/decl.cc101
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/cond.c4
-rw-r--r--gcc/d/dmd/cppmangle.c20
-rw-r--r--gcc/d/dmd/dmangle.c321
-rw-r--r--gcc/d/dmd/dtemplate.c182
-rw-r--r--gcc/d/dmd/expression.c2
-rw-r--r--gcc/d/dmd/expression.h2
-rw-r--r--gcc/d/dmd/globals.h1
-rw-r--r--gcc/d/dmd/hdrgen.c2
-rw-r--r--gcc/d/dmd/idgen.c3
-rw-r--r--gcc/d/dmd/json.c3
-rw-r--r--gcc/d/dmd/mangle.h1
-rw-r--r--gcc/d/dmd/mtype.c6
-rw-r--r--gcc/d/dmd/mtype.h3
-rw-r--r--gcc/d/dmd/parse.c4
-rw-r--r--gcc/d/dmd/root/array.h28
-rw-r--r--gcc/d/dmd/root/bitarray.h4
-rw-r--r--gcc/d/dmd/root/dcompat.h12
-rw-r--r--gcc/d/dmd/root/outbuffer.h4
-rw-r--r--gcc/d/dmd/root/rmem.h10
-rw-r--r--gcc/d/dmd/root/stringtable.h9
-rw-r--r--gcc/d/dmd/statementsem.c14
-rw-r--r--gcc/d/dmd/target.h4
-rw-r--r--gcc/d/expr.cc64
-rw-r--r--gcc/d/intrinsics.cc23
-rw-r--r--gcc/d/intrinsics.def20
-rw-r--r--gcc/d/modules.cc14
-rw-r--r--gcc/d/types.cc11
-rw-r--r--gcc/dbgcnt.def3
-rw-r--r--gcc/dbxout.c1
-rw-r--r--gcc/defaults.h11
-rw-r--r--gcc/df-scan.c12
-rw-r--r--gcc/df.h1
-rw-r--r--gcc/diagnostic.c23
-rw-r--r--gcc/digraph.cc2
-rw-r--r--gcc/doc/analyzer.texi2
-rw-r--r--gcc/doc/cpp.texi30
-rw-r--r--gcc/doc/cppopts.texi4
-rw-r--r--gcc/doc/extend.texi407
-rw-r--r--gcc/doc/generic.texi39
-rw-r--r--gcc/doc/implement-c.texi5
-rw-r--r--gcc/doc/install.texi73
-rw-r--r--gcc/doc/invoke.texi1200
-rw-r--r--gcc/doc/md.texi82
-rw-r--r--gcc/doc/options.texi3
-rw-r--r--gcc/doc/passes.texi3
-rw-r--r--gcc/doc/plugins.texi4
-rw-r--r--gcc/doc/rtl.texi811
-rw-r--r--gcc/doc/sourcebuild.texi34
-rw-r--r--gcc/doc/standards.texi8
-rw-r--r--gcc/doc/tm.texi183
-rw-r--r--gcc/doc/tm.texi.in30
-rw-r--r--gcc/dojump.c63
-rw-r--r--gcc/dse.c5
-rw-r--r--gcc/dumpfile.c18
-rw-r--r--gcc/dwarf2out.c416
-rw-r--r--gcc/dwarf2out.h17
-rw-r--r--gcc/edit-context.c14
-rw-r--r--gcc/emit-rtl.h6
-rw-r--r--gcc/explow.c12
-rw-r--r--gcc/explow.h2
-rw-r--r--gcc/expmed.c75
-rw-r--r--gcc/expmed.h4
-rw-r--r--gcc/expr.c222
-rw-r--r--gcc/final.c22
-rw-r--r--gcc/flag-types.h42
-rw-r--r--gcc/fold-const-call.c3
-rw-r--r--gcc/fold-const.c916
-rw-r--r--gcc/fold-const.h11
-rw-r--r--gcc/fortran/ChangeLog440
-rw-r--r--gcc/fortran/Make-lang.in6
-rw-r--r--gcc/fortran/check.c13
-rw-r--r--gcc/fortran/cpp.c10
-rw-r--r--gcc/fortran/data.c104
-rw-r--r--gcc/fortran/decl.c3
-rw-r--r--gcc/fortran/dump-parse-tree.c53
-rw-r--r--gcc/fortran/expr.c3
-rw-r--r--gcc/fortran/f95-lang.c11
-rw-r--r--gcc/fortran/gfortran.h41
-rw-r--r--gcc/fortran/gfortran.texi7
-rw-r--r--gcc/fortran/lang.opt4
-rw-r--r--gcc/fortran/match.c3
-rw-r--r--gcc/fortran/match.h1
-rw-r--r--gcc/fortran/misc.c28
-rw-r--r--gcc/fortran/module.c3
-rw-r--r--gcc/fortran/openmp.c754
-rw-r--r--gcc/fortran/options.c16
-rw-r--r--gcc/fortran/parse.c26
-rw-r--r--gcc/fortran/primary.c32
-rw-r--r--gcc/fortran/resolve.c60
-rw-r--r--gcc/fortran/scanner.c32
-rw-r--r--gcc/fortran/st.c5
-rw-r--r--gcc/fortran/trans-array.c658
-rw-r--r--gcc/fortran/trans-decl.c26
-rw-r--r--gcc/fortran/trans-expr.c312
-rw-r--r--gcc/fortran/trans-intrinsic.c108
-rw-r--r--gcc/fortran/trans-openmp.c238
-rw-r--r--gcc/fortran/trans-stmt.c7
-rw-r--r--gcc/fortran/trans-types.c22
-rw-r--r--gcc/fortran/trans-types.h3
-rw-r--r--gcc/fortran/trans.c23
-rw-r--r--gcc/fortran/trans.h5
-rw-r--r--gcc/fortran/types.def5
-rw-r--r--gcc/function-tests.c1
-rw-r--r--gcc/function.c200
-rw-r--r--gcc/function.h7
-rw-r--r--gcc/fwprop.c1685
-rw-r--r--gcc/gcc.c61
-rw-r--r--gcc/gcov-io.h2
-rw-r--r--gcc/gcov.c23
-rw-r--r--gcc/gdbinit.in38
-rw-r--r--gcc/genextract.c2
-rw-r--r--gcc/gengtype.c2
-rw-r--r--gcc/genmodes.c22
-rw-r--r--gcc/gimple-fold.c905
-rw-r--r--gcc/gimple-fold.h16
-rw-r--r--gcc/gimple-if-to-switch.cc575
-rw-r--r--gcc/gimple-isel.cc48
-rw-r--r--gcc/gimple-loop-interchange.cc9
-rw-r--r--gcc/gimple-pretty-print.c10
-rw-r--r--gcc/gimple-range-cache.cc387
-rw-r--r--gcc/gimple-range-cache.h24
-rw-r--r--gcc/gimple-range-gori.cc68
-rw-r--r--gcc/gimple-range-gori.h7
-rw-r--r--gcc/gimple-range.cc224
-rw-r--r--gcc/gimple-range.h10
-rw-r--r--gcc/gimple-ssa-evrp-analyze.c6
-rw-r--r--gcc/gimple-ssa-sprintf.c30
-rw-r--r--gcc/gimple-ssa-store-merging.c117
-rw-r--r--gcc/gimple.c108
-rw-r--r--gcc/gimple.h64
-rw-r--r--gcc/gimplify-me.c12
-rw-r--r--gcc/gimplify.c476
-rw-r--r--gcc/ginclude/float.h86
-rw-r--r--gcc/ginclude/stdatomic.h14
-rw-r--r--gcc/ginclude/stdbool.h5
-rw-r--r--gcc/go/ChangeLog34
-rw-r--r--gcc/go/Make-lang.in5
-rw-r--r--gcc/go/go-gcc.cc4
-rw-r--r--gcc/go/go-lang.c16
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/ast-dump.cc6
-rw-r--r--gcc/go/gofrontend/escape.cc2
-rw-r--r--gcc/go/gofrontend/export.cc11
-rw-r--r--gcc/go/gofrontend/expressions.cc344
-rw-r--r--gcc/go/gofrontend/expressions.h21
-rw-r--r--gcc/go/gofrontend/go-encode-id.cc289
-rw-r--r--gcc/go/gofrontend/go-encode-id.h13
-rw-r--r--gcc/go/gofrontend/gogo.cc279
-rw-r--r--gcc/go/gofrontend/gogo.h205
-rw-r--r--gcc/go/gofrontend/import.cc18
-rw-r--r--gcc/go/gofrontend/lex.cc11
-rw-r--r--gcc/go/gofrontend/names.cc885
-rw-r--r--gcc/go/gofrontend/parse.cc39
-rw-r--r--gcc/go/gofrontend/runtime.def57
-rw-r--r--gcc/go/gofrontend/statements.cc165
-rw-r--r--gcc/go/gofrontend/statements.h48
-rw-r--r--gcc/go/gofrontend/types.cc252
-rw-r--r--gcc/go/gofrontend/types.h88
-rw-r--r--gcc/go/gofrontend/wb.cc5
-rw-r--r--gcc/godump.c73
-rw-r--r--gcc/hard-reg-set.h2
-rw-r--r--gcc/ifcvt.c6
-rw-r--r--gcc/incpath.c6
-rw-r--r--gcc/internal-fn.c267
-rw-r--r--gcc/internal-fn.def10
-rw-r--r--gcc/internal-fn.h2
-rw-r--r--gcc/ipa-cp.c295
-rw-r--r--gcc/ipa-devirt.c3
-rw-r--r--gcc/ipa-fnsummary.c89
-rw-r--r--gcc/ipa-fnsummary.h17
-rw-r--r--gcc/ipa-icf-gimple.c225
-rw-r--r--gcc/ipa-icf-gimple.h25
-rw-r--r--gcc/ipa-icf.c124
-rw-r--r--gcc/ipa-icf.h10
-rw-r--r--gcc/ipa-inline-analysis.c3
-rw-r--r--gcc/ipa-inline-transform.c38
-rw-r--r--gcc/ipa-modref-tree.h44
-rw-r--r--gcc/ipa-modref.c2301
-rw-r--r--gcc/ipa-modref.h4
-rw-r--r--gcc/ipa-param-manipulation.c14
-rw-r--r--gcc/ipa-prop.c191
-rw-r--r--gcc/ipa-prop.h21
-rw-r--r--gcc/ipa-pure-const.c3
-rw-r--r--gcc/ipa-ref.c6
-rw-r--r--gcc/ipa-ref.h21
-rw-r--r--gcc/ipa-reference.c6
-rw-r--r--gcc/ipa-sra.c180
-rw-r--r--gcc/ipa-utils.h14
-rw-r--r--gcc/ira-color.c6
-rw-r--r--gcc/ira.c317
-rw-r--r--gcc/ira.h8
-rw-r--r--gcc/is-a.h81
-rw-r--r--gcc/iterator-utils.h203
-rw-r--r--gcc/jit/ChangeLog154
-rw-r--r--gcc/jit/Make-lang.in6
-rw-r--r--gcc/jit/docs/_build/texinfo/Makefile11
-rw-r--r--gcc/jit/docs/_build/texinfo/libgccjit.texi1837
-rw-r--r--gcc/jit/docs/cp/topics/asm.rst308
-rw-r--r--gcc/jit/docs/cp/topics/index.rst1
-rw-r--r--gcc/jit/docs/topics/asm.rst311
-rw-r--r--gcc/jit/docs/topics/compatibility.rst17
-rw-r--r--gcc/jit/docs/topics/functions.rst3
-rw-r--r--gcc/jit/docs/topics/index.rst1
-rw-r--r--gcc/jit/docs/topics/objects.rst1
-rw-r--r--gcc/jit/jit-common.h2
-rw-r--r--gcc/jit/jit-playback.c125
-rw-r--r--gcc/jit/jit-playback.h27
-rw-r--r--gcc/jit/jit-recording.c573
-rw-r--r--gcc/jit/jit-recording.h224
-rw-r--r--gcc/jit/libgccjit++.h170
-rw-r--r--gcc/jit/libgccjit.c188
-rw-r--r--gcc/jit/libgccjit.h105
-rw-r--r--gcc/jit/libgccjit.map13
-rw-r--r--gcc/json.cc5
-rw-r--r--gcc/jump.c24
-rw-r--r--gcc/langhooks-def.h16
-rw-r--r--gcc/langhooks.c18
-rw-r--r--gcc/langhooks.h28
-rw-r--r--gcc/loop-doloop.c2
-rw-r--r--gcc/loop-init.c9
-rw-r--r--gcc/loop-invariant.c4
-rw-r--r--gcc/loop-iv.c6
-rw-r--r--gcc/lra-assigns.c17
-rw-r--r--gcc/lra-constraints.c55
-rw-r--r--gcc/lra-int.h3
-rw-r--r--gcc/lra-remat.c4
-rw-r--r--gcc/lra-spills.c18
-rw-r--r--gcc/lra.c240
-rw-r--r--gcc/lto-cgraph.c44
-rw-r--r--gcc/lto-streamer-in.c8
-rw-r--r--gcc/lto-streamer-out.c5
-rw-r--r--gcc/lto-streamer.h6
-rw-r--r--gcc/lto-wrapper.c11
-rw-r--r--gcc/lto/ChangeLog45
-rw-r--r--gcc/lto/Make-lang.in18
-rw-r--r--gcc/lto/lang.opt6
-rw-r--r--gcc/lto/lto-common.c6
-rw-r--r--gcc/lto/lto-partition.c5
-rw-r--r--gcc/lto/lto-symtab.c6
-rw-r--r--gcc/machmode.def3
-rw-r--r--gcc/machmode.h4
-rw-r--r--gcc/match.pd205
-rw-r--r--gcc/mode-classes.def3
-rw-r--r--gcc/modulo-sched.c71
-rw-r--r--gcc/mux-utils.h251
-rw-r--r--gcc/objc/ChangeLog76
-rw-r--r--gcc/objc/Make-lang.in6
-rw-r--r--gcc/objc/objc-act.c431
-rw-r--r--gcc/objc/objc-act.h17
-rw-r--r--gcc/objc/objc-gnu-runtime-abi-01.c7
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c7
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c7
-rw-r--r--gcc/objcp/ChangeLog14
-rw-r--r--gcc/objcp/Make-lang.in6
-rw-r--r--gcc/obstack-utils.h86
-rw-r--r--gcc/omp-builtins.def9
-rw-r--r--gcc/omp-expand.c142
-rw-r--r--gcc/omp-general.c121
-rw-r--r--gcc/omp-low.c588
-rw-r--r--gcc/omp-oacc-kernels-decompose.cc1545
-rw-r--r--gcc/omp-offload.c104
-rw-r--r--gcc/omp-simd-clone.c70
-rw-r--r--gcc/opt-functions.awk4
-rw-r--r--gcc/optabs-tree.c66
-rw-r--r--gcc/optabs.c457
-rw-r--r--gcc/optabs.def10
-rw-r--r--gcc/optabs.h16
-rw-r--r--gcc/optc-gen.awk31
-rw-r--r--gcc/optc-save-gen.awk36
-rw-r--r--gcc/opts-common.c12
-rw-r--r--gcc/opts.c359
-rw-r--r--gcc/opts.h25
-rw-r--r--gcc/output.h16
-rw-r--r--gcc/params.opt50
-rw-r--r--gcc/passes.c56
-rw-r--r--gcc/passes.def14
-rw-r--r--gcc/plugin.c2
-rw-r--r--gcc/plugin.def4
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/po/zh_TW.po8
-rw-r--r--gcc/poly-int-types.h8
-rw-r--r--gcc/poly-int.h57
-rw-r--r--gcc/predict.c67
-rw-r--r--gcc/predict.h12
-rw-r--r--gcc/print-rtl.c7
-rw-r--r--gcc/print-rtl.h1
-rw-r--r--gcc/print-tree.c22
-rw-r--r--gcc/range-op.cc839
-rw-r--r--gcc/read-rtl.c175
-rw-r--r--gcc/recog.c500
-rw-r--r--gcc/recog.h155
-rw-r--r--gcc/reg-stack.c3
-rw-r--r--gcc/reginfo.c5
-rw-r--r--gcc/reload.c120
-rw-r--r--gcc/resource.c2
-rw-r--r--gcc/rtl-ssa.h71
-rw-r--r--gcc/rtl-ssa/access-utils.h553
-rw-r--r--gcc/rtl-ssa/accesses.cc1594
-rw-r--r--gcc/rtl-ssa/accesses.h1032
-rw-r--r--gcc/rtl-ssa/blocks.cc1146
-rw-r--r--gcc/rtl-ssa/blocks.h301
-rw-r--r--gcc/rtl-ssa/change-utils.h137
-rw-r--r--gcc/rtl-ssa/changes.cc1025
-rw-r--r--gcc/rtl-ssa/changes.h118
-rw-r--r--gcc/rtl-ssa/functions.cc325
-rw-r--r--gcc/rtl-ssa/functions.h433
-rw-r--r--gcc/rtl-ssa/insn-utils.h46
-rw-r--r--gcc/rtl-ssa/insns.cc718
-rw-r--r--gcc/rtl-ssa/insns.h505
-rw-r--r--gcc/rtl-ssa/internals.inl682
-rw-r--r--gcc/rtl-ssa/is-a.inl98
-rw-r--r--gcc/rtl-ssa/member-fns.inl928
-rw-r--r--gcc/rtl-ssa/movement.h335
-rw-r--r--gcc/rtl.h151
-rw-r--r--gcc/rtlanal.c331
-rw-r--r--gcc/rtlanal.h334
-rw-r--r--gcc/sanitizer.def61
-rw-r--r--gcc/sanopt.c21
-rw-r--r--gcc/sbitmap.c3
-rw-r--r--gcc/sel-sched-ir.c3
-rw-r--r--gcc/selftest-run-tests.c1
-rw-r--r--gcc/selftest.h2
-rw-r--r--gcc/shrink-wrap.c2
-rw-r--r--gcc/simplify-rtx.c152
-rw-r--r--gcc/splay-tree-utils.cc264
-rw-r--r--gcc/splay-tree-utils.h491
-rw-r--r--gcc/splay-tree-utils.tcc960
-rw-r--r--gcc/stor-layout.c3
-rw-r--r--gcc/symbol-summary.h189
-rw-r--r--gcc/symtab-clones.cc62
-rw-r--r--gcc/symtab-clones.h90
-rw-r--r--gcc/symtab-thunks.cc35
-rw-r--r--gcc/symtab-thunks.h9
-rw-r--r--gcc/symtab.c142
-rw-r--r--gcc/system.h12
-rw-r--r--gcc/target.def185
-rw-r--r--gcc/target.h26
-rw-r--r--gcc/targhooks.c154
-rw-r--r--gcc/targhooks.h14
-rw-r--r--gcc/testsuite/ChangeLog6349
-rw-r--r--gcc/testsuite/ada/acats/support/acats25.lst4308
-rw-r--r--gcc/testsuite/ada/acats/support/acats26.lst4332
-rw-r--r--gcc/testsuite/ada/acats/support/fcndecl.ada18
-rw-r--r--gcc/testsuite/ada/acats/support/impdef.a15
-rw-r--r--gcc/testsuite/ada/acats/support/impdefg.a27
-rw-r--r--gcc/testsuite/ada/acats/support/macro.dfs5
-rw-r--r--gcc/testsuite/ada/acats/support/repbody.ada5
-rw-r--r--gcc/testsuite/ada/acats/support/tctouch.ada3
-rw-r--r--gcc/testsuite/ada/acats/tests/c3/c352001.a270
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c433001.a9
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c453001.a236
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c45622a.ada83
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c45624a.ada86
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c45624b.ada81
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c460013.a188
-rw-r--r--gcc/testsuite/ada/acats/tests/c4/c460014.a289
-rw-r--r--gcc/testsuite/ada/acats/tests/c6/c620001.a340
-rw-r--r--gcc/testsuite/ada/acats/tests/c6/c620002.a509
-rw-r--r--gcc/testsuite/ada/acats/tests/c7/c761006.a47
-rw-r--r--gcc/testsuite/ada/acats/tests/c9/c96004a.ada48
-rw-r--r--gcc/testsuite/ada/acats/tests/c9/c96007a.ada28
-rw-r--r--gcc/testsuite/ada/acats/tests/cb/cb41004.a73
-rw-r--r--gcc/testsuite/ada/acats/tests/cc/cc3016f.ada19
-rw-r--r--gcc/testsuite/ada/acats/tests/cd/cd30011.a155
-rw-r--r--gcc/testsuite/ada/acats/tests/cd/cd30012.a173
-rw-r--r--gcc/testsuite/ada/acats/tests/cd/cd90001.a31
-rw-r--r--gcc/testsuite/ada/acats/tests/cxa/cxa3004.a235
-rw-r--r--gcc/testsuite/ada/acats/tests/cxa/cxa5013.a326
-rw-r--r--gcc/testsuite/ada/acats/tests/cxa/cxac005.a24
-rw-r--r--gcc/testsuite/ada/acats/tests/cxb/cxb30061.am404
-rw-r--r--gcc/testsuite/ada/acats/tests/cxf/cxf2001.a202
-rw-r--r--gcc/testsuite/c-c++-common/Wfree-nonheap-object-2.c52
-rw-r--r--gcc/testsuite/c-c++-common/Wfree-nonheap-object-3.c70
-rw-r--r--gcc/testsuite/c-c++-common/Wfree-nonheap-object.c50
-rw-r--r--gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c6
-rw-r--r--gcc/testsuite/c-c++-common/Wmismatched-dealloc.c67
-rw-r--r--gcc/testsuite/c-c++-common/Wstringop-overflow-2.c10
-rw-r--r--gcc/testsuite/c-c++-common/Wunused-value-1.c33
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-compare-1.c7
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr98204.c6
-rw-r--r--gcc/testsuite/c-c++-common/asmgoto-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/attr-fallthrough-2.c4
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-2.c1
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-3.c7
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-4.c7
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-5.c27
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-6.c27
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-7.c9
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-8.c9
-rw-r--r--gcc/testsuite/c-c++-common/attr-used-9.c28
-rw-r--r--gcc/testsuite/c-c++-common/attr-used.c1
-rw-r--r--gcc/testsuite/c-c++-common/builtin-clear-padding-1.c19
-rw-r--r--gcc/testsuite/c-c++-common/builtin-clear-padding-2.c17
-rw-r--r--gcc/testsuite/c-c++-common/builtin-clear-padding-3.c15
-rw-r--r--gcc/testsuite/c-c++-common/cpp/wide-narrow-predef-macros.c13
-rw-r--r--gcc/testsuite/c-c++-common/goacc-gomp/atomic.c43
-rw-r--r--gcc/testsuite/c-c++-common/goacc/atomic.c30
-rw-r--r--gcc/testsuite/c-c++-common/goacc/cache-1.c18
-rw-r--r--gcc/testsuite/c-c++-common/goacc/cache-2.c10
-rw-r--r--gcc/testsuite/c-c++-common/goacc/cache-3-1.c116
-rw-r--r--gcc/testsuite/c-c++-common/goacc/cache-3-2.c50
-rw-r--r--gcc/testsuite/c-c++-common/goacc/classify-parallel.c4
-rw-r--r--gcc/testsuite/c-c++-common/goacc/classify-serial.c29
-rw-r--r--gcc/testsuite/c-c++-common/goacc/clause-locations.c19
-rw-r--r--gcc/testsuite/c-c++-common/goacc/data-clause-1.c115
-rw-r--r--gcc/testsuite/c-c++-common/goacc/data-clause-2.c49
-rw-r--r--gcc/testsuite/c-c++-common/goacc/if-clause-2.c24
-rw-r--r--gcc/testsuite/c-c++-common/goacc/kernels-decompose-1.c91
-rw-r--r--gcc/testsuite/c-c++-common/goacc/kernels-decompose-2.c149
-rw-r--r--gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c109
-rw-r--r--gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c16
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-1-kernels.c236
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-1-parallel.c318
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-1-routine.c68
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-2-kernels.c305
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-2-parallel.c389
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-2-routine.c93
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions-warn.c525
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nested-reductions.c420
-rw-r--r--gcc/testsuite/c-c++-common/goacc/pr79428-1.c4
-rw-r--r--gcc/testsuite/c-c++-common/goacc/pr92793-1.c141
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-1.c84
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-2.c45
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-3.c38
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-4.c39
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-5.c41
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clauses-1.c138
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clauses-2.c20
-rw-r--r--gcc/testsuite/c-c++-common/gomp/depobj-2.c11
-rw-r--r--gcc/testsuite/c-c++-common/gomp/doacross-4.c30
-rw-r--r--gcc/testsuite/c-c++-common/gomp/map-1.c7
-rw-r--r--gcc/testsuite/c-c++-common/gomp/map-2.c7
-rw-r--r--gcc/testsuite/c-c++-common/gomp/map-5.c24
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr79428-2.c3
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr97862.c15
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr97958.c17
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr98187.c109
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c16
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c33
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c66
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c65
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c25
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/arguments-1.c3
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/arguments-2.c3
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/arguments-3.c3
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/arguments.c3
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c24
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c36
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c31
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c19
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c24
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/bitfield-1.c31
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/bitfield-2.c30
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c31
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/check-interface.c26
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c24
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c37
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/heap-overflow.c29
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c29
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c51
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c48
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c56
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c35
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c37
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c33
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c14
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c75
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c15
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c15
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c15
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c16
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c16
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c16
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c16
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/macro-definition.c11
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c12
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c10
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c7
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c21
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c7
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c7
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c25
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c54
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c19
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c37
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c18
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c33
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c46
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c16
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/use-after-free.c28
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c22
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c43
-rw-r--r--gcc/testsuite/c-c++-common/hwasan/very-large-objects.c68
-rw-r--r--gcc/testsuite/c-c++-common/patchable_function_entry-error-3.c6
-rw-r--r--gcc/testsuite/c-c++-common/raw-string-6.c3
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-noinit-1.c7
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-noinit-2.c8
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-noinit-3.c11
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c12
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc58
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-persistent-1.c8
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-persistent-2.c8
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-persistent-3.c10
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c11
-rw-r--r--gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc58
-rw-r--r--gcc/testsuite/c-c++-common/torture/builtin-clear-padding-1.c47
-rw-r--r--gcc/testsuite/c-c++-common/torture/builtin-clear-padding-2.c24
-rw-r--r--gcc/testsuite/c-c++-common/torture/builtin-clear-padding-3.c65
-rw-r--r--gcc/testsuite/c-c++-common/torture/builtin-clear-padding-4.c59
-rw-r--r--gcc/testsuite/c-c++-common/torture/builtin-clear-padding-5.c49
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c2
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-1.c15
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-10.c93
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-11.c5
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-2.c4
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-3.c4
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-4.c4
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-5.c5
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-6.c4
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-7.c4
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-8.c5
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-9.c5
-rw-r--r--gcc/testsuite/c-c++-common/zero-scratch-regs-attr-usages.c16
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2303.C37
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr625.C15
-rw-r--r--gcc/testsuite/g++.dg/Wclass-memaccess.C209
-rw-r--r--gcc/testsuite/g++.dg/abi/macro0.C2
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test.cc2
-rw-r--r--gcc/testsuite/g++.dg/concepts/pack-1.C31
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr94252.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof6.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof7.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof8.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto54.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C36
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-overflow3.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype63.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum41.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/fallthrough2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/friend6.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-64.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C45
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-deduce3.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-template3.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/linkage2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/new4.C36
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr68726.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr78341.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/using-enum-1.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/using-enum-2.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/using-enum-3.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-88982.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-98122.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-label.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/decltype-auto1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr65202.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr65340.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr68578.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction44.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction69.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction75.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction76.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/fold12.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inline-var8.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/attr-likely2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast1.C47
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast2.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast3.C229
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast4.C44
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast5.C69
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast6.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast7.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-abbrev1.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-complete1.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-complete2.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-complete3.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-conv3.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-conv3a.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-decltype2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nonbool3.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr78173.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr84979.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr97093.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat4.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires22.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires23.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-using3.C52
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-variadic2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval-defarg2.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor10.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor5.C35
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor6.C36
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor8.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/enum-conv1.C117
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/enum-conv2.C115
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/enum-conv3.C115
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/fn-template16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/fn-template7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-generic8.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class39.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class40.C79
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/pr98082.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-p1186.C117
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg5.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth10.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc15.C119
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc16.C97
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc17.C122
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc18.C100
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-1.C62
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-2.C48
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-3.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-4.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-5.C132
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-6.C5
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C7
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C7
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/using-enum.C21
-rw-r--r--gcc/testsuite/g++.dg/debug/localclass2.C24
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/nullptr.C8
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr87386.C2
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr96045-1.C4
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr96045-2.C6
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr96045-3.C6
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/static_assert1.C30
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/static_assert2.C68
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/static_assert3.C36
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C2
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/unclosed-function.C3
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C3
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C3
-rw-r--r--gcc/testsuite/g++.dg/eh/crash2.C20
-rw-r--r--gcc/testsuite/g++.dg/eh/pr42859.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/anew5.C26
-rw-r--r--gcc/testsuite/g++.dg/expr/anew6.C33
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-used-2.C15
-rw-r--r--gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C15
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_constructible1.C48
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_constructible2.C15
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_constructible3.C8
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_constructible4.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_constructible5.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/is_nothrow_constructible6.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/pr84598.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/sve-sizeless-1.C33
-rw-r--r--gcc/testsuite/g++.dg/ext/sve-sizeless-2.C33
-rw-r--r--gcc/testsuite/g++.dg/goacc/cache-1.C15
-rw-r--r--gcc/testsuite/g++.dg/goacc/cache-2.C64
-rw-r--r--gcc/testsuite/g++.dg/goacc/cache-3-1.C123
-rw-r--r--gcc/testsuite/g++.dg/goacc/cache-3-2.C57
-rw-r--r--gcc/testsuite/g++.dg/goacc/data-clause-1.C122
-rw-r--r--gcc/testsuite/g++.dg/goacc/data-clause-2.C56
-rw-r--r--gcc/testsuite/g++.dg/gomp/allocate-1.C88
-rw-r--r--gcc/testsuite/g++.dg/gomp/allocate-2.C11
-rw-r--r--gcc/testsuite/g++.dg/gomp/allocate-3.C206
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-target-3.C31
-rw-r--r--gcc/testsuite/g++.dg/gomp/map-1.C119
-rw-r--r--gcc/testsuite/g++.dg/gomp/map-2.C54
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr98383.C18
-rw-r--r--gcc/testsuite/g++.dg/gomp/tls-5.C2
-rw-r--r--gcc/testsuite/g++.dg/guality/guality.exp2
-rw-r--r--gcc/testsuite/g++.dg/guality/redeclaration1.C8
-rw-r--r--gcc/testsuite/g++.dg/hwasan/hwasan.exp34
-rw-r--r--gcc/testsuite/g++.dg/hwasan/rvo-handled.C46
-rw-r--r--gcc/testsuite/g++.dg/inherit/thunk8.C1
-rw-r--r--gcc/testsuite/g++.dg/inherit/using5.C2
-rw-r--r--gcc/testsuite/g++.dg/init/array60.C8
-rw-r--r--gcc/testsuite/g++.dg/init/empty3.C18
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-24.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr98057.C18
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr98075.C30
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr80891-5.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr97877.C8
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr97905.C7
-rw-r--r--gcc/testsuite/g++.dg/lookup/using26.C4
-rw-r--r--gcc/testsuite/g++.dg/lookup/using53.C1
-rw-r--r--gcc/testsuite/g++.dg/lto/pr79050_0.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr84805_0.C2
-rw-r--r--gcc/testsuite/g++.dg/modules/access-1_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/access-1_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/access-1_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/adhoc-1_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/adhoc-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-1_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-1_c.C57
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-2_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-2_b.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-2_c.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-3_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-3_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-3_c.C36
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-4_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-4_b.C36
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-5_a.c9
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-5_b.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-5_c.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/adl-5_d.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-1_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-1_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-1_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-1_d.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-1_e.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-1_f.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-2_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/alias-2_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/align-type-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/align-type-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/ambig-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/ambig-1_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/anon-1_a.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/anon-1_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/anon-1_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/anon-2.h6
-rw-r--r--gcc/testsuite/g++.dg/modules/anon-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/anon-2_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-decl-0_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-decl-0_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-decl-0_c.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-decl-2.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-decl-3.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-pragma-1.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-pragma-3.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-1.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-2_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-2_c.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-2_d.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-2_e.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-2_f.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-3.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-4.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/auto-1.h19
-rw-r--r--gcc/testsuite/g++.dg/modules/auto-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/auto-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/auto-2.h13
-rw-r--r--gcc/testsuite/g++.dg/modules/auto-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/auto-2_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/bad-mapper-1.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/bad-mapper-2.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/bad-mapper-3.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/ben-1.map3
-rw-r--r--gcc/testsuite/g++.dg/modules/ben-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/ben-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/bfield-1_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/bfield-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/bfield-2_a.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/bfield-2_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/bool-1.h8
-rw-r--r--gcc/testsuite/g++.dg/modules/bool-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/bool-1_b.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/bool-1_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/bug-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/bug-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-1_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-1_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-2.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-3_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-4_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-4_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-5_a.H3
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-5_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-6_a.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-6_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-7_a.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/builtin-7_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/by-name-1.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/cexpr-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/cexpr-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/cexpr-2_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/cexpr-2_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/circ-1_a.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/circ-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/circ-1_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/circ-1_d.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/class-1_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/class-1_b.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/class-1_c.C35
-rw-r--r--gcc/testsuite/g++.dg/modules/class-2_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/class-2_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/class-3_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/class-3_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/class-3_c.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/class-3_d.C25
-rw-r--r--gcc/testsuite/g++.dg/modules/class-4_a.C25
-rw-r--r--gcc/testsuite/g++.dg/modules/class-4_b.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/class-5_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/class-5_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/class-5_c.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/class-6_a.C30
-rw-r--r--gcc/testsuite/g++.dg/modules/class-6_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/class-6_c.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/class-7_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/class-7_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/class-7_c.C39
-rw-r--r--gcc/testsuite/g++.dg/modules/class-8_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/class-8_b.C23
-rw-r--r--gcc/testsuite/g++.dg/modules/clone-1_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/clone-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-1_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-2_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-2_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-3_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-3_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-4.H18
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-5.h7
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-5_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-5_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-6.h19
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-6_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/concept-6_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/constrained-partial-1_a.C38
-rw-r--r--gcc/testsuite/g++.dg/modules/constrained-partial-1_b.C31
-rw-r--r--gcc/testsuite/g++.dg/modules/convop-1_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/convop-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-1.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-2_b.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-2_c.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-3.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-4.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-4.h4
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-5_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-5_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-5_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-6_a.H3
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-6_b.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-6_c.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/debug-1_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/debug-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/decomp-1_a.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/decomp-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/deferred-1.h12
-rw-r--r--gcc/testsuite/g++.dg/modules/deferred-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/deferred-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/dep-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/dep-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/dep-2.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/dep-3.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/dir-only-1.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/dir-only-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/dir-only-2_b.C28
-rw-r--r--gcc/testsuite/g++.dg/modules/dir-only-3.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/dir-only-4.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/dir-recovery.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-1_a.C30
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-1_b.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-2_a.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-2_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-3_a.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-3_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-4_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-4_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-5_a.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-5_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-6_a.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-6_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-7.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-8_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-8_b.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-8_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-8_d.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-bad-1_a.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/enum-bad-1_b.C26
-rw-r--r--gcc/testsuite/g++.dg/modules/err-1_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/err-1_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/err-1_c.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/err-1_d.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/except-1.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/except-2.h42
-rw-r--r--gcc/testsuite/g++.dg/modules/except-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/except-2_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/except-3.h24
-rw-r--r--gcc/testsuite/g++.dg/modules/except-3_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/except-3_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/exp-xlate-1_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/exp-xlate-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/export-1.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-1_a.H23
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-1_c.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-2_a.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-2_b.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-2_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/extern-tpl-2_d.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/flag-1_a.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/flag-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/fn-inline-1_a.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/fn-inline-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/fn-inline-1_c.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/freeze-1_a.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/freeze-1_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/freeze-1_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/freeze-1_d.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-1_a.C37
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-1_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-2_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-2_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-3.C34
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-4_a.C33
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-4_b.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-5_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/friend-5_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/gc-1_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/gc-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/gc-1_c.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/gc-1_d.C28
-rw-r--r--gcc/testsuite/g++.dg/modules/gc-2.map2
-rw-r--r--gcc/testsuite/g++.dg/modules/gc-2_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/global-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/global-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/gmf-1_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/gmf-1_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/gmf-2_a.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/gmf-2_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/gmf-2_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/gmf-2_d.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/gvar_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/gvar_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/hdr-1_a.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/hdr-1_b.H21
-rw-r--r--gcc/testsuite/g++.dg/modules/hdr-1_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/hdr-init-1_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/hdr-init-1_b.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/hdr-init-1_c.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/horcrux-1_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/horcrux-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/ice-1.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-inline-1_a.C37
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-inline-1_b.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-1_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-1_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-1_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-1_d.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-1_e.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-2_a.C28
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-2_b.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-2_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/imp-member-3.H16
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_a.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_d.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_e.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_f.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/import-1_g.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/import-2.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/inc-xlate-1.map2
-rw-r--r--gcc/testsuite/g++.dg/modules/inc-xlate-1_a.H15
-rw-r--r--gcc/testsuite/g++.dg/modules/inc-xlate-1_b.H21
-rw-r--r--gcc/testsuite/g++.dg/modules/inc-xlate-1_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/inc-xlate-1_e.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-1_a.C41
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-1_b.C54
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-1_c.C49
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-2_a.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-2_b.C31
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-2_c.C25
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-3_a.C23
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-3_b.C30
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-3_c.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-4_a.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-4_b.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/indirect-4_c.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/inext-1.H11
-rw-r--r--gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1.h35
-rw-r--r--gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/init-1_a.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/init-1_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/init-2_a.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/init-2_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/init-2_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-1_a.C42
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-1_b.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-2_a.C26
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-2_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-3_a.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-3_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-4_a.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-4_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-5_a.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/inst-5_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/internal-1.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/internal-2_a.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/internal-2_b.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/internal-2_c.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/isalnum.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/keyword-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/keyword-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-1_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-1_b.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-2.h2
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-2_a.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-2_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-2_c.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-3.h5
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-3_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-3_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-3_c.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-4.h2
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-4_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/lambda-4_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/lang-1_a.H15
-rw-r--r--gcc/testsuite/g++.dg/modules/lang-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/lang-1_c.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/lang-2_a.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/lang-2_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-1.H16
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-2_a.H14
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-2_b.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-2_c.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-3_a.H20
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-3_b.H20
-rw-r--r--gcc/testsuite/g++.dg/modules/late-ret-3_c.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/lazy-1_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/lazy-1_b.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-1_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-1_b.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-1_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-1_d.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-2_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-2_b.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-2_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-3_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-3_b.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-3_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-3_d.C1
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-4_a.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-4_b.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-4_c.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-5_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-5_b.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-5_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-6_a.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-6_b.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-6_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-7_a.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-7_b.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-7_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-8_a.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-8_b.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-8_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-9_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-9_b.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/leg-merge-9_c.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-1_a.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-1_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-1_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-2.h1
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-2.map1
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-2_a.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-2_b.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-2_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-2_d.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-3.h1
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-3_a.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-3_b.H16
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-3_c.H25
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6.map2
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6_b.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6_d.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6_e.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-6_f.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-7_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-7_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-8_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-8_b.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-8_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-8_d.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/legacy-8_e.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/libfn-1_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/libfn-1_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/literals-1_a.C51
-rw-r--r--gcc/testsuite/g++.dg/modules/literals-1_b.C39
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-1_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-1_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-2_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-2_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-2_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-2_d.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-2_e.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-2_f.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-wrapper-1.h14
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-wrapper-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-wrapper-1_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/local-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/local-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/local-extern-1.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/local-extern-2.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/local-struct-1_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/local-struct-1_b.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/macloc-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/macloc-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/macloc-1_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/macloc-1_d.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/macloc-2_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/macloc-2_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-1_a.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-1_b.C25
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-2_a.H14
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-2_b.H24
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-2_c.H10
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-2_d.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-3_a.H19
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-3_b.H24
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-3_c.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_a.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_b.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_c.H14
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_d.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_e.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_f.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-4_g.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-5_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-5_b.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-5_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-6_a.H8
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-6_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-6_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-7_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-7_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/macro-7_c.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/map-1.map2
-rw-r--r--gcc/testsuite/g++.dg/modules/map-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/map-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/map-1_b.map3
-rw-r--r--gcc/testsuite/g++.dg/modules/map-2.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/map-2.map1
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-1_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-1_c.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-1_d.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-2_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-2_b.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-2_c.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/member-def-2_d.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/memref-1_a.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/memref-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-10.h8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-10_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-10_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-11.h15
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-11_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-11_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-12.h23
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-12_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-12_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-13.h10
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-13_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-13_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-14.h7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-14_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-14_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-15.h5
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-15_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-15_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-2_a.H29
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-2_b.C2
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-3_a.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-3_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-4.h7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-4_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-4_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-5.h8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-5_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-5_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-6.h10
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-6_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-6_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-7.h5
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-7_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-7_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-8.h17
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-8_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-8_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-9.h9
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-9_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/merge-9_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-0-2a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-0.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-1.C29
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-2_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-2_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-2_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-3.C26
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-5_a.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-5_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-exp-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-exp-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-imp-1_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-imp-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-imp-1_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-imp-1_d.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-impl-1_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-impl-1_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-impl-1_c.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-impl-1_d.C27
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-indirect-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-indirect-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-indirect-1_c.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-indirect-1_d.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-indirect-1_e.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-stamp-1_a.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-stamp-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-stamp-1_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-stamp-1_d.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-sym-1.C34
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-sym-2.C23
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-sym-3.C26
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-tpl-1_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-tpl-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-tpl-2_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-tpl-2_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/modules.exp376
-rw-r--r--gcc/testsuite/g++.dg/modules/mutual-friend.ii11
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-1_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-2_a.C40
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-2_b.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-3_a.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-3_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-4_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-4_b.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/namespace-4_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/nest-1_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/nest-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/nest-1_c.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-1_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-1_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-2_a.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-2_b.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-constr-1.h15
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-constr-1_a.H3
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-constr-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-constr-2_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-constr-2_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/nested-constr-2_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/nodes-1_a.C46
-rw-r--r--gcc/testsuite/g++.dg/modules/nodes-1_b.C27
-rw-r--r--gcc/testsuite/g++.dg/modules/noexcept-1.h78
-rw-r--r--gcc/testsuite/g++.dg/modules/noexcept-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/noexcept-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-alias-1_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-alias-1_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-alias-1_c.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-dir-1_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-dir-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-dup-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-dup-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-imp-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-imp-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-imp-1_c.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-part-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-part-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/ns-part-1_c.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/nsdmi-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/nsdmi-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/nsdmi-2.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/omp-1_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/omp-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/omp-1_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/omp-2_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/omp-2_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/only-1.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/only-2.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/only-3.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/operator-1_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/operator-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/p0713-1.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/p0713-2.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/p0713-3.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/part-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/part-1_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/part-1_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/part-2_a.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/part-2_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/part-2_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-2_d.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/part-2_e.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/part-3_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-3_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/part-3_c.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/part-3_d.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/part-4_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-4_b.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/part-4_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/part-6_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/part-6_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/part-6_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/part-6_d.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-6_e.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-7_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-7_b.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/part-7_c.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/part-hdr-1_a.H3
-rw-r--r--gcc/testsuite/g++.dg/modules/part-hdr-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/part-hdr-1_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/part-mac-1_a.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/part-mac-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/part-mac-1_c.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-1.h30
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/partial-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/pmf-1.h10
-rw-r--r--gcc/testsuite/g++.dg/modules/pmf-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/pmf-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/pmf-2.h26
-rw-r--r--gcc/testsuite/g++.dg/modules/pmf-2_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/pmf-2_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/pmp-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/pmp-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/pmp-2.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/pmp-3.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/pragma-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/pragma-1_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/predef-1.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/predef-1.h10
-rw-r--r--gcc/testsuite/g++.dg/modules/predef-2.h7
-rw-r--r--gcc/testsuite/g++.dg/modules/predef-2_a.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/predef-2_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/preproc-1.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/preproc-2_a.H11
-rw-r--r--gcc/testsuite/g++.dg/modules/preproc-2_b.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/printf-1_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/printf-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/reparent-1_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/reparent-1_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/reparent-1_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/scc-1.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/scc-2.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/shadow-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/shadow-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/stat-tpl-1_a.H13
-rw-r--r--gcc/testsuite/g++.dg/modules/static-1_a.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/static-1_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/static-1_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/std-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/std-1_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/stdns_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/stdns_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/sv-1.h75
-rw-r--r--gcc/testsuite/g++.dg/modules/sv-1_a.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/sv-1_b.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-1.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-2_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-2_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-3_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-3_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-4.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-5.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/sym-subst-6.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/sys/alias-2_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/sys/inext-1.H2
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-2_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-2_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-2_c.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-3_a.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-3_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-3_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-4_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-4_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-4_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-5_a.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-5_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-6_a.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-6_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-7.h7
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-7_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-7_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-8_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-8_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-inst-1.h14
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-inst-1_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/tdef-inst-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/thunk-1_a.C23
-rw-r--r--gcc/testsuite/g++.dg/modules/thunk-1_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/tmpl-part-req-1.h15
-rw-r--r--gcc/testsuite/g++.dg/modules/tmpl-part-req-1_a.H3
-rw-r--r--gcc/testsuite/g++.dg/modules/tmpl-part-req-1_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/tmpl-part-req-2.h24
-rw-r--r--gcc/testsuite/g++.dg/modules/tmpl-part-req-2_a.H3
-rw-r--r--gcc/testsuite/g++.dg/modules/tmpl-part-req-2_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/token-1.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/token-2_a.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/token-2_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/token-3.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/token-4.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/token-5.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-alias-1.h70
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-ary-1.h15
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-ary-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-ary-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H16
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H19
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-1_a.C40
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-1_b.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-2_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-3_a.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-3_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-4_a.C25
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-4_b.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-5_a.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-5_b.C23
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-6_a.C26
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-6_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-7_a.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-7_b.C5
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.cc6
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.h9
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_a.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_b.H6
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_c.H5
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_d.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_e.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_f.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-1_a.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-1_b.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-2_a.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-2_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-2_c.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-2_d.C27
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-3_a.C27
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-3_b.C24
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-4_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-4_b.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-5_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-5_b.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-6_a.C22
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-6_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-spec-7.C38
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_b.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1.h22
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2.h65
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_a.H12
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2.h16
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/tplmem-1_a.C32
-rw-r--r--gcc/testsuite/g++.dg/modules/tplmem-1_b.C28
-rw-r--r--gcc/testsuite/g++.dg/modules/tplmem-3_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/tplmem-3_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/ttp-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/ttp-1_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/ttp-2_a.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/ttp-2_b.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/ttp-3_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/ttp-3_b.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/typename-1_a.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/typename-1_b.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/unnamed-1_a.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/unnamed-1_b.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/unnamed-2.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/used-1_a.H7
-rw-r--r--gcc/testsuite/g++.dg/modules/used-1_b.H9
-rw-r--r--gcc/testsuite/g++.dg/modules/used-1_c.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/using-1_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/using-1_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/using-1_c.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/using-2_a.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/using-2_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/using-2_c.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/using-3.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/using-4_a.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/using-4_b.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/using-5_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/using-5_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/using-6_a.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/using-6_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/using-7.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/using-8_a.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/using-8_b.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/using-enum-1_a.H16
-rw-r--r--gcc/testsuite/g++.dg/modules/using-enum-1_b.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/var-1_a.C9
-rw-r--r--gcc/testsuite/g++.dg/modules/var-1_b.C13
-rw-r--r--gcc/testsuite/g++.dg/modules/var-tpl-1_a.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/var-tpl-1_b.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/var-tpl-concept-1.h70
-rw-r--r--gcc/testsuite/g++.dg/modules/var-tpl-concept-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/var-tpl-concept-1_b.C10
-rw-r--r--gcc/testsuite/g++.dg/modules/virt-1_a.C25
-rw-r--r--gcc/testsuite/g++.dg/modules/virt-1_b.C23
-rw-r--r--gcc/testsuite/g++.dg/modules/virt-2_a.C27
-rw-r--r--gcc/testsuite/g++.dg/modules/virt-2_b.C28
-rw-r--r--gcc/testsuite/g++.dg/modules/virt-2_c.C16
-rw-r--r--gcc/testsuite/g++.dg/modules/vmort-1_a.C34
-rw-r--r--gcc/testsuite/g++.dg/modules/vmort-1_b.C17
-rw-r--r--gcc/testsuite/g++.dg/modules/vmort-2_a.C15
-rw-r--r--gcc/testsuite/g++.dg/modules/vmort-2_b.C20
-rw-r--r--gcc/testsuite/g++.dg/modules/vmort-2_c.C21
-rw-r--r--gcc/testsuite/g++.dg/modules/vtt-1_a.C36
-rw-r--r--gcc/testsuite/g++.dg/modules/vtt-1_b.C28
-rw-r--r--gcc/testsuite/g++.dg/modules/vtt-1_c.C19
-rw-r--r--gcc/testsuite/g++.dg/modules/vtt-2.h14
-rw-r--r--gcc/testsuite/g++.dg/modules/vtt-2_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/vtt-2_b.C7
-rw-r--r--gcc/testsuite/g++.dg/opt/const4.C3
-rw-r--r--gcc/testsuite/g++.dg/opt/pr64411.C1
-rw-r--r--gcc/testsuite/g++.dg/opt/pr97767.C10
-rw-r--r--gcc/testsuite/g++.dg/opt/pr98130.C25
-rw-r--r--gcc/testsuite/g++.dg/opt/pr98353.C17
-rw-r--r--gcc/testsuite/g++.dg/other/abstract1.C29
-rw-r--r--gcc/testsuite/g++.dg/other/abstract2.C57
-rw-r--r--gcc/testsuite/g++.dg/other/abstract4.C4
-rw-r--r--gcc/testsuite/g++.dg/other/abstract5.C2
-rw-r--r--gcc/testsuite/g++.dg/other/abstract8.C40
-rw-r--r--gcc/testsuite/g++.dg/other/i386-2.C2
-rw-r--r--gcc/testsuite/g++.dg/other/i386-3.C2
-rw-r--r--gcc/testsuite/g++.dg/other/pr88187.C2
-rw-r--r--gcc/testsuite/g++.dg/other/switch4.C3
-rw-r--r--gcc/testsuite/g++.dg/parse/attr3.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/attr4.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/cond4.C3
-rw-r--r--gcc/testsuite/g++.dg/parse/crash10.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/crash18.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash27.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash34.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash35.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash52.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash59.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash61.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/crash67.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/defarg17.C11
-rw-r--r--gcc/testsuite/g++.dg/parse/error14.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error56.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/invalid1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/parameter-declaration-1.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/parser-pr28152-2.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/parser-pr28152.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/pr58898.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/pr68722.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/pr96258.C4
-rw-r--r--gcc/testsuite/g++.dg/pch/pr98343.C6
-rw-r--r--gcc/testsuite/g++.dg/pch/pr98343.Hs18
-rw-r--r--gcc/testsuite/g++.dg/pr46852.C1
-rw-r--r--gcc/testsuite/g++.dg/pr46868.C1
-rw-r--r--gcc/testsuite/g++.dg/pr57878.C1
-rw-r--r--gcc/testsuite/g++.dg/pr65032.C1
-rw-r--r--gcc/testsuite/g++.dg/pr84279.C1
-rw-r--r--gcc/testsuite/g++.dg/pr93195a.C27
-rw-r--r--gcc/testsuite/g++.dg/pr93195b.C14
-rw-r--r--gcc/testsuite/g++.dg/pr97560.C45
-rw-r--r--gcc/testsuite/g++.dg/pr97609.C46
-rw-r--r--gcc/testsuite/g++.dg/pr98213.C24
-rw-r--r--gcc/testsuite/g++.dg/template/crash115.C1
-rw-r--r--gcc/testsuite/g++.dg/template/crash132.C6
-rw-r--r--gcc/testsuite/g++.dg/template/crash43.C1
-rw-r--r--gcc/testsuite/g++.dg/template/crash90.C3
-rw-r--r--gcc/testsuite/g++.dg/template/error-recovery1.C1
-rw-r--r--gcc/testsuite/g++.dg/template/error25.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error57.C2
-rw-r--r--gcc/testsuite/g++.dg/template/lookup16.C23
-rw-r--r--gcc/testsuite/g++.dg/template/pr98115.C4
-rw-r--r--gcc/testsuite/g++.dg/template/pr98116-2.C34
-rw-r--r--gcc/testsuite/g++.dg/template/pr98116.C34
-rw-r--r--gcc/testsuite/g++.dg/template/pr98297.C6
-rw-r--r--gcc/testsuite/g++.dg/template/scope5.C2
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae-dr657.C9
-rw-r--r--gcc/testsuite/g++.dg/torture/builtin-clear-padding-1.C31
-rw-r--r--gcc/testsuite/g++.dg/torture/builtin-clear-padding-2.C34
-rw-r--r--gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C24
-rw-r--r--gcc/testsuite/g++.dg/torture/pr81659.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr93347.C320
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/if-to-switch-1.C25
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr90883.C4
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr97736.C12
-rw-r--r--gcc/testsuite/g++.dg/ubsan/align-4.C31
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr61272.C4
-rw-r--r--gcc/testsuite/g++.dg/ubsan/vptr-18.C25
-rw-r--r--gcc/testsuite/g++.dg/vect/pr98064.cc25
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-11.cc61
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-12.cc36
-rw-r--r--gcc/testsuite/g++.dg/vect/slp-pr97636.cc83
-rw-r--r--gcc/testsuite/g++.dg/warn/Warray-bounds-14.C25
-rw-r--r--gcc/testsuite/g++.dg/warn/Warray-bounds-8.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C6
-rw-r--r--gcc/testsuite/g++.dg/warn/Wexceptions1.C9
-rw-r--r--gcc/testsuite/g++.dg/warn/Wexceptions2.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/Wexceptions3.C29
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C274
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-3.C38
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-4.C26
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C124
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s0
-rw-r--r--gcc/testsuite/g++.dg/warn/Winit-list4.C15
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C185
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C27
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-2.C249
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C212
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull5.C16
-rw-r--r--gcc/testsuite/g++.dg/warn/Wplacement-new-size-8.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wplacement-new-size.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/Wrange-loop-construct2.C212
-rw-r--r--gcc/testsuite/g++.dg/warn/Wsequence-point-4.C53
-rw-r--r--gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C18
-rw-r--r--gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Wtautological-compare3.C11
-rw-r--r--gcc/testsuite/g++.dg/warn/Wtype-limits5.C11
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse.C110
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse2.C24
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse3.C129
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse4.C74
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse5.C14
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse6.C24
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse7.C27
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse8.C11
-rw-r--r--gcc/testsuite/g++.dg/warn/Wvexing-parse9.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/delete-array-1.C6
-rw-r--r--gcc/testsuite/g++.dg/warn/mvp3.C30
-rw-r--r--gcc/testsuite/g++.dg/warn/pr98104.C20
-rw-r--r--gcc/testsuite/g++.dg/warn/pr98160.C30
-rw-r--r--gcc/testsuite/g++.dg/warn/pr98413.C23
-rw-r--r--gcc/testsuite/g++.dg/warn/uninit-1.C29
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/recurse.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/catch10.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/template4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arm4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/for2.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/crash31.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/decl3.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/delete2.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/local4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/using1.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash10.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash3.C2
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/pr98177-1.C10
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/pr98177-2.C10
-rw-r--r--gcc/testsuite/g++.target/i386/mv29.C79
-rw-r--r--gcc/testsuite/g++.target/msp430/data-attributes.C55
-rw-r--r--gcc/testsuite/g++.target/msp430/msp430.exp44
-rw-r--r--gcc/testsuite/g++.target/powerpc/pr97947.C12
-rw-r--r--gcc/testsuite/g++.target/riscv/pr97682.C160
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/asmgoto-2.c65
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/asmgoto-3.c89
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/asmgoto-4.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/asmgoto-5.c56
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c16
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58901-0.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58901-1.c21
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr96998.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr97205.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr97576.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr97578.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr97979.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr98087.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr98199.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr98229.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr98256.c9
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr98407.c10
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/index-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c63
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97421-1.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97421-2.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97421-3.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97695.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97764.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97836.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97888-1.c24
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr97888-2.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr98366.c13
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr98474.c30
-rw-r--r--gcc/testsuite/gcc.dg/20021029-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/20031223-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-43.c27
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-70.c18
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c279
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c57
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object.c273
-rw-r--r--gcc/testsuite/gcc.dg/Wmismatched-dealloc-2.c141
-rw-r--r--gcc/testsuite/gcc.dg/Wmismatched-dealloc-3.c265
-rw-r--r--gcc/testsuite/gcc.dg/Wmismatched-dealloc.c327
-rw-r--r--gcc/testsuite/gcc.dg/Wstring-compare-3.c106
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-11.c8
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-12.c7
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-17.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-27.c10
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-28.c33
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-29.c10
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-37.c26
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-44.s271
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-46.c10
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-47.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-54.c10
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-56.c163
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-57.c91
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-58.c260
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-59.c267
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-60.c72
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-61.c88
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-62.c363
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-63.c33
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-64.c74
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-7.c124
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c34
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-1.c40
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr97568.c29
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr97608.c17
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr97668.c27
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/setjmp-5.c13
-rw-r--r--gcc/testsuite/gcc.dg/array-quals-1.c20
-rw-r--r--gcc/testsuite/gcc.dg/attr-access-3.c21
-rw-r--r--gcc/testsuite/gcc.dg/attr-access-4.c8
-rw-r--r--gcc/testsuite/gcc.dg/attr-access-5.c16
-rw-r--r--gcc/testsuite/gcc.dg/attr-malloc.c75
-rw-r--r--gcc/testsuite/gcc.dg/binary-constants-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/binary-constants-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c43
-rw-r--r--gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c87
-rw-r--r--gcc/testsuite/gcc.dg/builtin-clear-padding-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/builtin-clear-padding-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/c11-binary-constants-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/c11-binary-constants-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/c11-bool-1.c50
-rw-r--r--gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c52
-rw-r--r--gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c52
-rw-r--r--gcc/testsuite/gcc.dg/c11-float-4.c25
-rw-r--r--gcc/testsuite/gcc.dg/c11-float-5.c35
-rw-r--r--gcc/testsuite/gcc.dg/c11-float-6.c17
-rw-r--r--gcc/testsuite/gcc.dg/c11-float-dfp-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/c11-labels-1.c15
-rw-r--r--gcc/testsuite/gcc.dg/c11-labels-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/c11-labels-3.c15
-rw-r--r--gcc/testsuite/gcc.dg/c11-parm-omit-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/c11-parm-omit-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/c11-parm-omit-3.c5
-rw-r--r--gcc/testsuite/gcc.dg/c11-parm-omit-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c12
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c7
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c12
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-nodiscard-1.c62
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c42
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-nodiscard-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-nodiscard-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-syntax-3.c7
-rw-r--r--gcc/testsuite/gcc.dg/c2x-attr-syntax-5.c5
-rw-r--r--gcc/testsuite/gcc.dg/c2x-binary-constants-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/c2x-binary-constants-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/c2x-binary-constants-3.c9
-rw-r--r--gcc/testsuite/gcc.dg/c2x-bool-1.c50
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-10.c33
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-2.c23
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-3.c27
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-4.c33
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-5.c32
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-6.c49
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-7.c49
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-8.c7
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-9.c7
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c26
-rw-r--r--gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c10
-rw-r--r--gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c41
-rw-r--r--gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c25
-rw-r--r--gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c18
-rw-r--r--gcc/testsuite/gcc.dg/c2x-labels-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/c2x-labels-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/c2x-labels-3.c38
-rw-r--r--gcc/testsuite/gcc.dg/c2x-parm-omit-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/c2x-parm-omit-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/c2x-parm-omit-3.c23
-rw-r--r--gcc/testsuite/gcc.dg/c2x-parm-omit-4.c5
-rw-r--r--gcc/testsuite/gcc.dg/c99-bool-4.c46
-rw-r--r--gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c52
-rw-r--r--gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c52
-rw-r--r--gcc/testsuite/gcc.dg/cond-constqual-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/line10.c5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/line9.c5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pr97989-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pr97989-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/cr-decimal-dig-3.c14
-rw-r--r--gcc/testsuite/gcc.dg/darwin-minversion-link.c5
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c13
-rw-r--r--gcc/testsuite/gcc.dg/decl-9.c3
-rw-r--r--gcc/testsuite/gcc.dg/dfp/builtin-snan-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/dfp/builtin-snan-2.c44
-rw-r--r--gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c25
-rw-r--r--gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c25
-rw-r--r--gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c28
-rw-r--r--gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c45
-rw-r--r--gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c45
-rw-r--r--gcc/testsuite/gcc.dg/fold-isfinite-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isfinite-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isinf-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isinf-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isnan-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isnan-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c22
-rw-r--r--gcc/testsuite/gcc.dg/free-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/free-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-error-8.c9
-rw-r--r--gcc/testsuite/gcc.dg/goacc/pr98183.c15
-rw-r--r--gcc/testsuite/gcc.dg/goacc/tile-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/gomp/barrier-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-simd-5.c3
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-variant-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr98183.c15
-rw-r--r--gcc/testsuite/gcc.dg/guality/guality.exp2
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr59776.c2
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr98219-1.c49
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr98219-2.c63
-rw-r--r--gcc/testsuite/gcc.dg/hwasan/hwasan.exp36
-rw-r--r--gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c53
-rw-r--r--gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c27
-rw-r--r--gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c28
-rw-r--r--gcc/testsuite/gcc.dg/ipa/modref-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/label-compound-stmt-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/loop-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/lto/modref-2_0.c27
-rw-r--r--gcc/testsuite/gcc.dg/lto/modref-3_0.c17
-rw-r--r--gcc/testsuite/gcc.dg/lto/modref-3_1.c13
-rw-r--r--gcc/testsuite/gcc.dg/lto/modref-4_0.c17
-rw-r--r--gcc/testsuite/gcc.dg/lto/modref-4_1.c13
-rw-r--r--gcc/testsuite/gcc.dg/lvalue-11.c40
-rw-r--r--gcc/testsuite/gcc.dg/memchr-3.c25
-rw-r--r--gcc/testsuite/gcc.dg/nextafter-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/nextafter-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/no-strict-overflow-4.c5
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/pr79758.c2
-rw-r--r--gcc/testsuite/gcc.dg/parse-decl-after-label.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c436
-rw-r--r--gcc/testsuite/gcc.dg/plugin/gil-1.c90
-rw-r--r--gcc/testsuite/gcc.dg/plugin/gil.h32
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp2
-rw-r--r--gcc/testsuite/gcc.dg/pr25376.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr46309-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr83072.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr85811.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr91029.c48
-rw-r--r--gcc/testsuite/gcc.dg/pr91441.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr95853.c59
-rw-r--r--gcc/testsuite/gcc.dg/pr96239.c54
-rw-r--r--gcc/testsuite/gcc.dg/pr96260.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr96307.c25
-rw-r--r--gcc/testsuite/gcc.dg/pr96708-negative.c48
-rw-r--r--gcc/testsuite/gcc.dg/pr96708-positive.c48
-rw-r--r--gcc/testsuite/gcc.dg/pr97459-1.c54
-rw-r--r--gcc/testsuite/gcc.dg/pr97459-2.c57
-rw-r--r--gcc/testsuite/gcc.dg/pr97459-3.c54
-rw-r--r--gcc/testsuite/gcc.dg/pr97459-4.c57
-rw-r--r--gcc/testsuite/gcc.dg/pr97459-5.c56
-rw-r--r--gcc/testsuite/gcc.dg/pr97459-6.c62
-rw-r--r--gcc/testsuite/gcc.dg/pr97505.c23
-rw-r--r--gcc/testsuite/gcc.dg/pr97515.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr97534.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr97539.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr97555.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr97567-2.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr97567.c34
-rw-r--r--gcc/testsuite/gcc.dg/pr97579.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr97596.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr97721.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr97725.c28
-rw-r--r--gcc/testsuite/gcc.dg/pr97737.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr97741.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr97750.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr97806.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr97830.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr97860.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr97897.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr97953.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr97954.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr97955.c7
-rw-r--r--gcc/testsuite/gcc.dg/pr97979.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr97981.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr98099.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr98147.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr98190.c33
-rw-r--r--gcc/testsuite/gcc.dg/pr98211.c51
-rw-r--r--gcc/testsuite/gcc.dg/pr98271.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr98272.c22
-rw-r--r--gcc/testsuite/gcc.dg/pragma-diag-6.c9
-rw-r--r--gcc/testsuite/gcc.dg/predict-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/profile-info-section.c22
-rw-r--r--gcc/testsuite/gcc.dg/qual-assign-7.c18
-rw-r--r--gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c2
-rw-r--r--gcc/testsuite/gcc.dg/self-right-shift.c12
-rw-r--r--gcc/testsuite/gcc.dg/sin_cos.c41
-rw-r--r--gcc/testsuite/gcc.dg/sms-12.c1
-rw-r--r--gcc/testsuite/gcc.dg/strncmp-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/system-binary-constants-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/float16-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h36
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr71816.c4
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr97559-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr97559-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr97812.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr97901.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr98117.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr98191.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr98219-1.c45
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr98219-2.c59
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr98235.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr98289.c52
-rw-r--r--gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-fre-5.c8
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-fre-6.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/pr97461.c64
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/stringop-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/asm-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/asm-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c76
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/evrp20.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/evrp21.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/evrp22.c43
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-10.c44
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c36
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c42
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c27
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/modref-5.c27
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr23401.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr27810.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr56719.c33
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr71077.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr78655.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c68
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c98
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr94785.c36
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr94802-1.c68
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96094.c34
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96232-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96272.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96480.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96685-1.c52
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96685-2.c40
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96685-3.c43
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96789.c61
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr96929.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr97849.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr97964.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c52
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c41
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr98084.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr98094.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr98182.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c54
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/switch-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/switch-4.c25
-rw-r--r--gcc/testsuite/gcc.dg/tsan/atomic-fence.c11
-rw-r--r--gcc/testsuite/gcc.dg/typeof-2.c20
-rw-r--r--gcc/testsuite/gcc.dg/unused-9.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-41.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-43.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-54.c23
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-55.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-56.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-57.c38
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-58.c24
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-59.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-60.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-61.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-62.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-63.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-64.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-65.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-66.c32
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-67.c16
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-68.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-69.c46
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-70.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97615.c23
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97626.c34
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97633.c27
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97650.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97706.c61
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97732.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr97746.c20
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr98137.c27
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-byte.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-int.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-long.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-short.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-byte.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-int.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-long.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-short.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/complex-add-pattern-template.c60
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/complex-add-template.c79
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/complex-operations-run.c103
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/complex-operations.c358
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/complex.exp20
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-double.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-float.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-half-float.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-double.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-float.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-half-float.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-double.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-float.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-half-float.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-double.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-float.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-half-float.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-byte.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-int.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-long.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-short.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-byte.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-int.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-long.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-short.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr65947-8.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr91750.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97457.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97558-2.c54
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97558.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97678.c32
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97693.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97730.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97753.c10
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97760.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97769.c32
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97835.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97838.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr97929.c10
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr98048.c14
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr98069.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-11b.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-21.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-46.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-49.c39
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-perm-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-perm-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-perm-6.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-perm-7.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-reduc-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-reduc-7.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/tree-vect.h2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-35-big-array.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-35.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-epilogues.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-live-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c52
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c63
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c8
-rw-r--r--gcc/testsuite/gcc.misc-tests/godump-1.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/aapcs64/abitest-2.h2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/aapcs64/abitest.h2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/arm-neon-ref.h4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get-be.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vect_copy_lane_1.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_1.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_2.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_1.c227
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_2.c48
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bfcvt-compile.c40
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_1.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_2.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_2.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_2.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_2.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2q_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3q_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4q_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrn_high_n.c195
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrun_high_n.c197
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrn_high_n.c193
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrun_high_n.c143
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2_lane_bf16_indices_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2q_lane_bf16_indices_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3_lane_bf16_indices_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3q_lane_bf16_indices_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4_lane_bf16_indices_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4q_lane_bf16_indices_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c88
-rw-r--r--gcc/testsuite/gcc.target/aarch64/memset-q-reg.c81
-rw-r--r--gcc/testsuite/gcc.target/aarch64/narrow_high-intrinsics.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr97535.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr97638.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_bf16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_bf16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f16.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f32.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f64.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s32.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s64.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u32.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u64.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extw_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_u64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_s8.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_u8.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr97546.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr98037.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/undef_1.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cmp_1.c57
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cmp_2.c72
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1_run.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3_run.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_1.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_unary_1.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/dup_lane_2.c331
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/dup_lane_3.c90
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/ext_4.c353
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_7.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr97092.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr98177-1.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr98177-2.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/rev_2.c177
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/revhw_1.c127
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c127
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_8.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/trn1_2.c403
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/trn2_2.c403
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/uzp1_2.c375
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/uzp2_2.c375
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vcond_11.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vcond_11_run.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/zip1_2.c403
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/zip2_2.c403
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f32.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f64.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtx_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s16.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s64.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s8.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/recpe_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rsqrte_u32.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/bcax_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vect-widen-add.c92
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vect-widen-lshift.c62
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vect-widen-sub.c92
-rw-r--r--gcc/testsuite/gcc.target/aarch64/with-tune-config.c7
-rw-r--r--gcc/testsuite/gcc.target/aarch64/with-tune-march.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/with-tune-mcpu.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/with-tune-mtune.c7
-rw-r--r--gcc/testsuite/gcc.target/arc/loop-3.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/pmpyd.c15
-rw-r--r--gcc/testsuite/gcc.target/arc/tmac-1.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/uncached-9.c39
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-hard.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-softfp.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-nofp-flag-softfp.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-hard.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-softfp.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nofp-nomve-flag-softfp.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-hard.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-softfp.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-hard.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/data-rel-1.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/data-rel-2.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/data-rel-3.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/lob2.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/lob3.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/lob4.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/lob5.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/mve/intrinsics/pr97327.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/pr44788.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/pr52006.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/pr59858.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/pr91816.c64
-rw-r--r--gcc/testsuite/gcc.target/arm/pr97528.c28
-rw-r--r--gcc/testsuite/gcc.target/arm/pr97872.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m0.c176
-rw-r--r--gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m23.c172
-rw-r--r--gcc/testsuite/gcc.target/arm/pure-code/pr96767.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/pure-code/pr96770.c21
-rw-r--r--gcc/testsuite/gcc.target/arm/require-pic-register-loc.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/bf16_vldn_1.c48
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vand.c63
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vbic.c65
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-veor.c61
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vmvn.c35
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vneg.c49
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vorr.c64
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vld1_bf16_1.c29
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_1.c22
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_indices_1.c19
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vld1q_lane_bf16_indices_1.c19
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vldn_lane_bf16_1.c79
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vmmla_1.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vst1_bf16_1.c29
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_1.c22
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vstn_lane_bf16_1.c73
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vstq1_lane_bf16_indices_1.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/tlscall.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/vect-half-floats.c14
-rw-r--r--gcc/testsuite/gcc.target/h8300/add-2.c5
-rw-r--r--gcc/testsuite/gcc.target/h8300/add-3.c5
-rw-r--r--gcc/testsuite/gcc.target/h8300/add.c118
-rw-r--r--gcc/testsuite/gcc.target/h8300/sub-2.c5
-rw-r--r--gcc/testsuite/gcc.target/h8300/sub-3.c5
-rw-r--r--gcc/testsuite/gcc.target/h8300/sub.c118
-rw-r--r--gcc/testsuite/gcc.target/i386/amxbf16-asmintel-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/amxint8-asmintel-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/amxtile-asmintel-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vnni-1.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vnni-2.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vnni-3.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vnni-4.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vnni-5.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vnni-6.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vpdpbusd-2.c74
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vpdpbusds-2.c74
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vpdpwssd-2.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vpdpwssds-2.c70
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-pr98461.c54
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vec-set-1.c49
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vec-set-2.c50
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bitalg-pr97770-1.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-pr96906-1.c68
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vec-set-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vec-set-2.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu8-1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vandnpd-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vandnps-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vandpd-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vandps-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vorpd-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vorps-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vxorpd-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vxorps-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vec-set-2.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmovapd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmovaps-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmovdqa32-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmovdqa64-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vec-set-2.c55
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vmovapd-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vmovaps-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa32-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa64-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vnni-1a.c (renamed from gcc/testsuite/gcc.target/i386/avx512vl-vnni-1.c)0
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vnni-1b.c69
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vnni-2.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vnni-3.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vnnivl-builtin.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-1.c63
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-2.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avxvnni-builtin.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/builtin_thread_pointer.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentryname1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentryname2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentryname3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-256-maccXX.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-256-msubXX.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-256-nmaccXX.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-256-nmsubXX.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-maccXX.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-msubXX.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-nmaccXX.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-nmsubXX.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/funcspec-56.inc12
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/keylocker-loadiwkey.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/ms_hook_prologue.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr31799.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr45352-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr47602.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55151.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55458.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr56348.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57097.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr65753.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr65915.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66334.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66819-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67265.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78102.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79804.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81481.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr83994.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88178.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92180.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92469.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-avx2-2.c192
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-avx512bw-2.c280
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92658-sse4-2.c148
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94440-1.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94440-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95151-1.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95151-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95151-3.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95151-4.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95458-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95458-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95866-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96226.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96793-1.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96793-2.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96793.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96906-1.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97140.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97282.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97521.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97540.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97642-1.c41
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97642-2.c77
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97777.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97873-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97873-2.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97873-3.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97873.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97887.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr97950.c153
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98063.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98079.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98086.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98100.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98161.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98169.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98212.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98264.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98274.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98289.c54
-rw-r--r--gcc/testsuite/gcc.target/i386/returninst1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/returninst2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/returninst3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-13.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-14.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-22.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-23.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-pr98461.c50
-rw-r--r--gcc/testsuite/gcc.target/i386/uintr-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/uintr-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/uintr-4.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/uintr-5.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/vnni_inline_error.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v2-msabi.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v2-other.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v2.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v3-msabi.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v3-other.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v3.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v4-msabi.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v4-other.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-64-v4.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-needed-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-needed-2.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/x86-needed-3.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-haddX.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-hadduX.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-hsubX.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-24.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-25.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-26.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-27.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-28.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-29.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-30.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-31.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-32.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c15
-rw-r--r--gcc/testsuite/gcc.target/microblaze/others/strings1.c5
-rw-r--r--gcc/testsuite/gcc.target/msp430/data-attributes-2.c13
-rw-r--r--gcc/testsuite/gcc.target/msp430/pr78818-auto-warn.c4
-rw-r--r--gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c42
-rw-r--r--gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c38
-rw-r--r--gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c43
-rw-r--r--gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c38
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-consts.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bcd-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bcd-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bcd-4.c521
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bswap64-4.c6
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cfuged-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cntlzdm-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cnttzdm-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cprophard.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dg-future-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dimode_off.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-hw3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-mix-2.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-mix-3.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-mix.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-type-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-type-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p9.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p9.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p7.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p8.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-insert-int-p9.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-char.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-int.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-longlong.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-short.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-char.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-int.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-longlong.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-short.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/le-altivec-consts.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/localentry-1.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/lsbb-runnable.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mma-alignment.c41
-rwxr-xr-xgcc/testsuite/gcc.target/powerpc/mma-double-test.c8
-rwxr-xr-xgcc/testsuite/gcc.target/powerpc/mma-single-test.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p10-arch31.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p10-identify.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pdep-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pextd-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr64505.c265
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr67789.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr79439-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr79439-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83629.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr84112.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr93122.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr94740.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96506-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96506-2.c38
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96506.c66
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96787-2.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96933-1.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96933-2.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96933-3.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96933-4.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96933-run.h56
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr96933.h50
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr97267.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/r2_shrink-wrap.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sad-vectorize-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sad-vectorize-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sad-vectorize-3.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/sad-vectorize-4.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/signbit-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/signbit-2.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/signbit-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/swaps-p8-22.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdu-0.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdu-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdu-2.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdu-3.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdu-4.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdu-5.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdub-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsdub-2.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsduh-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsduh-2.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsduw-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vadsduw-2.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-blend-runnable.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-cfuged-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-clrl-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-clrl-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-clrr-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-clrr-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-cntlzm-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-cnttzm-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-insert-word-runnable.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-pdep-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-permute-ext-runnable.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-pext-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-replace-word-runnable.c22
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-shift-double-runnable.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-splati-runnable.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-16.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-17.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-18.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-19.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-20.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-21.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-22.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-23.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-5.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril_p-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril_p-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril_p-5.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-stril_p-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-16.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-17.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-18.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-19.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-20.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-21.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-22.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-23.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-5.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir_p-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir_p-3.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir_p-5.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-strir_p-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vslv-0.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vslv-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsrv-0.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsrv-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-char.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-int.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-longlong.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-short.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-char.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-int.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-longlong.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-short.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx_mask-count-runnable.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx_mask-expand-runnable.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx_mask-extract-runnable.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx_mask-move-runnable.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/xxgenpc-runnable.c5
-rw-r--r--gcc/testsuite/gcc.target/pru/halt.c9
-rw-r--r--gcc/testsuite/gcc.target/pru/lmbd.c14
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-10.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-11.c5
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-7.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-8.c5
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-9.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-10.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-11.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-12.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-13.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-14.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-15.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-16.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-17.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-6.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-8.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-9.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/interrupt-3.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/interrupt-4.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr91441.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr96260.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/builtin-constant-p-threading.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/float_t-1.c15
-rw-r--r--gcc/testsuite/gcc.target/s390/float_t-2.c13
-rw-r--r--gcc/testsuite/gcc.target/s390/load-imm64-1.c14
-rw-r--r--gcc/testsuite/gcc.target/s390/load-imm64-2.c14
-rw-r--r--gcc/testsuite/gcc.target/s390/pr97497.c36
-rw-r--r--gcc/testsuite/gcc.target/s390/s390.exp17
-rw-r--r--gcc/testsuite/gcc.target/s390/stack-clash-1.c4
-rw-r--r--gcc/testsuite/gcc.target/s390/stack-clash-2.c4
-rw-r--r--gcc/testsuite/gcc.target/s390/stack-clash-3.c4
-rw-r--r--gcc/testsuite/gcc.target/s390/stack-clash-4.c10
-rw-r--r--gcc/testsuite/gcc.target/s390/stack-clash-5.c10
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-callee-abi-scan.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-run.c5
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-scan.c13
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-copysign.c22
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-fprx2-constant.c11
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-double.c19
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-float.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-i16.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-i32.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-i64.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-i8.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-u16.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-u32.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-u64.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-from-u8.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-double.c19
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-float.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-i16.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-i32.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-i64.c22
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-i8.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-u16.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-u32.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-u64.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-to-u8.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-vec-duplicate.c13
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wf.h60
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfaxb.c18
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0001.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0111.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1011.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1101.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfdxb.c18
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfixb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-0111.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1011.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1101.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wflcxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wflpxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-2.c24
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-3.c14
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-disabled.c8
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb-disabled.c8
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfmxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb-disabled.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb-disabled.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfsqxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb-1.c22
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb-1.c15
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c5
-rw-r--r--gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c2
-rw-r--r--gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c5
-rw-r--r--gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/overflow-6.c20
-rw-r--r--gcc/testsuite/gcc.target/vax/bbcci.c20
-rw-r--r--gcc/testsuite/gcc.target/vax/bbssi.c20
-rw-r--r--gcc/testsuite/gcc.target/vax/bswapdi-1.c2
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-adddf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-addhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-addqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-addsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-addsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-andhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-andqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-andsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-ashlsi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-ashrsi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-divdf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-divhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-divqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-divsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-divsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-extendhisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-extendqisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-extvsi.c38
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-extzvsi.c39
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfhi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfqi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfsi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfhi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfqi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfsi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-floatsisf.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-insvsi.c46
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-iorhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-iorqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-iorsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-mova.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-movdf.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-movhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-movqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-movsf.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-movsi.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-muldf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-mulhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-mulqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-nothi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-notqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-notsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-rotlsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-rotrsi.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-subdf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-subhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-subqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-subsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-subsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-truncdfsf.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-trunchiqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsihi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsiqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendhisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqihi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-adddf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-addhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-addqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-addsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-addsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-andhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-andqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-andsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-ashlsi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-ashrsi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-divdf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-divhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-divqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-divsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-divsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-extendhisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-extendqisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-extvsi.c38
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-extzvsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfhi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfqi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfsi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfhi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfqi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfsi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-floatsisf.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-insvsi.c46
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-iorhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-iorqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-iorsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-movdf.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-movhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-movqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-movsf.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-movsi.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-muldf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-mulhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-mulqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-mulsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-mulsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-nothi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-notqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-notsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-rotlsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-rotrsi.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-subdf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-subhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-subqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-subsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-subsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-truncdfsf.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-xorhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-xorqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-le-xorsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-leu-subhi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-leu-subqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-leu-subsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-adddf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-addhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-addqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-addsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-addsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-andhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-andqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-andsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-ashlsi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-ashrsi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-divdf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-divhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-divqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-divsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-divsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-extendhisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-extendqisi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-extvsi.c38
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-extzvsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfhi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfqi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfsi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfhi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfqi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfsi.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-floatsisf.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-insvsi.c46
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-iorhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-iorqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-iorsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-movdf.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-movhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-movqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-movsf.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-movsi.c28
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-muldf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-mulhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-mulqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-nothi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-notqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-notsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-rotlsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-rotrsi.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-subdf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-subhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-subqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-subsf.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-subsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-truncdfsf.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-xorhi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-xorqi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-lt-xorsi.c29
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-ltu-subhi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-ltu-subqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-ltu-subsi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-xx-addsi.c36
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-xx-insvsi.c53
-rw-r--r--gcc/testsuite/gcc.target/vax/cmpelim-xxu-subsi.c40
-rw-r--r--gcc/testsuite/gcc.target/vax/compare-add-zero.c27
-rw-r--r--gcc/testsuite/gcc.target/vax/compare-mov-zero.c24
-rw-r--r--gcc/testsuite/gcc.target/vax/cpymem.c23
-rw-r--r--gcc/testsuite/gcc.target/vax/ctzhi.c20
-rw-r--r--gcc/testsuite/gcc.target/vax/ctzqi.c20
-rw-r--r--gcc/testsuite/gcc.target/vax/ctzsi.c15
-rw-r--r--gcc/testsuite/gcc.target/vax/ffshi.c24
-rw-r--r--gcc/testsuite/gcc.target/vax/ffsqi.c24
-rw-r--r--gcc/testsuite/gcc.target/vax/ffssi.c19
-rw-r--r--gcc/testsuite/gcc.target/vax/movmem.c23
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-andhi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-andqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-andsi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-cmpvsi.c36
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-cmpzvsi.c36
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-0.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-1.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-0.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-1.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-0.c32
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-1.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ffshi.c26
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ffsqi.c26
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-eq-ffssi.c27
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-le-andhi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-le-andqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-le-andsi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-le-cmpvsi.c36
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-le-cmpzvsi.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-leu-cmpvsi.c40
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-leu-cmpzvsi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-lt-andhi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-lt-andqi.c33
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-lt-andsi.c30
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-lt-cmpvsi.c36
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-lt-cmpzvsi.c34
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpvsi.c40
-rw-r--r--gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpzvsi.c31
-rw-r--r--gcc/testsuite/gcc.target/vax/pr56875.c11
-rw-r--r--gcc/testsuite/gcc.target/vax/push.c27
-rw-r--r--gcc/testsuite/gcc.target/vax/vax.exp2
-rw-r--r--gcc/testsuite/gcc.target/xtensa/bswap.c14
-rw-r--r--gcc/testsuite/gcc.target/xtensa/pr98285.c54
-rw-r--r--gcc/testsuite/gcc.target/xtensa/shifts.c31
-rw-r--r--gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S13
-rw-r--r--gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S9
-rw-r--r--gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S10
-rw-r--r--gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S50
-rw-r--r--gcc/testsuite/gcc.test-framework/test-framework.exp3
-rw-r--r--gcc/testsuite/gdc.dg/debug/debug.exp28
-rw-r--r--gcc/testsuite/gdc.dg/debug/dwarf2/dwarf2.exp31
-rw-r--r--gcc/testsuite/gdc.dg/debug/dwarf2/imports/pr98067.d3
-rw-r--r--gcc/testsuite/gdc.dg/debug/dwarf2/langdw2.d7
-rw-r--r--gcc/testsuite/gdc.dg/debug/dwarf2/langdw3.d6
-rw-r--r--gcc/testsuite/gdc.dg/debug/dwarf2/pr98067.d6
-rw-r--r--gcc/testsuite/gdc.dg/debug/trivial.d6
-rw-r--r--gcc/testsuite/gdc.dg/intrinsics.d92
-rw-r--r--gcc/testsuite/gdc.dg/pr92216.d4
-rw-r--r--gcc/testsuite/gdc.dg/pr98277.d13
-rw-r--r--gcc/testsuite/gdc.dg/pr98427.d23
-rw-r--r--gcc/testsuite/gdc.dg/torture/pr97843.d37
-rw-r--r--gcc/testsuite/gdc.dg/torture/pr97889.d29
-rw-r--r--gcc/testsuite/gdc.test/compilable/callconv.d20
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test21299/func.d8
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d8
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d96
-rw-r--r--gcc/testsuite/gdc.test/compilable/test17419.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21299a.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21299b.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21299c.d5
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21299d.d27
-rw-r--r--gcc/testsuite/gdc.test/compilable/testInference.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail12485.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail18970.d37
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test21164a.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test21164b.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test21164c.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test21164d.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21164.d13
-rw-r--r--gcc/testsuite/gdc.test/runnable/dhry.d927
-rw-r--r--gcc/testsuite/gdc.test/runnable/imports/testmangle.d66
-rw-r--r--gcc/testsuite/gdc.test/runnable/link6574.d10
-rw-r--r--gcc/testsuite/gdc.test/runnable/mangle.d82
-rw-r--r--gcc/testsuite/gdc.test/runnable/nested.d9
-rw-r--r--gcc/testsuite/gdc.test/runnable/template4.d31
-rw-r--r--gcc/testsuite/gdc.test/runnable/template9.d13
-rw-r--r--gcc/testsuite/gdc.test/runnable/test4.d12
-rw-r--r--gcc/testsuite/gdc.test/runnable/testconst.d3
-rw-r--r--gcc/testsuite/gfortran.dg/analyzer/pr97668.f26
-rw-r--r--gcc/testsuite/gfortran.dg/attr_deprecated.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/class_allocate_25.f9058
-rw-r--r--gcc/testsuite/gfortran.dg/class_assign_4.f90183
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/alloc_comp_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/coverage.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/data_inquiry_ref.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/deferred_character_36.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/dependency_60.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/entry_23.f57
-rw-r--r--gcc/testsuite/gfortran.dg/finalize_37.f9080
-rw-r--r--gcc/testsuite/gfortran.dg/forall_19.f9032
-rw-r--r--gcc/testsuite/gfortran.dg/goacc-gomp/atomic.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/goacc-gomp/fixed-1.f81
-rw-r--r--gcc/testsuite/gfortran.dg/goacc-gomp/free-1.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/goacc-gomp/goacc-gomp.exp37
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/atomic.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/classify-kernels.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/classify-parallel.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/classify-serial.f9531
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/clause-locations.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/fixed-5.f30
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/kernels-decompose-1.f9589
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/kernels-decompose-2.f95150
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/kernels-tree.f955
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-3.f9524
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/loop-5.f95357
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/loop-6.f9574
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-kernels.f90300
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-parallel.f90404
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-routine.f9088
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-kernels.f90389
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-parallel.f90499
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-routine.f90119
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions-warn.f90674
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-reductions.f90540
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/pr92793-1.f90135
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/sentinel-free-form.f957
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/specification-part.f90100
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic-2.f9070
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/atomic.f9087
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-target-4.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/map-2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/reduction4.f90143
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/reduction5.f9059
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/reduction6.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/reduction7.f909
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/requires-4.f906
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/requires-9.f904
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-1.f90213
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-2.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-3.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-4.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-5.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-6.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/scan-7.f9060
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f908
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-1.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-10.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-11.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-12.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-13.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-14.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-15.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-16.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-17.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-18.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-19.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-2.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-20.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-21.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-22.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-23.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-24.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-25.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-26.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-27.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-28.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-29.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-3.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-30.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-31.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-32.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-33.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-34.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-35.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-36.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-37.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-38.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-39.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-4.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-40.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-41.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-42.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-43.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-44.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-45.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-46.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-47.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-48.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-49.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-5.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-50.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-51.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-52.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-53.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-54.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-55.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-56.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-57.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-58.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-6.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-7.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-8.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/workshare-reduction-9.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/guality/guality.exp2
-rw-r--r--gcc/testsuite/gfortran.dg/ipcp-array-2.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/pr48958.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/pr85796.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr93685_1.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/pr93685_2.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/pr95342.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/pr97768_1.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/pr97768_2.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/pr98016.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/pr98017.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/pr98284.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/select_rank_5.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/structure_constructor_17.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f0359
-rw-r--r--gcc/testsuite/gfortran.dg/value_8.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/vect/O3-bb-slp-1.f28
-rw-r--r--gcc/testsuite/gfortran.dg/vect/O3-bb-slp-2.f40
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr97761.f9032
-rw-r--r--gcc/testsuite/gnat.dg/bias2.adb33
-rw-r--r--gcc/testsuite/gnat.dg/debug15.adb23
-rw-r--r--gcc/testsuite/gnat.dg/interface6.adb2
-rw-r--r--gcc/testsuite/gnat.dg/modular6.adb15
-rw-r--r--gcc/testsuite/gnat.dg/multfixed.adb3
-rw-r--r--gcc/testsuite/gnat.dg/not_null.adb4
-rw-r--r--gcc/testsuite/gnat.dg/opt39.adb1
-rw-r--r--gcc/testsuite/gnat.dg/opt88.adb52
-rw-r--r--gcc/testsuite/gnat.dg/opt89.adb18
-rw-r--r--gcc/testsuite/gnat.dg/opt90a.adb16
-rw-r--r--gcc/testsuite/gnat.dg/opt90a_pkg.ads15
-rw-r--r--gcc/testsuite/gnat.dg/opt90b.adb16
-rw-r--r--gcc/testsuite/gnat.dg/opt90b_pkg.ads16
-rw-r--r--gcc/testsuite/gnat.dg/opt90c.adb16
-rw-r--r--gcc/testsuite/gnat.dg/opt90c_pkg.ads16
-rw-r--r--gcc/testsuite/gnat.dg/opt90d.adb16
-rw-r--r--gcc/testsuite/gnat.dg/opt90d_pkg.ads16
-rw-r--r--gcc/testsuite/gnat.dg/opt90e.adb16
-rw-r--r--gcc/testsuite/gnat.dg/opt90e_pkg.ads16
-rw-r--r--gcc/testsuite/gnat.dg/opt91.adb11
-rw-r--r--gcc/testsuite/gnat.dg/opt91.ads10
-rw-r--r--gcc/testsuite/gnat.dg/opt91_pkg.adb12
-rw-r--r--gcc/testsuite/gnat.dg/opt91_pkg.ads19
-rw-r--r--gcc/testsuite/gnat.dg/protected_func.adb4
-rw-r--r--gcc/testsuite/gnat.dg/shift1.adb15
-rw-r--r--gcc/testsuite/gnat.dg/sin_cos.adb14
-rw-r--r--gcc/testsuite/gnat.dg/sin_cos.ads4
-rw-r--r--gcc/testsuite/gnat.dg/warn14.adb2
-rw-r--r--gcc/testsuite/go.test/go-test.exp220
-rw-r--r--gcc/testsuite/go.test/test/alias.go2
-rw-r--r--gcc/testsuite/go.test/test/alias1.go2
-rw-r--r--gcc/testsuite/go.test/test/alias2.go104
-rw-r--r--gcc/testsuite/go.test/test/alias3.dir/a.go42
-rw-r--r--gcc/testsuite/go.test/test/alias3.dir/b.go26
-rw-r--r--gcc/testsuite/go.test/test/alias3.dir/c.go25
-rw-r--r--gcc/testsuite/go.test/test/alias3.go7
-rw-r--r--gcc/testsuite/go.test/test/append.go25
-rw-r--r--gcc/testsuite/go.test/test/assign.go12
-rw-r--r--gcc/testsuite/go.test/test/bench/garbage/Makefile2
-rw-r--r--gcc/testsuite/go.test/test/bench/garbage/parser.go4
-rw-r--r--gcc/testsuite/go.test/test/bench/garbage/stats.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/garbage/tree.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/garbage/tree2.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/binarytree_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/fannkuch_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/fasta_test.go10
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/gob_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/gzip_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/http_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/json_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/jsondata_test.go4
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/mandel_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/parserdata_test.go6
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/revcomp_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/template_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.go129
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.txt8
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/binary-tree.c164
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/binary-tree.go92
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/binary-tree.txt8
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/chameneosredux.c330
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/chameneosredux.go180
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/chameneosredux.txt29
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.go224
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.txt31
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fannkuch.c134
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fannkuch.go122
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fannkuch.txt31
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fasta-1000.out171
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fasta.c219
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fasta.go205
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/fasta.txt171
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.go157
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.txt27
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.c228
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.go140
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.txt27
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/mandelbrot.c91
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/mandelbrot.go95
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/mandelbrot.txtbin5011 -> 0 bytes
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/meteor-contest.c626
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/meteor-contest.go656
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/meteor-contest.txt24
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/nbody.c170
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/nbody.go177
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/nbody.txt2
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/pidigits.c123
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/pidigits.go135
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/pidigits.txt3
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.go124
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.txt13
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/regex-dna.c154
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/regex-dna.go106
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/regex-dna.txt13
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/reverse-complement.c100
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/reverse-complement.go105
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/reverse-complement.txt171
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/spectral-norm-parallel.go111
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/spectral-norm.c82
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/spectral-norm.go93
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/spectral-norm.txt1
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/threadring.c103
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/threadring.go71
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/threadring.txt1
-rw-r--r--gcc/testsuite/go.test/test/bench/shootout/timing.log1254
-rwxr-xr-xgcc/testsuite/go.test/test/bench/shootout/timing.sh219
-rw-r--r--gcc/testsuite/go.test/test/blank1.go6
-rw-r--r--gcc/testsuite/go.test/test/bombad.go2
-rw-r--r--gcc/testsuite/go.test/test/bounds.go108
-rw-r--r--gcc/testsuite/go.test/test/bugs/bug395.go25
-rw-r--r--gcc/testsuite/go.test/test/bugs/placeholder2
-rw-r--r--gcc/testsuite/go.test/test/chan/doubleselect.go1
-rw-r--r--gcc/testsuite/go.test/test/chan/fifo.go1
-rw-r--r--gcc/testsuite/go.test/test/chan/perm.go30
-rw-r--r--gcc/testsuite/go.test/test/chan/powser1.go326
-rw-r--r--gcc/testsuite/go.test/test/chan/powser2.go412
-rw-r--r--gcc/testsuite/go.test/test/chan/select2.go2
-rw-r--r--gcc/testsuite/go.test/test/chan/select3.go18
-rw-r--r--gcc/testsuite/go.test/test/chan/select5.go10
-rw-r--r--gcc/testsuite/go.test/test/chan/select6.go2
-rw-r--r--gcc/testsuite/go.test/test/chan/select7.go2
-rw-r--r--gcc/testsuite/go.test/test/chan/select8.go55
-rw-r--r--gcc/testsuite/go.test/test/chan/sendstmt.go6
-rw-r--r--gcc/testsuite/go.test/test/chancap.go44
-rw-r--r--gcc/testsuite/go.test/test/cmp.go61
-rw-r--r--gcc/testsuite/go.test/test/cmp6.go13
-rw-r--r--gcc/testsuite/go.test/test/cmplx.go14
-rw-r--r--gcc/testsuite/go.test/test/cmplxdivide.c87
-rw-r--r--gcc/testsuite/go.test/test/cmplxdivide.go27
-rw-r--r--gcc/testsuite/go.test/test/cmplxdivide1.go6511
-rw-r--r--gcc/testsuite/go.test/test/complit1.go25
-rw-r--r--gcc/testsuite/go.test/test/compos.go2
-rw-r--r--gcc/testsuite/go.test/test/const.go83
-rw-r--r--gcc/testsuite/go.test/test/const1.go6
-rw-r--r--gcc/testsuite/go.test/test/const4.go2
-rw-r--r--gcc/testsuite/go.test/test/const5.go6
-rw-r--r--gcc/testsuite/go.test/test/const6.go2
-rw-r--r--gcc/testsuite/go.test/test/convert1.go2
-rw-r--r--gcc/testsuite/go.test/test/convlit.go11
-rw-r--r--gcc/testsuite/go.test/test/ddd.go2
-rw-r--r--gcc/testsuite/go.test/test/ddd1.go18
-rw-r--r--gcc/testsuite/go.test/test/ddd2.dir/ddd2.go2
-rw-r--r--gcc/testsuite/go.test/test/ddd2.dir/ddd3.go2
-rw-r--r--gcc/testsuite/go.test/test/ddd2.go2
-rw-r--r--gcc/testsuite/go.test/test/deferprint.go4
-rw-r--r--gcc/testsuite/go.test/test/divide.go2
-rw-r--r--gcc/testsuite/go.test/test/divmod.go4
-rw-r--r--gcc/testsuite/go.test/test/eof.go2
-rw-r--r--gcc/testsuite/go.test/test/eof1.go2
-rwxr-xr-xgcc/testsuite/go.test/test/errchk147
-rw-r--r--gcc/testsuite/go.test/test/escape2.go1139
-rw-r--r--gcc/testsuite/go.test/test/escape3.go2
-rw-r--r--gcc/testsuite/go.test/test/escape4.go28
-rw-r--r--gcc/testsuite/go.test/test/escape5.go160
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug0.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug0.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug0.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug108.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug121.go1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug0.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug13343.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug1515.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug160.dir/x.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug160.dir/y.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug169.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug173.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug176.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug19403.go134
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug195.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug203.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug206.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug214.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug215.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug216.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug217.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug218.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug221.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug227.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug228.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug229.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug230.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug231.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug232.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug233.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug234.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug235.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug236.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug237.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug243.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug245.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug247.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go106
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug3.go102
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug248.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug249.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug250.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug251.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug252.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug253.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug254.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug255.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug256.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug257.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug258.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug259.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug261.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug264.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug265.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug266.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug269.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug271.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug272.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug273.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug274.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug275.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug278.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug279.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug280.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug281.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug283.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug285.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug286.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug287.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug288.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug289.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug290.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug291.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug292.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug293.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug294.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug295.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug296.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug297.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug298.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug299.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug300.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug301.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug302.dir/main.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug302.dir/p.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug302.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug303.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug304.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug305.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug308.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug309.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug311.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug312.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug313.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug313.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug313.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug317.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug319.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug320.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug321.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug323.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug325.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug326.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug327.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug328.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug329.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug330.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug331.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug332.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug333.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug334.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug335.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug335.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug335.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug336.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug337.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug338.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug339.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug340.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug341.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug342.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug343.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug344.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug345.dir/io.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug345.dir/main.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug345.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug346.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug347.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug348.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug349.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug350.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug351.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug352.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug353.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug354.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug355.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug356.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug357.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug358.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug361.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug362.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug363.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug365.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug366.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug368.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug369.dir/main.go55
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug369.dir/pkg.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug369.go73
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug370.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug371.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug372.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug373.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug374.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug375.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug376.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug378.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug379.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug380.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug381.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug382.dir/pkg.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug383.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug384.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug385_32.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug385_64.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug386.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug387.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug388.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug389.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug391.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug392.dir/one.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg3.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug393.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug394.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug396.dir/one.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug396.dir/two.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug397.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug398.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug399.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug401.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug402.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug403.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug404.dir/one.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug404.dir/two.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug406.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug407.dir/one.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug407.dir/two.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug409.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug410.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug411.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug412.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug413.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug415.dir/p.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug415.dir/prog.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug415.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug416.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug424.dir/lib.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug424.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug425.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug427.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug428.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug429.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug435.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug437.dir/one.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug437.dir/two.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug437.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug441.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug442.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug443.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug444.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug445.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug447.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug448.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug450.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug452.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug453.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug454.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug455.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug456.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug457.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug458.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug459.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug460.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug461.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug462.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug463.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug464.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug465.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug466.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug467.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug468.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug470.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug471.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug473.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug474.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug475.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug476.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug477.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug478.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug478.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug478.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug479.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug479.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug479.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug480.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug480.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug480.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug481.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug482.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug483.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug484.go78
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug485.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug486.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug487.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug488.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug488.dir/b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug488.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug489.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug490.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug491.go110
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug492.dir/a.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug492.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug492.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug493.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug494.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug495.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug496.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug497.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug498.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug499.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug500.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug501.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug502.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug503.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug504.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug504.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug504.dir/c.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug504.dir/main.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug504.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug505.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug506.dir/a.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug506.dir/main.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug506.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug507.dir/a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug507.dir/b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug507.dir/c.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug507.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug508.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug509.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug510.dir/a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug510.dir/b.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug510.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61204.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61244.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61246.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61248.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61253.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61254.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61255.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61258.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61264.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61265.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc61273.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc65755.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/a.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/b.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc67968.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc78763.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc80226.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/gcc89321.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10047.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/a.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/b.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10066.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10135.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/a.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/c.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10219.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10253.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10284.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10320.go55
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10332.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10353.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10407.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10441.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10486.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10607.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10607a.go81
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10654.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/other.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/test.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10700.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10925.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10958.go95
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10975.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue10977.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p_test.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11053.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11053.out3
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11256.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11286.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11326b.go48
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11354.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11359.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11361.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11362.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11369.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11370.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11371.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11590.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11610.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11614.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11674.go40
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11699.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11750.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11771.go64
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11790.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11945.go71
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue11987.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12006.go174
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12108.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12133.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12226.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12347.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12411.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12413.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12536.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12577.go66
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12588.go88
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12621.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/p.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/q.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12677.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue12686.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue1304.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13160.go70
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13162.go82
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13169.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13171.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13248.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13261.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13262.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13263.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13266.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13268.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13274.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13337.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13365.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13415.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13471.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13480.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13485.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13539.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13684.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/burnin.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/main.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13777.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13799.go190
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13821.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue13821b.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14006.go67
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14010.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14136.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/a.go47
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/main.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14164.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/a.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14331.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14405.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14520.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14540.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14553.go45
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14591.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14636.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14646.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14651.go71
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14652.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14725.go57
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14729.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue14988.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15002.go132
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15013.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15039.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15042.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/exp.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/main.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15071.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15084.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15141.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15175.go66
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15252.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15277.go40
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15303.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15329.go79
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15439.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/a.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/b.go3
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15470.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/b.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/c.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15514.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15528.go131
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/a.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/c.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15548.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15550.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/a.go40
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/b.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15572.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15585.go45
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15602.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15604.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_386.s8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_amd64.s8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_decl.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/main.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/a.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/b.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15646.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15722.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15733.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/a.go61
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15838.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15895.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15898.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15902.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/b.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15920.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15926.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15961.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15988.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15992.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue15992.out4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16016.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16037_run.go70
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16095.go104
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16130.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a1.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a2.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/b.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/c.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16193.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16249.go58
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16306.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/a.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16317.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16331.go48
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16369.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16428.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16439.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16515.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/b.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/issue16616.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16616.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16733.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16741.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16760.go42
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16804.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16948.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16949.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue16985.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17005.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17111.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17194.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17270.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17328.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17381.go54
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17551.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17588.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17596.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17631.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17640.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17645.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17710.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17752.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17758.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue17918.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18089.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18092.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18231.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18393.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18410.go40
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/other.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/test.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18419.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18595.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18636.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18640.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18655.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18661.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18725.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18808.go63
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18906.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18915.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue18994.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19012.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/main.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19028.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19040.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19056.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19078.go42
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19084.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19113.go108
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19137.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19182.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19201.go52
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19217.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19275.go72
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19323.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19359.go91
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19482.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/div_arm.s12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/main.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19507.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19515.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/a.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/b.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19548.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19555.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19632.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19658.go99
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19667.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19671.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19678.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19679.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19696.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19699b.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19705.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19710.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19743.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19764.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19783.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19799.go71
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19880.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19911.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue19977.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20029.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20097.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20145.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20185.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20227.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20333.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20335.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20415.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20529.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20530.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20602.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/p.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/q.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/r.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20682.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20739.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20749.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20780.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20811.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20812.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20813.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue20923.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21048.go72
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/b.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/main.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21120.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21221.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21253.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21256.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21273.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21317.go56
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21576.go63
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21655.go62
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21770.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21808.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21808.out3
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21879.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21879.out2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21882.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21887.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21887.out2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21963.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21979.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue21988.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22063.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22076.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22083.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22198.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22200.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22200b.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22305.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22326.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22326.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22327.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22429.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22458.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22605.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22660.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22683.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22683.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22781.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22794.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22822.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22881.go117
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22904.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22921.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/b.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/main.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22941.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/a.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue22962.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23093.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23116.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23179.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23188.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23298.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23305.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23311.dir/main.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23311.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23414.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23489.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23504.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23521.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23522.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23545.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23546.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23586.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23719.go42
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23732.go42
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23734.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23780.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23781.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23812.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23823.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue23912.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24120.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24173.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24187.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24419.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24449.go62
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24470.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24488.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24503.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24547.go46
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24760.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24763.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24799.go58
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/main.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24801.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24817.go64
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24937.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue24939.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25006.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25101.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25322.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25322.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25507.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25516.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25727.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25741.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25776.go99
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25897a.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25897b.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25958.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/p.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/q.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue25984.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26024.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26043.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26097.go47
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26105.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26116.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26120.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue2615.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26153.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26248.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26335.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26340.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/a.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26341.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26407.go58
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26411.go92
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26416.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26438.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26495.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26616.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue26855.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27143.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27232.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27267.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27278.go63
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27289.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27356.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27695.go62
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27695b.go64
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27695c.go65
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27718.go102
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27829.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27938.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue27961.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28055.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28058.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28078.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28079a.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28079b.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28079c.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28268.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28390.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28390.out2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28430.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28445.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28450.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28601.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28616.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28688.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue28797.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29013a.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29013b.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29190.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29215.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29218.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29220.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29264.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29304.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29312.go70
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29329.go107
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29350.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29362.go42
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29362b.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29389.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29402.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29562.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/b.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/main.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29610.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29735.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29855.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29870.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29870b.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue29943.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30041.go63
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30061.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30085.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30087.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30116.go112
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30116.out558
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30116u.go112
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30116u.out340
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30243.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30430.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30476.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30566a.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30566b.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30606.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30606b.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/a.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30659.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30679.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30709.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30709.out4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/b.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/main.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30862.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30898.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/a.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30907.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30956.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30956.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue30977.go52
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31010.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31060.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/c.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/main.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31252.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31412a.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31412b.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31419.go58
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31573.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/b.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31637.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31777.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31782.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31782.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue31987.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32175.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32175.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32288.go48
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32347.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32454.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32560.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/b.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/main.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32595.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32680.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32680.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32680b.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32723.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/a.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32778.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/b.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/c.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/main.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32901.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/a.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32922.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue32959.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/b.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/c.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/d.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33013.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/a.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/b.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33020.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/b.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33020a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33062.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/a.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33158.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/a.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/b.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/c.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33219.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33275.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33275_run.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33308.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33355.go147
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33386.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33438.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33460.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33555.go81
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33724.go45
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/a.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33739.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/a.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/b.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33866.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue33903.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34123.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34395.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34503.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34520.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/a.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/b.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34577.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue34968.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35027.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35073.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35157.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35291.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35576.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35576.out1
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35586.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35652.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue35739.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/a.go3
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/b.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36085.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36259.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36437.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36516.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue36705.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3705.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue37246.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue37716.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue37753.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3783.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue37975.go54
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38093.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38117.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38125.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38356.go54
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38359.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38690.go65
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38745.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38746.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38905.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue38916.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3924.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3925.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue39292.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue39459.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue39505.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue39505b.go183
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue39541.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue39651.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40152.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/a.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/main.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40252.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40367.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40629.go69
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40746.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4085a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4085b.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40917.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue40954.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4097.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4099.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41247.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41440.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41500.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41575.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4162.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4167.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41680.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41736.go105
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41780.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue41872.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42032.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42058a.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42058b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42075.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42076.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4215.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4232.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4251.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4252.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42568.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42587.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42703.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42727.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42784.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42790.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4283.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue42876.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue43099.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue43111.go70
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue43112.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4313.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4316.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4323.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4348.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4353.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4359.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4365.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4396a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4396b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4399.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4405.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4429.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4448.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4452.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4458.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4463.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4468.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4470.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4495.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517c.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517d.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4518.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4529.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4545.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4562.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4585.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4614.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4618.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4620.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4654.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4663.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4667.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4734.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4748.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4752.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4776.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4785.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4909a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5002.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5056.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5172.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5231.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5358.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5373.go71
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5581.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5698.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5704.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5793.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5809.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5820.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5841.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5856.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5963.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6004.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6036.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6055.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6131.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6140.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6247.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6269.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p0.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p1.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p2.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6295.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6298.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6402.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6403.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6406.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/a.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/b.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/main.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703a.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703b.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703c.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703d.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703e.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703f.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703g.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703h.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703i.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703j.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703k.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703l.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703m.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703n.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703o.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703p.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703q.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703r.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703s.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703t.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703u.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703v.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703w.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703x.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703y.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6703z.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6772.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6847.go85
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6866.go80
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6889.go111
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6899.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6902.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6964.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue6977.go40
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/a.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7023.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7044.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7050.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7083.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7129.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7150.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7153.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7223.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7272.go48
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7310.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7316.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7346.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7366.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7405.go51
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7419.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7538a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7538b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7547.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7550.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7590.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/a.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7648.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7740.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7742.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7746.go133
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7760.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7794.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7863.go60
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7867.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7884.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7921.go57
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7944.go40
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7995.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x1.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x2.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7995b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7996.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7997.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue7998.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8004.go59
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8011.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8017.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8028.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8036.go45
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8039.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8042.go66
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8047.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8047b.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8048.go107
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8060.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8073.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8074.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8076.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8079.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8132.go32
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8139.go50
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8154.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8155.go48
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8158.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8183.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/a.go3
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/b.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8280.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8311.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8325.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8336.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8347.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8385.go42
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8438.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8440.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8475.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8501.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8613.go38
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8620.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8745.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8761.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8836.go24
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue887.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8947.go53
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue8961.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9006.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9017.go57
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9036.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9076.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9083.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9110.go91
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9321.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9355.dir/a.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9355.go63
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9370.go127
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9432.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9521.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/a.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/b.go43
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9537.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9604.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9604b.go180
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9608.dir/issue9608.go82
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9608.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9634.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9691.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9731.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9738.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9862.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue9862_run.go27
-rw-r--r--gcc/testsuite/go.test/test/func6.go4
-rw-r--r--gcc/testsuite/go.test/test/func7.go4
-rw-r--r--gcc/testsuite/go.test/test/func8.go8
-rw-r--r--gcc/testsuite/go.test/test/funcdup.go2
-rw-r--r--gcc/testsuite/go.test/test/funcdup2.go2
-rw-r--r--gcc/testsuite/go.test/test/gc2.go5
-rw-r--r--gcc/testsuite/go.test/test/golden.out24
-rw-r--r--gcc/testsuite/go.test/test/goprint.go24
-rw-r--r--gcc/testsuite/go.test/test/goto.go90
-rw-r--r--gcc/testsuite/go.test/test/helloworld.go2
-rw-r--r--gcc/testsuite/go.test/test/import2.dir/import2.go2
-rw-r--r--gcc/testsuite/go.test/test/import2.dir/import3.go2
-rw-r--r--gcc/testsuite/go.test/test/import2.go2
-rw-r--r--gcc/testsuite/go.test/test/import5.go36
-rw-r--r--gcc/testsuite/go.test/test/index.go6
-rw-r--r--gcc/testsuite/go.test/test/index0.go2
-rw-r--r--gcc/testsuite/go.test/test/index1.go2
-rw-r--r--gcc/testsuite/go.test/test/index2.go2
-rw-r--r--gcc/testsuite/go.test/test/init.go4
-rw-r--r--gcc/testsuite/go.test/test/init1.go28
-rw-r--r--gcc/testsuite/go.test/test/initializerr.go1
-rw-r--r--gcc/testsuite/go.test/test/interface/embed2.go23
-rw-r--r--gcc/testsuite/go.test/test/interface/explicit.go8
-rw-r--r--gcc/testsuite/go.test/test/interface/noeq.go2
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go2
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go2
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive1.go2
-rw-r--r--gcc/testsuite/go.test/test/ken/cplx0.go2
-rw-r--r--gcc/testsuite/go.test/test/ken/embed.go2
-rw-r--r--gcc/testsuite/go.test/test/ken/modconst.go2
-rw-r--r--gcc/testsuite/go.test/test/ken/string.go2
-rw-r--r--gcc/testsuite/go.test/test/label.go9
-rw-r--r--gcc/testsuite/go.test/test/label1.go50
-rw-r--r--gcc/testsuite/go.test/test/linkx.go32
-rw-r--r--gcc/testsuite/go.test/test/map.go2
-rw-r--r--gcc/testsuite/go.test/test/map1.go12
-rw-r--r--gcc/testsuite/go.test/test/mapnan.go56
-rw-r--r--gcc/testsuite/go.test/test/method1.go18
-rw-r--r--gcc/testsuite/go.test/test/method2.go8
-rw-r--r--gcc/testsuite/go.test/test/method4.dir/prog.go9
-rw-r--r--gcc/testsuite/go.test/test/method5.go2
-rw-r--r--gcc/testsuite/go.test/test/named.go2
-rw-r--r--gcc/testsuite/go.test/test/named1.go10
-rw-r--r--gcc/testsuite/go.test/test/nilcheck.go105
-rw-r--r--gcc/testsuite/go.test/test/nilptr.go6
-rw-r--r--gcc/testsuite/go.test/test/nilptr2.go2
-rw-r--r--gcc/testsuite/go.test/test/nilptr3.go200
-rw-r--r--gcc/testsuite/go.test/test/nul1.go7
-rw-r--r--gcc/testsuite/go.test/test/peano.go8
-rw-r--r--gcc/testsuite/go.test/test/printbig.go2
-rw-r--r--gcc/testsuite/go.test/test/range.go186
-rw-r--r--gcc/testsuite/go.test/test/recover.go94
-rw-r--r--gcc/testsuite/go.test/test/recover1.go2
-rw-r--r--gcc/testsuite/go.test/test/recover2.go4
-rw-r--r--gcc/testsuite/go.test/test/recover3.go2
-rw-r--r--gcc/testsuite/go.test/test/rename.go2
-rw-r--r--gcc/testsuite/go.test/test/rename1.go6
-rw-r--r--gcc/testsuite/go.test/test/reorder.go39
-rw-r--r--gcc/testsuite/go.test/test/reorder2.go177
-rw-r--r--gcc/testsuite/go.test/test/return.go2
-rw-r--r--gcc/testsuite/go.test/test/rotate.go2
-rw-r--r--gcc/testsuite/go.test/test/rotate0.go2
-rw-r--r--gcc/testsuite/go.test/test/rotate1.go2
-rw-r--r--gcc/testsuite/go.test/test/rotate2.go2
-rw-r--r--gcc/testsuite/go.test/test/rotate3.go2
-rwxr-xr-xgcc/testsuite/go.test/test/run138
-rw-r--r--gcc/testsuite/go.test/test/run.go1324
-rw-r--r--gcc/testsuite/go.test/test/rune.go2
-rw-r--r--gcc/testsuite/go.test/test/runtime.go2
-rw-r--r--gcc/testsuite/go.test/test/safe/main.go14
-rw-r--r--gcc/testsuite/go.test/test/safe/nousesafe.go8
-rw-r--r--gcc/testsuite/go.test/test/safe/pkg.go16
-rw-r--r--gcc/testsuite/go.test/test/safe/usesafe.go8
-rw-r--r--gcc/testsuite/go.test/test/shift1.go18
-rw-r--r--gcc/testsuite/go.test/test/shift2.go2
-rw-r--r--gcc/testsuite/go.test/test/sigchld.go4
-rw-r--r--gcc/testsuite/go.test/test/sinit.go90
-rw-r--r--gcc/testsuite/go.test/test/sizeof.go2
-rw-r--r--gcc/testsuite/go.test/test/slice3err.go2
-rw-r--r--gcc/testsuite/go.test/test/stress/maps.go4
-rw-r--r--gcc/testsuite/go.test/test/stress/parsego.go4
-rw-r--r--gcc/testsuite/go.test/test/stress/runstress.go2
-rw-r--r--gcc/testsuite/go.test/test/struct0.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/chan.go8
-rw-r--r--gcc/testsuite/go.test/test/syntax/chan1.go6
-rw-r--r--gcc/testsuite/go.test/test/syntax/composite.go4
-rw-r--r--gcc/testsuite/go.test/test/syntax/else.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/forvar.go10
-rw-r--r--gcc/testsuite/go.test/test/syntax/if.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/import.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/interface.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi1.go4
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi2.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi3.go4
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi4.go6
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi5.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi6.go8
-rw-r--r--gcc/testsuite/go.test/test/syntax/semi7.go4
-rw-r--r--gcc/testsuite/go.test/test/syntax/topexpr.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/typesw.go4
-rw-r--r--gcc/testsuite/go.test/test/syntax/vareq.go2
-rw-r--r--gcc/testsuite/go.test/test/syntax/vareq1.go4
-rw-r--r--gcc/testsuite/go.test/test/testlib170
-rw-r--r--gcc/testsuite/go.test/test/torture.go7
-rw-r--r--gcc/testsuite/go.test/test/typecheck.go12
-rw-r--r--gcc/testsuite/go.test/test/typeswitch2.go16
-rw-r--r--gcc/testsuite/go.test/test/typeswitch3.go31
-rw-r--r--gcc/testsuite/go.test/test/undef.go2
-rw-r--r--gcc/testsuite/go.test/test/varerr.go2
-rw-r--r--gcc/testsuite/go.test/test/zerodivide.go9
-rw-r--r--gcc/testsuite/jit.dg/jit.exp31
-rw-r--r--gcc/testsuite/jit.dg/test-asm.c492
-rw-r--r--gcc/testsuite/jit.dg/test-asm.cc453
-rw-r--r--gcc/testsuite/jit.dg/test-debug-strings.c20
-rw-r--r--gcc/testsuite/lib/asan-dg.exp37
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp4
-rw-r--r--gcc/testsuite/lib/hwasan-dg.exp167
-rw-r--r--gcc/testsuite/lib/options.exp5
-rw-r--r--gcc/testsuite/lib/profopt.exp1
-rw-r--r--gcc/testsuite/lib/prune.exp10
-rw-r--r--gcc/testsuite/lib/scanasm.exp202
-rw-r--r--gcc/testsuite/lib/target-supports.exp336
-rw-r--r--gcc/testsuite/lib/tsan-dg.exp6
-rw-r--r--gcc/testsuite/lib/ubsan-dg.exp6
-rw-r--r--gcc/testsuite/obj-c++.dg/SEL-typedef.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/class-attribute-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/nsobject-01.mm66
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/nullability-00.mm20
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/proto-attribute-3.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/proto-attribute-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm11
-rw-r--r--gcc/testsuite/obj-c++.dg/attributes/unused-parameter-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/bad-receiver-type.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/bitfield-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/bitfield-5.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/class-protocol-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-10.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-5.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-6.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-7.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/comp-types-8.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/demangle-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/demangle-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/duplicate-class-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/encode-1-next.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/encode-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/enhanced-proto-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-5.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/extern-c-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/fobjc-std-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-ivar.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-method.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-objc_msg_lookup.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-object.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-property.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-protocol.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-resolve-method.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/invalid-method-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/ivar-invalid-type-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/ivar-problem-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/lto/lto.exp16
-rw-r--r--gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/method-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-12.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-18.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-19.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-20.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-5.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-8.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-9.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/method-namespace-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/plugin/diagnostic-test-expressions-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/pr23709.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/pragma-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/private-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/private-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-1.mm13
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-29.mm8
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-4.mm56
-rw-r--r--gcc/testsuite/obj-c++.dg/property/nullability-00.mm21
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-2.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-6.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property.exp4
-rw-r--r--gcc/testsuite/obj-c++.dg/proto-lossage-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/proto-lossage-5.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/proto-qual-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/protocol-inheritance-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/protocol-inheritance-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/protocol-optional-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/root-class-00.mm10
-rw-r--r--gcc/testsuite/obj-c++.dg/selector-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/selector-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/selector-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/selector-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/strings/strings.exp4
-rw-r--r--gcc/testsuite/obj-c++.dg/stubify-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/stubify-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/super-dealloc-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/super-dealloc-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/sync-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-10.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-2.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-7.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-8.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-9.mm3
-rw-r--r--gcc/testsuite/obj-c++.dg/template-4.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/template-7.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/template-8.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/dg-torture.exp4
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/strings.exp4
-rw-r--r--gcc/testsuite/obj-c++.dg/try-catch-12.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/try-catch-13.mm1
-rw-r--r--gcc/testsuite/objc.dg/SEL-typedef.m7
-rw-r--r--gcc/testsuite/objc.dg/anon-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/class-attribute-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/class-attribute-2.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/class-attribute-3.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-deprecated-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-deprecated-2.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-deprecated-3.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-format-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-nonnull-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-noreturn-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/method-sentinel-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/nsobject-01.m67
-rw-r--r--gcc/testsuite/objc.dg/attributes/nullability-00.m20
-rw-r--r--gcc/testsuite/objc.dg/attributes/objc-exception-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/parameter-attribute-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/parameter-attribute-2.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/proto-attribute-1.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/proto-attribute-2.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/proto-attribute-3.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/proto-attribute-4.m1
-rw-r--r--gcc/testsuite/objc.dg/attributes/root-class-01.m11
-rw-r--r--gcc/testsuite/objc.dg/bitfield-2.m1
-rw-r--r--gcc/testsuite/objc.dg/break-in-ifstmt.m1
-rw-r--r--gcc/testsuite/objc.dg/class-1.m4
-rw-r--r--gcc/testsuite/objc.dg/class-extension-1.m1
-rw-r--r--gcc/testsuite/objc.dg/class-extension-2.m1
-rw-r--r--gcc/testsuite/objc.dg/class-extension-3.m1
-rw-r--r--gcc/testsuite/objc.dg/class-extension-4.m1
-rw-r--r--gcc/testsuite/objc.dg/class-protocol-1.m1
-rw-r--r--gcc/testsuite/objc.dg/comp-types-7.m1
-rw-r--r--gcc/testsuite/objc.dg/demangle-1.m1
-rw-r--r--gcc/testsuite/objc.dg/duplicate-class-1.m1
-rw-r--r--gcc/testsuite/objc.dg/encode-6-next.m1
-rw-r--r--gcc/testsuite/objc.dg/encode-6.m1
-rw-r--r--gcc/testsuite/objc.dg/enhanced-proto-2.m1
-rw-r--r--gcc/testsuite/objc.dg/exceptions-1.m1
-rw-r--r--gcc/testsuite/objc.dg/exceptions-3.m1
-rw-r--r--gcc/testsuite/objc.dg/exceptions-4.m1
-rw-r--r--gcc/testsuite/objc.dg/exceptions-5.m1
-rw-r--r--gcc/testsuite/objc.dg/fobjc-std-1.m5
-rw-r--r--gcc/testsuite/objc.dg/foreach-2.m1
-rw-r--r--gcc/testsuite/objc.dg/foreach-4.m1
-rw-r--r--gcc/testsuite/objc.dg/foreach-5.m1
-rw-r--r--gcc/testsuite/objc.dg/fsyntax-only.m3
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-class-meta.m4
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-class.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-ivar.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-method.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-objc.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-objc_msg_lookup.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-object.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-property.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-protocol.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-resolve-method.m1
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-sel.m1
-rw-r--r--gcc/testsuite/objc.dg/incomplete-type-1.m3
-rw-r--r--gcc/testsuite/objc.dg/instancetype-0.m3
-rw-r--r--gcc/testsuite/objc.dg/invalid-method-2.m3
-rw-r--r--gcc/testsuite/objc.dg/ivar-invalid-type-1.m3
-rw-r--r--gcc/testsuite/objc.dg/ivar-problem-1.m6
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-1.m3
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-2.m3
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-4.m3
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-1.m1
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-2.m2
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-3.m2
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-4.m2
-rw-r--r--gcc/testsuite/objc.dg/local-decl-1.m1
-rw-r--r--gcc/testsuite/objc.dg/lto/lto.exp16
-rw-r--r--gcc/testsuite/objc.dg/lto/trivial-1_0.m4
-rw-r--r--gcc/testsuite/objc.dg/method-1.m1
-rw-r--r--gcc/testsuite/objc.dg/method-12.m1
-rw-r--r--gcc/testsuite/objc.dg/method-13.m1
-rw-r--r--gcc/testsuite/objc.dg/method-14.m1
-rw-r--r--gcc/testsuite/objc.dg/missing-proto-3.m3
-rw-r--r--gcc/testsuite/objc.dg/next-runtime-1.m1
-rw-r--r--gcc/testsuite/objc.dg/objc-foreach-1.m1
-rw-r--r--gcc/testsuite/objc.dg/objc-foreach-2.m1
-rw-r--r--gcc/testsuite/objc.dg/objc-foreach-3.m1
-rw-r--r--gcc/testsuite/objc.dg/objc-nofilename-1.m1
-rw-r--r--gcc/testsuite/objc.dg/param-1.m1
-rw-r--r--gcc/testsuite/objc.dg/pch/pch.exp4
-rw-r--r--gcc/testsuite/objc.dg/plugin/diagnostic-test-expressions-1.m2
-rw-r--r--gcc/testsuite/objc.dg/pr23214.m2
-rw-r--r--gcc/testsuite/objc.dg/pr23709.m1
-rw-r--r--gcc/testsuite/objc.dg/private-1.m1
-rw-r--r--gcc/testsuite/objc.dg/private-2.m1
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-1.m12
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-29.m7
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-4.m50
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-5.m2
-rw-r--r--gcc/testsuite/objc.dg/property/nullability-00.m21
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-2.m2
-rw-r--r--gcc/testsuite/objc.dg/property/property.exp4
-rw-r--r--gcc/testsuite/objc.dg/proto-hier-1.m1
-rw-r--r--gcc/testsuite/objc.dg/proto-hier-2.m1
-rw-r--r--gcc/testsuite/objc.dg/proto-lossage-1.m1
-rw-r--r--gcc/testsuite/objc.dg/proto-lossage-5.m1
-rw-r--r--gcc/testsuite/objc.dg/proto-qual-1.m1
-rw-r--r--gcc/testsuite/objc.dg/protocol-inheritance-1.m1
-rw-r--r--gcc/testsuite/objc.dg/protocol-inheritance-2.m1
-rw-r--r--gcc/testsuite/objc.dg/protocol-optional-1.m1
-rw-r--r--gcc/testsuite/objc.dg/root-class-00.m10
-rw-r--r--gcc/testsuite/objc.dg/selector-1.m1
-rw-r--r--gcc/testsuite/objc.dg/selector-2.m1
-rw-r--r--gcc/testsuite/objc.dg/selector-3.m1
-rw-r--r--gcc/testsuite/objc.dg/selector-4.m1
-rw-r--r--gcc/testsuite/objc.dg/shadow-1.m1
-rw-r--r--gcc/testsuite/objc.dg/shadow-2.m1
-rw-r--r--gcc/testsuite/objc.dg/special/load-category-1.m1
-rw-r--r--gcc/testsuite/objc.dg/special/load-category-2.m1
-rw-r--r--gcc/testsuite/objc.dg/special/load-category-3.m1
-rw-r--r--gcc/testsuite/objc.dg/special/special.exp8
-rw-r--r--gcc/testsuite/objc.dg/special/unclaimed-category-1.h1
-rw-r--r--gcc/testsuite/objc.dg/special/unclaimed-category-1.m1
-rw-r--r--gcc/testsuite/objc.dg/stabs-1.m1
-rw-r--r--gcc/testsuite/objc.dg/strings/strings.exp4
-rw-r--r--gcc/testsuite/objc.dg/stubify-1.m1
-rw-r--r--gcc/testsuite/objc.dg/stubify-2.m1
-rw-r--r--gcc/testsuite/objc.dg/super-class-2.m1
-rw-r--r--gcc/testsuite/objc.dg/super-dealloc-1.m1
-rw-r--r--gcc/testsuite/objc.dg/super-dealloc-2.m1
-rw-r--r--gcc/testsuite/objc.dg/sync-3.m1
-rw-r--r--gcc/testsuite/objc.dg/threedotthree-abi-1.m1
-rw-r--r--gcc/testsuite/objc.dg/torture/dg-torture.exp4
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/strings.exp4
-rw-r--r--gcc/testsuite/objc.dg/try-catch-11.m1
-rw-r--r--gcc/testsuite/objc.dg/try-catch-12.m1
-rw-r--r--gcc/testsuite/objc.dg/type-size-2.m1
-rw-r--r--gcc/testsuite/objc.dg/type-size-3.m1
-rw-r--r--gcc/testsuite/objc.dg/type-size-4.m1
-rw-r--r--gcc/testsuite/objc.dg/type-size-5.m1
-rw-r--r--gcc/testsuite/objc.dg/undeclared-selector.m1
-rw-r--r--gcc/testsuite/objc.dg/volatile-1.m3
-rw-r--r--gcc/timevar.def5
-rw-r--r--gcc/toplev.c192
-rw-r--r--gcc/trans-mem.c2
-rw-r--r--gcc/tree-cfg.c23
-rw-r--r--gcc/tree-cfgcleanup.h1
-rw-r--r--gcc/tree-complex.c5
-rw-r--r--gcc/tree-core.h16
-rw-r--r--gcc/tree-data-ref.c425
-rw-r--r--gcc/tree-diagnostic-path.cc217
-rw-r--r--gcc/tree-emutls.c2
-rw-r--r--gcc/tree-if-conv.c13
-rw-r--r--gcc/tree-inline.c71
-rw-r--r--gcc/tree-into-ssa.c4
-rw-r--r--gcc/tree-nested.c32
-rw-r--r--gcc/tree-pass.h9
-rw-r--r--gcc/tree-pretty-print.c28
-rw-r--r--gcc/tree-scalar-evolution.c18
-rw-r--r--gcc/tree-ssa-alias-compare.h43
-rw-r--r--gcc/tree-ssa-alias.c951
-rw-r--r--gcc/tree-ssa-alias.h2
-rw-r--r--gcc/tree-ssa-ccp.c36
-rw-r--r--gcc/tree-ssa-dce.c103
-rw-r--r--gcc/tree-ssa-live.c34
-rw-r--r--gcc/tree-ssa-loop-im.c56
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c3
-rw-r--r--gcc/tree-ssa-loop-manip.h2
-rw-r--r--gcc/tree-ssa-loop.c2
-rw-r--r--gcc/tree-ssa-math-opts.c444
-rw-r--r--gcc/tree-ssa-phiopt.c61
-rw-r--r--gcc/tree-ssa-pre.c742
-rw-r--r--gcc/tree-ssa-propagate.c60
-rw-r--r--gcc/tree-ssa-reassoc.c160
-rw-r--r--gcc/tree-ssa-reassoc.h48
-rw-r--r--gcc/tree-ssa-sccvn.c87
-rw-r--r--gcc/tree-ssa-sccvn.h12
-rw-r--r--gcc/tree-ssa-sink.c14
-rw-r--r--gcc/tree-ssa-strlen.c554
-rw-r--r--gcc/tree-ssa-strlen.h7
-rw-r--r--gcc/tree-ssa-structalias.c34
-rw-r--r--gcc/tree-ssa-tail-merge.c4
-rw-r--r--gcc/tree-ssa-threadbackward.c7
-rw-r--r--gcc/tree-ssa-threadedge.c6
-rw-r--r--gcc/tree-ssa-uninit.c211
-rw-r--r--gcc/tree-ssa.c13
-rw-r--r--gcc/tree-ssa.h2
-rw-r--r--gcc/tree-ssanames.c27
-rw-r--r--gcc/tree-streamer-out.c6
-rw-r--r--gcc/tree-streamer.c1
-rw-r--r--gcc/tree-switch-conversion.c74
-rw-r--r--gcc/tree-switch-conversion.h30
-rw-r--r--gcc/tree-vect-data-refs.c34
-rw-r--r--gcc/tree-vect-generic.c6
-rw-r--r--gcc/tree-vect-loop-manip.c96
-rw-r--r--gcc/tree-vect-loop.c836
-rw-r--r--gcc/tree-vect-patterns.c187
-rw-r--r--gcc/tree-vect-slp-patterns.c721
-rw-r--r--gcc/tree-vect-slp.c1770
-rw-r--r--gcc/tree-vect-stmts.c124
-rw-r--r--gcc/tree-vectorizer.c27
-rw-r--r--gcc/tree-vectorizer.h139
-rw-r--r--gcc/tree-vrp.c1831
-rw-r--r--gcc/tree.c270
-rw-r--r--gcc/tree.def12
-rw-r--r--gcc/tree.h92
-rw-r--r--gcc/tsan.c6
-rw-r--r--gcc/typeclass.h2
-rw-r--r--gcc/ubsan.c13
-rw-r--r--gcc/value-query.cc6
-rw-r--r--gcc/value-range.cc539
-rw-r--r--gcc/value-range.h51
-rw-r--r--gcc/varasm.c261
-rw-r--r--gcc/varpool.c2
-rw-r--r--gcc/vec.h136
-rw-r--r--gcc/vr-values.c245
-rw-r--r--gcc/vr-values.h2
-rw-r--r--gcc/wide-int.cc21
-rw-r--r--gcc/wide-int.h10
-rw-r--r--gcc/xcoffout.c2
6000 files changed, 254097 insertions, 60382 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a049252..af11269 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8002 @@
+2020-12-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md: Remove unnecessary clobbers
+ from combine splitters.
+
+2020-12-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98461
+ * config/i386/sse.md (<sse2_avx2>_pmovmskb): Add splitters
+ for pmovmskb of NOT vector.
+
+2020-12-29 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (maddsidi4_split): Skip macd gen, use mac insn
+ instead.
+ (macd): Update register letters.
+ (umaddsidi4_split): Skip macdu gen, use macu insn instead.
+ (macdu): Update register letters.
+
+2020-12-29 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_secondary_reload): Flip if-condition
+ predicates.
+
+2020-12-29 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.h (REGNO_OK_FOR_BASE_P): Check if defined
+ reg_renumber.
+
+2020-12-29 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (prepare_move_operands): Use a temporary
+ registers when we have cached mem-to-uncached mem moves.
+
+2020-12-29 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (movdi_insn): Update pattern, no predicated
+ vadd2 usage.
+ (movdf_insn): Likewise.
+ * config/arc/simdext.md (movVEC_insn): Likewise.
+
+2020-12-29 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_gen_TWO52): Use REAL_MODE_FORMAT
+ to determine number of mantissa bits. Use real_2expN instead
+ of real_ldexp.
+ (ix86_expand_rint): Use copy_to_reg.
+ (ix86_expand_floorceildf_32): Ditto.
+ (ix86_expand_truncdf_32): Ditto.
+ (ix86_expand_rounddf_32): Ditto.
+ (ix86_expand_floorceil): Use copy_to_reg and int_mode_for_mode.
+ (ix86_expand_trunc): Ditto.
+ (ix86_expand_round): Ditto.
+
+2020-12-28 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/standards.texi (HSAIL): Remove section.
+
+2020-12-28 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/96793
+ * config/i386/i386-expand.c (ix86_expand_rint):
+ Remove the sign of the intermediate value for flag_rounding_math.
+
+2020-12-28 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_expand_trunc): Use
+ existing temporary register to avoid a call to force_reg.
+
+2020-12-28 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386.md (optab): New code attr.
+ * config/i386/sse.md (<code>v32qiv32hi2): Rename to ...
+ (<optab>v32qiv32hi2) ... this.
+ (<code>v16qiv16hi2): Likewise.
+ (<code>v8qiv8hi2): Likewise.
+ (<code>v16qiv16si2): Likewise.
+ (<code>v8qiv8si2): Likewise.
+ (<code>v4qiv4si2): Likewise.
+ (<code>v16hiv16si2): Likewise.
+ (<code>v8hiv8si2): Likewise.
+ (<code>v4hiv4si2): Likewise.
+ (<code>v8qiv8di2): Likewise.
+ (<code>v4qiv4di2): Likewise.
+ (<code>v2qiv2di2): Likewise.
+ (<code>v8hiv8di2): Likewise.
+ (<code>v4hiv4di2): Likewise.
+ (<code>v2hiv2di2): Likewise.
+ (<code>v8siv8di2): Likewise.
+ (<code>v4siv4di2): Likewise.
+ (<code>v2siv2di2): Likewise.
+
+2020-12-27 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/analyzer.texi (Analyzer Internals): Find a new source for
+ the "A Memory Model for Static Analysis of C Programs" paper.
+
+2020-12-25 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/invoke.texi (C++ Module Mapper): Fix reference to libcody.
+
+2020-12-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * configure.ac: Add gxx-libcxx-include-dir handled
+ in the same way as the regular cxx header directory.
+ * Makefile.in: Regenerated.
+ * config.in: Likewise.
+ * configure: Likewise.
+ * cppdefault.c: Pick up libc++ headers if the option
+ is enabled.
+ * cppdefault.h (struct default_include): Amend comments
+ to reflect the extended use of the cplusplus field.
+ * incpath.c (add_standard_paths): Allow for multiple
+ c++ header include path variants.
+ * doc/invoke.texi: Document the -stdlib= option.
+
+2020-12-24 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/multilib-generator (arch_canonicalize): Call
+ decode for the subprocess return value.
+
+2020-12-23 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/98160
+ * builtins.c (warn_dealloc_offset): Avoid assuming calls are made
+ through declared functions and not pointers.
+
+2020-12-23 Martin Sebor <msebor@redhat.com>
+
+ PR c++/98413
+ * builtins.c (get_offset_range): Avoid non-integers/-pointers.
+
+2020-12-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-driver.c (validate_macosx_version_min): Allow
+ MACOSX_DEPLOYMENT_TARGET=11.
+ (darwin_default_min_version): Adjust warning spelling to avoid
+ an apostrophe.
+
+2020-12-23 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/96793
+ * config/i386/i386-expand.c (ix86_expand_truncdf_32):
+ Remove the sign of the intermediate value for flag_rounding_math.
+
+2020-12-22 Qian Jianhua <qianjh@cn.fujitsu.com>
+
+ * config/arm/types.md (define_attr "autodetect_type"): New.
+ (define_attr "type"): Subdivide alu_shift_imm.
+ * config/arm/common.md: New file.
+ * config/aarch64/predicates.md:Include common.md.
+ * config/arm/predicates.md:Include common.md.
+ * config/aarch64/aarch64.md (*add_<shift>_<mode>): Set autodetect_type.
+ (*add_<shift>_si_uxtw): Likewise.
+ (*sub_<shift>_<mode>): Likewise.
+ (*sub_<shift>_si_uxtw): Likewise.
+ (*neg_<shift>_<mode>2): Likewise.
+ (*neg_<shift>_si2_uxtw): Likewise.
+ * config/arm/arm.md (*addsi3_carryin_shift): Likewise.
+ (add_not_shift_cin): Likewise.
+ (*subsi3_carryin_shift): Likewise.
+ (*subsi3_carryin_shift_alt): Likewise.
+ (*rsbsi3_carryin_shift): Likewise.
+ (*rsbsi3_carryin_shift_alt): Likewise.
+ (*arm_shiftsi3): Likewise.
+ (*<arith_shift_insn>_multsi): Likewise.
+ (*<arith_shift_insn>_shiftsi): Likewise.
+ (subsi3_carryin): Set new type.
+ (*if_arith_move): Set new type.
+ (*if_move_arith): Set new type.
+ (define_attr "core_cycles"): Use new type.
+ * config/arm/arm-fixed.md (arm_ssatsihi_shift): Set autodetect_type.
+ * config/arm/thumb2.md (*orsi_not_shiftsi_si): Likewise.
+ (*thumb2_shiftsi3_short): Set new type.
+ * config/aarch64/falkor.md (falkor_alu_1_xyz): Use new type.
+ * config/aarch64/saphira.md (saphira_alu_1_xyz): Likewise.
+ * config/aarch64/thunderx.md (thunderx_arith_shift): Likewise.
+ * config/aarch64/thunderx2t99.md (thunderx2t99_alu_shift): Likewise.
+ * config/aarch64/thunderx3t110.md (thunderx3t110_alu_shift): Likewise.
+ (thunderx3t110_alu_shift1): Likewise.
+ * config/aarch64/tsv110.md (tsv110_alu_shift): Likewise.
+ * config/arm/arm1020e.md (1020alu_shift_op): Likewise.
+ * config/arm/arm1026ejs.md (alu_shift_op): Likewise.
+ * config/arm/arm1136jfs.md (11_alu_shift_op): Likewise.
+ * config/arm/arm926ejs.md (9_alu_op): Likewise.
+ * config/arm/cortex-a15.md (cortex_a15_alu_shift): Likewise.
+ * config/arm/cortex-a17.md (cortex_a17_alu_shiftimm): Likewise.
+ * config/arm/cortex-a5.md (cortex_a5_alu_shift): Likewise.
+ * config/arm/cortex-a53.md (cortex_a53_alu_shift): Likewise.
+ * config/arm/cortex-a57.md (cortex_a57_alu_shift): Likewise.
+ * config/arm/cortex-a7.md (cortex_a7_alu_shift): Likewise.
+ * config/arm/cortex-a8.md (cortex_a8_alu_shift): Likewise.
+ * config/arm/cortex-a9.md (cortex_a9_dp_shift): Likewise.
+ * config/arm/cortex-m4.md (cortex_m4_alu): Likewise.
+ * config/arm/cortex-m7.md (cortex_m7_alu_shift): Likewise.
+ * config/arm/cortex-r4.md (cortex_r4_alu_shift): Likewise.
+ * config/arm/exynos-m1.md (exynos_m1_alu_shift): Likewise.
+ * config/arm/fa526.md (526_alu_shift_op): Likewise.
+ * config/arm/fa606te.md (606te_alu_op): Likewise.
+ * config/arm/fa626te.md (626te_alu_shift_op): Likewise.
+ * config/arm/fa726te.md (726te_alu_shift_op): Likewise.
+ * config/arm/fmp626.md (mp626_alu_shift_op): Likewise.
+ * config/arm/marvell-pj4.md (pj4_shift): Likewise.
+ (pj4_shift_conds): Likewise.
+ (pj4_alu_shift): Likewise.
+ (pj4_alu_shift_conds): Likewise.
+ * config/arm/xgene1.md (xgene1_alu): Likewise.
+ * config/arm/arm.c (xscale_sched_adjust_cost): Likewise.
+
+2020-12-22 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/96793
+ * config/i386/i386-expand.c (ix86_expand_floorceil):
+ Remove the sign of the intermediate value for flag_rounding_math.
+ (ix86_expand_floorceildf_32): Ditto.
+
+2020-12-22 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.md (*one_cmpl<mode>2_1): Fix typo, change
+ alternative from 2 to 1 in attr isa.
+
+2020-12-22 Ian Lance Taylor <iant@golang.org>
+
+ * godump.c (go_output_typedef): If DECL_ORIGINAL_TYPE is NULL, use
+ TREE_TYPE.
+
+2020-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98353
+ * gimplify.c (gimplify_init_ctor_eval_range): Gimplify value before
+ storing it into cref.
+
+2020-12-21 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-driver.c (darwin_find_version_from_kernel):
+ Compute the minor OS version from the minor kernel version.
+
+2020-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98407
+ * fold-const.c (native_encode_initializer): When handling flexible
+ array members, fix up computation of length for memset. Also remove
+ " - o" as o is always guaranteed to be 0 in this code path.
+
+2020-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98383
+ * gimplify.c (struct gimplify_omp_ctx): Add in_for_exprs flag.
+ (gimple_add_tmp_var): For addressable temporaries appearing in
+ simd lb, b or incr expressions, don't add a private clause unless
+ it is seen also outside of those expressions in the simd body.
+ (omp_notice_variable): Likewise.
+ (gimplify_omp_for): Set and reset in_for_exprs around gimplification
+ of lb, b or incr expressions.
+
+2020-12-20 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/xtensa.md (bswapsi2, bswapdi2): New patterns.
+
+2020-12-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/98400
+ * doc/invoke.texi (-mbackchain): Fix a typo - -mmo-backchain ->
+ -mno-backchain.
+
+2020-12-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98366
+ * fold-const.c (native_encode_initializer): Don't try to
+ memset more than total_bytes with off == -1 even if len is large.
+ Handle flexible array member initializers if off == -1 and mask is
+ NULL.
+ * expr.c (convert_to_bytes): Remove.
+ (constant_byte_string): Use native_encode_initializer instead of
+ convert_to_bytes. Remove extraneous semicolon. Punt on various
+ corner-cases the APIs don't handle, like sizes > INT_MAX,
+ BITS_PER_UNIT != 8, CHAR_BIT != 8.
+
+2020-12-19 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/98067
+ * dwarf2out.c (dwarf2out_imported_module_or_decl_1): Handle
+ CONST_DECL only if is_fortran, is_ada, or is_dlang.
+
+2020-12-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98378
+ * gimple-ssa-store-merging.c (find_bswap_or_nop): Punt if CONSTRUCTOR
+ has no elements.
+
+2020-12-18 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (struct gimplify_omp_ctx): Add has_depend member.
+ (gimplify_scan_omp_clauses): Set it to true if OMP_CLAUSE_DEPEND
+ appears on OMP_TASK.
+ (gimplify_adjust_omp_clauses_1, gimplify_adjust_omp_clauses): Force
+ GOVD_WRITTEN on shared variables if task construct has depend clause.
+
+2020-12-18 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ PR target/98177
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Use
+ get_same_sized_vectype to obtain index type.
+ (vectorizable_reduction): Likewise.
+
+2020-12-18 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * langhooks-def.h (lhd_get_decl_init): New.
+ (lhd_finish_decl_inits): New.
+ (LANG_HOOKS_GET_DECL_INIT): New.
+ (LANG_HOOKS_OMP_FINISH_DECL_INITS): New.
+ (LANG_HOOKS_DECLS): Add LANG_HOOKS_GET_DECL_INIT and
+ LANG_HOOKS_OMP_FINISH_DECL_INITS.
+ * langhooks.c (lhd_omp_get_decl_init): New.
+ (lhd_omp_finish_decl_inits): New.
+ * langhooks.h (struct lang_hooks_for_decls): Add omp_get_decl_init
+ and omp_finish_decl_inits.
+ * omp-offload.c (omp_discover_declare_target_var_r): Use
+ get_decl_init langhook in place of DECL_INITIAL. Call
+ omp_finish_decl_inits langhook at end of function.
+
+2020-12-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_preferred_simd_mode): Use
+ aarch64_full_sve_mode and aarch64_vq_mode directly, instead of
+ going via aarch64_simd_container_mode.
+
+2020-12-18 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/iterators.md (rot): Add UNSPEC_VCMUL, UNSPEC_VCMUL90,
+ UNSPEC_VCMUL180, UNSPEC_VCMUL270.
+
+2020-12-17 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/arm/arm-cpus.in: Add Cortex-A78C core.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR rtl-optimization/98347
+ * rtl-ssa/access-utils.h (full_register): Use regno_reg_rtx
+ instead of reg_raw_mode.
+
+2020-12-17 H.J. Lu <hjl.tools@gmail.com>
+
+ * targhooks.h (default_estimated_poly_value): Updated.
+
+2020-12-17 Nathan Sidwell <nathan@acm.org>
+
+ * doc/invoke.texi (C++ Modules): Document lack of std
+ library header units.
+
+2020-12-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * target.h (enum poly_value_estimate_kind): Define.
+ (estimated_poly_value): Take an estimate kind argument.
+ * target.def (estimated_poly_value): Update definition for the
+ above.
+ * doc/tm.texi: Regenerate.
+ * targhooks.c (estimated_poly_value): Update prototype.
+ * tree-vect-loop.c (vect_better_loop_vinfo_p): Use min, max and
+ likely estimates of VF to pick between vinfos.
+ * config/aarch64/aarch64.c (aarch64_cmp_autovec_modes): Use
+ estimated_poly_value instead of aarch64_estimated_poly_value.
+ (aarch64_estimated_poly_value): Take a kind argument and handle
+ it.
+
+2020-12-17 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm_neon.h (vcreate_p64): Remove call to
+ '__builtin_neon_vcreatedi'.
+
+2020-12-17 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97750
+ * range-op.cc (operator_cast::op1_range): Handle pointers better.
+
+2020-12-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * rtl-ssa.h: Include memmodel.h before tm_p.h.
+
+2020-12-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98289
+ * shrink-wrap.c (can_get_prologue): Don't punt on EDGE_CROSSING
+ incoming edges.
+
+2020-12-17 Marius Hillenbrand <mhillen@linux.ibm.com>
+
+ * configure.ac: Change --enable-s390-excess-float-precision
+ default behavior for cross compiles with target headers.
+ * configure: Regenerate.
+ * doc/install.texi: Adjust documentation.
+
+2020-12-17 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.md (*ashlsi3_1, *ashlsi3_3x, *ashrsi3_3x)
+ (*lshrsi3_3x): New patterns.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * fwprop.c: Rewrite to use the RTL SSA framework.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * configure.ac: Add rtl-ssa to the list of dependence directories.
+ * configure: Regenerate.
+ * Makefile.in (rtl-ssa-warn): New variable.
+ (OBJS): Add the rtl-ssa object files.
+ * emit-rtl.h (rtl_data::ssa): New field.
+ * rtl-ssa.h: New file.
+ * system.h: Include <functional> when INCLUDE_FUNCTIONAL is defined.
+ * rtl-ssa/access-utils.h: Likewise.
+ * rtl-ssa/accesses.h: New file.
+ * rtl-ssa/accesses.cc: Likewise.
+ * rtl-ssa/blocks.h: New file.
+ * rtl-ssa/blocks.cc: Likewise.
+ * rtl-ssa/change-utils.h: Likewise.
+ * rtl-ssa/changes.h: New file.
+ * rtl-ssa/changes.cc: Likewise.
+ * rtl-ssa/functions.h: New file.
+ * rtl-ssa/functions.cc: Likewise.
+ * rtl-ssa/insn-utils.h: Likewise.
+ * rtl-ssa/insns.h: New file.
+ * rtl-ssa/insns.cc: Likewise.
+ * rtl-ssa/internals.inl: Likewise.
+ * rtl-ssa/is-a.inl: Likewise.
+ * rtl-ssa/member-fns.inl: Likewise.
+ * rtl-ssa/movement.h: Likewise.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/rtl.texi (RTL SSA): New node.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * rtl.h (simple_regno_set): Declare.
+ * rtlanal.c (simple_regno_set): New function.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * rtlanal.h: New file.
+ (MEM_REGNO): New constant.
+ (rtx_obj_flags): New namespace.
+ (rtx_obj_reference, rtx_properties): New classes.
+ (growing_rtx_properties, vec_rtx_properties_base): Likewise.
+ (vec_rtx_properties): New alias.
+ * rtlanal.c: Include it.
+ (rtx_properties::try_to_add_reg): New function.
+ (rtx_properties::try_to_add_dest): Likewise.
+ (rtx_properties::try_to_add_src): Likewise.
+ (rtx_properties::try_to_add_pattern): Likewise.
+ (rtx_properties::try_to_add_insn): Likewise.
+ (vec_rtx_properties_base::grow): Likewise.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * recog.h (insn_change_watermark): New class.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * recog.h (insn_propagation): New class.
+ * recog.c (insn_propagation::apply_to_mem_1): New function.
+ (insn_propagation::apply_to_rvalue_1): Likewise.
+ (insn_propagation::apply_to_lvalue_1): Likewise.
+ (insn_propagation::apply_to_pattern_1): Likewise.
+ (insn_propagation::apply_to_pattern): Likewise.
+ (insn_propagation::apply_to_rvalue): Likewise.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * recog.h (temporarily_undo_changes, redo_changes): Declare.
+ * recog.c (temporarily_undone_changes): New variable.
+ (validate_change_1, confirm_change_group): Check that it's zero.
+ (cancel_changes): Likewise.
+ (swap_change, temporarily_undo_changes): New functions.
+ (redo_changes): Likewise.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * recog.h (validate_change_xveclen): Declare.
+ * recog.c (change_t::old_len): New field.
+ (validate_change_1): Add a new_len parameter. Conditionally
+ replace the XVECLEN of an rtx, avoiding single-element PARALLELs.
+ (validate_change_xveclen): New function.
+ (cancel_changes): Undo changes made by validate_change_xveclen.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * rtl.h (simplify_context): New class.
+ (simplify_unary_operation, simplify_binary_operation): Use it.
+ (simplify_ternary_operation, simplify_relational_operation): Likewise.
+ (simplify_subreg, simplify_gen_unary, simplify_gen_binary): Likewise.
+ (simplify_gen_ternary, simplify_gen_relational): Likewise.
+ (simplify_gen_subreg, lowpart_subreg): Likewise.
+ * simplify-rtx.c (simplify_gen_binary): Turn into a member function
+ of simplify_context.
+ (simplify_gen_unary, simplify_gen_ternary, simplify_gen_relational)
+ (simplify_truncation, simplify_unary_operation): Likewise.
+ (simplify_unary_operation_1, simplify_byte_swapping_operation)
+ (simplify_associative_operation, simplify_logical_relational_operation)
+ (simplify_binary_operation, simplify_binary_operation_series)
+ (simplify_distributive_operation, simplify_plus_minus): Likewise.
+ (simplify_relational_operation, simplify_relational_operation_1)
+ (simplify_cond_clz_ctz, simplify_merge_mask): Likewise.
+ (simplify_ternary_operation, simplify_subreg, simplify_gen_subreg)
+ (lowpart_subreg): Likewise.
+ (simplify_binary_operation_1): Likewise. Test mem_depth when
+ deciding whether the ASHIFT or MULT form is canonical.
+ (simplify_merge_mask): Use simplify_context.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * rtl.h (register_asm_p): Declare.
+ * recog.c (verify_changes): Split out the test for whether
+ a hard register is a register asm to...
+ * rtlanal.c (register_asm_p): ...this new function.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * print-rtl.h (print_insn_with_notes): Declare.
+ * print-rtl.c (print_insn_with_notes): Make non-static
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * cfgrtl.h (update_cfg_for_uncondjump): Declare.
+ * combine.c (update_cfg_for_uncondjump): Move to...
+ * cfgrtl.c: ...here.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * vec.h (array_slice): New class.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * Makefile.in (OBJS): Add splay-tree-utils.o.
+ * system.h: Include <array> when INCLUDE_ARRAY is defined.
+ * selftest.h (splay_tree_cc_tests): Declare.
+ * selftest-run-tests.c (selftest::run_tests): Run splay_tree_cc_tests.
+ * splay-tree-utils.h: New file.
+ * splay-tree-utils.tcc: Likewise.
+ * splay-tree-utils.cc: Likewise.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * mux-utils.h: New file.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * obstack-utils.h: New file.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * iterator-utils.h (derived_iterator): New class.
+ (const_derived_container, wrapper_iterator): Likewise.
+ (list_iterator): Likewise.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * hard-reg-set.h (global_reg_set): Declare.
+ * reginfo.c (global_reg_set): New variable.
+ (init_reg_sets_1, globalize_reg): Update it when globalizing
+ registers.
+
+2020-12-16 Piotr Kubaj <pkubaj@FreeBSD.org>
+
+ * config.gcc (powerpc*le-*-freebsd*): Add.
+ * configure.ac (powerpc*le-*-freebsd*): Ditto.
+ * configure: Regenerate.
+ * config/rs6000/freebsd64.h (ASM_SPEC_COMMON): Use ENDIAN_SELECT.
+ (DEFAULT_ASM_ENDIAN): Add little endian support.
+ (LINK_OS_FREEBSD_SPEC64): Ditto.
+
+2020-12-16 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.c (xtensa_emit_move_sequence): Try to
+ replace 'l32r' with 'movi' + 'slli' when optimizing for size.
+ * config/xtensa/xtensa.md (movdi): Split loading DI mode constant
+ into register pair into two loads of SI mode constants.
+
+2020-12-16 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm_mve.h (__arm_vcmulq_rot90_f16):
+ (__arm_vcmulq_rot270_f16, _arm_vcmulq_rot180_f16, __arm_vcmulq_f16,
+ __arm_vcmulq_rot90_f32, __arm_vcmulq_rot270_f32,
+ __arm_vcmulq_rot180_f32, __arm_vcmulq_f32, __arm_vcmlaq_f16,
+ __arm_vcmlaq_rot180_f16, __arm_vcmlaq_rot270_f16,
+ __arm_vcmlaq_rot90_f16, __arm_vcmlaq_f32, __arm_vcmlaq_rot180_f32,
+ __arm_vcmlaq_rot270_f32, __arm_vcmlaq_rot90_f32): Update builtin calls.
+ * config/arm/arm_mve_builtins.def (vcmulq_f, vcmulq_rot90_f,
+ vcmulq_rot180_f, vcmulq_rot270_f, vcmlaq_f, vcmlaq_rot90_f,
+ vcmlaq_rot180_f, vcmlaq_rot270_f): Removed.
+ (vcmulq, vcmulq_rot90, vcmulq_rot180, vcmulq_rot270, vcmlaq,
+ vcmlaq_rot90, vcmlaq_rot180, vcmlaq_rot270): New.
+ * config/arm/iterators.md (mve_rot): Add UNSPEC_VCMLA, UNSPEC_VCMLA90,
+ UNSPEC_VCMLA180, UNSPEC_VCMLA270, UNSPEC_VCMUL, UNSPEC_VCMUL90,
+ UNSPEC_VCMUL180, UNSPEC_VCMUL270.
+ (VCMUL): New.
+ * config/arm/mve.md (mve_vcmulq_f<mode, mve_vcmulq_rot180_f<mode>,
+ mve_vcmulq_rot270_f<mode>, mve_vcmulq_rot90_f<mode>, mve_vcmlaq_f<mode>,
+ mve_vcmlaq_rot180_f<mode>, mve_vcmlaq_rot270_f<mode>,
+ mve_vcmlaq_rot90_f<mode>): Removed.
+ (mve_vcmlaq<mve_rot><mode>, mve_vcmulq<mve_rot><mode>,
+ mve_vcaddq<mve_rot><mode>, cadd<rot><mode>3, mve_vcaddq<mve_rot><mode>):
+ New.
+ * config/arm/unspecs.md (UNSPEC_VCMUL90, UNSPEC_VCMUL270, UNSPEC_VCMUL,
+ UNSPEC_VCMUL180): New.
+ (VCMULQ_F, VCMULQ_ROT180_F, VCMULQ_ROT270_F, VCMULQ_ROT90_F,
+ VCMLAQ_F, VCMLAQ_ROT180_F, VCMLAQ_ROT90_F, VCMLAQ_ROT270_F): Removed.
+
+2020-12-16 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm_mve.h (__arm_vcaddq_rot90_u8, __arm_vcaddq_rot270_u8,
+ __arm_vcaddq_rot90_s8, __arm_vcaddq_rot270_s8,
+ __arm_vcaddq_rot90_u16, __arm_vcaddq_rot270_u16,
+ __arm_vcaddq_rot90_s16, __arm_vcaddq_rot270_s16,
+ __arm_vcaddq_rot90_u32, __arm_vcaddq_rot270_u32,
+ __arm_vcaddq_rot90_s32, __arm_vcaddq_rot270_s32,
+ __arm_vcaddq_rot90_f16, __arm_vcaddq_rot270_f16,
+ __arm_vcaddq_rot90_f32, __arm_vcaddq_rot270_f32): Update builtin calls.
+ * config/arm/arm_mve_builtins.def (vcaddq_rot90_u, vcaddq_rot270_u,
+ vcaddq_rot90_s, vcaddq_rot270_s, vcaddq_rot90_f, vcaddq_rot270_f):
+ Removed.
+ (vcaddq_rot90, vcaddq_rot270): New.
+ * config/arm/constraints.md (Dz): Include MVE.
+ * config/arm/iterators.md (mve_rot): New.
+ (supf): Remove VCADDQ_ROT270_S, VCADDQ_ROT270_U, VCADDQ_ROT90_S,
+ VCADDQ_ROT90_U.
+ (VCADDQ_ROT270, VCADDQ_ROT90): Removed.
+ * config/arm/mve.md (mve_vcaddq_rot270_<supf><mode,
+ mve_vcaddq_rot90_<supf><mode>, mve_vcaddq_rot270_f<mode>,
+ mve_vcaddq_rot90_f<mode>): Removed.
+ (mve_vcaddq<mve_rot><mode>, mve_vcaddq<mve_rot><mode>): New.
+ * config/arm/unspecs.md (VCADDQ_ROT270_S, VCADDQ_ROT90_S,
+ VCADDQ_ROT270_U, VCADDQ_ROT90_U, VCADDQ_ROT270_F,
+ VCADDQ_ROT90_F): Removed.
+ * config/arm/vec-common.md (cadd<rot><mode>3): New.
+
+2020-12-16 Tamar Christina <tamar.christina@arm.com>
+
+ * config/aarch64/aarch64-simd.md (cadd<rot><mode>3): New.
+ * config/aarch64/iterators.md (SVE2_INT_CADD_OP): New.
+ * config/aarch64/aarch64-sve.md (cadd<rot><mode>3): New.
+ * config/aarch64/aarch64-sve2.md (cadd<rot><mode>3): New.
+
+2020-12-16 Pat Haugen <pthaugen@linux.ibm.com>
+
+ * config/rs6000/mma.md (*movxo, mma_<vvi4i4i8>, mma_<avvi4i4i8>,
+ mma_<vvi4i4i2>, mma_<avvi4i4i2>, mma_<vvi4i4>, mma_<avvi4i4>,
+ mma_<pvi4i2>, mma_<apvi4i2>, mma_<vvi4i4i4>, mma_<avvi4i4i4>):
+ Remove explicit setting of length attribute.
+
+2020-12-16 Jakub Jelinek <jakub@redhat.com>
+
+ * varasm.c (default_elf_asm_named_section): Always force
+ section flags even for sections with SECTION_LINK_ORDER flag.
+
+2020-12-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98146
+ * defaults.h (SUPPORTS_SHF_GNU_RETAIN): New.
+ * varasm.c (get_section): Replace HAVE_GAS_SHF_GNU_RETAIN with
+ SUPPORTS_SHF_GNU_RETAIN.
+ (resolve_unique_section): Likewise.
+ (get_variable_section): Likewise.
+ (switch_to_section): Likewise.
+
+2020-12-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98146
+ * varasm.c (switch_to_section): Warn when a symbol without used
+ attribute and a symbol with used attribute are placed in the
+ section with the same name.
+
+2020-12-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98146
+ * output.h (switch_to_section): Add a tree argument, default to
+ nullptr.
+ * varasm.c (get_section): If the SECTION_RETAIN bit doesn't match,
+ return and switch to a new section later.
+ (assemble_start_function): Pass decl to switch_to_section.
+ (assemble_variable): Likewise.
+ (switch_to_section): If the SECTION_RETAIN bit doesn't match,
+ switch to a new section.
+
+2020-12-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96239
+ * gimple-ssa-store-merging.c (find_bswap_or_nop): Handle a vector
+ CONSTRUCTOR.
+ (bswap_replace): Likewise.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Remove usage of Report.
+ * config/aarch64/aarch64.opt: Ditto.
+ * config/alpha/alpha.opt: Ditto.
+ * config/arc/arc.opt: Ditto.
+ * config/arm/arm.opt: Ditto.
+ * config/avr/avr.opt: Ditto.
+ * config/bfin/bfin.opt: Ditto.
+ * config/bpf/bpf.opt: Ditto.
+ * config/c6x/c6x.opt: Ditto.
+ * config/cr16/cr16.opt: Ditto.
+ * config/cris/cris.opt: Ditto.
+ * config/cris/elf.opt: Ditto.
+ * config/csky/csky.opt: Ditto.
+ * config/darwin.opt: Ditto.
+ * config/fr30/fr30.opt: Ditto.
+ * config/frv/frv.opt: Ditto.
+ * config/ft32/ft32.opt: Ditto.
+ * config/gcn/gcn.opt: Ditto.
+ * config/i386/cygming.opt: Ditto.
+ * config/i386/i386.opt: Ditto.
+ * config/ia64/ia64.opt: Ditto.
+ * config/ia64/ilp32.opt: Ditto.
+ * config/linux-android.opt: Ditto.
+ * config/linux.opt: Ditto.
+ * config/lm32/lm32.opt: Ditto.
+ * config/m32r/m32r.opt: Ditto.
+ * config/m68k/m68k.opt: Ditto.
+ * config/mcore/mcore.opt: Ditto.
+ * config/microblaze/microblaze.opt: Ditto.
+ * config/mips/mips.opt: Ditto.
+ * config/mmix/mmix.opt: Ditto.
+ * config/mn10300/mn10300.opt: Ditto.
+ * config/moxie/moxie.opt: Ditto.
+ * config/msp430/msp430.opt: Ditto.
+ * config/nds32/nds32.opt: Ditto.
+ * config/nios2/elf.opt: Ditto.
+ * config/nios2/nios2.opt: Ditto.
+ * config/nvptx/nvptx.opt: Ditto.
+ * config/pa/pa.opt: Ditto.
+ * config/pdp11/pdp11.opt: Ditto.
+ * config/pru/pru.opt: Ditto.
+ * config/riscv/riscv.opt: Ditto.
+ * config/rl78/rl78.opt: Ditto.
+ * config/rs6000/aix64.opt: Ditto.
+ * config/rs6000/linux64.opt: Ditto.
+ * config/rs6000/rs6000.opt: Ditto.
+ * config/rs6000/sysv4.opt: Ditto.
+ * config/rx/elf.opt: Ditto.
+ * config/rx/rx.opt: Ditto.
+ * config/s390/s390.opt: Ditto.
+ * config/s390/tpf.opt: Ditto.
+ * config/sh/sh.opt: Ditto.
+ * config/sol2.opt: Ditto.
+ * config/sparc/long-double-switch.opt: Ditto.
+ * config/sparc/sparc.opt: Ditto.
+ * config/tilegx/tilegx.opt: Ditto.
+ * config/tilepro/tilepro.opt: Ditto.
+ * config/v850/v850.opt: Ditto.
+ * config/visium/visium.opt: Ditto.
+ * config/vms/vms.opt: Ditto.
+ * config/vxworks.opt: Ditto.
+ * config/xtensa/xtensa.opt: Ditto.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ * doc/options.texi: Remove Report keyword.
+ * opt-functions.awk: Print error when Report keyword
+ is used.
+ * optc-gen.awk: Do not handle Report keyword.
+ * opts.h (struct cl_option): Remove cl_report bitfield flag.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/97868
+ * common.opt: Add new warning -Wtsan.
+ * doc/invoke.texi: Likewise.
+ * tsan.c (instrument_builtin_call): Warn users about unsupported
+ std::atomic_thread_fence.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ PR rtl-optimization/98271
+ PR rtl-optimization/98276
+ PR tree-optimization/98279
+ * opts-common.c (set_option): Do not allow overflow for integer
+ arguments.
+
+2020-12-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR tree-optimization/98272
+ * tree-switch-conversion.c (bit_test_cluster::emit): When finding
+ out whether the entry test can be merged in the bit test, do the
+ computation using the type of the index expression.
+
+2020-12-16 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Use
+ paradoxical subreg instead of zero_extend for QI/HI promotion.
+
+2020-12-16 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/66791
+ * config/arm/arm_neon.h: Replace calls to __builtin_vcgt* by
+ <, > operators in vclt and vcgt intrinsics respectively.
+ * config/arm/arm_neon_builtins.def: Remove entry for
+ vcgt and vcgtu.
+
+2020-12-16 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/66791
+ * config/arm/arm_neon.h: Replace calls to __builtin_vneg* by - operator
+ in vneg intrinsics.
+ * config/arm/arm_neon_builtins.def: Remove entry for vneg.
+
+2020-12-16 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/66791
+ * config/arm/arm_neon.h: Replace calls to __builtin_vcreate*
+ in vcreate intrinsics.
+ * config/arm/arm_neon_builtins.def: Remove entry for vcreate.
+
+2020-12-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96094
+ * match.pd (X / bool_range_Y -> X): New simplification.
+
+2020-12-15 Nathan Sidwell <nathan@acm.org>
+
+ * doc/cppopts.texi: Document new cpp opt.
+ * doc/invoke.texi: Add C++20 module option & documentation.
+
+2020-12-15 Nathan Sidwell <nathan@acm.org>
+
+ * Makefile.in (CODYINC, CODYLIB, CODYLIB_H): New. Use them.
+
+2020-12-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98274
+ * config/i386/i386-options.c (ix86_option_override_internal): Set
+ ix86_tune_string to "generic" even when it wasn't specified and
+ ix86_arch_string is "x86-64-v2", "x86-64-v3" or "x86-64-v4".
+ Remove useless {}s around a single statement.
+
+2020-12-15 Martin Liska <mliska@suse.cz>
+
+ PR lto/98275
+ * lto-wrapper.c: Do not use -j0 when we are unable to detect
+ number of cores.
+
+2020-12-15 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386-options.c (ix86_option_override_internal): Don't
+ error on -march=x86-64-v[234] with -m32 or -mabi=ms.
+ * config.gcc: Don't reject --with-arch=x86-64-v[234] or
+ --with-arch_32=x86-64-v[234].
+ * doc/invoke.texi (-march=x86-64-v[234]): Document what the option
+ does for other ABIs.
+
+2020-12-15 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/98273
+ * gcov.c (output_json_intermediate_file): Use stack of nested
+ functions for lines in a source file. Pop when a function ends.
+
+2020-12-15 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/invoke.texi (Instrumentation Options): Update link to
+ KernelAddressSanitizer.
+
+2020-12-15 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/predicates.md (addsubx_operand): Change accepted
+ values from 2/4/8 to 1..3.
+ * config/xtensa/xtensa.md (*addx, *subx): Change RTL pattern
+ to use 'ashift' instead of 'mult'. Update operands[3] value.
+
+2020-12-14 Piotr Kubaj <pkubaj@FreeBSD.org>
+ Gerald Pfeifer <gerald@pfeifer.com>
+
+ * config/rs6000/freebsd64.h (PROCESSOR_DEFAULT): Update
+ to PROCESSOR_PPC7450.
+ (PROCESSOR_DEFAULT64): Update to PROCESSOR_POWER8.
+
+2020-12-14 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/98166
+ PR c++/57111
+ PR middle-end/98160
+ * builtins.c (check_access): Call tree_inlined_location
+ fndecl_alloc_p): Handle BUILT_IN_ALIGNED_ALLOC and
+ BUILT_IN_GOMP_ALLOC.
+ call_dealloc_p): Remove unused function.
+ (new_delete_mismatch_p): Call valid_new_delete_pair_p and rework.
+ (matching_alloc_calls_p): Handle built-in deallocation functions.
+ (warn_dealloc_offset): Corrct the handling of user-defined operators
+ delete.
+ (maybe_emit_free_warning): Avoid assuming expression is a decl.
+ Simplify.
+ * doc/extend.texi (attribute malloc): Update.
+ * tree-ssa-dce.c (valid_new_delete_pair_p): Factor code out into
+ valid_new_delete_pair_p in tree.c.
+ * tree.c (tree_inlined_location): Define new function.
+ (valid_new_delete_pair_p): Define.
+ * tree.h (tree_inlined_location): Declare.
+ (valid_new_delete_pair_p): Declare.
+
+2020-12-14 Sebastian Pop <spop@amazon.com>
+
+ * config.gcc (aarch64*-*-*): Remove --with-{cpu,arch,tune}-32 flags.
+
+2020-12-14 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config.gcc (aarch64*-*-*): Add --with-tune. Support --with-cpu=native.
+ * config/aarch64/aarch64.h (OPTION_DEFAULT_SPECS): Add --with-tune.
+
+2020-12-14 Martin Liska <mliska@suse.cz>
+
+ * gcov.c (output_json_intermediate_file): Update comments.
+
+2020-12-14 Tamar Christina <tamar.christina@arm.com>
+
+ PR middle-end/98264
+ * tree-vect-slp-patterns.c (linear_loads_p): Exclude TOP permute.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/mve.md (mve_vnegq_f): Use 'neg' instead of unspec.
+ (mve_vnegq_s): Likewise.
+ * config/arm/neon.md (neg<mode>2): Rename into neon_neg<mode>2.
+ (<absneg_str><mode>2): Rename into neon_<absneg_str><mode>2.
+ (neon_v<absneg_str><mode>): Call gen_neon_<absneg_str><mode>2.
+ (vashr<mode>3): Call gen_neon_neg<mode>2.
+ (vlshr<mode>3): Call gen_neon_neg<mode>2.
+ (neon_vneg<mode>): Call gen_neon_neg<mode>2.
+ * config/arm/unspecs.md (VNEGQ_F, VNEGQ_S): Remove.
+ * config/arm/vec-common.md (neg<mode>2): New expander.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/iterators.md (VDQNOTM2): New mode iterator.
+ (supf): Remove VMVNQ_S and VMVNQ_U.
+ (VMVNQ): Remove.
+ * config/arm/mve.md (mve_vmvnq_u<mode>): New entry for vmvn
+ instruction using expression not.
+ (mve_vmvnq_s<mode>): New expander.
+ * config/arm/neon.md (one_cmpl<mode>2): Renamed into
+ one_cmpl<mode>2_neon.
+ * config/arm/unspecs.md (VMVNQ_S, VMVNQ_U): Remove.
+ * config/arm/vec-common.md (one_cmpl<mode>2): New expander.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/iterators.md (supf): Remove VBICQ_S and VBICQ_U.
+ (VBICQ): Remove.
+ * config/arm/mve.md (mve_vbicq_u<mode>): New entry for vbic
+ instruction using expression and not.
+ (mve_vbicq_s<mode>): New expander.
+ (mve_vbicq_f<mode>): Replace use of unspec by 'and not'.
+ * config/arm/unspecs.md (VBICQ_S, VBICQ_U, VBICQ_F): Remove.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/iterators.md (supf): Remove VEORQ_S and VEORQ_U.
+ (VEORQ): Remove.
+ * config/arm/mve.md (mve_veorq_u<mode>): New entry for veor
+ instruction using expression xor.
+ (mve_veorq_s<mode>): New expander.
+ (mve_veorq_f<mode>): Use 'xor' code instead of unspec.
+ * config/arm/neon.md (xor<mode>3): Renamed into xor<mode>3_neon.
+ * config/arm/unspecs.md (VEORQ_S, VEORQ_U, VEORQ_F): Remove.
+ * config/arm/vec-common.md (xor<mode>3): New expander.
+
+2020-12-14 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): Add Cortex-A78C core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Update docs.
+
+2020-12-14 Nikhil Benesch <nikhil.benesch@gmail.com>
+
+ * godump.c (go_output_typedef): Suppress typedefs whose name
+ matches the tag of the underlying struct, union, or enum.
+ Output declarations for enums that do not appear in typedefs.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_output_int_move): Unify push operation
+ selection.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_output_int_move): Check the correct
+ operand for constant 0 push operation.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_expand_addsub_di_operands): Handle equal
+ input operands with subtraction.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_expand_addsub_di_operands): Handle the
+ addition or subtraction of 0.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_expand_addsub_di_operands): Remove
+ unused register allocation.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (casesi): Use `gen_int_mode' rather than
+ `GEN_INT' for the immediate used for lower bound adjustment.
+
+2020-12-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98256
+ * tree-ssa-math-opts.c (match_uaddsub_overflow): For BIT_NOT_EXPR,
+ only handle a single use, and insert .ADD_OVERFLOW before the
+ comparison rather than after the BIT_NOT_EXPR. Return true iff
+ it is BIT_NOT_EXPR and it has been removed.
+ (math_opts_dom_walker::after_dom_children) <case BIT_NOT_EXPR>:
+ If match_uaddsub_overflow returned true, continue instead of break.
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ Revert:
+ 2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm_mve.h (__arm_vcaddq_rot90_u8, __arm_vcaddq_rot270_u8,
+ , __arm_vcaddq_rot90_s8, __arm_vcaddq_rot270_s8,
+ __arm_vcaddq_rot90_u16, __arm_vcaddq_rot270_u16, __arm_vcaddq_rot90_s16,
+ __arm_vcaddq_rot270_s16, __arm_vcaddq_rot90_u32,
+ __arm_vcaddq_rot270_u32, __arm_vcaddq_rot90_s32,
+ __arm_vcaddq_rot270_s32, __arm_vcmulq_rot90_f16,
+ __arm_vcmulq_rot270_f16, __arm_vcmulq_rot180_f16,
+ __arm_vcmulq_f16, __arm_vcaddq_rot90_f16, __arm_vcaddq_rot270_f16,
+ __arm_vcmulq_rot90_f32, __arm_vcmulq_rot270_f32,
+ __arm_vcmulq_rot180_f32, __arm_vcmulq_f32, __arm_vcaddq_rot90_f32,
+ __arm_vcaddq_rot270_f32, __arm_vcmlaq_f16, __arm_vcmlaq_rot180_f16,
+ __arm_vcmlaq_rot270_f16, __arm_vcmlaq_rot90_f16, __arm_vcmlaq_f32,
+ __arm_vcmlaq_rot180_f32, __arm_vcmlaq_rot270_f32,
+ __arm_vcmlaq_rot90_f32): Update builtin calls.
+ * config/arm/arm_mve_builtins.def (vcaddq_rot90_u, vcaddq_rot270_u,
+ vcaddq_rot90_s, vcaddq_rot270_s, vcaddq_rot90_f, vcaddq_rot270_f,
+ vcmulq_f, vcmulq_rot90_f, vcmulq_rot180_f, vcmulq_rot270_f,
+ vcmlaq_f, vcmlaq_rot90_f, vcmlaq_rot180_f, vcmlaq_rot270_f): Removed.
+ (vcaddq_rot90, vcaddq_rot270, vcmulq, vcmulq_rot90, vcmulq_rot180,
+ vcmulq_rot270, vcmlaq, vcmlaq_rot90, vcmlaq_rot180, vcmlaq_rot270):
+ New.
+ * config/arm/constraints.md (Dz): Include MVE.
+ * config/arm/iterators.md (mve_rotsplit1, mve_rotsplit2): New.
+ (rot): Add UNSPEC_VCMLS, UNSPEC_VCMUL and UNSPEC_VCMUL180.
+ (rot_op, rotsplit1, rotsplit2, fcmac1, VCMLA_OP, VCMUL_OP): New.
+ * config/arm/mve.md (VCADDQ_ROT270_S, VCADDQ_ROT90_S, VCADDQ_ROT270_U,
+ VCADDQ_ROT90_U, VCADDQ_ROT270_F, VCADDQ_ROT90_F, VCMULQ_F,
+ VCMULQ_ROT180_F, VCMULQ_ROT270_F, VCMULQ_ROT90_F, VCMLAQ_F,
+ VCMLAQ_ROT180_F, VCMLAQ_ROT90_F, VCMLAQ_ROT270_F, VCADDQ_ROT270_S,
+ VCADDQ_ROT270, VCADDQ_ROT90): Removed.
+ (mve_rot, VCMUL): New.
+ (mve_vcaddq_rot270_<supf><mode, mve_vcaddq_rot90_<supf><mode>,
+ mve_vcaddq_rot270_f<mode>, mve_vcaddq_rot90_f<mode>, mve_vcmulq_f<mode,
+ mve_vcmulq_rot180_f<mode>, mve_vcmulq_rot270_f<mode>,
+ mve_vcmulq_rot90_f<mode>, mve_vcmlaq_f<mode>, mve_vcmlaq_rot180_f<mode>,
+ mve_vcmlaq_rot270_f<mode>, mve_vcmlaq_rot90_f<mode>): Removed.
+ (mve_vcmlaq<mve_rot><mode>, mve_vcmulq<mve_rot><mode>,
+ mve_vcaddq<mve_rot><mode>, cadd<rot><mode>3, mve_vcaddq<mve_rot><mode>):
+ New.
+ (cmul<rot_op><mode>3): Exclude MVE types.
+ * config/arm/unspecs.md (UNSPEC_VCMUL90, UNSPEC_VCMUL270): New.
+ * config/arm/vec-common.md (cadd<rot><mode>3, cmul<rot_op><mode>3,
+ arm_vcmla<rot><mode>, cml<fcmac1><rot_op><mode>4): New.
+ * config/arm/unspecs.md (UNSPEC_VCMUL, UNSPEC_VCMUL180, UNSPEC_VCMLS,
+ UNSPEC_VCMLS180): New.
+ * config/arm/neon.md (cmul<rot_op><mode>3): New.
+
+2020-12-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/92469
+ * varasm.c (eliminable_regno_p): New function.
+ (make_decl_rtl): Reject asm vars for frame and argp
+ if they are different from hard frame pointer.
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm_mve.h (__arm_vcaddq_rot90_u8, __arm_vcaddq_rot270_u8,
+ , __arm_vcaddq_rot90_s8, __arm_vcaddq_rot270_s8,
+ __arm_vcaddq_rot90_u16, __arm_vcaddq_rot270_u16, __arm_vcaddq_rot90_s16,
+ __arm_vcaddq_rot270_s16, __arm_vcaddq_rot90_u32,
+ __arm_vcaddq_rot270_u32, __arm_vcaddq_rot90_s32,
+ __arm_vcaddq_rot270_s32, __arm_vcmulq_rot90_f16,
+ __arm_vcmulq_rot270_f16, __arm_vcmulq_rot180_f16,
+ __arm_vcmulq_f16, __arm_vcaddq_rot90_f16, __arm_vcaddq_rot270_f16,
+ __arm_vcmulq_rot90_f32, __arm_vcmulq_rot270_f32,
+ __arm_vcmulq_rot180_f32, __arm_vcmulq_f32, __arm_vcaddq_rot90_f32,
+ __arm_vcaddq_rot270_f32, __arm_vcmlaq_f16, __arm_vcmlaq_rot180_f16,
+ __arm_vcmlaq_rot270_f16, __arm_vcmlaq_rot90_f16, __arm_vcmlaq_f32,
+ __arm_vcmlaq_rot180_f32, __arm_vcmlaq_rot270_f32,
+ __arm_vcmlaq_rot90_f32): Update builtin calls.
+ * config/arm/arm_mve_builtins.def (vcaddq_rot90_u, vcaddq_rot270_u,
+ vcaddq_rot90_s, vcaddq_rot270_s, vcaddq_rot90_f, vcaddq_rot270_f,
+ vcmulq_f, vcmulq_rot90_f, vcmulq_rot180_f, vcmulq_rot270_f,
+ vcmlaq_f, vcmlaq_rot90_f, vcmlaq_rot180_f, vcmlaq_rot270_f): Removed.
+ (vcaddq_rot90, vcaddq_rot270, vcmulq, vcmulq_rot90, vcmulq_rot180,
+ vcmulq_rot270, vcmlaq, vcmlaq_rot90, vcmlaq_rot180, vcmlaq_rot270):
+ New.
+ * config/arm/constraints.md (Dz): Include MVE.
+ * config/arm/iterators.md (mve_rotsplit1, mve_rotsplit2): New.
+ (rot): Add UNSPEC_VCMLS, UNSPEC_VCMUL and UNSPEC_VCMUL180.
+ (rot_op, rotsplit1, rotsplit2, fcmac1, VCMLA_OP, VCMUL_OP): New.
+ * config/arm/mve.md (VCADDQ_ROT270_S, VCADDQ_ROT90_S, VCADDQ_ROT270_U,
+ VCADDQ_ROT90_U, VCADDQ_ROT270_F, VCADDQ_ROT90_F, VCMULQ_F,
+ VCMULQ_ROT180_F, VCMULQ_ROT270_F, VCMULQ_ROT90_F, VCMLAQ_F,
+ VCMLAQ_ROT180_F, VCMLAQ_ROT90_F, VCMLAQ_ROT270_F, VCADDQ_ROT270_S,
+ VCADDQ_ROT270, VCADDQ_ROT90): Removed.
+ (mve_rot, VCMUL): New.
+ (mve_vcaddq_rot270_<supf><mode, mve_vcaddq_rot90_<supf><mode>,
+ mve_vcaddq_rot270_f<mode>, mve_vcaddq_rot90_f<mode>, mve_vcmulq_f<mode,
+ mve_vcmulq_rot180_f<mode>, mve_vcmulq_rot270_f<mode>,
+ mve_vcmulq_rot90_f<mode>, mve_vcmlaq_f<mode>, mve_vcmlaq_rot180_f<mode>,
+ mve_vcmlaq_rot270_f<mode>, mve_vcmlaq_rot90_f<mode>): Removed.
+ (mve_vcmlaq<mve_rot><mode>, mve_vcmulq<mve_rot><mode>,
+ mve_vcaddq<mve_rot><mode>, cadd<rot><mode>3, mve_vcaddq<mve_rot><mode>):
+ New.
+ (cmul<rot_op><mode>3): Exclude MVE types.
+ * config/arm/unspecs.md (UNSPEC_VCMUL90, UNSPEC_VCMUL270): New.
+ * config/arm/vec-common.md (cadd<rot><mode>3, cmul<rot_op><mode>3,
+ arm_vcmla<rot><mode>, cml<fcmac1><rot_op><mode>4): New.
+ * config/arm/unspecs.md (UNSPEC_VCMUL, UNSPEC_VCMUL180, UNSPEC_VCMLS,
+ UNSPEC_VCMLS180): New.
+ * config/arm/neon.md (cmul<rot_op><mode>3): New.
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm.c (arm_preferred_simd_mode): Add E_HFmode.
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-slp-patterns.c: New file.
+ * Makefile.in: Add it.
+ * doc/passes.texi: Document it.
+ * internal-fn.def (COMPLEX_ADD_ROT90, COMPLEX_ADD_ROT270): New.
+ * optabs.def (cadd90_optab, cadd270_optab): New.
+ * doc/md.texi: Document them.
+ * tree-vect-loop.c (vect_analyze_loop_2): Add dissolve code.
+ * tree-vect-slp.c:
+ (vect_free_slp_instance, vect_create_new_slp_node): Export.
+ (vect_match_slp_patterns_2, vect_match_slp_patterns): New.
+ (vect_analyze_slp): Use it.
+ * tree-vectorizer.h (vect_free_slp_tree): Export.
+ (enum _complex_operation): Forward declare.
+ (class vect_pattern): New
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-patterns.c (vect_mark_pattern_stmts): Remove static inline.
+ * tree-vect-slp.c (vect_create_new_slp_node): Remove static and only
+ set smts if valid.
+ * tree-vectorizer.c (vec_info::add_pattern_stmt): New.
+ (vec_info::set_vinfo_for_stmt): Optionally enforce read-only.
+ * tree-vectorizer.h (struct _slp_tree): Use new types.
+ (lane_permutation_t, lane_permutation_t): New.
+ (vect_create_new_slp_node, vect_mark_pattern_stmts): New.
+
+2020-12-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * doc/sourcebuild.texi (Commands for use in dg-final, Scan the
+ assembly output, scan-assembler-symbol-section): Document.
+ (scan-symbol-section): Document.
+
+2020-12-13 Richard Sandiford <richard.sandiford@arm.com>
+
+ * is-a.h (reinterpret_is_a_helper): New class.
+ (static_is_a_helper): Likewise.
+ (is_a_helper): Inherit from reinterpret_is_a_helper.
+ (is_a_helper<const T *>): New specialization.
+
+2020-12-13 Richard Sandiford <richard.sandiford@arm.com>
+
+ * coretypes.h (iterator_range): Move to...
+ * iterator-utils.h: ...this new file.
+
+2020-12-13 Richard Sandiford <richard.sandiford@arm.com>
+
+ * rtlanal.c (noop_move_p): Don't check for REG_EQUAL notes.
+
+2020-12-13 Richard Sandiford <richard.sandiford@arm.com>
+
+ * vec.h (vnull::operator vec<T, A, L>): Make const.
+
+2020-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96685
+ * match.pd (~(X - Y) -> ~X + Y): New optimization.
+ (~X + Y -> (Y - X) - 1): Likewise.
+
+2020-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96272
+ * tree-ssa-math-opts.c (uaddsub_overflow_check_p): Add OTHER argument.
+ Handle BIT_NOT_EXPR.
+ (match_uaddsub_overflow): Optimize unsigned a > ~b into
+ __imag__ .ADD_OVERFLOW (a, b).
+ (math_opts_dom_walker::after_dom_children): Call match_uaddsub_overflow
+ even for BIT_NOT_EXPR.
+
+2020-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98183
+ * omp-low.c (lower_omp_target): Don't add OMP_RETURN for
+ data regions.
+ * omp-expand.c (expand_omp_target): Don't try to remove
+ OMP_RETURN for data regions.
+ (build_omp_regions_1, omp_make_gimple_edges): Don't expect
+ OMP_RETURN for data regions.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.c (cpp_unique_options): Add Mmodules, Mno-modules.
+ * tree-core.h (enum tree_index): Add TI_MODULE_HWM.
+
+2020-12-11 Jim Wilson <jimw@sifive.com>
+
+ * varasm.c (get_section): Add DECL_P check before DECL_PRESERVE_P.
+
+2020-12-11 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/iterators.md (VDQ): Remove TARGET_HAVE_MVE
+ conditions.
+ * config/arm/vec-common.md (and<mode>3): Use
+ ARM_HAVE_<MODE>_ARITH.
+ (ior<mode>3): Likewise.
+
+2020-12-11 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_active_insn): Ignore all non essential
+ instructions when getting the next active instruction.
+ (check_store_cacheline_hazard): Update.
+ (workaround_arc_anomaly): Remove obsolete cache hazard code.
+
+2020-12-11 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_reorg): Avoid limm in BRcc.
+
+2020-12-11 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc-protos.h (arc_scheduling_not_expected): Remove
+ it.
+ (arc_sets_cc_p): Likewise.
+ (arc_need_delay): Likewise.
+ * config/arc/arc.c (arc_sets_cc_p): Likewise.
+ (arc_need_delay): Likewise.
+ (arc_scheduling_not_expected): Likewise.
+ * config/arc/arc.md: Convert adc/sbc patterns to simple
+ instruction definitions.
+
+2020-12-11 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/iterators.md (supf): Remove VORRQ_S and VORRQ_U.
+ (VORRQ): Remove.
+ * config/arm/mve.md (mve_vorrq_s<mode>): New entry for vorr
+ instruction using expression ior.
+ (mve_vorrq_u<mode>): New expander.
+ (mve_vorrq_f<mode>): Use ior code instead of unspec.
+ * config/arm/neon.md (ior<mode>3): Renamed into ior<mode>3_neon.
+ * config/arm/predicates.md (imm_for_neon_logic_operand): Enable
+ for MVE.
+ * config/arm/unspecs.md (VORRQ_S, VORRQ_U, VORRQ_F): Remove.
+ * config/arm/vec-common.md (ior<mode>3): New expander.
+
+2020-12-11 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (mpyd<su_optab>_arcv2hs): New template
+ pattern.
+ (*pmpyd<su_optab>_arcv2hs): Likewise.
+ (*pmpyd<su_optab>_imm_arcv2hs): Likewise.
+ (mpyd_arcv2hs): Moved into above template.
+ (mpyd_imm_arcv2hs): Moved into above template.
+ (mpydu_arcv2hs): Likewise.
+ (mpydu_imm_arcv2hs): Likewise.
+ (su_optab): New optab prefix for sign/zero-extending operations.
+
+2020-12-11 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98219
+ * config/i386/uintrintrin.h (__uintr_frame): Remove uirrv.
+
+2020-12-11 Andrea Corallo <andrea.corallo@arm.com>
+
+ * doc/sourcebuild.texi (arm_softfloat): Improve documentation.
+
+2020-12-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98229
+ * optabs.c (expand_doubleword_mod): Canonicalize op1 and
+ 1 - INTVAL (op1) as word_mode constants when used in
+ word_mode arithmetics.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98235
+ * tree-vect-slp.c (vect_build_slp_tree): Exchange npermutes
+ for limit. Decrement that for each cache miss and fail
+ discovery when it reaches zero.
+ (vect_build_slp_tree_2): Remove npermutes handling and
+ simply pass down limit.
+ (vect_build_slp_instance): Use pass down limit.
+ (vect_analyze_slp_instance): Likewise.
+ (vect_analyze_slp): Base the SLP discovery limit on
+ max_tree_size and pass it down.
+
+2020-12-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98190
+ * expr.c (expand_assignment): If to_rtx is a promoted SUBREG,
+ ensure sign or zero extension either through use of store_expr
+ or by extending manually.
+
+2020-12-11 Andrea Corallo <andrea.corallo@arm.com>
+
+ PR rtl-optimization/97092
+ * ira-color.c (update_costs_from_allocno): Do not carry over mode
+ between subsequent iterations.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/95582
+ * tree-vect-patterns.c (vect_recog_bool_pattern): Check
+ for VECT_SCALAR_BOOLEAN_TYPE_P, not just precision one.
+
+2020-12-11 Hongyu <hongyu.wang@intel.com>
+
+ * common/config/i386/cpuinfo.h (get_available_features):
+ Move check for HRESET/AVX_VNNI/UINTR out of avx512_usable.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98212
+ * dojump.c (do_compare_rtx_and_jump): Change computation of
+ first_prob for and_them. Add comment explaining and_them case.
+
+2020-12-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/98174
+ * gimple-range-cache.cc (ranger_cache::ssa_range_in_bb): Only push
+ poor values to be examined if it isn't a pure global.
+ (ranger_cache::block_range): Don't process pure globals.
+ (ranger_cache::fill_block_cache): Adjust has_edge_range call.
+ * gimple-range-gori.cc (gori_map::all_outgoing): New bitmap.
+ (gori_map::gori_map): Allocate all_outgoing.
+ (gori_map::is_export_p): No specified BB returns global context.
+ (gori_map::calculate_gori): Accumulate each block into global.
+ (gori_compute::gori_compute): Preprocess each block for exports.
+ (gori_compute::has_edge_range_p): No edge returns global context.
+ * gimple-range-gori.h (has_edge_range_p): Provide default parameter.
+
+2020-12-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * dwarf2out.c (loc_list_from_tree_1) <PLACEHOLDER_EXPR>: Deal with
+ a nested context type
+
+2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * cfgexpand.c (expand_gimple_basic_block): Remove special handling
+ of debug_inline_entries without block info.
+ * tree-inline.c (remap_gimple_stmt): Drop debug_nonbind_markers when
+ the call statement has no block info.
+ (copy_debug_stmt): Remove debug_nonbind_markers when inlining
+ and the block info is mapped to NULL.
+ * tree-ssa-live.c (clear_unused_block_pointer): Remove
+ debug_nonbind_markers originating from removed inline functions.
+
+2020-12-10 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.c (vectorizable_assignment): Remove special
+ allowance of VECTOR_BOOLEAN_TYPE_P conversions.
+
+2020-12-10 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/iterators.md (supf): Remove VANDQ_S and VANDQ_U.
+ (VANQ): Remove.
+ (VDQ): Add TARGET_HAVE_MVE condition where relevant.
+ * config/arm/mve.md (mve_vandq_u<mode>): New entry for vand
+ instruction using expression 'and'.
+ (mve_vandq_s<mode>): New expander.
+ (mve_vaddq_n_f<mode>): Use 'and' code instead of unspec.
+ * config/arm/neon.md (and<mode>3): Rename into and<mode>3_neon.
+ * config/arm/predicates.md (imm_for_neon_inv_logic_operand):
+ Enable for MVE.
+ * config/arm/unspecs.md (VANDQ_S, VANDQ_U, VANDQ_F): Remove.
+ * config/arm/vec-common.md (and<mode>3): New expander.
+
+2020-12-10 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/98069
+ * tree-data-ref.c (compute_distributive_range): New function.
+ (nop_conversion_for_offset_p): Likewise.
+ (split_constant_offset): In the internal overload, treat integer
+ expressions as having an implicit cast to sizetype and express
+ them accordingly. Pass back the range of the original (uncast)
+ expression in a new range parameter.
+ (split_constant_offset_1): Likewise. Rework the handling of
+ conversions to account for the implicit sizetype casts.
+
+2020-12-10 Joel Hutton <joel.hutton@arm.com>
+
+ PR tree-optimization/97929
+ * tree-vect-data-refs.c (vect_get_smallest_scalar_type): Add
+ WIDEN_PLUS/WIDEN_MINUS case.
+
+2020-12-10 Joel Hutton <joel.hutton@arm.com>
+
+ * tree-pretty-print.c (dump_generic_node): Add case for
+ VEC_WIDEN_(PLUS/MINUS)_(HI/LO)_EXPR and WIDEN_(PLUS/MINUS)_EXPR.
+
+2020-12-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98211
+ * tree-vect-stmts.c (vectorizable_assignment): Disallow
+ invalid conversions to bool vector types.
+
+2020-12-10 Alexandre Oliva <oliva@adacore.com>
+
+ * tree.c (build_common_builtin_nodes): Drop __builtin_ from
+ __clear_cache libname.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98212
+ * dojump.c (do_compare_rtx_and_jump): When splitting NE and backend
+ can do UNEQ, prefer splitting x != y into x unord y || !(x uneq y)
+ instead of into x unord y || x ltgt y.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98169
+ * dojump.c (do_compare_rtx_and_jump): Don't split self-EQ/NE
+ comparisons, just use ORDERED or UNORDERED.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98205
+ * omp-expand.c (expand_omp_for_generic): Fix up broken_loop handling.
+
+2020-12-10 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Do
+ not mark the defs to occur in a pattern if it is the
+ pattern root and record the original stmt defs in that
+ case.
+
+2020-12-10 Simon Cook <simon.cook@embecosm.com>
+
+ * config/riscv/multilib-generator (arch_canonicalize): Invoke
+ python interpreter when calling arch-canonicalize script.
+
+2020-12-10 Nikhil Benesch <nikhil.benesch@gmail.com>
+
+ * godump.c (go_format_type): Don't consider whether a type has
+ been seen when determining whether to output a type by name.
+ Consider only the use_type_name parameter.
+ (go_output_typedef): When outputting a typedef, format the
+ declaration's original type, which contains the name of the
+ underlying type rather than the name of the typedef.
+
+2020-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/98188
+ * tree-ssa-phiopt.c (two_value_replacement): Don't special case
+ BOOLEAN_TYPEs for ranges, instead if get_range_info doesn't return
+ VR_RANGE, set min/max to wi::min/max_value.
+
+2020-12-09 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-option-extensions.def
+ (AARCH64_OPT_EXTENSION): New +pauth option in -march for AArch64.
+ * config/aarch64/aarch64.h (AARCH64_FL_PAUTH): New pauth extension bitmask.
+ (AARCH64_ISA_PUATH): New ISA bitmask for PAUTH.
+ (AARCH64_FL_FOR_ARCH8_3): Add PAUTH to Armv8.3-A.
+ (TARGET_PAUTH): New target mask to isolate PAUTH instructions.
+ * config/aarch64/aarch64.md (do_return): Condition set to TARGET_PAUTH.
+ * doc/invoke.texi: Update docs for +flagm and +pauth.
+
+2020-12-09 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (REG_ALLOC_ORDER): Remove
+
+2020-12-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98213
+ * tree-ssa-loop-im.c (sm_seq_valid_bb): Cache successfully
+ processed PHIs.
+ (hoist_memory_references): Adjust.
+
+2020-12-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64-protos.h (cpu_vector_cost): Move simd
+ fields to...
+ (simd_vec_cost): ... Here. Define.
+ (advsimd_vec_cost): Define.
+ (sve_vec_cost): Define.
+ * config/aarch64/aarch64.c (generic_advsimd_vector_cost):
+ Define.
+ (generic_sve_vector_cost): Likewise.
+ (generic_vector_cost): Update.
+ (qdf24xx_advsimd_vector_cost): Define.
+ (qdf24xx_vector_cost): Update.
+ (thunderx_advsimd_vector_cost): Define.
+ (thunderx_vector_cost): Update.
+ (tsv110_advsimd_vector_cost): Define.
+ (tsv110_vector_cost): Likewise.
+ (cortexa57_advsimd_vector_cost): Define.
+ (cortexa57_vector_cost): Update.
+ (exynosm1_advsimd_vector_cost): Define.
+ (exynosm1_vector_cost): Update.
+ (xgene1_advsimd_vector_cost): Define.
+ (xgene1_vector_cost): Update.
+ (thunderx2t99_advsimd_vector_cost): Define.
+ (thunderx2t99_vector_cost): Update.
+ (thunderx3t110_advsimd_vector_cost): Define.
+ (thunderx3t110_vector_cost): Update.
+ (aarch64_builtin_vectorization_cost): Handle sve and advsimd
+ vector cost fields.
+
+2020-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98199
+ * fold-const.c (native_encode_initializer): Fix handling bit-fields
+ when off > 0.
+
+2020-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98193
+ * fold-const.c (native_encode_initializer): Set pos to field's
+ byte position if iterating over a field with missing initializer.
+
+2020-12-08 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98182
+ * gimple-if-to-switch.cc (pass_if_to_switch::execute): Request
+ chain linkage through false edges only.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * tree.h (DECL_ALIGN_RAW): New.
+ (DECL_ALIGN): Use it.
+ (DECL_WARN_IF_NOT_ALIGN_RAW): New.
+ (DECL_WARN_IF_NOT_ALIGN): Use it.
+ (SET_DECL_WARN_IF_NOT_ALIGN): Likewise.
+
+2020-12-08 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/66791
+ * config/arm/arm_neon.h: Replace calls to __builtin_vmvn* by ~
+ in vmvn intrinsics.
+ * config/arm/arm_neon_builtins.def: Remove entry for vmvn.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/94440
+ * config/i386/i386.opt (ix86_excess_precision,
+ ix86_unsafe_math_optimizations): New TargetVariables.
+ * config/i386/i386.h (X87_ENABLE_ARITH, X87_ENABLE_FLOAT): Use
+ ix86_unsafe_math_optimizations instead of
+ flag_unsafe_math_optimizations and ix86_excess_precision instead of
+ flag_excess_precision.
+ * config/i386/i386.c (ix86_excess_precision): Rename to ...
+ (ix86_get_excess_precision): ... this.
+ (TARGET_C_EXCESS_PRECISION): Define to ix86_get_excess_precision.
+ * config/i386/i386-options.c (ix86_valid_target_attribute_tree,
+ ix86_option_override_internal): Update ix86_unsafe_math_optimization
+ from flag_unsafe_math_optimizations and ix86_excess_precision
+ from flag_excess_precision when constructing target option nodes.
+ (ix86_set_current_function): If flag_unsafe_math_optimizations
+ or flag_excess_precision is different from the one recorded
+ in TARGET_OPTION_NODE, create a new target option node for the
+ current function and switch to that.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98192
+ * tree-vect-slp.c (vect_build_slp_instance): Get scalar_stmts
+ by reference.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98191
+ * tree-vect-slp.c (vect_slp_check_for_constructors): Do not
+ follow a non-SSA def chain.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97559
+ * tree-ssa-sink.c (statement_sink_location): Never ignore
+ PHIs on sink paths in irreducible regions.
+
+2020-12-08 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/97872
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Try to fold
+ x CMP y ? -1 : 0 to x CMP y.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98180
+ * tree-vect-slp.c (vect_slp_check_for_constructors): Check the
+ first inserted value has a def.
+
+2020-12-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR tree-optimization/96344
+ * tree-switch-conversion.c (bit_test_cluster::emit): Compute the
+ range only if an entry test is necessary. Merge the entry test in
+ the bit test when possible. Use PREC local variable consistently.
+ When there is only one test, do a single gimplification at the end.
+
+2020-12-08 Kito Cheng <kito.cheng@sifive.com>
+
+ PR target/98152
+ * config.gcc (riscv*-*-*): Checking python, python3 or python2
+ is available, and skip doing with_arch canonicalize if no python
+ available.
+
+2020-12-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98147
+ * builtins.c (default_emit_call_builtin___clear_cache): Call
+ convert_memory_address to ptr_mode on both begin and end.
+
+2020-12-07 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * ipa-param-manipulation.c
+ (ipa_param_body_adjustments::modify_call_stmt): Set location info.
+
+2020-12-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * doc/extend.texi (used function attribute): Document saving
+ the declaration from linker garbage collection.
+ (used variable attribute): Likewise.
+
+2020-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98113
+ * tree-vectorizer.h (struct slp_root): New.
+ (_bb_vec_info::roots): New member.
+ * tree-vect-slp.c (vect_analyze_slp): Also walk BB info
+ roots.
+ (_bb_vec_info::_bb_vec_info): Adjust.
+ (_bb_vec_info::~_bb_vec_info): Likewise.
+ (vld_cmp): New.
+ (vect_slp_is_lane_insert): Likewise.
+ (vect_slp_check_for_constructors): Match a series of
+ BIT_INSERT_EXPRs as vector constructor.
+ (vect_slp_analyze_bb_1): Continue if BB info roots is
+ not empty.
+ (vect_slp_analyze_bb_1): Mark the whole BIT_INSERT_EXPR root
+ sequence as pure_slp.
+
+2020-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98117
+ * tree-vect-loop-manip.c (vect_gen_vector_loop_niters):
+ Properly handle degenerate niter when setting the vector
+ loop IV range.
+
+2020-12-07 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.c (s390_emit_stack_probe): Change Pmode to
+ word_mode.
+
+2020-12-07 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/97816
+ * ipa-cp.c (safe_add): Removed.
+ (good_cloning_opportunity_p): Remove special handling of INT_MAX.
+ (value_topo_info<valtype>::propagate_effects): Take care not to
+ propagate from size one value to another through more sources. Scale
+ propagated times with edge frequencies. Include local time and size
+ in propagates ones here. Take care not to overflow size.
+ (decide_about_value): Do not add local and propagated effects when
+ passing them to good_cloning_opportunity_p.
+
+2020-12-07 Matthias Klose <doko@ubuntu.com>
+
+ * genextract.c (print_header): Undefine ENABLE_RTL_CHECKING
+ and ENABLE_RTL_FLAG_CHECKING.
+
+2020-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98137
+ * tree-data-ref.c (split_constant_offset_1): Use
+ determine_value_range instead of get_range_info to handle
+ arbitrary expressions.
+
+2020-12-06 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98162
+ * doc/extend.texi: Remove -mcet.
+
+2020-12-06 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98161
+ * config/i386/i386-features.c (pseudo_reg_set): Check mode of
+ pseudo register push.
+
+2020-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96232
+ * tree-ssa-phiopt.c (two_value_replacement): Optimize even boolean lhs
+ cases as long as arg0 has wider precision and conditional_replacement
+ doesn't handle that case.
+ (tree_ssa_phiopt_worker): Don't call two_value_replacement during
+ early phiopt.
+
+2020-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96232
+ * match.pd (-(type)!A -> (type)A - 1): New optimization.
+
+2020-12-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+ David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/xcoff.h (ASM_OUTPUT_DEF): Reference macro arguments.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ PR target/95294
+ * config/vax/elf.h (REGISTER_NAMES): Append `%psl'.
+ * config/vax/vax-modes.def (CCN, CCNZ, CCZ): New modes.
+ * config/vax/vax-protos.h (vax_select_cc_mode): New prototype.
+ (vax_maybe_split_dimode_move): Likewise.
+ (vax_notice_update_cc): Remove prototype.
+ * config/vax/vax.c (TARGET_FLAGS_REGNUM): New macro.
+ (TARGET_CC_MODES_COMPATIBLE): Likewise.
+ (TARGET_MD_ASM_ADJUST): Likewise.
+ (vax_select_cc_mode): New function
+ (vax_cc_modes_compatible): Likewise.
+ (vax_md_asm_adjust): Likewise.
+ (vax_notice_update_cc): Remove function.
+ (vax_output_int_move): Factor out code checking if a DImode move
+ may have to be split...
+ (vax_maybe_split_dimode_move): ... into this new function.
+ * config/vax/vax.h (FIRST_PSEUDO_REGISTER): Bump up.
+ (FIXED_REGISTERS): Append an entry for PSL.
+ (CALL_USED_REGISTERS): Likewise.
+ (NOTICE_UPDATE_CC, OUTPUT_JUMP): Remove macros.
+ (SELECT_CC_MODE): New macro.
+ (REGISTER_NAMES): Append `psl'.
+ * config/vax/predicates.md (const_zero_operand)
+ (vax_cc_comparison_operator, vax_ccn_comparison_operator)
+ (vax_ccnz_comparison_operator, vax_ccz_comparison_operator):
+ New predicates.
+ * config/vax/builtins.md: Rewrite for MODE_CC representation.
+ * config/vax/vax.md: Likewise.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/elf.h (VAX_CC1_SPEC, VAX_CC1PLUS_SPEC): New macros.
+ * config/vax/netbsd-elf.h (CC1_SPEC): Use VAX_CC1_SPEC rather
+ than VAX_CC1_AND_CC1PLUS_SPEC.
+ (CC1PLUS_SPEC): Use VAX_CC1PLUS_SPEC rather than
+ VAX_CC1_AND_CC1PLUS_SPEC.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/pdp11/pdp11.md (fcc_cc, fcc_ccnz): Use
+ `const_double_zero' to express double zero constant.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * read-rtl.c (rtx_reader::read_rtx_code): Handle syntactic
+ `const_double_zero' rtx.
+ * doc/rtl.texi (Constant Expression Types): Document it.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (divmoddisi4, *amulsi4): Make the comment
+ notation consistent with the rest of the file.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (movti): Fix output predicate. Emit `movo'
+ rather than `movh'.
+ (divmoddisi4): Fix output predicates, correct RTL.
+ (*amulsi4): Name insn. Fix output predicate.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (mulsidi3): Fix the multiplicand predicates.
+ (*maddsidi4, *maddsidi4_const): Likewise. Name insns.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (*cmpv_2): Name insn.
+ (*cmpv, *cmpzv, *cmpzv_2): Likewise. Fix location predicate and
+ constraint.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (extv): Rename insn to...
+ (*extv): ... this.
+ (extv): New expander.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (*insv_aligned, *extzv_aligned)
+ (*extv_aligned): Also make sure the memory address of a bit-field
+ location can be adjusted in the PIC mode.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (*insv_aligned, *extzv_aligned)
+ (*extv_aligned): Reject register bit-field locations that are not
+ aligned to the least significant bit; update output statement
+ accordingly.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (*insv_aligned, *extzv_aligned)
+ (*extv_aligned, *extv_non_const, *extzv_non_const): Name insns.
+ Fix location predicate.
+ (*extzv): Name insn.
+ (*insv): Likewise. Fix location constraint.
+ (*insv_2): Likewise, and the predicate.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md (cpymemhi1): Rename insn to...
+ (movmemhi1): ... this.
+ (cpymemhi): Update accordingly. Remove constraints.
+ (movmemhi): New expander.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/builtins.md: Add a peephole2 for QImode and HImode
+ `ctz' operations.
+ (any_extend): New code iterator.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/builtins.md (width): New mode attribute.
+ (ffssi2): Rework expander into...
+ (ffs<mode>2): ... this.
+ (ctzsi2): Rework insn into...
+ (ctz<mode>2): ... this.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/builtins.md (ffssi2_internal): Rename insn to...
+ (ctzsi2): ... this. Update the RTL operation.
+ (ffssi2): Update accordingly.
+ * config/vax/vax.c (vax_notice_update_cc): Handle CTZ.
+ * config/vax/vax.h (CTZ_DEFINED_VALUE_AT_ZERO): New macro.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.md: Include `builtins.md'.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/predicates.md (volatile_mem_operand)
+ (any_memory_operand): New predicates.
+ * config/vax/builtins.md (VUNSPEC_UNLOCK): Remove constant.
+ (sync_lock_test_and_set<mode>): Remove `set' and `unspec'
+ operations, match operands only. Reformat.
+ (sync_lock_release<mode>): Likewise. Remove cruft.
+ (jbb<ccss>i<mode>): Wrap into `unspec_volatile', use
+ `any_memory_operand' predicate.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/builtins.md (bit): New int iterator.
+ (ccss): New int attribute.
+ (jbbssi<mode>, jbbcci<mode>): Fold insns into...
+ (jbb<ccss>i<mode>): ... this.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/builtins.md (bb_mem): New mode attribute.
+ (jbbssiqi, jbbssihi, jbbssisi): Fold insns into...
+ (jbbssi<mode>): ... this.
+ (jbbcciqi, jbbccihi, jbbccisi): Likewise...
+ (jbbcci<mode>): ... this.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * jump.c (pc_set): Also accept a jump wrapped in UNSPEC or
+ UNSPEC_VOLATILE.
+ (any_uncondjump_p, any_condjump_p): Update comment accordingly.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * loop-doloop.c (add_test): Only remove the jump if `onlyjump_p'.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * cfgrtl.c (rtl_block_empty_p): Return false if `!onlyjump_p'
+ too.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * sel-sched-ir.c (maybe_tidy_empty_bb): Only try to remove a
+ conditional jump if `onlyjump_p'.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * loop-iv.c (simplify_using_initial_values): Only process jumps
+ that match `onlyjump_p'.
+ (check_simple_exit): Likewise.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * ifcvt.c (dead_or_predicable) [!IFCVT_MODIFY_TESTS]: Bail out
+ if `!onlyjump_p'.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * read-rtl.c: Add a page-feed separator at the start of iterator
+ code.
+ (struct iterator_group): Change the return type to HOST_WIDE_INT
+ for the `find_builtin' member. Likewise the second parameter
+ type for the `apply_iterator' member.
+ (atoll) [!HAVE_ATOQ]: Reorder.
+ (find_mode, find_code): Change the return type to HOST_WIDE_INT.
+ (apply_mode_iterator, apply_code_iterator)
+ (apply_subst_iterator): Change the second parameter type to
+ HOST_WIDE_INT.
+ (find_int): Handle input suitable for HOST_WIDE_INT output.
+ (apply_int_iterator): Rewrite in terms of explicit format
+ interpretation.
+ (rtx_reader::read_rtx_operand) <'w'>: Fold into...
+ <'i', 'n', 'p'>: ... this.
+ * doc/md.texi (Int Iterators): Document 'w' rtx format support.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/builtins.md (ffssi2): Make preparation statements
+ actually buildable.
+ (ffssi2_internal): Fix input constraints; make the RTL pattern
+ match reality for `cc0'.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_address_cost): Express the cost in terms
+ of COSTS_N_INSNS.
+ (vax_rtx_costs): Likewise.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/constraints.md (A): New constraint.
+ * config/vax/predicates.md (external_symbolic_operand)
+ (external_const_operand): Remove predicates.
+ (local_symbolic_operand): Rename to...
+ (pic_symbolic_operand): ... this, and rework.
+ (external_memory_operand): Rename to...
+ (non_pic_external_memory_operand): ... this, and rework.
+ (illegal_blk_memory_operand, illegal_addsub_di_memory_operand):
+ Update accordingly.
+ * config/vax/vax-protos.h (vax_acceptable_pic_operand_p): New
+ prototype.
+ * config/vax/vax.c (vax_acceptable_pic_operand_p): New function.
+ (vax_output_int_add): Update according to predicate rework.
+ * config/vax/vax.h (LEGITIMATE_PIC_OPERAND_P): New macro.
+ * config/vax/vax.md (pushlclsymreg, pushextsymreg): Fold
+ together, and rename to...
+ (*pushsymreg): ... this. Use the `pic_symbolic_operand'
+ predicate and the `A' constraint for the displacement operand.
+ (movlclsymreg, movextsymreg): Fold together, and rename to...
+ (*movsymreg): ... this. Use the `pic_symbolic_operand'
+ predicate and the `A' constraint for the displacement operand.
+ (pushextsym, pushlclsym): Fold together, and rename to...
+ (*pushsym): ... this. Use the `pic_symbolic_operand' predicate
+ and the `A' constraint for the displacement operand.
+ (movextsym, movlclsym): Fold together, and rename to...
+ (*movsym): ... this. Use the `pic_symbolic_operand' predicate
+ and the `A' constraint for the displacement operand.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (print_operand): Replace `c' and `C' with
+ `k' and `K' respectively.
+ * config/vax/vax.md (*branch, *branch_reversed): Update
+ accordingly.
+
+2020-12-05 Matt Thomas <matt@3am-software.com>
+ Maciej W. Rozycki <macro@linux-mips.org>
+
+ PR target/58901
+ * reload.c (push_reload): Also reload the inner expression of a
+ SUBREG for pseudos associated with a mode-dependent memory
+ reference.
+ (find_reloads): Force a reload likewise.
+
+2020-12-05 Roman Zhuykov <zhroma@ispras.ru>
+
+ PR rtl-optimization/97421
+ * modulo-sched.c (generate_prolog_epilog): Remove forward
+ declaration, adjust last argument name and type.
+ (const_iteration_count): Add bool pointer parameter to return
+ whether count register is read in pre-header after its
+ initialization.
+ (sms_schedule): Fix count register initialization adjustment
+ procedure according to what const_iteration_count said.
+
+2020-12-05 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/97865
+ * configure: Regenerate.
+
+2020-12-05 Venkataramanan Kumar <Venkataramanan.Kumar@amd.com>
+ Sharavan Kumar <Shravan.Kumar@amd.com>
+
+ * common/config/i386/cpuinfo.h (get_amd_cpu) recognize znver3.
+ * common/config/i386/i386-common.c (processor_names): Add
+ znver3.
+ (processor_alias_table): Add znver3 and AMDFAM19H entry.
+ * common/config/i386/i386-cpuinfo.h (processor_types): Add
+ AMDFAM19H.
+ (processor_subtypes): AMDFAM19H_ZNVER3.
+ * config.gcc (i[34567]86-*-linux* | ...): Likewise.
+ * config/i386/driver-i386.c: (host_detect_local_cpu): Let
+ -march=native recognize znver3 processors.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Add
+ znver3.
+ * config/i386/i386-options.c (m_znver3): New definition.
+ (m_ZNVER): Include m_znver3.
+ (processor_cost_table): Add znver3.
+ * config/i386/i386.c (ix86_reassociation_width): Likewise.
+ * config/i386/i386.h (TARGET_znver3): New definition.
+ (enum processor_type): Add PROCESSOR_ZNVER3.
+ * config/i386/i386.md (define_attr "cpu"): Add znver3.
+ * config/i386/x86-tune-sched.c: (ix86_issue_rate): Likewise.
+ (ix86_adjust_cost): Likewise.
+ * config/i386/x86-tune.def (X86_TUNE_AVOID_256FMA_CHAINS:
+ Likewise.
+ * config/i386/znver1.md: Add new reservations for znver3.
+ * doc/extend.texi: Add details about znver3.
+ * doc/invoke.texi: Likewise.
+
+2020-12-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/96226
+ * config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask,
+ splitter after *<rotate_insn><mode>3_mask_1): Drop the masking from
+ the patterns to split into.
+
+2020-12-04 Jason Merrill <jason@redhat.com>
+
+ * vec.h (begin, end): Add overloads for vec*.
+ * tree.c (build_constructor_from_vec): Remove *.
+
+2020-12-04 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Change PTR_SIZE to POINTER_SIZE_UNITS.
+
+2020-12-04 Hans-Peter Nilsson <hp@axis.com>
+ Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/94600
+ * doc/implement-c.texi (Qualifiers implementation): Add blurb
+ about access to the whole of a volatile aggregate object, only for
+ same-size as a scalar object.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98130
+ * gimple.c (gimple_call_fnspec): Only return ".co " for replaceable
+ operator delete or ".mC" for replaceable operator new called from
+ new/delete.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/96226
+ * config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask,
+ splitter after *<rotate_insn><mode>3_mask_1): New combine splitters.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * fold-const.c (native_encode_initializer): Use build_zero_cst
+ instead of build_constructor.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98100
+ * cfgexpand.c (expand_gimple_basic_block): For vars with
+ vector type, use TYPE_MODE rather than DECL_MODE.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ * common.opt (-gdwarf32, -gdwarf64): New options.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Default
+ dwarf_offset_size to 8 if not overridden from the command line.
+ * dwarf2out.c: Change all occurrences of DWARF_OFFSET_SIZE to
+ dwarf_offset_size.
+ * doc/invoke.texi (-gdwarf32, -gdwarf64): Document.
+
+2020-12-04 Martin Liska <mliska@suse.cz>
+
+ * doc/tm.texi: Change argument of the record_gcc_switches
+ hook and remove SWITCH_TYPE_* enum values.
+ * dwarf2out.c (gen_producer_string): Move to opts.c and remove
+ handling of the dwarf_record_gcc_switches option.
+ (dwarf2out_early_finish): Use moved gen_producer_string
+ function.
+ * opts.c (gen_producer_string): New.
+ * opts.h (gen_producer_string): New.
+ * target.def: Change type of record_gcc_switches.
+ * target.h (enum print_switch_type): Remove.
+ (elf_record_gcc_switches): Change first argument.
+ * toplev.c (MAX_LINE): Remove.
+ (print_to_asm_out_file): Likewise.
+ (print_to_stderr): Likewise.
+ (print_single_switch): Likewise.
+ (print_switch_values): Likewise.
+ (init_asm_output): Use new gen_producer_string function.
+ (process_options): Likewise.
+ * varasm.c (elf_record_gcc_switches): Just save the string argument
+ to the ELF container.
+
+2020-12-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * ipa-sra.c (verify_access_tree_1): Relax assertion on the size.
+
+2020-12-04 Martin Liska <mliska@suse.cz>
+
+ * doc/invoke.texi: Add missing params.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * builtins.c (access_ref::access_ref): Initialize new member.
+ (compute_objsize): Use access_ref::deref. Handle simple pointer
+ assignment.
+ (expand_builtin): Remove handling of the free built-in.
+ (call_dealloc_argno): Same.
+ (find_assignment_location): New function.
+ (fndecl_alloc_p): Same.
+ (gimple_call_alloc_p): Same.
+ (call_dealloc_p): Same.
+ (matching_alloc_calls_p): Same.
+ (warn_dealloc_offset): Same.
+ (maybe_emit_free_warning): Same.
+ * builtins.h (struct access_ref): Declare new member.
+ (maybe_emit_free_warning): Make extern. Make use of access_ref.
+ Handle -Wmismatched-new-delete.
+ * calls.c (initialize_argument_information): Call
+ maybe_emit_free_warning.
+ * doc/extend.texi (attribute malloc): Update.
+ * doc/invoke.texi (-Wfree-nonheap-object): Expand documentation.
+ (-Wmismatched-new-delete): Document new option.
+ (-Wmismatched-dealloc): Document new option.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * tree.c (build_common_builtin_nodes): Declare
+ __builtin___clear_cache for all languages.
+ * builtins.c (maybe_emit_call_builtin___clear_cache): Accept
+ Pmode arguments.
+
+2020-12-03 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/arm/t-rtems: Add "-mthumb -mcpu=cortex-r52
+ -mfloat-abi=hard" multilib.
+
+2020-12-03 Uroš Bizjak <ubizjak@gmail.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98086
+ * config/i386/i386.c (ix86_md_asm_adjustmd): Rewrite
+ zero-extension part to use convert_to_mode.
+
+2020-12-03 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.md ("@probe_stack2<mode>"): Change mode
+ iterator to W.
+
+2020-12-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve-builtins-base.cc (svundef_impl::fold):
+ Delete.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/98099
+ * expmed.c (flip_storage_order): In the case of a non-integer mode,
+ sorry out if the integer mode to be used instead is not supported.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/98082
+ * function.c (use_register_for_decl): Also return true for a result
+ if cfun->tail_call_marked is true.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * fold-const.h (native_encode_initializer): Add mask argument
+ defaulted to nullptr.
+ (find_bitfield_repr_type): Declare.
+ (native_interpret_aggregate): Declare.
+ * fold-const.c (find_bitfield_repr_type): New function.
+ (native_encode_initializer): Add mask argument and support for
+ filling it. Handle also some bitfields without integral
+ DECL_BIT_FIELD_REPRESENTATIVE.
+ (native_interpret_aggregate): New function.
+ * gimple-fold.h (clear_type_padding_in_mask): Declare.
+ * gimple-fold.c (struct clear_padding_struct): Add clear_in_mask
+ member.
+ (clear_padding_flush): Handle buf->clear_in_mask.
+ (clear_padding_union): Copy clear_in_mask. Don't error if
+ buf->clear_in_mask is set.
+ (clear_padding_type): Don't error if buf->clear_in_mask is set.
+ (clear_type_padding_in_mask): New function.
+ (gimple_fold_builtin_clear_padding): Set buf.clear_in_mask to false.
+ * doc/extend.texi (__builtin_bit_cast): Document.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-threadedge.c (record_temporary_equivalences_from_stmts_at_dest):
+ Do not allow __builtin_constant_p on a threading path.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-strlen.c (printf_strlen_execute): Avoid division by
+ 0.
+
+2020-12-03 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/multilib-generator (arch_canonicalize): Move
+ code to arch-canonicalize, and call that script to canonicalize arch
+ string.
+ (canonical_order): Move code to arch-canonicalize.
+ (LONG_EXT_PREFIXES): Ditto.
+ (IMPLIED_EXT): Ditto.
+ * config/riscv/arch-canonicalize: New.
+ * config.gcc (riscv*-*-*): Canonicalize --with-arch.
+
+2020-12-03 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-option-extensions.def
+ (AARCH64_OPT_EXTENSION): New +flagm option in -march for AArch64.
+ * config/aarch64/aarch64.h (AARCH64_FL_FLAGM): Add new flagm extension bit
+ mask.
+ (AARCH64_FL_FOR_ARCH8_4): Add flagm to Armv8.4-A.
+ * doc/invoke.texi: Update docs with +flagm.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ PR target/96906
+ * config/i386/sse.md
+ (<avx512>_ucmp<mode>3<mask_scalar_merge_name>): Add a new
+ define_split after this insn.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ PR target/97642
+ * config/i386/i386-expand.c
+ (ix86_expand_special_args_builtin): Don't move all-ones mask
+ operands into register.
+ * config/i386/sse.md (UNSPEC_MASKLOAD): New unspec.
+ (*<avx512>_load<mode>_mask): New define_insns for masked load
+ instructions.
+ (<avx512>_load<mode>_mask): Changed to define_expands which
+ specifically handle memory or all-ones mask operands.
+ (<avx512>_blendm<mode>): Changed to define_insns which are same
+ as original <avx512>_load<mode>_mask with adjustment of
+ operands order.
+ (*<avx512>_load<mode>): New define_insn_and_split which is
+ used to optimize for masked load with all one mask.
+
+2020-12-03 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/97770
+ * config/i386/sse.md (popcount<mode>2): New expander
+ for SI/DI vector modes.
+ (popcount<mode>2): Likewise for QI/HI vector modes.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * builtins.c (default_emit_call_builtin___clear_cache): New.
+ (maybe_emit_call_builtin___clear_cache): New.
+ (expand_builtin___clear_cache): Split into the above.
+ (expand_builtin): Do not issue clear_cache call any more.
+ * builtins.h (maybe_emit_call_builtin___clear_cache): Declare.
+ * config/aarch64/aarch64.c (aarch64_trampoline_init): Use
+ maybe_emit_call_builtin___clear_cache.
+ * config/arc/arc.c (arc_trampoline_init): Likewise.
+ * config/arm/arm.c (arm_trampoline_init): Likewise.
+ * config/c6x/c6x.c (c6x_initialize_trampoline): Likewise.
+ * config/csky/csky.c (csky_trampoline_init): Likewise.
+ * config/m68k/linux.h (FInALIZE_TRAMPOLINE): Likewise.
+ * config/tilegx/tilegx.c (tilegx_trampoline_init): Likewise.
+ * config/tilepro/tilepro.c (tilepro_trampoline_init): Ditto.
+ * config/vxworks.c: Include rtl.h, memmodel.h, and optabs.h.
+ (vxworks_emit_call_builtin___clear_cache): New.
+ * config/vxworks.h (CLEAR_INSN_CACHE): Drop.
+ (TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE): Define.
+ * target.def (trampoline_init): In the documentation, refer to
+ maybe_emit_call_builtin___clear_cache.
+ (emit_call_builtin___clear_cache): New.
+ * doc/tm.texi.in: Add new hook point.
+ (CLEAR_CACHE_INSN): Remove duplicate 'both'.
+ * doc/tm.texi: Rebuilt.
+ * targhooks.h (default_meit_call_builtin___clear_cache):
+ Declare.
+ * tree.h (BUILTIN_ASM_NAME_PTR): New.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * tree-ssa-threadbackward.c (thread_jumps::profitable_jump_thread_path):
+ Do not allow __builtin_constant_p on a threading path.
+
+2020-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (add_scalar_info): Only use add_AT_wide for 128-bit
+ constants and only in dwarf-5 or later, where DW_FORM_data16 is
+ available. Otherwise use DW_FORM_block*/DW_FORM_exprloc with
+ DW_OP_implicit_value to describe the constant.
+
+2020-12-02 qing zhao <qinzhao@gcc.gnu.org>
+
+ PR rtl-optimization/97777
+ * reg-stack.c (rest_of_handle_stack_regs): call
+ df_insn_rescan_all if reg_to_stack return true.
+
+2020-12-02 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390-protos.h (s390_const_int_pool_entry_p): New
+ function.
+ * config/s390/s390.c (s390_const_int_pool_entry_p): New
+ function.
+ * config/s390/s390.md: Add define_peephole2 that produces llihf
+ and oilf.
+
+2020-12-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97630
+ * tree-vectorizer.h (_slp_tree::next_node,
+ _slp_tree::prev_node): New.
+ (vect_slp_init): Declare.
+ (vect_slp_fini): Likewise.
+ * tree-vectorizer.c (vectorize_loops): Call vect_slp_init/fini.
+ (pass_slp_vectorize::execute): Likewise.
+ * tree-vect-slp.c (vect_slp_init): New.
+ (vect_slp_fini): Likewise.
+ (slp_first_node): New global.
+ (_slp_tree::_slp_tree): Link node into the SLP tree list.
+ (_slp_tree::~_slp_tree): Delink node from the SLP tree list.
+
+2020-12-02 Scott Snyder <sss@li-snyder.org>
+
+ PR plugins/98059
+ * vec.h (auto_delete_vec): Use
+ DISABLE_COPY_AND_ASSIGN(auto_delete_vec) instead of
+ DISABLE_COPY_AND_ASSIGN(auto_delete_vec<T>) to make it valid C++20
+ after DR2237.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR ipa/98075
+ * cgraph.c (cgraph_node::dump): Dump decl_is_malloc flag.
+ * ipa-pure-const.c (propagate_malloc): Do not set malloc
+ attribute for void functions.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+
+ PR middle-end/93195
+ PR middle-end/93197
+ * configure.ac (HAVE_GAS_SECTION_LINK_ORDER): New. Define 1 if
+ the assembler supports the section flag 'o' for specifying
+ section with link-order.
+ * output.h (SECTION_LINK_ORDER): New. Defined to 0x8000000.
+ (SECTION_MACH_DEP): Changed from 0x8000000 to 0x10000000.
+ * targhooks.c (default_print_patchable_function_entry): Pass
+ SECTION_LINK_ORDER to switch_to_section if the section flag 'o'
+ works. Pass current_function_decl to switch_to_section.
+ * varasm.c (default_elf_asm_named_section): Use 'o' flag for
+ SECTION_LINK_ORDER if assembler supports it.
+ * config.in: Regenerated.
+ * configure: Likewise.
+ * doc/sourcebuild.texi: Document o_flag_in_section.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+
+ * config/i386/i386.opt: Add the missing '.' for -mneeded.
+
+2020-12-02 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-loop.c (vect_transform_loop_stmt): Return whether
+ we vectorized a stmt.
+ (vect_transform_loop): Only call maybe_set_vectorized_backedge_value
+ when we vectorized the stmt.
+
+2020-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ * expmed.h (expand_divmod): Only declare if GCC_OPTABS_H is defined.
+ Add enum optabs_method argument defaulted to OPTAB_LIB_WIDEN.
+ * expmed.c: Include expmed.h after optabs.h.
+ (expand_divmod): Add methods argument, if it is not OPTAB_{,LIB_}WIDEN,
+ don't choose a wider mode, and pass it to other calls instead of
+ hardcoded OPTAB_LIB_WIDEN. Avoid emitting libcalls if not
+ OPTAB_LIB or OPTAB_LIB_WIDEN.
+ * optabs.c: Include expmed.h after optabs.h.
+ (expand_doubleword_mod, expand_doubleword_divmod): Pass OPTAB_DIRECT
+ as last argument to expand_divmod.
+ (expand_binop): Punt if {s,u}divmod_optab has handler for double-word
+ int_mode.
+ * expr.c: Include expmed.h after optabs.h.
+ * explow.c: Include expmed.h after optabs.h.
+
+2020-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97459
+ * optabs.h (expand_doubleword_divmod): Declare.
+ * optabs.c (expand_doubleword_divmod): New function.
+ (expand_binop): Use it.
+ * internal-fn.c (expand_DIVMOD): Likewise.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR c/98087
+ * gimple-fold.c (clear_padding_type): Do not divide by zero.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ * gdbinit.in: Write what each command calls
+ for a debugging function.
+
+2020-12-02 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Use OPTION_MASK_DIRECT_MOVE for Power8 target_enable instead
+ of OPTION_MASK_HTM.
+ * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_SERVER):
+ Remove OPTION_MASK_HTM.
+ (RS6000_CPU): Add OPTION_MASK_HTM to power8, power9 and
+ powerpc64le entries.
+
+2020-12-02 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/98079
+ * config/i386/i386.md (abs<mode>2): Enable QImode
+ only for !TARGET_PARTIAL_REG_STALL.
+ (*abs<mode>2_1): Ditto.
+ (<maxmin:code><mode>3): Ditto.
+ (*<maxmin:code><mode>3_1): Ditto.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ * diagnostic.c (diagnostic_report_diagnostic): ICE causes to
+ terminate compiler immediately, so I guess it should be printed
+ always.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/88702
+ * gimple-if-to-switch.cc (pass_if_to_switch::execute):
+ Require at least 2 BBs.
+ * gimple-if-to-switch.cc (find_conditions): Require
+ equal precision for low and high of a range.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98084
+ * gimple-if-to-switch.cc (find_conditions): Consider only
+ integral types.
+
+2020-12-02 Jeff Law <law@redhat.com>
+
+ * config/h8300/addsub.md (addqi3_clobber_flags): Rename to
+ addqi3_flags and annotate with a <cczn> for define_subst.
+ (addhi3_h8sx_clobber_flags): Likewise.
+ (subqi3_clobber_flags, sub<mode>3_clobber_flags): Likewise.
+ (neg<mode2>_clobber_flags): Similarly.
+ (addsi3_clobber_flags): Similarly. Update last argument to
+ output_plussi to distinguish when we need flags or do not need
+ flags.
+ (addhi3_clobber_flags): Similarly. Twiddle code for cases
+ +-1, +-2 and +-4.
+ * config/h8300/h8300.md: Define iterators, mode attributes and
+ substitutions for use in compare/test elimination.
+ * config/h8300/jumpcall.md (branch, branch_1): Use H8cc mode
+ iterator to cover the different modes for the CC register.
+ (branch_1_false): Likewise.
+
+2020-12-02 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * loop-iv.c: Fix a typo, s/bu/by/, in the `iv_analyze_expr'
+ description in the introduction.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+
+ * configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
+ the assembler supports marking sections with SHF_GNU_RETAIN flag.
+ * output.h (SECTION_RETAIN): New. Defined as 0x4000000.
+ (SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
+ (default_unique_section): Add a bool argument.
+ * varasm.c (get_section): Set SECTION_RETAIN for the preserved
+ symbol with HAVE_GAS_SHF_GNU_RETAIN.
+ (resolve_unique_section): Used named section for the preserved
+ symbol if assembler supports SHF_GNU_RETAIN.
+ (get_variable_section): Handle the preserved common symbol with
+ HAVE_GAS_SHF_GNU_RETAIN.
+ (default_elf_asm_named_section): Require the full declaration and
+ use the 'R' flag for SECTION_RETAIN.
+ * config.in: Regenerated.
+ * configure: Likewise.
+ * doc/sourcebuild.texi: Document R_flag_in_section.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+
+ * config.gcc: Replace cet.o with gnu-property.o. Replace
+ i386/t-cet with i386/t-gnu-property.
+ * config/i386/cet.c: Renamed to ...
+ * config/i386/gnu-property.c: This.
+ (emit_gnu_property): New function.
+ (file_end_indicate_exec_stack_and_cet): Renamed to ...
+ (file_end_indicate_exec_stack_and_gnu_property): This. Call
+ emit_gnu_property to generate GNU_PROPERTY_X86_FEATURE_1_AND and
+ GNU_PROPERTY_X86_ISA_1_NEEDED properties.
+ * config/i386/i386.opt (mneeded): New.
+ * config/i386/linux-common.h (file_end_indicate_exec_stack_and_cet):
+ Renamed to ...
+ (file_end_indicate_exec_stack_and_gnu_property): This.
+ (TARGET_ASM_FILE_END): Updated.
+ * config/i386/t-cet: Renamed to ...
+ * config/i386/t-gnu-property: This.
+ (cet.o): Renamed to ...
+ (gnu-property.o): This.
+ * doc/invoke.texi: Document -mneeded.
+
+2020-12-01 Eugene Rozenfeld <Eugene.Rozenfeld@microsoft.com>
+
+ PR tree-optimization/96708
+ * match.pd: New pattern for comparing X with MAX (X, Y)
+ or MIN (X, y).
+
+2020-12-01 Jeff Law <law@redhat.com>
+
+ * config/mcore/t-mcore (MULTILIB_EXCEPTIONS): Define.
+
+2020-12-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97595
+ * tree.c (component_ref_size): Fail when DECL_SIZE != TYPE_SIZE.
+ * tree.h (DECL_SIZE, TYPE_SIZE): Update comment.
+
+2020-12-01 JeanHeyd Meneide <phdofthehouse@gmail.com>
+
+ * doc/cpp.texi: Document new macros.
+
+2020-12-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97373
+ * builtins.c (compute_objsize): Rename...
+ (compute_objsize_r): to this. Change order and types of arguments.
+ Use new argument. Adjust calls to self.
+ (access_ref::get_ref): New member function.
+ (pointer_query::pointer_query): New member function.
+ (pointer_query::get_ref): Same.
+ (pointer_query::put_ref): Same.
+ (handle_min_max_size): Change order and types of arguments.
+ (maybe_emit_free_warning): Add a test.
+ * builtins.h (class pointer_query): New class.
+ (compute_objsize): Declare an overload.
+ * gimple-ssa-sprintf.c (get_destination_size): Add argument.
+ (handle_printf_call): Change argument type.
+ * tree-ssa-strlen.c (adjust_last_stmt): Add an argument and use it.
+ (maybe_warn_overflow): Same.
+ (handle_builtin_strcpy): Same.
+ (maybe_diag_stxncpy_trunc): Same.
+ (handle_builtin_memcpy): Change argument type. Adjust calls.
+ (handle_builtin_strcat): Same.
+ (handle_builtin_memset): Same.
+ (handle_store): Same.
+ (strlen_check_and_optimize_call): Same.
+ (check_and_optimize_stmt): Same.
+ (strlen_dom_walker): Add new data members.
+ (strlen_dom_walker::before_dom_children): Use new member.
+ (printf_strlen_execute): Dump cache performance counters. Remove
+ objsize pass cleanup.
+ * tree-ssa-strlen.h (maybe_diag_stxncpy_trunc): Add argument.
+ (handle_printf_call): Change argument type.
+
+2020-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * function.c (gen_call_used_regs_seq): In a function subject to the
+ leaf register optimization, skip registers that are not present.
+ * config/sparc/sparc.c (TARGET_ZERO_CALL_USED_REGS): Define to...
+ (sparc_zero_call_used_regs): ...this. New function.
+
+2020-12-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h: Remove unused 'X' specs in the link spec
+ rather than driver self-specs.
+
+2020-12-01 Nathan Sidwell <nathan@acm.org>
+
+ * params.opt (lazy-modules): New.
+ * timevar.def (TV_MODULE_IMPORT, TV_MODULE_EXPORT)
+ (TV_MODULE_MAPPER): New.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97459
+ * optabs.c (expand_doubleword_mod): Punt early for even op1.
+ (expand_binop): Don't require lshr_optab double-word handler.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97954
+ * loop-invariant.c (find_invariant_insn): Punt on JUMP_P insns.
+
+2020-12-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * configure.ac (check leb128 support): Check that assemblers both
+ accept the LEB128 directives and also give the expected output.
+ Add a test for uleb128 with the MSB set for a 64 bit value.
+ * configure: Regenerated.
+
+2020-12-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * configure: Regnerated.
+
+2020-12-01 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * optabs-tree.c (vec_cmp_icode_p): New function.
+ (vec_cmp_eq_icode_p): New function.
+ (expand_vec_cmp_expr_p): Use vec_cmp_icode_p and
+ vec_cmp_eq_icode_p.
+ (vcond_icode_p): Use get_rtx_code_1, just to be uniform with
+ vec_cmp_icode_p.
+ * optabs.c (unsigned_optab_p): New function.
+ (insn_predicate_matches_p): New function.
+ (can_vec_cmp_compare_p): New function.
+ (can_vcond_compare_p): Use unsigned_optab_p and
+ insn_predicate_matches_p.
+ (get_rtx_code): Use get_rtx_code_1.
+ (get_rtx_code_1): Version of get_rtx_code that returns UNKNOWN
+ instead of asserting.
+ * optabs.h (can_vec_cmp_compare_p): New function.
+ (get_rtx_code_1): New function.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/14799
+ PR ipa/88702
+ * Makefile.in: Add gimple-if-to-switch.o.
+ * dbgcnt.def (DEBUG_COUNTER): Add new debug counter.
+ * passes.def: Include new pass_if_to_switch pass.
+ * timevar.def (TV_TREE_IF_TO_SWITCH): New timevar.
+ * tree-pass.h (make_pass_if_to_switch): New.
+ * tree-ssa-reassoc.c (struct operand_entry): Move to the header.
+ (dump_range_entry): Move to header file.
+ (debug_range_entry): Likewise.
+ (no_side_effect_bb): Make it global.
+ * tree-switch-conversion.h (simple_cluster::simple_cluster):
+ Add inline for couple of functions in order to prevent error
+ about multiple defined symbols.
+ * gimple-if-to-switch.cc: New file.
+ * tree-ssa-reassoc.h: New file.
+
+2020-12-01 Marius Hillenbrand <mhillen@linux.ibm.com>
+
+ * configure.ac: Add configure option
+ --enable-s390-excess-float-precision and check to derive default
+ from glibc.
+ * config/s390/s390.c: Guard s390_excess_precision with an ifdef
+ for ENABLE_S390_EXCESS_FLOAT_PRECISION.
+ * doc/install.texi: Document --enable-s390-excess-float-precision.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ PR ipa/98057
+ * symtab.c (symtab_node::set_section_for_node): Drop
+ implicit_section if x_section is NULL.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98063
+ * config/i386/i386-expand.c (ix86_expand_call): Handle non-plt
+ CM_LARGE_PIC calls.
+
+2020-12-01 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/98070
+ * builtins.c (builtin_fnspec): realloc is ".Cw ".
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (gen_compile_unit_die): Treat GNU C++20
+ like C++14 for -gdwarf-5.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/97989
+ * gcc.c (cpp_unique_options): Add -dD if %:debug-level-gt(2)
+ rather than g3|ggdb3|gstabs3|gxcoff3|gvms3.
+
+2020-12-01 Kito Cheng <kito.cheng@sifive.com>
+
+ * config.gcc (riscv*-*-*): Drop some commited accidentally code.
+
+2020-11-30 Jeff Law <law@redhat.com>
+
+ * symtab.c (set_section_for_node): Add function comment.
+ (set_section_from_node): Likewise.
+
+2020-11-30 David Malcolm <dmalcolm@redhat.com>
+
+ * doc/plugins.texi (Plugin callbacks): Add PLUGIN_ANALYZER_INIT.
+ * plugin.c (register_callback): Likewise.
+ (invoke_plugin_callbacks_full): Likewise.
+ * plugin.def (PLUGIN_ANALYZER_INIT): New event.
+
+2020-11-30 Jeff Law <law@redhat.com>
+
+ * config/h8300/bitfield.md: Remove "cc" attribute on any
+ insns where it remained.
+ * config/h8300/combiner.md: Likewise.
+ * config/h8300/jumpcall.md: Likewise.
+ * config/h8300/logical.md: Likewise.
+ * config/h8300/testcompare.md: Likewise.
+ * config/h8300/h8300.md (old_cc attr): Renamed from cc attr.
+ * config/h8300/h8300.c (notice_update_cc): Remove.
+ (compute_plussi_cc): Change references to CC_* to OLD_CC_.
+ (compute_logical_op_cc): Likewise.
+ (shift_one, shift_two): Likewise.
+ (compute_a_shift_cc): Likewise.
+ (get_shift_alg): Likewise.
+ (struct shift_insn): Change type of cc_valid field.
+ (struct shift_info): Likewise.
+ * config/h8300/save.md: Remove accidentially created file.
+
+2020-11-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR rtl-optimization/98037
+ * dse.c (find_shift_sequence): Iterate over all integers and
+ skip modes that are too small.
+
+2020-11-30 Eugene Rozenfeld <Eugene.Rozenfeld@microsoft.com>
+
+ PR tree-optimization/96679
+ * match.pd (((b | c) & a) | b -> (a & c) | b): New pattern.
+
+2020-11-30 Martin Liska <mliska@suse.cz>
+
+ * passes.c (emergency_dump_function): Dump symtab when
+ we are in an IPA pass.
+
+2020-11-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98064
+ * tree-vect-loop.c (vectorizable_live_operation): Avoid
+ breaking LC SSA for BB vectorization.
+
+2020-11-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/sourcebuild.texi (Directives): Fix description of
+ dg-require-effective-target to include "target" in selector.
+
+2020-11-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98048
+ * tree-vect-generic.c (expand_vector_operations_1): Use the
+ correct type for the scalar LHS replacement.
+
+2020-11-30 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98066
+ * gimple-isel.cc (gimple_expand_vec_exprs): Return when
+ gimple_expand_vec_exprs replaces last stmt.
+
+2020-11-30 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * cfgrtl.c (rtl_bb_info_initialized_p): New function.
+ (rtl_dump_bb): Use rtl_bb_info_initialized_p before accessing bb
+ insns.
+
+2020-11-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/87818
+ * config.gcc (*-*-freebsd*): Add freebsd-d.o and t-freebsd.
+ * config/freebsd-d.c: New file.
+ * config/t-freebsd: New file.
+
+2020-11-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97459
+ * internal-fn.h (expand_addsub_overflow): Declare.
+ * internal-fn.c (expand_addsub_overflow): No longer static.
+ * optabs.c (expand_doubleword_mod): New function.
+ (expand_binop): Optimize double-word mod with constant divisor.
+
+2020-11-30 Kito Cheng <kito.cheng@sifive.com>
+
+ * config.gcc (riscv*-*-*): Add TARGET_RISCV_DEFAULT_ABI and
+ TARGET_RISCV_DEFAULT_ARCH to tm_defines.
+ Remove including riscv/withmultilib.h for --with-multilib-list.
+ * config/riscv/riscv.h (STRINGIZING): New.
+ (__STRINGIZING): Ditto.
+ (MULTILIB_DEFAULTS): Ditto.
+ * config/riscv/withmultilib.h: Remove.
+
+2020-11-30 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.c (print_multilib_info): Check default arguments not
+ appeared in multi-lib option list with '!'
+
+2020-11-30 Jeff Law <law@redhat.com>
+
+ * config/ft32/ft32.md (umulsidi3): Do not allow constants as
+ arguments.
+
+2020-11-29 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (ipa_merge_modref_summary_after_inlining): Fix
+ handling of ignore_stores.
+
+2020-11-29 Jan Hubicka <jh@suse.cz>
+
+ PR jit/97867
+ * symtab-thunks.h (thunk_info::release): Use ggc_delete.
+
+2020-11-29 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/92936
+ PR middle-end/92940
+ PR middle-end/89428
+ * builtins.c (access_ref::access_ref): Initialize member.
+ (access_ref::phi): New function.
+ (access_ref::get_ref): New function.
+ (access_ref::add_offset): Remove duplicate assignment.
+ (maybe_warn_for_bound): Add "maybe" kind of warning messages.
+ (warn_for_access): Same.
+ (inform_access): Rename...
+ (access_ref::inform_access): ...to this. Print PHI arguments. Format
+ offset the same as size and simplify. Improve printing of allocation
+ functions and VLAs.
+ (check_access): Adjust to the above.
+ (gimple_parm_array_size): Change argument.
+ (handle_min_max_size): New function.
+ * builtins.h (class ssa_name_limit_t): Move class here from
+ tree-ssa-strlen.c.
+ (struct access_ref): Declare new members.
+ (gimple_parm_array_size): Change argument.
+ * tree-ssa-strlen.c (maybe_warn_overflow): Use access_ref and simplify.
+ (handle_builtin_memcpy): Correct argument passed to maybe_warn_overflow.
+ (handle_builtin_memset): Same.
+ (class ssa_name_limit_t): Move class to builtins.{h,c}.
+
+2020-11-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * config.gcc (*-*-darwin*): Set d_target_objs and target_has_targetdm.
+ * config/elfos.h (TARGET_D_MINFO_SECTION): New macro.
+ (TARGET_D_MINFO_START_NAME): New macro.
+ (TARGET_D_MINFO_END_NAME): New macro.
+ * config/t-darwin: Add darwin-d.o.
+ * doc/tm.texi: Regenerate.
+ * doc/tm.texi.in (D language and ABI): Add @hook for
+ TARGET_D_MINFO_SECTION, TARGET_D_MINFO_START_NAME, and
+ TARGET_D_MINFO_END_NAME.
+ * config/darwin-d.c: New file.
+
+2020-11-29 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-structalias.c (handle_pure_call): Skip EAF_UNUSED
+ parameters.
+
+2020-11-29 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (modref_lattice::merge): Do nothing if F is EAF_UNUSED.
+ (analyze_parms): Detect unused params.
+ (modref_merge_call_site_flags): Merge correct EAF_UNUSED.
+
+2020-11-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/97939
+ * config/sparc/predicates.md (arith_double_add_operand): Comment.
+ * config/sparc/sparc.md (uaddvdi4): Use arith_double_operand.
+ (addvdi4): Use arith_double_add_operand.
+ (addsi3): Remove useless attributes.
+ (addvsi4): Use arith_add_operand.
+ (*cmp_ccv_plus): Likewise and add second alternative accordingly.
+ (*cmp_ccxv_plus): Likewise.
+ (*cmp_ccv_plus_set): Likewise.
+ (*cmp_ccxv_plus_set): Likewise.
+ (*cmp_ccv_plus_sltu_set): Likewise.
+ (usubvdi4): Use arith_double_operand.
+ (subvdi4): Use arith_double_add_operand.
+ (subsi3): Remove useless attributes.
+ (subvsi4): Use arith_add_operand.
+ (*cmp_ccv_minus): Likewise and add second alternative accordingly.
+ (*cmp_ccxv_minus): Likewise.
+ (*cmp_ccv_minus_set): Likewise.
+ (*cmp_ccxv_minus_set): Likewise.
+ (*cmp_ccv_minus_sltu_set): Likewise.
+ (negsi2): Use register_operand.
+ (unegvsi3): Likewise.
+ (negvsi3) Likewise.
+ (*cmp_ccnz_neg): Likewise.
+ (*cmp_ccxnz_neg): Likewise.
+ (*cmp_ccnz_neg_set): Likewise.
+ (*cmp_ccxnz_neg_set): Likewise.
+ (*cmp_ccc_neg_set): Likewise.
+ (*cmp_ccxc_neg_set): Likewise.
+ (*cmp_ccc_neg_sltu_set): Likewise.
+ (*cmp_ccv_neg): Likewise.
+ (*cmp_ccxv_neg): Likewise.
+ (*cmp_ccv_neg_set): Likewise.
+ (*cmp_ccxv_neg_set): Likewise.
+ (*cmp_ccv_neg_sltu_set): Likewise.
+
+2020-11-27 H.J. Lu <hjl.tools@gmail.com>
+
+ PR other/98027
+ * doc/install.texi: Default to --enable-cet=auto.
+
+2020-11-27 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-oacc-kernels-decompose.cc (flatten_binds): Don't choke on
+ empty GIMPLE sequence, and examine all statements contained in
+ inner 'GIMPLE_BIND'.
+
+2020-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98024
+ * tree-ssa-pre.c (insert): Fix successor RPO order check.
+ (do_pre_regular_insertion): When inserting an assignment
+ in place of an all-same-value PHI still record that into
+ PHI_GEN.
+
+2020-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-ssanames.c (get_range_info): Handle INTEGER_CST by returning
+ VR_RANGE with both *min and *max set to the wide_int value of the
+ INTEGER_CST. Return VR_VARYING for non-SSA_NAMEs.
+ * match.pd ((t * 2) / 2) -> t): Handle also @0 being INTEGER_CST.
+ Simplify by calling get_range_info on everything.
+ * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Simplify by calling
+ get_range_info on everything.
+ * tree-scalar-evolution.c (iv_can_overflow_p): Likewise.
+
+2020-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/88101
+ * gimple-fold.c (clear_padding_type): Ignore fields with is_empty_type
+ types.
+
+2020-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR c/97880
+ * omp-expand.c (expand_oacc_collapse_init, expand_oacc_collapse_vars):
+ Use now passed diff_type.
+ (expand_oacc_for): Take largest type for diff_type, taking tiling
+ and collapsing into account.
+
+2020-11-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.opt
+ (-param=aarch64-autovec-preference): Define.
+ * config/aarch64/aarch64.c (aarch64_override_options_internal):
+ Set aarch64_sve_compare_costs to 0 when preferring only Advanced
+ SIMD.
+ (aarch64_cmp_autovec_modes): Define.
+ (aarch64_preferred_simd_mode): Adjust to use the above.
+ (aarch64_autovectorize_vector_modes): Likewise.
+ * doc/invoke.texi: Document aarch64-autovec-preference param.
+
+2020-11-27 Xionghu Luo <luoxhu@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (altivec_expand_vec_set_builtin):
+ Change call param 2 from type int to rtx.
+ * config/rs6000/rs6000-protos.h (rs6000_expand_vector_set):
+ Likewise.
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init):
+ Change call param 2 from type int to rtx.
+ (rs6000_expand_vector_set): Likewise.
+ * config/rs6000/vector.md (vec_set<mode>): Support both constant
+ and variable index vec_set.
+
+2020-11-27 Haochen Gui <guihaoc@gcc.gnu.org>
+
+ * config/rs6000/rs6000-protos.h (rs6000_output_addr_vec_elt): Declare.
+ * config/rs6000/rs6000.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC):
+ Define.
+ (rs6000_gen_pic_addr_diff_vec, rs6000_output_addr_vec_elt): Implement.
+ * config/rs6000/rs6000.h (CASE_VECTOR_PC_RELATIVE,
+ CASE_VECTOR_MODE, ASM_OUTPUT_ADDR_VEC_ELT): Define.
+ * config/rs6000/rs6000.md (tablejump<mode>_absolute,
+ tablejump<mode>_absolute_nospec): New expanders.
+ * config/rs6000/rs6000.opt (mrelative-jumptables): New.
+
+2020-11-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/96607
+ * config/sparc/sparc-protos.h (eligible_for_call_delay): Delete.
+ * config/sparc/sparc.c (eligible_for_call_delay): Likewise.
+ * config/sparc/sparc.md (in_call_delay): Likewise.
+ (tls_delay_slot): New attribute.
+ (define_delay [call]): Use in_branch_delay.
+ (tgd_call<P:mode>): Set type to call_no_delay_slot when
+ tls_delay_slot is false.
+ (tldm_call<P:mode>): Likewise.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97997
+ * match.pd ((t * 2) / 2) -> t): Optimize even for defined
+ overflow if ranges prove there is no overflow.
+
+2020-11-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97953
+ * gimple-ssa-evrp-analyze.c
+ (evrp_range_analyzer::record_ranges_from_incoming_edge): Make
+ sure the condition post-dominates the SSA definition before
+ recording into SSA_NAME_RANGE_INFO.
+
+2020-11-26 Richard Biener <rguenther@suse.de>
+
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Only
+ lower VECTOR_BOOLEAN_TYPE_P VEC_COND_EXPRs.
+
+2020-11-26 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/mkoffload.c (copy_early_debug_info): Don't wipe
+ relocation symbols.
+
+2020-11-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_expand_multi_arg_builtin):
+ Remove args array of structs, declare rtx xops array instead.
+ Update all uses.
+ (ix86_expand_args_builtin): Ditto.
+ (ix86_expand_round_builtin): Ditto.
+ (ix86_expand_special_args_builtin): Ditto.
+
+2020-11-26 Martin Liska <mliska@suse.cz>
+
+ * dwarf2out.c (gen_compile_unit_die): Fix missing == 0 in a
+ strcmp.
+
+2020-11-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/sol2.h (TIME_LIBRARY): Remove.
+
+2020-11-26 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Set param_vect_partial_vector_usage as 1 for Power10 and up
+ by default.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ * gimple-fold.c (clear_padding_union): Ignore DECL_PADDING_P
+ fields.
+ (clear_padding_type): Ignore DECL_PADDING_P fields, rather than
+ DECL_BIT_FIELD with NULL DECL_NAME.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97979
+ * match.pd ((X {&,^,|} C2) << C1 into (X << C1) {&,^,|} (C2 << C1)):
+ Only optimize if int_const_binop returned non-NULL.
+
+2020-11-26 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386-expand.c
+ (ix86_expand_special_args_builtin): Delete last_arg_constant
+ and match.
+
+2020-11-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/97873
+ * config/i386/i386.md (abs<mode>2): Use SDWIM mode iterator.
+ (*abs<mode>2_1): Use SWI mode iterator.
+ (<maxmin:code><mode>3): Use SDWIM mode iterator.
+ (*<maxmin:code><mode>3_1): Use SWI mode iterator.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/96906
+ * config/i386/sse.md (VI12_AVX2): Remove V64QI/V32HI modes.
+ (VI12_AVX2_AVX512BW): New mode iterator.
+ (<sse2_avx2>_<plusminus_insn><mode>3<mask_name>,
+ uavg<mode>3_ceil, <sse2_avx2>_uavg<mode>3<mask_name>): Use
+ VI12_AVX2_AVX512BW iterator instead of VI12_AVX2.
+ (*<sse2_avx2>_<plusminus_insn><mode>3<mask_name>): Likewise.
+ (*<sse2_avx2>_uavg<mode>3<mask_name>): Likewise.
+ (*<sse2_avx2>_<plusminus_insn><mode>3<mask_name>): Add a new
+ define_split after this insn.
+
+2020-11-26 Martin Uecker <muecker@gwdg.de>
+
+ PR c/65455
+ PR c/92935
+ * ginclude/stdatomic.h: Use comma operator to drop qualifiers.
+
+2020-11-26 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR bootstrap/97983
+ * lra.c (lra_process_new_insns): Use emit_insn_before_noloc or
+ emit_insn_after_noloc with the destination BB.
+
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR bootstrap/97622
+ PR bootstrap/94982
+ * config/i386/i386-options.c (ix86_valid_target_attribute_inner_p):
+ Avoid -Wformat-diag.
+ * digraph.cc (struct test_edge): Same.
+ * dumpfile.c (dump_loc): Same.
+ (dump_context::begin_scope): Same.
+ * edit-context.c (edited_file::print_diff): Same.
+ (edited_file::print_diff_hunk): Same.
+ * json.cc (object::print): Same.
+ * lto-wrapper.c (merge_and_complain): Same.
+ * reload.c (find_reloads): Same.
+ * tree-diagnostic-path.cc (print_path_summary_as_text): Same.
+ * ubsan.c (ubsan_type_descriptor): Same.
+
+2020-11-25 Jan Hubicka <jh@suse.cz>
+
+ * gimple.c (gimple_call_arg_flags): Also imply EAF_NODIRECTESCAPE.
+ * tree-core.h (EAF_NODRECTESCAPE): New flag.
+ * tree-ssa-structalias.c (make_indirect_escape_constraint): New
+ function.
+ (handle_rhs_call): Hanlde EAF_NODIRECTESCAPE.
+ * ipa-modref.c (dump_eaf_flags): Print EAF_NODIRECTESCAPE.
+ (deref_flags): Dereference is always EAF_NODIRECTESCAPE.
+ (modref_lattice::init): Also set EAF_NODIRECTESCAPE.
+ (analyze_ssa_name_flags): Pure functions do not affect
+ EAF_NODIRECTESCAPE.
+ (analyze_params): Likewise.
+ (ipa_merge_modref_summary_after_inlining): Likewise.
+ (modref_merge_call_site_flags): Likewise.
+
+2020-11-25 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (modref_summaries::duplicate,
+ modref_summaries_lto::duplicate): Copy arg_flags.
+ (remap_arg_flags): Fix remapping of arg_flags.
+
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97956
+ * gimple-fold.c (gimple_fold_builtin_memchr): Use sizetype for pointer
+ offsets.
+
+2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * asan.c (asan_instrument_reads): New.
+ (asan_instrument_writes): New.
+ (asan_memintrin): New.
+ (handle_builtin_stack_restore): Account for HWASAN.
+ (handle_builtin_alloca): Account for HWASAN.
+ (get_mem_refs_of_builtin_call): Special case strlen for HWASAN.
+ (hwasan_instrument_reads): New.
+ (hwasan_instrument_writes): New.
+ (hwasan_memintrin): New.
+ (report_error_func): Assert not HWASAN.
+ (build_check_stmt): Make HWASAN_CHECK instead of ASAN_CHECK.
+ (instrument_derefs): HWASAN does not tag globals.
+ (instrument_builtin_call): Use new helper functions.
+ (maybe_instrument_call): Don't instrument `noreturn` functions.
+ (initialize_sanitizer_builtins): Add new type.
+ (asan_expand_mark_ifn): Account for HWASAN.
+ (asan_expand_check_ifn): Assert never called by HWASAN.
+ (asan_expand_poison_ifn): Account for HWASAN.
+ (asan_instrument): Branch based on whether using HWASAN or ASAN.
+ (pass_asan::gate): Return true if sanitizing HWASAN.
+ (pass_asan_O0::gate): Return true if sanitizing HWASAN.
+ (hwasan_check_func): New.
+ (hwasan_expand_check_ifn): New.
+ (hwasan_expand_mark_ifn): New.
+ (gate_hwasan): New.
+ * asan.h (hwasan_expand_check_ifn): New decl.
+ (hwasan_expand_mark_ifn): New decl.
+ (gate_hwasan): New decl.
+ (asan_intercepted_p): Always false for hwasan.
+ (asan_sanitize_use_after_scope): Account for HWASAN.
+ * builtin-types.def (BT_FN_PTR_CONST_PTR_UINT8): New.
+ * gimple-fold.c (gimple_build): New overload for building function
+ calls without arguments.
+ (gimple_build_round_up): New.
+ * gimple-fold.h (gimple_build): New decl.
+ (gimple_build): New inline function.
+ (gimple_build_round_up): New decl.
+ (gimple_build_round_up): New inline function.
+ * gimple-pretty-print.c (dump_gimple_call_args): Account for
+ HWASAN.
+ * gimplify.c (asan_poison_variable): Account for HWASAN.
+ (gimplify_function_tree): Remove requirement of
+ SANITIZE_ADDRESS, requiring asan or hwasan is accounted for in
+ `asan_sanitize_use_after_scope`.
+ * internal-fn.c (expand_HWASAN_CHECK): New.
+ (expand_HWASAN_ALLOCA_UNPOISON): New.
+ (expand_HWASAN_CHOOSE_TAG): New.
+ (expand_HWASAN_MARK): New.
+ (expand_HWASAN_SET_TAG): New.
+ * internal-fn.def (HWASAN_ALLOCA_UNPOISON): New.
+ (HWASAN_CHOOSE_TAG): New.
+ (HWASAN_CHECK): New.
+ (HWASAN_MARK): New.
+ (HWASAN_SET_TAG): New.
+ * sanitizer.def (BUILT_IN_HWASAN_LOAD1): New.
+ (BUILT_IN_HWASAN_LOAD2): New.
+ (BUILT_IN_HWASAN_LOAD4): New.
+ (BUILT_IN_HWASAN_LOAD8): New.
+ (BUILT_IN_HWASAN_LOAD16): New.
+ (BUILT_IN_HWASAN_LOADN): New.
+ (BUILT_IN_HWASAN_STORE1): New.
+ (BUILT_IN_HWASAN_STORE2): New.
+ (BUILT_IN_HWASAN_STORE4): New.
+ (BUILT_IN_HWASAN_STORE8): New.
+ (BUILT_IN_HWASAN_STORE16): New.
+ (BUILT_IN_HWASAN_STOREN): New.
+ (BUILT_IN_HWASAN_LOAD1_NOABORT): New.
+ (BUILT_IN_HWASAN_LOAD2_NOABORT): New.
+ (BUILT_IN_HWASAN_LOAD4_NOABORT): New.
+ (BUILT_IN_HWASAN_LOAD8_NOABORT): New.
+ (BUILT_IN_HWASAN_LOAD16_NOABORT): New.
+ (BUILT_IN_HWASAN_LOADN_NOABORT): New.
+ (BUILT_IN_HWASAN_STORE1_NOABORT): New.
+ (BUILT_IN_HWASAN_STORE2_NOABORT): New.
+ (BUILT_IN_HWASAN_STORE4_NOABORT): New.
+ (BUILT_IN_HWASAN_STORE8_NOABORT): New.
+ (BUILT_IN_HWASAN_STORE16_NOABORT): New.
+ (BUILT_IN_HWASAN_STOREN_NOABORT): New.
+ (BUILT_IN_HWASAN_TAG_MISMATCH4): New.
+ (BUILT_IN_HWASAN_HANDLE_LONGJMP): New.
+ (BUILT_IN_HWASAN_TAG_PTR): New.
+ * sanopt.c (sanopt_optimize_walker): Act for hwasan.
+ (pass_sanopt::execute): Act for hwasan.
+ * toplev.c (compile_file): Use `gate_hwasan` function.
+
+2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * asan.c (struct hwasan_stack_var): New.
+ (hwasan_sanitize_p): New.
+ (hwasan_sanitize_stack_p): New.
+ (hwasan_sanitize_allocas_p): New.
+ (initialize_sanitizer_builtins): Define new builtins.
+ (ATTR_NOTHROW_LIST): New macro.
+ (hwasan_current_frame_tag): New.
+ (hwasan_frame_base): New.
+ (stack_vars_base_reg_p): New.
+ (hwasan_maybe_init_frame_base_init): New.
+ (hwasan_record_stack_var): New.
+ (hwasan_get_frame_extent): New.
+ (hwasan_increment_frame_tag): New.
+ (hwasan_record_frame_init): New.
+ (hwasan_emit_prologue): New.
+ (hwasan_emit_untag_frame): New.
+ (hwasan_finish_file): New.
+ (hwasan_truncate_to_tag_size): New.
+ * asan.h (hwasan_record_frame_init): New declaration.
+ (hwasan_record_stack_var): New declaration.
+ (hwasan_emit_prologue): New declaration.
+ (hwasan_emit_untag_frame): New declaration.
+ (hwasan_get_frame_extent): New declaration.
+ (hwasan_maybe_enit_frame_base_init): New declaration.
+ (hwasan_frame_base): New declaration.
+ (stack_vars_base_reg_p): New declaration.
+ (hwasan_current_frame_tag): New declaration.
+ (hwasan_increment_frame_tag): New declaration.
+ (hwasan_truncate_to_tag_size): New declaration.
+ (hwasan_finish_file): New declaration.
+ (hwasan_sanitize_p): New declaration.
+ (hwasan_sanitize_stack_p): New declaration.
+ (hwasan_sanitize_allocas_p): New declaration.
+ (HWASAN_TAG_SIZE): New macro.
+ (HWASAN_TAG_GRANULE_SIZE): New macro.
+ (HWASAN_STACK_BACKGROUND): New macro.
+ * builtin-types.def (BT_FN_VOID_PTR_UINT8_PTRMODE): New.
+ * builtins.def (DEF_SANITIZER_BUILTIN): Enable for HWASAN.
+ * cfgexpand.c (align_local_variable): When using hwasan ensure
+ alignment to tag granule.
+ (align_frame_offset): New.
+ (expand_one_stack_var_at): For hwasan use tag offset.
+ (expand_stack_vars): Record stack objects for hwasan.
+ (expand_one_stack_var_1): Record stack objects for hwasan.
+ (init_vars_expansion): Initialise hwasan state.
+ (expand_used_vars): Emit hwasan prologue and generate hwasan epilogue.
+ (pass_expand::execute): Emit hwasan base initialization if needed.
+ * doc/tm.texi (TARGET_MEMTAG_TAG_SIZE,TARGET_MEMTAG_GRANULE_SIZE,
+ TARGET_MEMTAG_INSERT_RANDOM_TAG,TARGET_MEMTAG_ADD_TAG,
+ TARGET_MEMTAG_SET_TAG,TARGET_MEMTAG_EXTRACT_TAG,
+ TARGET_MEMTAG_UNTAGGED_POINTER): Document new hooks.
+ * doc/tm.texi.in (TARGET_MEMTAG_TAG_SIZE,TARGET_MEMTAG_GRANULE_SIZE,
+ TARGET_MEMTAG_INSERT_RANDOM_TAG,TARGET_MEMTAG_ADD_TAG,
+ TARGET_MEMTAG_SET_TAG,TARGET_MEMTAG_EXTRACT_TAG,
+ TARGET_MEMTAG_UNTAGGED_POINTER): Document new hooks.
+ * explow.c (get_dynamic_stack_base): Take new `base` argument.
+ * explow.h (get_dynamic_stack_base): Take new `base` argument.
+ * sanitizer.def (BUILT_IN_HWASAN_INIT): New.
+ (BUILT_IN_HWASAN_TAG_MEM): New.
+ * target.def (target_memtag_tag_size,target_memtag_granule_size,
+ target_memtag_insert_random_tag,target_memtag_add_tag,
+ target_memtag_set_tag,target_memtag_extract_tag,
+ target_memtag_untagged_pointer): New hooks.
+ * targhooks.c (HWASAN_SHIFT): New.
+ (HWASAN_SHIFT_RTX): New.
+ (default_memtag_tag_size): New default hook.
+ (default_memtag_granule_size): New default hook.
+ (default_memtag_insert_random_tag): New default hook.
+ (default_memtag_add_tag): New default hook.
+ (default_memtag_set_tag): New default hook.
+ (default_memtag_extract_tag): New default hook.
+ (default_memtag_untagged_pointer): New default hook.
+ * targhooks.h (default_memtag_tag_size): New default hook.
+ (default_memtag_granule_size): New default hook.
+ (default_memtag_insert_random_tag): New default hook.
+ (default_memtag_add_tag): New default hook.
+ (default_memtag_set_tag): New default hook.
+ (default_memtag_extract_tag): New default hook.
+ (default_memtag_untagged_pointer): New default hook.
+ * toplev.c (compile_file): Call hwasan_finish_file when finished.
+
+2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * common.opt (flag_sanitize_recover): Default for kernel
+ hwaddress.
+ (static-libhwasan): New cli option.
+ * config/aarch64/aarch64.c (aarch64_can_tag_addresses): New.
+ (TARGET_MEMTAG_CAN_TAG_ADDRESSES): New.
+ * config/gnu-user.h (LIBHWASAN_EARLY_SPEC): hwasan equivalent of
+ asan command line flags.
+ * cppbuiltin.c (define_builtin_macros_for_compilation_flags):
+ Add hwasan equivalent of __SANITIZE_ADDRESS__.
+ * doc/invoke.texi: Document hwasan command line flags.
+ * doc/tm.texi: Document new hook.
+ * doc/tm.texi.in: Document new hook.
+ * flag-types.h (enum sanitize_code): New sanitizer values.
+ * gcc.c (STATIC_LIBHWASAN_LIBS): New macro.
+ (LIBHWASAN_SPEC): New macro.
+ (LIBHWASAN_EARLY_SPEC): New macro.
+ (SANITIZER_EARLY_SPEC): Update to include hwasan.
+ (SANITIZER_SPEC): Update to include hwasan.
+ (sanitize_spec_function): Use hwasan options.
+ * opts.c (finish_options): Describe conflicts between address
+ sanitizers.
+ (find_sanitizer_argument): New.
+ (report_conflicting_sanitizer_options): New.
+ (sanitizer_opts): Introduce new sanitizer flags.
+ (common_handle_option): Add defaults for kernel sanitizer.
+ * params.opt (hwasan--instrument-stack): New
+ (hwasan-random-frame-tag): New
+ (hwasan-instrument-allocas): New
+ (hwasan-instrument-reads): New
+ (hwasan-instrument-writes): New
+ (hwasan-instrument-mem-intrinsics): New
+ * target.def (HOOK_PREFIX): Add new hook.
+ (can_tag_addresses): Add new hook under memtag prefix.
+ * targhooks.c (default_memtag_can_tag_addresses): New.
+ * targhooks.h (default_memtag_can_tag_addresses): New decl.
+ * toplev.c (process_options): Ensure hwasan only on
+ architectures that advertise the possibility.
+
+2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * doc/install.texi: Document new option.
+
+2020-11-25 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_maybe_expand_sve_subreg_move):
+ Do not optimize LRA subregs.
+ * config/aarch64/aarch64-sve.md
+ (@aarch64_pred_<SVE_INT_UNARY:optab><mode>): Tie the input to the
+ output.
+ (@aarch64_sve_revbhw_<SVE_ALL:mode><PRED_HSD:mode>): Likewise.
+ (*<ANY_EXTEND:optab><SVE_PARTIAL_I:mode><SVE_HSDI:mode>2): Likewise.
+ (@aarch64_pred_sxt<SVE_FULL_HSDI:mode><SVE_PARTIAL_I:mode>): Likewise.
+ (*cnot<mode>): Likewise.
+ (@aarch64_pred_<SVE_COND_FP_UNARY:optab><mode>): Likewise.
+ (@aarch64_sve_<optab>_nontrunc<SVE_FULL_F:mode><SVE_FULL_HSDI:mode>):
+ Likewise.
+ (@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
+ Likewise.
+ (@aarch64_sve_<optab>_nonextend<SVE_FULL_HSDI:mode><SVE_FULL_F:mode>):
+ Likewise.
+ (@aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>):
+ Likewise.
+ (@aarch64_sve_<optab>_trunc<SVE_FULL_SDF:mode><SVE_FULL_HSF:mode>):
+ Likewise.
+ (@aarch64_sve_<optab>_trunc<VNx4SF_ONLY:mode><VNx8BF_ONLY:mode>):
+ Likewise.
+ (@aarch64_sve_<optab>_nontrunc<SVE_FULL_HSF:mode><SVE_FULL_SDF:mode>):
+ Likewise.
+ * config/aarch64/aarch64-sve2.md
+ (@aarch64_pred_<SVE2_COND_FP_UNARY_LONG:sve_fp_op><mode>): Likewise.
+ (@aarch64_pred_<SVE2_COND_FP_UNARY_NARROWB:sve_fp_op><mode>): Likewise.
+ (@aarch64_pred_<SVE2_U32_UNARY:sve_int_op><mode>): Likewise.
+ (@aarch64_pred_<SVE2_COND_INT_UNARY_FP:sve_fp_op><mode>): Likewise.
+
+2020-11-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/95862
+ * internal-fn.c (get_min_precision): For narrowing conversion, recurse
+ on the operand and if the operand precision is smaller than the
+ current one, return that smaller precision.
+ (expand_mul_overflow): For s1 * u2 -> ur and s1 * s2 -> ur cases
+ if the sum of minimum precisions of both operands is smaller or equal
+ to the result precision, just perform normal multiplication and
+ set overflow to the sign bit of the multiplication result. For
+ u1 * u2 -> sr if both arguments have the MSB known zero, use
+ normal s1 * s2 -> sr expansion.
+
+2020-11-25 Jan Hubicka <jh@suse.cz>
+
+ * cfg.c (free_block): New function.
+ (clear_edges): Rename to ....
+ (free_cfg): ... this one; also free BBs and vectors.
+ (expunge_block): Update comment.
+ * cfg.h (clear_edges): Rename to ...
+ (free_cfg): ... this one.
+ * cgraph.c (release_function_body): Use free_cfg.
+
+2020-11-25 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/97579
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Lower
+ VECTOR_BOOLEAN_TYPE_P, non-vector mode VEC_COND_EXPRs.
+
+2020-11-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/97943
+ * gimple-fold.c (clear_padding_union, clear_padding_type): Error on and
+ ignore flexible array member fields. Ignore fields with
+ error_mark_node type.
+
+2020-11-24 Ulrich Weigand <ulrich.weigand@de.ibm.com>
+
+ Revert:
+ 2020-11-24 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * doc/invoke.texi (-ffast-math): Remove mention of -fno-signaling-nans.
+ Clarify conditions when __FAST_MATH__ preprocessor macro is defined.
+ * opts.c (common_handle_option): Pass OPTS_SET to set_fast_math_flags
+ and set_unsafe_math_optimizations_flags.
+ (set_fast_math_flags): Add OPTS_SET argument, and use it to avoid
+ setting flags already explicitly set on the command line. In the !set
+ case, also reset x_flag_cx_limited_range and x_flag_excess_precision.
+ Never reset x_flag_signaling_nans or x_flag_rounding_math.
+ (set_unsafe_math_optimizations_flags): Add OPTS_SET argument, and use
+ it to avoid setting flags already explicitly set on the command line.
+ (fast_math_flags_set_p): Also test x_flag_cx_limited_range,
+ x_flag_associative_math, x_flag_reciprocal_math, and
+ x_flag_rounding_math.
+
+2020-11-24 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR bootstrap/97933
+ * lra.c (lra_process_new_insns): Stop on the first real insn after
+ head of e->dest.
+
+2020-11-24 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/97534
+ * config/arm/arm.c (arm_split_atomic_op): Use gen_int_mode when
+ negating a const_int.
+
+2020-11-24 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/vector.md: Use vcond_comparison_operator
+ predicate.
+
+2020-11-24 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * doc/invoke.texi (-ffast-math): Remove mention of -fno-signaling-nans.
+ Clarify conditions when __FAST_MATH__ preprocessor macro is defined.
+ * opts.c (common_handle_option): Pass OPTS_SET to set_fast_math_flags
+ and set_unsafe_math_optimizations_flags.
+ (set_fast_math_flags): Add OPTS_SET argument, and use it to avoid
+ setting flags already explicitly set on the command line. In the !set
+ case, also reset x_flag_cx_limited_range and x_flag_excess_precision.
+ Never reset x_flag_signaling_nans or x_flag_rounding_math.
+ (set_unsafe_math_optimizations_flags): Add OPTS_SET argument, and use
+ it to avoid setting flags already explicitly set on the command line.
+ (fast_math_flags_set_p): Also test x_flag_cx_limited_range,
+ x_flag_associative_math, x_flag_reciprocal_math, and
+ x_flag_rounding_math.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/97950
+ * config/i386/i386.md (*setcc_si_1_and): Macroize into...
+ (*setcc_<mode>_1_and): New define_insn_and_split with SWI24 iterator.
+ (*setcc_si_1_movzbl): Macroize into...
+ (*setcc_<mode>_1_movzbl): New define_insn_and_split with SWI24
+ iterator.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ * gimple-fold.c (clear_padding_flush): If a word contains only 0
+ or 0xff bytes of padding other than all set, all clear, all set
+ followed by all clear or all clear followed by all set, don't emit
+ a RMW operation on the whole word or parts of it, but instead
+ clear the individual bytes of padding. For paddings of one byte
+ size, don't use char[1] and {}, but instead just char and 0.
+
+2020-11-24 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-expand.c (expand_oacc_for): More explicit checking of which
+ OMP constructs we're expecting.
+
+2020-11-24 Thomas Schwinge <thomas@codesourcery.com>
+
+ * doc/install.texi (Prerequisites) <Tcl>: Add comment.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96929
+ * fold-const.c (wide_int_binop) <case LSHIFT_EXPR, case RSHIFT_EXPR>:
+ Return false on negative second argument rather than trying to handle
+ it as shift in the other direction.
+ * tree-ssa-ccp.c (bit_value_binop) <case LSHIFT_EXPR,
+ case RSHIFT_EXPR>: Punt on negative shift count rather than trying
+ to handle it as shift in the other direction.
+ * match.pd (-1 >> x to -1): Remove tree_expr_nonnegative_p check.
+
+2020-11-24 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR tree-optimization/97849
+ * tree-if-conv.c (tree_if_conversion): Move ssa_name
+ replacement code from ifcvt_local_dce to this function
+ before calling do_rpo_vn.
+
+2020-11-24 Martin Sebor <msebor@redhat.com>
+
+ * tree-cfg.c (dump_function_to_file): Print type attributes
+ and return type.
+
+2020-11-23 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-prop.h (ipa_pass_through_data): Expand comment describing
+ operation.
+ * ipa-prop.c (analyze_agg_content_value): Detect new special case and
+ encode it as ASSERT_EXPR.
+ * ipa-cp.c (values_equal_for_ipcp_p): Move before
+ ipa_get_jf_arith_result.
+ (ipa_get_jf_arith_result): Special case ASSERT_EXPR.
+
+2020-11-23 Jeff Law <law@redhat.com>
+
+ * config/h8300/h8300.c (h8300_rtx_costs): Handle the various
+ comparison rtx codes too.
+
+2020-11-23 Jan Hubicka <jh@suse.cz>
+
+ * ipa-prop.c (build_agg_jump_func_from_list,
+ ipa_read_jump_function): Reserve agg.items precisely.
+ * ipa-prop.h (ipa_node_params::~ipa_node_params): Release descriptors
+ (ipa_edge_args::~ipa_edge_args): Release agg.items.
+
+2020-11-23 Jan Hubicka <jh@suse.cz>
+
+ * lto-streamer-in.c (input_cfg): Do not init ssa operands.
+ (input_function): Do not init tree_ssa and set in_ssa_p.
+ (input_ssa_names): Do it here.
+ * tree-ssa.c (init_tree_ssa): Add additional SIZE parameter, default
+ to 0
+ * tree-ssanames.c (init_ssanames): Do not round size up to 50, allocate
+ precisely.
+ * tree-ssa.h (init_tree_ssa): Update prototype.
+
+2020-11-23 Nathan Sidwell <nathan@acm.org>
+
+ * diagnostic.c (diagnostic_report_current_module): Adjust for C++
+ module importation.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (msp430_section_attr): Don't warn for "lower"
+ attribute used with "noinit" or "persistent" attributes.
+ (msp430_persist_attr): Remove.
+ (attr_lower_exclusions): Remove ATTR_PERSIST exclusion.
+ (attr_upper_exclusions): Likewise.
+ (attr_either_exclusions): Likewise.
+ (attr_persist_exclusions): Remove.
+ (msp430_attribute_table): Remove ATTR_PERSIST handling.
+ (msp430_handle_generic_attribute): Remove ATTR_PERSIST section conflict
+ handling.
+ (TARGET_ASM_INIT_SECTIONS): Remove.
+ (msp430_init_sections): Remove.
+ (msp430_select_section): Use default_elf_select_section for decls with
+ the "persistent" attribute.
+ (msp430_section_type_flags): Remove ".persistent" section handling.
+ * doc/extend.texi (MSP430 Variable Attributes): Remove "noinit" and
+ "persistent" documentation.
+
+2020-11-23 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (maybe_push_to_hybrid_worklist): Skip
+ debug stmts.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * doc/extend.texi (Common Variable Attributes): Document the
+ "persistent" variable attribute.
+ * doc/sourcebuild.texi (Effective-Target Keywords): Document
+ the "persistent" effective target keyword.
+ * tree.h (DECL_PERSISTENT_P): Define.
+ * varasm.c (bss_initializer_p): Return false for a
+ DECL_PERSISTENT_P decl initialized to zero.
+ (default_section_type_flags): Handle the ".persistent" section.
+ (default_elf_select_section): Likewise.
+ (default_unique_section): Likewise.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * tree.h (DECL_NOINIT_P): Define.
+ * varasm.c (DECL_NOINIT_P): Check DECL_NOINIT_P before using
+ unnamed bss/lcomm sections for bss_initializer variables.
+ (default_elf_select_section): Use DECL_NOINIT_P instead of
+ looking up attribute for .noinit section selection.
+ (default_unique_section): Check DECL_NOINIT_P for .noinit
+ section selection.
+
+2020-11-23 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * doc/install.texi: Document bootstrap-asan option.
+
+2020-11-22 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/97873
+ * config/i386/i386.md (abs<mode>2): Use SWI48DWI mode iterator.
+ (*abs<dwi>2_doubleword): Use DWIH mode iterator.
+ (<maxmin:code><mode>3): Use SWI48DWI mode iterator.
+ (*<maxmin:code><dwi>3_doubleword): Use DWIH mode iterator.
+
+2020-11-22 Austin Law <austinklaw@gmail.com>
+
+ * config/h8300/addsub.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ (add<mod>3_incdec): Remove pattern
+ (adds/subs splitter): Only run before reload.
+ * config/h8300/bitfield.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output
+ of the splitters.
+ (cstoreqi4, cstorehi4, cstoresi4): Comment out
+ (*bstzhireg, *cmpstz, *bstz, *bistz, *cmpcondset): Likewise
+ (*condbset, *cmpcondbclr, *condbclr): Likewise.
+ (*cmpcondbsetreg, *condbsetreg, *cmpcondbclrreg): Likewise.
+ (*condbclrreg): Likewise.
+ * config/h8300/combiner.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters. Add appropriate CC register clobbers to
+ existing splitters.
+ (*addsi3_and_r_1): Disable for now.
+ (*addsi3_and_not_r_1, bit-test branches): Likewise.
+ * config/h8300/divmod.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ * config/h8300/extensions.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ * config/h8300/genmova.sh: Drop "cc" attribute from patterns.
+ * config/h8300/mova.md: Drop "cc" attribute from patterns.
+ * config/h8300/h8300-modes.def: Add CCZN and CCZNV modes.
+ * config/h8300/h8300-protos.h (output_plussi): Update prototype.
+ (compute_plussi_length): Likewise.
+ (h8300_select_cc_mode): Add prototype.
+ (compute_a_shift_cc): Remove prototype
+ (cmpute_logical_op_cc): Likewise.
+ * config/h8300/h8300.c (names_big): Add "cc" register.
+ (names_extended, names_upper_extended): Likewise.
+ (h8300_emit_stack_adjustment): Be more selective about setting
+ RTX_FRAME_RELATED_P.
+ (h8300_print_operand): Handle CCZN mode
+ (h8300_select_cc_mode): New function.
+ (notice_update_cc): if-0 out. Only kept for reference purposes.
+ (h8300_expand_store): Likewise.
+ (h8300_binary_length): Handle new insn forms.
+ (output_plussi): Add argument for NEED_FLAGS and handle that case.
+ (compute_plussi_length): Likewise.
+ (compute_logical_op_cc): Return integer.
+ (TARGET_FLAGS_REGNUM): Define.
+ * config/h8300/h8300.h (FIRST_PSEUDO_REGISTER): Bump for cc register.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS): Handle cc register.
+ (REG_ALLOC_ORDER, REGISTER_NAMES): Likewise.
+ (SELECT_CC_MODE): Define.
+ * config/h8300/h8300.md: Add CC_REG.
+ Do not include peepholes.md for now.
+ * config/h8300/jumpcall.md (cbranchqi4): Consolidate into
+ cbranch<mode>4.
+ (cbranchhi4, cbranchsi4): Likewise.
+ (cbranch<mode>4): New expander.
+ (branch): New define_insn_and_split for use before reload.
+ (branch_1, branch_1_false): New patterns to match splitter output.
+ Remove code to manage cc_status.flags.
+ * config/h8300/logical.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters. Move various peepholes into this file.
+ * config/h8300/movepush.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ * config/h8300/multiply.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ * config/h8300/other.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ * config/h8300/peepholes.md: Remove peepholes that were moved
+ elsewhere.
+ * config/h8300/predicates.md (simple_memory_operand): New.
+ * config/h8300/proepi.md: Drop "cc" attribute setting.
+ * config/h8300/shiftrotate.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters.
+ * config/h8300/testcompare.md: Turn existing patterns into
+ define_insn_and_split style patterns where the splitter
+ adds a clobber of the condition code register. Drop "cc"
+ attribute. Add _clobber_flags patterns to match output of
+ the splitters. Disable various patterns for now.
+ Move some peepholes that were previously in peepholes.md here.
+ * config/h8300/save.md: New file.
+
+2020-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/95853
+ * tree-ssa-math-opts.c (uaddsub_overflow_check_p): Add maxval
+ argument, if non-NULL, instead look for r > maxval or r <= maxval
+ comparisons.
+ (match_uaddsub_overflow): Pattern recognize even other forms of
+ __builtin_add_overflow, in particular when addition is performed
+ in a wider type and result compared to maximum of the narrower
+ type.
+
+2020-11-22 Jeff Law <law@redhat.com>
+
+ * config/h8300/jumpcall.md (branch_true, branch_false): Revert
+ recent change. Ensure operand[0] is always the target label.
+
+2020-11-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-c.c (struct f_align_stack): Rename
+ to type from align_stack to f_align_stack.
+ (push_field_alignment): Likewise.
+ (pop_field_alignment): Likewise.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94695
+ * doc/invoke.texi: Update the -Wrange-loop-construct description.
+
+2020-11-21 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (ao_compare::compare_ao_refs,
+ ao_compare::hash_ao_ref): Use OEP_MATCH_SIDE_EFFECTS.
+
+2020-11-21 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf.c (sem_function::equals_wpa): Do not compare ODR type with
+ -fno-devirtualize.
+ (sem_item_optimizer::update_hash_by_addr_refs): Hash anonymous ODR
+ types by TYPE_UID of their main variant.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Enable vector pair memcpy/memmove expansion.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * config/rs6000/mma.md (unspec): Add assemble/extract UNSPECs.
+ (movoi): Change to movoo.
+ (*movpoi): Change to *movoo.
+ (movxi): Change to movxo.
+ (*movpxi): Change to *movxo.
+ (mma_assemble_pair): Change to OO mode.
+ (*mma_assemble_pair): New define_insn_and_split.
+ (mma_disassemble_pair): New define_expand.
+ (*mma_disassemble_pair): New define_insn_and_split.
+ (mma_assemble_acc): Change to XO mode.
+ (*mma_assemble_acc): Change to XO mode.
+ (mma_disassemble_acc): New define_expand.
+ (*mma_disassemble_acc): New define_insn_and_split.
+ (mma_<acc>): Change to XO mode.
+ (mma_<vv>): Change to XO mode.
+ (mma_<avv>): Change to XO mode.
+ (mma_<pv>): Change to OO mode.
+ (mma_<apv>): Change to XO/OO mode.
+ (mma_<vvi4i4i8>): Change to XO mode.
+ (mma_<avvi4i4i8>): Change to XO mode.
+ (mma_<vvi4i4i2>): Change to XO mode.
+ (mma_<avvi4i4i2>): Change to XO mode.
+ (mma_<vvi4i4>): Change to XO mode.
+ (mma_<avvi4i4>): Change to XO mode.
+ (mma_<pvi4i2>): Change to XO/OO mode.
+ (mma_<apvi4i2>): Change to XO/OO mode.
+ (mma_<vvi4i4i4>): Change to XO mode.
+ (mma_<avvi4i4i4>): Change to XO mode.
+ * config/rs6000/predicates.md (input_operand): Allow opaque.
+ (mma_disassemble_output_operand): New predicate.
+ * config/rs6000/rs6000-builtin.def:
+ Changes to disassemble builtins.
+ * config/rs6000/rs6000-call.c (rs6000_return_in_memory):
+ Disallow __vector_pair/__vector_quad as return types.
+ (rs6000_promote_function_mode): Remove function return type
+ check because we can't test it here any more.
+ (rs6000_function_arg): Do not allow __vector_pair/__vector_quad
+ as as function arguments.
+ (rs6000_gimple_fold_mma_builtin):
+ Handle mma_disassemble_* builtins.
+ (rs6000_init_builtins): Create types for XO/OO modes.
+ * config/rs6000/rs6000-modes.def: DElete OI, XI,
+ POI, and PXI modes, and create XO and OO modes.
+ * config/rs6000/rs6000-string.c (expand_block_move):
+ Update to OO mode.
+ * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok_uncached):
+ Update for XO/OO modes.
+ (rs6000_rtx_costs): Make UNSPEC_MMA_XXSETACCZ cost 0.
+ (rs6000_modes_tieable_p): Update for XO/OO modes.
+ (rs6000_debug_reg_global): Update for XO/OO modes.
+ (rs6000_setup_reg_addr_masks): Update for XO/OO modes.
+ (rs6000_init_hard_regno_mode_ok): Update for XO/OO modes.
+ (reg_offset_addressing_ok_p): Update for XO/OO modes.
+ (rs6000_emit_move): Update for XO/OO modes.
+ (rs6000_preferred_reload_class): Update for XO/OO modes.
+ (rs6000_split_multireg_move): Update for XO/OO modes.
+ (rs6000_mangle_type): Update for opaque types.
+ (rs6000_invalid_conversion): Update for XO/OO modes.
+ * config/rs6000/rs6000.h (VECTOR_ALIGNMENT_P):
+ Update for XO/OO modes.
+ * config/rs6000/rs6000.md (RELOAD): Update for XO/OO modes.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * typeclass.h: Add opaque_type_class.
+ * builtins.c (type_to_class): Identify opaque type class.
+ * dwarf2out.c (is_base_type): Handle opaque types.
+ (gen_type_die_with_usage): Handle opaque types.
+ * expr.c (count_type_elements): Opaque types should
+ never have initializers.
+ * ipa-devirt.c (odr_types_equivalent_p): No type-specific handling
+ for opaque types is needed as it eventually checks the underlying
+ mode which is what is important.
+ * tree-streamer.c (record_common_node): Handle opaque types.
+ * tree.c (type_contains_placeholder_1): Handle opaque types.
+ (type_cache_hasher::equal): No additional comparison needed for
+ opaque types.
+
+2020-11-20 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000-call.c (rs6000_expand_builtin): Add missing
+ XSCMP* cases for IEEE 128-bit long double.
+
+2020-11-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/97918
+ * dwarf2out.c (dwarf2out_early_finish): flush_limbo_die_list
+ after gen_scheduled_generic_parms_dies.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97879
+ * tree-core.h (enum attribute_flags): Add ATTR_FLAG_INTERNAL.
+
+2020-11-20 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf-gimple.c (func_checker::hash_operand): Improve hashing of
+ decls.
+
+2020-11-20 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf-gimple.c (func_checker::compare_decl): Do not compare types
+ of local variables.
+
+2020-11-20 Nathan Sidwell <nathan@acm.org>
+
+ * doc/invoke.texi: Replace a couple of @code with @command
+
+2020-11-20 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-slp.c (vectorizable_slp_permutation): Update types on nodes
+ when needed.
+
+2020-11-20 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (maybe_push_to_hybrid_worklist): New function.
+ (vect_detect_hybrid_slp): Use it. Perform a backward walk
+ over the IL.
+
+2020-11-20 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_print_slp_tree): Also dump
+ SLP_TREE_REPRESENTATIVE.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/88101
+ * builtins.def (BUILT_IN_CLEAR_PADDING): New built-in function.
+ * gimplify.c (gimplify_call_expr): Rewrite single argument
+ BUILT_IN_CLEAR_PADDING into two-argument variant.
+ * gimple-fold.c (clear_padding_unit, clear_padding_buf_size): New
+ const variables.
+ (struct clear_padding_struct): New type.
+ (clear_padding_flush, clear_padding_add_padding,
+ clear_padding_emit_loop, clear_padding_type,
+ clear_padding_union, clear_padding_real_needs_padding_p,
+ clear_padding_type_may_have_padding_p,
+ gimple_fold_builtin_clear_padding): New functions.
+ (gimple_fold_builtin): Handle BUILT_IN_CLEAR_PADDING.
+ * doc/extend.texi (__builtin_clear_padding): Document.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/97528
+ * config/arm/arm.c (neon_vector_mem_operand): For POST_MODIFY, require
+ first POST_MODIFY operand is a REG and is equal to the first operand
+ of PLUS.
+
+2020-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimple-ssa-store-merging.c (struct merged_store_group): Add
+ new 'consecutive' field.
+ (merged_store_group): Set it to true.
+ (do_merge): Set it to false if the store is not consecutive and
+ set string_concatenation to false in this case.
+ (merge_into): Call do_merge on entry.
+ (merge_overlapping): Likewise.
+
+2020-11-20 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf-gimple.c (func_checker::operand_equal_p): Fix comment.
+
+2020-11-20 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf-gimple.c (func_checker::hash_operand): Hash gimple clobber.
+ (func_checker::operand_equal_p): Special case gimple clobber.
+
+2020-11-20 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/97873
+ * config/i386/i386.md (*neg<mode>2_2): Rename from
+ "*neg<mode>2_cmpz". Use CCGOCmode instead of CCZmode.
+ (*negsi2_zext): Rename from *negsi2_cmpz_zext.
+ Use CCGOCmode instead of CCZmode.
+ (*neg<mode>_ccc_1): New insn pattern.
+ (*neg<dwi>2_doubleword): Use *neg<mode>_ccc_1.
+ (abs<mode>2): Add FLAGS_REG clobber.
+ Use TARGET_CMOVE insn predicate.
+ (*abs<mode>2_1): New insn_and_split pattern.
+ (*absdi2_doubleword): Ditto.
+ (<maxmin:code><mode>3): Use SWI48x mode iterator.
+ (*<maxmin:code><mode>3): Use SWI48 mode iterator.
+ * config/i386/i386-features.c
+ (general_scalar_chain::compute_convert_gain): Handle ABS code.
+ (general_scalar_chain::convert_insn): Ditto.
+ (general_scalar_to_vector_candidate_p): Ditto.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * configure.ac: In SERIAL_LIST use lang words without .serial
+ suffix. Change $lang.prev from a target to variable and instead
+ of depending on *.serial expand to the *.serial variable if
+ the word is in the SERIAL_LIST at all, otherwise to nothing.
+ * configure: Regenerated.
+
+2020-11-20 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000.md (p8_mtvsrd_df): Fix insn type.
+
+2020-11-20 Martin Uecker <muecker@gwdg.de>
+
+ * gimplify.c (gimplify_modify_expr_rhs): Optimizie
+ NOP_EXPRs that contain compound literals.
+
+2020-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91029
+ * range-op.cc (operator_trunc_mod::op1_range): Don't require signed
+ types, nor require that op2 >= 0. Implement (a % b) >= x && x > 0
+ implies a >= x and (a % b) <= x && x < 0 implies a <= x.
+ (operator_trunc_mod::op2_range): New method.
+
+2020-11-19 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/93781
+ * range-op.cc (get_shift_range): Rename from
+ undefined_shift_range_check and now return valid shift ranges.
+ (operator_lshift::fold_range): Use result from get_shift_range.
+ (operator_rshift::fold_range): Ditto.
+
+2020-11-19 Jan Hubicka <jh@suse.cz>
+
+ * fold-const.c (operand_compare::operand_equal_p): Fix thinko in
+ COMPONENT_REF handling and guard types_same_for_odr by
+ virtual_method_call_p.
+ (operand_compare::hash_operand): Likewise.
+
+2020-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97860
+ * tree.c (array_type_nelts): For complete arrays with zero min
+ and NULL max and zero size return -1.
+
+2020-11-19 Nathan Sidwell <nathan@acm.org>
+
+ * configure.ac: Add tests for fstatat, sighandler_t, O_CLOEXEC,
+ unix-domain and ipv6 sockets.
+ * config.in: Rebuilt.
+ * configure: Rebuilt.
+
+2020-11-19 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * config/pru/alu-zext.md: Add lmbd patterns for zero_extend
+ variants.
+ * config/pru/pru.c (enum pru_builtin): Add HALT and LMBD.
+ (pru_init_builtins): Ditto.
+ (pru_builtin_decl): Ditto.
+ (pru_expand_builtin): Ditto.
+ * config/pru/pru.h (CLZ_DEFINED_VALUE_AT_ZERO): Define PRU
+ value for CLZ with zero value parameter.
+ * config/pru/pru.md: Add halt, lmbd and clz patterns.
+ * doc/extend.texi: Document PRU builtins.
+
+2020-11-19 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/invoke.texi (-fvect-cost-model): Add a very-cheap model.
+ * common.opt (fvect-cost-model=): Add very-cheap as a possible option.
+ (fsimd-cost-model=): Likewise.
+ (vect_cost_model): Add very-cheap.
+ * flag-types.h (vect_cost_model): Add VECT_COST_MODEL_VERY_CHEAP.
+ Put the values in order of increasing aggressiveness.
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Use
+ range checks when comparing against VECT_COST_MODEL_CHEAP.
+ (vect_prune_runtime_alias_test_list): Do not allow any alias
+ checks for the very-cheap cost model.
+ * tree-vect-loop.c (vect_analyze_loop_costing): Do not allow
+ any peeling for the very-cheap cost model. Also require one
+ iteration of the vector loop to pay for itself.
+
+2020-11-19 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config/aarch64/aarch64.c (neoversen1_tunings): Use new
+ cortexa76_extra_costs.
+ (neoversev1_tunings): Likewise.
+ (neoversen2_tunines): Likewise.
+ * config/arm/aarch-cost-tables.h (cortexa76_extra_costs):
+ add new costs.
+
+2020-11-19 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_cpymem): Cleanup code and
+ comments, tweak expansion decisions and improve tail expansion.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ * fold-const.c (operand_compare::hash_operand): Fix typo.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-reassoc.c (get_rank): Refactor to consistently
+ use the cache and dump ranks assigned.
+
+2020-11-19 Jan Hubicka <jh@suse.cz>
+
+ * fold-const.c (operand_compare::operand_equal_p): More OBJ_TYPE_REF
+ matching to correct place; drop OEP_ADDRESS_OF for TOKEN, OBJECT and
+ class.
+ (operand_compare::hash_operand): Hash ODR type for OBJ_TYPE_REF.
+
+2020-11-19 Joel Hutton <joel.hutton@arm.com>
+
+ * config/aarch64/aarch64-simd.md: Add vec_widen_lshift_hi/lo<mode>
+ patterns.
+ * tree-vect-stmts.c (vectorizable_conversion): Fix for widen_lshift
+ case.
+
+2020-11-19 Joel Hutton <joel.hutton@arm.com>
+
+ * doc/generic.texi: Document new widen_plus/minus_lo/hi tree codes.
+ * doc/md.texi: Document new widenening add/subtract hi/lo optabs.
+ * expr.c (expand_expr_real_2): Add widen_add, widen_subtract cases.
+ * optabs-tree.c (optab_for_tree_code): Add case for widening optabs.
+ * optabs.def (OPTAB_D): Define vectorized widen add, subtracts.
+ * tree-cfg.c (verify_gimple_assign_binary): Add case for widening adds,
+ subtracts.
+ * tree-inline.c (estimate_operator_cost): Add case for widening adds,
+ subtracts.
+ * tree-vect-generic.c (expand_vector_operations_1): Add case for
+ widening adds, subtracts
+ * tree-vect-patterns.c (vect_recog_widen_add_pattern): New recog
+ pattern.
+ (vect_recog_widen_sub_pattern): New recog pattern.
+ (vect_recog_average_pattern): Update widened add code.
+ (vect_recog_average_pattern): Update widened add code.
+ * tree-vect-stmts.c (vectorizable_conversion): Add case for widened add,
+ subtract.
+ (supportable_widening_operation): Add case for widened add, subtract.
+ * tree.def
+ (WIDEN_PLUS_EXPR): New tree code.
+ (WIDEN_MINUS_EXPR): New tree code.
+ (VEC_WIDEN_ADD_HI_EXPR): New tree code.
+ (VEC_WIDEN_PLUS_LO_EXPR): New tree code.
+ (VEC_WIDEN_MINUS_HI_EXPR): New tree code.
+ (VEC_WIDEN_MINUS_LO_EXPR): New tree code.
+
+2020-11-19 Joel Hutton <joel.hutton@arm.com>
+
+ * config/aarch64/aarch64-simd.md: New patterns
+ vec_widen_saddl_lo/hi_<mode>.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97901
+ * tree-ssa-propagate.c (clean_up_loop_closed_phi): Compute
+ dominators and use replace_uses_by.
+
+2020-11-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * dwarf2out.h (struct fixed_point_type_info) <scale_factor>: Turn
+ numerator and denominator into a tree.
+ * dwarf2out.c (base_type_die): In the case of a fixed-point type
+ with arbitrary scale factor, call add_scalar_info on numerator and
+ denominator to emit the appropriate attributes.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97897
+ * tree-complex.c (complex_propagate::visit_stmt): Make sure
+ abnormally used SSA names are VARYING.
+ (complex_propagate::visit_phi): Likewise.
+ * tree-ssa.c (verify_phi_args): Verify PHI arguments on abnormal
+ edges are SSA names.
+
+2020-11-19 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (*<absneg:code><mode>2_i387_1):
+ Disable for TARGET_SSE_MATH modes.
+
+2020-11-19 Jeff Law <law@redhat.com>
+
+ * config/h8300/constraints.md (R constraint): Add argument to call
+ to h8300_shift_needs_scratch_p.
+ (S and T constraints): Similary.
+ * config/h8300/h8300-protos.h: Update h8300_shift_needs_scratch_p
+ prototype.
+ * config/h8300/h8300.c (expand_a_shift): Emit a different pattern
+ if the shift does not require a scratch register.
+ (h8300_shift_needs_scratch_p): Refine to be more accurate.
+ * config/h8300/shiftrotate.md (shiftqi_noscratch): New pattern.
+ (shifthi_noscratch, shiftsi_noscratch): Similarly.
+
+2020-11-18 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR middle-end/85811
+ * fold-const.c (tree_expr_finite_p): New function to test whether
+ a tree expression must be finite, i.e. not a FP NaN or infinity.
+ (tree_expr_infinite_p): New function to test whether a tree
+ expression must be infinite, i.e. a FP infinity.
+ (tree_expr_maybe_infinite_p): New function to test whether a tree
+ expression may be infinite, i.e. a FP infinity.
+ (tree_expr_signaling_nan_p): New function to test whether a tree
+ expression must evaluate to a signaling NaN (sNaN).
+ (tree_expr_maybe_signaling_nan_p): New function to test whether a
+ tree expression may be a signaling NaN (sNaN).
+ (tree_expr_nan_p): New function to test whether a tree expression
+ must evaluate to a (quiet or signaling) NaN.
+ (tree_expr_maybe_nan_p): New function to test whether a tree
+ expression me be a (quiet or signaling) NaN.
+ (tree_binary_nonnegative_warnv_p) [MAX_EXPR]: In the presence
+ of NaNs, MAX_EXPR is only guaranteed to be non-negative, if both
+ operands are non-negative.
+ (tree_call_nonnegative_warnv_p) [CASE_CFN_FMAX,CASE_CFN_FMAX_FN]:
+ In the presence of signaling NaNs, fmax is only guaranteed to be
+ non-negative if both operands are negative. In the presence of
+ quiet NaNs, fmax is non-negative if either operand is non-negative
+ and not a qNaN, or both operands are non-negative.
+ * fold-const.h (tree_expr_finite_p, tree_expr_infinite_p,
+ tree_expr_maybe_infinite_p, tree_expr_signaling_nan_p,
+ tree_expr_maybe_signaling_nan_p, tree_expr_nan_p,
+ tree_expr_maybe_nan_p): Prototype new functions here.
+ * builtins.c (fold_builtin_classify) [BUILT_IN_ISINF]: Fold to
+ a constant if argument is known to be (or not to be) an Infinity.
+ [BUILT_IN_ISFINITE]: Fold to a constant if argument is known to
+ be (or not to be) finite.
+ [BUILT_IN_ISNAN]: Fold to a constant if argument is known to be
+ (or not to be) a NaN.
+ (fold_builtin_fpclassify): Check tree_expr_maybe_infinite_p and
+ tree_expr_maybe_nan_p instead of HONOR_INFINITIES and HONOR_NANS
+ respectively.
+ (fold_builtin_unordered_cmp): Fold UNORDERED_EXPR to a constant
+ when its arguments are known to be (or not be) NaNs. Check
+ tree_expr_maybe_nan_p instead of HONOR_NANS when choosing between
+ unordered and regular forms of comparison operators.
+ * match.pd (ordered(x,y)->true/false): Constant fold ORDERED_EXPR
+ if its operands are known to be (or not to be) NaNs.
+ (unordered(x,y)->true/false): Constant fold UNORDERED_EXPR if its
+ operands are known to be (or not to be) NaNs.
+ (sqrt(x)*sqrt(x)->x): Check tree_expr_maybe_signaling_nan_p instead
+ of HONOR_SNANS.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91029
+ PR tree-optimization/97888
+ * range-op.cc (operator_trunc_mod::op1_range): Only set op1
+ range to >= 0 if lhs is > 0, rather than >= 0. Fix up comments.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * opts.h (struct cl_var): New type.
+ (cl_vars): Declare.
+ * optc-gen.awk: Generate cl_vars array.
+
+2020-11-18 Eugene Rozenfeld <Eugene.Rozenfeld@microsoft.com>
+
+ PR tree-optimization/96671
+ * match.pd (three xor patterns): New patterns.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * optc-save-gen.awk: Initialize var_opt_init. In
+ cl_optimization_stream_out for params with default values larger than
+ 10, xor the default value with the actual parameter value. In
+ cl_optimization_stream_in repeat the above xor.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * configure.ac: Add $lang.prev rules, INDEX.$lang and SERIAL_LIST and
+ SERIAL_COUNT variables to Make-hooks.
+ (--enable-link-serialization): New configure option.
+ * Makefile.in (DO_LINK_SERIALIZATION, LINK_PROGRESS): New variables.
+ * doc/install.texi (--enable-link-serialization): Document.
+ * configure: Regenerated.
+
+2020-11-18 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR target/97870
+ * lra-constraints.c (curr_insn_transform): Do not delete asm goto
+ with wrong constraints. Nullify it saving CFG.
+
+2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.md (mulhi3): New.
+ (mulsi3): New.
+ (mulsidi3): Rename to *mulsidi3_inline.
+ (umulsidi3): Rename to *umulsidi3_inline.
+ (mulsidi3): New define_expand.
+ (umulsidi3): New define_expand.
+
+2020-11-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97886
+ * tree-vect-loop.c (vectorizable_lc_phi): Properly assign
+ vector types to invariants for SLP.
+
+2020-11-18 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * config.gcc (*-*-dragonfly*): Add dragonfly-d.o and t-dragonfly.
+ * config/dragonfly-d.c: New file.
+ * config/t-dragonfly: New file.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/97862
+ * omp-expand.c (expand_omp_for_init_vars): Don't use the sqrt path
+ if number of iterations is constant 0.
+
+2020-11-18 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.c (riscv_ext_version): New.
+ (riscv_ext_version_table): Ditto.
+ (get_default_version): Ditto.
+ (riscv_subset_t::implied_p): New field.
+ (riscv_subset_t::riscv_subset_t): Init implied_p.
+ (riscv_subset_list::add): New.
+ (riscv_subset_list::handle_implied_ext): Pass riscv_subset_t
+ instead of separated argument.
+ (riscv_subset_list::to_string): Handle zifencei and zicsr, and
+ omit version if version is unknown.
+ (riscv_subset_list::parsing_subset_version): New argument `ext`,
+ remove default_major_version and default_minor_version, get
+ default version info via get_default_version.
+ (riscv_subset_list::parse_std_ext): Update argument for
+ parsing_subset_version calls.
+ Handle 2.2 ISA spec, always enable zicsr and zifencei, they are
+ included in baseline ISA in that time.
+ (riscv_subset_list::parse_multiletter_ext): Update argument for
+ `parsing_subset_version` and `add` calls.
+ (riscv_subset_list::parse): Adjust argument for
+ riscv_subset_list::handle_implied_ext call.
+ * config.gcc (riscv*-*-*): Handle --with-isa-spec=.
+ * config.in (HAVE_AS_MISA_SPEC): New.
+ (HAVE_AS_MARCH_ZIFENCEI): Ditto.
+ * config/riscv/riscv-opts.h (riscv_isa_spec_class): New.
+ (riscv_isa_spec): Ditto.
+ * config/riscv/riscv.h (HAVE_AS_MISA_SPEC): New.
+ (ASM_SPEC): Pass -misa-spec if gas supported.
+ * config/riscv/riscv.opt (riscv_isa_spec_class) New.
+ * configure.ac (HAVE_AS_MARCH_ZIFENCEI): New test.
+ (HAVE_AS_MISA_SPEC): Ditto.
+ * configure: Regen.
+
+2020-11-18 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.c (riscv_implied_info):
+ d and f implied zicsr.
+ (riscv_ext_flag_table): Handle zicsr and zifencei.
+ * config/riscv/riscv-opts.h (MASK_ZICSR): New.
+ (MASK_ZIFENCEI): Ditto.
+ (TARGET_ZICSR): Ditto.
+ (TARGET_ZIFENCEI): Ditto.
+ * config/riscv/riscv.md (clear_cache): Check TARGET_ZIFENCEI.
+ (fence_i): Ditto.
+ * config/riscv/riscv.opt (riscv_zi_subext): New.
+
+2020-11-18 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.c (single_letter_subset_rank): New.
+ (multi_letter_subset_rank): Ditto.
+ (subset_cmp): Ditto.
+ (riscv_subset_list::add): Insert subext in canonical ordering.
+ (riscv_subset_list::parse_std_ext): Move handle_implied_ext to ...
+ (riscv_subset_list::parse): ... here.
+
+2020-11-18 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ * cfgloop.h (loop_optimizer_finalize): Add flag argument.
+ * loop-init.c (loop_optimizer_finalize): Call clean_up_loop_closed_phi.
+ * tree-cfgcleanup.h (clean_up_loop_closed_phi): New declare.
+ * tree-ssa-loop.c (tree_ssa_loop_done): Call loop_optimizer_finalize
+ with flag argument.
+ * tree-ssa-propagate.c (clean_up_loop_closed_phi): New function.
+
+2020-11-17 Sebastian Pop <spop@amazon.com>
+
+ * config.gcc: add configure flags --with-{cpu,arch,tune}-{32,64}
+ as alias flags for --with-{cpu,arch,tune} on AArch64.
+ * doc/install.texi: Document new flags for aarch64.
+
+2020-11-17 Sebastian Pop <spop@amazon.com>
+
+ * config.gcc: Add --with-tune to AArch64 configure flags.
+
+2020-11-17 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/91029
+ * range-op.cc (operator_trunc_mod::op1_range): New.
+
+2020-11-17 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf.c (sem_function::hash_stmt): Fix conditional on
+ variably_modified_type_p.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ * tree.h (cache_integer_cst): Add defaulted might_duplicate parm.
+ * tree.c (cache_integer_cst): Return the integer cst, add
+ might_duplicate parm to permit finding a small duplicate.
+
+2020-11-17 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/83072
+ * range-op.cc (wi_optimize_and_or): Remove zero from IOR range when
+ mask is non-zero.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/float.h (CR_DECIMAL_DIG): Also define for
+ [__STDC_WANT_IEC_60559_EXT__].
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/float.h [__STDC_VERSION__ > 201710L] (FLT_IS_IEC_60559,
+ DBL_IS_IEC_60559, LDBL_IS_IEC_60559): New macros.
+
+2020-11-17 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ PR target/96791
+ * mode-classes.def: Add MODE_OPAQUE.
+ * machmode.def: Add OPAQUE_MODE.
+ * tree.def: Add OPAQUE_TYPE for types that will use
+ MODE_OPAQUE.
+ * doc/generic.texi: Document OPAQUE_TYPE.
+ * doc/rtl.texi: Document MODE_OPAQUE.
+ * machmode.h: Add OPAQUE_MODE_P().
+ * genmodes.c (complete_mode): Add MODE_OPAQUE.
+ (opaque_mode): New function.
+ * tree.c (tree_code_size): Add OPAQUE_TYPE.
+ * tree.h: Add OPAQUE_TYPE_P().
+ * stor-layout.c (int_mode_for_mode): Treat MODE_OPAQUE modes
+ like BLKmode.
+ * ira.c (find_moveable_pseudos): Treat MODE_OPAQUE modes more
+ like integer/float modes here.
+ * dbxout.c (dbxout_type): Treat OPAQUE_TYPE like VOID_TYPE.
+ * tree-pretty-print.c (dump_generic_node): Treat OPAQUE_TYPE
+ like like other types.
+
+2020-11-17 Jan Hubicka <hubicka@ucw.cz>
+ Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.c: Include data-streamer.h and alias.h.
+ (sem_function::sem_function): Initialize memory_access_types
+ and m_alias_sets_hash.
+ (sem_function::hash_stmt): For memory accesses and when going to
+ do lto streaming add base and ref types into memory_access_types.
+ (sem_item_optimizer::write_summary): Stream memory access types.
+ (sem_item_optimizer::read_section): Likewise and also iniitalize
+ m_alias_sets_hash.
+ (sem_item_optimizer::execute): Call
+ sem_item_optimizer::update_hash_by_memory_access_type.
+ (sem_item_optimizer::update_hash_by_memory_access_type): Updat.
+ * ipa-icf.h (sem_function): Add memory_access_types and
+ m_alias_sets_hash.
+
+2020-11-17 Jan Hubicka <jh@suse.cz>
+
+ PR bootstrap/97857
+ * ipa-devirt.c (odr_based_tbaa_p): Do not ICE when
+ odr_hash is not initialized
+ * ipa-utils.h (type_with_linkage_p): Do not sanity check
+ CXX_ODR_P.
+ * tree-streamer-out.c (pack_ts_type_common_value_fields): Set
+ CXX_ODR_P according to the canonical type.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ * langhooks-def.h (LANG_HOOKS_PREPROCESS_MAIN_FILE)
+ (LANG_HOOKS_PREPROCESS_OPTIONS, LANG_HOOKS_PREPROCESS_UNDEF)
+ (LANG_HOOKS_PREPROCESS_TOKEN): New.
+ (LANG_HOOKS_INITIALIZER): Add them.
+ * langhooks.h (struct lang_hooks): Add preprocess_main_file,
+ preprocess_options, preprocess_undef, preprocess_token hooks. Add
+ enum PT_flags.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/97693
+ * tree-vect-stmts.c (vectorizable_call): Pass the required vectype
+ to vect_get_vec_defs_for_operand.
+
+2020-11-17 Liu Hao <lh_mouse@126.com>
+
+ * config/i386/msformat-c.c: Add more length modifiers.
+
+2020-11-17 Tamar Christina <tamar.christina@arm.com>
+
+ PR driver/97574
+ * gcc.c (convert_filename): Don't add suffix to things that are
+ not files.
+ (not_actual_file_p): Use supplied argument.
+
+2020-11-17 Haochen Gui <guihaoc@gcc.gnu.org>
+
+ * final.c (final_scan_insn_1): Set jump table relocatable as the
+ second argument of targetm.asm_out.function_rodata_section.
+ * output.h (default_function_rodata_section,
+ default_no_function_rodata_section): Add the second argument to the
+ declarations.
+ * target.def (function_rodata_section): Change the doc and add
+ the second argument.
+ * doc/tm.texi: Regenerate.
+ * varasm.c (jumptable_relocatable): Implement.
+ (default_function_rodata_section): Add the second argument
+ and the support for relocatable read only sections.
+ (default_no_function_rodata_section): Add the second argument.
+ (function_mergeable_rodata_prefix): Set the second argument to false.
+ * config/mips/mips.c (mips_function_rodata_section): Add the second
+ arugment and set it to false.
+ * config/s390/s390.c (targetm.asm_out.function_rodata_section): Set
+ the second argument to false.
+ * config/s390/s390.md: Likewise.
+
+2020-11-17 liuhongt <hongtao.liu@intel.com>
+
+ PR target/97194
+ * config/i386/i386-expand.c (ix86_expand_vector_set_var): New function.
+ * config/i386/i386-protos.h (ix86_expand_vector_set_var): New Decl.
+ * config/i386/predicates.md (vec_setm_operand): New predicate,
+ true for const_int_operand or register_operand under TARGET_AVX2.
+ * config/i386/sse.md (vec_set<mode>): Support both constant
+ and variable index vec_set.
+
+2020-11-17 Martin Sebor <msebor@redhat.com>
+
+ * tree-ssa-uninit.c (maybe_warn_operand): Call is_empty_type.
+ * tree.c (default_is_empty_type): Rename...
+ (is_empty_type): ...to this.
+ * tree.h (is_empty_type): Declare.
+
+2020-11-17 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/95673
+ * tree-ssa-strlen.c (used_only_for_zero_equality): Rename...
+ (use_in_zero_equality): ...to this. Add a default argument.
+ (handle_builtin_memcmp): Adjust to the name change above.
+ (handle_builtin_string_cmp): Same.
+ (maybe_warn_pointless_strcmp): Same. Pass in an explicit argument.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/float.h (DEC32_SNAN, DEC64_SNAN, DEC128_SNAN): New C2x
+ macros.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/float.h (INFINITY, NAN, FLT_SNAN, DBL_SNAN, LDBL_SNAN)
+ (FLT16_SNAN, FLT32_SNAN, FLT64_SNAN, FLT128_SNAN, FLT32X_SNAN)
+ (FLT64X_SNAN, FLT128X_SNAN, DEC_INFINITY, DEC_NAN): New C2x
+ macros.
+ * doc/sourcebuild.texi (Effective-Target Keywords): Document inff.
+
+2020-11-17 Armin Brauns via Gcc-patches <gcc-patches@gcc.gnu.org>
+
+ * gcc.c: Document %T spec file directive.
+ * doc/invoke.texi: Remove %p, %P spec file directives.
+ Add %M, %R, %V, %nSTR, %>S, %<S*, %{%:function(args):X}, %@{...} spec
+ file directives add sanitize, version-compare, include, gt and
+ debug-level-gt spec functions.
+
+2020-11-16 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR rtl-optimization/92180
+ * config/i386/i386.c (ix86_hardreg_mov_ok): New function to
+ determine whether (set DST SRC) should be allowed at this point.
+ * config/i386/i386-protos.h (ix86_hardreg_mov_ok): Prototype here.
+ * config/i386/i386-expand.c (ix86_expand_move): Check whether
+ this is a complex set of a likely spilled hard register, and if
+ so place the value in a pseudo, and load the hard reg from it.
+ * config/i386/i386.md (*movdi_internal, *movsi_internal)
+ (*movhi_internal, *movqi_internal): Make these instructions
+ conditional on ix86_hardreg_mov_ok.
+ (*lea<mode>): Make this define_insn_and_split conditional on
+ ix86_hardreg_mov_ok.
+
+2020-11-16 Martin Liska <mliska@suse.cz>
+
+ * params.opt: Add missing dot.
+
+2020-11-16 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (escape_point): New type.
+ (modref_lattice): New type.
+ (escape_entry): New type.
+ (escape_summary): New type.
+ (escape_summaries_t): New type.
+ (escape_summaries): New static variable.
+ (eaf_flags_useful_p): New function.
+ (modref_summary::useful_p): Add new check_flags
+ attribute; check eaf_flags for usefulness.
+ (modref_summary_lto): Add arg_flags.
+ (modref_summary_lto::useful_p): Add new check_flags
+ attribute; check eaf_flags for usefulness.
+ (dump_modref_edge_summaries): New function.
+ (remove_modref_edge_summaries): New function.
+ (ignore_retval_p): New predicate.
+ (ignore_stores_p): Also ignore for const.
+ (remove_summary): Call remove_modref_edge_summaries.
+ (modref_lattice::init): New member function.
+ (modref_lattice::release): New member unction.
+ (modref_lattice::dump): New member function.
+ (modref_lattice::add_escape_point): New member function.
+ (modref_lattice::merge): Two new member functions.
+ (modref_lattice::merge_deref): New member functions.
+ (modref_lattice::merge_direct_load): New member function.
+ (modref_lattice::merge_direct_store): New member function.
+ (call_lhs_flags): Rename to ...
+ (merge_call_lhs_flags): ... this one; reimplement using
+ modreflattice.
+ (analyze_ssa_name_flags): Replace KNOWN_FLAGS param by LATTICE;
+ add IPA parametr; use modref_lattice.
+ (analyze_parms): New parameter IPA and SUMMARY_LTO; update for
+ modref_lattice; initialize escape_summary.
+ (analyze_function): Allocate escape_summaries; update uses of useful_p.
+ (modref_write_escape_summary): New function.
+ (modref_read_escape_summary): New function.
+ (modref_write): Write escape summary.
+ (read_section): Read escape summary.
+ (modref_read): Initialie escape_summaries.
+ (remap_arg_flags): New function.
+ (update_signature): Use it.
+ (escape_map): New structure.
+ (update_escape_summary_1, update_escape_summary): New functions.
+ (ipa_merge_modref_summary_after_inlining): Merge escape summaries.
+ (propagate_unknown_call): Do not remove useless summaries.
+ (remove_useless_summaries): Remove them here.
+ (modref_propagate_in_scc): Update; do not dump scc.
+ (modref_propagate_dump_scc): New function.
+ (modref_merge_call_site_flags): New function.
+ (modref_propagate_flags_in_scc): New function.
+ (pass_ipa_modref::execute): Use modref_propagate_flags_in_scc
+ and modref_propagate_dump_scc; delete escape_summaries.
+ (ipa_modref_c_finalize): Remove escape_summaries.
+ * ipa-modref.h (modref_summary): Update prototype of useful_p.
+ * params.opt (param=modref-max-escape-points): New param.
+ * doc/invoke.texi (modref-max-escape-points): Document.
+
+2020-11-16 Jan Hubicka <jh@suse.cz>
+
+ PR middle-end/97840
+ * ipa-modref.c (analyze_ssa_name_flags): Skip clobbers if inlining
+ is done.
+ * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Make stmt gcall;
+ skip const calls and unused arguments.
+ (warn_uninitialized_vars): Update prototype.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (vect_gather_slp_loads): Declare.
+ * tree-vect-loop.c (vect_analyze_loop_2): Call
+ vect_gather_slp_loads.
+ * tree-vect-slp.c (vect_build_slp_instance): Do not gather
+ SLP loads here.
+ (vect_gather_slp_loads): Remove wrapper, new function.
+ (vect_slp_analyze_bb_1): Call it.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-loop-im.c (analyze_memory_references): Add
+ store_motion parameter and elide unnecessary work.
+ (tree_ssa_lim_initialize): Likewise.
+ (loop_invariant_motion_in_fun): Pass down store_motion.
+
+2020-11-16 Martin Liska <mliska@suse.cz>
+
+ * params.opt: All modref parameters miss Optimization and Param
+ keyword as seen in testsuite failure.
+
+2020-11-16 Jan Hubicka <jh@suse.cz>
+
+ * params.opt (-param=modref-max-depth=): Add missing full stop.
+
+2020-11-16 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * common.opt (fprofile-info-section): New.
+ * coverage.c (build_gcov_info_var_registration): New.
+ (coverage_obj_init): Evaluate profile_info_section and use
+ build_gcov_info_var_registration().
+ * doc/invoke.texi (fprofile-info-section): Document.
+ * opts.c (common_handle_option): Process fprofile-info-section
+ option.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97838
+ * tree-vect-slp.c (vect_slp_build_vertices): Properly handle
+ not backwards reachable cycles.
+ (vect_optimize_slp): Check a node is leaf before marking it
+ visited.
+
+2020-11-16 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/97736
+ * tree-switch-conversion.c (switch_decision_tree::analyze_switch_statement):
+ Prefer bit tests.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97835
+ * tree-vect-loop.c (vectorizable_induction): Convert step
+ scalars rather than step vector.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97830
+ * tree-ssa-sccvn.c (vn_reference_eq): Check for incomplete
+ types before comparing TYPE_SIZE.
+
+2020-11-16 Cui,Lili <lili.cui@intel.com>
+
+ * config/i386/i386.h: Add PREFETCHW to march=broadwell.
+ * doc/invoke.texi: Put PREFETCHW back to relation arch.
+
+2020-11-15 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (msp430_output_labelref): Don't process mspabi
+ hwmult library function names into GCC-style names.
+
+2020-11-15 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (msp430_use_16bit_hwmult): New.
+ (use_32bit_hwmult): Rename to..
+ (msp430_use_32bit_hwmult): ..this.
+ (msp430_muldiv_costs): Use msp430_use_16bit_hwmult and
+ msp430_use_32bit_hwmult.
+ (msp430_expand_helper): Use msp430_use_16bit_hwmult and
+ msp430_use_32bit_hwmult.
+ (msp430_output_labelref): Use msp430_use_32bit_hwmult.
+
+2020-11-15 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_rtx_costs): Use `rtx_code' rather than
+ `int' for `code'.
+
+2020-11-15 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_output_int_add) <E_DImode>: Fix a typo
+ in NO_EXTERNAL_INDIRECT_ADDRESS.
+
+2020-11-15 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * config/vax/vax.c (vax_output_int_add) <E_SImode>: Also check
+ `operands[2]' for being symbolic with PIC rather than checking
+ `operands[1]' twice.
+
+2020-11-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * vr-values.c (vr_values::extract_range_builtin): Rename to...
+ (vr_values::extract_range_from_ubsan_builtin): ...this.
+ Remove everything but UBSAN code.
+ (vr_values::extract_range_basic): Call ranger version for
+ everything except UBSAN built-ins.
+ * vr-values.h (class vr_values): Rename extract_range_builtin to
+ extract_range_from_ubsan_builtin.
+
+2020-11-15 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * lra.c (lra_process_new_insns): Don't put reload insns in the
+ last empty BB.
+
+2020-11-15 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (analyze_ssa_name_flags): Make return to clear
+ EAF_UNUSED flag.
+
+2020-11-14 Jan Hubicka <jh@suse.cz>
+
+ * gimple.c: Include ipa-modref-tree.h and ipa-modref.h.
+ (gimple_call_arg_flags): Use modref to determine flags.
+ * ipa-modref.c: Include gimple-ssa.h, tree-phinodes.h,
+ tree-ssa-operands.h, stringpool.h and tree-ssanames.h.
+ (analyze_ssa_name_flags): Declare.
+ (modref_summary::useful_p): Summary is also useful if arg flags are
+ known.
+ (dump_eaf_flags): New function.
+ (modref_summary::dump): Use it.
+ (get_modref_function_summary): Be read for current_function_decl
+ being NULL.
+ (memory_access_to): New function.
+ (deref_flags): New function.
+ (call_lhs_flags): New function.
+ (analyze_parms): New function.
+ (analyze_function): Use it.
+ * ipa-modref.h (struct modref_summary): Add arg_flags.
+ * doc/invoke.texi (ipa-modref-max-depth): Document.
+ * params.opt (ipa-modref-max-depth): New param.
+
+2020-11-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/97599
+ * dwarf2out.c (gen_subprogram_die): Call
+ gen_unspecified_parameters_die even if not early dwarf, but only
+ if subr_die is a newly created DIE.
+
+2020-11-14 Monk Chiang <monk.chiang@sifive.com>
+
+ PR target/97682
+ * config/riscv/riscv.h (RISCV_PROLOGUE_TEMP_REGNUM): Change register
+ to t0.
+ (RISCV_CALL_ADDRESS_TEMP_REGNUM): New Marco, define t1 register.
+ (RISCV_CALL_ADDRESS_TEMP): Use it for call instructions.
+ * config/riscv/riscv.c (riscv_legitimize_call_address): Use
+ RISCV_CALL_ADDRESS_TEMP.
+ (riscv_compute_frame_info): Change temporary register to t0 form t1.
+ (riscv_trampoline_init): Adjust comment.
+
+2020-11-14 Jim Wilson <jimw@sifive.com>
+ cooper.joshua <cooper.joshua@linux.alibaba.com>
+
+ * config/riscv/riscv.c (riscv_asan_shadow_offset): New.
+ (TARGET_ASAN_SHADOW_OFFSET): New.
+ * doc/tm.texi: Regenerated.
+ * target.def (asan_shadow_offset); Mention that it can return zero.
+ * toplev.c (process_options): Check for and handle zero return from
+ targetm.asan_shadow_offset call.
+
+2020-11-14 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_omp_for): Add OMP_CLAUSE_ALLOCATE_ALLOCATOR
+ decls as firstprivate on task clauses even when allocate clause
+ decl is not lastprivate.
+ * omp-low.c (install_var_field): Don't dereference omp_is_reference
+ types if mask is 33 rather than 1.
+ (scan_sharing_clauses): Populate allocate_map even for task
+ constructs. For now remove it back for variables mentioned in
+ reduction and in_reduction clauses on task/taskloop constructs
+ or on VLA task firstprivates. For firstprivate on task construct,
+ install the var field into field_map with by_ref and 33 instead
+ of false and 1 if mentioned in allocate clause.
+ (lower_private_allocate): Set TREE_THIS_NOTRAP on the created
+ MEM_REF.
+ (lower_rec_input_clauses): Handle allocate for task firstprivatized
+ non-VLA variables.
+ (create_task_copyfn): Likewise.
+
+2020-11-13 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (ao_ref_base_alias_ptr_type): Remove accidental
+ commit.
+ (ao_ref_alias_ptr_type): Remove accidental commit.
+
+2020-11-13 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * omp-oacc-kernels-decompose.cc (maybe_build_inner_data_region):
+ Use langhook instead of accessing language-specific decl
+ information.
+
+2020-11-13 Gergö Barany <gergo@codesourcery.com>
+ Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-oacc-kernels-decompose.cc: New.
+ * Makefile.in (OBJS): Add it.
+ * passes.def: Instantiate it.
+ * tree-pass.h (make_pass_omp_oacc_kernels_decompose): Declare.
+ * flag-types.h (enum openacc_kernels): Add.
+ * doc/invoke.texi (-fopenacc-kernels): Document.
+ * gimple.h (enum gf_mask): Add
+ 'GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED',
+ 'GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE',
+ 'GF_OMP_TARGET_KIND_OACC_DATA_KERNELS'.
+ (is_gimple_omp_oacc, is_gimple_omp_offloaded): Handle these.
+ * gimple-pretty-print.c (dump_gimple_omp_target): Likewise.
+ * omp-expand.c (expand_omp_target, build_omp_regions_1)
+ (omp_make_gimple_edges): Likewise.
+ * omp-low.c (scan_sharing_clauses, scan_omp_for)
+ (check_omp_nesting_restrictions, lower_oacc_reductions)
+ (lower_oacc_head_mark, lower_omp_target): Likewise.
+ * omp-offload.c (execute_oacc_device_lower): Likewise.
+
+2020-11-13 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-low.c (scan_sharing_clauses, scan_omp_for)
+ (lower_oacc_reductions, lower_omp_target): More explicit checking
+ of which OMP constructs we're expecting.
+
+2020-11-13 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-expand.c (expand_omp_target): Attach an attribute to all
+ outlined OpenACC compute regions.
+ * omp-offload.c (execute_oacc_device_lower): Adjust.
+
+2020-11-13 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (modref_summaries::insert,
+ modref_summaries_lto::insert): Remove summary if ipa-modref is disabled.
+
+2020-11-13 Jan Hubicka <jh@suse.cz>
+
+ * attr-fnspec.h (attr_fnspec::arg_readonly_p): Accept '1'...'9'.
+
+2020-11-13 Peter Jones <pjones@redhat.com>
+
+ * doc/extend.texi: Clarify the documentation for the ms_abi
+ function attribute.
+
+2020-11-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range.h (gimple_range_handler): Cast to gimple stmt
+ kinds before asking for code and type.
+ * gimple.h (gimple_expr_code): Call gassign and gcond routines
+ to get their expr_code.
+
+2020-11-13 Jason Merrill <jason@redhat.com>
+
+ * dwarf2out.c (gen_enumeration_type_die): Call
+ equate_decl_number_to_die for enumerators.
+ (gen_member_die): Don't move enumerators to their
+ enclosing class.
+ (dwarf2out_imported_module_or_decl_1): Allow importing
+ individual enumerators.
+ (force_decl_die): Handle CONST_DECL.
+
+2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * cfgexpand.c (expand_asm_stmt): Output asm goto with outputs too.
+ Place insns after asm goto on edges.
+ * doc/extend.texi: Reflect the changes in asm goto documentation.
+ * gimple.c (gimple_build_asm_1): Remove an assert checking output
+ absence for asm goto.
+ * gimple.h (gimple_asm_label_op, gimple_asm_set_label_op): Take
+ possible asm goto outputs into account.
+ * ira.c (ira): Remove critical edges for potential asm goto output
+ reloads.
+ (ira_nullify_asm_goto): New function.
+ * ira.h (ira_nullify_asm_goto): New prototype.
+ * lra-assigns.c (lra_split_hard_reg_for): Use ira_nullify_asm_goto.
+ Check that splitting is done inside a basic block.
+ * lra-constraints.c (curr_insn_transform): Permit output reloads
+ for any jump insn.
+ * lra-spills.c (lra_final_code_change): Remove USEs added in ira
+ for asm gotos.
+ * lra.c (lra_process_new_insns): Place output reload insns after
+ jumps in the beginning of destination BBs.
+ * reload.c (find_reloads): Report error for asm gotos with
+ outputs. Modify them to keep CFG consistency to avoid crashes.
+ * tree-into-ssa.c (rewrite_stmt): Don't put debug stmt after asm
+ goto.
+
+2020-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-low.c (scan_sharing_clauses): For now remove for reduction
+ clauses with inscan or task modifiers decl from allocate_map.
+ (lower_private_allocate): Handle TYPE_P (new_var).
+ (lower_rec_input_clauses): Handle allocate clause for C/C++ array
+ reductions.
+
+2020-11-13 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/97816
+ * ipa-cp.c (value_topo_info<valtype>::propagate_effects): Use
+ safe_add instead of a simple addition.
+
+2020-11-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (TARGET_INSN_COST): Define.
+ (msp430_insn_cost): New function.
+ * config/msp430/msp430.h (BRANCH_COST): Define.
+ (LOGICAL_OP_NON_SHORT_CIRCUIT): Define.
+
+2020-11-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430-protos.h (msp430x_extendhisi): Return int
+ instead of char *.
+ (msp430_output_asm_shift_insns): Likewise.
+ Add new return_length argument.
+ (msp430x_insn_required): Add prototype.
+ * config/msp430/msp430.c (msp430_output_asm_shift_insns): Return the
+ total length, in bytes, of the emitted instructions.
+ (msp430x_insn_required): New function.
+ (msp430x_extendhisi): Return the total length, in bytes, of the
+ emitted instructions.
+ * config/msp430/msp430.h (ADJUST_INSN_LENGTH): Define.
+ * config/msp430/msp430.md: New define_attr "type".
+ New define_attr "extension".
+ New define_attr "length_multiplier".
+ New define_attr "extra_length".
+ Rewrite define_attr "length".
+ Set type, extension, length, length_multiplier or extra_length insn
+ attributes on all insns, as appropriate.
+ (andneghi3): Rewrite using constraints instead of C code to decide
+ output insns.
+ * config/msp430/predicates.md (msp430_cheap_operand): New predicate.
+ (msp430_high_memory_operand): New predicate.
+
+2020-11-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (use_helper_for_const_shift): Add forward
+ declaration.
+ Remove unused argument.
+ (struct msp430_multlib_costs): New struct.
+ (msp430_is_mem_indirect): New function.
+ (msp430_costs): Likewise.
+ (msp430_shift_costs): Likewise.
+ (msp430_muldiv_costs): Likewise.
+ (msp430_get_inner_dest_code): Likewise.
+ (msp430_single_op_cost): Likewise.
+ (msp430_rtx_costs): Rewrite from scratch.
+ (msp430_expand_shift): Adjust use_helper_for_const_shift call.
+
+2020-11-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (struct single_op_cost): New struct.
+ (struct double_op_cost): Likewise.
+ (TARGET_REGISTER_MOVE_COST): Don't define but add comment.
+ (TARGET_MEMORY_MOVE_COST): Define to...
+ (msp430_memory_move_cost): New function.
+ (BRANCH_COST): Don't define but add comment.
+
+2020-11-13 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf-gimple.c: Include tree-ssa-alias-compare.h.
+ (find_checker::func_checker): Initialize m_tbaa.
+ (func_checker::hash_operand): Use hash_ao_ref for memory accesses.
+ (func_checker::compare_operand): Use compare_ao_refs for memory
+ accesses.
+ (func_checker::cmopare_gimple_assign): Do not check LHS types
+ of memory stores.
+ * ipa-icf-gimple.h (func_checker): Derive from ao_compare;
+ add m_tbaa.
+ * ipa-icf.c: Include tree-ssa-alias-compare.h.
+ (sem_function::equals_private): Update call of
+ func_checker::func_checker.
+ * ipa-utils.h (lto_streaming_expected_p): New inline
+ predicate.
+ * tree-ssa-alias-compare.h: New file.
+ * tree-ssa-alias.c: Include tree-ssa-alias-compare.h
+ and bultins.h
+ (view_converted_memref_p): New function.
+ (types_equal_for_same_type_for_tbaa_p): New function.
+ (ao_ref_alias_ptr_type, ao_ref_base_alias_ptr_type): New functions.
+ (ao_compare::compare_ao_refs): New member function.
+ (ao_compare::hash_ao_ref): New function
+ * tree-ssa-alias.h (ao_ref_base_alias_ptr_type,
+ ao_ref_alias_ptr_type): Declare.
+
+2020-11-13 Jan Hubicka <jh@suse.cz>
+
+ * ipa-icf-gimple.c: Include gimple-walk.h.
+ (func_checker::compare_ssa_name): Update call of compare_operand.
+ (func_checker::hash_operand): Fix comment and add variant taking
+ operand_access_type parameter.
+ (func_checker::compare_operand): Add operand_access_type parameter.
+ (func_checker::compare_asm_inputs_outputs): Add
+ operand_access_type_map parameter; update use of
+ func_checker::compare_operand.
+ (func_checker::compare_gimple_call): Update use of
+ func_checker::compare_operand.
+ (func_checker::compare_gimple_assign): Likewise.
+ (func_checker::compare_gimple_cond): Likewise.
+ (func_checker::compare_gimple_switch): Likewise.
+ (func_checker::compare_gimple_return): Likewise.
+ (func_checker::compare_gimple_goto): Likewise.
+ (func_checker::compare_gimple_asm): Likewise.
+ (visit_load_store): New static functio.
+ (func_checker::classify_operands): New member function.
+ (func_checker::get_operand_access_type): New member function.
+ * ipa-icf-gimple.h (func_checker::operand_access_type): New enum
+ (func_checker::operand_access_type_map): New typedef.
+ (func_checker::compare_operand): Update prototype.
+ (func_checker::compare_asm_inputs_outputs): Likewise.
+ (func_checker::cleassify_operands): Declare.
+ (func_checker::get_operand_access_type): Declare.
+ (func_checker::hash_operand): New variant with operand_access_type.
+ * ipa-icf.c (sem_function::hash_stmt): Update uses of hash_operand.
+ (sem_function::compare_phi_node): Update use of compare_operand.
+
+2020-11-13 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/aarch-common.c (aarch_accumulator_forwarding): Use
+ RTL predicates where possible.
+ * config/arm/arm.c (legitimate_pic_operand_p)
+ (legitimize_pic_address, arm_is_segment_info_known)
+ (can_avoid_literal_pool_for_label_p)
+ (thumb1_legitimate_address_p, arm_legitimize_address)
+ (arm_tls_referenced_p, thumb_legitimate_constant_p)
+ (REG_OR_SUBREG_REG, thumb1_rtx_costs, thumb1_size_rtx_costs)
+ (arm_adjust_cost, arm_coproc_mem_operand_wb)
+ (neon_vector_mem_operand, neon_struct_mem_operand)
+ (symbol_mentioned_p, label_mentioned_p, )
+ (load_multiple_sequence, store_multiple_sequence)
+ (arm_select_cc_mode, arm_reload_in_hi, arm_reload_out_hi)
+ (mem_ok_for_ldrd_strd, arm_emit_call_insn, output_move_neon)
+ (arm_attr_length_move_neon, arm_assemble_integer)
+ (arm_emit_coreregs_64bit_shift, arm_valid_symbolic_address_p)
+ (extract_base_offset_in_addr, fusion_load_store): Likewise.
+
+2020-11-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range.cc: (gimple_ranger::range_of_range_op): Check for
+ ADDR_EXPR and call range_of_address.
+ (gimple_ranger::range_of_address): Rename from
+ range_of_non_trivial_assignment and match vrp_stmt_computes_nonzero.
+ * gimple-range.h: (range_of_address): Renamed.
+ * range-op.cc: (pointer_table): Add INTEGER_CST handler.
+
+2020-11-13 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/94406
+ * tree-ssa-loop-im.c (tree_ssa_lim): Renamed to
+ loop_invariant_motion_in_fun, added a parameter to control store
+ motion.
+ (pass_lim::execute): Adjust call to tree_ssa_lim, now
+ loop_invariant_motion_in_fun.
+ * tree-ssa-loop-manip.h (loop_invariant_motion_in_fun): Declare.
+ * gimple-loop-interchange.cc (pass_linterchange::execute): Call
+ loop_invariant_motion_in_fun if any interchange has been done.
+
+2020-11-13 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vn_phi_compute_hash): Always hash the
+ number of predecessors. Hash the block number also for
+ loop header PHIs.
+ (expressions_equal_p): Short-cut SSA name compares, remove
+ test for NULL operands.
+ (vn_phi_eq): Cache number of predecessors, change inlined
+ test from expressions_equal_p.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * doc/extend.texi: Don't try to line-wrap an @r command.
+
+2020-11-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97812
+ * tree-vrp.c (register_edge_assert_for_2): Extend the range
+ according to its sign before seeing whether it fits.
+
+2020-11-13 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/aarch64/aarch64.c (tls_symbolic_operand_type)
+ (aarch64_load_symref_appropriately, aarch64_mov128_immediate)
+ (aarch64_expand_mov_immediate)
+ (aarch64_maybe_expand_sve_subreg_move)
+ (aarch64_tls_referenced_p, aarch64_cannot_force_const_mem)
+ (aarch64_base_register_rtx_p, aarch64_classify_index)
+ (aarch64_classify_address, aarch64_symbolic_address_p)
+ (aarch64_reinterpret_float_as_int, aarch64_float_const_rtx_p)
+ (aarch64_can_const_movi_rtx_p, aarch64_select_cc_mode)
+ (aarch64_print_operand, aarch64_label_mentioned_p)
+ (aarch64_secondary_reload, aarch64_preferred_reload_class)
+ (aarch64_address_cost, aarch64_tls_symbol_p)
+ (aarch64_classify_symbol, aarch64_legitimate_pic_operand_p)
+ (aarch64_legitimate_constant_p)
+ (aarch64_sve_float_arith_immediate_p)
+ (aarch64_sve_float_mul_immediate_p, aarch64_mov_operand_p)
+ (fusion_load_store): Use RTL operands where possible.
+
+2020-11-13 Sudakshina Das <sudi.das@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_expand_setmem): New
+ declaration.
+ * config/aarch64/aarch64.c (aarch64_gen_store_pair): Add case for
+ E_V16QImode.
+ (aarch64_set_one_block_and_progress_pointer): New helper for
+ aarch64_expand_setmem.
+ (aarch64_expand_setmem): Define the expansion for memset.
+ * config/aarch64/aarch64.h (CLEAR_RATIO): Tweak to favor
+ aarch64_expand_setmem when allowed and profitable.
+ (SET_RATIO): Likewise.
+ * config/aarch64/aarch64.md: Define pattern for setmemdi.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90707
+ * doc/extend.texi: Document the objc_nullability attribute.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * doc/extend.texi: Document the objc_root_class attribute.
+ * doc/invoke.texi: Document -Wobjc-root-class.
+
+2020-11-13 Richard Biener <rguenther@suse.de>
+
+ * cfgexpand.c (gimple_assign_rhs_to_tree): Use
+ gimple_assign_rhs_class.
+ (expand_gimple_stmt_1): Likewise.
+ * gimplify-me.c (gimple_regimplify_operands): Use
+ gimple_assign_single_p.
+ * ipa-icf-gimple.c (func_checker::compare_gimple_assign):
+ Remove redundant compare.
+ (func_checker::compare_gimple_cond): Use gimple_cond_code.
+ * tree-ssa-tail-merge.c (gimple_equal_p): Likewise.
+ * predict.c (predict_loops): Use gimple_assign_rhs_code.
+
+2020-11-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (class vrp_folder): Make visit_stmt, visit_phi,
+ and m_vr_values private.
+ (vrp_folder::vrp_evaluate_conditional): Remove.
+ (vrp_folder::vrp_simplify_stmt_using_ranges): Remove.
+ (vrp_folder::fold_predicate_in): Inline
+ vrp_evaluate_conditional and vrp_simplify_stmt_using_ranges.
+ (vrp_folder::fold_stmt): Same.
+
+2020-11-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (class vrp_prop): Rename vr_values to m_vr_values.
+ (vrp_prop::vrp_prop): New.
+ (vrp_prop::initialize): Rename vr_values to m_vr_values.
+ (vrp_prop::visit_stmt): Same.
+ (vrp_prop::visit_phi): Same.
+ (vrp_prop::finalize): Same.
+ (execute_vrp): Instantiate vrp_vr_values and pass it to folder
+ and propagator.
+
+2020-11-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (class vrp_prop): Move entire class...
+ (class vrp_folder): ...before here.
+
+2020-11-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (identify_jump_threads): Refactor to..
+ (vrp_jump_threader::vrp_jump_threader): ...here
+ (vrp_jump_threader::~vrp_jump_threader): ...and here.
+ (vrp_jump_threader::after_dom_children): Rename vr_values to
+ m_vr_values.
+ (execute_vrp): Use vrp_jump_threader.
+
+2020-11-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (struct assert_locus): Move.
+ (class vrp_insert): Rename to vrp_asserts.
+ (vrp_insert::build_assert_expr_for): Move to vrp_asserts.
+ (fp_predicate): Same.
+ (vrp_insert::dump): Same.
+ (vrp_insert::register_new_assert_for): Same.
+ (extract_code_and_val_from_cond_with_ops): Move.
+ (vrp_insert::finish_register_edge_assert_for): Move to vrp_asserts.
+ (maybe_set_nonzero_bits): Move.
+ (vrp_insert::find_conditional_asserts): Move to vrp_asserts.
+ (stmt_interesting_for_vrp): Move.
+ (struct case_info): Move.
+ (compare_case_labels): Move.
+ (lhs_of_dominating_assert): Move.
+ (find_case_label_index): Move.
+ (find_case_label_range): Move.
+ (class vrp_asserts): New.
+ (vrp_asserts::build_assert_expr_for): Rename from vrp_insert.
+ (vrp_asserts::dump): Same.
+ (vrp_asserts::register_new_assert_for): Same.
+ (vrp_asserts::finish_register_edge_assert_for): Same.
+ (vrp_asserts::find_conditional_asserts): Same.
+ (vrp_asserts::compare_case_labels): Same.
+ (vrp_asserts::find_switch_asserts): Same.
+ (vrp_asserts::find_assert_locations_in_bb): Same.
+ (vrp_asserts::find_assert_locations): Same.
+ (vrp_asserts::process_assert_insertions_for): Same.
+ (vrp_asserts::compare_assert_loc): Same.
+ (vrp_asserts::process_assert_insertions): Same.
+ (vrp_asserts::insert_range_assertions): Same.
+ (vrp_asserts::all_imm_uses_in_stmt_or_feed_cond): Same.
+ (vrp_asserts::remove_range_assertions): Same.
+ (class vrp_prop): Move.
+ (all_imm_uses_in_stmt_or_feed_cond): Move.
+ (vrp_prop::vrp_initialize): Move.
+ (class vrp_folder): Move.
+ (vrp_folder::fold_predicate_in): Move.
+ (vrp_folder::fold_stmt): Move.
+ (vrp_prop::initialize): Move.
+ (vrp_prop::visit_stmt): Move.
+ (enum ssa_prop_result): Move.
+ (vrp_prop::visit_phi): Move.
+ (vrp_prop::finalize): Move.
+ (class vrp_dom_walker): Rename to...
+ (class vrp_jump_threader): ...this.
+ (vrp_jump_threader::before_dom_children): Rename from
+ vrp_dom_walker.
+ (simplify_stmt_for_jump_threading): Rename to...
+ (vrp_jump_threader::simplify_stmt): ...here.
+ (vrp_jump_threader::after_dom_children): Same.
+ (identify_jump_threads): Move.
+ (vrp_prop::vrp_finalize): Move array bounds setup code to...
+ (execute_vrp): ...here.
+
+2020-11-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range.h (gimple_range_handler): Use gimple_assign and
+ gimple_cond routines to get type and code.
+ * range-op.cc (range_op_handler): Check for integral types.
+
+2020-11-12 Nelson Chu <nelson.chu@sifive.com>
+
+ * configure: Regenerated.
+ * configure.ac: If ifunc was supported in the binutils for
+ linux toolchain, then set enable_gnu_indirect_function to yes.
+
+2020-11-12 Joseph Myers <joseph@codesourcery.com>
+
+ * doc/cpp.texi (__has_attribute): Document when scopes are allowed
+ for C.
+ (__has_c_attribute): New.
+
+2020-11-12 Jakub Jelinek <jakub@redhat.com>
+
+ * builtin-types.def (BT_FN_PTR_SIZE_SIZE_PTRMODE): New function type.
+ * omp-builtins.def (BUILT_IN_GOACC_DECLARE): Move earlier.
+ (BUILT_IN_GOMP_ALLOC, BUILT_IN_GOMP_FREE): New builtins.
+ * gimplify.c (gimplify_scan_omp_clauses): Force allocator into a
+ decl if it is not NULL, INTEGER_CST or decl.
+ (gimplify_adjust_omp_clauses): Clear GOVD_EXPLICIT on explicit clauses
+ which are being removed. Remove allocate clauses for variables not seen
+ if they are private, firstprivate or linear too. Call
+ omp_notice_variable on the allocator otherwise.
+ (gimplify_omp_for): Handle iterator vars mentioned in allocate clauses
+ similarly to non-is_gimple_reg iterators.
+ * omp-low.c (struct omp_context): Add allocate_map field.
+ (delete_omp_context): Delete it.
+ (scan_sharing_clauses): Fill it from allocate clauses. Remove it
+ if mentioned also in shared clause.
+ (lower_private_allocate): New function.
+ (lower_rec_input_clauses): Handle allocate clause for privatized
+ variables, except for task/taskloop, C/C++ array reductions for now
+ and task/inscan variables.
+ (lower_send_shared_vars): Don't consider variables in allocate_map
+ as shared.
+ * omp-expand.c (expand_omp_for_generic, expand_omp_for_static_nochunk,
+ expand_omp_for_static_chunk): Use expand_omp_build_assign instead of
+ gimple_build_assign + gsi_insert_after.
+ * builtins.c (builtin_fnspec): Handle BUILTIN_GOMP_ALLOC and
+ BUILTIN_GOMP_FREE.
+ * tree-ssa-ccp.c (evaluate_stmt): Handle BUILTIN_GOMP_ALLOC.
+ * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Handle
+ BUILTIN_GOMP_ALLOC.
+ (mark_all_reaching_defs_necessary_1): Handle BUILTIN_GOMP_ALLOC
+ and BUILTIN_GOMP_FREE.
+ (propagate_necessity): Likewise.
+
+2020-11-12 Martin Jambor <mjambor@suse.cz>
+
+ * cgraphclones.c (cgraph_node::materialize_clone): Check that clone
+ info is not NULL before attempting to dump it.
+
+2020-11-12 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-cp.c (class ipcp_value_base): Change the type of
+ local_time_benefit and prop_time_benefit to sreal. Adjust the
+ constructor initializer.
+ (ipcp_lattice::print): Dump sreals.
+ (struct caller_statistics): Change the type of freq_sum to sreal.
+ (gather_caller_stats): Work with sreal freq_sum.
+ (incorporate_penalties): Work with sreal evaluation.
+ (good_cloning_opportunity_p): Adjusted for sreal sreal time_benefit
+ and freq_sum. Bail out if size_cost is INT_MAX.
+ (perform_estimation_of_a_value): Work with sreal time_benefit. Avoid
+ unnecessary capping.
+ (estimate_local_effects): Pass sreal time benefit to
+ good_cloning_opportunity_p without capping it. Adjust dumping.
+ (safe_add): If there can be overflow, return INT_MAX.
+ (propagate_effects): Work with sreal times.
+ (get_info_about_necessary_edges): Work with sreal frequencies.
+ (decide_about_value): Likewise and with sreal time benefits.
+
+2020-11-12 Marek Polacek <polacek@redhat.com>
+
+ * system.h (WARN_UNUSED_RESULT): Define for GCC >= 3.4.
+ * tree.h (maybe_wrap_with_location): Add WARN_UNUSED_RESULT.
+
+2020-11-12 Jan Hubicka <jh@suse.cz>
+
+ * fold-const.c (operand_compare::operand_equal_p): Compare field
+ offsets in operand_equal_p and OEP_ADDRESS_OF.
+ (operand_compare::hash_operand): Update.
+
+2020-11-12 Richard Biener <rguenther@suse.de>
+
+ * bitmap.c (bitmap_list_view): Restore head->current.
+ * tree-ssa-pre.c (pre_expr_DFS): Elide expr_visited bitmap.
+ Special-case value expression bitmaps with one element.
+ (bitmap_find_leader): Likewise.
+ (sorted_array_from_bitmap_set): Elide expr_visited bitmap.
+
+2020-11-12 Jan Hubicka <jh@suse.cz>
+
+ * attr-fnspec.h: Update topleve comment.
+ (attr_fnspec::arg_direct_p): Accept 1...9.
+ (attr_fnspec::arg_maybe_written_p): Reject 1...9.
+ (attr_fnspec::arg_copied_to_arg_p): New member function.
+ * builtins.c (builtin_fnspec): Update fnspec of block copy.
+ * tree-ssa-alias.c (attr_fnspec::verify): Update.
+
+2020-11-12 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (bitmap_value_replace_in_set): Return
+ whether we have changed anything.
+ (do_pre_regular_insertion): Get topologically sorted array
+ of expressions from caller.
+ (do_pre_partial_partial_insertion): Likewise.
+ (insert): Compute topologically sorted arrays of expressions
+ here and locally iterate actual insertion. Iterate only
+ when AVAIL_OUT of an already visited block source changed.
+
+2020-11-12 Alex Coplan <alex.coplan@arm.com>
+
+ PR target/97730
+ * config/aarch64/aarch64-sve2.md (@aarch64_sve2_bcax<mode>):
+ Change to define_expand, add missing (trivially-predicated) not
+ rtx to fix wrong code bug.
+ (*aarch64_sve2_bcax<mode>): New.
+
+2020-11-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97806
+ * tree-ssa-pre.c (pre_expr_DFS): New overload for visiting
+ values, visiting all leaders for a value. Use a bitmap
+ for visited values.
+ (sorted_array_from_bitmap_set): Walk over values and adjust.
+
+2020-11-12 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/97326
+ * config/s390/vector.md: Support vector floating point modes in
+ vec_cmp.
+
+2020-11-12 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/vector.md: Rename tointvec to TOINTVEC.
+ * config/s390/vx-builtins.md: Likewise.
+
+2020-11-12 Jason Merrill <jason@redhat.com>
+
+ PR debug/97060
+ * dwarf2out.c (gen_subprogram_die): It's a declaration
+ if DECL_INITIAL isn't set.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/97424
+ * doc/invoke.texi (Static Analyzer Options): Add
+ -Wno-analyzer-shift-count-negative and
+ -Wno-analyzer-shift-count-overflow.
+ (-Wno-analyzer-shift-count-negative): New.
+ (-Wno-analyzer-shift-count-overflow): New.
+
+2020-11-11 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-protos.h (darwin_make_eh_symbol_indirect): New.
+ * config/darwin.c (darwin_make_eh_symbol_indirect): New. Use
+ Mach-O semantics for personality and ldsa indirections.
+ * config/darwin.h (TARGET_ASM_MAKE_EH_SYMBOL_INDIRECT): New.
+ * doc/tm.texi: Regenerate.
+ * doc/tm.texi.in: Add TARGET_ASM_MAKE_EH_SYMBOL_INDIRECT hook.
+ * dwarf2out.c (dwarf2out_do_cfi_startproc): If the target defines
+ a hook for indirecting personality and ldsa references, use that
+ otherwise default to ELF semantics.
+ * target.def (make_eh_symbol_indirect): New target hook.
+
+2020-11-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ * common.opt (-fabi-version): Document =15.
+ * doc/invoke.texi (C++ Dialect Options): Likewise.
+
+2020-11-11 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97518
+ * tree.c (maybe_wrap_with_location): Don't add a location
+ wrapper around an artificial and ignored decl.
+
+2020-11-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97623
+ * tree-ssa-pre.c (create_expression_by_pieces): Guard
+ NEW_SETS access.
+ (insert_into_preds_of_block): Likewise.
+
+2020-11-11 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (pre_expr_DFS): New function.
+ (sorted_array_from_bitmap_set): Use it to properly
+ topologically sort the expression set.
+ (clean): Verify we've cleaned everything we should.
+
+2020-11-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97623
+ * params.opt (-param=max-pre-hoist-insert-iterations): Remove
+ again.
+ * doc/invoke.texi (max-pre-hoist-insert-iterations): Likewise.
+ * tree-ssa-pre.c (insert): Move hoist insertion after PRE
+ insertion iteration and do not iterate it.
+
+2020-11-11 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@vcond_mask_<mode><vpred>): Extend
+ from SVE_FULL to SVE_ALL.
+ (*vcond_mask_<mode><vpred>): Likewise.
+ (@aarch64_sel_dup<mode>): Likewise.
+ (vcond<SVE_FULL:mode><v_int_equiv>): Extend to...
+ (vcond<SVE_ALL:mode><SVE_I:mode>): ...this, but requiring the
+ sizes of the container modes to match.
+ (vcondu<SVE_FULL:mode><v_int_equiv>): Extend to...
+ (vcondu<SVE_ALL:mode><SVE_I:mode>): ...this.
+ (vec_cmp<SVE_FULL_I:mode><vpred>): Extend to...
+ (vec_cmp<SVE_I:mode><vpred>): ...this.
+ (vec_cmpu<SVE_FULL_I:mode><vpred>): Extend to...
+ (vec_cmpu<SVE_I:mode><vpred>): ...this.
+ (@aarch64_pred_cmp<cmp_op><SVE_FULL_I:mode>): Extend to...
+ (@aarch64_pred_cmp<cmp_op><SVE_I:mode>): ...this.
+ (*cmp<cmp_op><SVE_FULL_I:mode>_cc): Extend to...
+ (*cmp<cmp_op><SVE_I:mode>_cc): ...this.
+ (*cmp<cmp_op><SVE_FULL_I:mode>_ptest): Extend to...
+ (*cmp<cmp_op><SVE_I:mode>_ptest): ...this.
+ (*cmp<cmp_op><SVE_FULL_I:mode>_and): Extend to...
+ (*cmp<cmp_op><SVE_I:mode>_and): ...this.
+
+2020-11-11 Richard Sandiford <richard.sandiford@arm.com>
+
+ * optabs-tree.c (expand_vec_cond_expr_p): Allow the compared values
+ and the selected values to have different mode sizes.
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Likewise.
+
+2020-11-11 Hongtao Liu <hongtao.liu@intel.com>
+ Hongyu Wang <hongyu.wang@intel.com>
+
+ * common/config/i386/cpuinfo.h (get_available_features):
+ Detect AVXVNNI.
+ * common/config/i386/i386-common.c
+ (OPTION_MASK_ISA2_AVXVNNI_SET,
+ OPTION_MASK_ISA2_AVXVNNI_UNSET): New.
+ (OPTION_MASK_ISA2_AVX2_UNSET): Add AVXVNNI.
+ (ix86_hanlde_option): Handle -mavxvnni, unset avxvnni when
+ avx2 is disabled.
+ * common/config/i386/i386-cpuinfo.h (enum processor_features):
+ Add FEATURE_AVXVNNI.
+ * common/config/i386/i386-isas.h: Add ISA_NAMES_TABLE_ENTRY
+ for avxvnni.
+ * config.gcc: Add avxvnniintrin.h.
+ * config/i386/avx512vnnivlintrin.h: Reimplement 128/256 bit non-mask
+ intrinsics with macros to support unified interface.
+ * config/i386/avxvnniintrin.h: New header file.
+ * config/i386/cpuid.h (bit_AVXVNNI): New.
+ * config/i386/i386-builtins.c (def_builtin): Handle AVXVNNI mask
+ for unified builtin.
+ * config/i386/i386-builtin.def (BDESC): Adjust AVX512VNNI
+ builtins for AVXVNNI.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Define
+ __AVXVNNI__.
+ * config/i386/i386-expand.c (ix86_expand_builtin): Handle bisa
+ for AVXVNNI to support unified intrinsic name, since there is no
+ dependency between AVX512VNNI and AVXVNNI.
+ * config/i386/i386-options.c (isa2_opts): Add -mavxvnni.
+ (ix86_valid_target_attribute_inner_p): Handle avxnnni.
+ (ix86_option_override_internal): Ditto.
+ * config/i386/i386.h (TARGET_AVXVNNI, TARGET_AVXVNNI_P,
+ TARGET_AVXVNNI_P, PTA_AVXVNNI): New.
+ (PTA_SAPPHIRERAPIDS): Add AVX_VNNI.
+ (PTA_ALDERLAKE): Likewise.
+ * config/i386/i386.md ("isa"): Add avxvnni, avx512vnnivl.
+ ("enabled"): Adjust for avxvnni and avx512vnnivl.
+ * config/i386/i386.opt: Add option -mavxvnni.
+ * config/i386/immintrin.h: Include avxvnniintrin.h.
+ * config/i386/sse.md (vpdpbusd_<mode>): Adjust for AVXVNNI.
+ (vpdpbusds_<mode>): Likewise.
+ (vpdpwssd_<mode>): Likewise.
+ (vpdpwssds_<mode>): Likewise.
+ (vpdpbusd_v16si): New.
+ (vpdpbusds_v16si): Likewise.
+ (vpdpwssd_v16si): Likewise.
+ (vpdpwssds_v16si): Likewise.
+ * doc/invoke.texi: Document -mavxvnni.
+ * doc/extend.texi: Document avxvnni.
+ * doc/sourcebuild.texi: Document target avxvnni.
+
+2020-11-11 Martin Liska <mliska@suse.cz>
+
+ * tree.c (copy_node): Fix spelling.
+
+2020-11-11 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (phi_translate_set): Do not sort the
+ expression set topologically.
+
+2020-11-11 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (irange::set): Early exit on VR_VARYING.
+
+2020-11-11 Zhiheng Xie <xiezhiheng@huawei.com>
+ Nannan Zheng <zhengnannan@huawei.com>
+
+ * config/aarch64/aarch64-simd-builtins.def: Add proper FLAG
+ for arithmetic operation intrinsics.
+
+2020-11-11 Strager Neds <strager.nds@gmail.com>
+
+ * cgraph.h (symtab_node::set_section_for_node): Declare new
+ overload.
+ (symtab_node::set_section_from_string): Rename from set_section.
+ (symtab_node::set_section_from_node): Declare.
+ * symtab.c (symtab_node::set_section_for_node): Define new
+ overload.
+ (symtab_node::set_section_from_string): Rename from set_section.
+ (symtab_node::set_section_from_node): Define.
+ (symtab_node::set_section): Call renamed set_section_from_string.
+ (symtab_node::set_section): Call new set_section_from_node.
+
+2020-11-11 Strager Neds <strager.nds@gmail.com>
+
+ * symtab.c (symtab_node::set_section_for_node): Extract reference
+ counting logic into ...
+ (retain_section_hash_entry): ... here (new function) and ...
+ (release_section_hash_entry): ... here (new function).
+
+2020-11-11 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/i386.h (PTA_MOVDIRI, PTA_MOVDIR64B,
+ PTA_AMX_TILE, PTA_AMX_INT8, PTA_AMX_BF16, PTA_HRESET):
+ Formatting.
+
+2020-11-11 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.h (HAVE_TF): Use opaque value when
+ GENERATOR_FILE is defined.
+
+2020-11-10 Strager Neds <strager.nds@gmail.com>
+
+ * cgraph.h (symtab_node::get_section): Constify.
+ (symtab_node::set_section): Declare new overload.
+ * symtab.c (symtab_node::set_section): Define new overload.
+ (symtab_node::copy_visibility_from): Use new overload of
+ symtab_node::set_section.
+ (symtab_node::resolve_alias): Same.
+ * tree.h (set_decl_section_name): Declare new overload.
+ * tree.c (set_decl_section_name): Define new overload.
+ * tree-emutls.c (get_emutls_init_templ_addr): Same.
+ * cgraphclones.c (cgraph_node::create_virtual_clone): Use new
+ overload of symtab_node::set_section.
+ (cgraph_node::create_version_clone_with_body): Same.
+ * trans-mem.c (ipa_tm_create_version): Same.
+
+2020-11-10 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (irange::set): Early exit for poly ints.
+
+2020-11-10 Tobias Burnus <tobias@codesourcery.com>
+
+ * gimplify.c (gimplify_scan_omp_clauses, gimplify_omp_loop): Use 'do'
+ instead of 'for' in error messages for Fortran.
+ * omp-low.c (check_omp_nesting_restrictions): Likewise
+
+2020-11-10 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * opts.c (control_options_for_live_patching): Reform 'is incompatible
+ with' error messages to use a standard message with differing format
+ arguments.
+ (finish_options): Likewise.
+
+2020-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97769
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel):
+ Remove assert.
+
+2020-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97780
+ * tree-ssa-pre.c (fini_pre): Deal with added basic blocks
+ when freeing PHI_TRANS_TABLE.
+
+2020-11-10 Zhiheng Xie <xiezhiheng@huawei.com>
+ Nannan Zheng <zhengnannan@huawei.com>
+
+ * config/aarch64/aarch64-simd-builtins.def: Add proper FLAG
+ for tbl/tbx intrinsics.
+
+2020-11-10 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * gimplify.c (is_or_contains_p): New static helper function.
+ (omp_target_reorder_clauses): New function.
+ (gimplify_scan_omp_clauses): Add use of omp_target_reorder_clauses to
+ reorder clause list according to OpenMP 5.0 rules. Add handling of
+ GOMP_MAP_ATTACH_DETACH for OpenMP cases.
+ * omp-low.c (is_omp_target): New static helper function.
+ (scan_sharing_clauses): Add scan phase handling of GOMP_MAP_ATTACH/DETACH
+ for OpenMP cases.
+ (lower_omp_target): Add lowering handling of GOMP_MAP_ATTACH/DETACH for
+ OpenMP cases.
+
+2020-11-10 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390-modes.def (FPRX2): New mode.
+ * config/s390/s390-protos.h (s390_fma_allowed_p): New function.
+ * config/s390/s390.c (s390_fma_allowed_p): Likewise.
+ (s390_build_signbit_mask): Support 128-bit masks.
+ (print_operand): Support printing the second word of a TFmode
+ operand as vector register.
+ (constant_modes): Add FPRX2mode.
+ (s390_class_max_nregs): Return 1 for TFmode on z14+.
+ (s390_is_fpr128): New function.
+ (s390_is_vr128): Likewise.
+ (s390_can_change_mode_class): Use s390_is_fpr128 and
+ s390_is_vr128 in order to determine whether mode refers to a FPR
+ pair or to a VR.
+ (s390_emit_compare): Force TFmode operands into registers on
+ z14+.
+ * config/s390/s390.h (HAVE_TF): New macro.
+ (EXPAND_MOVTF): New macro.
+ (EXPAND_TF): Likewise.
+ * config/s390/s390.md (PFPO_OP_TYPE_FPRX2): PFPO_OP_TYPE_TF
+ alias.
+ (ALL): Add FPRX2.
+ (FP_ALL): Add FPRX2 for z14+, restrict TFmode to z13-.
+ (FP): Likewise.
+ (FP_ANYTF): New mode iterator.
+ (BFP): Add FPRX2 for z14+, restrict TFmode to z13-.
+ (TD_TF): Likewise.
+ (xde): Add FPRX2.
+ (nBFP): Likewise.
+ (nDFP): Likewise.
+ (DSF): Likewise.
+ (DFDI): Likewise.
+ (SFSI): Likewise.
+ (DF): Likewise.
+ (SF): Likewise.
+ (fT0): Likewise.
+ (bt): Likewise.
+ (_d): Likewise.
+ (HALF_TMODE): Likewise.
+ (tf_fpr): New mode_attr.
+ (type): New mode_attr.
+ (*cmp<mode>_ccz_0): Use type instead of mode with fsimp.
+ (*cmp<mode>_ccs_0_fastmath): Likewise.
+ (*cmptf_ccs): New pattern for wfcxb.
+ (*cmptf_ccsfps): New pattern for wfkxb.
+ (mov<mode>): Rename to mov<mode><tf_fpr>.
+ (signbit<mode>2): Rename to signbit<mode>2<tf_fpr>.
+ (isinf<mode>2): Renamed to isinf<mode>2<tf_fpr>.
+ (*TDC_insn_<mode>): Use type instead of mode with fsimp.
+ (fixuns_trunc<FP:mode><GPR:mode>2): Rename to
+ fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>.
+ (fix_trunctf<mode>2): Rename to fix_trunctf<mode>2_fpr.
+ (floatdi<mode>2): Rename to floatdi<mode>2<tf_fpr>, use type
+ instead of mode with itof.
+ (floatsi<mode>2): Rename to floatsi<mode>2<tf_fpr>, use type
+ instead of mode with itof.
+ (*floatuns<GPR:mode><FP:mode>2): Use type instead of mode for
+ itof.
+ (floatuns<GPR:mode><FP:mode>2): Rename to
+ floatuns<GPR:mode><FP:mode>2<tf_fpr>.
+ (trunctf<mode>2): Rename to trunctf<mode>2_fpr, use type instead
+ of mode with fsimp.
+ (extend<DSF:mode><BFP:mode>2): Rename to
+ extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>.
+ (<FPINT:fpint_name><BFP:mode>2): Rename to
+ <FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>, use type instead of
+ mode with fsimp.
+ (rint<BFP:mode>2): Rename to rint<BFP:mode>2<BFP:tf_fpr>, use
+ type instead of mode with fsimp.
+ (<FPINT:fpint_name><DFP:mode>2): Use type instead of mode for
+ fsimp.
+ (rint<DFP:mode>2): Likewise.
+ (trunc<BFP:mode><DFP_ALL:mode>2): Rename to
+ trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
+ (trunc<DFP_ALL:mode><BFP:mode>2): Rename to
+ trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
+ (extend<BFP:mode><DFP_ALL:mode>2): Rename to
+ extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
+ (extend<DFP_ALL:mode><BFP:mode>2): Rename to
+ extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
+ (add<mode>3): Rename to add<mode>3<tf_fpr>, use type instead of
+ mode with fsimp.
+ (*add<mode>3_cc): Use type instead of mode with fsimp.
+ (*add<mode>3_cconly): Likewise.
+ (sub<mode>3): Rename to sub<mode>3<tf_fpr>, use type instead of
+ mode with fsimp.
+ (*sub<mode>3_cc): Use type instead of mode with fsimp.
+ (*sub<mode>3_cconly): Likewise.
+ (mul<mode>3): Rename to mul<mode>3<tf_fpr>, use type instead of
+ mode with fsimp.
+ (fma<mode>4): Restrict using s390_fma_allowed_p.
+ (fms<mode>4): Restrict using s390_fma_allowed_p.
+ (div<mode>3): Rename to div<mode>3<tf_fpr>, use type instead of
+ mode with fdiv.
+ (neg<mode>2): Rename to neg<mode>2<tf_fpr>.
+ (*neg<mode>2_cc): Use type instead of mode with fsimp.
+ (*neg<mode>2_cconly): Likewise.
+ (*neg<mode>2_nocc): Likewise.
+ (*neg<mode>2): Likeiwse.
+ (abs<mode>2): Rename to abs<mode>2<tf_fpr>, use type instead of
+ mode with fdiv.
+ (*abs<mode>2_cc): Use type instead of mode with fsimp.
+ (*abs<mode>2_cconly): Likewise.
+ (*abs<mode>2_nocc): Likewise.
+ (*abs<mode>2): Likewise.
+ (*negabs<mode>2_cc): Likewise.
+ (*negabs<mode>2_cconly): Likewise.
+ (*negabs<mode>2_nocc): Likewise.
+ (*negabs<mode>2): Likewise.
+ (sqrt<mode>2): Rename to sqrt<mode>2<tf_fpr>, use type instead
+ of mode with fsqrt.
+ (cbranch<mode>4): Use FP_ANYTF instead of FP.
+ (copysign<mode>3): Rename to copysign<mode>3<tf_fpr>, use type
+ instead of mode with fsimp.
+ * config/s390/s390.opt (flag_vx_long_double_fma): New
+ undocumented option.
+ * config/s390/vector.md (V_HW): Add TF for z14+.
+ (V_HW2): Likewise.
+ (VFT): Likewise.
+ (VF_HW): Likewise.
+ (V_128): Likewise.
+ (tf_vr): New mode_attr.
+ (tointvec): Add TF.
+ (mov<mode>): Rename to mov<mode><tf_vr>.
+ (movetf): New dispatcher.
+ (*vec_tf_to_v1tf): Rename to *vec_tf_to_v1tf_fpr, restrict to
+ z13-.
+ (*vec_tf_to_v1tf_vr): New pattern for z14+.
+ (*fprx2_to_tf): Likewise.
+ (*mov_tf_to_fprx2_0): Likewise.
+ (*mov_tf_to_fprx2_1): Likewise.
+ (add<mode>3): Rename to add<mode>3<tf_vr>.
+ (addtf3): New dispatcher.
+ (sub<mode>3): Rename to sub<mode>3<tf_vr>.
+ (subtf3): New dispatcher.
+ (mul<mode>3): Rename to mul<mode>3<tf_vr>.
+ (multf3): New dispatcher.
+ (div<mode>3): Rename to div<mode>3<tf_vr>.
+ (divtf3): New dispatcher.
+ (sqrt<mode>2): Rename to sqrt<mode>2<tf_vr>.
+ (sqrttf2): New dispatcher.
+ (fma<mode>4): Restrict using s390_fma_allowed_p.
+ (fms<mode>4): Likewise.
+ (neg_fma<mode>4): Likewise.
+ (neg_fms<mode>4): Likewise.
+ (neg<mode>2): Rename to neg<mode>2<tf_vr>.
+ (negtf2): New dispatcher.
+ (abs<mode>2): Rename to abs<mode>2<tf_vr>.
+ (abstf2): New dispatcher.
+ (float<mode>tf2_vr): New forwarder.
+ (float<mode>tf2): New dispatcher.
+ (floatuns<mode>tf2_vr): New forwarder.
+ (floatuns<mode>tf2): New dispatcher.
+ (fix_trunctf<mode>2_vr): New forwarder.
+ (fix_trunctf<mode>2): New dispatcher.
+ (fixuns_trunctf<mode>2_vr): New forwarder.
+ (fixuns_trunctf<mode>2): New dispatcher.
+ (<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>): New pattern.
+ (<FPINT:fpint_name>tf2): New forwarder.
+ (rint<mode>2<tf_vr>): New pattern.
+ (rinttf2): New forwarder.
+ (*trunctfdf2_vr): New pattern.
+ (trunctfdf2_vr): New forwarder.
+ (trunctfdf2): New dispatcher.
+ (trunctfsf2_vr): New forwarder.
+ (trunctfsf2): New dispatcher.
+ (extenddftf2_vr): New pattern.
+ (extenddftf2): New dispatcher.
+ (extendsftf2_vr): New forwarder.
+ (extendsftf2): New dispatcher.
+ (signbittf2_vr): New forwarder.
+ (signbittf2): New dispatchers.
+ (isinftf2_vr): New forwarder.
+ (isinftf2): New dispatcher.
+ * config/s390/vx-builtins.md (*vftci<mode>_cconly): Use VF_HW
+ instead of VECF_HW, add missing constraint, add vw support.
+ (vftci<mode>_intcconly): Use VF_HW instead of VECF_HW.
+ (*vftci<mode>): Rename to vftci<mode>, use VF_HW instead of
+ VECF_HW, and vw support.
+ (vftci<mode>_intcc): Use VF_HW instead of VECF_HW.
+
+2020-11-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * range-op.cc (operator_logical_not::fold_range): Tidy up.
+ (operator_logical_not::op1_range): Call above method.
+ (operator_bitwise_not::fold_range): If the type is compatible
+ with boolean, call op_logical_not.fold_range.
+ (operator_bitwise_not::op1_range): If the type is compatible
+ with boolean, call op_logical_not.op1_range.
+
+2020-11-10 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (pre_expr_d::value_id): Add.
+ (constant_value_expressions): Turn into an array of pre_expr.
+ (get_or_alloc_expr_for_nary): New function.
+ (get_or_alloc_expr_for_reference): Likewise.
+ (add_to_value): For constant values only ever add a single
+ CONSTANT.
+ (get_expr_value_id): Return the new value_id member.
+ (vn_valnum_from_value_id): Split out and simplify constant
+ value id handling.
+ (get_or_alloc_expr_for_constant): Set the value_id member.
+ (phi_translate_1): Use get_or_alloc_expr_for_*.
+ (compute_avail): Likewise.
+ (bitmap_find_leader): Simplify constant value id handling.
+
+2020-11-10 Alex Coplan <alex.coplan@arm.com>
+
+ * doc/md.texi (Modifiers): Fix grammar in description of
+ earlyclobber constraint modifier.
+
+2020-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97764
+ * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): For
+ little-endian stores with negative pd.offset, subtract
+ BITS_PER_UNIT - amnt from size if amnt is non-zero.
+
+2020-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97760
+ * tree-vect-loop.c (check_reduction_path): Reject
+ reduction paths we do not handle in epilogue generation.
+
+2020-11-10 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/97767
+ * value-range.cc (dump_bound_with_infinite_markers): Use
+ wi::min_value and wi::max_value.
+ (range_tests_strict_enum): New.
+ (range_tests): Call range_tests_strict_enum.
+ * value-range.h (irange::varying_p): Use wi::min_value
+ and wi::max_value.
+ (irange::set_varying): Same.
+ (irange::normalize_min_max): Remove comment.
+
+2020-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97567
+ * gimple-range-gori.cc: (gori_compute::logical_combine): False
+ OR operations should intersect the 2 results.
+ (gori_compute::compute_logical_operands_in_chain): If def chains
+ are outside the current basic block, don't follow them.
+
+2020-11-09 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_split_move): Recognize vadd2 instructions.
+ * config/arc/arc.md (movdi_insn): Update pattern to use vadd2
+ instructions.
+ (movdf_insn): Likewise.
+ (maddhisi4): New pattern.
+ (umaddhisi4): Likewise.
+ * config/arc/simdext.md (mov<mode>_int): Update pattern to use
+ vadd2.
+ (sdot_prodv4hi): New pattern.
+ (udot_prodv4hi): Likewise.
+ (arc_vec_<V_US>mac_hi_v4hi): Update/renamed to
+ arc_vec_<V_US>mac_v2hiv2si.
+ (arc_vec_<V_US>mac_v2hiv2si_zero): New pattern.
+ * config/arc/constraints.md (Ral): Accumulator register
+ constraint.
+
+2020-11-09 Aldy Hernandez <aldyh@redhat.com>
+
+ * function-tests.c (test_ranges): Call range_op_tests.
+ * range-op.cc (build_range3): Move to value-range.cc.
+ (range3_tests): Same.
+ (int_range_max_tests): Same.
+ (multi_precision_range_tests): Same.
+ (range_tests): Same.
+ (operator_tests): Split up...
+ (range_op_tests): Split up...
+ (range_op_cast_tests): ...here.
+ (range_op_lshift_tests): ...here.
+ (range_op_rshift_tests): ...here.
+ (range_op_bitwise_and_tests): ...here.
+ * selftest.h (range_op_tests): New.
+ * value-range.cc (build_range3): New.
+ (range_tests_irange3): New.
+ (range_tests_int_range_max): New.
+ (range_tests_legacy): New.
+ (range_tests_misc): New.
+ (range_tests): New.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97761
+ * tree-vect-slp.c (vect_bb_slp_mark_live_stmts): Remove
+ premature end of DFS walk.
+
+2020-11-09 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (irange::swap_out_of_order_endpoints): Rewrite
+ into static function.
+ (irange::set): Cleanup redundant manipulations.
+ * value-range.h (irange::normalize_min_max): Modify object
+ in-place instead of modifying arguments.
+
+2020-11-09 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/aarch64/aarch64-builtins.c
+ (aarch64_expand_fcmla_builtin): Do not alter force_reg returned
+ register.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97753
+ * tree-vect-loop.c (vectorizable_induction): Fill vec_steps
+ when CSEing inside the group.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97746
+ * tree-vect-patterns.c (vect_determine_precisions): First walk PHIs.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (get_representative_for): CSE VN_INFO calls.
+ (create_expression_by_pieces): Likewise.
+ (insert_into_preds_of_block): Likewsie.
+ (do_pre_regular_insertion): Likewsie.
+ * tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_insert):
+ Likewise.
+ (eliminate_dom_walker::eliminate_stmt): Likewise.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97765
+ * tree-ssa-pre.c (bb_bitmap_sets::phi_translate_table): Add.
+ (PHI_TRANS_TABLE): New macro.
+ (phi_translate_table): Remove.
+ (expr_pred_trans_d::pred): Remove.
+ (expr_pred_trans_d::hash): Simplify.
+ (expr_pred_trans_d::equal): Likewise.
+ (phi_trans_add): Adjust.
+ (phi_translate): Likewise. Remove hash-table expansion
+ detection and optimization.
+ (phi_translate_set): Allocate PHI_TRANS_TABLE here.
+ (init_pre): Adjsust.
+ (fini_pre): Free PHI_TRANS_TABLE.
+
+2020-11-09 Lili Cui <lili.cui@intel.com>
+
+ PR target/97685
+ * config/i386/i386.h:
+ (PTA_BROADWELL): Delete PTA_PRFCHW.
+ (PTA_SILVERMONT): Add PTA_PRFCHW.
+ (PTA_KNL): Add PTA_PREFETCHWT1.
+ (PTA_TREMONT): Add PTA_MOVDIRI, PTA_MOVDIR64B, PTA_CLDEMOTE and PTA_WAITPKG.
+ * doc/invoke.texi: Delete PREFETCHW for broadwell, skylake, knl, knm,
+ skylake-avx512, cannonlake, icelake-client, icelake-server, cascadelake,
+ cooperlake, tigerlake and sapphirerapids.
+ Add PREFETCHW for silvermont, goldmont, goldmont-plus and tremont.
+ Add XSAVEC and XSAVES for goldmont, goldmont-plus and tremont.
+ Add MOVDIRI, MOVDIR64B, CLDEMOTE and WAITPKG for tremont.
+ Add KEYLOCKER and HREST for alderlake.
+ Add AMX-BF16, AMX-TILE, AMX-INT8 and UINTR for sapphirerapids.
+ Add KEYLOCKER for tigerlake.
+
+2020-11-09 Kewen Lin <linkw@linux.ibm.com>
+
+ PR rtl-optimization/97705
+ * ira.c (ira): Refactor some regstat free/init/compute invocation
+ into lambda function regstat_recompute_for_max_regno, and call it
+ when max_regno increases as remove_scratches succeeds.
+
+2020-11-08 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Change
+ DECL_IS_BUILTIN -> DECL_IS_UNDECLARED_BUILTIN.
+
+2020-11-07 Martin Uecker <muecker@gwdg.de>
+
+ * doc/extend.texi: Document mixing labels and code.
+ * doc/invoke.texi: Likewise.
+
+2020-11-06 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (@tablejump<mode>_normal): Don't abuse
+ operands[].
+ (@tablejump<mode>_nospec): Ditto.
+
+2020-11-06 Peter Bergner <bergner@linux.ibm.com>
+
+ * config/rs6000/rs6000.h (BIGGEST_ALIGNMENT): Revert previous commit
+ so as not to break the ABI.
+ * config/rs6000/rs6000-call.c (rs6000_init_builtins): Set the ABI
+ mandated alignment for __vector_pair and __vector_quad types.
+
+2020-11-06 Jeff Law <law@torsion.usersys.redhat.com>
+
+ PR target/91489
+ * config/i386/i386.md (simple_return): Also check
+ for ms_hook_prologue function attribute.
+ * config/i386/i386.c (ix86_can_use_return_insn_p):
+ Also check for ms_hook_prologue function attribute.
+ * config/i386/i386-protos.h (ix86_function_ms_hook_prologue): Declare.
+
+2020-11-06 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/96933
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Use
+ TARGET_POWERPC64 instead of TARGET_64BIT.
+
+2020-11-06 Joseph Myers <joseph@codesourcery.com>
+
+ * builtins.def (BUILT_IN_NANSD32, BUILT_IN_NANSD64)
+ (BUILT_IN_NANSD128): New built-in functions.
+ * fold-const-call.c (fold_const_call): Handle the new built-in
+ functions.
+ * doc/extend.texi (__builtin_nansd32, __builtin_nansd64)
+ (__builtin_nansd128): Document.
+ * doc/sourcebuild.texi (Effective-Target Keywords): Document
+ fenv_exceptions_dfp.
+
+2020-11-06 Bin Cheng <bin.cheng@linux.alibaba.com>
+
+ * tree-ssa-uninit.c (find_var_cmp_const): New function.
+ (use_pred_not_overlap_with_undef_path_pred): Call above.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-c.c: Allow for Darwin20 to correspond to macOS 11.
+ * config/darwin-driver.c: Likewise.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (expr_pred_trans_d): Modify so elements
+ are embedded rather than allocated. Remove hashval member,
+ make all members integers.
+ (phi_trans_add): Adjust accordingly.
+ (phi_translate): Likewise. Deal with re-allocation
+ of the table.
+
+2020-11-06 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97737
+ PR tree-optimization/97741
+ * gimple-range.cc: (gimple_ranger::range_of_stmt): Intersect newly
+ calculated ranges with the existing known global range.
+
+2020-11-06 Darius Galis <darius.galis@cyberthorstudios.com>
+
+ * config/rx/rx.md (CTRLREG_PC): Add.
+ * config/rx/rx.c (CTRLREG_PC): Add
+ (rx_expand_builtin_mvtc): Add warning: PC register cannot
+ be used as dest.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * tree.h (DECL_IS_BUILTIN): Rename to ...
+ (DECL_IS_UNDECLARED_BUILTIN): ... here. No need to use SOURCE_LOCUS.
+ * calls.c (maybe_warn_alloc_args_overflow): Adjust for rename.
+ * cfgexpand.c (pass_expand::execute): Likewise.
+ * dwarf2out.c (base_type_die, is_naming_typedef_decl): Likewise.
+ * godump.c (go_decl, go_type_decl): Likewise.
+ * print-tree.c (print_decl_identifier): Likewise.
+ * tree-pretty-print.c (dump_generic_node): Likewise.
+ * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Likewise.
+ * xcoffout.c (xcoff_assign_fundamental_type_number): Likewise.
+
+2020-11-06 David Candler <david.candler@arm.com>
+
+ * config/aarch64/aarch64-builtins.c
+ (TYPES_SHIFT2IMM): Add define.
+ (TYPES_SHIFT2IMM_UUSS): Add define.
+ (TYPES_USHIFT2IMM): Add define.
+ * config/aarch64/aarch64-simd.md
+ (aarch64_<sur>q<r>shr<u>n2_n<mode>): Add new insn for upper saturating shift right.
+ * config/aarch64/aarch64-simd-builtins.def: Add intrinsics.
+ * config/aarch64/arm_neon.h:
+ (vqrshrn_high_n_s16): Expand using intrinsic rather than inline asm.
+ (vqrshrn_high_n_s32): Likewise.
+ (vqrshrn_high_n_s64): Likewise.
+ (vqrshrn_high_n_u16): Likewise.
+ (vqrshrn_high_n_u32): Likewise.
+ (vqrshrn_high_n_u64): Likewise.
+ (vqrshrun_high_n_s16): Likewise.
+ (vqrshrun_high_n_s32): Likewise.
+ (vqrshrun_high_n_s64): Likewise.
+ (vqshrn_high_n_s16): Likewise.
+ (vqshrn_high_n_s32): Likewise.
+ (vqshrn_high_n_s64): Likewise.
+ (vqshrn_high_n_u16): Likewise.
+ (vqshrn_high_n_u32): Likewise.
+ (vqshrn_high_n_u64): Likewise.
+ (vqshrun_high_n_s16): Likewise.
+ (vqshrun_high_n_s32): Likewise.
+ (vqshrun_high_n_s64): Likewise.
+
+2020-11-06 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-modes.def (VNx2BF, VNx4BF): Adjust nunits
+ and alignment based on the current VG.
+ * config/aarch64/iterators.md (SVE_ALL, SVE_24, SVE_2, SVE_4): Add
+ partial SVE BF modes.
+ (UNSPEC_REVBHW): New unspec.
+ (Vetype, Vesize, Vctype, VEL, Vel, vwcore, V_INT_CONTAINER)
+ (v_int_container, VPRED, vpred): Handle partial SVE BF modes.
+ (container_bits, Vcwtype): New mode attributes.
+ * config/aarch64/aarch64-sve.md
+ (@aarch64_sve_revbhw_<SVE_ALL:mode><PRED_HSD:mode>): New pattern.
+ (@aarch64_sve_dup_lane<mode>): Extended from SVE_FULL to SVE_ALL.
+ (@aarch64_sve_rev<mode>, @aarch64_sve_<perm_insn><mode>): Likewise.
+ (@aarch64_sve_ext<mode>): Likewise.
+ * config/aarch64/aarch64.c (aarch64_classify_vector_mode): Handle
+ E_VNx2BFmode and E_VNx4BFmode.
+ (aarch64_evpc_rev_local): Base the analysis on the container size
+ instead of the element size. Use the new aarch64_sve_revbhw
+ patterns for SVE.
+ (aarch64_evpc_dup): Handle partial SVE data modes. Use the
+ container size instead of the element size when applying the
+ SVE immediate limit. Fix a previously incorrect bounds check.
+ (aarch64_expand_vec_perm_const_1): Handle partial SVE data modes.
+
+2020-11-06 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Add new -fbit-tests option.
+ * doc/invoke.texi: Document the option.
+ * tree-switch-conversion.c (bit_test_cluster::find_bit_tests):
+ Use the option.
+ * tree-switch-conversion.h (is_enabled): New function.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.h (get_max_constant_value_id): Declare.
+ (get_next_constant_value_id): Likewise.
+ (value_id_constant_p): Inline and simplify.
+ * tree-ssa-sccvn.c (constant_value_ids): Remove.
+ (next_constant_value_id): Add.
+ (get_or_alloc_constant_value_id): Adjust.
+ (value_id_constant_p): Remove definition.
+ (get_max_constant_value_id): Define.
+ (get_next_value_id): Add assert for overflow.
+ (get_next_constant_value_id): Define.
+ (run_rpo_vn): Adjust.
+ (free_rpo_vn): Likewise.
+ (do_rpo_vn): Initialize next_constant_value_id.
+ * tree-ssa-pre.c (constant_value_expressions): New.
+ (add_to_value): Split into constant/non-constant value
+ handling. Avoid exact re-allocation.
+ (vn_valnum_from_value_id): Adjust.
+ (phi_translate_1): Remove spurious exact re-allocation.
+ (bitmap_find_leader): Adjust. Make sure we return
+ a CONSTANT value for a constant value id.
+ (do_pre_regular_insertion): Use 2 auto-elements for avail.
+ (do_pre_partial_partial_insertion): Likewise.
+ (init_pre): Allocate constant_value_expressions.
+ (fini_pre): Release constant_value_expressions.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97706
+ * tree-vect-patterns.c (possible_vector_mask_operation_p):
+ PHIs are possible mask operations.
+ (vect_determine_mask_precision): Handle PHIs.
+ (vect_determine_precisions): Walk PHIs in BB analysis.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_analyze_slp): Pass down the
+ SLP graph entry kind.
+ (vect_analyze_slp_instance): Simplify.
+ (vect_build_slp_instance): Adjust.
+ (vect_slp_check_for_constructors): Perform more
+ eligibility checks here.
+
+2020-11-06 Jan Hubicka <jh@suse.cz>
+
+ * ipa-ref.h (enum ipa_ref_use): Remove GTY marker.
+ (struct ipa_ref): Remove GTY marker; reorder for better packing.
+ (struct ipa_ref_list): Remove GTY marker; turn references
+ nad referring to va_heap, vl_ptr vectors; update accesors.
+ * cgraph.h (symtab_node::iterate_reference): Update.
+ * ipa-ref.c (ipa_ref::remove_reference): Update.
+ * symtab.c (symtab_node::create_reference): Update.
+ (symtab_node::remove_all_references): Update.
+ (symtab_node::resolve_alias): Update.
+
+2020-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ * ipa-modref-tree.h: Fix comment typos.
+ * ipa-modref.c: Likewise.
+
+2020-11-06 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.c (s390_option_override_internal): Remove
+ override of inline params.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97706
+ * tree-vect-patterns.c (vect_determine_mask_precision):
+ Remove worklist operation.
+ (vect_determine_stmt_precisions): Do not call
+ vect_determine_mask_precision here.
+ (vect_determine_precisions): Compute mask precision
+ in a forward walk.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97732
+ * tree-vect-loop.c (vectorizable_induction): Convert the
+ init elements to the vector component type.
+ * gimple-fold.c (gimple_build_vector): Use CONSTANT_CLASS_P
+ rather than TREE_CONSTANT to determine if elements are
+ eligible for VECTOR_CSTs.
+
+2020-11-06 Jan Hubicka <jh@suse.cz>
+
+ * attr-fnspec.h (attr_fnspec::get_str): New accessor
+ * ipa-fnsummary.c (read_ipa_call_summary): Store also parm info
+ for builtins.
+ * ipa-modref.c (class fnspec_summary): New type.
+ (class fnspec_summaries_t): New type.
+ (modref_summary::modref_summary): Initialize writes_errno.
+ (struct modref_summary_lto): Add writes_errno.
+ (modref_summary_lto::modref_summary_lto): Initialize writes_errno.
+ (modref_summary::dump): Check for NULL pointers.
+ (modref_summary_lto::dump): Dump writes_errno.
+ (collapse_loads): Move up in source file.
+ (collapse_stores): New function.
+ (process_fnspec): Handle also internal calls.
+ (analyze_call): Likewise.
+ (analyze_stmt): Store fnspec string if needed.
+ (analyze_function): Initialize fnspec_sumarries.
+ (modref_summaries_lto::duplicate): Copy writes_errno.
+ (modref_write): Store writes_errno and fnspec summaries.
+ (read_section): Read writes_errno and fnspec summaries.
+ (modref_read): Initialize fnspec summaries.
+ (update_signature): Fix formating.
+ (compute_parm_map): Return true if sucessful.
+ (get_parm_type): New function.
+ (get_access_for_fnspec): New function.
+ (propagate_unknown_call): New function.
+ (modref_propagate_in_scc): Use it.
+ (pass_ipa_modref::execute): Delete fnspec_summaries.
+ (ipa_modref_c_finalize): Delete fnspec_summaries.
+ * ipa-prop.c: Include attr-fnspec.h.
+ (ipa_compute_jump_functions_for_bb): Also compute jump functions
+ for functions with fnspecs.
+ (ipa_read_edge_info): Read jump functions for builtins.
+
+2020-11-06 Jan Hubicka <jh@suse.cz>
+
+ * ipa-fnsummary.h (class size_time_entry): Do not GTY annotate.
+ (class ipa_fnsummary): Turn size_time_table to auto_vec and
+ call_size_time_table to effecient vec; update constructors.
+ * ipa-fnsummary.c (ipa_fn_summary::account_size_time): Update.
+ (ipa_fn_summary::~ipa_fn_summary): Update.
+ (ipa_fn_summary_t::duplicate): Update.
+ (ipa_dump_fn_summary): Update.
+ (set_switch_stmt_execution_predicate): Update.
+ (analyze_function_body): Update.
+ (estimate_calls_size_and_time): Update.
+ (ipa_call_context::estimate_size_and_time): Update.
+ (ipa_merge_fn_summary_after_inlining): Update.
+ (ipa_update_overall_fn_summary): Update.
+ (inline_read_section): Update.
+ (ipa_fn_summary_write): Update.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97733
+ * tree-vect-slp.c (vect_analyze_slp_instance): If less
+ than two reductions were relevant or live do nothing.
+
+2020-11-06 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/97223
+ * match.pd (overflow detection and optimization): Handle conversions.
+
+2020-11-06 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * match.pd (x >> x): New pattern.
+
+2020-11-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.c (riscv_implied_info):
+ Add static and const.
+ (riscv_subset_list::handle_implied_ext): Add const due to
+ riscv_implied_info changed to const.
+
+2020-11-06 Kito Cheng <kito.cheng@sifive.com>
+
+ PR target/96307
+ * toplev.c (process_options): Remove param_asan_stack checking for kasan
+ option checking.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97675
+ * doc/invoke.texi: Document -Wexceptions.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/25814
+ * doc/invoke.texi: Document -Wvexing-parse.
+
+2020-11-05 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97725
+ * range-op.cc (operator_equal::fold_range): Use new tmp value.
+ (operator_not_equal::fold_range): Ditto.
+ * value-query.cc (range_query::value_of_expr): Use int_range_max
+ not a value_range.
+ (range_query::value_on_edge): Ditto.
+ (range_query::value_of_stmt): Ditto.
+
+2020-11-05 Olivier Hainque <hainque@adacore.com>
+
+ * config/aarch64/aarch64-vxworks.h (TARGET_OS_USES_R18):
+ Remove definition.
+ (STATIC_CHAIN_REGNUM): Redefine to 9.
+
+2020-11-05 Olivier Hainque <hainque@adacore.com>
+
+ * config/aarch64/aarch64.md: Define PROBE_STACK_FIRST_REGNUM
+ and PROBE_STACK_SECOND_REGNUM constants, designating r10/r11.
+ Replacements for the PROBE_STACK_FIRST/SECOND_REG constants in
+ aarch64.c.
+ * config/aarch64/aarch64.c (PROBE_STACK_FIRST_REG): Remove.
+ (PROBE_STACK_SECOND_REG): Remove.
+ (aarch64_emit_probe_stack_range): Adjust to the _REG -> _REGNUM
+ suffix update for PROBE_STACK register numbers.
+
+2020-11-05 Jan Hubicka <jh@suse.cz>
+
+ * gimple.c (gimple_call_fnspec): Handle C++ new and delete.
+ * gimple.h (gimple_call_from_new_or_delete): Constify parameter.
+
+2020-11-05 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/97721
+ * gimple-range.cc (get_tree_range): Drop overflow from constants.
+
+2020-11-05 David Malcolm <dmalcolm@redhat.com>
+
+ * tree-diagnostic-path.cc (struct path_summary::event_range): Move
+ out of path_summary to...
+ (struct event_range): ...here.
+ (class path_summary): Convert to...
+ (struct path_summary): ...this.
+ (path_summary::m_ranges): Drop "private".
+ (path_summary::print): Convert to...
+ (print_path_summary_as_text): ...this, passing in the path_summary
+ explicitly.
+ (default_tree_diagnostic_path_printer): Update for above change.
+ (selftest::test_empty_path): Likewise.
+ (selftest::test_intraprocedural_path): Likewise.
+ (selftest::test_interprocedural_path_1): Likewise.
+ (selftest::test_interprocedural_path_2): Likewise.
+ (selftest::test_recursion): Likewise.
+
+2020-11-05 qing zhao <qinzhao@gcc.gnu.org>
+
+ PR target/97715
+ * config/i386/i386.c (zero_all_st_registers): Return
+ earlier when the FPU is disabled.
+
+2020-11-05 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (parm_map_for_arg): Initialize parm_offset and
+ parm_offset_knonw.
+ (read_section): Set writes_errno to false.
+
+2020-11-05 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences):
+ Use the original stmts.
+ (vect_slp_analyze_node_alignment): Use the pattern stmt.
+ * tree-vect-slp.c (vect_fixup_store_groups_with_patterns):
+ New function.
+ (vect_slp_analyze_bb_1): Call it.
+
+2020-11-05 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-slp.c (vect_slp_tree_permute_noop_p): New.
+ (vect_optimize_slp): Optimize permutes.
+ (vectorizable_slp_permutation): Fix typo.
+
+2020-11-05 Richard Biener <rguenther@suse.de>
+
+ PR debug/97718
+ * dwarf2out.c (add_abstract_origin_attribute): Make sure to
+ point to the abstract instance.
+
+2020-11-05 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-loop.c (vect_analyze_loop_2): Check kind.
+ * tree-vect-slp.c (vect_build_slp_instance): New.
+ (enum slp_instance_kind): Move to...
+ * tree-vectorizer.h (enum slp_instance_kind): .. Here
+ (SLP_INSTANCE_KIND): New.
+
+2020-11-05 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/96933
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Use direct move
+ instructions for vector construction with char/short types.
+ * config/rs6000/rs6000.md (p8_mtvsrwz_v16qisi2): New define_insn.
+ (p8_mtvsrd_v16qidi2): Likewise.
+
+2020-11-04 Tamar Christina <tamar.christina@arm.com>
+
+ * tree-vect-slp.c (vect_analyze_slp_instance): Moved load/store lanes
+ check to ...
+ * tree-vect-loop.c (vect_analyze_loop_2): ..Here
+
+2020-11-04 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.c (NR_C_MODES): Unhardcode.
+ (s390_alloc_pool): Use size_t for iterating from 0 to
+ NR_C_MODES.
+ (s390_add_constant): Likewise.
+ (s390_find_constant): Likewise.
+ (s390_dump_pool): Likewise.
+ (s390_free_pool): Likewise.
+
+2020-11-04 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.md (RRe): Remove.
+ (RXe): Remove.
+
+2020-11-04 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97515
+ * gimple-range-cache.h (class ranger_cache): New prototypes plus
+ temporal cache pointer.
+ * gimple-range-cache.cc (struct range_timestamp): New.
+ (class temporal_cache): New.
+ (temporal_cache::temporal_cache): New.
+ (temporal_cache::~temporal_cache): New.
+ (temporal_cache::get_timestamp): New.
+ (temporal_cache::set_dependency): New.
+ (temporal_cache::temporal_value): New.
+ (temporal_cache::current_p): New.
+ (temporal_cache::set_timestamp): New.
+ (temporal_cache::set_always_current): New.
+ (ranger_cache::ranger_cache): Allocate the temporal cache.
+ (ranger_cache::~ranger_cache): Free temporal cache.
+ (ranger_cache::get_non_stale_global_range): New.
+ (ranger_cache::set_global_range): Add a timestamp.
+ (ranger_cache::register_dependency): New. Add timestamp dependency.
+ * gimple-range.cc (gimple_ranger::range_of_range_op): Add operand
+ dependencies.
+ (gimple_ranger::range_of_phi): Ditto.
+ (gimple_ranger::range_of_stmt): Check if global range is stale, and
+ recalculate if so.
+
+2020-11-04 Tobias Burnus <tobias@codesourcery.com>
+
+ * targhooks.c (default_zero_call_used_regs): Fix flag-name typo
+ in sorry.
+
+2020-11-04 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (vectorizable_phi): Adjust prototype.
+ * tree-vect-stmts.c (vect_transform_stmt): Adjust.
+ (vect_analyze_stmt): Pass cost_vec to vectorizable_phi.
+ * tree-vect-loop.c (vectorizable_phi): Do costing.
+
+2020-11-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97709
+ * tree-vect-loop.c (vectorizable_live_operation): Set
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI when necessary.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97690
+ * tree-ssa-phiopt.c (conditional_replacement): Also optimize
+ cond ? pow2p_cst : 0 as ((type) cond) << cst.
+
+2020-11-04 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-loop.c (vectorizable_induction): Re-instantiate
+ previously removed CSE of SLP IVs.
+
+2020-11-04 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-options.c (ix86_recompute_optlev_based_flags):
+ Fix Intel MCU psABI comment w.r.t DEFAULT_PCC_STRUCT_RETURN.
+
+2020-11-04 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/97666
+ * tree-vect-slp.c (vect_build_slp_tree_2): Revert previous
+ fix and instead adjust the memset.
+
+2020-11-04 Pat Bernardi <bernardi@adacore.com>
+
+ * config/i386/i386elf.h (SUBTARGET_RETURN_IN_MEMORY): Remove.
+ (ASM_OUTPUT_ASCII): Likewise.
+ (DEFAULT_PCC_STRUCT_RETURN): Define.
+ * config/i386/i386.c (ix86_return_in_memory): Remove
+ SUBTARGET_RETURN_IN_MEMORY.
+
+2020-11-04 liuhongt <hongtao.liu@intel.com>
+
+ PR target/97540
+ * ira.c: (ira_setup_alts): Extract memory from operand only
+ for special memory constraint.
+ * recog.c (asm_operand_ok): Ditto.
+ * lra-constraints.c (process_alt_operands): MEM_P is
+ required for normal memory constraint.
+
+2020-11-04 liuhongt <hongtao.liu@intel.com>
+
+ PR target/97532
+ * lra-constraints.c (valid_address_p): Handle operand of
+ special memory constraint.
+ (process_address_1): Ditto.
+
+2020-11-03 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/97695
+ * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Fix ICE with
+ in dumping code.
+ (cgraph_node::remove): Save clone info before releasing it and pass it
+ to unregister.
+ * cgraph.h (symtab_node::unregister): Add clone_info parameter.
+ (cgraph_clone::unregister): Likewise.
+ * cgraphclones.c (cgraph_node::find_replacement): Copy clone info
+ * symtab-clones.cc (clone_infos_t::duplicate): Remove.
+ (clone_info::get_create): Simplify.
+ * symtab.c (symtab_node::unregister): Pass around clone info.
+ * varpool.c (varpool_node::remove): Update.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-low.c (scan_omp_for) <OpenACC>: Use proper location to
+ 'inform' of enclosing parent compute construct.
+
+2020-11-03 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/97698
+ * cgraphclones.c (duplicate_thunk_for_node): Check that info is
+ non-NULL.
+
+2020-11-03 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_function_arg_regno_p): Use up to
+ SSE_REGPARM_MAX registers to pass function parameters
+ for 32bit Mach-O targets.
+ * config/i386/i386.h (X86_32_MMX_REGPARM_MAX): New macro.
+ (MMX_REGPARM_MAX): Use it.
+
+2020-11-03 Dennis Zhang <dennis.zhang@arm.com>
+
+ * config/aarch64/aarch64-simd-builtins.def (vget_lo_half): New entry.
+ (vget_hi_half): Likewise.
+ * config/aarch64/aarch64-simd.md (aarch64_vget_lo_halfv8bf): New entry.
+ (aarch64_vget_hi_halfv8bf): Likewise.
+ * config/aarch64/arm_neon.h (vget_low_bf16): New intrinsic.
+ (vget_high_bf16): Likewise.
+
+2020-11-03 Yang Yang <yangyang305@huawei.com>
+
+ * cgraph.h (struct cgraph_simd_clone): Change field "simdlen" of
+ struct cgraph_simd_clone from unsigned int to poly_uint64.
+ * config/aarch64/aarch64.c
+ (aarch64_simd_clone_compute_vecsize_and_simdlen): adaptation of
+ operations on "simdlen".
+ * config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen):
+ Printf formats update.
+ * gengtype.c (main): Handle poly_uint64.
+ * omp-simd-clone.c (simd_clone_mangle): Likewise.Re
+ (simd_clone_adjust_return_type): Likewise.
+ (create_tmp_simd_array): Likewise.
+ (simd_clone_adjust_argument_types): Likewise.
+ (simd_clone_init_simd_arrays): Likewise.
+ (ipa_simd_modify_function_body): Likewise.
+ (simd_clone_adjust): Likewise.
+ (expand_simd_clones): Likewise.
+ * poly-int-types.h (vector_unroll_factor): New macro.
+ * poly-int.h (constant_multiple_p): Add two-argument versions.
+ * tree-vect-stmts.c (vectorizable_simd_clone_call): Likewise.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97623
+ * params.opt (-param=max-pre-hoist-insert-iterations): New.
+ * doc/invoke.texi (max-pre-hoist-insert-iterations): Document.
+ * tree-ssa-pre.c (insert): Do at most max-pre-hoist-insert-iterations
+ hoist insert iterations.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/97579
+ * gimple-isel.cc (gimple_expand_vec_cond_expr): Use
+ the correct types for the vcond_mask/vec_cmp optab queries.
+
+2020-11-03 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (ssa_global_cache::get_global_range): Return
+ true if there was a previous range set.
+ (ranger_cache::ranger_cache): Take a gimple_ranger parameter.
+ (ranger_cache::set_global_range): Propagate the value if updating.
+ (ranger_cache::propagate_cache): Renamed from iterative_cache_update.
+ (ranger_cache::propagate_updated_value): New. Split from:
+ (ranger_cache::fill_block_cache): Split out value propagator.
+ * gimple-range-cache.h (ssa_global_cache): Update prototypes.
+ (ranger_cache): Update prototypes.
+
+2020-11-03 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.h (block_range_cache): Add new entry point.
+ (ranger_cache): Privatize global abnd block cache members.
+ * gimple-range-cache.cc (ssa_block_ranges::set_bb_range): Add bounds
+ check.
+ (ssa_block_ranges::set_bb_varying): Ditto.
+ (ssa_block_ranges::get_bb_range): Ditto.
+ (ssa_block_ranges::bb_range_p): Ditto.
+ (block_range_cache::get_block_ranges): Fix formatting.
+ (block_range_cache::query_block_ranges): New.
+ (block_range_cache::get_bb_range): Use Query_block_ranges.
+ (block_range_cache::bb_range_p): Ditto.
+ (ranger_cache::dump): New.
+ (ranger_cache::get_global_range): New.
+ (ranger_cache::set_global_range): New.
+ * gimple-range.cc (gimple_ranger::range_of_expr): Use new API.
+ (gimple_ranger::range_of_stmt): Ditto.
+ (gimple_ranger::export_global_ranges): Ditto.
+ (gimple_ranger::dump): Ditto.
+
+2020-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * fold-const.c (getbyterep): Remove duplicated statement.
+
+2020-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR target/97205
+ * cfgexpand.c (align_local_variable): Make SSA_NAMEs
+ at least MODE_ALIGNED.
+ (expand_one_stack_var_at): Increase MEM_ALIGN for SSA_NAMEs.
+
+2020-11-03 Zhiheng Xie <xiezhiheng@huawei.com>
+ Nannan Zheng <zhengnannan@huawei.com>
+
+ * config/aarch64/aarch64-simd-builtins.def: Add proper FLAG
+ for AES/SHA/SM3/SM4 intrinsics.
+
+2020-11-03 Zhiheng Xie <xiezhiheng@huawei.com>
+ Nannan Zheng <zhengnannan@huawei.com>
+
+ * config/aarch64/aarch64-simd-builtins.def: Add proper FLAG
+ for compare intrinsics.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ * dwarf2out.c (maybe_create_die_with_external_ref): Remove
+ hashtable entry.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm_neon.h (vst2_lane_bf16, vst2q_lane_bf16)
+ (vst3_lane_bf16, vst3q_lane_bf16, vst4_lane_bf16)
+ (vst4q_lane_bf16): New intrinsics.
+ * config/arm/arm_neon_builtins.def: Touch it for:
+ __builtin_neon_vst2_lanev4bf, __builtin_neon_vst2_lanev8bf,
+ __builtin_neon_vst3_lanev4bf, __builtin_neon_vst3_lanev8bf,
+ __builtin_neon_vst4_lanev4bf,__builtin_neon_vst4_lanev8bf.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm_neon.h (vld2_lane_bf16, vld2q_lane_bf16)
+ (vld3_lane_bf16, vld3q_lane_bf16, vld4_lane_bf16)
+ (vld4q_lane_bf16): Add intrinsics.
+ * config/arm/arm_neon_builtins.def: Touch for:
+ __builtin_neon_vld2_lanev4bf, __builtin_neon_vld2_lanev8bf,
+ __builtin_neon_vld3_lanev4bf, __builtin_neon_vld3_lanev8bf,
+ __builtin_neon_vld4_lanev4bf, __builtin_neon_vld4_lanev8bf.
+ * config/arm/iterators.md (VQ_HS): Add V8BF to the iterator.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm_neon.h (vst1_bf16, vst1q_bf16): Add intrinsics.
+ * config/arm/arm_neon_builtins.def : Touch for:
+ __builtin_neon_vst1v4bf, __builtin_neon_vst1v8bf.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm-builtins.c (VAR14): Define macro.
+ * config/arm/arm_neon_builtins.def: Touch for:
+ __builtin_neon_vld1v4bf, __builtin_neon_vld1v8bf.
+ * config/arm/arm_neon.h (vld1_bf16, vld1q_bf16): Add intrinsics.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm_neon.h (vst1_lane_bf16, vst1q_lane_bf16): Add
+ intrinsics.
+ * config/arm/arm_neon_builtins.def (STORE1LANE): Add v4bf, v8bf.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/arm/arm_neon_builtins.def: Add to LOAD1LANE v4bf, v8bf.
+ * config/arm/arm_neon.h (vld1_lane_bf16, vld1q_lane_bf16): Add
+ intrinsics.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/97666
+ * tree-vect-slp.c (vect_build_slp_tree_2): Scale
+ allocation of skip_args by sizeof (bool).
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/80928
+ * tree-vect-loop.c (vectorizable_induction): SLP vectorize
+ nested inductions.
+
+2020-11-03 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/97578
+ * ipa-inline-transform.c (maybe_materialize_called_clones): New
+ function.
+ (inline_transform): Use it.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97678
+ * tree-vect-slp.c (vect_build_slp_tree_2): Do not track
+ the initial values of inductions when not nested.
+ * tree-vect-loop.c (vectorizable_induction): Look at
+ PHI node initial values again for SLP and not nested
+ inductions. Handle LOOP_VINFO_MASK_SKIP_NITERS and cost
+ invariants.
+
+2020-11-03 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (aes<aeswideklvariant>u8):
+ Do not use xmm_regs array. Fix whitespace.
+
+2020-11-03 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_expand_builtin): Fix comment.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-low.c (scan_omp_for) <OpenACC>: Move earlier inconsistent
+ nested 'reduction' clauses checking.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-low.c (scan_omp_for) <OpenACC>: More precise diagnostics for
+ 'gang', 'worker', 'vector' clauses with arguments only allowed in
+ 'kernels' regions.
+
+2020-11-03 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR tree-optimization/96789
+ * function.h (struct function): New member unsigned pending_TODOs.
+ * passes.c (class pass_pre_slp_scalar_cleanup): New class.
+ (make_pass_pre_slp_scalar_cleanup): New function.
+ (pass_data_pre_slp_scalar_cleanup): New pass data.
+ * passes.def: (pass_pre_slp_scalar_cleanup): New pass, add
+ pass_fre and pass_dse as its children.
+ * timevar.def (TV_SCALAR_CLEANUP): New timevar.
+ * tree-pass.h (PENDING_TODO_force_next_scalar_cleanup): New
+ pending TODO flag.
+ (make_pass_pre_slp_scalar_cleanup): New declare.
+ * tree-ssa-loop-ivcanon.c (tree_unroll_loops_completely_1):
+ Once any outermost loop gets unrolled, flag cfun pending_TODOs
+ PENDING_TODO_force_next_scalar_cleanup on.
+
+2020-11-02 Alan Modra <amodra@gmail.com>
+
+ PR middle-end/97267
+ * calls.h (maybe_complain_about_tail_call): Declare.
+ * calls.c (maybe_complain_about_tail_call): Make global.
+ (can_implement_as_sibling_call_p): Delete reg_parm_stack_space
+ param. Adjust caller. Move REG_PARM_STACK_SPACE check to..
+ * config/i386/i386.c (ix86_function_ok_for_sibcall): ..here.
+
+2020-11-02 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * ira.c (ira_remove_scratches): Rename to remove_scratches. Make
+ it static and returning flag of any change.
+ (ira.c): Call ira_expand_reg_equiv in case of removing scratches.
+
+2020-11-02 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/97140
+ * config/i386/i386-expand.c (ix86_expand_builtin): Require MMX
+ for __builtin_ia32_maskmovq.
+
+2020-11-02 Martin Sebor <msebor@redhat.com>
+
+ * doc/invoke.texi (-Wstringop-overflow): Correct default setting.
+ (-Wstringop-overread): Move past -Wstringop-overflow.
+
+2020-11-02 François-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR bootstrap/57076
+ * Makefile.in (gcc-vers.texi): Quote @, { and }.
+
+2020-11-02 Carl Love <cel@us.ibm.com>
+
+ PR target/93449
+ * config/rs6000/altivec.h (__builtin_bcdadd, __builtin_bcdadd_lt,
+ __builtin_bcdadd_eq, __builtin_bcdadd_gt, __builtin_bcdadd_ofl,
+ __builtin_bcdadd_ov, __builtin_bcdsub, __builtin_bcdsub_lt,
+ __builtin_bcdsub_eq, __builtin_bcdsub_gt, __builtin_bcdsub_ofl,
+ __builtin_bcdsub_ov, __builtin_bcdinvalid, __builtin_bcdmul10,
+ __builtin_bcddiv10, __builtin_bcd2dfp, __builtin_bcdcmpeq,
+ __builtin_bcdcmpgt, __builtin_bcdcmplt, __builtin_bcdcmpge,
+ __builtin_bcdcmple): Add defines.
+ * config/rs6000/altivec.md: Add UNSPEC_BCDSHIFT.
+ (BCD_TEST): Add le, ge to code iterator.
+ Add VBCD mode iterator.
+ (bcd<bcd_add_sub>_test, *bcd<bcd_add_sub>_test2,
+ bcd<bcd_add_sub>_<code>, bcd<bcd_add_sub>_<code>): Add mode to name.
+ Change iterator from V1TI to VBCD.
+ (*bcdinvalid_<mode>, bcdshift_v16qi): New define_insn.
+ (bcdinvalid_<mode>, bcdmul10_v16qi, bcddiv10_v16qi): New define.
+ * config/rs6000/dfp.md (dfp_denbcd_v16qi_inst): New define_insn.
+ (dfp_denbcd_v16qi): New define_expand.
+ * config/rs6000/rs6000-builtin.def (BU_P8V_MISC_1): New define.
+ (BCDADD): Replaced with BCDADD_V1TI and BCDADD_V16QI.
+ (BCDADD_LT): Replaced with BCDADD_LT_V1TI and BCDADD_LT_V16QI.
+ (BCDADD_EQ): Replaced with BCDADD_EQ_V1TI and BCDADD_EQ_V16QI.
+ (BCDADD_GT): Replaced with BCDADD_GT_V1TI and BCDADD_GT_V16QI.
+ (BCDADD_OV): Replaced with BCDADD_OV_V1TI and BCDADD_OV_V16QI.
+ (BCDSUB_V1TI, BCDSUB_V16QI, BCDSUB_LT_V1TI, BCDSUB_LT_V16QI,
+ BCDSUB_LE_V1TI, BCDSUB_LE_V16QI, BCDSUB_EQ_V1TI, BCDSUB_EQ_V16QI,
+ BCDSUB_GT_V1TI, BCDSUB_GT_V16QI, BCDSUB_GE_V1TI, BCDSUB_GE_V16QI,
+ BCDSUB_OV_V1TI, BCDSUB_OV_V16QI, BCDINVALID_V1TI, BCDINVALID_V16QI,
+ BCDMUL10_V16QI, BCDDIV10_V16QI, DENBCD_V16QI): New builtin definitions.
+ (BCDADD, BCDADD_LT, BCDADD_EQ, BCDADD_GT, BCDADD_OV, BCDSUB, BCDSUB_LT,
+ BCDSUB_LE, BCDSUB_EQ, BCDSUB_GT, BCDSUB_GE, BCDSUB_OV, BCDINVALID,
+ BCDMUL10, BCDDIV10, DENBCD): New overload definitions.
+ * config/rs6000/rs6000-call.c (P8V_BUILTIN_VEC_BCDADD, P8V_BUILTIN_VEC_BCDADD_LT,
+ P8V_BUILTIN_VEC_BCDADD_EQ, P8V_BUILTIN_VEC_BCDADD_GT, P8V_BUILTIN_VEC_BCDADD_OV,
+ P8V_BUILTIN_VEC_BCDINVALID, P9V_BUILTIN_VEC_BCDMUL10, P8V_BUILTIN_VEC_DENBCD.
+ P8V_BUILTIN_VEC_BCDSUB, P8V_BUILTIN_VEC_BCDSUB_LT, P8V_BUILTIN_VEC_BCDSUB_LE,
+ P8V_BUILTIN_VEC_BCDSUB_EQ, P8V_BUILTIN_VEC_BCDSUB_GT, P8V_BUILTIN_VEC_BCDSUB_GE,
+ P8V_BUILTIN_VEC_BCDSUB_OV): New overloaded specifications.
+ (CODE_FOR_bcdadd): Replaced with CODE_FOR_bcdadd_v16qi and CODE_FOR_bcdadd_v1ti.
+ (CODE_FOR_bcdadd_lt): Replaced with CODE_FOR_bcdadd_lt_v16qi and CODE_FOR_bcdadd_lt_v1ti.
+ (CODE_FOR_bcdadd_eq): Replaced with CODE_FOR_bcdadd_eq_v16qi and CODE_FOR_bcdadd_eq_v1ti.
+ (CODE_FOR_bcdadd_gt): Replaced with CODE_FOR_bcdadd_gt_v16qi and CODE_FOR_bcdadd_gt_v1ti.
+ (CODE_FOR_bcdsub): Replaced with CODE_FOR_bcdsub_v16qi and CODE_FOR_bcdsub_v1ti.
+ (CODE_FOR_bcdsub_lt): Replaced with CODE_FOR_bcdsub_lt_v16qi and CODE_FOR_bcdsub_lt_v1ti.
+ (CODE_FOR_bcdsub_eq): Replaced with CODE_FOR_bcdsub_eq_v16qi and CODE_FOR_bcdsub_eq_v1ti.
+ (CODE_FOR_bcdsub_gt): Replaced with CODE_FOR_bcdsub_gt_v16qi and CODE_FOR_bcdsub_gt_v1ti.
+ (rs6000_expand_ternop_builtin): Add CODE_FOR_dfp_denbcd_v16qi to else if.
+ * doc/extend.texi: Add documentation for new builtins.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * tree.c (cache_integer_cst): Fixup pointer caching to match
+ wide_int_to_type_1's expectations. Add comment.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * tree.h (id_equal): Call the symetric predicate with swapped
+ arguments.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * print-tree.c (print_node): Display all the operands of a call
+ expr.
+
+2020-11-02 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * config/rs6000/vsx.md (*vsx_extract_<mode>_store_p9): Add hint *
+ to 2nd alternative of the 1st scratch.
+
+2020-11-02 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/97638
+ * config/aarch64/aarch64-bti-insert.c (aarch64_pac_insn_p): Update
+ return value on INSN_P check.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ * tree.h (build_real_from_wide): Declare.
+ * tree.c (build_real_from_wide): New function.
+ * tree-vect-slp.c (vect_build_slp_tree_2): Remove
+ restriction on induction vectorization, represent
+ the initial value.
+ * tree-vect-loop.c (vect_model_induction_cost): Inline ...
+ (vectorizable_induction): ... here. Rewrite SLP
+ code generation.
+
+2020-11-02 Martin Jambor <mjambor@suse.cz>
+
+ * dbgcnt.def (ipa_cp_values): New counter.
+ (ipa_cp_vr): Likewise.
+ * ipa-cp.c (decide_about_value): Check and bump ipa_cp_values debug
+ counter.
+ (decide_whether_version_node): Likewise.
+ (ipcp_store_vr_results):Check and bump ipa_cp_vr debug counter.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/arm.c (arm_thumb1_mi_thunk): Build mi_delta in r3 and
+ do not emit function address and delta when -mpure-code is used.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/thumb1.md (thumb1_movsi_insn): Call
+ thumb1_gen_const_int_print.
+ * config/arm/arm-protos.h (thumb1_gen_const_int_print): Add
+ prototype.
+ * config/arm/arm.c (thumb1_gen_const_int_print): New.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/arm.c (thumb1_const_rtl, thumb1_const_print): New
+ classes.
+ (thumb1_gen_const_int): Rename to ...
+ (thumb1_gen_const_int_1): ... New helper function. Add capability
+ to emit either RTL or asm, improve generated code.
+ (thumb1_gen_const_int_rtl): New function.
+ * config/arm/arm-protos.h (thumb1_gen_const_int): Rename to
+ thumb1_gen_const_int_rtl.
+ * config/arm/thumb1.md: Call thumb1_gen_const_int_rtl instead
+ of thumb1_gen_const_int.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97558
+ * tree-vect-loop.c (vectorizable_reduction): For nested SLP
+ cycles compute invariant operands vector type.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97558
+ * tree-vect-loop.c (vect_fixup_scalar_cycles_with_patterns):
+ Check for any mismatch in pattern vs. non-pattern and dissolve
+ the group if there is one.
+ * tree-vect-slp.c (vect_analyze_slp_instance): Avoid
+ analyzing not relevant reductions.
+ (vect_analyze_slp): Avoid analyzing not relevant reduction
+ groups.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97650
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Check
+ for SSA_NAME before checking SSA_NAME_IS_DEFAULT_DEF.
+
+2020-11-02 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.c
+ (riscv_subset_list::parse_multiletter_ext): Checking multiletter
+ extension has more than 1 letter.
+
+2020-11-02 Kito Cheng <kito.cheng@sifive.com>
+
+ * config.gcc (riscv*-*-*): Handle --with-multilib-generator.
+ * configure: Regen.
+ * configure.ac: Add --with-multilib-generator.
+ * config/riscv/multilib-generator: Exit when parsing arch string error.
+ * config/riscv/t-withmultilib-generator: New.
+ * doc/install.texi: Document --with-multilib-generator.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR target/96770
+ * config/arm/arm.c (thumb_legitimate_constant_p): Accept
+ (symbol_ref + addend) when literal pool is disabled.
+ (arm_valid_symbolic_address_p): Add support for thumb-1 without
+ MOVT/MOVW.
+ * config/arm/thumb1.md (*thumb1_movsi_insn): Accept (symbol_ref +
+ addend) in the pure-code alternative.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR target/96967
+ * config/arm/arm.c (thumb_legitimate_constant_p): Add support for
+ disabled literal pool in thumb-1.
+ * config/arm/thumb1.md (thumb1_movsi_symbol_ref): Remove.
+ (*thumb1_movsi_insn): Add support for SYMBOL_REF with -mpure-code.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/host-darwin.c: Align pch_address_space to 16384.
+
+2020-11-01 Pat Bernardi <bernardi@adacore.com>
+
+ * config/i386/i386.c (ix86_expand_prologue): Set the stack usage to 0
+ for naked functions.
+
+2020-11-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR ipa/97660
+ * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Don't call
+ clone_info::get when cgraph_node::get returns NULL.
+
+2020-10-31 Jan Hubicka <jh@suse.cz>
+
+ * Makefile.in: (OBJS): Add symtab-clones.o
+ (GTFILES): Add symtab-clones.h
+ * cgraph.c: Include symtab-clones.h.
+ (cgraph_edge::resolve_speculation): Fix formating
+ (cgraph_edge::redirect_call_stmt_to_callee): Update.
+ (cgraph_update_edges_for_call_stmt): Update
+ (release_function_body): Fix formating.
+ (cgraph_node::remove): Fix formating.
+ (cgraph_node::dump): Fix formating.
+ (cgraph_node::get_availability): Fix formating.
+ (cgraph_node::call_for_symbol_thunks_and_aliases): Fix formating.
+ (set_const_flag_1): Fix formating.
+ (set_pure_flag_1): Fix formating.
+ (cgraph_node::can_remove_if_no_direct_calls_p): Fix formating.
+ (collect_callers_of_node_1): Fix formating.
+ (clone_of_p): Update.
+ (cgraph_node::verify_node): Update.
+ (cgraph_c_finalize): Call clone_info::release ().
+ * cgraph.h (struct cgraph_clone_info): Move to symtab-clones.h.
+ (cgraph_node): Remove clone_info.
+ (symbol_table): Add m_clones.
+ * cgraphclones.c: Include symtab-clone.h.
+ (duplicate_thunk_for_node): Update.
+ (cgraph_node::create_clone): Update.
+ (cgraph_node::create_virtual_clone): Update.
+ (cgraph_node::find_replacement): Update.
+ (cgraph_node::materialize_clone): Update.
+ * gengtype.c (open_base_files): Include symtab-clones.h.
+ * ipa-cp.c: Include symtab-clones.h.
+ (initialize_node_lattices): Update.
+ (want_remove_some_param_p): Update.
+ (create_specialized_node): Update.
+ * ipa-fnsummary.c: Include symtab-clones.h.
+ (ipa_fn_summary_t::duplicate): Update.
+ * ipa-modref.c: Include symtab-clones.h.
+ (update_signature): Update.
+ * ipa-param-manipulation.c: Include symtab-clones.h.
+ (ipa_param_body_adjustments::common_initialization): Update.
+ * ipa-prop.c: Include symtab-clones.h.
+ (adjust_agg_replacement_values): Update.
+ (ipcp_get_parm_bits): Update.
+ (ipcp_update_bits): Update.
+ (ipcp_update_vr): Update.
+ * ipa-sra.c: Include symtab-clones.h.
+ (process_isra_node_results): Update.
+ (disable_unavailable_parameters): Update.
+ * lto-cgraph.c: Include symtab-clone.h.
+ (output_cgraph_opt_summary_p): Update.
+ (output_node_opt_summary): Update.
+ (input_node_opt_summary): Update.
+ * symtab-clones.cc: New file.
+ * symtab-clones.h: New file.
+ * tree-inline.c (expand_call_inline): Update.
+ (update_clone_info): Update.
+ (tree_function_versioning): Update.
+
+2020-10-31 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (modref_summary::dump): Dump writes_errno.
+ (parm_map_for_arg): Break out from ...
+ (merge_call_side_effects): ... here.
+ (get_access_for_fnspec): New function.
+ (process_fnspec): New function.
+ (analyze_call): Use it.
+ (analyze_stmt): Update.
+ (analyze_function): Initialize writes_errno.
+ (modref_summaries::duplicate): Duplicate writes_errno.
+ * ipa-modref.h (struct modref_summary): Add writes_errno.
+ * tree-ssa-alias.c (call_may_clobber_ref_p_1): Check errno.
+
+2020-10-30 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (glibc_supports_ieee_128bit): New helper
+ function.
+ (rs6000_option_override_internal): Call it.
+
+2020-10-30 Qing Zhao <qing.zhao@oracle.com>
+ H.J.Lu <hjl.tools@gmail.com>
+
+ * common.opt: Add new option -fzero-call-used-regs
+ * config/i386/i386.c (zero_call_used_regno_p): New function.
+ (zero_call_used_regno_mode): Likewise.
+ (zero_all_vector_registers): Likewise.
+ (zero_all_st_registers): Likewise.
+ (zero_all_mm_registers): Likewise.
+ (ix86_zero_call_used_regs): Likewise.
+ (TARGET_ZERO_CALL_USED_REGS): Define.
+ * df-scan.c (df_epilogue_uses_p): New function.
+ (df_get_exit_block_use_set): Replace EPILOGUE_USES with
+ df_epilogue_uses_p.
+ * df.h (df_epilogue_uses_p): Declare.
+ * doc/extend.texi: Document the new zero_call_used_regs attribute.
+ * doc/invoke.texi: Document the new -fzero-call-used-regs option.
+ * doc/tm.texi: Regenerate.
+ * doc/tm.texi.in (TARGET_ZERO_CALL_USED_REGS): New hook.
+ * emit-rtl.h (struct rtl_data): New field must_be_zero_on_return.
+ * flag-types.h (namespace zero_regs_flags): New namespace.
+ * function.c (gen_call_used_regs_seq): New function.
+ (class pass_zero_call_used_regs): New class.
+ (pass_zero_call_used_regs::execute): New function.
+ (make_pass_zero_call_used_regs): New function.
+ * optabs.c (expand_asm_reg_clobber_mem_blockage): New function.
+ * optabs.h (expand_asm_reg_clobber_mem_blockage): Declare.
+ * opts.c (zero_call_used_regs_opts): New structure array
+ initialization.
+ (parse_zero_call_used_regs_options): New function.
+ (common_handle_option): Handle -fzero-call-used-regs.
+ * opts.h (zero_call_used_regs_opts): New structure array.
+ * passes.def: Add new pass pass_zero_call_used_regs.
+ * recog.c (valid_insn_p): New function.
+ * recog.h (valid_insn_p): Declare.
+ * resource.c (init_resource_info): Replace EPILOGUE_USES with
+ df_epilogue_uses_p.
+ * target.def (zero_call_used_regs): New hook.
+ * targhooks.c (default_zero_call_used_regs): New function.
+ * targhooks.h (default_zero_call_used_regs): Declare.
+ * tree-pass.h (make_pass_zero_call_used_regs): Declare.
+
+2020-10-30 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * lra.c (get_scratch_reg): New function.
+ (remove_scratches_1): Rename remove_insn_scratches. Use
+ ira_remove_insn_scratches and get_scratch_reg.
+ (remove_scratches): Do not
+ initialize scratches, scratch_bitmap, and scratch_operand_bitmap.
+ (lra): Call ira_restore_scratches instead of restore_scratches.
+ (struct sloc, sloc_t, scratches, scratch_bitmap)
+ (scratch_operand_bitmap, lra_former_scratch_p)
+ (lra_former_scratch_operand_p, lra_register_new_scratch_op)
+ (restore_scratches): Move them to ...
+ * ira.c: ... here.
+ (former_scratch_p, former_scratch_operand_p): Rename to
+ ira_former_scratch_p and ira_former_scratch_operand_p.
+ (contains_X_constraint_p): New function.
+ (register_new_scratch_op): Rename to ira_register_new_scratch_op.
+ Change it to work for IRA and LRA.
+ (restore_scratches): Rename to ira_restore_scratches.
+ (get_scratch_reg, ira_remove_insn_scratches): New functions.
+ (ira): Call ira_remove_scratches if we use LRA.
+ * ira.h (ira_former_scratch_p, ira_former_scratch_operand_p): New
+ prototypes.
+ (ira_register_new_scratch_op, ira_restore_scratches): New prototypes.
+ (ira_remove_insn_scratches): New prototype.
+ * lra-int.h (lra_former_scratch_p, lra_former_scratch_operand_p):
+ Remove prototypes.
+ (lra_register_new_scratch_op): Ditto.
+ * lra-constraints.c: Rename lra_former_scratch_p and
+ lra_former_scratch_p to ira_former_scratch_p and to
+ ira_former_scratch_p.
+ * lra-remat.c: Ditto.
+ * lra-spills.c: Rename lra_former_scratch_p to ira_former_scratch_p.
+
+2020-10-30 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97556
+ * builtins.c (access_ref::add_offset): Cap offset lower bound
+ to at most the the upper bound.
+
+2020-10-30 Jan Hubicka <jh@suse.cz>
+
+ PR pch/97593
+ * cgraph.c (cgraph_node::create_thunk): Register thunk as early during
+ parsing.
+ * cgraphunit.c (analyze_functions): Call
+ thunk_info::process_early_thunks.
+ * symtab-thunks.cc (struct unprocessed_thunk): New struct.
+ (thunks): New static variable.
+ (thunk_info::register_early): New member function.
+ (thunk_info::process_early_thunks): New member function.
+ * symtab-thunks.h (thunk_info::register_early): Declare.
+ (thunk_info::process_early_thunks): Declare.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97623
+ * tree-ssa-pre.c (insert): First do hoist insertion in
+ a backward walk.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97626
+ * tree-vect-slp.c (vect_slp_analyze_node_operations):
+ Exchange the lvisited hash-set for a vector, roll back
+ recursive adds to visited when analysis failed.
+ (vect_slp_analyze_operations): Likewise.
+
+2020-10-30 Zhiheng Xie <xiezhiheng@huawei.com>
+ Nannan Zheng <zhengnannan@huawei.com>
+
+ * config/aarch64/aarch64-simd-builtins.def: Add proper FLAG
+ for conversion intrinsics.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97633
+ * tree-vect-slp.c (): Update backedges in single-node cycles.
+ Optimize processing of externals.
+
+2020-10-30 Alex Coplan <alex.coplan@arm.com>
+
+ PR target/96998
+ * combine.c (make_extraction): Also handle shifts written as
+ (mult x 2^n), avoid creating an extract rtx for these.
+ * config/aarch64/aarch64.c (aarch64_is_extend_from_extract): Delete.
+ (aarch64_classify_index): Remove extract-based address handling.
+ (aarch64_strip_extend): Likewise.
+ (aarch64_rtx_arith_op_extract_p): Likewise, remove now-unused parameter.
+ Update callers...
+ (aarch64_rtx_costs): ... here.
+
+2020-10-30 Olivier Hainque <hainque@adacore.com>
+
+ * config/rs6000/vxworks.h (TARGET_OS_CPP_BUILTINS): Also
+ builtin_define __ppc and __ppc__ for VxWorks 7.
+
+2020-10-30 Olivier Hainque <hainque@adacore.com>
+ Douglas Rupp <rupp@adacore.com>
+ Pat Bernardi <bernardi@adacore.com>
+
+ * config.gcc: Adjust the ix86/x86_64-wrs-vxworks filters
+ to apply to VxWorks 7 as well.
+ * config/i386/t-vxworks (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
+ Remove the fPIC multilib and add one for the large code model
+ on x86_64.
+ * config/i386/vxworks.h: Separate sections for TARGET_VXWORKS7,
+ other variants and common bits.
+ (TARGET_OS_CPP_BUILTINS): Augment to support a range of CPU
+ families. Leverage VX_CPU_PREFIX.
+ (CC1_SPEC): Add definition.
+ (STACK_CHECK_PROTECT): Use conditional expression instead of
+ heavier to read conditioned macro definitions.
+
+2020-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_scan_omp_clauses): Force
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR into a temporary if it is non-NULL and
+ non-constant.
+ (gimplify_omp_for): Only put allocate on inner taskloop if lastprivate
+ for the same variable is going to be put there, and in that case
+ if the OMP_CLAUSE_ALLOCATE_ALLOCATOR is non-NULL non-constant, make
+ the allocator firstprivate on task.
+
+2020-10-30 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Allow
+ long double type to be changed for C/C++ if glibc 2.32 or newer.
+ (rs6000_invalid_binary_op): Update error messages about mixing IBM
+ long double and IEEE 128-bit.
+
+2020-10-29 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (compute_avail): Free operands consistently.
+ * tree-vect-loop.c (vectorizable_phi): Make sure all operand
+ defs vectors are released.
+
+2020-10-29 Jan Hubicka <jh@suse.cz>
+
+ * vec.h (vec<T, va_heap, vl_ptr>::copy): Pass mem stat info.
+
+2020-10-29 Jan Hubicka <jh@suse.cz>
+
+ * wide-int.h (trailing_wide_ints <N>): Turn len to array of structures
+ so it does not imply typeless storage.
+ (trailing_wide_ints <N>::operator): update
+ (trailing_wide_ints <N>::operator []): Update.
+
+2020-10-29 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/stdbool.h [__STDC_VERSION__ > 201710L] (true, false):
+ Define with type _Bool.
+
+2020-10-29 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/97505
+ * vr-values.c (vr_values::extract_range_basic): Enable
+ trap again for everything except UBSAN builtins.
+
+2020-10-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_transform_slp_perm_load): Take an
+ optional extra parameter.
+ * tree-vect-slp.c (vect_transform_slp_perm_load): Calculate
+ the number of loads as well as the number of permutes, taking
+ the counting loop from...
+ * tree-vect-stmts.c (vect_model_load_cost): ...here. Use the
+ value computed by vect_transform_slp_perm_load for ncopies.
+
+2020-10-29 Martin Liska <mliska@suse.cz>
+
+ PR lto/97508
+ * langhooks.c (lhd_begin_section): Call get_section with
+ not_existing = true.
+ * output.h (get_section): Add new argument.
+ * varasm.c (get_section): Fail when NOT_EXISTING is true
+ and a section already exists.
+ * ipa-cp.c (ipcp_write_summary): Remove.
+ (ipcp_read_summary): Likewise.
+ * ipa-fnsummary.c (ipa_fn_summary_read): Always read jump
+ functions summary.
+ (ipa_fn_summary_write): Always stream it.
+
+2020-10-29 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_bb_slp_scalar_cost): Pass
+ SLP_TREE_VECTYPE to record_stmt_cost.
+
+2020-10-29 Martin Liska <mliska@suse.cz>
+
+ * optc-gen.awk: Check that params start with -param=.
+ * params.opt: Fix ipa-jump-function-lookups.
+
+2020-10-29 Alexandre Oliva <oliva@adacore.com>
+
+ * tree-ssa-math-opts.c (sincos_stats): Add conv_removed.
+ (execute_cse_conv_1): New.
+ (execute_cse_sincos_1): Call it. Fix return within
+ FOR_EACH_IMM_USE_STMT.
+ (pass_cse_sincos::execute): Report conv_inserted.
+
+2020-10-29 Xuepeng Guo <xuepeng.guo@intel.com>
+ Hongyu Wang <hongyu.wang@intel.com>
+ Hongtao Liu <hongtao.liu@intel.com>
+
+ * common/config/i386/cpuinfo.h (get_available_features):
+ Detect KL, AESKLE and WIDEKL features.
+ * common/config/i386/i386-common.c
+ (OPTION_MASK_ISA_KL_SET): New.
+ (OPTION_MASK_ISA_WIDEKL_SET): Likewise.
+ (OPTION_MASK_ISA_KL_UNSET): Likewise.
+ (OPTION_MASK_ISA_WIDEKL_UNSET): Likewise.
+ (OPTION_MASK_ISA2_AVX2_UNSET): Likewise.
+ (OPTION_MASK_ISA2_AVX_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSE4_2_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSE4_1_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSE4_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSSE3_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSE3_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSE2_UNSET): Likewise.
+ (OPTION_MASK_ISA2_SSE_UNSET): Likewise.
+ (ix86_handle_option): Handle kl and widekl, add dependency chain
+ for KL and SSE2.
+ * common/config/i386/i386-cpuinfo.h (enum processor_features):
+ (FEATURE_KL, FEATURE_AESKLE, FEATURE_WIDEKL): New.
+ * common/config/i386/i386-isas.h: Add ISA_NAMES_TABLE_ENTRY
+ for KL, AESKLE and WIDEKL.
+ * config.gcc: Add keylockerintrin.h.
+ * doc/invoke.texi: Document new option -mkl and -mwidekl.
+ * doc/extend.texi: Document kl and widekl.
+ * config/i386/cpuid.h (bit_KL, bit_AESKLE, bit_WIDEKL): New.
+ * config/i386/i386-builtin-types.def ((UINT, UINT, V2DI, V2DI, PVOID),
+ (UINT, UINT, V2DI, PVOID), (VOID, V2DI, V2DI, V2DI, UINT),
+ (UINT8, PV2DI, V2DI, PCVOID), (UINT8, PV2DI, PCV2DI, PCVOID)): New
+ function types.
+ * config/i386/i386-builtin.def: Add
+ __builtin_ia32_loadiwkey,
+ __builtin_ia32_aesdec128kl_u8,
+ __builtin_ia32_aesdec256kl_u8,
+ __builtin_ia32_aesenc128kl_u8,
+ __builtin_ia32_aesenc256kl_u8,
+ __builtin_ia32_aesdecwide128kl_u8,
+ __builtin_ia32_aesdecwide256kl_u8,
+ __builtin_ia32_aesencwide128kl_u8,
+ __builtin_ia32_aesencwide256kl_u8,
+ __builtin_ia32_encodekey128_u32,
+ __builtin_ia32_encodekey256_u32.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Handle
+ kl and widekl.
+ * config/i386/i386-options.c (isa2_opts): Add -mkl and -mwidekl.
+ (ix86_option_override_internal): Handle KL and WIDEKL.
+ (ix86_valid_target_attribute_inner_p): Add attribute for kl and widekl.
+ * config/i386/i386-expand.c
+ (ix86_expand_builtin): Expand Keylocker Builtins.
+ * config/i386/i386.h (TARGET_KL): New.
+ (TARGET_KL_P): Likewise.
+ (TARGET_WIDEKL): Likewise.
+ (TARGET_WIDEKL_P): Likewise.
+ (PTA_KL): Likewise.
+ (PTA_WIDEKL): Likewise.
+ (PTA_TIGERLAKE): Add PTA_KL, PTA_WIDEKL.
+ (PTA_ALDERLAKE): Likewise.
+ * config/i386/i386.opt: Add new option mkl and mwidekl.
+ * config/i386/keylockerintrin.h: New header file for Keylocker.
+ * config/i386/immintrin.h: Include keylockerintrin.h.
+ * config/i386/predicates.md (encodekey128_operation): New
+ predicate.
+ (encodekey256_operation): Likewise.
+ (aeswidekl_operation): Likewise.
+ * config/i386/sse.md (UNSPECV_LOADIWKEY): New.
+ (UNSPECV_AESDEC128KLU8): Likewise.
+ (UNSPECV_AESENC128KLU8): Likewise.
+ (UNSPECV_AESDEC256KLU8): Likewise.
+ (UNSPECV_AESENC256KLU8): Likewise.
+ (UNSPECV_AESDECWIDE128KLU8): Likewise.
+ (UNSPECV_AESENCWIDE128KLU8): Likewise.
+ (UNSPECV_AESDECWIDE256KLU8): Likewise.
+ (UNSPECV_AESENCWIDE256KLU8): Likewise.
+ (UNSPECV_ENCODEKEY128U32): Likewise.
+ (UNSPECV_ENCODEKEY256U32): Likewise.
+ (encodekey128u32): New expander.
+ (encodekey256u32): Likewise.
+ (aes<aeswideklvariant>u8): Likewise.
+ (loadiwkey): New insn pattern.
+ (*encodekey128u32): Likewise.
+ (*encodekey256u32): Likewise.
+ (aes<aesklvariant>u8): Likewise.
+ (*aes<aeswideklvariant>u8): Likewise.
+
+2020-10-29 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_build_slp_tree_2): Allow splatting
+ not vectorizable loads.
+ (vect_build_slp_instance): Amend dumping with address.
+ (vect_slp_convert_to_external): Likewise.
+
+2020-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97609
+ * gimple-range-cache.cc (non_null_ref::process_name): Call
+ infer_nonnull_range directly instead of infer_value_range.
+
+2020-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * Makefile.in (ANALYZER_OBJS): Add analyzer/complexity.o.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * doc/invoke.texi: Document -Wdeprecated-enum-enum-conversion
+ and -Wdeprecated-enum-float-conversion. -Wenum-conversion is
+ no longer C/ObjC only.
+
+2020-10-28 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/97457
+ * value-range.cc (irange::set): Don't decay POLY_INT_CST ranges
+ to integer ranges.
+
+2020-10-28 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/vsx.md(xxgenpcvm_<mode>_internal): Remove TARGET_64BIT.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_slp_analyze_node_operations_1): Dump
+ when shared vectype update fails.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): For skipped
+ args just push NULLs and vect_uninitialized_def.
+ (vect_build_slp_tree_2): Allocate skip_args for all ops
+ and pass it down to vect_get_and_check_slp_defs.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97615
+ * tree-vect-slp.c (vect_build_slp_tree_2): Do not build
+ an external from pattern defs.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_optimize_slp): Fix iteration over
+ all loads.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_build_slp_instance): Split the store
+ group at the failure boundary and also re-analyze a large enough
+ matching rest.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_slp_analyze_node_alignment):
+ Dump when vect_update_shared_vectype fails.
+
+2020-10-28 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/aarch64/arm_neon.h (__ST2_LANE_FUNC, __ST3_LANE_FUNC)
+ (__ST4_LANE_FUNC): Rename the macro generating the 'q' variants
+ into __ST2Q_LANE_FUNC, __ST2Q_LANE_FUNC, __ST2Q_LANE_FUNC so they
+ all can be undefed at the and of the file.
+ (vst2_lane_bf16, vst2q_lane_bf16, vst3_lane_bf16, vst3q_lane_bf16)
+ (vst4_lane_bf16, vst4q_lane_bf16): Add new intrinsics.
+
+2020-10-28 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/aarch64/arm_neon.h (__LD2_LANE_FUNC, __LD3_LANE_FUNC)
+ (__LD4_LANE_FUNC): Rename the macro generating the 'q' variants
+ into __LD2Q_LANE_FUNC, __LD2Q_LANE_FUNC, __LD2Q_LANE_FUNC so they
+ all can be undefed at the and of the file.
+ (vld2_lane_bf16, vld2q_lane_bf16, vld3_lane_bf16, vld3q_lane_bf16)
+ (vld4_lane_bf16, vld4q_lane_bf16): Add new intrinsics.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ALLOCATE.
+ * tree.h (OMP_CLAUSE_ALLOCATE_ALLOCATOR,
+ OMP_CLAUSE_ALLOCATE_COMBINED): Define.
+ * tree.c (omp_clause_num_ops, omp_clause_code_name): Add allocate
+ clause.
+ (walk_tree_1): Handle OMP_CLAUSE_ALLOCATE.
+ * tree-pretty-print.c (dump_omp_clause): Likewise.
+ * gimplify.c (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses,
+ gimplify_omp_for): Likewise.
+ * tree-nested.c (convert_nonlocal_omp_clauses,
+ convert_local_omp_clauses): Likewise.
+ * omp-low.c (scan_sharing_clauses): Likewise.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-offload.c (omp_declare_target_tgt_fn_r): Handle direct calls to
+ declare variant base functions.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR lto/96680
+ * lto-streamer.h (omp_lto_output_declare_variant_alt,
+ omp_lto_input_declare_variant_alt): Declare variant.
+ * symtab.c (symtab_node::get_partitioning_class): Return
+ SYMBOL_DUPLICATE for declare_variant_alt nodes.
+ * passes.c (ipa_write_summaries): Add declare_variant_alt to
+ partition.
+ * lto-cgraph.c (output_refs): Call omp_lto_output_declare_variant_alt
+ on declare_variant_alt nodes.
+ (input_refs): Call omp_lto_input_declare_variant_alt on
+ declare_variant_alt nodes.
+ * lto-streamer-out.c (output_function): Don't call
+ collect_block_tree_leafs if DECL_INITIAL is error_mark_node.
+ (lto_output): Call output_function even for declare_variant_alt
+ nodes.
+ * omp-general.c (omp_lto_output_declare_variant_alt,
+ omp_lto_input_declare_variant_alt): New functions.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * wide-int.cc (wi::set_bit_large): Call canonize unless setting
+ msb bit and clearing bits above it.
+
+2020-10-28 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-gori.cc (gori_compute_cache::cache_stmt): Accumulate
+ return values and only set cache when everything returned true.
+ * gimple-range.cc (get_tree_range): Set the return range to UNDEFINED
+ when the range isn't supported.
+ (gimple_ranger::calc_stmt): Return varying if the type is supported,
+ even if the stmt processing failed. False otherwise.
+ (range_of_builtin_ubsan_call): Don't use gcc_assert.
+ (range_of_builtin_call): Ditto.
+ (gimple_ranger::range_of_cond_expr): Ditto.
+ (gimple_ranger::range_of_expr): Ditto
+ (gimple_ranger::range_on_entry): Ditto.
+ (gimple_ranger::range_on_exit): Ditto.
+ (gimple_ranger::range_on_edge): DItto.
+ (gimple_ranger::range_of_stmt): Don't use gcc_assert, and initialize
+ return value to UNDEFINED.
+
+2020-10-27 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR rtl-optimization/97497
+ * config/s390/s390.c (s390_hard_regno_call_part_clobbered): Do not
+ return true for r12 when -fpic is used.
+
+2020-10-27 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/97535
+ * config/aarch64/aarch64.c (aarch64_expand_cpymem): Use unsigned
+ arithmetic in check.
+
+2020-10-27 Andrea Corallo <andrea.corallo@arm.com>
+
+ * config/aarch64/arm_neon.h (vcopy_lane_bf16, vcopyq_lane_bf16)
+ (vcopyq_laneq_bf16, vcopy_laneq_bf16): New intrinsics.
+
+2020-10-27 Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (VX_CPU_PREFIX): #define here.
+ * config/rs6000/vxworks.h: Remove #definition.
+
+2020-10-27 Olivier Hainque <hainque@adacore.com>
+
+ * config/rs6000/vxworks.h (CPP_SPEC): Fix macro definition
+ for -mcpu=e6500.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_build_slp_instance): Use ceil_log2
+ to compute maximum group-size.
+
+2020-10-27 Jan Hubicka <jh@suse.cz>
+
+ PR ipa/97586
+ * ipa-modref-tree.h (modref_tree::remap_params): New member function.
+ * ipa-modref.c (modref_summaries_lto::duplicate): Check that
+ optimization summaries are not duplicated.
+ (remap_arguments): Remove.
+ (modref_transform): Rename to ...
+ (update_signature): ... this one; handle also lto summary.
+ (pass_ipa_modref::execute): Update signatures here rather
+ than in transform hook.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_slp_bbs): Remove no-op
+ slp-max-insns-in-bb check.
+ (vect_slp_function): Dump when splitting the function.
+ Adjust the split condition for control altering stmts.
+ * params.opt (-param=slp-max-insns-in-bb): Remove.
+ * doc/invoke.texi (-param=slp-max-insns-in-bb): Likewise.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * gimple.h (gimple_expr_type): For PHIs return the type
+ of the result.
+ * tree-vect-loop-manip.c (slpeel_tree_duplicate_loop_to_edge_cfg):
+ Make sure edge order into copied loop headers line up with the
+ originals.
+ * tree-vect-loop.c (vect_transform_cycle_phi): Handle nested
+ loops with SLP.
+ (vectorizable_phi): New function.
+ (vectorizable_live_operation): For BB vectorization compute insert
+ location here.
+ * tree-vect-slp.c (vect_free_slp_tree): Deal with NULL
+ SLP_TREE_CHILDREN entries.
+ (vect_create_new_slp_node): Add overloads with pre-existing node
+ argument.
+ (vect_print_slp_graph): Likewise.
+ (vect_mark_slp_stmts): Likewise.
+ (vect_mark_slp_stmts_relevant): Likewise.
+ (vect_gather_slp_loads): Likewise.
+ (vect_optimize_slp): Likewise.
+ (vect_slp_analyze_node_operations): Likewise.
+ (vect_bb_slp_scalar_cost): Likewise.
+ (vect_remove_slp_scalar_calls): Likewise.
+ (vect_get_and_check_slp_defs): Handle PHIs.
+ (vect_build_slp_tree_1): Handle PHIs.
+ (vect_build_slp_tree_2): Continue SLP build, following PHI
+ arguments. Fix memory leak.
+ (vect_build_slp_tree): Put stub node into the hash-map so
+ we can discover cycles directly.
+ (vect_build_slp_instance): Set the backedge SLP def for
+ reduction chains.
+ (vect_analyze_slp_backedges): Remove.
+ (vect_analyze_slp): Do not call it.
+ (vect_slp_convert_to_external): Release SLP_TREE_LOAD_PERMUTATION.
+ (vect_slp_analyze_node_operations): Handle stray failed
+ backedge defs by failing.
+ (vect_slp_build_vertices): Adjust leaf condition.
+ (vect_bb_slp_mark_live_stmts): Handle PHIs, use visited
+ hash-set to handle cycles.
+ (vect_slp_analyze_operations): Adjust.
+ (vect_bb_partition_graph_r): Likewise.
+ (vect_slp_function): Adjust split condition to allow CFG
+ merges.
+ (vect_schedule_slp_instance): Rename to ...
+ (vect_schedule_slp_node): ... this. Move DFS walk to ...
+ (vect_schedule_scc): ... this new function.
+ (vect_schedule_slp): Call it. Remove ad-hoc vectorized
+ backedge fill code.
+ * tree-vect-stmts.c (vect_analyze_stmt): Call
+ vectorizable_phi.
+ (vect_transform_stmt): Likewise.
+ (vect_is_simple_use): Handle vect_backedge_def.
+ * tree-vectorizer.c (vec_info::new_stmt_vec_info): Only
+ set loop header PHIs to vect_unknown_def_type for loop
+ vectorization.
+ * tree-vectorizer.h (enum vect_def_type): Add vect_backedge_def.
+ (enum stmt_vec_info_type): Add phi_info_type.
+ (vectorizable_phi): Declare.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_build_slp_tree_2): When vectorizing
+ BBs splat uniform operands and stop SLP discovery.
+
+2020-10-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * config/aarch64/aarch64-linux.h (GNU_USER_TARGET_D_CRITSEC_SIZE):
+ Remove.
+ * config/glibc-d.c (glibc_d_critsec_size): Likewise.
+ (TARGET_D_CRITSEC_SIZE): Likewise.
+ * config/i386/linux-common.h (GNU_USER_TARGET_D_CRITSEC_SIZE):
+ Likewise.
+ * config/sol2-d.c (solaris_d_critsec_size): Likewise.
+ (TARGET_D_CRITSEC_SIZE): Likewise.
+ * doc/tm.texi.in (TARGET_D_CRITSEC_SIZE): Likewise.
+ * doc/tm.texi: Regenerate.
+
+2020-10-27 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/97461
+ * gcov-io.h (GCOV_PREALLOCATED_KVP): Pre-allocate 64
+ static counters.
+
+2020-10-27 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (attr_fnspec::verify): Re-enabl checking.
+
+2020-10-27 Jan Hubicka <jh@suse.cz>
+
+ * builtin-attrs.def (STRERRNOC): New macro.
+ (STRERRNOP): New macro.
+ (ATTR_ERRNOCONST_NOTHROW_LEAF_LIST): New attr list.
+ (ATTR_ERRNOPURE_NOTHROW_LEAF_LIST): New attr list.
+ * builtins.def (ATTR_MATHFN_ERRNO): Use
+ ATTR_ERRNOCONST_NOTHROW_LEAF_LIST.
+ (ATTR_MATHFN_FPROUNDING_ERRNO): Use ATTR_ERRNOCONST_NOTHROW_LEAF_LIST
+ or ATTR_ERRNOPURE_NOTHROW_LEAF_LIST.
+
+2020-10-27 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.c (opt_var_ref_t): New.
+ (riscv_ext_flag_table_t): New.
+ (riscv_ext_flag_table): New.
+ (riscv_parse_arch_string): Pass gcc_options* instead of
+ &opts->x_target_flags only, and using riscv_arch_option_table to
+ setup flags.
+ (riscv_handle_option): Update argument for riscv_parse_arch_string.
+ (riscv_expand_arch): Ditto.
+ (riscv_expand_arch_from_cpu): Ditto.
+
+2020-10-27 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-ccp.c (evaluate_stmt): Use EAF_RETURN_ARG; do not handle
+ string buitings specially.
+
+2020-10-27 Jan Hubicka <jh@suse.cz>
+
+ * tree.c (set_call_expr_flags): Fix string for ECF_RET1.
+ (build_common_builtin_nodes): Do not set ECF_RET1 for memcpy, memmove,
+ and memset. They are handled by builtin_fnspec.
+
+2020-10-27 Jan Hubicka <jh@suse.cz>
+
+ * builtins.c (builtin_fnspec): Add bzero, memcmp, memcmp_eq, bcmp,
+ strncmp, strncmp_eq, strncasecmp, rindex, strlen, strlnen, strcasecmp,
+ strcspn, strspn, strcmp, strcmp_eq.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (slp_tree_pool): Declare.
+ (_slp_tree::operator new): Likewise.
+ (_slp_tree::operator delete): Likewise.
+ * tree-vectorizer.c (vectorize_loops): Allocate and free the
+ slp_tree_pool.
+ (pass_slp_vectorize::execute): Likewise.
+ * tree-vect-slp.c (slp_tree_pool): Define.
+ (_slp_tree::operator new): Likewise.
+ (_slp_tree::operator delete): Likewise.
+
+2020-10-27 Martin Liska <mliska@suse.cz>
+
+ * lto-wrapper.c (run_gcc): Do not use sub-make when jobserver is
+ not detected properly.
+
+2020-10-27 Martin Liska <mliska@suse.cz>
+
+ * symbol-summary.h (call_summary_base): Pass symtab hooks to
+ base and register (or unregister) hooks directly.
+
+2020-10-27 Martin Liska <mliska@suse.cz>
+
+ * symbol-summary.h (function_summary_base::unregister_hooks):
+ Call disable_insertion_hook and disable_duplication_hook.
+ (function_summary_base::symtab_insertion): New field.
+ (function_summary_base::symtab_removal): Likewise.
+ (function_summary_base::symtab_duplication): Likewise.
+ Register hooks in function_summary_base and directly register
+ (or unregister) hooks.
+
+2020-10-26 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/97567
+ * gimple-range-gori.cc (gori_compute::logical_combine): Union the
+ ranges of operand1 and operand2, not intersect.
+
+2020-10-26 Jan Hubicka <jh@suse.cz>
+
+ * attr-fnspec.h: Update toplevel comment.
+ (attr_fnspec::attr_fnspec): New constructor.
+ (attr_fnspec::arg_read_p,
+ attr_fnspec::arg_written_p,
+ attr_fnspec::arg_access_size_given_by_arg_p,
+ attr_fnspec::arg_single_access_p
+ attr_fnspec::loads_known_p
+ attr_fnspec::stores_known_p,
+ attr_fnspec::clobbers_errno_p): New member functions.
+ (gimple_call_fnspec): Declare.
+ (builtin_fnspec): Declare.
+ * builtins.c: Include attr-fnspec.h
+ (builtin_fnspec): New function.
+ * builtins.def (BUILT_IN_MEMCPY): Do not specify RET1 fnspec.
+ (BUILT_IN_MEMMOVE): Do not specify RET1 fnspec.
+ (BUILT_IN_MEMSET): Do not specify RET1 fnspec.
+ (BUILT_IN_STRCAT): Do not specify RET1 fnspec.
+ (BUILT_IN_STRCPY): Do not specify RET1 fnspec.
+ (BUILT_IN_STRNCAT): Do not specify RET1 fnspec.
+ (BUILT_IN_STRNCPY): Do not specify RET1 fnspec.
+ (BUILT_IN_MEMCPY_CHK): Do not specify RET1 fnspec.
+ (BUILT_IN_MEMMOVE_CHK): Do not specify RET1 fnspec.
+ (BUILT_IN_MEMSET_CHK): Do not specify RET1 fnspec.
+ (BUILT_IN_STRCAT_CHK): Do not specify RET1 fnspec.
+ (BUILT_IN_STRCPY_CHK): Do not specify RET1 fnspec.
+ (BUILT_IN_STRNCAT_CHK): Do not specify RET1 fnspec.
+ (BUILT_IN_STRNCPY_CHK): Do not specify RET1 fnspec.
+ * gimple.c (gimple_call_fnspec): Return attr_fnspec.
+ (gimple_call_arg_flags): Update.
+ (gimple_call_return_flags): Update.
+ * tree-ssa-alias.c (check_fnspec): New function.
+ (ref_maybe_used_by_call_p_1): Use fnspec for builtin handling.
+ (call_may_clobber_ref_p_1): Likewise.
+ (attr_fnspec::verify): Update verifier.
+ * calls.c (decl_fnspec): New function.
+ (decl_return_flags): Use it.
+
+2020-10-26 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/97555
+ * range-op.cc (range_tests): Test 1-bit signed invert.
+ * value-range.cc (subtract_one): Adjust comment.
+ (add_one): New.
+ (irange::invert): Call add_one.
+
+2020-10-26 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.h (cgraph_node::optimize_for_size_p): Return
+ optimize_size_level.
+ (cgraph_node::optimize_for_size_p): Update.
+ * coretypes.h (enum optimize_size_level): New enum.
+ * predict.c (unlikely_executed_edge_p): Microoptimize.
+ (optimize_function_for_size_p): Return optimize_size_level.
+ (optimize_bb_for_size_p): Likewise.
+ (optimize_edge_for_size_p): Likewise.
+ (optimize_insn_for_size_p): Likewise.
+ (optimize_loop_nest_for_size_p): Likewise.
+ * predict.h (optimize_function_for_size_p): Update declaration.
+ (optimize_bb_for_size_p): Update declaration.
+ (optimize_edge_for_size_p): Update declaration.
+ (optimize_insn_for_size_p): Update declaration.
+ (optimize_loop_for_size_p): Update declaration.
+ (optimize_loop_nest_for_size_p): Update declaration.
+
+2020-10-26 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (enum slp_instance_kind): New.
+ (vect_build_slp_instance): Split out from...
+ (vect_analyze_slp_instance): ... this.
+
+2020-10-26 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range.cc (range_of_builtin_call): Initialize zerov to 0.
+
+2020-10-26 Jan Hubicka <jh@suse.cz>
+
+ PR ipa/97576
+ * cgraphclones.c (cgraph_node::materialize_clone): Clear stmt
+ references.
+ * cgraphunit.c (mark_functions_to_output): Do not clear them here.
+ * ipa-inline-transform.c (inline_transform): Clear stmt references.
+ * symtab.c (symtab_node::clear_stmts_in_references): Make recursive
+ for clones.
+ * tree-ssa-structalias.c (ipa_pta_execute): Do not clear references.
+
+2020-10-26 Zhiheng Xie <xiezhiheng@huawei.com>
+ Nannan Zheng <zhengnannan@huawei.com>
+
+ * config/aarch64/aarch64-builtins.c: Add FLAG STORE.
+ * config/aarch64/aarch64-simd-builtins.def: Add proper FLAG
+ for store intrinsics.
+
+2020-10-26 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/97546
+ * gimple-ssa-store-merging.c (find_bswap_or_nop): Return NULL if
+ type is not INTEGER_CST.
+
+2020-10-26 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/97521
+ * expr.c (const_scalar_mask_from_tree): Remove.
+ (expand_expr_real_1): Always VIEW_CONVERT integer mode
+ vector constants to an integer type.
+ * tree.c (build_truth_vector_type_for_mode): Use a single-bit
+ boolean component type for non-vector-mode mask_mode.
+
+2020-10-26 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/95458
+ * config/i386/i386-expand.c (ix86_expand_cmpstrn_or_cmpmem):
+ Return false for -mno-inline-all-stringops.
+
+2020-10-26 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/95151
+ * config/i386/i386-expand.c (ix86_expand_cmpstrn_or_cmpmem): New
+ function.
+ * config/i386/i386-protos.h (ix86_expand_cmpstrn_or_cmpmem): New
+ prototype.
+ * config/i386/i386.md (cmpmemsi): New pattern.
+
+2020-10-26 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/vector.md ("vcond_mask_<mode><mode>"): New expander.
+
+2020-10-26 Richard Biener <rguenther@suse.de>
+
+ * sbitmap.c (sbitmap_vector_alloc): Use size_t for byte
+ quantities to avoid overflow.
+
+2020-10-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97539
+ * tree-vect-loop-manip.c (vect_do_peeling): Reset out-of-loop
+ debug uses before peeling.
+
+2020-10-26 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.h (struct cgraph_node): Make ipa_transforms_to_apply vl_ptr.
+ * ipa-inline-analysis.c (initialize_growth_caches): Disable insertion
+ and duplication hooks.
+ * ipa-inline-transform.c (clone_inlined_nodes): Clear
+ ipa_transforms_to_apply.
+ (save_inline_function_body): Disable insertion hoook for
+ ipa_saved_clone_sources.
+ * ipa-prop.c (ipcp_transformation_initialize): Disable insertion hook.
+ * ipa-prop.h (ipa_node_params_t): Disable insertion hook.
+ * ipa-reference.c (propagate): Disable insertion hoook.
+ * ipa-sra.c (ipa_sra_summarize_function): Move out of anonymous
+ namespace.
+ (ipa_sra_function_summaries::insert): New virtual function.
+ * passes.c (execute_one_pass): Do not add transforms to inline clones.
+ * symbol-summary.h (function_summary_base): Make insert and duplicate
+ hooks fail instead of silently producing empty summaries; add way to
+ disable duplication hooks
+ (call_summary_base): Likewise.
+ * tree-nested.c (nested_function_info::get_create): Disable insertion
+ hooks
+ (maybe_record_nested_function): Likewise.
+
+2020-10-26 Xionghu Luo <luoxhu@linux.ibm.com>
+
+ * cfg.c (debug_bb): New overloaded function.
+ (debug_bb_n): New overloaded function.
+ * cfg.h (debug_bb): New declaration.
+ (debug_bb_n): New declaration.
+ * print-rtl.c (debug_bb_slim): Call debug_bb with flags.
+
2020-10-24 H.J. Lu <hjl.tools@gmail.com>
PR bootstrap/97451
@@ -684,29 +8683,6 @@
(vrp_simplify_cond_using_ranges): Move...
* tree-vrp.c (vrp_simplify_cond_using_ranges): ...to here.
-2020-10-22 Dennis Zhang <dennis.zhang@arm.com>
-
- * config/arm/mve.md (mve_vmaxq_<supf><mode>): Replace with ...
- (mve_vmaxq_s<mode>, mve_vmaxq_u<mode>): ... these new insns to
- use smax/umax instead of VMAXQ.
- (mve_vminq_<supf><mode>): Replace with ...
- (mve_vminq_s<mode>, mve_vminq_u<mode>): ... these new insns to
- use smin/umin instead of VMINQ.
- (mve_vmaxnmq_f<mode>): Use smax instead of VMAXNMQ_F.
- (mve_vminnmq_f<mode>): Use smin instead of VMINNMQ_F.
- * config/arm/vec-common.md (smin<mode>3): Use the new mode macros
- ARM_HAVE_<MODE>_ARITH.
- (umin<mode>3, smax<mode>3, umax<mode>3): Likewise.
-
-2020-10-22 Dennis Zhang <dennis.zhang@arm.com>
-
- * config/arm/mve.md (mve_vmulq<mode>): New entry for vmul instruction
- using expression 'mult'.
- (mve_vmulq_f<mode>): Use mult instead of VMULQ_F.
- * config/arm/neon.md (mul<mode>3): Removed.
- * config/arm/vec-common.md (mul<mode>3): Use the new mode macros
- ARM_HAVE_<MODE>_ARITH. Use mode iterator VDQWH instead of VALLW.
-
2020-10-20 Andrew MacLeod <amacleod@redhat.com>
PR tree-optimization/97505
@@ -2922,10 +10898,6 @@
* doc/invoke.texi: Add z15/arch13 to the list of documented
-march/-mtune options.
-2020-10-05 Dennis Zhang <dennis.zhang@arm.com>
-
- * config/arm/arm.c (arm_preferred_simd_mode): Enable MVE SIMD modes.
-
2020-10-05 Aldy Hernandez <aldyh@redhat.com>
* value-range.cc (irange::legacy_intersect): Only handle
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 49d6a92..e4fd5e9 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20201025
+20201231
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0894f48..6847022 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -207,6 +207,7 @@ VALGRIND_DRIVER_DEFINES = @valgrind_path_defines@
# This is how we control whether or not the additional warnings are applied.
.-warn = $(STRICT_WARN)
build-warn = $(STRICT_WARN)
+rtl-ssa-warn = $(STRICT_WARN)
GCC_WARN_CFLAGS = $(LOOSE_WARN) $(C_LOOSE_WARN) $($(@D)-warn) $(if $(filter-out $(STRICT_WARN),$($(@D)-warn)),,$(C_STRICT_WARN)) $(NOCOMMON_FLAG) $($@-warn)
GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn)
@@ -412,6 +413,9 @@ enable_as_accelerator = @enable_as_accelerator@
CPPLIB = ../libcpp/libcpp.a
CPPINC = -I$(srcdir)/../libcpp/include
+CODYLIB = ../libcody/libcody.a
+CODYINC = -I$(srcdir)/../libcody
+
# Where to find decNumber
enable_decimal_float = @enable_decimal_float@
DECNUM = $(srcdir)/../libdecnumber
@@ -675,6 +679,9 @@ build_tooldir = $(exec_prefix)/$(target_noncanonical)
# Directory in which the compiler finds target-independent g++ includes.
gcc_gxx_include_dir = @gcc_gxx_include_dir@
gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
+# Directory in which the compiler finds libc++ includes.
+gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@
+gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@
# Directory to search for site-specific includes.
local_includedir = $(local_prefix)/include
includedir = $(prefix)/include
@@ -982,6 +989,7 @@ SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h \
PREDICT_H = predict.h predict.def
CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
$(srcdir)/../libcpp/include/cpplib.h
+CODYLIB_H = $(srcdir)/../libcody/cody.hh
INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h
OPTS_H = $(INPUT_H) $(VEC_H) opts.h $(OBSTACK_H)
SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
@@ -1102,7 +1110,7 @@ BUILD_ERRORS = build/errors.o
# libintl.h will be found in ../intl if we are using the included libintl.
INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
-I$(srcdir)/../include @INCINTL@ \
- $(CPPINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \
+ $(CPPINC) $(CODYINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \
$(ISLINC)
COMPILE.base = $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) -o $@
@@ -1180,6 +1188,7 @@ FLAGS_TO_PASS = \
"prefix=$(prefix)" \
"local_prefix=$(local_prefix)" \
"gxx_include_dir=$(gcc_gxx_include_dir)" \
+ "gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \
"build_tooldir=$(build_tooldir)" \
"gcc_tooldir=$(gcc_tooldir)" \
"bindir=$(bindir)" \
@@ -1230,6 +1239,7 @@ ANALYZER_OBJS = \
analyzer/bar-chart.o \
analyzer/call-string.o \
analyzer/checker-path.o \
+ analyzer/complexity.o \
analyzer/constraint-manager.o \
analyzer/diagnostic-manager.o \
analyzer/engine.o \
@@ -1298,6 +1308,7 @@ OBJS = \
cfgrtl.o \
symtab.o \
symtab-thunks.o \
+ symtab-clones.o \
cgraph.o \
cgraphbuild.o \
cgraphunit.o \
@@ -1362,6 +1373,7 @@ OBJS = \
gimple-array-bounds.o \
gimple-builder.o \
gimple-expr.o \
+ gimple-if-to-switch.o \
gimple-iterator.o \
gimple-fold.o \
gimple-laddress.o \
@@ -1478,6 +1490,7 @@ OBJS = \
omp-expand.o \
omp-general.o \
omp-low.o \
+ omp-oacc-kernels-decompose.o \
omp-simd-clone.o \
opt-problem.o \
optabs.o \
@@ -1517,6 +1530,11 @@ OBJS = \
reorg.o \
resource.o \
rtl-error.o \
+ rtl-ssa/accesses.o \
+ rtl-ssa/blocks.o \
+ rtl-ssa/changes.o \
+ rtl-ssa/functions.o \
+ rtl-ssa/insns.o \
rtl-tests.o \
rtl.o \
rtlhash.o \
@@ -1538,6 +1556,7 @@ OBJS = \
sparseset.o \
spellcheck.o \
spellcheck-tree.o \
+ splay-tree-utils.o \
sreal.o \
stack-ptr-mod.o \
statistics.o \
@@ -1643,6 +1662,7 @@ OBJS = \
tree-vect-loop.o \
tree-vect-loop-manip.o \
tree-vect-slp.o \
+ tree-vect-slp-patterns.o \
tree-vectorizer.o \
tree-vector-builder.o \
tree-vrp.o \
@@ -1709,7 +1729,7 @@ endif
ALL_HOST_OBJS = $(ALL_HOST_FRONTEND_OBJS) $(ALL_HOST_BACKEND_OBJS)
BACKEND = libbackend.a main.o libcommon-target.a libcommon.a \
- $(CPPLIB) $(LIBDECNUMBER)
+ $(CPPLIB) $(CODYLIB) $(LIBDECNUMBER)
# This is defined to "yes" if Tree checking is enabled, which roughly means
# front-end checking.
@@ -1747,6 +1767,8 @@ $(FULL_DRIVER_NAME): ./xgcc$(exeext)
# Otherwise $(SELFTEST_DEPS) is empty when used from <LANG>/Make-lang.in.
SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
+DO_LINK_SERIALIZATION = @DO_LINK_SERIALIZATION@
+
# Language makefile fragments.
# The following targets define the interface between us and the languages.
@@ -1764,6 +1786,23 @@ SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
# language hooks, generated by configure
@language_hooks@
+ifeq ($(DO_LINK_SERIALIZATION),)
+LINK_PROGRESS = :
+else
+LINK_PROGRESS = msg="Linking |"; cnt=0; if test "$(2)" = start; then \
+ idx=0; cnt2=$(DO_LINK_SERIALIZATION); \
+ while test $$cnt2 -le $(1); do msg="$${msg}=="; cnt2=`expr $$cnt2 + 1`; idx=`expr $$idx + 1`; done; \
+ cnt=$$idx; \
+ while test $$cnt -lt $(1); do msg="$${msg}>>"; cnt=`expr $$cnt + 1`; done; \
+ msg="$${msg}--"; cnt=`expr $$cnt + 1`; \
+ else \
+ idx=`expr $(1) + 1`; \
+ while test $$cnt -le $(1); do msg="$${msg}=="; cnt=`expr $$cnt + 1`; done; \
+ fi; \
+ while test $$cnt -lt $(SERIAL_COUNT); do msg="$${msg} "; cnt=`expr $$cnt + 1`; done; \
+ msg="$${msg}| `expr 100 \* $$idx / $(SERIAL_COUNT)`%"; echo "$$msg"
+endif
+
# Wire in install-gnatlib invocation with `make install' for a configuration
# with top-level libada disabled.
gnat_install_lib = @gnat_install_lib@
@@ -2593,6 +2632,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/output.h $(srcdir)/cfgloop.h $(srcdir)/cfg.h $(srcdir)/profile-count.h \
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
$(srcdir)/symtab-thunks.h $(srcdir)/symtab-thunks.cc \
+ $(srcdir)/symtab-clones.h \
$(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
$(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-utils.h \
@@ -2968,6 +3008,8 @@ PREPROCESSOR_DEFINES = \
-DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
-DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
-DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
+ -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \
+ -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \
-DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
-DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
@@ -3283,7 +3325,7 @@ gcc-vers.texi: $(BASEVER) $(DEVPHASE)
then echo "@set DEVELOPMENT"; \
else echo "@clear DEVELOPMENT"; \
fi) > $@T
- $(build_file_translate) echo @set srcdir $(abs_srcdir) >> $@T
+ $(build_file_translate) echo @set srcdir `echo $(abs_srcdir) | sed -e 's|\\([@{}]\\)|@\\1|g'` >> $@T
if [ -n "$(PKGVERSION)" ]; then \
echo "@set VERSION_PACKAGE $(PKGVERSION)" >> $@T; \
fi
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 4b4e760..5ce188d 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,3134 @@
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/a-tags.ads, libgnat/a-tags.adb (CW_Membership): Move
+ to spec to allow inlining.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * checks.adb: Remove, not used.
+ * checks.ads: Likewise.
+ * exp_ch6.adb: Likewise.
+ * exp_ch7.adb: Likewise.
+ * exp_ch7.ads: Likewise.
+ * exp_fixd.adb: Likewise.
+ * exp_tss.adb: Likewise.
+ * exp_tss.ads: Likewise.
+ * exp_util.adb: Likewise.
+ * exp_util.ads: Likewise.
+ * gnat1drv.adb: Likewise.
+ * libgnat/s-finmas.adb: Likewise.
+ * libgnat/s-finmas.ads: Likewise.
+ * libgnat/system-aix.ads: Likewise.
+ * libgnat/system-darwin-arm.ads: Likewise.
+ * libgnat/system-darwin-ppc.ads: Likewise.
+ * libgnat/system-darwin-x86.ads: Likewise.
+ * libgnat/system-djgpp.ads: Likewise.
+ * libgnat/system-dragonfly-x86_64.ads: Likewise.
+ * libgnat/system-freebsd.ads: Likewise.
+ * libgnat/system-hpux-ia64.ads: Likewise.
+ * libgnat/system-hpux.ads: Likewise.
+ * libgnat/system-linux-alpha.ads: Likewise.
+ * libgnat/system-linux-arm.ads: Likewise.
+ * libgnat/system-linux-hppa.ads: Likewise.
+ * libgnat/system-linux-ia64.ads: Likewise.
+ * libgnat/system-linux-m68k.ads: Likewise.
+ * libgnat/system-linux-mips.ads: Likewise.
+ * libgnat/system-linux-ppc.ads: Likewise.
+ * libgnat/system-linux-riscv.ads: Likewise.
+ * libgnat/system-linux-s390.ads: Likewise.
+ * libgnat/system-linux-sh4.ads: Likewise.
+ * libgnat/system-linux-sparc.ads: Likewise.
+ * libgnat/system-linux-x86.ads: Likewise.
+ * libgnat/system-lynxos178-ppc.ads: Likewise.
+ * libgnat/system-lynxos178-x86.ads: Likewise.
+ * libgnat/system-mingw.ads: Likewise.
+ * libgnat/system-qnx-aarch64.ads: Likewise.
+ * libgnat/system-rtems.ads: Likewise.
+ * libgnat/system-solaris-sparc.ads: Likewise.
+ * libgnat/system-solaris-x86.ads: Likewise.
+ * libgnat/system-vxworks-arm-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks-arm-rtp.ads: Likewise.
+ * libgnat/system-vxworks-arm.ads: Likewise.
+ * libgnat/system-vxworks-e500-kernel.ads: Likewise.
+ * libgnat/system-vxworks-e500-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks-e500-rtp.ads: Likewise.
+ * libgnat/system-vxworks-e500-vthread.ads: Likewise.
+ * libgnat/system-vxworks-ppc-kernel.ads: Likewise.
+ * libgnat/system-vxworks-ppc-ravenscar.ads: Likewise.
+ * libgnat/system-vxworks-ppc-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks-ppc-rtp.ads: Likewise.
+ * libgnat/system-vxworks-ppc-vthread.ads: Likewise.
+ * libgnat/system-vxworks-ppc.ads: Likewise.
+ * libgnat/system-vxworks-x86-kernel.ads: Likewise.
+ * libgnat/system-vxworks-x86-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks-x86-rtp.ads: Likewise.
+ * libgnat/system-vxworks-x86-vthread.ads: Likewise.
+ * libgnat/system-vxworks-x86.ads: Likewise.
+ * libgnat/system-vxworks7-aarch64-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks7-aarch64.ads: Likewise.
+ * libgnat/system-vxworks7-arm-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks7-arm.ads: Likewise.
+ * libgnat/system-vxworks7-e500-kernel.ads: Likewise.
+ * libgnat/system-vxworks7-e500-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks7-e500-rtp.ads: Likewise.
+ * libgnat/system-vxworks7-ppc-kernel.ads: Likewise.
+ * libgnat/system-vxworks7-ppc-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks7-ppc-rtp.ads: Likewise.
+ * libgnat/system-vxworks7-ppc64-kernel.ads: Likewise.
+ * libgnat/system-vxworks7-ppc64-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks7-x86-kernel.ads: Likewise.
+ * libgnat/system-vxworks7-x86-rtp-smp.ads: Likewise.
+ * libgnat/system-vxworks7-x86-rtp.ads: Likewise.
+ * libgnat/system-vxworks7-x86_64-kernel.ads: Likewise.
+ * libgnat/system-vxworks7-x86_64-rtp-smp.ads: Likewise.
+ * repinfo.adb: Likewise.
+ * repinfo.ads: Likewise.
+ * rtsfind.ads: Likewise.
+ * sem_aux.adb: Likewise.
+ * sem_aux.ads: Likewise.
+ * sem_ch13.adb: Likewise.
+ * sem_ch13.ads: Likewise.
+ * sem_util.adb (Validity_Checks_Suppressed, TSS,
+ Is_All_Null_Statements, Known_Non_Negative,
+ Non_Limited_Designated_Type, Get_Binary_Nkind, Get_Unary_Nkind,
+ Is_Protected_Operation, Number_Components, Package_Body,
+ Validate_Independence, Independence_Checks): Likewise; update
+ comments.
+ * targparm.adb: Likewise.
+ * targparm.ads (AAM, AAM_Str, Fractional_Fixed_Ops,
+ Frontend_Layout, Make_Detach_Call, Target_Has_Fixed_Ops, Detach,
+ Back_End_Layout, Create_Dynamic_SO_Ref, Get_Dynamic_SO_Entity,
+ Is_Dynamic_SO_Ref, Is_Static_SO_Ref,
+ Fractional_Fixed_Ops_On_Target): Likewise.
+ * validsw.adb (Save_Validity_Check_Options,
+ Set_Default_Validity_Check_Options): Likewise.
+ * validsw.ads: Likewise.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * symbols.ads, symbols.adb: Removed no longer used.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_util.adb (New_Requires_Transient_Scope): Renamed
+ Requires_Transient_Scope.
+ (Requires_Transient_Scope, Old_Requires_Transient_Scope,
+ Results_Differ): Removed.
+ * debug.adb: Remove -gnatdQ.
+
+2020-12-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valrea.adb (Need_Extra): Fix comment.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch5.adb (Analyze_Case_Statement): Move modification of
+ Unblocked_Exit_Count after early return statements; fix typo in
+ comment.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch5.adb (Analyze_Case_Statement): Change local variable
+ Exp to constant; remove unreferenced Last_Choice variable;
+ reduce scope of other variables.
+ (Analyze_If_Statement): Reduce scope of a local variable; add
+ comment.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * opt.ads (Multiple_Unit_Index): Refine type from Int to Nat.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_util.adb (In_Check_Node): Add guard and rename Node to
+ Par, just like it is done in surrounding routines, e.g.
+ In_Assertion_Expression_Pragma and In_Generic_Formal_Package.
+
+2020-12-17 Bob Duff <duff@adacore.com>
+
+ * libgnat/a-cbdlli.adb, libgnat/a-cbdlli.ads,
+ libgnat/a-cdlili.adb, libgnat/a-cdlili.ads,
+ libgnat/a-cidlli.adb, libgnat/a-cidlli.ads,
+ libgnat/a-cobove.adb, libgnat/a-cobove.ads,
+ libgnat/a-coinve.adb, libgnat/a-coinve.ads,
+ libgnat/a-convec.adb, libgnat/a-convec.ads: Add *_Vector
+ operations, remove default for Count, rename Append_One to be
+ Append.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_res.adb (Resolve_Declare_Expression): Need to establish a
+ transient scope in case Expression (N) requires actions to be
+ wrapped. Code cleanup.
+ * exp_ch7.adb, exp_ch11.adb: Code cleanup.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch3.adb (P_Identifier_Declarations): Reuse
+ Error_Msg_Ada_2020_Feature for object renaming without subtype.
+ * par-ch4.adb (P_Primary): Likewise for target name.
+ (P_Iterated_Component_Association): Likewise for iterated
+ component.
+ (P_Declare_Expression): Likewise for declare expression.
+ * par-ch6.adb (P_Formal_Part): Likewise for aspect on formal
+ parameter.
+ * sem_aggr.adb (Resolve_Delta_Aggregate): Ditto.
+ * sem_ch8.adb (Analyze_Object_Renaming): Reuse
+ Error_Msg_Ada_2020_Feature.
+ * sem_ch13.adb (Validate_Aspect_Aggregate): Reuse
+ Error_Msg_Ada_2020_Feature; use lower case for "aspect" and
+ don't use underscore for "Ada_2020"; don't give up on analysis
+ in Ada 2012 mode.
+ (Validate_Aspect_Stable_Properties): Reuse
+ Error_Msg_Ada_2020_Feature; use lower case for "aspect"; minor
+ style fixes.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch4.adb (Analyze_Selected_Component): Request a compile
+ time error replacement in Apply_Compile_Time_Constraint_Error
+ in case of an invalid field.
+ * sem_ch3.adb (Create_Constrained_Components): Take advantage of
+ Gather_Components also in the case of a record extension and
+ also constrain records in the case of compile time known discriminant
+ values, as already done in gigi.
+ * sem_util.ads, sem_util.adb (Gather_Components): New parameter
+ Allow_Compile_Time to allow compile time known (but non static)
+ discriminant values, needed by Create_Constrained_Components,
+ and new parameter Include_Interface_Tag.
+ (Is_Dependent_Component_Of_Mutable_Object): Use Original_Node to
+ perform check on the original tree.
+ (Is_Object_Reference): Likewise. Only call Original_Node when
+ relevant via a new function Safe_Prefix.
+ (Is_Static_Discriminant_Component, In_Check_Node): New.
+ (Is_Actual_Out_Or_In_Out_Parameter): New.
+ * exp_ch4.adb (Expand_N_Selected_Component): Remove no longer needed
+ code preventing evaluating statically discriminants in more cases.
+ * exp_ch5.adb (Expand_N_Loop_Statement): Simplify expansion of loops
+ with an N_Raise_xxx_Error node to avoid confusing the code generator.
+ (Make_Component_List_Assign): Try to find a constrained type to
+ extract discriminant values from, so that the case statement
+ built gets an opportunity to be folded by
+ Expand_N_Case_Statement.
+ (Expand_Assign_Record): Update comments, code cleanups.
+ * sem_attr.adb (Analyze_Attribute): Perform most of the analysis
+ on the original prefix node to deal properly with a prefix rewritten
+ as a N_Raise_xxx_Error.
+ * sem_ch5.adb (Analyze_Loop_Parameter_Specification): Handle properly
+ a discrete subtype definition being rewritten as N_Raise_xxx_Error.
+ * sem_ch8.adb (Analyze_Object_Renaming): Handle N_Raise_xxx_Error
+ nodes as part of the expression being renamed.
+ * sem_eval.ads, sem_eval.adb (Fold, Eval_Selected_Component): New.
+ (Compile_Time_Known_Value, Expr_Value, Expr_Rep_Value): Evaluate
+ static discriminant component values.
+ * sem_res.adb (Resolve_Selected_Component): Call
+ Eval_Selected_Component.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Unchecked_Type_Conversion): Remove
+ folding of discrete values.
+ * exp_intr.adb (Expand_Unc_Conversion): Analyze, resolve and
+ evaluate (if possible) calls to instances of
+ Ada.Unchecked_Conversion after they have been expanded into
+ N_Unchecked_Type_Conversion.
+ * sem_eval.adb (Eval_Unchecked_Conversion): Add folding of
+ discrete values.
+
+2020-12-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Likewise.
+ * exp_imgv.adb (Expand_Value_Attribute): Use RE_Value_Long_Float in
+ lieu of RE_Value_Long_Long_Float as fallback for fixed-point types.
+ Also use it for Long_Long_Float if it has same size as Long_Float.
+ * libgnat/s-imgrea.adb: Replace Powten_Table with Powen_LLF.
+ * libgnat/s-powflt.ads: New file.
+ * libgnat/s-powlfl.ads: Likewise.
+ * libgnat/s-powtab.ads: Rename to...
+ * libgnat/s-powllf.ads: ...this.
+ * libgnat/s-valflt.ads: Add with clause for System.Powten_Flt and
+ pass its table as actual parameter to System.Val_Real.
+ * libgnat/s-vallfl.ads: Likewise for System.Powten_LFlt.
+ * libgnat/s-valllf.ads: Likewise for System.Powten_LLF.
+ * libgnat/s-valrea.ads: Add Maxpow and Powten_Address parameters.
+ * libgnat/s-valrea.adb: Add pragma Warnings (Off).
+ (Need_Extra): New boolean constant.
+ (Precision_Limit): Set it according to Need_Extra.
+ (Impl): Adjust actual parameter.
+ (Integer_to_Rea): Add assertion on the machine radix. Take into
+ account the extra digit only if Need_Extra is true. Reimplement
+ the computation of the final value for bases 2, 4, 8, 10 and 16.
+ * libgnat/s-valued.adb (Impl): Adjust actual parameter.
+ (Scan_Decimal): Add pragma Unreferenced.
+ (Value_Decimal): Likewise.
+ * libgnat/s-valuef.adb (Impl): Adjust actual parameter.
+ * libgnat/s-valuer.ads (Floating): Remove.
+ (Round): New formal parameter.
+ * libgnat/s-valuer.adb (Round_Extra): New procedure.
+ (Scan_Decimal_Digits): Use it to round the extra digit if Round
+ is set to True in the instantiation.
+ (Scan_Integral_Digits): Likewise.
+
+2020-12-17 Erwan Le Guillou <leguillou@adacore.com>
+
+ * libgnat/system-lynxos178-ppc.ads,
+ libgnat/system-lynxos178-x86.ads: Fix small typo in comments.
+
+2020-12-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_dbug.adb (Get_Encoded_Name): Generate encodings for fixed
+ point types only if -fgnat-encodings=all is specified.
+
+2020-12-17 Justin Squirek <squirek@adacore.com>
+
+ * checks.adb (Build_Discriminant_Checks): Add condition to
+ replace references to the current instance of the type when we
+ are within an Init_Proc.
+ (Replace_Current_Instance): Examine a given node and replace the
+ current instance of the type with the corresponding _init
+ formal.
+ (Search_And_Replace_Current_Instance): Traverse proc which calls
+ Replace_Current_Instance in order to replace all references
+ within a given expression.
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch12.adb (P_Formal_Derived_Type_Definition): Complain
+ about formal type with aspect specification, which only become
+ legal in Ada 2020.
+ * par-ch9.adb (P_Protected_Operation_Declaration_Opt): Reuse
+ Error_Msg_Ada_2005_Extension.
+ (P_Entry_Declaration): Likewise.
+ * scng.adb (Scan): Improve diagnostics for target_name; emit
+ error, but otherwise continue in earlier than Ada 2020 modes.
+
+2020-12-17 Ed Schonberg <schonberg@adacore.com>
+
+ * libgnat/a-cbsyqu.ads (Implementation): Provide a box
+ initialization for the element array used internally to
+ represent the queue, so that its components are properly
+ initialized if the given element type has default
+ initialization. Suppress warnings on the rest of the package in
+ case the element type has no default or discriminant, because it
+ is bound to be confusing to the user.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_util.adb (Inherit_Predicate_Flags): No-op before Ada 2012.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch7.adb (Make_Final_Call, Make_Init_Call): Take protected
+ types into account.
+ * sem_util.ads: Fix typo.
+
+2020-12-17 Yannick Moy <moy@adacore.com>
+
+ * checks.adb: Rework error messages.
+ * exp_ch3.adb: Likewise.
+ * freeze.adb: Likewise.
+ * lib-load.adb: Likewise.
+ * par-ch12.adb: Likewise.
+ * par-ch3.adb: Likewise.
+ * par-ch4.adb: Likewise.
+ * par-ch9.adb: Likewise.
+ * sem_aggr.adb: Likewise.
+ * sem_attr.adb: Likewise.
+ * sem_cat.adb: Likewise.
+ * sem_ch10.adb: Likewise.
+ * sem_ch12.adb: Likewise.
+ (Instantiate_Type): Fix CODEFIX comment, applicable only on
+ continuation message, and identify the second message as a
+ continuation.
+ * sem_ch13.adb: Rework error messages.
+ * sem_ch3.adb: Likewise.
+ * sem_ch4.adb: Likewise.
+ * sem_ch5.adb: Likewise.
+ * sem_ch6.adb: Likewise.
+ * sem_ch8.adb: Likewise.
+ * sem_ch9.adb: Likewise.
+ * sem_prag.adb: Likewise.
+ * sem_res.adb: Likewise.
+ * sem_util.adb: Likewise.
+ (Wrong_Type): Fix CODEFIX comment, applicable only on
+ continuation message, and identify the second message as a
+ continuation.
+ * symbols.adb: Rework error messages.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_attr.adb (OK_Self_Reference): Return True if node does not
+ come from source (e.g. a rewritten aggregate).
+
+2020-12-17 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Parse_Aspect_Stable_Properties): Fix style;
+ limit the scope of local variables; remove extra assignment in
+ Extract_Entity.
+ (Validate_Aspect_Stable_Properties): Simplify with procedural
+ Next.
+
+2020-12-16 Arnaud Charlet <charlet@adacore.com>
+
+ * ali.ads, ali.adb, bindo-writers.adb, lib-writ.adb (Scope):
+ Renamed to IS_Scope.
+
+2020-12-16 Joffrey Huguet <huguet@adacore.com>
+
+ * libgnat/a-strfix.ads: Add postconditions and contract cases to
+ subprograms.
+
+2020-12-16 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch5.adb (Analyze_Iterator_Specification): If iterator
+ filter is present, preanalyze filter without expansion.
+ (Analyze_Loop_Parameter_Specification): When
+ loop_Parameter_Specification is rewritten as
+ Iterator_Specification, transfer Iterator_Filter if present.
+
+2020-12-16 Doug Rupp <rupp@adacore.com>
+
+ * libgnat/s-objrea.ads (Object_Arch): Add ARM enum
+ * libgnat/s-objrea.adb (Initialize): Add EM_ARM case.
+ (Read_Address): Add ARM case to 32bit read.
+ * Makefile.rtl: Add trasym units to the runtime for armhf-linux.
+
+2020-12-16 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * libgnat/g-expect.adb (Non_Blocking_Spawn): Deallocate elements
+ on Arg_List after calling Set_Up_Child_Communications.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch3.adb (P_Modular_Type_Definition): Remove colon from
+ error message.
+ * sem_ch11.adb (Check_Duplication): Likewise.
+ * sem_ch3.adb (Derived_Type_Declaration): Likewise.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch12.adb (P_Formal_Object_Declarations): Refine types to
+ Pos.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * impunit.adb (Not_Impl_Defined_Unit): Fix typo in iteration
+ over Non_Imp_File_Names_12 array.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch9.adb, sem_warn.adb: Simplify membership test.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch6.adb, exp_util.adb, sem_ch4.adb, sem_disp.adb,
+ sem_elab.adb: Simplify membership test.
+
+2020-12-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-powtab.ads (Maxpow): Use explicit formula in comment.
+
+2020-12-16 Philippe Gil <gil@adacore.com>
+
+ * libgnarl/s-tporft.adb (Register_Foreign_Thread): Set
+ Global_Task_Lock_Nesting before using allocator.
+
+2020-12-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valrea.adb (Maxexp32): New constant array.
+ (Maxexp64): Likewise.
+ (Maxexp80): Likewise.
+ (Integer_to_Real): New local constants Maxexp and B.
+ When the exponent is too negative, do the divison in two steps.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_pragmas.rst
+ (Test_Case): Change integer to float literals.
+ * gnat_rm.texi: Regenerate.
+
+2020-12-16 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add a codefix
+ for extra parentheses around aspect Annotate expression; reject
+ "(null record)" aggregate and extra parentheses around aspect
+ Test_Case expression.
+ * sem_prag.adb (Analyze_Pragma): Reject "null", "(null record)"
+ and extra parentheses around pragma Contract_Cases; likewise for
+ pragma Subprogram_Variant.
+
+2020-12-16 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * adaint.h (__gnat_in_child_after_fork): New flag to express
+ child process side after fork call.
+ * adaint.c (__gnat_portable_spawn): Set flag
+ __gnat_in_child_after_fork.
+ * expect.c (__gnat_expect_fork): Set __gnat_in_child_after_fork
+ to one on child side.
+ * libgnat/memtrack.adb
+ (In_Child_After_Fork): Flag to disable memory tracking.
+ (Allow_Trace): New routine defining if memory should be tracked.
+ (Alloc, Realloc, Free): Use Allow_Trace in "if" condition
+ instead of First_Call.
+
+2020-12-16 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-tifiio.adb: Mark body not in SPARK.
+ * libgnat/a-tifiio.ads: Mark spec in SPARK.
+ * libgnat/a-tifiio__128.adb: Mark body not in SPARK.
+
+2020-12-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valuer.adb (Scan_Decimal_Digits): Tweak overflow test.
+ (Scan_Integral_Digits): Likewise.
+
+2020-12-16 Pascal Obry <obry@adacore.com>
+
+ * s-oscons-tmplt.c: Add some OS constants.
+
+2020-12-15 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-sercom__linux.adb (Set): Use cfsetospeed and
+ cfsetispeed to set the baud rate. Clear non-blocking serial port
+ status when blocking is requested.
+
+2020-12-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valrea.adb (Integer_to_Real): Always use Extra.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch5.adb (P_Condition): Simplify condition for warning
+ about extra parens and make it easier to understand.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * errout.ads (Error_Msg_Ada_2005_Extension): New routine (spec).
+ * errout.adb (Error_Msg_Ada_2005_Extension): New routine (body).
+ * par-ch10.adb: Reuse new routine; correct casing for "LIMITED
+ WITH".
+ * par-ch11.adb: Likewise.
+ * par-ch12.adb: Likewise.
+ * par-ch3.adb: Likewise.
+ * par-ch4.adb: Likewise; replace "box" with "<>".
+ * par-ch6.adb: Likewise.
+ * par-ch9.adb: Likewise; correct casing for "THEN ABORT".
+
+2020-12-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/gnat_and_program_execution.rst: Minor fix.
+ * gnat_ugn.texi: Regenerate.
+ * libgnat/s-valuer.ads (Precision_Limit): New formal parameter.
+ * libgnat/s-valuer.adb (Precision_Limit): Remove.
+ (Scan_Decimal_Digits): Robustify overflow check.
+ (Scan_Integral_Digits): Likewise.
+ * libgnat/s-valrea.adb: Add assertion on the size of the unsigned
+ type and instantiate System.Value_R with the mantissa limit.
+ (Integer_to_Real): Add Extra parameter and take it into account.
+ (Scan_Real): Pass Extra to Integer_to_Real.
+ (Value_Real): Likewise.
+ * libgnat/s-valued.adb: Add assertion on the size of the unsigned
+ type and instantiate System.Value_R with the mantissa limit.
+ * libgnat/s-valuef.adb: Likewise.
+
+2020-12-15 Justin Squirek <squirek@adacore.com>
+
+ * contracts.adb, contracts.ads (Build_Postconditions_Procedure):
+ Add declarations for Postcond_Enabled,
+ Result_Object_For_Postcondition, and
+ Return_Success_For_Postcond, and place all postconditions within
+ an if statement to control their execution for interactions when
+ cleanup actions get generated.
+ (Get_Postcond_Enabled): Created to fetch object declared to
+ handle new expansion of postconditions.
+ (Get_Result_Object_For_Postcond): Created to fetch object
+ declared to handle new expansion of postconditions.
+ (Get_Return_Success_For_Postcond): Created to fetch object
+ declared to handle new expansion of postconditions.
+ * einfo.adb, einfo.ads: Modify flag Stores_Attribute_Old_Prefix
+ to apply to constants, variables, and types.
+ * exp_ch6.adb (Add_Return): Add assignment to
+ Return_Success_For_Postcond.
+ (Expand_Non_Function_Return): Add assignment to
+ Return_Success_For_Postcond
+ (Expand_Simple_Function_Return): Add assignment to
+ Result_Object_For_Postcond and Return_Success_For_Postcond.
+ * exp_ch7.adb (Build_Finalization_Master): Mark finalization
+ masters which finalize types created store 'Old objects as
+ storing 'Old objects.
+ (Build_Finalizer): Created to generated a unified and special
+ expansion for finalization when postconditions are present.
+ (Build_Finalizer_Helper): Renamed Build_Finalizer and added
+ parameter to facilitate the creation of separate finalization
+ routines for 'Old objects and general objects.
+ (Create_Finalizer): Add condition for the insertion of the
+ finalizer spec to avoid malformed trees.
+ (Expand_Cleanup_Actions): Move _postconditions and related
+ declarations to the new declarative section. Fix the loop to
+ properly stop at the subprogram declaration for the
+ postconditions procedure and exclude its body from being moved
+ to the new list of declarations to avoid freezing issues.
+ * exp_prag.adb (Expand_Attributes): Mark temporary created to
+ store 'Old objects as storing a 'Old attribute.
+ * sem_ch6.adb (Find_What_Applies_To): Remove strange exception
+ to postconditions when traversing the scope stack.
+ * sem_prag.adb (Find_Related_Declaration_Or_Body): Use the newly
+ created Enclosing_HSS function to find the HSS for a potentially
+ nested statement.
+ * sem_util.adb, sem_util.ads (Declare_Indirect_Temp): Mark types
+ created to store 'Old objects as storing 'Old attributes.
+ (Enclosing_HSS): Created to find the enclosing handled sequence
+ of statements for a given statement.
+ * snames.ads-tmpl: Add multiple names to aid in the expansion of
+ finalization and to control the evaluation of postconditions.
+ Including _finalization_controller, a new routine to centralize
+ finalization actions and postcondition evaluation.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch5.adb (P_Loop_Parameter_Specification): Complain about
+ missing -gnat2020 switch.
+ (P_Iterator_Specification): Likewise.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch4.adb (P_Aggregate_Or_Paren_Expr): Simplify with
+ Append_New.
+
+2020-12-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Remove s-fatsfl$(objext)
+ and add s-valflt$(objext), s-vallfl$(objext), s-valllf$(objext).
+ * exp_attr.adb (Find_Fat_Info): Merge Short_Float and Float cases.
+ * exp_imgv.adb (Expand_Value_Attribute): Replace RE_Value_Real with
+ RE_Value_Long_Long_Float for fixed-point types and use appropriate
+ base type for floating-point types.
+ * rtsfind.ads (RTU_Id): Remove System_Fat_IEEE_Long_Float,
+ System_Fat_IEEE_Short_Float and System_Val_Real, add System_Val_Flt,
+ System_Val_LFlt and System_Val_LLF.
+ (RE_Id): Remove RE_Attr_IEEE_Long, RE_Fat_IEEE_Long,
+ RE_Attr_IEEE_Short, RE_Fat_IEEE_Short, RE_Attr_Short_Float, add
+ RE_Value_Float, RE_Value_Long_Float, RE_Value_Long_Long_Float,
+ (RE_Unit_Table): Likewise.
+ * libgnat/a-ticoau.ads: Add with clause for Float_Aux and make the
+ package generic.
+ (Get): Change parameter types to Num.
+ (Put): Likewise.
+ (Gets): Likewise.
+ (Puts): Likewise.
+ * libgnat/a-ticoau.adb: Remove clause and renaming for Float_Aux.
+ (Get): Change parameter types to Num.
+ (Gets): Likewise.
+ (Put): Likewise.
+ (Puts): Likewise. Add conversion to Long_Long_Float.
+ * libgnat/a-ticoio.adb: Remove with clause for Ada.Text_IO, add with
+ clause for Float_Aux, add with and use clauses for System.Val_Flt,
+ System.Val_LFlt and System.Val_LLF. Instantiate Float_Aux and
+ Complex_Aux on Float, Long_Float, and Long_Long_Float.
+ (OK_Float): New boolean constant.
+ (OK_Long_Float): Likewise.
+ (Get): Call appropriate Get routine from auxiliary package.
+ (Get): Call appropriate Gets routine from auxiliary package.
+ (Put): Call appropriate Put routine from auxiliary package.
+ (Put): Call appropriate Puts routine from auxiliary package.
+ * libgnat/a-tideau.adb: Remove with and use clause for Float_Aux.
+ * libgnat/a-tifiau.adb: Likewise.
+ * libgnat/a-tifiio.adb: Add with and use clause for System.Val_LLF.
+ Instantiate Float_Aux on Long_Long_Float.
+ (Get): Adjust call to Get routine from auxiliary package.
+ (Get): Adjust call to Gets routine from auxiliary package.
+ (Put): Adjust call to Put routine from auxiliary package.
+ (Put): Adjust call to Puts routine from auxiliary package.
+ * libgnat/a-tifiio__128.adb: Likewise.
+ (Get): Likewise.
+ (Get): Likewise.
+ (Put): Likewise.
+ (Put): Likewise.
+ * libgnat/a-tiflau.ads: Make the package generic.
+ (Get): Change parameter type to Num.
+ (Put): Likewise.
+ (Gets): Likewise.
+ (Puts): Likewise.
+ * libgnat/a-tiflau.adb: Remove clauses for System.Val_Real.
+ (Get): Change parameter type to Num and call Scan routine.
+ (Gets): Likewise.
+ (Load_Real): Move to...
+ (Put): Change parameter type and add conversion to Long_Long_Float.
+ (Puts): Likewise.
+ * libgnat/a-tiflio.adb: Add with and use clauses for System.Val_Flt,
+ System.Val_LFlt and System.Val_LLF. Instantiate Float_Aux on Float,
+ Long_Float and Long_Long_Float.
+ (OK_Float): New boolean constant.
+ (OK_Long_Float): Likewise.
+ (Get): Call appropriate Get routine from auxiliary package.
+ (Get): Call previous variant.
+ (Get): Call appropriate Gets routine from auxiliary package.
+ (Put): Call appropriate Put routine from auxiliary package.
+ (Put): Call previous variant.
+ (Put): Call appropriate Puts routine from auxiliary package.
+ * libgnat/a-tigeau.ads (Load_Real): New procedure.
+ * libgnat/a-tigeau.adb (Load_Real): ...here.
+ * libgnat/a-wtcoau.ads: Add with clause for Float_Aux and make the
+ package generic.
+ (Get): Change parameter types to Num.
+ (Put): Likewise.
+ (Gets): Likewise.
+ (Puts): Likewise.
+ * libgnat/a-wtcoau.adb: Remove clause and renaming for Float_Aux.
+ (Get): Change parameter types to Num.
+ (Gets): Likewise.
+ (Put): Likewise.
+ (Puts): Likewise. Add conversion to Long_Long_Float.
+ * libgnat/a-wtcoio.ads: Remove use clause for Complex_Types and use
+ qualified names throughout accordingly.
+ * libgnat/a-wtcoio.adb: Remove clause for Ada.Unchecked_Conversion,
+ add with clause for Float_Aux, add clauses for System.Val_Flt,
+ System.Val_LFlt and System.Val_LLF. Add clause for Complex_Types.
+ Instantiate Float_Aux and Complex_Aux on Float, Long_Float, and
+ Long_Long_Float. Remove LLF subtype and TFT instantiation.
+ (OK_Float): New boolean constant.
+ (OK_Long_Float): Likewise.
+ (Get): Call appropriate Get routine from auxiliary package.
+ (Get): Call appropriate Gets routine from auxiliary package.
+ (Put): Call appropriate Put routine from auxiliary package.
+ (Put): Call appropriate Puts routine from auxiliary package.
+ * libgnat/a-wtdeau.adb: Remove with and use clause for Float_Aux.
+ * libgnat/a-wtfiau.adb: Likewise.
+ * libgnat/a-wtfiio.adb: Add with and use clause for System.Val_LLF.
+ Instantiate Float_Aux on Long_Long_Float.
+ (Get): Adjust call to Get routine from auxiliary package.
+ (Get): Adjust call to Gets routine from auxiliary package.
+ (Put): Adjust call to Put routine from auxiliary package.
+ (Put): Adjust call to Puts routine from auxiliary package.
+ * libgnat/a-wtfiio__128.adb: Likewise.
+ (Get): Likewise.
+ (Get): Likewise.
+ (Put): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtflau.ads: Make the package generic.
+ (Get): Change parameter type to Num.
+ (Put): Likewise.
+ (Gets): Likewise.
+ (Puts): Likewise.
+ * libgnat/a-wtflau.adb: Remove clauses for System.Val_Real.
+ (Get): Change parameter type to Num and call Scan routine. Set
+ Ptr parameter lazily.
+ (Gets): Likewise.
+ (Load_Real): Move to...
+ (Put): Change parameter type and add conversion to Long_Long_Float.
+ Bump buffer length to Max_Real_Image_Length.
+ (Puts): Likewise.
+ * libgnat/a-wtflio.adb: Add with and use clauses for System.Val_Flt,
+ System.Val_LFlt and System.Val_LLF. Instantiate Float_Aux on Float,
+ Long_Float and Long_Long_Float.
+ (OK_Float): New boolean constant.
+ (OK_Long_Float): Likewise.
+ (Get): Call appropriate Get routine from auxiliary package. Add
+ pragma Unsuppress (Range_Check) and manual validity check.
+ (Get): Call appropriate Gets routine from auxiliary package. Add
+ pragma Unsuppress (Range_Check) and manual validity check.
+ (Put): Call appropriate Put routine from auxiliary package.
+ (Put): Call appropriate Puts routine from auxiliary package.
+ * libgnat/a-wtgeau.ads (Load_Real): New procedure.
+ * libgnat/a-wtgeau.adb (Load_Real): ...here.
+ * libgnat/a-ztcoau.ads: Add with clause for Float_Aux and make the
+ package generic.
+ (Get): Change parameter types to Num.
+ (Put): Likewise.
+ (Gets): Likewise.
+ (Puts): Likewise.
+ * libgnat/a-ztcoau.adb: Remove clause and renaming for Float_Aux.
+ (Get): Change parameter types to Num.
+ (Gets): Likewise.
+ (Put): Likewise.
+ (Puts): Likewise. Add conversion to Long_Long_Float.
+ * libgnat/a-ztcoio.ads: Remove use clause for Complex_Types and use
+ qualified names throughout accordingly.
+ * libgnat/a-ztcoio.adb: Remove clause for Ada.Unchecked_Conversion,
+ add with clause for Float_Aux, add clauses for System.Val_Flt,
+ System.Val_LFlt and System.Val_LLF. Add clause for Complex_Types.
+ Instantiate Float_Aux and Complex_Aux on Float, Long_Float, and
+ Long_Long_Float. Remove LLF subtype and TFT instantiation.
+ (OK_Float): New boolean constant.
+ (OK_Long_Float): Likewise.
+ (Get): Call appropriate Get routine from auxiliary package.
+ (Get): Call appropriate Gets routine from auxiliary package.
+ (Put): Call appropriate Put routine from auxiliary package.
+ (Put): Call appropriate Puts routine from auxiliary package.
+ * libgnat/a-ztdeau.adb: Remove with and use clause for Float_Aux.
+ * libgnat/a-ztfiau.adb: Likewise.
+ * libgnat/a-ztfiio.adb: Add with and use clause for System.Val_LLF.
+ Instantiate Float_Aux on Long_Long_Float.
+ (Get): Adjust call to Get routine from auxiliary package.
+ (Get): Adjust call to Gets routine from auxiliary package.
+ (Put): Adjust call to Put routine from auxiliary package.
+ (Put): Adjust call to Puts routine from auxiliary package.
+ * libgnat/a-ztfiio__128.adb: Likewise.
+ (Get): Likewise.
+ (Get): Likewise.
+ (Put): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztflau.ads: Make the package generic.
+ (Get): Change parameter type to Num.
+ (Put): Likewise.
+ (Gets): Likewise.
+ (Puts): Likewise.
+ * libgnat/a-ztflau.adb: Remove clauses for System.Val_Real.
+ (Get): Change parameter type to Num and call Scan routine. Set
+ Ptr parameter lazily.
+ (Gets): Likewise.
+ (Load_Real): Move to...
+ (Put): Change parameter type and add conversion to Long_Long_Float.
+ Bump buffer length to Max_Real_Image_Length.
+ (Puts): Likewise.
+ * libgnat/a-ztflio.adb: Add with and use clauses for System.Val_Flt,
+ System.Val_LFlt and System.Val_LLF. Instantiate Float_Aux on Float,
+ Long_Float and Long_Long_Float.
+ (OK_Float): New boolean constant.
+ (OK_Long_Float): Likewise.
+ (Get): Call appropriate Get routine from auxiliary package. Add
+ pragma Unsuppress (Range_Check) and manual validity check.
+ (Get): Call appropriate Gets routine from auxiliary package. Add
+ pragma Unsuppress (Range_Check) and manual validity check.
+ (Put): Call appropriate Put routine from auxiliary package.
+ (Put): Call appropriate Puts routine from auxiliary package.
+ * libgnat/a-ztgeau.ads (Load_Real): New procedure.
+ * libgnat/a-ztgeau.adb (Load_Real): ...here.
+ * libgnat/s-fatsfl.ads: Delete.
+ * libgnat/s-valflt.ads: New package.
+ * libgnat/s-vallfl.ads: Likewise.
+ * libgnat/s-valllf.ads: Likewise.
+ * libgnat/s-valrea.ads: Make generic. Add assertions, defensive
+ code and clarify intent.
+ (Scan_Real): Change parameter type to Num.
+ (Value_Real): Likewise.
+ * libgnat/s-valrea.adb: Instantiate Value_R on Uns.
+ (Integer_to_Real): Change parameter and result to Num.
+ Call Float_Control.Reset only if the mantissa is 64 bits. Use
+ a divide to compute the final value if the scale is negative.
+ (Scan_Real): Change result to Num.
+ (Value_Real): Likewise.
+ * libgnat/s-valuer.adb: Add assertions, defensive code and
+ clarify intent.
+ (F_Limit): Delete.
+ (I_Limit): Likewise.
+ (Precision_Limit): Always use the integer limit.
+ * libgnat/s-fatgen.adb: Add pragma Annotate.
+
+2020-12-15 Yannick Moy <moy@adacore.com>
+
+ * libgnat/a-tiflio.adb: Mark body not in SPARK.
+ * libgnat/a-tiflio.ads: Mark spec in SPARK.
+
+2020-12-15 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch6.adb (Build_Procedure_Body_Form): Adjust, the
+ declaration of the procedure form is now insert before the
+ original function body rather than after.
+ (Expand_N_Subprogram_Declaration): Deal with private types whose
+ full views are arrays.
+ * exp_unst.adb (Unnest_Subprogram): Deal with private types.
+ (Needs_Fat_Pointer): Code cleanup.
+ * freeze.adb (Freeze_Subprogram): Ditto.
+ * exp_util.adb (Build_Procedure_Form): Insert the procedure form
+ decl before and not after.
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Build missing
+ spec when needed for Transform_Function_Array.
+ * sem_util.adb (Get_Fullest_View): Deal with null entity.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Simplify code
+ for aspect Priority.
+ * sem_prag.adb (Analyze_Pragma): Simplify code for pragma
+ Priority.
+
+2020-12-15 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch7.adb (Reset_Scopes_To_Block_Elab_Proc): Do not crash on
+ a block with no Identifier. Code cleanups.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Reuse existing code for
+ attribute Value when analyzing attributes Wide_Value and
+ Wide_Wide_Value.
+
+2020-12-15 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-diopit.adb (Find): Fix possible infinite recursion
+ in Find iterator.
+ * libgnat/g-diopit.ads (Find): Update comments accordingly.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Callable and Terminated attributes; refactor calls to Set_Etype
+ occurring in both THEN and ELSE branches of an IF statement for
+ attribute Storage_Size.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Wide_Wide_Width, Wide_Width and Width attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Pred and Succ attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Size, Object_Size and Value_Size attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Consistently call
+ Check_Fixed_Point_Type before checking the number of attribute
+ expressions (like it is done for floating point types); reuse
+ Check_Fixed_Point_Type_0.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_disp.adb (Make_Tags): Remove call to UI_To_Int.
+ * sem_attr.adb (Check_Array_Type): Likewise; also, refine type
+ of a local variable.
+ (Analyze_Attribute): Likewise.
+ (Get_Enclosing_Object): Likewise.
+ * sem_util.adb (Get_Enum_Lit_From_Pos): Likewise.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ First_Bit/Last_Bit and Position attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Machine_Radix and Mantissa attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Machine_Overflows and Machine_Rounds attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Large, Small, Safe_Large and Safe_Small attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Epsilon, Model_Epsilon, Model_Small, Safe_First and Safe_Las
+ attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Emax, Machine_Emax, Machine_Emin, Machine_Mantissa, Model_Emin,
+ Model_Mantissa and Safe_Emax attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Denorm and Signed_Zeros attributes.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Adjacent, Copy_Sign and Remainder attributes.
+ (Check_Floating_Point_Type_2): Fix style in comment.
+
+2020-12-15 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Compose, Leading_Part and Scaling attributes.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Resolve second parameter of
+ attribute Scaling just like it is resolved for a similar
+ attribute Compose.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ First/Last, First_Bit/Last_Bit and First_Valid/Last_Valid
+ attributes.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge similar code for
+ Truncation and other floating point attributes.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Merge identical code for
+ Ceiling, Floor, Fraction, Machine, Machine_Rounding, Model,
+ Rounding and Unbiased_Rounding.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb: Adjust documentation.
+ (OK_Get_32): Compare the object size of the base type.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ * libgnat/a-tifiio__128.adb: Adjust documentation.
+ (OK_Get_32): Compare the object size of the base type.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (OK_Get_128): Likewise.
+ (OK_Put_128): Likewise.
+ * libgnat/a-wtfiio.adb (OK_Get_32): Likewise.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise
+ * libgnat/a-wtfiio__128.adb (OK_Get_32): Likewise.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (OK_Get_128): Likewise.
+ (OK_Put_128): Likewise.
+ * libgnat/a-ztfiio.adb (OK_Get_32): Likewise.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise
+ * libgnat/a-ztfiio__128.adb (OK_Get_32): Likewise.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (OK_Get_128): Likewise.
+ (OK_Put_128): Likewise.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb (Get): Replace Current_Input with Current_In.
+ * libgnat/a-tifiio__128.adb: (Get): Likewise.
+ * libgnat/a-wtcoio.adb (Get): Likewise.
+ (Put): Replace Current_Output with Current_Out.
+ * libgnat/a-wtdeio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtdeio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtenio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtfiio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtfiio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtflio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtinio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtinio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtmoio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-wtmoio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztcoio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztdeio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztdeio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztenio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztfiio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztfiio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztflio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztinio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztinio__128.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztmoio.adb (Get): Likewise.
+ (Put): Likewise.
+ * libgnat/a-ztmoio__128.adb (Get): Likewise.
+ (Put): Likewise.
+
+2020-12-14 Justin Squirek <squirek@adacore.com>
+
+ * sem_util.adb, sem_util.ads (In_Generic_Formal_Package):
+ Created to identify type declarations occurring within generic
+ formal packages.
+ * sem_res.adb (Resolve_Allocator): Add condition to avoid
+ emitting an error for allocators when the type being allocated
+ is class-wide and from a generic formal package.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-fatgen.adb (Tiny80): Add alignment clause.
+
+2020-12-14 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_util.adb (Process_Current_Value_Condition): Add assertion.
+ * libgnat/s-fatgen.adb (Scaling): Add annotation.
+
+2020-12-14 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_eval.adb (Fold_Shift): Compute values using the base type.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-fatgen.adb: Add with clause for Interfaces and use
+ type clause for Interfaces.Unsigned_64.
+ (Small): Comment out.
+ (Tiny): Likewise.
+ (Tiny16): New integer constant.
+ (Tiny32): Likewise.
+ (Tiny64): Likewise.
+ (Tiny80): New integer array constant.
+ (Pred): Declare a local overlay for Tiny.
+ (Succ): Likewise.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_pakd.adb (Expand_Bit_Packed_Element_Set): Fix again packed
+ array type in complex cases where array is Volatile.
+ * exp_util.adb (Remove_Side_Effects): Do not force a renaming to
+ be handled by the back-end.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-fatgen.adb: Remove use clause for
+ System.Unsigned_Types.
+ (Scaling): Add renaming of System.Unsigned_Types and use type
+ clause for Long_Long_Unsigned.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-fatgen.ads (Compose): Add pragma Inline.
+ (Copy_Sign): Likewise.
+ (Exponent): Likewise.
+ (Fraction): Likewise.
+ * libgnat/s-fatgen.adb: Remove with clause for System, add
+ with and use clauses for System.Unsigned_Types.
+ Add pragma Warnings (Off) for non-static constants.
+ Remove precomputed tables of powers of radix and add a few
+ constants describing the floating-point format.
+ (Gradual_Scaling): Delete.
+ (Copy_Sign): Reimplement directly.
+ (Decompose): Likewise.
+ (Scaling): Likewise.
+ (Pred): Speed up.
+ (Succ): Likewise.
+ (Truncation): Tidy up.
+ (Valid): Move constants to library level.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_eval.adb (CV_Cache): Remove initialization at elaboration.
+
+2020-12-14 Gary Dismukes <dismukes@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
+ Correct documentation of the -gnatw.K switch to say that it
+ disables rather than activates the warning.
+ * gnat_ugn.texi: Regenerate.
+
+2020-12-14 Doug Rupp <rupp@adacore.com>
+
+ * tracebak.c: Add a section for ARM Linux.
+
+2020-12-14 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * par-ch3.adb (P_Discriminant_Part_Opt): Parse aspects, update
+ documentation.
+ * par-ch6.adb (P_Return_Statement): Likewise.
+ * par-ch9.adb (P_Entry_Index_Specification): Likewise.
+
+2020-12-14 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_aggr.adb (Build_Array_Aggr_Code.Gen_Assign): Move
+ generation of the call for DIC check past the optional
+ generation of calls to controlled Initialize procedures.
+ * exp_ch3.adb
+ (Build_Array_Init_Proc.Init_One_Dimension.Possible_DIC_Call):
+ Suppress generation of a DIC call when the array component type
+ is controlled. The call will now be generated later inside the
+ array's DI (Deep_Initialize) procedure.
+ * exp_ch7.adb
+ (Make_Deep_Array_Body.Build_Initialize_Statements): Generate a
+ DIC call (when needed by the array component type) after any
+ call to the component type's controlled Initialize procedure, or
+ generate the DIC call by itself if there's no Initialize to
+ call.
+ * sem_aggr.adb (Resolve_Record_Aggregate.Add_Association):
+ Simplify condition to only test Is_Box_Init_By_Default (previous
+ condition was overkill, as well as incorrect in some cases).
+ * sem_elab.adb (Active_Scenarios.Output_Call): For
+ Default_Initial_Condition, suppress call to
+ Output_Verification_Call when the subprogram is a partial DIC
+ procedure.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference) <Attribute_Round>:
+ Adjust commentary and set the Rounded_Result flag on the type
+ conversion node when the node is needed.
+ * exp_ch4.adb (Expand_N_Type_Conversion): Minor tweak.
+ (Fixup_Universal_Fixed_Operation): Look through the type conversion
+ only when it is to Universal_Real.
+ * exp_fixd.adb: Remove with and use clauses for Snames.
+ (Build_Divide): Remove redundant test.
+ (Expand_Convert_Float_To_Fixed): Use Rounded_Result flag on the
+ node to set the truncation parameter.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Analyze_Refinement_Clause): Simplify recently
+ added code for preventing cascaded errors.
+
+2020-12-14 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.adb (Is_Build_In_Place_Result_Type): Further narrow
+ the conditions under which we enable build-in-place for
+ controlled types.
+
+2020-12-14 Yannick Moy <moy@adacore.com>
+
+ * sem_warn.adb (Output_Non_Modified_In_Out_Warnings): Use right
+ warning control character 'k' in both comment and call to
+ Errout_Msg_N.
+
+2020-12-14 Yannick Moy <moy@adacore.com>
+
+ * sem_prag.adb (Analyze_Refined_State_In_Decl_Part): Refine the
+ error message for missing Part_Of on constituent. Avoid
+ cascading error.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Analyze_Depends_In_Decl_Part): Replace early
+ returns with goto Leave.
+ (Collect_Subprogram_Inputs_Outputs): Fix style in comment.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-fatgen.ads (Valid): Add again pragma Inline.
+ * libgnat/s-fatgen.adb (Valid): Improve commentary, tidy up left
+ and right, and remove superfluous trick for denormalized numbers.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Find_Role): Constant object of
+ access-to-constant and access-to-subprogram types are not
+ writable.
+ (Collect_Subprogram_Inputs_Outputs): In-parameters of
+ access-to-variable type can act as outputs of the Depends
+ contracts.
+
+2020-12-14 Piotr Trojanek <trojanek@adacore.com>
+
+ * sa_messages.ads: Reference Subprogram_Variant in the comment
+ for Assertion_Check.
+ * sem_prag.adb (Analyze_Pragma): Add Subprogram_Variant as an
+ ID_ASSERTION_KIND; move Default_Initial_Condition as an
+ RM_ASSERTION_KIND.
+
+2020-12-14 Yannick Moy <moy@adacore.com>
+
+ * inline.adb (Cannot_Inline): Add No_Info parameter to disable
+ info message.
+ * inline.ads (Cannot_Inline): When No_Info is set to True, do
+ not issue info message in GNATprove mode, but still mark the
+ subprogram as not always inlined.
+ * sem_res.adb (Resolve_Call): Always call Cannot_Inline inside
+ an assertion expression.
+
+2020-12-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-imguti.ads (Set_Decimal_Digits): Adjust documentation.
+
+2020-12-10 Ed Schonberg <schonberg@adacore.com>
+
+ PR ada/98230
+ * exp_attr.adb (Expand_N_Attribute_Reference, case Mod): Use base
+ type of argument to obtain static bound and required size.
+
+2020-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Make-lang.in: Remove ^L characters.
+ * gcc-interface/decl.c (create_concat_name): Add cast.
+
+2020-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (maybe_make_gnu_thunk): Return false if the
+ target is local and thunk and target do not have the same context.
+
+2020-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (lvalue_for_aggregate_p): Also return true
+ for return statements.
+ * gcc-interface/utils.c (gnat_write_global_declarations): Use the
+ maximum index for the dummy object to avoid a name collision.
+
+2020-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <Fixed_Point_Type>: Put
+ back the "else" unduly removed.
+
+2020-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Call_to_gnu): Also create a temporary for
+ the return value if the LHS is a bit-field and the return type is
+ a type padding a self-referential type.
+ (gnat_to_gnu): Do not remove the padding on the result if it is too
+ small with regard to the natural padding size.
+
+2020-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (convert) <INTEGER_TYPE>: Call fold_convert
+ in the cases where convert_to_integer is not called.
+ <BOOLEAN_TYPE>: Call fold_convert instead of convert_to_integer.
+
+2020-12-07 Matthias Klose <doko@ubuntu.com>
+
+ PR ada/97504
+ * Makefile.rtl (LIBGNAT_TARGET_PAIRS) <mips*-*-linux*>: Use wraplf
+ version of Aux_Long_Long_Float.
+
+2020-11-30 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ * libgnat/s-trasym.ads: Update the list of supported platforms.
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * gcc-interface/Makefile.in, gcc-interface/trans.c: Remove ^L
+ characters.
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * gcc-interface/Makefile.in (GNATLIBFLAGS): Enable checks by
+ default.
+ * libgnat/s-bitfie.ads: Suppress alignment checks.
+ * libgnat/s-bituti.adb: Minor reformatting.
+ * libgnat/s-secsta.adb (SS_Allocate): Support Size = 0.
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch3.adb (Replace_Discr_Ref): Removed, no longer needed.
+
+2020-11-30 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch5.adb (Process_Statements): Replace low-level membership
+ test with a high-level wrapper.
+
+2020-11-30 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch5.adb (Set_Assignment_Type): Combine calls to Ekind
+ using membership test.
+ (Should_Transform_BIP_Assignment): Replace assignment to a
+ "Result" variable with simple return statements; avoid repeated
+ calls to Unqual_Conv by declaring a local constant.
+
+2020-11-30 Piotr Trojanek <trojanek@adacore.com>
+
+ * lib-xref.adb (Generate_Reference): Fix reference to
+ Analyze_Assignment.
+ * sem_ch5.adb (Diagnose_Non_Variable_Lhs): Reuse existing
+ utility function.
+
+2020-11-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * contracts.adb (Check_Type_Or_Object_External_Properties): Make
+ sure to exclude all return objects from the SPARK legality rule
+ on effectively volatile variables.
+ * exp_ch6.adb (Expand_N_Extended_Return_Statement): Use the fast
+ track only when the declaration of the return object can be
+ dropped.
+
+2020-11-30 Gary Dismukes <dismukes@adacore.com>
+
+ * einfo.ads (Is_Partial_DIC_Procedure): New function.
+ (Partial_DIC_Procedure): New procedure.
+ * einfo.adb (Is_Partial_DIC_Procedure): New function to return
+ whether a subprogram is a partial Default_Initial_Condition
+ procedure by checking the name (to avoid adding a new field).
+ (DIC_Procedure): Add a test that excludes partial DIC procedures
+ from being returned.
+ (Partial_DIC_Procedure): New procedure to return the partial DIC
+ procedure of a type, if it has one (otherwise returns Empty).
+ (Set_DIC_Procedure): Remove check for duplicate DIC procedures.
+ * exp_aggr.adb (Gen_Assign): Generate a call to the type's DIC
+ procedure in the case where an array component is default
+ initialized (due to an association with a box).
+ (Build_Record_Aggr_Code): For an extension aggregate, generate a
+ call to the ancestor type's DIC procedure (if any) when the
+ ancestor part is a subtype mark. For a record component
+ association that was specified with a box (tested for by
+ checking the new flag Was_Default_Init_Box_Association),
+ generate a call to the component type's DIC procedure (if it has
+ one).
+ * exp_ch4.adb (Expand_N_Allocator): When the allocated object is
+ default initialized and the designated type has a DIC aspect,
+ generate a call to the DIC procedure.
+ * exp_util.ads (Build_DIC_Call): Change the formal Obj_Id to
+ name Obj_Name, and change its type from Entity_Id to Node_Id
+ (and update comment).
+ (Build_DIC_Procedure_Body): Add formal Partial_DIC, remove
+ formal For_Freeze, and update comment accordingly.
+ (Build_DIC_Procedure_Declaration): Add formal Partial_DIC and
+ update comment.
+ * exp_util.adb
+ (Build_DIC_Call): Revised to use its Obj_Name (formerly Obj_Id)
+ formal directly rather than calling New_Occurrence_Of on it, to
+ allow arbitrary names to be passed rather than being limited to
+ Entity_Ids.
+ (Build_DIC_Procedure_Body): Call Add_Parent_DICs to generate
+ checks for DICs associated with any parent types, implementing
+ the required "additive" semantics for DICs. When building a DIC
+ procedure body for a partial view (when Partial_DIC is True),
+ call Add_Own_DIC when the type has its own DIC. In the case of
+ "full" DIC procedures, a call is generated to any partial DIC
+ procedure of the type (unless the procedure has a null body),
+ along with checks for any DICs inherited by the full view.
+ (Build_DIC_Procedure_Declaration): Add handling for partial DIC
+ procedures. For the suffix of a regular DIC procedure's name,
+ use "DIC" (instead of "Default_Initial_Condition"), and for the
+ suffix of a partial DIC procedure's name, use "Partial_DIC".
+ (Add_DIC_Check): Add the DIC pragma to the list of seen pragmas
+ (Pragmas_Seen).
+ (Add_Inherited_Tagged_DIC): Remove the formals Par_Typ,
+ Deriv_Typ, and Obj_Id, and add formal Expr, which denotes DIC's
+ expression. Remove the call to Replace_References (which is now
+ done in Add_Inherited_DICs).
+ (Add_Inherited_DICs): New procedure to locate a DIC pragma
+ associated with a parent type, replace its references
+ appropriately (such as any current instance references), and add
+ a check for the DIC.
+ (Add_Own_DIC): Add an Obj_Id formal to allow caller to pass the
+ _init formal of the generated DIC procedure.
+ (Add_Parent_DICs): New procedure to traverse a type's parents,
+ looking for DICs associated with those and calling
+ Add_Inherited_DICs to apply the appropriate DIC checks.
+ (Is_Verifiable_DIC_Pragma): Treat pragmas that have an Empty
+ first argument the same as a pragma without any arguments
+ (returning False for that case).
+ * exp_ch3.adb (Init_One_Dimension): Generate calls to the
+ component's DIC procedure when needed.
+ (Possible_DIC_Call): New function nested in Init_One_Dimension
+ to build a call to the array component type's DIC-checking
+ function when appropriate.
+ (Build_Array_Init_Proc): The presence of a DIC on the component
+ type is an additional condition for generating an init proc for
+ an array type.
+ (Build_Init_Statements): When the record component's type has a
+ DIC, and the component declaration does not have an
+ initialization expression, generate a call to the component
+ type's DIC procedure.
+ (Expand_N_Object_Declaration): Modify the call to Build_DIC_Call
+ to pass a new occurrence of the object's defining id rather than
+ the id itself.
+ (Freeze_Type): Only build a type's DIC procedure (if it has one)
+ for types that are not interfaces.
+ * exp_spark.adb (Expand_SPARK_N_Freeze_Type): Remove From_Freeze
+ actual and add a ??? comment.
+ (Expand_SPARK_N_Object_Declaration): Modify call to
+ Build_DIC_Call to pass a new occurrence of the object id rather
+ than the object id itself.
+ * sem_aggr.adb (Resolve_Record_Aggregate): Declare local flag
+ Is_Box_Init_By_Default and set it in cases where the component
+ association has a box and the component is being initialized by
+ default (as opposed to initialized by an initialization
+ expression associated with the component's declaration).
+ (Add_Association): If the association has a box for a component
+ initialized by default, the flag
+ Was_Default_Init_Box_Association is set on the new component
+ association (for later testing during expansion).
+ (Get_Value): Reset Is_Box_Init_By_Default to False.
+ * sem_ch3.adb (Build_Assertion_Bodies_For_Type): Rearrange code
+ to build DIC procedure bodies for a (noninterface) type that
+ Has_Own_DIC (for partial type views) or Has_DIC (for full type
+ views) as appropriate.
+ * sem_ch13.adb (Analyze_Aspect_Specifications,
+ Aspect_Default_Initial_Condition): Add an extra argument to the
+ DIC pragma to denote the type associated with the pragma (for
+ use in Build_DIC_Procedure_Body).
+ * sem_prag.adb (Analyze_Pragma): Allow two arguments for pragma
+ Default_Initial_Condition. If not already present, add an extra
+ argument denoting the type that the pragma is associated with.
+ * sem_util.adb (Propagate_DIC_Attributes): Retrieve any partial
+ DIC procedure associated with the type and add it to the type's
+ list of subprograms (Subprograms_For_Type).
+ * sinfo.ads (Was_Default_Init_Box_Association): New flag on
+ N_Component_Association nodes. Add subprograms to get and set
+ flag, as well as updating the documentation.
+ * sinfo.adb (Was_Default_Init_Box_Association): New function to
+ retrieve the corresponding flag (Flag14).
+ (Set_Was_Default_Init_Box_Association): New procedure to set the
+ corresponding flag (Flag14).
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * par-ch6.adb (P_Formal_Part): Remove extra call to Scan.
+ * par-tchk.adb: Minor reformatting.
+
+2020-11-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-nbnbre.adb (Float_Conversions): Instantiate Conv
+ package only once in the body.
+ (Fixed_Conversions.Float_Aux): New instance.
+ (Fixed_Conversions.Conv_I): Likewise.
+ (Fixed_Conversions.Conv_U): Likewise.
+ (Fixed_Conversions.LLLI): New subtype.
+ (Fixed_Conversions.LLLU): Likewise.
+ (Fixed_Conversions.Too_Large): New constant.
+ (Fixed_Conversions.To_Big_Real): Reimplement.
+ (Fixed_Conversions.From_Big_Real): Likewise.
+
+2020-11-30 Bob Duff <duff@adacore.com>
+
+ * exp_ch3.adb (Expand_N_Object_Declaration): Avoid crash in case
+ of conditional expression.
+
+2020-11-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_attributes.rst (Pool_Address):
+ Fix pasto.
+ (Small_Denominator): New entry.
+ (Small_Numerator): Likewise.
+ * doc/gnat_rm/implementation_defined_characteristics.rst (3.5.9):
+ Relax conditions on 128-bit smalls and integer-only implementation.
+ * gnat_rm.texi: Regenerate.
+ * exp_attr.adb (Expand_N_Attribute_Reference) <Attribute_Fore>:
+ Relax conditions on integer implementation for ordinary fixed-point
+ types and pass a third parameter to the routine.
+ <Attribute_Small_Denominator>: Raise Program_Error.
+ <Attribute_Small_Numerator>: Likewise.
+ * exp_fixd.adb (Expand_Convert_Fixed_To_Fixed): Use a scaled divide
+ if the numerator and denominator of the small ratio are sufficiently
+ small integers.
+ (Expand_Convert_Fixed_To_Integer): Use a scaled divide if numerator
+ and denominator of the small value are sufficiently small integers.
+ (Expand_Convert_Integer_To_Fixed): Likewise.
+ * exp_imgv.adb (Expand_Image_Attribute): Relax the conditions on the
+ integer implementation for ordinary fixed-point types.
+ (Expand_Value_Attribute): Likewise.
+ * freeze.adb (Freeze_Fixed_Point_Type): Relax conditions on 128-bit
+ smalls.
+ * sem_attr.adb (Analyze_Attribute) <Attribute_Small_Denominator>:
+ Check no arguments, fixed-point and set type to Universal_Integer.
+ <Attribute_Small_Numerator>: Likewise.
+ (Eval_Attribute) <Attribute_Small_Denominator>: Fold statically.
+ <Attribute_Small_Numerator>: Likewise.
+ * snames.ads-tmpl (Name_Small_Denominator): New attribute name.
+ (Name_Small_Numerator): Likewise.
+ (Attribute_Id): Add Attribute_Small_{Denominator,Numerator}.
+ * libgnat/a-tifiio.adb (Exact): Delete.
+ (Need_64): Likewise.
+ (OK_Get_32): New boolean constant.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (E): Adjust.
+ (Get procedures): Likewise.
+ (Put procedures): Likewise.
+ * libgnat/a-tifiio__128.adb (Exact): Delete.
+ (Need_64): Likewise.
+ (Need_128): Likewise.
+ (OK_Get_32): New boolean constant.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (OK_Get_128): Likewise.
+ (OK_Put_128): Likewise.
+ (E): Adjust.
+ (Get procedures): Likewise.
+ (Put procedures): Likewise.
+ * libgnat/a-wtfiio.adb (Exact): Delete.
+ (Need_64): Likewise.
+ (OK_Get_32): New boolean constant.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (E): Adjust.
+ (Get procedures): Likewise.
+ (Put procedures): Likewise.
+ * libgnat/a-wtfiio__128.adb (Exact): Delete.
+ (Need_64): Likewise.
+ (Need_128): Likewise.
+ (OK_Get_32): New boolean constant.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (OK_Get_128): Likewise.
+ (OK_Put_128): Likewise.
+ (E): Adjust.
+ (Get procedures): Likewise.
+ (Put procedures): Likewise.
+ * libgnat/a-ztfiio.adb (Exact): Delete.
+ (Need_64): Likewise.
+ (OK_Get_32): New boolean constant.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (E): Adjust.
+ (Get procedures): Likewise.
+ (Put procedures): Likewise.
+ * libgnat/a-ztfiio__128.adb (Exact): Delete.
+ (Need_64): Likewise.
+ (Need_128): Likewise.
+ (OK_Get_32): New boolean constant.
+ (OK_Put_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Put_64): Likewise.
+ (OK_Get_128): Likewise.
+ (OK_Put_128): Likewise.
+ (E): Adjust.
+ (Get procedures): Likewise.
+ (Put procedures): Likewise.
+ * libgnat/s-fore_f.ads (Fore_Fixed): Adjust signature.
+ * libgnat/s-fore_f.adb (Fore_Fixed): Reimplement.
+ * libgnat/s-fofi32.ads (Fore_Fixed32): Adjust signature.
+ * libgnat/s-fofi64.ads (Fore_Fixed64): Likewise.
+ * libgnat/s-fofi128.ads (Fore_Fixed128): Likewise.
+ * libgnat/s-imagef.ads: Adjust description.
+ * libgnat/s-imagef.adb (Maxdigs): Move around.
+ (Set_Image_Integer): Remove assertion.
+ * libgnat/s-valuef.ads: Adjust description.
+ * libgnat/s-valuef.adb (Integer_To_Fixed): Minor tweak.
+
+2020-11-30 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
+ Describe -gnateb switch.
+ * doc/gnat_ugn/the_gnat_compilation_model.rst: Mention -gnateb
+ switch in configuration pragma files section.
+ * gnat_ugn.texi: Regenerate.
+ * lib-writ.adb (Write_ALI): Strip directories from configuration
+ files path if needed.
+ * opt.ads: Declare Config_Files_Store_Basename option.
+ * par.adb (Par): Save configuration file checksum.
+ * switch-c.adb (Scan_Front_End_Switches): Set
+ Config_Files_Store_Basename true if -gnateb is present.
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_dist.adb (RCI_Cache): Initialize.
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * terminals.c (allocate_pty_desc): Copy one less byte since the
+ last byte will always be set to 0.
+
+2020-11-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst (-xdr):
+ Document that XDR is not supported for 128-bit integer types.
+ * gnat_ugn.texi: Regenerate.
+ * exp_strm.adb (Build_Elementary_Input_Call): Deal with types
+ larger than Long_Long_Integer.
+ (Build_Elementary_Write_Call): Likewise.
+ * rtsfind.ads (RE_Id): Add RE_I_LLL{I,U] and RE_W_LLL{I,U}.
+ (RE_Unit_Table): Add entries for them.
+ * libgnat/s-stratt.ads (I_LLLI): New inline function.
+ (I_LLLU): Likewise.
+ (W_LLLI): New inline procedure.
+ (W_LLLU): Likewise.
+ * libgnat/s-stratt.adb (S_LLLI): New subtype of SEA.
+ (S_LLLU): Likewise.
+ (From_LLLI): New instance of Unchecked_Conversion.
+ (From_LLLU): Likewise.
+ (To_LLLI): Likewise.
+ (To_LLLU): Likewise.
+ (I_LLLI): Implement.
+ (I_LLLU): Likewise.
+ (W_LLLI): Likewise.
+ (W_LLLU): Likewise.
+
+2020-11-30 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch5.adb (Expand_Iterator_Loop_Over_Container): Check the
+ signature of the private operation Get_Element_Access to prevent
+ accidental use of a user-defined homonym subprogram.
+
+2020-11-30 Yannick Moy <moy@adacore.com>
+
+ * spark_xrefs.ads: Add comment for Heap that it may remain
+ Empty.
+
+2020-11-30 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-sercom__linux.adb (Set): Fix control flags of the
+ serial port setting.
+
+2020-11-30 Pascal Obry <obry@adacore.com>
+
+ * libgnat/g-sercom__linux.adb: Minor style fixes.
+
+2020-11-30 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Get_Current_Value_Condition): Don't use current
+ value tracking in GNATprove mode.
+ * sem_res.adb (Resolve_Comparison_Op): Remove incomplete
+ special-casing for folding in GNATprove mode.
+
+2020-11-30 Bob Duff <duff@adacore.com>
+
+ * errout.adb (Error_Msg_NEL): Do not call Set_Posted if errors
+ are being ignored.
+ (Error_Msg): Change Errors_Must_Be_Ignored to use the getter.
+ * sem_ch8.adb (Find_Direct_Name): Do not skip all the error
+ checks when ignoring errors, but instead do not add an entry to
+ the Urefs table if errors are being ignored.
+ * exp_ch5.adb: Minor comment fix.
+
+2020-11-30 Yannick Moy <moy@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Improve error message.
+
+2020-11-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valuef.adb (Integer_To_Fixed): Do not modify numerator
+ or denominator in order to reduce the exponent.
+
+2020-11-30 Arnaud Charlet <charlet@adacore.com>
+
+ * ali-util.adb (Get_File_Checksum): Remove dead code.
+ * exp_ch4.adb (Expand_Boolean_Operator, Expand_N_Op_Not,
+ Make_Boolean_Array_Op): Take Transform_Function_Array into
+ account.
+ * exp_ch6.adb (Expand_Call_Helper): Update comment. Code
+ cleanup.
+ * exp_util.adb (Build_Procedure_Form): Use new predefined name
+ Name_UP_RESULT.
+ * snames.ads-tmpl (Name_UP_RESULT): New predefined name. Code
+ cleanup: remove unused names from the project parser, moved to
+ gprbuild sources.
+ * xsnamest.adb: Add support for uppercase names.
+
+2020-11-30 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.adb (Enter_Name): When an inherited operation for a
+ local derived type is hidden by an explicit declaration of a
+ non-overloadable entity in the same scope, make the inherited
+ operation non-visible to prevent its accidental use elsewhere.
+
+2020-11-29 John David Anglin <danglin@gcc.gnu.org>
+
+ PR ada/97504
+ * Makefile.rtl (LIBGNAT_TARGET_PAIRS) <hppa*-*-hpux*>: Use wraplf
+ version of Aux_Long_Long_Float.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valuef.adb (Integer_To_Fixed): Take into account the
+ extra digit when scaling up the input.
+ * libgnat/s-valuer.adb (Scan_Decimal_Digits): Restrict previous
+ change to fixed-point types.
+ (Scan_Integral_Digits): Likewise.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Parent_Is_Boolean): Simplify.
+ (Resolve_Op_Not): Reduce scope of a local variable.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * cstand.adb: Simplify with Append_New_Elmt.
+ * sem_util.adb: Likewise.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_eval.adb (Fold_Shift): Fix evaluation of Shift_Right on
+ negative values.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch6.adb (Expand_Call): Properly split
+ Transform_Function_Array and Modify_Tree_For_C.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_eval.ads (Compile_Time_Compare): Restore parameter Diff to
+ be of an access type.
+ * sem_eval.adb (Compile_Time_Compare): Adapt body and callers.
+ * sem_attr.adb (Eval_Attribute): Adapt callers.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valuer.adb (Scan_Decimal_Digits): Round Extra.
+ (Scan_Integral_Digits): Likewise.
+
+2020-11-27 Yannick Moy <moy@adacore.com>
+
+ * checks.adb (Selected_Range_Checks): Adapt the condition for
+ applying range checks so that it is not done inside generics.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_fixd.adb (Build_Double_Divide): Only use a 128-bit
+ division if one of the operands is larger than 64 bits.
+ (Build_Double_Divide_Code): Likewise.
+ (Build_Scaled_Divide): Likewise.
+ (Build_Scaled_Divide_Code): Likewise.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/s-os_lib.adb (To_GM_Time): Return valid and consistent
+ values for Invalid_Time.
+
+2020-11-27 Steve Baird <baird@adacore.com>
+
+ * snames.ads-tmpl: Define new Name_Stable_Properties Name_Id
+ value.
+ * aspects.ads, aspects.adb: Add new Aspect_Stable_Properties
+ enumeration literal to Aspect_Id type. Add Class_Present
+ parameter to Find_Aspect and related
+ functions (Find_Value_Of_Aspect and Has_Aspect).
+ * sem_util.adb (Has_Nontrivial_Precondition): Fix
+ previously-latent bug uncovered by adding Class_Present
+ parameter to Aspect.Find_Aspect. The code was wrong before, but
+ with the change the bug was more likely to make a user-visible
+ difference.
+ * sem_ch6.adb (Analyze_Operator_Symbol): If a string literal
+ like "abs" or "-" occurs in a Stable_Properties aspect
+ specification, then it is to be interpreted as an operator
+ symbol and not as a string literal.
+ * sem_ch13.ads: Export new Parse_Aspect_Stable_Properties
+ function, analogous to the existing Parse_Aspect_Aggregate
+ exported procedure.
+ * sem_ch13.adb: (Parse_Aspect_Stable_Properties): New function;
+ analogous to existing Parse_Aspect_Aggregate.
+ (Validate_Aspect_Stable_Properties): New procedure; analogous to
+ existing Validate_Aspect_Aggregate. Called from the same case
+ statement (casing on an Aspect_Id value) where
+ Validate_Aspect_Aggregate is called.
+ (Resolve_Aspect_Stable_Properties): New procedure; analogous to
+ existing Resolve_Aspect_Aggregate. Called from the same two case
+ statements (each casing on an Aspect_Id value) where
+ Resolve_Aspect_Aggregate is called.
+ (Analyze_Aspect_Specifications): Set Has_Delayed_Aspects and
+ Is_Delayed_Aspect attributes for Aspect_Stable_Properties aspect
+ specifications.
+ (Check_Aspect_At_End_Of_Declarations): The syntactic
+ "expression" for a Stable_Properties aspect specification is not
+ semantically an expression; it doesn't have a type. Thus, force
+ T to be empty in this case.
+ * contracts.adb (Expand_Subprogram_Contract): Add call to new
+ local procedure,
+ Expand_Subprogram_Contract.Add_Stable_Property_Contracts, which
+ generates Postcondition pragmas corresponding to stable property
+ checks.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_pragmas.rst:
+ (Assertion_Policy): Move "Default_Initial_Condition" from
+ ID_ASSERTION_KIND to RM_ASSERTION_KIND section.
+ * gnat_rm.texi: Regenerate.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_pragmas.rst
+ (Assertion_Policy): Add "Default_Initial_Condition",
+ "Initial_Condition" and "Subprogram_Variant".
+ * gnat_rm.texi: Regenerate.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Is_Valid_Assertion_Kind): Return False on
+ "Assertion_Policy"
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * make.adb (GNAT_Flag): Change to "-gnatg".
+ (Compile): Adjust comments accordingly.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch4.adb (Rewrite_Comparison): Add assertion to confirm
+ that evaluation folds comparisons with static operands; when
+ folding comparison with non-static operands, the resulting
+ literal is non-static.
+ * sem_eval.adb (Eval_Relational_Op): Refactor nested IF
+ statement for the special case in the THEN branch; move code for
+ the "general case" out of the ELSE branch.
+ * sem_res.adb (Resolve_Comparison_Op): Only apply a dubious
+ special-case for GNATprove in the GNATprove_Mode.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_eval.ads (Compile_Time_Compare): Change parameter Diff
+ from access to mode out.
+ * sem_eval.adb (Compile_Time_Compare): Adapt body and callers.
+ * sem_attr.adb (Eval_Attribute): Adapt callers.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Op_Multiply): Move down block calling
+ Narrow_Large_Operation if the type is Universal_Integer.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-nbnbre.adb: Remove clauses for System.Img_Real and
+ add them for System.Unsigned_Types.
+ (Float_Conversions.To_Big_Real): Reimplement.
+ (Float_Conversions.From_Big_Real): Likewise.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * checks.ads (Determine_Range_To_Discrete): New procedure.
+ * checks.adb (Apply_Scalar_Range_Check): Call it to determine
+ a range for the expression when the target type is discrete.
+ And also apply the tests for discrete types to fixed-point
+ types when they are treated as integers.
+ (Apply_Type_Conversion_Checks): Apply checks to conversions
+ involving fixed-point types when they are treated as integers.
+ (Determine_Range) <N_Type_Conversion>: Factor out code into...
+ (Determine_Range_To_Discrete): ...this new procedure and add
+ support for fixed-point types when they are treated as integers.
+ * einfo.ads (Type_High_Bound): Remove obsolete sentence.
+ (Type_Low_Bound): Likewise.
+ * exp_ch4.adb (Discrete_Range_Check): Remove obsolete code.
+ (Real_Range_Check): Likewise.
+ (Expand_N_Type_Conversion): In case of a no-op conversion, clear
+ the Do_Range_Check flag on the operand before substituting it.
+ Remove calls to Real_Range_Check and Discrete_Range_Check that
+ are not guarded by the Do_Range_Check flag, and an assertion.
+ * sem_res.adb (Resolve_Type_Conversion): Always apply range
+ checks in GNATprove mode; in normal mode, use the updated type
+ of the operand in the test against Universal_Fixed. Remove
+ obsolete code setting the Do_Range_Check flag at the end.
+
+2020-11-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Change "Ref Manual" to RM;
+ replace uses of an unnecessary "Ok" variable with RETURN
+ statements; replace nested IF with ELSIF.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnarl/s-tasren.adb (Local_Complete_Rendezvous): Always call
+ Defer_Abort.
+ * libgnat/a-except.adb: Abort does not need to be deferred.
+ * libgnarl/s-tpobop.adb (Exceptional_Complete_Entry_Body): Abort
+ never needs to be undeferred here.
+ * exp_ch11.adb (Expand_Exception_Handlers): Remove difference
+ between ZCX and SJLJ.
+ * exp_ch9.adb (Expand_N_Asynchronous_Select): Remove different
+ handling for sjlj.
+ * exp_sel.ads, exp_sel.adb (Build_Abort_Block,
+ Build_Abort_Block_Handler): Ditto.
+
+2020-11-27 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): declare new Check_No_Return
+ function and call it.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch12.adb (Instantiate_Object): Consistently use
+ New_Copy_Tree instead of New_Copy.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_fixd.adb (Build_Conversion): Adjust head comment.
+ (Build_Divide): Likewise.
+ (Build_Double_Divide): Likewise.
+ (Build_Multiply): Likewise.
+ (Build_Rem): Likewise.
+ (Build_Scaled_Divide): Likewise.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/s-genbig.ads, libgnat/s-genbig.adb (To_Bignum): New
+ variant taking an Unsigned_128.
+ * libgnat/a-nbnbin.adb (To_Big_Integer): Add support for 128
+ bits signed and unsigned types.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-imagef.adb (Set_Image_Fixed): Pass the full value
+ of the quotient to Set_Image_Integer during the first round and
+ adjust the handling of the minus sign.
+
+2020-11-27 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/a-nbnbre.adb ("=", "<"): Fix.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valuer.adb (Scan_Raw_Real): Move pragma Annotate around
+ and adjust its parameters.
+
+2020-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_fixd.adb (Build_Double_Divide): Use the RM size of types and
+ a more precise estimate for the size of the denominator.
+ (Build_Double_Divide_Code): Likewise.
+ (Build_Multiply): Use a more precise estimate for the size of the
+ result.
+ (Build_Scaled_Divide): Use the RM size of types and a more precise
+ estimate for the size of the numerator.
+ (Build_Scaled_Divide_Code): Likewise.
+
+2020-11-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.rtl <sparc*-sun-solaris*> (THREADSLIB): Remove.
+ (MISCLIB): Remove -lposix4.
+ <*86-*-solaris2*>: Likewise.
+ * libgnarl/s-osinte__solaris.ads (System.OS_Interface): Remove
+ -lposix4 -lthread.
+
+2020-11-26 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/a-nbnbre.adb (To_Big_Real): Do not loose precision.
+
+2020-11-26 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch8.adb (Analyze_Object_Renaming): Check for AI12-0401.
+
+2020-11-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Likewise.
+ (GNATRTL_128BIT_OBJS): Likewise.
+ (GNATRTL_128BIT_PAIRS): Add new 128-bit variants.
+ * cstand.adb (Create_Standard): Create Standard_Integer_128.
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Document
+ new limits on 64-bit platforms in entry for 3.5.9(10).
+ * gnat_rm.texi: Regenerate.
+ * exp_attr.adb: Add with and use clauses for Urealp.
+ (Expand_N_Attribute_Reference) <Attribute_Fore>: Call new routines
+ for decimal fixed-point types and common ordinary fixed-point types.
+ * exp_ch4.adb (Real_Range_Check): Extend conversion trick to all
+ ordinary fixed-point types and use Small_Integer_Type_For.
+ * exp_fixd.adb: Add with and use clauses for Ttypes.
+ (Build_Divide): Add special case for 32-bit values and deal with
+ 128-bit types.
+ (Build_Double_Divide): Deal with 128-bit types.
+ (Build_Double_Divide_Code): Likewise. Do not apply conversions
+ before calling Build_Multiply.
+ (Build_Multiply): Likewise. Add special case for 32-bit values.
+ (Build_Scaled_Divide): Deal with 128-bit types.
+ (Build_Scaled_Divide_Code): Likewise. Fix size computation. Do not
+ apply conversions before calling Build_Multiply.
+ (Do_Multiply_Fixed_Fixed): Minor tweak.
+ (Integer_Literal): Deal with 128-bit values.
+ * exp_imgv.adb (Has_Decimal_Small): Delete.
+ (Expand_Image_Attribute): Call new routines for common ordinary
+ fixed-point types.
+ (Expand_Value_Attribute): Likewise.
+ (Expand_Width_Attribute): Add new expansion for fixed-point types.
+ * freeze.adb (Freeze_Entity): Move error checks for ordinary
+ fixed-point types to...
+ (Freeze_Fixed_Point_Type): ...here. Deal with 128-bit types and
+ adjust limitations for 32-bnt and 64-bit types.
+ * rtsfind.ads (RTU_Id): Add entries for new System_Fore, System_Img,
+ and System_Val units and remove them for obsolete units.
+ (RE_Id): Add entries for Double_Divide128, Scaled_Divide128, the new
+ Fore, Image, Value routines and remove them for obsolete units.
+ (RE_Unit_Table): Likewise.
+ * sem_ch3.adb (Decimal_Fixed_Point_Type_Declaration): Deal with
+ 128-bit types.
+ * stand.ads (Standard_Entity_Type): Add Standard_Integer_128.
+ * uintp.ads (Uint_31): New deferred constant.
+ (Uint_Minus_18): Likewise.
+ (Uint_Minus_31): Likewise.
+ (Uint_Minus_76): Likewise.
+ (Uint_Minus_127): Likewise.
+ * urealp.ads (Ureal_2_31): New function.
+ (Ureal_2_63): Likewise.
+ (Ureal_2_127): Likewise.
+ (Ureal_2_M_127): Likewise.
+ (Ureal_2_10_18): Likewise.
+ (Ureal_M_2_10_18): Likewise.
+ (Ureal_9_10_36): Likewise.
+ (Ureal_M_9_10_36): Likewise.
+ (Ureal_10_76): Likewise.
+ (Ureal_M_10_76): Likewise.
+ (Ureal_10_36): Delete.
+ (Ureal_M_10_36): Likewise.
+ * urealp.adb (UR_2_10_18): New variable.
+ (UR_9_10_36): Likewise.
+ (UR_10_76): Likewise.
+ (UR_M_2_10_18): Likewise.
+ (UR_M_9_10_36): Likewise.
+ (UR_M_10_76): Likewise.
+ (UR_2_31): Likewise.
+ (UR_2_63): Likewise.
+ (UR_2_127): Likewise.
+ (UR_2_M_127): Likewise.
+ (UR_10_36): Delete.
+ (UR_M_10_36): Likewise.
+ (Initialize): Initialize them.
+ (UR_Write): Do not use awkward Ada literal style.
+ (Ureal_2_10_18): New function.
+ (Ureal_9_10_36): Likewise.
+ (Ureal_10_76): Likewise.
+ (Ureal_2_31): Likewise.
+ (Ureal_2_63): Likewise.
+ (Ureal_2_127): Likewise.
+ (Ureal_2_M_127): Likewise.
+ (Ureal_M_2_10_18): Likewise.
+ (Ureal_M_9_10_36): Likewise.
+ (Ureal_10_76): Likewise.
+ (Ureal_M_10_76): Likewise.
+ (Ureal_10_36): Delete.
+ (Ureal_M_10_36): Likewise.
+ * libgnat/a-decima__128.ads: New file.
+ * libgnat/a-tideau.ads, libgnat/a-tideau.adb: Reimplement as
+ generic unit.
+ * libgnat/a-tideio.adb: Reimplement.
+ * libgnat/a-tideio__128.adb: New file.
+ * libgnat/a-tifiau.ads, libgnat/a-tifiau.adb: New generic unit.
+ * libgnat/a-tifiio.adb: Move bulk of implementation to s-imagef
+ and reimplement.
+ * libgnat/a-tifiio__128.adb: New file.
+ * libgnat/a-tiflau.adb (Get): Minor consistency fix.
+ (Gets): Likewise.
+ * libgnat/a-wtdeau.ads, libgnat/a-wtdeau.adb: Reimplement as
+ generic unit.
+ * libgnat/a-wtdeio.adb: Reimplement.
+ * libgnat/a-wtdeio__128.adb: New file.
+ * libgnat/a-wtfiau.ads, libgnat/a-wtfiau.adb: New generic unit.
+ * libgnat/a-wtfiio.adb: Reimplement.
+ * libgnat/a-wtfiio__128.adb: New file.
+ * libgnat/a-ztdeau.ads, libgnat/a-ztdeau.adb: Reimplement as
+ generic unit.
+ * libgnat/a-ztdeio.adb: Reimplement.
+ * libgnat/a-ztdeio__128.adb: New file.
+ * libgnat/a-ztfiau.ads, libgnat/a-ztfiau.adb: New generic unit.
+ * libgnat/a-ztfiio.adb: Reimplement.
+ * libgnat/a-ztfiio__128.adb: New file.
+ * libgnat/g-rannum.adb (Random_Decimal_Fixed): Use a subtype of the
+ appropiate size for the instantiation.
+ (Random_Ordinary_Fixed): Likewise.
+ * libgnat/s-arit32.ads, libgnat/s-arit32.adb: New support unit.
+ * libgnat/s-fode128.ads: New instantiation.
+ * libgnat/s-fode32.ads: Likewise.
+ * libgnat/s-fode64.ads: Likewise.
+ * libgnat/s-fofi128.ads: Likewise.
+ * libgnat/s-fofi32.ads: Likewise.
+ * libgnat/s-fofi64.ads: Likewise.
+ * libgnat/s-fore_d.ads, libgnat/s-fore_d.adb: New generic unit.
+ * libgnat/s-fore_f.ads, libgnat/s-fore_f.adb: Likewise.
+ * libgnat/s-fore.ads, libgnat/s-fore.adb: Rename into...
+ * libgnat/s-forrea.ads, libgnat/s-forrea.adb: ...this.
+ * libgnat/s-imaged.ads, libgnat/s-imaged.adb: New generic unit.
+ * libgnat/s-imagef.ads, libgnat/s-imagef.adb: Likewise, taken
+ from a-tifiio.adb.
+ * libgnat/s-imde128.ads: New instantiation.
+ * libgnat/s-imde32.ads: Likewise.
+ * libgnat/s-imde64.ads: Likewise.
+ * libgnat/s-imfi128.ads: Likewise.
+ * libgnat/s-imfi32.ads: Likewise.
+ * libgnat/s-imfi64.ads: Likewise.
+ * libgnat/s-imgdec.ads, libgnat/s-imgdec.adb: Delete.
+ * libgnat/s-imglld.ads, libgnat/s-imglld.adb: Likewise.
+ * libgnat/s-imgrea.adb (Set_Image_Real): Replace Sign local variable
+ with Minus local variable for the sake of consistency.
+ * libgnat/s-imguti.ads, libgnat/s-imguti.adb: New support unit.
+ * libgnat/s-vade128.ads: New instantiation.
+ * libgnat/s-vade32.ads: Likewise.
+ * libgnat/s-vade64.ads: Likewise.
+ * libgnat/s-vafi128.ads: Likewise.
+ * libgnat/s-vafi32.ads: Likewise.
+ * libgnat/s-vafi64.ads: Likewise.
+ * libgnat/s-valdec.ads, libgnat/s-valdec.adb: Delete.
+ * libgnat/s-vallld.ads, libgnat/s-vallld.adb: Likewise.
+ * libgnat/s-valued.ads, libgnat/s-valued.adb: New generic unit.
+ * libgnat/s-valuef.ads, libgnat/s-valuef.adb: Likewise.
+ * libgnat/s-valuei.adb: Minor rewording.
+ * libgnat/s-valrea.adb: Move bulk of implementation to...
+ * libgnat/s-valuer.ads, libgnat/s-valuer.adb: ...here. New
+ generic unit.
+ * libgnat/system-aix.ads (Max_Mantissa): Adjust.
+ * libgnat/system-darwin-arm.ads (Max_Mantissa): Likewise.
+ * libgnat/system-darwin-ppc.ads (Max_Mantissa): Likewise.
+ * libgnat/system-darwin-x86.ads (Max_Mantissa): Likewise.
+ * libgnat/system-djgpp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-dragonfly-x86_64.ads (Max_Mantissa): Likewise.
+ * libgnat/system-freebsd.ads (Max_Mantissa): Likewise.
+ * libgnat/system-hpux-ia64.ads (Max_Mantissa): Likewise.
+ * libgnat/system-hpux.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-alpha.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-arm.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-hppa.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-ia64.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-m68k.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-mips.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-ppc.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-riscv.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-s390.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-sh4.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-sparc.ads (Max_Mantissa): Likewise.
+ * libgnat/system-linux-x86.ads (Max_Mantissa): Likewise.
+ * libgnat/system-lynxos178-ppc.ads (Max_Mantissa): Likewise.
+ * libgnat/system-lynxos178-x86.ads (Max_Mantissa): Likewise.
+ * libgnat/system-mingw.ads (Max_Mantissa): Likewise.
+ * libgnat/system-qnx-aarch64.ads (Max_Mantissa): Likewise.
+ * libgnat/system-rtems.ads (Max_Mantissa): Likewise.
+ * libgnat/system-solaris-sparc.ads (Max_Mantissa): Likewise.
+ * libgnat/system-solaris-x86.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-arm-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-arm-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-arm.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-e500-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-e500-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-e500-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-e500-vthread.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-ppc-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-ppc-ravenscar.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-ppc-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-ppc-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-ppc-vthread.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-ppc.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-x86-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-x86-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-x86-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-x86-vthread.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks-x86.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-aarch64-rtp-smp.ads (Max_Mantissa):
+ Likewise.
+ * libgnat/system-vxworks7-aarch64.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-arm-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-arm.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-e500-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-e500-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-e500-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-ppc-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-ppc-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-ppc-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-ppc64-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-ppc64-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-x86-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-x86-rtp-smp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-x86-rtp.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-x86_64-kernel.ads (Max_Mantissa): Likewise.
+ * libgnat/system-vxworks7-x86_64-rtp-smp.ads (Max_Mantissa): Likewise.
+
+2020-11-26 Liaiss Merzougue <merzougue@adacore.com>
+
+ * libgnat/s-imgrea.ads (Image_Ordinary_Fixed_Point): Add a
+ remark concerning the irrelevant use of Inf and -0.0
+
+2020-11-26 Arnaud Charlet <charlet@adacore.com>
+
+ * osint-c.adb (Set_Output_Object_File_Name): Add support for
+ .c output file.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * lib-writ.adb, sem_ch8.adb, sem_prag.adb: Use
+ Is_Generic_Subprogram instead of low-level membership tests.
+
+2020-11-26 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch6.adb (Analyze_Call_And_Resolve): Reformatted a comment.
+ * sem_prag.adb (Process_Restrictions_Or_Restriction_Warnings):
+ Fixed a typo.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_res.adb (Resolve_Membership_Op): Replace pragma Warnings
+ with pragma Assert.
+
+2020-11-26 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Call_And_Resolve): Add information to the
+ error message on an illegal procedure call, when the illegality
+ is due to the presence of a component of the full view of the
+ target object, as well as a procedure with the same name (See RM
+ 4.1.3 (9.2/3)).
+
+2020-11-26 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_prag.adb (Process_Restrictions_Or_Restriction_Warnings):
+ when the restriction is a configuration pragma and specifies
+ No_Tasking, a global flag is set to reject task declarations,
+ and to prevent the construction of Master entities. The flag
+ must not be set if the pragma is a Restriction_Warning, in which
+ case task declarationns are allowed.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-stzhas.adb (Wide_Wide_Hash): Instantiate inside a
+ wrapper function.
+ * libgnat/a-stzhas.ads (Wide_Wide_Hash): Likewise; remove wrong
+ comment, because this is indeed a RM unit, as described in Ada
+ RM A.4.8 (1/3).
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_eval.adb (Eval_Slice): Refactor repeated calls to Prefix
+ with a local constant (named just like in Resolve_Slice).
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_eval.adb (Eval_Slice): Emit warning not just for
+ constants, but for any objects.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch4.adb (Indicate_Name_And_Type): Fix whitespace in
+ comment.
+ * sem_res.adb (Resolve_Call): Remove redundant parens.
+ * sem_util.adb (Set_Entity_With_Checks): Remove extra call to
+ Set_Entity.
+
+2020-11-26 Bob Duff <duff@adacore.com>
+
+ * exp_ch4.adb (Expand_Concatenate): Call Set_No_Initialization
+ on the N_Allocator node that is supposed to allocate on the
+ secondary stack.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch13.adb, exp_ch9.adb, sem_ch8.adb, sem_util.adb: Replace
+ a combination of Is_Protected_Type and Is_Task_Type by
+ Is_Concurrent_Type.
+
+2020-11-26 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnarl/s-tassta.adb (Task_Wrapper): Fix computation of
+ Pattern_Size.
+
+2020-11-26 Bob Duff <duff@adacore.com>
+
+ * freeze.adb (Freeze_Array_Type): Remove propagation of
+ Has_Own_Invariants to the first subtype. This is a no-op,
+ because the current (incorrect) version of Has_Own_Invariants
+ calls Base_Type.
+ * sem_prag.adb, sem_util.adb: Pass the base type to
+ Set_Has_Own_Invariants.
+
+2020-11-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * einfo.ads (Aft_Value): Adjust documentation.
+ (Scale_Value): Likewise.
+
+2020-11-26 Justin Squirek <squirek@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Type_Conversion): Use the unexpanded
+ operand when generating accessibility checks.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-cbhase.adb (Read): Remove extra whitespace.
+ * libgnat/a-cbmutr.ads (Read): Likewise.
+ * libgnat/a-cborse.adb (Read): Likewise.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch7.adb, exp_util.adb, freeze.adb: Rewrite with
+ Is_Access_Object_Type.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Check_Valid_Library_Unit_Pragma): Raise
+ exception.
+ (Analyze_Pragma): Remove detection of rewritten pragmas.
+
+2020-11-26 Joffrey Huguet <huguet@adacore.com>
+
+ * libgnat/a-strmap.ads: Add preconditions and postconditions to
+ all subprograms.
+
+2020-11-26 Yannick Moy <moy@adacore.com>
+
+ * sem_res.adb (Resolve_Equality_Op): Warn when -gnatwq is used
+ (the default) and the problematic case is encountered.
+
+2020-11-26 Yannick Moy <moy@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute): Issue a continuation message
+ to give proper recommendation here.
+
+2020-11-26 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_util.adb (Expand_Subtype_From_Expr): A typo correction,
+ plus other minor reformatting.
+
+2020-11-26 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Instantiate_Formal_Package): If previous matched
+ entity is overloadable, advance in the list of actuals of the
+ actual package, to prevent an erroneous match of two adjacent
+ overloadable homonyms with the same entity.
+
+2020-11-26 Justin Squirek <squirek@adacore.com>
+
+ * sem_ch6.adb (First_Selector): Utility routine to return the
+ first selector or choice in an association.
+ (Check_Return_Construct_Accessibility): Modify loop to handle
+ named associations when iterating through discriminants.
+
+2020-11-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch12.adb: Fix casing from "Instantiation" to
+ "instantiation".
+
+2020-11-25 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb (Is_Uninitialized_Aggregate): Move...
+ * exp_util.adb (Is_Uninitialized_Aggregate): ... here.
+ (Expand_Subtype_From_Expr): If the expression is an
+ uninitialized aggregate, capture subtype for declared object and
+ remove expression to suppress further superfluous expansion.
+
+2020-11-25 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_eval.adb (Subtypes_Statically_Compatible): Scalar types
+ with compatible static bounds are statically compatible if
+ predicates are compatible, even if they are not static subtypes.
+ Same for private types without discriminants.
+
+2020-11-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch11.adb (Expand_N_Raise_Statement): Use Is_Entity_Name
+ consistently in tests on the name of the statement.
+ * exp_prag.adb (Expand_Pragma_Check): In the local propagation
+ case, wrap the raise statement in a block statement.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch8.adb (Expand_N_Exception_Renaming_Declaration): Move
+ "Nam" constant after the body of a nested subprogram; change "T"
+ from variable to constant.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * make.adb (Scan_Make_Arg): Merge ELSIF branches for -u and -U.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_attributes.rst
+ (Has_Tagged_Values): Document based on the existing description
+ of Has_Access_Type and the comment for Has_Tagged_Component,
+ which is where frontend evaluates this attribute.
+ * gnat_rm.texi: Regenerate.
+ * sem_attr.adb (Analyze_Attribute): Merge processing of
+ Has_Access_Type and Has_Tagged_Component attributes.
+ * sem_util.adb (Has_Access_Type): Fix casing in comment.
+ * sem_util.ads (Has_Tagged_Component): Remove wrong (or
+ outdated) comment about the use of this routine to implement the
+ equality operator.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb (Expand_Size_Attribute): Remove whitespace;
+ simplify with a membership test, which are now allowed in the
+ frontend code.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Analyze_One_Aspect): Fix inconsistent calls to
+ Make_Aitem_Pragma.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Check_Expr_Constants): Simplify with
+ Is_Named_Number.
+ * sem_prag.adb (Process_Convention): Likewise.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Analyze_One_Aspect): Detect aspect identifiers
+ with membership tests.
+ (Check_Aspect_At_End_Of_Declarations): Likewise.
+ (Freeze_Entity_Checks): Likewise; a local constant is no longer
+ needed.
+ (Is_Operational_Item): Similar simplification for attribute
+ identifiers.
+ (Is_Type_Related_Rep_Item): Likewise.
+ (Resolve_Iterable_Operation): Detect names with a membership
+ test.
+ (Validate_Independence): Replace repeated Ekind with a
+ membership test.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch13.adb (Analyze_One_Aspect): Replace duplicate of
+ Effective_Reads.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * einfo.adb: Use composite wrappers (e.g.
+ Is_Subprogram_Or_Entry) and membership tests where it appears to
+ improve clarity.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * einfo.adb (Is_Standard_Character_Type,
+ Is_Standard_String_Type): Simplify.
+ (Last_Formal): Use procedural variant of Next_Formal.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * einfo.adb: Replace "E" with Entity_Id in local object
+ declarations.
+
+2020-11-25 Steve Baird <baird@adacore.com>
+
+ * exp_ch2.adb (Expand_Entity_Reference): A new local predicate
+ Is_Object_Renaming_Name indicates whether a given expression
+ occurs (after looking through qualified expressions and type
+ conversions) as the name of an object renaming declaration. If
+ Current_Value is available but this new predicate is True, then
+ ignore the availability of Current_Value.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch12.adb (Instantiate_Type): Remove extra whitespace.
+ (Validate_Access_Type_Instance): Remove dead (and duplicated)
+ code.
+
+2020-11-25 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_util.adb (Possible_Side_Effect_In_SPARK): Replace hyphen
+ with a space in "side-effect" (two instances).
+
+2020-11-25 Justin Squirek <squirek@adacore.com>
+
+ * doc/gnat_rm/intrinsic_subprograms.rst (Shifts and Rotates):
+ Document behavior on negative numbers
+ * gnat_rm.texi: Regenerate.
+ * sem_eval.adb (Fold_Shift): Set modulus to be based on the RM
+ size for non-modular integer types.
+
+2020-11-25 Olivier Hainque <hainque@adacore.com>
+
+ * adaint.c (__gnat_copy_attribs): Reinstate code based on utime
+ for timestamp processing on VxWorks 6.
+
+2020-11-25 Yannick Moy <moy@adacore.com>
+
+ * exp_util.adb (Remove_Side_Effects): Only remove side-effects
+ in GNATprove mode when this is useful.
+ * sem_res.adb (Set_Slice_Subtype): Make sure in GNATprove mode
+ to define the Itype when needed, so that run-time errors can be
+ analyzed.
+ * sem_util.adb (Enclosing_Declaration): Correctly take into
+ account renaming declarations.
+
+2020-11-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-rannum.adb (Random_Discrete): Specifically deal with
+ the case where the size of the base type is larger than 64 bits.
+
+2020-11-25 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb (Access_Type_Declaration): Set Etype before
+ checking for volatility compatibility.
+
+2020-11-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/g-rannum.ads (Random): New functions returning 128-bit.
+ * libgnat/g-rannum.adb (Random): Implement them and alphabetize.
+ (To_Signed): New unchecked conversion function for 128-bit.
+
+2020-11-25 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch7.adb (Build_Finalization_Master, Build_Finalizer,
+ Build_Object_Declarations, Make_Deep_Array_Body,
+ Wrap_Transient_Expression): Call Set_Debug_Info_Needed on
+ temporaries when Debug_Generated_Code is True.
+
+2020-11-25 Liaiss Merzougue <merzougue@adacore.com>
+
+ * libgnat/s-imagei.adb
+ (Set_Digits): Rewrite the procedure to remove recursion.
+ (Image_Integer, Set_Image_Integer): Update assertions and remove
+ redundant ones.
+ * libgnat/s-imageu.adb
+ (Set_Image_Unsigned): Rewrite the procedure to remove recursion.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_util.adb (Attribute_Constrained_Static_Value): Fix body
+ box.
+ * sem_attr.adb (Eval_Attribute): Replace repeated calls to
+ Attribute_Name with a captured value of the Attribute_Id; also,
+ remove extra parens around Is_Generic_Type.
+
+2020-11-25 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Emit error on wrong argument
+ nkind.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb, sem_prag.adb: Use Is_Named_Number.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb, exp_util.adb: Fix style and typos in comments.
+
+2020-11-25 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference): A variable that
+ is only incremented in the code has now type Nat; conversion is
+ now unnecessary.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Analyze_Global_Item): Call SPARK_Msg_NE with the
+ entity, not with its identifier.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * opt.ads (Generate_Asm): New flag.
+ * osint-c.adb (Set_Output_Object_File_Name): Accept any
+ extension when generating assembly.
+ * adabkend.adb (Scan_Compiler_Args): Recognize -S.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb, exp_ch4.adb, exp_intr.adb, sem_ch8.adb,
+ sem_res.adb, sem_type.adb, sem_util.adb: Reuse Is_Packed_Array.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * checks.adb (Apply_Access_Check): Remove unbalanced paren.
+ * exp_attr.adb (Expand_N_Attribute_Reference): Fix typo in
+ comment.
+
+2020-11-24 Justin Squirek <squirek@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Mark relevant pragmas as ghost
+ when they are within a ghost region.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * contracts.adb, freeze.adb, sem_ch12.adb, sem_prag.adb: Reuse
+ In_Same_List.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_prag.adb (Is_Loop_Pragma): Avoid repeated calls to
+ Original_Node; remove unnecessary IF statement.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Rewrite
+ with a CASE statement.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference): Replace calls to
+ Sloc with a local constant Loc; remove call to
+ Analyze_And_Resolve and return, which is exactly what happens
+ anyway (and other branches in the Constrained declare block
+ appear to rely on analysis, resolution and returning happening
+ in all cases).
+ * sem_util.adb: Remove useless parens.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_util.adb (Is_Object_Reference): Delta and extension
+ aggregates are objects.
+
+2020-11-24 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * libgnat/s-rident.ads (System.Rident): Register new restriction
+ IDs.
+ * par-ch13.adb (Get_Aspect_Specifications): Add restriction check.
+ * par-prag.adb (Process_Restrictions_Or_Restriction_Warnings):
+ Register No_Unrecognized_Aspects restriction.
+ * sem_prag.adb (Analyze_Pragma): Add restriction check.
+ * snames.ads-tmpl: Create restriction names.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_attr.adb (Declared_Within): Return True for objects
+ declared within the attribute Loop_Entry prefix itself.
+
+2020-11-24 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb (Process_Discriminants): Correctly set right
+ context for analyzing default value of discriminant.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_type.adb (Add_One_Interp.Is_Universal_Operation): Account
+ for universal_access = operator.
+ (Disambiguate): Take into account preference on universal_access
+ = operator when relevant.
+ (Disambiguate.Is_User_Defined_Anonymous_Access_Equality): New.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_util.adb (Is_Finalizable_Transient): Take into account return
+ statements containing N_Expression_With_Actions. Also clean up a
+ condition to make it more readable.
+ * exp_ch6.adb: Fix typo.
+
+2020-11-24 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-wtdeio.adb (TFT): Delete and adjust throughout.
+ * libgnat/a-wtenau.adb (TFT): Likewise.
+ * libgnat/a-wtfiio.adb (TFT): Likewise.
+ * libgnat/a-wtflio.adb (TFT): Likewise.
+ * libgnat/a-wtinio.adb (TFT): Likewise.
+ * libgnat/a-wtinio__128.adb (TFT): Likewise.
+ * libgnat/a-wtmoio.adb (TFT): Likewise.
+ * libgnat/a-wtmoio__128.adb (TFT): Likewise.
+ * libgnat/a-ztdeio.adb (TFT): Likewise.
+ * libgnat/a-ztenau.adb (TFT): Likewise.
+ * libgnat/a-ztfiio.adb (TFT): Likewise.
+ * libgnat/a-ztflio.adb (TFT): Likewise.
+ * libgnat/a-ztinio.adb (TFT): Likewise.
+ * libgnat/a-ztinio__128.adb (TFT): Likewise.
+ * libgnat/a-ztmoio.adb (TFT): Likewise.
+ * libgnat/a-ztmoio__128.adb (TFT): Likewise.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch13.adb (Validate_Literal_Aspect): Add support for named
+ numbers and in particular overload of the Real_Literal function.
+ * sem_res.adb (Resolve): Add support for named numbers in
+ Real_Literal and Integer_Literal resolution.
+ * einfo.adb, einfo.ads (Related_Expression,
+ Set_Related_Expression): Allow E_Function.
+ * uintp.ads (UI_Image_Max): Bump size of buffer to avoid loosing
+ precision.
+ * sem_eval.adb: Fix typo in comment.
+ * libgnat/a-nbnbin.adb, libgnat/a-nbnbin.ads (From_String):
+ Return a Valid_Big_Integer.
+ * libgnat/a-nbnbre.adb, libgnat/a-nbnbre.ads (From_String): New
+ variant taking two strings. Return a Valid_Big_Real.
+
+2020-11-24 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_ch12.adb (Analyze_Associations) <Explicit_Freeze_Check>: Test
+ that the instance is in a statement sequence instead of local scope.
+ (Freeze_Subprogram_Body): Use the special delayed placement with
+ regard to the parent instance only if its Sloc is strictly greater.
+ (Install_Body): Likewise.
+
+2020-11-24 Steve Baird <baird@adacore.com>
+
+ * sem_ch13.adb (Validate_Literal_Aspect): Call to Base_Type
+ needed in order to correctly check result type of String_Literal
+ function when the first named subtype differs from the base
+ type (e.g.:
+ type T is range 1 .. 10 with String_Literal => ... ;
+ ).
+
+2020-11-24 Yannick Moy <moy@adacore.com>
+
+ * sem_prag.adb (Analyze_Global_Item): Handle specially the
+ current instance of a PO.
+ * sem_util.ads (Is_Effectively_Volatile,
+ Is_Effectively_Volatile_For_Reading): Add parameter
+ Ignore_Protected.
+ * sem_util.adb (Is_Effectively_Volatile,
+ Is_Effectively_Volatile_For_Reading): Add parameter
+ Ignore_Protected to compute the query results ignoring protected
+ objects/types.
+ (Is_Effectively_Volatile_Object,
+ Is_Effectively_Volatile_Object_For_Reading): Adapt to new
+ signature.
+
+2020-11-24 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
+ Update documentation on -gnatyk.
+ * gnat_ugn.texi: Regenerate.
+
+2020-11-24 Yannick Moy <moy@adacore.com>
+
+ * sem_ch10.adb (Analyze_Compilation_Unit): Move aspects from
+ body to the newly created spec.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch6.adb (Add_Cond_Expression_Extra_Actual): Simplify
+ handling of function calls and remove bug in handling of
+ transient objects. Minor reformatting along the way.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/a-nbnbin.adb (From_String): Implement fully.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_aggr.adb (Resolve_Delta_Array_Aggregate): If the choice is
+ a subtype_indication then call
+ Resolve_Discrete_Subtype_Indication; both for choices
+ immediately inside array delta aggregates and inside
+ iterated_component_association within array delta aggregates.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * lib-load.adb, lib-writ.adb, lib.adb, par-load.adb,
+ rtsfind.adb, sem_ch10.adb: Use Present where possible.
+
+2020-11-24 Yannick Moy <moy@adacore.com>
+
+ * sem_prag.adb (Analyze_Depends_Global): Reject Global and
+ Depends on null procedure.
+
+2020-11-24 Arnaud Charlet <charlet@adacore.com>
+
+ * libgnat/a-nbnbre.adb (From_String): Handle properly '_'
+ characters.
+
+2020-11-24 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_Array_Aggregate,
+ Expand_SPARK_N_Aggregate): Remove, no longer needed.
+ * sem_aggr.adb (Resolve_Iterated_Component_Association): Only
+ remove references in the analyzed expression when generating
+ code and the expression needs to be analyzed anew after being
+ rewritten into a loop.
+
+2020-11-24 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Complete
+ entry of 3.5.9(10).
+ * gnat_rm.texi: Regenerate.
+
+2020-11-20 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * adaint.c (__gnat_number_of_cpus): Check for the presence of
+ _SC_NPROCESSORS_ONLN rather than a list of OS-specific macros
+ to decide whether to use `sysconf'.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * gcc-interface/Make-lang.in (ada.serial): Change from goal to a
+ variable.
+ (.PHONY): Drop ada.serial and ada.prev.
+ (gnat1$(exeext)): Depend on $(ada.serial) rather than ada.serial.
+
+2020-11-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/97805
+ * adaint.c: Include climits in C++ and limits.h otherwise.
+
+2020-11-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_dbug.adb (Is_Handled_Scale_Factor): Delete.
+ (Get_Encoded_Name): Do not call it.
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <Fixed_Point_Type>:
+ Tidy up and always use a meaningful description for arbitrary
+ scale factors.
+ * gcc-interface/misc.c (gnat_get_fixed_point_type_info): Remove
+ obsolete block and adjust the description of the scale factor.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc-interface/Make-lang.in (ada.serial): New goal.
+ (.PHONY): Add ada.serial ada.prev.
+ (gnat1$(exeext)): Depend on ada.prev. Call LINK_PROGRESS.
+
+2020-11-18 Matthias Klose <doko@ubuntu.com>
+
+ PR ada/97859
+ * Makefile.rtl (powerpc% linux%): Also match powerpc64le cpu.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/gigi.h: Remove ^L characters throughout.
+ * gcc-interface/decl.c: Likewise.
+ * gcc-interface/utils.c: Likewise.
+ * gcc-interface/utils2.c: Likewise.
+ * gcc-interface/trans.c (gnat_to_gnu) <N_Allocator>: Do not explicitly
+ go to the base type for the Has_Constrained_Partial_View flag.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (build_binary_op_trapv): Convert operands
+ to the result type before doing generic overflow checking.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (can_be_lower_p): Remove.
+ (Regular_Loop_to_gnu): Add ENTRY_COND unconditionally if
+ BOTTOM_COND is non-zero.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Constant>: In case
+ the constant is not being defined, get the expression in type
+ annotation mode only if its type is elementary.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gnat_to_gnu) <N_Op_Shift>: Also convert
+ GNU_MAX_SHIFT if the type of the operation has been changed.
+ * gcc-interface/utils.c (can_materialize_object_renaming_p): Add
+ pair of missing parentheses.
+
+2020-11-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Makefile.in: Force target_cpu to powerpc if the
+ nominal target is powerpc64-suse-linux.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc-interface/misc.c (gnat_printable_name): Change
+ DECL_IS_BUILTIN -> DECL_IS_UNDECLARED_BUILTIN.
+
+2020-10-28 Alexandre Oliva <oliva@adacore.com>
+
+ PR ada/97504
+ * Makefile.rtl (LIBGNAT_TARGET_PAIRS> <riscv*-*-*>: Use wraplf
+ version of Aux_Long_Long_Float.
+
+2020-10-27 Doug Rupp <rupp@adacore.com>
+
+ * Makefile.rtl: Add vx7r2cert spec file to ARM, PowerPC and x86
+ targets.
+ * vxworks7-cert-rtp-link.spec: New spec file.
+
+2020-10-27 Arnaud Charlet <charlet@adacore.com>
+
+ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add g-spogwa object.
+ * libgnat/g-spogwa.adb: Fix style errors.
+
+2020-10-27 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_Array_Aggregate): Dedicated
+ routine for array aggregates; mostly reuses existing code, but
+ calls itself recursively for multi-dimensional array aggregates.
+ (Expand_SPARK_N_Aggregate): Call Expand_SPARK_Array_Aggregate to
+ do the actual expansion, starting from the first index of the
+ array type.
+
+2020-10-27 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aggr.adb (Resolve_Iterated_Component_Association): new
+ internal subprogram Remove_References, to reset semantic
+ information on each reference to the index variable of the
+ association, so that Collect_Aggregate_Bounds can work properly
+ on multidimensional arrays with nested associations, and
+ subsequent expansion into loops can verify that dimensions of
+ each subaggregate are compatible.
+
+2020-10-27 Ghjuvan Lacambre <lacambre@adacore.com>
+
+ * exp_prag.adb (Append_Copies): Handle N_Parameter_Associations.
+
+2020-10-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * ada_get_targ.adb (Digits_From_Size): Delete.
+ (Width_From_Size): Likewise.
+ * get_targ.adb (Digits_From_Size): Likewise.
+ (Width_From_Size): Likewise.
+ * get_targ.ads (Digits_From_Size): Likewise.
+ (Width_From_Size): Likewise.
+ * ttypes.ads: Remove with clause for Get_Targ.
+ (Standard_Short_Short_Integer_Width): Delete.
+ (Standard_Short_Integer_Width): Likewise.
+ (Standard_Integer_Width): Likewise.
+ (Standard_Long_Integer_Width): Likewise.
+ (Standard_Long_Long_Integer_Width): Likewise.
+ (Standard_Long_Long_Long_Integer_Width): Likewise.
+ (Standard_Short_Float_Digits): Likewise.
+ (Standard_Float_Digits): Likewise.
+ (Standard_Long_Float_Digits): Likewise.
+ (Standard_Long_Long_Float_Digits): Likewise.
+ * gnat1drv.adb (Adjust_Global_Switches): Adjust.
+
+2020-10-27 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch6.adb, freeze.adb, gnat1drv.adb, opt.ads, sem_ch6.adb
+ (Transform_Function_Array): New flag, split from Modify_Tree_For_C.
+ * exp_unst.adb: Minor reformatting.
+
+2020-10-27 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * libgnat/g-socpol.adb (Wait): Do not exit from loop on EINTR
+ error and timeout is over.
+
+2020-10-26 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Build_Array_Aggr_Code): If the aggregate
+ includes an Others_Choice in an association that is an
+ Iterated_Component_Association, generate a proper loop for it.
+
+2020-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb: Add missing sign in documentation.
+ * libgnat/s-imgrea.ads: Minor fixes in commentary.
+
+2020-10-26 Pat Rogers <rogers@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_pragmas.rst: Include
+ "Jorvik" in pragma Profile description.
+ * gnat_rm.texi: Regenerate.
+
+2020-10-26 Bob Duff <duff@adacore.com>
+
+ * sem_attr.adb (Check_Image_Type): Remove "|", so the compiler
+ will not crash.
+ * errout.ads: Improve comment. This has nothing to do with
+ -gnatQ.
+
+2020-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb: Minor editions to documentation.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * contracts.adb (Causes_Contract_Freezing): Extend condition to
+ match the one in Analyze_Subprogram_Body_Helper. This routine is
+ used both as an assertion at the very start of
+ Freeze_Previous_Contracts and to detect previous declaration for
+ which Freeze_Previous_Contracts has been executed.
+
+2020-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb: Move around documentaton paragraph.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * inline.adb (Establish_Actual_Mapping_For_Inlined_Call): Add
+ guard for a call to Set_Last_Assignment with the same condition
+ as the assertion in that routine and explain why this guard
+ fails in GNATprove mode.
+
+2020-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst: Adjust
+ the entries of 3.5.9(8) and 3.5.9(10).
+ * gnat_rm.texi: Regenerate.
+
+2020-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb: Change the range of supported Small
+ values.
+ (E0, E1, E2): Adjust factors.
+ (Exact): Return false if the Small does not fit in 64 bits.
+
+2020-10-26 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * libgnat/g-socket.adb (Wait_On_Socket): Boolean parameter
+ For_Read changed to Event parameter of type
+ GNAT.Sockets.Poll.Wait_Event_Set. Implementation is simplified
+ and based on call to GNAT.Sockets.Poll.Wait now.
+
+2020-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/a-tifiio.adb: Minor editions to documentation.
+
+2020-10-26 Yannick Moy <moy@adacore.com>
+
+ * sem_ch12.adb (Restore_Private_Views): Do not lose the
+ information provided by Is_Generic_Actual_Type in GNATprove
+ mode.
+
+2020-10-26 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_warn.adb (Warn_On_Unreferenced_Entity): Suppress warning
+ on formal parameters of all dispatching operations.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_aggr.adb (Resolve_Delta_Array_Aggregate): Fix typos in
+ error message.
+
+2020-10-26 Olivier Hainque <hainque@adacore.com>
+
+ * libgnat/s-dwalin.adb (Symbolic_Traceback): Always emit the hex
+ address at the beginning of an entry if suppression is not
+ requested. Consistently output a "???" for the subprogram name
+ when it is unknown.
+
+2020-10-26 Doug Rupp <rupp@adacore.com>
+
+ * s-oscons-tmplt.c (_nfds_t): Use sizeof (unsigned long int).
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch4.adb (P_Iterated_Component_Association): Move code for
+ iterated_element_association to
+ Build_Iterated_Element_Association.
+
+2020-10-26 Yannick Moy <moy@adacore.com>
+
+ * sem_ch12.adb (Needs_Body_Instantiated): In GNATprove mode, do
+ not instantiate bodies outside of the main unit.
+
+2020-10-26 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aggr.adb (Resolve_Delta_Array_Aggregate): For an
+ association that is an iterated component association, attach
+ the copy of the expression to the tree prior to analysis, in
+ order to preserve its context. This is needed when verifying
+ static semantic rules that depend on context, for example that a
+ use of 'Old appears only within a postcondition.
+
+2020-10-26 Bob Duff <duff@adacore.com>
+
+ * doc/gnat_ugn/gnat_utility_programs.rst: Document that
+ --no-comments-fill is now the default.
+
+2020-10-26 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_aggr.adb (Resolve_Extension_Aggregate): When testing for
+ an aggregate that is illegal due to having an ancestor type that
+ has unknown discriminants, add an "or else" condition testing
+ whether the aggregate type has unknown discriminants and that
+ Partial_View_Has_Unknown_Discr is also set on the ancestor type.
+ Extend the comment, including adding ??? about a possible
+ simpler test.
+
+2020-10-26 Bob Duff <duff@adacore.com>
+
+ * libgnat/a-cihama.adb, libgnat/a-cohama.adb,
+ libgnat/a-cohase.adb (Delete): Set Position.Position, and
+ assert.
+
+2020-10-26 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch8.adb (Find_Direct_Name.Undefined): Handle known unit
+ names with 3 selectors.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_Delta_Or_Update): Add missing call
+ to Enter_Name, just like it is called for
+ iterated_component_association in Expand_SPARK_N_Aggregate.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_Delta_Or_Update): Reuse local
+ constant Expr and the Choice_List routine.
+ (Expand_SPARK_N_Aggregate): Reuse local constant Expr.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * par-ch4.adb (P_Iterated_Component_Association): Fix typos in
+ comments.
+
+2020-10-26 Arnaud Charlet <charlet@adacore.com>
+
+ * par-ch6.adb (P_Formal_Part): Ada 2020 supports scanning
+ aspects on formal parameters.
+ * doc/gnat_rm/implementation_defined_aspects.rst (Aspect
+ Unreferenced): Update documentation.
+ * gnat_rm.texi: Regenerate.
+
+2020-10-26 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb (Freeze_Type_Refs): When an entity in an expression
+ function is a type, freeze the entity and not just its type,
+ which would be incomplete when the type is derived and/or
+ tagged.
+
+2020-10-26 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb (Expand_Update_Attribute): Handle
+ subtype_indication just like in Expand_Delta_Array_Aggregate.
+
+2020-10-25 Iain Sandoe <iain@sandoe.co.uk>
+
+ * Makefile.rtl: Add GNATRTL_128BIT_PAIRS/OBJS for 64bit
+ PowerPC Darwin cases.
+
2020-10-23 Iain Sandoe <iain@sandoe.co.uk>
* adaint.c: On Darwin platforms, define st_atim to
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 7b5b334..81df1e8 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -344,6 +344,7 @@ GNATRTL_NONTASKING_OBJS= \
a-tideio$(objext) \
a-tienau$(objext) \
a-tienio$(objext) \
+ a-tifiau$(objext) \
a-tifiio$(objext) \
a-tiflau$(objext) \
a-tiflio$(objext) \
@@ -371,6 +372,7 @@ GNATRTL_NONTASKING_OBJS= \
a-wtedit$(objext) \
a-wtenau$(objext) \
a-wtenio$(objext) \
+ a-wtfiau$(objext) \
a-wtfiio$(objext) \
a-wtflau$(objext) \
a-wtflio$(objext) \
@@ -394,6 +396,7 @@ GNATRTL_NONTASKING_OBJS= \
a-ztenau$(objext) \
a-ztenio$(objext) \
a-ztexio$(objext) \
+ a-ztfiau$(objext) \
a-ztfiio$(objext) \
a-ztflau$(objext) \
a-ztflio$(objext) \
@@ -483,6 +486,7 @@ GNATRTL_NONTASKING_OBJS= \
g-speche$(objext) \
g-spipat$(objext) \
g-spitbo$(objext) \
+ g-spogwa$(objext) \
g-sptabo$(objext) \
g-sptain$(objext) \
g-sptavs$(objext) \
@@ -519,6 +523,7 @@ GNATRTL_NONTASKING_OBJS= \
s-aomoar$(objext) \
s-aotase$(objext) \
s-aridou$(objext) \
+ s-arit32$(objext) \
s-arit64$(objext) \
s-assert$(objext) \
s-atacco$(objext) \
@@ -591,37 +596,47 @@ GNATRTL_NONTASKING_OBJS= \
s-fatgen$(objext) \
s-fatlfl$(objext) \
s-fatllf$(objext) \
- s-fatsfl$(objext) \
s-ficobl$(objext) \
s-filatt$(objext) \
s-fileio$(objext) \
s-finmas$(objext) \
s-finroo$(objext) \
s-flocon$(objext) \
- s-fore$(objext) \
+ s-fode32$(objext) \
+ s-fode64$(objext) \
+ s-fofi32$(objext) \
+ s-fofi64$(objext) \
+ s-fore_d$(objext) \
+ s-fore_f$(objext) \
+ s-forrea$(objext) \
s-gearop$(objext) \
s-genbig$(objext) \
s-geveop$(objext) \
s-gloloc$(objext) \
s-htable$(objext) \
s-imageb$(objext) \
+ s-imaged$(objext) \
+ s-imagef$(objext) \
s-imagei$(objext) \
s-imageu$(objext) \
s-imagew$(objext) \
+ s-imde32$(objext) \
+ s-imde64$(objext) \
s-imenne$(objext) \
+ s-imfi32$(objext) \
+ s-imfi64$(objext) \
s-imgbiu$(objext) \
s-imgboo$(objext) \
s-imgcha$(objext) \
- s-imgdec$(objext) \
s-imgenu$(objext) \
s-imgint$(objext) \
s-imgllb$(objext) \
- s-imglld$(objext) \
s-imglli$(objext) \
s-imgllu$(objext) \
s-imgllw$(objext) \
s-imgrea$(objext) \
s-imguns$(objext) \
+ s-imguti$(objext) \
s-imgwch$(objext) \
s-imgwiu$(objext) \
s-io$(objext) \
@@ -697,7 +712,9 @@ GNATRTL_NONTASKING_OBJS= \
s-pooglo$(objext) \
s-pooloc$(objext) \
s-poosiz$(objext) \
- s-powtab$(objext) \
+ s-powflt$(objext) \
+ s-powlfl$(objext) \
+ s-powllf$(objext) \
s-purexc$(objext) \
s-putima$(objext) \
s-rannum$(objext) \
@@ -735,14 +752,22 @@ GNATRTL_NONTASKING_OBJS= \
s-utf_32$(objext) \
s-valboo$(objext) \
s-valcha$(objext) \
- s-valdec$(objext) \
+ s-vade32$(objext) \
+ s-vade64$(objext) \
+ s-vafi32$(objext) \
+ s-vafi64$(objext) \
s-valenu$(objext) \
+ s-valflt$(objext) \
s-valint$(objext) \
- s-vallld$(objext) \
+ s-vallfl$(objext) \
+ s-valllf$(objext) \
s-vallli$(objext) \
s-valllu$(objext) \
s-valrea$(objext) \
+ s-valued$(objext) \
+ s-valuef$(objext) \
s-valuei$(objext) \
+ s-valuer$(objext) \
s-valueu$(objext) \
s-valuns$(objext) \
s-valuti$(objext) \
@@ -884,10 +909,17 @@ TRASYM_DWARF_UNIX_OBJS = $(TRASYM_DWARF_COMMON_OBJS) s-mmauni$(objext)
TRASYM_DWARF_MINGW_OBJS = $(TRASYM_DWARF_COMMON_OBJS)
GNATRTL_128BIT_PAIRS = \
+ a-decima.ads<libgnat/a-decima__128.ads \
+ a-tideio.adb<libgnat/a-tideio__128.adb \
+ a-tifiio.adb<libgnat/a-tifiio__128.adb \
a-tiinio.adb<libgnat/a-tiinio__128.adb \
a-timoio.adb<libgnat/a-timoio__128.adb \
+ a-wtdeio.adb<libgnat/a-wtdeio__128.adb \
+ a-wtfiio.adb<libgnat/a-wtfiio__128.adb \
a-wtinio.adb<libgnat/a-wtinio__128.adb \
a-wtmoio.adb<libgnat/a-wtmoio__128.adb \
+ a-ztdeio.adb<libgnat/a-ztdeio__128.adb \
+ a-ztfiio.adb<libgnat/a-ztfiio__128.adb \
a-ztinio.adb<libgnat/a-ztinio__128.adb \
a-ztmoio.adb<libgnat/a-ztmoio__128.adb \
i-cexten.ads<libgnat/i-cexten__128.ads \
@@ -902,6 +934,10 @@ GNATRTL_128BIT_OBJS = \
s-exnllli$(objext) \
s-expllli$(objext) \
s-explllu$(objext) \
+ s-fode128$(objext) \
+ s-fofi128$(objext) \
+ s-imde128$(objext) \
+ s-imfi128$(objext) \
s-imglllb$(objext) \
s-imgllli$(objext) \
s-imglllu$(objext) \
@@ -969,6 +1005,8 @@ GNATRTL_128BIT_OBJS = \
s-pack125$(objext) \
s-pack126$(objext) \
s-pack127$(objext) \
+ s-vade128$(objext) \
+ s-vafi128$(objext) \
s-valllli$(objext) \
s-vallllu$(objext) \
s-widllli$(objext) \
@@ -1135,6 +1173,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe
else
GCC_SPEC_FILES+=vxworks7-rtp-base-link.spec
endif
+ GCC_SPEC_FILES+=vxworks7-cert-rtp-link.spec
else
GCC_SPEC_FILES+=vxworks-$(ARCH_STR)-link.spec
GCC_SPEC_FILES+=vxworks-cert-$(ARCH_STR)-link.spec
@@ -1410,6 +1449,7 @@ ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7%,$(target_cpu) $(targ
ifeq ($(strip $(filter-out vxworks7%, $(target_os))),)
GCC_SPEC_FILES+=vxworks7-$(X86CPU)-rtp-base-link.spec
+ GCC_SPEC_FILES+=vxworks7-cert-rtp-link.spec
else
GCC_SPEC_FILES+=vxworks-x86-link.spec
GCC_SPEC_FILES+=vxworks-cert-x86-link.spec
@@ -1533,6 +1573,9 @@ ifeq ($(strip $(filter-out aarch64 arm% coff wrs vx%,$(target_cpu) $(target_vend
GCC_SPEC_FILES+=vxworks-smp-arm-link.spec
endif
endif
+ ifeq ($(strip $(filter-out vxworks7%, $(target_os))),)
+ GCC_SPEC_FILES+=vxworks7-cert-rtp-link.spec
+ endif
endif
# ARM android
@@ -1635,8 +1678,7 @@ ifeq ($(strip $(filter-out sparc% sun solaris%,$(target_cpu) $(target_vendor) $(
endif
EH_MECHANISM=-gcc
- THREADSLIB = -lposix4 -lthread
- MISCLIB = -lposix4 -lnsl -lsocket
+ MISCLIB = -lnsl -lsocket
SO_OPTS = -Wl,-h,
GNATLIB_SHARED = gnatlib-shared-dual
GMEM_LIB = gmemlib
@@ -1689,8 +1731,7 @@ ifeq ($(strip $(filter-out %86 %x86_64 solaris2%,$(target_cpu) $(target_os))),)
EXTRA_GNATRTL_NONTASKING_OBJS += $(TRASYM_DWARF_UNIX_OBJS)
EH_MECHANISM=-gcc
- THREADSLIB = -lposix4 -lthread
- MISCLIB = -lposix4 -lnsl -lsocket
+ MISCLIB = -lnsl -lsocket
SO_OPTS = -Wl,-h,
GNATLIB_SHARED = gnatlib-shared-dual
GMEM_LIB = gmemlib
@@ -2000,6 +2041,7 @@ ifeq ($(strip $(filter-out hppa% hp hpux10%,$(target_cpu) $(target_vendor) $(tar
s-inmaop.adb<libgnarl/s-inmaop__posix.adb \
s-interr.adb<libgnarl/s-interr__sigaction.adb \
s-intman.adb<libgnarl/s-intman__posix.adb \
+ a-nallfl.ads<libgnat/a-nallfl__wraplf.ads \
s-osinte.adb<libgnarl/s-osinte__hpux-dce.adb \
s-osinte.ads<libgnarl/s-osinte__hpux-dce.ads \
s-parame.ads<libgnat/s-parame__hpux.ads \
@@ -2018,6 +2060,7 @@ ifeq ($(strip $(filter-out hppa% hp hpux11%,$(target_cpu) $(target_vendor) $(tar
a-intnam.ads<libgnarl/a-intnam__hpux.ads \
s-inmaop.adb<libgnarl/s-inmaop__posix.adb \
s-intman.adb<libgnarl/s-intman__posix.adb \
+ a-nallfl.ads<libgnat/a-nallfl__wraplf.ads \
s-osinte.adb<libgnarl/s-osinte__posix.adb \
s-osinte.ads<libgnarl/s-osinte__hpux.ads \
s-parame.ads<libgnat/s-parame__hpux.ads \
@@ -2249,6 +2292,7 @@ endif
ifeq ($(strip $(filter-out mips% linux%,$(target_cpu) $(target_os))),)
LIBGNAT_TARGET_PAIRS = \
a-intnam.ads<libgnarl/a-intnam__linux.ads \
+ a-nallfl.ads<libgnat/a-nallfl__wraplf.ads \
s-inmaop.adb<libgnarl/s-inmaop__posix.adb \
s-intman.adb<libgnarl/s-intman__posix.adb \
s-linux.ads<libgnarl/s-linux__mips.ads \
@@ -2299,7 +2343,7 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(target_cpu) $(target_os))),)
$(ATOMICS_BUILTINS_TARGET_PAIRS) \
system.ads<libgnat/system-linux-ppc.ads
- ifeq ($(strip $(filter-out powerpc64,$(target_cpu))),)
+ ifeq ($(strip $(filter-out powerpc64%,$(target_cpu))),)
ifneq ($(strip $(MULTISUBDIR)),/32)
LIBGNAT_TARGET_PAIRS += $(GNATRTL_128BIT_PAIRS)
EXTRA_GNATRTL_NONTASKING_OBJS += $(GNATRTL_128BIT_OBJS)
@@ -2339,12 +2383,14 @@ ifeq ($(strip $(filter-out arm% linux-gnueabi%,$(target_cpu) $(target_os))),)
s-tasinf.adb<libgnarl/s-tasinf__linux.adb \
s-taspri.ads<libgnarl/s-taspri__posix-noaltstack.ads \
s-tpopsp.adb<libgnarl/s-tpopsp__posix-foreign.adb \
+ $(TRASYM_DWARF_UNIX_PAIRS) \
$(ATOMICS_TARGET_PAIRS) \
$(ATOMICS_BUILTINS_TARGET_PAIRS) \
system.ads<libgnat/system-linux-arm.ads
TOOLS_TARGET_PAIRS = indepsw.adb<indepsw-gnu.adb
+ EXTRA_GNATRTL_NONTASKING_OBJS += $(TRASYM_DWARF_UNIX_OBJS)
EXTRA_GNATRTL_TASKING_OBJS=s-linux.o
EH_MECHANISM=-arm
THREADSLIB = -lpthread
@@ -2697,6 +2743,7 @@ endif
ifeq ($(strip $(filter-out riscv% linux%,$(target_cpu) $(target_os))),)
LIBGNAT_TARGET_PAIRS = \
a-intnam.ads<libgnarl/a-intnam__linux.ads \
+ a-nallfl.ads<libgnat/a-nallfl__wraplf.ads \
s-inmaop.adb<libgnarl/s-inmaop__posix.adb \
s-intman.adb<libgnarl/s-intman__posix.adb \
s-linux.ads<libgnarl/s-linux__riscv.ads \
@@ -2795,8 +2842,19 @@ ifeq ($(strip $(filter-out darwin%,$(target_os))),)
$(ATOMICS_BUILTINS_TARGET_PAIRS) \
system.ads<libgnat/system-darwin-ppc.ads
- ifeq ($(strip $(MULTISUBDIR)),/ppc64)
+ ifeq ($(strip $(filter-out powerpc64,$(target_cpu))),)
+ ifneq ($(strip $(MULTISUBDIR)),/ppc)
+ LIBGNAT_TARGET_PAIRS += $(GNATRTL_128BIT_PAIRS)
+ EXTRA_GNATRTL_NONTASKING_OBJS += $(GNATRTL_128BIT_OBJS)
+ else
+ SO_OPTS += -m32
+ endif
+ else
+ ifeq ($(strip $(MULTISUBDIR)),/ppc64)
SO_OPTS += -m64
+ LIBGNAT_TARGET_PAIRS += $(GNATRTL_128BIT_PAIRS)
+ EXTRA_GNATRTL_NONTASKING_OBJS += $(GNATRTL_128BIT_OBJS)
+ endif
endif
endif
diff --git a/gcc/ada/ada_get_targ.adb b/gcc/ada/ada_get_targ.adb
index ddaca1a..123ba4e 100644
--- a/gcc/ada/ada_get_targ.adb
+++ b/gcc/ada/ada_get_targ.adb
@@ -208,22 +208,6 @@ package body Get_Targ is
return 0;
end Get_Double_Scalar_Alignment;
- ----------------------
- -- Digits_From_Size --
- ----------------------
-
- function Digits_From_Size (Size : Pos) return Pos is
- begin
- case Size is
- when 32 => return 6;
- when 48 => return 9;
- when 64 => return 15;
- when 96 => return 18;
- when 128 => return 18;
- when others => raise Program_Error;
- end case;
- end Digits_From_Size;
-
-----------------------------
-- Get_Max_Unaligned_Field --
-----------------------------
@@ -260,22 +244,6 @@ package body Get_Targ is
Alignment => 64);
end Register_Back_End_Types;
- ---------------------
- -- Width_From_Size --
- ---------------------
-
- function Width_From_Size (Size : Pos) return Pos is
- begin
- case Size is
- when 8 => return 4;
- when 16 => return 6;
- when 32 => return 11;
- when 64 => return 21;
- when 128 => return 40;
- when others => raise Program_Error;
- end case;
- end Width_From_Size;
-
------------------------------
-- Get_Back_End_Config_File --
------------------------------
diff --git a/gcc/ada/adabkend.adb b/gcc/ada/adabkend.adb
index 6fb4a84..b10c0bd 100644
--- a/gcc/ada/adabkend.adb
+++ b/gcc/ada/adabkend.adb
@@ -218,6 +218,9 @@ package body Adabkend is
end case;
end if;
+ elsif Switch_Chars (First .. Last) = "S" then
+ Generate_Asm := True;
+
-- Ignore all other back-end switches
elsif Is_Back_End_Switch (Switch_Chars) then
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index 560f352..0a90c92 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -145,6 +145,13 @@
#include "version.h"
#endif
+/* limits.h is needed for LLONG_MIN. */
+#ifdef __cplusplus
+#include <climits>
+#else
+#include <limits.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -237,6 +244,8 @@ UINT __gnat_current_ccs_encoding;
#include "adaint.h"
+int __gnat_in_child_after_fork = 0;
+
#if defined (__APPLE__) && defined (st_mtime)
#define st_atim st_atimespec
#define st_mtim st_mtimespec
@@ -2414,6 +2423,7 @@ __gnat_portable_spawn (char *args[] ATTRIBUTE_UNUSED)
if (pid == 0)
{
/* The child. */
+ __gnat_in_child_after_fork = 1;
if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
_exit (1);
}
@@ -2476,9 +2486,7 @@ __gnat_number_of_cpus (void)
{
int cores = 1;
-#if defined (__linux__) || defined (__sun__) || defined (_AIX) \
- || defined (__APPLE__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
- || defined (__DragonFly__) || defined (__NetBSD__)
+#ifdef _SC_NPROCESSORS_ONLN
cores = (int) sysconf (_SC_NPROCESSORS_ONLN);
#elif defined (__QNX__)
@@ -3262,7 +3270,22 @@ __gnat_copy_attribs (char *from ATTRIBUTE_UNUSED, char *to ATTRIBUTE_UNUSED,
return -1;
}
-#if _POSIX_C_SOURCE >= 200809L
+#if (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 7)
+
+ /* VxWorks prior to 7 only has utime. */
+
+ /* Do we need to copy the timestamp ? */
+ if (mode != 2) {
+ struct utimbuf tbuf;
+
+ tbuf.actime = fbuf.st_atime;
+ tbuf.modtime = fbuf.st_mtime;
+
+ if (utime (to, &tbuf) == -1)
+ return -1;
+ }
+
+#elif _POSIX_C_SOURCE >= 200809L
struct timespec tbuf[2];
if (mode != 2) {
diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h
index 4f42f6c..85997b9 100644
--- a/gcc/ada/adaint.h
+++ b/gcc/ada/adaint.h
@@ -139,7 +139,15 @@ struct file_attributes {
* fit the above struct on any system)
*/
-extern int __gnat_max_path_len;
+extern int __gnat_max_path_len;
+extern int __gnat_in_child_after_fork;
+/* This flag expresses the state when the fork call just returned zero result,
+ * i.e. when the new born child process is created and the new executable is
+ * not loaded yet. It is used to e.g. disable tracing memory
+ * allocation/deallocation in memtrack.adb just after fork returns in the child
+ * process to avoid both parent and child writing to the same gmem.out file
+ * simultaneously */
+
extern OS_Time __gnat_current_time (void);
extern void __gnat_current_time_string (char *);
extern void __gnat_to_gm_time (OS_Time *, int *, int *,
diff --git a/gcc/ada/ali-util.adb b/gcc/ada/ali-util.adb
index 9dcc656..7dabbfb 100644
--- a/gcc/ada/ali-util.adb
+++ b/gcc/ada/ali-util.adb
@@ -31,7 +31,6 @@ with Osint; use Osint;
with Scans; use Scans;
with Scng;
with Sinput.C;
-with Snames; use Snames;
with Stringt;
with Styleg;
@@ -154,15 +153,6 @@ package body ALI.Util is
Scanner.Initialize_Scanner (Source_Index);
- -- Make sure that the project language reserved words are not
- -- recognized as reserved words, but as identifiers. The byte info for
- -- those names have been set if we are in gnatmake.
-
- Set_Name_Table_Byte (Name_Project, 0);
- Set_Name_Table_Byte (Name_Extends, 0);
- Set_Name_Table_Byte (Name_External, 0);
- Set_Name_Table_Byte (Name_External_As_List, 0);
-
-- Scan the complete file to compute its checksum
loop
diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb
index 3bf1257..f213c30 100644
--- a/gcc/ada/ali.adb
+++ b/gcc/ada/ali.adb
@@ -3814,15 +3814,15 @@ package body ALI is
return No_ALI_Id;
end Scan_ALI;
- -----------
- -- Scope --
- -----------
+ --------------
+ -- IS_Scope --
+ --------------
- function Scope (IS_Id : Invocation_Signature_Id) return Name_Id is
+ function IS_Scope (IS_Id : Invocation_Signature_Id) return Name_Id is
begin
pragma Assert (Present (IS_Id));
return Invocation_Signatures.Table (IS_Id).Scope;
- end Scope;
+ end IS_Scope;
---------
-- SEq --
diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads
index 928fdbd..ccb516f 100644
--- a/gcc/ada/ali.ads
+++ b/gcc/ada/ali.ads
@@ -1350,8 +1350,8 @@ package ALI is
pragma Inline (Name);
-- Obtain the name of invocation signature IS_Id
- function Scope (IS_Id : Invocation_Signature_Id) return Name_Id;
- pragma Inline (Scope);
+ function IS_Scope (IS_Id : Invocation_Signature_Id) return Name_Id;
+ pragma Inline (IS_Scope);
-- Obtain the scope of invocation signature IS_Id
procedure Set_Invocation_Graph_Encoding
diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb
index 37bbcae..91550c8 100644
--- a/gcc/ada/aspects.adb
+++ b/gcc/ada/aspects.adb
@@ -44,6 +44,7 @@ package body Aspects is
Aspect_Discard_Names => True,
Aspect_Independent_Components => True,
Aspect_Iterator_Element => True,
+ Aspect_Stable_Properties => True,
Aspect_Type_Invariant => True,
Aspect_Unchecked_Union => True,
Aspect_Variable_Indexing => True,
@@ -185,7 +186,11 @@ package body Aspects is
-- Find_Aspect --
-----------------
- function Find_Aspect (Id : Entity_Id; A : Aspect_Id) return Node_Id is
+ function Find_Aspect
+ (Id : Entity_Id;
+ A : Aspect_Id;
+ Class_Present : Boolean := False) return Node_Id
+ is
Decl : Node_Id;
Item : Node_Id;
Owner : Entity_Id;
@@ -219,6 +224,7 @@ package body Aspects is
while Present (Item) loop
if Nkind (Item) = N_Aspect_Specification
and then Get_Aspect_Id (Item) = A
+ and then Class_Present = Sinfo.Class_Present (Item)
then
return Item;
end if;
@@ -241,7 +247,9 @@ package body Aspects is
if Permits_Aspect_Specifications (Decl) then
Spec := First (Aspect_Specifications (Decl));
while Present (Spec) loop
- if Get_Aspect_Id (Spec) = A then
+ if Get_Aspect_Id (Spec) = A
+ and then Class_Present = Sinfo.Class_Present (Spec)
+ then
return Spec;
end if;
@@ -260,10 +268,12 @@ package body Aspects is
--------------------------
function Find_Value_Of_Aspect
- (Id : Entity_Id;
- A : Aspect_Id) return Node_Id
+ (Id : Entity_Id;
+ A : Aspect_Id;
+ Class_Present : Boolean := False) return Node_Id
is
- Spec : constant Node_Id := Find_Aspect (Id, A);
+ Spec : constant Node_Id := Find_Aspect (Id, A,
+ Class_Present => Class_Present);
begin
if Present (Spec) then
@@ -296,9 +306,13 @@ package body Aspects is
-- Has_Aspect --
----------------
- function Has_Aspect (Id : Entity_Id; A : Aspect_Id) return Boolean is
+ function Has_Aspect
+ (Id : Entity_Id;
+ A : Aspect_Id;
+ Class_Present : Boolean := False) return Boolean
+ is
begin
- return Present (Find_Aspect (Id, A));
+ return Present (Find_Aspect (Id, A, Class_Present => Class_Present));
end Has_Aspect;
------------------
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 1470efe..e16ceb0 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -142,6 +142,7 @@ package Aspects is
Aspect_Size,
Aspect_Small,
Aspect_SPARK_Mode, -- GNAT
+ Aspect_Stable_Properties,
Aspect_Static_Predicate,
Aspect_Storage_Pool,
Aspect_Storage_Size,
@@ -237,16 +238,17 @@ package Aspects is
-- The following array indicates aspects that accept 'Class
Class_Aspect_OK : constant array (Aspect_Id) of Boolean :=
- (Aspect_Input => True,
- Aspect_Invariant => True,
- Aspect_Output => True,
- Aspect_Pre => True,
- Aspect_Predicate => True,
- Aspect_Post => True,
- Aspect_Read => True,
- Aspect_Write => True,
- Aspect_Type_Invariant => True,
- others => False);
+ (Aspect_Input => True,
+ Aspect_Invariant => True,
+ Aspect_Output => True,
+ Aspect_Pre => True,
+ Aspect_Predicate => True,
+ Aspect_Post => True,
+ Aspect_Read => True,
+ Aspect_Write => True,
+ Aspect_Stable_Properties => True,
+ Aspect_Type_Invariant => True,
+ others => False);
-- The following array identifies all implementation defined aspects
@@ -427,6 +429,7 @@ package Aspects is
Aspect_Size => Expression,
Aspect_Small => Expression,
Aspect_SPARK_Mode => Optional_Name,
+ Aspect_Stable_Properties => Expression,
Aspect_Static_Predicate => Expression,
Aspect_Storage_Pool => Name,
Aspect_Storage_Size => Expression,
@@ -528,6 +531,7 @@ package Aspects is
Aspect_Size => True,
Aspect_Small => True,
Aspect_SPARK_Mode => False,
+ Aspect_Stable_Properties => False,
Aspect_Static_Predicate => False,
Aspect_Storage_Pool => True,
Aspect_Storage_Size => True,
@@ -704,6 +708,7 @@ package Aspects is
Aspect_Size => Name_Size,
Aspect_Small => Name_Small,
Aspect_SPARK_Mode => Name_SPARK_Mode,
+ Aspect_Stable_Properties => Name_Stable_Properties,
Aspect_Static => Name_Static,
Aspect_Static_Predicate => Name_Static_Predicate,
Aspect_Storage_Pool => Name_Storage_Pool,
@@ -965,6 +970,7 @@ package Aspects is
Aspect_Refined_State => Never_Delay,
Aspect_Relaxed_Initialization => Never_Delay,
Aspect_SPARK_Mode => Never_Delay,
+ Aspect_Stable_Properties => Always_Delay,
Aspect_Static => Never_Delay,
Aspect_Subprogram_Variant => Never_Delay,
Aspect_Synchronization => Never_Delay,
@@ -1094,18 +1100,24 @@ package Aspects is
-- aspect specification list, the routine has no effect. It is assumed that
-- both nodes can support aspects.
- function Find_Aspect (Id : Entity_Id; A : Aspect_Id) return Node_Id;
- -- Find the aspect specification of aspect A associated with entity I.
+ function Find_Aspect (Id : Entity_Id;
+ A : Aspect_Id;
+ Class_Present : Boolean := False) return Node_Id;
+ -- Find the aspect specification of aspect A (or A'Class if Class_Present)
+ -- associated with entity I.
-- Return Empty if Id does not have the requested aspect.
function Find_Value_Of_Aspect
- (Id : Entity_Id;
- A : Aspect_Id) return Node_Id;
- -- Find the value of aspect A associated with entity Id. Return Empty if
- -- Id does not have the requested aspect.
-
- function Has_Aspect (Id : Entity_Id; A : Aspect_Id) return Boolean;
- -- Determine whether entity Id has aspect A
+ (Id : Entity_Id;
+ A : Aspect_Id;
+ Class_Present : Boolean := False) return Node_Id;
+ -- Find the value of aspect A (or A'Class, if Class_Present) associated
+ -- with entity Id. Return Empty if Id does not have the requested aspect.
+
+ function Has_Aspect (Id : Entity_Id;
+ A : Aspect_Id;
+ Class_Present : Boolean := False) return Boolean;
+ -- Determine whether entity Id has aspect A (or A'Class, if Class_Present)
procedure Move_Aspects (From : Node_Id; To : Node_Id);
-- Relocate the aspect specifications of node From to node To. On entry it
diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb
index cca6687..926fb82 100644
--- a/gcc/ada/bindo-writers.adb
+++ b/gcc/ada/bindo-writers.adb
@@ -222,7 +222,7 @@ package body Bindo.Writers is
Write_Eol;
Write_Str (" Scope = ");
- Write_Name (Scope (IS_Id));
+ Write_Name (IS_Scope (IS_Id));
Write_Eol;
end Write_Invocation_Signature;
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index b389da5..61e41dd 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -535,7 +535,7 @@ package body Checks is
-- We do not need checks if we are not generating code (i.e. the
-- expander is not active). This is not just an optimization, there
-- are cases (e.g. with pragma Debug) where generating the checks
- -- can cause real trouble).
+ -- can cause real trouble.
if not Expander_Active then
return;
@@ -3258,23 +3258,16 @@ package body Checks is
end if;
-- Return if we know expression is definitely in the range of the target
- -- type as determined by Determine_Range. Right now we only do this for
- -- discrete types, and not fixed-point or floating-point types.
-
- -- The additional less-precise tests below catch these cases
-
- -- In GNATprove_Mode, also deal with the case of a conversion from
- -- floating-point to integer. It is only possible because analysis
- -- in GNATprove rules out the possibility of a NaN or infinite value.
+ -- type as determined by Determine_Range_To_Discrete. Right now we only
+ -- do this for discrete target types, i.e. neither for fixed-point nor
+ -- for floating-point types. But the additional less precise tests below
+ -- catch these cases.
-- Note: skip this if we are given a source_typ, since the point of
-- supplying a Source_Typ is to stop us looking at the expression.
-- We could sharpen this test to be out parameters only ???
if Is_Discrete_Type (Target_Typ)
- and then (Is_Discrete_Type (Etype (Expr))
- or else (GNATprove_Mode
- and then Is_Floating_Point_Type (Etype (Expr))))
and then not Is_Unconstrained_Subscr_Ref
and then No (Source_Typ)
then
@@ -3318,35 +3311,8 @@ package body Checks is
-- Otherwise determine range of value
- if Is_Discrete_Type (Etype (Expr)) then
- Determine_Range
- (Expr, OK, Lo, Hi, Assume_Valid => True);
-
- -- When converting a float to an integer type, determine the
- -- range in real first, and then convert the bounds using
- -- UR_To_Uint which correctly rounds away from zero when
- -- half way between two integers, as required by normal
- -- Ada 95 rounding semantics. It is only possible because
- -- analysis in GNATprove rules out the possibility of a NaN
- -- or infinite value.
-
- elsif GNATprove_Mode
- and then Is_Floating_Point_Type (Etype (Expr))
- then
- declare
- Hir : Ureal;
- Lor : Ureal;
-
- begin
- Determine_Range_R
- (Expr, OK, Lor, Hir, Assume_Valid => True);
-
- if OK then
- Lo := UR_To_Uint (Lor);
- Hi := UR_To_Uint (Hir);
- end if;
- end;
- end if;
+ Determine_Range_To_Discrete
+ (Expr, OK, Lo, Hi, Fixed_Int, Assume_Valid => True);
if OK then
@@ -3389,10 +3355,12 @@ package body Checks is
-- Check if we can determine at compile time whether Expr is in the
-- range of the target type. Note that if S_Typ is within the bounds
-- of Target_Typ then this must be the case. This check is meaningful
- -- only if this is not a conversion between integer and real types.
+ -- only if this is not a conversion between integer and real types,
+ -- unless for a fixed-point type if Fixed_Int is set.
if not Is_Unconstrained_Subscr_Ref
- and then Is_Discrete_Type (S_Typ) = Is_Discrete_Type (Target_Typ)
+ and then (Is_Discrete_Type (S_Typ) = Is_Discrete_Type (Target_Typ)
+ or else (Fixed_Int and then Is_Discrete_Type (Target_Typ)))
and then
(In_Subrange_Of (S_Typ, Target_Typ, Fixed_Int)
@@ -3705,12 +3673,15 @@ package body Checks is
then
Apply_Float_Conversion_Check (Expr, Target_Type);
else
- -- Conversions involving fixed-point types are expanded
- -- separately, and do not need a Range_Check flag, except
- -- in GNATprove_Mode, where the explicit constraint check
- -- will not be generated.
+ -- Raw conversions involving fixed-point types are expanded
+ -- separately and do not need a Range_Check flag yet, except
+ -- in GNATprove_Mode where this expansion is not performed.
+ -- This does not apply to conversion where fixed-point types
+ -- are treated as integers, which are precisely generated by
+ -- this expansion.
if GNATprove_Mode
+ or else Conv_OK
or else (not Is_Fixed_Point_Type (Expr_Type)
and then not Is_Fixed_Point_Type (Target_Type))
then
@@ -3951,6 +3922,13 @@ package body Checks is
function Aggregate_Discriminant_Val (Disc : Entity_Id) return Node_Id;
+ function Replace_Current_Instance
+ (N : Node_Id) return Traverse_Result;
+ -- Replace a reference to the current instance of the type with the
+ -- corresponding _init formal of the initialization procedure. Note:
+ -- this function relies on us currently being within the initialization
+ -- procedure.
+
--------------------------------
-- Aggregate_Discriminant_Val --
--------------------------------
@@ -3978,6 +3956,26 @@ package body Checks is
raise Program_Error;
end Aggregate_Discriminant_Val;
+ ------------------------------
+ -- Replace_Current_Instance --
+ ------------------------------
+
+ function Replace_Current_Instance
+ (N : Node_Id) return Traverse_Result is
+ begin
+ if Is_Entity_Name (N)
+ and then Etype (N) = Entity (N)
+ then
+ Rewrite (N,
+ New_Occurrence_Of (First_Formal (Current_Subprogram), Loc));
+ end if;
+
+ return OK;
+ end Replace_Current_Instance;
+
+ procedure Search_And_Replace_Current_Instance is new
+ Traverse_Proc (Replace_Current_Instance);
+
-- Start of processing for Build_Discriminant_Checks
begin
@@ -4007,6 +4005,13 @@ package body Checks is
Dval := Duplicate_Subexpr_No_Checks (Dval);
end if;
+ -- Replace references to the current instance of the type with the
+ -- corresponding _init formal of the initialization procedure.
+
+ if Within_Init_Proc then
+ Search_And_Replace_Current_Instance (Dval);
+ end if;
+
-- If we have an Unchecked_Union node, we can infer the discriminants
-- of the node.
@@ -4415,7 +4420,7 @@ package body Checks is
Apply_Compile_Time_Constraint_Error
(N => Expr,
Msg =>
- "(Ada 2005) null not allowed in null-excluding "
+ "(Ada 2005) NULL not allowed in null-excluding "
& "components??",
Reason => CE_Null_Not_Allowed);
@@ -4423,7 +4428,7 @@ package body Checks is
Apply_Compile_Time_Constraint_Error
(N => Expr,
Msg =>
- "(Ada 2005) null not allowed in null-excluding "
+ "(Ada 2005) NULL not allowed in null-excluding "
& "objects??",
Reason => CE_Null_Not_Allowed);
@@ -4431,7 +4436,7 @@ package body Checks is
Apply_Compile_Time_Constraint_Error
(N => Expr,
Msg =>
- "(Ada 2005) null not allowed in null-excluding "
+ "(Ada 2005) NULL not allowed in null-excluding "
& "formals??",
Reason => CE_Null_Not_Allowed);
@@ -5354,38 +5359,11 @@ package body Checks is
end case;
when N_Type_Conversion =>
+ -- For a type conversion, we can try to refine the range using the
+ -- converted value.
- -- For type conversion from one discrete type to another, we can
- -- refine the range using the converted value.
-
- if Is_Discrete_Type (Etype (Expression (N))) then
- Determine_Range (Expression (N), OK1, Lor, Hir, Assume_Valid);
-
- -- When converting a float to an integer type, determine the range
- -- in real first, and then convert the bounds using UR_To_Uint
- -- which correctly rounds away from zero when half way between two
- -- integers, as required by normal Ada 95 rounding semantics. It
- -- is only possible because analysis in GNATprove rules out the
- -- possibility of a NaN or infinite value.
-
- elsif GNATprove_Mode
- and then Is_Floating_Point_Type (Etype (Expression (N)))
- then
- declare
- Lor_Real, Hir_Real : Ureal;
- begin
- Determine_Range_R (Expression (N), OK1, Lor_Real, Hir_Real,
- Assume_Valid);
-
- if OK1 then
- Lor := UR_To_Uint (Lor_Real);
- Hir := UR_To_Uint (Hir_Real);
- end if;
- end;
-
- else
- OK1 := False;
- end if;
+ Determine_Range_To_Discrete
+ (Expression (N), OK1, Lor, Hir, Conversion_OK (N), Assume_Valid);
-- Nothing special to do for all other expression kinds
@@ -5905,6 +5883,96 @@ package body Checks is
end if;
end Determine_Range_R;
+ ---------------------------------
+ -- Determine_Range_To_Discrete --
+ ---------------------------------
+
+ procedure Determine_Range_To_Discrete
+ (N : Node_Id;
+ OK : out Boolean;
+ Lo : out Uint;
+ Hi : out Uint;
+ Fixed_Int : Boolean := False;
+ Assume_Valid : Boolean := False)
+ is
+ Typ : constant Entity_Id := Etype (N);
+
+ begin
+ -- For a discrete type, simply defer to Determine_Range
+
+ if Is_Discrete_Type (Typ) then
+ Determine_Range (N, OK, Lo, Hi, Assume_Valid);
+
+ -- For a fixed point type treated as an integer, we can determine the
+ -- range using the Corresponding_Integer_Value of the bounds of the
+ -- type or base type. This is done by the calls to Expr_Value below.
+
+ elsif Is_Fixed_Point_Type (Typ) and then Fixed_Int then
+ declare
+ Btyp, Ftyp : Entity_Id;
+ Bound : Node_Id;
+
+ begin
+ if Assume_Valid then
+ Ftyp := Typ;
+ else
+ Ftyp := Underlying_Type (Base_Type (Typ));
+ end if;
+
+ Btyp := Base_Type (Ftyp);
+
+ -- First the low bound
+
+ Bound := Type_Low_Bound (Ftyp);
+
+ if Compile_Time_Known_Value (Bound) then
+ Lo := Expr_Value (Bound);
+ else
+ Lo := Expr_Value (Type_Low_Bound (Btyp));
+ end if;
+
+ -- Then the high bound
+
+ Bound := Type_High_Bound (Ftyp);
+
+ if Compile_Time_Known_Value (Bound) then
+ Hi := Expr_Value (Bound);
+ else
+ Hi := Expr_Value (Type_High_Bound (Btyp));
+ end if;
+
+ OK := True;
+ end;
+
+ -- For a floating-point type, we can determine the range in real first,
+ -- and then convert the bounds using UR_To_Uint, which correctly rounds
+ -- away from zero when half way between two integers, as required by
+ -- normal Ada 95 rounding semantics. But this is only possible because
+ -- GNATprove's analysis rules out the possibility of a NaN or infinite.
+
+ elsif GNATprove_Mode and then Is_Floating_Point_Type (Typ) then
+ declare
+ Lo_Real, Hi_Real : Ureal;
+
+ begin
+ Determine_Range_R (N, OK, Lo_Real, Hi_Real, Assume_Valid);
+
+ if OK then
+ Lo := UR_To_Uint (Lo_Real);
+ Hi := UR_To_Uint (Hi_Real);
+ else
+ Lo := No_Uint;
+ Hi := No_Uint;
+ end if;
+ end;
+
+ else
+ Lo := No_Uint;
+ Hi := No_Uint;
+ OK := False;
+ end if;
+ end Determine_Range_To_Discrete;
+
------------------------------------
-- Discriminant_Checks_Suppressed --
------------------------------------
@@ -10551,10 +10619,10 @@ package body Checks is
begin
-- Checks will be applied only when generating code. In GNATprove mode,
-- we do not apply the checks, but we still call Selected_Range_Checks
- -- to possibly issue errors on SPARK code when a run-time error can be
- -- detected at compile time.
+ -- outside of generics to possibly issue errors on SPARK code when a
+ -- run-time error can be detected at compile time.
- if not Expander_Active and not GNATprove_Mode then
+ if Inside_A_Generic or (not GNATprove_Mode and not Expander_Active) then
return Ret_Result;
end if;
@@ -11127,8 +11195,7 @@ package body Checks is
procedure Validity_Check_Range
(N : Node_Id;
- Related_Id : Entity_Id := Empty)
- is
+ Related_Id : Entity_Id := Empty) is
begin
if Validity_Checks_On and Validity_Check_Operands then
if Nkind (N) = N_Range then
@@ -11145,17 +11212,4 @@ package body Checks is
end if;
end Validity_Check_Range;
- --------------------------------
- -- Validity_Checks_Suppressed --
- --------------------------------
-
- function Validity_Checks_Suppressed (E : Entity_Id) return Boolean is
- begin
- if Present (E) and then Checks_May_Be_Suppressed (E) then
- return Is_Check_Suppressed (E, Validity_Check);
- else
- return Scope_Suppress.Suppress (Validity_Check);
- end if;
- end Validity_Checks_Suppressed;
-
end Checks;
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index aca1b7e..e7b7261 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -64,7 +64,6 @@ package Checks is
function Range_Checks_Suppressed (E : Entity_Id) return Boolean;
function Storage_Checks_Suppressed (E : Entity_Id) return Boolean;
function Tag_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Validity_Checks_Suppressed (E : Entity_Id) return Boolean;
-- These functions check to see if the named check is suppressed, either
-- by an active scope suppress setting, or because the check has been
-- specifically suppressed for the given entity. If no entity is relevant
@@ -338,6 +337,21 @@ package Checks is
-- For that to happen, the possibility of arguments of infinite or NaN
-- value should be taken into account, which is not the case currently.
+ procedure Determine_Range_To_Discrete
+ (N : Node_Id;
+ OK : out Boolean;
+ Lo : out Uint;
+ Hi : out Uint;
+ Fixed_Int : Boolean := False;
+ Assume_Valid : Boolean := False);
+ -- Similar to Determine_Range, but attempts to return a discrete range even
+ -- if N is not of a discrete type by doing a conversion. The Fixed_Int flag
+ -- if set causes any fixed-point values to be treated as though they were
+ -- discrete values (i.e. the underlying integer value is used), in which
+ -- case no conversion is needed. At the current time, this is used only for
+ -- discrete types, for fixed-point types if Fixed_Int is set, and also for
+ -- floating-point types in GNATprove, see Determine_Range_R above.
+
procedure Install_Null_Excluding_Check (N : Node_Id);
-- Determines whether an access node requires a run-time access check and
-- if so inserts the appropriate run-time check.
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 9e328e2..29557ec 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -47,6 +47,7 @@ with Sem_Disp; use Sem_Disp;
with Sem_Prag; use Sem_Prag;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
+with Sinput; use Sinput;
with Snames; use Snames;
with Stand; use Stand;
with Stringt; use Stringt;
@@ -904,9 +905,12 @@ package body Contracts is
-- The following checks are relevant only when SPARK_Mode is on, as
-- they are not standard Ada legality rules. Internally generated
- -- temporaries are ignored.
+ -- temporaries are ignored, as well as return objects.
- if SPARK_Mode = On and then Comes_From_Source (Type_Or_Obj_Id) then
+ if SPARK_Mode = On
+ and then Comes_From_Source (Type_Or_Obj_Id)
+ and then not Is_Return_Object (Type_Or_Obj_Id)
+ then
if Is_Effectively_Volatile (Type_Or_Obj_Id) then
-- The declaration of an effectively volatile object or type must
@@ -1668,6 +1672,12 @@ package body Contracts is
-- function, Result contains the entity of parameter _Result, to be
-- used in the creation of procedure _Postconditions.
+ procedure Add_Stable_Property_Contracts
+ (Subp_Id : Entity_Id; Class_Present : Boolean);
+ -- Augment postcondition contracts to reflect Stable_Property aspect
+ -- (if Class_Present = False) or Stable_Property'Class aspect (if
+ -- Class_Present = True).
+
procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
-- Append a node to a list. If there is no list, create a new one. When
-- the item denotes a pragma, it is added to the list only when it is
@@ -1905,6 +1915,244 @@ package body Contracts is
end loop;
end Add_Invariant_And_Predicate_Checks;
+ -----------------------------------
+ -- Add_Stable_Property_Contracts --
+ -----------------------------------
+
+ procedure Add_Stable_Property_Contracts
+ (Subp_Id : Entity_Id; Class_Present : Boolean)
+ is
+ Loc : constant Source_Ptr := Sloc (Subp_Id);
+
+ procedure Insert_Stable_Property_Check
+ (Formal : Entity_Id; Property_Function : Entity_Id);
+ -- Build the pragma for one check and insert it in the tree.
+
+ function Make_Stable_Property_Condition
+ (Formal : Entity_Id; Property_Function : Entity_Id) return Node_Id;
+ -- Builds tree for "Func (Formal) = Func (Formal)'Old" expression.
+
+ function Stable_Properties
+ (Aspect_Bearer : Entity_Id; Negated : out Boolean)
+ return Subprogram_List;
+ -- If no aspect specified, then returns length-zero result.
+ -- Negated indicates that reserved word NOT was specified.
+
+ ----------------------------------
+ -- Insert_Stable_Property_Check --
+ ----------------------------------
+
+ procedure Insert_Stable_Property_Check
+ (Formal : Entity_Id; Property_Function : Entity_Id) is
+
+ Args : constant List_Id :=
+ New_List
+ (Make_Pragma_Argument_Association
+ (Sloc => Loc,
+ Expression =>
+ Make_Stable_Property_Condition
+ (Formal => Formal,
+ Property_Function => Property_Function)),
+ Make_Pragma_Argument_Association
+ (Sloc => Loc,
+ Expression =>
+ Make_String_Literal
+ (Sloc => Loc,
+ Strval =>
+ "failed stable property check at "
+ & Build_Location_String (Loc)
+ & " for parameter "
+ & To_String (Fully_Qualified_Name_String
+ (Formal, Append_NUL => False))
+ & " and property function "
+ & To_String (Fully_Qualified_Name_String
+ (Property_Function, Append_NUL => False))
+ )));
+
+ Prag : constant Node_Id :=
+ Make_Pragma (Loc,
+ Pragma_Identifier =>
+ Make_Identifier (Loc, Name_Postcondition),
+ Pragma_Argument_Associations => Args,
+ Class_Present => Class_Present);
+
+ Subp_Decl : Node_Id := Subp_Id;
+ begin
+ -- Enclosing_Declaration may return, for example,
+ -- a N_Procedure_Specification node. Cope with this.
+ loop
+ Subp_Decl := Enclosing_Declaration (Subp_Decl);
+ exit when Is_Declaration (Subp_Decl);
+ Subp_Decl := Parent (Subp_Decl);
+ pragma Assert (Present (Subp_Decl));
+ end loop;
+
+ Insert_After_And_Analyze (Subp_Decl, Prag);
+ end Insert_Stable_Property_Check;
+
+ ------------------------------------
+ -- Make_Stable_Property_Condition --
+ ------------------------------------
+
+ function Make_Stable_Property_Condition
+ (Formal : Entity_Id; Property_Function : Entity_Id) return Node_Id
+ is
+ function Call_Property_Function return Node_Id is
+ (Make_Function_Call
+ (Loc,
+ Name =>
+ New_Occurrence_Of (Property_Function, Loc),
+ Parameter_Associations =>
+ New_List (New_Occurrence_Of (Formal, Loc))));
+ begin
+ return Make_Op_Eq
+ (Loc,
+ Call_Property_Function,
+ Make_Attribute_Reference
+ (Loc,
+ Prefix => Call_Property_Function,
+ Attribute_Name => Name_Old));
+ end Make_Stable_Property_Condition;
+
+ -----------------------
+ -- Stable_Properties --
+ -----------------------
+
+ function Stable_Properties
+ (Aspect_Bearer : Entity_Id; Negated : out Boolean)
+ return Subprogram_List
+ is
+ Aspect_Spec : Node_Id :=
+ Find_Value_Of_Aspect
+ (Aspect_Bearer, Aspect_Stable_Properties,
+ Class_Present => Class_Present);
+ begin
+ -- ??? For a derived type, we wish Find_Value_Of_Aspect
+ -- somehow knew that this aspect is not inherited.
+ -- But it doesn't, so we cope with that here.
+ --
+ -- There are probably issues here with inheritance from
+ -- interface types, where just looking for the one parent type
+ -- isn't enough. But this is far from the only work needed for
+ -- Stable_Properties'Class for interface types.
+
+ if Is_Derived_Type (Aspect_Bearer) then
+ declare
+ Parent_Type : constant Entity_Id :=
+ Etype (Base_Type (Aspect_Bearer));
+ begin
+ if Aspect_Spec =
+ Find_Value_Of_Aspect
+ (Parent_Type, Aspect_Stable_Properties,
+ Class_Present => Class_Present)
+ then
+ -- prevent inheritance
+ Aspect_Spec := Empty;
+ end if;
+ end;
+ end if;
+
+ if No (Aspect_Spec) then
+ Negated := Aspect_Bearer = Subp_Id;
+ -- This is a little bit subtle.
+ -- We need to assign True in the Subp_Id case in order to
+ -- distinguish between no aspect spec at all vs. an
+ -- explicitly specified "with S_P => []" empty list.
+ -- In both cases Stable_Properties will return a length-0
+ -- array, but the two cases are not equivalent.
+ -- Very roughly speaking the lack of an S_P aspect spec for
+ -- a subprogram would be equivalent to something like
+ -- "with S_P => [not]", where we apply the "not" modifier to
+ -- an empty set of subprograms, if such a construct existed.
+ -- We could just assign True here, but it seems untidy to
+ -- return True in the case of an aspect spec for a type
+ -- (since negation is only allowed for subp S_P aspects).
+
+ return (1 .. 0 => <>);
+ else
+ return Parse_Aspect_Stable_Properties
+ (Aspect_Spec, Negated => Negated);
+ end if;
+ end Stable_Properties;
+
+ Formal : Entity_Id := First_Formal (Subp_Id);
+ Type_Of_Formal : Entity_Id;
+
+ Subp_Properties_Negated : Boolean;
+ Subp_Properties : constant Subprogram_List :=
+ Stable_Properties (Subp_Id, Subp_Properties_Negated);
+
+ -- start of processing for Add_Stable_Property_Contracts
+
+ begin
+ if not (Is_Primitive (Subp_Id) and then Comes_From_Source (Subp_Id))
+ then
+ return;
+ end if;
+
+ while Present (Formal) loop
+ Type_Of_Formal := Base_Type (Etype (Formal));
+
+ if not Subp_Properties_Negated then
+
+ for SPF_Id of Subp_Properties loop
+ if Type_Of_Formal = Base_Type (Etype (First_Formal (SPF_Id)))
+ and then Scope (Type_Of_Formal) = Scope (Subp_Id)
+ then
+ -- ??? Need to filter out checks for SPFs that are
+ -- mentioned explicitly in the postcondition of
+ -- Subp_Id.
+
+ Insert_Stable_Property_Check
+ (Formal => Formal, Property_Function => SPF_Id);
+ end if;
+ end loop;
+
+ elsif Scope (Type_Of_Formal) = Scope (Subp_Id) then
+ declare
+ Ignored : Boolean range False .. False;
+
+ Typ_Property_Funcs : constant Subprogram_List :=
+ Stable_Properties (Type_Of_Formal, Negated => Ignored);
+
+ function Excluded_By_Aspect_Spec_Of_Subp
+ (SPF_Id : Entity_Id) return Boolean;
+ -- Examine Subp_Properties to determine whether SPF should
+ -- be excluded.
+
+ -------------------------------------
+ -- Excluded_By_Aspect_Spec_Of_Subp --
+ -------------------------------------
+
+ function Excluded_By_Aspect_Spec_Of_Subp
+ (SPF_Id : Entity_Id) return Boolean is
+ begin
+ pragma Assert (Subp_Properties_Negated);
+ -- Look through renames for equality test here ???
+ return (for some F of Subp_Properties => F = SPF_Id);
+ end Excluded_By_Aspect_Spec_Of_Subp;
+
+ -- Look through renames for equality test here ???
+ Subp_Is_Stable_Property_Function : constant Boolean :=
+ (for some F of Typ_Property_Funcs => F = Subp_Id);
+ begin
+ if not Subp_Is_Stable_Property_Function then
+ for SPF_Id of Typ_Property_Funcs loop
+ if not Excluded_By_Aspect_Spec_Of_Subp (SPF_Id) then
+ -- ??? Need to filter out checks for SPFs that are
+ -- mentioned explicitly in the postcondition of
+ -- Subp_Id.
+ Insert_Stable_Property_Check
+ (Formal => Formal, Property_Function => SPF_Id);
+ end if;
+ end loop;
+ end if;
+ end;
+ end if;
+ Next_Formal (Formal);
+ end loop;
+ end Add_Stable_Property_Contracts;
+
-------------------------
-- Append_Enabled_Item --
-------------------------
@@ -1950,12 +2198,24 @@ package body Contracts is
Result : Entity_Id)
is
Loc : constant Source_Ptr := Sloc (Body_Decl);
+ Last_Decl : Node_Id;
Params : List_Id := No_List;
Proc_Bod : Node_Id;
Proc_Decl : Node_Id;
Proc_Id : Entity_Id;
Proc_Spec : Node_Id;
+ -- Extra declarations needed to handle interactions between
+ -- postconditions and finalization.
+
+ Postcond_Enabled_Decl : Node_Id;
+ Return_Success_Decl : Node_Id;
+ Result_Obj_Decl : Node_Id;
+ Result_Obj_Type_Decl : Node_Id;
+ Result_Obj_Type : Entity_Id;
+
+ -- Start of processing for Build_Postconditions_Procedure
+
begin
-- Nothing to do if there are no actions to check on exit
@@ -1963,6 +2223,29 @@ package body Contracts is
return;
end if;
+ -- Otherwise, we generate the postcondition procedure and add
+ -- associated objects and conditions used to coordinate postcondition
+ -- evaluation with finalization.
+
+ -- Generate:
+ --
+ -- procedure _postconditions (Return_Exp : Result_Typ);
+ --
+ -- -- Result_Obj_Type created when Result_Type is non-elementary
+ -- [type Result_Obj_Type is access all Result_Typ;]
+ --
+ -- Result_Obj : Result_Obj_Type;
+ --
+ -- Postcond_Enabled : Boolean := True;
+ -- Return_Success_For_Postcond : Boolean := False;
+ --
+ -- procedure _postconditions (Return_Exp : Result_Typ) is
+ -- begin
+ -- if Postcond_Enabled and then Return_Success_For_Postcond then
+ -- [stmts];
+ -- end if;
+ -- end;
+
Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
Set_Debug_Info_Needed (Proc_Id);
Set_Postconditions_Proc (Subp_Id, Proc_Id);
@@ -2000,12 +2283,14 @@ package body Contracts is
-- body. This ensures that the body will not cause any premature
-- freezing, as it may mention types:
+ -- Generate:
+ --
-- procedure Proc (Obj : Array_Typ) is
-- procedure _postconditions is
-- begin
-- ... Obj ...
-- end _postconditions;
-
+ --
-- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
-- begin
@@ -2017,12 +2302,121 @@ package body Contracts is
Insert_Before_First_Source_Declaration
(Proc_Decl, Declarations (Body_Decl));
Analyze (Proc_Decl);
+ Last_Decl := Proc_Decl;
+
+ -- When Result is present (e.g. the postcondition checks apply to a
+ -- function) we make a local object to capture the result, so, if
+ -- needed, we can call the generated postconditions procedure during
+ -- finalization instead of at the point of return.
+
+ -- Note: The placement of the following declarations before the
+ -- declaration of the body of the postconditions, but after the
+ -- declaration of the postconditions spec is deliberate and required
+ -- since other code within the expander expects them to be located
+ -- here. Perhaps when more space is available in the tree this will
+ -- no longer be necessary ???
+
+ if Present (Result) then
+ -- Elementary result types mean a copy is cheap and preferred over
+ -- using pointers.
+
+ if Is_Elementary_Type (Etype (Result)) then
+ Result_Obj_Type := Etype (Result);
+
+ -- Otherwise, we create a named access type to capture the result
+
+ -- Generate:
+ --
+ -- type Result_Obj_Type is access all [Result_Type];
+
+ else
+ Result_Obj_Type := Make_Temporary (Loc, 'R');
+
+ Result_Obj_Type_Decl :=
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Result_Obj_Type,
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ All_Present => True,
+ Subtype_Indication => New_Occurrence_Of
+ (Etype (Result), Loc)));
+ Insert_After_And_Analyze (Proc_Decl, Result_Obj_Type_Decl);
+ Last_Decl := Result_Obj_Type_Decl;
+ end if;
+
+ -- Create the result obj declaration
+
+ -- Generate:
+ --
+ -- Result_Object_For_Postcond : Result_Obj_Type;
+
+ Result_Obj_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier
+ (Loc, Name_uResult_Object_For_Postcond),
+ Object_Definition =>
+ New_Occurrence_Of
+ (Result_Obj_Type, Loc));
+ Set_No_Initialization (Result_Obj_Decl);
+ Insert_After_And_Analyze (Last_Decl, Result_Obj_Decl);
+ Last_Decl := Result_Obj_Decl;
+ end if;
+
+ -- Build the Postcond_Enabled flag used to delay evaluation of
+ -- postconditions until finalization has been performed when cleanup
+ -- actions are present.
+
+ -- Generate:
+ --
+ -- Postcond_Enabled : Boolean := True;
+
+ Postcond_Enabled_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier
+ (Loc, Name_uPostcond_Enabled),
+ Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
+ Expression => New_Occurrence_Of (Standard_True, Loc));
+ Insert_After_And_Analyze (Last_Decl, Postcond_Enabled_Decl);
+ Last_Decl := Postcond_Enabled_Decl;
+
+ -- Create a flag to indicate that return has been reached
+
+ -- This is necessary for deciding whether to execute _postconditions
+ -- during finalization.
+
+ -- Generate:
+ --
+ -- Return_Success_For_Postcond : Boolean := False;
+
+ Return_Success_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier
+ (Loc, Name_uReturn_Success_For_Postcond),
+ Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
+ Expression => New_Occurrence_Of (Standard_False, Loc));
+ Insert_After_And_Analyze (Last_Decl, Return_Success_Decl);
+ Last_Decl := Return_Success_Decl;
-- Set an explicit End_Label to override the sloc of the implicit
-- RETURN statement, and prevent it from inheriting the sloc of one
-- the postconditions: this would cause confusing debug info to be
-- produced, interfering with coverage-analysis tools.
+ -- Also, wrap the postcondition checks in a conditional which can be
+ -- used to delay their evaluation when clean-up actions are present.
+
+ -- Generate:
+ --
+ -- procedure _postconditions is
+ -- begin
+ -- if Postcond_Enabled and then Return_Success_For_Postcond then
+ -- [Stmts];
+ -- end if;
+ -- end;
+
Proc_Bod :=
Make_Subprogram_Body (Loc,
Specification =>
@@ -2030,10 +2424,22 @@ package body Contracts is
Declarations => Empty_List,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Stmts,
- End_Label => Make_Identifier (Loc, Chars (Proc_Id))));
+ End_Label => Make_Identifier (Loc, Chars (Proc_Id)),
+ Statements => New_List (
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_And_Then (Loc,
+ Left_Opnd =>
+ New_Occurrence_Of
+ (Defining_Identifier
+ (Postcond_Enabled_Decl), Loc),
+ Right_Opnd =>
+ New_Occurrence_Of
+ (Defining_Identifier
+ (Return_Success_Decl), Loc)),
+ Then_Statements => Stmts))));
+ Insert_After_And_Analyze (Last_Decl, Proc_Bod);
- Insert_After_And_Analyze (Proc_Decl, Proc_Bod);
end Build_Postconditions_Procedure;
----------------------------
@@ -2559,8 +2965,7 @@ package body Contracts is
Was_Expression_Function (Body_Decl)
and then Sloc (Body_Id) /= Sloc (Subp_Id)
and then In_Same_Source_Unit (Body_Id, Subp_Id)
- and then List_Containing (Body_Decl) /=
- List_Containing (Subp_Decl);
+ and then not In_Same_List (Body_Decl, Subp_Decl);
if Present (Items) then
Prag := Pre_Post_Conditions (Items);
@@ -2794,30 +3199,39 @@ package body Contracts is
-- Routine _Postconditions holds all contract assertions that must be
-- verified on exit from the related subprogram.
- -- Step 1: Handle all preconditions. This action must come before the
+ -- Step 1: augment contracts list with postconditions associated with
+ -- Stable_Properties and Stable_Properties'Class aspects. This must
+ -- precede Process_Postconditions.
+
+ for Class_Present in Boolean loop
+ Add_Stable_Property_Contracts
+ (Subp_Id, Class_Present => Class_Present);
+ end loop;
+
+ -- Step 2: Handle all preconditions. This action must come before the
-- processing of pragma Contract_Cases because the pragma prepends items
-- to the body declarations.
Process_Preconditions;
- -- Step 2: Handle all postconditions. This action must come before the
+ -- Step 3: Handle all postconditions. This action must come before the
-- processing of pragma Contract_Cases because the pragma appends items
-- to list Stmts.
Process_Postconditions (Stmts);
- -- Step 3: Handle pragma Contract_Cases. This action must come before
+ -- Step 4: Handle pragma Contract_Cases. This action must come before
-- the processing of invariants and predicates because those append
-- items to list Stmts.
Process_Contract_Cases (Stmts);
- -- Step 4: Apply invariant and predicate checks on a function result and
+ -- Step 5: Apply invariant and predicate checks on a function result and
-- all formals. The resulting checks are accumulated in list Stmts.
Add_Invariant_And_Predicate_Checks (Subp_Id, Stmts, Result);
- -- Step 5: Construct procedure _Postconditions
+ -- Step 6: Construct procedure _Postconditions
Build_Postconditions_Procedure (Subp_Id, Stmts, Result);
@@ -2833,7 +3247,10 @@ package body Contracts is
procedure Freeze_Previous_Contracts (Body_Decl : Node_Id) is
function Causes_Contract_Freezing (N : Node_Id) return Boolean;
pragma Inline (Causes_Contract_Freezing);
- -- Determine whether arbitrary node N causes contract freezing
+ -- Determine whether arbitrary node N causes contract freezing. This is
+ -- used as an assertion for the current body declaration that caused
+ -- contract freezing, and as a condition to detect body declaration that
+ -- already caused contract freezing before.
procedure Freeze_Contracts;
pragma Inline (Freeze_Contracts);
@@ -2851,9 +3268,17 @@ package body Contracts is
function Causes_Contract_Freezing (N : Node_Id) return Boolean is
begin
- return Nkind (N) in
- N_Entry_Body | N_Package_Body | N_Protected_Body |
- N_Subprogram_Body | N_Subprogram_Body_Stub | N_Task_Body;
+ -- The following condition matches guards for calls to
+ -- Freeze_Previous_Contracts from routines that analyze various body
+ -- declarations. In particular, it detects expression functions, as
+ -- described in the call from Analyze_Subprogram_Body_Helper.
+
+ return
+ Comes_From_Source (Original_Node (N))
+ and then
+ Nkind (N) in
+ N_Entry_Body | N_Package_Body | N_Protected_Body |
+ N_Subprogram_Body | N_Subprogram_Body_Stub | N_Task_Body;
end Causes_Contract_Freezing;
----------------------
@@ -3013,6 +3438,81 @@ package body Contracts is
Freeze_Contracts;
end Freeze_Previous_Contracts;
+ --------------------------
+ -- Get_Postcond_Enabled --
+ --------------------------
+
+ function Get_Postcond_Enabled (Subp : Entity_Id) return Node_Id is
+ Decl : Node_Id;
+ begin
+ Decl :=
+ Next (Unit_Declaration_Node (Postconditions_Proc (Subp)));
+ while Present (Decl) loop
+
+ if Nkind (Decl) = N_Object_Declaration
+ and then Chars (Defining_Identifier (Decl))
+ = Name_uPostcond_Enabled
+ then
+ return Defining_Identifier (Decl);
+ end if;
+
+ Next (Decl);
+ end loop;
+
+ return Empty;
+ end Get_Postcond_Enabled;
+
+ ------------------------------------
+ -- Get_Result_Object_For_Postcond --
+ ------------------------------------
+
+ function Get_Result_Object_For_Postcond
+ (Subp : Entity_Id) return Node_Id
+ is
+ Decl : Node_Id;
+ begin
+ Decl :=
+ Next (Unit_Declaration_Node (Postconditions_Proc (Subp)));
+ while Present (Decl) loop
+
+ if Nkind (Decl) = N_Object_Declaration
+ and then Chars (Defining_Identifier (Decl))
+ = Name_uResult_Object_For_Postcond
+ then
+ return Defining_Identifier (Decl);
+ end if;
+
+ Next (Decl);
+ end loop;
+
+ return Empty;
+ end Get_Result_Object_For_Postcond;
+
+ -------------------------------------
+ -- Get_Return_Success_For_Postcond --
+ -------------------------------------
+
+ function Get_Return_Success_For_Postcond (Subp : Entity_Id) return Node_Id
+ is
+ Decl : Node_Id;
+ begin
+ Decl :=
+ Next (Unit_Declaration_Node (Postconditions_Proc (Subp)));
+ while Present (Decl) loop
+
+ if Nkind (Decl) = N_Object_Declaration
+ and then Chars (Defining_Identifier (Decl))
+ = Name_uReturn_Success_For_Postcond
+ then
+ return Defining_Identifier (Decl);
+ end if;
+
+ Next (Decl);
+ end loop;
+
+ return Empty;
+ end Get_Return_Success_For_Postcond;
+
---------------------------------
-- Inherit_Subprogram_Contract --
---------------------------------
diff --git a/gcc/ada/contracts.ads b/gcc/ada/contracts.ads
index 4782ef5..b8a12ff 100644
--- a/gcc/ada/contracts.ads
+++ b/gcc/ada/contracts.ads
@@ -188,6 +188,21 @@ package Contracts is
-- denoted by Body_Decl. In addition, freeze the contract of the nearest
-- enclosing package body.
+ function Get_Postcond_Enabled (Subp : Entity_Id) return Entity_Id;
+ -- Get the defining identifier for a subprogram's Postcond_Enabled
+ -- object created during the expansion of the subprogram's postconditions.
+
+ function Get_Result_Object_For_Postcond (Subp : Entity_Id) return Entity_Id;
+ -- Get the defining identifier for a subprogram's
+ -- Result_Object_For_Postcond object created during the expansion of the
+ -- subprogram's postconditions.
+
+ function Get_Return_Success_For_Postcond
+ (Subp : Entity_Id) return Entity_Id;
+ -- Get the defining identifier for a subprogram's
+ -- Return_Success_For_Postcond object created during the expansion of the
+ -- subprogram's postconditions.
+
procedure Inherit_Subprogram_Contract
(Subp : Entity_Id;
From_Subp : Entity_Id);
diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb
index fa335c1..3f5389c 100644
--- a/gcc/ada/cstand.adb
+++ b/gcc/ada/cstand.adb
@@ -1326,6 +1326,12 @@ package body CStand is
Set_Scope (Standard_Integer_64, Standard_Standard);
Build_Signed_Integer_Type (Standard_Integer_64, 64);
+ Standard_Integer_128 := New_Standard_Entity ("integer_128");
+ Decl := New_Node (N_Full_Type_Declaration, Stloc);
+ Set_Defining_Identifier (Decl, Standard_Integer_128);
+ Set_Scope (Standard_Integer_128, Standard_Standard);
+ Build_Signed_Integer_Type (Standard_Integer_128, 128);
+
-- Standard_*_Unsigned subtypes are not user visible, but they are
-- used internally. They are unsigned types with the same length as
-- the correspondingly named signed integer types.
@@ -2068,11 +2074,7 @@ package body CStand is
Build_Float_Type
(Ent, Pos (Digs), Float_Rep, Int (Size), Int (Alignment / 8));
- if No (Back_End_Float_Types) then
- Back_End_Float_Types := New_Elmt_List;
- end if;
-
- Append_Elmt (Ent, Back_End_Float_Types);
+ Append_New_Elmt (Ent, Back_End_Float_Types);
end Register_Float_Type;
----------------------
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index f57b148..2c7c712 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -74,7 +74,7 @@ package body Debug is
-- dN No file name information in exception messages
-- dO Output immediate error messages
-- dP Do not check for controlled objects in preelaborable packages
- -- dQ Use old secondary stack method
+ -- dQ
-- dR Bypass check for correct version of s-rpc
-- dS Never convert numbers to machine numbers in Sem_Eval
-- dT Convert to machine numbers only for constant declarations
@@ -643,11 +643,6 @@ package body Debug is
-- in preelaborable packages, but this restriction is a huge pain,
-- especially in the predefined library units.
- -- dQ Use old method for determining what goes on the secondary stack.
- -- This disables some newer optimizations. The intent is to use this
- -- temporarily to measure before/after efficiency. ???Remove this
- -- when we are done (see Sem_Util.Requires_Transient_Scope).
-
-- dR Bypass the check for a proper version of s-rpc being present
-- to use the -gnatz? switch. This allows debugging of the use
-- of stubs generation without needing to have GLADE (or some
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst b/gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst
index de5efea..6f39de6 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst
@@ -566,7 +566,7 @@ Aspect Unreferenced
This boolean aspect is equivalent to :ref:`pragma Unreferenced<Pragma-Unreferenced>`.
-When using the ``-gnatX`` switch, this aspect is also supported on formal
+When using the ``-gnat2020`` switch, this aspect is also supported on formal
parameters, which is in particular the only form possible for expression
functions.
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
index f98a427..f8d41ea 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
@@ -483,6 +483,19 @@ otherwise. The intended use of this attribute is in conjunction with generic
definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has discriminants.
+Attribute Has_Tagged_Values
+===========================
+.. index:: Tagged values, testing for
+
+.. index:: Has_Tagged_Values
+
+The prefix of the ``Has_Tagged_Values`` attribute is a type. The result is a
+Boolean value which is True if the type is a composite type (array or record)
+that is either a tagged type or has a subcomponent that is tagged, and is False
+otherwise. The intended use of this attribute is in conjunction with generic
+definitions. If the attribute is applied to a generic private type, it
+indicates whether or not the corresponding actual type has access values.
+
Attribute Img
=============
.. index:: Img
@@ -804,8 +817,6 @@ and is static. For non-scalar types, the result is nonstatic.
Attribute Pool_Address
======================
-.. index:: Parameters, when passed by reference
-
.. index:: Pool_Address
``X'Pool_Address`` for any object ``X`` returns the address
@@ -1129,6 +1140,26 @@ for compatibility with Ada 83. See
the Ada 83 reference manual for an exact description of the semantics of
this attribute when applied to floating-point types.
+Attribute Small_Denominator
+===========================
+.. index:: Small
+
+.. index:: Small_Denominator
+
+``typ'Small_Denominator`` for any fixed-point subtype `typ` yields the
+denominator in the representation of ``typ'Small`` as a rational number
+with coprime factors (i.e. as an irreducible fraction).
+
+Attribute Small_Numerator
+=========================
+.. index:: Small
+
+.. index:: Small_Numerator
+
+``typ'Small_Numerator`` for any fixed-point subtype `typ` yields the
+numerator in the representation of ``typ'Small`` as a rational number
+with coprime factors (i.e. as an irreducible fraction).
+
Attribute Storage_Unit
======================
.. index:: Storage_Unit
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst b/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
index 71e1834..10fcfc9 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_characteristics.rst
@@ -147,19 +147,33 @@ Type Representation
*
"The small of an ordinary fixed point type. See 3.5.9(8)."
-``Fine_Delta`` is 2**(-63)
+The small is the largest power of two that does not exceed the delta.
*
"What combinations of small, range, and digits are
supported for fixed point types. See 3.5.9(10)."
-Any combinations are permitted that do not result in a small less than
-``Fine_Delta`` and do not result in a mantissa larger than 63 bits.
-If the mantissa is larger than 53 bits on machines where Long_Long_Float
-is 64 bits (true of all architectures except x86), then the output from
-Text_IO is accurate to only 53 bits, rather than the full mantissa. This
-is because floating-point conversions are used to convert fixed point.
-
+For an ordinary fixed point type, on 32-bit platforms, the small must lie in
+2.0**(-80) .. 2.0**80 and the range in -9.0E+36 .. 9.0E+36; any combination
+is permitted that does not result in a mantissa larger than 63 bits.
+
+On 64-bit platforms, the small must lie in 2.0**(-127) .. 2.0**127 and the
+range in -1.0E+76 .. 1.0E+76; any combination is permitted that does not
+result in a mantissa larger than 63 bits, and any combination is permitted
+that results in a mantissa between 64 and 127 bits if the small is the
+ratio of two integers that lie in 1 .. 2.0**127.
+
+If the small is the ratio of two integers with 64-bit magnitude on 32-bit
+platforms and 128-bit magnitude on 64-bit platforms, which is the case if
+no ``small`` clause is provided, then the operations of the fixed point
+type are entirely implemented by means of integer instructions. In the
+other cases, some operations, in particular input and output, may be
+implemented by means of floating-point instructions and may be affected
+by accuracy issues on architectures other than x86.
+
+For a decimal fixed point type, on 32-bit platforms, the small must lie in
+1.0E-18 .. 1.0E+18 and the digits in 1 .. 18. On 64-bit platforms, the
+small must lie in 1.0E-38 .. 1.0E+38 and the digits in 1 .. 38.
*
"The result of ``Tags.Expanded_Name`` for types declared
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
index e1e6853..74b9718 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
@@ -434,15 +434,16 @@ Syntax::
ASSERTION_KIND ::= RM_ASSERTION_KIND | ID_ASSERTION_KIND
- RM_ASSERTION_KIND ::= Assert |
- Static_Predicate |
- Dynamic_Predicate |
- Pre |
- Pre'Class |
- Post |
- Post'Class |
- Type_Invariant |
- Type_Invariant'Class
+ RM_ASSERTION_KIND ::= Assert |
+ Static_Predicate |
+ Dynamic_Predicate |
+ Pre |
+ Pre'Class |
+ Post |
+ Post'Class |
+ Type_Invariant |
+ Type_Invariant'Class |
+ Default_Initial_Condition
ID_ASSERTION_KIND ::= Assertions |
Assert_And_Cut |
@@ -450,6 +451,7 @@ Syntax::
Contract_Cases |
Debug |
Ghost |
+ Initial_Condition |
Invariant |
Invariant'Class |
Loop_Invariant |
@@ -458,7 +460,8 @@ Syntax::
Precondition |
Predicate |
Refined_Post |
- Statement_Assertions
+ Statement_Assertions |
+ Subprogram_Variant
POLICY_IDENTIFIER ::= Check | Disable | Ignore | Suppressible
@@ -5079,7 +5082,7 @@ Syntax:
.. code-block:: ada
- pragma Profile (Ravenscar | Restricted | Rational |
+ pragma Profile (Ravenscar | Restricted | Rational | Jorvik |
GNAT_Extended_Ravenscar | GNAT_Ravenscar_EDF );
@@ -5087,10 +5090,12 @@ This pragma is standard in Ada 2005, but is available in all earlier
versions of Ada as an implementation-defined pragma. This is a
configuration pragma that establishes a set of configuration pragmas
that depend on the argument. ``Ravenscar`` is standard in Ada 2005.
+``Jorvik`` is standard in Ada 202x.
The other possibilities (``Restricted``, ``Rational``,
``GNAT_Extended_Ravenscar``, ``GNAT_Ravenscar_EDF``)
-are implementation-defined. The set of configuration pragmas
-is defined in the following sections.
+are implementation-defined. ``GNAT_Extended_Ravenscar`` is an alias for ``Jorvik``.
+
+The set of configuration pragmas is defined in the following sections.
* Pragma Profile (Ravenscar)
@@ -5160,7 +5165,7 @@ is defined in the following sections.
* ``Simple_Barriers``
The Ravenscar profile also includes the following restrictions that specify
- that there are no semantic dependences on the corresponding predefined
+ that there are no semantic dependencies on the corresponding predefined
packages:
* ``No_Dependence => Ada.Asynchronous_Task_Control``
@@ -5201,12 +5206,10 @@ is defined in the following sections.
automatically causes the use of a simplified,
more efficient version of the tasking run-time library.
-* Pragma Profile (GNAT_Extended_Ravenscar)
+* Pragma Profile (Jorvik)
- This profile corresponds to a GNAT specific extension of the
- Ravenscar profile. The profile may change in the future although
- only in a compatible way: some restrictions may be removed or
- relaxed. It is defined as a variation of the Ravenscar profile.
+ ``Jorvik`` is the new profile added to the Ada 202x draft standard,
+ previously implemented under the name ``GNAT_Extended_Ravenscar``.
The ``No_Implicit_Heap_Allocations`` restriction has been replaced
by ``No_Implicit_Task_Allocations`` and
@@ -5218,6 +5221,13 @@ is defined in the following sections.
The ``Max_Protected_Entries``, ``Max_Entry_Queue_Length``, and
``No_Relative_Delay`` restrictions have been removed.
+ Details on the rationale for ``Jorvik`` and implications for use may be
+ found in :title:`A New Ravenscar-Based Profile` by P. Rogers, J. Ruiz,
+ T. Gingold and P. Bernardi, in :title:`Reliable Software Technologies --
+ Ada Europe 2017`, Springer-Verlag Lecture Notes in Computer Science,
+ Number 10300.
+
+
* Pragma Profile (GNAT_Ravenscar_EDF)
This profile corresponds to the Ravenscar profile but using
@@ -6642,8 +6652,8 @@ expression. The following is an example of use within a package spec:
function Sqrt (Arg : Float) return Float;
pragma Test_Case (Name => "Test 1",
Mode => Nominal,
- Requires => Arg < 10000,
- Ensures => Sqrt'Result < 10);
+ Requires => Arg < 10000.0,
+ Ensures => Sqrt'Result < 10.0);
...
end Math_Functions;
diff --git a/gcc/ada/doc/gnat_rm/intrinsic_subprograms.rst b/gcc/ada/doc/gnat_rm/intrinsic_subprograms.rst
index bf9f0b9e..e448816 100644
--- a/gcc/ada/doc/gnat_rm/intrinsic_subprograms.rst
+++ b/gcc/ada/doc/gnat_rm/intrinsic_subprograms.rst
@@ -217,7 +217,9 @@ The formal parameter names can be anything.
A more convenient way of providing these shift operators is to use
the Provide_Shift_Operators pragma, which provides the function declarations
-and corresponding pragma Import's for all five shift functions.
+and corresponding pragma Import's for all five shift functions. Note that in
+using these provided shift operations, shifts performed on negative numbers
+will result in modification of the sign bit.
.. _Source_Location:
diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
index 1dec487..82e992a 100644
--- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -1517,6 +1517,13 @@ Alphabetical List of All Switches
an exception because ``Self(Obj)`` produces an anonymous object which does
not share the memory location of ``Obj``.
+.. index:: -gnateb (gcc)
+
+:switch:`-gnateb`
+ Store configuration files by their basename in ALI files. This switch is
+ used for instance by gprbuild for distributed builds in order to prevent
+ issues where machine-specific absolute paths could end up being stored in
+ ALI files.
.. index:: -gnatec (gcc)
@@ -3337,7 +3344,7 @@ of the pragma in the :title:`GNAT_Reference_manual`).
:switch:`-gnatw.K`
*Suppress warnings on redefinition of names in standard.*
- This switch activates warnings for declarations that declare a name that
+ This switch disables warnings for declarations that declare a name that
is defined in package Standard.
@@ -4807,7 +4814,8 @@ checks to be performed. The following checks are defined:
All keywords must be in lower case (with the exception of keywords
such as ``digits`` used as attribute names to which this check
- does not apply).
+ does not apply). A single error is reported for each line breaking
+ this rule even if multiple casing issues exist on a same line.
.. index:: -gnatyl (gcc)
@@ -6703,6 +6711,9 @@ be presented in subsequent sections.
Use the target-independent XDR protocol for stream oriented attributes
instead of the default implementation which is based on direct binary
representations and is therefore target-and endianness-dependent.
+ However it does not support 128-bit integer types and the exception
+ ``Ada.IO_Exceptions.Device_Error`` is raised if any attempt is made
+ at streaming 128-bit integer types with it.
.. index:: -Xnnn (gnatbind)
diff --git a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
index ba2c9b6..c4f186e 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
@@ -1840,7 +1840,7 @@ improves performance for your program.
.. _Floating_Point_Operations:
-Floating_Point_Operations
+Floating Point Operations
^^^^^^^^^^^^^^^^^^^^^^^^^
.. index:: Floating-Point Operations
diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
index 5c51222..f152ce3 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
@@ -1920,8 +1920,8 @@ building specialized scripts.
:switch:`--comments-fill`
- Fill comment blocks. This is the default.
- Use :switch:`--no-comments-fill` to turn off filling.
+ Fill comment blocks.
+ The default is :switch:`--no-comments-fill`.
:switch:`--comments-special`
diff --git a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
index 2f0e10c..46d589a 100644
--- a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
+++ b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst
@@ -1560,6 +1560,10 @@ temporary files that are immediately deleted; it doesn't make sense to
depend on a file that no longer exists. Such tools include
``gprbuild``, ``gnatmake``, and ``gnatcheck``.
+By default, configuration pragma files are stored by their absolute paths in
+ALI files. You can use the :switch:`-gnateb` switch in order to store them by
+their basename instead.
+
If you are using project file, a separate mechanism is provided using
project attributes.
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index f39b3bc..8c401ca 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -2543,6 +2543,29 @@ package body Einfo is
return Flag215 (Base_Type (Id));
end Is_Param_Block_Component_Type;
+ function Is_Partial_DIC_Procedure (Id : E) return B is
+ Partial_DIC_Suffix : constant String := "Partial_DIC";
+ DIC_Nam : constant String := Get_Name_String (Chars (Id));
+
+ begin
+ pragma Assert (Ekind (Id) in E_Function | E_Procedure);
+
+ -- Instead of adding a new Entity_Id flag (which are in short supply),
+ -- we test the form of the subprogram name. When the node field and flag
+ -- situation is eased, this should be replaced with a flag. ???
+
+ if DIC_Nam'Length > Partial_DIC_Suffix'Length
+ and then
+ DIC_Nam
+ (DIC_Nam'Last - Partial_DIC_Suffix'Length + 1 .. DIC_Nam'Last) =
+ Partial_DIC_Suffix
+ then
+ return True;
+ else
+ return False;
+ end if;
+ end Is_Partial_DIC_Procedure;
+
function Is_Partial_Invariant_Procedure (Id : E) return B is
begin
pragma Assert (Ekind (Id) in E_Function | E_Procedure);
@@ -3040,7 +3063,7 @@ package body Einfo is
function Overridden_Operation (Id : E) return E is
begin
- pragma Assert (Is_Subprogram (Id) or else Is_Generic_Subprogram (Id));
+ pragma Assert (Is_Subprogram_Or_Generic_Subprogram (Id));
return Node26 (Id);
end Overridden_Operation;
@@ -3133,7 +3156,7 @@ package body Einfo is
function Protected_Body_Subprogram (Id : E) return E is
begin
- pragma Assert (Is_Subprogram (Id) or else Is_Entry (Id));
+ pragma Assert (Is_Subprogram_Or_Entry (Id));
return Node11 (Id);
end Protected_Body_Subprogram;
@@ -3202,7 +3225,8 @@ package body Einfo is
function Related_Expression (Id : E) return N is
begin
- pragma Assert (Ekind (Id) in Type_Kind | E_Constant | E_Variable);
+ pragma Assert
+ (Ekind (Id) in Type_Kind | E_Constant | E_Variable | E_Function);
return Node24 (Id);
end Related_Expression;
@@ -4914,7 +4938,7 @@ package body Einfo is
procedure Set_Has_Out_Or_In_Out_Parameter (Id : E; V : B := True) is
begin
pragma Assert
- (Ekind (Id) in E_Entry | E_Entry_Family
+ (Is_Entry (Id)
or else Is_Subprogram_Or_Generic_Subprogram (Id));
Set_Flag110 (Id, V);
end Set_Has_Out_Or_In_Out_Parameter;
@@ -6201,7 +6225,7 @@ package body Einfo is
procedure Set_No_Return (Id : E; V : B := True) is
begin
- pragma Assert (Is_Subprogram (Id) or else Is_Generic_Subprogram (Id));
+ pragma Assert (Is_Subprogram_Or_Generic_Subprogram (Id));
Set_Flag113 (Id, V);
end Set_No_Return;
@@ -6308,7 +6332,7 @@ package body Einfo is
procedure Set_Overridden_Operation (Id : E; V : E) is
begin
- pragma Assert (Is_Subprogram (Id) or else Is_Generic_Subprogram (Id));
+ pragma Assert (Is_Subprogram_Or_Generic_Subprogram (Id));
Set_Node26 (Id, V);
end Set_Overridden_Operation;
@@ -6406,7 +6430,7 @@ package body Einfo is
procedure Set_Protected_Body_Subprogram (Id : E; V : E) is
begin
- pragma Assert (Is_Subprogram (Id) or else Is_Entry (Id));
+ pragma Assert (Is_Subprogram_Or_Entry (Id));
Set_Node11 (Id, V);
end Set_Protected_Body_Subprogram;
@@ -6478,7 +6502,8 @@ package body Einfo is
procedure Set_Related_Expression (Id : E; V : N) is
begin
pragma Assert
- (Ekind (Id) in Type_Kind | E_Constant | E_Variable | E_Void);
+ (Ekind (Id) in
+ Type_Kind | E_Constant | E_Variable | E_Function | E_Void);
Set_Node24 (Id, V);
end Set_Related_Expression;
@@ -6777,7 +6802,9 @@ package body Einfo is
procedure Set_Stores_Attribute_Old_Prefix (Id : E; V : B := True) is
begin
- pragma Assert (Ekind (Id) = E_Constant);
+ pragma Assert (Is_Type (Id)
+ or else (Ekind (Id) in E_Constant
+ | E_Variable));
Set_Flag270 (Id, V);
end Set_Stores_Attribute_Old_Prefix;
@@ -7358,7 +7385,7 @@ package body Einfo is
---------------------
function Designated_Type (Id : E) return E is
- Desig_Type : E;
+ Desig_Type : Entity_Id;
begin
Desig_Type := Directly_Designated_Type (Id);
@@ -7399,7 +7426,13 @@ package body Einfo is
while Present (Subp_Elmt) loop
Subp_Id := Node (Subp_Elmt);
- if Is_DIC_Procedure (Subp_Id) then
+ -- Currently the flag Is_DIC_Procedure is set for both normal DIC
+ -- check procedures as well as for partial DIC check procedures,
+ -- and we don't have a flag for the partial procedures.
+
+ if Is_DIC_Procedure (Subp_Id)
+ and then not Is_Partial_DIC_Procedure (Subp_Id)
+ then
return Subp_Id;
end if;
@@ -7425,7 +7458,7 @@ package body Einfo is
---------------------
function First_Component (Id : E) return E is
- Comp_Id : E;
+ Comp_Id : Entity_Id;
begin
pragma Assert
@@ -7447,7 +7480,7 @@ package body Einfo is
-------------------------------------
function First_Component_Or_Discriminant (Id : E) return E is
- Comp_Id : E;
+ Comp_Id : Entity_Id;
begin
pragma Assert
@@ -7470,7 +7503,7 @@ package body Einfo is
------------------
function First_Formal (Id : E) return E is
- Formal : E;
+ Formal : Entity_Id;
begin
pragma Assert
@@ -7511,7 +7544,7 @@ package body Einfo is
------------------------------
function First_Formal_With_Extras (Id : E) return E is
- Formal : E;
+ Formal : Entity_Id;
begin
pragma Assert
@@ -8152,9 +8185,7 @@ package body Einfo is
begin
-- Identifiers, operator symbols, expanded names are entity names
- return Kind = N_Identifier
- or else Kind = N_Operator_Symbol
- or else Kind = N_Expanded_Name
+ return Kind in N_Identifier | N_Operator_Symbol | N_Expanded_Name
-- Attribute references are entity names if they refer to an entity.
-- Note that we don't do this by testing for the presence of the
@@ -8173,10 +8204,9 @@ package body Einfo is
begin
return
Ekind (Id) in E_Constant | E_Package | E_Variable
- or else Is_Entry (Id)
- or else Is_Generic_Unit (Id)
- or else Is_Subprogram (Id)
- or else Is_Task_Type (Id);
+ or else Is_Generic_Unit (Id)
+ or else Is_Subprogram_Or_Entry (Id)
+ or else Is_Task_Type (Id);
end Is_Elaboration_Target;
-----------------------
@@ -8307,21 +8337,10 @@ package body Einfo is
function Is_Standard_Character_Type (Id : E) return B is
begin
- if Is_Type (Id) then
- declare
- R : constant Entity_Id := Root_Type (Id);
- begin
- return
- R = Standard_Character
- or else
- R = Standard_Wide_Character
- or else
- R = Standard_Wide_Wide_Character;
- end;
-
- else
- return False;
- end if;
+ return Is_Type (Id)
+ and then Root_Type (Id) in Standard_Character
+ | Standard_Wide_Character
+ | Standard_Wide_Wide_Character;
end Is_Standard_Character_Type;
-----------------------------
@@ -8330,21 +8349,10 @@ package body Einfo is
function Is_Standard_String_Type (Id : E) return B is
begin
- if Is_Type (Id) then
- declare
- R : constant Entity_Id := Root_Type (Id);
- begin
- return
- R = Standard_String
- or else
- R = Standard_Wide_String
- or else
- R = Standard_Wide_Wide_String;
- end;
-
- else
- return False;
- end if;
+ return Is_Type (Id)
+ and then Root_Type (Id) in Standard_String
+ | Standard_Wide_String
+ | Standard_Wide_Wide_String;
end Is_Standard_String_Type;
--------------------
@@ -8435,7 +8443,7 @@ package body Einfo is
-----------------
function Last_Formal (Id : E) return E is
- Formal : E;
+ Formal : Entity_Id;
begin
pragma Assert
@@ -8452,7 +8460,7 @@ package body Einfo is
if Present (Formal) then
while Present (Next_Formal (Formal)) loop
- Formal := Next_Formal (Formal);
+ Next_Formal (Formal);
end loop;
end if;
@@ -8591,7 +8599,7 @@ package body Einfo is
--------------------
function Next_Component (Id : E) return E is
- Comp_Id : E;
+ Comp_Id : Entity_Id;
begin
Comp_Id := Next_Entity (Id);
@@ -8608,7 +8616,7 @@ package body Einfo is
------------------------------------
function Next_Component_Or_Discriminant (Id : E) return E is
- Comp_Id : E;
+ Comp_Id : Entity_Id;
begin
Comp_Id := Next_Entity (Id);
@@ -8667,7 +8675,7 @@ package body Einfo is
-----------------
function Next_Formal (Id : E) return E is
- P : E;
+ P : Entity_Id;
begin
-- Follow the chain of declared entities as long as the kind of the
@@ -8815,6 +8823,36 @@ package body Einfo is
return Ekind (Id);
end Parameter_Mode;
+ ---------------------------
+ -- Partial_DIC_Procedure --
+ ---------------------------
+
+ function Partial_DIC_Procedure (Id : E) return E is
+ Subp_Elmt : Elmt_Id;
+ Subp_Id : Entity_Id;
+ Subps : Elist_Id;
+
+ begin
+ pragma Assert (Is_Type (Id));
+
+ Subps := Subprograms_For_Type (Base_Type (Id));
+
+ if Present (Subps) then
+ Subp_Elmt := First_Elmt (Subps);
+ while Present (Subp_Elmt) loop
+ Subp_Id := Node (Subp_Elmt);
+
+ if Is_Partial_DIC_Procedure (Subp_Id) then
+ return Subp_Id;
+ end if;
+
+ Next_Elmt (Subp_Elmt);
+ end loop;
+ end if;
+
+ return Empty;
+ end Partial_DIC_Procedure;
+
---------------------------------
-- Partial_Invariant_Procedure --
---------------------------------
@@ -9131,7 +9169,7 @@ package body Einfo is
---------------
function Root_Type (Id : E) return E is
- T, Etyp : E;
+ T, Etyp : Entity_Id;
begin
pragma Assert (Nkind (Id) in N_Entity);
@@ -9294,8 +9332,6 @@ package body Einfo is
procedure Set_DIC_Procedure (Id : E; V : E) is
Base_Typ : Entity_Id;
- Subp_Elmt : Elmt_Id;
- Subp_Id : Entity_Id;
Subps : Elist_Id;
begin
@@ -9309,21 +9345,17 @@ package body Einfo is
Set_Subprograms_For_Type (Base_Typ, Subps);
end if;
- Subp_Elmt := First_Elmt (Subps);
Prepend_Elmt (V, Subps);
+ end Set_DIC_Procedure;
- -- Check for a duplicate default initial condition procedure
-
- while Present (Subp_Elmt) loop
- Subp_Id := Node (Subp_Elmt);
-
- if Is_DIC_Procedure (Subp_Id) then
- raise Program_Error;
- end if;
+ -------------------------------------
+ -- Set_Partial_Invariant_Procedure --
+ -------------------------------------
- Next_Elmt (Subp_Elmt);
- end loop;
- end Set_DIC_Procedure;
+ procedure Set_Partial_DIC_Procedure (Id : E; V : E) is
+ begin
+ Set_DIC_Procedure (Id, V);
+ end Set_Partial_DIC_Procedure;
-----------------------------
-- Set_Invariant_Procedure --
@@ -10122,7 +10154,7 @@ package body Einfo is
when Array_Kind =>
declare
- Index : E;
+ Index : Entity_Id;
begin
Write_Attribute
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index be195ab..cc0c815 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -420,8 +420,10 @@ package Einfo is
-- output of certain warnings.
-- Aft_Value (synthesized)
--- Applies to fixed and decimal types. Computes a universal integer that
--- holds value of the Aft attribute for the type.
+-- Applies to fixed-point types and subtypes. This yields the value of
+-- the Aft attribute for the type, i.e. the number of decimal digits
+-- needed after the decimal point to accommodate the delta of the type,
+-- unless the delta is greater than 0.1, in which case it is 1.
-- Alias (Node18)
-- Defined in overloadable entities (literals, subprograms, entries) and
@@ -3930,6 +3932,20 @@ package Einfo is
-- of a single protected/task type, the references are examined as they
-- must appear only within the type defintion and the corresponding body.
+-- Partial_DIC_Procedure (synthesized)
+-- Defined in type entities. Set for a private type and its full view
+-- when the type is subject to pragma Default_Initial_Condition (DIC), or
+-- when the type inherits a DIC pragma from a parent type. Points to the
+-- entity of a procedure that takes a single argument of the given type
+-- and verifies the assertion expression of the DIC pragma at run time.
+-- When present, the Partial_DIC_Procedure of a type only checks DICs
+-- associated with the partial (private) view of the type, and is invoked
+-- by the full DIC_Procedure (which may check additional DICs associated
+-- with the full view).
+
+-- Note: the reason this is marked as a synthesized attribute is that the
+-- way this is stored is as an element of the Subprograms_For_Type field.
+
-- Partial_Invariant_Procedure (synthesized)
-- Defined in types and subtypes. Set for private types when one or more
-- [class-wide] type invariants apply to them. Points to the entity for a
@@ -4115,14 +4131,16 @@ package Einfo is
-- only for type-related error messages.
-- Related_Expression (Node24)
--- Defined in variables and types. When Set for internally generated
--- entities, it may be used to denote the source expression whose
--- elaboration created the variable declaration. If set, it is used
+-- Defined in variables, types and functions. When Set for internally
+-- generated entities, it may be used to denote the source expression
+-- whose elaboration created the variable declaration. If set, it is used
-- for generating clearer messages from CodePeer. It is used on source
-- entities that are variables in iterator specifications, to provide
-- a link to the container that is the domain of iteration. This allows
-- for better cross-reference information when the loop modifies elements
-- of the container, and suppresses spurious warnings.
+-- Finally this node is used on functions specified via the Real_Literal
+-- aspect, to denote the 2-parameter overloading, if found.
--
-- Shouldn't it also be used for the same purpose in errout? It seems
-- odd to have two mechanisms here???
@@ -4261,9 +4279,10 @@ package Einfo is
-- explicit range).
-- Scale_Value (Uint16)
--- Defined in decimal fixed-point types and subtypes. Contains the scale
--- for the type (i.e. the value of type'Scale = the number of decimal
--- digits after the decimal point).
+-- Defined in decimal fixed-point types and subtypes. This holds the
+-- value of the Scale attribute for the type, i.e. the scale of the type
+-- defined as the integer N such that the delta is equal to 10.0**(-N).
+-- Note that, if Scale_Value is positive, then it is equal to Aft_Value.
-- Scope (Node3)
-- Defined in all entities. Points to the entity for the scope (block,
@@ -4484,8 +4503,8 @@ package Einfo is
-- stored discriminants for the record (sub)type.
-- Stores_Attribute_Old_Prefix (Flag270)
--- Defined in constants. Set when the constant has been generated to save
--- the value of attribute 'Old's prefix.
+-- Defined in constants, variables, and types which are created during
+-- expansion in order to save the value of attribute 'Old's prefix.
-- Strict_Alignment (Flag145) [implementation base type only]
-- Defined in all type entities. Indicates that the type is by-reference
@@ -4591,15 +4610,13 @@ package Einfo is
-- Applies to scalar types. Returns the tree node (Node_Id) that contains
-- the high bound of a scalar type. The returned value is literal for a
-- base type, but may be an expression in the case of scalar type with
--- dynamic bounds. Note that in the case of a fixed point type, the high
--- bound is in units of small, and is an integer.
+-- dynamic bounds.
-- Type_Low_Bound (synthesized)
-- Applies to scalar types. Returns the tree node (Node_Id) that contains
-- the low bound of a scalar type. The returned value is literal for a
-- base type, but may be an expression in the case of scalar type with
--- dynamic bounds. Note that in the case of a fixed point type, the low
--- bound is in units of small, and is an integer.
+-- dynamic bounds.
-- Underlying_Full_View (Node19)
-- Defined in private subtypes that are the completion of other private
@@ -5818,6 +5835,7 @@ package Einfo is
-- Is_Full_Access (synth)
-- Is_Controlled (synth)
-- Object_Size_Clause (synth)
+ -- Partial_DIC_Procedure (synth)
-- Partial_Invariant_Procedure (synth)
-- Predicate_Function (synth)
-- Predicate_Function_M (synth)
@@ -6583,6 +6601,7 @@ package Einfo is
-- Is_Invariant_Procedure (Flag257) (non-generic case only)
-- Is_Machine_Code_Subprogram (Flag137) (non-generic case only)
-- Is_Null_Init_Proc (Flag178)
+ -- Is_Partial_DIC_Procedure (synth) (non-generic case only)
-- Is_Partial_Invariant_Procedure (Flag292) (non-generic case only)
-- Is_Predicate_Function (Flag255) (non-generic case only)
-- Is_Predicate_Function_M (Flag256) (non-generic case only)
@@ -7402,6 +7421,7 @@ package Einfo is
function Is_Packed_Array_Impl_Type (Id : E) return B;
function Is_Potentially_Use_Visible (Id : E) return B;
function Is_Param_Block_Component_Type (Id : E) return B;
+ function Is_Partial_DIC_Procedure (Id : E) return B;
function Is_Partial_Invariant_Procedure (Id : E) return B;
function Is_Predicate_Function (Id : E) return B;
function Is_Predicate_Function_M (Id : E) return B;
@@ -8306,12 +8326,14 @@ package Einfo is
---------------------------------------------------
function DIC_Procedure (Id : E) return E;
+ function Partial_DIC_Procedure (Id : E) return E;
function Invariant_Procedure (Id : E) return E;
function Partial_Invariant_Procedure (Id : E) return E;
function Predicate_Function (Id : E) return E;
function Predicate_Function_M (Id : E) return E;
procedure Set_DIC_Procedure (Id : E; V : E);
+ procedure Set_Partial_DIC_Procedure (Id : E; V : E);
procedure Set_Invariant_Procedure (Id : E; V : E);
procedure Set_Partial_Invariant_Procedure (Id : E; V : E);
procedure Set_Predicate_Function (Id : E; V : E);
diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb
index 049db89..cc291c6 100644
--- a/gcc/ada/errout.adb
+++ b/gcc/ada/errout.adb
@@ -337,7 +337,7 @@ package body Errout is
begin
-- Return if all errors are to be ignored
- if Errors_Must_Be_Ignored then
+ if Get_Ignore_Errors then
return;
end if;
@@ -612,6 +612,25 @@ package body Errout is
end;
end Error_Msg;
+ ----------------------------------
+ -- Error_Msg_Ada_2005_Extension --
+ ----------------------------------
+
+ procedure Error_Msg_Ada_2005_Extension (Extension : String) is
+ Loc : constant Source_Ptr := Token_Ptr;
+ begin
+ if Ada_Version < Ada_2005 then
+ Error_Msg (Extension & " is an Ada 2005 extension", Loc);
+
+ if No (Ada_Version_Pragma) then
+ Error_Msg ("\unit must be compiled with -gnat05 switch", Loc);
+ else
+ Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
+ Error_Msg ("\incompatible with Ada version set#", Loc);
+ end if;
+ end if;
+ end Error_Msg_Ada_2005_Extension;
+
--------------------------------
-- Error_Msg_Ada_2012_Feature --
--------------------------------
@@ -1430,7 +1449,9 @@ package body Errout is
Last_Killed := True;
end if;
- Set_Posted (N);
+ if not Get_Ignore_Errors then
+ Set_Posted (N);
+ end if;
end Error_Msg_NEL;
------------------
diff --git a/gcc/ada/errout.ads b/gcc/ada/errout.ads
index e46433f..02cfdee 100644
--- a/gcc/ada/errout.ads
+++ b/gcc/ada/errout.ads
@@ -381,12 +381,11 @@ package Errout is
-- continuations are being gathered into a single message.
-- Insertion character | (Vertical bar: non-serious error)
- -- By default, error messages (other than warning messages) are
- -- considered to be fatal error messages which prevent expansion or
- -- generation of code in the presence of the -gnatQ switch. If the
- -- insertion character | appears, the message is considered to be
- -- non-serious, and does not cause Serious_Errors_Detected to be
- -- incremented (so expansion is not prevented by such a msg). This
+ -- By default, error messages (but not warning messages) are considered
+ -- to be fatal error messages, which prevent expansion and generation
+ -- of code. If the insertion character | appears, the message is
+ -- considered to be nonserious, and Serious_Errors_Detected is not
+ -- incremented, so expansion is not prevented by such a msg. This
-- insertion character is ignored in continuation messages.
-- Insertion character ~ (Tilde: insert string)
@@ -903,6 +902,11 @@ package Errout is
-- overridden interface primitive Iface_Prim) indicating wrong mode of the
-- first formal (RM 9.4(11.9/3)).
+ procedure Error_Msg_Ada_2005_Extension (Extension : String);
+ -- Analogous to Error_Msg_Ada_2012_Feature, but phrase the message using
+ -- "extension" and not "feature". This routine is only used in the parser,
+ -- so the error is always placed at the Token_Ptr.
+
procedure Error_Msg_Ada_2012_Feature (Feature : String; Loc : Source_Ptr);
-- If not operating in Ada 2012 mode or higher, posts errors complaining
-- that Feature is only supported in Ada 2012, with appropriate suggestions
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 469777f..d7e5470 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -1895,6 +1895,22 @@ package body Exp_Aggr is
Append_To (Stmts, Init_Call);
end if;
end if;
+
+ -- If Default_Initial_Condition applies to the component type,
+ -- add a DIC check after the component is default-initialized,
+ -- as well as after an Initialize procedure is called, in the
+ -- case of components of a controlled type. It will be analyzed
+ -- and resolved before the code for initialization of other
+ -- components.
+
+ -- Theoretically this might also be needed for cases where Expr
+ -- is not empty, but a default init still applies, such as for
+ -- Default_Value cases, in which case we won't get here. ???
+
+ if Has_DIC (Ctype) and then Present (DIC_Procedure (Ctype)) then
+ Append_To (Stmts,
+ Build_DIC_Call (Loc, New_Copy_Tree (Indexed_Comp), Ctype));
+ end if;
end if;
return Add_Loop_Actions (Stmts);
@@ -2448,18 +2464,30 @@ package body Exp_Aggr is
Next (Expr);
end loop;
- -- STEP 2 (b): Generate final loop if an others choice is present
+ -- STEP 2 (b): Generate final loop if an others choice is present.
-- Here Nb_Elements gives the offset of the last positional element.
if Present (Component_Associations (N)) then
Assoc := Last (Component_Associations (N));
- -- Ada 2005 (AI-287)
+ if Nkind (Assoc) = N_Iterated_Component_Association then
+ -- Ada 2020: generate a loop to have a proper scope for
+ -- the identifier that typically appears in the expression.
+ -- The lower bound of the loop is the position after all
+ -- previous positional components.
- Append_List (Gen_While (Add (Nb_Elements, To => Aggr_L),
- Aggr_High,
- Get_Assoc_Expr (Assoc)), -- AI-287
- To => New_Code);
+ Append_List (Gen_Loop (Add (Nb_Elements + 1, To => Aggr_L),
+ Aggr_High,
+ Expression (Assoc)),
+ To => New_Code);
+ else
+ -- Ada 2005 (AI-287)
+
+ Append_List (Gen_While (Add (Nb_Elements, To => Aggr_L),
+ Aggr_High,
+ Get_Assoc_Expr (Assoc)),
+ To => New_Code);
+ end if;
end if;
end if;
@@ -3492,6 +3520,18 @@ package body Exp_Aggr is
then
Check_Ancestor_Discriminants (Entity (Ancestor));
end if;
+
+ -- If ancestor type has Default_Initialization_Condition,
+ -- add a DIC check after the ancestor object is initialized
+ -- by default.
+
+ if Has_DIC (Entity (Ancestor))
+ and then Present (DIC_Procedure (Entity (Ancestor)))
+ then
+ Append_To (L,
+ Build_DIC_Call
+ (Loc, New_Copy_Tree (Ref), Entity (Ancestor)));
+ end if;
end if;
-- Handle calls to C++ constructors
@@ -4097,6 +4137,22 @@ package body Exp_Aggr is
end;
end if;
+ -- If the component association was specified with a box and the
+ -- component type has a Default_Initial_Condition, then generate
+ -- a call to the DIC procedure.
+
+ if Has_DIC (Etype (Selector))
+ and then Was_Default_Init_Box_Association (Comp)
+ and then Present (DIC_Procedure (Etype (Selector)))
+ then
+ Append_To (L,
+ Build_DIC_Call (Loc,
+ Make_Selected_Component (Loc,
+ Prefix => New_Copy_Tree (Target),
+ Selector_Name => New_Occurrence_Of (Selector, Loc)),
+ Etype (Selector)));
+ end if;
+
Next (Comp);
end loop;
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index d3468d5..7f63a2d 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -67,6 +67,7 @@ with Tbuild; use Tbuild;
with Ttypes; use Ttypes;
with Uintp; use Uintp;
with Uname; use Uname;
+with Urealp; use Urealp;
with Validsw; use Validsw;
package body Exp_Attr is
@@ -1209,7 +1210,7 @@ package body Exp_Attr is
-- by Expand_Fpt_Attribute
procedure Expand_Fpt_Attribute_R (N : Node_Id) is
- E1 : constant Node_Id := First (Expressions (N));
+ E1 : constant Node_Id := First (Expressions (N));
Ftp : Entity_Id;
Pkg : RE_Id;
begin
@@ -1229,10 +1230,10 @@ package body Exp_Attr is
-- by Expand_Fpt_Attribute
procedure Expand_Fpt_Attribute_RI (N : Node_Id) is
- E1 : constant Node_Id := First (Expressions (N));
+ E1 : constant Node_Id := First (Expressions (N));
+ E2 : constant Node_Id := Next (E1);
Ftp : Entity_Id;
Pkg : RE_Id;
- E2 : constant Node_Id := Next (E1);
begin
Find_Fat_Info (Etype (E1), Ftp, Pkg);
Expand_Fpt_Attribute
@@ -2822,7 +2823,7 @@ package body Exp_Attr is
Id_Kind : constant Entity_Id := RTE (RO_AT_Task_Id);
Ent : constant Entity_Id := Entity (Pref);
Conctype : constant Entity_Id := Scope (Ent);
- Nest_Depth : Integer := 0;
+ Nest_Depth : Nat := 0;
Name : Node_Id;
S : Entity_Id;
@@ -2885,7 +2886,7 @@ package body Exp_Attr is
New_Occurrence_Of (RTE (RE_Task_Entry_Caller), Loc),
Parameter_Associations => New_List (
Make_Integer_Literal (Loc,
- Intval => Int (Nest_Depth))))));
+ Intval => Nest_Depth)))));
end if;
Analyze_And_Resolve (N, Id_Kind);
@@ -2923,8 +2924,6 @@ package body Exp_Attr is
when Attribute_Constrained => Constrained : declare
Formal_Ent : constant Entity_Id := Param_Entity (Pref);
- -- Start of processing for Constrained
-
begin
-- Reference to a parameter where the value is passed as an extra
-- actual, corresponding to the extra formal referenced by the
@@ -2938,7 +2937,7 @@ package body Exp_Attr is
then
Rewrite (N,
New_Occurrence_Of
- (Extra_Constrained (Formal_Ent), Sloc (N)));
+ (Extra_Constrained (Formal_Ent), Loc));
-- If the prefix is an access to object, the attribute applies to
-- the designated object, so rewrite with an explicit dereference.
@@ -2949,8 +2948,6 @@ package body Exp_Attr is
then
Rewrite (Pref,
Make_Explicit_Dereference (Loc, Relocate_Node (Pref)));
- Analyze_And_Resolve (N, Standard_Boolean);
- return;
-- For variables with a Extra_Constrained field, we use the
-- corresponding entity.
@@ -2961,7 +2958,7 @@ package body Exp_Attr is
then
Rewrite (N,
New_Occurrence_Of
- (Extra_Constrained (Entity (Pref)), Sloc (N)));
+ (Extra_Constrained (Entity (Pref)), Loc));
-- For all other cases, we can tell at compile time
@@ -2978,8 +2975,7 @@ package body Exp_Attr is
Rewrite (N,
New_Occurrence_Of
(Boolean_Literals
- (Exp_Util.Attribute_Constrained_Static_Value
- (Pref)), Sloc (N)));
+ (Exp_Util.Attribute_Constrained_Static_Value (Pref)), Loc));
end if;
Analyze_And_Resolve (N, Standard_Boolean);
@@ -2990,7 +2986,7 @@ package body Exp_Attr is
---------------
-- Transforms 'Copy_Sign into a call to the floating-point attribute
- -- function Copy_Sign in Fat_xxx (where xxx is the root type)
+ -- function Copy_Sign in Fat_xxx (where xxx is the root type).
when Attribute_Copy_Sign =>
Expand_Fpt_Attribute_RR (N);
@@ -3389,7 +3385,7 @@ package body Exp_Attr is
Size : Entity_Id;
- -- Start of Finalization_Size
+ -- Start of processing for Finalization_Size
begin
-- An object of a class-wide type first requires a runtime check to
@@ -3620,31 +3616,145 @@ package body Exp_Attr is
-- expands into
- -- Result_Type (System.Fore (Universal_Real (Type'First)),
- -- Universal_Real (Type'Last))
+ -- System.Fore_xx (ftyp (Typ'First), ftyp (Typ'Last) [,pm])
+
+ -- For decimal fixed-point types
+ -- xx = Decimal{32,64,128}
+ -- ftyp = Integer_{32,64,128}
+ -- pm = Typ'Scale
+
+ -- For the most common ordinary fixed-point types
+ -- xx = Fixed{32,64,128}
+ -- ftyp = Integer_{32,64,128}
+ -- pm = numerator of Typ'Small
+ -- denominator of Typ'Small
+ -- min (scale of Typ'Small, 0)
+
+ -- For other ordinary fixed-point types
+ -- xx = Real
+ -- ftyp = Universal_Real
+ -- pm = none
-- Note that we know that the type is a nonstatic subtype, or Fore would
- -- have itself been computed dynamically in Eval_Attribute.
+ -- have been computed statically in Eval_Attribute.
when Attribute_Fore =>
- Rewrite (N,
- Convert_To (Typ,
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Fore), Loc),
+ declare
+ Arg_List : List_Id;
+ Fid : RE_Id;
+ Ftyp : Entity_Id;
- Parameter_Associations => New_List (
- Convert_To (Universal_Real,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Ptyp, Loc),
- Attribute_Name => Name_First)),
+ begin
+ if Is_Decimal_Fixed_Point_Type (Ptyp) then
+ if Esize (Ptyp) <= 32 then
+ Fid := RE_Fore_Decimal32;
+ Ftyp := RTE (RE_Integer_32);
+ elsif Esize (Ptyp) <= 64 then
+ Fid := RE_Fore_Decimal64;
+ Ftyp := RTE (RE_Integer_64);
+ else
+ Fid := RE_Fore_Decimal128;
+ Ftyp := RTE (RE_Integer_128);
+ end if;
- Convert_To (Universal_Real,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Ptyp, Loc),
- Attribute_Name => Name_Last))))));
+ else
+ declare
+ Num : constant Uint := Norm_Num (Small_Value (Ptyp));
+ Den : constant Uint := Norm_Den (Small_Value (Ptyp));
+ Max : constant Uint := UI_Max (Num, Den);
+ Min : constant Uint := UI_Min (Num, Den);
+ Siz : constant Uint := Esize (Ptyp);
- Analyze_And_Resolve (N, Typ);
+ begin
+ if Siz <= 32
+ and then Max <= Uint_2 ** 31
+ and then (Min = Uint_1
+ or else Num < Den
+ or else Num < Uint_10 ** 8)
+ then
+ Fid := RE_Fore_Fixed32;
+ Ftyp := RTE (RE_Integer_32);
+ elsif Siz <= 64
+ and then Max <= Uint_2 ** 63
+ and then (Min = Uint_1
+ or else Num < Den
+ or else Num < Uint_10 ** 17)
+ then
+ Fid := RE_Fore_Fixed64;
+ Ftyp := RTE (RE_Integer_64);
+ elsif System_Max_Integer_Size = 128
+ and then Max <= Uint_2 ** 127
+ and then (Min = Uint_1
+ or else Num < Den
+ or else Num < Uint_10 ** 37)
+ then
+ Fid := RE_Fore_Fixed128;
+ Ftyp := RTE (RE_Integer_128);
+ else
+ Fid := RE_Fore_Real;
+ Ftyp := Universal_Real;
+ end if;
+ end;
+ end if;
+
+ Arg_List := New_List (
+ Convert_To (Ftyp,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_First)));
+
+ Append_To (Arg_List,
+ Convert_To (Ftyp,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Last)));
+
+ -- For decimal, append Scale and also set to do literal conversion
+
+ if Is_Decimal_Fixed_Point_Type (Ptyp) then
+ Set_Conversion_OK (First (Arg_List));
+ Set_Conversion_OK (Next (First (Arg_List)));
+
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, Scale_Value (Ptyp)));
+
+ -- For ordinary fixed-point types, append Num, Den and Scale
+ -- parameters and also set to do literal conversion
+
+ elsif Fid /= RE_Fore_Real then
+ Set_Conversion_OK (First (Arg_List));
+ Set_Conversion_OK (Next (First (Arg_List)));
+
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, -Norm_Num (Small_Value (Ptyp))));
+
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, -Norm_Den (Small_Value (Ptyp))));
+
+ declare
+ Val : Ureal := Small_Value (Ptyp);
+ Scale : Int := 0;
+
+ begin
+ while Val >= Ureal_10 loop
+ Val := Val / Ureal_10;
+ Scale := Scale - 1;
+ end loop;
+
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, UI_From_Int (Scale)));
+ end;
+ end if;
+
+ Rewrite (N,
+ Convert_To (Typ,
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (Fid), Loc),
+ Parameter_Associations => Arg_List)));
+
+ Analyze_And_Resolve (N, Typ);
+ end;
--------------
-- Fraction --
@@ -4240,7 +4350,7 @@ package body Exp_Attr is
begin
-- Processing for packed array types
- if Is_Array_Type (Ptyp) and then Is_Packed (Ptyp) then
+ if Is_Packed_Array (Ptyp) then
Ityp := Get_Index_Subtype (N);
-- If the index type, Ityp, is an enumeration type with holes,
@@ -4338,7 +4448,7 @@ package body Exp_Attr is
Xtyp : Entity_Id;
begin
- if Is_Array_Type (Dtyp) and then Is_Packed (Dtyp) then
+ if Is_Packed_Array (Dtyp) then
Xtyp := Get_Index_Subtype (N);
Rewrite (N,
@@ -4592,13 +4702,15 @@ package body Exp_Attr is
when Attribute_Mod => Mod_Case : declare
Arg : constant Node_Id := Relocate_Node (First (Exprs));
- Hi : constant Node_Id := Type_High_Bound (Etype (Arg));
+ Hi : constant Node_Id := Type_High_Bound (Base_Type (Etype (Arg)));
Modv : constant Uint := Modulus (Btyp);
begin
-- This is not so simple. The issue is what type to use for the
- -- computation of the modular value.
+ -- computation of the modular value. In addition we need to use
+ -- the base type as above to retrieve a static bound for the
+ -- comparisons that follow.
-- The easy case is when the modulus value is within the bounds
-- of the signed integer type of the argument. In this case we can
@@ -5717,14 +5829,14 @@ package body Exp_Attr is
when Attribute_Reduce =>
declare
- Loc : constant Source_Ptr := Sloc (N);
- E1 : constant Node_Id := First (Expressions (N));
- E2 : constant Node_Id := Next (E1);
- Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
- Typ : constant Entity_Id := Etype (N);
+ Loc : constant Source_Ptr := Sloc (N);
+ E1 : constant Node_Id := First (Expressions (N));
+ E2 : constant Node_Id := Next (E1);
+ Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
+ Typ : constant Entity_Id := Etype (N);
New_Loop : Node_Id;
- Stat : Node_Id;
+ Stat : Node_Id;
function Build_Stat (Comp : Node_Id) return Node_Id;
-- The reducer can be a function, a procedure whose first
@@ -5739,14 +5851,14 @@ package body Exp_Attr is
function Build_Stat (Comp : Node_Id) return Node_Id is
begin
if Nkind (E1) = N_Attribute_Reference then
- Stat := Make_Assignment_Statement (Loc,
- Name => New_Occurrence_Of (Bnn, Loc),
- Expression => Make_Attribute_Reference (Loc,
- Attribute_Name => Attribute_Name (E1),
- Prefix => New_Copy (Prefix (E1)),
- Expressions => New_List (
- New_Occurrence_Of (Bnn, Loc),
- Comp)));
+ Stat := Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Bnn, Loc),
+ Expression => Make_Attribute_Reference (Loc,
+ Attribute_Name => Attribute_Name (E1),
+ Prefix => New_Copy (Prefix (E1)),
+ Expressions => New_List (
+ New_Occurrence_Of (Bnn, Loc),
+ Comp)));
elsif Ekind (Entity (E1)) = E_Procedure then
Stat := Make_Procedure_Call_Statement (Loc,
@@ -5755,13 +5867,13 @@ package body Exp_Attr is
New_Occurrence_Of (Bnn, Loc),
Comp));
else
- Stat := Make_Assignment_Statement (Loc,
- Name => New_Occurrence_Of (Bnn, Loc),
- Expression => Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Entity (E1), Loc),
- Parameter_Associations => New_List (
- New_Occurrence_Of (Bnn, Loc),
- Comp)));
+ Stat := Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Bnn, Loc),
+ Expression => Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Entity (E1), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of (Bnn, Loc),
+ Comp)));
end if;
return Stat;
@@ -5769,9 +5881,8 @@ package body Exp_Attr is
-- If the prefix is an aggregate, its unique component is an
-- Iterated_Element, and we create a loop out of its iterator.
- -- The iterated_component_Association is parsed as a loop
- -- parameter specification with "in" or as a container
- -- iterator with "of".
+ -- The iterated_component_association is parsed as a loop parameter
+ -- specification with "in" or as a container iterator with "of".
begin
if Nkind (Prefix (N)) = N_Aggregate then
@@ -6085,20 +6196,19 @@ package body Exp_Attr is
-- Round --
-----------
- -- The handling of the Round attribute is quite delicate. The processing
- -- in Sem_Attr introduced a conversion to universal real, reflecting the
- -- semantics of Round, but we do not want anything to do with universal
- -- real at runtime, since this corresponds to using floating-point
- -- arithmetic.
+ -- The handling of the Round attribute is delicate when the operand is
+ -- universal fixed. In this case, the processing in Sem_Attr introduced
+ -- a conversion to universal real, reflecting the semantics of Round,
+ -- but we do not want anything to do with universal real at run time,
+ -- since this corresponds to using floating-point arithmetic.
-- What we have now is that the Etype of the Round attribute correctly
-- indicates the final result type. The operand of the Round is the
-- conversion to universal real, described above, and the operand of
-- this conversion is the actual operand of Round, which may be the
- -- special case of a fixed point multiplication or division (Etype =
- -- universal fixed)
+ -- special case of a fixed point multiplication or division.
- -- The exapander will expand first the operand of the conversion, then
+ -- The expander will expand first the operand of the conversion, then
-- the conversion, and finally the round attribute itself, since we
-- always work inside out. But we cannot simply process naively in this
-- order. In the semantic world where universal fixed and real really
@@ -6106,14 +6216,13 @@ package body Exp_Attr is
-- implementation world, where universal real is a floating-point type,
-- we would get the wrong result.
- -- So the approach is as follows. First, when expanding a multiply or
- -- divide whose type is universal fixed, we do nothing at all, instead
- -- deferring the operation till later.
-
- -- The actual processing is done in Expand_N_Type_Conversion which
- -- handles the special case of Round by looking at its parent to see if
- -- it is a Round attribute, and if it is, handling the conversion (or
- -- its fixed multiply/divide child) in an appropriate manner.
+ -- So the approach is as follows. When expanding a multiply or divide
+ -- whose type is universal fixed, Fixup_Universal_Fixed_Operation will
+ -- look up and skip the conversion to universal real if its parent is
+ -- a Round attribute, taking information from this attribute node. In
+ -- the other cases, Expand_N_Type_Conversion does the same by looking
+ -- at its parent to see if it is a Round attribute, before calling the
+ -- fixed-point expansion routine.
-- This means that by the time we get to expanding the Round attribute
-- itself, the Round is nothing more than a type conversion (and will
@@ -6121,8 +6230,12 @@ package body Exp_Attr is
-- appropriate conversion operation.
when Attribute_Round =>
- Rewrite (N,
- Convert_To (Etype (N), Relocate_Node (First (Exprs))));
+ if Etype (First (Exprs)) = Etype (N) then
+ Rewrite (N, Relocate_Node (First (Exprs)));
+ else
+ Rewrite (N, Convert_To (Etype (N), First (Exprs)));
+ Set_Rounded_Result (N);
+ end if;
Analyze_And_Resolve (N);
--------------
@@ -6229,7 +6342,7 @@ package body Exp_Attr is
then
Set_Attribute_Name (N, Name_Object_Size);
- -- In all other cases, Size and VADS_Size are the sane
+ -- In all other cases, Size and VADS_Size are the same
else
Set_Attribute_Name (N, Name_Size);
@@ -6293,7 +6406,7 @@ package body Exp_Attr is
------------------
when Attribute_Storage_Size => Storage_Size : declare
- Alloc_Op : Entity_Id := Empty;
+ Alloc_Op : Entity_Id := Empty;
begin
@@ -6714,7 +6827,7 @@ package body Exp_Attr is
------------
when Attribute_To_Any => To_Any : declare
- Decls : constant List_Id := New_List;
+ Decls : constant List_Id := New_List;
begin
Rewrite (N,
Build_To_Any_Call
@@ -6743,7 +6856,7 @@ package body Exp_Attr is
--------------
when Attribute_TypeCode => TypeCode : declare
- Decls : constant List_Id := New_List;
+ Decls : constant List_Id := New_List;
begin
Rewrite (N, Build_TypeCode_Call (Loc, Ptyp, Decls));
Insert_Actions (N, Decls);
@@ -7671,7 +7784,7 @@ package body Exp_Attr is
-- The following attributes should not appear at this stage, since they
-- have already been handled by the analyzer (and properly rewritten
- -- with corresponding values or entities to represent the right values)
+ -- with corresponding values or entities to represent the right values).
when Attribute_Abort_Signal
| Attribute_Address_Size
@@ -7725,6 +7838,8 @@ package body Exp_Attr is
| Attribute_Scale
| Attribute_Signed_Zeros
| Attribute_Small
+ | Attribute_Small_Denominator
+ | Attribute_Small_Numerator
| Attribute_Storage_Unit
| Attribute_Stub_Type
| Attribute_System_Allocator_Alignment
@@ -7802,17 +7917,17 @@ package body Exp_Attr is
---------------------------
procedure Expand_Size_Attribute (N : Node_Id) is
- Loc : constant Source_Ptr := Sloc (N);
- Typ : constant Entity_Id := Etype (N);
- Pref : constant Node_Id := Prefix (N);
- Ptyp : constant Entity_Id := Etype (Pref);
- Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
- Siz : Uint;
+ Loc : constant Source_Ptr := Sloc (N);
+ Typ : constant Entity_Id := Etype (N);
+ Pref : constant Node_Id := Prefix (N);
+ Ptyp : constant Entity_Id := Etype (Pref);
+ Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
+ Siz : Uint;
begin
-- Case of known RM_Size of a type
- if (Id = Attribute_Size or else Id = Attribute_Value_Size)
+ if Id in Attribute_Size | Attribute_Value_Size
and then Is_Entity_Name (Pref)
and then Is_Type (Entity (Pref))
and then Known_Static_RM_Size (Entity (Pref))
@@ -7874,8 +7989,7 @@ package body Exp_Attr is
if Is_Entity_Name (Pref)
and then Is_Formal (Entity (Pref))
- and then Is_Array_Type (Ptyp)
- and then Is_Packed (Ptyp)
+ and then Is_Packed_Array (Ptyp)
then
Rewrite (N,
Make_Attribute_Reference (Loc,
@@ -7889,9 +8003,8 @@ package body Exp_Attr is
-- type, but also a hint to the actual constrained type.
elsif Nkind (Pref) = N_Explicit_Dereference
- and then Is_Array_Type (Ptyp)
+ and then Is_Packed_Array (Ptyp)
and then not Is_Constrained (Ptyp)
- and then Is_Packed (Ptyp)
then
Set_Actual_Designated_Subtype (Pref, Get_Actual_Subtype (Pref));
@@ -8164,6 +8277,9 @@ package body Exp_Attr is
while Present (Comp) loop
if Nkind (Comp) = N_Range then
Process_Range_Update (Temp, Comp, Expr, Typ);
+ elsif Nkind (Comp) = N_Subtype_Indication then
+ Process_Range_Update
+ (Temp, Range_Expression (Constraint (Comp)), Expr, Typ);
else
Process_Component_Or_Element_Update (Temp, Comp, Expr, Typ);
end if;
@@ -8195,27 +8311,25 @@ package body Exp_Attr is
-- All we do is use the root type (historically this dealt with
-- VAX-float .. to be cleaned up further later ???)
- Fat_Type := Rtyp;
-
- if Fat_Type = Standard_Short_Float then
- Fat_Pkg := RE_Attr_Short_Float;
+ if Rtyp = Standard_Short_Float or else Rtyp = Standard_Float then
+ Fat_Type := Standard_Float;
+ Fat_Pkg := RE_Attr_Float;
- elsif Fat_Type = Standard_Float then
- Fat_Pkg := RE_Attr_Float;
+ elsif Rtyp = Standard_Long_Float then
+ Fat_Type := Standard_Long_Float;
+ Fat_Pkg := RE_Attr_Long_Float;
- elsif Fat_Type = Standard_Long_Float then
- Fat_Pkg := RE_Attr_Long_Float;
-
- elsif Fat_Type = Standard_Long_Long_Float then
- Fat_Pkg := RE_Attr_Long_Long_Float;
+ elsif Rtyp = Standard_Long_Long_Float then
+ Fat_Type := Standard_Long_Long_Float;
+ Fat_Pkg := RE_Attr_Long_Long_Float;
-- Universal real (which is its own root type) is treated as being
-- equivalent to Standard.Long_Long_Float, since it is defined to
-- have the same precision as the longest Float type.
- elsif Fat_Type = Universal_Real then
+ elsif Rtyp = Universal_Real then
Fat_Type := Standard_Long_Long_Float;
- Fat_Pkg := RE_Attr_Long_Long_Float;
+ Fat_Pkg := RE_Attr_Long_Long_Float;
else
raise Program_Error;
diff --git a/gcc/ada/exp_ch11.adb b/gcc/ada/exp_ch11.adb
index abc91a2..a501bf1 100644
--- a/gcc/ada/exp_ch11.adb
+++ b/gcc/ada/exp_ch11.adb
@@ -189,7 +189,6 @@ package body Exp_Ch11 is
Handlrs : constant List_Id := Exception_Handlers (HSS);
Loc : constant Source_Ptr := Sloc (HSS);
Handler : Node_Id;
- Others_Choice : Boolean;
Obj_Decl : Node_Id;
Next_Handler : Node_Id;
@@ -197,12 +196,6 @@ package body Exp_Ch11 is
-- This procedure handles the expansion of exception handlers for the
-- optimization of local raise statements into goto statements.
- procedure Prepend_Call_To_Handler
- (Proc : RE_Id;
- Args : List_Id := No_List);
- -- Routine to prepend a call to the procedure referenced by Proc at
- -- the start of the handler code for the current Handler.
-
procedure Replace_Raise_By_Goto (Raise_S : Node_Id; Goto_L1 : Node_Id);
-- Raise_S is a raise statement (possibly expanded, and possibly of the
-- form of a Raise_xxx_Error node with a condition. This procedure is
@@ -850,36 +843,6 @@ package body Exp_Ch11 is
end;
end Expand_Local_Exception_Handlers;
- -----------------------------
- -- Prepend_Call_To_Handler --
- -----------------------------
-
- procedure Prepend_Call_To_Handler
- (Proc : RE_Id;
- Args : List_Id := No_List)
- is
- Ent : constant Entity_Id := RTE (Proc);
-
- begin
- -- If we have no Entity, then we are probably in no run time mode or
- -- some weird error has occurred. In either case do nothing. Note use
- -- of No_Location to hide this code from the debugger, so single
- -- stepping doesn't jump back and forth.
-
- if Present (Ent) then
- declare
- Call : constant Node_Id :=
- Make_Procedure_Call_Statement (No_Location,
- Name => New_Occurrence_Of (RTE (Proc), No_Location),
- Parameter_Associations => Args);
-
- begin
- Prepend_To (Statements (Handler), Call);
- Analyze (Call, Suppress => All_Checks);
- end;
- end if;
- end Prepend_Call_To_Handler;
-
---------------------------
-- Replace_Raise_By_Goto --
---------------------------
@@ -1089,44 +1052,6 @@ package body Exp_Ch11 is
(Statements (Handler), Suppress => All_Checks);
end;
end if;
-
- -- For the normal case, we have to worry about the state of
- -- abort deferral. Generally, we defer abort during runtime
- -- handling of exceptions. When control is passed to the
- -- handler, then in the normal case we undefer aborts. In
- -- any case this entire handling is relevant only if aborts
- -- are allowed.
-
- if Abort_Allowed
- and then not ZCX_Exceptions
- then
- -- There are some special cases in which we do not do the
- -- undefer. In particular a finalization (AT END) handler
- -- wants to operate with aborts still deferred.
-
- -- We also suppress the call if this is the special handler
- -- for Abort_Signal, since if we are aborting, we want to
- -- keep aborts deferred (one abort is enough).
-
- -- If abort really needs to be deferred the expander must
- -- add this call explicitly, see
- -- Expand_N_Asynchronous_Select.
-
- Others_Choice :=
- Nkind (First (Exception_Choices (Handler))) =
- N_Others_Choice;
-
- if (Others_Choice
- or else Entity (First (Exception_Choices (Handler))) /=
- Stand.Abort_Signal)
- and then not
- (Others_Choice
- and then
- All_Others (First (Exception_Choices (Handler))))
- then
- Prepend_Call_To_Handler (RE_Abort_Undefer);
- end if;
- end if;
end if;
end if;
@@ -1553,7 +1478,7 @@ package body Exp_Ch11 is
begin
-- Processing for locally handled exception (exclude reraise case)
- if Present (Name (N)) and then Nkind (Name (N)) = N_Identifier then
+ if Present (Name (N)) and then Is_Entity_Name (Name (N)) then
if Debug_Flag_Dot_G
or else Restriction_Active (No_Exception_Propagation)
then
@@ -1657,7 +1582,7 @@ package body Exp_Ch11 is
-- but this is also faster in all modes). Propagate Comes_From_Source
-- flag to the new node.
- if Present (Name (N)) and then Nkind (Name (N)) = N_Identifier then
+ if Present (Name (N)) and then Is_Entity_Name (Name (N)) then
Src := Comes_From_Source (N);
if Entity (Name (N)) = Standard_Constraint_Error then
@@ -1689,7 +1614,7 @@ package body Exp_Ch11 is
-- where location_string identifies the file/line of the raise
- if Present (Name (N)) then
+ if Present (Name (N)) and then Is_Entity_Name (Name (N)) then
declare
Id : Entity_Id := Entity (Name (N));
Buf : Bounded_String;
@@ -1939,8 +1864,8 @@ package body Exp_Ch11 is
then
return Empty;
- -- Test for handled sequence of statements with at least one
- -- exception handler which might be the one we are looking for.
+ -- Test for handled sequence of statements with at least one
+ -- exception handler which might be the one we are looking for.
elsif Nkind (P) = N_Handled_Sequence_Of_Statements
and then Present (Exception_Handlers (P))
diff --git a/gcc/ada/exp_ch13.adb b/gcc/ada/exp_ch13.adb
index 30f101d..89efca9 100644
--- a/gcc/ada/exp_ch13.adb
+++ b/gcc/ada/exp_ch13.adb
@@ -582,9 +582,8 @@ package body Exp_Ch13 is
Install_Visible_Declarations (E_Scope);
end if;
- if Is_Package_Or_Generic_Package (E_Scope) or else
- Is_Protected_Type (E_Scope) or else
- Is_Task_Type (E_Scope)
+ if Is_Concurrent_Type (E_Scope)
+ or else Is_Package_Or_Generic_Package (E_Scope)
then
Install_Private_Declarations (E_Scope);
end if;
diff --git a/gcc/ada/exp_ch2.adb b/gcc/ada/exp_ch2.adb
index 5c3435b..6c41e08 100644
--- a/gcc/ada/exp_ch2.adb
+++ b/gcc/ada/exp_ch2.adb
@@ -338,8 +338,43 @@ package body Exp_Ch2 is
-----------------------------
procedure Expand_Entity_Reference (N : Node_Id) is
+
+ function Is_Object_Renaming_Name (N : Node_Id) return Boolean;
+ -- Indicates that N occurs (after accounting for qualified expressions
+ -- and type conversions) as the name of an object renaming declaration.
+ -- We don't want to fold values in that case.
+
+ -----------------------------
+ -- Is_Object_Renaming_Name --
+ -----------------------------
+
+ function Is_Object_Renaming_Name (N : Node_Id) return Boolean is
+ Trailer : Node_Id := N;
+ Rover : Node_Id;
+ begin
+ loop
+ Rover := Parent (Trailer);
+ case Nkind (Rover) is
+ when N_Qualified_Expression | N_Type_Conversion =>
+ -- Conservative for type conversions; only necessary if
+ -- conversion does not introduce a new object (as opposed
+ -- to a new view of an existing object).
+ null;
+ when N_Object_Renaming_Declaration =>
+ return Trailer = Name (Rover);
+ when others =>
+ return False; -- the usual case
+ end case;
+ Trailer := Rover;
+ end loop;
+ end Is_Object_Renaming_Name;
+
+ -- Local variables
+
E : constant Entity_Id := Entity (N);
+ -- Start of processing for Expand_Entity_Reference
+
begin
-- Defend against errors
@@ -441,10 +476,17 @@ package body Exp_Ch2 is
end;
end if;
- -- Interpret possible Current_Value for variable case
+ -- Interpret possible Current_Value for variable case. The
+ -- Is_Object_Renaming_Name test is needed for cases such as
+ -- X : Integer := 1;
+ -- Y : Integer renames Integer'(X);
+ -- where the value of Y is changed by any subsequent assignments to X.
+ -- In cases like this, we do not want to use Current_Value even though
+ -- it is available.
if Is_Assignable (E)
and then Present (Current_Value (E))
+ and then not Is_Object_Renaming_Name (N)
then
Expand_Current_Value (N);
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index f8b6ee6..e0040ed 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -671,24 +671,90 @@ package body Exp_Ch3 is
------------------------
function Init_One_Dimension (N : Int) return List_Id is
- Index : Entity_Id;
+ Index : Entity_Id;
+ DIC_Call : Node_Id;
+ Result_List : List_Id;
+
+ function Possible_DIC_Call return Node_Id;
+ -- If the component type has Default_Initial_Conditions and a DIC
+ -- procedure that is not an empty body, then builds a call to the
+ -- DIC procedure and returns it.
+
+ -----------------------
+ -- Possible_DIC_Call --
+ -----------------------
+
+ function Possible_DIC_Call return Node_Id is
+ begin
+ -- When the component's type has a Default_Initial_Condition, then
+ -- create a call for the DIC check.
+
+ if Has_DIC (Comp_Type)
+ -- In GNATprove mode, the component DICs are checked by other
+ -- means. They should not be added to the record type DIC
+ -- procedure, so that the procedure can be used to check the
+ -- record type invariants or DICs if any.
+
+ and then not GNATprove_Mode
+
+ -- DIC checks for components of controlled types are done later
+ -- (see Exp_Ch7.Make_Deep_Array_Body).
+
+ and then not Is_Controlled (Comp_Type)
+
+ and then Present (DIC_Procedure (Comp_Type))
+
+ and then not Has_Null_Body (DIC_Procedure (Comp_Type))
+ then
+ return
+ Build_DIC_Call (Loc,
+ Make_Indexed_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Expressions => Index_List),
+ Comp_Type);
+ else
+ return Empty;
+ end if;
+ end Possible_DIC_Call;
+
+ -- Start of processing for Init_One_Dimension
begin
-- If the component does not need initializing, then there is nothing
-- to do here, so we return a null body. This occurs when generating
-- the dummy Init_Proc needed for Initialize_Scalars processing.
+ -- An exception is if component type has a Default_Initial_Condition,
+ -- in which case we generate a call to the type's DIC procedure.
if not Has_Non_Null_Base_Init_Proc (Comp_Type)
and then not Comp_Simple_Init
and then not Has_Task (Comp_Type)
and then not Has_Default_Aspect (A_Type)
+ and then (not Has_DIC (Comp_Type)
+ or else N > Number_Dimensions (A_Type))
then
- return New_List (Make_Null_Statement (Loc));
+ DIC_Call := Possible_DIC_Call;
+
+ if Present (DIC_Call) then
+ return New_List (DIC_Call);
+ else
+ return New_List (Make_Null_Statement (Loc));
+ end if;
-- If all dimensions dealt with, we simply initialize the component
+ -- and append a call to component type's DIC procedure when needed.
elsif N > Number_Dimensions (A_Type) then
- return Init_Component;
+ DIC_Call := Possible_DIC_Call;
+
+ if Present (DIC_Call) then
+ Result_List := Init_Component;
+ Append (DIC_Call, Result_List);
+ return Result_List;
+
+ else
+ return Init_Component;
+ end if;
-- Here we generate the required loop
@@ -753,6 +819,7 @@ package body Exp_Ch3 is
-- 3. Tasks are present
-- 4. The type is marked as a public entity
-- 5. The array type has a Default_Component_Value aspect
+ -- 6. The array component type has a Default_Initialization_Condition
-- The reason for the public entity test is to deal properly with the
-- Initialize_Scalars pragma. This pragma can be set in the client and
@@ -771,7 +838,8 @@ package body Exp_Ch3 is
Has_Default_Init := Has_Non_Null_Base_Init_Proc (Comp_Type)
or else Comp_Simple_Init
or else Has_Task (Comp_Type)
- or else Has_Default_Aspect (A_Type);
+ or else Has_Default_Aspect (A_Type)
+ or else Has_DIC (Comp_Type);
if Has_Default_Init
or else (not Restriction_Active (No_Initialize_Scalars)
@@ -1945,47 +2013,6 @@ package body Exp_Ch3 is
Lhs : Node_Id;
Res : List_Id;
- function Replace_Discr_Ref (N : Node_Id) return Traverse_Result;
- -- Analysis of the aggregate has replaced discriminants by their
- -- corresponding discriminals, but these are irrelevant when the
- -- component has a mutable type and is initialized with an aggregate.
- -- Instead, they must be replaced by the values supplied in the
- -- aggregate, that will be assigned during the expansion of the
- -- assignment.
-
- -----------------------
- -- Replace_Discr_Ref --
- -----------------------
-
- function Replace_Discr_Ref (N : Node_Id) return Traverse_Result is
- Val : Node_Id;
-
- begin
- if Is_Entity_Name (N)
- and then Present (Entity (N))
- and then Is_Formal (Entity (N))
- and then Present (Discriminal_Link (Entity (N)))
- then
- Val :=
- Make_Selected_Component (Default_Loc,
- Prefix => New_Copy_Tree (Lhs),
- Selector_Name =>
- New_Occurrence_Of
- (Discriminal_Link (Entity (N)), Default_Loc));
-
- if Present (Val) then
- Rewrite (N, New_Copy_Tree (Val));
- end if;
- end if;
-
- return OK;
- end Replace_Discr_Ref;
-
- procedure Replace_Discriminant_References is
- new Traverse_Proc (Replace_Discr_Ref);
-
- -- Start of processing for Build_Assignment
-
begin
Lhs :=
Make_Selected_Component (Default_Loc,
@@ -1993,22 +2020,6 @@ package body Exp_Ch3 is
Selector_Name => New_Occurrence_Of (Id, Default_Loc));
Set_Assignment_OK (Lhs);
- if Nkind (Exp) = N_Aggregate
- and then Has_Discriminants (Typ)
- and then not Is_Constrained (Base_Type (Typ))
- then
- -- The aggregate may provide new values for the discriminants
- -- of the component, and other components may depend on those
- -- discriminants. Previous analysis of those expressions have
- -- replaced the discriminants by the formals of the initialization
- -- procedure for the type, but these are irrelevant in the
- -- enclosing initialization procedure: those discriminant
- -- references must be replaced by the values provided in the
- -- aggregate.
-
- Replace_Discriminant_References (Exp);
- end if;
-
-- Case of an access attribute applied to the current instance.
-- Replace the reference to the type by a reference to the actual
-- object. (Note that this handles the case of the top level of
@@ -3438,6 +3449,38 @@ package body Exp_Ch3 is
Actions := No_List;
end if;
+ -- When the component's type has a Default_Initial_Condition,
+ -- and the component is default initialized, then check the
+ -- DIC here.
+
+ if Has_DIC (Typ)
+ and then not Present (Expression (Decl))
+ and then Present (DIC_Procedure (Typ))
+ and then not Has_Null_Body (DIC_Procedure (Typ))
+
+ -- The DICs of ancestors are checked as part of the type's
+ -- DIC procedure.
+
+ and then Chars (Id) /= Name_uParent
+
+ -- In GNATprove mode, the component DICs are checked by other
+ -- means. They should not be added to the record type DIC
+ -- procedure, so that the procedure can be used to check the
+ -- record type invariants or DICs if any.
+
+ and then not GNATprove_Mode
+ then
+ Append_New_To (Actions,
+ Build_DIC_Call
+ (Comp_Loc,
+ Make_Selected_Component (Comp_Loc,
+ Prefix =>
+ Make_Identifier (Comp_Loc, Name_uInit),
+ Selector_Name =>
+ New_Occurrence_Of (Id, Comp_Loc)),
+ Typ));
+ end if;
+
if Present (Checks) then
if Chars (Id) = Name_uParent then
Append_List_To (Parent_Stmts, Checks);
@@ -7403,12 +7446,12 @@ package body Exp_Ch3 is
-- If we cannot convert the expression into a renaming we must
-- consider it an internal error because the backend does not
- -- have support to handle it. Also, when a raise expression is
- -- encountered we ignore it since it doesn't return a value and
- -- thus cannot trigger a copy.
+ -- have support to handle it. But avoid crashing on a raise
+ -- expression or conditional expression.
- elsif Nkind (Original_Node (Expr_Q)) /= N_Raise_Expression then
- pragma Assert (False);
+ elsif Nkind (Original_Node (Expr_Q)) not in
+ N_Raise_Expression | N_If_Expression | N_Case_Expression
+ then
raise Program_Error;
end if;
@@ -7552,12 +7595,14 @@ package body Exp_Ch3 is
if Comes_From_Source (Def_Id)
and then Has_DIC (Typ)
and then Present (DIC_Procedure (Typ))
+ and then not Has_Null_Body (DIC_Procedure (Typ))
and then not Has_Init_Expression (N)
and then not Is_Imported (Def_Id)
then
declare
- DIC_Call : constant Node_Id := Build_DIC_Call (Loc, Def_Id, Typ);
-
+ DIC_Call : constant Node_Id :=
+ Build_DIC_Call
+ (Loc, New_Occurrence_Of (Def_Id, Loc), Typ);
begin
if Present (Next_N) then
Insert_Before_And_Analyze (Next_N, DIC_Call);
@@ -8331,13 +8376,6 @@ package body Exp_Ch3 is
Process_Pending_Access_Types (Def_Id);
Freeze_Stream_Operations (N, Def_Id);
- -- Generate the [spec and] body of the procedure tasked with the runtime
- -- verification of pragma Default_Initial_Condition's expression.
-
- if Has_DIC (Def_Id) then
- Build_DIC_Procedure_Body (Def_Id, For_Freeze => True);
- end if;
-
-- Generate the [spec and] body of the invariant procedure tasked with
-- the runtime verification of all invariants that pertain to the type.
-- This includes invariants on the partial and full view, inherited
@@ -8363,14 +8401,24 @@ package body Exp_Ch3 is
-- subprograms, which may involve local declarations of local
-- subtypes to which these checks do not apply.
- elsif Has_Invariants (Def_Id) then
- if not Predicate_Check_In_Scope (Def_Id)
- or else (Ekind (Current_Scope) = E_Function
- and then Is_Predicate_Function (Current_Scope))
- then
- null;
- else
- Build_Invariant_Procedure_Body (Def_Id);
+ else
+ if Has_Invariants (Def_Id) then
+ if not Predicate_Check_In_Scope (Def_Id)
+ or else (Ekind (Current_Scope) = E_Function
+ and then Is_Predicate_Function (Current_Scope))
+ then
+ null;
+ else
+ Build_Invariant_Procedure_Body (Def_Id);
+ end if;
+ end if;
+
+ -- Generate the [spec and] body of the procedure tasked with the
+ -- run-time verification of pragma Default_Initial_Condition's
+ -- expression.
+
+ if Has_DIC (Def_Id) then
+ Build_DIC_Procedure_Body (Def_Id);
end if;
end if;
@@ -8976,13 +9024,13 @@ package body Exp_Ch3 is
if Warning_Needed then
Error_Msg_N
- ("Objects of the type cannot be initialized statically "
+ ("objects of the type cannot be initialized statically "
& "by default??", Parent (E));
end if;
end if;
else
- Error_Msg_N ("Object cannot be initialized statically??", E);
+ Error_Msg_N ("object cannot be initialized statically??", E);
end if;
end if;
end Initialization_Warning;
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 076e0de..04bd1fe 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -1268,9 +1268,8 @@ package body Exp_Ch4 is
-- expression with a constrained subtype in order to compute the
-- proper size for the allocator.
- if Is_Array_Type (T)
+ if Is_Packed_Array (T)
and then not Is_Constrained (T)
- and then Is_Packed (T)
then
declare
ConstrT : constant Entity_Id := Make_Temporary (Loc, 'A');
@@ -2184,21 +2183,54 @@ package body Exp_Ch4 is
then
return;
else
-
Func_Body := Make_Boolean_Array_Op (Etype (L), N);
Func_Name := Defining_Unit_Name (Specification (Func_Body));
Insert_Action (N, Func_Body);
-- Now rewrite the expression with a call
- Rewrite (N,
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Func_Name, Loc),
- Parameter_Associations =>
- New_List (
- L,
- Make_Type_Conversion
- (Loc, New_Occurrence_Of (Etype (L), Loc), R))));
+ if Transform_Function_Array then
+ declare
+ Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
+ Call : Node_Id;
+ Decl : Node_Id;
+
+ begin
+ -- Generate:
+ -- Temp : ...;
+
+ Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp_Id,
+ Object_Definition =>
+ New_Occurrence_Of (Etype (L), Loc));
+
+ -- Generate:
+ -- Proc_Call (L, R, Temp);
+
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Func_Name, Loc),
+ Parameter_Associations =>
+ New_List (
+ L,
+ Make_Type_Conversion
+ (Loc, New_Occurrence_Of (Etype (L), Loc), R),
+ New_Occurrence_Of (Temp_Id, Loc)));
+
+ Insert_Actions (Parent (N), New_List (Decl, Call));
+ Rewrite (N, New_Occurrence_Of (Temp_Id, Loc));
+ end;
+ else
+ Rewrite (N,
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Func_Name, Loc),
+ Parameter_Associations =>
+ New_List (
+ L,
+ Make_Type_Conversion
+ (Loc, New_Occurrence_Of (Etype (L), Loc), R))));
+ end if;
Analyze_And_Resolve (N, Typ);
end if;
@@ -3506,8 +3538,17 @@ package body Exp_Ch4 is
Alloc :=
Make_Allocator (Loc,
Expression => New_Occurrence_Of (ConstrT, Loc));
+
+ -- Allocate on the secondary stack. This is currently done
+ -- only for type String, which normally doesn't have default
+ -- initialization, but we need to Set_No_Initialization in case
+ -- of Initialize_Scalars or Normalize_Scalars; otherwise, the
+ -- allocator will get transformed and will not use the secondary
+ -- stack.
+
Set_Storage_Pool (Alloc, RTE (RE_SS_Pool));
Set_Procedure_To_Call (Alloc, RTE (RE_SS_Allocate));
+ Set_No_Initialization (Alloc);
Temp := Make_Temporary (Loc, 'R', Alloc);
Insert_Action (Cnode,
@@ -5347,6 +5388,24 @@ package body Exp_Ch4 is
Rewrite (N, New_Occurrence_Of (Temp, Loc));
Analyze_And_Resolve (N, PtrT);
+
+ -- When designated type has Default_Initial_Condition aspects,
+ -- make a call to the type's DIC procedure to perform the
+ -- checks. Theoretically this might also be needed for cases
+ -- where the type doesn't have an init proc, but those should
+ -- be very uncommon, and for now we only support the init proc
+ -- case. ???
+
+ if Has_DIC (Dtyp)
+ and then Present (DIC_Procedure (Dtyp))
+ and then not Has_Null_Body (DIC_Procedure (Dtyp))
+ then
+ Insert_Action (N,
+ Build_DIC_Call (Loc,
+ Make_Explicit_Dereference (Loc,
+ Prefix => New_Occurrence_Of (Temp, Loc)),
+ Dtyp));
+ end if;
end if;
end if;
end;
@@ -9708,16 +9767,6 @@ package body Exp_Ch4 is
end if;
end if;
- -- Try to narrow the operation
-
- if Typ = Universal_Integer then
- Narrow_Large_Operation (N);
-
- if Nkind (N) /= N_Op_Multiply then
- return;
- end if;
- end if;
-
-- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
-- Is_Power_Of_2_For_Shift is set means that we know that our left
-- operand is an integer, as required for this to work.
@@ -9794,6 +9843,16 @@ package body Exp_Ch4 is
return;
end if;
+ -- Try to narrow the operation
+
+ if Typ = Universal_Integer then
+ Narrow_Large_Operation (N);
+
+ if Nkind (N) /= N_Op_Multiply then
+ return;
+ end if;
+ end if;
+
-- Do required fixup of universal fixed operation
if Typ = Universal_Fixed then
@@ -9990,12 +10049,21 @@ package body Exp_Ch4 is
-- return B;
-- end Nnnn;
+ -- or in the case of Transform_Function_Array:
+
+ -- procedure Nnnn (A : arr; RESULT : out arr) is
+ -- begin
+ -- for J in a'range loop
+ -- RESULT (J) := not A (J);
+ -- end loop;
+ -- end Nnnn;
+
-- Here arr is the actual subtype of the parameter (and hence always
- -- constrained). Then we replace the not with a call to this function.
+ -- constrained). Then we replace the not with a call to this subprogram.
procedure Expand_N_Op_Not (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
- Typ : constant Entity_Id := Etype (N);
+ Typ : constant Entity_Id := Etype (Right_Opnd (N));
Opnd : Node_Id;
Arr : Entity_Id;
A : Entity_Id;
@@ -10091,7 +10159,13 @@ package body Exp_Ch4 is
end if;
A := Make_Defining_Identifier (Loc, Name_uA);
- B := Make_Defining_Identifier (Loc, Name_uB);
+
+ if Transform_Function_Array then
+ B := Make_Defining_Identifier (Loc, Name_UP_RESULT);
+ else
+ B := Make_Defining_Identifier (Loc, Name_uB);
+ end if;
+
J := Make_Defining_Identifier (Loc, Name_uJ);
A_J :=
@@ -10126,33 +10200,82 @@ package body Exp_Ch4 is
Func_Name := Make_Temporary (Loc, 'N');
Set_Is_Inlined (Func_Name);
- Insert_Action (N,
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Function_Specification (Loc,
- Defining_Unit_Name => Func_Name,
- Parameter_Specifications => New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier => A,
- Parameter_Type => New_Occurrence_Of (Typ, Loc))),
- Result_Definition => New_Occurrence_Of (Typ, Loc)),
+ if Transform_Function_Array then
+ Insert_Action (N,
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Func_Name,
+ Parameter_Specifications => New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => A,
+ Parameter_Type => New_Occurrence_Of (Typ, Loc)),
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => B,
+ Out_Present => True,
+ Parameter_Type => New_Occurrence_Of (Typ, Loc)))),
+
+ Declarations => New_List,
+
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Loop_Statement))));
- Declarations => New_List (
- Make_Object_Declaration (Loc,
- Defining_Identifier => B,
- Object_Definition => New_Occurrence_Of (Arr, Loc))),
+ declare
+ Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
+ Call : Node_Id;
+ Decl : Node_Id;
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (
- Loop_Statement,
- Make_Simple_Return_Statement (Loc,
- Expression => Make_Identifier (Loc, Chars (B)))))));
+ begin
+ -- Generate:
+ -- Temp : ...;
- Rewrite (N,
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Func_Name, Loc),
- Parameter_Associations => New_List (Opnd)));
+ Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp_Id,
+ Object_Definition => New_Occurrence_Of (Typ, Loc));
+
+ -- Generate:
+ -- Proc_Call (Opnd, Temp);
+
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Func_Name, Loc),
+ Parameter_Associations =>
+ New_List (Opnd, New_Occurrence_Of (Temp_Id, Loc)));
+
+ Insert_Actions (Parent (N), New_List (Decl, Call));
+ Rewrite (N, New_Occurrence_Of (Temp_Id, Loc));
+ end;
+ else
+ Insert_Action (N,
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Function_Specification (Loc,
+ Defining_Unit_Name => Func_Name,
+ Parameter_Specifications => New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => A,
+ Parameter_Type => New_Occurrence_Of (Typ, Loc))),
+ Result_Definition => New_Occurrence_Of (Typ, Loc)),
+
+ Declarations => New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => B,
+ Object_Definition => New_Occurrence_Of (Arr, Loc))),
+
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Loop_Statement,
+ Make_Simple_Return_Statement (Loc,
+ Expression => Make_Identifier (Loc, Chars (B)))))));
+
+ Rewrite (N,
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Func_Name, Loc),
+ Parameter_Associations => New_List (Opnd)));
+ end if;
Analyze_And_Resolve (N, Typ);
end Expand_N_Op_Not;
@@ -11039,7 +11162,7 @@ package body Exp_Ch4 is
-- because the selected component may be a reference to the
-- object being initialized, whose discriminant is not yet
-- set. This only happens in complex cases involving changes
- -- or representation.
+ -- of representation.
if Disc = Entity (Selector_Name (N))
and then (Is_Entity_Name (Dval)
@@ -11051,15 +11174,7 @@ package body Exp_Ch4 is
-- constrained by an outer discriminant, which cannot
-- be optimized away.
- if Denotes_Discriminant
- (Dval, Check_Concurrent => True)
- then
- exit Discr_Loop;
-
- elsif Nkind (Original_Node (Dval)) = N_Selected_Component
- and then
- Denotes_Discriminant
- (Selector_Name (Original_Node (Dval)), True)
+ if Denotes_Discriminant (Dval, Check_Concurrent => True)
then
exit Discr_Loop;
@@ -11457,11 +11572,6 @@ package body Exp_Ch4 is
-- Start of processing for Discrete_Range_Check
begin
- -- Clear the Do_Range_Check flag on N if needed: this can occur when
- -- e.g. a trivial type conversion is rewritten by its expression.
-
- Set_Do_Range_Check (N, False);
-
-- Nothing more to do if conversion was rewritten
if Nkind (N) /= N_Type_Conversion then
@@ -11470,12 +11580,6 @@ package body Exp_Ch4 is
Expr := Expression (N);
- -- Nothing to do if no range check flag set
-
- if not Do_Range_Check (Expr) then
- return;
- end if;
-
-- Clear the Do_Range_Check flag on Expr
Set_Do_Range_Check (Expr, False);
@@ -11748,11 +11852,6 @@ package body Exp_Ch4 is
Tnn : Entity_Id;
begin
- -- Clear the Do_Range_Check flag on N if needed: this can occur when
- -- e.g. a trivial type conversion is rewritten by its expression.
-
- Set_Do_Range_Check (N, False);
-
-- Nothing more to do if conversion was rewritten
if Nkind (N) /= N_Type_Conversion then
@@ -11871,33 +11970,20 @@ package body Exp_Ch4 is
-- which used to fail when Fix_Val was a bound of the type and
-- the 'Small was not a representable number.
-- This transformation requires an integer type large enough to
- -- accommodate a fixed-point value. This will not be the case
- -- in systems where Duration is larger than Long_Integer.
+ -- accommodate a fixed-point value.
if Is_Ordinary_Fixed_Point_Type (Target_Type)
and then Is_Floating_Point_Type (Etype (Expr))
- and then RM_Size (Btyp) <= RM_Size (Standard_Long_Integer)
+ and then RM_Size (Btyp) <= System_Max_Integer_Size
and then Nkind (Lo) = N_Real_Literal
and then Nkind (Hi) = N_Real_Literal
then
declare
Expr_Id : constant Entity_Id := Make_Temporary (Loc, 'T', Conv);
- Int_Type : Entity_Id;
+ Int_Typ : constant Entity_Id :=
+ Small_Integer_Type_For (RM_Size (Btyp), False);
begin
- -- Find an integer type of the appropriate size to perform an
- -- unchecked conversion to the target fixed-point type.
-
- if RM_Size (Btyp) > RM_Size (Standard_Integer) then
- Int_Type := Standard_Long_Integer;
-
- elsif RM_Size (Btyp) > RM_Size (Standard_Short_Integer) then
- Int_Type := Standard_Integer;
-
- else
- Int_Type := Standard_Short_Integer;
- end if;
-
-- Generate a temporary with the integer value. Required in the
-- CCG compiler to ensure that run-time checks reference this
-- integer expression (instead of the resulting fixed-point
@@ -11907,23 +11993,23 @@ package body Exp_Ch4 is
Insert_Action (N,
Make_Object_Declaration (Loc,
Defining_Identifier => Expr_Id,
- Object_Definition => New_Occurrence_Of (Int_Type, Loc),
+ Object_Definition => New_Occurrence_Of (Int_Typ, Loc),
Constant_Present => True,
Expression =>
- Convert_To (Int_Type, Expression (Conv))));
+ Convert_To (Int_Typ, Expression (Conv))));
-- Create integer objects for range checking of result.
Lo_Arg :=
Unchecked_Convert_To
- (Int_Type, New_Occurrence_Of (Expr_Id, Loc));
+ (Int_Typ, New_Occurrence_Of (Expr_Id, Loc));
Lo_Val :=
Make_Integer_Literal (Loc, Corresponding_Integer_Value (Lo));
Hi_Arg :=
Unchecked_Convert_To
- (Int_Type, New_Occurrence_Of (Expr_Id, Loc));
+ (Int_Typ, New_Occurrence_Of (Expr_Id, Loc));
Hi_Val :=
Make_Integer_Literal (Loc, Corresponding_Integer_Value (Hi));
@@ -12037,20 +12123,16 @@ package body Exp_Ch4 is
-- Nothing at all to do if conversion is to the identical type so remove
-- the conversion completely, it is useless, except that it may carry
-- an Assignment_OK attribute, which must be propagated to the operand
- -- and the Do_Range_Check flag on Operand should be taken into account.
+ -- and the Do_Range_Check flag on the operand must be cleared, if any.
if Operand_Type = Target_Type then
if Assignment_OK (N) then
Set_Assignment_OK (Operand);
end if;
- Rewrite (N, Relocate_Node (Operand));
-
- if Do_Range_Check (Operand) then
- pragma Assert (Is_Discrete_Type (Operand_Type));
+ Set_Do_Range_Check (Operand, False);
- Discrete_Range_Check;
- end if;
+ Rewrite (N, Relocate_Node (Operand));
goto Done;
end if;
@@ -12259,7 +12341,7 @@ package body Exp_Ch4 is
else
Apply_Accessibility_Check
- (Operand_Acc, Target_Type, Insert_Node => Operand);
+ (Operand, Target_Type, Insert_Node => Operand);
end if;
-- If the level of the operand type is statically deeper than the
@@ -12466,23 +12548,18 @@ package body Exp_Ch4 is
and then Nkind (Parent (N)) = N_Attribute_Reference
and then Attribute_Name (Parent (N)) = Name_Round
then
- Set_Rounded_Result (N);
Set_Etype (N, Etype (Parent (N)));
Target_Type := Etype (N);
+ Set_Rounded_Result (N);
end if;
if Is_Fixed_Point_Type (Target_Type) then
Expand_Convert_Fixed_To_Fixed (N);
- Real_Range_Check;
-
elsif Is_Integer_Type (Target_Type) then
Expand_Convert_Fixed_To_Integer (N);
- Discrete_Range_Check;
-
else
pragma Assert (Is_Floating_Point_Type (Target_Type));
Expand_Convert_Fixed_To_Float (N);
- Real_Range_Check;
end if;
-- Case of conversions to a fixed-point type
@@ -12497,11 +12574,9 @@ package body Exp_Ch4 is
then
if Is_Integer_Type (Operand_Type) then
Expand_Convert_Integer_To_Fixed (N);
- Real_Range_Check;
else
pragma Assert (Is_Floating_Point_Type (Operand_Type));
Expand_Convert_Float_To_Fixed (N);
- Real_Range_Check;
end if;
-- Case of array conversions
@@ -12661,8 +12736,6 @@ package body Exp_Ch4 is
-- Here at end of processing
<<Done>>
- pragma Assert (not Do_Range_Check (N));
-
-- Apply predicate check if required. Note that we can't just call
-- Apply_Predicate_Check here, because the type looks right after
-- the conversion and it would omit the check. The Comes_From_Source
@@ -12734,56 +12807,6 @@ package body Exp_Ch4 is
return;
end if;
- -- If we have a conversion of a compile time known value to a target
- -- type and the value is in range of the target type, then we can simply
- -- replace the construct by an integer literal of the correct type. We
- -- only apply this to discrete types being converted. Possibly it may
- -- apply in other cases, but it is too much trouble to worry about.
-
- -- Note that we do not do this transformation if the Kill_Range_Check
- -- flag is set, since then the value may be outside the expected range.
- -- This happens in the Normalize_Scalars case.
-
- -- We also skip this if either the target or operand type is biased
- -- because in this case, the unchecked conversion is supposed to
- -- preserve the bit pattern, not the integer value.
-
- if Is_Integer_Type (Target_Type)
- and then not Has_Biased_Representation (Target_Type)
- and then Is_Discrete_Type (Operand_Type)
- and then not Has_Biased_Representation (Operand_Type)
- and then Compile_Time_Known_Value (Operand)
- and then not Kill_Range_Check (N)
- then
- declare
- Val : constant Uint := Expr_Rep_Value (Operand);
-
- begin
- if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
- and then
- Compile_Time_Known_Value (Type_High_Bound (Target_Type))
- and then
- Val >= Expr_Value (Type_Low_Bound (Target_Type))
- and then
- Val <= Expr_Value (Type_High_Bound (Target_Type))
- then
- Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
-
- -- If Address is the target type, just set the type to avoid a
- -- spurious type error on the literal when Address is a visible
- -- integer type.
-
- if Is_Descendant_Of_Address (Target_Type) then
- Set_Etype (N, Target_Type);
- else
- Analyze_And_Resolve (N, Target_Type);
- end if;
-
- return;
- end if;
- end;
- end if;
-
-- Generate an extra temporary for cases unsupported by the C backend
if Modify_Tree_For_C then
@@ -13294,7 +13317,8 @@ package body Exp_Ch4 is
-- will be to universal real, and our real type comes from the Round
-- attribute (as well as an indication that we must round the result)
- if Nkind (Parent (Conv)) = N_Attribute_Reference
+ if Etype (Conv) = Universal_Real
+ and then Nkind (Parent (Conv)) = N_Attribute_Reference
and then Attribute_Name (Parent (Conv)) = Name_Round
then
Set_Etype (N, Base_Type (Etype (Parent (Conv))));
@@ -13932,6 +13956,15 @@ package body Exp_Ch4 is
-- return C;
-- end Annn;
+ -- or in the case of Transform_Function_Array:
+
+ -- procedure Annn (A : typ; B: typ; RESULT: out typ) is
+ -- begin
+ -- for J in A'range loop
+ -- RESULT (J) := A (J) op B (J);
+ -- end loop;
+ -- end Annn;
+
-- Here typ is the boolean array type
function Make_Boolean_Array_Op
@@ -13942,9 +13975,10 @@ package body Exp_Ch4 is
A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
- C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
+ C : Entity_Id;
+
A_J : Node_Id;
B_J : Node_Id;
C_J : Node_Id;
@@ -13956,6 +13990,12 @@ package body Exp_Ch4 is
Loop_Statement : Node_Id;
begin
+ if Transform_Function_Array then
+ C := Make_Defining_Identifier (Loc, Name_UP_RESULT);
+ else
+ C := Make_Defining_Identifier (Loc, Name_uC);
+ end if;
+
A_J :=
Make_Indexed_Component (Loc,
Prefix => New_Occurrence_Of (A, Loc),
@@ -14018,28 +14058,52 @@ package body Exp_Ch4 is
Defining_Identifier => B,
Parameter_Type => New_Occurrence_Of (Typ, Loc)));
+ if Transform_Function_Array then
+ Append_To (Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => C,
+ Out_Present => True,
+ Parameter_Type => New_Occurrence_Of (Typ, Loc)));
+ end if;
+
Func_Name := Make_Temporary (Loc, 'A');
Set_Is_Inlined (Func_Name);
- Func_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Function_Specification (Loc,
- Defining_Unit_Name => Func_Name,
- Parameter_Specifications => Formals,
- Result_Definition => New_Occurrence_Of (Typ, Loc)),
+ if Transform_Function_Array then
+ Func_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Func_Name,
+ Parameter_Specifications => Formals),
- Declarations => New_List (
- Make_Object_Declaration (Loc,
- Defining_Identifier => C,
- Object_Definition => New_Occurrence_Of (Typ, Loc))),
+ Declarations => New_List,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (
- Loop_Statement,
- Make_Simple_Return_Statement (Loc,
- Expression => New_Occurrence_Of (C, Loc)))));
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Loop_Statement)));
+
+ else
+ Func_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Function_Specification (Loc,
+ Defining_Unit_Name => Func_Name,
+ Parameter_Specifications => Formals,
+ Result_Definition => New_Occurrence_Of (Typ, Loc)),
+
+ Declarations => New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => C,
+ Object_Definition => New_Occurrence_Of (Typ, Loc))),
+
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Loop_Statement,
+ Make_Simple_Return_Statement (Loc,
+ Expression => New_Occurrence_Of (C, Loc)))));
+ end if;
return Func_Body;
end Make_Boolean_Array_Op;
@@ -14996,6 +15060,14 @@ package body Exp_Ch4 is
return;
end if;
+ -- If both operands are static, then the comparison has been already
+ -- folded in evaluation.
+
+ pragma Assert
+ (not Is_Static_Expression (Left_Opnd (N))
+ or else
+ not Is_Static_Expression (Right_Opnd (N)));
+
-- Determine the potential outcome of the comparison assuming that the
-- operands are valid and emit a warning when the comparison evaluates
-- to True or False only in the presence of invalid values.
@@ -15011,7 +15083,8 @@ package body Exp_Ch4 is
True_Result => True_Result,
False_Result => False_Result);
- -- The outcome is a decisive False or True, rewrite the operator
+ -- The outcome is a decisive False or True, rewrite the operator into a
+ -- non-static literal.
if False_Result or True_Result then
Rewrite (N,
@@ -15019,6 +15092,7 @@ package body Exp_Ch4 is
New_Occurrence_Of (Boolean_Literals (True_Result), Sloc (N))));
Analyze_And_Resolve (N, Typ);
+ Set_Is_Static_Expression (N, False);
Warn_On_Known_Condition (N);
end if;
end Rewrite_Comparison;
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 93351cf..4cae2ee 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -1469,7 +1469,7 @@ package body Exp_Ch5 is
-- there are volatile or independent components. If the Prefix of the
-- slice is a component or slice, then it might be a part of an object
-- with some other volatile or independent components, so we disable the
- -- optimization in that case as well. We could complicate this code by
+ -- optimization in that case as well. We could complicate this code by
-- actually looking for such volatile and independent components.
if Is_Bit_Packed_Array (L_Type)
@@ -1623,14 +1623,27 @@ package body Exp_Ch5 is
CI : constant List_Id := Component_Items (CL);
VP : constant Node_Id := Variant_Part (CL);
- Alts : List_Id;
- DC : Node_Id;
- DCH : List_Id;
- Expr : Node_Id;
- Result : List_Id;
- V : Node_Id;
+ Constrained_Typ : Entity_Id;
+ Alts : List_Id;
+ DC : Node_Id;
+ DCH : List_Id;
+ Expr : Node_Id;
+ Result : List_Id;
+ V : Node_Id;
begin
+ -- Try to find a constrained type to extract discriminant values
+ -- from, so that the case statement built below gets an
+ -- opportunity to be folded by Expand_N_Case_Statement.
+
+ if U_U or else Is_Constrained (Etype (Rhs)) then
+ Constrained_Typ := Etype (Rhs);
+ elsif Is_Constrained (Etype (Expression (N))) then
+ Constrained_Typ := Etype (Expression (N));
+ else
+ Constrained_Typ := Empty;
+ end if;
+
Result := Make_Field_Assigns (CI);
if Present (VP) then
@@ -1652,17 +1665,12 @@ package body Exp_Ch5 is
Next_Non_Pragma (V);
end loop;
- -- If we have an Unchecked_Union, use the value of the inferred
- -- discriminant of the variant part expression as the switch
- -- for the case statement. The case statement may later be
- -- folded.
-
- if U_U then
+ if Present (Constrained_Typ) then
Expr :=
New_Copy (Get_Discriminant_Value (
Entity (Name (VP)),
- Etype (Rhs),
- Discriminant_Constraint (Etype (Rhs))));
+ Constrained_Typ,
+ Discriminant_Constraint (Constrained_Typ)));
else
Expr :=
Make_Selected_Component (Loc,
@@ -1786,9 +1794,10 @@ package body Exp_Ch5 is
-- Start of processing for Expand_Assign_Record
begin
- -- Note that we use the base types for this processing. This results
- -- in some extra work in the constrained case, but the change of
- -- representation case is so unusual that it is not worth the effort.
+ -- Note that we need to use the base types for this processing in
+ -- order to retrieve the Type_Definition. In the constrained case,
+ -- we filter out the non relevant fields in
+ -- Make_Component_List_Assign.
-- First copy the discriminants. This is done unconditionally. It
-- is required in the unconstrained left side case, and also in the
@@ -1824,7 +1833,7 @@ package body Exp_Ch5 is
CF := F;
end if;
- if Is_Unchecked_Union (Base_Type (R_Typ)) then
+ if Is_Unchecked_Union (R_Typ) then
-- Within an initialization procedure this is the
-- assignment to an unchecked union component, in which
@@ -1916,8 +1925,8 @@ package body Exp_Ch5 is
Insert_Actions (N,
Make_Component_List_Assign (Component_List (RDef), True));
else
- Insert_Actions
- (N, Make_Component_List_Assign (Component_List (RDef)));
+ Insert_Actions (N,
+ Make_Component_List_Assign (Component_List (RDef)));
end if;
Rewrite (N, Make_Null_Statement (Loc));
@@ -4346,10 +4355,21 @@ package body Exp_Ch5 is
Iter_Pack := Scope (Root_Type (Etype (Iter_Type)));
-- Find declarations needed for "for ... of" optimization
+ -- These declarations come from GNAT sources or sources
+ -- derived from them. User code may include additional
+ -- overloadings with similar names, and we need to perforn
+ -- some reasonable resolution to find the needed primitives.
+ -- It is unclear whether this mechanism is fragile if a user
+ -- makes arbitrary changes to the private part of a package
+ -- that supports iterators.
Ent := First_Entity (Pack);
while Present (Ent) loop
- if Chars (Ent) = Name_Get_Element_Access then
+ if Chars (Ent) = Name_Get_Element_Access
+ and then Present (First_Formal (Ent))
+ and then Chars (First_Formal (Ent)) = Name_Position
+ and then No (Next_Formal (First_Formal (Ent)))
+ then
Fast_Element_Access_Op := Ent;
elsif Chars (Ent) = Name_Step
@@ -4670,6 +4690,16 @@ package body Exp_Ch5 is
New_Id : Entity_Id;
begin
+ -- If Discrete_Subtype_Definition has been rewritten as an
+ -- N_Raise_xxx_Error, rewrite the whole loop as a raise node to
+ -- avoid confusing the code generator down the line.
+
+ if Nkind (Discrete_Subtype_Definition (LPS)) in N_Raise_xxx_Error
+ then
+ Rewrite (N, Discrete_Subtype_Definition (LPS));
+ return;
+ end if;
+
if Present (Iterator_Filter (LPS)) then
pragma Assert (Ada_Version >= Ada_2020);
Set_Statements (N,
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index b762026..2cd40e4 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -883,9 +883,8 @@ package body Exp_Ch6 is
is
Loc : constant Source_Ptr := Sloc (Func_Body);
- Proc_Decl : constant Node_Id :=
- Next (Unit_Declaration_Node (Func_Id));
- -- It is assumed that the next node following the declaration of the
+ Proc_Decl : constant Node_Id := Prev (Unit_Declaration_Node (Func_Id));
+ -- It is assumed that the node before the declaration of the
-- corresponding subprogram spec is the declaration of the procedure
-- form.
@@ -2879,17 +2878,10 @@ package body Exp_Ch6 is
(Formal : Entity_Id)
is
Decl : Node_Id;
-
- -- Suppress warning for the final removal loop
- pragma Warnings (Off, Decl);
-
Lvl : Entity_Id;
- Res : Entity_Id;
- Temp : Node_Id;
- Typ : Node_Id;
procedure Insert_Level_Assign (Branch : Node_Id);
- -- Recursivly add assignment of the level temporary on each branch
+ -- Recursively add assignment of the level temporary on each branch
-- while moving through nested conditional expressions.
-------------------------
@@ -2917,12 +2909,10 @@ package body Exp_Ch6 is
-- There are more nested conditional expressions so we must go
-- deeper.
- if Nkind (Expression (Res_Assn)) =
- N_Expression_With_Actions
+ if Nkind (Expression (Res_Assn)) = N_Expression_With_Actions
and then
- Nkind
- (Original_Node (Expression (Res_Assn)))
- in N_Case_Expression | N_If_Expression
+ Nkind (Original_Node (Expression (Res_Assn)))
+ in N_Case_Expression | N_If_Expression
then
Insert_Level_Assign
(Expression (Res_Assn));
@@ -2932,9 +2922,7 @@ package body Exp_Ch6 is
else
Insert_Before_And_Analyze (Res_Assn,
Make_Assignment_Statement (Loc,
- Name =>
- New_Occurrence_Of
- (Lvl, Loc),
+ Name => New_Occurrence_Of (Lvl, Loc),
Expression =>
Accessibility_Level
(Expression (Res_Assn), Dynamic_Level)));
@@ -2956,9 +2944,7 @@ package body Exp_Ch6 is
Cond := First (Actions (Branch));
while Present (Cond) loop
- exit when Nkind (Cond) in
- N_Case_Statement | N_If_Statement;
-
+ exit when Nkind (Cond) in N_Case_Statement | N_If_Statement;
Next (Cond);
end loop;
@@ -2981,7 +2967,6 @@ package body Exp_Ch6 is
Alt := First (Alternatives (Cond));
while Present (Alt) loop
Expand_Branch (Last (Statements (Alt)));
-
Next (Alt);
end loop;
end if;
@@ -3000,7 +2985,7 @@ package body Exp_Ch6 is
New_Occurrence_Of (Standard_Natural, Loc));
-- Install the declaration and perform necessary expansion if we
- -- are dealing with a function call.
+ -- are dealing with a procedure call.
if Nkind (Call_Node) = N_Procedure_Call_Statement then
-- Generate:
@@ -3019,57 +3004,27 @@ package body Exp_Ch6 is
Insert_Before_And_Analyze (Call_Node, Decl);
- -- A function call must be transformed into an expression with
- -- actions.
+ -- Ditto for a function call. Note that we do not wrap the function
+ -- call into an expression with action to avoid bad interactions with
+ -- Exp_Ch4.Process_Transient_In_Expression.
else
-- Generate:
- -- do
- -- Lvl : Natural;
- -- in Call (do{
- -- If_Exp_Res : Typ
- -- if Cond then
- -- Lvl := 0; -- Access level
- -- If_Exp_Res := Exp;
- -- in If_Exp_Res end;},
- -- Lvl,
- -- ...
- -- )
- -- end;
-
- Res := Make_Temporary (Loc, 'R');
- Typ := Etype (Call_Node);
- Temp := Relocate_Node (Call_Node);
-
- -- Perform the rewrite with the dummy
-
- Rewrite (Call_Node,
-
- Make_Expression_With_Actions (Loc,
- Expression => New_Occurrence_Of (Res, Loc),
- Actions => New_List (
- Decl,
-
- Make_Object_Declaration (Loc,
- Defining_Identifier => Res,
- Object_Definition =>
- New_Occurrence_Of (Typ, Loc)))));
-
- -- Analyze the expression with the dummy
-
- Analyze_And_Resolve (Call_Node, Typ);
-
- -- Properly set the expression and move our view of the call node
-
- Set_Expression (Call_Node, Relocate_Node (Temp));
- Call_Node := Expression (Call_Node);
-
- -- Remove the declaration of the dummy and the subsequent actions
- -- its analysis has created.
+ -- Lvl : Natural; -- placed above the function call
+ -- ...
+ -- Func_Call (
+ -- {do
+ -- If_Exp_Res : Typ
+ -- if Cond then
+ -- Lvl := 0; -- Access level
+ -- If_Exp_Res := Exp;
+ -- in If_Exp_Res end;},
+ -- Lvl,
+ -- ...
+ -- )
- while Present (Remove_Next (Decl)) loop
- null;
- end loop;
+ Insert_Action (Call_Node, Decl);
+ Analyze (Call_Node);
end if;
-- Decorate the conditional expression with assignments to our level
@@ -3536,8 +3491,7 @@ package body Exp_Ch6 is
-- of the dimension I/O packages.
if Ada_Version >= Ada_2012
- and then
- Nkind (Call_Node) in N_Procedure_Call_Statement | N_Function_Call
+ and then Nkind (Call_Node) in N_Subprogram_Call
and then Present (Parameter_Associations (Call_Node))
then
Expand_Put_Call_With_Symbol (Call_Node);
@@ -3665,7 +3619,7 @@ package body Exp_Ch6 is
return;
end if;
- if Modify_Tree_For_C
+ if Transform_Function_Array
and then Nkind (Call_Node) = N_Function_Call
and then Is_Entity_Name (Name (Call_Node))
then
@@ -3681,9 +3635,9 @@ package body Exp_Ch6 is
-- For internally generated calls ensure that they reference
-- the entity of the spec of the called function (needed since
-- the expander may generate calls using the entity of their
- -- body). See for example Expand_Boolean_Operator().
+ -- body).
- if not (Comes_From_Source (Call_Node))
+ if not Comes_From_Source (Call_Node)
and then Nkind (Unit_Declaration_Node (Func_Id)) =
N_Subprogram_Body
then
@@ -3700,7 +3654,8 @@ package body Exp_Ch6 is
-- are passed by pointer in the generated C code, and we cannot
-- take a pointer from a subprogram call.
- elsif Nkind (Parent (Call_Node)) in N_Subprogram_Call
+ elsif Modify_Tree_For_C
+ and then Nkind (Parent (Call_Node)) in N_Subprogram_Call
and then Is_Record_Type (Etype (Func_Id))
then
declare
@@ -5427,13 +5382,15 @@ package body Exp_Ch6 is
end if;
-- Build a simple_return_statement that returns the return object when
- -- there is a statement sequence, or no expression, or the result will
- -- be built in place. Note however that we currently do this for all
- -- composite cases, even though not all are built in place.
+ -- there is a statement sequence, or no expression, or the analysis of
+ -- the return object declaration generated extra actions, or the result
+ -- will be built in place. Note however that we currently do this for
+ -- all composite cases, even though they are not built in place.
if Present (HSS)
- or else Is_Composite_Type (Ret_Typ)
or else No (Exp)
+ or else List_Length (Return_Object_Declarations (N)) > 1
+ or else Is_Composite_Type (Ret_Typ)
then
if No (HSS) then
Stmts := New_List;
@@ -5543,7 +5500,7 @@ package body Exp_Ch6 is
(Expression (Original_Node (Ret_Obj_Decl)))
-- It is a BIP object declaration that displaces the pointer
- -- to the object to reference a convered interface type.
+ -- to the object to reference a converted interface type.
or else
Present (Unqual_BIP_Iface_Function_Call
@@ -6101,16 +6058,11 @@ package body Exp_Ch6 is
end;
end if;
- -- Case where we do not build a block
+ -- Case where we do not need to build a block. But we're about to drop
+ -- Return_Object_Declarations on the floor, so assert that it contains
+ -- only the return object declaration.
- else
- -- We're about to drop Return_Object_Declarations on the floor, so
- -- we need to insert it, in case it got expanded into useful code.
- -- Remove side effects from expression, which may be duplicated in
- -- subsequent checks (see Expand_Simple_Function_Return).
-
- Insert_List_Before (N, Return_Object_Declarations (N));
- Remove_Side_Effects (Exp);
+ else pragma Assert (List_Length (Return_Object_Declarations (N)) = 1);
-- Build simple_return_statement that returns the expression directly
@@ -6293,9 +6245,24 @@ package body Exp_Ch6 is
-- Call the _Postconditions procedure if the related subprogram
-- has contract assertions that need to be verified on exit.
+ -- Also, mark the successful return to signal that postconditions
+ -- need to be evaluated when finalization occurs.
+
if Ekind (Spec_Id) = E_Procedure
and then Present (Postconditions_Proc (Spec_Id))
then
+ -- Generate:
+ --
+ -- Return_Success_For_Postcond := True;
+ -- _postconditions;
+
+ Insert_Action (Stmt,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Get_Return_Success_For_Postcond (Spec_Id), Loc),
+ Expression => New_Occurrence_Of (Standard_True, Loc)));
+
Insert_Action (Stmt,
Make_Procedure_Call_Statement (Loc,
Name =>
@@ -6617,6 +6584,7 @@ package body Exp_Ch6 is
Prot_Bod : Node_Id;
Prot_Decl : Node_Id;
Prot_Id : Entity_Id;
+ Typ : Entity_Id;
begin
-- Deal with case of protected subprogram. Do not generate protected
@@ -6691,10 +6659,12 @@ package body Exp_Ch6 is
-- are not needed by the C generator (and this also produces cleaner
-- output).
- if Modify_Tree_For_C
+ Typ := Get_Fullest_View (Etype (Subp));
+
+ if Transform_Function_Array
and then Nkind (Specification (N)) = N_Function_Specification
- and then Is_Array_Type (Etype (Subp))
- and then Is_Constrained (Etype (Subp))
+ and then Is_Array_Type (Typ)
+ and then Is_Constrained (Typ)
and then not Is_Unchecked_Conversion_Instance (Subp)
then
Build_Procedure_Form (N);
@@ -6720,9 +6690,24 @@ package body Exp_Ch6 is
-- Call the _Postconditions procedure if the related subprogram has
-- contract assertions that need to be verified on exit.
+ -- Also, mark the successful return to signal that postconditions need
+ -- to be evaluated when finalization occurs.
+
if Ekind (Scope_Id) in E_Entry | E_Entry_Family | E_Procedure
and then Present (Postconditions_Proc (Scope_Id))
then
+ -- Generate:
+ --
+ -- Return_Success_For_Postcond := True;
+ -- _postconditions;
+
+ Insert_Action (N,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Get_Return_Success_For_Postcond (Scope_Id), Loc),
+ Expression => New_Occurrence_Of (Standard_True, Loc)));
+
Insert_Action (N,
Make_Procedure_Call_Statement (Loc,
Name => New_Occurrence_Of (Postconditions_Proc (Scope_Id), Loc)));
@@ -7609,6 +7594,41 @@ package body Exp_Ch6 is
Force_Evaluation (Exp, Mode => Strict);
+ -- Save the return value or a pointer to the return value since we
+ -- may need to call postconditions after finalization when cleanup
+ -- actions are present.
+
+ -- Generate:
+ --
+ -- Result_Object_For_Postcond := [Exp]'Unrestricted_Access;
+
+ Insert_Action (Exp,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Get_Result_Object_For_Postcond (Scope_Id), Loc),
+ Expression =>
+ (if Is_Elementary_Type (Etype (R_Type)) then
+ New_Copy_Tree (Exp)
+ else
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Unrestricted_Access,
+ Prefix => New_Copy_Tree (Exp)))));
+
+ -- Mark the successful return to signal that postconditions need to
+ -- be evaluated when finalization occurs.
+
+ -- Generate:
+ --
+ -- Return_Success_For_Postcond := True;
+
+ Insert_Action (Exp,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Get_Return_Success_For_Postcond (Scope_Id), Loc),
+ Expression => New_Occurrence_Of (Standard_True, Loc)));
+
-- Generate call to _Postconditions
Insert_Action (Exp,
@@ -8137,6 +8157,7 @@ package body Exp_Ch6 is
if True then
Result := Is_Controlled (T)
+ and then not Is_Generic_Actual_Type (T)
and then Present (Enclosing_Subprogram (T))
and then not Is_Compilation_Unit (Enclosing_Subprogram (T))
and then Ekind (Enclosing_Subprogram (T)) = E_Procedure;
@@ -9321,7 +9342,7 @@ package body Exp_Ch6 is
Tmp_Id : Entity_Id;
begin
- -- No action of the call has already been processed
+ -- No action if the call has already been processed
if Is_Expanded_Build_In_Place_Call (BIP_Func_Call) then
return;
@@ -9996,7 +10017,7 @@ package body Exp_Ch6 is
procedure Warn_BIP (Func_Call : Node_Id) is
begin
if Debug_Flag_Underscore_BB then
- Error_Msg_N ("build-in-place function call?", Func_Call);
+ Error_Msg_N ("build-in-place function call??", Func_Call);
end if;
end Warn_BIP;
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index b58a3c1..5d8ad7d 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -27,42 +27,43 @@
-- - controlled types
-- - transient scopes
-with Atree; use Atree;
-with Debug; use Debug;
-with Einfo; use Einfo;
-with Elists; use Elists;
-with Errout; use Errout;
-with Exp_Ch6; use Exp_Ch6;
-with Exp_Ch9; use Exp_Ch9;
-with Exp_Ch11; use Exp_Ch11;
-with Exp_Dbug; use Exp_Dbug;
-with Exp_Dist; use Exp_Dist;
-with Exp_Disp; use Exp_Disp;
-with Exp_Prag; use Exp_Prag;
-with Exp_Tss; use Exp_Tss;
-with Exp_Util; use Exp_Util;
-with Freeze; use Freeze;
-with Lib; use Lib;
-with Nlists; use Nlists;
-with Nmake; use Nmake;
-with Opt; use Opt;
-with Output; use Output;
-with Restrict; use Restrict;
-with Rident; use Rident;
-with Rtsfind; use Rtsfind;
-with Sinfo; use Sinfo;
-with Sem; use Sem;
-with Sem_Aux; use Sem_Aux;
-with Sem_Ch3; use Sem_Ch3;
-with Sem_Ch7; use Sem_Ch7;
-with Sem_Ch8; use Sem_Ch8;
-with Sem_Res; use Sem_Res;
-with Sem_Util; use Sem_Util;
-with Snames; use Snames;
-with Stand; use Stand;
-with Tbuild; use Tbuild;
-with Ttypes; use Ttypes;
-with Uintp; use Uintp;
+with Atree; use Atree;
+with Contracts; use Contracts;
+with Debug; use Debug;
+with Einfo; use Einfo;
+with Elists; use Elists;
+with Errout; use Errout;
+with Exp_Ch6; use Exp_Ch6;
+with Exp_Ch9; use Exp_Ch9;
+with Exp_Ch11; use Exp_Ch11;
+with Exp_Dbug; use Exp_Dbug;
+with Exp_Dist; use Exp_Dist;
+with Exp_Disp; use Exp_Disp;
+with Exp_Prag; use Exp_Prag;
+with Exp_Tss; use Exp_Tss;
+with Exp_Util; use Exp_Util;
+with Freeze; use Freeze;
+with Lib; use Lib;
+with Nlists; use Nlists;
+with Nmake; use Nmake;
+with Opt; use Opt;
+with Output; use Output;
+with Restrict; use Restrict;
+with Rident; use Rident;
+with Rtsfind; use Rtsfind;
+with Sinfo; use Sinfo;
+with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Ch3; use Sem_Ch3;
+with Sem_Ch7; use Sem_Ch7;
+with Sem_Ch8; use Sem_Ch8;
+with Sem_Res; use Sem_Res;
+with Sem_Util; use Sem_Util;
+with Snames; use Snames;
+with Stand; use Stand;
+with Tbuild; use Tbuild;
+with Ttypes; use Ttypes;
+with Uintp; use Uintp;
package body Exp_Ch7 is
@@ -339,6 +340,17 @@ package body Exp_Ch7 is
-- such as for task termination. Fin_Id is the finalizer declaration
-- entity.
+ procedure Build_Finalizer_Helper
+ (N : Node_Id;
+ Clean_Stmts : List_Id;
+ Mark_Id : Entity_Id;
+ Top_Decls : List_Id;
+ Defer_Abort : Boolean;
+ Fin_Id : out Entity_Id;
+ Finalize_Old_Only : Boolean);
+ -- An internal routine which does all of the heavy lifting on behalf of
+ -- Build_Finalizer.
+
procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
-- N is a construct which contains a handled sequence of statements, Fin_Id
-- is the entity of a finalizer. Create an At_End handler which covers the
@@ -1273,6 +1285,10 @@ package body Exp_Ch7 is
Object_Definition =>
New_Occurrence_Of (RTE (RE_Finalization_Master), Loc)));
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Fin_Mas_Id);
+ end if;
+
-- Set the associated pool and primitive Finalize_Address of the new
-- finalization master.
@@ -1393,20 +1409,32 @@ package body Exp_Ch7 is
else
Append_Freeze_Actions (Ptr_Typ, Actions);
end if;
+
+ Analyze_List (Actions);
+
+ -- When the type the finalization master is being generated for was
+ -- created to store a 'Old object, then mark it as such so its
+ -- finalization can be delayed until after postconditions have been
+ -- checked.
+
+ if Stores_Attribute_Old_Prefix (Ptr_Typ) then
+ Set_Stores_Attribute_Old_Prefix (Fin_Mas_Id);
+ end if;
end;
end Build_Finalization_Master;
- ---------------------
- -- Build_Finalizer --
- ---------------------
+ ----------------------------
+ -- Build_Finalizer_Helper --
+ ----------------------------
- procedure Build_Finalizer
+ procedure Build_Finalizer_Helper
(N : Node_Id;
Clean_Stmts : List_Id;
Mark_Id : Entity_Id;
Top_Decls : List_Id;
Defer_Abort : Boolean;
- Fin_Id : out Entity_Id)
+ Fin_Id : out Entity_Id;
+ Finalize_Old_Only : Boolean)
is
Acts_As_Clean : constant Boolean :=
Present (Mark_Id)
@@ -1616,6 +1644,10 @@ package body Exp_Ch7 is
Set_Etype (Counter_Id, Counter_Typ);
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Counter_Id);
+ end if;
+
-- The counter and its type are inserted before the source
-- declarations of N.
@@ -1738,9 +1770,20 @@ package body Exp_Ch7 is
-- The default name is _finalizer
else
- Fin_Id :=
- Make_Defining_Identifier (Loc,
- Chars => New_External_Name (Name_uFinalizer));
+ -- Generation of a finalization procedure exclusively for 'Old
+ -- interally generated constants requires different name since
+ -- there will need to be multiple finalization routines in the
+ -- same scope. See Build_Finalizer for details.
+
+ if Finalize_Old_Only then
+ Fin_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Name_uFinalizer_Old));
+ else
+ Fin_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Name_uFinalizer));
+ end if;
-- The visibility semantics of AT_END handlers force a strange
-- separation of spec and body for stack-related finalizers:
@@ -1778,7 +1821,11 @@ package body Exp_Ch7 is
-- exactly twice (once on the normal path, and once for
-- exceptions/abort), so this won't bloat the code too much.
- Set_Is_Inlined (Fin_Id);
+ Set_Is_Inlined (Fin_Id);
+ end if;
+
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Fin_Id);
end if;
-- Step 2: Creation of the finalizer specification
@@ -1969,6 +2016,10 @@ package body Exp_Ch7 is
Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Body_Id);
+ end if;
+
if For_Package then
Set_Has_Qualified_Name (Body_Id);
Set_Has_Fully_Qualified_Name (Body_Id);
@@ -2035,8 +2086,26 @@ package body Exp_Ch7 is
pragma Assert (Present (Spec_Decls));
- Append_To (Spec_Decls, Fin_Spec);
- Analyze (Fin_Spec);
+ -- It maybe possible that we are finalizing 'Old objects which
+ -- exist in the spec declarations. When this is the case the
+ -- Finalizer_Insert_Node will come before the end of the
+ -- Spec_Decls. So, to mitigate this, we insert the finalizer spec
+ -- earlier at the Finalizer_Insert_Nod instead of appending to the
+ -- end of Spec_Decls to prevent its body appearing before its
+ -- corresponding spec.
+
+ if Present (Finalizer_Insert_Nod)
+ and then List_Containing (Finalizer_Insert_Nod) = Spec_Decls
+ then
+ Insert_After_And_Analyze (Finalizer_Insert_Nod, Fin_Spec);
+ Finalizer_Insert_Nod := Fin_Spec;
+
+ -- Otherwise, Finalizer_Insert_Nod is not in Spec_Decls
+
+ else
+ Append_To (Spec_Decls, Fin_Spec);
+ Analyze (Fin_Spec);
+ end if;
-- When the finalizer acts solely as a cleanup routine, the body
-- is inserted right after the spec.
@@ -2178,9 +2247,26 @@ package body Exp_Ch7 is
Decl := Last_Non_Pragma (Decls);
while Present (Decl) loop
+ -- Depending on the value of flag Finalize_Old_Only we determine
+ -- which objects get finalized as part of the current finalizer
+ -- being built.
+
+ -- When True, only temporaries capturing the value of attribute
+ -- 'Old are finalized and all other cases are ignored.
+
+ -- When False, temporary objects used to capture the value of 'Old
+ -- are ignored and all others are considered.
+
+ if Finalize_Old_Only
+ xor (Nkind (Decl) = N_Object_Declaration
+ and then Stores_Attribute_Old_Prefix
+ (Defining_Identifier (Decl)))
+ then
+ null;
+
-- Library-level tagged types
- if Nkind (Decl) = N_Full_Type_Declaration then
+ elsif Nkind (Decl) = N_Full_Type_Declaration then
Typ := Defining_Identifier (Decl);
-- Ignored Ghost types do not need any cleanup actions because
@@ -2400,8 +2486,7 @@ package body Exp_Ch7 is
if Is_Ignored_Ghost_Entity (Typ) then
null;
- elsif (Is_Access_Type (Typ)
- and then not Is_Access_Subprogram_Type (Typ)
+ elsif (Is_Access_Object_Type (Typ)
and then Needs_Finalization
(Available_View (Designated_Type (Typ))))
or else (Is_Type (Typ) and then Needs_Finalization (Typ))
@@ -2648,6 +2733,10 @@ package body Exp_Ch7 is
Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Pool_Id);
+ end if;
+
-- Create an explicit free statement. Note that the free uses the
-- caller's pool expressed as a renaming.
@@ -3390,7 +3479,7 @@ package body Exp_Ch7 is
New_Occurrence_Of (DT_Ptr, Loc))));
end Process_Tagged_Type_Declaration;
- -- Start of processing for Build_Finalizer
+ -- Start of processing for Build_Finalizer_Helper
begin
Fin_Id := Empty;
@@ -3540,7 +3629,7 @@ package body Exp_Ch7 is
if Acts_As_Clean or else Has_Ctrl_Objs or else Has_Tagged_Types then
Create_Finalizer;
end if;
- end Build_Finalizer;
+ end Build_Finalizer_Helper;
--------------------------
-- Build_Finalizer_Call --
@@ -3624,6 +3713,468 @@ package body Exp_Ch7 is
end Build_Finalizer_Call;
---------------------
+ -- Build_Finalizer --
+ ---------------------
+
+ procedure Build_Finalizer
+ (N : Node_Id;
+ Clean_Stmts : List_Id;
+ Mark_Id : Entity_Id;
+ Top_Decls : List_Id;
+ Defer_Abort : Boolean;
+ Fin_Id : out Entity_Id)
+ is
+ Def_Ent : constant Entity_Id := Unique_Defining_Entity (N);
+ Loc : constant Source_Ptr := Sloc (N);
+
+ -- Declarations used for the creation of _finalization_controller
+
+ Fin_Old_Id : Entity_Id := Empty;
+ Fin_Controller_Id : Entity_Id := Empty;
+ Fin_Controller_Decls : List_Id;
+ Fin_Controller_Stmts : List_Id;
+ Fin_Controller_Body : Node_Id := Empty;
+ Fin_Controller_Spec : Node_Id := Empty;
+ Postconditions_Call : Node_Id := Empty;
+
+ -- Defining identifiers for local objects used to store exception info
+
+ Raised_Post_Exception_Id : Entity_Id := Empty;
+ Raised_Finalization_Exception_Id : Entity_Id := Empty;
+ Saved_Exception_Id : Entity_Id := Empty;
+
+ -- Start of processing for Build_Finalizer
+
+ begin
+ -- Create the general finalization routine
+
+ Build_Finalizer_Helper
+ (N => N,
+ Clean_Stmts => Clean_Stmts,
+ Mark_Id => Mark_Id,
+ Top_Decls => Top_Decls,
+ Defer_Abort => Defer_Abort,
+ Fin_Id => Fin_Id,
+ Finalize_Old_Only => False);
+
+ -- When postconditions are present, expansion gets much more complicated
+ -- due to both the fact that they must be called after finalization and
+ -- that finalization of 'Old objects must occur after the postconditions
+ -- get checked.
+
+ -- Additionally, exceptions between general finalization and 'Old
+ -- finalization must be propagated correctly and exceptions which happen
+ -- during _postconditions need to be saved and reraised after
+ -- finalization of 'Old objects.
+
+ -- Generate:
+ --
+ -- Postcond_Enabled := False;
+ --
+ -- procedure _finalization_controller is
+ --
+ -- -- Exception capturing and tracking
+ --
+ -- Saved_Exception : Exception_Occurrence;
+ -- Raised_Post_Exception : Boolean := False;
+ -- Raised_Finalization_Exception : Boolean := False;
+ --
+ -- -- Start of processing for _finalization_controller
+ --
+ -- begin
+ -- -- Perform general finalization
+ --
+ -- begin
+ -- _finalizer;
+ -- exception
+ -- when others =>
+ -- -- Save the exception
+ --
+ -- Raised_Finalization_Exception := True;
+ -- Save_Occurrence
+ -- (Saved_Exception, Get_Current_Excep.all);
+ -- end;
+ --
+ -- -- Perform postcondition checks after general finalization, but
+ -- -- before finalization of 'Old related objects.
+ --
+ -- if not Raised_Finalization_Exception then
+ -- begin
+ -- -- Re-enable postconditions and check them
+ --
+ -- Postcond_Enabled := True;
+ -- _postconditions [(Result_Obj_For_Postcond[.all])];
+ -- exception
+ -- when others =>
+ -- -- Save the exception
+ --
+ -- Raised_Post_Exception := True;
+ -- Save_Occurrence
+ -- (Saved_Exception, Get_Current_Excep.all);
+ -- end;
+ -- end if;
+ --
+ -- -- Finally finalize 'Old related objects
+ --
+ -- begin
+ -- _finalizer_old;
+ -- exception
+ -- when others =>
+ -- -- Reraise the previous finalization error if there is
+ -- -- one.
+ --
+ -- if Raised_Finalization_Exception then
+ -- Reraise_Occurrence (Saved_Exception);
+ -- end if;
+ --
+ -- -- Otherwise, reraise the current one
+ --
+ -- raise;
+ -- end;
+ --
+ -- -- Reraise any saved exception
+ --
+ -- if Raised_Finalization_Exception
+ -- or else Raised_Post_Exception
+ -- then
+ -- Reraise_Occurrence (Saved_Exception);
+ -- end if;
+ -- end _finalization_controller;
+
+ if Nkind (N) = N_Subprogram_Body
+ and then Present (Postconditions_Proc (Def_Ent))
+ then
+ Fin_Controller_Stmts := New_List;
+ Fin_Controller_Decls := New_List;
+
+ -- Build the 'Old finalizer
+
+ Build_Finalizer_Helper
+ (N => N,
+ Clean_Stmts => Empty_List,
+ Mark_Id => Mark_Id,
+ Top_Decls => Top_Decls,
+ Defer_Abort => Defer_Abort,
+ Fin_Id => Fin_Old_Id,
+ Finalize_Old_Only => True);
+
+ -- Create local declarations for _finalization_controller needed for
+ -- saving exceptions.
+ --
+ -- Generate:
+ --
+ -- Saved_Exception : Exception_Occurrence;
+ -- Raised_Post_Exception : Boolean := False;
+ -- Raised_Finalization_Exception : Boolean := False;
+
+ Saved_Exception_Id := Make_Temporary (Loc, 'S');
+ Raised_Post_Exception_Id := Make_Temporary (Loc, 'P');
+ Raised_Finalization_Exception_Id := Make_Temporary (Loc, 'F');
+
+ Append_List_To (Fin_Controller_Decls, New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Saved_Exception_Id,
+ Object_Definition =>
+ New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc)),
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Raised_Post_Exception_Id,
+ Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
+ Expression => New_Occurrence_Of (Standard_False, Loc)),
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Raised_Finalization_Exception_Id,
+ Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
+ Expression => New_Occurrence_Of (Standard_False, Loc))));
+
+ -- Call _finalizer and save any exceptions which occur
+
+ -- Generate:
+ --
+ -- begin
+ -- _finalizer;
+ -- exception
+ -- when others =>
+ -- Raised_Finalization_Exception := True;
+ -- Save_Occurrence
+ -- (Saved_Exception, Get_Current_Excep.all);
+ -- end;
+
+ if Present (Fin_Id) then
+ Append_To (Fin_Controller_Stmts,
+ Make_Block_Statement (Loc,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Fin_Id, Loc))),
+ Exception_Handlers => New_List (
+ Make_Exception_Handler (Loc,
+ Exception_Choices => New_List (
+ Make_Others_Choice (Loc)),
+ Statements => New_List (
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Raised_Finalization_Exception_Id, Loc),
+ Expression =>
+ New_Occurrence_Of (Standard_True, Loc)),
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Save_Occurrence), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of
+ (Saved_Exception_Id, Loc),
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Make_Function_Call (Loc,
+ Name =>
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ New_Occurrence_Of
+ (RTE (RE_Get_Current_Excep),
+ Loc))))))))))));
+ end if;
+
+ -- Create the call to postconditions based on the kind of the current
+ -- subprogram, and the type of the Result_Obj_For_Postcond.
+
+ -- Generate:
+ --
+ -- _postconditions (Result_Obj_For_Postcond[.all]);
+ --
+ -- or
+ --
+ -- _postconditions;
+
+ if Ekind (Def_Ent) = E_Procedure then
+ Postconditions_Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Postconditions_Proc (Def_Ent), Loc));
+ else
+ Postconditions_Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Postconditions_Proc (Def_Ent), Loc),
+ Parameter_Associations => New_List (
+ (if Is_Elementary_Type (Etype (Def_Ent)) then
+ New_Occurrence_Of
+ (Get_Result_Object_For_Postcond
+ (Def_Ent), Loc)
+ else
+ Make_Explicit_Dereference (Loc,
+ New_Occurrence_Of
+ (Get_Result_Object_For_Postcond
+ (Def_Ent), Loc)))));
+ end if;
+
+ -- Call _postconditions when no general finalization exceptions have
+ -- occured taking care to enable the postconditions and save any
+ -- exception occurrences.
+
+ -- Generate:
+ --
+ -- if not Raised_Finalization_Exception then
+ -- begin
+ -- Postcond_Enabled := True;
+ -- _postconditions [(Result_Obj_For_Postcond[.all])];
+ -- exception
+ -- when others =>
+ -- Raised_Post_Exception := True;
+ -- Save_Occurrence
+ -- (Saved_Exception, Get_Current_Excep.all);
+ -- end;
+ -- end if;
+
+ Append_To (Fin_Controller_Stmts,
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Op_Not (Loc,
+ Right_Opnd =>
+ New_Occurrence_Of
+ (Raised_Finalization_Exception_Id, Loc)),
+ Then_Statements => New_List (
+ Make_Block_Statement (Loc,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Get_Postcond_Enabled (Def_Ent), Loc),
+ Expression =>
+ New_Occurrence_Of
+ (Standard_True, Loc)),
+ Postconditions_Call),
+ Exception_Handlers => New_List (
+ Make_Exception_Handler (Loc,
+ Exception_Choices => New_List (
+ Make_Others_Choice (Loc)),
+ Statements => New_List (
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Raised_Post_Exception_Id, Loc),
+ Expression =>
+ New_Occurrence_Of (Standard_True, Loc)),
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Save_Occurrence), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of
+ (Saved_Exception_Id, Loc),
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Make_Function_Call (Loc,
+ Name =>
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ New_Occurrence_Of
+ (RTE (RE_Get_Current_Excep),
+ Loc))))))))))))));
+
+ -- Call _finalizer_old and reraise any exception that occurred during
+ -- initial finalization within the exception handler. Otherwise,
+ -- propagate the current exception.
+
+ -- Generate:
+ --
+ -- begin
+ -- _finalizer_old;
+ -- exception
+ -- when others =>
+ -- if Raised_Finalization_Exception then
+ -- Reraise_Occurrence (Saved_Exception);
+ -- end if;
+ -- raise;
+ -- end;
+
+ if Present (Fin_Old_Id) then
+ Append_To (Fin_Controller_Stmts,
+ Make_Block_Statement (Loc,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Fin_Old_Id, Loc))),
+ Exception_Handlers => New_List (
+ Make_Exception_Handler (Loc,
+ Exception_Choices => New_List (
+ Make_Others_Choice (Loc)),
+ Statements => New_List (
+ Make_If_Statement (Loc,
+ Condition =>
+ New_Occurrence_Of
+ (Raised_Finalization_Exception_Id, Loc),
+ Then_Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Reraise_Occurrence), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of
+ (Saved_Exception_Id, Loc))))),
+ Make_Raise_Statement (Loc)))))));
+ end if;
+
+ -- Once finalization is complete reraise any pending exceptions
+
+ -- Generate:
+ --
+ -- if Raised_Post_Exception
+ -- or else Raised_Finalization_Exception
+ -- then
+ -- Reraise_Occurrence (Saved_Exception);
+ -- end if;
+
+ Append_To (Fin_Controller_Stmts,
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Or_Else (Loc,
+ Left_Opnd =>
+ New_Occurrence_Of
+ (Raised_Post_Exception_Id, Loc),
+ Right_Opnd =>
+ New_Occurrence_Of
+ (Raised_Finalization_Exception_Id, Loc)),
+ Then_Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Reraise_Occurrence), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of
+ (Saved_Exception_Id, Loc))))));
+
+ -- Make the finalization controller subprogram body and declaration.
+
+ -- Generate:
+ -- procedure _finalization_controller;
+ --
+ -- procedure _finalization_controller is
+ -- begin
+ -- [Fin_Controller_Stmts];
+ -- end;
+
+ Fin_Controller_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Name_uFinalization_Controller));
+
+ Fin_Controller_Spec :=
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Fin_Controller_Id));
+
+ Fin_Controller_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name =>
+ Make_Defining_Identifier (Loc, Chars (Fin_Controller_Id))),
+ Declarations => Fin_Controller_Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => Fin_Controller_Stmts));
+
+ -- Disable _postconditions calls which get generated before return
+ -- statements to delay their evaluation until after finalization.
+
+ -- This is done by way of the local Postcond_Enabled object which is
+ -- initially assigned to True - we then create an assignment within
+ -- the subprogram's declaration to make it False and assign it back
+ -- to True before _postconditions is called within
+ -- _finalization_controller.
+
+ -- Generate:
+ --
+ -- Postcond_Enable := False;
+
+ Append_To (Top_Decls,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Occurrence_Of
+ (Get_Postcond_Enabled (Def_Ent), Loc),
+ Expression =>
+ New_Occurrence_Of
+ (Standard_False, Loc)));
+
+ -- Add the subprogram to the list of declarations an analyze it
+
+ Append_To (Top_Decls, Fin_Controller_Spec);
+ Analyze (Fin_Controller_Spec);
+ Insert_After (Fin_Controller_Spec, Fin_Controller_Body);
+ Analyze (Fin_Controller_Body, Suppress => All_Checks);
+
+ -- Return the finalization controller as the result Fin_Id
+
+ Fin_Id := Fin_Controller_Id;
+ end if;
+ end Build_Finalizer;
+
+ ---------------------
-- Build_Late_Proc --
---------------------
@@ -3741,6 +4292,10 @@ package body Exp_Ch7 is
Defining_Identifier => Data.Raised_Id,
Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
Expression => New_Occurrence_Of (Standard_False, Loc)));
+
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Data.Raised_Id);
+ end if;
end Build_Object_Declarations;
---------------------------
@@ -4109,20 +4664,23 @@ package body Exp_Ch7 is
procedure Reset_Scopes_To_Block_Elab_Proc (L : List_Id) is
Id : Entity_Id;
Stat : Node_Id;
+ Node : Node_Id;
begin
Stat := First (L);
while Present (Stat) loop
case Nkind (Stat) is
when N_Block_Statement =>
- Id := Entity (Identifier (Stat));
+ if Present (Identifier (Stat)) then
+ Id := Entity (Identifier (Stat));
- -- The Scope of this block needs to be reset to the new
- -- procedure if the block contains nested subprograms.
+ -- The Scope of this block needs to be reset to the new
+ -- procedure if the block contains nested subprograms.
- if Present (Id) and then Contains_Subprogram (Id) then
- Set_Block_Elab_Proc;
- Set_Scope (Id, Block_Elab_Proc);
+ if Present (Id) and then Contains_Subprogram (Id) then
+ Set_Block_Elab_Proc;
+ Set_Scope (Id, Block_Elab_Proc);
+ end if;
end if;
when N_Loop_Statement =>
@@ -4145,34 +4703,20 @@ package body Exp_Ch7 is
when N_If_Statement =>
Reset_Scopes_To_Block_Elab_Proc (Then_Statements (Stat));
-
Reset_Scopes_To_Block_Elab_Proc (Else_Statements (Stat));
- declare
- Elif : Node_Id;
-
- begin
- Elif := First (Elsif_Parts (Stat));
- while Present (Elif) loop
- Reset_Scopes_To_Block_Elab_Proc
- (Then_Statements (Elif));
-
- Next (Elif);
- end loop;
- end;
+ Node := First (Elsif_Parts (Stat));
+ while Present (Node) loop
+ Reset_Scopes_To_Block_Elab_Proc (Then_Statements (Node));
+ Next (Node);
+ end loop;
when N_Case_Statement =>
- declare
- Alt : Node_Id;
-
- begin
- Alt := First (Alternatives (Stat));
- while Present (Alt) loop
- Reset_Scopes_To_Block_Elab_Proc (Statements (Alt));
-
- Next (Alt);
- end loop;
- end;
+ Node := First (Alternatives (Stat));
+ while Present (Node) loop
+ Reset_Scopes_To_Block_Elab_Proc (Statements (Node));
+ Next (Node);
+ end loop;
-- Reset the Scope of a subprogram occurring at the top level
@@ -4794,6 +5338,12 @@ package body Exp_Ch7 is
Nkind (N) = N_Block_Statement
and then Present (Cleanup_Actions (N));
+ Has_Postcondition : constant Boolean :=
+ Nkind (N) = N_Subprogram_Body
+ and then Present
+ (Postconditions_Proc
+ (Unique_Defining_Entity (N)));
+
Actions_Required : constant Boolean :=
Requires_Cleanup_Actions (N, True)
or else Is_Asynchronous_Call
@@ -5008,6 +5558,34 @@ package body Exp_Ch7 is
end;
end if;
+ -- Move the _postconditions subprogram declaration and its associated
+ -- objects into the declarations section so that it is callable
+ -- within _postconditions.
+
+ if Has_Postcondition then
+ declare
+ Decl : Node_Id;
+ Prev_Decl : Node_Id;
+
+ begin
+ Decl :=
+ Prev (Subprogram_Body
+ (Postconditions_Proc (Current_Subprogram)));
+ while Present (Decl) loop
+ Prev_Decl := Prev (Decl);
+
+ Remove (Decl);
+ Prepend_To (New_Decls, Decl);
+
+ exit when Nkind (Decl) = N_Subprogram_Declaration
+ and then Chars (Corresponding_Body (Decl))
+ = Name_uPostconditions;
+
+ Decl := Prev_Decl;
+ end loop;
+ end;
+ end if;
+
-- Ensure the presence of a declaration list in order to successfully
-- append all original statements to it.
@@ -5954,7 +6532,7 @@ package body Exp_Ch7 is
begin
-- Nothing to do if the scope does not manage the secondary stack or
- -- does not contain meaninful actions for insertion.
+ -- does not contain meaningful actions for insertion.
if not Manage_SS
and then No (Act_Before)
@@ -6178,22 +6756,6 @@ package body Exp_Ch7 is
end if;
end Make_Adjust_Call;
- ----------------------
- -- Make_Detach_Call --
- ----------------------
-
- function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
- Loc : constant Source_Ptr := Sloc (Obj_Ref);
-
- begin
- return
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Detach), Loc),
- Parameter_Associations => New_List (
- Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
- end Make_Detach_Call;
-
---------------
-- Make_Call --
---------------
@@ -6825,22 +7387,49 @@ package body Exp_Ch7 is
Init_Call := Build_Initialization_Call;
- -- Only create finalization block if there is a non-trivial
- -- call to initialization.
-
- if Present (Init_Call)
- and then Nkind (Init_Call) /= N_Null_Statement
+ -- Only create finalization block if there is a nontrivial call
+ -- to initialization or a Default_Initial_Condition check to be
+ -- performed.
+
+ if (Present (Init_Call)
+ and then Nkind (Init_Call) /= N_Null_Statement)
+ or else
+ (Has_DIC (Comp_Typ)
+ and then not GNATprove_Mode
+ and then Present (DIC_Procedure (Comp_Typ))
+ and then not Has_Null_Body (DIC_Procedure (Comp_Typ)))
then
- Init_Loop :=
- Make_Block_Statement (Loc,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Init_Call),
- Exception_Handlers => New_List (
- Make_Exception_Handler (Loc,
- Exception_Choices => New_List (
- Make_Others_Choice (Loc)),
- Statements => New_List (Final_Block)))));
+ declare
+ Init_Stmts : constant List_Id := New_List;
+
+ begin
+ if Present (Init_Call) then
+ Append_To (Init_Stmts, Init_Call);
+ end if;
+
+ if Has_DIC (Comp_Typ)
+ and then Present (DIC_Procedure (Comp_Typ))
+ then
+ Append_To
+ (Init_Stmts,
+ Build_DIC_Call (Loc,
+ Make_Indexed_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_V),
+ Expressions => New_References_To (Index_List, Loc)),
+ Comp_Typ));
+ end if;
+
+ Init_Loop :=
+ Make_Block_Statement (Loc,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => Init_Stmts,
+ Exception_Handlers => New_List (
+ Make_Exception_Handler (Loc,
+ Exception_Choices => New_List (
+ Make_Others_Choice (Loc)),
+ Statements => New_List (Final_Block)))));
+ end;
Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
Make_Assignment_Statement (Loc,
@@ -6906,6 +7495,10 @@ package body Exp_Ch7 is
Make_Handled_Sequence_Of_Statements (Loc,
Statements => New_List (Init_Loop)));
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Counter_Id);
+ end if;
+
-- Otherwise previous errors or a missing full view may prevent the
-- proper freezing of the component type. If this is the case, there
-- is no [Deep_]Initialize primitive to call.
@@ -8428,6 +9021,24 @@ package body Exp_Ch7 is
elsif Is_Tagged_Type (Utyp) then
Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
+ -- Protected types: these also require finalization even though they
+ -- are not marked controlled explicitly.
+
+ elsif Is_Protected_Type (Typ) then
+ -- Protected objects do not need to be finalized on restricted
+ -- runtimes.
+
+ if Restricted_Profile then
+ return Empty;
+
+ -- ??? Only handle the simple case for now. Will not support a record
+ -- or array containing protected objects.
+
+ elsif Is_Simple_Protected_Type (Typ) then
+ Fin_Id := RTE (RE_Finalize_Protection);
+ else
+ raise Program_Error;
+ end if;
else
raise Program_Error;
end if;
@@ -8868,8 +9479,11 @@ package body Exp_Ch7 is
-- The underlying type may not be present due to a missing full view.
-- In this case freezing did not take place and there is no suitable
-- [Deep_]Initialize primitive to call.
+ -- If Typ is protected then no additional processing is needed either.
- if No (Utyp) then
+ if No (Utyp)
+ or else Is_Protected_Type (Typ)
+ then
return Empty;
end if;
@@ -8891,7 +9505,7 @@ package body Exp_Ch7 is
and then Present (Alias (Proc))
and then Is_Trivial_Subprogram (Alias (Proc)))
then
- return Make_Null_Statement (Loc);
+ return Empty;
end if;
-- The object reference may need another conversion depending on the
@@ -9681,6 +10295,10 @@ package body Exp_Ch7 is
Expression => Expr),
Par => Parent (N))));
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Temp);
+ end if;
+
Rewrite (N, New_Occurrence_Of (Temp, Loc));
Analyze_And_Resolve (N, Typ);
end Wrap_Transient_Expression;
diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads
index 235b75a..5f75ab6 100644
--- a/gcc/ada/exp_ch7.ads
+++ b/gcc/ada/exp_ch7.ads
@@ -175,13 +175,6 @@ package Exp_Ch7 is
-- only the components (if any) are adjusted. Return Empty if Adjust or
-- Deep_Adjust is not available, possibly due to previous errors.
- function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id;
- -- Create a call to unhook an object from an arbitrary list. Obj_Ref is the
- -- object. Generate the following:
- --
- -- Ada.Finalization.Heap_Management.Detach
- -- (System.Finalization_Root.Root_Controlled_Ptr (Obj_Ref));
-
function Make_Final_Call
(Obj_Ref : Node_Id;
Typ : Entity_Id;
diff --git a/gcc/ada/exp_ch8.adb b/gcc/ada/exp_ch8.adb
index 9f4c65c..facd12e 100644
--- a/gcc/ada/exp_ch8.adb
+++ b/gcc/ada/exp_ch8.adb
@@ -101,10 +101,6 @@ package body Exp_Ch8 is
-- More comments needed for this para ???
procedure Expand_N_Object_Renaming_Declaration (N : Node_Id) is
- Nam : constant Node_Id := Name (N);
- Decl : Node_Id;
- T : Entity_Id;
-
function Evaluation_Required (Nam : Node_Id) return Boolean;
-- Determines whether it is necessary to do static name evaluation for
-- renaming of Nam. It is considered necessary if evaluating the name
@@ -165,6 +161,12 @@ package body Exp_Ch8 is
end if;
end Evaluation_Required;
+ -- Local variables
+
+ Decl : Node_Id;
+ Nam : constant Node_Id := Name (N);
+ T : constant Entity_Id := Etype (Defining_Identifier (N));
+
-- Start of processing for Expand_N_Object_Renaming_Declaration
begin
@@ -177,8 +179,6 @@ package body Exp_Ch8 is
-- Deal with construction of subtype in class-wide case
- T := Etype (Defining_Identifier (N));
-
if Is_Class_Wide_Type (T) then
Expand_Subtype_From_Expr (N, T, Subtype_Mark (N), Name (N));
Find_Type (Subtype_Mark (N));
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 7207723..b055b27 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -7061,7 +7061,6 @@ package body Exp_Ch9 is
Enqueue_Call : Node_Id;
Formals : List_Id;
Hdle : List_Id;
- Handler_Stmt : Node_Id;
Index : Node_Id;
Lim_Typ_Stmts : List_Id;
N_Orig : Node_Id;
@@ -7162,8 +7161,7 @@ package body Exp_Ch9 is
if Ada_Version >= Ada_2005
and then
(No (Original_Node (Ecall))
- or else Nkind (Original_Node (Ecall)) not in
- N_Delay_Relative_Statement | N_Delay_Until_Statement)
+ or else Nkind (Original_Node (Ecall)) not in N_Delay_Statement)
then
Extract_Dispatching_Call (Ecall, Call_Ent, Obj, Actuals, Formals);
@@ -7737,16 +7735,6 @@ package body Exp_Ch9 is
Has_Created_Identifier => True,
Is_Asynchronous_Call_Block => True);
- -- Aborts are not deferred at beginning of exception handlers in
- -- ZCX mode.
-
- if ZCX_Exceptions then
- Handler_Stmt := Make_Null_Statement (Loc);
-
- else
- Handler_Stmt := Build_Runtime_Call (Loc, RE_Abort_Undefer);
- end if;
-
Stmts := New_List (
Make_Block_Statement (Loc,
Handled_Statement_Sequence =>
@@ -7763,11 +7751,11 @@ package body Exp_Ch9 is
Make_Implicit_Exception_Handler (Loc,
-- when Abort_Signal =>
- -- Abort_Undefer.all;
+ -- null;
Exception_Choices =>
New_List (New_Occurrence_Of (Stand.Abort_Signal, Loc)),
- Statements => New_List (Handler_Stmt))))),
+ Statements => New_List (Make_Null_Statement (Loc)))))),
-- if not Cancelled (Bnn) then
-- triggered statements
@@ -10579,13 +10567,12 @@ package body Exp_Ch9 is
Extract_Entry (N, Concval, Ename, Index);
Conc_Typ := Etype (Concval);
- -- Examine the scope stack in order to find nearest enclosing protected
- -- or task type. This will constitute our invocation source.
+ -- Examine the scope stack in order to find nearest enclosing concurrent
+ -- type. This will constitute our invocation source.
Old_Typ := Current_Scope;
while Present (Old_Typ)
- and then not Is_Protected_Type (Old_Typ)
- and then not Is_Task_Type (Old_Typ)
+ and then not Is_Concurrent_Type (Old_Typ)
loop
Old_Typ := Scope (Old_Typ);
end loop;
diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb
index c2e7741..bb0003d 100644
--- a/gcc/ada/exp_dbug.adb
+++ b/gcc/ada/exp_dbug.adb
@@ -133,11 +133,6 @@ package body Exp_Dbug is
-- Determine whether the bounds of E match the size of the type. This is
-- used to determine whether encoding is required for a discrete type.
- function Is_Handled_Scale_Factor (U : Ureal) return Boolean;
- -- The argument U is the Small_Value of a fixed-point type. This function
- -- determines whether the back-end can handle this scale factor. When it
- -- cannot, we have to output a GNAT encoding for the corresponding type.
-
procedure Output_Homonym_Numbers_Suffix;
-- If homonym numbers are stored, then output them into Name_Buffer
@@ -594,27 +589,6 @@ package body Exp_Dbug is
return Make_Null_Statement (Loc);
end Debug_Renaming_Declaration;
- -----------------------------
- -- Is_Handled_Scale_Factor --
- -----------------------------
-
- function Is_Handled_Scale_Factor (U : Ureal) return Boolean is
- begin
- -- Keep in sync with gigi (see E_*_Fixed_Point_Type handling in
- -- decl.c:gnat_to_gnu_entity).
-
- if UI_Eq (Numerator (U), Uint_1) then
- if Rbase (U) = 2 or else Rbase (U) = 10 then
- return True;
- end if;
- end if;
-
- return
- (UI_Is_In_Int_Range (Norm_Num (U))
- and then
- UI_Is_In_Int_Range (Norm_Den (U)));
- end Is_Handled_Scale_Factor;
-
----------------------
-- Get_Encoded_Name --
----------------------
@@ -671,12 +645,10 @@ package body Exp_Dbug is
Has_Suffix := True;
- -- Fixed-point case: generate GNAT encodings when asked to or when we
- -- know the back-end will not be able to handle the scale factor.
+ -- Fixed-point case: generate GNAT encodings when asked to
if Is_Fixed_Point_Type (E)
- and then (GNAT_Encodings /= DWARF_GNAT_Encodings_Minimal
- or else not Is_Handled_Scale_Factor (Small_Value (E)))
+ and then GNAT_Encodings = DWARF_GNAT_Encodings_All
then
Get_External_Name (E, True, "XF_");
Add_Real_To_Buffer (Delta_Value (E));
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index 1a41d79..14f25db 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -7241,7 +7241,7 @@ package body Exp_Disp is
-- is used by Build_Get_Prim_Op_Address to expand dispatching calls
-- through the primary dispatch table.
- if UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))) = 0 then
+ if DT_Entry_Count (First_Tag_Component (Typ)) = 0 then
Analyze_List (Result);
-- Generate:
diff --git a/gcc/ada/exp_dist.adb b/gcc/ada/exp_dist.adb
index 760a412..2d3f75d 100644
--- a/gcc/ada/exp_dist.adb
+++ b/gcc/ada/exp_dist.adb
@@ -902,7 +902,7 @@ package body Exp_Dist is
-- Local variables and structures --
------------------------------------
- RCI_Cache : Node_Id;
+ RCI_Cache : Node_Id := Empty;
-- Needs comments ???
Output_From_Constrained : constant array (Boolean) of Name_Id :=
diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb
index 42cf626..4c658bb 100644
--- a/gcc/ada/exp_fixd.adb
+++ b/gcc/ada/exp_fixd.adb
@@ -37,9 +37,9 @@ with Sem_Eval; use Sem_Eval;
with Sem_Res; use Sem_Res;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
-with Snames; use Snames;
with Stand; use Stand;
with Tbuild; use Tbuild;
+with Ttypes; use Ttypes;
with Uintp; use Uintp;
with Urealp; use Urealp;
@@ -68,7 +68,7 @@ package body Exp_Fixd is
-- Build an expression that converts the expression Expr to type Typ,
-- taking the source location from Sloc (N). If the conversions involve
-- fixed-point types, then the Conversion_OK flag will be set so that the
- -- resulting conversions do not get re-expanded. On return the resulting
+ -- resulting conversions do not get re-expanded. On return, the resulting
-- node has its Etype set. If Rchk is set, then Do_Range_Check is set
-- in the resulting conversion node. If Trunc is set, then the
-- Float_Truncate flag is set on the conversion, which must be from
@@ -85,7 +85,7 @@ package body Exp_Fixd is
-- two operand types), and both operands are converted to this type. The
-- Etype of the result is also set to this value. The Rounded_Result flag
-- of the result in this case is set from the Rounded_Result flag of node
- -- N. On return, the resulting node is analyzed and has its Etype set.
+ -- N. On return, the resulting node has its Etype set.
function Build_Double_Divide
(N : Node_Id;
@@ -93,7 +93,7 @@ package body Exp_Fixd is
-- Returns a node corresponding to the value X/(Y*Z) using the source
-- location from Sloc (N). The division is rounded if the Rounded_Result
-- flag of N is set. The integer types of X, Y, Z may be different. On
- -- return the resulting node is analyzed, and has its Etype set.
+ -- return, the resulting node has its Etype set.
procedure Build_Double_Divide_Code
(N : Node_Id;
@@ -114,11 +114,9 @@ package body Exp_Fixd is
-- Make_Op_Multiply only in that the Etype of the resulting node is set (to
-- Universal_Real), or they can be integer or fixed-point types. In this
-- case the types need not be the same, and Build_Multiply chooses a type
- -- long enough to hold the product (i.e. twice the size of the longer of
- -- the two operand types), and both operands are converted to this type.
- -- The Etype of the result is also set to this value. However, the result
- -- can never overflow Integer_64, so this is the largest type that is ever
- -- generated. On return, the resulting node is analyzed and has Etype set.
+ -- long enough to hold the product and both operands are converted to this
+ -- type. The type of the result is also set to this value. On return, the
+ -- resulting node has its Etype set.
function Build_Rem (N : Node_Id; L, R : Node_Id) return Node_Id;
-- Builds an N_Op_Rem node from the given left and right operand
@@ -127,7 +125,7 @@ package body Exp_Fixd is
-- operand with the smaller sized type to match the type of the other
-- operand and sets this as the result type. The result is never rounded
-- (rem operations cannot be rounded in any case). On return, the resulting
- -- node is analyzed and has its Etype set.
+ -- node has its Etype set.
function Build_Scaled_Divide
(N : Node_Id;
@@ -135,7 +133,7 @@ package body Exp_Fixd is
-- Returns a node corresponding to the value X*Y/Z using the source
-- location from Sloc (N). The division is rounded if the Rounded_Result
-- flag of N is set. The integer types of X, Y, Z may be different. On
- -- return the resulting node is analyzed and has is Etype set.
+ -- return the resulting node has its Etype set.
procedure Build_Scaled_Divide_Code
(N : Node_Id;
@@ -194,12 +192,13 @@ package body Exp_Fixd is
V : Uint;
Negative : Boolean := False) return Node_Id;
-- Given a non-negative universal integer value, build a typed integer
- -- literal node, using the smallest applicable standard integer type. If
- -- and only if Negative is true a negative literal is built. If V exceeds
- -- 2**63-1, the largest value allowed for perfect result set scaling
- -- factors (see RM G.2.3(22)), then Empty is returned. The node N provides
- -- the Sloc value for the constructed literal. The Etype of the resulting
- -- literal is correctly set, and it is marked as analyzed.
+ -- literal node, using the smallest applicable standard integer type.
+ -- If Negative is true, then a negative literal is built. If V exceeds
+ -- 2**(System_Max_Integer_Size - 1) - 1, the largest value allowed for
+ -- perfect result set scaling factors (see RM G.2.3(22)), then Empty is
+ -- returned. The node N provides the Sloc value for the constructed
+ -- literal. The Etype of the resulting literal is correctly set, and it
+ -- is marked as analyzed.
function Real_Literal (N : Node_Id; V : Ureal) return Node_Id;
-- Build a real literal node from the given value, the Etype of the
@@ -347,11 +346,12 @@ package body Exp_Fixd is
return L;
end if;
+ -- Otherwise we need to figure out the correct result type size
-- First figure out the effective sizes of the operands. Normally
-- the effective size of an operand is the RM_Size of the operand.
-- But a special case arises with operands whose size is known at
-- compile time. In this case, we can use the actual value of the
- -- operand to get its size if it would fit signed in 8 or 16 bits.
+ -- operand to get its size if it would fit in signed 8/16/32 bits.
Left_Size := UI_To_Int (RM_Size (Left_Type));
@@ -359,10 +359,12 @@ package body Exp_Fixd is
declare
Val : constant Uint := Expr_Value (L);
begin
- if Val < Int'(2 ** 7) then
+ if Val < Uint_2 ** 7 then
Left_Size := 8;
- elsif Val < Int'(2 ** 15) then
+ elsif Val < Uint_2 ** 15 then
Left_Size := 16;
+ elsif Val < Uint_2 ** 31 then
+ Left_Size := 32;
end if;
end;
end if;
@@ -394,8 +396,11 @@ package body Exp_Fixd is
elsif Rsize <= 32 then
Result_Type := Standard_Integer_32;
- else
+ elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
Result_Type := Standard_Integer_64;
+
+ else
+ Result_Type := Standard_Integer_128;
end if;
Rnode :=
@@ -411,13 +416,9 @@ package body Exp_Fixd is
-- The result is rounded if the target of the operation is decimal
-- and Rounded_Result is set, or if the target of the operation
- -- is an integer type.
+ -- is an integer type, as determined by Rounded_Result_Set.
- if Is_Integer_Type (Etype (N))
- or else Rounded_Result_Set (N)
- then
- Set_Rounded_Result (Rnode);
- end if;
+ Set_Rounded_Result (Rnode, Rounded_Result_Set (N));
-- One more check. We did the divide operation using the longer of
-- the two sizes, which is reasonable. However, in the case where the
@@ -441,23 +442,29 @@ package body Exp_Fixd is
(N : Node_Id;
X, Y, Z : Node_Id) return Node_Id
is
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
- Z_Size : constant Nat := UI_To_Int (Esize (Etype (Z)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
+ D_Size : constant Nat := Y_Size + Z_Size;
+ M_Size : constant Nat := Nat'Max (X_Size, Nat'Max (Y_Size, Z_Size));
Expr : Node_Id;
begin
- -- If denominator fits in 64 bits, we can build the operations directly
- -- without causing any intermediate overflow, so that's what we do.
+ -- If the denominator fits in Max_Integer_Size bits, we can build the
+ -- operations directly without causing any intermediate overflow. But
+ -- for backward compatibility reasons, we use a 128-bit divide only
+ -- if one of the operands is already larger than 64 bits.
- if Nat'Max (Y_Size, Z_Size) <= 32 then
- return
- Build_Divide (N, X, Build_Multiply (N, Y, Z));
+ if D_Size <= System_Max_Integer_Size
+ and then (D_Size <= 64 or else M_Size > 64)
+ then
+ return Build_Divide (N, X, Build_Multiply (N, Y, Z));
-- Otherwise we use the runtime routine
- -- [Qnn : Interfaces.Integer_64,
- -- Rnn : Interfaces.Integer_64;
- -- Double_Divide (X, Y, Z, Qnn, Rnn, Round);
+ -- [Qnn : Interfaces.Integer_{64|128};
+ -- Rnn : Interfaces.Integer_{64|128};
+ -- Double_Divide{64|128} (X, Y, Z, Qnn, Rnn, Round);
-- Qnn]
else
@@ -489,18 +496,18 @@ package body Exp_Fixd is
-- Build_Double_Divide_Code --
------------------------------
- -- If the denominator can be computed in 64-bits, we build
+ -- If the denominator can be computed in Max_Integer_Size bits, we build
-- [Nnn : constant typ := typ (X);
-- Dnn : constant typ := typ (Y) * typ (Z)
-- Qnn : constant typ := Nnn / Dnn;
- -- Rnn : constant typ := Nnn / Dnn;
+ -- Rnn : constant typ := Nnn rem Dnn;
- -- If the numerator cannot be computed in 64 bits, we build
+ -- If the denominator cannot be computed in Max_Integer_Size bits, we build
- -- [Qnn : typ;
- -- Rnn : typ;
- -- Double_Divide (X, Y, Z, Qnn, Rnn, Round);]
+ -- [Qnn : Interfaces.Integer_{64|128};
+ -- Rnn : Interfaces.Integer_{64|128};
+ -- Double_Divide{64|128} (X, Y, Z, Qnn, Rnn, Round);]
procedure Build_Double_Divide_Code
(N : Node_Id;
@@ -510,10 +517,12 @@ package body Exp_Fixd is
is
Loc : constant Source_Ptr := Sloc (N);
- X_Size : constant Nat := UI_To_Int (Esize (Etype (X)));
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
- Z_Size : constant Nat := UI_To_Int (Esize (Etype (Z)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
+ M_Size : constant Nat := Nat'Max (X_Size, Nat'Max (Y_Size, Z_Size));
+ QR_Id : RE_Id;
QR_Siz : Nat;
QR_Typ : Entity_Id;
@@ -524,22 +533,36 @@ package body Exp_Fixd is
Rnd : Entity_Id;
begin
- -- Find type that will allow computation of numerator
+ -- Find type that will allow computation of denominator
- QR_Siz := Nat'Max (X_Size, 2 * Nat'Max (Y_Size, Z_Size));
+ QR_Siz := Nat'Max (X_Size, Y_Size + Z_Size);
if QR_Siz <= 16 then
QR_Typ := Standard_Integer_16;
+ QR_Id := RE_Null;
+
elsif QR_Siz <= 32 then
QR_Typ := Standard_Integer_32;
+ QR_Id := RE_Null;
+
elsif QR_Siz <= 64 then
QR_Typ := Standard_Integer_64;
+ QR_Id := RE_Null;
- -- For more than 64, bits, we use the 64-bit integer defined in
- -- Interfaces, so that it can be handled by the runtime routine.
+ -- For backward compatibility reasons, we use a 128-bit divide only
+ -- if one of the operands is already larger than 64 bits.
- else
+ elsif System_Max_Integer_Size < 128 or else M_Size <= 64 then
QR_Typ := RTE (RE_Integer_64);
+ QR_Id := RE_Double_Divide64;
+
+ elsif QR_Siz <= 128 then
+ QR_Typ := Standard_Integer_128;
+ QR_Id := RE_Null;
+
+ else
+ QR_Typ := RTE (RE_Integer_128);
+ QR_Id := RE_Double_Divide128;
end if;
-- Define quotient and remainder, and set their Etypes, so
@@ -551,9 +574,9 @@ package body Exp_Fixd is
Set_Etype (Qnn, QR_Typ);
Set_Etype (Rnn, QR_Typ);
- -- Case that we can compute the denominator in 64 bits
+ -- Case where we can compute the denominator in Max_Integer_Size bits
- if QR_Siz <= 64 then
+ if QR_Id = RE_Null then
-- Create temporaries for numerator and denominator and set Etypes,
-- so that New_Occurrence_Of picks them up for Build_xxx calls.
@@ -569,16 +592,13 @@ package body Exp_Fixd is
Defining_Identifier => Nnn,
Object_Definition => New_Occurrence_Of (QR_Typ, Loc),
Constant_Present => True,
- Expression => Build_Conversion (N, QR_Typ, X)),
+ Expression => Build_Conversion (N, QR_Typ, X)),
Make_Object_Declaration (Loc,
Defining_Identifier => Dnn,
Object_Definition => New_Occurrence_Of (QR_Typ, Loc),
Constant_Present => True,
- Expression =>
- Build_Multiply (N,
- Build_Conversion (N, QR_Typ, Y),
- Build_Conversion (N, QR_Typ, Z))));
+ Expression => Build_Multiply (N, Y, Z)));
Quo :=
Build_Divide (N,
@@ -604,8 +624,8 @@ package body Exp_Fixd is
New_Occurrence_Of (Nnn, Loc),
New_Occurrence_Of (Dnn, Loc))));
- -- Case where denominator does not fit in 64 bits, so we have to
- -- call the runtime routine to compute the quotient and remainder
+ -- Case where denominator does not fit in Max_Integer_Size bits, we have
+ -- to call the runtime routine to compute the quotient and remainder.
else
Rnd := Boolean_Literals (Rounded_Result_Set (N));
@@ -620,7 +640,7 @@ package body Exp_Fixd is
Object_Definition => New_Occurrence_Of (QR_Typ, Loc)),
Make_Procedure_Call_Statement (Loc,
- Name => New_Occurrence_Of (RTE (RE_Double_Divide64), Loc),
+ Name => New_Occurrence_Of (RTE (QR_Id), Loc),
Parameter_Associations => New_List (
Build_Conversion (N, QR_Typ, X),
Build_Conversion (N, QR_Typ, Y),
@@ -674,7 +694,7 @@ package body Exp_Fixd is
-- the effective size of an operand is the RM_Size of the operand.
-- But a special case arises with operands whose size is known at
-- compile time. In this case, we can use the actual value of the
- -- operand to get its size if it would fit signed in 8 or 16 bits.
+ -- operand to get its size if it would fit in signed 8/16/32 bits.
Left_Size := UI_To_Int (RM_Size (Left_Type));
@@ -682,10 +702,12 @@ package body Exp_Fixd is
declare
Val : constant Uint := Expr_Value (L);
begin
- if Val < Int'(2 ** 7) then
+ if Val < Uint_2 ** 7 then
Left_Size := 8;
- elsif Val < Int'(2 ** 15) then
+ elsif Val < Uint_2 ** 15 then
Left_Size := 16;
+ elsif Val < Uint_2 ** 31 then
+ Left_Size := 32;
end if;
end;
end if;
@@ -704,10 +726,10 @@ package body Exp_Fixd is
end;
end if;
- -- Now the result size must be at least twice the longer of
- -- the two sizes, to accommodate all possible results.
+ -- Now the result size must be at least the sum of the two sizes,
+ -- to accommodate all possible results.
- Rsize := 2 * Int'Max (Left_Size, Right_Size);
+ Rsize := Left_Size + Right_Size;
if Rsize <= 8 then
Result_Type := Standard_Integer_8;
@@ -718,8 +740,11 @@ package body Exp_Fixd is
elsif Rsize <= 32 then
Result_Type := Standard_Integer_32;
- else
+ elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
Result_Type := Standard_Integer_64;
+
+ else
+ Result_Type := Standard_Integer_128;
end if;
Rnode :=
@@ -805,23 +830,29 @@ package body Exp_Fixd is
(N : Node_Id;
X, Y, Z : Node_Id) return Node_Id
is
- X_Size : constant Nat := UI_To_Int (Esize (Etype (X)));
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
+ N_Size : constant Nat := X_Size + Y_Size;
+ M_Size : constant Nat := Nat'Max (X_Size, Nat'Max (Y_Size, Z_Size));
Expr : Node_Id;
begin
- -- If numerator fits in 64 bits, we can build the operations directly
- -- without causing any intermediate overflow, so that's what we do.
+ -- If the numerator fits in Max_Integer_Size bits, we can build the
+ -- operations directly without causing any intermediate overflow. But
+ -- for backward compatibility reasons, we use a 128-bit divide only
+ -- if one of the operands is already larger than 64 bits.
- if Nat'Max (X_Size, Y_Size) <= 32 then
- return
- Build_Divide (N, Build_Multiply (N, X, Y), Z);
+ if N_Size <= System_Max_Integer_Size
+ and then (N_Size <= 64 or else M_Size > 64)
+ then
+ return Build_Divide (N, Build_Multiply (N, X, Y), Z);
-- Otherwise we use the runtime routine
- -- [Qnn : Integer_64,
- -- Rnn : Integer_64;
- -- Scaled_Divide (X, Y, Z, Qnn, Rnn, Round);
+ -- [Qnn : Integer_{64|128},
+ -- Rnn : Integer_{64|128};
+ -- Scaled_Divide{64|128} (X, Y, Z, Qnn, Rnn, Round);
-- Qnn]
else
@@ -850,18 +881,18 @@ package body Exp_Fixd is
-- Build_Scaled_Divide_Code --
------------------------------
- -- If the numerator can be computed in 64-bits, we build
+ -- If the numerator can be computed in Max_Integer_Size bits, we build
-- [Nnn : constant typ := typ (X) * typ (Y);
-- Dnn : constant typ := typ (Z)
-- Qnn : constant typ := Nnn / Dnn;
- -- Rnn : constant typ := Nnn / Dnn;
+ -- Rnn : constant typ := Nnn rem Dnn;
- -- If the numerator cannot be computed in 64 bits, we build
+ -- If the numerator cannot be computed in Max_Integer_Size bits, we build
- -- [Qnn : Interfaces.Integer_64;
- -- Rnn : Interfaces.Integer_64;
- -- Scaled_Divide (X, Y, Z, Qnn, Rnn, Round);]
+ -- [Qnn : Interfaces.Integer_{64|128};
+ -- Rnn : Interfaces.Integer_{64|128};
+ -- Scaled_Divide_{64|128} (X, Y, Z, Qnn, Rnn, Round);]
procedure Build_Scaled_Divide_Code
(N : Node_Id;
@@ -871,10 +902,12 @@ package body Exp_Fixd is
is
Loc : constant Source_Ptr := Sloc (N);
- X_Size : constant Nat := UI_To_Int (Esize (Etype (X)));
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
- Z_Size : constant Nat := UI_To_Int (Esize (Etype (Z)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
+ M_Size : constant Nat := Nat'Max (X_Size, Nat'Max (Y_Size, Z_Size));
+ QR_Id : RE_Id;
QR_Siz : Nat;
QR_Typ : Entity_Id;
@@ -887,20 +920,34 @@ package body Exp_Fixd is
begin
-- Find type that will allow computation of numerator
- QR_Siz := Nat'Max (X_Size, 2 * Nat'Max (Y_Size, Z_Size));
+ QR_Siz := Nat'Max (X_Size + Y_Size, Z_Size);
if QR_Siz <= 16 then
QR_Typ := Standard_Integer_16;
+ QR_Id := RE_Null;
+
elsif QR_Siz <= 32 then
QR_Typ := Standard_Integer_32;
+ QR_Id := RE_Null;
+
elsif QR_Siz <= 64 then
QR_Typ := Standard_Integer_64;
+ QR_Id := RE_Null;
- -- For more than 64, bits, we use the 64-bit integer defined in
- -- Interfaces, so that it can be handled by the runtime routine.
+ -- For backward compatibility reasons, we use a 128-bit divide only
+ -- if one of the operands is already larger than 64 bits.
- else
+ elsif System_Max_Integer_Size < 128 or else M_Size <= 64 then
QR_Typ := RTE (RE_Integer_64);
+ QR_Id := RE_Scaled_Divide64;
+
+ elsif QR_Siz <= 128 then
+ QR_Typ := Standard_Integer_128;
+ QR_Id := RE_Null;
+
+ else
+ QR_Typ := RTE (RE_Integer_128);
+ QR_Id := RE_Scaled_Divide128;
end if;
-- Define quotient and remainder, and set their Etypes, so
@@ -912,9 +959,9 @@ package body Exp_Fixd is
Set_Etype (Qnn, QR_Typ);
Set_Etype (Rnn, QR_Typ);
- -- Case that we can compute the numerator in 64 bits
+ -- Case where we can compute the numerator in Max_Integer_Size bits
- if QR_Siz <= 64 then
+ if QR_Id = RE_Null then
Nnn := Make_Temporary (Loc, 'N');
Dnn := Make_Temporary (Loc, 'D');
@@ -928,16 +975,13 @@ package body Exp_Fixd is
Defining_Identifier => Nnn,
Object_Definition => New_Occurrence_Of (QR_Typ, Loc),
Constant_Present => True,
- Expression =>
- Build_Multiply (N,
- Build_Conversion (N, QR_Typ, X),
- Build_Conversion (N, QR_Typ, Y))),
+ Expression => Build_Multiply (N, X, Y)),
Make_Object_Declaration (Loc,
Defining_Identifier => Dnn,
Object_Definition => New_Occurrence_Of (QR_Typ, Loc),
Constant_Present => True,
- Expression => Build_Conversion (N, QR_Typ, Z)));
+ Expression => Build_Conversion (N, QR_Typ, Z)));
Quo :=
Build_Divide (N,
@@ -961,8 +1005,8 @@ package body Exp_Fixd is
New_Occurrence_Of (Nnn, Loc),
New_Occurrence_Of (Dnn, Loc))));
- -- Case where numerator does not fit in 64 bits, so we have to
- -- call the runtime routine to compute the quotient and remainder
+ -- Case where numerator does not fit in Max_Integer_Size bits, we have
+ -- to call the runtime routine to compute the quotient and remainder.
else
Rnd := Boolean_Literals (Rounded_Result_Set (N));
@@ -977,7 +1021,7 @@ package body Exp_Fixd is
Object_Definition => New_Occurrence_Of (QR_Typ, Loc)),
Make_Procedure_Call_Statement (Loc,
- Name => New_Occurrence_Of (RTE (RE_Scaled_Divide64), Loc),
+ Name => New_Occurrence_Of (RTE (QR_Id), Loc),
Parameter_Associations => New_List (
Build_Conversion (N, QR_Typ, X),
Build_Conversion (N, QR_Typ, Y),
@@ -1374,8 +1418,7 @@ package body Exp_Fixd is
if Present (Lit_Int) then
Set_Result (N,
- Build_Multiply (N, Build_Multiply (N, Left, Right),
- Lit_Int));
+ Build_Multiply (N, Build_Multiply (N, Left, Right), Lit_Int));
return;
end if;
@@ -1546,6 +1589,10 @@ package body Exp_Fixd is
-- If the small ratio is the reciprocal of a sufficiently small integer,
-- then the perfect result set is obtained by a single integer division.
+ -- If the numerator and denominator of the small ratio are sufficiently
+ -- small integers, then the perfect result set is obtained by a scaled
+ -- divide operation.
+
-- In other cases, we obtain the close result set by calculating the
-- result in floating-point.
@@ -1557,7 +1604,8 @@ package body Exp_Fixd is
Small_Ratio : Ureal;
Ratio_Num : Uint;
Ratio_Den : Uint;
- Lit : Node_Id;
+ Lit_Num : Node_Id;
+ Lit_Den : Node_Id;
begin
if Is_OK_Static_Expression (Expr) then
@@ -1575,26 +1623,36 @@ package body Exp_Fixd is
return;
else
- Lit := Integer_Literal (N, Ratio_Num);
+ Lit_Num := Integer_Literal (N, Ratio_Num);
- if Present (Lit) then
- Set_Result (N, Build_Multiply (N, Expr, Lit));
+ if Present (Lit_Num) then
+ Set_Result (N, Build_Multiply (N, Expr, Lit_Num));
return;
end if;
end if;
elsif Ratio_Num = 1 then
- Lit := Integer_Literal (N, Ratio_Den);
+ Lit_Den := Integer_Literal (N, Ratio_Den);
+
+ if Present (Lit_Den) then
+ Set_Result (N, Build_Divide (N, Expr, Lit_Den), Rng_Check);
+ return;
+ end if;
+
+ else
+ Lit_Num := Integer_Literal (N, Ratio_Num);
+ Lit_Den := Integer_Literal (N, Ratio_Den);
- if Present (Lit) then
- Set_Result (N, Build_Divide (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) and then Present (Lit_Den) then
+ Set_Result
+ (N, Build_Scaled_Divide (N, Expr, Lit_Num, Lit_Den), Rng_Check);
return;
end if;
end if;
- -- Fall through to use floating-point for the close result set case
- -- either as a result of the small ratio not being an integer or the
- -- reciprocal of an integer, or if the integer is out of range.
+ -- Fall through to use floating-point for the close result set case,
+ -- as a result of the numerator or denominator of the small ratio not
+ -- being a sufficiently small integer.
Set_Result (N,
Build_Multiply (N,
@@ -1650,6 +1708,10 @@ package body Exp_Fixd is
-- If the small value is the reciprocal of a sufficiently small integer,
-- then the perfect result set is obtained by a single integer division.
+ -- If the numerator and denominator of the small value are sufficiently
+ -- small integers, then the perfect result set is obtained by a scaled
+ -- divide operation.
+
-- In other cases, we obtain the close result set by calculating the
-- result in floating-point.
@@ -1660,7 +1722,8 @@ package body Exp_Fixd is
Small : constant Ureal := Small_Value (Source_Type);
Small_Num : constant Uint := Norm_Num (Small);
Small_Den : constant Uint := Norm_Den (Small);
- Lit : Node_Id;
+ Lit_Num : Node_Id;
+ Lit_Den : Node_Id;
begin
if Is_OK_Static_Expression (Expr) then
@@ -1669,25 +1732,35 @@ package body Exp_Fixd is
end if;
if Small_Den = 1 then
- Lit := Integer_Literal (N, Small_Num);
+ Lit_Num := Integer_Literal (N, Small_Num);
- if Present (Lit) then
- Set_Result (N, Build_Multiply (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) then
+ Set_Result (N, Build_Multiply (N, Expr, Lit_Num), Rng_Check);
return;
end if;
elsif Small_Num = 1 then
- Lit := Integer_Literal (N, Small_Den);
+ Lit_Den := Integer_Literal (N, Small_Den);
+
+ if Present (Lit_Den) then
+ Set_Result (N, Build_Divide (N, Expr, Lit_Den), Rng_Check);
+ return;
+ end if;
+
+ else
+ Lit_Num := Integer_Literal (N, Small_Num);
+ Lit_Den := Integer_Literal (N, Small_Den);
- if Present (Lit) then
- Set_Result (N, Build_Divide (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) and then Present (Lit_Den) then
+ Set_Result
+ (N, Build_Scaled_Divide (N, Expr, Lit_Num, Lit_Den), Rng_Check);
return;
end if;
end if;
- -- Fall through to use floating-point for the close result set case
- -- either as a result of the small value not being an integer or the
- -- reciprocal of an integer, or if the integer is out of range.
+ -- Fall through to use floating-point for the close result set case,
+ -- as a result of the numerator or denominator of the small value not
+ -- being a sufficiently small integer.
Set_Result (N,
Build_Multiply (N,
@@ -1714,11 +1787,9 @@ package body Exp_Fixd is
procedure Expand_Convert_Float_To_Fixed (N : Node_Id) is
Expr : constant Node_Id := Expression (N);
- Orig_N : constant Node_Id := Original_Node (N);
Result_Type : constant Entity_Id := Etype (N);
Rng_Check : constant Boolean := Do_Range_Check (N);
Small : constant Ureal := Small_Value (Result_Type);
- Truncate : Boolean;
begin
-- Optimize small = 1, where we can avoid the multiply completely
@@ -1733,15 +1804,6 @@ package body Exp_Fixd is
-- round.
else
- if Is_Decimal_Fixed_Point_Type (Result_Type) then
- Truncate :=
- Nkind (Orig_N) /= N_Attribute_Reference
- or else Get_Attribute_Id
- (Attribute_Name (Orig_N)) /= Attribute_Round;
- else
- Truncate := False;
- end if;
-
Set_Result
(N => N,
Expr =>
@@ -1750,7 +1812,8 @@ package body Exp_Fixd is
L => Fpt_Value (Expr),
R => Real_Literal (N, Ureal_1 / Small)),
Rchk => Rng_Check,
- Trunc => Truncate);
+ Trunc => Is_Decimal_Fixed_Point_Type (Result_Type)
+ and not Rounded_Result (N));
end if;
end Expand_Convert_Float_To_Fixed;
@@ -1769,6 +1832,10 @@ package body Exp_Fixd is
-- If the small value is the reciprocal of a sufficiently small integer,
-- the perfect result set is obtained by a single integer multiplication.
+ -- If the numerator and denominator of the small value are sufficiently
+ -- small integers, then the perfect result set is obtained by a scaled
+ -- divide operation.
+
-- In other cases, we obtain the close result set by calculating the
-- result in floating-point using a multiplication by the reciprocal
-- of the Result_Small.
@@ -1780,29 +1847,40 @@ package body Exp_Fixd is
Small : constant Ureal := Small_Value (Result_Type);
Small_Num : constant Uint := Norm_Num (Small);
Small_Den : constant Uint := Norm_Den (Small);
- Lit : Node_Id;
+ Lit_Num : Node_Id;
+ Lit_Den : Node_Id;
begin
if Small_Den = 1 then
- Lit := Integer_Literal (N, Small_Num);
+ Lit_Num := Integer_Literal (N, Small_Num);
- if Present (Lit) then
- Set_Result (N, Build_Divide (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) then
+ Set_Result (N, Build_Divide (N, Expr, Lit_Num), Rng_Check);
return;
end if;
elsif Small_Num = 1 then
- Lit := Integer_Literal (N, Small_Den);
+ Lit_Den := Integer_Literal (N, Small_Den);
- if Present (Lit) then
- Set_Result (N, Build_Multiply (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Den) then
+ Set_Result (N, Build_Multiply (N, Expr, Lit_Den), Rng_Check);
+ return;
+ end if;
+
+ else
+ Lit_Num := Integer_Literal (N, Small_Num);
+ Lit_Den := Integer_Literal (N, Small_Den);
+
+ if Present (Lit_Num) and then Present (Lit_Den) then
+ Set_Result
+ (N, Build_Scaled_Divide (N, Expr, Lit_Den, Lit_Num), Rng_Check);
return;
end if;
end if;
- -- Fall through to use floating-point for the close result set case
- -- either as a result of the small value not being an integer or the
- -- reciprocal of an integer, or if the integer is out of range.
+ -- Fall through to use floating-point for the close result set case,
+ -- as a result of the numerator or denominator of the small value not
+ -- being a sufficiently small integer.
Set_Result (N,
Build_Multiply (N,
@@ -2014,13 +2092,6 @@ package body Exp_Fixd is
Right : constant Node_Id := Right_Opnd (N);
begin
- -- Suppress expansion of a fixed-by-fixed division if the
- -- operation is supported directly by the target.
-
- if Target_Has_Fixed_Ops (Etype (Left), Etype (Right), Etype (N)) then
- return;
- end if;
-
if Etype (Left) = Universal_Real then
Do_Divide_Universal_Fixed (N);
@@ -2184,13 +2255,6 @@ package body Exp_Fixd is
-- Start of processing for Expand_Multiply_Fixed_By_Fixed_Giving_Fixed
begin
- -- Suppress expansion of a fixed-by-fixed multiplication if the
- -- operation is supported directly by the target.
-
- if Target_Has_Fixed_Ops (Etype (Left), Etype (Right), Etype (N)) then
- return;
- end if;
-
if Etype (Left) = Universal_Real then
if Nkind (Left) = N_Real_Literal then
Do_Multiply_Fixed_Universal (N, Left => Right, Right => Left);
@@ -2380,6 +2444,9 @@ package body Exp_Fixd is
elsif V < Uint_2 ** 63 then
T := Standard_Integer_64;
+ elsif V < Uint_2 ** 127 and then System_Max_Integer_Size = 128 then
+ T := Standard_Integer_128;
+
else
return Empty;
end if;
diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb
index 40cb514..0cb483b 100644
--- a/gcc/ada/exp_imgv.adb
+++ b/gcc/ada/exp_imgv.adb
@@ -49,11 +49,6 @@ with Urealp; use Urealp;
package body Exp_Imgv is
- function Has_Decimal_Small (E : Entity_Id) return Boolean;
- -- Applies to all entities. True for a Decimal_Fixed_Point_Type, or an
- -- Ordinary_Fixed_Point_Type with a small that is a negative power of ten.
- -- Shouldn't this be in einfo.adb or sem_aux.adb???
-
procedure Rewrite_Object_Image
(N : Node_Id;
Pref : Entity_Id;
@@ -219,21 +214,13 @@ package body Exp_Imgv is
-- xx = Boolean
-- tv = Boolean (Expr)
- -- For signed integer types with size <= Integer'Size
- -- xx = Integer
- -- tv = Integer (Expr)
-
- -- For other signed integer types
- -- xx = Long_Long_Integer
- -- tv = Long_Long_Integer (Expr)
-
- -- For modular types with modulus <= System.Unsigned_Types.Unsigned
- -- xx = Unsigned
- -- tv = System.Unsigned_Types.Unsigned (Expr)
+ -- For signed integer types
+ -- xx = [Long_Long_[Long_]]Integer
+ -- tv = [Long_Long_[Long_]]Integer (Expr)
- -- For other modular integer types
- -- xx = Long_Long_Unsigned
- -- tv = System.Unsigned_Types.Long_Long_Unsigned (Expr)
+ -- For modular types
+ -- xx = [Long_Long_[Long_]]Unsigned
+ -- tv = System.Unsigned_Types.[Long_Long_[Long_]]Unsigned (Expr)
-- For types whose root type is Wide_Character
-- xx = Wide_Character
@@ -249,21 +236,24 @@ package body Exp_Imgv is
-- tv = Long_Long_Float (Expr)
-- pm = typ'Digits (typ = subtype of expression)
- -- For ordinary fixed-point types
+ -- For decimal fixed-point types
+ -- xx = Decimal{32,64,128}
+ -- tv = Integer_{32,64,128} (Expr)? [convert with no scaling]
+ -- pm = typ'Scale (typ = subtype of expression)
+
+ -- For the most common ordinary fixed-point types
+ -- xx = Fixed{32,64,128}
+ -- tv = Integer_{32,64,128} (Expr) [convert with no scaling]
+ -- pm = numerator of typ'Small (typ = subtype of expression)
+ -- denominator of typ'Small
+ -- (Integer_{32,64,128} x typ'Small)'Fore
+ -- typ'Aft
+
+ -- For other ordinary fixed-point types
-- xx = Ordinary_Fixed_Point
-- tv = Long_Long_Float (Expr)
-- pm = typ'Aft (typ = subtype of expression)
- -- For decimal fixed-point types with size = Integer'Size
- -- xx = Decimal
- -- tv = Integer (Expr)
- -- pm = typ'Scale (typ = subtype of expression)
-
- -- For decimal fixed-point types with size > Integer'Size
- -- xx = Long_Long_Decimal
- -- tv = Long_Long_Integer?(Expr) [convert with no scaling]
- -- pm = typ'Scale (typ = subtype of expression)
-
-- For enumeration types other than those declared in package Standard
-- or System, Snn, Pnn, are expanded as above, but the call looks like:
@@ -593,18 +583,58 @@ package body Exp_Imgv is
Tent := RTE (RE_Long_Long_Long_Unsigned);
end if;
- elsif Is_Fixed_Point_Type (Rtyp) and then Has_Decimal_Small (Rtyp) then
- if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
- Imid := RE_Image_Decimal;
- Tent := Standard_Integer;
+ elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
+ if Esize (Rtyp) <= 32 then
+ Imid := RE_Image_Decimal32;
+ Tent := RTE (RE_Integer_32);
+ elsif Esize (Rtyp) <= 64 then
+ Imid := RE_Image_Decimal64;
+ Tent := RTE (RE_Integer_64);
else
- Imid := RE_Image_Long_Long_Decimal;
- Tent := Standard_Long_Long_Integer;
+ Imid := RE_Image_Decimal128;
+ Tent := RTE (RE_Integer_128);
end if;
elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
- Imid := RE_Image_Ordinary_Fixed_Point;
- Tent := Standard_Long_Long_Float;
+ declare
+ Num : constant Uint := Norm_Num (Small_Value (Rtyp));
+ Den : constant Uint := Norm_Den (Small_Value (Rtyp));
+ Max : constant Uint := UI_Max (Num, Den);
+ Min : constant Uint := UI_Min (Num, Den);
+ Siz : constant Uint := Esize (Rtyp);
+
+ begin
+ -- Note that we do not use sharp bounds to speed things up
+
+ if Siz <= 32
+ and then Max <= Uint_2 ** 31
+ and then (Min = Uint_1
+ or else (Num < Den and then Den <= Uint_2 ** 27)
+ or else (Den < Num and then Num <= Uint_2 ** 25))
+ then
+ Imid := RE_Image_Fixed32;
+ Tent := RTE (RE_Integer_32);
+ elsif Siz <= 64
+ and then Max <= Uint_2 ** 63
+ and then (Min = Uint_1
+ or else (Num < Den and then Den <= Uint_2 ** 59)
+ or else (Den < Num and then Num <= Uint_2 ** 53))
+ then
+ Imid := RE_Image_Fixed64;
+ Tent := RTE (RE_Integer_64);
+ elsif System_Max_Integer_Size = 128
+ and then Max <= Uint_2 ** 127
+ and then (Min = Uint_1
+ or else (Num < Den and then Den <= Uint_2 ** 123)
+ or else (Den < Num and then Num <= Uint_2 ** 122))
+ then
+ Imid := RE_Image_Fixed128;
+ Tent := RTE (RE_Integer_128);
+ else
+ Imid := RE_Image_Ordinary_Fixed_Point;
+ Tent := Standard_Long_Long_Float;
+ end if;
+ end;
elsif Is_Floating_Point_Type (Rtyp) then
Imid := RE_Image_Floating_Point;
@@ -746,29 +776,45 @@ package body Exp_Imgv is
Prefix => New_Occurrence_Of (Ptyp, Loc),
Attribute_Name => Name_Digits));
- -- For ordinary fixed-point types, append Aft parameter
+ -- For decimal, append Scale and also set to do literal conversion
- elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
- Append_To (Arg_List,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Ptyp, Loc),
- Attribute_Name => Name_Aft));
+ elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
+ Set_Conversion_OK (First (Arg_List));
- if Has_Decimal_Small (Rtyp) then
+ Append_To (Arg_List, Make_Integer_Literal (Loc, Scale_Value (Ptyp)));
+
+ -- For ordinary fixed-point types, append Num, Den, Fore, Aft parameters
+ -- and also set to do literal conversion.
+
+ elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
+ if Imid /= RE_Image_Ordinary_Fixed_Point then
Set_Conversion_OK (First (Arg_List));
- Set_Etype (First (Arg_List), Tent);
- end if;
- -- For decimal, append Scale and also set to do literal conversion
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, -Norm_Num (Small_Value (Ptyp))));
- elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
- Append_To (Arg_List,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Ptyp, Loc),
- Attribute_Name => Name_Scale));
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, -Norm_Den (Small_Value (Ptyp))));
- Set_Conversion_OK (First (Arg_List));
- Set_Etype (First (Arg_List), Tent);
+ -- We want to compute the Fore value for the fixed point type
+ -- whose mantissa type is Tent and whose small is typ'Small.
+
+ declare
+ T : Ureal := Uint_2 ** (Esize (Tent) - 1) * Small_Value (Ptyp);
+ F : Nat := 2;
+
+ begin
+ while T >= Ureal_10 loop
+ F := F + 1;
+ T := T / Ureal_10;
+ end loop;
+
+ Append_To (Arg_List,
+ Make_Integer_Literal (Loc, UI_From_Int (F)));
+ end;
+ end if;
+
+ Append_To (Arg_List, Make_Integer_Literal (Loc, Aft_Value (Ptyp)));
-- For Wide_Character, append Ada 2005 indication
@@ -827,20 +873,23 @@ package body Exp_Imgv is
-- For types whose root type is Boolean
-- xx = Boolean
- -- For signed integer types with size <= Integer'Size
- -- xx = Integer
+ -- For signed integer types
+ -- xx = [Long_Long_[Long_]]Integer
+
+ -- For modular types
+ -- xx = [Long_Long_[Long_]]Unsigned
- -- For other signed integer types
- -- xx = Long_Long_Integer
+ -- For floating-point types
+ -- xx = [Long_[Long_]]Float
+
+ -- For decimal fixed-point types, typ'Value (X) expands into
- -- For modular types with modulus <= System.Unsigned_Types.Unsigned
- -- xx = Unsigned
+ -- btyp?(Value_Decimal{32,64,128} (X, typ'Scale));
- -- For other modular integer types
- -- xx = Long_Long_Unsigned
+ -- For the most common ordinary fixed-point types
- -- For floating-point types and ordinary fixed-point types
- -- xx = Real
+ -- btyp?(Value_Fixed{32,64,128} (X, numerator of S, denominator of S));
+ -- where S = typ'Small
-- For Wide_[Wide_]Character types, typ'Value (X) expands into:
@@ -848,15 +897,6 @@ package body Exp_Imgv is
-- where btyp is the base type of the prefix, and EM is the encoding method
- -- For decimal types with size <= Integer'Size, typ'Value (X)
- -- expands into
-
- -- btyp?(Value_Decimal (X, typ'Scale));
-
- -- For all other decimal types, typ'Value (X) expands into
-
- -- btyp?(Value_Long_Long_Decimal (X, typ'Scale))
-
-- For enumeration types other than those derived from types Boolean,
-- Character, Wide_[Wide_]Character in Standard, typ'Value (X) expands to:
@@ -923,16 +963,15 @@ package body Exp_Imgv is
end if;
elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
- if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
- Vid := RE_Value_Decimal;
+ if Esize (Rtyp) <= 32 and then abs (Scale_Value (Rtyp)) <= 9 then
+ Vid := RE_Value_Decimal32;
+ elsif Esize (Rtyp) <= 64 and then abs (Scale_Value (Rtyp)) <= 18 then
+ Vid := RE_Value_Decimal64;
else
- Vid := RE_Value_Long_Long_Decimal;
+ Vid := RE_Value_Decimal128;
end if;
- Append_To (Args,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Typ, Loc),
- Attribute_Name => Name_Scale));
+ Append_To (Args, Make_Integer_Literal (Loc, Scale_Value (Rtyp)));
Rewrite (N,
OK_Convert_To (Btyp,
@@ -944,8 +983,75 @@ package body Exp_Imgv is
Analyze_And_Resolve (N, Btyp);
return;
- elsif Is_Real_Type (Rtyp) then
- Vid := RE_Value_Real;
+ elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
+ declare
+ Num : constant Uint := Norm_Num (Small_Value (Rtyp));
+ Den : constant Uint := Norm_Den (Small_Value (Rtyp));
+ Max : constant Uint := UI_Max (Num, Den);
+ Min : constant Uint := UI_Min (Num, Den);
+ Siz : constant Uint := Esize (Rtyp);
+
+ begin
+ if Siz <= 32
+ and then Max <= Uint_2 ** 31
+ and then (Min = Uint_1 or else Max <= Uint_2 ** 27)
+ then
+ Vid := RE_Value_Fixed32;
+ elsif Siz <= 64
+ and then Max <= Uint_2 ** 63
+ and then (Min = Uint_1 or else Max <= Uint_2 ** 59)
+ then
+ Vid := RE_Value_Fixed64;
+ elsif System_Max_Integer_Size = 128
+ and then Max <= Uint_2 ** 127
+ and then (Min = Uint_1 or else Max <= Uint_2 ** 123)
+ then
+ Vid := RE_Value_Fixed128;
+ else
+ Vid := RE_Value_Long_Float;
+ end if;
+
+ if Vid /= RE_Value_Long_Float then
+ Append_To (Args,
+ Make_Integer_Literal (Loc, -Norm_Num (Small_Value (Rtyp))));
+
+ Append_To (Args,
+ Make_Integer_Literal (Loc, -Norm_Den (Small_Value (Rtyp))));
+
+ Rewrite (N,
+ OK_Convert_To (Btyp,
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (RTE (Vid), Loc),
+ Parameter_Associations => Args)));
+
+ Set_Etype (N, Btyp);
+ Analyze_And_Resolve (N, Btyp);
+ return;
+ end if;
+ end;
+
+ elsif Is_Floating_Point_Type (Rtyp) then
+ -- Short_Float and Float are the same type for GNAT
+
+ if Rtyp = Standard_Short_Float or else Rtyp = Standard_Float then
+ Vid := RE_Value_Float;
+
+ -- If Long_Float and Long_Long_Float are the same type, then use the
+ -- implementation of the former, which is faster and more accurate.
+
+ elsif Rtyp = Standard_Long_Float
+ or else (Rtyp = Standard_Long_Long_Float
+ and then
+ Standard_Long_Long_Float_Size = Standard_Long_Float_Size)
+ then
+ Vid := RE_Value_Long_Float;
+
+ elsif Rtyp = Standard_Long_Long_Float then
+ Vid := RE_Value_Long_Long_Float;
+
+ else
+ raise Program_Error;
+ end if;
-- Only other possibility is user-defined enumeration type
@@ -1286,12 +1392,12 @@ package body Exp_Imgv is
-- yy = Boolean
-- For signed integer types
- -- xx = Width_Long_Long_Integer
- -- yy = Long_Long_Integer
+ -- xx = Width_[Long_Long_[Long_]]Integer
+ -- yy = [Long_Long_[Long_]]Integer
-- For modular integer types
- -- xx = Width_Long_Long_Unsigned
- -- yy = Long_Long_Unsigned
+ -- xx = Width_[Long_Long_[Long_]]Unsigned
+ -- yy = [Long_Long_[Long_]]Unsigned
-- For types derived from Wide_Character, typ'Width expands into
@@ -1329,7 +1435,11 @@ package body Exp_Imgv is
-- Wide_Wide_Character (typ'First),
-- Wide_Wide_Character (typ'Last));
- -- For real types, typ'Width and typ'Wide_[Wide_]Width expand into
+ -- For fixed point types, typ'Width and typ'Wide_[Wide_]Width expand into
+
+ -- if Ptyp'First > Ptyp'Last then 0 else Ptyp'Fore + 1 + Ptyp'Aft end if
+
+ -- and for floating point types, they expand into
-- if Ptyp'First > Ptyp'Last then 0 else btyp'Width end if
@@ -1451,9 +1561,41 @@ package body Exp_Imgv is
YY := RTE (RE_Long_Long_Long_Unsigned);
end if;
- -- Real types
+ -- Fixed point types
+
+ elsif Is_Fixed_Point_Type (Rtyp) then
+ Rewrite (N,
+ Make_If_Expression (Loc,
+ Expressions => New_List (
+
+ Make_Op_Gt (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_First),
+
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Last)),
- elsif Is_Real_Type (Rtyp) then
+ Make_Integer_Literal (Loc, 0),
+
+ Make_Op_Add (Loc,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Fore),
+
+ Make_Op_Add (Loc,
+ Make_Integer_Literal (Loc, 1),
+ Make_Integer_Literal (Loc, Aft_Value (Ptyp)))))));
+
+ Analyze_And_Resolve (N, Typ);
+ return;
+
+ -- Floating point types
+
+ elsif Is_Floating_Point_Type (Rtyp) then
Rewrite (N,
Make_If_Expression (Loc,
Expressions => New_List (
@@ -1680,18 +1822,6 @@ package body Exp_Imgv is
Analyze_And_Resolve (N, Typ);
end Expand_Width_Attribute;
- -----------------------
- -- Has_Decimal_Small --
- -----------------------
-
- function Has_Decimal_Small (E : Entity_Id) return Boolean is
- begin
- return Is_Decimal_Fixed_Point_Type (E)
- or else
- (Is_Ordinary_Fixed_Point_Type (E)
- and then Ureal_10**Aft_Value (E) * Small_Value (E) = Ureal_1);
- end Has_Decimal_Small;
-
--------------------------
-- Rewrite_Object_Image --
--------------------------
diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb
index 78bde89..3be039b 100644
--- a/gcc/ada/exp_intr.adb
+++ b/gcc/ada/exp_intr.adb
@@ -29,7 +29,6 @@ with Einfo; use Einfo;
with Elists; use Elists;
with Expander; use Expander;
with Exp_Atag; use Exp_Atag;
-with Exp_Ch4; use Exp_Ch4;
with Exp_Ch7; use Exp_Ch7;
with Exp_Ch11; use Exp_Ch11;
with Exp_Code; use Exp_Code;
@@ -857,7 +856,7 @@ package body Exp_Intr is
---------------------------
procedure Expand_Unc_Conversion (N : Node_Id; E : Entity_Id) is
- Func : constant Entity_Id := Entity (Name (N));
+ Func : constant Entity_Id := Entity (Name (N));
Conv : Node_Id;
Ftyp : Entity_Id;
Ttyp : Entity_Id;
@@ -908,12 +907,7 @@ package body Exp_Intr is
end if;
Rewrite (N, Unchecked_Convert_To (Ttyp, Conv));
- Set_Etype (N, Ttyp);
- Set_Analyzed (N);
-
- if Nkind (N) = N_Unchecked_Type_Conversion then
- Expand_N_Unchecked_Type_Conversion (N);
- end if;
+ Analyze_And_Resolve (N, Ttyp);
end Expand_Unc_Conversion;
-----------------------------
@@ -1229,9 +1223,8 @@ package body Exp_Intr is
if Is_Class_Wide_Type (Desig_Typ)
or else
- (Is_Array_Type (Desig_Typ)
- and then not Is_Constrained (Desig_Typ)
- and then Is_Packed (Desig_Typ))
+ (Is_Packed_Array (Desig_Typ)
+ and then not Is_Constrained (Desig_Typ))
then
declare
Deref : constant Node_Id :=
diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb
index 07a05a5..c90409b 100644
--- a/gcc/ada/exp_pakd.adb
+++ b/gcc/ada/exp_pakd.adb
@@ -1256,8 +1256,15 @@ package body Exp_Pakd is
-- array type on Obj to get lost. So we save the type of Obj, and
-- make sure it is reset properly.
- New_Lhs := Duplicate_Subexpr (Obj, Name_Req => True);
- New_Rhs := Duplicate_Subexpr_No_Checks (Obj);
+ declare
+ T : constant Entity_Id := Etype (Obj);
+ begin
+ New_Lhs := Duplicate_Subexpr (Obj, Name_Req => True);
+ New_Rhs := Duplicate_Subexpr_No_Checks (Obj);
+ Set_Etype (Obj, T);
+ Set_Etype (New_Lhs, T);
+ Set_Etype (New_Rhs, T);
+ end;
-- First we deal with the "and"
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index 14ccac9..d616fb6 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -425,7 +425,12 @@ package body Exp_Prag is
-- Generate the appropriate if statement. Note that we consider this to
-- be an explicit conditional in the source, not an implicit if, so we
- -- do not call Make_Implicit_If_Statement.
+ -- do not call Make_Implicit_If_Statement. Note also that we wrap the
+ -- raise statement in a block statement so that, if the condition is
+ -- evaluated at compile time to False, then the rewriting of the if
+ -- statement will not involve the raise but the block statement, and
+ -- thus not leave a dangling reference to the raise statement in the
+ -- Local_Raise_Statements list of the handler.
-- Case where we generate a direct raise
@@ -438,8 +443,14 @@ package body Exp_Prag is
Make_If_Statement (Loc,
Condition => Make_Op_Not (Loc, Right_Opnd => Cond),
Then_Statements => New_List (
- Make_Raise_Statement (Loc,
- Name => New_Occurrence_Of (RTE (RE_Assert_Failure), Loc)))));
+ Make_Block_Statement (Loc,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Raise_Statement (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Assert_Failure),
+ Loc))))))));
-- Case where we call the procedure
@@ -778,16 +789,23 @@ package body Exp_Prag is
is
Copy : Entity_Id;
Param : Node_Id;
+ Expr : Node_Id;
begin
Param := First (Params);
while Present (Param) loop
Copy := Make_Temporary (Loc, 'C');
+ if Nkind (Param) = N_Parameter_Association then
+ Expr := Explicit_Actual_Parameter (Param);
+ else
+ Expr := Param;
+ end if;
+
Append_To (Decls,
Make_Object_Declaration (Loc,
Defining_Identifier => Copy,
- Object_Definition => New_Occurrence_Of (Etype (Param), Loc),
- Expression => New_Copy_Tree (Param)));
+ Object_Definition => New_Occurrence_Of (Etype (Expr), Loc),
+ Expression => New_Copy_Tree (Expr)));
Append_Elmt (Copy, Copies);
Next (Param);
@@ -1563,6 +1581,12 @@ package body Exp_Prag is
Expression => Pref));
end if;
+ -- Mark the temporary as coming from a 'Old reference
+
+ if Present (Temp) then
+ Set_Stores_Attribute_Old_Prefix (Temp);
+ end if;
+
-- Ensure that the prefix is valid
if Validity_Checks_On and then Validity_Check_Operands then
diff --git a/gcc/ada/exp_sel.adb b/gcc/ada/exp_sel.adb
index 0fe9d3b..ccf62c6 100644
--- a/gcc/ada/exp_sel.adb
+++ b/gcc/ada/exp_sel.adb
@@ -70,27 +70,11 @@ package body Exp_Sel is
-------------------------------
function Build_Abort_Block_Handler (Loc : Source_Ptr) return Node_Id is
- Stmt : Node_Id;
-
begin
-
- -- With ZCX exceptions, aborts are not defered in handlers. With SJLJ,
- -- they are deferred at the beginning of Abort_Signal handlers.
-
- if ZCX_Exceptions then
- Stmt := Make_Null_Statement (Loc);
-
- else
- Stmt :=
- Make_Procedure_Call_Statement (Loc,
- Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
- Parameter_Associations => No_List);
- end if;
-
return Make_Implicit_Exception_Handler (Loc,
Exception_Choices =>
New_List (New_Occurrence_Of (Stand.Abort_Signal, Loc)),
- Statements => New_List (Stmt));
+ Statements => New_List (Make_Null_Statement (Loc)));
end Build_Abort_Block_Handler;
-------------
diff --git a/gcc/ada/exp_sel.ads b/gcc/ada/exp_sel.ads
index 98ac647..f2f2c56 100644
--- a/gcc/ada/exp_sel.ads
+++ b/gcc/ada/exp_sel.ads
@@ -39,21 +39,18 @@ package Exp_Sel is
-- begin
-- Blk
-- exception
- -- when Abort_Signal => Abort_Undefer / null;
+ -- when Abort_Signal => null;
-- end;
-- Abr_Blk_Ent is the name of the generated block, Cln_Blk_Ent is the name
-- of the encapsulated cleanup block, Blk is the actual block name.
-- The exception handler code is built by Build_Abort_Block_Handler.
function Build_Abort_Block_Handler (Loc : Source_Ptr) return Node_Id;
- -- Generate if front-end exception:
- -- when others =>
- -- Abort_Undefer;
- -- or if back-end exception:
+ -- Generate:
-- when others =>
-- null;
-- This is an exception handler to stop propagation of aborts, without
- -- modifying the deferal level.
+ -- modifying the deferral level.
function Build_B
(Loc : Source_Ptr;
diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb
index f6ef865..d65136b 100644
--- a/gcc/ada/exp_spark.adb
+++ b/gcc/ada/exp_spark.adb
@@ -52,9 +52,6 @@ package body Exp_SPARK is
-- Local Subprograms --
-----------------------
- procedure Expand_SPARK_N_Aggregate (N : Node_Id);
- -- Perform aggregate-specific expansion
-
procedure Expand_SPARK_N_Attribute_Reference (N : Node_Id);
-- Perform attribute-reference-specific expansion
@@ -105,9 +102,6 @@ package body Exp_SPARK is
=>
Qualify_Entity_Names (N);
- when N_Aggregate =>
- Expand_SPARK_N_Aggregate (N);
-
-- Replace occurrences of System'To_Address by calls to
-- System.Storage_Elements.To_Address.
@@ -227,7 +221,8 @@ package body Exp_SPARK is
if Nkind (Assoc) = N_Iterated_Component_Association then
Push_Scope (Scope (Defining_Identifier (Assoc)));
- Analyze_And_Resolve (Expression (Assoc), Comp_Type);
+ Enter_Name (Defining_Identifier (Assoc));
+ Analyze_And_Resolve (Expr, Comp_Type);
end if;
if Is_Scalar_Type (Comp_Type) then
@@ -240,11 +235,7 @@ package body Exp_SPARK is
End_Scope;
end if;
- Index :=
- First
- (if Nkind (Assoc) = N_Iterated_Component_Association
- then Discrete_Choices (Assoc)
- else Choices (Assoc));
+ Index := First (Choice_List (Assoc));
Index_Typ := First_Index (Typ);
while Present (Index) loop
@@ -366,78 +357,13 @@ package body Exp_SPARK is
-- procedure for it as done during regular expansion for compilation.
if Has_DIC (E) and then Is_Tagged_Type (E) then
- Build_DIC_Procedure_Body (E, For_Freeze => True);
+ -- Why is this needed for DIC, but not for other aspects (such as
+ -- Type_Invariant)???
+
+ Build_DIC_Procedure_Body (E);
end if;
end Expand_SPARK_N_Freeze_Type;
- ------------------------------
- -- Expand_SPARK_N_Aggregate --
- ------------------------------
-
- procedure Expand_SPARK_N_Aggregate (N : Node_Id) is
- Assoc : Node_Id := First (Component_Associations (N));
- begin
- -- For compilation, frontend analyses a copy of the
- -- iterated_component_association's expression for legality checking;
- -- (then the expression is copied again when expanding association into
- -- assignments for the individual choices). For SPARK we analyze the
- -- original expression and apply range checks, if required.
-
- while Present (Assoc) loop
- if Nkind (Assoc) = N_Iterated_Component_Association then
- declare
- Typ : constant Entity_Id := Etype (N);
-
- Comp_Type : constant Entity_Id := Component_Type (Typ);
- Expr : constant Node_Id := Expression (Assoc);
- Index_Typ : constant Entity_Id := First_Index (Typ);
-
- Index : Node_Id;
-
- begin
- -- Analyze expression with index parameter in scope
-
- Push_Scope (Scope (Defining_Identifier (Assoc)));
- Enter_Name (Defining_Identifier (Assoc));
- Analyze_And_Resolve (Expression (Assoc), Comp_Type);
-
- if Is_Scalar_Type (Comp_Type) then
- Apply_Scalar_Range_Check (Expr, Comp_Type);
- end if;
-
- End_Scope;
-
- -- Analyze discrete choices
-
- Index := First (Discrete_Choices (Assoc));
-
- while Present (Index) loop
-
- -- The index denotes a range of elements where range checks
- -- have been already applied.
-
- if Nkind (Index) in N_Others_Choice
- | N_Range
- | N_Subtype_Indication
- then
- null;
-
- -- Otherwise the index denotes a single element (or a
- -- subtype name which doesn't require range checks).
-
- else pragma Assert (Nkind (Index) in N_Subexpr);
- Apply_Scalar_Range_Check (Index, Etype (Index_Typ));
- end if;
-
- Next (Index);
- end loop;
- end;
- end if;
-
- Next (Assoc);
- end loop;
- end Expand_SPARK_N_Aggregate;
-
----------------------------------------
-- Expand_SPARK_N_Attribute_Reference --
----------------------------------------
@@ -451,101 +377,105 @@ package body Exp_SPARK is
Expr : Node_Id;
begin
- if Attr_Id = Attribute_To_Address then
+ case Attr_Id is
+ when Attribute_To_Address =>
- -- Extract and convert argument to expected type for call
+ -- Extract and convert argument to expected type for call
- Expr :=
- Make_Type_Conversion (Loc,
- Subtype_Mark =>
- New_Occurrence_Of (RTE (RE_Integer_Address), Loc),
- Expression => Relocate_Node (First (Expressions (N))));
+ Expr :=
+ Make_Type_Conversion (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (RTE (RE_Integer_Address), Loc),
+ Expression => Relocate_Node (First (Expressions (N))));
- -- Replace attribute reference with call
+ -- Replace attribute reference with call
- Rewrite (N,
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_To_Address), Loc),
- Parameter_Associations => New_List (Expr)));
- Analyze_And_Resolve (N, Typ);
-
- elsif Attr_Id = Attribute_Object_Size
- or else Attr_Id = Attribute_Size
- or else Attr_Id = Attribute_Value_Size
- or else Attr_Id = Attribute_VADS_Size
- then
- Exp_Attr.Expand_Size_Attribute (N);
-
- -- For attributes which return Universal_Integer, introduce a conversion
- -- to the expected type with the appropriate check flags set.
-
- elsif Attr_Id = Attribute_Alignment
- or else Attr_Id = Attribute_Bit
- or else Attr_Id = Attribute_Bit_Position
- or else Attr_Id = Attribute_Descriptor_Size
- or else Attr_Id = Attribute_First_Bit
- or else Attr_Id = Attribute_Last_Bit
- or else Attr_Id = Attribute_Length
- or else Attr_Id = Attribute_Max_Size_In_Storage_Elements
- or else Attr_Id = Attribute_Pos
- or else Attr_Id = Attribute_Position
- or else Attr_Id = Attribute_Range_Length
- or else Attr_Id = Attribute_Aft
- or else Attr_Id = Attribute_Max_Alignment_For_Allocation
- then
- -- If the expected type is Long_Long_Integer, there will be no check
- -- flag as the compiler assumes attributes always fit in this type.
- -- Since in SPARK_Mode we do not take Storage_Error into account, we
- -- cannot make this assumption and need to produce a check.
- -- ??? It should be enough to add this check for attributes
- -- 'Length, 'Range_Length and 'Pos when the type is as big
- -- as Long_Long_Integer.
-
- declare
- Typ : Entity_Id;
- begin
- if Attr_Id = Attribute_Range_Length
- or else Attr_Id = Attribute_Pos
- then
- Typ := Etype (Prefix (N));
+ Rewrite
+ (N,
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_To_Address), Loc),
+ Parameter_Associations => New_List (Expr)));
+ Analyze_And_Resolve (N, Typ);
- elsif Attr_Id = Attribute_Length then
- Typ := Get_Index_Subtype (N);
+ when Attribute_Object_Size
+ | Attribute_Size
+ | Attribute_Value_Size
+ | Attribute_VADS_Size
+ =>
+ Exp_Attr.Expand_Size_Attribute (N);
+
+ -- For attributes which return Universal_Integer, introduce a
+ -- conversion to the expected type with the appropriate check flags
+ -- set.
+
+ when Attribute_Aft
+ | Attribute_Alignment
+ | Attribute_Bit
+ | Attribute_Bit_Position
+ | Attribute_Descriptor_Size
+ | Attribute_First_Bit
+ | Attribute_Last_Bit
+ | Attribute_Length
+ | Attribute_Max_Alignment_For_Allocation
+ | Attribute_Max_Size_In_Storage_Elements
+ | Attribute_Pos
+ | Attribute_Position
+ | Attribute_Range_Length
+ =>
+ -- If the expected type is Long_Long_Integer, there will be no
+ -- check flag as the compiler assumes attributes always fit in
+ -- this type. Since in SPARK_Mode we do not take Storage_Error
+ -- into account, we cannot make this assumption and need to
+ -- produce a check. ??? It should be enough to add this check for
+ -- attributes 'Length, 'Range_Length and 'Pos when the type is as
+ -- big as Long_Long_Integer.
- else
- Typ := Empty;
- end if;
+ declare
+ Typ : Entity_Id;
+ begin
+ if Attr_Id in Attribute_Pos | Attribute_Range_Length then
+ Typ := Etype (Prefix (N));
- Apply_Universal_Integer_Attribute_Checks (N);
+ elsif Attr_Id = Attribute_Length then
+ Typ := Get_Index_Subtype (N);
- if Present (Typ)
- and then RM_Size (Typ) = RM_Size (Standard_Long_Long_Integer)
- then
- -- ??? This should rather be a range check, but this would
- -- crash GNATprove which somehow recovers the proper kind
- -- of check anyway.
- Set_Do_Overflow_Check (N);
- end if;
- end;
+ else
+ Typ := Empty;
+ end if;
+
+ Apply_Universal_Integer_Attribute_Checks (N);
- elsif Attr_Id = Attribute_Constrained then
+ if Present (Typ)
+ and then RM_Size (Typ) = RM_Size (Standard_Long_Long_Integer)
+ then
+ -- ??? This should rather be a range check, but this would
+ -- crash GNATprove which somehow recovers the proper kind
+ -- of check anyway.
+ Set_Do_Overflow_Check (N);
+ end if;
+ end;
- -- If the prefix is an access to object, the attribute applies to
- -- the designated object, so rewrite with an explicit dereference.
+ when Attribute_Constrained =>
- if Is_Access_Type (Etype (Pref))
- and then
- (not Is_Entity_Name (Pref) or else Is_Object (Entity (Pref)))
- then
- Rewrite (Pref,
- Make_Explicit_Dereference (Loc, Relocate_Node (Pref)));
- Analyze_And_Resolve (N, Standard_Boolean);
- end if;
+ -- If the prefix is an access to object, the attribute applies to
+ -- the designated object, so rewrite with an explicit dereference.
- elsif Attr_Id = Attribute_Update then
- Expand_SPARK_Delta_Or_Update (Typ, First (Expressions (N)));
- end if;
+ if Is_Access_Type (Etype (Pref))
+ and then
+ (not Is_Entity_Name (Pref) or else Is_Object (Entity (Pref)))
+ then
+ Rewrite (Pref,
+ Make_Explicit_Dereference (Loc, Relocate_Node (Pref)));
+ Analyze_And_Resolve (N, Standard_Boolean);
+ end if;
+
+ when Attribute_Update =>
+ Expand_SPARK_Delta_Or_Update (Typ, First (Expressions (N)));
+
+ when others =>
+ null;
+ end case;
end Expand_SPARK_N_Attribute_Reference;
------------------------------------
@@ -603,7 +533,7 @@ package body Exp_SPARK is
and then Present (DIC_Procedure (Typ))
and then not Has_Init_Expression (N)
then
- Call := Build_DIC_Call (Loc, Obj_Id, Typ);
+ Call := Build_DIC_Call (Loc, New_Occurrence_Of (Obj_Id, Loc), Typ);
-- Partially insert the call into the tree by setting its parent
-- pointer.
diff --git a/gcc/ada/exp_strm.adb b/gcc/ada/exp_strm.adb
index 6cda955..09bd872 100644
--- a/gcc/ada/exp_strm.adb
+++ b/gcc/ada/exp_strm.adb
@@ -578,8 +578,11 @@ package body Exp_Strm is
elsif P_Size <= Standard_Long_Integer_Size then
Lib_RE := RE_I_LI;
- else
+ elsif P_Size <= Standard_Long_Long_Integer_Size then
Lib_RE := RE_I_LLI;
+
+ else
+ Lib_RE := RE_I_LLLI;
end if;
-- Unsigned integer types, also includes unsigned fixed-point types
@@ -609,8 +612,11 @@ package body Exp_Strm is
elsif P_Size <= Standard_Long_Integer_Size then
Lib_RE := RE_I_LU;
- else
+ elsif P_Size <= Standard_Long_Long_Integer_Size then
Lib_RE := RE_I_LLU;
+
+ else
+ Lib_RE := RE_I_LLLU;
end if;
else pragma Assert (Is_Access_Type (U_Type));
@@ -802,16 +808,24 @@ package body Exp_Strm is
then
if P_Size <= Standard_Short_Short_Integer_Size then
Lib_RE := RE_W_SSI;
+
elsif P_Size <= Standard_Short_Integer_Size then
Lib_RE := RE_W_SI;
+
elsif P_Size = 24 then
Lib_RE := RE_W_I24;
+
elsif P_Size <= Standard_Integer_Size then
Lib_RE := RE_W_I;
+
elsif P_Size <= Standard_Long_Integer_Size then
Lib_RE := RE_W_LI;
- else
+
+ elsif P_Size <= Standard_Long_Long_Integer_Size then
Lib_RE := RE_W_LLI;
+
+ else
+ Lib_RE := RE_W_LLLI;
end if;
-- Unsigned integer types, also includes unsigned fixed-point types
@@ -828,16 +842,24 @@ package body Exp_Strm is
then
if P_Size <= Standard_Short_Short_Integer_Size then
Lib_RE := RE_W_SSU;
+
elsif P_Size <= Standard_Short_Integer_Size then
Lib_RE := RE_W_SU;
+
elsif P_Size = 24 then
Lib_RE := RE_W_U24;
+
elsif P_Size <= Standard_Integer_Size then
Lib_RE := RE_W_U;
+
elsif P_Size <= Standard_Long_Integer_Size then
Lib_RE := RE_W_LU;
- else
+
+ elsif P_Size <= Standard_Long_Long_Integer_Size then
Lib_RE := RE_W_LLU;
+
+ else
+ Lib_RE := RE_W_LLLU;
end if;
else pragma Assert (Is_Access_Type (U_Type));
diff --git a/gcc/ada/exp_tss.adb b/gcc/ada/exp_tss.adb
index 40943fb..c5f167a 100644
--- a/gcc/ada/exp_tss.adb
+++ b/gcc/ada/exp_tss.adb
@@ -522,46 +522,4 @@ package body Exp_Tss is
return Empty;
end TSS;
- function TSS (Typ : Entity_Id; Nam : Name_Id) return Entity_Id is
- FN : constant Node_Id := Freeze_Node (Typ);
- Elmt : Elmt_Id;
- Subp : Entity_Id;
-
- begin
- if No (FN) then
- return Empty;
-
- elsif No (TSS_Elist (FN)) then
- return Empty;
-
- else
- Elmt := First_Elmt (TSS_Elist (FN));
- while Present (Elmt) loop
- if Chars (Node (Elmt)) = Nam then
- Subp := Node (Elmt);
-
- -- For stream subprograms, the TSS entity may be a renaming-
- -- as-body of an already generated entity. Use that one rather
- -- the one introduced by the renaming, which is an artifact of
- -- current stream handling.
-
- if Nkind (Parent (Parent (Subp))) =
- N_Subprogram_Renaming_Declaration
- and then
- Present (Corresponding_Spec (Parent (Parent (Subp))))
- then
- return Corresponding_Spec (Parent (Parent (Subp)));
- else
- return Subp;
- end if;
-
- else
- Next_Elmt (Elmt);
- end if;
- end loop;
- end if;
-
- return Empty;
- end TSS;
-
end Exp_Tss;
diff --git a/gcc/ada/exp_tss.ads b/gcc/ada/exp_tss.ads
index 59234ff..ca35f5a 100644
--- a/gcc/ada/exp_tss.ads
+++ b/gcc/ada/exp_tss.ads
@@ -170,7 +170,6 @@ package Exp_Tss is
-- be explicitly frozen, so the N_Freeze_Entity node always exists).
function TSS (Typ : Entity_Id; Nam : TSS_Name_Type) return Entity_Id;
- function TSS (Typ : Entity_Id; Nam : Name_Id) return Entity_Id;
-- Finds the TSS with the given name associated with the given type.
-- If no such TSS exists, then Empty is returned.
diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb
index ffc30c3..ee2cf81 100644
--- a/gcc/ada/exp_unst.adb
+++ b/gcc/ada/exp_unst.adb
@@ -251,13 +251,8 @@ package body Exp_Unst is
-----------------------
function Needs_Fat_Pointer (E : Entity_Id) return Boolean is
- Typ : Entity_Id := Etype (E);
-
+ Typ : constant Entity_Id := Get_Fullest_View (Etype (E));
begin
- if Is_Private_Type (Typ) and then Present (Full_View (Typ)) then
- Typ := Full_View (Typ);
- end if;
-
return Is_Array_Type (Typ) and then not Is_Constrained (Typ);
end Needs_Fat_Pointer;
@@ -882,8 +877,8 @@ package body Exp_Unst is
-- outside the nested structure do not affect us.
if Scope_Within (Ent, Subp)
- and then Is_Subprogram (Ent)
- and then not Is_Imported (Ent)
+ and then Is_Subprogram (Ent)
+ and then not Is_Imported (Ent)
then
Append_Unique_Call ((N, Current_Subprogram, Ent));
end if;
@@ -898,6 +893,8 @@ package body Exp_Unst is
DT : Boolean := False;
Formal : Node_Id;
Subp : Entity_Id;
+ F_Type : Entity_Id;
+ A_Type : Entity_Id;
begin
if Nkind (Name (N)) = N_Explicit_Dereference then
@@ -908,12 +905,16 @@ package body Exp_Unst is
Actual := First_Actual (N);
Formal := First_Formal_With_Extras (Subp);
+
while Present (Actual) loop
- if Is_Array_Type (Etype (Formal))
- and then not Is_Constrained (Etype (Formal))
- and then Is_Constrained (Etype (Actual))
+ F_Type := Get_Fullest_View (Etype (Formal));
+ A_Type := Get_Fullest_View (Etype (Actual));
+
+ if Is_Array_Type (F_Type)
+ and then not Is_Constrained (F_Type)
+ and then Is_Constrained (A_Type)
then
- Check_Static_Type (Etype (Actual), Empty, DT);
+ Check_Static_Type (A_Type, Empty, DT);
end if;
Next_Actual (Actual);
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 6b474d8..cf4059a 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -60,10 +60,8 @@ with Sem_Util; use Sem_Util;
with Snames; use Snames;
with Stand; use Stand;
with Stringt; use Stringt;
-with Targparm; use Targparm;
with Tbuild; use Tbuild;
with Ttypes; use Ttypes;
-with Urealp; use Urealp;
with Validsw; use Validsw;
with GNAT.HTable;
@@ -169,6 +167,16 @@ package body Exp_Util is
-- Determine whether pragma Default_Initial_Condition denoted by Prag has
-- an assertion expression that should be verified at run time.
+ function Is_Uninitialized_Aggregate
+ (Exp : Node_Id;
+ T : Entity_Id) return Boolean;
+ -- Determine whether an array aggregate used in an object declaration
+ -- is uninitialized, when the aggregate is declared with a box and
+ -- the component type has no default value. Such an aggregate can be
+ -- optimized away to prevent the copying of uninitialized data, and
+ -- the bounds of the aggregate can be propagated directly to the
+ -- object declaration.
+
function Make_CW_Equivalent_Type
(T : Entity_Id;
E : Node_Id) return Entity_Id;
@@ -471,9 +479,9 @@ package body Exp_Util is
end if;
end Append_Freeze_Actions;
- --------------------------------------
- -- Attr_Constrained_Statically_True --
- --------------------------------------
+ ----------------------------------------
+ -- Attribute_Constrained_Static_Value --
+ ----------------------------------------
function Attribute_Constrained_Static_Value (Pref : Node_Id) return Boolean
is
@@ -535,7 +543,7 @@ package body Exp_Util is
if Is_Entity_Name (Pref) then
declare
- Ent : constant Entity_Id := Entity (Pref);
+ Ent : constant Entity_Id := Entity (Pref);
Res : Boolean;
begin
@@ -1436,21 +1444,27 @@ package body Exp_Util is
--------------------
function Build_DIC_Call
- (Loc : Source_Ptr;
- Obj_Id : Entity_Id;
- Typ : Entity_Id) return Node_Id
+ (Loc : Source_Ptr;
+ Obj_Name : Node_Id;
+ Typ : Entity_Id) return Node_Id
is
Proc_Id : constant Entity_Id := DIC_Procedure (Typ);
Formal_Typ : constant Entity_Id := Etype (First_Formal (Proc_Id));
begin
+ -- The DIC procedure has a null body if assertions are disabled or
+ -- Assertion_Policy Ignore is in effect. In that case, it would be
+ -- nice to generate a null statement instead of a call to the DIC
+ -- procedure, but doing that seems to interfere with the determination
+ -- of ECRs (early call regions) in SPARK. ???
+
return
Make_Procedure_Call_Statement (Loc,
Name => New_Occurrence_Of (Proc_Id, Loc),
Parameter_Associations => New_List (
Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark => New_Occurrence_Of (Formal_Typ, Loc),
- Expression => New_Occurrence_Of (Obj_Id, Loc))));
+ Expression => Obj_Name)));
end Build_DIC_Call;
------------------------------
@@ -1462,9 +1476,13 @@ package body Exp_Util is
-- Ghost mode.
procedure Build_DIC_Procedure_Body
- (Typ : Entity_Id;
- For_Freeze : Boolean := False)
+ (Typ : Entity_Id;
+ Partial_DIC : Boolean := False)
is
+ Pragmas_Seen : Elist_Id := No_Elist;
+ -- This list contains all DIC pragmas processed so far. The list is used
+ -- to avoid redundant Default_Initial_Condition checks.
+
procedure Add_DIC_Check
(DIC_Prag : Node_Id;
DIC_Expr : Node_Id;
@@ -1484,24 +1502,46 @@ package body Exp_Util is
-- pragma. All generated code is added to list Stmts.
procedure Add_Inherited_Tagged_DIC
- (DIC_Prag : Node_Id;
- Par_Typ : Entity_Id;
- Deriv_Typ : Entity_Id;
- Stmts : in out List_Id);
+ (DIC_Prag : Node_Id;
+ Expr : Node_Id;
+ Stmts : in out List_Id);
-- Add a runtime check to verify assertion expression DIC_Expr of
- -- inherited pragma DIC_Prag. This routine applies class-wide pre- and
- -- postcondition-like runtime semantics to the check. Par_Typ is the
- -- parent type whose DIC pragma is being inherited. Deriv_Typ is the
- -- derived type inheriting the DIC pragma. All generated code is added
- -- to list Stmts.
+ -- inherited pragma DIC_Prag. This routine applies class-wide pre-
+ -- and postcondition-like runtime semantics to the check. Expr is
+ -- the assertion expression after substitition has been performed
+ -- (via Replace_References). All generated code is added to list Stmts.
+
+ procedure Add_Inherited_DICs
+ (T : Entity_Id;
+ Priv_Typ : Entity_Id;
+ Full_Typ : Entity_Id;
+ Obj_Id : Entity_Id;
+ Checks : in out List_Id);
+ -- Generate a DIC check for each inherited Default_Initial_Condition
+ -- coming from all parent types of type T. Priv_Typ and Full_Typ denote
+ -- the partial and full view of the parent type. Obj_Id denotes the
+ -- entity of the _object formal parameter of the DIC procedure. All
+ -- created checks are added to list Checks.
procedure Add_Own_DIC
(DIC_Prag : Node_Id;
DIC_Typ : Entity_Id;
+ Obj_Id : Entity_Id;
Stmts : in out List_Id);
-- Add a runtime check to verify the assertion expression of pragma
- -- DIC_Prag. DIC_Typ is the owner of the DIC pragma. All generated code
- -- is added to list Stmts.
+ -- DIC_Prag. DIC_Typ is the owner of the DIC pragma. Obj_Id is the
+ -- object to substitute in the assertion expression for any references
+ -- to the current instance of the type All generated code is added to
+ -- list Stmts.
+
+ procedure Add_Parent_DICs
+ (T : Entity_Id;
+ Obj_Id : Entity_Id;
+ Checks : in out List_Id);
+ -- Generate a Default_Initial_Condition check for each inherited DIC
+ -- aspect coming from all parent types of type T. Obj_Id denotes the
+ -- entity of the _object formal parameter of the DIC procedure. All
+ -- created checks are added to list Checks.
-------------------
-- Add_DIC_Check --
@@ -1539,6 +1579,10 @@ package body Exp_Util is
Make_Pragma_Argument_Association (Loc,
Expression => DIC_Expr))));
end if;
+
+ -- Add the pragma to the list of processed pragmas
+
+ Append_New_Elmt (DIC_Prag, Pragmas_Seen);
end Add_DIC_Check;
-----------------------
@@ -1580,65 +1624,172 @@ package body Exp_Util is
------------------------------
procedure Add_Inherited_Tagged_DIC
- (DIC_Prag : Node_Id;
- Par_Typ : Entity_Id;
- Deriv_Typ : Entity_Id;
- Stmts : in out List_Id)
+ (DIC_Prag : Node_Id;
+ Expr : Node_Id;
+ Stmts : in out List_Id)
is
- Deriv_Proc : constant Entity_Id := DIC_Procedure (Deriv_Typ);
- DIC_Args : constant List_Id :=
- Pragma_Argument_Associations (DIC_Prag);
- DIC_Arg : constant Node_Id := First (DIC_Args);
- DIC_Expr : constant Node_Id := Expression_Copy (DIC_Arg);
- Par_Proc : constant Entity_Id := DIC_Procedure (Par_Typ);
+ begin
+ -- Once the DIC assertion expression is fully processed, add a check
+ -- to the statements of the DIC procedure.
- Expr : Node_Id;
+ Add_DIC_Check
+ (DIC_Prag => DIC_Prag,
+ DIC_Expr => Expr,
+ Stmts => Stmts);
+ end Add_Inherited_Tagged_DIC;
+
+ ------------------------
+ -- Add_Inherited_DICs --
+ ------------------------
+
+ procedure Add_Inherited_DICs
+ (T : Entity_Id;
+ Priv_Typ : Entity_Id;
+ Full_Typ : Entity_Id;
+ Obj_Id : Entity_Id;
+ Checks : in out List_Id)
+ is
+ Deriv_Typ : Entity_Id;
+ Expr : Node_Id;
+ Prag : Node_Id;
+ Prag_Expr : Node_Id;
+ Prag_Expr_Arg : Node_Id;
+ Prag_Typ : Node_Id;
+ Prag_Typ_Arg : Node_Id;
+
+ Par_Proc : Entity_Id;
+ -- The "partial" invariant procedure of Par_Typ
+
+ Par_Typ : Entity_Id;
+ -- The suitable view of the parent type used in the substitution of
+ -- type attributes.
begin
- -- The processing of an inherited DIC assertion expression starts off
- -- with a copy of the original parent expression where all references
- -- to the parent type have already been replaced with references to
- -- the _object formal parameter of the parent type's DIC procedure.
+ if not Present (Priv_Typ) and then not Present (Full_Typ) then
+ return;
+ end if;
- pragma Assert (Present (DIC_Expr));
- Expr := New_Copy_Tree (DIC_Expr);
+ -- When the type inheriting the class-wide invariant is a concurrent
+ -- type, use the corresponding record type because it contains all
+ -- primitive operations of the concurrent type and allows for proper
+ -- substitution.
+
+ if Is_Concurrent_Type (T) then
+ Deriv_Typ := Corresponding_Record_Type (T);
+ else
+ Deriv_Typ := T;
+ end if;
- -- Perform the following substitutions:
+ pragma Assert (Present (Deriv_Typ));
- -- * Replace a reference to the _object parameter of the parent
- -- type's DIC procedure with a reference to the _object parameter
- -- of the derived types' DIC procedure.
+ -- Determine which rep item chain to use. Precedence is given to that
+ -- of the parent type's partial view since it usually carries all the
+ -- class-wide invariants.
- -- * Replace a reference to a discriminant of the parent type with
- -- a suitable value from the point of view of the derived type.
+ if Present (Priv_Typ) then
+ Prag := First_Rep_Item (Priv_Typ);
+ else
+ Prag := First_Rep_Item (Full_Typ);
+ end if;
- -- * Replace a call to an overridden parent primitive with a call
- -- to the overriding derived type primitive.
+ while Present (Prag) loop
+ if Nkind (Prag) = N_Pragma
+ and then Pragma_Name (Prag) = Name_Default_Initial_Condition
+ then
+ -- Nothing to do if the pragma was already processed
- -- * Replace a call to an inherited parent primitive with a call to
- -- the internally-generated inherited derived type primitive.
+ if Contains (Pragmas_Seen, Prag) then
+ return;
+ end if;
- -- Note that primitives defined in the private part are automatically
- -- handled by the overriding/inheritance mechanism and do not require
- -- an extra replacement pass.
+ -- Extract arguments of the Default_Initial_Condition pragma
- pragma Assert (Present (Deriv_Proc) and then Present (Par_Proc));
+ Prag_Expr_Arg := First (Pragma_Argument_Associations (Prag));
+ Prag_Expr := Expression_Copy (Prag_Expr_Arg);
- Replace_References
- (Expr => Expr,
- Par_Typ => Par_Typ,
- Deriv_Typ => Deriv_Typ,
- Par_Obj => First_Formal (Par_Proc),
- Deriv_Obj => First_Formal (Deriv_Proc));
+ -- Pick up the implicit second argument of the pragma, which
+ -- indicates the type that the pragma applies to.
- -- Once the DIC assertion expression is fully processed, add a check
- -- to the statements of the DIC procedure.
+ Prag_Typ_Arg := Next (Prag_Expr_Arg);
+ if Present (Prag_Typ_Arg) then
+ Prag_Typ := Get_Pragma_Arg (Prag_Typ_Arg);
+ else
+ Prag_Typ := Empty;
+ end if;
- Add_DIC_Check
- (DIC_Prag => DIC_Prag,
- DIC_Expr => Expr,
- Stmts => Stmts);
- end Add_Inherited_Tagged_DIC;
+ -- The pragma applies to the partial view of the parent type
+
+ if Present (Priv_Typ)
+ and then Present (Prag_Typ)
+ and then Entity (Prag_Typ) = Priv_Typ
+ then
+ Par_Typ := Priv_Typ;
+
+ -- The pragma applies to the full view of the parent type
+
+ elsif Present (Full_Typ)
+ and then Present (Prag_Typ)
+ and then Entity (Prag_Typ) = Full_Typ
+ then
+ Par_Typ := Full_Typ;
+
+ -- Otherwise the pragma does not belong to the parent type and
+ -- should not be considered.
+
+ else
+ return;
+ end if;
+
+ -- Substitute references in the DIC expression that are related
+ -- to the partial type with corresponding references related to
+ -- the derived type (call to Replace_References below).
+
+ Expr := New_Copy_Tree (Prag_Expr);
+
+ Par_Proc := Partial_DIC_Procedure (Par_Typ);
+
+ -- If there's not a partial DIC procedure (such as when a
+ -- full type doesn't have its own DIC, but is inherited from
+ -- a type with DIC), get the full DIC procedure.
+
+ if not Present (Par_Proc) then
+ Par_Proc := DIC_Procedure (Par_Typ);
+ end if;
+
+ Replace_References
+ (Expr => Expr,
+ Par_Typ => Par_Typ,
+ Deriv_Typ => Deriv_Typ,
+ Par_Obj => First_Formal (Par_Proc),
+ Deriv_Obj => Obj_Id);
+
+ -- Why are there different actions depending on whether T is
+ -- tagged? Can these be unified? ???
+
+ if Is_Tagged_Type (T) then
+ Add_Inherited_Tagged_DIC
+ (DIC_Prag => Prag,
+ Expr => Expr,
+ Stmts => Checks);
+
+ else
+ Add_Inherited_DIC
+ (DIC_Prag => Prag,
+ Par_Typ => Par_Typ,
+ Deriv_Typ => Deriv_Typ,
+ Stmts => Checks);
+ end if;
+
+ -- Leave as soon as we get a DIC pragma, since we'll visit
+ -- the pragmas of the parents, so will get to any "inherited"
+ -- pragmas that way.
+
+ return;
+ end if;
+
+ Next_Rep_Item (Prag);
+ end loop;
+ end Add_Inherited_DICs;
-----------------
-- Add_Own_DIC --
@@ -1647,6 +1798,7 @@ package body Exp_Util is
procedure Add_Own_DIC
(DIC_Prag : Node_Id;
DIC_Typ : Entity_Id;
+ Obj_Id : Entity_Id;
Stmts : in out List_Id)
is
DIC_Args : constant List_Id :=
@@ -1654,8 +1806,6 @@ package body Exp_Util is
DIC_Arg : constant Node_Id := First (DIC_Args);
DIC_Asp : constant Node_Id := Corresponding_Aspect (DIC_Prag);
DIC_Expr : constant Node_Id := Get_Pragma_Arg (DIC_Arg);
- DIC_Proc : constant Entity_Id := DIC_Procedure (DIC_Typ);
- Obj_Id : constant Entity_Id := First_Formal (DIC_Proc);
-- Local variables
@@ -1712,6 +1862,66 @@ package body Exp_Util is
Stmts => Stmts);
end Add_Own_DIC;
+ ---------------------
+ -- Add_Parent_DICs --
+ ---------------------
+
+ procedure Add_Parent_DICs
+ (T : Entity_Id;
+ Obj_Id : Entity_Id;
+ Checks : in out List_Id)
+ is
+ Dummy_1 : Entity_Id;
+ Dummy_2 : Entity_Id;
+
+ Curr_Typ : Entity_Id;
+ -- The entity of the current type being examined
+
+ Full_Typ : Entity_Id;
+ -- The full view of Par_Typ
+
+ Par_Typ : Entity_Id;
+ -- The entity of the parent type
+
+ Priv_Typ : Entity_Id;
+ -- The partial view of Par_Typ
+
+ begin
+ -- Climb the parent type chain
+
+ Curr_Typ := T;
+ loop
+ -- Do not consider subtypes, as they inherit the DICs from their
+ -- base types.
+
+ Par_Typ := Base_Type (Etype (Base_Type (Curr_Typ)));
+
+ -- Stop the climb once the root of the parent chain is
+ -- reached.
+
+ exit when Curr_Typ = Par_Typ;
+
+ -- Process the DICs of the parent type
+
+ Get_Views (Par_Typ, Priv_Typ, Full_Typ, Dummy_1, Dummy_2);
+
+ -- Only try to inherit a DIC pragma from the parent type Par_Typ
+ -- if it Has_Own_DIC pragma. The loop will proceed up the parent
+ -- chain to find all types that have their own DIC.
+
+ if Has_Own_DIC (Par_Typ) then
+ Add_Inherited_DICs
+ (T => T,
+ Priv_Typ => Priv_Typ,
+ Full_Typ => Full_Typ,
+ Obj_Id => Obj_Id,
+ Checks => Checks);
+ end if;
+
+ Curr_Typ := Par_Typ;
+ end loop;
+ end Add_Parent_DICs;
+
-- Local variables
Loc : constant Source_Ptr := Sloc (Typ);
@@ -1730,8 +1940,20 @@ package body Exp_Util is
Proc_Id : Entity_Id;
Stmts : List_Id := No_List;
- Build_Body : Boolean := False;
- -- Flag set when the type requires a DIC procedure body to be built
+ CRec_Typ : Entity_Id := Empty;
+ -- The corresponding record type of Full_Typ
+
+ Full_Typ : Entity_Id := Empty;
+ -- The full view of the working type
+
+ Obj_Id : Entity_Id := Empty;
+ -- The _object formal parameter of the invariant procedure
+
+ Part_Proc : Entity_Id := Empty;
+ -- The entity of the "partial" invariant procedure
+
+ Priv_Typ : Entity_Id := Empty;
+ -- The partial view of the working type
Work_Typ : Entity_Id;
-- The working type
@@ -1795,25 +2017,41 @@ package body Exp_Util is
goto Leave;
end if;
- -- The working type may lack a DIC procedure declaration. This may be
- -- due to several reasons:
+ -- Obtain both views of the type
+
+ Get_Views (Work_Typ, Priv_Typ, Full_Typ, Dummy_1, CRec_Typ);
+
+ -- The caller requests a body for the partial DIC procedure
+
+ if Partial_DIC then
+ Proc_Id := Partial_DIC_Procedure (Work_Typ);
+
+ -- The "full" DIC procedure body was already created
+
+ -- Create a declaration for the "partial" DIC procedure if it
+ -- is not available.
+
+ if No (Proc_Id) then
+ Build_DIC_Procedure_Declaration
+ (Typ => Work_Typ,
+ Partial_DIC => True);
- -- * The working type's own DIC pragma does not contain a verifiable
- -- assertion expression. In this case there is no need to build a
- -- DIC procedure because there is nothing to check.
+ Proc_Id := Partial_DIC_Procedure (Work_Typ);
+ end if;
- -- * The working type derives from a parent type. In this case a DIC
- -- procedure should be built only when the inherited DIC pragma has
- -- a verifiable assertion expression.
+ -- The caller requests a body for the "full" DIC procedure
- Proc_Id := DIC_Procedure (Work_Typ);
+ else
+ Proc_Id := DIC_Procedure (Work_Typ);
+ Part_Proc := Partial_DIC_Procedure (Work_Typ);
- -- Build a DIC procedure declaration when the working type derives from
- -- a parent type.
+ -- Create a declaration for the "full" DIC procedure if it is
+ -- not available.
- if No (Proc_Id) then
- Build_DIC_Procedure_Declaration (Work_Typ);
- Proc_Id := DIC_Procedure (Work_Typ);
+ if No (Proc_Id) then
+ Build_DIC_Procedure_Declaration (Work_Typ);
+ Proc_Id := DIC_Procedure (Work_Typ);
+ end if;
end if;
-- At this point there should be a DIC procedure declaration
@@ -1833,123 +2071,146 @@ package body Exp_Util is
Push_Scope (Proc_Id);
Install_Formals (Proc_Id);
- -- The working type defines its own DIC pragma. Replace the current
- -- instance of the working type with the formal of the DIC procedure.
- -- Note that there is no need to consider inherited DIC pragmas from
- -- parent types because the working type's DIC pragma "hides" all
- -- inherited DIC pragmas.
+ Obj_Id := First_Formal (Proc_Id);
+ pragma Assert (Present (Obj_Id));
- if Has_Own_DIC (Work_Typ) then
- pragma Assert (DIC_Typ = Work_Typ);
+ -- The "partial" DIC procedure verifies the DICs of the partial view
+ -- only.
- Add_Own_DIC
- (DIC_Prag => DIC_Prag,
- DIC_Typ => DIC_Typ,
- Stmts => Stmts);
+ if Partial_DIC then
+ pragma Assert (Present (Priv_Typ));
- Build_Body := True;
+ if Has_Own_DIC (Work_Typ) then -- If we're testing this then maybe
+ Add_Own_DIC -- we shouldn't be calling Find_DIC_Typ above???
+ (DIC_Prag => DIC_Prag,
+ DIC_Typ => DIC_Typ, -- Should this just be Work_Typ???
+ Obj_Id => Obj_Id,
+ Stmts => Stmts);
+ end if;
- -- Otherwise the working type inherits a DIC pragma from a parent type.
- -- This processing is carried out when the type is frozen because the
- -- state of all parent discriminants is known at that point. Note that
- -- it is semantically sound to delay the creation of the DIC procedure
- -- body till the freeze point. If the type has a DIC pragma of its own,
- -- then the DIC procedure body would have already been constructed at
- -- the end of the visible declarations and all parent DIC pragmas are
- -- effectively "hidden" and irrelevant.
+ -- Otherwise the "full" DIC procedure verifies the DICs of the full
+ -- view, well as DICs inherited from parent types. In addition, it
+ -- indirectly verifies the DICs of the partial view by calling the
+ -- "partial" DIC procedure.
- elsif For_Freeze then
- pragma Assert (Has_Inherited_DIC (Work_Typ));
- pragma Assert (DIC_Typ /= Work_Typ);
+ else
+ pragma Assert (Present (Full_Typ));
- -- The working type is tagged. The verification of the assertion
- -- expression is subject to the same semantics as class-wide pre-
- -- and postconditions.
+ -- Check the DIC of the partial view by calling the "partial" DIC
+ -- procedure, unless the partial DIC body is empty. Generate:
- if Is_Tagged_Type (Work_Typ) then
- Add_Inherited_Tagged_DIC
- (DIC_Prag => DIC_Prag,
- Par_Typ => DIC_Typ,
- Deriv_Typ => Work_Typ,
- Stmts => Stmts);
+ -- <Work_Typ>Partial_DIC (_object);
- -- Otherwise the working type is not tagged. Verify the assertion
- -- expression of the inherited DIC pragma by directly calling the
- -- DIC procedure of the parent type.
+ if Present (Part_Proc) and then not Has_Null_Body (Part_Proc) then
+ Append_New_To (Stmts,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Part_Proc, Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of (Obj_Id, Loc))));
+ end if;
- else
- Add_Inherited_DIC
- (DIC_Prag => DIC_Prag,
- Par_Typ => DIC_Typ,
- Deriv_Typ => Work_Typ,
- Stmts => Stmts);
+ -- Derived subtypes do not have a partial view
+
+ if Present (Priv_Typ) then
+
+ -- The processing of the "full" DIC procedure intentionally
+ -- skips the partial view because a) this may result in changes of
+ -- visibility and b) lead to duplicate checks. However, when the
+ -- full view is the underlying full view of an untagged derived
+ -- type whose parent type is private, partial DICs appear on
+ -- the rep item chain of the partial view only.
+
+ -- package Pack_1 is
+ -- type Root ... is private;
+ -- private
+ -- <full view of Root>
+ -- end Pack_1;
+
+ -- with Pack_1;
+ -- package Pack_2 is
+ -- type Child is new Pack_1.Root with Type_DIC => ...;
+ -- <underlying full view of Child>
+ -- end Pack_2;
+
+ -- As a result, the processing of the full view must also consider
+ -- all DICs of the partial view.
+
+ if Is_Untagged_Private_Derivation (Priv_Typ, Full_Typ) then
+ null;
+
+ -- Otherwise the DICs of the partial view are ignored
+
+ else
+ -- Ignore the DICs of the partial view by eliminating the view
+
+ Priv_Typ := Empty;
+ end if;
end if;
- Build_Body := True;
+ -- Process inherited Default_Initial_Conditions for all parent types
+
+ Add_Parent_DICs (Work_Typ, Obj_Id, Stmts);
end if;
End_Scope;
- if Build_Body then
+ -- Produce an empty completing body in the following cases:
+ -- * Assertions are disabled
+ -- * The DIC Assertion_Policy is Ignore
- -- Produce an empty completing body in the following cases:
- -- * Assertions are disabled
- -- * The DIC Assertion_Policy is Ignore
+ if No (Stmts) then
+ Stmts := New_List (Make_Null_Statement (Loc));
+ end if;
- if No (Stmts) then
- Stmts := New_List (Make_Null_Statement (Loc));
- end if;
+ -- Generate:
+ -- procedure <Work_Typ>DIC (_object : <Work_Typ>) is
+ -- begin
+ -- <Stmts>
+ -- end <Work_Typ>DIC;
- -- Generate:
- -- procedure <Work_Typ>DIC (_object : <Work_Typ>) is
- -- begin
- -- <Stmts>
- -- end <Work_Typ>DIC;
-
- Proc_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Copy_Subprogram_Spec (Parent (Proc_Id)),
- Declarations => Empty_List,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Stmts));
- Proc_Body_Id := Defining_Entity (Proc_Body);
-
- -- Perform minor decoration in case the body is not analyzed
-
- Set_Ekind (Proc_Body_Id, E_Subprogram_Body);
- Set_Etype (Proc_Body_Id, Standard_Void_Type);
- Set_Scope (Proc_Body_Id, Current_Scope);
- Set_SPARK_Pragma (Proc_Body_Id, SPARK_Pragma (Proc_Id));
- Set_SPARK_Pragma_Inherited
- (Proc_Body_Id, SPARK_Pragma_Inherited (Proc_Id));
-
- -- Link both spec and body to avoid generating duplicates
-
- Set_Corresponding_Body (Proc_Decl, Proc_Body_Id);
- Set_Corresponding_Spec (Proc_Body, Proc_Id);
-
- -- The body should not be inserted into the tree when the context
- -- is a generic unit because it is not part of the template.
- -- Note that the body must still be generated in order to resolve the
- -- DIC assertion expression.
-
- if Inside_A_Generic then
- null;
+ Proc_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Copy_Subprogram_Spec (Parent (Proc_Id)),
+ Declarations => Empty_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => Stmts));
+ Proc_Body_Id := Defining_Entity (Proc_Body);
- -- Semi-insert the body into the tree for GNATprove by setting its
- -- Parent field. This allows for proper upstream tree traversals.
+ -- Perform minor decoration in case the body is not analyzed
- elsif GNATprove_Mode then
- Set_Parent (Proc_Body, Parent (Declaration_Node (Work_Typ)));
+ Set_Ekind (Proc_Body_Id, E_Subprogram_Body);
+ Set_Etype (Proc_Body_Id, Standard_Void_Type);
+ Set_Scope (Proc_Body_Id, Current_Scope);
+ Set_SPARK_Pragma (Proc_Body_Id, SPARK_Pragma (Proc_Id));
+ Set_SPARK_Pragma_Inherited
+ (Proc_Body_Id, SPARK_Pragma_Inherited (Proc_Id));
- -- Otherwise the body is part of the freezing actions of the working
- -- type.
+ -- Link both spec and body to avoid generating duplicates
- else
- Append_Freeze_Action (Work_Typ, Proc_Body);
- end if;
+ Set_Corresponding_Body (Proc_Decl, Proc_Body_Id);
+ Set_Corresponding_Spec (Proc_Body, Proc_Id);
+
+ -- The body should not be inserted into the tree when the context
+ -- is a generic unit because it is not part of the template.
+ -- Note that the body must still be generated in order to resolve the
+ -- DIC assertion expression.
+
+ if Inside_A_Generic then
+ null;
+
+ -- Semi-insert the body into the tree for GNATprove by setting its
+ -- Parent field. This allows for proper upstream tree traversals.
+
+ elsif GNATprove_Mode then
+ Set_Parent (Proc_Body, Parent (Declaration_Node (Work_Typ)));
+
+ -- Otherwise the body is part of the freezing actions of the working
+ -- type.
+
+ else
+ Append_Freeze_Action (Work_Typ, Proc_Body);
end if;
<<Leave>>
@@ -1964,7 +2225,10 @@ package body Exp_Util is
-- replaced by gotos which jump to the end of the routine and restore the
-- Ghost mode.
- procedure Build_DIC_Procedure_Declaration (Typ : Entity_Id) is
+ procedure Build_DIC_Procedure_Declaration
+ (Typ : Entity_Id;
+ Partial_DIC : Boolean := False)
+ is
Loc : constant Source_Ptr := Sloc (Typ);
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
@@ -1975,6 +2239,7 @@ package body Exp_Util is
DIC_Typ : Entity_Id;
Proc_Decl : Node_Id;
Proc_Id : Entity_Id;
+ Proc_Nam : Name_Id;
Typ_Decl : Node_Id;
CRec_Typ : Entity_Id;
@@ -2050,17 +2315,35 @@ package body Exp_Util is
if not Is_Verifiable_DIC_Pragma (DIC_Prag) then
goto Leave;
+ end if;
+
+ -- Nothing to do if the type already has a "partial" DIC procedure
+
+ if Partial_DIC then
+ if Present (Partial_DIC_Procedure (Work_Typ)) then
+ goto Leave;
+ end if;
- -- Nothing to do if the type already has a DIC procedure
+ -- Nothing to do if the type already has a "full" DIC procedure
elsif Present (DIC_Procedure (Work_Typ)) then
goto Leave;
end if;
+ -- The caller requests the declaration of the "partial" DIC procedure
+
+ if Partial_DIC then
+ Proc_Nam := New_External_Name (Chars (Work_Typ), "Partial_DIC");
+
+ -- Otherwise the caller requests the declaration of the "full" DIC
+ -- procedure.
+
+ else
+ Proc_Nam := New_External_Name (Chars (Work_Typ), "DIC");
+ end if;
+
Proc_Id :=
- Make_Defining_Identifier (Loc,
- Chars =>
- New_External_Name (Chars (Work_Typ), "Default_Initial_Condition"));
+ Make_Defining_Identifier (Loc, Chars => Proc_Nam);
-- Perform minor decoration in case the declaration is not analyzed
@@ -3702,18 +3985,18 @@ package body Exp_Util is
-- Add an extra out parameter to carry the function result
- Name_Len := 6;
- Name_Buffer (1 .. Name_Len) := "RESULT";
Append_To (Proc_Formals,
Make_Parameter_Specification (Loc,
Defining_Identifier =>
- Make_Defining_Identifier (Loc, Chars => Name_Find),
+ Make_Defining_Identifier (Loc, Name_UP_RESULT),
Out_Present => True,
Parameter_Type => New_Occurrence_Of (Etype (Subp), Loc)));
- -- The new procedure declaration is inserted immediately after the
- -- function declaration. The processing in Build_Procedure_Body_Form
- -- relies on this order.
+ -- The new procedure declaration is inserted before the function
+ -- declaration. The processing in Build_Procedure_Body_Form relies on
+ -- this order. Note that we insert before because in the case of a
+ -- function body with no separate spec, we do not want to insert the
+ -- new spec after the body which will later get rewritten.
Proc_Decl :=
Make_Subprogram_Declaration (Loc,
@@ -3723,7 +4006,7 @@ package body Exp_Util is
Make_Defining_Identifier (Loc, Chars (Subp)),
Parameter_Specifications => Proc_Formals));
- Insert_After_And_Analyze (Unit_Declaration_Node (Subp), Proc_Decl);
+ Insert_Before_And_Analyze (Unit_Declaration_Node (Subp), Proc_Decl);
-- Entity of procedure must remain invisible so that it does not
-- overload subsequent references to the original function.
@@ -5337,7 +5620,7 @@ package body Exp_Util is
then
null;
- -- For limited objects initialized with build in place function calls,
+ -- For limited objects initialized with build-in-place function calls,
-- nothing to be done; otherwise we prematurely introduce an N_Reference
-- node in the expression initializing the object, which breaks the
-- circuitry that detects and adds the additional arguments to the
@@ -5346,6 +5629,17 @@ package body Exp_Util is
elsif Is_Build_In_Place_Function_Call (Exp) then
null;
+ -- If the expression is an uninitialized aggregate, no need to build
+ -- a subtype from the expression, because this may require the use of
+ -- dynamic memory to create the object.
+
+ elsif Is_Uninitialized_Aggregate (Exp, Exp_Typ) then
+ Rewrite (Subtype_Indic, New_Occurrence_Of (Etype (Exp), Sloc (N)));
+ if Nkind (N) = N_Object_Declaration then
+ Set_Expression (N, Empty);
+ Set_No_Initialization (N);
+ end if;
+
else
Remove_Side_Effects (Exp);
Rewrite (Subtype_Indic,
@@ -6183,9 +6477,7 @@ package body Exp_Util is
Loc : constant Source_Ptr := Sloc (Var);
Ent : constant Entity_Id := Entity (Var);
- procedure Process_Current_Value_Condition
- (N : Node_Id;
- S : Boolean);
+ procedure Process_Current_Value_Condition (N : Node_Id; S : Boolean);
-- N is an expression which holds either True (S = True) or False (S =
-- False) in the condition. This procedure digs out the expression and
-- if it refers to Ent, sets Op and Val appropriately.
@@ -6246,6 +6538,7 @@ package body Exp_Util is
-- Recursively process AND and AND THEN branches
Process_Current_Value_Condition (Left_Opnd (Cond), True);
+ pragma Assert (Op'Valid);
if Op /= N_Empty then
return;
@@ -6341,6 +6634,17 @@ package body Exp_Util is
return;
end if;
+ -- In GNATprove mode we don't want to use current value optimizer, in
+ -- particular for loop invariant expressions and other assertions that
+ -- act as cut points for proof. The optimizer often folds expressions
+ -- into True/False where they trivially follow from the previous
+ -- assignments, but this deprives proof from the information needed to
+ -- discharge checks that are beyond the scope of the value optimizer.
+
+ if GNATprove_Mode then
+ return;
+ end if;
+
-- Otherwise examine current value
declare
@@ -6567,7 +6871,7 @@ package body Exp_Util is
if Has_Stream_Size_Clause (E) then
return Static_Integer (Expression (Stream_Size_Clause (E)));
- -- Otherwise the Stream_Size if the size of the type
+ -- Otherwise the Stream_Size is the size of the type
else
return Esize (E);
@@ -7594,26 +7898,6 @@ package body Exp_Util is
end if;
end Integer_Type_For;
- ----------------------------
- -- Is_All_Null_Statements --
- ----------------------------
-
- function Is_All_Null_Statements (L : List_Id) return Boolean is
- Stm : Node_Id;
-
- begin
- Stm := First (L);
- while Present (Stm) loop
- if Nkind (Stm) /= N_Null_Statement then
- return False;
- end if;
-
- Next (Stm);
- end loop;
-
- return True;
- end Is_All_Null_Statements;
-
--------------------------------------------------
-- Is_Displacement_Of_Object_Or_Function_Result --
--------------------------------------------------
@@ -7854,6 +8138,10 @@ package body Exp_Util is
-- is in the process of being iterated in the statement list starting
-- from First_Stmt.
+ function Is_Part_Of_BIP_Return_Statement (N : Node_Id) return Boolean;
+ -- Return True if N is directly part of a build-in-place return
+ -- statement.
+
---------------------------
-- Initialized_By_Access --
---------------------------
@@ -8183,6 +8471,35 @@ package body Exp_Util is
return False;
end Is_Iterated_Container;
+ -------------------------------------
+ -- Is_Part_Of_BIP_Return_Statement --
+ -------------------------------------
+
+ function Is_Part_Of_BIP_Return_Statement (N : Node_Id) return Boolean is
+ Subp : constant Entity_Id := Current_Subprogram;
+ Context : Node_Id;
+ begin
+ -- First check if N is part of a BIP function
+
+ if No (Subp)
+ or else not Is_Build_In_Place_Function (Subp)
+ then
+ return False;
+ end if;
+
+ -- Then check whether N is a complete part of a return statement
+ -- Should we consider other node kinds to go up the tree???
+
+ Context := N;
+ loop
+ case Nkind (Context) is
+ when N_Expression_With_Actions => Context := Parent (Context);
+ when N_Simple_Return_Statement => return True;
+ when others => return False;
+ end case;
+ end loop;
+ end Is_Part_Of_BIP_Return_Statement;
+
-- Local variables
Desig : Entity_Id := Obj_Typ;
@@ -8201,6 +8518,7 @@ package body Exp_Util is
and then Needs_Finalization (Desig)
and then Requires_Transient_Scope (Desig)
and then Nkind (Rel_Node) /= N_Simple_Return_Statement
+ and then not Is_Part_Of_BIP_Return_Statement (Rel_Node)
-- Do not consider a transient object that was already processed
@@ -8220,9 +8538,8 @@ package body Exp_Util is
-- initialized by a function that returns a pointer or acts as a
-- renaming of another pointer.
- and then
- (not Is_Access_Type (Obj_Typ)
- or else not Initialized_By_Access (Obj_Id))
+ and then not
+ (Is_Access_Type (Obj_Typ) and then Initialized_By_Access (Obj_Id))
-- Do not consider transient objects which act as indirect aliases
-- of build-in-place function results.
@@ -8761,6 +9078,47 @@ package body Exp_Util is
and then Etype (Expression (Expr)) = RTE (RE_Tag);
end Is_Tag_To_Class_Wide_Conversion;
+ --------------------------------
+ -- Is_Uninitialized_Aggregate --
+ --------------------------------
+
+ function Is_Uninitialized_Aggregate
+ (Exp : Node_Id;
+ T : Entity_Id) return Boolean
+ is
+ Comp : Node_Id;
+ Comp_Type : Entity_Id;
+ Typ : Entity_Id;
+
+ begin
+ if Nkind (Exp) /= N_Aggregate then
+ return False;
+ end if;
+
+ Preanalyze_And_Resolve (Exp, T);
+ Typ := Etype (Exp);
+
+ if No (Typ)
+ or else Ekind (Typ) /= E_Array_Subtype
+ or else Present (Expressions (Exp))
+ or else No (Component_Associations (Exp))
+ then
+ return False;
+ else
+ Comp_Type := Component_Type (Typ);
+ Comp := First (Component_Associations (Exp));
+
+ if not Box_Present (Comp)
+ or else Present (Next (Comp))
+ then
+ return False;
+ end if;
+
+ return Is_Scalar_Type (Comp_Type)
+ and then No (Default_Aspect_Component_Value (Typ));
+ end if;
+ end Is_Uninitialized_Aggregate;
+
----------------------------
-- Is_Untagged_Derivation --
----------------------------
@@ -8804,6 +9162,13 @@ package body Exp_Util is
return
Present (Args)
+
+ -- If there are args, but the first arg is Empty, then treat the
+ -- pragma the same as having no args (there may be a second arg that
+ -- is an implicitly added type arg, and Empty is a placeholder).
+
+ and then Present (Get_Pragma_Arg (First (Args)))
+
and then Nkind (Get_Pragma_Arg (First (Args))) /= N_Null;
end Is_Verifiable_DIC_Pragma;
@@ -9005,25 +9370,6 @@ package body Exp_Util is
end if;
end Kill_Dead_Code;
- ------------------------
- -- Known_Non_Negative --
- ------------------------
-
- function Known_Non_Negative (Opnd : Node_Id) return Boolean is
- begin
- if Is_OK_Static_Expression (Opnd) and then Expr_Value (Opnd) >= 0 then
- return True;
-
- else
- declare
- Lo : constant Node_Id := Type_Low_Bound (Etype (Opnd));
- begin
- return
- Is_OK_Static_Expression (Lo) and then Expr_Value (Lo) >= 0;
- end;
- end if;
- end Known_Non_Negative;
-
-----------------------------
-- Make_CW_Equivalent_Type --
-----------------------------
@@ -10592,20 +10938,6 @@ package body Exp_Util is
return Res;
end New_Class_Wide_Subtype;
- --------------------------------
- -- Non_Limited_Designated_Type --
- ---------------------------------
-
- function Non_Limited_Designated_Type (T : Entity_Id) return Entity_Id is
- Desig : constant Entity_Id := Designated_Type (T);
- begin
- if Has_Non_Limited_View (Desig) then
- return Non_Limited_View (Desig);
- else
- return Desig;
- end if;
- end Non_Limited_Designated_Type;
-
-----------------------------------
-- OK_To_Do_Constant_Replacement --
-----------------------------------
@@ -11091,6 +11423,12 @@ package body Exp_Util is
-- otherwise it generates an internal temporary. The created temporary
-- entity is marked as internal.
+ function Possible_Side_Effect_In_SPARK (Exp : Node_Id) return Boolean;
+ -- Computes whether a side effect is possible in SPARK, which should
+ -- be handled by removing it from the expression for GNATprove. Note
+ -- that other side effects related to volatile variables are handled
+ -- separately.
+
---------------------
-- Build_Temporary --
---------------------
@@ -11126,6 +11464,26 @@ package body Exp_Util is
return Temp_Id;
end Build_Temporary;
+ -----------------------------------
+ -- Possible_Side_Effect_In_SPARK --
+ -----------------------------------
+
+ function Possible_Side_Effect_In_SPARK (Exp : Node_Id) return Boolean is
+ begin
+ -- Side-effect removal in SPARK should only occur when not inside a
+ -- generic and not doing a preanalysis, inside an object renaming or
+ -- a type declaration or a for-loop iteration scheme.
+
+ return not Inside_A_Generic
+ and then Full_Analysis
+ and then Nkind (Enclosing_Declaration (Exp)) in
+ N_Full_Type_Declaration
+ | N_Iterator_Specification
+ | N_Loop_Parameter_Specification
+ | N_Object_Renaming_Declaration
+ | N_Subtype_Declaration;
+ end Possible_Side_Effect_In_SPARK;
+
-- Local variables
Loc : constant Source_Ptr := Sloc (Exp);
@@ -11143,11 +11501,11 @@ package body Exp_Util is
begin
-- Handle cases in which there is nothing to do. In GNATprove mode,
-- removal of side effects is useful for the light expansion of
- -- renamings. This removal should only occur when not inside a
- -- generic and not doing a preanalysis.
+ -- renamings.
if not Expander_Active
- and (Inside_A_Generic or not Full_Analysis or not GNATprove_Mode)
+ and then not
+ (GNATprove_Mode and then Possible_Side_Effect_In_SPARK (Exp))
then
return;
@@ -11185,14 +11543,6 @@ package body Exp_Util is
and then Is_Class_Wide_Type (Etype (Exp))
then
return;
-
- -- An expression which is in SPARK mode is considered side effect free
- -- if the resulting value is captured by a variable or a constant.
-
- elsif GNATprove_Mode
- and then Nkind (Parent (Exp)) = N_Object_Declaration
- then
- return;
end if;
-- The remaining processing is done with all checks suppressed
@@ -11394,8 +11744,8 @@ package body Exp_Util is
-- If this is a packed array component or a selected component with a
-- nonstandard representation, we cannot generate a reference because
-- the component may be unaligned, so we must use a renaming and this
- -- renaming must be handled by the front end, as the back end may balk
- -- at the nonstandard representation (see Exp_Ch2.Expand_Renaming).
+ -- renaming is handled by the front end, as the back end may balk at
+ -- the nonstandard representation (see Evaluation_Required in Exp_Ch8).
elsif Nkind (Exp) in N_Indexed_Component | N_Selected_Component
and then Has_Non_Standard_Rep (Etype (Prefix (Exp)))
@@ -11409,8 +11759,7 @@ package body Exp_Util is
Subtype_Mark => New_Occurrence_Of (Exp_Type, Loc),
Name => Relocate_Node (Exp)));
- -- For an expression that denotes a name, we can use a renaming scheme
- -- that is handled by the back end, instead of the front end as above.
+ -- For an expression that denotes a name, we can use a renaming scheme.
-- This is needed for correctness in the case of a volatile object of
-- a nonvolatile type because the Make_Reference call of the "default"
-- approach would generate an illegal access value (an access value
@@ -11433,8 +11782,6 @@ package body Exp_Util is
Subtype_Mark => New_Occurrence_Of (Exp_Type, Loc),
Name => Relocate_Node (Exp)));
- Set_Is_Renaming_Of_Object (Def_Id, False);
-
-- Avoid generating a variable-sized temporary, by generating the
-- reference just for the function call. The transformation could be
-- refined to apply only when the array component is constrained by a
@@ -11845,8 +12192,7 @@ package body Exp_Util is
-- and view swaps, the parent type is taken from the formal
-- parameter of the subprogram being called.
- if Nkind (Context) in
- N_Function_Call | N_Procedure_Call_Statement
+ if Nkind (Context) in N_Subprogram_Call
and then No (Type_Map.Get (Entity (Name (Context))))
then
New_Ref :=
@@ -12288,8 +12634,7 @@ package body Exp_Util is
if Is_Ignored_Ghost_Entity (Typ) then
null;
- elsif ((Is_Access_Type (Typ)
- and then not Is_Access_Subprogram_Type (Typ)
+ elsif ((Is_Access_Object_Type (Typ)
and then Needs_Finalization
(Available_View (Designated_Type (Typ))))
or else (Is_Type (Typ) and then Needs_Finalization (Typ)))
@@ -13443,88 +13788,6 @@ package body Exp_Util is
end if;
end Small_Integer_Type_For;
- --------------------------
- -- Target_Has_Fixed_Ops --
- --------------------------
-
- Integer_Sized_Small : Ureal;
- -- Set to 2.0 ** -(Integer'Size - 1) the first time that this function is
- -- called (we don't want to compute it more than once).
-
- Long_Integer_Sized_Small : Ureal;
- -- Set to 2.0 ** -(Long_Integer'Size - 1) the first time that this function
- -- is called (we don't want to compute it more than once)
-
- First_Time_For_THFO : Boolean := True;
- -- Set to False after first call (if Fractional_Fixed_Ops_On_Target)
-
- function Target_Has_Fixed_Ops
- (Left_Typ : Entity_Id;
- Right_Typ : Entity_Id;
- Result_Typ : Entity_Id) return Boolean
- is
- function Is_Fractional_Type (Typ : Entity_Id) return Boolean;
- -- Return True if the given type is a fixed-point type with a small
- -- value equal to 2 ** (-(T'Object_Size - 1)) and whose values have
- -- an absolute value less than 1.0. This is currently limited to
- -- fixed-point types that map to Integer or Long_Integer.
-
- ------------------------
- -- Is_Fractional_Type --
- ------------------------
-
- function Is_Fractional_Type (Typ : Entity_Id) return Boolean is
- begin
- if Esize (Typ) = Standard_Integer_Size then
- return Small_Value (Typ) = Integer_Sized_Small;
-
- elsif Esize (Typ) = Standard_Long_Integer_Size then
- return Small_Value (Typ) = Long_Integer_Sized_Small;
-
- else
- return False;
- end if;
- end Is_Fractional_Type;
-
- -- Start of processing for Target_Has_Fixed_Ops
-
- begin
- -- Return False if Fractional_Fixed_Ops_On_Target is false
-
- if not Fractional_Fixed_Ops_On_Target then
- return False;
- end if;
-
- -- Here the target has Fractional_Fixed_Ops, if first time, compute
- -- standard constants used by Is_Fractional_Type.
-
- if First_Time_For_THFO then
- First_Time_For_THFO := False;
-
- Integer_Sized_Small :=
- UR_From_Components
- (Num => Uint_1,
- Den => UI_From_Int (Standard_Integer_Size - 1),
- Rbase => 2);
-
- Long_Integer_Sized_Small :=
- UR_From_Components
- (Num => Uint_1,
- Den => UI_From_Int (Standard_Long_Integer_Size - 1),
- Rbase => 2);
- end if;
-
- -- Return True if target supports fixed-by-fixed multiply/divide for
- -- fractional fixed-point types (see Is_Fractional_Type) and the operand
- -- and result types are equivalent fractional types.
-
- return Is_Fractional_Type (Base_Type (Left_Typ))
- and then Is_Fractional_Type (Base_Type (Right_Typ))
- and then Is_Fractional_Type (Base_Type (Result_Typ))
- and then Esize (Left_Typ) = Esize (Right_Typ)
- and then Esize (Left_Typ) = Esize (Result_Typ);
- end Target_Has_Fixed_Ops;
-
-------------------
-- Type_Map_Hash --
-------------------
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 37eb86f..96d3894 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -293,23 +293,29 @@ package Exp_Util is
-- type is frozen.
function Build_DIC_Call
- (Loc : Source_Ptr;
- Obj_Id : Entity_Id;
- Typ : Entity_Id) return Node_Id;
- -- Build a call to the DIC procedure of type Typ with Obj_Id as the actual
+ (Loc : Source_Ptr;
+ Obj_Name : Node_Id;
+ Typ : Entity_Id) return Node_Id;
+ -- Build a call to the DIC procedure for Typ with Obj_Name as the actual
-- parameter.
procedure Build_DIC_Procedure_Body
- (Typ : Entity_Id;
- For_Freeze : Boolean := False);
+ (Typ : Entity_Id;
+ Partial_DIC : Boolean := False);
-- Create the body of the procedure which verifies the assertion expression
- -- of pragma Default_Initial_Condition at run time. Flag For_Freeze should
- -- be set when the body is constructed as part of the freezing actions for
- -- Typ.
-
- procedure Build_DIC_Procedure_Declaration (Typ : Entity_Id);
+ -- of pragma Default_Initial_Condition at run time. Partial_DIC indicates
+ -- that a partial DIC-checking procedure body should be built, for checking
+ -- a DIC associated with the type's partial view, and which will be called
+ -- by the main DIC procedure.
+
+ procedure Build_DIC_Procedure_Declaration
+ (Typ : Entity_Id;
+ Partial_DIC : Boolean := False);
-- Create the declaration of the procedure which verifies the assertion
- -- expression of pragma Default_Initial_Condition at run time.
+ -- expression of pragma Default_Initial_Condition at run time. Partial_DIC
+ -- indicates that a partial DIC-checking procedure should be declared,
+ -- for checking a DIC associated with the type's partial view, and which
+ -- will be called by the main DIC procedure.
procedure Build_Invariant_Procedure_Body
(Typ : Entity_Id;
@@ -750,11 +756,6 @@ package Exp_Util is
-- Return a suitable standard integer type containing at least S bits and
-- of the signedness given by Uns.
- function Is_All_Null_Statements (L : List_Id) return Boolean;
- -- Return True if all the items of the list are N_Null_Statement nodes.
- -- False otherwise. True for an empty list. It is an error to call this
- -- routine with No_List as the argument.
-
function Is_Displacement_Of_Object_Or_Function_Result
(Obj_Id : Entity_Id) return Boolean;
-- Determine whether Obj_Id is a source entity that has been initialized by
@@ -864,11 +865,6 @@ package Exp_Util is
-- list. If Warn is True, a warning will be output at the start of N
-- indicating the deletion of the code.
- function Known_Non_Negative (Opnd : Node_Id) return Boolean;
- -- Given a node for a subexpression, determines if it represents a value
- -- that cannot possibly be negative, and if so returns True. A value of
- -- False means that it is not known if the value is positive or negative.
-
function Make_Invariant_Call (Expr : Node_Id) return Node_Id;
-- Generate a call to the Invariant_Procedure associated with the type of
-- expression Expr. Expr is passed as an actual parameter in the call.
@@ -949,11 +945,6 @@ package Exp_Util is
-- consist of constants, when the object has a nontrivial initialization
-- or is controlled.
- function Non_Limited_Designated_Type (T : Entity_Id) return Entity_Id;
- -- An anonymous access type may designate a limited view. Check whether
- -- non-limited view is available during expansion, to examine components
- -- or other characteristics of the full type.
-
function OK_To_Do_Constant_Replacement (E : Entity_Id) return Boolean;
-- This function is used when testing whether or not to replace a reference
-- to entity E by a known constant value. Such replacement must be done
@@ -1172,15 +1163,6 @@ package Exp_Util is
-- Return the smallest standard integer type containing at least S bits and
-- of the signedness given by Uns.
- function Target_Has_Fixed_Ops
- (Left_Typ : Entity_Id;
- Right_Typ : Entity_Id;
- Result_Typ : Entity_Id) return Boolean;
- -- Returns True if and only if the target machine has direct support
- -- for fixed-by-fixed multiplications and divisions for the given
- -- operand and result types. This is called in package Exp_Fixd to
- -- determine whether to expand such operations.
-
function Type_May_Have_Bit_Aligned_Components
(Typ : Entity_Id) return Boolean;
-- Determines if Typ is a composite type that has within it (looking down
diff --git a/gcc/ada/expect.c b/gcc/ada/expect.c
index 718886d..30c5b8e 100644
--- a/gcc/ada/expect.c
+++ b/gcc/ada/expect.c
@@ -39,6 +39,7 @@
#include "system.h"
#endif
+#include "adaint.h"
#include <sys/types.h>
#ifdef __MINGW32__
@@ -78,7 +79,6 @@
#include <process.h>
#include <signal.h>
#include <io.h>
-#include "adaint.h"
#include "mingw32.h"
int
@@ -360,7 +360,11 @@ __gnat_pipe (int *fd)
int
__gnat_expect_fork (void)
{
- return fork ();
+ int pid = fork();
+ if (pid == 0) {
+ __gnat_in_child_after_fork = 1;
+ }
+ return pid;
}
void
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index f3abba1..8dc8a22 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -182,12 +182,6 @@ package body Freeze is
-- the designated type. Otherwise freezing the access type does not freeze
-- the designated type.
- function Is_Uninitialized_Aggregate (N : Node_Id) return Boolean;
- -- Determine whether an array aggregate used in an object declaration
- -- is uninitialized, when the aggregate is declared with a box and
- -- the component type has no default value. Such an aggregate can be
- -- optimized away and prevent the copying of uninitialized data.
-
procedure Process_Default_Expressions
(E : Entity_Id;
After : in out Node_Id);
@@ -727,12 +721,6 @@ package body Freeze is
if Present (Init)
and then not Is_Limited_View (Typ)
then
- if Is_Uninitialized_Aggregate (Init) then
- Init := Empty;
- Set_No_Initialization (Decl);
- return;
- end if;
-
-- Capture initialization value at point of declaration, and make
-- explicit assignment legal, because object may be a constant.
@@ -2007,7 +1995,7 @@ package body Freeze is
| N_Task_Body
| N_Body_Stub
and then
- List_Containing (After) = List_Containing (Parent (E))
+ In_Same_List (After, Parent (E))
then
Error_Msg_Sloc := Sloc (Next (After));
Error_Msg_NE
@@ -2606,13 +2594,6 @@ package body Freeze is
and then not GNATprove_Mode
then
Set_Has_Own_Invariants (Arr);
-
- -- The array type is an implementation base type. Propagate the
- -- same property to the first subtype.
-
- if Is_Itype (Arr) then
- Set_Has_Own_Invariants (First_Subtype (Arr));
- end if;
end if;
-- Warn for pragma Pack overriding foreign convention
@@ -5661,7 +5642,7 @@ package body Freeze is
Has_Rep_Pragma (E, Name_Atomic_Components)
then
Error_Msg_N
- ("stand alone atomic constant must be " &
+ ("standalone atomic constant must be " &
"imported (RM C.6(13))", E);
elsif Has_Rep_Pragma (E, Name_Volatile)
@@ -5669,7 +5650,7 @@ package body Freeze is
Has_Rep_Pragma (E, Name_Volatile_Components)
then
Error_Msg_N
- ("stand alone volatile constant must be " &
+ ("standalone volatile constant must be " &
"imported (RM C.6(13))", E);
end if;
end if;
@@ -6358,35 +6339,6 @@ package body Freeze is
if Is_Fixed_Point_Type (E) then
Freeze_Fixed_Point_Type (E);
- -- Some error checks required for ordinary fixed-point type. Defer
- -- these till the freeze-point since we need the small and range
- -- values. We only do these checks for base types
-
- if Is_Ordinary_Fixed_Point_Type (E) and then Is_Base_Type (E) then
- if Small_Value (E) < Ureal_2_M_80 then
- Error_Msg_Name_1 := Name_Small;
- Error_Msg_N
- ("`&''%` too small, minimum allowed is 2.0'*'*(-80)", E);
-
- elsif Small_Value (E) > Ureal_2_80 then
- Error_Msg_Name_1 := Name_Small;
- Error_Msg_N
- ("`&''%` too large, maximum allowed is 2.0'*'*80", E);
- end if;
-
- if Expr_Value_R (Type_Low_Bound (E)) < Ureal_M_10_36 then
- Error_Msg_Name_1 := Name_First;
- Error_Msg_N
- ("`&''%` too small, minimum allowed is -10.0'*'*36", E);
- end if;
-
- if Expr_Value_R (Type_High_Bound (E)) > Ureal_10_36 then
- Error_Msg_Name_1 := Name_Last;
- Error_Msg_N
- ("`&''%` too large, maximum allowed is 10.0'*'*36", E);
- end if;
- end if;
-
elsif Is_Enumeration_Type (E) then
Freeze_Enumeration_Type (E);
@@ -6403,8 +6355,7 @@ package body Freeze is
-- to subprogram and to internal types generated for 'Access
-- references.
- elsif Is_Access_Type (E)
- and then not Is_Access_Subprogram_Type (E)
+ elsif Is_Access_Object_Type (E)
and then Ekind (E) /= E_Access_Attribute_Type
then
-- If a pragma Default_Storage_Pool applies, and this type has no
@@ -7978,7 +7929,16 @@ package body Freeze is
-- Check that a type referenced by an entity can be frozen
if Is_Entity_Name (Node) and then Present (Entity (Node)) then
- Check_And_Freeze_Type (Etype (Entity (Node)));
+ -- The entity itself may be a type, as in a membership test
+ -- or an attribute reference. Freezing its own type would be
+ -- incomplete if the entity is derived or an extension.
+
+ if Is_Type (Entity (Node)) then
+ Check_And_Freeze_Type (Entity (Node));
+
+ else
+ Check_And_Freeze_Type (Etype (Entity (Node)));
+ end if;
-- Check that the enclosing record type can be frozen
@@ -8134,6 +8094,12 @@ package body Freeze is
-- Returns size of type with given bounds. Also leaves these
-- bounds set as the current bounds of the Typ.
+ function Larger (A, B : Ureal) return Boolean;
+ -- Returns true if A > B with a margin of Typ'Small
+
+ function Smaller (A, B : Ureal) return Boolean;
+ -- Returns true if A < B with a margin of Typ'Small
+
-----------
-- Fsize --
-----------
@@ -8145,6 +8111,24 @@ package body Freeze is
return Minimum_Size (Typ);
end Fsize;
+ ------------
+ -- Larger --
+ ------------
+
+ function Larger (A, B : Ureal) return Boolean is
+ begin
+ return A > B and then A - Small > B;
+ end Larger;
+
+ -------------
+ -- Smaller --
+ -------------
+
+ function Smaller (A, B : Ureal) return Boolean is
+ begin
+ return A < B and then A + Small < B;
+ end Smaller;
+
-- Start of processing for Freeze_Fixed_Point_Type
begin
@@ -8166,7 +8150,7 @@ package body Freeze is
if Present (Atype) then
Set_Esize (Typ, Esize (Atype));
else
- Set_Esize (Typ, Esize (Base_Type (Typ)));
+ Set_Esize (Typ, Esize (Btyp));
end if;
end if;
@@ -8446,6 +8430,111 @@ package body Freeze is
Set_Realval (Hi, Actual_Hi);
end Fudge;
+ -- Enforce some limitations for ordinary fixed-point types. They come
+ -- from an exact algorithm used to implement Text_IO.Fixed_IO and the
+ -- Fore, Image and Value attributes. The requirement on the Small is
+ -- to lie in the range 2**(-(Siz - 1)) .. 2**(Siz - 1) for a type of
+ -- Siz bits (Siz=32,64,128) and the requirement on the bounds is to
+ -- be smaller in magnitude than 10.0**N * 2**(Siz - 1), where N is
+ -- given by the formula N = floor ((Siz - 1) * log 2 / log 10).
+
+ -- If the bounds of a 32-bit type are too large, force 64-bit type
+
+ if Actual_Size <= 32
+ and then Small <= Ureal_2_31
+ and then (Smaller (Expr_Value_R (Lo), Ureal_M_2_10_18)
+ or else Larger (Expr_Value_R (Hi), Ureal_2_10_18))
+ then
+ Actual_Size := 33;
+ end if;
+
+ -- If the bounds of a 64-bit type are too large, force 128-bit type
+
+ if System_Max_Integer_Size = 128
+ and then Actual_Size <= 64
+ and then Small <= Ureal_2_63
+ and then (Smaller (Expr_Value_R (Lo), Ureal_M_9_10_36)
+ or else Larger (Expr_Value_R (Hi), Ureal_9_10_36))
+ then
+ Actual_Size := 65;
+ end if;
+
+ -- Give error messages for first subtypes and not base types, as the
+ -- bounds of base types are always maximum for their size, see below.
+
+ if System_Max_Integer_Size < 128 and then Typ /= Btyp then
+
+ -- See the 128-bit case below for the reason why we cannot test
+ -- against the 2**(-63) .. 2**63 range. This quirk should have
+ -- been kludged around as in the 128-bit case below, but it was
+ -- not and we end up with a ludicrous range as a result???
+
+ if Small < Ureal_2_M_80 then
+ Error_Msg_Name_1 := Name_Small;
+ Error_Msg_N
+ ("`&''%` too small, minimum allowed is 2.0'*'*(-80)", Typ);
+
+ elsif Small > Ureal_2_80 then
+ Error_Msg_Name_1 := Name_Small;
+ Error_Msg_N
+ ("`&''%` too large, maximum allowed is 2.0'*'*80", Typ);
+ end if;
+
+ if Smaller (Expr_Value_R (Lo), Ureal_M_9_10_36) then
+ Error_Msg_Name_1 := Name_First;
+ Error_Msg_N
+ ("`&''%` too small, minimum allowed is -9.0E+36", Typ);
+ end if;
+
+ if Larger (Expr_Value_R (Hi), Ureal_9_10_36) then
+ Error_Msg_Name_1 := Name_Last;
+ Error_Msg_N
+ ("`&''%` too large, maximum allowed is 9.0E+36", Typ);
+ end if;
+
+ elsif System_Max_Integer_Size = 128 and then Typ /= Btyp then
+
+ -- ACATS c35902d tests a delta equal to 2**(-(Max_Mantissa + 1))
+ -- but we cannot really support anything smaller than Fine_Delta
+ -- because of the way we implement I/O for fixed point types???
+
+ if Small = Ureal_2_M_128 then
+ null;
+
+ elsif Small < Ureal_2_M_127 then
+ Error_Msg_Name_1 := Name_Small;
+ Error_Msg_N
+ ("`&''%` too small, minimum allowed is 2.0'*'*(-127)", Typ);
+
+ elsif Small > Ureal_2_127 then
+ Error_Msg_Name_1 := Name_Small;
+ Error_Msg_N
+ ("`&''%` too large, maximum allowed is 2.0'*'*127", Typ);
+ end if;
+
+ if Actual_Size > 64
+ and then (Norm_Num (Small) > Uint_2 ** 127
+ or else Norm_Den (Small) > Uint_2 ** 127)
+ and then Small /= Ureal_2_M_128
+ then
+ Error_Msg_Name_1 := Name_Small;
+ Error_Msg_N
+ ("`&''%` not the ratio of two 128-bit integers", Typ);
+ end if;
+
+ if Smaller (Expr_Value_R (Lo), Ureal_M_10_76) then
+ Error_Msg_Name_1 := Name_First;
+ Error_Msg_N
+ ("`&''%` too small, minimum allowed is -1.0E+76", Typ);
+ end if;
+
+ if Larger (Expr_Value_R (Hi), Ureal_10_76) then
+ Error_Msg_Name_1 := Name_Last;
+ Error_Msg_N
+ ("`&''%` too large, maximum allowed is 1.0E+76", Typ);
+ end if;
+ end if;
+
-- For the decimal case, none of this fudging is required, since there
-- are no end-point problems in the decimal case (the end-points are
-- always included).
@@ -8457,12 +8546,13 @@ package body Freeze is
-- At this stage, the actual size has been calculated and the proper
-- required bounds are stored in the low and high bounds.
- if Actual_Size > 64 then
+ if Actual_Size > System_Max_Integer_Size then
Error_Msg_Uint_1 := UI_From_Int (Actual_Size);
+ Error_Msg_Uint_2 := UI_From_Int (System_Max_Integer_Size);
Error_Msg_N
- ("size required (^) for type& too large, maximum allowed is 64",
+ ("size required (^) for type& too large, maximum allowed is ^",
Typ);
- Actual_Size := 64;
+ Actual_Size := System_Max_Integer_Size;
end if;
-- Check size against explicit given size
@@ -8488,8 +8578,10 @@ package body Freeze is
Actual_Size := 16;
elsif Actual_Size <= 32 then
Actual_Size := 32;
- else
+ elsif Actual_Size <= 64 then
Actual_Size := 64;
+ else
+ Actual_Size := 128;
end if;
Init_Esize (Typ, Actual_Size);
@@ -8500,7 +8592,7 @@ package body Freeze is
-- the full width of the allocated size in bits, to avoid junk range
-- checks on intermediate computations.
- if Base_Type (Typ) = Typ then
+ if Typ = Btyp then
Set_Realval (Lo, -(Small * (Uint_2 ** (Actual_Size - 1))));
Set_Realval (Hi, (Small * (Uint_2 ** (Actual_Size - 1) - 1)));
end if;
@@ -9133,10 +9225,12 @@ package body Freeze is
Check_Overriding_Indicator (E, Empty, Is_Primitive (E));
end if;
- if Modify_Tree_For_C
+ Retype := Get_Fullest_View (Etype (E));
+
+ if Transform_Function_Array
and then Nkind (Parent (E)) = N_Function_Specification
- and then Is_Array_Type (Etype (E))
- and then Is_Constrained (Etype (E))
+ and then Is_Array_Type (Retype)
+ and then Is_Constrained (Retype)
and then not Is_Unchecked_Conversion_Instance (E)
and then not Rewritten_For_C (E)
then
@@ -9144,40 +9238,6 @@ package body Freeze is
end if;
end Freeze_Subprogram;
- --------------------------------
- -- Is_Uninitialized_Aggregate --
- --------------------------------
-
- function Is_Uninitialized_Aggregate (N : Node_Id) return Boolean is
- Aggr : constant Node_Id := Original_Node (N);
- Typ : constant Entity_Id := Etype (Aggr);
-
- Comp : Node_Id;
- Comp_Type : Entity_Id;
- begin
- if Nkind (Aggr) /= N_Aggregate
- or else No (Typ)
- or else Ekind (Typ) /= E_Array_Type
- or else Present (Expressions (Aggr))
- or else No (Component_Associations (Aggr))
- then
- return False;
- else
- Comp_Type := Component_Type (Typ);
- Comp := First (Component_Associations (Aggr));
-
- if not Box_Present (Comp)
- or else Present (Next (Comp))
- then
- return False;
- end if;
-
- return Is_Scalar_Type (Comp_Type)
- and then No (Default_Aspect_Component_Value (Typ))
- and then No (Default_Aspect_Value (Comp_Type));
- end if;
- end Is_Uninitialized_Aggregate;
-
----------------------
-- Is_Fully_Defined --
----------------------
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 78fe602..d88c354 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -42,7 +42,7 @@ MV = mv
MKDIR = mkdir -p
RM = rm -f
RMDIR = rm -rf
-
+
# Extra flags to pass to recursive makes.
COMMON_ADAFLAGS= -gnatpg
@@ -146,6 +146,7 @@ endif
# Define the names for selecting Ada in LANGUAGES.
ada: gnat1$(exeext) gnatbind$(exeext)
+ada.serial = gnat1$(exeext)
# Tell GNU Make to ignore these, if they exist.
.PHONY: ada
@@ -667,10 +668,13 @@ ada/libgnat/s-excmac.adb: $(srcdir)/ada/libgnat/s-excmac__$(EH_MECHANISM).adb
# Needs to be built with CC=gcc
# Since the RTL should be built with the latest compiler, remove the
# stamp target in the parent directory whenever gnat1 is rebuilt
-gnat1$(exeext): $(TARGET_ADA_SRCS) $(GNAT1_OBJS) $(ADA_BACKEND) libcommon-target.a $(LIBDEPS)
+gnat1$(exeext): $(TARGET_ADA_SRCS) $(GNAT1_OBJS) $(ADA_BACKEND) libcommon-target.a \
+ $(LIBDEPS) $(ada.prev)
+ @$(call LINK_PROGRESS,$(INDEX.ada),start)
+$(GCC_LLINK) -o $@ $(GNAT1_OBJS) $(ADA_BACKEND) \
libcommon-target.a $(LIBS) $(SYSLIBS) $(BACKENDLIBS) $(CFLAGS)
$(RM) stamp-gnatlib2-rts stamp-tools
+ @$(call LINK_PROGRESS,$(INDEX.ada),end)
gnatbind$(exeext): ada/b_gnatb.o $(CONFIG_H) $(GNATBIND_OBJS) ggc-none.o libcommon-target.a $(LIBDEPS)
+$(GCC_LINK) -o $@ ada/b_gnatb.o $(GNATBIND_OBJS) ggc-none.o libcommon-target.a $(LIBS) $(SYSLIBS) $(CFLAGS)
@@ -810,7 +814,6 @@ doc/gnat_rm.pdf: ada/gnat_rm.texi $(gcc_docdir)/include/fdl.texi \
doc/gnat-style.pdf: ada/gnat-style.texi $(gcc_docdir)/include/fdl.texi
$(TEXI2PDF) -c -I $(abs_docdir)/include -o $@ $<
-
# Install hooks:
# gnat1 is installed elsewhere as part of $(COMPILERS).
@@ -904,7 +907,7 @@ ada.maintainer-clean:
-$(RM) ada/nmake.ads
-$(RM) ada/treeprs.ads
-$(RM) ada/snames.ads ada/snames.adb ada/snames.h
-
+
# Stage hooks:
# The main makefile has already created stage?/ada
@@ -1001,7 +1004,7 @@ $(check_acats_targets): check-acats%:
touch $$GCC_RUNTEST_PARALLELIZE_DIR/finished
.PHONY: check-acats $(check_acats_targets)
-
+
# Compiling object files from source files.
# Ada language specific files.
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 6177d75..836fcbe 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -110,7 +110,7 @@ NO_INLINE_ADAFLAGS = -fno-inline
NO_OMIT_ADAFLAGS = -fno-omit-frame-pointer
NO_SIBLING_ADAFLAGS = -fno-optimize-sibling-calls
NO_REORDER_ADAFLAGS = -fno-toplevel-reorder
-GNATLIBFLAGS = -W -Wall -gnatpg -nostdinc
+GNATLIBFLAGS = -W -Wall -gnatg -nostdinc
GNATLIBCFLAGS = -g -O2
# Pretend that _Unwind_GetIPInfo is available for the target by default. This
# should be autodetected during the configuration of libada and passed down to
@@ -216,7 +216,7 @@ endif
ifneq ($(xmake_file),)
include $(xmake_file)
endif
-
+
# Now figure out from those variables how to compile and link.
all.indirect: Makefile ../gnat1$(exeext)
@@ -311,7 +311,7 @@ Makefile: ../config.status $(srcdir)/ada/gcc-interface/Makefile.in $(srcdir)/ada
# This tells GNU make version 3 not to export all the variables
# defined in this file into the environment.
.NOEXPORT:
-
+
# Lists of files for various purposes.
GNATLINK_OBJS = gnatlink.o \
@@ -338,7 +338,7 @@ GNATMAKE_OBJS = a-except.o ali.o ali-util.o aspects.o s-casuti.o alloc.o \
# picks up the right files. For a given target this must be coherent
# with MULTILIB_DIRNAMES defined in gcc/config/target/t-*.
-ifeq ($(strip $(filter-out %x86_64, $(target_cpu))),)
+ifeq ($(strip $(filter-out x86_64, $(target_cpu))),)
ifeq ($(strip $(MULTISUBDIR)),/32)
target_cpu:=i686
else
@@ -348,6 +348,11 @@ ifeq ($(strip $(filter-out %x86_64, $(target_cpu))),)
endif
endif
+# The SuSE PowerPC64/Linux compiler is actually a 32-bit PowerPC compiler
+ifeq ($(strip $(filter-out powerpc64 suse linux%, $(target_cpu) $(target_vendor) $(target_os))),)
+ target_cpu:=powerpc
+endif
+
# Configuration of host tools
# Under linux, host tools need to be linked with -ldl
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 4e6dc84..5ea1b16 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -261,7 +261,7 @@ typedef struct {
} intrin_binding_t;
static bool intrin_profiles_compatible_p (intrin_binding_t *);
-
+
/* Given GNAT_ENTITY, a GNAT defining identifier node, which denotes some Ada
entity, return the equivalent GCC tree for that entity (a ..._DECL node)
and associate the ..._DECL node with the input GNAT defining identifier.
@@ -667,21 +667,24 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If we have a constant that we are not defining, get the expression it
was defined to represent. This is necessary to avoid generating dumb
- elaboration code in simple cases, but we may throw it away later if it
+ elaboration code in simple cases, and we may throw it away later if it
is not a constant. But do not do it for dispatch tables because they
are only referenced indirectly and we need to have a consistent view
of the exported and of the imported declarations of the tables from
external units for them to be properly merged in LTO mode. Moreover
- simply do not retrieve the expression it if it is an allocator since
+ simply do not retrieve the expression if it is an allocator because
the designated type might still be dummy at this point. Note that we
invoke gnat_to_gnu_external and not gnat_to_gnu because the expression
may contain N_Expression_With_Actions nodes and thus declarations of
- objects from other units that we need to discard. */
+ objects from other units that we need to discard. Note also that we
+ need to do it even if we are only annotating types, so as to be able
+ to validate representation clauses using constants. */
if (!definition
&& !No_Initialization (gnat_decl)
&& !Is_Dispatch_Table_Entity (gnat_entity)
&& Present (gnat_temp = Expression (gnat_decl))
- && Nkind (gnat_temp) != N_Allocator)
+ && Nkind (gnat_temp) != N_Allocator
+ && (Is_Elementary_Type (Etype (gnat_entity)) || !type_annotate_only))
gnu_expr = gnat_to_gnu_external (gnat_temp);
/* ... fall through ... */
@@ -1740,24 +1743,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnu_type = make_signed_type (esize);
- /* Try to decode the scale factor and to save it for the fixed-point
- types debug hook. */
-
- /* There are various ways to describe the scale factor, however there
- are cases where back-end internals cannot hold it. In such cases,
- we output invalid scale factor for such cases (i.e. the 0/0
- rational constant) but we expect GNAT to output GNAT encodings,
- then. Thus, keep this in sync with
- Exp_Dbug.Is_Handled_Scale_Factor. */
-
/* When encoded as 1/2**N or 1/10**N, describe the scale factor as a
binary or decimal scale: it is easier to read for humans. */
if (UI_Eq (Numerator (gnat_small_value), Uint_1)
&& (Rbase (gnat_small_value) == 2
|| Rbase (gnat_small_value) == 10))
{
- /* Given RM restrictions on 'Small values, we assume here that
- the denominator fits in an int. */
tree base
= build_int_cst (integer_type_node, Rbase (gnat_small_value));
tree exponent
@@ -1770,29 +1761,19 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
base, exponent));
}
- /* Default to arbitrary scale factors descriptions. */
+ /* Use the arbitrary scale factor description. Note that we support
+ a Small_Value whose magnitude is larger than 64-bit even on 32-bit
+ platforms, so we unconditionally use a (dummy) 128-bit type. */
else
{
- const Uint num = Norm_Num (gnat_small_value);
- const Uint den = Norm_Den (gnat_small_value);
+ const Uint gnat_num = Norm_Num (gnat_small_value);
+ const Uint gnat_den = Norm_Den (gnat_small_value);
+ tree gnu_small_type = make_unsigned_type (128);
+ tree gnu_num = UI_To_gnu (gnat_num, gnu_small_type);
+ tree gnu_den = UI_To_gnu (gnat_den, gnu_small_type);
- if (UI_Is_In_Int_Range (num) && UI_Is_In_Int_Range (den))
- {
- tree gnu_num
- = build_int_cst (integer_type_node,
- UI_To_Int (Norm_Num (gnat_small_value)));
- tree gnu_den
- = build_int_cst (integer_type_node,
- UI_To_Int (Norm_Den (gnat_small_value)));
- scale_factor = build2 (RDIV_EXPR, integer_type_node,
- gnu_num, gnu_den);
- }
- else
- /* If compiler internals cannot represent arbitrary scale
- factors, output an invalid scale factor so that debugger
- don't try to handle them but so that we still have a type
- in the output. Note that GNAT */
- scale_factor = integer_zero_node;
+ scale_factor
+ = build2 (RDIV_EXPR, gnu_small_type, gnu_num, gnu_den);
}
TYPE_FIXED_POINT_P (gnu_type) = 1;
@@ -6575,7 +6556,7 @@ update_n_elem (tree n_elem, tree min, tree max)
return n_elem;
}
-
+
/* Given GNAT_ENTITY, elaborate all expressions that are required to
be elaborated at the point of its definition, but do nothing else. */
@@ -6632,7 +6613,7 @@ elaborate_entity (Entity_Id gnat_entity)
}
}
-
+
/* Prepend to ATTR_LIST an entry for an attribute with provided TYPE,
NAME, ARGS and ERROR_POINT. */
@@ -6747,7 +6728,7 @@ prepend_attributes (struct attrib **attr_list, Entity_Id gnat_entity)
if (Nkind (gnat_temp) == N_Pragma)
prepend_one_attribute_pragma (attr_list, gnat_temp);
}
-
+
/* Given a GNAT tree GNAT_EXPR, for an expression which is a value within a
type definition (either a bound or a discriminant value) for GNAT_ENTITY,
return the GCC tree to use for that expression. S is the suffix to use
@@ -6954,7 +6935,7 @@ elaborate_reference (tree ref, Entity_Id gnat_entity, bool definition,
struct er_data er = { gnat_entity, definition, 0 };
return gnat_rewrite_reference (ref, elaborate_reference_1, &er, init);
}
-
+
/* Given a GNU tree and a GNAT list of choices, generate an expression to test
the value passed against the list of choices. */
@@ -7051,7 +7032,7 @@ choices_to_gnu (tree gnu_operand, Node_Id gnat_choices)
return gnu_result;
}
-
+
/* Adjust PACKED setting as passed to gnat_to_gnu_field for a field of
type FIELD_TYPE to be placed in RECORD_TYPE. Return the result. */
@@ -7464,7 +7445,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
return gnu_field;
}
-
+
/* Return true if at least one member of COMPONENT_LIST needs strict
alignment. */
@@ -8430,7 +8411,7 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
return (gnu_rep_list && !p_gnu_rep_list) || variants_have_rep;
}
-
+
/* Given GNU_SIZE, a GCC tree representing a size, return a Uint to be
placed into an Esize, Component_Bit_Offset, or Component_Size value
in the GNAT tree. */
@@ -8798,7 +8779,7 @@ annotate_rep (Entity_Id gnat_entity, tree gnu_type)
}
}
}
-
+
/* Scan all fields in GNU_TYPE and return a TREE_LIST where TREE_PURPOSE is
the FIELD_DECL and TREE_VALUE a TREE_VEC containing the byte position, the
value to be placed into DECL_OFFSET_ALIGN and the bit position. The list
@@ -8956,7 +8937,7 @@ build_variant_list (tree gnu_qual_union_type, Node_Id gnat_variant_part,
return gnu_list;
}
-
+
/* If SIZE has overflowed, return the maximum valid size, which is the upper
bound of the signed sizetype in bits, rounded down to ALIGN. Otherwise
return SIZE unmodified. */
@@ -9100,7 +9081,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
return size;
}
-
+
/* Similarly, but both validate and process a value of RM size. This routine
is only called for types. */
@@ -9177,7 +9158,7 @@ set_rm_size (Uint uint_size, tree gnu_type, Entity_Id gnat_entity)
&& !TYPE_FAT_POINTER_P (gnu_type))
SET_TYPE_ADA_SIZE (gnu_type, size);
}
-
+
/* ALIGNMENT is a Uint giving the alignment specified for GNAT_ENTITY,
a type or object whose present alignment is ALIGN. If this alignment is
valid, return it. Otherwise, give an error and return ALIGN. */
@@ -9270,7 +9251,7 @@ validate_alignment (Uint alignment, Entity_Id gnat_entity, unsigned int align)
return align;
}
-
+
/* Promote the alignment of GNU_TYPE corresponding to GNAT_ENTITY. Return
a positive value on success or zero on failure. */
@@ -9317,7 +9298,7 @@ promote_object_alignment (tree gnu_type, Entity_Id gnat_entity)
return align;
}
-
+
/* Verify that TYPE is something we can implement atomically. If not, issue
an error for GNAT_ENTITY. COMPONENT_P is true if we are being called to
process a component type. */
@@ -9385,7 +9366,7 @@ check_ok_for_atomic_type (tree type, Entity_Id gnat_entity, bool component_p)
post_error_ne ("atomic access to & cannot be guaranteed",
gnat_error_point, gnat_entity);
}
-
+
/* Helper for the intrin compatibility checks family. Evaluate whether
two types are definitely incompatible. */
@@ -9540,7 +9521,7 @@ intrin_profiles_compatible_p (intrin_binding_t * inb)
return return_compatible_p && arglists_compatible_p;
}
-
+
/* Return a FIELD_DECL node modeled on OLD_FIELD. FIELD_TYPE is its type
and RECORD_TYPE is the type of the parent. If SIZE is nonzero, it is the
specified size for this field. POS_LIST is a position list describing
@@ -10154,7 +10135,7 @@ associate_original_type_to_packed_array (tree gnu_type, Entity_Id gnat_entity)
return NULL_TREE;
}
}
-
+
/* Given a type T, a FIELD_DECL F, and a replacement value R, return an
equivalent type with adjusted size expressions where all occurrences
of references to F in a PLACEHOLDER_EXPR have been replaced by R.
@@ -10315,7 +10296,7 @@ substitute_in_type (tree t, tree f, tree r)
return t;
}
}
-
+
/* Return the RM size of GNU_TYPE. This is the actual number of bits
needed to represent the object. */
@@ -10344,7 +10325,7 @@ rm_size (tree gnu_type)
/* For other types, this is just the size. */
return TYPE_SIZE (gnu_type);
}
-
+
/* Return the name to be used for GNAT_ENTITY. If a type, create a
fully-qualified name, possibly with type information encoding.
Otherwise, return the name. */
@@ -10372,7 +10353,7 @@ create_concat_name (Entity_Id gnat_entity, const char *suffix)
{
const Entity_Kind kind = Ekind (gnat_entity);
const bool has_suffix = (suffix != NULL);
- String_Template temp = {1, has_suffix ? strlen (suffix) : 0};
+ String_Template temp = {1, has_suffix ? (int) strlen (suffix) : 0};
String_Pointer sp = {suffix, &temp};
Get_External_Name (gnat_entity, has_suffix, sp);
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 355178e..328e5f3 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -325,7 +325,7 @@ extern int double_scalar_alignment;
/* True if floating-point arithmetics may use wider intermediate results. */
extern bool fp_arith_may_widen;
-
+
/* Data structures used to represent attributes. */
enum attrib_type
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 781868e..d0867e0 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -559,7 +559,7 @@ gnat_printable_name (tree decl, int verbosity)
__gnat_decode (coded_name, ada_name, 0);
- if (verbosity == 2 && !DECL_IS_BUILTIN (decl))
+ if (verbosity == 2 && !DECL_IS_UNDECLARED_BUILTIN (decl))
{
Set_Identifier_Casing (ada_name, DECL_SOURCE_FILE (decl));
return ggc_strdup (Name_Buffer);
@@ -628,16 +628,6 @@ gnat_get_fixed_point_type_info (const_tree type,
/* We expect here only a finite set of pattern. See fixed-point types
handling in gnat_to_gnu_entity. */
- /* Put invalid values when compiler internals cannot represent the scale
- factor. */
- if (scale_factor == integer_zero_node)
- {
- info->scale_factor_kind = fixed_point_scale_factor_arbitrary;
- info->scale_factor.arbitrary.numerator = 0;
- info->scale_factor.arbitrary.denominator = 0;
- return true;
- }
-
if (TREE_CODE (scale_factor) == RDIV_EXPR)
{
tree num = TREE_OPERAND (scale_factor, 0);
@@ -677,8 +667,8 @@ gnat_get_fixed_point_type_info (const_tree type,
&& TREE_CODE (den) == INTEGER_CST);
info->scale_factor_kind = fixed_point_scale_factor_arbitrary;
- info->scale_factor.arbitrary.numerator = tree_to_uhwi (num);
- info->scale_factor.arbitrary.denominator = tree_to_shwi (den);
+ info->scale_factor.arbitrary.numerator = num;
+ info->scale_factor.arbitrary.denominator = den;
return true;
}
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 059e1a4..4ab26d3 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -255,7 +255,7 @@ static bool maybe_make_gnu_thunk (Entity_Id gnat_thunk, tree gnu_thunk);
of configurations. */
static const char *extract_encoding (const char *) ATTRIBUTE_UNUSED;
static const char *decode_name (const char *) ATTRIBUTE_UNUSED;
-
+
/* This makes gigi's file_info_ptr visible in this translation unit,
so that Sloc_to_locus can look it up when deciding whether to map
decls to instances. */
@@ -735,7 +735,7 @@ gigi (Node_Id gnat_root,
/* We cannot track the location of errors past this point. */
Current_Error_Node = Empty;
}
-
+
/* Return a subprogram decl corresponding to __gnat_rcheck_xx for the given
CHECK if KIND is EXCEPTION_SIMPLE, or else to __gnat_rcheck_xx_ext. */
@@ -779,7 +779,7 @@ build_raise_check (int check, enum exception_info_kind kind)
return result;
}
-
+
/* Return a positive value if an lvalue is required for GNAT_NODE, which is
an N_Attribute_Reference. */
@@ -970,6 +970,10 @@ lvalue_for_aggregate_p (Node_Id gnat_node, tree gnu_type)
/* Even if the parameter is by copy, prefer an lvalue. */
return true;
+ case N_Simple_Return_Statement:
+ /* Likewise for a return value. */
+ return true;
+
case N_Indexed_Component:
case N_Selected_Component:
/* If an elementary component is used, take it from the constant. */
@@ -1333,7 +1337,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
return gnu_result;
}
-
+
/* Subroutine of gnat_to_gnu to process gnat_node, an N_Pragma. Return
any statements we generate. */
@@ -1599,7 +1603,7 @@ Pragma_to_gnu (Node_Id gnat_node)
return gnu_result;
}
-
+
/* Check the inline status of nested function FNDECL wrt its parent function.
If a non-inline nested function is referenced from an inline external
@@ -1645,7 +1649,7 @@ check_inlining_for_nested_subprog (tree fndecl)
DECL_UNINLINABLE (parent_decl) = 1;
}
}
-
+
/* Return an expression for the length of TYPE, an integral type, computed in
RESULT_TYPE, another integral type.
@@ -2590,7 +2594,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
*gnu_result_type_p = gnu_result_type;
return gnu_result;
}
-
+
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Case_Statement,
to a GCC tree, which is returned. */
@@ -2715,7 +2719,7 @@ Case_Statement_to_gnu (Node_Id gnat_node)
return gnu_result;
}
-
+
/* Return true if we are in the body of a loop. */
static inline bool
@@ -2814,38 +2818,6 @@ can_equal_max_val_p (tree val, tree type, bool reverse)
return can_equal_min_or_max_val_p (val, type, !reverse);
}
-/* Return true if VAL1 can be lower than VAL2. */
-
-static bool
-can_be_lower_p (tree val1, tree val2)
-{
- if (TREE_CODE (val1) == NOP_EXPR)
- {
- tree type = TREE_TYPE (TREE_OPERAND (val1, 0));
- if (can_be_lower_p (TYPE_MAX_VALUE (type), TYPE_MIN_VALUE (type)))
- return true;
-
- val1 = TYPE_MIN_VALUE (type);
- }
-
- if (TREE_CODE (val1) != INTEGER_CST)
- return true;
-
- if (TREE_CODE (val2) == NOP_EXPR)
- {
- tree type = TREE_TYPE (TREE_OPERAND (val2, 0));
- if (can_be_lower_p (TYPE_MAX_VALUE (type), TYPE_MIN_VALUE (type)))
- return true;
-
- val2 = TYPE_MAX_VALUE (type);
- }
-
- if (TREE_CODE (val2) != INTEGER_CST)
- return true;
-
- return tree_int_cst_lt (val1, val2);
-}
-
/* Replace EXPR1 and EXPR2 by invariant expressions if possible. Return
true if both expressions have been replaced and false otherwise. */
@@ -3126,19 +3098,16 @@ Regular_Loop_to_gnu (Node_Id gnat_node, tree *gnu_cond_expr_p)
}
/* If we use the BOTTOM_COND, we can turn the test into an inequality
- test but we may have to add ENTRY_COND to protect the empty loop. */
+ test but we have to add ENTRY_COND to protect the empty loop. */
if (LOOP_STMT_BOTTOM_COND_P (gnu_loop_stmt))
{
test_code = NE_EXPR;
- if (can_be_lower_p (gnu_high, gnu_low))
- {
- gnu_cond_expr
- = build3 (COND_EXPR, void_type_node,
- build_binary_op (LE_EXPR, boolean_type_node,
- gnu_low, gnu_high),
- NULL_TREE, alloc_stmt_list ());
- set_expr_location_from_node (gnu_cond_expr, gnat_iter_scheme);
- }
+ gnu_cond_expr
+ = build3 (COND_EXPR, void_type_node,
+ build_binary_op (LE_EXPR, boolean_type_node,
+ gnu_low, gnu_high),
+ NULL_TREE, alloc_stmt_list ());
+ set_expr_location_from_node (gnu_cond_expr, gnat_iter_scheme);
}
/* Open a new nesting level that will surround the loop to declare the
@@ -3363,7 +3332,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
return gnu_result;
}
-
+
/* This page implements a form of Named Return Value optimization modeled
on the C++ optimization of the same name. The main difference is that
we disregard any semantical considerations when applying it here, the
@@ -3855,7 +3824,7 @@ build_return_expr (tree ret_obj, tree ret_val)
return build1 (RETURN_EXPR, void_type_node, result_expr);
}
-
+
/* Subroutine of gnat_to_gnu to process gnat_node, an N_Subprogram_Body. We
don't return anything. */
@@ -4179,7 +4148,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
else
rest_of_subprog_body_compilation (gnu_subprog_decl);
}
-
+
/* The type of an atomic access. */
typedef enum { NOT_ATOMIC, SIMPLE_ATOMIC, OUTER_ATOMIC } atomic_acces_t;
@@ -4369,8 +4338,8 @@ not_atomic:
*type = NOT_ATOMIC;
*sync = false;
}
-
- /* Return true if GNAT_NODE requires simple atomic access and, if so, set SYNC
+
+/* Return true if GNAT_NODE requires simple atomic access and, if so, set SYNC
according to the associated synchronization setting. */
static inline bool
@@ -4548,7 +4517,11 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
and the return type has variable size, because the gimplifier
doesn't handle these cases.
- 4. There is no target and we have misaligned In Out or Out parameters
+ 4. There is a target which is a bit-field and the function returns an
+ unconstrained record type with default discriminant, because the
+ return may copy more data than the bit-field can contain.
+
+ 5. There is no target and we have misaligned In Out or Out parameters
passed by reference, because we need to preserve the return value
before copying back the parameters. However, in this case, we'll
defer creating the temporary, see below.
@@ -4571,7 +4544,11 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
|| (TREE_CODE (TREE_TYPE (gnu_target)) == ARRAY_TYPE
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_target)))
== INTEGER_CST))
- && TREE_CODE (TYPE_SIZE (gnu_result_type)) != INTEGER_CST)))
+ && TREE_CODE (TYPE_SIZE (gnu_result_type)) != INTEGER_CST)
+ || (gnu_target
+ && TREE_CODE (gnu_target) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (gnu_target, 1))
+ && type_is_padding_self_referential (gnu_result_type))))
{
gnu_retval = create_temporary ("R", gnu_result_type);
DECL_RETURN_VALUE_P (gnu_retval) = 1;
@@ -5240,7 +5217,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
return gnu_result;
}
-
+
/* Subroutine of gnat_to_gnu to translate gnat_node, an
N_Handled_Sequence_Of_Statements, to a GCC tree, which is returned. */
@@ -5479,7 +5456,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
return gnu_result;
}
-
+
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Exception_Handler,
to a GCC tree, which is returned. This is the variant for front-end sjlj
exception handling. */
@@ -5548,7 +5525,7 @@ Exception_Handler_to_gnu_fe_sjlj (Node_Id gnat_node)
return build3 (COND_EXPR, void_type_node, gnu_choice, gnu_body, NULL_TREE);
}
-
+
/* Return true if no statement in GNAT_LIST can alter the control flow. */
static bool
@@ -5755,7 +5732,7 @@ Exception_Handler_to_gnu_gcc (Node_Id gnat_node)
return
build2 (CATCH_EXPR, void_type_node, gnu_etypes_list, end_stmt_group ());
}
-
+
/* Subroutine of gnat_to_gnu to generate code for an N_Compilation unit. */
static void
@@ -5885,7 +5862,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
/* Force the processing for all nodes that remain in the queue. */
process_deferred_decl_context (true);
}
-
+
/* Mark COND, a boolean expression, as predicating a call to a noreturn
function, i.e. predict that it is very likely false, and return it.
@@ -6099,7 +6076,7 @@ Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
return gnu_result;
}
-
+
/* Return true if GNAT_NODE is on the LHS of an assignment or an actual
parameter of a call. */
@@ -7085,6 +7062,8 @@ gnat_to_gnu (Node_Id gnat_node)
if (TREE_CODE (gnu_lhs) == INTEGER_CST && ignore_lhs_overflow)
TREE_OVERFLOW (gnu_lhs) = TREE_OVERFLOW (gnu_old_lhs);
gnu_rhs = convert (gnu_type, gnu_rhs);
+ if (gnu_max_shift)
+ gnu_max_shift = convert (gnu_type, gnu_max_shift);
}
/* For signed integer addition, subtraction and multiplication, do an
@@ -7192,9 +7171,7 @@ gnat_to_gnu (Node_Id gnat_node)
const Entity_Id gnat_desig_type
= Designated_Type (Underlying_Type (Etype (gnat_node)));
- /* The flag is effectively only set on the base types. */
- ignore_init_type
- = Has_Constrained_Partial_View (Base_Type (gnat_desig_type));
+ ignore_init_type = Has_Constrained_Partial_View (gnat_desig_type);
gnu_init = gnat_to_gnu (Expression (gnat_temp));
gnu_init = maybe_unconstrained_array (gnu_init);
@@ -8284,8 +8261,10 @@ gnat_to_gnu (Node_Id gnat_node)
/* Remove padding only if the inner object is of self-referential
size: in that case it must be an object of unconstrained type
with a default discriminant and we want to avoid copying too
- much data. */
- if (type_is_padding_self_referential (TREE_TYPE (gnu_result)))
+ much data. But do not remove it if it is already too small. */
+ if (type_is_padding_self_referential (TREE_TYPE (gnu_result))
+ && !(TREE_CODE (gnu_result) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (gnu_result, 1))))
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
gnu_result);
}
@@ -8364,7 +8343,7 @@ gnat_to_gnu_external (Node_Id gnat_node)
return gnu_result;
}
-
+
/* Return true if the statement list STMT_LIST is empty. */
static bool
@@ -8408,7 +8387,7 @@ insert_code_for (Node_Id gnat_node)
save_gnu_tree (gnat_node, NULL_TREE, true);
}
-
+
/* Start a new statement group chained to the previous group. */
void
@@ -8680,7 +8659,7 @@ build_stmt_group (List_Id gnat_list, bool binding_p)
return end_stmt_group ();
}
-
+
/* Generate GIMPLE in place for the expression at *EXPR_P. */
int
@@ -8929,7 +8908,7 @@ gnat_gimplify_stmt (tree *stmt_p)
gcc_unreachable ();
}
}
-
+
/* Force a reference to each of the entities in GNAT_PACKAGE recursively.
This routine is exclusively called in type_annotate mode, to compute DDA
@@ -9055,7 +9034,7 @@ elaborate_all_entities (Node_Id gnat_node)
if (Nkind (Unit (gnat_node)) == N_Package_Body)
elaborate_all_entities (Library_Unit (gnat_node));
}
-
+
/* Do the processing of GNAT_NODE, an N_Freeze_Entity. */
static void
@@ -9195,7 +9174,7 @@ process_freeze_entity (Node_Id gnat_node)
used_types_insert (TREE_TYPE (gnu_new));
}
}
-
+
/* Elaborate decls in the lists GNAT_DECLS and GNAT_DECLS2, if present.
We make two passes, one to elaborate anything other than bodies (but
we declare a function if there was no spec). The second pass
@@ -9330,7 +9309,7 @@ process_decls (List_Id gnat_decls, List_Id gnat_decls2,
add_stmt (gnat_to_gnu (gnat_decl));
}
}
-
+
/* Make a unary operation of kind CODE using build_unary_op, but guard
the operation by an overflow check. CODE can be one of NEGATE_EXPR
or ABS_EXPR. GNU_TYPE is the type desired for the result. Usually
@@ -9394,6 +9373,11 @@ build_binary_op_trapv (enum tree_code code, tree gnu_type, tree left,
/* If no operand is a constant, we use the generic implementation. */
if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (rhs) != INTEGER_CST)
{
+ /* First convert the operands to the result type like build_binary_op.
+ This is where the bias is made explicit for biased types. */
+ lhs = convert (gnu_type, lhs);
+ rhs = convert (gnu_type, rhs);
+
/* Never inline a 64-bit mult for a 32-bit target, it's way too long. */
if (code == MULT_EXPR && precision == 64 && BITS_PER_WORD < 64)
{
@@ -9573,7 +9557,7 @@ emit_check (tree gnu_cond, tree gnu_expr, int reason, Node_Id gnat_node)
: build_int_cst (TREE_TYPE (gnu_expr), 0)),
gnu_expr);
}
-
+
/* Return an expression that converts GNU_EXPR to GNAT_TYPE, doing overflow
checks if OVERFLOW_P is true. If TRUNCATE_P is true, do a fp-to-integer
conversion with truncation, otherwise round. GNAT_NODE is the GNAT node
@@ -9758,7 +9742,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflow_p,
return convert (gnu_type, gnu_result);
}
-
+
/* Return true if GNU_EXPR can be directly addressed. This is the case
unless it is an expression involving computation or if it involves a
reference to a bitfield or to an object not sufficiently aligned for
@@ -9936,7 +9920,7 @@ addressable_p (tree gnu_expr, tree gnu_type)
return false;
}
}
-
+
/* Do the processing for the declaration of a GNAT_ENTITY, a type or subtype.
If a Freeze node exists for the entity, delay the bulk of the processing.
Otherwise make a GCC type for GNAT_ENTITY and set up the correspondence. */
@@ -10020,7 +10004,7 @@ process_type (Entity_Id gnat_entity)
TREE_TYPE (gnu_new));
}
}
-
+
/* Subroutine of assoc_to_constructor: VALUES is a list of field associations,
some of which are from RECORD_TYPE. Return a CONSTRUCTOR consisting of the
associations that are from RECORD_TYPE. If we see an internal record, make
@@ -10174,7 +10158,7 @@ pos_to_constructor (Node_Id gnat_expr, tree gnu_array_type)
return gnat_build_constructor (gnu_array_type, gnu_expr_vec);
}
-
+
/* Process a N_Validate_Unchecked_Conversion node. */
static void
@@ -10233,7 +10217,7 @@ validate_unchecked_conversion (Node_Id gnat_node)
}
}
}
-
+
/* Convert SLOC into LOCUS. Return true if SLOC corresponds to a
source code location and false if it doesn't. If CLEAR_COLUMN is
true, set the column information to 0. If DECL is given and SLOC
@@ -10415,7 +10399,7 @@ set_end_locus_from_node (tree gnu_node, Node_Id gnat_node)
return false;
}
}
-
+
/* Return a colon-separated list of encodings contained in encoded Ada
name. */
@@ -10436,7 +10420,7 @@ decode_name (const char *name)
__gnat_decode (name, decoded, 0);
return decoded;
}
-
+
/* Post an error message. MSG is the error message, properly annotated.
NODE is the node at which to post the error and the node to use for the
'&' substitution. */
@@ -10746,8 +10730,11 @@ maybe_make_gnu_thunk (Entity_Id gnat_thunk, tree gnu_thunk)
tree gnu_target = gnat_to_gnu_entity (gnat_target, NULL_TREE, false);
- /* Thunk and target must have the same nesting level, if any. */
- gcc_assert (DECL_CONTEXT (gnu_thunk) == DECL_CONTEXT (gnu_target));
+ /* If the target is local, then thunk and target must have the same context
+ because cgraph_node::expand_thunk can only forward the static chain. */
+ if (DECL_STATIC_CHAIN (gnu_target)
+ && DECL_CONTEXT (gnu_thunk) != DECL_CONTEXT (gnu_target))
+ return false;
/* If the target returns by invisible reference and is external, apply the
same transformation as Subprogram_Body_to_gnu here. */
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index d50872f..494f60e 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -357,7 +357,7 @@ add_deferred_decl_context (tree decl, Entity_Id gnat_scope, int force_global);
computed. */
static void add_deferred_type_context (struct deferred_decl_context_node *n,
tree type);
-
+
/* Initialize data structures of the utils.c module. */
void
@@ -397,7 +397,7 @@ destroy_gnat_utils (void)
pad_type_hash_table->empty ();
pad_type_hash_table = NULL;
}
-
+
/* GNAT_ENTITY is a GNAT tree node for an entity. Associate GNU_DECL, a GCC
tree node, with GNAT_ENTITY. If GNU_DECL is not a ..._DECL node, abort.
If NO_CHECK is true, the latter check is suppressed.
@@ -438,7 +438,7 @@ present_gnu_tree (Entity_Id gnat_entity)
{
return PRESENT_GNU_TREE (gnat_entity);
}
-
+
/* Make a dummy type corresponding to GNAT_TYPE. */
tree
@@ -533,7 +533,7 @@ build_dummy_unc_pointer_types (Entity_Id gnat_desig_type, tree gnu_desig_type)
TYPE_REFERENCE_TO (gnu_desig_type) = gnu_fat_type;
TYPE_OBJECT_RECORD_TYPE (gnu_desig_type) = gnu_object_type;
}
-
+
/* Return true if we are in the global binding level. */
bool
@@ -663,7 +663,7 @@ gnat_zaplevel (void)
level->chain = free_binding_level;
free_binding_level = level;
}
-
+
/* Set the context of TYPE and its parallel types (if any) to CONTEXT. */
static void
@@ -935,7 +935,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
}
}
}
-
+
/* Create a record type that contains a SIZE bytes long field of TYPE with a
starting bit position so that it is aligned to ALIGN bits, and leaving at
least ROOM bytes free before the field. BASE_ALIGN is the alignment the
@@ -1772,7 +1772,7 @@ set_reverse_storage_order_on_pad_type (tree type)
TYPE_REVERSE_STORAGE_ORDER (type) = 1;
return canonicalize_pad_type (type);
}
-
+
/* Relate the alias sets of GNU_NEW_TYPE and GNU_OLD_TYPE according to OP.
If this is a multi-dimensional array type, do this recursively.
@@ -1847,7 +1847,7 @@ relate_alias_sets (tree gnu_new_type, tree gnu_old_type, enum alias_set_op op)
record_component_aliases (gnu_new_type);
}
-
+
/* Record TYPE as a builtin type for Ada. NAME is the name of the type.
ARTIFICIAL_P is true if the type was generated by the compiler. */
@@ -1863,7 +1863,7 @@ record_builtin_type (const char *name, tree type, bool artificial_p)
if (debug_hooks->type_decl)
debug_hooks->type_decl (type_decl, false);
}
-
+
/* Finish constructing the character type CHAR_TYPE.
In Ada character types are enumeration types and, as a consequence, are
@@ -2558,7 +2558,7 @@ split_plus (tree in, tree *pvar)
else
return bitsize_zero_node;
}
-
+
/* Return a copy of TYPE but safe to modify in any way. */
tree
@@ -2595,7 +2595,7 @@ copy_type (tree type)
return new_type;
}
-
+
/* Return a subtype of sizetype with range MIN to MAX and whose
TYPE_INDEX_TYPE is INDEX. GNAT_NODE is used for the position
of the associated TYPE_DECL. */
@@ -2634,8 +2634,8 @@ create_range_type (tree type, tree min, tree max)
return range_type;
}
-
- /* Return an extra subtype of TYPE with range MIN to MAX. */
+
+/* Return an extra subtype of TYPE with range MIN to MAX. */
tree
create_extra_subtype (tree type, tree min, tree max)
@@ -2652,7 +2652,7 @@ create_extra_subtype (tree type, tree min, tree max)
return subtype;
}
-
+
/* Return a TYPE_DECL node suitable for the TYPE_STUB_DECL field of TYPE.
NAME gives the name of the type to be used in the declaration. */
@@ -2718,7 +2718,7 @@ create_type_decl (tree name, tree type, bool artificial_p, bool debug_info_p,
return type_decl;
}
-
+
/* Return a VAR_DECL or CONST_DECL node.
NAME gives the name of the variable. ASM_NAME is its assembler name
@@ -2886,7 +2886,7 @@ create_var_decl (tree name, tree asm_name, tree type, tree init,
return var_decl;
}
-
+
/* Return true if TYPE, an aggregate type, contains (or is) an array.
If SELF_REFERENTIAL is true, then an additional requirement on the
array is that it be self-referential. */
@@ -3097,7 +3097,7 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
return field_decl;
}
-
+
/* Return a PARM_DECL node with NAME and TYPE. */
tree
@@ -3131,7 +3131,7 @@ create_param_decl (tree name, tree type)
DECL_ARG_TYPE (param_decl) = type;
return param_decl;
}
-
+
/* Process the attributes in ATTR_LIST for NODE, which is either a DECL or
a TYPE. If IN_PLACE is true, the tree pointed to by NODE should not be
changed. GNAT_NODE is used for the position of error messages. */
@@ -3420,7 +3420,7 @@ create_label_decl (tree name, Node_Id gnat_node)
return label_decl;
}
-
+
/* Return a FUNCTION_DECL node. NAME is the name of the subprogram, ASM_NAME
its assembler name, TYPE its type (a FUNCTION_TYPE or METHOD_TYPE node),
PARAM_DECL_LIST the list of its parameters (a list of PARM_DECL nodes
@@ -3558,7 +3558,7 @@ finish_subprog_decl (tree decl, tree asm_name, tree type)
DECL_NAME (decl) = main_identifier_node;
}
}
-
+
/* Set up the framework for generating code for SUBPROG_DECL, a subprogram
body. This routine needs to be invoked before processing the declarations
appearing in the subprogram. */
@@ -3830,7 +3830,7 @@ fntype_same_flags_p (const_tree t, tree cico_list, bool return_unconstrained_p,
&& TYPE_RETURN_BY_DIRECT_REF_P (t) == return_by_direct_ref_p
&& TREE_ADDRESSABLE (t) == return_by_invisi_ref_p;
}
-
+
/* EXP is an expression for the size of an object. If this size contains
discriminant references, replace them with the maximum (if MAX_P) or
minimum (if !MAX_P) possible value of the discriminant.
@@ -4042,7 +4042,7 @@ max_size (tree exp, bool max_p)
gcc_unreachable ();
}
-
+
/* Build a template of type TEMPLATE_TYPE from the array bounds of ARRAY_TYPE.
EXPR is an expression that we can use to locate any PLACEHOLDER_EXPRs.
Return a constructor for the template. */
@@ -4108,7 +4108,7 @@ build_template (tree template_type, tree array_type, tree expr)
return gnat_build_constructor (template_type, template_elts);
}
-
+
/* Return true if TYPE is suitable for the element type of a vector. */
static bool
@@ -4198,7 +4198,7 @@ build_vector_type_for_array (tree array_type, tree attribute)
TYPE_REPRESENTATIVE_ARRAY (vector_type) = array_type;
return vector_type;
}
-
+
/* Build a type to be used to represent an aliased object whose nominal type
is an unconstrained array. This consists of a RECORD_TYPE containing a
field of TEMPLATE_TYPE and a field of OBJECT_TYPE, which is an ARRAY_TYPE.
@@ -4248,7 +4248,7 @@ build_unc_object_type_from_ptr (tree thin_fat_ptr_type, tree object_type,
return
build_unc_object_type (template_type, object_type, name, debug_info_p);
}
-
+
/* Update anything previously pointing to OLD_TYPE to point to NEW_TYPE.
In the normal case this is just two adjustments, but we have more to
do if NEW_TYPE is an UNCONSTRAINED_ARRAY_TYPE. */
@@ -4379,7 +4379,7 @@ update_pointer_to (tree old_type, tree new_type)
TYPE_REFERENCE_TO (old_type) = NULL_TREE;
}
}
-
+
/* Convert EXPR, a pointer to a constrained array, into a pointer to an
unconstrained one. This involves making or finding a template. */
@@ -4483,7 +4483,7 @@ convert_to_fat_pointer (tree type, tree expr)
CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (TYPE_FIELDS (type)), template_addr);
return gnat_build_constructor (type, v);
}
-
+
/* Create an expression whose value is that of EXPR,
converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable
@@ -4930,10 +4930,6 @@ convert (tree type, tree expr)
convert (TREE_TYPE (type),
TYPE_MIN_VALUE (type))));
- /* ... fall through ... */
-
- case ENUMERAL_TYPE:
- case BOOLEAN_TYPE:
/* If we are converting an additive expression to an integer type
with lower precision, be wary of the optimization that can be
applied by convert_to_integer. There are 2 problematic cases:
@@ -4945,8 +4941,7 @@ convert (tree type, tree expr)
intermediate conversion that changes the sign could
be inserted and thus introduce an artificial overflow
at compile time when the placeholder is substituted. */
- if (code == INTEGER_TYPE
- && ecode == INTEGER_TYPE
+ if (ecode == INTEGER_TYPE
&& TYPE_PRECISION (type) < TYPE_PRECISION (etype)
&& (TREE_CODE (expr) == PLUS_EXPR || TREE_CODE (expr) == MINUS_EXPR))
{
@@ -4955,11 +4950,18 @@ convert (tree type, tree expr)
if ((TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
&& TYPE_BIASED_REPRESENTATION_P (TREE_TYPE (op0)))
|| CONTAINS_PLACEHOLDER_P (expr))
- return build1 (NOP_EXPR, type, expr);
+ return fold_convert (type, expr);
}
+ /* ... fall through ... */
+
+ case ENUMERAL_TYPE:
return fold (convert_to_integer (type, expr));
+ case BOOLEAN_TYPE:
+ /* Do not use convert_to_integer with boolean types. */
+ return fold_convert_loc (EXPR_LOCATION (expr), type, expr);
+
case POINTER_TYPE:
case REFERENCE_TYPE:
/* If converting between two thin pointers, adjust if needed to account
@@ -5170,7 +5172,7 @@ convert_to_index_type (tree expr)
return convert (sizetype, expr);
}
-
+
/* Remove all conversions that are done in EXP. This includes converting
from a padded type or to a justified modular type. If TRUE_ADDRESS
is true, always return the address of the containing object even if
@@ -5205,7 +5207,7 @@ remove_conversions (tree exp, bool true_address)
return exp;
}
-
+
/* If EXP's type is an UNCONSTRAINED_ARRAY_TYPE, return an expression that
refers to the underlying array. If it has TYPE_CONTAINS_TEMPLATE_P,
likewise return an expression pointing to the underlying array. */
@@ -5293,7 +5295,7 @@ maybe_unconstrained_array (tree exp)
return exp;
}
-
+
/* Return true if EXPR is an expression that can be folded as an operand
of a VIEW_CONVERT_EXPR. See ada-tree.h for a complete rationale. */
@@ -5687,7 +5689,7 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
return expr;
}
-
+
/* Return the appropriate GCC tree code for the specified GNAT_TYPE,
the latter being a record type as predicated by Is_Record_Type. */
@@ -5837,7 +5839,7 @@ can_materialize_object_renaming_p (Node_Id expr)
{
expr = Original_Node (expr);
- switch Nkind (expr)
+ switch (Nkind (expr))
{
case N_Identifier:
case N_Expanded_Name:
@@ -5901,7 +5903,7 @@ gnat_write_global_declarations (void)
struct varpool_node *node;
char *label;
- ASM_FORMAT_PRIVATE_NAME (label, first_global_object_name, 0);
+ ASM_FORMAT_PRIVATE_NAME (label, first_global_object_name, ULONG_MAX);
dummy_global
= build_decl (BUILTINS_LOCATION, VAR_DECL, get_identifier (label),
void_type_node);
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index c8a2d7c..316033b 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -73,7 +73,7 @@ get_base_type (tree type)
return type;
}
-
+
/* EXP is a GCC tree representing an address. See if we can find how strictly
the object at this address is aligned and, if so, return the alignment of
the object in bits. Otherwise return 0. */
@@ -203,7 +203,7 @@ known_alignment (tree exp)
return this_alignment;
}
-
+
/* We have a comparison or assignment operation on two types, T1 and T2, which
are either both array types or both record types. T1 is assumed to be for
the left hand side operand, and T2 for the right hand side. Return the
@@ -271,7 +271,7 @@ find_common_type (tree t1, tree t2)
could cause a bad self-referential reference. */
return NULL_TREE;
}
-
+
/* Return an expression tree representing an equality comparison of A1 and A2,
two objects of type ARRAY_TYPE. The result should be of type RESULT_TYPE.
@@ -533,7 +533,7 @@ compare_fat_pointers (location_t loc, tree result_type, tree p1, tree p2)
build_binary_op (TRUTH_ORIF_EXPR, result_type,
p1_array_is_null, same_bounds));
}
-
+
/* Compute the result of applying OP_CODE to LHS and RHS, where both are of
type TYPE. We know that TYPE is a modular type with a nonbinary
modulus. */
@@ -629,7 +629,7 @@ nonbinary_modular_operation (enum tree_code op_code, tree type, tree lhs,
return convert (type, result);
}
-
+
/* This page contains routines that implement the Ada semantics with regard
to atomic objects. They are fully piggybacked on the middle-end support
for atomic loads and stores.
@@ -828,7 +828,7 @@ build_load_modify_store (tree dest, tree src, Node_Id gnat_node)
/* Something went wrong earlier if we have not found the atomic load. */
gcc_unreachable ();
}
-
+
/* Make a binary operation of kind OP_CODE. RESULT_TYPE is the type
desired for the result. Usually the operation is to be performed
in that type. For INIT_EXPR and MODIFY_EXPR, RESULT_TYPE must be
@@ -1323,7 +1323,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
return result;
}
-
+
/* Similar, but for unary operations. */
tree
@@ -1683,7 +1683,7 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
return result;
}
-
+
/* Similar, but for COND_EXPR. */
tree
@@ -1758,7 +1758,7 @@ build_compound_expr (tree result_type, tree stmt_operand, tree expr_operand)
return result;
}
-
+
/* Conveniently construct a function call expression. FNDECL names the
function to be called, N is the number of arguments, and the "..."
parameters are the argument expressions. Unlike build_call_expr
@@ -1776,7 +1776,7 @@ build_call_n_expr (tree fndecl, int n, ...)
va_end (ap);
return fn;
}
-
+
/* Build a goto to LABEL for a raise, with an optional call to Local_Raise.
MSG gives the exception's identity for the call to Local_Raise, if any. */
@@ -1924,7 +1924,7 @@ build_call_raise_range (int msg, Node_Id gnat_node, char kind,
convert (integer_type_node, first),
convert (integer_type_node, last));
}
-
+
/* qsort comparer for the bit positions of two constructor elements
for record components. */
@@ -1987,7 +1987,7 @@ gnat_build_constructor (tree type, vec<constructor_elt, va_gc> *v)
TREE_READONLY (result) = TYPE_READONLY (type) || read_only || allconstant;
return result;
}
-
+
/* Return a COMPONENT_REF to access FIELD in RECORD, or NULL_TREE if the field
is not found in the record. Don't fold the result if NO_FOLD is true. */
@@ -2113,7 +2113,7 @@ build_component_ref (tree record, tree field, bool no_fold)
build_call_raise (CE_Discriminant_Check_Failed, Empty,
N_Raise_Constraint_Error));
}
-
+
/* Helper for build_call_alloc_dealloc, with arguments to be interpreted
identically. Process the case where a GNAT_PROC to call is provided. */
@@ -2326,7 +2326,7 @@ build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, tree gnu_type,
return maybe_wrap_malloc (gnu_size, gnu_type, gnat_node);
}
}
-
+
/* Build a GCC tree that corresponds to allocating an object of TYPE whose
initial value is INIT, if INIT is nonzero. Convert the expression to
RESULT_TYPE, which must be some pointer type, and return the result.
@@ -2457,7 +2457,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
return storage;
}
-
+
/* Indicate that we need to take the address of T and that it therefore
should not be allocated in a register. Return true if successful. */
@@ -2505,7 +2505,7 @@ gnat_mark_addressable (tree t)
return true;
}
}
-
+
/* Return true if EXP is a stable expression for the purpose of the functions
below and, therefore, can be returned unmodified by them. We accept things
that are actual constants or that have already been handled. */
diff --git a/gcc/ada/get_targ.adb b/gcc/ada/get_targ.adb
index 8b35b1c..881c06c 100644
--- a/gcc/ada/get_targ.adb
+++ b/gcc/ada/get_targ.adb
@@ -278,22 +278,6 @@ package body Get_Targ is
return null;
end Get_Back_End_Config_File;
- ----------------------
- -- Digits_From_Size --
- ----------------------
-
- function Digits_From_Size (Size : Pos) return Pos is
- begin
- case Size is
- when 32 => return 6;
- when 48 => return 9;
- when 64 => return 15;
- when 96 => return 18;
- when 128 => return 18;
- when others => raise Program_Error;
- end case;
- end Digits_From_Size;
-
-----------------------------
-- Get_Max_Unaligned_Field --
-----------------------------
@@ -314,20 +298,4 @@ package body Get_Targ is
Enumerate_Modes (Call_Back);
end Register_Back_End_Types;
- ---------------------
- -- Width_From_Size --
- ---------------------
-
- function Width_From_Size (Size : Pos) return Pos is
- begin
- case Size is
- when 8 => return 4;
- when 16 => return 6;
- when 32 => return 11;
- when 64 => return 21;
- when 128 => return 40;
- when others => raise Program_Error;
- end case;
- end Width_From_Size;
-
end Get_Targ;
diff --git a/gcc/ada/get_targ.ads b/gcc/ada/get_targ.ads
index 676e117..5315292 100644
--- a/gcc/ada/get_targ.ads
+++ b/gcc/ada/get_targ.ads
@@ -115,10 +115,6 @@ package Get_Targ is
-- Returns the maximum supported size in bits for a field that is
-- not aligned on a storage unit boundary.
- function Width_From_Size (Size : Pos) return Pos;
- function Digits_From_Size (Size : Pos) return Pos;
- -- Calculate values for 'Width or 'Digits from 'Size
-
type C_String is array (0 .. 255) of aliased Character;
pragma Convention (C, C_String);
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index 180a140..0318194 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -167,6 +167,7 @@ procedure Gnat1drv is
if Debug_Flag_Dot_U then
Modify_Tree_For_C := True;
+ Transform_Function_Array := True;
end if;
-- -gnatd_A disables generation of ALI files
@@ -179,6 +180,7 @@ procedure Gnat1drv is
if Generate_C_Code then
Modify_Tree_For_C := True;
+ Transform_Function_Array := True;
Unnest_Subprogram_Mode := True;
Building_Static_Dispatch_Tables := False;
Minimize_Expression_With_Actions := True;
@@ -246,9 +248,10 @@ procedure Gnat1drv is
-- this way when we are doing CodePeer tests on existing test suites
-- that may have -gnateg set, to avoid the need for special casing.
- Modify_Tree_For_C := False;
- Generate_C_Code := False;
- Unnest_Subprogram_Mode := False;
+ Modify_Tree_For_C := False;
+ Transform_Function_Array := False;
+ Generate_C_Code := False;
+ Unnest_Subprogram_Mode := False;
-- Turn off inlining, confuses CodePeer output and gains nothing
@@ -454,9 +457,10 @@ procedure Gnat1drv is
-- this way when we are doing GNATprove tests on existing test suites
-- that may have -gnateg set, to avoid the need for special casing.
- Modify_Tree_For_C := False;
- Generate_C_Code := False;
- Unnest_Subprogram_Mode := False;
+ Modify_Tree_For_C := False;
+ Transform_Function_Array := False;
+ Generate_C_Code := False;
+ Unnest_Subprogram_Mode := False;
-- Turn off inlining, which would confuse formal verification output
-- and gain nothing.
@@ -809,8 +813,6 @@ procedure Gnat1drv is
Ttypes.Standard_Long_Long_Long_Integer_Size :=
Ttypes.Standard_Long_Long_Integer_Size;
- Ttypes.Standard_Long_Long_Long_Integer_Width :=
- Ttypes.Standard_Long_Long_Integer_Width;
Ttypes.System_Max_Integer_Size :=
Ttypes.Standard_Long_Long_Integer_Size;
Ttypes.System_Max_Binary_Modulus_Power :=
@@ -1018,15 +1020,6 @@ procedure Gnat1drv is
-- by the backend where possible).
Sem_Ch13.Validate_Address_Clauses;
-
- -- Validate independence pragmas (again using values annotated by the
- -- back end for component layout where possible) but only for non-GCC
- -- back ends, as this is done a priori for GCC back ends.
- -- ??? We use to test for AAMP_On_Target which is now gone, consider
- --
- -- if AAMP_On_Target then
- -- Sem_Ch13.Validate_Independence;
- -- end if;
end Post_Compilation_Validation_Checks;
-----------------------------------
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index e1a5568..02e8219 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT Reference Manual , Sep 29, 2020
+GNAT Reference Manual , Dec 11, 2020
AdaCore
@@ -394,6 +394,7 @@ Implementation Defined Attributes
* Attribute From_Any::
* Attribute Has_Access_Values::
* Attribute Has_Discriminants::
+* Attribute Has_Tagged_Values::
* Attribute Img::
* Attribute Initialized::
* Attribute Integer_Value::
@@ -422,6 +423,8 @@ Implementation Defined Attributes
* Attribute Scalar_Storage_Order::
* Attribute Simple_Storage_Pool::
* Attribute Small::
+* Attribute Small_Denominator::
+* Attribute Small_Numerator::
* Attribute Storage_Unit::
* Attribute Stub_Type::
* Attribute System_Allocator_Alignment::
@@ -1806,15 +1809,16 @@ pragma Assertion_Policy (
ASSERTION_KIND ::= RM_ASSERTION_KIND | ID_ASSERTION_KIND
-RM_ASSERTION_KIND ::= Assert |
- Static_Predicate |
- Dynamic_Predicate |
- Pre |
- Pre'Class |
- Post |
- Post'Class |
- Type_Invariant |
- Type_Invariant'Class
+RM_ASSERTION_KIND ::= Assert |
+ Static_Predicate |
+ Dynamic_Predicate |
+ Pre |
+ Pre'Class |
+ Post |
+ Post'Class |
+ Type_Invariant |
+ Type_Invariant'Class |
+ Default_Initial_Condition
ID_ASSERTION_KIND ::= Assertions |
Assert_And_Cut |
@@ -1822,6 +1826,7 @@ ID_ASSERTION_KIND ::= Assertions |
Contract_Cases |
Debug |
Ghost |
+ Initial_Condition |
Invariant |
Invariant'Class |
Loop_Invariant |
@@ -1830,7 +1835,8 @@ ID_ASSERTION_KIND ::= Assertions |
Precondition |
Predicate |
Refined_Post |
- Statement_Assertions
+ Statement_Assertions |
+ Subprogram_Variant
POLICY_IDENTIFIER ::= Check | Disable | Ignore | Suppressible
@end example
@@ -6536,7 +6542,7 @@ See Ada 2012 Reference Manual for details.
Syntax:
@example
-pragma Profile (Ravenscar | Restricted | Rational |
+pragma Profile (Ravenscar | Restricted | Rational | Jorvik |
GNAT_Extended_Ravenscar | GNAT_Ravenscar_EDF );
@end example
@@ -6544,10 +6550,12 @@ This pragma is standard in Ada 2005, but is available in all earlier
versions of Ada as an implementation-defined pragma. This is a
configuration pragma that establishes a set of configuration pragmas
that depend on the argument. @code{Ravenscar} is standard in Ada 2005.
+@code{Jorvik} is standard in Ada 202x.
The other possibilities (@code{Restricted}, @code{Rational},
@code{GNAT_Extended_Ravenscar}, @code{GNAT_Ravenscar_EDF})
-are implementation-defined. The set of configuration pragmas
-is defined in the following sections.
+are implementation-defined. @code{GNAT_Extended_Ravenscar} is an alias for @code{Jorvik}.
+
+The set of configuration pragmas is defined in the following sections.
@itemize *
@@ -6647,7 +6655,7 @@ No rendezvous statements are allowed.
@end itemize
The Ravenscar profile also includes the following restrictions that specify
-that there are no semantic dependences on the corresponding predefined
+that there are no semantic dependencies on the corresponding predefined
packages:
@@ -6699,12 +6707,10 @@ automatically causes the use of a simplified,
more efficient version of the tasking run-time library.
@item
-Pragma Profile (GNAT_Extended_Ravenscar)
+Pragma Profile (Jorvik)
-This profile corresponds to a GNAT specific extension of the
-Ravenscar profile. The profile may change in the future although
-only in a compatible way: some restrictions may be removed or
-relaxed. It is defined as a variation of the Ravenscar profile.
+@code{Jorvik} is the new profile added to the Ada 202x draft standard,
+previously implemented under the name @code{GNAT_Extended_Ravenscar}.
The @code{No_Implicit_Heap_Allocations} restriction has been replaced
by @code{No_Implicit_Task_Allocations} and
@@ -6716,6 +6722,11 @@ The @code{Simple_Barriers} restriction has been replaced by
The @code{Max_Protected_Entries}, @code{Max_Entry_Queue_Length}, and
@code{No_Relative_Delay} restrictions have been removed.
+Details on the rationale for @code{Jorvik} and implications for use may be
+found in @cite{A New Ravenscar-Based Profile} by P. Rogers, J. Ruiz,
+T. Gingold and P. Bernardi, in @cite{Reliable Software Technologies -- Ada Europe 2017}, Springer-Verlag Lecture Notes in Computer Science,
+Number 10300.
+
@item
Pragma Profile (GNAT_Ravenscar_EDF)
@@ -8148,8 +8159,8 @@ package Math_Functions is
function Sqrt (Arg : Float) return Float;
pragma Test_Case (Name => "Test 1",
Mode => Nominal,
- Requires => Arg < 10000,
- Ensures => Sqrt'Result < 10);
+ Requires => Arg < 10000.0,
+ Ensures => Sqrt'Result < 10.0);
...
end Math_Functions;
@end example
@@ -9933,7 +9944,7 @@ This boolean aspect is equivalent to @ref{10b,,pragma Unmodified}.
This boolean aspect is equivalent to @ref{10c,,pragma Unreferenced}.
-When using the @code{-gnatX} switch, this aspect is also supported on formal
+When using the @code{-gnat2020} switch, this aspect is also supported on formal
parameters, which is in particular the only form possible for expression
functions.
@@ -10038,6 +10049,7 @@ consideration, you should minimize the use of these attributes.
* Attribute From_Any::
* Attribute Has_Access_Values::
* Attribute Has_Discriminants::
+* Attribute Has_Tagged_Values::
* Attribute Img::
* Attribute Initialized::
* Attribute Integer_Value::
@@ -10066,6 +10078,8 @@ consideration, you should minimize the use of these attributes.
* Attribute Scalar_Storage_Order::
* Attribute Simple_Storage_Pool::
* Attribute Small::
+* Attribute Small_Denominator::
+* Attribute Small_Numerator::
* Attribute Storage_Unit::
* Attribute Stub_Type::
* Attribute System_Allocator_Alignment::
@@ -10617,7 +10631,7 @@ The intended use of this attribute is in conjunction with generic
definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has access values.
-@node Attribute Has_Discriminants,Attribute Img,Attribute Has_Access_Values,Implementation Defined Attributes
+@node Attribute Has_Discriminants,Attribute Has_Tagged_Values,Attribute Has_Access_Values,Implementation Defined Attributes
@anchor{gnat_rm/implementation_defined_attributes attribute-has-discriminants}@anchor{183}
@section Attribute Has_Discriminants
@@ -10633,8 +10647,25 @@ otherwise. The intended use of this attribute is in conjunction with generic
definitions. If the attribute is applied to a generic private type, it
indicates whether or not the corresponding actual type has discriminants.
-@node Attribute Img,Attribute Initialized,Attribute Has_Discriminants,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-img}@anchor{184}
+@node Attribute Has_Tagged_Values,Attribute Img,Attribute Has_Discriminants,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-has-tagged-values}@anchor{184}
+@section Attribute Has_Tagged_Values
+
+
+@geindex Tagged values
+@geindex testing for
+
+@geindex Has_Tagged_Values
+
+The prefix of the @code{Has_Tagged_Values} attribute is a type. The result is a
+Boolean value which is True if the type is a composite type (array or record)
+that is either a tagged type or has a subcomponent that is tagged, and is False
+otherwise. The intended use of this attribute is in conjunction with generic
+definitions. If the attribute is applied to a generic private type, it
+indicates whether or not the corresponding actual type has access values.
+
+@node Attribute Img,Attribute Initialized,Attribute Has_Tagged_Values,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-img}@anchor{185}
@section Attribute Img
@@ -10664,7 +10695,7 @@ that returns the appropriate string when called. This means that
in an instantiation as a function parameter.
@node Attribute Initialized,Attribute Integer_Value,Attribute Img,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-initialized}@anchor{185}
+@anchor{gnat_rm/implementation_defined_attributes attribute-initialized}@anchor{186}
@section Attribute Initialized
@@ -10674,7 +10705,7 @@ For the syntax and semantics of this attribute, see the SPARK 2014 Reference
Manual, section 6.10.
@node Attribute Integer_Value,Attribute Invalid_Value,Attribute Initialized,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-integer-value}@anchor{186}
+@anchor{gnat_rm/implementation_defined_attributes attribute-integer-value}@anchor{187}
@section Attribute Integer_Value
@@ -10702,7 +10733,7 @@ This attribute is primarily intended for use in implementation of the
standard input-output functions for fixed-point values.
@node Attribute Invalid_Value,Attribute Iterable,Attribute Integer_Value,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-invalid-value}@anchor{187}
+@anchor{gnat_rm/implementation_defined_attributes attribute-invalid-value}@anchor{188}
@section Attribute Invalid_Value
@@ -10716,7 +10747,7 @@ including the ability to modify the value with the binder -Sxx flag and
relevant environment variables at run time.
@node Attribute Iterable,Attribute Large,Attribute Invalid_Value,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-iterable}@anchor{188}
+@anchor{gnat_rm/implementation_defined_attributes attribute-iterable}@anchor{189}
@section Attribute Iterable
@@ -10725,7 +10756,7 @@ relevant environment variables at run time.
Equivalent to Aspect Iterable.
@node Attribute Large,Attribute Library_Level,Attribute Iterable,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-large}@anchor{189}
+@anchor{gnat_rm/implementation_defined_attributes attribute-large}@anchor{18a}
@section Attribute Large
@@ -10738,7 +10769,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Library_Level,Attribute Lock_Free,Attribute Large,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-library-level}@anchor{18a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-library-level}@anchor{18b}
@section Attribute Library_Level
@@ -10764,7 +10795,7 @@ end Gen;
@end example
@node Attribute Lock_Free,Attribute Loop_Entry,Attribute Library_Level,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-lock-free}@anchor{18b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-lock-free}@anchor{18c}
@section Attribute Lock_Free
@@ -10774,7 +10805,7 @@ end Gen;
pragma @code{Lock_Free} applies to P.
@node Attribute Loop_Entry,Attribute Machine_Size,Attribute Lock_Free,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-loop-entry}@anchor{18c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-loop-entry}@anchor{18d}
@section Attribute Loop_Entry
@@ -10804,7 +10835,7 @@ entry. This copy is not performed if the loop is not entered, or if the
corresponding pragmas are ignored or disabled.
@node Attribute Machine_Size,Attribute Mantissa,Attribute Loop_Entry,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-machine-size}@anchor{18d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-machine-size}@anchor{18e}
@section Attribute Machine_Size
@@ -10814,7 +10845,7 @@ This attribute is identical to the @code{Object_Size} attribute. It is
provided for compatibility with the DEC Ada 83 attribute of this name.
@node Attribute Mantissa,Attribute Maximum_Alignment,Attribute Machine_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-mantissa}@anchor{18e}
+@anchor{gnat_rm/implementation_defined_attributes attribute-mantissa}@anchor{18f}
@section Attribute Mantissa
@@ -10827,7 +10858,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Maximum_Alignment,Attribute Max_Integer_Size,Attribute Mantissa,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-maximum-alignment}@anchor{18f}@anchor{gnat_rm/implementation_defined_attributes id2}@anchor{190}
+@anchor{gnat_rm/implementation_defined_attributes attribute-maximum-alignment}@anchor{190}@anchor{gnat_rm/implementation_defined_attributes id2}@anchor{191}
@section Attribute Maximum_Alignment
@@ -10843,7 +10874,7 @@ for an object, guaranteeing that it is properly aligned in all
cases.
@node Attribute Max_Integer_Size,Attribute Mechanism_Code,Attribute Maximum_Alignment,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-max-integer-size}@anchor{191}
+@anchor{gnat_rm/implementation_defined_attributes attribute-max-integer-size}@anchor{192}
@section Attribute Max_Integer_Size
@@ -10854,7 +10885,7 @@ prefix) provides the size of the largest supported integer type for
the target. The result is a static constant.
@node Attribute Mechanism_Code,Attribute Null_Parameter,Attribute Max_Integer_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-mechanism-code}@anchor{192}
+@anchor{gnat_rm/implementation_defined_attributes attribute-mechanism-code}@anchor{193}
@section Attribute Mechanism_Code
@@ -10885,7 +10916,7 @@ by reference
@end table
@node Attribute Null_Parameter,Attribute Object_Size,Attribute Mechanism_Code,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-null-parameter}@anchor{193}
+@anchor{gnat_rm/implementation_defined_attributes attribute-null-parameter}@anchor{194}
@section Attribute Null_Parameter
@@ -10910,7 +10941,7 @@ There is no way of indicating this without the @code{Null_Parameter}
attribute.
@node Attribute Object_Size,Attribute Old,Attribute Null_Parameter,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-object-size}@anchor{143}@anchor{gnat_rm/implementation_defined_attributes id3}@anchor{194}
+@anchor{gnat_rm/implementation_defined_attributes attribute-object-size}@anchor{143}@anchor{gnat_rm/implementation_defined_attributes id3}@anchor{195}
@section Attribute Object_Size
@@ -10980,7 +11011,7 @@ Similar additional checks are performed in other contexts requiring
statically matching subtypes.
@node Attribute Old,Attribute Passed_By_Reference,Attribute Object_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-old}@anchor{195}
+@anchor{gnat_rm/implementation_defined_attributes attribute-old}@anchor{196}
@section Attribute Old
@@ -10995,7 +11026,7 @@ definition are allowed under control of
implementation defined pragma @code{Unevaluated_Use_Of_Old}.
@node Attribute Passed_By_Reference,Attribute Pool_Address,Attribute Old,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-passed-by-reference}@anchor{196}
+@anchor{gnat_rm/implementation_defined_attributes attribute-passed-by-reference}@anchor{197}
@section Attribute Passed_By_Reference
@@ -11011,13 +11042,10 @@ passed by copy in calls. For scalar types, the result is always @code{False}
and is static. For non-scalar types, the result is nonstatic.
@node Attribute Pool_Address,Attribute Range_Length,Attribute Passed_By_Reference,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-pool-address}@anchor{197}
+@anchor{gnat_rm/implementation_defined_attributes attribute-pool-address}@anchor{198}
@section Attribute Pool_Address
-@geindex Parameters
-@geindex when passed by reference
-
@geindex Pool_Address
@code{X'Pool_Address} for any object @code{X} returns the address
@@ -11036,7 +11064,7 @@ For an object created by @code{new}, @code{Ptr.all'Pool_Address} is
what is passed to @code{Allocate} and returned from @code{Deallocate}.
@node Attribute Range_Length,Attribute Restriction_Set,Attribute Pool_Address,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-range-length}@anchor{198}
+@anchor{gnat_rm/implementation_defined_attributes attribute-range-length}@anchor{199}
@section Attribute Range_Length
@@ -11049,7 +11077,7 @@ applied to the index subtype of a one dimensional array always gives the
same result as @code{Length} applied to the array itself.
@node Attribute Restriction_Set,Attribute Result,Attribute Range_Length,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-restriction-set}@anchor{199}
+@anchor{gnat_rm/implementation_defined_attributes attribute-restriction-set}@anchor{19a}
@section Attribute Restriction_Set
@@ -11119,7 +11147,7 @@ Restrictions pragma, they are not analyzed semantically,
so they do not have a type.
@node Attribute Result,Attribute Safe_Emax,Attribute Restriction_Set,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-result}@anchor{19a}
+@anchor{gnat_rm/implementation_defined_attributes attribute-result}@anchor{19b}
@section Attribute Result
@@ -11132,7 +11160,7 @@ For a further discussion of the use of this attribute and examples of its use,
see the description of pragma Postcondition.
@node Attribute Safe_Emax,Attribute Safe_Large,Attribute Result,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-safe-emax}@anchor{19b}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-emax}@anchor{19c}
@section Attribute Safe_Emax
@@ -11145,7 +11173,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Safe_Large,Attribute Safe_Small,Attribute Safe_Emax,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-safe-large}@anchor{19c}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-large}@anchor{19d}
@section Attribute Safe_Large
@@ -11158,7 +11186,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Safe_Small,Attribute Scalar_Storage_Order,Attribute Safe_Large,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-safe-small}@anchor{19d}
+@anchor{gnat_rm/implementation_defined_attributes attribute-safe-small}@anchor{19e}
@section Attribute Safe_Small
@@ -11171,7 +11199,7 @@ the Ada 83 reference manual for an exact description of the semantics of
this attribute.
@node Attribute Scalar_Storage_Order,Attribute Simple_Storage_Pool,Attribute Safe_Small,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19e}@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{151}
+@anchor{gnat_rm/implementation_defined_attributes id4}@anchor{19f}@anchor{gnat_rm/implementation_defined_attributes attribute-scalar-storage-order}@anchor{151}
@section Attribute Scalar_Storage_Order
@@ -11294,7 +11322,7 @@ Note that debuggers may be unable to display the correct value of scalar
components of a type for which the opposite storage order is specified.
@node Attribute Simple_Storage_Pool,Attribute Small,Attribute Scalar_Storage_Order,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-simple-storage-pool}@anchor{e5}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{19f}
+@anchor{gnat_rm/implementation_defined_attributes attribute-simple-storage-pool}@anchor{e5}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{1a0}
@section Attribute Simple_Storage_Pool
@@ -11356,8 +11384,8 @@ parameter. The detailed semantics of such unchecked deallocations is the same
as defined in section 13.11.2 of the Ada Reference Manual, except that the
term @emph{simple storage pool} is substituted for @emph{storage pool}.
-@node Attribute Small,Attribute Storage_Unit,Attribute Simple_Storage_Pool,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{1a0}
+@node Attribute Small,Attribute Small_Denominator,Attribute Simple_Storage_Pool,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{1a1}
@section Attribute Small
@@ -11372,8 +11400,34 @@ for compatibility with Ada 83. See
the Ada 83 reference manual for an exact description of the semantics of
this attribute when applied to floating-point types.
-@node Attribute Storage_Unit,Attribute Stub_Type,Attribute Small,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-storage-unit}@anchor{1a1}
+@node Attribute Small_Denominator,Attribute Small_Numerator,Attribute Small,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-small-denominator}@anchor{1a2}
+@section Attribute Small_Denominator
+
+
+@geindex Small
+
+@geindex Small_Denominator
+
+@code{typ'Small_Denominator} for any fixed-point subtype @cite{typ} yields the
+denominator in the representation of @code{typ'Small} as a rational number
+with coprime factors (i.e. as an irreducible fraction).
+
+@node Attribute Small_Numerator,Attribute Storage_Unit,Attribute Small_Denominator,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-small-numerator}@anchor{1a3}
+@section Attribute Small_Numerator
+
+
+@geindex Small
+
+@geindex Small_Numerator
+
+@code{typ'Small_Numerator} for any fixed-point subtype @cite{typ} yields the
+numerator in the representation of @code{typ'Small} as a rational number
+with coprime factors (i.e. as an irreducible fraction).
+
+@node Attribute Storage_Unit,Attribute Stub_Type,Attribute Small_Numerator,Implementation Defined Attributes
+@anchor{gnat_rm/implementation_defined_attributes attribute-storage-unit}@anchor{1a4}
@section Attribute Storage_Unit
@@ -11383,7 +11437,7 @@ this attribute when applied to floating-point types.
prefix) provides the same value as @code{System.Storage_Unit}.
@node Attribute Stub_Type,Attribute System_Allocator_Alignment,Attribute Storage_Unit,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-stub-type}@anchor{1a2}
+@anchor{gnat_rm/implementation_defined_attributes attribute-stub-type}@anchor{1a5}
@section Attribute Stub_Type
@@ -11407,7 +11461,7 @@ unit @code{System.Partition_Interface}. Use of this attribute will create
an implicit dependency on this unit.
@node Attribute System_Allocator_Alignment,Attribute Target_Name,Attribute Stub_Type,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-system-allocator-alignment}@anchor{1a3}
+@anchor{gnat_rm/implementation_defined_attributes attribute-system-allocator-alignment}@anchor{1a6}
@section Attribute System_Allocator_Alignment
@@ -11424,7 +11478,7 @@ with alignment too large or to enable a realignment circuitry if the
alignment request is larger than this value.
@node Attribute Target_Name,Attribute To_Address,Attribute System_Allocator_Alignment,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-target-name}@anchor{1a4}
+@anchor{gnat_rm/implementation_defined_attributes attribute-target-name}@anchor{1a7}
@section Attribute Target_Name
@@ -11437,7 +11491,7 @@ standard gcc target name without the terminating slash (for
example, GNAT 5.0 on windows yields "i586-pc-mingw32msv").
@node Attribute To_Address,Attribute To_Any,Attribute Target_Name,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-to-address}@anchor{1a5}
+@anchor{gnat_rm/implementation_defined_attributes attribute-to-address}@anchor{1a8}
@section Attribute To_Address
@@ -11460,7 +11514,7 @@ modular manner (e.g., -1 means the same as 16#FFFF_FFFF# on
a 32 bits machine).
@node Attribute To_Any,Attribute Type_Class,Attribute To_Address,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-to-any}@anchor{1a6}
+@anchor{gnat_rm/implementation_defined_attributes attribute-to-any}@anchor{1a9}
@section Attribute To_Any
@@ -11470,7 +11524,7 @@ This internal attribute is used for the generation of remote subprogram
stubs in the context of the Distributed Systems Annex.
@node Attribute Type_Class,Attribute Type_Key,Attribute To_Any,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-type-class}@anchor{1a7}
+@anchor{gnat_rm/implementation_defined_attributes attribute-type-class}@anchor{1aa}
@section Attribute Type_Class
@@ -11500,7 +11554,7 @@ applies to all concurrent types. This attribute is designed to
be compatible with the DEC Ada 83 attribute of the same name.
@node Attribute Type_Key,Attribute TypeCode,Attribute Type_Class,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-type-key}@anchor{1a8}
+@anchor{gnat_rm/implementation_defined_attributes attribute-type-key}@anchor{1ab}
@section Attribute Type_Key
@@ -11512,7 +11566,7 @@ about the type or subtype. This provides improved compatibility with
other implementations that support this attribute.
@node Attribute TypeCode,Attribute Unconstrained_Array,Attribute Type_Key,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-typecode}@anchor{1a9}
+@anchor{gnat_rm/implementation_defined_attributes attribute-typecode}@anchor{1ac}
@section Attribute TypeCode
@@ -11522,7 +11576,7 @@ This internal attribute is used for the generation of remote subprogram
stubs in the context of the Distributed Systems Annex.
@node Attribute Unconstrained_Array,Attribute Universal_Literal_String,Attribute TypeCode,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-unconstrained-array}@anchor{1aa}
+@anchor{gnat_rm/implementation_defined_attributes attribute-unconstrained-array}@anchor{1ad}
@section Attribute Unconstrained_Array
@@ -11536,7 +11590,7 @@ still static, and yields the result of applying this test to the
generic actual.
@node Attribute Universal_Literal_String,Attribute Unrestricted_Access,Attribute Unconstrained_Array,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-universal-literal-string}@anchor{1ab}
+@anchor{gnat_rm/implementation_defined_attributes attribute-universal-literal-string}@anchor{1ae}
@section Attribute Universal_Literal_String
@@ -11564,7 +11618,7 @@ end;
@end example
@node Attribute Unrestricted_Access,Attribute Update,Attribute Universal_Literal_String,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-unrestricted-access}@anchor{1ac}
+@anchor{gnat_rm/implementation_defined_attributes attribute-unrestricted-access}@anchor{1af}
@section Attribute Unrestricted_Access
@@ -11751,7 +11805,7 @@ In general this is a risky approach. It may appear to "work" but such uses of
of GNAT to another, so are best avoided if possible.
@node Attribute Update,Attribute Valid_Scalars,Attribute Unrestricted_Access,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-update}@anchor{1ad}
+@anchor{gnat_rm/implementation_defined_attributes attribute-update}@anchor{1b0}
@section Attribute Update
@@ -11832,7 +11886,7 @@ A := A'Update ((1, 2) => 20, (3, 4) => 30);
which changes element (1,2) to 20 and (3,4) to 30.
@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Update,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1ae}
+@anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1b1}
@section Attribute Valid_Scalars
@@ -11866,7 +11920,7 @@ write a function with a single use of the attribute, and then call that
function from multiple places.
@node Attribute VADS_Size,Attribute Value_Size,Attribute Valid_Scalars,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-vads-size}@anchor{1af}
+@anchor{gnat_rm/implementation_defined_attributes attribute-vads-size}@anchor{1b2}
@section Attribute VADS_Size
@@ -11886,7 +11940,7 @@ gives the result that would be obtained by applying the attribute to
the corresponding type.
@node Attribute Value_Size,Attribute Wchar_T_Size,Attribute VADS_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b0}@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{160}
+@anchor{gnat_rm/implementation_defined_attributes id6}@anchor{1b3}@anchor{gnat_rm/implementation_defined_attributes attribute-value-size}@anchor{160}
@section Attribute Value_Size
@@ -11900,7 +11954,7 @@ a value of the given subtype. It is the same as @code{type'Size},
but, unlike @code{Size}, may be set for non-first subtypes.
@node Attribute Wchar_T_Size,Attribute Word_Size,Attribute Value_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-wchar-t-size}@anchor{1b1}
+@anchor{gnat_rm/implementation_defined_attributes attribute-wchar-t-size}@anchor{1b4}
@section Attribute Wchar_T_Size
@@ -11912,7 +11966,7 @@ primarily for constructing the definition of this type in
package @code{Interfaces.C}. The result is a static constant.
@node Attribute Word_Size,,Attribute Wchar_T_Size,Implementation Defined Attributes
-@anchor{gnat_rm/implementation_defined_attributes attribute-word-size}@anchor{1b2}
+@anchor{gnat_rm/implementation_defined_attributes attribute-word-size}@anchor{1b5}
@section Attribute Word_Size
@@ -11923,7 +11977,7 @@ prefix) provides the value @code{System.Word_Size}. The result is
a static constant.
@node Standard and Implementation Defined Restrictions,Implementation Advice,Implementation Defined Attributes,Top
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9}@anchor{gnat_rm/standard_and_implementation_defined_restrictions doc}@anchor{1b3}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions standard-and-implementation-defined-restrictions}@anchor{9}@anchor{gnat_rm/standard_and_implementation_defined_restrictions doc}@anchor{1b6}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id1}@anchor{1b7}
@chapter Standard and Implementation Defined Restrictions
@@ -11952,7 +12006,7 @@ language defined or GNAT-specific, are listed in the following.
@end menu
@node Partition-Wide Restrictions,Program Unit Level Restrictions,,Standard and Implementation Defined Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b5}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions partition-wide-restrictions}@anchor{1b8}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id2}@anchor{1b9}
@section Partition-Wide Restrictions
@@ -12041,7 +12095,7 @@ then all compilation units in the partition must obey the restriction).
@end menu
@node Immediate_Reclamation,Max_Asynchronous_Select_Nesting,,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions immediate-reclamation}@anchor{1b7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions immediate-reclamation}@anchor{1ba}
@subsection Immediate_Reclamation
@@ -12053,7 +12107,7 @@ deallocation, any storage reserved at run time for an object is
immediately reclaimed when the object no longer exists.
@node Max_Asynchronous_Select_Nesting,Max_Entry_Queue_Length,Immediate_Reclamation,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-asynchronous-select-nesting}@anchor{1b8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-asynchronous-select-nesting}@anchor{1bb}
@subsection Max_Asynchronous_Select_Nesting
@@ -12065,7 +12119,7 @@ detected at compile time. Violations of this restriction with values
other than zero cause Storage_Error to be raised.
@node Max_Entry_Queue_Length,Max_Protected_Entries,Max_Asynchronous_Select_Nesting,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-entry-queue-length}@anchor{1b9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-entry-queue-length}@anchor{1bc}
@subsection Max_Entry_Queue_Length
@@ -12086,7 +12140,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node Max_Protected_Entries,Max_Select_Alternatives,Max_Entry_Queue_Length,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-protected-entries}@anchor{1ba}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-protected-entries}@anchor{1bd}
@subsection Max_Protected_Entries
@@ -12097,7 +12151,7 @@ bounds of every entry family of a protected unit shall be static, or shall be
defined by a discriminant of a subtype whose corresponding bound is static.
@node Max_Select_Alternatives,Max_Storage_At_Blocking,Max_Protected_Entries,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-select-alternatives}@anchor{1bb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-select-alternatives}@anchor{1be}
@subsection Max_Select_Alternatives
@@ -12106,7 +12160,7 @@ defined by a discriminant of a subtype whose corresponding bound is static.
[RM D.7] Specifies the maximum number of alternatives in a selective accept.
@node Max_Storage_At_Blocking,Max_Task_Entries,Max_Select_Alternatives,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-storage-at-blocking}@anchor{1bc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-storage-at-blocking}@anchor{1bf}
@subsection Max_Storage_At_Blocking
@@ -12117,7 +12171,7 @@ Storage_Size that can be retained by a blocked task. A violation of this
restriction causes Storage_Error to be raised.
@node Max_Task_Entries,Max_Tasks,Max_Storage_At_Blocking,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-task-entries}@anchor{1bd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-task-entries}@anchor{1c0}
@subsection Max_Task_Entries
@@ -12130,7 +12184,7 @@ defined by a discriminant of a subtype whose
corresponding bound is static.
@node Max_Tasks,No_Abort_Statements,Max_Task_Entries,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-tasks}@anchor{1be}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions max-tasks}@anchor{1c1}
@subsection Max_Tasks
@@ -12143,7 +12197,7 @@ time. Violations of this restriction with values other than zero cause
Storage_Error to be raised.
@node No_Abort_Statements,No_Access_Parameter_Allocators,Max_Tasks,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-abort-statements}@anchor{1bf}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-abort-statements}@anchor{1c2}
@subsection No_Abort_Statements
@@ -12153,7 +12207,7 @@ Storage_Error to be raised.
no calls to Task_Identification.Abort_Task.
@node No_Access_Parameter_Allocators,No_Access_Subprograms,No_Abort_Statements,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-parameter-allocators}@anchor{1c0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-parameter-allocators}@anchor{1c3}
@subsection No_Access_Parameter_Allocators
@@ -12164,7 +12218,7 @@ occurrences of an allocator as the actual parameter to an access
parameter.
@node No_Access_Subprograms,No_Allocators,No_Access_Parameter_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-subprograms}@anchor{1c1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-access-subprograms}@anchor{1c4}
@subsection No_Access_Subprograms
@@ -12174,7 +12228,7 @@ parameter.
declarations of access-to-subprogram types.
@node No_Allocators,No_Anonymous_Allocators,No_Access_Subprograms,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-allocators}@anchor{1c2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-allocators}@anchor{1c5}
@subsection No_Allocators
@@ -12184,7 +12238,7 @@ declarations of access-to-subprogram types.
occurrences of an allocator.
@node No_Anonymous_Allocators,No_Asynchronous_Control,No_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-anonymous-allocators}@anchor{1c3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-anonymous-allocators}@anchor{1c6}
@subsection No_Anonymous_Allocators
@@ -12194,7 +12248,7 @@ occurrences of an allocator.
occurrences of an allocator of anonymous access type.
@node No_Asynchronous_Control,No_Calendar,No_Anonymous_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-asynchronous-control}@anchor{1c4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-asynchronous-control}@anchor{1c7}
@subsection No_Asynchronous_Control
@@ -12204,7 +12258,7 @@ occurrences of an allocator of anonymous access type.
dependences on the predefined package Asynchronous_Task_Control.
@node No_Calendar,No_Coextensions,No_Asynchronous_Control,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-calendar}@anchor{1c5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-calendar}@anchor{1c8}
@subsection No_Calendar
@@ -12214,7 +12268,7 @@ dependences on the predefined package Asynchronous_Task_Control.
dependences on package Calendar.
@node No_Coextensions,No_Default_Initialization,No_Calendar,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-coextensions}@anchor{1c6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-coextensions}@anchor{1c9}
@subsection No_Coextensions
@@ -12224,7 +12278,7 @@ dependences on package Calendar.
coextensions. See 3.10.2.
@node No_Default_Initialization,No_Delay,No_Coextensions,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-default-initialization}@anchor{1c7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-default-initialization}@anchor{1ca}
@subsection No_Default_Initialization
@@ -12241,7 +12295,7 @@ is to prohibit all cases of variables declared without a specific
initializer (including the case of OUT scalar parameters).
@node No_Delay,No_Dependence,No_Default_Initialization,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-delay}@anchor{1c8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-delay}@anchor{1cb}
@subsection No_Delay
@@ -12251,7 +12305,7 @@ initializer (including the case of OUT scalar parameters).
delay statements and no semantic dependences on package Calendar.
@node No_Dependence,No_Direct_Boolean_Operators,No_Delay,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dependence}@anchor{1c9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dependence}@anchor{1cc}
@subsection No_Dependence
@@ -12261,7 +12315,7 @@ delay statements and no semantic dependences on package Calendar.
dependences on a library unit.
@node No_Direct_Boolean_Operators,No_Dispatch,No_Dependence,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-direct-boolean-operators}@anchor{1ca}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-direct-boolean-operators}@anchor{1cd}
@subsection No_Direct_Boolean_Operators
@@ -12274,7 +12328,7 @@ protocol requires the use of short-circuit (and then, or else) forms for all
composite boolean operations.
@node No_Dispatch,No_Dispatching_Calls,No_Direct_Boolean_Operators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatch}@anchor{1cb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatch}@anchor{1ce}
@subsection No_Dispatch
@@ -12284,7 +12338,7 @@ composite boolean operations.
occurrences of @code{T'Class}, for any (tagged) subtype @code{T}.
@node No_Dispatching_Calls,No_Dynamic_Attachment,No_Dispatch,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatching-calls}@anchor{1cc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dispatching-calls}@anchor{1cf}
@subsection No_Dispatching_Calls
@@ -12345,7 +12399,7 @@ end Example;
@end example
@node No_Dynamic_Attachment,No_Dynamic_Priorities,No_Dispatching_Calls,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-attachment}@anchor{1cd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-attachment}@anchor{1d0}
@subsection No_Dynamic_Attachment
@@ -12364,7 +12418,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node No_Dynamic_Priorities,No_Entry_Calls_In_Elaboration_Code,No_Dynamic_Attachment,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-priorities}@anchor{1ce}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-priorities}@anchor{1d1}
@subsection No_Dynamic_Priorities
@@ -12373,7 +12427,7 @@ warnings on obsolescent features are activated).
[RM D.7] There are no semantic dependencies on the package Dynamic_Priorities.
@node No_Entry_Calls_In_Elaboration_Code,No_Enumeration_Maps,No_Dynamic_Priorities,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-calls-in-elaboration-code}@anchor{1cf}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-calls-in-elaboration-code}@anchor{1d2}
@subsection No_Entry_Calls_In_Elaboration_Code
@@ -12385,7 +12439,7 @@ restriction, the compiler can assume that no code past an accept statement
in a task can be executed at elaboration time.
@node No_Enumeration_Maps,No_Exception_Handlers,No_Entry_Calls_In_Elaboration_Code,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-enumeration-maps}@anchor{1d0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-enumeration-maps}@anchor{1d3}
@subsection No_Enumeration_Maps
@@ -12396,7 +12450,7 @@ enumeration maps are used (that is Image and Value attributes applied
to enumeration types).
@node No_Exception_Handlers,No_Exception_Propagation,No_Enumeration_Maps,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-handlers}@anchor{1d1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-handlers}@anchor{1d4}
@subsection No_Exception_Handlers
@@ -12421,7 +12475,7 @@ statement generated by the compiler). The Line parameter when nonzero
represents the line number in the source program where the raise occurs.
@node No_Exception_Propagation,No_Exception_Registration,No_Exception_Handlers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-propagation}@anchor{1d2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-propagation}@anchor{1d5}
@subsection No_Exception_Propagation
@@ -12438,7 +12492,7 @@ the package GNAT.Current_Exception is not permitted, and reraise
statements (raise with no operand) are not permitted.
@node No_Exception_Registration,No_Exceptions,No_Exception_Propagation,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-registration}@anchor{1d3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exception-registration}@anchor{1d6}
@subsection No_Exception_Registration
@@ -12452,7 +12506,7 @@ code is simplified by omitting the otherwise-required global registration
of exceptions when they are declared.
@node No_Exceptions,No_Finalization,No_Exception_Registration,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exceptions}@anchor{1d4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-exceptions}@anchor{1d7}
@subsection No_Exceptions
@@ -12463,7 +12517,7 @@ raise statements and no exception handlers and also suppresses the
generation of language-defined run-time checks.
@node No_Finalization,No_Fixed_Point,No_Exceptions,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-finalization}@anchor{1d5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-finalization}@anchor{1d8}
@subsection No_Finalization
@@ -12504,7 +12558,7 @@ object or a nested component, either declared on the stack or on the heap. The
deallocation of a controlled object no longer finalizes its contents.
@node No_Fixed_Point,No_Floating_Point,No_Finalization,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-fixed-point}@anchor{1d6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-fixed-point}@anchor{1d9}
@subsection No_Fixed_Point
@@ -12514,7 +12568,7 @@ deallocation of a controlled object no longer finalizes its contents.
occurrences of fixed point types and operations.
@node No_Floating_Point,No_Implicit_Conditionals,No_Fixed_Point,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-floating-point}@anchor{1d7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-floating-point}@anchor{1da}
@subsection No_Floating_Point
@@ -12524,7 +12578,7 @@ occurrences of fixed point types and operations.
occurrences of floating point types and operations.
@node No_Implicit_Conditionals,No_Implicit_Dynamic_Code,No_Floating_Point,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-conditionals}@anchor{1d8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-conditionals}@anchor{1db}
@subsection No_Implicit_Conditionals
@@ -12540,7 +12594,7 @@ normal manner. Constructs generating implicit conditionals include comparisons
of composite objects and the Max/Min attributes.
@node No_Implicit_Dynamic_Code,No_Implicit_Heap_Allocations,No_Implicit_Conditionals,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-dynamic-code}@anchor{1d9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-dynamic-code}@anchor{1dc}
@subsection No_Implicit_Dynamic_Code
@@ -12570,7 +12624,7 @@ foreign-language convention; primitive operations of nested tagged
types.
@node No_Implicit_Heap_Allocations,No_Implicit_Protected_Object_Allocations,No_Implicit_Dynamic_Code,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-heap-allocations}@anchor{1da}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-heap-allocations}@anchor{1dd}
@subsection No_Implicit_Heap_Allocations
@@ -12579,7 +12633,7 @@ types.
[RM D.7] No constructs are allowed to cause implicit heap allocation.
@node No_Implicit_Protected_Object_Allocations,No_Implicit_Task_Allocations,No_Implicit_Heap_Allocations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-protected-object-allocations}@anchor{1db}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-protected-object-allocations}@anchor{1de}
@subsection No_Implicit_Protected_Object_Allocations
@@ -12589,7 +12643,7 @@ types.
protected object.
@node No_Implicit_Task_Allocations,No_Initialize_Scalars,No_Implicit_Protected_Object_Allocations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-task-allocations}@anchor{1dc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-task-allocations}@anchor{1df}
@subsection No_Implicit_Task_Allocations
@@ -12598,7 +12652,7 @@ protected object.
[GNAT] No constructs are allowed to cause implicit heap allocation of a task.
@node No_Initialize_Scalars,No_IO,No_Implicit_Task_Allocations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-initialize-scalars}@anchor{1dd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-initialize-scalars}@anchor{1e0}
@subsection No_Initialize_Scalars
@@ -12610,7 +12664,7 @@ code, and in particular eliminates dummy null initialization routines that
are otherwise generated for some record and array types.
@node No_IO,No_Local_Allocators,No_Initialize_Scalars,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-io}@anchor{1de}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-io}@anchor{1e1}
@subsection No_IO
@@ -12621,7 +12675,7 @@ dependences on any of the library units Sequential_IO, Direct_IO,
Text_IO, Wide_Text_IO, Wide_Wide_Text_IO, or Stream_IO.
@node No_Local_Allocators,No_Local_Protected_Objects,No_IO,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-allocators}@anchor{1df}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-allocators}@anchor{1e2}
@subsection No_Local_Allocators
@@ -12632,7 +12686,7 @@ occurrences of an allocator in subprograms, generic subprograms, tasks,
and entry bodies.
@node No_Local_Protected_Objects,No_Local_Timing_Events,No_Local_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-protected-objects}@anchor{1e0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-protected-objects}@anchor{1e3}
@subsection No_Local_Protected_Objects
@@ -12642,7 +12696,7 @@ and entry bodies.
only declared at the library level.
@node No_Local_Timing_Events,No_Long_Long_Integers,No_Local_Protected_Objects,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-timing-events}@anchor{1e1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-local-timing-events}@anchor{1e4}
@subsection No_Local_Timing_Events
@@ -12652,7 +12706,7 @@ only declared at the library level.
declared at the library level.
@node No_Long_Long_Integers,No_Multiple_Elaboration,No_Local_Timing_Events,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-long-long-integers}@anchor{1e2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-long-long-integers}@anchor{1e5}
@subsection No_Long_Long_Integers
@@ -12664,7 +12718,7 @@ implicit base type is Long_Long_Integer, and modular types whose size exceeds
Long_Integer'Size.
@node No_Multiple_Elaboration,No_Nested_Finalization,No_Long_Long_Integers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-multiple-elaboration}@anchor{1e3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-multiple-elaboration}@anchor{1e6}
@subsection No_Multiple_Elaboration
@@ -12680,7 +12734,7 @@ possible, including non-Ada main programs and Stand Alone libraries, are not
permitted and will be diagnosed by the binder.
@node No_Nested_Finalization,No_Protected_Type_Allocators,No_Multiple_Elaboration,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-nested-finalization}@anchor{1e4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-nested-finalization}@anchor{1e7}
@subsection No_Nested_Finalization
@@ -12689,7 +12743,7 @@ permitted and will be diagnosed by the binder.
[RM D.7] All objects requiring finalization are declared at the library level.
@node No_Protected_Type_Allocators,No_Protected_Types,No_Nested_Finalization,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-type-allocators}@anchor{1e5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-type-allocators}@anchor{1e8}
@subsection No_Protected_Type_Allocators
@@ -12699,7 +12753,7 @@ permitted and will be diagnosed by the binder.
expressions that attempt to allocate protected objects.
@node No_Protected_Types,No_Recursion,No_Protected_Type_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-types}@anchor{1e6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-protected-types}@anchor{1e9}
@subsection No_Protected_Types
@@ -12709,7 +12763,7 @@ expressions that attempt to allocate protected objects.
declarations of protected types or protected objects.
@node No_Recursion,No_Reentrancy,No_Protected_Types,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-recursion}@anchor{1e7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-recursion}@anchor{1ea}
@subsection No_Recursion
@@ -12719,7 +12773,7 @@ declarations of protected types or protected objects.
part of its execution.
@node No_Reentrancy,No_Relative_Delay,No_Recursion,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-reentrancy}@anchor{1e8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-reentrancy}@anchor{1eb}
@subsection No_Reentrancy
@@ -12729,7 +12783,7 @@ part of its execution.
two tasks at the same time.
@node No_Relative_Delay,No_Requeue_Statements,No_Reentrancy,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-relative-delay}@anchor{1e9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-relative-delay}@anchor{1ec}
@subsection No_Relative_Delay
@@ -12740,7 +12794,7 @@ relative statements and prevents expressions such as @code{delay 1.23;} from
appearing in source code.
@node No_Requeue_Statements,No_Secondary_Stack,No_Relative_Delay,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-requeue-statements}@anchor{1ea}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-requeue-statements}@anchor{1ed}
@subsection No_Requeue_Statements
@@ -12758,7 +12812,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on oNobsolescent features are activated).
@node No_Secondary_Stack,No_Select_Statements,No_Requeue_Statements,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-secondary-stack}@anchor{1eb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-secondary-stack}@anchor{1ee}
@subsection No_Secondary_Stack
@@ -12771,7 +12825,7 @@ stack is used to implement functions returning unconstrained objects
secondary stacks for tasks (excluding the environment task) at run time.
@node No_Select_Statements,No_Specific_Termination_Handlers,No_Secondary_Stack,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-select-statements}@anchor{1ec}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-select-statements}@anchor{1ef}
@subsection No_Select_Statements
@@ -12781,7 +12835,7 @@ secondary stacks for tasks (excluding the environment task) at run time.
kind are permitted, that is the keyword @code{select} may not appear.
@node No_Specific_Termination_Handlers,No_Specification_of_Aspect,No_Select_Statements,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specific-termination-handlers}@anchor{1ed}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specific-termination-handlers}@anchor{1f0}
@subsection No_Specific_Termination_Handlers
@@ -12791,7 +12845,7 @@ kind are permitted, that is the keyword @code{select} may not appear.
or to Ada.Task_Termination.Specific_Handler.
@node No_Specification_of_Aspect,No_Standard_Allocators_After_Elaboration,No_Specific_Termination_Handlers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specification-of-aspect}@anchor{1ee}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-specification-of-aspect}@anchor{1f1}
@subsection No_Specification_of_Aspect
@@ -12802,7 +12856,7 @@ specification, attribute definition clause, or pragma is given for a
given aspect.
@node No_Standard_Allocators_After_Elaboration,No_Standard_Storage_Pools,No_Specification_of_Aspect,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-allocators-after-elaboration}@anchor{1ef}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-allocators-after-elaboration}@anchor{1f2}
@subsection No_Standard_Allocators_After_Elaboration
@@ -12814,7 +12868,7 @@ library items of the partition has completed. Otherwise, Storage_Error
is raised.
@node No_Standard_Storage_Pools,No_Stream_Optimizations,No_Standard_Allocators_After_Elaboration,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-storage-pools}@anchor{1f0}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-standard-storage-pools}@anchor{1f3}
@subsection No_Standard_Storage_Pools
@@ -12826,7 +12880,7 @@ have an explicit Storage_Pool attribute defined specifying a
user-defined storage pool.
@node No_Stream_Optimizations,No_Streams,No_Standard_Storage_Pools,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-stream-optimizations}@anchor{1f1}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-stream-optimizations}@anchor{1f4}
@subsection No_Stream_Optimizations
@@ -12839,7 +12893,7 @@ due to their superior performance. When this restriction is in effect, the
compiler performs all IO operations on a per-character basis.
@node No_Streams,No_Task_Allocators,No_Stream_Optimizations,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-streams}@anchor{1f2}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-streams}@anchor{1f5}
@subsection No_Streams
@@ -12860,7 +12914,7 @@ unit declaring a tagged type should be compiled with the restriction,
though this is not required.
@node No_Task_Allocators,No_Task_At_Interrupt_Priority,No_Streams,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-allocators}@anchor{1f3}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-allocators}@anchor{1f6}
@subsection No_Task_Allocators
@@ -12870,7 +12924,7 @@ though this is not required.
or types containing task subcomponents.
@node No_Task_At_Interrupt_Priority,No_Task_Attributes_Package,No_Task_Allocators,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-at-interrupt-priority}@anchor{1f4}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-at-interrupt-priority}@anchor{1f7}
@subsection No_Task_At_Interrupt_Priority
@@ -12882,7 +12936,7 @@ a consequence, the tasks are always created with a priority below
that an interrupt priority.
@node No_Task_Attributes_Package,No_Task_Hierarchy,No_Task_At_Interrupt_Priority,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-attributes-package}@anchor{1f5}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-attributes-package}@anchor{1f8}
@subsection No_Task_Attributes_Package
@@ -12899,7 +12953,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node No_Task_Hierarchy,No_Task_Termination,No_Task_Attributes_Package,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-hierarchy}@anchor{1f6}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-hierarchy}@anchor{1f9}
@subsection No_Task_Hierarchy
@@ -12909,7 +12963,7 @@ warnings on obsolescent features are activated).
directly on the environment task of the partition.
@node No_Task_Termination,No_Tasking,No_Task_Hierarchy,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-termination}@anchor{1f7}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-task-termination}@anchor{1fa}
@subsection No_Task_Termination
@@ -12918,7 +12972,7 @@ directly on the environment task of the partition.
[RM D.7] Tasks that terminate are erroneous.
@node No_Tasking,No_Terminate_Alternatives,No_Task_Termination,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-tasking}@anchor{1f8}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-tasking}@anchor{1fb}
@subsection No_Tasking
@@ -12931,7 +12985,7 @@ and cause an error message to be output either by the compiler or
binder.
@node No_Terminate_Alternatives,No_Unchecked_Access,No_Tasking,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-terminate-alternatives}@anchor{1f9}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-terminate-alternatives}@anchor{1fc}
@subsection No_Terminate_Alternatives
@@ -12940,7 +12994,7 @@ binder.
[RM D.7] There are no selective accepts with terminate alternatives.
@node No_Unchecked_Access,No_Unchecked_Conversion,No_Terminate_Alternatives,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-access}@anchor{1fa}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-access}@anchor{1fd}
@subsection No_Unchecked_Access
@@ -12950,7 +13004,7 @@ binder.
occurrences of the Unchecked_Access attribute.
@node No_Unchecked_Conversion,No_Unchecked_Deallocation,No_Unchecked_Access,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-conversion}@anchor{1fb}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-conversion}@anchor{1fe}
@subsection No_Unchecked_Conversion
@@ -12960,7 +13014,7 @@ occurrences of the Unchecked_Access attribute.
dependences on the predefined generic function Unchecked_Conversion.
@node No_Unchecked_Deallocation,No_Use_Of_Entity,No_Unchecked_Conversion,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-deallocation}@anchor{1fc}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-unchecked-deallocation}@anchor{1ff}
@subsection No_Unchecked_Deallocation
@@ -12970,7 +13024,7 @@ dependences on the predefined generic function Unchecked_Conversion.
dependences on the predefined generic procedure Unchecked_Deallocation.
@node No_Use_Of_Entity,Pure_Barriers,No_Unchecked_Deallocation,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-use-of-entity}@anchor{1fd}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-use-of-entity}@anchor{200}
@subsection No_Use_Of_Entity
@@ -12990,7 +13044,7 @@ No_Use_Of_Entity => Ada.Text_IO.Put_Line
@end example
@node Pure_Barriers,Simple_Barriers,No_Use_Of_Entity,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions pure-barriers}@anchor{1fe}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions pure-barriers}@anchor{201}
@subsection Pure_Barriers
@@ -13041,7 +13095,7 @@ but still ensures absence of side effects, exceptions, and recursion
during the evaluation of the barriers.
@node Simple_Barriers,Static_Priorities,Pure_Barriers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions simple-barriers}@anchor{1ff}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions simple-barriers}@anchor{202}
@subsection Simple_Barriers
@@ -13060,7 +13114,7 @@ compatibility purposes (and a warning will be generated for its use if
warnings on obsolescent features are activated).
@node Static_Priorities,Static_Storage_Size,Simple_Barriers,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-priorities}@anchor{200}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-priorities}@anchor{203}
@subsection Static_Priorities
@@ -13071,7 +13125,7 @@ are static, and that there are no dependences on the package
@code{Ada.Dynamic_Priorities}.
@node Static_Storage_Size,,Static_Priorities,Partition-Wide Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-storage-size}@anchor{201}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-storage-size}@anchor{204}
@subsection Static_Storage_Size
@@ -13081,7 +13135,7 @@ are static, and that there are no dependences on the package
in a Storage_Size pragma or attribute definition clause is static.
@node Program Unit Level Restrictions,,Partition-Wide Restrictions,Standard and Implementation Defined Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{202}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{203}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions program-unit-level-restrictions}@anchor{205}@anchor{gnat_rm/standard_and_implementation_defined_restrictions id3}@anchor{206}
@section Program Unit Level Restrictions
@@ -13111,7 +13165,7 @@ other compilation units in the partition.
@end menu
@node No_Elaboration_Code,No_Dynamic_Sized_Objects,,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-elaboration-code}@anchor{204}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-elaboration-code}@anchor{207}
@subsection No_Elaboration_Code
@@ -13167,7 +13221,7 @@ associated with the unit. This counter is typically used to check for access
before elaboration and to control multiple elaboration attempts.
@node No_Dynamic_Sized_Objects,No_Entry_Queue,No_Elaboration_Code,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-sized-objects}@anchor{205}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-dynamic-sized-objects}@anchor{208}
@subsection No_Dynamic_Sized_Objects
@@ -13185,7 +13239,7 @@ access discriminants. It is often a good idea to combine this restriction
with No_Secondary_Stack.
@node No_Entry_Queue,No_Implementation_Aspect_Specifications,No_Dynamic_Sized_Objects,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-queue}@anchor{206}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-entry-queue}@anchor{209}
@subsection No_Entry_Queue
@@ -13198,7 +13252,7 @@ checked at compile time. A program execution is erroneous if an attempt
is made to queue a second task on such an entry.
@node No_Implementation_Aspect_Specifications,No_Implementation_Attributes,No_Entry_Queue,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-aspect-specifications}@anchor{207}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-aspect-specifications}@anchor{20a}
@subsection No_Implementation_Aspect_Specifications
@@ -13209,7 +13263,7 @@ GNAT-defined aspects are present. With this restriction, the only
aspects that can be used are those defined in the Ada Reference Manual.
@node No_Implementation_Attributes,No_Implementation_Identifiers,No_Implementation_Aspect_Specifications,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-attributes}@anchor{208}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-attributes}@anchor{20b}
@subsection No_Implementation_Attributes
@@ -13221,7 +13275,7 @@ attributes that can be used are those defined in the Ada Reference
Manual.
@node No_Implementation_Identifiers,No_Implementation_Pragmas,No_Implementation_Attributes,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-identifiers}@anchor{209}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-identifiers}@anchor{20c}
@subsection No_Implementation_Identifiers
@@ -13232,7 +13286,7 @@ implementation-defined identifiers (marked with pragma Implementation_Defined)
occur within language-defined packages.
@node No_Implementation_Pragmas,No_Implementation_Restrictions,No_Implementation_Identifiers,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-pragmas}@anchor{20a}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-pragmas}@anchor{20d}
@subsection No_Implementation_Pragmas
@@ -13243,7 +13297,7 @@ GNAT-defined pragmas are present. With this restriction, the only
pragmas that can be used are those defined in the Ada Reference Manual.
@node No_Implementation_Restrictions,No_Implementation_Units,No_Implementation_Pragmas,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-restrictions}@anchor{20b}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-restrictions}@anchor{20e}
@subsection No_Implementation_Restrictions
@@ -13255,7 +13309,7 @@ are present. With this restriction, the only other restriction identifiers
that can be used are those defined in the Ada Reference Manual.
@node No_Implementation_Units,No_Implicit_Aliasing,No_Implementation_Restrictions,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-units}@anchor{20c}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implementation-units}@anchor{20f}
@subsection No_Implementation_Units
@@ -13266,7 +13320,7 @@ mention in the context clause of any implementation-defined descendants
of packages Ada, Interfaces, or System.
@node No_Implicit_Aliasing,No_Implicit_Loops,No_Implementation_Units,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-aliasing}@anchor{20d}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-aliasing}@anchor{210}
@subsection No_Implicit_Aliasing
@@ -13281,7 +13335,7 @@ to be aliased, and in such cases, it can always be replaced by
the standard attribute Unchecked_Access which is preferable.
@node No_Implicit_Loops,No_Obsolescent_Features,No_Implicit_Aliasing,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-loops}@anchor{20e}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-implicit-loops}@anchor{211}
@subsection No_Implicit_Loops
@@ -13298,7 +13352,7 @@ arrays larger than about 5000 scalar components. Note that if this restriction
is set in the spec of a package, it will not apply to its body.
@node No_Obsolescent_Features,No_Wide_Characters,No_Implicit_Loops,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-obsolescent-features}@anchor{20f}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-obsolescent-features}@anchor{212}
@subsection No_Obsolescent_Features
@@ -13308,7 +13362,7 @@ is set in the spec of a package, it will not apply to its body.
features are used, as defined in Annex J of the Ada Reference Manual.
@node No_Wide_Characters,Static_Dispatch_Tables,No_Obsolescent_Features,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-wide-characters}@anchor{210}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-wide-characters}@anchor{213}
@subsection No_Wide_Characters
@@ -13322,7 +13376,7 @@ appear in the program (that is literals representing characters not in
type @code{Character}).
@node Static_Dispatch_Tables,SPARK_05,No_Wide_Characters,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-dispatch-tables}@anchor{211}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions static-dispatch-tables}@anchor{214}
@subsection Static_Dispatch_Tables
@@ -13332,7 +13386,7 @@ type @code{Character}).
associated with dispatch tables can be placed in read-only memory.
@node SPARK_05,,Static_Dispatch_Tables,Program Unit Level Restrictions
-@anchor{gnat_rm/standard_and_implementation_defined_restrictions spark-05}@anchor{212}
+@anchor{gnat_rm/standard_and_implementation_defined_restrictions spark-05}@anchor{215}
@subsection SPARK_05
@@ -13355,7 +13409,7 @@ gnatprove -P project.gpr --mode=check_all
@end example
@node Implementation Advice,Implementation Defined Characteristics,Standard and Implementation Defined Restrictions,Top
-@anchor{gnat_rm/implementation_advice doc}@anchor{213}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}@anchor{gnat_rm/implementation_advice id1}@anchor{214}
+@anchor{gnat_rm/implementation_advice doc}@anchor{216}@anchor{gnat_rm/implementation_advice implementation-advice}@anchor{a}@anchor{gnat_rm/implementation_advice id1}@anchor{217}
@chapter Implementation Advice
@@ -13452,7 +13506,7 @@ case the text describes what GNAT does and why.
@end menu
@node RM 1 1 3 20 Error Detection,RM 1 1 3 31 Child Units,,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-1-1-3-20-error-detection}@anchor{215}
+@anchor{gnat_rm/implementation_advice rm-1-1-3-20-error-detection}@anchor{218}
@section RM 1.1.3(20): Error Detection
@@ -13469,7 +13523,7 @@ or diagnosed at compile time.
@geindex Child Units
@node RM 1 1 3 31 Child Units,RM 1 1 5 12 Bounded Errors,RM 1 1 3 20 Error Detection,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-1-1-3-31-child-units}@anchor{216}
+@anchor{gnat_rm/implementation_advice rm-1-1-3-31-child-units}@anchor{219}
@section RM 1.1.3(31): Child Units
@@ -13485,7 +13539,7 @@ Followed.
@geindex Bounded errors
@node RM 1 1 5 12 Bounded Errors,RM 2 8 16 Pragmas,RM 1 1 3 31 Child Units,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-1-1-5-12-bounded-errors}@anchor{217}
+@anchor{gnat_rm/implementation_advice rm-1-1-5-12-bounded-errors}@anchor{21a}
@section RM 1.1.5(12): Bounded Errors
@@ -13502,7 +13556,7 @@ runtime.
@geindex Pragmas
@node RM 2 8 16 Pragmas,RM 2 8 17-19 Pragmas,RM 1 1 5 12 Bounded Errors,Implementation Advice
-@anchor{gnat_rm/implementation_advice id2}@anchor{218}@anchor{gnat_rm/implementation_advice rm-2-8-16-pragmas}@anchor{219}
+@anchor{gnat_rm/implementation_advice id2}@anchor{21b}@anchor{gnat_rm/implementation_advice rm-2-8-16-pragmas}@anchor{21c}
@section RM 2.8(16): Pragmas
@@ -13615,7 +13669,7 @@ that this advice not be followed. For details see
@ref{7,,Implementation Defined Pragmas}.
@node RM 2 8 17-19 Pragmas,RM 3 5 2 5 Alternative Character Sets,RM 2 8 16 Pragmas,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-2-8-17-19-pragmas}@anchor{21a}
+@anchor{gnat_rm/implementation_advice rm-2-8-17-19-pragmas}@anchor{21d}
@section RM 2.8(17-19): Pragmas
@@ -13636,14 +13690,14 @@ replacing @code{library_items}."
@end itemize
@end quotation
-See @ref{219,,RM 2.8(16); Pragmas}.
+See @ref{21c,,RM 2.8(16); Pragmas}.
@geindex Character Sets
@geindex Alternative Character Sets
@node RM 3 5 2 5 Alternative Character Sets,RM 3 5 4 28 Integer Types,RM 2 8 17-19 Pragmas,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-2-5-alternative-character-sets}@anchor{21b}
+@anchor{gnat_rm/implementation_advice rm-3-5-2-5-alternative-character-sets}@anchor{21e}
@section RM 3.5.2(5): Alternative Character Sets
@@ -13671,7 +13725,7 @@ there is no such restriction.
@geindex Integer types
@node RM 3 5 4 28 Integer Types,RM 3 5 4 29 Integer Types,RM 3 5 2 5 Alternative Character Sets,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-4-28-integer-types}@anchor{21c}
+@anchor{gnat_rm/implementation_advice rm-3-5-4-28-integer-types}@anchor{21f}
@section RM 3.5.4(28): Integer Types
@@ -13690,7 +13744,7 @@ are supported for convenient interface to C, and so that all hardware
types of the machine are easily available.
@node RM 3 5 4 29 Integer Types,RM 3 5 5 8 Enumeration Values,RM 3 5 4 28 Integer Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-4-29-integer-types}@anchor{21d}
+@anchor{gnat_rm/implementation_advice rm-3-5-4-29-integer-types}@anchor{220}
@section RM 3.5.4(29): Integer Types
@@ -13706,7 +13760,7 @@ Followed.
@geindex Enumeration values
@node RM 3 5 5 8 Enumeration Values,RM 3 5 7 17 Float Types,RM 3 5 4 29 Integer Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-5-8-enumeration-values}@anchor{21e}
+@anchor{gnat_rm/implementation_advice rm-3-5-5-8-enumeration-values}@anchor{221}
@section RM 3.5.5(8): Enumeration Values
@@ -13726,7 +13780,7 @@ Followed.
@geindex Float types
@node RM 3 5 7 17 Float Types,RM 3 6 2 11 Multidimensional Arrays,RM 3 5 5 8 Enumeration Values,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-5-7-17-float-types}@anchor{21f}
+@anchor{gnat_rm/implementation_advice rm-3-5-7-17-float-types}@anchor{222}
@section RM 3.5.7(17): Float Types
@@ -13756,7 +13810,7 @@ is a software rather than a hardware format.
@geindex multidimensional
@node RM 3 6 2 11 Multidimensional Arrays,RM 9 6 30-31 Duration'Small,RM 3 5 7 17 Float Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-3-6-2-11-multidimensional-arrays}@anchor{220}
+@anchor{gnat_rm/implementation_advice rm-3-6-2-11-multidimensional-arrays}@anchor{223}
@section RM 3.6.2(11): Multidimensional Arrays
@@ -13774,7 +13828,7 @@ Followed.
@geindex Duration'Small
@node RM 9 6 30-31 Duration'Small,RM 10 2 1 12 Consistent Representation,RM 3 6 2 11 Multidimensional Arrays,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-9-6-30-31-duration-small}@anchor{221}
+@anchor{gnat_rm/implementation_advice rm-9-6-30-31-duration-small}@anchor{224}
@section RM 9.6(30-31): Duration'Small
@@ -13795,7 +13849,7 @@ it need not be the same time base as used for @code{Calendar.Clock}."
Followed.
@node RM 10 2 1 12 Consistent Representation,RM 11 4 1 19 Exception Information,RM 9 6 30-31 Duration'Small,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-10-2-1-12-consistent-representation}@anchor{222}
+@anchor{gnat_rm/implementation_advice rm-10-2-1-12-consistent-representation}@anchor{225}
@section RM 10.2.1(12): Consistent Representation
@@ -13817,7 +13871,7 @@ advice without severely impacting efficiency of execution.
@geindex Exception information
@node RM 11 4 1 19 Exception Information,RM 11 5 28 Suppression of Checks,RM 10 2 1 12 Consistent Representation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-11-4-1-19-exception-information}@anchor{223}
+@anchor{gnat_rm/implementation_advice rm-11-4-1-19-exception-information}@anchor{226}
@section RM 11.4.1(19): Exception Information
@@ -13848,7 +13902,7 @@ Pragma @code{Discard_Names}.
@geindex suppression of
@node RM 11 5 28 Suppression of Checks,RM 13 1 21-24 Representation Clauses,RM 11 4 1 19 Exception Information,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-11-5-28-suppression-of-checks}@anchor{224}
+@anchor{gnat_rm/implementation_advice rm-11-5-28-suppression-of-checks}@anchor{227}
@section RM 11.5(28): Suppression of Checks
@@ -13863,7 +13917,7 @@ Followed.
@geindex Representation clauses
@node RM 13 1 21-24 Representation Clauses,RM 13 2 6-8 Packed Types,RM 11 5 28 Suppression of Checks,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-1-21-24-representation-clauses}@anchor{225}
+@anchor{gnat_rm/implementation_advice rm-13-1-21-24-representation-clauses}@anchor{228}
@section RM 13.1 (21-24): Representation Clauses
@@ -13912,7 +13966,7 @@ Followed.
@geindex Packed types
@node RM 13 2 6-8 Packed Types,RM 13 3 14-19 Address Clauses,RM 13 1 21-24 Representation Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-2-6-8-packed-types}@anchor{226}
+@anchor{gnat_rm/implementation_advice rm-13-2-6-8-packed-types}@anchor{229}
@section RM 13.2(6-8): Packed Types
@@ -13951,7 +14005,7 @@ Followed.
@geindex Address clauses
@node RM 13 3 14-19 Address Clauses,RM 13 3 29-35 Alignment Clauses,RM 13 2 6-8 Packed Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-14-19-address-clauses}@anchor{227}
+@anchor{gnat_rm/implementation_advice rm-13-3-14-19-address-clauses}@anchor{22a}
@section RM 13.3(14-19): Address Clauses
@@ -14004,7 +14058,7 @@ Followed.
@geindex Alignment clauses
@node RM 13 3 29-35 Alignment Clauses,RM 13 3 42-43 Size Clauses,RM 13 3 14-19 Address Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-29-35-alignment-clauses}@anchor{228}
+@anchor{gnat_rm/implementation_advice rm-13-3-29-35-alignment-clauses}@anchor{22b}
@section RM 13.3(29-35): Alignment Clauses
@@ -14061,7 +14115,7 @@ Followed.
@geindex Size clauses
@node RM 13 3 42-43 Size Clauses,RM 13 3 50-56 Size Clauses,RM 13 3 29-35 Alignment Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-42-43-size-clauses}@anchor{229}
+@anchor{gnat_rm/implementation_advice rm-13-3-42-43-size-clauses}@anchor{22c}
@section RM 13.3(42-43): Size Clauses
@@ -14079,7 +14133,7 @@ object's @code{Alignment} (if the @code{Alignment} is nonzero)."
Followed.
@node RM 13 3 50-56 Size Clauses,RM 13 3 71-73 Component Size Clauses,RM 13 3 42-43 Size Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-50-56-size-clauses}@anchor{22a}
+@anchor{gnat_rm/implementation_advice rm-13-3-50-56-size-clauses}@anchor{22d}
@section RM 13.3(50-56): Size Clauses
@@ -14130,7 +14184,7 @@ Followed.
@geindex Component_Size clauses
@node RM 13 3 71-73 Component Size Clauses,RM 13 4 9-10 Enumeration Representation Clauses,RM 13 3 50-56 Size Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-3-71-73-component-size-clauses}@anchor{22b}
+@anchor{gnat_rm/implementation_advice rm-13-3-71-73-component-size-clauses}@anchor{22e}
@section RM 13.3(71-73): Component Size Clauses
@@ -14164,7 +14218,7 @@ Followed.
@geindex enumeration
@node RM 13 4 9-10 Enumeration Representation Clauses,RM 13 5 1 17-22 Record Representation Clauses,RM 13 3 71-73 Component Size Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-4-9-10-enumeration-representation-clauses}@anchor{22c}
+@anchor{gnat_rm/implementation_advice rm-13-4-9-10-enumeration-representation-clauses}@anchor{22f}
@section RM 13.4(9-10): Enumeration Representation Clauses
@@ -14186,7 +14240,7 @@ Followed.
@geindex records
@node RM 13 5 1 17-22 Record Representation Clauses,RM 13 5 2 5 Storage Place Attributes,RM 13 4 9-10 Enumeration Representation Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-5-1-17-22-record-representation-clauses}@anchor{22d}
+@anchor{gnat_rm/implementation_advice rm-13-5-1-17-22-record-representation-clauses}@anchor{230}
@section RM 13.5.1(17-22): Record Representation Clauses
@@ -14246,7 +14300,7 @@ and all mentioned features are implemented.
@geindex Storage place attributes
@node RM 13 5 2 5 Storage Place Attributes,RM 13 5 3 7-8 Bit Ordering,RM 13 5 1 17-22 Record Representation Clauses,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-5-2-5-storage-place-attributes}@anchor{22e}
+@anchor{gnat_rm/implementation_advice rm-13-5-2-5-storage-place-attributes}@anchor{231}
@section RM 13.5.2(5): Storage Place Attributes
@@ -14266,7 +14320,7 @@ Followed. There are no such components in GNAT.
@geindex Bit ordering
@node RM 13 5 3 7-8 Bit Ordering,RM 13 7 37 Address as Private,RM 13 5 2 5 Storage Place Attributes,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-5-3-7-8-bit-ordering}@anchor{22f}
+@anchor{gnat_rm/implementation_advice rm-13-5-3-7-8-bit-ordering}@anchor{232}
@section RM 13.5.3(7-8): Bit Ordering
@@ -14286,7 +14340,7 @@ Thus non-default bit ordering is not supported.
@geindex as private type
@node RM 13 7 37 Address as Private,RM 13 7 1 16 Address Operations,RM 13 5 3 7-8 Bit Ordering,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-7-37-address-as-private}@anchor{230}
+@anchor{gnat_rm/implementation_advice rm-13-7-37-address-as-private}@anchor{233}
@section RM 13.7(37): Address as Private
@@ -14304,7 +14358,7 @@ Followed.
@geindex operations of
@node RM 13 7 1 16 Address Operations,RM 13 9 14-17 Unchecked Conversion,RM 13 7 37 Address as Private,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-7-1-16-address-operations}@anchor{231}
+@anchor{gnat_rm/implementation_advice rm-13-7-1-16-address-operations}@anchor{234}
@section RM 13.7.1(16): Address Operations
@@ -14322,7 +14376,7 @@ operation raises @code{Program_Error}, since all operations make sense.
@geindex Unchecked conversion
@node RM 13 9 14-17 Unchecked Conversion,RM 13 11 23-25 Implicit Heap Usage,RM 13 7 1 16 Address Operations,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-9-14-17-unchecked-conversion}@anchor{232}
+@anchor{gnat_rm/implementation_advice rm-13-9-14-17-unchecked-conversion}@anchor{235}
@section RM 13.9(14-17): Unchecked Conversion
@@ -14366,7 +14420,7 @@ Followed.
@geindex implicit
@node RM 13 11 23-25 Implicit Heap Usage,RM 13 11 2 17 Unchecked Deallocation,RM 13 9 14-17 Unchecked Conversion,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-11-23-25-implicit-heap-usage}@anchor{233}
+@anchor{gnat_rm/implementation_advice rm-13-11-23-25-implicit-heap-usage}@anchor{236}
@section RM 13.11(23-25): Implicit Heap Usage
@@ -14417,7 +14471,7 @@ Followed.
@geindex Unchecked deallocation
@node RM 13 11 2 17 Unchecked Deallocation,RM 13 13 2 1 6 Stream Oriented Attributes,RM 13 11 23-25 Implicit Heap Usage,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-11-2-17-unchecked-deallocation}@anchor{234}
+@anchor{gnat_rm/implementation_advice rm-13-11-2-17-unchecked-deallocation}@anchor{237}
@section RM 13.11.2(17): Unchecked Deallocation
@@ -14432,7 +14486,7 @@ Followed.
@geindex Stream oriented attributes
@node RM 13 13 2 1 6 Stream Oriented Attributes,RM A 1 52 Names of Predefined Numeric Types,RM 13 11 2 17 Unchecked Deallocation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-13-13-2-1-6-stream-oriented-attributes}@anchor{235}
+@anchor{gnat_rm/implementation_advice rm-13-13-2-1-6-stream-oriented-attributes}@anchor{238}
@section RM 13.13.2(1.6): Stream Oriented Attributes
@@ -14463,7 +14517,7 @@ scalar types. This XDR alternative can be enabled via the binder switch -xdr.
@geindex Stream oriented attributes
@node RM A 1 52 Names of Predefined Numeric Types,RM A 3 2 49 Ada Characters Handling,RM 13 13 2 1 6 Stream Oriented Attributes,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-1-52-names-of-predefined-numeric-types}@anchor{236}
+@anchor{gnat_rm/implementation_advice rm-a-1-52-names-of-predefined-numeric-types}@anchor{239}
@section RM A.1(52): Names of Predefined Numeric Types
@@ -14481,7 +14535,7 @@ Followed.
@geindex Ada.Characters.Handling
@node RM A 3 2 49 Ada Characters Handling,RM A 4 4 106 Bounded-Length String Handling,RM A 1 52 Names of Predefined Numeric Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-3-2-49-ada-characters-handling}@anchor{237}
+@anchor{gnat_rm/implementation_advice rm-a-3-2-49-ada-characters-handling}@anchor{23a}
@section RM A.3.2(49): @code{Ada.Characters.Handling}
@@ -14498,7 +14552,7 @@ Followed. GNAT provides no such localized definitions.
@geindex Bounded-length strings
@node RM A 4 4 106 Bounded-Length String Handling,RM A 5 2 46-47 Random Number Generation,RM A 3 2 49 Ada Characters Handling,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-4-4-106-bounded-length-string-handling}@anchor{238}
+@anchor{gnat_rm/implementation_advice rm-a-4-4-106-bounded-length-string-handling}@anchor{23b}
@section RM A.4.4(106): Bounded-Length String Handling
@@ -14513,7 +14567,7 @@ Followed. No implicit pointers or dynamic allocation are used.
@geindex Random number generation
@node RM A 5 2 46-47 Random Number Generation,RM A 10 7 23 Get_Immediate,RM A 4 4 106 Bounded-Length String Handling,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-5-2-46-47-random-number-generation}@anchor{239}
+@anchor{gnat_rm/implementation_advice rm-a-5-2-46-47-random-number-generation}@anchor{23c}
@section RM A.5.2(46-47): Random Number Generation
@@ -14542,7 +14596,7 @@ condition here to hold true.
@geindex Get_Immediate
@node RM A 10 7 23 Get_Immediate,RM B 1 39-41 Pragma Export,RM A 5 2 46-47 Random Number Generation,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-a-10-7-23-get-immediate}@anchor{23a}
+@anchor{gnat_rm/implementation_advice rm-a-10-7-23-get-immediate}@anchor{23d}
@section RM A.10.7(23): @code{Get_Immediate}
@@ -14566,7 +14620,7 @@ this functionality.
@geindex Export
@node RM B 1 39-41 Pragma Export,RM B 2 12-13 Package Interfaces,RM A 10 7 23 Get_Immediate,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-1-39-41-pragma-export}@anchor{23b}
+@anchor{gnat_rm/implementation_advice rm-b-1-39-41-pragma-export}@anchor{23e}
@section RM B.1(39-41): Pragma @code{Export}
@@ -14614,7 +14668,7 @@ Followed.
@geindex Interfaces
@node RM B 2 12-13 Package Interfaces,RM B 3 63-71 Interfacing with C,RM B 1 39-41 Pragma Export,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-2-12-13-package-interfaces}@anchor{23c}
+@anchor{gnat_rm/implementation_advice rm-b-2-12-13-package-interfaces}@anchor{23f}
@section RM B.2(12-13): Package @code{Interfaces}
@@ -14644,7 +14698,7 @@ Followed. GNAT provides all the packages described in this section.
@geindex interfacing with
@node RM B 3 63-71 Interfacing with C,RM B 4 95-98 Interfacing with COBOL,RM B 2 12-13 Package Interfaces,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-3-63-71-interfacing-with-c}@anchor{23d}
+@anchor{gnat_rm/implementation_advice rm-b-3-63-71-interfacing-with-c}@anchor{240}
@section RM B.3(63-71): Interfacing with C
@@ -14732,7 +14786,7 @@ Followed.
@geindex interfacing with
@node RM B 4 95-98 Interfacing with COBOL,RM B 5 22-26 Interfacing with Fortran,RM B 3 63-71 Interfacing with C,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-4-95-98-interfacing-with-cobol}@anchor{23e}
+@anchor{gnat_rm/implementation_advice rm-b-4-95-98-interfacing-with-cobol}@anchor{241}
@section RM B.4(95-98): Interfacing with COBOL
@@ -14773,7 +14827,7 @@ Followed.
@geindex interfacing with
@node RM B 5 22-26 Interfacing with Fortran,RM C 1 3-5 Access to Machine Operations,RM B 4 95-98 Interfacing with COBOL,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-b-5-22-26-interfacing-with-fortran}@anchor{23f}
+@anchor{gnat_rm/implementation_advice rm-b-5-22-26-interfacing-with-fortran}@anchor{242}
@section RM B.5(22-26): Interfacing with Fortran
@@ -14824,7 +14878,7 @@ Followed.
@geindex Machine operations
@node RM C 1 3-5 Access to Machine Operations,RM C 1 10-16 Access to Machine Operations,RM B 5 22-26 Interfacing with Fortran,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-1-3-5-access-to-machine-operations}@anchor{240}
+@anchor{gnat_rm/implementation_advice rm-c-1-3-5-access-to-machine-operations}@anchor{243}
@section RM C.1(3-5): Access to Machine Operations
@@ -14859,7 +14913,7 @@ object that is specified as exported."
Followed.
@node RM C 1 10-16 Access to Machine Operations,RM C 3 28 Interrupt Support,RM C 1 3-5 Access to Machine Operations,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-1-10-16-access-to-machine-operations}@anchor{241}
+@anchor{gnat_rm/implementation_advice rm-c-1-10-16-access-to-machine-operations}@anchor{244}
@section RM C.1(10-16): Access to Machine Operations
@@ -14920,7 +14974,7 @@ Followed on any target supporting such operations.
@geindex Interrupt support
@node RM C 3 28 Interrupt Support,RM C 3 1 20-21 Protected Procedure Handlers,RM C 1 10-16 Access to Machine Operations,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-3-28-interrupt-support}@anchor{242}
+@anchor{gnat_rm/implementation_advice rm-c-3-28-interrupt-support}@anchor{245}
@section RM C.3(28): Interrupt Support
@@ -14938,7 +14992,7 @@ of interrupt blocking.
@geindex Protected procedure handlers
@node RM C 3 1 20-21 Protected Procedure Handlers,RM C 3 2 25 Package Interrupts,RM C 3 28 Interrupt Support,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-3-1-20-21-protected-procedure-handlers}@anchor{243}
+@anchor{gnat_rm/implementation_advice rm-c-3-1-20-21-protected-procedure-handlers}@anchor{246}
@section RM C.3.1(20-21): Protected Procedure Handlers
@@ -14964,7 +15018,7 @@ Followed. Compile time warnings are given when possible.
@geindex Interrupts
@node RM C 3 2 25 Package Interrupts,RM C 4 14 Pre-elaboration Requirements,RM C 3 1 20-21 Protected Procedure Handlers,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-3-2-25-package-interrupts}@anchor{244}
+@anchor{gnat_rm/implementation_advice rm-c-3-2-25-package-interrupts}@anchor{247}
@section RM C.3.2(25): Package @code{Interrupts}
@@ -14982,7 +15036,7 @@ Followed.
@geindex Pre-elaboration requirements
@node RM C 4 14 Pre-elaboration Requirements,RM C 5 8 Pragma Discard_Names,RM C 3 2 25 Package Interrupts,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-4-14-pre-elaboration-requirements}@anchor{245}
+@anchor{gnat_rm/implementation_advice rm-c-4-14-pre-elaboration-requirements}@anchor{248}
@section RM C.4(14): Pre-elaboration Requirements
@@ -14998,7 +15052,7 @@ Followed. Executable code is generated in some cases, e.g., loops
to initialize large arrays.
@node RM C 5 8 Pragma Discard_Names,RM C 7 2 30 The Package Task_Attributes,RM C 4 14 Pre-elaboration Requirements,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-5-8-pragma-discard-names}@anchor{246}
+@anchor{gnat_rm/implementation_advice rm-c-5-8-pragma-discard-names}@anchor{249}
@section RM C.5(8): Pragma @code{Discard_Names}
@@ -15016,7 +15070,7 @@ Followed.
@geindex Task_Attributes
@node RM C 7 2 30 The Package Task_Attributes,RM D 3 17 Locking Policies,RM C 5 8 Pragma Discard_Names,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-c-7-2-30-the-package-task-attributes}@anchor{247}
+@anchor{gnat_rm/implementation_advice rm-c-7-2-30-the-package-task-attributes}@anchor{24a}
@section RM C.7.2(30): The Package Task_Attributes
@@ -15037,7 +15091,7 @@ Not followed. This implementation is not targeted to such a domain.
@geindex Locking Policies
@node RM D 3 17 Locking Policies,RM D 4 16 Entry Queuing Policies,RM C 7 2 30 The Package Task_Attributes,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-3-17-locking-policies}@anchor{248}
+@anchor{gnat_rm/implementation_advice rm-d-3-17-locking-policies}@anchor{24b}
@section RM D.3(17): Locking Policies
@@ -15054,7 +15108,7 @@ whose names (@code{Inheritance_Locking} and
@geindex Entry queuing policies
@node RM D 4 16 Entry Queuing Policies,RM D 6 9-10 Preemptive Abort,RM D 3 17 Locking Policies,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-4-16-entry-queuing-policies}@anchor{249}
+@anchor{gnat_rm/implementation_advice rm-d-4-16-entry-queuing-policies}@anchor{24c}
@section RM D.4(16): Entry Queuing Policies
@@ -15069,7 +15123,7 @@ Followed. No such implementation-defined queuing policies exist.
@geindex Preemptive abort
@node RM D 6 9-10 Preemptive Abort,RM D 7 21 Tasking Restrictions,RM D 4 16 Entry Queuing Policies,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-6-9-10-preemptive-abort}@anchor{24a}
+@anchor{gnat_rm/implementation_advice rm-d-6-9-10-preemptive-abort}@anchor{24d}
@section RM D.6(9-10): Preemptive Abort
@@ -15095,7 +15149,7 @@ Followed.
@geindex Tasking restrictions
@node RM D 7 21 Tasking Restrictions,RM D 8 47-49 Monotonic Time,RM D 6 9-10 Preemptive Abort,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-7-21-tasking-restrictions}@anchor{24b}
+@anchor{gnat_rm/implementation_advice rm-d-7-21-tasking-restrictions}@anchor{24e}
@section RM D.7(21): Tasking Restrictions
@@ -15114,7 +15168,7 @@ pragma @code{Profile (Restricted)} for more details.
@geindex monotonic
@node RM D 8 47-49 Monotonic Time,RM E 5 28-29 Partition Communication Subsystem,RM D 7 21 Tasking Restrictions,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-d-8-47-49-monotonic-time}@anchor{24c}
+@anchor{gnat_rm/implementation_advice rm-d-8-47-49-monotonic-time}@anchor{24f}
@section RM D.8(47-49): Monotonic Time
@@ -15149,7 +15203,7 @@ Followed.
@geindex PCS
@node RM E 5 28-29 Partition Communication Subsystem,RM F 7 COBOL Support,RM D 8 47-49 Monotonic Time,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-e-5-28-29-partition-communication-subsystem}@anchor{24d}
+@anchor{gnat_rm/implementation_advice rm-e-5-28-29-partition-communication-subsystem}@anchor{250}
@section RM E.5(28-29): Partition Communication Subsystem
@@ -15177,7 +15231,7 @@ GNAT.
@geindex COBOL support
@node RM F 7 COBOL Support,RM F 1 2 Decimal Radix Support,RM E 5 28-29 Partition Communication Subsystem,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-f-7-cobol-support}@anchor{24e}
+@anchor{gnat_rm/implementation_advice rm-f-7-cobol-support}@anchor{251}
@section RM F(7): COBOL Support
@@ -15197,7 +15251,7 @@ Followed.
@geindex Decimal radix support
@node RM F 1 2 Decimal Radix Support,RM G Numerics,RM F 7 COBOL Support,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-f-1-2-decimal-radix-support}@anchor{24f}
+@anchor{gnat_rm/implementation_advice rm-f-1-2-decimal-radix-support}@anchor{252}
@section RM F.1(2): Decimal Radix Support
@@ -15213,7 +15267,7 @@ representations.
@geindex Numerics
@node RM G Numerics,RM G 1 1 56-58 Complex Types,RM F 1 2 Decimal Radix Support,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-numerics}@anchor{250}
+@anchor{gnat_rm/implementation_advice rm-g-numerics}@anchor{253}
@section RM G: Numerics
@@ -15233,7 +15287,7 @@ Followed.
@geindex Complex types
@node RM G 1 1 56-58 Complex Types,RM G 1 2 49 Complex Elementary Functions,RM G Numerics,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-1-1-56-58-complex-types}@anchor{251}
+@anchor{gnat_rm/implementation_advice rm-g-1-1-56-58-complex-types}@anchor{254}
@section RM G.1.1(56-58): Complex Types
@@ -15295,7 +15349,7 @@ Followed.
@geindex Complex elementary functions
@node RM G 1 2 49 Complex Elementary Functions,RM G 2 4 19 Accuracy Requirements,RM G 1 1 56-58 Complex Types,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-1-2-49-complex-elementary-functions}@anchor{252}
+@anchor{gnat_rm/implementation_advice rm-g-1-2-49-complex-elementary-functions}@anchor{255}
@section RM G.1.2(49): Complex Elementary Functions
@@ -15317,7 +15371,7 @@ Followed.
@geindex Accuracy requirements
@node RM G 2 4 19 Accuracy Requirements,RM G 2 6 15 Complex Arithmetic Accuracy,RM G 1 2 49 Complex Elementary Functions,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-2-4-19-accuracy-requirements}@anchor{253}
+@anchor{gnat_rm/implementation_advice rm-g-2-4-19-accuracy-requirements}@anchor{256}
@section RM G.2.4(19): Accuracy Requirements
@@ -15341,7 +15395,7 @@ Followed.
@geindex complex arithmetic
@node RM G 2 6 15 Complex Arithmetic Accuracy,RM H 6 15/2 Pragma Partition_Elaboration_Policy,RM G 2 4 19 Accuracy Requirements,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-g-2-6-15-complex-arithmetic-accuracy}@anchor{254}
+@anchor{gnat_rm/implementation_advice rm-g-2-6-15-complex-arithmetic-accuracy}@anchor{257}
@section RM G.2.6(15): Complex Arithmetic Accuracy
@@ -15359,7 +15413,7 @@ Followed.
@geindex Sequential elaboration policy
@node RM H 6 15/2 Pragma Partition_Elaboration_Policy,,RM G 2 6 15 Complex Arithmetic Accuracy,Implementation Advice
-@anchor{gnat_rm/implementation_advice rm-h-6-15-2-pragma-partition-elaboration-policy}@anchor{255}
+@anchor{gnat_rm/implementation_advice rm-h-6-15-2-pragma-partition-elaboration-policy}@anchor{258}
@section RM H.6(15/2): Pragma Partition_Elaboration_Policy
@@ -15374,7 +15428,7 @@ immediately terminated."
Not followed.
@node Implementation Defined Characteristics,Intrinsic Subprograms,Implementation Advice,Top
-@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{256}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{257}
+@anchor{gnat_rm/implementation_defined_characteristics implementation-defined-characteristics}@anchor{b}@anchor{gnat_rm/implementation_defined_characteristics doc}@anchor{259}@anchor{gnat_rm/implementation_defined_characteristics id1}@anchor{25a}
@chapter Implementation Defined Characteristics
@@ -15675,7 +15729,7 @@ Representation
"The small of an ordinary fixed point type. See 3.5.9(8)."
@end itemize
-@code{Fine_Delta} is 2**(-63)
+The small is the largest power of two that does not exceed the delta.
@itemize *
@@ -15685,12 +15739,27 @@ Representation
supported for fixed point types. See 3.5.9(10)."
@end itemize
-Any combinations are permitted that do not result in a small less than
-@code{Fine_Delta} and do not result in a mantissa larger than 63 bits.
-If the mantissa is larger than 53 bits on machines where Long_Long_Float
-is 64 bits (true of all architectures except x86), then the output from
-Text_IO is accurate to only 53 bits, rather than the full mantissa. This
-is because floating-point conversions are used to convert fixed point.
+For an ordinary fixed point type, on 32-bit platforms, the small must lie in
+2.0**(-80) .. 2.0**80 and the range in -9.0E+36 .. 9.0E+36; any combination
+is permitted that does not result in a mantissa larger than 63 bits.
+
+On 64-bit platforms, the small must lie in 2.0**(-127) .. 2.0**127 and the
+range in -1.0E+76 .. 1.0E+76; any combination is permitted that does not
+result in a mantissa larger than 63 bits, and any combination is permitted
+that results in a mantissa between 64 and 127 bits if the small is the
+ratio of two integers that lie in 1 .. 2.0**127.
+
+If the small is the ratio of two integers with 64-bit magnitude on 32-bit
+platforms and 128-bit magnitude on 64-bit platforms, which is the case if
+no @code{small} clause is provided, then the operations of the fixed point
+type are entirely implemented by means of integer instructions. In the
+other cases, some operations, in particular input and output, may be
+implemented by means of floating-point instructions and may be affected
+by accuracy issues on architectures other than x86.
+
+For a decimal fixed point type, on 32-bit platforms, the small must lie in
+1.0E-18 .. 1.0E+18 and the digits in 1 .. 18. On 64-bit platforms, the
+small must lie in 1.0E-38 .. 1.0E+38 and the digits in 1 .. 38.
@itemize *
@@ -16578,7 +16647,7 @@ When the @code{Pattern} parameter is not the null string, it is interpreted
according to the syntax of regular expressions as defined in the
@code{GNAT.Regexp} package.
-See @ref{258,,GNAT.Regexp (g-regexp.ads)}.
+See @ref{25b,,GNAT.Regexp (g-regexp.ads)}.
@itemize *
@@ -17626,7 +17695,7 @@ H.4(27)."
There are no restrictions on pragma @code{Restrictions}.
@node Intrinsic Subprograms,Representation Clauses and Pragmas,Implementation Defined Characteristics,Top
-@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{259}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25a}
+@anchor{gnat_rm/intrinsic_subprograms doc}@anchor{25c}@anchor{gnat_rm/intrinsic_subprograms intrinsic-subprograms}@anchor{c}@anchor{gnat_rm/intrinsic_subprograms id1}@anchor{25d}
@chapter Intrinsic Subprograms
@@ -17664,7 +17733,7 @@ Ada standard does not require Ada compilers to implement this feature.
@end menu
@node Intrinsic Operators,Compilation_ISO_Date,,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id2}@anchor{25b}@anchor{gnat_rm/intrinsic_subprograms intrinsic-operators}@anchor{25c}
+@anchor{gnat_rm/intrinsic_subprograms id2}@anchor{25e}@anchor{gnat_rm/intrinsic_subprograms intrinsic-operators}@anchor{25f}
@section Intrinsic Operators
@@ -17695,7 +17764,7 @@ It is also possible to specify such operators for private types, if the
full views are appropriate arithmetic types.
@node Compilation_ISO_Date,Compilation_Date,Intrinsic Operators,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{25d}@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{25e}
+@anchor{gnat_rm/intrinsic_subprograms id3}@anchor{260}@anchor{gnat_rm/intrinsic_subprograms compilation-iso-date}@anchor{261}
@section Compilation_ISO_Date
@@ -17709,7 +17778,7 @@ application program should simply call the function
the current compilation (in local time format YYYY-MM-DD).
@node Compilation_Date,Compilation_Time,Compilation_ISO_Date,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms compilation-date}@anchor{25f}@anchor{gnat_rm/intrinsic_subprograms id4}@anchor{260}
+@anchor{gnat_rm/intrinsic_subprograms compilation-date}@anchor{262}@anchor{gnat_rm/intrinsic_subprograms id4}@anchor{263}
@section Compilation_Date
@@ -17719,7 +17788,7 @@ Same as Compilation_ISO_Date, except the string is in the form
MMM DD YYYY.
@node Compilation_Time,Enclosing_Entity,Compilation_Date,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms compilation-time}@anchor{261}@anchor{gnat_rm/intrinsic_subprograms id5}@anchor{262}
+@anchor{gnat_rm/intrinsic_subprograms compilation-time}@anchor{264}@anchor{gnat_rm/intrinsic_subprograms id5}@anchor{265}
@section Compilation_Time
@@ -17733,7 +17802,7 @@ application program should simply call the function
the current compilation (in local time format HH:MM:SS).
@node Enclosing_Entity,Exception_Information,Compilation_Time,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{263}@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{264}
+@anchor{gnat_rm/intrinsic_subprograms id6}@anchor{266}@anchor{gnat_rm/intrinsic_subprograms enclosing-entity}@anchor{267}
@section Enclosing_Entity
@@ -17747,7 +17816,7 @@ application program should simply call the function
the current subprogram, package, task, entry, or protected subprogram.
@node Exception_Information,Exception_Message,Enclosing_Entity,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{265}@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{266}
+@anchor{gnat_rm/intrinsic_subprograms id7}@anchor{268}@anchor{gnat_rm/intrinsic_subprograms exception-information}@anchor{269}
@section Exception_Information
@@ -17761,7 +17830,7 @@ so an application program should simply call the function
the exception information associated with the current exception.
@node Exception_Message,Exception_Name,Exception_Information,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms exception-message}@anchor{267}@anchor{gnat_rm/intrinsic_subprograms id8}@anchor{268}
+@anchor{gnat_rm/intrinsic_subprograms exception-message}@anchor{26a}@anchor{gnat_rm/intrinsic_subprograms id8}@anchor{26b}
@section Exception_Message
@@ -17775,7 +17844,7 @@ so an application program should simply call the function
the message associated with the current exception.
@node Exception_Name,File,Exception_Message,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms exception-name}@anchor{269}@anchor{gnat_rm/intrinsic_subprograms id9}@anchor{26a}
+@anchor{gnat_rm/intrinsic_subprograms exception-name}@anchor{26c}@anchor{gnat_rm/intrinsic_subprograms id9}@anchor{26d}
@section Exception_Name
@@ -17789,7 +17858,7 @@ so an application program should simply call the function
the name of the current exception.
@node File,Line,Exception_Name,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{26b}@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26c}
+@anchor{gnat_rm/intrinsic_subprograms id10}@anchor{26e}@anchor{gnat_rm/intrinsic_subprograms file}@anchor{26f}
@section File
@@ -17803,7 +17872,7 @@ application program should simply call the function
file.
@node Line,Shifts and Rotates,File,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms id11}@anchor{26d}@anchor{gnat_rm/intrinsic_subprograms line}@anchor{26e}
+@anchor{gnat_rm/intrinsic_subprograms id11}@anchor{270}@anchor{gnat_rm/intrinsic_subprograms line}@anchor{271}
@section Line
@@ -17817,7 +17886,7 @@ application program should simply call the function
source line.
@node Shifts and Rotates,Source_Location,Line,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{26f}@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{270}
+@anchor{gnat_rm/intrinsic_subprograms shifts-and-rotates}@anchor{272}@anchor{gnat_rm/intrinsic_subprograms id12}@anchor{273}
@section Shifts and Rotates
@@ -17853,10 +17922,12 @@ The formal parameter names can be anything.
A more convenient way of providing these shift operators is to use
the Provide_Shift_Operators pragma, which provides the function declarations
-and corresponding pragma Import's for all five shift functions.
+and corresponding pragma Import's for all five shift functions. Note that in
+using these provided shift operations, shifts performed on negative numbers
+will result in modification of the sign bit.
@node Source_Location,,Shifts and Rotates,Intrinsic Subprograms
-@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{272}
+@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{274}@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{275}
@section Source_Location
@@ -17870,7 +17941,7 @@ application program should simply call the function
source file location.
@node Representation Clauses and Pragmas,Standard Library Routines,Intrinsic Subprograms,Top
-@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{273}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{274}
+@anchor{gnat_rm/representation_clauses_and_pragmas representation-clauses-and-pragmas}@anchor{d}@anchor{gnat_rm/representation_clauses_and_pragmas doc}@anchor{276}@anchor{gnat_rm/representation_clauses_and_pragmas id1}@anchor{277}
@chapter Representation Clauses and Pragmas
@@ -17916,7 +17987,7 @@ and this section describes the additional capabilities provided.
@end menu
@node Alignment Clauses,Size Clauses,,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{275}@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{276}
+@anchor{gnat_rm/representation_clauses_and_pragmas id2}@anchor{278}@anchor{gnat_rm/representation_clauses_and_pragmas alignment-clauses}@anchor{279}
@section Alignment Clauses
@@ -17938,7 +18009,7 @@ For elementary types, the alignment is the minimum of the actual size of
objects of the type divided by @code{Storage_Unit},
and the maximum alignment supported by the target.
(This maximum alignment is given by the GNAT-specific attribute
-@code{Standard'Maximum_Alignment}; see @ref{18f,,Attribute Maximum_Alignment}.)
+@code{Standard'Maximum_Alignment}; see @ref{190,,Attribute Maximum_Alignment}.)
@geindex Maximum_Alignment attribute
@@ -18047,7 +18118,7 @@ assumption is non-portable, and other compilers may choose different
alignments for the subtype @code{RS}.
@node Size Clauses,Storage_Size Clauses,Alignment Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id3}@anchor{277}@anchor{gnat_rm/representation_clauses_and_pragmas size-clauses}@anchor{278}
+@anchor{gnat_rm/representation_clauses_and_pragmas id3}@anchor{27a}@anchor{gnat_rm/representation_clauses_and_pragmas size-clauses}@anchor{27b}
@section Size Clauses
@@ -18124,7 +18195,7 @@ if it is known that a Size value can be accommodated in an object of
type Integer.
@node Storage_Size Clauses,Size of Variant Record Objects,Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{279}@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27a}
+@anchor{gnat_rm/representation_clauses_and_pragmas storage-size-clauses}@anchor{27c}@anchor{gnat_rm/representation_clauses_and_pragmas id4}@anchor{27d}
@section Storage_Size Clauses
@@ -18197,7 +18268,7 @@ Of course in practice, there will not be any explicit allocators in the
case of such an access declaration.
@node Size of Variant Record Objects,Biased Representation,Storage_Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id5}@anchor{27b}@anchor{gnat_rm/representation_clauses_and_pragmas size-of-variant-record-objects}@anchor{27c}
+@anchor{gnat_rm/representation_clauses_and_pragmas id5}@anchor{27e}@anchor{gnat_rm/representation_clauses_and_pragmas size-of-variant-record-objects}@anchor{27f}
@section Size of Variant Record Objects
@@ -18307,7 +18378,7 @@ the maximum size, regardless of the current variant value, the
variant value.
@node Biased Representation,Value_Size and Object_Size Clauses,Size of Variant Record Objects,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{27d}@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{27e}
+@anchor{gnat_rm/representation_clauses_and_pragmas id6}@anchor{280}@anchor{gnat_rm/representation_clauses_and_pragmas biased-representation}@anchor{281}
@section Biased Representation
@@ -18345,7 +18416,7 @@ biased representation can be used for all discrete types except for
enumeration types for which a representation clause is given.
@node Value_Size and Object_Size Clauses,Component_Size Clauses,Biased Representation,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id7}@anchor{27f}@anchor{gnat_rm/representation_clauses_and_pragmas value-size-and-object-size-clauses}@anchor{280}
+@anchor{gnat_rm/representation_clauses_and_pragmas id7}@anchor{282}@anchor{gnat_rm/representation_clauses_and_pragmas value-size-and-object-size-clauses}@anchor{283}
@section Value_Size and Object_Size Clauses
@@ -18661,7 +18732,7 @@ definition clause forces biased representation. This
warning can be turned off using @code{-gnatw.B}.
@node Component_Size Clauses,Bit_Order Clauses,Value_Size and Object_Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{281}@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{282}
+@anchor{gnat_rm/representation_clauses_and_pragmas id8}@anchor{284}@anchor{gnat_rm/representation_clauses_and_pragmas component-size-clauses}@anchor{285}
@section Component_Size Clauses
@@ -18709,7 +18780,7 @@ and a pragma Pack for the same array type. if such duplicate
clauses are given, the pragma Pack will be ignored.
@node Bit_Order Clauses,Effect of Bit_Order on Byte Ordering,Component_Size Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas bit-order-clauses}@anchor{283}@anchor{gnat_rm/representation_clauses_and_pragmas id9}@anchor{284}
+@anchor{gnat_rm/representation_clauses_and_pragmas bit-order-clauses}@anchor{286}@anchor{gnat_rm/representation_clauses_and_pragmas id9}@anchor{287}
@section Bit_Order Clauses
@@ -18815,7 +18886,7 @@ if desired. The following section contains additional
details regarding the issue of byte ordering.
@node Effect of Bit_Order on Byte Ordering,Pragma Pack for Arrays,Bit_Order Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{285}@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-bit-order-on-byte-ordering}@anchor{286}
+@anchor{gnat_rm/representation_clauses_and_pragmas id10}@anchor{288}@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-bit-order-on-byte-ordering}@anchor{289}
@section Effect of Bit_Order on Byte Ordering
@@ -19072,7 +19143,7 @@ to set the boolean constant @code{Master_Byte_First} in
an appropriate manner.
@node Pragma Pack for Arrays,Pragma Pack for Records,Effect of Bit_Order on Byte Ordering,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{287}@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{288}
+@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-arrays}@anchor{28a}@anchor{gnat_rm/representation_clauses_and_pragmas id11}@anchor{28b}
@section Pragma Pack for Arrays
@@ -19192,7 +19263,7 @@ Here 31-bit packing is achieved as required, and no warning is generated,
since in this case the programmer intention is clear.
@node Pragma Pack for Records,Record Representation Clauses,Pragma Pack for Arrays,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{289}@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28a}
+@anchor{gnat_rm/representation_clauses_and_pragmas pragma-pack-for-records}@anchor{28c}@anchor{gnat_rm/representation_clauses_and_pragmas id12}@anchor{28d}
@section Pragma Pack for Records
@@ -19276,7 +19347,7 @@ array that is longer than 64 bits, so it is itself non-packable on
boundary, and takes an integral number of bytes, i.e., 72 bits.
@node Record Representation Clauses,Handling of Records with Holes,Pragma Pack for Records,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id13}@anchor{28b}@anchor{gnat_rm/representation_clauses_and_pragmas record-representation-clauses}@anchor{28c}
+@anchor{gnat_rm/representation_clauses_and_pragmas id13}@anchor{28e}@anchor{gnat_rm/representation_clauses_and_pragmas record-representation-clauses}@anchor{28f}
@section Record Representation Clauses
@@ -19355,7 +19426,7 @@ end record;
@end example
@node Handling of Records with Holes,Enumeration Clauses,Record Representation Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas handling-of-records-with-holes}@anchor{28d}@anchor{gnat_rm/representation_clauses_and_pragmas id14}@anchor{28e}
+@anchor{gnat_rm/representation_clauses_and_pragmas handling-of-records-with-holes}@anchor{290}@anchor{gnat_rm/representation_clauses_and_pragmas id14}@anchor{291}
@section Handling of Records with Holes
@@ -19431,7 +19502,7 @@ for Hrec'Size use 64;
@end example
@node Enumeration Clauses,Address Clauses,Handling of Records with Holes,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas enumeration-clauses}@anchor{28f}@anchor{gnat_rm/representation_clauses_and_pragmas id15}@anchor{290}
+@anchor{gnat_rm/representation_clauses_and_pragmas enumeration-clauses}@anchor{292}@anchor{gnat_rm/representation_clauses_and_pragmas id15}@anchor{293}
@section Enumeration Clauses
@@ -19474,7 +19545,7 @@ the overhead of converting representation values to the corresponding
positional values, (i.e., the value delivered by the @code{Pos} attribute).
@node Address Clauses,Use of Address Clauses for Memory-Mapped I/O,Enumeration Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{291}@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{292}
+@anchor{gnat_rm/representation_clauses_and_pragmas id16}@anchor{294}@anchor{gnat_rm/representation_clauses_and_pragmas address-clauses}@anchor{295}
@section Address Clauses
@@ -19803,7 +19874,7 @@ then the program compiles without the warning and when run will generate
the output @code{X was not clobbered}.
@node Use of Address Clauses for Memory-Mapped I/O,Effect of Convention on Representation,Address Clauses,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id17}@anchor{293}@anchor{gnat_rm/representation_clauses_and_pragmas use-of-address-clauses-for-memory-mapped-i-o}@anchor{294}
+@anchor{gnat_rm/representation_clauses_and_pragmas id17}@anchor{296}@anchor{gnat_rm/representation_clauses_and_pragmas use-of-address-clauses-for-memory-mapped-i-o}@anchor{297}
@section Use of Address Clauses for Memory-Mapped I/O
@@ -19861,7 +19932,7 @@ provides the pragma @code{Volatile_Full_Access} which can be used in lieu of
pragma @code{Atomic} and will give the additional guarantee.
@node Effect of Convention on Representation,Conventions and Anonymous Access Types,Use of Address Clauses for Memory-Mapped I/O,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{295}@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{296}
+@anchor{gnat_rm/representation_clauses_and_pragmas id18}@anchor{298}@anchor{gnat_rm/representation_clauses_and_pragmas effect-of-convention-on-representation}@anchor{299}
@section Effect of Convention on Representation
@@ -19939,7 +20010,7 @@ when one of these values is read, any nonzero value is treated as True.
@end itemize
@node Conventions and Anonymous Access Types,Determining the Representations chosen by GNAT,Effect of Convention on Representation,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas conventions-and-anonymous-access-types}@anchor{297}@anchor{gnat_rm/representation_clauses_and_pragmas id19}@anchor{298}
+@anchor{gnat_rm/representation_clauses_and_pragmas conventions-and-anonymous-access-types}@anchor{29a}@anchor{gnat_rm/representation_clauses_and_pragmas id19}@anchor{29b}
@section Conventions and Anonymous Access Types
@@ -20015,7 +20086,7 @@ package ConvComp is
@end example
@node Determining the Representations chosen by GNAT,,Conventions and Anonymous Access Types,Representation Clauses and Pragmas
-@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{299}@anchor{gnat_rm/representation_clauses_and_pragmas determining-the-representations-chosen-by-gnat}@anchor{29a}
+@anchor{gnat_rm/representation_clauses_and_pragmas id20}@anchor{29c}@anchor{gnat_rm/representation_clauses_and_pragmas determining-the-representations-chosen-by-gnat}@anchor{29d}
@section Determining the Representations chosen by GNAT
@@ -20167,7 +20238,7 @@ generated by the compiler into the original source to fix and guarantee
the actual representation to be used.
@node Standard Library Routines,The Implementation of Standard I/O,Representation Clauses and Pragmas,Top
-@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}@anchor{gnat_rm/standard_library_routines doc}@anchor{29b}@anchor{gnat_rm/standard_library_routines id1}@anchor{29c}
+@anchor{gnat_rm/standard_library_routines standard-library-routines}@anchor{e}@anchor{gnat_rm/standard_library_routines doc}@anchor{29e}@anchor{gnat_rm/standard_library_routines id1}@anchor{29f}
@chapter Standard Library Routines
@@ -20991,7 +21062,7 @@ For packages in Interfaces and System, all the RM defined packages are
available in GNAT, see the Ada 2012 RM for full details.
@node The Implementation of Standard I/O,The GNAT Library,Standard Library Routines,Top
-@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f}@anchor{gnat_rm/the_implementation_of_standard_i_o doc}@anchor{29d}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{29e}
+@anchor{gnat_rm/the_implementation_of_standard_i_o the-implementation-of-standard-i-o}@anchor{f}@anchor{gnat_rm/the_implementation_of_standard_i_o doc}@anchor{2a0}@anchor{gnat_rm/the_implementation_of_standard_i_o id1}@anchor{2a1}
@chapter The Implementation of Standard I/O
@@ -21043,7 +21114,7 @@ these additional facilities are also described in this chapter.
@end menu
@node Standard I/O Packages,FORM Strings,,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{29f}@anchor{gnat_rm/the_implementation_of_standard_i_o id2}@anchor{2a0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o standard-i-o-packages}@anchor{2a2}@anchor{gnat_rm/the_implementation_of_standard_i_o id2}@anchor{2a3}
@section Standard I/O Packages
@@ -21114,7 +21185,7 @@ flush the common I/O streams and in particular Standard_Output before
elaborating the Ada code.
@node FORM Strings,Direct_IO,Standard I/O Packages,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o form-strings}@anchor{2a1}@anchor{gnat_rm/the_implementation_of_standard_i_o id3}@anchor{2a2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o form-strings}@anchor{2a4}@anchor{gnat_rm/the_implementation_of_standard_i_o id3}@anchor{2a5}
@section FORM Strings
@@ -21140,7 +21211,7 @@ unrecognized keyword appears in a form string, it is silently ignored
and not considered invalid.
@node Direct_IO,Sequential_IO,FORM Strings,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o direct-io}@anchor{2a3}@anchor{gnat_rm/the_implementation_of_standard_i_o id4}@anchor{2a4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o direct-io}@anchor{2a6}@anchor{gnat_rm/the_implementation_of_standard_i_o id4}@anchor{2a7}
@section Direct_IO
@@ -21160,7 +21231,7 @@ There is no limit on the size of Direct_IO files, they are expanded as
necessary to accommodate whatever records are written to the file.
@node Sequential_IO,Text_IO,Direct_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2a5}@anchor{gnat_rm/the_implementation_of_standard_i_o id5}@anchor{2a6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o sequential-io}@anchor{2a8}@anchor{gnat_rm/the_implementation_of_standard_i_o id5}@anchor{2a9}
@section Sequential_IO
@@ -21207,7 +21278,7 @@ using Stream_IO, and this is the preferred mechanism. In particular, the
above program fragment rewritten to use Stream_IO will work correctly.
@node Text_IO,Wide_Text_IO,Sequential_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id6}@anchor{2a7}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io}@anchor{2a8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id6}@anchor{2aa}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io}@anchor{2ab}
@section Text_IO
@@ -21290,7 +21361,7 @@ the file.
@end menu
@node Stream Pointer Positioning,Reading and Writing Non-Regular Files,,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id7}@anchor{2a9}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning}@anchor{2aa}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id7}@anchor{2ac}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning}@anchor{2ad}
@subsection Stream Pointer Positioning
@@ -21326,7 +21397,7 @@ between two Ada files, then the difference may be observable in some
situations.
@node Reading and Writing Non-Regular Files,Get_Immediate,Stream Pointer Positioning,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2ab}@anchor{gnat_rm/the_implementation_of_standard_i_o id8}@anchor{2ac}
+@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files}@anchor{2ae}@anchor{gnat_rm/the_implementation_of_standard_i_o id8}@anchor{2af}
@subsection Reading and Writing Non-Regular Files
@@ -21377,7 +21448,7 @@ to read data past that end of
file indication, until another end of file indication is entered.
@node Get_Immediate,Treating Text_IO Files as Streams,Reading and Writing Non-Regular Files,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o get-immediate}@anchor{2ad}@anchor{gnat_rm/the_implementation_of_standard_i_o id9}@anchor{2ae}
+@anchor{gnat_rm/the_implementation_of_standard_i_o get-immediate}@anchor{2b0}@anchor{gnat_rm/the_implementation_of_standard_i_o id9}@anchor{2b1}
@subsection Get_Immediate
@@ -21395,7 +21466,7 @@ possible), it is undefined whether the FF character will be treated as a
page mark.
@node Treating Text_IO Files as Streams,Text_IO Extensions,Get_Immediate,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id10}@anchor{2af}@anchor{gnat_rm/the_implementation_of_standard_i_o treating-text-io-files-as-streams}@anchor{2b0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id10}@anchor{2b2}@anchor{gnat_rm/the_implementation_of_standard_i_o treating-text-io-files-as-streams}@anchor{2b3}
@subsection Treating Text_IO Files as Streams
@@ -21411,7 +21482,7 @@ skipped and the effect is similar to that described above for
@code{Get_Immediate}.
@node Text_IO Extensions,Text_IO Facilities for Unbounded Strings,Treating Text_IO Files as Streams,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id11}@anchor{2b1}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-extensions}@anchor{2b2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id11}@anchor{2b4}@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-extensions}@anchor{2b5}
@subsection Text_IO Extensions
@@ -21439,7 +21510,7 @@ the string is to be read.
@end itemize
@node Text_IO Facilities for Unbounded Strings,,Text_IO Extensions,Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b3}@anchor{gnat_rm/the_implementation_of_standard_i_o id12}@anchor{2b4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o text-io-facilities-for-unbounded-strings}@anchor{2b6}@anchor{gnat_rm/the_implementation_of_standard_i_o id12}@anchor{2b7}
@subsection Text_IO Facilities for Unbounded Strings
@@ -21487,7 +21558,7 @@ files @code{a-szuzti.ads} and @code{a-szuzti.adb} provides similar extended
@code{Wide_Wide_Text_IO} functionality for unbounded wide wide strings.
@node Wide_Text_IO,Wide_Wide_Text_IO,Text_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2b5}@anchor{gnat_rm/the_implementation_of_standard_i_o id13}@anchor{2b6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o wide-text-io}@anchor{2b8}@anchor{gnat_rm/the_implementation_of_standard_i_o id13}@anchor{2b9}
@section Wide_Text_IO
@@ -21734,12 +21805,12 @@ input also causes Constraint_Error to be raised.
@end menu
@node Stream Pointer Positioning<2>,Reading and Writing Non-Regular Files<2>,,Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2b7}@anchor{gnat_rm/the_implementation_of_standard_i_o id14}@anchor{2b8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-1}@anchor{2ba}@anchor{gnat_rm/the_implementation_of_standard_i_o id14}@anchor{2bb}
@subsection Stream Pointer Positioning
@code{Ada.Wide_Text_IO} is similar to @code{Ada.Text_IO} in its handling
-of stream pointer positioning (@ref{2a8,,Text_IO}). There is one additional
+of stream pointer positioning (@ref{2ab,,Text_IO}). There is one additional
case:
If @code{Ada.Wide_Text_IO.Look_Ahead} reads a character outside the
@@ -21758,7 +21829,7 @@ to a normal program using @code{Wide_Text_IO}. However, this discrepancy
can be observed if the wide text file shares a stream with another file.
@node Reading and Writing Non-Regular Files<2>,,Stream Pointer Positioning<2>,Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2b9}@anchor{gnat_rm/the_implementation_of_standard_i_o id15}@anchor{2ba}
+@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-1}@anchor{2bc}@anchor{gnat_rm/the_implementation_of_standard_i_o id15}@anchor{2bd}
@subsection Reading and Writing Non-Regular Files
@@ -21769,7 +21840,7 @@ treated as data characters), and @code{End_Of_Page} always returns
it is possible to read beyond an end of file.
@node Wide_Wide_Text_IO,Stream_IO,Wide_Text_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id16}@anchor{2bb}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-wide-text-io}@anchor{2bc}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id16}@anchor{2be}@anchor{gnat_rm/the_implementation_of_standard_i_o wide-wide-text-io}@anchor{2bf}
@section Wide_Wide_Text_IO
@@ -21938,12 +22009,12 @@ input also causes Constraint_Error to be raised.
@end menu
@node Stream Pointer Positioning<3>,Reading and Writing Non-Regular Files<3>,,Wide_Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2bd}@anchor{gnat_rm/the_implementation_of_standard_i_o id17}@anchor{2be}
+@anchor{gnat_rm/the_implementation_of_standard_i_o stream-pointer-positioning-2}@anchor{2c0}@anchor{gnat_rm/the_implementation_of_standard_i_o id17}@anchor{2c1}
@subsection Stream Pointer Positioning
@code{Ada.Wide_Wide_Text_IO} is similar to @code{Ada.Text_IO} in its handling
-of stream pointer positioning (@ref{2a8,,Text_IO}). There is one additional
+of stream pointer positioning (@ref{2ab,,Text_IO}). There is one additional
case:
If @code{Ada.Wide_Wide_Text_IO.Look_Ahead} reads a character outside the
@@ -21962,7 +22033,7 @@ to a normal program using @code{Wide_Wide_Text_IO}. However, this discrepancy
can be observed if the wide text file shares a stream with another file.
@node Reading and Writing Non-Regular Files<3>,,Stream Pointer Positioning<3>,Wide_Wide_Text_IO
-@anchor{gnat_rm/the_implementation_of_standard_i_o id18}@anchor{2bf}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-2}@anchor{2c0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id18}@anchor{2c2}@anchor{gnat_rm/the_implementation_of_standard_i_o reading-and-writing-non-regular-files-2}@anchor{2c3}
@subsection Reading and Writing Non-Regular Files
@@ -21973,7 +22044,7 @@ treated as data characters), and @code{End_Of_Page} always returns
it is possible to read beyond an end of file.
@node Stream_IO,Text Translation,Wide_Wide_Text_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id19}@anchor{2c1}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-io}@anchor{2c2}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id19}@anchor{2c4}@anchor{gnat_rm/the_implementation_of_standard_i_o stream-io}@anchor{2c5}
@section Stream_IO
@@ -21995,7 +22066,7 @@ manner described for stream attributes.
@end itemize
@node Text Translation,Shared Files,Stream_IO,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id20}@anchor{2c3}@anchor{gnat_rm/the_implementation_of_standard_i_o text-translation}@anchor{2c4}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id20}@anchor{2c6}@anchor{gnat_rm/the_implementation_of_standard_i_o text-translation}@anchor{2c7}
@section Text Translation
@@ -22029,7 +22100,7 @@ mode. (corresponds to_O_U16TEXT).
@end itemize
@node Shared Files,Filenames encoding,Text Translation,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o id21}@anchor{2c5}@anchor{gnat_rm/the_implementation_of_standard_i_o shared-files}@anchor{2c6}
+@anchor{gnat_rm/the_implementation_of_standard_i_o id21}@anchor{2c8}@anchor{gnat_rm/the_implementation_of_standard_i_o shared-files}@anchor{2c9}
@section Shared Files
@@ -22092,7 +22163,7 @@ heterogeneous input-output. Although this approach will work in GNAT if
for this purpose (using the stream attributes)
@node Filenames encoding,File content encoding,Shared Files,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o filenames-encoding}@anchor{2c7}@anchor{gnat_rm/the_implementation_of_standard_i_o id22}@anchor{2c8}
+@anchor{gnat_rm/the_implementation_of_standard_i_o filenames-encoding}@anchor{2ca}@anchor{gnat_rm/the_implementation_of_standard_i_o id22}@anchor{2cb}
@section Filenames encoding
@@ -22132,7 +22203,7 @@ platform. On the other Operating Systems the run-time is supporting
UTF-8 natively.
@node File content encoding,Open Modes,Filenames encoding,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o file-content-encoding}@anchor{2c9}@anchor{gnat_rm/the_implementation_of_standard_i_o id23}@anchor{2ca}
+@anchor{gnat_rm/the_implementation_of_standard_i_o file-content-encoding}@anchor{2cc}@anchor{gnat_rm/the_implementation_of_standard_i_o id23}@anchor{2cd}
@section File content encoding
@@ -22165,7 +22236,7 @@ Unicode 8-bit encoding
This encoding is only supported on the Windows platform.
@node Open Modes,Operations on C Streams,File content encoding,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2cb}@anchor{gnat_rm/the_implementation_of_standard_i_o id24}@anchor{2cc}
+@anchor{gnat_rm/the_implementation_of_standard_i_o open-modes}@anchor{2ce}@anchor{gnat_rm/the_implementation_of_standard_i_o id24}@anchor{2cf}
@section Open Modes
@@ -22268,7 +22339,7 @@ subsequently requires switching from reading to writing or vice-versa,
then the file is reopened in @code{r+} mode to permit the required operation.
@node Operations on C Streams,Interfacing to C Streams,Open Modes,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2cd}@anchor{gnat_rm/the_implementation_of_standard_i_o id25}@anchor{2ce}
+@anchor{gnat_rm/the_implementation_of_standard_i_o operations-on-c-streams}@anchor{2d0}@anchor{gnat_rm/the_implementation_of_standard_i_o id25}@anchor{2d1}
@section Operations on C Streams
@@ -22428,7 +22499,7 @@ end Interfaces.C_Streams;
@end example
@node Interfacing to C Streams,,Operations on C Streams,The Implementation of Standard I/O
-@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2cf}@anchor{gnat_rm/the_implementation_of_standard_i_o id26}@anchor{2d0}
+@anchor{gnat_rm/the_implementation_of_standard_i_o interfacing-to-c-streams}@anchor{2d2}@anchor{gnat_rm/the_implementation_of_standard_i_o id26}@anchor{2d3}
@section Interfacing to C Streams
@@ -22521,7 +22592,7 @@ imported from a C program, allowing an Ada file to operate on an
existing C file.
@node The GNAT Library,Interfacing to Other Languages,The Implementation of Standard I/O,Top
-@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}@anchor{gnat_rm/the_gnat_library doc}@anchor{2d1}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d2}
+@anchor{gnat_rm/the_gnat_library the-gnat-library}@anchor{10}@anchor{gnat_rm/the_gnat_library doc}@anchor{2d4}@anchor{gnat_rm/the_gnat_library id1}@anchor{2d5}
@chapter The GNAT Library
@@ -22715,7 +22786,7 @@ of GNAT, and will generate a warning message.
@end menu
@node Ada Characters Latin_9 a-chlat9 ads,Ada Characters Wide_Latin_1 a-cwila1 ads,,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id2}@anchor{2d3}@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d4}
+@anchor{gnat_rm/the_gnat_library id2}@anchor{2d6}@anchor{gnat_rm/the_gnat_library ada-characters-latin-9-a-chlat9-ads}@anchor{2d7}
@section @code{Ada.Characters.Latin_9} (@code{a-chlat9.ads})
@@ -22732,7 +22803,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Latin_1 a-cwila1 ads,Ada Characters Wide_Latin_9 a-cwila1 ads,Ada Characters Latin_9 a-chlat9 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-1-a-cwila1-ads}@anchor{2d5}@anchor{gnat_rm/the_gnat_library id3}@anchor{2d6}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-1-a-cwila1-ads}@anchor{2d8}@anchor{gnat_rm/the_gnat_library id3}@anchor{2d9}
@section @code{Ada.Characters.Wide_Latin_1} (@code{a-cwila1.ads})
@@ -22749,7 +22820,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Latin_9 a-cwila1 ads,Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,Ada Characters Wide_Latin_1 a-cwila1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id4}@anchor{2d7}@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2d8}
+@anchor{gnat_rm/the_gnat_library id4}@anchor{2da}@anchor{gnat_rm/the_gnat_library ada-characters-wide-latin-9-a-cwila1-ads}@anchor{2db}
@section @code{Ada.Characters.Wide_Latin_9} (@code{a-cwila1.ads})
@@ -22766,7 +22837,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,Ada Characters Wide_Latin_9 a-cwila1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-1-a-chzla1-ads}@anchor{2d9}@anchor{gnat_rm/the_gnat_library id5}@anchor{2da}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-1-a-chzla1-ads}@anchor{2dc}@anchor{gnat_rm/the_gnat_library id5}@anchor{2dd}
@section @code{Ada.Characters.Wide_Wide_Latin_1} (@code{a-chzla1.ads})
@@ -22783,7 +22854,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,Ada Characters Wide_Wide_Latin_1 a-chzla1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-9-a-chzla9-ads}@anchor{2db}@anchor{gnat_rm/the_gnat_library id6}@anchor{2dc}
+@anchor{gnat_rm/the_gnat_library ada-characters-wide-wide-latin-9-a-chzla9-ads}@anchor{2de}@anchor{gnat_rm/the_gnat_library id6}@anchor{2df}
@section @code{Ada.Characters.Wide_Wide_Latin_9} (@code{a-chzla9.ads})
@@ -22800,7 +22871,7 @@ is specifically authorized by the Ada Reference Manual
(RM A.3.3(27)).
@node Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,Ada Containers Formal_Hashed_Maps a-cfhama ads,Ada Characters Wide_Wide_Latin_9 a-chzla9 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id7}@anchor{2dd}@anchor{gnat_rm/the_gnat_library ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2de}
+@anchor{gnat_rm/the_gnat_library id7}@anchor{2e0}@anchor{gnat_rm/the_gnat_library ada-containers-formal-doubly-linked-lists-a-cfdlli-ads}@anchor{2e1}
@section @code{Ada.Containers.Formal_Doubly_Linked_Lists} (@code{a-cfdlli.ads})
@@ -22819,7 +22890,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Hashed_Maps a-cfhama ads,Ada Containers Formal_Hashed_Sets a-cfhase ads,Ada Containers Formal_Doubly_Linked_Lists a-cfdlli ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id8}@anchor{2df}@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e0}
+@anchor{gnat_rm/the_gnat_library id8}@anchor{2e2}@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-maps-a-cfhama-ads}@anchor{2e3}
@section @code{Ada.Containers.Formal_Hashed_Maps} (@code{a-cfhama.ads})
@@ -22838,7 +22909,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Hashed_Sets a-cfhase ads,Ada Containers Formal_Ordered_Maps a-cforma ads,Ada Containers Formal_Hashed_Maps a-cfhama ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id9}@anchor{2e1}@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e2}
+@anchor{gnat_rm/the_gnat_library id9}@anchor{2e4}@anchor{gnat_rm/the_gnat_library ada-containers-formal-hashed-sets-a-cfhase-ads}@anchor{2e5}
@section @code{Ada.Containers.Formal_Hashed_Sets} (@code{a-cfhase.ads})
@@ -22857,7 +22928,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Ordered_Maps a-cforma ads,Ada Containers Formal_Ordered_Sets a-cforse ads,Ada Containers Formal_Hashed_Sets a-cfhase ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id10}@anchor{2e3}@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e4}
+@anchor{gnat_rm/the_gnat_library id10}@anchor{2e6}@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-maps-a-cforma-ads}@anchor{2e7}
@section @code{Ada.Containers.Formal_Ordered_Maps} (@code{a-cforma.ads})
@@ -22876,7 +22947,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Ordered_Sets a-cforse ads,Ada Containers Formal_Vectors a-cofove ads,Ada Containers Formal_Ordered_Maps a-cforma ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-sets-a-cforse-ads}@anchor{2e5}@anchor{gnat_rm/the_gnat_library id11}@anchor{2e6}
+@anchor{gnat_rm/the_gnat_library ada-containers-formal-ordered-sets-a-cforse-ads}@anchor{2e8}@anchor{gnat_rm/the_gnat_library id11}@anchor{2e9}
@section @code{Ada.Containers.Formal_Ordered_Sets} (@code{a-cforse.ads})
@@ -22895,7 +22966,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Vectors a-cofove ads,Ada Containers Formal_Indefinite_Vectors a-cfinve ads,Ada Containers Formal_Ordered_Sets a-cforse ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id12}@anchor{2e7}@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2e8}
+@anchor{gnat_rm/the_gnat_library id12}@anchor{2ea}@anchor{gnat_rm/the_gnat_library ada-containers-formal-vectors-a-cofove-ads}@anchor{2eb}
@section @code{Ada.Containers.Formal_Vectors} (@code{a-cofove.ads})
@@ -22914,7 +22985,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Formal_Indefinite_Vectors a-cfinve ads,Ada Containers Functional_Vectors a-cofuve ads,Ada Containers Formal_Vectors a-cofove ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id13}@anchor{2e9}@anchor{gnat_rm/the_gnat_library ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2ea}
+@anchor{gnat_rm/the_gnat_library id13}@anchor{2ec}@anchor{gnat_rm/the_gnat_library ada-containers-formal-indefinite-vectors-a-cfinve-ads}@anchor{2ed}
@section @code{Ada.Containers.Formal_Indefinite_Vectors} (@code{a-cfinve.ads})
@@ -22933,7 +23004,7 @@ efficient version than the one defined in the standard. In particular it
does not have the complex overhead required to detect cursor tampering.
@node Ada Containers Functional_Vectors a-cofuve ads,Ada Containers Functional_Sets a-cofuse ads,Ada Containers Formal_Indefinite_Vectors a-cfinve ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id14}@anchor{2eb}@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ec}
+@anchor{gnat_rm/the_gnat_library id14}@anchor{2ee}@anchor{gnat_rm/the_gnat_library ada-containers-functional-vectors-a-cofuve-ads}@anchor{2ef}
@section @code{Ada.Containers.Functional_Vectors} (@code{a-cofuve.ads})
@@ -22955,7 +23026,7 @@ and annotations, so that they can be removed from the final executable. The
specification of this unit is compatible with SPARK 2014.
@node Ada Containers Functional_Sets a-cofuse ads,Ada Containers Functional_Maps a-cofuma ads,Ada Containers Functional_Vectors a-cofuve ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-functional-sets-a-cofuse-ads}@anchor{2ed}@anchor{gnat_rm/the_gnat_library id15}@anchor{2ee}
+@anchor{gnat_rm/the_gnat_library ada-containers-functional-sets-a-cofuse-ads}@anchor{2f0}@anchor{gnat_rm/the_gnat_library id15}@anchor{2f1}
@section @code{Ada.Containers.Functional_Sets} (@code{a-cofuse.ads})
@@ -22977,7 +23048,7 @@ and annotations, so that they can be removed from the final executable. The
specification of this unit is compatible with SPARK 2014.
@node Ada Containers Functional_Maps a-cofuma ads,Ada Containers Bounded_Holders a-coboho ads,Ada Containers Functional_Sets a-cofuse ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id16}@anchor{2ef}@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f0}
+@anchor{gnat_rm/the_gnat_library id16}@anchor{2f2}@anchor{gnat_rm/the_gnat_library ada-containers-functional-maps-a-cofuma-ads}@anchor{2f3}
@section @code{Ada.Containers.Functional_Maps} (@code{a-cofuma.ads})
@@ -22999,7 +23070,7 @@ and annotations, so that they can be removed from the final executable. The
specification of this unit is compatible with SPARK 2014.
@node Ada Containers Bounded_Holders a-coboho ads,Ada Command_Line Environment a-colien ads,Ada Containers Functional_Maps a-cofuma ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-containers-bounded-holders-a-coboho-ads}@anchor{2f1}@anchor{gnat_rm/the_gnat_library id17}@anchor{2f2}
+@anchor{gnat_rm/the_gnat_library ada-containers-bounded-holders-a-coboho-ads}@anchor{2f4}@anchor{gnat_rm/the_gnat_library id17}@anchor{2f5}
@section @code{Ada.Containers.Bounded_Holders} (@code{a-coboho.ads})
@@ -23011,7 +23082,7 @@ This child of @code{Ada.Containers} defines a modified version of
Indefinite_Holders that avoids heap allocation.
@node Ada Command_Line Environment a-colien ads,Ada Command_Line Remove a-colire ads,Ada Containers Bounded_Holders a-coboho ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-command-line-environment-a-colien-ads}@anchor{2f3}@anchor{gnat_rm/the_gnat_library id18}@anchor{2f4}
+@anchor{gnat_rm/the_gnat_library ada-command-line-environment-a-colien-ads}@anchor{2f6}@anchor{gnat_rm/the_gnat_library id18}@anchor{2f7}
@section @code{Ada.Command_Line.Environment} (@code{a-colien.ads})
@@ -23024,7 +23095,7 @@ provides a mechanism for obtaining environment values on systems
where this concept makes sense.
@node Ada Command_Line Remove a-colire ads,Ada Command_Line Response_File a-clrefi ads,Ada Command_Line Environment a-colien ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id19}@anchor{2f5}@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f6}
+@anchor{gnat_rm/the_gnat_library id19}@anchor{2f8}@anchor{gnat_rm/the_gnat_library ada-command-line-remove-a-colire-ads}@anchor{2f9}
@section @code{Ada.Command_Line.Remove} (@code{a-colire.ads})
@@ -23042,7 +23113,7 @@ to further calls on the subprograms in @code{Ada.Command_Line} will not
see the removed argument.
@node Ada Command_Line Response_File a-clrefi ads,Ada Direct_IO C_Streams a-diocst ads,Ada Command_Line Remove a-colire ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id20}@anchor{2f7}@anchor{gnat_rm/the_gnat_library ada-command-line-response-file-a-clrefi-ads}@anchor{2f8}
+@anchor{gnat_rm/the_gnat_library id20}@anchor{2fa}@anchor{gnat_rm/the_gnat_library ada-command-line-response-file-a-clrefi-ads}@anchor{2fb}
@section @code{Ada.Command_Line.Response_File} (@code{a-clrefi.ads})
@@ -23062,7 +23133,7 @@ Using a response file allow passing a set of arguments to an executable longer
than the maximum allowed by the system on the command line.
@node Ada Direct_IO C_Streams a-diocst ads,Ada Exceptions Is_Null_Occurrence a-einuoc ads,Ada Command_Line Response_File a-clrefi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id21}@anchor{2f9}@anchor{gnat_rm/the_gnat_library ada-direct-io-c-streams-a-diocst-ads}@anchor{2fa}
+@anchor{gnat_rm/the_gnat_library id21}@anchor{2fc}@anchor{gnat_rm/the_gnat_library ada-direct-io-c-streams-a-diocst-ads}@anchor{2fd}
@section @code{Ada.Direct_IO.C_Streams} (@code{a-diocst.ads})
@@ -23077,7 +23148,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Exceptions Is_Null_Occurrence a-einuoc ads,Ada Exceptions Last_Chance_Handler a-elchha ads,Ada Direct_IO C_Streams a-diocst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id22}@anchor{2fb}@anchor{gnat_rm/the_gnat_library ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2fc}
+@anchor{gnat_rm/the_gnat_library id22}@anchor{2fe}@anchor{gnat_rm/the_gnat_library ada-exceptions-is-null-occurrence-a-einuoc-ads}@anchor{2ff}
@section @code{Ada.Exceptions.Is_Null_Occurrence} (@code{a-einuoc.ads})
@@ -23091,7 +23162,7 @@ exception occurrence (@code{Null_Occurrence}) without raising
an exception.
@node Ada Exceptions Last_Chance_Handler a-elchha ads,Ada Exceptions Traceback a-exctra ads,Ada Exceptions Is_Null_Occurrence a-einuoc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id23}@anchor{2fd}@anchor{gnat_rm/the_gnat_library ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{2fe}
+@anchor{gnat_rm/the_gnat_library id23}@anchor{300}@anchor{gnat_rm/the_gnat_library ada-exceptions-last-chance-handler-a-elchha-ads}@anchor{301}
@section @code{Ada.Exceptions.Last_Chance_Handler} (@code{a-elchha.ads})
@@ -23105,7 +23176,7 @@ exceptions (hence the name last chance), and perform clean ups before
terminating the program. Note that this subprogram never returns.
@node Ada Exceptions Traceback a-exctra ads,Ada Sequential_IO C_Streams a-siocst ads,Ada Exceptions Last_Chance_Handler a-elchha ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-exceptions-traceback-a-exctra-ads}@anchor{2ff}@anchor{gnat_rm/the_gnat_library id24}@anchor{300}
+@anchor{gnat_rm/the_gnat_library ada-exceptions-traceback-a-exctra-ads}@anchor{302}@anchor{gnat_rm/the_gnat_library id24}@anchor{303}
@section @code{Ada.Exceptions.Traceback} (@code{a-exctra.ads})
@@ -23118,7 +23189,7 @@ give a traceback array of addresses based on an exception
occurrence.
@node Ada Sequential_IO C_Streams a-siocst ads,Ada Streams Stream_IO C_Streams a-ssicst ads,Ada Exceptions Traceback a-exctra ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-sequential-io-c-streams-a-siocst-ads}@anchor{301}@anchor{gnat_rm/the_gnat_library id25}@anchor{302}
+@anchor{gnat_rm/the_gnat_library ada-sequential-io-c-streams-a-siocst-ads}@anchor{304}@anchor{gnat_rm/the_gnat_library id25}@anchor{305}
@section @code{Ada.Sequential_IO.C_Streams} (@code{a-siocst.ads})
@@ -23133,7 +23204,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Streams Stream_IO C_Streams a-ssicst ads,Ada Strings Unbounded Text_IO a-suteio ads,Ada Sequential_IO C_Streams a-siocst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id26}@anchor{303}@anchor{gnat_rm/the_gnat_library ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{304}
+@anchor{gnat_rm/the_gnat_library id26}@anchor{306}@anchor{gnat_rm/the_gnat_library ada-streams-stream-io-c-streams-a-ssicst-ads}@anchor{307}
@section @code{Ada.Streams.Stream_IO.C_Streams} (@code{a-ssicst.ads})
@@ -23148,7 +23219,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Strings Unbounded Text_IO a-suteio ads,Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,Ada Streams Stream_IO C_Streams a-ssicst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-strings-unbounded-text-io-a-suteio-ads}@anchor{305}@anchor{gnat_rm/the_gnat_library id27}@anchor{306}
+@anchor{gnat_rm/the_gnat_library ada-strings-unbounded-text-io-a-suteio-ads}@anchor{308}@anchor{gnat_rm/the_gnat_library id27}@anchor{309}
@section @code{Ada.Strings.Unbounded.Text_IO} (@code{a-suteio.ads})
@@ -23165,7 +23236,7 @@ strings, avoiding the necessity for an intermediate operation
with ordinary strings.
@node Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,Ada Strings Unbounded Text_IO a-suteio ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id28}@anchor{307}@anchor{gnat_rm/the_gnat_library ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{308}
+@anchor{gnat_rm/the_gnat_library id28}@anchor{30a}@anchor{gnat_rm/the_gnat_library ada-strings-wide-unbounded-wide-text-io-a-swuwti-ads}@anchor{30b}
@section @code{Ada.Strings.Wide_Unbounded.Wide_Text_IO} (@code{a-swuwti.ads})
@@ -23182,7 +23253,7 @@ wide strings, avoiding the necessity for an intermediate operation
with ordinary wide strings.
@node Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,Ada Task_Initialization a-tasini ads,Ada Strings Wide_Unbounded Wide_Text_IO a-swuwti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id29}@anchor{309}@anchor{gnat_rm/the_gnat_library ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30a}
+@anchor{gnat_rm/the_gnat_library id29}@anchor{30c}@anchor{gnat_rm/the_gnat_library ada-strings-wide-wide-unbounded-wide-wide-text-io-a-szuzti-ads}@anchor{30d}
@section @code{Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Text_IO} (@code{a-szuzti.ads})
@@ -23199,7 +23270,7 @@ wide wide strings, avoiding the necessity for an intermediate operation
with ordinary wide wide strings.
@node Ada Task_Initialization a-tasini ads,Ada Text_IO C_Streams a-tiocst ads,Ada Strings Wide_Wide_Unbounded Wide_Wide_Text_IO a-szuzti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-task-initialization-a-tasini-ads}@anchor{30b}@anchor{gnat_rm/the_gnat_library id30}@anchor{30c}
+@anchor{gnat_rm/the_gnat_library ada-task-initialization-a-tasini-ads}@anchor{30e}@anchor{gnat_rm/the_gnat_library id30}@anchor{30f}
@section @code{Ada.Task_Initialization} (@code{a-tasini.ads})
@@ -23211,7 +23282,7 @@ parameterless procedures. Note that such a handler is only invoked for
those tasks activated after the handler is set.
@node Ada Text_IO C_Streams a-tiocst ads,Ada Text_IO Reset_Standard_Files a-tirsfi ads,Ada Task_Initialization a-tasini ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-text-io-c-streams-a-tiocst-ads}@anchor{30d}@anchor{gnat_rm/the_gnat_library id31}@anchor{30e}
+@anchor{gnat_rm/the_gnat_library ada-text-io-c-streams-a-tiocst-ads}@anchor{310}@anchor{gnat_rm/the_gnat_library id31}@anchor{311}
@section @code{Ada.Text_IO.C_Streams} (@code{a-tiocst.ads})
@@ -23226,7 +23297,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Text_IO Reset_Standard_Files a-tirsfi ads,Ada Wide_Characters Unicode a-wichun ads,Ada Text_IO C_Streams a-tiocst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-text-io-reset-standard-files-a-tirsfi-ads}@anchor{30f}@anchor{gnat_rm/the_gnat_library id32}@anchor{310}
+@anchor{gnat_rm/the_gnat_library ada-text-io-reset-standard-files-a-tirsfi-ads}@anchor{312}@anchor{gnat_rm/the_gnat_library id32}@anchor{313}
@section @code{Ada.Text_IO.Reset_Standard_Files} (@code{a-tirsfi.ads})
@@ -23241,7 +23312,7 @@ execution (for example a standard input file may be redefined to be
interactive).
@node Ada Wide_Characters Unicode a-wichun ads,Ada Wide_Text_IO C_Streams a-wtcstr ads,Ada Text_IO Reset_Standard_Files a-tirsfi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id33}@anchor{311}@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{312}
+@anchor{gnat_rm/the_gnat_library id33}@anchor{314}@anchor{gnat_rm/the_gnat_library ada-wide-characters-unicode-a-wichun-ads}@anchor{315}
@section @code{Ada.Wide_Characters.Unicode} (@code{a-wichun.ads})
@@ -23254,7 +23325,7 @@ This package provides subprograms that allow categorization of
Wide_Character values according to Unicode categories.
@node Ada Wide_Text_IO C_Streams a-wtcstr ads,Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,Ada Wide_Characters Unicode a-wichun ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id34}@anchor{313}@anchor{gnat_rm/the_gnat_library ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{314}
+@anchor{gnat_rm/the_gnat_library id34}@anchor{316}@anchor{gnat_rm/the_gnat_library ada-wide-text-io-c-streams-a-wtcstr-ads}@anchor{317}
@section @code{Ada.Wide_Text_IO.C_Streams} (@code{a-wtcstr.ads})
@@ -23269,7 +23340,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,Ada Wide_Wide_Characters Unicode a-zchuni ads,Ada Wide_Text_IO C_Streams a-wtcstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-text-io-reset-standard-files-a-wrstfi-ads}@anchor{315}@anchor{gnat_rm/the_gnat_library id35}@anchor{316}
+@anchor{gnat_rm/the_gnat_library ada-wide-text-io-reset-standard-files-a-wrstfi-ads}@anchor{318}@anchor{gnat_rm/the_gnat_library id35}@anchor{319}
@section @code{Ada.Wide_Text_IO.Reset_Standard_Files} (@code{a-wrstfi.ads})
@@ -23284,7 +23355,7 @@ execution (for example a standard input file may be redefined to be
interactive).
@node Ada Wide_Wide_Characters Unicode a-zchuni ads,Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,Ada Wide_Text_IO Reset_Standard_Files a-wrstfi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id36}@anchor{317}@anchor{gnat_rm/the_gnat_library ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{318}
+@anchor{gnat_rm/the_gnat_library id36}@anchor{31a}@anchor{gnat_rm/the_gnat_library ada-wide-wide-characters-unicode-a-zchuni-ads}@anchor{31b}
@section @code{Ada.Wide_Wide_Characters.Unicode} (@code{a-zchuni.ads})
@@ -23297,7 +23368,7 @@ This package provides subprograms that allow categorization of
Wide_Wide_Character values according to Unicode categories.
@node Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,Ada Wide_Wide_Characters Unicode a-zchuni ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id37}@anchor{319}@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31a}
+@anchor{gnat_rm/the_gnat_library id37}@anchor{31c}@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-c-streams-a-ztcstr-ads}@anchor{31d}
@section @code{Ada.Wide_Wide_Text_IO.C_Streams} (@code{a-ztcstr.ads})
@@ -23312,7 +23383,7 @@ extracted from a file opened on the Ada side, and an Ada file
can be constructed from a stream opened on the C side.
@node Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,GNAT Altivec g-altive ads,Ada Wide_Wide_Text_IO C_Streams a-ztcstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-reset-standard-files-a-zrstfi-ads}@anchor{31b}@anchor{gnat_rm/the_gnat_library id38}@anchor{31c}
+@anchor{gnat_rm/the_gnat_library ada-wide-wide-text-io-reset-standard-files-a-zrstfi-ads}@anchor{31e}@anchor{gnat_rm/the_gnat_library id38}@anchor{31f}
@section @code{Ada.Wide_Wide_Text_IO.Reset_Standard_Files} (@code{a-zrstfi.ads})
@@ -23327,7 +23398,7 @@ change during execution (for example a standard input file may be
redefined to be interactive).
@node GNAT Altivec g-altive ads,GNAT Altivec Conversions g-altcon ads,Ada Wide_Wide_Text_IO Reset_Standard_Files a-zrstfi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-g-altive-ads}@anchor{31d}@anchor{gnat_rm/the_gnat_library id39}@anchor{31e}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-g-altive-ads}@anchor{320}@anchor{gnat_rm/the_gnat_library id39}@anchor{321}
@section @code{GNAT.Altivec} (@code{g-altive.ads})
@@ -23340,7 +23411,7 @@ definitions of constants and types common to all the versions of the
binding.
@node GNAT Altivec Conversions g-altcon ads,GNAT Altivec Vector_Operations g-alveop ads,GNAT Altivec g-altive ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-conversions-g-altcon-ads}@anchor{31f}@anchor{gnat_rm/the_gnat_library id40}@anchor{320}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-conversions-g-altcon-ads}@anchor{322}@anchor{gnat_rm/the_gnat_library id40}@anchor{323}
@section @code{GNAT.Altivec.Conversions} (@code{g-altcon.ads})
@@ -23351,7 +23422,7 @@ binding.
This package provides the Vector/View conversion routines.
@node GNAT Altivec Vector_Operations g-alveop ads,GNAT Altivec Vector_Types g-alvety ads,GNAT Altivec Conversions g-altcon ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id41}@anchor{321}@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{322}
+@anchor{gnat_rm/the_gnat_library id41}@anchor{324}@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-operations-g-alveop-ads}@anchor{325}
@section @code{GNAT.Altivec.Vector_Operations} (@code{g-alveop.ads})
@@ -23365,7 +23436,7 @@ library. The hard binding is provided as a separate package. This unit
is common to both bindings.
@node GNAT Altivec Vector_Types g-alvety ads,GNAT Altivec Vector_Views g-alvevi ads,GNAT Altivec Vector_Operations g-alveop ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-types-g-alvety-ads}@anchor{323}@anchor{gnat_rm/the_gnat_library id42}@anchor{324}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-types-g-alvety-ads}@anchor{326}@anchor{gnat_rm/the_gnat_library id42}@anchor{327}
@section @code{GNAT.Altivec.Vector_Types} (@code{g-alvety.ads})
@@ -23377,7 +23448,7 @@ This package exposes the various vector types part of the Ada binding
to AltiVec facilities.
@node GNAT Altivec Vector_Views g-alvevi ads,GNAT Array_Split g-arrspl ads,GNAT Altivec Vector_Types g-alvety ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-views-g-alvevi-ads}@anchor{325}@anchor{gnat_rm/the_gnat_library id43}@anchor{326}
+@anchor{gnat_rm/the_gnat_library gnat-altivec-vector-views-g-alvevi-ads}@anchor{328}@anchor{gnat_rm/the_gnat_library id43}@anchor{329}
@section @code{GNAT.Altivec.Vector_Views} (@code{g-alvevi.ads})
@@ -23392,7 +23463,7 @@ vector elements and provides a simple way to initialize vector
objects.
@node GNAT Array_Split g-arrspl ads,GNAT AWK g-awk ads,GNAT Altivec Vector_Views g-alvevi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-array-split-g-arrspl-ads}@anchor{327}@anchor{gnat_rm/the_gnat_library id44}@anchor{328}
+@anchor{gnat_rm/the_gnat_library gnat-array-split-g-arrspl-ads}@anchor{32a}@anchor{gnat_rm/the_gnat_library id44}@anchor{32b}
@section @code{GNAT.Array_Split} (@code{g-arrspl.ads})
@@ -23405,7 +23476,7 @@ an array wherever the separators appear, and provide direct access
to the resulting slices.
@node GNAT AWK g-awk ads,GNAT Bind_Environment g-binenv ads,GNAT Array_Split g-arrspl ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id45}@anchor{329}@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32a}
+@anchor{gnat_rm/the_gnat_library id45}@anchor{32c}@anchor{gnat_rm/the_gnat_library gnat-awk-g-awk-ads}@anchor{32d}
@section @code{GNAT.AWK} (@code{g-awk.ads})
@@ -23420,7 +23491,7 @@ or more files containing formatted data. The file is viewed as a database
where each record is a line and a field is a data element in this line.
@node GNAT Bind_Environment g-binenv ads,GNAT Branch_Prediction g-brapre ads,GNAT AWK g-awk ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id46}@anchor{32b}@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32c}
+@anchor{gnat_rm/the_gnat_library id46}@anchor{32e}@anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{32f}
@section @code{GNAT.Bind_Environment} (@code{g-binenv.ads})
@@ -23433,7 +23504,7 @@ These associations can be specified using the @code{-V} binder command
line switch.
@node GNAT Branch_Prediction g-brapre ads,GNAT Bounded_Buffers g-boubuf ads,GNAT Bind_Environment g-binenv ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id47}@anchor{32d}@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{32e}
+@anchor{gnat_rm/the_gnat_library id47}@anchor{330}@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{331}
@section @code{GNAT.Branch_Prediction} (@code{g-brapre.ads})
@@ -23444,7 +23515,7 @@ line switch.
Provides routines giving hints to the branch predictor of the code generator.
@node GNAT Bounded_Buffers g-boubuf ads,GNAT Bounded_Mailboxes g-boumai ads,GNAT Branch_Prediction g-brapre ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{32f}@anchor{gnat_rm/the_gnat_library id48}@anchor{330}
+@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{332}@anchor{gnat_rm/the_gnat_library id48}@anchor{333}
@section @code{GNAT.Bounded_Buffers} (@code{g-boubuf.ads})
@@ -23459,7 +23530,7 @@ useful directly or as parts of the implementations of other abstractions,
such as mailboxes.
@node GNAT Bounded_Mailboxes g-boumai ads,GNAT Bubble_Sort g-bubsor ads,GNAT Bounded_Buffers g-boubuf ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{331}@anchor{gnat_rm/the_gnat_library id49}@anchor{332}
+@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{334}@anchor{gnat_rm/the_gnat_library id49}@anchor{335}
@section @code{GNAT.Bounded_Mailboxes} (@code{g-boumai.ads})
@@ -23472,7 +23543,7 @@ such as mailboxes.
Provides a thread-safe asynchronous intertask mailbox communication facility.
@node GNAT Bubble_Sort g-bubsor ads,GNAT Bubble_Sort_A g-busora ads,GNAT Bounded_Mailboxes g-boumai ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{333}@anchor{gnat_rm/the_gnat_library id50}@anchor{334}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{336}@anchor{gnat_rm/the_gnat_library id50}@anchor{337}
@section @code{GNAT.Bubble_Sort} (@code{g-bubsor.ads})
@@ -23487,7 +23558,7 @@ data items. Exchange and comparison procedures are provided by passing
access-to-procedure values.
@node GNAT Bubble_Sort_A g-busora ads,GNAT Bubble_Sort_G g-busorg ads,GNAT Bubble_Sort g-bubsor ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id51}@anchor{335}@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{336}
+@anchor{gnat_rm/the_gnat_library id51}@anchor{338}@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{339}
@section @code{GNAT.Bubble_Sort_A} (@code{g-busora.ads})
@@ -23503,7 +23574,7 @@ access-to-procedure values. This is an older version, retained for
compatibility. Usually @code{GNAT.Bubble_Sort} will be preferable.
@node GNAT Bubble_Sort_G g-busorg ads,GNAT Byte_Order_Mark g-byorma ads,GNAT Bubble_Sort_A g-busora ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{337}@anchor{gnat_rm/the_gnat_library id52}@anchor{338}
+@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{33a}@anchor{gnat_rm/the_gnat_library id52}@anchor{33b}
@section @code{GNAT.Bubble_Sort_G} (@code{g-busorg.ads})
@@ -23519,7 +23590,7 @@ if the procedures can be inlined, at the expense of duplicating code for
multiple instantiations.
@node GNAT Byte_Order_Mark g-byorma ads,GNAT Byte_Swapping g-bytswa ads,GNAT Bubble_Sort_G g-busorg ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{339}@anchor{gnat_rm/the_gnat_library id53}@anchor{33a}
+@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{33c}@anchor{gnat_rm/the_gnat_library id53}@anchor{33d}
@section @code{GNAT.Byte_Order_Mark} (@code{g-byorma.ads})
@@ -23535,7 +23606,7 @@ the encoding of the string. The routine includes detection of special XML
sequences for various UCS input formats.
@node GNAT Byte_Swapping g-bytswa ads,GNAT Calendar g-calend ads,GNAT Byte_Order_Mark g-byorma ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{33b}@anchor{gnat_rm/the_gnat_library id54}@anchor{33c}
+@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{33e}@anchor{gnat_rm/the_gnat_library id54}@anchor{33f}
@section @code{GNAT.Byte_Swapping} (@code{g-bytswa.ads})
@@ -23549,7 +23620,7 @@ General routines for swapping the bytes in 2-, 4-, and 8-byte quantities.
Machine-specific implementations are available in some cases.
@node GNAT Calendar g-calend ads,GNAT Calendar Time_IO g-catiio ads,GNAT Byte_Swapping g-bytswa ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id55}@anchor{33d}@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{33e}
+@anchor{gnat_rm/the_gnat_library id55}@anchor{340}@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{341}
@section @code{GNAT.Calendar} (@code{g-calend.ads})
@@ -23563,7 +23634,7 @@ Also provides conversion of @code{Ada.Calendar.Time} values to and from the
C @code{timeval} format.
@node GNAT Calendar Time_IO g-catiio ads,GNAT CRC32 g-crc32 ads,GNAT Calendar g-calend ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id56}@anchor{33f}@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{340}
+@anchor{gnat_rm/the_gnat_library id56}@anchor{342}@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{343}
@section @code{GNAT.Calendar.Time_IO} (@code{g-catiio.ads})
@@ -23574,7 +23645,7 @@ C @code{timeval} format.
@geindex GNAT.Calendar.Time_IO (g-catiio.ads)
@node GNAT CRC32 g-crc32 ads,GNAT Case_Util g-casuti ads,GNAT Calendar Time_IO g-catiio ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id57}@anchor{341}@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{342}
+@anchor{gnat_rm/the_gnat_library id57}@anchor{344}@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{345}
@section @code{GNAT.CRC32} (@code{g-crc32.ads})
@@ -23591,7 +23662,7 @@ of this algorithm see
Aug. 1988. Sarwate, D.V.
@node GNAT Case_Util g-casuti ads,GNAT CGI g-cgi ads,GNAT CRC32 g-crc32 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id58}@anchor{343}@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{344}
+@anchor{gnat_rm/the_gnat_library id58}@anchor{346}@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{347}
@section @code{GNAT.Case_Util} (@code{g-casuti.ads})
@@ -23606,7 +23677,7 @@ without the overhead of the full casing tables
in @code{Ada.Characters.Handling}.
@node GNAT CGI g-cgi ads,GNAT CGI Cookie g-cgicoo ads,GNAT Case_Util g-casuti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id59}@anchor{345}@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{346}
+@anchor{gnat_rm/the_gnat_library id59}@anchor{348}@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{349}
@section @code{GNAT.CGI} (@code{g-cgi.ads})
@@ -23621,7 +23692,7 @@ builds a table whose index is the key and provides some services to deal
with this table.
@node GNAT CGI Cookie g-cgicoo ads,GNAT CGI Debug g-cgideb ads,GNAT CGI g-cgi ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{347}@anchor{gnat_rm/the_gnat_library id60}@anchor{348}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{34a}@anchor{gnat_rm/the_gnat_library id60}@anchor{34b}
@section @code{GNAT.CGI.Cookie} (@code{g-cgicoo.ads})
@@ -23636,7 +23707,7 @@ Common Gateway Interface (CGI). It exports services to deal with Web
cookies (piece of information kept in the Web client software).
@node GNAT CGI Debug g-cgideb ads,GNAT Command_Line g-comlin ads,GNAT CGI Cookie g-cgicoo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{349}@anchor{gnat_rm/the_gnat_library id61}@anchor{34a}
+@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{34c}@anchor{gnat_rm/the_gnat_library id61}@anchor{34d}
@section @code{GNAT.CGI.Debug} (@code{g-cgideb.ads})
@@ -23648,7 +23719,7 @@ This is a package to help debugging CGI (Common Gateway Interface)
programs written in Ada.
@node GNAT Command_Line g-comlin ads,GNAT Compiler_Version g-comver ads,GNAT CGI Debug g-cgideb ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id62}@anchor{34b}@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34c}
+@anchor{gnat_rm/the_gnat_library id62}@anchor{34e}@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{34f}
@section @code{GNAT.Command_Line} (@code{g-comlin.ads})
@@ -23661,7 +23732,7 @@ including the ability to scan for named switches with optional parameters
and expand file names using wildcard notations.
@node GNAT Compiler_Version g-comver ads,GNAT Ctrl_C g-ctrl_c ads,GNAT Command_Line g-comlin ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{34d}@anchor{gnat_rm/the_gnat_library id63}@anchor{34e}
+@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{350}@anchor{gnat_rm/the_gnat_library id63}@anchor{351}
@section @code{GNAT.Compiler_Version} (@code{g-comver.ads})
@@ -23679,7 +23750,7 @@ of the compiler if a consistent tool set is used to compile all units
of a partition).
@node GNAT Ctrl_C g-ctrl_c ads,GNAT Current_Exception g-curexc ads,GNAT Compiler_Version g-comver ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id64}@anchor{34f}@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{350}
+@anchor{gnat_rm/the_gnat_library id64}@anchor{352}@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{353}
@section @code{GNAT.Ctrl_C} (@code{g-ctrl_c.ads})
@@ -23690,7 +23761,7 @@ of a partition).
Provides a simple interface to handle Ctrl-C keyboard events.
@node GNAT Current_Exception g-curexc ads,GNAT Debug_Pools g-debpoo ads,GNAT Ctrl_C g-ctrl_c ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id65}@anchor{351}@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{352}
+@anchor{gnat_rm/the_gnat_library id65}@anchor{354}@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{355}
@section @code{GNAT.Current_Exception} (@code{g-curexc.ads})
@@ -23707,7 +23778,7 @@ This is particularly useful in simulating typical facilities for
obtaining information about exceptions provided by Ada 83 compilers.
@node GNAT Debug_Pools g-debpoo ads,GNAT Debug_Utilities g-debuti ads,GNAT Current_Exception g-curexc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{353}@anchor{gnat_rm/the_gnat_library id66}@anchor{354}
+@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{356}@anchor{gnat_rm/the_gnat_library id66}@anchor{357}
@section @code{GNAT.Debug_Pools} (@code{g-debpoo.ads})
@@ -23724,7 +23795,7 @@ problems.
See @code{The GNAT Debug_Pool Facility} section in the @cite{GNAT User's Guide}.
@node GNAT Debug_Utilities g-debuti ads,GNAT Decode_String g-decstr ads,GNAT Debug_Pools g-debpoo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{355}@anchor{gnat_rm/the_gnat_library id67}@anchor{356}
+@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{358}@anchor{gnat_rm/the_gnat_library id67}@anchor{359}
@section @code{GNAT.Debug_Utilities} (@code{g-debuti.ads})
@@ -23737,7 +23808,7 @@ to and from string images of address values. Supports both C and Ada formats
for hexadecimal literals.
@node GNAT Decode_String g-decstr ads,GNAT Decode_UTF8_String g-deutst ads,GNAT Debug_Utilities g-debuti ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{357}@anchor{gnat_rm/the_gnat_library id68}@anchor{358}
+@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{35a}@anchor{gnat_rm/the_gnat_library id68}@anchor{35b}
@section @code{GNAT.Decode_String} (@code{g-decstr.ads})
@@ -23761,7 +23832,7 @@ Useful in conjunction with Unicode character coding. Note there is a
preinstantiation for UTF-8. See next entry.
@node GNAT Decode_UTF8_String g-deutst ads,GNAT Directory_Operations g-dirope ads,GNAT Decode_String g-decstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{359}@anchor{gnat_rm/the_gnat_library id69}@anchor{35a}
+@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{35c}@anchor{gnat_rm/the_gnat_library id69}@anchor{35d}
@section @code{GNAT.Decode_UTF8_String} (@code{g-deutst.ads})
@@ -23782,7 +23853,7 @@ preinstantiation for UTF-8. See next entry.
A preinstantiation of GNAT.Decode_Strings for UTF-8 encoding.
@node GNAT Directory_Operations g-dirope ads,GNAT Directory_Operations Iteration g-diopit ads,GNAT Decode_UTF8_String g-deutst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id70}@anchor{35b}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35c}
+@anchor{gnat_rm/the_gnat_library id70}@anchor{35e}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{35f}
@section @code{GNAT.Directory_Operations} (@code{g-dirope.ads})
@@ -23795,7 +23866,7 @@ the current directory, making new directories, and scanning the files in a
directory.
@node GNAT Directory_Operations Iteration g-diopit ads,GNAT Dynamic_HTables g-dynhta ads,GNAT Directory_Operations g-dirope ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id71}@anchor{35d}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{35e}
+@anchor{gnat_rm/the_gnat_library id71}@anchor{360}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{361}
@section @code{GNAT.Directory_Operations.Iteration} (@code{g-diopit.ads})
@@ -23807,7 +23878,7 @@ A child unit of GNAT.Directory_Operations providing additional operations
for iterating through directories.
@node GNAT Dynamic_HTables g-dynhta ads,GNAT Dynamic_Tables g-dyntab ads,GNAT Directory_Operations Iteration g-diopit ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id72}@anchor{35f}@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{360}
+@anchor{gnat_rm/the_gnat_library id72}@anchor{362}@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{363}
@section @code{GNAT.Dynamic_HTables} (@code{g-dynhta.ads})
@@ -23825,7 +23896,7 @@ dynamic instances of the hash table, while an instantiation of
@code{GNAT.HTable} creates a single instance of the hash table.
@node GNAT Dynamic_Tables g-dyntab ads,GNAT Encode_String g-encstr ads,GNAT Dynamic_HTables g-dynhta ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{361}@anchor{gnat_rm/the_gnat_library id73}@anchor{362}
+@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{364}@anchor{gnat_rm/the_gnat_library id73}@anchor{365}
@section @code{GNAT.Dynamic_Tables} (@code{g-dyntab.ads})
@@ -23845,7 +23916,7 @@ dynamic instances of the table, while an instantiation of
@code{GNAT.Table} creates a single instance of the table type.
@node GNAT Encode_String g-encstr ads,GNAT Encode_UTF8_String g-enutst ads,GNAT Dynamic_Tables g-dyntab ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id74}@anchor{363}@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{364}
+@anchor{gnat_rm/the_gnat_library id74}@anchor{366}@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{367}
@section @code{GNAT.Encode_String} (@code{g-encstr.ads})
@@ -23867,7 +23938,7 @@ encoding method. Useful in conjunction with Unicode character coding.
Note there is a preinstantiation for UTF-8. See next entry.
@node GNAT Encode_UTF8_String g-enutst ads,GNAT Exception_Actions g-excact ads,GNAT Encode_String g-encstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{365}@anchor{gnat_rm/the_gnat_library id75}@anchor{366}
+@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{368}@anchor{gnat_rm/the_gnat_library id75}@anchor{369}
@section @code{GNAT.Encode_UTF8_String} (@code{g-enutst.ads})
@@ -23888,7 +23959,7 @@ Note there is a preinstantiation for UTF-8. See next entry.
A preinstantiation of GNAT.Encode_Strings for UTF-8 encoding.
@node GNAT Exception_Actions g-excact ads,GNAT Exception_Traces g-exctra ads,GNAT Encode_UTF8_String g-enutst ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{367}@anchor{gnat_rm/the_gnat_library id76}@anchor{368}
+@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{36a}@anchor{gnat_rm/the_gnat_library id76}@anchor{36b}
@section @code{GNAT.Exception_Actions} (@code{g-excact.ads})
@@ -23901,7 +23972,7 @@ for specific exceptions, or when any exception is raised. This
can be used for instance to force a core dump to ease debugging.
@node GNAT Exception_Traces g-exctra ads,GNAT Exceptions g-except ads,GNAT Exception_Actions g-excact ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{369}@anchor{gnat_rm/the_gnat_library id77}@anchor{36a}
+@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{36c}@anchor{gnat_rm/the_gnat_library id77}@anchor{36d}
@section @code{GNAT.Exception_Traces} (@code{g-exctra.ads})
@@ -23915,7 +23986,7 @@ Provides an interface allowing to control automatic output upon exception
occurrences.
@node GNAT Exceptions g-except ads,GNAT Expect g-expect ads,GNAT Exception_Traces g-exctra ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id78}@anchor{36b}@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36c}
+@anchor{gnat_rm/the_gnat_library id78}@anchor{36e}@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{36f}
@section @code{GNAT.Exceptions} (@code{g-except.ads})
@@ -23936,7 +24007,7 @@ predefined exceptions, and for example allow raising
@code{Constraint_Error} with a message from a pure subprogram.
@node GNAT Expect g-expect ads,GNAT Expect TTY g-exptty ads,GNAT Exceptions g-except ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id79}@anchor{36d}@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{36e}
+@anchor{gnat_rm/the_gnat_library id79}@anchor{370}@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{371}
@section @code{GNAT.Expect} (@code{g-expect.ads})
@@ -23952,7 +24023,7 @@ It is not implemented for cross ports, and in particular is not
implemented for VxWorks or LynxOS.
@node GNAT Expect TTY g-exptty ads,GNAT Float_Control g-flocon ads,GNAT Expect g-expect ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id80}@anchor{36f}@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{370}
+@anchor{gnat_rm/the_gnat_library id80}@anchor{372}@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{373}
@section @code{GNAT.Expect.TTY} (@code{g-exptty.ads})
@@ -23964,7 +24035,7 @@ ports. It is not implemented for cross ports, and
in particular is not implemented for VxWorks or LynxOS.
@node GNAT Float_Control g-flocon ads,GNAT Formatted_String g-forstr ads,GNAT Expect TTY g-exptty ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id81}@anchor{371}@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{372}
+@anchor{gnat_rm/the_gnat_library id81}@anchor{374}@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{375}
@section @code{GNAT.Float_Control} (@code{g-flocon.ads})
@@ -23978,7 +24049,7 @@ library calls may cause this mode to be modified, and the Reset procedure
in this package can be used to reestablish the required mode.
@node GNAT Formatted_String g-forstr ads,GNAT Heap_Sort g-heasor ads,GNAT Float_Control g-flocon ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id82}@anchor{373}@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{374}
+@anchor{gnat_rm/the_gnat_library id82}@anchor{376}@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{377}
@section @code{GNAT.Formatted_String} (@code{g-forstr.ads})
@@ -23993,7 +24064,7 @@ derived from Integer, Float or enumerations as values for the
formatted string.
@node GNAT Heap_Sort g-heasor ads,GNAT Heap_Sort_A g-hesora ads,GNAT Formatted_String g-forstr ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id83}@anchor{375}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{376}
+@anchor{gnat_rm/the_gnat_library id83}@anchor{378}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{379}
@section @code{GNAT.Heap_Sort} (@code{g-heasor.ads})
@@ -24007,7 +24078,7 @@ access-to-procedure values. The algorithm used is a modified heap sort
that performs approximately N*log(N) comparisons in the worst case.
@node GNAT Heap_Sort_A g-hesora ads,GNAT Heap_Sort_G g-hesorg ads,GNAT Heap_Sort g-heasor ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{377}@anchor{gnat_rm/the_gnat_library id84}@anchor{378}
+@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{37a}@anchor{gnat_rm/the_gnat_library id84}@anchor{37b}
@section @code{GNAT.Heap_Sort_A} (@code{g-hesora.ads})
@@ -24023,7 +24094,7 @@ This differs from @code{GNAT.Heap_Sort} in having a less convenient
interface, but may be slightly more efficient.
@node GNAT Heap_Sort_G g-hesorg ads,GNAT HTable g-htable ads,GNAT Heap_Sort_A g-hesora ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id85}@anchor{379}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37a}
+@anchor{gnat_rm/the_gnat_library id85}@anchor{37c}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{37d}
@section @code{GNAT.Heap_Sort_G} (@code{g-hesorg.ads})
@@ -24037,7 +24108,7 @@ if the procedures can be inlined, at the expense of duplicating code for
multiple instantiations.
@node GNAT HTable g-htable ads,GNAT IO g-io ads,GNAT Heap_Sort_G g-hesorg ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id86}@anchor{37b}@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37c}
+@anchor{gnat_rm/the_gnat_library id86}@anchor{37e}@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{37f}
@section @code{GNAT.HTable} (@code{g-htable.ads})
@@ -24050,7 +24121,7 @@ data. Provides two approaches, one a simple static approach, and the other
allowing arbitrary dynamic hash tables.
@node GNAT IO g-io ads,GNAT IO_Aux g-io_aux ads,GNAT HTable g-htable ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id87}@anchor{37d}@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{37e}
+@anchor{gnat_rm/the_gnat_library id87}@anchor{380}@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{381}
@section @code{GNAT.IO} (@code{g-io.ads})
@@ -24066,7 +24137,7 @@ Standard_Input, and writing characters, strings and integers to either
Standard_Output or Standard_Error.
@node GNAT IO_Aux g-io_aux ads,GNAT Lock_Files g-locfil ads,GNAT IO g-io ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id88}@anchor{37f}@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{380}
+@anchor{gnat_rm/the_gnat_library id88}@anchor{382}@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{383}
@section @code{GNAT.IO_Aux} (@code{g-io_aux.ads})
@@ -24080,7 +24151,7 @@ Provides some auxiliary functions for use with Text_IO, including a test
for whether a file exists, and functions for reading a line of text.
@node GNAT Lock_Files g-locfil ads,GNAT MBBS_Discrete_Random g-mbdira ads,GNAT IO_Aux g-io_aux ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id89}@anchor{381}@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{382}
+@anchor{gnat_rm/the_gnat_library id89}@anchor{384}@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{385}
@section @code{GNAT.Lock_Files} (@code{g-locfil.ads})
@@ -24094,7 +24165,7 @@ Provides a general interface for using files as locks. Can be used for
providing program level synchronization.
@node GNAT MBBS_Discrete_Random g-mbdira ads,GNAT MBBS_Float_Random g-mbflra ads,GNAT Lock_Files g-locfil ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id90}@anchor{383}@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{384}
+@anchor{gnat_rm/the_gnat_library id90}@anchor{386}@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{387}
@section @code{GNAT.MBBS_Discrete_Random} (@code{g-mbdira.ads})
@@ -24106,7 +24177,7 @@ The original implementation of @code{Ada.Numerics.Discrete_Random}. Uses
a modified version of the Blum-Blum-Shub generator.
@node GNAT MBBS_Float_Random g-mbflra ads,GNAT MD5 g-md5 ads,GNAT MBBS_Discrete_Random g-mbdira ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id91}@anchor{385}@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{386}
+@anchor{gnat_rm/the_gnat_library id91}@anchor{388}@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{389}
@section @code{GNAT.MBBS_Float_Random} (@code{g-mbflra.ads})
@@ -24118,7 +24189,7 @@ The original implementation of @code{Ada.Numerics.Float_Random}. Uses
a modified version of the Blum-Blum-Shub generator.
@node GNAT MD5 g-md5 ads,GNAT Memory_Dump g-memdum ads,GNAT MBBS_Float_Random g-mbflra ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id92}@anchor{387}@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{388}
+@anchor{gnat_rm/the_gnat_library id92}@anchor{38a}@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{38b}
@section @code{GNAT.MD5} (@code{g-md5.ads})
@@ -24131,7 +24202,7 @@ the HMAC-MD5 message authentication function as described in RFC 2104 and
FIPS PUB 198.
@node GNAT Memory_Dump g-memdum ads,GNAT Most_Recent_Exception g-moreex ads,GNAT MD5 g-md5 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id93}@anchor{389}@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38a}
+@anchor{gnat_rm/the_gnat_library id93}@anchor{38c}@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{38d}
@section @code{GNAT.Memory_Dump} (@code{g-memdum.ads})
@@ -24144,7 +24215,7 @@ standard output or standard error files. Uses GNAT.IO for actual
output.
@node GNAT Most_Recent_Exception g-moreex ads,GNAT OS_Lib g-os_lib ads,GNAT Memory_Dump g-memdum ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{38b}@anchor{gnat_rm/the_gnat_library id94}@anchor{38c}
+@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{38e}@anchor{gnat_rm/the_gnat_library id94}@anchor{38f}
@section @code{GNAT.Most_Recent_Exception} (@code{g-moreex.ads})
@@ -24158,7 +24229,7 @@ various logging purposes, including duplicating functionality of some
Ada 83 implementation dependent extensions.
@node GNAT OS_Lib g-os_lib ads,GNAT Perfect_Hash_Generators g-pehage ads,GNAT Most_Recent_Exception g-moreex ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{38d}@anchor{gnat_rm/the_gnat_library id95}@anchor{38e}
+@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{390}@anchor{gnat_rm/the_gnat_library id95}@anchor{391}
@section @code{GNAT.OS_Lib} (@code{g-os_lib.ads})
@@ -24174,7 +24245,7 @@ including a portable spawn procedure, and access to environment variables
and error return codes.
@node GNAT Perfect_Hash_Generators g-pehage ads,GNAT Random_Numbers g-rannum ads,GNAT OS_Lib g-os_lib ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{38f}@anchor{gnat_rm/the_gnat_library id96}@anchor{390}
+@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{392}@anchor{gnat_rm/the_gnat_library id96}@anchor{393}
@section @code{GNAT.Perfect_Hash_Generators} (@code{g-pehage.ads})
@@ -24192,7 +24263,7 @@ hashcode are in the same order. These hashing functions are very
convenient for use with realtime applications.
@node GNAT Random_Numbers g-rannum ads,GNAT Regexp g-regexp ads,GNAT Perfect_Hash_Generators g-pehage ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{391}@anchor{gnat_rm/the_gnat_library id97}@anchor{392}
+@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{394}@anchor{gnat_rm/the_gnat_library id97}@anchor{395}
@section @code{GNAT.Random_Numbers} (@code{g-rannum.ads})
@@ -24204,7 +24275,7 @@ Provides random number capabilities which extend those available in the
standard Ada library and are more convenient to use.
@node GNAT Regexp g-regexp ads,GNAT Registry g-regist ads,GNAT Random_Numbers g-rannum ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id98}@anchor{393}@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{258}
+@anchor{gnat_rm/the_gnat_library id98}@anchor{396}@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{25b}
@section @code{GNAT.Regexp} (@code{g-regexp.ads})
@@ -24220,7 +24291,7 @@ simplest of the three pattern matching packages provided, and is particularly
suitable for 'file globbing' applications.
@node GNAT Registry g-regist ads,GNAT Regpat g-regpat ads,GNAT Regexp g-regexp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id99}@anchor{394}@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{395}
+@anchor{gnat_rm/the_gnat_library id99}@anchor{397}@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{398}
@section @code{GNAT.Registry} (@code{g-regist.ads})
@@ -24234,7 +24305,7 @@ registry API, but at a lower level of abstraction, refer to the Win32.Winreg
package provided with the Win32Ada binding
@node GNAT Regpat g-regpat ads,GNAT Rewrite_Data g-rewdat ads,GNAT Registry g-regist ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id100}@anchor{396}@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{397}
+@anchor{gnat_rm/the_gnat_library id100}@anchor{399}@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{39a}
@section @code{GNAT.Regpat} (@code{g-regpat.ads})
@@ -24249,7 +24320,7 @@ from the original V7 style regular expression library written in C by
Henry Spencer (and binary compatible with this C library).
@node GNAT Rewrite_Data g-rewdat ads,GNAT Secondary_Stack_Info g-sestin ads,GNAT Regpat g-regpat ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id101}@anchor{398}@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{399}
+@anchor{gnat_rm/the_gnat_library id101}@anchor{39b}@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{39c}
@section @code{GNAT.Rewrite_Data} (@code{g-rewdat.ads})
@@ -24263,7 +24334,7 @@ full content to be processed is not loaded into memory all at once. This makes
this interface usable for large files or socket streams.
@node GNAT Secondary_Stack_Info g-sestin ads,GNAT Semaphores g-semaph ads,GNAT Rewrite_Data g-rewdat ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{39a}@anchor{gnat_rm/the_gnat_library id102}@anchor{39b}
+@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{39d}@anchor{gnat_rm/the_gnat_library id102}@anchor{39e}
@section @code{GNAT.Secondary_Stack_Info} (@code{g-sestin.ads})
@@ -24275,7 +24346,7 @@ Provide the capability to query the high water mark of the current task's
secondary stack.
@node GNAT Semaphores g-semaph ads,GNAT Serial_Communications g-sercom ads,GNAT Secondary_Stack_Info g-sestin ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id103}@anchor{39c}@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{39d}
+@anchor{gnat_rm/the_gnat_library id103}@anchor{39f}@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{3a0}
@section @code{GNAT.Semaphores} (@code{g-semaph.ads})
@@ -24286,7 +24357,7 @@ secondary stack.
Provides classic counting and binary semaphores using protected types.
@node GNAT Serial_Communications g-sercom ads,GNAT SHA1 g-sha1 ads,GNAT Semaphores g-semaph ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{39e}@anchor{gnat_rm/the_gnat_library id104}@anchor{39f}
+@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{3a1}@anchor{gnat_rm/the_gnat_library id104}@anchor{3a2}
@section @code{GNAT.Serial_Communications} (@code{g-sercom.ads})
@@ -24298,7 +24369,7 @@ Provides a simple interface to send and receive data over a serial
port. This is only supported on GNU/Linux and Windows.
@node GNAT SHA1 g-sha1 ads,GNAT SHA224 g-sha224 ads,GNAT Serial_Communications g-sercom ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{3a0}@anchor{gnat_rm/the_gnat_library id105}@anchor{3a1}
+@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{3a3}@anchor{gnat_rm/the_gnat_library id105}@anchor{3a4}
@section @code{GNAT.SHA1} (@code{g-sha1.ads})
@@ -24311,7 +24382,7 @@ and RFC 3174, and the HMAC-SHA1 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA224 g-sha224 ads,GNAT SHA256 g-sha256 ads,GNAT SHA1 g-sha1 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{3a2}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a3}
+@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{3a5}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a6}
@section @code{GNAT.SHA224} (@code{g-sha224.ads})
@@ -24324,7 +24395,7 @@ and the HMAC-SHA224 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA256 g-sha256 ads,GNAT SHA384 g-sha384 ads,GNAT SHA224 g-sha224 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{3a4}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a5}
+@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{3a7}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a8}
@section @code{GNAT.SHA256} (@code{g-sha256.ads})
@@ -24337,7 +24408,7 @@ and the HMAC-SHA256 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA384 g-sha384 ads,GNAT SHA512 g-sha512 ads,GNAT SHA256 g-sha256 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id108}@anchor{3a6}@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3a7}
+@anchor{gnat_rm/the_gnat_library id108}@anchor{3a9}@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3aa}
@section @code{GNAT.SHA384} (@code{g-sha384.ads})
@@ -24350,7 +24421,7 @@ and the HMAC-SHA384 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT SHA512 g-sha512 ads,GNAT Signals g-signal ads,GNAT SHA384 g-sha384 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id109}@anchor{3a8}@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3a9}
+@anchor{gnat_rm/the_gnat_library id109}@anchor{3ab}@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3ac}
@section @code{GNAT.SHA512} (@code{g-sha512.ads})
@@ -24363,7 +24434,7 @@ and the HMAC-SHA512 message authentication function as described
in RFC 2104 and FIPS PUB 198.
@node GNAT Signals g-signal ads,GNAT Sockets g-socket ads,GNAT SHA512 g-sha512 ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3aa}@anchor{gnat_rm/the_gnat_library id110}@anchor{3ab}
+@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3ad}@anchor{gnat_rm/the_gnat_library id110}@anchor{3ae}
@section @code{GNAT.Signals} (@code{g-signal.ads})
@@ -24375,7 +24446,7 @@ Provides the ability to manipulate the blocked status of signals on supported
targets.
@node GNAT Sockets g-socket ads,GNAT Source_Info g-souinf ads,GNAT Signals g-signal ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3ac}@anchor{gnat_rm/the_gnat_library id111}@anchor{3ad}
+@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3af}@anchor{gnat_rm/the_gnat_library id111}@anchor{3b0}
@section @code{GNAT.Sockets} (@code{g-socket.ads})
@@ -24390,7 +24461,7 @@ on all native GNAT ports and on VxWorks cross prots. It is not implemented for
the LynxOS cross port.
@node GNAT Source_Info g-souinf ads,GNAT Spelling_Checker g-speche ads,GNAT Sockets g-socket ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3ae}@anchor{gnat_rm/the_gnat_library id112}@anchor{3af}
+@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3b1}@anchor{gnat_rm/the_gnat_library id112}@anchor{3b2}
@section @code{GNAT.Source_Info} (@code{g-souinf.ads})
@@ -24404,7 +24475,7 @@ subprograms yielding the date and time of the current compilation (like the
C macros @code{__DATE__} and @code{__TIME__})
@node GNAT Spelling_Checker g-speche ads,GNAT Spelling_Checker_Generic g-spchge ads,GNAT Source_Info g-souinf ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3b0}@anchor{gnat_rm/the_gnat_library id113}@anchor{3b1}
+@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3b3}@anchor{gnat_rm/the_gnat_library id113}@anchor{3b4}
@section @code{GNAT.Spelling_Checker} (@code{g-speche.ads})
@@ -24416,7 +24487,7 @@ Provides a function for determining whether one string is a plausible
near misspelling of another string.
@node GNAT Spelling_Checker_Generic g-spchge ads,GNAT Spitbol Patterns g-spipat ads,GNAT Spelling_Checker g-speche ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3b2}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b3}
+@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3b5}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b6}
@section @code{GNAT.Spelling_Checker_Generic} (@code{g-spchge.ads})
@@ -24429,7 +24500,7 @@ determining whether one string is a plausible near misspelling of another
string.
@node GNAT Spitbol Patterns g-spipat ads,GNAT Spitbol g-spitbo ads,GNAT Spelling_Checker_Generic g-spchge ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3b4}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b5}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3b7}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b8}
@section @code{GNAT.Spitbol.Patterns} (@code{g-spipat.ads})
@@ -24445,7 +24516,7 @@ the SNOBOL4 dynamic pattern construction and matching capabilities, using the
efficient algorithm developed by Robert Dewar for the SPITBOL system.
@node GNAT Spitbol g-spitbo ads,GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Patterns g-spipat ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id116}@anchor{3b6}@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3b7}
+@anchor{gnat_rm/the_gnat_library id116}@anchor{3b9}@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3ba}
@section @code{GNAT.Spitbol} (@code{g-spitbo.ads})
@@ -24460,7 +24531,7 @@ useful for constructing arbitrary mappings from strings in the style of
the SNOBOL4 TABLE function.
@node GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Table_Integer g-sptain ads,GNAT Spitbol g-spitbo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3b8}@anchor{gnat_rm/the_gnat_library id117}@anchor{3b9}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3bb}@anchor{gnat_rm/the_gnat_library id117}@anchor{3bc}
@section @code{GNAT.Spitbol.Table_Boolean} (@code{g-sptabo.ads})
@@ -24475,7 +24546,7 @@ for type @code{Standard.Boolean}, giving an implementation of sets of
string values.
@node GNAT Spitbol Table_Integer g-sptain ads,GNAT Spitbol Table_VString g-sptavs ads,GNAT Spitbol Table_Boolean g-sptabo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3ba}@anchor{gnat_rm/the_gnat_library id118}@anchor{3bb}
+@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3bd}@anchor{gnat_rm/the_gnat_library id118}@anchor{3be}
@section @code{GNAT.Spitbol.Table_Integer} (@code{g-sptain.ads})
@@ -24492,7 +24563,7 @@ for type @code{Standard.Integer}, giving an implementation of maps
from string to integer values.
@node GNAT Spitbol Table_VString g-sptavs ads,GNAT SSE g-sse ads,GNAT Spitbol Table_Integer g-sptain ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id119}@anchor{3bc}@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3bd}
+@anchor{gnat_rm/the_gnat_library id119}@anchor{3bf}@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3c0}
@section @code{GNAT.Spitbol.Table_VString} (@code{g-sptavs.ads})
@@ -24509,7 +24580,7 @@ a variable length string type, giving an implementation of general
maps from strings to strings.
@node GNAT SSE g-sse ads,GNAT SSE Vector_Types g-ssvety ads,GNAT Spitbol Table_VString g-sptavs ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id120}@anchor{3be}@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3bf}
+@anchor{gnat_rm/the_gnat_library id120}@anchor{3c1}@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3c2}
@section @code{GNAT.SSE} (@code{g-sse.ads})
@@ -24521,7 +24592,7 @@ targets. It exposes vector component types together with a general
introduction to the binding contents and use.
@node GNAT SSE Vector_Types g-ssvety ads,GNAT String_Hash g-strhas ads,GNAT SSE g-sse ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3c0}@anchor{gnat_rm/the_gnat_library id121}@anchor{3c1}
+@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3c3}@anchor{gnat_rm/the_gnat_library id121}@anchor{3c4}
@section @code{GNAT.SSE.Vector_Types} (@code{g-ssvety.ads})
@@ -24530,7 +24601,7 @@ introduction to the binding contents and use.
SSE vector types for use with SSE related intrinsics.
@node GNAT String_Hash g-strhas ads,GNAT Strings g-string ads,GNAT SSE Vector_Types g-ssvety ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3c2}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c3}
+@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3c5}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c6}
@section @code{GNAT.String_Hash} (@code{g-strhas.ads})
@@ -24542,7 +24613,7 @@ Provides a generic hash function working on arrays of scalars. Both the scalar
type and the hash result type are parameters.
@node GNAT Strings g-string ads,GNAT String_Split g-strspl ads,GNAT String_Hash g-strhas ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id123}@anchor{3c4}@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c5}
+@anchor{gnat_rm/the_gnat_library id123}@anchor{3c7}@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3c8}
@section @code{GNAT.Strings} (@code{g-string.ads})
@@ -24552,7 +24623,7 @@ Common String access types and related subprograms. Basically it
defines a string access and an array of string access types.
@node GNAT String_Split g-strspl ads,GNAT Table g-table ads,GNAT Strings g-string ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3c6}@anchor{gnat_rm/the_gnat_library id124}@anchor{3c7}
+@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3c9}@anchor{gnat_rm/the_gnat_library id124}@anchor{3ca}
@section @code{GNAT.String_Split} (@code{g-strspl.ads})
@@ -24566,7 +24637,7 @@ to the resulting slices. This package is instantiated from
@code{GNAT.Array_Split}.
@node GNAT Table g-table ads,GNAT Task_Lock g-tasloc ads,GNAT String_Split g-strspl ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id125}@anchor{3c8}@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3c9}
+@anchor{gnat_rm/the_gnat_library id125}@anchor{3cb}@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3cc}
@section @code{GNAT.Table} (@code{g-table.ads})
@@ -24586,7 +24657,7 @@ while an instantiation of @code{GNAT.Dynamic_Tables} creates a type that can be
used to define dynamic instances of the table.
@node GNAT Task_Lock g-tasloc ads,GNAT Time_Stamp g-timsta ads,GNAT Table g-table ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id126}@anchor{3ca}@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3cb}
+@anchor{gnat_rm/the_gnat_library id126}@anchor{3cd}@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3ce}
@section @code{GNAT.Task_Lock} (@code{g-tasloc.ads})
@@ -24603,7 +24674,7 @@ single global task lock. Appropriate for use in situations where contention
between tasks is very rarely expected.
@node GNAT Time_Stamp g-timsta ads,GNAT Threads g-thread ads,GNAT Task_Lock g-tasloc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id127}@anchor{3cc}@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3cd}
+@anchor{gnat_rm/the_gnat_library id127}@anchor{3cf}@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3d0}
@section @code{GNAT.Time_Stamp} (@code{g-timsta.ads})
@@ -24618,7 +24689,7 @@ represents the current date and time in ISO 8601 format. This is a very simple
routine with minimal code and there are no dependencies on any other unit.
@node GNAT Threads g-thread ads,GNAT Traceback g-traceb ads,GNAT Time_Stamp g-timsta ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3ce}@anchor{gnat_rm/the_gnat_library id128}@anchor{3cf}
+@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3d1}@anchor{gnat_rm/the_gnat_library id128}@anchor{3d2}
@section @code{GNAT.Threads} (@code{g-thread.ads})
@@ -24635,7 +24706,7 @@ further details if your program has threads that are created by a non-Ada
environment which then accesses Ada code.
@node GNAT Traceback g-traceb ads,GNAT Traceback Symbolic g-trasym ads,GNAT Threads g-thread ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id129}@anchor{3d0}@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d1}
+@anchor{gnat_rm/the_gnat_library id129}@anchor{3d3}@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3d4}
@section @code{GNAT.Traceback} (@code{g-traceb.ads})
@@ -24647,7 +24718,7 @@ Provides a facility for obtaining non-symbolic traceback information, useful
in various debugging situations.
@node GNAT Traceback Symbolic g-trasym ads,GNAT UTF_32 g-table ads,GNAT Traceback g-traceb ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id130}@anchor{3d2}@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d3}
+@anchor{gnat_rm/the_gnat_library id130}@anchor{3d5}@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3d6}
@section @code{GNAT.Traceback.Symbolic} (@code{g-trasym.ads})
@@ -24656,7 +24727,7 @@ in various debugging situations.
@geindex Trace back facilities
@node GNAT UTF_32 g-table ads,GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Traceback Symbolic g-trasym ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id131}@anchor{3d4}@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d5}
+@anchor{gnat_rm/the_gnat_library id131}@anchor{3d7}@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d8}
@section @code{GNAT.UTF_32} (@code{g-table.ads})
@@ -24675,7 +24746,7 @@ lower case to upper case fold routine corresponding to
the Ada 2005 rules for identifier equivalence.
@node GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Wide_Spelling_Checker g-wispch ads,GNAT UTF_32 g-table ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3d6}@anchor{gnat_rm/the_gnat_library id132}@anchor{3d7}
+@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3d9}@anchor{gnat_rm/the_gnat_library id132}@anchor{3da}
@section @code{GNAT.Wide_Spelling_Checker} (@code{g-u3spch.ads})
@@ -24688,7 +24759,7 @@ near misspelling of another wide wide string, where the strings are represented
using the UTF_32_String type defined in System.Wch_Cnv.
@node GNAT Wide_Spelling_Checker g-wispch ads,GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Spelling_Checker g-u3spch ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3d8}@anchor{gnat_rm/the_gnat_library id133}@anchor{3d9}
+@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3db}@anchor{gnat_rm/the_gnat_library id133}@anchor{3dc}
@section @code{GNAT.Wide_Spelling_Checker} (@code{g-wispch.ads})
@@ -24700,7 +24771,7 @@ Provides a function for determining whether one wide string is a plausible
near misspelling of another wide string.
@node GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Spelling_Checker g-wispch ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id134}@anchor{3da}@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3db}
+@anchor{gnat_rm/the_gnat_library id134}@anchor{3dd}@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3de}
@section @code{GNAT.Wide_String_Split} (@code{g-wistsp.ads})
@@ -24714,7 +24785,7 @@ to the resulting slices. This package is instantiated from
@code{GNAT.Array_Split}.
@node GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Wide_String_Split g-zistsp ads,GNAT Wide_String_Split g-wistsp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3dc}@anchor{gnat_rm/the_gnat_library id135}@anchor{3dd}
+@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3df}@anchor{gnat_rm/the_gnat_library id135}@anchor{3e0}
@section @code{GNAT.Wide_Wide_Spelling_Checker} (@code{g-zspche.ads})
@@ -24726,7 +24797,7 @@ Provides a function for determining whether one wide wide string is a plausible
near misspelling of another wide wide string.
@node GNAT Wide_Wide_String_Split g-zistsp ads,Interfaces C Extensions i-cexten ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3de}@anchor{gnat_rm/the_gnat_library id136}@anchor{3df}
+@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3e1}@anchor{gnat_rm/the_gnat_library id136}@anchor{3e2}
@section @code{GNAT.Wide_Wide_String_Split} (@code{g-zistsp.ads})
@@ -24740,7 +24811,7 @@ to the resulting slices. This package is instantiated from
@code{GNAT.Array_Split}.
@node Interfaces C Extensions i-cexten ads,Interfaces C Streams i-cstrea ads,GNAT Wide_Wide_String_Split g-zistsp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e0}@anchor{gnat_rm/the_gnat_library id137}@anchor{3e1}
+@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3e3}@anchor{gnat_rm/the_gnat_library id137}@anchor{3e4}
@section @code{Interfaces.C.Extensions} (@code{i-cexten.ads})
@@ -24751,7 +24822,7 @@ for use with either manually or automatically generated bindings
to C libraries.
@node Interfaces C Streams i-cstrea ads,Interfaces Packed_Decimal i-pacdec ads,Interfaces C Extensions i-cexten ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id138}@anchor{3e2}@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3e3}
+@anchor{gnat_rm/the_gnat_library id138}@anchor{3e5}@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3e6}
@section @code{Interfaces.C.Streams} (@code{i-cstrea.ads})
@@ -24764,7 +24835,7 @@ This package is a binding for the most commonly used operations
on C streams.
@node Interfaces Packed_Decimal i-pacdec ads,Interfaces VxWorks i-vxwork ads,Interfaces C Streams i-cstrea ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e4}@anchor{gnat_rm/the_gnat_library id139}@anchor{3e5}
+@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e7}@anchor{gnat_rm/the_gnat_library id139}@anchor{3e8}
@section @code{Interfaces.Packed_Decimal} (@code{i-pacdec.ads})
@@ -24779,7 +24850,7 @@ from a packed decimal format compatible with that used on IBM
mainframes.
@node Interfaces VxWorks i-vxwork ads,Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces Packed_Decimal i-pacdec ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e6}@anchor{gnat_rm/the_gnat_library id140}@anchor{3e7}
+@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e9}@anchor{gnat_rm/the_gnat_library id140}@anchor{3ea}
@section @code{Interfaces.VxWorks} (@code{i-vxwork.ads})
@@ -24795,7 +24866,7 @@ In particular, it interfaces with the
VxWorks hardware interrupt facilities.
@node Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces VxWorks IO i-vxwoio ads,Interfaces VxWorks i-vxwork ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3e8}@anchor{gnat_rm/the_gnat_library id141}@anchor{3e9}
+@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3eb}@anchor{gnat_rm/the_gnat_library id141}@anchor{3ec}
@section @code{Interfaces.VxWorks.Int_Connection} (@code{i-vxinco.ads})
@@ -24811,7 +24882,7 @@ intConnect() with a custom routine for installing interrupt
handlers.
@node Interfaces VxWorks IO i-vxwoio ads,System Address_Image s-addima ads,Interfaces VxWorks Int_Connection i-vxinco ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ea}@anchor{gnat_rm/the_gnat_library id142}@anchor{3eb}
+@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3ed}@anchor{gnat_rm/the_gnat_library id142}@anchor{3ee}
@section @code{Interfaces.VxWorks.IO} (@code{i-vxwoio.ads})
@@ -24834,7 +24905,7 @@ function codes. A particular use of this package is
to enable the use of Get_Immediate under VxWorks.
@node System Address_Image s-addima ads,System Assertions s-assert ads,Interfaces VxWorks IO i-vxwoio ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3ec}@anchor{gnat_rm/the_gnat_library id143}@anchor{3ed}
+@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3ef}@anchor{gnat_rm/the_gnat_library id143}@anchor{3f0}
@section @code{System.Address_Image} (@code{s-addima.ads})
@@ -24850,7 +24921,7 @@ function that gives an (implementation dependent)
string which identifies an address.
@node System Assertions s-assert ads,System Atomic_Counters s-atocou ads,System Address_Image s-addima ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id144}@anchor{3ee}@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3ef}
+@anchor{gnat_rm/the_gnat_library id144}@anchor{3f1}@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3f2}
@section @code{System.Assertions} (@code{s-assert.ads})
@@ -24866,7 +24937,7 @@ by an run-time assertion failure, as well as the routine that
is used internally to raise this assertion.
@node System Atomic_Counters s-atocou ads,System Memory s-memory ads,System Assertions s-assert ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id145}@anchor{3f0}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3f1}
+@anchor{gnat_rm/the_gnat_library id145}@anchor{3f3}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3f4}
@section @code{System.Atomic_Counters} (@code{s-atocou.ads})
@@ -24880,7 +24951,7 @@ on most targets, including all Alpha, ia64, PowerPC, SPARC V9,
x86, and x86_64 platforms.
@node System Memory s-memory ads,System Multiprocessors s-multip ads,System Atomic_Counters s-atocou ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f2}@anchor{gnat_rm/the_gnat_library id146}@anchor{3f3}
+@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3f5}@anchor{gnat_rm/the_gnat_library id146}@anchor{3f6}
@section @code{System.Memory} (@code{s-memory.ads})
@@ -24898,7 +24969,7 @@ calls to this unit may be made for low level allocation uses (for
example see the body of @code{GNAT.Tables}).
@node System Multiprocessors s-multip ads,System Multiprocessors Dispatching_Domains s-mudido ads,System Memory s-memory ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id147}@anchor{3f4}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f5}
+@anchor{gnat_rm/the_gnat_library id147}@anchor{3f7}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f8}
@section @code{System.Multiprocessors} (@code{s-multip.ads})
@@ -24911,7 +24982,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is
technically an implementation-defined addition).
@node System Multiprocessors Dispatching_Domains s-mudido ads,System Partition_Interface s-parint ads,System Multiprocessors s-multip ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f6}@anchor{gnat_rm/the_gnat_library id148}@anchor{3f7}
+@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f9}@anchor{gnat_rm/the_gnat_library id148}@anchor{3fa}
@section @code{System.Multiprocessors.Dispatching_Domains} (@code{s-mudido.ads})
@@ -24924,7 +24995,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is
technically an implementation-defined addition).
@node System Partition_Interface s-parint ads,System Pool_Global s-pooglo ads,System Multiprocessors Dispatching_Domains s-mudido ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id149}@anchor{3f8}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3f9}
+@anchor{gnat_rm/the_gnat_library id149}@anchor{3fb}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3fc}
@section @code{System.Partition_Interface} (@code{s-parint.ads})
@@ -24937,7 +25008,7 @@ is used primarily in a distribution context when using Annex E
with @code{GLADE}.
@node System Pool_Global s-pooglo ads,System Pool_Local s-pooloc ads,System Partition_Interface s-parint ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id150}@anchor{3fa}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3fb}
+@anchor{gnat_rm/the_gnat_library id150}@anchor{3fd}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3fe}
@section @code{System.Pool_Global} (@code{s-pooglo.ads})
@@ -24954,7 +25025,7 @@ declared. It uses malloc/free to allocate/free and does not attempt to
do any automatic reclamation.
@node System Pool_Local s-pooloc ads,System Restrictions s-restri ads,System Pool_Global s-pooglo ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3fc}@anchor{gnat_rm/the_gnat_library id151}@anchor{3fd}
+@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3ff}@anchor{gnat_rm/the_gnat_library id151}@anchor{400}
@section @code{System.Pool_Local} (@code{s-pooloc.ads})
@@ -24971,7 +25042,7 @@ a list of allocated blocks, so that all storage allocated for the pool can
be freed automatically when the pool is finalized.
@node System Restrictions s-restri ads,System Rident s-rident ads,System Pool_Local s-pooloc ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id152}@anchor{3fe}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{3ff}
+@anchor{gnat_rm/the_gnat_library id152}@anchor{401}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{402}
@section @code{System.Restrictions} (@code{s-restri.ads})
@@ -24987,7 +25058,7 @@ compiler determined information on which restrictions
are violated by one or more packages in the partition.
@node System Rident s-rident ads,System Strings Stream_Ops s-ststop ads,System Restrictions s-restri ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{400}@anchor{gnat_rm/the_gnat_library id153}@anchor{401}
+@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{403}@anchor{gnat_rm/the_gnat_library id153}@anchor{404}
@section @code{System.Rident} (@code{s-rident.ads})
@@ -25003,7 +25074,7 @@ since the necessary instantiation is included in
package System.Restrictions.
@node System Strings Stream_Ops s-ststop ads,System Unsigned_Types s-unstyp ads,System Rident s-rident ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id154}@anchor{402}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{403}
+@anchor{gnat_rm/the_gnat_library id154}@anchor{405}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{406}
@section @code{System.Strings.Stream_Ops} (@code{s-ststop.ads})
@@ -25019,7 +25090,7 @@ stream attributes are applied to string types, but the subprograms in this
package can be used directly by application programs.
@node System Unsigned_Types s-unstyp ads,System Wch_Cnv s-wchcnv ads,System Strings Stream_Ops s-ststop ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{404}@anchor{gnat_rm/the_gnat_library id155}@anchor{405}
+@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{407}@anchor{gnat_rm/the_gnat_library id155}@anchor{408}
@section @code{System.Unsigned_Types} (@code{s-unstyp.ads})
@@ -25032,7 +25103,7 @@ also contains some related definitions for other specialized types
used by the compiler in connection with packed array types.
@node System Wch_Cnv s-wchcnv ads,System Wch_Con s-wchcon ads,System Unsigned_Types s-unstyp ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{406}@anchor{gnat_rm/the_gnat_library id156}@anchor{407}
+@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{409}@anchor{gnat_rm/the_gnat_library id156}@anchor{40a}
@section @code{System.Wch_Cnv} (@code{s-wchcnv.ads})
@@ -25053,7 +25124,7 @@ encoding method. It uses definitions in
package @code{System.Wch_Con}.
@node System Wch_Con s-wchcon ads,,System Wch_Cnv s-wchcnv ads,The GNAT Library
-@anchor{gnat_rm/the_gnat_library id157}@anchor{408}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{409}
+@anchor{gnat_rm/the_gnat_library id157}@anchor{40b}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{40c}
@section @code{System.Wch_Con} (@code{s-wchcon.ads})
@@ -25065,7 +25136,7 @@ in ordinary strings. These definitions are used by
the package @code{System.Wch_Cnv}.
@node Interfacing to Other Languages,Specialized Needs Annexes,The GNAT Library,Top
-@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40a}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40b}
+@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{40d}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{40e}
@chapter Interfacing to Other Languages
@@ -25083,7 +25154,7 @@ provided.
@end menu
@node Interfacing to C,Interfacing to C++,,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{40d}
+@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{40f}@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{410}
@section Interfacing to C
@@ -25223,7 +25294,7 @@ of the length corresponding to the @code{type'Size} value in Ada.
@end itemize
@node Interfacing to C++,Interfacing to COBOL,Interfacing to C,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{47}
+@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{411}@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{47}
@section Interfacing to C++
@@ -25280,7 +25351,7 @@ The @code{External_Name} is the name of the C++ RTTI symbol. You can then
cover a specific C++ exception in an exception handler.
@node Interfacing to COBOL,Interfacing to Fortran,Interfacing to C++,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{40f}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{410}
+@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{412}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{413}
@section Interfacing to COBOL
@@ -25288,7 +25359,7 @@ Interfacing to COBOL is achieved as described in section B.4 of
the Ada Reference Manual.
@node Interfacing to Fortran,Interfacing to non-GNAT Ada code,Interfacing to COBOL,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{411}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{412}
+@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{414}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{415}
@section Interfacing to Fortran
@@ -25298,7 +25369,7 @@ multi-dimensional array causes the array to be stored in column-major
order as required for convenient interface to Fortran.
@node Interfacing to non-GNAT Ada code,,Interfacing to Fortran,Interfacing to Other Languages
-@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{413}@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{414}
+@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{416}@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{417}
@section Interfacing to non-GNAT Ada code
@@ -25322,7 +25393,7 @@ values or simple record types without variants, or simple array
types with fixed bounds.
@node Specialized Needs Annexes,Implementation of Specific Ada Features,Interfacing to Other Languages,Top
-@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{415}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{416}
+@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{418}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{419}
@chapter Specialized Needs Annexes
@@ -25363,7 +25434,7 @@ in Ada 2005) is fully implemented.
@end table
@node Implementation of Specific Ada Features,Implementation of Ada 2012 Features,Specialized Needs Annexes,Top
-@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{417}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{418}
+@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{41a}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{41b}
@chapter Implementation of Specific Ada Features
@@ -25381,7 +25452,7 @@ facilities.
@end menu
@node Machine Code Insertions,GNAT Implementation of Tasking,,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{169}@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{419}
+@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{169}@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{41c}
@section Machine Code Insertions
@@ -25549,7 +25620,7 @@ according to normal visibility rules. In particular if there is no
qualification is required.
@node GNAT Implementation of Tasking,GNAT Implementation of Shared Passive Packages,Machine Code Insertions,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41a}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{41b}
+@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{41d}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{41e}
@section GNAT Implementation of Tasking
@@ -25565,7 +25636,7 @@ to compliance with the Real-Time Systems Annex.
@end menu
@node Mapping Ada Tasks onto the Underlying Kernel Threads,Ensuring Compliance with the Real-Time Annex,,GNAT Implementation of Tasking
-@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{41d}
+@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{41f}@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{420}
@subsection Mapping Ada Tasks onto the Underlying Kernel Threads
@@ -25634,7 +25705,7 @@ support this functionality when the parent contains more than one task.
@geindex Forking a new process
@node Ensuring Compliance with the Real-Time Annex,Support for Locking Policies,Mapping Ada Tasks onto the Underlying Kernel Threads,GNAT Implementation of Tasking
-@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{41f}
+@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{421}@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{422}
@subsection Ensuring Compliance with the Real-Time Annex
@@ -25685,7 +25756,7 @@ placed at the end.
@c Support_for_Locking_Policies
@node Support for Locking Policies,,Ensuring Compliance with the Real-Time Annex,GNAT Implementation of Tasking
-@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{420}
+@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{423}
@subsection Support for Locking Policies
@@ -25719,7 +25790,7 @@ then ceiling locking is used.
Otherwise, the @code{Ceiling_Locking} policy is ignored.
@node GNAT Implementation of Shared Passive Packages,Code Generation for Array Aggregates,GNAT Implementation of Tasking,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{421}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{422}
+@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{424}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{425}
@section GNAT Implementation of Shared Passive Packages
@@ -25817,7 +25888,7 @@ This is used to provide the required locking
semantics for proper protected object synchronization.
@node Code Generation for Array Aggregates,The Size of Discriminated Records with Default Discriminants,GNAT Implementation of Shared Passive Packages,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{423}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{424}
+@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{426}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{427}
@section Code Generation for Array Aggregates
@@ -25848,7 +25919,7 @@ component values and static subtypes also lead to simpler code.
@end menu
@node Static constant aggregates with static bounds,Constant aggregates with unconstrained nominal types,,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{425}@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{426}
+@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{428}@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{429}
@subsection Static constant aggregates with static bounds
@@ -25895,7 +25966,7 @@ Zero2: constant two_dim := (others => (others => 0));
@end example
@node Constant aggregates with unconstrained nominal types,Aggregates with static bounds,Static constant aggregates with static bounds,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{427}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{428}
+@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{42a}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{42b}
@subsection Constant aggregates with unconstrained nominal types
@@ -25910,7 +25981,7 @@ Cr_Unc : constant One_Unc := (12,24,36);
@end example
@node Aggregates with static bounds,Aggregates with nonstatic bounds,Constant aggregates with unconstrained nominal types,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{429}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{42a}
+@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{42c}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{42d}
@subsection Aggregates with static bounds
@@ -25938,7 +26009,7 @@ end loop;
@end example
@node Aggregates with nonstatic bounds,Aggregates in assignment statements,Aggregates with static bounds,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{42b}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{42c}
+@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{42e}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{42f}
@subsection Aggregates with nonstatic bounds
@@ -25949,7 +26020,7 @@ have to be applied to sub-arrays individually, if they do not have statically
compatible subtypes.
@node Aggregates in assignment statements,,Aggregates with nonstatic bounds,Code Generation for Array Aggregates
-@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{42d}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{42e}
+@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{430}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{431}
@subsection Aggregates in assignment statements
@@ -25991,7 +26062,7 @@ a temporary (created either by the front-end or the code generator) and then
that temporary will be copied onto the target.
@node The Size of Discriminated Records with Default Discriminants,Strict Conformance to the Ada Reference Manual,Code Generation for Array Aggregates,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{42f}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{430}
+@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{432}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{433}
@section The Size of Discriminated Records with Default Discriminants
@@ -26071,7 +26142,7 @@ say) must be consistent, so it is imperative that the object, once created,
remain invariant.
@node Strict Conformance to the Ada Reference Manual,,The Size of Discriminated Records with Default Discriminants,Implementation of Specific Ada Features
-@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{431}@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{432}
+@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{434}@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{435}
@section Strict Conformance to the Ada Reference Manual
@@ -26098,7 +26169,7 @@ behavior (although at the cost of a significant performance penalty), so
infinite and NaN values are properly generated.
@node Implementation of Ada 2012 Features,Obsolescent Features,Implementation of Specific Ada Features,Top
-@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{433}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{434}
+@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{436}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{437}
@chapter Implementation of Ada 2012 Features
@@ -28264,7 +28335,7 @@ RM References: H.04 (8/1)
@end itemize
@node Obsolescent Features,Compatibility and Porting Guide,Implementation of Ada 2012 Features,Top
-@anchor{gnat_rm/obsolescent_features id1}@anchor{435}@anchor{gnat_rm/obsolescent_features doc}@anchor{436}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15}
+@anchor{gnat_rm/obsolescent_features id1}@anchor{438}@anchor{gnat_rm/obsolescent_features doc}@anchor{439}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15}
@chapter Obsolescent Features
@@ -28283,7 +28354,7 @@ compatibility purposes.
@end menu
@node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id2}@anchor{437}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{438}
+@anchor{gnat_rm/obsolescent_features id2}@anchor{43a}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{43b}
@section pragma No_Run_Time
@@ -28296,7 +28367,7 @@ preferred usage is to use an appropriately configured run-time that
includes just those features that are to be made accessible.
@node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features id3}@anchor{439}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{43a}
+@anchor{gnat_rm/obsolescent_features id3}@anchor{43c}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{43d}
@section pragma Ravenscar
@@ -28305,7 +28376,7 @@ The pragma @code{Ravenscar} has exactly the same effect as pragma
is part of the new Ada 2005 standard.
@node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{43b}@anchor{gnat_rm/obsolescent_features id4}@anchor{43c}
+@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{43e}@anchor{gnat_rm/obsolescent_features id4}@anchor{43f}
@section pragma Restricted_Run_Time
@@ -28315,7 +28386,7 @@ preferred since the Ada 2005 pragma @code{Profile} is intended for
this kind of implementation dependent addition.
@node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{43d}@anchor{gnat_rm/obsolescent_features id5}@anchor{43e}
+@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{440}@anchor{gnat_rm/obsolescent_features id5}@anchor{441}
@section pragma Task_Info
@@ -28341,7 +28412,7 @@ in the spec of package System.Task_Info in the runtime
library.
@node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features
-@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{43f}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{440}
+@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{442}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{443}
@section package System.Task_Info (@code{s-tasinf.ads})
@@ -28351,7 +28422,7 @@ to support the @code{Task_Info} pragma. The predefined Ada package
standard replacement for GNAT's @code{Task_Info} functionality.
@node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{441}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{442}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{444}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{445}
@chapter Compatibility and Porting Guide
@@ -28373,7 +28444,7 @@ applications developed in other Ada environments.
@end menu
@node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{443}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{444}
+@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{446}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{447}
@section Writing Portable Fixed-Point Declarations
@@ -28495,7 +28566,7 @@ If you follow this scheme you will be guaranteed that your fixed-point
types will be portable.
@node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{445}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{446}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{448}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{449}
@section Compatibility with Ada 83
@@ -28523,7 +28594,7 @@ following subsections treat the most likely issues to be encountered.
@end menu
@node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{447}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{448}
+@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{44a}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{44b}
@subsection Legal Ada 83 programs that are illegal in Ada 95
@@ -28623,7 +28694,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration.
@end itemize
@node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{449}@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44a}
+@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{44c}@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{44d}
@subsection More deterministic semantics
@@ -28651,7 +28722,7 @@ which open select branches are executed.
@end itemize
@node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{44b}@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44c}
+@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{44e}@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{44f}
@subsection Changed semantics
@@ -28693,7 +28764,7 @@ covers only the restricted range.
@end itemize
@node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83
-@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{44d}@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{44e}
+@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{450}@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{451}
@subsection Other language compatibility issues
@@ -28726,7 +28797,7 @@ include @code{pragma Interface} and the floating point type attributes
@end itemize
@node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{44f}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{450}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{452}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{453}
@section Compatibility between Ada 95 and Ada 2005
@@ -28798,7 +28869,7 @@ can declare a function returning a value from an anonymous access type.
@end itemize
@node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{451}@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{452}
+@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{454}@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{455}
@section Implementation-dependent characteristics
@@ -28821,7 +28892,7 @@ transition from certain Ada 83 compilers.
@end menu
@node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{453}@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{454}
+@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{456}@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{457}
@subsection Implementation-defined pragmas
@@ -28843,7 +28914,7 @@ avoiding compiler rejection of units that contain such pragmas; they are not
relevant in a GNAT context and hence are not otherwise implemented.
@node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{455}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{456}
+@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{458}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{459}
@subsection Implementation-defined attributes
@@ -28857,7 +28928,7 @@ Ada 83, GNAT supplies the attributes @code{Bit}, @code{Machine_Size} and
@code{Type_Class}.
@node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{458}
+@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{45a}@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{45b}
@subsection Libraries
@@ -28886,7 +28957,7 @@ be preferable to retrofit the application using modular types.
@end itemize
@node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{45a}
+@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{45c}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{45d}
@subsection Elaboration order
@@ -28922,7 +28993,7 @@ pragmas either globally (as an effect of the @emph{-gnatE} switch) or locally
@end itemize
@node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics
-@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{45b}@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45c}
+@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{45e}@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{45f}
@subsection Target-specific aspects
@@ -28935,10 +29006,10 @@ on the robustness of the original design. Moreover, Ada 95 (and thus
Ada 2005 and Ada 2012) are sometimes
incompatible with typical Ada 83 compiler practices regarding implicit
packing, the meaning of the Size attribute, and the size of access values.
-GNAT's approach to these issues is described in @ref{45d,,Representation Clauses}.
+GNAT's approach to these issues is described in @ref{460,,Representation Clauses}.
@node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{45e}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{45f}
+@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{461}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{462}
@section Compatibility with Other Ada Systems
@@ -28981,7 +29052,7 @@ far beyond this minimal set, as described in the next section.
@end itemize
@node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{45d}@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{460}
+@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{460}@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{463}
@section Representation Clauses
@@ -29074,7 +29145,7 @@ with thin pointers.
@end itemize
@node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide
-@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{461}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{462}
+@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{464}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{465}
@section Compatibility with HP Ada 83
@@ -29104,7 +29175,7 @@ extension of package System.
@end itemize
@node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top
-@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{463}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{464}
+@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{466}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{467}
@chapter GNU Free Documentation License
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 47618f6..2efa06f 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Sep 29, 2020
+GNAT User's Guide for Native Platforms , Dec 11, 2020
AdaCore
@@ -381,7 +381,7 @@ Performance Considerations
* Optimization Levels::
* Debugging Optimized Code::
* Inlining of Subprograms::
-* Floating_Point_Operations::
+* Floating Point Operations::
* Vectorization of loops::
* Other Optimization Switches::
* Optimization and Strict Aliasing::
@@ -2970,6 +2970,10 @@ temporary files that are immediately deleted; it doesn't make sense to
depend on a file that no longer exists. Such tools include
@code{gprbuild}, @code{gnatmake}, and @code{gnatcheck}.
+By default, configuration pragma files are stored by their absolute paths in
+ALI files. You can use the @code{-gnateb} switch in order to store them by
+their basename instead.
+
If you are using project file, a separate mechanism is provided using
project attributes.
@@ -8968,6 +8972,19 @@ an exception because @code{Self(Obj)} produces an anonymous object which does
not share the memory location of @code{Obj}.
@end table
+@geindex -gnateb (gcc)
+
+
+@table @asis
+
+@item @code{-gnateb}
+
+Store configuration files by their basename in ALI files. This switch is
+used for instance by gprbuild for distributed builds in order to prevent
+issues where machine-specific absolute paths could end up being stored in
+ALI files.
+@end table
+
@geindex -gnatec (gcc)
@@ -11490,7 +11507,7 @@ not included in this check.
@emph{Suppress warnings on redefinition of names in standard.}
-This switch activates warnings for declarations that declare a name that
+This switch disables warnings for declarations that declare a name that
is defined in package Standard.
@end table
@@ -13464,7 +13481,8 @@ but not @code{in} on its own.
All keywords must be in lower case (with the exception of keywords
such as @code{digits} used as attribute names to which this check
-does not apply).
+does not apply). A single error is reported for each line breaking
+this rule even if multiple casing issues exist on a same line.
@end table
@geindex -gnatyl (gcc)
@@ -15918,6 +15936,9 @@ Exclude source files (check object consistency only).
Use the target-independent XDR protocol for stream oriented attributes
instead of the default implementation which is based on direct binary
representations and is therefore target-and endianness-dependent.
+However it does not support 128-bit integer types and the exception
+@code{Ada.IO_Exceptions.Device_Error} is raised if any attempt is made
+at streaming 128-bit integer types with it.
@geindex -Xnnn (gnatbind)
@@ -19631,7 +19652,7 @@ some guidelines on debugging optimized code.
* Optimization Levels::
* Debugging Optimized Code::
* Inlining of Subprograms::
-* Floating_Point_Operations::
+* Floating Point Operations::
* Vectorization of loops::
* Other Optimization Switches::
* Optimization and Strict Aliasing::
@@ -19980,7 +20001,7 @@ Note that if you use @code{-g} you can then use the @code{strip} program
on the resulting executable,
which removes both debugging information and global symbols.
-@node Inlining of Subprograms,Floating_Point_Operations,Debugging Optimized Code,Performance Considerations
+@node Inlining of Subprograms,Floating Point Operations,Debugging Optimized Code,Performance Considerations
@anchor{gnat_ugn/gnat_and_program_execution id32}@anchor{185}@anchor{gnat_ugn/gnat_and_program_execution inlining-of-subprograms}@anchor{100}
@subsubsection Inlining of Subprograms
@@ -20119,9 +20140,9 @@ automatically assume that @code{-O3} is better than @code{-O2}, and
indeed you should use @code{-O3} only if tests show that it actually
improves performance for your program.
-@node Floating_Point_Operations,Vectorization of loops,Inlining of Subprograms,Performance Considerations
+@node Floating Point Operations,Vectorization of loops,Inlining of Subprograms,Performance Considerations
@anchor{gnat_ugn/gnat_and_program_execution floating-point-operations}@anchor{186}@anchor{gnat_ugn/gnat_and_program_execution id33}@anchor{187}
-@subsubsection Floating_Point_Operations
+@subsubsection Floating Point Operations
@geindex Floating-Point Operations
@@ -20167,7 +20188,7 @@ Note that the ABI has the same form for both floating-point models,
so it is permissible to mix units compiled with and without these
switches.
-@node Vectorization of loops,Other Optimization Switches,Floating_Point_Operations,Performance Considerations
+@node Vectorization of loops,Other Optimization Switches,Floating Point Operations,Performance Considerations
@anchor{gnat_ugn/gnat_and_program_execution id34}@anchor{188}@anchor{gnat_ugn/gnat_and_program_execution vectorization-of-loops}@anchor{189}
@subsubsection Vectorization of loops
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index 2cde430..e7262cd 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -999,7 +999,7 @@ package body Impunit is
for J in Non_Imp_File_Names_12'Range loop
if Name_Buffer (1 .. 8) = Non_Imp_File_Names_12 (J).Fname then
- return Non_Imp_File_Names_95 (J).RMdef
+ return Non_Imp_File_Names_12 (J).RMdef
and then Ada_Version >= Ada_2012;
end if;
end loop;
diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index b4d56b6..bb4d97c 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -1945,10 +1945,11 @@ package body Inline is
-------------------
procedure Cannot_Inline
- (Msg : String;
- N : Node_Id;
- Subp : Entity_Id;
- Is_Serious : Boolean := False)
+ (Msg : String;
+ N : Node_Id;
+ Subp : Entity_Id;
+ Is_Serious : Boolean := False;
+ Suppress_Info : Boolean := False)
is
begin
-- In GNATprove mode, inlining is the technical means by which the
@@ -1971,7 +1972,7 @@ package body Inline is
New_Msg (1 .. Len2) := "info: no contextual analysis of";
New_Msg (Len2 + 1 .. Msg'Length + Len2 - Len1) :=
Msg (Msg'First + Len1 .. Msg'Last);
- Cannot_Inline (New_Msg, N, Subp, Is_Serious);
+ Cannot_Inline (New_Msg, N, Subp, Is_Serious, Suppress_Info);
return;
end;
end if;
@@ -1992,14 +1993,14 @@ package body Inline is
then
null;
- -- In GNATprove mode, issue a warning when -gnatd_f is set, and
- -- indicate that the subprogram is not always inlined by setting
- -- flag Is_Inlined_Always to False.
+ -- In GNATprove mode, issue an info message when -gnatd_f is set and
+ -- Suppress_Info is False, and indicate that the subprogram is not
+ -- always inlined by setting flag Is_Inlined_Always to False.
elsif GNATprove_Mode then
Set_Is_Inlined_Always (Subp, False);
- if Debug_Flag_Underscore_F then
+ if Debug_Flag_Underscore_F and not Suppress_Info then
Error_Msg_NE (Msg, N, Subp);
end if;
@@ -2022,14 +2023,14 @@ package body Inline is
Error_Msg_NE (Msg (Msg'First .. Msg'Last - 1), N, Subp);
- -- In GNATprove mode, issue a warning when -gnatd_f is set, and
- -- indicate that the subprogram is not always inlined by setting
- -- flag Is_Inlined_Always to False.
+ -- In GNATprove mode, issue an info message when -gnatd_f is set and
+ -- Suppress_Info is False, and indicate that the subprogram is not
+ -- always inlined by setting flag Is_Inlined_Always to False.
elsif GNATprove_Mode then
Set_Is_Inlined_Always (Subp, False);
- if Debug_Flag_Underscore_F then
+ if Debug_Flag_Underscore_F and not Suppress_Info then
Error_Msg_NE (Msg, N, Subp);
end if;
@@ -2917,7 +2918,24 @@ package body Inline is
-- formal in the inlined code.
if Is_Entity_Name (A) and then Ekind (F) /= E_In_Parameter then
- Set_Last_Assignment (Entity (A), Empty);
+
+ -- In GNATprove mode a protected component acting as an actual
+ -- subprogram parameter will appear as inlined-for-proof. However,
+ -- its E_Component entity is not an assignable object, so the
+ -- assertion in Set_Last_Assignment will fail. We just omit the
+ -- call to Set_Last_Assignment, because GNATprove flags useless
+ -- assignments with its own flow analysis.
+ --
+ -- In GNAT mode such a problem does not occur, because protected
+ -- components are inlined via object renamings whose entity kind
+ -- E_Variable is assignable.
+
+ if Is_Assignable (Entity (A)) then
+ Set_Last_Assignment (Entity (A), Empty);
+ else
+ pragma Assert
+ (GNATprove_Mode and then Is_Protected_Component (Entity (A)));
+ end if;
end if;
-- If the argument may be a controlling argument in a call within
diff --git a/gcc/ada/inline.ads b/gcc/ada/inline.ads
index 51eab9c..6790f15 100644
--- a/gcc/ada/inline.ads
+++ b/gcc/ada/inline.ads
@@ -154,15 +154,17 @@ package Inline is
-- its treatment of the subprogram.
procedure Cannot_Inline
- (Msg : String;
- N : Node_Id;
- Subp : Entity_Id;
- Is_Serious : Boolean := False);
+ (Msg : String;
+ N : Node_Id;
+ Subp : Entity_Id;
+ Is_Serious : Boolean := False;
+ Suppress_Info : Boolean := False);
-- This procedure is called if the node N, an instance of a call to
-- subprogram Subp, cannot be inlined. Msg is the message to be issued,
-- which ends with ? (it does not end with ?p?, this routine takes care of
- -- the need to change ? to ?p?). The behavior of this routine depends on
- -- the value of Back_End_Inlining:
+ -- the need to change ? to ?p?). Suppress_Info is set to True to prevent
+ -- issuing an info message in GNATprove mode. The behavior of this routine
+ -- depends on the value of Back_End_Inlining:
--
-- * If Back_End_Inlining is not set (ie. legacy frontend inlining model)
-- then if Subp has a pragma Always_Inlined, then an error message is
diff --git a/gcc/ada/lib-load.adb b/gcc/ada/lib-load.adb
index 2598285..f8d632a 100644
--- a/gcc/ada/lib-load.adb
+++ b/gcc/ada/lib-load.adb
@@ -551,7 +551,7 @@ package body Lib.Load is
-- Note: Unit_Name (Main_Unit) is not set if we are parsing gnat.adc.
if Present (Error_Node)
- and then Unit_Name (Main_Unit) /= No_Unit_Name
+ and then Present (Unit_Name (Main_Unit))
then
-- It seems like In_Extended_Main_Source_Unit (Error_Node) would
-- do the trick here, but that's wrong, it is much too early to
@@ -646,7 +646,7 @@ package body Lib.Load is
else
Error_Msg_File_1 := Fname;
Error_Msg_Unit_1 := Uname_Actual;
- Error_Msg ("File{ does not contain unit$", Load_Msg_Sloc);
+ Error_Msg ("file{ does not contain unit$", Load_Msg_Sloc);
end if;
Write_Dependency_Chain;
diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb
index 6a63b8f..16449e8 100644
--- a/gcc/ada/lib-writ.adb
+++ b/gcc/ada/lib-writ.adb
@@ -837,7 +837,7 @@ package body Lib.Writ is
-- preprocessing data and definition files, there is no Unit_Name,
-- check for that first.
- if Unit_Name (J) /= No_Unit_Name
+ if Present (Unit_Name (J))
and then (With_Flags (J) or else Unit_Name (J) = Pname)
then
Num_Withs := Num_Withs + 1;
@@ -1125,9 +1125,7 @@ package body Lib.Writ is
if Nkind (U) = N_Subprogram_Body
and then Present (Corresponding_Spec (U))
- and then
- Ekind (Corresponding_Spec (U)) in E_Generic_Procedure
- | E_Generic_Function
+ and then Is_Generic_Subprogram (Corresponding_Spec (U))
then
null;
@@ -1478,11 +1476,8 @@ package body Lib.Writ is
-- Normal case of a unit entry with a source index
if Sind > No_Source_File then
- -- We never want directory information in ALI files
- -- ???But back out this change temporarily until
- -- gprbuild is fixed.
- if False then
+ if Config_Files_Store_Basename then
Fname := Strip_Directory (File_Name (Sind));
else
Fname := File_Name (Sind);
@@ -1729,7 +1724,7 @@ package body Lib.Writ is
-- scope
- Write_Info_Name (Scope (IS_Id));
+ Write_Info_Name (IS_Scope (IS_Id));
Write_Info_Char (' ');
-- line
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 64b9683..0869906 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -819,7 +819,7 @@ package body Lib.Xref is
end if;
-- For the left hand of an assignment case, we do nothing here.
- -- The processing for Analyze_Assignment_Statement will set the
+ -- The processing for Analyze_Assignment will set the
-- Referenced_As_LHS flag.
else
diff --git a/gcc/ada/lib.adb b/gcc/ada/lib.adb
index 49a352a..d298267 100644
--- a/gcc/ada/lib.adb
+++ b/gcc/ada/lib.adb
@@ -275,7 +275,7 @@ package body Lib is
begin
-- First unregister the old name, if any
- if Old_N /= No_Unit_Name and then Unit_Names.Get (Old_N) = U then
+ if Present (Old_N) and then Unit_Names.Get (Old_N) = U then
Unit_Names.Set (Old_N, No_Unit);
end if;
diff --git a/gcc/ada/libgnarl/s-osinte__solaris.ads b/gcc/ada/libgnarl/s-osinte__solaris.ads
index b3faa10..b9d6b88 100644
--- a/gcc/ada/libgnarl/s-osinte__solaris.ads
+++ b/gcc/ada/libgnarl/s-osinte__solaris.ads
@@ -45,9 +45,6 @@ with Ada.Unchecked_Conversion;
package System.OS_Interface is
pragma Preelaborate;
- pragma Linker_Options ("-lposix4");
- pragma Linker_Options ("-lthread");
-
subtype int is Interfaces.C.int;
subtype short is Interfaces.C.short;
subtype long is Interfaces.C.long;
diff --git a/gcc/ada/libgnarl/s-tasren.adb b/gcc/ada/libgnarl/s-tasren.adb
index 567b955..b7ee865 100644
--- a/gcc/ada/libgnarl/s-tasren.adb
+++ b/gcc/ada/libgnarl/s-tasren.adb
@@ -473,19 +473,7 @@ package body System.Tasking.Rendezvous is
pragma Debug
(Debug.Trace (Self_Id, "Local_Complete_Rendezvous", 'R'));
- if Ex = Ada.Exceptions.Null_Id then
-
- -- The call came from normal end-of-rendezvous, so abort is not yet
- -- deferred.
-
- Initialization.Defer_Abort (Self_Id);
-
- elsif ZCX_By_Default then
-
- -- With ZCX, aborts are not automatically deferred in handlers
-
- Initialization.Defer_Abort (Self_Id);
- end if;
+ Initialization.Defer_Abort (Self_Id);
-- We need to clean up any accepts which Self may have been serving when
-- it was aborted.
diff --git a/gcc/ada/libgnarl/s-tassta.adb b/gcc/ada/libgnarl/s-tassta.adb
index aada734..900b3b7 100644
--- a/gcc/ada/libgnarl/s-tassta.adb
+++ b/gcc/ada/libgnarl/s-tassta.adb
@@ -1096,11 +1096,10 @@ package body System.Tasking.Stages is
-- stack analysis.
Big_Overflow_Guard : constant := 64 * 1024 + 8 * 1024;
- Small_Stack_Limit : constant := 64 * 1024;
- -- ??? These three values are experimental, and seem to work on
- -- most platforms. They still need to be analyzed further. They
- -- also need documentation, what are they and why does the logic
- -- differ depending on whether the stack is large or small???
+ -- These two values are experimental, and seem to work on most
+ -- platforms. They still need to be analyzed further. They also
+ -- need documentation, what are they and why does the logic differ
+ -- depending on whether the stack is large or small???
Pattern_Size : Natural :=
Natural (Self_ID.Common.
@@ -1123,7 +1122,7 @@ package body System.Tasking.Stages is
-- Adjustments for inner frames
Pattern_Size := Pattern_Size -
- (if Pattern_Size < Small_Stack_Limit
+ (if Pattern_Size < Big_Overflow_Guard
then Small_Overflow_Guard
else Big_Overflow_Guard);
else
diff --git a/gcc/ada/libgnarl/s-tpobop.adb b/gcc/ada/libgnarl/s-tpobop.adb
index 5537c1a..b123c19 100644
--- a/gcc/ada/libgnarl/s-tpobop.adb
+++ b/gcc/ada/libgnarl/s-tpobop.adb
@@ -246,17 +246,7 @@ package body System.Tasking.Protected_Objects.Operations is
Entry_Call.Exception_To_Raise := Ex;
if Ex /= Ada.Exceptions.Null_Id then
-
- -- An exception was raised and abort was deferred, so adjust
- -- before propagating, otherwise the task will stay with deferral
- -- enabled for its remaining life.
-
Self_Id := STPO.Self;
-
- if not ZCX_By_Default then
- Initialization.Undefer_Abort_Nestable (Self_Id);
- end if;
-
Transfer_Occurrence
(Entry_Call.Self.Common.Compiler_Data.Current_Excep'Access,
Self_Id.Common.Compiler_Data.Current_Excep);
diff --git a/gcc/ada/libgnarl/s-tporft.adb b/gcc/ada/libgnarl/s-tporft.adb
index 9d99eac..634eae6 100644
--- a/gcc/ada/libgnarl/s-tporft.adb
+++ b/gcc/ada/libgnarl/s-tporft.adb
@@ -53,6 +53,7 @@ begin
Local_ATCB.Common.LL.Thread := Thread;
Local_ATCB.Common.Current_Priority := System.Priority'First;
+ Local_ATCB.Common.Global_Task_Lock_Nesting := 0;
Specific.Set (Local_ATCB'Unchecked_Access);
-- It is now safe to use an allocator
diff --git a/gcc/ada/libgnat/a-cbdlli.adb b/gcc/ada/libgnat/a-cbdlli.adb
index a0c356d..948b706 100644
--- a/gcc/ada/libgnat/a-cbdlli.adb
+++ b/gcc/ada/libgnat/a-cbdlli.adb
@@ -199,23 +199,19 @@ is
procedure Append
(Container : in out List;
New_Item : Element_Type;
- Count : Count_Type := 1)
+ Count : Count_Type)
is
begin
Insert (Container, No_Element, New_Item, Count);
end Append;
- ---------------
- -- Append_One --
- ---------------
-
- procedure Append_One
+ procedure Append
(Container : in out List;
New_Item : Element_Type)
is
begin
Insert (Container, No_Element, New_Item, 1);
- end Append_One;
+ end Append;
------------
-- Assign --
diff --git a/gcc/ada/libgnat/a-cbdlli.ads b/gcc/ada/libgnat/a-cbdlli.ads
index 183c01e..4574aa6 100644
--- a/gcc/ada/libgnat/a-cbdlli.ads
+++ b/gcc/ada/libgnat/a-cbdlli.ads
@@ -57,7 +57,7 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append_One);
+ Add_Unnamed => Append);
pragma Preelaborable_Initialization (List);
type Cursor is private;
@@ -151,9 +151,9 @@ is
procedure Append
(Container : in out List;
New_Item : Element_Type;
- Count : Count_Type := 1);
+ Count : Count_Type);
- procedure Append_One
+ procedure Append
(Container : in out List;
New_Item : Element_Type);
diff --git a/gcc/ada/libgnat/a-cbhase.adb b/gcc/ada/libgnat/a-cbhase.adb
index 293d722..75b9667 100644
--- a/gcc/ada/libgnat/a-cbhase.adb
+++ b/gcc/ada/libgnat/a-cbhase.adb
@@ -1783,7 +1783,7 @@ is
-- Read --
----------
- procedure Read
+ procedure Read
(Stream : not null access Root_Stream_Type'Class;
Item : out Reference_Type)
is
diff --git a/gcc/ada/libgnat/a-cbmutr.ads b/gcc/ada/libgnat/a-cbmutr.ads
index a9fb55a..d9a4a9a 100644
--- a/gcc/ada/libgnat/a-cbmutr.ads
+++ b/gcc/ada/libgnat/a-cbmutr.ads
@@ -333,7 +333,7 @@ private
Node : Count_Type'Base := No_Node;
end record;
- procedure Read
+ procedure Read
(Stream : not null access Root_Stream_Type'Class;
Position : out Cursor);
for Cursor'Read use Read;
diff --git a/gcc/ada/libgnat/a-cborse.adb b/gcc/ada/libgnat/a-cborse.adb
index e4a2de8..41f0859 100644
--- a/gcc/ada/libgnat/a-cborse.adb
+++ b/gcc/ada/libgnat/a-cborse.adb
@@ -908,7 +908,7 @@ is
-- Read --
----------
- procedure Read
+ procedure Read
(Stream : not null access Root_Stream_Type'Class;
Item : out Reference_Type)
is
diff --git a/gcc/ada/libgnat/a-cbsyqu.ads b/gcc/ada/libgnat/a-cbsyqu.ads
index 225db21..4037d84 100644
--- a/gcc/ada/libgnat/a-cbsyqu.ads
+++ b/gcc/ada/libgnat/a-cbsyqu.ads
@@ -71,6 +71,14 @@ is
-- Need proper heap data structure here ???
+ -- We suppress warnings here, which might otherwise be triggered
+ -- by the box initialization of the Elements array below. This
+ -- initialization is needed to preserve constraints, such as
+ -- discriminant values, that the actual for Element_Type might
+ -- carry.
+
+ pragma Warnings (Off);
+
type Element_Array is
array (Count_Type range <>) of Queue_Interfaces.Element_Type;
@@ -78,7 +86,7 @@ is
First, Last : Count_Type := 0;
Length : Count_Type := 0;
Max_Length : Count_Type := 0;
- Elements : Element_Array (1 .. Capacity);
+ Elements : Element_Array (1 .. Capacity) := (others => <>);
end record;
end Implementation;
diff --git a/gcc/ada/libgnat/a-cdlili.adb b/gcc/ada/libgnat/a-cdlili.adb
index f07190e..08c29f2 100644
--- a/gcc/ada/libgnat/a-cdlili.adb
+++ b/gcc/ada/libgnat/a-cdlili.adb
@@ -158,23 +158,19 @@ is
procedure Append
(Container : in out List;
New_Item : Element_Type;
- Count : Count_Type := 1)
+ Count : Count_Type)
is
begin
Insert (Container, No_Element, New_Item, Count);
end Append;
- ---------------
- -- Append_One --
- ---------------
-
- procedure Append_One
+ procedure Append
(Container : in out List;
New_Item : Element_Type)
is
begin
Insert (Container, No_Element, New_Item, 1);
- end Append_One;
+ end Append;
------------
-- Assign --
diff --git a/gcc/ada/libgnat/a-cdlili.ads b/gcc/ada/libgnat/a-cdlili.ads
index 35c4352..53de78b 100644
--- a/gcc/ada/libgnat/a-cdlili.ads
+++ b/gcc/ada/libgnat/a-cdlili.ads
@@ -58,7 +58,7 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append_One);
+ Add_Unnamed => Append);
pragma Preelaborable_Initialization (List);
@@ -154,9 +154,9 @@ is
procedure Append
(Container : in out List;
New_Item : Element_Type;
- Count : Count_Type := 1);
+ Count : Count_Type);
- procedure Append_One
+ procedure Append
(Container : in out List;
New_Item : Element_Type);
diff --git a/gcc/ada/libgnat/a-cidlli.adb b/gcc/ada/libgnat/a-cidlli.adb
index a62338f..79df5a9 100644
--- a/gcc/ada/libgnat/a-cidlli.adb
+++ b/gcc/ada/libgnat/a-cidlli.adb
@@ -179,23 +179,19 @@ is
procedure Append
(Container : in out List;
New_Item : Element_Type;
- Count : Count_Type := 1)
+ Count : Count_Type)
is
begin
Insert (Container, No_Element, New_Item, Count);
end Append;
- ---------------
- -- Append_One --
- ---------------
-
- procedure Append_One
+ procedure Append
(Container : in out List;
New_Item : Element_Type)
is
begin
Insert (Container, No_Element, New_Item, 1);
- end Append_One;
+ end Append;
------------
-- Assign --
diff --git a/gcc/ada/libgnat/a-cidlli.ads b/gcc/ada/libgnat/a-cidlli.ads
index 5e63cf2..c75e5af 100644
--- a/gcc/ada/libgnat/a-cidlli.ads
+++ b/gcc/ada/libgnat/a-cidlli.ads
@@ -57,7 +57,7 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append_One);
+ Add_Unnamed => Append);
pragma Preelaborable_Initialization (List);
@@ -147,9 +147,9 @@ is
procedure Append
(Container : in out List;
New_Item : Element_Type;
- Count : Count_Type := 1);
+ Count : Count_Type);
- procedure Append_One
+ procedure Append
(Container : in out List;
New_Item : Element_Type);
diff --git a/gcc/ada/libgnat/a-cihama.adb b/gcc/ada/libgnat/a-cihama.adb
index 64f662f..7a490d5 100644
--- a/gcc/ada/libgnat/a-cihama.adb
+++ b/gcc/ada/libgnat/a-cihama.adb
@@ -349,6 +349,8 @@ is
Free (Position.Node);
Position.Container := null;
+ Position.Position := No_Element.Position;
+ pragma Assert (Position = No_Element);
end Delete;
-------------
diff --git a/gcc/ada/libgnat/a-cobove.adb b/gcc/ada/libgnat/a-cobove.adb
index 0408741..8a8b279 100644
--- a/gcc/ada/libgnat/a-cobove.adb
+++ b/gcc/ada/libgnat/a-cobove.adb
@@ -321,9 +321,13 @@ package body Ada.Containers.Bounded_Vectors is
-- Append --
------------
- procedure Append (Container : in out Vector; New_Item : Vector) is
+ procedure Append
+ (Container : in out Vector;
+ New_Item : Element_Type;
+ Count : Count_Type)
+ is
begin
- if New_Item.Is_Empty then
+ if Count = 0 then
return;
end if;
@@ -331,16 +335,16 @@ package body Ada.Containers.Bounded_Vectors is
raise Constraint_Error with "vector is already at its maximum length";
end if;
- Container.Insert (Container.Last + 1, New_Item);
+ Container.Insert (Container.Last + 1, New_Item, Count);
end Append;
- procedure Append
- (Container : in out Vector;
- New_Item : Element_Type;
- Count : Count_Type := 1)
- is
+ -------------------
+ -- Append_Vector --
+ -------------------
+
+ procedure Append_Vector (Container : in out Vector; New_Item : Vector) is
begin
- if Count = 0 then
+ if New_Item.Is_Empty then
return;
end if;
@@ -348,19 +352,19 @@ package body Ada.Containers.Bounded_Vectors is
raise Constraint_Error with "vector is already at its maximum length";
end if;
- Container.Insert (Container.Last + 1, New_Item, Count);
- end Append;
+ Container.Insert_Vector (Container.Last + 1, New_Item);
+ end Append_Vector;
- ----------------
- -- Append_One --
- ----------------
+ ------------
+ -- Append --
+ ------------
- procedure Append_One (Container : in out Vector;
- New_Item : Element_Type)
+ procedure Append (Container : in out Vector;
+ New_Item : Element_Type)
is
begin
Insert (Container, Last_Index (Container) + 1, New_Item, 1);
- end Append_One;
+ end Append;
--------------
-- Capacity --
@@ -1243,7 +1247,7 @@ package body Ada.Containers.Bounded_Vectors is
end if;
end Insert;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Extended_Index;
New_Item : Vector)
@@ -1309,9 +1313,9 @@ package body Ada.Containers.Bounded_Vectors is
Container.Elements (B + N - Src'Length .. B + N - 1) := Src;
end;
- end Insert;
+ end Insert_Vector;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Cursor;
New_Item : Vector)
@@ -1343,10 +1347,10 @@ package body Ada.Containers.Bounded_Vectors is
Index := Before.Index;
end if;
- Insert (Container, Index, New_Item);
- end Insert;
+ Insert_Vector (Container, Index, New_Item);
+ end Insert_Vector;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Cursor;
New_Item : Vector;
@@ -1387,10 +1391,10 @@ package body Ada.Containers.Bounded_Vectors is
Index := Before.Index;
end if;
- Insert (Container, Index, New_Item);
+ Insert_Vector (Container, Index, New_Item);
Position := Cursor'(Container'Unchecked_Access, Index);
- end Insert;
+ end Insert_Vector;
procedure Insert
(Container : in out Vector;
@@ -2028,23 +2032,24 @@ package body Ada.Containers.Bounded_Vectors is
-- Prepend --
-------------
- procedure Prepend (Container : in out Vector; New_Item : Vector) is
- begin
- Insert (Container, Index_Type'First, New_Item);
- end Prepend;
-
procedure Prepend
(Container : in out Vector;
New_Item : Element_Type;
Count : Count_Type := 1)
is
begin
- Insert (Container,
- Index_Type'First,
- New_Item,
- Count);
+ Insert (Container, Index_Type'First, New_Item, Count);
end Prepend;
+ --------------------
+ -- Prepend_Vector --
+ --------------------
+
+ procedure Prepend_Vector (Container : in out Vector; New_Item : Vector) is
+ begin
+ Insert_Vector (Container, Index_Type'First, New_Item);
+ end Prepend_Vector;
+
--------------
-- Previous --
--------------
diff --git a/gcc/ada/libgnat/a-cobove.ads b/gcc/ada/libgnat/a-cobove.ads
index ab4ce4e..324ca84 100644
--- a/gcc/ada/libgnat/a-cobove.ads
+++ b/gcc/ada/libgnat/a-cobove.ads
@@ -61,7 +61,7 @@ package Ada.Containers.Bounded_Vectors is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append_One,
+ Add_Unnamed => Append,
New_Indexed => New_Vector,
Assign_Indexed => Replace_Element);
@@ -190,24 +190,43 @@ package Ada.Containers.Bounded_Vectors is
procedure Move (Target : in out Vector; Source : in out Vector);
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Extended_Index;
New_Item : Vector);
procedure Insert
(Container : in out Vector;
+ Before : Extended_Index;
+ New_Item : Vector) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert_Vector
+ (Container : in out Vector;
Before : Cursor;
New_Item : Vector);
procedure Insert
(Container : in out Vector;
Before : Cursor;
+ New_Item : Vector) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert_Vector
+ (Container : in out Vector;
+ Before : Cursor;
New_Item : Vector;
Position : out Cursor);
procedure Insert
(Container : in out Vector;
+ Before : Cursor;
+ New_Item : Vector;
+ Position : out Cursor) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert
+ (Container : in out Vector;
Before : Extended_Index;
New_Item : Element_Type;
Count : Count_Type := 1);
@@ -236,27 +255,36 @@ package Ada.Containers.Bounded_Vectors is
Position : out Cursor;
Count : Count_Type := 1);
- procedure Prepend
+ procedure Prepend_Vector
(Container : in out Vector;
New_Item : Vector);
procedure Prepend
(Container : in out Vector;
+ New_Item : Vector) renames Prepend_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Prepend
+ (Container : in out Vector;
New_Item : Element_Type;
Count : Count_Type := 1);
- procedure Append
+ procedure Append_Vector
(Container : in out Vector;
New_Item : Vector);
procedure Append
(Container : in out Vector;
+ New_Item : Vector) renames Append_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Append
+ (Container : in out Vector;
New_Item : Element_Type;
- Count : Count_Type := 1);
+ Count : Count_Type);
- procedure Append_One (Container : in out Vector;
- New_Item : Element_Type);
- -- Ada_2020 aggregate operation.
+ procedure Append (Container : in out Vector;
+ New_Item : Element_Type);
procedure Insert_Space
(Container : in out Vector;
diff --git a/gcc/ada/libgnat/a-cohama.adb b/gcc/ada/libgnat/a-cohama.adb
index 1475330..9c4e51a 100644
--- a/gcc/ada/libgnat/a-cohama.adb
+++ b/gcc/ada/libgnat/a-cohama.adb
@@ -336,6 +336,8 @@ is
Free (Position.Node);
Position.Container := null;
+ Position.Position := No_Element.Position;
+ pragma Assert (Position = No_Element);
end Delete;
-------------
diff --git a/gcc/ada/libgnat/a-cohase.adb b/gcc/ada/libgnat/a-cohase.adb
index 63e44e1..0131f73 100644
--- a/gcc/ada/libgnat/a-cohase.adb
+++ b/gcc/ada/libgnat/a-cohase.adb
@@ -319,6 +319,8 @@ is
Free (Position.Node);
Position.Container := null;
+ Position.Position := No_Element.Position;
+ pragma Assert (Position = No_Element);
end Delete;
----------------
diff --git a/gcc/ada/libgnat/a-coinve.adb b/gcc/ada/libgnat/a-coinve.adb
index 10711ff..051aa71 100644
--- a/gcc/ada/libgnat/a-coinve.adb
+++ b/gcc/ada/libgnat/a-coinve.adb
@@ -67,8 +67,8 @@ is
begin
return Result : Vector do
Reserve_Capacity (Result, Length (Left) + Length (Right));
- Append (Result, Left);
- Append (Result, Right);
+ Append_Vector (Result, Left);
+ Append_Vector (Result, Right);
end return;
end "&";
@@ -76,7 +76,7 @@ is
begin
return Result : Vector do
Reserve_Capacity (Result, Length (Left) + 1);
- Append (Result, Left);
+ Append_Vector (Result, Left);
Append (Result, Right);
end return;
end "&";
@@ -86,7 +86,7 @@ is
return Result : Vector do
Reserve_Capacity (Result, 1 + Length (Right));
Append (Result, Left);
- Append (Result, Right);
+ Append_Vector (Result, Right);
end return;
end "&";
@@ -176,25 +176,25 @@ is
end;
end Adjust;
- ------------
- -- Append --
- ------------
+ -------------------
+ -- Append_Vector --
+ -------------------
- procedure Append (Container : in out Vector; New_Item : Vector) is
+ procedure Append_Vector (Container : in out Vector; New_Item : Vector) is
begin
if Is_Empty (New_Item) then
return;
elsif Checks and then Container.Last = Index_Type'Last then
raise Constraint_Error with "vector is already at its maximum length";
else
- Insert (Container, Container.Last + 1, New_Item);
+ Insert_Vector (Container, Container.Last + 1, New_Item);
end if;
- end Append;
+ end Append_Vector;
procedure Append
(Container : in out Vector;
New_Item : Element_Type;
- Count : Count_Type := 1)
+ Count : Count_Type)
is
begin
-- In the general case, we pass the buck to Insert, but for efficiency,
@@ -229,16 +229,16 @@ is
end if;
end Append;
- ----------------
- -- Append_One --
- ----------------
+ ------------
+ -- Append --
+ ------------
- procedure Append_One (Container : in out Vector;
+ procedure Append (Container : in out Vector;
New_Item : Element_Type)
is
begin
Insert (Container, Last_Index (Container) + 1, New_Item, 1);
- end Append_One;
+ end Append;
----------------------
-- Append_Slow_Path --
@@ -269,7 +269,7 @@ is
return;
else
Target.Clear;
- Target.Append (Source);
+ Target.Append_Vector (Source);
end if;
end Assign;
@@ -1619,7 +1619,7 @@ is
end;
end Insert;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Extended_Index;
New_Item : Vector)
@@ -1766,9 +1766,9 @@ is
Dst_Index := Dst_Index + 1;
end loop;
end;
- end Insert;
+ end Insert_Vector;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Cursor;
New_Item : Vector)
@@ -1798,10 +1798,10 @@ is
Index := Before.Index;
end if;
- Insert (Container, Index, New_Item);
- end Insert;
+ Insert_Vector (Container, Index, New_Item);
+ end Insert_Vector;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Cursor;
New_Item : Vector;
@@ -1838,10 +1838,10 @@ is
Index := Before.Index;
end if;
- Insert (Container, Index, New_Item);
+ Insert_Vector (Container, Index, New_Item);
Position := (Container'Unrestricted_Access, Index);
- end Insert;
+ end Insert_Vector;
procedure Insert
(Container : in out Vector;
@@ -2559,11 +2559,6 @@ is
-- Prepend --
-------------
- procedure Prepend (Container : in out Vector; New_Item : Vector) is
- begin
- Insert (Container, Index_Type'First, New_Item);
- end Prepend;
-
procedure Prepend
(Container : in out Vector;
New_Item : Element_Type;
@@ -2573,6 +2568,15 @@ is
Insert (Container, Index_Type'First, New_Item, Count);
end Prepend;
+ -------------
+ -- Prepend_Vector --
+ -------------
+
+ procedure Prepend_Vector (Container : in out Vector; New_Item : Vector) is
+ begin
+ Insert_Vector (Container, Index_Type'First, New_Item);
+ end Prepend_Vector;
+
--------------
-- Previous --
--------------
diff --git a/gcc/ada/libgnat/a-coinve.ads b/gcc/ada/libgnat/a-coinve.ads
index 593b63e..c9364c7 100644
--- a/gcc/ada/libgnat/a-coinve.ads
+++ b/gcc/ada/libgnat/a-coinve.ads
@@ -64,7 +64,7 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty_Vector,
- Add_Unnamed => Append_One,
+ Add_Unnamed => Append,
New_Indexed => New_Vector,
Assign_Indexed => Replace_Element);
@@ -195,24 +195,43 @@ is
procedure Move (Target : in out Vector; Source : in out Vector);
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Extended_Index;
New_Item : Vector);
procedure Insert
(Container : in out Vector;
+ Before : Extended_Index;
+ New_Item : Vector) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert_Vector
+ (Container : in out Vector;
Before : Cursor;
New_Item : Vector);
procedure Insert
(Container : in out Vector;
Before : Cursor;
+ New_Item : Vector) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert_Vector
+ (Container : in out Vector;
+ Before : Cursor;
New_Item : Vector;
Position : out Cursor);
procedure Insert
(Container : in out Vector;
+ Before : Cursor;
+ New_Item : Vector;
+ Position : out Cursor) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert
+ (Container : in out Vector;
Before : Extended_Index;
New_Item : Element_Type;
Count : Count_Type := 1);
@@ -230,26 +249,36 @@ is
Position : out Cursor;
Count : Count_Type := 1);
- procedure Prepend
+ procedure Prepend_Vector
(Container : in out Vector;
New_Item : Vector);
procedure Prepend
(Container : in out Vector;
+ New_Item : Vector) renames Prepend_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Prepend
+ (Container : in out Vector;
New_Item : Element_Type;
Count : Count_Type := 1);
- procedure Append
+ procedure Append_Vector
(Container : in out Vector;
New_Item : Vector);
procedure Append
(Container : in out Vector;
+ New_Item : Vector) renames Append_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Append
+ (Container : in out Vector;
New_Item : Element_Type;
- Count : Count_Type := 1);
+ Count : Count_Type);
- procedure Append_One (Container : in out Vector;
- New_Item : Element_Type);
+ procedure Append (Container : in out Vector;
+ New_Item : Element_Type);
procedure Insert_Space
(Container : in out Vector;
diff --git a/gcc/ada/libgnat/a-convec.adb b/gcc/ada/libgnat/a-convec.adb
index a43be97..fec72cc 100644
--- a/gcc/ada/libgnat/a-convec.adb
+++ b/gcc/ada/libgnat/a-convec.adb
@@ -64,8 +64,8 @@ is
begin
return Result : Vector do
Reserve_Capacity (Result, Length (Left) + Length (Right));
- Append (Result, Left);
- Append (Result, Right);
+ Append_Vector (Result, Left);
+ Append_Vector (Result, Right);
end return;
end "&";
@@ -73,7 +73,7 @@ is
begin
return Result : Vector do
Reserve_Capacity (Result, Length (Left) + 1);
- Append (Result, Left);
+ Append_Vector (Result, Left);
Append (Result, Right);
end return;
end "&";
@@ -83,7 +83,7 @@ is
return Result : Vector do
Reserve_Capacity (Result, 1 + Length (Right));
Append (Result, Left);
- Append (Result, Right);
+ Append_Vector (Result, Right);
end return;
end "&";
@@ -167,21 +167,10 @@ is
-- Append --
------------
- procedure Append (Container : in out Vector; New_Item : Vector) is
- begin
- if Is_Empty (New_Item) then
- return;
- elsif Checks and then Container.Last = Index_Type'Last then
- raise Constraint_Error with "vector is already at its maximum length";
- else
- Insert (Container, Container.Last + 1, New_Item);
- end if;
- end Append;
-
procedure Append
(Container : in out Vector;
New_Item : Element_Type;
- Count : Count_Type := 1)
+ Count : Count_Type)
is
begin
-- In the general case, we pass the buck to Insert, but for efficiency,
@@ -210,16 +199,31 @@ is
end if;
end Append;
- ----------------
- -- Append_One --
- ----------------
+ -------------------
+ -- Append_Vector --
+ -------------------
+
+ procedure Append_Vector (Container : in out Vector; New_Item : Vector) is
+ begin
+ if Is_Empty (New_Item) then
+ return;
+ elsif Checks and then Container.Last = Index_Type'Last then
+ raise Constraint_Error with "vector is already at its maximum length";
+ else
+ Insert_Vector (Container, Container.Last + 1, New_Item);
+ end if;
+ end Append_Vector;
+
+ ------------
+ -- Append --
+ ------------
- procedure Append_One (Container : in out Vector;
- New_Item : Element_Type)
+ procedure Append (Container : in out Vector;
+ New_Item : Element_Type)
is
begin
Insert (Container, Last_Index (Container) + 1, New_Item, 1);
- end Append_One;
+ end Append;
----------------------
-- Append_Slow_Path --
@@ -250,7 +254,7 @@ is
return;
else
Target.Clear;
- Target.Append (Source);
+ Target.Append_Vector (Source);
end if;
end Assign;
@@ -1310,7 +1314,7 @@ is
end;
end Insert;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Extended_Index;
New_Item : Vector)
@@ -1429,9 +1433,9 @@ is
Container.Elements.EA (K .. J) := Src;
end;
- end Insert;
+ end Insert_Vector;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Cursor;
New_Item : Vector)
@@ -1461,10 +1465,10 @@ is
Index := Before.Index;
end if;
- Insert (Container, Index, New_Item);
- end Insert;
+ Insert_Vector (Container, Index, New_Item);
+ end Insert_Vector;
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Cursor;
New_Item : Vector;
@@ -1501,10 +1505,10 @@ is
Index := Before.Index;
end if;
- Insert (Container, Index, New_Item);
+ Insert_Vector (Container, Index, New_Item);
Position := (Container'Unrestricted_Access, Index);
- end Insert;
+ end Insert_Vector;
procedure Insert
(Container : in out Vector;
@@ -2266,11 +2270,6 @@ is
-- Prepend --
-------------
- procedure Prepend (Container : in out Vector; New_Item : Vector) is
- begin
- Insert (Container, Index_Type'First, New_Item);
- end Prepend;
-
procedure Prepend
(Container : in out Vector;
New_Item : Element_Type;
@@ -2280,6 +2279,15 @@ is
Insert (Container, Index_Type'First, New_Item, Count);
end Prepend;
+ --------------------
+ -- Prepend_Vector --
+ --------------------
+
+ procedure Prepend_Vector (Container : in out Vector; New_Item : Vector) is
+ begin
+ Insert_Vector (Container, Index_Type'First, New_Item);
+ end Prepend_Vector;
+
--------------
-- Previous --
--------------
diff --git a/gcc/ada/libgnat/a-convec.ads b/gcc/ada/libgnat/a-convec.ads
index f969e6f..1d257a0 100644
--- a/gcc/ada/libgnat/a-convec.ads
+++ b/gcc/ada/libgnat/a-convec.ads
@@ -95,7 +95,7 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append_One,
+ Add_Unnamed => Append,
New_Indexed => New_Vector,
Assign_Indexed => Replace_Element);
@@ -334,59 +334,80 @@ is
with Pre => First = Index_Type'First;
-- Ada_2020 aggregate operation.
- procedure Insert
+ procedure Insert_Vector
(Container : in out Vector;
Before : Extended_Index;
New_Item : Vector);
-- If Before is not in the range First_Index (Container) .. Last_Index
-- (Container) + 1, then Constraint_Error is propagated. If
- -- Length(New_Item) is 0, then Insert does nothing. Otherwise, it computes
- -- the new length NL as the sum of the current length and Length
+ -- Length(New_Item) is 0, then Insert_Vector does nothing. Otherwise, it
+ -- computes the new length NL as the sum of the current length and Length
-- (New_Item); if the value of Last appropriate for length NL would be
-- greater than Index_Type'Last then Constraint_Error is propagated.
--
-- If the current vector capacity is less than NL, Reserve_Capacity
- -- (Container, NL) is called to increase the vector capacity. Then Insert
- -- slides the elements in the range Before .. Last_Index (Container) up by
- -- Length(New_Item) positions, and then copies the elements of New_Item to
- -- the positions starting at Before. Any exception raised during the
- -- copying is propagated.
+ -- (Container, NL) is called to increase the vector capacity. Then
+ -- Insert_Vector slides the elements in the range Before .. Last_Index
+ -- (Container) up by Length(New_Item) positions, and then copies the
+ -- elements of New_Item to the positions starting at Before. Any exception
+ -- raised during the copying is propagated.
procedure Insert
(Container : in out Vector;
+ Before : Extended_Index;
+ New_Item : Vector) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert_Vector
+ (Container : in out Vector;
Before : Cursor;
New_Item : Vector);
-- If Before is not No_Element, and does not designate an element in
-- Container, then Program_Error is propagated. Otherwise, if
- -- Length(New_Item) is 0, then Insert does nothing. If Before is
- -- No_Element, then the call is equivalent to Insert (Container, Last_Index
- -- (Container) + 1, New_Item); otherwise the call is equivalent to Insert
- -- (Container, To_Index (Before), New_Item);
+ -- Length(New_Item) is 0, then Insert_Vector does nothing. If Before is
+ -- No_Element, then the call is equivalent to Insert_Vector (Container,
+ -- Last_Index (Container) + 1, New_Item); otherwise the call is equivalent
+ -- to Insert_Vector (Container, To_Index (Before), New_Item);
procedure Insert
(Container : in out Vector;
Before : Cursor;
+ New_Item : Vector) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Insert_Vector
+ (Container : in out Vector;
+ Before : Cursor;
New_Item : Vector;
Position : out Cursor);
-- If Before is not No_Element, and does not designate an element in
-- Container, then Program_Error is propagated. If Before equals
-- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T
- -- be To_Index (Before). Insert (Container, T, New_Item) is called, and
- -- then Position is set to To_Cursor (Container, T).
+ -- be To_Index (Before). Insert_Vector (Container, T, New_Item) is called,
+ -- and then Position is set to To_Cursor (Container, T).
+
+ procedure Insert
+ (Container : in out Vector;
+ Before : Cursor;
+ New_Item : Vector;
+ Position : out Cursor) renames Insert_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
procedure Insert
(Container : in out Vector;
Before : Extended_Index;
New_Item : Element_Type;
Count : Count_Type := 1);
- -- Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));
+ -- Equivalent to:
+ -- Insert_Vector (Container, Before, To_Vector (New_Item, Count));
procedure Insert
(Container : in out Vector;
Before : Cursor;
New_Item : Element_Type;
Count : Count_Type := 1);
- -- Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));
+ -- Equivalent to:
+ -- Insert_Vector (Container, Before, To_Vector (New_Item, Count));
procedure Insert
(Container : in out Vector;
@@ -395,7 +416,7 @@ is
Position : out Cursor;
Count : Count_Type := 1);
-- Equivalent to
- -- Insert (Container, Before, To_Vector (New_Item, Count), Position);
+ -- Insert_Vector (Container, Before, To_Vector (New_Item, Count), Position)
procedure Insert
(Container : in out Vector;
@@ -425,33 +446,42 @@ is
-- be To_Index (Before). Insert (Container, T, Count) is called, and then
-- Position is set to To_Cursor (Container, T).
- procedure Prepend
+ procedure Prepend_Vector
(Container : in out Vector;
New_Item : Vector);
-- Equivalent to Insert (Container, First_Index (Container), New_Item).
procedure Prepend
(Container : in out Vector;
+ New_Item : Vector) renames Prepend_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Prepend
+ (Container : in out Vector;
New_Item : Element_Type;
Count : Count_Type := 1);
-- Equivalent to Insert (Container, First_Index (Container), New_Item,
-- Count).
- procedure Append
+ procedure Append_Vector
(Container : in out Vector;
New_Item : Vector);
-- Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item).
procedure Append
(Container : in out Vector;
+ New_Item : Vector) renames Append_Vector;
+ -- Retained for now for compatibility; AI12-0400 will remove this.
+
+ procedure Append
+ (Container : in out Vector;
New_Item : Element_Type;
- Count : Count_Type := 1);
+ Count : Count_Type);
-- Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item,
-- Count).
- procedure Append_One (Container : in out Vector;
- New_Item : Element_Type);
- -- Ada_2020 aggregate operation.
+ procedure Append (Container : in out Vector;
+ New_Item : Element_Type);
procedure Insert_Space
(Container : in out Vector;
diff --git a/gcc/ada/libgnat/a-decima__128.ads b/gcc/ada/libgnat/a-decima__128.ads
new file mode 100644
index 0000000..b29b010
--- /dev/null
+++ b/gcc/ada/libgnat/a-decima__128.ads
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . D E C I M A L --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- This specification is derived from the Ada Reference Manual for use with --
+-- GNAT. The copyright notice above, and the license provisions that follow --
+-- apply solely to the contents of the part following the private keyword. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This is the 128-bit version of this package
+
+package Ada.Decimal is
+ pragma Pure;
+
+ -- The compiler makes a number of assumptions based on the following five
+ -- constants (e.g. there is an assumption that decimal values can always
+ -- be represented in 128-bit signed binary form), so code modifications are
+ -- required to increase these constants.
+
+ Max_Scale : constant := +38;
+ Min_Scale : constant := -38;
+
+ Min_Delta : constant := 1.0E-38;
+ Max_Delta : constant := 1.0E+38;
+
+ Max_Decimal_Digits : constant := 38;
+
+ generic
+ type Dividend_Type is delta <> digits <>;
+ type Divisor_Type is delta <> digits <>;
+ type Quotient_Type is delta <> digits <>;
+ type Remainder_Type is delta <> digits <>;
+
+ procedure Divide
+ (Dividend : Dividend_Type;
+ Divisor : Divisor_Type;
+ Quotient : out Quotient_Type;
+ Remainder : out Remainder_Type);
+
+private
+ pragma Inline (Divide);
+
+end Ada.Decimal;
diff --git a/gcc/ada/libgnat/a-except.adb b/gcc/ada/libgnat/a-except.adb
index 52e716f..f7fd5bb 100644
--- a/gcc/ada/libgnat/a-except.adb
+++ b/gcc/ada/libgnat/a-except.adb
@@ -957,11 +957,6 @@ package body Ada.Exceptions is
begin
Exception_Data.Set_Exception_Msg (X, E, Message);
-
- if not ZCX_By_Default then
- Abort_Defer.all;
- end if;
-
Complete_And_Propagate_Occurrence (X);
end Raise_Exception_Always;
@@ -1041,11 +1036,6 @@ package body Ada.Exceptions is
begin
Exception_Data.Set_Exception_C_Msg (X, E, M);
-
- if not ZCX_By_Default then
- Abort_Defer.all;
- end if;
-
Complete_Occurrence (X);
return X;
end Create_Occurrence_From_Signal_Handler;
@@ -1141,11 +1131,6 @@ package body Ada.Exceptions is
X : constant EOA := Exception_Propagation.Allocate_Occurrence;
begin
Exception_Data.Set_Exception_C_Msg (X, E, F, L, C, M);
-
- if not ZCX_By_Default then
- Abort_Defer.all;
- end if;
-
Complete_And_Propagate_Occurrence (X);
end Raise_With_Location_And_Msg;
@@ -1168,13 +1153,6 @@ package body Ada.Exceptions is
Excep.Msg_Length := Ex.Msg_Length;
Excep.Msg (1 .. Excep.Msg_Length) := Ex.Msg (1 .. Ex.Msg_Length);
- -- The following is a common pattern, should be abstracted
- -- into a procedure call ???
-
- if not ZCX_By_Default then
- Abort_Defer.all;
- end if;
-
Complete_And_Propagate_Occurrence (Excep);
end Raise_With_Msg;
@@ -1507,10 +1485,6 @@ package body Ada.Exceptions is
Saved_MO : constant System.Address := Excep.Machine_Occurrence;
begin
- if not ZCX_By_Default then
- Abort_Defer.all;
- end if;
-
Save_Occurrence (Excep.all, Get_Current_Excep.all.all);
Excep.Machine_Occurrence := Saved_MO;
Complete_And_Propagate_Occurrence (Excep);
@@ -1556,10 +1530,6 @@ package body Ada.Exceptions is
procedure Reraise_Occurrence_Always (X : Exception_Occurrence) is
begin
- if not ZCX_By_Default then
- Abort_Defer.all;
- end if;
-
Reraise_Occurrence_No_Defer (X);
end Reraise_Occurrence_Always;
diff --git a/gcc/ada/libgnat/a-nbnbin.adb b/gcc/ada/libgnat/a-nbnbin.adb
index 70df2c2..9e051d3 100644
--- a/gcc/ada/libgnat/a-nbnbin.adb
+++ b/gcc/ada/libgnat/a-nbnbin.adb
@@ -177,7 +177,7 @@ package body Ada.Numerics.Big_Numbers.Big_Integers is
function To_Big_Integer (Arg : Int) return Valid_Big_Integer is
Result : Big_Integer;
begin
- Set_Bignum (Result, To_Bignum (Long_Long_Integer (Arg)));
+ Set_Bignum (Result, To_Bignum (Long_Long_Long_Integer (Arg)));
return Result;
end To_Big_Integer;
@@ -205,7 +205,7 @@ package body Ada.Numerics.Big_Numbers.Big_Integers is
function To_Big_Integer (Arg : Int) return Valid_Big_Integer is
Result : Big_Integer;
begin
- Set_Bignum (Result, To_Bignum (Unsigned_64 (Arg)));
+ Set_Bignum (Result, To_Bignum (Unsigned_128 (Arg)));
return Result;
end To_Big_Integer;
@@ -235,12 +235,197 @@ package body Ada.Numerics.Big_Numbers.Big_Integers is
-- From_String --
-----------------
- function From_String (Arg : String) return Big_Integer is
+ function From_String (Arg : String) return Valid_Big_Integer is
+ procedure Scan_Decimal
+ (Arg : String; J : in out Natural; Result : out Big_Integer);
+ -- Scan decimal value starting at Arg (J). Store value in Result if
+ -- successful, raise Constraint_Error if not. On exit, J points to the
+ -- first index past the decimal value.
+
+ ------------------
+ -- Scan_Decimal --
+ ------------------
+
+ procedure Scan_Decimal
+ (Arg : String; J : in out Natural; Result : out Big_Integer)
+ is
+ Initial_J : constant Natural := J;
+ Ten : constant Big_Integer := To_Big_Integer (10);
+ begin
+ Result := To_Big_Integer (0);
+
+ while J <= Arg'Last loop
+ if Arg (J) in '0' .. '9' then
+ Result :=
+ Result * Ten + To_Big_Integer (Character'Pos (Arg (J))
+ - Character'Pos ('0'));
+
+ elsif Arg (J) = '_' then
+ if J in Initial_J | Arg'Last
+ or else Arg (J - 1) not in '0' .. '9'
+ or else Arg (J + 1) not in '0' .. '9'
+ then
+ raise Constraint_Error with "invalid integer value: " & Arg;
+ end if;
+ else
+ exit;
+ end if;
+
+ J := J + 1;
+ end loop;
+ end Scan_Decimal;
+
Result : Big_Integer;
+
begin
- -- ??? only support Long_Long_Long_Integer, good enough for now
+ -- First try the fast path via Long_Long_Long_Integer'Value
+
Set_Bignum (Result, To_Bignum (Long_Long_Long_Integer'Value (Arg)));
return Result;
+
+ exception
+ when Constraint_Error =>
+ -- Then try the slow path
+
+ declare
+ Neg : Boolean := False;
+ Base_Found : Boolean := False;
+ Base_Int : Positive := 10;
+ J : Natural := Arg'First;
+ Val : Natural;
+ Base : Big_Integer;
+ Exp : Big_Integer;
+
+ begin
+ -- Scan past leading blanks
+
+ while J <= Arg'Last and then Arg (J) = ' ' loop
+ J := J + 1;
+ end loop;
+
+ if J > Arg'Last then
+ raise;
+ end if;
+
+ -- Scan and store negative sign if found
+
+ if Arg (J) = '-' then
+ Neg := True;
+ J := J + 1;
+ end if;
+
+ -- Scan decimal value: either the result itself, or the base
+ -- value if followed by a '#'.
+
+ Scan_Decimal (Arg, J, Result);
+
+ -- Scan explicit base if requested
+
+ if J <= Arg'Last and then Arg (J) = '#' then
+ Base_Int := To_Integer (Result);
+
+ if Base_Int not in 2 .. 16 then
+ raise;
+ end if;
+
+ Base_Found := True;
+ Base := Result;
+ Result := To_Big_Integer (0);
+ J := J + 1;
+
+ while J <= Arg'Last loop
+ case Arg (J) is
+ when '0' .. '9' =>
+ Val := Character'Pos (Arg (J)) - Character'Pos ('0');
+
+ if Val >= Base_Int then
+ raise;
+ end if;
+
+ Result := Result * Base + To_Big_Integer (Val);
+
+ when 'a' .. 'f' =>
+ Val :=
+ 10 + Character'Pos (Arg (J)) - Character'Pos ('a');
+
+ if Val >= Base_Int then
+ raise;
+ end if;
+
+ Result := Result * Base + To_Big_Integer (Val);
+
+ when 'A' .. 'F' =>
+ Val :=
+ 10 + Character'Pos (Arg (J)) - Character'Pos ('A');
+
+ if Val >= Base_Int then
+ raise;
+ end if;
+
+ Result := Result * Base + To_Big_Integer (Val);
+
+ when '_' =>
+
+ -- We only allow _ preceded and followed by a valid
+ -- number and not any other character.
+
+ if J in Arg'First | Arg'Last
+ or else Arg (J - 1) in '_' | '#'
+ or else Arg (J + 1) = '#'
+ then
+ raise;
+ end if;
+
+ when '#' =>
+ J := J + 1;
+ exit;
+
+ when others =>
+ raise;
+ end case;
+
+ J := J + 1;
+ end loop;
+ else
+ Base := To_Big_Integer (10);
+ end if;
+
+ if Base_Found and then Arg (J - 1) /= '#' then
+ raise;
+ end if;
+
+ if J <= Arg'Last then
+
+ -- Scan exponent
+
+ if Arg (J) in 'e' | 'E' then
+ J := J + 1;
+
+ if Arg (J) = '+' then
+ J := J + 1;
+ end if;
+
+ Scan_Decimal (Arg, J, Exp);
+ Result := Result * (Base ** To_Integer (Exp));
+ end if;
+
+ -- Scan past trailing blanks
+
+ while J <= Arg'Last and then Arg (J) = ' ' loop
+ J := J + 1;
+ end loop;
+
+ if J <= Arg'Last then
+ raise;
+ end if;
+ end if;
+
+ if Neg then
+ return -Result;
+ else
+ return Result;
+ end if;
+ end;
end From_String;
---------------
diff --git a/gcc/ada/libgnat/a-nbnbin.ads b/gcc/ada/libgnat/a-nbnbin.ads
index 7b4974a..668da8d 100644
--- a/gcc/ada/libgnat/a-nbnbin.ads
+++ b/gcc/ada/libgnat/a-nbnbin.ads
@@ -113,7 +113,7 @@ is
Post => To_String'Result'First = 1,
Global => null;
- function From_String (Arg : String) return Big_Integer
+ function From_String (Arg : String) return Valid_Big_Integer
with Global => null;
procedure Put_Image (S : in out Sink'Class; V : Big_Integer);
diff --git a/gcc/ada/libgnat/a-nbnbre.adb b/gcc/ada/libgnat/a-nbnbre.adb
index d61668d..4ff5b35 100644
--- a/gcc/ada/libgnat/a-nbnbre.adb
+++ b/gcc/ada/libgnat/a-nbnbre.adb
@@ -29,9 +29,8 @@
-- --
------------------------------------------------------------------------------
--- This is the default version of this package, based on Big_Integers only.
-
with Ada.Strings.Text_Output.Utils;
+with System.Unsigned_Types; use System.Unsigned_Types;
package body Ada.Numerics.Big_Numbers.Big_Reals is
@@ -84,14 +83,16 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
---------
function "=" (L, R : Valid_Big_Real) return Boolean is
- (abs L.Num = abs R.Num and then L.Den = R.Den);
+ (L.Num = R.Num and then L.Den = R.Den);
---------
-- "<" --
---------
function "<" (L, R : Valid_Big_Real) return Boolean is
- (abs L.Num * R.Den < abs R.Num * L.Den);
+ (L.Num * R.Den < R.Num * L.Den);
+ -- The denominator is guaranteed to be positive since Normalized is
+ -- always called when constructing a Valid_Big_Real
----------
-- "<=" --
@@ -117,22 +118,185 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
package body Float_Conversions is
+ package Conv is new
+ Big_Integers.Unsigned_Conversions (Long_Long_Unsigned);
+
-----------------
-- To_Big_Real --
-----------------
+ -- We get the fractional representation of the floating-point number by
+ -- multiplying Num'Fraction by 2.0**M, with M the size of the mantissa,
+ -- which gives zero or a number in the range [2.0**(M-1)..2.0**M), which
+ -- means that it is an integer N of M bits. The floating-point number is
+ -- thus equal to N / 2**(M-E) where E is its Num'Exponent.
+
function To_Big_Real (Arg : Num) return Valid_Big_Real is
+
+ A : constant Num'Base := abs (Arg);
+ E : constant Integer := Num'Exponent (A);
+ F : constant Num'Base := Num'Fraction (A);
+ M : constant Natural := Num'Machine_Mantissa;
+
+ N, D : Big_Integer;
+
begin
- return From_String (Arg'Image);
+ pragma Assert (Num'Machine_Radix = 2);
+ -- This implementation does not handle radix 16
+
+ pragma Assert (M <= 64);
+ -- This implementation handles only 80-bit IEEE Extended or smaller
+
+ N := Conv.To_Big_Integer (Long_Long_Unsigned (F * 2.0**M));
+
+ -- If E is smaller than M, the denominator is 2**(M-E)
+
+ if E < M then
+ D := To_Big_Integer (2) ** (M - E);
+
+ -- Or else, if E is larger than M, multiply the numerator by 2**(E-M)
+
+ elsif E > M then
+ N := N * To_Big_Integer (2) ** (E - M);
+ D := To_Big_Integer (1);
+
+ -- Otherwise E is equal to M and the result is just N
+
+ else
+ D := To_Big_Integer (1);
+ end if;
+
+ return (if Arg >= 0.0 then N / D else -N / D);
end To_Big_Real;
-------------------
-- From_Big_Real --
-------------------
+ -- We get the (Frac, Exp) representation of the real number by finding
+ -- the exponent E such that it lies in the range [2.0**(E-1)..2.0**E),
+ -- multiplying the number by 2.0**(M-E) with M the size of the mantissa,
+ -- and converting the result to integer N in the range [2**(M-1)..2**M)
+ -- with rounding to nearest, ties to even, and finally call Num'Compose.
+ -- This does not apply to the zero, for which we return 0.0 early.
+
function From_Big_Real (Arg : Big_Real) return Num is
+
+ M : constant Natural := Num'Machine_Mantissa;
+ One : constant Big_Real := To_Real (1);
+ Two : constant Big_Real := To_Real (2);
+ Half : constant Big_Real := One / Two;
+ TwoI : constant Big_Integer := To_Big_Integer (2);
+
+ function Log2_Estimate (V : Big_Real) return Natural;
+ -- Return an integer not larger than Log2 (V) for V >= 1.0
+
+ function Minus_Log2_Estimate (V : Big_Real) return Natural;
+ -- Return an integer not larger than -Log2 (V) for V < 1.0
+
+ -------------------
+ -- Log2_Estimate --
+ -------------------
+
+ function Log2_Estimate (V : Big_Real) return Natural is
+ Log : Natural := 1;
+ Pow : Big_Real := Two;
+
+ begin
+ while V >= Pow loop
+ Pow := Pow * Pow;
+ Log := Log + Log;
+ end loop;
+
+ return Log / 2;
+ end Log2_Estimate;
+
+ -------------------------
+ -- Minus_Log2_Estimate --
+ -------------------------
+
+ function Minus_Log2_Estimate (V : Big_Real) return Natural is
+ Log : Natural := 1;
+ Pow : Big_Real := Half;
+
+ begin
+ while V <= Pow loop
+ Pow := Pow * Pow;
+ Log := Log + Log;
+ end loop;
+
+ return Log / 2;
+ end Minus_Log2_Estimate;
+
+ -- Local variables
+
+ V : Big_Real := abs (Arg);
+ E : Integer := 0;
+ L : Integer;
+
+ A, B, Q, X : Big_Integer;
+ N : Long_Long_Unsigned;
+ R : Num'Base;
+
begin
- return Num'Value (To_String (Arg));
+ pragma Assert (Num'Machine_Radix = 2);
+ -- This implementation does not handle radix 16
+
+ pragma Assert (M <= 64);
+ -- This implementation handles only 80-bit IEEE Extended or smaller
+
+ -- Protect from degenerate case
+
+ if Numerator (V) = To_Big_Integer (0) then
+ return 0.0;
+ end if;
+
+ -- Use a binary search to compute exponent E
+
+ while V < Half loop
+ L := Minus_Log2_Estimate (V);
+ V := V * (Two ** L);
+ E := E - L;
+ end loop;
+
+ -- The dissymetry with above is expected since we go below 2
+
+ while V >= One loop
+ L := Log2_Estimate (V) + 1;
+ V := V / (Two ** L);
+ E := E + L;
+ end loop;
+
+ -- The multiplication by 2.0**(-E) has already been done in the loops
+
+ V := V * To_Big_Real (TwoI ** M);
+
+ -- Now go into the integer domain and divide
+
+ A := Numerator (V);
+ B := Denominator (V);
+
+ Q := A / B;
+ N := Conv.From_Big_Integer (Q);
+
+ -- Round to nearest, ties to even, by comparing twice the remainder
+
+ X := (A - Q * B) * TwoI;
+
+ if X > B or else (X = B and then (N mod 2) = 1) then
+ N := N + 1;
+
+ -- If the adjusted quotient overflows the mantissa, scale up
+
+ if N = 2**M then
+ N := 1;
+ E := E + 1;
+ end if;
+ end if;
+
+ R := Num'Compose (Num'Base (N), E);
+
+ return (if Numerator (Arg) >= To_Big_Integer (0) then R else -R);
end From_Big_Real;
end Float_Conversions;
@@ -143,22 +307,78 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
package body Fixed_Conversions is
+ package Float_Aux is new Float_Conversions (Long_Long_Float);
+
+ subtype LLLI is Long_Long_Long_Integer;
+ subtype LLLU is Long_Long_Long_Unsigned;
+
+ Too_Large : constant Boolean :=
+ Num'Small_Numerator > LLLU'Last
+ or else Num'Small_Denominator > LLLU'Last;
+ -- True if the Small is too large for Long_Long_Long_Unsigned, in which
+ -- case we convert to/from Long_Long_Float as an intermediate step.
+
+ package Conv_I is new Big_Integers.Signed_Conversions (LLLI);
+ package Conv_U is new Big_Integers.Unsigned_Conversions (LLLU);
+
-----------------
-- To_Big_Real --
-----------------
+ -- We just compute V * N / D where V is the mantissa value of the fixed
+ -- point number, and N resp. D is the numerator resp. the denominator of
+ -- the Small of the fixed-point type.
+
function To_Big_Real (Arg : Num) return Valid_Big_Real is
+ N, D, V : Big_Integer;
+
begin
- return From_String (Arg'Image);
+ if Too_Large then
+ return Float_Aux.To_Big_Real (Long_Long_Float (Arg));
+ end if;
+
+ N := Conv_U.To_Big_Integer (Num'Small_Numerator);
+ D := Conv_U.To_Big_Integer (Num'Small_Denominator);
+ V := Conv_I.To_Big_Integer (LLLI'Integer_Value (Arg));
+
+ return V * N / D;
end To_Big_Real;
-------------------
-- From_Big_Real --
-------------------
+ -- We first compute A / B = Arg * D / N where N resp. D is the numerator
+ -- resp. the denominator of the Small of the fixed-point type. Then we
+ -- divide A by B and convert the result to the mantissa value.
+
function From_Big_Real (Arg : Big_Real) return Num is
+ N, D, A, B, Q, X : Big_Integer;
+
begin
- return Num'Value (To_String (Arg));
+ if Too_Large then
+ return Num (Float_Aux.From_Big_Real (Arg));
+ end if;
+
+ N := Conv_U.To_Big_Integer (Num'Small_Numerator);
+ D := Conv_U.To_Big_Integer (Num'Small_Denominator);
+ A := Numerator (Arg) * D;
+ B := Denominator (Arg) * N;
+
+ Q := A / B;
+
+ -- Round to nearest, ties to away, by comparing twice the remainder
+
+ X := (A - Q * B) * To_Big_Integer (2);
+
+ if X >= B then
+ Q := Q + To_Big_Integer (1);
+
+ elsif X <= -B then
+ Q := Q - To_Big_Integer (1);
+ end if;
+
+ return Num'Fixed_Value (Conv_I.From_Big_Integer (Q));
end From_Big_Real;
end Fixed_Conversions;
@@ -318,7 +538,7 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
-- From_String --
-----------------
- function From_String (Arg : String) return Big_Real is
+ function From_String (Arg : String) return Valid_Big_Real is
Ten : constant Big_Integer := To_Big_Integer (10);
Frac : Big_Integer;
Exp : Integer := 0;
@@ -340,7 +560,7 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
elsif Arg (J) = '.' then
Index := J - 1;
exit;
- else
+ elsif Arg (J) /= '_' then
Pow := Pow + 1;
end if;
end loop;
@@ -373,6 +593,13 @@ package body Ada.Numerics.Big_Numbers.Big_Reals is
end;
end From_String;
+ function From_String
+ (Numerator, Denominator : String) return Valid_Big_Real is
+ begin
+ return Big_Integers.From_String (Numerator) /
+ Big_Integers.From_String (Denominator);
+ end From_String;
+
--------------------------
-- From_Quotient_String --
--------------------------
diff --git a/gcc/ada/libgnat/a-nbnbre.ads b/gcc/ada/libgnat/a-nbnbre.ads
index 5a8ebb9..ee5636f 100644
--- a/gcc/ada/libgnat/a-nbnbre.ads
+++ b/gcc/ada/libgnat/a-nbnbre.ads
@@ -120,7 +120,9 @@ is
Post => To_String'Result'First = 1,
Global => null;
- function From_String (Arg : String) return Big_Real
+ function From_String (Arg : String) return Valid_Big_Real
+ with Global => null;
+ function From_String (Numerator, Denominator : String) return Valid_Big_Real
with Global => null;
function To_Quotient_String (Arg : Big_Real) return String is
diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads
index 7d6e121..4214157 100644
--- a/gcc/ada/libgnat/a-strfix.ads
+++ b/gcc/ada/libgnat/a-strfix.ads
@@ -108,10 +108,57 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre =>
+ Pre =>
Pattern'Length /= 0
and then (if Source'Length /= 0 then From in Source'Range),
- Global => null;
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If no slice in the considered range of Source matches Pattern,
+ -- then 0 is returned.
+
+ ((for all J in Source'Range =>
+ (if (if Going = Forward
+ then J in From .. Source'Last - Pattern'Length + 1
+ else J <= From - Pattern'Length + 1)
+ then Translate (Source (J .. J - 1 + Pattern'Length), Mapping)
+ /= Pattern))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, a valid index is returned
+
+ others
+ =>
+
+ -- The result is in the considered range of Source
+
+ (if Going = Forward
+ then Index'Result in From .. Source'Last - Pattern'Length + 1
+ else Index'Result in Source'First .. From - Pattern'Length + 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then
+ Translate (Source (Index'Result
+ .. Index'Result - 1 + Pattern'Length),
+ Mapping)
+ = Pattern
+
+ -- The result is the smallest or largest index which satisfies the
+ -- matching, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result .. From - Pattern'Length)
+ then Translate (Source (J .. J - 1 + Pattern'Length),
+ Mapping)
+ /= Pattern))),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -121,10 +168,57 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre =>
+ Pre =>
Pattern'Length /= 0
and then (if Source'Length /= 0 then From in Source'Range),
- Global => null;
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If no slice in the considered range of Source matches Pattern,
+ -- then 0 is returned.
+
+ ((for all J in Source'Range =>
+ (if (if Going = Forward
+ then J in From .. Source'Last - Pattern'Length + 1
+ else J <= From - Pattern'Length + 1)
+ then Translate (Source (J .. J - 1 + Pattern'Length), Mapping)
+ /= Pattern))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, a valid index is returned
+
+ others
+ =>
+
+ -- The result is in the considered range of Source
+
+ (if Going = Forward
+ then Index'Result in From .. Source'Last - Pattern'Length + 1
+ else Index'Result in Source'First .. From - Pattern'Length + 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then
+ Translate (Source (Index'Result
+ .. Index'Result - 1 + Pattern'Length),
+ Mapping)
+ = Pattern
+
+ -- The result is the smallest or largest index which satisfies the
+ -- matching, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result .. From - Pattern'Length)
+ then Translate (Source (J .. J - 1 + Pattern'Length),
+ Mapping)
+ /= Pattern))),
+ Global => null;
pragma Ada_05 (Index);
-- Each Index function searches, starting from From, for a slice of
@@ -146,8 +240,53 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre => Pattern'Length > 0,
- Global => null;
+ Pre => Pattern'Length > 0,
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is empty, or if no slice of Source matches Pattern, then
+ -- 0 is returned.
+
+ (Source'Length = 0
+ or else
+ (for all J in Source'First .. Source'Last - Pattern'Length + 1 =>
+ Translate (Source (J .. J - 1 + Pattern'Length), Mapping)
+ /= Pattern)
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, a valid index is returned
+
+ others
+ =>
+
+ -- The result is in the considered range of Source
+
+ Index'Result in Source'First .. Source'Last - Pattern'Length + 1
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then
+ Translate (Source (Index'Result
+ .. Index'Result - 1 + Pattern'Length),
+ Mapping)
+ = Pattern
+
+ -- The result is the smallest or largest index which satisfies the
+ -- matching, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Source'Last - Pattern'Length)
+ then Translate (Source (J .. J - 1 + Pattern'Length),
+ Mapping)
+ /= Pattern))),
+ Global => null;
function Index
(Source : String;
@@ -155,8 +294,53 @@ package Ada.Strings.Fixed with SPARK_Mode is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
- Global => null;
+ Pre => Pattern'Length > 0,
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If Source is empty, or if no slice of Source matches Pattern, then
+ -- 0 is returned.
+
+ (Source'Length = 0
+ or else
+ (for all J in Source'First .. Source'Last - Pattern'Length + 1 =>
+ Translate (Source (J .. J - 1 + Pattern'Length), Mapping)
+ /= Pattern)
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, a valid index is returned
+
+ others
+ =>
+
+ -- The result is in the considered range of Source
+
+ Index'Result in Source'First .. Source'Last - Pattern'Length + 1
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then
+ Translate (Source (Index'Result
+ .. Index'Result - 1 + Pattern'Length),
+ Mapping)
+ = Pattern
+
+ -- The result is the smallest or largest index which satisfies the
+ -- matching, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Source'Last - Pattern'Length)
+ then Translate (Source (J .. J - 1 + Pattern'Length),
+ Mapping)
+ /= Pattern))),
+ Global => null;
-- If Going = Forward, returns:
--
@@ -172,7 +356,44 @@ package Ada.Strings.Fixed with SPARK_Mode is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set, then
+ -- 0 is returned.
+
+ ((for all C of Source =>
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (C, Set))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, a index in the range of Source is returned
+
+ others
+ =>
+
+ -- The result is in the range of Source
+
+ Index'Result in Source'Range
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set
+
+ and then
+ (Test = Inside)
+ = Ada.Strings.Maps.Is_In (Source (Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies the
+ -- property, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Ada.Strings.Maps.Is_In (Source (J), Set)))),
+ Global => null;
function Index
(Source : String;
@@ -181,8 +402,53 @@ package Ada.Strings.Fixed with SPARK_Mode is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Pre => (if Source'Length /= 0 then From in Source'Range),
- Global => null;
+ Pre => (if Source'Length /= 0 then From in Source'Range),
+
+ Post => Index'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If no character in the considered slice of Source satisfies the
+ -- property Test on Set, then 0 is returned.
+
+ ((for all I in Source'Range =>
+ (if I = From
+ or else (I > From) = (Going = Forward)
+ then (Test = Inside) /= Ada.Strings.Maps.Is_In (Source (I), Set)))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+
+ -- The result is in the considered range of Source
+
+ Index'Result in Source'Range
+ and then (Index'Result = From
+ or else (Index'Result > From) = (Going = Forward))
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside)
+ = Ada.Strings.Maps.Is_In (Source (Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies the
+ -- property, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then
+ (Test = Inside)
+ /= Ada.Strings.Maps.Is_In (Source (J), Set)))),
+ Global => null;
pragma Ada_05 (Index);
-- Index searches for the first or last occurrence of any of a set of
-- characters (when Test=Inside), or any of the complement of a set of
@@ -198,8 +464,49 @@ package Ada.Strings.Fixed with SPARK_Mode is
From : Positive;
Going : Direction := Forward) return Natural
with
- Pre => (if Source'Length /= 0 then From in Source'Range),
- Global => null;
+ Pre => (if Source'Length /= 0 then From in Source'Range),
+
+ Post => Index_Non_Blank'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If all characters in the considered slice of Source are Space
+ -- characters, then 0 is returned.
+
+ ((for all J in Source'Range =>
+ (if J = From or else (J > From) = (Going = Forward)
+ then Source (J) = ' '))
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, a valid index is returned
+
+ others
+ =>
+
+ -- The result is in the considered range of Source
+
+ Index_Non_Blank'Result in Source'Range
+ and then (Index_Non_Blank'Result = From
+ or else (Index_Non_Blank'Result > From)
+ = (Going = Forward))
+
+ -- The character at the returned index is not a Space character
+
+ and then Source (Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if J /= Index_Non_Blank'Result
+ and then (J < Index_Non_Blank'Result)
+ = (Going = Forward)
+ and then (J = From or else (J > From)
+ = (Going = Forward))
+ then Source (J) = ' '))),
+ Global => null;
pragma Ada_05 (Index_Non_Blank);
-- Returns Index (Source, Maps.To_Set(Space), From, Outside, Going)
@@ -207,7 +514,37 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Source : String;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index_Non_Blank'Result in 0 | Source'Range,
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of Source => C = ' ') => Index_Non_Blank'Result = 0,
+
+ -- Otherwise, a valid index is returned
+
+ others =>
+
+ -- The result is in the range of Source
+
+ Index_Non_Blank'Result in Source'Range
+
+ -- The character at the returned index is not a Space character
+
+ and then Source (Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and
+ -- Going = Backwards.
+
+ and then
+ (for all J in Source'Range =>
+ (if J /= Index_Non_Blank'Result
+ and then (J < Index_Non_Blank'Result)
+ = (Going = Forward)
+ then Source (J) = ' '))),
+ Global => null;
-- Returns Index (Source, Maps.To_Set(Space), Outside, Going)
function Count
@@ -246,8 +583,53 @@ package Ada.Strings.Fixed with SPARK_Mode is
First : out Positive;
Last : out Natural)
with
- Pre => (if Source'Length /= 0 then From in Source'Range),
- Global => null;
+ Pre => (if Source'Length /= 0 then From in Source'Range),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the considered
+ -- slice of Source satisfies the property Test on Set, then First is
+ -- set to From and Last is set to 0.
+
+ (Source'Length = 0
+ or else
+ (for all C of Source (From .. Source'Last) =>
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (C, Set))
+ =>
+ First = From and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+
+ -- First and Last are in the considered range of Source
+
+ First in From .. Source'Last
+ and then Last in First .. Source'Last
+
+ -- No character between From and First satisfies the property Test
+ -- on Set.
+
+ and then
+ (for all C of Source (From .. First - 1) =>
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (C, Set))
+
+ -- All characters between First and Last satisfy the property Test
+ -- on Set.
+
+ and then
+ (for all C of Source (First .. Last) =>
+ (Test = Inside) = Ada.Strings.Maps.Is_In (C, Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Source'Last
+ then
+ (Test = Inside)
+ /= Ada.Strings.Maps.Is_In (Source (Last + 1), Set))),
+ Global => null;
pragma Ada_2012 (Find_Token);
-- If Source is not the null string and From is not in Source'Range, then
-- Index_Error is raised. Otherwise, First is set to the index of the first
@@ -264,6 +646,50 @@ package Ada.Strings.Fixed with SPARK_Mode is
First : out Positive;
Last : out Natural)
with
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of Source
+ -- satisfies the property Test on Set, then First is set to From and
+ -- Last is set to 0.
+
+ (Source'Length = 0
+ or else
+ (for all C of Source =>
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (C, Set))
+ =>
+ First = Source'First and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+
+ -- First and Last are in the considered range of Source
+
+ First in Source'Range
+ and then Last in First .. Source'Last
+
+ -- No character before First satisfies the property Test on Set
+
+ and then
+ (for all C of Source (Source'First .. First - 1) =>
+ (Test = Inside) /= Ada.Strings.Maps.Is_In (C, Set))
+
+ -- All characters between First and Last satisfy the property Test
+ -- on Set.
+
+ and then
+ (for all C of Source (First .. Last) =>
+ (Test = Inside) = Ada.Strings.Maps.Is_In (C, Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Source'Last
+ then
+ (Test = Inside)
+ /= Ada.Strings.Maps.Is_In (Source (Last + 1), Set))),
Global => null;
-- Equivalent to Find_Token (Source, Set, Source'First, Test, First, Last)
@@ -275,14 +701,46 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Source : String;
Mapping : Maps.Character_Mapping_Function) return String
with
- Post => Translate'Result'Length = Source'Length,
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Translate'Result'First = 1
+
+ -- The returned string has the same length as Source
+
+ and then Translate'Result'Last = Source'Length
+
+ -- Each character in the returned string is the translation of the
+ -- character at the same position in Source through Mapping.
+
+ and then
+ (for all J in Source'Range =>
+ Translate'Result (J - Source'First + 1)
+ = Mapping (Source (J))),
Global => null;
function Translate
(Source : String;
Mapping : Maps.Character_Mapping) return String
with
- Post => Translate'Result'Length = Source'Length,
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Translate'Result'First = 1
+
+ -- The returned string has the same length as Source
+
+ and then Translate'Result'Last = Source'Length
+
+ -- Each character in the returned string is the translation of the
+ -- character at the same position in Source through Mapping.
+
+ and then
+ (for all J in Source'Range =>
+ Translate'Result (J - Source'First + 1)
+ = Ada.Strings.Maps.Value (Mapping, Source (J))),
Global => null;
-- Returns the string S whose length is Source'Length and such that S (I)
@@ -293,12 +751,25 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Source : in out String;
Mapping : Maps.Character_Mapping_Function)
with
+ Post =>
+
+ -- Each character in Source after the call is the translation of
+ -- the character at the same position before the call, through Mapping.
+
+ (for all J in Source'Range => Source (J) = Mapping (Source'Old (J))),
Global => null;
procedure Translate
(Source : in out String;
Mapping : Maps.Character_Mapping)
with
+ Post =>
+
+ -- Each character in Source after the call is the translation of
+ -- the character at the same position before the call, through Mapping.
+
+ (for all J in Source'Range =>
+ Source (J) = Ada.Strings.Maps.Value (Mapping, Source'Old (J))),
Global => null;
-- Equivalent to Source := Translate(Source, Mapping)
@@ -344,17 +815,80 @@ package Ada.Strings.Fixed with SPARK_Mode is
and then High >= Source'First - 1
and then (if High >= Low
then Natural'Max (0, Low - Source'First)
- <= Natural'Last - By'Length
- - Natural'Max (Source'Last - High, 0)
+ <= Natural'Last
+ - By'Length
+ - Natural'Max (Source'Last - High, 0)
else Source'Length <= Natural'Last - By'Length),
+
+ -- Lower bound of the returned string is 1
+
+ Post => Replace_Slice'Result'First = 1,
Contract_Cases =>
+
+ -- If High >= Low, then the returned string comprises
+ -- Source (Source'First .. Low - 1) & By
+ -- & Source(High + 1 .. Source'Last).
+
(High >= Low =>
+
+ -- Length of the returned string
+
Replace_Slice'Result'Length
- = Natural'Max (0, Low - Source'First)
- + By'Length
- + Natural'Max (Source'Last - High, 0),
+ = Natural'Max (0, Low - Source'First)
+ + By'Length
+ + Natural'Max (Source'Last - High, 0)
+
+ -- Elements starting at Low are replaced by elements of By
+
+ and then
+ Replace_Slice'Result (1 .. Natural'Max (0, Low - Source'First))
+ = Source (Source'First .. Low - 1)
+ and then
+ Replace_Slice'Result
+ (Natural'Max (0, Low - Source'First) + 1
+ .. Natural'Max (0, Low - Source'First) + By'Length)
+ = By
+
+ -- When there are remaining characters after the replaced slice,
+ -- they are appended to the result.
+
+ and then
+ (if High < Source'Last
+ then
+ Replace_Slice'Result
+ (Natural'Max (0, Low - Source'First) + By'Length + 1
+ .. Replace_Slice'Result'Last)
+ = Source (High + 1 .. Source'Last)),
+
+ -- If High < Low, then the returned string is
+ -- Insert (Source, Before => Low, New_Item => By).
+
others =>
- Replace_Slice'Result'Length = Source'Length + By'Length),
+
+ -- Length of the returned string
+
+ Replace_Slice'Result'Length = Source'Length + By'Length
+
+ -- Elements of By are inserted after the element at Low
+
+ and then
+ Replace_Slice'Result (1 .. Low - Source'First)
+ = Source (Source'First .. Low - 1)
+ and then
+ Replace_Slice'Result
+ (Low - Source'First + 1 .. Low - Source'First + By'Length)
+ = By
+
+ -- When there are remaining characters after Low in Source, they
+ -- are appended to the result.
+
+ and then
+ (if Low < Source'Last
+ then
+ Replace_Slice'Result
+ (Low - Source'First + By'Length + 1
+ .. Replace_Slice'Result'Last)
+ = Source (Low .. Source'Last))),
Global => null;
-- Equivalent to:
--
@@ -369,7 +903,38 @@ package Ada.Strings.Fixed with SPARK_Mode is
Pre =>
Before - 1 in Source'First - 1 .. Source'Last
and then Source'Length <= Natural'Last - New_Item'Length,
- Post => Insert'Result'Length = Source'Length + New_Item'Length,
+
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Insert'Result'First = 1
+
+ -- Length of the returned string
+
+ and then Insert'Result'Length = Source'Length + New_Item'Length
+
+ -- Elements of New_Item are inserted after element at Before
+
+ and then
+ Insert'Result (1 .. Before - Source'First)
+ = Source (Source'First .. Before - 1)
+ and then
+ Insert'Result
+ (Before - Source'First + 1
+ .. Before - Source'First + New_Item'Length)
+ = New_Item
+
+ -- When there are remaining characters after Before in Source, they
+ -- are appended to the returned string.
+
+ and then
+ (if Before - 1 < Source'Last
+ then
+ Insert'Result
+ (Before - Source'First + New_Item'Length + 1
+ .. Insert'Result'Last)
+ = Source (Before .. Source'Last)),
Global => null;
-- Propagates Index_Error if Before is not in
-- Source'First .. Source'Last+1; otherwise, returns
@@ -397,12 +962,44 @@ package Ada.Strings.Fixed with SPARK_Mode is
Pre =>
Position - 1 in Source'First - 1 .. Source'Last
and then
- (if Position - Source'First >= Source'Length - New_Item'Length
- then Position - Source'First <= Natural'Last - New_Item'Length),
+ (if Position - Source'First >= Source'Length - New_Item'Length
+ then Position - Source'First <= Natural'Last - New_Item'Length),
+
Post =>
- Overwrite'Result'Length
- = Integer'Max (Source'Length,
- Position - Source'First + New_Item'Length),
+
+ -- Lower bound of the returned string is 1
+
+ Overwrite'Result'First = 1
+
+ -- Length of the returned string
+
+ and then
+ Overwrite'Result'Length
+ = Integer'Max (Source'Length,
+ Position - Source'First + New_Item'Length)
+
+ -- Elements after Position are replaced by elements of New_Item
+
+ and then
+ Overwrite'Result (1 .. Position - Source'First)
+ = Source (Source'First .. Position - 1)
+ and then
+ Overwrite'Result
+ (Position - Source'First + 1
+ .. Position - Source'First + New_Item'Length)
+ = New_Item
+
+ -- If the end of Source is reached before the characters in New_Item
+ -- are exhausted, the remaining characters from New_Item are appended
+ -- to the string.
+
+ and then
+ (if Position <= Source'Last - New_Item'Length
+ then
+ Overwrite'Result
+ (Position - Source'First + New_Item'Length + 1
+ .. Overwrite'Result'Last)
+ = Source (Position + New_Item'Length .. Source'Last)),
Global => null;
-- Propagates Index_Error if Position is not in
-- Source'First .. Source'Last + 1; otherwise, returns the string obtained
@@ -429,15 +1026,47 @@ package Ada.Strings.Fixed with SPARK_Mode is
From : Positive;
Through : Natural) return String
with
- Pre => (if From <= Through
- then (From in Source'Range
- and then Through <= Source'Last)),
- Post =>
- Delete'Result'Length
- = Source'Length - (if From <= Through
- then Through - From + 1
- else 0),
- Global => null;
+ Pre => (if From <= Through
+ then (From in Source'Range
+ and then Through <= Source'Last)),
+
+ -- Lower bound of the returned string is 1
+
+ Post =>
+ Delete'Result'First = 1,
+
+ Contract_Cases =>
+
+ -- If From <= Through, the characters between From and Through are
+ -- removed.
+
+ (From <= Through =>
+
+ -- Length of the returned string
+
+ Delete'Result'Length = Source'Length - (Through - From + 1)
+
+ -- Elements before From are preserved
+
+ and then
+ Delete'Result (1 .. From - Source'First)
+ = Source (Source'First .. From - 1)
+
+ -- If there are remaining characters after Through, they are
+ -- appended to the returned string.
+
+ and then
+ (if Through < Source'Last
+ then Delete'Result
+ (From - Source'First + 1 .. Delete'Result'Last)
+ = Source (Through + 1 .. Source'Last)),
+
+ -- Otherwise, the returned string is Source with lower bound 1
+
+ others =>
+ Delete'Result'Length = Source'Length
+ and then Delete'Result = Source),
+ Global => null;
-- If From <= Through, the returned string is
-- Replace_Slice(Source, From, Through, ""); otherwise, it is Source with
-- lower bound 1.
@@ -469,7 +1098,47 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Source : String;
Side : Trim_End) return String
with
- Post => Trim'Result'Length <= Source'Length,
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Trim'Result'First = 1
+
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ and then
+ (if (for all J in Source'Range => Source (J) = ' ')
+ then Trim'Result = ""
+
+ -- Otherwise, the returned string is a slice of Source
+
+ else
+ (for some Low in Source'Range =>
+ (for some High in Source'Range =>
+
+ -- Trim returns the slice of Source between Low and High
+
+ Trim'Result = Source (Low .. High)
+
+ -- Values of Low and High and the characters at their
+ -- position depend on Side.
+
+ and then
+ (if Side = Left then High = Source'Last
+ else Source (High) /= ' ')
+ and then
+ (if Side = Right then Low = Source'First
+ else Source (Low) /= ' ')
+
+ -- All characters outside range Low .. High are
+ -- Space characters.
+
+ and then
+ (for all J in Source'Range =>
+ (if J < Low then Source (J) = ' ')
+ and then
+ (if J > High then Source (J) = ' '))))),
Global => null;
-- Returns the string obtained by removing from Source all leading Space
-- characters (if Side = Left), all trailing Space characters (if
@@ -495,7 +1164,50 @@ package Ada.Strings.Fixed with SPARK_Mode is
Left : Maps.Character_Set;
Right : Maps.Character_Set) return String
with
- Post => Trim'Result'Length <= Source'Length,
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Trim'Result'First = 1
+
+ -- If all characters are contained in one of the sets Left and Right,
+ -- then the returned string is empty.
+
+ and then
+ (if (for all K in Source'Range =>
+ Ada.Strings.Maps.Is_In (Source (K), Left))
+ or
+ (for all K in Source'Range =>
+ Ada.Strings.Maps.Is_In (Source (K), Right))
+ then Trim'Result = ""
+
+ -- Otherwise, the returned string is a slice of Source
+
+ else
+ (for some Low in Source'Range =>
+ (for some High in Source'Range =>
+
+ -- Trim returns the slice of Source between Low and High
+
+ Trim'Result = Source (Low .. High)
+
+ -- Characters at the bounds of the returned string are
+ -- not contained in Left or Right.
+
+ and then not Ada.Strings.Maps.Is_In (Source (Low), Left)
+ and then not Ada.Strings.Maps.Is_In (Source (High), Right)
+
+ -- All characters before Low are contained in Left.
+ -- All characters after High are contained in Right.
+
+ and then
+ (for all K in Source'Range =>
+ (if K < Low
+ then
+ Ada.Strings.Maps.Is_In (Source (K), Left))
+ and then
+ (if K > High then
+ Ada.Strings.Maps.Is_In (Source (K), Right)))))),
Global => null;
-- Returns the string obtained by removing from Source all leading
-- characters in Left and all trailing characters in Right.
@@ -521,8 +1233,33 @@ package Ada.Strings.Fixed with SPARK_Mode is
Count : Natural;
Pad : Character := Space) return String
with
- Post => Head'Result'Length = Count,
- Global => null;
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Head'Result'First = 1
+
+ -- Length of the returned string is Count.
+
+ and then Head'Result'Length = Count,
+
+ Contract_Cases =>
+
+ -- If Count <= Source'Length, then the first Count characters of
+ -- Source are returned.
+
+ (Count <= Source'Length =>
+ Head'Result = Source (Source'First .. Source'First - 1 + Count),
+
+ -- Otherwise, the returned string is Source concatenated with
+ -- Count - Source'Length Pad characters.
+
+ others =>
+ Head'Result (1 .. Source'Length) = Source
+ and then
+ Head'Result (Source'Length + 1 .. Count)
+ = (1 .. Count - Source'Length => Pad)),
+ Global => null;
-- Returns a string of length Count. If Count <= Source'Length, the string
-- comprises the first Count characters of Source. Otherwise, its contents
-- are Source concatenated with Count - Source'Length Pad characters.
@@ -547,7 +1284,44 @@ package Ada.Strings.Fixed with SPARK_Mode is
Count : Natural;
Pad : Character := Space) return String
with
- Post => Tail'Result'Length = Count,
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ Tail'Result'First = 1
+
+ -- Length of the returned string is Count
+
+ and then Tail'Result'Length = Count,
+ Contract_Cases =>
+
+ -- If Count is zero, then the returned string is empty
+
+ (Count = 0 =>
+ Tail'Result = "",
+
+ -- Otherwise, if Count <= Source'Length, then the last Count
+ -- characters of Source are returned.
+
+ (Count in 1 .. Source'Length) =>
+ Tail'Result = Source (Source'Last - Count + 1 .. Source'Last),
+
+ -- Otherwise, the returned string is Count - Source'Length Pad
+ -- characters concatenated with Source.
+
+ others =>
+
+ -- If Source is empty, then the returned string is Count Pad
+ -- characters.
+
+ (if Source'Length = 0
+ then Tail'Result = (1 .. Count => Pad)
+ else
+ Tail'Result (1 .. Count - Source'Length)
+ = (1 .. Count - Source'Length => Pad)
+ and then
+ Tail'Result (Count - Source'Length + 1 .. Tail'Result'Last)
+ = Source)),
Global => null;
-- Returns a string of length Count. If Count <= Source'Length, the string
-- comprises the last Count characters of Source. Otherwise, its contents
@@ -576,7 +1350,19 @@ package Ada.Strings.Fixed with SPARK_Mode is
(Left : Natural;
Right : Character) return String
with
- Post => "*"'Result'Length = Left,
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ "*"'Result'First = 1
+
+ -- Length of the returned string
+
+ and then "*"'Result'Length = Left
+
+ -- All characters of the returned string are Right
+
+ and then (for all C of "*"'Result => C = Right),
Global => null;
function "*"
@@ -584,7 +1370,23 @@ package Ada.Strings.Fixed with SPARK_Mode is
Right : String) return String
with
Pre => (if Right'Length /= 0 then Left <= Natural'Last / Right'Length),
- Post => "*"'Result'Length = Left * Right'Length,
+
+ Post =>
+
+ -- Lower bound of the returned string is 1
+
+ "*"'Result'First = 1
+
+ -- Length of the returned string
+
+ and then "*"'Result'Length = Left * Right'Length
+
+ -- Content of the string is Right concatenated with itself Left times
+
+ and then
+ (for all J in 0 .. Left - 1 =>
+ "*"'Result (J * Right'Length + 1 .. (J + 1) * Right'Length)
+ = Right),
Global => null;
-- These functions replicate a character or string a specified number of
diff --git a/gcc/ada/libgnat/a-strmap.ads b/gcc/ada/libgnat/a-strmap.ads
index ab59402..c922f4e 100644
--- a/gcc/ada/libgnat/a-strmap.ads
+++ b/gcc/ada/libgnat/a-strmap.ads
@@ -33,6 +33,12 @@
-- --
------------------------------------------------------------------------------
+-- Preconditions in this unit are meant for analysis only, not for run-time
+-- checking, so that the expected exceptions are raised. This is enforced by
+-- setting the corresponding assertion policy to Ignore.
+
+pragma Assertion_Policy (Pre => Ignore);
+
with Ada.Characters.Latin_1;
package Ada.Strings.Maps is
@@ -61,23 +67,85 @@ package Ada.Strings.Maps is
type Character_Ranges is array (Positive range <>) of Character_Range;
- function To_Set (Ranges : Character_Ranges) return Character_Set;
-
- function To_Set (Span : Character_Range) return Character_Set;
-
- function To_Ranges (Set : Character_Set) return Character_Ranges;
+ function To_Set (Ranges : Character_Ranges) return Character_Set with
+ Post =>
+ (if Ranges'Length = 0 then To_Set'Result = Null_Set)
+ and then
+ (for all Char in Character =>
+ (if Is_In (Char, To_Set'Result)
+ then (for some Span of Ranges => Char in Span.Low .. Span.High)))
+ and then
+ (for all Span of Ranges =>
+ (for all Char in Span.Low .. Span.High =>
+ Is_In (Char, To_Set'Result)));
+
+ function To_Set (Span : Character_Range) return Character_Set with
+ Post =>
+ (if Span.High < Span.Low then To_Set'Result = Null_Set)
+ and then
+ (for all Char in Character =>
+ (if Is_In (Char, To_Set'Result) then Char in Span.Low .. Span.High))
+ and then
+ (for all Char in Span.Low .. Span.High => Is_In (Char, To_Set'Result));
+
+ function To_Ranges (Set : Character_Set) return Character_Ranges with
+ Post =>
+ (if Set = Null_Set then To_Ranges'Result'Length = 0)
+ and then
+ (for all Char in Character =>
+ (if Is_In (Char, Set)
+ then
+ (for some Span of To_Ranges'Result =>
+ Char in Span.Low .. Span.High)))
+ and then
+ (for all Span of To_Ranges'Result =>
+ (for all Char in Span.Low .. Span.High => Is_In (Char, Set)));
----------------------------------
-- Operations on Character Sets --
----------------------------------
- function "=" (Left, Right : Character_Set) return Boolean;
-
- function "not" (Right : Character_Set) return Character_Set;
- function "and" (Left, Right : Character_Set) return Character_Set;
- function "or" (Left, Right : Character_Set) return Character_Set;
- function "xor" (Left, Right : Character_Set) return Character_Set;
- function "-" (Left, Right : Character_Set) return Character_Set;
+ function "=" (Left, Right : Character_Set) return Boolean with
+ Post =>
+ "="'Result
+ =
+ (for all Char in Character =>
+ (Is_In (Char, Left) = Is_In (Char, Right)));
+
+ function "not" (Right : Character_Set) return Character_Set with
+ Post =>
+ (for all Char in Character =>
+ (Is_In (Char, "not"'Result)
+ =
+ not Is_In (Char, Right)));
+
+ function "and" (Left, Right : Character_Set) return Character_Set with
+ Post =>
+ (for all Char in Character =>
+ (Is_In (Char, "and"'Result)
+ =
+ (Is_In (Char, Left) and Is_In (Char, Right))));
+
+ function "or" (Left, Right : Character_Set) return Character_Set with
+ Post =>
+ (for all Char in Character =>
+ (Is_In (Char, "or"'Result)
+ =
+ (Is_In (Char, Left) or Is_In (Char, Right))));
+
+ function "xor" (Left, Right : Character_Set) return Character_Set with
+ Post =>
+ (for all Char in Character =>
+ (Is_In (Char, "xor"'Result)
+ =
+ (Is_In (Char, Left) xor Is_In (Char, Right))));
+
+ function "-" (Left, Right : Character_Set) return Character_Set with
+ Post =>
+ (for all Char in Character =>
+ (Is_In (Char, "-"'Result)
+ =
+ (Is_In (Char, Left) and not Is_In (Char, Right))));
function Is_In
(Element : Character;
@@ -85,20 +153,54 @@ package Ada.Strings.Maps is
function Is_Subset
(Elements : Character_Set;
- Set : Character_Set) return Boolean;
+ Set : Character_Set) return Boolean
+ with
+ Post =>
+ Is_Subset'Result
+ =
+ (for all Char in Character =>
+ (if Is_In (Char, Elements) then Is_In (Char, Set)));
function "<="
(Left : Character_Set;
- Right : Character_Set) return Boolean
+ Right : Character_Set) return Boolean
renames Is_Subset;
subtype Character_Sequence is String;
-- Alternative representation for a set of character values
- function To_Set (Sequence : Character_Sequence) return Character_Set;
- function To_Set (Singleton : Character) return Character_Set;
-
- function To_Sequence (Set : Character_Set) return Character_Sequence;
+ function To_Set (Sequence : Character_Sequence) return Character_Set with
+ Post =>
+ (if Sequence'Length = 0 then To_Set'Result = Null_Set)
+ and then
+ (for all Char in Character =>
+ (if Is_In (Char, To_Set'Result)
+ then (for some X of Sequence => Char = X)))
+ and then
+ (for all Char of Sequence => Is_In (Char, To_Set'Result));
+
+ function To_Set (Singleton : Character) return Character_Set with
+ Post =>
+ Is_In (Singleton, To_Set'Result)
+ and then
+ (for all Char in Character =>
+ (if Char /= Singleton
+ then not Is_In (Char, To_Set'Result)));
+
+ function To_Sequence (Set : Character_Set) return Character_Sequence with
+ Post =>
+ (if Set = Null_Set then To_Sequence'Result'Length = 0)
+ and then
+ (for all Char in Character =>
+ (if Is_In (Char, Set)
+ then (for some X of To_Sequence'Result => Char = X)))
+ and then
+ (for all Char of To_Sequence'Result => Is_In (Char, Set))
+ and then
+ (for all J in To_Sequence'Result'Range =>
+ (for all K in To_Sequence'Result'Range =>
+ (if J /= K
+ then To_Sequence'Result (J) /= To_Sequence'Result (K))));
------------------------------------
-- Character Mapping Declarations --
@@ -119,13 +221,48 @@ package Ada.Strings.Maps is
----------------------------
function To_Mapping
- (From, To : Character_Sequence) return Character_Mapping;
+ (From, To : Character_Sequence) return Character_Mapping
+ with
+ Pre =>
+ From'Length = To'Length
+ and then
+ (for all J in From'Range =>
+ (for all K in From'Range =>
+ (if J /= K then From (J) /= From (K)))),
+ Post =>
+ (if From = To then To_Mapping'Result = Identity)
+ and then
+ (for all Char in Character =>
+ ((for all J in From'Range =>
+ (if From (J) = Char
+ then Value (To_Mapping'Result, Char)
+ = To (J - From'First + To'First)))
+ and then
+ (if (for all X of From => Char /= X)
+ then Value (To_Mapping'Result, Char) = Char)));
function To_Domain
- (Map : Character_Mapping) return Character_Sequence;
+ (Map : Character_Mapping) return Character_Sequence with
+ Post =>
+ (if Map = Identity then To_Domain'Result'Length = 0)
+ and then
+ To_Domain'Result'First = 1
+ and then
+ (for all Char in Character =>
+ (if (for all X of To_Domain'Result => X /= Char)
+ then Value (Map, Char) = Char))
+ and then
+ (for all Char of To_Domain'Result => Value (Map, Char) /= Char);
function To_Range
- (Map : Character_Mapping) return Character_Sequence;
+ (Map : Character_Mapping) return Character_Sequence with
+ Post =>
+ To_Range'Result'First = 1
+ and then
+ To_Range'Result'Last = To_Domain (Map)'Last
+ and then
+ (for all J in To_Range'Result'Range =>
+ To_Range'Result (J) = Value (Map, To_Domain (Map) (J)));
type Character_Mapping_Function is
access function (From : Character) return Character;
diff --git a/gcc/ada/libgnat/a-stzhas.adb b/gcc/ada/libgnat/a-stzhas.adb
index 43abb80..c055de6 100644
--- a/gcc/ada/libgnat/a-stzhas.adb
+++ b/gcc/ada/libgnat/a-stzhas.adb
@@ -29,8 +29,14 @@
-- --
------------------------------------------------------------------------------
--- This package does not require a body, since it is an instantiation. We
--- provide a dummy file containing a No_Body pragma so that previous versions
--- of the body (which did exist) will not interfere.
+with System.String_Hash;
-pragma No_Body;
+function Ada.Strings.Wide_Wide_Hash
+ (Key : Wide_Wide_String) return Containers.Hash_Type
+is
+ use Ada.Containers;
+ function Hash_Fun is new System.String_Hash.Hash
+ (Wide_Wide_Character, Wide_Wide_String, Hash_Type);
+begin
+ return Hash_Fun (Key);
+end Ada.Strings.Wide_Wide_Hash;
diff --git a/gcc/ada/libgnat/a-stzhas.ads b/gcc/ada/libgnat/a-stzhas.ads
index 0c87672..dea0ff1 100644
--- a/gcc/ada/libgnat/a-stzhas.ads
+++ b/gcc/ada/libgnat/a-stzhas.ads
@@ -13,13 +13,9 @@
-- --
------------------------------------------------------------------------------
--- Is this really an RM unit? Doc needed???
-
with Ada.Containers;
-with System.String_Hash;
function Ada.Strings.Wide_Wide_Hash
-is new System.String_Hash.Hash
- (Wide_Wide_Character, Wide_Wide_String, Containers.Hash_Type);
+ (Key : Wide_Wide_String) return Containers.Hash_Type;
pragma Pure (Ada.Strings.Wide_Wide_Hash);
diff --git a/gcc/ada/libgnat/a-tags.adb b/gcc/ada/libgnat/a-tags.adb
index 798780a..7138f76 100644
--- a/gcc/ada/libgnat/a-tags.adb
+++ b/gcc/ada/libgnat/a-tags.adb
@@ -30,7 +30,6 @@
------------------------------------------------------------------------------
with Ada.Exceptions;
-with Ada.Unchecked_Conversion;
with System.HTable;
with System.Storage_Elements; use System.Storage_Elements;
@@ -96,12 +95,6 @@ package body Ada.Tags is
function To_Tag is
new Unchecked_Conversion (Integer_Address, Tag);
- function To_Addr_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Addr_Ptr);
-
- function To_Address is
- new Ada.Unchecked_Conversion (Tag, System.Address);
-
function To_Dispatch_Table_Ptr is
new Ada.Unchecked_Conversion (Tag, Dispatch_Table_Ptr);
@@ -114,9 +107,6 @@ package body Ada.Tags is
function To_Tag_Ptr is
new Ada.Unchecked_Conversion (System.Address, Tag_Ptr);
- function To_Type_Specific_Data_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr);
-
-------------------------------
-- Inline_Always Subprograms --
-------------------------------
@@ -125,40 +115,6 @@ package body Ada.Tags is
-- avoid defeating the frontend inlining mechanism and thus ensure the
-- generation of their correct debug info.
- -------------------
- -- CW_Membership --
- -------------------
-
- -- Canonical implementation of Classwide Membership corresponding to:
-
- -- Obj in Typ'Class
-
- -- Each dispatch table contains a reference to a table of ancestors (stored
- -- in the first part of the Tags_Table) and a count of the level of
- -- inheritance "Idepth".
-
- -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
- -- contained in the dispatch table referenced by Obj'Tag . Knowing the
- -- level of inheritance of both types, this can be computed in constant
- -- time by the formula:
-
- -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth)
- -- = Typ'tag
-
- function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is
- Obj_TSD_Ptr : constant Addr_Ptr :=
- To_Addr_Ptr (To_Address (Obj_Tag) - DT_Typeinfo_Ptr_Size);
- Typ_TSD_Ptr : constant Addr_Ptr :=
- To_Addr_Ptr (To_Address (Typ_Tag) - DT_Typeinfo_Ptr_Size);
- Obj_TSD : constant Type_Specific_Data_Ptr :=
- To_Type_Specific_Data_Ptr (Obj_TSD_Ptr.all);
- Typ_TSD : constant Type_Specific_Data_Ptr :=
- To_Type_Specific_Data_Ptr (Typ_TSD_Ptr.all);
- Pos : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth;
- begin
- return Pos >= 0 and then Obj_TSD.Tags_Table (Pos) = Typ_Tag;
- end CW_Membership;
-
----------------------
-- Get_External_Tag --
----------------------
diff --git a/gcc/ada/libgnat/a-tags.ads b/gcc/ada/libgnat/a-tags.ads
index fb386c3..203f7ca 100644
--- a/gcc/ada/libgnat/a-tags.ads
+++ b/gcc/ada/libgnat/a-tags.ads
@@ -65,6 +65,7 @@
-- length depends on the number of interfaces covered by a tagged type.
with System.Storage_Elements;
+with Ada.Unchecked_Conversion;
package Ada.Tags is
pragma Preelaborate;
@@ -501,10 +502,6 @@ private
-- dispatch table, return the tagged kind of a type in the context of
-- concurrency and limitedness.
- function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean;
- -- Given the tag of an object and the tag associated to a type, return
- -- true if Obj is in Typ'Class.
-
function IW_Membership (This : System.Address; T : Tag) return Boolean;
-- Ada 2005 (AI-251): General routine that checks if a given object
-- implements a tagged type. Its common usage is to check if Obj is in
@@ -623,4 +620,49 @@ private
-- This type is used by the frontend to generate the code that handles
-- dispatch table slots of types declared at the local level.
+ -------------------
+ -- CW_Membership --
+ -------------------
+
+ function To_Address is
+ new Ada.Unchecked_Conversion (Tag, System.Address);
+
+ function To_Addr_Ptr is
+ new Ada.Unchecked_Conversion (System.Address, Addr_Ptr);
+
+ function To_Type_Specific_Data_Ptr is
+ new Ada.Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr);
+
+ -- Canonical implementation of Classwide Membership corresponding to:
+
+ -- Obj in Typ'Class
+
+ -- Each dispatch table contains a reference to a table of ancestors (stored
+ -- in the first part of the Tags_Table) and a count of the level of
+ -- inheritance "Idepth".
+
+ -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
+ -- contained in the dispatch table referenced by Obj'Tag . Knowing the
+ -- level of inheritance of both types, this can be computed in constant
+ -- time by the formula:
+
+ -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth)
+ -- = Typ'tag
+
+ function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is
+ (declare
+ Obj_TSD_Ptr : constant Addr_Ptr :=
+ To_Addr_Ptr (To_Address (Obj_Tag) - DT_Typeinfo_Ptr_Size);
+ Typ_TSD_Ptr : constant Addr_Ptr :=
+ To_Addr_Ptr (To_Address (Typ_Tag) - DT_Typeinfo_Ptr_Size);
+ Obj_TSD : constant Type_Specific_Data_Ptr :=
+ To_Type_Specific_Data_Ptr (Obj_TSD_Ptr.all);
+ Typ_TSD : constant Type_Specific_Data_Ptr :=
+ To_Type_Specific_Data_Ptr (Typ_TSD_Ptr.all);
+ Pos : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth;
+ begin
+ Pos >= 0 and then Obj_TSD.Tags_Table (Pos) = Typ_Tag);
+ -- Given the tag of an object and the tag associated to a type, return
+ -- true if Obj is in Typ'Class.
+
end Ada.Tags;
diff --git a/gcc/ada/libgnat/a-ticoau.adb b/gcc/ada/libgnat/a-ticoau.adb
index e4f56dd..cf94305 100644
--- a/gcc/ada/libgnat/a-ticoau.adb
+++ b/gcc/ada/libgnat/a-ticoau.adb
@@ -30,22 +30,19 @@
------------------------------------------------------------------------------
with Ada.Text_IO.Generic_Aux; use Ada.Text_IO.Generic_Aux;
-with Ada.Text_IO.Float_Aux;
with System.Img_Real; use System.Img_Real;
package body Ada.Text_IO.Complex_Aux is
- package Aux renames Ada.Text_IO.Float_Aux;
-
---------
-- Get --
---------
procedure Get
(File : File_Type;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Width : Field)
is
Buf : String (1 .. Field'Last);
@@ -95,8 +92,8 @@ package body Ada.Text_IO.Complex_Aux is
procedure Gets
(From : String;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Last : out Positive)
is
Paren : Boolean;
@@ -139,8 +136,8 @@ package body Ada.Text_IO.Complex_Aux is
procedure Put
(File : File_Type;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Fore : Field;
Aft : Field;
Exp : Field)
@@ -159,8 +156,8 @@ package body Ada.Text_IO.Complex_Aux is
procedure Puts
(To : out String;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Aft : Field;
Exp : Field)
is
@@ -174,9 +171,9 @@ package body Ada.Text_IO.Complex_Aux is
-- Both parts are initially converted with a Fore of 0
Rptr := 0;
- Set_Image_Real (ItemR, R_String, Rptr, 0, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (ItemR), R_String, Rptr, 0, Aft, Exp);
Iptr := 0;
- Set_Image_Real (ItemI, I_String, Iptr, 0, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (ItemI), I_String, Iptr, 0, Aft, Exp);
-- Check room for both parts plus parens plus comma (RM G.1.3(34))
diff --git a/gcc/ada/libgnat/a-ticoau.ads b/gcc/ada/libgnat/a-ticoau.ads
index 739dce8..22555cf 100644
--- a/gcc/ada/libgnat/a-ticoau.ads
+++ b/gcc/ada/libgnat/a-ticoau.ads
@@ -30,39 +30,46 @@
------------------------------------------------------------------------------
-- This package contains the routines for Ada.Text_IO.Complex_IO that are
--- shared among separate instantiations of this package. The routines in
--- this package are identical semantically to those in Complex_IO itself,
--- except that the generic parameter Complex has been replaced by separate
--- real and imaginary values of type Long_Long_Float, and default parameters
--- have been removed because they are supplied explicitly by the calls from
--- within the generic template.
+-- shared among separate instantiations of this package. The routines in this
+-- package are identical semantically to those in Complex_IO, except that the
+-- generic parameter Complex has been replaced by separate real and imaginary
+-- parameters, and default parameters have been removed because they are
+-- supplied explicitly by the calls from within the generic template.
+
+with Ada.Text_IO.Float_Aux;
+
+private generic
+
+ type Num is digits <>;
+
+ with package Aux is new Ada.Text_IO.Float_Aux (Num, <>);
package Ada.Text_IO.Complex_Aux is
procedure Get
(File : File_Type;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Width : Field);
procedure Put
(File : File_Type;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Fore : Field;
Aft : Field;
Exp : Field);
procedure Gets
(From : String;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Last : out Positive);
procedure Puts
(To : out String;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Aft : Field;
Exp : Field);
diff --git a/gcc/ada/libgnat/a-ticoio.adb b/gcc/ada/libgnat/a-ticoio.adb
index fa52b60..e35a745 100644
--- a/gcc/ada/libgnat/a-ticoio.adb
+++ b/gcc/ada/libgnat/a-ticoio.adb
@@ -29,18 +29,42 @@
-- --
------------------------------------------------------------------------------
-with Ada.Text_IO;
-
with Ada.Text_IO.Complex_Aux;
+with Ada.Text_IO.Float_Aux;
+with System.Val_Flt; use System.Val_Flt;
+with System.Val_LFlt; use System.Val_LFlt;
+with System.Val_LLF; use System.Val_LLF;
package body Ada.Text_IO.Complex_IO is
use Complex_Types;
- package Aux renames Ada.Text_IO.Complex_Aux;
+ package Scalar_Float is new
+ Ada.Text_IO.Float_Aux (Float, Scan_Float);
+
+ package Scalar_Long_Float is new
+ Ada.Text_IO.Float_Aux (Long_Float, Scan_Long_Float);
+
+ package Scalar_Long_Long_Float is new
+ Ada.Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ package Aux_Float is new
+ Ada.Text_IO.Complex_Aux (Float, Scalar_Float);
+
+ package Aux_Long_Float is new
+ Ada.Text_IO.Complex_Aux (Long_Float, Scalar_Long_Float);
- subtype LLF is Long_Long_Float;
- -- Type used for calls to routines in Aux
+ package Aux_Long_Long_Float is new
+ Ada.Text_IO.Complex_Aux (Long_Long_Float, Scalar_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Float is OK, where type Long_Float is OK and where type Long_Long_Float
+ -- is needed. These boolean constants are used to test for this, such that
+ -- only code for the relevant case is included in the instance.
+
+ OK_Float : constant Boolean := Real'Base'Digits <= Float'Digits;
+
+ OK_Long_Float : constant Boolean := Real'Base'Digits <= Long_Float'Digits;
---------
-- Get --
@@ -48,14 +72,24 @@ package body Ada.Text_IO.Complex_IO is
procedure Get
(File : File_Type;
- Item : out Complex_Types.Complex;
+ Item : out Complex;
Width : Field := 0)
is
Real_Item : Real'Base;
Imag_Item : Real'Base;
begin
- Aux.Get (File, LLF (Real_Item), LLF (Imag_Item), Width);
+ if OK_Float then
+ Aux_Float.Get (File, Float (Real_Item), Float (Imag_Item), Width);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Get
+ (File, Long_Float (Real_Item), Long_Float (Imag_Item), Width);
+ else
+ Aux_Long_Long_Float.Get
+ (File, Long_Long_Float (Real_Item), Long_Long_Float (Imag_Item),
+ Width);
+ end if;
+
Item := (Real_Item, Imag_Item);
exception
@@ -67,7 +101,7 @@ package body Ada.Text_IO.Complex_IO is
---------
procedure Get
- (Item : out Complex_Types.Complex;
+ (Item : out Complex;
Width : Field := 0)
is
begin
@@ -80,14 +114,24 @@ package body Ada.Text_IO.Complex_IO is
procedure Get
(From : String;
- Item : out Complex_Types.Complex;
+ Item : out Complex;
Last : out Positive)
is
Real_Item : Real'Base;
Imag_Item : Real'Base;
begin
- Aux.Gets (From, LLF (Real_Item), LLF (Imag_Item), Last);
+ if OK_Float then
+ Aux_Float.Gets (From, Float (Real_Item), Float (Imag_Item), Last);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Gets
+ (From, Long_Float (Real_Item), Long_Float (Imag_Item), Last);
+ else
+ Aux_Long_Long_Float.Gets
+ (From, Long_Long_Float (Real_Item), Long_Long_Float (Imag_Item),
+ Last);
+ end if;
+
Item := (Real_Item, Imag_Item);
exception
@@ -100,13 +144,24 @@ package body Ada.Text_IO.Complex_IO is
procedure Put
(File : File_Type;
- Item : Complex_Types.Complex;
+ Item : Complex;
Fore : Field := Default_Fore;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp)
is
begin
- Aux.Put (File, LLF (Re (Item)), LLF (Im (Item)), Fore, Aft, Exp);
+ if OK_Float then
+ Aux_Float.Put
+ (File, Float (Re (Item)), Float (Im (Item)), Fore, Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Put
+ (File, Long_Float (Re (Item)), Long_Float (Im (Item)), Fore, Aft,
+ Exp);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Re (Item)), Long_Long_Float (Im (Item)),
+ Fore, Aft, Exp);
+ end if;
end Put;
---------
@@ -114,7 +169,7 @@ package body Ada.Text_IO.Complex_IO is
---------
procedure Put
- (Item : Complex_Types.Complex;
+ (Item : Complex;
Fore : Field := Default_Fore;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp)
@@ -129,12 +184,21 @@ package body Ada.Text_IO.Complex_IO is
procedure Put
(To : out String;
- Item : Complex_Types.Complex;
+ Item : Complex;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp)
is
begin
- Aux.Puts (To, LLF (Re (Item)), LLF (Im (Item)), Aft, Exp);
+ if OK_Float then
+ Aux_Float.Puts (To, Float (Re (Item)), Float (Im (Item)), Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Puts
+ (To, Long_Float (Re (Item)), Long_Float (Im (Item)), Aft, Exp);
+ else
+ Aux_Long_Long_Float.Puts
+ (To, Long_Long_Float (Re (Item)), Long_Long_Float (Im (Item)),
+ Aft, Exp);
+ end if;
end Put;
end Ada.Text_IO.Complex_IO;
diff --git a/gcc/ada/libgnat/a-tideau.adb b/gcc/ada/libgnat/a-tideau.adb
index caf77e3..ac751c1 100644
--- a/gcc/ada/libgnat/a-tideau.adb
+++ b/gcc/ada/libgnat/a-tideau.adb
@@ -30,28 +30,22 @@
------------------------------------------------------------------------------
with Ada.Text_IO.Generic_Aux; use Ada.Text_IO.Generic_Aux;
-with Ada.Text_IO.Float_Aux; use Ada.Text_IO.Float_Aux;
-
-with System.Img_Dec; use System.Img_Dec;
-with System.Img_LLD; use System.Img_LLD;
-with System.Val_Dec; use System.Val_Dec;
-with System.Val_LLD; use System.Val_LLD;
package body Ada.Text_IO.Decimal_Aux is
- -------------
- -- Get_Dec --
- -------------
+ ---------
+ -- Get --
+ ---------
- function Get_Dec
+ function Get
(File : File_Type;
Width : Field;
- Scale : Integer) return Integer
+ Scale : Integer) return Int
is
Buf : String (1 .. Field'Last);
Ptr : aliased Integer;
Stop : Integer := 0;
- Item : Integer;
+ Item : Int;
begin
if Width /= 0 then
@@ -62,114 +56,42 @@ package body Ada.Text_IO.Decimal_Aux is
Ptr := 1;
end if;
- Item := Scan_Decimal (Buf, Ptr'Access, Stop, Scale);
+ Item := Scan (Buf, Ptr'Access, Stop, Scale);
Check_End_Of_Field (Buf, Stop, Ptr, Width);
return Item;
- end Get_Dec;
-
- -------------
- -- Get_LLD --
- -------------
-
- function Get_LLD
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Long_Long_Integer
- is
- Buf : String (1 .. Field'Last);
- Ptr : aliased Integer;
- Stop : Integer := 0;
- Item : Long_Long_Integer;
+ end Get;
- begin
- if Width /= 0 then
- Load_Width (File, Width, Buf, Stop);
- String_Skip (Buf, Ptr);
- else
- Load_Real (File, Buf, Stop);
- Ptr := 1;
- end if;
+ ----------
+ -- Gets --
+ ----------
- Item := Scan_Long_Long_Decimal (Buf, Ptr'Access, Stop, Scale);
- Check_End_Of_Field (Buf, Stop, Ptr, Width);
- return Item;
- end Get_LLD;
-
- --------------
- -- Gets_Dec --
- --------------
-
- function Gets_Dec
+ function Gets
(From : String;
- Last : not null access Positive;
- Scale : Integer) return Integer
+ Last : out Positive;
+ Scale : Integer) return Int
is
Pos : aliased Integer;
- Item : Integer;
+ Item : Int;
begin
String_Skip (From, Pos);
- Item := Scan_Decimal (From, Pos'Access, From'Last, Scale);
- Last.all := Pos - 1;
+ Item := Scan (From, Pos'Access, From'Last, Scale);
+ Last := Pos - 1;
return Item;
exception
when Constraint_Error =>
- Last.all := Pos - 1;
+ Last := Pos - 1;
raise Data_Error;
- end Gets_Dec;
-
- --------------
- -- Gets_LLD --
- --------------
-
- function Gets_LLD
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Long_Long_Integer
- is
- Pos : aliased Integer;
- Item : Long_Long_Integer;
-
- begin
- String_Skip (From, Pos);
- Item := Scan_Long_Long_Decimal (From, Pos'Access, From'Last, Scale);
- Last.all := Pos - 1;
- return Item;
-
- exception
- when Constraint_Error =>
- Last.all := Pos - 1;
- raise Data_Error;
- end Gets_LLD;
-
- -------------
- -- Put_Dec --
- -------------
+ end Gets;
- procedure Put_Dec
- (File : File_Type;
- Item : Integer;
- Fore : Field;
- Aft : Field;
- Exp : Field;
- Scale : Integer)
- is
- Buf : String (1 .. Field'Last);
- Ptr : Natural := 0;
-
- begin
- Set_Image_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
- Put_Item (File, Buf (1 .. Ptr));
- end Put_Dec;
-
- -------------
- -- Put_LLD --
- -------------
+ ---------
+ -- Put --
+ ---------
- procedure Put_LLD
+ procedure Put
(File : File_Type;
- Item : Long_Long_Integer;
+ Item : Int;
Fore : Field;
Aft : Field;
Exp : Field;
@@ -179,83 +101,51 @@ package body Ada.Text_IO.Decimal_Aux is
Ptr : Natural := 0;
begin
- Set_Image_Long_Long_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
+ Set_Image (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
Put_Item (File, Buf (1 .. Ptr));
- end Put_LLD;
+ end Put;
- --------------
- -- Puts_Dec --
- --------------
+ ----------
+ -- Puts --
+ ----------
- procedure Puts_Dec
+ procedure Puts
(To : out String;
- Item : Integer;
+ Item : Int;
Aft : Field;
Exp : Field;
Scale : Integer)
is
- Buf : String (1 .. Field'Last);
+ Buf : String (1 .. Positive'Max (Field'Last, To'Length));
Fore : Integer;
Ptr : Natural := 0;
begin
- -- Compute Fore, allowing for Aft digits and the decimal dot
+ -- Compute Fore, allowing for the decimal dot and Aft digits
- Fore := To'Length - Field'Max (1, Aft) - 1;
+ Fore := To'Length - 1 - Field'Max (1, Aft);
- -- Allow for Exp and two more for E+ or E- if exponent present
+ -- Allow for Exp and one more for E if exponent present
if Exp /= 0 then
- Fore := Fore - 2 - Exp;
+ Fore := Fore - 1 - Field'Max (2, Exp);
end if;
-- Make sure we have enough room
- if Fore < 1 then
+ if Fore < 1 + Boolean'Pos (Item < 0) then
raise Layout_Error;
end if;
-- Do the conversion and check length of result
- Set_Image_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
-
- if Ptr > To'Length then
- raise Layout_Error;
- else
- To := Buf (1 .. Ptr);
- end if;
- end Puts_Dec;
-
- --------------
- -- Puts_LLD --
- --------------
-
- procedure Puts_LLD
- (To : out String;
- Item : Long_Long_Integer;
- Aft : Field;
- Exp : Field;
- Scale : Integer)
- is
- Buf : String (1 .. Field'Last);
- Fore : Integer;
- Ptr : Natural := 0;
-
- begin
- Fore :=
- (if Exp = 0 then To'Length - 1 - Aft else To'Length - 2 - Aft - Exp);
-
- if Fore < 1 then
- raise Layout_Error;
- end if;
-
- Set_Image_Long_Long_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
+ Set_Image (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
if Ptr > To'Length then
raise Layout_Error;
else
To := Buf (1 .. Ptr);
end if;
- end Puts_LLD;
+ end Puts;
end Ada.Text_IO.Decimal_Aux;
diff --git a/gcc/ada/libgnat/a-tideau.ads b/gcc/ada/libgnat/a-tideau.ads
index e7d7f44..522e351 100644
--- a/gcc/ada/libgnat/a-tideau.ads
+++ b/gcc/ada/libgnat/a-tideau.ads
@@ -29,62 +29,54 @@
-- --
------------------------------------------------------------------------------
--- This package contains the routines for Ada.Text_IO.Decimal_IO that are
--- shared among separate instantiations of this package. The routines in
--- the package are identical semantically to those declared in Text_IO,
--- except that default values have been supplied by the generic, and the
--- Num parameter has been replaced by Integer or Long_Long_Integer, with
--- an additional Scale parameter giving the value of Num'Scale. In addition
--- the Get routines return the value rather than store it in an Out parameter.
+-- This package contains the implementation for Ada.Text_IO.Decimal_IO. The
+-- routines in this package are identical semantically to those in Decimal_IO,
+-- except that the default parameters have been removed because they are
+-- supplied explicitly by the calls from within these units, and there is an
+-- additional Scale parameter giving the value of Num'Scale. In addition the
+-- Get routines return the value rather than store it in an Out parameter.
-private package Ada.Text_IO.Decimal_Aux is
+private generic
+ type Int is range <>;
- function Get_Dec
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Integer;
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int;
- function Get_LLD
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Long_Long_Integer;
+ with procedure Set_Image
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+
+package Ada.Text_IO.Decimal_Aux is
- procedure Put_Dec
+ function Get
(File : File_Type;
- Item : Integer;
- Fore : Field;
- Aft : Field;
- Exp : Field;
- Scale : Integer);
+ Width : Field;
+ Scale : Integer) return Int;
- procedure Put_LLD
+ procedure Put
(File : File_Type;
- Item : Long_Long_Integer;
+ Item : Int;
Fore : Field;
Aft : Field;
Exp : Field;
Scale : Integer);
- function Gets_Dec
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Integer;
-
- function Gets_LLD
+ function Gets
(From : String;
- Last : not null access Positive;
- Scale : Integer) return Long_Long_Integer;
-
- procedure Puts_Dec
- (To : out String;
- Item : Integer;
- Aft : Field;
- Exp : Field;
- Scale : Integer);
+ Last : out Positive;
+ Scale : Integer) return Int;
- procedure Puts_LLD
+ procedure Puts
(To : out String;
- Item : Long_Long_Integer;
+ Item : Int;
Aft : Field;
Exp : Field;
Scale : Integer);
diff --git a/gcc/ada/libgnat/a-tideio.adb b/gcc/ada/libgnat/a-tideio.adb
index 0624c2c..f71cf2d 100644
--- a/gcc/ada/libgnat/a-tideio.adb
+++ b/gcc/ada/libgnat/a-tideio.adb
@@ -29,11 +29,35 @@
-- --
------------------------------------------------------------------------------
+with Interfaces;
with Ada.Text_IO.Decimal_Aux;
+with System.Img_Decimal_32; use System.Img_Decimal_32;
+with System.Img_Decimal_64; use System.Img_Decimal_64;
+with System.Val_Decimal_32; use System.Val_Decimal_32;
+with System.Val_Decimal_64; use System.Val_Decimal_64;
package body Ada.Text_IO.Decimal_IO is
- package Aux renames Ada.Text_IO.Decimal_Aux;
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Aux32 is new
+ Ada.Text_IO.Decimal_Aux
+ (Int32,
+ Scan_Decimal32,
+ Set_Image_Decimal32);
+
+ package Aux64 is new
+ Ada.Text_IO.Decimal_Aux
+ (Int64,
+ Scan_Decimal64,
+ Set_Image_Decimal64);
+
+ Need64 : constant Boolean := Num'Size > 32;
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is acceptable and where type Int64 is needed. This Boolean is used
+ -- to test for these cases and since it is a constant, only code for the
+ -- relevant case will be included in the instance.
Scale : constant Integer := Num'Scale;
@@ -49,10 +73,10 @@ package body Ada.Text_IO.Decimal_IO is
pragma Unsuppress (Range_Check);
begin
- if Num'Size > Integer'Size then
- Item := Num'Fixed_Value (Aux.Get_LLD (File, Width, Scale));
+ if Need64 then
+ Item := Num'Fixed_Value (Aux64.Get (File, Width, Scale));
else
- Item := Num'Fixed_Value (Aux.Get_Dec (File, Width, Scale));
+ Item := Num'Fixed_Value (Aux32.Get (File, Width, Scale));
end if;
exception
@@ -75,12 +99,10 @@ package body Ada.Text_IO.Decimal_IO is
pragma Unsuppress (Range_Check);
begin
- if Num'Size > Integer'Size then
- Item := Num'Fixed_Value
- (Aux.Gets_LLD (From, Last'Unrestricted_Access, Scale));
+ if Need64 then
+ Item := Num'Fixed_Value (Aux64.Gets (From, Last, Scale));
else
- Item := Num'Fixed_Value
- (Aux.Gets_Dec (From, Last'Unrestricted_Access, Scale));
+ Item := Num'Fixed_Value (Aux32.Gets (From, Last, Scale));
end if;
exception
@@ -99,13 +121,12 @@ package body Ada.Text_IO.Decimal_IO is
Exp : Field := Default_Exp)
is
begin
- if Num'Size > Integer'Size then
- Aux.Put_LLD
- (File, Long_Long_Integer'Integer_Value (Item),
- Fore, Aft, Exp, Scale);
+ if Need64 then
+ Aux64.Put
+ (File, Int64'Integer_Value (Item), Fore, Aft, Exp, Scale);
else
- Aux.Put_Dec
- (File, Integer'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ Aux32.Put
+ (File, Int32'Integer_Value (Item), Fore, Aft, Exp, Scale);
end if;
end Put;
@@ -126,11 +147,10 @@ package body Ada.Text_IO.Decimal_IO is
Exp : Field := Default_Exp)
is
begin
- if Num'Size > Integer'Size then
- Aux.Puts_LLD
- (To, Long_Long_Integer'Integer_Value (Item), Aft, Exp, Scale);
+ if Need64 then
+ Aux64.Puts (To, Int64'Integer_Value (Item), Aft, Exp, Scale);
else
- Aux.Puts_Dec (To, Integer'Integer_Value (Item), Aft, Exp, Scale);
+ Aux32.Puts (To, Int32'Integer_Value (Item), Aft, Exp, Scale);
end if;
end Put;
diff --git a/gcc/ada/libgnat/a-tideio__128.adb b/gcc/ada/libgnat/a-tideio__128.adb
new file mode 100644
index 0000000..a8cdf9f
--- /dev/null
+++ b/gcc/ada/libgnat/a-tideio__128.adb
@@ -0,0 +1,177 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . T E X T _ I O . D E C I M A L _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Interfaces;
+with Ada.Text_IO.Decimal_Aux;
+with System.Img_Decimal_32; use System.Img_Decimal_32;
+with System.Img_Decimal_64; use System.Img_Decimal_64;
+with System.Img_Decimal_128; use System.Img_Decimal_128;
+with System.Val_Decimal_32; use System.Val_Decimal_32;
+with System.Val_Decimal_64; use System.Val_Decimal_64;
+with System.Val_Decimal_128; use System.Val_Decimal_128;
+
+package body Ada.Text_IO.Decimal_IO is
+
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Int64 is Interfaces.Integer_64;
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Aux32 is new
+ Ada.Text_IO.Decimal_Aux
+ (Int32,
+ Scan_Decimal32,
+ Set_Image_Decimal32);
+
+ package Aux64 is new
+ Ada.Text_IO.Decimal_Aux
+ (Int64,
+ Scan_Decimal64,
+ Set_Image_Decimal64);
+
+ package Aux128 is new
+ Ada.Text_IO.Decimal_Aux
+ (Int128,
+ Scan_Decimal128,
+ Set_Image_Decimal128);
+
+ Need64 : constant Boolean := Num'Size > 32;
+ Need128 : constant Boolean := Num'Size > 64;
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is acceptable, where type Int64 is acceptable and where an Int128
+ -- is needed. These boolean constants are used to test for these cases and
+ -- since it is a constant, only code for the relevant case will be included
+ -- in the instance.
+
+ Scale : constant Integer := Num'Scale;
+
+ ---------
+ -- Get --
+ ---------
+
+ procedure Get
+ (File : File_Type;
+ Item : out Num;
+ Width : Field := 0)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if Need128 then
+ Item := Num'Fixed_Value (Aux128.Get (File, Width, Scale));
+ elsif Need64 then
+ Item := Num'Fixed_Value (Aux64.Get (File, Width, Scale));
+ else
+ Item := Num'Fixed_Value (Aux32.Get (File, Width, Scale));
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ procedure Get
+ (Item : out Num;
+ Width : Field := 0)
+ is
+ begin
+ Get (Current_In, Item, Width);
+ end Get;
+
+ procedure Get
+ (From : String;
+ Item : out Num;
+ Last : out Positive)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if Need128 then
+ Item := Num'Fixed_Value (Aux128.Gets (From, Last, Scale));
+ elsif Need64 then
+ Item := Num'Fixed_Value (Aux64.Gets (From, Last, Scale));
+ else
+ Item := Num'Fixed_Value (Aux32.Gets (From, Last, Scale));
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if Need128 then
+ Aux128.Put
+ (File, Int128'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ elsif Need64 then
+ Aux64.Put
+ (File, Int64'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ else
+ Aux32.Put
+ (File, Int32'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ end if;
+ end Put;
+
+ procedure Put
+ (Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ Put (Current_Out, Item, Fore, Aft, Exp);
+ end Put;
+
+ procedure Put
+ (To : out String;
+ Item : Num;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if Need128 then
+ Aux128.Puts (To, Int128'Integer_Value (Item), Aft, Exp, Scale);
+ elsif Need64 then
+ Aux64.Puts (To, Int64'Integer_Value (Item), Aft, Exp, Scale);
+ else
+ Aux32.Puts (To, Int32'Integer_Value (Item), Aft, Exp, Scale);
+ end if;
+ end Put;
+
+end Ada.Text_IO.Decimal_IO;
diff --git a/gcc/ada/libgnat/a-tifiau.adb b/gcc/ada/libgnat/a-tifiau.adb
new file mode 100644
index 0000000..c6f4430
--- /dev/null
+++ b/gcc/ada/libgnat/a-tifiau.adb
@@ -0,0 +1,159 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . T E X T _ I O . F I X E D _ A U X --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Text_IO.Generic_Aux; use Ada.Text_IO.Generic_Aux;
+
+package body Ada.Text_IO.Fixed_Aux is
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get
+ (File : File_Type;
+ Width : Field;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Buf : String (1 .. Field'Last);
+ Ptr : aliased Integer;
+ Stop : Integer := 0;
+ Item : Int;
+
+ begin
+ if Width /= 0 then
+ Load_Width (File, Width, Buf, Stop);
+ String_Skip (Buf, Ptr);
+ else
+ Load_Real (File, Buf, Stop);
+ Ptr := 1;
+ end if;
+
+ Item := Scan (Buf, Ptr'Access, Stop, Num, Den);
+ Check_End_Of_Field (Buf, Stop, Ptr, Width);
+ return Item;
+ end Get;
+
+ ----------
+ -- Gets --
+ ----------
+
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Pos : aliased Integer;
+ Item : Int;
+
+ begin
+ String_Skip (From, Pos);
+ Item := Scan (From, Pos'Access, From'Last, Num, Den);
+ Last := Pos - 1;
+ return Item;
+
+ exception
+ when Constraint_Error =>
+ Last := Pos - 1;
+ raise Data_Error;
+ end Gets;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Int;
+ Fore : Field;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ Buf : String (1 .. Field'Last);
+ Ptr : Natural := 0;
+
+ begin
+ Set_Image (Item, Buf, Ptr, Num, Den, For0, Aft0, Fore, Aft, Exp);
+ Put_Item (File, Buf (1 .. Ptr));
+ end Put;
+
+ ----------
+ -- Puts --
+ ----------
+
+ procedure Puts
+ (To : out String;
+ Item : Int;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ Buf : String (1 .. Positive'Max (Field'Last, To'Length));
+ Fore : Integer;
+ Ptr : Natural := 0;
+
+ begin
+ -- Compute Fore, allowing for the decimal dot and Aft digits
+
+ Fore := To'Length - 1 - Field'Max (1, Aft);
+
+ -- Allow for Exp and one more for E if exponent present
+
+ if Exp /= 0 then
+ Fore := Fore - 1 - Field'Max (2, Exp);
+ end if;
+
+ -- Make sure we have enough room
+
+ if Fore < 1 + Boolean'Pos (Item < 0) then
+ raise Layout_Error;
+ end if;
+
+ -- Do the conversion and check length of result
+
+ Set_Image (Item, Buf, Ptr, Num, Den, For0, Aft0, Fore, Aft, Exp);
+
+ if Ptr > To'Length then
+ raise Layout_Error;
+ else
+ To := Buf (1 .. Ptr);
+ end if;
+ end Puts;
+
+end Ada.Text_IO.Fixed_Aux;
diff --git a/gcc/ada/libgnat/a-tifiau.ads b/gcc/ada/libgnat/a-tifiau.ads
new file mode 100644
index 0000000..32701c5
--- /dev/null
+++ b/gcc/ada/libgnat/a-tifiau.ads
@@ -0,0 +1,97 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . T E X T _ I O . F I X E D _ A U X --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the implementation for Ada.Text_IO.Fixed_IO. The
+-- routines in this package are identical semantically to those in Fixed_IO,
+-- except that the default parameters have been removed because they are
+-- supplied explicitly by the calls from within these units, and there are
+-- additional Num and Den parameters giving the value of Num'Small, as well
+-- as For0 and Aft0 giving some properties of Num'Small. In addition the Get
+-- routines return the value rather than store it in an Out parameter.
+
+private generic
+ type Int is range <>;
+
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int;
+ Den : Int) return Int;
+
+ with procedure Set_Image
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+
+package Ada.Text_IO.Fixed_Aux is
+
+ function Get
+ (File : File_Type;
+ Width : Field;
+ Num : Int;
+ Den : Int) return Int;
+
+ procedure Put
+ (File : File_Type;
+ Item : Int;
+ Fore : Field;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Num : Int;
+ Den : Int) return Int;
+
+ procedure Puts
+ (To : out String;
+ Item : Int;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+
+end Ada.Text_IO.Fixed_Aux;
diff --git a/gcc/ada/libgnat/a-tifiio.adb b/gcc/ada/libgnat/a-tifiio.adb
index 440a77d..412740e 100644
--- a/gcc/ada/libgnat/a-tifiio.adb
+++ b/gcc/ada/libgnat/a-tifiio.adb
@@ -29,18 +29,19 @@
-- --
------------------------------------------------------------------------------
--- Fixed point I/O
--- ---------------
+-- -------------------
+-- - Fixed point I/O -
+-- -------------------
--- The following documents implementation details of the fixed point
--- input/output routines in the GNAT run time. The first part describes
--- general properties of fixed point types as defined by the Ada 95 standard,
+-- The following text documents implementation details of the fixed point
+-- input/output routines in the GNAT runtime. The first part describes the
+-- general properties of fixed point types as defined by the Ada standard,
-- including the Information Systems Annex.
-- Subsequently these are reduced to implementation constraints and the impact
--- of these constraints on a few possible approaches to I/O are given.
+-- of these constraints on a few possible approaches to input/output is given.
-- Based on this analysis, a specific implementation is selected for use in
--- the GNAT run time. Finally, the chosen algorithm is analyzed numerically in
+-- the GNAT runtime. Finally the chosen algorithms are analyzed numerically in
-- order to provide user-level documentation on limits for range and precision
-- of fixed point types as well as accuracy of input/output conversions.
@@ -48,29 +49,27 @@
-- - General Properties of Fixed Point Types -
-- -------------------------------------------
--- Operations on fixed point values, other than input and output, are not
--- important for the purposes of this document. Only the set of values that a
--- fixed point type can represent and the input and output operations are
--- significant.
+-- Operations on fixed point types, other than input/output, are not important
+-- for the purpose of this document. Only the set of values that a fixed point
+-- type can represent and the input/output operations are significant.
-- Values
-- ------
--- Set set of values of a fixed point type comprise the integral
--- multiples of a number called the small of the type. The small can
--- either be a power of ten, a power of two or (if the implementation
--- allows) an arbitrary strictly positive real value.
+-- The set of values of a fixed point type comprise the integral multiples of
+-- a number called the small of the type. The small can be either a power of
+-- two, a power of ten or (if the implementation allows) an arbitrary strictly
+-- positive real value.
--- Implementations need to support fixed-point types with a precision
--- of at least 24 bits, and (in order to comply with the Information
--- Systems Annex) decimal types need to support at least digits 18.
--- For the rest, however, no requirements exist for the minimal small
--- and range that need to be supported.
+-- Implementations need to support ordinary fixed point types with a precision
+-- of at least 24 bits, and (in order to comply with the Information Systems
+-- Annex) decimal fixed point types with at least 18 digits. For the rest, no
+-- requirements exist for the minimal small and range that must be supported.
-- Operations
-- ----------
--- 'Image and 'Wide_Image (see RM 3.5(34))
+-- [Wide_[Wide_]]Image attribute (see RM 3.5(27.1/2))
-- These attributes return a decimal real literal best approximating
-- the value (rounded away from zero if halfway between) with a
@@ -90,7 +89,7 @@
-- attributes, although it would be nice to be able to output more
-- than S'Aft digits after the decimal point for values of subtype S.
--- 'Value and 'Wide_Value attribute (RM 3.5(40-55))
+-- [Wide_[Wide_]]Value attribute (RM 3.5(39.1/2))
-- Since the input can be given in any base in the range 2..16,
-- accurate conversion to a fixed point number may require
@@ -112,202 +111,154 @@
-- Implementation Strategies
-- -------------------------
--- * Float arithmetic
+-- * Floating point arithmetic
-- * Arbitrary-precision integer arithmetic
-- * Fixed-precision integer arithmetic
--- Although it seems convenient to convert fixed point numbers to floating-
+-- Although it seems convenient to convert fixed point numbers to floating
-- point and then print them, this leads to a number of restrictions.
-- The first one is precision. The widest floating-point type generally
-- available has 53 bits of mantissa. This means that Fine_Delta cannot
-- be less than 2.0**(-53).
--- In GNAT, Fine_Delta is 2.0**(-63), and Duration for example is a
--- 64-bit type. It would still be possible to use multi-precision
--- floating-point to perform calculations using longer mantissas,
--- but this is a much harder approach.
+-- In GNAT, Fine_Delta is 2.0**(-63), and Duration for example is a 64-bit
+-- type. This means that a floating-point type with 64 bits of mantissa needs
+-- to be used, which is only generally available on the x86 architecture. It
+-- would still be possible to use multi-precision floating point to perform
+-- calculations using longer mantissas, but this is a much harder approach.
--- The base conversions needed for input and output of (non-decimal)
--- fixed point types can be seen as pairs of integer multiplications
--- and divisions.
+-- The base conversions needed for input/output of (non-decimal) fixed point
+-- types can be seen as pairs of integer multiplications and divisions.
--- Arbitrary-precision integer arithmetic would be suitable for the job
--- at hand, but has the draw-back that it is very heavy implementation-wise.
+-- Arbitrary-precision integer arithmetic would be suitable for the job at
+-- hand, but has the drawback that it is very heavy implementation-wise.
-- Especially in embedded systems, where fixed point types are often used,
-- it may not be desirable to require large amounts of storage and time
-- for fixed I/O operations.
-- Fixed-precision integer arithmetic has the advantage of simplicity and
-- speed. For the most common fixed point types this would be a perfect
--- solution. The downside however may be a too limited set of acceptable
+-- solution. The downside however may be a restricted set of acceptable
-- fixed point types.
--- Extra Precision
--- ---------------
-
--- Using a scaled divide which truncates and returns a remainder R,
--- another E trailing digits can be calculated by computing the value
--- (R * (10.0**E)) / Z using another scaled divide. This procedure
--- can be repeated to compute an arbitrary number of digits in linear
--- time and storage. The last scaled divide should be rounded, with
--- a possible carry propagating to the more significant digits, to
--- ensure correct rounding of the unit in the last place.
-
--- An extension of this technique is to limit the value of Q to 9 decimal
--- digits, since 32-bit integers can be much more efficient than 64-bit
--- integers to output.
-
-with Interfaces; use Interfaces;
-with System.Arith_64; use System.Arith_64;
-with System.Img_Real; use System.Img_Real;
-with Ada.Text_IO; use Ada.Text_IO;
-with Ada.Text_IO.Float_Aux;
-with Ada.Text_IO.Generic_Aux;
-
-package body Ada.Text_IO.Fixed_IO is
-
- -- Note: we still use the floating-point I/O routines for input of
- -- ordinary fixed-point and output using exponent format. This will
- -- result in inaccuracies for fixed point types with a small that is
- -- not a power of two, and for types that require more precision than
- -- is available in Long_Long_Float.
-
- package Aux renames Ada.Text_IO.Float_Aux;
-
- Extra_Layout_Space : constant Field := 5 + Num'Fore;
- -- Extra space that may be needed for output of sign, decimal point,
- -- exponent indication and mandatory decimals after and before the
- -- decimal point. A string with length
-
- -- Fore + Aft + Exp + Extra_Layout_Space
-
- -- is always long enough for formatting any fixed point number
-
- -- Implementation of Put routines
-
- -- The following section describes a specific implementation choice for
- -- performing base conversions needed for output of values of a fixed
- -- point type T with small T'Small. The goal is to be able to output
- -- all values of types with a precision of 64 bits and a delta of at
- -- least 2.0**(-63), as these are current GNAT limitations already.
-
- -- The chosen algorithm uses fixed precision integer arithmetic for
- -- reasons of simplicity and efficiency. It is important to understand
- -- in what ways the most simple and accurate approach to fixed point I/O
- -- is limiting, before considering more complicated schemes.
-
- -- Without loss of generality assume T has a range (-2.0**63) * T'Small
- -- .. (2.0**63 - 1) * T'Small, and is output with Aft digits after the
- -- decimal point and T'Fore - 1 before. If T'Small is integer, or
- -- 1.0 / T'Small is integer, let S = T'Small and E = 0. For other T'Small,
- -- let S and E be integers such that S / 10**E best approximates T'Small
- -- and S is in the range 10**17 .. 10**18 - 1. The extra decimal scaling
- -- factor 10**E can be trivially handled during final output, by adjusting
- -- the decimal point or exponent.
-
- -- Convert a value X * S of type T to a 64-bit integer value Q equal
- -- to 10.0**D * (X * S) rounded to the nearest integer.
- -- This conversion is a scaled integer divide of the form
-
- -- Q := (X * Y) / Z,
-
- -- where all variables are 64-bit signed integers using 2's complement,
- -- and both the multiplication and division are done using full
- -- intermediate precision. The final decimal value to be output is
-
- -- Q * 10**(E-D)
-
- -- This value can be written to the output file or to the result string
- -- according to the format described in RM A.3.10. The details of this
- -- operation are omitted here.
-
- -- A 64-bit value can contain all integers with 18 decimal digits, but
- -- not all with 19 decimal digits. If the total number of requested output
- -- digits (Fore - 1) + Aft is greater than 18, for purposes of the
- -- conversion Aft is adjusted to 18 - (Fore - 1). In that case, or
- -- when Fore > 19, trailing zeros can complete the output after writing
- -- the first 18 significant digits, or the technique described in the
- -- next section can be used.
-
- -- The final expression for D is
-
- -- D := Integer'Max (-18, Integer'Min (Aft, 18 - (Fore - 1)));
-
- -- For Y and Z the following expressions can be derived:
-
- -- Q / (10.0**D) = X * S
-
- -- Q = X * S * (10.0**D) = (X * Y) / Z
-
- -- S * 10.0**D = Y / Z;
-
- -- If S is an integer greater than or equal to one, then Fore must be at
- -- least 20 in order to print T'First, which is at most -2.0**63.
- -- This means D < 0, so use
-
- -- (1) Y = -S and Z = -10**(-D)
-
- -- If 1.0 / S is an integer greater than one, use
-
- -- (2) Y = -10**D and Z = -(1.0 / S), for D >= 0
-
- -- or
-
- -- (3) Y = 1 and Z = (1.0 / S) * 10**(-D), for D < 0
-
- -- Negative values are used for nominator Y and denominator Z, so that S
- -- can have a maximum value of 2.0**63 and a minimum of 2.0**(-63).
- -- For Z in -1 .. -9, Fore will still be 20, and D will be negative, as
- -- (-2.0**63) / -9 is greater than 10**18. In these cases there is room
- -- in the denominator for the extra decimal scaling required, so case (3)
- -- will not overflow.
-
- pragma Assert (System.Fine_Delta >= 2.0**(-63));
- pragma Assert (Num'Small in 2.0**(-63) .. 2.0**63);
- pragma Assert (Num'Fore <= 37);
- -- These assertions need to be relaxed to allow for a Small of
- -- 2.0**(-64) at least, since there is an ACATS test for this ???
+-- Implementation Choices
+-- ----------------------
- Max_Digits : constant := 18;
- -- Maximum number of decimal digits that can be represented in a
- -- 64-bit signed number, see above
+-- The current implementation in the GNAT runtime uses fixed-precision integer
+-- arithmetic for fixed point types whose Small is the ratio of two integers
+-- whose magnitude is bounded relatively to the size of the mantissa, with a
+-- two-tiered approach for 32-bit and 64-bit fixed point types. For the other
+-- fixed point types, the implementation uses floating-point arithmetic.
- -- The constants E0 .. E5 implement a binary search for the appropriate
- -- power of ten to scale the small so that it has one digit before the
- -- decimal point.
+-- The exact requirements of the algorithms are analyzed and documented along
+-- with the implementation in their respective units.
- subtype Int is Integer;
- E0 : constant Int := -(20 * Boolean'Pos (Num'Small >= 1.0E1));
- E1 : constant Int := E0 + 10 * Boolean'Pos (Num'Small * 10.0**E0 < 1.0E-10);
- E2 : constant Int := E1 + 5 * Boolean'Pos (Num'Small * 10.0**E1 < 1.0E-5);
- E3 : constant Int := E2 + 3 * Boolean'Pos (Num'Small * 10.0**E2 < 1.0E-3);
- E4 : constant Int := E3 + 2 * Boolean'Pos (Num'Small * 10.0**E3 < 1.0E-1);
- E5 : constant Int := E4 + 1 * Boolean'Pos (Num'Small * 10.0**E4 < 1.0E-0);
-
- Scale : constant Integer := E5;
-
- pragma Assert (Num'Small * 10.0**Scale >= 1.0
- and then Num'Small * 10.0**Scale < 10.0);
-
- Exact : constant Boolean :=
- Float'Floor (Num'Small) = Float'Ceiling (Num'Small)
- or else Float'Floor (1.0 / Num'Small) = Float'Ceiling (1.0 / Num'Small)
- or else Num'Small >= 10.0**Max_Digits;
- -- True iff a numerator and denominator can be calculated such that
- -- their ratio exactly represents the small of Num.
-
- procedure Put
- (To : out String;
- Last : out Natural;
- Item : Num;
- Fore : Integer;
- Aft : Field;
- Exp : Field);
- -- Actual output function, used internally by all other Put routines.
- -- The formal Fore is an Integer, not a Field, because the routine is
- -- also called from the version of Put that performs I/O to a string,
- -- where the starting position depends on the size of the String, and
- -- bears no relation to the bounds of Field.
+with Interfaces;
+with Ada.Text_IO.Fixed_Aux;
+with Ada.Text_IO.Float_Aux;
+with System.Img_Fixed_32; use System.Img_Fixed_32;
+with System.Img_Fixed_64; use System.Img_Fixed_64;
+with System.Val_Fixed_32; use System.Val_Fixed_32;
+with System.Val_Fixed_64; use System.Val_Fixed_64;
+with System.Val_LLF; use System.Val_LLF;
+
+package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
+
+ -- Note: we still use the floating-point I/O routines for types whose small
+ -- is not the ratio of two sufficiently small integers. This will result in
+ -- inaccuracies for fixed point types that require more precision than is
+ -- available in Long_Long_Float.
+
+ subtype Int32 is Interfaces.Integer_32; use type Int32;
+ subtype Int64 is Interfaces.Integer_64; use type Int64;
+
+ package Aux32 is new
+ Ada.Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32);
+
+ package Aux64 is new
+ Ada.Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64);
+
+ package Aux_Long_Long_Float is new
+ Ada.Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is OK and where type Int64 is OK. These boolean constants are used
+ -- to test for this, such that only code for the relevant case is included
+ -- in the instance; that's why the computation of their value must be fully
+ -- static (although it is not a static expressions in the RM sense).
+
+ OK_Get_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator <= 2**27
+ and then Num'Small_Denominator <= 2**27));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**27)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**25));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator <= 2**59
+ and then Num'Small_Denominator <= 2**59));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**59)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**53));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ E : constant Natural := 63 - 32 * Boolean'Pos (OK_Put_32);
+ -- T'Size - 1 for the selected Int{32,64}
+
+ F0 : constant Natural := 0;
+ F1 : constant Natural :=
+ F0 + 18 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+18);
+ F2 : constant Natural :=
+ F1 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+9);
+ F3 : constant Natural :=
+ F2 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+5);
+ F4 : constant Natural :=
+ F3 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+3);
+ F5 : constant Natural :=
+ F4 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+2);
+ F6 : constant Natural :=
+ F5 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+1);
+ -- Binary search for the number of digits - 1 before the decimal point of
+ -- the product 2.0**E * Num'Small.
+
+ For0 : constant Natural := 2 + F6;
+ -- Fore value for the fixed point type whose mantissa is Int{32,64} and
+ -- whose small is Num'Small.
---------
-- Get --
@@ -319,8 +270,22 @@ package body Ada.Text_IO.Fixed_IO is
Width : Field := 0)
is
pragma Unsuppress (Range_Check);
+
begin
- Aux.Get (File, Long_Long_Float (Item), Width);
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
+
exception
when Constraint_Error => raise Data_Error;
end Get;
@@ -329,11 +294,8 @@ package body Ada.Text_IO.Fixed_IO is
(Item : out Num;
Width : Field := 0)
is
- pragma Unsuppress (Range_Check);
begin
- Aux.Get (Current_In, Long_Long_Float (Item), Width);
- exception
- when Constraint_Error => raise Data_Error;
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -342,8 +304,22 @@ package body Ada.Text_IO.Fixed_IO is
Last : out Positive)
is
pragma Unsuppress (Range_Check);
+
begin
- Aux.Gets (From, Long_Long_Float (Item), Last);
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Gets (From, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Gets (From, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Gets (From, Long_Long_Float (Item), Last);
+ end if;
+
exception
when Constraint_Error => raise Data_Error;
end Get;
@@ -359,11 +335,19 @@ package body Ada.Text_IO.Fixed_IO is
Aft : Field := Default_Aft;
Exp : Field := Default_Exp)
is
- S : String (1 .. Fore + Aft + Exp + Extra_Layout_Space);
- Last : Natural;
begin
- Put (S, Last, Item, Fore, Aft, Exp);
- Generic_Aux.Put_Item (File, S (1 .. Last));
+ if OK_Put_32 then
+ Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
end Put;
procedure Put
@@ -372,11 +356,8 @@ package body Ada.Text_IO.Fixed_IO is
Aft : Field := Default_Aft;
Exp : Field := Default_Exp)
is
- S : String (1 .. Fore + Aft + Exp + Extra_Layout_Space);
- Last : Natural;
begin
- Put (S, Last, Item, Fore, Aft, Exp);
- Generic_Aux.Put_Item (Text_IO.Current_Out, S (1 .. Last));
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -385,332 +366,18 @@ package body Ada.Text_IO.Fixed_IO is
Aft : Field := Default_Aft;
Exp : Field := Default_Exp)
is
- Fore : constant Integer :=
- To'Length
- - 1 -- Decimal point
- - Field'Max (1, Aft) -- Decimal part
- - Boolean'Pos (Exp /= 0) -- Exponent indicator
- - Exp; -- Exponent
-
- Last : Natural;
-
begin
- if Fore - Boolean'Pos (Item < 0.0) < 1 then
- raise Layout_Error;
- end if;
-
- Put (To, Last, Item, Fore, Aft, Exp);
-
- if Last /= To'Last then
- raise Layout_Error;
+ if OK_Put_32 then
+ Aux32.Puts (To, Int32'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Puts (To, Int64'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Puts (To, Long_Long_Float (Item), Aft, Exp);
end if;
end Put;
- procedure Put
- (To : out String;
- Last : out Natural;
- Item : Num;
- Fore : Integer;
- Aft : Field;
- Exp : Field)
- is
- subtype Digit is Int64 range 0 .. 9;
-
- X : constant Int64 := Int64'Integer_Value (Item);
- A : constant Field := Field'Max (Aft, 1);
- Neg : constant Boolean := (Item < 0.0);
- Pos : Integer := 0; -- Next digit X has value X * 10.0**Pos;
-
- procedure Put_Character (C : Character);
- pragma Inline (Put_Character);
- -- Add C to the output string To, updating Last
-
- procedure Put_Digit (X : Digit);
- -- Add digit X to the output string (going from left to right), updating
- -- Last and Pos, and inserting the sign, leading zeros or a decimal
- -- point when necessary. After outputting the first digit, Pos must not
- -- be changed outside Put_Digit anymore.
-
- procedure Put_Int64 (X : Int64; Scale : Integer);
- -- Output the decimal number abs X * 10**Scale
-
- procedure Put_Scaled
- (X, Y, Z : Int64;
- A : Field;
- E : Integer);
- -- Output the decimal number (X * Y / Z) * 10**E, producing A digits
- -- after the decimal point and rounding the final digit. The value
- -- X * Y / Z is computed with full precision, but must be in the
- -- range of Int64.
-
- -------------------
- -- Put_Character --
- -------------------
-
- procedure Put_Character (C : Character) is
- begin
- Last := Last + 1;
-
- -- Never put a character outside of string To. Exception Layout_Error
- -- will be raised later if Last is greater than To'Last.
-
- if Last <= To'Last then
- To (Last) := C;
- end if;
- end Put_Character;
-
- ---------------
- -- Put_Digit --
- ---------------
-
- procedure Put_Digit (X : Digit) is
- Digs : constant array (Digit) of Character := "0123456789";
-
- begin
- if Last = To'First - 1 then
- if X /= 0 or else Pos <= 0 then
-
- -- Before outputting first digit, include leading space,
- -- possible minus sign and, if the first digit is fractional,
- -- decimal seperator and leading zeros.
-
- -- The Fore part has Pos + 1 + Boolean'Pos (Neg) characters,
- -- if Pos >= 0 and otherwise has a single zero digit plus minus
- -- sign if negative. Add leading space if necessary.
-
- for J in Integer'Max (0, Pos) + 2 + Boolean'Pos (Neg) .. Fore
- loop
- Put_Character (' ');
- end loop;
-
- -- Output minus sign, if number is negative
-
- if Neg then
- Put_Character ('-');
- end if;
-
- -- If starting with fractional digit, output leading zeros
-
- if Pos < 0 then
- Put_Character ('0');
- Put_Character ('.');
-
- for J in Pos .. -2 loop
- Put_Character ('0');
- end loop;
- end if;
-
- Put_Character (Digs (X));
- end if;
-
- else
- -- This is not the first digit to be output, so the only
- -- special handling is that for the decimal point
-
- if Pos = -1 then
- Put_Character ('.');
- end if;
-
- Put_Character (Digs (X));
- end if;
-
- Pos := Pos - 1;
- end Put_Digit;
-
- ---------------
- -- Put_Int64 --
- ---------------
-
- procedure Put_Int64 (X : Int64; Scale : Integer) is
- begin
- if X = 0 then
- return;
- end if;
-
- if X not in -9 .. 9 then
- Put_Int64 (X / 10, Scale + 1);
- end if;
-
- -- Use Put_Digit to advance Pos. This fixes a case where the second
- -- or later Scaled_Divide would omit leading zeroes, resulting in
- -- too few digits produced and a Layout_Error as result.
-
- while Pos > Scale loop
- Put_Digit (0);
- end loop;
-
- -- If and only if more than one digit is output before the decimal
- -- point, pos will be unequal to scale when outputting the first
- -- digit.
-
- pragma Assert (Pos = Scale or else Last = To'First - 1);
-
- Pos := Scale;
-
- Put_Digit (abs (X rem 10));
- end Put_Int64;
-
- ----------------
- -- Put_Scaled --
- ----------------
-
- procedure Put_Scaled
- (X, Y, Z : Int64;
- A : Field;
- E : Integer)
- is
- pragma Assert (E >= -Max_Digits);
- AA : constant Field := Integer'Max (E + A, 0);
- N : constant Natural := (AA + Max_Digits - 1) / Max_Digits + 1;
-
- Q : array (0 .. N - 1) of Int64 := (others => 0);
- -- Each element of Q has Max_Digits decimal digits, except the
- -- last, which has eAA rem Max_Digits. Only Q (Q'First) may have an
- -- absolute value equal to or larger than 10**Max_Digits. Only the
- -- absolute value of the elements is not significant, not the sign.
-
- XX : Int64 := X;
- YY : Int64 := Y;
-
- begin
- for J in Q'Range loop
- exit when XX = 0;
-
- if J > 0 then
- YY := 10**(Integer'Min (Max_Digits, AA - (J - 1) * Max_Digits));
- end if;
-
- Scaled_Divide64 (XX, YY, Z, Q (J), R => XX, Round => False);
- end loop;
-
- if -E > A then
- pragma Assert (N = 1);
-
- Discard_Extra_Digits : declare
- Factor : constant Int64 := 10**(-E - A);
-
- begin
- -- The scaling factors were such that the first division
- -- produced more digits than requested. So divide away extra
- -- digits and compute new remainder for later rounding.
-
- if abs (Q (0) rem Factor) >= Factor / 2 then
- Q (0) := abs (Q (0) / Factor) + 1;
- else
- Q (0) := Q (0) / Factor;
- end if;
-
- XX := 0;
- end Discard_Extra_Digits;
- end if;
-
- -- At this point XX is a remainder and we need to determine if the
- -- quotient in Q must be rounded away from zero.
-
- -- As XX is less than the divisor, it is safe to take its absolute
- -- without chance of overflow. The check to see if XX is at least
- -- half the absolute value of the divisor must be done carefully to
- -- avoid overflow or lose precision.
-
- XX := abs XX;
-
- if XX >= 2**62
- or else (Z < 0 and then (-XX) * 2 <= Z)
- or else (Z >= 0 and then XX * 2 >= Z)
- then
- -- OK, rounding is necessary. As the sign is not significant,
- -- take advantage of the fact that an extra negative value will
- -- always be available when propagating the carry.
-
- Q (Q'Last) := -abs Q (Q'Last) - 1;
-
- Propagate_Carry :
- for J in reverse 1 .. Q'Last loop
- if Q (J) = YY or else Q (J) = -YY then
- Q (J) := 0;
- Q (J - 1) := -abs Q (J - 1) - 1;
-
- else
- exit Propagate_Carry;
- end if;
- end loop Propagate_Carry;
- end if;
-
- for J in Q'First .. Q'Last - 1 loop
- Put_Int64 (Q (J), E - J * Max_Digits);
- end loop;
-
- Put_Int64 (Q (Q'Last), -A);
- end Put_Scaled;
-
- -- Start of processing for Put
-
- begin
- Last := To'First - 1;
-
- if Exp /= 0 then
-
- -- With the Exp format, it is not known how many output digits to
- -- generate, as leading zeros must be ignored. Computing too many
- -- digits and then truncating the output will not give the closest
- -- output, it is necessary to round at the correct digit.
-
- -- The general approach is as follows: as long as no digits have
- -- been generated, compute the Aft next digits (without rounding).
- -- Once a non-zero digit is generated, determine the exact number
- -- of digits remaining and compute them with rounding.
-
- -- Since a large number of iterations might be necessary in case
- -- of Aft = 1, the following optimization would be desirable.
-
- -- Count the number Z of leading zero bits in the integer
- -- representation of X, and start with producing Aft + Z * 1000 /
- -- 3322 digits in the first scaled division.
-
- -- However, the floating-point routines are still used now ???
-
- System.Img_Real.Set_Image_Real (Long_Long_Float (Item), To, Last,
- Fore, Aft, Exp);
- return;
- end if;
-
- if Exact then
- declare
- D : constant Integer := Integer'Min (A, Max_Digits
- - (Num'Fore - 1));
- Y : constant Int64 := Int64'Min (Int64 (-Num'Small), -1)
- * 10**Integer'Max (0, D);
- Z : constant Int64 := Int64'Min (Int64 (-(1.0 / Num'Small)), -1)
- * 10**Integer'Max (0, -D);
- begin
- Put_Scaled (X, Y, Z, A, -D);
- end;
-
- else -- not Exact
- declare
- E : constant Integer := Max_Digits - 1 + Scale;
- D : constant Integer := Scale - 1;
- Y : constant Int64 := Int64 (-Num'Small * 10.0**E);
- Z : constant Int64 := -10**Max_Digits;
- begin
- Put_Scaled (X, Y, Z, A, -D);
- end;
- end if;
-
- -- If only zero digits encountered, unit digit has not been output yet
-
- if Last < To'First then
- Pos := 0;
-
- elsif Last > To'Last then
- raise Layout_Error; -- Not enough room in the output variable
- end if;
-
- -- Always output digits up to the first one after the decimal point
-
- while Pos >= -A loop
- Put_Digit (0);
- end loop;
- end Put;
-
end Ada.Text_IO.Fixed_IO;
diff --git a/gcc/ada/libgnat/a-tifiio.ads b/gcc/ada/libgnat/a-tifiio.ads
index 1acf67a..8a3886d 100644
--- a/gcc/ada/libgnat/a-tifiio.ads
+++ b/gcc/ada/libgnat/a-tifiio.ads
@@ -23,7 +23,7 @@
private generic
type Num is delta <>;
-package Ada.Text_IO.Fixed_IO is
+package Ada.Text_IO.Fixed_IO with SPARK_Mode => On is
Default_Fore : Field := Num'Fore;
Default_Aft : Field := Num'Aft;
diff --git a/gcc/ada/libgnat/a-tifiio__128.adb b/gcc/ada/libgnat/a-tifiio__128.adb
new file mode 100644
index 0000000..f50e4c9
--- /dev/null
+++ b/gcc/ada/libgnat/a-tifiio__128.adb
@@ -0,0 +1,436 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . T E X T _ I O . F I X E D _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- -------------------
+-- - Fixed point I/O -
+-- -------------------
+
+-- The following text documents implementation details of the fixed point
+-- input/output routines in the GNAT runtime. The first part describes the
+-- general properties of fixed point types as defined by the Ada standard,
+-- including the Information Systems Annex.
+
+-- Subsequently these are reduced to implementation constraints and the impact
+-- of these constraints on a few possible approaches to input/output is given.
+-- Based on this analysis, a specific implementation is selected for use in
+-- the GNAT runtime. Finally the chosen algorithms are analyzed numerically in
+-- order to provide user-level documentation on limits for range and precision
+-- of fixed point types as well as accuracy of input/output conversions.
+
+-- -------------------------------------------
+-- - General Properties of Fixed Point Types -
+-- -------------------------------------------
+
+-- Operations on fixed point types, other than input/output, are not important
+-- for the purpose of this document. Only the set of values that a fixed point
+-- type can represent and the input/output operations are significant.
+
+-- Values
+-- ------
+
+-- The set of values of a fixed point type comprise the integral multiples of
+-- a number called the small of the type. The small can be either a power of
+-- two, a power of ten or (if the implementation allows) an arbitrary strictly
+-- positive real value.
+
+-- Implementations need to support ordinary fixed point types with a precision
+-- of at least 24 bits, and (in order to comply with the Information Systems
+-- Annex) decimal fixed point types with at least 18 digits. For the rest, no
+-- requirements exist for the minimal small and range that must be supported.
+
+-- Operations
+-- ----------
+
+-- [Wide_[Wide_]]Image attribute (see RM 3.5(27.1/2))
+
+-- These attributes return a decimal real literal best approximating
+-- the value (rounded away from zero if halfway between) with a
+-- single leading character that is either a minus sign or a space,
+-- one or more digits before the decimal point (with no redundant
+-- leading zeros), a decimal point, and N digits after the decimal
+-- point. For a subtype S, the value of N is S'Aft, the smallest
+-- positive integer such that (10**N)*S'Delta is greater or equal to
+-- one, see RM 3.5.10(5).
+
+-- For an arbitrary small, this means large number arithmetic needs
+-- to be performed.
+
+-- Put (see RM A.10.9(22-26))
+
+-- The requirements for Put add no extra constraints over the image
+-- attributes, although it would be nice to be able to output more
+-- than S'Aft digits after the decimal point for values of subtype S.
+
+-- [Wide_[Wide_]]Value attribute (RM 3.5(39.1/2))
+
+-- Since the input can be given in any base in the range 2..16,
+-- accurate conversion to a fixed point number may require
+-- arbitrary precision arithmetic if there is no limit on the
+-- magnitude of the small of the fixed point type.
+
+-- Get (see RM A.10.9(12-21))
+
+-- The requirements for Get are identical to those of the Value
+-- attribute.
+
+-- ------------------------------
+-- - Implementation Constraints -
+-- ------------------------------
+
+-- The requirements listed above for the input/output operations lead to
+-- significant complexity, if no constraints are put on supported smalls.
+
+-- Implementation Strategies
+-- -------------------------
+
+-- * Floating point arithmetic
+-- * Arbitrary-precision integer arithmetic
+-- * Fixed-precision integer arithmetic
+
+-- Although it seems convenient to convert fixed point numbers to floating
+-- point and then print them, this leads to a number of restrictions.
+-- The first one is precision. The widest floating-point type generally
+-- available has 53 bits of mantissa. This means that Fine_Delta cannot
+-- be less than 2.0**(-53).
+
+-- In GNAT, Fine_Delta is 2.0**(-127), and Duration for example is a 64-bit
+-- type. This means that a floating-point type with 128 bits of mantissa needs
+-- to be used, which currently does not exist in any common architecture. It
+-- would still be possible to use multi-precision floating point to perform
+-- calculations using longer mantissas, but this is a much harder approach.
+
+-- The base conversions needed for input/output of (non-decimal) fixed point
+-- types can be seen as pairs of integer multiplications and divisions.
+
+-- Arbitrary-precision integer arithmetic would be suitable for the job at
+-- hand, but has the drawback that it is very heavy implementation-wise.
+-- Especially in embedded systems, where fixed point types are often used,
+-- it may not be desirable to require large amounts of storage and time
+-- for fixed I/O operations.
+
+-- Fixed-precision integer arithmetic has the advantage of simplicity and
+-- speed. For the most common fixed point types this would be a perfect
+-- solution. The downside however may be a restricted set of acceptable
+-- fixed point types.
+
+-- Implementation Choices
+-- ----------------------
+
+-- The current implementation in the GNAT runtime uses fixed-precision integer
+-- arithmetic for fixed point types whose Small is the ratio of two integers
+-- whose magnitude is bounded relatively to the size of the mantissa, with a
+-- three-tiered approach for 32-bit, 64-bit and 128-bit fixed point types. For
+-- other fixed point types, the implementation uses floating-point arithmetic.
+
+-- The exact requirements of the algorithms are analyzed and documented along
+-- with the implementation in their respective units.
+
+with Interfaces;
+with Ada.Text_IO.Fixed_Aux;
+with Ada.Text_IO.Float_Aux;
+with System.Img_Fixed_32; use System.Img_Fixed_32;
+with System.Img_Fixed_64; use System.Img_Fixed_64;
+with System.Img_Fixed_128; use System.Img_Fixed_128;
+with System.Val_Fixed_32; use System.Val_Fixed_32;
+with System.Val_Fixed_64; use System.Val_Fixed_64;
+with System.Val_Fixed_128; use System.Val_Fixed_128;
+with System.Val_LLF; use System.Val_LLF;
+
+package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
+
+ -- Note: we still use the floating-point I/O routines for types whose small
+ -- is not the ratio of two sufficiently small integers. This will result in
+ -- inaccuracies for fixed point types that require more precision than is
+ -- available in Long_Long_Float.
+
+ subtype Int32 is Interfaces.Integer_32; use type Int32;
+ subtype Int64 is Interfaces.Integer_64; use type Int64;
+ subtype Int128 is Interfaces.Integer_128; use type Int128;
+
+ package Aux32 is new
+ Ada.Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32);
+
+ package Aux64 is new
+ Ada.Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64);
+
+ package Aux128 is new
+ Ada.Text_IO.Fixed_Aux (Int128, Scan_Fixed128, Set_Image_Fixed128);
+
+ package Aux_Long_Long_Float is new
+ Ada.Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is OK, where type Int64 is OK and where type Int128 is OK. These
+ -- boolean constants are used to test for this, such that only code for the
+ -- relevant case is included in the instance; that's why the computation of
+ -- their value must be fully static (although it is not a static expression
+ -- in the RM sense).
+
+ OK_Get_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator <= 2**27
+ and then Num'Small_Denominator <= 2**27));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**27)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**25));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator <= 2**59
+ and then Num'Small_Denominator <= 2**59));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**59)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**53));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_128 : constant Boolean :=
+ Num'Base'Object_Size <= 128
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**127)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**127)
+ or else
+ (Num'Small_Numerator <= 2**123
+ and then Num'Small_Denominator <= 2**123));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_128 : constant Boolean :=
+ Num'Base'Object_Size <= 128
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**127)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**127)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**123)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**122));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ E : constant Natural :=
+ 127 - 64 * Boolean'Pos (OK_Put_64) - 32 * Boolean'Pos (OK_Put_32);
+ -- T'Size - 1 for the selected Int{32,64,128}
+
+ F0 : constant Natural := 0;
+ F1 : constant Natural :=
+ F0 + 38 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+38);
+ F2 : constant Natural :=
+ F1 + 19 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+19);
+ F3 : constant Natural :=
+ F2 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+9);
+ F4 : constant Natural :=
+ F3 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+5);
+ F5 : constant Natural :=
+ F4 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+3);
+ F6 : constant Natural :=
+ F5 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+2);
+ F7 : constant Natural :=
+ F6 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F6) >= 1.0E+1);
+ -- Binary search for the number of digits - 1 before the decimal point of
+ -- the product 2.0**E * Num'Small.
+
+ For0 : constant Natural := 2 + F7;
+ -- Fore value for the fixed point type whose mantissa is Int{32,64,128} and
+ -- whose small is Num'Small.
+
+ ---------
+ -- Get --
+ ---------
+
+ procedure Get
+ (File : File_Type;
+ Item : out Num;
+ Width : Field := 0)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_128 then
+ Item := Num'Fixed_Value
+ (Aux128.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ procedure Get
+ (Item : out Num;
+ Width : Field := 0)
+ is
+ begin
+ Get (Current_In, Item, Width);
+ end Get;
+
+ procedure Get
+ (From : String;
+ Item : out Num;
+ Last : out Positive)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Gets (From, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Gets (From, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_128 then
+ Item := Num'Fixed_Value
+ (Aux128.Gets (From, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Gets (From, Long_Long_Float (Item), Last);
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if OK_Put_32 then
+ Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_128 then
+ Aux128.Put (File, Int128'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
+ end Put;
+
+ procedure Put
+ (Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ Put (Current_Out, Item, Fore, Aft, Exp);
+ end Put;
+
+ procedure Put
+ (To : out String;
+ Item : Num;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if OK_Put_32 then
+ Aux32.Puts (To, Int32'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Puts (To, Int64'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_128 then
+ Aux128.Puts (To, Int128'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Puts (To, Long_Long_Float (Item), Aft, Exp);
+ end if;
+ end Put;
+
+end Ada.Text_IO.Fixed_IO;
diff --git a/gcc/ada/libgnat/a-tiflau.adb b/gcc/ada/libgnat/a-tiflau.adb
index 214b5c8..4955a99 100644
--- a/gcc/ada/libgnat/a-tiflau.adb
+++ b/gcc/ada/libgnat/a-tiflau.adb
@@ -32,7 +32,6 @@
with Ada.Text_IO.Generic_Aux; use Ada.Text_IO.Generic_Aux;
with System.Img_Real; use System.Img_Real;
-with System.Val_Real; use System.Val_Real;
package body Ada.Text_IO.Float_Aux is
@@ -42,12 +41,12 @@ package body Ada.Text_IO.Float_Aux is
procedure Get
(File : File_Type;
- Item : out Long_Long_Float;
+ Item : out Num;
Width : Field)
is
Buf : String (1 .. Field'Last);
Stop : Integer := 0;
- Ptr : aliased Integer := 1;
+ Ptr : aliased Integer;
begin
if Width /= 0 then
@@ -55,10 +54,10 @@ package body Ada.Text_IO.Float_Aux is
String_Skip (Buf, Ptr);
else
Load_Real (File, Buf, Stop);
+ Ptr := 1;
end if;
- Item := Scan_Real (Buf, Ptr'Access, Stop);
-
+ Item := Scan (Buf, Ptr'Access, Stop);
Check_End_Of_Field (Buf, Stop, Ptr, Width);
end Get;
@@ -68,128 +67,27 @@ package body Ada.Text_IO.Float_Aux is
procedure Gets
(From : String;
- Item : out Long_Long_Float;
+ Item : out Num;
Last : out Positive)
is
Pos : aliased Integer;
begin
String_Skip (From, Pos);
- Item := Scan_Real (From, Pos'Access, From'Last);
+ Item := Scan (From, Pos'Access, From'Last);
Last := Pos - 1;
exception
- when Constraint_Error =>
- raise Data_Error;
+ when Constraint_Error => raise Data_Error;
end Gets;
- ---------------
- -- Load_Real --
- ---------------
-
- procedure Load_Real
- (File : File_Type;
- Buf : out String;
- Ptr : in out Natural)
- is
- Loaded : Boolean;
-
- begin
- -- Skip initial blanks, and load possible sign
-
- Load_Skip (File);
- Load (File, Buf, Ptr, '+', '-');
-
- -- Case of .nnnn
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Digits (File, Buf, Ptr, Loaded);
-
- -- Hopeless junk if no digits loaded
-
- if not Loaded then
- return;
- end if;
-
- -- Otherwise must have digits to start
-
- else
- Load_Digits (File, Buf, Ptr, Loaded);
-
- -- Hopeless junk if no digits loaded
-
- if not Loaded then
- return;
- end if;
-
- -- Based cases. We recognize either the standard '#' or the
- -- allowed alternative replacement ':' (see RM J.2(3)).
-
- Load (File, Buf, Ptr, '#', ':', Loaded);
-
- if Loaded then
-
- -- Case of nnn#.xxx#
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Extended_Digits (File, Buf, Ptr);
- Load (File, Buf, Ptr, '#', ':');
-
- -- Case of nnn#xxx.[xxx]# or nnn#xxx#
-
- else
- Load_Extended_Digits (File, Buf, Ptr);
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Extended_Digits (File, Buf, Ptr);
- end if;
-
- -- As usual, it seems strange to allow mixed base characters,
- -- but that is what ACVC tests expect, see CE3804M, case (3).
-
- Load (File, Buf, Ptr, '#', ':');
- end if;
-
- -- Case of nnn.[nnn] or nnn
-
- else
- -- Prevent the potential processing of '.' in cases where the
- -- initial digits have a trailing underscore.
-
- if Buf (Ptr) = '_' then
- return;
- end if;
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Digits (File, Buf, Ptr);
- end if;
- end if;
- end if;
-
- -- Deal with exponent
-
- Load (File, Buf, Ptr, 'E', 'e', Loaded);
-
- if Loaded then
- Load (File, Buf, Ptr, '+', '-');
- Load_Digits (File, Buf, Ptr);
- end if;
- end Load_Real;
-
---------
-- Put --
---------
procedure Put
(File : File_Type;
- Item : Long_Long_Float;
+ Item : Num;
Fore : Field;
Aft : Field;
Exp : Field)
@@ -198,7 +96,7 @@ package body Ada.Text_IO.Float_Aux is
Ptr : Natural := 0;
begin
- Set_Image_Real (Item, Buf, Ptr, Fore, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (Item), Buf, Ptr, Fore, Aft, Exp);
Put_Item (File, Buf (1 .. Ptr));
end Put;
@@ -208,7 +106,7 @@ package body Ada.Text_IO.Float_Aux is
procedure Puts
(To : out String;
- Item : Long_Long_Float;
+ Item : Num;
Aft : Field;
Exp : Field)
is
@@ -216,7 +114,8 @@ package body Ada.Text_IO.Float_Aux is
Ptr : Natural := 0;
begin
- Set_Image_Real (Item, Buf, Ptr, Fore => 1, Aft => Aft, Exp => Exp);
+ Set_Image_Real
+ (Long_Long_Float (Item), Buf, Ptr, Fore => 1, Aft => Aft, Exp => Exp);
if Ptr > To'Length then
raise Layout_Error;
diff --git a/gcc/ada/libgnat/a-tiflau.ads b/gcc/ada/libgnat/a-tiflau.ads
index 68ac9eb..2dfe76d 100644
--- a/gcc/ada/libgnat/a-tiflau.ads
+++ b/gcc/ada/libgnat/a-tiflau.ads
@@ -31,41 +31,42 @@
-- This package contains the routines for Ada.Text_IO.Float_IO that are
-- shared among separate instantiations of this package. The routines in
--- this package are identical semantically to those in Float_IO itself,
--- except that generic parameter Num has been replaced by Long_Long_Float,
--- and the default parameters have been removed because they are supplied
+-- this package are identical semantically to those in Float_IO, except
+-- that the default parameters have been removed because they are supplied
-- explicitly by the calls from within the generic template. This package
--- is also used by Ada.Text_IO.Fixed_IO, and Ada.Text_IO.Decimal_IO.
+-- is also used by Ada.Text_IO.Fixed_IO and Ada.Text_IO.Decimal_IO.
-private package Ada.Text_IO.Float_Aux is
+private generic
- procedure Load_Real
- (File : File_Type;
- Buf : out String;
- Ptr : in out Natural);
- -- This is an auxiliary routine that is used to load a possibly signed
- -- real literal value from the input file into Buf, starting at Ptr + 1.
+ type Num is digits <>;
+
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Num;
+
+package Ada.Text_IO.Float_Aux is
procedure Get
(File : File_Type;
- Item : out Long_Long_Float;
+ Item : out Num;
Width : Field);
procedure Put
(File : File_Type;
- Item : Long_Long_Float;
+ Item : Num;
Fore : Field;
Aft : Field;
Exp : Field);
procedure Gets
(From : String;
- Item : out Long_Long_Float;
+ Item : out Num;
Last : out Positive);
procedure Puts
(To : out String;
- Item : Long_Long_Float;
+ Item : Num;
Aft : Field;
Exp : Field);
diff --git a/gcc/ada/libgnat/a-tiflio.adb b/gcc/ada/libgnat/a-tiflio.adb
index 0daa044..db1cea2 100644
--- a/gcc/ada/libgnat/a-tiflio.adb
+++ b/gcc/ada/libgnat/a-tiflio.adb
@@ -30,10 +30,29 @@
------------------------------------------------------------------------------
with Ada.Text_IO.Float_Aux;
+with System.Val_Flt; use System.Val_Flt;
+with System.Val_LFlt; use System.Val_LFlt;
+with System.Val_LLF; use System.Val_LLF;
-package body Ada.Text_IO.Float_IO is
+package body Ada.Text_IO.Float_IO with SPARK_Mode => Off is
- package Aux renames Ada.Text_IO.Float_Aux;
+ package Aux_Float is new
+ Ada.Text_IO.Float_Aux (Float, Scan_Float);
+
+ package Aux_Long_Float is new
+ Ada.Text_IO.Float_Aux (Long_Float, Scan_Long_Float);
+
+ package Aux_Long_Long_Float is new
+ Ada.Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Float is OK, where type Long_Float is OK and where type Long_Long_Float
+ -- is needed. These boolean constants are used to test for this, such that
+ -- only code for the relevant case is included in the instance.
+
+ OK_Float : constant Boolean := Num'Base'Digits <= Float'Digits;
+
+ OK_Long_Float : constant Boolean := Num'Base'Digits <= Long_Float'Digits;
---------
-- Get --
@@ -47,7 +66,13 @@ package body Ada.Text_IO.Float_IO is
pragma Unsuppress (Range_Check);
begin
- Aux.Get (File, Long_Long_Float (Item), Width);
+ if OK_Float then
+ Aux_Float.Get (File, Float (Item), Width);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Get (File, Long_Float (Item), Width);
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
-- In the case where the type is unconstrained (e.g. Standard'Float),
-- the above conversion may result in an infinite value, which is
@@ -66,22 +91,8 @@ package body Ada.Text_IO.Float_IO is
(Item : out Num;
Width : Field := 0)
is
- pragma Unsuppress (Range_Check);
-
begin
- Aux.Get (Current_In, Long_Long_Float (Item), Width);
-
- -- In the case where the type is unconstrained (e.g. Standard'Float),
- -- the above conversion may result in an infinite value, which is
- -- normally fine for a conversion, but in this case, we want to treat
- -- that as a data error.
-
- if not Item'Valid then
- raise Data_Error;
- end if;
-
- exception
- when Constraint_Error => raise Data_Error;
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -92,7 +103,13 @@ package body Ada.Text_IO.Float_IO is
pragma Unsuppress (Range_Check);
begin
- Aux.Gets (From, Long_Long_Float (Item), Last);
+ if OK_Float then
+ Aux_Float.Gets (From, Float (Item), Last);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Gets (From, Long_Float (Item), Last);
+ else
+ Aux_Long_Long_Float.Gets (From, Long_Long_Float (Item), Last);
+ end if;
-- In the case where the type is unconstrained (e.g. Standard'Float),
-- the above conversion may result in an infinite value, which is
@@ -119,7 +136,14 @@ package body Ada.Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ if OK_Float then
+ Aux_Float.Put (File, Float (Item), Fore, Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Put (File, Long_Float (Item), Fore, Aft, Exp);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
end Put;
procedure Put
@@ -129,7 +153,7 @@ package body Ada.Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (Current_Out, Long_Long_Float (Item), Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -139,7 +163,13 @@ package body Ada.Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Puts (To, Long_Long_Float (Item), Aft, Exp);
+ if OK_Float then
+ Aux_Float.Puts (To, Float (Item), Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Puts (To, Long_Float (Item), Aft, Exp);
+ else
+ Aux_Long_Long_Float.Puts (To, Long_Long_Float (Item), Aft, Exp);
+ end if;
end Put;
end Ada.Text_IO.Float_IO;
diff --git a/gcc/ada/libgnat/a-tiflio.ads b/gcc/ada/libgnat/a-tiflio.ads
index bd4c64f64..d61b9e7 100644
--- a/gcc/ada/libgnat/a-tiflio.ads
+++ b/gcc/ada/libgnat/a-tiflio.ads
@@ -43,7 +43,7 @@
private generic
type Num is digits <>;
-package Ada.Text_IO.Float_IO is
+package Ada.Text_IO.Float_IO with SPARK_Mode => On is
Default_Fore : Field := 2;
Default_Aft : Field := Num'Digits - 1;
diff --git a/gcc/ada/libgnat/a-tigeau.adb b/gcc/ada/libgnat/a-tigeau.adb
index f1ba60a..5e13dae 100644
--- a/gcc/ada/libgnat/a-tigeau.adb
+++ b/gcc/ada/libgnat/a-tigeau.adb
@@ -377,6 +377,106 @@ package body Ada.Text_IO.Generic_Aux is
end Load_Integer;
---------------
+ -- Load_Real --
+ ---------------
+
+ procedure Load_Real
+ (File : File_Type;
+ Buf : out String;
+ Ptr : in out Natural)
+ is
+ Loaded : Boolean;
+
+ begin
+ -- Skip initial blanks, and load possible sign
+
+ Load_Skip (File);
+ Load (File, Buf, Ptr, '+', '-');
+
+ -- Case of .nnnn
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Digits (File, Buf, Ptr, Loaded);
+
+ -- Hopeless junk if no digits loaded
+
+ if not Loaded then
+ return;
+ end if;
+
+ -- Otherwise must have digits to start
+
+ else
+ Load_Digits (File, Buf, Ptr, Loaded);
+
+ -- Hopeless junk if no digits loaded
+
+ if not Loaded then
+ return;
+ end if;
+
+ -- Based cases. We recognize either the standard '#' or the
+ -- allowed alternative replacement ':' (see RM J.2(3)).
+
+ Load (File, Buf, Ptr, '#', ':', Loaded);
+
+ if Loaded then
+
+ -- Case of nnn#.xxx#
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Extended_Digits (File, Buf, Ptr);
+ Load (File, Buf, Ptr, '#', ':');
+
+ -- Case of nnn#xxx.[xxx]# or nnn#xxx#
+
+ else
+ Load_Extended_Digits (File, Buf, Ptr);
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Extended_Digits (File, Buf, Ptr);
+ end if;
+
+ -- As usual, it seems strange to allow mixed base characters,
+ -- but that is what ACVC tests expect, see CE3804M, case (3).
+
+ Load (File, Buf, Ptr, '#', ':');
+ end if;
+
+ -- Case of nnn.[nnn] or nnn
+
+ else
+ -- Prevent the potential processing of '.' in cases where the
+ -- initial digits have a trailing underscore.
+
+ if Buf (Ptr) = '_' then
+ return;
+ end if;
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Digits (File, Buf, Ptr);
+ end if;
+ end if;
+ end if;
+
+ -- Deal with exponent
+
+ Load (File, Buf, Ptr, 'E', 'e', Loaded);
+
+ if Loaded then
+ Load (File, Buf, Ptr, '+', '-');
+ Load_Digits (File, Buf, Ptr);
+ end if;
+ end Load_Real;
+
+ ---------------
-- Load_Skip --
---------------
diff --git a/gcc/ada/libgnat/a-tigeau.ads b/gcc/ada/libgnat/a-tigeau.ads
index 09334b3..d6acd8d 100644
--- a/gcc/ada/libgnat/a-tigeau.ads
+++ b/gcc/ada/libgnat/a-tigeau.ads
@@ -156,6 +156,12 @@ private package Ada.Text_IO.Generic_Aux is
Ptr : in out Natural);
-- Loads a possibly signed integer literal value
+ procedure Load_Real
+ (File : File_Type;
+ Buf : out String;
+ Ptr : in out Natural);
+ -- Loads a possibly signed real literal value
+
function Nextc (File : File_Type) return Integer;
-- Like Getc, but includes a call to Ungetc, so that the file
-- pointer is not moved by the call.
diff --git a/gcc/ada/libgnat/a-wtcoau.adb b/gcc/ada/libgnat/a-wtcoau.adb
index a60336b..05a6d9d 100644
--- a/gcc/ada/libgnat/a-wtcoau.adb
+++ b/gcc/ada/libgnat/a-wtcoau.adb
@@ -30,22 +30,19 @@
------------------------------------------------------------------------------
with Ada.Wide_Text_IO.Generic_Aux; use Ada.Wide_Text_IO.Generic_Aux;
-with Ada.Wide_Text_IO.Float_Aux;
with System.Img_Real; use System.Img_Real;
package body Ada.Wide_Text_IO.Complex_Aux is
- package Aux renames Ada.Wide_Text_IO.Float_Aux;
-
---------
-- Get --
---------
procedure Get
(File : File_Type;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Width : Field)
is
Buf : String (1 .. Field'Last);
@@ -95,8 +92,8 @@ package body Ada.Wide_Text_IO.Complex_Aux is
procedure Gets
(From : String;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Last : out Positive)
is
Paren : Boolean;
@@ -139,8 +136,8 @@ package body Ada.Wide_Text_IO.Complex_Aux is
procedure Put
(File : File_Type;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Fore : Field;
Aft : Field;
Exp : Field)
@@ -159,8 +156,8 @@ package body Ada.Wide_Text_IO.Complex_Aux is
procedure Puts
(To : out String;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Aft : Field;
Exp : Field)
is
@@ -174,9 +171,9 @@ package body Ada.Wide_Text_IO.Complex_Aux is
-- Both parts are initially converted with a Fore of 0
Rptr := 0;
- Set_Image_Real (ItemR, R_String, Rptr, 0, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (ItemR), R_String, Rptr, 0, Aft, Exp);
Iptr := 0;
- Set_Image_Real (ItemI, I_String, Iptr, 0, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (ItemI), I_String, Iptr, 0, Aft, Exp);
-- Check room for both parts plus parens plus comma (RM G.1.3(34))
diff --git a/gcc/ada/libgnat/a-wtcoau.ads b/gcc/ada/libgnat/a-wtcoau.ads
index 781dd8d..affb969 100644
--- a/gcc/ada/libgnat/a-wtcoau.ads
+++ b/gcc/ada/libgnat/a-wtcoau.ads
@@ -29,40 +29,47 @@
-- --
------------------------------------------------------------------------------
--- This package contains the routines for Ada.Wide_Text_IO.Complex_IO that
--- are shared among separate instantiations of this package. The routines
--- in this package are identical semantically to those in Complex_IO itself,
--- except that the generic parameter Complex has been replaced by separate
--- real and imaginary values of type Long_Long_Float, and default parameters
--- have been removed because they are supplied explicitly by the calls from
--- within the generic template.
+-- This package contains the routines for Ada.Wide_Text_IO.Complex_IO that are
+-- shared among separate instantiations of this package. The routines in this
+-- package are identical semantically to those in Complex_IO, except that the
+-- generic parameter Complex has been replaced by separate real and imaginary
+-- parameters, and default parameters have been removed because they are
+-- supplied explicitly by the calls from within the generic template.
+
+with Ada.Wide_Text_IO.Float_Aux;
+
+private generic
+
+ type Num is digits <>;
+
+ with package Aux is new Ada.Wide_Text_IO.Float_Aux (Num, <>);
package Ada.Wide_Text_IO.Complex_Aux is
procedure Get
(File : File_Type;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Width : Field);
- procedure Gets
- (From : String;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
- Last : out Positive);
-
procedure Put
(File : File_Type;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Fore : Field;
Aft : Field;
Exp : Field);
+ procedure Gets
+ (From : String;
+ ItemR : out Num;
+ ItemI : out Num;
+ Last : out Positive);
+
procedure Puts
(To : out String;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Aft : Field;
Exp : Field);
diff --git a/gcc/ada/libgnat/a-wtcoio.adb b/gcc/ada/libgnat/a-wtcoio.adb
index c1c3b94..8e9ff7a 100644
--- a/gcc/ada/libgnat/a-wtcoio.adb
+++ b/gcc/ada/libgnat/a-wtcoio.adb
@@ -30,24 +30,43 @@
------------------------------------------------------------------------------
with Ada.Wide_Text_IO.Complex_Aux;
+with Ada.Wide_Text_IO.Float_Aux;
+with System.Val_Flt; use System.Val_Flt;
+with System.Val_LFlt; use System.Val_LFlt;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
-with System.WCh_Con; use System.WCh_Con;
-with System.WCh_WtS; use System.WCh_WtS;
+package body Ada.Wide_Text_IO.Complex_IO is
-with Ada.Unchecked_Conversion;
+ use Complex_Types;
-package body Ada.Wide_Text_IO.Complex_IO is
+ package Scalar_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Float, Scan_Float);
+
+ package Scalar_Long_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Long_Float, Scan_Long_Float);
+
+ package Scalar_Long_Long_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ package Aux_Float is new
+ Ada.Wide_Text_IO.Complex_Aux (Float, Scalar_Float);
- package Aux renames Ada.Wide_Text_IO.Complex_Aux;
+ package Aux_Long_Float is new
+ Ada.Wide_Text_IO.Complex_Aux (Long_Float, Scalar_Long_Float);
- subtype LLF is Long_Long_Float;
- -- Type used for calls to routines in Aux
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Text_IO.Complex_Aux (Long_Long_Float, Scalar_Long_Long_Float);
- function TFT is new
- Ada.Unchecked_Conversion (File_Type, Ada.Wide_Text_IO.File_Type);
- -- This unchecked conversion is to get around a visibility bug in
- -- GNAT version 2.04w. It should be possible to simply use the
- -- subtype declared above and do normal checked conversions.
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Float is OK, where type Long_Float is OK and where type Long_Long_Float
+ -- is needed. These boolean constants are used to test for this, such that
+ -- only code for the relevant case is included in the instance.
+
+ OK_Float : constant Boolean := Real'Base'Digits <= Float'Digits;
+
+ OK_Long_Float : constant Boolean := Real'Base'Digits <= Long_Float'Digits;
---------
-- Get --
@@ -62,7 +81,17 @@ package body Ada.Wide_Text_IO.Complex_IO is
Imag_Item : Real'Base;
begin
- Aux.Get (TFT (File), LLF (Real_Item), LLF (Imag_Item), Width);
+ if OK_Float then
+ Aux_Float.Get (File, Float (Real_Item), Float (Imag_Item), Width);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Get
+ (File, Long_Float (Real_Item), Long_Float (Imag_Item), Width);
+ else
+ Aux_Long_Long_Float.Get
+ (File, Long_Long_Float (Real_Item), Long_Long_Float (Imag_Item),
+ Width);
+ end if;
+
Item := (Real_Item, Imag_Item);
exception
@@ -78,7 +107,7 @@ package body Ada.Wide_Text_IO.Complex_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
---------
@@ -100,7 +129,17 @@ package body Ada.Wide_Text_IO.Complex_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- Aux.Gets (S, LLF (Real_Item), LLF (Imag_Item), Last);
+ if OK_Float then
+ Aux_Float.Gets (S, Float (Real_Item), Float (Imag_Item), Last);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Gets
+ (S, Long_Float (Real_Item), Long_Float (Imag_Item), Last);
+ else
+ Aux_Long_Long_Float.Gets
+ (S, Long_Long_Float (Real_Item), Long_Long_Float (Imag_Item),
+ Last);
+ end if;
+
Item := (Real_Item, Imag_Item);
exception
@@ -119,7 +158,18 @@ package body Ada.Wide_Text_IO.Complex_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (TFT (File), LLF (Re (Item)), LLF (Im (Item)), Fore, Aft, Exp);
+ if OK_Float then
+ Aux_Float.Put
+ (File, Float (Re (Item)), Float (Im (Item)), Fore, Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Put
+ (File, Long_Float (Re (Item)), Long_Float (Im (Item)), Fore, Aft,
+ Exp);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Re (Item)), Long_Long_Float (Im (Item)),
+ Fore, Aft, Exp);
+ end if;
end Put;
---------
@@ -133,7 +183,7 @@ package body Ada.Wide_Text_IO.Complex_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
---------
@@ -149,7 +199,16 @@ package body Ada.Wide_Text_IO.Complex_IO is
S : String (To'First .. To'Last);
begin
- Aux.Puts (S, LLF (Re (Item)), LLF (Im (Item)), Aft, Exp);
+ if OK_Float then
+ Aux_Float.Puts (S, Float (Re (Item)), Float (Im (Item)), Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Puts
+ (S, Long_Float (Re (Item)), Long_Float (Im (Item)), Aft, Exp);
+ else
+ Aux_Long_Long_Float.Puts
+ (S, Long_Long_Float (Re (Item)), Long_Long_Float (Im (Item)),
+ Aft, Exp);
+ end if;
for J in S'Range loop
To (J) := Wide_Character'Val (Character'Pos (S (J)));
diff --git a/gcc/ada/libgnat/a-wtcoio.ads b/gcc/ada/libgnat/a-wtcoio.ads
index 31fab2b..f80a5b9 100644
--- a/gcc/ada/libgnat/a-wtcoio.ads
+++ b/gcc/ada/libgnat/a-wtcoio.ads
@@ -20,42 +20,40 @@ generic
package Ada.Wide_Text_IO.Complex_IO is
- use Complex_Types;
-
Default_Fore : Field := 2;
- Default_Aft : Field := Real'Digits - 1;
+ Default_Aft : Field := Complex_Types.Real'Digits - 1;
Default_Exp : Field := 3;
procedure Get
(File : File_Type;
- Item : out Complex;
+ Item : out Complex_Types.Complex;
Width : Field := 0);
procedure Get
- (Item : out Complex;
+ (Item : out Complex_Types.Complex;
Width : Field := 0);
procedure Put
(File : File_Type;
- Item : Complex;
+ Item : Complex_Types.Complex;
Fore : Field := Default_Fore;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp);
procedure Put
- (Item : Complex;
+ (Item : Complex_Types.Complex;
Fore : Field := Default_Fore;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp);
procedure Get
(From : Wide_String;
- Item : out Complex;
+ Item : out Complex_Types.Complex;
Last : out Positive);
procedure Put
(To : out Wide_String;
- Item : Complex;
+ Item : Complex_Types.Complex;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp);
diff --git a/gcc/ada/libgnat/a-wtdeau.adb b/gcc/ada/libgnat/a-wtdeau.adb
index 7bfc613..57fcc92 100644
--- a/gcc/ada/libgnat/a-wtdeau.adb
+++ b/gcc/ada/libgnat/a-wtdeau.adb
@@ -30,56 +30,22 @@
------------------------------------------------------------------------------
with Ada.Wide_Text_IO.Generic_Aux; use Ada.Wide_Text_IO.Generic_Aux;
-with Ada.Wide_Text_IO.Float_Aux; use Ada.Wide_Text_IO.Float_Aux;
-
-with System.Img_Dec; use System.Img_Dec;
-with System.Img_LLD; use System.Img_LLD;
-with System.Val_Dec; use System.Val_Dec;
-with System.Val_LLD; use System.Val_LLD;
package body Ada.Wide_Text_IO.Decimal_Aux is
- -------------
- -- Get_Dec --
- -------------
-
- function Get_Dec
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Integer
- is
- Buf : String (1 .. Field'Last);
- Ptr : aliased Integer;
- Stop : Integer := 0;
- Item : Integer;
-
- begin
- if Width /= 0 then
- Load_Width (File, Width, Buf, Stop);
- String_Skip (Buf, Ptr);
- else
- Load_Real (File, Buf, Stop);
- Ptr := 1;
- end if;
-
- Item := Scan_Decimal (Buf, Ptr'Access, Stop, Scale);
- Check_End_Of_Field (Buf, Stop, Ptr, Width);
- return Item;
- end Get_Dec;
-
- -------------
- -- Get_LLD --
- -------------
+ ---------
+ -- Get --
+ ---------
- function Get_LLD
+ function Get
(File : File_Type;
Width : Field;
- Scale : Integer) return Long_Long_Integer
+ Scale : Integer) return Int
is
Buf : String (1 .. Field'Last);
Ptr : aliased Integer;
Stop : Integer := 0;
- Item : Long_Long_Integer;
+ Item : Int;
begin
if Width /= 0 then
@@ -90,68 +56,42 @@ package body Ada.Wide_Text_IO.Decimal_Aux is
Ptr := 1;
end if;
- Item := Scan_Long_Long_Decimal (Buf, Ptr'Access, Stop, Scale);
+ Item := Scan (Buf, Ptr'Access, Stop, Scale);
Check_End_Of_Field (Buf, Stop, Ptr, Width);
return Item;
- end Get_LLD;
-
- --------------
- -- Gets_Dec --
- --------------
-
- function Gets_Dec
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Integer
- is
- Pos : aliased Integer;
- Item : Integer;
-
- begin
- String_Skip (From, Pos);
- Item := Scan_Decimal (From, Pos'Access, From'Last, Scale);
- Last.all := Pos - 1;
- return Item;
+ end Get;
- exception
- when Constraint_Error =>
- Last.all := Pos - 1;
- raise Data_Error;
-
- end Gets_Dec;
+ ----------
+ -- Gets --
+ ----------
- --------------
- -- Gets_LLD --
- --------------
-
- function Gets_LLD
+ function Gets
(From : String;
- Last : not null access Positive;
- Scale : Integer) return Long_Long_Integer
+ Last : out Positive;
+ Scale : Integer) return Int
is
Pos : aliased Integer;
- Item : Long_Long_Integer;
+ Item : Int;
begin
String_Skip (From, Pos);
- Item := Scan_Long_Long_Decimal (From, Pos'Access, From'Last, Scale);
- Last.all := Pos - 1;
+ Item := Scan (From, Pos'Access, From'Last, Scale);
+ Last := Pos - 1;
return Item;
exception
when Constraint_Error =>
- Last.all := Pos - 1;
+ Last := Pos - 1;
raise Data_Error;
+ end Gets;
- end Gets_LLD;
-
- -------------
- -- Put_Dec --
- -------------
+ ---------
+ -- Put --
+ ---------
- procedure Put_Dec
+ procedure Put
(File : File_Type;
- Item : Integer;
+ Item : Int;
Fore : Field;
Aft : Field;
Exp : Field;
@@ -161,105 +101,51 @@ package body Ada.Wide_Text_IO.Decimal_Aux is
Ptr : Natural := 0;
begin
- Set_Image_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
+ Set_Image (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
Put_Item (File, Buf (1 .. Ptr));
- end Put_Dec;
+ end Put;
- -------------
- -- Put_LLD --
- -------------
+ ----------
+ -- Puts --
+ ----------
- procedure Put_LLD
- (File : File_Type;
- Item : Long_Long_Integer;
- Fore : Field;
- Aft : Field;
- Exp : Field;
- Scale : Integer)
- is
- Buf : String (1 .. Field'Last);
- Ptr : Natural := 0;
-
- begin
- Set_Image_Long_Long_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
- Put_Item (File, Buf (1 .. Ptr));
- end Put_LLD;
-
- --------------
- -- Puts_Dec --
- --------------
-
- procedure Puts_Dec
+ procedure Puts
(To : out String;
- Item : Integer;
+ Item : Int;
Aft : Field;
Exp : Field;
Scale : Integer)
is
- Buf : String (1 .. Field'Last);
+ Buf : String (1 .. Positive'Max (Field'Last, To'Length));
Fore : Integer;
Ptr : Natural := 0;
begin
- -- Compute Fore, allowing for Aft digits and the decimal dot
+ -- Compute Fore, allowing for the decimal dot and Aft digits
- Fore := To'Length - Field'Max (1, Aft) - 1;
+ Fore := To'Length - 1 - Field'Max (1, Aft);
- -- Allow for Exp and two more for E+ or E- if exponent present
+ -- Allow for Exp and one more for E if exponent present
if Exp /= 0 then
- Fore := Fore - 2 - Exp;
+ Fore := Fore - 1 - Field'Max (2, Exp);
end if;
-- Make sure we have enough room
- if Fore < 1 then
+ if Fore < 1 + Boolean'Pos (Item < 0) then
raise Layout_Error;
end if;
-- Do the conversion and check length of result
- Set_Image_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
-
- if Ptr > To'Length then
- raise Layout_Error;
- else
- To := Buf (1 .. Ptr);
- end if;
- end Puts_Dec;
-
- --------------
- -- Puts_LLD --
- --------------
-
- procedure Puts_LLD
- (To : out String;
- Item : Long_Long_Integer;
- Aft : Field;
- Exp : Field;
- Scale : Integer)
- is
- Buf : String (1 .. Field'Last);
- Fore : Integer;
- Ptr : Natural := 0;
-
- begin
- Fore :=
- (if Exp = 0
- then To'Length - 1 - Aft
- else To'Length - 2 - Aft - Exp);
-
- if Fore < 1 then
- raise Layout_Error;
- end if;
-
- Set_Image_Long_Long_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
+ Set_Image (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
if Ptr > To'Length then
raise Layout_Error;
else
To := Buf (1 .. Ptr);
end if;
- end Puts_LLD;
+ end Puts;
end Ada.Wide_Text_IO.Decimal_Aux;
diff --git a/gcc/ada/libgnat/a-wtdeau.ads b/gcc/ada/libgnat/a-wtdeau.ads
index 0465455..5c0c4d6 100644
--- a/gcc/ada/libgnat/a-wtdeau.ads
+++ b/gcc/ada/libgnat/a-wtdeau.ads
@@ -29,63 +29,54 @@
-- --
------------------------------------------------------------------------------
--- This package contains the routines for Ada.Wide_Text_IO.Decimal_IO
--- that are shared among separate instantiations of this package. The
--- routines in the package are identical semantically to those declared
--- in Wide_Text_IO, except that default values have been supplied by the
--- generic, and the Num parameter has been replaced by Integer or
--- Long_Long_Integer, with an additional Scale parameter giving the
--- value of Num'Scale. In addition the Get routines return the value
--- rather than store it in an Out parameter.
+-- This package contains the implementation for Ada.Wide_Text_IO.Decimal_IO.
+-- Routines in this package are identical semantically to those in Decimal_IO,
+-- except that the default parameters have been removed because they are
+-- supplied explicitly by the calls from within these units, and there is an
+-- additional Scale parameter giving the value of Num'Scale. In addition the
+-- Get routines return the value rather than store it in an Out parameter.
-private package Ada.Wide_Text_IO.Decimal_Aux is
+private generic
+ type Int is range <>;
- function Get_Dec
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Integer;
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int;
- function Get_LLD
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Long_Long_Integer;
+ with procedure Set_Image
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
- function Gets_Dec
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Integer;
+package Ada.Wide_Text_IO.Decimal_Aux is
- function Gets_LLD
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Long_Long_Integer;
-
- procedure Put_Dec
+ function Get
(File : File_Type;
- Item : Integer;
- Fore : Field;
- Aft : Field;
- Exp : Field;
- Scale : Integer);
+ Width : Field;
+ Scale : Integer) return Int;
- procedure Put_LLD
+ procedure Put
(File : File_Type;
- Item : Long_Long_Integer;
+ Item : Int;
Fore : Field;
Aft : Field;
Exp : Field;
Scale : Integer);
- procedure Puts_Dec
- (To : out String;
- Item : Integer;
- Aft : Field;
- Exp : Field;
- Scale : Integer);
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Scale : Integer) return Int;
- procedure Puts_LLD
+ procedure Puts
(To : out String;
- Item : Long_Long_Integer;
+ Item : Int;
Aft : Field;
Exp : Field;
Scale : Integer);
diff --git a/gcc/ada/libgnat/a-wtdeio.adb b/gcc/ada/libgnat/a-wtdeio.adb
index 845a217..c503a20 100644
--- a/gcc/ada/libgnat/a-wtdeio.adb
+++ b/gcc/ada/libgnat/a-wtdeio.adb
@@ -30,16 +30,35 @@
------------------------------------------------------------------------------
with Ada.Wide_Text_IO.Decimal_Aux;
-
+with System.Img_Decimal_32; use System.Img_Decimal_32;
+with System.Img_Decimal_64; use System.Img_Decimal_64;
+with System.Val_Decimal_32; use System.Val_Decimal_32;
+with System.Val_Decimal_64; use System.Val_Decimal_64;
with System.WCh_Con; use System.WCh_Con;
with System.WCh_WtS; use System.WCh_WtS;
package body Ada.Wide_Text_IO.Decimal_IO is
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Aux32 is new
+ Ada.Wide_Text_IO.Decimal_Aux
+ (Int32,
+ Scan_Decimal32,
+ Set_Image_Decimal32);
- package Aux renames Ada.Wide_Text_IO.Decimal_Aux;
+ package Aux64 is new
+ Ada.Wide_Text_IO.Decimal_Aux
+ (Int64,
+ Scan_Decimal64,
+ Set_Image_Decimal64);
+
+ Need64 : constant Boolean := Num'Size > 32;
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is acceptable and where type Int64 is needed. This Boolean is used
+ -- to test for these cases and since it is a constant, only code for the
+ -- relevant case will be included in the instance.
Scale : constant Integer := Num'Scale;
@@ -52,12 +71,15 @@ package body Ada.Wide_Text_IO.Decimal_IO is
Item : out Num;
Width : Field := 0)
is
+ pragma Unsuppress (Range_Check);
+
begin
- if Num'Size > Integer'Size then
- Item := Num'Fixed_Value (Aux.Get_LLD (TFT (File), Width, Scale));
+ if Need64 then
+ Item := Num'Fixed_Value (Aux64.Get (File, Width, Scale));
else
- Item := Num'Fixed_Value (Aux.Get_Dec (TFT (File), Width, Scale));
+ Item := Num'Fixed_Value (Aux32.Get (File, Width, Scale));
end if;
+
exception
when Constraint_Error => raise Data_Error;
end Get;
@@ -67,7 +89,7 @@ package body Ada.Wide_Text_IO.Decimal_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -75,6 +97,8 @@ package body Ada.Wide_Text_IO.Decimal_IO is
Item : out Num;
Last : out Positive)
is
+ pragma Unsuppress (Range_Check);
+
S : constant String := Wide_String_To_String (From, WCEM_Upper);
-- String on which we do the actual conversion. Note that the method
-- used for wide character encoding is irrelevant, since if there is
@@ -82,16 +106,10 @@ package body Ada.Wide_Text_IO.Decimal_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- if Num'Size > Integer'Size then
- -- Item := Num'Fixed_Value
- -- should write above, but gets assert error ???
- Item := Num
- (Aux.Gets_LLD (S, Last'Unrestricted_Access, Scale));
+ if Need64 then
+ Item := Num'Fixed_Value (Aux64.Gets (S, Last, Scale));
else
- -- Item := Num'Fixed_Value
- -- should write above, but gets assert error ???
- Item := Num
- (Aux.Gets_Dec (S, Last'Unrestricted_Access, Scale));
+ Item := Num'Fixed_Value (Aux32.Gets (S, Last, Scale));
end if;
exception
@@ -110,13 +128,12 @@ package body Ada.Wide_Text_IO.Decimal_IO is
Exp : Field := Default_Exp)
is
begin
- if Num'Size > Integer'Size then
- Aux.Put_LLD
- (TFT (File), Long_Long_Integer'Integer_Value (Item),
- Fore, Aft, Exp, Scale);
+ if Need64 then
+ Aux64.Put
+ (File, Int64'Integer_Value (Item), Fore, Aft, Exp, Scale);
else
- Aux.Put_Dec
- (TFT (File), Integer'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ Aux32.Put
+ (File, Int32'Integer_Value (Item), Fore, Aft, Exp, Scale);
end if;
end Put;
@@ -127,7 +144,7 @@ package body Ada.Wide_Text_IO.Decimal_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -139,12 +156,10 @@ package body Ada.Wide_Text_IO.Decimal_IO is
S : String (To'First .. To'Last);
begin
- if Num'Size > Integer'Size then
- Aux.Puts_LLD
- (S, Long_Long_Integer'Integer_Value (Item), Aft, Exp, Scale);
-
+ if Need64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp, Scale);
else
- Aux.Puts_Dec (S, Integer'Integer_Value (Item), Aft, Exp, Scale);
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp, Scale);
end if;
for J in S'Range loop
diff --git a/gcc/ada/libgnat/a-wtdeio__128.adb b/gcc/ada/libgnat/a-wtdeio__128.adb
new file mode 100644
index 0000000..796c724
--- /dev/null
+++ b/gcc/ada/libgnat/a-wtdeio__128.adb
@@ -0,0 +1,190 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ T E X T _ I O . D E C I M A L _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Wide_Text_IO.Decimal_Aux;
+with System.Img_Decimal_32; use System.Img_Decimal_32;
+with System.Img_Decimal_64; use System.Img_Decimal_64;
+with System.Img_Decimal_128; use System.Img_Decimal_128;
+with System.Val_Decimal_32; use System.Val_Decimal_32;
+with System.Val_Decimal_64; use System.Val_Decimal_64;
+with System.Val_Decimal_128; use System.Val_Decimal_128;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
+
+package body Ada.Wide_Text_IO.Decimal_IO is
+
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Int64 is Interfaces.Integer_64;
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Aux32 is new
+ Ada.Wide_Text_IO.Decimal_Aux
+ (Int32,
+ Scan_Decimal32,
+ Set_Image_Decimal32);
+
+ package Aux64 is new
+ Ada.Wide_Text_IO.Decimal_Aux
+ (Int64,
+ Scan_Decimal64,
+ Set_Image_Decimal64);
+
+ package Aux128 is new
+ Ada.Wide_Text_IO.Decimal_Aux
+ (Int128,
+ Scan_Decimal128,
+ Set_Image_Decimal128);
+
+ Need64 : constant Boolean := Num'Size > 32;
+ Need128 : constant Boolean := Num'Size > 64;
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is acceptable, where type Int64 is acceptable and where an Int128
+ -- is needed. These boolean constants are used to test for these cases and
+ -- since it is a constant, only code for the relevant case will be included
+ -- in the instance.
+
+ Scale : constant Integer := Num'Scale;
+
+ ---------
+ -- Get --
+ ---------
+
+ procedure Get
+ (File : File_Type;
+ Item : out Num;
+ Width : Field := 0)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if Need128 then
+ Item := Num'Fixed_Value (Aux128.Get (File, Width, Scale));
+ elsif Need64 then
+ Item := Num'Fixed_Value (Aux64.Get (File, Width, Scale));
+ else
+ Item := Num'Fixed_Value (Aux32.Get (File, Width, Scale));
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ procedure Get
+ (Item : out Num;
+ Width : Field := 0)
+ is
+ begin
+ Get (Current_In, Item, Width);
+ end Get;
+
+ procedure Get
+ (From : Wide_String;
+ Item : out Num;
+ Last : out Positive)
+ is
+ pragma Unsuppress (Range_Check);
+
+ S : constant String := Wide_String_To_String (From, WCEM_Upper);
+ -- String on which we do the actual conversion. Note that the method
+ -- used for wide character encoding is irrelevant, since if there is
+ -- a character outside the Standard.Character range then the call to
+ -- Aux.Gets will raise Data_Error in any case.
+
+ begin
+ if Need128 then
+ Item := Num'Fixed_Value (Aux128.Gets (S, Last, Scale));
+ elsif Need64 then
+ Item := Num'Fixed_Value (Aux64.Gets (S, Last, Scale));
+ else
+ Item := Num'Fixed_Value (Aux32.Gets (S, Last, Scale));
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if Need128 then
+ Aux128.Put
+ (File, Int128'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ elsif Need64 then
+ Aux64.Put
+ (File, Int64'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ else
+ Aux32.Put
+ (File, Int32'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ end if;
+ end Put;
+
+ procedure Put
+ (Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ Put (Current_Out, Item, Fore, Aft, Exp);
+ end Put;
+
+ procedure Put
+ (To : out Wide_String;
+ Item : Num;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ S : String (To'First .. To'Last);
+
+ begin
+ if Need128 then
+ Aux128.Puts (S, Int128'Integer_Value (Item), Aft, Exp, Scale);
+ elsif Need64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp, Scale);
+ else
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp, Scale);
+ end if;
+
+ for J in S'Range loop
+ To (J) := Wide_Character'Val (Character'Pos (S (J)));
+ end loop;
+ end Put;
+
+end Ada.Wide_Text_IO.Decimal_IO;
diff --git a/gcc/ada/libgnat/a-wtenau.adb b/gcc/ada/libgnat/a-wtenau.adb
index 3fb6f76..6dcda30 100644
--- a/gcc/ada/libgnat/a-wtenau.adb
+++ b/gcc/ada/libgnat/a-wtenau.adb
@@ -36,9 +36,6 @@ with System.WCh_Con; use System.WCh_Con;
package body Ada.Wide_Text_IO.Enumeration_Aux is
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
-----------------------
-- Local Subprograms --
-----------------------
@@ -69,8 +66,8 @@ package body Ada.Wide_Text_IO.Enumeration_Aux is
begin
Buflen := 0;
- Load_Skip (TFT (File));
- ch := Nextc (TFT (File));
+ Load_Skip (File);
+ ch := Nextc (File);
-- Character literal case. If the initial character is a quote, then
-- we read as far as we can without backup (see ACVC test CE3905L)
@@ -79,7 +76,7 @@ package body Ada.Wide_Text_IO.Enumeration_Aux is
Get (File, WC);
Store_Char (WC, Buf, Buflen);
- ch := Nextc (TFT (File));
+ ch := Nextc (File);
if ch = LM or else ch = EOF then
return;
@@ -88,7 +85,7 @@ package body Ada.Wide_Text_IO.Enumeration_Aux is
Get (File, WC);
Store_Char (WC, Buf, Buflen);
- ch := Nextc (TFT (File));
+ ch := Nextc (File);
if ch /= Character'Pos (''') then
return;
@@ -117,7 +114,7 @@ package body Ada.Wide_Text_IO.Enumeration_Aux is
Get (File, WC);
Store_Char (WC, Buf, Buflen);
- ch := Nextc (TFT (File));
+ ch := Nextc (File);
exit when ch = EOF;
@@ -155,7 +152,7 @@ package body Ada.Wide_Text_IO.Enumeration_Aux is
Integer'Max (Integer (Width), Item'Length);
begin
- Check_On_One_Line (TFT (File), Actual_Width);
+ Check_On_One_Line (File, Actual_Width);
if Set = Lower_Case and then Item (Item'First) /= ''' then
declare
diff --git a/gcc/ada/libgnat/a-wtenio.adb b/gcc/ada/libgnat/a-wtenio.adb
index ee500f9..f89359c 100644
--- a/gcc/ada/libgnat/a-wtenio.adb
+++ b/gcc/ada/libgnat/a-wtenio.adb
@@ -51,7 +51,7 @@ package body Ada.Wide_Text_IO.Enumeration_IO is
procedure Get (Item : out Enum) is
begin
- Get (Current_Input, Item);
+ Get (Current_In, Item);
end Get;
procedure Get
@@ -88,7 +88,7 @@ package body Ada.Wide_Text_IO.Enumeration_IO is
Set : Type_Set := Default_Setting)
is
begin
- Put (Current_Output, Item, Width, Set);
+ Put (Current_Out, Item, Width, Set);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-wtfiau.adb b/gcc/ada/libgnat/a-wtfiau.adb
new file mode 100644
index 0000000..611b76d
--- /dev/null
+++ b/gcc/ada/libgnat/a-wtfiau.adb
@@ -0,0 +1,159 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ T E X T _ I O . F I X E D _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Wide_Text_IO.Generic_Aux; use Ada.Wide_Text_IO.Generic_Aux;
+
+package body Ada.Wide_Text_IO.Fixed_Aux is
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get
+ (File : File_Type;
+ Width : Field;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Buf : String (1 .. Field'Last);
+ Ptr : aliased Integer;
+ Stop : Integer := 0;
+ Item : Int;
+
+ begin
+ if Width /= 0 then
+ Load_Width (File, Width, Buf, Stop);
+ String_Skip (Buf, Ptr);
+ else
+ Load_Real (File, Buf, Stop);
+ Ptr := 1;
+ end if;
+
+ Item := Scan (Buf, Ptr'Access, Stop, Num, Den);
+ Check_End_Of_Field (Buf, Stop, Ptr, Width);
+ return Item;
+ end Get;
+
+ ----------
+ -- Gets --
+ ----------
+
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Pos : aliased Integer;
+ Item : Int;
+
+ begin
+ String_Skip (From, Pos);
+ Item := Scan (From, Pos'Access, From'Last, Num, Den);
+ Last := Pos - 1;
+ return Item;
+
+ exception
+ when Constraint_Error =>
+ Last := Pos - 1;
+ raise Data_Error;
+ end Gets;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Int;
+ Fore : Field;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ Buf : String (1 .. Field'Last);
+ Ptr : Natural := 0;
+
+ begin
+ Set_Image (Item, Buf, Ptr, Num, Den, For0, Aft0, Fore, Aft, Exp);
+ Put_Item (File, Buf (1 .. Ptr));
+ end Put;
+
+ ----------
+ -- Puts --
+ ----------
+
+ procedure Puts
+ (To : out String;
+ Item : Int;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ Buf : String (1 .. Positive'Max (Field'Last, To'Length));
+ Fore : Integer;
+ Ptr : Natural := 0;
+
+ begin
+ -- Compute Fore, allowing for the decimal dot and Aft digits
+
+ Fore := To'Length - 1 - Field'Max (1, Aft);
+
+ -- Allow for Exp and one more for E if exponent present
+
+ if Exp /= 0 then
+ Fore := Fore - 1 - Field'Max (2, Exp);
+ end if;
+
+ -- Make sure we have enough room
+
+ if Fore < 1 + Boolean'Pos (Item < 0) then
+ raise Layout_Error;
+ end if;
+
+ -- Do the conversion and check length of result
+
+ Set_Image (Item, Buf, Ptr, Num, Den, For0, Aft0, Fore, Aft, Exp);
+
+ if Ptr > To'Length then
+ raise Layout_Error;
+ else
+ To := Buf (1 .. Ptr);
+ end if;
+ end Puts;
+
+end Ada.Wide_Text_IO.Fixed_Aux;
diff --git a/gcc/ada/libgnat/a-wtfiau.ads b/gcc/ada/libgnat/a-wtfiau.ads
new file mode 100644
index 0000000..f487931
--- /dev/null
+++ b/gcc/ada/libgnat/a-wtfiau.ads
@@ -0,0 +1,97 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ T E X T _ I O . F I X E D _ I O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the implementation for Ada.Wide_Text_IO.Fixed_IO.
+-- Routines in this package are identical semantically to those in Fixed_IO,
+-- except that the default parameters have been removed because they are
+-- supplied explicitly by the calls from within these units, and there are
+-- additional Num and Den parameters giving the value of Num'Small, as well
+-- as For0 and Aft0 giving some properties of Num'Small. In addition the Get
+-- routines return the value rather than store it in an Out parameter.
+
+private generic
+ type Int is range <>;
+
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int;
+ Den : Int) return Int;
+
+ with procedure Set_Image
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+
+package Ada.Wide_Text_IO.Fixed_Aux is
+
+ function Get
+ (File : File_Type;
+ Width : Field;
+ Num : Int;
+ Den : Int) return Int;
+
+ procedure Put
+ (File : File_Type;
+ Item : Int;
+ Fore : Field;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Num : Int;
+ Den : Int) return Int;
+
+ procedure Puts
+ (To : out String;
+ Item : Int;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+
+end Ada.Wide_Text_IO.Fixed_Aux;
diff --git a/gcc/ada/libgnat/a-wtfiio.adb b/gcc/ada/libgnat/a-wtfiio.adb
index f70c8e4..e2537ae 100644
--- a/gcc/ada/libgnat/a-wtfiio.adb
+++ b/gcc/ada/libgnat/a-wtfiio.adb
@@ -2,7 +2,7 @@
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
--- A D A . T E X T _ I O . W I D E _ T E X T _ I O . F I X E D _ I O --
+-- A D A . W I D E _ T E X T _ I O . F I X E D _ I O --
-- --
-- B o d y --
-- --
@@ -29,16 +29,114 @@
-- --
------------------------------------------------------------------------------
+with Interfaces;
+with Ada.Wide_Text_IO.Fixed_Aux;
with Ada.Wide_Text_IO.Float_Aux;
-with System.WCh_Con; use System.WCh_Con;
-with System.WCh_WtS; use System.WCh_WtS;
+with System.Img_Fixed_32; use System.Img_Fixed_32;
+with System.Img_Fixed_64; use System.Img_Fixed_64;
+with System.Val_Fixed_32; use System.Val_Fixed_32;
+with System.Val_Fixed_64; use System.Val_Fixed_64;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
package body Ada.Wide_Text_IO.Fixed_IO is
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
+ -- Note: we still use the floating-point I/O routines for types whose small
+ -- is not the ratio of two sufficiently small integers. This will result in
+ -- inaccuracies for fixed point types that require more precision than is
+ -- available in Long_Long_Float.
- package Aux renames Ada.Wide_Text_IO.Float_Aux;
+ subtype Int32 is Interfaces.Integer_32; use type Int32;
+ subtype Int64 is Interfaces.Integer_64; use type Int64;
+
+ package Aux32 is new
+ Ada.Wide_Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32);
+
+ package Aux64 is new
+ Ada.Wide_Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64);
+
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is OK and where type Int64 is OK. These boolean constants are used
+ -- to test for this, such that only code for the relevant case is included
+ -- in the instance; that's why the computation of their value must be fully
+ -- static (although it is not a static expressions in the RM sense).
+
+ OK_Get_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator <= 2**27
+ and then Num'Small_Denominator <= 2**27));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**27)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**25));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator <= 2**59
+ and then Num'Small_Denominator <= 2**59));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**59)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**53));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ E : constant Natural := 63 - 32 * Boolean'Pos (OK_Put_32);
+ -- T'Size - 1 for the selected Int{32,64}
+
+ F0 : constant Natural := 0;
+ F1 : constant Natural :=
+ F0 + 18 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+18);
+ F2 : constant Natural :=
+ F1 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+9);
+ F3 : constant Natural :=
+ F2 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+5);
+ F4 : constant Natural :=
+ F3 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+3);
+ F5 : constant Natural :=
+ F4 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+2);
+ F6 : constant Natural :=
+ F5 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+1);
+ -- Binary search for the number of digits - 1 before the decimal point of
+ -- the product 2.0**E * Num'Small.
+
+ For0 : constant Natural := 2 + F6;
+ -- Fore value for the fixed point type whose mantissa is Int{32,64} and
+ -- whose small is Num'Small.
---------
-- Get --
@@ -49,8 +147,22 @@ package body Ada.Wide_Text_IO.Fixed_IO is
Item : out Num;
Width : Field := 0)
is
+ pragma Unsuppress (Range_Check);
+
begin
- Aux.Get (TFT (File), Long_Long_Float (Item), Width);
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -61,7 +173,7 @@ package body Ada.Wide_Text_IO.Fixed_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -69,6 +181,8 @@ package body Ada.Wide_Text_IO.Fixed_IO is
Item : out Num;
Last : out Positive)
is
+ pragma Unsuppress (Range_Check);
+
S : constant String := Wide_String_To_String (From, WCEM_Upper);
-- String on which we do the actual conversion. Note that the method
-- used for wide character encoding is irrelevant, since if there is
@@ -76,7 +190,19 @@ package body Ada.Wide_Text_IO.Fixed_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- Aux.Gets (S, Long_Long_Float (Item), Last);
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Gets (S, Long_Long_Float (Item), Last);
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -94,7 +220,18 @@ package body Ada.Wide_Text_IO.Fixed_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (TFT (File), Long_Long_Float (Item), Fore, Aft, Exp);
+ if OK_Put_32 then
+ Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
end Put;
procedure Put
@@ -104,7 +241,7 @@ package body Ada.Wide_Text_IO.Fixed_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -116,7 +253,17 @@ package body Ada.Wide_Text_IO.Fixed_IO is
S : String (To'First .. To'Last);
begin
- Aux.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ if OK_Put_32 then
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ end if;
for J in S'Range loop
To (J) := Wide_Character'Val (Character'Pos (S (J)));
diff --git a/gcc/ada/libgnat/a-wtfiio__128.adb b/gcc/ada/libgnat/a-wtfiio__128.adb
new file mode 100644
index 0000000..a5801be
--- /dev/null
+++ b/gcc/ada/libgnat/a-wtfiio__128.adb
@@ -0,0 +1,326 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ T E X T _ I O . F I X E D _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Interfaces;
+with Ada.Wide_Text_IO.Fixed_Aux;
+with Ada.Wide_Text_IO.Float_Aux;
+with System.Img_Fixed_32; use System.Img_Fixed_32;
+with System.Img_Fixed_64; use System.Img_Fixed_64;
+with System.Img_Fixed_128; use System.Img_Fixed_128;
+with System.Val_Fixed_32; use System.Val_Fixed_32;
+with System.Val_Fixed_64; use System.Val_Fixed_64;
+with System.Val_Fixed_128; use System.Val_Fixed_128;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
+
+package body Ada.Wide_Text_IO.Fixed_IO is
+
+ -- Note: we still use the floating-point I/O routines for types whose small
+ -- is not the ratio of two sufficiently small integers. This will result in
+ -- inaccuracies for fixed point types that require more precision than is
+ -- available in Long_Long_Float.
+
+ subtype Int32 is Interfaces.Integer_32; use type Int32;
+ subtype Int64 is Interfaces.Integer_64; use type Int64;
+ subtype Int128 is Interfaces.Integer_128; use type Int128;
+
+ package Aux32 is new
+ Ada.Wide_Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32);
+
+ package Aux64 is new
+ Ada.Wide_Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64);
+
+ package Aux128 is new
+ Ada.Wide_Text_IO.Fixed_Aux (Int128, Scan_Fixed128, Set_Image_Fixed128);
+
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is OK, where type Int64 is OK and where type Int128 is OK. These
+ -- boolean constants are used to test for this, such that only code for the
+ -- relevant case is included in the instance; that's why the computation of
+ -- their value must be fully static (although it is not a static expression
+ -- in the RM sense).
+
+ OK_Get_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator <= 2**27
+ and then Num'Small_Denominator <= 2**27));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**27)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**25));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator <= 2**59
+ and then Num'Small_Denominator <= 2**59));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**59)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**53));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_128 : constant Boolean :=
+ Num'Base'Object_Size <= 128
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**127)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**127)
+ or else
+ (Num'Small_Numerator <= 2**123
+ and then Num'Small_Denominator <= 2**123));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_128 : constant Boolean :=
+ Num'Base'Object_Size <= 128
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**127)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**127)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**123)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**122));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ E : constant Natural :=
+ 127 - 64 * Boolean'Pos (OK_Put_64) - 32 * Boolean'Pos (OK_Put_32);
+ -- T'Size - 1 for the selected Int{32,64,128}
+
+ F0 : constant Natural := 0;
+ F1 : constant Natural :=
+ F0 + 38 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+38);
+ F2 : constant Natural :=
+ F1 + 19 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+19);
+ F3 : constant Natural :=
+ F2 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+9);
+ F4 : constant Natural :=
+ F3 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+5);
+ F5 : constant Natural :=
+ F4 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+3);
+ F6 : constant Natural :=
+ F5 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+2);
+ F7 : constant Natural :=
+ F6 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F6) >= 1.0E+1);
+ -- Binary search for the number of digits - 1 before the decimal point of
+ -- the product 2.0**E * Num'Small.
+
+ For0 : constant Natural := 2 + F7;
+ -- Fore value for the fixed point type whose mantissa is Int{32,64,128} and
+ -- whose small is Num'Small.
+
+ ---------
+ -- Get --
+ ---------
+
+ procedure Get
+ (File : File_Type;
+ Item : out Num;
+ Width : Field := 0)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_128 then
+ Item := Num'Fixed_Value
+ (Aux128.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ procedure Get
+ (Item : out Num;
+ Width : Field := 0)
+ is
+ begin
+ Get (Current_In, Item, Width);
+ end Get;
+
+ procedure Get
+ (From : Wide_String;
+ Item : out Num;
+ Last : out Positive)
+ is
+ pragma Unsuppress (Range_Check);
+
+ S : constant String := Wide_String_To_String (From, WCEM_Upper);
+ -- String on which we do the actual conversion. Note that the method
+ -- used for wide character encoding is irrelevant, since if there is
+ -- a character outside the Standard.Character range then the call to
+ -- Aux.Gets will raise Data_Error in any case.
+
+ begin
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_128 then
+ Item := Num'Fixed_Value
+ (Aux128.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Gets (S, Long_Long_Float (Item), Last);
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if OK_Put_32 then
+ Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_128 then
+ Aux128.Put (File, Int128'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
+ end Put;
+
+ procedure Put
+ (Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ Put (Current_Out, Item, Fore, Aft, Exp);
+ end Put;
+
+ procedure Put
+ (To : out Wide_String;
+ Item : Num;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ S : String (To'First .. To'Last);
+
+ begin
+ if OK_Put_32 then
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_128 then
+ Aux128.Puts (S, Int128'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ end if;
+
+ for J in S'Range loop
+ To (J) := Wide_Character'Val (Character'Pos (S (J)));
+ end loop;
+ end Put;
+
+end Ada.Wide_Text_IO.Fixed_IO;
diff --git a/gcc/ada/libgnat/a-wtflau.adb b/gcc/ada/libgnat/a-wtflau.adb
index fd9ff1a..7db1b78 100644
--- a/gcc/ada/libgnat/a-wtflau.adb
+++ b/gcc/ada/libgnat/a-wtflau.adb
@@ -31,8 +31,7 @@
with Ada.Wide_Text_IO.Generic_Aux; use Ada.Wide_Text_IO.Generic_Aux;
-with System.Img_Real; use System.Img_Real;
-with System.Val_Real; use System.Val_Real;
+with System.Img_Real; use System.Img_Real;
package body Ada.Wide_Text_IO.Float_Aux is
@@ -42,12 +41,12 @@ package body Ada.Wide_Text_IO.Float_Aux is
procedure Get
(File : File_Type;
- Item : out Long_Long_Float;
+ Item : out Num;
Width : Field)
is
Buf : String (1 .. Field'Last);
Stop : Integer := 0;
- Ptr : aliased Integer := 1;
+ Ptr : aliased Integer;
begin
if Width /= 0 then
@@ -55,10 +54,10 @@ package body Ada.Wide_Text_IO.Float_Aux is
String_Skip (Buf, Ptr);
else
Load_Real (File, Buf, Stop);
+ Ptr := 1;
end if;
- Item := Scan_Real (Buf, Ptr'Access, Stop);
-
+ Item := Scan (Buf, Ptr'Access, Stop);
Check_End_Of_Field (Buf, Stop, Ptr, Width);
end Get;
@@ -68,137 +67,36 @@ package body Ada.Wide_Text_IO.Float_Aux is
procedure Gets
(From : String;
- Item : out Long_Long_Float;
+ Item : out Num;
Last : out Positive)
is
Pos : aliased Integer;
begin
String_Skip (From, Pos);
- Item := Scan_Real (From, Pos'Access, From'Last);
+ Item := Scan (From, Pos'Access, From'Last);
Last := Pos - 1;
exception
- when Constraint_Error =>
- raise Data_Error;
+ when Constraint_Error => raise Data_Error;
end Gets;
- ---------------
- -- Load_Real --
- ---------------
-
- procedure Load_Real
- (File : File_Type;
- Buf : out String;
- Ptr : in out Natural)
- is
- Loaded : Boolean;
-
- begin
- -- Skip initial blanks and load possible sign
-
- Load_Skip (File);
- Load (File, Buf, Ptr, '+', '-');
-
- -- Case of .nnnn
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Digits (File, Buf, Ptr, Loaded);
-
- -- Hopeless junk if no digits loaded
-
- if not Loaded then
- return;
- end if;
-
- -- Otherwise must have digits to start
-
- else
- Load_Digits (File, Buf, Ptr, Loaded);
-
- -- Hopeless junk if no digits loaded
-
- if not Loaded then
- return;
- end if;
-
- -- Deal with based case. We recognize either the standard '#' or the
- -- allowed alternative replacement ':' (see RM J.2(3)).
-
- Load (File, Buf, Ptr, '#', ':', Loaded);
-
- if Loaded then
-
- -- Case of nnn#.xxx#
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Extended_Digits (File, Buf, Ptr);
- Load (File, Buf, Ptr, '#', ':');
-
- -- Case of nnn#xxx.[xxx]# or nnn#xxx#
-
- else
- Load_Extended_Digits (File, Buf, Ptr);
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Extended_Digits (File, Buf, Ptr);
- end if;
-
- -- As usual, it seems strange to allow mixed base characters,
- -- but that is what ACVC tests expect, see CE3804M, case (3).
-
- Load (File, Buf, Ptr, '#', ':');
- end if;
-
- -- Case of nnn.[nnn] or nnn
-
- else
- -- Prevent the potential processing of '.' in cases where the
- -- initial digits have a trailing underscore.
-
- if Buf (Ptr) = '_' then
- return;
- end if;
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Digits (File, Buf, Ptr);
- end if;
- end if;
- end if;
-
- -- Deal with exponent
-
- Load (File, Buf, Ptr, 'E', 'e', Loaded);
-
- if Loaded then
- Load (File, Buf, Ptr, '+', '-');
- Load_Digits (File, Buf, Ptr);
- end if;
- end Load_Real;
-
---------
-- Put --
---------
procedure Put
(File : File_Type;
- Item : Long_Long_Float;
+ Item : Num;
Fore : Field;
Aft : Field;
Exp : Field)
is
- Buf : String (1 .. Field'Last);
+ Buf : String (1 .. Max_Real_Image_Length);
Ptr : Natural := 0;
begin
- Set_Image_Real (Item, Buf, Ptr, Fore, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (Item), Buf, Ptr, Fore, Aft, Exp);
Put_Item (File, Buf (1 .. Ptr));
end Put;
@@ -208,15 +106,16 @@ package body Ada.Wide_Text_IO.Float_Aux is
procedure Puts
(To : out String;
- Item : Long_Long_Float;
+ Item : Num;
Aft : Field;
Exp : Field)
is
- Buf : String (1 .. Field'Last);
+ Buf : String (1 .. Max_Real_Image_Length);
Ptr : Natural := 0;
begin
- Set_Image_Real (Item, Buf, Ptr, Fore => 1, Aft => Aft, Exp => Exp);
+ Set_Image_Real
+ (Long_Long_Float (Item), Buf, Ptr, Fore => 1, Aft => Aft, Exp => Exp);
if Ptr > To'Length then
raise Layout_Error;
diff --git a/gcc/ada/libgnat/a-wtflau.ads b/gcc/ada/libgnat/a-wtflau.ads
index 3598f77..82ace79 100644
--- a/gcc/ada/libgnat/a-wtflau.ads
+++ b/gcc/ada/libgnat/a-wtflau.ads
@@ -31,41 +31,42 @@
-- This package contains the routines for Ada.Wide_Text_IO.Float_IO that
-- are shared among separate instantiations of this package. The routines
--- in this package are identical semantically to those in Float_IO itself,
--- except that generic parameter Num has been replaced by Long_Long_Float,
--- and the default parameters have been removed because they are supplied
+-- in this package are identical semantically to those in Float_IO, except
+-- that the default parameters have been removed because they are supplied
-- explicitly by the calls from within the generic template. This package
--- is also used by Ada.Wide_Text_IO.Fixed_IO, Ada.Wide_Text_IO.Decimal_IO.
+-- is also used by Ada.Wide_Text_IO.Fixed_IO and Ada.Wide_Text_IO.Decimal_IO.
-private package Ada.Wide_Text_IO.Float_Aux is
+private generic
- procedure Load_Real
- (File : File_Type;
- Buf : out String;
- Ptr : in out Natural);
- -- This is an auxiliary routine that is used to load a possibly signed
- -- real literal value from the input file into Buf, starting at Ptr + 1.
+ type Num is digits <>;
+
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Num;
+
+package Ada.Wide_Text_IO.Float_Aux is
procedure Get
(File : File_Type;
- Item : out Long_Long_Float;
+ Item : out Num;
Width : Field);
- procedure Gets
- (From : String;
- Item : out Long_Long_Float;
- Last : out Positive);
-
procedure Put
(File : File_Type;
- Item : Long_Long_Float;
+ Item : Num;
Fore : Field;
Aft : Field;
Exp : Field);
+ procedure Gets
+ (From : String;
+ Item : out Num;
+ Last : out Positive);
+
procedure Puts
(To : out String;
- Item : Long_Long_Float;
+ Item : Num;
Aft : Field;
Exp : Field);
diff --git a/gcc/ada/libgnat/a-wtflio.adb b/gcc/ada/libgnat/a-wtflio.adb
index 5a36d88..3691786 100644
--- a/gcc/ada/libgnat/a-wtflio.adb
+++ b/gcc/ada/libgnat/a-wtflio.adb
@@ -30,16 +30,31 @@
------------------------------------------------------------------------------
with Ada.Wide_Text_IO.Float_Aux;
-
-with System.WCh_Con; use System.WCh_Con;
-with System.WCh_WtS; use System.WCh_WtS;
+with System.Val_Flt; use System.Val_Flt;
+with System.Val_LFlt; use System.Val_LFlt;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
package body Ada.Wide_Text_IO.Float_IO is
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
+ package Aux_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Float, Scan_Float);
+
+ package Aux_Long_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Long_Float, Scan_Long_Float);
+
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Float is OK, where type Long_Float is OK and where type Long_Long_Float
+ -- is needed. These boolean constants are used to test for this, such that
+ -- only code for the relevant case is included in the instance.
- package Aux renames Ada.Wide_Text_IO.Float_Aux;
+ OK_Float : constant Boolean := Num'Base'Digits <= Float'Digits;
+
+ OK_Long_Float : constant Boolean := Num'Base'Digits <= Long_Float'Digits;
---------
-- Get --
@@ -50,8 +65,25 @@ package body Ada.Wide_Text_IO.Float_IO is
Item : out Num;
Width : Field := 0)
is
+ pragma Unsuppress (Range_Check);
+
begin
- Aux.Get (TFT (File), Long_Long_Float (Item), Width);
+ if OK_Float then
+ Aux_Float.Get (File, Float (Item), Width);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Get (File, Long_Float (Item), Width);
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
+
+ -- In the case where the type is unconstrained (e.g. Standard'Float),
+ -- the above conversion may result in an infinite value, which is
+ -- normally fine for a conversion, but in this case, we want to treat
+ -- that as a data error.
+
+ if not Item'Valid then
+ raise Data_Error;
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -62,7 +94,7 @@ package body Ada.Wide_Text_IO.Float_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -70,6 +102,8 @@ package body Ada.Wide_Text_IO.Float_IO is
Item : out Num;
Last : out Positive)
is
+ pragma Unsuppress (Range_Check);
+
S : constant String := Wide_String_To_String (From, WCEM_Upper);
-- String on which we do the actual conversion. Note that the method
-- used for wide character encoding is irrelevant, since if there is
@@ -77,7 +111,22 @@ package body Ada.Wide_Text_IO.Float_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- Aux.Gets (S, Long_Long_Float (Item), Last);
+ if OK_Float then
+ Aux_Float.Gets (S, Float (Item), Last);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Gets (S, Long_Float (Item), Last);
+ else
+ Aux_Long_Long_Float.Gets (S, Long_Long_Float (Item), Last);
+ end if;
+
+ -- In the case where the type is unconstrained (e.g. Standard'Float),
+ -- the above conversion may result in an infinite value, which is
+ -- normally fine for a conversion, but in this case, we want to treat
+ -- that as a data error.
+
+ if not Item'Valid then
+ raise Data_Error;
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -95,7 +144,14 @@ package body Ada.Wide_Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (TFT (File), Long_Long_Float (Item), Fore, Aft, Exp);
+ if OK_Float then
+ Aux_Float.Put (File, Float (Item), Fore, Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Put (File, Long_Float (Item), Fore, Aft, Exp);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
end Put;
procedure Put
@@ -105,7 +161,7 @@ package body Ada.Wide_Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -117,7 +173,13 @@ package body Ada.Wide_Text_IO.Float_IO is
S : String (To'First .. To'Last);
begin
- Aux.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ if OK_Float then
+ Aux_Float.Puts (S, Float (Item), Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Puts (S, Long_Float (Item), Aft, Exp);
+ else
+ Aux_Long_Long_Float.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ end if;
for J in S'Range loop
To (J) := Wide_Character'Val (Character'Pos (S (J)));
diff --git a/gcc/ada/libgnat/a-wtgeau.adb b/gcc/ada/libgnat/a-wtgeau.adb
index 9d24070..bc9b459 100644
--- a/gcc/ada/libgnat/a-wtgeau.adb
+++ b/gcc/ada/libgnat/a-wtgeau.adb
@@ -403,6 +403,106 @@ package body Ada.Wide_Text_IO.Generic_Aux is
end Load_Integer;
---------------
+ -- Load_Real --
+ ---------------
+
+ procedure Load_Real
+ (File : File_Type;
+ Buf : out String;
+ Ptr : in out Natural)
+ is
+ Loaded : Boolean;
+
+ begin
+ -- Skip initial blanks and load possible sign
+
+ Load_Skip (File);
+ Load (File, Buf, Ptr, '+', '-');
+
+ -- Case of .nnnn
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Digits (File, Buf, Ptr, Loaded);
+
+ -- Hopeless junk if no digits loaded
+
+ if not Loaded then
+ return;
+ end if;
+
+ -- Otherwise must have digits to start
+
+ else
+ Load_Digits (File, Buf, Ptr, Loaded);
+
+ -- Hopeless junk if no digits loaded
+
+ if not Loaded then
+ return;
+ end if;
+
+ -- Deal with based case. We recognize either the standard '#' or the
+ -- allowed alternative replacement ':' (see RM J.2(3)).
+
+ Load (File, Buf, Ptr, '#', ':', Loaded);
+
+ if Loaded then
+
+ -- Case of nnn#.xxx#
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Extended_Digits (File, Buf, Ptr);
+ Load (File, Buf, Ptr, '#', ':');
+
+ -- Case of nnn#xxx.[xxx]# or nnn#xxx#
+
+ else
+ Load_Extended_Digits (File, Buf, Ptr);
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Extended_Digits (File, Buf, Ptr);
+ end if;
+
+ -- As usual, it seems strange to allow mixed base characters,
+ -- but that is what ACVC tests expect, see CE3804M, case (3).
+
+ Load (File, Buf, Ptr, '#', ':');
+ end if;
+
+ -- Case of nnn.[nnn] or nnn
+
+ else
+ -- Prevent the potential processing of '.' in cases where the
+ -- initial digits have a trailing underscore.
+
+ if Buf (Ptr) = '_' then
+ return;
+ end if;
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Digits (File, Buf, Ptr);
+ end if;
+ end if;
+ end if;
+
+ -- Deal with exponent
+
+ Load (File, Buf, Ptr, 'E', 'e', Loaded);
+
+ if Loaded then
+ Load (File, Buf, Ptr, '+', '-');
+ Load_Digits (File, Buf, Ptr);
+ end if;
+ end Load_Real;
+
+ ---------------
-- Load_Skip --
---------------
diff --git a/gcc/ada/libgnat/a-wtgeau.ads b/gcc/ada/libgnat/a-wtgeau.ads
index 9577ac2..7c89971 100644
--- a/gcc/ada/libgnat/a-wtgeau.ads
+++ b/gcc/ada/libgnat/a-wtgeau.ads
@@ -155,6 +155,12 @@ package Ada.Wide_Text_IO.Generic_Aux is
Ptr : in out Natural);
-- Loads a possibly signed integer literal value
+ procedure Load_Real
+ (File : File_Type;
+ Buf : out String;
+ Ptr : in out Natural);
+ -- Loads a possibly signed real literal value
+
procedure Put_Item (File : File_Type; Str : String);
-- This routine is like Wide_Text_IO.Put, except that it checks for
-- overflow of bounded lines, as described in (RM A.10.6(8)). It is used
diff --git a/gcc/ada/libgnat/a-wtinio.adb b/gcc/ada/libgnat/a-wtinio.adb
index a3f666e..b322433 100644
--- a/gcc/ada/libgnat/a-wtinio.adb
+++ b/gcc/ada/libgnat/a-wtinio.adb
@@ -65,9 +65,6 @@ package body Ada.Wide_Text_IO.Integer_IO is
-- Boolean is used to test for these cases and since it is a constant, only
-- code for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -84,9 +81,9 @@ package body Ada.Wide_Text_IO.Integer_IO is
begin
if Need_LLI then
- Aux_LLI.Get (TFT (File), Long_Long_Integer (Item), Width);
+ Aux_LLI.Get (File, Long_Long_Integer (Item), Width);
else
- Aux_Int.Get (TFT (File), Integer (Item), Width);
+ Aux_Int.Get (File, Integer (Item), Width);
end if;
exception
@@ -98,7 +95,7 @@ package body Ada.Wide_Text_IO.Integer_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -140,9 +137,9 @@ package body Ada.Wide_Text_IO.Integer_IO is
is
begin
if Need_LLI then
- Aux_LLI.Put (TFT (File), Long_Long_Integer (Item), Width, Base);
+ Aux_LLI.Put (File, Long_Long_Integer (Item), Width, Base);
else
- Aux_Int.Put (TFT (File), Integer (Item), Width, Base);
+ Aux_Int.Put (File, Integer (Item), Width, Base);
end if;
end Put;
@@ -152,7 +149,7 @@ package body Ada.Wide_Text_IO.Integer_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-wtinio__128.adb b/gcc/ada/libgnat/a-wtinio__128.adb
index edc78c3..0eea7b5 100644
--- a/gcc/ada/libgnat/a-wtinio__128.adb
+++ b/gcc/ada/libgnat/a-wtinio__128.adb
@@ -79,9 +79,6 @@ package body Ada.Wide_Text_IO.Integer_IO is
-- are used to test for these cases and since they are constant, only code
-- for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -98,11 +95,11 @@ package body Ada.Wide_Text_IO.Integer_IO is
begin
if Need_LLLI then
- Aux_LLLI.Get (TFT (File), Long_Long_Long_Integer (Item), Width);
+ Aux_LLLI.Get (File, Long_Long_Long_Integer (Item), Width);
elsif Need_LLI then
- Aux_LLI.Get (TFT (File), Long_Long_Integer (Item), Width);
+ Aux_LLI.Get (File, Long_Long_Integer (Item), Width);
else
- Aux_Int.Get (TFT (File), Integer (Item), Width);
+ Aux_Int.Get (File, Integer (Item), Width);
end if;
exception
@@ -114,7 +111,7 @@ package body Ada.Wide_Text_IO.Integer_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -158,11 +155,11 @@ package body Ada.Wide_Text_IO.Integer_IO is
is
begin
if Need_LLLI then
- Aux_LLLI.Put (TFT (File), Long_Long_Long_Integer (Item), Width, Base);
+ Aux_LLLI.Put (File, Long_Long_Long_Integer (Item), Width, Base);
elsif Need_LLI then
- Aux_LLI.Put (TFT (File), Long_Long_Integer (Item), Width, Base);
+ Aux_LLI.Put (File, Long_Long_Integer (Item), Width, Base);
else
- Aux_Int.Put (TFT (File), Integer (Item), Width, Base);
+ Aux_Int.Put (File, Integer (Item), Width, Base);
end if;
end Put;
@@ -172,7 +169,7 @@ package body Ada.Wide_Text_IO.Integer_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-wtmoio.adb b/gcc/ada/libgnat/a-wtmoio.adb
index 702dcbb..efab035 100644
--- a/gcc/ada/libgnat/a-wtmoio.adb
+++ b/gcc/ada/libgnat/a-wtmoio.adb
@@ -65,9 +65,6 @@ package body Ada.Wide_Text_IO.Modular_IO is
-- Boolean is used to test for these cases and since it is a constant, only
-- code for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -83,9 +80,9 @@ package body Ada.Wide_Text_IO.Modular_IO is
begin
if Need_LLU then
- Aux_LLU.Get (TFT (File), Long_Long_Unsigned (Item), Width);
+ Aux_LLU.Get (File, Long_Long_Unsigned (Item), Width);
else
- Aux_Uns.Get (TFT (File), Unsigned (Item), Width);
+ Aux_Uns.Get (File, Unsigned (Item), Width);
end if;
exception
@@ -97,7 +94,7 @@ package body Ada.Wide_Text_IO.Modular_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -138,9 +135,9 @@ package body Ada.Wide_Text_IO.Modular_IO is
is
begin
if Need_LLU then
- Aux_LLU.Put (TFT (File), Long_Long_Unsigned (Item), Width, Base);
+ Aux_LLU.Put (File, Long_Long_Unsigned (Item), Width, Base);
else
- Aux_Uns.Put (TFT (File), Unsigned (Item), Width, Base);
+ Aux_Uns.Put (File, Unsigned (Item), Width, Base);
end if;
end Put;
@@ -150,7 +147,7 @@ package body Ada.Wide_Text_IO.Modular_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-wtmoio__128.adb b/gcc/ada/libgnat/a-wtmoio__128.adb
index 661faec..a32eaf2 100644
--- a/gcc/ada/libgnat/a-wtmoio__128.adb
+++ b/gcc/ada/libgnat/a-wtmoio__128.adb
@@ -79,9 +79,6 @@ package body Ada.Wide_Text_IO.Modular_IO is
-- are used to test for these cases and since they are constant, only code
-- for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -99,9 +96,9 @@ package body Ada.Wide_Text_IO.Modular_IO is
if Need_LLLU then
Aux_LLLU.Get (File, Long_Long_Long_Unsigned (Item), Width);
elsif Need_LLU then
- Aux_LLU.Get (TFT (File), Long_Long_Unsigned (Item), Width);
+ Aux_LLU.Get (File, Long_Long_Unsigned (Item), Width);
else
- Aux_Uns.Get (TFT (File), Unsigned (Item), Width);
+ Aux_Uns.Get (File, Unsigned (Item), Width);
end if;
exception
@@ -113,7 +110,7 @@ package body Ada.Wide_Text_IO.Modular_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -158,9 +155,9 @@ package body Ada.Wide_Text_IO.Modular_IO is
if Need_LLLU then
Aux_LLLU.Put (File, Long_Long_Long_Unsigned (Item), Width, Base);
elsif Need_LLU then
- Aux_LLU.Put (TFT (File), Long_Long_Unsigned (Item), Width, Base);
+ Aux_LLU.Put (File, Long_Long_Unsigned (Item), Width, Base);
else
- Aux_Uns.Put (TFT (File), Unsigned (Item), Width, Base);
+ Aux_Uns.Put (File, Unsigned (Item), Width, Base);
end if;
end Put;
@@ -170,7 +167,7 @@ package body Ada.Wide_Text_IO.Modular_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-ztcoau.adb b/gcc/ada/libgnat/a-ztcoau.adb
index ffe0a90..bb33680 100644
--- a/gcc/ada/libgnat/a-ztcoau.adb
+++ b/gcc/ada/libgnat/a-ztcoau.adb
@@ -30,22 +30,19 @@
------------------------------------------------------------------------------
with Ada.Wide_Wide_Text_IO.Generic_Aux; use Ada.Wide_Wide_Text_IO.Generic_Aux;
-with Ada.Wide_Wide_Text_IO.Float_Aux;
with System.Img_Real; use System.Img_Real;
package body Ada.Wide_Wide_Text_IO.Complex_Aux is
- package Aux renames Ada.Wide_Wide_Text_IO.Float_Aux;
-
---------
-- Get --
---------
procedure Get
(File : File_Type;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Width : Field)
is
Buf : String (1 .. Field'Last);
@@ -95,8 +92,8 @@ package body Ada.Wide_Wide_Text_IO.Complex_Aux is
procedure Gets
(From : String;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Last : out Positive)
is
Paren : Boolean;
@@ -139,8 +136,8 @@ package body Ada.Wide_Wide_Text_IO.Complex_Aux is
procedure Put
(File : File_Type;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Fore : Field;
Aft : Field;
Exp : Field)
@@ -159,8 +156,8 @@ package body Ada.Wide_Wide_Text_IO.Complex_Aux is
procedure Puts
(To : out String;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Aft : Field;
Exp : Field)
is
@@ -174,9 +171,9 @@ package body Ada.Wide_Wide_Text_IO.Complex_Aux is
-- Both parts are initially converted with a Fore of 0
Rptr := 0;
- Set_Image_Real (ItemR, R_String, Rptr, 0, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (ItemR), R_String, Rptr, 0, Aft, Exp);
Iptr := 0;
- Set_Image_Real (ItemI, I_String, Iptr, 0, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (ItemI), I_String, Iptr, 0, Aft, Exp);
-- Check room for both parts plus parens plus comma (RM G.1.3(34))
diff --git a/gcc/ada/libgnat/a-ztcoau.ads b/gcc/ada/libgnat/a-ztcoau.ads
index b68c38b..43546d8 100644
--- a/gcc/ada/libgnat/a-ztcoau.ads
+++ b/gcc/ada/libgnat/a-ztcoau.ads
@@ -15,38 +15,45 @@
-- This package contains the routines for Ada.Wide_Wide_Text_IO.Complex_IO
-- that are shared among separate instantiations of this package. The routines
--- in this package are identical semantically to those in Complex_IO itself,
--- except that the generic parameter Complex has been replaced by separate
--- real and imaginary values of type Long_Long_Float, and default parameters
--- have been removed because they are supplied explicitly by the calls from
--- within the generic template.
+-- in this package are identical semantically to those in Complex_IO, except
+-- that the generic parameter Complex has been replaced by separate real and
+-- imaginary parameters, and default parameters have been removed because they
+-- are supplied explicitly by the calls from within the generic template.
+
+with Ada.Wide_Wide_Text_IO.Float_Aux;
+
+private generic
+
+ type Num is digits <>;
+
+ with package Aux is new Ada.Wide_Wide_Text_IO.Float_Aux (Num, <>);
package Ada.Wide_Wide_Text_IO.Complex_Aux is
procedure Get
(File : File_Type;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
+ ItemR : out Num;
+ ItemI : out Num;
Width : Field);
- procedure Gets
- (From : String;
- ItemR : out Long_Long_Float;
- ItemI : out Long_Long_Float;
- Last : out Positive);
-
procedure Put
(File : File_Type;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Fore : Field;
Aft : Field;
Exp : Field);
+ procedure Gets
+ (From : String;
+ ItemR : out Num;
+ ItemI : out Num;
+ Last : out Positive);
+
procedure Puts
(To : out String;
- ItemR : Long_Long_Float;
- ItemI : Long_Long_Float;
+ ItemR : Num;
+ ItemI : Num;
Aft : Field;
Exp : Field);
diff --git a/gcc/ada/libgnat/a-ztcoio.adb b/gcc/ada/libgnat/a-ztcoio.adb
index ead1234..5103191 100644
--- a/gcc/ada/libgnat/a-ztcoio.adb
+++ b/gcc/ada/libgnat/a-ztcoio.adb
@@ -30,24 +30,46 @@
------------------------------------------------------------------------------
with Ada.Wide_Wide_Text_IO.Complex_Aux;
-
-with System.WCh_Con; use System.WCh_Con;
-with System.WCh_WtS; use System.WCh_WtS;
+with Ada.Wide_Wide_Text_IO.Float_Aux;
+with System.Val_Flt; use System.Val_Flt;
+with System.Val_LFlt; use System.Val_LFlt;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
with Ada.Unchecked_Conversion;
package body Ada.Wide_Wide_Text_IO.Complex_IO is
- package Aux renames Ada.Wide_Wide_Text_IO.Complex_Aux;
+ use Complex_Types;
+
+ package Scalar_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Float, Scan_Float);
+
+ package Scalar_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Long_Float, Scan_Long_Float);
+
+ package Scalar_Long_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ package Aux_Float is new
+ Ada.Wide_Wide_Text_IO.Complex_Aux (Float, Scalar_Float);
- subtype LLF is Long_Long_Float;
- -- Type used for calls to routines in Aux
+ package Aux_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Complex_Aux (Long_Float, Scalar_Long_Float);
- function TFT is new
- Ada.Unchecked_Conversion (File_Type, Ada.Wide_Wide_Text_IO.File_Type);
- -- This unchecked conversion is to get around a visibility bug in
- -- GNAT version 2.04w. It should be possible to simply use the
- -- subtype declared above and do normal checked conversions.
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Complex_Aux
+ (Long_Long_Float, Scalar_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Float is OK, where type Long_Float is OK and where type Long_Long_Float
+ -- is needed. These boolean constants are used to test for this, such that
+ -- only code for the relevant case is included in the instance.
+
+ OK_Float : constant Boolean := Real'Base'Digits <= Float'Digits;
+
+ OK_Long_Float : constant Boolean := Real'Base'Digits <= Long_Float'Digits;
---------
-- Get --
@@ -62,7 +84,17 @@ package body Ada.Wide_Wide_Text_IO.Complex_IO is
Imag_Item : Real'Base;
begin
- Aux.Get (TFT (File), LLF (Real_Item), LLF (Imag_Item), Width);
+ if OK_Float then
+ Aux_Float.Get (File, Float (Real_Item), Float (Imag_Item), Width);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Get
+ (File, Long_Float (Real_Item), Long_Float (Imag_Item), Width);
+ else
+ Aux_Long_Long_Float.Get
+ (File, Long_Long_Float (Real_Item), Long_Long_Float (Imag_Item),
+ Width);
+ end if;
+
Item := (Real_Item, Imag_Item);
exception
@@ -78,7 +110,7 @@ package body Ada.Wide_Wide_Text_IO.Complex_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
---------
@@ -100,7 +132,17 @@ package body Ada.Wide_Wide_Text_IO.Complex_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- Aux.Gets (S, LLF (Real_Item), LLF (Imag_Item), Last);
+ if OK_Float then
+ Aux_Float.Gets (S, Float (Real_Item), Float (Imag_Item), Last);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Gets
+ (S, Long_Float (Real_Item), Long_Float (Imag_Item), Last);
+ else
+ Aux_Long_Long_Float.Gets
+ (S, Long_Long_Float (Real_Item), Long_Long_Float (Imag_Item),
+ Last);
+ end if;
+
Item := (Real_Item, Imag_Item);
exception
@@ -119,7 +161,18 @@ package body Ada.Wide_Wide_Text_IO.Complex_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (TFT (File), LLF (Re (Item)), LLF (Im (Item)), Fore, Aft, Exp);
+ if OK_Float then
+ Aux_Float.Put
+ (File, Float (Re (Item)), Float (Im (Item)), Fore, Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Put
+ (File, Long_Float (Re (Item)), Long_Float (Im (Item)), Fore, Aft,
+ Exp);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Re (Item)), Long_Long_Float (Im (Item)),
+ Fore, Aft, Exp);
+ end if;
end Put;
---------
@@ -133,7 +186,7 @@ package body Ada.Wide_Wide_Text_IO.Complex_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
---------
@@ -149,7 +202,16 @@ package body Ada.Wide_Wide_Text_IO.Complex_IO is
S : String (To'First .. To'Last);
begin
- Aux.Puts (S, LLF (Re (Item)), LLF (Im (Item)), Aft, Exp);
+ if OK_Float then
+ Aux_Float.Puts (S, Float (Re (Item)), Float (Im (Item)), Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Puts
+ (S, Long_Float (Re (Item)), Long_Float (Im (Item)), Aft, Exp);
+ else
+ Aux_Long_Long_Float.Puts
+ (S, Long_Long_Float (Re (Item)), Long_Long_Float (Im (Item)),
+ Aft, Exp);
+ end if;
for J in S'Range loop
To (J) := Wide_Wide_Character'Val (Character'Pos (S (J)));
diff --git a/gcc/ada/libgnat/a-ztcoio.ads b/gcc/ada/libgnat/a-ztcoio.ads
index 866fd87..2a08153 100644
--- a/gcc/ada/libgnat/a-ztcoio.ads
+++ b/gcc/ada/libgnat/a-ztcoio.ads
@@ -23,39 +23,39 @@ package Ada.Wide_Wide_Text_IO.Complex_IO is
use Complex_Types;
Default_Fore : Field := 2;
- Default_Aft : Field := Real'Digits - 1;
+ Default_Aft : Field := Complex_Types.Real'Digits - 1;
Default_Exp : Field := 3;
procedure Get
(File : File_Type;
- Item : out Complex;
+ Item : out Complex_Types.Complex;
Width : Field := 0);
procedure Get
- (Item : out Complex;
+ (Item : out Complex_Types.Complex;
Width : Field := 0);
procedure Put
(File : File_Type;
- Item : Complex;
+ Item : Complex_Types.Complex;
Fore : Field := Default_Fore;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp);
procedure Put
- (Item : Complex;
+ (Item : Complex_Types.Complex;
Fore : Field := Default_Fore;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp);
procedure Get
(From : Wide_Wide_String;
- Item : out Complex;
+ Item : out Complex_Types.Complex;
Last : out Positive);
procedure Put
(To : out Wide_Wide_String;
- Item : Complex;
+ Item : Complex_Types.Complex;
Aft : Field := Default_Aft;
Exp : Field := Default_Exp);
diff --git a/gcc/ada/libgnat/a-ztdeau.adb b/gcc/ada/libgnat/a-ztdeau.adb
index 3daff0f..ec6431b 100644
--- a/gcc/ada/libgnat/a-ztdeau.adb
+++ b/gcc/ada/libgnat/a-ztdeau.adb
@@ -30,56 +30,22 @@
------------------------------------------------------------------------------
with Ada.Wide_Wide_Text_IO.Generic_Aux; use Ada.Wide_Wide_Text_IO.Generic_Aux;
-with Ada.Wide_Wide_Text_IO.Float_Aux; use Ada.Wide_Wide_Text_IO.Float_Aux;
-
-with System.Img_Dec; use System.Img_Dec;
-with System.Img_LLD; use System.Img_LLD;
-with System.Val_Dec; use System.Val_Dec;
-with System.Val_LLD; use System.Val_LLD;
package body Ada.Wide_Wide_Text_IO.Decimal_Aux is
- -------------
- -- Get_Dec --
- -------------
-
- function Get_Dec
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Integer
- is
- Buf : String (1 .. Field'Last);
- Ptr : aliased Integer;
- Stop : Integer := 0;
- Item : Integer;
-
- begin
- if Width /= 0 then
- Load_Width (File, Width, Buf, Stop);
- String_Skip (Buf, Ptr);
- else
- Load_Real (File, Buf, Stop);
- Ptr := 1;
- end if;
-
- Item := Scan_Decimal (Buf, Ptr'Access, Stop, Scale);
- Check_End_Of_Field (Buf, Stop, Ptr, Width);
- return Item;
- end Get_Dec;
-
- -------------
- -- Get_LLD --
- -------------
+ ---------
+ -- Get --
+ ---------
- function Get_LLD
+ function Get
(File : File_Type;
Width : Field;
- Scale : Integer) return Long_Long_Integer
+ Scale : Integer) return Int
is
Buf : String (1 .. Field'Last);
Ptr : aliased Integer;
Stop : Integer := 0;
- Item : Long_Long_Integer;
+ Item : Int;
begin
if Width /= 0 then
@@ -90,68 +56,42 @@ package body Ada.Wide_Wide_Text_IO.Decimal_Aux is
Ptr := 1;
end if;
- Item := Scan_Long_Long_Decimal (Buf, Ptr'Access, Stop, Scale);
+ Item := Scan (Buf, Ptr'Access, Stop, Scale);
Check_End_Of_Field (Buf, Stop, Ptr, Width);
return Item;
- end Get_LLD;
-
- --------------
- -- Gets_Dec --
- --------------
-
- function Gets_Dec
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Integer
- is
- Pos : aliased Integer;
- Item : Integer;
-
- begin
- String_Skip (From, Pos);
- Item := Scan_Decimal (From, Pos'Access, From'Last, Scale);
- Last.all := Pos - 1;
- return Item;
+ end Get;
- exception
- when Constraint_Error =>
- Last.all := Pos - 1;
- raise Data_Error;
-
- end Gets_Dec;
+ ----------
+ -- Gets --
+ ----------
- --------------
- -- Gets_LLD --
- --------------
-
- function Gets_LLD
+ function Gets
(From : String;
- Last : not null access Positive;
- Scale : Integer) return Long_Long_Integer
+ Last : out Positive;
+ Scale : Integer) return Int
is
Pos : aliased Integer;
- Item : Long_Long_Integer;
+ Item : Int;
begin
String_Skip (From, Pos);
- Item := Scan_Long_Long_Decimal (From, Pos'Access, From'Last, Scale);
- Last.all := Pos - 1;
+ Item := Scan (From, Pos'Access, From'Last, Scale);
+ Last := Pos - 1;
return Item;
exception
when Constraint_Error =>
- Last.all := Pos - 1;
+ Last := Pos - 1;
raise Data_Error;
+ end Gets;
- end Gets_LLD;
-
- -------------
- -- Put_Dec --
- -------------
+ ---------
+ -- Put --
+ ---------
- procedure Put_Dec
+ procedure Put
(File : File_Type;
- Item : Integer;
+ Item : Int;
Fore : Field;
Aft : Field;
Exp : Field;
@@ -161,103 +101,51 @@ package body Ada.Wide_Wide_Text_IO.Decimal_Aux is
Ptr : Natural := 0;
begin
- Set_Image_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
+ Set_Image (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
Put_Item (File, Buf (1 .. Ptr));
- end Put_Dec;
+ end Put;
- -------------
- -- Put_LLD --
- -------------
+ ----------
+ -- Puts --
+ ----------
- procedure Put_LLD
- (File : File_Type;
- Item : Long_Long_Integer;
- Fore : Field;
- Aft : Field;
- Exp : Field;
- Scale : Integer)
- is
- Buf : String (1 .. Field'Last);
- Ptr : Natural := 0;
-
- begin
- Set_Image_Long_Long_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
- Put_Item (File, Buf (1 .. Ptr));
- end Put_LLD;
-
- --------------
- -- Puts_Dec --
- --------------
-
- procedure Puts_Dec
+ procedure Puts
(To : out String;
- Item : Integer;
+ Item : Int;
Aft : Field;
Exp : Field;
Scale : Integer)
is
- Buf : String (1 .. Field'Last);
+ Buf : String (1 .. Positive'Max (Field'Last, To'Length));
Fore : Integer;
Ptr : Natural := 0;
begin
- -- Compute Fore, allowing for Aft digits and the decimal dot
+ -- Compute Fore, allowing for the decimal dot and Aft digits
- Fore := To'Length - Field'Max (1, Aft) - 1;
+ Fore := To'Length - 1 - Field'Max (1, Aft);
- -- Allow for Exp and two more for E+ or E- if exponent present
+ -- Allow for Exp and one more for E if exponent present
if Exp /= 0 then
- Fore := Fore - 2 - Exp;
+ Fore := Fore - 1 - Field'Max (2, Exp);
end if;
-- Make sure we have enough room
- if Fore < 1 then
+ if Fore < 1 + Boolean'Pos (Item < 0) then
raise Layout_Error;
end if;
-- Do the conversion and check length of result
- Set_Image_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
-
- if Ptr > To'Length then
- raise Layout_Error;
- else
- To := Buf (1 .. Ptr);
- end if;
- end Puts_Dec;
-
- --------------
- -- Puts_LLD --
- --------------
-
- procedure Puts_LLD
- (To : out String;
- Item : Long_Long_Integer;
- Aft : Field;
- Exp : Field;
- Scale : Integer)
- is
- Buf : String (1 .. Field'Last);
- Fore : Integer;
- Ptr : Natural := 0;
-
- begin
- Fore :=
- (if Exp = 0 then To'Length - 1 - Aft else To'Length - 2 - Aft - Exp);
-
- if Fore < 1 then
- raise Layout_Error;
- end if;
-
- Set_Image_Long_Long_Decimal (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
+ Set_Image (Item, Buf, Ptr, Scale, Fore, Aft, Exp);
if Ptr > To'Length then
raise Layout_Error;
else
To := Buf (1 .. Ptr);
end if;
- end Puts_LLD;
+ end Puts;
end Ada.Wide_Wide_Text_IO.Decimal_Aux;
diff --git a/gcc/ada/libgnat/a-ztdeau.ads b/gcc/ada/libgnat/a-ztdeau.ads
index b493b80..962f479 100644
--- a/gcc/ada/libgnat/a-ztdeau.ads
+++ b/gcc/ada/libgnat/a-ztdeau.ads
@@ -29,63 +29,54 @@
-- --
------------------------------------------------------------------------------
--- This package contains the routines for Ada.Wide_Wide_Text_IO.Decimal_IO
--- that are shared among separate instantiations of this package. The
--- routines in the package are identical semantically to those declared
--- in Wide_Wide_Text_IO, except that default values have been supplied by the
--- generic, and the Num parameter has been replaced by Integer or
--- Long_Long_Integer, with an additional Scale parameter giving the
--- value of Num'Scale. In addition the Get routines return the value
--- rather than store it in an Out parameter.
+-- This package contains implementation for Ada.Wide_Wide_Text_IO.Decimal_IO
+-- Routines in this package are identical semantically to those in Decimal_IO,
+-- except that the default parameters have been removed because they are
+-- supplied explicitly by the calls from within these units, and there is an
+-- additional Scale parameter giving the value of Num'Scale. In addition the
+-- Get routines return the value rather than store it in an Out parameter.
-private package Ada.Wide_Wide_Text_IO.Decimal_Aux is
+private generic
+ type Int is range <>;
- function Get_Dec
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Integer;
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int;
- function Get_LLD
- (File : File_Type;
- Width : Field;
- Scale : Integer) return Long_Long_Integer;
+ with procedure Set_Image
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
- function Gets_Dec
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Integer;
+package Ada.Wide_Wide_Text_IO.Decimal_Aux is
- function Gets_LLD
- (From : String;
- Last : not null access Positive;
- Scale : Integer) return Long_Long_Integer;
-
- procedure Put_Dec
+ function Get
(File : File_Type;
- Item : Integer;
- Fore : Field;
- Aft : Field;
- Exp : Field;
- Scale : Integer);
+ Width : Field;
+ Scale : Integer) return Int;
- procedure Put_LLD
+ procedure Put
(File : File_Type;
- Item : Long_Long_Integer;
+ Item : Int;
Fore : Field;
Aft : Field;
Exp : Field;
Scale : Integer);
- procedure Puts_Dec
- (To : out String;
- Item : Integer;
- Aft : Field;
- Exp : Field;
- Scale : Integer);
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Scale : Integer) return Int;
- procedure Puts_LLD
+ procedure Puts
(To : out String;
- Item : Long_Long_Integer;
+ Item : Int;
Aft : Field;
Exp : Field;
Scale : Integer);
diff --git a/gcc/ada/libgnat/a-ztdeio.adb b/gcc/ada/libgnat/a-ztdeio.adb
index 3655386..1d9f5d8 100644
--- a/gcc/ada/libgnat/a-ztdeio.adb
+++ b/gcc/ada/libgnat/a-ztdeio.adb
@@ -30,16 +30,35 @@
------------------------------------------------------------------------------
with Ada.Wide_Wide_Text_IO.Decimal_Aux;
-
+with System.Img_Decimal_32; use System.Img_Decimal_32;
+with System.Img_Decimal_64; use System.Img_Decimal_64;
+with System.Val_Decimal_32; use System.Val_Decimal_32;
+with System.Val_Decimal_64; use System.Val_Decimal_64;
with System.WCh_Con; use System.WCh_Con;
with System.WCh_WtS; use System.WCh_WtS;
package body Ada.Wide_Wide_Text_IO.Decimal_IO is
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Aux32 is new
+ Ada.Wide_Wide_Text_IO.Decimal_Aux
+ (Int32,
+ Scan_Decimal32,
+ Set_Image_Decimal32);
- package Aux renames Ada.Wide_Wide_Text_IO.Decimal_Aux;
+ package Aux64 is new
+ Ada.Wide_Wide_Text_IO.Decimal_Aux
+ (Int64,
+ Scan_Decimal64,
+ Set_Image_Decimal64);
+
+ Need64 : constant Boolean := Num'Size > 32;
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is acceptable and where type Int64 is needed. This Boolean is used
+ -- to test for these cases and since it is a constant, only code for the
+ -- relevant case will be included in the instance.
Scale : constant Integer := Num'Scale;
@@ -52,12 +71,15 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
Item : out Num;
Width : Field := 0)
is
+ pragma Unsuppress (Range_Check);
+
begin
- if Num'Size > Integer'Size then
- Item := Num'Fixed_Value (Aux.Get_LLD (TFT (File), Width, Scale));
+ if Need64 then
+ Item := Num'Fixed_Value (Aux64.Get (File, Width, Scale));
else
- Item := Num'Fixed_Value (Aux.Get_Dec (TFT (File), Width, Scale));
+ Item := Num'Fixed_Value (Aux32.Get (File, Width, Scale));
end if;
+
exception
when Constraint_Error => raise Data_Error;
end Get;
@@ -67,7 +89,7 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -75,6 +97,8 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
Item : out Num;
Last : out Positive)
is
+ pragma Unsuppress (Range_Check);
+
S : constant String := Wide_Wide_String_To_String (From, WCEM_Upper);
-- String on which we do the actual conversion. Note that the method
-- used for wide character encoding is irrelevant, since if there is
@@ -82,16 +106,10 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- if Num'Size > Integer'Size then
- -- Item := Num'Fixed_Value
- -- should write above, but gets assert error ???
- Item := Num
- (Aux.Gets_LLD (S, Last'Unrestricted_Access, Scale));
+ if Need64 then
+ Item := Num'Fixed_Value (Aux64.Gets (S, Last, Scale));
else
- -- Item := Num'Fixed_Value
- -- should write above, but gets assert error ???
- Item := Num
- (Aux.Gets_Dec (S, Last'Unrestricted_Access, Scale));
+ Item := Num'Fixed_Value (Aux32.Gets (S, Last, Scale));
end if;
exception
@@ -110,18 +128,12 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
Exp : Field := Default_Exp)
is
begin
- if Num'Size > Integer'Size then
- Aux.Put_LLD
--- (TFT (File), Long_Long_Integer'Integer_Value (Item),
--- ???
- (TFT (File), Long_Long_Integer (Item),
- Fore, Aft, Exp, Scale);
+ if Need64 then
+ Aux64.Put
+ (File, Int64'Integer_Value (Item), Fore, Aft, Exp, Scale);
else
- Aux.Put_Dec
--- (TFT (File), Integer'Integer_Value (Item), Fore, Aft, Exp, Scale);
--- ???
- (TFT (File), Integer (Item), Fore, Aft, Exp, Scale);
-
+ Aux32.Put
+ (File, Int32'Integer_Value (Item), Fore, Aft, Exp, Scale);
end if;
end Put;
@@ -132,7 +144,7 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -144,16 +156,10 @@ package body Ada.Wide_Wide_Text_IO.Decimal_IO is
S : String (To'First .. To'Last);
begin
- if Num'Size > Integer'Size then
--- Aux.Puts_LLD
--- (S, Long_Long_Integer'Integer_Value (Item), Aft, Exp, Scale);
--- ???
- Aux.Puts_LLD
- (S, Long_Long_Integer (Item), Aft, Exp, Scale);
+ if Need64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp, Scale);
else
--- Aux.Puts_Dec (S, Integer'Integer_Value (Item), Aft, Exp, Scale);
--- ???
- Aux.Puts_Dec (S, Integer (Item), Aft, Exp, Scale);
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp, Scale);
end if;
for J in S'Range loop
diff --git a/gcc/ada/libgnat/a-ztdeio__128.adb b/gcc/ada/libgnat/a-ztdeio__128.adb
new file mode 100644
index 0000000..156a66d
--- /dev/null
+++ b/gcc/ada/libgnat/a-ztdeio__128.adb
@@ -0,0 +1,190 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ W I D E _ T E X T _ I O . D E C I M A L _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Wide_Wide_Text_IO.Decimal_Aux;
+with System.Img_Decimal_32; use System.Img_Decimal_32;
+with System.Img_Decimal_64; use System.Img_Decimal_64;
+with System.Img_Decimal_128; use System.Img_Decimal_128;
+with System.Val_Decimal_32; use System.Val_Decimal_32;
+with System.Val_Decimal_64; use System.Val_Decimal_64;
+with System.Val_Decimal_128; use System.Val_Decimal_128;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
+
+package body Ada.Wide_Wide_Text_IO.Decimal_IO is
+
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Int64 is Interfaces.Integer_64;
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Aux32 is new
+ Ada.Wide_Wide_Text_IO.Decimal_Aux
+ (Int32,
+ Scan_Decimal32,
+ Set_Image_Decimal32);
+
+ package Aux64 is new
+ Ada.Wide_Wide_Text_IO.Decimal_Aux
+ (Int64,
+ Scan_Decimal64,
+ Set_Image_Decimal64);
+
+ package Aux128 is new
+ Ada.Wide_Wide_Text_IO.Decimal_Aux
+ (Int128,
+ Scan_Decimal128,
+ Set_Image_Decimal128);
+
+ Need64 : constant Boolean := Num'Size > 32;
+ Need128 : constant Boolean := Num'Size > 64;
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is acceptable, where type Int64 is acceptable and where an Int128
+ -- is needed. These boolean constants are used to test for these cases and
+ -- since it is a constant, only code for the relevant case will be included
+ -- in the instance.
+
+ Scale : constant Integer := Num'Scale;
+
+ ---------
+ -- Get --
+ ---------
+
+ procedure Get
+ (File : File_Type;
+ Item : out Num;
+ Width : Field := 0)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if Need128 then
+ Item := Num'Fixed_Value (Aux128.Get (File, Width, Scale));
+ elsif Need64 then
+ Item := Num'Fixed_Value (Aux64.Get (File, Width, Scale));
+ else
+ Item := Num'Fixed_Value (Aux32.Get (File, Width, Scale));
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ procedure Get
+ (Item : out Num;
+ Width : Field := 0)
+ is
+ begin
+ Get (Current_In, Item, Width);
+ end Get;
+
+ procedure Get
+ (From : Wide_Wide_String;
+ Item : out Num;
+ Last : out Positive)
+ is
+ pragma Unsuppress (Range_Check);
+
+ S : constant String := Wide_Wide_String_To_String (From, WCEM_Upper);
+ -- String on which we do the actual conversion. Note that the method
+ -- used for wide character encoding is irrelevant, since if there is
+ -- a character outside the Standard.Character range then the call to
+ -- Aux.Gets will raise Data_Error in any case.
+
+ begin
+ if Need128 then
+ Item := Num'Fixed_Value (Aux128.Gets (S, Last, Scale));
+ elsif Need64 then
+ Item := Num'Fixed_Value (Aux64.Gets (S, Last, Scale));
+ else
+ Item := Num'Fixed_Value (Aux32.Gets (S, Last, Scale));
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if Need128 then
+ Aux128.Put
+ (File, Int128'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ elsif Need64 then
+ Aux64.Put
+ (File, Int64'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ else
+ Aux32.Put
+ (File, Int32'Integer_Value (Item), Fore, Aft, Exp, Scale);
+ end if;
+ end Put;
+
+ procedure Put
+ (Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ Put (Current_Out, Item, Fore, Aft, Exp);
+ end Put;
+
+ procedure Put
+ (To : out Wide_Wide_String;
+ Item : Num;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ S : String (To'First .. To'Last);
+
+ begin
+ if Need128 then
+ Aux128.Puts (S, Int128'Integer_Value (Item), Aft, Exp, Scale);
+ elsif Need64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp, Scale);
+ else
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp, Scale);
+ end if;
+
+ for J in S'Range loop
+ To (J) := Wide_Wide_Character'Val (Character'Pos (S (J)));
+ end loop;
+ end Put;
+
+end Ada.Wide_Wide_Text_IO.Decimal_IO;
diff --git a/gcc/ada/libgnat/a-ztenau.adb b/gcc/ada/libgnat/a-ztenau.adb
index f985d52d..f3b11af 100644
--- a/gcc/ada/libgnat/a-ztenau.adb
+++ b/gcc/ada/libgnat/a-ztenau.adb
@@ -37,9 +37,6 @@ with System.WCh_Con; use System.WCh_Con;
package body Ada.Wide_Wide_Text_IO.Enumeration_Aux is
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
-----------------------
-- Local Subprograms --
-----------------------
@@ -70,8 +67,8 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_Aux is
begin
Buflen := 0;
- Load_Skip (TFT (File));
- ch := Nextc (TFT (File));
+ Load_Skip (File);
+ ch := Nextc (File);
-- Character literal case. If the initial character is a quote, then
-- we read as far as we can without backup (see ACVC test CE3905L)
@@ -80,7 +77,7 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_Aux is
Get (File, WC);
Store_Char (WC, Buf, Buflen);
- ch := Nextc (TFT (File));
+ ch := Nextc (File);
if ch = LM or else ch = EOF then
return;
@@ -89,7 +86,7 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_Aux is
Get (File, WC);
Store_Char (WC, Buf, Buflen);
- ch := Nextc (TFT (File));
+ ch := Nextc (File);
if ch /= Character'Pos (''') then
return;
@@ -118,7 +115,7 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_Aux is
Get (File, WC);
Store_Char (WC, Buf, Buflen);
- ch := Nextc (TFT (File));
+ ch := Nextc (File);
exit when ch = EOF;
@@ -156,7 +153,7 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_Aux is
Integer'Max (Integer (Width), Item'Length);
begin
- Check_On_One_Line (TFT (File), Actual_Width);
+ Check_On_One_Line (File, Actual_Width);
if Set = Lower_Case and then Item (Item'First) /= ''' then
declare
diff --git a/gcc/ada/libgnat/a-ztenio.adb b/gcc/ada/libgnat/a-ztenio.adb
index 5a61874..6c35b9f 100644
--- a/gcc/ada/libgnat/a-ztenio.adb
+++ b/gcc/ada/libgnat/a-ztenio.adb
@@ -51,7 +51,7 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_IO is
procedure Get (Item : out Enum) is
begin
- Get (Current_Input, Item);
+ Get (Current_In, Item);
end Get;
procedure Get
@@ -88,7 +88,7 @@ package body Ada.Wide_Wide_Text_IO.Enumeration_IO is
Set : Type_Set := Default_Setting)
is
begin
- Put (Current_Output, Item, Width, Set);
+ Put (Current_Out, Item, Width, Set);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-ztfiau.adb b/gcc/ada/libgnat/a-ztfiau.adb
new file mode 100644
index 0000000..1e94fef
--- /dev/null
+++ b/gcc/ada/libgnat/a-ztfiau.adb
@@ -0,0 +1,159 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ W I D E _ T E X T _ I O . F I X E D _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Wide_Wide_Text_IO.Generic_Aux; use Ada.Wide_Wide_Text_IO.Generic_Aux;
+
+package body Ada.Wide_Wide_Text_IO.Fixed_Aux is
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get
+ (File : File_Type;
+ Width : Field;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Buf : String (1 .. Field'Last);
+ Ptr : aliased Integer;
+ Stop : Integer := 0;
+ Item : Int;
+
+ begin
+ if Width /= 0 then
+ Load_Width (File, Width, Buf, Stop);
+ String_Skip (Buf, Ptr);
+ else
+ Load_Real (File, Buf, Stop);
+ Ptr := 1;
+ end if;
+
+ Item := Scan (Buf, Ptr'Access, Stop, Num, Den);
+ Check_End_Of_Field (Buf, Stop, Ptr, Width);
+ return Item;
+ end Get;
+
+ ----------
+ -- Gets --
+ ----------
+
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Pos : aliased Integer;
+ Item : Int;
+
+ begin
+ String_Skip (From, Pos);
+ Item := Scan (From, Pos'Access, From'Last, Num, Den);
+ Last := Pos - 1;
+ return Item;
+
+ exception
+ when Constraint_Error =>
+ Last := Pos - 1;
+ raise Data_Error;
+ end Gets;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Int;
+ Fore : Field;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ Buf : String (1 .. Field'Last);
+ Ptr : Natural := 0;
+
+ begin
+ Set_Image (Item, Buf, Ptr, Num, Den, For0, Aft0, Fore, Aft, Exp);
+ Put_Item (File, Buf (1 .. Ptr));
+ end Put;
+
+ ----------
+ -- Puts --
+ ----------
+
+ procedure Puts
+ (To : out String;
+ Item : Int;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ Buf : String (1 .. Positive'Max (Field'Last, To'Length));
+ Fore : Integer;
+ Ptr : Natural := 0;
+
+ begin
+ -- Compute Fore, allowing for the decimal dot and Aft digits
+
+ Fore := To'Length - 1 - Field'Max (1, Aft);
+
+ -- Allow for Exp and one more for E if exponent present
+
+ if Exp /= 0 then
+ Fore := Fore - 1 - Field'Max (2, Exp);
+ end if;
+
+ -- Make sure we have enough room
+
+ if Fore < 1 + Boolean'Pos (Item < 0) then
+ raise Layout_Error;
+ end if;
+
+ -- Do the conversion and check length of result
+
+ Set_Image (Item, Buf, Ptr, Num, Den, For0, Aft0, Fore, Aft, Exp);
+
+ if Ptr > To'Length then
+ raise Layout_Error;
+ else
+ To := Buf (1 .. Ptr);
+ end if;
+ end Puts;
+
+end Ada.Wide_Wide_Text_IO.Fixed_Aux;
diff --git a/gcc/ada/libgnat/a-ztfiau.ads b/gcc/ada/libgnat/a-ztfiau.ads
new file mode 100644
index 0000000..aac4e42
--- /dev/null
+++ b/gcc/ada/libgnat/a-ztfiau.ads
@@ -0,0 +1,97 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ W I D E _ T E X T _ I O . F I X E D _ I O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the implementation for Ada.Wide_Wide_Text_IO.Fixed_IO
+-- Routines in this package are identical semantically to those in Fixed_IO,
+-- except that the default parameters have been removed because they are
+-- supplied explicitly by the calls from within these units, and there are
+-- additional Num and Den parameters giving the value of Num'Small, as well
+-- as For0 and Aft0 giving some properties of Num'Small. In addition the Get
+-- routines return the value rather than store it in an Out parameter.
+
+private generic
+ type Int is range <>;
+
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int;
+ Den : Int) return Int;
+
+ with procedure Set_Image
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+
+package Ada.Wide_Wide_Text_IO.Fixed_Aux is
+
+ function Get
+ (File : File_Type;
+ Width : Field;
+ Num : Int;
+ Den : Int) return Int;
+
+ procedure Put
+ (File : File_Type;
+ Item : Int;
+ Fore : Field;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+
+ function Gets
+ (From : String;
+ Last : out Positive;
+ Num : Int;
+ Den : Int) return Int;
+
+ procedure Puts
+ (To : out String;
+ Item : Int;
+ Aft : Field;
+ Exp : Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+
+end Ada.Wide_Wide_Text_IO.Fixed_Aux;
diff --git a/gcc/ada/libgnat/a-ztfiio.adb b/gcc/ada/libgnat/a-ztfiio.adb
index 7c0c95d..53ed45b 100644
--- a/gcc/ada/libgnat/a-ztfiio.adb
+++ b/gcc/ada/libgnat/a-ztfiio.adb
@@ -2,7 +2,7 @@
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
--- A D A . T E X T _ I O . W I D E _ T E X T _ I O . F I X E D _ I O --
+-- A D A . W I D E _ W I D E _ T E X T _ I O . F I X E D _ I O --
-- --
-- B o d y --
-- --
@@ -29,16 +29,114 @@
-- --
------------------------------------------------------------------------------
+with Interfaces;
+with Ada.Wide_Wide_Text_IO.Fixed_Aux;
with Ada.Wide_Wide_Text_IO.Float_Aux;
-with System.WCh_Con; use System.WCh_Con;
-with System.WCh_WtS; use System.WCh_WtS;
+with System.Img_Fixed_32; use System.Img_Fixed_32;
+with System.Img_Fixed_64; use System.Img_Fixed_64;
+with System.Val_Fixed_32; use System.Val_Fixed_32;
+with System.Val_Fixed_64; use System.Val_Fixed_64;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
package body Ada.Wide_Wide_Text_IO.Fixed_IO is
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
+ -- Note: we still use the floating-point I/O routines for types whose small
+ -- is not the ratio of two sufficiently small integers. This will result in
+ -- inaccuracies for fixed point types that require more precision than is
+ -- available in Long_Long_Float.
- package Aux renames Ada.Wide_Wide_Text_IO.Float_Aux;
+ subtype Int32 is Interfaces.Integer_32; use type Int32;
+ subtype Int64 is Interfaces.Integer_64; use type Int64;
+
+ package Aux32 is new
+ Ada.Wide_Wide_Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32);
+
+ package Aux64 is new
+ Ada.Wide_Wide_Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64);
+
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is OK and where type Int64 is OK. These boolean constants are used
+ -- to test for this, such that only code for the relevant case is included
+ -- in the instance; that's why the computation of their value must be fully
+ -- static (although it is not a static expressions in the RM sense).
+
+ OK_Get_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator <= 2**27
+ and then Num'Small_Denominator <= 2**27));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**27)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**25));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator <= 2**59
+ and then Num'Small_Denominator <= 2**59));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**59)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**53));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ E : constant Natural := 63 - 32 * Boolean'Pos (OK_Put_32);
+ -- T'Size - 1 for the selected Int{32,64}
+
+ F0 : constant Natural := 0;
+ F1 : constant Natural :=
+ F0 + 18 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+18);
+ F2 : constant Natural :=
+ F1 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+9);
+ F3 : constant Natural :=
+ F2 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+5);
+ F4 : constant Natural :=
+ F3 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+3);
+ F5 : constant Natural :=
+ F4 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+2);
+ F6 : constant Natural :=
+ F5 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+1);
+ -- Binary search for the number of digits - 1 before the decimal point of
+ -- the product 2.0**E * Num'Small.
+
+ For0 : constant Natural := 2 + F6;
+ -- Fore value for the fixed point type whose mantissa is Int{32,64} and
+ -- whose small is Num'Small.
---------
-- Get --
@@ -49,8 +147,22 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
Item : out Num;
Width : Field := 0)
is
+ pragma Unsuppress (Range_Check);
+
begin
- Aux.Get (TFT (File), Long_Long_Float (Item), Width);
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -61,7 +173,7 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -69,6 +181,8 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
Item : out Num;
Last : out Positive)
is
+ pragma Unsuppress (Range_Check);
+
S : constant String := Wide_Wide_String_To_String (From, WCEM_Upper);
-- String on which we do the actual conversion. Note that the method
-- used for wide character encoding is irrelevant, since if there is
@@ -76,7 +190,19 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- Aux.Gets (S, Long_Long_Float (Item), Last);
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Gets (S, Long_Long_Float (Item), Last);
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -94,7 +220,18 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (TFT (File), Long_Long_Float (Item), Fore, Aft, Exp);
+ if OK_Put_32 then
+ Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
end Put;
procedure Put
@@ -104,7 +241,7 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -116,7 +253,17 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
S : String (To'First .. To'Last);
begin
- Aux.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ if OK_Put_32 then
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ end if;
for J in S'Range loop
To (J) := Wide_Wide_Character'Val (Character'Pos (S (J)));
diff --git a/gcc/ada/libgnat/a-ztfiio__128.adb b/gcc/ada/libgnat/a-ztfiio__128.adb
new file mode 100644
index 0000000..13ed410
--- /dev/null
+++ b/gcc/ada/libgnat/a-ztfiio__128.adb
@@ -0,0 +1,327 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- A D A . W I D E _ W I D E _ T E X T _ I O . F I X E D _ I O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Interfaces;
+with Ada.Wide_Wide_Text_IO.Fixed_Aux;
+with Ada.Wide_Wide_Text_IO.Float_Aux;
+with System.Img_Fixed_32; use System.Img_Fixed_32;
+with System.Img_Fixed_64; use System.Img_Fixed_64;
+with System.Img_Fixed_128; use System.Img_Fixed_128;
+with System.Val_Fixed_32; use System.Val_Fixed_32;
+with System.Val_Fixed_64; use System.Val_Fixed_64;
+with System.Val_Fixed_128; use System.Val_Fixed_128;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
+
+package body Ada.Wide_Wide_Text_IO.Fixed_IO is
+
+ -- Note: we still use the floating-point I/O routines for types whose small
+ -- is not the ratio of two sufficiently small integers. This will result in
+ -- inaccuracies for fixed point types that require more precision than is
+ -- available in Long_Long_Float.
+
+ subtype Int32 is Interfaces.Integer_32; use type Int32;
+ subtype Int64 is Interfaces.Integer_64; use type Int64;
+ subtype Int128 is Interfaces.Integer_128; use type Int128;
+
+ package Aux32 is new
+ Ada.Wide_Wide_Text_IO.Fixed_Aux (Int32, Scan_Fixed32, Set_Image_Fixed32);
+
+ package Aux64 is new
+ Ada.Wide_Wide_Text_IO.Fixed_Aux (Int64, Scan_Fixed64, Set_Image_Fixed64);
+
+ package Aux128 is new
+ Ada.Wide_Wide_Text_IO.Fixed_Aux
+ (Int128, Scan_Fixed128, Set_Image_Fixed128);
+
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Int32 is OK, where type Int64 is OK and where type Int128 is OK. These
+ -- boolean constants are used to test for this, such that only code for the
+ -- relevant case is included in the instance; that's why the computation of
+ -- their value must be fully static (although it is not a static expression
+ -- in the RM sense).
+
+ OK_Get_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator <= 2**27
+ and then Num'Small_Denominator <= 2**27));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_32 : constant Boolean :=
+ Num'Base'Object_Size <= 32
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**31)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**31)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**27)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**25));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator <= 2**59
+ and then Num'Small_Denominator <= 2**59));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_64 : constant Boolean :=
+ Num'Base'Object_Size <= 64
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**63)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**63)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**59)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**53));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ OK_Get_128 : constant Boolean :=
+ Num'Base'Object_Size <= 128
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**127)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**127)
+ or else
+ (Num'Small_Numerator <= 2**123
+ and then Num'Small_Denominator <= 2**123));
+ -- These conditions are derived from the prerequisites of System.Value_F
+
+ OK_Put_128 : constant Boolean :=
+ Num'Base'Object_Size <= 128
+ and then
+ ((Num'Small_Numerator = 1 and then Num'Small_Denominator <= 2**127)
+ or else
+ (Num'Small_Denominator = 1 and then Num'Small_Numerator <= 2**127)
+ or else
+ (Num'Small_Numerator < Num'Small_Denominator
+ and then Num'Small_Denominator <= 2**123)
+ or else
+ (Num'Small_Denominator < Num'Small_Numerator
+ and then Num'Small_Numerator <= 2**122));
+ -- These conditions are derived from the prerequisites of System.Image_F
+
+ E : constant Natural :=
+ 127 - 64 * Boolean'Pos (OK_Put_64) - 32 * Boolean'Pos (OK_Put_32);
+ -- T'Size - 1 for the selected Int{32,64,128}
+
+ F0 : constant Natural := 0;
+ F1 : constant Natural :=
+ F0 + 38 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F0) >= 1.0E+38);
+ F2 : constant Natural :=
+ F1 + 19 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F1) >= 1.0E+19);
+ F3 : constant Natural :=
+ F2 + 9 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F2) >= 1.0E+9);
+ F4 : constant Natural :=
+ F3 + 5 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F3) >= 1.0E+5);
+ F5 : constant Natural :=
+ F4 + 3 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F4) >= 1.0E+3);
+ F6 : constant Natural :=
+ F5 + 2 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F5) >= 1.0E+2);
+ F7 : constant Natural :=
+ F6 + 1 * Boolean'Pos (2.0**E * Num'Small * 10.0**(-F6) >= 1.0E+1);
+ -- Binary search for the number of digits - 1 before the decimal point of
+ -- the product 2.0**E * Num'Small.
+
+ For0 : constant Natural := 2 + F7;
+ -- Fore value for the fixed point type whose mantissa is Int{32,64,128} and
+ -- whose small is Num'Small.
+
+ ---------
+ -- Get --
+ ---------
+
+ procedure Get
+ (File : File_Type;
+ Item : out Num;
+ Width : Field := 0)
+ is
+ pragma Unsuppress (Range_Check);
+
+ begin
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_128 then
+ Item := Num'Fixed_Value
+ (Aux128.Get (File, Width,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ procedure Get
+ (Item : out Num;
+ Width : Field := 0)
+ is
+ begin
+ Get (Current_In, Item, Width);
+ end Get;
+
+ procedure Get
+ (From : Wide_Wide_String;
+ Item : out Num;
+ Last : out Positive)
+ is
+ pragma Unsuppress (Range_Check);
+
+ S : constant String := Wide_Wide_String_To_String (From, WCEM_Upper);
+ -- String on which we do the actual conversion. Note that the method
+ -- used for wide character encoding is irrelevant, since if there is
+ -- a character outside the Standard.Character range then the call to
+ -- Aux.Gets will raise Data_Error in any case.
+
+ begin
+ if OK_Get_32 then
+ Item := Num'Fixed_Value
+ (Aux32.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_64 then
+ Item := Num'Fixed_Value
+ (Aux64.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ elsif OK_Get_128 then
+ Item := Num'Fixed_Value
+ (Aux128.Gets (S, Last,
+ -Num'Small_Numerator,
+ -Num'Small_Denominator));
+ else
+ Aux_Long_Long_Float.Gets (S, Long_Long_Float (Item), Last);
+ end if;
+
+ exception
+ when Constraint_Error => raise Data_Error;
+ end Get;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (File : File_Type;
+ Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ if OK_Put_32 then
+ Aux32.Put (File, Int32'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Put (File, Int64'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_128 then
+ Aux128.Put (File, Int128'Integer_Value (Item), Fore, Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
+ end Put;
+
+ procedure Put
+ (Item : Num;
+ Fore : Field := Default_Fore;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ begin
+ Put (Current_Out, Item, Fore, Aft, Exp);
+ end Put;
+
+ procedure Put
+ (To : out Wide_Wide_String;
+ Item : Num;
+ Aft : Field := Default_Aft;
+ Exp : Field := Default_Exp)
+ is
+ S : String (To'First .. To'Last);
+
+ begin
+ if OK_Put_32 then
+ Aux32.Puts (S, Int32'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_64 then
+ Aux64.Puts (S, Int64'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ elsif OK_Put_128 then
+ Aux128.Puts (S, Int128'Integer_Value (Item), Aft, Exp,
+ -Num'Small_Numerator, -Num'Small_Denominator,
+ For0, Num'Aft);
+ else
+ Aux_Long_Long_Float.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ end if;
+
+ for J in S'Range loop
+ To (J) := Wide_Wide_Character'Val (Character'Pos (S (J)));
+ end loop;
+ end Put;
+
+end Ada.Wide_Wide_Text_IO.Fixed_IO;
diff --git a/gcc/ada/libgnat/a-ztflau.adb b/gcc/ada/libgnat/a-ztflau.adb
index c0c55ba..1bddcd8 100644
--- a/gcc/ada/libgnat/a-ztflau.adb
+++ b/gcc/ada/libgnat/a-ztflau.adb
@@ -31,8 +31,7 @@
with Ada.Wide_Wide_Text_IO.Generic_Aux; use Ada.Wide_Wide_Text_IO.Generic_Aux;
-with System.Img_Real; use System.Img_Real;
-with System.Val_Real; use System.Val_Real;
+with System.Img_Real; use System.Img_Real;
package body Ada.Wide_Wide_Text_IO.Float_Aux is
@@ -42,12 +41,12 @@ package body Ada.Wide_Wide_Text_IO.Float_Aux is
procedure Get
(File : File_Type;
- Item : out Long_Long_Float;
+ Item : out Num;
Width : Field)
is
Buf : String (1 .. Field'Last);
Stop : Integer := 0;
- Ptr : aliased Integer := 1;
+ Ptr : aliased Integer;
begin
if Width /= 0 then
@@ -55,10 +54,10 @@ package body Ada.Wide_Wide_Text_IO.Float_Aux is
String_Skip (Buf, Ptr);
else
Load_Real (File, Buf, Stop);
+ Ptr := 1;
end if;
- Item := Scan_Real (Buf, Ptr'Access, Stop);
-
+ Item := Scan (Buf, Ptr'Access, Stop);
Check_End_Of_Field (Buf, Stop, Ptr, Width);
end Get;
@@ -68,137 +67,36 @@ package body Ada.Wide_Wide_Text_IO.Float_Aux is
procedure Gets
(From : String;
- Item : out Long_Long_Float;
+ Item : out Num;
Last : out Positive)
is
Pos : aliased Integer;
begin
String_Skip (From, Pos);
- Item := Scan_Real (From, Pos'Access, From'Last);
+ Item := Scan (From, Pos'Access, From'Last);
Last := Pos - 1;
exception
- when Constraint_Error =>
- raise Data_Error;
+ when Constraint_Error => raise Data_Error;
end Gets;
- ---------------
- -- Load_Real --
- ---------------
-
- procedure Load_Real
- (File : File_Type;
- Buf : out String;
- Ptr : in out Natural)
- is
- Loaded : Boolean;
-
- begin
- -- Skip initial blanks and load possible sign
-
- Load_Skip (File);
- Load (File, Buf, Ptr, '+', '-');
-
- -- Case of .nnnn
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Digits (File, Buf, Ptr, Loaded);
-
- -- Hopeless junk if no digits loaded
-
- if not Loaded then
- return;
- end if;
-
- -- Otherwise must have digits to start
-
- else
- Load_Digits (File, Buf, Ptr, Loaded);
-
- -- Hopeless junk if no digits loaded
-
- if not Loaded then
- return;
- end if;
-
- -- Deal with based case. We recognize either the standard '#' or the
- -- allowed alternative replacement ':' (see RM J.2(3)).
-
- Load (File, Buf, Ptr, '#', ':', Loaded);
-
- if Loaded then
-
- -- Case of nnn#.xxx#
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Extended_Digits (File, Buf, Ptr);
- Load (File, Buf, Ptr, '#', ':');
-
- -- Case of nnn#xxx.[xxx]# or nnn#xxx#
-
- else
- Load_Extended_Digits (File, Buf, Ptr);
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Extended_Digits (File, Buf, Ptr);
- end if;
-
- -- As usual, it seems strange to allow mixed base characters,
- -- but that is what ACVC tests expect, see CE3804M, case (3).
-
- Load (File, Buf, Ptr, '#', ':');
- end if;
-
- -- Case of nnn.[nnn] or nnn
-
- else
- -- Prevent the potential processing of '.' in cases where the
- -- initial digits have a trailing underscore.
-
- if Buf (Ptr) = '_' then
- return;
- end if;
-
- Load (File, Buf, Ptr, '.', Loaded);
-
- if Loaded then
- Load_Digits (File, Buf, Ptr);
- end if;
- end if;
- end if;
-
- -- Deal with exponent
-
- Load (File, Buf, Ptr, 'E', 'e', Loaded);
-
- if Loaded then
- Load (File, Buf, Ptr, '+', '-');
- Load_Digits (File, Buf, Ptr);
- end if;
- end Load_Real;
-
---------
-- Put --
---------
procedure Put
(File : File_Type;
- Item : Long_Long_Float;
+ Item : Num;
Fore : Field;
Aft : Field;
Exp : Field)
is
- Buf : String (1 .. Field'Last);
+ Buf : String (1 .. Max_Real_Image_Length);
Ptr : Natural := 0;
begin
- Set_Image_Real (Item, Buf, Ptr, Fore, Aft, Exp);
+ Set_Image_Real (Long_Long_Float (Item), Buf, Ptr, Fore, Aft, Exp);
Put_Item (File, Buf (1 .. Ptr));
end Put;
@@ -208,15 +106,16 @@ package body Ada.Wide_Wide_Text_IO.Float_Aux is
procedure Puts
(To : out String;
- Item : Long_Long_Float;
+ Item : Num;
Aft : Field;
Exp : Field)
is
- Buf : String (1 .. Field'Last);
- Ptr : Natural := 0;
+ Buf : String (1 .. Max_Real_Image_Length);
+ Ptr : Natural := 0;
begin
- Set_Image_Real (Item, Buf, Ptr, Fore => 1, Aft => Aft, Exp => Exp);
+ Set_Image_Real
+ (Long_Long_Float (Item), Buf, Ptr, Fore => 1, Aft => Aft, Exp => Exp);
if Ptr > To'Length then
raise Layout_Error;
diff --git a/gcc/ada/libgnat/a-ztflau.ads b/gcc/ada/libgnat/a-ztflau.ads
index dc24682..48fba82 100644
--- a/gcc/ada/libgnat/a-ztflau.ads
+++ b/gcc/ada/libgnat/a-ztflau.ads
@@ -31,41 +31,42 @@
-- This package contains the routines for Ada.Wide_Wide_Text_IO.Float_IO that
-- are shared among separate instantiations of this package. The routines
--- in this package are identical semantically to those in Float_IO itself,
--- except that generic parameter Num has been replaced by Long_Long_Float,
--- and the default parameters have been removed because they are supplied
+-- in this package are identical semantically to those in Float_IO, except
+-- that the default parameters have been removed because they are supplied
-- explicitly by the calls from within the generic template. Also used by
--- Ada.Wide_Wide_Text_IO.Fixed_IO, and by Ada.Wide_Wide_Text_IO.Decimal_IO.
+-- Ada.Wide_Wide_Text_IO.Fixed_IO and by Ada.Wide_Wide_Text_IO.Decimal_IO.
-private package Ada.Wide_Wide_Text_IO.Float_Aux is
+private generic
- procedure Load_Real
- (File : File_Type;
- Buf : out String;
- Ptr : in out Natural);
- -- This is an auxiliary routine that is used to load a possibly signed
- -- real literal value from the input file into Buf, starting at Ptr + 1.
+ type Num is digits <>;
+
+ with function Scan
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Num;
+
+package Ada.Wide_Wide_Text_IO.Float_Aux is
procedure Get
(File : File_Type;
- Item : out Long_Long_Float;
+ Item : out Num;
Width : Field);
- procedure Gets
- (From : String;
- Item : out Long_Long_Float;
- Last : out Positive);
-
procedure Put
(File : File_Type;
- Item : Long_Long_Float;
+ Item : Num;
Fore : Field;
Aft : Field;
Exp : Field);
+ procedure Gets
+ (From : String;
+ Item : out Num;
+ Last : out Positive);
+
procedure Puts
(To : out String;
- Item : Long_Long_Float;
+ Item : Num;
Aft : Field;
Exp : Field);
diff --git a/gcc/ada/libgnat/a-ztflio.adb b/gcc/ada/libgnat/a-ztflio.adb
index fd6bf52..e491e62 100644
--- a/gcc/ada/libgnat/a-ztflio.adb
+++ b/gcc/ada/libgnat/a-ztflio.adb
@@ -30,15 +30,31 @@
------------------------------------------------------------------------------
with Ada.Wide_Wide_Text_IO.Float_Aux;
-with System.WCh_Con; use System.WCh_Con;
-with System.WCh_WtS; use System.WCh_WtS;
+with System.Val_Flt; use System.Val_Flt;
+with System.Val_LFlt; use System.Val_LFlt;
+with System.Val_LLF; use System.Val_LLF;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_WtS; use System.WCh_WtS;
package body Ada.Wide_Wide_Text_IO.Float_IO is
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
+ package Aux_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Float, Scan_Float);
- package Aux renames Ada.Wide_Wide_Text_IO.Float_Aux;
+ package Aux_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Long_Float, Scan_Long_Float);
+
+ package Aux_Long_Long_Float is new
+ Ada.Wide_Wide_Text_IO.Float_Aux (Long_Long_Float, Scan_Long_Long_Float);
+
+ -- Throughout this generic body, we distinguish between the case where type
+ -- Float is OK, where type Long_Float is OK and where type Long_Long_Float
+ -- is needed. These boolean constants are used to test for this, such that
+ -- only code for the relevant case is included in the instance.
+
+ OK_Float : constant Boolean := Num'Base'Digits <= Float'Digits;
+
+ OK_Long_Float : constant Boolean := Num'Base'Digits <= Long_Float'Digits;
---------
-- Get --
@@ -49,8 +65,25 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
Item : out Num;
Width : Field := 0)
is
+ pragma Unsuppress (Range_Check);
+
begin
- Aux.Get (TFT (File), Long_Long_Float (Item), Width);
+ if OK_Float then
+ Aux_Float.Get (File, Float (Item), Width);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Get (File, Long_Float (Item), Width);
+ else
+ Aux_Long_Long_Float.Get (File, Long_Long_Float (Item), Width);
+ end if;
+
+ -- In the case where the type is unconstrained (e.g. Standard'Float),
+ -- the above conversion may result in an infinite value, which is
+ -- normally fine for a conversion, but in this case, we want to treat
+ -- that as a data error.
+
+ if not Item'Valid then
+ raise Data_Error;
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -61,7 +94,7 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -69,6 +102,8 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
Item : out Num;
Last : out Positive)
is
+ pragma Unsuppress (Range_Check);
+
S : constant String := Wide_Wide_String_To_String (From, WCEM_Upper);
-- String on which we do the actual conversion. Note that the method
-- used for wide character encoding is irrelevant, since if there is
@@ -76,7 +111,22 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
-- Aux.Gets will raise Data_Error in any case.
begin
- Aux.Gets (S, Long_Long_Float (Item), Last);
+ if OK_Float then
+ Aux_Float.Gets (S, Float (Item), Last);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Gets (S, Long_Float (Item), Last);
+ else
+ Aux_Long_Long_Float.Gets (S, Long_Long_Float (Item), Last);
+ end if;
+
+ -- In the case where the type is unconstrained (e.g. Standard'Float),
+ -- the above conversion may result in an infinite value, which is
+ -- normally fine for a conversion, but in this case, we want to treat
+ -- that as a data error.
+
+ if not Item'Valid then
+ raise Data_Error;
+ end if;
exception
when Constraint_Error => raise Data_Error;
@@ -94,7 +144,14 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Aux.Put (TFT (File), Long_Long_Float (Item), Fore, Aft, Exp);
+ if OK_Float then
+ Aux_Float.Put (File, Float (Item), Fore, Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Put (File, Long_Float (Item), Fore, Aft, Exp);
+ else
+ Aux_Long_Long_Float.Put
+ (File, Long_Long_Float (Item), Fore, Aft, Exp);
+ end if;
end Put;
procedure Put
@@ -104,7 +161,7 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
Exp : Field := Default_Exp)
is
begin
- Put (Current_Output, Item, Fore, Aft, Exp);
+ Put (Current_Out, Item, Fore, Aft, Exp);
end Put;
procedure Put
@@ -116,7 +173,13 @@ package body Ada.Wide_Wide_Text_IO.Float_IO is
S : String (To'First .. To'Last);
begin
- Aux.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ if OK_Float then
+ Aux_Float.Puts (S, Float (Item), Aft, Exp);
+ elsif OK_Long_Float then
+ Aux_Long_Float.Puts (S, Long_Float (Item), Aft, Exp);
+ else
+ Aux_Long_Long_Float.Puts (S, Long_Long_Float (Item), Aft, Exp);
+ end if;
for J in S'Range loop
To (J) := Wide_Wide_Character'Val (Character'Pos (S (J)));
diff --git a/gcc/ada/libgnat/a-ztgeau.adb b/gcc/ada/libgnat/a-ztgeau.adb
index be7aecc..6b5e4c5 100644
--- a/gcc/ada/libgnat/a-ztgeau.adb
+++ b/gcc/ada/libgnat/a-ztgeau.adb
@@ -403,6 +403,106 @@ package body Ada.Wide_Wide_Text_IO.Generic_Aux is
end Load_Integer;
---------------
+ -- Load_Real --
+ ---------------
+
+ procedure Load_Real
+ (File : File_Type;
+ Buf : out String;
+ Ptr : in out Natural)
+ is
+ Loaded : Boolean;
+
+ begin
+ -- Skip initial blanks and load possible sign
+
+ Load_Skip (File);
+ Load (File, Buf, Ptr, '+', '-');
+
+ -- Case of .nnnn
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Digits (File, Buf, Ptr, Loaded);
+
+ -- Hopeless junk if no digits loaded
+
+ if not Loaded then
+ return;
+ end if;
+
+ -- Otherwise must have digits to start
+
+ else
+ Load_Digits (File, Buf, Ptr, Loaded);
+
+ -- Hopeless junk if no digits loaded
+
+ if not Loaded then
+ return;
+ end if;
+
+ -- Deal with based case. We recognize either the standard '#' or the
+ -- allowed alternative replacement ':' (see RM J.2(3)).
+
+ Load (File, Buf, Ptr, '#', ':', Loaded);
+
+ if Loaded then
+
+ -- Case of nnn#.xxx#
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Extended_Digits (File, Buf, Ptr);
+ Load (File, Buf, Ptr, '#', ':');
+
+ -- Case of nnn#xxx.[xxx]# or nnn#xxx#
+
+ else
+ Load_Extended_Digits (File, Buf, Ptr);
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Extended_Digits (File, Buf, Ptr);
+ end if;
+
+ -- As usual, it seems strange to allow mixed base characters,
+ -- but that is what ACVC tests expect, see CE3804M, case (3).
+
+ Load (File, Buf, Ptr, '#', ':');
+ end if;
+
+ -- Case of nnn.[nnn] or nnn
+
+ else
+ -- Prevent the potential processing of '.' in cases where the
+ -- initial digits have a trailing underscore.
+
+ if Buf (Ptr) = '_' then
+ return;
+ end if;
+
+ Load (File, Buf, Ptr, '.', Loaded);
+
+ if Loaded then
+ Load_Digits (File, Buf, Ptr);
+ end if;
+ end if;
+ end if;
+
+ -- Deal with exponent
+
+ Load (File, Buf, Ptr, 'E', 'e', Loaded);
+
+ if Loaded then
+ Load (File, Buf, Ptr, '+', '-');
+ Load_Digits (File, Buf, Ptr);
+ end if;
+ end Load_Real;
+
+ ---------------
-- Load_Skip --
---------------
diff --git a/gcc/ada/libgnat/a-ztgeau.ads b/gcc/ada/libgnat/a-ztgeau.ads
index 68d4a33..6b80ed4 100644
--- a/gcc/ada/libgnat/a-ztgeau.ads
+++ b/gcc/ada/libgnat/a-ztgeau.ads
@@ -155,6 +155,12 @@ package Ada.Wide_Wide_Text_IO.Generic_Aux is
Ptr : in out Natural);
-- Loads a possibly signed integer literal value
+ procedure Load_Real
+ (File : File_Type;
+ Buf : out String;
+ Ptr : in out Natural);
+ -- Loads a possibly signed real literal value
+
procedure Put_Item (File : File_Type; Str : String);
-- This routine is like Wide_Wide_Text_IO.Put, except that it checks for
-- overflow of bounded lines, as described in (RM A.10.6(8)). It is used
diff --git a/gcc/ada/libgnat/a-ztinio.adb b/gcc/ada/libgnat/a-ztinio.adb
index ab8741e..c19c8a6 100644
--- a/gcc/ada/libgnat/a-ztinio.adb
+++ b/gcc/ada/libgnat/a-ztinio.adb
@@ -65,9 +65,6 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
-- Boolean is used to test for these cases and since it is a constant, only
-- code for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -84,9 +81,9 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
begin
if Need_LLI then
- Aux_LLI.Get (TFT (File), Long_Long_Integer (Item), Width);
+ Aux_LLI.Get (File, Long_Long_Integer (Item), Width);
else
- Aux_Int.Get (TFT (File), Integer (Item), Width);
+ Aux_Int.Get (File, Integer (Item), Width);
end if;
exception
@@ -98,7 +95,7 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -140,9 +137,9 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
is
begin
if Need_LLI then
- Aux_LLI.Put (TFT (File), Long_Long_Integer (Item), Width, Base);
+ Aux_LLI.Put (File, Long_Long_Integer (Item), Width, Base);
else
- Aux_Int.Put (TFT (File), Integer (Item), Width, Base);
+ Aux_Int.Put (File, Integer (Item), Width, Base);
end if;
end Put;
@@ -152,7 +149,7 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-ztinio__128.adb b/gcc/ada/libgnat/a-ztinio__128.adb
index c809eeb..19dcc34 100644
--- a/gcc/ada/libgnat/a-ztinio__128.adb
+++ b/gcc/ada/libgnat/a-ztinio__128.adb
@@ -79,9 +79,6 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
-- are used to test for these cases and since they are constant, only code
-- for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -98,11 +95,11 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
begin
if Need_LLLI then
- Aux_LLLI.Get (TFT (File), Long_Long_Long_Integer (Item), Width);
+ Aux_LLLI.Get (File, Long_Long_Long_Integer (Item), Width);
elsif Need_LLI then
- Aux_LLI.Get (TFT (File), Long_Long_Integer (Item), Width);
+ Aux_LLI.Get (File, Long_Long_Integer (Item), Width);
else
- Aux_Int.Get (TFT (File), Integer (Item), Width);
+ Aux_Int.Get (File, Integer (Item), Width);
end if;
exception
@@ -114,7 +111,7 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -158,11 +155,11 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
is
begin
if Need_LLLI then
- Aux_LLLI.Put (TFT (File), Long_Long_Long_Integer (Item), Width, Base);
+ Aux_LLLI.Put (File, Long_Long_Long_Integer (Item), Width, Base);
elsif Need_LLI then
- Aux_LLI.Put (TFT (File), Long_Long_Integer (Item), Width, Base);
+ Aux_LLI.Put (File, Long_Long_Integer (Item), Width, Base);
else
- Aux_Int.Put (TFT (File), Integer (Item), Width, Base);
+ Aux_Int.Put (File, Integer (Item), Width, Base);
end if;
end Put;
@@ -172,7 +169,7 @@ package body Ada.Wide_Wide_Text_IO.Integer_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-ztmoio.adb b/gcc/ada/libgnat/a-ztmoio.adb
index d2f81e2..ba854ff 100644
--- a/gcc/ada/libgnat/a-ztmoio.adb
+++ b/gcc/ada/libgnat/a-ztmoio.adb
@@ -65,9 +65,6 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
-- Boolean is used to test for these cases and since it is a constant, only
-- code for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -83,9 +80,9 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
begin
if Need_LLU then
- Aux_LLU.Get (TFT (File), Long_Long_Unsigned (Item), Width);
+ Aux_LLU.Get (File, Long_Long_Unsigned (Item), Width);
else
- Aux_Uns.Get (TFT (File), Unsigned (Item), Width);
+ Aux_Uns.Get (File, Unsigned (Item), Width);
end if;
exception
@@ -97,7 +94,7 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -138,9 +135,9 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
is
begin
if Need_LLU then
- Aux_LLU.Put (TFT (File), Long_Long_Unsigned (Item), Width, Base);
+ Aux_LLU.Put (File, Long_Long_Unsigned (Item), Width, Base);
else
- Aux_Uns.Put (TFT (File), Unsigned (Item), Width, Base);
+ Aux_Uns.Put (File, Unsigned (Item), Width, Base);
end if;
end Put;
@@ -150,7 +147,7 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/a-ztmoio__128.adb b/gcc/ada/libgnat/a-ztmoio__128.adb
index e6e11de..2101508 100644
--- a/gcc/ada/libgnat/a-ztmoio__128.adb
+++ b/gcc/ada/libgnat/a-ztmoio__128.adb
@@ -79,9 +79,6 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
-- are used to test for these cases and since they are constant, only code
-- for the relevant case will be included in the instance.
- subtype TFT is Ada.Wide_Wide_Text_IO.File_Type;
- -- File type required for calls to routines in Aux
-
---------
-- Get --
---------
@@ -99,9 +96,9 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
if Need_LLLU then
Aux_LLLU.Get (File, Long_Long_Long_Unsigned (Item), Width);
elsif Need_LLU then
- Aux_LLU.Get (TFT (File), Long_Long_Unsigned (Item), Width);
+ Aux_LLU.Get (File, Long_Long_Unsigned (Item), Width);
else
- Aux_Uns.Get (TFT (File), Unsigned (Item), Width);
+ Aux_Uns.Get (File, Unsigned (Item), Width);
end if;
exception
@@ -113,7 +110,7 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
Width : Field := 0)
is
begin
- Get (Current_Input, Item, Width);
+ Get (Current_In, Item, Width);
end Get;
procedure Get
@@ -158,9 +155,9 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
if Need_LLLU then
Aux_LLLU.Put (File, Long_Long_Long_Unsigned (Item), Width, Base);
elsif Need_LLU then
- Aux_LLU.Put (TFT (File), Long_Long_Unsigned (Item), Width, Base);
+ Aux_LLU.Put (File, Long_Long_Unsigned (Item), Width, Base);
else
- Aux_Uns.Put (TFT (File), Unsigned (Item), Width, Base);
+ Aux_Uns.Put (File, Unsigned (Item), Width, Base);
end if;
end Put;
@@ -170,7 +167,7 @@ package body Ada.Wide_Wide_Text_IO.Modular_IO is
Base : Number_Base := Default_Base)
is
begin
- Put (Current_Output, Item, Width, Base);
+ Put (Current_Out, Item, Width, Base);
end Put;
procedure Put
diff --git a/gcc/ada/libgnat/g-diopit.adb b/gcc/ada/libgnat/g-diopit.adb
index 50bbf9b..1e8627e 100644
--- a/gcc/ada/libgnat/g-diopit.adb
+++ b/gcc/ada/libgnat/g-diopit.adb
@@ -32,6 +32,7 @@
with Ada.Characters.Handling;
with Ada.Strings.Fixed;
with Ada.Strings.Maps;
+
with GNAT.OS_Lib;
with GNAT.Regexp;
@@ -49,7 +50,7 @@ package body GNAT.Directory_Operations.Iteration is
is
File_Regexp : constant Regexp.Regexp := Regexp.Compile (File_Pattern);
Index : Natural := 0;
- Quit : Boolean;
+ Quit : Boolean := False;
procedure Read_Directory (Directory : Dir_Name_Str);
-- Open Directory and read all entries. This routine is called
@@ -113,6 +114,7 @@ package body GNAT.Directory_Operations.Iteration is
if not (Dir_Entry = "." or else Dir_Entry = "..")
and then OS_Lib.Is_Directory (Pathname)
+ and then not OS_Lib.Is_Symbolic_Link (Pathname)
then
Read_Directory (Pathname);
exit when Quit;
@@ -124,7 +126,6 @@ package body GNAT.Directory_Operations.Iteration is
end Read_Directory;
begin
- Quit := False;
Read_Directory (Root_Directory);
end Find;
diff --git a/gcc/ada/libgnat/g-diopit.ads b/gcc/ada/libgnat/g-diopit.ads
index aa60d32..952d795 100644
--- a/gcc/ada/libgnat/g-diopit.ads
+++ b/gcc/ada/libgnat/g-diopit.ads
@@ -50,6 +50,8 @@ package GNAT.Directory_Operations.Iteration is
-- will pass in the value False on each call to Action. The iterator will
-- terminate after passing the last matched path to Action or after
-- returning from a call to Action which sets Quit to True.
+ -- The iterator does not follow symbolic links avoiding possible
+ -- circularities or exploring unrelated directories.
-- Raises GNAT.Regexp.Error_In_Regexp if File_Pattern is ill formed.
generic
diff --git a/gcc/ada/libgnat/g-expect.adb b/gcc/ada/libgnat/g-expect.adb
index 78b3c27..0f9d0b9 100644
--- a/gcc/ada/libgnat/g-expect.adb
+++ b/gcc/ada/libgnat/g-expect.adb
@@ -1181,6 +1181,12 @@ package body GNAT.Expect is
Set_Up_Child_Communications
(Descriptor, Pipe1, Pipe2, Pipe3, Command_With_Path.all,
C_Arg_List'Address);
+
+ -- On Windows systems we need to release memory taken for Arg_List
+
+ for A of Arg_List loop
+ Free (A);
+ end loop;
end if;
Free (Command_With_Path);
diff --git a/gcc/ada/libgnat/g-rannum.adb b/gcc/ada/libgnat/g-rannum.adb
index b7ef7d1..9c6693b 100644
--- a/gcc/ada/libgnat/g-rannum.adb
+++ b/gcc/ada/libgnat/g-rannum.adb
@@ -58,6 +58,8 @@ is
new Ada.Unchecked_Conversion (Unsigned_32, Integer_32);
function To_Signed is
new Ada.Unchecked_Conversion (Unsigned_64, Integer_64);
+ function To_Signed is
+ new Ada.Unchecked_Conversion (Unsigned_128, Integer_128);
------------------
-- Insert_Image --
@@ -98,12 +100,37 @@ is
Min : Result_Subtype := Default_Min;
Max : Result_Subtype := Result_Subtype'Last) return Result_Subtype
is
- subtype IntV is Integer_64 range
- Integer_64'Integer_Value (Min) ..
- Integer_64'Integer_Value (Max);
- function R is new Random_Discrete (Integer_64, IntV'First);
begin
- return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ if Result_Subtype'Base'Size > 64 then
+ declare
+ subtype IntV is Integer_128 range
+ Integer_128'Integer_Value (Min) ..
+ Integer_128'Integer_Value (Max);
+ function R is new Random_Discrete (Integer_128, IntV'First);
+ begin
+ return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ end;
+
+ elsif Result_Subtype'Base'Size > 32 then
+ declare
+ subtype IntV is Integer_64 range
+ Integer_64'Integer_Value (Min) ..
+ Integer_64'Integer_Value (Max);
+ function R is new Random_Discrete (Integer_64, IntV'First);
+ begin
+ return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ end;
+
+ else
+ declare
+ subtype IntV is Integer_32 range
+ Integer_32'Integer_Value (Min) ..
+ Integer_32'Integer_Value (Max);
+ function R is new Random_Discrete (Integer_32, IntV'First);
+ begin
+ return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ end;
+ end if;
end Random_Decimal_Fixed;
---------------------------
@@ -115,12 +142,37 @@ is
Min : Result_Subtype := Default_Min;
Max : Result_Subtype := Result_Subtype'Last) return Result_Subtype
is
- subtype IntV is Integer_64 range
- Integer_64'Integer_Value (Min) ..
- Integer_64'Integer_Value (Max);
- function R is new Random_Discrete (Integer_64, IntV'First);
begin
- return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ if Result_Subtype'Base'Size > 64 then
+ declare
+ subtype IntV is Integer_128 range
+ Integer_128'Integer_Value (Min) ..
+ Integer_128'Integer_Value (Max);
+ function R is new Random_Discrete (Integer_128, IntV'First);
+ begin
+ return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ end;
+
+ elsif Result_Subtype'Base'Size > 32 then
+ declare
+ subtype IntV is Integer_64 range
+ Integer_64'Integer_Value (Min) ..
+ Integer_64'Integer_Value (Max);
+ function R is new Random_Discrete (Integer_64, IntV'First);
+ begin
+ return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ end;
+
+ else
+ declare
+ subtype IntV is Integer_32 range
+ Integer_32'Integer_Value (Min) ..
+ Integer_32'Integer_Value (Max);
+ function R is new Random_Discrete (Integer_32, IntV'First);
+ begin
+ return Result_Subtype'Fixed_Value (R (Gen, IntV'First, IntV'Last));
+ end;
+ end if;
end Random_Ordinary_Fixed;
------------
@@ -147,9 +199,9 @@ is
return Random (Gen.Rep);
end Random;
- function Random (Gen : Generator) return Integer_64 is
+ function Random (Gen : Generator) return Interfaces.Unsigned_128 is
begin
- return To_Signed (Unsigned_64'(Random (Gen)));
+ return Random (Gen.Rep);
end Random;
function Random (Gen : Generator) return Integer_32 is
@@ -157,6 +209,16 @@ is
return To_Signed (Unsigned_32'(Random (Gen)));
end Random;
+ function Random (Gen : Generator) return Integer_64 is
+ begin
+ return To_Signed (Unsigned_64'(Random (Gen)));
+ end Random;
+
+ function Random (Gen : Generator) return Integer_128 is
+ begin
+ return To_Signed (Unsigned_128'(Random (Gen)));
+ end Random;
+
function Random (Gen : Generator) return Long_Integer is
function Random_Long_Integer is new Random_Discrete (Long_Integer);
begin
diff --git a/gcc/ada/libgnat/g-rannum.ads b/gcc/ada/libgnat/g-rannum.ads
index 5b633ff..f795ae0 100644
--- a/gcc/ada/libgnat/g-rannum.ads
+++ b/gcc/ada/libgnat/g-rannum.ads
@@ -69,6 +69,8 @@ is
function Random (Gen : Generator) return Interfaces.Unsigned_32;
function Random (Gen : Generator) return Interfaces.Integer_64;
function Random (Gen : Generator) return Interfaces.Unsigned_64;
+ function Random (Gen : Generator) return Interfaces.Integer_128;
+ function Random (Gen : Generator) return Interfaces.Unsigned_128;
function Random (Gen : Generator) return Integer;
function Random (Gen : Generator) return Long_Integer;
-- Return pseudo-random numbers uniformly distributed on T'First .. T'Last
diff --git a/gcc/ada/libgnat/g-sercom__linux.adb b/gcc/ada/libgnat/g-sercom__linux.adb
index 7d93e57..f7212e8 100644
--- a/gcc/ada/libgnat/g-sercom__linux.adb
+++ b/gcc/ada/libgnat/g-sercom__linux.adb
@@ -30,15 +30,41 @@
------------------------------------------------------------------------------
-- This is the GNU/Linux implementation of this package
-
-with Ada.Streams; use Ada.Streams;
-with Ada; use Ada;
+--
+-- Testing on GNU/Linux can be done with socat & stty tools.
+--
+-- First in a terminal create a virtual serial port:
+--
+-- * First solution, the terminal is one of the side of the channel
+-- characters written with Write into the port will be displayed
+-- there and characters typed into the terminal will be send to the
+-- channel and will be received by a Read call.
+--
+-- $ socat PTY,link=/tmp/virtual-tty,raw,echo=1 -
+--
+-- * Second solution, the virtual channel contains two side and the
+-- program can Read and Write date to it.
+--
+-- $ socat PTY,link=/tmp/virtual-tty,raw,echo=1 \
+-- PTY,link=/tmp/virtual-tty,raw,echo=1
+--
+-- Connect to this virtual serial port with:
+--
+-- Open (Port => P, Name => "/tmp/virtual-tty");
+--
+-- Do any settings using the Set routine below, then you can check
+-- the serial port configuration with:
+--
+-- $ stty --file /tmp/virtual-tty
+--
+
+with Ada.Streams; use Ada.Streams;
with System; use System;
with System.Communication; use System.Communication;
with System.CRTL; use System.CRTL;
-with GNAT.OS_Lib; use GNAT.OS_Lib;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
package body GNAT.Serial_Communications is
@@ -191,6 +217,8 @@ package body GNAT.Serial_Communications is
is
use OSC;
+ subtype speed_t is unsigned;
+
type termios is record
c_iflag : unsigned;
c_oflag : unsigned;
@@ -198,8 +226,8 @@ package body GNAT.Serial_Communications is
c_lflag : unsigned;
c_line : unsigned_char;
c_cc : Interfaces.C.char_array (0 .. 31);
- c_ispeed : unsigned;
- c_ospeed : unsigned;
+ c_ispeed : speed_t;
+ c_ospeed : speed_t;
end record;
pragma Convention (C, termios);
@@ -213,9 +241,15 @@ package body GNAT.Serial_Communications is
function tcflush (fd : int; queue_selector : int) return int;
pragma Import (C, tcflush, "tcflush");
+ function cfsetospeed (termios_p : Address; speed : speed_t) return int;
+ pragma Import (C, cfsetospeed, "cfsetospeed");
+
+ function cfsetispeed (termios_p : Address; speed : speed_t) return int;
+ pragma Import (C, cfsetispeed, "cfsetispeed");
+
Current : termios;
- Res : int;
+ Res : int := 0;
pragma Warnings (Off, Res);
-- Warnings off, since we don't always test the result
@@ -230,11 +264,11 @@ package body GNAT.Serial_Communications is
-- Change settings now
- Current.c_cflag := C_Data_Rate (Rate)
- or C_Bits (Bits)
+ Current.c_cflag := C_Bits (Bits)
or C_Stop_Bits (Stop_Bits)
or C_Parity (Parity)
or CREAD;
+
Current.c_iflag := 0;
Current.c_lflag := 0;
Current.c_oflag := 0;
@@ -254,10 +288,36 @@ package body GNAT.Serial_Communications is
Current.c_iflag := Current.c_iflag or IXON;
end case;
- Current.c_ispeed := Data_Rate_Value (Rate);
- Current.c_ospeed := Data_Rate_Value (Rate);
- Current.c_cc (VMIN) := char'Val (0);
- Current.c_cc (VTIME) := char'Val (Natural (Timeout * 10));
+ Current.c_ispeed := Data_Rate_Value (Rate);
+ Current.c_ospeed := Data_Rate_Value (Rate);
+
+ -- See man termios for descriptions about the different modes
+
+ if Block and then Timeout = 0.0 then
+ -- MIN > 0, TIME == 0 (blocking read)
+ Current.c_cc (VMIN) := char'Val (1);
+ Current.c_cc (VTIME) := char'Val (0);
+
+ else
+ -- MIN == 0, TIME > 0 (read with timeout)
+ -- MIN == 0, TIME == 0 (polling read)
+ Current.c_cc (VMIN) := char'Val (0);
+ Current.c_cc (VTIME) := char'Val (Natural (Timeout * 10));
+
+ Current.c_lflag := Current.c_lflag or (not ICANON);
+ end if;
+
+ Res := cfsetispeed (Current'Address, C_Data_Rate (Rate));
+
+ if Res = -1 then
+ Raise_Error ("set: cfsetispeed failed");
+ end if;
+
+ Res := cfsetospeed (Current'Address, C_Data_Rate (Rate));
+
+ if Res = -1 then
+ Raise_Error ("set: cfsetospeed failed");
+ end if;
-- Set port settings
@@ -266,7 +326,11 @@ package body GNAT.Serial_Communications is
-- Block
- Res := fcntl (int (Port.H), F_SETFL, (if Block then 0 else FNDELAY));
+ if Block then
+ -- In blocking mode, remove the non-blocking flags set while
+ -- opening the serial port (see Open).
+ Res := fcntl (int (Port.H), F_SETFL, 0);
+ end if;
if Res = -1 then
Raise_Error ("set: fcntl failed");
diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb
index 57a8800..a4e9fd1 100644
--- a/gcc/ada/libgnat/g-socket.adb
+++ b/gcc/ada/libgnat/g-socket.adb
@@ -42,6 +42,8 @@ with GNAT.Sockets.Linker_Options;
pragma Warnings (Off, GNAT.Sockets.Linker_Options);
-- Need to include pragma Linker_Options which is platform dependent
+with GNAT.Sockets.Poll;
+
with System; use System;
with System.Communication; use System.Communication;
with System.CRTL; use System.CRTL;
@@ -252,15 +254,13 @@ package body GNAT.Sockets is
procedure Wait_On_Socket
(Socket : Socket_Type;
- For_Read : Boolean;
+ Event : Poll.Wait_Event_Set;
Timeout : Selector_Duration;
Selector : access Selector_Type := null;
Status : out Selector_Status);
-- Common code for variants of socket operations supporting a timeout:
- -- block in Check_Selector on Socket for at most the indicated timeout.
- -- If For_Read is True, Socket is added to the read set for this call, else
- -- it is added to the write set. If no selector is provided, a local one is
- -- created for this call and destroyed prior to returning.
+ -- block in Poll.Wait on Socket for at most the indicated timeout.
+ -- Event parameter defines what the Poll.Wait is waiting for.
type Sockets_Library_Controller is new Ada.Finalization.Limited_Controlled
with null record;
@@ -371,11 +371,11 @@ package body GNAT.Sockets is
-- Wait for socket to become available for reading
Wait_On_Socket
- (Socket => Server,
- For_Read => True,
- Timeout => Timeout,
- Selector => Selector,
- Status => Status);
+ (Socket => Server,
+ Event => Poll.Input_Event,
+ Timeout => Timeout,
+ Selector => Selector,
+ Status => Status);
-- Accept connection if available
@@ -729,7 +729,7 @@ package body GNAT.Sockets is
else
Wait_On_Socket
(Socket => Socket,
- For_Read => False,
+ Event => Poll.Output_Event,
Timeout => Timeout,
Selector => Selector,
Status => Status);
@@ -2016,57 +2016,32 @@ package body GNAT.Sockets is
procedure Wait_On_Socket
(Socket : Socket_Type;
- For_Read : Boolean;
+ Event : Poll.Wait_Event_Set;
Timeout : Selector_Duration;
Selector : access Selector_Type := null;
Status : out Selector_Status)
is
- type Local_Selector_Access is access Selector_Type;
- for Local_Selector_Access'Storage_Size use Selector_Type'Size;
-
- procedure Unchecked_Free is new Ada.Unchecked_Deallocation
- (Selector_Type, Local_Selector_Access);
+ Fd_Set : Poll.Set := Poll.To_Set (Socket, Event, 2);
+ -- Socket itself and second place for signaling socket if necessary
- Local_S : Local_Selector_Access;
- S : Selector_Access;
- -- Selector to use for waiting
-
- R_Fd_Set : Socket_Set_Type;
- W_Fd_Set : Socket_Set_Type;
+ Count : Natural;
+ Index : Natural := 0;
begin
- -- Create selector if not provided by the user
-
- if Selector = null then
- Local_S := new Selector_Type;
- S := Local_S.all'Unchecked_Access;
- Create_Selector (S.all);
+ -- Add signaling socket if selector defined
- else
- S := Selector.all'Access;
+ if Selector /= null then
+ Poll.Append (Fd_Set, Selector.R_Sig_Socket, Poll.Input_Event);
end if;
- if For_Read then
- Set (R_Fd_Set, Socket);
- else
- Set (W_Fd_Set, Socket);
- end if;
+ Poll.Wait (Fd_Set, Timeout, Count);
- Check_Selector (S.all, R_Fd_Set, W_Fd_Set, Status, Timeout);
-
- if Selector = null then
- Close_Selector (S.all);
- Unchecked_Free (Local_S);
+ if Count = 0 then
+ Status := Expired;
+ else
+ Poll.Next (Fd_Set, Index);
+ Status := (if Index = 1 then Completed else Aborted);
end if;
-
- exception
- when others =>
- Status := Completed;
-
- if Selector = null then
- Close_Selector (S.all);
- Unchecked_Free (Local_S);
- end if;
end Wait_On_Socket;
-----------------
diff --git a/gcc/ada/libgnat/g-socpol.adb b/gcc/ada/libgnat/g-socpol.adb
index ab3286c..cd82bb8 100644
--- a/gcc/ada/libgnat/g-socpol.adb
+++ b/gcc/ada/libgnat/g-socpol.adb
@@ -368,8 +368,7 @@ package body GNAT.Sockets.Poll is
Poll_Timeout := Timeout - (Clock - Stamp);
if Poll_Timeout < 0.0 then
- Count := 0;
- return;
+ Poll_Timeout := 0.0;
elsif Poll_Timeout > Timeout then
-- Clock moved back in time. This should not be happen when
diff --git a/gcc/ada/libgnat/g-spogwa.adb b/gcc/ada/libgnat/g-spogwa.adb
index a9135ea..6e0af44 100644
--- a/gcc/ada/libgnat/g-spogwa.adb
+++ b/gcc/ada/libgnat/g-spogwa.adb
@@ -36,8 +36,6 @@ procedure GNAT.Sockets.Poll.G_Wait
is
use Interfaces;
- use type C.int;
-
function C_Select
(Nfds : C.int;
readfds : access FD_Set_Type;
@@ -65,8 +63,8 @@ begin
if Timeout >= 0 then
Timeout_A := Timeout_V'Access;
- Timeout_V.tv_sec := Thin_Common.time_t (Timeout / 1000);
- Timeout_V.tv_usec := Thin_Common.suseconds_t (Timeout rem 1000 * 1000);
+ Timeout_V.Tv_Sec := Thin_Common.time_t (Timeout / 1000);
+ Timeout_V.Tv_Usec := Thin_Common.suseconds_t (Timeout rem 1000 * 1000);
end if;
Reset_Socket_Set (Rfds);
diff --git a/gcc/ada/libgnat/memtrack.adb b/gcc/ada/libgnat/memtrack.adb
index bd34796..a5f508d 100644
--- a/gcc/ada/libgnat/memtrack.adb
+++ b/gcc/ada/libgnat/memtrack.adb
@@ -102,6 +102,9 @@ package body System.Memory is
pragma Import (C, OS_Exit, "__gnat_os_exit");
pragma No_Return (OS_Exit);
+ In_Child_After_Fork : Integer;
+ pragma Import (C, In_Child_After_Fork, "__gnat_in_child_after_fork");
+
procedure fwrite
(Ptr : System.Address;
Size : size_t;
@@ -149,6 +152,24 @@ package body System.Memory is
-- themselves do dynamic allocation. We use First_Call flag to avoid
-- infinite recursion
+ function Allow_Trace return Boolean;
+ pragma Inline (Allow_Trace);
+ -- Check if the memory trace is allowed
+
+ -----------------
+ -- Allow_Trace --
+ -----------------
+
+ function Allow_Trace return Boolean is
+ begin
+ if First_Call then
+ First_Call := False;
+ return In_Child_After_Fork = 0;
+ else
+ return False;
+ end if;
+ end Allow_Trace;
+
-----------
-- Alloc --
-----------
@@ -176,14 +197,12 @@ package body System.Memory is
Result := c_malloc (Actual_Size);
- if First_Call then
+ if Allow_Trace then
-- Logs allocation call
-- format is:
-- 'A' <mem addr> <size chunk> <len backtrace> <addr1> ... <addrn>
- First_Call := False;
-
if Needs_Init then
Gmem_Initialize;
end if;
@@ -243,14 +262,12 @@ package body System.Memory is
begin
Lock_Task.all;
- if First_Call then
+ if Allow_Trace then
-- Logs deallocation call
-- format is:
-- 'D' <mem addr> <len backtrace> <addr1> ... <addrn>
- First_Call := False;
-
if Needs_Init then
Gmem_Initialize;
end if;
@@ -334,9 +351,7 @@ package body System.Memory is
Abort_Defer.all;
Lock_Task.all;
- if First_Call then
- First_Call := False;
-
+ if Allow_Trace then
-- We first log deallocation call
if Needs_Init then
diff --git a/gcc/ada/libgnat/s-arit32.adb b/gcc/ada/libgnat/s-arit32.adb
new file mode 100644
index 0000000..742f2e1
--- /dev/null
+++ b/gcc/ada/libgnat/s-arit32.adb
@@ -0,0 +1,182 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . A R I T H _ 3 2 --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Conversion;
+
+package body System.Arith_32 is
+
+ pragma Suppress (Overflow_Check);
+ pragma Suppress (Range_Check);
+
+ subtype Uns32 is Interfaces.Unsigned_32;
+ subtype Uns64 is Interfaces.Unsigned_64;
+
+ use Interfaces;
+
+ function To_Int is new Ada.Unchecked_Conversion (Uns32, Int32);
+
+ -----------------------
+ -- Local Subprograms --
+ -----------------------
+
+ function "abs" (X : Int32) return Uns32 is
+ (if X = Int32'First
+ then 2**31
+ else Uns32 (Int32'(abs X)));
+ -- Convert absolute value of X to unsigned. Note that we can't just use
+ -- the expression of the Else since it overflows for X = Int32'First.
+
+ function Hi (A : Uns64) return Uns32 is (Uns32 (Shift_Right (A, 32)));
+ -- High order half of 64-bit value
+
+ function To_Neg_Int (A : Uns32) return Int32;
+ -- Convert to negative integer equivalent. If the input is in the range
+ -- 0 .. 2**31, then the corresponding nonpositive signed integer (obtained
+ -- by negating the given value) is returned, otherwise constraint error is
+ -- raised.
+
+ function To_Pos_Int (A : Uns32) return Int32;
+ -- Convert to positive integer equivalent. If the input is in the range
+ -- 0 .. 2**31 - 1, then the corresponding nonnegative signed integer is
+ -- returned, otherwise constraint error is raised.
+
+ procedure Raise_Error;
+ pragma No_Return (Raise_Error);
+ -- Raise constraint error with appropriate message
+
+ -----------------
+ -- Raise_Error --
+ -----------------
+
+ procedure Raise_Error is
+ begin
+ raise Constraint_Error with "32-bit arithmetic overflow";
+ end Raise_Error;
+
+ -------------------
+ -- Scaled_Divide --
+ -------------------
+
+ procedure Scaled_Divide32
+ (X, Y, Z : Int32;
+ Q, R : out Int32;
+ Round : Boolean)
+ is
+ Xu : constant Uns32 := abs X;
+ Yu : constant Uns32 := abs Y;
+ Zu : constant Uns32 := abs Z;
+
+ D : Uns64;
+ -- The dividend
+
+ Qu : Uns32;
+ Ru : Uns32;
+ -- Unsigned quotient and remainder
+
+ begin
+ -- First do the 64-bit multiplication
+
+ D := Uns64 (Xu) * Uns64 (Yu);
+
+ -- If dividend is too large, raise error
+
+ if Hi (D) >= Zu then
+ Raise_Error;
+
+ -- Then do the 64-bit division
+
+ else
+ Qu := Uns32 (D / Uns64 (Zu));
+ Ru := Uns32 (D rem Uns64 (Zu));
+ end if;
+
+ -- Deal with rounding case
+
+ if Round and then Ru > (Zu - Uns32'(1)) / Uns32'(2) then
+
+ -- Protect against wrapping around when rounding, by signaling
+ -- an overflow when the quotient is too large.
+
+ if Qu = Uns32'Last then
+ Raise_Error;
+ end if;
+
+ Qu := Qu + Uns32'(1);
+ end if;
+
+ -- Set final signs (RM 4.5.5(27-30))
+
+ -- Case of dividend (X * Y) sign positive
+
+ if (X >= 0 and then Y >= 0) or else (X < 0 and then Y < 0) then
+ R := To_Pos_Int (Ru);
+ Q := (if Z > 0 then To_Pos_Int (Qu) else To_Neg_Int (Qu));
+
+ -- Case of dividend (X * Y) sign negative
+
+ else
+ R := To_Neg_Int (Ru);
+ Q := (if Z > 0 then To_Neg_Int (Qu) else To_Pos_Int (Qu));
+ end if;
+ end Scaled_Divide32;
+
+ ----------------
+ -- To_Neg_Int --
+ ----------------
+
+ function To_Neg_Int (A : Uns32) return Int32 is
+ R : constant Int32 :=
+ (if A = 2**31 then Int32'First else -To_Int (A));
+ -- Note that we can't just use the expression of the Else, because it
+ -- overflows for A = 2**31.
+ begin
+ if R <= 0 then
+ return R;
+ else
+ Raise_Error;
+ end if;
+ end To_Neg_Int;
+
+ ----------------
+ -- To_Pos_Int --
+ ----------------
+
+ function To_Pos_Int (A : Uns32) return Int32 is
+ R : constant Int32 := To_Int (A);
+ begin
+ if R >= 0 then
+ return R;
+ else
+ Raise_Error;
+ end if;
+ end To_Pos_Int;
+
+end System.Arith_32;
diff --git a/gcc/ada/libgnat/s-arit32.ads b/gcc/ada/libgnat/s-arit32.ads
new file mode 100644
index 0000000..5656855
--- /dev/null
+++ b/gcc/ada/libgnat/s-arit32.ads
@@ -0,0 +1,55 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . A R I T H _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This unit provides software routines for doing arithmetic on 32-bit
+-- signed integer values in cases where either overflow checking is
+-- required, or intermediate results are longer than 32 bits.
+
+with Interfaces;
+
+package System.Arith_32 is
+ pragma Pure;
+
+ subtype Int32 is Interfaces.Integer_32;
+
+ procedure Scaled_Divide32
+ (X, Y, Z : Int32;
+ Q, R : out Int32;
+ Round : Boolean);
+ -- Performs the division of (X * Y) / Z, storing the quotient in Q
+ -- and the remainder in R. Constraint_Error is raised if Z is zero,
+ -- or if the quotient does not fit in 32 bits. Round indicates if
+ -- the result should be rounded. If Round is False, then Q, R are
+ -- the normal quotient and remainder from a truncating division.
+ -- If Round is True, then Q is the rounded quotient. The remainder
+ -- R is not affected by the setting of the Round flag.
+
+end System.Arith_32;
diff --git a/gcc/ada/libgnat/s-bitfie.ads b/gcc/ada/libgnat/s-bitfie.ads
index 4f17a9c..21b7294 100644
--- a/gcc/ada/libgnat/s-bitfie.ads
+++ b/gcc/ada/libgnat/s-bitfie.ads
@@ -47,6 +47,12 @@ package System.Bitfields is
pragma Provide_Shift_Operators (Val_2);
type Val is mod 2**Val_Bits with Alignment => Val_Bytes;
+ -- ??? It turns out that enabling checks on the instantiation of
+ -- System.Bitfield_Utils.G makes a latent visibility bug appear on strict
+ -- alignment platforms related to alignment checks. Work around it by
+ -- suppressing these checks explicitly.
+
+ pragma Suppress (Alignment_Check);
package Utils is new System.Bitfield_Utils.G (Val, Val_2);
procedure Copy_Bitfield
diff --git a/gcc/ada/libgnat/s-bituti.adb b/gcc/ada/libgnat/s-bituti.adb
index e3bd70a..ef839a8 100644
--- a/gcc/ada/libgnat/s-bituti.adb
+++ b/gcc/ada/libgnat/s-bituti.adb
@@ -317,6 +317,7 @@ package body System.Bitfield_Utils is
Get_Val_2 (S_Addr, S_Off, Initial_Size);
Initial_Val : constant Val :=
Get_Bitfield (Initial_Val_2, S_Off, Initial_Size);
+
begin
Set_Bitfield
(Initial_Val, D_Addr, D_Off, Initial_Size);
diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb
index abb499c..d8b15c5d 100644
--- a/gcc/ada/libgnat/s-dwalin.adb
+++ b/gcc/ada/libgnat/s-dwalin.adb
@@ -1582,6 +1582,13 @@ package body System.Dwarf_Lines is
Subprg_Name,
Line_Num);
+ -- If we're not requested to suppress hex addresses, emit it now.
+
+ if not Suppress_Hex then
+ Append_Address (Res, Addr_In_Traceback);
+ Append (Res, ' ');
+ end if;
+
if File_Name /= null then
declare
Last : constant Natural := String_Length (File_Name);
@@ -1626,26 +1633,22 @@ package body System.Dwarf_Lines is
(Res,
String (Subprg_Name.Ptr (Off .. Subprg_Name.Len)));
end if;
- Append (Res, ' ');
+ else
+ Append (Res, "???");
end if;
- Append (Res, "at ");
+ Append (Res, " at ");
Append (Res, String (File_Name (1 .. Last)));
Append (Res, ':');
Append (Res, Line_Image (2 .. Line_Image'Last));
end;
else
- if Suppress_Hex then
- Append (Res, "...");
- else
- Append_Address (Res, Addr_In_Traceback);
- end if;
-
if Subprg_Name.Len > 0 then
Off := Strip_Leading_Char (C.Obj.all, Subprg_Name);
- Append (Res, ' ');
Append (Res, String (Subprg_Name.Ptr (Off .. Subprg_Name.Len)));
+ else
+ Append (Res, "???");
end if;
Append (Res, " at ???");
diff --git a/gcc/ada/libgnat/s-fatgen.adb b/gcc/ada/libgnat/s-fatgen.adb
index a598a12..9f25987 100644
--- a/gcc/ada/libgnat/s-fatgen.adb
+++ b/gcc/ada/libgnat/s-fatgen.adb
@@ -29,50 +29,137 @@
-- --
------------------------------------------------------------------------------
--- The implementation here is portable to any IEEE implementation. It does
--- not handle nonbinary radix, and also assumes that model numbers and
--- machine numbers are basically identical, which is not true of all possible
--- floating-point implementations. On a non-IEEE machine, this body must be
--- specialized appropriately, or better still, its generic instantiations
--- should be replaced by efficient machine-specific code.
+-- This implementation is portable to any IEEE implementation. It does not
+-- handle nonbinary radix, and also assumes that model numbers and machine
+-- numbers are basically identical, which is not true of all possible
+-- floating-point implementations.
with Ada.Unchecked_Conversion;
-with System;
-package body System.Fat_Gen is
+with Interfaces;
+with System.Unsigned_Types;
+
+pragma Warnings (Off, "non-static constant in preelaborated unit");
+-- Every constant is static given our instantiation model
- Float_Radix : constant T := T (T'Machine_Radix);
- Radix_To_M_Minus_1 : constant T := Float_Radix ** (T'Machine_Mantissa - 1);
+package body System.Fat_Gen is
+ use type Interfaces.Unsigned_64;
pragma Assert (T'Machine_Radix = 2);
-- This version does not handle radix 16
- -- Constants for Decompose and Scaling
+ Rad : constant T := T (T'Machine_Radix);
+ -- Renaming for the machine radix
- Rad : constant T := T (T'Machine_Radix);
- Invrad : constant T := 1.0 / Rad;
+ Mantissa : constant Integer := T'Machine_Mantissa;
+ -- Renaming for the machine mantissa
- subtype Expbits is Integer range 0 .. 6;
- -- 2 ** (2 ** 7) might overflow. How big can radix-16 exponents get?
-
- Log_Power : constant array (Expbits) of Integer := (1, 2, 4, 8, 16, 32, 64);
-
- R_Power : constant array (Expbits) of T :=
- (Rad ** 1,
- Rad ** 2,
- Rad ** 4,
- Rad ** 8,
- Rad ** 16,
- Rad ** 32,
- Rad ** 64);
-
- R_Neg_Power : constant array (Expbits) of T :=
- (Invrad ** 1,
- Invrad ** 2,
- Invrad ** 4,
- Invrad ** 8,
- Invrad ** 16,
- Invrad ** 32,
- Invrad ** 64);
+ Invrad : constant T := 1.0 / Rad;
+ -- Smallest positive mantissa in the canonical form (RM A.5.3(4))
+
+ -- Small : constant T := Rad ** (T'Machine_Emin - 1);
+ -- Smallest positive normalized number
+
+ -- Tiny : constant T := Rad ** (T'Machine_Emin - Mantissa);
+ -- Smallest positive denormalized number
+
+ Tiny16 : constant Interfaces.Unsigned_16 := 1;
+ Tiny32 : constant Interfaces.Unsigned_32 := 1;
+ Tiny64 : constant Interfaces.Unsigned_64 := 1;
+ Tiny80 : constant array (1 .. 2) of Interfaces.Unsigned_64 :=
+ (1 * Standard'Default_Bit_Order,
+ 2**48 * (1 - Standard'Default_Bit_Order));
+ for Tiny80'Alignment use Standard'Maximum_Alignment;
+ -- We cannot use the direct declaration because it cannot be translated
+ -- into C90, as the hexadecimal floating constants were introduced in C99.
+ -- So we work around this by using an overlay of the integer constant.
+
+ RM1 : constant T := Rad ** (Mantissa - 1);
+ -- Smallest positive member of the large consecutive integers. It is equal
+ -- to the ratio Small / Tiny, which means that multiplying by it normalizes
+ -- any nonzero denormalized number.
+
+ IEEE_Emin : constant Integer := T'Machine_Emin - 1;
+ IEEE_Emax : constant Integer := T'Machine_Emax - 1;
+ -- The mantissa is a fraction with first digit set in Ada whereas it is
+ -- shifted by 1 digit to the left in the IEEE floating-point format.
+
+ subtype IEEE_Erange is Integer range IEEE_Emin - 1 .. IEEE_Emax + 1;
+ -- The IEEE floating-point format extends the machine range by 1 to the
+ -- left for denormalized numbers and 1 to the right for infinities/NaNs.
+
+ IEEE_Ebias : constant Integer := -(IEEE_Emin - 1);
+ -- The exponent is biased such that denormalized numbers have it zero
+
+ -- The implementation uses a representation type Float_Rep that allows
+ -- direct access to exponent and mantissa of the floating point number.
+
+ -- The Float_Rep type is a simple array of Float_Word elements. This
+ -- representation is chosen to make it possible to size the type based
+ -- on a generic parameter. Since the array size is known at compile
+ -- time, efficient code can still be generated. The size of Float_Word
+ -- elements should be large enough to allow accessing the exponent in
+ -- one read, but small enough so that all floating-point object sizes
+ -- are a multiple of Float_Word'Size.
+
+ -- The following conditions must be met for all possible instantiations
+ -- of the attribute package:
+
+ -- - T'Size is an integral multiple of Float_Word'Size
+
+ -- - The exponent and sign are completely contained in a single
+ -- component of Float_Rep, named Most Significant Word (MSW).
+
+ -- - The sign occupies the most significant bit of the MSW and the
+ -- exponent is in the following bits. The exception is 80-bit
+ -- double extended, where they occupy the low 16-bit halfword.
+
+ -- The low-level primitives Copy_Sign, Decompose, Scaling and Valid are
+ -- implemented by accessing the bit pattern of the floating-point number.
+ -- Only the normalization of denormalized numbers, if any, and the gradual
+ -- underflow are left to the hardware, mainly because there is some leeway
+ -- for the hardware implementation in this area: for example, the MSB of
+ -- the mantissa, which is 1 for normalized numbers and 0 for denormalized
+ -- numbers, may or may not be stored by the hardware.
+
+ Siz : constant := (if System.Word_Size > 32 then 32 else System.Word_Size);
+ type Float_Word is mod 2**Siz;
+
+ N : constant Natural := (T'Size + Siz - 1) / Siz;
+ Rep_Last : constant Natural := Natural'Min (N - 1, (Mantissa + 16) / Siz);
+ -- Determine the number of Float_Words needed for representing the
+ -- entire floating-point value. Do not take into account excessive
+ -- padding, as occurs on IA-64 where 80 bits floats get padded to 128
+ -- bits. In general, the exponent field cannot be larger than 15 bits,
+ -- even for 128-bit floating-point types, so the final format size
+ -- won't be larger than Mantissa + 16.
+
+ type Float_Rep is array (Natural range 0 .. N - 1) of Float_Word;
+ pragma Suppress_Initialization (Float_Rep);
+ -- This pragma suppresses the generation of an initialization procedure
+ -- for type Float_Rep when operating in Initialize/Normalize_Scalars mode.
+
+ MSW : constant Natural := Rep_Last * Standard'Default_Bit_Order;
+ -- Finding the location of the Exponent_Word is a bit tricky. In general
+ -- we assume Word_Order = Bit_Order.
+
+ Exp_Factor : constant Float_Word :=
+ (if Mantissa = 64
+ then 1
+ else 2**(Siz - 1) / Float_Word (IEEE_Emax - IEEE_Emin + 3));
+ -- Factor that the extracted exponent needs to be divided by to be in
+ -- range 0 .. IEEE_Emax - IEEE_Emin + 2. The special case is 80-bit
+ -- double extended, where the exponent starts the 3rd float word.
+
+ Exp_Mask : constant Float_Word :=
+ Float_Word (IEEE_Emax - IEEE_Emin + 2) * Exp_Factor;
+ -- Value needed to mask out the exponent field. This assumes that the
+ -- range 0 .. IEEE_Emax - IEEE_Emin + 2 contains 2**N values, for some
+ -- N in Natural.
+
+ Sign_Mask : constant Float_Word :=
+ (if Mantissa = 64 then 2**15 else 2**(Siz - 1));
+ -- Value needed to mask out the sign field. The special case is 80-bit
+ -- double extended, where the exponent starts the 3rd float word.
-----------------------
-- Local Subprograms --
@@ -84,11 +171,6 @@ package body System.Fat_Gen is
-- the sign of the exponent. The absolute value of Frac is in the range
-- 0.0 <= Frac < 1.0. If Frac = 0.0 or -0.0, then Expo is always zero.
- function Gradual_Scaling (Adjustment : UI) return T;
- -- Like Scaling with a first argument of 1.0, but returns the smallest
- -- denormal rather than zero when the adjustment is smaller than
- -- Machine_Emin. Used for Succ and Pred.
-
--------------
-- Adjacent --
--------------
@@ -138,19 +220,22 @@ package body System.Fat_Gen is
---------------
function Copy_Sign (Value, Sign : T) return T is
- Result : T;
+ S : constant T := T'Machine (Sign);
- function Is_Negative (V : T) return Boolean;
- pragma Import (Intrinsic, Is_Negative);
+ Rep_S : Float_Rep;
+ for Rep_S'Address use S'Address;
+ -- Rep_S is a view of the Sign parameter
- begin
- Result := abs Value;
+ V : T := T'Machine (Value);
- if Is_Negative (Sign) then
- return -Result;
- else
- return Result;
- end if;
+ Rep_V : Float_Rep;
+ for Rep_V'Address use V'Address;
+ -- Rep_V is a view of the Value parameter
+
+ begin
+ Rep_V (MSW) :=
+ (Rep_V (MSW) and not Sign_Mask) or (Rep_S (MSW) and Sign_Mask);
+ return V;
end Copy_Sign;
---------------
@@ -158,94 +243,53 @@ package body System.Fat_Gen is
---------------
procedure Decompose (XX : T; Frac : out T; Expo : out UI) is
- X : constant T := T'Machine (XX);
+ X : T := T'Machine (XX);
- begin
- if X = 0.0 then
+ Rep : Float_Rep;
+ for Rep'Address use X'Address;
+ -- Rep is a view of the input floating-point parameter
- -- The normalized exponent of zero is zero, see RM A.5.2(15)
+ Exp : constant IEEE_Erange :=
+ Integer ((Rep (MSW) and Exp_Mask) / Exp_Factor) - IEEE_Ebias;
+ -- Mask/Shift X to only get bits from the exponent. Then convert biased
+ -- value to final value.
- Frac := X;
- Expo := 0;
-
- -- Check for infinities, transfinites, whatnot
+ Minus : constant Boolean := (Rep (MSW) and Sign_Mask) /= 0;
+ -- Mask/Shift X to only get bit from the sign
- elsif X > T'Safe_Last then
- Frac := Invrad;
- pragma Annotate (CodePeer, Intentional, "dead code",
- "Check float range.");
- Expo := T'Machine_Emax + 1;
-
- elsif X < T'Safe_First then
- Frac := -Invrad;
- pragma Annotate (CodePeer, Intentional, "dead code",
- "Check float range.");
- Expo := T'Machine_Emax + 2; -- how many extra negative values?
+ begin
+ -- The normalized exponent of zero is zero, see RM A.5.3(15)
- else
- -- Case of nonzero finite x. Essentially, we just multiply
- -- by Rad ** (+-2**N) to reduce the range.
+ if X = 0.0 then
+ Expo := 0;
+ Frac := X;
- declare
- Ax : T := abs X;
- Ex : UI := 0;
+ -- Check for infinities and NaNs
- -- Ax * Rad ** Ex is invariant
+ elsif Exp = IEEE_Emax + 1 then
+ Expo := T'Machine_Emax + 1;
+ Frac := (if Minus then -Invrad else Invrad);
- begin
- if Ax >= 1.0 then
- while Ax >= R_Power (Expbits'Last) loop
- Ax := Ax * R_Neg_Power (Expbits'Last);
- Ex := Ex + Log_Power (Expbits'Last);
- end loop;
+ -- Check for nonzero denormalized numbers
- -- Ax < Rad ** 64
+ elsif Exp = IEEE_Emin - 1 then
+ -- Normalize by multiplying by Radix ** (Mantissa - 1)
- for N in reverse Expbits'First .. Expbits'Last - 1 loop
- if Ax >= R_Power (N) then
- Ax := Ax * R_Neg_Power (N);
- Ex := Ex + Log_Power (N);
- end if;
+ Decompose (X * RM1, Frac, Expo);
+ Expo := Expo - (Mantissa - 1);
- -- Ax < R_Power (N)
+ -- Case of normalized numbers
- end loop;
+ else
+ -- The Ada exponent is the IEEE exponent plus 1, see above
- -- 1 <= Ax < Rad
+ Expo := Exp + 1;
- Ax := Ax * Invrad;
- Ex := Ex + 1;
+ -- Set Ada exponent of X to zero, so we end up with the fraction
- else
- -- 0 < ax < 1
-
- while Ax < R_Neg_Power (Expbits'Last) loop
- Ax := Ax * R_Power (Expbits'Last);
- pragma Annotate (CodePeer, Intentional, "dead code",
- "Check float range.");
- Ex := Ex - Log_Power (Expbits'Last);
- end loop;
- pragma Annotate
- (CodePeer, Intentional,
- "test always false",
- "expected for some instantiations");
-
- -- Rad ** -64 <= Ax < 1
-
- for N in reverse Expbits'First .. Expbits'Last - 1 loop
- if Ax < R_Neg_Power (N) then
- Ax := Ax * R_Power (N);
- Ex := Ex - Log_Power (N);
- end if;
-
- -- R_Neg_Power (N) <= Ax < 1
-
- end loop;
- end if;
-
- Frac := (if X > 0.0 then Ax else -Ax);
- Expo := Ex;
- end;
+ Rep (MSW) := (Rep (MSW) and not Exp_Mask) +
+ Float_Word (IEEE_Ebias - 1) * Exp_Factor;
+ Frac := X;
end if;
end Decompose;
@@ -291,38 +335,6 @@ package body System.Fat_Gen is
return X_Frac;
end Fraction;
- ---------------------
- -- Gradual_Scaling --
- ---------------------
-
- function Gradual_Scaling (Adjustment : UI) return T is
- Y : T;
- Y1 : T;
- Ex : UI := Adjustment;
-
- begin
- if Adjustment < T'Machine_Emin - 1 then
- Y := 2.0 ** T'Machine_Emin;
- Y1 := Y;
- Ex := Ex - T'Machine_Emin;
- while Ex < 0 loop
- Y := T'Machine (Y / 2.0);
-
- if Y = 0.0 then
- return Y1;
- end if;
-
- Ex := Ex + 1;
- Y1 := Y;
- end loop;
-
- return Y1;
-
- else
- return Scaling (1.0, Adjustment);
- end if;
- end Gradual_Scaling;
-
------------------
-- Leading_Part --
------------------
@@ -332,7 +344,7 @@ package body System.Fat_Gen is
Y, Z : T;
begin
- if Radix_Digits >= T'Machine_Mantissa then
+ if Radix_Digits >= Mantissa then
return X;
elsif Radix_Digits <= 0 then
@@ -412,6 +424,13 @@ package body System.Fat_Gen is
----------
function Pred (X : T) return T is
+ Tiny : constant T;
+ pragma Import (Ada, Tiny);
+ for Tiny'Address use (if T'Size = 16 then Tiny16'Address
+ elsif T'Size = 32 then Tiny32'Address
+ elsif T'Size = 64 then Tiny64'Address
+ elsif Mantissa = 64 then Tiny80'Address
+ else raise Program_Error);
X_Frac : T;
X_Exp : UI;
@@ -419,12 +438,11 @@ package body System.Fat_Gen is
-- Zero has to be treated specially, since its exponent is zero
if X = 0.0 then
- return -Succ (X);
+ return -Tiny;
- -- Special treatment for most negative number
+ -- Special treatment for largest negative number: raise Constraint_Error
elsif X = T'First then
-
raise Constraint_Error with "Pred of largest negative number";
-- For infinities, return unchanged
@@ -438,28 +456,33 @@ package body System.Fat_Gen is
-- Subtract from the given number a number equivalent to the value
-- of its least significant bit. Given that the most significant bit
- -- represents a value of 1.0 * radix ** (exp - 1), the value we want
- -- is obtained by shifting this by (mantissa-1) bits to the right,
+ -- represents a value of 1.0 * Radix ** (Exp - 1), the value we want
+ -- is obtained by shifting this by (Mantissa-1) bits to the right,
-- i.e. decreasing the exponent by that amount.
else
Decompose (X, X_Frac, X_Exp);
- -- A special case, if the number we had was a positive power of
- -- two, then we want to subtract half of what we would otherwise
- -- subtract, since the exponent is going to be reduced.
+ -- For a denormalized number or a normalized number with the lowest
+ -- exponent, just subtract the Tiny.
+
+ if X_Exp <= T'Machine_Emin then
+ return X - Tiny;
- -- Note that X_Frac has the same sign as X, so if X_Frac is 0.5,
- -- then we know that we have a positive number (and hence a
- -- positive power of 2).
+ -- A special case, if the number we had was a power of two on the
+ -- positive side of zero, then we want to subtract half of what we
+ -- would have subtracted, since the exponent is going to be reduced.
- if X_Frac = 0.5 then
- return X - Gradual_Scaling (X_Exp - T'Machine_Mantissa - 1);
+ -- Note that X_Frac has the same sign as X so, if X_Frac is Invrad,
+ -- then we know that we had a power of two on the positive side.
- -- Otherwise the exponent is unchanged
+ elsif X_Frac = Invrad then
+ return X - Scaling (1.0, X_Exp - Mantissa - 1);
+
+ -- Otherwise the adjustment is unchanged
else
- return X - Gradual_Scaling (X_Exp - T'Machine_Mantissa);
+ return X - Scaling (1.0, X_Exp - Mantissa);
end if;
end if;
end Pred;
@@ -579,70 +602,97 @@ package body System.Fat_Gen is
-- Scaling --
-------------
- -- Return x * rad ** adjustment quickly, or quietly underflow to zero,
- -- or overflow naturally.
-
function Scaling (X : T; Adjustment : UI) return T is
+ pragma Assert (Mantissa <= 64);
+ -- This implementation handles only 80-bit IEEE Extended or smaller
+
+ package UST renames System.Unsigned_Types;
+ use type UST.Long_Long_Unsigned;
+
+ XX : T := T'Machine (X);
+
+ Rep : Float_Rep;
+ for Rep'Address use XX'Address;
+ -- Rep is a view of the input floating-point parameter
+
+ Exp : constant IEEE_Erange :=
+ Integer ((Rep (MSW) and Exp_Mask) / Exp_Factor) - IEEE_Ebias;
+ -- Mask/Shift X to only get bits from the exponent. Then convert biased
+ -- value to final value.
+
+ Minus : constant Boolean := (Rep (MSW) and Sign_Mask) /= 0;
+ -- Mask/Shift X to only get bit from the sign
+
+ Expi, Expf : IEEE_Erange;
+
begin
- if X = 0.0 or else Adjustment = 0 then
+ -- Check for zero, infinities, NaNs as well as no adjustment
+
+ if X = 0.0 or else Exp = IEEE_Emax + 1 or else Adjustment = 0 then
return X;
- end if;
- -- Nonzero x essentially, just multiply repeatedly by Rad ** (+-2**n)
+ -- Check for nonzero denormalized numbers
- declare
- Y : T := X;
- Ex : UI := Adjustment;
+ elsif Exp = IEEE_Emin - 1 then
+ -- Check for zero result to protect the subtraction below
- -- Y * Rad ** Ex is invariant
+ if Adjustment < -(Mantissa - 1) then
+ XX := 0.0;
+ return (if Minus then -XX else XX);
- begin
- if Ex < 0 then
- while Ex <= -Log_Power (Expbits'Last) loop
- Y := Y * R_Neg_Power (Expbits'Last);
- Ex := Ex + Log_Power (Expbits'Last);
- end loop;
+ -- Normalize by multiplying by Radix ** (Mantissa - 1)
- -- -64 < Ex <= 0
+ else
+ return Scaling (XX * RM1, Adjustment - (Mantissa - 1));
+ end if;
- for N in reverse Expbits'First .. Expbits'Last - 1 loop
- if Ex <= -Log_Power (N) then
- Y := Y * R_Neg_Power (N);
- Ex := Ex + Log_Power (N);
- end if;
+ -- Case of normalized numbers
- -- -Log_Power (N) < Ex <= 0
+ else
+ -- Check for overflow
- end loop;
+ if Adjustment > IEEE_Emax - Exp then
+ XX := 0.0;
+ return (if Minus then -1.0 / XX else 1.0 / XX);
+ pragma Annotate
+ (CodePeer, Intentional, "overflow check", "Infinity produced");
+ pragma Annotate
+ (CodePeer, Intentional, "divide by zero", "Infinity produced");
- -- Ex = 0
+ -- Check for underflow
- else
- -- Ex >= 0
+ elsif Adjustment < IEEE_Emin - Exp then
+ -- Check for gradual underflow
- while Ex >= Log_Power (Expbits'Last) loop
- Y := Y * R_Power (Expbits'Last);
- Ex := Ex - Log_Power (Expbits'Last);
- end loop;
+ if T'Denorm
+ and then Adjustment >= IEEE_Emin - (Mantissa - 1) - Exp
+ then
+ Expf := IEEE_Emin;
+ Expi := Exp + Adjustment - Expf;
- -- 0 <= Ex < 64
+ -- Case of zero result
- for N in reverse Expbits'First .. Expbits'Last - 1 loop
- if Ex >= Log_Power (N) then
- Y := Y * R_Power (N);
- Ex := Ex - Log_Power (N);
- end if;
+ else
+ XX := 0.0;
+ return (if Minus then -XX else XX);
+ end if;
- -- 0 <= Ex < Log_Power (N)
+ -- Case of normalized results
- end loop;
+ else
+ Expf := Exp + Adjustment;
+ Expi := 0;
+ end if;
- -- Ex = 0
+ Rep (MSW) := (Rep (MSW) and not Exp_Mask) +
+ Float_Word (IEEE_Ebias + Expf) * Exp_Factor;
+ if Expi < 0 then
+ XX := XX / T (UST.Long_Long_Unsigned (2) ** (-Expi));
end if;
- return Y;
- end;
+ return XX;
+ end if;
end Scaling;
----------
@@ -650,36 +700,27 @@ package body System.Fat_Gen is
----------
function Succ (X : T) return T is
+ Tiny : constant T;
+ pragma Import (Ada, Tiny);
+ for Tiny'Address use (if T'Size = 16 then Tiny16'Address
+ elsif T'Size = 32 then Tiny32'Address
+ elsif T'Size = 64 then Tiny64'Address
+ elsif Mantissa = 64 then Tiny80'Address
+ else raise Program_Error);
X_Frac : T;
X_Exp : UI;
- X1, X2 : T;
begin
-- Treat zero specially since it has a zero exponent
if X = 0.0 then
- X1 := 2.0 ** T'Machine_Emin;
+ return Tiny;
- -- Following loop generates smallest denormal
-
- loop
- X2 := T'Machine (X1 / 2.0);
- exit when X2 = 0.0;
- X1 := X2;
- end loop;
-
- return X1;
-
- -- Special treatment for largest positive number
+ -- Special treatment for largest positive number: raise Constraint_Error
elsif X = T'Last then
-
- -- If not generating infinities, we raise a constraint error
-
raise Constraint_Error with "Succ of largest positive number";
- -- Otherwise generate a positive infinity
-
-- For infinities, return unchanged
elsif X < T'First or else X > T'Last then
@@ -689,30 +730,35 @@ package body System.Fat_Gen is
pragma Annotate (CodePeer, Intentional, "dead code",
"Check float range.");
- -- Add to the given number a number equivalent to the value
- -- of its least significant bit. Given that the most significant bit
- -- represents a value of 1.0 * radix ** (exp - 1), the value we want
- -- is obtained by shifting this by (mantissa-1) bits to the right,
+ -- Add to the given number a number equivalent to the value of its
+ -- least significant bit. Given that the most significant bit
+ -- represents a value of 1.0 * Radix ** (Exp - 1), the value we want
+ -- is obtained by shifting this by (Mantissa-1) bits to the right,
-- i.e. decreasing the exponent by that amount.
else
Decompose (X, X_Frac, X_Exp);
- -- A special case, if the number we had was a negative power of two,
- -- then we want to add half of what we would otherwise add, since the
- -- exponent is going to be reduced.
+ -- For a denormalized number or a normalized number with the lowest
+ -- exponent, just add the Tiny.
+
+ if X_Exp <= T'Machine_Emin then
+ return X + Tiny;
- -- Note that X_Frac has the same sign as X, so if X_Frac is -0.5,
- -- then we know that we have a negative number (and hence a negative
- -- power of 2).
+ -- A special case, if the number we had was a power of two on the
+ -- negative side of zero, then we want to add half of what we would
+ -- have added, since the exponent is going to be reduced.
- if X_Frac = -0.5 then
- return X + Gradual_Scaling (X_Exp - T'Machine_Mantissa - 1);
+ -- Note that X_Frac has the same sign as X, so if X_Frac is -Invrad,
+ -- then we know that we had a power of two on the negative side.
- -- Otherwise the exponent is unchanged
+ elsif X_Frac = -Invrad then
+ return X + Scaling (1.0, X_Exp - Mantissa - 1);
+
+ -- Otherwise the adjustment is unchanged
else
- return X + Gradual_Scaling (X_Exp - T'Machine_Mantissa);
+ return X + Scaling (1.0, X_Exp - Mantissa);
end if;
end if;
end Succ;
@@ -725,7 +771,7 @@ package body System.Fat_Gen is
-- T'Machine (RM1 + N) - RM1
- -- where N >= 0.0 and RM1 = radix ** (mantissa - 1)
+ -- where N >= 0.0 and RM1 = Radix ** (Mantissa - 1)
-- This works provided that the intermediate result (RM1 + N) does not
-- have extra precision (which is why we call Machine). When we compute
@@ -742,19 +788,18 @@ package body System.Fat_Gen is
begin
Result := abs X;
- if Result >= Radix_To_M_Minus_1 then
+ if Result >= RM1 then
return T'Machine (X);
else
- Result :=
- T'Machine (Radix_To_M_Minus_1 + Result) - Radix_To_M_Minus_1;
+ Result := T'Machine (RM1 + Result) - RM1;
if Result > abs X then
Result := Result - 1.0;
end if;
if X > 0.0 then
- return Result;
+ return Result;
elsif X < 0.0 then
return -Result;
@@ -805,132 +850,37 @@ package body System.Fat_Gen is
-----------
function Valid (X : not null access T) return Boolean is
- IEEE_Emin : constant Integer := T'Machine_Emin - 1;
- IEEE_Emax : constant Integer := T'Machine_Emax - 1;
-
- IEEE_Bias : constant Integer := -(IEEE_Emin - 1);
-
- subtype IEEE_Exponent_Range is
- Integer range IEEE_Emin - 1 .. IEEE_Emax + 1;
-
- -- The implementation of this floating point attribute uses a
- -- representation type Float_Rep that allows direct access to the
- -- exponent and mantissa parts of a floating point number.
-
- -- The Float_Rep type is an array of Float_Word elements. This
- -- representation is chosen to make it possible to size the type based
- -- on a generic parameter. Since the array size is known at compile
- -- time, efficient code can still be generated. The size of Float_Word
- -- elements should be large enough to allow accessing the exponent in
- -- one read, but small enough so that all floating point object sizes
- -- are a multiple of the Float_Word'Size.
-
- -- The following conditions must be met for all possible instantiations
- -- of the attributes package:
-
- -- - T'Size is an integral multiple of Float_Word'Size
-
- -- - The exponent and sign are completely contained in a single
- -- component of Float_Rep, named Most_Significant_Word (MSW).
-
- -- - The sign occupies the most significant bit of the MSW and the
- -- exponent is in the following bits. Unused bits (if any) are in
- -- the least significant part.
-
- type Float_Word is mod 2**Positive'Min (System.Word_Size, 32);
- type Rep_Index is range 0 .. 7;
-
- Rep_Words : constant Positive :=
- (T'Size + Float_Word'Size - 1) / Float_Word'Size;
- Rep_Last : constant Rep_Index :=
- Rep_Index'Min
- (Rep_Index (Rep_Words - 1),
- (T'Mantissa + 16) / Float_Word'Size);
- -- Determine the number of Float_Words needed for representing the
- -- entire floating-point value. Do not take into account excessive
- -- padding, as occurs on IA-64 where 80 bits floats get padded to 128
- -- bits. In general, the exponent field cannot be larger than 15 bits,
- -- even for 128-bit floating-point types, so the final format size
- -- won't be larger than T'Mantissa + 16.
-
- type Float_Rep is
- array (Rep_Index range 0 .. Rep_Index (Rep_Words - 1)) of Float_Word;
-
- pragma Suppress_Initialization (Float_Rep);
- -- This pragma suppresses the generation of an initialization procedure
- -- for type Float_Rep when operating in Initialize/Normalize_Scalars
- -- mode. This is not just a matter of efficiency, but of functionality,
- -- since Valid has a pragma Inline_Always, which is not permitted if
- -- there are nested subprograms present.
-
- Most_Significant_Word : constant Rep_Index :=
- Rep_Last * Standard'Default_Bit_Order;
- -- Finding the location of the Exponent_Word is a bit tricky. In general
- -- we assume Word_Order = Bit_Order.
-
- Exponent_Factor : constant Float_Word :=
- 2**(Float_Word'Size - 1) /
- Float_Word (IEEE_Emax - IEEE_Emin + 3) *
- Boolean'Pos (Most_Significant_Word /= 2) +
- Boolean'Pos (Most_Significant_Word = 2);
- -- Factor that the extracted exponent needs to be divided by to be in
- -- range 0 .. IEEE_Emax - IEEE_Emin + 2. Special case: Exponent_Factor
- -- is 1 for x86/IA64 double extended (GCC adds unused bits to the type).
-
- Exponent_Mask : constant Float_Word :=
- Float_Word (IEEE_Emax - IEEE_Emin + 2) *
- Exponent_Factor;
- -- Value needed to mask out the exponent field. This assumes that the
- -- range IEEE_Emin - 1 .. IEEE_Emax + contains 2**N values, for some N
- -- in Natural.
-
- function To_Float is new Ada.Unchecked_Conversion (Float_Rep, T);
-
- type Float_Access is access all T;
+ type Access_T is access all T;
function To_Address is
- new Ada.Unchecked_Conversion (Float_Access, System.Address);
-
- XA : constant System.Address := To_Address (Float_Access (X));
+ new Ada.Unchecked_Conversion (Access_T, System.Address);
- R : Float_Rep;
- pragma Import (Ada, R);
- for R'Address use XA;
- -- R is a view of the input floating-point parameter. Note that we
- -- must avoid copying the actual bits of this parameter in float
- -- form (since it may be a signalling NaN).
+ Rep : Float_Rep;
+ for Rep'Address use To_Address (Access_T (X));
+ -- Rep is a view of the input floating-point parameter. Note that we
+ -- must avoid reading the actual bits of this parameter in float form
+ -- since it may be a signalling NaN.
- E : constant IEEE_Exponent_Range :=
- Integer ((R (Most_Significant_Word) and Exponent_Mask) /
- Exponent_Factor)
- - IEEE_Bias;
- -- Mask/Shift T to only get bits from the exponent. Then convert biased
- -- value to integer value.
-
- SR : Float_Rep;
- -- Float_Rep representation of significant of X.all
+ Exp : constant IEEE_Erange :=
+ Integer ((Rep (MSW) and Exp_Mask) / Exp_Factor) - IEEE_Ebias;
+ -- Mask/Shift X to only get bits from the exponent. Then convert biased
+ -- value to final value.
begin
- if T'Denorm then
-
- -- All denormalized numbers are valid, so the only invalid numbers
- -- are overflows and NaNs, both with exponent = Emax + 1.
+ if Exp = IEEE_Emax + 1 then
+ -- This is an infinity or a NaN, i.e. always invalid
- return E /= IEEE_Emax + 1;
+ return False;
- end if;
+ elsif Exp in IEEE_Emin .. IEEE_Emax then
+ -- This is a normalized number, i.e. always valid
- -- All denormalized numbers except 0.0 are invalid
+ return True;
- -- Set exponent of X to zero, so we end up with the significand, which
- -- definitely is a valid number and can be converted back to a float.
+ else pragma Assert (Exp = IEEE_Emin - 1);
+ -- This is a denormalized number, valid if T'Denorm is True or 0.0
- SR := R;
- SR (Most_Significant_Word) :=
- (SR (Most_Significant_Word)
- and not Exponent_Mask) + Float_Word (IEEE_Bias) * Exponent_Factor;
-
- return (E in IEEE_Emin .. IEEE_Emax) or else
- ((E = IEEE_Emin - 1) and then abs To_Float (SR) = 1.0);
+ return T'Denorm or else X.all = 0.0;
+ end if;
end Valid;
end System.Fat_Gen;
diff --git a/gcc/ada/libgnat/s-fatgen.ads b/gcc/ada/libgnat/s-fatgen.ads
index b84d23b..700cfdc 100644
--- a/gcc/ada/libgnat/s-fatgen.ads
+++ b/gcc/ada/libgnat/s-fatgen.ads
@@ -31,9 +31,8 @@
-- This generic package provides a target independent implementation of the
-- floating-point attributes that denote functions. The implementations here
--- are portable, but very slow. The runtime contains a set of instantiations
--- of this package for all predefined floating-point types, and these should
--- be replaced by efficient assembly language code where possible.
+-- should be portable and reasonably efficient. The runtime contains a set of
+-- instantiations of this package for all predefined floating-point types.
generic
type T is digits <>;
@@ -107,12 +106,12 @@ package System.Fat_Gen is
-- floating point register).
private
+ pragma Inline (Compose);
+ pragma Inline (Copy_Sign);
+ pragma Inline (Exponent);
+ pragma Inline (Fraction);
pragma Inline (Machine);
pragma Inline (Model);
-
- -- Note: previously the validity checking subprograms (Unaligned_Valid and
- -- Valid) were also inlined, but this was changed since there were some
- -- problems with this inlining in optimized mode, and in any case it seems
- -- better to avoid this inlining (space and robustness considerations).
+ pragma Inline (Valid);
end System.Fat_Gen;
diff --git a/gcc/ada/libgnat/s-fatsfl.ads b/gcc/ada/libgnat/s-fatsfl.ads
deleted file mode 100644
index 45b13e1..0000000
--- a/gcc/ada/libgnat/s-fatsfl.ads
+++ /dev/null
@@ -1,47 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y S T E M . F A T _ S F L T --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This package contains an instantiation of the floating-point attribute
--- runtime routines for the type Short_Float.
-
-with System.Fat_Gen;
-
-package System.Fat_SFlt is
- pragma Pure;
-
- -- Note the only entity from this package that is accessed by Rtsfind
- -- is the name of the package instantiation. Entities within this package
- -- (i.e. the individual floating-point attribute routines) are accessed
- -- by name using selected notation.
-
- package Attr_Short_Float is new System.Fat_Gen (Short_Float);
-
-end System.Fat_SFlt;
diff --git a/gcc/ada/libgnat/s-finmas.adb b/gcc/ada/libgnat/s-finmas.adb
index 5a6583a..3e9ae58 100644
--- a/gcc/ada/libgnat/s-finmas.adb
+++ b/gcc/ada/libgnat/s-finmas.adb
@@ -119,20 +119,6 @@ package body System.Finalization_Masters is
Finalize_Address_Table.Remove (Obj);
end Delete_Finalize_Address_Unprotected;
- ------------
- -- Detach --
- ------------
-
- procedure Detach (N : not null FM_Node_Ptr) is
- begin
- Lock_Task.all;
- Detach_Unprotected (N);
- Unlock_Task.all;
-
- -- Note: No need to unlock in case of an exception because the above
- -- code can never raise one.
- end Detach;
-
------------------------
-- Detach_Unprotected --
------------------------
diff --git a/gcc/ada/libgnat/s-finmas.ads b/gcc/ada/libgnat/s-finmas.ads
index ae0276f..eb30ea1 100644
--- a/gcc/ada/libgnat/s-finmas.ads
+++ b/gcc/ada/libgnat/s-finmas.ads
@@ -86,10 +86,6 @@ package System.Finalization_Masters is
-- Destroy the relation pair object - Finalize_Address from the internal
-- hash table.
- procedure Detach (N : not null FM_Node_Ptr);
- -- Compiler interface, do not call from within the run-time. Remove a node
- -- from an arbitrary finalization master.
-
procedure Detach_Unprotected (N : not null FM_Node_Ptr);
-- Remove a node from an arbitrary finalization master
diff --git a/gcc/ada/libgnat/s-fode128.ads b/gcc/ada/libgnat/s-fode128.ads
new file mode 100644
index 0000000..200a020
--- /dev/null
+++ b/gcc/ada/libgnat/s-fode128.ads
@@ -0,0 +1,48 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ D E C I M A L _ 1 2 8 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the 'Fore attribute for decimal
+-- fixed point types up to 128-bit mantissa.
+
+with Interfaces;
+with System.Fore_D;
+
+package System.Fore_Decimal_128 is
+ pragma Pure;
+
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Impl is new Fore_D (Int128);
+
+ function Fore_Decimal128 (Lo, Hi : Int128; Scale : Integer) return Natural
+ renames Impl.Fore_Decimal;
+
+end System.Fore_Decimal_128;
diff --git a/gcc/ada/libgnat/s-fode32.ads b/gcc/ada/libgnat/s-fode32.ads
new file mode 100644
index 0000000..15c07a4
--- /dev/null
+++ b/gcc/ada/libgnat/s-fode32.ads
@@ -0,0 +1,48 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ D E C I M A L _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the 'Fore attribute for decimal
+-- fixed point types up to 32-bit mantissa.
+
+with Interfaces;
+with System.Fore_D;
+
+package System.Fore_Decimal_32 is
+ pragma Pure;
+
+ subtype Int32 is Interfaces.Integer_32;
+
+ package Impl is new Fore_D (Int32);
+
+ function Fore_Decimal32 (Lo, Hi : Int32; Scale : Integer) return Natural
+ renames Impl.Fore_Decimal;
+
+end System.Fore_Decimal_32;
diff --git a/gcc/ada/libgnat/s-fode64.ads b/gcc/ada/libgnat/s-fode64.ads
new file mode 100644
index 0000000..7e98185
--- /dev/null
+++ b/gcc/ada/libgnat/s-fode64.ads
@@ -0,0 +1,48 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ D E C I M A L _ 6 4 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the 'Fore attribute for decimal
+-- fixed point types up to 64-bit mantissa.
+
+with Interfaces;
+with System.Fore_D;
+
+package System.Fore_Decimal_64 is
+ pragma Pure;
+
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Impl is new Fore_D (Int64);
+
+ function Fore_Decimal64 (Lo, Hi : Int64; Scale : Integer) return Natural
+ renames Impl.Fore_Decimal;
+
+end System.Fore_Decimal_64;
diff --git a/gcc/ada/libgnat/s-fofi128.ads b/gcc/ada/libgnat/s-fofi128.ads
new file mode 100644
index 0000000..aaa117f
--- /dev/null
+++ b/gcc/ada/libgnat/s-fofi128.ads
@@ -0,0 +1,50 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O F I _ 1 2 8 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the 'Fore attribute for ordinary
+-- fixed point types up to 128-bit small and mantissa.
+
+with Interfaces;
+with System.Arith_128;
+with System.Fore_F;
+
+package System.Fore_Fixed_128 is
+ pragma Pure;
+
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Impl is new Fore_F (Int128, Arith_128.Scaled_Divide128);
+
+ function Fore_Fixed128
+ (Lo, Hi, Num, Den : Int128; Scale : Integer) return Natural
+ renames Impl.Fore_Fixed;
+
+end System.Fore_Fixed_128;
diff --git a/gcc/ada/libgnat/s-fofi32.ads b/gcc/ada/libgnat/s-fofi32.ads
new file mode 100644
index 0000000..cf94fb8
--- /dev/null
+++ b/gcc/ada/libgnat/s-fofi32.ads
@@ -0,0 +1,50 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ F I X E D _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the 'Fore attribute for ordinary
+-- fixed point types up to 32-bit small and mantissa.
+
+with Interfaces;
+with System.Arith_32;
+with System.Fore_F;
+
+package System.Fore_Fixed_32 is
+ pragma Pure;
+
+ subtype Int32 is Interfaces.Integer_32;
+
+ package Impl is new Fore_F (Int32, Arith_32.Scaled_Divide32);
+
+ function Fore_Fixed32
+ (Lo, Hi, Num, Den : Int32; Scale : Integer) return Natural
+ renames Impl.Fore_Fixed;
+
+end System.Fore_Fixed_32;
diff --git a/gcc/ada/libgnat/s-fofi64.ads b/gcc/ada/libgnat/s-fofi64.ads
new file mode 100644
index 0000000..cdde204
--- /dev/null
+++ b/gcc/ada/libgnat/s-fofi64.ads
@@ -0,0 +1,50 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ F I X E D _ 6 4 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the 'Fore attribute for ordinary
+-- fixed point types up to 64-bit small and mantissa.
+
+with Interfaces;
+with System.Arith_64;
+with System.Fore_F;
+
+package System.Fore_Fixed_64 is
+ pragma Pure;
+
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Impl is new Fore_F (Int64, Arith_64.Scaled_Divide64);
+
+ function Fore_Fixed64
+ (Lo, Hi, Num, Den : Int64; Scale : Integer) return Natural
+ renames Impl.Fore_Fixed;
+
+end System.Fore_Fixed_64;
diff --git a/gcc/ada/libgnat/s-fore.adb b/gcc/ada/libgnat/s-fore.adb
deleted file mode 100644
index 2a4aa81..0000000
--- a/gcc/ada/libgnat/s-fore.adb
+++ /dev/null
@@ -1,56 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . F O R E --
--- --
--- B o d y --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-package body System.Fore is
-
- ----------
- -- Fore --
- ----------
-
- function Fore (Lo, Hi : Long_Long_Float) return Natural is
- T : Long_Long_Float := Long_Long_Float'Max (abs Lo, abs Hi);
- R : Natural;
-
- begin
- -- Initial value of 2 allows for sign and mandatory single digit
-
- R := 2;
-
- -- Loop to increase Fore as needed to include full range of values
-
- while T >= 10.0 loop
- T := T / 10.0;
- R := R + 1;
- end loop;
-
- return R;
- end Fore;
-end System.Fore;
diff --git a/gcc/ada/libgnat/s-fore.ads b/gcc/ada/libgnat/s-fore.ads
deleted file mode 100644
index 7d78952..0000000
--- a/gcc/ada/libgnat/s-fore.ads
+++ /dev/null
@@ -1,41 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . F O R E --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This package contains the routine used for the 'Fore attribute
-
-package System.Fore is
- pragma Pure;
-
- function Fore (Lo, Hi : Long_Long_Float) return Natural;
- -- Compute Fore attribute value for a fixed-point type. The parameters
- -- are the low and high bounds values, converted to Long_Long_Float.
-
-end System.Fore;
diff --git a/gcc/ada/libgnat/s-fore_d.adb b/gcc/ada/libgnat/s-fore_d.adb
new file mode 100644
index 0000000..1141c67
--- /dev/null
+++ b/gcc/ada/libgnat/s-fore_d.adb
@@ -0,0 +1,62 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ D --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+package body System.Fore_D is
+
+ ------------------
+ -- Fore_Decimal --
+ ------------------
+
+ function Fore_Decimal (Lo, Hi : Int; Scale : Integer) return Natural is
+
+ function Negative_Abs (Val : Int) return Int is
+ (if Val <= 0 then Val else -Val);
+ -- Return the opposite of the absolute value of Val
+
+ T : Int := Int'Min (Negative_Abs (Lo), Negative_Abs (Hi));
+ F : Natural;
+
+ begin
+ -- Initial value of 2 allows for sign and mandatory single digit
+
+ F := 2;
+
+ -- Loop to increase Fore as needed to include full range of values
+
+ while T <= -10 loop
+ T := T / 10;
+ F := F + 1;
+ end loop;
+
+ return Natural'Max (F - Scale, 2);
+ end Fore_Decimal;
+
+end System.Fore_D;
diff --git a/gcc/ada/libgnat/s-fore_d.ads b/gcc/ada/libgnat/s-fore_d.ads
new file mode 100644
index 0000000..25e3449
--- /dev/null
+++ b/gcc/ada/libgnat/s-fore_d.ads
@@ -0,0 +1,47 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the Fore attribute of decimal
+-- fixed point types.
+
+generic
+
+ type Int is range <>;
+
+package System.Fore_D is
+ pragma Pure;
+
+ function Fore_Decimal (Lo, Hi : Int; Scale : Integer) return Natural;
+ -- Compute Fore attribute value for a decimal fixed point type. The
+ -- parameters are the low and high bounds (in units of delta) and the
+ -- scale.
+
+end System.Fore_D;
diff --git a/gcc/ada/libgnat/s-fore_f.adb b/gcc/ada/libgnat/s-fore_f.adb
new file mode 100644
index 0000000..c9c476d
--- /dev/null
+++ b/gcc/ada/libgnat/s-fore_f.adb
@@ -0,0 +1,136 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ F --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+package body System.Fore_F is
+
+ Maxdigs : constant Natural := Int'Width - 2;
+ -- Maximum number of decimal digits that can be represented in an Int.
+ -- The "-2" accounts for the sign and one extra digit, since we need the
+ -- maximum number of 9's that can be represented, e.g. for the 64-bit case,
+ -- Integer_64'Width is 20 since the maximum value is approximately 9.2E+18
+ -- and has 19 digits, but the maximum number of 9's that can be represented
+ -- in Integer_64 is only 18.
+
+ -- The first prerequisite of the implementation is that the scaled divide
+ -- does not overflow, which means that the absolute value of the bounds of
+ -- the subtype must be smaller than 10**Maxdigs * 2**(Int'Size - 1).
+ -- Otherwise Constraint_Error is raised by the scaled divide operation.
+
+ -- The second prerequisite is that the computation of the operands does not
+ -- overflow, which means that, if the small is larger than 1, it is either
+ -- an integer or its numerator and denominator must be both smaller than
+ -- the power 10**(Maxdigs - 1).
+
+ ----------------
+ -- Fore_Fixed --
+ ----------------
+
+ function Fore_Fixed (Lo, Hi, Num, Den : Int; Scale : Integer) return Natural
+ is
+ pragma Assert (Num < 0 and then Den < 0);
+ -- Accept only negative numbers to allow -2**(Int'Size - 1)
+
+ function Negative_Abs (Val : Int) return Int is
+ (if Val <= 0 then Val else -Val);
+ -- Return the opposite of the absolute value of Val
+
+ T : Int := Int'Min (Negative_Abs (Lo), Negative_Abs (Hi));
+ F : Natural;
+
+ Q, R : Int;
+
+ begin
+ -- Initial value of 2 allows for sign and mandatory single digit
+
+ F := 2;
+
+ -- The easy case is when Num is not larger than Den in magnitude,
+ -- i.e. if S = Num / Den, then S <= 1, in which case we can just
+ -- compute the product Q = T * S.
+
+ if Num >= Den then
+ Scaled_Divide (T, Num, Den, Q, R, Round => False);
+ T := Q;
+
+ -- Otherwise S > 1 and thus Scale <= 0, compute Q and R such that
+
+ -- T * Num = Q * (Den * 10**(-D)) + R
+
+ -- with
+
+ -- D = Integer'Max (-Maxdigs, Scale - 1)
+
+ -- then reason on Q if it is non-zero or else on R / Den.
+
+ -- This works only if Den * 10**(-D) does not overflow, which is true
+ -- if Den = 1. Suppose that Num corresponds to the maximum value of -D,
+ -- i.e. Maxdigs and 10**(-D) = 10**Maxdigs. If you change Den into 10,
+ -- then S becomes 10 times smaller and, therefore, Scale is incremented
+ -- by 1, which means that -D is decremented by 1 provided that Scale was
+ -- initially not smaller than 1 - Maxdigs, so the multiplication still
+ -- does not overflow. But you need to reach 10 to trigger this effect,
+ -- which means that a leeway of 10 is required, so let's restrict this
+ -- to a Num for which 10**(-D) <= 10**(Maxdigs - 1). To sum up, if S is
+ -- the ratio of two integers with
+
+ -- 1 < Den < Num <= B
+
+ -- where B is a fixed limit, then the multiplication does not overflow.
+ -- B can be taken as the largest integer Small such that D = 1 - Maxdigs
+ -- i.e. such that Scale = 2 - Maxdigs, which is 10**(Maxdigs - 1) - 1.
+
+ else
+ declare
+ D : constant Integer := Integer'Max (-Maxdigs, Scale - 1);
+
+ begin
+ Scaled_Divide (T, Num, Den * 10**(-D), Q, R, Round => False);
+
+ if Q /= 0 then
+ T := Q;
+ F := F - D;
+ else
+ T := R / Den;
+ end if;
+ end;
+ end if;
+
+ -- Loop to increase Fore as needed to include full range of values
+
+ while T <= -10 or else T >= 10 loop
+ T := T / 10;
+ F := F + 1;
+ end loop;
+
+ return F;
+ end Fore_Fixed;
+
+end System.Fore_F;
diff --git a/gcc/ada/libgnat/s-fore_f.ads b/gcc/ada/libgnat/s-fore_f.ads
new file mode 100644
index 0000000..cf6d983
--- /dev/null
+++ b/gcc/ada/libgnat/s-fore_f.ads
@@ -0,0 +1,54 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ F --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the Fore attribute of ordinary
+-- fixed point types whose Small is the ratio of two Int values.
+
+generic
+
+ type Int is range <>;
+
+ with procedure Scaled_Divide
+ (X, Y, Z : Int;
+ Q, R : out Int;
+ Round : Boolean);
+
+package System.Fore_F is
+ pragma Pure;
+
+ function Fore_Fixed
+ (Lo, Hi, Num, Den : Int; Scale : Integer) return Natural;
+ -- Compute Fore attribute value for an ordinary fixed point type. The
+ -- parameters are the low and high bounds (in units of small), the small
+ -- Num/Den and the associated scale, which is the smallest integer N such
+ -- that 10**N * (Num/Den) is greater or equal to 1, if it is nonpositive.
+
+end System.Fore_F;
diff --git a/gcc/ada/libgnat/s-forrea.adb b/gcc/ada/libgnat/s-forrea.adb
new file mode 100644
index 0000000..cb74dc6
--- /dev/null
+++ b/gcc/ada/libgnat/s-forrea.adb
@@ -0,0 +1,57 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ R E A L --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+package body System.Fore_Real is
+
+ ---------------
+ -- Fore_Real --
+ ---------------
+
+ function Fore_Real (Lo, Hi : Long_Long_Float) return Natural is
+ T : Long_Long_Float := Long_Long_Float'Max (abs Lo, abs Hi);
+ F : Natural;
+
+ begin
+ -- Initial value of 2 allows for sign and mandatory single digit
+
+ F := 2;
+
+ -- Loop to increase Fore as needed to include full range of values
+
+ while T >= 10.0 loop
+ T := T / 10.0;
+ F := F + 1;
+ end loop;
+
+ return F;
+ end Fore_Real;
+
+end System.Fore_Real;
diff --git a/gcc/ada/libgnat/s-forrea.ads b/gcc/ada/libgnat/s-forrea.ads
new file mode 100644
index 0000000..6b0a211
--- /dev/null
+++ b/gcc/ada/libgnat/s-forrea.ads
@@ -0,0 +1,42 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . F O R E _ R E A L --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routine used for the Fore attribute of ordinary
+-- fixed point types whose Small is neither an integer nor its reciprocal.
+
+package System.Fore_Real is
+ pragma Pure;
+
+ function Fore_Real (Lo, Hi : Long_Long_Float) return Natural;
+ -- Compute Fore attribute value for a fixed point type. The parameters
+ -- are the low and high bounds, converted to Long_Long_Float.
+
+end System.Fore_Real;
diff --git a/gcc/ada/libgnat/s-genbig.adb b/gcc/ada/libgnat/s-genbig.adb
index 12167ac..bf222ac 100644
--- a/gcc/ada/libgnat/s-genbig.adb
+++ b/gcc/ada/libgnat/s-genbig.adb
@@ -1193,7 +1193,7 @@ package body System.Generic_Bignums is
return To_Bignum (Long_Long_Long_Integer (X));
end To_Bignum;
- function To_Bignum (X : Unsigned_64) return Big_Integer is
+ function To_Bignum (X : Unsigned_128) return Big_Integer is
begin
if X = 0 then
return Allocate_Big_Integer ((1 .. 0 => <>), False);
@@ -1205,11 +1205,33 @@ package body System.Generic_Bignums is
-- Two word result
- else
+ elsif Shift_Right (X, 32) < 2 ** 32 then
return Allocate_Big_Integer ((SD (X / Base), SD (X mod Base)), False);
+
+ -- Three or four word result
+
+ else
+ declare
+ Vector : Digit_Vector (1 .. 4);
+ High : constant Unsigned_64 := Unsigned_64 (Shift_Right (X, 64));
+ Low : constant Unsigned_64 :=
+ Unsigned_64 (X and 16#FFFF_FFFF_FFFF_FFFF#);
+
+ begin
+ Vector (1) := SD (High / Base);
+ Vector (2) := SD (High mod Base);
+ Vector (3) := SD (Low / Base);
+ Vector (4) := SD (Low mod Base);
+ return Normalize (Vector, False);
+ end;
end if;
end To_Bignum;
+ function To_Bignum (X : Unsigned_64) return Big_Integer is
+ begin
+ return To_Bignum (Unsigned_128 (X));
+ end To_Bignum;
+
---------------
-- To_String --
---------------
diff --git a/gcc/ada/libgnat/s-genbig.ads b/gcc/ada/libgnat/s-genbig.ads
index 81e3843..be8340e 100644
--- a/gcc/ada/libgnat/s-genbig.ads
+++ b/gcc/ada/libgnat/s-genbig.ads
@@ -109,6 +109,10 @@ package System.Generic_Bignums is
-- Convert Unsigned_64 to a big integer. No exception can be raised for any
-- input argument.
+ function To_Bignum (X : Interfaces.Unsigned_128) return Big_Integer;
+ -- Convert Unsigned_128 to a big integer. No exception can be raised for
+ -- any input argument.
+
function From_Bignum (X : Bignum) return Long_Long_Integer;
-- Convert Bignum to Long_Long_Integer. Constraint_Error raised with
-- appropriate message if value is out of range of Long_Long_Integer.
diff --git a/gcc/ada/libgnat/s-imaged.adb b/gcc/ada/libgnat/s-imaged.adb
new file mode 100644
index 0000000..726b9d8
--- /dev/null
+++ b/gcc/ada/libgnat/s-imaged.adb
@@ -0,0 +1,81 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M A G E _ D --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Img_Util; use System.Img_Util;
+
+package body System.Image_D is
+
+ -------------------
+ -- Image_Decimal --
+ -------------------
+
+ procedure Image_Decimal
+ (V : Int;
+ S : in out String;
+ P : out Natural;
+ Scale : Integer)
+ is
+ pragma Assert (S'First = 1);
+
+ begin
+ -- Add space at start for non-negative numbers
+
+ if V >= 0 then
+ S (1) := ' ';
+ P := 1;
+ else
+ P := 0;
+ end if;
+
+ Set_Image_Decimal (V, S, P, Scale, 1, Integer'Max (1, Scale), 0);
+ end Image_Decimal;
+
+ -----------------------
+ -- Set_Image_Decimal --
+ -----------------------
+
+ procedure Set_Image_Decimal
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ is
+ Digs : String := Int'Image (V);
+ -- Sign and digits of decimal value
+
+ begin
+ Set_Decimal_Digits (Digs, Digs'Length, S, P, Scale, Fore, Aft, Exp);
+ end Set_Image_Decimal;
+
+end System.Image_D;
diff --git a/gcc/ada/libgnat/s-imaged.ads b/gcc/ada/libgnat/s-imaged.ads
new file mode 100644
index 0000000..5c3f82a
--- /dev/null
+++ b/gcc/ada/libgnat/s-imaged.ads
@@ -0,0 +1,72 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M A G E _ D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- decimal fixed point types, and also for conversion operations required in
+-- Text_IO.Decimal_IO for such types.
+
+generic
+
+ type Int is range <>;
+
+package System.Image_D is
+ pragma Pure;
+
+ procedure Image_Decimal
+ (V : Int;
+ S : in out String;
+ P : out Natural;
+ Scale : Integer);
+ -- Computes fixed_type'Image (V), where V is the integer value (in units of
+ -- delta) of a decimal type whose Scale is as given and stores the result
+ -- S (1 .. P), updating P to the value of L. The image is given by the
+ -- rules in RM 3.5(34) for fixed-point type image functions. The caller
+ -- guarantees that S is long enough to hold the result and has a lower
+ -- bound of 1.
+
+ procedure Set_Image_Decimal
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+ -- Sets the image of V, where V is the integer value (in units of delta)
+ -- of a decimal type with the specified Scale, starting at S (P + 1) and
+ -- updating P to point to the last character stored, the caller promises
+ -- that the buffer is large enough and no check is made. Constraint_Error
+ -- will not necessarily be raised if this requirement is violated, since
+ -- it is perfectly valid to compile this unit with checks off. The Fore,
+ -- Aft and Exp values can be set to any valid values for the case of use
+ -- by Text_IO.Decimal_IO.
+
+end System.Image_D;
diff --git a/gcc/ada/libgnat/s-imagef.adb b/gcc/ada/libgnat/s-imagef.adb
new file mode 100644
index 0000000..94a7a2f
--- /dev/null
+++ b/gcc/ada/libgnat/s-imagef.adb
@@ -0,0 +1,362 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M A G E _ F --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Image_I;
+with System.Img_Util; use System.Img_Util;
+
+package body System.Image_F is
+
+ Maxdigs : constant Natural := Int'Width - 2;
+ -- Maximum number of decimal digits that can be represented in an Int.
+ -- The "-2" accounts for the sign and one extra digit, since we need the
+ -- maximum number of 9's that can be represented, e.g. for the 64-bit case,
+ -- Integer_64'Width is 20 since the maximum value is approximately 9.2E+18
+ -- and has 19 digits, but the maximum number of 9's that can be represented
+ -- in Integer_64 is only 18.
+
+ -- The first prerequisite of the implementation is that the first scaled
+ -- divide does not overflow, which means that the absolute value of the
+ -- input X must always be smaller than 10**Maxdigs * 2**(Int'Size - 1).
+ -- Otherwise Constraint_Error is raised by the scaled divide operation.
+
+ -- The second prerequisite of the implementation is that the computation
+ -- of the operands does not overflow when the small is neither an integer
+ -- nor the reciprocal of an integer, which means that its numerator and
+ -- denominator must be smaller than 10**(2*Maxdigs-1) / 2**(Int'Size - 1)
+ -- if the small is larger than 1, and smaller than 2**(Int'Size - 1) / 10
+ -- if the small is smaller than 1.
+
+ package Image_I is new System.Image_I (Int);
+
+ procedure Set_Image_Integer
+ (V : Int;
+ S : in out String;
+ P : in out Natural)
+ renames Image_I.Set_Image_Integer;
+
+ -- The following section describes a specific implementation choice for
+ -- performing base conversions needed for output of values of a fixed
+ -- point type T with small T'Small. The goal is to be able to output
+ -- all values of fixed point types with a precision of 64 bits and a
+ -- small in the range 2.0**(-63) .. 2.0**63. The reasoning can easily
+ -- be adapted to fixed point types with a precision of 32 or 128 bits.
+
+ -- The chosen algorithm uses fixed precision integer arithmetic for
+ -- reasons of simplicity and efficiency. It is important to understand
+ -- in what ways the most simple and accurate approach to fixed point I/O
+ -- is limiting, before considering more complicated schemes.
+
+ -- Without loss of generality assume T has a range (-2.0**63) * T'Small
+ -- .. (2.0**63 - 1) * T'Small, and is output with Aft digits after the
+ -- decimal point and T'Fore - 1 before. If T'Small is integer, or
+ -- 1.0 / T'Small is integer, let S = T'Small.
+
+ -- The idea is to convert a value X * S of type T to a 64-bit integer value
+ -- Q equal to 10.0**D * (X * S) rounded to the nearest integer, using only
+ -- a scaled integer divide of the form
+
+ -- Q = (X * Y) / Z,
+
+ -- where the variables X, Y, Z are 64-bit integers, and both multiplication
+ -- and division are done using full intermediate precision. Then the final
+ -- decimal value to be output is
+
+ -- Q * 10**(-D)
+
+ -- This value can be written to the output file or to the result string
+ -- according to the format described in RM A.3.10. The details of this
+ -- operation are omitted here.
+
+ -- A 64-bit value can represent all integers with 18 decimal digits, but
+ -- not all with 19 decimal digits. If the total number of requested ouput
+ -- digits (Fore - 1) + Aft is greater than 18 then, for purposes of the
+ -- conversion, Aft is adjusted to 18 - (Fore - 1). In that case, trailing
+ -- zeros can complete the output after writing the first 18 significant
+ -- digits, or the technique described in the next section can be used.
+ -- In addition, D cannot be smaller than -18, in order for 10.0**(-D) to
+ -- fit in a 64-bit integer.
+
+ -- The final expression for D is
+
+ -- D = Integer'Max (-18, Integer'Min (Aft, 18 - (Fore - 1)));
+
+ -- For Y and Z the following expressions can be derived:
+
+ -- Q = X * S * (10.0**D) = (X * Y) / Z
+
+ -- If S is an integer greater than or equal to one, then Fore must be at
+ -- least 20 in order to print T'First, which is at most -2.0**63. This
+ -- means that D < 0, so use
+
+ -- (1) Y = -S and Z = -10**(-D)
+
+ -- If 1.0 / S is an integer greater than one, use
+
+ -- (2) Y = -10**D and Z = -(1.0 / S), for D >= 0
+
+ -- or
+
+ -- (3) Y = -1 and Z = -(1.0 / S) * 10**(-D), for D < 0
+
+ -- Negative values are used for nominator Y and denominator Z, so that S
+ -- can have a maximum value of 2.0**63 and a minimum of 2.0**(-63). For
+ -- -(1.0 / S) in -1 .. -9, Fore will still be 20, and D will be negative,
+ -- as (-2.0**63) / -9 is greater than 10**18. In these cases there is room
+ -- in the denominator for the extra decimal scaling required, so case (3)
+ -- will not overflow.
+
+ -- In fact this reasoning can be generalized to most S which are the ratio
+ -- of two integers with bounded magnitude. Let S = Num / Den and rewrite
+ -- case (1) above where Den = 1 into
+
+ -- (1b) Y = -Num and Z = -Den * 10**(-D)
+
+ -- Suppose that Num corresponds to the maximum value of -D, i.e. 18 and
+ -- 10**(-D) = 10**18. If you change Den into 10, then S becomes 10 times
+ -- smaller and, therefore, Fore is decremented by 1, which means that -D
+ -- is as well, provided that Fore was initially not larger than 37, so the
+ -- multiplication for Z still does not overflow. But you need to reach 10
+ -- to trigger this effect, which means that a leeway of 10 is required, so
+ -- let's restrict this to a Num for which 10**(-D) <= 10**17. To summarize
+ -- this case, if S is the ratio of two integers with
+
+ -- Den < Num <= B1
+
+ -- where B1 is a fixed limit, then case (1b) does not overflow. B1 can be
+ -- taken as the largest integer Small such that D = -17, i.e. Fore = 36,
+ -- which means that B1 * 2.0**63 must be smaller than 10**35.
+
+ -- Let's continue and rewrite case (2) above when Num = 1 into
+
+ -- (2b) Y = -Num * 10**D and Z = -Den, for D >= 0
+
+ -- Note that D <= 18 - (Fore - 1) and Fore >= 2 so D <= 17, thus you can
+ -- safely change Num into 10 in the product, but then S becomes 10 times
+ -- larger and, therefore, Fore is incremented by 1, which means that D is
+ -- decremented by 1 so you again have a product lesser or equal to 10**17.
+ -- To sum up, if S is the ratio of two integers with
+
+ -- Num <= Den * S0
+
+ -- where S0 is the largest Small such that D >= 0, then case (2b) does not
+ -- overflow.
+
+ -- Let's conclude and rewrite case (3) above when Num = 1 into
+
+ -- (3b) Y = -Num and Z = -Den * 10**(-D), for D < 0
+
+ -- As explained above, this occurs only if both S0 < S < 1 and D = -1 and
+ -- is preserved if you scale up Num and Den simultaneously, what you can
+ -- do until Den * 10 tops the upper bound. To sum up, if S is the ratio of
+ -- two integers with
+
+ -- Den * S0 < Num < Den <= B2
+
+ -- where B2 is a fixed limit, then case (3b) does not overflow. B2 can be
+ -- taken as the largest integer such that B2 * 10 is smaller than 2.0**63.
+
+ -- The conclusion is that the algorithm works if the small is the ratio of
+ -- two integers in the range 1 .. 2**63 if either is equal to 1, or of two
+ -- integers in the range 1 .. B1 if the small is larger than 1, or of two
+ -- integers in the range 1 .. B2 if the small is smaller than 1.
+
+ -- Using a scaled divide which truncates and returns a remainder R,
+ -- another K trailing digits can be calculated by computing the value
+ -- (R * (10.0**K)) / Z using another scaled divide. This procedure
+ -- can be repeated to compute an arbitrary number of digits in linear
+ -- time and storage. The last scaled divide should be rounded, with
+ -- a possible carry propagating to the more significant digits, to
+ -- ensure correct rounding of the unit in the last place.
+
+ -----------------
+ -- Image_Fixed --
+ -----------------
+
+ procedure Image_Fixed
+ (V : Int;
+ S : in out String;
+ P : out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural)
+ is
+ pragma Assert (S'First = 1);
+
+ begin
+ -- Add space at start for non-negative numbers
+
+ if V >= 0 then
+ S (1) := ' ';
+ P := 1;
+ else
+ P := 0;
+ end if;
+
+ Set_Image_Fixed (V, S, P, Num, Den, For0, Aft0, 1, Aft0, 0);
+ end Image_Fixed;
+
+ ---------------------
+ -- Set_Image_Fixed --
+ ---------------------
+
+ procedure Set_Image_Fixed
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ is
+ pragma Assert (Num < 0 and then Den < 0);
+ -- Accept only negative numbers to allow -2**(Int'Size - 1)
+
+ A : constant Natural :=
+ Boolean'Pos (Exp > 0) * Aft0 + Natural'Max (Aft, 1) + 1;
+ -- Number of digits after the decimal point to be computed. If Exp is
+ -- positive, we need to compute Aft decimal digits after the first non
+ -- zero digit and we are guaranteed there is at least one in the first
+ -- Aft0 digits (unless V is zero). In both cases, we compute one more
+ -- digit than requested so that Set_Decimal_Digits can round at Aft.
+
+ D : constant Integer :=
+ Integer'Max (-Maxdigs, Integer'Min (A, Maxdigs - (For0 - 1)));
+ Y : constant Int := Num * 10**Integer'Max (0, D);
+ Z : constant Int := Den * 10**Integer'Max (0, -D);
+ -- See the description of the algorithm above
+
+ AF : constant Natural := A - D;
+ -- Number of remaining digits to be computed after the first round. It
+ -- is larger than A if the first round does not compute all the digits
+ -- before the decimal point, i.e. (For0 - 1) larger than Maxdigs.
+
+ N : constant Natural := 1 + (AF + Maxdigs - 1) / Maxdigs;
+ -- Number of rounds of scaled divide to be performed
+
+ Q : Int;
+ -- Quotient of the scaled divide in this round. Only the first round may
+ -- yield more than Maxdigs digits and has a significant sign.
+
+ Buf : String (1 .. Maxdigs);
+ Len : Natural;
+ -- Buffer for the image of the quotient
+
+ Digs : String (1 .. 2 + N * Maxdigs);
+ Ndigs : Natural;
+ -- Concatenated image of the successive quotients
+
+ Scale : Integer := 0;
+ -- Exponent such that the result is Digs (1 .. NDigs) * 10**(-Scale)
+
+ XX : Int := V;
+ YY : Int := Y;
+ -- First two operands of the scaled divide
+
+ begin
+ -- Set the first character like Image
+
+ if V >= 0 then
+ Digs (1) := ' ';
+ Ndigs := 1;
+ else
+ Ndigs := 0;
+ end if;
+
+ for J in 1 .. N loop
+ exit when XX = 0;
+
+ Scaled_Divide (XX, YY, Z, Q, R => XX, Round => False);
+
+ if J = 1 then
+ if Q /= 0 then
+ Set_Image_Integer (Q, Digs, Ndigs);
+ end if;
+
+ Scale := Scale + D;
+
+ -- Prepare for next round, if any
+
+ YY := 10**Maxdigs;
+
+ else
+ pragma Assert (-10**Maxdigs < Q and then Q < 10**Maxdigs);
+
+ Len := 0;
+ Set_Image_Integer (abs Q, Buf, Len);
+
+ pragma Assert (1 <= Len and then Len <= Maxdigs);
+
+ -- If no character but the space has been written, write the
+ -- minus if need be, since Set_Image_Integer did not do it.
+
+ if Ndigs <= 1 then
+ if Q /= 0 then
+ if Ndigs = 0 then
+ Digs (1) := '-';
+ end if;
+
+ Digs (2 .. Len + 1) := Buf (1 .. Len);
+ Ndigs := Len + 1;
+ end if;
+
+ -- Or else pad the output with zeroes up to Maxdigs
+
+ else
+ for K in 1 .. Maxdigs - Len loop
+ Digs (Ndigs + K) := '0';
+ end loop;
+
+ for K in 1 .. Len loop
+ Digs (Ndigs + Maxdigs - Len + K) := Buf (K);
+ end loop;
+
+ Ndigs := Ndigs + Maxdigs;
+ end if;
+
+ Scale := Scale + Maxdigs;
+ end if;
+ end loop;
+
+ -- If no digit was output, this is zero
+
+ if Ndigs <= 1 then
+ Digs (1 .. 2) := " 0";
+ Ndigs := 2;
+ end if;
+
+ Set_Decimal_Digits (Digs, Ndigs, S, P, Scale, Fore, Aft, Exp);
+ end Set_Image_Fixed;
+
+end System.Image_F;
diff --git a/gcc/ada/libgnat/s-imagef.ads b/gcc/ada/libgnat/s-imagef.ads
new file mode 100644
index 0000000..ace7e6b
--- /dev/null
+++ b/gcc/ada/libgnat/s-imagef.ads
@@ -0,0 +1,88 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M A G E _ F --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- ordinary fixed point types whose Small is the ratio of two Int values, and
+-- also for conversion operations required in Text_IO.Fixed_IO for such types.
+
+generic
+
+ type Int is range <>;
+
+ with procedure Scaled_Divide
+ (X, Y, Z : Int;
+ Q, R : out Int;
+ Round : Boolean);
+
+package System.Image_F is
+ pragma Pure;
+
+ procedure Image_Fixed
+ (V : Int;
+ S : in out String;
+ P : out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural);
+ -- Computes fixed_type'Image (V), where V is the integer value (in units of
+ -- small) of an ordinary fixed point type with small Num/Den, and stores
+ -- the result in S (1 .. P), updating P on return. The result is computed
+ -- according to the rules for image for fixed-point types (RM 3.5(34)).
+ -- For0 and Aft0 are the values of the Fore and Aft attributes for the
+ -- fixed point type whose mantissa type is Int and whose small is Num/Den.
+ -- This function is used only for fixed point whose Small is an integer or
+ -- its reciprocal (see package System.Img_Real for the handling of other
+ -- ordinary fixed-point types). The caller guarantees that S is long enough
+ -- to hold the result and has a lower bound of 1.
+
+ procedure Set_Image_Fixed
+ (V : Int;
+ S : in out String;
+ P : in out Natural;
+ Num : Int;
+ Den : Int;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+ -- Sets the image of V, where V is the integer value (in units of small)
+ -- of a fixed point type with small Num/Den, starting at S (P + 1) and
+ -- updating P to point to the last character stored, the caller promises
+ -- that the buffer is large enough and no check is made. Constraint_Error
+ -- will not necessarily be raised if this requirement is violated, since
+ -- it is perfectly valid to compile this unit with checks off. For0 and
+ -- Aft0 are the values of the Fore and Aft attributes for the fixed point
+ -- type whose mantissa type is Int and whose small is Num/Den. The Fore,
+ -- Aft and Exp can be set to any valid values for use by Text_IO.Fixed_IO.
+
+end System.Image_F;
diff --git a/gcc/ada/libgnat/s-imagei.adb b/gcc/ada/libgnat/s-imagei.adb
index c739dfb..36c1f6f 100644
--- a/gcc/ada/libgnat/s-imagei.adb
+++ b/gcc/ada/libgnat/s-imagei.adb
@@ -56,8 +56,11 @@ package body System.Image_I is
if V >= 0 then
S (1) := ' ';
P := 1;
+ pragma Assert (P < S'Last);
+
else
P := 0;
+ pragma Assert (P < S'Last - 1);
end if;
Set_Image_Integer (V, S, P);
@@ -72,26 +75,31 @@ package body System.Image_I is
S : in out String;
P : in out Natural)
is
+ Nb_Digits : Natural := 0;
+ Value : Non_Positive := T;
begin
- if T <= -10 then
- Set_Digits (T / 10, S, P);
- pragma Assert (P >= (S'First - 1) and P < S'Last and
- P < Natural'Last);
- -- No check is done since, as documented in the Set_Image_Integer
- -- specification, the caller guarantees that S is long enough to
- -- hold the result.
- P := P + 1;
- S (P) := Character'Val (48 - (T rem 10));
+ pragma Assert (P >= S'First - 1 and P < S'Last);
+ -- No check is done since, as documented in the Set_Image_Integer
+ -- specification, the caller guarantees that S is long enough to
+ -- hold the result.
- else
- pragma Assert (P >= (S'First - 1) and P < S'Last and
- P < Natural'Last);
- -- No check is done since, as documented in the Set_Image_Integer
- -- specification, the caller guarantees that S is long enough to
- -- hold the result.
- P := P + 1;
- S (P) := Character'Val (48 - T);
- end if;
+ -- First we compute the number of characters needed for representing
+ -- the number.
+ loop
+ Value := Value / 10;
+ Nb_Digits := Nb_Digits + 1;
+ exit when Value = 0;
+ end loop;
+
+ Value := T;
+
+ -- We now populate digits from the end of the string to the beginning
+ for J in reverse 1 .. Nb_Digits loop
+ S (P + J) := Character'Val (48 - (Value rem 10));
+ Value := Value / 10;
+ end loop;
+
+ P := P + Nb_Digits;
end Set_Digits;
-----------------------
@@ -108,8 +116,7 @@ package body System.Image_I is
Set_Digits (-V, S, P);
else
- pragma Assert (P >= (S'First - 1) and P < S'Last and
- P < Natural'Last);
+ pragma Assert (P >= S'First - 1 and P < S'Last);
-- No check is done since, as documented in the specification,
-- the caller guarantees that S is long enough to hold the result.
P := P + 1;
diff --git a/gcc/ada/libgnat/s-imageu.adb b/gcc/ada/libgnat/s-imageu.adb
index c995d55..8ffb8f0 100644
--- a/gcc/ada/libgnat/s-imageu.adb
+++ b/gcc/ada/libgnat/s-imageu.adb
@@ -56,24 +56,31 @@ package body System.Image_U is
S : in out String;
P : in out Natural)
is
+ Nb_Digits : Natural := 0;
+ Value : Uns := V;
begin
- if V >= 10 then
- Set_Image_Unsigned (V / 10, S, P);
- pragma Assert (P >= (S'First - 1) and P < S'Last and
- P < Natural'Last);
- -- No check is done since, as documented in the specification,
- -- the caller guarantees that S is long enough to hold the result.
- P := P + 1;
- S (P) := Character'Val (48 + (V rem 10));
+ pragma Assert (P >= S'First - 1 and then P < S'Last and then
+ P < Natural'Last);
+ -- No check is done since, as documented in the specification, the
+ -- caller guarantees that S is long enough to hold the result.
- else
- pragma Assert (P >= (S'First - 1) and P < S'Last and
- P < Natural'Last);
- -- No check is done since, as documented in the specification,
- -- the caller guarantees that S is long enough to hold the result.
- P := P + 1;
- S (P) := Character'Val (48 + V);
- end if;
+ -- First we compute the number of characters needed for representing
+ -- the number.
+ loop
+ Value := Value / 10;
+ Nb_Digits := Nb_Digits + 1;
+ exit when Value = 0;
+ end loop;
+
+ Value := V;
+
+ -- We now populate digits from the end of the string to the beginning
+ for J in reverse 1 .. Nb_Digits loop
+ S (P + J) := Character'Val (48 + (Value rem 10));
+ Value := Value / 10;
+ end loop;
+
+ P := P + Nb_Digits;
end Set_Image_Unsigned;
end System.Image_U;
diff --git a/gcc/ada/libgnat/s-imde128.ads b/gcc/ada/libgnat/s-imde128.ads
new file mode 100644
index 0000000..cffd0c0
--- /dev/null
+++ b/gcc/ada/libgnat/s-imde128.ads
@@ -0,0 +1,63 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ D E C I M A L _ 1 2 8 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- decimal fixed point types up to 128-bit mantissa, and also for conversion
+-- operations required in Text_IO.Decimal_IO for them.
+
+with Interfaces;
+with System.Image_D;
+
+package System.Img_Decimal_128 is
+ pragma Pure;
+
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Impl is new Image_D (Int128);
+
+ procedure Image_Decimal128
+ (V : Int128;
+ S : in out String;
+ P : out Natural;
+ Scale : Integer)
+ renames Impl.Image_Decimal;
+
+ procedure Set_Image_Decimal128
+ (V : Int128;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ renames Impl.Set_Image_Decimal;
+
+end System.Img_Decimal_128;
diff --git a/gcc/ada/libgnat/s-imde32.ads b/gcc/ada/libgnat/s-imde32.ads
new file mode 100644
index 0000000..bf19e9c
--- /dev/null
+++ b/gcc/ada/libgnat/s-imde32.ads
@@ -0,0 +1,63 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ D E C I M A L _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- decimal fixed point types up to 32-bit mantissa, and also for conversion
+-- operations required in Text_IO.Decimal_IO for such types.
+
+with Interfaces;
+with System.Image_D;
+
+package System.Img_Decimal_32 is
+ pragma Pure;
+
+ subtype Int32 is Interfaces.Integer_32;
+
+ package Impl is new Image_D (Int32);
+
+ procedure Image_Decimal32
+ (V : Int32;
+ S : in out String;
+ P : out Natural;
+ Scale : Integer)
+ renames Impl.Image_Decimal;
+
+ procedure Set_Image_Decimal32
+ (V : Int32;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ renames Impl.Set_Image_Decimal;
+
+end System.Img_Decimal_32;
diff --git a/gcc/ada/libgnat/s-imde64.ads b/gcc/ada/libgnat/s-imde64.ads
new file mode 100644
index 0000000..dfc8403
--- /dev/null
+++ b/gcc/ada/libgnat/s-imde64.ads
@@ -0,0 +1,63 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ D E C I M A L _ 6 4 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- decimal fixed point types up to 64-bit mantissa, and also for conversion
+-- operations required in Text_IO.Decimal_IO for such types.
+
+with Interfaces;
+with System.Image_D;
+
+package System.Img_Decimal_64 is
+ pragma Pure;
+
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Impl is new Image_D (Int64);
+
+ procedure Image_Decimal64
+ (V : Int64;
+ S : in out String;
+ P : out Natural;
+ Scale : Integer)
+ renames Impl.Image_Decimal;
+
+ procedure Set_Image_Decimal64
+ (V : Int64;
+ S : in out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ renames Impl.Set_Image_Decimal;
+
+end System.Img_Decimal_64;
diff --git a/gcc/ada/libgnat/s-imfi128.ads b/gcc/ada/libgnat/s-imfi128.ads
new file mode 100644
index 0000000..24fdf97
--- /dev/null
+++ b/gcc/ada/libgnat/s-imfi128.ads
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ F I X E D _ 1 2 8 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- ordinary fixed point types up to 128-bit small and mantissa.
+
+with Interfaces;
+with System.Arith_128;
+with System.Image_F;
+
+package System.Img_Fixed_128 is
+ pragma Pure;
+
+ subtype Int128 is Interfaces.Integer_128;
+
+ package Impl is new Image_F (Int128, Arith_128.Scaled_Divide128);
+
+ procedure Image_Fixed128
+ (V : Int128;
+ S : in out String;
+ P : out Natural;
+ Num : Int128;
+ Den : Int128;
+ For0 : Natural;
+ Aft0 : Natural)
+ renames Impl.Image_Fixed;
+
+ procedure Set_Image_Fixed128
+ (V : Int128;
+ S : in out String;
+ P : in out Natural;
+ Num : Int128;
+ Den : Int128;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ renames Impl.Set_Image_Fixed;
+
+end System.Img_Fixed_128;
diff --git a/gcc/ada/libgnat/s-imfi32.ads b/gcc/ada/libgnat/s-imfi32.ads
new file mode 100644
index 0000000..8c425df
--- /dev/null
+++ b/gcc/ada/libgnat/s-imfi32.ads
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ F I X E D _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- ordinary fixed point types up to 32-bit small and mantissa.
+
+with Interfaces;
+with System.Arith_32;
+with System.Image_F;
+
+package System.Img_Fixed_32 is
+ pragma Pure;
+
+ subtype Int32 is Interfaces.Integer_32;
+
+ package Impl is new Image_F (Int32, Arith_32.Scaled_Divide32);
+
+ procedure Image_Fixed32
+ (V : Int32;
+ S : in out String;
+ P : out Natural;
+ Num : Int32;
+ Den : Int32;
+ For0 : Natural;
+ Aft0 : Natural)
+ renames Impl.Image_Fixed;
+
+ procedure Set_Image_Fixed32
+ (V : Int32;
+ S : in out String;
+ P : in out Natural;
+ Num : Int32;
+ Den : Int32;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ renames Impl.Set_Image_Fixed;
+
+end System.Img_Fixed_32;
diff --git a/gcc/ada/libgnat/s-imfi64.ads b/gcc/ada/libgnat/s-imfi64.ads
new file mode 100644
index 0000000..9045bf6
--- /dev/null
+++ b/gcc/ada/libgnat/s-imfi64.ads
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ F I X E D _ 6 4 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Image attribute for
+-- ordinary fixed point types up to 64-bit small and mantissa.
+
+with Interfaces;
+with System.Arith_64;
+with System.Image_F;
+
+package System.Img_Fixed_64 is
+ pragma Pure;
+
+ subtype Int64 is Interfaces.Integer_64;
+
+ package Impl is new Image_F (Int64, Arith_64.Scaled_Divide64);
+
+ procedure Image_Fixed64
+ (V : Int64;
+ S : in out String;
+ P : out Natural;
+ Num : Int64;
+ Den : Int64;
+ For0 : Natural;
+ Aft0 : Natural)
+ renames Impl.Image_Fixed;
+
+ procedure Set_Image_Fixed64
+ (V : Int64;
+ S : in out String;
+ P : in out Natural;
+ Num : Int64;
+ Den : Int64;
+ For0 : Natural;
+ Aft0 : Natural;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ renames Impl.Set_Image_Fixed;
+
+end System.Img_Fixed_64;
diff --git a/gcc/ada/libgnat/s-imgdec.adb b/gcc/ada/libgnat/s-imgdec.adb
deleted file mode 100644
index 840dadb..0000000
--- a/gcc/ada/libgnat/s-imgdec.adb
+++ /dev/null
@@ -1,454 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ D E C --
--- --
--- B o d y --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-with System.Img_Int; use System.Img_Int;
-
-package body System.Img_Dec is
-
- -------------------
- -- Image_Decimal --
- -------------------
-
- procedure Image_Decimal
- (V : Integer;
- S : in out String;
- P : out Natural;
- Scale : Integer)
- is
- pragma Assert (S'First = 1);
-
- begin
- -- Add space at start for non-negative numbers
-
- if V >= 0 then
- S (1) := ' ';
- P := 1;
- else
- P := 0;
- end if;
-
- Set_Image_Decimal (V, S, P, Scale, 1, Integer'Max (1, Scale), 0);
- end Image_Decimal;
-
- ------------------------
- -- Set_Decimal_Digits --
- ------------------------
-
- procedure Set_Decimal_Digits
- (Digs : in out String;
- NDigs : Natural;
- S : out String;
- P : in out Natural;
- Scale : Integer;
- Fore : Natural;
- Aft : Natural;
- Exp : Natural)
- is
- pragma Assert (NDigs >= 1);
- pragma Assert (Digs'First = 1);
- pragma Assert (Digs'First < Digs'Last);
-
- Minus : constant Boolean := (Digs (Digs'First) = '-');
- -- Set True if input is negative
-
- Zero : Boolean := (Digs (Digs'First + 1) = '0');
- -- Set True if input is exactly zero (only case when a leading zero
- -- is permitted in the input string given to this procedure). This
- -- flag can get set later if rounding causes the value to become zero.
-
- FD : Natural := 2;
- -- First digit position of digits remaining to be processed
-
- LD : Natural := NDigs;
- -- Last digit position of digits remaining to be processed
-
- ND : Natural := NDigs - 1;
- -- Number of digits remaining to be processed (LD - FD + 1)
-
- Digits_Before_Point : Integer := ND - Scale;
- -- Number of digits before decimal point in the input value. This
- -- value can be negative if the input value is less than 0.1, so
- -- it is an indication of the current exponent. Digits_Before_Point
- -- is adjusted if the rounding step generates an extra digit.
-
- Digits_After_Point : constant Natural := Integer'Max (1, Aft);
- -- Digit positions after decimal point in result string
-
- Expon : Integer;
- -- Integer value of exponent
-
- procedure Round (N : Integer);
- -- Round the number in Digs. N is the position of the last digit to be
- -- retained in the rounded position (rounding is based on Digs (N + 1)
- -- FD, LD, ND are reset as necessary if required. Note that if the
- -- result value rounds up (e.g. 9.99 => 10.0), an extra digit can be
- -- placed in the sign position as a result of the rounding, this is
- -- the case in which FD is adjusted. The call to Round has no effect
- -- if N is outside the range FD .. LD.
-
- procedure Set (C : Character);
- pragma Inline (Set);
- -- Sets character C in output buffer
-
- procedure Set_Blanks_And_Sign (N : Integer);
- -- Sets leading blanks and minus sign if needed. N is the number of
- -- positions to be filled (a minus sign is output even if N is zero
- -- or negative, For a positive value, if N is non-positive, then
- -- a leading blank is filled.
-
- procedure Set_Digits (S, E : Natural);
- pragma Inline (Set_Digits);
- -- Set digits S through E from Digs, no effect if S > E
-
- procedure Set_Zeroes (N : Integer);
- pragma Inline (Set_Zeroes);
- -- Set N zeroes, no effect if N is negative
-
- -----------
- -- Round --
- -----------
-
- procedure Round (N : Integer) is
- D : Character;
-
- pragma Assert (NDigs >= 1);
- pragma Assert (Digs'First = 1);
- pragma Assert (Digs'First < Digs'Last);
-
- begin
- -- Nothing to do if rounding past the last digit we have
-
- if N >= LD then
- return;
-
- -- Cases of rounding before the initial digit
-
- elsif N < FD then
-
- -- The result is zero, unless we are rounding just before
- -- the first digit, and the first digit is five or more.
-
- if N = 1 and then Digs (Digs'First + 1) >= '5' then
- Digs (Digs'First) := '1';
- else
- Digs (Digs'First) := '0';
- Zero := True;
- end if;
-
- Digits_Before_Point := Digits_Before_Point + 1;
- FD := 1;
- LD := 1;
- ND := 1;
-
- -- Normal case of rounding an existing digit
-
- else
- LD := N;
- pragma Assert (LD >= 1);
- -- In this case, we have N < LD and N >= FD. FD is a Natural,
- -- So we can conclude, LD >= 1
- ND := LD - 1;
- pragma Assert (N + 1 <= Digs'Last);
-
- if Digs (N + 1) >= '5' then
- for J in reverse Digs'First + 1 .. Digs'First + N - 1 loop
- pragma Assert (Digs (J) in '0' .. '9' | ' ' | '-');
- -- Because it is a decimal image, we can assume that
- -- it can only contain these characters.
- D := Character'Succ (Digs (J));
-
- if D <= '9' then
- Digs (J) := D;
- return;
- else
- Digs (J) := '0';
- end if;
- end loop;
-
- -- Here the rounding overflows into the sign position. That's
- -- OK, because we already captured the value of the sign and
- -- we are in any case destroying the value in the Digs buffer
-
- Digs (Digs'First) := '1';
- FD := 1;
- ND := ND + 1;
- Digits_Before_Point := Digits_Before_Point + 1;
- end if;
- end if;
- end Round;
-
- ---------
- -- Set --
- ---------
-
- procedure Set (C : Character) is
- begin
- pragma Assert (P >= (S'First - 1) and P < S'Last and
- P < Natural'Last);
- -- No check is done as documented in the header : updating P to
- -- point to the last character stored, the caller promises that the
- -- buffer is large enough and no check is made for this.
- -- Constraint_Error will not necessarily be raised if this
- -- requirement is violated, since it is perfectly valid to compile
- -- this unit with checks off.
- --
- -- Due to codepeer limitation, codepeer should be used with switch:
- -- -no-propagation system.img_dec.set_decimal_digits.set
- P := P + 1;
- S (P) := C;
- end Set;
-
- -------------------------
- -- Set_Blanks_And_Sign --
- -------------------------
-
- procedure Set_Blanks_And_Sign (N : Integer) is
- W : Integer := N;
-
- begin
- if Minus then
- W := W - 1;
-
- for J in 1 .. W loop
- Set (' ');
- end loop;
-
- Set ('-');
-
- else
- for J in 1 .. W loop
- Set (' ');
- end loop;
- end if;
- end Set_Blanks_And_Sign;
-
- ----------------
- -- Set_Digits --
- ----------------
-
- procedure Set_Digits (S, E : Natural) is
- begin
- pragma Assert (S >= Digs'First and E <= Digs'Last);
- -- S and E should be in the Digs array range
- -- TBC: Analysis should be completed
- for J in S .. E loop
- Set (Digs (J));
- end loop;
- end Set_Digits;
-
- ----------------
- -- Set_Zeroes --
- ----------------
-
- procedure Set_Zeroes (N : Integer) is
- begin
- for J in 1 .. N loop
- Set ('0');
- end loop;
- end Set_Zeroes;
-
- -- Start of processing for Set_Decimal_Digits
-
- begin
- -- Case of exponent given
-
- if Exp > 0 then
- Set_Blanks_And_Sign (Fore - 1);
- Round (Digits_After_Point + 2);
-
- Set (Digs (FD));
- FD := FD + 1;
- pragma Assert (ND >= 1);
- ND := ND - 1;
- Set ('.');
-
- if ND >= Digits_After_Point then
- Set_Digits (FD, FD + Digits_After_Point - 1);
- else
- Set_Digits (FD, LD);
- Set_Zeroes (Digits_After_Point - ND);
- end if;
-
- -- Calculate exponent. The number of digits before the decimal point
- -- in the input is Digits_Before_Point, and the number of digits
- -- before the decimal point in the output is 1, so we can get the
- -- exponent as the difference between these two values. The one
- -- exception is for the value zero, which by convention has an
- -- exponent of +0.
-
- Expon := (if Zero then 0 else Digits_Before_Point - 1);
- Set ('E');
- ND := 0;
-
- if Expon >= 0 then
- Set ('+');
- Set_Image_Integer (Expon, Digs, ND);
- else
- Set ('-');
- Set_Image_Integer (-Expon, Digs, ND);
- end if;
-
- Set_Zeroes (Exp - ND - 1);
- Set_Digits (1, ND);
- return;
-
- -- Case of no exponent given. To make these cases clear, we use
- -- examples. For all the examples, we assume Fore = 2, Aft = 3.
- -- A P in the example input string is an implied zero position,
- -- not included in the input string.
-
- else
- -- Round at correct position
- -- Input: 4PP => unchanged
- -- Input: 400.03 => unchanged
- -- Input 3.4567 => 3.457
- -- Input: 9.9999 => 10.000
- -- Input: 0.PPP5 => 0.001
- -- Input: 0.PPP4 => 0
- -- Input: 0.00003 => 0
-
- Round (LD - (Scale - Digits_After_Point));
-
- -- No digits before point in input
- -- Input: .123 Output: 0.123
- -- Input: .PP3 Output: 0.003
-
- if Digits_Before_Point <= 0 then
- Set_Blanks_And_Sign (Fore - 1);
- Set ('0');
- Set ('.');
-
- declare
- DA : Natural := Digits_After_Point;
- -- Digits remaining to output after point
-
- LZ : constant Integer := Integer'Min (DA, -Digits_Before_Point);
- -- Number of leading zeroes after point. Note: there used to be
- -- a Max of this result with zero, but that's redundant, since
- -- we know DA is positive, and because of the test above, we
- -- know that -Digits_Before_Point >= 0.
-
- begin
- Set_Zeroes (LZ);
- DA := DA - LZ;
-
- if DA < ND then
-
- -- Note: it is definitely possible for the above condition
- -- to be True, for example:
-
- -- V => 1234, Scale => 5, Fore => 0, After => 1, Exp => 0
-
- -- but in this case DA = 0, ND = 1, FD = 1, FD + DA-1 = 0
- -- so the arguments in the call are (1, 0) meaning that no
- -- digits are output.
-
- -- No obvious example exists where the following call to
- -- Set_Digits actually outputs some digits, but we lack a
- -- proof that no such example exists.
-
- -- So it is safer to retain this call, even though as a
- -- result it is hard (or perhaps impossible) to create a
- -- coverage test for the inlined code of the call.
-
- Set_Digits (FD, FD + DA - 1);
-
- else
- Set_Digits (FD, LD);
- Set_Zeroes (DA - ND);
- end if;
- end;
-
- -- At least one digit before point in input
-
- else
- -- Less digits in input than are needed before point
- -- Input: 1PP Output: 100.000
-
- if ND < Digits_Before_Point then
-
- -- Special case, if the input is the single digit 0, then we
- -- do not want 000.000, but instead 0.000.
-
- if ND = 1 and then Digs (FD) = '0' then
- Set_Blanks_And_Sign (Fore - 1);
- Set ('0');
-
- -- Normal case where we need to output scaling zeroes
-
- else
- Set_Blanks_And_Sign (Fore - Digits_Before_Point);
- Set_Digits (FD, LD);
- Set_Zeroes (Digits_Before_Point - ND);
- end if;
-
- -- Set period and zeroes after the period
-
- Set ('.');
- Set_Zeroes (Digits_After_Point);
-
- -- Input has full amount of digits before decimal point
-
- else
- Set_Blanks_And_Sign (Fore - Digits_Before_Point);
- pragma Assert (FD + Digits_Before_Point - 1 >= 0);
- -- In this branch, we have Digits_Before_Point > 0. It is the
- -- else of test (Digits_Before_Point <= 0)
- Set_Digits (FD, FD + Digits_Before_Point - 1);
- Set ('.');
- Set_Digits (FD + Digits_Before_Point, LD);
- Set_Zeroes (Digits_After_Point - (ND - Digits_Before_Point));
- end if;
- end if;
- end if;
- end Set_Decimal_Digits;
-
- -----------------------
- -- Set_Image_Decimal --
- -----------------------
-
- procedure Set_Image_Decimal
- (V : Integer;
- S : in out String;
- P : in out Natural;
- Scale : Integer;
- Fore : Natural;
- Aft : Natural;
- Exp : Natural)
- is
- Digs : String := Integer'Image (V);
- -- Sign and digits of decimal value
-
- begin
- Set_Decimal_Digits (Digs, Digs'Length, S, P, Scale, Fore, Aft, Exp);
- end Set_Image_Decimal;
-
-end System.Img_Dec;
diff --git a/gcc/ada/libgnat/s-imgdec.ads b/gcc/ada/libgnat/s-imgdec.ads
deleted file mode 100644
index d45a05f..0000000
--- a/gcc/ada/libgnat/s-imgdec.ads
+++ /dev/null
@@ -1,83 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ D E C --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- Image for decimal fixed types where the size of the corresponding integer
--- type does not exceed Integer'Size (also used for Text_IO.Decimal_IO output)
-
-package System.Img_Dec is
- pragma Pure;
-
- procedure Image_Decimal
- (V : Integer;
- S : in out String;
- P : out Natural;
- Scale : Integer);
- -- Computes fixed_type'Image (V), where V is the integer value (in units of
- -- delta) of a decimal type whose Scale is as given and stores the result
- -- S (1 .. P), updating P to the value of L. The image is given by the
- -- rules in RM 3.5(34) for fixed-point type image functions. The caller
- -- guarantees that S is long enough to hold the result. S need not have a
- -- lower bound of 1.
-
- procedure Set_Image_Decimal
- (V : Integer;
- S : in out String;
- P : in out Natural;
- Scale : Integer;
- Fore : Natural;
- Aft : Natural;
- Exp : Natural);
- -- Sets the image of V, where V is the integer value (in units of delta)
- -- of a decimal type with the given Scale, starting at S (P + 1), updating
- -- P to point to the last character stored, the caller promises that the
- -- buffer is large enough and no check is made for this. Constraint_Error
- -- will not necessarily be raised if this requirement is violated, since
- -- it is perfectly valid to compile this unit with checks off. The Fore,
- -- Aft and Exp values can be set to any valid values for the case of use
- -- by Text_IO.Decimal_IO. Note that there is no leading space stored.
-
- procedure Set_Decimal_Digits
- (Digs : in out String;
- NDigs : Natural;
- S : out String;
- P : in out Natural;
- Scale : Integer;
- Fore : Natural;
- Aft : Natural;
- Exp : Natural);
- -- This procedure has the same semantics as Set_Image_Decimal, except that
- -- the value in Digs (1 .. NDigs) is given as a string of decimal digits
- -- preceded by either a minus sign or a space (i.e. the integer image of
- -- the value in units of delta). The call may destroy the value in Digs,
- -- which is why Digs is in-out (this happens if rounding is required).
- -- Set_Decimal_Digits is shared by all the decimal image routines.
-
-end System.Img_Dec;
diff --git a/gcc/ada/libgnat/s-imglld.adb b/gcc/ada/libgnat/s-imglld.adb
deleted file mode 100644
index c70f409..0000000
--- a/gcc/ada/libgnat/s-imglld.adb
+++ /dev/null
@@ -1,82 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ L L D --
--- --
--- B o d y --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-with System.Img_Dec; use System.Img_Dec;
-
-package body System.Img_LLD is
-
- -----------------------------
- -- Image_Long_Long_Decimal --
- ----------------------------
-
- procedure Image_Long_Long_Decimal
- (V : Long_Long_Integer;
- S : in out String;
- P : out Natural;
- Scale : Integer)
- is
- pragma Assert (S'First = 1);
-
- begin
- -- Add space at start for non-negative numbers
-
- if V >= 0 then
- S (1) := ' ';
- P := 1;
- else
- P := 0;
- end if;
-
- Set_Image_Long_Long_Decimal
- (V, S, P, Scale, 1, Integer'Max (1, Scale), 0);
- end Image_Long_Long_Decimal;
-
- ---------------------------------
- -- Set_Image_Long_Long_Decimal --
- ---------------------------------
-
- procedure Set_Image_Long_Long_Decimal
- (V : Long_Long_Integer;
- S : in out String;
- P : in out Natural;
- Scale : Integer;
- Fore : Natural;
- Aft : Natural;
- Exp : Natural)
- is
- Digs : String := Long_Long_Integer'Image (V);
- -- Sign and digits of decimal value
-
- begin
- Set_Decimal_Digits (Digs, Digs'Length, S, P, Scale, Fore, Aft, Exp);
- end Set_Image_Long_Long_Decimal;
-
-end System.Img_LLD;
diff --git a/gcc/ada/libgnat/s-imglld.ads b/gcc/ada/libgnat/s-imglld.ads
deleted file mode 100644
index fdb25b4..0000000
--- a/gcc/ada/libgnat/s-imglld.ads
+++ /dev/null
@@ -1,67 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ L L D --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- Image for decimal fixed types where the size of the corresponding integer
--- type does exceeds Integer'Size (also used for Text_IO.Decimal_IO output)
-
-package System.Img_LLD is
- pragma Pure;
-
- procedure Image_Long_Long_Decimal
- (V : Long_Long_Integer;
- S : in out String;
- P : out Natural;
- Scale : Integer);
- -- Computes fixed_type'Image (V), where V is the integer value (in units of
- -- delta) of a decimal type whose Scale is as given and store the result in
- -- S (P + 1 .. L), updating P to the value of L. The image is given by the
- -- rules in RM 3.5(34) for fixed-point type image functions. The caller
- -- guarantees that S is long enough to hold the result. S need not have a
- -- lower bound of 1.
-
- procedure Set_Image_Long_Long_Decimal
- (V : Long_Long_Integer;
- S : in out String;
- P : in out Natural;
- Scale : Integer;
- Fore : Natural;
- Aft : Natural;
- Exp : Natural);
- -- Sets the image of V, where V is the integer value (in units of delta)
- -- of a decimal type with the given Scale, starting at S (P + 1), updating
- -- P to point to the last character stored, the caller promises that the
- -- buffer is large enough and no check is made for this. Constraint_Error
- -- will not necessarily be raised if this requirement is violated, since
- -- it is perfectly valid to compile this unit with checks off. The Fore,
- -- Aft and Exp values can be set to any valid values for the case of use
- -- by Text_IO.Decimal_IO. Note that there is no leading space stored.
-
-end System.Img_LLD;
diff --git a/gcc/ada/libgnat/s-imgrea.adb b/gcc/ada/libgnat/s-imgrea.adb
index 45d0ae5..2ec6a1a 100644
--- a/gcc/ada/libgnat/s-imgrea.adb
+++ b/gcc/ada/libgnat/s-imgrea.adb
@@ -29,9 +29,9 @@
-- --
------------------------------------------------------------------------------
-with System.Img_LLU; use System.Img_LLU;
-with System.Img_Uns; use System.Img_Uns;
-with System.Powten_Table; use System.Powten_Table;
+with System.Img_LLU; use System.Img_LLU;
+with System.Img_Uns; use System.Img_Uns;
+with System.Powten_LLF; use System.Powten_LLF;
with System.Float_Control;
package body System.Img_Real is
@@ -47,10 +47,10 @@ package body System.Img_Real is
-- in very high precision floating-point output.
-- Note that in the following, the "-2" accounts for the sign and one
- -- extra digits, since we need the maximum number of 9's that can be
- -- supported, e.g. for the normal 64 bit case, Long_Long_Integer'Width
- -- is 21, since the maximum value (approx 1.6 * 10**19) has 20 digits,
- -- but the maximum number of 9's that can be supported is 19.
+ -- extra digit, since we need the maximum number of 9's that can be
+ -- represented, e.g. for the 64-bit case, Long_Long_Unsigned'Width is
+ -- 21, since the maximum value (approx 1.8E+19) has 20 digits, but the
+ -- maximum number of 9's that can be represented is only 19.
Maxdigs : constant :=
Natural'Min
@@ -58,7 +58,6 @@ package body System.Img_Real is
Unsdigs : constant := Unsigned'Width - 2;
-- Number of digits that can be converted using type Unsigned
- -- See above for the explanation of the -2.
Maxscaling : constant := 5000;
-- Max decimal scaling required during conversion of floating-point
@@ -88,11 +87,8 @@ package body System.Img_Real is
-- Decide whether a blank should be prepended before the call to
-- Set_Image_Real. We generate a blank for positive values, and
-- also for positive zeroes. For negative zeroes, we generate a
- -- space only if Signed_Zeroes is True (the RM only permits the
- -- output of -0.0 on targets where this is the case). We can of
- -- course still see a -0.0 on a target where Signed_Zeroes is
- -- False (since this attribute refers to the proper handling of
- -- negative zeroes, not to their existence). We do not generate
+ -- blank only if Signed_Zeros is False (the RM only permits the
+ -- output of -0.0 when Signed_Zeros is True). We do not generate
-- a blank for positive infinity, since we output an explicit +.
if (not Is_Negative (V) and then V <= Long_Long_Float'Last)
@@ -150,7 +146,7 @@ package body System.Img_Real is
Exp : Natural)
is
NFrac : constant Natural := Natural'Max (Aft, 1);
- Sign : Character;
+ Minus : Boolean;
X : Long_Long_Float;
Scale : Integer;
Expon : Integer;
@@ -419,7 +415,7 @@ package body System.Img_Real is
procedure Set_Blanks_And_Sign (N : Integer) is
begin
- if Sign = '-' then
+ if Minus then
for J in 1 .. N - 1 loop
Set (' ');
end loop;
@@ -483,10 +479,10 @@ package body System.Img_Real is
-- Start of processing for Set_Image_Real
begin
- -- We call the floating-point processor reset routine so that we can
- -- be sure the floating-point processor is properly set for conversion
- -- calls. This is notably need on Windows, where calls to the operating
- -- system randomly reset the processor into 64-bit mode.
+ -- We call the floating-point processor reset routine so we can be sure
+ -- that the processor is properly set for conversions. This is notably
+ -- needed on Windows, where calls to the operating system randomly reset
+ -- the processor into 64-bit mode.
System.Float_Control.Reset;
@@ -539,21 +535,21 @@ package body System.Img_Real is
if V > 0.0 then
X := V;
- Sign := '+';
+ Minus := False;
-- Negative values
elsif V < 0.0 then
X := -V;
- Sign := '-';
+ Minus := True;
-- Zero values
elsif V = 0.0 then
if Long_Long_Float'Signed_Zeros and then Is_Negative (V) then
- Sign := '-';
+ Minus := True;
else
- Sign := '+';
+ Minus := False;
end if;
Set_Blanks_And_Sign (Fore - 1);
@@ -578,7 +574,7 @@ package body System.Img_Real is
raise Constraint_Error;
end if;
- -- X and Sign are set here, and X is known to be a valid,
+ -- X and Minus are set here, and X is known to be a valid,
-- non-zero floating-point number.
-- Case of non-zero value with Exp = 0
diff --git a/gcc/ada/libgnat/s-imgrea.ads b/gcc/ada/libgnat/s-imgrea.ads
index 9711516..d8eb721 100644
--- a/gcc/ada/libgnat/s-imgrea.ads
+++ b/gcc/ada/libgnat/s-imgrea.ads
@@ -44,15 +44,18 @@ package System.Img_Real is
-- image for fixed-point types (RM 3.5(34)), where Aft is the value of the
-- Aft attribute for the fixed-point type. This function is used only for
-- ordinary fixed point (see package System.Img_Dec for handling of decimal
- -- fixed-point). The caller guarantees that S is long enough to hold the
+ -- fixed point). The caller guarantees that S is long enough to hold the
-- result and has a lower bound of 1.
+ --
+ -- Remark: This procedure should NOT be called with V = -0.0 or V = +/-Inf,
+ -- The result is irrelevant.
procedure Image_Floating_Point
(V : Long_Long_Float;
S : in out String;
P : out Natural;
Digs : Natural);
- -- Computes fixed_type'Image (V) and returns the result in S (1 .. P)
+ -- Computes float_type'Image (V) and returns the result in S (1 .. P)
-- updating P on return. The result is computed according to the rules for
-- image for floating-point types (RM 3.5(33)), where Digs is the value of
-- the Digits attribute for the floating-point type. The caller guarantees
diff --git a/gcc/ada/libgnat/s-imguti.adb b/gcc/ada/libgnat/s-imguti.adb
new file mode 100644
index 0000000..571fb67
--- /dev/null
+++ b/gcc/ada/libgnat/s-imguti.adb
@@ -0,0 +1,403 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ U T I L --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Img_Uns; use System.Img_Uns;
+
+package body System.Img_Util is
+
+ ------------------------
+ -- Set_Decimal_Digits --
+ ------------------------
+
+ procedure Set_Decimal_Digits
+ (Digs : in out String;
+ NDigs : Natural;
+ S : out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural)
+ is
+ pragma Assert (NDigs >= 1);
+ pragma Assert (Digs'First = 1);
+ pragma Assert (Digs'First < Digs'Last);
+
+ Minus : constant Boolean := (Digs (Digs'First) = '-');
+ -- Set True if input is negative
+
+ Zero : Boolean := (Digs (Digs'First + 1) = '0');
+ -- Set True if input is exactly zero (only case when a leading zero
+ -- is permitted in the input string given to this procedure). This
+ -- flag can get set later if rounding causes the value to become zero.
+
+ FD : Natural := 2;
+ -- First digit position of digits remaining to be processed
+
+ LD : Natural := NDigs;
+ -- Last digit position of digits remaining to be processed
+
+ ND : Natural := NDigs - 1;
+ -- Number of digits remaining to be processed (LD - FD + 1)
+
+ Digits_Before_Point : Integer := ND - Scale;
+ -- Number of digits before decimal point in the input value. This
+ -- value can be negative if the input value is less than 0.1, so
+ -- it is an indication of the current exponent. Digits_Before_Point
+ -- is adjusted if the rounding step generates an extra digit.
+
+ Digits_After_Point : constant Natural := Integer'Max (1, Aft);
+ -- Digit positions after decimal point in result string
+
+ Expon : Integer;
+ -- Integer value of exponent
+
+ procedure Round (N : Integer);
+ -- Round the number in Digs. N is the position of the last digit to be
+ -- retained in the rounded position (rounding is based on Digs (N + 1)
+ -- FD, LD, ND are reset as necessary if required. Note that if the
+ -- result value rounds up (e.g. 9.99 => 10.0), an extra digit can be
+ -- placed in the sign position as a result of the rounding, this is
+ -- the case in which FD is adjusted. The call to Round has no effect
+ -- if N is outside the range FD .. LD.
+
+ procedure Set (C : Character);
+ pragma Inline (Set);
+ -- Sets character C in output buffer
+
+ procedure Set_Blanks_And_Sign (N : Integer);
+ -- Sets leading blanks and minus sign if needed. N is the number of
+ -- positions to be filled (a minus sign is output even if N is zero
+ -- or negative, but for a positive value, if N is non-positive, then
+ -- the call has no effect).
+
+ procedure Set_Digits (S, E : Natural);
+ pragma Inline (Set_Digits);
+ -- Set digits S through E from Digs, no effect if S > E
+
+ procedure Set_Zeroes (N : Integer);
+ pragma Inline (Set_Zeroes);
+ -- Set N zeroes, no effect if N is negative
+
+ -----------
+ -- Round --
+ -----------
+
+ procedure Round (N : Integer) is
+ D : Character;
+
+ pragma Assert (NDigs >= 1);
+ pragma Assert (Digs'First = 1);
+ pragma Assert (Digs'First < Digs'Last);
+
+ begin
+ -- Nothing to do if rounding past the last digit we have
+
+ if N >= LD then
+ return;
+
+ -- Cases of rounding before the initial digit
+
+ elsif N < FD then
+
+ -- The result is zero, unless we are rounding just before
+ -- the first digit, and the first digit is five or more.
+
+ if N = 1 and then Digs (Digs'First + 1) >= '5' then
+ Digs (Digs'First) := '1';
+ else
+ Digs (Digs'First) := '0';
+ Zero := True;
+ end if;
+
+ Digits_Before_Point := Digits_Before_Point + 1;
+ FD := 1;
+ LD := 1;
+ ND := 1;
+
+ -- Normal case of rounding an existing digit
+
+ else
+ LD := N;
+ pragma Assert (LD >= 1);
+ -- In this case, we have N < LD and N >= FD. FD is a Natural,
+ -- So we can conclude, LD >= 1
+ ND := LD - 1;
+ pragma Assert (N + 1 <= Digs'Last);
+
+ if Digs (N + 1) >= '5' then
+ for J in reverse Digs'First + 1 .. Digs'First + N - 1 loop
+ pragma Assert (Digs (J) in '0' .. '9' | ' ' | '-');
+ -- Because it is a decimal image, we can assume that
+ -- it can only contain these characters.
+ D := Character'Succ (Digs (J));
+
+ if D <= '9' then
+ Digs (J) := D;
+ return;
+ else
+ Digs (J) := '0';
+ end if;
+ end loop;
+
+ -- Here the rounding overflows into the sign position. That's
+ -- OK, because we already captured the value of the sign and
+ -- we are in any case destroying the value in the Digs buffer
+
+ Digs (Digs'First) := '1';
+ FD := 1;
+ ND := ND + 1;
+ Digits_Before_Point := Digits_Before_Point + 1;
+ end if;
+ end if;
+ end Round;
+
+ ---------
+ -- Set --
+ ---------
+
+ procedure Set (C : Character) is
+ begin
+ pragma Assert (P >= (S'First - 1) and P < S'Last and
+ P < Natural'Last);
+ -- No check is done as documented in the header : updating P to
+ -- point to the last character stored, the caller promises that the
+ -- buffer is large enough and no check is made for this.
+ -- Constraint_Error will not necessarily be raised if this
+ -- requirement is violated, since it is perfectly valid to compile
+ -- this unit with checks off.
+ P := P + 1;
+ S (P) := C;
+ end Set;
+
+ -------------------------
+ -- Set_Blanks_And_Sign --
+ -------------------------
+
+ procedure Set_Blanks_And_Sign (N : Integer) is
+ begin
+ if Minus then
+ for J in 1 .. N - 1 loop
+ Set (' ');
+ end loop;
+
+ Set ('-');
+
+ else
+ for J in 1 .. N loop
+ Set (' ');
+ end loop;
+ end if;
+ end Set_Blanks_And_Sign;
+
+ ----------------
+ -- Set_Digits --
+ ----------------
+
+ procedure Set_Digits (S, E : Natural) is
+ begin
+ pragma Assert (S >= Digs'First and E <= Digs'Last);
+ -- S and E should be in the Digs array range
+ -- TBC: Analysis should be completed
+ for J in S .. E loop
+ Set (Digs (J));
+ end loop;
+ end Set_Digits;
+
+ ----------------
+ -- Set_Zeroes --
+ ----------------
+
+ procedure Set_Zeroes (N : Integer) is
+ begin
+ for J in 1 .. N loop
+ Set ('0');
+ end loop;
+ end Set_Zeroes;
+
+ -- Start of processing for Set_Decimal_Digits
+
+ begin
+ -- Case of exponent given
+
+ if Exp > 0 then
+ Set_Blanks_And_Sign (Fore - 1);
+ Round (Digits_After_Point + 2);
+
+ Set (Digs (FD));
+ FD := FD + 1;
+ pragma Assert (ND >= 1);
+ ND := ND - 1;
+ Set ('.');
+
+ if ND >= Digits_After_Point then
+ Set_Digits (FD, FD + Digits_After_Point - 1);
+ else
+ Set_Digits (FD, LD);
+ Set_Zeroes (Digits_After_Point - ND);
+ end if;
+
+ -- Calculate exponent. The number of digits before the decimal point
+ -- in the input is Digits_Before_Point, and the number of digits
+ -- before the decimal point in the output is 1, so we can get the
+ -- exponent as the difference between these two values. The one
+ -- exception is for the value zero, which by convention has an
+ -- exponent of +0.
+
+ Expon := (if Zero then 0 else Digits_Before_Point - 1);
+
+ Set ('E');
+ ND := 0;
+
+ if Expon >= 0 then
+ Set ('+');
+ Set_Image_Unsigned (Unsigned (Expon), Digs, ND);
+ else
+ Set ('-');
+ Set_Image_Unsigned (Unsigned (-Expon), Digs, ND);
+ end if;
+
+ Set_Zeroes (Exp - ND - 1);
+ Set_Digits (1, ND);
+ return;
+
+ -- Case of no exponent given. To make these cases clear, we use
+ -- examples. For all the examples, we assume Fore = 2, Aft = 3.
+ -- A P in the example input string is an implied zero position,
+ -- not included in the input string.
+
+ else
+ -- Round at correct position
+ -- Input: 4PP => unchanged
+ -- Input: 400.03 => unchanged
+ -- Input 3.4567 => 3.457
+ -- Input: 9.9999 => 10.000
+ -- Input: 0.PPP5 => 0.001
+ -- Input: 0.PPP4 => 0
+ -- Input: 0.00003 => 0
+
+ Round (LD - (Scale - Digits_After_Point));
+
+ -- No digits before point in input
+ -- Input: .123 Output: 0.123
+ -- Input: .PP3 Output: 0.003
+
+ if Digits_Before_Point <= 0 then
+ Set_Blanks_And_Sign (Fore - 1);
+ Set ('0');
+ Set ('.');
+
+ declare
+ DA : Natural := Digits_After_Point;
+ -- Digits remaining to output after point
+
+ LZ : constant Integer := Integer'Min (DA, -Digits_Before_Point);
+ -- Number of leading zeroes after point. Note: there used to be
+ -- a Max of this result with zero, but that's redundant, since
+ -- we know DA is positive, and because of the test above, we
+ -- know that -Digits_Before_Point >= 0.
+
+ begin
+ Set_Zeroes (LZ);
+ DA := DA - LZ;
+
+ if DA < ND then
+
+ -- Note: it is definitely possible for the above condition
+ -- to be True, for example:
+
+ -- V => 1234, Scale => 5, Fore => 0, After => 1, Exp => 0
+
+ -- but in this case DA = 0, ND = 1, FD = 1, FD + DA-1 = 0
+ -- so the arguments in the call are (1, 0) meaning that no
+ -- digits are output.
+
+ -- No obvious example exists where the following call to
+ -- Set_Digits actually outputs some digits, but we lack a
+ -- proof that no such example exists.
+
+ -- So it is safer to retain this call, even though as a
+ -- result it is hard (or perhaps impossible) to create a
+ -- coverage test for the inlined code of the call.
+
+ Set_Digits (FD, FD + DA - 1);
+
+ else
+ Set_Digits (FD, LD);
+ Set_Zeroes (DA - ND);
+ end if;
+ end;
+
+ -- At least one digit before point in input
+
+ else
+ -- Less digits in input than are needed before point
+ -- Input: 1PP Output: 100.000
+
+ if ND < Digits_Before_Point then
+
+ -- Special case, if the input is the single digit 0, then we
+ -- do not want 000.000, but instead 0.000.
+
+ if ND = 1 and then Digs (FD) = '0' then
+ Set_Blanks_And_Sign (Fore - 1);
+ Set ('0');
+
+ -- Normal case where we need to output scaling zeroes
+
+ else
+ Set_Blanks_And_Sign (Fore - Digits_Before_Point);
+ Set_Digits (FD, LD);
+ Set_Zeroes (Digits_Before_Point - ND);
+ end if;
+
+ -- Set period and zeroes after the period
+
+ Set ('.');
+ Set_Zeroes (Digits_After_Point);
+
+ -- Input has full amount of digits before decimal point
+
+ else
+ Set_Blanks_And_Sign (Fore - Digits_Before_Point);
+ pragma Assert (FD + Digits_Before_Point - 1 >= 0);
+ -- In this branch, we have Digits_Before_Point > 0. It is the
+ -- else of test (Digits_Before_Point <= 0)
+ Set_Digits (FD, FD + Digits_Before_Point - 1);
+ Set ('.');
+ Set_Digits (FD + Digits_Before_Point, LD);
+ Set_Zeroes (Digits_After_Point - (ND - Digits_Before_Point));
+ end if;
+ end if;
+ end if;
+ end Set_Decimal_Digits;
+
+end System.Img_Util;
diff --git a/gcc/ada/libgnat/s-imguti.ads b/gcc/ada/libgnat/s-imguti.ads
new file mode 100644
index 0000000..6e21c65
--- /dev/null
+++ b/gcc/ada/libgnat/s-imguti.ads
@@ -0,0 +1,61 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . I M G _ U T I L --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides some common utilities used by the s-imgxxx files
+
+package System.Img_Util is
+ pragma Pure;
+
+ procedure Set_Decimal_Digits
+ (Digs : in out String;
+ NDigs : Natural;
+ S : out String;
+ P : in out Natural;
+ Scale : Integer;
+ Fore : Natural;
+ Aft : Natural;
+ Exp : Natural);
+ -- Sets the image of Digs (1 .. NDigs), which is a string of decimal digits
+ -- preceded by either a minus sign or a space, i.e. the integer image of
+ -- the value in units of delta if this is for a decimal fixed point type
+ -- with the given Scale, or the integer image of the value converted to an
+ -- implicit decimal fixed point type with the given Scale if this is for an
+ -- ordinary fixed point type, starting at S (P + 1), updating P to point to
+ -- the last character stored. The caller promises that the buffer is large
+ -- enough and therefore no check is made for it. Constraint_Error will not
+ -- necessarily be raised if the requirement is violated since it is valid
+ -- to compile this unit with checks off. The Fore, Aft and Exp values can
+ -- be set to any valid values for the case of use by Text_IO.Decimal_IO or
+ -- Text_IO.Fixed_IO. Note that there is no leading space stored. The call
+ -- may destroy the value in Digs, which is why Digs is in-out (this happens
+ -- if rounding is required).
+
+end System.Img_Util;
diff --git a/gcc/ada/libgnat/s-objrea.adb b/gcc/ada/libgnat/s-objrea.adb
index d64e285..0cfa522 100644
--- a/gcc/ada/libgnat/s-objrea.adb
+++ b/gcc/ada/libgnat/s-objrea.adb
@@ -645,6 +645,9 @@ package body System.Object_Reader is
when EM_X86_64 =>
Res.Arch := x86_64;
+ when EM_ARM =>
+ Res.Arch := ARM;
+
when others =>
raise Format_Error with "unrecognized architecture";
end case;
@@ -2030,6 +2033,7 @@ package body System.Object_Reader is
| MIPS
| PPC
| SPARC
+ | ARM
=>
Address_32 := Read (S);
return uint64 (Address_32);
diff --git a/gcc/ada/libgnat/s-objrea.ads b/gcc/ada/libgnat/s-objrea.ads
index bd4fbd5..b3cfe13 100644
--- a/gcc/ada/libgnat/s-objrea.ads
+++ b/gcc/ada/libgnat/s-objrea.ads
@@ -117,9 +117,12 @@ package System.Object_Reader is
PPC,
-- 32-bit PowerPC
- PPC64);
+ PPC64,
-- 64-bit PowerPC
+ ARM);
+ -- 32-bit ARM
+
------------------
-- Target types --
------------------
diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb
index 288325c..93522bc 100644
--- a/gcc/ada/libgnat/s-os_lib.adb
+++ b/gcc/ada/libgnat/s-os_lib.adb
@@ -1365,6 +1365,21 @@ package body System.OS_Lib is
S : Integer;
begin
+ -- Special case Invalid_Time which is handled differently between
+ -- Windows and Linux: Linux will set to 1 second before 1970-01-01
+ -- while Windows will set the time to 1970-01-01 with Second set to -1,
+ -- which is not a valid value.
+
+ if Date = Invalid_Time then
+ Year := 1969;
+ Month := 12;
+ Day := 31;
+ Hour := 23;
+ Minute := 59;
+ Second := 59;
+ return;
+ end if;
+
-- Use the global lock because To_GM_Time is not thread safe
Locked_Processing : begin
@@ -1387,7 +1402,15 @@ package body System.OS_Lib is
Year := Y + 1900;
Month := Mo + 1;
- Day := D;
+
+ -- May happen if To_GM_Time fails
+
+ if D = 0 then
+ Day := 1;
+ else
+ Day := D;
+ end if;
+
Hour := H;
Minute := Mn;
Second := S;
diff --git a/gcc/ada/libgnat/s-powflt.ads b/gcc/ada/libgnat/s-powflt.ads
new file mode 100644
index 0000000..9d58967
--- /dev/null
+++ b/gcc/ada/libgnat/s-powflt.ads
@@ -0,0 +1,85 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . P O W T E N _ F L T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides a powers of ten table used for real conversions
+
+package System.Powten_Flt is
+ pragma Pure;
+
+ Maxpow : constant := 38;
+ -- Largest power of ten representable with Float
+
+ Maxpow_Exact : constant := 10;
+ -- Largest power of ten exactly representable with Float. It is equal to
+ -- floor (M * log 2 / log 5), when M is the size of the mantissa (24).
+
+ Powten : constant array (0 .. Maxpow) of Float :=
+ (00 => 1.0E+00,
+ 01 => 1.0E+01,
+ 02 => 1.0E+02,
+ 03 => 1.0E+03,
+ 04 => 1.0E+04,
+ 05 => 1.0E+05,
+ 06 => 1.0E+06,
+ 07 => 1.0E+07,
+ 08 => 1.0E+08,
+ 09 => 1.0E+09,
+ 10 => 1.0E+10,
+ 11 => 1.0E+11,
+ 12 => 1.0E+12,
+ 13 => 1.0E+13,
+ 14 => 1.0E+14,
+ 15 => 1.0E+15,
+ 16 => 1.0E+16,
+ 17 => 1.0E+17,
+ 18 => 1.0E+18,
+ 19 => 1.0E+19,
+ 20 => 1.0E+20,
+ 21 => 1.0E+21,
+ 22 => 1.0E+22,
+ 23 => 1.0E+23,
+ 24 => 1.0E+24,
+ 25 => 1.0E+25,
+ 26 => 1.0E+26,
+ 27 => 1.0E+27,
+ 28 => 1.0E+28,
+ 29 => 1.0E+29,
+ 30 => 1.0E+30,
+ 31 => 1.0E+31,
+ 32 => 1.0E+32,
+ 33 => 1.0E+33,
+ 34 => 1.0E+34,
+ 35 => 1.0E+35,
+ 36 => 1.0E+36,
+ 37 => 1.0E+37,
+ 38 => 1.0E+38);
+
+end System.Powten_Flt;
diff --git a/gcc/ada/libgnat/s-powlfl.ads b/gcc/ada/libgnat/s-powlfl.ads
new file mode 100644
index 0000000..d191eff
--- /dev/null
+++ b/gcc/ada/libgnat/s-powlfl.ads
@@ -0,0 +1,355 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . P O W T E N _ L F L T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides a powers of ten table used for real conversions
+
+package System.Powten_LFlt is
+ pragma Pure;
+
+ Maxpow : constant := 308;
+ -- Largest power of ten representable with Long_Float
+
+ Maxpow_Exact : constant := 22;
+ -- Largest power of ten exactly representable with Long_Float. It is equal
+ -- to floor (M * log 2 / log 5), when M is the size of the mantissa (53).
+
+ Powten : constant array (0 .. Maxpow) of Long_Float :=
+ (00 => 1.0E+00,
+ 01 => 1.0E+01,
+ 02 => 1.0E+02,
+ 03 => 1.0E+03,
+ 04 => 1.0E+04,
+ 05 => 1.0E+05,
+ 06 => 1.0E+06,
+ 07 => 1.0E+07,
+ 08 => 1.0E+08,
+ 09 => 1.0E+09,
+ 10 => 1.0E+10,
+ 11 => 1.0E+11,
+ 12 => 1.0E+12,
+ 13 => 1.0E+13,
+ 14 => 1.0E+14,
+ 15 => 1.0E+15,
+ 16 => 1.0E+16,
+ 17 => 1.0E+17,
+ 18 => 1.0E+18,
+ 19 => 1.0E+19,
+ 20 => 1.0E+20,
+ 21 => 1.0E+21,
+ 22 => 1.0E+22,
+ 23 => 1.0E+23,
+ 24 => 1.0E+24,
+ 25 => 1.0E+25,
+ 26 => 1.0E+26,
+ 27 => 1.0E+27,
+ 28 => 1.0E+28,
+ 29 => 1.0E+29,
+ 30 => 1.0E+30,
+ 31 => 1.0E+31,
+ 32 => 1.0E+32,
+ 33 => 1.0E+33,
+ 34 => 1.0E+34,
+ 35 => 1.0E+35,
+ 36 => 1.0E+36,
+ 37 => 1.0E+37,
+ 38 => 1.0E+38,
+ 39 => 1.0E+39,
+ 40 => 1.0E+40,
+ 41 => 1.0E+41,
+ 42 => 1.0E+42,
+ 43 => 1.0E+43,
+ 44 => 1.0E+44,
+ 45 => 1.0E+45,
+ 46 => 1.0E+46,
+ 47 => 1.0E+47,
+ 48 => 1.0E+48,
+ 49 => 1.0E+49,
+ 50 => 1.0E+50,
+ 51 => 1.0E+51,
+ 52 => 1.0E+52,
+ 53 => 1.0E+53,
+ 54 => 1.0E+54,
+ 55 => 1.0E+55,
+ 56 => 1.0E+56,
+ 57 => 1.0E+57,
+ 58 => 1.0E+58,
+ 59 => 1.0E+59,
+ 60 => 1.0E+60,
+ 61 => 1.0E+61,
+ 62 => 1.0E+62,
+ 63 => 1.0E+63,
+ 64 => 1.0E+64,
+ 65 => 1.0E+65,
+ 66 => 1.0E+66,
+ 67 => 1.0E+67,
+ 68 => 1.0E+68,
+ 69 => 1.0E+69,
+ 70 => 1.0E+70,
+ 71 => 1.0E+71,
+ 72 => 1.0E+72,
+ 73 => 1.0E+73,
+ 74 => 1.0E+74,
+ 75 => 1.0E+75,
+ 76 => 1.0E+76,
+ 77 => 1.0E+77,
+ 78 => 1.0E+78,
+ 79 => 1.0E+79,
+ 80 => 1.0E+80,
+ 81 => 1.0E+81,
+ 82 => 1.0E+82,
+ 83 => 1.0E+83,
+ 84 => 1.0E+84,
+ 85 => 1.0E+85,
+ 86 => 1.0E+86,
+ 87 => 1.0E+87,
+ 88 => 1.0E+88,
+ 89 => 1.0E+89,
+ 90 => 1.0E+90,
+ 91 => 1.0E+91,
+ 92 => 1.0E+92,
+ 93 => 1.0E+93,
+ 94 => 1.0E+94,
+ 95 => 1.0E+95,
+ 96 => 1.0E+96,
+ 97 => 1.0E+97,
+ 98 => 1.0E+98,
+ 99 => 1.0E+99,
+ 100 => 1.0E+100,
+ 101 => 1.0E+101,
+ 102 => 1.0E+102,
+ 103 => 1.0E+103,
+ 104 => 1.0E+104,
+ 105 => 1.0E+105,
+ 106 => 1.0E+106,
+ 107 => 1.0E+107,
+ 108 => 1.0E+108,
+ 109 => 1.0E+109,
+ 110 => 1.0E+110,
+ 111 => 1.0E+111,
+ 112 => 1.0E+112,
+ 113 => 1.0E+113,
+ 114 => 1.0E+114,
+ 115 => 1.0E+115,
+ 116 => 1.0E+116,
+ 117 => 1.0E+117,
+ 118 => 1.0E+118,
+ 119 => 1.0E+119,
+ 120 => 1.0E+120,
+ 121 => 1.0E+121,
+ 122 => 1.0E+122,
+ 123 => 1.0E+123,
+ 124 => 1.0E+124,
+ 125 => 1.0E+125,
+ 126 => 1.0E+126,
+ 127 => 1.0E+127,
+ 128 => 1.0E+128,
+ 129 => 1.0E+129,
+ 130 => 1.0E+130,
+ 131 => 1.0E+131,
+ 132 => 1.0E+132,
+ 133 => 1.0E+133,
+ 134 => 1.0E+134,
+ 135 => 1.0E+135,
+ 136 => 1.0E+136,
+ 137 => 1.0E+137,
+ 138 => 1.0E+138,
+ 139 => 1.0E+139,
+ 140 => 1.0E+140,
+ 141 => 1.0E+141,
+ 142 => 1.0E+142,
+ 143 => 1.0E+143,
+ 144 => 1.0E+144,
+ 145 => 1.0E+145,
+ 146 => 1.0E+146,
+ 147 => 1.0E+147,
+ 148 => 1.0E+148,
+ 149 => 1.0E+149,
+ 150 => 1.0E+150,
+ 151 => 1.0E+151,
+ 152 => 1.0E+152,
+ 153 => 1.0E+153,
+ 154 => 1.0E+154,
+ 155 => 1.0E+155,
+ 156 => 1.0E+156,
+ 157 => 1.0E+157,
+ 158 => 1.0E+158,
+ 159 => 1.0E+159,
+ 160 => 1.0E+160,
+ 161 => 1.0E+161,
+ 162 => 1.0E+162,
+ 163 => 1.0E+163,
+ 164 => 1.0E+164,
+ 165 => 1.0E+165,
+ 166 => 1.0E+166,
+ 167 => 1.0E+167,
+ 168 => 1.0E+168,
+ 169 => 1.0E+169,
+ 170 => 1.0E+170,
+ 171 => 1.0E+171,
+ 172 => 1.0E+172,
+ 173 => 1.0E+173,
+ 174 => 1.0E+174,
+ 175 => 1.0E+175,
+ 176 => 1.0E+176,
+ 177 => 1.0E+177,
+ 178 => 1.0E+178,
+ 179 => 1.0E+179,
+ 180 => 1.0E+180,
+ 181 => 1.0E+181,
+ 182 => 1.0E+182,
+ 183 => 1.0E+183,
+ 184 => 1.0E+184,
+ 185 => 1.0E+185,
+ 186 => 1.0E+186,
+ 187 => 1.0E+187,
+ 188 => 1.0E+188,
+ 189 => 1.0E+189,
+ 190 => 1.0E+190,
+ 191 => 1.0E+191,
+ 192 => 1.0E+192,
+ 193 => 1.0E+193,
+ 194 => 1.0E+194,
+ 195 => 1.0E+195,
+ 196 => 1.0E+196,
+ 197 => 1.0E+197,
+ 198 => 1.0E+198,
+ 199 => 1.0E+199,
+ 200 => 1.0E+200,
+ 201 => 1.0E+201,
+ 202 => 1.0E+202,
+ 203 => 1.0E+203,
+ 204 => 1.0E+204,
+ 205 => 1.0E+205,
+ 206 => 1.0E+206,
+ 207 => 1.0E+207,
+ 208 => 1.0E+208,
+ 209 => 1.0E+209,
+ 210 => 1.0E+210,
+ 211 => 1.0E+211,
+ 212 => 1.0E+212,
+ 213 => 1.0E+213,
+ 214 => 1.0E+214,
+ 215 => 1.0E+215,
+ 216 => 1.0E+216,
+ 217 => 1.0E+217,
+ 218 => 1.0E+218,
+ 219 => 1.0E+219,
+ 220 => 1.0E+220,
+ 221 => 1.0E+221,
+ 222 => 1.0E+222,
+ 223 => 1.0E+223,
+ 224 => 1.0E+224,
+ 225 => 1.0E+225,
+ 226 => 1.0E+226,
+ 227 => 1.0E+227,
+ 228 => 1.0E+228,
+ 229 => 1.0E+229,
+ 230 => 1.0E+230,
+ 231 => 1.0E+231,
+ 232 => 1.0E+232,
+ 233 => 1.0E+233,
+ 234 => 1.0E+234,
+ 235 => 1.0E+235,
+ 236 => 1.0E+236,
+ 237 => 1.0E+237,
+ 238 => 1.0E+238,
+ 239 => 1.0E+239,
+ 240 => 1.0E+240,
+ 241 => 1.0E+241,
+ 242 => 1.0E+242,
+ 243 => 1.0E+243,
+ 244 => 1.0E+244,
+ 245 => 1.0E+245,
+ 246 => 1.0E+246,
+ 247 => 1.0E+247,
+ 248 => 1.0E+248,
+ 249 => 1.0E+249,
+ 250 => 1.0E+250,
+ 251 => 1.0E+251,
+ 252 => 1.0E+252,
+ 253 => 1.0E+253,
+ 254 => 1.0E+254,
+ 255 => 1.0E+255,
+ 256 => 1.0E+256,
+ 257 => 1.0E+257,
+ 258 => 1.0E+258,
+ 259 => 1.0E+259,
+ 260 => 1.0E+260,
+ 261 => 1.0E+261,
+ 262 => 1.0E+262,
+ 263 => 1.0E+263,
+ 264 => 1.0E+264,
+ 265 => 1.0E+265,
+ 266 => 1.0E+266,
+ 267 => 1.0E+267,
+ 268 => 1.0E+268,
+ 269 => 1.0E+269,
+ 270 => 1.0E+270,
+ 271 => 1.0E+271,
+ 272 => 1.0E+272,
+ 273 => 1.0E+273,
+ 274 => 1.0E+274,
+ 275 => 1.0E+275,
+ 276 => 1.0E+276,
+ 277 => 1.0E+277,
+ 278 => 1.0E+278,
+ 279 => 1.0E+279,
+ 280 => 1.0E+280,
+ 281 => 1.0E+281,
+ 282 => 1.0E+282,
+ 283 => 1.0E+283,
+ 284 => 1.0E+284,
+ 285 => 1.0E+285,
+ 286 => 1.0E+286,
+ 287 => 1.0E+287,
+ 288 => 1.0E+288,
+ 289 => 1.0E+289,
+ 290 => 1.0E+290,
+ 291 => 1.0E+291,
+ 292 => 1.0E+292,
+ 293 => 1.0E+293,
+ 294 => 1.0E+294,
+ 295 => 1.0E+295,
+ 296 => 1.0E+296,
+ 297 => 1.0E+297,
+ 298 => 1.0E+298,
+ 299 => 1.0E+299,
+ 300 => 1.0E+300,
+ 301 => 1.0E+301,
+ 302 => 1.0E+302,
+ 303 => 1.0E+303,
+ 304 => 1.0E+304,
+ 305 => 1.0E+305,
+ 306 => 1.0E+306,
+ 307 => 1.0E+307,
+ 308 => 1.0E+308);
+
+end System.Powten_LFlt;
diff --git a/gcc/ada/libgnat/s-powllf.ads b/gcc/ada/libgnat/s-powllf.ads
new file mode 100644
index 0000000..c5c42a1
--- /dev/null
+++ b/gcc/ada/libgnat/s-powllf.ads
@@ -0,0 +1,70 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . P O W T E N _ L L F --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides a powers of ten table used for real conversions
+
+package System.Powten_LLF is
+ pragma Pure;
+
+ Maxpow : constant := 22;
+ -- The number of entries in this table is chosen to include powers of ten
+ -- that are exactly representable with Long_Long_Float. Assuming that on
+ -- all targets we have 53 bits of mantissa for the type, the upper bound
+ -- is given by 53 * log 2 / log 5. If the scaling factor is greater than
+ -- Maxpow, it can be obtained by several multiplications, which is less
+ -- efficient than with a bigger table, but avoids anomalies at end points.
+
+ Powten : constant array (0 .. Maxpow) of Long_Long_Float :=
+ (00 => 1.0E+00,
+ 01 => 1.0E+01,
+ 02 => 1.0E+02,
+ 03 => 1.0E+03,
+ 04 => 1.0E+04,
+ 05 => 1.0E+05,
+ 06 => 1.0E+06,
+ 07 => 1.0E+07,
+ 08 => 1.0E+08,
+ 09 => 1.0E+09,
+ 10 => 1.0E+10,
+ 11 => 1.0E+11,
+ 12 => 1.0E+12,
+ 13 => 1.0E+13,
+ 14 => 1.0E+14,
+ 15 => 1.0E+15,
+ 16 => 1.0E+16,
+ 17 => 1.0E+17,
+ 18 => 1.0E+18,
+ 19 => 1.0E+19,
+ 20 => 1.0E+20,
+ 21 => 1.0E+21,
+ 22 => 1.0E+22);
+
+end System.Powten_LLF;
diff --git a/gcc/ada/libgnat/s-powtab.ads b/gcc/ada/libgnat/s-powtab.ads
deleted file mode 100644
index ef8d74a..0000000
--- a/gcc/ada/libgnat/s-powtab.ads
+++ /dev/null
@@ -1,70 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y S T E M . P O W T E N _ T A B L E --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This package provides a powers of ten table used for real conversions
-
-package System.Powten_Table is
- pragma Pure;
-
- Maxpow : constant := 22;
- -- The number of entries in this table is chosen to include powers of ten
- -- that are exactly representable with long_long_float. Assuming that on
- -- all targets we have 53 bits of mantissa for the type, the upper bound is
- -- given by 53/(log 5). If the scaling factor for a string is greater than
- -- Maxpow, it can be obtained by several multiplications, which is less
- -- efficient than with a bigger table, but avoids anomalies at end points.
-
- Powten : constant array (0 .. Maxpow) of Long_Long_Float :=
- (00 => 1.0E+00,
- 01 => 1.0E+01,
- 02 => 1.0E+02,
- 03 => 1.0E+03,
- 04 => 1.0E+04,
- 05 => 1.0E+05,
- 06 => 1.0E+06,
- 07 => 1.0E+07,
- 08 => 1.0E+08,
- 09 => 1.0E+09,
- 10 => 1.0E+10,
- 11 => 1.0E+11,
- 12 => 1.0E+12,
- 13 => 1.0E+13,
- 14 => 1.0E+14,
- 15 => 1.0E+15,
- 16 => 1.0E+16,
- 17 => 1.0E+17,
- 18 => 1.0E+18,
- 19 => 1.0E+19,
- 20 => 1.0E+20,
- 21 => 1.0E+21,
- 22 => 1.0E+22);
-
-end System.Powten_Table;
diff --git a/gcc/ada/libgnat/s-rannum.adb b/gcc/ada/libgnat/s-rannum.adb
index e65e6a7..ab6428f 100644
--- a/gcc/ada/libgnat/s-rannum.adb
+++ b/gcc/ada/libgnat/s-rannum.adb
@@ -409,6 +409,41 @@ is
elsif Max < Min then
raise Constraint_Error;
+ -- In the 128-bit case, we have to be careful since not all 128-bit
+ -- unsigned values are representable in GNAT's universal integer.
+
+ elsif Result_Subtype'Base'Size > 64 then
+ declare
+ -- Ignore unequal-size warnings since GNAT's handling is correct.
+
+ pragma Warnings ("Z");
+ function Conv_To_Unsigned is
+ new Unchecked_Conversion (Result_Subtype'Base, Unsigned_128);
+ function Conv_To_Result is
+ new Unchecked_Conversion (Unsigned_128, Result_Subtype'Base);
+ pragma Warnings ("z");
+
+ N : constant Unsigned_128 :=
+ Conv_To_Unsigned (Max) - Conv_To_Unsigned (Min) + 1;
+
+ X, Slop : Unsigned_128;
+
+ begin
+ if N = 0 then
+ return Conv_To_Result (Conv_To_Unsigned (Min) + Random (Gen));
+
+ else
+ Slop := Unsigned_128'Last rem N + 1;
+
+ loop
+ X := Random (Gen);
+ exit when Slop = N or else X <= Unsigned_128'Last - Slop;
+ end loop;
+
+ return Conv_To_Result (Conv_To_Unsigned (Min) + X rem N);
+ end if;
+ end;
+
-- In the 64-bit case, we have to be careful since not all 64-bit
-- unsigned values are representable in GNAT's universal integer.
diff --git a/gcc/ada/libgnat/s-rident.ads b/gcc/ada/libgnat/s-rident.ads
index 662721a..c6c3d3d 100644
--- a/gcc/ada/libgnat/s-rident.ads
+++ b/gcc/ada/libgnat/s-rident.ads
@@ -184,6 +184,8 @@ package System.Rident is
No_Implicit_Loops, -- GNAT
No_Elaboration_Code, -- GNAT
No_Obsolescent_Features, -- Ada 2005 AI-368
+ No_Unrecognized_Aspects, -- AI12-0389-1/02
+ No_Unrecognized_Pragmas, -- AI12-0389-1/02
No_Wide_Characters, -- GNAT
Static_Dispatch_Tables, -- GNAT
SPARK_05, -- GNAT
diff --git a/gcc/ada/libgnat/s-secsta.adb b/gcc/ada/libgnat/s-secsta.adb
index 7ec8462..f2d264d 100644
--- a/gcc/ada/libgnat/s-secsta.adb
+++ b/gcc/ada/libgnat/s-secsta.adb
@@ -587,15 +587,18 @@ package body System.Secondary_Stack is
-- Start of processing for SS_Allocate
begin
- -- It should not be possible to request an allocation of negative or
- -- zero size.
-
- pragma Assert (Storage_Size > 0);
-
-- Round the requested size up to the nearest multiple of the maximum
-- alignment to ensure efficient access.
- Mem_Size := Round_Up (Storage_Size);
+ if Storage_Size = 0 then
+ Mem_Size := Memory_Alignment;
+ else
+ -- It should not be possible to request an allocation of negative
+ -- size.
+
+ pragma Assert (Storage_Size >= 0);
+ Mem_Size := Round_Up (Storage_Size);
+ end if;
if Sec_Stack_Dynamic then
Allocate_Dynamic (Stack, Mem_Size, Addr);
diff --git a/gcc/ada/libgnat/s-stratt.adb b/gcc/ada/libgnat/s-stratt.adb
index 366dabd..8fe2721 100644
--- a/gcc/ada/libgnat/s-stratt.adb
+++ b/gcc/ada/libgnat/s-stratt.adb
@@ -44,7 +44,8 @@ package body System.Stream_Attributes is
function XDR_Support return Boolean;
pragma Inline (XDR_Support);
- -- Return True if XDR streaming should be used
+ -- Return True if XDR streaming should be used. Note that 128-bit integers
+ -- are not supported by the XDR protocol and will raise Device_Error.
Err : exception renames Ada.IO_Exceptions.End_Error;
-- Exception raised if insufficient data read (note that the RM implies
@@ -64,74 +65,81 @@ package body System.Stream_Attributes is
Thin_Pointer_Size : constant := System.Address'Size;
Fat_Pointer_Size : constant := System.Address'Size * 2;
- subtype S_AD is SEA (1 .. (Fat_Pointer_Size + SU - 1) / SU);
- subtype S_AS is SEA (1 .. (Thin_Pointer_Size + SU - 1) / SU);
- subtype S_B is SEA (1 .. (Boolean'Size + SU - 1) / SU);
- subtype S_C is SEA (1 .. (Character'Size + SU - 1) / SU);
- subtype S_F is SEA (1 .. (Float'Size + SU - 1) / SU);
- subtype S_I is SEA (1 .. (Integer'Size + SU - 1) / SU);
- subtype S_I24 is SEA (1 .. (Integer_24'Size + SU - 1) / SU);
- subtype S_LF is SEA (1 .. (Long_Float'Size + SU - 1) / SU);
- subtype S_LI is SEA (1 .. (Long_Integer'Size + SU - 1) / SU);
- subtype S_LLF is SEA (1 .. (Long_Long_Float'Size + SU - 1) / SU);
- subtype S_LLI is SEA (1 .. (Long_Long_Integer'Size + SU - 1) / SU);
- subtype S_LLU is SEA (1 .. (UST.Long_Long_Unsigned'Size + SU - 1) / SU);
- subtype S_LU is SEA (1 .. (UST.Long_Unsigned'Size + SU - 1) / SU);
- subtype S_SF is SEA (1 .. (Short_Float'Size + SU - 1) / SU);
- subtype S_SI is SEA (1 .. (Short_Integer'Size + SU - 1) / SU);
- subtype S_SSI is SEA (1 .. (Short_Short_Integer'Size + SU - 1) / SU);
- subtype S_SSU is SEA (1 .. (UST.Short_Short_Unsigned'Size + SU - 1) / SU);
- subtype S_SU is SEA (1 .. (UST.Short_Unsigned'Size + SU - 1) / SU);
- subtype S_U is SEA (1 .. (UST.Unsigned'Size + SU - 1) / SU);
- subtype S_U24 is SEA (1 .. (Unsigned_24'Size + SU - 1) / SU);
- subtype S_WC is SEA (1 .. (Wide_Character'Size + SU - 1) / SU);
- subtype S_WWC is SEA (1 .. (Wide_Wide_Character'Size + SU - 1) / SU);
+ subtype S_AD is SEA (1 .. (Fat_Pointer_Size + SU - 1) / SU);
+ subtype S_AS is SEA (1 .. (Thin_Pointer_Size + SU - 1) / SU);
+ subtype S_B is SEA (1 .. (Boolean'Size + SU - 1) / SU);
+ subtype S_C is SEA (1 .. (Character'Size + SU - 1) / SU);
+ subtype S_F is SEA (1 .. (Float'Size + SU - 1) / SU);
+ subtype S_I is SEA (1 .. (Integer'Size + SU - 1) / SU);
+ subtype S_I24 is SEA (1 .. (Integer_24'Size + SU - 1) / SU);
+ subtype S_LF is SEA (1 .. (Long_Float'Size + SU - 1) / SU);
+ subtype S_LI is SEA (1 .. (Long_Integer'Size + SU - 1) / SU);
+ subtype S_LLF is SEA (1 .. (Long_Long_Float'Size + SU - 1) / SU);
+ subtype S_LLI is SEA (1 .. (Long_Long_Integer'Size + SU - 1) / SU);
+ subtype S_LLLI is SEA (1 .. (Long_Long_Long_Integer'Size + SU - 1) / SU);
+ subtype S_LLLU is
+ SEA (1 .. (UST.Long_Long_Long_Unsigned'Size + SU - 1) / SU);
+ subtype S_LLU is SEA (1 .. (UST.Long_Long_Unsigned'Size + SU - 1) / SU);
+ subtype S_LU is SEA (1 .. (UST.Long_Unsigned'Size + SU - 1) / SU);
+ subtype S_SF is SEA (1 .. (Short_Float'Size + SU - 1) / SU);
+ subtype S_SI is SEA (1 .. (Short_Integer'Size + SU - 1) / SU);
+ subtype S_SSI is SEA (1 .. (Short_Short_Integer'Size + SU - 1) / SU);
+ subtype S_SSU is SEA (1 .. (UST.Short_Short_Unsigned'Size + SU - 1) / SU);
+ subtype S_SU is SEA (1 .. (UST.Short_Unsigned'Size + SU - 1) / SU);
+ subtype S_U is SEA (1 .. (UST.Unsigned'Size + SU - 1) / SU);
+ subtype S_U24 is SEA (1 .. (Unsigned_24'Size + SU - 1) / SU);
+ subtype S_WC is SEA (1 .. (Wide_Character'Size + SU - 1) / SU);
+ subtype S_WWC is SEA (1 .. (Wide_Wide_Character'Size + SU - 1) / SU);
-- Unchecked conversions from the elementary type to the stream type
- function From_AD is new UC (Fat_Pointer, S_AD);
- function From_AS is new UC (Thin_Pointer, S_AS);
- function From_F is new UC (Float, S_F);
- function From_I is new UC (Integer, S_I);
- function From_I24 is new UC (Integer_24, S_I24);
- function From_LF is new UC (Long_Float, S_LF);
- function From_LI is new UC (Long_Integer, S_LI);
- function From_LLF is new UC (Long_Long_Float, S_LLF);
- function From_LLI is new UC (Long_Long_Integer, S_LLI);
- function From_LLU is new UC (UST.Long_Long_Unsigned, S_LLU);
- function From_LU is new UC (UST.Long_Unsigned, S_LU);
- function From_SF is new UC (Short_Float, S_SF);
- function From_SI is new UC (Short_Integer, S_SI);
- function From_SSI is new UC (Short_Short_Integer, S_SSI);
- function From_SSU is new UC (UST.Short_Short_Unsigned, S_SSU);
- function From_SU is new UC (UST.Short_Unsigned, S_SU);
- function From_U is new UC (UST.Unsigned, S_U);
- function From_U24 is new UC (Unsigned_24, S_U24);
- function From_WC is new UC (Wide_Character, S_WC);
- function From_WWC is new UC (Wide_Wide_Character, S_WWC);
+ function From_AD is new UC (Fat_Pointer, S_AD);
+ function From_AS is new UC (Thin_Pointer, S_AS);
+ function From_F is new UC (Float, S_F);
+ function From_I is new UC (Integer, S_I);
+ function From_I24 is new UC (Integer_24, S_I24);
+ function From_LF is new UC (Long_Float, S_LF);
+ function From_LI is new UC (Long_Integer, S_LI);
+ function From_LLF is new UC (Long_Long_Float, S_LLF);
+ function From_LLI is new UC (Long_Long_Integer, S_LLI);
+ function From_LLLI is new UC (Long_Long_Long_Integer, S_LLLI);
+ function From_LLLU is new UC (UST.Long_Long_Long_Unsigned, S_LLLU);
+ function From_LLU is new UC (UST.Long_Long_Unsigned, S_LLU);
+ function From_LU is new UC (UST.Long_Unsigned, S_LU);
+ function From_SF is new UC (Short_Float, S_SF);
+ function From_SI is new UC (Short_Integer, S_SI);
+ function From_SSI is new UC (Short_Short_Integer, S_SSI);
+ function From_SSU is new UC (UST.Short_Short_Unsigned, S_SSU);
+ function From_SU is new UC (UST.Short_Unsigned, S_SU);
+ function From_U is new UC (UST.Unsigned, S_U);
+ function From_U24 is new UC (Unsigned_24, S_U24);
+ function From_WC is new UC (Wide_Character, S_WC);
+ function From_WWC is new UC (Wide_Wide_Character, S_WWC);
-- Unchecked conversions from the stream type to elementary type
- function To_AD is new UC (S_AD, Fat_Pointer);
- function To_AS is new UC (S_AS, Thin_Pointer);
- function To_F is new UC (S_F, Float);
- function To_I is new UC (S_I, Integer);
- function To_I24 is new UC (S_I24, Integer_24);
- function To_LF is new UC (S_LF, Long_Float);
- function To_LI is new UC (S_LI, Long_Integer);
- function To_LLF is new UC (S_LLF, Long_Long_Float);
- function To_LLI is new UC (S_LLI, Long_Long_Integer);
- function To_LLU is new UC (S_LLU, UST.Long_Long_Unsigned);
- function To_LU is new UC (S_LU, UST.Long_Unsigned);
- function To_SF is new UC (S_SF, Short_Float);
- function To_SI is new UC (S_SI, Short_Integer);
- function To_SSI is new UC (S_SSI, Short_Short_Integer);
- function To_SSU is new UC (S_SSU, UST.Short_Short_Unsigned);
- function To_SU is new UC (S_SU, UST.Short_Unsigned);
- function To_U is new UC (S_U, UST.Unsigned);
- function To_U24 is new UC (S_U24, Unsigned_24);
- function To_WC is new UC (S_WC, Wide_Character);
- function To_WWC is new UC (S_WWC, Wide_Wide_Character);
+ function To_AD is new UC (S_AD, Fat_Pointer);
+ function To_AS is new UC (S_AS, Thin_Pointer);
+ function To_F is new UC (S_F, Float);
+ function To_I is new UC (S_I, Integer);
+ function To_I24 is new UC (S_I24, Integer_24);
+ function To_LF is new UC (S_LF, Long_Float);
+ function To_LI is new UC (S_LI, Long_Integer);
+ function To_LLF is new UC (S_LLF, Long_Long_Float);
+ function To_LLI is new UC (S_LLI, Long_Long_Integer);
+ function To_LLLI is new UC (S_LLLI, Long_Long_Long_Integer);
+ function To_LLLU is new UC (S_LLLU, UST.Long_Long_Long_Unsigned);
+ function To_LLU is new UC (S_LLU, UST.Long_Long_Unsigned);
+ function To_LU is new UC (S_LU, UST.Long_Unsigned);
+ function To_SF is new UC (S_SF, Short_Float);
+ function To_SI is new UC (S_SI, Short_Integer);
+ function To_SSI is new UC (S_SSI, Short_Short_Integer);
+ function To_SSU is new UC (S_SSU, UST.Short_Short_Unsigned);
+ function To_SU is new UC (S_SU, UST.Short_Unsigned);
+ function To_U is new UC (S_U, UST.Unsigned);
+ function To_U24 is new UC (S_U24, Unsigned_24);
+ function To_WC is new UC (S_WC, Wide_Character);
+ function To_WWC is new UC (S_WWC, Wide_Wide_Character);
-----------------
-- XDR_Support --
@@ -393,6 +401,53 @@ package body System.Stream_Attributes is
end if;
end I_LLI;
+ ------------
+ -- I_LLLI --
+ ------------
+
+ function I_LLLI (Stream : not null access RST) return Long_Long_Long_Integer
+ is
+ T : S_LLLI;
+ L : SEO;
+
+ begin
+ if XDR_Support then
+ raise Ada.IO_Exceptions.Device_Error;
+ end if;
+
+ Ada.Streams.Read (Stream.all, T, L);
+
+ if L < T'Last then
+ raise Err;
+ else
+ return To_LLLI (T);
+ end if;
+ end I_LLLI;
+
+ ------------
+ -- I_LLLU --
+ ------------
+
+ function I_LLLU
+ (Stream : not null access RST) return UST.Long_Long_Long_Unsigned
+ is
+ T : S_LLLU;
+ L : SEO;
+
+ begin
+ if XDR_Support then
+ raise Ada.IO_Exceptions.Device_Error;
+ end if;
+
+ Ada.Streams.Read (Stream.all, T, L);
+
+ if L < T'Last then
+ raise Err;
+ else
+ return To_LLLU (T);
+ end if;
+ end I_LLLU;
+
-----------
-- I_LLU --
-----------
@@ -799,6 +854,35 @@ package body System.Stream_Attributes is
Ada.Streams.Write (Stream.all, From_LLI (Item));
end W_LLI;
+ ------------
+ -- W_LLLI --
+ ------------
+
+ procedure W_LLLI
+ (Stream : not null access RST; Item : Long_Long_Long_Integer) is
+ begin
+ if XDR_Support then
+ raise Ada.IO_Exceptions.Device_Error;
+ end if;
+
+ Ada.Streams.Write (Stream.all, From_LLLI (Item));
+ end W_LLLI;
+
+ ------------
+ -- W_LLLU --
+ ------------
+
+ procedure W_LLLU
+ (Stream : not null access RST; Item : UST.Long_Long_Long_Unsigned)
+ is
+ begin
+ if XDR_Support then
+ raise Ada.IO_Exceptions.Device_Error;
+ end if;
+
+ Ada.Streams.Write (Stream.all, From_LLLU (Item));
+ end W_LLLU;
+
-----------
-- W_LLU --
-----------
diff --git a/gcc/ada/libgnat/s-stratt.ads b/gcc/ada/libgnat/s-stratt.ads
index c8c453a..965dff6 100644
--- a/gcc/ada/libgnat/s-stratt.ads
+++ b/gcc/ada/libgnat/s-stratt.ads
@@ -104,29 +104,34 @@ package System.Stream_Attributes is
-- is the same for all elementary types (no bounds or discriminants
-- are involved).
- function I_AD (Stream : not null access RST) return Fat_Pointer;
- function I_AS (Stream : not null access RST) return Thin_Pointer;
- function I_B (Stream : not null access RST) return Boolean;
- function I_C (Stream : not null access RST) return Character;
- function I_F (Stream : not null access RST) return Float;
- function I_I (Stream : not null access RST) return Integer;
- function I_I24 (Stream : not null access RST) return Integer_24;
- function I_LF (Stream : not null access RST) return Long_Float;
- function I_LI (Stream : not null access RST) return Long_Integer;
- function I_LLF (Stream : not null access RST) return Long_Long_Float;
- function I_LLI (Stream : not null access RST) return Long_Long_Integer;
- function I_LLU (Stream : not null access RST) return UST.Long_Long_Unsigned;
- function I_LU (Stream : not null access RST) return UST.Long_Unsigned;
- function I_SF (Stream : not null access RST) return Short_Float;
- function I_SI (Stream : not null access RST) return Short_Integer;
- function I_SSI (Stream : not null access RST) return Short_Short_Integer;
- function I_SSU (Stream : not null access RST) return
- UST.Short_Short_Unsigned;
- function I_SU (Stream : not null access RST) return UST.Short_Unsigned;
- function I_U (Stream : not null access RST) return UST.Unsigned;
- function I_U24 (Stream : not null access RST) return Unsigned_24;
- function I_WC (Stream : not null access RST) return Wide_Character;
- function I_WWC (Stream : not null access RST) return Wide_Wide_Character;
+ function I_AD (Stream : not null access RST) return Fat_Pointer;
+ function I_AS (Stream : not null access RST) return Thin_Pointer;
+ function I_B (Stream : not null access RST) return Boolean;
+ function I_C (Stream : not null access RST) return Character;
+ function I_F (Stream : not null access RST) return Float;
+ function I_I (Stream : not null access RST) return Integer;
+ function I_I24 (Stream : not null access RST) return Integer_24;
+ function I_LF (Stream : not null access RST) return Long_Float;
+ function I_LI (Stream : not null access RST) return Long_Integer;
+ function I_LLF (Stream : not null access RST) return Long_Long_Float;
+ function I_LLI (Stream : not null access RST) return Long_Long_Integer;
+ function I_LLLI (Stream : not null access RST) return
+ Long_Long_Long_Integer;
+ function I_LLLU (Stream : not null access RST) return
+ UST.Long_Long_Long_Unsigned;
+ function I_LLU (Stream : not null access RST) return
+ UST.Long_Long_Unsigned;
+ function I_LU (Stream : not null access RST) return UST.Long_Unsigned;
+ function I_SF (Stream : not null access RST) return Short_Float;
+ function I_SI (Stream : not null access RST) return Short_Integer;
+ function I_SSI (Stream : not null access RST) return Short_Short_Integer;
+ function I_SSU (Stream : not null access RST) return
+ UST.Short_Short_Unsigned;
+ function I_SU (Stream : not null access RST) return UST.Short_Unsigned;
+ function I_U (Stream : not null access RST) return UST.Unsigned;
+ function I_U24 (Stream : not null access RST) return Unsigned_24;
+ function I_WC (Stream : not null access RST) return Wide_Character;
+ function I_WWC (Stream : not null access RST) return Wide_Wide_Character;
-----------------------
-- Output Procedures --
@@ -137,30 +142,34 @@ package System.Stream_Attributes is
-- 'Write and 'Output because there are no discriminants or bounds to
-- be written.
- procedure W_AD (Stream : not null access RST; Item : Fat_Pointer);
- procedure W_AS (Stream : not null access RST; Item : Thin_Pointer);
- procedure W_B (Stream : not null access RST; Item : Boolean);
- procedure W_C (Stream : not null access RST; Item : Character);
- procedure W_F (Stream : not null access RST; Item : Float);
- procedure W_I (Stream : not null access RST; Item : Integer);
- procedure W_I24 (Stream : not null access RST; Item : Integer_24);
- procedure W_LF (Stream : not null access RST; Item : Long_Float);
- procedure W_LI (Stream : not null access RST; Item : Long_Integer);
- procedure W_LLF (Stream : not null access RST; Item : Long_Long_Float);
- procedure W_LLI (Stream : not null access RST; Item : Long_Long_Integer);
- procedure W_LLU (Stream : not null access RST; Item :
- UST.Long_Long_Unsigned);
- procedure W_LU (Stream : not null access RST; Item : UST.Long_Unsigned);
- procedure W_SF (Stream : not null access RST; Item : Short_Float);
- procedure W_SI (Stream : not null access RST; Item : Short_Integer);
- procedure W_SSI (Stream : not null access RST; Item : Short_Short_Integer);
- procedure W_SSU (Stream : not null access RST; Item :
- UST.Short_Short_Unsigned);
- procedure W_SU (Stream : not null access RST; Item : UST.Short_Unsigned);
- procedure W_U (Stream : not null access RST; Item : UST.Unsigned);
- procedure W_U24 (Stream : not null access RST; Item : Unsigned_24);
- procedure W_WC (Stream : not null access RST; Item : Wide_Character);
- procedure W_WWC (Stream : not null access RST; Item : Wide_Wide_Character);
+ procedure W_AD (Stream : not null access RST; Item : Fat_Pointer);
+ procedure W_AS (Stream : not null access RST; Item : Thin_Pointer);
+ procedure W_B (Stream : not null access RST; Item : Boolean);
+ procedure W_C (Stream : not null access RST; Item : Character);
+ procedure W_F (Stream : not null access RST; Item : Float);
+ procedure W_I (Stream : not null access RST; Item : Integer);
+ procedure W_I24 (Stream : not null access RST; Item : Integer_24);
+ procedure W_LF (Stream : not null access RST; Item : Long_Float);
+ procedure W_LI (Stream : not null access RST; Item : Long_Integer);
+ procedure W_LLF (Stream : not null access RST; Item : Long_Long_Float);
+ procedure W_LLI (Stream : not null access RST; Item : Long_Long_Integer);
+ procedure W_LLLI (Stream : not null access RST; Item :
+ Long_Long_Long_Integer);
+ procedure W_LLLU (Stream : not null access RST; Item :
+ UST.Long_Long_Long_Unsigned);
+ procedure W_LLU (Stream : not null access RST; Item :
+ UST.Long_Long_Unsigned);
+ procedure W_LU (Stream : not null access RST; Item : UST.Long_Unsigned);
+ procedure W_SF (Stream : not null access RST; Item : Short_Float);
+ procedure W_SI (Stream : not null access RST; Item : Short_Integer);
+ procedure W_SSI (Stream : not null access RST; Item : Short_Short_Integer);
+ procedure W_SSU (Stream : not null access RST; Item :
+ UST.Short_Short_Unsigned);
+ procedure W_SU (Stream : not null access RST; Item : UST.Short_Unsigned);
+ procedure W_U (Stream : not null access RST; Item : UST.Unsigned);
+ procedure W_U24 (Stream : not null access RST; Item : Unsigned_24);
+ procedure W_WC (Stream : not null access RST; Item : Wide_Character);
+ procedure W_WWC (Stream : not null access RST; Item : Wide_Wide_Character);
function Block_IO_OK return Boolean;
-- Indicate whether the current setting supports block IO. See
@@ -177,6 +186,8 @@ private
pragma Inline (I_LI);
pragma Inline (I_LLF);
pragma Inline (I_LLI);
+ pragma Inline (I_LLLI);
+ pragma Inline (I_LLLU);
pragma Inline (I_LLU);
pragma Inline (I_LU);
pragma Inline (I_SF);
@@ -198,6 +209,8 @@ private
pragma Inline (W_LI);
pragma Inline (W_LLF);
pragma Inline (W_LLI);
+ pragma Inline (W_LLLI);
+ pragma Inline (W_LLLU);
pragma Inline (W_LLU);
pragma Inline (W_LU);
pragma Inline (W_SF);
diff --git a/gcc/ada/libgnat/s-trasym.ads b/gcc/ada/libgnat/s-trasym.ads
index e974ee9..fbeec8d 100644
--- a/gcc/ada/libgnat/s-trasym.ads
+++ b/gcc/ada/libgnat/s-trasym.ads
@@ -33,7 +33,8 @@
-- The full capability is currently supported on the following targets:
--- GNU/Linux x86, x86_64, ia64
+-- GNU/Linux x86, x86_64
+-- Windows x86, x86_64
-- Note: on targets other than those listed above, a dummy implementation
-- of the body returns a series of LF separated strings of the form "0x..."
diff --git a/gcc/ada/libgnat/s-vade128.ads b/gcc/ada/libgnat/s-vade128.ads
new file mode 100644
index 0000000..8edc742
--- /dev/null
+++ b/gcc/ada/libgnat/s-vade128.ads
@@ -0,0 +1,60 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ D E C I M A L _ 1 2 8 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning values for decimal fixed point
+-- types up to 128-bit mantissa, for use in Text_IO.Decimal_IO, and the Value
+-- attribute for such decimal types.
+
+with Interfaces;
+with System.Arith_128;
+with System.Value_D;
+
+package System.Val_Decimal_128 is
+ pragma Preelaborate;
+
+ subtype Int128 is Interfaces.Integer_128;
+ subtype Uns128 is Interfaces.Unsigned_128;
+
+ package Impl is new Value_D (Int128, Uns128, Arith_128.Scaled_Divide128);
+
+ function Scan_Decimal128
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int128
+ renames Impl.Scan_Decimal;
+
+ function Value_Decimal128
+ (Str : String;
+ Scale : Integer) return Int128
+ renames Impl.Value_Decimal;
+
+end System.Val_Decimal_128;
diff --git a/gcc/ada/libgnat/s-vade32.ads b/gcc/ada/libgnat/s-vade32.ads
new file mode 100644
index 0000000..b86ae52
--- /dev/null
+++ b/gcc/ada/libgnat/s-vade32.ads
@@ -0,0 +1,58 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ D E C I M A L _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning values for decimal fixed point
+-- types up to 32-bit mantissa, for use in Text_IO.Decimal_IO, and the Value
+-- attribute for such decimal types.
+
+with Interfaces;
+with System.Arith_32;
+with System.Value_D;
+
+package System.Val_Decimal_32 is
+ pragma Preelaborate;
+
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Uns32 is Interfaces.Unsigned_32;
+
+ package Impl is new Value_D (Int32, Uns32, Arith_32.Scaled_Divide32);
+
+ function Scan_Decimal32
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int32
+ renames Impl.Scan_Decimal;
+
+ function Value_Decimal32 (Str : String; Scale : Integer) return Int32
+ renames Impl.Value_Decimal;
+
+end System.Val_Decimal_32;
diff --git a/gcc/ada/libgnat/s-vade64.ads b/gcc/ada/libgnat/s-vade64.ads
new file mode 100644
index 0000000..d3a5b4f
--- /dev/null
+++ b/gcc/ada/libgnat/s-vade64.ads
@@ -0,0 +1,60 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ D E C I M A L _ 6 4 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning values for decimal fixed point
+-- types up to 64-bit mantissa, for use in Text_IO.Decimal_IO, and the Value
+-- attribute for such decimal types.
+
+with Interfaces;
+with System.Arith_64;
+with System.Value_D;
+
+package System.Val_Decimal_64 is
+ pragma Preelaborate;
+
+ subtype Int64 is Interfaces.Integer_64;
+ subtype Uns64 is Interfaces.Unsigned_64;
+
+ package Impl is new Value_D (Int64, Uns64, Arith_64.Scaled_Divide64);
+
+ function Scan_Decimal64
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int64
+ renames Impl.Scan_Decimal;
+
+ function Value_Decimal64
+ (Str : String;
+ Scale : Integer) return Int64
+ renames Impl.Value_Decimal;
+
+end System.Val_Decimal_64;
diff --git a/gcc/ada/libgnat/s-vafi128.ads b/gcc/ada/libgnat/s-vafi128.ads
new file mode 100644
index 0000000..03fbe80
--- /dev/null
+++ b/gcc/ada/libgnat/s-vafi128.ads
@@ -0,0 +1,60 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ F I X E D _ 1 2 8 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning values for ordinary fixed point
+-- types up to 128-bit small and mantissa, for use in Text_IO.Decimal_IO, and
+-- the Value attribute for such decimal types.
+
+with Interfaces;
+with System.Arith_128;
+with System.Value_F;
+
+package System.Val_Fixed_128 is
+ pragma Preelaborate;
+
+ subtype Int128 is Interfaces.Integer_128;
+ subtype Uns128 is Interfaces.Unsigned_128;
+
+ package Impl is new Value_F (Int128, Uns128, Arith_128.Scaled_Divide128);
+
+ function Scan_Fixed128
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int128;
+ Den : Int128) return Int128
+ renames Impl.Scan_Fixed;
+
+ function Value_Fixed128
+ (Str : String; Num : Int128; Den : Int128) return Int128
+ renames Impl.Value_Fixed;
+
+end System.Val_Fixed_128;
diff --git a/gcc/ada/libgnat/s-vafi32.ads b/gcc/ada/libgnat/s-vafi32.ads
new file mode 100644
index 0000000..6235a82
--- /dev/null
+++ b/gcc/ada/libgnat/s-vafi32.ads
@@ -0,0 +1,60 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ F I X E D _ 3 2 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning values for decimal fixed point
+-- types up to 32-bit small and mantissa, for use in Text_IO.Decimal_IO, and
+-- the Value attribute for such decimal types.
+
+with Interfaces;
+with System.Arith_32;
+with System.Value_F;
+
+package System.Val_Fixed_32 is
+ pragma Preelaborate;
+
+ subtype Int32 is Interfaces.Integer_32;
+ subtype Uns32 is Interfaces.Unsigned_32;
+
+ package Impl is new Value_F (Int32, Uns32, Arith_32.Scaled_Divide32);
+
+ function Scan_Fixed32
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int32;
+ Den : Int32) return Int32
+ renames Impl.Scan_Fixed;
+
+ function Value_Fixed32
+ (Str : String; Num : Int32; Den : Int32) return Int32
+ renames Impl.Value_Fixed;
+
+end System.Val_Fixed_32;
diff --git a/gcc/ada/libgnat/s-vafi64.ads b/gcc/ada/libgnat/s-vafi64.ads
new file mode 100644
index 0000000..9f98df4
--- /dev/null
+++ b/gcc/ada/libgnat/s-vafi64.ads
@@ -0,0 +1,60 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ F I X E D _ 6 4 --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning values for decimal fixed point
+-- types up to 64-bit small and mantissa, for use in Text_IO.Decimal_IO, and
+-- the Value attribute for such decimal types.
+
+with Interfaces;
+with System.Arith_64;
+with System.Value_F;
+
+package System.Val_Fixed_64 is
+ pragma Preelaborate;
+
+ subtype Int64 is Interfaces.Integer_64;
+ subtype Uns64 is Interfaces.Unsigned_64;
+
+ package Impl is new Value_F (Int64, Uns64, Arith_64.Scaled_Divide64);
+
+ function Scan_Fixed64
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int64;
+ Den : Int64) return Int64
+ renames Impl.Scan_Fixed;
+
+ function Value_Fixed64
+ (Str : String; Num : Int64; Den : Int64) return Int64
+ renames Impl.Value_Fixed;
+
+end System.Val_Fixed_64;
diff --git a/gcc/ada/libgnat/s-valdec.adb b/gcc/ada/libgnat/s-valdec.adb
deleted file mode 100644
index 99fffaf..0000000
--- a/gcc/ada/libgnat/s-valdec.adb
+++ /dev/null
@@ -1,68 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y S T E M . V A L _ D E C --
--- --
--- B o d y --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-with System.Val_Real; use System.Val_Real;
-
-package body System.Val_Dec is
-
- ------------------
- -- Scan_Decimal --
- ------------------
-
- -- For decimal types where Size < Integer'Size, it is fine to use
- -- the floating-point circuit, since it certainly has sufficient
- -- precision for any reasonable hardware, and we just don't support
- -- things on junk hardware.
-
- function Scan_Decimal
- (Str : String;
- Ptr : not null access Integer;
- Max : Integer;
- Scale : Integer) return Integer
- is
- Val : Long_Long_Float;
- begin
- Val := Scan_Real (Str, Ptr, Max);
- return Integer (Val * 10.0 ** Scale);
- end Scan_Decimal;
-
- -------------------
- -- Value_Decimal --
- -------------------
-
- -- Again, we use the real circuit for this purpose
-
- function Value_Decimal (Str : String; Scale : Integer) return Integer is
- begin
- return Integer (Value_Real (Str) * 10.0 ** Scale);
- end Value_Decimal;
-
-end System.Val_Dec;
diff --git a/gcc/ada/libgnat/s-valdec.ads b/gcc/ada/libgnat/s-valdec.ads
deleted file mode 100644
index 05fab98..0000000
--- a/gcc/ada/libgnat/s-valdec.ads
+++ /dev/null
@@ -1,80 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y S T E M . V A L _ D E C --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This package contains routines for scanning decimal values where the size
--- of the type is no greater than Standard.Integer'Size, for use in Text_IO.
--- Decimal_IO, and the Value attribute for such decimal types.
-
-package System.Val_Dec is
- pragma Preelaborate;
-
- function Scan_Decimal
- (Str : String;
- Ptr : not null access Integer;
- Max : Integer;
- Scale : Integer) return Integer;
- -- This function scans the string starting at Str (Ptr.all) for a valid
- -- real literal according to the syntax described in (RM 3.5(43)). The
- -- substring scanned extends no further than Str (Max). There are three
- -- cases for the return:
- --
- -- If a valid real literal is found after scanning past any initial spaces,
- -- then Ptr.all is updated past the last character of the literal (but
- -- trailing spaces are not scanned out). The value returned is the value
- -- Integer'Integer_Value (decimal-literal-value), using the given Scale
- -- to determine this value.
- --
- -- If no valid real literal is found, then Ptr.all points either to an
- -- initial non-digit character, or to Max + 1 if the field is all spaces
- -- and the exception Constraint_Error is raised.
- --
- -- If a syntactically valid integer is scanned, but the value is out of
- -- range, or, in the based case, the base value is out of range or there
- -- is an out of range digit, then Ptr.all points past the integer, and
- -- Constraint_Error is raised.
- --
- -- Note: these rules correspond to the requirements for leaving the
- -- pointer positioned in Text_Io.Get
- --
- -- Note: if Str is null, i.e. if Max is less than Ptr, then this is a
- -- special case of an all-blank string, and Ptr is unchanged, and hence
- -- is greater than Max as required in this case.
-
- function Value_Decimal (Str : String; Scale : Integer) return Integer;
- -- Used in computing X'Value (Str) where X is a decimal fixed-point type
- -- whose size does not exceed Standard.Integer'Size. Str is the string
- -- argument of the attribute. Constraint_Error is raised if the string
- -- is malformed or if the value is out of range of Integer (not the
- -- range of the fixed-point type, that check must be done by the caller.
- -- Otherwise the value returned is the value Integer'Integer_Value
- -- (decimal-literal-value), using Scale to determine this value.
-
-end System.Val_Dec;
diff --git a/gcc/ada/libgnat/s-valflt.ads b/gcc/ada/libgnat/s-valflt.ads
new file mode 100644
index 0000000..5806d58
--- /dev/null
+++ b/gcc/ada/libgnat/s-valflt.ads
@@ -0,0 +1,57 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ F L T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning real values for floating point
+-- type Float, for use in Text_IO.Float_IO and the Value attribute.
+
+with Interfaces;
+with System.Powten_Flt;
+with System.Val_Real;
+
+package System.Val_Flt is
+ pragma Preelaborate;
+
+ package Impl is new Val_Real
+ (Float,
+ Interfaces.Unsigned_32,
+ System.Powten_Flt.Maxpow,
+ System.Powten_Flt.Powten'Address);
+
+ function Scan_Float
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Float
+ renames Impl.Scan_Real;
+
+ function Value_Float (Str : String) return Float
+ renames Impl.Value_Real;
+
+end System.Val_Flt;
diff --git a/gcc/ada/libgnat/s-vallfl.ads b/gcc/ada/libgnat/s-vallfl.ads
new file mode 100644
index 0000000..c612f75
--- /dev/null
+++ b/gcc/ada/libgnat/s-vallfl.ads
@@ -0,0 +1,57 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ L F L T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning real values for floating point
+-- type Long_Float, for use in Text_IO.Float_IO and the Value attribute.
+
+with Interfaces;
+with System.Powten_LFlt;
+with System.Val_Real;
+
+package System.Val_LFlt is
+ pragma Preelaborate;
+
+ package Impl is new Val_Real
+ (Long_Float,
+ Interfaces.Unsigned_64,
+ System.Powten_LFlt.Maxpow,
+ System.Powten_LFlt.Powten'Address);
+
+ function Scan_Long_Float
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Long_Float
+ renames Impl.Scan_Real;
+
+ function Value_Long_Float (Str : String) return Long_Float
+ renames Impl.Value_Real;
+
+end System.Val_LFlt;
diff --git a/gcc/ada/libgnat/s-vallld.adb b/gcc/ada/libgnat/s-vallld.adb
deleted file mode 100644
index 4efa969..0000000
--- a/gcc/ada/libgnat/s-vallld.adb
+++ /dev/null
@@ -1,70 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y S T E M . V A L _ L L D --
--- --
--- B o d y --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-with System.Val_Real; use System.Val_Real;
-
-package body System.Val_LLD is
-
- ----------------------------
- -- Scan_Long_Long_Decimal --
- ----------------------------
-
- -- We use the floating-point circuit for now, this will be OK on a PC,
- -- but definitely does NOT have the required precision if the longest
- -- float type is IEEE double. This must be fixed in the future ???
-
- function Scan_Long_Long_Decimal
- (Str : String;
- Ptr : not null access Integer;
- Max : Integer;
- Scale : Integer) return Long_Long_Integer
- is
- Val : Long_Long_Float;
- begin
- Val := Scan_Real (Str, Ptr, Max);
- return Long_Long_Integer (Val * 10.0 ** Scale);
- end Scan_Long_Long_Decimal;
-
- -----------------------------
- -- Value_Long_Long_Decimal --
- -----------------------------
-
- -- Again we cheat and use floating-point ???
-
- function Value_Long_Long_Decimal
- (Str : String;
- Scale : Integer) return Long_Long_Integer
- is
- begin
- return Long_Long_Integer (Value_Real (Str) * 10.0 ** Scale);
- end Value_Long_Long_Decimal;
-
-end System.Val_LLD;
diff --git a/gcc/ada/libgnat/s-vallld.ads b/gcc/ada/libgnat/s-vallld.ads
deleted file mode 100644
index 652362d..0000000
--- a/gcc/ada/libgnat/s-vallld.ads
+++ /dev/null
@@ -1,81 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y S T E M . V A L _ L L D --
--- --
--- S p e c --
--- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This package contains routines for scanning decimal values where the size
--- of the type is greater than Standard.Integer'Size, for use in Text_IO.
--- Decimal_IO, and the Value attribute for such decimal types.
-
-package System.Val_LLD is
- pragma Preelaborate;
-
- function Scan_Long_Long_Decimal
- (Str : String;
- Ptr : not null access Integer;
- Max : Integer;
- Scale : Integer) return Long_Long_Integer;
- -- This function scans the string starting at Str (Ptr.all) for a valid
- -- real literal according to the syntax described in (RM 3.5(43)). The
- -- substring scanned extends no further than Str (Max). There are three
- -- cases for the return:
- --
- -- If a valid real literal is found after scanning past any initial spaces,
- -- then Ptr.all is updated past the last character of the literal (but
- -- trailing spaces are not scanned out). The value returned is the value
- -- Long_Long_Integer'Integer_Value (decimal-literal-value), using the given
- -- Scale to determine this value.
- --
- -- If no valid real literal is found, then Ptr.all points either to an
- -- initial non-digit character, or to Max + 1 if the field is all spaces
- -- and the exception Constraint_Error is raised.
- --
- -- If a syntactically valid integer is scanned, but the value is out of
- -- range, or, in the based case, the base value is out of range or there
- -- is an out of range digit, then Ptr.all points past the integer, and
- -- Constraint_Error is raised.
- --
- -- Note: these rules correspond to the requirements for leaving the
- -- pointer positioned in Text_Io.Get
- --
- -- Note: if Str is null, i.e. if Max is less than Ptr, then this is a
- -- special case of an all-blank string, and Ptr is unchanged, and hence
- -- is greater than Max as required in this case.
-
- function Value_Long_Long_Decimal
- (Str : String;
- Scale : Integer) return Long_Long_Integer;
- -- Used in computing X'Value (Str) where X is a decimal types whose size
- -- exceeds Standard.Integer'Size. Str is the string argument of the
- -- attribute. Constraint_Error is raised if the string is malformed
- -- or if the value is out of range, otherwise the value returned is the
- -- value Long_Long_Integer'Integer_Value (decimal-literal-value), using
- -- the given Scale to determine this value.
-
-end System.Val_LLD;
diff --git a/gcc/ada/libgnat/s-valllf.ads b/gcc/ada/libgnat/s-valllf.ads
new file mode 100644
index 0000000..46a311b
--- /dev/null
+++ b/gcc/ada/libgnat/s-valllf.ads
@@ -0,0 +1,57 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L _ L L F --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning real values for floating point
+-- type Long_Long_Float, for use in Text_IO.Float_IO and the Value attribute.
+
+with Interfaces;
+with System.Powten_LLF;
+with System.Val_Real;
+
+package System.Val_LLF is
+ pragma Preelaborate;
+
+ package Impl is new Val_Real
+ (Long_Long_Float,
+ Interfaces.Unsigned_64,
+ System.Powten_LLF.Maxpow,
+ System.Powten_LLF.Powten'Address);
+
+ function Scan_Long_Long_Float
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Long_Long_Float
+ renames Impl.Scan_Real;
+
+ function Value_Long_Long_Float (Str : String) return Long_Long_Float
+ renames Impl.Value_Real;
+
+end System.Val_LLF;
diff --git a/gcc/ada/libgnat/s-valrea.adb b/gcc/ada/libgnat/s-valrea.adb
index 1a47dc2..0ac3846 100644
--- a/gcc/ada/libgnat/s-valrea.adb
+++ b/gcc/ada/libgnat/s-valrea.adb
@@ -29,514 +29,241 @@
-- --
------------------------------------------------------------------------------
-with System.Val_Util; use System.Val_Util;
with System.Float_Control;
+with System.Unsigned_Types; use System.Unsigned_Types;
+with System.Val_Util; use System.Val_Util;
+with System.Value_R;
-package body System.Val_Real is
+pragma Warnings (Off, "non-static constant in preelaborated unit");
+-- Every constant is static given our instantiation model
- procedure Scan_Integral_Digits
- (Str : String;
- Index : in out Integer;
- Max : Integer;
- Value : out Long_Long_Integer;
- Scale : out Integer;
- Base_Violation : in out Boolean;
- Base : Long_Long_Integer := 10;
- Base_Specified : Boolean := False);
- -- Scan the integral part of a real (i.e: before decimal separator)
- --
- -- The string parsed is Str (Index .. Max), and after the call Index will
- -- point to the first non parsed character.
- --
- -- For each digit parsed either value := value * base + digit, or scale
- -- is incremented by 1.
- --
- -- Base_Violation will be set to True a digit found is not part of the Base
-
- procedure Scan_Decimal_Digits
- (Str : String;
- Index : in out Integer;
- Max : Integer;
- Value : in out Long_Long_Integer;
- Scale : in out Integer;
- Base_Violation : in out Boolean;
- Base : Long_Long_Integer := 10;
- Base_Specified : Boolean := False);
- -- Scan the decimal part of a real (i.e: after decimal separator)
- --
- -- The string parsed is Str (Index .. Max), and after the call Index will
- -- point to the first non parsed character.
- --
- -- For each digit parsed value = value * base + digit and scale is
- -- decremented by 1. If precision limit is reached remaining digits are
- -- still parsed but ignored.
- --
- -- Base_Violation will be set to True a digit found is not part of the Base
-
- subtype Char_As_Digit is Long_Long_Integer range -2 .. 15;
- subtype Valid_Digit is Char_As_Digit range 0 .. Char_As_Digit'Last;
- Underscore : constant Char_As_Digit := -2;
- E_Digit : constant Char_As_Digit := 14;
-
- function As_Digit (C : Character) return Char_As_Digit;
- -- Given a character return the digit it represent. If the character is
- -- not a digit then a negative value is returned, -2 for underscore and
- -- -1 for any other character.
-
- Precision_Limit : constant Long_Long_Integer :=
- 2 ** (Long_Long_Float'Machine_Mantissa - 1) - 1;
- -- This is an upper bound for the number of bits used to represent the
- -- mantissa. Beyond that number, any digits parsed are useless.
-
- --------------
- -- As_Digit --
- --------------
-
- function As_Digit (C : Character) return Char_As_Digit is
- begin
- case C is
- when '0' .. '9' =>
- return Character'Pos (C) - Character'Pos ('0');
- when 'a' .. 'f' =>
- return Character'Pos (C) - (Character'Pos ('a') - 10);
- when 'A' .. 'F' =>
- return Character'Pos (C) - (Character'Pos ('A') - 10);
- when '_' =>
- return Underscore;
- when others =>
- return -1;
- end case;
- end As_Digit;
-
- -------------------------
- -- Scan_Decimal_Digits --
- -------------------------
-
- procedure Scan_Decimal_Digits
- (Str : String;
- Index : in out Integer;
- Max : Integer;
- Value : in out Long_Long_Integer;
- Scale : in out Integer;
- Base_Violation : in out Boolean;
- Base : Long_Long_Integer := 10;
- Base_Specified : Boolean := False)
+package body System.Val_Real is
+ pragma Assert (Num'Machine_Mantissa <= Uns'Size);
+ -- We need an unsigned type large enough to represent the mantissa
+
+ Need_Extra : constant Boolean := Num'Machine_Mantissa > Uns'Size - 4;
+ -- If the mantissa of the floating-point type is almost as large as the
+ -- unsigned type, we do not have enough space for an extra digit in the
+ -- unsigned type so we handle the extra digit separately, at the cost of
+ -- a potential roundoff error.
+
+ Precision_Limit : constant Uns :=
+ (if Need_Extra then 2**Num'Machine_Mantissa - 1 else 2**Uns'Size - 1);
+ -- If we handle the extra digit separately, we use the precision of the
+ -- floating-point type so that the conversion is exact.
+
+ package Impl is new Value_R (Uns, Precision_Limit, Round => Need_Extra);
+
+ subtype Base_T is Unsigned range 2 .. 16;
+
+ -- The following tables compute the maximum exponent of the base that can
+ -- fit in the given floating-point format, that is to say the element at
+ -- index N is the largest K such that N**K <= Num'Last.
+
+ Maxexp32 : constant array (Base_T) of Positive :=
+ (2 => 127, 3 => 80, 4 => 63, 5 => 55, 6 => 49,
+ 7 => 45, 8 => 42, 9 => 40, 10 => 38, 11 => 37,
+ 12 => 35, 13 => 34, 14 => 33, 15 => 32, 16 => 31);
+
+ Maxexp64 : constant array (Base_T) of Positive :=
+ (2 => 1023, 3 => 646, 4 => 511, 5 => 441, 6 => 396,
+ 7 => 364, 8 => 341, 9 => 323, 10 => 308, 11 => 296,
+ 12 => 285, 13 => 276, 14 => 268, 15 => 262, 16 => 255);
+
+ Maxexp80 : constant array (Base_T) of Positive :=
+ (2 => 16383, 3 => 10337, 4 => 8191, 5 => 7056, 6 => 6338,
+ 7 => 5836, 8 => 5461, 9 => 5168, 10 => 4932, 11 => 4736,
+ 12 => 4570, 13 => 4427, 14 => 4303, 15 => 4193, 16 => 4095);
+
+ function Integer_to_Real
+ (Str : String;
+ Val : Uns;
+ Base : Unsigned;
+ Scale : Integer;
+ Extra : Unsigned;
+ Minus : Boolean) return Num;
+ -- Convert the real value from integer to real representation
+
+ ---------------------
+ -- Integer_to_Real --
+ ---------------------
+
+ function Integer_to_Real
+ (Str : String;
+ Val : Uns;
+ Base : Unsigned;
+ Scale : Integer;
+ Extra : Unsigned;
+ Minus : Boolean) return Num
is
- Precision_Limit_Reached : Boolean := False;
- -- Set to True if addition of a digit will cause Value to be superior
- -- to Precision_Limit.
+ pragma Assert (Base in 2 .. 16);
+
+ pragma Assert (Num'Machine_Radix = 2);
+
+ pragma Unsuppress (Range_Check);
+
+ Maxexp : constant Positive :=
+ (if Num'Size = 32 then Maxexp32 (Base)
+ elsif Num'Size = 64 then Maxexp64 (Base)
+ elsif Num'Machine_Mantissa = 64 then Maxexp80 (Base)
+ else raise Program_Error);
+ -- Maximum exponent of the base that can fit in Num
- Digit : Char_As_Digit;
- -- The current digit.
+ B : constant Num := Num (Base);
- Trailing_Zeros : Natural := 0;
- -- Number of trailing zeros at a given point.
+ R_Val : Num;
+ S : Integer := Scale;
begin
- pragma Assert (Base in 2 .. 16);
+ -- We call the floating-point processor reset routine so we can be sure
+ -- that the x87 FPU is properly set for conversions. This is especially
+ -- needed on Windows, where calls to the operating system randomly reset
+ -- the processor into 64-bit mode.
- -- If initial Scale is not 0 then it means that Precision_Limit was
- -- reached during integral part scanning.
- if Scale > 0 then
- Precision_Limit_Reached := True;
+ if Num'Machine_Mantissa = 64 then
+ System.Float_Control.Reset;
end if;
- -- The function precondition is that the first character is a valid
- -- digit.
- Digit := As_Digit (Str (Index));
-
- loop
- -- Check if base is correct. If the base is not specified the digit
- -- E or e cannot be considered as a base violation as it can be used
- -- for exponentiation.
- if Digit >= Base then
- if Base_Specified then
- Base_Violation := True;
- elsif Digit = E_Digit then
- return;
- else
- Base_Violation := True;
- end if;
- end if;
-
- -- If precision limit has been reached just ignore any remaining
- -- digits for the computation of Value and Scale. The scanning
- -- should continue only to assess the validity of the string
- if not Precision_Limit_Reached then
- if Digit = 0 then
- -- Trailing '0' digits are ignored unless a non-zero digit is
- -- found.
- Trailing_Zeros := Trailing_Zeros + 1;
- else
-
- -- Handle accumulated zeros.
- for J in 1 .. Trailing_Zeros loop
- if Value > Precision_Limit / Base then
- Precision_Limit_Reached := True;
- exit;
- else
- Value := Value * Base;
- Scale := Scale - 1;
- end if;
- end loop;
+ -- Do the conversion
- -- Reset trailing zero counter
- Trailing_Zeros := 0;
+ R_Val := Num (Val);
- -- Handle current non zero digit
- if Value > (Precision_Limit - Digit) / Base then
- Precision_Limit_Reached := True;
- else
- Value := Value * Base + Digit;
- Scale := Scale - 1;
- end if;
- end if;
- end if;
+ -- Take into account the extra digit, if need be. In this case, the
+ -- three operands are exact, so using an FMA would be ideal.
- -- Check next character
- Index := Index + 1;
+ if Need_Extra and then Extra > 0 then
+ R_Val := R_Val * B + Num (Extra);
+ S := S - 1;
+ end if;
- if Index > Max then
- return;
- end if;
+ -- Compute the final value
- Digit := As_Digit (Str (Index));
+ if R_Val /= 0.0 and then S /= 0 then
+ case Base is
+ -- If the base is a power of two, we use the efficient Scaling
+ -- attribute with an overflow check, if it is not 2, to catch
+ -- ludicrous exponents that would result in an infinity or zero.
- if Digit < 0 then
- if Digit = Underscore and Index + 1 <= Max then
- -- Underscore is only allowed if followed by a digit
- Digit := As_Digit (Str (Index + 1));
- if Digit in Valid_Digit then
- Index := Index + 1;
- else
- return;
+ when 2 =>
+ R_Val := Num'Scaling (R_Val, S);
+
+ when 4 =>
+ if Integer'First / 2 <= S and then S <= Integer'Last / 2 then
+ S := S * 2;
end if;
- else
- -- Neither a valid underscore nor a digit.
- return;
- end if;
- end if;
- end loop;
- end Scan_Decimal_Digits;
-
- --------------------------
- -- Scan_Integral_Digits --
- --------------------------
-
- procedure Scan_Integral_Digits
- (Str : String;
- Index : in out Integer;
- Max : Integer;
- Value : out Long_Long_Integer;
- Scale : out Integer;
- Base_Violation : in out Boolean;
- Base : Long_Long_Integer := 10;
- Base_Specified : Boolean := False)
- is
- Precision_Limit_Reached : Boolean := False;
- -- Set to True if addition of a digit will cause Value to be superior
- -- to Precision_Limit.
- Digit : Char_As_Digit;
- -- The current digit
- begin
+ R_Val := Num'Scaling (R_Val, S);
- -- Initialize Scale and Value
- Value := 0;
- Scale := 0;
-
- -- The function precondition is that the first character is a valid
- -- digit.
- Digit := As_Digit (Str (Index));
-
- loop
- -- Check if base is correct. If the base is not specified the digit
- -- E or e cannot be considered as a base violation as it can be used
- -- for exponentiation.
- if Digit >= Base then
- if Base_Specified then
- Base_Violation := True;
- elsif Digit = E_Digit then
- return;
- else
- Base_Violation := True;
- end if;
- end if;
-
- if Precision_Limit_Reached then
- -- Precision limit has been reached so just update the exponent
- Scale := Scale + 1;
- else
- pragma Assert (Base /= 0);
-
- if Value > (Precision_Limit - Digit) / Base then
- -- Updating Value will overflow so ignore this digit and any
- -- following ones. Only update the scale
- Precision_Limit_Reached := True;
- Scale := Scale + 1;
- else
- Value := Value * Base + Digit;
- end if;
- end if;
-
- -- Look for the next character
- Index := Index + 1;
- if Index > Max then
- return;
- end if;
-
- Digit := As_Digit (Str (Index));
-
- if Digit not in Valid_Digit then
- -- Next character is not a digit. In that case stop scanning
- -- unless the next chracter is an underscore followed by a digit.
- if Digit = Underscore and Index + 1 <= Max then
- Digit := As_Digit (Str (Index + 1));
- if Digit in Valid_Digit then
- Index := Index + 1;
- else
- return;
+ when 8 =>
+ if Integer'First / 3 <= S and then S <= Integer'Last / 3 then
+ S := S * 3;
end if;
- else
- return;
- end if;
- end if;
- end loop;
- end Scan_Integral_Digits;
+ R_Val := Num'Scaling (R_Val, S);
- ---------------
- -- Scan_Real --
- ---------------
-
- function Scan_Real
- (Str : String;
- Ptr : not null access Integer;
- Max : Integer)
- return Long_Long_Float
+ when 16 =>
+ if Integer'First / 4 <= S and then S <= Integer'Last / 4 then
+ S := S * 4;
+ end if;
- is
- Start : Positive;
- -- Position of starting non-blank character
+ R_Val := Num'Scaling (R_Val, S);
- Minus : Boolean;
- -- Set to True if minus sign is present, otherwise to False
+ -- If the base is 10, we use a table of powers for accuracy's sake
- Index : Integer;
- -- Local copy of string pointer
+ when 10 =>
+ declare
+ Powten : constant array (0 .. Maxpow) of Num;
+ pragma Import (Ada, Powten);
+ for Powten'Address use Powten_Address;
- Int_Value : Long_Long_Integer := -1;
- -- Mantissa as an Integer
+ begin
+ if S > 0 then
+ while S > Maxpow loop
+ R_Val := R_Val * Powten (Maxpow);
+ S := S - Maxpow;
+ end loop;
- Int_Scale : Integer := 0;
- -- Exponent value
+ R_Val := R_Val * Powten (S);
- Base_Violation : Boolean := False;
- -- If True some digits where not in the base. The float is still scan
- -- till the end even if an error will be raised.
-
- Uval : Long_Long_Float := 0.0;
- -- Contain the final value at the end of the function
+ else
+ while S < -Maxpow loop
+ R_Val := R_Val / Powten (Maxpow);
+ S := S + Maxpow;
+ end loop;
- After_Point : Boolean := False;
- -- True if a decimal should be parsed
+ R_Val := R_Val / Powten (-S);
+ end if;
+ end;
- Base : Long_Long_Integer := 10;
- -- Current base (default: 10)
+ -- Implementation for other bases with exponentiation
- Base_Char : Character := ASCII.NUL;
- -- Character used to set the base. If Nul this means that default
- -- base is used.
+ -- When the exponent is positive, we can do the computation
+ -- directly because, if the exponentiation overflows, then
+ -- the final value overflows as well. But when the exponent
+ -- is negative, we may need to do it in two steps to avoid
+ -- an artificial underflow.
- begin
- -- We do not tolerate strings with Str'Last = Positive'Last
+ when others =>
+ if S > 0 then
+ R_Val := R_Val * B ** S;
- if Str'Last = Positive'Last then
- raise Program_Error with
- "string upper bound is Positive'Last, not supported";
- end if;
+ else
+ if S < -Maxexp then
+ R_Val := R_Val / B ** Maxexp;
+ S := S + Maxexp;
+ end if;
- -- We call the floating-point processor reset routine so that we can
- -- be sure the floating-point processor is properly set for conversion
- -- calls. This is notably need on Windows, where calls to the operating
- -- system randomly reset the processor into 64-bit mode.
-
- System.Float_Control.Reset;
-
- -- Scan the optional sign
- Scan_Sign (Str, Ptr, Max, Minus, Start);
- Index := Ptr.all;
- Ptr.all := Start;
-
- -- First character can be either a decimal digit or a dot.
- if Str (Index) in '0' .. '9' then
- pragma Annotate
- (CodePeer, Intentional,
- "test always true", "defensive code below");
-
- -- If this is a digit it can indicates either the float decimal
- -- part or the base to use
- Scan_Integral_Digits
- (Str,
- Index,
- Max => Max,
- Value => Int_Value,
- Scale => Int_Scale,
- Base_Violation => Base_Violation,
- Base => 10);
- elsif Str (Index) = '.' and then
- -- A dot is only allowed if followed by a digit.
- Index < Max and then
- Str (Index + 1) in '0' .. '9'
- then
- -- Initial point, allowed only if followed by digit (RM 3.5(47))
- After_Point := True;
- Index := Index + 1;
- Int_Value := 0;
- else
- Bad_Value (Str);
+ R_Val := R_Val / B ** (-S);
+ end if;
+ end case;
end if;
- -- Check if the first number encountered is a base
- if Index < Max and then
- (Str (Index) = '#' or else Str (Index) = ':')
- then
- Base_Char := Str (Index);
- Base := Int_Value;
-
- -- Reset Int_Value to indicate that parsing of integral value should
- -- be done
- Int_Value := -1;
- if Base < 2 or else Base > 16 then
- Base_Violation := True;
- Base := 16;
- end if;
-
- Index := Index + 1;
-
- if Str (Index) = '.' and then
- Index < Max and then
- As_Digit (Str (Index + 1)) in Valid_Digit
- then
- After_Point := True;
- Index := Index + 1;
- Int_Value := 0;
- end if;
- end if;
+ -- Finally deal with initial minus sign, note that this processing is
+ -- done even if Uval is zero, so that -0.0 is correctly interpreted.
- -- Does scanning of integral part needed
- if Int_Value < 0 then
- if Index > Max or else As_Digit (Str (Index)) not in Valid_Digit then
- Bad_Value (Str);
- end if;
-
- Scan_Integral_Digits
- (Str,
- Index,
- Max => Max,
- Value => Int_Value,
- Scale => Int_Scale,
- Base_Violation => Base_Violation,
- Base => Base,
- Base_Specified => Base_Char /= ASCII.NUL);
- end if;
+ return (if Minus then -R_Val else R_Val);
- -- Do we have a dot ?
- if not After_Point and then
- Index <= Max and then
- Str (Index) = '.'
- then
- -- At this stage if After_Point was not set, this means that an
- -- integral part has been found. Thus the dot is valid even if not
- -- followed by a digit.
- if Index < Max and then As_Digit (Str (Index + 1)) in Valid_Digit then
- After_Point := True;
- end if;
-
- Index := Index + 1;
- end if;
+ exception
+ when Constraint_Error => Bad_Value (Str);
+ end Integer_to_Real;
- if After_Point then
- -- Parse decimal part
- Scan_Decimal_Digits
- (Str,
- Index,
- Max => Max,
- Value => Int_Value,
- Scale => Int_Scale,
- Base_Violation => Base_Violation,
- Base => Base,
- Base_Specified => Base_Char /= ASCII.NUL);
- end if;
+ ---------------
+ -- Scan_Real --
+ ---------------
- -- If an explicit base was specified ensure that the delimiter is found
- if Base_Char /= ASCII.NUL then
- if Index > Max or else Str (Index) /= Base_Char then
- Bad_Value (Str);
- else
- Index := Index + 1;
- end if;
- end if;
+ function Scan_Real
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer) return Num
+ is
+ Base : Unsigned;
+ Scale : Integer;
+ Extra : Unsigned;
+ Minus : Boolean;
+ Val : Uns;
- -- Compute the final value
- Uval := Long_Long_Float (Int_Value);
-
- -- Update pointer and scan exponent.
- Ptr.all := Index;
-
- Int_Scale := Int_Scale + Scan_Exponent (Str,
- Ptr,
- Max,
- Real => True);
-
- Uval := Uval * Long_Long_Float (Base) ** Int_Scale;
-
- -- Here is where we check for a bad based number
- if Base_Violation then
- Bad_Value (Str);
-
- -- If OK, then deal with initial minus sign, note that this processing
- -- is done even if Uval is zero, so that -0.0 is correctly interpreted.
- else
- if Minus then
- return -Uval;
- else
- return Uval;
- end if;
- end if;
+ begin
+ Val := Impl.Scan_Raw_Real (Str, Ptr, Max, Base, Scale, Extra, Minus);
+ return Integer_to_Real (Str, Val, Base, Scale, Extra, Minus);
end Scan_Real;
----------------
-- Value_Real --
----------------
- function Value_Real (Str : String) return Long_Long_Float is
+ function Value_Real (Str : String) return Num is
+ Base : Unsigned;
+ Scale : Integer;
+ Extra : Unsigned;
+ Minus : Boolean;
+ Val : Uns;
+
begin
- -- We have to special case Str'Last = Positive'Last because the normal
- -- circuit ends up setting P to Str'Last + 1 which is out of bounds. We
- -- deal with this by converting to a subtype which fixes the bounds.
-
- if Str'Last = Positive'Last then
- declare
- subtype NT is String (1 .. Str'Length);
- begin
- return Value_Real (NT (Str));
- end;
-
- -- Normal case where Str'Last < Positive'Last
-
- else
- declare
- V : Long_Long_Float;
- P : aliased Integer := Str'First;
- begin
- V := Scan_Real (Str, P'Access, Str'Last);
- Scan_Trailing_Blanks (Str, P);
- return V;
- end;
- end if;
+ Val := Impl.Value_Raw_Real (Str, Base, Scale, Extra, Minus);
+
+ return Integer_to_Real (Str, Val, Base, Scale, Extra, Minus);
end Value_Real;
end System.Val_Real;
diff --git a/gcc/ada/libgnat/s-valrea.ads b/gcc/ada/libgnat/s-valrea.ads
index cb5374c..d6ade80 100644
--- a/gcc/ada/libgnat/s-valrea.ads
+++ b/gcc/ada/libgnat/s-valrea.ads
@@ -29,13 +29,26 @@
-- --
------------------------------------------------------------------------------
+-- This package contains routines for scanning real values for use in
+-- Text_IO.Float_IO and the Value attribute.
+
+generic
+
+ type Num is digits <>;
+
+ type Uns is mod <>;
+
+ Maxpow : Positive;
+
+ Powten_Address : System.Address;
+
package System.Val_Real is
pragma Preelaborate;
function Scan_Real
(Str : String;
Ptr : not null access Integer;
- Max : Integer) return Long_Long_Float;
+ Max : Integer) return Num;
-- This function scans the string starting at Str (Ptr.all) for a valid
-- real literal according to the syntax described in (RM 3.5(43)). The
-- substring scanned extends no further than Str (Max). There are three
@@ -65,10 +78,10 @@ package System.Val_Real is
-- If this occurs Program_Error is raised with a message noting that this
-- case is not supported. Most such cases are eliminated by the caller.
- function Value_Real (Str : String) return Long_Long_Float;
+ function Value_Real (Str : String) return Num;
-- Used in computing X'Value (Str) where X is a floating-point type or an
-- ordinary fixed-point type. Str is the string argument of the attribute.
-- Constraint_Error is raised if the string is malformed, or if the value
- -- out of range of Long_Long_Float.
+ -- out of range of Num.
end System.Val_Real;
diff --git a/gcc/ada/libgnat/s-valued.adb b/gcc/ada/libgnat/s-valued.adb
new file mode 100644
index 0000000..8930752
--- /dev/null
+++ b/gcc/ada/libgnat/s-valued.adb
@@ -0,0 +1,263 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L U E _ D --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Unsigned_Types; use System.Unsigned_Types;
+with System.Val_Util; use System.Val_Util;
+with System.Value_R;
+
+package body System.Value_D is
+
+ pragma Assert (Int'Size <= Uns'Size);
+ -- We need an unsigned type large enough to represent the mantissa
+
+ package Impl is new Value_R (Uns, 2**(Int'Size - 1), Round => False);
+ -- We do not use the Extra digit for decimal fixed-point types
+
+ function Integer_to_Decimal
+ (Str : String;
+ Val : Uns;
+ Base : Unsigned;
+ ScaleB : Integer;
+ Minus : Boolean;
+ Scale : Integer) return Int;
+ -- Convert the real value from integer to decimal representation
+
+ ------------------------
+ -- Integer_to_Decimal --
+ ------------------------
+
+ function Integer_to_Decimal
+ (Str : String;
+ Val : Uns;
+ Base : Unsigned;
+ ScaleB : Integer;
+ Minus : Boolean;
+ Scale : Integer) return Int
+ is
+ function Safe_Expont
+ (Base : Int;
+ Exp : in out Natural;
+ Factor : Int) return Int;
+ -- Return (Base ** Exp) * Factor if the computation does not overflow,
+ -- or else the number of the form (Base ** K) * Factor with the largest
+ -- magnitude if the former computation overflows. In both cases, Exp is
+ -- updated to contain the remaining power in the computation. Note that
+ -- Factor is expected to be positive in this context.
+
+ function Unsigned_To_Signed (Val : Uns) return Int;
+ -- Convert an integer value from unsigned to signed representation
+
+ -----------------
+ -- Safe_Expont --
+ -----------------
+
+ function Safe_Expont
+ (Base : Int;
+ Exp : in out Natural;
+ Factor : Int) return Int
+ is
+ pragma Assert (Base /= 0 and then Factor > 0);
+
+ Max : constant Int := Int'Last / Base;
+
+ Result : Int := Factor;
+
+ begin
+ while Exp > 0 and then Result <= Max loop
+ Result := Result * Base;
+ Exp := Exp - 1;
+ end loop;
+
+ return Result;
+ end Safe_Expont;
+
+ ------------------------
+ -- Unsigned_To_Signed --
+ ------------------------
+
+ function Unsigned_To_Signed (Val : Uns) return Int is
+ begin
+ -- Deal with overflow cases, and also with largest negative number
+
+ if Val > Uns (Int'Last) then
+ if Minus and then Val = Uns (-(Int'First)) then
+ return Int'First;
+ else
+ Bad_Value (Str);
+ end if;
+
+ -- Negative values
+
+ elsif Minus then
+ return -(Int (Val));
+
+ -- Positive values
+
+ else
+ return Int (Val);
+ end if;
+ end Unsigned_To_Signed;
+
+ begin
+ -- If the base of the value is 10 or its scaling factor is zero, then
+ -- add the scales (they are defined in the opposite sense) and apply
+ -- the result to the value, checking for overflow in the process.
+
+ if Base = 10 or else ScaleB = 0 then
+ declare
+ S : Integer := ScaleB + Scale;
+ V : Uns := Val;
+
+ begin
+ while S < 0 loop
+ V := V / 10;
+ S := S + 1;
+ end loop;
+
+ while S > 0 loop
+ if V <= Uns'Last / 10 then
+ V := V * 10;
+ S := S - 1;
+ else
+ Bad_Value (Str);
+ end if;
+ end loop;
+
+ return Unsigned_To_Signed (V);
+ end;
+
+ -- If the base of the value is not 10, use a scaled divide operation
+ -- to compute Val * (Base ** ScaleB) * (10 ** Scale).
+
+ else
+ declare
+ B : constant Int := Int (Base);
+ S : constant Integer := ScaleB;
+
+ V : Uns := Val;
+
+ Y, Z, Q, R : Int;
+
+ begin
+ -- If S is too negative, then drop trailing digits
+
+ if S < 0 then
+ declare
+ LS : Integer := -S;
+
+ begin
+ Y := 10 ** Integer'Max (0, Scale);
+ Z := Safe_Expont (B, LS, 10 ** Integer'Max (0, -Scale));
+
+ for J in 1 .. LS loop
+ V := V / Uns (B);
+ end loop;
+ end;
+
+ -- If S is too positive, then scale V up, which may then overflow
+
+ elsif S > 0 then
+ declare
+ LS : Integer := S;
+
+ begin
+ Y := Safe_Expont (B, LS, 10 ** Integer'Max (0, Scale));
+ Z := 10 ** Integer'Max (0, -Scale);
+
+ for J in 1 .. LS loop
+ if V <= Uns'Last / Uns (B) then
+ V := V * Uns (B);
+ else
+ Bad_Value (Str);
+ end if;
+ end loop;
+ end;
+
+ -- The case S equal to zero should have been handled earlier
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Perform a scale divide operation with rounding to match 'Image
+
+ Scaled_Divide (Unsigned_To_Signed (V), Y, Z, Q, R, Round => True);
+
+ return Q;
+ end;
+ end if;
+
+ exception
+ when Constraint_Error => Bad_Value (Str);
+ end Integer_to_Decimal;
+
+ ------------------
+ -- Scan_Decimal --
+ ------------------
+
+ function Scan_Decimal
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int
+ is
+ Base : Unsigned;
+ ScaleB : Integer;
+ Extra : Unsigned;
+ pragma Unreferenced (Extra);
+ Minus : Boolean;
+ Val : Uns;
+
+ begin
+ Val := Impl.Scan_Raw_Real (Str, Ptr, Max, Base, ScaleB, Extra, Minus);
+
+ return Integer_to_Decimal (Str, Val, Base, ScaleB, Minus, Scale);
+ end Scan_Decimal;
+
+ -------------------
+ -- Value_Decimal --
+ -------------------
+
+ function Value_Decimal (Str : String; Scale : Integer) return Int is
+ Base : Unsigned;
+ ScaleB : Integer;
+ Extra : Unsigned;
+ pragma Unreferenced (Extra);
+ Minus : Boolean;
+ Val : Uns;
+
+ begin
+ Val := Impl.Value_Raw_Real (Str, Base, ScaleB, Extra, Minus);
+
+ return Integer_to_Decimal (Str, Val, Base, ScaleB, Minus, Scale);
+ end Value_Decimal;
+
+end System.Value_D;
diff --git a/gcc/ada/libgnat/s-valued.ads b/gcc/ada/libgnat/s-valued.ads
new file mode 100644
index 0000000..e27e171
--- /dev/null
+++ b/gcc/ada/libgnat/s-valued.ads
@@ -0,0 +1,90 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L U E _ D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Value attribute for
+-- decimal fixed point types, and also for conversion operations required in
+-- Text_IO.Decimal_IO for such types.
+
+generic
+
+ type Int is range <>;
+
+ type Uns is mod <>;
+
+ with procedure Scaled_Divide
+ (X, Y, Z : Int;
+ Q, R : out Int;
+ Round : Boolean);
+
+package System.Value_D is
+ pragma Preelaborate;
+
+ function Scan_Decimal
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Scale : Integer) return Int;
+ -- This function scans the string starting at Str (Ptr.all) for a valid
+ -- real literal according to the syntax described in (RM 3.5(43)). The
+ -- substring scanned extends no further than Str (Max). There are three
+ -- cases for the return:
+ --
+ -- If a valid real literal is found after scanning past any initial spaces,
+ -- then Ptr.all is updated past the last character of the literal (but
+ -- trailing spaces are not scanned out). The value returned is the value
+ -- Int'Integer_Value (decimal-literal-value), using the given Scale to
+ -- determine this value.
+ --
+ -- If no valid real literal is found, then Ptr.all points either to an
+ -- initial non-digit character, or to Max + 1 if the field is all spaces
+ -- and the exception Constraint_Error is raised.
+ --
+ -- If a syntactically valid integer is scanned, but the value is out of
+ -- range, or, in the based case, the base value is out of range or there
+ -- is an out of range digit, then Ptr.all points past the integer, and
+ -- Constraint_Error is raised.
+ --
+ -- Note: these rules correspond to the requirements for leaving the
+ -- pointer positioned in Text_Io.Get
+ --
+ -- Note: if Str is null, i.e. if Max is less than Ptr, then this is a
+ -- special case of an all-blank string, and Ptr is unchanged, and hence
+ -- is greater than Max as required in this case.
+
+ function Value_Decimal (Str : String; Scale : Integer) return Int;
+ -- Used in computing X'Value (Str) where X is a decimal fixed-point type.
+ -- Str is the string argument of the attribute. Constraint_Error is raised
+ -- if the string is malformed or if the value is out of range of Int (not
+ -- the range of the fixed-point type, which must be done by the caller).
+ -- Otherwise the value returned is the value Int'Integer_Value
+ -- (decimal-literal-value), using Scale to determine this value.
+
+end System.Value_D;
diff --git a/gcc/ada/libgnat/s-valuef.adb b/gcc/ada/libgnat/s-valuef.adb
new file mode 100644
index 0000000..d13111a
--- /dev/null
+++ b/gcc/ada/libgnat/s-valuef.adb
@@ -0,0 +1,368 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L U E _ F --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Unsigned_Types; use System.Unsigned_Types;
+with System.Val_Util; use System.Val_Util;
+with System.Value_R;
+
+package body System.Value_F is
+
+ -- The prerequisite of the implementation is that the computation of the
+ -- operands of the scaled divide does not unduly overflow when the small
+ -- is neither an integer nor the reciprocal of an integer, which means
+ -- that its numerator and denominator must be both not larger than the
+ -- smallest divide 2**(Int'Size - 1) / Base where Base ranges over the
+ -- supported values for the base of the literal. Given that the largest
+ -- supported base is 16, this gives a limit of 2**(Int'Size - 5).
+
+ pragma Assert (Int'Size <= Uns'Size);
+ -- We need an unsigned type large enough to represent the mantissa
+
+ package Impl is new Value_R (Uns, 2**(Int'Size - 1), Round => True);
+ -- We use the Extra digit for ordinary fixed-point types
+
+ function Integer_To_Fixed
+ (Str : String;
+ Val : Uns;
+ Base : Unsigned;
+ ScaleB : Integer;
+ Extra : Unsigned;
+ Minus : Boolean;
+ Num : Int;
+ Den : Int) return Int;
+ -- Convert the real value from integer to fixed point representation
+
+ -- The goal is to compute Val * (Base ** ScaleB) / (Num / Den) with correct
+ -- rounding for all decimal values output by Typ'Image, that is to say up
+ -- to Typ'Aft decimal digits. Unlike for the output, the RM does not say
+ -- what the rounding must be for the input, but a reasonable exegesis of
+ -- the intent is that Typ'Value o Typ'Image should be the identity, which
+ -- is made possible because 'Aft is defined such that 'Image is injective.
+
+ -- For a type with a mantissa of M bits including the sign, the number N1
+ -- of decimal digits required to represent all the numbers is given by:
+
+ -- N1 = ceil ((M - 1) * log 2 / log 10) [N1 = 10/19/39 for M = 32/64/128]
+
+ -- but this mantissa can represent any set of contiguous numbers with only
+ -- N2 different decimal digits where:
+
+ -- N2 = floor ((M - 1) * log 2 / log 10) [N2 = 9/18/38 for M = 32/64/128]
+
+ -- Of course N1 = N2 + 1 holds, which means both that Val may not contain
+ -- enough significant bits to represent all the values of the type and that
+ -- 1 extra decimal digit contains the information for the missing bits.
+
+ -- Therefore the actual computation to be performed is
+
+ -- V = (Val * Base + Extra) * (Base ** (ScaleB - 1)) / (Num / Den)
+
+ -- using two steps of scaled divide if Extra is positive and ScaleB too
+
+ -- (1) Val * (Den * (Base ** ScaleB)) = Q1 * Num + R1
+
+ -- (2) Extra * (Den * (Base ** ScaleB)) = Q2 * -Base + R2
+
+ -- which yields after dividing (1) by Num and (2) by Num * Base and summing
+
+ -- V = Q1 + (R1 - Q2) / Num + R2 / (Num * Base)
+
+ -- but we get rid of the third term by using a rounding divide for (2).
+
+ -- This works only if Den * (Base ** ScaleB) does not overflow for inputs
+ -- corresponding to 'Image. Let S = Num / Den, B = Base and N the scale in
+ -- base B of S, i.e. the smallest integer such that B**N * S >= 1. Then,
+ -- for X a positive of the mantissa, i.e. 1 <= X <= 2**(M-1), we have
+
+ -- 1/B <= X * S * B**(N-1) < 2**(M-1)
+
+ -- which means that the inputs corresponding to the output of 'Image have a
+ -- ScaleB equal either to 1 - N or (after multiplying the inequality by B)
+ -- to -N, possibly after renormalizing X, i.e. multiplying it by a suitable
+ -- power of B. Therefore
+
+ -- Den * (Base ** ScaleB) <= Den * (B ** (1 - N)) < Num * B
+
+ -- which means that the product does not overflow if Num <= 2**(M-1) / B.
+
+ -- On the other hand, if Extra is positive and ScaleB negative, the above
+ -- two steps are
+
+ -- (1b) Val * Den = Q1 * (Num * (Base ** -ScaleB)) + R1
+
+ -- (2b) Extra * Den = Q2 * -Base + R2
+
+ -- which yields after dividing (1b) by Num * (Base ** -ScaleB) and (2b) by
+ -- Num * (Base ** (1 - ScaleB)) and summing
+
+ -- V = Q1 + (R1 - Q2) / (Num * (Base ** -ScaleB)) + R2 / ...
+
+ -- but we get rid of the third term by using a rounding divide for (2b).
+
+ -- This works only if Num * (Base ** -ScaleB) does not overflow for inputs
+ -- corresponding to 'Image. With the determination of ScaleB above, we have
+
+ -- Num * (Base ** -ScaleB) <= Num * (B ** N) < Den * B
+
+ -- which means that the product does not overflow if Den <= 2**(M-1) / B.
+
+ ----------------------
+ -- Integer_To_Fixed --
+ ----------------------
+
+ function Integer_To_Fixed
+ (Str : String;
+ Val : Uns;
+ Base : Unsigned;
+ ScaleB : Integer;
+ Extra : Unsigned;
+ Minus : Boolean;
+ Num : Int;
+ Den : Int) return Int
+ is
+ pragma Assert (Base in 2 .. 16);
+
+ pragma Assert (Extra < Base);
+ -- Accept only one extra digit after those used for Val
+
+ pragma Assert (Num < 0 and then Den < 0);
+ -- Accept only negative numbers to allow -2**(Int'Size - 1)
+
+ function Safe_Expont
+ (Base : Int;
+ Exp : in out Natural;
+ Factor : Int) return Int;
+ -- Return (Base ** Exp) * Factor if the computation does not overflow,
+ -- or else the number of the form (Base ** K) * Factor with the largest
+ -- magnitude if the former computation overflows. In both cases, Exp is
+ -- updated to contain the remaining power in the computation. Note that
+ -- Factor is expected to be negative in this context.
+
+ function Unsigned_To_Signed (Val : Uns) return Int;
+ -- Convert an integer value from unsigned to signed representation
+
+ -----------------
+ -- Safe_Expont --
+ -----------------
+
+ function Safe_Expont
+ (Base : Int;
+ Exp : in out Natural;
+ Factor : Int) return Int
+ is
+ pragma Assert (Base /= 0 and then Factor < 0);
+
+ Min : constant Int := Int'First / Base;
+
+ Result : Int := Factor;
+
+ begin
+ while Exp > 0 and then Result >= Min loop
+ Result := Result * Base;
+ Exp := Exp - 1;
+ end loop;
+
+ return Result;
+ end Safe_Expont;
+
+ ------------------------
+ -- Unsigned_To_Signed --
+ ------------------------
+
+ function Unsigned_To_Signed (Val : Uns) return Int is
+ begin
+ -- Deal with overflow cases, and also with largest negative number
+
+ if Val > Uns (Int'Last) then
+ if Minus and then Val = Uns (-(Int'First)) then
+ return Int'First;
+ else
+ Bad_Value (Str);
+ end if;
+
+ -- Negative values
+
+ elsif Minus then
+ return -(Int (Val));
+
+ -- Positive values
+
+ else
+ return Int (Val);
+ end if;
+ end Unsigned_To_Signed;
+
+ -- Local variables
+
+ B : constant Int := Int (Base);
+
+ V : Uns := Val;
+ E : Uns := Uns (Extra);
+
+ Y, Z, Q1, R1, Q2, R2 : Int;
+
+ begin
+ -- We will use a scaled divide operation for which we must control the
+ -- magnitude of operands so that an overflow exception is not unduly
+ -- raised during the computation. The only real concern is the exponent.
+
+ -- If ScaleB is too negative, then drop trailing digits, but preserve
+ -- the last dropped digit.
+
+ if ScaleB < 0 then
+ declare
+ LS : Integer := -ScaleB;
+
+ begin
+ Y := Den;
+ Z := Safe_Expont (B, LS, Num);
+
+ for J in 1 .. LS loop
+ E := V rem Uns (B);
+ V := V / Uns (B);
+ end loop;
+ end;
+
+ -- If ScaleB is too positive, then scale V up, which may then overflow
+
+ elsif ScaleB > 0 then
+ declare
+ LS : Integer := ScaleB;
+
+ begin
+ Y := Safe_Expont (B, LS, Den);
+ Z := Num;
+
+ for J in 1 .. LS loop
+ if V <= (Uns'Last - E) / Uns (B) then
+ V := V * Uns (B) + E;
+ E := 0;
+ else
+ Bad_Value (Str);
+ end if;
+ end loop;
+ end;
+
+ -- If ScaleB is zero, then proceed directly
+
+ else
+ Y := Den;
+ Z := Num;
+ end if;
+
+ -- Perform a scaled divide operation with final rounding to match Image
+ -- using two steps if there is an extra digit available. The second and
+ -- third operands are always negative so the sign of the quotient is the
+ -- sign of the first operand and the sign of the remainder the opposite.
+
+ if E > 0 then
+ Scaled_Divide (Unsigned_To_Signed (V), Y, Z, Q1, R1, Round => False);
+ Scaled_Divide (Unsigned_To_Signed (E), Y, -B, Q2, R2, Round => True);
+
+ -- Avoid an overflow during the subtraction. Note that Q2 is smaller
+ -- than Y and R1 smaller than Z in magnitude, so it is safe to take
+ -- their absolute value.
+
+ if abs Q2 >= 2 ** (Int'Size - 2)
+ or else abs R1 >= 2 ** (Int'Size - 2)
+ then
+ declare
+ Bit : constant Int := Q2 rem 2;
+
+ begin
+ Q2 := (Q2 - Bit) / 2;
+ R1 := (R1 - Bit) / 2;
+ Y := -2;
+ end;
+
+ else
+ Y := -1;
+ end if;
+
+ Scaled_Divide (Q2 - R1, Y, Z, Q2, R2, Round => True);
+
+ return Q1 + Q2;
+
+ else
+ Scaled_Divide (Unsigned_To_Signed (V), Y, Z, Q1, R1, Round => True);
+
+ return Q1;
+ end if;
+
+ exception
+ when Constraint_Error => Bad_Value (Str);
+ end Integer_To_Fixed;
+
+ ----------------
+ -- Scan_Fixed --
+ ----------------
+
+ function Scan_Fixed
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Base : Unsigned;
+ ScaleB : Integer;
+ Extra : Unsigned;
+ Minus : Boolean;
+ Val : Uns;
+
+ begin
+ Val := Impl.Scan_Raw_Real (Str, Ptr, Max, Base, ScaleB, Extra, Minus);
+
+ return Integer_To_Fixed (Str, Val, Base, ScaleB, Extra, Minus, Num, Den);
+ end Scan_Fixed;
+
+ -----------------
+ -- Value_Fixed --
+ -----------------
+
+ function Value_Fixed
+ (Str : String;
+ Num : Int;
+ Den : Int) return Int
+ is
+ Base : Unsigned;
+ ScaleB : Integer;
+ Extra : Unsigned;
+ Minus : Boolean;
+ Val : Uns;
+
+ begin
+ Val := Impl.Value_Raw_Real (Str, Base, ScaleB, Extra, Minus);
+
+ return Integer_To_Fixed (Str, Val, Base, ScaleB, Extra, Minus, Num, Den);
+ end Value_Fixed;
+
+end System.Value_F;
diff --git a/gcc/ada/libgnat/s-valuef.ads b/gcc/ada/libgnat/s-valuef.ads
new file mode 100644
index 0000000..abd4817
--- /dev/null
+++ b/gcc/ada/libgnat/s-valuef.ads
@@ -0,0 +1,94 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L U E _ F --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains the routines for supporting the Value attribute for
+-- ordinary fixed point types whose Small is the ratio of two Int values, and
+-- also for conversion operations required in Text_IO.Fixed_IO for such types.
+
+generic
+
+ type Int is range <>;
+
+ type Uns is mod <>;
+
+ with procedure Scaled_Divide
+ (X, Y, Z : Int;
+ Q, R : out Int;
+ Round : Boolean);
+
+package System.Value_F is
+ pragma Preelaborate;
+
+ function Scan_Fixed
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Num : Int;
+ Den : Int) return Int;
+ -- This function scans the string starting at Str (Ptr.all) for a valid
+ -- real literal according to the syntax described in (RM 3.5(43)). The
+ -- substring scanned extends no further than Str (Max). There are three
+ -- cases for the return:
+ --
+ -- If a valid real literal is found after scanning past any initial spaces,
+ -- then Ptr.all is updated past the last character of the literal (but
+ -- trailing spaces are not scanned out). The value returned is the value
+ -- Int'Integer_Value (decimal-literal-value), using the given Num/Den to
+ -- determine this value.
+ --
+ -- If no valid real literal is found, then Ptr.all points either to an
+ -- initial non-digit character, or to Max + 1 if the field is all spaces
+ -- and the exception Constraint_Error is raised.
+ --
+ -- If a syntactically valid integer is scanned, but the value is out of
+ -- range, or, in the based case, the base value is out of range or there
+ -- is an out of range digit, then Ptr.all points past the integer, and
+ -- Constraint_Error is raised.
+ --
+ -- Note: these rules correspond to the requirements for leaving the
+ -- pointer positioned in Text_Io.Get
+ --
+ -- Note: if Str is null, i.e. if Max is less than Ptr, then this is a
+ -- special case of an all-blank string, and Ptr is unchanged, and hence
+ -- is greater than Max as required in this case.
+
+ function Value_Fixed
+ (Str : String;
+ Num : Int;
+ Den : Int) return Int;
+ -- Used in computing X'Value (Str) where X is an ordinary fixed-point type.
+ -- Str is the string argument of the attribute. Constraint_Error is raised
+ -- if the string is malformed or if the value is out of range of Int (not
+ -- the range of the fixed-point type, which must be done by the caller).
+ -- Otherwise the value returned is the value Int'Integer_Value
+ -- (decimal-literal-value), using Small Num/Den to determine this value.
+
+end System.Value_F;
diff --git a/gcc/ada/libgnat/s-valuei.adb b/gcc/ada/libgnat/s-valuei.adb
index 1bc8b32..ac5a776 100644
--- a/gcc/ada/libgnat/s-valuei.adb
+++ b/gcc/ada/libgnat/s-valuei.adb
@@ -61,7 +61,7 @@ package body System.Value_I is
Uval := Scan_Raw_Unsigned (Str, Ptr, Max);
- -- Deal with overflow cases, and also with maximum negative number
+ -- Deal with overflow cases, and also with largest negative number
if Uval > Uns (Int'Last) then
if Minus and then Uval = Uns (-(Int'First)) then
diff --git a/gcc/ada/libgnat/s-valuer.adb b/gcc/ada/libgnat/s-valuer.adb
new file mode 100644
index 0000000..9e4de3e
--- /dev/null
+++ b/gcc/ada/libgnat/s-valuer.adb
@@ -0,0 +1,685 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L U E _ R --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Val_Util; use System.Val_Util;
+
+package body System.Value_R is
+
+ subtype Char_As_Digit is Unsigned range 0 .. 17;
+ subtype Valid_Digit is Char_As_Digit range 0 .. 15;
+ E_Digit : constant Char_As_Digit := 14;
+ Underscore : constant Char_As_Digit := 16;
+ Not_A_Digit : constant Char_As_Digit := 17;
+
+ function As_Digit (C : Character) return Char_As_Digit;
+ -- Given a character return the digit it represents
+
+ procedure Round_Extra
+ (Digit : Char_As_Digit;
+ Value : in out Uns;
+ Scale : in out Integer;
+ Extra : in out Char_As_Digit;
+ Base : Unsigned);
+ -- Round the triplet (Value, Scale, Extra) according to Digit in Base
+
+ procedure Scan_Decimal_Digits
+ (Str : String;
+ Index : in out Integer;
+ Max : Integer;
+ Value : in out Uns;
+ Scale : in out Integer;
+ Extra : in out Char_As_Digit;
+ Base_Violation : in out Boolean;
+ Base : Unsigned;
+ Base_Specified : Boolean);
+ -- Scan the decimal part of a real (i.e. after decimal separator)
+ --
+ -- The string parsed is Str (Index .. Max) and after the call Index will
+ -- point to the first non-parsed character.
+ --
+ -- For each digit parsed, Value = Value * Base + Digit and Scale is
+ -- decremented by 1. If precision limit is reached, remaining digits are
+ -- still parsed but ignored, except for the first which is stored in Extra.
+ --
+ -- Base_Violation is set to True if a digit found is not part of the Base
+ --
+ -- If Base_Specified is set, then the base was specified in the real
+
+ procedure Scan_Integral_Digits
+ (Str : String;
+ Index : in out Integer;
+ Max : Integer;
+ Value : out Uns;
+ Scale : out Integer;
+ Extra : out Char_As_Digit;
+ Base_Violation : in out Boolean;
+ Base : Unsigned;
+ Base_Specified : Boolean);
+ -- Scan the integral part of a real (i.e. before decimal separator)
+ --
+ -- The string parsed is Str (Index .. Max) and after the call Index will
+ -- point to the first non-parsed character.
+ --
+ -- For each digit parsed, either Value := Value * Base + Digit or Scale
+ -- is incremented by 1 if precision limit is reached, in which case the
+ -- remaining digits are still parsed but ignored, except for the first
+ -- which is stored in Extra.
+ --
+ -- Base_Violation is set to True if a digit found is not part of the Base
+ --
+ -- If Base_Specified is set, then the base was specified in the real
+
+ --------------
+ -- As_Digit --
+ --------------
+
+ function As_Digit (C : Character) return Char_As_Digit is
+ begin
+ case C is
+ when '0' .. '9' =>
+ return Character'Pos (C) - Character'Pos ('0');
+ when 'a' .. 'f' =>
+ return Character'Pos (C) - (Character'Pos ('a') - 10);
+ when 'A' .. 'F' =>
+ return Character'Pos (C) - (Character'Pos ('A') - 10);
+ when '_' =>
+ return Underscore;
+ when others =>
+ return Not_A_Digit;
+ end case;
+ end As_Digit;
+
+ -----------------
+ -- Round_Extra --
+ -----------------
+
+ procedure Round_Extra
+ (Digit : Char_As_Digit;
+ Value : in out Uns;
+ Scale : in out Integer;
+ Extra : in out Char_As_Digit;
+ Base : Unsigned)
+ is
+ B : constant Uns := Uns (Base);
+
+ begin
+ if Digit >= Base / 2 then
+
+ -- If Extra is maximum, round Value
+
+ if Extra = Base - 1 then
+
+ -- If Value is maximum, scale it up
+
+ if Value = Precision_Limit then
+ Extra := Char_As_Digit (Value mod B);
+ Value := Value / B;
+ Scale := Scale + 1;
+ Round_Extra (Digit, Value, Scale, Extra, Base);
+
+ else
+ Extra := 0;
+ Value := Value + 1;
+ end if;
+
+ else
+ Extra := Extra + 1;
+ end if;
+ end if;
+ end Round_Extra;
+
+ -------------------------
+ -- Scan_Decimal_Digits --
+ -------------------------
+
+ procedure Scan_Decimal_Digits
+ (Str : String;
+ Index : in out Integer;
+ Max : Integer;
+ Value : in out Uns;
+ Scale : in out Integer;
+ Extra : in out Char_As_Digit;
+ Base_Violation : in out Boolean;
+ Base : Unsigned;
+ Base_Specified : Boolean)
+
+ is
+ pragma Assert (Base in 2 .. 16);
+ pragma Assert (Index in Str'Range);
+ pragma Assert (Max <= Str'Last);
+
+ Umax : constant Uns := (Precision_Limit - Uns (Base) + 1) / Uns (Base);
+ -- Max value which cannot overflow on accumulating next digit
+
+ UmaxB : constant Uns := Precision_Limit / Uns (Base);
+ -- Numbers bigger than UmaxB overflow if multiplied by base
+
+ Precision_Limit_Reached : Boolean := False;
+ -- Set to True if addition of a digit will cause Value to be superior
+ -- to Precision_Limit.
+
+ Precision_Limit_Just_Reached : Boolean;
+ -- Set to True if Precision_Limit_Reached was just set to True, but only
+ -- used when Round is True.
+
+ Digit : Char_As_Digit;
+ -- The current digit
+
+ Temp : Uns;
+ -- Temporary
+
+ Trailing_Zeros : Natural := 0;
+ -- Number of trailing zeros at a given point
+
+ begin
+ -- If initial Scale is not 0 then it means that Precision_Limit was
+ -- reached during scanning of the integral part.
+
+ if Scale > 0 then
+ Precision_Limit_Reached := True;
+ else
+ Extra := 0;
+ end if;
+
+ if Round then
+ Precision_Limit_Just_Reached := False;
+ end if;
+
+ -- The function precondition is that the first character is a valid
+ -- digit.
+
+ Digit := As_Digit (Str (Index));
+
+ loop
+ -- Check if base is correct. If the base is not specified, the digit
+ -- E or e cannot be considered as a base violation as it can be used
+ -- for exponentiation.
+
+ if Digit >= Base then
+ if Base_Specified then
+ Base_Violation := True;
+ elsif Digit = E_Digit then
+ return;
+ else
+ Base_Violation := True;
+ end if;
+ end if;
+
+ -- If precision limit has been reached, just ignore any remaining
+ -- digits for the computation of Value and Scale, but store the
+ -- first in Extra and use the second to round Extra. The scanning
+ -- should continue only to assess the validity of the string.
+
+ if Precision_Limit_Reached then
+ if Round and then Precision_Limit_Just_Reached then
+ Round_Extra (Digit, Value, Scale, Extra, Base);
+ Precision_Limit_Just_Reached := False;
+ end if;
+
+ else
+ -- Trailing '0' digits are ignored until a non-zero digit is found
+
+ if Digit = 0 then
+ Trailing_Zeros := Trailing_Zeros + 1;
+
+ else
+ -- Handle accumulated zeros.
+
+ for J in 1 .. Trailing_Zeros loop
+ if Value <= UmaxB then
+ Value := Value * Uns (Base);
+ Scale := Scale - 1;
+
+ else
+ Precision_Limit_Reached := True;
+ exit;
+ end if;
+ end loop;
+
+ -- Reset trailing zero counter
+
+ Trailing_Zeros := 0;
+
+ -- Handle current non zero digit
+
+ Temp := Value * Uns (Base) + Uns (Digit);
+
+ -- Check if Temp is larger than Precision_Limit, taking into
+ -- account that Temp may wrap around when Precision_Limit is
+ -- equal to the largest integer.
+
+ if Value <= Umax
+ or else (Value <= UmaxB
+ and then ((Precision_Limit < Uns'Last
+ and then Temp <= Precision_Limit)
+ or else (Precision_Limit = Uns'Last
+ and then Temp >= Uns (Base))))
+ then
+ Value := Temp;
+ Scale := Scale - 1;
+
+ else
+ Extra := Digit;
+ Precision_Limit_Reached := True;
+ if Round then
+ Precision_Limit_Just_Reached := True;
+ end if;
+ end if;
+ end if;
+ end if;
+
+ -- Check next character
+
+ Index := Index + 1;
+
+ if Index > Max then
+ return;
+ end if;
+
+ Digit := As_Digit (Str (Index));
+
+ if Digit not in Valid_Digit then
+
+ -- Underscore is only allowed if followed by a digit
+
+ if Digit = Underscore and Index + 1 <= Max then
+
+ Digit := As_Digit (Str (Index + 1));
+ if Digit in Valid_Digit then
+ Index := Index + 1;
+ else
+ return;
+ end if;
+
+ -- Neither a valid underscore nor a digit
+
+ else
+ return;
+ end if;
+ end if;
+ end loop;
+ end Scan_Decimal_Digits;
+
+ --------------------------
+ -- Scan_Integral_Digits --
+ --------------------------
+
+ procedure Scan_Integral_Digits
+ (Str : String;
+ Index : in out Integer;
+ Max : Integer;
+ Value : out Uns;
+ Scale : out Integer;
+ Extra : out Char_As_Digit;
+ Base_Violation : in out Boolean;
+ Base : Unsigned;
+ Base_Specified : Boolean)
+ is
+ pragma Assert (Base in 2 .. 16);
+
+ Umax : constant Uns := (Precision_Limit - Uns (Base) + 1) / Uns (Base);
+ -- Max value which cannot overflow on accumulating next digit
+
+ UmaxB : constant Uns := Precision_Limit / Uns (Base);
+ -- Numbers bigger than UmaxB overflow if multiplied by base
+
+ Precision_Limit_Reached : Boolean := False;
+ -- Set to True if addition of a digit will cause Value to be superior
+ -- to Precision_Limit.
+
+ Precision_Limit_Just_Reached : Boolean;
+ -- Set to True if Precision_Limit_Reached was just set to True, but only
+ -- used when Round is True.
+
+ Digit : Char_As_Digit;
+ -- The current digit
+
+ Temp : Uns;
+ -- Temporary
+
+ begin
+ -- Initialize Value, Scale and Extra
+
+ Value := 0;
+ Scale := 0;
+ Extra := 0;
+
+ if Round then
+ Precision_Limit_Just_Reached := False;
+ end if;
+
+ pragma Assert (Max <= Str'Last);
+
+ -- The function precondition is that the first character is a valid
+ -- digit.
+
+ Digit := As_Digit (Str (Index));
+
+ loop
+ -- Check if base is correct. If the base is not specified, the digit
+ -- E or e cannot be considered as a base violation as it can be used
+ -- for exponentiation.
+
+ if Digit >= Base then
+ if Base_Specified then
+ Base_Violation := True;
+ elsif Digit = E_Digit then
+ return;
+ else
+ Base_Violation := True;
+ end if;
+ end if;
+
+ -- If precision limit has been reached, just ignore any remaining
+ -- digits for the computation of Value and Scale, but store the
+ -- first in Extra and use the second to round Extra. The scanning
+ -- should continue only to assess the validity of the string.
+
+ if Precision_Limit_Reached then
+ Scale := Scale + 1;
+
+ if Round and then Precision_Limit_Just_Reached then
+ Round_Extra (Digit, Value, Scale, Extra, Base);
+ Precision_Limit_Just_Reached := False;
+ end if;
+
+ else
+ Temp := Value * Uns (Base) + Uns (Digit);
+
+ -- Check if Temp is larger than Precision_Limit, taking into
+ -- account that Temp may wrap around when Precision_Limit is
+ -- equal to the largest integer.
+
+ if Value <= Umax
+ or else (Value <= UmaxB
+ and then ((Precision_Limit < Uns'Last
+ and then Temp <= Precision_Limit)
+ or else (Precision_Limit = Uns'Last
+ and then Temp >= Uns (Base))))
+ then
+ Value := Temp;
+
+ else
+ Extra := Digit;
+ Precision_Limit_Reached := True;
+ if Round then
+ Precision_Limit_Just_Reached := True;
+ end if;
+ Scale := Scale + 1;
+ end if;
+ end if;
+
+ -- Look for the next character
+
+ Index := Index + 1;
+ if Index > Max then
+ return;
+ end if;
+
+ Digit := As_Digit (Str (Index));
+
+ if Digit not in Valid_Digit then
+
+ -- Next character is not a digit. In that case stop scanning
+ -- unless the next chracter is an underscore followed by a digit.
+
+ if Digit = Underscore and Index + 1 <= Max then
+ Digit := As_Digit (Str (Index + 1));
+ if Digit in Valid_Digit then
+ Index := Index + 1;
+ else
+ return;
+ end if;
+ else
+ return;
+ end if;
+ end if;
+ end loop;
+ end Scan_Integral_Digits;
+
+ -------------------
+ -- Scan_Raw_Real --
+ -------------------
+
+ function Scan_Raw_Real
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Base : out Unsigned;
+ Scale : out Integer;
+ Extra : out Unsigned;
+ Minus : out Boolean) return Uns
+ is
+ pragma Assert (Max <= Str'Last);
+
+ After_Point : Boolean;
+ -- True if a decimal should be parsed
+
+ Base_Char : Character := ASCII.NUL;
+ -- Character used to set the base. If Nul this means that default
+ -- base is used.
+
+ Base_Violation : Boolean := False;
+ -- If True some digits where not in the base. The real is still scanned
+ -- till the end even if an error will be raised.
+
+ Index : Integer;
+ -- Local copy of string pointer
+
+ Start : Positive;
+ pragma Unreferenced (Start);
+
+ Value : Uns;
+ -- Mantissa as an Integer
+
+ begin
+ -- The default base is 10
+
+ Base := 10;
+
+ -- We do not tolerate strings with Str'Last = Positive'Last
+
+ if Str'Last = Positive'Last then
+ raise Program_Error with
+ "string upper bound is Positive'Last, not supported";
+ end if;
+
+ -- Scan the optional sign
+
+ Scan_Sign (Str, Ptr, Max, Minus, Start);
+ Index := Ptr.all;
+
+ pragma Assert (Index >= Str'First);
+
+ pragma Annotate (CodePeer, Modified, Str (Index));
+
+ -- First character can be either a decimal digit or a dot and for some
+ -- reason CodePeer incorrectly thinks it is always a digit.
+
+ if Str (Index) in '0' .. '9' then
+ After_Point := False;
+
+ -- If this is a digit it can indicates either the float decimal
+ -- part or the base to use.
+
+ Scan_Integral_Digits
+ (Str, Index, Max, Value, Scale, Char_As_Digit (Extra),
+ Base_Violation, Base, Base_Specified => False);
+
+ -- A dot is allowed only if followed by a digit (RM 3.5(47))
+
+ elsif Str (Index) = '.'
+ and then Index < Max
+ and then Str (Index + 1) in '0' .. '9'
+ then
+ After_Point := True;
+ Index := Index + 1;
+ Value := 0;
+ Scale := 0;
+ Extra := 0;
+
+ else
+ Bad_Value (Str);
+ end if;
+
+ -- Check if the first number encountered is a base
+
+ pragma Assert (Index >= Str'First);
+
+ if Index < Max
+ and then (Str (Index) = '#' or else Str (Index) = ':')
+ then
+ Base_Char := Str (Index);
+
+ if Value in 2 .. 16 then
+ Base := Unsigned (Value);
+ else
+ Base_Violation := True;
+ Base := 16;
+ end if;
+
+ Index := Index + 1;
+
+ if Str (Index) = '.'
+ and then Index < Max
+ and then As_Digit (Str (Index + 1)) in Valid_Digit
+ then
+ After_Point := True;
+ Index := Index + 1;
+ Value := 0;
+ end if;
+ end if;
+
+ -- Scan the integral part if still necessary
+
+ if Base_Char /= ASCII.NUL and then not After_Point then
+ if Index > Max or else As_Digit (Str (Index)) not in Valid_Digit then
+ Bad_Value (Str);
+ end if;
+
+ Scan_Integral_Digits
+ (Str, Index, Max, Value, Scale, Char_As_Digit (Extra),
+ Base_Violation, Base, Base_Specified => Base_Char /= ASCII.NUL);
+ end if;
+
+ -- Do we have a dot?
+
+ pragma Assert (Index >= Str'First);
+
+ if not After_Point and then Index <= Max and then Str (Index) = '.' then
+
+ -- At this stage if After_Point was not set, this means that an
+ -- integral part has been found. Thus the dot is valid even if not
+ -- followed by a digit.
+
+ if Index < Max and then As_Digit (Str (Index + 1)) in Valid_Digit then
+ After_Point := True;
+ end if;
+
+ Index := Index + 1;
+ end if;
+
+ -- Scan the decimal part
+
+ if After_Point then
+ pragma Assert (Index <= Max);
+
+ Scan_Decimal_Digits
+ (Str, Index, Max, Value, Scale, Char_As_Digit (Extra),
+ Base_Violation, Base, Base_Specified => Base_Char /= ASCII.NUL);
+ end if;
+
+ -- If an explicit base was specified ensure that the delimiter is found
+
+ if Base_Char /= ASCII.NUL then
+ pragma Assert (Index > Max or else Index in Str'Range);
+
+ if Index > Max or else Str (Index) /= Base_Char then
+ Bad_Value (Str);
+ else
+ Index := Index + 1;
+ end if;
+ end if;
+
+ -- Update pointer and scan exponent
+
+ Ptr.all := Index;
+ Scale := Scale + Scan_Exponent (Str, Ptr, Max, Real => True);
+
+ -- Here is where we check for a bad based number
+
+ if Base_Violation then
+ Bad_Value (Str);
+ else
+ return Value;
+ end if;
+
+ end Scan_Raw_Real;
+
+ --------------------
+ -- Value_Raw_Real --
+ --------------------
+
+ function Value_Raw_Real
+ (Str : String;
+ Base : out Unsigned;
+ Scale : out Integer;
+ Extra : out Unsigned;
+ Minus : out Boolean) return Uns
+ is
+ begin
+ -- We have to special case Str'Last = Positive'Last because the normal
+ -- circuit ends up setting P to Str'Last + 1 which is out of bounds. We
+ -- deal with this by converting to a subtype which fixes the bounds.
+
+ if Str'Last = Positive'Last then
+ declare
+ subtype NT is String (1 .. Str'Length);
+ begin
+ return Value_Raw_Real (NT (Str), Base, Scale, Extra, Minus);
+ end;
+
+ -- Normal case where Str'Last < Positive'Last
+
+ else
+ declare
+ V : Uns;
+ P : aliased Integer := Str'First;
+ begin
+ V := Scan_Raw_Real
+ (Str, P'Access, Str'Last, Base, Scale, Extra, Minus);
+ Scan_Trailing_Blanks (Str, P);
+ return V;
+ end;
+ end if;
+ end Value_Raw_Real;
+
+end System.Value_R;
diff --git a/gcc/ada/libgnat/s-valuer.ads b/gcc/ada/libgnat/s-valuer.ads
new file mode 100644
index 0000000..a933859
--- /dev/null
+++ b/gcc/ada/libgnat/s-valuer.ads
@@ -0,0 +1,101 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . V A L U E _ R --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package contains routines for scanning real values for use in
+-- Text_IO.Decimal_IO, Fixed_IO, Float_IO and the Value attribute.
+
+with System.Unsigned_Types; use System.Unsigned_Types;
+
+generic
+
+ type Uns is mod <>;
+
+ Precision_Limit : Uns;
+
+ Round : Boolean;
+
+package System.Value_R is
+ pragma Preelaborate;
+
+ function Scan_Raw_Real
+ (Str : String;
+ Ptr : not null access Integer;
+ Max : Integer;
+ Base : out Unsigned;
+ Scale : out Integer;
+ Extra : out Unsigned;
+ Minus : out Boolean) return Uns;
+ -- This function scans the string starting at Str (Ptr.all) for a valid
+ -- real literal according to the syntax described in (RM 3.5(43)). The
+ -- substring scanned extends no further than Str (Max). There are three
+ -- cases for the return:
+ --
+ -- If a valid real is found after scanning past any initial spaces, then
+ -- Ptr.all is updated past the last character of the real (but trailing
+ -- spaces are not scanned out) and the Base, Scale, Extra and Minus out
+ -- parameters are set; if Val is the result of the call, then the real
+ -- represented by the literal is equal to
+ --
+ -- (Val * Base + Extra) * (Base ** (Scale - 1))
+ --
+ -- with the negative sign if Minus is true.
+ --
+ -- If no valid real is found, then Ptr.all points either to an initial
+ -- non-blank character, or to Max + 1 if the field is all spaces and the
+ -- exception Constraint_Error is raised.
+ --
+ -- If a syntactically valid real is scanned, but the value is out of
+ -- range, or, in the based case, the base value is out of range or there
+ -- is an out of range digit, then Ptr.all points past the real literal,
+ -- and Constraint_Error is raised.
+ --
+ -- Note: these rules correspond to the requirements for leaving the
+ -- pointer positioned in Text_Io.Get
+ --
+ -- Note: if Str is null, i.e. if Max is less than Ptr, then this is a
+ -- special case of an all-blank string, and Ptr is unchanged, and hence
+ -- is greater than Max as required in this case.
+ --
+ -- Note: this routine should not be called with Str'Last = Positive'Last.
+ -- If this occurs Program_Error is raised with a message noting that this
+ -- case is not supported. Most such cases are eliminated by the caller.
+
+ function Value_Raw_Real
+ (Str : String;
+ Base : out Unsigned;
+ Scale : out Integer;
+ Extra : out Unsigned;
+ Minus : out Boolean) return Uns;
+ -- Used in computing X'Value (Str) where X is a real type. Str is the
+ -- string argument of the attribute. Constraint_Error is raised if the
+ -- string is malformed.
+
+end System.Value_R;
diff --git a/gcc/ada/libgnat/system-aix.ads b/gcc/ada/libgnat/system-aix.ads
index 5bf603d..db4579f 100644
--- a/gcc/ada/libgnat/system-aix.ads
+++ b/gcc/ada/libgnat/system-aix.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -135,8 +135,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-darwin-arm.ads b/gcc/ada/libgnat/system-darwin-arm.ads
index 70e02a1..b306920 100644
--- a/gcc/ada/libgnat/system-darwin-arm.ads
+++ b/gcc/ada/libgnat/system-darwin-arm.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -151,8 +151,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-darwin-ppc.ads b/gcc/ada/libgnat/system-darwin-ppc.ads
index 4947c6c..bc0b147 100644
--- a/gcc/ada/libgnat/system-darwin-ppc.ads
+++ b/gcc/ada/libgnat/system-darwin-ppc.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -151,8 +151,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-darwin-x86.ads b/gcc/ada/libgnat/system-darwin-x86.ads
index 828b310..c175224 100644
--- a/gcc/ada/libgnat/system-darwin-x86.ads
+++ b/gcc/ada/libgnat/system-darwin-x86.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -151,8 +151,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-djgpp.ads b/gcc/ada/libgnat/system-djgpp.ads
index 68fdb49..52e4a88 100644
--- a/gcc/ada/libgnat/system-djgpp.ads
+++ b/gcc/ada/libgnat/system-djgpp.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-dragonfly-x86_64.ads b/gcc/ada/libgnat/system-dragonfly-x86_64.ads
index 6bfb5c4..0cc0dab 100644
--- a/gcc/ada/libgnat/system-dragonfly-x86_64.ads
+++ b/gcc/ada/libgnat/system-dragonfly-x86_64.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-freebsd.ads b/gcc/ada/libgnat/system-freebsd.ads
index d4fe60e..ce1835c 100644
--- a/gcc/ada/libgnat/system-freebsd.ads
+++ b/gcc/ada/libgnat/system-freebsd.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -126,8 +126,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-hpux-ia64.ads b/gcc/ada/libgnat/system-hpux-ia64.ads
index f11edc6..202bcac 100644
--- a/gcc/ada/libgnat/system-hpux-ia64.ads
+++ b/gcc/ada/libgnat/system-hpux-ia64.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-hpux.ads b/gcc/ada/libgnat/system-hpux.ads
index ddf6a82..34f2752 100644
--- a/gcc/ada/libgnat/system-hpux.ads
+++ b/gcc/ada/libgnat/system-hpux.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-alpha.ads b/gcc/ada/libgnat/system-linux-alpha.ads
index eebe93a..2c638e5 100644
--- a/gcc/ada/libgnat/system-linux-alpha.ads
+++ b/gcc/ada/libgnat/system-linux-alpha.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 1024.0;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-arm.ads b/gcc/ada/libgnat/system-linux-arm.ads
index 4d09d9e..9020c79 100644
--- a/gcc/ada/libgnat/system-linux-arm.ads
+++ b/gcc/ada/libgnat/system-linux-arm.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -134,8 +134,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-hppa.ads b/gcc/ada/libgnat/system-linux-hppa.ads
index 6bc9541..dccf444 100644
--- a/gcc/ada/libgnat/system-linux-hppa.ads
+++ b/gcc/ada/libgnat/system-linux-hppa.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-ia64.ads b/gcc/ada/libgnat/system-linux-ia64.ads
index ae9b49a..14b6bb3 100644
--- a/gcc/ada/libgnat/system-linux-ia64.ads
+++ b/gcc/ada/libgnat/system-linux-ia64.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -133,8 +133,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-m68k.ads b/gcc/ada/libgnat/system-linux-m68k.ads
index 3fbd781..db7f9e7 100644
--- a/gcc/ada/libgnat/system-linux-m68k.ads
+++ b/gcc/ada/libgnat/system-linux-m68k.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -135,8 +135,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-mips.ads b/gcc/ada/libgnat/system-linux-mips.ads
index d760db8..d44bf1b 100644
--- a/gcc/ada/libgnat/system-linux-mips.ads
+++ b/gcc/ada/libgnat/system-linux-mips.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -126,8 +126,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-ppc.ads b/gcc/ada/libgnat/system-linux-ppc.ads
index 0f39370..917b949 100644
--- a/gcc/ada/libgnat/system-linux-ppc.ads
+++ b/gcc/ada/libgnat/system-linux-ppc.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -134,8 +134,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-riscv.ads b/gcc/ada/libgnat/system-linux-riscv.ads
index 91eddf2..9e93e5e 100644
--- a/gcc/ada/libgnat/system-linux-riscv.ads
+++ b/gcc/ada/libgnat/system-linux-riscv.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-s390.ads b/gcc/ada/libgnat/system-linux-s390.ads
index 374b938..0ceeb96 100644
--- a/gcc/ada/libgnat/system-linux-s390.ads
+++ b/gcc/ada/libgnat/system-linux-s390.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-sh4.ads b/gcc/ada/libgnat/system-linux-sh4.ads
index cd811de..fd0e0c7 100644
--- a/gcc/ada/libgnat/system-linux-sh4.ads
+++ b/gcc/ada/libgnat/system-linux-sh4.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -133,8 +133,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-sparc.ads b/gcc/ada/libgnat/system-linux-sparc.ads
index e74214b..29a650a 100644
--- a/gcc/ada/libgnat/system-linux-sparc.ads
+++ b/gcc/ada/libgnat/system-linux-sparc.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-linux-x86.ads b/gcc/ada/libgnat/system-linux-x86.ads
index eb8b5dd..73c99c3 100644
--- a/gcc/ada/libgnat/system-linux-x86.ads
+++ b/gcc/ada/libgnat/system-linux-x86.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -133,8 +133,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-lynxos178-ppc.ads b/gcc/ada/libgnat/system-lynxos178-ppc.ads
index cf516e1..e2d9765 100644
--- a/gcc/ada/libgnat/system-lynxos178-ppc.ads
+++ b/gcc/ada/libgnat/system-lynxos178-ppc.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -102,7 +102,7 @@ package System is
-- (Priority'First + Priority'Last) / 2
-- However, the default priority given by the OS is not the same thing as
- -- the Ada value Default_Prioirity (previous examples include VxWorks).
+ -- the Ada value Default_Priority (previous examples include VxWorks).
-- Therefore, we follow a model based on the full range of LynxOS-178
-- priorities.
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-lynxos178-x86.ads b/gcc/ada/libgnat/system-lynxos178-x86.ads
index c151472..3131895 100644
--- a/gcc/ada/libgnat/system-lynxos178-x86.ads
+++ b/gcc/ada/libgnat/system-lynxos178-x86.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -102,7 +102,7 @@ package System is
-- (Priority'First + Priority'Last) / 2
-- However, the default priority given by the OS is not the same thing as
- -- the Ada value Default_Prioirity (previous examples include VxWorks).
+ -- the Ada value Default_Priority (previous examples include VxWorks).
-- Therefore, we follow a model based on the full range of LynxOS-178
-- priorities.
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-mingw.ads b/gcc/ada/libgnat/system-mingw.ads
index cf960da..3729e44 100644
--- a/gcc/ada/libgnat/system-mingw.ads
+++ b/gcc/ada/libgnat/system-mingw.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-qnx-aarch64.ads b/gcc/ada/libgnat/system-qnx-aarch64.ads
index 37b8fd1..a6336a9 100644
--- a/gcc/ada/libgnat/system-qnx-aarch64.ads
+++ b/gcc/ada/libgnat/system-qnx-aarch64.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.000_001;
@@ -134,8 +134,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-rtems.ads b/gcc/ada/libgnat/system-rtems.ads
index 099c234..dca09dd 100644
--- a/gcc/ada/libgnat/system-rtems.ads
+++ b/gcc/ada/libgnat/system-rtems.ads
@@ -61,7 +61,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -144,8 +144,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-solaris-sparc.ads b/gcc/ada/libgnat/system-solaris-sparc.ads
index 0e1ce01..1efc78f 100644
--- a/gcc/ada/libgnat/system-solaris-sparc.ads
+++ b/gcc/ada/libgnat/system-solaris-sparc.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-solaris-x86.ads b/gcc/ada/libgnat/system-solaris-x86.ads
index 010ce5b..8dc46ed 100644
--- a/gcc/ada/libgnat/system-solaris-x86.ads
+++ b/gcc/ada/libgnat/system-solaris-x86.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 0.01;
@@ -125,8 +125,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-arm-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks-arm-rtp-smp.ads
index 91806e5..592e25b 100644
--- a/gcc/ada/libgnat/system-vxworks-arm-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks-arm-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -144,8 +144,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-arm-rtp.ads b/gcc/ada/libgnat/system-vxworks-arm-rtp.ads
index de13974..ac025ce 100644
--- a/gcc/ada/libgnat/system-vxworks-arm-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks-arm-rtp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-arm.ads b/gcc/ada/libgnat/system-vxworks-arm.ads
index fac4e72..483881f 100644
--- a/gcc/ada/libgnat/system-vxworks-arm.ads
+++ b/gcc/ada/libgnat/system-vxworks-arm.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-e500-kernel.ads b/gcc/ada/libgnat/system-vxworks-e500-kernel.ads
index cf89c2d..ac674bd 100644
--- a/gcc/ada/libgnat/system-vxworks-e500-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks-e500-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-e500-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks-e500-rtp-smp.ads
index 862f3f6..45a99f3 100644
--- a/gcc/ada/libgnat/system-vxworks-e500-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks-e500-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -144,8 +144,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-e500-rtp.ads b/gcc/ada/libgnat/system-vxworks-e500-rtp.ads
index a3baecb..27f7707 100644
--- a/gcc/ada/libgnat/system-vxworks-e500-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks-e500-rtp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-e500-vthread.ads b/gcc/ada/libgnat/system-vxworks-e500-vthread.ads
index fc92958..f60fbcd 100644
--- a/gcc/ada/libgnat/system-vxworks-e500-vthread.ads
+++ b/gcc/ada/libgnat/system-vxworks-e500-vthread.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc-kernel.ads b/gcc/ada/libgnat/system-vxworks-ppc-kernel.ads
index 383c820..ec3de26 100644
--- a/gcc/ada/libgnat/system-vxworks-ppc-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks-ppc-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads b/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads
index 53a1f9e..e38ff3b 100644
--- a/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads
+++ b/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads
@@ -82,7 +82,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -163,8 +163,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := True;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := True;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks-ppc-rtp-smp.ads
index aa99413..b4277e2 100644
--- a/gcc/ada/libgnat/system-vxworks-ppc-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks-ppc-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -144,8 +144,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc-rtp.ads b/gcc/ada/libgnat/system-vxworks-ppc-rtp.ads
index acb20c4..eeeca9b 100644
--- a/gcc/ada/libgnat/system-vxworks-ppc-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks-ppc-rtp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads b/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads
index aca420e..05d27d6 100644
--- a/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads
+++ b/gcc/ada/libgnat/system-vxworks-ppc-vthread.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := True;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-ppc.ads b/gcc/ada/libgnat/system-vxworks-ppc.ads
index 99644ee..9862f42 100644
--- a/gcc/ada/libgnat/system-vxworks-ppc.ads
+++ b/gcc/ada/libgnat/system-vxworks-ppc.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-x86-kernel.ads b/gcc/ada/libgnat/system-vxworks-x86-kernel.ads
index 3781020..b6eebb5 100644
--- a/gcc/ada/libgnat/system-vxworks-x86-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks-x86-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-x86-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks-x86-rtp-smp.ads
index 374041c..e6d31de 100644
--- a/gcc/ada/libgnat/system-vxworks-x86-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks-x86-rtp-smp.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -142,8 +142,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-x86-rtp.ads b/gcc/ada/libgnat/system-vxworks-x86-rtp.ads
index cff7291..960a7ed 100644
--- a/gcc/ada/libgnat/system-vxworks-x86-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks-x86-rtp.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-x86-vthread.ads b/gcc/ada/libgnat/system-vxworks-x86-vthread.ads
index 1867196..f3f4037 100644
--- a/gcc/ada/libgnat/system-vxworks-x86-vthread.ads
+++ b/gcc/ada/libgnat/system-vxworks-x86-vthread.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := True;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks-x86.ads b/gcc/ada/libgnat/system-vxworks-x86.ads
index c82a61f..55bc3f6 100644
--- a/gcc/ada/libgnat/system-vxworks-x86.ads
+++ b/gcc/ada/libgnat/system-vxworks-x86.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-aarch64-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-aarch64-rtp-smp.ads
index 37bf607..0624ffa 100644
--- a/gcc/ada/libgnat/system-vxworks7-aarch64-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-aarch64-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-aarch64.ads b/gcc/ada/libgnat/system-vxworks7-aarch64.ads
index c386500..1491332 100644
--- a/gcc/ada/libgnat/system-vxworks7-aarch64.ads
+++ b/gcc/ada/libgnat/system-vxworks7-aarch64.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-arm-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-arm-rtp-smp.ads
index 7e2db7a..d7da53d 100644
--- a/gcc/ada/libgnat/system-vxworks7-arm-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-arm-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-arm.ads b/gcc/ada/libgnat/system-vxworks7-arm.ads
index fac4e72..483881f 100644
--- a/gcc/ada/libgnat/system-vxworks7-arm.ads
+++ b/gcc/ada/libgnat/system-vxworks7-arm.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-e500-kernel.ads b/gcc/ada/libgnat/system-vxworks7-e500-kernel.ads
index e03264e..e697629 100644
--- a/gcc/ada/libgnat/system-vxworks7-e500-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks7-e500-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-e500-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-e500-rtp-smp.ads
index a9b3317..6388628 100644
--- a/gcc/ada/libgnat/system-vxworks7-e500-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-e500-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-e500-rtp.ads b/gcc/ada/libgnat/system-vxworks7-e500-rtp.ads
index 3e963d0..69a0a66 100644
--- a/gcc/ada/libgnat/system-vxworks7-e500-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-e500-rtp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-ppc-kernel.ads b/gcc/ada/libgnat/system-vxworks7-ppc-kernel.ads
index 93b3271..82c5d3a 100644
--- a/gcc/ada/libgnat/system-vxworks7-ppc-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks7-ppc-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-ppc-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-ppc-rtp-smp.ads
index e5d984b..d34d632 100644
--- a/gcc/ada/libgnat/system-vxworks7-ppc-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-ppc-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-ppc-rtp.ads b/gcc/ada/libgnat/system-vxworks7-ppc-rtp.ads
index e96d303..404da85 100644
--- a/gcc/ada/libgnat/system-vxworks7-ppc-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-ppc-rtp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-ppc64-kernel.ads b/gcc/ada/libgnat/system-vxworks7-ppc64-kernel.ads
index 90499f6..05a51d9 100644
--- a/gcc/ada/libgnat/system-vxworks7-ppc64-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks7-ppc64-kernel.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -140,8 +140,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-ppc64-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-ppc64-rtp-smp.ads
index 49b22b6..e55de8c 100644
--- a/gcc/ada/libgnat/system-vxworks7-ppc64-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-ppc64-rtp-smp.ads
@@ -59,7 +59,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -143,8 +143,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-x86-kernel.ads b/gcc/ada/libgnat/system-vxworks7-x86-kernel.ads
index d7b35dd..b3659a3 100644
--- a/gcc/ada/libgnat/system-vxworks7-x86-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks7-x86-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-x86-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-x86-rtp-smp.ads
index 293ede8..8c2d527 100644
--- a/gcc/ada/libgnat/system-vxworks7-x86-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-x86-rtp-smp.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-x86-rtp.ads b/gcc/ada/libgnat/system-vxworks7-x86-rtp.ads
index caf458f..f6528ba 100644
--- a/gcc/ada/libgnat/system-vxworks7-x86-rtp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-x86-rtp.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-x86_64-kernel.ads b/gcc/ada/libgnat/system-vxworks7-x86_64-kernel.ads
index a5f00ff..fc4655f 100644
--- a/gcc/ada/libgnat/system-vxworks7-x86_64-kernel.ads
+++ b/gcc/ada/libgnat/system-vxworks7-x86_64-kernel.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -138,8 +138,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/libgnat/system-vxworks7-x86_64-rtp-smp.ads b/gcc/ada/libgnat/system-vxworks7-x86_64-rtp-smp.ads
index 05e69e5..2bc8e6a 100644
--- a/gcc/ada/libgnat/system-vxworks7-x86_64-rtp-smp.ads
+++ b/gcc/ada/libgnat/system-vxworks7-x86_64-rtp-smp.ads
@@ -57,7 +57,7 @@ package System is
Max_Base_Digits : constant := Long_Long_Float'Digits;
Max_Digits : constant := Long_Long_Float'Digits;
- Max_Mantissa : constant := 63;
+ Max_Mantissa : constant := Standard'Max_Integer_Size - 1;
Fine_Delta : constant := 2.0 ** (-Max_Mantissa);
Tick : constant := 1.0 / 60.0;
@@ -141,8 +141,6 @@ private
Denorm : constant Boolean := True;
Duration_32_Bits : constant Boolean := False;
Exit_Status_Supported : constant Boolean := True;
- Fractional_Fixed_Ops : constant Boolean := False;
- Frontend_Layout : constant Boolean := False;
Machine_Overflows : constant Boolean := False;
Machine_Rounds : constant Boolean := True;
Preallocated_Stacks : constant Boolean := False;
diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb
index 0034d1a..ede4c5a 100644
--- a/gcc/ada/make.adb
+++ b/gcc/ada/make.adb
@@ -464,7 +464,7 @@ package body Make is
Ada_Flag_1 : constant String_Access := new String'("-x");
Ada_Flag_2 : constant String_Access := new String'("ada");
AdaSCIL_Flag : constant String_Access := new String'("adascil");
- GNAT_Flag : constant String_Access := new String'("-gnatpg");
+ GNAT_Flag : constant String_Access := new String'("-gnatg");
Do_Not_Check_Flag : constant String_Access := new String'("-x");
Object_Suffix : constant String := Get_Target_Object_Suffix.all;
@@ -1677,7 +1677,7 @@ package body Make is
L : File_Name_Type;
Source_Index : Int;
Args : Argument_List) return Process_Id;
- -- Compiles S using Args. If S is a GNAT predefined source "-gnatpg" is
+ -- Compiles S using Args. If S is a GNAT predefined source "-gnatg" is
-- added to Args. Non blocking call. L corresponds to the expected
-- library file name. Process_Id of the process spawned to execute the
-- compilation.
@@ -2027,7 +2027,7 @@ package body Make is
end loop;
end;
- -- Set -gnatpg for predefined files (for this purpose the renamings
+ -- Set -gnatg for predefined files (for this purpose the renamings
-- such as Text_IO do not count as predefined). Note that we strip
-- the directory name from the source file name because the call to
-- Fname.Is_Predefined_File_Name cannot deal with directory prefixes.
@@ -4697,19 +4697,9 @@ package body Make is
pragma Assert (Argv'Last = 2);
Minimal_Recompilation := True;
- -- -u
+ -- -u and -U (they are differentiated elsewhere)
- elsif Argv (2) = 'u' and then Argv'Last = 2 then
- Unique_Compile := True;
- Compile_Only := True;
- Do_Bind_Step := False;
- Do_Link_Step := False;
-
- -- -U
-
- elsif Argv (2) = 'U'
- and then Argv'Last = 2
- then
+ elsif Argv (2) in 'u' | 'U' and then Argv'Last = 2 then
Unique_Compile := True;
Compile_Only := True;
Do_Bind_Step := False;
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index 7ec44dc..6b32a96 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -364,6 +364,11 @@ package Opt is
-- GNAT
-- Names of configuration pragmas files (given by switches -gnatec)
+ Config_Files_Store_Basename : Boolean := False;
+ -- GNAT
+ -- Set True for -gnateb. Tells GNAT that config files should be referred to
+ -- by their basename and their checksums computed in ALI files.
+
Configurable_Run_Time_Mode : Boolean := False;
-- GNAT, GNATBIND
-- Set True if the compiler is operating in configurable run-time mode.
@@ -719,6 +724,10 @@ package Opt is
-- the name is of the form .xxx, then to name.xxx where name is the source
-- file name with extension stripped.
+ Generate_Asm : Boolean := False;
+ -- GNAT
+ -- True if generating assembly instead of an object file, via the -S switch
+
Generate_C_Code : Boolean := False;
-- GNAT, GNATBIND
-- If True, the Cprint circuitry to generate C code output is activated.
@@ -1126,7 +1135,7 @@ package Opt is
-- make it easier to interface with back ends that implement C semantics.
-- There is a section in Sinfo which describes the transformations made.
- Multiple_Unit_Index : Int := 0;
+ Multiple_Unit_Index : Nat := 0;
-- GNAT
-- This is set non-zero if the current unit is being compiled in multiple
-- unit per file mode, meaning that the current unit is selected from the
@@ -1588,6 +1597,12 @@ package Opt is
-- Tolerate time stamp and other consistency errors. If this flag is set to
-- True (-t), then inconsistencies result in warnings rather than errors.
+ Transform_Function_Array : Boolean := False;
+ -- GNAT
+ -- If this switch is set True, then functions returning constrained arrays
+ -- are transformed into a procedure with an out parameter, and all calls
+ -- are updated accordingly.
+
Treat_Categorization_Errors_As_Warnings : Boolean := False;
-- Normally categorization errors are true illegalities. If this switch
-- is set, then such errors result in warning messages rather than error
diff --git a/gcc/ada/osint-c.adb b/gcc/ada/osint-c.adb
index 0010a8d..4fc0998 100644
--- a/gcc/ada/osint-c.adb
+++ b/gcc/ada/osint-c.adb
@@ -475,14 +475,14 @@ package body Osint.C is
begin
-- Make sure that the object file has the expected extension
+ -- Allow for either .o or .c (for C code generation)
if NL <= EL
or else
- (Name (NL - EL + Name'First .. Name'Last) /= Ext
+ (not Generate_Asm
+ and then Name (NL - EL + Name'First .. Name'Last) /= Ext
and then Name (NL - 2 + Name'First .. Name'Last) /= ".o"
- and then
- (not Generate_C_Code
- or else Name (NL - 2 + Name'First .. Name'Last) /= ".c"))
+ and then Name (NL - 2 + Name'First .. Name'Last) /= ".c")
then
Fail ("incorrect object file extension");
end if;
diff --git a/gcc/ada/par-ch10.adb b/gcc/ada/par-ch10.adb
index e4298e8..70984b1 100644
--- a/gcc/ada/par-ch10.adb
+++ b/gcc/ada/par-ch10.adb
@@ -861,11 +861,7 @@ package body Ch10 is
("unexpected LIMITED ignored");
end if;
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("LIMITED WITH is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("`LIMITED WITH`");
elsif Token = Tok_Private then
Has_Limited := False;
@@ -879,13 +875,10 @@ package body Ch10 is
Restore_Scan_State (Scan_State); -- to PRIVATE
return Item_List;
-
- elsif Ada_Version < Ada_2005 then
- Error_Msg_SP ("`PRIVATE WITH` is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
end if;
+ Error_Msg_Ada_2005_Extension ("`PRIVATE WITH`");
+
else
Has_Limited := False;
Has_Private := False;
diff --git a/gcc/ada/par-ch11.adb b/gcc/ada/par-ch11.adb
index 468ba03a..63f0c6e 100644
--- a/gcc/ada/par-ch11.adb
+++ b/gcc/ada/par-ch11.adb
@@ -227,10 +227,7 @@ package body Ch11 is
end if;
if Token = Tok_With then
- if Ada_Version < Ada_2005 then
- Error_Msg_SC ("string expression in raise is Ada 2005 extension");
- Error_Msg_SC ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("string expression in raise");
Scan; -- past WITH
Set_Expression (Raise_Node, P_Expression);
diff --git a/gcc/ada/par-ch12.adb b/gcc/ada/par-ch12.adb
index c53f7cb..a4799c7 100644
--- a/gcc/ada/par-ch12.adb
+++ b/gcc/ada/par-ch12.adb
@@ -349,24 +349,19 @@ package body Ch12 is
-- Ada 2005: an association can be given by: others => <>
if Token = Tok_Others then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("partial parameterization of formal packages"
- & " is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("partial parameterization of formal package");
Scan; -- past OTHERS
if Token /= Tok_Arrow then
- Error_Msg_BC ("expect arrow after others");
+ Error_Msg_BC ("expect `='>` after OTHERS");
else
Scan; -- past arrow
end if;
if Token /= Tok_Box then
- Error_Msg_BC ("expect Box after arrow");
+ Error_Msg_BC ("expect `'<'>` after `='>`");
else
Scan; -- past box
end if;
@@ -428,12 +423,12 @@ package body Ch12 is
procedure P_Formal_Object_Declarations (Decls : List_Id) is
Decl_Node : Node_Id;
- Ident : Nat;
+ Ident : Pos;
Not_Null_Present : Boolean := False;
- Num_Idents : Nat;
+ Num_Idents : Pos;
Scan_State : Saved_Scan_State;
- Idents : array (Int range 1 .. 4096) of Entity_Id;
+ Idents : array (Pos range 1 .. 4096) of Entity_Id;
-- This array holds the list of defining identifiers. The upper bound
-- of 4096 is intended to be essentially infinite, and we do not even
-- bother to check for it being exceeded.
@@ -478,12 +473,8 @@ package body Ch12 is
Set_Access_Definition (Decl_Node,
P_Access_Definition (Not_Null_Present));
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("access definition not allowed in formal object " &
- "declaration");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("access definition in formal object declaration");
-- Formal object with a subtype mark
@@ -923,23 +914,13 @@ package body Ch12 is
Set_Limited_Present (Def_Node);
Scan; -- past LIMITED
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("LIMITED in derived type is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("LIMITED in derived type");
elsif Token = Tok_Synchronized then
Set_Synchronized_Present (Def_Node);
Scan; -- past SYNCHRONIZED
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("SYNCHRONIZED in derived type is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("SYNCHRONIZED in derived type");
end if;
if Token = Tok_Abstract then
@@ -955,11 +936,7 @@ package body Ch12 is
if Token = Tok_And then
Scan; -- past AND
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("abstract interface is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("abstract interface");
Set_Interface_List (Def_Node, New_List);
@@ -972,20 +949,21 @@ package body Ch12 is
if Token = Tok_With then
- if Ada_Version >= Ada_2020 and not Next_Token_Is (Tok_Private) then
-
+ if Next_Token_Is (Tok_Private) then
+ Scan; -- past WITH
+ Set_Private_Present (Def_Node, True);
+ T_Private;
+ else
-- Formal type has aspect specifications, parsed later.
-- Otherwise this is a formal derived type. Note that it may
-- also include later aspect specifications, as in:
- -- type DT is new T with private with atomic;
+ -- type DT is new T with private with Atomic;
- return Def_Node;
+ Error_Msg_Ada_2020_Feature
+ ("formal type with aspect specification", Token_Ptr);
- else
- Scan; -- past WITH
- Set_Private_Present (Def_Node, True);
- T_Private;
+ return Def_Node;
end if;
elsif Token = Tok_Tagged then
@@ -1190,11 +1168,7 @@ package body Ch12 is
New_Node (N_Formal_Abstract_Subprogram_Declaration, Prev_Sloc);
Scan; -- past ABSTRACT
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("formal abstract subprograms are an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("formal abstract subprogram");
else
Def_Node :=
@@ -1214,11 +1188,7 @@ package body Ch12 is
Scan; -- past <>
elsif Token = Tok_Null then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("null default subprograms are an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("null default subprogram");
if Nkind (Spec_Node) = N_Procedure_Specification then
Set_Null_Present (Spec_Node);
diff --git a/gcc/ada/par-ch13.adb b/gcc/ada/par-ch13.adb
index 95223a1..8bee840 100644
--- a/gcc/ada/par-ch13.adb
+++ b/gcc/ada/par-ch13.adb
@@ -23,6 +23,8 @@
-- --
------------------------------------------------------------------------------
+with Rident; use Rident;
+with Restrict; use Restrict;
pragma Style_Checks (All_Checks);
-- Turn off subprogram body ordering check. Subprograms are in order
-- by RM section rather than alphabetical
@@ -264,20 +266,28 @@ package body Ch13 is
-- The aspect mark is not recognized
if A_Id = No_Aspect then
- Error_Msg_Warn := not Debug_Flag_2;
- Error_Msg_N ("<<& is not a valid aspect identifier", Token_Node);
- OK := False;
-
- -- Check bad spelling
-
- for J in Aspect_Id_Exclude_No_Aspect loop
- if Is_Bad_Spelling_Of (Token_Name, Aspect_Names (J)) then
- Error_Msg_Name_1 := Aspect_Names (J);
- Error_Msg_N -- CODEFIX
- ("\<<possible misspelling of%", Token_Node);
- exit;
+ declare
+ Msg_Issued : Boolean := False;
+ begin
+ Check_Restriction (Msg_Issued, No_Unrecognized_Aspects, Aspect);
+ if not Msg_Issued then
+ Error_Msg_Warn := not Debug_Flag_2;
+ Error_Msg_N
+ ("<<& is not a valid aspect identifier", Token_Node);
+ OK := False;
+
+ -- Check bad spelling
+
+ for J in Aspect_Id_Exclude_No_Aspect loop
+ if Is_Bad_Spelling_Of (Token_Name, Aspect_Names (J)) then
+ Error_Msg_Name_1 := Aspect_Names (J);
+ Error_Msg_N -- CODEFIX
+ ("\<<possible misspelling of%", Token_Node);
+ exit;
+ end if;
+ end loop;
end if;
- end loop;
+ end;
Scan; -- past incorrect identifier
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
index 017a0a1..78a3ebd 100644
--- a/gcc/ada/par-ch3.adb
+++ b/gcc/ada/par-ch3.adb
@@ -690,12 +690,7 @@ package body Ch3 is
-- Ada 2005 (AI-419): LIMITED NEW
elsif Token = Tok_New then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("LIMITED in derived type is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("LIMITED in derived type");
Typedef_Node := P_Derived_Type_Def_Or_Private_Ext_Decl;
Set_Limited_Present (Typedef_Node);
@@ -919,7 +914,7 @@ package body Ch3 is
if Unknown_Dis then
Error_Msg
- ("Full type declaration cannot have unknown discriminants",
+ ("full type declaration cannot have unknown discriminants",
Discr_Sloc);
end if;
end if;
@@ -1056,7 +1051,7 @@ package body Ch3 is
-- otherwise things are really messed up, so resynchronize.
if Token = Tok_Record then
- Error_Msg_SC ("anonymous record definitions are not permitted");
+ Error_Msg_SC ("anonymous record definition not permitted");
Discard_Junk_Node (P_Record_Definition);
return Error;
@@ -1491,11 +1486,8 @@ package body Ch3 is
-- access_definition
elsif Token = Tok_Renames then
- if Ada_Version < Ada_2020 then
- Error_Msg_SC
- ("object renaming without subtype is an Ada 202x feature");
- Error_Msg_SC ("\compile with -gnat2020");
- end if;
+ Error_Msg_Ada_2020_Feature
+ ("object renaming without subtype", Token_Ptr);
Scan; -- past renames
@@ -1671,13 +1663,8 @@ package body Ch3 is
Set_Null_Exclusion_Present (Decl_Node, Not_Null_Present);
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("generalized use of anonymous access types " &
- "is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("generalized use of anonymous access types");
Set_Object_Definition
(Decl_Node, P_Access_Definition (Not_Null_Present));
@@ -1734,13 +1721,8 @@ package body Ch3 is
-- Access definition (AI-406) or subtype indication
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("generalized use of anonymous access types " &
- "is an Ada 2005 extension");
- Error_Msg_SP
- ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("generalized use of anonymous access types");
Set_Object_Definition
(Decl_Node, P_Access_Definition (Not_Null_Present));
@@ -1779,12 +1761,8 @@ package body Ch3 is
Not_Null_Present := P_Null_Exclusion; -- Ada 2005 (AI-231/423)
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("generalized use of anonymous access types " &
- "is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("generalized use of anonymous access types");
Acc_Node := P_Access_Definition (Not_Null_Present);
@@ -1850,12 +1828,8 @@ package body Ch3 is
-- Ada 2005 (AI-230): Access Definition case
elsif Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("generalized use of anonymous access types " &
- "is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("generalized use of anonymous access types");
Acc_Node := P_Access_Definition (Null_Exclusion_Present => False);
@@ -2063,11 +2037,7 @@ package body Ch3 is
if Token = Tok_And then
Scan; -- past AND
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("abstract interface is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("abstract interface");
Set_Interface_List (Typedef_Node, New_List);
@@ -2457,7 +2427,7 @@ package body Ch3 is
begin
if Ada_Version = Ada_83 then
- Error_Msg_SC ("(Ada 83): modular types not allowed");
+ Error_Msg_SC ("(Ada 83) modular types not allowed");
end if;
Typedef_Node := New_Node (N_Modular_Type_Definition, Token_Ptr);
@@ -2795,12 +2765,8 @@ package body Ch3 is
-- Ada 2005 (AI-230): Access Definition case
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("generalized use of anonymous access types " &
- "is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("generalized use of anonymous access types");
-- AI95-406 makes "aliased" legal (and useless) in this context so
-- followintg code which used to be needed is commented out.
@@ -3002,9 +2968,9 @@ package body Ch3 is
-- DISCRIMINANT_SPECIFICATION ::=
-- DEFINING_IDENTIFIER_LIST : [NULL_EXCLUSION] SUBTYPE_MARK
- -- [:= DEFAULT_EXPRESSION]
+ -- [:= DEFAULT_EXPRESSION] [ASPECT_SPECIFICATION]
-- | DEFINING_IDENTIFIER_LIST : ACCESS_DEFINITION
- -- [:= DEFAULT_EXPRESSION]
+ -- [:= DEFAULT_EXPRESSION] [ASPECT_SPECIFICATION]
-- If no known discriminant part is present, then No_List is returned
@@ -3098,6 +3064,10 @@ package body Ch3 is
Set_Expression
(Specification_Node, Init_Expr_Opt (True));
+ if Token = Tok_With then
+ P_Aspect_Specifications (Specification_Node, False);
+ end if;
+
if Ident > 1 then
Set_Prev_Ids (Specification_Node, True);
end if;
@@ -3584,7 +3554,7 @@ package body Ch3 is
Set_Defining_Identifier (Decl_Node, Idents (Ident));
if Token = Tok_Constant then
- Error_Msg_SC ("constant components are not permitted");
+ Error_Msg_SC ("constant component not permitted");
Scan;
end if;
@@ -3604,12 +3574,8 @@ package body Ch3 is
-- Ada 2005 (AI-230): Access Definition case
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("generalized use of anonymous access types " &
- "is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension
+ ("generalized use of anonymous access types");
-- AI95-406 makes "aliased" legal (and useless) here, so the
-- following code which used to be required is commented out.
@@ -3629,7 +3595,7 @@ package body Ch3 is
Set_Null_Exclusion_Present (CompDef_Node, Not_Null_Present);
if Token = Tok_Array then
- Error_Msg_SC ("anonymous arrays not allowed as components");
+ Error_Msg_SC ("anonymous array not allowed as component");
raise Error_Resync;
end if;
@@ -3949,10 +3915,7 @@ package body Ch3 is
Typedef_Node : Node_Id;
begin
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("abstract interface is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("abstract interface");
if Abstract_Present then
Error_Msg_SP
@@ -4139,11 +4102,7 @@ package body Ch3 is
-- Ada 2005 (AI-318-02)
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SC
- ("anonymous access result type is an Ada 2005 extension");
- Error_Msg_SC ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("anonymous access result type");
Result_Node := P_Access_Definition (Result_Not_Null);
@@ -4241,10 +4200,7 @@ package body Ch3 is
or else Token = Tok_Procedure
or else Token = Tok_Function
then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("access-to-subprogram is an Ada 2005 extension");
- Error_Msg_SP ("\unit should be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("access-to-subprogram");
Subp_Node := P_Access_Type_Definition (Header_Already_Parsed => True);
Set_Null_Exclusion_Present (Subp_Node, Null_Exclusion_Present);
@@ -4259,17 +4215,14 @@ package body Ch3 is
if Token = Tok_All then
if Ada_Version < Ada_2005 then
Error_Msg_SP
- ("ALL is not permitted for anonymous access types");
+ ("ALL not permitted for anonymous access type");
end if;
Scan; -- past ALL
Set_All_Present (Def_Node);
elsif Token = Tok_Constant then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("access-to-constant is an Ada 2005 extension");
- Error_Msg_SP ("\unit should be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("access-to-constant");
Scan; -- past CONSTANT
Set_Constant_Present (Def_Node);
@@ -4794,7 +4747,7 @@ package body Ch3 is
elsif Kind = N_Assignment_Statement then
Error_Msg
("assignment statement not allowed in package spec",
- Sloc (Decl));
+ Sloc (Decl));
end if;
Next (Decl);
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 925da76..340668e 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -1233,7 +1233,7 @@ package body Ch4 is
Attr_Node := New_Node (N_Attribute_Reference, Token_Ptr);
Set_Attribute_Name (Attr_Node, Attr_Name);
if Attr_Name /= Name_Reduce then
- Error_Msg ("reduce attribute expected", Prev_Token_Ptr);
+ Error_Msg ("Reduce attribute expected", Prev_Token_Ptr);
end if;
Set_Prefix (Attr_Node, S);
@@ -1360,9 +1360,7 @@ package body Ch4 is
procedure Box_Error is
begin
- if Ada_Version < Ada_2005 then
- Error_Msg_SC ("box in aggregate is an Ada 2005 extension");
- end if;
+ Error_Msg_Ada_2005_Extension ("'<'> in aggregate");
-- Ada 2005 (AI-287): The box notation is allowed only with named
-- notation because positional notation might be error prone. For
@@ -1580,17 +1578,13 @@ package body Ch4 is
-- Deal with others association first. This is a named association
if No (Expr_Node) then
- if No (Assoc_List) then
- Assoc_List := New_List;
- end if;
-
- Append (P_Record_Or_Array_Component_Association, Assoc_List);
+ Append_New (P_Record_Or_Array_Component_Association, Assoc_List);
-- Improper use of WITH
elsif Token = Tok_With then
Error_Msg_SC ("WITH must be preceded by single expression in " &
- "extension aggregate");
+ "extension aggregate");
raise Error_Resync;
-- Range attribute can only appear as part of a discrete choice list
@@ -1612,11 +1606,7 @@ package body Ch4 is
elsif Nkind (Expr_Node) in
N_Iterated_Component_Association | N_Iterated_Element_Association
then
- if No (Assoc_List) then
- Assoc_List := New_List (Expr_Node);
- else
- Append_To (Assoc_List, Expr_Node);
- end if;
+ Append_New (Expr_Node, Assoc_List);
elsif Token = Tok_Comma
or else Token = Tok_Right_Paren
@@ -1630,11 +1620,7 @@ package body Ch4 is
& "named association)");
end if;
- if No (Expr_List) then
- Expr_List := New_List;
- end if;
-
- Append (Expr_Node, Expr_List);
+ Append_New (Expr_Node, Expr_List);
-- Check for aggregate followed by left parent, maybe missing comma
@@ -1643,18 +1629,10 @@ package body Ch4 is
then
T_Comma;
- if No (Expr_List) then
- Expr_List := New_List;
- end if;
-
- Append (Expr_Node, Expr_List);
+ Append_New (Expr_Node, Expr_List);
elsif Token = Tok_Right_Bracket then
- if No (Expr_List) then
- Expr_List := New_List;
- end if;
-
- Append (Expr_Node, Expr_List);
+ Append_New (Expr_Node, Expr_List);
exit;
-- Anything else is assumed to be a named association
@@ -1662,11 +1640,7 @@ package body Ch4 is
else
Restore_Scan_State (Scan_State); -- to start of expression
- if No (Assoc_List) then
- Assoc_List := New_List;
- end if;
-
- Append (P_Record_Or_Array_Component_Association, Assoc_List);
+ Append_New (P_Record_Or_Array_Component_Association, Assoc_List);
end if;
exit when not Comma_Present;
@@ -1779,11 +1753,7 @@ package body Ch4 is
-- Ada 2005(AI-287): The box notation is used to indicate the
-- default initialization of aggregate components
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- ("component association with '<'> is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("component association with '<'>");
Set_Box_Present (Assoc_Node);
Scan; -- Past box
@@ -2958,10 +2928,7 @@ package body Ch4 is
Scan; -- past minus
when Tok_At_Sign => -- AI12-0125 : target_name
- if Ada_Version < Ada_2020 then
- Error_Msg_SC ("target name is an Ada 202x feature");
- Error_Msg_SC ("\compile with -gnat2020");
- end if;
+ Error_Msg_Ada_2020_Feature ("target name", Token_Ptr);
Node1 := P_Name;
return Node1;
@@ -3438,6 +3405,12 @@ package body Ch4 is
procedure Build_Iterated_Element_Association is
begin
+ -- Build loop_parameter_specification
+
+ Loop_Spec :=
+ New_Node (N_Loop_Parameter_Specification, Prev_Token_Ptr);
+ Set_Defining_Identifier (Loop_Spec, Id);
+
Choice := First (Discrete_Choices (Assoc_Node));
Assoc_Node :=
New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
@@ -3469,43 +3442,37 @@ package body Ch4 is
-- In addition, if "use" is present after the specification,
-- this is an Iterated_Element_Association that carries a
-- key_expression, and we generate the appropriate node.
- -- Finally, the Iterated_Element form is reserved for contwiner
+ -- Finally, the Iterated_Element form is reserved for container
-- aggregates, and is illegal in array aggregates.
Id := P_Defining_Identifier;
Assoc_Node :=
New_Node (N_Iterated_Component_Association, Prev_Token_Ptr);
- if Token = Tok_In then
+ if Token = Tok_In then
Set_Defining_Identifier (Assoc_Node, Id);
T_In;
Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List);
- -- The iterator may include a filter.
+ -- The iterator may include a filter
if Token = Tok_When then
Scan; -- past WHEN
Filter := P_Condition;
end if;
- -- Build loop_parameter specification.
-
- Loop_Spec :=
- New_Node (N_Loop_Parameter_Specification, Prev_Token_Ptr);
- Set_Defining_Identifier (Loop_Spec, Id);
-
if Token = Tok_Use then
-- Ada_2020 Key-expression is present, rewrite node as an
- -- iterated_Element_Awwoiation.
+ -- Iterated_Element_Association.
Scan; -- past USE
Build_Iterated_Element_Association;
Set_Key_Expression (Assoc_Node, P_Expression);
elsif Present (Filter) then
- -- A loop_Parameter_Specification also indicates an Ada_2020
- -- conwtruct, in contrast with a subtype indication used in
+ -- A loop_parameter_specification also indicates an Ada_2020
+ -- construct, in contrast with a subtype indication used in
-- array aggregates.
Build_Iterated_Element_Association;
@@ -3525,7 +3492,7 @@ package body Ch4 is
if Token = Tok_Use then
Scan; -- past USE
- -- This is an iterated_elenent_qssociation.
+ -- This is an iterated_element_association
Assoc_Node :=
New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
@@ -3537,10 +3504,7 @@ package body Ch4 is
Set_Expression (Assoc_Node, P_Expression);
end if;
- if Ada_Version < Ada_2020 then
- Error_Msg_SC ("iterated component is an Ada 202x feature");
- Error_Msg_SC ("\compile with -gnat2020");
- end if;
+ Error_Msg_Ada_2020_Feature ("iterated component", Token_Ptr);
return Assoc_Node;
end P_Iterated_Component_Association;
@@ -3725,9 +3689,7 @@ package body Ch4 is
Result : constant Node_Id :=
Make_Expression_With_Actions (Loc, Actions, Expression);
begin
- if Ada_Version < Ada_2020 then
- Error_Msg ("declare_expression is an Ada 2020 feature", Loc);
- end if;
+ Error_Msg_Ada_2020_Feature ("declare expression", Loc);
return Result;
end;
diff --git a/gcc/ada/par-ch5.adb b/gcc/ada/par-ch5.adb
index 5b002c4..a8d49b1 100644
--- a/gcc/ada/par-ch5.adb
+++ b/gcc/ada/par-ch5.adb
@@ -1306,14 +1306,16 @@ package body Ch5 is
-- syntax rule.
else
- if Style_Check and then Paren_Count (Cond) > 0 then
- if Nkind (Cond) not in N_If_Expression
- | N_Case_Expression
+ if Style_Check
+ and then
+ Paren_Count (Cond) >
+ (if Nkind (Cond) in N_Case_Expression
+ | N_If_Expression
| N_Quantified_Expression
- or else Paren_Count (Cond) > 1
- then
- Style.Check_Xtra_Parens (First_Sloc (Cond));
- end if;
+ then 1
+ else 0)
+ then
+ Style.Check_Xtra_Parens (First_Sloc (Cond));
end if;
-- And return the result
@@ -1712,9 +1714,9 @@ package body Ch5 is
Set_Discrete_Subtype_Definition
(Loop_Param_Specification_Node, P_Discrete_Subtype_Definition);
- if Ada_Version >= Ada_2020
- and then Token = Tok_When
- then
+ if Token = Tok_When then
+ Error_Msg_Ada_2020_Feature ("iterator filter", Token_Ptr);
+
Scan; -- past WHEN
Set_Iterator_Filter
(Loop_Param_Specification_Node, P_Condition);
@@ -1773,9 +1775,9 @@ package body Ch5 is
Set_Name (Node1, P_Name);
- if Ada_Version >= Ada_2020
- and then Token = Tok_When
- then
+ if Token = Tok_When then
+ Error_Msg_Ada_2020_Feature ("iterator filter", Token_Ptr);
+
Scan; -- past WHEN
Set_Iterator_Filter
(Node1, P_Condition);
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
index 622a508..145fbc4 100644
--- a/gcc/ada/par-ch6.adb
+++ b/gcc/ada/par-ch6.adb
@@ -426,11 +426,7 @@ package body Ch6 is
-- Ada 2005 (AI-318-02)
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SC
- ("anonymous access result type is an Ada 2005 extension");
- Error_Msg_SC ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("anonymous access result type");
Result_Node := P_Access_Definition (Result_Not_Null);
@@ -598,10 +594,7 @@ package body Ch6 is
-- Ada 2005 (AI-248): Parse a null procedure declaration
elsif Token = Tok_Null then
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("null procedures are an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("null procedure");
Scan; -- past NULL
@@ -1064,11 +1057,7 @@ package body Ch6 is
-- Ada 2005 (AI-318-02)
if Token = Tok_Access then
- if Ada_Version < Ada_2005 then
- Error_Msg_SC
- ("anonymous access result type is an Ada 2005 extension");
- Error_Msg_SC ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("anonymous access result type");
Result_Node := P_Access_Definition (Result_Not_Null);
@@ -1631,9 +1620,8 @@ package body Ch6 is
-- the time being.
elsif Token = Tok_With then
- if not Extensions_Allowed then
- Error_Msg_SP ("aspect on formal parameter requires -gnatX");
- end if;
+ Error_Msg_Ada_2020_Feature
+ ("aspect on formal parameter", Token_Ptr);
P_Aspect_Specifications (Specification_Node, False);
@@ -1650,7 +1638,6 @@ package body Ch6 is
elsif Token = Tok_Comma then
T_Semicolon;
- Scan; -- past comma
-- Special check for omitted separator
@@ -1771,7 +1758,8 @@ package body Ch6 is
--
-- EXTENDED_RETURN_STATEMENT ::=
-- return DEFINING_IDENTIFIER : [aliased] RETURN_SUBTYPE_INDICATION
- -- [:= EXPRESSION] [do
+ -- [:= EXPRESSION]
+ -- [ASPECT_SPECIFICATION] [do
-- HANDLED_SEQUENCE_OF_STATEMENTS
-- end return];
--
@@ -1917,6 +1905,7 @@ package body Ch6 is
Ret_Sloc : constant Source_Ptr := Token_Ptr;
Ret_Strt : constant Column_Number := Start_Column;
Ret_Node : Node_Id;
+ Decl : Node_Id;
-- Start of processing for P_Return_Statement
@@ -1949,15 +1938,15 @@ package body Ch6 is
-- Extended_return_statement (Ada 2005 only -- AI-318):
else
- if Ada_Version < Ada_2005 then
- Error_Msg_SP
- (" extended_return_statement is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("extended return statement");
Ret_Node := New_Node (N_Extended_Return_Statement, Ret_Sloc);
- Set_Return_Object_Declarations
- (Ret_Node, New_List (P_Return_Object_Declaration));
+ Decl := P_Return_Object_Declaration;
+ Set_Return_Object_Declarations (Ret_Node, New_List (Decl));
+
+ if Token = Tok_With then
+ P_Aspect_Specifications (Decl, False);
+ end if;
if Token = Tok_Do then
Push_Scope_Stack;
diff --git a/gcc/ada/par-ch9.adb b/gcc/ada/par-ch9.adb
index 2672e52..151656c 100644
--- a/gcc/ada/par-ch9.adb
+++ b/gcc/ada/par-ch9.adb
@@ -220,10 +220,7 @@ package body Ch9 is
if Token = Tok_New then
Scan; -- past NEW
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("task interface is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("task interface");
Set_Interface_List (Task_Node, New_List);
@@ -565,10 +562,7 @@ package body Ch9 is
if Token = Tok_New then
Scan; -- past NEW
- if Ada_Version < Ada_2005 then
- Error_Msg_SP ("protected interface is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
- end if;
+ Error_Msg_Ada_2005_Extension ("protected interface");
Set_Interface_List (Protected_Node, New_List);
@@ -758,8 +752,7 @@ package body Ch9 is
if Is_Overriding or else Not_Overriding then
if Ada_Version < Ada_2005 then
- Error_Msg_SP ("overriding indicator is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
+ Error_Msg_Ada_2005_Extension ("overriding indicator");
elsif Token = Tok_Entry then
Decl := P_Entry_Declaration;
@@ -910,7 +903,7 @@ package body Ch9 is
Resync_Past_Semicolon;
elsif Token in Token_Class_Declk then
- Error_Msg_SC ("this declaration not allowed in protected body");
+ Error_Msg_SC ("declaration not allowed in protected body");
Resync_Past_Semicolon;
else
@@ -968,9 +961,7 @@ package body Ch9 is
if Is_Overriding or else Not_Overriding then
if Ada_Version < Ada_2005 then
- Error_Msg_SP ("overriding indicator is an Ada 2005 extension");
- Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
-
+ Error_Msg_Ada_2005_Extension ("overriding indicator");
elsif Token /= Tok_Entry then
Error_Msg_SC -- CODEFIX
("ENTRY expected!");
@@ -1316,6 +1307,7 @@ package body Ch9 is
-- ENTRY_INDEX_SPECIFICATION ::=
-- for DEFINING_IDENTIFIER in DISCRETE_SUBTYPE_DEFINITION
+ -- [ASPECT_SPECIFICATION]
-- Error recovery: can raise Error_Resync
@@ -1329,6 +1321,11 @@ package body Ch9 is
T_In;
Set_Discrete_Subtype_Definition
(Iterator_Node, P_Discrete_Subtype_Definition);
+
+ if Token = Tok_With then
+ P_Aspect_Specifications (Iterator_Node, False);
+ end if;
+
return Iterator_Node;
end P_Entry_Index_Specification;
@@ -1654,7 +1651,7 @@ package body Ch9 is
if Ada_Version = Ada_83 then
Error_Msg_BC ("OR or ELSE expected");
else
- Error_Msg_BC ("OR or ELSE or THEN ABORT expected");
+ Error_Msg_BC ("OR or ELSE or `THEN ABORT` expected");
end if;
Select_Node := Error;
diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb
index a1857dc..ecd5404 100644
--- a/gcc/ada/par-load.adb
+++ b/gcc/ada/par-load.adb
@@ -318,7 +318,7 @@ begin
Spec_Name := Get_Parent_Spec_Name (Unit_Name (Cur_Unum));
- if Spec_Name /= No_Unit_Name then
+ if Present (Spec_Name) then
Unum :=
Load_Unit
(Load_Name => Spec_Name,
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 5783c33..51409f2 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -105,6 +105,9 @@ function Prag (Pragma_Node : Node_Id; Semi : Source_Ptr) return Node_Id is
-- No_Dependence must be processed at parse time, since otherwise it gets
-- handled too late.
--
+ -- No_Unrecognized_Aspects must be processed at parse time, since
+ -- unrecognized aspects are ignored by the parser.
+ --
-- Note that we don't need to do full error checking for badly formed cases
-- of restrictions, since these will be caught during semantic analysis.
@@ -259,6 +262,12 @@ function Prag (Pragma_Node : Node_Id; Semi : Source_Ptr) return Node_Id is
("??% restriction is obsolete and ignored, consider " &
"using 'S'P'A'R'K_'Mode and gnatprove instead", Arg);
+ when Name_No_Unrecognized_Aspects =>
+ Set_Restriction
+ (No_Unrecognized_Aspects,
+ Pragma_Node,
+ Prag_Id = Pragma_Restriction_Warnings);
+
when others =>
null;
end case;
diff --git a/gcc/ada/par-tchk.adb b/gcc/ada/par-tchk.adb
index 65ff45a..7a3ed5c 100644
--- a/gcc/ada/par-tchk.adb
+++ b/gcc/ada/par-tchk.adb
@@ -436,7 +436,6 @@ package body Tchk is
procedure T_Semicolon is
begin
-
if Token = Tok_Semicolon then
Scan;
diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb
index 4c3a154..95695d2 100644
--- a/gcc/ada/par.adb
+++ b/gcc/ada/par.adb
@@ -1546,6 +1546,10 @@ begin
end loop;
end;
+ if Config_Files_Store_Basename then
+ Complete_Source_File_Entry;
+ end if;
+
-- Normal case of compilation unit
else
diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
index dff3272..61912ef 100644
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -92,18 +92,6 @@ package body Repinfo is
Table_Increment => Alloc.Rep_Table_Increment,
Table_Name => "BE_Rep_Table");
- --------------------------------------------------------------
- -- Representation of Front-End Dynamic Size/Offset Entities --
- --------------------------------------------------------------
-
- package Dynamic_SO_Entity_Table is new Table.Table (
- Table_Component_Type => Entity_Id,
- Table_Index_Type => Nat,
- Table_Low_Bound => 1,
- Table_Initial => Alloc.Rep_Table_Initial,
- Table_Increment => Alloc.Rep_Table_Increment,
- Table_Name => "FE_Rep_Table");
-
Unit_Casing : Casing_Type;
-- Identifier casing for current unit. This is set by List_Rep_Info for
-- each unit, before calling subprograms which may read it.
@@ -138,11 +126,6 @@ package body Repinfo is
-- Local Subprograms --
-----------------------
- function Back_End_Layout return Boolean;
- -- Test for layout mode, True = back end, False = front end. This function
- -- is used rather than checking the configuration parameter because we do
- -- not want Repinfo to depend on Targparm.
-
procedure List_Entities
(Ent : Entity_Id;
Bytes_Big_Endian : Boolean;
@@ -218,18 +201,6 @@ package body Repinfo is
-- flag Paren is set, then the output is surrounded in parentheses if it is
-- other than a simple value.
- ---------------------
- -- Back_End_Layout --
- ---------------------
-
- function Back_End_Layout return Boolean is
- begin
- -- We have back-end layout if the back end has made any entries in the
- -- table of GCC expressions, otherwise we have front-end layout.
-
- return Rep_Table.Last > 0;
- end Back_End_Layout;
-
------------------------
-- Create_Discrim_Ref --
------------------------
@@ -241,16 +212,6 @@ package body Repinfo is
Op1 => Discriminant_Number (Discr));
end Create_Discrim_Ref;
- ---------------------------
- -- Create_Dynamic_SO_Ref --
- ---------------------------
-
- function Create_Dynamic_SO_Ref (E : Entity_Id) return Dynamic_SO_Ref is
- begin
- Dynamic_SO_Entity_Table.Append (E);
- return UI_From_Int (-Dynamic_SO_Entity_Table.Last);
- end Create_Dynamic_SO_Ref;
-
-----------------
-- Create_Node --
-----------------
@@ -279,33 +240,6 @@ package body Repinfo is
return Entity_Header_Num (Id mod Relevant_Entities_Size);
end Entity_Hash;
- ---------------------------
- -- Get_Dynamic_SO_Entity --
- ---------------------------
-
- function Get_Dynamic_SO_Entity (U : Dynamic_SO_Ref) return Entity_Id is
- begin
- return Dynamic_SO_Entity_Table.Table (-UI_To_Int (U));
- end Get_Dynamic_SO_Entity;
-
- -----------------------
- -- Is_Dynamic_SO_Ref --
- -----------------------
-
- function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean is
- begin
- return U < Uint_0;
- end Is_Dynamic_SO_Ref;
-
- ----------------------
- -- Is_Static_SO_Ref --
- ----------------------
-
- function Is_Static_SO_Ref (U : SO_Ref) return Boolean is
- begin
- return U >= Uint_0;
- end Is_Static_SO_Ref;
-
---------
-- lgx --
---------
@@ -1224,14 +1158,6 @@ package body Repinfo is
else
Write_Val (Esiz, Paren => not List_Representation_Info_To_JSON);
- -- If in front-end layout mode, then dynamic size is stored in
- -- storage units, so renormalize for output.
-
- if not Back_End_Layout then
- Write_Str (" * ");
- Write_Int (SSU);
- end if;
-
-- Add appropriate first bit offset
if not List_Representation_Info_To_JSON then
@@ -2397,11 +2323,7 @@ package body Repinfo is
Write_Char ('(');
end if;
- if Back_End_Layout then
- List_GCC_Expression (Val);
- else
- Write_Name_Decoded (Chars (Get_Dynamic_SO_Entity (Val)));
- end if;
+ List_GCC_Expression (Val);
if Paren then
Write_Char (')');
diff --git a/gcc/ada/repinfo.ads b/gcc/ada/repinfo.ads
index 6731dff..f730c53 100644
--- a/gcc/ada/repinfo.ads
+++ b/gcc/ada/repinfo.ads
@@ -45,28 +45,22 @@ package Repinfo is
-- the corresponding entities as constant non-negative integers,
-- and the Uint values are stored directly in these fields.
- -- For composite types, there are three cases:
+ -- For composite types, there are two cases:
-- 1. In some cases the front end knows the values statically,
-- for example in the case where representation clauses or
-- pragmas specify the values.
- -- 2. If Frontend_Layout is False, then the backend is responsible
- -- for layout of all types and objects not laid out by the
- -- front end. This includes all dynamic values, and also
- -- static values (e.g. record sizes) when not set by the
- -- front end.
-
- -- 3. If Frontend_Layout is True, then the front end lays out
- -- all data, according to target dependent size and alignment
- -- information, creating dynamic inlinable functions where
- -- needed in the case of sizes not known till runtime.
+ -- 2. Otherwise the backend is responsible for layout of all types and
+ -- objects not laid out by the front end. This includes all dynamic
+ -- values, and also static values (e.g. record sizes) when not set by
+ -- the front end.
-----------------------------
-- Back Annotation by Gigi --
-----------------------------
- -- The following interface is used by gigi if Frontend_Layout is False
+ -- The following interface is used by gigi
-- As part of the processing in gigi, the types are laid out and
-- appropriate values computed for the sizes and component positions
@@ -297,76 +291,6 @@ package Repinfo is
function Create_Discrim_Ref (Discr : Entity_Id) return Node_Ref;
-- Creates a reference to the discriminant whose entity is Discr
- --------------------------------------------------------
- -- Front-End Interface for Dynamic Size/Offset Values --
- --------------------------------------------------------
-
- -- If Frontend_Layout is True, then the front-end deals with all
- -- dynamic size and offset fields. There are two cases:
-
- -- 1. The value can be computed at the time of type freezing, and
- -- is stored in a run-time constant. In this case, the field
- -- contains a reference to this entity. In the case of sizes
- -- the value stored is the size in storage units, since dynamic
- -- sizes are always a multiple of storage units.
-
- -- 2. The size/offset depends on the value of discriminants at
- -- run-time. In this case, the front end builds a function to
- -- compute the value. This function has a single parameter
- -- which is the discriminated record object in question. Any
- -- references to discriminant values are simply references to
- -- the appropriate discriminant in this single argument, and
- -- to compute the required size/offset value at run time, the
- -- code generator simply constructs a call to the function
- -- with the appropriate argument. The size/offset field in
- -- this case contains a reference to the function entity.
- -- Note that as for case 1, if such a function is used to
- -- return a size, then the size in storage units is returned,
- -- not the size in bits.
-
- -- The interface here allows these created entities to be referenced
- -- using negative Unit values, so that they can be stored in the
- -- appropriate size and offset fields in the tree.
-
- -- In the case of components, if the location of the component is static,
- -- then all four fields (Component_Bit_Offset, Normalized_Position, Esize,
- -- and Normalized_First_Bit) are set to appropriate values. In the case of
- -- a non-static component location, Component_Bit_Offset is not used and
- -- is left set to Unknown. Normalized_Position and Normalized_First_Bit
- -- are set appropriately.
-
- subtype SO_Ref is Uint;
- -- Type used to represent a Uint value that represents a static or
- -- dynamic size/offset value (non-negative if static, negative if
- -- the size value is dynamic).
-
- subtype Dynamic_SO_Ref is Uint;
- -- Type used to represent a negative Uint value used to store
- -- a dynamic size/offset value.
-
- function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean;
- pragma Inline (Is_Dynamic_SO_Ref);
- -- Given a SO_Ref (Uint) value, returns True iff the SO_Ref value
- -- represents a dynamic Size/Offset value (i.e. it is negative).
-
- function Is_Static_SO_Ref (U : SO_Ref) return Boolean;
- pragma Inline (Is_Static_SO_Ref);
- -- Given a SO_Ref (Uint) value, returns True iff the SO_Ref value
- -- represents a static Size/Offset value (i.e. it is non-negative).
-
- function Create_Dynamic_SO_Ref (E : Entity_Id) return Dynamic_SO_Ref;
- -- Given the Entity_Id for a constant (case 1), the Node_Id for an
- -- expression (case 2), or the Entity_Id for a function (case 3),
- -- this function returns a (negative) Uint value that can be used
- -- to retrieve the entity or expression for later use.
-
- function Get_Dynamic_SO_Entity (U : Dynamic_SO_Ref) return Entity_Id;
- -- Retrieve the Node_Id or Entity_Id stored by a previous call to
- -- Create_Dynamic_SO_Ref. The approach is that the front end makes
- -- the necessary Create_Dynamic_SO_Ref calls to associate the node
- -- and entity id values and the back end makes Get_Dynamic_SO_Ref
- -- calls to retrieve them.
-
------------------------------
-- External tools Interface --
------------------------------
diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb
index 872ce01..6a0631f 100644
--- a/gcc/ada/rtsfind.adb
+++ b/gcc/ada/rtsfind.adb
@@ -423,7 +423,7 @@ package body Rtsfind is
(Unit_Name (Current_Sem_Unit));
begin
- if Parent_Name /= No_Unit_Name then
+ if Present (Parent_Name) then
Get_Name_String (Parent_Name);
declare
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 42578db..a690bb4 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -239,8 +239,6 @@ package Rtsfind is
System_Exp_Mod,
System_Exp_Uns,
System_Fat_Flt,
- System_Fat_IEEE_Long_Float,
- System_Fat_IEEE_Short_Float,
System_Fat_LFlt,
System_Fat_LLF,
System_Fat_SFlt,
@@ -249,14 +247,24 @@ package Rtsfind is
System_Fat_VAX_G_Float,
System_Finalization_Masters,
System_Finalization_Root,
- System_Fore,
+ System_Fore_Decimal_32,
+ System_Fore_Decimal_64,
+ System_Fore_Decimal_128,
+ System_Fore_Fixed_32,
+ System_Fore_Fixed_64,
+ System_Fore_Fixed_128,
+ System_Fore_Real,
System_Img_Bool,
System_Img_Char,
- System_Img_Dec,
+ System_Img_Decimal_32,
+ System_Img_Decimal_64,
+ System_Img_Decimal_128,
System_Img_Enum,
System_Img_Enum_New,
+ System_Img_Fixed_32,
+ System_Img_Fixed_64,
+ System_Img_Fixed_128,
System_Img_Int,
- System_Img_LLD,
System_Img_LLI,
System_Img_LLLI,
System_Img_LLU,
@@ -417,16 +425,22 @@ package Rtsfind is
System_Unsigned_Types,
System_Val_Bool,
System_Val_Char,
- System_Val_Dec,
+ System_Val_Decimal_32,
+ System_Val_Decimal_64,
+ System_Val_Decimal_128,
System_Val_Enum,
+ System_Val_Fixed_32,
+ System_Val_Fixed_64,
+ System_Val_Fixed_128,
+ System_Val_Flt,
System_Val_Int,
- System_Val_LLD,
+ System_Val_LFlt,
+ System_Val_LLF,
System_Val_LLI,
System_Val_LLLI,
System_Val_LLU,
System_Val_LLLU,
System_Val_Name,
- System_Val_Real,
System_Val_Uns,
System_Val_WChar,
System_Version_Control,
@@ -756,8 +770,10 @@ package Rtsfind is
RE_Subtract_With_Ovflo_Check64, -- System.Arith_64
RE_Add_With_Ovflo_Check128, -- System.Arith_128
+ RE_Double_Divide128, -- System.Arith_128
RE_Multiply_With_Ovflo_Check128, -- System.Arith_128
RE_Subtract_With_Ovflo_Check128, -- System.Arith_128
+ RE_Scaled_Divide128, -- System.Arith_128
RE_Create_AST_Handler, -- System.AST_Handling
@@ -909,18 +925,10 @@ package Rtsfind is
RE_Attr_Float, -- System.Fat_Flt
- RE_Attr_IEEE_Long, -- System.Fat_IEEE_Long_Float
- RE_Fat_IEEE_Long, -- System.Fat_IEEE_Long_Float
-
- RE_Attr_IEEE_Short, -- System.Fat_IEEE_Short_Float
- RE_Fat_IEEE_Short, -- System.Fat_IEEE_Short_Float
-
RE_Attr_Long_Float, -- System.Fat_LFlt
RE_Attr_Long_Long_Float, -- System.Fat_LLF
- RE_Attr_Short_Float, -- System.Fat_SFlt
-
RE_Attr_VAX_D_Float, -- System.Fat_VAX_D_Float
RE_Fat_VAX_D, -- System.Fat_VAX_D_Float
@@ -933,7 +941,6 @@ package Rtsfind is
RE_Add_Offset_To_Address, -- System.Finalization_Masters
RE_Attach, -- System.Finalization_Masters
RE_Base_Pool, -- System.Finalization_Masters
- RE_Detach, -- System.Finalization_Masters
RE_Finalization_Master, -- System.Finalization_Masters
RE_Finalization_Master_Ptr, -- System.Finalization_Masters
RE_Set_Base_Pool, -- System.Finalization_Masters
@@ -943,14 +950,30 @@ package Rtsfind is
RE_Root_Controlled, -- System.Finalization_Root
RE_Root_Controlled_Ptr, -- System.Finalization_Root
- RE_Fore, -- System.Fore
+ RE_Fore_Decimal32, -- System.Fore_Decimal_32
+
+ RE_Fore_Decimal64, -- System.Fore_Decimal_64
+
+ RE_Fore_Decimal128, -- System.Fore_Decimal_128
+
+ RE_Fore_Fixed32, -- System.Fore_Fixed_32
+
+ RE_Fore_Fixed64, -- System.Fore_Fixed_64
+
+ RE_Fore_Fixed128, -- System.Fore_Fixed_128
+
+ RE_Fore_Real, -- System.Fore_Real
RE_Image_Boolean, -- System.Img_Bool
RE_Image_Character, -- System.Img_Char
RE_Image_Character_05, -- System.Img_Char
- RE_Image_Decimal, -- System.Img_Dec
+ RE_Image_Decimal32, -- System.Img_Decimal_32
+
+ RE_Image_Decimal64, -- System.Img_Decimal_64
+
+ RE_Image_Decimal128, -- System.Img_Decimal_128
RE_Image_Enumeration_8, -- System.Img_Enum_New
RE_Image_Enumeration_16, -- System.Img_Enum_New
@@ -958,8 +981,6 @@ package Rtsfind is
RE_Image_Integer, -- System.Img_Int
- RE_Image_Long_Long_Decimal, -- System.Img_LLD
-
RE_Image_Long_Long_Integer, -- System.Img_LLI
RE_Image_Long_Long_Long_Integer, -- System.Img_LLLI
@@ -968,6 +989,10 @@ package Rtsfind is
RE_Image_Long_Long_Long_Unsigned, -- System.Img_LLLU
+ RE_Image_Fixed32, -- System.Img_Fixed_32
+ RE_Image_Fixed64, -- System.Img_Fixed_64
+ RE_Image_Fixed128, -- System.Img_Fixed_128
+
RE_Image_Ordinary_Fixed_Point, -- System.Img_Real
RE_Image_Floating_Point, -- System.Img_Real
@@ -1835,6 +1860,8 @@ package Rtsfind is
RE_I_LI, -- System.Stream_Attributes
RE_I_LLF, -- System.Stream_Attributes
RE_I_LLI, -- System.Stream_Attributes
+ RE_I_LLLI, -- System.Stream_Attributes
+ RE_I_LLLU, -- System.Stream_Attributes
RE_I_LLU, -- System.Stream_Attributes
RE_I_LU, -- System.Stream_Attributes
RE_I_SF, -- System.Stream_Attributes
@@ -1858,6 +1885,8 @@ package Rtsfind is
RE_W_LI, -- System.Stream_Attributes
RE_W_LLF, -- System.Stream_Attributes
RE_W_LLI, -- System.Stream_Attributes
+ RE_W_LLLI, -- System.Stream_Attributes
+ RE_W_LLLU, -- System.Stream_Attributes
RE_W_LLU, -- System.Stream_Attributes
RE_W_LU, -- System.Stream_Attributes
RE_W_SF, -- System.Stream_Attributes
@@ -1991,15 +2020,29 @@ package Rtsfind is
RE_Value_Character, -- System.Val_Char
- RE_Value_Decimal, -- System.Val_Dec
+ RE_Value_Decimal32, -- System_Val_Decimal_32
+
+ RE_Value_Decimal64, -- System_Val_Decimal_64
+
+ RE_Value_Decimal128, -- System_Val_Decimal_128
RE_Value_Enumeration_8, -- System.Val_Enum
RE_Value_Enumeration_16, -- System.Val_Enum
RE_Value_Enumeration_32, -- System.Val_Enum
+ RE_Value_Fixed32, -- System_Val_Fixed_32
+
+ RE_Value_Fixed64, -- System_Val_Fixed_64
+
+ RE_Value_Fixed128, -- System_Val_Fixed_128
+
+ RE_Value_Float, -- System_Val_Flt
+
RE_Value_Integer, -- System.Val_Int
- RE_Value_Long_Long_Decimal, -- System.Val_LLD
+ RE_Value_Long_Float, -- System_Val_LFlt
+
+ RE_Value_Long_Long_Float, -- System_Val_LLF
RE_Value_Long_Long_Integer, -- System.Val_LLI
@@ -2009,8 +2052,6 @@ package Rtsfind is
RE_Value_Long_Long_Long_Unsigned, -- System.Val_LLLU
- RE_Value_Real, -- System.Val_Real
-
RE_Value_Unsigned, -- System.Val_Uns
RE_Value_Wide_Character, -- System.Val_WChar
@@ -2403,8 +2444,10 @@ package Rtsfind is
RE_Subtract_With_Ovflo_Check64 => System_Arith_64,
RE_Add_With_Ovflo_Check128 => System_Arith_128,
+ RE_Double_Divide128 => System_Arith_128,
RE_Multiply_With_Ovflo_Check128 => System_Arith_128,
RE_Subtract_With_Ovflo_Check128 => System_Arith_128,
+ RE_Scaled_Divide128 => System_Arith_128,
RE_Create_AST_Handler => System_AST_Handling,
@@ -2562,18 +2605,10 @@ package Rtsfind is
RE_Attr_Float => System_Fat_Flt,
- RE_Attr_IEEE_Long => System_Fat_IEEE_Long_Float,
- RE_Fat_IEEE_Long => System_Fat_IEEE_Long_Float,
-
- RE_Attr_IEEE_Short => System_Fat_IEEE_Short_Float,
- RE_Fat_IEEE_Short => System_Fat_IEEE_Short_Float,
-
RE_Attr_Long_Float => System_Fat_LFlt,
RE_Attr_Long_Long_Float => System_Fat_LLF,
- RE_Attr_Short_Float => System_Fat_SFlt,
-
RE_Attr_VAX_D_Float => System_Fat_VAX_D_Float,
RE_Fat_VAX_D => System_Fat_VAX_D_Float,
@@ -2586,7 +2621,6 @@ package Rtsfind is
RE_Add_Offset_To_Address => System_Finalization_Masters,
RE_Attach => System_Finalization_Masters,
RE_Base_Pool => System_Finalization_Masters,
- RE_Detach => System_Finalization_Masters,
RE_Finalization_Master => System_Finalization_Masters,
RE_Finalization_Master_Ptr => System_Finalization_Masters,
RE_Set_Base_Pool => System_Finalization_Masters,
@@ -2596,14 +2630,30 @@ package Rtsfind is
RE_Root_Controlled => System_Finalization_Root,
RE_Root_Controlled_Ptr => System_Finalization_Root,
- RE_Fore => System_Fore,
+ RE_Fore_Decimal32 => System_Fore_Decimal_32,
+
+ RE_Fore_Decimal64 => System_Fore_Decimal_64,
+
+ RE_Fore_Decimal128 => System_Fore_Decimal_128,
+
+ RE_Fore_Fixed32 => System_Fore_Fixed_32,
+
+ RE_Fore_Fixed64 => System_Fore_Fixed_64,
+
+ RE_Fore_Fixed128 => System_Fore_Fixed_128,
+
+ RE_Fore_Real => System_Fore_Real,
RE_Image_Boolean => System_Img_Bool,
RE_Image_Character => System_Img_Char,
RE_Image_Character_05 => System_Img_Char,
- RE_Image_Decimal => System_Img_Dec,
+ RE_Image_Decimal32 => System_Img_Decimal_32,
+
+ RE_Image_Decimal64 => System_Img_Decimal_64,
+
+ RE_Image_Decimal128 => System_Img_Decimal_128,
RE_Image_Enumeration_8 => System_Img_Enum_New,
RE_Image_Enumeration_16 => System_Img_Enum_New,
@@ -2611,8 +2661,6 @@ package Rtsfind is
RE_Image_Integer => System_Img_Int,
- RE_Image_Long_Long_Decimal => System_Img_LLD,
-
RE_Image_Long_Long_Integer => System_Img_LLI,
RE_Image_Long_Long_Long_Integer => System_Img_LLLI,
@@ -2621,6 +2669,10 @@ package Rtsfind is
RE_Image_Long_Long_Long_Unsigned => System_Img_LLLU,
+ RE_Image_Fixed32 => System_Img_Fixed_32,
+ RE_Image_Fixed64 => System_Img_Fixed_64,
+ RE_Image_Fixed128 => System_Img_Fixed_128,
+
RE_Image_Ordinary_Fixed_Point => System_Img_Real,
RE_Image_Floating_Point => System_Img_Real,
@@ -3488,6 +3540,8 @@ package Rtsfind is
RE_I_LI => System_Stream_Attributes,
RE_I_LLF => System_Stream_Attributes,
RE_I_LLI => System_Stream_Attributes,
+ RE_I_LLLI => System_Stream_Attributes,
+ RE_I_LLLU => System_Stream_Attributes,
RE_I_LLU => System_Stream_Attributes,
RE_I_LU => System_Stream_Attributes,
RE_I_SF => System_Stream_Attributes,
@@ -3511,6 +3565,8 @@ package Rtsfind is
RE_W_LI => System_Stream_Attributes,
RE_W_LLF => System_Stream_Attributes,
RE_W_LLI => System_Stream_Attributes,
+ RE_W_LLLI => System_Stream_Attributes,
+ RE_W_LLLU => System_Stream_Attributes,
RE_W_LLU => System_Stream_Attributes,
RE_W_LU => System_Stream_Attributes,
RE_W_SF => System_Stream_Attributes,
@@ -3644,15 +3700,29 @@ package Rtsfind is
RE_Value_Character => System_Val_Char,
- RE_Value_Decimal => System_Val_Dec,
+ RE_Value_Decimal32 => System_Val_Decimal_32,
+
+ RE_Value_Decimal64 => System_Val_Decimal_64,
+
+ RE_Value_Decimal128 => System_Val_Decimal_128,
RE_Value_Enumeration_8 => System_Val_Enum,
RE_Value_Enumeration_16 => System_Val_Enum,
RE_Value_Enumeration_32 => System_Val_Enum,
+ RE_Value_Fixed32 => System_Val_Fixed_32,
+
+ RE_Value_Fixed64 => System_Val_Fixed_64,
+
+ RE_Value_Fixed128 => System_Val_Fixed_128,
+
+ RE_Value_Float => System_Val_Flt,
+
RE_Value_Integer => System_Val_Int,
- RE_Value_Long_Long_Decimal => System_Val_LLD,
+ RE_Value_Long_Float => System_Val_LFlt,
+
+ RE_Value_Long_Long_Float => System_Val_LLF,
RE_Value_Long_Long_Integer => System_Val_LLI,
@@ -3662,8 +3732,6 @@ package Rtsfind is
RE_Value_Long_Long_Long_Unsigned => System_Val_LLLU,
- RE_Value_Real => System_Val_Real,
-
RE_Value_Unsigned => System_Val_Uns,
RE_Value_Wide_Character => System_Val_WChar,
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index e3e5bc2..582c35e 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -724,6 +724,41 @@ CNU(CRTSCTS, "Output hw flow control")
#endif
CNU(CREAD, "Read")
+#ifndef ICANON
+# define ICANON -1
+#endif
+CNU(ICANON, "canonical mode")
+
+#ifndef CBAUD
+# define CBAUD -1
+#endif
+CNU(CBAUD, "baud speed mask")
+
+#ifndef ECHO
+# define ECHO -1
+#endif
+CNU(ECHO, "echo input characters")
+
+#ifndef ECHOE
+# define ECHOE -1
+#endif
+CNU(ECHOE, "erase preceding characters")
+
+#ifndef ECHOK
+# define ECHOK -1
+#endif
+CNU(ECHOK, "kill character, erases current line")
+
+#ifndef ECHOCTL
+# define ECHOCTL -1
+#endif
+CNU(ECHOCTL, "echo special characters")
+
+#ifndef ECHONL
+# define ECHONL -1
+#endif
+CNU(ECHONL, "force echo NL character")
+
#ifndef CS5
# define CS5 -1
#endif
@@ -1739,6 +1774,9 @@ CND(SIZEOF_sigset, "sigset")
#if defined(_WIN32) || defined(__vxworks)
#define SIZEOF_nfds_t sizeof (int) * 8
#define SIZEOF_socklen_t sizeof (size_t)
+#elif defined(__Lynx__)
+#define SIZEOF_nfds_t sizeof (unsigned long int) * 8
+#define SIZEOF_socklen_t sizeof (socklen_t)
#else
#define SIZEOF_nfds_t sizeof (nfds_t) * 8
#define SIZEOF_socklen_t sizeof (socklen_t)
diff --git a/gcc/ada/sa_messages.ads b/gcc/ada/sa_messages.ads
index 11da9fc..1f6fca8 100644
--- a/gcc/ada/sa_messages.ads
+++ b/gcc/ada/sa_messages.ads
@@ -94,7 +94,7 @@ package SA_Messages is
-- type invariant checks (specific and class-wide), and checks for
-- implementation-defined assertions such as Assert_And_Cut, Assume,
-- Contract_Cases, Default_Initial_Condition, Initial_Condition,
- -- Loop_Invariant, Loop_Variant, and Refined_Post.
+ -- Loop_Invariant, Loop_Variant, Refined_Post, and Subprogram_Variant.
--
-- TBD: it might be nice to distinguish these different kinds of assertions
-- as is done in SPARK's VC_Kind enumeration type, but any distinction
diff --git a/gcc/ada/scng.adb b/gcc/ada/scng.adb
index 0d5cff8..df6a689 100644
--- a/gcc/ada/scng.adb
+++ b/gcc/ada/scng.adb
@@ -25,6 +25,7 @@
with Atree; use Atree;
with Csets; use Csets;
+with Errout; use Errout;
with Hostparm; use Hostparm;
with Namet; use Namet;
with Opt; use Opt;
@@ -1299,19 +1300,15 @@ package body Scng is
return;
end if;
- when '@' =>
- if Ada_Version < Ada_2020 then
- Error_Msg ("target_name is an Ada 202x feature", Scan_Ptr);
- Scan_Ptr := Scan_Ptr + 1;
+ -- AI12-0125-03 : @ is target_name
- else
- -- AI12-0125-03 : @ is target_name
+ when '@' =>
+ Error_Msg_Ada_2020_Feature ("target name", Token_Ptr);
- Accumulate_Checksum ('@');
- Scan_Ptr := Scan_Ptr + 1;
- Token := Tok_At_Sign;
- return;
- end if;
+ Accumulate_Checksum ('@');
+ Scan_Ptr := Scan_Ptr + 1;
+ Token := Tok_At_Sign;
+ return;
-- Asterisk (can be multiplication operator or double asterisk which
-- is the exponentiation compound delimiter).
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index fdc27b3..b94f369 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -452,7 +452,7 @@ package body Sem_Aggr is
This_Range : constant Node_Id := Aggregate_Bounds (N);
-- The aggregate range node of this specific sub-aggregate
- This_Low : constant Node_Id := Low_Bound (Aggregate_Bounds (N));
+ This_Low : constant Node_Id := Low_Bound (Aggregate_Bounds (N));
This_High : constant Node_Id := High_Bound (Aggregate_Bounds (N));
-- The aggregate bounds of this specific sub-aggregate
@@ -785,7 +785,7 @@ package body Sem_Aggr is
-----------------------
procedure Resolve_Aggregate (N : Node_Id; Typ : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (N);
+ Loc : constant Source_Ptr := Sloc (N);
Aggr_Subtyp : Entity_Id;
-- The actual aggregate subtype. This is not necessarily the same as Typ
@@ -816,6 +816,8 @@ package body Sem_Aggr is
return False;
end Within_Aggregate;
+ -- Start of processing for Resolve_Aggregate
+
begin
-- Ignore junk empty aggregate resulting from parser error
@@ -1588,12 +1590,39 @@ package body Sem_Aggr is
Index_Typ : Entity_Id)
is
Loc : constant Source_Ptr := Sloc (N);
+ Id : constant Entity_Id := Defining_Identifier (N);
+
+ -----------------------
+ -- Remove_References --
+ -----------------------
+
+ function Remove_Ref (N : Node_Id) return Traverse_Result;
+ -- Remove references to the entity Id after analysis, so it can be
+ -- properly reanalyzed after construct is expanded into a loop.
+
+ function Remove_Ref (N : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (N) = N_Identifier
+ and then Present (Entity (N))
+ and then Entity (N) = Id
+ then
+ Set_Entity (N, Empty);
+ Set_Etype (N, Empty);
+ end if;
+ Set_Analyzed (N, False);
+ return OK;
+ end Remove_Ref;
+
+ procedure Remove_References is new Traverse_Proc (Remove_Ref);
+
+ -- Local variables
Choice : Node_Id;
Dummy : Boolean;
Ent : Entity_Id;
Expr : Node_Id;
- Id : Entity_Id;
+
+ -- Start of processing for Resolve_Iterated_Component_Association
begin
-- An element iterator specification cannot appear in
@@ -1646,26 +1675,31 @@ package body Sem_Aggr is
-- The expression has to be analyzed once the index variable is
-- directly visible.
- Id := Defining_Identifier (N);
Enter_Name (Id);
Set_Etype (Id, Index_Typ);
Set_Ekind (Id, E_Variable);
Set_Scope (Id, Ent);
- -- Analyze a copy of the expression, to verify legality. We use
- -- a copy because the expression will be analyzed anew when the
- -- enclosing aggregate is expanded, and the construct is rewritten
- -- as a loop with a new index variable.
+ -- Analyze expression without expansion, to verify legality.
+ -- When generating code, we then remove references to the index
+ -- variable, because the expression will be analyzed anew after
+ -- rewritting as a loop with a new index variable; when not
+ -- generating code we leave the analyzed expression as it is.
+
+ Expr := Expression (N);
- Expr := New_Copy_Tree (Expression (N));
- Set_Parent (Expr, N);
- Dummy := Resolve_Aggr_Expr (Expr, False);
+ Expander_Mode_Save_And_Set (False);
+ Dummy := Resolve_Aggr_Expr (Expr, Single_Elmt => False);
+ Expander_Mode_Restore;
+
+ if Operating_Mode /= Check_Semantics then
+ Remove_References (Expr);
+ end if;
-- An iterated_component_association may appear in a nested
-- aggregate for a multidimensional structure: preserve the bounds
-- computed for the expression, as well as the anonymous array
-- type generated for it; both are needed during array expansion.
- -- This does not work for more than two levels of nesting. ???
if Nkind (Expr) = N_Aggregate then
Set_Aggregate_Bounds (Expression (N), Aggregate_Bounds (Expr));
@@ -1836,10 +1870,15 @@ package body Sem_Aggr is
-- Test for the validity of an others choice if present
if Others_Present and then not Others_Allowed then
- Error_Msg_N
- ("OTHERS choice not allowed here",
- First (Choice_List (First (Component_Associations (N)))));
- return Failure;
+ declare
+ Others_N : constant Node_Id :=
+ First (Choice_List (First (Component_Associations (N))));
+ begin
+ Error_Msg_N ("OTHERS choice not allowed here", Others_N);
+ Error_Msg_N ("\qualify the aggregate with a constrained subtype "
+ & "to provide bounds for it", Others_N);
+ return Failure;
+ end;
end if;
-- Protect against cascaded errors
@@ -2572,7 +2611,7 @@ package body Sem_Aggr is
-- In order to diagnose the semantic error we create a duplicate
-- tree to analyze it and perform the check.
- else
+ elsif Nkind (Assoc) /= N_Iterated_Component_Association then
declare
Save_Analysis : constant Boolean := Full_Analysis;
Expr : constant Node_Id :=
@@ -2910,7 +2949,7 @@ package body Sem_Aggr is
while Present (Choice) loop
Analyze_And_Resolve (Choice, Key_Type);
if not Is_Static_Expression (Choice) then
- Error_Msg_N ("Choice must be static", Choice);
+ Error_Msg_N ("choice must be static", Choice);
end if;
Next (Choice);
@@ -2955,7 +2994,7 @@ package body Sem_Aggr is
if Present (Component_Associations (N)) then
if Present (Expressions (N)) then
- Error_Msg_N ("Container aggregate cannot be "
+ Error_Msg_N ("container aggregate cannot be "
& "both positional and named", N);
return;
end if;
@@ -2996,10 +3035,7 @@ package body Sem_Aggr is
Base : constant Node_Id := Expression (N);
begin
- if Ada_Version < Ada_2020 then
- Error_Msg_N ("delta_aggregate is an Ada 202x feature", N);
- Error_Msg_N ("\compile with -gnat2020", N);
- end if;
+ Error_Msg_Ada_2020_Feature ("delta aggregate", Sloc (N));
if not Is_Composite_Type (Typ) then
Error_Msg_N ("not a composite type", N);
@@ -3026,6 +3062,7 @@ package body Sem_Aggr is
Assoc : Node_Id;
Choice : Node_Id;
+ Expr : Node_Id;
begin
Assoc := First (Deltas);
@@ -3035,7 +3072,11 @@ package body Sem_Aggr is
while Present (Choice) loop
if Nkind (Choice) = N_Others_Choice then
Error_Msg_N
- ("others not allowed in delta aggregate", Choice);
+ ("OTHERS not allowed in delta aggregate", Choice);
+
+ elsif Nkind (Choice) = N_Subtype_Indication then
+ Resolve_Discrete_Subtype_Indication
+ (Choice, Base_Type (Index_Type));
else
Analyze_And_Resolve (Choice, Index_Type);
@@ -3062,36 +3103,43 @@ package body Sem_Aggr is
end if;
Enter_Name (Id);
- Analyze_And_Resolve
- (New_Copy_Tree (Expression (Assoc)), Component_Type (Typ));
+ -- Resolve a copy of the expression, after setting
+ -- its parent properly to preserve its context.
+
+ Expr := New_Copy_Tree (Expression (Assoc));
+ Set_Parent (Expr, Assoc);
+ Analyze_And_Resolve (Expr, Component_Type (Typ));
End_Scope;
end;
else
Choice := First (Choice_List (Assoc));
while Present (Choice) loop
+ Analyze (Choice);
+
if Nkind (Choice) = N_Others_Choice then
Error_Msg_N
- ("others not allowed in delta aggregate", Choice);
+ ("OTHERS not allowed in delta aggregate", Choice);
- else
- Analyze (Choice);
+ elsif Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ then
+ -- Choice covers a range of values
- if Is_Entity_Name (Choice)
- and then Is_Type (Entity (Choice))
+ if Base_Type (Entity (Choice)) /=
+ Base_Type (Index_Type)
then
- -- Choice covers a range of values
-
- if Base_Type (Entity (Choice)) /=
- Base_Type (Index_Type)
- then
- Error_Msg_NE
- ("choice does mat match index type of",
- Choice, Typ);
- end if;
- else
- Resolve (Choice, Index_Type);
+ Error_Msg_NE
+ ("choice does not match index type of &",
+ Choice, Typ);
end if;
+
+ elsif Nkind (Choice) = N_Subtype_Indication then
+ Resolve_Discrete_Subtype_Indication
+ (Choice, Base_Type (Index_Type));
+
+ else
+ Resolve (Choice, Index_Type);
end if;
Next (Choice);
@@ -3458,10 +3506,23 @@ package body Sem_Aggr is
if Is_Entity_Name (A) and then Is_Type (Entity (A)) then
- -- AI05-0115: if the ancestor part is a subtype mark, the ancestor
- -- must not have unknown discriminants.
-
- if Has_Unknown_Discriminants (Entity (A)) then
+ -- AI05-0115: If the ancestor part is a subtype mark, the ancestor
+ -- must not have unknown discriminants. To catch cases where the
+ -- aggregate occurs at a place where the full view of the ancestor
+ -- type is visible and doesn't have unknown discriminants, but the
+ -- aggregate type was derived from a partial view that has unknown
+ -- discriminants, we check whether the aggregate type has unknown
+ -- discriminants (unknown discriminants were inherited), along
+ -- with checking that the partial view of the ancestor has unknown
+ -- discriminants. (It might be sufficient to replace the entire
+ -- condition with Has_Unknown_Discriminants (Typ), but that might
+ -- miss some cases, not clear, and causes error changes in some tests
+ -- such as class-wide cases, that aren't clearly improvements. ???)
+
+ if Has_Unknown_Discriminants (Entity (A))
+ or else (Has_Unknown_Discriminants (Typ)
+ and then Partial_View_Has_Unknown_Discr (Entity (A)))
+ then
Error_Msg_NE
("aggregate not available for type& whose ancestor "
& "has unknown discriminants", N, Typ);
@@ -3651,9 +3712,10 @@ package body Sem_Aggr is
--
-- This variable is updated as a side effect of function Get_Value.
- Box_Node : Node_Id := Empty;
- Is_Box_Present : Boolean := False;
- Others_Box : Natural := 0;
+ Box_Node : Node_Id := Empty;
+ Is_Box_Present : Boolean := False;
+ Is_Box_Init_By_Default : Boolean := False;
+ Others_Box : Natural := 0;
-- Ada 2005 (AI-287): Variables used in case of default initialization
-- to provide a functionality similar to Others_Etype. Box_Present
-- indicates that the component takes its default initialization;
@@ -3778,6 +3840,14 @@ package body Sem_Aggr is
Choices => Choice_List,
Expression => Expr,
Box_Present => Is_Box_Present));
+
+ -- If this association has a box for a component that is initialized
+ -- by default, then set flag on the new association to indicate that
+ -- the original association was for such a box-initialized component.
+
+ if Is_Box_Init_By_Default then
+ Set_Was_Default_Init_Box_Association (Last (Assoc_List));
+ end if;
end Add_Association;
-----------------------------
@@ -3995,6 +4065,7 @@ package body Sem_Aggr is
begin
Is_Box_Present := False;
+ Is_Box_Init_By_Default := False;
if No (From) then
return Empty;
@@ -4990,6 +5061,11 @@ package body Sem_Aggr is
Ctyp : constant Entity_Id := Etype (Component);
begin
+ -- Initially assume that the box is for a default-initialized
+ -- component and reset to False in cases where that's not true.
+
+ Is_Box_Init_By_Default := True;
+
-- If there is a default expression for the aggregate, copy
-- it into a new association. This copy must modify the scopes
-- of internal types that may be attached to the expression
@@ -5013,6 +5089,11 @@ package body Sem_Aggr is
and then Nkind (Parent (Component)) = N_Component_Declaration
and then Present (Expression (Parent (Component)))
then
+ -- If component declaration has an initialization expression
+ -- then this is not a case of default initialization.
+
+ Is_Box_Init_By_Default := False;
+
Expr :=
New_Copy_Tree_And_Copy_Dimensions
(Expression (Parent (Component)),
@@ -5303,7 +5384,7 @@ package body Sem_Aggr is
("OTHERS must represent at least one component", Selectr);
elsif Others_Box = 1 and then Warn_On_Redundant_Constructs then
- Error_Msg_N ("others choice is redundant?", Box_Node);
+ Error_Msg_N ("OTHERS choice is redundant?", Box_Node);
Error_Msg_N
("\previous choices cover all components?", Box_Node);
end if;
@@ -5470,7 +5551,7 @@ package body Sem_Aggr is
-- because the association may be a null array range.
Error_Msg_N
- ("(Ada 2005) null not allowed in null-excluding component??", Expr);
+ ("(Ada 2005) NULL not allowed in null-excluding component??", Expr);
Error_Msg_N
("\Constraint_Error will be raised at run time??", Expr);
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index e361601..e4537e4 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -227,9 +227,11 @@ package body Sem_Attr is
procedure Analyze_Attribute (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Aname : constant Name_Id := Attribute_Name (N);
- P : constant Node_Id := Prefix (N);
Exprs : constant List_Id := Expressions (N);
Attr_Id : constant Attribute_Id := Get_Attribute_Id (Aname);
+ P_Old : constant Node_Id := Prefix (N);
+
+ P : Node_Id := P_Old;
E1 : Node_Id;
E2 : Node_Id;
@@ -348,7 +350,7 @@ package body Sem_Attr is
procedure Check_Floating_Point_Type_2;
-- Verify that prefix of attribute N is a float type and that
- -- two attribute expressions are present
+ -- two attribute expressions are present.
procedure Check_Integer_Type;
-- Verify that prefix of attribute N is an integer type
@@ -420,9 +422,11 @@ package body Sem_Attr is
-- no arguments is used when the caller has already generated the
-- required error messages.
- procedure Error_Attr_P (Msg : String);
+ procedure Error_Attr_P (Msg : String; Msg_Cont : String := "");
pragma No_Return (Error_Attr_P);
- -- Like Error_Attr, but error is posted at the start of the prefix
+ -- Like Error_Attr, but error is posted at the start of the prefix. The
+ -- second message Msg_Cont is useful to issue a continuation message
+ -- before raising Bad_Attribute.
procedure Legal_Formal_Attribute;
-- Common processing for attributes Definite and Has_Discriminants.
@@ -780,6 +784,13 @@ package body Sem_Attr is
Par : Node_Id;
begin
+ -- If N does not come from source, the reference is assumed to be
+ -- valid.
+
+ if not Comes_From_Source (N) then
+ return True;
+ end if;
+
Par := Parent (N);
while Present (Par)
and then
@@ -1030,9 +1041,7 @@ package body Sem_Attr is
-- expression comes from source, e.g. when a single component
-- association in an aggregate has a box association.
- elsif Ada_Version >= Ada_2005
- and then OK_Self_Reference
- then
+ elsif Ada_Version >= Ada_2005 and then OK_Self_Reference then
null;
-- OK if reference to current instance of a protected object
@@ -1460,7 +1469,7 @@ package body Sem_Attr is
if Ada_Version < Ada_2020
and then not Is_Scalar_Type (Image_Type)
then
- Error_Msg_Ada_2020_Feature ("|nonscalar ''Image", Sloc (P));
+ Error_Msg_Ada_2020_Feature ("nonscalar ''Image", Sloc (P));
Error_Attr;
end if;
end Check_Image_Type;
@@ -1654,7 +1663,7 @@ package body Sem_Attr is
----------------------
procedure Check_Array_Type is
- D : Int;
+ D : Pos;
-- Dimension number for array attributes
begin
@@ -1739,9 +1748,7 @@ package body Sem_Attr is
("expression for dimension must be static!", E1);
Error_Attr;
- elsif UI_To_Int (Expr_Value (E1)) > D
- or else UI_To_Int (Expr_Value (E1)) < 1
- then
+ elsif Expr_Value (E1) > D or else Expr_Value (E1) < 1 then
Error_Attr ("invalid dimension number for array type", E1);
end if;
end if;
@@ -1831,7 +1838,7 @@ package body Sem_Attr is
-- Case of an expression
- Resolve (P);
+ Resolve (P_Old);
if Is_Access_Type (P_Type) then
@@ -1847,12 +1854,12 @@ package body Sem_Attr is
Freeze_Before (N, Designated_Type (P_Type));
end if;
- Rewrite (P,
- Make_Explicit_Dereference (Sloc (P),
- Prefix => Relocate_Node (P)));
+ Rewrite (P_Old,
+ Make_Explicit_Dereference (Sloc (P_Old),
+ Prefix => Relocate_Node (P_Old)));
- Analyze_And_Resolve (P);
- P_Type := Etype (P);
+ Analyze_And_Resolve (P_Old);
+ P_Type := Etype (P_Old);
if P_Type = Any_Type then
raise Bad_Attribute;
@@ -2690,10 +2697,13 @@ package body Sem_Attr is
-- Error_Attr_P --
------------------
- procedure Error_Attr_P (Msg : String) is
+ procedure Error_Attr_P (Msg : String; Msg_Cont : String := "") is
begin
Error_Msg_Name_1 := Aname;
Error_Msg_F (Msg, P);
+ if Msg_Cont /= "" then
+ Error_Msg_F (Msg_Cont, P);
+ end if;
Error_Attr;
end Error_Attr_P;
@@ -2842,7 +2852,10 @@ package body Sem_Attr is
and then Attr_Id = Attribute_Old
then " or be eligible for conditional evaluation"
& " (RM 6.1.1 (27))"
- else ""));
+ else ""),
+ Msg_Cont =>
+ "\using pragma Unevaluated_Use_Of_Old (Allow) will make "
+ & "this legal");
when 'W' =>
Error_Msg_Name_1 := Aname;
@@ -3091,6 +3104,15 @@ package body Sem_Attr is
end if;
end if;
+ -- If the prefix was rewritten as a raise node, then rewrite N as a
+ -- raise node, to avoid creating inconsistent trees. We still need to
+ -- perform legality checks on the original tree.
+
+ if Nkind (P) in N_Raise_xxx_Error then
+ Rewrite (N, Relocate_Node (P));
+ P := Original_Node (P_Old);
+ end if;
+
-- Remaining processing depends on attribute
case Attr_Id is
@@ -3151,7 +3173,10 @@ package body Sem_Attr is
-- Adjacent --
--------------
- when Attribute_Adjacent =>
+ when Attribute_Adjacent
+ | Attribute_Copy_Sign
+ | Attribute_Remainder
+ =>
Check_Floating_Point_Type_2;
Set_Etype (N, P_Base_Type);
Resolve (E1, P_Base_Type);
@@ -3273,7 +3298,7 @@ package body Sem_Attr is
Check_E0;
if not Is_Object_Reference (P) then
- Error_Attr_P ("prefix for % attribute must be object");
+ Error_Attr_P ("prefix of % attribute must be object");
-- What about the access object cases ???
@@ -3342,7 +3367,9 @@ package body Sem_Attr is
-- Callable --
--------------
- when Attribute_Callable =>
+ when Attribute_Callable
+ | Attribute_Terminated
+ =>
Check_E0;
Set_Etype (N, Standard_Boolean);
Check_Task_Prefix;
@@ -3387,7 +3414,16 @@ package body Sem_Attr is
-- Ceiling --
-------------
- when Attribute_Ceiling =>
+ when Attribute_Ceiling
+ | Attribute_Floor
+ | Attribute_Fraction
+ | Attribute_Machine
+ | Attribute_Machine_Rounding
+ | Attribute_Model
+ | Attribute_Rounding
+ | Attribute_Truncation
+ | Attribute_Unbiased_Rounding
+ =>
Check_Floating_Point_Type_1;
Set_Etype (N, P_Base_Type);
Resolve (E1, P_Base_Type);
@@ -3479,7 +3515,10 @@ package body Sem_Attr is
-- Compose --
-------------
- when Attribute_Compose =>
+ when Attribute_Compose
+ | Attribute_Leading_Part
+ | Attribute_Scaling
+ =>
Check_Floating_Point_Type_2;
Set_Etype (N, P_Base_Type);
Resolve (E1, P_Base_Type);
@@ -3597,11 +3636,7 @@ package body Sem_Attr is
-- Copy_Sign --
---------------
- when Attribute_Copy_Sign =>
- Check_Floating_Point_Type_2;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
- Resolve (E2, P_Base_Type);
+ -- Shares processing with Adjacent attribute
-----------
-- Count --
@@ -3674,7 +3709,7 @@ package body Sem_Attr is
null;
else
Error_Attr
- ("Attribute % must apply to entry of current task", N);
+ ("attribute % must apply to entry of current task", N);
end if;
end if;
@@ -3686,7 +3721,7 @@ package body Sem_Attr is
| E_Entry_Family
| E_Loop
then
- Error_Attr ("Attribute % cannot appear in inner unit", N);
+ Error_Attr ("attribute % cannot appear in inner unit", N);
elsif Ekind (Scope (Ent)) = E_Protected_Type
and then not Has_Completion (Scope (Ent))
@@ -3800,7 +3835,9 @@ package body Sem_Attr is
-- Denorm --
------------
- when Attribute_Denorm =>
+ when Attribute_Denorm
+ | Attribute_Signed_Zeros
+ =>
Check_Floating_Point_Type_0;
Set_Etype (N, Standard_Boolean);
@@ -3868,7 +3905,7 @@ package body Sem_Attr is
-- Elab_Spec --
---------------
- -- Shares processing with Elab_Body
+ -- Shares processing with Elab_Body attribute
----------------
-- Elaborated --
@@ -3883,7 +3920,14 @@ package body Sem_Attr is
-- Emax --
----------
- when Attribute_Emax =>
+ when Attribute_Emax
+ | Attribute_Machine_Emax
+ | Attribute_Machine_Emin
+ | Attribute_Machine_Mantissa
+ | Attribute_Model_Emin
+ | Attribute_Model_Mantissa
+ | Attribute_Safe_Emax
+ =>
Check_Floating_Point_Type_0;
Set_Etype (N, Universal_Integer);
@@ -3974,7 +4018,12 @@ package body Sem_Attr is
-- Epsilon --
-------------
- when Attribute_Epsilon =>
+ when Attribute_Epsilon
+ | Attribute_Model_Epsilon
+ | Attribute_Model_Small
+ | Attribute_Safe_First
+ | Attribute_Safe_Last
+ =>
Check_Floating_Point_Type_0;
Set_Etype (N, Universal_Real);
@@ -4049,7 +4098,9 @@ package body Sem_Attr is
-- First --
-----------
- when Attribute_First =>
+ when Attribute_First
+ | Attribute_Last
+ =>
Check_Array_Or_Scalar_Type;
Bad_Attribute_For_Predicate;
@@ -4057,7 +4108,10 @@ package body Sem_Attr is
-- First_Bit --
---------------
- when Attribute_First_Bit =>
+ when Attribute_First_Bit
+ | Attribute_Last_Bit
+ | Attribute_Position
+ =>
Check_Component;
Set_Etype (N, Universal_Integer);
@@ -4065,7 +4119,9 @@ package body Sem_Attr is
-- First_Valid --
-----------------
- when Attribute_First_Valid =>
+ when Attribute_First_Valid
+ | Attribute_Last_Valid
+ =>
Check_First_Last_Valid;
Set_Etype (N, P_Type);
@@ -4074,8 +4130,8 @@ package body Sem_Attr is
-----------------
when Attribute_Fixed_Value =>
- Check_E1;
Check_Fixed_Point_Type;
+ Check_E1;
Resolve (E1, Any_Integer);
Set_Etype (N, P_Base_Type);
@@ -4083,10 +4139,7 @@ package body Sem_Attr is
-- Floor --
-----------
- when Attribute_Floor =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
----------
-- Fore --
@@ -4100,10 +4153,7 @@ package body Sem_Attr is
-- Fraction --
--------------
- when Attribute_Fraction =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
--------------
-- From_Any --
@@ -4118,7 +4168,9 @@ package body Sem_Attr is
-- Has_Access_Values --
-----------------------
- when Attribute_Has_Access_Values =>
+ when Attribute_Has_Access_Values
+ | Attribute_Has_Tagged_Values
+ =>
Check_Type;
Check_E0;
Set_Etype (N, Standard_Boolean);
@@ -4142,10 +4194,7 @@ package body Sem_Attr is
-- Has_Tagged_Values --
-----------------------
- when Attribute_Has_Tagged_Values =>
- Check_Type;
- Check_E0;
- Set_Etype (N, Standard_Boolean);
+ -- Shares processing with Has_Access_Values attribute
-----------------------
-- Has_Discriminants --
@@ -4276,7 +4325,11 @@ package body Sem_Attr is
-- Large --
-----------
- when Attribute_Large =>
+ when Attribute_Large
+ | Attribute_Small
+ | Attribute_Safe_Large
+ | Attribute_Safe_Small
+ =>
Check_E0;
Check_Real_Type;
Set_Etype (N, Universal_Real);
@@ -4285,35 +4338,25 @@ package body Sem_Attr is
-- Last --
----------
- when Attribute_Last =>
- Check_Array_Or_Scalar_Type;
- Bad_Attribute_For_Predicate;
+ -- Shares processing with First attribute
--------------
-- Last_Bit --
--------------
- when Attribute_Last_Bit =>
- Check_Component;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with First_Bit attribute
----------------
-- Last_Valid --
----------------
- when Attribute_Last_Valid =>
- Check_First_Last_Valid;
- Set_Etype (N, P_Type);
+ -- Shares processing with First_Valid attribute
------------------
-- Leading_Part --
------------------
- when Attribute_Leading_Part =>
- Check_Floating_Point_Type_2;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
- Resolve (E2, Any_Integer);
+ -- Shares processing with Compose attribute
------------
-- Length --
@@ -4375,7 +4418,8 @@ package body Sem_Attr is
-- within the related loop.
function Declared_Within (Nod : Node_Id) return Boolean;
- -- Determine whether Nod appears in the subtree of Loop_Decl
+ -- Determine whether Nod appears in the subtree of Loop_Decl but
+ -- not within the subtree of the prefix P itself.
---------------------
-- Check_Reference --
@@ -4411,6 +4455,9 @@ package body Sem_Attr is
if Stmt = Loop_Decl then
return True;
+ elsif Stmt = P then
+ return False;
+
-- Prevent the search from going too far
elsif Is_Body_Or_Package_Declaration (Stmt) then
@@ -4679,40 +4726,33 @@ package body Sem_Attr is
-- Machine --
-------------
- when Attribute_Machine =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
------------------
-- Machine_Emax --
------------------
- when Attribute_Machine_Emax =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Emax attribute
------------------
-- Machine_Emin --
------------------
- when Attribute_Machine_Emin =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Emax attribute
----------------------
-- Machine_Mantissa --
----------------------
- when Attribute_Machine_Mantissa =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Emax attribute
-----------------------
-- Machine_Overflows --
-----------------------
- when Attribute_Machine_Overflows =>
+ when Attribute_Machine_Overflows
+ | Attribute_Machine_Rounds
+ =>
Check_Real_Type;
Check_E0;
Set_Etype (N, Standard_Boolean);
@@ -4721,7 +4761,9 @@ package body Sem_Attr is
-- Machine_Radix --
-------------------
- when Attribute_Machine_Radix =>
+ when Attribute_Machine_Radix
+ | Attribute_Mantissa
+ =>
Check_Real_Type;
Check_E0;
Set_Etype (N, Universal_Integer);
@@ -4730,25 +4772,22 @@ package body Sem_Attr is
-- Machine_Rounding --
----------------------
- when Attribute_Machine_Rounding =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
--------------------
-- Machine_Rounds --
--------------------
- when Attribute_Machine_Rounds =>
- Check_Real_Type;
- Check_E0;
- Set_Etype (N, Standard_Boolean);
+ -- Shares processing with Machine_Overflows attribute
------------------
-- Machine_Size --
------------------
- when Attribute_Machine_Size =>
+ when Attribute_Machine_Size
+ | Attribute_Object_Size
+ | Attribute_Value_Size
+ =>
Check_E0;
Check_Type;
Check_Not_Incomplete_Type;
@@ -4758,10 +4797,7 @@ package body Sem_Attr is
-- Mantissa --
--------------
- when Attribute_Mantissa =>
- Check_E0;
- Check_Real_Type;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Machine_Radix attribute
---------
-- Max --
@@ -4821,7 +4857,7 @@ package body Sem_Attr is
Error_Attr;
elsif UI_To_Int (Intval (E1)) > Number_Formals (Entity (P))
- or else UI_To_Int (Intval (E1)) < 0
+ or else Intval (E1) < 0
then
Error_Attr ("invalid parameter number for % attribute", E1);
end if;
@@ -4855,42 +4891,31 @@ package body Sem_Attr is
-- Model --
-----------
- when Attribute_Model =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
----------------
-- Model_Emin --
----------------
- when Attribute_Model_Emin =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Emax attribute
-------------------
-- Model_Epsilon --
-------------------
- when Attribute_Model_Epsilon =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Epsilon attribute
--------------------
-- Model_Mantissa --
--------------------
- when Attribute_Model_Mantissa =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Emax attribute
-----------------
-- Model_Small --
-----------------
- when Attribute_Model_Small =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Epsilon attribute
-------------
-- Modulus --
@@ -4989,11 +5014,7 @@ package body Sem_Attr is
-- Object_Size --
-----------------
- when Attribute_Object_Size =>
- Check_E0;
- Check_Type;
- Check_Not_Incomplete_Type;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Machine_Size attribute
---------
-- Old --
@@ -5300,23 +5321,23 @@ package body Sem_Attr is
-- Position --
--------------
- when Attribute_Position =>
- Check_Component;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with First_Bit attribute
----------
-- Pred --
----------
- when Attribute_Pred =>
+ when Attribute_Pred
+ | Attribute_Succ
+ =>
Check_Scalar_Type;
Check_E1;
Resolve (E1, P_Base_Type);
Set_Etype (N, P_Base_Type);
- -- Since Pred works on the base type, we normally do no check for the
- -- floating-point case, since the base type is unconstrained. But we
- -- make an exception in Check_Float_Overflow mode.
+ -- Since Pred/Succ work on the base type, we normally do no check for
+ -- the floating-point case, since the base type is unconstrained. But
+ -- we make an exception in Check_Float_Overflow mode.
if Is_Floating_Point_Type (P_Type) then
if not Range_Checks_Suppressed (P_Base_Type) then
@@ -5657,7 +5678,7 @@ package body Sem_Attr is
null;
else
Error_Msg_NE
- ("cannot apply reduce to object of type$", N, Typ);
+ ("cannot apply Reduce to object of type$", N, Typ);
end if;
elsif Present (Expressions (Stream))
@@ -5666,7 +5687,7 @@ package body Sem_Attr is
N_Iterated_Component_Association
then
Error_Msg_N
- ("Prefix of reduce must be an iterated component", N);
+ ("prefix of Reduce must be an iterated component", N);
end if;
Analyze (E1);
@@ -5706,11 +5727,7 @@ package body Sem_Attr is
-- Remainder --
---------------
- when Attribute_Remainder =>
- Check_Floating_Point_Type_2;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
- Resolve (E2, P_Base_Type);
+ -- Shares processing with Adjacent attribute
---------------------
-- Restriction_Set --
@@ -5833,52 +5850,37 @@ package body Sem_Attr is
-- Rounding --
--------------
- when Attribute_Rounding =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
---------------
-- Safe_Emax --
---------------
- when Attribute_Safe_Emax =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Emax attribute
----------------
-- Safe_First --
----------------
- when Attribute_Safe_First =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Epsilon attribute
----------------
-- Safe_Large --
----------------
- when Attribute_Safe_Large =>
- Check_E0;
- Check_Real_Type;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Large attribute
---------------
-- Safe_Last --
---------------
- when Attribute_Safe_Last =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Epsilon attribute
----------------
-- Safe_Small --
----------------
- when Attribute_Safe_Small =>
- Check_E0;
- Check_Real_Type;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Large attribute
--------------------------
-- Scalar_Storage_Order --
@@ -5947,18 +5949,13 @@ package body Sem_Attr is
-- Scaling --
-------------
- when Attribute_Scaling =>
- Check_Floating_Point_Type_2;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Compose attribute
------------------
-- Signed_Zeros --
------------------
- when Attribute_Signed_Zeros =>
- Check_Floating_Point_Type_0;
- Set_Etype (N, Standard_Boolean);
+ -- Shares processing with Denorm attribute
----------
-- Size --
@@ -6048,10 +6045,17 @@ package body Sem_Attr is
-- Small --
-----------
- when Attribute_Small =>
- Check_E0;
- Check_Real_Type;
- Set_Etype (N, Universal_Real);
+ -- Shares processing with Large attribute
+
+ ---------------------------------------
+ -- Small_Denominator/Small_Numerator --
+ ---------------------------------------
+
+ when Attribute_Small_Denominator
+ | Attribute_Small_Numerator
+ =>
+ Check_Fixed_Point_Type_0;
+ Set_Etype (N, Universal_Integer);
------------------
-- Storage_Pool --
@@ -6135,6 +6139,8 @@ package body Sem_Attr is
Check_Restriction (No_Obsolescent_Features, P);
elsif Is_Access_Type (P_Type) then
+ Set_Etype (N, Universal_Integer);
+
if Ekind (P_Type) = E_Access_Subprogram_Type then
Error_Attr_P
("cannot use % attribute for access-to-subprogram type");
@@ -6144,7 +6150,6 @@ package body Sem_Attr is
and then Is_Type (Entity (P))
then
Check_Type;
- Set_Etype (N, Universal_Integer);
-- Validate_Remote_Access_To_Class_Wide_Type for attribute
-- Storage_Size since this attribute is not defined for
@@ -6157,7 +6162,6 @@ package body Sem_Attr is
else
Check_Task_Prefix;
- Set_Etype (N, Universal_Integer);
end if;
else
@@ -6227,30 +6231,7 @@ package body Sem_Attr is
-- Succ --
----------
- when Attribute_Succ =>
- Check_Scalar_Type;
- Check_E1;
- Resolve (E1, P_Base_Type);
- Set_Etype (N, P_Base_Type);
-
- -- Since Pred works on the base type, we normally do no check for the
- -- floating-point case, since the base type is unconstrained. But we
- -- make an exception in Check_Float_Overflow mode.
-
- if Is_Floating_Point_Type (P_Type) then
- if not Range_Checks_Suppressed (P_Base_Type) then
- Set_Do_Range_Check (E1);
- end if;
-
- -- If not modular type, test for overflow check required
-
- else
- if not Is_Modular_Integer_Type (P_Type)
- and then not Range_Checks_Suppressed (P_Base_Type)
- then
- Enable_Range_Check (E1);
- end if;
- end if;
+ -- Shares processing with Pred attribute
--------------------------------
-- System_Allocator_Alignment --
@@ -6279,7 +6260,7 @@ package body Sem_Attr is
then
Error_Attr_P
("% attribute can only be applied to objects " &
- "of class - wide type");
+ "of class-wide type");
end if;
-- The prefix cannot be an incomplete type. However, references to
@@ -6331,10 +6312,7 @@ package body Sem_Attr is
-- Terminated --
----------------
- when Attribute_Terminated =>
- Check_E0;
- Set_Etype (N, Standard_Boolean);
- Check_Task_Prefix;
+ -- Shares processing with Callable attribute
----------------
-- To_Address --
@@ -6397,10 +6375,7 @@ package body Sem_Attr is
-- Truncation --
----------------
- when Attribute_Truncation =>
- Check_Floating_Point_Type_1;
- Resolve (E1, P_Base_Type);
- Set_Etype (N, P_Base_Type);
+ -- Shares processing with Ceiling attribute
----------------
-- Type_Class --
@@ -6589,10 +6564,7 @@ package body Sem_Attr is
-- Unbiased_Rounding --
-----------------------
- when Attribute_Unbiased_Rounding =>
- Check_Floating_Point_Type_1;
- Set_Etype (N, P_Base_Type);
- Resolve (E1, P_Base_Type);
+ -- Shares processing with Ceiling attribute
----------------------
-- Unchecked_Access --
@@ -6632,7 +6604,7 @@ package body Sem_Attr is
Check_E0;
if not Is_Entity_Name (P)
- or else Ekind (Entity (P)) not in Named_Kind
+ or else not Is_Named_Number (Entity (P))
then
Error_Attr_P ("prefix for % attribute must be named number");
@@ -6773,7 +6745,7 @@ package body Sem_Attr is
if Nkind (Expr) = N_Others_Choice then
Error_Attr
- ("others choice not allowed in attribute %", Expr);
+ ("OTHERS choice not allowed in attribute %", Expr);
-- Otherwise analyze and resolve all indexes
@@ -6820,7 +6792,7 @@ package body Sem_Attr is
if Nkind (Index) = N_Others_Choice then
Error_Attr
- ("others choice not allowed in attribute %", Index);
+ ("OTHERS choice not allowed in attribute %", Index);
-- The index denotes a range of elements
@@ -6995,7 +6967,7 @@ package body Sem_Attr is
elsif Nkind (Comp) = N_Others_Choice then
Error_Attr
- ("others choice not allowed in attribute %", Comp);
+ ("OTHERS choice not allowed in attribute %", Comp);
-- The name of a record component cannot appear in any
-- other form.
@@ -7132,7 +7104,10 @@ package body Sem_Attr is
-- Value --
-----------
- when Attribute_Value =>
+ when Attribute_Value
+ | Attribute_Wide_Value
+ | Attribute_Wide_Wide_Value
+ =>
Check_E1;
Check_Scalar_Type;
@@ -7182,11 +7157,7 @@ package body Sem_Attr is
-- Value_Size --
----------------
- when Attribute_Value_Size =>
- Check_E0;
- Check_Type;
- Check_Not_Incomplete_Type;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Machine_Size attribute
-------------
-- Version --
@@ -7222,51 +7193,22 @@ package body Sem_Attr is
-- Wide_Value --
----------------
- when Attribute_Wide_Value =>
- Check_E1;
- Check_Scalar_Type;
-
- -- Set Etype before resolving expression because expansion
- -- of expression may require enclosing type.
-
- Set_Etype (N, P_Type);
- Validate_Non_Static_Attribute_Function_Call;
-
- -- Check restriction No_Fixed_IO
-
- if Restriction_Check_Required (No_Fixed_IO)
- and then Is_Fixed_Point_Type (P_Type)
- then
- Check_Restriction (No_Fixed_IO, P);
- end if;
+ -- Shares processing with Value attribute
---------------------
-- Wide_Wide_Value --
---------------------
- when Attribute_Wide_Wide_Value =>
- Check_E1;
- Check_Scalar_Type;
-
- -- Set Etype before resolving expression because expansion
- -- of expression may require enclosing type.
-
- Set_Etype (N, P_Type);
- Validate_Non_Static_Attribute_Function_Call;
-
- -- Check restriction No_Fixed_IO
-
- if Restriction_Check_Required (No_Fixed_IO)
- and then Is_Fixed_Point_Type (P_Type)
- then
- Check_Restriction (No_Fixed_IO, P);
- end if;
+ -- Shares processing with Value attribute
---------------------
-- Wide_Wide_Width --
---------------------
- when Attribute_Wide_Wide_Width =>
+ when Attribute_Wide_Wide_Width
+ | Attribute_Wide_Width
+ | Attribute_Width
+ =>
Check_E0;
Check_Scalar_Type;
Set_Etype (N, Universal_Integer);
@@ -7275,19 +7217,13 @@ package body Sem_Attr is
-- Wide_Width --
----------------
- when Attribute_Wide_Width =>
- Check_E0;
- Check_Scalar_Type;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Wide_Wide_Width attribute
-----------
-- Width --
-----------
- when Attribute_Width =>
- Check_E0;
- Check_Scalar_Type;
- Set_Etype (N, Universal_Integer);
+ -- Shares processing with Wide_Wide_Width attribute
---------------
-- Word_Size --
@@ -7789,7 +7725,7 @@ package body Sem_Attr is
-- we will do the folding right here (things get confused if we let this
-- case go through the normal circuitry).
- if Attribute_Name (N) = Name_Img
+ if Id = Attribute_Img
and then Is_Entity_Name (P)
and then Is_Enumeration_Type (Etype (Entity (P)))
and then Is_OK_Static_Expression (P)
@@ -8123,7 +8059,7 @@ package body Sem_Attr is
-- T'Descriptor_Size is never static, even if T is static.
if Is_Scalar_Type (P_Entity)
- and then (not Is_Generic_Type (P_Entity))
+ and then not Is_Generic_Type (P_Entity)
and then Is_Static_Subtype (P_Entity)
and then Is_Scalar_Type (Etype (N))
and then
@@ -8147,7 +8083,7 @@ package body Sem_Attr is
if Is_Type (P_Entity)
and then (Is_Scalar_Type (P_Entity) or Is_Array_Type (P_Entity))
- and then (not Is_Generic_Type (P_Entity))
+ and then not Is_Generic_Type (P_Entity)
then
P_Type := P_Entity;
@@ -8155,7 +8091,7 @@ package body Sem_Attr is
elsif Ekind (P_Entity) in E_Variable | E_Constant
and then Is_Array_Type (Etype (P_Entity))
- and then (not Is_Generic_Type (Etype (P_Entity)))
+ and then not Is_Generic_Type (Etype (P_Entity))
then
P_Type := Etype (P_Entity);
@@ -8204,7 +8140,7 @@ package body Sem_Attr is
elsif (Id = Attribute_Size or
Id = Attribute_Max_Size_In_Storage_Elements)
and then Is_Type (P_Entity)
- and then (not Is_Generic_Type (P_Entity))
+ and then not Is_Generic_Type (P_Entity)
and then Known_Static_RM_Size (P_Entity)
then
declare
@@ -8226,7 +8162,7 @@ package body Sem_Attr is
elsif Id = Attribute_Alignment
and then Is_Type (P_Entity)
- and then (not Is_Generic_Type (P_Entity))
+ and then not Is_Generic_Type (P_Entity)
and then Known_Alignment (P_Entity)
then
Compile_Time_Known_Attribute (N, Alignment (P_Entity));
@@ -8235,7 +8171,7 @@ package body Sem_Attr is
-- If this is an access attribute that is known to fail accessibility
-- check, rewrite accordingly.
- elsif Attribute_Name (N) = Name_Access
+ elsif Id = Attribute_Address
and then Raises_Constraint_Error (N)
then
Rewrite (N,
@@ -9894,6 +9830,20 @@ package body Sem_Attr is
Fold_Ureal (N, Small_Value (P_Type), True);
end if;
+ -----------------------
+ -- Small_Denominator --
+ -----------------------
+
+ when Attribute_Small_Denominator =>
+ Fold_Uint (N, Norm_Den (Small_Value (P_Type)), True);
+
+ ---------------------
+ -- Small_Numerator --
+ ---------------------
+
+ when Attribute_Small_Numerator =>
+ Fold_Uint (N, Norm_Num (Small_Value (P_Type)), True);
+
-----------------
-- Stream_Size --
-----------------
diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb
index 36fd6ad..4925ffd 100644
--- a/gcc/ada/sem_aux.adb
+++ b/gcc/ada/sem_aux.adb
@@ -26,6 +26,7 @@
with Atree; use Atree;
with Einfo; use Einfo;
with Nlists; use Nlists;
+with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Uintp; use Uintp;
@@ -430,34 +431,6 @@ package body Sem_Aux is
return Empty;
end First_Tag_Component;
- ---------------------
- -- Get_Binary_Nkind --
- ---------------------
-
- function Get_Binary_Nkind (Op : Entity_Id) return Node_Kind is
- begin
- case Chars (Op) is
- when Name_Op_Add => return N_Op_Add;
- when Name_Op_Concat => return N_Op_Concat;
- when Name_Op_Expon => return N_Op_Expon;
- when Name_Op_Subtract => return N_Op_Subtract;
- when Name_Op_Mod => return N_Op_Mod;
- when Name_Op_Multiply => return N_Op_Multiply;
- when Name_Op_Divide => return N_Op_Divide;
- when Name_Op_Rem => return N_Op_Rem;
- when Name_Op_And => return N_Op_And;
- when Name_Op_Eq => return N_Op_Eq;
- when Name_Op_Ge => return N_Op_Ge;
- when Name_Op_Gt => return N_Op_Gt;
- when Name_Op_Le => return N_Op_Le;
- when Name_Op_Lt => return N_Op_Lt;
- when Name_Op_Ne => return N_Op_Ne;
- when Name_Op_Or => return N_Op_Or;
- when Name_Op_Xor => return N_Op_Xor;
- when others => raise Program_Error;
- end case;
- end Get_Binary_Nkind;
-
-----------------------
-- Get_Called_Entity --
-----------------------
@@ -656,21 +629,6 @@ package body Sem_Aux is
return Empty;
end Get_Rep_Pragma;
- ---------------------
- -- Get_Unary_Nkind --
- ---------------------
-
- function Get_Unary_Nkind (Op : Entity_Id) return Node_Kind is
- begin
- case Chars (Op) is
- when Name_Op_Abs => return N_Op_Abs;
- when Name_Op_Subtract => return N_Op_Minus;
- when Name_Op_Not => return N_Op_Not;
- when Name_Op_Add => return N_Op_Plus;
- when others => raise Program_Error;
- end case;
- end Get_Unary_Nkind;
-
---------------------------------
-- Has_External_Tag_Rep_Clause --
---------------------------------
@@ -1288,19 +1246,6 @@ package body Sem_Aux is
end if;
end Is_Limited_View;
- ----------------------------
- -- Is_Protected_Operation --
- ----------------------------
-
- function Is_Protected_Operation (E : Entity_Id) return Boolean is
- begin
- return
- Is_Entry (E)
- or else (Is_Subprogram (E)
- and then Nkind (Parent (Unit_Declaration_Node (E))) =
- N_Protected_Definition);
- end Is_Protected_Operation;
-
-------------------------------
-- Is_Record_Or_Limited_Type --
-------------------------------
@@ -1414,33 +1359,6 @@ package body Sem_Aux is
return Empty;
end Next_Tag_Component;
- -----------------------
- -- Number_Components --
- -----------------------
-
- function Number_Components (Typ : Entity_Id) return Nat is
- N : Nat := 0;
- Comp : Entity_Id;
-
- begin
- -- We do not call Einfo.First_Component_Or_Discriminant, as this
- -- function does not skip completely hidden discriminants, which we
- -- want to skip here.
-
- if Has_Discriminants (Typ) then
- Comp := First_Discriminant (Typ);
- else
- Comp := First_Component (Typ);
- end if;
-
- while Present (Comp) loop
- N := N + 1;
- Next_Component_Or_Discriminant (Comp);
- end loop;
-
- return N;
- end Number_Components;
-
--------------------------
-- Number_Discriminants --
--------------------------
@@ -1479,38 +1397,6 @@ package body Sem_Aux is
end Object_Type_Has_Constrained_Partial_View;
------------------
- -- Package_Body --
- ------------------
-
- function Package_Body (E : Entity_Id) return Node_Id is
- N : Node_Id;
-
- begin
- if Ekind (E) = E_Package_Body then
- N := Parent (E);
-
- if Nkind (N) = N_Defining_Program_Unit_Name then
- N := Parent (N);
- end if;
-
- else
- N := Package_Spec (E);
-
- if Present (Corresponding_Body (N)) then
- N := Parent (Corresponding_Body (N));
-
- if Nkind (N) = N_Defining_Program_Unit_Name then
- N := Parent (N);
- end if;
- else
- N := Empty;
- end if;
- end if;
-
- return N;
- end Package_Body;
-
- ------------------
-- Package_Spec --
------------------
diff --git a/gcc/ada/sem_aux.ads b/gcc/ada/sem_aux.ads
index 1d82045..237d5dc 100644
--- a/gcc/ada/sem_aux.ads
+++ b/gcc/ada/sem_aux.ads
@@ -34,7 +34,6 @@ with Alloc;
with Namet; use Namet;
with Table;
with Types; use Types;
-with Sinfo; use Sinfo;
package Sem_Aux is
@@ -148,22 +147,10 @@ package Sem_Aux is
-- Typ must be a tagged record type. This function returns the Entity for
-- the first _Tag field in the record type.
- function Get_Binary_Nkind (Op : Entity_Id) return Node_Kind;
- -- Op must be an entity with an Ekind of E_Operator. This function returns
- -- the Nkind value that would be used to construct a binary operator node
- -- referencing this entity. It is an error to call this function if Ekind
- -- (Op) /= E_Operator.
-
function Get_Called_Entity (Call : Node_Id) return Entity_Id;
-- Obtain the entity of the entry, operator, or subprogram being invoked
-- by call Call.
- function Get_Unary_Nkind (Op : Entity_Id) return Node_Kind;
- -- Op must be an entity with an Ekind of E_Operator. This function returns
- -- the Nkind value that would be used to construct a unary operator node
- -- referencing this entity. It is an error to call this function if Ekind
- -- (Op) /= E_Operator.
-
function Get_Rep_Item
(E : Entity_Id;
Nam : Name_Id;
@@ -347,10 +334,6 @@ package Sem_Aux is
-- these types). This older routine overlaps with the previous one, this
-- should be cleaned up???
- function Is_Protected_Operation (E : Entity_Id) return Boolean;
- -- Given a subprogram or entry, determines whether E is a protected entry
- -- or subprogram.
-
function Is_Record_Or_Limited_Type (Typ : Entity_Id) return Boolean;
-- Return True if Typ requires is a record or limited type.
@@ -382,10 +365,6 @@ package Sem_Aux is
-- The result returned is the next _Tag field in this record, or Empty
-- if this is the last such field.
- function Number_Components (Typ : Entity_Id) return Nat;
- -- Typ is a record type, yields number of components (including
- -- discriminants) in type.
-
function Number_Discriminants (Typ : Entity_Id) return Pos;
-- Typ is a type with discriminants, yields number of discriminants in type
@@ -398,10 +377,6 @@ package Sem_Aux is
-- derived type, and the subtype is not an unconstrained array subtype
-- (RM 3.3(23.10/3)).
- function Package_Body (E : Entity_Id) return Node_Id;
- -- Given an entity for a package (spec or body), return the corresponding
- -- package body if any, or else Empty.
-
function Package_Spec (E : Entity_Id) return Node_Id;
-- Given an entity for a package spec, return the corresponding package
-- spec if any, or else Empty.
diff --git a/gcc/ada/sem_cat.adb b/gcc/ada/sem_cat.adb
index 7872c68..ee22113 100644
--- a/gcc/ada/sem_cat.adb
+++ b/gcc/ada/sem_cat.adb
@@ -1068,7 +1068,8 @@ package body Sem_Cat is
and then not Private_Present (P)
and then not Is_Remote_Call_Interface (E)
then
- Error_Msg_N ("public child of rci unit must also be rci unit", N);
+ Error_Msg_N
+ ("public child of 'R'C'I unit must also be 'R'C'I unit", N);
end if;
end if;
end Validate_Categorization_Dependency;
@@ -1580,21 +1581,21 @@ package body Sem_Cat is
if Comes_From_Source (E) then
if Is_Limited_Type (E) then
Error_Msg_N
- ("limited type not allowed in rci unit", Parent (E));
+ ("limited type not allowed in 'R'C'I unit", Parent (E));
Explain_Limited_Type (E, Parent (E));
elsif Ekind (E) in E_Generic_Function
| E_Generic_Package
| E_Generic_Procedure
then
- Error_Msg_N ("generic declaration not allowed in rci unit",
+ Error_Msg_N ("generic declaration not allowed in 'R'C'I unit",
Parent (E));
elsif (Ekind (E) = E_Function or else Ekind (E) = E_Procedure)
and then Has_Pragma_Inline (E)
then
Error_Msg_N
- ("inlined subprogram not allowed in rci unit", Parent (E));
+ ("inlined subprogram not allowed in 'R'C'I unit", Parent (E));
-- Inner packages that are renamings need not be checked. Generic
-- RCI packages are subject to the checks, but entities that come
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 0bad136..e5519bf 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -768,7 +768,7 @@ package body Sem_Ch10 is
Unum := Get_Cunit_Unit_Number (N);
Par_Spec_Name := Get_Parent_Spec_Name (Unit_Name (Unum));
- if Par_Spec_Name /= No_Unit_Name then
+ if Present (Par_Spec_Name) then
Unum :=
Load_Unit
(Load_Name => Par_Spec_Name,
@@ -828,6 +828,7 @@ package body Sem_Ch10 is
-- of the child unit does not act as spec any longer.
Set_Acts_As_Spec (N, False);
+ Move_Aspects (From => Unit_Node, To => Unit (Lib_Unit));
Set_Is_Child_Unit (Defining_Entity (Unit_Node));
Set_Debug_Info_Needed (Defining_Entity (Unit (Lib_Unit)));
Set_Comes_From_Source_Default (SCS);
@@ -6183,34 +6184,35 @@ package body Sem_Ch10 is
null;
when N_Subprogram_Declaration =>
- Error_Msg_N ("subprograms not allowed in limited with_clauses", N);
+ Error_Msg_N
+ ("subprogram not allowed in `LIMITED WITH` clause", N);
return;
when N_Generic_Package_Declaration
| N_Generic_Subprogram_Declaration
=>
- Error_Msg_N ("generics not allowed in limited with_clauses", N);
+ Error_Msg_N ("generic not allowed in `LIMITED WITH` clause", N);
return;
when N_Generic_Instantiation =>
Error_Msg_N
- ("generic instantiations not allowed in limited with_clauses",
+ ("generic instantiation not allowed in `LIMITED WITH` clause",
N);
return;
when N_Generic_Renaming_Declaration =>
Error_Msg_N
- ("generic renamings not allowed in limited with_clauses", N);
+ ("generic renaming not allowed in `LIMITED WITH` clause", N);
return;
when N_Subprogram_Renaming_Declaration =>
Error_Msg_N
- ("renamed subprograms not allowed in limited with_clauses", N);
+ ("renamed subprogram not allowed in `LIMITED WITH` clause", N);
return;
when N_Package_Renaming_Declaration =>
Error_Msg_N
- ("renamed packages not allowed in limited with_clauses", N);
+ ("renamed package not allowed in `LIMITED WITH` clause", N);
return;
when others =>
diff --git a/gcc/ada/sem_ch11.adb b/gcc/ada/sem_ch11.adb
index 940c93b..48c9855 100644
--- a/gcc/ada/sem_ch11.adb
+++ b/gcc/ada/sem_ch11.adb
@@ -127,7 +127,7 @@ package body Sem_Ch11 is
and then Comes_From_Source (Id)
then
Error_Msg_N
- ("(Ada 83): duplicate exception choice&", Id);
+ ("(Ada 83) duplicate exception choice&", Id);
end if;
end if;
end if;
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 06b3bec..7e6aa8f 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -1619,7 +1619,7 @@ package body Sem_Ch12 is
Others_Choice := Actual;
if Present (Next (Actual)) then
- Error_Msg_N ("others must be last association", Actual);
+ Error_Msg_N ("OTHERS must be last association", Actual);
end if;
-- This subprogram is used both for formal packages and for
@@ -1630,7 +1630,7 @@ package body Sem_Ch12 is
and then Comes_From_Source (I_Node)
then
Error_Msg_N
- ("others association not allowed in an instance",
+ ("OTHERS association not allowed in an instance",
Actual);
end if;
@@ -1998,7 +1998,7 @@ package body Sem_Ch12 is
Gen_Par : Entity_Id;
Needs_Freezing : Boolean;
- S : Entity_Id;
+ P : Node_Id;
procedure Check_Generic_Parent;
-- The actual may be an instantiation of a unit
@@ -2102,18 +2102,15 @@ package body Sem_Ch12 is
Needs_Freezing := True;
- S := Current_Scope;
- while Present (S) loop
- if Ekind (S) in E_Block
- | E_Function
- | E_Loop
- | E_Procedure
+ P := Parent (I_Node);
+ while Nkind (P) /= N_Compilation_Unit loop
+ if Nkind (P) = N_Handled_Sequence_Of_Statements
then
Needs_Freezing := False;
exit;
end if;
- S := Scope (S);
+ P := Parent (P);
end loop;
if Needs_Freezing then
@@ -4070,6 +4067,16 @@ package body Sem_Ch12 is
return True;
end if;
+ -- In GNATprove mode, never instantiate bodies outside of the main
+ -- unit, as it does not use frontend/backend inlining in the way that
+ -- GNAT does, so does not benefit from such instantiations. On the
+ -- contrary, such instantiations may bring artificial constraints,
+ -- as for example such bodies may require preprocessing.
+
+ if GNATprove_Mode then
+ return False;
+ end if;
+
-- If not, then again no need to instantiate bodies in generic units
if Is_Generic_Unit (Cunit_Entity (Get_Code_Unit (N))) then
@@ -4299,7 +4306,7 @@ package body Sem_Ch12 is
elsif Contains_Instance_Of (Gen_Unit, Current_Scope, Gen_Id) then
Error_Msg_Node_2 := Current_Scope;
Error_Msg_NE
- ("circular Instantiation: & instantiated in &!", N, Gen_Unit);
+ ("circular instantiation: & instantiated in &!", N, Gen_Unit);
Circularity_Detected := True;
Restore_Env;
goto Leave;
@@ -5675,7 +5682,7 @@ package body Sem_Ch12 is
if Contains_Instance_Of (Gen_Unit, Current_Scope, Gen_Id) then
Error_Msg_Node_2 := Current_Scope;
Error_Msg_NE
- ("circular Instantiation: & instantiated in &!", N, Gen_Unit);
+ ("circular instantiation: & instantiated in &!", N, Gen_Unit);
Circularity_Detected := True;
Restore_Hidden_Primitives (Vis_Prims_List);
goto Leave;
@@ -7793,7 +7800,7 @@ package body Sem_Ch12 is
if Node (Elmt) = Scop then
Error_Msg_Node_2 := Inner;
Error_Msg_NE
- ("circular Instantiation: & instantiated within &!",
+ ("circular instantiation: & instantiated within &!",
N, Scop);
return True;
@@ -7803,7 +7810,7 @@ package body Sem_Ch12 is
elsif Contains_Instance_Of (Node (Elmt), Scop, N) then
Error_Msg_Node_2 := Inner;
Error_Msg_NE
- ("circular Instantiation: & instantiated within &!",
+ ("circular instantiation: & instantiated within &!",
N, Node (Elmt));
return True;
end if;
@@ -8795,7 +8802,7 @@ package body Sem_Ch12 is
while not Is_List_Member (P1)
or else not Is_List_Member (P2)
- or else List_Containing (P1) /= List_Containing (P2)
+ or else not In_Same_List (P1, P2)
loop
P1 := True_Parent (P1);
P2 := True_Parent (P2);
@@ -9074,7 +9081,7 @@ package body Sem_Ch12 is
--
-- procedure P ... -- this body freezes Parent_Inst
--
- -- package Inst is new ...
+ -- procedure Inst is new ...
--
-- In this particular scenario, the freeze node for Inst must be
-- inserted in the same manner as that of Parent_Inst - before the
@@ -9085,9 +9092,8 @@ package body Sem_Ch12 is
-- after that of Parent_Inst. This relation is established by
-- comparing the Slocs of Parent_Inst freeze node and Inst.
- elsif List_Containing (Get_Unit_Instantiation_Node (Par)) =
- List_Containing (Inst_Node)
- and then Sloc (Freeze_Node (Par)) < Sloc (Inst_Node)
+ elsif In_Same_List (Get_Unit_Instantiation_Node (Par), Inst_Node)
+ and then Sloc (Freeze_Node (Par)) <= Sloc (Inst_Node)
then
Insert_Freeze_Node_For_Instance (Inst_Node, F_Node);
@@ -9928,7 +9934,7 @@ package body Sem_Ch12 is
if Parent (List_Containing (Get_Unit_Instantiation_Node (Par)))
= Parent (List_Containing (N))
- and then Sloc (Freeze_Node (Par)) < Sloc (N)
+ and then Sloc (Freeze_Node (Par)) <= Sloc (N)
then
Insert_Freeze_Node_For_Instance (N, F_Node);
else
@@ -9982,8 +9988,7 @@ package body Sem_Ch12 is
-- the enclosing package, insert the freeze node after
-- the body.
- elsif List_Containing (Freeze_Node (Par)) =
- List_Containing (Parent (N))
+ elsif In_Same_List (Freeze_Node (Par), Parent (N))
and then Sloc (Freeze_Node (Par)) < Sloc (Parent (N))
then
Insert_Freeze_Node_For_Instance
@@ -10796,6 +10801,16 @@ package body Sem_Ch12 is
Next_Non_Pragma (Formal_Node);
Next (Actual_Of_Formal);
+ -- A formal subprogram may be overloaded, so advance in
+ -- the list of actuals to make sure we do not match two
+ -- successive formals to the same actual. This is only
+ -- relevant for overloadable entities, others have
+ -- distinct names.
+
+ if Is_Overloadable (Actual_Ent) then
+ Next_Entity (Actual_Ent);
+ end if;
+
else
-- No further formals to match, but the generic part may
-- contain inherited operation that are not hidden in the
@@ -11552,7 +11567,7 @@ package body Sem_Ch12 is
-- Use default to construct declaration
if Present (Subt_Mark) then
- Def := New_Copy (Subt_Mark);
+ Def := New_Copy_Tree (Subt_Mark);
else
pragma Assert (Present (Acc_Def));
Def := New_Copy_Tree (Acc_Def);
@@ -12640,10 +12655,10 @@ package body Sem_Ch12 is
Analyzed_Formal : Node_Id;
Actual_Decls : List_Id) return List_Id
is
- A_Gen_T : constant Entity_Id :=
+ A_Gen_T : constant Entity_Id :=
Defining_Identifier (Analyzed_Formal);
- Def : constant Node_Id := Formal_Type_Definition (Formal);
- Gen_T : constant Entity_Id := Defining_Identifier (Formal);
+ Def : constant Node_Id := Formal_Type_Definition (Formal);
+ Gen_T : constant Entity_Id := Defining_Identifier (Formal);
Act_T : Entity_Id;
Ancestor : Entity_Id := Empty;
Decl_Node : Node_Id;
@@ -12921,10 +12936,10 @@ package body Sem_Ch12 is
elsif Ekind (A_Gen_T) = E_General_Access_Type
and then Ekind (Base_Type (Act_T)) /= E_General_Access_Type
then
- Error_Msg_N -- CODEFIX
+ Error_Msg_N
("actual must be general access type!", Actual);
Error_Msg_NE -- CODEFIX
- ("add ALL to }!", Actual, Act_T);
+ ("\add ALL to }!", Actual, Act_T);
Abandon_Instantiation (Actual);
end if;
end if;
@@ -12953,21 +12968,6 @@ package body Sem_Ch12 is
end if;
Abandon_Instantiation (Actual);
-
- elsif Is_Access_Type (Designated_Type (Act_T))
- and then Is_Constrained (Designated_Type (Designated_Type (Act_T)))
- /=
- Is_Constrained (Designated_Type (Desig_Type))
- then
- Error_Msg_NE
- ("designated type of actual does not match that of formal &",
- Actual, Gen_T);
-
- if not Predicates_Match (Desig_Type, Desig_Act) then
- Error_Msg_N ("\predicates do not match", Actual);
- end if;
-
- Abandon_Instantiation (Actual);
end if;
-- Ada 2005: null-exclusion indicators of the two types must agree
@@ -13230,7 +13230,7 @@ package body Sem_Ch12 is
else
Error_Msg_Name_1 := Chars (Act_T);
Error_Msg_NE
- ("Actual% must implement interface&",
+ ("actual% must implement interface&",
Actual, Etype (Iface));
end if;
@@ -15379,13 +15379,21 @@ package body Sem_Ch12 is
if Is_Type (E)
and then Nkind (Parent (E)) = N_Subtype_Declaration
then
+ -- Always preserve the flag Is_Generic_Actual_Type for GNATprove,
+ -- as it is needed to identify the subtype with the type it
+ -- renames, when there are conversions between access types
+ -- to these.
+
+ if GNATprove_Mode then
+ null;
+
-- If the actual for E is itself a generic actual type from
-- an enclosing instance, E is still a generic actual type
-- outside of the current instance. This matter when resolving
-- an overloaded call that may be ambiguous in the enclosing
-- instance, when two of its actuals coincide.
- if Is_Entity_Name (Subtype_Indication (Parent (E)))
+ elsif Is_Entity_Name (Subtype_Indication (Parent (E)))
and then Is_Generic_Actual_Type
(Entity (Subtype_Indication (Parent (E))))
then
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 7013094..4724e0e 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -54,7 +54,6 @@ with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
with Sem_Dim; use Sem_Dim;
-with Sem_Disp; use Sem_Disp;
with Sem_Eval; use Sem_Eval;
with Sem_Prag; use Sem_Prag;
with Sem_Res; use Sem_Res;
@@ -65,6 +64,7 @@ with Sinfo; use Sinfo;
with Sinput; use Sinput;
with Snames; use Snames;
with Stand; use Stand;
+with Table;
with Targparm; use Targparm;
with Ttypes; use Ttypes;
with Tbuild; use Tbuild;
@@ -252,6 +252,18 @@ package body Sem_Ch13 is
-- Resolve each one of the operations specified in the specification of
-- Aspect_Aggregate.
+ procedure Validate_Aspect_Stable_Properties
+ (E : Entity_Id; N : Node_Id; Class_Present : Boolean);
+ -- Check legality of functions given in the Ada 202x Stable_Properties
+ -- (or Stable_Properties'Class) aspect.
+
+ procedure Resolve_Aspect_Stable_Properties
+ (Typ_Or_Subp : Entity_Id;
+ Expr : Node_Id;
+ Class_Present : Boolean);
+ -- Resolve each one of the functions specified in the specification of
+ -- aspect Stable_Properties (or Stable_Properties'Class).
+
procedure Resolve_Iterable_Operation
(N : Node_Id;
Cursor : Entity_Id;
@@ -1439,9 +1451,9 @@ package body Sem_Ch13 is
-- Aspect Full_Access_Only must be analyzed last so that
-- aspects Volatile and Atomic, if any, are analyzed.
- if A_Id /= Aspect_Export
- and then A_Id /= Aspect_Import
- and then A_Id /= Aspect_Full_Access_Only
+ if A_Id not in Aspect_Export
+ | Aspect_Full_Access_Only
+ | Aspect_Import
then
Make_Pragma_From_Boolean_Aspect (ASN);
end if;
@@ -2001,9 +2013,9 @@ package body Sem_Ch13 is
Error_Msg_N
("incompatible interfacing aspects given for &", E);
Error_Msg_Sloc := Sloc (Expo);
- Error_Msg_N ("\aspect `Export` #", E);
+ Error_Msg_N ("\aspect Export #", E);
Error_Msg_Sloc := Sloc (Imp);
- Error_Msg_N ("\aspect `Import` #", E);
+ Error_Msg_N ("\aspect Import #", E);
end if;
-- A variable is most likely modified from the outside. Take
@@ -2085,8 +2097,8 @@ package body Sem_Ch13 is
if A_Id = Aspect_External_Name then
if No (Expo) and then No (Imp) then
Error_Msg_N
- ("aspect `External_Name` requires aspect `Import` or "
- & "`Export`", Aspect);
+ ("aspect External_Name requires aspect Import or "
+ & "Export", Aspect);
end if;
-- Otherwise ensure that aspect Link_Name applies to aspect
@@ -2096,8 +2108,8 @@ package body Sem_Ch13 is
pragma Assert (A_Id = Aspect_Link_Name);
if No (Expo) and then No (Imp) then
Error_Msg_N
- ("aspect `Link_Name` requires aspect `Import` or "
- & "`Export`", Aspect);
+ ("aspect Link_Name requires aspect Import or Export",
+ Aspect);
end if;
end if;
end Analyze_Aspect_External_Link_Name;
@@ -2583,8 +2595,9 @@ package body Sem_Ch13 is
for Asp in Pre_Post_Aspects loop
if Has_Aspect (E, Asp) then
Error_Msg_N
- ("this aspect not allowed for static expression "
- & "functions", Find_Aspect (E, Asp));
+ ("this aspect is not allowed for a static "
+ & "expression function",
+ Find_Aspect (E, Asp));
return;
end if;
@@ -2648,7 +2661,7 @@ package body Sem_Ch13 is
elsif Within_Protected_Type (E) then
Error_Msg_N
- ("aspect% not applicable to protected operations", Id);
+ ("aspect% not applicable to protected operation", Id);
return;
else
@@ -2800,9 +2813,7 @@ package body Sem_Ch13 is
Ent := New_Occurrence_Of (E, Sloc (Id));
- if A_Id = Aspect_Attach_Handler
- or else A_Id = Aspect_Interrupt_Handler
- then
+ if A_Id in Aspect_Attach_Handler | Aspect_Interrupt_Handler then
-- Treat the specification as a reference to the protected
-- operation, which might otherwise appear unreferenced and
@@ -2846,10 +2857,10 @@ package body Sem_Ch13 is
-- Check some general restrictions on language defined aspects
if not Implementation_Defined_Aspect (A_Id)
- or else A_Id = Aspect_Async_Readers
- or else A_Id = Aspect_Async_Writers
- or else A_Id = Aspect_Effective_Reads
- or else A_Id = Aspect_Effective_Reads
+ or else A_Id in Aspect_Async_Readers
+ | Aspect_Async_Writers
+ | Aspect_Effective_Reads
+ | Aspect_Effective_Writes
then
Error_Msg_Name_1 := Nam;
@@ -2873,16 +2884,16 @@ package body Sem_Ch13 is
("aspect % not allowed for formal type declaration",
Aspect);
- elsif A_Id /= Aspect_Atomic
- and then A_Id /= Aspect_Volatile
- and then A_Id /= Aspect_Independent
- and then A_Id /= Aspect_Atomic_Components
- and then A_Id /= Aspect_Independent_Components
- and then A_Id /= Aspect_Volatile_Components
- and then A_Id /= Aspect_Async_Readers
- and then A_Id /= Aspect_Async_Writers
- and then A_Id /= Aspect_Effective_Reads
- and then A_Id /= Aspect_Effective_Reads
+ elsif A_Id not in Aspect_Atomic
+ | Aspect_Volatile
+ | Aspect_Independent
+ | Aspect_Atomic_Components
+ | Aspect_Independent_Components
+ | Aspect_Volatile_Components
+ | Aspect_Async_Readers
+ | Aspect_Async_Writers
+ | Aspect_Effective_Reads
+ | Aspect_Effective_Writes
then
Error_Msg_N
("aspect % not allowed for formal type declaration",
@@ -2938,11 +2949,11 @@ package body Sem_Ch13 is
-- an attribute reference whose prefix is Standard, for
-- example Standard'Maximum_Alignment or Standard'Word_Size.
- elsif (A_Id = Aspect_Alignment
- or else A_Id = Aspect_Component_Size
- or else A_Id = Aspect_Object_Size
- or else A_Id = Aspect_Size
- or else A_Id = Aspect_Value_Size)
+ elsif A_Id in Aspect_Alignment
+ | Aspect_Component_Size
+ | Aspect_Object_Size
+ | Aspect_Size
+ | Aspect_Value_Size
and then Present (Expr)
and then Nkind (Expr) = N_Attribute_Reference
and then Nkind (Prefix (Expr)) = N_Identifier
@@ -2958,6 +2969,18 @@ package body Sem_Ch13 is
end if;
end case;
+ if Delay_Required
+
+ and then A_Id = Aspect_Stable_Properties
+ -- ??? It seems like we should do this for all aspects, not
+ -- just Stable_Properties, but that causes as-yet-undiagnosed
+ -- regressions.
+
+ then
+ Set_Has_Delayed_Aspects (E);
+ Set_Is_Delayed_Aspect (Aspect);
+ end if;
+
-- Check 13.1(9.2/5): A representation aspect of a subtype or type
-- shall not be specified (whether by a representation item or an
-- aspect_specification) before the type is completely defined
@@ -3011,9 +3034,8 @@ package body Sem_Ch13 is
=>
-- Indexing aspects apply only to tagged type
- if (A_Id = Aspect_Constant_Indexing
- or else
- A_Id = Aspect_Variable_Indexing)
+ if A_Id in Aspect_Constant_Indexing
+ | Aspect_Variable_Indexing
and then not (Is_Type (E)
and then Is_Tagged_Type (E))
then
@@ -3040,10 +3062,10 @@ package body Sem_Ch13 is
-- illegal specification of this aspect for a subtype now,
-- to prevent malformed rep_item chains.
- if A_Id = Aspect_Input or else
- A_Id = Aspect_Output or else
- A_Id = Aspect_Read or else
- A_Id = Aspect_Write
+ if A_Id in Aspect_Input
+ | Aspect_Output
+ | Aspect_Read
+ | Aspect_Write
then
if not Is_First_Subtype (E) then
Error_Msg_N
@@ -3070,7 +3092,7 @@ package body Sem_Ch13 is
Aitem :=
Make_Attribute_Definition_Clause (Loc,
Name => Ent,
- Chars => Chars (Id),
+ Chars => Nam,
Expression => Relocate_Node (Expr));
-- If the address is specified, then we treat the entity as
@@ -3099,7 +3121,7 @@ package body Sem_Ch13 is
Expression => New_Occurrence_Of (E, Loc)),
Make_Pragma_Argument_Association (Sloc (Expr),
Expression => Relocate_Node (Expr))),
- Pragma_Name => Chars (Id));
+ Pragma_Name => Name_Linker_Section);
-- Linker_Section does not need delaying, as its argument
-- must be a static string. Furthermore, if applied to
@@ -3355,7 +3377,7 @@ package body Sem_Ch13 is
else
Error_Msg_N
- ("main subprogram CPU is out of range", Expr);
+ ("main subprogram 'C'P'U is out of range", Expr);
end if;
-- For the Priority aspect
@@ -3388,15 +3410,11 @@ package body Sem_Ch13 is
-- System.Tasking, but this package does not trigger the
-- required initialization of the run-time library.
- declare
- Discard : Entity_Id;
- begin
- if Restricted_Profile then
- Discard := RTE (RE_Activate_Restricted_Tasks);
- else
- Discard := RTE (RE_Activate_Tasks);
- end if;
- end;
+ if Restricted_Profile then
+ Discard_Node (RTE (RE_Activate_Restricted_Tasks));
+ else
+ Discard_Node (RTE (RE_Activate_Tasks));
+ end if;
-- Handling for these aspects in subprograms is complete
@@ -3409,7 +3427,7 @@ package body Sem_Ch13 is
Aitem :=
Make_Attribute_Definition_Clause (Loc,
Name => Ent,
- Chars => Chars (Id),
+ Chars => Nam,
Expression => Relocate_Node (Expr));
end if;
@@ -3424,7 +3442,7 @@ package body Sem_Ch13 is
Expression => Relocate_Node (Expr)),
Make_Pragma_Argument_Association (Sloc (Expr),
Expression => New_Occurrence_Of (E, Loc))),
- Pragma_Name => Chars (Id));
+ Pragma_Name => Nam);
Delay_Required := False;
@@ -3437,7 +3455,7 @@ package body Sem_Ch13 is
Expression => Relocate_Node (Expr)),
Make_Pragma_Argument_Association (Loc,
Expression => New_Occurrence_Of (E, Loc))),
- Pragma_Name => Chars (Id));
+ Pragma_Name => Name_Warnings);
Decorate (Aspect, Aitem);
Insert_Pragma (Aitem);
@@ -3586,11 +3604,17 @@ package body Sem_Ch13 is
-- wrapped inside of a procedure at the freeze point of the
-- private type's full view.
+ -- A type entity argument is appended to facilitate inheriting
+ -- the aspect from parent types (see Build_DIC_Procedure_Body),
+ -- though that extra argument isn't documented for the pragma.
+
when Aspect_Default_Initial_Condition =>
Aitem := Make_Aitem_Pragma
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Loc,
- Expression => Relocate_Node (Expr))),
+ Expression => Relocate_Node (Expr)),
+ Make_Pragma_Argument_Association (Sloc (Ent),
+ Expression => Ent)),
Pragma_Name =>
Name_Default_Initial_Condition);
@@ -3879,7 +3903,7 @@ package body Sem_Ch13 is
Aitem := Make_Aitem_Pragma
(Pragma_Argument_Associations => Args,
- Pragma_Name => Chars (Id));
+ Pragma_Name => Name_Obsolescent);
end;
-- Part_Of
@@ -4123,7 +4147,8 @@ package body Sem_Ch13 is
-- Must not be parenthesized
if Paren_Count (Expr) /= 0 then
- Error_Msg_F ("extra parentheses ignored", Expr);
+ Error_Msg -- CODEFIX
+ ("redundant parentheses", First_Sloc (Expr));
end if;
-- List of arguments is list of aggregate expressions
@@ -4165,7 +4190,7 @@ package body Sem_Ch13 is
-- pragmas/attributes but do require delayed analysis.
when Aspect_Default_Value | Aspect_Default_Component_Value =>
- Error_Msg_Name_1 := Chars (Id);
+ Error_Msg_Name_1 := Nam;
if not Is_Type (E) then
Error_Msg_N ("aspect% can only apply to a type", Id);
@@ -4178,14 +4203,14 @@ package body Sem_Ch13 is
elsif A_Id = Aspect_Default_Value
and then not Is_Scalar_Type (E)
then
- Error_Msg_N ("aspect% can only be applied to scalar type",
- Id);
+ Error_Msg_N
+ ("aspect% can only be applied to scalar type", Id);
goto Continue;
elsif A_Id = Aspect_Default_Component_Value then
if not Is_Array_Type (E) then
- Error_Msg_N ("aspect% can only be applied to array " &
- "type", Id);
+ Error_Msg_N
+ ("aspect% can only be applied to array type", Id);
goto Continue;
elsif not Is_Scalar_Type (Component_Type (E)) then
@@ -4201,6 +4226,12 @@ package body Sem_Ch13 is
Record_Rep_Item (E, Aspect);
goto Continue;
+ when Aspect_Stable_Properties =>
+ Validate_Aspect_Stable_Properties
+ (E, Expr, Class_Present => Class_Present (Aspect));
+ Record_Rep_Item (E, Aspect);
+ goto Continue;
+
when Aspect_Integer_Literal
| Aspect_Real_Literal
| Aspect_String_Literal
@@ -4262,7 +4293,7 @@ package body Sem_Ch13 is
Pname : Name_Id;
begin
- if A_Id = Aspect_Pre or else A_Id = Aspect_Precondition then
+ if A_Id in Aspect_Pre | Aspect_Precondition then
Pname := Name_Precondition;
else
Pname := Name_Postcondition;
@@ -4394,14 +4425,25 @@ package body Sem_Ch13 is
if Nkind (Parent (N)) = N_Compilation_Unit then
Error_Msg_Name_1 := Nam;
- Error_Msg_N ("incorrect placement of aspect `%`", E);
+ Error_Msg_N ("incorrect placement of aspect %", E);
goto Continue;
end if;
- if Nkind (Expr) /= N_Aggregate then
+ if Nkind (Expr) /= N_Aggregate
+ or else Null_Record_Present (Expr)
+ then
Error_Msg_Name_1 := Nam;
Error_Msg_NE
- ("wrong syntax for aspect `%` for &", Id, E);
+ ("wrong syntax for aspect % for &", Id, E);
+ goto Continue;
+ end if;
+
+ -- Check that the expression is a proper aggregate (no
+ -- parentheses).
+
+ if Paren_Count (Expr) /= 0 then
+ Error_Msg -- CODEFIX
+ ("redundant parentheses", First_Sloc (Expr));
goto Continue;
end if;
@@ -4424,7 +4466,7 @@ package body Sem_Ch13 is
then
Error_Msg_Name_1 := Nam;
Error_Msg_NE
- ("wrong syntax for aspect `%` for &", Id, E);
+ ("wrong syntax for aspect % for &", Id, E);
goto Continue;
end if;
@@ -4440,7 +4482,7 @@ package body Sem_Ch13 is
Aitem := Make_Aitem_Pragma
(Pragma_Argument_Associations => Args,
- Pragma_Name => Nam);
+ Pragma_Name => Name_Test_Case);
end Test_Case;
-- Contract_Cases
@@ -4450,7 +4492,7 @@ package body Sem_Ch13 is
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Loc,
Expression => Relocate_Node (Expr))),
- Pragma_Name => Nam);
+ Pragma_Name => Name_Contract_Cases);
Decorate (Aspect, Aitem);
Insert_Pragma (Aitem);
@@ -4463,7 +4505,7 @@ package body Sem_Ch13 is
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Loc,
Expression => Relocate_Node (Expr))),
- Pragma_Name => Nam);
+ Pragma_Name => Name_Subprogram_Variant);
Decorate (Aspect, Aitem);
Insert_Pragma (Aitem);
@@ -4509,7 +4551,7 @@ package body Sem_Ch13 is
goto Continue;
- elsif A_Id = Aspect_Export or else A_Id = Aspect_Import then
+ elsif A_Id in Aspect_Export | Aspect_Import then
Analyze_Aspect_Export_Import;
-- Disable_Controlled
@@ -4581,14 +4623,12 @@ package body Sem_Ch13 is
-- Exclude aspects Export and Import because their pragma
-- syntax does not map directly to a Boolean aspect.
- if A_Id /= Aspect_Export
- and then A_Id /= Aspect_Import
- then
+ if A_Id not in Aspect_Export | Aspect_Import then
Aitem := Make_Aitem_Pragma
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Sloc (Ent),
Expression => Ent)),
- Pragma_Name => Chars (Id));
+ Pragma_Name => Nam);
end if;
-- In general cases, the corresponding pragma/attribute
@@ -4651,7 +4691,7 @@ package body Sem_Ch13 is
Aitem :=
Make_Attribute_Definition_Clause (Loc,
Name => Ent,
- Chars => Chars (Id),
+ Chars => Name_Storage_Size,
Expression => Relocate_Node (Expr));
end if;
end case;
@@ -4698,7 +4738,7 @@ package body Sem_Ch13 is
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Sloc (Ent),
Expression => Ent)),
- Pragma_Name => Chars (Id));
+ Pragma_Name => Nam);
Set_From_Aspect_Specification (Aitem, True);
Set_Corresponding_Aspect (Aitem, Aspect);
@@ -6589,7 +6629,7 @@ package body Sem_Ch13 is
-- come from an aspect specification.
if not Is_Task_Type (U_Ent) then
- Error_Msg_N ("CPU can only be defined for task", Nam);
+ Error_Msg_N ("'C'P'U can only be defined for task", Nam);
elsif Duplicate_Clause then
null;
@@ -6680,7 +6720,7 @@ package body Sem_Ch13 is
else
Error_Msg_NE
- ("Default Iterator must be a primitive of&", Func, U_Ent);
+ ("Default_Iterator must be a primitive of&", Func, U_Ent);
end if;
end Default_Iterator;
@@ -7734,7 +7774,7 @@ package body Sem_Ch13 is
| N_Implicit_Label_Declaration
then
Error_Msg_N
- ("this declaration not allowed in machine code subprogram",
+ ("this declaration is not allowed in machine code subprogram",
DeclO);
end if;
@@ -7933,7 +7973,7 @@ package body Sem_Ch13 is
end if;
if Nkind (Choice) = N_Others_Choice then
- Error_Msg_N ("others choice not allowed here", Choice);
+ Error_Msg_N ("OTHERS choice not allowed here", Choice);
Err := True;
elsif Nkind (Choice) = N_Range then
@@ -9111,7 +9151,7 @@ package body Sem_Ch13 is
or else Etype (Expression (Expr)) /= Typ
then
Error_Msg_N
- ("expression must denaote subtype", Expression (Expr));
+ ("expression must denote subtype", Expression (Expr));
return False_Range;
end if;
@@ -10495,12 +10535,14 @@ package body Sem_Ch13 is
-- Expression from call to Check_Aspect_At_Freeze_Point.
T : constant Entity_Id :=
- (if Present (Freeze_Expr)
+ (if Present (Freeze_Expr) and (A_Id /= Aspect_Stable_Properties)
then Etype (Original_Node (Freeze_Expr))
else Empty);
-- Type required for preanalyze call. We use the original expression to
-- get the proper type, to prevent cascaded errors when the expression
- -- is constant-folded.
+ -- is constant-folded. For Stable_Properties, the aspect value is
+ -- not semantically an expression (although it is syntactically);
+ -- in particular, it has no type.
Err : Boolean;
-- Set False if error
@@ -10578,22 +10620,22 @@ package body Sem_Ch13 is
-- name, so we need to verify that one of these interpretations is
-- the one available at at the freeze point.
- elsif A_Id = Aspect_Input or else
- A_Id = Aspect_Output or else
- A_Id = Aspect_Read or else
- A_Id = Aspect_Write or else
- A_Id = Aspect_Put_Image
+ elsif A_Id in Aspect_Input
+ | Aspect_Output
+ | Aspect_Read
+ | Aspect_Write
+ | Aspect_Put_Image
then
Analyze (End_Decl_Expr);
Check_Overloaded_Name;
- elsif A_Id = Aspect_Variable_Indexing or else
- A_Id = Aspect_Constant_Indexing or else
- A_Id = Aspect_Default_Iterator or else
- A_Id = Aspect_Iterator_Element or else
- A_Id = Aspect_Integer_Literal or else
- A_Id = Aspect_Real_Literal or else
- A_Id = Aspect_String_Literal
+ elsif A_Id in Aspect_Variable_Indexing
+ | Aspect_Constant_Indexing
+ | Aspect_Default_Iterator
+ | Aspect_Iterator_Element
+ | Aspect_Integer_Literal
+ | Aspect_Real_Literal
+ | Aspect_String_Literal
then
-- Make type unfrozen before analysis, to prevent spurious errors
-- about late attributes.
@@ -10619,9 +10661,7 @@ package body Sem_Ch13 is
-- also make its potential components accessible.
if not Analyzed (Freeze_Expr) and then Inside_A_Generic then
- if A_Id = Aspect_Dynamic_Predicate
- or else A_Id = Aspect_Predicate
- then
+ if A_Id in Aspect_Dynamic_Predicate | Aspect_Predicate then
Push_Type (Ent);
Preanalyze_Spec_Expression (Freeze_Expr, Standard_Boolean);
Pop_Type (Ent);
@@ -10647,9 +10687,9 @@ package body Sem_Ch13 is
-- visible for aspects that may reference them.
if Present (Freeze_Expr) and then No (T) then
- if A_Id = Aspect_Dynamic_Predicate
- or else A_Id = Aspect_Predicate
- or else A_Id = Aspect_Priority
+ if A_Id in Aspect_Dynamic_Predicate
+ | Aspect_Predicate
+ | Aspect_Priority
then
Push_Type (Ent);
Check_Aspect_At_Freeze_Point (ASN);
@@ -10665,9 +10705,7 @@ package body Sem_Ch13 is
-- partial view is visible. The expression must be scalar, so use
-- the full view to resolve.
- elsif (A_Id = Aspect_Default_Value
- or else
- A_Id = Aspect_Default_Component_Value)
+ elsif A_Id in Aspect_Default_Component_Value | Aspect_Default_Value
and then Is_Private_Type (T)
then
Preanalyze_Spec_Expression (End_Decl_Expr, Full_View (T));
@@ -10675,10 +10713,10 @@ package body Sem_Ch13 is
-- The following aspect expressions may contain references to
-- components and discriminants of the type.
- elsif A_Id = Aspect_Dynamic_Predicate
- or else A_Id = Aspect_Predicate
- or else A_Id = Aspect_Priority
- or else A_Id = Aspect_CPU
+ elsif A_Id in Aspect_CPU
+ | Aspect_Dynamic_Predicate
+ | Aspect_Predicate
+ | Aspect_Priority
then
Push_Type (Ent);
Preanalyze_Spec_Expression (End_Decl_Expr, T);
@@ -10911,7 +10949,13 @@ package body Sem_Ch13 is
return;
when Aspect_Aggregate =>
- Resolve_Aspect_Aggregate (Entity (ASN), Expr);
+ Resolve_Aspect_Aggregate (Entity (ASN), Expression (ASN));
+ return;
+
+ when Aspect_Stable_Properties =>
+ Resolve_Aspect_Stable_Properties
+ (Entity (ASN), Expression (ASN),
+ Class_Present => Class_Present (ASN));
return;
-- Invariant/Predicate take boolean expressions
@@ -11129,9 +11173,7 @@ package body Sem_Ch13 is
-- Otherwise look at the identifier and see if it is OK
- if Ekind (Ent) in E_Named_Integer | E_Named_Real
- or else Is_Type (Ent)
- then
+ if Is_Named_Number (Ent) or else Is_Type (Ent) then
return;
elsif Ekind (Ent) in E_Constant | E_In_Parameter then
@@ -12700,7 +12742,6 @@ package body Sem_Ch13 is
and then Scope (E) = Current_Scope
then
declare
- A_Id : Aspect_Id;
Ritem : Node_Id;
begin
@@ -12712,12 +12753,10 @@ package body Sem_Ch13 is
and then Entity (Ritem) = E
and then Is_Delayed_Aspect (Ritem)
then
- A_Id := Get_Aspect_Id (Ritem);
-
- if A_Id = Aspect_Dynamic_Predicate
- or else A_Id = Aspect_Predicate
- or else A_Id = Aspect_Priority
- or else A_Id = Aspect_CPU
+ if Get_Aspect_Id (Ritem) in Aspect_CPU
+ | Aspect_Dynamic_Predicate
+ | Aspect_Predicate
+ | Aspect_Priority
then
-- Retrieve the visibility to components and discriminants
-- in order to properly analyze the aspects.
@@ -13463,31 +13502,23 @@ package body Sem_Ch13 is
function Is_Operational_Item (N : Node_Id) return Boolean is
begin
- if Nkind (N) /= N_Attribute_Definition_Clause then
- return False;
-
- else
- declare
- Id : constant Attribute_Id := Get_Attribute_Id (Chars (N));
- begin
-
- -- List of operational items is given in AARM 13.1(8.mm/1).
- -- It is clearly incomplete, as it does not include iterator
- -- aspects, among others.
-
- return Id = Attribute_Constant_Indexing
- or else Id = Attribute_Default_Iterator
- or else Id = Attribute_Implicit_Dereference
- or else Id = Attribute_Input
- or else Id = Attribute_Iterator_Element
- or else Id = Attribute_Iterable
- or else Id = Attribute_Output
- or else Id = Attribute_Read
- or else Id = Attribute_Variable_Indexing
- or else Id = Attribute_Write
- or else Id = Attribute_External_Tag;
- end;
- end if;
+ -- List of operational items is given in AARM 13.1(8.mm/1). It is
+ -- clearly incomplete, as it does not include iterator aspects, among
+ -- others.
+
+ return Nkind (N) = N_Attribute_Definition_Clause
+ and then
+ Get_Attribute_Id (Chars (N)) in Attribute_Constant_Indexing
+ | Attribute_External_Tag
+ | Attribute_Default_Iterator
+ | Attribute_Implicit_Dereference
+ | Attribute_Input
+ | Attribute_Iterable
+ | Attribute_Iterator_Element
+ | Attribute_Output
+ | Attribute_Read
+ | Attribute_Variable_Indexing
+ | Attribute_Write;
end Is_Operational_Item;
-------------------------
@@ -13695,17 +13726,13 @@ package body Sem_Ch13 is
begin
case Nkind (N) is
when N_Attribute_Definition_Clause =>
- declare
- Id : constant Attribute_Id := Get_Attribute_Id (Chars (N));
- -- See AARM 13.1(8.f-8.x) list items that end in "clause"
- -- ???: include any GNAT-defined attributes here?
- begin
- return Id = Attribute_Component_Size
- or else Id = Attribute_Bit_Order
- or else Id = Attribute_Storage_Pool
- or else Id = Attribute_Stream_Size
- or else Id = Attribute_Machine_Radix;
- end;
+ -- See AARM 13.1(8.f-8.x) list items that end in "clause"
+ -- ???: include any GNAT-defined attributes here?
+ return Get_Attribute_Id (Chars (N)) in Attribute_Bit_Order
+ | Attribute_Component_Size
+ | Attribute_Machine_Radix
+ | Attribute_Storage_Pool
+ | Attribute_Stream_Size;
when N_Pragma =>
case Get_Pragma_Id (N) is
@@ -14920,6 +14947,10 @@ package body Sem_Ch13 is
when Aspect_Aggregate =>
Resolve_Aspect_Aggregate (Entity (ASN), Expr);
+ when Aspect_Stable_Properties =>
+ Resolve_Aspect_Stable_Properties
+ (Entity (ASN), Expr, Class_Present (ASN));
+
-- For now we only deal with aspects that do not generate
-- subprograms, or that may mention current instances of
-- types. These will require special handling (???TBD).
@@ -15058,6 +15089,72 @@ package body Sem_Ch13 is
end loop;
end Parse_Aspect_Aggregate;
+ ------------------------------------
+ -- Parse_Aspect_Stable_Properties --
+ ------------------------------------
+
+ function Parse_Aspect_Stable_Properties
+ (Aspect_Spec : Node_Id; Negated : out Boolean) return Subprogram_List
+ is
+ function Extract_Entity (Expr : Node_Id) return Entity_Id;
+ -- Given an element of a Stable_Properties aspect spec, return the
+ -- associated entity.
+ -- This function updates the Negated flag as a side-effect.
+
+ --------------------
+ -- Extract_Entity --
+ --------------------
+
+ function Extract_Entity (Expr : Node_Id) return Entity_Id is
+ Name : Node_Id;
+ begin
+ if Nkind (Expr) = N_Op_Not then
+ Negated := True;
+ Name := Right_Opnd (Expr);
+ else
+ Name := Expr;
+ end if;
+
+ if Nkind (Name) in N_Has_Entity then
+ return Entity (Name);
+ else
+ return Empty;
+ end if;
+ end Extract_Entity;
+
+ -- Local variables
+
+ L : List_Id;
+ Id : Node_Id;
+
+ -- Start of processing for Parse_Aspect_Stable_Properties
+
+ begin
+ Negated := False;
+
+ if Nkind (Aspect_Spec) /= N_Aggregate then
+ return (1 => Extract_Entity (Aspect_Spec));
+ else
+ L := Expressions (Aspect_Spec);
+ Id := First (L);
+
+ return Result : Subprogram_List (1 .. List_Length (L)) do
+ for I in Result'Range loop
+ Result (I) := Extract_Entity (Id);
+
+ if No (Result (I)) then
+ pragma Assert (Serious_Errors_Detected > 0);
+ goto Ignore_Aspect;
+ end if;
+
+ Next (Id);
+ end loop;
+ end return;
+ end if;
+
+ <<Ignore_Aspect>> return (1 .. 0 => <>);
+ end Parse_Aspect_Stable_Properties;
+
-------------------------------
-- Validate_Aspect_Aggregate --
-------------------------------
@@ -15070,14 +15167,13 @@ package body Sem_Ch13 is
Assign_Indexed_Subp : Node_Id := Empty;
begin
- if Ada_Version < Ada_2020 then
- Error_Msg_N ("Aspect Aggregate is an Ada_2020 feature", N);
+ Error_Msg_Ada_2020_Feature ("aspect Aggregate", Sloc (N));
- elsif Nkind (N) /= N_Aggregate
+ if Nkind (N) /= N_Aggregate
or else Present (Expressions (N))
or else No (Component_Associations (N))
then
- Error_Msg_N ("Aspect Aggregate requires an aggregate "
+ Error_Msg_N ("aspect Aggregate requires an aggregate "
& "with component associations", N);
return;
end if;
@@ -15104,6 +15200,136 @@ package body Sem_Ch13 is
end if;
end Validate_Aspect_Aggregate;
+ -------------------------------
+ -- Validate_Aspect_Stable_Properties --
+ -------------------------------
+
+ procedure Validate_Aspect_Stable_Properties
+ (E : Entity_Id; N : Node_Id; Class_Present : Boolean)
+ is
+ Is_Aspect_Of_Type : constant Boolean := Is_Type (E);
+
+ type Permission is (Forbidden, Optional, Required);
+ Modifier_Permission : Permission :=
+ (if Is_Aspect_Of_Type then Forbidden else Optional);
+ Modifier_Error_Called : Boolean := False;
+
+ procedure Check_Property_Function_Arg (PF_Arg : Node_Id);
+ -- Check syntax of a property function argument
+
+ ----------------------------------
+ -- Check_Property_Function_Arg --
+ ----------------------------------
+
+ procedure Check_Property_Function_Arg (PF_Arg : Node_Id) is
+ procedure Modifier_Error;
+ -- Generate message about bad "not" modifier if no message already
+ -- generated. Errors include specifying "not" for an aspect of
+ -- of a type and specifying "not" for some but not all of the
+ -- names in a list.
+
+ --------------------
+ -- Modifier_Error --
+ --------------------
+
+ procedure Modifier_Error is
+ begin
+ if Modifier_Error_Called then
+ return; -- error message already generated
+ end if;
+
+ Modifier_Error_Called := True;
+
+ if Is_Aspect_Of_Type then
+ Error_Msg_N
+ ("NOT modifier not allowed for Stable_Properties aspect"
+ & " of a type", PF_Arg);
+ else
+ Error_Msg_N ("mixed use of NOT modifiers", PF_Arg);
+ end if;
+ end Modifier_Error;
+
+ PF_Name : Node_Id := PF_Arg;
+
+ -- Start of processing for Check_Property_Function_Arg
+
+ begin
+ if Nkind (PF_Arg) = N_Op_Not then
+ PF_Name := Right_Opnd (PF_Arg);
+
+ case Modifier_Permission is
+ when Forbidden =>
+ Modifier_Error;
+ when Optional =>
+ Modifier_Permission := Required;
+ when Required =>
+ null;
+ end case;
+ else
+ case Modifier_Permission is
+ when Forbidden =>
+ null;
+ when Optional =>
+ Modifier_Permission := Forbidden;
+ when Required =>
+ Modifier_Error;
+ end case;
+ end if;
+
+ if Nkind (PF_Name) not in
+ N_Identifier | N_Operator_Symbol | N_Selected_Component
+ then
+ Error_Msg_N ("bad property function name", PF_Name);
+ end if;
+ end Check_Property_Function_Arg;
+
+ -- Start of processing for Validate_Aspect_Stable_Properties
+
+ begin
+ Error_Msg_Ada_2020_Feature ("aspect Stable_Properties", Sloc (N));
+
+ if (not Is_Aspect_Of_Type) and then (not Is_Subprogram (E)) then
+ Error_Msg_N ("Stable_Properties aspect can only be specified for "
+ & "a type or a subprogram", N);
+ elsif Class_Present then
+ if Is_Aspect_Of_Type then
+ if not Is_Tagged_Type (E) then
+ Error_Msg_N
+ ("Stable_Properties''Class aspect cannot be specified for "
+ & "an untagged type", N);
+ end if;
+ else
+ if not Is_Dispatching_Operation (E) then
+ Error_Msg_N
+ ("Stable_Properties''Class aspect cannot be specified for "
+ & "a subprogram that is not a primitive subprogram "
+ & "of a tagged type", N);
+ end if;
+ end if;
+ end if;
+
+ if Nkind (N) = N_Aggregate then
+ if Present (Component_Associations (N))
+ or else Null_Record_Present (N)
+ or else not Present (Expressions (N))
+ then
+ Error_Msg_N ("bad Stable_Properties aspect specification", N);
+ return;
+ end if;
+
+ declare
+ PF_Arg : Node_Id := First (Expressions (N));
+ begin
+ while Present (PF_Arg) loop
+ Check_Property_Function_Arg (PF_Arg);
+ Next (PF_Arg);
+ end loop;
+ end;
+ else
+ Check_Property_Function_Arg (N);
+ end if;
+ end Validate_Aspect_Stable_Properties;
+
--------------------------------
-- Resolve_Iterable_Operation --
--------------------------------
@@ -15135,12 +15361,12 @@ package body Sem_Ch13 is
Ent := Entity (N);
F1 := First_Formal (Ent);
- if Nam = Name_First or else Nam = Name_Last then
+ if Nam in Name_First | Name_Last then
-- First or Last (Container) => Cursor
if Etype (Ent) /= Cursor then
- Error_Msg_N ("primitive for First must yield a curosr", N);
+ Error_Msg_N ("primitive for First must yield a cursor", N);
end if;
elsif Nam = Name_Next then
@@ -15463,6 +15689,224 @@ package body Sem_Ch13 is
end loop;
end Resolve_Aspect_Aggregate;
+ --------------------------------------
+ -- Resolve_Aspect_Stable_Properties --
+ --------------------------------------
+
+ procedure Resolve_Aspect_Stable_Properties
+ (Typ_Or_Subp : Entity_Id; Expr : Node_Id; Class_Present : Boolean)
+ is
+ Is_Aspect_Of_Type : constant Boolean := Is_Type (Typ_Or_Subp);
+
+ Singleton : constant Boolean := Nkind (Expr) /= N_Aggregate;
+ Subp_Name : Node_Id := (if Singleton
+ then Expr
+ else First (Expressions (Expr)));
+ Has_Not : Boolean;
+ begin
+ if Is_Aspect_Of_Type
+ and then Has_Private_Declaration (Typ_Or_Subp)
+ and then not Is_Private_Type (Typ_Or_Subp)
+ then
+ Error_Msg_N
+ ("Stable_Properties aspect cannot be specified " &
+ "for the completion of a private type", Typ_Or_Subp);
+ end if;
+
+ -- Analogous checks that the aspect is not specified for a completion
+ -- in the subprogram case are not performed here because they are not
+ -- specific to this particular aspect. Right ???
+
+ loop
+ Has_Not := Nkind (Subp_Name) = N_Op_Not;
+ if Has_Not then
+ Set_Analyzed (Subp_Name); -- ???
+ Subp_Name := Right_Opnd (Subp_Name);
+ end if;
+
+ if No (Etype (Subp_Name)) then
+ Analyze (Subp_Name);
+ end if;
+
+ declare
+ Subp : Entity_Id := Empty;
+
+ I : Interp_Index;
+ It : Interp;
+
+ function Is_Property_Function (E : Entity_Id) return Boolean;
+ -- Implements RM 7.3.4 definition of "property function".
+
+ function Is_Property_Function (E : Entity_Id) return Boolean is
+ begin
+ if Ekind (E) not in E_Function | E_Operator
+ or else Number_Formals (E) /= 1
+ then
+ return False;
+ end if;
+
+ declare
+ Param_Type : constant Entity_Id :=
+ Base_Type (Etype (First_Formal (E)));
+
+ function Matches_Param_Type (Typ : Entity_Id)
+ return Boolean is
+ ((Base_Type (Typ) = Param_Type)
+ or else
+ (Is_Class_Wide_Type (Param_Type)
+ and then Is_Ancestor (Root_Type (Param_Type),
+ Base_Type (Typ))));
+ begin
+ if Is_Aspect_Of_Type then
+ if Matches_Param_Type (Typ_Or_Subp) then
+ return True;
+ end if;
+ elsif Is_Primitive (Typ_Or_Subp) then
+ declare
+ Formal : Entity_Id := First_Formal (Typ_Or_Subp);
+ begin
+ while Present (Formal) loop
+ if Matches_Param_Type (Etype (Formal)) then
+
+ -- Test whether Typ_Or_Subp (which is a subp
+ -- in this case) is primitive op of the type
+ -- of this parameter.
+ if Scope (Typ_Or_Subp) = Scope (Param_Type) then
+ return True;
+ end if;
+ end if;
+ Next_Formal (Formal);
+ end loop;
+ end;
+ end if;
+ end;
+
+ return False;
+ end Is_Property_Function;
+ begin
+ if not Is_Overloaded (Subp_Name) then
+ Subp := Entity (Subp_Name);
+ if not Is_Property_Function (Subp) then
+ Error_Msg_NE ("improper property function for&",
+ Subp_Name, Typ_Or_Subp);
+ return;
+ end if;
+ else
+ Set_Entity (Subp_Name, Empty);
+ Get_First_Interp (Subp_Name, I, It);
+ while Present (It.Nam) loop
+ if Is_Property_Function (It.Nam) then
+ if Present (Subp) then
+ Error_Msg_NE
+ ("ambiguous property function name for&",
+ Subp_Name, Typ_Or_Subp);
+ return;
+ end if;
+
+ Subp := It.Nam;
+ Set_Is_Overloaded (Subp_Name, False);
+ Set_Entity (Subp_Name, Subp);
+ end if;
+
+ Get_Next_Interp (I, It);
+ end loop;
+
+ if No (Subp) then
+ Error_Msg_NE ("improper property function for&",
+ Subp_Name, Typ_Or_Subp);
+ return;
+ end if;
+ end if;
+
+ -- perform legality (as opposed to name resolution) Subp checks
+
+ if Is_Limited_Type (Etype (Subp)) then
+ Error_Msg_NE
+ ("result type of property function for& is limited",
+ Subp_Name, Typ_Or_Subp);
+ end if;
+
+ if Ekind (First_Formal (Subp)) /= E_In_Parameter then
+ Error_Msg_NE
+ ("mode of parameter of property function for& is not IN",
+ Subp_Name, Typ_Or_Subp);
+ end if;
+
+ if Is_Class_Wide_Type (Etype (First_Formal (Subp))) then
+ if not Covers (Etype (First_Formal (Subp)), Typ_Or_Subp) then
+ Error_Msg_NE
+ ("class-wide parameter type of property function " &
+ "for& does not cover the type",
+ Subp_Name, Typ_Or_Subp);
+
+ -- ??? This test is slightly stricter than 7.3.4(12/5);
+ -- some legal corner cases may be incorrectly rejected.
+ elsif Scope (Subp) /= Scope (Etype (First_Formal (Subp)))
+ then
+ Error_Msg_NE
+ ("property function for& not declared in same scope " &
+ "as parameter type",
+ Subp_Name, Typ_Or_Subp);
+ end if;
+ elsif Is_Aspect_Of_Type and then
+ Scope (Subp) /= Scope (Typ_Or_Subp) and then
+ Scope (Subp) /= Standard_Standard -- e.g., derived type's "abs"
+ then
+ Error_Msg_NE
+ ("property function for& " &
+ "not a primitive function of the type",
+ Subp_Name, Typ_Or_Subp);
+ end if;
+
+ if Has_Not then
+ -- check that Subp was mentioned in param type's aspect spec
+ declare
+ Param_Type : constant Entity_Id :=
+ Base_Type (Etype (First_Formal (Subp)));
+ Aspect_Spec : constant Node_Id :=
+ Find_Value_Of_Aspect
+ (Param_Type, Aspect_Stable_Properties,
+ Class_Present => Class_Present);
+ Found : Boolean := False;
+ begin
+ if Present (Aspect_Spec) then
+ declare
+ Ignored : Boolean;
+ SPF_List : constant Subprogram_List :=
+ Parse_Aspect_Stable_Properties
+ (Aspect_Spec, Negated => Ignored);
+ begin
+ Found := (for some E of SPF_List => E = Subp);
+ -- look through renamings ???
+ end;
+ end if;
+ if not Found then
+ declare
+ CW_Modifier : constant String :=
+ (if Class_Present then "class-wide " else "");
+ begin
+ Error_Msg_NE
+ (CW_Modifier
+ & "property function for& mentioned after NOT "
+ & "but not a "
+ & CW_Modifier
+ & "stable property function of its parameter type",
+ Subp_Name, Typ_Or_Subp);
+ end;
+ end if;
+ end;
+ end if;
+ end;
+
+ exit when Singleton;
+ Subp_Name :=
+ Next ((if Has_Not then Parent (Subp_Name) else Subp_Name));
+ exit when No (Subp_Name);
+ end loop;
+
+ Set_Analyzed (Expr);
+ end Resolve_Aspect_Stable_Properties;
+
----------------
-- Set_Biased --
----------------
@@ -15781,303 +16225,6 @@ package body Sem_Ch13 is
end loop;
end Validate_Address_Clauses;
- ---------------------------
- -- Validate_Independence --
- ---------------------------
-
- procedure Validate_Independence is
- SU : constant Uint := UI_From_Int (System_Storage_Unit);
- N : Node_Id;
- E : Entity_Id;
- IC : Boolean;
- Comp : Entity_Id;
- Addr : Node_Id;
- P : Node_Id;
-
- procedure Check_Array_Type (Atyp : Entity_Id);
- -- Checks if the array type Atyp has independent components, and
- -- if not, outputs an appropriate set of error messages.
-
- procedure No_Independence;
- -- Output message that independence cannot be guaranteed
-
- function OK_Component (C : Entity_Id) return Boolean;
- -- Checks one component to see if it is independently accessible, and
- -- if so yields True, otherwise yields False if independent access
- -- cannot be guaranteed. This is a conservative routine, it only
- -- returns True if it knows for sure, it returns False if it knows
- -- there is a problem, or it cannot be sure there is no problem.
-
- procedure Reason_Bad_Component (C : Entity_Id);
- -- Outputs continuation message if a reason can be determined for
- -- the component C being bad.
-
- ----------------------
- -- Check_Array_Type --
- ----------------------
-
- procedure Check_Array_Type (Atyp : Entity_Id) is
- Ctyp : constant Entity_Id := Component_Type (Atyp);
-
- begin
- -- OK if no alignment clause, no pack, and no component size
-
- if not Has_Component_Size_Clause (Atyp)
- and then not Has_Alignment_Clause (Atyp)
- and then not Is_Packed (Atyp)
- then
- return;
- end if;
-
- -- Case where component size is greater than or equal to the maximum
- -- integer size and the alignment of the array is at least as large
- -- as the alignment of the component. We are OK in this situation.
-
- if Known_Component_Size (Atyp)
- and then Component_Size (Atyp) >= System_Max_Integer_Size
- and then Known_Alignment (Atyp)
- and then Known_Alignment (Ctyp)
- and then Alignment (Atyp) >= Alignment (Ctyp)
- then
- return;
- end if;
-
- -- Check actual component size
-
- if not Known_Component_Size (Atyp)
- or else not Addressable (Component_Size (Atyp))
- or else Component_Size (Atyp) mod Esize (Ctyp) /= 0
- then
- No_Independence;
-
- -- Bad component size, check reason
-
- if Has_Component_Size_Clause (Atyp) then
- P := Get_Attribute_Definition_Clause
- (Atyp, Attribute_Component_Size);
-
- if Present (P) then
- Error_Msg_Sloc := Sloc (P);
- Error_Msg_N ("\because of Component_Size clause#", N);
- return;
- end if;
- end if;
-
- if Is_Packed (Atyp) then
- P := Get_Rep_Pragma (Atyp, Name_Pack);
-
- if Present (P) then
- Error_Msg_Sloc := Sloc (P);
- Error_Msg_N ("\because of pragma Pack#", N);
- return;
- end if;
- end if;
-
- -- No reason found, just return
-
- return;
- end if;
-
- -- Array type is OK independence-wise
-
- return;
- end Check_Array_Type;
-
- ---------------------
- -- No_Independence --
- ---------------------
-
- procedure No_Independence is
- begin
- if Pragma_Name (N) = Name_Independent then
- Error_Msg_NE ("independence cannot be guaranteed for&", N, E);
- else
- Error_Msg_NE
- ("independent components cannot be guaranteed for&", N, E);
- end if;
- end No_Independence;
-
- ------------------
- -- OK_Component --
- ------------------
-
- function OK_Component (C : Entity_Id) return Boolean is
- Rec : constant Entity_Id := Scope (C);
- Ctyp : constant Entity_Id := Etype (C);
-
- begin
- -- OK if no component clause, no Pack, and no alignment clause
-
- if No (Component_Clause (C))
- and then not Is_Packed (Rec)
- and then not Has_Alignment_Clause (Rec)
- then
- return True;
- end if;
-
- -- Here we look at the actual component layout. A component is
- -- addressable if its size is a multiple of the Esize of the
- -- component type, and its starting position in the record has
- -- appropriate alignment, and the record itself has appropriate
- -- alignment to guarantee the component alignment.
-
- -- Make sure sizes are static, always assume the worst for any
- -- cases where we cannot check static values.
-
- if not (Known_Static_Esize (C)
- and then
- Known_Static_Esize (Ctyp))
- then
- return False;
- end if;
-
- -- Size of component must be addressable or greater than the maximum
- -- integer size and a multiple of bytes.
-
- if not Addressable (Esize (C))
- and then Esize (C) < System_Max_Integer_Size
- then
- return False;
- end if;
-
- -- Check size is proper multiple
-
- if Esize (C) mod Esize (Ctyp) /= 0 then
- return False;
- end if;
-
- -- Check alignment of component is OK
-
- if not Known_Component_Bit_Offset (C)
- or else Component_Bit_Offset (C) < Uint_0
- or else Component_Bit_Offset (C) mod Esize (Ctyp) /= 0
- then
- return False;
- end if;
-
- -- Check alignment of record type is OK
-
- if not Known_Alignment (Rec)
- or else (Alignment (Rec) * SU) mod Esize (Ctyp) /= 0
- then
- return False;
- end if;
-
- -- All tests passed, component is addressable
-
- return True;
- end OK_Component;
-
- --------------------------
- -- Reason_Bad_Component --
- --------------------------
-
- procedure Reason_Bad_Component (C : Entity_Id) is
- Rec : constant Entity_Id := Scope (C);
- Ctyp : constant Entity_Id := Etype (C);
-
- begin
- -- If component clause present assume that's the problem
-
- if Present (Component_Clause (C)) then
- Error_Msg_Sloc := Sloc (Component_Clause (C));
- Error_Msg_N ("\because of Component_Clause#", N);
- return;
- end if;
-
- -- If pragma Pack clause present, assume that's the problem
-
- if Is_Packed (Rec) then
- P := Get_Rep_Pragma (Rec, Name_Pack);
-
- if Present (P) then
- Error_Msg_Sloc := Sloc (P);
- Error_Msg_N ("\because of pragma Pack#", N);
- return;
- end if;
- end if;
-
- -- See if record has bad alignment clause
-
- if Has_Alignment_Clause (Rec)
- and then Known_Alignment (Rec)
- and then (Alignment (Rec) * SU) mod Esize (Ctyp) /= 0
- then
- P := Get_Attribute_Definition_Clause (Rec, Attribute_Alignment);
-
- if Present (P) then
- Error_Msg_Sloc := Sloc (P);
- Error_Msg_N ("\because of Alignment clause#", N);
- end if;
- end if;
-
- -- Couldn't find a reason, so return without a message
-
- return;
- end Reason_Bad_Component;
-
- -- Start of processing for Validate_Independence
-
- begin
- for J in Independence_Checks.First .. Independence_Checks.Last loop
- N := Independence_Checks.Table (J).N;
- E := Independence_Checks.Table (J).E;
- IC := Pragma_Name (N) = Name_Independent_Components;
-
- -- Deal with component case
-
- if Ekind (E) = E_Discriminant or else Ekind (E) = E_Component then
- if not OK_Component (E) then
- No_Independence;
- Reason_Bad_Component (E);
- goto Continue;
- end if;
- end if;
-
- -- Deal with record with Independent_Components
-
- if IC and then Is_Record_Type (E) then
- Comp := First_Component_Or_Discriminant (E);
- while Present (Comp) loop
- if not OK_Component (Comp) then
- No_Independence;
- Reason_Bad_Component (Comp);
- goto Continue;
- end if;
-
- Next_Component_Or_Discriminant (Comp);
- end loop;
- end if;
-
- -- Deal with address clause case
-
- if Is_Object (E) then
- Addr := Address_Clause (E);
-
- if Present (Addr) then
- No_Independence;
- Error_Msg_Sloc := Sloc (Addr);
- Error_Msg_N ("\because of Address clause#", N);
- goto Continue;
- end if;
- end if;
-
- -- Deal with independent components for array type
-
- if IC and then Is_Array_Type (E) then
- Check_Array_Type (E);
- end if;
-
- -- Deal with independent components for array object
-
- if IC and then Is_Object (E) and then Is_Array_Type (Etype (E)) then
- Check_Array_Type (Etype (E));
- end if;
-
- <<Continue>> null;
- end loop;
- end Validate_Independence;
-
------------------------------
-- Validate_Iterable_Aspect --
------------------------------
@@ -16177,12 +16324,31 @@ package body Sem_Ch13 is
Func_Name : constant Node_Id := Expression (ASN);
Overloaded : Boolean := Is_Overloaded (Func_Name);
- I : Interp_Index;
- It : Interp;
- Param_Type : Entity_Id;
- Match_Found : Boolean := False;
- Is_Match : Boolean;
- Match : Interp;
+ I : Interp_Index;
+ It : Interp;
+ Param_Type : Entity_Id;
+ Match_Found : Boolean := False;
+ Match2_Found : Boolean := False;
+ Is_Match : Boolean;
+ Match : Interp;
+ Match2 : Entity_Id := Empty;
+
+ function Matching
+ (Param_Id : Entity_Id; Param_Type : Entity_Id) return Boolean;
+ -- Return True if Param_Id is a non aliased in parameter whose base type
+ -- is Param_Type.
+
+ --------------
+ -- Matching --
+ --------------
+
+ function Matching
+ (Param_Id : Entity_Id; Param_Type : Entity_Id) return Boolean is
+ begin
+ return Base_Type (Etype (Param_Id)) = Param_Type
+ and then Ekind (Param_Id) = E_In_Parameter
+ and then not Is_Aliased (Param_Id);
+ end Matching;
begin
if not Is_Type (Typ) then
@@ -16228,26 +16394,45 @@ package body Sem_Ch13 is
Is_Match := False;
if Ekind (It.Nam) = E_Function
- and then Base_Type (Etype (It.Nam)) = Typ
+ and then Base_Type (Etype (It.Nam)) = Base_Type (Typ)
then
declare
Params : constant List_Id :=
Parameter_Specifications (Parent (It.Nam));
Param_Spec : Node_Id;
- Param_Id : Entity_Id;
begin
if List_Length (Params) = 1 then
Param_Spec := First (Params);
+ Is_Match :=
+ Matching (Defining_Identifier (Param_Spec), Param_Type);
+
+ -- Look for the optional overloaded 2-param Real_Literal
+
+ elsif List_Length (Params) = 2
+ and then A_Id = Aspect_Real_Literal
+ then
+ Param_Spec := First (Params);
- if not More_Ids (Param_Spec) then
- Param_Id := Defining_Identifier (Param_Spec);
+ if Matching (Defining_Identifier (Param_Spec), Param_Type)
+ then
+ Param_Spec := Next (Param_Spec);
- if Base_Type (Etype (Param_Id)) = Param_Type
- and then Ekind (Param_Id) = E_In_Parameter
- and then not Is_Aliased (Param_Id)
+ if Matching (Defining_Identifier (Param_Spec), Param_Type)
then
- Is_Match := True;
+ if No (Match2) then
+ Match2 := It.Nam;
+ Match2_Found := True;
+ else
+ -- If we find more than one possible match then
+ -- do not take any into account here: since the
+ -- 2-parameter version of Real_Literal is optional
+ -- we cannot generate an error here, so let
+ -- standard resolution fail later if we do need to
+ -- call this variant.
+
+ Match2_Found := False;
+ end if;
end if;
end if;
end if;
@@ -16282,6 +16467,12 @@ package body Sem_Ch13 is
Set_Entity (Func_Name, Match.Nam);
Set_Etype (Func_Name, Etype (Match.Nam));
Set_Is_Overloaded (Func_Name, False);
+
+ -- Record the match for 2-parameter function if found
+
+ if Match2_Found then
+ Set_Related_Expression (Match.Nam, Match2);
+ end if;
end Validate_Literal_Aspect;
-----------------------------------
diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads
index 7d9f38d..e2ea55a 100644
--- a/gcc/ada/sem_ch13.ads
+++ b/gcc/ada/sem_ch13.ads
@@ -23,8 +23,8 @@
-- --
------------------------------------------------------------------------------
-with Table;
with Types; use Types;
+with Sem_Disp; use Sem_Disp;
with Uintp; use Uintp;
package Sem_Ch13 is
@@ -147,6 +147,11 @@ package Sem_Ch13 is
-- used to verify the structure of the aspect, and resolve and expand an
-- aggregate for a container type that carries the aspect.
+ function Parse_Aspect_Stable_Properties
+ (Aspect_Spec : Node_Id; Negated : out Boolean) return Subprogram_List;
+ -- Utility to unpack the subprograms in a Stable_Properties list;
+ -- in the case of the aspect of a type, Negated will always be False.
+
function Rep_Item_Too_Early (T : Entity_Id; N : Node_Id) return Boolean;
-- Called at start of processing a representation clause/pragma. Used to
-- check that the representation item is not being applied to an incomplete
@@ -232,36 +237,6 @@ package Sem_Ch13 is
-- table of saved address clauses checking for suspicious alignments and
-- if necessary issuing warnings.
- procedure Validate_Independence;
- -- This is called after the back end has been called (and thus after the
- -- layout of components has been back annotated). It goes through the
- -- table of saved pragma Independent[_Component] entries, checking that
- -- independence can be achieved, and if necessary issuing error messages.
-
- -------------------------------------
- -- Table for Validate_Independence --
- -------------------------------------
-
- -- If a legal pragma Independent or Independent_Components is given for
- -- an entity, then an entry is made in this table, to be checked by a
- -- call to Validate_Independence after back annotation of layout is done.
-
- type Independence_Check_Record is record
- N : Node_Id;
- -- The pragma Independent or Independent_Components
-
- E : Entity_Id;
- -- The entity to which it applies
- end record;
-
- package Independence_Checks is new Table.Table (
- Table_Component_Type => Independence_Check_Record,
- Table_Index_Type => Int,
- Table_Low_Bound => 1,
- Table_Initial => 20,
- Table_Increment => 200,
- Table_Name => "Independence_Checks");
-
-----------------------------------
-- Handling of Aspect Visibility --
-----------------------------------
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 269818a..c01bce1 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -833,7 +833,7 @@ package body Sem_Ch3 is
if All_Present (N)
and then Ada_Version >= Ada_2005
then
- Error_Msg_N ("ALL is not permitted for anonymous access types", N);
+ Error_Msg_N ("ALL not permitted for anonymous access types", N);
end if;
-- Ada 2005 (AI-254): In case of anonymous access to subprograms call
@@ -1026,7 +1026,8 @@ package body Sem_Ch3 is
if Nkind (Def) in N_Has_Etype then
if Etype (Def) = T_Name then
Error_Msg_N
- ("type& cannot be used before end of its declaration", Def);
+ ("type& cannot be used before the end of its declaration",
+ Def);
end if;
-- If this is not a subtype, then this is an access_definition
@@ -1411,6 +1412,8 @@ package body Sem_Ch3 is
Set_Is_Tagged_Type (T, False);
end if;
+ Set_Etype (T, T);
+
-- For SPARK, check that the designated type is compatible with
-- respect to volatility with the access type.
@@ -1431,8 +1434,6 @@ package body Sem_Ch3 is
Srcpos_Bearer => T);
end if;
- Set_Etype (T, T);
-
-- If the type has appeared already in a with_type clause, it is frozen
-- and the pointer size is already set. Else, initialize.
@@ -2312,13 +2313,6 @@ package body Sem_Ch3 is
procedure Build_Assertion_Bodies_For_Type (Typ : Entity_Id) is
begin
- -- Preanalyze and resolve the Default_Initial_Condition assertion
- -- expression at the end of the declarations to catch any errors.
-
- if Has_DIC (Typ) then
- Build_DIC_Procedure_Body (Typ);
- end if;
-
if Nkind (Context) = N_Package_Specification then
-- Preanalyze and resolve the class-wide invariants of an
@@ -2341,32 +2335,57 @@ package body Sem_Ch3 is
Partial_Invariant => True);
end if;
- -- Preanalyze and resolve the invariants of a private type
- -- at the end of the visible declarations to catch potential
- -- errors. Inherited class-wide invariants are not included
- -- because they have already been resolved.
+ elsif Decls = Visible_Declarations (Context) then
+ -- Preanalyze and resolve the invariants of a private type
+ -- at the end of the visible declarations to catch potential
+ -- errors. Inherited class-wide invariants are not included
+ -- because they have already been resolved.
- elsif Decls = Visible_Declarations (Context)
- and then Ekind (Typ) in E_Limited_Private_Type
- | E_Private_Type
- | E_Record_Type_With_Private
- and then Has_Own_Invariants (Typ)
- then
- Build_Invariant_Procedure_Body
- (Typ => Typ,
- Partial_Invariant => True);
-
- -- Preanalyze and resolve the invariants of a private type's
- -- full view at the end of the private declarations to catch
- -- potential errors.
-
- elsif Decls = Private_Declarations (Context)
- and then (not Is_Private_Type (Typ)
- or else Present (Underlying_Full_View (Typ)))
- and then Has_Private_Declaration (Typ)
- and then Has_Invariants (Typ)
- then
- Build_Invariant_Procedure_Body (Typ);
+ if Ekind (Typ) in E_Limited_Private_Type
+ | E_Private_Type
+ | E_Record_Type_With_Private
+ and then Has_Own_Invariants (Typ)
+ then
+ Build_Invariant_Procedure_Body
+ (Typ => Typ,
+ Partial_Invariant => True);
+ end if;
+
+ -- Preanalyze and resolve the Default_Initial_Condition
+ -- assertion expression at the end of the declarations to
+ -- catch any errors.
+
+ if Ekind (Typ) in E_Limited_Private_Type
+ | E_Private_Type
+ | E_Record_Type_With_Private
+ and then Has_Own_DIC (Typ)
+ then
+ Build_DIC_Procedure_Body
+ (Typ => Typ,
+ Partial_DIC => True);
+ end if;
+
+ elsif Decls = Private_Declarations (Context) then
+
+ -- Preanalyze and resolve the invariants of a private type's
+ -- full view at the end of the private declarations to catch
+ -- potential errors.
+
+ if (not Is_Private_Type (Typ)
+ or else Present (Underlying_Full_View (Typ)))
+ and then Has_Private_Declaration (Typ)
+ and then Has_Invariants (Typ)
+ then
+ Build_Invariant_Procedure_Body (Typ);
+ end if;
+
+ if (not Is_Private_Type (Typ)
+ or else Present (Underlying_Full_View (Typ)))
+ and then Has_Private_Declaration (Typ)
+ and then Has_DIC (Typ)
+ then
+ Build_DIC_Procedure_Body (Typ);
+ end if;
end if;
end if;
end Build_Assertion_Bodies_For_Type;
@@ -12974,7 +12993,7 @@ package body Sem_Ch3 is
then
Error_Msg_N
("deferred constant must be declared in visible part",
- Parent (Prev));
+ Parent (Prev));
end if;
if Is_Access_Type (T)
@@ -14600,11 +14619,13 @@ package body Sem_Ch3 is
Comp_List : constant Elist_Id := New_Elmt_List;
Parent_Type : constant Entity_Id := Etype (Typ);
Assoc_List : constant List_Id := New_List;
- Discr_Val : Elmt_Id;
- Errors : Boolean;
- New_C : Entity_Id;
- Old_C : Entity_Id;
- Is_Static : Boolean := True;
+
+ Discr_Val : Elmt_Id;
+ Errors : Boolean;
+ New_C : Entity_Id;
+ Old_C : Entity_Id;
+ Is_Static : Boolean := True;
+ Is_Compile_Time_Known : Boolean := True;
procedure Collect_Fixed_Components (Typ : Entity_Id);
-- Collect parent type components that do not appear in a variant part
@@ -14754,7 +14775,11 @@ package body Sem_Ch3 is
while Present (Discr_Val) loop
if not Is_OK_Static_Expression (Node (Discr_Val)) then
Is_Static := False;
- exit;
+
+ if not Compile_Time_Known_Value (Node (Discr_Val)) then
+ Is_Compile_Time_Known := False;
+ exit;
+ end if;
end if;
Next_Elmt (Discr_Val);
@@ -14852,19 +14877,18 @@ package body Sem_Ch3 is
end if;
end Add_Discriminants;
- if Is_Static
+ if Is_Compile_Time_Known
and then Is_Variant_Record (Typ)
then
Collect_Fixed_Components (Typ);
-
- Gather_Components (
- Typ,
- Component_List (Type_Definition (Parent (Typ))),
- Governed_By => Assoc_List,
- Into => Comp_List,
- Report_Errors => Errors);
- pragma Assert (not Errors
- or else Serious_Errors_Detected > 0);
+ Gather_Components
+ (Typ,
+ Component_List (Type_Definition (Parent (Typ))),
+ Governed_By => Assoc_List,
+ Into => Comp_List,
+ Report_Errors => Errors,
+ Allow_Compile_Time => True);
+ pragma Assert (not Errors or else Serious_Errors_Detected > 0);
Create_All_Components;
@@ -14872,7 +14896,7 @@ package body Sem_Ch3 is
-- with constraints, we retrieve the record definition of the parent
-- type to select the components of the proper variant.
- elsif Is_Static
+ elsif Is_Compile_Time_Known
and then Is_Tagged_Type (Typ)
and then Nkind (Parent (Typ)) = N_Full_Type_Declaration
and then
@@ -14880,13 +14904,13 @@ package body Sem_Ch3 is
and then Is_Variant_Record (Parent_Type)
then
Collect_Fixed_Components (Typ);
-
Gather_Components
(Typ,
Component_List (Type_Definition (Parent (Parent_Type))),
- Governed_By => Assoc_List,
- Into => Comp_List,
- Report_Errors => Errors);
+ Governed_By => Assoc_List,
+ Into => Comp_List,
+ Report_Errors => Errors,
+ Allow_Compile_Time => True);
-- Note: previously there was a check at this point that no errors
-- were detected. As a consequence of AI05-220 there may be an error
@@ -14894,21 +14918,19 @@ package body Sem_Ch3 is
-- static constraint.
-- If the tagged derivation has a type extension, collect all the
- -- new components therein.
+ -- new relevant components therein via Gather_Components.
if Present (Record_Extension_Part (Type_Definition (Parent (Typ))))
then
- Old_C := First_Component (Typ);
- while Present (Old_C) loop
- if Original_Record_Component (Old_C) = Old_C
- and then Chars (Old_C) /= Name_uTag
- and then Chars (Old_C) /= Name_uParent
- then
- Append_Elmt (Old_C, Comp_List);
- end if;
-
- Next_Component (Old_C);
- end loop;
+ Gather_Components
+ (Typ,
+ Component_List
+ (Record_Extension_Part (Type_Definition (Parent (Typ)))),
+ Governed_By => Assoc_List,
+ Into => Comp_List,
+ Report_Errors => Errors,
+ Allow_Compile_Time => True,
+ Include_Interface_Tag => True);
end if;
Create_All_Components;
@@ -14945,6 +14967,10 @@ package body Sem_Ch3 is
Loc : constant Source_Ptr := Sloc (Def);
Digs_Expr : constant Node_Id := Digits_Expression (Def);
Delta_Expr : constant Node_Id := Delta_Expression (Def);
+ Max_Digits : constant Nat :=
+ (if System_Max_Integer_Size = 128 then 38 else 18);
+ -- Maximum number of digits that can be represented in an integer
+
Implicit_Base : Entity_Id;
Digs_Val : Uint;
Delta_Val : Ureal;
@@ -14982,9 +15008,10 @@ package body Sem_Ch3 is
Scale_Val := Scale_Val + 1;
end loop;
- if Scale_Val > 18 then
- Error_Msg_N ("scale exceeds maximum value of 18", Def);
- Scale_Val := UI_From_Int (+18);
+ if Scale_Val > Max_Digits then
+ Error_Msg_Uint_1 := UI_From_Int (Max_Digits);
+ Error_Msg_N ("scale exceeds maximum value of ^", Def);
+ Scale_Val := UI_From_Int (Max_Digits);
end if;
else
@@ -14993,9 +15020,10 @@ package body Sem_Ch3 is
Scale_Val := Scale_Val - 1;
end loop;
- if Scale_Val < -18 then
- Error_Msg_N ("scale is less than minimum value of -18", Def);
- Scale_Val := UI_From_Int (-18);
+ if Scale_Val < -Max_Digits then
+ Error_Msg_Uint_1 := UI_From_Int (-Max_Digits);
+ Error_Msg_N ("scale is less than minimum value of ^", Def);
+ Scale_Val := UI_From_Int (-Max_Digits);
end if;
end if;
@@ -15017,9 +15045,10 @@ package body Sem_Ch3 is
Check_Digits_Expression (Digs_Expr);
Digs_Val := Expr_Value (Digs_Expr);
- if Digs_Val > 18 then
- Digs_Val := UI_From_Int (+18);
- Error_Msg_N ("digits value out of range, maximum is 18", Digs_Expr);
+ if Digs_Val > Max_Digits then
+ Error_Msg_Uint_1 := UI_From_Int (Max_Digits);
+ Error_Msg_N ("digits value out of range, maximum is ^", Digs_Expr);
+ Digs_Val := UI_From_Int (Max_Digits);
end if;
Set_Digits_Value (Implicit_Base, Digs_Val);
@@ -16918,7 +16947,7 @@ package body Sem_Ch3 is
then
if Ada_Version = Ada_83 and then Comes_From_Source (Indic) then
Error_Msg_N
- ("(Ada 83): premature use of type for derivation", Indic);
+ ("(Ada 83) premature use of type for derivation", Indic);
end if;
end if;
@@ -20093,7 +20122,7 @@ package body Sem_Ch3 is
-- Per-Object Expressions" in spec of package Sem).
if Present (Expression (Discr)) then
- Preanalyze_Spec_Expression (Expression (Discr), Discr_Type);
+ Preanalyze_Default_Expression (Expression (Discr), Discr_Type);
-- Legaity checks
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index d06a4a8..7a8c261 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -2297,7 +2297,7 @@ package body Sem_Ch4 is
end if;
if Aliased_Present (A) then
- Error_Msg_N ("aliased not allowed in declare_expression", A);
+ Error_Msg_N ("ALIASED not allowed in declare_expression", A);
end if;
if Constant_Present (A)
@@ -2449,7 +2449,7 @@ package body Sem_Ch4 is
if Etype (N) = Any_Type then
Error_Msg_N
- ("type incompatible with that of `THEN` expression",
+ ("type incompatible with that of THEN expression",
Else_Expr);
return;
end if;
@@ -3414,7 +3414,7 @@ package body Sem_Ch4 is
Success := True;
-- If the prefix of the call is a name, indicate the entity
- -- being called. If it is not a name, it is an expression that
+ -- being called. If it is not a name, it is an expression that
-- denotes an access to subprogram or else an entry or family. In
-- the latter case, the name is a selected component, and the entity
-- being called is noted on the selector.
@@ -5455,7 +5455,7 @@ package body Sem_Ch4 is
Apply_Compile_Time_Constraint_Error
(N, "component not present in }??",
CE_Discriminant_Check_Failed,
- Ent => Prefix_Type, Rep => False);
+ Ent => Prefix_Type);
Set_Raises_Constraint_Error (N);
return;
@@ -5700,7 +5700,7 @@ package body Sem_Ch4 is
Error_Msg_N ("\use qualified expression instead", N);
elsif Nkind (Expr) = N_Allocator then
- Error_Msg_N ("argument of conversion cannot be an allocator", N);
+ Error_Msg_N ("argument of conversion cannot be allocator", N);
Error_Msg_N ("\use qualified expression instead", N);
elsif Nkind (Expr) = N_String_Literal then
@@ -5711,8 +5711,8 @@ package body Sem_Ch4 is
if Ada_Version = Ada_83 then
Resolve (Expr, Typ);
else
- Error_Msg_N ("argument of conversion cannot be character literal",
- N);
+ Error_Msg_N
+ ("argument of conversion cannot be character literal", N);
Error_Msg_N ("\use qualified expression instead", N);
end if;
@@ -5721,7 +5721,8 @@ package body Sem_Ch4 is
| Name_Unchecked_Access
| Name_Unrestricted_Access
then
- Error_Msg_N ("argument of conversion cannot be access", N);
+ Error_Msg_N
+ ("argument of conversion cannot be access attribute", N);
Error_Msg_N ("\use qualified expression instead", N);
end if;
@@ -8088,8 +8089,7 @@ package body Sem_Ch4 is
-- resolution does not depend on the type of the parameter that
-- includes the indexing operation.
- elsif Nkind (Parent (Par)) in
- N_Function_Call | N_Procedure_Call_Statement
+ elsif Nkind (Parent (Par)) in N_Subprogram_Call
and then Is_Entity_Name (Name (Parent (Par)))
then
declare
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 2afe18b..04fc980 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -192,12 +192,11 @@ package body Sem_Ch5 is
-- directly.
elsif (Is_Prival (Ent) and then Within_Function)
- or else
- (Ekind (Ent) = E_Component
- and then Is_Protected_Type (Scope (Ent)))
+ or else Is_Protected_Component (Ent)
then
Error_Msg_N
- ("protected function cannot modify protected object", N);
+ ("protected function cannot modify its protected object",
+ N);
return;
end if;
end;
@@ -305,9 +304,9 @@ package body Sem_Ch5 is
-- also have an actual subtype.
if Is_Entity_Name (Opnd)
- and then (Ekind (Entity (Opnd)) = E_Out_Parameter
- or else Ekind (Entity (Opnd)) in
- E_In_Out_Parameter | E_Generic_In_Out_Parameter
+ and then (Ekind (Entity (Opnd)) in E_Out_Parameter
+ | E_In_Out_Parameter
+ | E_Generic_In_Out_Parameter
or else
(Ekind (Entity (Opnd)) = E_Variable
and then Nkind (Parent (Entity (Opnd))) =
@@ -351,8 +350,6 @@ package body Sem_Ch5 is
function Should_Transform_BIP_Assignment
(Typ : Entity_Id) return Boolean
is
- Result : Boolean;
-
begin
if Expander_Active
and then not Is_Limited_View (Typ)
@@ -366,37 +363,33 @@ package body Sem_Ch5 is
-- parameterless function call if it denotes a function.
-- Finally, an attribute reference can be a function call.
- case Nkind (Unqual_Conv (Rhs)) is
- when N_Function_Call
- | N_Op
- =>
- Result := True;
-
- when N_Expanded_Name
- | N_Identifier
- =>
- case Ekind (Entity (Unqual_Conv (Rhs))) is
- when E_Function
- | E_Operator
- =>
- Result := True;
-
- when others =>
- Result := False;
- end case;
-
- when N_Attribute_Reference =>
- Result := Attribute_Name (Unqual_Conv (Rhs)) = Name_Input;
+ declare
+ Unqual_Rhs : constant Node_Id := Unqual_Conv (Rhs);
+ begin
+ case Nkind (Unqual_Rhs) is
+ when N_Function_Call
+ | N_Op
+ =>
+ return True;
+
+ when N_Expanded_Name
+ | N_Identifier
+ =>
+ return
+ Ekind (Entity (Unqual_Rhs)) in E_Function | E_Operator;
+
-- T'Input will turn into a call whose result type is T
- when others =>
- Result := False;
- end case;
+ when N_Attribute_Reference =>
+ return Attribute_Name (Unqual_Rhs) = Name_Input;
+
+ when others =>
+ return False;
+ end case;
+ end;
else
- Result := False;
+ return False;
end if;
-
- return Result;
end Should_Transform_BIP_Assignment;
------------------------------
@@ -713,7 +706,8 @@ package body Sem_Ch5 is
and then Convention (S) = Convention_Protected
then
Error_Msg_N
- ("protected function cannot modify protected object",
+ ("protected function cannot modify its protected " &
+ "object",
Lhs);
end if;
@@ -779,7 +773,7 @@ package body Sem_Ch5 is
if Is_Protected_Part_Of_Constituent (Lhs) and then Within_Function then
Error_Msg_N
- ("protected function cannot modify protected object", Lhs);
+ ("protected function cannot modify its protected object", Lhs);
end if;
-- Resolution may have updated the subtype, in case the left-hand side
@@ -962,7 +956,7 @@ package body Sem_Ch5 is
Apply_Compile_Time_Constraint_Error
(N => Rhs,
Msg =>
- "(Ada 2005) null not allowed in null-excluding objects??",
+ "(Ada 2005) NULL not allowed in null-excluding objects??",
Reason => CE_Null_Not_Allowed);
-- We still mark this as a possible modification, that's necessary
@@ -1395,16 +1389,7 @@ package body Sem_Ch5 is
----------------------------
procedure Analyze_Case_Statement (N : Node_Id) is
- Exp : Node_Id;
- Exp_Type : Entity_Id;
- Exp_Btype : Entity_Id;
- Last_Choice : Nat;
-
- Others_Present : Boolean;
- -- Indicates if Others was present
-
- pragma Warnings (Off, Last_Choice);
- -- Don't care about assigned value
+ Exp : constant Node_Id := Expression (N);
Statements_Analyzed : Boolean := False;
-- Set True if at least some statement sequences get analyzed. If False
@@ -1412,9 +1397,6 @@ package body Sem_Ch5 is
-- the case statement, and as a result it is not a good idea to output
-- warning messages about unreachable code.
- Save_Unblocked_Exit_Count : constant Nat := Unblocked_Exit_Count;
- -- Recursively save value of this global, will be restored on exit
-
procedure Non_Static_Choice_Error (Choice : Node_Id);
-- Error routine invoked by the generic instantiation below when the
-- case statement has a non static choice.
@@ -1474,8 +1456,7 @@ package body Sem_Ch5 is
if Is_Entity_Name (Exp) then
Ent := Entity (Exp);
- if Ekind (Ent) in E_Variable | E_In_Out_Parameter | E_Out_Parameter
- then
+ if Is_Assignable (Ent) then
if List_Length (Choices) = 1
and then Nkind (First (Choices)) in N_Subexpr
and then Compile_Time_Known_Value (First (Choices))
@@ -1499,11 +1480,20 @@ package body Sem_Ch5 is
Analyze_Statements (Statements (Alternative));
end Process_Statements;
+ -- Local variables
+
+ Exp_Type : Entity_Id;
+ Exp_Btype : Entity_Id;
+
+ Others_Present : Boolean;
+ -- Indicates if Others was present
+
+ Save_Unblocked_Exit_Count : constant Nat := Unblocked_Exit_Count;
+ -- Recursively save value of this global, will be restored on exit
+
-- Start of processing for Analyze_Case_Statement
begin
- Unblocked_Exit_Count := 0;
- Exp := Expression (N);
Analyze (Exp);
-- The expression must be of any discrete type. In rare cases, the
@@ -1567,7 +1557,9 @@ package body Sem_Ch5 is
Exp_Type := Exp_Btype;
end if;
- -- Call instantiated procedures to analyzwe and check discrete choices
+ -- Call instantiated procedures to analyze and check discrete choices
+
+ Unblocked_Exit_Count := 0;
Analyze_Choices (Alternatives (N), Exp_Type);
Check_Choices (N, Alternatives (N), Exp_Type, Others_Present);
@@ -1782,8 +1774,6 @@ package body Sem_Ch5 is
-- on which they depend will not be available at the freeze point.
procedure Analyze_If_Statement (N : Node_Id) is
- E : Node_Id;
-
Save_Unblocked_Exit_Count : constant Nat := Unblocked_Exit_Count;
-- Recursively save value of this global, will be restored on exit
@@ -1848,6 +1838,11 @@ package body Sem_Ch5 is
end if;
end Analyze_Cond_Then;
+ -- Local variables
+
+ E : Node_Id;
+ -- For iterating over elsif parts
+
-- Start of processing for Analyze_If_Statement
begin
@@ -2629,7 +2624,10 @@ package body Sem_Ch5 is
end if;
if Present (Iterator_Filter (N)) then
- Analyze_And_Resolve (Iterator_Filter (N), Standard_Boolean);
+ -- Preanalyze the filter. Expansion will take place when enclosing
+ -- loop is expanded.
+
+ Preanalyze_And_Resolve (Iterator_Filter (N), Standard_Boolean);
end if;
end Analyze_Iterator_Specification;
@@ -3026,6 +3024,9 @@ package body Sem_Ch5 is
begin
Set_Iterator_Specification (Scheme, I_Spec);
Set_Loop_Parameter_Specification (Scheme, Empty);
+ Set_Iterator_Filter (I_Spec,
+ Relocate_Node (Iterator_Filter (N)));
+
Analyze_Iterator_Specification (I_Spec);
-- In a generic context, analyze the original domain of
@@ -3098,7 +3099,10 @@ package body Sem_Ch5 is
Check_Predicate_Use (Entity (Subtype_Mark (DS)));
end if;
- Make_Index (DS, N);
+ if Nkind (DS) not in N_Raise_xxx_Error then
+ Make_Index (DS, N);
+ end if;
+
Set_Ekind (Id, E_Loop_Parameter);
-- A quantified expression which appears in a pre- or post-condition may
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 88bbdf7..7bab772 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -784,13 +784,49 @@ package body Sem_Ch6 is
------------------------------------------
procedure Check_Return_Construct_Accessibility (Return_Stmt : Node_Id) is
- Return_Con : Node_Id;
- Assoc : Node_Id := Empty;
- Assoc_Expr : Node_Id;
- Disc : Entity_Id;
+
+ function First_Selector (Assoc : Node_Id) return Node_Id;
+ -- Obtain the first selector or choice from a given association
+
+ --------------------
+ -- First_Selector --
+ --------------------
+
+ function First_Selector (Assoc : Node_Id) return Node_Id is
+ begin
+ if Nkind (Assoc) = N_Component_Association then
+ return First (Choices (Assoc));
+
+ elsif Nkind (Assoc) = N_Discriminant_Association then
+ return (First (Selector_Names (Assoc)));
+
+ else
+ raise Program_Error;
+ end if;
+ end First_Selector;
+
+ -- Local declarations
+
+ Assoc : Node_Id := Empty;
+ -- Assoc should perhaps be renamed and declared as a
+ -- Node_Or_Entity_Id since it encompasses not only component and
+ -- discriminant associations, but also discriminant components within
+ -- a type declaration or subtype indication ???
+
+ Assoc_Expr : Node_Id;
+ Assoc_Present : Boolean := False;
+
+ Unseen_Disc_Count : Nat := 0;
+ Seen_Discs : Elist_Id;
+ Disc : Entity_Id;
+ First_Disc : Entity_Id;
+
Obj_Decl : Node_Id;
+ Return_Con : Node_Id;
Unqual : Node_Id;
+ -- Start of processing for Check_Return_Construct_Accessibility
+
begin
-- Only perform checks on record types with access discriminants and
-- non-internally generated functions.
@@ -845,7 +881,7 @@ package body Sem_Ch6 is
Unqual := Unqualify (Original_Node (Return_Con));
- -- Obtain the corresponding declaration based on the return object's
+ -- Get the corresponding declaration based on the return object's
-- identifier.
if Nkind (Unqual) = N_Identifier
@@ -982,30 +1018,175 @@ package body Sem_Ch6 is
(Etype (Defining_Identifier (Obj_Decl)));
end if;
+ -- Preserve the first discriminant for checking named associations
+
+ First_Disc := Disc;
+
+ -- Count the number of discriminants for processing an aggregate
+ -- which includes an others.
+
+ Disc := First_Disc;
+ while Present (Disc) loop
+ Unseen_Disc_Count := Unseen_Disc_Count + 1;
+
+ Next_Discriminant (Disc);
+ end loop;
+
+ Seen_Discs := New_Elmt_List;
+
-- Loop through each of the discriminants and check each expression
-- associated with an anonymous access discriminant.
- while Present (Assoc) and then Present (Disc) loop
- -- Unwrap the associated expression
+ -- When named associations occur in the return aggregate then
+ -- discriminants can be in any order, so we need to ensure we do
+ -- not continue to loop when all discriminants have been seen.
+
+ Disc := First_Disc;
+ while Present (Assoc)
+ and then (Present (Disc) or else Assoc_Present)
+ and then Unseen_Disc_Count > 0
+ loop
+ -- Handle named associations by searching through the names of
+ -- the relevant discriminant components.
if Nkind (Assoc)
in N_Component_Association | N_Discriminant_Association
then
- Assoc_Expr := Expression (Assoc);
+ Assoc_Expr := Expression (Assoc);
+ Assoc_Present := True;
+
+ -- We currently don't handle box initialized discriminants,
+ -- however, since default initialized anonymous access
+ -- discriminants are a corner case, this is ok for now ???
+
+ if Nkind (Assoc) = N_Component_Association
+ and then Box_Present (Assoc)
+ then
+ Assoc_Present := False;
+
+ if Nkind (First_Selector (Assoc)) = N_Others_Choice then
+ Unseen_Disc_Count := 0;
+ end if;
+
+ -- When others is present we must identify a discriminant we
+ -- haven't already seen so as to get the appropriate type for
+ -- the static accessibility check.
+
+ -- This works because all components within an others clause
+ -- must have the same type.
+
+ elsif Nkind (First_Selector (Assoc)) = N_Others_Choice then
+
+ Disc := First_Disc;
+ Outer : while Present (Disc) loop
+ declare
+ Current_Seen_Disc : Elmt_Id;
+ begin
+ -- Move through the list of identified discriminants
+
+ Current_Seen_Disc := First_Elmt (Seen_Discs);
+ while Present (Current_Seen_Disc) loop
+ -- Exit the loop when we found a match
+
+ exit when
+ Chars (Node (Current_Seen_Disc)) = Chars (Disc);
+
+ Next_Elmt (Current_Seen_Disc);
+ end loop;
+
+ -- When we have exited the above loop without finding
+ -- a match then we know that Disc has not been seen.
+
+ exit Outer when No (Current_Seen_Disc);
+ end;
+
+ Next_Discriminant (Disc);
+ end loop Outer;
+
+ -- If we got to an others clause with a non-zero
+ -- discriminant count there must be a discriminant left to
+ -- check.
+
+ pragma Assert (Present (Disc));
+
+ -- Set the unseen discriminant count to zero because we know
+ -- an others clause sets all remaining components of an
+ -- aggregate.
+
+ Unseen_Disc_Count := 0;
+
+ -- Move through each of the selectors in the named association
+ -- and obtain a discriminant for accessibility checking if one
+ -- is referenced in the list. Also track which discriminants
+ -- are referenced for the purpose of handling an others clause.
+
+ else
+ declare
+ Assoc_Choice : Node_Id;
+ Curr_Disc : Node_Id;
+ begin
+
+ Disc := Empty;
+ Curr_Disc := First_Disc;
+ while Present (Curr_Disc) loop
+ -- Check each of the choices in the associations for a
+ -- match to the name of the current discriminant.
+
+ Assoc_Choice := First_Selector (Assoc);
+ while Present (Assoc_Choice) loop
+ -- When the name matches we track that we have seen
+ -- the discriminant, but instead of exiting the
+ -- loop we continue iterating to make sure all the
+ -- discriminants within the named association get
+ -- tracked.
+
+ if Chars (Assoc_Choice) = Chars (Curr_Disc) then
+ Append_Elmt (Curr_Disc, Seen_Discs);
+
+ Disc := Curr_Disc;
+ Unseen_Disc_Count := Unseen_Disc_Count - 1;
+ end if;
+
+ Next (Assoc_Choice);
+ end loop;
+
+ Next_Discriminant (Curr_Disc);
+ end loop;
+ end;
+ end if;
+
+ -- Unwrap the associated expression if we are looking at a default
+ -- initialized type declaration. In this case Assoc is not really
+ -- an association, but a component declaration. Should Assoc be
+ -- renamed in some way to be more clear ???
+
+ -- This occurs when the return object does not initialize
+ -- discriminant and instead relies on the type declaration for
+ -- their supplied values.
elsif Nkind (Assoc) in N_Entity
and then Ekind (Assoc) = E_Discriminant
then
- Assoc_Expr := Discriminant_Default_Value (Assoc);
+ Append_Elmt (Disc, Seen_Discs);
+
+ Assoc_Expr := Discriminant_Default_Value (Assoc);
+ Unseen_Disc_Count := Unseen_Disc_Count - 1;
+
+ -- Otherwise, there is nothing to do because Assoc is an
+ -- expression within the return aggregate itself.
else
- Assoc_Expr := Assoc;
+ Append_Elmt (Disc, Seen_Discs);
+
+ Assoc_Expr := Assoc;
+ Unseen_Disc_Count := Unseen_Disc_Count - 1;
end if;
-- Check the accessibility level of the expression when the
-- discriminant is of an anonymous access type.
if Present (Assoc_Expr)
+ and then Present (Disc)
and then Ekind (Etype (Disc)) = E_Anonymous_Access_Type
then
-- Perform a static check first, if possible
@@ -1019,8 +1200,8 @@ package body Sem_Ch6 is
Error_Msg_N
("access discriminant in return object would be a dangling"
& " reference", Return_Stmt);
- exit;
+ exit;
end if;
-- Otherwise, generate a dynamic check based on the extra
@@ -1041,9 +1222,16 @@ package body Sem_Ch6 is
end if;
end if;
- -- Iterate over the discriminants
+ -- Iterate over the discriminants, except when we have encountered
+ -- a named association since the discriminant order becomes
+ -- irrelevant in that case.
+
+ if not Assoc_Present then
+ Next_Discriminant (Disc);
+ end if;
+
+ -- Iterate over associations
- Disc := Next_Discriminant (Disc);
if not Is_List_Member (Assoc) then
exit;
else
@@ -1349,12 +1537,12 @@ package body Sem_Ch6 is
-- Can it really happen (extended return???)
Error_Msg_N
- ("aliased only allowed for limited return objects "
+ ("ALIASED only allowed for limited return objects "
& "in Ada 2012??", N);
elsif not Is_Limited_View (R_Type) then
Error_Msg_N
- ("aliased only allowed for limited return objects", N);
+ ("ALIASED only allowed for limited return objects", N);
end if;
end if;
@@ -1921,12 +2109,18 @@ package body Sem_Ch6 is
-- is just a string, as in (conjunction = "or"). In these cases the parser
-- generates this node, and the semantics does the disambiguation. Other
-- such case are actuals in an instantiation, the generic unit in an
- -- instantiation, and pragma arguments.
+ -- instantiation, pragma arguments, and aspect specifications.
procedure Analyze_Operator_Symbol (N : Node_Id) is
Par : constant Node_Id := Parent (N);
+ Maybe_Aspect_Spec : Node_Id := Par;
begin
+ if Nkind (Maybe_Aspect_Spec) /= N_Aspect_Specification then
+ -- deal with N_Aggregate nodes
+ Maybe_Aspect_Spec := Parent (Maybe_Aspect_Spec);
+ end if;
+
if (Nkind (Par) = N_Function_Call and then N = Name (Par))
or else Nkind (Par) = N_Function_Instantiation
or else (Nkind (Par) = N_Indexed_Component and then N = Prefix (Par))
@@ -1935,6 +2129,10 @@ package body Sem_Ch6 is
or else Nkind (Par) = N_Subprogram_Renaming_Declaration
or else (Nkind (Par) = N_Attribute_Reference
and then Attribute_Name (Par) /= Name_Value)
+ or else (Nkind (Maybe_Aspect_Spec) = N_Aspect_Specification
+ and then Get_Aspect_Id (Maybe_Aspect_Spec)
+ -- include other aspects here ???
+ in Aspect_Stable_Properties | Aspect_Aggregate)
then
Find_Direct_Name (N);
@@ -2232,6 +2430,26 @@ package body Sem_Ch6 is
else
Error_Msg_N ("invalid procedure or entry call", N);
+
+ -- Specialize the error message in the case where both a primitive
+ -- operation and a record component are visible at the same time.
+
+ if Nkind (P) = N_Selected_Component
+ and then Is_Entity_Name (Selector_Name (P))
+ then
+ declare
+ Sel : constant Entity_Id := Entity (Selector_Name (P));
+ begin
+ if Ekind (Sel) = E_Component
+ and then Present (Homonym (Sel))
+ and then Ekind (Homonym (Sel)) = E_Procedure
+ then
+ Error_Msg_NE ("\component & conflicts with"
+ & " homonym procedure (RM 4.1.3 (9.2/3))",
+ Selector_Name (P), Sel);
+ end if;
+ end;
+ end if;
end if;
<<Leave>>
@@ -2272,13 +2490,11 @@ package body Sem_Ch6 is
Result : Entity_Id := Empty;
begin
- -- Loop outward through the Scope_Stack, skipping blocks, loops,
- -- and postconditions.
+ -- Loop outward through the Scope_Stack, skipping blocks, and loops
for J in reverse 0 .. Scope_Stack.Last loop
Result := Scope_Stack.Table (J).Entity;
- exit when Ekind (Result) not in E_Block | E_Loop
- and then Chars (Result) /= Name_uPostconditions;
+ exit when Ekind (Result) not in E_Block | E_Loop;
end loop;
pragma Assert (Present (Result));
@@ -3023,10 +3239,10 @@ package body Sem_Ch6 is
-- Required to ensure that Expand_Call rewrites calls to this
-- function by calls to the built procedure.
- if Modify_Tree_For_C
+ if Transform_Function_Array
and then Nkind (Body_Spec) = N_Function_Specification
and then
- Rewritten_For_C (Defining_Entity (Specification (Subp_Decl)))
+ Rewritten_For_C (Defining_Entity (Specification (Subp_Decl)))
then
Set_Rewritten_For_C (Defining_Entity (Body_Spec));
Set_Corresponding_Procedure (Defining_Entity (Body_Spec),
@@ -4073,11 +4289,11 @@ package body Sem_Ch6 is
Build_Subprogram_Declaration;
-- If this is a function that returns a constrained array, and
- -- we are generating C code, create subprogram declaration
- -- to simplify subsequent C generation.
+ -- Transform_Function_Array is set, create subprogram
+ -- declaration to simplify e.g. subsequent C generation.
elsif No (Spec_Id)
- and then Modify_Tree_For_C
+ and then Transform_Function_Array
and then Nkind (Body_Spec) = N_Function_Specification
and then Is_Array_Type (Etype (Body_Id))
and then Is_Constrained (Etype (Body_Id))
@@ -4171,33 +4387,58 @@ package body Sem_Ch6 is
Spec_Id := Build_Internal_Protected_Declaration (N);
end if;
- -- If we are generating C and this is a function returning a constrained
- -- array type for which we must create a procedure with an extra out
- -- parameter, build and analyze the body now. The procedure declaration
- -- has already been created. We reuse the source body of the function,
- -- because in an instance it may contain global references that cannot
- -- be reanalyzed. The source function itself is not used any further,
- -- so we mark it as having a completion. If the subprogram is a stub the
- -- transformation is done later, when the proper body is analyzed.
+ -- If Transform_Function_Array is set and this is a function returning a
+ -- constrained array type for which we must create a procedure with an
+ -- extra out parameter, build and analyze the body now. The procedure
+ -- declaration has already been created. We reuse the source body of the
+ -- function, because in an instance it may contain global references
+ -- that cannot be reanalyzed. The source function itself is not used any
+ -- further, so we mark it as having a completion. If the subprogram is a
+ -- stub the transformation is done later, when the proper body is
+ -- analyzed.
if Expander_Active
- and then Modify_Tree_For_C
- and then Present (Spec_Id)
- and then Ekind (Spec_Id) = E_Function
+ and then Transform_Function_Array
and then Nkind (N) /= N_Subprogram_Body_Stub
- and then Rewritten_For_C (Spec_Id)
then
- Set_Has_Completion (Spec_Id);
+ declare
+ S : constant Entity_Id :=
+ (if Present (Spec_Id)
+ then Spec_Id
+ else Defining_Unit_Name (Specification (N)));
+ Proc_Body : Node_Id;
- Rewrite (N, Build_Procedure_Body_Form (Spec_Id, N));
- Analyze (N);
+ begin
+ if Ekind (S) = E_Function and then Rewritten_For_C (S) then
+ Set_Has_Completion (S);
+ Proc_Body := Build_Procedure_Body_Form (S, N);
- -- The entity for the created procedure must remain invisible, so it
- -- does not participate in resolution of subsequent references to the
- -- function.
+ if Present (Spec_Id) then
+ Rewrite (N, Proc_Body);
+ Analyze (N);
- Set_Is_Immediately_Visible (Corresponding_Spec (N), False);
- goto Leave;
+ -- The entity for the created procedure must remain
+ -- invisible, so it does not participate in resolution of
+ -- subsequent references to the function.
+
+ Set_Is_Immediately_Visible (Corresponding_Spec (N), False);
+
+ -- If we do not have a separate spec for N, build one and
+ -- insert the new body right after.
+
+ else
+ Rewrite (N,
+ Make_Subprogram_Declaration (Loc,
+ Specification => Relocate_Node (Specification (N))));
+ Analyze (N);
+ Insert_After_And_Analyze (N, Proc_Body);
+ Set_Is_Immediately_Visible
+ (Corresponding_Spec (Proc_Body), False);
+ end if;
+
+ goto Leave;
+ end if;
+ end;
end if;
-- If a separate spec is present, then deal with freezing issues
@@ -9727,7 +9968,7 @@ package body Sem_Ch6 is
Error_Msg_Sloc :=
Text_Ptr'Max (Sloc (Entity (E1)), Sloc (Entity (E2)));
Error_Msg_NE
- ("Meaning of& differs because of declaration#", E1, E2);
+ ("meaning of& differs because of declaration#", E1, E2);
end if;
return Result;
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 35c6f60..4689ae4 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -772,6 +772,31 @@ package body Sem_Ch8 is
-- Obtain the name of the object from node Nod which is being renamed by
-- the object renaming declaration N.
+ function Find_Raise_Node (N : Node_Id) return Traverse_Result;
+ -- Process one node in search for N_Raise_xxx_Error nodes.
+ -- Return Abandon if found, OK otherwise.
+
+ ---------------------
+ -- Find_Raise_Node --
+ ---------------------
+
+ function Find_Raise_Node (N : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (N) in N_Raise_xxx_Error then
+ return Abandon;
+ else
+ return OK;
+ end if;
+ end Find_Raise_Node;
+
+ ------------------------
+ -- No_Raise_xxx_Error --
+ ------------------------
+
+ function No_Raise_xxx_Error is new Traverse_Func (Find_Raise_Node);
+ -- Traverse tree to look for a N_Raise_xxx_Error node and returns
+ -- Abandon if so and OK if none found.
+
------------------------------
-- Check_Constrained_Object --
------------------------------
@@ -1038,6 +1063,22 @@ package body Sem_Ch8 is
Mark_Ghost_Renaming (N, Entity (Nam));
end if;
+ -- Check against AI12-0401 here before Resolve may rewrite Nam and
+ -- potentially generate spurious warnings.
+
+ if Nkind (Nam) = N_Qualified_Expression
+ and then Is_Variable (Expression (Nam))
+ and then not
+ (Subtypes_Statically_Match (T, Etype (Expression (Nam)))
+ or else
+ Subtypes_Statically_Match (Base_Type (T), Etype (Nam)))
+ then
+ Error_Msg_N
+ ("subtype of renamed qualified expression does not " &
+ "statically match", N);
+ return;
+ end if;
+
Resolve (Nam, T);
-- If the renamed object is a function call of a limited type,
@@ -1438,10 +1479,11 @@ package body Sem_Ch8 is
then
Error_Msg_N ("incompatible types in renaming", Nam);
- -- AI12-0383: Names that denote values can be renamed
+ -- AI12-0383: Names that denote values can be renamed.
+ -- Ignore (accept) N_Raise_xxx_Error nodes in this context.
- elsif Ada_Version < Ada_2020 then
- Error_Msg_N ("value in renaming requires -gnat2020", Nam);
+ elsif No_Raise_xxx_Error (Nam) = OK then
+ Error_Msg_Ada_2020_Feature ("value in renaming", Sloc (Nam));
end if;
Set_Etype (Id, T2);
@@ -5551,9 +5593,25 @@ package body Sem_Ch8 is
and then N = Prefix (Parent (N))
and then Is_Known_Unit (Parent (N))
then
- Error_Msg_Node_2 := Selector_Name (Parent (N));
- Error_Msg_N -- CODEFIX
- ("\\missing `WITH &.&;`", Prefix (Parent (N)));
+ declare
+ P : Node_Id := Parent (N);
+ begin
+ Error_Msg_Name_1 := Chars (N);
+ Error_Msg_Name_2 := Chars (Selector_Name (P));
+
+ if Nkind (Parent (P)) = N_Selected_Component
+ and then Is_Known_Unit (Parent (P))
+ then
+ P := Parent (P);
+ Error_Msg_Name_3 := Chars (Selector_Name (P));
+ Error_Msg_N -- CODEFIX
+ ("\\missing `WITH %.%.%;`", N);
+
+ else
+ Error_Msg_N -- CODEFIX
+ ("\\missing `WITH %.%;`", N);
+ end if;
+ end;
end if;
-- Now check for possible misspellings
@@ -5590,7 +5648,10 @@ package body Sem_Ch8 is
-- undefined reference. The entry is not added if we are ignoring
-- errors.
- if not All_Errors_Mode and then Ignore_Errors_Enable = 0 then
+ if not All_Errors_Mode
+ and then Ignore_Errors_Enable = 0
+ and then not Get_Ignore_Errors
+ then
Urefs.Append (
(Node => N,
Err => Emsg,
@@ -5643,8 +5704,7 @@ package body Sem_Ch8 is
-- happens for trees generated from Exp_Pakd, where expressions
-- can be deliberately "mis-typed" to the packed array type.
- if Is_Array_Type (Entyp)
- and then Is_Packed (Entyp)
+ if Is_Packed_Array (Entyp)
and then Present (Etype (N))
and then Etype (N) = Packed_Array_Impl_Type (Entyp)
then
@@ -5721,12 +5781,6 @@ package body Sem_Ch8 is
E := Homonym (E);
end loop;
- -- If we are ignoring errors, skip the error processing
-
- if Get_Ignore_Errors then
- return;
- end if;
-
-- If no entries on homonym chain that were potentially visible,
-- and no entities reasonably considered as non-visible, then
-- we have a plain undefined reference, with no additional
@@ -7504,7 +7558,7 @@ package body Sem_Ch8 is
-- Reference to type name in predicate/invariant expression
- elsif (Is_Task_Type (P_Type) or else Is_Protected_Type (P_Type))
+ elsif Is_Concurrent_Type (P_Type)
and then not In_Open_Scopes (P_Name)
and then (not Is_Concurrent_Type (Etype (P_Name))
or else not In_Open_Scopes (Etype (P_Name)))
@@ -7839,7 +7893,7 @@ package body Sem_Ch8 is
elsif Warn_On_Obsolescent_Feature and then False then
Error_Msg_N
- ("applying 'Class to an untagged incomplete type"
+ ("applying ''Class to an untagged incomplete type"
& " is an obsolescent feature (RM J.11)?r?", N);
end if;
end if;
@@ -8735,9 +8789,8 @@ package body Sem_Ch8 is
-- Mark primitives
- elsif (Ekind (Id) in Overloadable_Kind
- or else Ekind (Id) in
- E_Generic_Function | E_Generic_Procedure)
+ elsif (Is_Overloadable (Id)
+ or else Is_Generic_Subprogram (Id))
and then (Is_Potentially_Use_Visible (Id)
or else Is_Intrinsic_Subprogram (Id)
or else (Ekind (Id) in E_Function | E_Procedure
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index a9d720b..b7b7d7d 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -790,13 +790,13 @@ package body Sem_Ch9 is
if Kind /= E_Block and then Kind /= E_Loop
and then not Is_Entry (Task_Nam)
then
- Error_Msg_N ("enclosing body of accept must be a task", N);
+ Error_Msg_N ("enclosing body of ACCEPT must be a task", N);
return;
end if;
end loop;
if Ekind (Etype (Task_Nam)) /= E_Task_Type then
- Error_Msg_N ("invalid context for accept statement", N);
+ Error_Msg_N ("invalid context for ACCEPT statement", N);
return;
end if;
@@ -844,7 +844,7 @@ package body Sem_Ch9 is
end loop;
if Entry_Nam = Any_Id then
- Error_Msg_N ("no entry declaration matches accept statement", N);
+ Error_Msg_N ("no entry declaration matches ACCEPT statement", N);
return;
else
Set_Entity (Nam, Entry_Nam);
@@ -882,7 +882,7 @@ package body Sem_Ch9 is
if Entry_Nam = Scope_Stack.Table (J).Entity then
Error_Msg_N
- ("duplicate accept statement for same entry (RM 9.5.2 (15))", N);
+ ("duplicate ACCEPT statement for same entry (RM 9.5.2 (15))", N);
-- Do not continue analysis of accept statement, to prevent
-- cascaded errors.
@@ -904,8 +904,8 @@ package body Sem_Ch9 is
when N_Asynchronous_Select =>
Error_Msg_N
- ("accept statements are not allowed within an "
- & "asynchronous select inner to the enclosing task body",
+ ("ACCEPT statement not allowed within an "
+ & "asynchronous SELECT inner to the enclosing task body",
N);
exit;
@@ -2671,7 +2671,7 @@ package body Sem_Ch9 is
if Entity (EDN1) = Ent then
Error_Msg_Sloc := Sloc (Stm1);
Error_Msg_N
- ("accept duplicates one on line#??", Stm);
+ ("ACCEPT duplicates one on line#??", Stm);
exit;
end if;
end if;
@@ -2691,16 +2691,16 @@ package body Sem_Ch9 is
Check_Potentially_Blocking_Operation (N);
if Terminate_Present and Delay_Present then
- Error_Msg_N ("at most one of terminate or delay alternative", N);
+ Error_Msg_N ("at most one of TERMINATE or DELAY alternative", N);
elsif not Accept_Present then
Error_Msg_N
- ("select must contain at least one accept alternative", N);
+ ("SELECT must contain at least one ACCEPT alternative", N);
end if;
if Present (Else_Statements (N)) then
if Terminate_Present or Delay_Present then
- Error_Msg_N ("else part not allowed with other alternatives", N);
+ Error_Msg_N ("ELSE part not allowed with other alternatives", N);
end if;
Analyze_Statements (Else_Statements (N));
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index cf54337..36efa42 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -625,7 +625,7 @@ package body Sem_Disp is
Par := Parent (Par);
end if;
- if Nkind (Par) in N_Function_Call | N_Procedure_Call_Statement
+ if Nkind (Par) in N_Subprogram_Call
and then Is_Entity_Name (Name (Par))
then
declare
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index d7a8bb0..89b6e13 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -2414,10 +2414,16 @@ package body Sem_Elab is
-- Default_Initial_Condition
elsif Is_Default_Initial_Condition_Proc (Subp_Id) then
- Output_Verification_Call
- (Pred => "Default_Initial_Condition",
- Id => First_Formal_Type (Subp_Id),
- Id_Kind => "type");
+
+ -- Only do output for a normal DIC procedure, since partial DIC
+ -- procedures are subsidiary to those.
+
+ if not Is_Partial_DIC_Procedure (Subp_Id) then
+ Output_Verification_Call
+ (Pred => "Default_Initial_Condition",
+ Id => First_Formal_Type (Subp_Id),
+ Id_Kind => "type");
+ end if;
-- Entries
@@ -3738,7 +3744,7 @@ package body Sem_Elab is
Set_Is_Dispatching_Call
(Marker,
- Nkind (N) in N_Function_Call | N_Procedure_Call_Statement
+ Nkind (N) in N_Subprogram_Call
and then Present (Controlling_Argument (N)));
Set_Is_Elaboration_Checks_OK_Node
@@ -19362,7 +19368,7 @@ package body Sem_Elab is
function Is_Call_Of_Generic_Formal (N : Node_Id) return Boolean is
begin
- return Nkind (N) in N_Function_Call | N_Procedure_Call_Statement
+ return Nkind (N) in N_Subprogram_Call
-- Always return False if debug flag -gnatd.G is set
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 12f2822..8d47589 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -43,6 +43,7 @@ with Rtsfind; use Rtsfind;
with Sem; use Sem;
with Sem_Aux; use Sem_Aux;
with Sem_Cat; use Sem_Cat;
+with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch8; use Sem_Ch8;
with Sem_Elab; use Sem_Elab;
@@ -124,7 +125,7 @@ package body Sem_Eval is
type CV_Cache_Array is array (CV_Range) of CV_Entry;
- CV_Cache : CV_Cache_Array := (others => (Node_High_Bound, Uint_0));
+ CV_Cache : CV_Cache_Array;
-- This is the actual cache, with entries consisting of node/value pairs,
-- and the impossible value Node_High_Bound used for unset entries.
@@ -1855,6 +1856,12 @@ package body Sem_Eval is
N_Character_Literal | N_Real_Literal | N_String_Literal | N_Null
then
return True;
+
+ -- Evaluate static discriminants, to eliminate dead paths and
+ -- redundant discriminant checks.
+
+ elsif Is_Static_Discriminant_Component (Op) then
+ return True;
end if;
end if;
@@ -3731,83 +3738,81 @@ package body Sem_Eval is
Raises_Constraint_Error (Right)
then
return;
+ end if;
-- OK, we have the case where we may be able to do this fold
- else
- Left_Len := Static_Length (Left);
- Right_Len := Static_Length (Right);
+ Left_Len := Static_Length (Left);
+ Right_Len := Static_Length (Right);
- if Left_Len /= Uint_Minus_1
- and then Right_Len /= Uint_Minus_1
- and then Left_Len /= Right_Len
- then
- -- AI12-0201: comparison of string is static in Ada 202x
+ if Left_Len /= Uint_Minus_1
+ and then Right_Len /= Uint_Minus_1
+ and then Left_Len /= Right_Len
+ then
+ -- AI12-0201: comparison of string is static in Ada 202x
- Fold_Uint
- (N,
- Test (Nkind (N) = N_Op_Ne),
- Static => Ada_Version >= Ada_2020
- and then Is_String_Type (Left_Typ));
- Warn_On_Known_Condition (N);
- return;
- end if;
+ Fold_Uint
+ (N,
+ Test (Nkind (N) = N_Op_Ne),
+ Static => Ada_Version >= Ada_2020
+ and then Is_String_Type (Left_Typ));
+ Warn_On_Known_Condition (N);
+ return;
end if;
+ end if;
-- General case
- else
- -- Initialize the value of Is_Static_Expression. The value of Fold
- -- returned by Test_Expression_Is_Foldable is not needed since, even
- -- when some operand is a variable, we can still perform the static
- -- evaluation of the expression in some cases (for example, for a
- -- variable of a subtype of Integer we statically know that any value
- -- stored in such variable is smaller than Integer'Last).
-
- Test_Expression_Is_Foldable
- (N, Left, Right, Is_Static_Expression, Fold);
-
- -- Comparisons of scalars can give static results.
- -- In addition starting with Ada 202x (AI12-0201), comparison of
- -- strings can also give static results, and as noted above, we also
- -- allow for earlier Ada versions internally generated equality and
- -- inequality for strings.
- -- ??? The Comes_From_Source test below isn't correct and will accept
- -- some cases that are illegal in Ada 2012. and before. Now that
- -- Ada 202x has relaxed the rules, this doesn't really matter.
-
- if Is_String_Type (Left_Typ) then
- if Ada_Version < Ada_2020
- and then (Comes_From_Source (N)
- or else Nkind (N) not in N_Op_Eq | N_Op_Ne)
- then
- Is_Static_Expression := False;
- Set_Is_Static_Expression (N, False);
- end if;
+ -- Initialize the value of Is_Static_Expression. The value of Fold
+ -- returned by Test_Expression_Is_Foldable is not needed since, even
+ -- when some operand is a variable, we can still perform the static
+ -- evaluation of the expression in some cases (for example, for a
+ -- variable of a subtype of Integer we statically know that any value
+ -- stored in such variable is smaller than Integer'Last).
- elsif not Is_Scalar_Type (Left_Typ) then
+ Test_Expression_Is_Foldable
+ (N, Left, Right, Is_Static_Expression, Fold);
+
+ -- Comparisons of scalars can give static results.
+ -- In addition starting with Ada 202x (AI12-0201), comparison of strings
+ -- can also give static results, and as noted above, we also allow for
+ -- earlier Ada versions internally generated equality and inequality for
+ -- strings.
+ -- ??? The Comes_From_Source test below isn't correct and will accept
+ -- some cases that are illegal in Ada 2012. and before. Now that Ada
+ -- 202x has relaxed the rules, this doesn't really matter.
+
+ if Is_String_Type (Left_Typ) then
+ if Ada_Version < Ada_2020
+ and then (Comes_From_Source (N)
+ or else Nkind (N) not in N_Op_Eq | N_Op_Ne)
+ then
Is_Static_Expression := False;
Set_Is_Static_Expression (N, False);
end if;
- -- For operators on universal numeric types called as functions with
- -- an explicit scope, determine appropriate specific numeric type,
- -- and diagnose possible ambiguity.
+ elsif not Is_Scalar_Type (Left_Typ) then
+ Is_Static_Expression := False;
+ Set_Is_Static_Expression (N, False);
+ end if;
- if Is_Universal_Numeric_Type (Left_Typ)
- and then
- Is_Universal_Numeric_Type (Right_Typ)
- then
- Op_Typ := Find_Universal_Operator_Type (N);
- end if;
+ -- For operators on universal numeric types called as functions with an
+ -- explicit scope, determine appropriate specific numeric type, and
+ -- diagnose possible ambiguity.
+
+ if Is_Universal_Numeric_Type (Left_Typ)
+ and then
+ Is_Universal_Numeric_Type (Right_Typ)
+ then
+ Op_Typ := Find_Universal_Operator_Type (N);
+ end if;
- -- Attempt to fold the relational operator
+ -- Attempt to fold the relational operator
- if Is_Static_Expression and then Is_Real_Type (Left_Typ) then
- Fold_Static_Real_Op;
- else
- Fold_General_Op (Is_Static_Expression);
- end if;
+ if Is_Static_Expression and then Is_Real_Type (Left_Typ) then
+ Fold_Static_Real_Op;
+ else
+ Fold_General_Op (Is_Static_Expression);
end if;
-- For the case of a folded relational operator on a specific numeric
@@ -3820,6 +3825,24 @@ package body Sem_Eval is
Warn_On_Known_Condition (N);
end Eval_Relational_Op;
+ -----------------------------
+ -- Eval_Selected_Component --
+ -----------------------------
+
+ procedure Eval_Selected_Component (N : Node_Id) is
+ begin
+ -- If an attribute reference or a LHS, nothing to do.
+ -- Also do not fold if N is an [in] out subprogram parameter.
+ -- Fold will perform the other relevant tests.
+
+ if Nkind (Parent (N)) /= N_Attribute_Reference
+ and then Is_LHS (N) = No
+ and then not Is_Actual_Out_Or_In_Out_Parameter (N)
+ then
+ Fold (N);
+ end if;
+ end Eval_Selected_Component;
+
----------------
-- Eval_Shift --
----------------
@@ -3944,6 +3967,7 @@ package body Sem_Eval is
procedure Eval_Slice (N : Node_Id) is
Drange : constant Node_Id := Discrete_Range (N);
+ Name : constant Node_Id := Prefix (N);
begin
if Nkind (Drange) = N_Range then
@@ -3955,13 +3979,13 @@ package body Sem_Eval is
-- the type of A, is redundant, the slice can be replaced with A, and
-- this is worth a warning.
- if Is_Entity_Name (Prefix (N)) then
+ if Is_Entity_Name (Name) then
declare
- E : constant Entity_Id := Entity (Prefix (N));
+ E : constant Entity_Id := Entity (Name);
T : constant Entity_Id := Etype (E);
begin
- if Ekind (E) = E_Constant
+ if Is_Object (E)
and then Is_Array_Type (T)
and then Is_Entity_Name (Drange)
then
@@ -4360,8 +4384,62 @@ package body Sem_Eval is
-- processing is to check for a non-static context for the operand.
procedure Eval_Unchecked_Conversion (N : Node_Id) is
+ Target_Type : constant Entity_Id := Etype (N);
+ Operand : constant Node_Id := Expression (N);
+ Operand_Type : constant Entity_Id := Etype (Operand);
+
begin
- Check_Non_Static_Context (Expression (N));
+ Check_Non_Static_Context (Operand);
+
+ -- If we have a conversion of a compile time known value to a target
+ -- type and the value is in range of the target type, then we can simply
+ -- replace the construct by an integer literal of the correct type. We
+ -- only apply this to discrete types being converted. Possibly it may
+ -- apply in other cases, but it is too much trouble to worry about.
+
+ -- Note that we do not do this transformation if the Kill_Range_Check
+ -- flag is set, since then the value may be outside the expected range.
+ -- This happens in the Normalize_Scalars case.
+
+ -- We also skip this if either the target or operand type is biased
+ -- because in this case, the unchecked conversion is supposed to
+ -- preserve the bit pattern, not the integer value.
+
+ if Is_Integer_Type (Target_Type)
+ and then not Has_Biased_Representation (Target_Type)
+ and then Is_Discrete_Type (Operand_Type)
+ and then not Has_Biased_Representation (Operand_Type)
+ and then Compile_Time_Known_Value (Operand)
+ and then not Kill_Range_Check (N)
+ then
+ declare
+ Val : constant Uint := Expr_Rep_Value (Operand);
+
+ begin
+ if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
+ and then
+ Compile_Time_Known_Value (Type_High_Bound (Target_Type))
+ and then
+ Val >= Expr_Value (Type_Low_Bound (Target_Type))
+ and then
+ Val <= Expr_Value (Type_High_Bound (Target_Type))
+ then
+ Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
+
+ -- If Address is the target type, just set the type to avoid a
+ -- spurious type error on the literal when Address is a visible
+ -- integer type.
+
+ if Is_Descendant_Of_Address (Target_Type) then
+ Set_Etype (N, Target_Type);
+ else
+ Analyze_And_Resolve (N, Target_Type);
+ end if;
+
+ return;
+ end if;
+ end;
+ end if;
end Eval_Unchecked_Conversion;
--------------------
@@ -4434,6 +4512,15 @@ package body Sem_Eval is
elsif Kind = N_Unchecked_Type_Conversion then
return Expr_Rep_Value (Expression (N));
+ -- Static discriminant value
+
+ elsif Is_Static_Discriminant_Component (N) then
+ return Expr_Rep_Value
+ (Get_Discriminant_Value
+ (Entity (Selector_Name (N)),
+ Etype (Prefix (N)),
+ Discriminant_Constraint (Etype (Prefix (N)))));
+
else
raise Program_Error;
end if;
@@ -4521,6 +4608,15 @@ package body Sem_Eval is
elsif Kind = N_Unchecked_Type_Conversion then
Val := Expr_Value (Expression (N));
+ -- Static discriminant value
+
+ elsif Is_Static_Discriminant_Component (N) then
+ Val := Expr_Value
+ (Get_Discriminant_Value
+ (Entity (Selector_Name (N)),
+ Etype (Prefix (N)),
+ Discriminant_Constraint (Etype (Prefix (N)))));
+
else
raise Program_Error;
end if;
@@ -4748,6 +4844,32 @@ package body Sem_Eval is
end if;
end Flag_Non_Static_Expr;
+ ----------
+ -- Fold --
+ ----------
+
+ procedure Fold (N : Node_Id) is
+ Typ : constant Entity_Id := Etype (N);
+ begin
+ -- If not known at compile time or if already a literal, nothing to do
+
+ if Nkind (N) in N_Numeric_Or_String_Literal
+ or else not Compile_Time_Known_Value (N)
+ then
+ null;
+
+ elsif Is_Discrete_Type (Typ) then
+ Fold_Uint (N, Expr_Value (N), Static => Is_Static_Expression (N));
+
+ elsif Is_Real_Type (Typ) then
+ Fold_Ureal (N, Expr_Value_R (N), Static => Is_Static_Expression (N));
+
+ elsif Is_String_Type (Typ) then
+ Fold_Str
+ (N, Strval (Expr_Value_S (N)), Static => Is_Static_Expression (N));
+ end if;
+ end Fold;
+
----------------
-- Fold_Dummy --
----------------
@@ -4786,7 +4908,7 @@ package body Sem_Eval is
Static : Boolean := False;
Check_Elab : Boolean := False)
is
- Typ : constant Entity_Id := Etype (Left);
+ Typ : constant Entity_Id := Base_Type (Etype (Left));
procedure Check_Elab_Call;
-- Add checks related to calls in elaboration code
@@ -4806,6 +4928,8 @@ package body Sem_Eval is
end if;
end Check_Elab_Call;
+ Modulus : Uint;
+
begin
if Compile_Time_Known_Value (Left)
and then Compile_Time_Known_Value (Right)
@@ -4815,30 +4939,55 @@ package body Sem_Eval is
if Op = N_Op_Shift_Left then
Check_Elab_Call;
- -- Fold Shift_Left (X, Y) by computing (X * 2**Y) rem modulus
+ declare
+ Modulus : Uint;
+ begin
+ if Is_Modular_Integer_Type (Typ) then
+ Modulus := Einfo.Modulus (Typ);
+ else
+ Modulus := Uint_2 ** RM_Size (Typ);
+ end if;
+
+ -- Fold Shift_Left (X, Y) by computing (X * 2**Y) rem modulus
- Fold_Uint
- (N,
- (Expr_Value (Left) * (Uint_2 ** Expr_Value (Right)))
- rem Modulus (Typ),
- Static => Static);
+ Fold_Uint
+ (N,
+ (Expr_Value (Left) * (Uint_2 ** Expr_Value (Right)))
+ rem Modulus,
+ Static => Static);
+ end;
elsif Op = N_Op_Shift_Right then
Check_Elab_Call;
- -- Fold Shift_Right (X, Y) by computing abs X / 2**Y
+ -- X >> 0 is a no-op
- Fold_Uint
- (N,
- abs Expr_Value (Left) / (Uint_2 ** Expr_Value (Right)),
- Static => Static);
+ if Expr_Value (Right) = Uint_0 then
+ Fold_Uint (N, Expr_Value (Left), Static => Static);
+ else
+ if Is_Modular_Integer_Type (Typ) then
+ Modulus := Einfo.Modulus (Typ);
+ else
+ Modulus := Uint_2 ** RM_Size (Typ);
+ end if;
+
+ -- Fold X >> Y by computing (X [+ Modulus]) / 2**Y
+ -- Note that after a Shift_Right operation (with Y > 0), the
+ -- result is always positive, even if the original operand was
+ -- negative.
+ Fold_Uint
+ (N,
+ (Expr_Value (Left) +
+ (if Expr_Value (Left) >= Uint_0 then Uint_0 else Modulus))
+ / (Uint_2 ** Expr_Value (Right)),
+ Static => Static);
+ end if;
elsif Op = N_Op_Shift_Right_Arithmetic then
Check_Elab_Call;
declare
Two_Y : constant Uint := Uint_2 ** Expr_Value (Right);
- Modulus : Uint;
begin
if Is_Modular_Integer_Type (Typ) then
Modulus := Einfo.Modulus (Typ);
@@ -6301,11 +6450,13 @@ package body Sem_Eval is
if Subtypes_Statically_Match (T1, T2) then
return True;
- -- If either subtype is nonstatic then they're not compatible
+ -- A scalar subtype S1 is compatible with S2 if their bounds
+ -- are static and compatible, even if S1 has dynamic predicates
+ -- and is thus non-static. Predicate compatibility has been
+ -- checked above.
- elsif not Is_OK_Static_Subtype (T1)
- or else
- not Is_OK_Static_Subtype (T2)
+ elsif not Is_Static_Range (Scalar_Range (T1))
+ or else not Is_Static_Range (Scalar_Range (T2))
then
return False;
@@ -6353,6 +6504,14 @@ package body Sem_Eval is
and then not (Can_Never_Be_Null (T2)
and then not Can_Never_Be_Null (T1));
+ -- Private types without discriminants can be handled specially.
+ -- Predicate matching has been checked above.
+
+ elsif Is_Private_Type (T1)
+ and then not Has_Discriminants (T1)
+ then
+ return not Has_Discriminants (T2);
+
-- All other cases
else
@@ -7318,7 +7477,7 @@ package body Sem_Eval is
elsif Ekind (E) = E_Constant then
- -- One case we can give a metter message is when we have a
+ -- One case we can give a better message is when we have a
-- string literal created by concatenating an aggregate with
-- an others expression.
diff --git a/gcc/ada/sem_eval.ads b/gcc/ada/sem_eval.ads
index 76e4bdf..972cee6 100644
--- a/gcc/ada/sem_eval.ads
+++ b/gcc/ada/sem_eval.ads
@@ -330,6 +330,7 @@ package Sem_Eval is
procedure Eval_Op_Not (N : Node_Id);
procedure Eval_Real_Literal (N : Node_Id);
procedure Eval_Relational_Op (N : Node_Id);
+ procedure Eval_Selected_Component (N : Node_Id);
procedure Eval_Shift (N : Node_Id);
procedure Eval_Short_Circuit (N : Node_Id);
procedure Eval_Slice (N : Node_Id);
@@ -387,6 +388,10 @@ package Sem_Eval is
-- The call has no effect if Raises_Constraint_Error (N) is True, since
-- there is no point in folding if we have an error.
+ procedure Fold (N : Node_Id);
+ -- Rewrite N with the relevant value if Compile_Time_Known_Value (N) is
+ -- True, otherwise a no-op.
+
function Is_In_Range
(N : Node_Id;
Typ : Entity_Id;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 1e1a279..3ef5e82 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -466,7 +466,7 @@ package body Sem_Prag is
if Nkind (Case_Guard) = N_Others_Choice then
if Others_Seen then
Error_Msg_N
- ("only one others choice allowed in contract cases",
+ ("only one OTHERS choice allowed in contract cases",
Case_Guard);
else
Others_Seen := True;
@@ -474,7 +474,7 @@ package body Sem_Prag is
elsif Others_Seen then
Error_Msg_N
- ("others must be the last choice in contract cases", N);
+ ("OTHERS must be the last choice in contract cases", N);
end if;
-- Preanalyze the case guard and consequence
@@ -545,16 +545,31 @@ package body Sem_Prag is
-- Single and multiple contract cases must appear in aggregate form. If
-- this is not the case, then either the parser or the analysis of the
- -- pragma failed to produce an aggregate.
+ -- pragma failed to produce an aggregate, e.g. when the contract is
+ -- "null" or a "(null record)".
- pragma Assert (Nkind (CCases) = N_Aggregate);
+ pragma Assert
+ (if Nkind (CCases) = N_Aggregate
+ then Null_Record_Present (CCases)
+ xor (Present (Component_Associations (CCases))
+ or
+ Present (Expressions (CCases)))
+ else Nkind (CCases) = N_Null);
-- Only CASE_GUARD => CONSEQUENCE clauses are allowed
- if Present (Component_Associations (CCases))
+ if Nkind (CCases) = N_Aggregate
+ and then Present (Component_Associations (CCases))
and then No (Expressions (CCases))
then
+ -- Check that the expression is a proper aggregate (no parentheses)
+
+ if Paren_Count (CCases) /= 0 then
+ Error_Msg -- CODEFIX
+ ("redundant parentheses", First_Sloc (CCases));
+ end if;
+
-- Ensure that the formal parameters are visible when analyzing all
-- clauses. This falls out of the general rule of aspects pertaining
-- to subprogram declarations.
@@ -1267,9 +1282,9 @@ package body Sem_Prag is
(Item_Is_Input : out Boolean;
Item_Is_Output : out Boolean)
is
- -- A constant or IN parameter of access type should be handled
- -- like a variable, as the underlying memory pointed-to can be
- -- modified. Use Adjusted_Kind to do this adjustment.
+ -- A constant or IN parameter of access-to-variable type should be
+ -- handled like a variable, as the underlying memory pointed-to
+ -- can be modified. Use Adjusted_Kind to do this adjustment.
Adjusted_Kind : Entity_Kind := Ekind (Item_Id);
@@ -1277,7 +1292,7 @@ package body Sem_Prag is
if Ekind (Item_Id) in E_Constant
| E_Generic_In_Parameter
| E_In_Parameter
- and then Is_Access_Type (Etype (Item_Id))
+ and then Is_Access_Variable (Etype (Item_Id))
then
Adjusted_Kind := E_Variable;
end if;
@@ -1975,7 +1990,7 @@ package body Sem_Prag is
-- clause as this will lead to misleading errors.
if Has_Extra_Parentheses (Deps) then
- return;
+ goto Leave;
end if;
if Present (Component_Associations (Deps)) then
@@ -2066,7 +2081,7 @@ package body Sem_Prag is
else
Error_Msg_N ("malformed dependency relation", Deps);
- return;
+ goto Leave;
end if;
-- The top level dependency relation is malformed. This is a syntax
@@ -2383,9 +2398,9 @@ package body Sem_Prag is
("global item must denote object, state or current "
& "instance of concurrent type", Item);
- if Ekind (Item_Id) in Named_Kind then
+ if Is_Named_Number (Item_Id) then
SPARK_Msg_NE
- ("\named number & is not an object", Item, Item);
+ ("\named number & is not an object", Item, Item_Id);
end if;
return;
@@ -2476,11 +2491,22 @@ package body Sem_Prag is
and then Ekind (Item_Id) = E_Variable
and then Is_Effectively_Volatile_For_Reading (Item_Id)
then
+ -- The current instance of a protected unit is not an
+ -- effectively volatile object, unless the protected unit
+ -- is already volatile for another reason (SPARK RM 7.1.2).
+
+ if Is_Single_Protected_Object (Item_Id)
+ and then Is_CCT_Instance (Etype (Item_Id), Spec_Id)
+ and then not Is_Effectively_Volatile_For_Reading
+ (Item_Id, Ignore_Protected => True)
+ then
+ null;
+
-- An effectively volatile object for reading cannot appear
-- as a global item of a nonvolatile function (SPARK RM
-- 7.1.3(8)).
- if Ekind (Spec_Id) in E_Function | E_Generic_Function
+ elsif Ekind (Spec_Id) in E_Function | E_Generic_Function
and then not Is_Volatile_Function (Spec_Id)
then
Error_Msg_NE
@@ -4062,7 +4088,8 @@ package body Sem_Prag is
-- than library level instantiations these can appear in contexts which
-- would normally be invalid (they only apply to the original template
-- and to library level instantiations), and they are simply ignored,
- -- which is implemented by rewriting them as null statements.
+ -- which is implemented by rewriting them as null statements and raising
+ -- exception to terminate analysis.
procedure Check_Variant (Variant : Node_Id; UU_Typ : Entity_Id);
-- Check an Unchecked_Union variant for lack of nested variants and
@@ -4437,7 +4464,17 @@ package body Sem_Prag is
-- Subprogram declaration
elsif Nkind (Subp_Decl) = N_Subprogram_Declaration then
- null;
+
+ -- Pragmas Global and Depends are forbidden on null procedures
+ -- (SPARK RM 6.1.2(2)).
+
+ if Nkind (Specification (Subp_Decl)) = N_Procedure_Specification
+ and then Null_Present (Specification (Subp_Decl))
+ then
+ Error_Msg_N (Fix_Error
+ ("pragma % cannot apply to null procedure"), N);
+ return;
+ end if;
-- Task type
@@ -6069,7 +6106,7 @@ package body Sem_Prag is
-- The group and the current pragma are not in the same
-- declarative or statement list.
- if List_Containing (Stmt) /= List_Containing (N) then
+ if not In_Same_List (Stmt, N) then
Grouping_Error (Stmt);
-- Try to reach the current pragma from the first pragma
@@ -6173,17 +6210,15 @@ package body Sem_Prag is
--------------------
function Is_Loop_Pragma (Stmt : Node_Id) return Boolean is
+ Original_Stmt : constant Node_Id := Original_Node (Stmt);
+
begin
-- Inspect the original node as Loop_Invariant and Loop_Variant
-- pragmas are rewritten to null when assertions are disabled.
- if Nkind (Original_Node (Stmt)) = N_Pragma then
- return
- Pragma_Name_Unmapped (Original_Node (Stmt))
+ return Nkind (Original_Stmt) = N_Pragma
+ and then Pragma_Name_Unmapped (Original_Stmt)
in Name_Loop_Invariant | Name_Loop_Variant;
- else
- return False;
- end if;
end Is_Loop_Pragma;
---------------------
@@ -6567,7 +6602,7 @@ package body Sem_Prag is
if Loc not in Source_First (Sindex) .. Source_Last (Sindex) then
Rewrite (N, Make_Null_Statement (Loc));
- return;
+ raise Pragma_Exit;
-- If before first declaration, the pragma applies to the
-- enclosing unit, and the name if present must be this name.
@@ -8100,7 +8135,7 @@ package body Sem_Prag is
-- Check that we are not applying this to a named constant
- if Ekind (E) in E_Named_Integer | E_Named_Real then
+ if Is_Named_Number (E) then
Error_Msg_Name_1 := Pname;
Error_Msg_N
("cannot apply pragma% to named constant!",
@@ -8841,7 +8876,7 @@ package body Sem_Prag is
Error_Pragma ("at least one parameter required for pragma%");
elsif Ekind (Formal) /= E_Out_Parameter then
- Error_Pragma ("first parameter must have mode out for pragma%");
+ Error_Pragma ("first parameter must have mode OUT for pragma%");
else
Set_Is_Valued_Procedure (Ent);
@@ -9866,7 +9901,7 @@ package body Sem_Prag is
-- the test will have been applied to the original generic.
elsif Nkind (Decl) in N_Formal_Subprogram_Declaration
- and then List_Containing (Decl) = List_Containing (N)
+ and then In_Same_List (Decl, N)
and then not In_Instance
then
Error_Msg_N
@@ -10418,10 +10453,13 @@ package body Sem_Prag is
Add_To_Config_Boolean_Restrictions (No_Elaboration_Code);
end if;
- -- Special processing for No_Tasking restriction placed in
- -- a configuration pragmas file.
+ -- Special processing for No_Tasking restriction (not just a
+ -- warning) when it appears as a configuration pragma.
- elsif R_Id = No_Tasking and then No (Cunit (Main_Unit)) then
+ elsif R_Id = No_Tasking
+ and then No (Cunit (Main_Unit))
+ and then not Warn
+ then
Set_Global_No_Tasking;
end if;
@@ -11343,19 +11381,26 @@ package body Sem_Prag is
-- Deal with unrecognized pragma
if not Is_Pragma_Name (Pname) then
- if Warn_On_Unrecognized_Pragma then
- Error_Msg_Name_1 := Pname;
- Error_Msg_N ("?g?unrecognized pragma%!", Pragma_Identifier (N));
-
- for PN in First_Pragma_Name .. Last_Pragma_Name loop
- if Is_Bad_Spelling_Of (Pname, PN) then
- Error_Msg_Name_1 := PN;
- Error_Msg_N -- CODEFIX
- ("\?g?possible misspelling of %!", Pragma_Identifier (N));
- exit;
- end if;
- end loop;
- end if;
+ declare
+ Msg_Issued : Boolean := False;
+ begin
+ Check_Restriction
+ (Msg_Issued, No_Unrecognized_Pragmas, Pragma_Identifier (N));
+ if not Msg_Issued and then Warn_On_Unrecognized_Pragma then
+ Error_Msg_Name_1 := Pname;
+ Error_Msg_N ("?g?unrecognized pragma%!", Pragma_Identifier (N));
+
+ for PN in First_Pragma_Name .. Last_Pragma_Name loop
+ if Is_Bad_Spelling_Of (Pname, PN) then
+ Error_Msg_Name_1 := PN;
+ Error_Msg_N -- CODEFIX
+ ("\?g?possible misspelling of %!",
+ Pragma_Identifier (N));
+ exit;
+ end if;
+ end loop;
+ end if;
+ end;
return;
end if;
@@ -11411,6 +11456,12 @@ package body Sem_Prag is
end if;
end if;
+ -- Mark assertion pragmas as Ghost depending on their enclosing context
+
+ if Assertion_Expression_Pragma (Prag_Id) then
+ Mark_Ghost_Pragma (N, Current_Scope);
+ end if;
+
-- Preset arguments
Arg_Count := 0;
@@ -11711,7 +11762,7 @@ package body Sem_Prag is
if Nkind (Prop) = N_Others_Choice then
if Others_Seen then
SPARK_Msg_N
- ("only one others choice allowed in option External",
+ ("only one OTHERS choice allowed in option External",
Prop);
else
Others_Seen := True;
@@ -11719,7 +11770,7 @@ package body Sem_Prag is
elsif Others_Seen then
SPARK_Msg_N
- ("others must be the last property in option External",
+ ("OTHERS must be the last property in option External",
Prop);
-- The only remaining legal options are the four predefined
@@ -12519,10 +12570,6 @@ package body Sem_Prag is
Check_Ada_83_Warning;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Lib_Entity := Find_Lib_Unit_Name;
-- A pragma that applies to a Ghost entity becomes Ghost for the
@@ -12871,30 +12918,31 @@ package body Sem_Prag is
-- ASSERTION_KIND ::= RM_ASSERTION_KIND | ID_ASSERTION_KIND
- -- RM_ASSERTION_KIND ::= Assert |
- -- Static_Predicate |
- -- Dynamic_Predicate |
- -- Pre |
- -- Pre'Class |
- -- Post |
- -- Post'Class |
- -- Type_Invariant |
- -- Type_Invariant'Class
-
- -- ID_ASSERTION_KIND ::= Assert_And_Cut |
- -- Assume |
- -- Contract_Cases |
- -- Debug |
- -- Default_Initial_Condition |
- -- Ghost |
- -- Initial_Condition |
- -- Loop_Invariant |
- -- Loop_Variant |
- -- Postcondition |
- -- Precondition |
- -- Predicate |
- -- Refined_Post |
- -- Statement_Assertions
+ -- RM_ASSERTION_KIND ::= Assert |
+ -- Static_Predicate |
+ -- Dynamic_Predicate |
+ -- Pre |
+ -- Pre'Class |
+ -- Post |
+ -- Post'Class |
+ -- Type_Invariant |
+ -- Type_Invariant'Class |
+ -- Default_Initial_Condition
+
+ -- ID_ASSERTION_KIND ::= Assert_And_Cut |
+ -- Assume |
+ -- Contract_Cases |
+ -- Debug |
+ -- Ghost |
+ -- Initial_Condition |
+ -- Loop_Invariant |
+ -- Loop_Variant |
+ -- Postcondition |
+ -- Precondition |
+ -- Predicate |
+ -- Refined_Post |
+ -- Statement_Assertions |
+ -- Subprogram_Variant
-- Note: The RM_ASSERTION_KIND list is language-defined, and the
-- ID_ASSERTION_KIND list contains implementation-defined additions
@@ -15079,7 +15127,7 @@ package body Sem_Prag is
begin
GNAT_Pragma;
Check_No_Identifiers;
- Check_At_Most_N_Arguments (1);
+ Check_At_Most_N_Arguments (2); -- Accounts for implicit type arg
Typ := Empty;
Stmt := Prev (N);
@@ -15142,6 +15190,27 @@ package body Sem_Prag is
Set_Has_Own_DIC (Typ);
+ -- A type entity argument is appended to facilitate inheriting the
+ -- aspect/pragma from parent types (see Build_DIC_Procedure_Body),
+ -- though that extra argument isn't documented for the pragma.
+
+ if not Present (Arg2) then
+ -- When the pragma has no arguments, create an argument with
+ -- the value Empty, so the type name argument can be appended
+ -- following it (since it's expected as the second argument).
+
+ if not Present (Arg1) then
+ Set_Pragma_Argument_Associations (N, New_List (
+ Make_Pragma_Argument_Association (Sloc (Typ),
+ Expression => Empty)));
+ end if;
+
+ Append_To
+ (Pragma_Argument_Associations (N),
+ Make_Pragma_Argument_Association (Sloc (Typ),
+ Expression => New_Occurrence_Of (Typ, Sloc (Typ))));
+ end if;
+
-- Chain the pragma on the rep item chain for further processing
Discard := Rep_Item_Too_Late (Typ, N, FOnly => True);
@@ -15713,10 +15782,6 @@ package body Sem_Prag is
Check_Ada_83_Warning;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Cunit_Node := Cunit (Current_Sem_Unit);
Cunit_Ent := Cunit_Entity (Current_Sem_Unit);
@@ -18508,7 +18573,7 @@ package body Sem_Prag is
-- The pragma defines a type-specific invariant, the type is said
-- to have invariants of its "own".
- Set_Has_Own_Invariants (Typ);
+ Set_Has_Own_Invariants (Base_Type (Typ));
-- If the invariant is class-wide, then it can be inherited by
-- derived or interface implementing types. The type is said to
@@ -19421,10 +19486,6 @@ package body Sem_Prag is
GNAT_Pragma;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
-- Must appear for a spec or generic spec
if Nkind (Unit (Cunit (Current_Sem_Unit))) not in
@@ -19646,7 +19707,53 @@ package body Sem_Prag is
-- pragma No_Return (procedure_LOCAL_NAME {, procedure_Local_Name});
- when Pragma_No_Return => No_Return : declare
+ when Pragma_No_Return => Prag_No_Return : declare
+
+ function Check_No_Return
+ (E : Entity_Id;
+ N : Node_Id) return Boolean;
+ -- Check rule 6.5.1(4/3) of the Ada RM. If the rule is violated,
+ -- emit an error message and return False, otherwise return True.
+ -- 6.5.1 Nonreturning procedures:
+ -- 4/3 "Aspect No_Return shall not be specified for a null
+ -- procedure nor an instance of a generic unit."
+
+ ---------------------
+ -- Check_No_Return --
+ ---------------------
+
+ function Check_No_Return
+ (E : Entity_Id;
+ N : Node_Id) return Boolean
+ is
+ begin
+ if Ekind (E) = E_Procedure then
+
+ -- If E is a generic instance, marking it with No_Return
+ -- is forbidden, but having it inherit the No_Return of
+ -- the generic is allowed. We check if E is inheriting its
+ -- No_Return flag from the generic by checking if No_Return
+ -- is already set.
+
+ if Is_Generic_Instance (E) and then not No_Return (E) then
+ Error_Msg_NE
+ ("generic instance & is marked as No_Return", N, E);
+ Error_Msg_NE
+ ("\generic procedure & must be marked No_Return",
+ N,
+ Generic_Parent (Parent (E)));
+ return False;
+
+ elsif Null_Present (Subprogram_Specification (E)) then
+ Error_Msg_NE
+ ("null procedure & cannot be marked No_Return", N, E);
+ return False;
+ end if;
+ end if;
+
+ return True;
+ end Check_No_Return;
+
Arg : Node_Id;
E : Entity_Id;
Found : Boolean;
@@ -19718,7 +19825,9 @@ package body Sem_Prag is
end if;
end if;
- Set_No_Return (E);
+ if Check_No_Return (E, N) then
+ Set_No_Return (E);
+ end if;
-- A pragma that applies to a Ghost entity becomes Ghost
-- for the purposes of legality checks and removal of
@@ -19757,7 +19866,10 @@ package body Sem_Prag is
-- Set flag on any alias as well
- if Is_Overloadable (E) and then Present (Alias (E)) then
+ if Is_Overloadable (E)
+ and then Present (Alias (E))
+ and then Check_No_Return (Alias (E), N)
+ then
Set_No_Return (Alias (E));
end if;
@@ -19774,6 +19886,7 @@ package body Sem_Prag is
if not Found then
if Entity (Id) = Current_Scope
and then From_Aspect_Specification (N)
+ and then Check_No_Return (Entity (Id), N)
then
Set_No_Return (Entity (Id));
@@ -19788,7 +19901,7 @@ package body Sem_Prag is
Next (Arg);
end loop;
- end No_Return;
+ end Prag_No_Return;
-----------------
-- No_Run_Time --
@@ -21158,10 +21271,6 @@ package body Sem_Prag is
Check_Ada_83_Warning;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Ent := Find_Lib_Unit_Name;
-- A pragma that applies to a Ghost entity becomes Ghost for the
@@ -21270,16 +21379,11 @@ package body Sem_Prag is
-- package does not trigger the required initialization of the
-- run-time library.
- declare
- Discard : Entity_Id;
- pragma Warnings (Off, Discard);
- begin
- if Restricted_Profile then
- Discard := RTE (RE_Activate_Restricted_Tasks);
- else
- Discard := RTE (RE_Activate_Tasks);
- end if;
- end;
+ if Restricted_Profile then
+ Discard_Node (RTE (RE_Activate_Restricted_Tasks));
+ else
+ Discard_Node (RTE (RE_Activate_Tasks));
+ end if;
-- Task or Protected, must be of type Integer
@@ -21462,7 +21566,11 @@ package body Sem_Prag is
Argx : constant Node_Id := Get_Pragma_Arg (Arg1);
begin
- if Chars (Argx) = Name_Ravenscar then
+ if Nkind (Argx) /= N_Identifier then
+ Error_Msg_N
+ ("argument of pragma Profile must be an identifier", N);
+
+ elsif Chars (Argx) = Name_Ravenscar then
Set_Ravenscar_Profile (Ravenscar, N);
elsif Chars (Argx) = Name_Jorvik then
@@ -21803,10 +21911,6 @@ package body Sem_Prag is
Check_Valid_Library_Unit_Pragma;
end if;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Ent := Find_Lib_Unit_Name;
-- A pragma that applies to a Ghost entity becomes Ghost for the
@@ -22343,10 +22447,6 @@ package body Sem_Prag is
Check_Ada_83_Warning;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Cunit_Node := Cunit (Current_Sem_Unit);
K := Nkind (Unit (Cunit_Node));
Cunit_Ent := Cunit_Entity (Current_Sem_Unit);
@@ -22386,10 +22486,6 @@ package body Sem_Prag is
Check_Ada_83_Warning;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Cunit_Node := Cunit (Current_Sem_Unit);
Cunit_Ent := Cunit_Entity (Current_Sem_Unit);
@@ -22586,10 +22682,6 @@ package body Sem_Prag is
Check_Ada_83_Warning;
Check_Valid_Library_Unit_Pragma;
- if Nkind (N) = N_Null_Statement then
- return;
- end if;
-
Cunit_Node := Cunit (Current_Sem_Unit);
Cunit_Ent := Cunit_Entity (Current_Sem_Unit);
@@ -24773,18 +24865,15 @@ package body Sem_Prag is
-- body, not in the spec).
when Pragma_Unimplemented_Unit => Unimplemented_Unit : declare
- Cunitent : constant Entity_Id :=
+ Cunitent : constant Entity_Id :=
Cunit_Entity (Get_Source_Unit (Loc));
- Ent_Kind : constant Entity_Kind := Ekind (Cunitent);
begin
GNAT_Pragma;
Check_Arg_Count (0);
if Operating_Mode = Generate_Code
- or else Ent_Kind = E_Generic_Function
- or else Ent_Kind = E_Generic_Procedure
- or else Ent_Kind = E_Generic_Package
+ or else Is_Generic_Unit (Cunitent)
then
Get_Name_String (Chars (Cunitent));
Set_Casing (Mixed_Case);
@@ -28414,35 +28503,69 @@ package body Sem_Prag is
Constit, Encapsulating_State (Constit_Id));
end if;
- -- The only other source of legal constituents is the body
- -- state space of the related package.
-
else
- if Present (Body_States) then
- State_Elmt := First_Elmt (Body_States);
- while Present (State_Elmt) loop
+ declare
+ Pack_Id : Entity_Id;
+ Placement : State_Space_Kind;
+ begin
+ -- Find where the constituent lives with respect to the
+ -- state space.
- -- Consume a valid constituent to signal that it has
- -- been encountered.
+ Find_Placement_In_State_Space
+ (Item_Id => Constit_Id,
+ Placement => Placement,
+ Pack_Id => Pack_Id);
- if Node (State_Elmt) = Constit_Id then
- Remove_Elmt (Body_States, State_Elmt);
- Collect_Constituent;
- return;
- end if;
+ -- The constituent is part of the visible state of a
+ -- private child package, but lacks a Part_Of indicator.
- Next_Elmt (State_Elmt);
- end loop;
- end if;
+ if Placement = Visible_State_Space
+ and then Is_Child_Unit (Pack_Id)
+ and then not Is_Generic_Unit (Pack_Id)
+ and then Is_Private_Descendant (Pack_Id)
+ then
+ Error_Msg_Name_1 := Chars (State_Id);
+ SPARK_Msg_NE
+ ("& cannot act as constituent of state %",
+ Constit, Constit_Id);
+ Error_Msg_Sloc :=
+ Sloc (Enclosing_Declaration (Constit_Id));
+ SPARK_Msg_NE
+ ("\missing Part_Of indicator # should specify "
+ & "encapsulator &",
+ Constit, State_Id);
- -- At this point it is known that the constituent is not
- -- part of the package hidden state and cannot be used in
- -- a refinement (SPARK RM 7.2.2(9)).
+ -- The only other source of legal constituents is the
+ -- body state space of the related package.
- Error_Msg_Name_1 := Chars (Spec_Id);
- SPARK_Msg_NE
- ("cannot use & in refinement, constituent is not a hidden "
- & "state of package %", Constit, Constit_Id);
+ else
+ if Present (Body_States) then
+ State_Elmt := First_Elmt (Body_States);
+ while Present (State_Elmt) loop
+
+ -- Consume a valid constituent to signal that it
+ -- has been encountered.
+
+ if Node (State_Elmt) = Constit_Id then
+ Remove_Elmt (Body_States, State_Elmt);
+ Collect_Constituent;
+ return;
+ end if;
+
+ Next_Elmt (State_Elmt);
+ end loop;
+ end if;
+
+ -- At this point it is known that the constituent is
+ -- not part of the package hidden state and cannot be
+ -- used in a refinement (SPARK RM 7.2.2(9)).
+
+ Error_Msg_Name_1 := Chars (Spec_Id);
+ SPARK_Msg_NE
+ ("cannot use & in refinement, constituent is not a "
+ & "hidden state of package %", Constit, Constit_Id);
+ end if;
+ end;
end if;
end Match_Constituent;
@@ -28864,6 +28987,20 @@ package body Sem_Prag is
-- in the refinement clause.
Report_Unused_Constituents (Part_Of_Constits);
+
+ -- Avoid a cascading error reporting a missing refinement by adding a
+ -- dummy constituent.
+
+ if No (Refinement_Constituents (State_Id)) then
+ Set_Refinement_Constituents (State_Id, New_Elmt_List (Any_Id));
+ end if;
+
+ -- At this point the refinement might be dummy, but must be
+ -- well-formed, to prevent cascaded errors.
+
+ pragma Assert (Has_Null_Refinement (State_Id)
+ xor
+ Has_Non_Null_Refinement (State_Id));
end Analyze_Refinement_Clause;
-----------------------------
@@ -29048,16 +29185,31 @@ package body Sem_Prag is
-- Single and multiple contract cases must appear in aggregate form. If
-- this is not the case, then either the parser of the analysis of the
- -- pragma failed to produce an aggregate.
+ -- pragma failed to produce an aggregate, e.g. when the contract is
+ -- "null" or a "(null record)".
- pragma Assert (Nkind (Variants) = N_Aggregate);
+ pragma Assert
+ (if Nkind (Variants) = N_Aggregate
+ then Null_Record_Present (Variants)
+ xor (Present (Component_Associations (Variants))
+ or
+ Present (Expressions (Variants)))
+ else Nkind (Variants) = N_Null);
-- Only "change_direction => discrete_expression" clauses are allowed
- if Present (Component_Associations (Variants))
+ if Nkind (Variants) = N_Aggregate
+ and then Present (Component_Associations (Variants))
and then No (Expressions (Variants))
then
+ -- Check that the expression is a proper aggregate (no parentheses)
+
+ if Paren_Count (Variants) /= 0 then
+ Error_Msg -- CODEFIX
+ ("redundant parentheses", First_Sloc (Variants));
+ end if;
+
-- Ensure that the formal parameters are visible when analyzing all
-- clauses. This falls out of the general rule of aspects pertaining
-- to subprogram declarations.
@@ -30096,13 +30248,23 @@ package body Sem_Prag is
Formal := First_Entity (Spec_Id);
while Present (Formal) loop
if Ekind (Formal) in E_In_Out_Parameter | E_In_Parameter then
+
+ -- IN parameters can act as output when the related type is
+ -- access-to-variable.
+
+ if Ekind (Formal) = E_In_Parameter
+ and then Is_Access_Variable (Etype (Formal))
+ then
+ Append_New_Elmt (Formal, Subp_Outputs);
+ end if;
+
Append_New_Elmt (Formal, Subp_Inputs);
end if;
if Ekind (Formal) in E_In_Out_Parameter | E_Out_Parameter then
Append_New_Elmt (Formal, Subp_Outputs);
- -- Out parameters can act as inputs when the related type is
+ -- OUT parameters can act as inputs when the related type is
-- tagged, unconstrained array, unconstrained record, or record
-- with unconstrained components.
@@ -30137,7 +30299,7 @@ package body Sem_Prag is
Global := Get_Pragma (Subp_Id, Pragma_Refined_Global);
-- Subprogram declaration or stand-alone body case, look for pragmas
- -- Depends and Global
+ -- Depends and Global.
else
Depends := Get_Pragma (Spec_Id, Pragma_Depends);
@@ -30381,11 +30543,11 @@ package body Sem_Prag is
if From_Aspect_Specification (Prag) then
Error_Msg_N
- ("aspect % cannot apply to a stand alone expression function",
+ ("aspect % cannot apply to a standalone expression function",
Prag);
else
Error_Msg_N
- ("pragma % cannot apply to a stand alone expression function",
+ ("pragma % cannot apply to a standalone expression function",
Prag);
end if;
end Expression_Function_Error;
@@ -30519,8 +30681,10 @@ package body Sem_Prag is
-- The pragma appears inside the statements of a subprogram body. This
-- placement is the result of subprogram contract expansion.
- elsif Nkind (Context) = N_Handled_Sequence_Of_Statements then
- return Parent (Context);
+ elsif Is_Statement (Context)
+ and then Present (Enclosing_HSS (Context))
+ then
+ return Parent (Enclosing_HSS (Context));
-- The pragma appears inside the declarative part of a package body
@@ -31417,7 +31581,6 @@ package body Sem_Prag is
-- RM defined
Name_Assert
- | Name_Assertion_Policy
| Name_Static_Predicate
| Name_Dynamic_Predicate
| Name_Pre
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index a24c9c2..f6e0eab 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -2155,6 +2155,10 @@ package body Sem_Res is
N_Real_Literal => Aspect_Real_Literal,
N_String_Literal => Aspect_String_Literal);
+ Named_Number_Aspect_Map : constant array (Named_Kind) of Aspect_Id :=
+ (E_Named_Integer => Aspect_Integer_Literal,
+ E_Named_Real => Aspect_Real_Literal);
+
-- Start of processing for Resolve
begin
@@ -2294,11 +2298,8 @@ package body Sem_Res is
-- Declare_Expression and requires scope management.
if Nkind (N) = N_Expression_With_Actions then
- if Comes_From_Source (N)
- and then N = Original_Node (N)
- then
+ if Comes_From_Source (N) and then N = Original_Node (N) then
Resolve_Declare_Expression (N, Typ);
-
else
Resolve (Expression (N), Typ);
end if;
@@ -2880,58 +2881,102 @@ package body Sem_Res is
-- Rewrite Literal as a call if the corresponding literal aspect
-- is set.
- if Nkind (N) in N_Numeric_Or_String_Literal
- and then Present
- (Find_Aspect (Typ, Literal_Aspect_Map (Nkind (N))))
+ if (Nkind (N) in N_Numeric_Or_String_Literal
+ and then
+ Present
+ (Find_Aspect (Typ, Literal_Aspect_Map (Nkind (N)))))
+ or else
+ (Nkind (N) = N_Identifier
+ and then Is_Named_Number (Entity (N))
+ and then
+ Present
+ (Find_Aspect
+ (Typ, Named_Number_Aspect_Map (Ekind (Entity (N))))))
then
declare
- function Literal_Text (N : Node_Id) return String_Id;
- -- Returns the text of a literal node
+ Lit_Aspect : constant Aspect_Id :=
+ (if Nkind (N) = N_Identifier
+ then Named_Number_Aspect_Map (Ekind (Entity (N)))
+ else Literal_Aspect_Map (Nkind (N)));
- -------------------
- -- Literal_Text --
- -------------------
+ Loc : constant Source_Ptr := Sloc (N);
- function Literal_Text (N : Node_Id) return String_Id is
- begin
- pragma Assert (Nkind (N) in N_Numeric_Or_String_Literal);
+ Callee : Entity_Id :=
+ Entity (Expression (Find_Aspect (Typ, Lit_Aspect)));
- if Nkind (N) = N_String_Literal then
- return Strval (N);
- else
- return String_From_Numeric_Literal (N);
- end if;
- end Literal_Text;
+ Name : constant Node_Id :=
+ Make_Identifier (Loc, Chars (Callee));
- Lit_Aspect : constant Aspect_Id :=
- Literal_Aspect_Map (Nkind (N));
+ Param1 : Node_Id;
+ Param2 : Node_Id;
+ Params : List_Id;
+ Call : Node_Id;
+ Expr : Node_Id;
- Callee : constant Entity_Id :=
- Entity (Expression (Find_Aspect (Typ, Lit_Aspect)));
+ begin
+ if Nkind (N) = N_Identifier then
+ Expr := Expression (Declaration_Node (Entity (N)));
- Loc : constant Source_Ptr := Sloc (N);
+ if Ekind (Entity (N)) = E_Named_Integer then
+ UI_Image (Expr_Value (Expr), Decimal);
+ Start_String;
+ Store_String_Chars
+ (UI_Image_Buffer (1 .. UI_Image_Length));
+ Param1 := Make_String_Literal (Loc, End_String);
+ Params := New_List (Param1);
- Name : constant Node_Id :=
- Make_Identifier (Loc, Chars (Callee));
+ else
+ UI_Image (Norm_Num (Expr_Value_R (Expr)), Decimal);
+ Start_String;
+ Store_String_Chars
+ (UI_Image_Buffer (1 .. UI_Image_Length));
+ Param1 := Make_String_Literal (Loc, End_String);
+
+ -- Note: Set_Etype is called below on Param1
- Param : constant Node_Id :=
- Make_String_Literal (Loc, Literal_Text (N));
+ UI_Image (Norm_Den (Expr_Value_R (Expr)), Decimal);
+ Start_String;
+ Store_String_Chars
+ (UI_Image_Buffer (1 .. UI_Image_Length));
+ Param2 := Make_String_Literal (Loc, End_String);
+ Set_Etype (Param2, Standard_String);
- Params : constant List_Id := New_List (Param);
+ Params := New_List (Param1, Param2);
+
+ if Present (Related_Expression (Callee)) then
+ Callee := Related_Expression (Callee);
+ else
+ Error_Msg_NE
+ ("cannot resolve & for a named real", N, Callee);
+ return;
+ end if;
+ end if;
+
+ elsif Nkind (N) = N_String_Literal then
+ Param1 := Make_String_Literal (Loc, Strval (N));
+ Params := New_List (Param1);
+ else
+ Param1 :=
+ Make_String_Literal
+ (Loc, String_From_Numeric_Literal (N));
+ Params := New_List (Param1);
+ end if;
- Call : Node_Id :=
+ Call :=
Make_Function_Call
(Sloc => Loc,
Name => Name,
Parameter_Associations => Params);
- begin
+
Set_Entity (Name, Callee);
Set_Is_Overloaded (Name, False);
+
if Lit_Aspect = Aspect_String_Literal then
- Set_Etype (Param, Standard_Wide_Wide_String);
+ Set_Etype (Param1, Standard_Wide_Wide_String);
else
- Set_Etype (Param, Standard_String);
+ Set_Etype (Param1, Standard_String);
end if;
+
Set_Etype (Call, Etype (Callee));
-- Conversion needed in case of an inherited aspect
@@ -2947,6 +2992,7 @@ package body Sem_Res is
Rewrite (N, Call);
end;
+
Analyze_And_Resolve (N, Typ);
return;
end if;
@@ -4634,7 +4680,7 @@ package body Sem_Res is
elsif Ada_Version >= Ada_2005 then
Apply_Compile_Time_Constraint_Error
(N => A,
- Msg => "(Ada 2005) null not allowed in "
+ Msg => "(Ada 2005) NULL not allowed in "
& "null-excluding formal??",
Reason => CE_Null_Not_Allowed);
end if;
@@ -5402,9 +5448,12 @@ package body Sem_Res is
-- Do not apply Ada 2005 accessibility checks on a class-wide
-- allocator if the type given in the allocator is a formal
- -- type. A run-time check will be performed in the instance.
+ -- type or within a formal package. A run-time check will be
+ -- performed in the instance.
- elsif not Is_Generic_Type (Exp_Typ) then
+ elsif not Is_Generic_Type (Exp_Typ)
+ and then not In_Generic_Formal_Package (Exp_Typ)
+ then
Error_Msg_N
("type in allocator has deeper level than designated "
& "class-wide type", E);
@@ -6244,7 +6293,7 @@ package body Sem_Res is
-- Normal subprogram call with name established in Resolve
- elsif not (Is_Type (Entity (Subp))) then
+ elsif not Is_Type (Entity (Subp)) then
Nam := Entity (Subp);
Set_Entity_With_Checks (Subp, Nam);
@@ -7073,10 +7122,9 @@ package body Sem_Res is
-- on expression functions.
elsif In_Assertion_Expr /= 0 then
- if Present (Body_Id) then
- Cannot_Inline
- ("cannot inline & (in assertion expression)?", N, Nam_UA);
- end if;
+ Cannot_Inline
+ ("cannot inline & (in assertion expression)?", N, Nam_UA,
+ Suppress_Info => No (Body_Id));
-- Calls cannot be inlined inside default expressions
@@ -7408,21 +7456,7 @@ package body Sem_Res is
Analyze_Dimension (N);
- -- Evaluate the relation (note we do this after the above check since
- -- this Eval call may change N to True/False. Skip this evaluation
- -- inside assertions, in order to keep assertions as written by users
- -- for tools that rely on these, e.g. GNATprove for loop invariants.
- -- Except evaluation is still performed even inside assertions for
- -- comparisons between values of universal type, which are useless
- -- for static analysis tools, and not supported even by GNATprove.
-
- if In_Assertion_Expr = 0
- or else (Is_Universal_Numeric_Type (Etype (L))
- and then
- Is_Universal_Numeric_Type (Etype (R)))
- then
- Eval_Relational_Op (N);
- end if;
+ Eval_Relational_Op (N);
end Resolve_Comparison_Op;
--------------------------------
@@ -7433,7 +7467,8 @@ package body Sem_Res is
(N : Node_Id;
Typ : Entity_Id)
is
- Decl : Node_Id;
+ Decl : Node_Id;
+ Need_Transient_Scope : Boolean := False;
begin
-- Install the scope created for local declarations, if
-- any. The syntax allows a Declare_Expression with no
@@ -7442,7 +7477,6 @@ package body Sem_Res is
-- appears as the scope of all entities declared therein.
Decl := First (Actions (N));
-
while Present (Decl) loop
exit when Nkind (Decl)
in N_Object_Declaration | N_Object_Renaming_Declaration;
@@ -7450,11 +7484,35 @@ package body Sem_Res is
end loop;
if Present (Decl) then
- Push_Scope (Scope (Defining_Identifier (Decl)));
+
+ -- Need to establish a transient scope in case Expression (N)
+ -- requires actions to be wrapped.
declare
- E : Entity_Id := First_Entity (Current_Scope);
+ Node : Node_Id;
+ begin
+ Node := First (Actions (N));
+ while Present (Node) loop
+ if Nkind (Node) = N_Object_Declaration
+ and then Requires_Transient_Scope
+ (Etype (Defining_Identifier (Node)))
+ then
+ Need_Transient_Scope := True;
+ exit;
+ end if;
+
+ Next (Node);
+ end loop;
+ end;
+
+ if Need_Transient_Scope then
+ Establish_Transient_Scope (Decl, True);
+ else
+ Push_Scope (Scope (Defining_Identifier (Decl)));
+ end if;
+ declare
+ E : Entity_Id := First_Entity (Current_Scope);
begin
while Present (E) loop
Set_Current_Entity (E);
@@ -8369,6 +8427,11 @@ package body Sem_Res is
-- This is semantically dubious, and of no interest to any real code,
-- but c48008a makes it all worthwhile.
+ function Suspicious_Prio_For_Equality return Boolean;
+ -- Returns True iff the parent node is a and/or/xor operation that
+ -- could be the cause of confused priorities. Note that if the not is
+ -- in parens, then False is returned.
+
-------------------------
-- Check_If_Expression --
-------------------------
@@ -8498,6 +8561,47 @@ package body Sem_Res is
return Empty;
end Find_Unique_Access_Type;
+ ----------------------------------
+ -- Suspicious_Prio_For_Equality --
+ ----------------------------------
+
+ function Suspicious_Prio_For_Equality return Boolean is
+ Par : constant Node_Id := Parent (N);
+
+ begin
+ -- Check if parent node is one of and/or/xor, not parenthesized
+ -- explicitly, and its own parent is not of this kind. Otherwise,
+ -- it's a case of chained Boolean conditions which is likely well
+ -- parenthesized.
+
+ if Nkind (Par) in N_Op_And | N_Op_Or | N_Op_Xor
+ and then Paren_Count (N) = 0
+ and then Nkind (Parent (Par)) not in N_Op_And | N_Op_Or | N_Op_Xor
+ then
+ declare
+ Compar : Node_Id :=
+ (if Left_Opnd (Par) = N then
+ Right_Opnd (Par)
+ else
+ Left_Opnd (Par));
+ begin
+ -- Compar may have been rewritten, for example from (a /= b)
+ -- into not (a = b). Use the Original_Node instead.
+
+ Compar := Original_Node (Compar);
+
+ -- If the other argument of the and/or/xor is also a
+ -- comparison, or another and/or/xor then most likely
+ -- the priorities are correctly set.
+
+ return Nkind (Compar) not in N_Op_Boolean;
+ end;
+
+ else
+ return False;
+ end if;
+ end Suspicious_Prio_For_Equality;
+
-- Start of processing for Resolve_Equality_Op
begin
@@ -8578,6 +8682,24 @@ package body Sem_Res is
Explain_Redundancy (Original_Node (R));
end if;
+ -- Warn on a (in)equality between boolean values which is not
+ -- parenthesized when the parent expression is one of and/or/xor, as
+ -- this is interpreted as (a = b) op c where most likely a = (b op c)
+ -- was intended. Do not generate a warning in generic instances, as
+ -- the problematic expression may be implicitly parenthesized in
+ -- the generic itself if one of the operators is a generic formal.
+ -- Also do not generate a warning for generated equality, for
+ -- example from rewritting a membership test.
+
+ if Warn_On_Questionable_Missing_Parens
+ and then not In_Instance
+ and then Comes_From_Source (N)
+ and then Is_Boolean_Type (T)
+ and then Suspicious_Prio_For_Equality
+ then
+ Error_Msg_N ("?q?equality should be parenthesized here!", N);
+ end if;
+
-- If the equality is overloaded and the operands have resolved
-- properly, set the proper equality operator on the node. The
-- current setting is the first one found during analysis, which
@@ -8800,8 +8922,7 @@ package body Sem_Res is
-- actual subtype. We also exclude generated code (which builds actual
-- subtypes directly if they are needed).
- if Is_Array_Type (Etype (N))
- and then Is_Packed (Etype (N))
+ if Is_Packed_Array (Etype (N))
and then not Is_Constrained (Etype (N))
and then Nkind (Parent (N)) /= N_Attribute_Reference
and then Comes_From_Source (N)
@@ -9507,7 +9628,7 @@ package body Sem_Res is
-- universal types applies.
procedure Resolve_Membership_Op (N : Node_Id; Typ : Entity_Id) is
- pragma Warnings (Off, Typ);
+ pragma Assert (Is_Boolean_Type (Typ));
L : constant Node_Id := Left_Opnd (N);
R : constant Node_Id := Right_Opnd (N);
@@ -9724,13 +9845,13 @@ package body Sem_Res is
if Nkind (Parent (N)) in N_Subprogram_Call then
Error_Msg_N
- ("null is not allowed as argument for an access parameter", N);
+ ("NULL is not allowed as argument for an access parameter", N);
-- Standard message for all other cases (are there any?)
else
Error_Msg_N
- ("null cannot be of an anonymous access type", N);
+ ("NULL cannot be of an anonymous access type", N);
end if;
end if;
@@ -9777,7 +9898,7 @@ package body Sem_Res is
else
Insert_Action
(Compile_Time_Constraint_Error (N,
- "(Ada 2005) null not allowed in null-excluding objects??"),
+ "(Ada 2005) NULL not allowed in null-excluding objects??"),
Make_Raise_Constraint_Error (Loc,
Reason => CE_Access_Check_Failed));
end if;
@@ -10130,8 +10251,6 @@ package body Sem_Res is
--------------------
procedure Resolve_Op_Not (N : Node_Id; Typ : Entity_Id) is
- B_Typ : Entity_Id;
-
function Parent_Is_Boolean return Boolean;
-- This function determines if the parent node is a boolean operator or
-- operation (comparison op, membership test, or short circuit form) and
@@ -10144,32 +10263,16 @@ package body Sem_Res is
function Parent_Is_Boolean return Boolean is
begin
- if Paren_Count (N) /= 0 then
- return False;
+ return Paren_Count (N) = 0
+ and then Nkind (Parent (N)) in N_Membership_Test
+ | N_Op_Boolean
+ | N_Short_Circuit
+ and then Left_Opnd (Parent (N)) = N;
+ end Parent_Is_Boolean;
- else
- case Nkind (Parent (N)) is
- when N_And_Then
- | N_In
- | N_Not_In
- | N_Op_And
- | N_Op_Eq
- | N_Op_Ge
- | N_Op_Gt
- | N_Op_Le
- | N_Op_Lt
- | N_Op_Ne
- | N_Op_Or
- | N_Op_Xor
- | N_Or_Else
- =>
- return Left_Opnd (Parent (N)) = N;
+ -- Local variables
- when others =>
- return False;
- end case;
- end if;
- end Parent_Is_Boolean;
+ B_Typ : Entity_Id;
-- Start of processing for Resolve_Op_Not
@@ -10196,7 +10299,7 @@ package body Sem_Res is
elsif Typ = Universal_Integer or else Typ = Any_Modular then
if Parent_Is_Boolean then
Error_Msg_N
- ("operand of not must be enclosed in parentheses",
+ ("operand of NOT must be enclosed in parentheses",
Right_Opnd (N));
else
Error_Msg_N
@@ -10809,30 +10912,34 @@ package body Sem_Res is
Set_Etype (N, Base_Type (Typ));
end if;
- -- Note: No Eval processing is required, because the prefix is of a
- -- record type, or protected type, and neither can possibly be static.
+ -- Eval_Selected_Component may e.g. fold statically known discriminants.
- -- If the record type is atomic and the component is not, then this is
- -- worth a warning before Ada 2020, since we have a situation where the
- -- access to the component may cause extra read/writes of the atomic
- -- object, or partial word accesses, both of which may be unexpected.
+ Eval_Selected_Component (N);
- if Nkind (N) = N_Selected_Component
- and then Is_Atomic_Ref_With_Address (N)
- and then not Is_Atomic (Entity (S))
- and then not Is_Atomic (Etype (Entity (S)))
- and then Ada_Version < Ada_2020
- then
- Error_Msg_N
- ("??access to non-atomic component of atomic record",
- Prefix (N));
- Error_Msg_N
- ("\??may cause unexpected accesses to atomic object",
- Prefix (N));
- end if;
+ if Nkind (N) = N_Selected_Component then
- Resolve_Implicit_Dereference (Prefix (N));
- Analyze_Dimension (N);
+ -- If the record type is atomic and the component is not, then this
+ -- is worth a warning before Ada 2020, since we have a situation
+ -- where the access to the component may cause extra read/writes of
+ -- the atomic object, or partial word accesses, both of which may be
+ -- unexpected.
+
+ if Is_Atomic_Ref_With_Address (N)
+ and then not Is_Atomic (Entity (S))
+ and then not Is_Atomic (Etype (Entity (S)))
+ and then Ada_Version < Ada_2020
+ then
+ Error_Msg_N
+ ("??access to non-atomic component of atomic record",
+ Prefix (N));
+ Error_Msg_N
+ ("\??may cause unexpected accesses to atomic object",
+ Prefix (N));
+ end if;
+
+ Resolve_Implicit_Dereference (Prefix (N));
+ Analyze_Dimension (N);
+ end if;
end Resolve_Selected_Component;
-------------------
@@ -11635,16 +11742,14 @@ package body Sem_Res is
Simplify_Type_Conversion (N);
-- If after evaluation we still have a type conversion, then we may need
- -- to apply checks required for a subtype conversion.
-
- -- Skip these type conversion checks if universal fixed operands
- -- are involved, since range checks are handled separately for
- -- these cases (in the appropriate Expand routines in unit Exp_Fixd).
+ -- to apply checks required for a subtype conversion. But skip them if
+ -- universal fixed operands are involved, since range checks are handled
+ -- separately for these cases, after the expansion done by Exp_Fixd.
if Nkind (N) = N_Type_Conversion
and then not Is_Generic_Type (Root_Type (Target_Typ))
and then Target_Typ /= Universal_Fixed
- and then Operand_Typ /= Universal_Fixed
+ and then Etype (Operand) /= Universal_Fixed
then
Apply_Type_Conversion_Checks (N);
end if;
@@ -11883,11 +11988,12 @@ package body Sem_Res is
(N, Target_Typ, Static_Failure_Is_Error => True);
end if;
- -- If at this stage we have a fixed point to integer conversion, make
- -- sure that the Do_Range_Check flag is set which is not always done
- -- by exp_fixd.adb.
+ -- If at this stage we have a fixed to integer conversion, make sure the
+ -- Do_Range_Check flag is set, because such conversions in general need
+ -- a range check. We only need this if expansion is off, see above why.
if Nkind (N) = N_Type_Conversion
+ and then not Expander_Active
and then Is_Integer_Type (Target_Typ)
and then Is_Fixed_Point_Type (Operand_Typ)
and then not Range_Checks_Suppressed (Target_Typ)
@@ -12390,9 +12496,10 @@ package body Sem_Res is
-- the point where actions for the slice are analyzed). Note that this
-- is different from freezing the itype immediately, which might be
-- premature (e.g. if the slice is within a transient scope). This needs
- -- to be done only if expansion is enabled.
+ -- to be done only if expansion is enabled, or in GNATprove mode to
+ -- capture the associated run-time exceptions if any.
- elsif Expander_Active then
+ elsif Expander_Active or GNATprove_Mode then
Ensure_Defined (Typ => Slice_Subtype, N => N);
end if;
end Set_Slice_Subtype;
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 3b1f48e..8dbfa18 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -326,8 +326,19 @@ package body Sem_Type is
return False;
elsif Nkind (N) in N_Binary_Op then
- return Present (Universal_Interpretation (Left_Opnd (N)))
- and then Present (Universal_Interpretation (Right_Opnd (N)));
+ if Present (Universal_Interpretation (Left_Opnd (N)))
+ and then Present (Universal_Interpretation (Right_Opnd (N)))
+ then
+ return True;
+ elsif Nkind (N) in N_Op_Eq | N_Op_Ne
+ and then
+ (Is_Anonymous_Access_Type (Etype (Left_Opnd (N)))
+ or else Is_Anonymous_Access_Type (Etype (Right_Opnd (N))))
+ then
+ return True;
+ else
+ return False;
+ end if;
elsif Nkind (N) in N_Unary_Op then
return Present (Universal_Interpretation (Right_Opnd (N)));
@@ -1156,16 +1167,14 @@ package body Sem_Type is
-- useless unchecked conversions, and since this can only arise in
-- (known correct) expanded code, no harm is done.
- elsif Is_Array_Type (T2)
- and then Is_Packed (T2)
+ elsif Is_Packed_Array (T2)
and then T1 = Packed_Array_Impl_Type (T2)
then
return True;
-- Similarly an array type covers its corresponding packed array type
- elsif Is_Array_Type (T1)
- and then Is_Packed (T1)
+ elsif Is_Packed_Array (T1)
and then T2 = Packed_Array_Impl_Type (T1)
then
return True;
@@ -1338,6 +1347,13 @@ package body Sem_Type is
-- for special handling of expressions with universal operands, see
-- comments to Has_Abstract_Interpretation below.
+ function Is_User_Defined_Anonymous_Access_Equality
+ (User_Subp, Predef_Subp : Entity_Id) return Boolean;
+ -- Check for Ada 2005, AI-020: If the context involves an anonymous
+ -- access operand, recognize a user-defined equality (User_Subp) with
+ -- the proper signature, declared in the same declarative list as the
+ -- type and not hiding a predefined equality Predef_Subp.
+
---------------------------
-- Inherited_From_Actual --
---------------------------
@@ -1743,6 +1759,37 @@ package body Sem_Type is
end if;
end Standard_Operator;
+ -----------------------------------------------
+ -- Is_User_Defined_Anonymous_Access_Equality --
+ -----------------------------------------------
+
+ function Is_User_Defined_Anonymous_Access_Equality
+ (User_Subp, Predef_Subp : Entity_Id) return Boolean is
+ begin
+ return Present (User_Subp)
+
+ -- Check for Ada 2005 and use of anonymous access
+
+ and then Ada_Version >= Ada_2005
+ and then Etype (User_Subp) = Standard_Boolean
+ and then Is_Anonymous_Access_Type (Operand_Type)
+
+ -- This check is only relevant if User_Subp is visible and not in
+ -- an instance
+
+ and then (In_Open_Scopes (Scope (User_Subp))
+ or else Is_Potentially_Use_Visible (User_Subp))
+ and then not In_Instance
+ and then not Hides_Op (User_Subp, Predef_Subp)
+
+ -- Is User_Subp declared in the same declarative list as the type?
+
+ and then
+ In_Same_Declaration_List
+ (Designated_Type (Operand_Type),
+ Unit_Declaration_Node (User_Subp));
+ end Is_User_Defined_Anonymous_Access_Equality;
+
-- Start of processing for Disambiguate
begin
@@ -1856,17 +1903,41 @@ package body Sem_Type is
Arg2 := Next_Actual (Arg1);
end if;
- if Present (Arg2)
- and then Present (Universal_Interpretation (Arg1))
- and then Universal_Interpretation (Arg2) =
- Universal_Interpretation (Arg1)
- then
- Get_First_Interp (N, I, It);
- while Scope (It.Nam) /= Standard_Standard loop
- Get_Next_Interp (I, It);
- end loop;
+ if Present (Arg2) then
+ if Ekind (Nam1) = E_Operator then
+ Predef_Subp := Nam1;
+ User_Subp := Nam2;
+ elsif Ekind (Nam2) = E_Operator then
+ Predef_Subp := Nam2;
+ User_Subp := Nam1;
+ else
+ Predef_Subp := Empty;
+ User_Subp := Empty;
+ end if;
- return It;
+ -- Take into account universal interpretation as well as
+ -- universal_access equality, as long as AI05-0020 does not
+ -- trigger.
+
+ if (Present (Universal_Interpretation (Arg1))
+ and then Universal_Interpretation (Arg2) =
+ Universal_Interpretation (Arg1))
+ or else
+ (Nkind (N) in N_Op_Eq | N_Op_Ne
+ and then (Is_Anonymous_Access_Type (Etype (Arg1))
+ or else
+ Is_Anonymous_Access_Type (Etype (Arg2)))
+ and then not
+ Is_User_Defined_Anonymous_Access_Equality
+ (User_Subp, Predef_Subp))
+ then
+ Get_First_Interp (N, I, It);
+ while Scope (It.Nam) /= Standard_Standard loop
+ Get_Next_Interp (I, It);
+ end loop;
+
+ return It;
+ end if;
end if;
end;
end if;
@@ -2117,20 +2188,11 @@ package body Sem_Type is
return It2;
end if;
- -- Ada 2005, AI-420: preference rule for "=" on Universal_Access
- -- states that the operator defined in Standard is not available
- -- if there is a user-defined equality with the proper signature,
- -- declared in the same declarative list as the type. The node
- -- may be an operator or a function call.
+ -- Check for AI05-020
elsif Chars (Nam1) in Name_Op_Eq | Name_Op_Ne
- and then Ada_Version >= Ada_2005
- and then Etype (User_Subp) = Standard_Boolean
- and then Is_Anonymous_Access_Type (Operand_Type)
- and then
- In_Same_Declaration_List
- (Designated_Type (Operand_Type),
- Unit_Declaration_Node (User_Subp))
+ and then Is_User_Defined_Anonymous_Access_Equality
+ (User_Subp, Predef_Subp)
then
if It2.Nam = Predef_Subp then
return It1;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 0eb4905..1cf5c69 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -23,8 +23,6 @@
-- --
------------------------------------------------------------------------------
-with Treepr; -- ???For debugging code below
-
with Casing; use Casing;
with Checks; use Checks;
with Debug; use Debug;
@@ -170,24 +168,6 @@ package body Sem_Util is
-- routine does not take simple flow diagnostics into account, it relies on
-- static facts such as the presence of null exclusions.
- function Old_Requires_Transient_Scope (Id : Entity_Id) return Boolean;
- function New_Requires_Transient_Scope (Id : Entity_Id) return Boolean;
- -- ???We retain the old and new algorithms for Requires_Transient_Scope for
- -- the time being. New_Requires_Transient_Scope is used by default; the
- -- debug switch -gnatdQ can be used to do Old_Requires_Transient_Scope
- -- instead. The intent is to use this temporarily to measure before/after
- -- efficiency. Note: when this temporary code is removed, the documentation
- -- of dQ in debug.adb should be removed.
-
- procedure Results_Differ
- (Id : Entity_Id;
- Old_Val : Boolean;
- New_Val : Boolean);
- -- ???Debugging code. Called when the Old_Val and New_Val differ. This
- -- routine will be removed eventially when New_Requires_Transient_Scope
- -- becomes Requires_Transient_Scope and Old_Requires_Transient_Scope is
- -- eliminated.
-
function Subprogram_Name (N : Node_Id) return String;
-- Return the fully qualified name of the enclosing subprogram for the
-- given node N, with file:line:col information appended, e.g.
@@ -2492,7 +2472,7 @@ package body Sem_Util is
function Build_Discriminal_Array_Constraint return List_Id;
-- If one or more of the bounds of the component depends on
- -- discriminants, build actual constraint using the discriminants
+ -- discriminants, build actual constraint using the discriminants
-- of the prefix.
function Build_Discriminal_Record_Constraint return List_Id;
@@ -6454,11 +6434,7 @@ package body Sem_Util is
and then Etype (First_Formal (Id)) =
Etype (Next_Formal (First_Formal (Id)))
then
- if No (Eq_Prims_List) then
- Eq_Prims_List := New_Elmt_List;
- end if;
-
- Append_Elmt (Id, Eq_Prims_List);
+ Append_New_Elmt (Id, Eq_Prims_List);
end if;
end if;
end if;
@@ -7859,6 +7835,8 @@ package body Sem_Util is
or else
Nkind (Decl) in N_Later_Decl_Item
or else
+ Nkind (Decl) in N_Renaming_Declaration
+ or else
Nkind (Decl) = N_Number_Declaration)
loop
Decl := Parent (Decl);
@@ -7933,6 +7911,34 @@ package body Sem_Util is
return Empty;
end Enclosing_Generic_Unit;
+ -------------------
+ -- Enclosing_HSS --
+ -------------------
+
+ function Enclosing_HSS (Stmt : Node_Id) return Node_Id is
+ Par : Node_Id;
+ begin
+ pragma Assert (Is_Statement (Stmt));
+
+ Par := Parent (Stmt);
+ while Present (Par) loop
+
+ if Nkind (Par) = N_Handled_Sequence_Of_Statements then
+ return Par;
+
+ -- Prevent the search from going too far
+
+ elsif Is_Body_Or_Package_Declaration (Par) then
+ return Empty;
+
+ end if;
+
+ Par := Parent (Par);
+ end loop;
+
+ return Par;
+ end Enclosing_HSS;
+
-------------------------------
-- Enclosing_Lib_Unit_Entity --
-------------------------------
@@ -8290,6 +8296,13 @@ package body Sem_Util is
else
Set_Name_Entity_Id (Chars (E), Homonym (E));
end if;
+
+ -- The inherited operation cannot be retrieved
+ -- by name, even though it may remain accesssible
+ -- in some cases involving subprogram bodies without
+ -- specs appearing in with_clauses..
+
+ Set_Is_Immediately_Visible (E, False);
end if;
end;
@@ -9863,11 +9876,13 @@ package body Sem_Util is
-----------------------
procedure Gather_Components
- (Typ : Entity_Id;
- Comp_List : Node_Id;
- Governed_By : List_Id;
- Into : Elist_Id;
- Report_Errors : out Boolean)
+ (Typ : Entity_Id;
+ Comp_List : Node_Id;
+ Governed_By : List_Id;
+ Into : Elist_Id;
+ Report_Errors : out Boolean;
+ Allow_Compile_Time : Boolean := False;
+ Include_Interface_Tag : Boolean := False)
is
Assoc : Node_Id;
Variant : Node_Id;
@@ -9899,15 +9914,20 @@ package body Sem_Util is
while Present (Comp_Item) loop
- -- Skip the tag of a tagged record, the interface tags, as well
- -- as all items that are not user components (anonymous types,
- -- rep clauses, Parent field, controller field).
+ -- Skip the tag of a tagged record, as well as all items that are not
+ -- user components (anonymous types, rep clauses, Parent field,
+ -- controller field).
if Nkind (Comp_Item) = N_Component_Declaration then
declare
Comp : constant Entity_Id := Defining_Identifier (Comp_Item);
begin
- if not Is_Tag (Comp) and then Chars (Comp) /= Name_uParent then
+ if not (Is_Tag (Comp)
+ and then not
+ (Include_Interface_Tag
+ and then Etype (Comp) = RTE (RE_Interface_Tag)))
+ and then Chars (Comp) /= Name_uParent
+ then
Append_Elmt (Comp, Into);
end if;
end;
@@ -10016,7 +10036,11 @@ package body Sem_Util is
end loop Find_Constraint;
Discrim_Value := Expression (Assoc);
- if Is_OK_Static_Expression (Discrim_Value) then
+
+ if Is_OK_Static_Expression (Discrim_Value)
+ or else (Allow_Compile_Time
+ and then Compile_Time_Known_Value (Discrim_Value))
+ then
Discrim_Value_Status := Static_Expr;
else
if Ada_Version >= Ada_2020 then
@@ -10195,7 +10219,8 @@ package body Sem_Util is
end if;
Gather_Components
- (Typ, Component_List (Variant), Governed_By, Into, Report_Errors);
+ (Typ, Component_List (Variant), Governed_By, Into,
+ Report_Errors, Allow_Compile_Time);
end if;
end Gather_Components;
@@ -10430,7 +10455,7 @@ package body Sem_Util is
then
if Cursor /= Any_Type then
Error_Msg_N
- ("Operation First for iterable type must be unique", Aspect);
+ ("operation First for iterable type must be unique", Aspect);
return Any_Type;
else
Cursor := Etype (Func);
@@ -10548,7 +10573,7 @@ package body Sem_Util is
-- Position in the enumeration type starts at 0
- if UI_To_Int (Pos) < 0 then
+ if Pos < 0 then
raise Constraint_Error;
end if;
@@ -10584,6 +10609,12 @@ package body Sem_Util is
function Get_Fullest_View
(E : Entity_Id; Include_PAT : Boolean := True) return Entity_Id is
begin
+ -- Prevent cascaded errors
+
+ if No (E) then
+ return E;
+ end if;
+
-- Strictly speaking, the recursion below isn't necessary, but
-- it's both simplest and safest.
@@ -11394,7 +11425,7 @@ package body Sem_Util is
Comp : Entity_Id;
begin
- -- Loop to Check components
+ -- Loop to check components
Comp := First_Component_Or_Discriminant (Typ);
while Present (Comp) loop
@@ -12727,12 +12758,11 @@ package body Sem_Util is
----------------------------------
function Has_Non_Trivial_Precondition (Subp : Entity_Id) return Boolean is
- Pre : constant Node_Id := Find_Aspect (Subp, Aspect_Pre);
-
+ Pre : constant Node_Id := Find_Aspect (Subp, Aspect_Pre,
+ Class_Present => True);
begin
return
Present (Pre)
- and then Class_Present (Pre)
and then not Is_Entity_Name (Expression (Pre));
end Has_Non_Trivial_Precondition;
@@ -13823,6 +13853,52 @@ package body Sem_Util is
and then Assertion_Expression_Pragma (Get_Pragma_Id (Prag));
end In_Assertion_Expression_Pragma;
+ -------------------
+ -- In_Check_Node --
+ -------------------
+
+ function In_Check_Node (N : Node_Id) return Boolean is
+ Par : Node_Id := Parent (N);
+ begin
+ while Present (Par) loop
+ if Nkind (Par) in N_Raise_xxx_Error then
+ return True;
+
+ -- Prevent the search from going too far
+
+ elsif Is_Body_Or_Package_Declaration (Par) then
+ return False;
+
+ else
+ Par := Parent (Par);
+ end if;
+ end loop;
+
+ return False;
+ end In_Check_Node;
+
+ -------------------------------
+ -- In_Generic_Formal_Package --
+ -------------------------------
+
+ function In_Generic_Formal_Package (E : Entity_Id) return Boolean is
+ Par : Node_Id;
+
+ begin
+ Par := Parent (E);
+ while Present (Par) loop
+ if Nkind (Par) = N_Formal_Package_Declaration
+ or else Nkind (Original_Node (Par)) = N_Formal_Package_Declaration
+ then
+ return True;
+ end if;
+
+ Par := Parent (Par);
+ end loop;
+
+ return False;
+ end In_Generic_Formal_Package;
+
----------------------
-- In_Generic_Scope --
----------------------
@@ -14565,7 +14641,9 @@ package body Sem_Util is
procedure Inherit_Predicate_Flags (Subt, Par : Entity_Id) is
begin
- if Present (Predicate_Function (Subt)) then
+ if Ada_Version < Ada_2012
+ or else Present (Predicate_Function (Subt))
+ then
return;
end if;
@@ -15148,6 +15226,19 @@ package body Sem_Util is
return Present (Formal) and then Ekind (Formal) = E_In_Out_Parameter;
end Is_Actual_In_Out_Parameter;
+ ---------------------------------------
+ -- Is_Actual_Out_Or_In_Out_Parameter --
+ ---------------------------------------
+
+ function Is_Actual_Out_Or_In_Out_Parameter (N : Node_Id) return Boolean is
+ Formal : Entity_Id;
+ Call : Node_Id;
+ begin
+ Find_Actual (N, Formal, Call);
+ return Present (Formal)
+ and then Ekind (Formal) in E_Out_Parameter | E_In_Out_Parameter;
+ end Is_Actual_Out_Or_In_Out_Parameter;
+
-------------------------
-- Is_Actual_Parameter --
-------------------------
@@ -16250,7 +16341,7 @@ package body Sem_Util is
P_Aliased : Boolean := False;
Comp : Entity_Id;
- Deref : Node_Id := Object;
+ Deref : Node_Id := Original_Node (Object);
-- Dereference node, in something like X.all.Y(2)
-- Start of processing for Is_Dependent_Component_Of_Mutable_Object
@@ -16261,11 +16352,9 @@ package body Sem_Util is
while Nkind (Deref) in
N_Indexed_Component | N_Selected_Component | N_Slice
loop
- Deref := Prefix (Deref);
+ Deref := Original_Node (Prefix (Deref));
end loop;
- Deref := Original_Node (Deref);
-
-- If the prefix is a qualified expression of a variable, then function
-- Is_Variable will return False for that because a qualified expression
-- denotes a constant view, so we need to get the name being qualified
@@ -16441,14 +16530,16 @@ package body Sem_Util is
elsif Nkind (Object) = N_Indexed_Component
or else Nkind (Object) = N_Slice
then
- return Is_Dependent_Component_Of_Mutable_Object (Prefix (Object));
+ return Is_Dependent_Component_Of_Mutable_Object
+ (Original_Node (Prefix (Object)));
-- A type conversion that Is_Variable is a view conversion:
-- go back to the denoted object.
elsif Nkind (Object) = N_Type_Conversion then
return
- Is_Dependent_Component_Of_Mutable_Object (Expression (Object));
+ Is_Dependent_Component_Of_Mutable_Object
+ (Original_Node (Expression (Object)));
end if;
end if;
@@ -16582,7 +16673,9 @@ package body Sem_Util is
-- Is_Effectively_Volatile --
-----------------------------
- function Is_Effectively_Volatile (Id : Entity_Id) return Boolean is
+ function Is_Effectively_Volatile
+ (Id : Entity_Id;
+ Ignore_Protected : Boolean := False) return Boolean is
begin
if Is_Type (Id) then
@@ -16610,15 +16703,16 @@ package body Sem_Util is
-- Test for presence of ancestor, as the full view of a
-- private type may be missing in case of error.
- return
- Present (Anc)
- and then Is_Effectively_Volatile (Component_Type (Anc));
+ return Present (Anc)
+ and then Is_Effectively_Volatile
+ (Component_Type (Anc), Ignore_Protected);
end;
end if;
- -- A protected type is always volatile
+ -- A protected type is always volatile unless Ignore_Protected is
+ -- True.
- elsif Is_Protected_Type (Id) then
+ elsif Is_Protected_Type (Id) and then not Ignore_Protected then
return True;
-- A descendant of Ada.Synchronous_Task_Control.Suspension_Object is
@@ -16644,7 +16738,7 @@ package body Sem_Util is
and then not
(Ekind (Id) = E_Variable and then No_Caching_Enabled (Id)))
or else Has_Volatile_Components (Id)
- or else Is_Effectively_Volatile (Etype (Id));
+ or else Is_Effectively_Volatile (Etype (Id), Ignore_Protected);
end if;
end Is_Effectively_Volatile;
@@ -16653,15 +16747,19 @@ package body Sem_Util is
-----------------------------------------
function Is_Effectively_Volatile_For_Reading
- (Id : Entity_Id) return Boolean
+ (Id : Entity_Id;
+ Ignore_Protected : Boolean := False) return Boolean
is
begin
- -- A concurrent type is effectively volatile for reading
+ -- A concurrent type is effectively volatile for reading, except for a
+ -- protected type when Ignore_Protected is True.
- if Is_Concurrent_Type (Id) then
+ if Is_Task_Type (Id)
+ or else (Is_Protected_Type (Id) and then not Ignore_Protected)
+ then
return True;
- elsif Is_Effectively_Volatile (Id) then
+ elsif Is_Effectively_Volatile (Id, Ignore_Protected) then
-- Other volatile types and objects are effectively volatile for
-- reading when they have property Async_Writers or Effective_Reads
@@ -16689,10 +16787,9 @@ package body Sem_Util is
-- Test for presence of ancestor, as the full view of a
-- private type may be missing in case of error.
- return
- Present (Anc)
- and then Is_Effectively_Volatile_For_Reading
- (Component_Type (Anc));
+ return Present (Anc)
+ and then Is_Effectively_Volatile_For_Reading
+ (Component_Type (Anc), Ignore_Protected);
end;
end if;
end if;
@@ -16706,6 +16803,9 @@ package body Sem_Util is
------------------------------------
function Is_Effectively_Volatile_Object (N : Node_Id) return Boolean is
+ function Is_Effectively_Volatile (E : Entity_Id) return Boolean is
+ (Is_Effectively_Volatile (E, Ignore_Protected => False));
+
function Is_Effectively_Volatile_Object_Inst
is new Is_Effectively_Volatile_Object_Shared (Is_Effectively_Volatile);
begin
@@ -16719,6 +16819,10 @@ package body Sem_Util is
function Is_Effectively_Volatile_Object_For_Reading
(N : Node_Id) return Boolean
is
+ function Is_Effectively_Volatile_For_Reading
+ (E : Entity_Id) return Boolean
+ is (Is_Effectively_Volatile_For_Reading (E, Ignore_Protected => False));
+
function Is_Effectively_Volatile_Object_For_Reading_Inst
is new Is_Effectively_Volatile_Object_Shared
(Is_Effectively_Volatile_For_Reading);
@@ -18221,6 +18325,23 @@ package body Sem_Util is
-------------------------
function Is_Object_Reference (N : Node_Id) return Boolean is
+ function Safe_Prefix (N : Node_Id) return Node_Id;
+ -- Return Prefix (N) unless it has been rewritten as an
+ -- N_Raise_xxx_Error node, in which case return its original node.
+
+ -----------------
+ -- Safe_Prefix --
+ -----------------
+
+ function Safe_Prefix (N : Node_Id) return Node_Id is
+ begin
+ if Nkind (Prefix (N)) in N_Raise_xxx_Error then
+ return Original_Node (Prefix (N));
+ else
+ return Prefix (N);
+ end if;
+ end Safe_Prefix;
+
begin
-- AI12-0068: Note that a current instance reference in a type or
-- subtype's aspect_specification is considered a value, not an object
@@ -18236,8 +18357,8 @@ package body Sem_Util is
| N_Slice
=>
return
- Is_Object_Reference (Prefix (N))
- or else Is_Access_Type (Etype (Prefix (N)));
+ Is_Object_Reference (Safe_Prefix (N))
+ or else Is_Access_Type (Etype (Safe_Prefix (N)));
-- In Ada 95, a function call is a constant object; a procedure
-- call is not.
@@ -18265,8 +18386,8 @@ package body Sem_Util is
return
Is_Object_Reference (Selector_Name (N))
and then
- (Is_Object_Reference (Prefix (N))
- or else Is_Access_Type (Etype (Prefix (N))));
+ (Is_Object_Reference (Safe_Prefix (N))
+ or else Is_Access_Type (Etype (Safe_Prefix (N))));
-- An explicit dereference denotes an object, except that a
-- conditional expression gets turned into an explicit dereference
@@ -18311,7 +18432,10 @@ package body Sem_Util is
-- In Ada 95 an aggregate is an object reference
- when N_Aggregate =>
+ when N_Aggregate
+ | N_Delta_Aggregate
+ | N_Extension_Aggregate
+ =>
return Ada_Version >= Ada_95;
-- A string literal is not an object reference, but it might come
@@ -19876,6 +20000,22 @@ package body Sem_Util is
or else Nkind (N) = N_Procedure_Call_Statement;
end Is_Statement;
+ --------------------------------------
+ -- Is_Static_Discriminant_Component --
+ --------------------------------------
+
+ function Is_Static_Discriminant_Component (N : Node_Id) return Boolean is
+ begin
+ return Nkind (N) = N_Selected_Component
+ and then not Is_In_Discriminant_Check (N)
+ and then Present (Etype (Prefix (N)))
+ and then Ekind (Etype (Prefix (N))) = E_Record_Subtype
+ and then Has_Static_Discriminants (Etype (Prefix (N)))
+ and then Present (Entity (Selector_Name (N)))
+ and then Ekind (Entity (Selector_Name (N))) = E_Discriminant
+ and then not In_Check_Node (N);
+ end Is_Static_Discriminant_Component;
+
------------------------
-- Is_Static_Function --
------------------------
@@ -20434,8 +20574,7 @@ package body Sem_Util is
elsif Nkind (P) = N_Type_Conversion
and then not Comes_From_Source (P)
- and then Is_Array_Type (Etype (P))
- and then Is_Packed (Etype (P))
+ and then Is_Packed_Array (Etype (P))
then
return Is_Variable (Expression (P));
@@ -22439,11 +22578,7 @@ package body Sem_Util is
function Search_Decl (N : Node_Id) return Traverse_Result is
begin
if Nkind (N) in N_Declaration then
- if No (Decls) then
- Decls := New_Elmt_List;
- end if;
-
- Append_Elmt (N, Decls);
+ Append_New_Elmt (N, Decls);
end if;
return OK;
@@ -24265,228 +24400,6 @@ package body Sem_Util is
Node := Next_Global (Node);
end Next_Global;
- ----------------------------------
- -- New_Requires_Transient_Scope --
- ----------------------------------
-
- function New_Requires_Transient_Scope (Id : Entity_Id) return Boolean is
- function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean;
- -- This is called for untagged records and protected types, with
- -- nondefaulted discriminants. Returns True if the size of function
- -- results is known at the call site, False otherwise. Returns False
- -- if there is a variant part that depends on the discriminants of
- -- this type, or if there is an array constrained by the discriminants
- -- of this type. ???Currently, this is overly conservative (the array
- -- could be nested inside some other record that is constrained by
- -- nondiscriminants). That is, the recursive calls are too conservative.
-
- function Large_Max_Size_Mutable (Typ : Entity_Id) return Boolean;
- -- Returns True if Typ is a nonlimited record with defaulted
- -- discriminants whose max size makes it unsuitable for allocating on
- -- the primary stack.
-
- ------------------------------
- -- Caller_Known_Size_Record --
- ------------------------------
-
- function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean is
- pragma Assert (Typ = Underlying_Type (Typ));
-
- begin
- if Has_Variant_Part (Typ) and then not Is_Definite_Subtype (Typ) then
- return False;
- end if;
-
- declare
- Comp : Entity_Id;
-
- begin
- Comp := First_Component (Typ);
- while Present (Comp) loop
-
- -- Only look at E_Component entities. No need to look at
- -- E_Discriminant entities, and we must ignore internal
- -- subtypes generated for constrained components.
-
- declare
- Comp_Type : constant Entity_Id :=
- Underlying_Type (Etype (Comp));
-
- begin
- if Is_Record_Type (Comp_Type)
- or else
- Is_Protected_Type (Comp_Type)
- then
- if not Caller_Known_Size_Record (Comp_Type) then
- return False;
- end if;
-
- elsif Is_Array_Type (Comp_Type) then
- if Size_Depends_On_Discriminant (Comp_Type) then
- return False;
- end if;
- end if;
- end;
-
- Next_Component (Comp);
- end loop;
- end;
-
- return True;
- end Caller_Known_Size_Record;
-
- ------------------------------
- -- Large_Max_Size_Mutable --
- ------------------------------
-
- function Large_Max_Size_Mutable (Typ : Entity_Id) return Boolean is
- pragma Assert (Typ = Underlying_Type (Typ));
-
- function Is_Large_Discrete_Type (T : Entity_Id) return Boolean;
- -- Returns true if the discrete type T has a large range
-
- ----------------------------
- -- Is_Large_Discrete_Type --
- ----------------------------
-
- function Is_Large_Discrete_Type (T : Entity_Id) return Boolean is
- Threshold : constant Int := 16;
- -- Arbitrary threshold above which we consider it "large". We want
- -- a fairly large threshold, because these large types really
- -- shouldn't have default discriminants in the first place, in
- -- most cases.
-
- begin
- return UI_To_Int (RM_Size (T)) > Threshold;
- end Is_Large_Discrete_Type;
-
- -- Start of processing for Large_Max_Size_Mutable
-
- begin
- if Is_Record_Type (Typ)
- and then not Is_Limited_View (Typ)
- and then Has_Defaulted_Discriminants (Typ)
- then
- -- Loop through the components, looking for an array whose upper
- -- bound(s) depends on discriminants, where both the subtype of
- -- the discriminant and the index subtype are too large.
-
- declare
- Comp : Entity_Id;
-
- begin
- Comp := First_Component (Typ);
- while Present (Comp) loop
- declare
- Comp_Type : constant Entity_Id :=
- Underlying_Type (Etype (Comp));
-
- Hi : Node_Id;
- Indx : Node_Id;
- Ityp : Entity_Id;
-
- begin
- if Is_Array_Type (Comp_Type) then
- Indx := First_Index (Comp_Type);
-
- while Present (Indx) loop
- Ityp := Etype (Indx);
- Hi := Type_High_Bound (Ityp);
-
- if Nkind (Hi) = N_Identifier
- and then Ekind (Entity (Hi)) = E_Discriminant
- and then Is_Large_Discrete_Type (Ityp)
- and then Is_Large_Discrete_Type
- (Etype (Entity (Hi)))
- then
- return True;
- end if;
-
- Next_Index (Indx);
- end loop;
- end if;
- end;
-
- Next_Component (Comp);
- end loop;
- end;
- end if;
-
- return False;
- end Large_Max_Size_Mutable;
-
- -- Local declarations
-
- Typ : constant Entity_Id := Underlying_Type (Id);
-
- -- Start of processing for New_Requires_Transient_Scope
-
- begin
- -- This is a private type which is not completed yet. This can only
- -- happen in a default expression (of a formal parameter or of a
- -- record component). Do not expand transient scope in this case.
-
- if No (Typ) then
- return False;
-
- -- Do not expand transient scope for non-existent procedure return or
- -- string literal types.
-
- elsif Typ = Standard_Void_Type
- or else Ekind (Typ) = E_String_Literal_Subtype
- then
- return False;
-
- -- If Typ is a generic formal incomplete type, then we want to look at
- -- the actual type.
-
- elsif Ekind (Typ) = E_Record_Subtype
- and then Present (Cloned_Subtype (Typ))
- then
- return New_Requires_Transient_Scope (Cloned_Subtype (Typ));
-
- -- Functions returning specific tagged types may dispatch on result, so
- -- their returned value is allocated on the secondary stack, even in the
- -- definite case. We must treat nondispatching functions the same way,
- -- because access-to-function types can point at both, so the calling
- -- conventions must be compatible. Is_Tagged_Type includes controlled
- -- types and class-wide types. Controlled type temporaries need
- -- finalization.
-
- -- ???It's not clear why we need to return noncontrolled types with
- -- controlled components on the secondary stack.
-
- elsif Is_Tagged_Type (Typ) or else Has_Controlled_Component (Typ) then
- return True;
-
- -- Untagged definite subtypes are known size. This includes all
- -- elementary [sub]types. Tasks are known size even if they have
- -- discriminants. So we return False here, with one exception:
- -- For a type like:
- -- type T (Last : Natural := 0) is
- -- X : String (1 .. Last);
- -- end record;
- -- we return True. That's because for "P(F(...));", where F returns T,
- -- we don't know the size of the result at the call site, so if we
- -- allocated it on the primary stack, we would have to allocate the
- -- maximum size, which is way too big.
-
- elsif Is_Definite_Subtype (Typ) or else Is_Task_Type (Typ) then
- return Large_Max_Size_Mutable (Typ);
-
- -- Indefinite (discriminated) untagged record or protected type
-
- elsif Is_Record_Type (Typ) or else Is_Protected_Type (Typ) then
- return not Caller_Known_Size_Record (Typ);
-
- -- Unconstrained array
-
- else
- pragma Assert (Is_Array_Type (Typ) and not Is_Definite_Subtype (Typ));
- return True;
- end if;
- end New_Requires_Transient_Scope;
-
------------------------
-- No_Caching_Enabled --
------------------------
@@ -25361,105 +25274,6 @@ package body Sem_Util is
return Num;
end Number_Of_Elements_In_Array;
- ----------------------------------
- -- Old_Requires_Transient_Scope --
- ----------------------------------
-
- function Old_Requires_Transient_Scope (Id : Entity_Id) return Boolean is
- Typ : constant Entity_Id := Underlying_Type (Id);
-
- begin
- -- This is a private type which is not completed yet. This can only
- -- happen in a default expression (of a formal parameter or of a
- -- record component). Do not expand transient scope in this case.
-
- if No (Typ) then
- return False;
-
- -- Do not expand transient scope for non-existent procedure return
-
- elsif Typ = Standard_Void_Type then
- return False;
-
- -- Elementary types do not require a transient scope
-
- elsif Is_Elementary_Type (Typ) then
- return False;
-
- -- Generally, indefinite subtypes require a transient scope, since the
- -- back end cannot generate temporaries, since this is not a valid type
- -- for declaring an object. It might be possible to relax this in the
- -- future, e.g. by declaring the maximum possible space for the type.
-
- elsif not Is_Definite_Subtype (Typ) then
- return True;
-
- -- Functions returning tagged types may dispatch on result so their
- -- returned value is allocated on the secondary stack. Controlled
- -- type temporaries need finalization.
-
- elsif Is_Tagged_Type (Typ) or else Has_Controlled_Component (Typ) then
- return True;
-
- -- Record type
-
- elsif Is_Record_Type (Typ) then
- declare
- Comp : Entity_Id;
-
- begin
- Comp := First_Entity (Typ);
- while Present (Comp) loop
- if Ekind (Comp) = E_Component then
-
- -- ???It's not clear we need a full recursive call to
- -- Old_Requires_Transient_Scope here. Note that the
- -- following can't happen.
-
- pragma Assert (Is_Definite_Subtype (Etype (Comp)));
- pragma Assert (not Has_Controlled_Component (Etype (Comp)));
-
- if Old_Requires_Transient_Scope (Etype (Comp)) then
- return True;
- end if;
- end if;
-
- Next_Entity (Comp);
- end loop;
- end;
-
- return False;
-
- -- String literal types never require transient scope
-
- elsif Ekind (Typ) = E_String_Literal_Subtype then
- return False;
-
- -- Array type. Note that we already know that this is a constrained
- -- array, since unconstrained arrays will fail the indefinite test.
-
- elsif Is_Array_Type (Typ) then
-
- -- If component type requires a transient scope, the array does too
-
- if Old_Requires_Transient_Scope (Component_Type (Typ)) then
- return True;
-
- -- Otherwise, we only need a transient scope if the size depends on
- -- the value of one or more discriminants.
-
- else
- return Size_Depends_On_Discriminant (Typ);
- end if;
-
- -- All other cases do not require a transient scope
-
- else
- pragma Assert (Is_Protected_Type (Typ) or else Is_Task_Type (Typ));
- return False;
- end if;
- end Old_Requires_Transient_Scope;
-
---------------------------------
-- Original_Aspect_Pragma_Name --
---------------------------------
@@ -25678,7 +25492,7 @@ package body Sem_Util is
end if;
end if;
- return (Empty);
+ return Empty;
end Param_Entity;
----------------------
@@ -26169,7 +25983,8 @@ package body Sem_Util is
(Typ : Entity_Id;
From_Typ : Entity_Id)
is
- DIC_Proc : Entity_Id;
+ DIC_Proc : Entity_Id;
+ Partial_DIC_Proc : Entity_Id;
begin
if Present (Typ) and then Present (From_Typ) then
@@ -26190,6 +26005,7 @@ package body Sem_Util is
end if;
DIC_Proc := DIC_Procedure (From_Typ);
+ Partial_DIC_Proc := Partial_DIC_Procedure (From_Typ);
-- The setting of the attributes is intentionally conservative. This
-- prevents accidental clobbering of enabled attributes.
@@ -26205,6 +26021,12 @@ package body Sem_Util is
if Present (DIC_Proc) and then No (DIC_Procedure (Typ)) then
Set_DIC_Procedure (Typ, DIC_Proc);
end if;
+
+ if Present (Partial_DIC_Proc)
+ and then No (Partial_DIC_Procedure (Typ))
+ then
+ Set_Partial_DIC_Procedure (Typ, Partial_DIC_Proc);
+ end if;
end if;
end Propagate_DIC_Attributes;
@@ -26245,7 +26067,7 @@ package body Sem_Util is
end if;
if Has_Own_Invariants (From_Typ) then
- Set_Has_Own_Invariants (Typ);
+ Set_Has_Own_Invariants (Base_Type (Typ));
end if;
if Present (Full_IP) and then No (Invariant_Procedure (Typ)) then
@@ -26549,18 +26371,82 @@ package body Sem_Util is
-- generated before the next instruction.
function Requires_Transient_Scope (Id : Entity_Id) return Boolean is
- Old_Result : constant Boolean := Old_Requires_Transient_Scope (Id);
+ function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean;
+ -- This is called for untagged records and protected types, with
+ -- nondefaulted discriminants. Returns True if the size of function
+ -- results is known at the call site, False otherwise. Returns False
+ -- if there is a variant part that depends on the discriminants of
+ -- this type, or if there is an array constrained by the discriminants
+ -- of this type. ???Currently, this is overly conservative (the array
+ -- could be nested inside some other record that is constrained by
+ -- nondiscriminants). That is, the recursive calls are too conservative.
procedure Ensure_Minimum_Decoration (Typ : Entity_Id);
-- If Typ is not frozen then add to Typ the minimum decoration required
-- by Requires_Transient_Scope to reliably provide its functionality;
-- otherwise no action is performed.
+ function Large_Max_Size_Mutable (Typ : Entity_Id) return Boolean;
+ -- Returns True if Typ is a nonlimited record with defaulted
+ -- discriminants whose max size makes it unsuitable for allocating on
+ -- the primary stack.
+
+ ------------------------------
+ -- Caller_Known_Size_Record --
+ ------------------------------
+
+ function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean is
+ pragma Assert (Typ = Underlying_Type (Typ));
+
+ begin
+ if Has_Variant_Part (Typ) and then not Is_Definite_Subtype (Typ) then
+ return False;
+ end if;
+
+ declare
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+
+ -- Only look at E_Component entities. No need to look at
+ -- E_Discriminant entities, and we must ignore internal
+ -- subtypes generated for constrained components.
+
+ declare
+ Comp_Type : constant Entity_Id :=
+ Underlying_Type (Etype (Comp));
+
+ begin
+ if Is_Record_Type (Comp_Type)
+ or else
+ Is_Protected_Type (Comp_Type)
+ then
+ if not Caller_Known_Size_Record (Comp_Type) then
+ return False;
+ end if;
+
+ elsif Is_Array_Type (Comp_Type) then
+ if Size_Depends_On_Discriminant (Comp_Type) then
+ return False;
+ end if;
+ end if;
+ end;
+
+ Next_Component (Comp);
+ end loop;
+ end;
+
+ return True;
+ end Caller_Known_Size_Record;
+
-------------------------------
-- Ensure_Minimum_Decoration --
-------------------------------
procedure Ensure_Minimum_Decoration (Typ : Entity_Id) is
+ Comp : Entity_Id;
begin
-- Do not set Has_Controlled_Component on a class-wide equivalent
-- type. See Make_CW_Equivalent_Type.
@@ -26572,82 +26458,182 @@ package body Sem_Util is
or else Is_Incomplete_Or_Private_Type (Typ))
and then not Is_Class_Wide_Equivalent_Type (Typ)
then
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+ if Has_Controlled_Component (Etype (Comp))
+ or else
+ (Chars (Comp) /= Name_uParent
+ and then Is_Controlled (Etype (Comp)))
+ or else
+ (Is_Protected_Type (Etype (Comp))
+ and then
+ Present (Corresponding_Record_Type (Etype (Comp)))
+ and then
+ Has_Controlled_Component
+ (Corresponding_Record_Type (Etype (Comp))))
+ then
+ Set_Has_Controlled_Component (Typ);
+ exit;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ end if;
+ end Ensure_Minimum_Decoration;
+
+ ------------------------------
+ -- Large_Max_Size_Mutable --
+ ------------------------------
+
+ function Large_Max_Size_Mutable (Typ : Entity_Id) return Boolean is
+ pragma Assert (Typ = Underlying_Type (Typ));
+
+ function Is_Large_Discrete_Type (T : Entity_Id) return Boolean;
+ -- Returns true if the discrete type T has a large range
+
+ ----------------------------
+ -- Is_Large_Discrete_Type --
+ ----------------------------
+
+ function Is_Large_Discrete_Type (T : Entity_Id) return Boolean is
+ Threshold : constant Int := 16;
+ -- Arbitrary threshold above which we consider it "large". We want
+ -- a fairly large threshold, because these large types really
+ -- shouldn't have default discriminants in the first place, in
+ -- most cases.
+
+ begin
+ return UI_To_Int (RM_Size (T)) > Threshold;
+ end Is_Large_Discrete_Type;
+
+ -- Start of processing for Large_Max_Size_Mutable
+
+ begin
+ if Is_Record_Type (Typ)
+ and then not Is_Limited_View (Typ)
+ and then Has_Defaulted_Discriminants (Typ)
+ then
+ -- Loop through the components, looking for an array whose upper
+ -- bound(s) depends on discriminants, where both the subtype of
+ -- the discriminant and the index subtype are too large.
+
declare
Comp : Entity_Id;
begin
Comp := First_Component (Typ);
while Present (Comp) loop
- if Has_Controlled_Component (Etype (Comp))
- or else
- (Chars (Comp) /= Name_uParent
- and then Is_Controlled (Etype (Comp)))
- or else
- (Is_Protected_Type (Etype (Comp))
- and then
- Present (Corresponding_Record_Type (Etype (Comp)))
- and then
- Has_Controlled_Component
- (Corresponding_Record_Type (Etype (Comp))))
- then
- Set_Has_Controlled_Component (Typ);
- exit;
- end if;
+ declare
+ Comp_Type : constant Entity_Id :=
+ Underlying_Type (Etype (Comp));
+
+ Hi : Node_Id;
+ Indx : Node_Id;
+ Ityp : Entity_Id;
+
+ begin
+ if Is_Array_Type (Comp_Type) then
+ Indx := First_Index (Comp_Type);
+
+ while Present (Indx) loop
+ Ityp := Etype (Indx);
+ Hi := Type_High_Bound (Ityp);
+
+ if Nkind (Hi) = N_Identifier
+ and then Ekind (Entity (Hi)) = E_Discriminant
+ and then Is_Large_Discrete_Type (Ityp)
+ and then Is_Large_Discrete_Type
+ (Etype (Entity (Hi)))
+ then
+ return True;
+ end if;
+
+ Next_Index (Indx);
+ end loop;
+ end if;
+ end;
Next_Component (Comp);
end loop;
end;
end if;
- end Ensure_Minimum_Decoration;
+
+ return False;
+ end Large_Max_Size_Mutable;
+
+ -- Local declarations
+
+ Typ : constant Entity_Id := Underlying_Type (Id);
-- Start of processing for Requires_Transient_Scope
begin
- if Debug_Flag_QQ then
- return Old_Result;
- end if;
-
Ensure_Minimum_Decoration (Id);
- declare
- New_Result : constant Boolean := New_Requires_Transient_Scope (Id);
+ -- This is a private type which is not completed yet. This can only
+ -- happen in a default expression (of a formal parameter or of a
+ -- record component). Do not expand transient scope in this case.
- begin
- -- Assert that we're not putting things on the secondary stack if we
- -- didn't before; we are trying to AVOID secondary stack when
- -- possible.
+ if No (Typ) then
+ return False;
- if not Old_Result then
- pragma Assert (not New_Result);
- null;
- end if;
+ -- Do not expand transient scope for non-existent procedure return or
+ -- string literal types.
- if New_Result /= Old_Result then
- Results_Differ (Id, Old_Result, New_Result);
- end if;
+ elsif Typ = Standard_Void_Type
+ or else Ekind (Typ) = E_String_Literal_Subtype
+ then
+ return False;
- return New_Result;
- end;
- end Requires_Transient_Scope;
+ -- If Typ is a generic formal incomplete type, then we want to look at
+ -- the actual type.
- --------------------
- -- Results_Differ --
- --------------------
+ elsif Ekind (Typ) = E_Record_Subtype
+ and then Present (Cloned_Subtype (Typ))
+ then
+ return Requires_Transient_Scope (Cloned_Subtype (Typ));
- procedure Results_Differ
- (Id : Entity_Id;
- Old_Val : Boolean;
- New_Val : Boolean)
- is
- begin
- if False then -- False to disable; True for debugging
- Treepr.Print_Tree_Node (Id);
+ -- Functions returning specific tagged types may dispatch on result, so
+ -- their returned value is allocated on the secondary stack, even in the
+ -- definite case. We must treat nondispatching functions the same way,
+ -- because access-to-function types can point at both, so the calling
+ -- conventions must be compatible. Is_Tagged_Type includes controlled
+ -- types and class-wide types. Controlled type temporaries need
+ -- finalization.
- if Old_Val = New_Val then
- raise Program_Error;
- end if;
+ -- ???It's not clear why we need to return noncontrolled types with
+ -- controlled components on the secondary stack.
+
+ elsif Is_Tagged_Type (Typ) or else Has_Controlled_Component (Typ) then
+ return True;
+
+ -- Untagged definite subtypes are known size. This includes all
+ -- elementary [sub]types. Tasks are known size even if they have
+ -- discriminants. So we return False here, with one exception:
+ -- For a type like:
+ -- type T (Last : Natural := 0) is
+ -- X : String (1 .. Last);
+ -- end record;
+ -- we return True. That's because for "P(F(...));", where F returns T,
+ -- we don't know the size of the result at the call site, so if we
+ -- allocated it on the primary stack, we would have to allocate the
+ -- maximum size, which is way too big.
+
+ elsif Is_Definite_Subtype (Typ) or else Is_Task_Type (Typ) then
+ return Large_Max_Size_Mutable (Typ);
+
+ -- Indefinite (discriminated) untagged record or protected type
+
+ elsif Is_Record_Type (Typ) or else Is_Protected_Type (Typ) then
+ return not Caller_Known_Size_Record (Typ);
+
+ -- Unconstrained array
+
+ else
+ pragma Assert (Is_Array_Type (Typ) and not Is_Definite_Subtype (Typ));
+ return True;
end if;
- end Results_Differ;
+ end Requires_Transient_Scope;
--------------------------
-- Reset_Analyzed_Flags --
@@ -27583,8 +27569,6 @@ package body Sem_Util is
Style.Check_Identifier (Nod, Val_Actual);
end if;
end if;
-
- Set_Entity (N, Val);
end Set_Entity_With_Checks;
------------------------------
@@ -29626,10 +29610,10 @@ package body Sem_Util is
and then Covers
(Designated_Type (Expec_Type), Designated_Type (Found_Type))
then
- Error_Msg_N -- CODEFIX
+ Error_Msg_N
("result must be general access type!", Expr);
Error_Msg_NE -- CODEFIX
- ("add ALL to }!", Expr, Expec_Type);
+ ("\add ALL to }!", Expr, Expec_Type);
-- Another special check, if the expected type is an integer type,
-- but the expression is of type System.Address, and the parent is
@@ -31077,7 +31061,7 @@ package body Sem_Util is
--
-- See Large_Max_Size_Mutable function elsewhere in this
-- file (currently declared inside of
- -- New_Requires_Transient_Scope, so it would have to be
+ -- Requires_Transient_Scope, so it would have to be
-- moved if we want it to be callable from here).
end Indirect_Temp_Needed;
@@ -31131,9 +31115,9 @@ package body Sem_Util is
-- If the prefix is of an anonymous access type, then returns
-- the designated type of that type.
- -----------------------------
+ -----------------------------
-- Designated_Subtype_Mark --
- -----------------------------
+ -----------------------------
function Designated_Subtype_Mark return Node_Id is
Typ : Entity_Id := Prefix_Type;
@@ -31171,6 +31155,16 @@ package body Sem_Util is
Append_Item (Temp_Decl, Is_Eval_Stmt => False);
end if;
+ -- When a type associated with an indirect temporary gets
+ -- created for a 'Old attribute reference we need to mark
+ -- the type as such. This allows, for example, finalization
+ -- masters associated with them to be finalized in the correct
+ -- order after postcondition checks.
+
+ if Attribute_Name (Parent (Attr_Prefix)) = Name_Old then
+ Set_Stores_Attribute_Old_Prefix (Access_Type_Id);
+ end if;
+
Analyze (Access_Type_Decl);
Analyze (Temp_Decl);
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 1b993f9..6560180 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -765,6 +765,10 @@ package Sem_Util is
-- Returns the Node_Id associated with the innermost enclosing generic
-- unit, if any. If none, then returns Empty.
+ function Enclosing_HSS (Stmt : Node_Id) return Node_Id;
+ -- Returns the nearest handled sequence of statements that encloses a given
+ -- statement, or Empty.
+
function Enclosing_Lib_Unit_Entity
(E : Entity_Id := Current_Scope) return Entity_Id;
-- Returns the entity of enclosing library unit node which is the root of
@@ -1045,11 +1049,13 @@ package Sem_Util is
-- be installed on the scope stack to prevent spurious visibility errors.
procedure Gather_Components
- (Typ : Entity_Id;
- Comp_List : Node_Id;
- Governed_By : List_Id;
- Into : Elist_Id;
- Report_Errors : out Boolean);
+ (Typ : Entity_Id;
+ Comp_List : Node_Id;
+ Governed_By : List_Id;
+ Into : Elist_Id;
+ Report_Errors : out Boolean;
+ Allow_Compile_Time : Boolean := False;
+ Include_Interface_Tag : Boolean := False);
-- The purpose of this procedure is to gather the valid components in a
-- record type according to the values of its discriminants, in order to
-- validate the components of a record aggregate.
@@ -1072,6 +1078,12 @@ package Sem_Util is
-- Report_Errors is set to True if the values of the discriminants are
-- non-static.
--
+ -- Allow_Compile_Time if set to True, allows compile time known values in
+ -- Governed_By expressions in addition to static expressions.
+ --
+ -- Include_Interface_Tag if set to True, gather any interface tag
+ -- component, otherwise exclude them.
+ --
-- This procedure is also used when building a record subtype. If the
-- discriminant constraint of the subtype is static, the components of the
-- subtype are only those of the variants selected by the values of the
@@ -1503,9 +1515,7 @@ package Sem_Util is
function Has_Tagged_Component (Typ : Entity_Id) return Boolean;
-- Returns True if Typ is a composite type (array or record) that is either
-- a tagged type or has a subcomponent that is tagged. Returns False for a
- -- noncomposite type, or if no tagged subcomponents are present. This
- -- function is used to check if "=" has to be expanded into a bunch
- -- component comparisons.
+ -- noncomposite type, or if no tagged subcomponents are present.
function Has_Unconstrained_Access_Discriminants
(Subtyp : Entity_Id) return Boolean;
@@ -1540,6 +1550,12 @@ package Sem_Util is
-- Returns True if node N appears within a pragma that acts as an assertion
-- expression. See Sem_Prag for the list of qualifying pragmas.
+ function In_Check_Node (N : Node_Id) return Boolean;
+ -- Return True if N is part of a N_Raise_xxx_Error node
+
+ function In_Generic_Formal_Package (E : Entity_Id) return Boolean;
+ -- Returns True if entity E is inside a generic formal package
+
function In_Generic_Scope (E : Entity_Id) return Boolean;
-- Returns True if entity E is inside a generic scope
@@ -1691,6 +1707,10 @@ package Sem_Util is
function Is_Actual_Out_Parameter (N : Node_Id) return Boolean;
-- Determines if N is an actual parameter of out mode in a subprogram call
+ function Is_Actual_Out_Or_In_Out_Parameter (N : Node_Id) return Boolean;
+ -- Determines if N is an actual parameter of out or in out mode in a
+ -- subprogram call.
+
function Is_Actual_Parameter (N : Node_Id) return Boolean;
-- Determines if N is an actual parameter in a subprogram call
@@ -1879,7 +1899,9 @@ package Sem_Util is
-- . machine_emax = 2**10
-- . machine_emin = 3 - machine_emax
- function Is_Effectively_Volatile (Id : Entity_Id) return Boolean;
+ function Is_Effectively_Volatile
+ (Id : Entity_Id;
+ Ignore_Protected : Boolean := False) return Boolean;
-- Determine whether a type or object denoted by entity Id is effectively
-- volatile (SPARK RM 7.1.2). To qualify as such, the entity must be either
-- * Volatile without No_Caching
@@ -1887,9 +1909,14 @@ package Sem_Util is
-- * An array type whose component type is effectively volatile
-- * A protected type
-- * Descendant of type Ada.Synchronous_Task_Control.Suspension_Object
+ --
+ -- If Ignore_Protected is True, then a protected object/type is treated
+ -- like a non-protected record object/type for computing the result of
+ -- this query.
function Is_Effectively_Volatile_For_Reading
- (Id : Entity_Id) return Boolean;
+ (Id : Entity_Id;
+ Ignore_Protected : Boolean := False) return Boolean;
-- Determine whether a type or object denoted by entity Id is effectively
-- volatile for reading (SPARK RM 7.1.2). To qualify as such, the entity
-- must be either
@@ -1901,6 +1928,10 @@ package Sem_Util is
-- reading
-- * A protected type
-- * Descendant of type Ada.Synchronous_Task_Control.Suspension_Object
+ --
+ -- If Ignore_Protected is True, then a protected object/type is treated
+ -- like a non-protected record object/type for computing the result of
+ -- this query.
function Is_Effectively_Volatile_Object
(N : Node_Id) return Boolean;
@@ -2220,6 +2251,13 @@ package Sem_Util is
-- the N_Statement_Other_Than_Procedure_Call subtype from Sinfo).
-- Note that a label is *not* a statement, and will return False.
+ function Is_Static_Discriminant_Component (N : Node_Id) return Boolean;
+ -- Return True if N is guaranteed to a selected component containing a
+ -- statically known discriminant.
+ -- Note that this routine takes a conservative view and may return False
+ -- in some cases where N would match the criteria. In other words this
+ -- routine should be used to simplify or optimize the expanded code.
+
function Is_Static_Function (Subp : Entity_Id) return Boolean;
-- Determine whether subprogram Subp denotes a static function,
-- which is a function with the aspect Static with value True.
@@ -2479,7 +2517,7 @@ package Sem_Util is
-- entity E. If no such instance exits, return Empty.
function Needs_Finalization (Typ : Entity_Id) return Boolean;
- -- Determine whether type Typ is controlled and this requires finalization
+ -- Determine whether type Typ is controlled and thus requires finalization
-- actions.
function Needs_One_Actual (E : Entity_Id) return Boolean;
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
index d1acf2f..b5275a8 100644
--- a/gcc/ada/sem_warn.adb
+++ b/gcc/ada/sem_warn.adb
@@ -750,9 +750,7 @@ package body Sem_Warn is
Fstm : constant Node_Id :=
Original_Node (First (Statements (Loop_Statement)));
begin
- if Nkind (Fstm) = N_Delay_Relative_Statement
- or else Nkind (Fstm) = N_Delay_Until_Statement
- then
+ if Nkind (Fstm) in N_Delay_Statement then
return;
end if;
end;
@@ -3077,14 +3075,14 @@ package body Sem_Warn is
-- Here we generate the warning
else
- -- If -gnatwc is set then output message that we could be IN
+ -- If -gnatwk is set then output message that we could be IN
if not Is_Trivial_Subprogram (Scope (E1)) then
if Warn_On_Constant then
Error_Msg_N
- ("?u?formal parameter & is not modified!", E1);
+ ("?k?formal parameter & is not modified!", E1);
Error_Msg_N
- ("\?u?mode could be IN instead of `IN OUT`!", E1);
+ ("\?k?mode could be IN instead of `IN OUT`!", E1);
-- We do not generate warnings for IN OUT parameters
-- unless we have at least -gnatwu. This is deliberately
@@ -4421,23 +4419,30 @@ package body Sem_Warn is
end if;
declare
- B : constant Node_Id := Parent (Parent (Scope (E)));
- S : Entity_Id := Empty;
+ S : Node_Id := Scope (E);
begin
- if Nkind (B) in
- N_Expression_Function |
- N_Subprogram_Body |
- N_Subprogram_Renaming_Declaration
- then
- S := Corresponding_Spec (B);
+ if Ekind (S) = E_Subprogram_Body then
+ S := Parent (S);
+
+ while Nkind (S) not in
+ N_Expression_Function |
+ N_Subprogram_Body |
+ N_Subprogram_Renaming_Declaration |
+ N_Empty
+ loop
+ S := Parent (S);
+ end loop;
+
+ if Present (S) then
+ S := Corresponding_Spec (S);
+ end if;
end if;
-- Do not warn for dispatching operations, because
-- that causes too much noise. Also do not warn for
- -- trivial subprograms.
+ -- trivial subprograms (e.g. stubs).
- if (not Present (S)
- or else not Is_Dispatching_Operation (S))
+ if (No (S) or else not Is_Dispatching_Operation (S))
and then not Is_Trivial_Subprogram (Scope (E))
then
Error_Msg_NE -- CODEFIX
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index c88d9a9..2d0a957 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -3535,6 +3535,14 @@ package body Sinfo is
return Flag2 (N);
end Was_Attribute_Reference;
+ function Was_Default_Init_Box_Association
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Component_Association);
+ return Flag14 (N);
+ end Was_Default_Init_Box_Association;
+
function Was_Expression_Function
(N : Node_Id) return Boolean is
begin
@@ -7036,6 +7044,14 @@ package body Sinfo is
Set_Flag2 (N, Val);
end Set_Was_Attribute_Reference;
+ procedure Set_Was_Default_Init_Box_Association
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Component_Association);
+ Set_Flag14 (N, Val);
+ end Set_Was_Default_Init_Box_Association;
+
procedure Set_Was_Expression_Function
(N : Node_Id; Val : Boolean := True) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 439eef4..f9b0667 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -2412,6 +2412,11 @@ package Sinfo is
-- instantiation prologue renames these attributes, and expansion later
-- converts them into subprogram bodies.
+ -- Was_Default_Init_Box_Association (Flag14-Sem)
+ -- Present in N_Component_Association. Set to True if the original source
+ -- is an aggregate component association with a box (<>) for a component
+ -- that is initialized by default.
+
-- Was_Expression_Function (Flag18-Sem)
-- Present in N_Subprogram_Body. True if the original source had an
-- N_Expression_Function, which was converted to the N_Subprogram_Body
@@ -4120,6 +4125,7 @@ package Sinfo is
-- Expression (Node3) (empty if Box_Present)
-- Loop_Actions (List5-Sem)
-- Box_Present (Flag15)
+ -- Was_Default_Init_Box_Association (Flag14)
-- Inherited_Discriminant (Flag13)
-- Note: this structure is used for both record component associations
@@ -4128,7 +4134,9 @@ package Sinfo is
-- list of selector names in the record aggregate case, or a list of
-- discrete choices in the array aggregate case or an N_Others_Choice
-- node (which appears as a singleton list). Box_Present gives support
- -- to Ada 2005 (AI-287).
+ -- to Ada 2005 (AI-287). Was_Default_Init_Box_Association is used for
+ -- determining the need for Default_Initial_Condition check on component
+ -- associations with a box.
----------------------------------
-- 4.3.1 Component Choice List --
@@ -10254,6 +10262,9 @@ package Sinfo is
function Was_Attribute_Reference
(N : Node_Id) return Boolean; -- Flag2
+ function Was_Default_Init_Box_Association
+ (N : Node_Id) return Boolean; -- Flag14
+
function Was_Expression_Function
(N : Node_Id) return Boolean; -- Flag18
@@ -11366,6 +11377,9 @@ package Sinfo is
procedure Set_Was_Attribute_Reference
(N : Node_Id; Val : Boolean := True); -- Flag2
+ procedure Set_Was_Default_Init_Box_Association
+ (N : Node_Id; Val : Boolean := True); -- Flag14
+
procedure Set_Was_Expression_Function
(N : Node_Id; Val : Boolean := True); -- Flag18
@@ -13477,6 +13491,7 @@ package Sinfo is
pragma Inline (Visible_Declarations);
pragma Inline (Used_Operations);
pragma Inline (Was_Attribute_Reference);
+ pragma Inline (Was_Default_Init_Box_Association);
pragma Inline (Was_Expression_Function);
pragma Inline (Was_Originally_Stub);
@@ -13842,6 +13857,7 @@ package Sinfo is
pragma Inline (Set_Variants);
pragma Inline (Set_Visible_Declarations);
pragma Inline (Set_Was_Attribute_Reference);
+ pragma Inline (Set_Was_Default_Init_Box_Association);
pragma Inline (Set_Was_Expression_Function);
pragma Inline (Set_Was_Originally_Stub);
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index a9fd7c5..715a53a 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -147,6 +147,7 @@ package Snames is
Name_Integer_Literal : constant Name_Id := N + $;
Name_Real_Literal : constant Name_Id := N + $;
Name_Relaxed_Initialization : constant Name_Id := N + $;
+ Name_Stable_Properties : constant Name_Id := N + $;
Name_Static_Predicate : constant Name_Id := N + $;
Name_String_Literal : constant Name_Id := N + $;
Name_Synchronization : constant Name_Id := N + $;
@@ -167,6 +168,8 @@ package Snames is
Name_uEntry_Bodies : constant Name_Id := N + $;
Name_uExpunge : constant Name_Id := N + $;
Name_uFinalizer : constant Name_Id := N + $;
+ Name_uFinalizer_Old : constant Name_Id := N + $;
+ Name_uFinalization_Controller : constant Name_Id := N + $;
Name_uIdepth : constant Name_Id := N + $;
Name_uInit : constant Name_Id := N + $;
Name_uInit_Level : constant Name_Id := N + $;
@@ -175,11 +178,14 @@ package Snames is
Name_uObject : constant Name_Id := N + $;
Name_uPost : constant Name_Id := N + $;
Name_uPostconditions : constant Name_Id := N + $;
+ Name_uPostcond_Enabled : constant Name_Id := N + $;
Name_uPre : constant Name_Id := N + $;
Name_uPriority : constant Name_Id := N + $;
Name_uProcess_ATSD : constant Name_Id := N + $;
Name_uRelative_Deadline : constant Name_Id := N + $;
Name_uResult : constant Name_Id := N + $;
+ Name_uResult_Object_For_Postcond : constant Name_Id := N + $;
+ Name_uReturn_Success_For_Postcond : constant Name_Id := N + $;
Name_uSecondary_Stack : constant Name_Id := N + $;
Name_uSecondary_Stack_Size : constant Name_Id := N + $;
Name_uService : constant Name_Id := N + $;
@@ -756,8 +762,9 @@ package Snames is
Name_DLL : constant Name_Id := N + $;
Name_Win32 : constant Name_Id := N + $;
- -- Other special names used in processing attributes and pragmas
+ -- Other special names used in processing attributes, aspects, and pragmas
+ Name_Aggregate : constant Name_Id := N + $;
Name_Allow : constant Name_Id := N + $;
Name_Amount : constant Name_Id := N + $;
Name_As_Is : constant Name_Id := N + $;
@@ -839,9 +846,12 @@ package Snames is
Name_No_Use_Of_Entity : constant Name_Id := N + $;
Name_No_Use_Of_Pragma : constant Name_Id := N + $;
Name_No_Unroll : constant Name_Id := N + $;
+ Name_No_Unrecognized_Aspects : constant Name_Id := N + $;
+ Name_No_Unrecognized_Pragmas : constant Name_Id := N + $;
Name_No_Vector : constant Name_Id := N + $;
Name_Nominal : constant Name_Id := N + $;
Name_Non_Volatile : constant Name_Id := N + $;
+ Name_None : constant Name_Id := N + $;
Name_On : constant Name_Id := N + $;
Name_Optional : constant Name_Id := N + $;
Name_Policy : constant Name_Id := N + $;
@@ -1019,6 +1029,8 @@ package Snames is
Name_Signed_Zeros : constant Name_Id := N + $;
Name_Size : constant Name_Id := N + $;
Name_Small : constant Name_Id := N + $; -- Ada 83
+ Name_Small_Denominator : constant Name_Id := N + $; -- GNAT
+ Name_Small_Numerator : constant Name_Id := N + $; -- GNAT
Name_Storage_Size : constant Name_Id := N + $;
Name_Storage_Unit : constant Name_Id := N + $; -- GNAT
Name_Stream_Size : constant Name_Id := N + $; -- Ada 05
@@ -1356,186 +1368,17 @@ package Snames is
Name_Raise_Exception : constant Name_Id := N + $;
- -- Additional reserved words and identifiers used in GNAT Project Files
- -- Note that Name_External is already previously declared.
-
- -- Names with a -- GB annotation are only used in gprbuild or gprclean
-
- Name_Active : constant Name_Id := N + $;
- Name_Aggregate : constant Name_Id := N + $;
- Name_Archive_Builder : constant Name_Id := N + $;
- Name_Archive_Builder_Append_Option : constant Name_Id := N + $;
- Name_Archive_Indexer : constant Name_Id := N + $;
- Name_Archive_Suffix : constant Name_Id := N + $;
- Name_Artifacts : constant Name_Id := N + $;
- Name_Artifacts_In_Exec_Dir : constant Name_Id := N + $; -- GB
- Name_Artifacts_In_Object_Dir : constant Name_Id := N + $; -- GB
- Name_Binder : constant Name_Id := N + $;
- Name_Body_Suffix : constant Name_Id := N + $;
- Name_Builder : constant Name_Id := N + $;
- Name_Clean : constant Name_Id := N + $;
- Name_Compiler : constant Name_Id := N + $;
- Name_Compiler_Command : constant Name_Id := N + $; -- GB
- Name_Config_Body_File_Name : constant Name_Id := N + $;
- Name_Config_Body_File_Name_Index : constant Name_Id := N + $;
- Name_Config_Body_File_Name_Pattern : constant Name_Id := N + $;
- Name_Config_File_Switches : constant Name_Id := N + $;
- Name_Config_File_Unique : constant Name_Id := N + $;
- Name_Config_Spec_File_Name : constant Name_Id := N + $;
- Name_Config_Spec_File_Name_Index : constant Name_Id := N + $;
- Name_Config_Spec_File_Name_Pattern : constant Name_Id := N + $;
- Name_Configuration : constant Name_Id := N + $;
- Name_Cross_Reference : constant Name_Id := N + $;
- Name_Default_Language : constant Name_Id := N + $;
- Name_Default_Switches : constant Name_Id := N + $;
- Name_Dependency_Driver : constant Name_Id := N + $;
- Name_Dependency_Kind : constant Name_Id := N + $;
- Name_Dependency_Switches : constant Name_Id := N + $;
- Name_Driver : constant Name_Id := N + $;
- Name_Excluded_Source_Dirs : constant Name_Id := N + $;
- Name_Excluded_Source_Files : constant Name_Id := N + $;
- Name_Excluded_Source_List_File : constant Name_Id := N + $;
- Name_Exec_Dir : constant Name_Id := N + $;
- Name_Exec_Subdir : constant Name_Id := N + $;
- Name_Excluded_Patterns : constant Name_Id := N + $;
- Name_Executable : constant Name_Id := N + $;
- Name_Executable_Suffix : constant Name_Id := N + $;
- Name_Extends : constant Name_Id := N + $;
- Name_External_As_List : constant Name_Id := N + $;
- Name_Externally_Built : constant Name_Id := N + $;
- Name_Finder : constant Name_Id := N + $;
- Name_Global_Compilation_Switches : constant Name_Id := N + $;
- Name_Global_Configuration_Pragmas : constant Name_Id := N + $;
- Name_Global_Config_File : constant Name_Id := N + $; -- GB
- Name_Gnatls : constant Name_Id := N + $;
- Name_Gnatstub : constant Name_Id := N + $;
- Name_Gnu : constant Name_Id := N + $;
- Name_Ide : constant Name_Id := N + $;
- Name_Ignore_Source_Sub_Dirs : constant Name_Id := N + $;
- Name_Implementation : constant Name_Id := N + $;
- Name_Implementation_Exceptions : constant Name_Id := N + $;
- Name_Implementation_Suffix : constant Name_Id := N + $;
- Name_Included_Artifact_Patterns : constant Name_Id := N + $;
- Name_Included_Patterns : constant Name_Id := N + $;
- Name_Include_Switches : constant Name_Id := N + $;
- Name_Include_Path : constant Name_Id := N + $;
- Name_Include_Path_File : constant Name_Id := N + $;
- Name_Inherit_Source_Path : constant Name_Id := N + $;
- Name_Install : constant Name_Id := N + $;
- Name_Install_Name : constant Name_Id := N + $;
- Name_Languages : constant Name_Id := N + $;
- Name_Language_Kind : constant Name_Id := N + $;
- Name_Leading_Library_Options : constant Name_Id := N + $;
- Name_Leading_Required_Switches : constant Name_Id := N + $;
- Name_Leading_Switches : constant Name_Id := N + $;
- Name_Lib_Subdir : constant Name_Id := N + $;
- Name_Link_Lib_Subdir : constant Name_Id := N + $;
- Name_Library : constant Name_Id := N + $;
- Name_Library_Ali_Dir : constant Name_Id := N + $;
- Name_Library_Auto_Init : constant Name_Id := N + $;
- Name_Library_Auto_Init_Supported : constant Name_Id := N + $;
- Name_Library_Builder : constant Name_Id := N + $;
- Name_Library_Dir : constant Name_Id := N + $;
- Name_Library_GCC : constant Name_Id := N + $;
- Name_Library_Install_Name_Option : constant Name_Id := N + $;
- Name_Library_Interface : constant Name_Id := N + $;
- Name_Library_Kind : constant Name_Id := N + $;
- Name_Library_Name : constant Name_Id := N + $;
- Name_Library_Major_Minor_Id_Supported : constant Name_Id := N + $;
- Name_Library_Options : constant Name_Id := N + $;
- Name_Library_Partial_Linker : constant Name_Id := N + $;
- Name_Library_Reference_Symbol_File : constant Name_Id := N + $;
- Name_Library_Rpath_Options : constant Name_Id := N + $; -- GB
- Name_Library_Standalone : constant Name_Id := N + $;
- Name_Library_Encapsulated_Options : constant Name_Id := N + $; -- GB
- Name_Library_Encapsulated_Supported : constant Name_Id := N + $; -- GB
- Name_Library_Src_Dir : constant Name_Id := N + $;
- Name_Library_Support : constant Name_Id := N + $;
- Name_Library_Symbol_File : constant Name_Id := N + $;
- Name_Library_Symbol_Policy : constant Name_Id := N + $;
- Name_Library_Version : constant Name_Id := N + $;
- Name_Library_Version_Switches : constant Name_Id := N + $;
- Name_Linker : constant Name_Id := N + $;
- Name_Linker_Executable_Option : constant Name_Id := N + $;
- Name_Linker_Lib_Dir_Option : constant Name_Id := N + $;
- Name_Linker_Lib_Name_Option : constant Name_Id := N + $;
- Name_Local_Config_File : constant Name_Id := N + $; -- GB
- Name_Local_Configuration_Pragmas : constant Name_Id := N + $;
- Name_Locally_Removed_Files : constant Name_Id := N + $;
- Name_Map_File_Option : constant Name_Id := N + $;
- Name_Mapping_File_Switches : constant Name_Id := N + $;
- Name_Mapping_Spec_Suffix : constant Name_Id := N + $;
- Name_Mapping_Body_Suffix : constant Name_Id := N + $;
- Name_Max_Command_Line_Length : constant Name_Id := N + $;
- Name_Metrics : constant Name_Id := N + $;
- Name_Multi_Unit_Object_Separator : constant Name_Id := N + $;
- Name_Multi_Unit_Switches : constant Name_Id := N + $;
- Name_Naming : constant Name_Id := N + $;
- Name_None : constant Name_Id := N + $;
- Name_Object_Artifact_Extensions : constant Name_Id := N + $;
- Name_Object_File_Suffix : constant Name_Id := N + $;
- Name_Object_File_Switches : constant Name_Id := N + $;
- Name_Object_Generated : constant Name_Id := N + $;
- Name_Object_List : constant Name_Id := N + $;
- Name_Object_Path_Switches : constant Name_Id := N + $;
- Name_Objects_Linked : constant Name_Id := N + $;
- Name_Objects_Path : constant Name_Id := N + $;
- Name_Objects_Path_File : constant Name_Id := N + $;
- Name_Object_Dir : constant Name_Id := N + $;
- Name_Option_List : constant Name_Id := N + $;
- Name_Path_Syntax : constant Name_Id := N + $;
- Name_Pic_Option : constant Name_Id := N + $;
- Name_Pretty_Printer : constant Name_Id := N + $;
- Name_Prefix : constant Name_Id := N + $;
- Name_Project : constant Name_Id := N + $;
- Name_Project_Dir : constant Name_Id := N + $;
- Name_Project_Files : constant Name_Id := N + $;
- Name_Project_Path : constant Name_Id := N + $;
- Name_Project_Subdir : constant Name_Id := N + $;
- Name_Remote : constant Name_Id := N + $;
- Name_Required_Artifacts : constant Name_Id := N + $;
- Name_Response_File_Format : constant Name_Id := N + $;
- Name_Response_File_Switches : constant Name_Id := N + $;
- Name_Root_Dir : constant Name_Id := N + $;
- Name_Roots : constant Name_Id := N + $; -- GB
- Name_Required_Switches : constant Name_Id := N + $;
- Name_Run_Path_Option : constant Name_Id := N + $;
- Name_Run_Path_Origin : constant Name_Id := N + $;
- Name_Separate_Run_Path_Options : constant Name_Id := N + $;
- Name_Shared_Library_Minimum_Switches : constant Name_Id := N + $;
- Name_Shared_Library_Prefix : constant Name_Id := N + $;
- Name_Shared_Library_Suffix : constant Name_Id := N + $;
- Name_Separate_Suffix : constant Name_Id := N + $;
- Name_Source_Artifact_Extensions : constant Name_Id := N + $;
- Name_Source_Dirs : constant Name_Id := N + $;
- Name_Source_File_Switches : constant Name_Id := N + $;
- Name_Source_Files : constant Name_Id := N + $;
- Name_Source_List_File : constant Name_Id := N + $;
- Name_Sources_Subdir : constant Name_Id := N + $;
- Name_Spec : constant Name_Id := N + $;
- Name_Spec_Suffix : constant Name_Id := N + $;
- Name_Specification : constant Name_Id := N + $;
- Name_Specification_Exceptions : constant Name_Id := N + $;
- Name_Specification_Suffix : constant Name_Id := N + $;
- Name_Stack : constant Name_Id := N + $;
- Name_Switches : constant Name_Id := N + $;
- Name_Symbolic_Link_Supported : constant Name_Id := N + $;
- Name_Synchronize : constant Name_Id := N + $;
- Name_Toolchain_Description : constant Name_Id := N + $;
- Name_Toolchain_Version : constant Name_Id := N + $;
- Name_Trailing_Required_Switches : constant Name_Id := N + $;
- Name_Trailing_Switches : constant Name_Id := N + $;
- Name_Runtime_Library_Dir : constant Name_Id := N + $;
- Name_Runtime_Source_Dir : constant Name_Id := N + $;
-
-- Additional names used by the Repinfo unit
Name_Discriminant : constant Name_Id := N + $;
Name_Operands : constant Name_Id := N + $;
-- Other miscellaneous names used in front end
+ -- Note that the UP_ prefix means use the rest of the name in uppercase,
+ -- e.g. Name_UP_RESULT corresponds to the name "RESULT".
Name_Unaligned_Valid : constant Name_Id := N + $;
+ Name_UP_RESULT : constant Name_Id := N + $;
Name_Suspension_Object : constant Name_Id := N + $;
Name_Synchronous_Task_Control : constant Name_Id := N + $;
@@ -1715,6 +1558,8 @@ package Snames is
Attribute_Signed_Zeros,
Attribute_Size,
Attribute_Small,
+ Attribute_Small_Denominator,
+ Attribute_Small_Numerator,
Attribute_Storage_Size,
Attribute_Storage_Unit,
Attribute_Stream_Size,
diff --git a/gcc/ada/spark_xrefs.ads b/gcc/ada/spark_xrefs.ads
index 88a34c5..ffd7268 100644
--- a/gcc/ada/spark_xrefs.ads
+++ b/gcc/ada/spark_xrefs.ads
@@ -57,7 +57,8 @@ package SPARK_Xrefs is
Heap : Entity_Id := Empty;
-- A special entity which denotes the heap object; it should be considered
-- constant, but needs to be variable, because it can only be initialized
- -- after the node tables are created.
+ -- after the node tables are created. Also, it is only created if there is
+ -- an actual need for it, and remains Empty otherwise.
-----------------
-- Subprograms --
diff --git a/gcc/ada/stand.ads b/gcc/ada/stand.ads
index 5742e51..848239f 100644
--- a/gcc/ada/stand.ads
+++ b/gcc/ada/stand.ads
@@ -451,10 +451,11 @@ package Stand is
-- universal integer and universal real, it is never used for runtime
-- calculations).
- Standard_Integer_8 : Entity_Id;
- Standard_Integer_16 : Entity_Id;
- Standard_Integer_32 : Entity_Id;
- Standard_Integer_64 : Entity_Id;
+ Standard_Integer_8 : Entity_Id;
+ Standard_Integer_16 : Entity_Id;
+ Standard_Integer_32 : Entity_Id;
+ Standard_Integer_64 : Entity_Id;
+ Standard_Integer_128 : Entity_Id;
-- These are signed integer types with the indicated sizes. Used for the
-- underlying implementation types for fixed-point and enumeration types.
diff --git a/gcc/ada/switch-c.adb b/gcc/ada/switch-c.adb
index e086a5d..c6eb063 100644
--- a/gcc/ada/switch-c.adb
+++ b/gcc/ada/switch-c.adb
@@ -486,6 +486,12 @@ package body Switch.C is
Ptr := Ptr + 1;
Check_Aliasing_Of_Parameters := True;
+ -- -gnateb (config file basenames and checksums in ALI)
+
+ when 'b' =>
+ Ptr := Ptr + 1;
+ Config_Files_Store_Basename := True;
+
-- -gnatec (configuration pragmas)
when 'c' =>
diff --git a/gcc/ada/symbols.adb b/gcc/ada/symbols.adb
deleted file mode 100644
index d8d4992..0000000
--- a/gcc/ada/symbols.adb
+++ /dev/null
@@ -1,90 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y M B O L S --
--- --
--- B o d y --
--- --
--- Copyright (C) 2003-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT 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 distributed with GNAT; see file COPYING3. If not, go to --
--- http://www.gnu.org/licenses for a complete copy of the license. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This is the default version of this package, used when the creation
--- of symbol files is not supported.
-
-with Ada.Text_IO; use Ada.Text_IO;
-
-package body Symbols is
-
- ----------------
- -- Initialize --
- ----------------
-
- procedure Initialize
- (Symbol_File : String;
- Reference : String;
- Symbol_Policy : Policy;
- Quiet : Boolean;
- Version : String;
- Success : out Boolean)
- is
- pragma Unreferenced (Symbol_File);
- pragma Unreferenced (Reference);
- pragma Unreferenced (Symbol_Policy);
- pragma Unreferenced (Quiet);
- pragma Unreferenced (Version);
- begin
- Put_Line
- ("creation of symbol files are not supported on this platform");
- Success := False;
- end Initialize;
-
- ----------------
- -- Processing --
- ----------------
-
- package body Processing is
-
- -------------
- -- Process --
- -------------
-
- procedure Process
- (Object_File : String;
- Success : out Boolean)
- is
- pragma Unreferenced (Object_File);
- begin
- Success := False;
- end Process;
-
- end Processing;
-
- --------------
- -- Finalize --
- --------------
-
- procedure Finalize
- (Quiet : Boolean;
- Success : out Boolean)
- is
- pragma Unreferenced (Quiet);
- begin
- Success := False;
- end Finalize;
-
-end Symbols;
diff --git a/gcc/ada/symbols.ads b/gcc/ada/symbols.ads
deleted file mode 100644
index 0193830..0000000
--- a/gcc/ada/symbols.ads
+++ /dev/null
@@ -1,115 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S Y M B O L S --
--- --
--- S p e c --
--- --
--- Copyright (C) 2003-2020, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT 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 distributed with GNAT; see file COPYING3. If not, go to --
--- http://www.gnu.org/licenses for a complete copy of the license. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- This package allows the creation of symbol files to be used for linking
--- libraries. The format of symbol files depends on the platform, so there is
--- several implementations of the body.
-
-with GNAT.Dynamic_Tables;
-
-with System.OS_Lib; use System.OS_Lib;
-
-package Symbols is
-
- type Policy is
- -- Symbol policy
-
- (Autonomous,
- -- Create a symbol file without considering any reference
-
- Compliant,
- -- Either create a symbol file with the same major and minor IDs if
- -- all symbols are already found in the reference file or with an
- -- incremented minor ID, if not.
-
- Controlled,
- -- Fail if symbols are not the same as those in the reference file
-
- Restricted,
- -- Restrict the symbols to those in the symbol file. Fail if some
- -- symbols in the symbol file are not exported from the object files.
-
- Direct);
- -- The reference symbol file is copied to the symbol file
-
- type Symbol_Kind is (Data, Proc);
- -- To distinguish between the different kinds of symbols
-
- type Symbol_Data is record
- Name : String_Access;
- Kind : Symbol_Kind := Data;
- Present : Boolean := True;
- end record;
- -- Data (name and kind) for each of the symbols
-
- package Symbol_Table is new GNAT.Dynamic_Tables
- (Table_Component_Type => Symbol_Data,
- Table_Index_Type => Natural,
- Table_Low_Bound => 0,
- Table_Initial => 100,
- Table_Increment => 100);
- -- The symbol tables
-
- Original_Symbols : Symbol_Table.Instance;
- -- The symbols, if any, found in the reference symbol table
-
- Complete_Symbols : Symbol_Table.Instance;
- -- The symbols, if any, found in the objects files
-
- procedure Initialize
- (Symbol_File : String;
- Reference : String;
- Symbol_Policy : Policy;
- Quiet : Boolean;
- Version : String;
- Success : out Boolean);
- -- Initialize a symbol file. This procedure must be called before
- -- Processing any object file. Depending on the platforms and the
- -- circumstances, additional messages may be issued if Quiet is False.
-
- package Processing is
-
- -- This package, containing a single visible procedure Process, exists
- -- so that it can be a subunits, for some platforms, the body of package
- -- Symbols is common, while the subunit Processing is not.
-
- procedure Process
- (Object_File : String;
- Success : out Boolean);
- -- Get the symbols from an object file. Success is set to True if the
- -- object file exists and has the expected format.
-
- end Processing;
-
- procedure Finalize
- (Quiet : Boolean;
- Success : out Boolean);
- -- Finalize the symbol file. This procedure should be called after
- -- Initialize (once) and Process (one or more times). If Success is
- -- True, the symbol file is written and closed, ready to be used for
- -- linking the library. Depending on the platforms and the circumstances,
- -- additional messages may be issued if Quiet is False.
-
-end Symbols;
diff --git a/gcc/ada/targparm.adb b/gcc/ada/targparm.adb
index 0be05ae..cbc3f89 100644
--- a/gcc/ada/targparm.adb
+++ b/gcc/ada/targparm.adb
@@ -39,8 +39,7 @@ package body Targparm is
-- The following array defines a tag name for each entry
type Targparm_Tags is
- (AAM, -- AAMP
- ACR, -- Always_Compatible_Rep
+ (ACR, -- Always_Compatible_Rep
ASD, -- Atomic_Sync_Default
BDC, -- Backend_Divide_Checks
BOC, -- Backend_Overflow_Checks
@@ -49,9 +48,7 @@ package body Targparm is
D32, -- Duration_32_Bits
DEN, -- Denorm
EXS, -- Exit_Status_Supported
- FEL, -- Frontend_Layout
FEX, -- Frontend_Exceptions
- FFO, -- Fractional_Fixed_Ops
MOV, -- Machine_Overflows
MRN, -- Machine_Rounds
PAS, -- Preallocated_Stacks
@@ -73,7 +70,6 @@ package body Targparm is
-- The following list of string constants gives the parameter names
- AAM_Str : aliased constant Source_Buffer := "AAMP";
ACR_Str : aliased constant Source_Buffer := "Always_Compatible_Rep";
ASD_Str : aliased constant Source_Buffer := "Atomic_Sync_Default";
BDC_Str : aliased constant Source_Buffer := "Backend_Divide_Checks";
@@ -83,9 +79,7 @@ package body Targparm is
D32_Str : aliased constant Source_Buffer := "Duration_32_Bits";
DEN_Str : aliased constant Source_Buffer := "Denorm";
EXS_Str : aliased constant Source_Buffer := "Exit_Status_Supported";
- FEL_Str : aliased constant Source_Buffer := "Frontend_Layout";
FEX_Str : aliased constant Source_Buffer := "Frontend_Exceptions";
- FFO_Str : aliased constant Source_Buffer := "Fractional_Fixed_Ops";
MOV_Str : aliased constant Source_Buffer := "Machine_Overflows";
MRN_Str : aliased constant Source_Buffer := "Machine_Rounds";
PAS_Str : aliased constant Source_Buffer := "Preallocated_Stacks";
@@ -107,8 +101,7 @@ package body Targparm is
type Buffer_Ptr is access constant Source_Buffer;
Targparm_Str : constant array (Targparm_Tags) of Buffer_Ptr :=
- (AAM => AAM_Str'Access,
- ACR => ACR_Str'Access,
+ (ACR => ACR_Str'Access,
ASD => ASD_Str'Access,
BDC => BDC_Str'Access,
BOC => BOC_Str'Access,
@@ -117,9 +110,7 @@ package body Targparm is
D32 => D32_Str'Access,
DEN => DEN_Str'Access,
EXS => EXS_Str'Access,
- FEL => FEL_Str'Access,
FEX => FEX_Str'Access,
- FFO => FFO_Str'Access,
MOV => MOV_Str'Access,
MRN => MRN_Str'Access,
PAS => PAS_Str'Access,
@@ -803,7 +794,6 @@ package body Targparm is
Result := (System_Text (P) = 'T');
case K is
- when AAM => null;
when ACR => Always_Compatible_Rep_On_Target := Result;
when ASD => Atomic_Sync_Default_On_Target := Result;
when BDC => Backend_Divide_Checks_On_Target := Result;
@@ -813,9 +803,7 @@ package body Targparm is
when D32 => Duration_32_Bits_On_Target := Result;
when DEN => Denorm_On_Target := Result;
when EXS => Exit_Status_Supported_On_Target := Result;
- when FEL => null;
when FEX => Frontend_Exceptions_On_Target := Result;
- when FFO => Fractional_Fixed_Ops_On_Target := Result;
when MOV => Machine_Overflows_On_Target := Result;
when MRN => Machine_Rounds_On_Target := Result;
when PAS => Preallocated_Stacks_On_Target := Result;
diff --git a/gcc/ada/targparm.ads b/gcc/ada/targparm.ads
index 60b2367..5195a39 100644
--- a/gcc/ada/targparm.ads
+++ b/gcc/ada/targparm.ads
@@ -544,16 +544,6 @@ package Targparm is
-- WARNING: There is a matching C declaration of this variable in fe.h
- -------------------------------------------
- -- Boolean-Valued Fixed-Point Attributes --
- -------------------------------------------
-
- Fractional_Fixed_Ops_On_Target : Boolean := False;
- -- Set to True for targets that support fixed-by-fixed multiplication
- -- and division for fixed-point types with a small value equal to
- -- 2 ** (-(T'Object_Size - 1)) and whose values have an absolute
- -- value less than 1.0.
-
-----------------
-- Subprograms --
-----------------
diff --git a/gcc/ada/terminals.c b/gcc/ada/terminals.c
index 81388a7..ec9db3a 100644
--- a/gcc/ada/terminals.c
+++ b/gcc/ada/terminals.c
@@ -1244,7 +1244,7 @@ allocate_pty_desc (pty_desc **desc) {
result->slave_fd = slave_fd;
/* the string returned by ptsname or _getpty is a static allocated string. So
we should make a copy */
- strncpy (result->slave_name, slave_name, sizeof (result->slave_name));
+ strncpy (result->slave_name, slave_name, sizeof (result->slave_name) - 1);
result->slave_name[sizeof (result->slave_name) - 1] = '\0';
result->child_pid = -1;
*desc=result;
diff --git a/gcc/ada/tracebak.c b/gcc/ada/tracebak.c
index d643cfc..23ed8da 100644
--- a/gcc/ada/tracebak.c
+++ b/gcc/ada/tracebak.c
@@ -309,6 +309,13 @@ __gnat_backtrace (void **array,
#define USING_ARM_UNWINDING 1
#endif
+/*---------------------- ARM Linux ------------------------------------ -*/
+#elif (defined (__ARMEL__) && defined (__linux))
+
+#define USE_GCC_UNWINDER
+#define PC_ADJUST -2
+#define USING_ARM_UNWINDING 1
+
/*---------------------- PPC AIX/PPC Lynx 178/Older Darwin --------------*/
#elif ((defined (_POWER) && defined (_AIX)) || \
(defined (__powerpc__) && defined (__Lynx__) && !defined(__ELF__)) || \
diff --git a/gcc/ada/ttypes.ads b/gcc/ada/ttypes.ads
index ebd02b3..46f9698 100644
--- a/gcc/ada/ttypes.ads
+++ b/gcc/ada/ttypes.ads
@@ -26,7 +26,6 @@
-- This package contains constants describing target properties
with Types; use Types;
-with Get_Targ;
with Set_Targ;
package Ttypes is
@@ -102,63 +101,33 @@ package Ttypes is
Standard_Short_Short_Integer_Size : constant Pos :=
Set_Targ.Char_Size;
- Standard_Short_Short_Integer_Width : constant Pos :=
- Get_Targ.Width_From_Size
- (Standard_Short_Short_Integer_Size);
Standard_Short_Integer_Size : constant Pos :=
Set_Targ.Short_Size;
- Standard_Short_Integer_Width : constant Pos :=
- Get_Targ.Width_From_Size
- (Standard_Short_Integer_Size);
Standard_Integer_Size : constant Pos :=
Set_Targ.Int_Size;
- Standard_Integer_Width : constant Pos :=
- Get_Targ.Width_From_Size
- (Standard_Integer_Size);
Standard_Long_Integer_Size : constant Pos :=
Set_Targ.Long_Size;
- Standard_Long_Integer_Width : constant Pos :=
- Get_Targ.Width_From_Size
- (Standard_Long_Integer_Size);
Standard_Long_Long_Integer_Size : constant Pos :=
Set_Targ.Long_Long_Size;
- Standard_Long_Long_Integer_Width : constant Pos :=
- Get_Targ.Width_From_Size
- (Standard_Long_Long_Integer_Size);
Standard_Long_Long_Long_Integer_Size : Pos :=
Set_Targ.Long_Long_Long_Size;
- Standard_Long_Long_Long_Integer_Width : Pos :=
- Get_Targ.Width_From_Size
- (Standard_Long_Long_Long_Integer_Size);
Standard_Short_Float_Size : constant Pos :=
Set_Targ.Float_Size;
- Standard_Short_Float_Digits : constant Pos :=
- Get_Targ.Digits_From_Size
- (Standard_Short_Float_Size);
Standard_Float_Size : constant Pos :=
Set_Targ.Float_Size;
- Standard_Float_Digits : constant Pos :=
- Get_Targ.Digits_From_Size
- (Standard_Float_Size);
Standard_Long_Float_Size : constant Pos :=
Set_Targ.Double_Size;
- Standard_Long_Float_Digits : constant Pos :=
- Get_Targ.Digits_From_Size
- (Standard_Long_Float_Size);
Standard_Long_Long_Float_Size : constant Pos :=
Set_Targ.Long_Double_Size;
- Standard_Long_Long_Float_Digits : constant Pos :=
- Get_Targ.Digits_From_Size
- (Standard_Long_Long_Float_Size);
Standard_Character_Size : constant Pos := Set_Targ.Char_Size;
diff --git a/gcc/ada/uintp.ads b/gcc/ada/uintp.ads
index 648ee31..5f1f759 100644
--- a/gcc/ada/uintp.ads
+++ b/gcc/ada/uintp.ads
@@ -63,6 +63,7 @@ package Uintp is
Uint_15 : constant Uint;
Uint_16 : constant Uint;
Uint_24 : constant Uint;
+ Uint_31 : constant Uint;
Uint_32 : constant Uint;
Uint_63 : constant Uint;
Uint_64 : constant Uint;
@@ -80,9 +81,13 @@ package Uintp is
Uint_Minus_8 : constant Uint;
Uint_Minus_9 : constant Uint;
Uint_Minus_12 : constant Uint;
+ Uint_Minus_18 : constant Uint;
+ Uint_Minus_31 : constant Uint;
Uint_Minus_36 : constant Uint;
Uint_Minus_63 : constant Uint;
+ Uint_Minus_76 : constant Uint;
Uint_Minus_80 : constant Uint;
+ Uint_Minus_127 : constant Uint;
Uint_Minus_128 : constant Uint;
type UI_Vector is array (Pos range <>) of Int;
@@ -281,7 +286,7 @@ package Uintp is
-- or decimal format. Auto, the default setting, lets the routine make a
-- decision based on the value.
- UI_Image_Max : constant := 48; -- Enough for a 128-bit number
+ UI_Image_Max : constant := 1024;
UI_Image_Buffer : String (1 .. UI_Image_Max);
UI_Image_Length : Natural;
-- Buffer used for UI_Image as described below
@@ -470,6 +475,7 @@ private
Uint_15 : constant Uint := Uint (Uint_Direct_Bias + 15);
Uint_16 : constant Uint := Uint (Uint_Direct_Bias + 16);
Uint_24 : constant Uint := Uint (Uint_Direct_Bias + 24);
+ Uint_31 : constant Uint := Uint (Uint_Direct_Bias + 31);
Uint_32 : constant Uint := Uint (Uint_Direct_Bias + 32);
Uint_63 : constant Uint := Uint (Uint_Direct_Bias + 63);
Uint_64 : constant Uint := Uint (Uint_Direct_Bias + 64);
@@ -487,9 +493,13 @@ private
Uint_Minus_8 : constant Uint := Uint (Uint_Direct_Bias - 8);
Uint_Minus_9 : constant Uint := Uint (Uint_Direct_Bias - 9);
Uint_Minus_12 : constant Uint := Uint (Uint_Direct_Bias - 12);
+ Uint_Minus_18 : constant Uint := Uint (Uint_Direct_Bias - 18);
+ Uint_Minus_31 : constant Uint := Uint (Uint_Direct_Bias - 31);
Uint_Minus_36 : constant Uint := Uint (Uint_Direct_Bias - 36);
Uint_Minus_63 : constant Uint := Uint (Uint_Direct_Bias - 63);
+ Uint_Minus_76 : constant Uint := Uint (Uint_Direct_Bias - 76);
Uint_Minus_80 : constant Uint := Uint (Uint_Direct_Bias - 80);
+ Uint_Minus_127 : constant Uint := Uint (Uint_Direct_Bias - 127);
Uint_Minus_128 : constant Uint := Uint (Uint_Direct_Bias - 128);
Uint_Max_Simple_Mul : constant := Uint_Direct_Bias + 2**15;
diff --git a/gcc/ada/urealp.adb b/gcc/ada/urealp.adb
index f45f261..88cb681 100644
--- a/gcc/ada/urealp.adb
+++ b/gcc/ada/urealp.adb
@@ -73,20 +73,28 @@ package body Urealp is
-- The following universal reals are the values returned by the constant
-- functions. They are initialized by the initialization procedure.
- UR_0 : Ureal;
- UR_M_0 : Ureal;
- UR_Tenth : Ureal;
- UR_Half : Ureal;
- UR_1 : Ureal;
- UR_2 : Ureal;
- UR_10 : Ureal;
- UR_10_36 : Ureal;
- UR_M_10_36 : Ureal;
- UR_100 : Ureal;
- UR_2_128 : Ureal;
- UR_2_80 : Ureal;
- UR_2_M_128 : Ureal;
- UR_2_M_80 : Ureal;
+ UR_0 : Ureal;
+ UR_M_0 : Ureal;
+ UR_Tenth : Ureal;
+ UR_Half : Ureal;
+ UR_1 : Ureal;
+ UR_2 : Ureal;
+ UR_10 : Ureal;
+ UR_2_10_18 : Ureal;
+ UR_9_10_36 : Ureal;
+ UR_10_76 : Ureal;
+ UR_M_2_10_18 : Ureal;
+ UR_M_9_10_36 : Ureal;
+ UR_M_10_76 : Ureal;
+ UR_100 : Ureal;
+ UR_2_127 : Ureal;
+ UR_2_128 : Ureal;
+ UR_2_31 : Ureal;
+ UR_2_63 : Ureal;
+ UR_2_80 : Ureal;
+ UR_2_M_127 : Ureal;
+ UR_2_M_128 : Ureal;
+ UR_2_M_80 : Ureal;
Normalized_Real : Ureal := No_Ureal;
-- Used to memoize Norm_Num and Norm_Den, if either of these functions
@@ -288,20 +296,28 @@ package body Urealp is
procedure Initialize is
begin
Ureals.Init;
- UR_0 := UR_From_Components (Uint_0, Uint_1, 0, False);
- UR_M_0 := UR_From_Components (Uint_0, Uint_1, 0, True);
- UR_Half := UR_From_Components (Uint_1, Uint_1, 2, False);
- UR_Tenth := UR_From_Components (Uint_1, Uint_1, 10, False);
- UR_1 := UR_From_Components (Uint_1, Uint_1, 0, False);
- UR_2 := UR_From_Components (Uint_1, Uint_Minus_1, 2, False);
- UR_10 := UR_From_Components (Uint_1, Uint_Minus_1, 10, False);
- UR_10_36 := UR_From_Components (Uint_1, Uint_Minus_36, 10, False);
- UR_M_10_36 := UR_From_Components (Uint_1, Uint_Minus_36, 10, True);
- UR_100 := UR_From_Components (Uint_1, Uint_Minus_2, 10, False);
- UR_2_128 := UR_From_Components (Uint_1, Uint_Minus_128, 2, False);
- UR_2_M_128 := UR_From_Components (Uint_1, Uint_128, 2, False);
- UR_2_80 := UR_From_Components (Uint_1, Uint_Minus_80, 2, False);
- UR_2_M_80 := UR_From_Components (Uint_1, Uint_80, 2, False);
+ UR_0 := UR_From_Components (Uint_0, Uint_1, 0, False);
+ UR_M_0 := UR_From_Components (Uint_0, Uint_1, 0, True);
+ UR_Half := UR_From_Components (Uint_1, Uint_1, 2, False);
+ UR_Tenth := UR_From_Components (Uint_1, Uint_1, 10, False);
+ UR_1 := UR_From_Components (Uint_1, Uint_1, 0, False);
+ UR_2 := UR_From_Components (Uint_1, Uint_Minus_1, 2, False);
+ UR_10 := UR_From_Components (Uint_1, Uint_Minus_1, 10, False);
+ UR_2_10_18 := UR_From_Components (Uint_2, Uint_Minus_18, 10, False);
+ UR_9_10_36 := UR_From_Components (Uint_9, Uint_Minus_36, 10, False);
+ UR_10_76 := UR_From_Components (Uint_1, Uint_Minus_76, 10, False);
+ UR_M_2_10_18 := UR_From_Components (Uint_2, Uint_Minus_18, 10, True);
+ UR_M_9_10_36 := UR_From_Components (Uint_9, Uint_Minus_36, 10, True);
+ UR_M_10_76 := UR_From_Components (Uint_1, Uint_Minus_76, 10, True);
+ UR_100 := UR_From_Components (Uint_1, Uint_Minus_2, 10, False);
+ UR_2_127 := UR_From_Components (Uint_1, Uint_Minus_127, 2, False);
+ UR_2_M_127 := UR_From_Components (Uint_1, Uint_127, 2, False);
+ UR_2_128 := UR_From_Components (Uint_1, Uint_Minus_128, 2, False);
+ UR_2_M_128 := UR_From_Components (Uint_1, Uint_128, 2, False);
+ UR_2_31 := UR_From_Components (Uint_1, Uint_Minus_31, 2, False);
+ UR_2_63 := UR_From_Components (Uint_1, Uint_Minus_63, 2, False);
+ UR_2_80 := UR_From_Components (Uint_1, Uint_Minus_80, 2, False);
+ UR_2_M_80 := UR_From_Components (Uint_1, Uint_80, 2, False);
end Initialize;
----------------
@@ -1408,14 +1424,6 @@ package body Urealp is
UI_Write (Int (UI_Image_Length - 1) - Val.Den, Decimal);
end if;
- -- Constants in a base other than 10 can still be easily written in
- -- normal Ada literal style if the numerator is one.
-
- elsif Val.Rbase /= 0 and then Val.Num = 1 then
- Write_Int (Val.Rbase);
- Write_Str ("#1.0#E");
- UI_Write (-Val.Den);
-
-- Other constants with a base other than 10 are written using one of
-- the following forms, depending on the sign of the number and the
-- sign of the exponent (= minus denominator value). See that we are
@@ -1525,14 +1533,50 @@ package body Urealp is
return UR_100;
end Ureal_100;
+ -------------------
+ -- Ureal_2_10_18 --
+ -------------------
+
+ function Ureal_2_10_18 return Ureal is
+ begin
+ return UR_2_10_18;
+ end Ureal_2_10_18;
+
+ -------------------
+ -- Ureal_9_10_36 --
+ -------------------
+
+ function Ureal_9_10_36 return Ureal is
+ begin
+ return UR_9_10_36;
+ end Ureal_9_10_36;
+
-----------------
- -- Ureal_10_36 --
+ -- Ureal_10_76 --
-----------------
- function Ureal_10_36 return Ureal is
+ function Ureal_10_76 return Ureal is
+ begin
+ return UR_10_76;
+ end Ureal_10_76;
+
+ ----------------
+ -- Ureal_2_31 --
+ ----------------
+
+ function Ureal_2_31 return Ureal is
+ begin
+ return UR_2_31;
+ end Ureal_2_31;
+
+ ----------------
+ -- Ureal_2_63 --
+ ----------------
+
+ function Ureal_2_63 return Ureal is
begin
- return UR_10_36;
- end Ureal_10_36;
+ return UR_2_63;
+ end Ureal_2_63;
----------------
-- Ureal_2_80 --
@@ -1544,6 +1588,15 @@ package body Urealp is
end Ureal_2_80;
-----------------
+ -- Ureal_2_127 --
+ -----------------
+
+ function Ureal_2_127 return Ureal is
+ begin
+ return UR_2_127;
+ end Ureal_2_127;
+
+ -----------------
-- Ureal_2_128 --
-----------------
@@ -1562,6 +1615,15 @@ package body Urealp is
end Ureal_2_M_80;
-------------------
+ -- Ureal_2_M_127 --
+ -------------------
+
+ function Ureal_2_M_127 return Ureal is
+ begin
+ return UR_2_M_127;
+ end Ureal_2_M_127;
+
+ -------------------
-- Ureal_2_M_128 --
-------------------
@@ -1588,14 +1650,32 @@ package body Urealp is
return UR_M_0;
end Ureal_M_0;
+ ---------------------
+ -- Ureal_M_2_10_18 --
+ ---------------------
+
+ function Ureal_M_2_10_18 return Ureal is
+ begin
+ return UR_M_2_10_18;
+ end Ureal_M_2_10_18;
+
+ ---------------------
+ -- Ureal_M_9_10_36 --
+ ---------------------
+
+ function Ureal_M_9_10_36 return Ureal is
+ begin
+ return UR_M_9_10_36;
+ end Ureal_M_9_10_36;
+
-------------------
- -- Ureal_M_10_36 --
+ -- Ureal_M_10_76 --
-------------------
- function Ureal_M_10_36 return Ureal is
+ function Ureal_M_10_76 return Ureal is
begin
- return UR_M_10_36;
- end Ureal_M_10_36;
+ return UR_M_10_76;
+ end Ureal_M_10_76;
-----------------
-- Ureal_Tenth --
diff --git a/gcc/ada/urealp.ads b/gcc/ada/urealp.ads
index 5c511ef..3f74735 100644
--- a/gcc/ada/urealp.ads
+++ b/gcc/ada/urealp.ads
@@ -106,23 +106,47 @@ package Urealp is
function Ureal_100 return Ureal;
-- Returns value 100.0
+ function Ureal_2_31 return Ureal;
+ -- Returns value 2.0 ** 31
+
+ function Ureal_2_63 return Ureal;
+ -- Returns value 2.0 ** 63
+
function Ureal_2_80 return Ureal;
-- Returns value 2.0 ** 80
function Ureal_2_M_80 return Ureal;
-- Returns value 2.0 ** (-80)
+ function Ureal_2_127 return Ureal;
+ -- Returns value 2.0 ** 127
+
+ function Ureal_2_M_127 return Ureal;
+ -- Returns value 2.0 ** (-127)
+
function Ureal_2_128 return Ureal;
-- Returns value 2.0 ** 128
function Ureal_2_M_128 return Ureal;
-- Returns value 2.0 ** (-128)
- function Ureal_10_36 return Ureal;
- -- Returns value 10.0 ** 36
+ function Ureal_2_10_18 return Ureal;
+ -- Returns value 2.0 * 10.0 ** 18
+
+ function Ureal_M_2_10_18 return Ureal;
+ -- Returns value -2.0 * 10.0 ** 18
+
+ function Ureal_9_10_36 return Ureal;
+ -- Returns value 9.0 * 10.0 ** 36
+
+ function Ureal_M_9_10_36 return Ureal;
+ -- Returns value -9.0 * 10.0 ** 36
+
+ function Ureal_10_76 return Ureal;
+ -- Returns value 10.0 ** 76
- function Ureal_M_10_36 return Ureal;
- -- Returns value -10.0 ** 36
+ function Ureal_M_10_76 return Ureal;
+ -- Returns value -10.0 ** 76
-----------------
-- Subprograms --
diff --git a/gcc/ada/validsw.adb b/gcc/ada/validsw.adb
index dd3b6a0..2f8d769 100644
--- a/gcc/ada/validsw.adb
+++ b/gcc/ada/validsw.adb
@@ -47,56 +47,6 @@ package body Validsw is
Validity_Check_Tests := False;
end Reset_Validity_Check_Options;
- ---------------------------------
- -- Save_Validity_Check_Options --
- ---------------------------------
-
- procedure Save_Validity_Check_Options
- (Options : out Validity_Check_Options)
- is
- P : Natural := 0;
-
- procedure Add (C : Character; S : Boolean);
- -- Add given character C to string if switch S is true
-
- procedure Add (C : Character; S : Boolean) is
- begin
- if S then
- P := P + 1;
- Options (P) := C;
- end if;
- end Add;
-
- -- Start of processing for Save_Validity_Check_Options
-
- begin
- for K in Options'Range loop
- Options (K) := ' ';
- end loop;
-
- Add ('e', Validity_Check_Components);
- Add ('c', Validity_Check_Copies);
- Add ('d', Validity_Check_Default);
- Add ('f', Validity_Check_Floating_Point);
- Add ('i', Validity_Check_In_Params);
- Add ('m', Validity_Check_In_Out_Params);
- Add ('o', Validity_Check_Operands);
- Add ('p', Validity_Check_Parameters);
- Add ('r', Validity_Check_Returns);
- Add ('s', Validity_Check_Subscripts);
- Add ('t', Validity_Check_Tests);
- end Save_Validity_Check_Options;
-
- ----------------------------------------
- -- Set_Default_Validity_Check_Options --
- ----------------------------------------
-
- procedure Set_Default_Validity_Check_Options is
- begin
- Reset_Validity_Check_Options;
- Set_Validity_Check_Options ("d");
- end Set_Default_Validity_Check_Options;
-
--------------------------------
-- Set_Validity_Check_Options --
--------------------------------
diff --git a/gcc/ada/validsw.ads b/gcc/ada/validsw.ads
index 4b2e4b7..6af95d4 100644
--- a/gcc/ada/validsw.ads
+++ b/gcc/ada/validsw.ads
@@ -126,10 +126,6 @@ package Validsw is
-- Subprograms --
-----------------
- procedure Set_Default_Validity_Check_Options;
- -- This procedure is called to set the default validity checking options
- -- that apply if no Validity_Check switches or pragma is given.
-
procedure Set_Validity_Check_Options
(Options : String;
OK : out Boolean;
@@ -146,8 +142,7 @@ package Validsw is
procedure Set_Validity_Check_Options (Options : String);
-- Like the above procedure, except that the call is simply ignored if
-- there are any error conditions, this is for example appropriate for
- -- calls where the string is known to be valid, e.g. because it was
- -- obtained by Save_Validity_Check_Options.
+ -- calls where the string is known to be valid.
procedure Reset_Validity_Check_Options;
-- Sets all validity check options to off
@@ -155,10 +150,4 @@ package Validsw is
subtype Validity_Check_Options is String (1 .. 16);
-- Long enough string to hold all options from Save call below
- procedure Save_Validity_Check_Options
- (Options : out Validity_Check_Options);
- -- Sets Options to represent current selection of options. This
- -- set can be restored by first calling Reset_Validity_Check_Options,
- -- and then calling Set_Validity_Check_Options with the Options string.
-
end Validsw;
diff --git a/gcc/ada/vxworks7-cert-rtp-link.spec b/gcc/ada/vxworks7-cert-rtp-link.spec
new file mode 100644
index 0000000..0e0440f
--- /dev/null
+++ b/gcc/ada/vxworks7-cert-rtp-link.spec
@@ -0,0 +1,9 @@
+*self_spec:
++ %{!nostdlib:-nodefaultlibs -nostartfiles}
+
+*link:
++ %{!nostdlib:%{mrtp:%{!shared: \
+ -l:certRtp.o \
+ -L%:getenv(VSB_DIR /usr/lib/common/objcert) \
+ -T%:getenv(VSB_DIR /usr/ldscripts/rtp.ld) \
+ }}}
diff --git a/gcc/ada/xsnamest.adb b/gcc/ada/xsnamest.adb
index 834d3c4..941e2e8 100644
--- a/gcc/ada/xsnamest.adb
+++ b/gcc/ada/xsnamest.adb
@@ -260,11 +260,14 @@ begin
Replace (M, Translate (A, Xlate_U_Und));
Translate (Name0, Lower_Case_Map);
- elsif not Match (Name0, "Op_", "") then
- Translate (Name0, Lower_Case_Map);
+ elsif Match (Name0, "UP_", "") then
+ Translate (Name0, Upper_Case_Map);
- else
+ elsif Match (Name0, "Op_", "") then
Name0 := 'O' & Translate (Name0, Lower_Case_Map);
+
+ else
+ Translate (Name0, Lower_Case_Map);
end if;
if not Match (Name0, Chk_Low) then
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index a8e277c..971ed47 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,232 @@
+2020-11-30 David Malcolm <dmalcolm@redhat.com>
+
+ * analyzer-pass.cc: Include "analyzer/analyzer.h" for the
+ declaration of sorry_no_analyzer; include "tree.h" and
+ "function.h" as these are needed by it.
+
+2020-11-30 David Malcolm <dmalcolm@redhat.com>
+
+ * analyzer-pass.cc (pass_analyzer::execute): Move sorry call to...
+ (sorry_no_analyzer): New.
+ * analyzer.h (class state_machine): New forward decl.
+ (class logger): New forward decl.
+ (class plugin_analyzer_init_iface): New.
+ (sorry_no_analyzer): New decl.
+ * checker-path.cc (checker_path::fixup_locations): New.
+ * checker-path.h (checker_event::set_location): New.
+ (checker_path::fixup_locations): New decl.
+ * diagnostic-manager.cc
+ (diagnostic_manager::emit_saved_diagnostic): Call
+ checker_path::fixup_locations, and call fixup_location
+ on the primary location.
+ * engine.cc: Include "plugin.h".
+ (class plugin_analyzer_init_impl): New.
+ (impl_run_checkers): Invoke PLUGIN_ANALYZER_INIT callbacks.
+ * pending-diagnostic.h (pending_diagnostic::fixup_location): New
+ vfunc.
+
+2020-11-18 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97893
+ * sm-malloc.cc (null_deref::emit): Use CWE-476 rather than
+ CWE-690, as this isn't due to an unchecked return value.
+ (null_arg::emit): Likewise.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ * checker-path.h (checker_event::get_id_ptr): New.
+ * diagnostic-manager.cc (path_builder::path_builder): Add "sd"
+ param and use it to initialize new field "m_sd".
+ (path_builder::get_pending_diagnostic): New.
+ (path_builder::m_sd): New field.
+ (diagnostic_manager::emit_saved_diagnostic): Pass sd to
+ path_builder ctor.
+ (diagnostic_manager::add_events_for_superedge): Call new
+ maybe_add_custom_events_for_superedge vfunc.
+ * engine.cc (stale_jmp_buf::stale_jmp_buf): Add "setjmp_point"
+ param and use it to initialize new field "m_setjmp_point".
+ Initialize new field "m_stack_pop_event".
+ (stale_jmp_buf::maybe_add_custom_events_for_superedge): New vfunc
+ implementation.
+ (stale_jmp_buf::describe_final_event): New vfunc implementation.
+ (stale_jmp_buf::m_setjmp_point): New field.
+ (stale_jmp_buf::m_stack_pop_event): New field.
+ (exploded_node::on_longjmp): Pass setjmp_point to stale_jmp_buf
+ ctor.
+ * pending-diagnostic.h
+ (pending_diagnostic::maybe_add_custom_events_for_superedge): New
+ vfunc.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/97424
+ * analyzer.opt (Wanalyzer-shift-count-negative): New.
+ (Wanalyzer-shift-count-overflow): New.
+ * region-model.cc (class shift_count_negative_diagnostic): New.
+ (class shift_count_overflow_diagnostic): New.
+ (region_model::get_gassign_result): Complain about shift counts that
+ are negative or are >= the operand's type's width.
+
+2020-11-10 Martin Liska <mliska@suse.cz>
+
+ * constraint-manager.cc (constraint_manager::merge): Remove
+ unused code.
+ * constraint-manager.h: Likewise.
+ * program-state.cc (sm_state_map::sm_state_map): Likewise.
+ (program_state::program_state): Likewise.
+ (test_sm_state_map): Likewise.
+ * program-state.h: Likewise.
+ * region-model-reachability.cc (reachable_regions::reachable_regions): Likewise.
+ * region-model-reachability.h: Likewise.
+ * region-model.cc (region_model::handle_unrecognized_call): Likewise.
+ (region_model::get_reachable_svalues): Likewise.
+ (region_model::can_merge_with_p): Likewise.
+
+2020-11-05 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97668
+ * svalue.cc (cmp_cst): Handle COMPLEX_CST.
+
+2020-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * program-state.cc (sm_state_map::on_liveness_change): Sort the
+ leaking svalues before calling on_state_leak.
+ (program_state::detect_leaks): Likewise when calling
+ on_svalue_leak.
+ * region-model-reachability.cc
+ (reachable_regions::mark_escaped_clusters): Likewise when
+ calling on_escaped_function.
+
+2020-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97608
+ * region-model-reachability.cc (reachable_regions::handle_sval):
+ Operands of reachable reversible operations are reachable.
+
+2020-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * analyzer.h (class state_machine): New forward decl.
+ (class logger): Likewise.
+ (class visitor): Likewise.
+ * complexity.cc: New file, taken from svalue.cc.
+ * complexity.h: New file, taken from region-model.h.
+ * region-model.h: Include "analyzer/svalue.h" and
+ "analyzer/region.h". Move struct complexity to complexity.h.
+ Move svalue, its subclasses and supporting decls to svalue.h.
+ Move region, its subclasses and supporting decls to region.h.
+ * region.cc: Include "analyzer/region.h".
+ (symbolic_region::symbolic_region): Move here from region-model.h.
+ * region.h: New file, based on material from region-model.h.
+ * svalue.cc: Include "analyzer/svalue.h".
+ (complexity::complexity): Move to complexity.cc.
+ (complexity::from_pair): Likewise.
+ * svalue.h: New file, based on material from region-model.h.
+
+2020-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * program-state.cc (sm_state_map::print): Guard the printing of
+ the origin pointer with !flag_dump_noaddr.
+ * region.cc (string_region::dump_to_pp): Likewise for
+ m_string_cst.
+
+2020-10-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97568
+ * region-model.cc (region_model::get_initial_value_for_global):
+ Move check that !DECL_EXTERNAL from here to...
+ * region.cc (decl_region::get_svalue_for_initializer): ...here,
+ using it to reject zero initialization.
+
+2020-10-27 Markus Böck <markus.boeck02@gmail.com>
+
+ PR analyzer/96608
+ * store.h (hash): Cast to intptr_t instead of long
+
+2020-10-27 David Malcolm <dmalcolm@redhat.com>
+
+ * constraint-manager.cc (svalue_cmp_by_ptr): Delete.
+ (equiv_class::canonicalize): Use svalue::cmp_ptr_ptr instead.
+ (equiv_class_cmp): Eliminate pointer comparison.
+ * diagnostic-manager.cc (dedupe_key::comparator): If they are at
+ the same location, also compare epath ength and pending_diagnostic
+ kind.
+ * engine.cc (readability_comparator): If two path_vars have the
+ same readability, then impose an arbitrary ordering on them.
+ (worklist::key_t::cmp): If two points have the same plan ordering,
+ continue the comparison. Call sm_state_map::cmp rather than
+ comparing hash values.
+ * program-state.cc (sm_state_map::entry_t::cmp): New.
+ (sm_state_map::cmp): New.
+ * program-state.h (sm_state_map::entry_t::cmp): New decl.
+ (sm_state_map::elements): New.
+ (sm_state_map::cmp): New.
+
+2020-10-27 David Malcolm <dmalcolm@redhat.com>
+
+ * engine.cc (setjmp_record::cmp): New.
+ (supernode_cluster::dump_dot): Avoid embedding pointer in cluster
+ name.
+ (supernode_cluster::cmp_ptr_ptr): New.
+ (function_call_string_cluster::dump_dot): Avoid embedding pointer
+ in cluster name. Sort m_map when dumping child clusters.
+ (function_call_string_cluster::cmp_ptr_ptr): New.
+ (root_cluster::dump_dot): Sort m_map when dumping child clusters.
+ * program-point.cc (function_point::cmp): New.
+ (function_point::cmp_ptr): New.
+ * program-point.h (function_point::cmp): New decl.
+ (function_point::cmp_ptr): New decl.
+ * program-state.cc (sm_state_map::print): Sort the values. Guard
+ the printing of pointers with !flag_dump_noaddr.
+ (program_state::prune_for_point): Sort the regions.
+ (log_set_of_svalues): Sort the values. Guard the printing of
+ pointers with !flag_dump_noaddr.
+ * region-model-manager.cc (log_uniq_map): Sort the values.
+ * region-model-reachability.cc (dump_set): New function template.
+ (reachable_regions::dump_to_pp): Use it.
+ * region-model.h (svalue::cmp_ptr): New decl.
+ (svalue::cmp_ptr_ptr): New decl.
+ (setjmp_record::cmp): New decl.
+ (placeholder_svalue::get_name): New accessor.
+ (widening_svalue::get_point): New accessor.
+ (compound_svalue::get_map): New accessor.
+ (conjured_svalue::get_stmt): New accessor.
+ (conjured_svalue::get_id_region): New accessor.
+ (region::cmp_ptrs): Rename to...
+ (region::cmp_ptr_ptr): ...this.
+ * region.cc (region::cmp_ptrs): Rename to...
+ (region::cmp_ptr_ptr): ...this.
+ * state-purge.cc
+ (state_purge_per_ssa_name::state_purge_per_ssa_name): Sort
+ m_points_needing_name when dumping.
+ * store.cc (concrete_binding::cmp_ptr_ptr): New.
+ (symbolic_binding::cmp_ptr_ptr): New.
+ (binding_map::cmp): New.
+ (get_sorted_parent_regions): Update for renaming of
+ region::cmp_ptrs to region::cmp_ptr_ptr.
+ (store::dump_to_pp): Likewise.
+ (store::to_json): Likewise.
+ (store::can_merge_p): Sort the base regions before considering
+ them.
+ * store.h (concrete_binding::cmp_ptr_ptr): New decl.
+ (symbolic_binding::cmp_ptr_ptr): New decl.
+ (binding_map::cmp): New decl.
+ * supergraph.cc (supergraph::supergraph): Assign UIDs to the
+ gimple stmts.
+ * svalue.cc (cmp_cst): New.
+ (svalue::cmp_ptr): New.
+ (svalue::cmp_ptr_ptr): New.
+
+2020-10-27 David Malcolm <dmalcolm@redhat.com>
+
+ * engine.cc (exploded_graph::get_or_create_node): Fix off-by-one
+ when imposing param_analyzer_max_enodes_per_program_point limit.
+
+2020-10-27 David Malcolm <dmalcolm@redhat.com>
+
+ * region-model.cc (region_model::get_representative_path_var):
+ Implement case RK_LABEL.
+ * region-model.h (label_region::get_label): New accessor.
+
2020-10-22 David Malcolm <dmalcolm@redhat.com>
PR analyzer/97514
diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc
index a27421e..333f87b 100644
--- a/gcc/analyzer/analyzer-pass.cc
+++ b/gcc/analyzer/analyzer-pass.cc
@@ -25,6 +25,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "diagnostic.h"
#include "options.h"
+#include "tree.h"
+#include "function.h"
+#include "analyzer/analyzer.h"
#include "analyzer/engine.h"
namespace {
@@ -83,9 +86,7 @@ pass_analyzer::execute (function *)
#if ENABLE_ANALYZER
ana::run_checkers ();
#else
- sorry ("%qs was not enabled in this build of GCC"
- " (missing configure-time option %qs)",
- "-fanalyzer", "--enable-analyzer");
+ sorry_no_analyzer ();
#endif
return 0;
@@ -100,3 +101,17 @@ make_pass_analyzer (gcc::context *ctxt)
{
return new pass_analyzer (ctxt);
}
+
+#if !ENABLE_ANALYZER
+
+/* Issue a "sorry" diagnostic that the analyzer was not enabled. */
+
+void
+sorry_no_analyzer ()
+{
+ sorry ("%qs was not enabled in this build of GCC"
+ " (missing configure-time option %qs)",
+ "-fanalyzer", "--enable-analyzer");
+}
+
+#endif /* #if !ENABLE_ANALYZER */
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index aa43b7f..cd46bfc 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -97,6 +97,9 @@ class state_change;
class rewind_info_t;
class engine;
+class state_machine;
+class logger;
+class visitor;
/* Forward decls of functions. */
@@ -186,6 +189,15 @@ private:
extern location_t get_stmt_location (const gimple *stmt, function *fun);
+/* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks. */
+
+class plugin_analyzer_init_iface
+{
+public:
+ virtual void register_state_machine (state_machine *) = 0;
+ virtual logger *get_logger () const = 0;
+};
+
} // namespace ana
extern bool is_special_named_call_p (const gcall *call, const char *funcname,
@@ -306,4 +318,8 @@ private:
#pragma GCC diagnostic ignored "-Wformat-diag"
#endif
+#if !ENABLE_ANALYZER
+extern void sorry_no_analyzer ();
+#endif /* #if !ENABLE_ANALYZER */
+
#endif /* GCC_ANALYZER_ANALYZER_H */
diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index c9df6dc..bbf9e42 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -98,6 +98,14 @@ Wanalyzer-null-dereference
Common Var(warn_analyzer_null_dereference) Init(1) Warning
Warn about code paths in which a NULL pointer is dereferenced.
+Wanalyzer-shift-count-negative
+Common Var(warn_analyzer_shift_count_negative) Init(1) Warning
+Warn about code paths in which a shift with negative count is attempted.
+
+Wanalyzer-shift-count-overflow
+Common Var(warn_analyzer_shift_count_overflow) Init(1) Warning
+Warn about code paths in which a shift with count >= width of type is attempted.
+
Wanalyzer-stale-setjmp-buffer
Common Var(warn_analyzer_stale_setjmp_buffer) Init(1) Warning
Warn about code paths in which a longjmp rewinds to a jmp_buf saved in a stack frame that has returned.
diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc
index 1f6d6a8..062730c 100644
--- a/gcc/analyzer/checker-path.cc
+++ b/gcc/analyzer/checker-path.cc
@@ -982,6 +982,15 @@ checker_path::add_final_event (const state_machine *sm,
add_event (end_of_path);
}
+void
+checker_path::fixup_locations (pending_diagnostic *pd)
+{
+ checker_event *e;
+ int i;
+ FOR_EACH_VEC_ELT (m_events, i, e)
+ e->set_location (pd->fixup_location (e->get_location ()));
+}
+
} // namespace ana
#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 7b86d48..79553ba 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -97,8 +97,16 @@ public:
virtual bool is_function_entry_p () const { return false; }
virtual bool is_return_p () const { return false; }
+ /* For use with %@. */
+ const diagnostic_event_id_t *get_id_ptr () const
+ {
+ return &m_emission_id;
+ }
+
void dump (pretty_printer *pp) const;
+ void set_location (location_t loc) { m_loc = loc; }
+
public:
const enum event_kind m_kind;
protected:
@@ -498,6 +506,8 @@ public:
e->prepare_for_emission (this, pd, diagnostic_event_id_t (i));
}
+ void fixup_locations (pending_diagnostic *pd);
+
void record_setjmp_event (const exploded_node *enode,
diagnostic_event_id_t setjmp_emission_id)
{
diff --git a/gcc/analyzer/complexity.cc b/gcc/analyzer/complexity.cc
new file mode 100644
index 0000000..221f3a6
--- /dev/null
+++ b/gcc/analyzer/complexity.cc
@@ -0,0 +1,95 @@
+/* Measuring the complexity of svalues/regions.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "diagnostic-core.h"
+#include "gimple-pretty-print.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "diagnostic-core.h"
+#include "graphviz.h"
+#include "options.h"
+#include "cgraph.h"
+#include "tree-dfa.h"
+#include "stringpool.h"
+#include "convert.h"
+#include "target.h"
+#include "fold-const.h"
+#include "tree-pretty-print.h"
+#include "tristate.h"
+#include "bitmap.h"
+#include "selftest.h"
+#include "function.h"
+#include "json.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/analyzer-logging.h"
+#include "options.h"
+#include "cgraph.h"
+#include "cfg.h"
+#include "digraph.h"
+#include "analyzer/call-string.h"
+#include "analyzer/program-point.h"
+#include "analyzer/store.h"
+#include "analyzer/complexity.h"
+#include "analyzer/svalue.h"
+#include "analyzer/region.h"
+
+#if ENABLE_ANALYZER
+
+namespace ana {
+
+/* struct complexity. */
+
+/* Get complexity for a new node that references REG
+ (the complexity of REG, plus one for the new node). */
+
+complexity::complexity (const region *reg)
+: m_num_nodes (reg->get_complexity ().m_num_nodes + 1),
+ m_max_depth (reg->get_complexity ().m_max_depth + 1)
+{
+}
+
+/* Get complexity for a new node that references SVAL.
+ (the complexity of SVAL, plus one for the new node). */
+
+complexity::complexity (const svalue *sval)
+: m_num_nodes (sval->get_complexity ().m_num_nodes + 1),
+ m_max_depth (sval->get_complexity ().m_max_depth + 1)
+{
+}
+
+/* Get complexity for a new node that references nodes with complexity
+ C1 and C2. */
+
+complexity
+complexity::from_pair (const complexity &c1, const complexity &c2)
+{
+ return complexity (c1.m_num_nodes + c2.m_num_nodes + 1,
+ MAX (c1.m_max_depth, c2.m_max_depth) + 1);
+}
+
+} // namespace ana
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/complexity.h b/gcc/analyzer/complexity.h
new file mode 100644
index 0000000..e15967f
--- /dev/null
+++ b/gcc/analyzer/complexity.h
@@ -0,0 +1,51 @@
+/* Measuring the complexity of svalues/regions.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_ANALYZER_COMPLEXITY_H
+#define GCC_ANALYZER_COMPLEXITY_H
+
+namespace ana {
+
+/* A measurement of the complexity of an svalue or region, so that
+ we can impose bounds on the growth of these tree-like structures
+ and thus avoid infinite chains of analysis. */
+
+struct complexity
+{
+ complexity (unsigned num_nodes, unsigned max_depth)
+ : m_num_nodes (num_nodes), m_max_depth (max_depth)
+ {}
+
+ complexity (const region *reg);
+ complexity (const svalue *sval);
+ static complexity from_pair (const complexity &c1, const complexity &c);
+
+ /* The total number of svalues and regions in the tree of this
+ entity, including the entity itself. */
+ unsigned m_num_nodes;
+
+ /* The maximum depth of the tree of this entity, including the
+ entity itself. */
+ unsigned m_max_depth;
+};
+
+} // namespace ana
+
+#endif /* GCC_ANALYZER_COMPLEXITY_H */
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 603b228..590bf32 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -423,26 +423,12 @@ equiv_class::get_representative () const
return m_vars[0];
}
-/* Comparator for use by equiv_class::canonicalize. */
-
-static int
-svalue_cmp_by_ptr (const void *p1, const void *p2)
-{
- const svalue *sval1 = *(const svalue * const *)p1;
- const svalue *sval2 = *(const svalue * const *)p2;
- if (sval1 < sval2)
- return 1;
- if (sval1 > sval2)
- return -1;
- return 0;
-}
-
/* Sort the svalues within this equiv_class. */
void
equiv_class::canonicalize ()
{
- m_vars.qsort (svalue_cmp_by_ptr);
+ m_vars.qsort (svalue::cmp_ptr_ptr);
}
/* Get a debug string for C_OP. */
@@ -1693,11 +1679,7 @@ equiv_class_cmp (const void *p1, const void *p2)
gcc_assert (rep1);
gcc_assert (rep2);
- if (rep1 < rep2)
- return 1;
- if (rep1 > rep2)
- return -1;
- return 0;
+ return svalue::cmp_ptr (rep1, rep2);
}
/* Comparator for use by constraint_manager::canonicalize.
@@ -1808,9 +1790,8 @@ class merger_fact_visitor : public fact_visitor
{
public:
merger_fact_visitor (const constraint_manager *cm_b,
- constraint_manager *out,
- const model_merger &merger)
- : m_cm_b (cm_b), m_out (out), m_merger (merger)
+ constraint_manager *out)
+ : m_cm_b (cm_b), m_out (out)
{}
void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs)
@@ -1844,7 +1825,6 @@ public:
private:
const constraint_manager *m_cm_b;
constraint_manager *m_out;
- const model_merger &m_merger;
};
/* Use MERGER to merge CM_A and CM_B into *OUT.
@@ -1856,14 +1836,13 @@ private:
void
constraint_manager::merge (const constraint_manager &cm_a,
const constraint_manager &cm_b,
- constraint_manager *out,
- const model_merger &merger)
+ constraint_manager *out)
{
/* Merge the equivalence classes and constraints.
The easiest way to do this seems to be to enumerate all of the facts
in cm_a, see which are also true in cm_b,
and add those to *OUT. */
- merger_fact_visitor v (&cm_b, out, merger);
+ merger_fact_visitor v (&cm_b, out);
cm_a.for_each_fact (&v);
}
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index 98960ff..1142b1f 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -274,8 +274,7 @@ public:
static void merge (const constraint_manager &cm_a,
const constraint_manager &cm_b,
- constraint_manager *out,
- const model_merger &merger);
+ constraint_manager *out);
void for_each_fact (fact_visitor *) const;
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index cb95a95..9739ca6 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -161,15 +161,22 @@ class path_builder
public:
path_builder (const exploded_graph &eg,
const exploded_path &epath,
- const feasibility_problem *problem)
+ const feasibility_problem *problem,
+ const saved_diagnostic &sd)
: m_eg (eg),
m_diag_enode (epath.get_final_enode ()),
+ m_sd (sd),
m_reachability (eg, m_diag_enode),
m_feasibility_problem (problem)
{}
const exploded_node *get_diag_node () const { return m_diag_enode; }
+ pending_diagnostic *get_pending_diagnostic () const
+ {
+ return m_sd.m_d;
+ }
+
bool reachable_from_p (const exploded_node *src_enode) const
{
return m_reachability.reachable_from_p (src_enode);
@@ -190,6 +197,8 @@ private:
/* The enode where the diagnostic occurs. */
const exploded_node *m_diag_enode;
+ const saved_diagnostic &m_sd;
+
/* Precompute all enodes from which the diagnostic is reachable. */
enode_reachability m_reachability;
@@ -318,7 +327,15 @@ public:
location_t loc1 = pk1->get_location ();
location_t loc2 = pk2->get_location ();
- return linemap_compare_locations (line_table, loc2, loc1);
+ if (int cmp = linemap_compare_locations (line_table, loc2, loc1))
+ return cmp;
+ if (int cmp = ((int)pk1->m_sd.get_epath_length ()
+ - (int)pk2->m_sd.get_epath_length ()))
+ return cmp;
+ if (int cmp = strcmp (pk1->m_sd.m_d->get_kind (),
+ pk2->m_sd.m_d->get_kind ()))
+ return cmp;
+ return 0;
}
const saved_diagnostic &m_sd;
@@ -621,7 +638,7 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
pretty_printer *pp = global_dc->printer->clone ();
/* Precompute all enodes from which the diagnostic is reachable. */
- path_builder pb (eg, epath, sd.get_feasibility_problem ());
+ path_builder pb (eg, epath, sd.get_feasibility_problem (), sd);
/* This is the diagnostic_path subclass that will be built for
the diagnostic. */
@@ -648,7 +665,14 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
emission_path.prepare_for_emission (sd.m_d);
- gcc_rich_location rich_loc (get_stmt_location (stmt, sd.m_snode->m_fun));
+ location_t loc = get_stmt_location (stmt, sd.m_snode->m_fun);
+
+ /* Allow the pending_diagnostic to fix up the primary location
+ and any locations for events. */
+ loc = sd.m_d->fixup_location (loc);
+ emission_path.fixup_locations (sd.m_d);
+
+ gcc_rich_location rich_loc (loc);
rich_loc.set_path (&emission_path);
auto_diagnostic_group d;
@@ -1167,6 +1191,11 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb,
{
gcc_assert (eedge.m_sedge);
+ /* Give diagnostics an opportunity to override this function. */
+ pending_diagnostic *pd = pb.get_pending_diagnostic ();
+ if (pd->maybe_add_custom_events_for_superedge (eedge, emission_path))
+ return;
+
/* Don't add events for insignificant edges at verbosity levels below 3. */
if (m_verbosity < 3)
if (!significant_edge_p (pb, eedge))
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index d4c654a..d022b3a 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/state-purge.h"
#include "analyzer/bar-chart.h"
#include <zlib.h>
+#include "plugin.h"
/* For an overview, see gcc/doc/analyzer.texi. */
@@ -149,6 +150,17 @@ impl_region_model_context::on_escaped_function (tree fndecl)
m_eg->on_escaped_function (fndecl);
}
+/* struct setjmp_record. */
+
+int
+setjmp_record::cmp (const setjmp_record &rec1, const setjmp_record &rec2)
+{
+ if (int cmp_enode = rec1.m_enode->m_index - rec2.m_enode->m_index)
+ return cmp_enode;
+ gcc_assert (&rec1 == &rec2);
+ return 0;
+}
+
/* class setjmp_svalue : public svalue. */
/* Implementation of svalue::accept vfunc for setjmp_svalue. */
@@ -506,6 +518,29 @@ readability_comparator (const void *p1, const void *p2)
if (int cmp = pv2.m_stack_depth - pv1.m_stack_depth)
return cmp;
+ /* Otherwise, if they have the same readability, then impose an
+ arbitrary deterministic ordering on them. */
+
+ if (int cmp = TREE_CODE (pv1.m_tree) - TREE_CODE (pv2.m_tree))
+ return cmp;
+
+ switch (TREE_CODE (pv1.m_tree))
+ {
+ default:
+ break;
+ case SSA_NAME:
+ if (int cmp = (SSA_NAME_VERSION (pv1.m_tree)
+ - SSA_NAME_VERSION (pv2.m_tree)))
+ return cmp;
+ break;
+ case PARM_DECL:
+ case VAR_DECL:
+ case RESULT_DECL:
+ if (int cmp = DECL_UID (pv1.m_tree) - DECL_UID (pv2.m_tree))
+ return cmp;
+ break;
+ }
+
/* TODO: We ought to find ways of sorting such cases. */
return 0;
}
@@ -1243,8 +1278,10 @@ valid_longjmp_stack_p (const program_point &longjmp_point,
class stale_jmp_buf : public pending_diagnostic_subclass<dump_path_diagnostic>
{
public:
- stale_jmp_buf (const gcall *setjmp_call, const gcall *longjmp_call)
- : m_setjmp_call (setjmp_call), m_longjmp_call (longjmp_call)
+ stale_jmp_buf (const gcall *setjmp_call, const gcall *longjmp_call,
+ const program_point &setjmp_point)
+ : m_setjmp_call (setjmp_call), m_longjmp_call (longjmp_call),
+ m_setjmp_point (setjmp_point), m_stack_pop_event (NULL)
{}
bool emit (rich_location *richloc) FINAL OVERRIDE
@@ -1265,9 +1302,56 @@ public:
&& m_longjmp_call == other.m_longjmp_call);
}
+ bool
+ maybe_add_custom_events_for_superedge (const exploded_edge &eedge,
+ checker_path *emission_path)
+ FINAL OVERRIDE
+ {
+ /* Detect exactly when the stack first becomes invalid,
+ and issue an event then. */
+ if (m_stack_pop_event)
+ return false;
+ const exploded_node *src_node = eedge.m_src;
+ const program_point &src_point = src_node->get_point ();
+ const exploded_node *dst_node = eedge.m_dest;
+ const program_point &dst_point = dst_node->get_point ();
+ if (valid_longjmp_stack_p (src_point, m_setjmp_point)
+ && !valid_longjmp_stack_p (dst_point, m_setjmp_point))
+ {
+ /* Compare with diagnostic_manager::add_events_for_superedge. */
+ const int src_stack_depth = src_point.get_stack_depth ();
+ m_stack_pop_event = new custom_event
+ (src_point.get_location (),
+ src_point.get_fndecl (),
+ src_stack_depth,
+ "stack frame is popped here, invalidating saved environment");
+ emission_path->add_event (m_stack_pop_event);
+ return false;
+ }
+ return false;
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev)
+ {
+ if (m_stack_pop_event)
+ return ev.formatted_print
+ ("%qs called after enclosing function of %qs returned at %@",
+ get_user_facing_name (m_longjmp_call),
+ get_user_facing_name (m_setjmp_call),
+ m_stack_pop_event->get_id_ptr ());
+ else
+ return ev.formatted_print
+ ("%qs called after enclosing function of %qs has returned",
+ get_user_facing_name (m_longjmp_call),
+ get_user_facing_name (m_setjmp_call));;
+ }
+
+
private:
const gcall *m_setjmp_call;
const gcall *m_longjmp_call;
+ program_point m_setjmp_point;
+ custom_event *m_stack_pop_event;
};
/* Handle LONGJMP_CALL, a call to longjmp or siglongjmp.
@@ -1310,7 +1394,7 @@ exploded_node::on_longjmp (exploded_graph &eg,
/* Verify that the setjmp's call_stack hasn't been popped. */
if (!valid_longjmp_stack_p (longjmp_point, setjmp_point))
{
- ctxt->warn (new stale_jmp_buf (setjmp_call, longjmp_call));
+ ctxt->warn (new stale_jmp_buf (setjmp_call, longjmp_call, setjmp_point));
return;
}
@@ -1813,8 +1897,9 @@ worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
&& point_b.get_function () != NULL
&& point_a.get_function () != point_b.get_function ())
{
- return ka.m_worklist.m_plan.cmp_function (point_a.get_function (),
- point_b.get_function ());
+ if (int cmp = ka.m_worklist.m_plan.cmp_function (point_a.get_function (),
+ point_b.get_function ()))
+ return cmp;
}
/* First, order by SCC. */
@@ -1865,20 +1950,15 @@ worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
const program_state &state_b = kb.m_enode->get_state ();
/* Sort by sm-state, so that identical sm-states are grouped
- together in the worklist.
- For now, sort by the hash value (might not be deterministic). */
+ together in the worklist. */
for (unsigned sm_idx = 0; sm_idx < state_a.m_checker_states.length ();
++sm_idx)
{
sm_state_map *smap_a = state_a.m_checker_states[sm_idx];
sm_state_map *smap_b = state_b.m_checker_states[sm_idx];
- hashval_t hash_a = smap_a->hash ();
- hashval_t hash_b = smap_b->hash ();
- if (hash_a < hash_b)
- return -1;
- else if (hash_a > hash_b)
- return 1;
+ if (int smap_cmp = sm_state_map::cmp (*smap_a, *smap_b))
+ return smap_cmp;
}
/* Otherwise, we have two enodes at the same program point but with
@@ -2100,7 +2180,7 @@ exploded_graph::get_or_create_node (const program_point &point,
/* Impose a limit on the number of enodes per program point, and
simply stop if we exceed it. */
if ((int)per_point_data->m_enodes.length ()
- > param_analyzer_max_enodes_per_program_point)
+ >= param_analyzer_max_enodes_per_program_point)
{
pretty_printer pp;
point.print (&pp, format (false));
@@ -3506,8 +3586,7 @@ public:
void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
{
- gv->println ("subgraph \"cluster_supernode_%p\" {",
- (const void *)this);
+ gv->println ("subgraph \"cluster_supernode_%i\" {", m_supernode->m_index);
gv->indent ();
gv->println ("style=\"dashed\";");
gv->println ("label=\"SN: %i (bb: %i; scc: %i)\";",
@@ -3529,6 +3608,17 @@ public:
m_enodes.safe_push (en);
}
+ /* Comparator for use by auto_vec<supernode_cluster *>::qsort. */
+
+ static int cmp_ptr_ptr (const void *p1, const void *p2)
+ {
+ const supernode_cluster *c1
+ = *(const supernode_cluster * const *)p1;
+ const supernode_cluster *c2
+ = *(const supernode_cluster * const *)p2;
+ return c1->m_supernode->m_index - c2->m_supernode->m_index;
+ }
+
private:
const supernode *m_supernode;
auto_vec <exploded_node *> m_enodes;
@@ -3555,7 +3645,8 @@ public:
{
const char *funcname = function_name (m_fun);
- gv->println ("subgraph \"cluster_function_%p\" {", (const void *)this);
+ gv->println ("subgraph \"cluster_function_%s\" {",
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (m_fun->decl)));
gv->indent ();
gv->write_indent ();
gv->print ("label=\"call string: ");
@@ -3563,10 +3654,19 @@ public:
gv->print (" function: %s \";", funcname);
gv->print ("\n");
+ /* Dump m_map, sorting it to avoid churn when comparing dumps. */
+ auto_vec<supernode_cluster *> child_clusters (m_map.elements ());
for (map_t::iterator iter = m_map.begin ();
iter != m_map.end ();
++iter)
- (*iter).second->dump_dot (gv, args);
+ child_clusters.quick_push ((*iter).second);
+
+ child_clusters.qsort (supernode_cluster::cmp_ptr_ptr);
+
+ unsigned i;
+ supernode_cluster *child_cluster;
+ FOR_EACH_VEC_ELT (child_clusters, i, child_cluster)
+ child_cluster->dump_dot (gv, args);
/* Terminate subgraph. */
gv->outdent ();
@@ -3588,6 +3688,21 @@ public:
}
}
+ /* Comparator for use by auto_vec<function_call_string_cluster *>. */
+
+ static int cmp_ptr_ptr (const void *p1, const void *p2)
+ {
+ const function_call_string_cluster *c1
+ = *(const function_call_string_cluster * const *)p1;
+ const function_call_string_cluster *c2
+ = *(const function_call_string_cluster * const *)p2;
+ if (int cmp_names
+ = strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (c1->m_fun->decl)),
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (c2->m_fun->decl))))
+ return cmp_names;
+ return call_string::cmp (c1->m_cs, c2->m_cs);
+ }
+
private:
function *m_fun;
call_string m_cs;
@@ -3680,10 +3795,18 @@ public:
FOR_EACH_VEC_ELT (m_functionless_enodes, i, enode)
enode->dump_dot (gv, args);
+ /* Dump m_map, sorting it to avoid churn when comparing dumps. */
+ auto_vec<function_call_string_cluster *> child_clusters (m_map.elements ());
for (map_t::iterator iter = m_map.begin ();
iter != m_map.end ();
++iter)
- (*iter).second->dump_dot (gv, args);
+ child_clusters.quick_push ((*iter).second);
+
+ child_clusters.qsort (function_call_string_cluster::cmp_ptr_ptr);
+
+ function_call_string_cluster *child_cluster;
+ FOR_EACH_VEC_ELT (child_clusters, i, child_cluster)
+ child_cluster->dump_dot (gv, args);
}
void add_node (exploded_node *en) FINAL OVERRIDE
@@ -4516,6 +4639,33 @@ dump_analyzer_json (const supergraph &sg,
free (filename);
}
+/* Concrete subclass of plugin_analyzer_init_iface, allowing plugins
+ to register new state machines. */
+
+class plugin_analyzer_init_impl : public plugin_analyzer_init_iface
+{
+public:
+ plugin_analyzer_init_impl (auto_delete_vec <state_machine> *checkers,
+ logger *logger)
+ : m_checkers (checkers),
+ m_logger (logger)
+ {}
+
+ void register_state_machine (state_machine *sm) FINAL OVERRIDE
+ {
+ m_checkers->safe_push (sm);
+ }
+
+ logger *get_logger () const FINAL OVERRIDE
+ {
+ return m_logger;
+ }
+
+private:
+ auto_delete_vec <state_machine> *m_checkers;
+ logger *m_logger;
+};
+
/* Run the analysis "engine". */
void
@@ -4561,6 +4711,9 @@ impl_run_checkers (logger *logger)
auto_delete_vec <state_machine> checkers;
make_checkers (checkers, logger);
+ plugin_analyzer_init_impl data (&checkers, logger);
+ invoke_plugin_callbacks (PLUGIN_ANALYZER_INIT, &data);
+
if (logger)
{
int i;
diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h
index b1ff268..0cec27a 100644
--- a/gcc/analyzer/pending-diagnostic.h
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -175,6 +175,14 @@ class pending_diagnostic
diagnostic deduplication. */
static bool same_tree_p (tree t1, tree t2);
+ /* A vfunc for fixing up locations (both the primary location for the
+ diagnostic, and for events in their paths), e.g. to avoid unwinding
+ inside specific macros. */
+ virtual location_t fixup_location (location_t loc) const
+ {
+ return loc;
+ }
+
/* For greatest precision-of-wording, the various following "describe_*"
virtual functions give the pending diagnostic a way to describe events
in a diagnostic_path in terms that make sense for that diagnostic.
@@ -246,6 +254,21 @@ class pending_diagnostic
}
/* End of precision-of-wording vfuncs. */
+
+ /* Vfunc for extending/overriding creation of the events for an
+ exploded_edge that corresponds to a superedge, allowing for custom
+ events to be created that are pertinent to a particular
+ pending_diagnostic subclass.
+
+ For example, the -Wanalyzer-stale-setjmp-buffer diagnostic adds a
+ custom event showing when the pertinent stack frame is popped
+ (and thus the point at which the jmp_buf becomes invalid). */
+
+ virtual bool maybe_add_custom_events_for_superedge (const exploded_edge &,
+ checker_path *)
+ {
+ return false;
+ }
};
/* A template to make it easier to make subclasses of pending_diagnostic.
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index 0aadd73..d8fde60 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -558,6 +558,33 @@ function_point::cmp_within_supernode (const function_point &point_a,
return result;
}
+/* Comparator for imposing an order on function_points. */
+
+int
+function_point::cmp (const function_point &point_a,
+ const function_point &point_b)
+{
+ int idx_a = point_a.m_supernode ? point_a.m_supernode->m_index : -1;
+ int idx_b = point_b.m_supernode ? point_b.m_supernode->m_index : -1;
+ if (int cmp_idx = idx_a - idx_b)
+ return cmp_idx;
+ gcc_assert (point_a.m_supernode == point_b.m_supernode);
+ if (point_a.m_supernode)
+ return cmp_within_supernode (point_a, point_b);
+ else
+ return 0;
+}
+
+/* Comparator for use by vec<function_point>::qsort. */
+
+int
+function_point::cmp_ptr (const void *p1, const void *p2)
+{
+ const function_point *fp1 = (const function_point *)p1;
+ const function_point *fp2 = (const function_point *)p2;
+ return cmp (*fp1, *fp2);
+}
+
/* For PK_BEFORE_STMT, go to next stmt (or to PK_AFTER_SUPERNODE). */
void
diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h
index d804621..2d1c3ab 100644
--- a/gcc/analyzer/program-point.h
+++ b/gcc/analyzer/program-point.h
@@ -138,6 +138,9 @@ public:
const function_point &point_b);
static int cmp_within_supernode (const function_point &point_a,
const function_point &point_b);
+ static int cmp (const function_point &point_a,
+ const function_point &point_b);
+ static int cmp_ptr (const void *p1, const void *p2);
/* For before_stmt, go to next stmt. */
void next_stmt ();
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 5bb8907..5c59c09 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -131,12 +131,31 @@ extrinsic_state::get_model_manager () const
return NULL; /* for selftests. */
}
+/* struct sm_state_map::entry_t. */
+
+int
+sm_state_map::entry_t::cmp (const entry_t &entry_a, const entry_t &entry_b)
+{
+ gcc_assert (entry_a.m_state);
+ gcc_assert (entry_b.m_state);
+ if (int cmp_state = ((int)entry_a.m_state->get_id ()
+ - (int)entry_b.m_state->get_id ()))
+ return cmp_state;
+ if (entry_a.m_origin && entry_b.m_origin)
+ return svalue::cmp_ptr (entry_a.m_origin, entry_b.m_origin);
+ if (entry_a.m_origin)
+ return 1;
+ if (entry_b.m_origin)
+ return -1;
+ return 0;
+}
+
/* class sm_state_map. */
/* sm_state_map's ctor. */
-sm_state_map::sm_state_map (const state_machine &sm, int sm_idx)
-: m_sm (sm), m_sm_idx (sm_idx), m_map (), m_global_state (sm.get_start_state ())
+sm_state_map::sm_state_map (const state_machine &sm)
+: m_sm (sm), m_map (), m_global_state (sm.get_start_state ())
{
}
@@ -170,21 +189,29 @@ sm_state_map::print (const region_model *model,
pp_newline (pp);
first = false;
}
+ auto_vec <const svalue *> keys (m_map.elements ());
for (map_t::iterator iter = m_map.begin ();
iter != m_map.end ();
++iter)
+ keys.quick_push ((*iter).first);
+ keys.qsort (svalue::cmp_ptr_ptr);
+ unsigned i;
+ const svalue *sval;
+ FOR_EACH_VEC_ELT (keys, i, sval)
{
if (multiline)
pp_string (pp, " ");
else if (!first)
pp_string (pp, ", ");
first = false;
- const svalue *sval = (*iter).first;
- pp_pointer (pp, sval);
- pp_string (pp, ": ");
+ if (!flag_dump_noaddr)
+ {
+ pp_pointer (pp, sval);
+ pp_string (pp, ": ");
+ }
sval->dump_to_pp (pp, simple);
- entry_t e = (*iter).second;
+ entry_t e = *const_cast <map_t &> (m_map).get (sval);
pp_string (pp, ": ");
e.m_state->dump_to_pp (pp);
if (model)
@@ -197,8 +224,11 @@ sm_state_map::print (const region_model *model,
if (e.m_origin)
{
pp_string (pp, " (origin: ");
- pp_pointer (pp, e.m_origin);
- pp_string (pp, ": ");
+ if (!flag_dump_noaddr)
+ {
+ pp_pointer (pp, e.m_origin);
+ pp_string (pp, ": ");
+ }
e.m_origin->dump_to_pp (pp, simple);
if (model)
if (tree rep = model->get_representative_tree (e.m_origin))
@@ -487,6 +517,7 @@ sm_state_map::on_liveness_change (const svalue_set &live_svalues,
{
svalue_set svals_to_unset;
+ auto_vec<const svalue *> leaked_svals (m_map.elements ());
for (map_t::iterator iter = m_map.begin ();
iter != m_map.end ();
++iter)
@@ -497,10 +528,20 @@ sm_state_map::on_liveness_change (const svalue_set &live_svalues,
svals_to_unset.add (iter_sval);
entry_t e = (*iter).second;
if (!m_sm.can_purge_p (e.m_state))
- ctxt->on_state_leak (m_sm, iter_sval, e.m_state);
+ leaked_svals.quick_push (iter_sval);
}
}
+ leaked_svals.qsort (svalue::cmp_ptr_ptr);
+
+ unsigned i;
+ const svalue *sval;
+ FOR_EACH_VEC_ELT (leaked_svals, i, sval)
+ {
+ entry_t e = *m_map.get (sval);
+ ctxt->on_state_leak (m_sm, sval, e.m_state);
+ }
+
for (svalue_set::iterator iter = svals_to_unset.begin ();
iter != svals_to_unset.end (); ++iter)
m_map.remove (*iter);
@@ -545,6 +586,44 @@ sm_state_map::on_unknown_change (const svalue *sval,
impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state);
}
+/* Comparator for imposing an order on sm_state_map instances. */
+
+int
+sm_state_map::cmp (const sm_state_map &smap_a, const sm_state_map &smap_b)
+{
+ if (int cmp_count = smap_a.elements () - smap_b.elements ())
+ return cmp_count;
+
+ auto_vec <const svalue *> keys_a (smap_a.elements ());
+ for (map_t::iterator iter = smap_a.begin ();
+ iter != smap_a.end ();
+ ++iter)
+ keys_a.quick_push ((*iter).first);
+ keys_a.qsort (svalue::cmp_ptr_ptr);
+
+ auto_vec <const svalue *> keys_b (smap_b.elements ());
+ for (map_t::iterator iter = smap_b.begin ();
+ iter != smap_b.end ();
+ ++iter)
+ keys_b.quick_push ((*iter).first);
+ keys_b.qsort (svalue::cmp_ptr_ptr);
+
+ unsigned i;
+ const svalue *sval_a;
+ FOR_EACH_VEC_ELT (keys_a, i, sval_a)
+ {
+ const svalue *sval_b = keys_b[i];
+ if (int cmp_sval = svalue::cmp_ptr (sval_a, sval_b))
+ return cmp_sval;
+ const entry_t *e_a = const_cast <map_t &> (smap_a.m_map).get (sval_a);
+ const entry_t *e_b = const_cast <map_t &> (smap_b.m_map).get (sval_b);
+ if (int cmp_entry = entry_t::cmp (*e_a, *e_b))
+ return cmp_entry;
+ }
+
+ return 0;
+}
+
/* Canonicalize SVAL before getting/setting it within the map.
Convert all NULL pointers to (void *) to avoid state explosions
involving all of the various (foo *)NULL vs (bar *)NULL. */
@@ -577,7 +656,7 @@ program_state::program_state (const extrinsic_state &ext_state)
const int num_states = ext_state.get_num_checkers ();
for (int i = 0; i < num_states; i++)
{
- sm_state_map *sm = new sm_state_map (ext_state.get_sm (i), i);
+ sm_state_map *sm = new sm_state_map (ext_state.get_sm (i));
m_checker_states.quick_push (sm);
}
}
@@ -916,6 +995,7 @@ program_state::prune_for_point (exploded_graph &eg,
auto_vec<const decl_region *> ssa_name_regs;
new_state.m_region_model->get_ssa_name_regions_for_current_frame
(&ssa_name_regs);
+ ssa_name_regs.qsort (region::cmp_ptr_ptr);
unsigned i;
const decl_region *reg;
FOR_EACH_VEC_ELT (ssa_name_regs, i, reg)
@@ -1032,18 +1112,26 @@ program_state::validate (const extrinsic_state &ext_state) const
static void
log_set_of_svalues (logger *logger, const char *name,
- const svalue_set &set)
+ const svalue_set &set)
{
logger->log (name);
logger->inc_indent ();
+ auto_vec<const svalue *> sval_vecs (set.elements ());
for (svalue_set::iterator iter = set.begin ();
iter != set.end (); ++iter)
+ sval_vecs.quick_push (*iter);
+ sval_vecs.qsort (svalue::cmp_ptr_ptr);
+ unsigned i;
+ const svalue *sval;
+ FOR_EACH_VEC_ELT (sval_vecs, i, sval)
{
logger->start_log_line ();
pretty_printer *pp = logger->get_printer ();
- const svalue *sval = (*iter);
- pp_pointer (pp, sval);
- pp_string (pp, ": ");
+ if (!flag_dump_noaddr)
+ {
+ pp_pointer (pp, sval);
+ pp_string (pp, ": ");
+ }
sval->dump_to_pp (pp, false);
logger->end_log_line ();
}
@@ -1104,6 +1192,7 @@ program_state::detect_leaks (const program_state &src_state,
dest_svalues);
}
+ auto_vec <const svalue *> dead_svals (src_svalues.elements ());
for (svalue_set::iterator iter = src_svalues.begin ();
iter != src_svalues.end (); ++iter)
{
@@ -1111,11 +1200,19 @@ program_state::detect_leaks (const program_state &src_state,
/* For each sval reachable from SRC_STATE, determine if it is
live in DEST_STATE: either explicitly reachable, or implicitly
live based on the set of explicitly reachable svalues.
- Call CTXT->on_svalue_leak on those that have ceased to be live. */
+ Record those that have ceased to be live. */
if (!sval->live_p (dest_svalues, dest_state.m_region_model))
- ctxt->on_svalue_leak (sval);
+ dead_svals.quick_push (sval);
}
+ /* Call CTXT->on_svalue_leak on all svals in SRC_STATE that have ceased
+ to be live, sorting them first to ensure deterministic behavior. */
+ dead_svals.qsort (svalue::cmp_ptr_ptr);
+ unsigned i;
+ const svalue *sval;
+ FOR_EACH_VEC_ELT (dead_svals, i, sval)
+ ctxt->on_svalue_leak (sval);
+
/* Purge dead svals from sm-state. */
ctxt->on_liveness_change (dest_svalues, dest_state.m_region_model);
@@ -1154,7 +1251,7 @@ test_sm_state_map ()
const svalue *y_sval = model.get_rvalue (y, NULL);
const svalue *z_sval = model.get_rvalue (z, NULL);
- sm_state_map map (*sm, 0);
+ sm_state_map map (*sm);
ASSERT_TRUE (map.is_empty_p ());
ASSERT_EQ (map.get_state (x_sval, ext_state), start);
@@ -1183,7 +1280,7 @@ test_sm_state_map ()
const svalue *y_sval = model.get_rvalue (y, NULL);
const svalue *z_sval = model.get_rvalue (z, NULL);
- sm_state_map map (*sm, 0);
+ sm_state_map map (*sm);
ASSERT_TRUE (map.is_empty_p ());
ASSERT_EQ (map.get_state (x_sval, ext_state), start);
ASSERT_EQ (map.get_state (y_sval, ext_state), start);
@@ -1206,9 +1303,9 @@ test_sm_state_map ()
const svalue *y_sval = model.get_rvalue (y, NULL);
const svalue *z_sval = model.get_rvalue (z, NULL);
- sm_state_map map0 (*sm, 0);
- sm_state_map map1 (*sm, 0);
- sm_state_map map2 (*sm, 0);
+ sm_state_map map0 (*sm);
+ sm_state_map map1 (*sm);
+ sm_state_map map2 (*sm);
ASSERT_EQ (map0.hash (), map1.hash ());
ASSERT_EQ (map0, map1);
@@ -1229,9 +1326,9 @@ test_sm_state_map ()
const state_machine::state_t TEST_STATE_2 = &test_state_2;
const state_machine::state test_state_3 ("test state 3", 3);
const state_machine::state_t TEST_STATE_3 = &test_state_3;
- sm_state_map map0 (*sm, 0);
- sm_state_map map1 (*sm, 0);
- sm_state_map map2 (*sm, 0);
+ sm_state_map map0 (*sm);
+ sm_state_map map1 (*sm);
+ sm_state_map map2 (*sm);
ASSERT_EQ (map0.hash (), map1.hash ());
ASSERT_EQ (map0, map1);
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 094d256..1532210 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -96,13 +96,15 @@ public:
return !(*this == other);
}
+ static int cmp (const entry_t &entry_a, const entry_t &entry_b);
+
state_machine::state_t m_state;
const svalue *m_origin;
};
typedef hash_map <const svalue *, entry_t> map_t;
typedef map_t::iterator iterator_t;
- sm_state_map (const state_machine &sm, int m_sm_idx);
+ sm_state_map (const state_machine &sm);
sm_state_map *clone () const;
@@ -157,13 +159,15 @@ public:
iterator_t begin () const { return m_map.begin (); }
iterator_t end () const { return m_map.end (); }
+ size_t elements () const { return m_map.elements (); }
+
+ static int cmp (const sm_state_map &smap_a, const sm_state_map &smap_b);
static const svalue *
canonicalize_svalue (const svalue *sval, const extrinsic_state &ext_state);
private:
const state_machine &m_sm;
- int m_sm_idx;
map_t m_map;
state_machine::state_t m_global_state;
};
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index 8dd3ad0..f7fa33b 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -1033,13 +1033,19 @@ log_uniq_map (logger *logger, bool show_objs, const char *title,
const hash_map<K, T*> &uniq_map)
{
logger->log (" # %s: %li", title, uniq_map.elements ());
- if (show_objs)
- for (typename hash_map<K, T*>::iterator iter = uniq_map.begin ();
- iter != uniq_map.end (); ++iter)
- {
- T *managed_obj = (*iter).second;
- log_managed_object<T> (logger, managed_obj);
- }
+ if (!show_objs)
+ return;
+ auto_vec<const T *> vec_objs (uniq_map.elements ());
+ for (typename hash_map<K, T*>::iterator iter = uniq_map.begin ();
+ iter != uniq_map.end (); ++iter)
+ vec_objs.quick_push ((*iter).second);
+
+ vec_objs.qsort (T::cmp_ptr_ptr);
+
+ unsigned i;
+ const T *obj;
+ FOR_EACH_VEC_ELT (vec_objs, i, obj)
+ log_managed_object<T> (logger, obj);
}
/* Dump the number of objects that were managed by MAP to LOGGER.
@@ -1051,13 +1057,20 @@ log_uniq_map (logger *logger, bool show_objs, const char *title,
const consolidation_map<T> &map)
{
logger->log (" # %s: %li", title, map.elements ());
- if (show_objs)
- for (typename consolidation_map<T>::iterator iter = map.begin ();
- iter != map.end (); ++iter)
- {
- T *managed_obj = (*iter).second;
- log_managed_object<T> (logger, managed_obj);
- }
+ if (!show_objs)
+ return;
+
+ auto_vec<const T *> vec_objs (map.elements ());
+ for (typename consolidation_map<T>::iterator iter = map.begin ();
+ iter != map.end (); ++iter)
+ vec_objs.quick_push ((*iter).second);
+
+ vec_objs.qsort (T::cmp_ptr_ptr);
+
+ unsigned i;
+ const T *obj;
+ FOR_EACH_VEC_ELT (vec_objs, i, obj)
+ log_managed_object<T> (logger, obj);
}
/* Dump the number of objects of each class that were managed by this
diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc
index 3a6b312..9fc70d2 100644
--- a/gcc/analyzer/region-model-reachability.cc
+++ b/gcc/analyzer/region-model-reachability.cc
@@ -58,9 +58,8 @@ along with GCC; see the file COPYING3. If not see
namespace ana {
-reachable_regions::reachable_regions (region_model *model,
- region_model_manager *mgr)
-: m_model (model), m_store (model->get_store ()), m_mgr (mgr),
+reachable_regions::reachable_regions (region_model *model)
+: m_model (model), m_store (model->get_store ()),
m_reachable_base_regs (), m_mutable_base_regs ()
{
}
@@ -181,6 +180,40 @@ reachable_regions::handle_sval (const svalue *sval)
}
if (const svalue *cast = sval->maybe_undo_cast ())
handle_sval (cast);
+
+ /* If SVAL is the result of a reversible operation, then the operands
+ are reachable. */
+ switch (sval->get_kind ())
+ {
+ default:
+ break;
+ case SK_UNARYOP:
+ {
+ const unaryop_svalue *unaryop_sval = (const unaryop_svalue *)sval;
+ switch (unaryop_sval->get_op ())
+ {
+ default:
+ break;
+ case NEGATE_EXPR:
+ handle_sval (unaryop_sval->get_arg ());
+ break;
+ }
+ }
+ break;
+ case SK_BINOP:
+ {
+ const binop_svalue *binop_sval = (const binop_svalue *)sval;
+ switch (binop_sval->get_op ())
+ {
+ default:
+ break;
+ case POINTER_PLUS_EXPR:
+ handle_sval (binop_sval->get_arg0 ());
+ handle_sval (binop_sval->get_arg1 ());
+ break;
+ }
+ }
+ }
}
/* Add SVAL. If it is a pointer, add the pointed-to region.
@@ -214,6 +247,8 @@ void
reachable_regions::mark_escaped_clusters (region_model_context *ctxt)
{
gcc_assert (ctxt);
+ auto_vec<const function_region *> escaped_fn_regs
+ (m_mutable_base_regs.elements ());
for (hash_set<const region *>::iterator iter = m_mutable_base_regs.begin ();
iter != m_mutable_base_regs.end (); ++iter)
{
@@ -223,7 +258,36 @@ reachable_regions::mark_escaped_clusters (region_model_context *ctxt)
/* If we have a function that's escaped, potentially add
it to the worklist. */
if (const function_region *fn_reg = base_reg->dyn_cast_function_region ())
- ctxt->on_escaped_function (fn_reg->get_fndecl ());
+ escaped_fn_regs.quick_push (fn_reg);
+ }
+ /* Sort to ensure deterministic results. */
+ escaped_fn_regs.qsort (region::cmp_ptr_ptr);
+ unsigned i;
+ const function_region *fn_reg;
+ FOR_EACH_VEC_ELT (escaped_fn_regs, i, fn_reg)
+ ctxt->on_escaped_function (fn_reg->get_fndecl ());
+}
+
+/* Dump SET to PP, sorting it to avoid churn when comparing dumps. */
+
+template <typename T>
+static void
+dump_set (const hash_set<const T *> &set, pretty_printer *pp)
+{
+ auto_vec<const T *> elements (set.elements ());
+ for (typename hash_set<const T *>::iterator iter = set.begin ();
+ iter != set.end (); ++iter)
+ elements.quick_push (*iter);
+
+ elements.qsort (T::cmp_ptr_ptr);
+
+ unsigned i;
+ const T *element;
+ FOR_EACH_VEC_ELT (elements, i, element)
+ {
+ pp_string (pp, " ");
+ element->dump_to_pp (pp, true);
+ pp_newline (pp);
}
}
@@ -234,40 +298,19 @@ reachable_regions::dump_to_pp (pretty_printer *pp) const
{
pp_string (pp, "reachable clusters: ");
pp_newline (pp);
- for (hash_set<const region *>::iterator iter = m_reachable_base_regs.begin ();
- iter != m_reachable_base_regs.end (); ++iter)
- {
- pp_string (pp, " ");
- (*iter)->dump_to_pp (pp, true);
- pp_newline (pp);
- }
+ dump_set (m_reachable_base_regs, pp);
+
pp_string (pp, "mutable clusters: ");
pp_newline (pp);
- for (hash_set<const region *>::iterator iter = m_mutable_base_regs.begin ();
- iter != m_mutable_base_regs.end (); ++iter)
- {
- pp_string (pp, " ");
- (*iter)->dump_to_pp (pp, true);
- pp_newline (pp);
- }
+ dump_set (m_mutable_base_regs, pp);
+
pp_string (pp, "reachable svals: ");
pp_newline (pp);
- for (svalue_set::iterator iter = m_reachable_svals.begin ();
- iter != m_reachable_svals.end (); ++iter)
- {
- pp_string (pp, " ");
- (*iter)->dump_to_pp (pp, true);
- pp_newline (pp);
- }
+ dump_set (m_reachable_svals, pp);
+
pp_string (pp, "mutable svals: ");
pp_newline (pp);
- for (svalue_set::iterator iter = m_mutable_svals.begin ();
- iter != m_mutable_svals.end (); ++iter)
- {
- pp_string (pp, " ");
- (*iter)->dump_to_pp (pp, true);
- pp_newline (pp);
- }
+ dump_set (m_mutable_svals, pp);
}
/* Dump a multiline representation of this object to stderr. */
diff --git a/gcc/analyzer/region-model-reachability.h b/gcc/analyzer/region-model-reachability.h
index fe305b0..4d30c1f 100644
--- a/gcc/analyzer/region-model-reachability.h
+++ b/gcc/analyzer/region-model-reachability.h
@@ -35,7 +35,7 @@ namespace ana {
class reachable_regions
{
public:
- reachable_regions (region_model *model, region_model_manager *mgr);
+ reachable_regions (region_model *model);
/* Callback called for each cluster when initializing this object. */
static void init_cluster_cb (const region *base_reg,
@@ -97,7 +97,6 @@ public:
private:
region_model *m_model;
store *m_store;
- region_model_manager *m_mgr;
/* The base regions already seen. */
hash_set<const region *> m_reachable_base_regs;
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 06c0c86..57c657b 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -363,6 +363,88 @@ private:
enum poison_kind m_pkind;
};
+/* A subclass of pending_diagnostic for complaining about shifts
+ by negative counts. */
+
+class shift_count_negative_diagnostic
+: public pending_diagnostic_subclass<shift_count_negative_diagnostic>
+{
+public:
+ shift_count_negative_diagnostic (const gassign *assign, tree count_cst)
+ : m_assign (assign), m_count_cst (count_cst)
+ {}
+
+ const char *get_kind () const FINAL OVERRIDE
+ {
+ return "shift_count_negative_diagnostic";
+ }
+
+ bool operator== (const shift_count_negative_diagnostic &other) const
+ {
+ return (m_assign == other.m_assign
+ && same_tree_p (m_count_cst, other.m_count_cst));
+ }
+
+ bool emit (rich_location *rich_loc) FINAL OVERRIDE
+ {
+ return warning_at (rich_loc, OPT_Wanalyzer_shift_count_negative,
+ "shift by negative count (%qE)", m_count_cst);
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
+ {
+ return ev.formatted_print ("shift by negative amount here (%qE)", m_count_cst);
+ }
+
+private:
+ const gassign *m_assign;
+ tree m_count_cst;
+};
+
+/* A subclass of pending_diagnostic for complaining about shifts
+ by counts >= the width of the operand type. */
+
+class shift_count_overflow_diagnostic
+: public pending_diagnostic_subclass<shift_count_overflow_diagnostic>
+{
+public:
+ shift_count_overflow_diagnostic (const gassign *assign,
+ int operand_precision,
+ tree count_cst)
+ : m_assign (assign), m_operand_precision (operand_precision),
+ m_count_cst (count_cst)
+ {}
+
+ const char *get_kind () const FINAL OVERRIDE
+ {
+ return "shift_count_overflow_diagnostic";
+ }
+
+ bool operator== (const shift_count_overflow_diagnostic &other) const
+ {
+ return (m_assign == other.m_assign
+ && m_operand_precision == other.m_operand_precision
+ && same_tree_p (m_count_cst, other.m_count_cst));
+ }
+
+ bool emit (rich_location *rich_loc) FINAL OVERRIDE
+ {
+ return warning_at (rich_loc, OPT_Wanalyzer_shift_count_overflow,
+ "shift by count (%qE) >= precision of type (%qi)",
+ m_count_cst, m_operand_precision);
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
+ {
+ return ev.formatted_print ("shift by count %qE here", m_count_cst);
+ }
+
+private:
+ const gassign *m_assign;
+ int m_operand_precision;
+ tree m_count_cst;
+};
+
/* If ASSIGN is a stmt that can be modelled via
set_value (lhs_reg, SVALUE, CTXT)
for some SVALUE, get the SVALUE.
@@ -514,6 +596,26 @@ region_model::get_gassign_result (const gassign *assign,
const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
+ if (ctxt && (op == LSHIFT_EXPR || op == RSHIFT_EXPR))
+ {
+ /* "INT34-C. Do not shift an expression by a negative number of bits
+ or by greater than or equal to the number of bits that exist in
+ the operand." */
+ if (const tree rhs2_cst = rhs2_sval->maybe_get_constant ())
+ if (TREE_CODE (rhs2_cst) == INTEGER_CST)
+ {
+ if (tree_int_cst_sgn (rhs2_cst) < 0)
+ ctxt->warn (new shift_count_negative_diagnostic
+ (assign, rhs2_cst));
+ else if (compare_tree_int (rhs2_cst,
+ TYPE_PRECISION (TREE_TYPE (rhs1)))
+ >= 0)
+ ctxt->warn (new shift_count_overflow_diagnostic
+ (assign, TYPE_PRECISION (TREE_TYPE (rhs1)),
+ rhs2_cst));
+ }
+ }
+
const svalue *sval_binop
= m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
rhs1_sval, rhs2_sval);
@@ -836,7 +938,7 @@ region_model::handle_unrecognized_call (const gcall *call,
{
tree fndecl = get_fndecl_for_call (call, ctxt);
- reachable_regions reachable_regs (this, m_mgr);
+ reachable_regions reachable_regs (this);
/* Determine the reachable regions and their mutability. */
{
@@ -904,7 +1006,7 @@ void
region_model::get_reachable_svalues (svalue_set *out,
const svalue *extra_sval)
{
- reachable_regions reachable_regs (this, m_mgr);
+ reachable_regions reachable_regs (this);
/* Add globals and regions that already escaped in previous
unknown calls. */
@@ -1342,8 +1444,7 @@ region_model::get_initial_value_for_global (const region *reg) const
global decl defined in this TU that hasn't been touched yet, then
the initial value of REG can be taken from the initialization value
of the decl. */
- if ((called_from_main_p () && !DECL_EXTERNAL (decl))
- || TREE_READONLY (decl))
+ if (called_from_main_p () || TREE_READONLY (decl))
{
/* Attempt to get the initializer value for base_reg. */
if (const svalue *base_reg_init
@@ -2192,7 +2293,10 @@ region_model::get_representative_path_var (const region *reg,
return path_var (function_reg->get_fndecl (), 0);
}
case RK_LABEL:
- gcc_unreachable (); // TODO
+ {
+ const label_region *label_reg = as_a <const label_region *> (reg);
+ return path_var (label_reg->get_label (), 0);
+ }
case RK_SYMBOLIC:
{
@@ -2855,8 +2959,7 @@ region_model::can_merge_with_p (const region_model &other_model,
/* Merge constraints. */
constraint_manager::merge (*m_constraints,
*other_model.m_constraints,
- out_model->m_constraints,
- m);
+ out_model->m_constraints);
return true;
}
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 5ad4a49..75f1512 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -26,6 +26,9 @@ along with GCC; see the file COPYING3. If not see
(Zhongxing Xu, Ted Kremenek, and Jian Zhang)
http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf */
+#include "analyzer/svalue.h"
+#include "analyzer/region.h"
+
using namespace ana;
namespace inchash
@@ -147,29 +150,6 @@ struct purge_stats
int m_num_client_items;
};
-/* A measurement of the complexity of an svalue or region, so that
- we can impose bounds on the growth of these tree-like structures
- and thus avoid infinite chains of analysis. */
-
-struct complexity
-{
- complexity (unsigned num_nodes, unsigned max_depth)
- : m_num_nodes (num_nodes), m_max_depth (max_depth)
- {}
-
- complexity (const region *reg);
- complexity (const svalue *sval);
- static complexity from_pair (const complexity &c1, const complexity &c);
-
- /* The total number of svalues and regions in the tree of this
- entity, including the entity itself. */
- unsigned m_num_nodes;
-
- /* The maximum depth of the tree of this entity, including the
- entity itself. */
- unsigned m_max_depth;
-};
-
/* A base class for visiting regions and svalues, with do-nothing
base implementations of the per-subclass vfuncs. */
@@ -194,2104 +174,10 @@ public:
virtual void visit_region (const region *) {}
};
-/* An enum for discriminating between the different concrete subclasses
- of svalue. */
-
-enum svalue_kind
-{
- SK_REGION,
- SK_CONSTANT,
- SK_UNKNOWN,
- SK_POISONED,
- SK_SETJMP,
- SK_INITIAL,
- SK_UNARYOP,
- SK_BINOP,
- SK_SUB,
- SK_UNMERGEABLE,
- SK_PLACEHOLDER,
- SK_WIDENING,
- SK_COMPOUND,
- SK_CONJURED
-};
-
-/* svalue and its subclasses.
-
- The class hierarchy looks like this (using indentation to show
- inheritance, and with svalue_kinds shown for the concrete subclasses):
-
- svalue
- region_svalue (SK_REGION): a pointer to a region
- constant_svalue (SK_CONSTANT): a constant
- unknown_svalue (SK_UNKNOWN): an unknowable value
- poisoned_svalue (SK_POISONED): a unusable value (undefined)
- setjmp_svalue (SK_SETJMP): a setjmp/longjmp buffer
- initial_svalue (SK_INITIAL): the initial value of a region
- unaryop_svalue (SK_UNARYOP): unary operation on another svalue
- binop_svalue (SK_BINOP): binary operation on two svalues
- sub_svalue (SK_SUB): the result of accessing a subregion
- unmergeable_svalue (SK_UNMERGEABLE): a value that is so interesting
- from a control-flow perspective that it can inhibit state-merging
- placeholder_svalue (SK_PLACEHOLDER): for use in selftests.
- widening_svalue (SK_WIDENING): a merger of two svalues (possibly
- in an iteration).
- compound_svalue (SK_COMPOUND): a mapping of bit-ranges to svalues
- conjured_svalue (SK_CONJURED): a value arising from a stmt. */
-
-/* An abstract base class representing a value held by a region of memory. */
-
-class svalue
-{
-public:
- virtual ~svalue () {}
-
- tree get_type () const { return m_type; }
-
- virtual enum svalue_kind get_kind () const = 0;
-
- void print (const region_model &model,
- pretty_printer *pp) const;
-
- virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
- void dump (bool simple=true) const;
- label_text get_desc (bool simple=true) const;
-
- json::value *to_json () const;
-
- virtual const region_svalue *
- dyn_cast_region_svalue () const { return NULL; }
- virtual const constant_svalue *
- dyn_cast_constant_svalue () const { return NULL; }
- virtual const poisoned_svalue *
- dyn_cast_poisoned_svalue () const { return NULL; }
- virtual const setjmp_svalue *
- dyn_cast_setjmp_svalue () const { return NULL; }
- virtual const initial_svalue *
- dyn_cast_initial_svalue () const { return NULL; }
- virtual const unaryop_svalue *
- dyn_cast_unaryop_svalue () const { return NULL; }
- virtual const binop_svalue *
- dyn_cast_binop_svalue () const { return NULL; }
- virtual const sub_svalue *
- dyn_cast_sub_svalue () const { return NULL; }
- virtual const unmergeable_svalue *
- dyn_cast_unmergeable_svalue () const { return NULL; }
- virtual const widening_svalue *
- dyn_cast_widening_svalue () const { return NULL; }
- virtual const compound_svalue *
- dyn_cast_compound_svalue () const { return NULL; }
- virtual const conjured_svalue *
- dyn_cast_conjured_svalue () const { return NULL; }
-
- tree maybe_get_constant () const;
- const svalue *maybe_undo_cast () const;
- const svalue *unwrap_any_unmergeable () const;
-
- const svalue *can_merge_p (const svalue *other,
- region_model_manager *mgr,
- model_merger *merger) const;
-
- const complexity &get_complexity () const { return m_complexity; }
-
- virtual void accept (visitor *v) const = 0;
-
- bool live_p (const svalue_set &live_svalues,
- const region_model *model) const;
- virtual bool implicitly_live_p (const svalue_set &live_svalues,
- const region_model *model) const;
-
- protected:
- svalue (complexity c, tree type)
- : m_complexity (c), m_type (type)
- {}
-
- private:
- complexity m_complexity;
- tree m_type;
-};
-
-/* Concrete subclass of svalue representing a pointer value that points to
- a known region */
-
-class region_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of region_svalue. */
- struct key_t
- {
- key_t (tree type, const region *reg)
- : m_type (type), m_reg (reg)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_type);
- hstate.add_ptr (m_reg);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type && m_reg == other.m_reg);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- tree m_type;
- const region *m_reg;
- };
-
- region_svalue (tree type, const region *reg)
- : svalue (complexity (reg), type),
- m_reg (reg)
- {
- gcc_assert (m_reg != NULL);
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_REGION; }
- const region_svalue *
- dyn_cast_region_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- const region * get_pointee () const { return m_reg; }
-
- static tristate eval_condition (const region_svalue *lhs_ptr,
- enum tree_code op,
- const region_svalue *rhs_ptr);
-
- private:
- const region *m_reg;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const region_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_REGION;
-}
-
-template <> struct default_hash_traits<region_svalue::key_t>
-: public member_function_hash_traits<region_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete subclass of svalue representing a specific constant value. */
-
-class constant_svalue : public svalue
-{
-public:
- constant_svalue (tree cst_expr)
- : svalue (complexity (1, 1), TREE_TYPE (cst_expr)), m_cst_expr (cst_expr)
- {
- gcc_assert (cst_expr);
- gcc_assert (CONSTANT_CLASS_P (cst_expr));
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_CONSTANT; }
- const constant_svalue *
- dyn_cast_constant_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
- bool implicitly_live_p (const svalue_set &,
- const region_model *) const FINAL OVERRIDE;
-
- tree get_constant () const { return m_cst_expr; }
- static tristate eval_condition (const constant_svalue *lhs,
- enum tree_code op,
- const constant_svalue *rhs);
-
- private:
- tree m_cst_expr;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const constant_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_CONSTANT;
-}
-
-namespace ana {
-
-/* Concrete subclass of svalue representing an unknowable value, the bottom
- value when thinking of svalues as a lattice.
- This is a singleton (w.r.t. its manager): there is a single unknown_svalue
- per type. Self-comparisons of such instances yield "unknown". */
-
-class unknown_svalue : public svalue
-{
-public:
- unknown_svalue (tree type)
- : svalue (complexity (1, 1), type)
- {}
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_UNKNOWN; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-};
-
-/* An enum describing a particular kind of "poisoned" value. */
-
-enum poison_kind
-{
- /* For use to describe freed memory. */
- POISON_KIND_FREED,
-
- /* For use on pointers to regions within popped stack frames. */
- POISON_KIND_POPPED_STACK
-};
-
-extern const char *poison_kind_to_str (enum poison_kind);
-
-/* Concrete subclass of svalue representing a value that should not
- be used (e.g. uninitialized memory, freed memory). */
-
-class poisoned_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of poisoned_svalue. */
- struct key_t
- {
- key_t (enum poison_kind kind, tree type)
- : m_kind (kind), m_type (type)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_int (m_kind);
- hstate.add_ptr (m_type);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_kind == other.m_kind && m_type == other.m_type);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- enum poison_kind m_kind;
- tree m_type;
- };
-
- poisoned_svalue (enum poison_kind kind, tree type)
- : svalue (complexity (1, 1), type), m_kind (kind) {}
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_POISONED; }
- const poisoned_svalue *
- dyn_cast_poisoned_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- enum poison_kind get_poison_kind () const { return m_kind; }
-
- private:
- enum poison_kind m_kind;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const poisoned_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_POISONED;
-}
-
-template <> struct default_hash_traits<poisoned_svalue::key_t>
-: public member_function_hash_traits<poisoned_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* A bundle of information recording a setjmp/sigsetjmp call, corresponding
- roughly to a jmp_buf. */
-
-struct setjmp_record
-{
- setjmp_record (const exploded_node *enode,
- const gcall *setjmp_call)
- : m_enode (enode), m_setjmp_call (setjmp_call)
- {
- }
-
- bool operator== (const setjmp_record &other) const
- {
- return (m_enode == other.m_enode
- && m_setjmp_call == other.m_setjmp_call);
- }
-
- void add_to_hash (inchash::hash *hstate) const
- {
- hstate->add_ptr (m_enode);
- hstate->add_ptr (m_setjmp_call);
- }
-
- const exploded_node *m_enode;
- const gcall *m_setjmp_call;
-};
-
-/* Concrete subclass of svalue representing buffers for setjmp/sigsetjmp,
- so that longjmp/siglongjmp can potentially "return" to an entirely
- different function. */
-
-class setjmp_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of poisoned_svalue. */
- struct key_t
- {
- key_t (const setjmp_record &record, tree type)
- : m_record (record), m_type (type)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- m_record.add_to_hash (&hstate);
- hstate.add_ptr (m_type);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_record == other.m_record && m_type == other.m_type);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- setjmp_record m_record;
- tree m_type;
- };
-
- setjmp_svalue (const setjmp_record &setjmp_record,
- tree type)
- : svalue (complexity (1, 1), type), m_setjmp_record (setjmp_record)
- {}
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_SETJMP; }
- const setjmp_svalue *
- dyn_cast_setjmp_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- int get_enode_index () const;
-
- const setjmp_record &get_setjmp_record () const { return m_setjmp_record; }
-
- private:
- setjmp_record m_setjmp_record;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const setjmp_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_SETJMP;
-}
-
-template <> struct default_hash_traits<setjmp_svalue::key_t>
-: public member_function_hash_traits<setjmp_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete subclass of svalue representing the initial value of a
- specific region.
-
- This represents the initial value at the start of the analysis path,
- as opposed to the first time the region is accessed during the path.
- Hence as soon as we have a call to an unknown function, all previously
- unmodelled globals become implicitly "unknown" rathen than "initial". */
-
-class initial_svalue : public svalue
-{
-public:
- initial_svalue (tree type, const region *reg)
- : svalue (complexity (reg), type), m_reg (reg)
- {
- gcc_assert (m_reg != NULL);
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_INITIAL; }
- const initial_svalue *
- dyn_cast_initial_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
- bool implicitly_live_p (const svalue_set &,
- const region_model *) const FINAL OVERRIDE;
-
- const region *get_region () const { return m_reg; }
-
- private:
- const region *m_reg;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const initial_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_INITIAL;
-}
-
-namespace ana {
-
-/* Concrete subclass of svalue representing a unary operation on
- another svalues (e.g. a cast). */
-
-class unaryop_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of unaryop_svalue. */
- struct key_t
- {
- key_t (tree type, enum tree_code op, const svalue *arg)
- : m_type (type), m_op (op), m_arg (arg)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_type);
- hstate.add_int (m_op);
- hstate.add_ptr (m_arg);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type
- && m_op == other.m_op
- && m_arg == other.m_arg);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- tree m_type;
- enum tree_code m_op;
- const svalue *m_arg;
- };
-
- unaryop_svalue (tree type, enum tree_code op, const svalue *arg)
- : svalue (complexity (arg), type), m_op (op), m_arg (arg)
- {
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_UNARYOP; }
- const unaryop_svalue *
- dyn_cast_unaryop_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
- bool implicitly_live_p (const svalue_set &,
- const region_model *) const FINAL OVERRIDE;
-
- enum tree_code get_op () const { return m_op; }
- const svalue *get_arg () const { return m_arg; }
-
- private:
- enum tree_code m_op;
- const svalue *m_arg;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const unaryop_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_UNARYOP;
-}
-
-template <> struct default_hash_traits<unaryop_svalue::key_t>
-: public member_function_hash_traits<unaryop_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete subclass of svalue representing a binary operation of
- two svalues. */
-
-class binop_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of binop_svalue. */
- struct key_t
- {
- key_t (tree type, enum tree_code op,
- const svalue *arg0, const svalue *arg1)
- : m_type (type), m_op (op), m_arg0 (arg0), m_arg1 (arg1)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_type);
- hstate.add_int (m_op);
- hstate.add_ptr (m_arg0);
- hstate.add_ptr (m_arg1);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type
- && m_op == other.m_op
- && m_arg0 == other.m_arg0
- && m_arg1 == other.m_arg1);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- tree m_type;
- enum tree_code m_op;
- const svalue *m_arg0;
- const svalue *m_arg1;
- };
-
- binop_svalue (tree type, enum tree_code op,
- const svalue *arg0, const svalue *arg1)
- : svalue (complexity::from_pair (arg0->get_complexity (),
- arg1->get_complexity ()),
- type),
- m_op (op), m_arg0 (arg0), m_arg1 (arg1)
- {
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_BINOP; }
- const binop_svalue *dyn_cast_binop_svalue () const FINAL OVERRIDE
- {
- return this;
- }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
- bool implicitly_live_p (const svalue_set &,
- const region_model *) const FINAL OVERRIDE;
-
- enum tree_code get_op () const { return m_op; }
- const svalue *get_arg0 () const { return m_arg0; }
- const svalue *get_arg1 () const { return m_arg1; }
-
- private:
- enum tree_code m_op;
- const svalue *m_arg0;
- const svalue *m_arg1;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const binop_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_BINOP;
-}
-
-template <> struct default_hash_traits<binop_svalue::key_t>
-: public member_function_hash_traits<binop_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete subclass of svalue representing the result of accessing a subregion
- of another svalue (the value of a component/field of a struct, or an element
- from an array). */
-
-class sub_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of sub_svalue. */
- struct key_t
- {
- key_t (tree type, const svalue *parent_svalue, const region *subregion)
- : m_type (type), m_parent_svalue (parent_svalue), m_subregion (subregion)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_type);
- hstate.add_ptr (m_parent_svalue);
- hstate.add_ptr (m_subregion);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type
- && m_parent_svalue == other.m_parent_svalue
- && m_subregion == other.m_subregion);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- tree m_type;
- const svalue *m_parent_svalue;
- const region *m_subregion;
- };
- sub_svalue (tree type, const svalue *parent_svalue,
- const region *subregion);
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_SUB; }
- const sub_svalue *dyn_cast_sub_svalue () const FINAL OVERRIDE
- {
- return this;
- }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
- bool implicitly_live_p (const svalue_set &,
- const region_model *) const FINAL OVERRIDE;
-
- const svalue *get_parent () const { return m_parent_svalue; }
- const region *get_subregion () const { return m_subregion; }
-
- private:
- const svalue *m_parent_svalue;
- const region *m_subregion;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const sub_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_SUB;
-}
-
-template <> struct default_hash_traits<sub_svalue::key_t>
-: public member_function_hash_traits<sub_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete subclass of svalue: decorate another svalue,
- so that the resulting svalue can be identified as being
- "interesting to control flow".
- For example, consider the return value from setjmp. We
- don't want to merge states in which the result is 0 with
- those in which the result is non-zero. By using an
- unmergeable_svalue for the result, we can inhibit such merges
- and have separate exploded nodes for those states, keeping
- the first and second returns from setjmp distinct in the exploded
- graph. */
-
-class unmergeable_svalue : public svalue
-{
-public:
- unmergeable_svalue (const svalue *arg)
- : svalue (complexity (arg), arg->get_type ()), m_arg (arg)
- {
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_UNMERGEABLE; }
- const unmergeable_svalue *
- dyn_cast_unmergeable_svalue () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
- bool implicitly_live_p (const svalue_set &,
- const region_model *) const FINAL OVERRIDE;
-
- const svalue *get_arg () const { return m_arg; }
-
- private:
- const svalue *m_arg;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const unmergeable_svalue *>::test (const svalue *sval)
-{
- return sval->get_kind () == SK_UNMERGEABLE;
-}
-
-namespace ana {
-
-/* Concrete subclass of svalue for use in selftests, where
- we want a specific but unknown svalue.
- Unlike other svalue subclasses these aren't managed by
- region_model_manager. */
-
-class placeholder_svalue : public svalue
-{
-public:
- placeholder_svalue (tree type, const char *name)
- : svalue (complexity (1, 1), type), m_name (name)
- {
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_PLACEHOLDER; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- private:
- const char *m_name;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <placeholder_svalue *>::test (svalue *sval)
-{
- return sval->get_kind () == SK_PLACEHOLDER;
-}
-
-namespace ana {
-
-/* Concrete subclass of svalue representing a "widening" seen when merging
- states, widening from a base value to {base value, iter value} and thus
- representing a possible fixed point in an iteration from the base to
- +ve infinity, or -ve infinity, and thus useful for representing a value
- within a loop.
- We also need to capture the program_point at which the merger happens,
- so that distinguish between different iterators, and thus handle
- nested loops. (currently we capture the function_point instead, for
- simplicity of hashing). */
-
-class widening_svalue : public svalue
-{
-public:
- /* A support class for uniquifying instances of widening_svalue. */
- struct key_t
- {
- key_t (tree type, const program_point &point,
- const svalue *base_sval, const svalue *iter_sval)
- : m_type (type), m_point (point.get_function_point ()),
- m_base_sval (base_sval), m_iter_sval (iter_sval)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_base_sval);
- hstate.add_ptr (m_iter_sval);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type
- && m_point == other.m_point
- && m_base_sval == other.m_base_sval
- && m_iter_sval == other.m_iter_sval);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- tree m_type;
- function_point m_point;
- const svalue *m_base_sval;
- const svalue *m_iter_sval;
- };
-
- enum direction_t
- {
- DIR_ASCENDING,
- DIR_DESCENDING,
- DIR_UNKNOWN
- };
-
- widening_svalue (tree type, const program_point &point,
- const svalue *base_sval, const svalue *iter_sval)
- : svalue (complexity::from_pair (base_sval->get_complexity (),
- iter_sval->get_complexity ()),
- type),
- m_point (point.get_function_point ()),
- m_base_sval (base_sval), m_iter_sval (iter_sval)
- {
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_WIDENING; }
- const widening_svalue *dyn_cast_widening_svalue () const FINAL OVERRIDE
- {
- return this;
- }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- const svalue *get_base_svalue () const { return m_base_sval; }
- const svalue *get_iter_svalue () const { return m_iter_sval; }
-
- enum direction_t get_direction () const;
-
- tristate eval_condition_without_cm (enum tree_code op,
- tree rhs_cst) const;
-
- private:
- function_point m_point;
- const svalue *m_base_sval;
- const svalue *m_iter_sval;
-};
-
} // namespace ana
-template <>
-template <>
-inline bool
-is_a_helper <widening_svalue *>::test (svalue *sval)
-{
- return sval->get_kind () == SK_WIDENING;
-}
-
-template <> struct default_hash_traits<widening_svalue::key_t>
-: public member_function_hash_traits<widening_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
namespace ana {
-/* Concrete subclass of svalue representing a mapping of bit-ranges
- to svalues, analogous to a cluster within the store.
-
- This is for use in places where we want to represent a store-like
- mapping, but are required to use an svalue, such as when handling
- compound assignments and compound return values.
-
- All keys within the underlying binding_map are required to be concrete,
- not symbolic.
-
- Instances of this class shouldn't be bound as-is into the store;
- instead they should be unpacked. Similarly, they should not be
- nested. */
-
-class compound_svalue : public svalue
-{
-public:
- typedef binding_map::iterator_t iterator_t;
-
- /* A support class for uniquifying instances of compound_svalue.
- Note that to avoid copies, keys store pointers to binding_maps,
- rather than the maps themselves. */
- struct key_t
- {
- key_t (tree type, const binding_map *map_ptr)
- : m_type (type), m_map_ptr (map_ptr)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_type);
- //hstate.add_ptr (m_map_ptr); // TODO
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type
- && *m_map_ptr == *other.m_map_ptr);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- tree m_type;
- const binding_map *m_map_ptr;
- };
-
- compound_svalue (tree type, const binding_map &map);
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_COMPOUND; }
- const compound_svalue *dyn_cast_compound_svalue () const FINAL OVERRIDE
- {
- return this;
- }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- iterator_t begin () const { return m_map.begin (); }
- iterator_t end () const { return m_map.end (); }
-
- struct key_t make_key () const
- {
- return key_t (get_type (), &m_map);
- }
-
- private:
- static complexity calc_complexity (const binding_map &map);
-
- binding_map m_map;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <compound_svalue *>::test (svalue *sval)
-{
- return sval->get_kind () == SK_COMPOUND;
-}
-
-template <> struct default_hash_traits<compound_svalue::key_t>
-: public member_function_hash_traits<compound_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* A defined value arising from a statement, where we want to identify a
- particular unknown value, rather than resorting to the unknown_value
- singleton, so that the value can have sm-state.
-
- Comparisons of variables that share the same conjured_svalue are known
- to be equal, even if we don't know what the value is.
-
- For example, this is used for the values of regions that may have been
- touched when calling an unknown function.
-
- The value captures a region as well as a stmt in order to avoid falsely
- aliasing the various values that could arise in one statement. For
- example, after:
- unknown_fn (&a, &b);
- we want values to clobber a and b with, but we don't want to use the
- same value, or it would falsely implicitly assume that a == b. */
-
-class conjured_svalue : public svalue
-{
-public:
- typedef binding_map::iterator_t iterator_t;
-
- /* A support class for uniquifying instances of conjured_svalue. */
- struct key_t
- {
- key_t (tree type, const gimple *stmt, const region *id_reg)
- : m_type (type), m_stmt (stmt), m_id_reg (id_reg)
- {}
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_type);
- hstate.add_ptr (m_stmt);
- hstate.add_ptr (m_id_reg);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_type == other.m_type
- && m_stmt == other.m_stmt
- && m_id_reg == other.m_id_reg);
- }
-
- /* Use m_stmt to mark empty/deleted, as m_type can be NULL for
- legitimate instances. */
- void mark_deleted () { m_stmt = reinterpret_cast<const gimple *> (1); }
- void mark_empty () { m_stmt = NULL; }
- bool is_deleted () const
- {
- return m_stmt == reinterpret_cast<const gimple *> (1);
- }
- bool is_empty () const { return m_stmt == NULL; }
-
- tree m_type;
- const gimple *m_stmt;
- const region *m_id_reg;
- };
-
- conjured_svalue (tree type, const gimple *stmt, const region *id_reg)
- : svalue (complexity (id_reg), type),
- m_stmt (stmt), m_id_reg (id_reg)
- {
- gcc_assert (m_stmt != NULL);
- }
-
- enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_CONJURED; }
- const conjured_svalue *dyn_cast_conjured_svalue () const FINAL OVERRIDE
- {
- return this;
- }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- void accept (visitor *v) const FINAL OVERRIDE;
-
- private:
- const gimple *m_stmt;
- const region *m_id_reg;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <conjured_svalue *>::test (svalue *sval)
-{
- return sval->get_kind () == SK_CONJURED;
-}
-
-template <> struct default_hash_traits<conjured_svalue::key_t>
-: public member_function_hash_traits<conjured_svalue::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* An enum for discriminating between the different concrete subclasses
- of region. */
-
-enum region_kind
-{
- RK_FRAME,
- RK_GLOBALS,
- RK_CODE,
- RK_FUNCTION,
- RK_LABEL,
- RK_STACK,
- RK_HEAP,
- RK_ROOT,
- RK_SYMBOLIC,
- RK_DECL,
- RK_FIELD,
- RK_ELEMENT,
- RK_OFFSET,
- RK_CAST,
- RK_HEAP_ALLOCATED,
- RK_ALLOCA,
- RK_STRING,
- RK_UNKNOWN
-};
-
-/* Region and its subclasses.
-
- The class hierarchy looks like this (using indentation to show
- inheritance, and with region_kinds shown for the concrete subclasses):
-
- region
- space_region
- frame_region (RK_FRAME)
- globals_region (RK_GLOBALS)
- code_region (RK_CODE)
- stack_region (RK_STACK)
- heap_region (RK_HEAP)
- root_region (RK_ROOT)
- function_region (RK_FUNCTION)
- label_region (RK_LABEL)
- symbolic_region (RK_SYMBOLIC)
- decl_region (RK_DECL),
- field_region (RK_FIELD)
- element_region (RK_ELEMENT)
- offset_region (RK_OFFSET)
- cast_region (RK_CAST)
- heap_allocated_region (RK_HEAP_ALLOCATED)
- alloca_region (RK_ALLOCA)
- string_region (RK_STRING)
- unknown_region (RK_UNKNOWN). */
-
-/* Abstract base class for representing ways of accessing chunks of memory.
-
- Regions form a tree-like hierarchy, with a root region at the base,
- with memory space regions within it, representing the stack and
- globals, with frames within the stack, and regions for variables
- within the frames and the "globals" region. Regions for structs
- can have subregions for fields. */
-
-class region
-{
-public:
- virtual ~region ();
-
- unsigned get_id () const { return m_id; }
- static int cmp_ids (const region *reg1, const region *reg2);
-
- virtual enum region_kind get_kind () const = 0;
- virtual const frame_region *
- dyn_cast_frame_region () const { return NULL; }
- virtual const function_region *
- dyn_cast_function_region () const { return NULL; }
- virtual const symbolic_region *
- dyn_cast_symbolic_region () const { return NULL; }
- virtual const decl_region *
- dyn_cast_decl_region () const { return NULL; }
- virtual const field_region *
- dyn_cast_field_region () const { return NULL; }
- virtual const element_region *
- dyn_cast_element_region () const { return NULL; }
- virtual const offset_region *
- dyn_cast_offset_region () const { return NULL; }
- virtual const cast_region *
- dyn_cast_cast_region () const { return NULL; }
- virtual const string_region *
- dyn_cast_string_region () const { return NULL; }
-
- virtual void accept (visitor *v) const;
-
- const region *get_parent_region () const { return m_parent; }
- const region *get_base_region () const;
- bool base_region_p () const;
- bool descendent_of_p (const region *elder) const;
- const frame_region *maybe_get_frame_region () const;
-
- tree maybe_get_decl () const;
-
- tree get_type () const { return m_type; }
-
- void print (const region_model &model,
- pretty_printer *pp) const;
- label_text get_desc (bool simple=true) const;
-
- void dump_to_pp (const region_model &model,
- pretty_printer *pp,
- const char *prefix,
- bool is_last_child) const;
-
- virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
- void dump (bool simple) const;
-
- json::value *to_json () const;
-
- bool non_null_p () const;
-
- static int cmp_ptrs (const void *, const void *);
-
- region_offset get_offset () const;
- bool get_byte_size (byte_size_t *out) const;
- bool get_bit_size (bit_size_t *out) const;
-
- void
- get_subregions_for_binding (region_model_manager *mgr,
- bit_offset_t start_bit_offset,
- bit_size_t size_in_bits,
- tree type,
- auto_vec <const region *> *out) const;
-
- bool symbolic_for_unknown_ptr_p () const;
-
- const complexity &get_complexity () const { return m_complexity; }
-
- protected:
- region (complexity c, unsigned id, const region *parent, tree type);
-
- private:
- region_offset calc_offset () const;
-
- complexity m_complexity;
- unsigned m_id; // purely for deterministic sorting at this stage, for dumps
- const region *m_parent;
- tree m_type;
-
- mutable region_offset *m_cached_offset;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const region *>::test (const region *)
-{
- return true;
-}
-
-namespace ana {
-
-/* Abstract subclass of region, for regions that represent an untyped
- space within memory, such as the stack or the heap. */
-
-class space_region : public region
-{
-protected:
- space_region (unsigned id, const region *parent)
- : region (complexity (parent), id, parent, NULL_TREE)
- {}
-};
-
-/* Concrete space_region subclass, representing a function frame on the stack,
- to contain the locals.
- The parent is the stack region; there's also a hierarchy of call-stack
- prefixes expressed via m_calling_frame.
- For example, given "oldest" calling "middle" called "newest" we would have
- - a stack depth of 3
- - frame (A) for "oldest" with index 0 for depth 1, calling_frame == NULL
- - frame (B) for "middle" with index 1 for depth 2, calling_frame == (A)
- - frame (C) for "newest" with index 2 for depth 3, calling_frame == (B)
- where the parent region for each of the frames is the "stack" region.
- The index is the count of frames earlier than this in the stack. */
-
-class frame_region : public space_region
-{
-public:
- /* A support class for uniquifying instances of frame_region. */
- struct key_t
- {
- key_t (const frame_region *calling_frame, function *fun)
- : m_calling_frame (calling_frame), m_fun (fun)
- {
- /* calling_frame can be NULL. */
- gcc_assert (fun);
- }
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_calling_frame);
- hstate.add_ptr (m_fun);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_calling_frame == other.m_calling_frame && m_fun == other.m_fun);
- }
-
- void mark_deleted () { m_fun = reinterpret_cast<function *> (1); }
- void mark_empty () { m_fun = NULL; }
- bool is_deleted () const
- {
- return m_fun == reinterpret_cast<function *> (1);
- }
- bool is_empty () const { return m_fun == NULL; }
-
- const frame_region *m_calling_frame;
- function *m_fun;
- };
-
- frame_region (unsigned id, const region *parent,
- const frame_region *calling_frame,
- function *fun, int index)
- : space_region (id, parent), m_calling_frame (calling_frame),
- m_fun (fun), m_index (index)
- {}
- ~frame_region ();
-
- /* region vfuncs. */
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_FRAME; }
- const frame_region * dyn_cast_frame_region () const FINAL OVERRIDE
- {
- return this;
- }
- void accept (visitor *v) const FINAL OVERRIDE;
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- /* Accessors. */
- const frame_region *get_calling_frame () const { return m_calling_frame; }
- function *get_function () const { return m_fun; }
- int get_index () const { return m_index; }
- int get_stack_depth () const { return m_index + 1; }
-
- const decl_region *get_region_for_local (region_model_manager *mgr,
- tree expr) const;
-
- unsigned get_num_locals () const { return m_locals.elements (); }
-
- private:
- const frame_region *m_calling_frame;
- function *m_fun;
- int m_index;
-
- /* The regions for the decls within this frame are managed by this
- object, rather than the region_model_manager, to make it a simple
- lookup by tree. */
- typedef hash_map<tree, decl_region *> map_t;
- map_t m_locals;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const frame_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_FRAME;
-}
-
-template <> struct default_hash_traits<frame_region::key_t>
-: public member_function_hash_traits<frame_region::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete space_region subclass, to hold global variables (data and bss). */
-
-class globals_region : public space_region
-{
- public:
- globals_region (unsigned id, const region *parent)
- : space_region (id, parent)
- {}
-
- /* region vfuncs. */
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_GLOBALS; }
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const globals_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_GLOBALS;
-}
-
-namespace ana {
-
-/* Concrete space_region subclass, representing the code segment
- containing functions. */
-
-class code_region : public space_region
-{
-public:
- code_region (unsigned id, const region *parent)
- : space_region (id, parent)
- {}
-
- /* region vfuncs. */
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_CODE; }
-
- const region *get_element (region_model *model,
- const svalue *index,
- region_model_context *ctxt);
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const code_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_CODE;
-}
-
-namespace ana {
-
-/* Concrete region subclass. A region representing the code for
- a particular function. */
-
-class function_region : public region
-{
-public:
- function_region (unsigned id, const code_region *parent, tree fndecl)
- : region (complexity (parent), id, parent, TREE_TYPE (fndecl)),
- m_fndecl (fndecl)
- {
- gcc_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndecl)));
- }
-
- /* region vfuncs. */
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_FUNCTION; }
- const function_region *
- dyn_cast_function_region () const FINAL OVERRIDE{ return this; }
-
- tree get_fndecl () const { return m_fndecl; }
-
- region *get_element (region_model *model,
- const svalue *index_sid,
- region_model_context *ctxt);
-
-private:
- tree m_fndecl;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const function_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_FUNCTION;
-}
-
-namespace ana {
-
-/* Concrete region subclass. A region representing a particular label
- within a function. */
-
-class label_region : public region
-{
-public:
- label_region (unsigned id, const function_region *parent, tree label)
- : region (complexity (parent), id, parent, NULL_TREE), m_label (label)
- {
- gcc_assert (TREE_CODE (label) == LABEL_DECL);
- }
-
- /* region vfuncs. */
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_LABEL; }
-
-private:
- tree m_label;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const label_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_LABEL;
-}
-
-namespace ana {
-
-/* Concrete space_region subclass representing a stack, containing all stack
- frames. */
-
-class stack_region : public space_region
-{
-public:
- stack_region (unsigned id, region *parent)
- : space_region (id, parent)
- {}
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_STACK; }
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const stack_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_STACK;
-}
-
-namespace ana {
-
-/* Concrete space_region subclass: a region within which regions can be
- dynamically allocated. */
-
-class heap_region : public space_region
-{
-public:
- heap_region (unsigned id, region *parent)
- : space_region (id, parent)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_HEAP; }
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const heap_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_HEAP;
-}
-
-namespace ana {
-
-/* Concrete region subclass. The root region, containing all regions
- (either directly, or as descendents).
- Unique within a region_model_manager. */
-
-class root_region : public region
-{
-public:
- root_region (unsigned id);
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_ROOT; }
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const root_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_ROOT;
-}
-
-namespace ana {
-
-/* Concrete region subclass: a region to use when dereferencing an unknown
- pointer. */
-
-class symbolic_region : public region
-{
-public:
- /* A support class for uniquifying instances of symbolic_region. */
- struct key_t
- {
- key_t (const region *parent, const svalue *sval_ptr)
- : m_parent (parent), m_sval_ptr (sval_ptr)
- {
- gcc_assert (sval_ptr);
- }
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_parent);
- hstate.add_ptr (m_sval_ptr);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_parent == other.m_parent && m_sval_ptr == other.m_sval_ptr);
- }
-
- void mark_deleted () { m_sval_ptr = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_sval_ptr = NULL; }
- bool is_deleted () const
- {
- return m_sval_ptr == reinterpret_cast<const svalue *> (1);
- }
- bool is_empty () const { return m_sval_ptr == NULL; }
-
- const region *m_parent;
- const svalue *m_sval_ptr;
- };
-
- symbolic_region (unsigned id, region *parent, const svalue *sval_ptr)
- : region (complexity::from_pair (parent, sval_ptr), id, parent,
- TREE_TYPE (sval_ptr->get_type ())),
- m_sval_ptr (sval_ptr)
- {}
-
- const symbolic_region *
- dyn_cast_symbolic_region () const FINAL OVERRIDE { return this; }
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_SYMBOLIC; }
- void accept (visitor *v) const FINAL OVERRIDE;
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- const svalue *get_pointer () const { return m_sval_ptr; }
-
-private:
- const svalue *m_sval_ptr;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const symbolic_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_SYMBOLIC;
-}
-
-template <> struct default_hash_traits<symbolic_region::key_t>
-: public member_function_hash_traits<symbolic_region::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* Concrete region subclass representing the memory occupied by a
- variable (whether for a global or a local). */
-
-class decl_region : public region
-{
-public:
- decl_region (unsigned id, const region *parent, tree decl)
- : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_DECL; }
- const decl_region *
- dyn_cast_decl_region () const FINAL OVERRIDE { return this; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- tree get_decl () const { return m_decl; }
- int get_stack_depth () const;
-
- const svalue *maybe_get_constant_value (region_model_manager *mgr) const;
- const svalue *get_svalue_for_constructor (tree ctor,
- region_model_manager *mgr) const;
- const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
-
-private:
- tree m_decl;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const decl_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_DECL;
-}
-
-namespace ana {
-
-/* Concrete region subclass representing the memory occupied by a
- field within a struct or union. */
-
-class field_region : public region
-{
-public:
- /* A support class for uniquifying instances of field_region. */
- struct key_t
- {
- key_t (const region *parent, tree field)
- : m_parent (parent), m_field (field)
- {
- gcc_assert (field);
- }
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_parent);
- hstate.add_ptr (m_field);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_parent == other.m_parent && m_field == other.m_field);
- }
-
- void mark_deleted () { m_field = reinterpret_cast<tree> (1); }
- void mark_empty () { m_field = NULL_TREE; }
- bool is_deleted () const { return m_field == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_field == NULL_TREE; }
-
- const region *m_parent;
- tree m_field;
- };
-
- field_region (unsigned id, const region *parent, tree field)
- : region (complexity (parent), id, parent, TREE_TYPE (field)),
- m_field (field)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_FIELD; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
- const field_region *
- dyn_cast_field_region () const FINAL OVERRIDE { return this; }
-
- tree get_field () const { return m_field; }
-
-private:
- tree m_field;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const field_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_FIELD;
-}
-
-template <> struct default_hash_traits<field_region::key_t>
-: public member_function_hash_traits<field_region::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* An element within an array. */
-
-class element_region : public region
-{
-public:
- /* A support class for uniquifying instances of element_region. */
- struct key_t
- {
- key_t (const region *parent, tree element_type, const svalue *index)
- : m_parent (parent), m_element_type (element_type), m_index (index)
- {
- gcc_assert (index);
- }
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_parent);
- hstate.add_ptr (m_element_type);
- hstate.add_ptr (m_index);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_parent == other.m_parent
- && m_element_type == other.m_element_type
- && m_index == other.m_index);
- }
-
- void mark_deleted () { m_index = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_index = NULL; }
- bool is_deleted () const
- {
- return m_index == reinterpret_cast<const svalue *> (1);
- }
- bool is_empty () const { return m_index == NULL; }
-
- const region *m_parent;
- tree m_element_type;
- const svalue *m_index;
- };
-
- element_region (unsigned id, const region *parent, tree element_type,
- const svalue *index)
- : region (complexity::from_pair (parent, index), id, parent, element_type),
- m_index (index)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_ELEMENT; }
- const element_region *
- dyn_cast_element_region () const FINAL OVERRIDE { return this; }
-
- void accept (visitor *v) const FINAL OVERRIDE;
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- const svalue *get_index () const { return m_index; }
-
-private:
- const svalue *m_index;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const element_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_ELEMENT;
-}
-
-template <> struct default_hash_traits<element_region::key_t>
-: public member_function_hash_traits<element_region::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* A byte-offset within another region, for handling pointer arithmetic
- as a region. */
-
-class offset_region : public region
-{
-public:
- /* A support class for uniquifying instances of offset_region. */
- struct key_t
- {
- key_t (const region *parent, tree element_type, const svalue *byte_offset)
- : m_parent (parent), m_element_type (element_type), m_byte_offset (byte_offset)
- {
- gcc_assert (byte_offset);
- }
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_parent);
- hstate.add_ptr (m_element_type);
- hstate.add_ptr (m_byte_offset);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_parent == other.m_parent
- && m_element_type == other.m_element_type
- && m_byte_offset == other.m_byte_offset);
- }
-
- void mark_deleted () { m_byte_offset = reinterpret_cast<const svalue *> (1); }
- void mark_empty () { m_byte_offset = NULL; }
- bool is_deleted () const
- {
- return m_byte_offset == reinterpret_cast<const svalue *> (1);
- }
- bool is_empty () const { return m_byte_offset == NULL; }
-
- const region *m_parent;
- tree m_element_type;
- const svalue *m_byte_offset;
- };
-
- offset_region (unsigned id, const region *parent, tree type,
- const svalue *byte_offset)
- : region (complexity::from_pair (parent, byte_offset), id, parent, type),
- m_byte_offset (byte_offset)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_OFFSET; }
- const offset_region *
- dyn_cast_offset_region () const FINAL OVERRIDE { return this; }
-
- void accept (visitor *v) const FINAL OVERRIDE;
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- const svalue *get_byte_offset () const { return m_byte_offset; }
-
-private:
- const svalue *m_byte_offset;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const offset_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_OFFSET;
-}
-
-template <> struct default_hash_traits<offset_region::key_t>
-: public member_function_hash_traits<offset_region::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* A region that views another region using a different type. */
-
-class cast_region : public region
-{
-public:
- /* A support class for uniquifying instances of cast_region. */
- struct key_t
- {
- key_t (const region *original_region, tree type)
- : m_original_region (original_region), m_type (type)
- {
- gcc_assert (type);
- }
-
- hashval_t hash () const
- {
- inchash::hash hstate;
- hstate.add_ptr (m_original_region);
- hstate.add_ptr (m_type);
- return hstate.end ();
- }
-
- bool operator== (const key_t &other) const
- {
- return (m_original_region == other.m_original_region
- && m_type == other.m_type);
- }
-
- void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
- void mark_empty () { m_type = NULL_TREE; }
- bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
- bool is_empty () const { return m_type == NULL_TREE; }
-
- const region *m_original_region;
- tree m_type;
- };
-
- cast_region (unsigned id, const region *original_region, tree type)
- : region (complexity (original_region), id,
- original_region->get_parent_region (), type),
- m_original_region (original_region)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_CAST; }
- const cast_region *
- dyn_cast_cast_region () const FINAL OVERRIDE { return this; }
- void accept (visitor *v) const FINAL OVERRIDE;
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- const region *get_original_region () const { return m_original_region; }
-
-private:
- const region *m_original_region;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const cast_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_CAST;
-}
-
-template <> struct default_hash_traits<cast_region::key_t>
-: public member_function_hash_traits<cast_region::key_t>
-{
- static const bool empty_zero_p = true;
-};
-
-namespace ana {
-
-/* An untyped region dynamically allocated on the heap via "malloc"
- or similar. */
-
-class heap_allocated_region : public region
-{
-public:
- heap_allocated_region (unsigned id, const region *parent)
- : region (complexity (parent), id, parent, NULL_TREE)
- {}
-
- enum region_kind
- get_kind () const FINAL OVERRIDE { return RK_HEAP_ALLOCATED; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-};
-
-/* An untyped region dynamically allocated on the stack via "alloca". */
-
-class alloca_region : public region
-{
-public:
- alloca_region (unsigned id, const frame_region *parent)
- : region (complexity (parent), id, parent, NULL_TREE)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_ALLOCA; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-};
-
-/* A region for a STRING_CST. */
-
-class string_region : public region
-{
-public:
- string_region (unsigned id, const region *parent, tree string_cst)
- : region (complexity (parent), id, parent, TREE_TYPE (string_cst)),
- m_string_cst (string_cst)
- {}
-
- const string_region *
- dyn_cast_string_region () const FINAL OVERRIDE { return this; }
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_STRING; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-
- tree get_string_cst () const { return m_string_cst; }
-
-private:
- tree m_string_cst;
-};
-
-} // namespace ana
-
-template <>
-template <>
-inline bool
-is_a_helper <const string_region *>::test (const region *reg)
-{
- return reg->get_kind () == RK_STRING;
-}
-
-namespace ana {
-
-/* An unknown region, for handling unimplemented tree codes. */
-
-class unknown_region : public region
-{
-public:
- unknown_region (unsigned id, const region *parent, tree type)
- : region (complexity (parent), id, parent, type)
- {}
-
- enum region_kind get_kind () const FINAL OVERRIDE { return RK_UNKNOWN; }
-
- void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
-};
-
/* A class responsible for owning and consolidating region and svalue
instances.
region and svalue instances are immutable as far as clients are
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index adf0e2c..cce366d 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/call-string.h"
#include "analyzer/program-point.h"
#include "analyzer/store.h"
+#include "analyzer/region.h"
#include "analyzer/region-model.h"
#if ENABLE_ANALYZER
@@ -517,10 +518,11 @@ region::region (complexity c, unsigned id, const region *parent, tree type)
gcc_assert (type == NULL_TREE || TYPE_P (type));
}
-/* Comparator for regions, using their IDs to order them. */
+/* Comparator for use by vec<const region *>::qsort,
+ using their IDs to order them. */
int
-region::cmp_ptrs (const void *p1, const void *p2)
+region::cmp_ptr_ptr (const void *p1, const void *p2)
{
const region * const *reg1 = (const region * const *)p1;
const region * const *reg2 = (const region * const *)p2;
@@ -824,6 +826,16 @@ root_region::dump_to_pp (pretty_printer *pp, bool simple) const
/* class symbolic_region : public map_region. */
+/* symbolic_region's ctor. */
+
+symbolic_region::symbolic_region (unsigned id, region *parent,
+ const svalue *sval_ptr)
+: region (complexity::from_pair (parent, sval_ptr), id, parent,
+ TREE_TYPE (sval_ptr->get_type ())),
+ m_sval_ptr (sval_ptr)
+{
+}
+
/* Implementation of region::accept vfunc for symbolic_region. */
void
@@ -937,6 +949,11 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
tree init = DECL_INITIAL (m_decl);
if (!init)
{
+ /* If we have an "extern" decl then there may be an initializer in
+ another TU. */
+ if (DECL_EXTERNAL (m_decl))
+ return NULL;
+
/* Implicit initialization to zero; use a compound_svalue for it.
Doing so requires that we have a concrete binding for this region,
which can fail if we have a region with unknown size
@@ -1129,9 +1146,12 @@ string_region::dump_to_pp (pretty_printer *pp, bool simple) const
{
pp_string (pp, "string_region(");
dump_tree (pp, m_string_cst);
- pp_string (pp, " (");
- pp_pointer (pp, m_string_cst);
- pp_string (pp, "))");
+ if (!flag_dump_noaddr)
+ {
+ pp_string (pp, " (");
+ pp_pointer (pp, m_string_cst);
+ pp_string (pp, "))");
+ }
}
}
diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h
new file mode 100644
index 0000000..8430650
--- /dev/null
+++ b/gcc/analyzer/region.h
@@ -0,0 +1,1017 @@
+/* Regions of memory.
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_ANALYZER_REGION_H
+#define GCC_ANALYZER_REGION_H
+
+#include "analyzer/complexity.h"
+
+namespace ana {
+
+/* An enum for discriminating between the different concrete subclasses
+ of region. */
+
+enum region_kind
+{
+ RK_FRAME,
+ RK_GLOBALS,
+ RK_CODE,
+ RK_FUNCTION,
+ RK_LABEL,
+ RK_STACK,
+ RK_HEAP,
+ RK_ROOT,
+ RK_SYMBOLIC,
+ RK_DECL,
+ RK_FIELD,
+ RK_ELEMENT,
+ RK_OFFSET,
+ RK_CAST,
+ RK_HEAP_ALLOCATED,
+ RK_ALLOCA,
+ RK_STRING,
+ RK_UNKNOWN
+};
+
+/* Region and its subclasses.
+
+ The class hierarchy looks like this (using indentation to show
+ inheritance, and with region_kinds shown for the concrete subclasses):
+
+ region
+ space_region
+ frame_region (RK_FRAME)
+ globals_region (RK_GLOBALS)
+ code_region (RK_CODE)
+ stack_region (RK_STACK)
+ heap_region (RK_HEAP)
+ root_region (RK_ROOT)
+ function_region (RK_FUNCTION)
+ label_region (RK_LABEL)
+ symbolic_region (RK_SYMBOLIC)
+ decl_region (RK_DECL),
+ field_region (RK_FIELD)
+ element_region (RK_ELEMENT)
+ offset_region (RK_OFFSET)
+ cast_region (RK_CAST)
+ heap_allocated_region (RK_HEAP_ALLOCATED)
+ alloca_region (RK_ALLOCA)
+ string_region (RK_STRING)
+ unknown_region (RK_UNKNOWN). */
+
+/* Abstract base class for representing ways of accessing chunks of memory.
+
+ Regions form a tree-like hierarchy, with a root region at the base,
+ with memory space regions within it, representing the stack and
+ globals, with frames within the stack, and regions for variables
+ within the frames and the "globals" region. Regions for structs
+ can have subregions for fields. */
+
+class region
+{
+public:
+ virtual ~region ();
+
+ unsigned get_id () const { return m_id; }
+ static int cmp_ids (const region *reg1, const region *reg2);
+
+ virtual enum region_kind get_kind () const = 0;
+ virtual const frame_region *
+ dyn_cast_frame_region () const { return NULL; }
+ virtual const function_region *
+ dyn_cast_function_region () const { return NULL; }
+ virtual const symbolic_region *
+ dyn_cast_symbolic_region () const { return NULL; }
+ virtual const decl_region *
+ dyn_cast_decl_region () const { return NULL; }
+ virtual const field_region *
+ dyn_cast_field_region () const { return NULL; }
+ virtual const element_region *
+ dyn_cast_element_region () const { return NULL; }
+ virtual const offset_region *
+ dyn_cast_offset_region () const { return NULL; }
+ virtual const cast_region *
+ dyn_cast_cast_region () const { return NULL; }
+ virtual const string_region *
+ dyn_cast_string_region () const { return NULL; }
+
+ virtual void accept (visitor *v) const;
+
+ const region *get_parent_region () const { return m_parent; }
+ const region *get_base_region () const;
+ bool base_region_p () const;
+ bool descendent_of_p (const region *elder) const;
+ const frame_region *maybe_get_frame_region () const;
+
+ tree maybe_get_decl () const;
+
+ tree get_type () const { return m_type; }
+
+ void print (const region_model &model,
+ pretty_printer *pp) const;
+ label_text get_desc (bool simple=true) const;
+
+ void dump_to_pp (const region_model &model,
+ pretty_printer *pp,
+ const char *prefix,
+ bool is_last_child) const;
+
+ virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
+ void dump (bool simple) const;
+
+ json::value *to_json () const;
+
+ bool non_null_p () const;
+
+ static int cmp_ptr_ptr (const void *, const void *);
+
+ region_offset get_offset () const;
+ bool get_byte_size (byte_size_t *out) const;
+ bool get_bit_size (bit_size_t *out) const;
+
+ void
+ get_subregions_for_binding (region_model_manager *mgr,
+ bit_offset_t start_bit_offset,
+ bit_size_t size_in_bits,
+ tree type,
+ auto_vec <const region *> *out) const;
+
+ bool symbolic_for_unknown_ptr_p () const;
+
+ const complexity &get_complexity () const { return m_complexity; }
+
+ protected:
+ region (complexity c, unsigned id, const region *parent, tree type);
+
+ private:
+ region_offset calc_offset () const;
+
+ complexity m_complexity;
+ unsigned m_id; // purely for deterministic sorting at this stage, for dumps
+ const region *m_parent;
+ tree m_type;
+
+ mutable region_offset *m_cached_offset;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const region *>::test (const region *)
+{
+ return true;
+}
+
+namespace ana {
+
+/* Abstract subclass of region, for regions that represent an untyped
+ space within memory, such as the stack or the heap. */
+
+class space_region : public region
+{
+protected:
+ space_region (unsigned id, const region *parent)
+ : region (complexity (parent), id, parent, NULL_TREE)
+ {}
+};
+
+/* Concrete space_region subclass, representing a function frame on the stack,
+ to contain the locals.
+ The parent is the stack region; there's also a hierarchy of call-stack
+ prefixes expressed via m_calling_frame.
+ For example, given "oldest" calling "middle" called "newest" we would have
+ - a stack depth of 3
+ - frame (A) for "oldest" with index 0 for depth 1, calling_frame == NULL
+ - frame (B) for "middle" with index 1 for depth 2, calling_frame == (A)
+ - frame (C) for "newest" with index 2 for depth 3, calling_frame == (B)
+ where the parent region for each of the frames is the "stack" region.
+ The index is the count of frames earlier than this in the stack. */
+
+class frame_region : public space_region
+{
+public:
+ /* A support class for uniquifying instances of frame_region. */
+ struct key_t
+ {
+ key_t (const frame_region *calling_frame, function *fun)
+ : m_calling_frame (calling_frame), m_fun (fun)
+ {
+ /* calling_frame can be NULL. */
+ gcc_assert (fun);
+ }
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_calling_frame);
+ hstate.add_ptr (m_fun);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_calling_frame == other.m_calling_frame && m_fun == other.m_fun);
+ }
+
+ void mark_deleted () { m_fun = reinterpret_cast<function *> (1); }
+ void mark_empty () { m_fun = NULL; }
+ bool is_deleted () const
+ {
+ return m_fun == reinterpret_cast<function *> (1);
+ }
+ bool is_empty () const { return m_fun == NULL; }
+
+ const frame_region *m_calling_frame;
+ function *m_fun;
+ };
+
+ frame_region (unsigned id, const region *parent,
+ const frame_region *calling_frame,
+ function *fun, int index)
+ : space_region (id, parent), m_calling_frame (calling_frame),
+ m_fun (fun), m_index (index)
+ {}
+ ~frame_region ();
+
+ /* region vfuncs. */
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_FRAME; }
+ const frame_region * dyn_cast_frame_region () const FINAL OVERRIDE
+ {
+ return this;
+ }
+ void accept (visitor *v) const FINAL OVERRIDE;
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ /* Accessors. */
+ const frame_region *get_calling_frame () const { return m_calling_frame; }
+ function *get_function () const { return m_fun; }
+ int get_index () const { return m_index; }
+ int get_stack_depth () const { return m_index + 1; }
+
+ const decl_region *get_region_for_local (region_model_manager *mgr,
+ tree expr) const;
+
+ unsigned get_num_locals () const { return m_locals.elements (); }
+
+ private:
+ const frame_region *m_calling_frame;
+ function *m_fun;
+ int m_index;
+
+ /* The regions for the decls within this frame are managed by this
+ object, rather than the region_model_manager, to make it a simple
+ lookup by tree. */
+ typedef hash_map<tree, decl_region *> map_t;
+ map_t m_locals;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const frame_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_FRAME;
+}
+
+template <> struct default_hash_traits<frame_region::key_t>
+: public member_function_hash_traits<frame_region::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete space_region subclass, to hold global variables (data and bss). */
+
+class globals_region : public space_region
+{
+ public:
+ globals_region (unsigned id, const region *parent)
+ : space_region (id, parent)
+ {}
+
+ /* region vfuncs. */
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_GLOBALS; }
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const globals_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_GLOBALS;
+}
+
+namespace ana {
+
+/* Concrete space_region subclass, representing the code segment
+ containing functions. */
+
+class code_region : public space_region
+{
+public:
+ code_region (unsigned id, const region *parent)
+ : space_region (id, parent)
+ {}
+
+ /* region vfuncs. */
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_CODE; }
+
+ const region *get_element (region_model *model,
+ const svalue *index,
+ region_model_context *ctxt);
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const code_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_CODE;
+}
+
+namespace ana {
+
+/* Concrete region subclass. A region representing the code for
+ a particular function. */
+
+class function_region : public region
+{
+public:
+ function_region (unsigned id, const code_region *parent, tree fndecl)
+ : region (complexity (parent), id, parent, TREE_TYPE (fndecl)),
+ m_fndecl (fndecl)
+ {
+ gcc_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndecl)));
+ }
+
+ /* region vfuncs. */
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_FUNCTION; }
+ const function_region *
+ dyn_cast_function_region () const FINAL OVERRIDE{ return this; }
+
+ tree get_fndecl () const { return m_fndecl; }
+
+ region *get_element (region_model *model,
+ const svalue *index_sid,
+ region_model_context *ctxt);
+
+private:
+ tree m_fndecl;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const function_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_FUNCTION;
+}
+
+namespace ana {
+
+/* Concrete region subclass. A region representing a particular label
+ within a function. */
+
+class label_region : public region
+{
+public:
+ label_region (unsigned id, const function_region *parent, tree label)
+ : region (complexity (parent), id, parent, NULL_TREE), m_label (label)
+ {
+ gcc_assert (TREE_CODE (label) == LABEL_DECL);
+ }
+
+ /* region vfuncs. */
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_LABEL; }
+
+ tree get_label () const { return m_label; }
+
+private:
+ tree m_label;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const label_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_LABEL;
+}
+
+namespace ana {
+
+/* Concrete space_region subclass representing a stack, containing all stack
+ frames. */
+
+class stack_region : public space_region
+{
+public:
+ stack_region (unsigned id, region *parent)
+ : space_region (id, parent)
+ {}
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_STACK; }
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const stack_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_STACK;
+}
+
+namespace ana {
+
+/* Concrete space_region subclass: a region within which regions can be
+ dynamically allocated. */
+
+class heap_region : public space_region
+{
+public:
+ heap_region (unsigned id, region *parent)
+ : space_region (id, parent)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_HEAP; }
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const heap_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_HEAP;
+}
+
+namespace ana {
+
+/* Concrete region subclass. The root region, containing all regions
+ (either directly, or as descendents).
+ Unique within a region_model_manager. */
+
+class root_region : public region
+{
+public:
+ root_region (unsigned id);
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_ROOT; }
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const root_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_ROOT;
+}
+
+namespace ana {
+
+/* Concrete region subclass: a region to use when dereferencing an unknown
+ pointer. */
+
+class symbolic_region : public region
+{
+public:
+ /* A support class for uniquifying instances of symbolic_region. */
+ struct key_t
+ {
+ key_t (const region *parent, const svalue *sval_ptr)
+ : m_parent (parent), m_sval_ptr (sval_ptr)
+ {
+ gcc_assert (sval_ptr);
+ }
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_parent);
+ hstate.add_ptr (m_sval_ptr);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_parent == other.m_parent && m_sval_ptr == other.m_sval_ptr);
+ }
+
+ void mark_deleted () { m_sval_ptr = reinterpret_cast<const svalue *> (1); }
+ void mark_empty () { m_sval_ptr = NULL; }
+ bool is_deleted () const
+ {
+ return m_sval_ptr == reinterpret_cast<const svalue *> (1);
+ }
+ bool is_empty () const { return m_sval_ptr == NULL; }
+
+ const region *m_parent;
+ const svalue *m_sval_ptr;
+ };
+
+ symbolic_region (unsigned id, region *parent, const svalue *sval_ptr);
+
+ const symbolic_region *
+ dyn_cast_symbolic_region () const FINAL OVERRIDE { return this; }
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_SYMBOLIC; }
+ void accept (visitor *v) const FINAL OVERRIDE;
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ const svalue *get_pointer () const { return m_sval_ptr; }
+
+private:
+ const svalue *m_sval_ptr;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const symbolic_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_SYMBOLIC;
+}
+
+template <> struct default_hash_traits<symbolic_region::key_t>
+: public member_function_hash_traits<symbolic_region::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete region subclass representing the memory occupied by a
+ variable (whether for a global or a local). */
+
+class decl_region : public region
+{
+public:
+ decl_region (unsigned id, const region *parent, tree decl)
+ : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_DECL; }
+ const decl_region *
+ dyn_cast_decl_region () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ tree get_decl () const { return m_decl; }
+ int get_stack_depth () const;
+
+ const svalue *maybe_get_constant_value (region_model_manager *mgr) const;
+ const svalue *get_svalue_for_constructor (tree ctor,
+ region_model_manager *mgr) const;
+ const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
+
+private:
+ tree m_decl;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const decl_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_DECL;
+}
+
+namespace ana {
+
+/* Concrete region subclass representing the memory occupied by a
+ field within a struct or union. */
+
+class field_region : public region
+{
+public:
+ /* A support class for uniquifying instances of field_region. */
+ struct key_t
+ {
+ key_t (const region *parent, tree field)
+ : m_parent (parent), m_field (field)
+ {
+ gcc_assert (field);
+ }
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_parent);
+ hstate.add_ptr (m_field);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_parent == other.m_parent && m_field == other.m_field);
+ }
+
+ void mark_deleted () { m_field = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_field = NULL_TREE; }
+ bool is_deleted () const { return m_field == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_field == NULL_TREE; }
+
+ const region *m_parent;
+ tree m_field;
+ };
+
+ field_region (unsigned id, const region *parent, tree field)
+ : region (complexity (parent), id, parent, TREE_TYPE (field)),
+ m_field (field)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_FIELD; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ const field_region *
+ dyn_cast_field_region () const FINAL OVERRIDE { return this; }
+
+ tree get_field () const { return m_field; }
+
+private:
+ tree m_field;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const field_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_FIELD;
+}
+
+template <> struct default_hash_traits<field_region::key_t>
+: public member_function_hash_traits<field_region::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* An element within an array. */
+
+class element_region : public region
+{
+public:
+ /* A support class for uniquifying instances of element_region. */
+ struct key_t
+ {
+ key_t (const region *parent, tree element_type, const svalue *index)
+ : m_parent (parent), m_element_type (element_type), m_index (index)
+ {
+ gcc_assert (index);
+ }
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_parent);
+ hstate.add_ptr (m_element_type);
+ hstate.add_ptr (m_index);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_parent == other.m_parent
+ && m_element_type == other.m_element_type
+ && m_index == other.m_index);
+ }
+
+ void mark_deleted () { m_index = reinterpret_cast<const svalue *> (1); }
+ void mark_empty () { m_index = NULL; }
+ bool is_deleted () const
+ {
+ return m_index == reinterpret_cast<const svalue *> (1);
+ }
+ bool is_empty () const { return m_index == NULL; }
+
+ const region *m_parent;
+ tree m_element_type;
+ const svalue *m_index;
+ };
+
+ element_region (unsigned id, const region *parent, tree element_type,
+ const svalue *index)
+ : region (complexity::from_pair (parent, index), id, parent, element_type),
+ m_index (index)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_ELEMENT; }
+ const element_region *
+ dyn_cast_element_region () const FINAL OVERRIDE { return this; }
+
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ const svalue *get_index () const { return m_index; }
+
+private:
+ const svalue *m_index;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const element_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_ELEMENT;
+}
+
+template <> struct default_hash_traits<element_region::key_t>
+: public member_function_hash_traits<element_region::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* A byte-offset within another region, for handling pointer arithmetic
+ as a region. */
+
+class offset_region : public region
+{
+public:
+ /* A support class for uniquifying instances of offset_region. */
+ struct key_t
+ {
+ key_t (const region *parent, tree element_type, const svalue *byte_offset)
+ : m_parent (parent), m_element_type (element_type), m_byte_offset (byte_offset)
+ {
+ gcc_assert (byte_offset);
+ }
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_parent);
+ hstate.add_ptr (m_element_type);
+ hstate.add_ptr (m_byte_offset);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_parent == other.m_parent
+ && m_element_type == other.m_element_type
+ && m_byte_offset == other.m_byte_offset);
+ }
+
+ void mark_deleted () { m_byte_offset = reinterpret_cast<const svalue *> (1); }
+ void mark_empty () { m_byte_offset = NULL; }
+ bool is_deleted () const
+ {
+ return m_byte_offset == reinterpret_cast<const svalue *> (1);
+ }
+ bool is_empty () const { return m_byte_offset == NULL; }
+
+ const region *m_parent;
+ tree m_element_type;
+ const svalue *m_byte_offset;
+ };
+
+ offset_region (unsigned id, const region *parent, tree type,
+ const svalue *byte_offset)
+ : region (complexity::from_pair (parent, byte_offset), id, parent, type),
+ m_byte_offset (byte_offset)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_OFFSET; }
+ const offset_region *
+ dyn_cast_offset_region () const FINAL OVERRIDE { return this; }
+
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ const svalue *get_byte_offset () const { return m_byte_offset; }
+
+private:
+ const svalue *m_byte_offset;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const offset_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_OFFSET;
+}
+
+template <> struct default_hash_traits<offset_region::key_t>
+: public member_function_hash_traits<offset_region::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* A region that views another region using a different type. */
+
+class cast_region : public region
+{
+public:
+ /* A support class for uniquifying instances of cast_region. */
+ struct key_t
+ {
+ key_t (const region *original_region, tree type)
+ : m_original_region (original_region), m_type (type)
+ {
+ gcc_assert (type);
+ }
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_original_region);
+ hstate.add_ptr (m_type);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_original_region == other.m_original_region
+ && m_type == other.m_type);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ const region *m_original_region;
+ tree m_type;
+ };
+
+ cast_region (unsigned id, const region *original_region, tree type)
+ : region (complexity (original_region), id,
+ original_region->get_parent_region (), type),
+ m_original_region (original_region)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_CAST; }
+ const cast_region *
+ dyn_cast_cast_region () const FINAL OVERRIDE { return this; }
+ void accept (visitor *v) const FINAL OVERRIDE;
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ const region *get_original_region () const { return m_original_region; }
+
+private:
+ const region *m_original_region;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const cast_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_CAST;
+}
+
+template <> struct default_hash_traits<cast_region::key_t>
+: public member_function_hash_traits<cast_region::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* An untyped region dynamically allocated on the heap via "malloc"
+ or similar. */
+
+class heap_allocated_region : public region
+{
+public:
+ heap_allocated_region (unsigned id, const region *parent)
+ : region (complexity (parent), id, parent, NULL_TREE)
+ {}
+
+ enum region_kind
+ get_kind () const FINAL OVERRIDE { return RK_HEAP_ALLOCATED; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+};
+
+/* An untyped region dynamically allocated on the stack via "alloca". */
+
+class alloca_region : public region
+{
+public:
+ alloca_region (unsigned id, const frame_region *parent)
+ : region (complexity (parent), id, parent, NULL_TREE)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_ALLOCA; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+};
+
+/* A region for a STRING_CST. */
+
+class string_region : public region
+{
+public:
+ string_region (unsigned id, const region *parent, tree string_cst)
+ : region (complexity (parent), id, parent, TREE_TYPE (string_cst)),
+ m_string_cst (string_cst)
+ {}
+
+ const string_region *
+ dyn_cast_string_region () const FINAL OVERRIDE { return this; }
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_STRING; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+ tree get_string_cst () const { return m_string_cst; }
+
+private:
+ tree m_string_cst;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const string_region *>::test (const region *reg)
+{
+ return reg->get_kind () == RK_STRING;
+}
+
+namespace ana {
+
+/* An unknown region, for handling unimplemented tree codes. */
+
+class unknown_region : public region
+{
+public:
+ unknown_region (unsigned id, const region *parent, tree type)
+ : region (complexity (parent), id, parent, type)
+ {}
+
+ enum region_kind get_kind () const FINAL OVERRIDE { return RK_UNKNOWN; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+};
+
+} // namespace ana
+
+#endif /* GCC_ANALYZER_REGION_H */
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index fd12a35..4c38738 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -675,9 +675,9 @@ public:
bool emit (rich_location *rich_loc) FINAL OVERRIDE
{
- /* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */
+ /* CWE-476: NULL Pointer Dereference. */
diagnostic_metadata m;
- m.add_cwe (690);
+ m.add_cwe (476);
return warning_meta (rich_loc, m,
OPT_Wanalyzer_null_dereference,
"dereference of NULL %qE", m_arg);
@@ -723,10 +723,10 @@ public:
bool emit (rich_location *rich_loc) FINAL OVERRIDE
{
- /* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */
+ /* CWE-476: NULL Pointer Dereference. */
auto_diagnostic_group d;
diagnostic_metadata m;
- m.add_cwe (690);
+ m.add_cwe (476);
bool warned;
if (zerop (m_arg))
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
index e4942a6..418d80c 100644
--- a/gcc/analyzer/state-purge.cc
+++ b/gcc/analyzer/state-purge.cc
@@ -209,13 +209,21 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
if (map.get_logger ())
{
map.log ("%qE in %qD is needed to process:", name, fun->decl);
+ /* Log m_points_needing_name, sorting it to avoid churn when comparing
+ dumps. */
+ auto_vec<function_point> points;
for (point_set_t::iterator iter = m_points_needing_name.begin ();
iter != m_points_needing_name.end ();
++iter)
+ points.safe_push (*iter);
+ points.qsort (function_point::cmp_ptr);
+ unsigned i;
+ function_point *point;
+ FOR_EACH_VEC_ELT (points, i, point)
{
map.start_log_line ();
map.get_logger ()->log_partial (" point: ");
- (*iter).print (map.get_logger ()->get_printer (), format (false));
+ point->print (map.get_logger ()->get_printer (), format (false));
map.end_log_line ();
}
}
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 7e91add..05dd47d 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -208,6 +208,23 @@ concrete_binding::overlaps_p (const concrete_binding &other) const
return false;
}
+/* Comparator for use by vec<const concrete_binding *>::qsort. */
+
+int
+concrete_binding::cmp_ptr_ptr (const void *p1, const void *p2)
+{
+ const concrete_binding *b1 = *(const concrete_binding * const *)p1;
+ const concrete_binding *b2 = *(const concrete_binding * const *)p2;
+
+ if (int kind_cmp = b1->get_kind () - b2->get_kind ())
+ return kind_cmp;
+
+ if (int start_cmp = wi::cmps (b1->m_start_bit_offset, b2->m_start_bit_offset))
+ return start_cmp;
+
+ return wi::cmpu (b1->m_size_in_bits, b2->m_size_in_bits);
+}
+
/* class symbolic_binding : public binding_key. */
void
@@ -218,6 +235,20 @@ symbolic_binding::dump_to_pp (pretty_printer *pp, bool simple) const
m_region->dump_to_pp (pp, simple);
}
+/* Comparator for use by vec<const symbolic_binding *>::qsort. */
+
+int
+symbolic_binding::cmp_ptr_ptr (const void *p1, const void *p2)
+{
+ const symbolic_binding *b1 = *(const symbolic_binding * const *)p1;
+ const symbolic_binding *b2 = *(const symbolic_binding * const *)p2;
+
+ if (int kind_cmp = b1->get_kind () - b2->get_kind ())
+ return kind_cmp;
+
+ return region::cmp_ids (b1->get_region (), b2->get_region ());
+}
+
/* The store is oblivious to the types of the svalues bound within
it: any type can get bound at any location.
Simplify any casts before binding.
@@ -409,6 +440,40 @@ binding_map::to_json () const
return map_obj;
}
+/* Comparator for imposing an order on binding_maps. */
+
+int
+binding_map::cmp (const binding_map &map1, const binding_map &map2)
+{
+ if (int count_cmp = map1.elements () - map2.elements ())
+ return count_cmp;
+
+ auto_vec <const binding_key *> keys1 (map1.elements ());
+ for (map_t::iterator iter = map1.begin ();
+ iter != map1.end (); ++iter)
+ keys1.quick_push ((*iter).first);
+ keys1.qsort (binding_key::cmp_ptrs);
+
+ auto_vec <const binding_key *> keys2 (map2.elements ());
+ for (map_t::iterator iter = map2.begin ();
+ iter != map2.end (); ++iter)
+ keys2.quick_push ((*iter).first);
+ keys2.qsort (binding_key::cmp_ptrs);
+
+ for (size_t i = 0; i < keys1.length (); i++)
+ {
+ const binding_key *k1 = keys1[i];
+ const binding_key *k2 = keys2[i];
+ if (int key_cmp = binding_key::cmp (k1, k2))
+ return key_cmp;
+ gcc_assert (k1 == k2);
+ if (int sval_cmp = svalue::cmp_ptr (map1.get (k1), map2.get (k2)))
+ return sval_cmp;
+ }
+
+ return 0;
+}
+
/* Get the child region of PARENT_REG based upon INDEX within a
CONSTRUCTOR. */
@@ -1512,7 +1577,7 @@ get_sorted_parent_regions (auto_vec<const region *> *out,
out->safe_push (*iter);
/* Sort OUT. */
- out->qsort (region::cmp_ptrs);
+ out->qsort (region::cmp_ptr_ptr);
}
/* Dump a representation of this store to PP, using SIMPLE to control how
@@ -1532,7 +1597,7 @@ store::dump_to_pp (pretty_printer *pp, bool simple, bool multiline,
const region *base_reg = (*iter).first;
base_regions.safe_push (base_reg);
}
- base_regions.qsort (region::cmp_ptrs);
+ base_regions.qsort (region::cmp_ptr_ptr);
/* Gather clusters, organize by parent region, so that we can group
together locals, globals, etc. */
@@ -1653,7 +1718,7 @@ store::to_json () const
const region *base_reg = (*iter).first;
base_regions.safe_push (base_reg);
}
- base_regions.qsort (region::cmp_ptrs);
+ base_regions.qsort (region::cmp_ptr_ptr);
/* Gather clusters, organize by parent region, so that we can group
together locals, globals, etc. */
@@ -1991,10 +2056,19 @@ store::can_merge_p (const store *store_a, const store *store_b,
base_regions.add (base_reg_b);
}
+ /* Sort the base regions before considering them. This ought not to
+ affect the results, but can affect which types UNKNOWN_REGIONs are
+ created for in a run; sorting them thus avoids minor differences
+ in logfiles. */
+ auto_vec<const region *> vec_base_regions (base_regions.elements ());
for (hash_set<const region *>::iterator iter = base_regions.begin ();
iter != base_regions.end (); ++iter)
+ vec_base_regions.quick_push (*iter);
+ vec_base_regions.qsort (region::cmp_ptr_ptr);
+ unsigned i;
+ const region *base_reg;
+ FOR_EACH_VEC_ELT (vec_base_regions, i, base_reg)
{
- const region *base_reg = *iter;
const binding_cluster *cluster_a = store_a->get_cluster (base_reg);
const binding_cluster *cluster_b = store_b->get_cluster (base_reg);
/* At least one of cluster_a and cluster_b must be non-NULL. */
diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 0f4e7ab..8054b34 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -237,6 +237,8 @@ public:
bool overlaps_p (const concrete_binding &other) const;
+ static int cmp_ptr_ptr (const void *, const void *);
+
private:
bit_offset_t m_start_bit_offset;
bit_size_t m_size_in_bits;
@@ -269,7 +271,7 @@ public:
hashval_t hash () const
{
- return (binding_key::impl_hash () ^ (long)m_region);
+ return (binding_key::impl_hash () ^ (intptr_t)m_region);
}
bool operator== (const symbolic_binding &other) const
{
@@ -282,6 +284,8 @@ public:
const region *get_region () const { return m_region; }
+ static int cmp_ptr_ptr (const void *, const void *);
+
private:
const region *m_region;
};
@@ -346,6 +350,8 @@ public:
bool apply_ctor_to_region (const region *parent_reg, tree ctor,
region_model_manager *mgr);
+ static int cmp (const binding_map &map1, const binding_map &map2);
+
private:
bool apply_ctor_val_to_range (const region *parent_reg,
region_model_manager *mgr,
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index 735c4a3..37f143c 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -90,7 +90,8 @@ supergraph_call_edge (function *fun, gimple *stmt)
/* supergraph's ctor. Walk the callgraph, building supernodes for each
CFG basic block, splitting the basic blocks at callsites. Join
together the supernodes with interprocedural and intraprocedural
- superedges as appropriate. */
+ superedges as appropriate.
+ Assign UIDs to the gimple stmts. */
supergraph::supergraph (logger *logger)
{
@@ -98,8 +99,10 @@ supergraph::supergraph (logger *logger)
LOG_FUNC (logger);
- /* First pass: make supernodes. */
+ /* First pass: make supernodes (and assign UIDs to the gimple stmts). */
{
+ unsigned next_uid = 0;
+
/* Sort the cgraph_nodes? */
cgraph_node *node;
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
@@ -124,6 +127,7 @@ supergraph::supergraph (logger *logger)
{
gimple *stmt = gsi_stmt (gpi);
m_stmt_to_node_t.put (stmt, node_for_stmts);
+ stmt->uid = next_uid++;
}
/* Append statements from BB to the current supernode, splitting
@@ -135,6 +139,7 @@ supergraph::supergraph (logger *logger)
gimple *stmt = gsi_stmt (gsi);
node_for_stmts->m_stmts.safe_push (stmt);
m_stmt_to_node_t.put (stmt, node_for_stmts);
+ stmt->uid = next_uid++;
if (cgraph_edge *edge = supergraph_call_edge (fun, stmt))
{
m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index ae3b678..e930452 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -52,42 +52,13 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/call-string.h"
#include "analyzer/program-point.h"
#include "analyzer/store.h"
+#include "analyzer/svalue.h"
#include "analyzer/region-model.h"
#if ENABLE_ANALYZER
namespace ana {
-/* struct complexity. */
-
-/* Get complexity for a new node that references REG
- (the complexity of REG, plus one for the new node). */
-
-complexity::complexity (const region *reg)
-: m_num_nodes (reg->get_complexity ().m_num_nodes + 1),
- m_max_depth (reg->get_complexity ().m_max_depth + 1)
-{
-}
-
-/* Get complexity for a new node that references SVAL.
- (the complexity of SVAL, plus one for the new node). */
-
-complexity::complexity (const svalue *sval)
-: m_num_nodes (sval->get_complexity ().m_num_nodes + 1),
- m_max_depth (sval->get_complexity ().m_max_depth + 1)
-{
-}
-
-/* Get complexity for a new node that references nodes with complexity
- C1 and C2. */
-
-complexity
-complexity::from_pair (const complexity &c1, const complexity &c2)
-{
- return complexity (c1.m_num_nodes + c2.m_num_nodes + 1,
- MAX (c1.m_max_depth, c2.m_max_depth) + 1);
-}
-
/* class svalue and its various subclasses. */
/* class svalue. */
@@ -298,6 +269,215 @@ svalue::implicitly_live_p (const svalue_set &, const region_model *) const
return false;
}
+/* Comparator for imposing a deterministic order on constants that are
+ of the same type. */
+
+static int
+cmp_cst (const_tree cst1, const_tree cst2)
+{
+ gcc_assert (TREE_TYPE (cst1) == TREE_TYPE (cst2));
+ gcc_assert (TREE_CODE (cst1) == TREE_CODE (cst2));
+ switch (TREE_CODE (cst1))
+ {
+ default:
+ gcc_unreachable ();
+ case INTEGER_CST:
+ return tree_int_cst_compare (cst1, cst2);
+ case STRING_CST:
+ return strcmp (TREE_STRING_POINTER (cst1),
+ TREE_STRING_POINTER (cst2));
+ case REAL_CST:
+ /* Impose an arbitrary but deterministic order. */
+ return memcmp (TREE_REAL_CST_PTR (cst1),
+ TREE_REAL_CST_PTR (cst2),
+ sizeof (real_value));
+ case COMPLEX_CST:
+ if (int cmp_real = cmp_cst (TREE_REALPART (cst1), TREE_REALPART (cst2)))
+ return cmp_real;
+ return cmp_cst (TREE_IMAGPART (cst1), TREE_IMAGPART (cst2));
+ case VECTOR_CST:
+ if (int cmp_log2_npatterns
+ = ((int)VECTOR_CST_LOG2_NPATTERNS (cst1)
+ - (int)VECTOR_CST_LOG2_NPATTERNS (cst2)))
+ return cmp_log2_npatterns;
+ if (int cmp_nelts_per_pattern
+ = ((int)VECTOR_CST_NELTS_PER_PATTERN (cst1)
+ - (int)VECTOR_CST_NELTS_PER_PATTERN (cst2)))
+ return cmp_nelts_per_pattern;
+ unsigned encoded_nelts = vector_cst_encoded_nelts (cst1);
+ for (unsigned i = 0; i < encoded_nelts; i++)
+ if (int el_cmp = cmp_cst (VECTOR_CST_ENCODED_ELT (cst1, i),
+ VECTOR_CST_ENCODED_ELT (cst2, i)))
+ return el_cmp;
+ return 0;
+ }
+}
+
+/* Comparator for imposing a deterministic order on svalues. */
+
+int
+svalue::cmp_ptr (const svalue *sval1, const svalue *sval2)
+{
+ if (sval1 == sval2)
+ return 0;
+ if (int cmp_kind = sval1->get_kind () - sval2->get_kind ())
+ return cmp_kind;
+ int t1 = sval1->get_type () ? TYPE_UID (sval1->get_type ()) : -1;
+ int t2 = sval2->get_type () ? TYPE_UID (sval2->get_type ()) : -1;
+ if (int cmp_type = t1 - t2)
+ return cmp_type;
+ switch (sval1->get_kind ())
+ {
+ default:
+ gcc_unreachable ();
+ case SK_REGION:
+ {
+ const region_svalue *region_sval1 = (const region_svalue *)sval1;
+ const region_svalue *region_sval2 = (const region_svalue *)sval2;
+ return region::cmp_ids (region_sval1->get_pointee (),
+ region_sval2->get_pointee ());
+ }
+ break;
+ case SK_CONSTANT:
+ {
+ const constant_svalue *constant_sval1 = (const constant_svalue *)sval1;
+ const constant_svalue *constant_sval2 = (const constant_svalue *)sval2;
+ const_tree cst1 = constant_sval1->get_constant ();
+ const_tree cst2 = constant_sval2->get_constant ();
+ return cmp_cst (cst1, cst2);
+ }
+ break;
+ case SK_UNKNOWN:
+ {
+ gcc_assert (sval1 == sval2);
+ return 0;
+ }
+ break;
+ case SK_POISONED:
+ {
+ const poisoned_svalue *poisoned_sval1 = (const poisoned_svalue *)sval1;
+ const poisoned_svalue *poisoned_sval2 = (const poisoned_svalue *)sval2;
+ return (poisoned_sval1->get_poison_kind ()
+ - poisoned_sval2->get_poison_kind ());
+ }
+ break;
+ case SK_SETJMP:
+ {
+ const setjmp_svalue *setjmp_sval1 = (const setjmp_svalue *)sval1;
+ const setjmp_svalue *setjmp_sval2 = (const setjmp_svalue *)sval2;
+ const setjmp_record &rec1 = setjmp_sval1->get_setjmp_record ();
+ const setjmp_record &rec2 = setjmp_sval2->get_setjmp_record ();
+ return setjmp_record::cmp (rec1, rec2);
+ }
+ break;
+ case SK_INITIAL:
+ {
+ const initial_svalue *initial_sval1 = (const initial_svalue *)sval1;
+ const initial_svalue *initial_sval2 = (const initial_svalue *)sval2;
+ return region::cmp_ids (initial_sval1->get_region (),
+ initial_sval2->get_region ());
+ }
+ break;
+ case SK_UNARYOP:
+ {
+ const unaryop_svalue *unaryop_sval1 = (const unaryop_svalue *)sval1;
+ const unaryop_svalue *unaryop_sval2 = (const unaryop_svalue *)sval2;
+ if (int op_cmp = unaryop_sval1->get_op () - unaryop_sval2->get_op ())
+ return op_cmp;
+ return svalue::cmp_ptr (unaryop_sval1->get_arg (),
+ unaryop_sval2->get_arg ());
+ }
+ break;
+ case SK_BINOP:
+ {
+ const binop_svalue *binop_sval1 = (const binop_svalue *)sval1;
+ const binop_svalue *binop_sval2 = (const binop_svalue *)sval2;
+ if (int op_cmp = binop_sval1->get_op () - binop_sval2->get_op ())
+ return op_cmp;
+ if (int arg0_cmp = svalue::cmp_ptr (binop_sval1->get_arg0 (),
+ binop_sval2->get_arg0 ()))
+ return arg0_cmp;
+ return svalue::cmp_ptr (binop_sval1->get_arg1 (),
+ binop_sval2->get_arg1 ());
+ }
+ break;
+ case SK_SUB:
+ {
+ const sub_svalue *sub_sval1 = (const sub_svalue *)sval1;
+ const sub_svalue *sub_sval2 = (const sub_svalue *)sval2;
+ if (int parent_cmp = svalue::cmp_ptr (sub_sval1->get_parent (),
+ sub_sval2->get_parent ()))
+ return parent_cmp;
+ return region::cmp_ids (sub_sval1->get_subregion (),
+ sub_sval2->get_subregion ());
+ }
+ break;
+ case SK_UNMERGEABLE:
+ {
+ const unmergeable_svalue *unmergeable_sval1
+ = (const unmergeable_svalue *)sval1;
+ const unmergeable_svalue *unmergeable_sval2
+ = (const unmergeable_svalue *)sval2;
+ return svalue::cmp_ptr (unmergeable_sval1->get_arg (),
+ unmergeable_sval2->get_arg ());
+ }
+ break;
+ case SK_PLACEHOLDER:
+ {
+ const placeholder_svalue *placeholder_sval1
+ = (const placeholder_svalue *)sval1;
+ const placeholder_svalue *placeholder_sval2
+ = (const placeholder_svalue *)sval2;
+ return strcmp (placeholder_sval1->get_name (),
+ placeholder_sval2->get_name ());
+ }
+ break;
+ case SK_WIDENING:
+ {
+ const widening_svalue *widening_sval1 = (const widening_svalue *)sval1;
+ const widening_svalue *widening_sval2 = (const widening_svalue *)sval2;
+ if (int point_cmp = function_point::cmp (widening_sval1->get_point (),
+ widening_sval2->get_point ()))
+ return point_cmp;
+ if (int base_cmp = svalue::cmp_ptr (widening_sval1->get_base_svalue (),
+ widening_sval2->get_base_svalue ()))
+ return base_cmp;
+ return svalue::cmp_ptr (widening_sval1->get_iter_svalue (),
+ widening_sval2->get_iter_svalue ());
+ }
+ break;
+ case SK_COMPOUND:
+ {
+ const compound_svalue *compound_sval1 = (const compound_svalue *)sval1;
+ const compound_svalue *compound_sval2 = (const compound_svalue *)sval2;
+ return binding_map::cmp (compound_sval1->get_map (),
+ compound_sval2->get_map ());
+ }
+ break;
+ case SK_CONJURED:
+ {
+ const conjured_svalue *conjured_sval1 = (const conjured_svalue *)sval1;
+ const conjured_svalue *conjured_sval2 = (const conjured_svalue *)sval2;
+ if (int stmt_cmp = (conjured_sval1->get_stmt ()->uid
+ - conjured_sval2->get_stmt ()->uid))
+ return stmt_cmp;
+ return region::cmp_ids (conjured_sval1->get_id_region (),
+ conjured_sval2->get_id_region ());
+ }
+ break;
+ }
+}
+
+/* Comparator for use by vec<const svalue *>::qsort. */
+
+int
+svalue::cmp_ptr_ptr (const void *p1, const void *p2)
+{
+ const svalue *sval1 = *(const svalue * const *)p1;
+ const svalue *sval2 = *(const svalue * const *)p2;
+ return cmp_ptr (sval1, sval2);
+}
+
/* class region_svalue : public svalue. */
/* Implementation of svalue::dump_to_pp vfunc for region_svalue. */
diff --git a/gcc/analyzer/svalue.h b/gcc/analyzer/svalue.h
new file mode 100644
index 0000000..b519d26
--- /dev/null
+++ b/gcc/analyzer/svalue.h
@@ -0,0 +1,1150 @@
+/* Symbolic values.
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_ANALYZER_SVALUE_H
+#define GCC_ANALYZER_SVALUE_H
+
+#include "analyzer/complexity.h"
+
+using namespace ana;
+
+namespace ana {
+
+/* An enum for discriminating between the different concrete subclasses
+ of svalue. */
+
+enum svalue_kind
+{
+ SK_REGION,
+ SK_CONSTANT,
+ SK_UNKNOWN,
+ SK_POISONED,
+ SK_SETJMP,
+ SK_INITIAL,
+ SK_UNARYOP,
+ SK_BINOP,
+ SK_SUB,
+ SK_UNMERGEABLE,
+ SK_PLACEHOLDER,
+ SK_WIDENING,
+ SK_COMPOUND,
+ SK_CONJURED
+};
+
+/* svalue and its subclasses.
+
+ The class hierarchy looks like this (using indentation to show
+ inheritance, and with svalue_kinds shown for the concrete subclasses):
+
+ svalue
+ region_svalue (SK_REGION): a pointer to a region
+ constant_svalue (SK_CONSTANT): a constant
+ unknown_svalue (SK_UNKNOWN): an unknowable value
+ poisoned_svalue (SK_POISONED): a unusable value (undefined)
+ setjmp_svalue (SK_SETJMP): a setjmp/longjmp buffer
+ initial_svalue (SK_INITIAL): the initial value of a region
+ unaryop_svalue (SK_UNARYOP): unary operation on another svalue
+ binop_svalue (SK_BINOP): binary operation on two svalues
+ sub_svalue (SK_SUB): the result of accessing a subregion
+ unmergeable_svalue (SK_UNMERGEABLE): a value that is so interesting
+ from a control-flow perspective that it can inhibit state-merging
+ placeholder_svalue (SK_PLACEHOLDER): for use in selftests.
+ widening_svalue (SK_WIDENING): a merger of two svalues (possibly
+ in an iteration).
+ compound_svalue (SK_COMPOUND): a mapping of bit-ranges to svalues
+ conjured_svalue (SK_CONJURED): a value arising from a stmt. */
+
+/* An abstract base class representing a value held by a region of memory. */
+
+class svalue
+{
+public:
+ virtual ~svalue () {}
+
+ tree get_type () const { return m_type; }
+
+ virtual enum svalue_kind get_kind () const = 0;
+
+ void print (const region_model &model,
+ pretty_printer *pp) const;
+
+ virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
+ void dump (bool simple=true) const;
+ label_text get_desc (bool simple=true) const;
+
+ json::value *to_json () const;
+
+ virtual const region_svalue *
+ dyn_cast_region_svalue () const { return NULL; }
+ virtual const constant_svalue *
+ dyn_cast_constant_svalue () const { return NULL; }
+ virtual const poisoned_svalue *
+ dyn_cast_poisoned_svalue () const { return NULL; }
+ virtual const setjmp_svalue *
+ dyn_cast_setjmp_svalue () const { return NULL; }
+ virtual const initial_svalue *
+ dyn_cast_initial_svalue () const { return NULL; }
+ virtual const unaryop_svalue *
+ dyn_cast_unaryop_svalue () const { return NULL; }
+ virtual const binop_svalue *
+ dyn_cast_binop_svalue () const { return NULL; }
+ virtual const sub_svalue *
+ dyn_cast_sub_svalue () const { return NULL; }
+ virtual const unmergeable_svalue *
+ dyn_cast_unmergeable_svalue () const { return NULL; }
+ virtual const widening_svalue *
+ dyn_cast_widening_svalue () const { return NULL; }
+ virtual const compound_svalue *
+ dyn_cast_compound_svalue () const { return NULL; }
+ virtual const conjured_svalue *
+ dyn_cast_conjured_svalue () const { return NULL; }
+
+ tree maybe_get_constant () const;
+ const svalue *maybe_undo_cast () const;
+ const svalue *unwrap_any_unmergeable () const;
+
+ const svalue *can_merge_p (const svalue *other,
+ region_model_manager *mgr,
+ model_merger *merger) const;
+
+ const complexity &get_complexity () const { return m_complexity; }
+
+ virtual void accept (visitor *v) const = 0;
+
+ bool live_p (const svalue_set &live_svalues,
+ const region_model *model) const;
+ virtual bool implicitly_live_p (const svalue_set &live_svalues,
+ const region_model *model) const;
+
+ static int cmp_ptr (const svalue *, const svalue *);
+ static int cmp_ptr_ptr (const void *, const void *);
+
+ protected:
+ svalue (complexity c, tree type)
+ : m_complexity (c), m_type (type)
+ {}
+
+ private:
+ complexity m_complexity;
+ tree m_type;
+};
+
+/* Concrete subclass of svalue representing a pointer value that points to
+ a known region */
+
+class region_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of region_svalue. */
+ struct key_t
+ {
+ key_t (tree type, const region *reg)
+ : m_type (type), m_reg (reg)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_type);
+ hstate.add_ptr (m_reg);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type && m_reg == other.m_reg);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ tree m_type;
+ const region *m_reg;
+ };
+
+ region_svalue (tree type, const region *reg)
+ : svalue (complexity (reg), type),
+ m_reg (reg)
+ {
+ gcc_assert (m_reg != NULL);
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_REGION; }
+ const region_svalue *
+ dyn_cast_region_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ const region * get_pointee () const { return m_reg; }
+
+ static tristate eval_condition (const region_svalue *lhs_ptr,
+ enum tree_code op,
+ const region_svalue *rhs_ptr);
+
+ private:
+ const region *m_reg;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const region_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_REGION;
+}
+
+template <> struct default_hash_traits<region_svalue::key_t>
+: public member_function_hash_traits<region_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete subclass of svalue representing a specific constant value. */
+
+class constant_svalue : public svalue
+{
+public:
+ constant_svalue (tree cst_expr)
+ : svalue (complexity (1, 1), TREE_TYPE (cst_expr)), m_cst_expr (cst_expr)
+ {
+ gcc_assert (cst_expr);
+ gcc_assert (CONSTANT_CLASS_P (cst_expr));
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_CONSTANT; }
+ const constant_svalue *
+ dyn_cast_constant_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+ bool implicitly_live_p (const svalue_set &,
+ const region_model *) const FINAL OVERRIDE;
+
+ tree get_constant () const { return m_cst_expr; }
+ static tristate eval_condition (const constant_svalue *lhs,
+ enum tree_code op,
+ const constant_svalue *rhs);
+
+ private:
+ tree m_cst_expr;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const constant_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_CONSTANT;
+}
+
+namespace ana {
+
+/* Concrete subclass of svalue representing an unknowable value, the bottom
+ value when thinking of svalues as a lattice.
+ This is a singleton (w.r.t. its manager): there is a single unknown_svalue
+ per type. Self-comparisons of such instances yield "unknown". */
+
+class unknown_svalue : public svalue
+{
+public:
+ unknown_svalue (tree type)
+ : svalue (complexity (1, 1), type)
+ {}
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_UNKNOWN; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+};
+
+/* An enum describing a particular kind of "poisoned" value. */
+
+enum poison_kind
+{
+ /* For use to describe freed memory. */
+ POISON_KIND_FREED,
+
+ /* For use on pointers to regions within popped stack frames. */
+ POISON_KIND_POPPED_STACK
+};
+
+extern const char *poison_kind_to_str (enum poison_kind);
+
+/* Concrete subclass of svalue representing a value that should not
+ be used (e.g. uninitialized memory, freed memory). */
+
+class poisoned_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of poisoned_svalue. */
+ struct key_t
+ {
+ key_t (enum poison_kind kind, tree type)
+ : m_kind (kind), m_type (type)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_int (m_kind);
+ hstate.add_ptr (m_type);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_kind == other.m_kind && m_type == other.m_type);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ enum poison_kind m_kind;
+ tree m_type;
+ };
+
+ poisoned_svalue (enum poison_kind kind, tree type)
+ : svalue (complexity (1, 1), type), m_kind (kind) {}
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_POISONED; }
+ const poisoned_svalue *
+ dyn_cast_poisoned_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ enum poison_kind get_poison_kind () const { return m_kind; }
+
+ private:
+ enum poison_kind m_kind;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const poisoned_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_POISONED;
+}
+
+template <> struct default_hash_traits<poisoned_svalue::key_t>
+: public member_function_hash_traits<poisoned_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* A bundle of information recording a setjmp/sigsetjmp call, corresponding
+ roughly to a jmp_buf. */
+
+struct setjmp_record
+{
+ setjmp_record (const exploded_node *enode,
+ const gcall *setjmp_call)
+ : m_enode (enode), m_setjmp_call (setjmp_call)
+ {
+ }
+
+ bool operator== (const setjmp_record &other) const
+ {
+ return (m_enode == other.m_enode
+ && m_setjmp_call == other.m_setjmp_call);
+ }
+
+ void add_to_hash (inchash::hash *hstate) const
+ {
+ hstate->add_ptr (m_enode);
+ hstate->add_ptr (m_setjmp_call);
+ }
+
+ static int cmp (const setjmp_record &rec1, const setjmp_record &rec2);
+
+ const exploded_node *m_enode;
+ const gcall *m_setjmp_call;
+};
+
+/* Concrete subclass of svalue representing buffers for setjmp/sigsetjmp,
+ so that longjmp/siglongjmp can potentially "return" to an entirely
+ different function. */
+
+class setjmp_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of poisoned_svalue. */
+ struct key_t
+ {
+ key_t (const setjmp_record &record, tree type)
+ : m_record (record), m_type (type)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ m_record.add_to_hash (&hstate);
+ hstate.add_ptr (m_type);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_record == other.m_record && m_type == other.m_type);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ setjmp_record m_record;
+ tree m_type;
+ };
+
+ setjmp_svalue (const setjmp_record &setjmp_record,
+ tree type)
+ : svalue (complexity (1, 1), type), m_setjmp_record (setjmp_record)
+ {}
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_SETJMP; }
+ const setjmp_svalue *
+ dyn_cast_setjmp_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ int get_enode_index () const;
+
+ const setjmp_record &get_setjmp_record () const { return m_setjmp_record; }
+
+ private:
+ setjmp_record m_setjmp_record;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const setjmp_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_SETJMP;
+}
+
+template <> struct default_hash_traits<setjmp_svalue::key_t>
+: public member_function_hash_traits<setjmp_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete subclass of svalue representing the initial value of a
+ specific region.
+
+ This represents the initial value at the start of the analysis path,
+ as opposed to the first time the region is accessed during the path.
+ Hence as soon as we have a call to an unknown function, all previously
+ unmodelled globals become implicitly "unknown" rathen than "initial". */
+
+class initial_svalue : public svalue
+{
+public:
+ initial_svalue (tree type, const region *reg)
+ : svalue (complexity (reg), type), m_reg (reg)
+ {
+ gcc_assert (m_reg != NULL);
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_INITIAL; }
+ const initial_svalue *
+ dyn_cast_initial_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+ bool implicitly_live_p (const svalue_set &,
+ const region_model *) const FINAL OVERRIDE;
+
+ const region *get_region () const { return m_reg; }
+
+ private:
+ const region *m_reg;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const initial_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_INITIAL;
+}
+
+namespace ana {
+
+/* Concrete subclass of svalue representing a unary operation on
+ another svalues (e.g. a cast). */
+
+class unaryop_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of unaryop_svalue. */
+ struct key_t
+ {
+ key_t (tree type, enum tree_code op, const svalue *arg)
+ : m_type (type), m_op (op), m_arg (arg)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_type);
+ hstate.add_int (m_op);
+ hstate.add_ptr (m_arg);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type
+ && m_op == other.m_op
+ && m_arg == other.m_arg);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ tree m_type;
+ enum tree_code m_op;
+ const svalue *m_arg;
+ };
+
+ unaryop_svalue (tree type, enum tree_code op, const svalue *arg)
+ : svalue (complexity (arg), type), m_op (op), m_arg (arg)
+ {
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_UNARYOP; }
+ const unaryop_svalue *
+ dyn_cast_unaryop_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+ bool implicitly_live_p (const svalue_set &,
+ const region_model *) const FINAL OVERRIDE;
+
+ enum tree_code get_op () const { return m_op; }
+ const svalue *get_arg () const { return m_arg; }
+
+ private:
+ enum tree_code m_op;
+ const svalue *m_arg;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const unaryop_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_UNARYOP;
+}
+
+template <> struct default_hash_traits<unaryop_svalue::key_t>
+: public member_function_hash_traits<unaryop_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete subclass of svalue representing a binary operation of
+ two svalues. */
+
+class binop_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of binop_svalue. */
+ struct key_t
+ {
+ key_t (tree type, enum tree_code op,
+ const svalue *arg0, const svalue *arg1)
+ : m_type (type), m_op (op), m_arg0 (arg0), m_arg1 (arg1)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_type);
+ hstate.add_int (m_op);
+ hstate.add_ptr (m_arg0);
+ hstate.add_ptr (m_arg1);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type
+ && m_op == other.m_op
+ && m_arg0 == other.m_arg0
+ && m_arg1 == other.m_arg1);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ tree m_type;
+ enum tree_code m_op;
+ const svalue *m_arg0;
+ const svalue *m_arg1;
+ };
+
+ binop_svalue (tree type, enum tree_code op,
+ const svalue *arg0, const svalue *arg1)
+ : svalue (complexity::from_pair (arg0->get_complexity (),
+ arg1->get_complexity ()),
+ type),
+ m_op (op), m_arg0 (arg0), m_arg1 (arg1)
+ {
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_BINOP; }
+ const binop_svalue *dyn_cast_binop_svalue () const FINAL OVERRIDE
+ {
+ return this;
+ }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+ bool implicitly_live_p (const svalue_set &,
+ const region_model *) const FINAL OVERRIDE;
+
+ enum tree_code get_op () const { return m_op; }
+ const svalue *get_arg0 () const { return m_arg0; }
+ const svalue *get_arg1 () const { return m_arg1; }
+
+ private:
+ enum tree_code m_op;
+ const svalue *m_arg0;
+ const svalue *m_arg1;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const binop_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_BINOP;
+}
+
+template <> struct default_hash_traits<binop_svalue::key_t>
+: public member_function_hash_traits<binop_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete subclass of svalue representing the result of accessing a subregion
+ of another svalue (the value of a component/field of a struct, or an element
+ from an array). */
+
+class sub_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of sub_svalue. */
+ struct key_t
+ {
+ key_t (tree type, const svalue *parent_svalue, const region *subregion)
+ : m_type (type), m_parent_svalue (parent_svalue), m_subregion (subregion)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_type);
+ hstate.add_ptr (m_parent_svalue);
+ hstate.add_ptr (m_subregion);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type
+ && m_parent_svalue == other.m_parent_svalue
+ && m_subregion == other.m_subregion);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ tree m_type;
+ const svalue *m_parent_svalue;
+ const region *m_subregion;
+ };
+ sub_svalue (tree type, const svalue *parent_svalue,
+ const region *subregion);
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_SUB; }
+ const sub_svalue *dyn_cast_sub_svalue () const FINAL OVERRIDE
+ {
+ return this;
+ }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+ bool implicitly_live_p (const svalue_set &,
+ const region_model *) const FINAL OVERRIDE;
+
+ const svalue *get_parent () const { return m_parent_svalue; }
+ const region *get_subregion () const { return m_subregion; }
+
+ private:
+ const svalue *m_parent_svalue;
+ const region *m_subregion;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const sub_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_SUB;
+}
+
+template <> struct default_hash_traits<sub_svalue::key_t>
+: public member_function_hash_traits<sub_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete subclass of svalue: decorate another svalue,
+ so that the resulting svalue can be identified as being
+ "interesting to control flow".
+ For example, consider the return value from setjmp. We
+ don't want to merge states in which the result is 0 with
+ those in which the result is non-zero. By using an
+ unmergeable_svalue for the result, we can inhibit such merges
+ and have separate exploded nodes for those states, keeping
+ the first and second returns from setjmp distinct in the exploded
+ graph. */
+
+class unmergeable_svalue : public svalue
+{
+public:
+ unmergeable_svalue (const svalue *arg)
+ : svalue (complexity (arg), arg->get_type ()), m_arg (arg)
+ {
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_UNMERGEABLE; }
+ const unmergeable_svalue *
+ dyn_cast_unmergeable_svalue () const FINAL OVERRIDE { return this; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+ bool implicitly_live_p (const svalue_set &,
+ const region_model *) const FINAL OVERRIDE;
+
+ const svalue *get_arg () const { return m_arg; }
+
+ private:
+ const svalue *m_arg;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <const unmergeable_svalue *>::test (const svalue *sval)
+{
+ return sval->get_kind () == SK_UNMERGEABLE;
+}
+
+namespace ana {
+
+/* Concrete subclass of svalue for use in selftests, where
+ we want a specific but unknown svalue.
+ Unlike other svalue subclasses these aren't managed by
+ region_model_manager. */
+
+class placeholder_svalue : public svalue
+{
+public:
+ placeholder_svalue (tree type, const char *name)
+ : svalue (complexity (1, 1), type), m_name (name)
+ {
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_PLACEHOLDER; }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ const char *get_name () const { return m_name; }
+
+ private:
+ const char *m_name;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <placeholder_svalue *>::test (svalue *sval)
+{
+ return sval->get_kind () == SK_PLACEHOLDER;
+}
+
+namespace ana {
+
+/* Concrete subclass of svalue representing a "widening" seen when merging
+ states, widening from a base value to {base value, iter value} and thus
+ representing a possible fixed point in an iteration from the base to
+ +ve infinity, or -ve infinity, and thus useful for representing a value
+ within a loop.
+ We also need to capture the program_point at which the merger happens,
+ so that distinguish between different iterators, and thus handle
+ nested loops. (currently we capture the function_point instead, for
+ simplicity of hashing). */
+
+class widening_svalue : public svalue
+{
+public:
+ /* A support class for uniquifying instances of widening_svalue. */
+ struct key_t
+ {
+ key_t (tree type, const program_point &point,
+ const svalue *base_sval, const svalue *iter_sval)
+ : m_type (type), m_point (point.get_function_point ()),
+ m_base_sval (base_sval), m_iter_sval (iter_sval)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_base_sval);
+ hstate.add_ptr (m_iter_sval);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type
+ && m_point == other.m_point
+ && m_base_sval == other.m_base_sval
+ && m_iter_sval == other.m_iter_sval);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ tree m_type;
+ function_point m_point;
+ const svalue *m_base_sval;
+ const svalue *m_iter_sval;
+ };
+
+ enum direction_t
+ {
+ DIR_ASCENDING,
+ DIR_DESCENDING,
+ DIR_UNKNOWN
+ };
+
+ widening_svalue (tree type, const program_point &point,
+ const svalue *base_sval, const svalue *iter_sval)
+ : svalue (complexity::from_pair (base_sval->get_complexity (),
+ iter_sval->get_complexity ()),
+ type),
+ m_point (point.get_function_point ()),
+ m_base_sval (base_sval), m_iter_sval (iter_sval)
+ {
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_WIDENING; }
+ const widening_svalue *dyn_cast_widening_svalue () const FINAL OVERRIDE
+ {
+ return this;
+ }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ const function_point &get_point () const { return m_point; }
+ const svalue *get_base_svalue () const { return m_base_sval; }
+ const svalue *get_iter_svalue () const { return m_iter_sval; }
+
+ enum direction_t get_direction () const;
+
+ tristate eval_condition_without_cm (enum tree_code op,
+ tree rhs_cst) const;
+
+ private:
+ function_point m_point;
+ const svalue *m_base_sval;
+ const svalue *m_iter_sval;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <widening_svalue *>::test (svalue *sval)
+{
+ return sval->get_kind () == SK_WIDENING;
+}
+
+template <> struct default_hash_traits<widening_svalue::key_t>
+: public member_function_hash_traits<widening_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* Concrete subclass of svalue representing a mapping of bit-ranges
+ to svalues, analogous to a cluster within the store.
+
+ This is for use in places where we want to represent a store-like
+ mapping, but are required to use an svalue, such as when handling
+ compound assignments and compound return values.
+
+ All keys within the underlying binding_map are required to be concrete,
+ not symbolic.
+
+ Instances of this class shouldn't be bound as-is into the store;
+ instead they should be unpacked. Similarly, they should not be
+ nested. */
+
+class compound_svalue : public svalue
+{
+public:
+ typedef binding_map::iterator_t iterator_t;
+
+ /* A support class for uniquifying instances of compound_svalue.
+ Note that to avoid copies, keys store pointers to binding_maps,
+ rather than the maps themselves. */
+ struct key_t
+ {
+ key_t (tree type, const binding_map *map_ptr)
+ : m_type (type), m_map_ptr (map_ptr)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_type);
+ //hstate.add_ptr (m_map_ptr); // TODO
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type
+ && *m_map_ptr == *other.m_map_ptr);
+ }
+
+ void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+ void mark_empty () { m_type = NULL_TREE; }
+ bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+ bool is_empty () const { return m_type == NULL_TREE; }
+
+ tree m_type;
+ const binding_map *m_map_ptr;
+ };
+
+ compound_svalue (tree type, const binding_map &map);
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_COMPOUND; }
+ const compound_svalue *dyn_cast_compound_svalue () const FINAL OVERRIDE
+ {
+ return this;
+ }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ const binding_map &get_map () const { return m_map; }
+
+ iterator_t begin () const { return m_map.begin (); }
+ iterator_t end () const { return m_map.end (); }
+
+ struct key_t make_key () const
+ {
+ return key_t (get_type (), &m_map);
+ }
+
+ private:
+ static complexity calc_complexity (const binding_map &map);
+
+ binding_map m_map;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <compound_svalue *>::test (svalue *sval)
+{
+ return sval->get_kind () == SK_COMPOUND;
+}
+
+template <> struct default_hash_traits<compound_svalue::key_t>
+: public member_function_hash_traits<compound_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+namespace ana {
+
+/* A defined value arising from a statement, where we want to identify a
+ particular unknown value, rather than resorting to the unknown_value
+ singleton, so that the value can have sm-state.
+
+ Comparisons of variables that share the same conjured_svalue are known
+ to be equal, even if we don't know what the value is.
+
+ For example, this is used for the values of regions that may have been
+ touched when calling an unknown function.
+
+ The value captures a region as well as a stmt in order to avoid falsely
+ aliasing the various values that could arise in one statement. For
+ example, after:
+ unknown_fn (&a, &b);
+ we want values to clobber a and b with, but we don't want to use the
+ same value, or it would falsely implicitly assume that a == b. */
+
+class conjured_svalue : public svalue
+{
+public:
+ typedef binding_map::iterator_t iterator_t;
+
+ /* A support class for uniquifying instances of conjured_svalue. */
+ struct key_t
+ {
+ key_t (tree type, const gimple *stmt, const region *id_reg)
+ : m_type (type), m_stmt (stmt), m_id_reg (id_reg)
+ {}
+
+ hashval_t hash () const
+ {
+ inchash::hash hstate;
+ hstate.add_ptr (m_type);
+ hstate.add_ptr (m_stmt);
+ hstate.add_ptr (m_id_reg);
+ return hstate.end ();
+ }
+
+ bool operator== (const key_t &other) const
+ {
+ return (m_type == other.m_type
+ && m_stmt == other.m_stmt
+ && m_id_reg == other.m_id_reg);
+ }
+
+ /* Use m_stmt to mark empty/deleted, as m_type can be NULL for
+ legitimate instances. */
+ void mark_deleted () { m_stmt = reinterpret_cast<const gimple *> (1); }
+ void mark_empty () { m_stmt = NULL; }
+ bool is_deleted () const
+ {
+ return m_stmt == reinterpret_cast<const gimple *> (1);
+ }
+ bool is_empty () const { return m_stmt == NULL; }
+
+ tree m_type;
+ const gimple *m_stmt;
+ const region *m_id_reg;
+ };
+
+ conjured_svalue (tree type, const gimple *stmt, const region *id_reg)
+ : svalue (complexity (id_reg), type),
+ m_stmt (stmt), m_id_reg (id_reg)
+ {
+ gcc_assert (m_stmt != NULL);
+ }
+
+ enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_CONJURED; }
+ const conjured_svalue *dyn_cast_conjured_svalue () const FINAL OVERRIDE
+ {
+ return this;
+ }
+
+ void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+ void accept (visitor *v) const FINAL OVERRIDE;
+
+ const gimple *get_stmt () const { return m_stmt; }
+ const region *get_id_region () const { return m_id_reg; }
+
+ private:
+ const gimple *m_stmt;
+ const region *m_id_reg;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <conjured_svalue *>::test (svalue *sval)
+{
+ return sval->get_kind () == SK_CONJURED;
+}
+
+template <> struct default_hash_traits<conjured_svalue::key_t>
+: public member_function_hash_traits<conjured_svalue::key_t>
+{
+ static const bool empty_zero_p = true;
+};
+
+#endif /* GCC_ANALYZER_SVALUE_H */
diff --git a/gcc/asan.c b/gcc/asan.c
index 0b471af..5968e12 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -257,6 +257,58 @@ hash_set<tree> *asan_handled_variables = NULL;
hash_set <tree> *asan_used_labels = NULL;
+/* Global variables for HWASAN stack tagging. */
+/* hwasan_frame_tag_offset records the offset from the frame base tag that the
+ next object should have. */
+static uint8_t hwasan_frame_tag_offset = 0;
+/* hwasan_frame_base_ptr is a pointer with the same address as
+ `virtual_stack_vars_rtx` for the current frame, and with the frame base tag
+ stored in it. N.b. this global RTX does not need to be marked GTY, but is
+ done so anyway. The need is not there since all uses are in just one pass
+ (cfgexpand) and there are no calls to ggc_collect between the uses. We mark
+ it GTY(()) anyway to allow the use of the variable later on if needed by
+ future features. */
+static GTY(()) rtx hwasan_frame_base_ptr = NULL_RTX;
+/* hwasan_frame_base_init_seq is the sequence of RTL insns that will initialize
+ the hwasan_frame_base_ptr. When the hwasan_frame_base_ptr is requested, we
+ generate this sequence but do not emit it. If the sequence was created it
+ is emitted once the function body has been expanded.
+
+ This delay is because the frame base pointer may be needed anywhere in the
+ function body, or needed by the expand_used_vars function. Emitting once in
+ a known place is simpler than requiring the emission of the instructions to
+ be know where it should go depending on the first place the hwasan frame
+ base is needed. */
+static GTY(()) rtx_insn *hwasan_frame_base_init_seq = NULL;
+
+/* Structure defining the extent of one object on the stack that HWASAN needs
+ to tag in the corresponding shadow stack space.
+
+ The range this object spans on the stack is between `untagged_base +
+ nearest_offset` and `untagged_base + farthest_offset`.
+ `tagged_base` is an rtx containing the same value as `untagged_base` but
+ with a random tag stored in the top byte. We record both `untagged_base`
+ and `tagged_base` so that `hwasan_emit_prologue` can use both without having
+ to emit RTL into the instruction stream to re-calculate one from the other.
+ (`hwasan_emit_prologue` needs to use both bases since the
+ __hwasan_tag_memory call it emits uses an untagged value, and it calculates
+ the tag to store in shadow memory based on the tag_offset plus the tag in
+ tagged_base). */
+struct hwasan_stack_var
+{
+ rtx untagged_base;
+ rtx tagged_base;
+ poly_int64 nearest_offset;
+ poly_int64 farthest_offset;
+ uint8_t tag_offset;
+};
+
+/* Variable recording all stack variables that HWASAN needs to tag.
+ Does not need to be marked as GTY(()) since every use is in the cfgexpand
+ pass and gcc_collect is not called in the middle of that pass. */
+static vec<hwasan_stack_var> hwasan_tagged_stack_vars;
+
+
/* Sets shadow offset to value in string VAL. */
bool
@@ -318,6 +370,25 @@ asan_sanitize_allocas_p (void)
return (asan_sanitize_stack_p () && param_asan_protect_allocas);
}
+bool
+asan_instrument_reads (void)
+{
+ return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_reads);
+}
+
+bool
+asan_instrument_writes (void)
+{
+ return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_writes);
+}
+
+bool
+asan_memintrin (void)
+{
+ return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_memintrin);
+}
+
+
/* Checks whether section SEC should be sanitized. */
static bool
@@ -578,20 +649,47 @@ get_last_alloca_addr ()
To overcome the issue we use following trick: pass new_sp as a second
parameter to __asan_allocas_unpoison and rewrite it during expansion with
new_sp + (virtual_dynamic_stack_rtx - sp) later in
- expand_asan_emit_allocas_unpoison function. */
+ expand_asan_emit_allocas_unpoison function.
+
+ HWASAN needs to do very similar, the eventual pseudocode should be:
+ __hwasan_tag_memory (virtual_stack_dynamic_rtx,
+ 0,
+ new_sp - sp);
+ __builtin_stack_restore (new_sp)
+
+ Need to use the same trick to handle STACK_DYNAMIC_OFFSET as described
+ above. */
static void
handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
{
- if (!iter || !asan_sanitize_allocas_p ())
+ if (!iter
+ || !(asan_sanitize_allocas_p () || hwasan_sanitize_allocas_p ()))
return;
- tree last_alloca = get_last_alloca_addr ();
tree restored_stack = gimple_call_arg (call, 0);
- tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
- gimple *g = gimple_build_call (fn, 2, last_alloca, restored_stack);
- gsi_insert_before (iter, g, GSI_SAME_STMT);
- g = gimple_build_assign (last_alloca, restored_stack);
+
+ gimple *g;
+
+ if (hwasan_sanitize_allocas_p ())
+ {
+ enum internal_fn fn = IFN_HWASAN_ALLOCA_UNPOISON;
+ /* There is only one piece of information `expand_HWASAN_ALLOCA_UNPOISON`
+ needs to work. This is the length of the area that we're
+ deallocating. Since the stack pointer is known at expand time, the
+ position of the new stack pointer after deallocation is enough
+ information to calculate this length. */
+ g = gimple_build_call_internal (fn, 1, restored_stack);
+ }
+ else
+ {
+ tree last_alloca = get_last_alloca_addr ();
+ tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
+ g = gimple_build_call (fn, 2, last_alloca, restored_stack);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ g = gimple_build_assign (last_alloca, restored_stack);
+ }
+
gsi_insert_before (iter, g, GSI_SAME_STMT);
}
@@ -621,14 +719,12 @@ handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
static void
handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
{
- if (!iter || !asan_sanitize_allocas_p ())
+ if (!iter
+ || !(asan_sanitize_allocas_p () || hwasan_sanitize_allocas_p ()))
return;
gassign *g;
gcall *gg;
- const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
-
- tree last_alloca = get_last_alloca_addr ();
tree callee = gimple_call_fndecl (call);
tree old_size = gimple_call_arg (call, 0);
tree ptr_type = gimple_call_lhs (call) ? TREE_TYPE (gimple_call_lhs (call))
@@ -638,6 +734,68 @@ handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
= DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
+ if (hwasan_sanitize_allocas_p ())
+ {
+ gimple_seq stmts = NULL;
+ location_t loc = gimple_location (gsi_stmt (*iter));
+ /*
+ HWASAN needs a different expansion.
+
+ addr = __builtin_alloca (size, align);
+
+ should be replaced by
+
+ new_size = size rounded up to HWASAN_TAG_GRANULE_SIZE byte alignment;
+ untagged_addr = __builtin_alloca (new_size, align);
+ tag = __hwasan_choose_alloca_tag ();
+ addr = ifn_HWASAN_SET_TAG (untagged_addr, tag);
+ __hwasan_tag_memory (untagged_addr, tag, new_size);
+ */
+ /* Ensure alignment at least HWASAN_TAG_GRANULE_SIZE bytes so we start on
+ a tag granule. */
+ align = align > HWASAN_TAG_GRANULE_SIZE ? align : HWASAN_TAG_GRANULE_SIZE;
+
+ tree old_size = gimple_call_arg (call, 0);
+ tree new_size = gimple_build_round_up (&stmts, loc, size_type_node,
+ old_size,
+ HWASAN_TAG_GRANULE_SIZE);
+
+ /* Make the alloca call */
+ tree untagged_addr
+ = gimple_build (&stmts, loc,
+ as_combined_fn (BUILT_IN_ALLOCA_WITH_ALIGN), ptr_type,
+ new_size, build_int_cst (size_type_node, align));
+
+ /* Choose the tag.
+ Here we use an internal function so we can choose the tag at expand
+ time. We need the decision to be made after stack variables have been
+ assigned their tag (i.e. once the hwasan_frame_tag_offset variable has
+ been set to one after the last stack variables tag). */
+ tree tag = gimple_build (&stmts, loc, CFN_HWASAN_CHOOSE_TAG,
+ unsigned_char_type_node);
+
+ /* Add tag to pointer. */
+ tree addr
+ = gimple_build (&stmts, loc, CFN_HWASAN_SET_TAG, ptr_type,
+ untagged_addr, tag);
+
+ /* Tag shadow memory.
+ NOTE: require using `untagged_addr` here for libhwasan API. */
+ gimple_build (&stmts, loc, as_combined_fn (BUILT_IN_HWASAN_TAG_MEM),
+ void_type_node, untagged_addr, tag, new_size);
+
+ /* Insert the built up code sequence into the original instruction stream
+ the iterator points to. */
+ gsi_insert_seq_before (iter, stmts, GSI_SAME_STMT);
+
+ /* Finally, replace old alloca ptr with NEW_ALLOCA. */
+ replace_call_with_value (iter, addr);
+ return;
+ }
+
+ tree last_alloca = get_last_alloca_addr ();
+ const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
+
/* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
bytes of allocated space. Otherwise, align alloca to ASAN_RED_ZONE_SIZE
manually. */
@@ -790,6 +948,31 @@ get_mem_refs_of_builtin_call (gcall *call,
break;
case BUILT_IN_STRLEN:
+ /* Special case strlen here since its length is taken from its return
+ value.
+
+ The approach taken by the sanitizers is to check a memory access
+ before it's taken. For ASAN strlen is intercepted by libasan, so no
+ check is inserted by the compiler.
+
+ This function still returns `true` and provides a length to the rest
+ of the ASAN pass in order to record what areas have been checked,
+ avoiding superfluous checks later on.
+
+ HWASAN does not intercept any of these internal functions.
+ This means that checks for memory accesses must be inserted by the
+ compiler.
+ strlen is a special case, because we can tell the length from the
+ return of the function, but that is not known until after the function
+ has returned.
+
+ Hence we can't check the memory access before it happens.
+ We could check the memory access after it has already happened, but
+ for now we choose to just ignore `strlen` calls.
+ This decision was simply made because that means the special case is
+ limited to this one case of this one function. */
+ if (hwasan_sanitize_p ())
+ return false;
source0 = gimple_call_arg (call, 0);
len = gimple_call_lhs (call);
break;
@@ -1359,6 +1542,199 @@ asan_redzone_buffer::flush_if_full (void)
flush_redzone_payload ();
}
+
+/* HWAddressSanitizer (hwasan) is a probabilistic method for detecting
+ out-of-bounds and use-after-free bugs.
+ Read more:
+ http://code.google.com/p/address-sanitizer/
+
+ Similar to AddressSanitizer (asan) it consists of two parts: the
+ instrumentation module in this file, and a run-time library.
+
+ The instrumentation module adds a run-time check before every memory insn in
+ the same manner as asan (see the block comment for AddressSanitizer above).
+ Currently, hwasan only adds out-of-line instrumentation, where each check is
+ implemented as a function call to the run-time library. Hence a check for a
+ load of N bytes from address X would be implemented with a function call to
+ __hwasan_loadN(X), and checking a store of N bytes from address X would be
+ implemented with a function call to __hwasan_storeN(X).
+
+ The main difference between hwasan and asan is in the information stored to
+ help this checking. Both sanitizers use a shadow memory area which stores
+ data recording the state of main memory at a corresponding address.
+
+ For hwasan, each 16 byte granule in main memory has a corresponding 1 byte
+ in shadow memory. This shadow address can be calculated with equation:
+ (addr >> log_2(HWASAN_TAG_GRANULE_SIZE))
+ + __hwasan_shadow_memory_dynamic_address;
+ The conversion between real and shadow memory for asan is given in the block
+ comment at the top of this file.
+ The description of how this shadow memory is laid out for asan is in the
+ block comment at the top of this file, here we describe how this shadow
+ memory is used for hwasan.
+
+ For hwasan, each variable is assigned a byte-sized 'tag'. The extent of
+ the shadow memory for that variable is filled with the assigned tag, and
+ every pointer referencing that variable has its top byte set to the same
+ tag. The run-time library redefines malloc so that every allocation returns
+ a tagged pointer and tags the corresponding shadow memory with the same tag.
+
+ On each pointer dereference the tag found in the pointer is compared to the
+ tag found in the shadow memory corresponding to the accessed memory address.
+ If these tags are found to differ then this memory access is judged to be
+ invalid and a report is generated.
+
+ This method of bug detection is not perfect -- it can not catch every bad
+ access -- but catches them probabilistically instead. There is always the
+ possibility that an invalid memory access will happen to access memory
+ tagged with the same tag as the pointer that this access used.
+ The chances of this are approx. 0.4% for any two uncorrelated objects.
+
+ Random tag generation can mitigate this problem by decreasing the
+ probability that an invalid access will be missed in the same manner over
+ multiple runs. i.e. if two objects are tagged the same in one run of the
+ binary they are unlikely to be tagged the same in the next run.
+ Both heap and stack allocated objects have random tags by default.
+
+ [16 byte granule implications]
+ Since the shadow memory only has a resolution on real memory of 16 bytes,
+ invalid accesses that are within the same 16 byte granule as a valid
+ address will not be caught.
+
+ There is a "short-granule" feature in the runtime library which does catch
+ such accesses, but this feature is not implemented for stack objects (since
+ stack objects are allocated and tagged by compiler instrumentation, and
+ this feature has not yet been implemented in GCC instrumentation).
+
+ Another outcome of this 16 byte resolution is that each tagged object must
+ be 16 byte aligned. If two objects were to share any 16 byte granule in
+ memory, then they both would have to be given the same tag, and invalid
+ accesses to one using a pointer to the other would be undetectable.
+
+ [Compiler instrumentation]
+ Compiler instrumentation ensures that two adjacent buffers on the stack are
+ given different tags, this means an access to one buffer using a pointer
+ generated from the other (e.g. through buffer overrun) will have mismatched
+ tags and be caught by hwasan.
+
+ We don't randomly tag every object on the stack, since that would require
+ keeping many registers to record each tag. Instead we randomly generate a
+ tag for each function frame, and each new stack object uses a tag offset
+ from that frame tag.
+ i.e. each object is tagged as RFT + offset, where RFT is the "random frame
+ tag" generated for this frame.
+ This means that randomisation does not peturb the difference between tags
+ on tagged stack objects within a frame, but this is mitigated by the fact
+ that objects with the same tag within a frame are very far apart
+ (approx. 2^HWASAN_TAG_SIZE objects apart).
+
+ As a demonstration, using the same example program as in the asan block
+ comment above:
+
+ int
+ foo ()
+ {
+ char a[23] = {0};
+ int b[2] = {0};
+
+ a[5] = 1;
+ b[1] = 2;
+
+ return a[5] + b[1];
+ }
+
+ On AArch64 the stack will be ordered as follows for the above function:
+
+ Slot 1/ [24 bytes for variable 'a']
+ Slot 2/ [8 bytes padding for alignment]
+ Slot 3/ [8 bytes for variable 'b']
+ Slot 4/ [8 bytes padding for alignment]
+
+ (The padding is there to ensure 16 byte alignment as described in the 16
+ byte granule implications).
+
+ While the shadow memory will be ordered as follows:
+
+ - 2 bytes (representing 32 bytes in real memory) tagged with RFT + 1.
+ - 1 byte (representing 16 bytes in real memory) tagged with RFT + 2.
+
+ And any pointer to "a" will have the tag RFT + 1, and any pointer to "b"
+ will have the tag RFT + 2.
+
+ [Top Byte Ignore requirements]
+ Hwasan requires the ability to store an 8 bit tag in every pointer. There
+ is no instrumentation done to remove this tag from pointers before
+ dereferencing, which means the hardware must ignore this tag during memory
+ accesses.
+
+ Architectures where this feature is available should indicate this using
+ the TARGET_MEMTAG_CAN_TAG_ADDRESSES hook.
+
+ [Stack requires cleanup on unwinding]
+ During normal operation of a hwasan sanitized program more space in the
+ shadow memory becomes tagged as the stack grows. As the stack shrinks this
+ shadow memory space must become untagged. If it is not untagged then when
+ the stack grows again (during other function calls later on in the program)
+ objects on the stack that are usually not tagged (e.g. parameters passed on
+ the stack) can be placed in memory whose shadow space is tagged with
+ something else, and accesses can cause false positive reports.
+
+ Hence we place untagging code on every epilogue of functions which tag some
+ stack objects.
+
+ Moreover, the run-time library intercepts longjmp & setjmp to untag when
+ the stack is unwound this way.
+
+ C++ exceptions are not yet handled, which means this sanitizer can not
+ handle C++ code that throws exceptions -- it will give false positives
+ after an exception has been thrown. The implementation that the hwasan
+ library has for handling these relies on the frame pointer being after any
+ local variables. This is not generally the case for GCC. */
+
+
+/* Returns whether we are tagging pointers and checking those tags on memory
+ access. */
+bool
+hwasan_sanitize_p ()
+{
+ return sanitize_flags_p (SANITIZE_HWADDRESS);
+}
+
+/* Are we tagging the stack? */
+bool
+hwasan_sanitize_stack_p ()
+{
+ return (hwasan_sanitize_p () && param_hwasan_instrument_stack);
+}
+
+/* Are we tagging alloca objects? */
+bool
+hwasan_sanitize_allocas_p (void)
+{
+ return (hwasan_sanitize_stack_p () && param_hwasan_instrument_allocas);
+}
+
+/* Should we instrument reads? */
+bool
+hwasan_instrument_reads (void)
+{
+ return (hwasan_sanitize_p () && param_hwasan_instrument_reads);
+}
+
+/* Should we instrument writes? */
+bool
+hwasan_instrument_writes (void)
+{
+ return (hwasan_sanitize_p () && param_hwasan_instrument_writes);
+}
+
+/* Should we instrument builtin calls? */
+bool
+hwasan_memintrin (void)
+{
+ return (hwasan_sanitize_p () && param_hwasan_instrument_mem_intrinsics);
+}
+
/* Insert code to protect stack vars. The prologue sequence should be emitted
directly, epilogue sequence returned. BASE is the register holding the
stack base, against which OFFSETS array offsets are relative to, OFFSETS
@@ -1854,6 +2230,8 @@ static tree
report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
int *nargs)
{
+ gcc_assert (!hwasan_sanitize_p ());
+
static enum built_in_function report[2][2][6]
= { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
@@ -2146,6 +2524,7 @@ build_check_stmt (location_t loc, tree base, tree len,
gimple *g;
gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len));
+ gcc_assert (size_in_bytes == -1 || size_in_bytes >= 1);
gsi = *iter;
@@ -2190,7 +2569,11 @@ build_check_stmt (location_t loc, tree base, tree len,
if (is_scalar_access)
flags |= ASAN_CHECK_SCALAR_ACCESS;
- g = gimple_build_call_internal (IFN_ASAN_CHECK, 4,
+ enum internal_fn fn = hwasan_sanitize_p ()
+ ? IFN_HWASAN_CHECK
+ : IFN_ASAN_CHECK;
+
+ g = gimple_build_call_internal (fn, 4,
build_int_cst (integer_type_node, flags),
base, len,
build_int_cst (integer_type_node,
@@ -2214,9 +2597,9 @@ static void
instrument_derefs (gimple_stmt_iterator *iter, tree t,
location_t location, bool is_store)
{
- if (is_store && !param_asan_instrument_writes)
+ if (is_store && !(asan_instrument_writes () || hwasan_instrument_writes ()))
return;
- if (!is_store && !param_asan_instrument_reads)
+ if (!is_store && !(asan_instrument_reads () || hwasan_instrument_reads ()))
return;
tree type, base;
@@ -2277,7 +2660,12 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
{
if (DECL_THREAD_LOCAL_P (inner))
return;
- if (!param_asan_globals && is_global_var (inner))
+ /* If we're not sanitizing globals and we can tell statically that this
+ access is inside a global variable, then there's no point adding
+ instrumentation to check the access. N.b. hwasan currently never
+ sanitizes globals. */
+ if ((hwasan_sanitize_p () || !param_asan_globals)
+ && is_global_var (inner))
return;
if (!TREE_STATIC (inner))
{
@@ -2370,7 +2758,7 @@ instrument_mem_region_access (tree base, tree len,
static bool
instrument_builtin_call (gimple_stmt_iterator *iter)
{
- if (!param_asan_memintrin)
+ if (!(asan_memintrin () || hwasan_memintrin ()))
return false;
bool iter_advanced_p = false;
@@ -2506,10 +2894,27 @@ maybe_instrument_call (gimple_stmt_iterator *iter)
break;
}
}
- tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
- gimple *g = gimple_build_call (decl, 0);
- gimple_set_location (g, gimple_location (stmt));
- gsi_insert_before (iter, g, GSI_SAME_STMT);
+ /* If a function does not return, then we must handle clearing up the
+ shadow stack accordingly. For ASAN we can simply set the entire stack
+ to "valid" for accesses by setting the shadow space to 0 and all
+ accesses will pass checks. That means that some bad accesses may be
+ missed, but we will not report any false positives.
+
+ This is not possible for HWASAN. Since there is no "always valid" tag
+ we can not set any space to "always valid". If we were to clear the
+ entire shadow stack then code resuming from `longjmp` or a caught
+ exception would trigger false positives when correctly accessing
+ variables on the stack. Hence we need to handle things like
+ `longjmp`, thread exit, and exceptions in a different way. These
+ problems must be handled externally to the compiler, e.g. in the
+ language runtime. */
+ if (! hwasan_sanitize_p ())
+ {
+ tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
+ gimple *g = gimple_build_call (decl, 0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ }
}
bool instrumented = false;
@@ -2908,6 +3313,14 @@ initialize_sanitizer_builtins (void)
= build_function_type_list (void_type_node, uint64_type_node,
ptr_type_node, NULL_TREE);
+ tree BT_FN_PTR_CONST_PTR_UINT8
+ = build_function_type_list (ptr_type_node, const_ptr_type_node,
+ unsigned_char_type_node, NULL_TREE);
+ tree BT_FN_VOID_PTR_UINT8_PTRMODE
+ = build_function_type_list (void_type_node, ptr_type_node,
+ unsigned_char_type_node,
+ pointer_sized_int_node, NULL_TREE);
+
tree BT_FN_BOOL_VPTR_PTR_IX_INT_INT[5];
tree BT_FN_IX_CONST_VPTR_INT[5];
tree BT_FN_IX_VPTR_IX_INT[5];
@@ -2958,6 +3371,8 @@ initialize_sanitizer_builtins (void)
#define BT_FN_I16_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[4]
#define BT_FN_I16_VPTR_I16_INT BT_FN_IX_VPTR_IX_INT[4]
#define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4]
+#undef ATTR_NOTHROW_LIST
+#define ATTR_NOTHROW_LIST ECF_NOTHROW
#undef ATTR_NOTHROW_LEAF_LIST
#define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF
#undef ATTR_TMPURE_NOTHROW_LEAF_LIST
@@ -3224,6 +3639,31 @@ asan_expand_mark_ifn (gimple_stmt_iterator *iter)
gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
+ if (hwasan_sanitize_p ())
+ {
+ gcc_assert (param_hwasan_instrument_stack);
+ gimple_seq stmts = NULL;
+ /* Here we swap ASAN_MARK calls for HWASAN_MARK.
+ This is because we are using the approach of using ASAN_MARK as a
+ synonym until here.
+ That approach means we don't yet have to duplicate all the special
+ cases for ASAN_MARK and ASAN_POISON with the exact same handling but
+ called HWASAN_MARK etc.
+
+ N.b. __asan_poison_stack_memory (which implements ASAN_MARK for ASAN)
+ rounds the size up to its shadow memory granularity, while
+ __hwasan_tag_memory (which implements the same for HWASAN) does not.
+ Hence we emit HWASAN_MARK with an aligned size unlike ASAN_MARK. */
+ tree len = gimple_call_arg (g, 2);
+ tree new_len = gimple_build_round_up (&stmts, loc, size_type_node, len,
+ HWASAN_TAG_GRANULE_SIZE);
+ gimple_build (&stmts, loc, CFN_HWASAN_MARK,
+ void_type_node, gimple_call_arg (g, 0),
+ base, new_len);
+ gsi_replace_with_seq (iter, stmts, true);
+ return false;
+ }
+
if (is_poison)
{
if (asan_handled_variables == NULL)
@@ -3298,6 +3738,7 @@ asan_expand_mark_ifn (gimple_stmt_iterator *iter)
bool
asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
{
+ gcc_assert (!hwasan_sanitize_p ());
gimple *g = gsi_stmt (*iter);
location_t loc = gimple_location (g);
bool recover_p;
@@ -3571,11 +4012,61 @@ asan_expand_poison_ifn (gimple_stmt_iterator *iter,
int nargs;
bool store_p = gimple_call_internal_p (use, IFN_ASAN_POISON_USE);
- tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
- &nargs);
-
- gcall *call = gimple_build_call (fun, 1,
- build_fold_addr_expr (shadow_var));
+ gcall *call;
+ if (hwasan_sanitize_p ())
+ {
+ tree fun = builtin_decl_implicit (BUILT_IN_HWASAN_TAG_MISMATCH4);
+ /* NOTE: hwasan has no __hwasan_report_* functions like asan does.
+ We use __hwasan_tag_mismatch4 with arguments that tell it the
+ size of access and load to report all tag mismatches.
+
+ The arguments to this function are:
+ Address of invalid access.
+ Bitfield containing information about the access
+ (access_info)
+ Pointer to a frame of registers
+ (for use in printing the contents of registers in a dump)
+ Not used yet -- to be used by inline instrumentation.
+ Size of access.
+
+ The access_info bitfield encodes the following pieces of
+ information:
+ - Is this a store or load?
+ access_info & 0x10 => store
+ - Should the program continue after reporting the error?
+ access_info & 0x20 => recover
+ - What size access is this (not used here since we can always
+ pass the size in the last argument)
+
+ if (access_info & 0xf == 0xf)
+ size is taken from last argument.
+ else
+ size == 1 << (access_info & 0xf)
+
+ The last argument contains the size of the access iff the
+ access_info size indicator is 0xf (we always use this argument
+ rather than storing the size in the access_info bitfield).
+
+ See the function definition `__hwasan_tag_mismatch4` in
+ libsanitizer/hwasan for the full definition.
+ */
+ unsigned access_info = (0x20 * recover_p)
+ + (0x10 * store_p)
+ + (0xf);
+ call = gimple_build_call (fun, 4,
+ build_fold_addr_expr (shadow_var),
+ build_int_cst (pointer_sized_int_node,
+ access_info),
+ build_int_cst (pointer_sized_int_node, 0),
+ size);
+ }
+ else
+ {
+ tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
+ &nargs);
+ call = gimple_build_call (fun, 1,
+ build_fold_addr_expr (shadow_var));
+ }
gimple_set_location (call, gimple_location (use));
gimple *call_to_insert = call;
@@ -3623,6 +4114,12 @@ asan_expand_poison_ifn (gimple_stmt_iterator *iter,
static unsigned int
asan_instrument (void)
{
+ if (hwasan_sanitize_p ())
+ {
+ transform_statements ();
+ return 0;
+ }
+
if (shadow_ptr_types[0] == NULL_TREE)
asan_init_shadow_ptr_types ();
transform_statements ();
@@ -3660,7 +4157,7 @@ public:
/* opt_pass methods: */
opt_pass * clone () { return new pass_asan (m_ctxt); }
- virtual bool gate (function *) { return gate_asan (); }
+ virtual bool gate (function *) { return gate_asan () || gate_hwasan (); }
virtual unsigned int execute (function *) { return asan_instrument (); }
}; // class pass_asan
@@ -3696,7 +4193,10 @@ public:
{}
/* opt_pass methods: */
- virtual bool gate (function *) { return !optimize && gate_asan (); }
+ virtual bool gate (function *)
+ {
+ return !optimize && (gate_asan () || gate_hwasan ());
+ }
virtual unsigned int execute (function *) { return asan_instrument (); }
}; // class pass_asan_O0
@@ -3709,4 +4209,484 @@ make_pass_asan_O0 (gcc::context *ctxt)
return new pass_asan_O0 (ctxt);
}
+/* HWASAN */
+
+/* For stack tagging:
+
+ Return the offset from the frame base tag that the "next" expanded object
+ should have. */
+uint8_t
+hwasan_current_frame_tag ()
+{
+ return hwasan_frame_tag_offset;
+}
+
+/* For stack tagging:
+
+ Return the 'base pointer' for this function. If that base pointer has not
+ yet been created then we create a register to hold it and record the insns
+ to initialize the register in `hwasan_frame_base_init_seq` for later
+ emission. */
+rtx
+hwasan_frame_base ()
+{
+ if (! hwasan_frame_base_ptr)
+ {
+ start_sequence ();
+ hwasan_frame_base_ptr
+ = force_reg (Pmode,
+ targetm.memtag.insert_random_tag (virtual_stack_vars_rtx,
+ NULL_RTX));
+ hwasan_frame_base_init_seq = get_insns ();
+ end_sequence ();
+ }
+
+ return hwasan_frame_base_ptr;
+}
+
+/* For stack tagging:
+
+ Check whether this RTX is a standard pointer addressing the base of the
+ stack variables for this frame. Returns true if the RTX is either
+ virtual_stack_vars_rtx or hwasan_frame_base_ptr. */
+bool
+stack_vars_base_reg_p (rtx base)
+{
+ return base == virtual_stack_vars_rtx || base == hwasan_frame_base_ptr;
+}
+
+/* For stack tagging:
+
+ Emit frame base initialisation.
+ If hwasan_frame_base has been used before here then
+ hwasan_frame_base_init_seq contains the sequence of instructions to
+ initialize it. This must be put just before the hwasan prologue, so we emit
+ the insns before parm_birth_insn (which will point to the first instruction
+ of the hwasan prologue if it exists).
+
+ We update `parm_birth_insn` to point to the start of this initialisation
+ since that represents the end of the initialisation done by
+ expand_function_{start,end} functions and we want to maintain that. */
+void
+hwasan_maybe_emit_frame_base_init ()
+{
+ if (! hwasan_frame_base_init_seq)
+ return;
+ emit_insn_before (hwasan_frame_base_init_seq, parm_birth_insn);
+ parm_birth_insn = hwasan_frame_base_init_seq;
+}
+
+/* Record a compile-time constant size stack variable that HWASAN will need to
+ tag. This record of the range of a stack variable will be used by
+ `hwasan_emit_prologue` to emit the RTL at the start of each frame which will
+ set tags in the shadow memory according to the assigned tag for each object.
+
+ The range that the object spans in stack space should be described by the
+ bounds `untagged_base + nearest_offset` and
+ `untagged_base + farthest_offset`.
+ `tagged_base` is the base address which contains the "base frame tag" for
+ this frame, and from which the value to address this object with will be
+ calculated.
+
+ We record the `untagged_base` since the functions in the hwasan library we
+ use to tag memory take pointers without a tag. */
+void
+hwasan_record_stack_var (rtx untagged_base, rtx tagged_base,
+ poly_int64 nearest_offset, poly_int64 farthest_offset)
+{
+ hwasan_stack_var cur_var;
+ cur_var.untagged_base = untagged_base;
+ cur_var.tagged_base = tagged_base;
+ cur_var.nearest_offset = nearest_offset;
+ cur_var.farthest_offset = farthest_offset;
+ cur_var.tag_offset = hwasan_current_frame_tag ();
+
+ hwasan_tagged_stack_vars.safe_push (cur_var);
+}
+
+/* Return the RTX representing the farthest extent of the statically allocated
+ stack objects for this frame. If hwasan_frame_base_ptr has not been
+ initialized then we are not storing any static variables on the stack in
+ this frame. In this case we return NULL_RTX to represent that.
+
+ Otherwise simply return virtual_stack_vars_rtx + frame_offset. */
+rtx
+hwasan_get_frame_extent ()
+{
+ return (hwasan_frame_base_ptr
+ ? plus_constant (Pmode, virtual_stack_vars_rtx, frame_offset)
+ : NULL_RTX);
+}
+
+/* For stack tagging:
+
+ Increment the frame tag offset modulo the size a tag can represent. */
+void
+hwasan_increment_frame_tag ()
+{
+ uint8_t tag_bits = HWASAN_TAG_SIZE;
+ gcc_assert (HWASAN_TAG_SIZE
+ <= sizeof (hwasan_frame_tag_offset) * CHAR_BIT);
+ hwasan_frame_tag_offset = (hwasan_frame_tag_offset + 1) % (1 << tag_bits);
+ /* The "background tag" of the stack is zero by definition.
+ This is the tag that objects like parameters passed on the stack and
+ spilled registers are given. It is handy to avoid this tag for objects
+ whose tags we decide ourselves, partly to ensure that buffer overruns
+ can't affect these important variables (e.g. saved link register, saved
+ stack pointer etc) and partly to make debugging easier (everything with a
+ tag of zero is space allocated automatically by the compiler).
+
+ This is not feasible when using random frame tags (the default
+ configuration for hwasan) since the tag for the given frame is randomly
+ chosen at runtime. In order to avoid any tags matching the stack
+ background we would need to decide tag offsets at runtime instead of
+ compile time (and pay the resulting performance cost).
+
+ When not using random base tags for each frame (i.e. when compiled with
+ `--param hwasan-random-frame-tag=0`) the base tag for each frame is zero.
+ This means the tag that each object gets is equal to the
+ hwasan_frame_tag_offset used in determining it.
+ When this is the case we *can* ensure no object gets the tag of zero by
+ simply ensuring no object has the hwasan_frame_tag_offset of zero.
+
+ There is the extra complication that we only record the
+ hwasan_frame_tag_offset here (which is the offset from the tag stored in
+ the stack pointer). In the kernel, the tag in the stack pointer is 0xff
+ rather than zero. This does not cause problems since tags of 0xff are
+ never checked in the kernel. As mentioned at the beginning of this
+ comment the background tag of the stack is zero by definition, which means
+ that for the kernel we should skip offsets of both 0 and 1 from the stack
+ pointer. Avoiding the offset of 0 ensures we use a tag which will be
+ checked, avoiding the offset of 1 ensures we use a tag that is not the
+ same as the background. */
+ if (hwasan_frame_tag_offset == 0 && ! param_hwasan_random_frame_tag)
+ hwasan_frame_tag_offset += 1;
+ if (hwasan_frame_tag_offset == 1 && ! param_hwasan_random_frame_tag
+ && sanitize_flags_p (SANITIZE_KERNEL_HWADDRESS))
+ hwasan_frame_tag_offset += 1;
+}
+
+/* Clear internal state for the next function.
+ This function is called before variables on the stack get expanded, in
+ `init_vars_expansion`. */
+void
+hwasan_record_frame_init ()
+{
+ delete asan_used_labels;
+ asan_used_labels = NULL;
+
+ /* If this isn't the case then some stack variable was recorded *before*
+ hwasan_record_frame_init is called, yet *after* the hwasan prologue for
+ the previous frame was emitted. Such stack variables would not have
+ their shadow stack filled in. */
+ gcc_assert (hwasan_tagged_stack_vars.is_empty ());
+ hwasan_frame_base_ptr = NULL_RTX;
+ hwasan_frame_base_init_seq = NULL;
+
+ /* When not using a random frame tag we can avoid the background stack
+ color which gives the user a little better debug output upon a crash.
+ Meanwhile, when using a random frame tag it will be nice to avoid adding
+ tags for the first object since that is unnecessary extra work.
+ Hence set the initial hwasan_frame_tag_offset to be 0 if using a random
+ frame tag and 1 otherwise.
+
+ As described in hwasan_increment_frame_tag, in the kernel the stack
+ pointer has the tag 0xff. That means that to avoid 0xff and 0 (the tag
+ which the kernel does not check and the background tag respectively) we
+ start with a tag offset of 2. */
+ hwasan_frame_tag_offset = param_hwasan_random_frame_tag
+ ? 0
+ : sanitize_flags_p (SANITIZE_KERNEL_HWADDRESS) ? 2 : 1;
+}
+
+/* For stack tagging:
+ (Emits HWASAN equivalent of what is emitted by
+ `asan_emit_stack_protection`).
+
+ Emits the extra prologue code to set the shadow stack as required for HWASAN
+ stack instrumentation.
+
+ Uses the vector of recorded stack variables hwasan_tagged_stack_vars. When
+ this function has completed hwasan_tagged_stack_vars is empty and all
+ objects it had pointed to are deallocated. */
+void
+hwasan_emit_prologue ()
+{
+ /* We need untagged base pointers since libhwasan only accepts untagged
+ pointers in __hwasan_tag_memory. We need the tagged base pointer to obtain
+ the base tag for an offset. */
+
+ if (hwasan_tagged_stack_vars.is_empty ())
+ return;
+
+ poly_int64 bot = 0, top = 0;
+ for (hwasan_stack_var &cur : hwasan_tagged_stack_vars)
+ {
+ poly_int64 nearest = cur.nearest_offset;
+ poly_int64 farthest = cur.farthest_offset;
+
+ if (known_ge (nearest, farthest))
+ {
+ top = nearest;
+ bot = farthest;
+ }
+ else
+ {
+ /* Given how these values are calculated, one must be known greater
+ than the other. */
+ gcc_assert (known_le (nearest, farthest));
+ top = farthest;
+ bot = nearest;
+ }
+ poly_int64 size = (top - bot);
+
+ /* Assert the edge of each variable is aligned to the HWASAN tag granule
+ size. */
+ gcc_assert (multiple_p (top, HWASAN_TAG_GRANULE_SIZE));
+ gcc_assert (multiple_p (bot, HWASAN_TAG_GRANULE_SIZE));
+ gcc_assert (multiple_p (size, HWASAN_TAG_GRANULE_SIZE));
+
+ rtx fn = init_one_libfunc ("__hwasan_tag_memory");
+ rtx base_tag = targetm.memtag.extract_tag (cur.tagged_base, NULL_RTX);
+ rtx tag = plus_constant (QImode, base_tag, cur.tag_offset);
+ tag = hwasan_truncate_to_tag_size (tag, NULL_RTX);
+
+ rtx bottom = convert_memory_address (ptr_mode,
+ plus_constant (Pmode,
+ cur.untagged_base,
+ bot));
+ emit_library_call (fn, LCT_NORMAL, VOIDmode,
+ bottom, ptr_mode,
+ tag, QImode,
+ gen_int_mode (size, ptr_mode), ptr_mode);
+ }
+ /* Clear the stack vars, we've emitted the prologue for them all now. */
+ hwasan_tagged_stack_vars.truncate (0);
+}
+
+/* For stack tagging:
+
+ Return RTL insns to clear the tags between DYNAMIC and VARS pointers
+ into the stack. These instructions should be emitted at the end of
+ every function.
+
+ If `dynamic` is NULL_RTX then no insns are returned. */
+rtx_insn *
+hwasan_emit_untag_frame (rtx dynamic, rtx vars)
+{
+ if (! dynamic)
+ return NULL;
+
+ start_sequence ();
+
+ dynamic = convert_memory_address (ptr_mode, dynamic);
+ vars = convert_memory_address (ptr_mode, vars);
+
+ rtx top_rtx;
+ rtx bot_rtx;
+ if (FRAME_GROWS_DOWNWARD)
+ {
+ top_rtx = vars;
+ bot_rtx = dynamic;
+ }
+ else
+ {
+ top_rtx = dynamic;
+ bot_rtx = vars;
+ }
+
+ rtx size_rtx = expand_simple_binop (ptr_mode, MINUS, top_rtx, bot_rtx,
+ NULL_RTX, /* unsignedp = */0,
+ OPTAB_DIRECT);
+
+ rtx fn = init_one_libfunc ("__hwasan_tag_memory");
+ emit_library_call (fn, LCT_NORMAL, VOIDmode,
+ bot_rtx, ptr_mode,
+ HWASAN_STACK_BACKGROUND, QImode,
+ size_rtx, ptr_mode);
+
+ do_pending_stack_adjust ();
+ rtx_insn *insns = get_insns ();
+ end_sequence ();
+ return insns;
+}
+
+/* Needs to be GTY(()), because cgraph_build_static_cdtor may
+ invoke ggc_collect. */
+static GTY(()) tree hwasan_ctor_statements;
+
+/* Insert module initialization into this TU. This initialization calls the
+ initialization code for libhwasan. */
+void
+hwasan_finish_file (void)
+{
+ /* Do not emit constructor initialization for the kernel.
+ (the kernel has its own initialization already). */
+ if (flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
+ return;
+
+ /* Avoid instrumenting code in the hwasan constructors/destructors. */
+ flag_sanitize &= ~SANITIZE_HWADDRESS;
+ int priority = MAX_RESERVED_INIT_PRIORITY - 1;
+ tree fn = builtin_decl_implicit (BUILT_IN_HWASAN_INIT);
+ append_to_statement_list (build_call_expr (fn, 0), &hwasan_ctor_statements);
+ cgraph_build_static_cdtor ('I', hwasan_ctor_statements, priority);
+ flag_sanitize |= SANITIZE_HWADDRESS;
+}
+
+/* For stack tagging:
+
+ Truncate `tag` to the number of bits that a tag uses (i.e. to
+ HWASAN_TAG_SIZE). Store the result in `target` if it's convenient. */
+rtx
+hwasan_truncate_to_tag_size (rtx tag, rtx target)
+{
+ gcc_assert (GET_MODE (tag) == QImode);
+ if (HWASAN_TAG_SIZE != GET_MODE_PRECISION (QImode))
+ {
+ gcc_assert (GET_MODE_PRECISION (QImode) > HWASAN_TAG_SIZE);
+ rtx mask = gen_int_mode ((HOST_WIDE_INT_1U << HWASAN_TAG_SIZE) - 1,
+ QImode);
+ tag = expand_simple_binop (QImode, AND, tag, mask, target,
+ /* unsignedp = */1, OPTAB_WIDEN);
+ gcc_assert (tag);
+ }
+ return tag;
+}
+
+/* Construct a function tree for __hwasan_{load,store}{1,2,4,8,16,_n}.
+ IS_STORE is either 1 (for a store) or 0 (for a load). */
+static combined_fn
+hwasan_check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+ int *nargs)
+{
+ static enum built_in_function check[2][2][6]
+ = { { { BUILT_IN_HWASAN_LOAD1, BUILT_IN_HWASAN_LOAD2,
+ BUILT_IN_HWASAN_LOAD4, BUILT_IN_HWASAN_LOAD8,
+ BUILT_IN_HWASAN_LOAD16, BUILT_IN_HWASAN_LOADN },
+ { BUILT_IN_HWASAN_STORE1, BUILT_IN_HWASAN_STORE2,
+ BUILT_IN_HWASAN_STORE4, BUILT_IN_HWASAN_STORE8,
+ BUILT_IN_HWASAN_STORE16, BUILT_IN_HWASAN_STOREN } },
+ { { BUILT_IN_HWASAN_LOAD1_NOABORT,
+ BUILT_IN_HWASAN_LOAD2_NOABORT,
+ BUILT_IN_HWASAN_LOAD4_NOABORT,
+ BUILT_IN_HWASAN_LOAD8_NOABORT,
+ BUILT_IN_HWASAN_LOAD16_NOABORT,
+ BUILT_IN_HWASAN_LOADN_NOABORT },
+ { BUILT_IN_HWASAN_STORE1_NOABORT,
+ BUILT_IN_HWASAN_STORE2_NOABORT,
+ BUILT_IN_HWASAN_STORE4_NOABORT,
+ BUILT_IN_HWASAN_STORE8_NOABORT,
+ BUILT_IN_HWASAN_STORE16_NOABORT,
+ BUILT_IN_HWASAN_STOREN_NOABORT } } };
+ if (size_in_bytes == -1)
+ {
+ *nargs = 2;
+ return as_combined_fn (check[recover_p][is_store][5]);
+ }
+ *nargs = 1;
+ int size_log2 = exact_log2 (size_in_bytes);
+ gcc_assert (size_log2 >= 0 && size_log2 <= 5);
+ return as_combined_fn (check[recover_p][is_store][size_log2]);
+}
+
+/* Expand the HWASAN_{LOAD,STORE} builtins. */
+bool
+hwasan_expand_check_ifn (gimple_stmt_iterator *iter, bool)
+{
+ gimple *g = gsi_stmt (*iter);
+ location_t loc = gimple_location (g);
+ bool recover_p;
+ if (flag_sanitize & SANITIZE_USER_HWADDRESS)
+ recover_p = (flag_sanitize_recover & SANITIZE_USER_HWADDRESS) != 0;
+ else
+ recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_HWADDRESS) != 0;
+
+ HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
+ gcc_assert (flags < ASAN_CHECK_LAST);
+ bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
+ bool is_store = (flags & ASAN_CHECK_STORE) != 0;
+ bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
+
+ tree base = gimple_call_arg (g, 1);
+ tree len = gimple_call_arg (g, 2);
+
+ /* `align` is unused for HWASAN_CHECK, but we pass the argument anyway
+ since that way the arguments match ASAN_CHECK. */
+ /* HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3)); */
+
+ unsigned HOST_WIDE_INT size_in_bytes
+ = is_scalar_access ? tree_to_shwi (len) : -1;
+
+ gimple_stmt_iterator gsi = *iter;
+
+ if (!is_non_zero_len)
+ {
+ /* So, the length of the memory area to hwasan-protect is
+ non-constant. Let's guard the generated instrumentation code
+ like:
+
+ if (len != 0)
+ {
+ // hwasan instrumentation code goes here.
+ }
+ // falltrough instructions, starting with *ITER. */
+
+ g = gimple_build_cond (NE_EXPR,
+ len,
+ build_int_cst (TREE_TYPE (len), 0),
+ NULL_TREE, NULL_TREE);
+ gimple_set_location (g, loc);
+
+ basic_block then_bb, fallthrough_bb;
+ insert_if_then_before_iter (as_a <gcond *> (g), iter,
+ /*then_more_likely_p=*/true,
+ &then_bb, &fallthrough_bb);
+ /* Note that fallthrough_bb starts with the statement that was
+ pointed to by ITER. */
+
+ /* The 'then block' of the 'if (len != 0) condition is where
+ we'll generate the hwasan instrumentation code now. */
+ gsi = gsi_last_bb (then_bb);
+ }
+
+ gimple_seq stmts = NULL;
+ tree base_addr = gimple_build (&stmts, loc, NOP_EXPR,
+ pointer_sized_int_node, base);
+
+ int nargs = 0;
+ combined_fn fn
+ = hwasan_check_func (is_store, recover_p, size_in_bytes, &nargs);
+ if (nargs == 1)
+ gimple_build (&stmts, loc, fn, void_type_node, base_addr);
+ else
+ {
+ gcc_assert (nargs == 2);
+ tree sz_arg = gimple_build (&stmts, loc, NOP_EXPR,
+ pointer_sized_int_node, len);
+ gimple_build (&stmts, loc, fn, void_type_node, base_addr, sz_arg);
+ }
+
+ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
+ gsi_remove (iter, true);
+ *iter = gsi;
+ return false;
+}
+
+/* For stack tagging:
+
+ Dummy: the HWASAN_MARK internal function should only ever be in the code
+ after the sanopt pass. */
+bool
+hwasan_expand_mark_ifn (gimple_stmt_iterator *)
+{
+ gcc_unreachable ();
+}
+
+bool
+gate_hwasan ()
+{
+ return hwasan_sanitize_p ();
+}
+
#include "gt-asan.h"
diff --git a/gcc/asan.h b/gcc/asan.h
index 114b457..4b873d6 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -34,6 +34,25 @@ extern bool asan_expand_mark_ifn (gimple_stmt_iterator *);
extern bool asan_expand_poison_ifn (gimple_stmt_iterator *, bool *,
hash_map<tree, tree> &);
+extern void hwasan_record_frame_init ();
+extern void hwasan_record_stack_var (rtx, rtx, poly_int64, poly_int64);
+extern void hwasan_emit_prologue ();
+extern rtx_insn *hwasan_emit_untag_frame (rtx, rtx);
+extern rtx hwasan_get_frame_extent ();
+extern rtx hwasan_frame_base ();
+extern void hwasan_maybe_emit_frame_base_init (void);
+extern bool stack_vars_base_reg_p (rtx);
+extern uint8_t hwasan_current_frame_tag ();
+extern void hwasan_increment_frame_tag ();
+extern rtx hwasan_truncate_to_tag_size (rtx, rtx);
+extern void hwasan_finish_file (void);
+extern bool hwasan_sanitize_p (void);
+extern bool hwasan_sanitize_stack_p (void);
+extern bool hwasan_sanitize_allocas_p (void);
+extern bool hwasan_expand_check_ifn (gimple_stmt_iterator *, bool);
+extern bool hwasan_expand_mark_ifn (gimple_stmt_iterator *);
+extern bool gate_hwasan (void);
+
extern gimple_stmt_iterator create_cond_insert_point
(gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *);
@@ -75,6 +94,26 @@ extern hash_set <tree> *asan_used_labels;
#define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory"
+/* NOTE: The values below and the hooks under targetm.memtag define an ABI and
+ are hard-coded to these values in libhwasan, hence they can't be changed
+ independently here. */
+/* How many bits are used to store a tag in a pointer.
+ The default version uses the entire top byte of a pointer (i.e. 8 bits). */
+#define HWASAN_TAG_SIZE targetm.memtag.tag_size ()
+/* Tag Granule of HWASAN shadow stack.
+ This is the size in real memory that each byte in the shadow memory refers
+ to. I.e. if a variable is X bytes long in memory then its tag in shadow
+ memory will span X / HWASAN_TAG_GRANULE_SIZE bytes.
+ Most variables will need to be aligned to this amount since two variables
+ that are neighbors in memory and share a tag granule would need to share the
+ same tag (the shared tag granule can only store one tag). */
+#define HWASAN_TAG_GRANULE_SIZE targetm.memtag.granule_size ()
+/* Define the tag for the stack background.
+ This defines what tag the stack pointer will be and hence what tag all
+ variables that are not given special tags are (e.g. spilled registers,
+ and parameters passed on the stack). */
+#define HWASAN_STACK_BACKGROUND gen_int_mode (0, QImode)
+
/* Various flags for Asan builtins. */
enum asan_check_flags
{
@@ -145,6 +184,9 @@ extern hash_set<tree> *asan_handled_variables;
static inline bool
asan_intercepted_p (enum built_in_function fcode)
{
+ if (hwasan_sanitize_p ())
+ return false;
+
return fcode == BUILT_IN_INDEX
|| fcode == BUILT_IN_MEMCHR
|| fcode == BUILT_IN_MEMCMP
@@ -173,7 +215,8 @@ asan_intercepted_p (enum built_in_function fcode)
static inline bool
asan_sanitize_use_after_scope (void)
{
- return (flag_sanitize_address_use_after_scope && asan_sanitize_stack_p ());
+ return (flag_sanitize_address_use_after_scope
+ && (asan_sanitize_stack_p () || hwasan_sanitize_stack_p ()));
}
/* Return true if DECL should be guarded on the stack. */
diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h
index d38b84a..ccc36e1 100644
--- a/gcc/attr-fnspec.h
+++ b/gcc/attr-fnspec.h
@@ -27,13 +27,23 @@
'.' specifies that nothing is known.
character 1 specifies additional function properties
' ' specifies that nothing is known
+ 'p' or 'P' specifies that function is pure except for described side
+ effects.
+ 'c' or 'C' specifies that function is const except for described side
+ effects.
+ The uppercase letter in addition specifies that function clobbers errno.
character 2+2i specifies properties of argument number i as follows:
'x' or 'X' specifies that parameter is unused.
'r' or 'R' specifies that the memory pointed to by the parameter is only
read and does not escape
+ 'o' or 'O' specifies that the memory pointed to by the parameter is only
+ written and does not escape
'w' or 'W' specifies that the memory pointed to by the parameter does not
escape
+ '1'....'9' specifies that the memory pointed to by the parameter is
+ copied to memory pointed to by different parameter
+ (as in memcpy).
'.' specifies that nothing is known.
The uppercase letter in addition specifies that the memory pointed to
by the parameter is not dereferenced. For 'r' only read applies
@@ -42,6 +52,10 @@
character 3+2i specifies additional properties of argument number i
as follows:
' ' nothing is known
+ 't' the size of value written/read corresponds to the size of
+ of the pointed-to type of the argument type
+ '1'...'9' specifies the size of value written/read is given by the
+ specified argument
*/
#ifndef ATTR_FNSPEC_H
@@ -72,6 +86,12 @@ public:
if (flag_checking)
verify ();
}
+ attr_fnspec (const char *str)
+ : str (str), len (strlen (str))
+ {
+ if (flag_checking)
+ verify ();
+ }
attr_fnspec (const_tree identifier)
: str (TREE_STRING_POINTER (identifier)),
len (TREE_STRING_LENGTH (identifier))
@@ -79,6 +99,17 @@ public:
if (flag_checking)
verify ();
}
+ attr_fnspec ()
+ : str (NULL), len (0)
+ {
+ }
+
+ /* Return true if fn spec is known. */
+ bool
+ known_p ()
+ {
+ return len;
+ }
/* Return true if arg I is specified. */
bool
@@ -94,7 +125,8 @@ public:
{
unsigned int idx = arg_idx (i);
gcc_checking_assert (arg_specified_p (i));
- return str[idx] == 'R' || str[idx] == 'W';
+ return str[idx] == 'R' || str[idx] == 'O'
+ || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9');
}
/* True if argument is used. */
@@ -112,9 +144,72 @@ public:
{
unsigned int idx = arg_idx (i);
gcc_checking_assert (arg_specified_p (i));
- return str[idx] == 'r' || str[idx] == 'R';
+ return str[idx] == 'r' || str[idx] == 'R' || (str[idx] >= '1' && str[idx] <= '9');
+ }
+
+ /* True if memory reached by the argument is read (directly or indirectly) */
+ bool
+ arg_maybe_read_p (unsigned int i)
+ {
+ unsigned int idx = arg_idx (i);
+ gcc_checking_assert (arg_specified_p (i));
+ return str[idx] != 'o' && str[idx] != 'O'
+ && str[idx] != 'x' && str[idx] != 'X';
+ }
+
+ /* True if memory reached by the argument is written.
+ (directly or indirectly) */
+ bool
+ arg_maybe_written_p (unsigned int i)
+ {
+ unsigned int idx = arg_idx (i);
+ gcc_checking_assert (arg_specified_p (i));
+ return str[idx] != 'r' && str[idx] != 'R'
+ && (str[idx] < '1' || str[idx] > '9')
+ && str[idx] != 'x' && str[idx] != 'X';
+ }
+
+ /* Return true if load of memory pointed to by argument I is specified
+ by another argument. In this case set ARG. */
+ bool
+ arg_max_access_size_given_by_arg_p (unsigned int i, unsigned int *arg)
+ {
+ unsigned int idx = arg_idx (i);
+ gcc_checking_assert (arg_specified_p (i));
+ if (str[idx + 1] >= '1' && str[idx + 1] <= '9')
+ {
+ *arg = str[idx + 1] - '1';
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /* Return true if the pointed-to type of the argument correspond to the
+ size of the memory acccess. */
+ bool
+ arg_access_size_given_by_type_p (unsigned int i)
+ {
+ unsigned int idx = arg_idx (i);
+ gcc_checking_assert (arg_specified_p (i));
+ return str[idx + 1] == 't';
}
+ /* Return true if memory pointer to by argument is copied to a memory
+ pointed to by a different argument (as in memcpy).
+ In this case set ARG. */
+ bool
+ arg_copied_to_arg_p (unsigned int i, unsigned int *arg)
+ {
+ unsigned int idx = arg_idx (i);
+ gcc_checking_assert (arg_specified_p (i));
+ if (str[idx] < '1' || str[idx] > '9')
+ return false;
+ *arg = str[idx] - '1';
+ return true;
+ }
+
+
/* True if the argument does not escape. */
bool
arg_noescape_p (unsigned int i)
@@ -122,7 +217,8 @@ public:
unsigned int idx = arg_idx (i);
gcc_checking_assert (arg_specified_p (i));
return str[idx] == 'w' || str[idx] == 'W'
- || str[idx] == 'R' || str[idx] == 'r';
+ || str[idx] == 'r' || str[idx] == 'R'
+ || str[idx] == 'o' || str[idx] == 'O';
}
/* Return true if function returns value of its parameter. If ARG_NO is
@@ -147,8 +243,39 @@ public:
return str[0] == 'm';
}
+ /* Return true if all memory read by the function is specified by fnspec. */
+ bool
+ global_memory_read_p ()
+ {
+ return str[1] != 'c' && str[1] != 'C';
+ }
+
+ /* Return true if all memory written by the function
+ is specified by fnspec. */
+ bool
+ global_memory_written_p ()
+ {
+ return str[1] != 'c' && str[1] != 'C' && str[1] != 'p' && str[1] != 'P';
+ }
+
+ bool
+ errno_maybe_written_p ()
+ {
+ return str[1] == 'C' || str[1] == 'P';
+ }
+
/* Check validity of the string. */
void verify ();
+
+ /* Return the fnspec string. */
+ const char *
+ get_str ()
+ {
+ return str;
+ }
};
+extern attr_fnspec gimple_call_fnspec (const gcall *stmt);
+extern attr_fnspec builtin_fnspec (tree);
+
#endif /* ATTR_FNSPEC_H */
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index 810b80b..c849b0d 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -678,6 +678,11 @@ bitmap_list_view (bitmap head)
}
head->tree_form = false;
+ if (!head->current)
+ {
+ head->current = head->first;
+ head->indx = head->current ? head->current->indx : 0;
+ }
}
/* Convert bitmap HEAD from linked-list view to splay-tree view.
diff --git a/gcc/brig/ChangeLog b/gcc/brig/ChangeLog
index b8fefa5..7d599fa 100644
--- a/gcc/brig/ChangeLog
+++ b/gcc/brig/ChangeLog
@@ -1,3 +1,20 @@
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ * lang.opt: Remove usage of Report.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (brig.serial): Change from goal to a variable.
+ (.PHONY): Drop brig.serial and brig.prev.
+ (brig1$(exeext)): Depend on $(brig.serial) rather than brig.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (brig.serial): New goal.
+ (.PHONY): Add brig.serial brig.prev.
+ (brig1$(exeext)): Depend on brig.prev. Call LINK_PROGRESS.
+
2020-08-03 Martin Jambor <mjambor@suse.cz>
* brigfrontend/brig-util.h (hsa_type_packed_p): Declared.
diff --git a/gcc/brig/Make-lang.in b/gcc/brig/Make-lang.in
index f553856..0141b982 100644
--- a/gcc/brig/Make-lang.in
+++ b/gcc/brig/Make-lang.in
@@ -29,6 +29,7 @@ GCCBRIG_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccbrig|sed \
# The name for selecting brig in LANGUAGES.
brig: brig1$(exeext)
+brig.serial = brig1$(exeext)
.PHONY: brig
@@ -81,15 +82,12 @@ BRIG_OBJS = \
brig_OBJS = $(BRIG_OBJS) brig/brigspec.o
-# brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
-# +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-# $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
-
-
-brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS) $(brig.prev)
+ @$(call LINK_PROGRESS,$(INDEX.brig),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(BRIG_OBJS) attribs.o $(BACKEND) $(LIBS) \
$(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.brig),end)
# Documentation.
diff --git a/gcc/brig/lang.opt b/gcc/brig/lang.opt
index b2bcc3b..39a4ddf 100644
--- a/gcc/brig/lang.opt
+++ b/gcc/brig/lang.opt
@@ -32,7 +32,7 @@ BRIG Separate Alias(d)
BRIG Joined Alias(d)
fassume-phsa
-BRIG Report Var(flag_assume_phsa) Init(1) Optimization
+BRIG Var(flag_assume_phsa) Init(1) Optimization
Assume we are finalizing for phsa and its libhsail-rt. Enables additional
phsa-specific optimizations (default).
diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def
index 778bc8a..0875724 100644
--- a/gcc/builtin-attrs.def
+++ b/gcc/builtin-attrs.def
@@ -67,6 +67,8 @@ DEF_ATTR_FOR_INT (6)
DEF_ATTR_TREE_LIST (ATTR_LIST_##ENUM, ATTR_NULL, \
ATTR_##ENUM, ATTR_NULL)
DEF_ATTR_FOR_STRING (STR1, "1 ")
+DEF_ATTR_FOR_STRING (STRERRNOC, ".C")
+DEF_ATTR_FOR_STRING (STRERRNOP, ".P")
#undef DEF_ATTR_FOR_STRING
/* Construct a tree for a list of two integers. */
@@ -136,6 +138,10 @@ DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST, \
ATTR_NULL, ATTR_NOTHROW_LIST)
DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LEAF_LIST, ATTR_CONST, \
ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ERRNOCONST_NOTHROW_LEAF_LIST, ATTR_FNSPEC,\
+ ATTR_LIST_STRERRNOC, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ERRNOPURE_NOTHROW_LEAF_LIST, ATTR_FNSPEC,\
+ ATTR_LIST_STRERRNOP, ATTR_NOTHROW_LEAF_LIST)
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LIST, ATTR_PURE, \
ATTR_NULL, ATTR_NOTHROW_LIST)
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LEAF_LIST, ATTR_PURE, \
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index c46b1bc..770f357 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -503,6 +503,7 @@ DEF_FUNCTION_TYPE_2 (BT_FN_INT_FEXCEPT_T_PTR_INT, BT_INT, BT_FEXCEPT_T_PTR,
BT_INT)
DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_FEXCEPT_T_PTR_INT, BT_INT,
BT_CONST_FEXCEPT_T_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_UINT8, BT_PTR, BT_CONST_PTR, BT_UINT8)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
@@ -637,6 +638,10 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_SIZE_SIZE_PTR, BT_VOID, BT_SIZE, BT_SIZE,
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_PTR_PTR, BT_UINT, BT_UINT, BT_PTR, BT_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_CONST_SIZE_BOOL,
BT_PTR, BT_PTR, BT_CONST_SIZE, BT_BOOL)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_SIZE_PTRMODE,
+ BT_PTR, BT_SIZE, BT_SIZE, BT_PTRMODE)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_UINT8_PTRMODE, BT_VOID, BT_PTR, BT_UINT8,
+ BT_PTRMODE)
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 72627b5..ffbb9b7 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -73,9 +73,11 @@ along with GCC; see the file COPYING3. If not see
#include "gomp-constants.h"
#include "omp-general.h"
#include "tree-dfa.h"
+#include "gimple-iterator.h"
#include "gimple-ssa.h"
#include "tree-ssa-live.h"
#include "tree-outof-ssa.h"
+#include "attr-fnspec.h"
struct target_builtins default_target_builtins;
#if SWITCHABLE_TARGET
@@ -181,9 +183,10 @@ static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
enum built_in_function);
static void maybe_emit_chk_warning (tree, enum built_in_function);
static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
-static void maybe_emit_free_warning (tree);
static tree fold_builtin_object_size (tree, tree);
static bool check_read_access (tree, tree, tree = NULL_TREE, int = 1);
+static bool compute_objsize_r (tree, int, access_ref *, ssa_name_limit_t &,
+ pointer_query *);
unsigned HOST_WIDE_INT target_newline;
unsigned HOST_WIDE_INT target_percent;
@@ -198,7 +201,8 @@ static void expand_builtin_sync_synchronize (void);
access_ref::access_ref (tree bound /* = NULL_TREE */,
bool minaccess /* = false */)
-: ref (), eval ([](tree x){ return x; }), trail1special (true), base0 (true)
+: ref (), eval ([](tree x){ return x; }), deref (), trail1special (true),
+ base0 (true), parmarray ()
{
/* Set to valid. */
offrng[0] = offrng[1] = 0;
@@ -221,6 +225,181 @@ access_ref::access_ref (tree bound /* = NULL_TREE */,
}
}
+/* Return the PHI node REF refers to or null if it doesn't. */
+
+gphi *
+access_ref::phi () const
+{
+ if (!ref || TREE_CODE (ref) != SSA_NAME)
+ return NULL;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
+ if (gimple_code (def_stmt) != GIMPLE_PHI)
+ return NULL;
+
+ return as_a <gphi *> (def_stmt);
+}
+
+/* Determine and return the largest object to which *THIS. If *THIS
+ refers to a PHI and PREF is nonnull, fill *PREF with the details
+ of the object determined by compute_objsize(ARG, OSTYPE) for each
+ PHI argument ARG. */
+
+tree
+access_ref::get_ref (vec<access_ref> *all_refs,
+ access_ref *pref /* = NULL */,
+ int ostype /* = 1 */,
+ ssa_name_limit_t *psnlim /* = NULL */,
+ pointer_query *qry /* = NULL */) const
+{
+ gphi *phi_stmt = this->phi ();
+ if (!phi_stmt)
+ return ref;
+
+ /* FIXME: Calling get_ref() with a null PSNLIM is dangerous and might
+ cause unbounded recursion. */
+ ssa_name_limit_t snlim_buf;
+ if (!psnlim)
+ psnlim = &snlim_buf;
+
+ if (!psnlim->visit_phi (ref))
+ return NULL_TREE;
+
+ /* Reflects the range of offsets of all PHI arguments refer to the same
+ object (i.e., have the same REF). */
+ access_ref same_ref;
+ /* The conservative result of the PHI reflecting the offset and size
+ of the largest PHI argument, regardless of whether or not they all
+ refer to the same object. */
+ pointer_query empty_qry;
+ if (!qry)
+ qry = &empty_qry;
+
+ access_ref phi_ref;
+ if (pref)
+ {
+ phi_ref = *pref;
+ same_ref = *pref;
+ }
+
+ /* Set if any argument is a function array (or VLA) parameter not
+ declared [static]. */
+ bool parmarray = false;
+ /* The size of the smallest object referenced by the PHI arguments. */
+ offset_int minsize = 0;
+ const offset_int maxobjsize = wi::to_offset (max_object_size ());
+ /* The offset of the PHI, not reflecting those of its arguments. */
+ const offset_int orng[2] = { phi_ref.offrng[0], phi_ref.offrng[1] };
+
+ const unsigned nargs = gimple_phi_num_args (phi_stmt);
+ for (unsigned i = 0; i < nargs; ++i)
+ {
+ access_ref phi_arg_ref;
+ tree arg = gimple_phi_arg_def (phi_stmt, i);
+ if (!compute_objsize_r (arg, ostype, &phi_arg_ref, *psnlim, qry)
+ || phi_arg_ref.sizrng[0] < 0)
+ /* A PHI with all null pointer arguments. */
+ return NULL_TREE;
+
+ /* Add PREF's offset to that of the argument. */
+ phi_arg_ref.add_offset (orng[0], orng[1]);
+ if (TREE_CODE (arg) == SSA_NAME)
+ qry->put_ref (arg, phi_arg_ref);
+
+ if (all_refs)
+ all_refs->safe_push (phi_arg_ref);
+
+ const bool arg_known_size = (phi_arg_ref.sizrng[0] != 0
+ || phi_arg_ref.sizrng[1] != maxobjsize);
+
+ parmarray |= phi_arg_ref.parmarray;
+
+ const bool nullp = integer_zerop (arg) && (i || i + 1 < nargs);
+
+ if (phi_ref.sizrng[0] < 0)
+ {
+ if (!nullp)
+ same_ref = phi_arg_ref;
+ phi_ref = phi_arg_ref;
+ if (arg_known_size)
+ minsize = phi_arg_ref.sizrng[0];
+ continue;
+ }
+
+ const bool phi_known_size = (phi_ref.sizrng[0] != 0
+ || phi_ref.sizrng[1] != maxobjsize);
+
+ if (phi_known_size && phi_arg_ref.sizrng[0] < minsize)
+ minsize = phi_arg_ref.sizrng[0];
+
+ /* Disregard null pointers in PHIs with two or more arguments.
+ TODO: Handle this better! */
+ if (nullp)
+ continue;
+
+ /* Determine the amount of remaining space in the argument. */
+ offset_int argrem[2];
+ argrem[1] = phi_arg_ref.size_remaining (argrem);
+
+ /* Determine the amount of remaining space computed so far and
+ if the remaining space in the argument is more use it instead. */
+ offset_int phirem[2];
+ phirem[1] = phi_ref.size_remaining (phirem);
+
+ if (phi_arg_ref.ref != same_ref.ref)
+ same_ref.ref = NULL_TREE;
+
+ if (phirem[1] < argrem[1]
+ || (phirem[1] == argrem[1]
+ && phi_ref.sizrng[1] < phi_arg_ref.sizrng[1]))
+ /* Use the argument with the most space remaining as the result,
+ or the larger one if the space is equal. */
+ phi_ref = phi_arg_ref;
+
+ /* Set SAME_REF.OFFRNG to the maximum range of all arguments. */
+ if (phi_arg_ref.offrng[0] < same_ref.offrng[0])
+ same_ref.offrng[0] = phi_arg_ref.offrng[0];
+ if (same_ref.offrng[1] < phi_arg_ref.offrng[1])
+ same_ref.offrng[1] = phi_arg_ref.offrng[1];
+ }
+
+ if (phi_ref.sizrng[0] < 0)
+ {
+ /* Fail if none of the PHI's arguments resulted in updating PHI_REF
+ (perhaps because they have all been already visited by prior
+ recursive calls). */
+ psnlim->leave_phi (ref);
+ return NULL_TREE;
+ }
+
+ if (!same_ref.ref && same_ref.offrng[0] != 0)
+ /* Clear BASE0 if not all the arguments refer to the same object and
+ if not all their offsets are zero-based. This allows the final
+ PHI offset to out of bounds for some arguments but not for others
+ (or negative even of all the arguments are BASE0), which is overly
+ permissive. */
+ phi_ref.base0 = false;
+
+ if (same_ref.ref)
+ phi_ref = same_ref;
+ else
+ {
+ /* Replace the lower bound of the largest argument with the size
+ of the smallest argument, and set PARMARRAY if any argument
+ was one. */
+ phi_ref.sizrng[0] = minsize;
+ phi_ref.parmarray = parmarray;
+ }
+
+ /* Avoid changing *THIS. */
+ if (pref && pref != this)
+ *pref = phi_ref;
+
+ psnlim->leave_phi (ref);
+
+ return phi_ref.ref;
+}
+
/* Return the maximum amount of space remaining and if non-null, set
argument to the minimum. */
@@ -317,10 +496,15 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max)
return;
}
- offrng[1] = maxoff;
offset_int absmax = wi::abs (max);
if (offrng[0] < absmax)
- offrng[0] += min;
+ {
+ offrng[0] += min;
+ /* Cap the lower bound at the upper (set to MAXOFF above)
+ to avoid inadvertently recreating an inverted range. */
+ if (offrng[1] < offrng[0])
+ offrng[0] = offrng[1];
+ }
else
offrng[0] = 0;
}
@@ -346,6 +530,210 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max)
}
}
+/* Set a bit for the PHI in VISITED and return true if it wasn't
+ already set. */
+
+bool
+ssa_name_limit_t::visit_phi (tree ssa_name)
+{
+ if (!visited)
+ visited = BITMAP_ALLOC (NULL);
+
+ /* Return false if SSA_NAME has already been visited. */
+ return bitmap_set_bit (visited, SSA_NAME_VERSION (ssa_name));
+}
+
+/* Clear a bit for the PHI in VISITED. */
+
+void
+ssa_name_limit_t::leave_phi (tree ssa_name)
+{
+ /* Return false if SSA_NAME has already been visited. */
+ bitmap_clear_bit (visited, SSA_NAME_VERSION (ssa_name));
+}
+
+/* Return false if the SSA_NAME chain length counter has reached
+ the limit, otherwise increment the counter and return true. */
+
+bool
+ssa_name_limit_t::next ()
+{
+ /* Return a negative value to let caller avoid recursing beyond
+ the specified limit. */
+ if (ssa_def_max == 0)
+ return false;
+
+ --ssa_def_max;
+ return true;
+}
+
+/* If the SSA_NAME has already been "seen" return a positive value.
+ Otherwise add it to VISITED. If the SSA_NAME limit has been
+ reached, return a negative value. Otherwise return zero. */
+
+int
+ssa_name_limit_t::next_phi (tree ssa_name)
+{
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (ssa_name);
+ /* Return a positive value if the PHI has already been visited. */
+ if (gimple_code (def_stmt) == GIMPLE_PHI
+ && !visit_phi (ssa_name))
+ return 1;
+ }
+
+ /* Return a negative value to let caller avoid recursing beyond
+ the specified limit. */
+ if (ssa_def_max == 0)
+ return -1;
+
+ --ssa_def_max;
+
+ return 0;
+}
+
+ssa_name_limit_t::~ssa_name_limit_t ()
+{
+ if (visited)
+ BITMAP_FREE (visited);
+}
+
+/* Default ctor. Initialize object with pointers to the range_query
+ and cache_type instances to use or null. */
+
+pointer_query::pointer_query (range_query *qry /* = NULL */,
+ cache_type *cache /* = NULL */)
+: rvals (qry), var_cache (cache), hits (), misses (),
+ failures (), depth (), max_depth ()
+{
+ /* No op. */
+}
+
+/* Return a pointer to the cached access_ref instance for the SSA_NAME
+ PTR if it's there or null otherwise. */
+
+const access_ref *
+pointer_query::get_ref (tree ptr, int ostype /* = 1 */) const
+{
+ if (!var_cache)
+ {
+ ++misses;
+ return NULL;
+ }
+
+ unsigned version = SSA_NAME_VERSION (ptr);
+ unsigned idx = version << 1 | (ostype & 1);
+ if (var_cache->indices.length () <= idx)
+ {
+ ++misses;
+ return NULL;
+ }
+
+ unsigned cache_idx = var_cache->indices[idx];
+ if (var_cache->access_refs.length () <= cache_idx)
+ {
+ ++misses;
+ return NULL;
+ }
+
+ access_ref &cache_ref = var_cache->access_refs[cache_idx];
+ if (cache_ref.ref)
+ {
+ ++hits;
+ return &cache_ref;
+ }
+
+ ++misses;
+ return NULL;
+}
+
+/* Retrieve the access_ref instance for a variable from the cache if it's
+ there or compute it and insert it into the cache if it's nonnonull. */
+
+bool
+pointer_query::get_ref (tree ptr, access_ref *pref, int ostype /* = 1 */)
+{
+ const unsigned version
+ = TREE_CODE (ptr) == SSA_NAME ? SSA_NAME_VERSION (ptr) : 0;
+
+ if (var_cache && version)
+ {
+ unsigned idx = version << 1 | (ostype & 1);
+ if (idx < var_cache->indices.length ())
+ {
+ unsigned cache_idx = var_cache->indices[idx] - 1;
+ if (cache_idx < var_cache->access_refs.length ()
+ && var_cache->access_refs[cache_idx].ref)
+ {
+ ++hits;
+ *pref = var_cache->access_refs[cache_idx];
+ return true;
+ }
+ }
+
+ ++misses;
+ }
+
+ if (!compute_objsize (ptr, ostype, pref, this))
+ {
+ ++failures;
+ return false;
+ }
+
+ return true;
+}
+
+/* Add a copy of the access_ref REF for the SSA_NAME to the cache if it's
+ nonnull. */
+
+void
+pointer_query::put_ref (tree ptr, const access_ref &ref, int ostype /* = 1 */)
+{
+ /* Only add populated/valid entries. */
+ if (!var_cache || !ref.ref || ref.sizrng[0] < 0)
+ return;
+
+ /* Add REF to the two-level cache. */
+ unsigned version = SSA_NAME_VERSION (ptr);
+ unsigned idx = version << 1 | (ostype & 1);
+
+ /* Grow INDICES if necessary. An index is valid if it's nonzero.
+ Its value minus one is the index into ACCESS_REFS. Not all
+ entries are valid. */
+ if (var_cache->indices.length () <= idx)
+ var_cache->indices.safe_grow_cleared (idx + 1);
+
+ if (!var_cache->indices[idx])
+ var_cache->indices[idx] = var_cache->access_refs.length () + 1;
+
+ /* Grow ACCESS_REF cache if necessary. An entry is valid if its
+ REF member is nonnull. All entries except for the last two
+ are valid. Once nonnull, the REF value must stay unchanged. */
+ unsigned cache_idx = var_cache->indices[idx];
+ if (var_cache->access_refs.length () <= cache_idx)
+ var_cache->access_refs.safe_grow_cleared (cache_idx + 1);
+
+ access_ref cache_ref = var_cache->access_refs[cache_idx - 1];
+ if (cache_ref.ref)
+ {
+ gcc_checking_assert (cache_ref.ref == ref.ref);
+ return;
+ }
+
+ cache_ref = ref;
+}
+
+/* Flush the cache if it's nonnull. */
+
+void
+pointer_query::flush_cache ()
+{
+ if (!var_cache)
+ return;
+ var_cache->indices.release ();
+ var_cache->access_refs.release ();
+}
+
/* Return true if NAME starts with __builtin_ or __sync_. */
static bool
@@ -2221,6 +2609,7 @@ type_to_class (tree type)
case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
? string_type_class : array_type_class);
case LANG_TYPE: return lang_type_class;
+ case OPAQUE_TYPE: return opaque_type_class;
default: return no_type_class;
}
}
@@ -3553,28 +3942,42 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
if (opt == OPT_Wstringop_overread)
{
+ bool maybe = pad && pad->src.phi ();
+
if (tree_int_cst_lt (maxobjsize, bndrng[0]))
{
if (bndrng[0] == bndrng[1])
warned = (func
? warning_at (loc, opt,
- "%K%qD specified bound %E "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%K%qD specified bound %E may "
+ "exceed maximum object size %E")
+ : G_("%K%qD specified bound %E "
+ "exceeds maximum object size %E")),
exp, func, bndrng[0], maxobjsize)
: warning_at (loc, opt,
- "%Kspecified bound %E "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%Kspecified bound %E may "
+ "exceed maximum object size %E")
+ : G_("%Kspecified bound %E "
+ "exceeds maximum object size %E")),
exp, bndrng[0], maxobjsize));
else
warned = (func
? warning_at (loc, opt,
- "%K%qD specified bound [%E, %E] "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%K%qD specified bound [%E, %E] may "
+ "exceed maximum object size %E")
+ : G_("%K%qD specified bound [%E, %E] "
+ "exceeds maximum object size %E")),
exp, func,
bndrng[0], bndrng[1], maxobjsize)
: warning_at (loc, opt,
- "%Kspecified bound [%E, %E] "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%Kspecified bound [%E, %E] may "
+ "exceed maximum object size %E")
+ : G_("%Kspecified bound [%E, %E] "
+ "exceeds maximum object size %E")),
exp, bndrng[0], bndrng[1], maxobjsize));
}
else if (!size || tree_int_cst_le (bndrng[0], size))
@@ -3582,22 +3985,34 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
warned = (func
? warning_at (loc, opt,
- "%K%qD specified bound %E exceeds "
- "source size %E",
+ (maybe
+ ? G_("%K%qD specified bound %E may exceed "
+ "source size %E")
+ : G_("%K%qD specified bound %E exceeds "
+ "source size %E")),
exp, func, bndrng[0], size)
: warning_at (loc, opt,
- "%Kspecified bound %E exceeds "
- "source size %E",
+ (maybe
+ ? G_("%Kspecified bound %E may exceed "
+ "source size %E")
+ : G_("%Kspecified bound %E exceeds "
+ "source size %E")),
exp, bndrng[0], size));
else
warned = (func
? warning_at (loc, opt,
- "%K%qD specified bound [%E, %E] exceeds "
- "source size %E",
+ (maybe
+ ? G_("%K%qD specified bound [%E, %E] may "
+ "exceed source size %E")
+ : G_("%K%qD specified bound [%E, %E] exceeds "
+ "source size %E")),
exp, func, bndrng[0], bndrng[1], size)
: warning_at (loc, opt,
- "%Kspecified bound [%E, %E] exceeds "
- "source size %E",
+ (maybe
+ ? G_("%Kspecified bound [%E, %E] may exceed "
+ "source size %E")
+ : G_("%Kspecified bound [%E, %E] exceeds "
+ "source size %E")),
exp, bndrng[0], bndrng[1], size));
if (warned)
{
@@ -3616,28 +4031,41 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
return warned;
}
+ bool maybe = pad && pad->dst.phi ();
if (tree_int_cst_lt (maxobjsize, bndrng[0]))
{
if (bndrng[0] == bndrng[1])
warned = (func
? warning_at (loc, opt,
- "%K%qD specified size %E "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%K%qD specified size %E may "
+ "exceed maximum object size %E")
+ : G_("%K%qD specified size %E "
+ "exceeds maximum object size %E")),
exp, func, bndrng[0], maxobjsize)
: warning_at (loc, opt,
- "%Kspecified size %E "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%Kspecified size %E may exceed "
+ "maximum object size %E")
+ : G_("%Kspecified size %E exceeds "
+ "maximum object size %E")),
exp, bndrng[0], maxobjsize));
else
warned = (func
? warning_at (loc, opt,
- "%K%qD specified size between %E and %E "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%K%qD specified size between %E and %E "
+ "may exceed maximum object size %E")
+ : G_("%K%qD specified size between %E and %E "
+ "exceeds maximum object size %E")),
exp, func,
bndrng[0], bndrng[1], maxobjsize)
: warning_at (loc, opt,
- "%Kspecified size between %E and %E "
- "exceeds maximum object size %E",
+ (maybe
+ ? G_("%Kspecified size between %E and %E "
+ "may exceed maximum object size %E")
+ : G_("%Kspecified size between %E and %E "
+ "exceeds maximum object size %E")),
exp, bndrng[0], bndrng[1], maxobjsize));
}
else if (!size || tree_int_cst_le (bndrng[0], size))
@@ -3645,22 +4073,34 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
warned = (func
? warning_at (loc, OPT_Wstringop_overflow_,
- "%K%qD specified bound %E exceeds "
- "destination size %E",
+ (maybe
+ ? G_("%K%qD specified bound %E may exceed "
+ "destination size %E")
+ : G_("%K%qD specified bound %E exceeds "
+ "destination size %E")),
exp, func, bndrng[0], size)
: warning_at (loc, OPT_Wstringop_overflow_,
- "%Kspecified bound %E exceeds "
- "destination size %E",
+ (maybe
+ ? G_("%Kspecified bound %E may exceed "
+ "destination size %E")
+ : G_("%Kspecified bound %E exceeds "
+ "destination size %E")),
exp, bndrng[0], size));
else
warned = (func
? warning_at (loc, OPT_Wstringop_overflow_,
- "%K%qD specified bound [%E, %E] exceeds "
- "destination size %E",
+ (maybe
+ ? G_("%K%qD specified bound [%E, %E] may exceed "
+ "destination size %E")
+ : G_("%K%qD specified bound [%E, %E] exceeds "
+ "destination size %E")),
exp, func, bndrng[0], bndrng[1], size)
: warning_at (loc, OPT_Wstringop_overflow_,
- "%Kspecified bound [%E, %E] exceeds "
- "destination size %E",
+ (maybe
+ ? G_("%Kspecified bound [%E, %E] exceeds "
+ "destination size %E")
+ : G_("%Kspecified bound [%E, %E] exceeds "
+ "destination size %E")),
exp, bndrng[0], bndrng[1], size));
if (warned)
@@ -3689,7 +4129,7 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
static bool
warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
- tree size, bool write, bool read)
+ tree size, bool write, bool read, bool maybe)
{
bool warned = false;
@@ -3698,40 +4138,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
if (tree_int_cst_equal (range[0], range[1]))
warned = (func
? warning_n (loc, opt, tree_to_uhwi (range[0]),
- "%K%qD accessing %E byte in a region "
- "of size %E",
- "%K%qD accessing %E bytes in a region "
- "of size %E",
+ (maybe
+ ? G_("%K%qD may access %E byte in a region "
+ "of size %E")
+ : G_("%K%qD accessing %E byte in a region "
+ "of size %E")),
+ (maybe
+ ? G_ ("%K%qD may access %E bytes in a region "
+ "of size %E")
+ : G_ ("%K%qD accessing %E bytes in a region "
+ "of size %E")),
exp, func, range[0], size)
: warning_n (loc, opt, tree_to_uhwi (range[0]),
- "%Kaccessing %E byte in a region "
- "of size %E",
- "%Kaccessing %E bytes in a region "
- "of size %E",
+ (maybe
+ ? G_("%Kmay access %E byte in a region "
+ "of size %E")
+ : G_("%Kaccessing %E byte in a region "
+ "of size %E")),
+ (maybe
+ ? G_("%Kmay access %E bytes in a region "
+ "of size %E")
+ : G_("%Kaccessing %E bytes in a region "
+ "of size %E")),
exp, range[0], size));
else if (tree_int_cst_sign_bit (range[1]))
{
/* Avoid printing the upper bound if it's invalid. */
warned = (func
? warning_at (loc, opt,
- "%K%qD accessing %E or more bytes in "
- "a region of size %E",
+ (maybe
+ ? G_("%K%qD may access %E or more bytes "
+ "in a region of size %E")
+ : G_("%K%qD accessing %E or more bytes "
+ "in a region of size %E")),
exp, func, range[0], size)
: warning_at (loc, opt,
- "%Kaccessing %E or more bytes in "
- "a region of size %E",
+ (maybe
+ ? G_("%Kmay access %E or more bytes "
+ "in a region of size %E")
+ : G_("%Kaccessing %E or more bytes "
+ "in a region of size %E")),
exp, range[0], size));
}
else
warned = (func
? warning_at (loc, opt,
- "%K%qD accessing between %E and %E bytes "
- "in a region of size %E",
+ (maybe
+ ? G_("%K%qD may access between %E and %E "
+ "bytes in a region of size %E")
+ : G_("%K%qD accessing between %E and %E "
+ "bytes in a region of size %E")),
exp, func, range[0], range[1],
size)
: warning_at (loc, opt,
- "%Kaccessing between %E and %E bytes "
- "in a region of size %E",
+ (maybe
+ ? G_("%Kmay access between %E and %E bytes "
+ "in a region of size %E")
+ : G_("%Kaccessing between %E and %E bytes "
+ "in a region of size %E")),
exp, range[0], range[1],
size));
return warned;
@@ -3742,44 +4206,69 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
if (tree_int_cst_equal (range[0], range[1]))
warned = (func
? warning_n (loc, opt, tree_to_uhwi (range[0]),
- "%K%qD writing %E byte into a region "
- "of size %E overflows the destination",
- "%K%qD writing %E bytes into a region "
- "of size %E overflows the destination",
+ (maybe
+ ? G_("%K%qD may write %E byte into a region "
+ "of size %E")
+ : G_("%K%qD writing %E byte into a region "
+ "of size %E overflows the destination")),
+ (maybe
+ ? G_("%K%qD may write %E bytes into a region "
+ "of size %E")
+ : G_("%K%qD writing %E bytes into a region "
+ "of size %E overflows the destination")),
exp, func, range[0], size)
: warning_n (loc, opt, tree_to_uhwi (range[0]),
- "%Kwriting %E byte into a region "
- "of size %E overflows the destination",
- "%Kwriting %E bytes into a region "
- "of size %E overflows the destination",
+ (maybe
+ ? G_("%Kmay write %E byte into a region "
+ "of size %E")
+ : G_("%Kwriting %E byte into a region "
+ "of size %E overflows the destination")),
+ (maybe
+ ? G_("%Kmay write %E bytes into a region "
+ "of size %E")
+ : G_("%Kwriting %E bytes into a region "
+ "of size %E overflows the destination")),
exp, range[0], size));
else if (tree_int_cst_sign_bit (range[1]))
{
/* Avoid printing the upper bound if it's invalid. */
warned = (func
? warning_at (loc, opt,
- "%K%qD writing %E or more bytes into "
- "a region of size %E overflows "
- "the destination",
+ (maybe
+ ? G_("%K%qD may write %E or more bytes "
+ "into a region of size %E "
+ "the destination")
+ : G_("%K%qD writing %E or more bytes "
+ "into a region of size %E overflows "
+ "the destination")),
exp, func, range[0], size)
: warning_at (loc, opt,
- "%Kwriting %E or more bytes into "
- "a region of size %E overflows "
- "the destination",
+ (maybe
+ ? G_("%Kmay write %E or more bytes into "
+ "a region of size %E")
+ : G_("%Kwriting %E or more bytes into "
+ "a region of size %E overflows "
+ "the destination")),
exp, range[0], size));
}
else
warned = (func
? warning_at (loc, opt,
- "%K%qD writing between %E and %E bytes "
- "into a region of size %E overflows "
- "the destination",
+ (maybe
+ ? G_("%K%qD may write between %E and %E bytes "
+ "into a region of size %E")
+ : G_("%K%qD writing between %E and %E bytes "
+ "into a region of size %E overflows "
+ "the destination")),
exp, func, range[0], range[1],
size)
: warning_at (loc, opt,
- "%Kwriting between %E and %E bytes "
- "into a region of size %E overflows "
- "the destination",
+ (maybe
+ ? G_("%Kmay write between %E and %E bytes "
+ "into a region of size %E")
+ : G_("%Kwriting between %E and %E bytes "
+ "into a region of size %E overflows "
+ "the destination")),
exp, range[0], range[1],
size));
return warned;
@@ -3791,35 +4280,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
warned = (func
? warning_n (loc, OPT_Wstringop_overread,
tree_to_uhwi (range[0]),
- "%K%qD reading %E byte from a region of size %E",
- "%K%qD reading %E bytes from a region of size %E", exp, func, range[0], size)
+ (maybe
+ ? G_("%K%qD may reade %E byte from a region "
+ "of size %E")
+ : G_("%K%qD reading %E byte from a region "
+ "of size %E")),
+ (maybe
+ ? G_("%K%qD may read %E bytes from a region "
+ "of size %E")
+ : G_("%K%qD reading %E bytes from a region "
+ "of size %E")),
+ exp, func, range[0], size)
: warning_n (loc, OPT_Wstringop_overread,
tree_to_uhwi (range[0]),
- "%Kreading %E byte from a region of size %E",
- "%Kreading %E bytes from a region of size %E",
+ (maybe
+ ? G_("%Kmay read %E byte from a region "
+ "of size %E")
+ : G_("%Kreading %E byte from a region "
+ "of size %E")),
+ (maybe
+ ? G_("%Kmay read %E bytes from a region "
+ "of size %E")
+ : G_("%Kreading %E bytes from a region "
+ "of size %E")),
exp, range[0], size));
else if (tree_int_cst_sign_bit (range[1]))
{
/* Avoid printing the upper bound if it's invalid. */
warned = (func
? warning_at (loc, OPT_Wstringop_overread,
- "%K%qD reading %E or more bytes from "
- "a region of size %E",
+ (maybe
+ ? G_("%K%qD may read %E or more bytes "
+ "from a region of size %E")
+ : G_("%K%qD reading %E or more bytes "
+ "from a region of size %E")),
exp, func, range[0], size)
: warning_at (loc, OPT_Wstringop_overread,
- "%Kreading %E or more bytes from a region "
- "of size %E",
+ (maybe
+ ? G_("%Kmay read %E or more bytes "
+ "from a region of size %E")
+ : G_("%Kreading %E or more bytes "
+ "from a region of size %E")),
exp, range[0], size));
}
else
warned = (func
? warning_at (loc, OPT_Wstringop_overread,
- "%K%qD reading between %E and %E bytes from "
- "a region of size %E",
+ (maybe
+ ? G_("%K%qD may read between %E and %E bytes "
+ "from a region of size %E")
+ : G_("%K%qD reading between %E and %E bytes "
+ "from a region of size %E")),
exp, func, range[0], range[1], size)
: warning_at (loc, opt,
- "%K reading between %E and %E bytes from "
- "a region of size %E",
+ (maybe
+ ? G_("%Kmay read between %E and %E bytes "
+ "from a region of size %E")
+ : G_("%Kreading between %E and %E bytes "
+ "from a region of size %E")),
exp, range[0], range[1], size));
if (warned)
@@ -3871,28 +4389,61 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
return warned;
}
-/* Issue an inform message describing the target of an access REF.
+/* Issue one inform message describing each target of an access REF.
WRITE is set for a write access and clear for a read access. */
-static void
-inform_access (const access_ref &ref, access_mode mode)
+void
+access_ref::inform_access (access_mode mode) const
{
- if (!ref.ref)
+ const access_ref &aref = *this;
+ if (!aref.ref)
return;
+ if (aref.phi ())
+ {
+ /* Set MAXREF to refer to the largest object and fill ALL_REFS
+ with data for all objects referenced by the PHI arguments. */
+ access_ref maxref;
+ auto_vec<access_ref> all_refs;
+ if (!get_ref (&all_refs, &maxref))
+ return;
+
+ /* Except for MAXREF, the rest of the arguments' offsets need not
+ reflect one added to the PHI itself. Determine the latter from
+ MAXREF on which the result is based. */
+ const offset_int orng[] =
+ {
+ offrng[0] - maxref.offrng[0],
+ wi::smax (offrng[1] - maxref.offrng[1], offrng[0]),
+ };
+
+ /* Add the final PHI's offset to that of each of the arguments
+ and recurse to issue an inform message for it. */
+ for (unsigned i = 0; i != all_refs.length (); ++i)
+ {
+ /* Skip any PHIs; those could lead to infinite recursion. */
+ if (all_refs[i].phi ())
+ continue;
+
+ all_refs[i].add_offset (orng[0], orng[1]);
+ all_refs[i].inform_access (mode);
+ }
+ return;
+ }
+
/* Convert offset range and avoid including a zero range since it
isn't necessarily meaningful. */
HOST_WIDE_INT diff_min = tree_to_shwi (TYPE_MIN_VALUE (ptrdiff_type_node));
HOST_WIDE_INT diff_max = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
HOST_WIDE_INT minoff;
HOST_WIDE_INT maxoff = diff_max;
- if (wi::fits_shwi_p (ref.offrng[0]))
- minoff = ref.offrng[0].to_shwi ();
+ if (wi::fits_shwi_p (aref.offrng[0]))
+ minoff = aref.offrng[0].to_shwi ();
else
- minoff = ref.offrng[0] < 0 ? diff_min : diff_max;
+ minoff = aref.offrng[0] < 0 ? diff_min : diff_max;
- if (wi::fits_shwi_p (ref.offrng[1]))
- maxoff = ref.offrng[1].to_shwi ();
+ if (wi::fits_shwi_p (aref.offrng[1]))
+ maxoff = aref.offrng[1].to_shwi ();
if (maxoff <= diff_min || maxoff >= diff_max)
/* Avoid mentioning an upper bound that's equal to or in excess
@@ -3902,110 +4453,127 @@ inform_access (const access_ref &ref, access_mode mode)
/* Convert size range and always include it since all sizes are
meaningful. */
unsigned long long minsize = 0, maxsize = 0;
- if (wi::fits_shwi_p (ref.sizrng[0])
- && wi::fits_shwi_p (ref.sizrng[1]))
+ if (wi::fits_shwi_p (aref.sizrng[0])
+ && wi::fits_shwi_p (aref.sizrng[1]))
{
- minsize = ref.sizrng[0].to_shwi ();
- maxsize = ref.sizrng[1].to_shwi ();
+ minsize = aref.sizrng[0].to_shwi ();
+ maxsize = aref.sizrng[1].to_shwi ();
}
+ /* SIZRNG doesn't necessarily have the same range as the allocation
+ size determined by gimple_call_alloc_size (). */
char sizestr[80];
- location_t loc;
- tree allocfn = NULL_TREE;
- if (TREE_CODE (ref.ref) == SSA_NAME)
- {
- gimple *stmt = SSA_NAME_DEF_STMT (ref.ref);
- gcc_assert (is_gimple_call (stmt));
- loc = gimple_location (stmt);
- allocfn = gimple_call_fndecl (stmt);
- if (!allocfn)
- /* Handle calls through pointers to functions. */
- allocfn = gimple_call_fn (stmt);
-
- /* SIZRNG doesn't necessarily have the same range as the allocation
- size determined by gimple_call_alloc_size (). */
+ if (minsize == maxsize)
+ sprintf (sizestr, "%llu", minsize);
+ else
+ sprintf (sizestr, "[%llu, %llu]", minsize, maxsize);
+
+ char offstr[80];
+ if (minoff == 0
+ && (maxoff == 0 || aref.sizrng[1] <= maxoff))
+ offstr[0] = '\0';
+ else if (minoff == maxoff)
+ sprintf (offstr, "%lli", (long long) minoff);
+ else
+ sprintf (offstr, "[%lli, %lli]", (long long) minoff, (long long) maxoff);
- if (minsize == maxsize)
- sprintf (sizestr, "%llu", minsize);
- else
- sprintf (sizestr, "[%llu, %llu]", minsize, maxsize);
+ location_t loc = UNKNOWN_LOCATION;
+ tree ref = this->ref;
+ tree allocfn = NULL_TREE;
+ if (TREE_CODE (ref) == SSA_NAME)
+ {
+ gimple *stmt = SSA_NAME_DEF_STMT (ref);
+ if (is_gimple_call (stmt))
+ {
+ loc = gimple_location (stmt);
+ if (gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
+ {
+ /* Strip the SSA_NAME suffix from the variable name and
+ recreate an identifier with the VLA's original name. */
+ ref = gimple_call_lhs (stmt);
+ ref = SSA_NAME_IDENTIFIER (ref);
+ const char *id = IDENTIFIER_POINTER (ref);
+ size_t len = strcspn (id, ".$");
+ if (!len)
+ len = strlen (id);
+ ref = get_identifier_with_length (id, len);
+ }
+ else
+ {
+ /* Except for VLAs, retrieve the allocation function. */
+ allocfn = gimple_call_fndecl (stmt);
+ if (!allocfn)
+ allocfn = gimple_call_fn (stmt);
+ if (TREE_CODE (allocfn) == SSA_NAME)
+ {
+ /* For an ALLOC_CALL via a function pointer make a small
+ effort to determine the destination of the pointer. */
+ gimple *def = SSA_NAME_DEF_STMT (allocfn);
+ if (gimple_assign_single_p (def))
+ {
+ tree rhs = gimple_assign_rhs1 (def);
+ if (DECL_P (rhs))
+ allocfn = rhs;
+ else if (TREE_CODE (rhs) == COMPONENT_REF)
+ allocfn = TREE_OPERAND (rhs, 1);
+ }
+ }
+ }
+ }
+ else if (gimple_nop_p (stmt))
+ /* Handle DECL_PARM below. */
+ ref = SSA_NAME_VAR (ref);
}
- else if (DECL_P (ref.ref))
- loc = DECL_SOURCE_LOCATION (ref.ref);
- else if (EXPR_P (ref.ref) && EXPR_HAS_LOCATION (ref.ref))
- loc = EXPR_LOCATION (ref.ref);
- else
+
+ if (DECL_P (ref))
+ loc = DECL_SOURCE_LOCATION (ref);
+ else if (EXPR_P (ref) && EXPR_HAS_LOCATION (ref))
+ loc = EXPR_LOCATION (ref);
+ else if (TREE_CODE (ref) != IDENTIFIER_NODE
+ && TREE_CODE (ref) != SSA_NAME)
return;
if (mode == access_read_write || mode == access_write_only)
{
if (allocfn == NULL_TREE)
{
- if (minoff == maxoff)
- {
- if (minoff == 0)
- inform (loc, "destination object %qE", ref.ref);
- else
- inform (loc, "at offset %wi into destination object %qE",
- minoff, ref.ref);
- }
+ if (*offstr)
+ inform (loc, "at offset %s into destination object %qE of size %s",
+ offstr, ref, sizestr);
else
- inform (loc, "at offset [%wi, %wi] into destination object %qE",
- minoff, maxoff, ref.ref);
+ inform (loc, "destination object %qE of size %s", ref, sizestr);
return;
}
- if (minoff == maxoff)
- {
- if (minoff == 0)
- inform (loc, "destination object of size %s allocated by %qE",
- sizestr, allocfn);
- else
- inform (loc,
- "at offset %wi into destination object of size %s "
- "allocated by %qE", minoff, sizestr, allocfn);
- }
- else
+ if (*offstr)
inform (loc,
- "at offset [%wi, %wi] into destination object of size %s "
- "allocated by %qE",
- minoff, maxoff, sizestr, allocfn);
-
+ "at offset %s into destination object of size %s "
+ "allocated by %qE", offstr, sizestr, allocfn);
+ else
+ inform (loc, "destination object of size %s allocated by %qE",
+ sizestr, allocfn);
return;
}
- if (DECL_P (ref.ref))
+ if (DECL_P (ref))
{
- if (minoff == maxoff)
- {
- if (minoff == 0)
- inform (loc, "source object %qD", ref.ref);
- else
- inform (loc, "at offset %wi into source object %qD",
- minoff, ref.ref);
- }
+ if (*offstr)
+ inform (loc, "at offset %s into source object %qD of size %s",
+ offstr, ref, sizestr);
else
- inform (loc, "at offset [%wi, %wi] into source object %qD",
- minoff, maxoff, ref.ref);
+ inform (loc, "source object %qD of size %s", ref, sizestr);
+
return;
}
- if (minoff == maxoff)
- {
- if (minoff == 0)
- inform (loc, "source object of size %s allocated by %qE",
- sizestr, allocfn);
- else
- inform (loc,
- "at offset %wi into source object of size %s "
- "allocated by %qE", minoff, sizestr, allocfn);
- }
- else
+ if (*offstr)
inform (loc,
- "at offset [%wi, %wi] into source object of size %s "
- "allocated by %qE",
- minoff, maxoff, sizestr, allocfn);
+ "at offset %s into source object of size %s allocated by %qE",
+ offstr, sizestr, allocfn);
+ else
+ inform (loc, "source object of size %s allocated by %qE",
+ sizestr, allocfn);
}
/* Helper to set RANGE to the range of BOUND if it's nonnull, bounded
@@ -4170,9 +4738,7 @@ check_access (tree exp, tree dstwrite,
&& TREE_CODE (range[0]) == INTEGER_CST
&& tree_int_cst_lt (maxobjsize, range[0]))
{
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
NULL_TREE, pad);
return false;
@@ -4198,9 +4764,7 @@ check_access (tree exp, tree dstwrite,
|| (pad && pad->dst.ref && TREE_NO_WARNING (pad->dst.ref)))
return false;
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
bool warned = false;
if (dstwrite == slen && at_least_one)
{
@@ -4225,17 +4789,18 @@ check_access (tree exp, tree dstwrite,
= mode == access_read_only || mode == access_read_write;
const bool write
= mode == access_write_only || mode == access_read_write;
+ const bool maybe = pad && pad->dst.parmarray;
warned = warn_for_access (loc, func, exp,
OPT_Wstringop_overflow_,
range, dstsize,
- write, read && !builtin);
+ write, read && !builtin, maybe);
}
if (warned)
{
TREE_NO_WARNING (exp) = true;
if (pad)
- inform_access (pad->dst, pad->mode);
+ pad->dst.inform_access (pad->mode);
}
/* Return error when an overflow has been detected. */
@@ -4252,9 +4817,7 @@ check_access (tree exp, tree dstwrite,
PAD is nonnull and BNDRNG is valid. */
get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
tree size = dstsize;
if (pad && pad->mode == access_read_only)
size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4313,17 +4876,16 @@ check_access (tree exp, tree dstwrite,
|| (pad && pad->src.ref && TREE_NO_WARNING (pad->src.ref)))
return false;
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
const bool read
= mode == access_read_only || mode == access_read_write;
+ const bool maybe = pad && pad->dst.parmarray;
if (warn_for_access (loc, func, exp, OPT_Wstringop_overread, range,
- slen, false, read))
+ slen, false, read, maybe))
{
TREE_NO_WARNING (exp) = true;
if (pad)
- inform_access (pad->src, access_read_only);
+ pad->src.inform_access (access_read_only);
}
return false;
}
@@ -4455,11 +5017,12 @@ gimple_call_alloc_size (gimple *stmt, wide_int rng1[2] /* = NULL */,
/* For an access to an object referenced to by the function parameter PTR
of pointer type, and set RNG[] to the range of sizes of the object
obtainedfrom the attribute access specification for the current function.
+ Set STATIC_ARRAY if the array parameter has been declared [static].
Return the function parameter on success and null otherwise. */
tree
gimple_parm_array_size (tree ptr, wide_int rng[2],
- range_query * /* = NULL */)
+ bool *static_array /* = NULL */)
{
/* For a function argument try to determine the byte size of the array
from the current function declaratation (e.g., attribute access or
@@ -4491,6 +5054,9 @@ gimple_parm_array_size (tree ptr, wide_int rng[2],
if (warn_array_parameter < 2 && !access->static_p)
return NULL_TREE;
+ if (static_array)
+ *static_array = access->static_p;
+
rng[0] = wi::zero (prec);
rng[1] = wi::uhwi (access->minsize, prec);
/* Multiply the array bound encoded in the attribute by the size
@@ -4531,6 +5097,8 @@ get_offset_range (tree x, gimple *stmt, offset_int r[2], range_query *rvals)
x = TREE_OPERAND (x, 0);
tree type = TREE_TYPE (x);
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ return false;
if (TREE_CODE (x) != INTEGER_CST
&& TREE_CODE (x) != SSA_NAME)
@@ -4638,6 +5206,84 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2],
return NULL_TREE;
}
+/* A helper of compute_objsize() to determine the size from an assignment
+ statement STMT with the RHS of either MIN_EXPR or MAX_EXPR. */
+
+static bool
+handle_min_max_size (gimple *stmt, int ostype, access_ref *pref,
+ ssa_name_limit_t &snlim, pointer_query *qry)
+{
+ tree_code code = gimple_assign_rhs_code (stmt);
+
+ tree ptr = gimple_assign_rhs1 (stmt);
+
+ /* In a valid MAX_/MIN_EXPR both operands must refer to the same array.
+ Determine the size/offset of each and use the one with more or less
+ space remaining, respectively. If either fails, use the information
+ determined from the other instead, adjusted up or down as appropriate
+ for the expression. */
+ access_ref aref[2] = { *pref, *pref };
+ if (!compute_objsize_r (ptr, ostype, &aref[0], snlim, qry))
+ {
+ aref[0].base0 = false;
+ aref[0].offrng[0] = aref[0].offrng[1] = 0;
+ aref[0].add_max_offset ();
+ aref[0].set_max_size_range ();
+ }
+
+ ptr = gimple_assign_rhs2 (stmt);
+ if (!compute_objsize_r (ptr, ostype, &aref[1], snlim, qry))
+ {
+ aref[1].base0 = false;
+ aref[1].offrng[0] = aref[1].offrng[1] = 0;
+ aref[1].add_max_offset ();
+ aref[1].set_max_size_range ();
+ }
+
+ if (!aref[0].ref && !aref[1].ref)
+ /* Fail if the identity of neither argument could be determined. */
+ return false;
+
+ bool i0 = false;
+ if (aref[0].ref && aref[0].base0)
+ {
+ if (aref[1].ref && aref[1].base0)
+ {
+ /* If the object referenced by both arguments has been determined
+ set *PREF to the one with more or less space remainng, whichever
+ is appopriate for CODE.
+ TODO: Indicate when the objects are distinct so it can be
+ diagnosed. */
+ i0 = code == MAX_EXPR;
+ const bool i1 = !i0;
+
+ if (aref[i0].size_remaining () < aref[i1].size_remaining ())
+ *pref = aref[i1];
+ else
+ *pref = aref[i0];
+ return true;
+ }
+
+ /* If only the object referenced by one of the arguments could be
+ determined, use it and... */
+ *pref = aref[0];
+ i0 = true;
+ }
+ else
+ *pref = aref[1];
+
+ const bool i1 = !i0;
+ /* ...see if the offset obtained from the other pointer can be used
+ to tighten up the bound on the offset obtained from the first. */
+ if ((code == MAX_EXPR && aref[i1].offrng[1] < aref[i0].offrng[0])
+ || (code == MIN_EXPR && aref[i0].offrng[0] < aref[i1].offrng[1]))
+ {
+ pref->offrng[0] = aref[i0].offrng[0];
+ pref->offrng[1] = aref[i0].offrng[1];
+ }
+ return true;
+}
+
/* Helper to compute the size of the object referenced by the PTR
expression which must have pointer type, using Object Size type
OSTYPE (only the least significant 2 bits are used).
@@ -4645,7 +5291,7 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2],
if it's unique, otherwise to null, PREF->OFFRNG to the range of
offsets into it, and PREF->SIZRNG to the range of sizes of
the object(s).
- VISITED is used to avoid visiting the same PHI operand multiple
+ SNLIM is used to avoid visiting the same PHI operand multiple
times, and, when nonnull, RVALS to determine range information.
Returns true on success, false when a meaningful size (or range)
cannot be determined.
@@ -4654,14 +5300,17 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2],
to influence code generation or optimization. */
static bool
-compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
- range_query *rvals)
+compute_objsize_r (tree ptr, int ostype, access_ref *pref,
+ ssa_name_limit_t &snlim, pointer_query *qry)
{
STRIP_NOPS (ptr);
const bool addr = TREE_CODE (ptr) == ADDR_EXPR;
if (addr)
- ptr = TREE_OPERAND (ptr, 0);
+ {
+ --pref->deref;
+ ptr = TREE_OPERAND (ptr, 0);
+ }
if (DECL_P (ptr))
{
@@ -4687,11 +5336,12 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
}
const tree_code code = TREE_CODE (ptr);
+ range_query *const rvals = qry ? qry->rvals : NULL;
if (code == BIT_FIELD_REF)
{
tree ref = TREE_OPERAND (ptr, 0);
- if (!compute_objsize (ref, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (ref, ostype, pref, snlim, qry))
return false;
offset_int off = wi::to_offset (pref->eval (TREE_OPERAND (ptr, 2)));
@@ -4702,6 +5352,10 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
if (code == COMPONENT_REF)
{
tree ref = TREE_OPERAND (ptr, 0);
+ if (TREE_CODE (TREE_TYPE (ref)) == UNION_TYPE)
+ /* In accesses through union types consider the entire unions
+ rather than just their members. */
+ ostype = 0;
tree field = TREE_OPERAND (ptr, 1);
if (ostype == 0)
@@ -4709,7 +5363,7 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
/* In OSTYPE zero (for raw memory functions like memcpy), use
the maximum size instead if the identity of the enclosing
object cannot be determined. */
- if (!compute_objsize (ref, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (ref, ostype, pref, snlim, qry))
return false;
/* Otherwise, use the size of the enclosing object and add
@@ -4719,9 +5373,17 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
pref->add_offset (wi::to_offset (offset));
else
pref->add_max_offset ();
+
+ if (!pref->ref)
+ /* REF may have been already set to an SSA_NAME earlier
+ to provide better context for diagnostics. In that case,
+ leave it unchanged. */
+ pref->ref = ref;
return true;
}
+ pref->ref = field;
+
if (!addr && POINTER_TYPE_P (TREE_TYPE (field)))
{
/* Set maximum size if the reference is to the pointer member
@@ -4730,8 +5392,6 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
return true;
}
- pref->ref = field;
-
/* SAM is set for array members that might need special treatment. */
special_array_member sam;
tree size = component_ref_size (ptr, &sam);
@@ -4758,9 +5418,11 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
if (code == ARRAY_REF || code == MEM_REF)
{
+ ++pref->deref;
+
tree ref = TREE_OPERAND (ptr, 0);
tree reftype = TREE_TYPE (ref);
- if (code == ARRAY_REF
+ if (!addr && code == ARRAY_REF
&& TREE_CODE (TREE_TYPE (reftype)) == POINTER_TYPE)
/* Avoid arrays of pointers. FIXME: Hande pointers to arrays
of known bound. */
@@ -4778,7 +5440,7 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
return false;
}
- if (!compute_objsize (ref, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (ref, ostype, pref, snlim, qry))
return false;
offset_int orng[2];
@@ -4844,7 +5506,7 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
if (code == TARGET_MEM_REF)
{
tree ref = TREE_OPERAND (ptr, 0);
- if (!compute_objsize (ref, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (ref, ostype, pref, snlim, qry))
return false;
/* TODO: Handle remaining operands. Until then, add maximum offset. */
@@ -4871,15 +5533,20 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
if (code == STRING_CST)
{
pref->sizrng[0] = pref->sizrng[1] = TREE_STRING_LENGTH (ptr);
+ pref->ref = ptr;
return true;
}
if (code == POINTER_PLUS_EXPR)
{
tree ref = TREE_OPERAND (ptr, 0);
- if (!compute_objsize (ref, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (ref, ostype, pref, snlim, qry))
return false;
+ /* Clear DEREF since the offset is being applied to the target
+ of the dereference. */
+ pref->deref = 0;
+
offset_int orng[2];
tree off = pref->eval (TREE_OPERAND (ptr, 1));
if (get_offset_range (off, NULL, orng, rvals))
@@ -4892,11 +5559,29 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
if (code == VIEW_CONVERT_EXPR)
{
ptr = TREE_OPERAND (ptr, 0);
- return compute_objsize (ptr, ostype, pref, visited, rvals);
+ return compute_objsize_r (ptr, ostype, pref, snlim, qry);
}
- if (TREE_CODE (ptr) == SSA_NAME)
+ if (code == SSA_NAME)
{
+ if (!snlim.next ())
+ return false;
+
+ /* Only process an SSA_NAME if the recursion limit has not yet
+ been reached. */
+ if (qry)
+ {
+ if (++qry->depth)
+ qry->max_depth = qry->depth;
+ if (const access_ref *cache_ref = qry->get_ref (ptr))
+ {
+ /* If the pointer is in the cache set *PREF to what it refers
+ to and return success. */
+ *pref = *cache_ref;
+ return true;
+ }
+ }
+
gimple *stmt = SSA_NAME_DEF_STMT (ptr);
if (is_gimple_call (stmt))
{
@@ -4925,7 +5610,7 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
offset_int offrng[2];
if (tree ret = gimple_call_return_array (stmt, offrng, rvals))
{
- if (!compute_objsize (ret, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (ret, ostype, pref, snlim, qry))
return false;
/* Cap OFFRNG[1] to at most the remaining size of
@@ -4947,6 +5632,7 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
pref->ref = ptr;
}
}
+ qry->put_ref (ptr, *pref);
return true;
}
@@ -4956,25 +5642,35 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
of the array from the current function declaratation
(e.g., attribute access or related). */
wide_int wr[2];
- if (tree ref = gimple_parm_array_size (ptr, wr, rvals))
+ bool static_array = false;
+ if (tree ref = gimple_parm_array_size (ptr, wr, &static_array))
{
+ pref->parmarray = !static_array;
pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED);
pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED);
pref->ref = ref;
+ qry->put_ref (ptr, *pref);
return true;
}
pref->set_max_size_range ();
pref->base0 = false;
pref->ref = ptr;
- if (tree var = SSA_NAME_VAR (ptr))
- if (TREE_CODE (var) == PARM_DECL)
- pref->ref = var;
-
+ qry->put_ref (ptr, *pref);
return true;
}
- /* TODO: Handle PHI. */
+ if (gimple_code (stmt) == GIMPLE_PHI)
+ {
+ pref->ref = ptr;
+ access_ref phi_ref = *pref;
+ if (!pref->get_ref (NULL, &phi_ref, ostype, &snlim, qry))
+ return false;
+ *pref = phi_ref;
+ pref->ref = ptr;
+ qry->put_ref (ptr, *pref);
+ return true;
+ }
if (!is_gimple_assign (stmt))
{
@@ -4984,21 +5680,27 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
PREF->REF to it. */
pref->base0 = false;
pref->set_max_size_range ();
- if (tree var = SSA_NAME_VAR (ptr))
- if (TREE_CODE (var) == PARM_DECL)
- pref->ref = var;
+ pref->ref = ptr;
return true;
}
- ptr = gimple_assign_rhs1 (stmt);
-
tree_code code = gimple_assign_rhs_code (stmt);
+ if (code == MAX_EXPR || code == MIN_EXPR)
+ {
+ if (!handle_min_max_size (stmt, ostype, pref, snlim, qry))
+ return false;
+ qry->put_ref (ptr, *pref);
+ return true;
+ }
+
+ tree rhs = gimple_assign_rhs1 (stmt);
+
if (code == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_TYPE (ptr)) == POINTER_TYPE)
+ && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE)
{
/* Compute the size of the object first. */
- if (!compute_objsize (ptr, ostype, pref, visited, rvals))
+ if (!compute_objsize_r (rhs, ostype, pref, snlim, qry))
return false;
offset_int orng[2];
@@ -5007,22 +5709,30 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, bitmap *visited,
pref->add_offset (orng[0], orng[1]);
else
pref->add_max_offset ();
+ qry->put_ref (ptr, *pref);
return true;
}
- if (code == ADDR_EXPR)
- return compute_objsize (ptr, ostype, pref, visited, rvals);
+ if (code == ADDR_EXPR
+ || code == SSA_NAME)
+ return compute_objsize_r (rhs, ostype, pref, snlim, qry);
- /* This could be an assignment from a nonlocal pointer. Save PTR
- to mention in diagnostics but otherwise treat it as a pointer
+ /* (This could also be an assignment from a nonlocal pointer.) Save
+ PTR to mention in diagnostics but otherwise treat it as a pointer
to an unknown object. */
- pref->ref = ptr;
+ pref->ref = rhs;
+ pref->base0 = false;
+ pref->set_max_size_range ();
+ return true;
}
/* Assume all other expressions point into an unknown object
of the maximum valid size. */
+ pref->ref = ptr;
pref->base0 = false;
pref->set_max_size_range ();
+ if (TREE_CODE (ptr) == SSA_NAME)
+ qry->put_ref (ptr, *pref);
return true;
}
@@ -5033,15 +5743,32 @@ tree
compute_objsize (tree ptr, int ostype, access_ref *pref,
range_query *rvals /* = NULL */)
{
- bitmap visited = NULL;
+ pointer_query qry;
+ qry.rvals = rvals;
+ ssa_name_limit_t snlim;
+ if (!compute_objsize_r (ptr, ostype, pref, snlim, &qry))
+ return NULL_TREE;
- bool success
- = compute_objsize (ptr, ostype, pref, &visited, rvals);
+ offset_int maxsize = pref->size_remaining ();
+ if (pref->base0 && pref->offrng[0] < 0 && pref->offrng[1] >= 0)
+ pref->offrng[0] = 0;
+ return wide_int_to_tree (sizetype, maxsize);
+}
- if (visited)
- BITMAP_FREE (visited);
+/* Transitional wrapper. The function should be removed once callers
+ transition to the pointer_query API. */
- if (!success)
+tree
+compute_objsize (tree ptr, int ostype, access_ref *pref, pointer_query *ptr_qry)
+{
+ pointer_query qry;
+ if (ptr_qry)
+ ptr_qry->depth = 0;
+ else
+ ptr_qry = &qry;
+
+ ssa_name_limit_t snlim;
+ if (!compute_objsize_r (ptr, ostype, pref, snlim, ptr_qry))
return NULL_TREE;
offset_int maxsize = pref->size_remaining ();
@@ -5050,7 +5777,7 @@ compute_objsize (tree ptr, int ostype, access_ref *pref,
return wide_int_to_tree (sizetype, maxsize);
}
-/* Transitional wrapper around the above. The function should be removed
+/* Legacy wrapper around the above. The function should be removed
once callers transition to one of the two above. */
tree
@@ -5648,9 +6375,7 @@ check_strncat_sizes (tree exp, tree objsize)
if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
&& tree_int_cst_equal (objsize, maxread))
{
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
warning_at (loc, OPT_Wstringop_overflow_,
"%K%qD specified bound %E equals destination size",
exp, get_callee_fndecl (exp), maxread);
@@ -5723,9 +6448,7 @@ expand_builtin_strncat (tree exp, rtx)
if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
&& tree_int_cst_equal (destsize, maxread))
{
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
warning_at (loc, OPT_Wstringop_overflow_,
"%K%qD specified bound %E equals destination size",
exp, get_callee_fndecl (exp), maxread);
@@ -6307,9 +7030,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
|| !check_nul_terminated_array (exp, arg2, arg3))
return NULL_RTX;
- location_t loc = tree_nonartificial_location (exp);
- loc = expansion_point_location_if_in_system_header (loc);
-
+ location_t loc = tree_inlined_location (exp);
tree len1 = c_strlen (arg1, 1);
tree len2 = c_strlen (arg2, 1);
@@ -7046,26 +7767,64 @@ expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
return expand_copysign (op0, op1, target);
}
-/* Expand a call to __builtin___clear_cache. */
+/* Emit a call to __builtin___clear_cache. */
-static rtx
-expand_builtin___clear_cache (tree exp)
+void
+default_emit_call_builtin___clear_cache (rtx begin, rtx end)
{
- if (!targetm.code_for_clear_cache)
+ rtx callee = gen_rtx_SYMBOL_REF (Pmode,
+ BUILTIN_ASM_NAME_PTR
+ (BUILT_IN_CLEAR_CACHE));
+
+ emit_library_call (callee,
+ LCT_NORMAL, VOIDmode,
+ convert_memory_address (ptr_mode, begin), ptr_mode,
+ convert_memory_address (ptr_mode, end), ptr_mode);
+}
+
+/* Emit a call to __builtin___clear_cache, unless the target specifies
+ it as do-nothing. This function can be used by trampoline
+ finalizers to duplicate the effects of expanding a call to the
+ clear_cache builtin. */
+
+void
+maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
+{
+ if ((GET_MODE (begin) != ptr_mode && GET_MODE (begin) != Pmode)
+ || (GET_MODE (end) != ptr_mode && GET_MODE (end) != Pmode))
{
-#ifdef CLEAR_INSN_CACHE
- /* There is no "clear_cache" insn, and __clear_cache() in libgcc
- does something. Just do the default expansion to a call to
- __clear_cache(). */
- return NULL_RTX;
-#else
+ error ("both arguments to %<__builtin___clear_cache%> must be pointers");
+ return;
+ }
+
+ if (targetm.have_clear_cache ())
+ {
+ /* We have a "clear_cache" insn, and it will handle everything. */
+ class expand_operand ops[2];
+
+ create_address_operand (&ops[0], begin);
+ create_address_operand (&ops[1], end);
+
+ if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
+ return;
+ }
+ else
+ {
+#ifndef CLEAR_INSN_CACHE
/* There is no "clear_cache" insn, and __clear_cache() in libgcc
does nothing. There is no need to call it. Do nothing. */
- return const0_rtx;
+ return;
#endif /* CLEAR_INSN_CACHE */
}
- /* We have a "clear_cache" insn, and it will handle everything. */
+ targetm.calls.emit_call_builtin___clear_cache (begin, end);
+}
+
+/* Expand a call to __builtin___clear_cache. */
+
+static void
+expand_builtin___clear_cache (tree exp)
+{
tree begin, end;
rtx begin_rtx, end_rtx;
@@ -7075,25 +7834,16 @@ expand_builtin___clear_cache (tree exp)
if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
error ("both arguments to %<__builtin___clear_cache%> must be pointers");
- return const0_rtx;
+ return;
}
- if (targetm.have_clear_cache ())
- {
- class expand_operand ops[2];
+ begin = CALL_EXPR_ARG (exp, 0);
+ begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
- begin = CALL_EXPR_ARG (exp, 0);
- begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
+ end = CALL_EXPR_ARG (exp, 1);
+ end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
- end = CALL_EXPR_ARG (exp, 1);
- end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
-
- create_address_operand (&ops[0], begin_rtx);
- create_address_operand (&ops[1], end_rtx);
- if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
- return const0_rtx;
- }
- return const0_rtx;
+ maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
}
/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
@@ -8783,6 +9533,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
&& fcode != BUILT_IN_EXECLE
&& fcode != BUILT_IN_EXECVP
&& fcode != BUILT_IN_EXECVE
+ && fcode != BUILT_IN_CLEAR_CACHE
&& !ALLOCA_FUNCTION_CODE_P (fcode)
&& fcode != BUILT_IN_FREE)
return expand_call (exp, target, ignore);
@@ -8972,10 +9723,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return expand_builtin_next_arg ();
case BUILT_IN_CLEAR_CACHE:
- target = expand_builtin___clear_cache (exp);
- if (target)
- return target;
- break;
+ expand_builtin___clear_cache (exp);
+ return const0_rtx;
case BUILT_IN_CLASSIFY_TYPE:
return expand_builtin_classify_type (exp);
@@ -9878,11 +10627,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
maybe_emit_sprintf_chk_warning (exp, fcode);
break;
- case BUILT_IN_FREE:
- if (warn_free_nonheap_object)
- maybe_emit_free_warning (exp);
- break;
-
case BUILT_IN_THREAD_POINTER:
return expand_builtin_thread_pointer (exp, target);
@@ -10684,9 +11428,10 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
switch (builtin_index)
{
case BUILT_IN_ISINF:
- if (!HONOR_INFINITIES (arg))
+ if (tree_expr_infinite_p (arg))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg);
+ if (!tree_expr_maybe_infinite_p (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
-
return NULL_TREE;
case BUILT_IN_ISINF_SIGN:
@@ -10722,14 +11467,16 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
}
case BUILT_IN_ISFINITE:
- if (!HONOR_NANS (arg)
- && !HONOR_INFINITIES (arg))
+ if (tree_expr_finite_p (arg))
return omit_one_operand_loc (loc, type, integer_one_node, arg);
-
+ if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg);
return NULL_TREE;
case BUILT_IN_ISNAN:
- if (!HONOR_NANS (arg))
+ if (tree_expr_nan_p (arg))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg);
+ if (!tree_expr_maybe_nan_p (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
{
@@ -10803,7 +11550,7 @@ fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
arg, build_real (type, r));
res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
- if (HONOR_INFINITIES (mode))
+ if (tree_expr_maybe_infinite_p (arg))
{
real_inf (&r);
tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
@@ -10812,7 +11559,7 @@ fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
fp_infinite, res);
}
- if (HONOR_NANS (mode))
+ if (tree_expr_maybe_nan_p (arg))
{
tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
@@ -10860,12 +11607,15 @@ fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
if (unordered_code == UNORDERED_EXPR)
{
- if (!HONOR_NANS (arg0))
+ if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
+ return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
+ if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
}
- code = HONOR_NANS (arg0) ? unordered_code : ordered_code;
+ code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
+ ? unordered_code : ordered_code;
return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
fold_build2_loc (loc, code, type, arg0, arg1));
}
@@ -12186,30 +12936,662 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
access_write_only);
}
-/* Emit warning if a free is called with address of a variable. */
+/* Return true if STMT is a call to an allocation function. Unless
+ ALL_ALLOC is set, consider only functions that return dynmamically
+ allocated objects. Otherwise return true even for all forms of
+ alloca (including VLA). */
-static void
+static bool
+fndecl_alloc_p (tree fndecl, bool all_alloc)
+{
+ if (!fndecl)
+ return false;
+
+ /* A call to operator new isn't recognized as one to a built-in. */
+ if (DECL_IS_OPERATOR_NEW_P (fndecl))
+ return true;
+
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ return all_alloc;
+ case BUILT_IN_ALIGNED_ALLOC:
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_GOMP_ALLOC:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STRDUP:
+ case BUILT_IN_STRNDUP:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ /* A function is considered an allocation function if it's declared
+ with attribute malloc with an argument naming its associated
+ deallocation function. */
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return false;
+
+ for (tree allocs = attrs;
+ (allocs = lookup_attribute ("malloc", allocs));
+ allocs = TREE_CHAIN (allocs))
+ {
+ tree args = TREE_VALUE (allocs);
+ if (!args)
+ continue;
+
+ if (TREE_VALUE (args))
+ return true;
+ }
+
+ return false;
+}
+
+/* Return true if STMT is a call to an allocation function. A wrapper
+ around fndecl_alloc_p. */
+
+static bool
+gimple_call_alloc_p (gimple *stmt, bool all_alloc = false)
+{
+ return fndecl_alloc_p (gimple_call_fndecl (stmt), all_alloc);
+}
+
+/* Return the zero-based number corresponding to the argument being
+ deallocated if STMT is a call to a deallocation function or UINT_MAX
+ if it isn't. */
+
+static unsigned
+call_dealloc_argno (tree exp)
+{
+ tree fndecl = get_callee_fndecl (exp);
+ if (!fndecl)
+ return UINT_MAX;
+
+ /* A call to operator delete isn't recognized as one to a built-in. */
+ if (DECL_IS_OPERATOR_DELETE_P (fndecl))
+ return 0;
+
+ /* TODO: Handle user-defined functions with attribute malloc? Handle
+ known non-built-ins like fopen? */
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_FREE:
+ case BUILT_IN_REALLOC:
+ return 0;
+ default:
+ break;
+ }
+ return UINT_MAX;
+ }
+
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return UINT_MAX;
+
+ for (tree atfree = attrs;
+ (atfree = lookup_attribute ("*dealloc", atfree));
+ atfree = TREE_CHAIN (atfree))
+ {
+ tree alloc = TREE_VALUE (atfree);
+ if (!alloc)
+ continue;
+
+ tree pos = TREE_CHAIN (alloc);
+ if (!pos)
+ return 0;
+
+ pos = TREE_VALUE (pos);
+ return TREE_INT_CST_LOW (pos) - 1;
+ }
+
+ return UINT_MAX;
+}
+
+/* Return true if DELETE_DECL is an operator delete that's not suitable
+ to call with a pointer returned fron NEW_DECL. */
+
+static bool
+new_delete_mismatch_p (tree new_decl, tree delete_decl)
+{
+ tree new_name = DECL_ASSEMBLER_NAME (new_decl);
+ tree delete_name = DECL_ASSEMBLER_NAME (delete_decl);
+
+ /* valid_new_delete_pair_p() returns a conservative result. A true
+ result is reliable but a false result doesn't necessarily mean
+ the operators don't match. */
+ if (valid_new_delete_pair_p (new_name, delete_name))
+ return false;
+
+ const char *new_str = IDENTIFIER_POINTER (new_name);
+ const char *del_str = IDENTIFIER_POINTER (delete_name);
+
+ if (*new_str != '_')
+ return *new_str != *del_str;
+
+ ++del_str;
+ if (*++new_str != 'Z')
+ return *new_str != *del_str;
+
+ ++del_str;
+ if (*++new_str == 'n')
+ return *del_str != 'd';
+
+ if (*new_str != 'N')
+ return *del_str != 'N';
+
+ /* Handle user-defined member operators below. */
+ ++new_str;
+ ++del_str;
+
+ do
+ {
+ /* Determine if both operators are members of the same type.
+ If not, they don't match. */
+ char *new_end, *del_end;
+ unsigned long nlen = strtoul (new_str, &new_end, 10);
+ unsigned long dlen = strtoul (del_str, &del_end, 10);
+ if (nlen != dlen)
+ return true;
+
+ /* Skip past the name length. */
+ new_str = new_end;
+ del_str = del_end;
+
+ /* Skip past the names making sure each has the expected length
+ (it would suggest some sort of a corruption if they didn't). */
+ while (nlen--)
+ if (!*++new_end)
+ return true;
+
+ for (nlen = dlen; nlen--; )
+ if (!*++del_end)
+ return true;
+
+ /* The names have the expected length. Compare them. */
+ if (memcmp (new_str, del_str, dlen))
+ return true;
+
+ new_str = new_end;
+ del_str = del_end;
+
+ if (*new_str == 'I')
+ {
+ /* Template instantiation. */
+ do
+ {
+ ++new_str;
+ ++del_str;
+
+ if (*new_str == 'n')
+ break;
+ if (*new_str != *del_str)
+ return true;
+ }
+ while (*new_str);
+ }
+
+ if (*new_str == 'n')
+ {
+ if (*del_str != 'd')
+ return true;
+
+ ++del_str;
+ if (*++new_str == 'w' && *del_str != 'l')
+ return true;
+ if (*new_str == 'a' && *del_str != 'a')
+ return true;
+ ++new_str;
+ ++del_str;
+ break;
+ }
+ } while (true);
+
+ if (*new_str != 'E')
+ return *del_str != *new_str;
+
+ ++new_str;
+ ++del_str;
+ if (*new_str != 'j' && *new_str != 'm' && *new_str != 'y')
+ return true;
+ if (*del_str != 'P' || *++del_str != 'v')
+ return true;
+
+ /* Ignore any remaining arguments. Since both operators are members
+ of the same class, mismatches in those should be detectable and
+ diagnosed by the front end. */
+ return false;
+}
+
+/* ALLOC_DECL and DEALLOC_DECL are pair of allocation and deallocation
+ functions. Return true if the latter is suitable to deallocate objects
+ allocated by calls to the former. */
+
+static bool
+matching_alloc_calls_p (tree alloc_decl, tree dealloc_decl)
+{
+ /* Set to alloc_kind_t::builtin if ALLOC_DECL is associated with
+ a built-in deallocator. */
+ enum class alloc_kind_t { none, builtin, user }
+ alloc_dealloc_kind = alloc_kind_t::none;
+
+ if (DECL_IS_OPERATOR_NEW_P (alloc_decl))
+ {
+ if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
+ /* Return true iff both functions are of the same array or
+ singleton form and false otherwise. */
+ return !new_delete_mismatch_p (alloc_decl, dealloc_decl);
+
+ /* Return false for deallocation functions that are known not
+ to match. */
+ if (fndecl_built_in_p (dealloc_decl, BUILT_IN_FREE)
+ || fndecl_built_in_p (dealloc_decl, BUILT_IN_REALLOC))
+ return false;
+ /* Otherwise proceed below to check the deallocation function's
+ "*dealloc" attributes to look for one that mentions this operator
+ new. */
+ }
+ else if (fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (alloc_decl))
+ {
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ return false;
+
+ case BUILT_IN_ALIGNED_ALLOC:
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_GOMP_ALLOC:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STRDUP:
+ case BUILT_IN_STRNDUP:
+ if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
+ return false;
+
+ if (fndecl_built_in_p (dealloc_decl, BUILT_IN_FREE)
+ || fndecl_built_in_p (dealloc_decl, BUILT_IN_REALLOC))
+ return true;
+
+ alloc_dealloc_kind = alloc_kind_t::builtin;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Set if DEALLOC_DECL both allocates and deallocates. */
+ alloc_kind_t realloc_kind = alloc_kind_t::none;
+
+ if (fndecl_built_in_p (dealloc_decl, BUILT_IN_NORMAL))
+ {
+ built_in_function dealloc_code = DECL_FUNCTION_CODE (dealloc_decl);
+ if (dealloc_code == BUILT_IN_REALLOC)
+ realloc_kind = alloc_kind_t::builtin;
+
+ for (tree amats = DECL_ATTRIBUTES (alloc_decl);
+ (amats = lookup_attribute ("malloc", amats));
+ amats = TREE_CHAIN (amats))
+ {
+ tree args = TREE_VALUE (amats);
+ if (!args)
+ continue;
+
+ tree fndecl = TREE_VALUE (args);
+ if (!fndecl || !DECL_P (fndecl))
+ continue;
+
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
+ && dealloc_code == DECL_FUNCTION_CODE (fndecl))
+ return true;
+ }
+ }
+
+ const bool alloc_builtin = fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL);
+ alloc_kind_t realloc_dealloc_kind = alloc_kind_t::none;
+
+ /* If DEALLOC_DECL has an internal "*dealloc" attribute scan the list
+ of its associated allocation functions for ALLOC_DECL.
+ If the corresponding ALLOC_DECL is found they're a matching pair,
+ otherwise they're not.
+ With DDATS set to the Deallocator's *Dealloc ATtributes... */
+ for (tree ddats = DECL_ATTRIBUTES (dealloc_decl);
+ (ddats = lookup_attribute ("*dealloc", ddats));
+ ddats = TREE_CHAIN (ddats))
+ {
+ tree args = TREE_VALUE (ddats);
+ if (!args)
+ continue;
+
+ tree alloc = TREE_VALUE (args);
+ if (!alloc)
+ continue;
+
+ if (alloc == DECL_NAME (dealloc_decl))
+ realloc_kind = alloc_kind_t::user;
+
+ if (DECL_P (alloc))
+ {
+ gcc_checking_assert (fndecl_built_in_p (alloc, BUILT_IN_NORMAL));
+
+ switch (DECL_FUNCTION_CODE (alloc))
+ {
+ case BUILT_IN_ALIGNED_ALLOC:
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_GOMP_ALLOC:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STRDUP:
+ case BUILT_IN_STRNDUP:
+ realloc_dealloc_kind = alloc_kind_t::builtin;
+ break;
+ default:
+ break;
+ }
+
+ if (!alloc_builtin)
+ continue;
+
+ if (DECL_FUNCTION_CODE (alloc) != DECL_FUNCTION_CODE (alloc_decl))
+ continue;
+
+ return true;
+ }
+
+ if (alloc == DECL_NAME (alloc_decl))
+ return true;
+ }
+
+ if (realloc_kind == alloc_kind_t::none)
+ return false;
+
+ hash_set<tree> common_deallocs;
+ /* Special handling for deallocators. Iterate over both the allocator's
+ and the reallocator's associated deallocator functions looking for
+ the first one in common. If one is found, the de/reallocator is
+ a match for the allocator even though the latter isn't directly
+ associated with the former. This simplifies declarations in system
+ headers.
+ With AMATS set to the Allocator's Malloc ATtributes,
+ and RMATS set to Reallocator's Malloc ATtributes... */
+ for (tree amats = DECL_ATTRIBUTES (alloc_decl),
+ rmats = DECL_ATTRIBUTES (dealloc_decl);
+ (amats = lookup_attribute ("malloc", amats))
+ || (rmats = lookup_attribute ("malloc", rmats));
+ amats = amats ? TREE_CHAIN (amats) : NULL_TREE,
+ rmats = rmats ? TREE_CHAIN (rmats) : NULL_TREE)
+ {
+ if (tree args = amats ? TREE_VALUE (amats) : NULL_TREE)
+ if (tree adealloc = TREE_VALUE (args))
+ {
+ if (DECL_P (adealloc)
+ && fndecl_built_in_p (adealloc, BUILT_IN_NORMAL))
+ {
+ built_in_function fncode = DECL_FUNCTION_CODE (adealloc);
+ if (fncode == BUILT_IN_FREE || fncode == BUILT_IN_REALLOC)
+ {
+ if (realloc_kind == alloc_kind_t::builtin)
+ return true;
+ alloc_dealloc_kind = alloc_kind_t::builtin;
+ }
+ continue;
+ }
+
+ common_deallocs.add (adealloc);
+ }
+
+ if (tree args = rmats ? TREE_VALUE (rmats) : NULL_TREE)
+ if (tree ddealloc = TREE_VALUE (args))
+ {
+ if (DECL_P (ddealloc)
+ && fndecl_built_in_p (ddealloc, BUILT_IN_NORMAL))
+ {
+ built_in_function fncode = DECL_FUNCTION_CODE (ddealloc);
+ if (fncode == BUILT_IN_FREE || fncode == BUILT_IN_REALLOC)
+ {
+ if (alloc_dealloc_kind == alloc_kind_t::builtin)
+ return true;
+ realloc_dealloc_kind = alloc_kind_t::builtin;
+ }
+ continue;
+ }
+
+ if (common_deallocs.add (ddealloc))
+ return true;
+ }
+ }
+
+ /* Succeed only if ALLOC_DECL and the reallocator DEALLOC_DECL share
+ a built-in deallocator. */
+ return (alloc_dealloc_kind == alloc_kind_t::builtin
+ && realloc_dealloc_kind == alloc_kind_t::builtin);
+}
+
+/* Return true if DEALLOC_DECL is a function suitable to deallocate
+ objectes allocated by the ALLOC call. */
+
+static bool
+matching_alloc_calls_p (gimple *alloc, tree dealloc_decl)
+{
+ tree alloc_decl = gimple_call_fndecl (alloc);
+ if (!alloc_decl)
+ return true;
+
+ return matching_alloc_calls_p (alloc_decl, dealloc_decl);
+}
+
+/* Diagnose a call EXP to deallocate a pointer referenced by AREF if it
+ includes a nonzero offset. Such a pointer cannot refer to the beginning
+ of an allocated object. A negative offset may refer to it only if
+ the target pointer is unknown. */
+
+static bool
+warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
+{
+ if (aref.deref || aref.offrng[0] <= 0 || aref.offrng[1] <= 0)
+ return false;
+
+ tree dealloc_decl = get_callee_fndecl (exp);
+ if (!dealloc_decl)
+ return false;
+
+ if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
+ && !DECL_IS_REPLACEABLE_OPERATOR (dealloc_decl))
+ {
+ /* A call to a user-defined operator delete with a pointer plus offset
+ may be valid if it's returned from an unknown function (i.e., one
+ that's not operator new). */
+ if (TREE_CODE (aref.ref) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (aref.ref);
+ if (is_gimple_call (def_stmt))
+ {
+ tree alloc_decl = gimple_call_fndecl (def_stmt);
+ if (!alloc_decl || !DECL_IS_OPERATOR_NEW_P (alloc_decl))
+ return false;
+ }
+ }
+ }
+
+ char offstr[80];
+ offstr[0] = '\0';
+ if (wi::fits_shwi_p (aref.offrng[0]))
+ {
+ if (aref.offrng[0] == aref.offrng[1]
+ || !wi::fits_shwi_p (aref.offrng[1]))
+ sprintf (offstr, " %lli",
+ (long long)aref.offrng[0].to_shwi ());
+ else
+ sprintf (offstr, " [%lli, %lli]",
+ (long long)aref.offrng[0].to_shwi (),
+ (long long)aref.offrng[1].to_shwi ());
+ }
+
+ if (!warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on pointer %qE with nonzero offset%s",
+ exp, dealloc_decl, aref.ref, offstr))
+ return false;
+
+ if (DECL_P (aref.ref))
+ inform (DECL_SOURCE_LOCATION (aref.ref), "declared here");
+ else if (TREE_CODE (aref.ref) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (aref.ref);
+ if (is_gimple_call (def_stmt))
+ {
+ location_t def_loc = gimple_location (def_stmt);
+ tree alloc_decl = gimple_call_fndecl (def_stmt);
+ if (alloc_decl)
+ inform (def_loc,
+ "returned from %qD", alloc_decl);
+ else if (tree alloc_fntype = gimple_call_fntype (def_stmt))
+ inform (def_loc,
+ "returned from %qT", alloc_fntype);
+ else
+ inform (def_loc, "obtained here");
+ }
+ }
+
+ return true;
+}
+
+/* Issue a warning if a deallocation function such as free, realloc,
+ or C++ operator delete is called with an argument not returned by
+ a matching allocation function such as malloc or the corresponding
+ form of C++ operatorn new. */
+
+void
maybe_emit_free_warning (tree exp)
{
- if (call_expr_nargs (exp) != 1)
+ tree fndecl = get_callee_fndecl (exp);
+ if (!fndecl)
return;
- tree arg = CALL_EXPR_ARG (exp, 0);
+ unsigned argno = call_dealloc_argno (exp);
+ if ((unsigned) call_expr_nargs (exp) <= argno)
+ return;
- STRIP_NOPS (arg);
- if (TREE_CODE (arg) != ADDR_EXPR)
+ tree ptr = CALL_EXPR_ARG (exp, argno);
+ if (integer_zerop (ptr))
return;
- arg = get_base_address (TREE_OPERAND (arg, 0));
- if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
+ access_ref aref;
+ if (!compute_objsize (ptr, 0, &aref))
return;
- if (SSA_VAR_P (arg))
- warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
- "%Kattempt to free a non-heap object %qD", exp, arg);
- else
- warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
- "%Kattempt to free a non-heap object", exp);
+ tree ref = aref.ref;
+ if (integer_zerop (ref))
+ return;
+
+ tree dealloc_decl = get_callee_fndecl (exp);
+ location_t loc = tree_inlined_location (exp);
+
+ if (DECL_P (ref) || EXPR_P (ref))
+ {
+ /* Diagnose freeing a declared object. */
+ if (aref.ref_declared ()
+ && warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on unallocated object %qD",
+ exp, dealloc_decl, ref))
+ {
+ loc = (DECL_P (ref)
+ ? DECL_SOURCE_LOCATION (ref)
+ : EXPR_LOCATION (ref));
+ inform (loc, "declared here");
+ return;
+ }
+
+ /* Diagnose freeing a pointer that includes a positive offset.
+ Such a pointer cannot refer to the beginning of an allocated
+ object. A negative offset may refer to it. */
+ if (aref.sizrng[0] != aref.sizrng[1]
+ && warn_dealloc_offset (loc, exp, aref))
+ return;
+ }
+ else if (CONSTANT_CLASS_P (ref))
+ {
+ if (warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on a pointer to an unallocated "
+ "object %qE", exp, dealloc_decl, ref))
+ {
+ if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (ptr);
+ if (is_gimple_assign (def_stmt))
+ {
+ location_t loc = gimple_location (def_stmt);
+ inform (loc, "assigned here");
+ }
+ }
+ return;
+ }
+ }
+ else if (TREE_CODE (ref) == SSA_NAME)
+ {
+ /* Also warn if the pointer argument refers to the result
+ of an allocation call like alloca or VLA. */
+ gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
+ if (is_gimple_call (def_stmt))
+ {
+ bool warned = false;
+ if (gimple_call_alloc_p (def_stmt))
+ {
+ if (matching_alloc_calls_p (def_stmt, dealloc_decl))
+ {
+ if (warn_dealloc_offset (loc, exp, aref))
+ return;
+ }
+ else
+ {
+ tree alloc_decl = gimple_call_fndecl (def_stmt);
+ int opt = (DECL_IS_OPERATOR_NEW_P (alloc_decl)
+ || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
+ ? OPT_Wmismatched_new_delete
+ : OPT_Wmismatched_dealloc);
+ warned = warning_at (loc, opt,
+ "%K%qD called on pointer returned "
+ "from a mismatched allocation "
+ "function", exp, dealloc_decl);
+ }
+ }
+ else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
+ || gimple_call_builtin_p (def_stmt,
+ BUILT_IN_ALLOCA_WITH_ALIGN))
+ warned = warning_at (loc, OPT_Wfree_nonheap_object,
+ "%K%qD called on pointer to "
+ "an unallocated object",
+ exp, dealloc_decl);
+ else if (warn_dealloc_offset (loc, exp, aref))
+ return;
+
+ if (warned)
+ {
+ tree fndecl = gimple_call_fndecl (def_stmt);
+ inform (gimple_location (def_stmt),
+ "returned from %qD", fndecl);
+ return;
+ }
+ }
+ else if (gimple_nop_p (def_stmt))
+ {
+ ref = SSA_NAME_VAR (ref);
+ /* Diagnose freeing a pointer that includes a positive offset. */
+ if (TREE_CODE (ref) == PARM_DECL
+ && !aref.deref
+ && aref.sizrng[0] != aref.sizrng[1]
+ && aref.offrng[0] > 0 && aref.offrng[1] > 0
+ && warn_dealloc_offset (loc, exp, aref))
+ return;
+ }
+ }
}
/* Fold a call to __builtin_object_size with arguments PTR and OST,
@@ -12913,3 +14295,185 @@ access_ref::offset_bounded () const
tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
}
+
+/* If CALLEE has known side effects, fill in INFO and return true.
+ See tree-ssa-structalias.c:find_func_aliases
+ for the list of builtins we might need to handle here. */
+
+attr_fnspec
+builtin_fnspec (tree callee)
+{
+ built_in_function code = DECL_FUNCTION_CODE (callee);
+
+ switch (code)
+ {
+ /* All the following functions read memory pointed to by
+ their second argument and write memory pointed to by first
+ argument.
+ strcat/strncat additionally reads memory pointed to by the first
+ argument. */
+ case BUILT_IN_STRCAT:
+ case BUILT_IN_STRCAT_CHK:
+ return "1cW 1 ";
+ case BUILT_IN_STRNCAT:
+ case BUILT_IN_STRNCAT_CHK:
+ return "1cW 13";
+ case BUILT_IN_STRCPY:
+ case BUILT_IN_STRCPY_CHK:
+ return "1cO 1 ";
+ case BUILT_IN_STPCPY:
+ case BUILT_IN_STPCPY_CHK:
+ return ".cO 1 ";
+ case BUILT_IN_STRNCPY:
+ case BUILT_IN_MEMCPY:
+ case BUILT_IN_MEMMOVE:
+ case BUILT_IN_TM_MEMCPY:
+ case BUILT_IN_TM_MEMMOVE:
+ case BUILT_IN_STRNCPY_CHK:
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMMOVE_CHK:
+ return "1cO313";
+ case BUILT_IN_MEMPCPY:
+ case BUILT_IN_MEMPCPY_CHK:
+ return ".cO313";
+ case BUILT_IN_STPNCPY:
+ case BUILT_IN_STPNCPY_CHK:
+ return ".cO313";
+ case BUILT_IN_BCOPY:
+ return ".c23O3";
+ case BUILT_IN_BZERO:
+ return ".cO2";
+ case BUILT_IN_MEMCMP:
+ case BUILT_IN_MEMCMP_EQ:
+ case BUILT_IN_BCMP:
+ case BUILT_IN_STRNCMP:
+ case BUILT_IN_STRNCMP_EQ:
+ case BUILT_IN_STRNCASECMP:
+ return ".cR3R3";
+
+ /* The following functions read memory pointed to by their
+ first argument. */
+ CASE_BUILT_IN_TM_LOAD (1):
+ CASE_BUILT_IN_TM_LOAD (2):
+ CASE_BUILT_IN_TM_LOAD (4):
+ CASE_BUILT_IN_TM_LOAD (8):
+ CASE_BUILT_IN_TM_LOAD (FLOAT):
+ CASE_BUILT_IN_TM_LOAD (DOUBLE):
+ CASE_BUILT_IN_TM_LOAD (LDOUBLE):
+ CASE_BUILT_IN_TM_LOAD (M64):
+ CASE_BUILT_IN_TM_LOAD (M128):
+ CASE_BUILT_IN_TM_LOAD (M256):
+ case BUILT_IN_TM_LOG:
+ case BUILT_IN_TM_LOG_1:
+ case BUILT_IN_TM_LOG_2:
+ case BUILT_IN_TM_LOG_4:
+ case BUILT_IN_TM_LOG_8:
+ case BUILT_IN_TM_LOG_FLOAT:
+ case BUILT_IN_TM_LOG_DOUBLE:
+ case BUILT_IN_TM_LOG_LDOUBLE:
+ case BUILT_IN_TM_LOG_M64:
+ case BUILT_IN_TM_LOG_M128:
+ case BUILT_IN_TM_LOG_M256:
+ return ".cR ";
+
+ case BUILT_IN_INDEX:
+ case BUILT_IN_RINDEX:
+ case BUILT_IN_STRCHR:
+ case BUILT_IN_STRLEN:
+ case BUILT_IN_STRRCHR:
+ return ".cR ";
+ case BUILT_IN_STRNLEN:
+ return ".cR2";
+
+ /* These read memory pointed to by the first argument.
+ Allocating memory does not have any side-effects apart from
+ being the definition point for the pointer.
+ Unix98 specifies that errno is set on allocation failure. */
+ case BUILT_IN_STRDUP:
+ return "mCR ";
+ case BUILT_IN_STRNDUP:
+ return "mCR2";
+ /* Allocating memory does not have any side-effects apart from
+ being the definition point for the pointer. */
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_ALIGNED_ALLOC:
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_GOMP_ALLOC:
+ return "mC";
+ CASE_BUILT_IN_ALLOCA:
+ return "mc";
+ /* These read memory pointed to by the first argument with size
+ in the third argument. */
+ case BUILT_IN_MEMCHR:
+ return ".cR3";
+ /* These read memory pointed to by the first and second arguments. */
+ case BUILT_IN_STRSTR:
+ case BUILT_IN_STRPBRK:
+ case BUILT_IN_STRCASECMP:
+ case BUILT_IN_STRCSPN:
+ case BUILT_IN_STRSPN:
+ case BUILT_IN_STRCMP:
+ case BUILT_IN_STRCMP_EQ:
+ return ".cR R ";
+ /* Freeing memory kills the pointed-to memory. More importantly
+ the call has to serve as a barrier for moving loads and stores
+ across it. */
+ case BUILT_IN_STACK_RESTORE:
+ case BUILT_IN_FREE:
+ case BUILT_IN_GOMP_FREE:
+ return ".co ";
+ case BUILT_IN_VA_END:
+ return ".cO ";
+ /* Realloc serves both as allocation point and deallocation point. */
+ case BUILT_IN_REALLOC:
+ return ".Cw ";
+ case BUILT_IN_GAMMA_R:
+ case BUILT_IN_GAMMAF_R:
+ case BUILT_IN_GAMMAL_R:
+ case BUILT_IN_LGAMMA_R:
+ case BUILT_IN_LGAMMAF_R:
+ case BUILT_IN_LGAMMAL_R:
+ return ".C. Ot";
+ case BUILT_IN_FREXP:
+ case BUILT_IN_FREXPF:
+ case BUILT_IN_FREXPL:
+ case BUILT_IN_MODF:
+ case BUILT_IN_MODFF:
+ case BUILT_IN_MODFL:
+ return ".c. Ot";
+ case BUILT_IN_REMQUO:
+ case BUILT_IN_REMQUOF:
+ case BUILT_IN_REMQUOL:
+ return ".c. . Ot";
+ case BUILT_IN_SINCOS:
+ case BUILT_IN_SINCOSF:
+ case BUILT_IN_SINCOSL:
+ return ".c. OtOt";
+ case BUILT_IN_MEMSET:
+ case BUILT_IN_MEMSET_CHK:
+ case BUILT_IN_TM_MEMSET:
+ return "1cO3";
+ CASE_BUILT_IN_TM_STORE (1):
+ CASE_BUILT_IN_TM_STORE (2):
+ CASE_BUILT_IN_TM_STORE (4):
+ CASE_BUILT_IN_TM_STORE (8):
+ CASE_BUILT_IN_TM_STORE (FLOAT):
+ CASE_BUILT_IN_TM_STORE (DOUBLE):
+ CASE_BUILT_IN_TM_STORE (LDOUBLE):
+ CASE_BUILT_IN_TM_STORE (M64):
+ CASE_BUILT_IN_TM_STORE (M128):
+ CASE_BUILT_IN_TM_STORE (M256):
+ return ".cO ";
+ case BUILT_IN_STACK_SAVE:
+ return ".c";
+ case BUILT_IN_ASSUME_ALIGNED:
+ return "1cX ";
+ /* But posix_memalign stores a pointer into the memory pointed to
+ by its first argument. */
+ case BUILT_IN_POSIX_MEMALIGN:
+ return ".cOt";
+
+ default:
+ return "";
+ }
+}
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 95428c0..aec43ca 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -245,6 +245,7 @@ along with GCC; see the file COPYING3. If not see
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
true, true, true, ATTRS, true, \
(flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
+ | SANITIZE_HWADDRESS \
| SANITIZE_UNDEFINED \
| SANITIZE_UNDEFINED_NONDEFAULT) \
|| flag_sanitize_coverage))
@@ -254,7 +255,7 @@ along with GCC; see the file COPYING3. If not see
`errno'. If !flag_errno_math they are instead "const". */
#undef ATTR_MATHFN_ERRNO
#define ATTR_MATHFN_ERRNO (flag_errno_math ? \
- ATTR_NOTHROW_LEAF_LIST : ATTR_CONST_NOTHROW_LEAF_LIST)
+ ATTR_ERRNOCONST_NOTHROW_LEAF_LIST : ATTR_CONST_NOTHROW_LEAF_LIST)
/* Define an attribute list for math functions that are normally
"const" but if flag_rounding_math is set they are instead "pure".
@@ -271,7 +272,8 @@ along with GCC; see the file COPYING3. If not see
"const" depending on whether we care about FP rounding. */
#undef ATTR_MATHFN_FPROUNDING_ERRNO
#define ATTR_MATHFN_FPROUNDING_ERRNO (flag_errno_math ? \
- ATTR_NOTHROW_LEAF_LIST : ATTR_MATHFN_FPROUNDING)
+ (flag_rounding_math ? ATTR_ERRNOPURE_NOTHROW_LEAF_LIST \
+ : ATTR_ERRNOCONST_NOTHROW_LEAF_LIST) : ATTR_MATHFN_FPROUNDING)
/* Define an attribute list for math functions that need to mind FP
rounding, but because they store into memory they are never "const"
@@ -517,6 +519,9 @@ DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_
DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_NANS, "nans", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
#undef NAN_TYPE
+DEF_GCC_BUILTIN (BUILT_IN_NANSD32, "nansd32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANSD64, "nansd64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANSD128, "nansd128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_C99_BUILTIN (BUILT_IN_NEARBYINT, "nearbyint", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_NEARBYINTF, "nearbyintf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_NEARBYINTL, "nearbyintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -701,26 +706,26 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHR
DEF_EXT_LIB_BUILTIN (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_MEMCHR, "memchr", BT_FN_PTR_CONST_PTR_INT_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY, "mempcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_RINDEX, "rindex", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY, "stpcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_RETNONNULL_NOTHROW_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPNCPY, "stpncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCASECMP, "strcasecmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_STRCAT, "strcat", BT_FN_STRING_STRING_CONST_STRING, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCAT, "strcat", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_C2X_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
DEF_C2X_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRNCMP, "strncmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_LIB_BUILTIN (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNLEN, "strnlen", BT_FN_SIZE_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRPBRK, "strpbrk", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRRCHR, "strrchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
@@ -835,6 +840,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PT
/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */
DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLEAR_PADDING, "clear_padding", BT_FN_VOID_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLZIMAX, "clzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLZL, "clzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -970,16 +976,16 @@ DEF_BUILTIN_STUB (BUILT_IN_STRNCMP_EQ, "__builtin_strncmp_eq")
/* Object size checking builtins. */
DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY_CHK, "__stpcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPNCPY_CHK, "__stpncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_5_6)
DEF_EXT_LIB_BUILTIN (BUILT_IN_SPRINTF_CHK, "__sprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR, ATTR_NOTHROW_NONNULL_1_FORMAT_PRINTF_4_5)
DEF_EXT_LIB_BUILTIN (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_5_0)
diff --git a/gcc/builtins.h b/gcc/builtins.h
index c09f36d..6429232 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -128,6 +128,7 @@ extern tree fold_call_expr (location_t, tree, bool);
extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
extern bool validate_gimple_arglist (const gcall *, ...);
extern rtx default_expand_builtin (tree, rtx, rtx, machine_mode, int);
+extern void maybe_emit_call_builtin___clear_cache (rtx, rtx);
extern bool fold_builtin_next_arg (tree, bool);
extern tree do_mpc_arg2 (tree, tree, tree, int, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t));
extern tree fold_call_stmt (gcall *, bool);
@@ -153,6 +154,42 @@ extern void warn_string_no_nul (location_t, tree, const char *, tree,
extern tree unterminated_array (tree, tree * = NULL, bool * = NULL);
extern bool builtin_with_linkage_p (tree);
+/* Describes recursion limits used by functions that follow use-def
+ chains of SSA_NAMEs. */
+
+class ssa_name_limit_t
+{
+ bitmap visited; /* Bitmap of visited SSA_NAMEs. */
+ unsigned ssa_def_max; /* Longest chain of SSA_NAMEs to follow. */
+
+ /* Not copyable or assignable. */
+ DISABLE_COPY_AND_ASSIGN (ssa_name_limit_t);
+
+public:
+
+ ssa_name_limit_t ()
+ : visited (),
+ ssa_def_max (param_ssa_name_def_chain_limit) { }
+
+ /* Set a bit for the PHI in VISITED and return true if it wasn't
+ already set. */
+ bool visit_phi (tree);
+ /* Clear a bit for the PHI in VISITED. */
+ void leave_phi (tree);
+ /* Return false if the SSA_NAME chain length counter has reached
+ the limit, otherwise increment the counter and return true. */
+ bool next ();
+
+ /* If the SSA_NAME has already been "seen" return a positive value.
+ Otherwise add it to VISITED. If the SSA_NAME limit has been
+ reached, return a negative value. Otherwise return zero. */
+ int next_phi (tree);
+
+ ~ssa_name_limit_t ();
+};
+
+class pointer_query;
+
/* Describes a reference to an object used in an access. */
struct access_ref
{
@@ -162,17 +199,12 @@ struct access_ref
is a constant zero. */
access_ref (tree = NULL_TREE, bool = false);
- /* Reference to the accessed object(s). */
- tree ref;
+ /* Return the PHI node REF refers to or null if it doesn't. */
+ gphi *phi () const;
- /* Range of byte offsets into and sizes of the object(s). */
- offset_int offrng[2];
- offset_int sizrng[2];
- /* Range of the bound of the access: denotes that the access
- is at least BNDRNG[0] bytes but no more than BNDRNG[1].
- For string functions the size of the actual access is
- further constrained by the length of the string. */
- offset_int bndrng[2];
+ /* Return the object to which REF refers. */
+ tree get_ref (vec<access_ref> *, access_ref * = NULL, int = 1,
+ ssa_name_limit_t * = NULL, pointer_query * = NULL) const;
/* Return true if OFFRNG is the constant zero. */
bool offset_zero () const
@@ -188,6 +220,12 @@ struct access_ref
argument to the minimum. */
offset_int size_remaining (offset_int * = NULL) const;
+ /* Return true if *THIS is an access to a declared object. */
+ bool ref_declared () const
+ {
+ return DECL_P (ref) && base0 && deref < 1;
+ }
+
/* Set the size range to the maximum. */
void set_max_size_range ()
{
@@ -211,14 +249,82 @@ struct access_ref
add_offset (-maxoff - 1, maxoff);
}
+ /* Issue an informational message describing the target of an access
+ with the given mode. */
+ void inform_access (access_mode) const;
+
+ /* Reference to the accessed object(s). */
+ tree ref;
+
+ /* Range of byte offsets into and sizes of the object(s). */
+ offset_int offrng[2];
+ offset_int sizrng[2];
+ /* Range of the bound of the access: denotes that the access
+ is at least BNDRNG[0] bytes but no more than BNDRNG[1].
+ For string functions the size of the actual access is
+ further constrained by the length of the string. */
+ offset_int bndrng[2];
+
/* Used to fold integer expressions when called from front ends. */
tree (*eval)(tree);
+ /* Positive when REF is dereferenced, negative when its address is
+ taken. */
+ int deref;
/* Set if trailing one-element arrays should be treated as flexible
array members. */
bool trail1special;
/* Set if valid offsets must start at zero (for declared and allocated
objects but not for others referenced by pointers). */
bool base0;
+ /* Set if REF refers to a function array parameter not declared
+ static. */
+ bool parmarray;
+};
+
+class range_query;
+
+/* Queries and caches compute_objsize results. */
+class pointer_query
+{
+ DISABLE_COPY_AND_ASSIGN (pointer_query);
+
+public:
+ /* Type of the two-level cache object defined by clients of the class
+ to have pointer SSA_NAMEs cached for speedy access. */
+ struct cache_type
+ {
+ /* 1-based indices into cache. */
+ vec<unsigned> indices;
+ /* The cache itself. */
+ vec<access_ref> access_refs;
+ };
+
+ /* Construct an object with the given Ranger instance and cache. */
+ explicit pointer_query (range_query * = NULL, cache_type * = NULL);
+
+ /* Retrieve the access_ref for a variable from cache if it's there. */
+ const access_ref* get_ref (tree, int = 1) const;
+
+ /* Retrieve the access_ref for a variable from cache or compute it. */
+ bool get_ref (tree, access_ref*, int = 1);
+
+ /* Add an access_ref for the SSA_NAME to the cache. */
+ void put_ref (tree, const access_ref&, int = 1);
+
+ /* Flush the cache. */
+ void flush_cache ();
+
+ /* A Ranger instance. May be null to use global ranges. */
+ range_query *rvals;
+ /* Cache of SSA_NAMEs. May be null to disable caching. */
+ cache_type *var_cache;
+
+ /* Cache performance counters. */
+ mutable unsigned hits;
+ mutable unsigned misses;
+ mutable unsigned failures;
+ mutable unsigned depth;
+ mutable unsigned max_depth;
};
/* Describes a pair of references used in an access by built-in
@@ -242,14 +348,17 @@ struct access_data
access_mode mode;
};
-class range_query;
extern tree gimple_call_alloc_size (gimple *, wide_int[2] = NULL,
range_query * = NULL);
-extern tree gimple_parm_array_size (tree, wide_int[2], range_query * = NULL);
+extern tree gimple_parm_array_size (tree, wide_int[2], bool * = NULL);
+
extern tree compute_objsize (tree, int, access_ref *, range_query * = NULL);
+/* Legacy/transitional API. Should not be used in new code. */
+extern tree compute_objsize (tree, int, access_ref *, pointer_query *);
extern tree compute_objsize (tree, int, tree * = NULL, tree * = NULL,
range_query * = NULL);
extern bool check_access (tree, tree, tree, tree, tree,
access_mode, const access_data * = NULL);
+extern void maybe_emit_free_warning (tree);
#endif /* GCC_BUILTINS_H */
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 27a59c2..79d2655 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,409 @@
+2020-12-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c.opt: Add -stdlib= option and enumerations for
+ libstdc++ and libc++.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ * c.opt: Remove usage of Report.
+
+2020-12-14 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/98166
+ PR c++/57111
+ PR middle-end/98160
+ * c-attribs.c (maybe_add_noinline): New function.
+ (handle_malloc_attribute): Call it. Use ATTR_FLAG_INTERNAL.
+ Implicitly add attribute noinline to functions not declared inline
+ and warn on those.
+
+2020-12-09 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-pragma.c (omp_pragmas): Add 'allocate'.
+ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ALLOCATE.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98187
+ * c-pragma.c (omp_pragmas): Remove "master".
+ (omp_pragmas_simd): Add "master".
+
+2020-12-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/98126
+ * c-common.c (verify_tree_lim_r): New function.
+ (verify_sequence_points): Use it. Use nullptr instead of 0.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * c-attribs.c (handle_dealloc_attribute): New function.
+ (handle_malloc_attribute): Handle argument forms of attribute.
+ * c.opt (-Wmismatched-dealloc): New option.
+ (-Wmismatched-new-delete): New option.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * c-common.h (enum rid): Add RID_BUILTIN_BIT_CAST.
+ * c-common.c (c_common_reswords): Add __builtin_bit_cast.
+
+2020-12-01 JeanHeyd Meneide <phdofthehouse@gmail.com>
+
+ * c-cppbuiltin.c (c_cpp_builtins): Add predefined
+ {__GNUC_EXECUTION_CHARSET_NAME} and
+ _WIDE_EXECUTION_CHARSET_NAME} macros.
+
+2020-12-01 Nathan Sidwell <nathan@acm.org>
+
+ * c-common.c (module, import, export): New internal tokens (with
+ trailing space).
+ * c-common.h (RID__MODULE, RID__IMPORT & RID__EXPORT): Enumerate
+ them.
+ (D_CXX_MODULES, D_CXX_MODULES_FLAGS): Enable them.
+ * c-cppbuiltin.c (c_cpp_builtins): Feature macro.
+
+2020-12-01 Nathan Sidwell <nathan@acm.org>
+
+ * c-opts.c (c_common_init_options): Ask for module dependencies.
+ (c_common_handle_option): Handle -Mmodules -Mno-modules.
+ * c-pch.c (c_common_valid_pch): ... does not play with C++
+ modules.
+ * c.opt (Mmodules, Mno-modules): New preprocessor dependency
+ options.
+ (fmodules-ts, fmodule-header, fmodule-implicit-inline)
+ (fmodule-only, fmodule-mapper, fmodule-lazy)
+ (fmodule-version-ignore, Winvalid-imported-macros)
+ (flang-info-include-translate, flang-info-include-translate-not):
+ New options
+
+2020-11-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.c (dump_nested_type) <RECORD_TYPE>: Remove obsolete code.
+ (dump_ada_structure): Also deal with convention, unchecked union and
+ bit-field for nested types. In the latter case, print an Alignment
+ aspect along with the Pack aspect.
+
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR bootstrap/94982
+ * c-attribs.c (handle_patchable_function_entry_attribute): Avoid
+ -Wformat-diag.
+
+2020-11-24 Martin Sebor <msebor@redhat.com>
+
+ * c-warn.c (warn_parm_array_mismatch): Avoid invalid redeclarations.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * c-attribs.c (handle_special_var_sec_attribute): New.
+ (handle_noinit_attribute): Remove.
+ (attr_noinit_exclusions): Rename to...
+ (attr_section_exclusions): ...this, and add "persistent" attribute
+ exclusion.
+ (c_common_attribute_table): Add "persistent" attribute.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * c-pretty-print.c (c_pretty_printer::simple_type_specifier):
+ Treat opaque types like other types.
+ (c_pretty_printer::direct_abstract_declarator): Opaque types are
+ supported types.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ * c-warn.c (warn_parm_array_mismatch): Bail on invalid redeclarations
+ with fewer arguments.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97879
+ * c-attribs.c (handle_access_attribute): Handle ATTR_FLAG_INTERNAL.
+ Error out on invalid modes.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/88101
+ * c-common.c (check_builtin_function_arguments): Handle
+ BUILT_IN_CLEAR_PADDING.
+
+2020-11-18 Nathan Sidwell <nathan@acm.org>
+
+ * c-lex.c (c_lex_with_flags): CPP_HEADER_NAMEs can now be seen.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ * c-common.h (enum c_tree_index): Reorder to place lazy fields
+ after newly-added CTI_MODULE_HWM.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * c-cppbuiltin.c (builtin_define_float_constants): Define
+ "*_IS_IEC_60559__" macros.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ * c-lex.c: #include "langhooks.h".
+ (cb_undef): Maybe call preprocess_undef lang hook.
+ * c-opts.c (c_common_post_options): Maybe call preprocess_options
+ lang hook.
+ (push_command_line_include): Maybe call preprocess_main_file lang
+ hook.
+ (cb_file_change): Likewise.
+ * c-ppoutput.c: #include "langhooks.h.
+ (scan_translation_unit): Maybe call preprocess_token lang hook.
+ (class do_streamer): New, derive from token_streamer.
+ (directives_only_cb): Data pointer is do_streamer, call
+ preprocess_token lang hook.
+ (scan_translation_unit_directives_only): Use do_streamer.
+ (print_line_1): Move src_line recording to after string output.
+ (cb_undef): Maybe call preprocess_undef lang hook.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ * c-ppoutput.c (scan_translation_unit): Use token_streamer, remove
+ code duplicating that functionality.
+
+2020-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/90628
+ * c-common.c (check_builtin_function_arguments)
+ <case BUILT_IN_ADD_OVERFLOW>: Diagnose when last argument is pointer
+ to _Atomic. For the TYPE_READONLY case, adjust message to be usable
+ for more builtins and argument positions.
+
+2020-11-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/97854
+ * stub-objc.c: Include c-common.h to declare enum rid.
+
+2020-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/63287
+ * c-cppbuiltin.c: Include configargs.h.
+ (c_cpp_builtins): For C++11 and later if THREAD_MODEL_SPEC is not
+ defined, predefine __STDCPP_THREADS__ to 1 unless thread_model is
+ "single".
+
+2020-11-13 Gergö Barany <gergo@codesourcery.com>
+ Thomas Schwinge <thomas@codesourcery.com>
+
+ * c.opt (fopenacc-kernels): Add.
+
+2020-11-13 Jason Merrill <jason@redhat.com>
+
+ * c-cppbuiltin.c (c_cpp_builtins): Define __cpp_using_enum.
+
+2020-11-13 Piotr H. Dabrowski <phd@phd.re>
+
+ PR c++/91318
+ * c-cppbuiltin.c: c_cpp_builtins_optimize_pragma(): use cpp_define_unused()
+
+2020-11-13 Martin Liska <mliska@suse.cz>
+
+ * c-attribs.c (build_attr_access_from_parms): Format properly.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90707
+ * c-common.c (c_common_reswords): null_unspecified, nullable,
+ nonnull, null_resettable: New keywords.
+ * c-common.h (enum rid): RID_NULL_UNSPECIFIED, RID_NULLABLE,
+ RID_NONNULL, RID_NULL_RESETTABLE: New.
+ (OBJC_IS_PATTR_KEYWORD): Include nullability keywords in the
+ ranges accepted for property attributes.
+ * c-attribs.c (handle_objc_nullability_attribute): New.
+ * c-objc.h (enum objc_property_attribute_group): Add
+ OBJC_PROPATTR_GROUP_NULLABLE.
+ (enum objc_property_attribute_kind):Add
+ OBJC_PROPERTY_ATTR_NULL_UNSPECIFIED, OBJC_PROPERTY_ATTR_NULLABLE,
+ OBJC_PROPERTY_ATTR_NONNULL, OBJC_PROPERTY_ATTR_NULL_RESETTABLE.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * c-attribs.c (handle_objc_root_class_attribute): New
+ * c-objc.h (objc_start_class_interface): Add a location
+ value for the position of the class name.
+ * c.opt: Add Wobjc-root-class.
+ * stub-objc.c (objc_start_class_interface): Add a location
+ value for the position of the class name.
+
+2020-11-12 Joseph Myers <joseph@codesourcery.com>
+
+ * c-lex.c (c_common_has_attribute): Take argument std_syntax.
+ Allow scope for C. Handle standard attributes for C. Do not
+ accept unscoped attributes if std_syntax and not handled as
+ standard attributes.
+ * c-common.h (c_common_has_attribute): Update prototype.
+
+2020-11-12 Nicholas Guriev <guriev-ns@ya.ru>
+
+ PR pch/86674
+ * c-pch.c (c_common_valid_pch): Use cpp_warning with CPP_W_INVALID_PCH
+ reason to fix -Werror=invalid-pch and -Wno-error=invalid-pch switches.
+
+2020-11-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ * c-opts.c (c_common_post_options): Update latest_abi_version.
+
+2020-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97748
+ * c-common.h (warn_if_unused_value): Add quiet argument defaulted
+ to false.
+ * c-warn.c (warn_if_unused_value): Likewise. Pass it down
+ recursively and just return true instead of warning if it is true.
+ Handle COMPLEX_EXPR.
+
+2020-11-10 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-common.h (c_omp_adjust_map_clauses): New declaration.
+ * c-omp.c (struct map_clause): Helper type for c_omp_adjust_map_clauses.
+ (c_omp_adjust_map_clauses): New function.
+
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ DR 1914
+ * c-common.c (attribute_fallthrough_p): Tweak the warning
+ message.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * c-pragma.c (handle_pragma_diagnostic): Split the
+ unknown-option -Wpragmas diagnostic into a warning and a
+ subsequent note containing a spelling suggestion. Avoid
+ computing the suggestion if -Wpragmas warnings are being
+ suppressed.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ PR testsuite/97117
+ * c-indentation.c (get_visual_column): Remove location_t
+ parameter. Move the column-tracking diagnostic code from here
+ to ...
+ (should_warn_for_misleading_indentation): ... here, before the
+ early exit for when the loci are not all distinct. Don't pass a
+ location_t argument to get_visual_column.
+ (assert_get_visual_column_succeeds): Don't pass a location_t
+ argument to get_visual_column.
+ (assert_get_visual_column_fails): Likewise.
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-common.h (OBJC_IS_PATTR_KEYWORD): Add class to the list
+ of keywords accepted in @property attribute contexts.
+ * c-objc.h (enum objc_property_attribute_group): Add
+ OBJC_PROPATTR_GROUP_CLASS.
+ (enum objc_property_attribute_kind): Add
+ OBJC_PROPERTY_ATTR_CLASS.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-common.c (c_common_reswords): Add 'atomic' property
+ attribute.
+ * c-common.h (enum rid): Add RID_PROPATOMIC for atomic
+ property attributes.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-attribs.c (handle_nsobject_attribute): New.
+ * c.opt: Add WNSObject-attribute.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-objc.h (enum objc_property_attribute_group): New
+ (enum objc_property_attribute_kind): New.
+ (OBJC_PROPATTR_GROUP_MASK): New.
+ (struct property_attribute_info): Small class encapsulating
+ parser output from property attributes.
+ (objc_prop_attr_kind_for_rid): New
+ (objc_add_property_declaration): Simplify interface.
+ * stub-objc.c (enum rid): Dummy type.
+ (objc_add_property_declaration): Simplify interface.
+ (objc_prop_attr_kind_for_rid): New.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * c-ada-spec.c (collect_ada_nodes): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+ (collect_ada_node): Likewise.
+ (dump_forward_type): Likewise.
+ * c-common.c (set_underlying_type): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+ (user_facing_original_type, c_common_finalize_early_debug): Likewise.
+
+2020-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ * c-common.c (verify_sequence_points): Remove DEBUG_FUNCTION.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97675
+ * c.opt (Wexceptions): New option.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/25814
+ * c.opt (Wvexing-parse): New option.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97670
+ * c-omp.c (c_omp_split_clauses): Look through array reductions to find
+ underlying decl to clear in the allocate_head bitmap.
+
+2020-11-04 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-objc.h (objc_non_constant_expr_p): New.
+ * stub-objc.c (objc_non_constant_expr_p): New.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * c.opt (MQ,MT): Reword description to be make-agnostic.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * c-opts.c (c_common_post_options): Move var decl to its
+ initialization point.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-lex.c (c_lex_with_flags): When combining '@' with a
+ keyword for Objective-C, combine the location ranges too.
+
+2020-10-30 Qing Zhao <qing.zhao@oracle.com>
+ H.J.Lu <hjl.tools@gmail.com>
+
+ * c-attribs.c (c_common_attribute_table): Add new attribute
+ zero_call_used_regs.
+ (handle_zero_call_used_regs_attribute): New function.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * c-opts.c (c_common_post_options): In C++20, turn on
+ -Wdeprecated-enum-enum-conversion and
+ -Wdeprecated-enum-float-conversion.
+ * c.opt (Wdeprecated-enum-enum-conversion,
+ Wdeprecated-enum-float-conversion): New options.
+ (Wenum-conversion): Allow for C++ too.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ALLOCATE.
+ * c-omp.c: Include bitmap.h.
+ (c_omp_split_clauses): Handle OMP_CLAUSE_ALLOCATE.
+
+2020-10-26 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ * c-common.c (__is_nothrow_assignable): New.
+ (__is_nothrow_constructible): Likewise.
+ * c-common.h (RID_IS_NOTHROW_ASSIGNABLE): New.
+ (RID_IS_NOTHROW_CONSTRUCTIBLE): Likewise.
+
2020-10-23 Jan Hubicka <hubicka@ucw.cz>
* c-common.c (c_common_finalize_early_debug): Update for new thunk api.
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index c75b173..883036f 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -713,7 +713,7 @@ collect_ada_nodes (tree t, const char *source_file)
in the context of bindings) and namespaces (we do not handle them properly
yet). */
for (n = t; n; n = TREE_CHAIN (n))
- if (!DECL_IS_BUILTIN (n)
+ if (!DECL_IS_UNDECLARED_BUILTIN (n)
&& TREE_CODE (n) != NAMESPACE_DECL
&& LOCATION_FILE (decl_sloc (n, false)) == source_file)
to_dump_count++;
@@ -723,7 +723,7 @@ collect_ada_nodes (tree t, const char *source_file)
/* Store the relevant nodes. */
for (n = t; n; n = TREE_CHAIN (n))
- if (!DECL_IS_BUILTIN (n)
+ if (!DECL_IS_UNDECLARED_BUILTIN (n)
&& TREE_CODE (n) != NAMESPACE_DECL
&& LOCATION_FILE (decl_sloc (n, false)) == source_file)
to_dump[i++] = n;
@@ -2321,7 +2321,7 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
return 0;
case TYPE_DECL:
- if (DECL_IS_BUILTIN (node))
+ if (DECL_IS_UNDECLARED_BUILTIN (node))
{
/* Don't print the declaration of built-in types. */
if (name_only)
@@ -2444,7 +2444,7 @@ dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc)
return;
}
- if (DECL_IS_BUILTIN (decl) || TREE_VISITED (decl))
+ if (DECL_IS_UNDECLARED_BUILTIN (decl) || TREE_VISITED (decl))
return;
/* Forward declarations are only needed within a given file. */
@@ -2598,16 +2598,6 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
pp_string (buffer, " is ");
dump_ada_structure (buffer, field_type, t, true, spc);
-
- pp_string (buffer, "with Convention => C_Pass_By_Copy");
-
- if (TREE_CODE (field_type) == UNION_TYPE)
- {
- pp_comma (buffer);
- newline_and_indent (buffer, spc + 5);
- pp_string (buffer, "Unchecked_Union => True");
- }
-
pp_semicolon (buffer);
newline_and_indent (buffer, spc);
break;
@@ -3318,10 +3308,7 @@ dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested,
newline_and_indent (buffer, spc);
/* We disregard the methods for anonymous nested types. */
- if (nested)
- return;
-
- if (has_nontrivial_methods (node))
+ if (has_nontrivial_methods (node) && !nested)
{
pp_string (buffer, "with Import => True,");
newline_and_indent (buffer, spc + 5);
@@ -3339,12 +3326,20 @@ dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested,
if (bitfield_used)
{
+ char buf[32];
pp_comma (buffer);
newline_and_indent (buffer, spc + 5);
pp_string (buffer, "Pack => True");
+ pp_comma (buffer);
+ newline_and_indent (buffer, spc + 5);
+ sprintf (buf, "Alignment => %d", TYPE_ALIGN (node) / BITS_PER_UNIT);
+ pp_string (buffer, buf);
bitfield_used = false;
}
+ if (nested)
+ return;
+
need_semicolon = !dump_ada_methods (buffer, node, spc);
/* Print the static fields of the structure, if any. */
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index a3b2b3d..29e2672 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -94,10 +94,10 @@ static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
static tree handle_section_attribute (tree *, tree, tree, int, bool *);
+static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *);
static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree,
int, bool *);
-static tree handle_noinit_attribute (tree *, tree, tree, int, bool *);
static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
@@ -113,6 +113,7 @@ static tree handle_no_instrument_function_attribute (tree *, tree,
static tree handle_no_profile_instrument_function_attribute (tree *, tree,
tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_dealloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
bool *);
@@ -140,6 +141,8 @@ static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
+static tree handle_zero_call_used_regs_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_argspec_attribute (tree *, tree, tree, int, bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
@@ -155,6 +158,9 @@ static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *);
static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
int, bool *);
static tree handle_copy_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nsobject_attribute (tree *, tree, tree, int, bool *);
+static tree handle_objc_root_class_attribute (tree *, tree, tree, int, bool *);
+static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *);
/* Helper to define attribute exclusions. */
#define ATTR_EXCL(name, function, type, variable) \
@@ -243,9 +249,12 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
ATTR_EXCL (NULL, false, false, false)
};
-static const struct attribute_spec::exclusions attr_noinit_exclusions[] =
+/* Exclusions that apply to attributes that put declarations in specific
+ sections. */
+static const struct attribute_spec::exclusions attr_section_exclusions[] =
{
ATTR_EXCL ("noinit", true, true, true),
+ ATTR_EXCL ("persistent", true, true, true),
ATTR_EXCL ("section", true, true, true),
ATTR_EXCL (NULL, false, false, false),
};
@@ -334,7 +343,7 @@ const struct attribute_spec c_common_attribute_table[] =
{ "mode", 1, 1, false, true, false, false,
handle_mode_attribute, NULL },
{ "section", 1, 1, true, false, false, false,
- handle_section_attribute, attr_noinit_exclusions },
+ handle_section_attribute, attr_section_exclusions },
{ "aligned", 0, 1, false, false, false, false,
handle_aligned_attribute,
attr_aligned_exclusions },
@@ -356,7 +365,7 @@ const struct attribute_spec c_common_attribute_table[] =
{ "no_profile_instrument_function", 0, 0, true, false, false, false,
handle_no_profile_instrument_function_attribute,
NULL },
- { "malloc", 0, 0, true, false, false, false,
+ { "malloc", 0, 2, true, false, false, false,
handle_malloc_attribute, attr_alloc_exclusions },
{ "returns_twice", 0, 0, true, false, false, false,
handle_returns_twice_attribute,
@@ -451,6 +460,8 @@ const struct attribute_spec c_common_attribute_table[] =
ignore_attribute, NULL },
{ "no_split_stack", 0, 0, true, false, false, false,
handle_no_split_stack_attribute, NULL },
+ { "zero_call_used_regs", 1, 1, true, false, false, false,
+ handle_zero_call_used_regs_attribute, NULL },
/* For internal use only (marking of function arguments).
The name contains a space to prevent its usage in source code. */
{ "arg spec", 1, -1, true, false, false, false,
@@ -502,9 +513,20 @@ const struct attribute_spec c_common_attribute_table[] =
{ "copy", 1, 1, false, false, false, false,
handle_copy_attribute, NULL },
{ "noinit", 0, 0, true, false, false, false,
- handle_noinit_attribute, attr_noinit_exclusions },
+ handle_special_var_sec_attribute, attr_section_exclusions },
+ { "persistent", 0, 0, true, false, false, false,
+ handle_special_var_sec_attribute, attr_section_exclusions },
{ "access", 1, 3, false, true, true, false,
handle_access_attribute, NULL },
+ /* Attributes used by Objective-C. */
+ { "NSObject", 0, 0, true, false, false, false,
+ handle_nsobject_attribute, NULL },
+ { "objc_root_class", 0, 0, true, false, false, false,
+ handle_objc_root_class_attribute, NULL },
+ { "objc_nullability", 1, 1, true, false, false, false,
+ handle_objc_nullability_attribute, NULL },
+ { "*dealloc", 1, 2, true, false, false, false,
+ handle_dealloc_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -2373,64 +2395,112 @@ handle_weak_attribute (tree *node, tree name,
return NULL_TREE;
}
-/* Handle a "noinit" attribute; arguments as in struct
- attribute_spec.handler. Check whether the attribute is allowed
- here and add the attribute to the variable decl tree or otherwise
- issue a diagnostic. This function checks NODE is of the expected
- type and issues diagnostics otherwise using NAME. If it is not of
- the expected type *NO_ADD_ATTRS will be set to true. */
-
+/* Handle a "noinit" or "persistent" attribute; arguments as in
+ struct attribute_spec.handler.
+ This generic handler is used for "special variable sections" that allow the
+ section name to be set using a dedicated attribute. Additional validation
+ is performed for the specific properties of the section corresponding to the
+ attribute.
+ The ".noinit" section *is not* loaded by the program loader, and is not
+ initialized by the runtime startup code.
+ The ".persistent" section *is* loaded by the program loader, but is not
+ initialized by the runtime startup code. */
static tree
-handle_noinit_attribute (tree * node,
- tree name,
- tree args,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
+handle_special_var_sec_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
{
- const char *message = NULL;
+ tree decl = *node;
tree res = NULL_TREE;
- gcc_assert (DECL_P (*node));
- gcc_assert (args == NULL);
+ /* First perform generic validation common to "noinit" and "persistent"
+ attributes. */
+ if (!targetm_common.have_named_sections)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "section attributes are not supported for this target");
+ goto fail;
+ }
- if (TREE_CODE (*node) != VAR_DECL)
- message = G_("%qE attribute only applies to variables");
+ if (!VAR_P (decl))
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute not set on a variable",
+ name);
+ goto fail;
+ }
- /* Check that it's possible for the variable to have a section. */
- else if ((TREE_STATIC (*node) || DECL_EXTERNAL (*node) || in_lto_p)
- && DECL_SECTION_NAME (*node))
- message = G_("%qE attribute cannot be applied to variables "
- "with specific sections");
+ if (VAR_P (decl)
+ && current_function_decl != NULL_TREE
+ && !TREE_STATIC (decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE attribute cannot be specified for local variables",
+ name);
+ goto fail;
+ }
- else if (!targetm.have_switchable_bss_sections)
- message = G_("%qE attribute is specific to ELF targets");
+ if (VAR_P (decl)
+ && !targetm.have_tls && targetm.emutls.tmpl_section
+ && DECL_THREAD_LOCAL_P (decl))
+ {
+ error ("section of %q+D cannot be overridden", decl);
+ goto fail;
+ }
- if (message)
+ if (!targetm.have_switchable_bss_sections)
{
- warning (OPT_Wattributes, message, name);
- *no_add_attrs = true;
+ error ("%qE attribute is specific to ELF targets", name);
+ goto fail;
}
- else
+
+ if (TREE_READONLY (decl))
{
- res = targetm.handle_generic_attribute (node, name, args, flags,
- no_add_attrs);
- /* If the back end confirms the attribute can be added then continue onto
- final processing. */
- if (!(*no_add_attrs))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute set on const variable",
+ name);
+ goto fail;
+ }
+
+ /* Now validate noinit/persistent individually. */
+ if (strcmp (IDENTIFIER_POINTER (name), "noinit") == 0)
+ {
+ if (DECL_INITIAL (decl))
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute set on initialized variable",
+ name);
+ goto fail;
+ }
+ /* If this var is thought to be common, then change this. "noinit"
+ variables must be placed in an explicit ".noinit" section. */
+ DECL_COMMON (decl) = 0;
+ }
+ else if (strcmp (IDENTIFIER_POINTER (name), "persistent") == 0)
+ {
+ if (DECL_COMMON (decl) || DECL_INITIAL (decl) == NULL_TREE)
{
- /* If this var is thought to be common, then change this. Common
- variables are assigned to sections before the backend has a
- chance to process them. Do this only if the attribute is
- valid. */
- if (DECL_COMMON (*node))
- DECL_COMMON (*node) = 0;
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute set on uninitialized variable",
+ name);
+ goto fail;
}
}
+ else
+ gcc_unreachable ();
+
+ res = targetm.handle_generic_attribute (node, name, args, flags,
+ no_add_attrs);
+
+ /* If the back end confirms the attribute can be added then continue onto
+ final processing. */
+ if (!(*no_add_attrs))
+ return res;
+fail:
+ *no_add_attrs = true;
return res;
}
-
/* Handle a "noplt" attribute; arguments as in
struct attribute_spec.handler. */
@@ -2796,9 +2866,11 @@ handle_copy_attribute (tree *node, tree name, tree args,
tree attrs = TYPE_ATTRIBUTES (reftype);
/* Copy type attributes from REF to DECL. Pass in REF if it's a DECL
- or a type but not if it's an expression. */
+ or a type but not if it's an expression. Set ATTR_FLAG_INTERNAL
+ since the attributes' arguments may be in their internal form. */
for (tree at = attrs; at; at = TREE_CHAIN (at))
- decl_attributes (node, at, flags, EXPR_P (ref) ? NULL_TREE : ref);
+ decl_attributes (node, at, flags | ATTR_FLAG_INTERNAL,
+ EXPR_P (ref) ? NULL_TREE : ref);
return NULL_TREE;
}
@@ -3058,20 +3130,260 @@ handle_no_profile_instrument_function_attribute (tree *node, tree name, tree,
return NULL_TREE;
}
-/* Handle a "malloc" attribute; arguments as in
- struct attribute_spec.handler. */
+/* If ALLOC_DECL and DEALLOC_DECL are a pair of user-defined functions,
+ if they are declared inline issue warnings and return null. Otherwise
+ create attribute noinline, install it in ALLOC_DECL, and return it.
+ Otherwise return null. */
static tree
-handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), bool *no_add_attrs)
+maybe_add_noinline (tree name, tree alloc_decl, tree dealloc_decl,
+ bool *no_add_attrs)
{
- if (TREE_CODE (*node) == FUNCTION_DECL
- && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
- DECL_IS_MALLOC (*node) = 1;
- else
+ if (fndecl_built_in_p (alloc_decl) || fndecl_built_in_p (dealloc_decl))
+ return NULL_TREE;
+
+ /* When inlining (or optimization) is enabled and the allocator and
+ deallocator are not built-in functions, ignore the attribute on
+ functions declared inline since it could lead to false positives
+ when inlining one or the other call would wind up calling
+ a mismatched allocator or deallocator. */
+ if ((optimize && DECL_DECLARED_INLINE_P (alloc_decl))
+ || lookup_attribute ("always_inline", DECL_ATTRIBUTES (alloc_decl)))
+ {
+ warning (OPT_Wattributes,
+ "%<%E (%E)%> attribute ignored on functions "
+ "declared %qs", name, DECL_NAME (dealloc_decl), "inline");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if ((optimize && DECL_DECLARED_INLINE_P (dealloc_decl))
+ || lookup_attribute ("always_inline", DECL_ATTRIBUTES (dealloc_decl)))
+ {
+ warning (OPT_Wattributes,
+ "%<%E (%E)%> attribute ignored with deallocation "
+ "functions declared %qs",
+ name, DECL_NAME (dealloc_decl), "inline");
+ inform (DECL_SOURCE_LOCATION (dealloc_decl),
+ "deallocation function declared here" );
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* Disable inlining for non-standard deallocators to avoid false
+ positives due to mismatches between the inlined implementation
+ of one and not the other pair of functions. */
+ tree attr = tree_cons (get_identifier ("noinline"), NULL_TREE, NULL_TREE);
+ decl_attributes (&alloc_decl, attr, 0);
+ return attr;
+}
+
+/* Handle the "malloc" attribute. */
+
+static tree
+handle_malloc_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+ if (flags & ATTR_FLAG_INTERNAL)
+ /* Recursive call. */
+ return NULL_TREE;
+
+ tree fndecl = *node;
+
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored; valid only "
+ "for functions",
+ name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ tree rettype = TREE_TYPE (TREE_TYPE (*node));
+ if (!POINTER_TYPE_P (rettype))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored on functions "
+ "returning %qT; valid only for pointer return types",
+ name, rettype);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (!args)
+ {
+ /* Only the form of the attribute with no arguments declares
+ a function malloc-like. */
+ DECL_IS_MALLOC (*node) = 1;
+ return NULL_TREE;
+ }
+
+ tree dealloc = TREE_VALUE (args);
+ if (error_operand_p (dealloc))
+ {
+ /* If the argument is in error it will have already been diagnosed.
+ Avoid issuing redundant errors here. */
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ STRIP_NOPS (dealloc);
+ if (TREE_CODE (dealloc) == ADDR_EXPR)
+ {
+ /* In C++ the argument may be wrapped in a cast to disambiguate
+ one of a number of overloads (such as operator delete). To
+ make things interesting, the cast looks different between
+ different C++ versions. Strip it and install the attribute
+ with the disambiguated function. */
+ dealloc = TREE_OPERAND (dealloc, 0);
+
+ *no_add_attrs = true;
+ tree attr = tree_cons (NULL_TREE, dealloc, TREE_CHAIN (args));
+ attr = build_tree_list (name, attr);
+ return decl_attributes (node, attr, 0);
+ }
+
+ if (TREE_CODE (dealloc) != FUNCTION_DECL)
+ {
+ if (TREE_CODE (dealloc) == OVERLOAD)
+ {
+ /* Handle specially the common case of specifying one of a number
+ of overloads, such as operator delete. */
+ error ("%qE attribute argument 1 is ambiguous", name);
+ inform (input_location,
+ "use a cast to the expected type to disambiguate");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ error ("%qE attribute argument 1 does not name a function", name);
+ if (DECL_P (dealloc))
+ inform (DECL_SOURCE_LOCATION (dealloc),
+ "argument references a symbol declared here");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* Mentioning the deallocation function qualifies as its use. */
+ TREE_USED (dealloc) = 1;
+
+ tree fntype = TREE_TYPE (dealloc);
+ tree argpos = TREE_CHAIN (args) ? TREE_VALUE (TREE_CHAIN (args)) : NULL_TREE;
+ if (!argpos)
+ {
+ tree argtypes = TYPE_ARG_TYPES (fntype);
+ if (!argtypes)
+ {
+ /* Reject functions without a prototype. */
+ error ("%qE attribute argument 1 must take a pointer "
+ "type as its first argument", name);
+ inform (DECL_SOURCE_LOCATION (dealloc),
+ "refernced symbol declared here" );
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ tree argtype = TREE_VALUE (argtypes);
+ if (TREE_CODE (argtype) != POINTER_TYPE)
+ {
+ /* Reject functions that don't take a pointer as their first
+ argument. */
+ error ("%qE attribute argument 1 must take a pointer type "
+ "as its first argument; have %qT", name, argtype);
+ inform (DECL_SOURCE_LOCATION (dealloc),
+ "referenced symbol declared here" );
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* Disable inlining for non-standard deallocators to avoid false
+ positives (or warn if either function is explicitly inline). */
+ tree at_noinline =
+ maybe_add_noinline (name, fndecl, dealloc, no_add_attrs);
+ if (*no_add_attrs)
+ return NULL_TREE;
+
+ /* Add attribute *dealloc to the deallocator function associating
+ it with this one. Ideally, the attribute would reference
+ the DECL of the deallocator but since that changes for each
+ redeclaration, use DECL_NAME instead. (DECL_ASSEMBLER_NAME
+ need not be set set this point and setting it here is too early. */
+ tree attrs = build_tree_list (NULL_TREE, DECL_NAME (fndecl));
+ attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline);
+ decl_attributes (&dealloc, attrs, 0);
+ return NULL_TREE;
+ }
+
+ /* Validate the positional argument. */
+ argpos = positional_argument (fntype, name, argpos, POINTER_TYPE);
+ if (!argpos)
{
- warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* As above, disable inlining for non-standard deallocators to avoid
+ false positives (or warn). */
+ tree at_noinline =
+ maybe_add_noinline (name, fndecl, dealloc, no_add_attrs);
+ if (*no_add_attrs)
+ return NULL_TREE;
+
+ /* It's valid to declare the same function with multiple instances
+ of attribute malloc, each naming the same or different deallocator
+ functions, and each referencing either the same or a different
+ positional argument. */
+ tree attrs = tree_cons (NULL_TREE, argpos, NULL_TREE);
+ attrs = tree_cons (NULL_TREE, DECL_NAME (fndecl), attrs);
+ attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline);
+ decl_attributes (&dealloc, attrs, 0);
+ return NULL_TREE;
+}
+
+/* Handle the internal "*dealloc" attribute added for functions declared
+ with the one- and two-argument forms of attribute malloc. Add it
+ to *NODE unless it's already there with the same arguments. */
+
+static tree
+handle_dealloc_attribute (tree *node, tree name, tree args, int,
+ bool *no_add_attrs)
+{
+ tree fndecl = *node;
+
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return NULL_TREE;
+
+ tree arg = TREE_VALUE (args);
+ args = TREE_CHAIN (args);
+ tree arg_pos = args ? TREE_VALUE (args) : integer_zero_node;
+
+ gcc_checking_assert ((DECL_P (arg)
+ && fndecl_built_in_p (arg, BUILT_IN_NORMAL))
+ || TREE_CODE (arg) == IDENTIFIER_NODE);
+
+ const char* const namestr = IDENTIFIER_POINTER (name);
+ for (tree at = attrs; (at = lookup_attribute (namestr, at));
+ at = TREE_CHAIN (at))
+ {
+ tree alloc = TREE_VALUE (at);
+ if (!alloc)
+ continue;
+
+ tree pos = TREE_CHAIN (alloc);
+ alloc = TREE_VALUE (alloc);
+ pos = pos ? TREE_VALUE (pos) : integer_zero_node;
+ gcc_checking_assert ((DECL_P (alloc)
+ && fndecl_built_in_p (alloc, BUILT_IN_NORMAL))
+ || TREE_CODE (alloc) == IDENTIFIER_NODE);
+
+ if (alloc == arg && tree_int_cst_equal (pos, arg_pos))
+ {
+ /* The function already has the attribute either without any
+ arguments or with the same arguments as the attribute that's
+ being added. Return without adding another copy. */
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
}
return NULL_TREE;
@@ -4275,8 +4587,8 @@ append_access_attr (tree node[3], tree attrs, const char *attrstr,
the attribute and its arguments into a string. */
static tree
-handle_access_attribute (tree node[3], tree name, tree args,
- int ARG_UNUSED (flags), bool *no_add_attrs)
+handle_access_attribute (tree node[3], tree name, tree args, int flags,
+ bool *no_add_attrs)
{
tree attrs = TYPE_ATTRIBUTES (*node);
tree type = *node;
@@ -4322,15 +4634,19 @@ handle_access_attribute (tree node[3], tree name, tree args,
/* Recursively call self to "replace" the documented/external
form of the attribute with the condensend internal form. */
- decl_attributes (node, axsat, flags);
+ decl_attributes (node, axsat, flags | ATTR_FLAG_INTERNAL);
return NULL_TREE;
}
- /* This is a recursive call to handle the condensed internal form
- of the attribute (see below). Since all validation has been
- done simply return here, accepting the attribute as is. */
- *no_add_attrs = false;
- return NULL_TREE;
+ if (flags & ATTR_FLAG_INTERNAL)
+ {
+ /* This is a recursive call to handle the condensed internal
+ form of the attribute (see below). Since all validation
+ has been done simply return here, accepting the attribute
+ as is. */
+ *no_add_attrs = false;
+ return NULL_TREE;
+ }
}
/* Set to true when the access mode has the form of a function call
@@ -4349,6 +4665,13 @@ handle_access_attribute (tree node[3], tree name, tree args,
access_mode = DECL_NAME (access_mode);
funcall = true;
}
+ else if (TREE_CODE (access_mode) != IDENTIFIER_NODE)
+ {
+ error ("attribute %qE mode %qE is not an identifier; expected one of "
+ "%qs, %qs, %qs, or %qs", name, access_mode,
+ "read_only", "read_write", "write_only", "none");
+ return NULL_TREE;
+ }
const char* const access_str = IDENTIFIER_POINTER (access_mode);
const char *ps = access_str;
@@ -4559,7 +4882,7 @@ handle_access_attribute (tree node[3], tree name, tree args,
/* Recursively call self to "replace" the documented/external form
of the attribute with the condensed internal form. */
- decl_attributes (node, new_attrs, flags);
+ decl_attributes (node, new_attrs, flags | ATTR_FLAG_INTERNAL);
return NULL_TREE;
}
@@ -4687,7 +5010,7 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr)
/* Attribute access takes a two or three arguments. Wrap VBLIST in
another list in case it has more nodes than would otherwise fit. */
- vblist = build_tree_list (NULL_TREE, vblist);
+ vblist = build_tree_list (NULL_TREE, vblist);
/* Build a single attribute access with the string describing all
array arguments and an optional list of any non-parameter VLA
@@ -4994,6 +5317,53 @@ handle_no_split_stack_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "zero_call_used_regs" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_zero_call_used_regs_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree decl = *node;
+ tree id = TREE_VALUE (args);
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE attribute applies only to functions", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE argument not a string", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ bool found = false;
+ for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
+ if (strcmp (TREE_STRING_POINTER (id),
+ zero_call_used_regs_opts[i].name) == 0)
+ {
+ found = true;
+ break;
+ }
+
+ if (!found)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "unrecognized %qE attribute argument %qs",
+ name, TREE_STRING_POINTER (id));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "returns_nonnull" attribute; arguments as in
struct attribute_spec.handler. */
@@ -5064,8 +5434,8 @@ handle_patchable_function_entry_attribute (tree *, tree name, tree args,
if (tree_to_uhwi (val) > USHRT_MAX)
{
warning (OPT_Wattributes,
- "%qE attribute argument %qE is out of range (> 65535)",
- name, val);
+ "%qE attribute argument %qE exceeds %u",
+ name, val, USHRT_MAX);
*no_add_attrs = true;
return NULL_TREE;
}
@@ -5073,6 +5443,103 @@ handle_patchable_function_entry_attribute (tree *, tree name, tree args,
return NULL_TREE;
}
+/* Handle a "NSObject" attributes; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_nsobject_attribute (tree *node, tree name, tree args,
+ int /*flags*/, bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+
+ /* This attribute only applies to typedefs (or field decls for properties),
+ we drop it otherwise - but warn about this if enabled. */
+ if (TREE_CODE (*node) != TYPE_DECL && TREE_CODE (*node) != FIELD_DECL)
+ {
+ warning (OPT_WNSObject_attribute, "%qE attribute may be put on a"
+ " typedef only; attribute is ignored", name);
+ return NULL_TREE;
+ }
+
+ /* The original implementation only allowed pointers to records, however
+ recent implementations also allow void *. */
+ tree type = TREE_TYPE (*node);
+ if (!type || !POINTER_TYPE_P (type)
+ || (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE
+ && !VOID_TYPE_P (TREE_TYPE (type))))
+ {
+ error ("%qE attribute is for pointer types only", name);
+ return NULL_TREE;
+ }
+
+ tree t = tree_cons (name, args, TYPE_ATTRIBUTES (type));
+ TREE_TYPE (*node) = build_type_attribute_variant (type, t);
+
+ return NULL_TREE;
+}
+
+/* Handle a "objc_root_class" attributes; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_objc_root_class_attribute (tree */*node*/, tree name, tree /*args*/,
+ int /*flags*/, bool *no_add_attrs)
+{
+ /* This has no meaning outside Objective-C. */
+ if (!c_dialect_objc())
+ warning (OPT_Wattributes, "%qE is only applicable to Objective-C"
+ " class interfaces, attribute ignored", name);
+
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+/* Handle an "objc_nullability" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_objc_nullability_attribute (tree *node, tree name, tree args,
+ int /*flags*/,
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+
+ tree type = TREE_TYPE (*node);
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ type = TREE_TYPE (type);
+
+ if (type && !POINTER_TYPE_P (type))
+ {
+ error ("%qE cannot be applied to non-pointer type %qT", name, type);
+ return NULL_TREE;
+ }
+
+ /* We accept objc_nullability() with a single argument.
+ string: "unspecified", "nullable", "nonnull" or "resettable"
+ integer: 0 and 3 where the values have the same meaning as
+ the strings. */
+ tree val = TREE_VALUE (args);
+ if (TREE_CODE (val) == INTEGER_CST)
+ {
+ val = default_conversion (val);
+ if (!tree_fits_uhwi_p (val) || tree_to_uhwi (val) > 3)
+ error ("%qE attribute argument %qE is not an integer constant"
+ " between 0 and 3", name, val);
+ else
+ *no_add_attrs = false; /* OK */
+ }
+ else if (TREE_CODE (val) == STRING_CST
+ && (strcmp (TREE_STRING_POINTER (val), "nullable") == 0
+ || strcmp (TREE_STRING_POINTER (val), "nonnull") == 0
+ || strcmp (TREE_STRING_POINTER (val), "unspecified") == 0
+ || strcmp (TREE_STRING_POINTER (val), "resettable") == 0))
+ *no_add_attrs = false; /* OK */
+ else if (val != error_mark_node)
+ error ("%qE attribute argument %qE is not recognised", name, val);
+
+ return NULL_TREE;
+}
+
/* Attempt to partially validate a single attribute ATTR as if
it were to be applied to an entity OPER. */
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 1787dfd..0b348ae 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -374,6 +374,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__auto_type", RID_AUTO_TYPE, D_CONLY },
{ "__bases", RID_BASES, D_CXXONLY },
{ "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY },
+ { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY },
{ "__builtin_call_with_static_chain",
RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
@@ -527,6 +528,8 @@ const struct c_common_resword c_common_reswords[] =
{ "while", RID_WHILE, 0 },
{ "__is_assignable", RID_IS_ASSIGNABLE, D_CXXONLY },
{ "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY },
+ { "__is_nothrow_assignable", RID_IS_NOTHROW_ASSIGNABLE, D_CXXONLY },
+ { "__is_nothrow_constructible", RID_IS_NOTHROW_CONSTRUCTIBLE, D_CXXONLY },
/* C++ transactional memory. */
{ "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM },
@@ -538,6 +541,12 @@ const struct c_common_resword c_common_reswords[] =
{ "concept", RID_CONCEPT, D_CXX_CONCEPTS_FLAGS | D_CXXWARN },
{ "requires", RID_REQUIRES, D_CXX_CONCEPTS_FLAGS | D_CXXWARN },
+ /* Modules-related keywords, these are internal unspellable tokens,
+ created by the preprocessor. */
+ { "module ", RID__MODULE, D_CXX_MODULES_FLAGS | D_CXXWARN },
+ { "import ", RID__IMPORT, D_CXX_MODULES_FLAGS | D_CXXWARN },
+ { "export ", RID__EXPORT, D_CXX_MODULES_FLAGS | D_CXXWARN },
+
/* Coroutines-related keywords */
{ "co_await", RID_CO_AWAIT, D_CXX_COROUTINES_FLAGS | D_CXXWARN },
{ "co_yield", RID_CO_YIELD, D_CXX_COROUTINES_FLAGS | D_CXXWARN },
@@ -569,14 +578,21 @@ const struct c_common_resword c_common_reswords[] =
{ "oneway", RID_ONEWAY, D_OBJC },
{ "out", RID_OUT, D_OBJC },
/* These are recognized inside a property attribute list */
- { "assign", RID_ASSIGN, D_OBJC },
- { "copy", RID_COPY, D_OBJC },
- { "getter", RID_GETTER, D_OBJC },
- { "nonatomic", RID_NONATOMIC, D_OBJC },
- { "readonly", RID_READONLY, D_OBJC },
- { "readwrite", RID_READWRITE, D_OBJC },
- { "retain", RID_RETAIN, D_OBJC },
- { "setter", RID_SETTER, D_OBJC },
+ { "assign", RID_ASSIGN, D_OBJC },
+ { "atomic", RID_PROPATOMIC, D_OBJC },
+ { "copy", RID_COPY, D_OBJC },
+ { "getter", RID_GETTER, D_OBJC },
+ { "nonatomic", RID_NONATOMIC, D_OBJC },
+ { "readonly", RID_READONLY, D_OBJC },
+ { "readwrite", RID_READWRITE, D_OBJC },
+ { "retain", RID_RETAIN, D_OBJC },
+ { "setter", RID_SETTER, D_OBJC },
+ /* These are Objective C implementation of nullability, accepted only in
+ specific contexts. */
+ { "null_unspecified", RID_NULL_UNSPECIFIED, D_OBJC },
+ { "nullable", RID_NULLABLE, D_OBJC },
+ { "nonnull", RID_NONNULL, D_OBJC },
+ { "null_resettable", RID_NULL_RESETTABLE, D_OBJC },
};
const unsigned int num_c_common_reswords =
@@ -2040,23 +2056,45 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
}
}
+static constexpr size_t verify_sequence_points_limit = 1024;
+
+/* Called from verify_sequence_points via walk_tree. */
+
+static tree
+verify_tree_lim_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (++*((size_t *) data) > verify_sequence_points_limit)
+ return integer_zero_node;
+
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
+}
+
/* Try to warn for undefined behavior in EXPR due to missing sequence
points. */
-DEBUG_FUNCTION void
+void
verify_sequence_points (tree expr)
{
- struct tlist *before_sp = 0, *after_sp = 0;
+ tlist *before_sp = nullptr, *after_sp = nullptr;
- warned_ids = 0;
- save_expr_cache = 0;
- if (tlist_firstobj == 0)
+ /* verify_tree is highly recursive, and merge_tlist is O(n^2),
+ so we return early if the expression is too big. */
+ size_t n = 0;
+ if (walk_tree (&expr, verify_tree_lim_r, &n, nullptr))
+ return;
+
+ warned_ids = nullptr;
+ save_expr_cache = nullptr;
+ if (!tlist_firstobj)
{
gcc_obstack_init (&tlist_obstack);
tlist_firstobj = (char *) obstack_alloc (&tlist_obstack, 0);
}
- verify_tree (expr, &before_sp, &after_sp, 0);
+ verify_tree (expr, &before_sp, &after_sp, NULL_TREE);
warn_for_collisions (after_sp);
obstack_free (&tlist_obstack, tlist_firstobj);
}
@@ -5749,9 +5787,10 @@ attribute_fallthrough_p (tree attr)
tree t = lookup_attribute ("fallthrough", attr);
if (t == NULL_TREE)
return false;
- /* This attribute shall appear at most once in each attribute-list. */
+ /* It is no longer true that "this attribute shall appear at most once in
+ each attribute-list", but we still give a warning. */
if (lookup_attribute ("fallthrough", TREE_CHAIN (t)))
- warning (OPT_Wattributes, "%<fallthrough%> attribute specified multiple "
+ warning (OPT_Wattributes, "attribute %<fallthrough%> specified multiple "
"times");
/* No attribute-argument-clause shall be present. */
else if (TREE_VALUE (t) != NULL_TREE)
@@ -6123,11 +6162,18 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
}
else if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (args[2]))))
{
- error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
- "has pointer to %<const%> type (%qT)", fndecl,
+ error_at (ARG_LOCATION (2), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 3, fndecl, "const",
TREE_TYPE (args[2]));
return false;
}
+ else if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (args[2]))))
+ {
+ error_at (ARG_LOCATION (2), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 3, fndecl,
+ "_Atomic", TREE_TYPE (args[2]));
+ return false;
+ }
return true;
}
return false;
@@ -6161,6 +6207,39 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
}
return false;
+ case BUILT_IN_CLEAR_PADDING:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 1))
+ {
+ if (!POINTER_TYPE_P (TREE_TYPE (args[0])))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function "
+ "%qE does not have pointer type", 1, fndecl);
+ return false;
+ }
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (args[0]))))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function "
+ "%qE points to incomplete type", 1, fndecl);
+ return false;
+ }
+ else if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (args[0]))))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 1, fndecl, "const",
+ TREE_TYPE (args[0]));
+ return false;
+ }
+ else if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (args[0]))))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 1, fndecl,
+ "_Atomic", TREE_TYPE (args[0]));
+ return false;
+ }
+ return true;
+ }
+ return false;
+
default:
return true;
}
@@ -7837,7 +7916,7 @@ set_underlying_type (tree x)
{
if (x == error_mark_node)
return;
- if (DECL_IS_BUILTIN (x) && TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE)
+ if (DECL_IS_UNDECLARED_BUILTIN (x) && TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE)
{
if (TYPE_NAME (TREE_TYPE (x)) == 0)
TYPE_NAME (TREE_TYPE (x)) = x;
@@ -7871,7 +7950,7 @@ user_facing_original_type_p (const_tree type)
tree decl = TYPE_NAME (type);
/* Look through any typedef in "user" code. */
- if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_BUILTIN (decl))
+ if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_UNDECLARED_BUILTIN (decl))
return true;
/* If the original type is also named and is in the user namespace,
@@ -8367,13 +8446,13 @@ reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
if (TREE_TYPE (expr)
&& TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
&& TREE_CODE (expr) == FUNCTION_DECL
- /* The intersection of DECL_BUILT_IN and DECL_IS_BUILTIN avoids
+ /* The intersection of DECL_BUILT_IN and DECL_IS_UNDECLARED_BUILTIN avoids
false positives for user-declared built-ins such as abs or
strlen, and for C++ operators new and delete.
The c_decl_implicit() test avoids false positives for implicitly
declared built-ins with library fallbacks (such as abs). */
&& fndecl_built_in_p (expr)
- && DECL_IS_BUILTIN (expr)
+ && DECL_IS_UNDECLARED_BUILTIN (expr)
&& !c_decl_implicit (expr)
&& !DECL_ASSEMBLER_NAME_SET_P (expr))
{
@@ -9135,7 +9214,8 @@ c_common_finalize_early_debug (void)
struct cgraph_node *cnode;
FOR_EACH_FUNCTION (cnode)
if (!cnode->alias && !cnode->thunk
- && (cnode->has_gimple_body_p () || !DECL_IS_BUILTIN (cnode->decl)))
+ && (cnode->has_gimple_body_p ()
+ || !DECL_IS_UNDECLARED_BUILTIN (cnode->decl)))
(*debug_hooks->early_global_decl) (cnode->decl);
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bb38e6c..80830d8 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -85,7 +85,12 @@ enum rid
RID_GETTER, RID_SETTER,
RID_READONLY, RID_READWRITE,
RID_ASSIGN, RID_RETAIN, RID_COPY,
- RID_NONATOMIC,
+ RID_PROPATOMIC, RID_NONATOMIC,
+
+ /* ObjC nullability support keywords that also can appear in the
+ property attribute context. These values should remain contiguous
+ with the other property attributes. */
+ RID_NULL_UNSPECIFIED, RID_NULLABLE, RID_NONNULL, RID_NULL_RESETTABLE,
/* C (reserved and imaginary types not implemented, so any use is a
syntax error) */
@@ -164,7 +169,7 @@ enum rid
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_UNIQUE_OBJ_REPRESENTATIONS,
- RID_HAS_VIRTUAL_DESTRUCTOR,
+ RID_HAS_VIRTUAL_DESTRUCTOR, RID_BUILTIN_BIT_CAST,
RID_IS_ABSTRACT, RID_IS_AGGREGATE,
RID_IS_BASE_OF, RID_IS_CLASS,
RID_IS_EMPTY, RID_IS_ENUM,
@@ -176,6 +181,7 @@ enum rid
RID_IS_TRIVIALLY_COPYABLE,
RID_IS_UNION, RID_UNDERLYING_TYPE,
RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE,
+ RID_IS_NOTHROW_ASSIGNABLE, RID_IS_NOTHROW_CONSTRUCTIBLE,
/* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
@@ -189,6 +195,9 @@ enum rid
/* C++ concepts */
RID_CONCEPT, RID_REQUIRES,
+ /* C++ modules. */
+ RID__MODULE, RID__IMPORT, RID__EXPORT, /* Internal tokens. */
+
/* C++ coroutines */
RID_CO_AWAIT, RID_CO_YIELD, RID_CO_RETURN,
@@ -263,7 +272,7 @@ enum rid
RID_FIRST_PQ = RID_IN,
RID_LAST_PQ = RID_ONEWAY,
RID_FIRST_PATTR = RID_GETTER,
- RID_LAST_PATTR = RID_NONATOMIC
+ RID_LAST_PATTR = RID_NULL_RESETTABLE
};
#define OBJC_IS_AT_KEYWORD(rid) \
@@ -274,9 +283,11 @@ enum rid
((unsigned int) (rid) >= (unsigned int) RID_FIRST_PQ && \
(unsigned int) (rid) <= (unsigned int) RID_LAST_PQ)
+/* Keywords permitted in an @property attribute context. */
#define OBJC_IS_PATTR_KEYWORD(rid) \
- ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PATTR && \
- (unsigned int) (rid) <= (unsigned int) RID_LAST_PATTR)
+ ((((unsigned int) (rid) >= (unsigned int) RID_FIRST_PATTR && \
+ (unsigned int) (rid) <= (unsigned int) RID_LAST_PATTR)) \
+ || rid == RID_CLASS)
/* OBJC_IS_CXX_KEYWORD recognizes the 'CXX_OBJC' keywords (such as
'class') which are shared in a subtle way between Objective-C and
@@ -356,13 +367,17 @@ enum c_tree_index
CTI_DEFAULT_FUNCTION_TYPE,
+ CTI_NULL,
+
/* These are not types, but we have to look them up all the time. */
CTI_FUNCTION_NAME_DECL,
CTI_PRETTY_FUNCTION_NAME_DECL,
CTI_C99_FUNCTION_NAME_DECL,
- CTI_SAVED_FUNCTION_NAME_DECLS,
- CTI_NULL,
+ CTI_MODULE_HWM,
+ /* Below here entities change during compilation. */
+
+ CTI_SAVED_FUNCTION_NAME_DECLS,
CTI_MAX
};
@@ -437,9 +452,11 @@ extern machine_mode c_default_pointer_mode;
#define D_CXX_CHAR8_T 0X1000 /* In C++, only with -fchar8_t. */
#define D_CXX20 0x2000 /* In C++, C++20 only. */
#define D_CXX_COROUTINES 0x4000 /* In C++, only with coroutines. */
+#define D_CXX_MODULES 0x8000 /* In C++, only with modules. */
#define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS
#define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T
+#define D_CXX_MODULES_FLAGS (D_CXXONLY | D_CXX_MODULES)
#define D_CXX_COROUTINES_FLAGS (D_CXXONLY | D_CXX_COROUTINES)
/* The reserved keyword table. */
@@ -1039,7 +1056,7 @@ extern bool c_cpp_diagnostic (cpp_reader *, enum cpp_diagnostic_level,
enum cpp_warning_reason, rich_location *,
const char *, va_list *)
ATTRIBUTE_GCC_DIAG(5,0);
-extern int c_common_has_attribute (cpp_reader *);
+extern int c_common_has_attribute (cpp_reader *, bool);
extern int c_common_has_builtin (cpp_reader *);
extern bool parse_optimize_options (tree, bool);
@@ -1221,6 +1238,7 @@ extern enum omp_clause_defaultmap_kind c_omp_predetermined_mapping (tree);
extern tree c_omp_check_context_selector (location_t, tree);
extern void c_omp_mark_declare_variant (location_t, tree, tree);
extern const char *c_omp_map_clause_name (tree, bool);
+extern void c_omp_adjust_map_clauses (tree, bool);
/* Return next tree in the chain for chain_next walking of tree nodes. */
static inline tree
@@ -1361,7 +1379,7 @@ extern void warn_tautological_cmp (const op_location_t &, enum tree_code,
tree, tree);
extern void warn_logical_not_parentheses (location_t, enum tree_code, tree,
tree);
-extern bool warn_if_unused_value (const_tree, location_t);
+extern bool warn_if_unused_value (const_tree, location_t, bool = false);
extern bool strict_aliasing_warning (location_t, tree, tree);
extern void sizeof_pointer_memaccess_warning (location_t *, tree,
vec<tree, va_gc> *, tree *,
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index e5ebb79..7b7b07d 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h" /* For dwarf2out_do_cfi_asm. */
#include "common/common-target.h"
#include "cppbuiltin.h"
+#include "configargs.h"
#ifndef TARGET_OS_CPP_BUILTINS
# define TARGET_OS_CPP_BUILTINS()
@@ -316,6 +317,16 @@ builtin_define_float_constants (const char *name_prefix,
sprintf (name, "__FP_FAST_FMA%s", fma_suffix);
builtin_define_with_int_value (name, 1);
}
+
+ /* For C2x *_IS_IEC_60559. 0 means the type does not match an IEC
+ 60559 format, 1 that it matches a format but not operations and 2
+ that it matches a format and operations (but may not conform to
+ Annex F; we take this as meaning exceptions and rounding modes
+ need not be supported). */
+ sprintf (name, "__%s_IS_IEC_60559__", name_prefix);
+ builtin_define_with_int_value (name,
+ (fmt->ieee_bits == 0
+ ? 0 : (fmt->round_towards_zero ? 1 : 2)));
}
/* Define __DECx__ constants for TYPE using NAME_PREFIX and SUFFIX. */
@@ -581,41 +592,41 @@ c_cpp_builtins_optimize_pragma (cpp_reader *pfile, tree prev_tree,
/* Other target-independent built-ins determined by command-line
options. */
if (!prev->x_optimize_size && cur->x_optimize_size)
- cpp_define (pfile, "__OPTIMIZE_SIZE__");
+ cpp_define_unused (pfile, "__OPTIMIZE_SIZE__");
else if (prev->x_optimize_size && !cur->x_optimize_size)
cpp_undef (pfile, "__OPTIMIZE_SIZE__");
if (!prev->x_optimize && cur->x_optimize)
- cpp_define (pfile, "__OPTIMIZE__");
+ cpp_define_unused (pfile, "__OPTIMIZE__");
else if (prev->x_optimize && !cur->x_optimize)
cpp_undef (pfile, "__OPTIMIZE__");
prev_fast_math = fast_math_flags_struct_set_p (prev);
cur_fast_math = fast_math_flags_struct_set_p (cur);
if (!prev_fast_math && cur_fast_math)
- cpp_define (pfile, "__FAST_MATH__");
+ cpp_define_unused (pfile, "__FAST_MATH__");
else if (prev_fast_math && !cur_fast_math)
cpp_undef (pfile, "__FAST_MATH__");
if (!prev->x_flag_signaling_nans && cur->x_flag_signaling_nans)
- cpp_define (pfile, "__SUPPORT_SNAN__");
+ cpp_define_unused (pfile, "__SUPPORT_SNAN__");
else if (prev->x_flag_signaling_nans && !cur->x_flag_signaling_nans)
cpp_undef (pfile, "__SUPPORT_SNAN__");
if (!prev->x_flag_errno_math && cur->x_flag_errno_math)
cpp_undef (pfile, "__NO_MATH_ERRNO__");
else if (prev->x_flag_errno_math && !cur->x_flag_errno_math)
- cpp_define (pfile, "__NO_MATH_ERRNO__");
+ cpp_define_unused (pfile, "__NO_MATH_ERRNO__");
if (!prev->x_flag_finite_math_only && cur->x_flag_finite_math_only)
{
cpp_undef (pfile, "__FINITE_MATH_ONLY__");
- cpp_define (pfile, "__FINITE_MATH_ONLY__=1");
+ cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=1");
}
else if (prev->x_flag_finite_math_only && !cur->x_flag_finite_math_only)
{
cpp_undef (pfile, "__FINITE_MATH_ONLY__");
- cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
+ cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=0");
}
}
@@ -866,6 +877,13 @@ c_cpp_builtins (cpp_reader *pfile)
define_language_independent_builtin_macros (pfile);
+ /* encoding definitions used by users and libraries */
+ builtin_define_with_value ("__GNUC_EXECUTION_CHARSET_NAME",
+ cpp_get_narrow_charset_name (pfile), 1);
+ builtin_define_with_value ("__GNUC_WIDE_EXECUTION_CHARSET_NAME",
+ cpp_get_wide_charset_name (pfile), 1);
+
+
if (c_dialect_cxx ())
{
int major;
@@ -1005,6 +1023,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_constexpr_dynamic_alloc=201907L");
cpp_define (pfile, "__cpp_impl_three_way_comparison=201907L");
cpp_define (pfile, "__cpp_aggregate_paren_init=201902L");
+ cpp_define (pfile, "__cpp_using_enum=201907L");
}
if (flag_concepts)
{
@@ -1013,6 +1032,10 @@ c_cpp_builtins (cpp_reader *pfile)
else
cpp_define (pfile, "__cpp_concepts=201507L");
}
+ if (flag_modules)
+ /* The std-defined value is 201907L, but I don't think we can
+ claim victory yet. 201810 is the p1103 date. */
+ cpp_define (pfile, "__cpp_modules=201810L");
if (flag_coroutines)
cpp_define (pfile, "__cpp_impl_coroutine=201902L"); /* n4861, DIS */
if (flag_tm)
@@ -1033,6 +1056,12 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_threadsafe_static_init=200806L");
if (flag_char8_t)
cpp_define (pfile, "__cpp_char8_t=201811L");
+#ifndef THREAD_MODEL_SPEC
+ /* Targets that define THREAD_MODEL_SPEC need to define
+ __STDCPP_THREADS__ in their config/XXX/XXX-c.c themselves. */
+ if (cxx_dialect >= cxx11 && strcmp (thread_model, "single") != 0)
+ cpp_define (pfile, "__STDCPP_THREADS__=1");
+#endif
}
/* Note that we define this for C as well, so that we know if
__attribute__((cleanup)) will interface with EH. */
diff --git a/gcc/c-family/c-indentation.c b/gcc/c-family/c-indentation.c
index 8b88a8a..836a524 100644
--- a/gcc/c-family/c-indentation.c
+++ b/gcc/c-family/c-indentation.c
@@ -45,36 +45,11 @@ next_tab_stop (unsigned int vis_column, unsigned int tab_width)
on the line (up to or before EXPLOC). */
static bool
-get_visual_column (expanded_location exploc, location_t loc,
+get_visual_column (expanded_location exploc,
unsigned int *out,
unsigned int *first_nws,
unsigned int tab_width)
{
- /* PR c++/68819: if the column number is zero, we presumably
- had a location_t > LINE_MAP_MAX_LOCATION_WITH_COLS, and so
- we have no column information.
- Act as if no conversion was possible, triggering the
- error-handling path in the caller. */
- if (!exploc.column)
- {
- static bool issued_note = false;
- if (!issued_note)
- {
- /* Notify the user the first time this happens. */
- issued_note = true;
- inform (loc,
- "%<-Wmisleading-indentation%> is disabled from this point"
- " onwards, since column-tracking was disabled due to"
- " the size of the code/headers");
- if (!flag_large_source_files)
- inform (loc,
- "adding %<-flarge-source-files%> will allow for more"
- " column-tracking support, at the expense of compilation"
- " time and memory");
- }
- return false;
- }
-
char_span line = location_get_source_line (exploc.file, exploc.line);
if (!line)
return false;
@@ -325,14 +300,37 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
NULL);
}
- /* Give up if the loci are not all distinct. */
- if (guard_loc == body_loc || body_loc == next_stmt_loc)
- return false;
-
expanded_location body_exploc = expand_location (body_loc);
expanded_location next_stmt_exploc = expand_location (next_stmt_loc);
expanded_location guard_exploc = expand_location (guard_loc);
+ /* PR c++/68819: if the column number is zero, we presumably
+ had a location_t > LINE_MAP_MAX_LOCATION_WITH_COLS, and so
+ we have no column information. */
+ if (!guard_exploc.column || !body_exploc.column || !next_stmt_exploc.column)
+ {
+ static bool issued_note = false;
+ if (!issued_note)
+ {
+ /* Notify the user the first time this happens. */
+ issued_note = true;
+ inform (guard_loc,
+ "%<-Wmisleading-indentation%> is disabled from this point"
+ " onwards, since column-tracking was disabled due to"
+ " the size of the code/headers");
+ if (!flag_large_source_files)
+ inform (guard_loc,
+ "adding %<-flarge-source-files%> will allow for more"
+ " column-tracking support, at the expense of compilation"
+ " time and memory");
+ }
+ return false;
+ }
+
+ /* Give up if the loci are not all distinct. */
+ if (guard_loc == body_loc || body_loc == next_stmt_loc)
+ return false;
+
const unsigned int tab_width = global_dc->tabstop;
/* They must be in the same file. */
@@ -378,7 +376,7 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
gcc_assert (guard_exploc.line == next_stmt_exploc.line);
unsigned int guard_vis_column;
unsigned int guard_line_first_nws;
- if (!get_visual_column (guard_exploc, guard_loc,
+ if (!get_visual_column (guard_exploc,
&guard_vis_column,
&guard_line_first_nws, tab_width))
return false;
@@ -438,15 +436,15 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
the case for input files containing #line directives, and these
are often for autogenerated sources (e.g. from .md files), where
it's not clear that it's meaningful to look at indentation. */
- if (!get_visual_column (next_stmt_exploc, next_stmt_loc,
+ if (!get_visual_column (next_stmt_exploc,
&next_stmt_vis_column,
&next_stmt_line_first_nws, tab_width))
return false;
- if (!get_visual_column (body_exploc, body_loc,
+ if (!get_visual_column (body_exploc,
&body_vis_column,
&body_line_first_nws, tab_width))
return false;
- if (!get_visual_column (guard_exploc, guard_loc,
+ if (!get_visual_column (guard_exploc,
&guard_vis_column,
&guard_line_first_nws, tab_width))
return false;
@@ -701,7 +699,7 @@ assert_get_visual_column_succeeds (const location &loc,
exploc.sysp = false;
unsigned int actual_visual_column;
unsigned int actual_first_nws;
- bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
+ bool result = get_visual_column (exploc,
&actual_visual_column,
&actual_first_nws, tab_width);
ASSERT_TRUE_AT (loc, result);
@@ -739,7 +737,7 @@ assert_get_visual_column_fails (const location &loc,
exploc.sysp = false;
unsigned int actual_visual_column;
unsigned int actual_first_nws;
- bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
+ bool result = get_visual_column (exploc,
&actual_visual_column,
&actual_first_nws, tab_width);
ASSERT_FALSE_AT (loc, result);
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index b1cef23..c8d33d0 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-pragma.h"
#include "debug.h"
#include "file-prefix-map.h" /* remap_macro_filename() */
-
+#include "langhooks.h"
#include "attribs.h"
/* We may keep statistics about how long which files took to compile. */
@@ -274,9 +274,11 @@ cb_define (cpp_reader *pfile, location_t loc, cpp_hashnode *node)
/* #undef callback for DWARF and DWARF2 debug info. */
static void
-cb_undef (cpp_reader * ARG_UNUSED (pfile), location_t loc,
- cpp_hashnode *node)
+cb_undef (cpp_reader *pfile, location_t loc, cpp_hashnode *node)
{
+ if (lang_hooks.preprocess_undef)
+ lang_hooks.preprocess_undef (pfile, loc, node);
+
const struct line_map *map = linemap_lookup (line_table, loc);
(*debug_hooks->undef) (SOURCE_LINE (linemap_check_ordinary (map), loc),
(const char *) NODE_NAME (node));
@@ -300,7 +302,7 @@ get_token_no_padding (cpp_reader *pfile)
/* Callback for has_attribute. */
int
-c_common_has_attribute (cpp_reader *pfile)
+c_common_has_attribute (cpp_reader *pfile, bool std_syntax)
{
int result = 0;
tree attr_name = NULL_TREE;
@@ -319,35 +321,37 @@ c_common_has_attribute (cpp_reader *pfile)
attr_name = get_identifier ((const char *)
cpp_token_as_text (pfile, token));
attr_name = canonicalize_attr_name (attr_name);
- if (c_dialect_cxx ())
+ bool have_scope = false;
+ int idx = 0;
+ const cpp_token *nxt_token;
+ do
+ nxt_token = cpp_peek_token (pfile, idx++);
+ while (nxt_token->type == CPP_PADDING);
+ if (nxt_token->type == CPP_SCOPE)
{
- int idx = 0;
- const cpp_token *nxt_token;
- do
- nxt_token = cpp_peek_token (pfile, idx++);
- while (nxt_token->type == CPP_PADDING);
- if (nxt_token->type == CPP_SCOPE)
+ have_scope = true;
+ get_token_no_padding (pfile); // Eat scope.
+ nxt_token = get_token_no_padding (pfile);
+ if (nxt_token->type == CPP_NAME)
{
- get_token_no_padding (pfile); // Eat scope.
- nxt_token = get_token_no_padding (pfile);
- if (nxt_token->type == CPP_NAME)
- {
- tree attr_ns = attr_name;
- tree attr_id
- = get_identifier ((const char *)
- cpp_token_as_text (pfile, nxt_token));
- attr_name = build_tree_list (attr_ns, attr_id);
- }
- else
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "attribute identifier required after scope");
- attr_name = NULL_TREE;
- }
+ tree attr_ns = attr_name;
+ tree attr_id
+ = get_identifier ((const char *)
+ cpp_token_as_text (pfile, nxt_token));
+ attr_name = build_tree_list (attr_ns, attr_id);
}
else
{
- /* Some standard attributes need special handling. */
+ cpp_error (pfile, CPP_DL_ERROR,
+ "attribute identifier required after scope");
+ attr_name = NULL_TREE;
+ }
+ }
+ else
+ {
+ /* Some standard attributes need special handling. */
+ if (c_dialect_cxx ())
+ {
if (is_attribute_p ("noreturn", attr_name))
result = 200809;
else if (is_attribute_p ("deprecated", attr_name))
@@ -361,11 +365,20 @@ c_common_has_attribute (cpp_reader *pfile)
result = 201803;
else if (is_attribute_p ("nodiscard", attr_name))
result = 201907;
- if (result)
- attr_name = NULL_TREE;
}
+ else
+ {
+ if (is_attribute_p ("deprecated", attr_name)
+ || is_attribute_p ("maybe_unused", attr_name)
+ || is_attribute_p ("fallthrough", attr_name))
+ result = 201904;
+ else if (is_attribute_p ("nodiscard", attr_name))
+ result = 202003;
+ }
+ if (result)
+ attr_name = NULL_TREE;
}
- if (attr_name)
+ if (attr_name && (have_scope || !std_syntax))
{
init_attributes ();
const struct attribute_spec *attr = lookup_attribute_spec (attr_name);
@@ -550,7 +563,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
returning a token of type CPP_AT_NAME and rid
code RID_CLASS (not RID_AT_CLASS). The language
parser needs to convert that to RID_AT_CLASS.
+ However, we've now spliced the '@' together with the
+ keyword that follows; Adjust the location so that we
+ get a source range covering the composite.
*/
+ *loc = make_location (atloc, atloc, newloc);
break;
}
/* FALLTHROUGH */
@@ -650,8 +667,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
*value = build_int_cst (integer_type_node, tok->val.pragma);
break;
- /* These tokens should not be visible outside cpplib. */
case CPP_HEADER_NAME:
+ *value = build_string (tok->val.str.len, (const char *)tok->val.str.text);
+ break;
+
+ /* This token should not be visible outside cpplib. */
case CPP_MACRO_ARG:
gcc_unreachable ();
diff --git a/gcc/c-family/c-objc.h b/gcc/c-family/c-objc.h
index 6025283..4b50260 100644
--- a/gcc/c-family/c-objc.h
+++ b/gcc/c-family/c-objc.h
@@ -28,6 +28,74 @@ enum GTY(()) objc_ivar_visibility_kind {
OBJC_IVAR_VIS_PACKAGE = 3
};
+/* ObjC property attribute kinds.
+ These have two fields; a unique value (that identifies which attribute)
+ and a group key that indicates membership of an exclusion group.
+ Only one member may be present from an exclusion group in a given attribute
+ list.
+ getters and setters have additional rules, since they are excluded from
+ non-overlapping group sets. */
+
+enum objc_property_attribute_group
+{
+ OBJC_PROPATTR_GROUP_UNKNOWN = 0,
+ OBJC_PROPATTR_GROUP_GETTER,
+ OBJC_PROPATTR_GROUP_SETTER,
+ OBJC_PROPATTR_GROUP_READWRITE,
+ OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPATTR_GROUP_ATOMIC,
+ OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPATTR_GROUP_CLASS,
+ OBJC_PROPATTR_GROUP_MAX
+};
+
+enum objc_property_attribute_kind
+{
+ OBJC_PROPERTY_ATTR_UNKNOWN = 0|OBJC_PROPATTR_GROUP_UNKNOWN,
+ OBJC_PROPERTY_ATTR_GETTER = ( 1 << 8)|OBJC_PROPATTR_GROUP_GETTER,
+ OBJC_PROPERTY_ATTR_SETTER = ( 2 << 8)|OBJC_PROPATTR_GROUP_SETTER,
+ OBJC_PROPERTY_ATTR_READONLY = ( 3 << 8)|OBJC_PROPATTR_GROUP_READWRITE,
+ OBJC_PROPERTY_ATTR_READWRITE = ( 4 << 8)|OBJC_PROPATTR_GROUP_READWRITE,
+ OBJC_PROPERTY_ATTR_ASSIGN = ( 5 << 8)|OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPERTY_ATTR_RETAIN = ( 6 << 8)|OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPERTY_ATTR_COPY = ( 7 << 8)|OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPERTY_ATTR_ATOMIC = ( 8 << 8)|OBJC_PROPATTR_GROUP_ATOMIC,
+ OBJC_PROPERTY_ATTR_NONATOMIC = ( 9 << 8)|OBJC_PROPATTR_GROUP_ATOMIC,
+ OBJC_PROPERTY_ATTR_NULL_UNSPECIFIED = (12 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_NULLABLE = (13 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_NONNULL = (14 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_NULL_RESETTABLE = (15 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_CLASS = (16 << 8)|OBJC_PROPATTR_GROUP_CLASS,
+ OBJC_PROPERTY_ATTR_MAX = (255 << 8|OBJC_PROPATTR_GROUP_MAX)
+};
+
+#define OBJC_PROPATTR_GROUP_MASK 0x0f
+
+/* To contain parsed, but unverified, information about a single property
+ attribute. */
+struct property_attribute_info
+{
+ property_attribute_info () = default;
+ property_attribute_info (tree name, location_t loc,
+ enum objc_property_attribute_kind k)
+ : name (name), ident (NULL_TREE), prop_loc (loc), prop_kind (k),
+ parse_error (false) {}
+
+ enum objc_property_attribute_group group ()
+ {
+ return (enum objc_property_attribute_group)
+ ((unsigned)prop_kind & OBJC_PROPATTR_GROUP_MASK);
+ }
+
+ tree name; /* Name of the attribute. */
+ tree ident; /* For getter/setter cases, the method/selector name. */
+ location_t prop_loc; /* Extended location covering the parsed attr. */
+ enum objc_property_attribute_kind prop_kind : 16;
+ unsigned parse_error : 1; /* The C/C++ parser saw an error in this attr. */
+};
+
+extern enum objc_property_attribute_kind objc_prop_attr_kind_for_rid (enum rid);
+
/* Objective-C / Objective-C++ entry points. */
/* The following ObjC/ObjC++ functions are called by the C and/or C++
@@ -61,7 +129,7 @@ extern tree objc_get_protocol_qualified_type (tree, tree);
extern tree objc_get_class_reference (tree);
extern tree objc_get_class_ivars (tree);
extern bool objc_detect_field_duplicates (bool);
-extern void objc_start_class_interface (tree, tree, tree, tree);
+extern void objc_start_class_interface (tree, location_t, tree, tree, tree);
extern void objc_start_category_interface (tree, tree, tree, tree);
extern void objc_start_protocol (tree, tree, tree);
extern void objc_continue_interface (void);
@@ -90,8 +158,8 @@ extern tree objc_generate_write_barrier (tree, enum tree_code, tree);
extern void objc_set_method_opt (bool);
extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree);
extern bool objc_method_decl (enum tree_code);
-extern void objc_add_property_declaration (location_t, tree, bool, bool, bool,
- bool, bool, bool, tree, tree);
+extern void objc_add_property_declaration (location_t, tree,
+ vec<property_attribute_info *>&);
extern tree objc_maybe_build_component_ref (tree, tree);
extern tree objc_build_class_component_ref (tree, tree);
extern tree objc_maybe_build_modify_expr (tree, tree);
@@ -101,6 +169,7 @@ extern void objc_add_synthesize_declaration (location_t, tree);
extern void objc_add_dynamic_declaration (location_t, tree);
extern const char * objc_maybe_printable_name (tree, int);
extern bool objc_is_property_ref (tree);
+extern bool objc_non_constant_expr_p (tree);
extern bool objc_string_ref_type_p (tree);
extern void objc_check_format_arg (tree, tree);
extern void objc_finish_function (void);
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index d7cff0f..8457211 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "gimplify.h"
#include "langhooks.h"
+#include "bitmap.h"
/* Complete a #pragma oacc wait construct. LOC is the location of
@@ -1575,6 +1576,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
tree next, c;
enum c_omp_clause_split s;
int i;
+ bool has_dup_allocate = false;
for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
cclauses[i] = NULL;
@@ -2198,6 +2200,71 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
else
s = C_OMP_CLAUSE_SPLIT_FOR;
break;
+ /* Allocate clause is allowed on target, teams, distribute, parallel,
+ for, sections and taskloop. Distribute it to all. */
+ case OMP_CLAUSE_ALLOCATE:
+ s = C_OMP_CLAUSE_SPLIT_COUNT;
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ {
+ switch (i)
+ {
+ case C_OMP_CLAUSE_SPLIT_TARGET:
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_MAP)) == 0)
+ continue;
+ break;
+ case C_OMP_CLAUSE_SPLIT_TEAMS:
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
+ continue;
+ break;
+ case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
+ continue;
+ break;
+ case C_OMP_CLAUSE_SPLIT_PARALLEL:
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
+ continue;
+ break;
+ case C_OMP_CLAUSE_SPLIT_FOR:
+ STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
+ == C_OMP_CLAUSE_SPLIT_FOR
+ && (C_OMP_CLAUSE_SPLIT_TASKLOOP
+ == C_OMP_CLAUSE_SPLIT_FOR)
+ && (C_OMP_CLAUSE_SPLIT_LOOP
+ == C_OMP_CLAUSE_SPLIT_FOR));
+ if (code == OMP_SECTIONS)
+ break;
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
+ break;
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
+ break;
+ continue;
+ case C_OMP_CLAUSE_SPLIT_SIMD:
+ continue;
+ default:
+ gcc_unreachable ();
+ }
+ if (s != C_OMP_CLAUSE_SPLIT_COUNT)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_ALLOCATE);
+ OMP_CLAUSE_DECL (c)
+ = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+ = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[s];
+ cclauses[s] = c;
+ has_dup_allocate = true;
+ }
+ s = (enum c_omp_clause_split) i;
+ }
+ gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
+ break;
default:
gcc_unreachable ();
}
@@ -2205,6 +2272,131 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
cclauses[s] = clauses;
}
+ if (has_dup_allocate)
+ {
+ bool need_prune = false;
+ bitmap_obstack_initialize (NULL);
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
+ if (cclauses[i])
+ {
+ bitmap_head allocate_head;
+ bitmap_initialize (&allocate_head, &bitmap_default_obstack);
+ for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && DECL_P (OMP_CLAUSE_DECL (c)))
+ bitmap_set_bit (&allocate_head,
+ DECL_UID (OMP_CLAUSE_DECL (c)));
+ for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
+ {
+ tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (DECL_P (t))
+ bitmap_clear_bit (&allocate_head, DECL_UID (t));
+ break;
+ }
+ else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
+ {
+ tree t;
+ for (t = OMP_CLAUSE_DECL (c);
+ TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
+ ;
+ if (DECL_P (t))
+ bitmap_clear_bit (&allocate_head, DECL_UID (t));
+ break;
+ }
+ /* FALLTHRU */
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_LINEAR:
+ if (DECL_P (OMP_CLAUSE_DECL (c)))
+ bitmap_clear_bit (&allocate_head,
+ DECL_UID (OMP_CLAUSE_DECL (c)));
+ break;
+ default:
+ break;
+ }
+ for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && DECL_P (OMP_CLAUSE_DECL (c))
+ && bitmap_bit_p (&allocate_head,
+ DECL_UID (OMP_CLAUSE_DECL (c))))
+ {
+ /* Mark allocate clauses which don't have corresponding
+ explicit data sharing clause. */
+ OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
+ need_prune = true;
+ }
+ }
+ bitmap_obstack_release (NULL);
+ if (need_prune)
+ {
+ /* At least one allocate clause has been marked. Walk all the
+ duplicated allocate clauses in sync. If it is marked in all
+ constituent constructs, diagnose it as invalid and remove
+ them. Otherwise, remove all marked inner clauses inside
+ a construct that doesn't have them marked. Keep the outer
+ marked ones, because some clause duplication is done only
+ during gimplification. */
+ tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ if (cclauses[i] == NULL_TREE
+ || i == C_OMP_CLAUSE_SPLIT_SIMD
+ || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
+ p[i] = NULL;
+ else
+ p[i] = &cclauses[i];
+ do
+ {
+ int j = -1;
+ tree seen = NULL_TREE;
+ for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
+ if (p[i])
+ {
+ while (*p[i]
+ && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
+ p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
+ if (*p[i] == NULL_TREE)
+ {
+ i = C_OMP_CLAUSE_SPLIT_COUNT;
+ break;
+ }
+ if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
+ j = i;
+ seen = *p[i];
+ }
+ if (i == C_OMP_CLAUSE_SPLIT_COUNT)
+ break;
+ if (j == -1)
+ error_at (OMP_CLAUSE_LOCATION (seen),
+ "%qD specified in %<allocate%> clause but not in "
+ "an explicit privatization clause",
+ OMP_CLAUSE_DECL (seen));
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ if (p[i])
+ {
+ if (i > j)
+ /* Remove. */
+ *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
+ else
+ /* Keep. */
+ p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
+ }
+ }
+ while (1);
+ }
+ }
+
if (!flag_checking)
return;
@@ -2579,3 +2771,93 @@ c_omp_map_clause_name (tree clause, bool oacc)
}
return omp_clause_code_name[OMP_CLAUSE_CODE (clause)];
}
+
+/* Used to merge map clause information in c_omp_adjust_map_clauses. */
+struct map_clause
+{
+ tree clause;
+ bool firstprivate_ptr_p;
+ bool decl_mapped;
+ bool omp_declare_target;
+ map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
+ decl_mapped (false), omp_declare_target (false) { }
+};
+
+/* Adjust map clauses after normal clause parsing, mainly to turn specific
+ base-pointer map cases into attach/detach and mark them addressable. */
+void
+c_omp_adjust_map_clauses (tree clauses, bool is_target)
+{
+ if (!is_target)
+ {
+ /* If this is not a target construct, just turn firstprivate pointers
+ into attach/detach, the runtime will check and do the rest. */
+
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
+ && DECL_P (OMP_CLAUSE_DECL (c))
+ && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
+ {
+ tree ptr = OMP_CLAUSE_DECL (c);
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH_DETACH);
+ c_common_mark_addressable_vec (ptr);
+ }
+ return;
+ }
+
+ hash_map<tree, map_clause> maps;
+
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && DECL_P (OMP_CLAUSE_DECL (c)))
+ {
+ /* If this is for a target construct, the firstprivate pointer
+ is changed to attach/detach if either is true:
+ (1) the base-pointer is mapped in this same construct, or
+ (2) the base-pointer is a variable place on the device by
+ "declare target" directives.
+
+ Here we iterate through all map clauses collecting these cases,
+ and merge them with a hash_map to process below. */
+
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
+ && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
+ {
+ tree ptr = OMP_CLAUSE_DECL (c);
+ map_clause &mc = maps.get_or_insert (ptr);
+ if (mc.clause == NULL_TREE)
+ mc.clause = c;
+ mc.firstprivate_ptr_p = true;
+
+ if (is_global_var (ptr)
+ && lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (ptr)))
+ mc.omp_declare_target = true;
+ }
+ else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
+ {
+ map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
+ mc.decl_mapped = true;
+ }
+ }
+
+ for (hash_map<tree, map_clause>::iterator i = maps.begin ();
+ i != maps.end (); ++i)
+ {
+ map_clause &mc = (*i).second;
+
+ if (mc.firstprivate_ptr_p
+ && (mc.decl_mapped || mc.omp_declare_target))
+ {
+ OMP_CLAUSE_SET_MAP_KIND (mc.clause, GOMP_MAP_ATTACH_DETACH);
+ c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
+ }
+ }
+}
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 38d3384..59cabd1 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -234,6 +234,7 @@ c_common_init_options (unsigned int decoded_options_count,
cpp_opts = cpp_get_options (parse_in);
cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
cpp_opts->objc = c_dialect_objc ();
+ cpp_opts->deps.modules = true;
/* Reset to avoid warnings on internal definitions. We set it just
before passing on command-line options to cpplib. */
@@ -367,6 +368,18 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
cpp_opts->deps.phony_targets = true;
break;
+ case OPT_Mmodules:
+ /* Do not set deps_seen, so the user can unconditionally turn
+ this on or off. */
+ cpp_opts->deps.modules = true;
+ break;
+
+ case OPT_Mno_modules:
+ /* Do not set deps_seen, so the user can unconditionally turn
+ this on or off. */
+ cpp_opts->deps.modules = false;
+ break;
+
case OPT_MQ:
case OPT_MT:
deps_seen = true;
@@ -752,8 +765,6 @@ default_handle_c_option (size_t code ATTRIBUTE_UNUSED,
bool
c_common_post_options (const char **pfilename)
{
- struct cpp_callbacks *cb;
-
/* Canonicalize the input and output filenames. */
if (in_fnames == NULL)
{
@@ -925,6 +936,16 @@ c_common_post_options (const char **pfilename)
SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_volatile,
cxx_dialect >= cxx20 && warn_deprecated);
+ /* -Wdeprecated-enum-enum-conversion is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_enum_enum_conv,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
+ /* -Wdeprecated-enum-float-conversion is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_enum_float_conv,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
/* Declone C++ 'structors if -Os. */
if (flag_declone_ctor_dtor == -1)
flag_declone_ctor_dtor = optimize_size;
@@ -937,7 +958,7 @@ c_common_post_options (const char **pfilename)
/* Change flag_abi_version to be the actual current ABI level, for the
benefit of c_cpp_builtins, and to make comparison simpler. */
- const int latest_abi_version = 14;
+ const int latest_abi_version = 15;
/* Generate compatibility aliases for ABI v11 (7.1) by default. */
const int abi_compat_default = 11;
@@ -1095,9 +1116,11 @@ c_common_post_options (const char **pfilename)
input_location = UNKNOWN_LOCATION;
}
- cb = cpp_get_callbacks (parse_in);
+ struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
cb->file_change = cb_file_change;
cb->dir_change = cb_dir_change;
+ if (lang_hooks.preprocess_options)
+ lang_hooks.preprocess_options (parse_in);
cpp_post_options (parse_in);
init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in));
@@ -1540,7 +1563,13 @@ push_command_line_include (void)
cpp_opts->warn_unused_macros = cpp_warn_unused_macros;
/* Restore the line map back to the main file. */
if (!cpp_opts->preprocessed)
- cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+ {
+ cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+ if (lang_hooks.preprocess_main_file)
+ /* We're starting the main file. Inform the FE of that. */
+ lang_hooks.preprocess_main_file
+ (parse_in, line_table, LINEMAPS_LAST_ORDINARY_MAP (line_table));
+ }
/* Set this here so the client can change the option if it wishes,
and after stacking the main file so we don't trace the main file. */
@@ -1550,14 +1579,19 @@ push_command_line_include (void)
/* File change callback. Has to handle -include files. */
static void
-cb_file_change (cpp_reader * ARG_UNUSED (pfile),
- const line_map_ordinary *new_map)
+cb_file_change (cpp_reader *reader, const line_map_ordinary *new_map)
{
if (flag_preprocess_only)
pp_file_change (new_map);
else
fe_file_change (new_map);
+ if (new_map && cpp_opts->preprocessed
+ && lang_hooks.preprocess_main_file && MAIN_FILE_P (new_map)
+ && ORDINARY_MAP_STARTING_LINE_NUMBER (new_map))
+ /* We're starting the main file. Inform the FE of that. */
+ lang_hooks.preprocess_main_file (reader, line_table, new_map);
+
if (new_map
&& (new_map->reason == LC_ENTER || new_map->reason == LC_RENAME))
{
diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c
index a2292f4..fdeb860 100644
--- a/gcc/c-family/c-pch.c
+++ b/gcc/c-family/c-pch.c
@@ -206,13 +206,16 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
/* Perform a quick test of whether this is a valid
precompiled header for the current language. */
+ /* C++ modules and PCH don't play together. */
+ if (flag_modules)
+ return 2;
+
sizeread = read (fd, ident, IDENT_LENGTH + 16);
if (sizeread == -1)
fatal_error (input_location, "cannot read %s: %m", name);
else if (sizeread != IDENT_LENGTH + 16)
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING, "%s: too short to be a PCH file",
+ cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: too short to be a PCH file",
name);
return 2;
}
@@ -220,27 +223,22 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
pch_ident = get_ident();
if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- {
- if (memcmp (ident, pch_ident, 5) == 0)
- /* It's a PCH, for the right language, but has the wrong version.
- */
- cpp_error (pfile, CPP_DL_WARNING,
+ if (memcmp (ident, pch_ident, 5) == 0)
+ /* It's a PCH, for the right language, but has the wrong version. */
+ cpp_warning (pfile, CPP_W_INVALID_PCH,
"%s: not compatible with this GCC version", name);
- else if (memcmp (ident, pch_ident, 4) == 0)
- /* It's a PCH for the wrong language. */
- cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
+ else if (memcmp (ident, pch_ident, 4) == 0)
+ /* It's a PCH for the wrong language. */
+ cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: not for %s", name,
lang_hooks.name);
- else
- /* Not any kind of PCH. */
- cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
- }
+ else
+ /* Not any kind of PCH. */
+ cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: not a PCH file", name);
return 2;
}
if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0)
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_INVALID_PCH,
"%s: created by a different GCC executable", name);
return 2;
}
@@ -257,8 +255,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
if (v.debug_info_type != write_symbols
&& write_symbols != NO_DEBUG)
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_INVALID_PCH,
"%s: created with -g%s, but used with -g%s", name,
debug_type_names[v.debug_info_type],
debug_type_names[write_symbols]);
@@ -271,8 +268,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
for (i = 0; i < MATCH_SIZE; i++)
if (*pch_matching[i].flag_var != v.match[i])
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_INVALID_PCH,
"%s: settings for %s do not match", name,
pch_matching[i].flag_name);
return 2;
@@ -287,8 +283,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
check one function. */
if (v.pch_init != &pch_init)
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_INVALID_PCH,
"%s: had text segment at different address", name);
return 2;
}
@@ -305,8 +300,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
free (this_file_data);
if (msg != NULL)
{
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
+ cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: %s", name, msg);
return 2;
}
}
diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c
index 44c6f30..e3e0e59 100644
--- a/gcc/c-family/c-ppoutput.c
+++ b/gcc/c-family/c-ppoutput.c
@@ -21,6 +21,7 @@
#include "coretypes.h"
#include "c-common.h" /* For flags. */
#include "../libcpp/internal.h"
+#include "langhooks.h"
#include "c-pragma.h" /* For parse_in. */
#include "file-prefix-map.h" /* remap_macro_filename() */
@@ -301,125 +302,48 @@ token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
/* Writes out the preprocessed file, handling spacing and paste
avoidance issues. */
+
static void
scan_translation_unit (cpp_reader *pfile)
{
- bool avoid_paste = false;
- bool do_line_adjustments
- = cpp_get_options (parse_in)->lang != CLK_ASM
- && !flag_no_line_commands;
- bool in_pragma = false;
- bool line_marker_emitted = false;
+ token_streamer streamer (pfile);
+ uintptr_t filter = 0;
+
+ if (lang_hooks.preprocess_token)
+ filter = lang_hooks.preprocess_token (pfile, NULL, filter);
print.source = NULL;
for (;;)
{
- location_t loc;
- const cpp_token *token = cpp_get_token_with_location (pfile, &loc);
+ location_t spelling_loc;
+ const cpp_token *token
+ = cpp_get_token_with_location (pfile, &spelling_loc);
- if (token->type == CPP_PADDING)
+ streamer.stream (pfile, token, spelling_loc);
+ if (filter)
{
- avoid_paste = true;
- if (print.source == NULL
- || (!(print.source->flags & PREV_WHITE)
- && token->val.source == NULL))
- print.source = token->val.source;
- continue;
+ unsigned flags = lang_hooks.preprocess_token (pfile, token, filter);
+ if (flags & lang_hooks::PT_begin_pragma)
+ streamer.begin_pragma ();
}
-
if (token->type == CPP_EOF)
break;
+ }
- /* Subtle logic to output a space if and only if necessary. */
- if (avoid_paste)
- {
- int src_line = LOCATION_LINE (loc);
-
- if (print.source == NULL)
- print.source = token;
-
- if (src_line != print.src_line
- && do_line_adjustments
- && !in_pragma)
- {
- line_marker_emitted = do_line_change (pfile, token, loc, false);
- putc (' ', print.outf);
- print.printed = true;
- }
- else if (print.source->flags & PREV_WHITE
- || (print.prev
- && cpp_avoid_paste (pfile, print.prev, token))
- || (print.prev == NULL && token->type == CPP_HASH))
- {
- putc (' ', print.outf);
- print.printed = true;
- }
- }
- else if (token->flags & PREV_WHITE)
- {
- int src_line = LOCATION_LINE (loc);
-
- if (src_line != print.src_line
- && do_line_adjustments
- && !in_pragma)
- line_marker_emitted = do_line_change (pfile, token, loc, false);
- putc (' ', print.outf);
- print.printed = true;
- }
+ if (filter)
+ lang_hooks.preprocess_token (pfile, NULL, filter);
+}
- avoid_paste = false;
- print.source = NULL;
- print.prev = token;
- if (token->type == CPP_PRAGMA)
- {
- const char *space;
- const char *name;
-
- line_marker_emitted = maybe_print_line (token->src_loc);
- fputs ("#pragma ", print.outf);
- c_pp_lookup_pragma (token->val.pragma, &space, &name);
- if (space)
- fprintf (print.outf, "%s %s", space, name);
- else
- fprintf (print.outf, "%s", name);
- print.printed = true;
- in_pragma = true;
- }
- else if (token->type == CPP_PRAGMA_EOL)
- {
- maybe_print_line (token->src_loc);
- in_pragma = false;
- }
- else
- {
- if (cpp_get_options (parse_in)->debug)
- linemap_dump_location (line_table, token->src_loc, print.outf);
-
- if (do_line_adjustments
- && !in_pragma
- && !line_marker_emitted
- && print.prev_was_system_token != !!in_system_header_at (loc)
- && !is_location_from_builtin_token (loc))
- /* The system-ness of this token is different from the one
- of the previous token. Let's emit a line change to
- mark the new system-ness before we emit the token. */
- {
- do_line_change (pfile, token, loc, false);
- print.prev_was_system_token = !!in_system_header_at (loc);
- }
- cpp_output_token (token, print.outf);
- line_marker_emitted = false;
- print.printed = true;
- }
+class do_streamer : public token_streamer
+{
+ public:
+ uintptr_t filter;
- /* CPP_COMMENT tokens and raw-string literal tokens can
- have embedded new-line characters. Rather than enumerating
- all the possible token types just check if token uses
- val.str union member. */
- if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
- account_for_newlines (token->val.str.text, token->val.str.len);
+ do_streamer (cpp_reader *pfile, uintptr_t filter)
+ :token_streamer (pfile), filter (filter)
+ {
}
-}
+};
static void
directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
@@ -427,7 +351,7 @@ directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
va_list args;
va_start (args, data_);
- token_streamer *streamer = reinterpret_cast <token_streamer *> (data_);
+ do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
switch (task)
{
default:
@@ -452,6 +376,13 @@ directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
const cpp_token *token = va_arg (args, const cpp_token *);
location_t spelling_loc = va_arg (args, location_t);
streamer->stream (pfile, token, spelling_loc);
+ if (streamer->filter)
+ {
+ unsigned flags = lang_hooks.preprocess_token
+ (pfile, token, streamer->filter);
+ if (flags & lang_hooks::PT_begin_pragma)
+ streamer->begin_pragma ();
+ }
}
break;
}
@@ -464,8 +395,13 @@ directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
static void
scan_translation_unit_directives_only (cpp_reader *pfile)
{
- token_streamer streamer (pfile);
+ uintptr_t filter = 0;
+ if (lang_hooks.preprocess_token)
+ filter = lang_hooks.preprocess_token (pfile, NULL, filter);
+ do_streamer streamer (pfile, filter);
cpp_directive_only_process (pfile, &streamer, directives_only_cb);
+ if (streamer.filter)
+ lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
}
/* Adjust print.src_line for newlines embedded in output. */
@@ -564,15 +500,16 @@ print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
unsigned char *to_file_quoted =
(unsigned char *) alloca (to_file_len * 4 + 1);
- print.src_line = LOCATION_LINE (src_loc);
- print.src_file = file_path;
-
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
unsigned char *p = cpp_quote_string (to_file_quoted,
(const unsigned char *) file_path,
to_file_len);
*p = '\0';
+
+ print.src_line = LOCATION_LINE (src_loc);
+ print.src_file = file_path;
+
fprintf (stream, "# %u \"%s\"%s",
print.src_line, to_file_quoted, special_flags);
@@ -678,9 +615,10 @@ cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
}
static void
-cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
- cpp_hashnode *node)
+cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
{
+ if (lang_hooks.preprocess_undef)
+ lang_hooks.preprocess_undef (pfile, line, node);
maybe_print_line (line);
fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
print.src_line++;
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index dc52ee8..5fd4360 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -809,16 +809,15 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
unsigned int option_index = find_opt (option_string + 1, lang_mask);
if (option_index == OPT_SPECIAL_unknown)
{
- option_proposer op;
- const char *hint = op.suggest_option (option_string + 1);
- if (hint)
- warning_at (loc, OPT_Wpragmas,
- "unknown option after %<#pragma GCC diagnostic%> kind;"
- " did you mean %<-%s%>?", hint);
- else
- warning_at (loc, OPT_Wpragmas,
- "unknown option after %<#pragma GCC diagnostic%> kind");
-
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wpragmas,
+ "unknown option after %<#pragma GCC diagnostic%> kind"))
+ {
+ option_proposer op;
+ const char *hint = op.suggest_option (option_string + 1);
+ if (hint)
+ inform (loc, "did you mean %<-%s%>?", hint);
+ }
return;
}
else if (!(cl_options[option_index].flags & CL_WARNING))
@@ -1310,6 +1309,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
{ "wait", PRAGMA_OACC_WAIT }
};
static const struct omp_pragma_def omp_pragmas[] = {
+ { "allocate", PRAGMA_OMP_ALLOCATE },
{ "atomic", PRAGMA_OMP_ATOMIC },
{ "barrier", PRAGMA_OMP_BARRIER },
{ "cancel", PRAGMA_OMP_CANCEL },
@@ -1318,7 +1318,6 @@ static const struct omp_pragma_def omp_pragmas[] = {
{ "depobj", PRAGMA_OMP_DEPOBJ },
{ "end", PRAGMA_OMP_END_DECLARE_TARGET },
{ "flush", PRAGMA_OMP_FLUSH },
- { "master", PRAGMA_OMP_MASTER },
{ "requires", PRAGMA_OMP_REQUIRES },
{ "section", PRAGMA_OMP_SECTION },
{ "sections", PRAGMA_OMP_SECTIONS },
@@ -1334,6 +1333,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = {
{ "distribute", PRAGMA_OMP_DISTRIBUTE },
{ "for", PRAGMA_OMP_FOR },
{ "loop", PRAGMA_OMP_LOOP },
+ { "master", PRAGMA_OMP_MASTER },
{ "ordered", PRAGMA_OMP_ORDERED },
{ "parallel", PRAGMA_OMP_PARALLEL },
{ "scan", PRAGMA_OMP_SCAN },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 3e9695fa..e0e4da6 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -42,6 +42,7 @@ enum pragma_kind {
PRAGMA_OACC_UPDATE,
PRAGMA_OACC_WAIT,
+ PRAGMA_OMP_ALLOCATE,
PRAGMA_OMP_ATOMIC,
PRAGMA_OMP_BARRIER,
PRAGMA_OMP_CANCEL,
@@ -86,6 +87,7 @@ enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_NONE = 0,
PRAGMA_OMP_CLAUSE_ALIGNED,
+ PRAGMA_OMP_CLAUSE_ALLOCATE,
PRAGMA_OMP_CLAUSE_BIND,
PRAGMA_OMP_CLAUSE_COLLAPSE,
PRAGMA_OMP_CLAUSE_COPYIN,
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 8953e3b..3027703 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -342,6 +342,7 @@ c_pretty_printer::simple_type_specifier (tree t)
break;
case VOID_TYPE:
+ case OPAQUE_TYPE:
case BOOLEAN_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
@@ -662,6 +663,7 @@ c_pretty_printer::direct_abstract_declarator (tree t)
case IDENTIFIER_NODE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case BOOLEAN_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 68b093e..91abafe 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -585,7 +585,7 @@ warn_logical_not_parentheses (location_t location, enum tree_code code,
(potential) location of the expression. */
bool
-warn_if_unused_value (const_tree exp, location_t locus)
+warn_if_unused_value (const_tree exp, location_t locus, bool quiet)
{
restart:
if (TREE_USED (exp) || TREE_NO_WARNING (exp))
@@ -633,7 +633,7 @@ warn_if_unused_value (const_tree exp, location_t locus)
goto restart;
case COMPOUND_EXPR:
- if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus))
+ if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus, quiet))
return true;
/* Let people do `(foo (), 0)' without a warning. */
if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))
@@ -648,6 +648,13 @@ warn_if_unused_value (const_tree exp, location_t locus)
return false;
goto warn;
+ case COMPLEX_EXPR:
+ /* Warn only if both operands are unused. */
+ if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus, true)
+ && warn_if_unused_value (TREE_OPERAND (exp, 1), locus, true))
+ goto warn;
+ return false;
+
case INDIRECT_REF:
/* Don't warn about automatic dereferencing of references, since
the user cannot control it. */
@@ -671,6 +678,8 @@ warn_if_unused_value (const_tree exp, location_t locus)
return false;
warn:
+ if (quiet)
+ return true;
return warning_at (locus, OPT_Wunused_value, "value computed is not used");
}
}
@@ -3365,18 +3374,21 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms)
for (tree curp = curparms, newp = newparms; curp;
curp = TREE_CHAIN (curp), newp = TREE_CHAIN (newp), ++parmpos)
{
+ if (!newp)
+ /* Bail on invalid redeclarations with fewer arguments. */
+ return;
+
/* Only check pointers and C++ references. */
+ tree curptype = TREE_TYPE (curp);
tree newptype = TREE_TYPE (newp);
- if (!POINTER_TYPE_P (newptype))
+ if (!POINTER_TYPE_P (curptype) || !POINTER_TYPE_P (newptype))
continue;
- {
- /* Skip mismatches in __builtin_va_list that is commonly
- an array but that in declarations of built-ins decays
- to a pointer. */
- if (builtin && TREE_TYPE (newptype) == TREE_TYPE (va_list_type_node))
- continue;
- }
+ /* Skip mismatches in __builtin_va_list that is commonly
+ an array but that in declarations of built-ins decays
+ to a pointer. */
+ if (builtin && TREE_TYPE (newptype) == TREE_TYPE (va_list_type_node))
+ continue;
/* Access specs for the argument on the current (previous) and
new (to replace the current) declarations. Either may be null,
@@ -3419,7 +3431,6 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms)
if (origloc == UNKNOWN_LOCATION)
origloc = newloc;
- tree curptype = TREE_TYPE (curp);
const std::string newparmstr = newa->array_as_string (newptype);
const std::string curparmstr = cura->array_as_string (curptype);
if (new_vla_p && !cur_vla_p)
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 1009def..e0c322f 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -236,17 +236,25 @@ MMD
C ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
Like -MD but ignore system header files.
+Mmodules
+C++
+Generate C++ Module dependency information.
+
+Mno-modules
+C++
+; undocumented
+
MP
C ObjC C++ ObjC++
Generate phony targets for all headers.
MQ
C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
--MQ <target> Add a MAKE-quoted target.
+-MQ <target> Add a target that may require quoting.
MT
C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
--MT <target> Add an unquoted target.
+-MT <target> Add a target that does not require quoting.
P
C ObjC C++ ObjC++
@@ -256,6 +264,10 @@ U
C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
-U<macro> Undefine <macro>.
+WNSObject-attribute
+C ObjC C++ ObjC++ LTO Var(warn_nsobject_attribute) Warning Init(1)
+Warn if the NSObject attribute is applied to a non-typedef.
+
Wabi
C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
Warn about things that will change when compiling with an ABI-compliant compiler.
@@ -518,6 +530,15 @@ C++ ObjC++ Var(warn_deprecated_copy, 2) Warning
Mark implicitly-declared copy operations as deprecated if the class has a
user-provided copy operation or destructor.
+Wdeprecated-enum-enum-conversion
+C++ ObjC++ Var(warn_deprecated_enum_enum_conv) Warning
+Warn about deprecated arithmetic conversions on operands of enumeration types.
+
+Wdeprecated-enum-float-conversion
+C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning
+Warn about deprecated arithmetic conversions on operands where one is of enumeration
+type and the other is of a floating-point type.
+
Wdesignated-init
C ObjC Var(warn_designated_init) Init(1) Warning
Warn about positional initialization of structs requiring designated initializers.
@@ -559,7 +580,7 @@ C ObjC C++ ObjC++ Var(warn_enum_compare) Init(-1) Warning LangEnabledBy(C ObjC,W
Warn about comparison of different enum types.
Wenum-conversion
-C ObjC Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra)
+C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra)
Warn about implicit conversion of enum types.
Werror
@@ -570,6 +591,10 @@ Werror-implicit-function-declaration
C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration)
This switch is deprecated; use -Werror=implicit-function-declaration instead.
+Wexceptions
+C++ ObjC++ Var(warn_exceptions) Init(1)
+Warn when an exception handler is shadowed by another handler.
+
Wextra
C ObjC C++ ObjC++ Warning
; in common.opt
@@ -768,6 +793,16 @@ Wmisleading-indentation
C C++ Common Var(warn_misleading_indentation) Warning LangEnabledBy(C C++,Wall)
Warn when the indentation of the code does not reflect the block structure.
+Wmismatched-dealloc
+C ObjC C++ ObjC++ Var(warn_mismatched_alloc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for deallocation calls with arguments returned from mismatched allocation
+functions.
+
+Wmismatched-new-delete
+C++ ObjC++ Var(warn_mismatched_new_delete) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for mismatches between calls to operator new or delete and the corrsponding
+call to the allocation or deallocation function.
+
Wmismatched-tags
C++ ObjC++ Var(warn_mismatched_tags) Warning
Warn when a class is redeclared or referenced using a mismatched class-key.
@@ -985,6 +1020,11 @@ Enum(cpp_normalize_level) String(id) Value(normalized_identifier_C)
EnumValue
Enum(cpp_normalize_level) String(nfc) Value(normalized_C)
+Wobjc-root-class
+ObjC ObjC++ Var(warn_objc_root_class) Warning Init(1)
+Warn if a class interface has no superclass. Root classes may use an attribute
+to suppress this warning.
+
Wold-style-cast
C++ ObjC++ Var(warn_old_style_cast) Warning
Warn if a C-style cast is used in a program.
@@ -1265,6 +1305,10 @@ Wvarargs
C ObjC C++ ObjC++ Warning Var(warn_varargs) Init(1)
Warn about questionable usage of the macros used to retrieve variable arguments.
+Wvexing-parse
+C++ ObjC++ Warning Var(warn_vexing_parse) Init(1)
+Warn about the most vexing parse syntactic ambiguity.
+
Wvla
C ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning
Warn if a variable length array is used.
@@ -1603,7 +1647,7 @@ C++ ObjC++ Var(flag_no_gnu_keywords, 0)
Recognize GNU-defined keywords.
fgnu-runtime
-ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime,0) Init(NEXT_OBJC_RUNTIME)
+ObjC ObjC++ LTO RejectNegative Var(flag_next_runtime,0) Init(NEXT_OBJC_RUNTIME)
Generate code for GNU runtime environment.
fgnu89-inline
@@ -1647,7 +1691,7 @@ ffriend-injection
C++ ObjC++ WarnRemoved
fkeep-inline-dllexport
-C C++ ObjC ObjC++ Var(flag_keep_inline_dllexport) Init(1) Report Condition(TARGET_DLLIMPORT_DECL_ATTRIBUTES)
+C C++ ObjC ObjC++ Var(flag_keep_inline_dllexport) Init(1) Condition(TARGET_DLLIMPORT_DECL_ATTRIBUTES)
Don't emit dllexported inline functions unless needed.
flabels-ok
@@ -1657,6 +1701,57 @@ flax-vector-conversions
C ObjC C++ ObjC++ Var(flag_lax_vector_conversions)
Allow implicit conversions between vectors with differing numbers of subparts and/or differing element types.
+fmodules-ts
+C++ ObjC++ Var(flag_modules) Integer Init(0)
+Enable C++ modules-ts (experimental).
+
+fno-modules
+C++ ObjC++ Undocumented RejectNegative Var(flag_modules,0) Integer
+;; undocumented
+
+fmodule-header
+C++ ObjC RejectNegative Var(flag_header_unit,0) Integer
+Enable C++ header module (experimental).
+
+fmodule-header=
+C++ ObjC++ Joined RejectNegative Undocumented
+
+fmodule-implicit-inline
+C++ ObjC++ Var(flag_module_implicit_inline,0) Integer
+Member functions defined within their class are inline in module purview.
+
+fmodule-only
+C++ ObjC RejectNegative Var(flag_module_only) Integer
+Only emit Compiled Module Interface.
+
+fmodule-mapper=
+C++ ObjC++ Joined RejectNegative MissingArgError(missing mapper)
+Mapper for module to CMI files.
+
+fmodule-lazy
+C++ ObjC++ Var(flag_module_lazy) Init(1)
+Enable lazy module importing.
+
+fmodule-version-ignore
+C++ ObjC Var(flag_module_version_ignore) Integer
+; undocumented, Very dangerous, but occasionally useful
+
+Winvalid-imported-macros
+C++ ObjC++ Var(warn_imported_macros)
+Warn about macros that have conflicting header units definitions.
+
+flang-info-include-translate
+C++ Var(note_include_translate_yes)
+Note #include directives translated to import declarations.
+
+flang-info-include-translate-not
+C++ Var(note_include_translate_no)
+Note #include directives not translated to import declarations, and not known to be textual.
+
+flang-info-include-translate=
+C++ Joined RejectNegative MissingArgError(missing header name)
+Note a #include translation of a specific header.
+
fmax-include-depth=
C ObjC C++ ObjC++ Joined RejectNegative UInteger
fmax-include-depth=<number> Set the maximum depth of the nested #include.
@@ -1685,7 +1780,7 @@ C++ ObjC++ Var(flag_new_ttp)
Implement resolution of DR 150 for matching of template template arguments.
fnext-runtime
-ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime)
+ObjC ObjC++ LTO RejectNegative Var(flag_next_runtime)
Generate code for NeXT (Apple Mac OS X) runtime environment.
fnil-receivers
@@ -1726,7 +1821,7 @@ C++ ObjC++ Optimization Var(flag_nothrow_opt)
Treat a throw() exception specification as noexcept to improve code size.
fobjc-abi-version=
-ObjC ObjC++ LTO Joined Report RejectNegative UInteger Var(flag_objc_abi)
+ObjC ObjC++ LTO Joined RejectNegative UInteger Var(flag_objc_abi)
Specify which ABI to use for Objective-C family code and meta-data generation.
; Generate special '- .cxx_construct' and '- .cxx_destruct' methods
@@ -1770,6 +1865,19 @@ fopenacc-dim=
C ObjC C++ ObjC++ LTO Joined Var(flag_openacc_dims)
Specify default OpenACC compute dimensions.
+fopenacc-kernels=
+C ObjC C++ ObjC++ RejectNegative Joined Enum(openacc_kernels) Var(flag_openacc_kernels) Init(OPENACC_KERNELS_PARLOOPS)
+-fopenacc-kernels=[decompose|parloops] Specify mode of OpenACC 'kernels' constructs handling.
+
+Enum
+Name(openacc_kernels) Type(enum openacc_kernels)
+
+EnumValue
+Enum(openacc_kernels) String(decompose) Value(OPENACC_KERNELS_DECOMPOSE)
+
+EnumValue
+Enum(openacc_kernels) String(parloops) Value(OPENACC_KERNELS_PARLOOPS)
+
fopenmp
C ObjC C++ ObjC++ LTO Var(flag_openmp)
Enable OpenMP (implies -frecursive in Fortran).
@@ -2248,6 +2356,20 @@ std=iso9899:2018
C ObjC Alias(std=c17)
Conform to the ISO 2017 C standard (published in 2018).
+stdlib=
+Driver C++ ObjC++ Common Condition(ENABLE_STDLIB_OPTION) Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1)
+-stdlib=[libstdc++|libc++] The standard library to be used for C++ headers
+and runtime.
+
+Enum
+Name(stdlib_kind) Type(int)
+
+EnumValue
+Enum(stdlib_kind) String(libstdc++) Value(1)
+
+EnumValue
+Enum(stdlib_kind) String(libc++) Value(2)
+
traditional
Driver
diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c
index c30f0b3..1914432 100644
--- a/gcc/c-family/stub-objc.c
+++ b/gcc/c-family/stub-objc.c
@@ -23,6 +23,9 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
+#include "vec.h"
+
+#include "c-common.h" /* for enum rid. */
#include "c-objc.h"
tree
@@ -131,6 +134,7 @@ objc_set_method_opt (bool ARG_UNUSED (optional))
void
objc_start_class_interface (tree ARG_UNUSED (name),
+ location_t /*name_loc*/,
tree ARG_UNUSED (super),
tree ARG_UNUSED (protos),
tree ARG_UNUSED (attribs))
@@ -314,14 +318,8 @@ objc_get_class_ivars (tree ARG_UNUSED (name))
void
objc_add_property_declaration (location_t ARG_UNUSED (location),
tree ARG_UNUSED (decl),
- bool ARG_UNUSED (parsed_property_readonly),
- bool ARG_UNUSED (parsed_property_readwrite),
- bool ARG_UNUSED (parsed_property_assign),
- bool ARG_UNUSED (parsed_property_retain),
- bool ARG_UNUSED (parsed_property_copy),
- bool ARG_UNUSED (parsed_property_nonatomic),
- tree ARG_UNUSED (parsed_property_getter_ident),
- tree ARG_UNUSED (parsed_property_setter_ident))
+ vec<property_attribute_info *>&
+ /*prop_attr_list*/)
{
}
@@ -331,6 +329,12 @@ objc_is_property_ref (tree ARG_UNUSED (node))
return 0;
}
+bool
+objc_non_constant_expr_p (tree)
+{
+ return 0;
+}
+
tree
objc_maybe_build_component_ref (tree ARG_UNUSED (datum), tree ARG_UNUSED (component))
{
@@ -459,3 +463,8 @@ void
objc_maybe_warn_exceptions (location_t ARG_UNUSED (loc))
{
}
+
+enum objc_property_attribute_kind objc_prop_attr_kind_for_rid (enum rid)
+{
+ return OBJC_PROPERTY_ATTR_UNKNOWN;
+}
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8c6893b..b5cf1a7 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,203 @@
+2020-12-16 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98047
+ * c-typeck.c (build_modify_expr): Drop qualifiers.
+
+2020-12-16 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98260
+ * c-parser.c (c_parser_expression): Look into
+ nop expression when marking expressions as read.
+
+2020-12-14 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/98204
+ * c-typeck.c (pointer_diff): Do not emit a top-level
+ sanitization.
+ (build_binary_op): Likewise.
+
+2020-12-09 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_allocate): New.
+ (c_parser_omp_construct): Call it.
+
+2020-12-09 Richard Biener <rguenther@suse.de>
+
+ PR c/98200
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Return
+ early on error.
+
+2020-12-07 Martin Uecker <muecker@gwdg.de>
+
+ PR c/97981
+ * c-typeck.c (convert_lvalue_to_rvalue): Move the code
+ that drops qualifiers to the end of the function.
+
+2020-11-26 Martin Uecker <muecker@gwdg.de>
+
+ PR c/65455
+ PR c/92935
+ * c-parser.c (c_parser_declaration_or_fndef): Remove
+ redundant code to drop qualifiers of _Atomic types for __auto_type.
+ (c_parser_typeof_specifier): Do not drop qualifiers of _Atomic
+ types for __typeof__.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97958
+ * c-parser.c (c_parser_binary_expression): For omp atomic binary
+ expressions, use make_node instead of build2 to avoid checking build2
+ performs.
+
+2020-11-23 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/95630
+ * c-typeck.c (build_binary_op): Use pedwarn_c99 with OPT_Wpedantic
+ for comparisons of complete and incomplete pointers.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * c-aux-info.c (gen_type): Support opaque types.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97879
+ * c-decl.c (start_function): Set ATTR_FLAG_INTERNAL in flags.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (c.serial): Change from goal to a variable.
+ (.PHONY): Drop c.serial.
+
+2020-11-20 Martin Uecker <muecker@gwdg.de>
+
+ * c-typeck.c (convert_lvalue_to_rvalue): Drop qualifiers.
+
+2020-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97860
+ * c-decl.c (get_parm_array_spec): Bail out of nelts is
+ error_operand_p.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (c.serial): New goal.
+ (.PHONY): Add c.serial c.prev.
+ (cc1$(exeext)): Call LINK_PROGRESS.
+
+2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * c-parser.c (c_parser_asm_statement): Parse outputs for asm
+ goto too.
+ * c-typeck.c (build_asm_expr): Remove an assert checking output
+ absence for asm goto.
+
+2020-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Don't clear
+ OMP_CLAUSE_REDUCTION_INSCAN unless reduction_seen == -2.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * c-parser.c (c_parser_objc_class_definition): Pass the
+ location of the class name to the interface declaration.
+
+2020-11-10 Strager Neds <strager.nds@gmail.com>
+
+ * c-decl.c (merge_decls): Use new overload of
+ set_decl_section_name.
+
+2020-11-10 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_target_data): Add use of
+ new c_omp_adjust_map_clauses function. Add GOMP_MAP_ATTACH_DETACH as
+ handled map clause kind.
+ (c_parser_omp_target_enter_data): Likewise.
+ (c_parser_omp_target_exit_data): Likewise.
+ (c_parser_omp_target): Likewise.
+ * c-typeck.c (handle_omp_array_sections): Adjust COMPONENT_REF case to
+ use GOMP_MAP_ATTACH_DETACH map kind for C_ORT_OMP region type.
+ (c_finish_omp_clauses): Adjust bitmap checks to allow struct decl and
+ same struct field access to co-exist on OpenMP construct.
+
+2020-11-07 Martin Uecker <muecker@gwdg.de>
+
+ * c-parser.c (c_parser_label): Implement mixing of labels and code.
+ (c_parser_all_labels): Likewise.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-parser.c (c_parser_objc_at_property_declaration):
+ Improve parsing fidelity. Associate better location info
+ with @property attributes. Clean up the interface to
+ objc_add_property_declaration ().
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * c-decl.c (diagnose_mismatched_decls): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+ (warn_if_shadowing, implicitly_declare, names_builtin_p)
+ (collect_source_refs): Likewise.
+ * c-typeck.c (inform_declaration, inform_for_arg)
+ (convert_for_assignment): Likewise.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_atomic): Add openacc parameter and update
+ OpenACC matching.
+ (c_parser_omp_construct): Update call.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97670
+ * c-typeck.c (c_finish_omp_clauses): Look through array reductions to
+ find underlying decl to clear in the aligned_head bitmap.
+
+2020-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (handle_nodiscard_attribute): New.
+ (std_attribute_table): Add nodiscard.
+ * c-parser.c (c_parser_std_attribute): Expect argument to
+ nodiscard attribute to be a string. Do not special-case ignoring
+ nodiscard.
+ * c-typeck.c (maybe_warn_nodiscard): New.
+ (build_compound_expr, emit_side_effect_warnings): Call
+ maybe_warn_nodiscard.
+ (c_process_expr_stmt, c_finish_stmt_expr): Also call
+ emit_side_effect_warnings if warn_unused_result.
+
+2020-10-29 Asher Gordon <AsDaGo@posteo.net>
+
+ * c-typeck.c (free_all_tagged_tu_seen_up_to): Replace free
+ with XDELETE.
+ (finish_init): Likewise.
+ (pop_init_level): Likewise.
+
+2020-10-28 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (store_parm_decls_newstyle): Use pedwarn_c11 not
+ error_at for omitted parameter name.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_name): Handle allocate.
+ (c_parser_omp_clause_allocate): New function.
+ (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ALLOCATE.
+ (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK,
+ OMP_PARALLEL_CLAUSE_MASK, OMP_SINGLE_CLAUSE_MASK,
+ OMP_TASK_CLAUSE_MASK, OMP_TASKGROUP_CLAUSE_MASK,
+ OMP_DISTRIBUTE_CLAUSE_MASK, OMP_TEAMS_CLAUSE_MASK,
+ OMP_TARGET_CLAUSE_MASK, OMP_TASKLOOP_CLAUSE_MASK): Add
+ PRAGMA_OMP_CLAUSE_ALLOCATE.
+ * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_ALLOCATE.
+
+2020-10-27 Joseph Myers <joseph@codesourcery.com>
+
+ * c-parser.c (c_parser_std_attribute_specifier): Allow duplicate
+ standard attributes.
+
2020-10-23 Marek Polacek <polacek@redhat.com>
PR c++/91741
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index 7efc7c2..4b2e616 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -37,6 +37,7 @@
#
# Define the names for selecting c in LANGUAGES.
c: cc1$(exeext)
+c.serial = cc1$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: c gcc
@@ -82,8 +83,10 @@ cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
fi
cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+ @$(call LINK_PROGRESS,$(INDEX.c),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.c),end)
cc1.fda: ../stage1-gcc/cc1$(exeext) ../prev-gcc/$(PERF_DATA)
$(CREATE_GCOV) -binary ../stage1-gcc/cc1$(exeext) -gcov cc1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index ffc8099..bdeef52 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -409,6 +409,7 @@ gen_type (const char *ret_val, tree t, formals_style style)
data_type = concat ("unsigned ", data_type, NULL);
break;
+ case OPAQUE_TYPE:
case REAL_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
break;
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 1673b95..27f7722 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2051,7 +2051,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_IS_BUILTIN (olddecl))
+ && DECL_IS_UNDECLARED_BUILTIN (olddecl))
{
/* A conflicting function declaration for a predeclared
function that isn't actually built in. Objective C uses
@@ -2265,7 +2265,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
built in, newdecl silently overrides olddecl. The latter
occur only in Objective C; see also above. (FIXME: Make
Objective C use normal builtins.) */
- if (!DECL_IS_BUILTIN (olddecl)
+ if (!DECL_IS_UNDECLARED_BUILTIN (olddecl)
&& !DECL_EXTERN_INLINE (olddecl))
{
auto_diagnostic_group d;
@@ -2884,7 +2884,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|| TREE_PUBLIC (olddecl)
|| TREE_STATIC (olddecl))
&& DECL_SECTION_NAME (newdecl) != NULL)
- set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl));
+ set_decl_section_name (olddecl, newdecl);
/* This isn't quite correct for something like
int __thread x attribute ((tls_model ("local-exec")));
@@ -2978,7 +2978,7 @@ warn_if_shadowing (tree new_decl)
|| warn_shadow_local
|| warn_shadow_compatible_local)
/* No shadow warnings for internally generated vars. */
- || DECL_IS_BUILTIN (new_decl))
+ || DECL_IS_UNDECLARED_BUILTIN (new_decl))
return;
/* Is anything being shadowed? Invisible decls do not count. */
@@ -3631,7 +3631,7 @@ implicitly_declare (location_t loc, tree functionid)
in the external scope because they're pushed before the file
scope gets created. Catch this here and rebind them into the
file scope. */
- if (!fndecl_built_in_p (decl) && DECL_IS_BUILTIN (decl))
+ if (!fndecl_built_in_p (decl) && DECL_IS_UNDECLARED_BUILTIN (decl))
{
bind (functionid, decl, file_scope,
/*invisible=*/false, /*nested=*/true,
@@ -4400,6 +4400,31 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
}
+/* Handle the standard [[nodiscard]] attribute. */
+
+static tree
+handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
+ int /*flags*/, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+ if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
+ warning_at (DECL_SOURCE_LOCATION (*node),
+ OPT_Wattributes, "%qE attribute applied to %qD with void "
+ "return type", name, *node);
+ }
+ else if (RECORD_OR_UNION_TYPE_P (*node)
+ || TREE_CODE (*node) == ENUMERAL_TYPE)
+ /* OK */;
+ else
+ {
+ pedwarn (input_location,
+ OPT_Wattributes, "%qE attribute can only be applied to "
+ "functions or to structure, union or enumeration types", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
/* Table of supported standard (C2x) attributes. */
const struct attribute_spec std_attribute_table[] =
{
@@ -4411,6 +4436,8 @@ const struct attribute_spec std_attribute_table[] =
handle_fallthrough_attribute, NULL },
{ "maybe_unused", 0, 0, false, false, false, false,
handle_unused_attribute, NULL },
+ { "nodiscard", 0, 1, false, false, false, false,
+ handle_nodiscard_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -5748,6 +5775,8 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
type = TREE_TYPE (type))
{
tree nelts = array_type_nelts (type);
+ if (error_operand_p (nelts))
+ return attrs;
if (TREE_CODE (nelts) != INTEGER_CST)
{
/* Each variable VLA bound is represented by the dollar
@@ -9569,7 +9598,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
current_function_decl = pushdecl (decl1);
if (tree access = build_attr_access_from_parms (parms, false))
- decl_attributes (&current_function_decl, access, 0, old_decl);
+ decl_attributes (&current_function_decl, access, ATTR_FLAG_INTERNAL,
+ old_decl);
push_scope ();
declare_parm_level ();
@@ -9630,7 +9660,9 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
warn_if_shadowing (decl);
}
else
- error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
+ pedwarn_c11 (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+ "ISO C does not support omitting parameter names in "
+ "function definitions before C2X");
}
/* Record the parameter list in the function declaration. */
@@ -10471,7 +10503,7 @@ names_builtin_p (const char *name)
{
tree id = get_identifier (name);
if (tree decl = identifier_global_value (id))
- return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl);
+ return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_UNDECLARED_BUILTIN (decl);
/* Also detect common reserved C words that aren't strictly built-in
functions. */
@@ -12105,12 +12137,12 @@ collect_source_refs (void)
{
decls = DECL_INITIAL (t);
for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
- if (!DECL_IS_BUILTIN (decl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (decl))
collect_source_ref (DECL_SOURCE_FILE (decl));
}
for (decl = BLOCK_VARS (ext_block); decl; decl = TREE_CHAIN (decl))
- if (!DECL_IS_BUILTIN (decl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (decl))
collect_source_ref (DECL_SOURCE_FILE (decl));
}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index b6a7ef4..b9fdc90 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1521,7 +1521,7 @@ static void c_parser_initval (c_parser *, struct c_expr *,
struct obstack *);
static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
static location_t c_parser_compound_statement_nostart (c_parser *);
-static void c_parser_label (c_parser *);
+static void c_parser_label (c_parser *, tree);
static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
static void c_parser_statement_after_labels (c_parser *, bool *,
vec<tree> * = NULL);
@@ -2224,10 +2224,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
" initializer");
init = convert_lvalue_to_rvalue (init_loc, init, true, true);
tree init_type = TREE_TYPE (init.value);
- /* As with typeof, remove all qualifiers from atomic types. */
- if (init_type != error_mark_node && TYPE_ATOMIC (init_type))
- init_type
- = c_build_qualified_type (init_type, TYPE_UNQUALIFIED);
bool vm_type = variably_modified_type_p (init_type,
NULL_TREE);
if (vm_type)
@@ -3743,11 +3739,6 @@ c_parser_typeof_specifier (c_parser *parser)
if (was_vm)
ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
pop_maybe_used (was_vm);
- /* For use in macros such as those in <stdatomic.h>, remove all
- qualifiers from atomic types. (const can be an issue for more macros
- using typeof than just the <stdatomic.h> ones.) */
- if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec))
- ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED);
}
parens.skip_until_found_close (parser);
return ret;
@@ -4950,7 +4941,8 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
&& attribute_takes_identifier_p (name));
bool require_string
= (ns == NULL_TREE
- && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0);
+ && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0
+ || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0));
TREE_VALUE (attribute)
= c_parser_attribute_arguments (parser, takes_identifier,
require_string, false);
@@ -4960,13 +4952,12 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
parens.require_close (parser);
}
out:
- if (ns == NULL_TREE && !for_tm && !as && !is_attribute_p ("nodiscard", name))
+ if (ns == NULL_TREE && !for_tm && !as)
{
/* An attribute with standard syntax and no namespace specified
is a constraint violation if it is not one of the known
- standard attributes (of which nodiscard is the only one
- without a handler in GCC). Diagnose it here with a pedwarn
- and then discard it to prevent a duplicate warning later. */
+ standard attributes. Diagnose it here with a pedwarn and
+ then discard it to prevent a duplicate warning later. */
pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
name);
return error_mark_node;
@@ -4977,9 +4968,6 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
static tree
c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
{
- bool seen_deprecated = false;
- bool seen_fallthrough = false;
- bool seen_maybe_unused = false;
location_t loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
return NULL_TREE;
@@ -5005,55 +4993,8 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
tree attribute = c_parser_std_attribute (parser, for_tm);
if (attribute != error_mark_node)
{
- bool duplicate = false;
- tree name = get_attribute_name (attribute);
- tree ns = get_attribute_namespace (attribute);
- if (ns == NULL_TREE)
- {
- /* Some standard attributes may appear at most once in
- each attribute list. Diagnose duplicates and remove
- them from the list to avoid subsequent diagnostics
- such as the more general one for multiple
- "fallthrough" attributes in the same place (including
- in separate attribute lists in the same attribute
- specifier sequence, which is not a constraint
- violation). */
- if (is_attribute_p ("deprecated", name))
- {
- if (seen_deprecated)
- {
- error ("attribute %<deprecated%> can appear at most "
- "once in an attribute-list");
- duplicate = true;
- }
- seen_deprecated = true;
- }
- else if (is_attribute_p ("fallthrough", name))
- {
- if (seen_fallthrough)
- {
- error ("attribute %<fallthrough%> can appear at most "
- "once in an attribute-list");
- duplicate = true;
- }
- seen_fallthrough = true;
- }
- else if (is_attribute_p ("maybe_unused", name))
- {
- if (seen_maybe_unused)
- {
- error ("attribute %<maybe_unused%> can appear at most "
- "once in an attribute-list");
- duplicate = true;
- }
- seen_maybe_unused = true;
- }
- }
- if (!duplicate)
- {
- TREE_CHAIN (attribute) = attributes;
- attributes = attribute;
- }
+ TREE_CHAIN (attribute) = attributes;
+ attributes = attribute;
}
if (c_parser_next_token_is_not (parser, CPP_COMMA))
break;
@@ -5573,7 +5514,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
- C99 6.8.2, C11 6.8.2).
+ C99 6.8.2, C11 6.8.2, C2X 6.8.2).
compound-statement:
{ block-item-list[opt] }
@@ -5584,6 +5525,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
block-item-list block-item
block-item:
+ label
nested-declaration
statement
@@ -5724,7 +5666,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
loc = expansion_point_location_if_in_system_header (loc);
- /* Standard attributes may start a statement or a declaration. */
+ /* Standard attributes may start a label, statement or declaration. */
bool have_std_attrs
= c_parser_nth_token_starts_std_attributes (parser, 1);
tree std_attrs = NULL_TREE;
@@ -5735,7 +5677,6 @@ c_parser_compound_statement_nostart (c_parser *parser)
|| (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
{
- c_warn_unused_attributes (std_attrs);
if (c_parser_next_token_is_keyword (parser, RID_CASE))
label_loc = c_parser_peek_2nd_token (parser)->location;
else
@@ -5743,27 +5684,31 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_label = true;
last_stmt = false;
mark_valid_location_for_stdc_pragma (false);
- c_parser_label (parser);
+ c_parser_label (parser, std_attrs);
}
- else if (!last_label
- && (c_parser_next_tokens_start_declaration (parser)
- || (have_std_attrs
- && c_parser_next_token_is (parser, CPP_SEMICOLON))))
+ else if (c_parser_next_tokens_start_declaration (parser)
+ || (have_std_attrs
+ && c_parser_next_token_is (parser, CPP_SEMICOLON)))
{
- last_label = false;
+ if (last_label)
+ pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+ "a label can only be part of a statement and "
+ "a declaration is not a statement");
+
mark_valid_location_for_stdc_pragma (false);
bool fallthru_attr_p = false;
c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
true, true, true, NULL,
vNULL, have_std_attrs, std_attrs,
NULL, &fallthru_attr_p);
+
if (last_stmt && !fallthru_attr_p)
pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
"ISO C90 forbids mixed declarations and code");
last_stmt = fallthru_attr_p;
+ last_label = false;
}
- else if (!last_label
- && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+ else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
{
/* __extension__ can start a declaration, but is also an
unary operator that can start an expression. Consume all
@@ -5846,7 +5791,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
parser->error = false;
}
if (last_label)
- error_at (label_loc, "label at end of compound statement");
+ pedwarn_c11 (label_loc, OPT_Wpedantic, "label at end of compound statement");
location_t endloc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
/* Restore the value we started with. */
@@ -5862,19 +5807,29 @@ c_parser_compound_statement_nostart (c_parser *parser)
static void
c_parser_all_labels (c_parser *parser)
{
+ tree std_attrs = NULL;
if (c_parser_nth_token_starts_std_attributes (parser, 1))
{
- tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ std_attrs = c_parser_std_attribute_specifier_sequence (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
c_parser_error (parser, "expected statement");
- else
- c_warn_unused_attributes (std_attrs);
}
while (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|| (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
- c_parser_label (parser);
+ {
+ c_parser_label (parser, std_attrs);
+ std_attrs = NULL;
+ if (c_parser_nth_token_starts_std_attributes (parser, 1))
+ {
+ std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ c_parser_error (parser, "expected statement");
+ }
+ }
+ if (std_attrs)
+ c_warn_unused_attributes (std_attrs);
}
/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
@@ -5896,9 +5851,8 @@ c_parser_all_labels (c_parser *parser)
in the caller, to distinguish statements from declarations. Any
attribute-specifier-sequence after the label is parsed in this
function. */
-
static void
-c_parser_label (c_parser *parser)
+c_parser_label (c_parser *parser, tree std_attrs)
{
location_t loc1 = c_parser_peek_token (parser)->location;
tree label = NULL_TREE;
@@ -5948,8 +5902,13 @@ c_parser_label (c_parser *parser)
if (tlab)
{
decl_attributes (&tlab, attrs, 0);
+ decl_attributes (&tlab, std_attrs, 0);
label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
}
+ if (attrs
+ && c_parser_next_tokens_start_declaration (parser))
+ warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
+ " label and declaration appertains to the label");
}
if (label)
{
@@ -5957,55 +5916,6 @@ c_parser_label (c_parser *parser)
FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
else
FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
-
- /* Standard attributes are only allowed here if they start a
- statement, not a declaration (including the case of an
- attribute-declaration with only attributes). */
- bool have_std_attrs
- = c_parser_nth_token_starts_std_attributes (parser, 1);
- tree std_attrs = NULL_TREE;
- if (have_std_attrs)
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
-
- /* Allow '__attribute__((fallthrough));'. */
- if (!have_std_attrs
- && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- {
- location_t loc = c_parser_peek_token (parser)->location;
- tree attrs = c_parser_gnu_attributes (parser);
- if (attribute_fallthrough_p (attrs))
- {
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- tree fn = build_call_expr_internal_loc (loc,
- IFN_FALLTHROUGH,
- void_type_node, 0);
- add_stmt (fn);
- }
- else
- warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute "
- "not followed by %<;%>");
- }
- else if (attrs != NULL_TREE)
- warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
- " can be applied to a null statement");
- }
- if (c_parser_next_tokens_start_declaration (parser)
- || (have_std_attrs
- && c_parser_next_token_is (parser, CPP_SEMICOLON)))
- {
- error_at (c_parser_peek_token (parser)->location,
- "a label can only be part of a statement and "
- "a declaration is not a statement");
- c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
- /*static_assert_ok*/ true,
- /*empty_ok*/ true, /*nested*/ true,
- /*start_attr_ok*/ true, NULL,
- vNULL, have_std_attrs, std_attrs);
- }
- else if (std_attrs)
- /* Nonempty attributes on the following statement are ignored. */
- c_warn_unused_attributes (std_attrs);
}
}
@@ -7225,10 +7135,7 @@ c_parser_asm_statement (c_parser *parser)
switch (section)
{
case 0:
- /* For asm goto, we don't allow output operands, but reserve
- the slot for a future extension that does allow them. */
- if (!is_goto)
- outputs = c_parser_asm_operands (parser);
+ outputs = c_parser_asm_operands (parser);
break;
case 1:
inputs = c_parser_asm_operands (parser);
@@ -7949,9 +7856,13 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
&& stack[1].expr.value != error_mark_node \
&& (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
|| c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \
- stack[0].expr.value \
- = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \
- stack[0].expr.value, stack[1].expr.value); \
+ { \
+ tree t = make_node (stack[1].op); \
+ TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
+ TREE_OPERAND (t, 0) = stack[0].expr.value; \
+ TREE_OPERAND (t, 1) = stack[1].expr.value; \
+ stack[0].expr.value = t; \
+ } \
else \
stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
stack[sp].op, \
@@ -10704,8 +10615,14 @@ c_parser_expression (c_parser *parser)
c_parser_consume_token (parser);
expr_loc = c_parser_peek_token (parser)->location;
lhsval = expr.value;
- while (TREE_CODE (lhsval) == COMPOUND_EXPR)
- lhsval = TREE_OPERAND (lhsval, 1);
+ while (TREE_CODE (lhsval) == COMPOUND_EXPR
+ || TREE_CODE (lhsval) == NOP_EXPR)
+ {
+ if (TREE_CODE (lhsval) == COMPOUND_EXPR)
+ lhsval = TREE_OPERAND (lhsval, 1);
+ else
+ lhsval = TREE_OPERAND (lhsval, 0);
+ }
if (DECL_P (lhsval) || handled_component_p (lhsval))
mark_exp_read (lhsval);
next = c_parser_expr_no_commas (parser, NULL);
@@ -10882,6 +10799,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
return;
}
id1 = c_parser_peek_token (parser)->value;
+ location_t loc1 = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
@@ -10941,7 +10859,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
tree proto = NULL_TREE;
if (c_parser_next_token_is (parser, CPP_LESS))
proto = c_parser_objc_protocol_refs (parser);
- objc_start_class_interface (id1, superclass, proto, attributes);
+ objc_start_class_interface (id1, loc1, superclass, proto, attributes);
}
else
objc_start_class_implementation (id1, superclass);
@@ -12008,158 +11926,196 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
static void
c_parser_objc_at_property_declaration (c_parser *parser)
{
- /* The following variables hold the attributes of the properties as
- parsed. They are 'false' or 'NULL_TREE' if the attribute was not
- seen. When we see an attribute, we set them to 'true' (if they
- are boolean properties) or to the identifier (if they have an
- argument, ie, for getter and setter). Note that here we only
- parse the list of attributes, check the syntax and accumulate the
- attributes that we find. objc_add_property_declaration() will
- then process the information. */
- bool property_assign = false;
- bool property_copy = false;
- tree property_getter_ident = NULL_TREE;
- bool property_nonatomic = false;
- bool property_readonly = false;
- bool property_readwrite = false;
- bool property_retain = false;
- tree property_setter_ident = NULL_TREE;
-
- /* 'properties' is the list of properties that we read. Usually a
- single one, but maybe more (eg, in "@property int a, b, c;" there
- are three). */
- tree properties;
- location_t loc;
-
- loc = c_parser_peek_token (parser)->location;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
-
+ location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser); /* Eat '@property'. */
- /* Parse the optional attribute list... */
+ /* Parse the optional attribute list.
+
+ A list of parsed, but not verified, attributes. */
+ vec<property_attribute_info *> prop_attr_list = vNULL;
+
+ bool syntax_error = false;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
matching_parens parens;
+ location_t attr_start = c_parser_peek_token (parser)->location;
/* Eat the '(' */
parens.consume_open (parser);
/* Property attribute keywords are valid now. */
parser->objc_property_attr_context = true;
- while (true)
+ /* Allow @property (), with a warning. */
+ location_t attr_end = c_parser_peek_token (parser)->location;
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
- bool syntax_error = false;
- c_token *token = c_parser_peek_token (parser);
- enum rid keyword;
+ location_t attr_comb = make_location (attr_end, attr_start, attr_end);
+ warning_at (attr_comb, OPT_Wattributes,
+ "empty property attribute list");
+ }
+ else
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+ attr_start = token->location;
+ attr_end = get_finish (token->location);
+ location_t attr_comb = make_location (attr_start, attr_start,
+ attr_end);
- if (token->type != CPP_KEYWORD)
- {
- if (token->type == CPP_CLOSE_PAREN)
- c_parser_error (parser, "expected identifier");
- else
- {
- c_parser_consume_token (parser);
- c_parser_error (parser, "unknown property attribute");
- }
- break;
- }
- keyword = token->keyword;
- c_parser_consume_token (parser);
- switch (keyword)
- {
- case RID_ASSIGN: property_assign = true; break;
- case RID_COPY: property_copy = true; break;
- case RID_NONATOMIC: property_nonatomic = true; break;
- case RID_READONLY: property_readonly = true; break;
- case RID_READWRITE: property_readwrite = true; break;
- case RID_RETAIN: property_retain = true; break;
-
- case RID_GETTER:
- case RID_SETTER:
- if (c_parser_next_token_is_not (parser, CPP_EQ))
- {
- if (keyword == RID_GETTER)
- c_parser_error (parser,
- "missing %<=%> (after %<getter%> attribute)");
- else
- c_parser_error (parser,
- "missing %<=%> (after %<setter%> attribute)");
- syntax_error = true;
- break;
- }
- c_parser_consume_token (parser); /* eat the = */
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- syntax_error = true;
+ if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
+ {
+ warning_at (attr_comb, OPT_Wattributes,
+ "missing property attribute");
+ if (token->type == CPP_CLOSE_PAREN)
break;
- }
- if (keyword == RID_SETTER)
- {
- if (property_setter_ident != NULL_TREE)
- c_parser_error (parser, "the %<setter%> attribute may only be specified once");
- else
- property_setter_ident = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_COLON))
- c_parser_error (parser, "setter name must terminate with %<:%>");
- else
- c_parser_consume_token (parser);
- }
- else
- {
- if (property_getter_ident != NULL_TREE)
- c_parser_error (parser, "the %<getter%> attribute may only be specified once");
- else
- property_getter_ident = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- break;
- default:
- c_parser_error (parser, "unknown property attribute");
- syntax_error = true;
- break;
+ c_parser_consume_token (parser);
+ continue;
+ }
+
+ tree attr_name = NULL_TREE;
+ enum rid keyword = RID_MAX; /* Not a valid property attribute. */
+ bool add_at = false;
+ if (token->type == CPP_KEYWORD)
+ {
+ keyword = token->keyword;
+ if (OBJC_IS_AT_KEYWORD (keyword))
+ {
+ /* For '@' keywords the token value has the keyword,
+ prepend the '@' for diagnostics. */
+ attr_name = token->value;
+ add_at = true;
+ }
+ else
+ attr_name = ridpointers[(int)keyword];
+ }
+ else if (token->type == CPP_NAME)
+ attr_name = token->value;
+ c_parser_consume_token (parser);
+
+ enum objc_property_attribute_kind prop_kind
+ = objc_prop_attr_kind_for_rid (keyword);
+ property_attribute_info *prop
+ = new property_attribute_info (attr_name, attr_comb, prop_kind);
+ prop_attr_list.safe_push (prop);
+
+ tree meth_name;
+ switch (prop->prop_kind)
+ {
+ default: break;
+ case OBJC_PROPERTY_ATTR_UNKNOWN:
+ if (attr_name)
+ error_at (attr_comb, "unknown property attribute %<%s%s%>",
+ add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
+ else
+ error_at (attr_comb, "unknown property attribute");
+ prop->parse_error = syntax_error = true;
+ break;
+
+ case OBJC_PROPERTY_ATTR_GETTER:
+ case OBJC_PROPERTY_ATTR_SETTER:
+ if (c_parser_next_token_is_not (parser, CPP_EQ))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %<=%> after Objective-C %qE",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+ token = c_parser_peek_token (parser);
+ attr_end = token->location;
+ c_parser_consume_token (parser); /* eat the = */
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %qE selector name",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+ /* Get the end of the method name, and consume the name. */
+ token = c_parser_peek_token (parser);
+ attr_end = get_finish (token->location);
+ meth_name = token->value;
+ c_parser_consume_token (parser);
+ if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
+ {
+ if (c_parser_next_token_is_not (parser, CPP_COLON))
+ {
+ attr_comb = make_location (attr_end, attr_start,
+ attr_end);
+ error_at (attr_comb, "setter method names must"
+ " terminate with %<:%>");
+ prop->parse_error = syntax_error = true;
+ }
+ else
+ {
+ attr_end = get_finish (c_parser_peek_token
+ (parser)->location);
+ c_parser_consume_token (parser);
+ }
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ }
+ else
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ prop->ident = meth_name;
+ /* Updated location including all that was successfully
+ parsed. */
+ prop->prop_loc = attr_comb;
+ break;
}
- if (syntax_error)
- break;
-
+ /* If we see a comma here, then keep going - even if we already
+ saw a syntax error. For simple mistakes e.g. (asign, getter=x)
+ this makes a more useful output and avoid spurious warnings about
+ missing attributes that are, in fact, specified after the one with
+ the syntax error. */
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
else
break;
}
parser->objc_property_attr_context = false;
- parens.skip_until_found_close (parser);
- }
- /* ... and the property declaration(s). */
- properties = c_parser_struct_declaration (parser);
- if (properties == error_mark_node)
- {
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- parser->error = false;
- return;
+ if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+ /* We don't really want to chew the whole of the file looking for a
+ matching closing parenthesis, so we will try to read the decl and
+ let the error handling for that close out the statement. */
+ ;
+ else
+ syntax_error = false, parens.skip_until_found_close (parser);
}
- if (properties == NULL_TREE)
- c_parser_error (parser, "expected identifier");
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three). */
+ tree properties = c_parser_struct_declaration (parser);
+
+ if (properties == error_mark_node)
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
else
{
- /* Comma-separated properties are chained together in
- reverse order; add them one by one. */
- properties = nreverse (properties);
-
- for (; properties; properties = TREE_CHAIN (properties))
- objc_add_property_declaration (loc, copy_node (properties),
- property_readonly, property_readwrite,
- property_assign, property_retain,
- property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident);
+ if (properties == NULL_TREE)
+ c_parser_error (parser, "expected identifier");
+ else
+ {
+ /* Comma-separated properties are chained together in reverse order;
+ add them one by one. */
+ properties = nreverse (properties);
+ for (; properties; properties = TREE_CHAIN (properties))
+ objc_add_property_declaration (loc, copy_node (properties),
+ prop_attr_list);
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ while (!prop_attr_list.is_empty())
+ delete prop_attr_list.pop ();
+ prop_attr_list.release ();
parser->error = false;
}
@@ -12653,6 +12609,8 @@ c_parser_omp_clause_name (c_parser *parser)
case 'a':
if (!strcmp ("aligned", p))
result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ else if (!strcmp ("allocate", p))
+ result = PRAGMA_OMP_CLAUSE_ALLOCATE;
else if (!strcmp ("async", p))
result = PRAGMA_OACC_CLAUSE_ASYNC;
else if (!strcmp ("attach", p))
@@ -15162,6 +15120,62 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
return nl;
}
+/* OpenMP 5.0:
+ allocate ( variable-list )
+ allocate ( expression : variable-list ) */
+
+static tree
+c_parser_omp_clause_allocate (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree nl, c;
+ tree allocator = NULL_TREE;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ if ((c_parser_next_token_is_not (parser, CPP_NAME)
+ && c_parser_next_token_is_not (parser, CPP_KEYWORD))
+ || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
+ && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ tree orig_type
+ = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
+ || TREE_CODE (orig_type) != ENUMERAL_TYPE
+ || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t"))
+ {
+ error_at (clause_loc, "%<allocate%> clause allocator expression "
+ "has type %qT rather than "
+ "%<omp_allocator_handle_t%>",
+ TREE_TYPE (allocator));
+ allocator = NULL_TREE;
+ }
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ }
+
+ nl = c_parser_omp_variable_list (parser, clause_loc,
+ OMP_CLAUSE_ALLOCATE, list);
+
+ if (allocator)
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ parens.skip_until_found_close (parser);
+ return nl;
+}
+
/* OpenMP 4.0:
linear ( variable-list )
linear ( variable-list : expression )
@@ -16404,6 +16418,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_aligned (parser, clauses);
c_name = "aligned";
break;
+ case PRAGMA_OMP_CLAUSE_ALLOCATE:
+ clauses = c_parser_omp_clause_allocate (parser, clauses);
+ c_name = "allocate";
+ break;
case PRAGMA_OMP_CLAUSE_LINEAR:
clauses = c_parser_omp_clause_linear (parser, clauses);
c_name = "linear";
@@ -17238,6 +17256,55 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
return stmt;
}
+/* OpenMP 5.0:
+ # pragma omp allocate (list) [allocator(allocator)] */
+
+static void
+c_parser_omp_allocate (location_t loc, c_parser *parser)
+{
+ tree allocator = NULL_TREE;
+ tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ matching_parens parens;
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ if (strcmp ("allocator", p) != 0)
+ error_at (c_parser_peek_token (parser)->location,
+ "expected %<allocator%>");
+ else if (parens.require_open (parser))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ tree orig_type
+ = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
+ || TREE_CODE (orig_type) != ENUMERAL_TYPE
+ || TYPE_NAME (orig_type)
+ != get_identifier ("omp_allocator_handle_t"))
+ {
+ error_at (expr_loc, "%<allocator%> clause allocator expression "
+ "has type %qT rather than "
+ "%<omp_allocator_handle_t%>",
+ TREE_TYPE (allocator));
+ allocator = NULL_TREE;
+ }
+ parens.skip_until_found_close (parser);
+ }
+ }
+ c_parser_skip_to_pragma_eol (parser);
+
+ if (allocator)
+ for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ sorry_at (loc, "%<#pragma omp allocate%> not yet supported");
+}
+
/* OpenMP 2.5:
# pragma omp atomic new-line
expression-stmt
@@ -17292,7 +17359,7 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
LOC is the location of the #pragma token. */
static void
-c_parser_omp_atomic (location_t loc, c_parser *parser)
+c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
@@ -17331,6 +17398,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
new_code = OMP_ATOMIC;
else if (!strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
+ else if (openacc)
+ {
+ p = NULL;
+ error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+ "or %<capture%> clause");
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -17358,7 +17431,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
{
if (new_code != ERROR_MARK)
{
- if (code != ERROR_MARK)
+ /* OpenACC permits 'update capture'. */
+ if (openacc
+ && code == OMP_ATOMIC
+ && new_code == OMP_ATOMIC_CAPTURE_NEW)
+ code = new_code;
+ else if (code != ERROR_MARK)
error_at (cloc, "too many atomic clauses");
else
code = new_code;
@@ -17380,7 +17458,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
- if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+ if (openacc)
+ memory_order = OMP_MEMORY_ORDER_RELAXED;
+ else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
{
omp_requires_mask
= (enum omp_requires) (omp_requires_mask
@@ -17436,6 +17516,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
}
break;
case OMP_ATOMIC:
+ /* case OMP_ATOMIC_CAPTURE_NEW: - or update to OpenMP 5.1 */
if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
|| memory_order == OMP_MEMORY_ORDER_ACQUIRE)
{
@@ -18584,6 +18665,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
static tree
@@ -18875,6 +18957,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -18929,6 +19012,7 @@ c_parser_omp_sections (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
@@ -19070,6 +19154,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -19104,6 +19189,7 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
static tree
@@ -19174,7 +19260,8 @@ c_parser_omp_taskyield (c_parser *parser)
*/
#define OMP_TASKGROUP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
static tree
c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
@@ -19275,6 +19362,7 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
@@ -19364,6 +19452,7 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
static tree
@@ -19470,6 +19559,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
"#pragma omp target data");
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -19487,6 +19577,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -19610,6 +19701,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
"#pragma omp target enter data");
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -19623,6 +19715,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -19694,7 +19787,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
"#pragma omp target exit data");
-
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -19709,6 +19802,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -19751,6 +19845,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
@@ -19918,6 +20013,8 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
OMP_TARGET_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
"#pragma omp target");
+ c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
@@ -19942,6 +20039,7 @@ check_clauses:
case GOMP_MAP_ALLOC:
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
error_at (OMP_CLAUSE_LOCATION (*pc),
@@ -21381,6 +21479,7 @@ c_finish_taskloop_clauses (tree clauses)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
@@ -21467,7 +21566,7 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
switch (p_kind)
{
case PRAGMA_OACC_ATOMIC:
- c_parser_omp_atomic (loc, parser);
+ c_parser_omp_atomic (loc, parser, true);
return;
case PRAGMA_OACC_CACHE:
strcpy (p_name, "#pragma acc");
@@ -21493,8 +21592,11 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma wait");
stmt = c_parser_oacc_wait (loc, parser, p_name);
break;
+ case PRAGMA_OMP_ALLOCATE:
+ c_parser_omp_allocate (loc, parser);
+ return;
case PRAGMA_OMP_ATOMIC:
- c_parser_omp_atomic (loc, parser);
+ c_parser_omp_atomic (loc, parser, false);
return;
case PRAGMA_OMP_CRITICAL:
stmt = c_parser_omp_critical (loc, parser, if_p);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 459090e..f68cb01 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -1407,7 +1407,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
const struct tagged_tu_seen_cache *const tu1
= (const struct tagged_tu_seen_cache *) tu;
tu = tu1->next;
- free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
+ XDELETE (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
}
tagged_tu_seen_base = tu_til;
}
@@ -2116,6 +2116,9 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
exp.value = build4 (TARGET_EXPR, nonatomic_type, tmp, func_call,
NULL_TREE, NULL_TREE);
}
+ if (convert_p && !error_operand_p (exp.value)
+ && (TREE_CODE (TREE_TYPE (exp.value)) != ARRAY_TYPE))
+ exp.value = convert (build_qualified_type (TREE_TYPE (exp.value), TYPE_UNQUALIFIED), exp.value);
return exp;
}
@@ -3014,7 +3017,8 @@ build_function_call (location_t loc, tree function, tree params)
static void
inform_declaration (tree decl)
{
- if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_IS_BUILTIN (decl)))
+ if (decl && (TREE_CODE (decl) != FUNCTION_DECL
+ || !DECL_IS_UNDECLARED_BUILTIN (decl)))
inform (DECL_SOURCE_LOCATION (decl), "declared here");
}
@@ -3945,10 +3949,9 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
pedwarn (loc, OPT_Wpointer_arith,
"pointer to a function used in subtraction");
- if (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
+ if (current_function_decl != NULL_TREE
+ && sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
{
- gcc_assert (current_function_decl != NULL_TREE);
-
op0 = save_expr (op0);
op1 = save_expr (op1);
@@ -5490,6 +5493,82 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
return ret;
}
+/* EXPR is an expression, location LOC, whose result is discarded.
+ Warn if it is a call to a nodiscard function (or a COMPOUND_EXPR
+ whose right-hand operand is such a call, possibly recursively). */
+
+static void
+maybe_warn_nodiscard (location_t loc, tree expr)
+{
+ if (VOID_TYPE_P (TREE_TYPE (expr)))
+ return;
+ while (TREE_CODE (expr) == COMPOUND_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 1);
+ if (EXPR_HAS_LOCATION (expr))
+ loc = EXPR_LOCATION (expr);
+ }
+ if (TREE_CODE (expr) != CALL_EXPR)
+ return;
+ tree fn = CALL_EXPR_FN (expr);
+ if (!fn)
+ return;
+ tree attr;
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ && (attr = lookup_attribute ("nodiscard",
+ DECL_ATTRIBUTES (TREE_OPERAND (fn, 0)))))
+ {
+ fn = TREE_OPERAND (fn, 0);
+ tree args = TREE_VALUE (attr);
+ if (args)
+ args = TREE_VALUE (args);
+ auto_diagnostic_group d;
+ int warned;
+ if (args)
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of %qD, declared with "
+ "attribute %<nodiscard%>: %E", fn, args);
+ else
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of %qD, declared with "
+ "attribute %<nodiscard%>", fn);
+ if (warned)
+ inform (DECL_SOURCE_LOCATION (fn), "declared here");
+ }
+ else
+ {
+ tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
+ attr = lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype));
+ if (!attr)
+ return;
+ tree args = TREE_VALUE (attr);
+ if (args)
+ args = TREE_VALUE (args);
+ auto_diagnostic_group d;
+ int warned;
+ if (args)
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of type %qT, declared "
+ "with attribute %<nodiscard%>: %E",
+ rettype, args);
+ else
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of type %qT, declared "
+ "with attribute %<nodiscard%>", rettype);
+ if (warned)
+ {
+ if (TREE_CODE (fn) == ADDR_EXPR)
+ {
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) == FUNCTION_DECL)
+ inform (DECL_SOURCE_LOCATION (fn),
+ "in call to %qD, declared here", fn);
+ }
+ }
+ }
+}
+
/* Return a compound expression that performs two expressions and
returns the value of the second of them.
@@ -5561,6 +5640,8 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
else if (warn_unused_value)
warn_if_unused_value (expr1, loc);
+ maybe_warn_nodiscard (loc, expr1);
+
if (expr2 == error_mark_node)
return error_mark_node;
@@ -6194,16 +6275,9 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
"enum conversion in assignment is invalid in C++");
}
- /* If the lhs is atomic, remove that qualifier. */
- if (is_atomic_op)
- {
- lhstype = build_qualified_type (lhstype,
- (TYPE_QUALS (lhstype)
- & ~TYPE_QUAL_ATOMIC));
- olhstype = build_qualified_type (olhstype,
- (TYPE_QUALS (lhstype)
- & ~TYPE_QUAL_ATOMIC));
- }
+ /* Remove qualifiers. */
+ lhstype = build_qualified_type (lhstype, TYPE_UNQUALIFIED);
+ olhstype = build_qualified_type (olhstype, TYPE_UNQUALIFIED);
/* Convert new value to destination type. Fold it first, then
restore any excess precision information, for the sake of
@@ -6500,7 +6574,7 @@ inform_for_arg (tree fundecl, location_t ploc, int parmnum,
tree expected_type, tree actual_type)
{
location_t loc;
- if (fundecl && !DECL_IS_BUILTIN (fundecl))
+ if (fundecl && !DECL_IS_UNDECLARED_BUILTIN (fundecl))
loc = get_fndecl_argument_location (fundecl, parmnum - 1);
else
loc = ploc;
@@ -6750,7 +6824,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wc___compat, "enum conversion when "
"passing argument %d of %qE is invalid in C++",
parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
+ inform ((fundecl && !DECL_IS_UNDECLARED_BUILTIN (fundecl))
? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
"expected %qT but argument is of type %qT",
type, rhstype);
@@ -7161,7 +7235,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
case ic_argpass:
/* Do not warn for built-in functions, for example memcpy, since we
control how they behave and they can be useful in this area. */
- if (TREE_CODE (rname) != FUNCTION_DECL || !DECL_IS_BUILTIN (rname))
+ if (TREE_CODE (rname) != FUNCTION_DECL
+ || !DECL_IS_UNDECLARED_BUILTIN (rname))
warning_at (location, OPT_Wscalar_storage_order,
"passing argument %d of %qE from incompatible "
"scalar storage order", parmnum, rname);
@@ -8314,13 +8389,13 @@ finish_init (void)
{
struct constructor_stack *q = constructor_stack;
constructor_stack = q->next;
- free (q);
+ XDELETE (q);
}
gcc_assert (!constructor_range_stack);
/* Pop back to the data of the outer initializer (if any). */
- free (spelling_base);
+ XDELETE (spelling_base);
constructor_decl = p->decl;
require_constant_value = p->require_constant_value;
@@ -8333,7 +8408,7 @@ finish_init (void)
spelling_size = p->spelling_size;
constructor_top_level = p->top_level;
initializer_stack = p->next;
- free (p);
+ XDELETE (p);
}
/* Call here when we see the initializer is surrounded by braces.
@@ -8864,7 +8939,7 @@ pop_init_level (location_t loc, int implicit,
RESTORE_SPELLING_DEPTH (constructor_depth);
constructor_stack = p->next;
- free (p);
+ XDELETE (p);
if (ret.value == NULL_TREE && constructor_stack == 0)
ret.value = error_mark_node;
@@ -10586,10 +10661,6 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
TREE_VALUE (tail) = input;
}
- /* ASMs with labels cannot have outputs. This should have been
- enforced by the parser. */
- gcc_assert (outputs == NULL || labels == NULL);
-
args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
/* asm statements without outputs, including simple ones, are treated
@@ -11072,6 +11143,9 @@ c_finish_bc_stmt (location_t loc, tree label, bool is_break)
static void
emit_side_effect_warnings (location_t loc, tree expr)
{
+ maybe_warn_nodiscard (loc, expr);
+ if (!warn_unused_value)
+ return;
if (expr == error_mark_node)
;
else if (!TREE_SIDE_EFFECTS (expr))
@@ -11127,7 +11201,7 @@ c_process_expr_stmt (location_t loc, tree expr)
Warnings for statement expressions will be emitted later, once we figure
out which is the result. */
if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
- && warn_unused_value)
+ && (warn_unused_value || warn_unused_result))
emit_side_effect_warnings (EXPR_LOC_OR_LOC (expr, loc), expr);
exprv = expr;
@@ -11221,7 +11295,7 @@ c_finish_stmt_expr (location_t loc, tree body)
/* If we're supposed to generate side effects warnings, process
all of the statements except the last. */
- if (warn_unused_value)
+ if (warn_unused_value || warn_unused_result)
{
for (tree_stmt_iterator i = tsi_start (last);
tsi_stmt (i) != tsi_stmt (l); tsi_next (&i))
@@ -12184,8 +12258,8 @@ build_binary_op (location_t location, enum tree_code code,
result_type = common_pointer_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
- pedwarn (location, 0,
- "comparison of complete and incomplete pointers");
+ pedwarn_c99 (location, OPT_Wpedantic,
+ "comparison of complete and incomplete pointers");
else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn (location, OPT_Wpedantic, "ISO C forbids "
"ordered comparisons of pointers to functions");
@@ -12242,6 +12316,7 @@ build_binary_op (location_t location, enum tree_code code,
}
if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
+ && current_function_decl != NULL_TREE
&& sanitize_flags_p (SANITIZE_POINTER_COMPARE))
{
op0 = save_expr (op0);
@@ -13501,11 +13576,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
if (ort != C_ORT_OMP && ort != C_ORT_ACC)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
else if (TREE_CODE (t) == COMPONENT_REF)
- {
- gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
- OMP_CLAUSE_SET_MAP_KIND (c2, k);
- }
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
@@ -13795,6 +13866,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* 1 if normal/task reduction has been seen, -1 if inscan reduction
has been seen, -2 if mixed inscan/normal reduction diagnosed. */
int reduction_seen = 0;
+ bool allocate_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -14344,6 +14416,29 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
break;
+ case OMP_CLAUSE_ALLOCATE:
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<allocate%> clause", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%qE appears more than once in %<allocate%> clauses",
+ t);
+ remove = true;
+ }
+ else
+ {
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ if (!OMP_CLAUSE_ALLOCATE_COMBINED (c))
+ allocate_seen = true;
+ }
+ break;
+
case OMP_CLAUSE_DEPEND:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
@@ -14604,7 +14699,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
{
- if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
+ if (bitmap_bit_p (&map_field_head, DECL_UID (t))
+ || (ort == C_ORT_OMP
+ && bitmap_bit_p (&map_head, DECL_UID (t))))
break;
}
}
@@ -14673,7 +14770,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else
bitmap_set_bit (&generic_head, DECL_UID (t));
}
- else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+ else if (bitmap_bit_p (&map_head, DECL_UID (t))
+ && (ort != C_ORT_OMP
+ || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -14687,7 +14786,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
- || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ && ort == C_ORT_ACC)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -15041,10 +15146,40 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
reduction_seen = -2;
}
- if (linear_variable_step_check || reduction_seen == -2)
+ if (linear_variable_step_check || reduction_seen == -2 || allocate_seen)
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
+ if (allocate_seen)
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
+ {
+ t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ break;
+ }
+ /* FALLTHRU */
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_LINEAR:
+ if (DECL_P (OMP_CLAUSE_DECL (c)))
+ bitmap_clear_bit (&aligned_head,
+ DECL_UID (OMP_CLAUSE_DECL (c)));
+ break;
+ default:
+ break;
+ }
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
&& OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c)
&& !bitmap_bit_p (&map_head,
@@ -15056,7 +15191,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
OMP_CLAUSE_LINEAR_STEP (c));
remove = true;
}
- else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && reduction_seen == -2)
OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
if (remove)
@@ -15065,6 +15201,25 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (allocate_seen)
+ for (pc = &clauses, c = clauses; c ; c = *pc)
+ {
+ bool remove = false;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && !OMP_CLAUSE_ALLOCATE_COMBINED (c)
+ && bitmap_bit_p (&aligned_head, DECL_UID (OMP_CLAUSE_DECL (c))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %<allocate%> clause but not in "
+ "an explicit privatization clause", OMP_CLAUSE_DECL (c));
+ remove = true;
+ }
+ if (remove)
+ *pc = OMP_CLAUSE_CHAIN (c);
+ else
+ pc = &OMP_CLAUSE_CHAIN (c);
+ }
+
if (nogroup_seen && reduction_seen)
{
error_at (OMP_CLAUSE_LOCATION (*nogroup_seen),
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 5c0ed82..473cb90 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1700,6 +1700,8 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
expr.set_error ();
break;
}
+ if (expr.value == error_mark_node)
+ return expr;
return c_parser_gimple_postfix_expression_after_primary
(parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
}
diff --git a/gcc/calls.c b/gcc/calls.c
index 17b8e2f..4114bf5 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -630,21 +630,32 @@ special_function_p (const_tree fndecl, int flags)
return flags;
}
+/* Return fnspec for DECL. */
+
+static attr_fnspec
+decl_fnspec (tree fndecl)
+{
+ tree attr;
+ tree type = TREE_TYPE (fndecl);
+ if (type)
+ {
+ attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+ if (attr)
+ {
+ return TREE_VALUE (TREE_VALUE (attr));
+ }
+ }
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ return builtin_fnspec (fndecl);
+ return "";
+}
+
/* Similar to special_function_p; return a set of ERF_ flags for the
function FNDECL. */
static int
decl_return_flags (tree fndecl)
{
- tree attr;
- tree type = TREE_TYPE (fndecl);
- if (!type)
- return 0;
-
- attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
- if (!attr)
- return 0;
-
- attr_fnspec fnspec (TREE_VALUE (TREE_VALUE (attr)));
+ attr_fnspec fnspec = decl_fnspec (fndecl);
unsigned int arg;
if (fnspec.returns_arg (&arg))
@@ -1537,7 +1548,7 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
{
location_t fnloc = DECL_SOURCE_LOCATION (fn);
- if (DECL_IS_BUILTIN (fn))
+ if (DECL_IS_UNDECLARED_BUILTIN (fn))
inform (loc,
"in a call to built-in allocation function %qD", fn);
else
@@ -1911,7 +1922,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
/* Issue an error if CALL_EXPR was flagged as requiring
tall-call optimization. */
-static void
+void
maybe_complain_about_tail_call (tree call_expr, const char *reason)
{
gcc_assert (TREE_CODE (call_expr) == CALL_EXPR);
@@ -2612,6 +2623,10 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
/* Check attribute access arguments. */
maybe_warn_rdwr_sizes (&rdwr_idx, fndecl, fntype, exp);
+
+ /* Check calls to operator new for mismatched forms and attempts
+ to deallocate unallocated objects. */
+ maybe_emit_free_warning (exp);
}
/* Update ARGS_SIZE to contain the total size for the argument block.
@@ -3514,7 +3529,6 @@ static bool
can_implement_as_sibling_call_p (tree exp,
rtx structure_value_addr,
tree funtype,
- int reg_parm_stack_space ATTRIBUTE_UNUSED,
tree fndecl,
int flags,
tree addr,
@@ -3539,20 +3553,6 @@ can_implement_as_sibling_call_p (tree exp,
return false;
}
-#ifdef REG_PARM_STACK_SPACE
- /* If outgoing reg parm stack space changes, we cannot do sibcall. */
- if (OUTGOING_REG_PARM_STACK_SPACE (funtype)
- != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl))
- || (reg_parm_stack_space != REG_PARM_STACK_SPACE (current_function_decl)))
- {
- maybe_complain_about_tail_call (exp,
- "inconsistent size of stack space"
- " allocated for arguments which are"
- " passed in registers");
- return false;
- }
-#endif
-
/* Check whether the target is able to optimize the call
into a sibcall. */
if (!targetm.function_ok_for_sibcall (fndecl, exp))
@@ -4077,7 +4077,6 @@ expand_call (tree exp, rtx target, int ignore)
try_tail_call = can_implement_as_sibling_call_p (exp,
structure_value_addr,
funtype,
- reg_parm_stack_space,
fndecl,
flags, addr, args_size);
diff --git a/gcc/calls.h b/gcc/calls.h
index f32b630..b20d24b 100644
--- a/gcc/calls.h
+++ b/gcc/calls.h
@@ -133,6 +133,7 @@ extern bool reference_callee_copied (CUMULATIVE_ARGS *,
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
extern tree get_attr_nonstring_decl (tree, tree * = NULL);
extern bool maybe_warn_nonstring_arg (tree, tree);
+extern void maybe_complain_about_tail_call (tree, const char *);
enum size_range_flags
{
/* Set to consider zero a valid range. */
diff --git a/gcc/cfg.c b/gcc/cfg.c
index d82324f..529b6ed 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
Available functionality:
- Initialization/deallocation
- init_flow, clear_edges
+ init_flow, free_cfg
- Low level basic block manipulation
alloc_block, expunge_block
- Edge manipulation
@@ -83,7 +83,7 @@ init_flow (struct function *the_fun)
the_fun->cfg->bb_flags_allocated = BB_ALL_FLAGS;
}
-/* Helper function for remove_edge and clear_edges. Frees edge structure
+/* Helper function for remove_edge and free_cffg. Frees edge structure
without actually removing it from the pred/succ arrays. */
static void
@@ -93,29 +93,44 @@ free_edge (function *fn, edge e)
ggc_free (e);
}
-/* Free the memory associated with the edge structures. */
+/* Free basic block BB. */
+
+static void
+free_block (basic_block bb)
+{
+ vec_free (bb->succs);
+ bb->succs = NULL;
+ vec_free (bb->preds);
+ bb->preds = NULL;
+ /* Do not free BB itself yet since we leak pointers to dead statements
+ that points to dead basic blocks. */
+}
+
+/* Free the memory associated with the CFG in FN. */
void
-clear_edges (struct function *fn)
+free_cfg (struct function *fn)
{
- basic_block bb;
edge e;
edge_iterator ei;
+ basic_block next;
- FOR_EACH_BB_FN (bb, fn)
+ for (basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (fn); bb; bb = next)
{
+ next = bb->next_bb;
FOR_EACH_EDGE (e, ei, bb->succs)
free_edge (fn, e);
- vec_safe_truncate (bb->succs, 0);
- vec_safe_truncate (bb->preds, 0);
+ free_block (bb);
}
- FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fn)->succs)
- free_edge (fn, e);
- vec_safe_truncate (EXIT_BLOCK_PTR_FOR_FN (fn)->preds, 0);
- vec_safe_truncate (ENTRY_BLOCK_PTR_FOR_FN (fn)->succs, 0);
-
gcc_assert (!n_edges_for_fn (fn));
+ /* Sanity check that dominance tree is freed. */
+ gcc_assert (!fn->cfg->x_dom_computed[0] && !fn->cfg->x_dom_computed[1]);
+
+ vec_free (fn->cfg->x_label_to_block_map);
+ vec_free (basic_block_info_for_fn (fn));
+ ggc_free (fn->cfg);
+ fn->cfg = NULL;
}
/* Allocate memory for basic_block. */
@@ -190,8 +205,8 @@ expunge_block (basic_block b)
/* We should be able to ggc_free here, but we are not.
The dead SSA_NAMES are left pointing to dead statements that are pointing
to dead basic blocks making garbage collector to die.
- We should be able to release all dead SSA_NAMES and at the same time we should
- clear out BB pointer of dead statements consistently. */
+ We should be able to release all dead SSA_NAMES and at the same time we
+ should clear out BB pointer of dead statements consistently. */
}
/* Connect E to E->src. */
@@ -720,7 +735,7 @@ free_aux_for_edges (void)
DEBUG_FUNCTION void
debug_bb (basic_block bb)
{
- dump_bb (stderr, bb, 0, dump_flags);
+ debug_bb (bb, dump_flags);
}
DEBUG_FUNCTION basic_block
@@ -731,6 +746,24 @@ debug_bb_n (int n)
return bb;
}
+/* Print BB with specified FLAGS. */
+
+DEBUG_FUNCTION void
+debug_bb (basic_block bb, dump_flags_t flags)
+{
+ dump_bb (stderr, bb, 0, flags);
+}
+
+/* Print basic block numbered N with specified FLAGS. */
+
+DEBUG_FUNCTION basic_block
+debug_bb_n (int n, dump_flags_t flags)
+{
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, n);
+ debug_bb (bb, flags);
+ return bb;
+}
+
/* Dumps cfg related information about basic block BB to OUTF.
If HEADER is true, dump things that appear before the instructions
contained in BB. If FOOTER is true, dump things that appear after.
diff --git a/gcc/cfg.h b/gcc/cfg.h
index 1eb7866..a9c8300 100644
--- a/gcc/cfg.h
+++ b/gcc/cfg.h
@@ -82,7 +82,7 @@ struct GTY(()) control_flow_graph {
extern void init_flow (function *);
-extern void clear_edges (function *);
+extern void free_cfg (function *);
extern basic_block alloc_block (void);
extern void link_block (basic_block, basic_block);
extern void unlink_block (basic_block);
@@ -108,6 +108,8 @@ extern void clear_aux_for_edges (void);
extern void free_aux_for_edges (void);
extern void debug_bb (basic_block);
extern basic_block debug_bb_n (int);
+extern void debug_bb (basic_block, dump_flags_t);
+extern basic_block debug_bb_n (int, dump_flags_t);
extern void dump_bb_info (FILE *, basic_block, int, dump_flags_t, bool, bool);
extern void brief_dump_cfg (FILE *, dump_flags_t);
extern void update_bb_profile_for_threading (basic_block, profile_count, edge);
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index f3f17d3..2cbcbc8 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -103,7 +103,7 @@ tree
gimple_assign_rhs_to_tree (gimple *stmt)
{
tree t;
- switch (get_gimple_rhs_class (gimple_expr_code (stmt)))
+ switch (gimple_assign_rhs_class (stmt))
{
case GIMPLE_TERNARY_RHS:
t = build3 (gimple_assign_rhs_code (stmt),
@@ -366,17 +366,28 @@ align_local_variable (tree decl, bool really_expand)
unsigned int align;
if (TREE_CODE (decl) == SSA_NAME)
- align = TYPE_ALIGN (TREE_TYPE (decl));
- else
{
- align = LOCAL_DECL_ALIGNMENT (decl);
- /* Don't change DECL_ALIGN when called from estimated_stack_frame_size.
- That is done before IPA and could bump alignment based on host
- backend even for offloaded code which wants different
- LOCAL_DECL_ALIGNMENT. */
- if (really_expand)
- SET_DECL_ALIGN (decl, align);
+ tree type = TREE_TYPE (decl);
+ machine_mode mode = TYPE_MODE (type);
+
+ align = TYPE_ALIGN (type);
+ if (mode != BLKmode
+ && align < GET_MODE_ALIGNMENT (mode))
+ align = GET_MODE_ALIGNMENT (mode);
}
+ else
+ align = LOCAL_DECL_ALIGNMENT (decl);
+
+ if (hwasan_sanitize_stack_p ())
+ align = MAX (align, (unsigned) HWASAN_TAG_GRANULE_SIZE * BITS_PER_UNIT);
+
+ if (TREE_CODE (decl) != SSA_NAME && really_expand)
+ /* Don't change DECL_ALIGN when called from estimated_stack_frame_size.
+ That is done before IPA and could bump alignment based on host
+ backend even for offloaded code which wants different
+ LOCAL_DECL_ALIGNMENT. */
+ SET_DECL_ALIGN (decl, align);
+
return align / BITS_PER_UNIT;
}
@@ -420,6 +431,14 @@ alloc_stack_frame_space (poly_int64 size, unsigned HOST_WIDE_INT align)
return offset;
}
+/* Ensure that the stack is aligned to ALIGN bytes.
+ Return the new frame offset. */
+static poly_int64
+align_frame_offset (unsigned HOST_WIDE_INT align)
+{
+ return alloc_stack_frame_space (0, align);
+}
+
/* Accumulate DECL into STACK_VARS. */
static void
@@ -996,23 +1015,29 @@ expand_one_stack_var_at (tree decl, rtx base, unsigned base_align,
/* If this fails, we've overflowed the stack frame. Error nicely? */
gcc_assert (known_eq (offset, trunc_int_for_mode (offset, Pmode)));
- x = plus_constant (Pmode, base, offset);
+ if (hwasan_sanitize_stack_p ())
+ x = targetm.memtag.add_tag (base, offset,
+ hwasan_current_frame_tag ());
+ else
+ x = plus_constant (Pmode, base, offset);
+
x = gen_rtx_MEM (TREE_CODE (decl) == SSA_NAME
? TYPE_MODE (TREE_TYPE (decl))
- : DECL_MODE (SSAVAR (decl)), x);
+ : DECL_MODE (decl), x);
+
+ /* Set alignment we actually gave this decl if it isn't an SSA name.
+ If it is we generate stack slots only accidentally so it isn't as
+ important, we'll simply set the alignment directly on the MEM. */
+
+ if (stack_vars_base_reg_p (base))
+ offset -= frame_phase;
+ align = known_alignment (offset);
+ align *= BITS_PER_UNIT;
+ if (align == 0 || align > base_align)
+ align = base_align;
if (TREE_CODE (decl) != SSA_NAME)
{
- /* Set alignment we actually gave this decl if it isn't an SSA name.
- If it is we generate stack slots only accidentally so it isn't as
- important, we'll simply use the alignment that is already set. */
- if (base == virtual_stack_vars_rtx)
- offset -= frame_phase;
- align = known_alignment (offset);
- align *= BITS_PER_UNIT;
- if (align == 0 || align > base_align)
- align = base_align;
-
/* One would think that we could assert that we're not decreasing
alignment here, but (at least) the i386 port does exactly this
via the MINIMUM_ALIGNMENT hook. */
@@ -1022,6 +1047,8 @@ expand_one_stack_var_at (tree decl, rtx base, unsigned base_align,
}
set_rtl (decl, x);
+
+ set_mem_align (x, align);
}
class stack_vars_data
@@ -1045,13 +1072,13 @@ public:
/* A subroutine of expand_used_vars. Give each partition representative
a unique location within the stack frame. Update each partition member
with that location. */
-
static void
expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
{
size_t si, i, j, n = stack_vars_num;
poly_uint64 large_size = 0, large_alloc = 0;
rtx large_base = NULL;
+ rtx large_untagged_base = NULL;
unsigned large_align = 0;
bool large_allocation_done = false;
tree decl;
@@ -1102,7 +1129,7 @@ expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
{
rtx base;
unsigned base_align, alignb;
- poly_int64 offset;
+ poly_int64 offset = 0;
i = stack_vars_sorted[si];
@@ -1123,10 +1150,33 @@ expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
if (pred && !pred (i))
continue;
+ base = (hwasan_sanitize_stack_p ()
+ ? hwasan_frame_base ()
+ : virtual_stack_vars_rtx);
alignb = stack_vars[i].alignb;
if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
{
- base = virtual_stack_vars_rtx;
+ poly_int64 hwasan_orig_offset;
+ if (hwasan_sanitize_stack_p ())
+ {
+ /* There must be no tag granule "shared" between different
+ objects. This means that no HWASAN_TAG_GRANULE_SIZE byte
+ chunk can have more than one object in it.
+
+ We ensure this by forcing the end of the last bit of data to
+ be aligned to HWASAN_TAG_GRANULE_SIZE bytes here, and setting
+ the start of each variable to be aligned to
+ HWASAN_TAG_GRANULE_SIZE bytes in `align_local_variable`.
+
+ We can't align just one of the start or end, since there are
+ untagged things stored on the stack which we do not align to
+ HWASAN_TAG_GRANULE_SIZE bytes. If we only aligned the start
+ or the end of tagged objects then untagged objects could end
+ up sharing the first granule of a tagged object or sharing the
+ last granule of a tagged object respectively. */
+ hwasan_orig_offset = align_frame_offset (HWASAN_TAG_GRANULE_SIZE);
+ gcc_assert (stack_vars[i].alignb >= HWASAN_TAG_GRANULE_SIZE);
+ }
/* ASAN description strings don't yet have a syntax for expressing
polynomial offsets. */
HOST_WIDE_INT prev_offset;
@@ -1137,7 +1187,7 @@ expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
{
if (data->asan_vec.is_empty ())
{
- alloc_stack_frame_space (0, ASAN_RED_ZONE_SIZE);
+ align_frame_offset (ASAN_RED_ZONE_SIZE);
prev_offset = frame_offset.to_constant ();
}
prev_offset = align_base (prev_offset,
@@ -1205,6 +1255,24 @@ expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
{
offset = alloc_stack_frame_space (stack_vars[i].size, alignb);
base_align = crtl->max_used_stack_slot_alignment;
+
+ if (hwasan_sanitize_stack_p ())
+ {
+ /* Align again since the point of this alignment is to handle
+ the "end" of the object (i.e. smallest address after the
+ stack object). For FRAME_GROWS_DOWNWARD that requires
+ aligning the stack before allocating, but for a frame that
+ grows upwards that requires aligning the stack after
+ allocation.
+
+ Use `frame_offset` to record the offset value rather than
+ `offset` since the `frame_offset` describes the extent
+ allocated for this particular variable while `offset`
+ describes the address that this variable starts at. */
+ align_frame_offset (HWASAN_TAG_GRANULE_SIZE);
+ hwasan_record_stack_var (virtual_stack_vars_rtx, base,
+ hwasan_orig_offset, frame_offset);
+ }
}
}
else
@@ -1225,14 +1293,33 @@ expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
loffset = alloc_stack_frame_space
(rtx_to_poly_int64 (large_allocsize),
PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT);
- large_base = get_dynamic_stack_base (loffset, large_align);
+ large_base = get_dynamic_stack_base (loffset, large_align, base);
large_allocation_done = true;
}
- gcc_assert (large_base != NULL);
+ gcc_assert (large_base != NULL);
large_alloc = aligned_upper_bound (large_alloc, alignb);
offset = large_alloc;
large_alloc += stack_vars[i].size;
+ if (hwasan_sanitize_stack_p ())
+ {
+ /* An object with a large alignment requirement means that the
+ alignment requirement is greater than the required alignment
+ for tags. */
+ if (!large_untagged_base)
+ large_untagged_base
+ = targetm.memtag.untagged_pointer (large_base, NULL_RTX);
+ /* Ensure the end of the variable is also aligned correctly. */
+ poly_int64 align_again
+ = aligned_upper_bound (large_alloc, HWASAN_TAG_GRANULE_SIZE);
+ /* For large allocations we always allocate a chunk of space
+ (which is addressed by large_untagged_base/large_base) and
+ then use positive offsets from that. Hence the farthest
+ offset is `align_again` and the nearest offset from the base
+ is `offset`. */
+ hwasan_record_stack_var (large_untagged_base, large_base,
+ offset, align_again);
+ }
base = large_base;
base_align = large_align;
@@ -1243,9 +1330,10 @@ expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data)
for (j = i; j != EOC; j = stack_vars[j].next)
{
expand_one_stack_var_at (stack_vars[j].decl,
- base, base_align,
- offset);
+ base, base_align, offset);
}
+ if (hwasan_sanitize_stack_p ())
+ hwasan_increment_frame_tag ();
}
gcc_assert (known_eq (large_alloc, large_size));
@@ -1327,21 +1415,46 @@ expand_one_stack_var_1 (tree var)
{
tree type = TREE_TYPE (var);
size = tree_to_poly_uint64 (TYPE_SIZE_UNIT (type));
- byte_align = TYPE_ALIGN_UNIT (type);
}
else
- {
- size = tree_to_poly_uint64 (DECL_SIZE_UNIT (var));
- byte_align = align_local_variable (var, true);
- }
+ size = tree_to_poly_uint64 (DECL_SIZE_UNIT (var));
+
+ byte_align = align_local_variable (var, true);
/* We handle highly aligned variables in expand_stack_vars. */
gcc_assert (byte_align * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT);
- offset = alloc_stack_frame_space (size, byte_align);
+ rtx base;
+ if (hwasan_sanitize_stack_p ())
+ {
+ /* Allocate zero bytes to align the stack. */
+ poly_int64 hwasan_orig_offset
+ = align_frame_offset (HWASAN_TAG_GRANULE_SIZE);
+ offset = alloc_stack_frame_space (size, byte_align);
+ align_frame_offset (HWASAN_TAG_GRANULE_SIZE);
+ base = hwasan_frame_base ();
+ /* Use `frame_offset` to automatically account for machines where the
+ frame grows upwards.
+
+ `offset` will always point to the "start" of the stack object, which
+ will be the smallest address, for ! FRAME_GROWS_DOWNWARD this is *not*
+ the "furthest" offset from the base delimiting the current stack
+ object. `frame_offset` will always delimit the extent that the frame.
+ */
+ hwasan_record_stack_var (virtual_stack_vars_rtx, base,
+ hwasan_orig_offset, frame_offset);
+ }
+ else
+ {
+ offset = alloc_stack_frame_space (size, byte_align);
+ base = virtual_stack_vars_rtx;
+ }
- expand_one_stack_var_at (var, virtual_stack_vars_rtx,
+ expand_one_stack_var_at (var, base,
crtl->max_used_stack_slot_alignment, offset);
+
+ if (hwasan_sanitize_stack_p ())
+ hwasan_increment_frame_tag ();
}
/* Wrapper for expand_one_stack_var_1 that checks SSA_NAMEs are
@@ -1941,6 +2054,8 @@ init_vars_expansion (void)
/* Initialize local stack smashing state. */
has_protected_decls = false;
has_short_buffer = false;
+ if (hwasan_sanitize_stack_p ())
+ hwasan_record_frame_init ();
}
/* Free up stack variable graph data. */
@@ -2268,10 +2383,26 @@ expand_used_vars (void)
expand_stack_vars (NULL, &data);
}
+ if (hwasan_sanitize_stack_p ())
+ hwasan_emit_prologue ();
if (asan_sanitize_allocas_p () && cfun->calls_alloca)
var_end_seq = asan_emit_allocas_unpoison (virtual_stack_dynamic_rtx,
virtual_stack_vars_rtx,
var_end_seq);
+ else if (hwasan_sanitize_allocas_p () && cfun->calls_alloca)
+ /* When using out-of-line instrumentation we only want to emit one function
+ call for clearing the tags in a region of shadow stack. When there are
+ alloca calls in this frame we want to emit a call using the
+ virtual_stack_dynamic_rtx, but when not we use the hwasan_frame_extent
+ rtx we created in expand_stack_vars. */
+ var_end_seq = hwasan_emit_untag_frame (virtual_stack_dynamic_rtx,
+ virtual_stack_vars_rtx);
+ else if (hwasan_sanitize_stack_p ())
+ /* If no variables were stored on the stack, `hwasan_get_frame_extent`
+ will return NULL_RTX and hence `hwasan_emit_untag_frame` will return
+ NULL (i.e. an empty sequence). */
+ var_end_seq = hwasan_emit_untag_frame (hwasan_get_frame_extent (),
+ virtual_stack_vars_rtx);
fini_vars_expansion ();
@@ -3362,20 +3493,21 @@ expand_asm_stmt (gasm *stmt)
ARGVEC CONSTRAINTS OPNAMES))
If there is more than one, put them inside a PARALLEL. */
- if (nlabels > 0 && nclobbers == 0)
- {
- gcc_assert (noutputs == 0);
- emit_jump_insn (body);
- }
- else if (noutputs == 0 && nclobbers == 0)
+ if (noutputs == 0 && nclobbers == 0)
{
/* No output operands: put in a raw ASM_OPERANDS rtx. */
- emit_insn (body);
+ if (nlabels > 0)
+ emit_jump_insn (body);
+ else
+ emit_insn (body);
}
else if (noutputs == 1 && nclobbers == 0)
{
ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0];
- emit_insn (gen_rtx_SET (output_rvec[0], body));
+ if (nlabels > 0)
+ emit_jump_insn (gen_rtx_SET (output_rvec[0], body));
+ else
+ emit_insn (gen_rtx_SET (output_rvec[0], body));
}
else
{
@@ -3452,7 +3584,27 @@ expand_asm_stmt (gasm *stmt)
if (after_md_seq)
emit_insn (after_md_seq);
if (after_rtl_seq)
- emit_insn (after_rtl_seq);
+ {
+ if (nlabels == 0)
+ emit_insn (after_rtl_seq);
+ else
+ {
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
+ {
+ start_sequence ();
+ for (rtx_insn *curr = after_rtl_seq;
+ curr != NULL_RTX;
+ curr = NEXT_INSN (curr))
+ emit_insn (copy_insn (PATTERN (curr)));
+ rtx_insn *copy = get_insns ();
+ end_sequence ();
+ insert_insn_on_edge (copy, e);
+ }
+ }
+ }
free_temp_slots ();
crtl->has_asm_statement = 1;
@@ -3732,11 +3884,10 @@ expand_gimple_stmt_1 (gimple *stmt)
of binary assigns must be a gimple reg. */
if (TREE_CODE (lhs) != SSA_NAME
- || get_gimple_rhs_class (gimple_expr_code (stmt))
- == GIMPLE_SINGLE_RHS)
+ || gimple_assign_rhs_class (assign_stmt) == GIMPLE_SINGLE_RHS)
{
tree rhs = gimple_assign_rhs1 (assign_stmt);
- gcc_assert (get_gimple_rhs_class (gimple_expr_code (stmt))
+ gcc_assert (gimple_assign_rhs_class (assign_stmt)
== GIMPLE_SINGLE_RHS);
if (gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (rhs)
/* Do not put locations on possibly shared trees. */
@@ -5768,7 +5919,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
&& !target_for_debug_bind (var))
goto delink_debug_stmt;
- if (DECL_P (var))
+ if (DECL_P (var) && !VECTOR_TYPE_P (TREE_TYPE (var)))
mode = DECL_MODE (var);
else
mode = TYPE_MODE (TREE_TYPE (var));
@@ -5785,7 +5936,10 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
value = gimple_debug_source_bind_get_value (stmt);
- mode = DECL_MODE (var);
+ if (!VECTOR_TYPE_P (TREE_TYPE (var)))
+ mode = DECL_MODE (var);
+ else
+ mode = TYPE_MODE (TREE_TYPE (var));
val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value,
VAR_INIT_STATUS_UNINITIALIZED);
@@ -5802,14 +5956,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
else if (gimple_debug_begin_stmt_p (stmt))
val = GEN_RTX_DEBUG_MARKER_BEGIN_STMT_PAT ();
else if (gimple_debug_inline_entry_p (stmt))
- {
- tree block = gimple_block (stmt);
-
- if (block)
- val = GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT ();
- else
- goto delink_debug_stmt;
- }
+ val = GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT ();
else
gcc_unreachable ();
@@ -6403,7 +6550,7 @@ pass_expand::execute (function *fun)
rtl_profile_for_bb (ENTRY_BLOCK_PTR_FOR_FN (fun));
insn_locations_init ();
- if (!DECL_IS_BUILTIN (current_function_decl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (current_function_decl))
{
/* Eventually, all FEs should explicitly set function_start_locus. */
if (LOCATION_LOCUS (fun->function_start_locus) == UNKNOWN_LOCATION)
@@ -6612,6 +6759,9 @@ pass_expand::execute (function *fun)
emit_insn_after (var_ret_seq, after);
}
+ if (hwasan_sanitize_stack_p ())
+ hwasan_maybe_emit_frame_base_init ();
+
/* Zap the tree EH table. */
set_eh_throw_stmt_table (fun, NULL);
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index d14689d..438b1f7 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -824,7 +824,7 @@ extern void init_set_costs (void);
/* Loop optimizer initialization. */
extern void loop_optimizer_init (unsigned);
-extern void loop_optimizer_finalize (function *);
+extern void loop_optimizer_finalize (function *, bool = false);
inline void
loop_optimizer_finalize ()
{
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 45d84d3..79f38b7a 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -97,6 +97,7 @@ static basic_block rtl_split_block (basic_block, void *);
static void rtl_dump_bb (FILE *, basic_block, int, dump_flags_t);
static int rtl_verify_flow_info_1 (void);
static void rtl_make_forwarder_block (edge);
+static bool rtl_bb_info_initialized_p (basic_block bb);
/* Return true if NOTE is not one of the ones that must be kept paired,
so that we may simply delete it. */
@@ -2149,7 +2150,8 @@ rtl_dump_bb (FILE *outf, basic_block bb, int indent, dump_flags_t flags)
putc ('\n', outf);
}
- if (bb->index != ENTRY_BLOCK && bb->index != EXIT_BLOCK)
+ if (bb->index != ENTRY_BLOCK && bb->index != EXIT_BLOCK
+ && rtl_bb_info_initialized_p (bb))
{
rtx_insn *last = BB_END (bb);
if (last)
@@ -3417,6 +3419,53 @@ fixup_abnormal_edges (void)
return inserted;
}
+/* Delete the unconditional jump INSN and adjust the CFG correspondingly.
+ Note that the INSN should be deleted *after* removing dead edges, so
+ that the kept edge is the fallthrough edge for a (set (pc) (pc))
+ but not for a (set (pc) (label_ref FOO)). */
+
+void
+update_cfg_for_uncondjump (rtx_insn *insn)
+{
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ gcc_assert (BB_END (bb) == insn);
+
+ purge_dead_edges (bb);
+
+ if (current_ir_type () != IR_RTL_CFGLAYOUT)
+ {
+ if (!find_fallthru_edge (bb->succs))
+ {
+ auto barrier = next_nonnote_nondebug_insn (insn);
+ if (!barrier || !BARRIER_P (barrier))
+ emit_barrier_after (insn);
+ }
+ return;
+ }
+
+ delete_insn (insn);
+ if (EDGE_COUNT (bb->succs) == 1)
+ {
+ rtx_insn *insn;
+
+ single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
+
+ /* Remove barriers from the footer if there are any. */
+ for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
+ if (BARRIER_P (insn))
+ {
+ if (PREV_INSN (insn))
+ SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
+ else
+ BB_FOOTER (bb) = NEXT_INSN (insn);
+ if (NEXT_INSN (insn))
+ SET_PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
+ }
+ else if (LABEL_P (insn))
+ break;
+ }
+}
+
/* Cut the insns from FIRST to LAST out of the insns stream. */
rtx_insn *
@@ -4860,7 +4909,8 @@ rtl_block_empty_p (basic_block bb)
return true;
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn) && !any_uncondjump_p (insn))
+ if (NONDEBUG_INSN_P (insn)
+ && (!any_uncondjump_p (insn) || !onlyjump_p (insn)))
return false;
return true;
@@ -5135,6 +5185,12 @@ init_rtl_bb_info (basic_block bb)
bb->il.x.rtl = ggc_cleared_alloc<rtl_bb_info> ();
}
+static bool
+rtl_bb_info_initialized_p (basic_block bb)
+{
+ return bb->il.x.rtl;
+}
+
/* Returns true if it is possible to remove edge E by redirecting
it to the destination of the other edge from E->src. */
diff --git a/gcc/cfgrtl.h b/gcc/cfgrtl.h
index ae62d6c..1c177d3 100644
--- a/gcc/cfgrtl.h
+++ b/gcc/cfgrtl.h
@@ -47,6 +47,7 @@ extern void fixup_partitions (void);
extern bool purge_dead_edges (basic_block);
extern bool purge_all_dead_edges (void);
extern bool fixup_abnormal_edges (void);
+extern void update_cfg_for_uncondjump (rtx_insn *);
extern rtx_insn *unlink_insn_chain (rtx_insn *, rtx_insn *);
extern void relink_block_chain (bool);
extern rtx_insn *duplicate_insn_chain (rtx_insn *, rtx_insn *,
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index d1a773d..cb59a5a 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-inline.h"
#include "tree-nested.h"
#include "symtab-thunks.h"
+#include "symtab-clones.h"
/* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */
#include "tree-pass.h"
@@ -633,13 +634,20 @@ cgraph_node::create_thunk (tree alias, tree, bool this_adjusting,
node->thunk = true;
node->definition = true;
- thunk_info *i = thunk_info::get_create (node);
+ thunk_info *i;
+ thunk_info local_info;
+ if (symtab->state < CONSTRUCTION)
+ i = &local_info;
+ else
+ i = thunk_info::get_create (node);
i->fixed_offset = fixed_offset;
i->virtual_value = virtual_value;
i->indirect_offset = indirect_offset;
i->alias = real_alias;
i->this_adjusting = this_adjusting;
i->virtual_offset_p = virtual_offset != NULL;
+ if (symtab->state < CONSTRUCTION)
+ i->register_early (node);
return node;
}
@@ -1229,7 +1237,7 @@ cgraph_edge::resolve_speculation (cgraph_edge *edge, tree callee_decl)
{
cgraph_edge *tmp = edge;
if (dump_file)
- fprintf (dump_file, "Speculative call turned into direct call.\n");
+ fprintf (dump_file, "Speculative call turned into direct call.\n");
edge = e2;
e2 = tmp;
/* FIXME: If EDGE is inlined, we should scale up the frequencies
@@ -1481,38 +1489,44 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
return e->call_stmt;
}
}
-
if (flag_checking && decl)
{
- cgraph_node *node = cgraph_node::get (decl);
- gcc_assert (!node || !node->clone.param_adjustments);
+ if (cgraph_node *node = cgraph_node::get (decl))
+ {
+ clone_info *info = clone_info::get (node);
+ gcc_assert (!info || !info->param_adjustments);
+ }
}
+ clone_info *callee_info = clone_info::get (e->callee);
+ clone_info *caller_info = clone_info::get (e->caller);
+
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "updating call of %s -> %s: ",
e->caller->dump_name (), e->callee->dump_name ());
print_gimple_stmt (symtab->dump_file, e->call_stmt, 0, dump_flags);
- if (e->callee->clone.param_adjustments)
- e->callee->clone.param_adjustments->dump (symtab->dump_file);
+ if (callee_info && callee_info->param_adjustments)
+ callee_info->param_adjustments->dump (symtab->dump_file);
unsigned performed_len
- = vec_safe_length (e->caller->clone.performed_splits);
+ = caller_info ? vec_safe_length (caller_info->performed_splits) : 0;
if (performed_len > 0)
fprintf (symtab->dump_file, "Performed splits records:\n");
for (unsigned i = 0; i < performed_len; i++)
{
ipa_param_performed_split *sm
- = &(*e->caller->clone.performed_splits)[i];
+ = &(*caller_info->performed_splits)[i];
print_node_brief (symtab->dump_file, " dummy_decl: ", sm->dummy_decl,
TDF_UID);
fprintf (symtab->dump_file, ", unit_offset: %u\n", sm->unit_offset);
}
}
- if (ipa_param_adjustments *padjs = e->callee->clone.param_adjustments)
+ if (ipa_param_adjustments *padjs
+ = callee_info ? callee_info->param_adjustments : NULL)
{
/* We need to defer cleaning EH info on the new statement to
- fixup-cfg. We may not have dominator information at this point
+ fixup-cfg. We may not have dominator information at this point
and thus would end up with unreachable blocks and have no way
to communicate that we need to run CFG cleanup then. */
int lp_nr = lookup_stmt_eh_lp (e->call_stmt);
@@ -1521,7 +1535,8 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
tree old_fntype = gimple_call_fntype (e->call_stmt);
new_stmt = padjs->modify_call (e->call_stmt,
- e->caller->clone.performed_splits,
+ caller_info
+ ? caller_info->performed_splits : NULL,
e->callee->decl, false);
cgraph_node *origin = e->callee;
while (origin->clone_of)
@@ -1570,7 +1585,7 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
var = get_or_create_ssa_default_def
(DECL_STRUCT_FUNCTION (e->caller->decl), var);
gimple *set_stmt = gimple_build_assign (lhs, var);
- gsi = gsi_for_stmt (new_stmt);
+ gsi = gsi_for_stmt (new_stmt);
gsi_insert_before_without_update (&gsi, set_stmt, GSI_SAME_STMT);
update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), set_stmt);
}
@@ -1696,7 +1711,8 @@ cgraph_update_edges_for_call_stmt (gimple *old_stmt, tree old_decl,
if (orig->clones)
for (node = orig->clones; node != orig;)
{
- cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl, new_stmt);
+ cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl,
+ new_stmt);
if (node->clones)
node = node->clones;
else if (node->next_sibling_clone)
@@ -1795,14 +1811,14 @@ release_function_body (tree decl)
gcc_assert (!dom_info_available_p (fn, CDI_DOMINATORS));
gcc_assert (!dom_info_available_p (fn, CDI_POST_DOMINATORS));
delete_tree_cfg_annotations (fn);
- clear_edges (fn);
+ free_cfg (fn);
fn->cfg = NULL;
}
if (fn->value_histograms)
free_histograms (fn);
gimple_set_body (decl, NULL);
/* Struct function hangs a lot of data that would leak if we didn't
- removed all pointers to it. */
+ removed all pointers to it. */
ggc_free (fn);
DECL_STRUCT_FUNCTION (decl) = NULL;
}
@@ -1844,12 +1860,19 @@ cgraph_node::release_body (bool keep_arguments)
void
cgraph_node::remove (void)
{
+ bool clone_info_set = false;
+ clone_info *info, saved_info;
if (symtab->ipa_clones_dump_file && symtab->cloned_nodes.contains (this))
fprintf (symtab->ipa_clones_dump_file,
"Callgraph removal;%s;%d;%s;%d;%d\n", asm_name (), order,
DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
DECL_SOURCE_COLUMN (decl));
+ if ((info = clone_info::get (this)) != NULL)
+ {
+ saved_info = *info;
+ clone_info_set = true;
+ }
symtab->call_cgraph_removal_hooks (this);
remove_callers ();
remove_callees ();
@@ -1861,7 +1884,7 @@ cgraph_node::remove (void)
force_output = false;
forced_by_abi = false;
- unregister ();
+ unregister (clone_info_set ? &saved_info : NULL);
if (prev_sibling_clone)
prev_sibling_clone->next_sibling_clone = next_sibling_clone;
else if (clone_of)
@@ -1873,7 +1896,7 @@ cgraph_node::remove (void)
cgraph_node *n, *next;
if (clone_of)
- {
+ {
for (n = clones; n->next_sibling_clone; n = n->next_sibling_clone)
n->clone_of = clone_of;
n->clone_of = clone_of;
@@ -1883,7 +1906,7 @@ cgraph_node::remove (void)
clone_of->clones = clones;
}
else
- {
+ {
/* We are removing node with clones. This makes clones inconsistent,
but assume they will be removed subsequently and just keep clone
tree intact. This can happen in unreachable function removal since
@@ -2167,6 +2190,8 @@ cgraph_node::dump (FILE *f)
fprintf (f, " optimize_size");
if (parallelized_function)
fprintf (f, " parallelized_function");
+ if (DECL_IS_MALLOC (decl))
+ fprintf (f, " decl_is_malloc");
if (DECL_IS_OPERATOR_NEW_P (decl))
fprintf (f, " %soperator_new",
DECL_IS_REPLACEABLE_OPERATOR (decl) ? "replaceable_" : "");
@@ -2241,12 +2266,12 @@ cgraph_node::dump (FILE *f)
{
if (edge->indirect_info->polymorphic)
{
- fprintf (f, " Polymorphic indirect call of type ");
+ fprintf (f, " Polymorphic indirect call of type ");
print_generic_expr (f, edge->indirect_info->otr_type, TDF_SLIM);
fprintf (f, " token:%i", (int) edge->indirect_info->otr_token);
}
else
- fprintf (f, " Indirect call");
+ fprintf (f, " Indirect call");
edge->dump_edge_flags (f);
if (edge->indirect_info->param_index != -1)
{
@@ -2343,8 +2368,8 @@ cgraph_node::get_availability (symtab_node *ref)
Also comdat groups are always resolved in groups. */
else if ((this == ref && !has_aliases_p ())
- || (ref && get_comdat_group ()
- && get_comdat_group () == ref->get_comdat_group ()))
+ || (ref && get_comdat_group ()
+ && get_comdat_group () == ref->get_comdat_group ()))
avail = AVAIL_AVAILABLE;
/* Inline functions are safe to be analyzed even if their symbol can
be overwritten at runtime. It is not meaningful to enforce any sane
@@ -2412,7 +2437,7 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
|| (avail = get_availability ()) > AVAIL_INTERPOSABLE)
{
if (callback (this, data))
- return true;
+ return true;
}
FOR_EACH_ALIAS (this, ref)
{
@@ -2607,8 +2632,8 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
{
if (TREE_READONLY (node->decl))
{
- TREE_READONLY (node->decl) = 0;
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+ TREE_READONLY (node->decl) = 0;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
*changed = true;
}
}
@@ -2635,14 +2660,14 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
{
if (!looping && DECL_LOOPING_CONST_OR_PURE_P (node->decl))
{
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
*changed = true;
}
}
else if (node->binds_to_current_def_p ())
{
TREE_READONLY (node->decl) = true;
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
DECL_PURE_P (node->decl) = false;
*changed = true;
}
@@ -2654,12 +2679,12 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
if (!DECL_PURE_P (node->decl))
{
DECL_PURE_P (node->decl) = true;
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
*changed = true;
}
else if (!looping && DECL_LOOPING_CONST_OR_PURE_P (node->decl))
{
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
*changed = true;
}
}
@@ -2678,9 +2703,9 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
{
/* Virtual thunks access virtual offset in the vtable, so they can
only be pure, never const. */
- if (set_const
+ if (set_const
&& (thunk_info::get (e->caller)->virtual_offset_p
- || !node->binds_to_current_def_p (e->caller)))
+ || !node->binds_to_current_def_p (e->caller)))
*changed |= e->caller->set_pure_flag (true, looping);
else
set_const_flag_1 (e->caller, set_const, looping, changed);
@@ -2750,14 +2775,14 @@ set_pure_flag_1 (cgraph_node *node, void *data)
{
if (!DECL_PURE_P (node->decl) && !TREE_READONLY (node->decl))
{
- DECL_PURE_P (node->decl) = true;
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = info->looping;
+ DECL_PURE_P (node->decl) = true;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = info->looping;
info->changed = true;
}
else if (DECL_LOOPING_CONST_OR_PURE_P (node->decl)
&& !info->looping)
{
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
info->changed = true;
}
}
@@ -2765,8 +2790,8 @@ set_pure_flag_1 (cgraph_node *node, void *data)
{
if (DECL_PURE_P (node->decl))
{
- DECL_PURE_P (node->decl) = false;
- DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+ DECL_PURE_P (node->decl) = false;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
info->changed = true;
}
}
@@ -2920,7 +2945,7 @@ cgraph_node::can_remove_if_no_direct_calls_p (bool will_inline)
/* If function is not being inlined, we care only about
references outside of the comdat group. */
if (!will_inline)
- for (int i = 0; next->iterate_referring (i, ref); i++)
+ for (int i = 0; next->iterate_referring (i, ref); i++)
if (ref->referring->get_comdat_group () != get_comdat_group ())
return false;
}
@@ -3024,7 +3049,7 @@ collect_callers_of_node_1 (cgraph_node *node, void *data)
for (cs = node->callers; cs != NULL; cs = cs->next_caller)
if (!cs->indirect_inlining_edge
&& !cs->caller->thunk)
- redirect_callers->safe_push (cs);
+ redirect_callers->safe_push (cs);
return false;
}
@@ -3076,8 +3101,9 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
return true;
node = node->callees->callee->ultimate_alias_target ();
- if (!node2->clone.param_adjustments
- || node2->clone.param_adjustments->first_param_intact_p ())
+ clone_info *info = clone_info::get (node2);
+ if (!info || !info->param_adjustments
+ || info->param_adjustments->first_param_intact_p ())
return false;
if (node2->former_clone_of == node->decl
|| node2->former_clone_of == node->former_clone_of)
@@ -3608,7 +3634,7 @@ cgraph_node::verify_node (void)
if (callees)
{
error ("Alias has call edges");
- error_found = true;
+ error_found = true;
}
for (i = 0; iterate_reference (i, ref); i++)
if (ref->use != IPA_REF_ALIAS)
@@ -3635,18 +3661,18 @@ cgraph_node::verify_node (void)
if (!callees)
{
error ("No edge out of thunk node");
- error_found = true;
+ error_found = true;
}
else if (callees->next_callee)
{
error ("More than one edge out of thunk node");
- error_found = true;
+ error_found = true;
}
if (gimple_has_body_p (decl) && !inlined_to)
- {
+ {
error ("Thunk is not supposed to have body");
- error_found = true;
- }
+ error_found = true;
+ }
}
else if (analyzed && gimple_has_body_p (decl)
&& !TREE_ASM_WRITTEN (decl)
@@ -3991,6 +4017,7 @@ cgraph_c_finalize (void)
{
nested_function_info::release ();
thunk_info::release ();
+ clone_info::release ();
symtab = NULL;
x_cgraph_nodes_queue = NULL;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 9eb48d5..97287bd 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -221,7 +221,7 @@ public:
/* Get number of references for this node. */
inline unsigned num_references (void)
{
- return ref_list.references ? ref_list.references->length () : 0;
+ return ref_list.references.length ();
}
/* Iterates I-th reference in the list, REF is also set. */
@@ -263,7 +263,7 @@ public:
}
/* Return section as string. */
- const char * get_section ()
+ const char * get_section () const
{
if (!x_section)
return NULL;
@@ -322,11 +322,18 @@ public:
/* Set section for symbol and its aliases. */
void set_section (const char *section);
+ /* Like set_section, but copying the section name from another node. */
+ void set_section (const symtab_node &other);
+
/* Set section, do not recurse into aliases.
When one wants to change section of symbol and its aliases,
use set_section. */
void set_section_for_node (const char *section);
+ /* Like set_section_for_node, but copying the section name from another
+ node. */
+ void set_section_for_node (const symtab_node &other);
+
/* Set initialization priority to PRIORITY. */
void set_init_priority (priority_type priority);
@@ -604,7 +611,7 @@ public:
symtab_node *same_comdat_group;
/* Vectors of referring and referenced entities. */
- ipa_ref_list ref_list;
+ ipa_ref_list GTY((skip)) ref_list;
/* Alias target. May be either DECL pointer or ASSEMBLER_NAME pointer
depending to what was known to frontend on the creation time.
@@ -631,7 +638,7 @@ protected:
/* Remove node from symbol table. This function is not used directly, but via
cgraph/varpool node removal routines. */
- void unregister (void);
+ void unregister (struct clone_info *);
/* Return the initialization and finalization priority information for
DECL. If there is no previous priority information, a freshly
@@ -643,8 +650,9 @@ protected:
void *data,
bool include_overwrite);
private:
- /* Worker for set_section. */
- static bool set_section (symtab_node *n, void *s);
+ /* Workers for set_section. */
+ static bool set_section_from_string (symtab_node *n, void *s);
+ static bool set_section_from_node (symtab_node *n, void *o);
/* Worker for symtab_resolve_alias. */
static bool set_implicit_section (symtab_node *n, void *);
@@ -691,27 +699,6 @@ struct GTY(()) ipa_replace_map
int parm_num;
};
-struct GTY(()) cgraph_clone_info
-{
- /* Constants discovered by IPA-CP, i.e. which parameter should be replaced
- with what. */
- vec<ipa_replace_map *, va_gc> *tree_map;
- /* Parameter modification that IPA-SRA decided to perform. */
- ipa_param_adjustments *param_adjustments;
- /* Lists of dummy-decl and offset pairs representing split formal parameters
- in the caller. Offsets of all new replacements are enumerated, those
- coming from the same original parameter have the same dummy decl stored
- along with them.
-
- Dummy decls sit in call statement arguments followed by new parameter
- decls (or their SSA names) in between (caller) clone materialization and
- call redirection. Redirection then recognizes the dummy variable and
- together with the stored offsets can reconstruct what exactly the new
- parameter decls represent and can leave in place only those that the
- callee expects. */
- vec<ipa_param_performed_split, va_gc> *performed_splits;
-};
-
enum cgraph_simd_clone_arg_type
{
SIMD_CLONE_ARG_TYPE_VECTOR,
@@ -780,17 +767,17 @@ struct GTY(()) cgraph_simd_clone_arg {
struct GTY(()) cgraph_simd_clone {
/* Number of words in the SIMD lane associated with this clone. */
- unsigned int simdlen;
+ poly_uint64 simdlen;
/* Number of annotated function arguments in `args'. This is
usually the number of named arguments in FNDECL. */
unsigned int nargs;
/* Max hardware vector size in bits for integral vectors. */
- unsigned int vecsize_int;
+ poly_uint64 vecsize_int;
/* Max hardware vector size in bits for floating point vectors. */
- unsigned int vecsize_float;
+ poly_uint64 vecsize_float;
/* Machine mode of the mask argument(s), if they are to be passed
as bitmasks in integer argument(s). VOIDmode if masks are passed
@@ -879,7 +866,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
next_sibling_clone (NULL), prev_sibling_clone (NULL), clones (NULL),
clone_of (NULL), call_site_hash (NULL), former_clone_of (NULL),
simdclone (NULL), simd_clones (NULL), ipa_transforms_to_apply (vNULL),
- inlined_to (NULL), rtl (NULL), clone (),
+ inlined_to (NULL), rtl (NULL),
count (profile_count::uninitialized ()),
count_materialization_scale (REG_BR_PROB_BASE), profile_id (0),
unit_id (0), tp_first_run (0), thunk (false),
@@ -970,7 +957,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
/* cgraph node being removed from symbol table; see if its entry can be
replaced by other inline clone. */
- cgraph_node *find_replacement (void);
+ cgraph_node *find_replacement (struct clone_info *);
/* Create a new cgraph node which is the new version of
callgraph node. REDIRECT_CALLERS holds the callers
@@ -1279,7 +1266,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
bool check_calls_comdat_local_p ();
/* Return true if function should be optimized for size. */
- bool optimize_for_size_p (void);
+ enum optimize_size_level optimize_for_size_p (void);
/* Dump the callgraph to file F. */
static void dump_cgraph (FILE *f);
@@ -1402,14 +1389,13 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
/* Interprocedural passes scheduled to have their transform functions
applied next time we execute local pass on them. We maintain it
per-function in order to allow IPA passes to introduce new functions. */
- vec<ipa_opt_pass> GTY((skip)) ipa_transforms_to_apply;
+ vec<ipa_opt_pass, va_heap, vl_ptr> GTY((skip)) ipa_transforms_to_apply;
/* For inline clones this points to the function they will be
inlined into. */
cgraph_node *inlined_to;
struct cgraph_rtl_info *rtl;
- cgraph_clone_info clone;
/* Expected number of executions: calculated in profile.c. */
profile_count count;
@@ -2190,10 +2176,16 @@ struct asmname_hasher : ggc_ptr_hash <symtab_node>
static bool equal (symtab_node *n, const_tree t);
};
+/* Core summaries maintained about symbols. */
+
struct thunk_info;
template <class T> class function_summary;
typedef function_summary <thunk_info *> thunk_summary;
+struct clone_info;
+template <class T> class function_summary;
+typedef function_summary <clone_info *> clone_summary;
+
class GTY((tag ("SYMTAB"))) symbol_table
{
public:
@@ -2210,7 +2202,7 @@ public:
function_flags_ready (false), cpp_implicit_aliases_done (false),
section_hash (NULL), assembler_name_hash (NULL), init_priority_hash (NULL),
dump_file (NULL), ipa_clones_dump_file (NULL), cloned_nodes (),
- m_thunks (NULL),
+ m_thunks (NULL), m_clones (NULL),
m_first_edge_removal_hook (NULL), m_first_cgraph_removal_hook (NULL),
m_first_edge_duplicated_hook (NULL), m_first_cgraph_duplicated_hook (NULL),
m_first_cgraph_insertion_hook (NULL), m_first_varpool_insertion_hook (NULL),
@@ -2495,6 +2487,9 @@ public:
/* Thunk annotations. */
thunk_summary *m_thunks;
+ /* Virtual clone annotations. */
+ clone_summary *m_clones;
+
private:
/* Allocate a cgraph_edge structure and fill it with data according to the
parameters of which only CALLEE can be NULL (when creating an indirect
@@ -2689,7 +2684,7 @@ symtab_node::next_defined_symbol (void)
inline ipa_ref *
symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
{
- vec_safe_iterate (ref_list.references, i, &ref);
+ ref_list.references.iterate (i, &ref);
return ref;
}
@@ -3315,15 +3310,17 @@ cgraph_node::mark_force_output (void)
/* Return true if function should be optimized for size. */
-inline bool
+inline enum optimize_size_level
cgraph_node::optimize_for_size_p (void)
{
if (opt_for_fn (decl, optimize_size))
- return true;
+ return OPTIMIZE_SIZE_MAX;
+ if (count == profile_count::zero ())
+ return OPTIMIZE_SIZE_MAX;
if (frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
- return true;
+ return OPTIMIZE_SIZE_BALANCED;
else
- return false;
+ return OPTIMIZE_SIZE_NO;
}
/* Return symtab_node for NODE or create one if it is not present
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 41c6efb..2bf9baf 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -86,6 +86,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-prop.h"
#include "ipa-fnsummary.h"
#include "symtab-thunks.h"
+#include "symtab-clones.h"
/* Create clone of edge in the node N represented by CALL_EXPR
the callgraph. */
@@ -201,16 +202,17 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node)
}
tree new_decl;
- if (node->clone.param_adjustments)
+ clone_info *info = clone_info::get (node);
+ if (info && info->param_adjustments)
{
/* We do not need to duplicate this_adjusting thunks if we have removed
this. */
if (i->this_adjusting
- && !node->clone.param_adjustments->first_param_intact_p ())
+ && !info->param_adjustments->first_param_intact_p ())
return node;
new_decl = copy_node (thunk->decl);
- ipa_param_body_adjustments body_adj (node->clone.param_adjustments,
+ ipa_param_body_adjustments body_adj (info->param_adjustments,
new_decl);
body_adj.modify_formal_parameters ();
}
@@ -237,7 +239,9 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node)
new_thunk->thunk = thunk->thunk;
new_thunk->unique_name = in_lto_p;
new_thunk->former_clone_of = thunk->decl;
- new_thunk->clone.param_adjustments = node->clone.param_adjustments;
+ if (info && info->param_adjustments)
+ clone_info::get_create (new_thunk)->param_adjustments
+ = info->param_adjustments;
new_thunk->unit_id = thunk->unit_id;
new_thunk->merged_comdat = thunk->merged_comdat;
new_thunk->merged_extern_inline = thunk->merged_extern_inline;
@@ -403,13 +407,16 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
new_node->unit_id = unit_id;
new_node->merged_comdat = merged_comdat;
new_node->merged_extern_inline = merged_extern_inline;
+ clone_info *info = clone_info::get (this);
if (param_adjustments)
- new_node->clone.param_adjustments = param_adjustments;
- else
- new_node->clone.param_adjustments = clone.param_adjustments;
- new_node->clone.tree_map = NULL;
- new_node->clone.performed_splits = vec_safe_copy (clone.performed_splits);
+ clone_info::get_create (new_node)->param_adjustments = param_adjustments;
+ else if (info && info->param_adjustments)
+ clone_info::get_create (new_node)->param_adjustments
+ = info->param_adjustments;
+ if (info && info->performed_splits)
+ clone_info::get_create (new_node)->performed_splits
+ = vec_safe_copy (info->performed_splits);
new_node->split_part = split_part;
FOR_EACH_VEC_ELT (redirect_callers, i, e)
@@ -616,9 +623,10 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers,
ABI support for this. */
set_new_clone_decl_and_node_flags (new_node);
new_node->ipcp_clone = ipcp_clone;
- new_node->clone.tree_map = tree_map;
+ if (tree_map)
+ clone_info::get_create (new_node)->tree_map = tree_map;
if (!implicit_section)
- new_node->set_section (get_section ());
+ new_node->set_section (*this);
/* Clones of global symbols or symbols with unique names are unique. */
if ((TREE_PUBLIC (old_decl)
@@ -640,9 +648,10 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers,
}
/* callgraph node being removed from symbol table; see if its entry can be
- replaced by other inline clone. */
+ replaced by other inline clone.
+ INFO is clone info to attach to the new root. */
cgraph_node *
-cgraph_node::find_replacement (void)
+cgraph_node::find_replacement (clone_info *info)
{
cgraph_node *next_inline_clone, *replacement;
@@ -682,7 +691,8 @@ cgraph_node::find_replacement (void)
clones = NULL;
/* Copy clone info. */
- next_inline_clone->clone = clone;
+ if (info)
+ *clone_info::get_create (next_inline_clone) = *info;
/* Now place it into clone tree at same level at NODE. */
next_inline_clone->clone_of = clone_of;
@@ -1050,7 +1060,7 @@ cgraph_node::create_version_clone_with_body
new_version_node->local = 1;
new_version_node->lowered = true;
if (!implicit_section)
- new_version_node->set_section (get_section ());
+ new_version_node->set_section (*this);
/* Clones of global symbols or symbols with unique names are unique. */
if ((TREE_PUBLIC (old_decl)
&& !DECL_EXTERNAL (old_decl)
@@ -1087,6 +1097,7 @@ void cgraph_node::remove_from_clone_tree ()
void
cgraph_node::materialize_clone ()
{
+ clone_info *info = clone_info::get (this);
clone_of->get_untransformed_body ();
former_clone_of = clone_of->decl;
if (clone_of->former_clone_of)
@@ -1096,15 +1107,15 @@ cgraph_node::materialize_clone ()
fprintf (symtab->dump_file, "cloning %s to %s\n",
clone_of->dump_name (),
dump_name ());
- if (clone.tree_map)
+ if (info && info->tree_map)
{
fprintf (symtab->dump_file, " replace map:");
for (unsigned int i = 0;
- i < vec_safe_length (clone.tree_map);
+ i < vec_safe_length (info->tree_map);
i++)
{
ipa_replace_map *replace_info;
- replace_info = (*clone.tree_map)[i];
+ replace_info = (*info->tree_map)[i];
fprintf (symtab->dump_file, "%s %i -> ",
i ? "," : "", replace_info->parm_num);
print_generic_expr (symtab->dump_file,
@@ -1112,12 +1123,14 @@ cgraph_node::materialize_clone ()
}
fprintf (symtab->dump_file, "\n");
}
- if (clone.param_adjustments)
- clone.param_adjustments->dump (symtab->dump_file);
+ if (info && info->param_adjustments)
+ info->param_adjustments->dump (symtab->dump_file);
}
+ clear_stmts_in_references ();
/* Copy the OLD_VERSION_NODE function tree to the new version. */
tree_function_versioning (clone_of->decl, decl,
- clone.tree_map, clone.param_adjustments,
+ info ? info->tree_map : NULL,
+ info ? info->param_adjustments : NULL,
true, NULL, NULL);
if (symtab->dump_file)
{
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index d2d98c8..3a98958 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1155,6 +1155,8 @@ analyze_functions (bool first_time)
symtab->state = CONSTRUCTION;
input_location = UNKNOWN_LOCATION;
+ thunk_info::process_early_thunks ();
+
/* Ugly, but the fixup cannot happen at a time same body alias is created;
C++ FE is confused about the COMDAT groups being right. */
if (symtab->cpp_implicit_aliases_done)
@@ -1600,7 +1602,6 @@ mark_functions_to_output (void)
FOR_EACH_FUNCTION (node)
{
tree decl = node->decl;
- node->clear_stmts_in_references ();
gcc_assert (!node->process || node->same_comdat_group);
if (node->process)
diff --git a/gcc/combine.c b/gcc/combine.c
index 4782e1d..5864474 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2531,42 +2531,6 @@ reg_subword_p (rtx x, rtx reg)
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_INT;
}
-/* Delete the unconditional jump INSN and adjust the CFG correspondingly.
- Note that the INSN should be deleted *after* removing dead edges, so
- that the kept edge is the fallthrough edge for a (set (pc) (pc))
- but not for a (set (pc) (label_ref FOO)). */
-
-static void
-update_cfg_for_uncondjump (rtx_insn *insn)
-{
- basic_block bb = BLOCK_FOR_INSN (insn);
- gcc_assert (BB_END (bb) == insn);
-
- purge_dead_edges (bb);
-
- delete_insn (insn);
- if (EDGE_COUNT (bb->succs) == 1)
- {
- rtx_insn *insn;
-
- single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
-
- /* Remove barriers from the footer if there are any. */
- for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
- if (BARRIER_P (insn))
- {
- if (PREV_INSN (insn))
- SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
- else
- BB_FOOTER (bb) = NEXT_INSN (insn);
- if (NEXT_INSN (insn))
- SET_PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
- }
- else if (LABEL_P (insn))
- break;
- }
-}
-
/* Return whether PAT is a PARALLEL of exactly N register SETs followed
by an arbitrary number of CLOBBERs. */
static bool
@@ -7665,6 +7629,24 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
if (new_rtx != 0)
return gen_rtx_ASHIFT (mode, new_rtx, XEXP (inner, 1));
}
+ else if (GET_CODE (inner) == MULT
+ && CONST_INT_P (XEXP (inner, 1))
+ && pos_rtx == 0 && pos == 0)
+ {
+ /* We're extracting the least significant bits of an rtx
+ (mult X (const_int 2^C)), where LEN > C. Extract the
+ least significant (LEN - C) bits of X, giving an rtx
+ whose mode is MODE, then multiply it by 2^C. */
+ const HOST_WIDE_INT shift_amt = exact_log2 (INTVAL (XEXP (inner, 1)));
+ if (IN_RANGE (shift_amt, 1, len - 1))
+ {
+ new_rtx = make_extraction (mode, XEXP (inner, 0),
+ 0, 0, len - shift_amt,
+ unsignedp, in_dest, in_compare);
+ if (new_rtx)
+ return gen_rtx_MULT (mode, new_rtx, XEXP (inner, 1));
+ }
+ }
else if (GET_CODE (inner) == TRUNCATE
/* If trying or potentionally trying to extract
bits outside of is_mode, don't look through
diff --git a/gcc/common.opt b/gcc/common.opt
index 7e789d1..fcb86c8 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -218,7 +218,7 @@ unsigned int flag_sanitize
; What sanitizers should recover from errors
Variable
-unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)
+unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS | SANITIZE_KERNEL_HWADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)
; What the coverage sanitizers should instrument
Variable
@@ -228,6 +228,10 @@ unsigned int flag_sanitize_coverage
Variable
bool dump_base_name_prefixed = false
+; What subset of registers should be zeroed on function return
+Variable
+unsigned int flag_zero_call_used_regs
+
###
Driver
@@ -294,7 +298,7 @@ Common Driver Var(help_flag)
Display this information.
-help=
-Common Driver Report Joined
+Common Driver Joined
--help=<class> Display descriptions of a specific class of options. <class> is one or more of optimizers, target, warnings, undocumented, params.
-language
@@ -838,6 +842,10 @@ Wvector-operation-performance
Common Var(warn_vector_operation_performance) Warning
Warn when a vector operation is compiled outside the SIMD.
+Wtsan
+Common Var(warn_tsan) Init(1) Warning
+Warn about unsupported features in ThreadSanitizer.
+
Xassembler
Driver Separate
@@ -956,9 +964,13 @@ Driver Undocumented
; 13: Fixes the accidental change in 12 to the calling convention for classes
; with deleted copy constructor and trivial move constructor.
; Default in G++ 8.2.
+;
; 14: Corrects the mangling of nullptr expression.
; Default in G++ 10.
;
+; 15: Changes the mangling of __alignof__ to be distinct from that of alignof.
+; Default in G++ 11.
+;
; Additional positive integers will be assigned as new versions of
; the ABI become the default version of the ABI.
fabi-version=
@@ -966,42 +978,42 @@ Common Joined RejectNegative UInteger Var(flag_abi_version) Init(0)
The version of the C++ ABI in use.
faggressive-loop-optimizations
-Common Report Var(flag_aggressive_loop_optimizations) Optimization Init(1)
+Common Var(flag_aggressive_loop_optimizations) Optimization Init(1)
Aggressively optimize loops using language constraints.
falign-functions
-Common Report Var(flag_align_functions) Optimization
+Common Var(flag_align_functions) Optimization
Align the start of functions.
falign-functions=
Common RejectNegative Joined Var(str_align_functions) Optimization
flimit-function-alignment
-Common Report Var(flag_limit_function_alignment) Optimization Init(0)
+Common Var(flag_limit_function_alignment) Optimization Init(0)
falign-jumps
-Common Report Var(flag_align_jumps) Optimization
+Common Var(flag_align_jumps) Optimization
Align labels which are only reached by jumping.
falign-jumps=
Common RejectNegative Joined Var(str_align_jumps) Optimization
falign-labels
-Common Report Var(flag_align_labels) Optimization
+Common Var(flag_align_labels) Optimization
Align all labels.
falign-labels=
Common RejectNegative Joined Var(str_align_labels) Optimization
falign-loops
-Common Report Var(flag_align_loops) Optimization
+Common Var(flag_align_loops) Optimization
Align the start of loops.
falign-loops=
Common RejectNegative Joined Var(str_align_loops) Optimization
fallow-store-data-races
-Common Report Var(flag_store_data_races) Optimization
+Common Var(flag_store_data_races) Optimization
Allow the compiler to introduce new data races on stores.
fanalyzer
@@ -1025,11 +1037,11 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fsanitize=
-Common Driver Report Joined
+Common Driver Joined
Select what to sanitize.
fsanitize-coverage=
-Common Report Joined
+Common Joined
Select type of coverage sanitization.
fasan-shadow-offset=
@@ -1042,30 +1054,30 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
in user-defined sections.
fsanitize-recover=
-Common Report Joined
+Common Joined
After diagnosing undefined behavior attempt to continue execution.
fsanitize-recover
-Common Report
+Common
This switch is deprecated; use -fsanitize-recover= instead.
fsanitize-address-use-after-scope
-Common Driver Report Var(flag_sanitize_address_use_after_scope) Init(0)
+Common Driver Var(flag_sanitize_address_use_after_scope) Init(0)
fsanitize-undefined-trap-on-error
-Common Driver Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
+Common Driver Var(flag_sanitize_undefined_trap_on_error) Init(0)
Use trap instead of a library function for undefined behavior sanitization.
fasynchronous-unwind-tables
-Common Report Var(flag_asynchronous_unwind_tables) Optimization
+Common Var(flag_asynchronous_unwind_tables) Optimization
Generate unwind tables that are exact at each instruction boundary.
fauto-inc-dec
-Common Report Var(flag_auto_inc_dec) Init(1) Optimization
+Common Var(flag_auto_inc_dec) Init(1) Optimization
Generate auto-inc/dec instructions.
fauto-profile
-Common Report Var(flag_auto_profile)
+Common Var(flag_auto_profile)
Use sample profile information for call graph node weights. The default
profile file is fbdata.afdo in 'pwd'.
@@ -1079,15 +1091,15 @@ file is specified in the argument.
; For Java: defaults to on.
; For Fortran: defaults to off.
fbounds-check
-Common Report Var(flag_bounds_check)
+Common Var(flag_bounds_check)
Generate code to check bounds before indexing arrays.
fbranch-count-reg
-Common Report Var(flag_branch_on_count_reg) Optimization
+Common Var(flag_branch_on_count_reg) Optimization
Replace add, compare, branch with branch on count register.
fbranch-probabilities
-Common Report Var(flag_branch_probabilities) Optimization
+Common Var(flag_branch_probabilities) Optimization
Use profiling information for branch probabilities.
fbranch-target-load-optimize
@@ -1103,11 +1115,11 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fcallgraph-info
-Common Report RejectNegative Var(flag_callgraph_info) Init(NO_CALLGRAPH_INFO);
+Common RejectNegative Var(flag_callgraph_info) Init(NO_CALLGRAPH_INFO);
Output callgraph information on a per-file basis.
fcallgraph-info=
-Common Report RejectNegative Joined
+Common RejectNegative Joined
Output callgraph information on a per-file basis with decorations.
fcall-saved-
@@ -1122,7 +1134,7 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
; be saved across function calls, if that produces overall better code.
; Optional now, so people can test it.
fcaller-saves
-Common Report Var(flag_caller_saves) Optimization
+Common Var(flag_caller_saves) Optimization
Save registers around function calls.
fcheck-data-deps
@@ -1142,15 +1154,15 @@ Common Joined RejectNegative UInteger Var(flag_checking)
Perform internal consistency checkings.
fcode-hoisting
-Common Report Var(flag_code_hoisting) Optimization
+Common Var(flag_code_hoisting) Optimization
Enable code hoisting.
fcombine-stack-adjustments
-Common Report Var(flag_combine_stack_adjustments) Optimization
+Common Var(flag_combine_stack_adjustments) Optimization
Looks for opportunities to reduce stack adjustments and stack references.
fcommon
-Common Report Var(flag_no_common,0) Init(1)
+Common Var(flag_no_common,0) Init(1)
Put uninitialized globals in the common section.
fcompare-debug
@@ -1166,7 +1178,7 @@ Common Driver RejectNegative Var(flag_compare_debug)
Run only the second compilation of -fcompare-debug.
fcompare-elim
-Common Report Var(flag_compare_elim_after_reload) Optimization
+Common Var(flag_compare_elim_after_reload) Optimization
Perform comparison elimination after register allocation has finished.
fconserve-stack
@@ -1174,15 +1186,15 @@ Common Var(flag_conserve_stack) Optimization
Do not perform optimizations increasing noticeably stack usage.
fcprop-registers
-Common Report Var(flag_cprop_registers) Optimization
+Common Var(flag_cprop_registers) Optimization
Perform a register copy-propagation optimization pass.
fcrossjumping
-Common Report Var(flag_crossjumping) Optimization
+Common Var(flag_crossjumping) Optimization
Perform cross-jumping optimization.
fcse-follow-jumps
-Common Report Var(flag_cse_follow_jumps) Optimization
+Common Var(flag_cse_follow_jumps) Optimization
When running CSE, follow jumps to their targets.
fcse-skip-blocks
@@ -1190,19 +1202,19 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fcx-limited-range
-Common Report Var(flag_cx_limited_range) Optimization SetByCombined
+Common Var(flag_cx_limited_range) Optimization SetByCombined
Omit range reduction step when performing complex division.
fcx-fortran-rules
-Common Report Var(flag_cx_fortran_rules) Optimization
+Common Var(flag_cx_fortran_rules) Optimization
Complex multiplication and division follow Fortran rules.
fdata-sections
-Common Report Var(flag_data_sections)
+Common Var(flag_data_sections)
Place data items into their own section.
fdbg-cnt-list
-Common Report Var(flag_dbg_cnt_list)
+Common Var(flag_dbg_cnt_list)
List all available debugging counters with their limits and counts.
fdbg-cnt=
@@ -1218,37 +1230,37 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
-ffile-prefix-map=<old>=<new> Map one directory name to another in compilation result.
fdebug-types-section
-Common Report Var(flag_debug_types_section) Init(0)
+Common Var(flag_debug_types_section) Init(0)
Output .debug_types section when using DWARF v4 debuginfo.
; Nonzero for -fdefer-pop: don't pop args after each function call
; instead save them up to pop many calls' args with one insns.
fdefer-pop
-Common Report Var(flag_defer_pop) Optimization
+Common Var(flag_defer_pop) Optimization
Defer popping functions args from stack until later.
fdelayed-branch
-Common Report Var(flag_delayed_branch) Optimization
+Common Var(flag_delayed_branch) Optimization
Attempt to fill delay slots of branch instructions.
fdelete-dead-exceptions
-Common Report Var(flag_delete_dead_exceptions) Init(0) Optimization
+Common Var(flag_delete_dead_exceptions) Init(0) Optimization
Delete dead instructions that may throw exceptions.
fdelete-null-pointer-checks
-Common Report Var(flag_delete_null_pointer_checks) Init(-1) Optimization
+Common Var(flag_delete_null_pointer_checks) Init(-1) Optimization
Delete useless null pointer checks.
fdevirtualize-at-ltrans
-Common Report Var(flag_ltrans_devirtualize)
+Common Var(flag_ltrans_devirtualize)
Stream extra data to support more aggressive devirtualization in LTO local transformation mode.
fdevirtualize-speculatively
-Common Report Var(flag_devirtualize_speculatively) Optimization
+Common Var(flag_devirtualize_speculatively) Optimization
Perform speculative devirtualization.
fdevirtualize
-Common Report Var(flag_devirtualize) Optimization
+Common Var(flag_devirtualize) Optimization
Try to convert virtual calls to direct ones.
fdiagnostics-show-location=
@@ -1430,7 +1442,7 @@ Common RejectNegative Joined Var(flag_dump_go_spec)
-fdump-go-spec=filename Write all declarations to file as Go code.
fdump-noaddr
-Common Report Var(flag_dump_noaddr)
+Common Var(flag_dump_noaddr)
Suppress output of addresses in debugging dumps.
freport-bug
@@ -1447,19 +1459,19 @@ Common Var(flag_dump_passes) Init(0)
Dump optimization passes.
fdump-unnumbered
-Common Report Var(flag_dump_unnumbered)
+Common Var(flag_dump_unnumbered)
Suppress output of instruction numbers, line number notes and addresses in debugging dumps.
fdump-unnumbered-links
-Common Report Var(flag_dump_unnumbered_links)
+Common Var(flag_dump_unnumbered_links)
Suppress output of previous and next insn numbers in debugging dumps.
fdwarf2-cfi-asm
-Common Report Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
+Common Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
Enable CFI tables via GAS assembler directives.
fearly-inlining
-Common Report Var(flag_early_inlining) Init(1) Optimization
+Common Var(flag_early_inlining) Init(1) Optimization
Perform early inlining.
feliminate-dwarf2-dups
@@ -1467,27 +1479,27 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fipa-sra
-Common Report Var(flag_ipa_sra) Init(0) Optimization
+Common Var(flag_ipa_sra) Init(0) Optimization
Perform interprocedural reduction of aggregates.
feliminate-unused-debug-symbols
-Common Report Var(flag_debug_only_used_symbols) Init(1)
+Common Var(flag_debug_only_used_symbols) Init(1)
Perform unused symbol elimination in debug info.
feliminate-unused-debug-types
-Common Report Var(flag_eliminate_unused_debug_types) Init(1)
+Common Var(flag_eliminate_unused_debug_types) Init(1)
Perform unused type elimination in debug info.
femit-class-debug-always
-Common Report Var(flag_emit_class_debug_always) Init(0)
+Common Var(flag_emit_class_debug_always) Init(0)
Do not suppress C++ class debug information.
fexceptions
-Common Report Var(flag_exceptions) Optimization
+Common Var(flag_exceptions) Optimization
Enable exception handling.
fexpensive-optimizations
-Common Report Var(flag_expensive_optimizations) Optimization
+Common Var(flag_expensive_optimizations) Optimization
Perform a number of minor, expensive optimizations.
fexcess-precision=
@@ -1526,11 +1538,11 @@ Common Var(flag_fat_lto_objects)
Output lto objects containing both the intermediate language and binary output.
ffinite-math-only
-Common Report Var(flag_finite_math_only) Optimization SetByCombined
+Common Var(flag_finite_math_only) Optimization SetByCombined
Assume no NaNs or infinities are generated.
ffinite-loops
-Common Report Var(flag_finite_loops) Optimization Init(0)
+Common Var(flag_finite_loops) Optimization Init(0)
Assume that loops with an exit will terminate and not loop indefinitely.
ffixed-
@@ -1538,7 +1550,7 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
-ffixed-<register> Mark <register> as being unavailable to the compiler.
ffloat-store
-Common Report Var(flag_float_store) Optimization
+Common Var(flag_float_store) Optimization
Don't allocate floats and doubles in extended-precision registers.
fforce-addr
@@ -1546,7 +1558,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fforward-propagate
-Common Report Var(flag_forward_propagate) Optimization
+Common Var(flag_forward_propagate) Optimization
Perform a forward propagation pass on RTL.
ffp-contract=
@@ -1567,39 +1579,39 @@ EnumValue
Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
ffp-int-builtin-inexact
-Common Report Var(flag_fp_int_builtin_inexact) Init(1) Optimization
+Common Var(flag_fp_int_builtin_inexact) Init(1) Optimization
Allow built-in functions ceil, floor, round, trunc to raise \"inexact\" exceptions.
; Nonzero means don't put addresses of constant functions in registers.
; Used for compiling the Unix kernel, where strange substitutions are
; done on the assembly output.
ffunction-cse
-Common Report Var(flag_no_function_cse,0) Optimization
+Common Var(flag_no_function_cse,0) Optimization
Allow function addresses to be held in registers.
ffunction-sections
-Common Report Var(flag_function_sections)
+Common Var(flag_function_sections)
Place each function into its own section.
fgcse
-Common Report Var(flag_gcse) Optimization
+Common Var(flag_gcse) Optimization
Perform global common subexpression elimination.
fgcse-lm
-Common Report Var(flag_gcse_lm) Init(1) Optimization
+Common Var(flag_gcse_lm) Init(1) Optimization
Perform enhanced load motion during global common subexpression elimination.
fgcse-sm
-Common Report Var(flag_gcse_sm) Init(0) Optimization
+Common Var(flag_gcse_sm) Init(0) Optimization
Perform store motion after global common subexpression elimination.
fgcse-las
-Common Report Var(flag_gcse_las) Init(0) Optimization
+Common Var(flag_gcse_las) Init(0) Optimization
Perform redundant load after store elimination in global common subexpression
elimination.
fgcse-after-reload
-Common Report Var(flag_gcse_after_reload) Optimization
+Common Var(flag_gcse_after_reload) Optimization
Perform global common subexpression elimination after register allocation has
finished.
@@ -1616,34 +1628,34 @@ EnumValue
Enum(dwarf_gnat_encodings) String(minimal) Value(DWARF_GNAT_ENCODINGS_MINIMAL)
fgnat-encodings=
-Common Enum(dwarf_gnat_encodings) Joined RejectNegative Report Undocumented Var(gnat_encodings)
+Common Enum(dwarf_gnat_encodings) Joined RejectNegative Undocumented Var(gnat_encodings)
-fgnat-encodings=[all|gdb|minimal] Select the balance between GNAT encodings and standard DWARF emitted in the debug information.
; This option is not documented yet as its semantics will change.
fgraphite
-Common Report Var(flag_graphite) Optimization
+Common Var(flag_graphite) Optimization
Enable in and out of Graphite representation.
fgraphite-identity
-Common Report Var(flag_graphite_identity) Optimization
+Common Var(flag_graphite_identity) Optimization
Enable Graphite Identity transformation.
fhoist-adjacent-loads
-Common Report Var(flag_hoist_adjacent_loads) Optimization
+Common Var(flag_hoist_adjacent_loads) Optimization
Enable hoisting adjacent loads to encourage generating conditional move
instructions.
fkeep-gc-roots-live
-Common Undocumented Report Var(flag_keep_gc_roots_live) Optimization
+Common Undocumented Var(flag_keep_gc_roots_live) Optimization
; Always keep a pointer to a live memory block
flarge-source-files
-Common Report Var(flag_large_source_files) Init(0)
+Common Var(flag_large_source_files) Init(0)
Improve GCC's ability to track column numbers in large source files,
at the expense of slower compilation.
floop-parallelize-all
-Common Report Var(flag_loop_parallelize_all) Optimization
+Common Var(flag_loop_parallelize_all) Optimization
Mark all loops as parallel.
floop-strip-mine
@@ -1651,7 +1663,7 @@ Common Alias(floop-nest-optimize)
Enable loop nest transforms. Same as -floop-nest-optimize.
floop-interchange
-Common Report Var(flag_loop_interchange) Optimization
+Common Var(flag_loop_interchange) Optimization
Enable loop interchange on trees.
floop-block
@@ -1659,15 +1671,15 @@ Common Alias(floop-nest-optimize)
Enable loop nest transforms. Same as -floop-nest-optimize.
floop-unroll-and-jam
-Common Report Var(flag_unroll_jam) Optimization
+Common Var(flag_unroll_jam) Optimization
Perform unroll-and-jam on loops.
fgnu-tm
-Common Report Var(flag_tm)
+Common Var(flag_tm)
Enable support for GNU transactional memory.
fgnu-unique
-Common Report Var(flag_gnu_unique) Init(1)
+Common Var(flag_gnu_unique) Init(1)
Use STB_GNU_UNIQUE if supported by the assembler.
floop-flatten
@@ -1675,19 +1687,19 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
floop-nest-optimize
-Common Report Var(flag_loop_nest_optimize) Optimization
+Common Var(flag_loop_nest_optimize) Optimization
Enable the loop nest optimizer.
fstrict-volatile-bitfields
-Common Report Var(flag_strict_volatile_bitfields) Init(-1) Optimization
+Common Var(flag_strict_volatile_bitfields) Init(-1) Optimization
Force bitfield accesses to match their type width.
fstore-merging
-Common Report Var(flag_store_merging) Optimization
+Common Var(flag_store_merging) Optimization
Merge adjacent stores.
fguess-branch-probability
-Common Report Var(flag_guess_branch_prob) Optimization
+Common Var(flag_guess_branch_prob) Optimization
Enable guessing of branch probabilities.
; Nonzero means ignore `#ident' directives. 0 means handle them.
@@ -1695,15 +1707,15 @@ Enable guessing of branch probabilities.
; On SVR4 targets, it also controls whether or not to emit a
; string identifying the compiler.
fident
-Common Report Var(flag_no_ident,0)
+Common Var(flag_no_ident,0)
Process #ident directives.
fif-conversion
-Common Report Var(flag_if_conversion) Optimization
+Common Var(flag_if_conversion) Optimization
Perform conversion of conditional jumps to branchless equivalents.
fif-conversion2
-Common Report Var(flag_if_conversion2) Optimization
+Common Var(flag_if_conversion2) Optimization
Perform conversion of conditional jumps to conditional execution.
fstack-reuse=
@@ -1723,7 +1735,7 @@ EnumValue
Enum(stack_reuse_level) String(none) Value(SR_NONE)
ftree-loop-if-convert
-Common Report Var(flag_tree_loop_if_convert) Init(-1) Optimization
+Common Var(flag_tree_loop_if_convert) Init(-1) Optimization
Convert conditional jumps in innermost loops to branchless equivalents.
ftree-loop-if-convert-stores
@@ -1735,29 +1747,29 @@ Does nothing. Preserved for backward compatibility.
; and it may be extended to other effects
; needed for crtstuff.c on other systems.
finhibit-size-directive
-Common Report Var(flag_inhibit_size_directive)
+Common Var(flag_inhibit_size_directive)
Do not generate .size directives.
findirect-inlining
-Common Report Var(flag_indirect_inlining) Optimization
+Common Var(flag_indirect_inlining) Optimization
Perform indirect inlining.
; General flag to enable inlining. Specifying -fno-inline will disable
; all inlining apart from always-inline functions.
finline
-Common Report Var(flag_no_inline,0) Init(0) Optimization
+Common Var(flag_no_inline,0) Init(0) Optimization
Enable inlining of function declared \"inline\", disabling disables all inlining.
finline-small-functions
-Common Report Var(flag_inline_small_functions) Optimization
+Common Var(flag_inline_small_functions) Optimization
Integrate functions into their callers when code size is known not to grow.
finline-functions
-Common Report Var(flag_inline_functions) Optimization
+Common Var(flag_inline_functions) Optimization
Integrate functions not declared \"inline\" into their callers when profitable.
finline-functions-called-once
-Common Report Var(flag_inline_functions_called_once) Optimization
+Common Var(flag_inline_functions_called_once) Optimization
Integrate functions only required by their single caller.
finline-limit-
@@ -1768,14 +1780,14 @@ Common RejectNegative Joined UInteger
-finline-limit=<number> Limit the size of inlined functions to <number>.
finline-atomics
-Common Report Var(flag_inline_atomics) Init(1) Optimization
+Common Var(flag_inline_atomics) Init(1) Optimization
Inline __atomic operations when a lock free instruction sequence is available.
fcf-protection
Common RejectNegative Alias(fcf-protection=,full)
fcf-protection=
-Common Report Joined RejectNegative Enum(cf_protection_level) Var(flag_cf_protection) Init(CF_NONE)
+Common Joined RejectNegative Enum(cf_protection_level) Var(flag_cf_protection) Init(CF_NONE)
-fcf-protection=[full|branch|return|none|check] Instrument functions with checks to verify jump/call/return control-flow transfer
instructions have valid targets.
@@ -1798,7 +1810,7 @@ EnumValue
Enum(cf_protection_level) String(none) Value(CF_NONE)
finstrument-functions
-Common Report Var(flag_instrument_function_entry_exit)
+Common Var(flag_instrument_function_entry_exit)
Instrument function entry and exit with profiling calls.
finstrument-functions-exclude-function-list=
@@ -1810,11 +1822,11 @@ Common RejectNegative Joined
-finstrument-functions-exclude-file-list=filename,... Do not instrument functions listed in files.
fipa-cp
-Common Report Var(flag_ipa_cp) Optimization
+Common Var(flag_ipa_cp) Optimization
Perform interprocedural constant propagation.
fipa-cp-clone
-Common Report Var(flag_ipa_cp_clone) Optimization
+Common Var(flag_ipa_cp_clone) Optimization
Perform cloning to make Interprocedural constant propagation stronger.
fipa-cp-alignment
@@ -1822,47 +1834,47 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fipa-bit-cp
-Common Report Var(flag_ipa_bit_cp) Optimization
+Common Var(flag_ipa_bit_cp) Optimization
Perform interprocedural bitwise constant propagation.
fipa-modref
-Common Report Var(flag_ipa_modref) Optimization
+Common Var(flag_ipa_modref) Optimization
Perform interprocedural modref analysis.
fipa-profile
-Common Report Var(flag_ipa_profile) Init(0) Optimization
+Common Var(flag_ipa_profile) Init(0) Optimization
Perform interprocedural profile propagation.
fipa-pta
-Common Report Var(flag_ipa_pta) Init(0) Optimization
+Common Var(flag_ipa_pta) Init(0) Optimization
Perform interprocedural points-to analysis.
fipa-pure-const
-Common Report Var(flag_ipa_pure_const) Init(0) Optimization
+Common Var(flag_ipa_pure_const) Init(0) Optimization
Discover pure and const functions.
fipa-icf
-Common Report Var(flag_ipa_icf) Optimization
+Common Var(flag_ipa_icf) Optimization
Perform Identical Code Folding for functions and read-only variables.
fipa-icf-functions
-Common Report Var(flag_ipa_icf_functions) Optimization
+Common Var(flag_ipa_icf_functions) Optimization
Perform Identical Code Folding for functions.
fipa-icf-variables
-Common Report Var(flag_ipa_icf_variables) Optimization
+Common Var(flag_ipa_icf_variables) Optimization
Perform Identical Code Folding for variables.
fipa-reference
-Common Report Var(flag_ipa_reference) Init(0) Optimization
+Common Var(flag_ipa_reference) Init(0) Optimization
Discover read-only and non addressable static variables.
fipa-reference-addressable
-Common Report Var(flag_ipa_reference_addressable) Init(0) Optimization
+Common Var(flag_ipa_reference_addressable) Init(0) Optimization
Discover read-only, write-only and non-addressable static variables.
fipa-stack-alignment
-Common Report Var(flag_ipa_stack_alignment) Init(1) Optimization
+Common Var(flag_ipa_stack_alignment) Init(1) Optimization
Reduce stack alignment on call sites if possible.
fipa-matrix-reorg
@@ -1874,7 +1886,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fipa-vrp
-Common Report Var(flag_ipa_vrp) Optimization
+Common Var(flag_ipa_vrp) Optimization
Perform IPA Value Range Propagation.
fira-algorithm=
@@ -1907,21 +1919,21 @@ EnumValue
Enum(ira_region) String(mixed) Value(IRA_REGION_MIXED)
fira-hoist-pressure
-Common Report Var(flag_ira_hoist_pressure) Init(1) Optimization
+Common Var(flag_ira_hoist_pressure) Init(1) Optimization
Use IRA based register pressure calculation
in RTL hoist optimizations.
fira-loop-pressure
-Common Report Var(flag_ira_loop_pressure) Optimization
+Common Var(flag_ira_loop_pressure) Optimization
Use IRA based register pressure calculation
in RTL loop optimizations.
fira-share-save-slots
-Common Report Var(flag_ira_share_save_slots) Init(1) Optimization
+Common Var(flag_ira_share_save_slots) Init(1) Optimization
Share slots for saving different hard registers.
fira-share-spill-slots
-Common Report Var(flag_ira_share_spill_slots) Init(1) Optimization
+Common Var(flag_ira_share_spill_slots) Init(1) Optimization
Share stack slots for spilled pseudo-registers.
fira-verbose=
@@ -1929,27 +1941,31 @@ Common RejectNegative Joined UInteger Var(flag_ira_verbose) Init(5)
-fira-verbose=<number> Control IRA's level of diagnostic messages.
fivopts
-Common Report Var(flag_ivopts) Init(1) Optimization
+Common Var(flag_ivopts) Init(1) Optimization
Optimize induction variables on trees.
fjump-tables
Common Var(flag_jump_tables) Init(1) Optimization
Use jump tables for sufficiently large switch statements.
+fbit-tests
+Common Var(flag_bit_tests) Init(1) Optimization
+Use bit tests for sufficiently large switch statements.
+
fkeep-inline-functions
-Common Report Var(flag_keep_inline_functions)
+Common Var(flag_keep_inline_functions)
Generate code for functions even if they are fully inlined.
fkeep-static-functions
-Common Report Var(flag_keep_static_functions)
+Common Var(flag_keep_static_functions)
Generate code for static functions even if they are never called.
fkeep-static-consts
-Common Report Var(flag_keep_static_consts) Init(1)
+Common Var(flag_keep_static_consts) Init(1)
Emit static const variables even if they are not used.
fleading-underscore
-Common Report Var(flag_leading_underscore) Init(-1)
+Common Var(flag_leading_underscore) Init(-1)
Give external symbols a leading underscore.
floop-optimize
@@ -1957,7 +1973,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
flra-remat
-Common Report Var(flag_lra_remat) Optimization
+Common Var(flag_lra_remat) Optimization
Do CFG-sensitive rematerialization in LRA.
flto
@@ -2000,15 +2016,15 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
flto-report
-Common Report Var(flag_lto_report) Init(0)
+Common Var(flag_lto_report) Init(0)
Report various link-time optimization statistics.
flto-report-wpa
-Common Report Var(flag_lto_report_wpa) Init(0)
+Common Var(flag_lto_report_wpa) Init(0)
Report various link-time optimization statistics for WPA only.
fmath-errno
-Common Report Var(flag_errno_math) Init(1) Optimization SetByCombined
+Common Var(flag_errno_math) Init(1) Optimization SetByCombined
Set errno after built-in math functions.
fmax-errors=
@@ -2016,26 +2032,26 @@ Common Joined RejectNegative UInteger Var(flag_max_errors)
-fmax-errors=<number> Maximum number of errors to report.
fmem-report
-Common Report Var(mem_report)
+Common Var(mem_report)
Report on permanent memory allocation.
fmem-report-wpa
-Common Report Var(mem_report_wpa)
+Common Var(mem_report_wpa)
Report on permanent memory allocation in WPA only.
; This will attempt to merge constant section constants, if 1 only
; string constants and constants from constant pool, if 2 also constant
; variables.
fmerge-all-constants
-Common Report Var(flag_merge_constants,2) Init(1)
+Common Var(flag_merge_constants,2) Init(1)
Attempt to merge identical constants and constant variables.
fmerge-constants
-Common Report Var(flag_merge_constants,1)
+Common Var(flag_merge_constants,1)
Attempt to merge identical constants across compilation units.
fmerge-debug-strings
-Common Report Var(flag_merge_debug_strings) Init(1)
+Common Var(flag_merge_debug_strings) Init(1)
Attempt to merge identical debug strings across compilation units.
fmessage-length=
@@ -2043,15 +2059,15 @@ Common RejectNegative Joined UInteger
-fmessage-length=<number> Limit diagnostics to <number> characters per line. 0 suppresses line-wrapping.
fmodulo-sched
-Common Report Var(flag_modulo_sched) Optimization
+Common Var(flag_modulo_sched) Optimization
Perform SMS based modulo scheduling before the first scheduling pass.
fmodulo-sched-allow-regmoves
-Common Report Var(flag_modulo_sched_allow_regmoves) Optimization
+Common Var(flag_modulo_sched_allow_regmoves) Optimization
Perform SMS based modulo scheduling with register moves allowed.
fmove-loop-invariants
-Common Report Var(flag_move_loop_invariants) Optimization
+Common Var(flag_move_loop_invariants) Optimization
Move loop invariant computations out of loops.
fdce
@@ -2063,11 +2079,11 @@ Common Var(flag_dse) Init(0) Optimization
Use the RTL dead store elimination pass.
freschedule-modulo-scheduled-loops
-Common Report Var(flag_resched_modulo_sched) Optimization
+Common Var(flag_resched_modulo_sched) Optimization
Enable/Disable the traditional scheduling in loops that already passed modulo scheduling.
fnon-call-exceptions
-Common Report Var(flag_non_call_exceptions) Optimization
+Common Var(flag_non_call_exceptions) Optimization
Support synchronous non-call exceptions.
foffload=
@@ -2088,11 +2104,11 @@ EnumValue
Enum(offload_abi) String(lp64) Value(OFFLOAD_ABI_LP64)
fomit-frame-pointer
-Common Report Var(flag_omit_frame_pointer) Optimization
+Common Var(flag_omit_frame_pointer) Optimization
When possible do not generate stack frames.
fopt-info
-Common Report Var(flag_opt_info) Optimization
+Common Var(flag_opt_info) Optimization
Enable all optimization info dumps on stderr.
fopt-info-
@@ -2100,7 +2116,7 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
-fopt-info[-<type>=filename] Dump compiler optimization details.
fsave-optimization-record
-Common Report Var(flag_save_optimization_record) Optimization
+Common Var(flag_save_optimization_record) Optimization
Write a SRCFILE.opt-record.json file detailing what optimizations were performed.
foptimize-register-move
@@ -2108,23 +2124,23 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
foptimize-sibling-calls
-Common Report Var(flag_optimize_sibling_calls) Optimization
+Common Var(flag_optimize_sibling_calls) Optimization
Optimize sibling and tail recursive calls.
fpartial-inlining
-Common Report Var(flag_partial_inlining) Optimization
+Common Var(flag_partial_inlining) Optimization
Perform partial inlining.
fpre-ipa-mem-report
-Common Report Var(pre_ipa_mem_report)
+Common Var(pre_ipa_mem_report)
Report on memory allocation before interprocedural optimization.
fpost-ipa-mem-report
-Common Report Var(post_ipa_mem_report)
+Common Var(post_ipa_mem_report)
Report on memory allocation before interprocedural optimization.
fpack-struct
-Common Report Var(flag_pack_struct) Optimization
+Common Var(flag_pack_struct) Optimization
Pack structure members together without holes.
fpack-struct=
@@ -2132,39 +2148,39 @@ Common RejectNegative Joined UInteger Optimization
-fpack-struct=<number> Set initial maximum structure member alignment.
fpcc-struct-return
-Common Report Var(flag_pcc_struct_return,1) Init(DEFAULT_PCC_STRUCT_RETURN)
+Common Var(flag_pcc_struct_return,1) Init(DEFAULT_PCC_STRUCT_RETURN)
Return small aggregates in memory, not registers.
fpeel-loops
-Common Report Var(flag_peel_loops) Optimization
+Common Var(flag_peel_loops) Optimization
Perform loop peeling.
fpeephole
-Common Report Var(flag_no_peephole,0) Optimization
+Common Var(flag_no_peephole,0) Optimization
Enable machine specific peephole optimizations.
fpeephole2
-Common Report Var(flag_peephole2) Optimization
+Common Var(flag_peephole2) Optimization
Enable an RTL peephole pass before sched2.
fPIC
-Common Report Var(flag_pic,2) Negative(fPIE) Init(-1)
+Common Var(flag_pic,2) Negative(fPIE) Init(-1)
Generate position-independent code if possible (large mode).
fPIE
-Common Report Var(flag_pie,2) Negative(fpic) Init(-1)
+Common Var(flag_pie,2) Negative(fpic) Init(-1)
Generate position-independent code for executables if possible (large mode).
fpic
-Common Report Var(flag_pic,1) Negative(fpie) Init(-1)
+Common Var(flag_pic,1) Negative(fpie) Init(-1)
Generate position-independent code if possible (small mode).
fpie
-Common Report Var(flag_pie,1) Negative(fPIC) Init(-1)
+Common Var(flag_pie,1) Negative(fPIC) Init(-1)
Generate position-independent code for executables if possible (small mode).
fplt
-Common Report Var(flag_plt) Init(1) Optimization
+Common Var(flag_plt) Init(1) Optimization
Use PLT for PIC calls (-fno-plt: load the address from GOT at call site).
fplugin=
@@ -2176,23 +2192,23 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
-fplugin-arg-<name>-<key>[=<value>] Specify argument <key>=<value> for plugin <name>.
fpredictive-commoning
-Common Report Var(flag_predictive_commoning) Optimization
+Common Var(flag_predictive_commoning) Optimization
Run predictive commoning optimization.
fprefetch-loop-arrays
-Common Report Var(flag_prefetch_loop_arrays) Init(-1) Optimization
+Common Var(flag_prefetch_loop_arrays) Init(-1) Optimization
Generate prefetch instructions, if available, for arrays in loops.
fprofile
-Common Report Var(profile_flag)
+Common Var(profile_flag)
Enable basic program profiling code.
fprofile-abs-path
-Common Report Var(profile_abs_path_flag)
+Common Var(profile_abs_path_flag)
Generate absolute source path names for gcov.
fprofile-arcs
-Common Report Var(profile_arc_flag)
+Common Var(profile_arc_flag)
Insert arc-based program profiling code.
fprofile-dir=
@@ -2205,7 +2221,7 @@ Common Joined RejectNegative Var(profile_note_location)
Select the name for storing the profile note file.
fprofile-correction
-Common Report Var(flag_profile_correction)
+Common Var(flag_profile_correction)
Enable correction of flow inconsistent profile data input.
fprofile-update=
@@ -2260,8 +2276,16 @@ fprofile-generate=
Common Joined RejectNegative
Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=.
+fprofile-info-section
+Common RejectNegative
+Register the profile information in the .gcov_info section instead of using a constructor/destructor.
+
+fprofile-info-section=
+Common Joined RejectNegative Var(profile_info_section)
+Register the profile information in the specified section instead of using a constructor/destructor.
+
fprofile-partial-training
-Common Report Var(flag_profile_partial_training) Optimization
+Common Var(flag_profile_partial_training) Optimization
Do not assume that functions never executed during the train run are cold.
fprofile-use
@@ -2273,15 +2297,15 @@ Common Joined RejectNegative
Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
fprofile-values
-Common Report Var(flag_profile_values)
+Common Var(flag_profile_values)
Insert code to profile values of expressions.
fprofile-report
-Common Report Var(profile_report)
+Common Var(profile_report)
Report on consistency of profile.
fprofile-reorder-functions
-Common Report Var(flag_profile_reorder_functions) Optimization
+Common Var(flag_profile_reorder_functions) Optimization
Enable function reordering that improves code placement.
fpatchable-function-entry=
@@ -2302,11 +2326,11 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
; records information in the assembler output file as comments, so
; they never reach the object file.
frecord-gcc-switches
-Common Report Var(flag_record_gcc_switches)
+Common Var(flag_record_gcc_switches)
Record gcc command line switches in the object file.
freg-struct-return
-Common Report Var(flag_pcc_struct_return,0) Optimization
+Common Var(flag_pcc_struct_return,0) Optimization
Return small aggregates in registers.
fregmove
@@ -2314,7 +2338,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
flifetime-dse
-Common Report Var(flag_lifetime_dse,2) Init(2) Optimization
+Common Var(flag_lifetime_dse,2) Init(2) Optimization
Tell DSE that the storage for a C++ object is dead when the constructor
starts and when the destructor finishes.
@@ -2325,7 +2349,7 @@ flive-patching
Common RejectNegative Alias(flive-patching=,inline-clone) Optimization
flive-patching=
-Common Report Joined RejectNegative Enum(live_patching_level) Var(flag_live_patching) Init(LIVE_PATCHING_NONE) Optimization
+Common Joined RejectNegative Enum(live_patching_level) Var(flag_live_patching) Init(LIVE_PATCHING_NONE) Optimization
-flive-patching=[inline-only-static|inline-clone] Control IPA
optimizations to provide a safe compilation for live-patching. At the same
time, provides multiple-level control on the enabled IPA optimizations.
@@ -2340,23 +2364,23 @@ EnumValue
Enum(live_patching_level) String(inline-clone) Value(LIVE_PATCHING_INLINE_CLONE)
fallocation-dce
-Common Report Var(flag_allocation_dce) Init(1) Optimization
+Common Var(flag_allocation_dce) Init(1) Optimization
Tell DCE to remove unused C++ allocations.
flive-range-shrinkage
-Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
+Common Var(flag_live_range_shrinkage) Init(0) Optimization
Relief of register pressure through live range shrinkage.
frename-registers
-Common Report Var(flag_rename_registers) Init(2) Optimization
+Common Var(flag_rename_registers) Init(2) Optimization
Perform a register renaming optimization pass.
fschedule-fusion
-Common Report Var(flag_schedule_fusion) Init(2) Optimization
+Common Var(flag_schedule_fusion) Init(2) Optimization
Perform a target dependent instruction fusion optimization pass.
freorder-blocks
-Common Report Var(flag_reorder_blocks) Optimization
+Common Var(flag_reorder_blocks) Optimization
Reorder basic blocks to improve code placement.
freorder-blocks-algorithm=
@@ -2373,15 +2397,15 @@ EnumValue
Enum(reorder_blocks_algorithm) String(stc) Value(REORDER_BLOCKS_ALGORITHM_STC)
freorder-blocks-and-partition
-Common Report Var(flag_reorder_blocks_and_partition) Optimization
+Common Var(flag_reorder_blocks_and_partition) Optimization
Reorder basic blocks and partition into hot and cold sections.
freorder-functions
-Common Report Var(flag_reorder_functions) Optimization
+Common Var(flag_reorder_functions) Optimization
Reorder functions to improve code placement.
frerun-cse-after-loop
-Common Report Var(flag_rerun_cse_after_loop) Optimization
+Common Var(flag_rerun_cse_after_loop) Optimization
Add a common subexpression elimination pass after loop optimizations.
frerun-loop-opt
@@ -2389,27 +2413,27 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
frounding-math
-Common Report Var(flag_rounding_math) Optimization SetByCombined
+Common Var(flag_rounding_math) Optimization SetByCombined
Disable optimizations that assume default FP rounding behavior.
fsched-interblock
-Common Report Var(flag_schedule_interblock) Init(1) Optimization
+Common Var(flag_schedule_interblock) Init(1) Optimization
Enable scheduling across basic blocks.
fsched-pressure
-Common Report Var(flag_sched_pressure) Init(0) Optimization
+Common Var(flag_sched_pressure) Init(0) Optimization
Enable register pressure sensitive insn scheduling.
fsched-spec
-Common Report Var(flag_schedule_speculative) Init(1) Optimization
+Common Var(flag_schedule_speculative) Init(1) Optimization
Allow speculative motion of non-loads.
fsched-spec-load
-Common Report Var(flag_schedule_speculative_load) Optimization
+Common Var(flag_schedule_speculative_load) Optimization
Allow speculative motion of some loads.
fsched-spec-load-dangerous
-Common Report Var(flag_schedule_speculative_load_dangerous) Optimization
+Common Var(flag_schedule_speculative_load_dangerous) Optimization
Allow speculative motion of more loads.
fsched-verbose=
@@ -2417,7 +2441,7 @@ Common RejectNegative Joined UInteger Var(sched_verbose_param) Init(1)
-fsched-verbose=<number> Set the verbosity level of the scheduler.
fsched2-use-superblocks
-Common Report Var(flag_sched2_use_superblocks) Optimization
+Common Var(flag_sched2_use_superblocks) Optimization
If scheduling post reload, do superblock scheduling.
fsched2-use-traces
@@ -2425,22 +2449,22 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fschedule-insns
-Common Report Var(flag_schedule_insns) Optimization
+Common Var(flag_schedule_insns) Optimization
Reschedule instructions before register allocation.
fschedule-insns2
-Common Report Var(flag_schedule_insns_after_reload) Optimization
+Common Var(flag_schedule_insns_after_reload) Optimization
Reschedule instructions after register allocation.
; This flag should be on when a target implements non-trivial
; scheduling hooks, maybe saving some information for its own sake.
; On IA64, for example, this is used for correct bundling.
fselective-scheduling
-Common Report Var(flag_selective_scheduling) Optimization
+Common Var(flag_selective_scheduling) Optimization
Schedule instructions using selective scheduling algorithm.
fselective-scheduling2
-Common Report Var(flag_selective_scheduling2) Optimization
+Common Var(flag_selective_scheduling2) Optimization
Run selective scheduling after reload.
fself-test=
@@ -2448,25 +2472,25 @@ Common Undocumented Joined Var(flag_self_test)
Run self-tests, using the given path to locate test files.
fsel-sched-pipelining
-Common Report Var(flag_sel_sched_pipelining) Init(0) Optimization
+Common Var(flag_sel_sched_pipelining) Init(0) Optimization
Perform software pipelining of inner loops during selective scheduling.
fsel-sched-pipelining-outer-loops
-Common Report Var(flag_sel_sched_pipelining_outer_loops) Init(0) Optimization
+Common Var(flag_sel_sched_pipelining_outer_loops) Init(0) Optimization
Perform software pipelining of outer loops during selective scheduling.
fsel-sched-reschedule-pipelined
-Common Report Var(flag_sel_sched_reschedule_pipelined) Init(0) Optimization
+Common Var(flag_sel_sched_reschedule_pipelined) Init(0) Optimization
Reschedule pipelined regions without pipelining.
fsemantic-interposition
-Common Report Var(flag_semantic_interposition) Init(1)
+Common Var(flag_semantic_interposition) Init(1)
Allow interposing function (or variables) by ones with different semantics (or initializer) respectively by dynamic linker.
; sched_stalled_insns means that insns can be moved prematurely from the queue
; of stalled insns into the ready list.
fsched-stalled-insns
-Common Report Var(flag_sched_stalled_insns) Optimization UInteger
+Common Var(flag_sched_stalled_insns) Optimization UInteger
Allow premature scheduling of queued insns.
fsched-stalled-insns=
@@ -2478,7 +2502,7 @@ Common RejectNegative Joined UInteger Optimization
; premature removal from the queue of stalled insns into the ready list (has
; an effect only if the flag 'sched_stalled_insns' is set).
fsched-stalled-insns-dep
-Common Report Var(flag_sched_stalled_insns_dep,1) Init(1) Optimization UInteger
+Common Var(flag_sched_stalled_insns_dep,1) Init(1) Optimization UInteger
Set dependence distance checking in premature scheduling of queued insns.
fsched-stalled-insns-dep=
@@ -2486,31 +2510,31 @@ Common RejectNegative Joined UInteger Optimization
-fsched-stalled-insns-dep=<number> Set dependence distance checking in premature scheduling of queued insns.
fsched-group-heuristic
-Common Report Var(flag_sched_group_heuristic) Init(1) Optimization
+Common Var(flag_sched_group_heuristic) Init(1) Optimization
Enable the group heuristic in the scheduler.
fsched-critical-path-heuristic
-Common Report Var(flag_sched_critical_path_heuristic) Init(1) Optimization
+Common Var(flag_sched_critical_path_heuristic) Init(1) Optimization
Enable the critical path heuristic in the scheduler.
fsched-spec-insn-heuristic
-Common Report Var(flag_sched_spec_insn_heuristic) Init(1) Optimization
+Common Var(flag_sched_spec_insn_heuristic) Init(1) Optimization
Enable the speculative instruction heuristic in the scheduler.
fsched-rank-heuristic
-Common Report Var(flag_sched_rank_heuristic) Init(1) Optimization
+Common Var(flag_sched_rank_heuristic) Init(1) Optimization
Enable the rank heuristic in the scheduler.
fsched-last-insn-heuristic
-Common Report Var(flag_sched_last_insn_heuristic) Init(1) Optimization
+Common Var(flag_sched_last_insn_heuristic) Init(1) Optimization
Enable the last instruction heuristic in the scheduler.
fsched-dep-count-heuristic
-Common Report Var(flag_sched_dep_count_heuristic) Init(1) Optimization
+Common Var(flag_sched_dep_count_heuristic) Init(1) Optimization
Enable the dependent count heuristic in the scheduler.
fsection-anchors
-Common Report Var(flag_section_anchors) Optimization
+Common Var(flag_section_anchors) Optimization
Access data in the same section from shared anchor points.
fsee
@@ -2522,68 +2546,68 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
free
-Common Report Var(flag_ree) Init(0) Optimization
+Common Var(flag_ree) Init(0) Optimization
Turn on Redundant Extensions Elimination pass.
fshow-column
-Common Report Var(flag_show_column) Init(1)
+Common Var(flag_show_column) Init(1)
Show column numbers in diagnostics, when available. Default on.
fshrink-wrap
-Common Report Var(flag_shrink_wrap) Optimization
+Common Var(flag_shrink_wrap) Optimization
Emit function prologues only before parts of the function that need it,
rather than at the top of the function.
fshrink-wrap-separate
-Common Report Var(flag_shrink_wrap_separate) Init(1) Optimization
+Common Var(flag_shrink_wrap_separate) Init(1) Optimization
Shrink-wrap parts of the prologue and epilogue separately.
fsignaling-nans
-Common Report Var(flag_signaling_nans) Optimization SetByCombined
+Common Var(flag_signaling_nans) Optimization SetByCombined
Disable optimizations observable by IEEE signaling NaNs.
fsigned-zeros
-Common Report Var(flag_signed_zeros) Init(1) Optimization SetByCombined
+Common Var(flag_signed_zeros) Init(1) Optimization SetByCombined
Disable floating point optimizations that ignore the IEEE signedness of zero.
fsingle-precision-constant
-Common Report Var(flag_single_precision_constant) Optimization
+Common Var(flag_single_precision_constant) Optimization
Convert floating point constants to single precision constants.
fsplit-ivs-in-unroller
-Common Report Var(flag_split_ivs_in_unroller) Init(1) Optimization
+Common Var(flag_split_ivs_in_unroller) Init(1) Optimization
Split lifetimes of induction variables when loops are unrolled.
fsplit-stack
-Common Report Var(flag_split_stack) Init(-1)
+Common Var(flag_split_stack) Init(-1)
Generate discontiguous stack frames.
fsplit-wide-types
-Common Report Var(flag_split_wide_types) Optimization
+Common Var(flag_split_wide_types) Optimization
Split wide types into independent registers.
fsplit-wide-types-early
-Common Report Var(flag_split_wide_types_early) Optimization
+Common Var(flag_split_wide_types_early) Optimization
Split wide types into independent registers earlier.
fssa-backprop
-Common Report Var(flag_ssa_backprop) Init(1) Optimization
+Common Var(flag_ssa_backprop) Init(1) Optimization
Enable backward propagation of use properties at the SSA level.
fssa-phiopt
-Common Report Var(flag_ssa_phiopt) Optimization
+Common Var(flag_ssa_phiopt) Optimization
Optimize conditional patterns using SSA PHI nodes.
fstdarg-opt
-Common Report Var(flag_stdarg_opt) Init(1) Optimization
+Common Var(flag_stdarg_opt) Init(1) Optimization
Optimize amount of stdarg registers saved to stack at start of function.
fvariable-expansion-in-unroller
-Common Report Var(flag_variable_expansion_in_unroller) Optimization
+Common Var(flag_variable_expansion_in_unroller) Optimization
Apply variable expansion when loops are unrolled.
fstack-check=
-Common Report RejectNegative Joined Optimization
+Common RejectNegative Joined Optimization
-fstack-check=[no|generic|specific] Insert stack checking code into the program.
fstack-check
@@ -2591,7 +2615,7 @@ Common Alias(fstack-check=, specific, no)
Insert stack checking code into the program. Same as -fstack-check=specific.
fstack-clash-protection
-Common Report Var(flag_stack_clash_protection) Optimization
+Common Var(flag_stack_clash_protection) Optimization
Insert code to probe each page of stack space as it is allocated to protect
from stack-clash style attacks.
@@ -2607,19 +2631,19 @@ Common RejectNegative Joined Var(common_deferred_options) Defer
-fstack-limit-symbol=<name> Trap if the stack goes past symbol <name>.
fstack-protector
-Common Report Var(flag_stack_protect, 1) Init(-1) Optimization
+Common Var(flag_stack_protect, 1) Init(-1) Optimization
Use propolice as a stack protection method.
fstack-protector-all
-Common Report RejectNegative Var(flag_stack_protect, 2) Init(-1) Optimization
+Common RejectNegative Var(flag_stack_protect, 2) Init(-1) Optimization
Use a stack protection method for every function.
fstack-protector-strong
-Common Report RejectNegative Var(flag_stack_protect, 3) Init(-1) Optimization
+Common RejectNegative Var(flag_stack_protect, 3) Init(-1) Optimization
Use a smart stack protection method for certain functions.
fstack-protector-explicit
-Common Report RejectNegative Var(flag_stack_protect, 4) Optimization
+Common RejectNegative Var(flag_stack_protect, 4) Optimization
Use stack protection method only for functions with the stack_protect attribute.
fstack-usage
@@ -2635,35 +2659,35 @@ Does nothing. Preserved for backward compatibility.
; types do not alias expressions of certain other types. Only used
; if alias analysis (in general) is enabled.
fstrict-aliasing
-Common Report Var(flag_strict_aliasing) Optimization
+Common Var(flag_strict_aliasing) Optimization
Assume strict aliasing rules apply.
fstrict-overflow
-Common Report
+Common
Treat signed overflow as undefined. Negated as -fwrapv -fwrapv-pointer.
fsync-libcalls
-Common Report Var(flag_sync_libcalls) Init(1)
+Common Var(flag_sync_libcalls) Init(1)
Implement __atomic operations via libcalls to legacy __sync functions.
fsyntax-only
-Common Report Var(flag_syntax_only)
+Common Var(flag_syntax_only)
Check for syntax errors, then stop.
ftest-coverage
-Common Report Var(flag_test_coverage)
+Common Var(flag_test_coverage)
Create data files needed by \"gcov\".
fthread-jumps
-Common Report Var(flag_thread_jumps) Optimization
+Common Var(flag_thread_jumps) Optimization
Perform jump threading optimizations.
ftime-report
-Common Report Var(time_report)
+Common Var(time_report)
Report the time taken by each compiler pass.
ftime-report-details
-Common Report Var(time_report_details)
+Common Var(time_report_details)
Record times taken by sub-phases separately.
ftls-model=
@@ -2686,15 +2710,15 @@ EnumValue
Enum(tls_model) String(local-exec) Value(TLS_MODEL_LOCAL_EXEC)
ftoplevel-reorder
-Common Report Var(flag_toplevel_reorder) Init(2) Optimization
+Common Var(flag_toplevel_reorder) Init(2) Optimization
Reorder top level functions, variables, and asms.
ftracer
-Common Report Var(flag_tracer) Optimization
+Common Var(flag_tracer) Optimization
Perform superblock formation via tail duplication.
ftrampolines
-Common Report Var(flag_trampolines) Init(0)
+Common Var(flag_trampolines) Init(0)
For targets that normally need trampolines for nested functions, always
generate them instead of using descriptors.
@@ -2702,19 +2726,19 @@ generate them instead of using descriptors.
; (user-visible) trap. This is the case, for example, in nonstop
; IEEE 754 arithmetic.
ftrapping-math
-Common Report Var(flag_trapping_math) Init(1) Optimization SetByCombined
+Common Var(flag_trapping_math) Init(1) Optimization SetByCombined
Assume floating-point operations can trap.
ftrapv
-Common Report Var(flag_trapv) Optimization
+Common Var(flag_trapv) Optimization
Trap for signed overflow in addition, subtraction and multiplication.
ftree-ccp
-Common Report Var(flag_tree_ccp) Optimization
+Common Var(flag_tree_ccp) Optimization
Enable SSA-CCP optimization on trees.
ftree-bit-ccp
-Common Report Var(flag_tree_bit_ccp) Optimization
+Common Var(flag_tree_bit_ccp) Optimization
Enable SSA-BIT-CCP optimization on trees.
ftree-store-ccp
@@ -2722,7 +2746,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
ftree-ch
-Common Report Var(flag_tree_ch) Optimization
+Common Var(flag_tree_ch) Optimization
Enable loop header copying on trees.
ftree-coalesce-inlined-vars
@@ -2730,7 +2754,7 @@ Common Ignore RejectNegative
Does nothing. Preserved for backward compatibility.
ftree-coalesce-vars
-Common Report Var(flag_tree_coalesce_vars) Optimization
+Common Var(flag_tree_coalesce_vars) Optimization
Enable SSA coalescing of user variables.
ftree-copyrename
@@ -2738,7 +2762,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
ftree-copy-prop
-Common Report Var(flag_tree_copy_prop) Optimization
+Common Var(flag_tree_copy_prop) Optimization
Enable copy propagation on trees.
ftree-store-copy-prop
@@ -2746,64 +2770,64 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
ftree-cselim
-Common Report Var(flag_tree_cselim) Init(2) Optimization
+Common Var(flag_tree_cselim) Init(2) Optimization
Transform condition stores into unconditional ones.
ftree-switch-conversion
-Common Report Var(flag_tree_switch_conversion) Optimization
+Common Var(flag_tree_switch_conversion) Optimization
Perform conversions of switch initializations.
ftree-dce
-Common Report Var(flag_tree_dce) Optimization
+Common Var(flag_tree_dce) Optimization
Enable SSA dead code elimination optimization on trees.
ftree-dominator-opts
-Common Report Var(flag_tree_dom) Optimization
+Common Var(flag_tree_dom) Optimization
Enable dominator optimizations.
ftree-tail-merge
-Common Report Var(flag_tree_tail_merge) Optimization
+Common Var(flag_tree_tail_merge) Optimization
Enable tail merging on trees.
ftree-dse
-Common Report Var(flag_tree_dse) Optimization
+Common Var(flag_tree_dse) Optimization
Enable dead store elimination.
ftree-forwprop
-Common Report Var(flag_tree_forwprop) Init(1) Optimization
+Common Var(flag_tree_forwprop) Init(1) Optimization
Enable forward propagation on trees.
ftree-fre
-Common Report Var(flag_tree_fre) Optimization
+Common Var(flag_tree_fre) Optimization
Enable Full Redundancy Elimination (FRE) on trees.
foptimize-strlen
-Common Report Var(flag_optimize_strlen) Optimization
+Common Var(flag_optimize_strlen) Optimization
Enable string length optimizations on trees.
fisolate-erroneous-paths-dereference
-Common Report Var(flag_isolate_erroneous_paths_dereference) Optimization
+Common Var(flag_isolate_erroneous_paths_dereference) Optimization
Detect paths that trigger erroneous or undefined behavior due to
dereferencing a null pointer. Isolate those paths from the main control
flow and turn the statement with erroneous or undefined behavior into a trap.
fisolate-erroneous-paths-attribute
-Common Report Var(flag_isolate_erroneous_paths_attribute) Optimization
+Common Var(flag_isolate_erroneous_paths_attribute) Optimization
Detect paths that trigger erroneous or undefined behavior due to a null value
being used in a way forbidden by a returns_nonnull or nonnull
attribute. Isolate those paths from the main control flow and turn the
statement with erroneous or undefined behavior into a trap.
ftree-loop-distribution
-Common Report Var(flag_tree_loop_distribution) Optimization
+Common Var(flag_tree_loop_distribution) Optimization
Enable loop distribution on trees.
ftree-loop-distribute-patterns
-Common Report Var(flag_tree_loop_distribute_patterns) Optimization
+Common Var(flag_tree_loop_distribute_patterns) Optimization
Enable loop distribution for patterns transformed into a library call.
ftree-loop-im
-Common Report Var(flag_tree_loop_im) Init(1) Optimization
+Common Var(flag_tree_loop_im) Init(1) Optimization
Enable loop invariant motion on trees.
ftree-loop-linear
@@ -2811,35 +2835,35 @@ Common Alias(floop-nest-optimize)
Enable loop nest transforms. Same as -floop-nest-optimize.
ftree-loop-ivcanon
-Common Report Var(flag_tree_loop_ivcanon) Init(1) Optimization
+Common Var(flag_tree_loop_ivcanon) Init(1) Optimization
Create canonical induction variables in loops.
ftree-loop-optimize
-Common Report Var(flag_tree_loop_optimize) Init(1) Optimization
+Common Var(flag_tree_loop_optimize) Init(1) Optimization
Enable loop optimizations on tree level.
ftree-parallelize-loops=
-Common Report Joined RejectNegative UInteger Var(flag_tree_parallelize_loops) Init(1) Optimization
+Common Joined RejectNegative UInteger Var(flag_tree_parallelize_loops) Init(1) Optimization
-ftree-parallelize-loops=<number> Enable automatic parallelization of loops.
ftree-phiprop
-Common Report Var(flag_tree_phiprop) Init(1) Optimization
+Common Var(flag_tree_phiprop) Init(1) Optimization
Enable hoisting loads from conditional pointers.
ftree-pre
-Common Report Var(flag_tree_pre) Optimization
+Common Var(flag_tree_pre) Optimization
Enable SSA-PRE optimization on trees.
ftree-partial-pre
-Common Report Var(flag_tree_partial_pre) Optimization
+Common Var(flag_tree_partial_pre) Optimization
In SSA-PRE optimization on trees, enable partial-partial redundancy elimination.
ftree-pta
-Common Report Var(flag_tree_pta) Optimization
+Common Var(flag_tree_pta) Optimization
Perform function-local points-to analysis on trees.
ftree-reassoc
-Common Report Var(flag_tree_reassoc) Init(1) Optimization
+Common Var(flag_tree_reassoc) Init(1) Optimization
Enable reassociation on tree level.
ftree-salias
@@ -2847,31 +2871,31 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
ftree-sink
-Common Report Var(flag_tree_sink) Optimization
+Common Var(flag_tree_sink) Optimization
Enable SSA code sinking on trees.
ftree-slsr
-Common Report Var(flag_tree_slsr) Optimization
+Common Var(flag_tree_slsr) Optimization
Perform straight-line strength reduction.
ftree-sra
-Common Report Var(flag_tree_sra) Optimization
+Common Var(flag_tree_sra) Optimization
Perform scalar replacement of aggregates.
ftree-ter
-Common Report Var(flag_tree_ter) Optimization
+Common Var(flag_tree_ter) Optimization
Replace temporary expressions in the SSA->normal pass.
ftree-lrs
-Common Report Var(flag_tree_live_range_split) Optimization
+Common Var(flag_tree_live_range_split) Optimization
Perform live range splitting during the SSA->normal pass.
ftree-vrp
-Common Report Var(flag_tree_vrp) Init(0) Optimization
+Common Var(flag_tree_vrp) Init(0) Optimization
Perform Value Range Propagation on trees.
fsplit-paths
-Common Report Var(flag_split_paths) Init(0) Optimization
+Common Var(flag_split_paths) Init(0) Optimization
Split paths leading to loop backedges.
funconstrained-commons
@@ -2880,15 +2904,15 @@ Assume common declarations may be overridden with ones with a larger
trailing array.
funit-at-a-time
-Common Report Var(flag_unit_at_a_time) Init(1)
+Common Var(flag_unit_at_a_time) Init(1)
Compile whole compilation unit at a time.
funroll-loops
-Common Report Var(flag_unroll_loops) Optimization
+Common Var(flag_unroll_loops) Optimization
Perform loop unrolling when iteration count is known.
funroll-all-loops
-Common Report Var(flag_unroll_all_loops) Optimization
+Common Var(flag_unroll_all_loops) Optimization
Perform loop unrolling for all loops.
funroll-completely-grow-size
@@ -2903,12 +2927,12 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
fassociative-math
-Common Report Var(flag_associative_math) SetByCombined Optimization
+Common Var(flag_associative_math) SetByCombined Optimization
Allow optimization for floating-point arithmetic which may change the
result of the operation due to rounding.
freciprocal-math
-Common Report Var(flag_reciprocal_math) SetByCombined Optimization
+Common Var(flag_reciprocal_math) SetByCombined Optimization
Same as -fassociative-math for expressions which include division.
; Nonzero means that unsafe floating-point math optimizations are allowed
@@ -2916,23 +2940,23 @@ Same as -fassociative-math for expressions which include division.
; are allowed to assume that their arguments and results are "normal"
; (e.g., nonnegative for SQRT).
funsafe-math-optimizations
-Common Report Var(flag_unsafe_math_optimizations) Optimization SetByCombined
+Common Var(flag_unsafe_math_optimizations) Optimization SetByCombined
Allow math optimizations that may violate IEEE or ISO standards.
funswitch-loops
-Common Report Var(flag_unswitch_loops) Optimization
+Common Var(flag_unswitch_loops) Optimization
Perform loop unswitching.
fsplit-loops
-Common Report Var(flag_split_loops) Optimization
+Common Var(flag_split_loops) Optimization
Perform loop splitting.
fversion-loops-for-strides
-Common Report Var(flag_version_loops_for_strides) Optimization
+Common Var(flag_version_loops_for_strides) Optimization
Version loops based on whether indices have a stride of one.
funwind-tables
-Common Report Var(flag_unwind_tables) Optimization
+Common Var(flag_unwind_tables) Optimization
Just generate unwind tables for exception handling.
fuse-ld=bfd
@@ -2956,7 +2980,7 @@ Common Undocumented Var(flag_use_linker_plugin)
; will be set according to optimize, debug_info_level and debug_hooks
; in process_options ().
fvar-tracking
-Common Report Var(flag_var_tracking) Init(2) PerFunction
+Common Var(flag_var_tracking) Init(2) PerFunction
Perform variable tracking.
; Positive if we should track variables at assignments, negative if
@@ -2964,13 +2988,13 @@ Perform variable tracking.
; annotations. When flag_var_tracking_assignments ==
; AUTODETECT_VALUE it will be set according to flag_var_tracking.
fvar-tracking-assignments
-Common Report Var(flag_var_tracking_assignments) Init(2) PerFunction
+Common Var(flag_var_tracking_assignments) Init(2) PerFunction
Perform variable tracking by annotating assignments.
; Nonzero if we should toggle flag_var_tracking_assignments after
; processing options and computing its default. */
fvar-tracking-assignments-toggle
-Common Report Var(flag_var_tracking_assignments_toggle) PerFunction
+Common Var(flag_var_tracking_assignments_toggle) PerFunction
Toggle -fvar-tracking-assignments.
; Positive if we should track uninitialized variables, negative if
@@ -2978,12 +3002,12 @@ Toggle -fvar-tracking-assignments.
; annotations. When flag_var_tracking_uninit == AUTODETECT_VALUE it
; will be set according to flag_var_tracking.
fvar-tracking-uninit
-Common Report Var(flag_var_tracking_uninit) PerFunction
+Common Var(flag_var_tracking_uninit) PerFunction
Perform variable tracking and also tag variables that are uninitialized.
; Alias to enable both -ftree-loop-vectorize and -ftree-slp-vectorize.
ftree-vectorize
-Common Report Optimization
+Common Optimization
Enable vectorization on trees.
ftree-vectorizer-verbose=
@@ -2991,20 +3015,20 @@ Common Joined RejectNegative Ignore
Does nothing. Preserved for backward compatibility.
ftree-loop-vectorize
-Common Report Var(flag_tree_loop_vectorize) Optimization EnabledBy(ftree-vectorize)
+Common Var(flag_tree_loop_vectorize) Optimization EnabledBy(ftree-vectorize)
Enable loop vectorization on trees.
ftree-slp-vectorize
-Common Report Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize)
+Common Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize)
Enable basic block vectorization (SLP) on trees.
fvect-cost-model=
Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Optimization
--fvect-cost-model=[unlimited|dynamic|cheap] Specifies the cost model for vectorization.
+-fvect-cost-model=[unlimited|dynamic|cheap|very-cheap] Specifies the cost model for vectorization.
fsimd-cost-model=
Common Joined RejectNegative Enum(vect_cost_model) Var(flag_simd_cost_model) Init(VECT_COST_MODEL_UNLIMITED) Optimization
--fsimd-cost-model=[unlimited|dynamic|cheap] Specifies the vectorization cost model for code marked with a simd directive.
+-fsimd-cost-model=[unlimited|dynamic|cheap|very-cheap] Specifies the vectorization cost model for code marked with a simd directive.
Enum
Name(vect_cost_model) Type(enum vect_cost_model) UnknownError(unknown vectorizer cost model %qs)
@@ -3018,6 +3042,9 @@ Enum(vect_cost_model) String(dynamic) Value(VECT_COST_MODEL_DYNAMIC)
EnumValue
Enum(vect_cost_model) String(cheap) Value(VECT_COST_MODEL_CHEAP)
+EnumValue
+Enum(vect_cost_model) String(very-cheap) Value(VECT_COST_MODEL_VERY_CHEAP)
+
fvect-cost-model
Common Alias(fvect-cost-model=,dynamic,unlimited)
Enables the dynamic vectorizer cost model. Preserved for backward compatibility.
@@ -3027,7 +3054,7 @@ Common Ignore
Does nothing. Preserved for backward compatibility.
ftree-scev-cprop
-Common Report Var(flag_tree_scev_cprop) Init(1) Optimization
+Common Var(flag_tree_scev_cprop) Init(1) Optimization
Enable copy propagation of scalar-evolution information.
; -fverbose-asm causes extra commentary information to be produced in
@@ -3037,7 +3064,7 @@ Enable copy propagation of scalar-evolution information.
; -fno-verbose-asm, the default, causes the extra information
; to not be added and is useful when comparing two assembler files.
fverbose-asm
-Common Report Var(flag_verbose_asm)
+Common Var(flag_verbose_asm)
Add extra commentary to assembler output.
fvisibility=
@@ -3084,33 +3111,37 @@ Common Var(flag_vtv_debug)
Output vtable verification pointer sets information.
fvpt
-Common Report Var(flag_value_profile_transformations) Optimization
+Common Var(flag_value_profile_transformations) Optimization
Use expression value profiles in optimizations.
fweb
-Common Report Var(flag_web) Init(2) Optimization
+Common Var(flag_web) Init(2) Optimization
Construct webs and split unrelated uses of single variable.
ftree-builtin-call-dce
-Common Report Var(flag_tree_builtin_call_dce) Init(0) Optimization
+Common Var(flag_tree_builtin_call_dce) Init(0) Optimization
Enable conditional dead code elimination for builtin calls.
fwhole-program
-Common Report Var(flag_whole_program) Init(0)
+Common Var(flag_whole_program) Init(0)
Perform whole program optimizations.
fwrapv-pointer
-Common Report Var(flag_wrapv_pointer) Optimization
+Common Var(flag_wrapv_pointer) Optimization
Assume pointer overflow wraps around.
fwrapv
-Common Report Var(flag_wrapv) Optimization
+Common Var(flag_wrapv) Optimization
Assume signed arithmetic overflow wraps around.
fzero-initialized-in-bss
-Common Report Var(flag_zero_initialized_in_bss) Init(1)
+Common Var(flag_zero_initialized_in_bss) Init(1)
Put zero initialized data in the bss section.
+fzero-call-used-regs=
+Common RejectNegative Joined
+Clear call-used registers upon function return.
+
g
Common Driver RejectNegative JoinedOrMissing
Generate debug information in default format.
@@ -3151,6 +3182,14 @@ gdwarf-
Common Driver Joined UInteger Var(dwarf_version) Init(4) Negative(gstabs)
Generate debug information in DWARF v2 (or later) format.
+gdwarf32
+Common Driver Var(dwarf_offset_size,4) Init(4) RejectNegative
+Use 32-bit DWARF format when emitting DWARF debug information.
+
+gdwarf64
+Common Driver Var(dwarf_offset_size,8) RejectNegative
+Use 64-bit DWARF format when emitting DWARF debug information.
+
ggdb
Common Driver JoinedOrMissing
Generate debug information in default extended format.
@@ -3200,15 +3239,15 @@ Common Driver Var(debug_nonbind_markers_p) Init(2)
Emit progressive recommended breakpoint locations.
gstrict-dwarf
-Common Driver Report Var(dwarf_strict) Init(0)
+Common Driver Var(dwarf_strict) Init(0)
Don't emit DWARF additions beyond selected version.
gdescribe-dies
-Common Driver Report Var(flag_describe_dies) Init(0)
+Common Driver Var(flag_describe_dies) Init(0)
Add description attributes to some DWARF DIEs that have no name attribute.
gtoggle
-Common Driver Report Var(flag_gtoggle)
+Common Driver Var(flag_gtoggle)
Toggle debug information generation.
gvariable-location-views
@@ -3421,6 +3460,9 @@ Driver
static-libasan
Driver
+static-libhwasan
+Driver
+
static-libtsan
Driver
@@ -3449,7 +3491,7 @@ z
Driver Joined Separate
fipa-ra
-Common Report Var(flag_ipa_ra) Optimization
+Common Var(flag_ipa_ra) Optimization
Use caller save register across calls if possible.
; This comment is to ensure we retain the blank line above.
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
index 1e8324e..a3372fc 100644
--- a/gcc/common/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -241,6 +241,23 @@ get_amd_cpu (struct __processor_model *cpu_model,
cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
}
break;
+ case 0x19:
+ cpu_model->__cpu_type = AMDFAM19H;
+ /* AMD family 19h version 1. */
+ if (model <= 0x0f)
+ {
+ cpu = "znver3";
+ CHECK___builtin_cpu_is ("znver3");
+ cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_VAES))
+ {
+ cpu = "znver3";
+ CHECK___builtin_cpu_is ("znver3");
+ cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
+ }
+ break;
default:
break;
}
@@ -523,6 +540,8 @@ get_available_features (struct __processor_model *cpu_model,
int avx_usable = 0;
int avx512_usable = 0;
int amx_usable = 0;
+ /* Check if KL is usable. */
+ int has_kl = 0;
if ((ecx & bit_OSXSAVE))
{
/* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
@@ -650,6 +669,8 @@ get_available_features (struct __processor_model *cpu_model,
set_feature (FEATURE_WAITPKG);
if (ecx & bit_SHSTK)
set_feature (FEATURE_SHSTK);
+ if (ecx & bit_KL)
+ has_kl = 1;
if (edx & bit_SERIALIZE)
set_feature (FEATURE_SERIALIZE);
if (edx & bit_TSXLDTRK)
@@ -658,6 +679,8 @@ get_available_features (struct __processor_model *cpu_model,
set_feature (FEATURE_PCONFIG);
if (edx & bit_IBT)
set_feature (FEATURE_IBT);
+ if (edx & bit_UINTR)
+ set_feature (FEATURE_UINTR);
if (amx_usable)
{
if (edx & bit_AMX_TILE)
@@ -701,15 +724,20 @@ get_available_features (struct __processor_model *cpu_model,
set_feature (FEATURE_AVX5124FMAPS);
if (edx & bit_AVX512VP2INTERSECT)
set_feature (FEATURE_AVX512VP2INTERSECT);
- if (edx & bit_UINTR)
- set_feature (FEATURE_UINTR);
+ }
- __cpuid_count (7, 1, eax, ebx, ecx, edx);
+ __cpuid_count (7, 1, eax, ebx, ecx, edx);
+ if (eax & bit_HRESET)
+ set_feature (FEATURE_HRESET);
+ if (avx_usable)
+ {
+ if (eax & bit_AVXVNNI)
+ set_feature (FEATURE_AVXVNNI);
+ }
+ if (avx512_usable)
+ {
if (eax & bit_AVX512BF16)
set_feature (FEATURE_AVX512BF16);
- if (eax & bit_HRESET)
- set_feature (FEATURE_HRESET);
-
}
}
@@ -733,6 +761,21 @@ get_available_features (struct __processor_model *cpu_model,
set_feature (FEATURE_PTWRITE);
}
+ /* Get Advanced Features at level 0x19 (eax = 0x19). */
+ if (max_cpuid_level >= 0x19)
+ {
+ set_feature (FEATURE_AESKLE);
+ __cpuid (19, eax, ebx, ecx, edx);
+ /* Check if OS support keylocker. */
+ if (ebx & bit_AESKLE)
+ {
+ if (ebx & bit_WIDEKL)
+ set_feature (FEATURE_WIDEKL);
+ if (has_kl)
+ set_feature (FEATURE_KL);
+ }
+ }
+
/* Check cpuid level of extended features. */
__cpuid (0x80000000, ext_level, ebx, ecx, edx);
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index bfdca85..2a1d31f 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see
(OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512F_SET)
#define OPTION_MASK_ISA_AVX512VNNI_SET \
(OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512F_SET)
+#define OPTION_MASK_ISA2_AVXVNNI_SET OPTION_MASK_ISA2_AVXVNNI
#define OPTION_MASK_ISA_AVX512VPOPCNTDQ_SET \
(OPTION_MASK_ISA_AVX512VPOPCNTDQ | OPTION_MASK_ISA_AVX512F_SET)
#define OPTION_MASK_ISA_AVX512BITALG_SET \
@@ -165,6 +166,9 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA2_TSXLDTRK_SET OPTION_MASK_ISA2_TSXLDTRK
#define OPTION_MASK_ISA2_UINTR_SET OPTION_MASK_ISA2_UINTR
#define OPTION_MASK_ISA2_HRESET_SET OPTION_MASK_ISA2_HRESET
+#define OPTION_MASK_ISA2_KL_SET OPTION_MASK_ISA2_KL
+#define OPTION_MASK_ISA2_WIDEKL_SET \
+ (OPTION_MASK_ISA2_WIDEKL | OPTION_MASK_ISA2_KL_SET)
/* Define a set of ISAs which aren't available when a given ISA is
disabled. MMX and SSE ISAs are handled separately. */
@@ -203,6 +207,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_XSAVEOPT_UNSET OPTION_MASK_ISA_XSAVEOPT
#define OPTION_MASK_ISA_AVX2_UNSET \
(OPTION_MASK_ISA_AVX2 | OPTION_MASK_ISA_AVX512F_UNSET)
+#define OPTION_MASK_ISA2_AVX2_UNSET \
+ (OPTION_MASK_ISA2_AVXVNNI_UNSET | OPTION_MASK_ISA2_AVX512F_UNSET)
#define OPTION_MASK_ISA_AVX512F_UNSET \
(OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX512CD_UNSET \
| OPTION_MASK_ISA_AVX512PF_UNSET | OPTION_MASK_ISA_AVX512ER_UNSET \
@@ -225,6 +231,7 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA2_AVX5124VNNIW_UNSET OPTION_MASK_ISA2_AVX5124VNNIW
#define OPTION_MASK_ISA_AVX512VBMI2_UNSET OPTION_MASK_ISA_AVX512VBMI2
#define OPTION_MASK_ISA_AVX512VNNI_UNSET OPTION_MASK_ISA_AVX512VNNI
+#define OPTION_MASK_ISA2_AVXVNNI_UNSET OPTION_MASK_ISA2_AVXVNNI
#define OPTION_MASK_ISA_AVX512VPOPCNTDQ_UNSET OPTION_MASK_ISA_AVX512VPOPCNTDQ
#define OPTION_MASK_ISA_AVX512BITALG_UNSET OPTION_MASK_ISA_AVX512BITALG
#define OPTION_MASK_ISA2_AVX512BF16_UNSET OPTION_MASK_ISA2_AVX512BF16
@@ -258,6 +265,9 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA2_AMX_BF16_UNSET OPTION_MASK_ISA2_AMX_BF16
#define OPTION_MASK_ISA2_UINTR_UNSET OPTION_MASK_ISA2_UINTR
#define OPTION_MASK_ISA2_HRESET_UNSET OPTION_MASK_ISA2_HRESET
+#define OPTION_MASK_ISA2_KL_UNSET \
+ (OPTION_MASK_ISA2_KL | OPTION_MASK_ISA2_WIDEKL_UNSET)
+#define OPTION_MASK_ISA2_WIDEKL_UNSET OPTION_MASK_ISA2_WIDEKL
/* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same
as -mno-sse4.1. */
@@ -304,6 +314,15 @@ along with GCC; see the file COPYING3. If not see
| OPTION_MASK_ISA2_AVX512VP2INTERSECT_UNSET)
#define OPTION_MASK_ISA2_GENERAL_REGS_ONLY_UNSET \
(OPTION_MASK_ISA2_AVX512F_UNSET)
+#define OPTION_MASK_ISA2_AVX_UNSET OPTION_MASK_ISA2_AVX2_UNSET
+#define OPTION_MASK_ISA2_SSE4_2_UNSET OPTION_MASK_ISA2_AVX_UNSET
+#define OPTION_MASK_ISA2_SSE4_1_UNSET OPTION_MASK_ISA2_SSE4_2_UNSET
+#define OPTION_MASK_ISA2_SSE4_UNSET OPTION_MASK_ISA2_SSE4_1_UNSET
+#define OPTION_MASK_ISA2_SSSE3_UNSET OPTION_MASK_ISA2_SSE4_1_UNSET
+#define OPTION_MASK_ISA2_SSE3_UNSET OPTION_MASK_ISA2_SSSE3_UNSET
+#define OPTION_MASK_ISA2_SSE2_UNSET \
+ (OPTION_MASK_ISA2_SSE3_UNSET | OPTION_MASK_ISA2_KL_UNSET)
+#define OPTION_MASK_ISA2_SSE_UNSET OPTION_MASK_ISA2_SSE2_UNSET
#define OPTION_MASK_ISA2_AVX512BW_UNSET OPTION_MASK_ISA2_AVX512BF16_UNSET
@@ -399,8 +418,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSE_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSE_UNSET;
}
return true;
@@ -414,8 +433,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE2_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSE2_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSE2_UNSET;
}
return true;
@@ -429,8 +448,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE3_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE3_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSE3_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSE3_UNSET;
}
return true;
@@ -444,8 +463,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSSE3_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSSE3_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSSE3_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSSE3_UNSET;
}
return true;
@@ -459,8 +478,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_1_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_1_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSE4_1_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSE4_1_UNSET;
}
return true;
@@ -474,8 +493,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_2_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_2_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSE4_2_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSE4_2_UNSET;
}
return true;
@@ -489,8 +508,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX_UNSET;
}
return true;
@@ -504,8 +523,8 @@ ix86_handle_option (struct gcc_options *opts,
{
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX2_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX2_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX2_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX2_UNSET;
}
return true;
@@ -691,6 +710,40 @@ ix86_handle_option (struct gcc_options *opts,
opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_ENQCMD_UNSET;
opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_ENQCMD_UNSET;
}
+ return true;
+
+ case OPT_mkl:
+ if (value)
+ {
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_KL_SET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_KL_SET;
+
+ /* The Keylocker instructions need XMM registers from SSE2. */
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE2_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_KL_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_KL_UNSET;
+ }
+ return true;
+
+ case OPT_mwidekl:
+ if (value)
+ {
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_WIDEKL_SET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_WIDEKL_SET;
+
+ /* The Widekl instructions need XMM registers from SSE2. */
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE2_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_WIDEKL_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_WIDEKL_UNSET;
+ }
return true;
case OPT_mserialize:
@@ -832,6 +885,21 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
+ case OPT_mavxvnni:
+ if (value)
+ {
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVXVNNI_SET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVXVNNI_SET;
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX2_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVXVNNI_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVXVNNI_UNSET;
+ }
+ return true;
+
case OPT_msgx:
if (value)
{
@@ -1043,8 +1111,8 @@ ix86_handle_option (struct gcc_options *opts,
case OPT_mno_sse4:
opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_UNSET;
opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_UNSET;
- opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET;
- opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET;
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_SSE4_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_SSE4_UNSET;
return true;
case OPT_msse4a:
@@ -1694,7 +1762,8 @@ const char *const processor_names[] =
"btver1",
"btver2",
"znver1",
- "znver2"
+ "znver2",
+ "znver3"
};
/* Guarantee that the array is aligned with enum processor_type. */
@@ -1936,6 +2005,17 @@ const pta processor_alias_table[] =
| PTA_SHA | PTA_LZCNT | PTA_POPCNT | PTA_CLWB | PTA_RDPID
| PTA_WBNOINVD,
M_CPU_SUBTYPE (AMDFAM17H_ZNVER2), P_PROC_AVX2},
+ {"znver3", PROCESSOR_ZNVER3, CPU_ZNVER3,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2
+ | PTA_BMI | PTA_BMI2 | PTA_F16C | PTA_FMA | PTA_PRFCHW
+ | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE
+ | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED
+ | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES
+ | PTA_SHA | PTA_LZCNT | PTA_POPCNT | PTA_CLWB | PTA_RDPID
+ | PTA_WBNOINVD | PTA_VAES | PTA_VPCLMULQDQ | PTA_PKU,
+ M_CPU_SUBTYPE (AMDFAM19H_ZNVER3), P_PROC_AVX2},
{"btver1", PROCESSOR_BTVER1, CPU_GENERIC,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
| PTA_SSSE3 | PTA_SSE4A | PTA_ABM | PTA_CX16 | PTA_PRFCHW
@@ -1962,6 +2042,8 @@ const pta processor_alias_table[] =
M_CPU_TYPE (AMDFAM15H), P_NONE},
{"amdfam17h", PROCESSOR_GENERIC, CPU_GENERIC, 0,
M_CPU_TYPE (AMDFAM17H), P_NONE},
+ {"amdfam19h", PROCESSOR_GENERIC, CPU_GENERIC, 0,
+ M_CPU_TYPE (AMDFAM19H), P_NONE},
{"shanghai", PROCESSOR_GENERIC, CPU_GENERIC, 0,
M_CPU_TYPE (AMDFAM10H_SHANGHAI), P_NONE},
{"istanbul", PROCESSOR_GENERIC, CPU_GENERIC, 0,
diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
index 8c3f782..849e95a 100644
--- a/gcc/common/config/i386/i386-cpuinfo.h
+++ b/gcc/common/config/i386/i386-cpuinfo.h
@@ -55,6 +55,7 @@ enum processor_types
INTEL_GOLDMONT,
INTEL_GOLDMONT_PLUS,
INTEL_TREMONT,
+ AMDFAM19H,
CPU_TYPE_MAX,
BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
};
@@ -86,6 +87,7 @@ enum processor_subtypes
INTEL_COREI7_COOPERLAKE,
INTEL_COREI7_SAPPHIRERAPIDS,
INTEL_COREI7_ALDERLAKE,
+ AMDFAM19H_ZNVER3,
CPU_SUBTYPE_MAX
};
@@ -221,6 +223,10 @@ enum processor_features
FEATURE_AMX_BF16,
FEATURE_UINTR,
FEATURE_HRESET,
+ FEATURE_KL,
+ FEATURE_AESKLE,
+ FEATURE_WIDEKL,
+ FEATURE_AVXVNNI,
CPU_FEATURE_MAX
};
diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
index 888e325..c4fd036 100644
--- a/gcc/common/config/i386/i386-isas.h
+++ b/gcc/common/config/i386/i386-isas.h
@@ -165,4 +165,8 @@ ISA_NAMES_TABLE_START
ISA_NAMES_TABLE_ENTRY("amx-bf16", FEATURE_AMX_BF16, P_NONE, "-mamx-bf16")
ISA_NAMES_TABLE_ENTRY("uintr", FEATURE_UINTR, P_NONE, "-muintr")
ISA_NAMES_TABLE_ENTRY("hreset", FEATURE_HRESET, P_NONE, "-mhreset")
+ ISA_NAMES_TABLE_ENTRY("kl", FEATURE_KL, P_NONE, "-mkl")
+ ISA_NAMES_TABLE_ENTRY("aeskle", FEATURE_AESKLE, P_NONE, NULL)
+ ISA_NAMES_TABLE_ENTRY("widekl", FEATURE_WIDEKL, P_NONE, "-mwidekl")
+ ISA_NAMES_TABLE_ENTRY("avxvnni", FEATURE_AVXVNNI, P_NONE, "-mavxvnni")
ISA_NAMES_TABLE_END
diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index 4b6bdf8..5e3ddcf 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -44,6 +44,7 @@ struct riscv_subset_t
struct riscv_subset_t *next;
bool explicit_version_p;
+ bool implied_p;
};
/* Type for implied ISA info. */
@@ -54,12 +55,66 @@ struct riscv_implied_info_t
};
/* Implied ISA info, must end with NULL sentinel. */
-riscv_implied_info_t riscv_implied_info[] =
+static const riscv_implied_info_t riscv_implied_info[] =
{
{"d", "f"},
+ {"f", "zicsr"},
+ {"d", "zicsr"},
{NULL, NULL}
};
+/* This structure holds version information for specific ISA version. */
+
+struct riscv_ext_version
+{
+ const char *name;
+ enum riscv_isa_spec_class isa_spec_class;
+ int major_version;
+ int minor_version;
+};
+
+/* All standard extensions defined in all supported ISA spec. */
+static const struct riscv_ext_version riscv_ext_version_table[] =
+{
+ /* name, ISA spec, major version, minor_version. */
+ {"e", ISA_SPEC_CLASS_20191213, 1, 9},
+ {"e", ISA_SPEC_CLASS_20190608, 1, 9},
+ {"e", ISA_SPEC_CLASS_2P2, 1, 9},
+
+ {"i", ISA_SPEC_CLASS_20191213, 2, 1},
+ {"i", ISA_SPEC_CLASS_20190608, 2, 1},
+ {"i", ISA_SPEC_CLASS_2P2, 2, 0},
+
+ {"m", ISA_SPEC_CLASS_20191213, 2, 0},
+ {"m", ISA_SPEC_CLASS_20190608, 2, 0},
+ {"m", ISA_SPEC_CLASS_2P2, 2, 0},
+
+ {"a", ISA_SPEC_CLASS_20191213, 2, 1},
+ {"a", ISA_SPEC_CLASS_20190608, 2, 0},
+ {"a", ISA_SPEC_CLASS_2P2, 2, 0},
+
+ {"f", ISA_SPEC_CLASS_20191213, 2, 2},
+ {"f", ISA_SPEC_CLASS_20190608, 2, 2},
+ {"f", ISA_SPEC_CLASS_2P2, 2, 0},
+
+ {"d", ISA_SPEC_CLASS_20191213, 2, 2},
+ {"d", ISA_SPEC_CLASS_20190608, 2, 2},
+ {"d", ISA_SPEC_CLASS_2P2, 2, 0},
+
+ {"c", ISA_SPEC_CLASS_20191213, 2, 0},
+ {"c", ISA_SPEC_CLASS_20190608, 2, 0},
+ {"c", ISA_SPEC_CLASS_2P2, 2, 0},
+
+ {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0},
+ {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0},
+
+ {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0},
+ {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0},
+
+ /* Terminate the list. */
+ {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
+};
+
static const riscv_cpu_info riscv_cpu_tables[] =
{
#define RISCV_CORE(CORE_NAME, ARCH, TUNE) \
@@ -89,20 +144,22 @@ private:
riscv_subset_list (const char *, location_t);
- const char *parsing_subset_version (const char *, unsigned *, unsigned *,
- unsigned, unsigned, bool, bool *);
+ const char *parsing_subset_version (const char *, const char *, unsigned *,
+ unsigned *, bool, bool *);
const char *parse_std_ext (const char *);
const char *parse_multiletter_ext (const char *, const char *,
const char *);
- void handle_implied_ext (const char *, int, int, bool);
+ void handle_implied_ext (riscv_subset_t *);
public:
~riscv_subset_list ();
- void add (const char *, int, int, bool);
+ void add (const char *, int, int, bool, bool);
+
+ void add (const char *, bool);
riscv_subset_t *lookup (const char *,
int major_version = RISCV_DONT_CARE_VERSION,
@@ -122,7 +179,7 @@ static riscv_subset_list *current_subset_list = NULL;
riscv_subset_t::riscv_subset_t ()
: name (), major_version (0), minor_version (0), next (NULL),
- explicit_version_p (false)
+ explicit_version_p (false), implied_p (false)
{
}
@@ -145,13 +202,160 @@ riscv_subset_list::~riscv_subset_list ()
}
}
+/* Get the rank for single-letter subsets, lower value meaning higher
+ priority. */
+
+static int
+single_letter_subset_rank (char ext)
+{
+ int rank;
+
+ switch (ext)
+ {
+ case 'i':
+ return 0;
+ case 'e':
+ return 1;
+ default:
+ break;
+ }
+
+ const char *all_ext = riscv_supported_std_ext ();
+ const char *ext_pos = strchr (all_ext, ext);
+ if (ext_pos == NULL)
+ /* If got an unknown extension letter, then give it an alphabetical
+ order, but after all known standard extension. */
+ rank = strlen (all_ext) + ext - 'a';
+ else
+ rank = (int)(ext_pos - all_ext) + 2 /* e and i has higher rank. */;
+
+ return rank;
+}
+
+/* Get the rank for multi-letter subsets, lower value meaning higher
+ priority. */
+
+static int
+multi_letter_subset_rank (const std::string &subset)
+{
+ gcc_assert (subset.length () >= 2);
+ int high_order = -1;
+ int low_order = 0;
+ /* The order between multi-char extensions: s -> h -> z -> x. */
+ char multiletter_class = subset[0];
+ switch (multiletter_class)
+ {
+ case 's':
+ high_order = 0;
+ break;
+ case 'h':
+ high_order = 1;
+ break;
+ case 'z':
+ gcc_assert (subset.length () > 2);
+ high_order = 2;
+ break;
+ case 'x':
+ high_order = 3;
+ break;
+ default:
+ gcc_unreachable ();
+ return -1;
+ }
+
+ if (multiletter_class == 'z')
+ /* Order for z extension on spec: If multiple "Z" extensions are named, they
+ should be ordered first by category, then alphabetically within a
+ category - for example, "Zicsr_Zifencei_Zam". */
+ low_order = single_letter_subset_rank (subset[1]);
+ else
+ low_order = 0;
+
+ return (high_order << 8) + low_order;
+}
+
+/* subset compare
+
+ Returns an integral value indicating the relationship between the subsets:
+ Return value indicates
+ -1 B has higher order than A.
+ 0 A and B are same subset.
+ 1 A has higher order than B.
+
+*/
+
+static int
+subset_cmp (const std::string &a, const std::string &b)
+{
+ if (a == b)
+ return 0;
+
+ size_t a_len = a.length ();
+ size_t b_len = b.length ();
+
+ /* Single-letter extension always get higher order than
+ multi-letter extension. */
+ if (a_len == 1 && b_len != 1)
+ return 1;
+
+ if (a_len != 1 && b_len == 1)
+ return -1;
+
+ if (a_len == 1 && b_len == 1)
+ {
+ int rank_a = single_letter_subset_rank (a[0]);
+ int rank_b = single_letter_subset_rank (b[0]);
+
+ if (rank_a < rank_b)
+ return 1;
+ else
+ return -1;
+ }
+ else
+ {
+ int rank_a = multi_letter_subset_rank(a);
+ int rank_b = multi_letter_subset_rank(b);
+
+ /* Using alphabetical/lexicographical order if they have same rank. */
+ if (rank_a == rank_b)
+ /* The return value of strcmp has opposite meaning. */
+ return -strcmp (a.c_str (), b.c_str ());
+ else
+ return (rank_a < rank_b) ? 1 : -1;
+ }
+}
+
/* Add new subset to list. */
void
riscv_subset_list::add (const char *subset, int major_version,
- int minor_version, bool explicit_version_p)
+ int minor_version, bool explicit_version_p,
+ bool implied_p)
{
+ riscv_subset_t *ext = lookup (subset);
+
+ if (ext)
+ {
+ if (ext->implied_p)
+ {
+ /* We won't add impiled `ext` if it already in list. */
+ gcc_assert (!implied_p);
+ ext->implied_p = implied_p;
+ ext->major_version = major_version;
+ ext->minor_version = minor_version;
+ }
+ else
+ error_at (
+ m_loc,
+ "%<-march=%s%>: Extension `%s' appear more than one time.",
+ m_arch,
+ subset);
+
+ return;
+ }
+
riscv_subset_t *s = new riscv_subset_t ();
+ riscv_subset_t *itr;
if (m_head == NULL)
m_head = s;
@@ -160,14 +364,88 @@ riscv_subset_list::add (const char *subset, int major_version,
s->major_version = major_version;
s->minor_version = minor_version;
s->explicit_version_p = explicit_version_p;
+ s->implied_p = implied_p;
s->next = NULL;
- if (m_tail != NULL)
- m_tail->next = s;
+ if (m_tail == NULL)
+ {
+ m_tail = s;
+ return;
+ }
+
+ /* e, i or g should be first subext, never come here. */
+ gcc_assert (subset[0] != 'e'
+ && subset[0] != 'i'
+ && subset[0] != 'g');
+
+ if (m_tail == m_head)
+ {
+ gcc_assert (m_head->next == NULL);
+ m_head->next = s;
+ m_tail = s;
+ return;
+ }
+ gcc_assert (m_head->next != NULL);
+
+ /* Subset list must in canonical order, but implied subset won't
+ add in canonical order. */
+ for (itr = m_head; itr->next != NULL; itr = itr->next)
+ {
+ riscv_subset_t *next = itr->next;
+ int cmp = subset_cmp (s->name, next->name);
+ gcc_assert (cmp != 0);
+
+ if (cmp > 0)
+ {
+ s->next = next;
+ itr->next = s;
+ return;
+ }
+ }
+
+ /* Insert at tail of the list. */
+ itr->next = s;
m_tail = s;
}
+static void
+get_default_version (const char *ext,
+ unsigned int *major_version,
+ unsigned int *minor_version)
+{
+ const riscv_ext_version *ext_ver;
+ for (ext_ver = &riscv_ext_version_table[0];
+ ext_ver->name != NULL;
+ ++ext_ver)
+ if (strcmp (ext, ext_ver->name) == 0)
+ {
+ if ((ext_ver->isa_spec_class == riscv_isa_spec) ||
+ (ext_ver->isa_spec_class == ISA_SPEC_CLASS_NONE))
+ {
+ *major_version = ext_ver->major_version;
+ *minor_version = ext_ver->minor_version;
+ return;
+ }
+ }
+
+ /* Not found version info. */
+ *major_version = 0;
+ *minor_version = 0;
+}
+
+/* Add new subset to list, but using default version from ISA spec version. */
+
+void
+riscv_subset_list::add (const char *subset, bool implied_p)
+{
+ unsigned int major_version = 0, minor_version = 0;
+
+ get_default_version (subset, &major_version, &minor_version);
+
+ add (subset, major_version, minor_version, false, implied_p);
+}
+
/* Convert subset info to string with explicit version info,
VERSION_P to determine append version info or not. */
@@ -178,10 +456,37 @@ riscv_subset_list::to_string (bool version_p) const
oss << "rv" << m_xlen;
bool first = true;
- riscv_subset_t *subset = m_head;
+ riscv_subset_t *subset;
+
+ bool skip_zifencei = false;
+ bool skip_zicsr = false;
+
+ /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifencei is
+ included in the base ISA. */
+ if (riscv_isa_spec == ISA_SPEC_CLASS_2P2)
+ {
+ skip_zifencei = true;
+ skip_zicsr = true;
+ }
- while (subset != NULL)
+#ifndef HAVE_AS_MISA_SPEC
+ /* Skip since older binutils doesn't recognize zicsr. */
+ skip_zicsr = true;
+#endif
+#ifndef HAVE_AS_MARCH_ZIFENCE
+ /* Skip since older binutils doesn't recognize zifencei, we made
+ a mistake in that binutils 2.35 supports zicsr but not zifencei. */
+ skip_zifencei = true;
+#endif
+
+ for (subset = m_head; subset != NULL; subset = subset->next)
{
+ if (subset->implied_p && skip_zifencei && subset->name == "zifencei")
+ continue;
+
+ if (subset->implied_p && skip_zicsr && subset->name == "zicsr")
+ continue;
+
/* For !version_p, we only separate extension with underline for
multi-letter extension. */
if (!first &&
@@ -193,12 +498,12 @@ riscv_subset_list::to_string (bool version_p) const
oss << subset->name;
- if (version_p || subset->explicit_version_p)
+ /* Let binutils decide the extension version if we don't know. */
+ if ((version_p || subset->explicit_version_p) &&
+ (subset->major_version != 0 || subset->minor_version != 0))
oss << subset->major_version
<< 'p'
<< subset->minor_version;
-
- subset = subset->next;
}
return oss.str ();
@@ -246,23 +551,21 @@ riscv_supported_std_ext (void)
Points to the end of version
Arguments:
+ `ext`: This extension.
`p`: Current parsing position.
`major_version`: Parsing result of major version, using
default_major_version if version is not present in arch string.
`minor_version`: Parsing result of minor version, set to 0 if version is
not present in arch string, but set to `default_minor_version` if
`major_version` using default_major_version.
- `default_major_version`: Default major version.
- `default_minor_version`: Default minor version.
`std_ext_p`: True if parsing std extension.
`explicit_version_p`: True if this subset is not using default version. */
const char *
-riscv_subset_list::parsing_subset_version (const char *p,
+riscv_subset_list::parsing_subset_version (const char *ext,
+ const char *p,
unsigned *major_version,
unsigned *minor_version,
- unsigned default_major_version,
- unsigned default_minor_version,
bool std_ext_p,
bool *explicit_version_p)
{
@@ -313,11 +616,7 @@ riscv_subset_list::parsing_subset_version (const char *p,
minor = version;
if (major == 0 && minor == 0)
- {
- /* We didn't find any version string, use default version. */
- *major_version = default_major_version;
- *minor_version = default_minor_version;
- }
+ get_default_version (ext, major_version, minor_version);
else
{
*explicit_version_p = true;
@@ -351,23 +650,17 @@ riscv_subset_list::parse_std_ext (const char *p)
{
case 'i':
p++;
- p = parsing_subset_version (p, &major_version, &minor_version,
- /* default_major_version= */ 2,
- /* default_minor_version= */ 0,
- /* std_ext_p= */ true,
- &explicit_version_p);
- add ("i", major_version, minor_version, explicit_version_p);
+ p = parsing_subset_version ("i", p, &major_version, &minor_version,
+ /* std_ext_p= */ true, &explicit_version_p);
+ add ("i", major_version, minor_version, explicit_version_p, false);
break;
case 'e':
p++;
- p = parsing_subset_version (p, &major_version, &minor_version,
- /* default_major_version= */ 1,
- /* default_minor_version= */ 9,
- /* std_ext_p= */ true,
- &explicit_version_p);
+ p = parsing_subset_version ("e", p, &major_version, &minor_version,
+ /* std_ext_p= */ true, &explicit_version_p);
- add ("e", major_version, minor_version, explicit_version_p);
+ add ("e", major_version, minor_version, explicit_version_p, false);
if (m_xlen > 32)
{
@@ -379,18 +672,26 @@ riscv_subset_list::parse_std_ext (const char *p)
case 'g':
p++;
- p = parsing_subset_version (p, &major_version, &minor_version,
- /* default_major_version= */ 2,
- /* default_minor_version= */ 0,
- /* std_ext_p= */ true,
- &explicit_version_p);
- add ("i", major_version, minor_version, explicit_version_p);
-
- for (; *std_exts != 'q'; std_exts++)
+ p = parsing_subset_version ("g", p, &major_version, &minor_version,
+ /* std_ext_p= */ true, &explicit_version_p);
+ if (major_version != 0 || minor_version != 0)
{
- const char subset[] = {*std_exts, '\0'};
- add (subset, major_version, minor_version, explicit_version_p);
+ warning_at (m_loc, 0, "version of `g` will be omitted, please "
+ "specify version for individual extension.");
}
+
+ /* We have special rule for G, we disallow rv32gm2p but allow rv32g_zicsr
+ here, basically we treating G expand to imafd and implied zicsr and
+ zifencei. */
+
+ add ("i", false);
+ add ("m", false);
+ add ("a", false);
+ add ("f", false);
+ add ("d", false);
+ add ("zicsr", true);
+ add ("zifencei", true);
+
break;
default:
@@ -433,47 +734,47 @@ riscv_subset_list::parse_std_ext (const char *p)
std_exts++;
p++;
- p = parsing_subset_version (p, &major_version, &minor_version,
- /* default_major_version= */ 2,
- /* default_minor_version= */ 0,
- /* std_ext_p= */ true,
- &explicit_version_p);
-
subset[0] = std_ext;
- handle_implied_ext (subset, major_version,
- minor_version, explicit_version_p);
+ p = parsing_subset_version (subset, p, &major_version, &minor_version,
+ /* std_ext_p= */ true, &explicit_version_p);
- add (subset, major_version, minor_version, explicit_version_p);
+ add (subset, major_version, minor_version, explicit_version_p, false);
}
return p;
}
-/* Check any implied extensions for EXT with version
- MAJOR_VERSION.MINOR_VERSION, EXPLICIT_VERSION_P indicate the version is
- explicitly given by user or not. */
+/* Check any implied extensions for EXT. */
void
-riscv_subset_list::handle_implied_ext (const char *ext,
- int major_version,
- int minor_version,
- bool explicit_version_p)
+riscv_subset_list::handle_implied_ext (riscv_subset_t *ext)
{
- riscv_implied_info_t *implied_info;
+ const riscv_implied_info_t *implied_info;
for (implied_info = &riscv_implied_info[0];
implied_info->ext;
++implied_info)
{
- if (strcmp (ext, implied_info->ext) != 0)
+ if (strcmp (ext->name.c_str (), implied_info->ext) != 0)
continue;
/* Skip if implied extension already present. */
if (lookup (implied_info->implied_ext))
continue;
- /* TODO: Implied extension might use different version. */
- add (implied_info->implied_ext, major_version, minor_version,
- explicit_version_p);
+ /* Version of implied extension will get from current ISA spec
+ version. */
+ add (implied_info->implied_ext, true);
+ }
+
+ /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifence is
+ included in the base ISA. */
+ if (riscv_isa_spec == ISA_SPEC_CLASS_2P2)
+ {
+ if (lookup ("zicsr") == NULL)
+ add ("zicsr", true);
+
+ if (lookup ("zifencei") == NULL)
+ add ("zifencei", true);
}
}
@@ -511,20 +812,33 @@ riscv_subset_list::parse_multiletter_ext (const char *p,
char *q = subset;
const char *end_of_version;
bool explicit_version_p = false;
+ char *ext;
+ char backup;
while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
;
+ backup = *q;
+ *q = '\0';
+ ext = xstrdup (subset);
+ *q = backup;
+
end_of_version
- = parsing_subset_version (q, &major_version, &minor_version,
- /* default_major_version= */ 2,
- /* default_minor_version= */ 0,
- /* std_ext_p= */ FALSE,
- &explicit_version_p);
+ = parsing_subset_version (ext, q, &major_version, &minor_version,
+ /* std_ext_p= */ false, &explicit_version_p);
+ free (ext);
*q = '\0';
- add (subset, major_version, minor_version, explicit_version_p);
+ if (strlen (subset) == 1)
+ {
+ error_at (m_loc, "%<-march=%s%>: name of %s must be more than 1 letter",
+ m_arch, ext_type_str);
+ free (subset);
+ return NULL;
+ }
+
+ add (subset, major_version, minor_version, explicit_version_p, false);
free (subset);
p += end_of_version - subset;
@@ -545,6 +859,7 @@ riscv_subset_list *
riscv_subset_list::parse (const char *arch, location_t loc)
{
riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
+ riscv_subset_t *itr;
const char *p = arch;
if (strncmp (p, "rv32", 4) == 0)
{
@@ -600,6 +915,11 @@ riscv_subset_list::parse (const char *arch, location_t loc)
goto fail;
}
+ for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
+ {
+ subset_list->handle_implied_ext (itr);
+ }
+
return subset_list;
fail:
@@ -618,44 +938,68 @@ riscv_arch_str (bool version_p)
return std::string();
}
+/* Type for pointer to member of gcc_options. */
+typedef int (gcc_options::*opt_var_ref_t);
+
+/* Types for recording extension to internal flag. */
+struct riscv_ext_flag_table_t {
+ const char *ext;
+ opt_var_ref_t var_ref;
+ int mask;
+};
+
+/* Mapping table between extension to internal flag. */
+static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
+{
+ {"e", &gcc_options::x_target_flags, MASK_RVE},
+ {"m", &gcc_options::x_target_flags, MASK_MUL},
+ {"a", &gcc_options::x_target_flags, MASK_ATOMIC},
+ {"f", &gcc_options::x_target_flags, MASK_HARD_FLOAT},
+ {"d", &gcc_options::x_target_flags, MASK_DOUBLE_FLOAT},
+ {"c", &gcc_options::x_target_flags, MASK_RVC},
+
+ {"zicsr", &gcc_options::x_riscv_zi_subext, MASK_ZICSR},
+ {"zifencei", &gcc_options::x_riscv_zi_subext, MASK_ZIFENCEI},
+
+ {NULL, NULL, 0}
+};
+
/* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
dependent mask bits, in case more than one -march string is passed. */
static void
-riscv_parse_arch_string (const char *isa, int *flags, location_t loc)
+riscv_parse_arch_string (const char *isa,
+ struct gcc_options *opts,
+ location_t loc)
{
riscv_subset_list *subset_list;
subset_list = riscv_subset_list::parse (isa, loc);
if (!subset_list)
return;
- if (subset_list->xlen () == 32)
- *flags &= ~MASK_64BIT;
- else if (subset_list->xlen () == 64)
- *flags |= MASK_64BIT;
-
- *flags &= ~MASK_RVE;
- if (subset_list->lookup ("e"))
- *flags |= MASK_RVE;
-
- *flags &= ~MASK_MUL;
- if (subset_list->lookup ("m"))
- *flags |= MASK_MUL;
-
- *flags &= ~MASK_ATOMIC;
- if (subset_list->lookup ("a"))
- *flags |= MASK_ATOMIC;
-
- *flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT);
- if (subset_list->lookup ("f"))
- *flags |= MASK_HARD_FLOAT;
-
- if (subset_list->lookup ("d"))
- *flags |= MASK_DOUBLE_FLOAT;
-
- *flags &= ~MASK_RVC;
- if (subset_list->lookup ("c"))
- *flags |= MASK_RVC;
+ if (opts)
+ {
+ const riscv_ext_flag_table_t *arch_ext_flag_tab;
+ /* Clean up target flags before we set. */
+ for (arch_ext_flag_tab = &riscv_ext_flag_table[0];
+ arch_ext_flag_tab->ext;
+ ++arch_ext_flag_tab)
+ opts->*arch_ext_flag_tab->var_ref &= ~arch_ext_flag_tab->mask;
+
+ if (subset_list->xlen () == 32)
+ opts->x_target_flags &= ~MASK_64BIT;
+ else if (subset_list->xlen () == 64)
+ opts->x_target_flags |= MASK_64BIT;
+
+
+ for (arch_ext_flag_tab = &riscv_ext_flag_table[0];
+ arch_ext_flag_tab->ext;
+ ++arch_ext_flag_tab)
+ {
+ if (subset_list->lookup (arch_ext_flag_tab->ext))
+ opts->*arch_ext_flag_tab->var_ref |= arch_ext_flag_tab->mask;
+ }
+ }
if (current_subset_list)
delete current_subset_list;
@@ -689,7 +1033,7 @@ riscv_handle_option (struct gcc_options *opts,
switch (decoded->opt_index)
{
case OPT_march_:
- riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc);
+ riscv_parse_arch_string (decoded->arg, opts, loc);
return true;
case OPT_mcpu_:
@@ -710,9 +1054,8 @@ riscv_expand_arch (int argc ATTRIBUTE_UNUSED,
const char **argv)
{
gcc_assert (argc == 1);
- int flags;
location_t loc = UNKNOWN_LOCATION;
- riscv_parse_arch_string (argv[0], &flags, loc);
+ riscv_parse_arch_string (argv[0], NULL, loc);
const std::string arch = riscv_arch_str (false);
if (arch.length())
return xasprintf ("-march=%s", arch.c_str());
@@ -760,9 +1103,8 @@ riscv_expand_arch_from_cpu (int argc ATTRIBUTE_UNUSED,
arch_str = cpu->arch;
location_t loc = UNKNOWN_LOCATION;
- int flags;
- riscv_parse_arch_string (arch_str, &flags, loc);
+ riscv_parse_arch_string (arch_str, NULL, loc);
const std::string arch = riscv_arch_str (false);
return xasprintf ("-march=%s", arch.c_str());
}
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 411200d..70ecc51 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -414,7 +414,7 @@ i[34567]86-*-*)
avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h
tsxldtrkintrin.h amxtileintrin.h amxint8intrin.h
amxbf16intrin.h x86gprintrin.h uintrintrin.h
- hresetintrin.h"
+ hresetintrin.h keylockerintrin.h avxvnniintrin.h"
;;
x86_64-*-*)
cpu_type=i386
@@ -451,7 +451,7 @@ x86_64-*-*)
avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h
tsxldtrkintrin.h amxtileintrin.h amxint8intrin.h
amxbf16intrin.h x86gprintrin.h uintrintrin.h
- hresetintrin.h"
+ hresetintrin.h keylockerintrin.h avxvnniintrin.h"
;;
ia64-*-*)
extra_headers=ia64intrin.h
@@ -668,7 +668,7 @@ c7 esther"
# 64-bit x86 processors supported by --with-arch=. Each processor
# MUST be separated by exactly one space.
x86_64_archs="amdfam10 athlon64 athlon64-sse3 barcelona bdver1 bdver2 \
-bdver3 bdver4 znver1 znver2 btver1 btver2 k8 k8-sse3 opteron \
+bdver3 bdver4 znver1 znver2 znver3 btver1 btver2 k8 k8-sse3 opteron \
opteron-sse3 nocona core2 corei7 corei7-avx core-avx-i core-avx2 atom \
slm nehalem westmere sandybridge ivybridge haswell broadwell bonnell \
silvermont knl knm skylake-avx512 cannonlake icelake-client icelake-server \
@@ -702,8 +702,10 @@ case ${target} in
extra_options="${extra_options} darwin.opt"
c_target_objs="${c_target_objs} darwin-c.o"
cxx_target_objs="${cxx_target_objs} darwin-c.o"
+ d_target_objs="${d_target_objs} darwin-d.o"
fortran_target_objs="darwin-f.o"
target_has_targetcm=yes
+ target_has_targetdm=yes
extra_objs="${extra_objs} darwin.o"
extra_gcc_objs="darwin-driver.o"
default_use_cxa_atexit=yes
@@ -731,6 +733,9 @@ case ${target} in
extra_options="$extra_options rpath.opt dragonfly.opt"
default_use_cxa_atexit=yes
use_gcc_stdint=wrap
+ d_target_objs="${d_target_objs} dragonfly-d.o"
+ tmake_file="${tmake_file} t-dragonfly"
+ target_has_targetdm=yes
;;
*-*-freebsd*)
# This is the generic ELF configuration of FreeBSD. Later
@@ -779,6 +784,9 @@ case ${target} in
default_use_cxa_atexit=yes;;
esac
use_gcc_stdint=wrap
+ d_target_objs="${d_target_objs} freebsd-d.o"
+ tmake_file="${tmake_file} t-freebsd"
+ target_has_targetdm=yes
;;
*-*-fuchsia*)
native_system_header_dir=/include
@@ -2050,7 +2058,7 @@ i[34567]86-*-solaris2* | x86_64-*-solaris2*)
esac
fi
;;
-i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae|i[4567]86-wrs-vxworks7|x86_64-wrs-vxworks7)
+i[4567]86-wrs-vxworks*|x86_64-wrs-vxworks7*)
tm_file="${tm_file} i386/unix.h i386/att.h elfos.h"
case ${target} in
x86_64-*)
@@ -2438,11 +2446,13 @@ riscv*-*-elf* | riscv*-*-rtems*)
tmake_file="${tmake_file} riscv/t-rtems"
;;
*)
- case "x${enable_multilib}" in
- xno) ;;
- xyes) tmake_file="${tmake_file} riscv/t-elf-multilib" ;;
- *) echo "Unknown value for enable_multilib"; exit 1
- esac
+ if test "x${with_multilib_generator}" == xdefault; then
+ case "x${enable_multilib}" in
+ xno) ;;
+ xyes) tmake_file="${tmake_file} riscv/t-elf-multilib" ;;
+ *) echo "Unknown value for enable_multilib"; exit 1
+ esac
+ fi
esac
tmake_file="${tmake_file} riscv/t-riscv"
gnu_ld=yes
@@ -2856,6 +2866,10 @@ powerpc*-*-freebsd*)
extra_options="${extra_options} rs6000/sysv4.opt"
tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
case ${target} in
+ powerpc*le-*-*)
+ tm_file="${tm_file} rs6000/sysv4le.h" ;;
+ esac
+ case ${target} in
powerpc64*)
tm_file="${tm_file} rs6000/default64.h rs6000/freebsd64.h"
tmake_file="${tmake_file} rs6000/t-freebsd64"
@@ -3668,6 +3682,10 @@ case ${target} in
arch=znver2
cpu=znver2
;;
+ znver3-*)
+ arch=znver3
+ cpu=znver3
+ ;;
bdver4-*)
arch=bdver4
cpu=bdver4
@@ -3789,6 +3807,10 @@ case ${target} in
arch=znver2
cpu=znver2
;;
+ znver3-*)
+ arch=znver3
+ cpu=znver3
+ ;;
bdver4-*)
arch=bdver4
cpu=bdver4
@@ -4081,9 +4103,17 @@ fi
supported_defaults=
case "${target}" in
aarch64*-*-*)
- supported_defaults="abi cpu arch"
- for which in cpu arch; do
-
+ supported_defaults="abi cpu cpu_64 arch arch_64 tune tune_64"
+ if test x$with_cpu_64 != x && test x$with_cpu = x; then
+ with_cpu=$with_cpu_64
+ fi
+ if test x$with_arch_64 != x && test x$with_arch = x; then
+ with_arch=$with_arch_64
+ fi
+ if test x$with_tune_64 != x && test x$with_tune = x; then
+ with_tune=$with_tune_64
+ fi
+ for which in cpu arch tune; do
eval "val=\$with_$which"
base_val=`echo $val | sed -e 's/\+.*//'`
ext_val=`echo $val | sed -e 's/[a-z0-9.-]\+//'`
@@ -4122,6 +4152,12 @@ case "${target}" in
sed -e 's/,.*$//'`
fi
+ # Disallow extensions in --with-tune=cortex-a53+crc.
+ if [ $which = tune ] && [ x"$ext_val" != x ]; then
+ echo "Architecture extensions not supported in --with-$which=$val" 1>&2
+ exit 1
+ fi
+
# Use the pre-processor to strip flatten the options.
# This makes the format less rigid than if we use
# grep and sed directly here.
@@ -4179,8 +4215,13 @@ case "${target}" in
fi
true
else
- echo "Unknown $which used in --with-$which=$val" 1>&2
- exit 1
+ # Allow --with-$which=native.
+ if [ "$val" = native ]; then
+ true
+ else
+ echo "Unknown $which used in --with-$which=$val" 1>&2
+ exit 1
+ fi
fi
done
;;
@@ -4482,10 +4523,8 @@ case "${target}" in
case " $x86_64_archs " in
*" ${val} "*)
# Disallow x86-64-v* for --with-cpu=/--with-tune=
- # or --with-arch= or --with-arch_32=
- # It can be only specified in --with-arch_64=
case "x$which$val" in
- xcpu*x86-64-v*|xtune*x86-64-v*|xarchx86-64-v*|xarch_32x86-64-v*)
+ xcpu*x86-64-v*|xtune*x86-64-v*)
echo "Unknown CPU given in --with-$which=$val." 1>&2
exit 1
;;
@@ -4522,7 +4561,7 @@ case "${target}" in
;;
riscv*-*-*)
- supported_defaults="abi arch tune riscv_attribute"
+ supported_defaults="abi arch tune riscv_attribute isa_spec"
case "${target}" in
riscv-* | riscv32*) xlen=32 ;;
@@ -4530,6 +4569,21 @@ case "${target}" in
*) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
esac
+ case "${with_isa_spec}" in
+ ""|default|2.2)
+ tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2"
+ ;;
+ 20191213 | 201912)
+ tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20191213"
+ ;;
+ 20190608 | 201906)
+ tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20190608"
+ ;;
+ *)
+ echo "--with-isa-spec only accept 2.2, 20191213, 201912, 20190608 or 201906" 1>&2
+ exit 1
+ esac
+
case "${with_riscv_attribute}" in
yes)
tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
@@ -4573,6 +4627,11 @@ case "${target}" in
exit 1
;;
esac
+ PYTHON=`which python || which python3 || which python2`
+ if test "x${PYTHON}" != x; then
+ with_arch=`${PYTHON} ${srcdir}/config/riscv/arch-canonicalize ${with_arch}`
+ fi
+ tm_defines="${tm_defines} TARGET_RISCV_DEFAULT_ARCH=${with_arch}"
# Make sure --with-abi is valid. If it was not specified,
# pick a default based on the ISA, preferring soft-float
@@ -4594,6 +4653,7 @@ case "${target}" in
exit 1
;;
esac
+ tm_defines="${tm_defines} TARGET_RISCV_DEFAULT_ABI=${with_abi}"
# Make sure ABI and ISA are compatible.
case "${with_abi},${with_arch}" in
@@ -4609,10 +4669,33 @@ case "${target}" in
exit 1
;;
esac
+ # Handle --with-multilib-generator.
+ if test "x${with_multilib_generator}" != xdefault; then
+ if test "x${with_multilib_list}" != xdefault; then
+ echo "--with-multilib-list= can't used with --with-multilib-generator= at same time" 1>&2
+ exit 1
+ fi
+ case "${target}" in
+ riscv*-*-elf*)
+ if ${srcdir}/config/riscv/multilib-generator \
+ `echo ${with_multilib_generator} | sed 's/;/ /g'`\
+ > t-multilib-config;
+ then
+ tmake_file="${tmake_file} riscv/t-withmultilib-generator"
+ else
+ echo "invalid option for --with-multilib-generator" 1>&2
+ exit 1
+ fi
+ ;;
+ *)
+ echo "--with-multilib-generator= is not supported for ${target}, only supported for riscv*-*-elf*" 1>&2
+ exit 1
+ ;;
+ esac
+ fi
# Handle --with-multilib-list.
if test "x${with_multilib_list}" != xdefault; then
- tm_file="${tm_file} riscv/withmultilib.h"
tmake_file="${tmake_file} riscv/t-withmultilib"
case ${with_multilib_list} in
@@ -4624,42 +4707,6 @@ case "${target}" in
echo "--with-multilib-list=${with_multilib_list} not supported."
exit 1
esac
-
- # Define macros to select the default multilib.
- case ${with_arch} in
- rv32gc)
- tm_defines="${tm_defines} TARGET_MLIB_ARCH=1"
- ;;
- rv64gc)
- tm_defines="${tm_defines} TARGET_MLIB_ARCH=2"
- ;;
- *)
- echo "unsupported --with-arch for --with-multilib-list"
- exit 1
- esac
- case ${with_abi} in
- ilp32)
- tm_defines="${tm_defines} TARGET_MLIB_ABI=1"
- ;;
- ilp32f)
- tm_defines="${tm_defines} TARGET_MLIB_ABI=2"
- ;;
- ilp32d)
- tm_defines="${tm_defines} TARGET_MLIB_ABI=3"
- ;;
- lp64)
- tm_defines="${tm_defines} TARGET_MLIB_ABI=4"
- ;;
- lp64f)
- tm_defines="${tm_defines} TARGET_MLIB_ABI=5"
- ;;
- lp64d)
- tm_defines="${tm_defines} TARGET_MLIB_ABI=6"
- ;;
- *)
- echo "unsupported --with-abi for --with-multilib"
- exit 1
- esac
fi
;;
@@ -5200,8 +5247,8 @@ case ${target} in
i[34567]86-*-darwin* | x86_64-*-darwin*)
;;
i[34567]86-*-linux* | x86_64-*-linux*)
- extra_objs="${extra_objs} cet.o"
- tmake_file="$tmake_file i386/t-linux i386/t-cet"
+ extra_objs="${extra_objs} gnu-property.o"
+ tmake_file="$tmake_file i386/t-linux i386/t-gnu-property"
;;
i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
tmake_file="$tmake_file i386/t-kfreebsd"
diff --git a/gcc/config.in b/gcc/config.in
index b7c3107..10a13cd 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -236,6 +236,16 @@
/* Define if you want runtime assertions enabled. This is a cheap check. */
#undef ENABLE_RUNTIME_CHECKING
+/* Define to enable evaluating float expressions with double precision in
+ standards-compatible mode on s390 targets. */
+#undef ENABLE_S390_EXCESS_FLOAT_PRECISION
+
+/* Define if the -stdlib= option should be enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_STDLIB_OPTION
+#endif
+
+
/* Define if you want all operations on trees (the basic data structure of the
front ends) to be checked for dynamic type safety at runtime. This is
moderately expensive. */
@@ -302,6 +312,18 @@
#endif
+/* Define if AF_INET6 supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AF_INET6
+#endif
+
+
+/* Define if AF_UNIX supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AF_UNIX
+#endif
+
+
/* Define if your assembler supports architecture modifiers. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_ARCHITECTURE_MODIFIERS
@@ -564,12 +586,24 @@
#endif
+/* Define if the assembler understands -march=rv*_zifencei. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZIFENCEI
+#endif
+
+
/* Define if your assembler supports mfcr field. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_MFCRF
#endif
+/* Define if the assembler understands -misa-spec=. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MISA_SPEC
+#endif
+
+
/* Define if your Mac OS X assembler supports the -mmacos-version-min option.
*/
#ifndef USED_FOR_TARGET
@@ -1253,6 +1287,12 @@
#endif
+/* Define to 1 if you have the `fstatat' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FSTATAT
+#endif
+
+
/* Define to 1 if you have the <ftw.h> header file. */
#ifndef USED_FOR_TARGET
#undef HAVE_FTW_H
@@ -1352,6 +1392,19 @@
#endif
+/* Define 0/1 if your assembler supports 'o' flag in .section directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SECTION_LINK_ORDER
+#endif
+
+
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
*/
#ifndef USED_FOR_TARGET
@@ -1758,6 +1811,12 @@
#endif
+/* Define to 1 if you have the `posix_fallocate' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_POSIX_FALLOCATE
+#endif
+
+
/* Define to 1 if you have the `putchar_unlocked' function. */
#ifndef USED_FOR_TARGET
#undef HAVE_PUTCHAR_UNLOCKED
@@ -1782,6 +1841,12 @@
#endif
+/* Define if <sys/signal.h> defines sighandler_t */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SIGHANDLER_T
+#endif
+
+
/* Define if the system-provided CRTs are present on Solaris. */
#ifndef USED_FOR_TARGET
#undef HAVE_SOLARIS_CRTS
@@ -2021,6 +2086,12 @@
#endif
+/* Define if O_CLOEXEC supported by fcntl. */
+#ifndef USED_FOR_TARGET
+#undef HOST_HAS_O_CLOEXEC
+#endif
+
+
/* Define as const if the declaration of iconv() needs const. */
#ifndef USED_FOR_TARGET
#undef ICONV_CONST
diff --git a/gcc/config/aarch64/aarch64-bti-insert.c b/gcc/config/aarch64/aarch64-bti-insert.c
index 57663ee..9802669 100644
--- a/gcc/config/aarch64/aarch64-bti-insert.c
+++ b/gcc/config/aarch64/aarch64-bti-insert.c
@@ -95,7 +95,7 @@ static bool
aarch64_pac_insn_p (rtx x)
{
if (!INSN_P (x))
- return x;
+ return false;
subrtx_var_iterator::array_type array;
FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (x), ALL)
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 732a4dc..188fce0 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -132,6 +132,7 @@ const unsigned int FLAG_AUTO_FP = 1U << 5;
const unsigned int FLAG_FP = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS;
const unsigned int FLAG_ALL = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS
| FLAG_READ_MEMORY | FLAG_PREFETCH_MEMORY | FLAG_WRITE_MEMORY;
+const unsigned int FLAG_STORE = FLAG_WRITE_MEMORY | FLAG_AUTO_FP;
typedef struct
{
@@ -265,6 +266,11 @@ static enum aarch64_type_qualifiers
aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
#define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
+#define TYPES_USHIFT2IMM (aarch64_types_ternopu_imm_qualifiers)
+static enum aarch64_type_qualifiers
+aarch64_types_shift2_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_unsigned, qualifier_unsigned, qualifier_none, qualifier_immediate };
+#define TYPES_SHIFT2IMM_UUSS (aarch64_types_shift2_to_unsigned_qualifiers)
static enum aarch64_type_qualifiers
aarch64_types_ternop_s_imm_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
@@ -276,6 +282,7 @@ aarch64_types_ternop_s_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
#define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
#define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
#define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
+#define TYPES_SHIFT2IMM (aarch64_types_ternop_s_imm_qualifiers)
static enum aarch64_type_qualifiers
aarch64_types_ternop_p_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
@@ -1855,10 +1862,10 @@ aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
only need to know the order in a V2mode. */
lane_idx = aarch64_endian_lane_rtx (V2DImode, lane);
- if (!target)
+ if (!target
+ || !REG_P (target)
+ || GET_MODE (target) != d->mode)
target = gen_reg_rtx (d->mode);
- else
- target = force_reg (d->mode, target);
rtx pat = NULL_RTX;
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index 3aa13f6..701fb7a 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -105,6 +105,7 @@ AARCH64_CORE("cortex-a76ae", cortexa76ae, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH
AARCH64_CORE("cortex-a77", cortexa77, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
AARCH64_CORE("cortex-a78", cortexa78, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
AARCH64_CORE("cortex-a78ae", cortexa78ae, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
+AARCH64_CORE("cortex-a78c", cortexa78c, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
AARCH64_CORE("cortex-a65", cortexa65, cortexa53, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
AARCH64_CORE("cortex-a65ae", cortexa65ae, cortexa53, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
AARCH64_CORE("cortex-x1", cortexx1, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
diff --git a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h
index e587e2e..b1d1f67 100644
--- a/gcc/config/aarch64/aarch64-linux.h
+++ b/gcc/config/aarch64/aarch64-linux.h
@@ -64,8 +64,6 @@
} \
while (0)
-#define GNU_USER_TARGET_D_CRITSEC_SIZE 48
-
#define TARGET_ASM_FILE_END aarch64_file_end_indicate_exec_stack
/* Uninitialized common symbols in non-PIE executables, even with
diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def
index af972e8..f304992 100644
--- a/gcc/config/aarch64/aarch64-modes.def
+++ b/gcc/config/aarch64/aarch64-modes.def
@@ -136,11 +136,13 @@ ADJUST_NUNITS (VNx2QI, aarch64_sve_vg);
ADJUST_NUNITS (VNx2HI, aarch64_sve_vg);
ADJUST_NUNITS (VNx2SI, aarch64_sve_vg);
ADJUST_NUNITS (VNx2HF, aarch64_sve_vg);
+ADJUST_NUNITS (VNx2BF, aarch64_sve_vg);
ADJUST_NUNITS (VNx2SF, aarch64_sve_vg);
ADJUST_NUNITS (VNx4QI, aarch64_sve_vg * 2);
ADJUST_NUNITS (VNx4HI, aarch64_sve_vg * 2);
ADJUST_NUNITS (VNx4HF, aarch64_sve_vg * 2);
+ADJUST_NUNITS (VNx4BF, aarch64_sve_vg * 2);
ADJUST_NUNITS (VNx8QI, aarch64_sve_vg * 4);
@@ -151,7 +153,9 @@ ADJUST_ALIGNMENT (VNx8QI, 1);
ADJUST_ALIGNMENT (VNx2HI, 2);
ADJUST_ALIGNMENT (VNx4HI, 2);
ADJUST_ALIGNMENT (VNx2HF, 2);
+ADJUST_ALIGNMENT (VNx2BF, 2);
ADJUST_ALIGNMENT (VNx4HF, 2);
+ADJUST_ALIGNMENT (VNx4BF, 2);
ADJUST_ALIGNMENT (VNx2SI, 4);
ADJUST_ALIGNMENT (VNx2SF, 4);
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index ca08642..7db0a9f 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -226,4 +226,10 @@ AARCH64_OPT_EXTENSION("f64mm", AARCH64_FL_F64MM, \
AARCH64_OPT_EXTENSION("bf16", AARCH64_FL_BF16, \
AARCH64_FL_SIMD | AARCH64_FL_FP, 0, false, "bf16")
+/* Enabling/Disabling "flagm" only changes "flagm". */
+AARCH64_OPT_EXTENSION("flagm", AARCH64_FL_FLAGM, 0, 0, false, "flagm")
+
+/* Enabling/Disabling "pauth" only changes "pauth". */
+AARCH64_OPT_EXTENSION("pauth", AARCH64_FL_PAUTH, 0, 0, false, "paca pacg")
+
#undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 7a34c84..c847966 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -192,6 +192,29 @@ struct cpu_regmove_cost
const int FP2FP;
};
+struct simd_vec_cost
+{
+ const int int_stmt_cost; /* Cost of any int vector operation,
+ excluding load, store, permute,
+ vector-to-scalar and
+ scalar-to-vector operation. */
+ const int fp_stmt_cost; /* Cost of any fp vector operation,
+ excluding load, store, permute,
+ vector-to-scalar and
+ scalar-to-vector operation. */
+ const int permute_cost; /* Cost of permute operation. */
+ const int vec_to_scalar_cost; /* Cost of vec-to-scalar operation. */
+ const int scalar_to_vec_cost; /* Cost of scalar-to-vector
+ operation. */
+ const int align_load_cost; /* Cost of aligned vector load. */
+ const int unalign_load_cost; /* Cost of unaligned vector load. */
+ const int unalign_store_cost; /* Cost of unaligned vector store. */
+ const int store_cost; /* Cost of vector store. */
+};
+
+typedef struct simd_vec_cost advsimd_vec_cost;
+typedef struct simd_vec_cost sve_vec_cost;
+
/* Cost for vector insn classes. */
struct cpu_vector_cost
{
@@ -201,24 +224,10 @@ struct cpu_vector_cost
excluding load and store. */
const int scalar_load_cost; /* Cost of scalar load. */
const int scalar_store_cost; /* Cost of scalar store. */
- const int vec_int_stmt_cost; /* Cost of any int vector operation,
- excluding load, store, permute,
- vector-to-scalar and
- scalar-to-vector operation. */
- const int vec_fp_stmt_cost; /* Cost of any fp vector operation,
- excluding load, store, permute,
- vector-to-scalar and
- scalar-to-vector operation. */
- const int vec_permute_cost; /* Cost of permute operation. */
- const int vec_to_scalar_cost; /* Cost of vec-to-scalar operation. */
- const int scalar_to_vec_cost; /* Cost of scalar-to-vector
- operation. */
- const int vec_align_load_cost; /* Cost of aligned vector load. */
- const int vec_unalign_load_cost; /* Cost of unaligned vector load. */
- const int vec_unalign_store_cost; /* Cost of unaligned vector store. */
- const int vec_store_cost; /* Cost of vector store. */
const int cond_taken_branch_cost; /* Cost of taken branch. */
const int cond_not_taken_branch_cost; /* Cost of not taken branch. */
+ const advsimd_vec_cost *advsimd; /* Cost of Advanced SIMD operations. */
+ const sve_vec_cost *sve; /* Cost of SVE operations. */
};
/* Branch costs. */
@@ -510,6 +519,7 @@ bool aarch64_emit_approx_div (rtx, rtx, rtx);
bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
void aarch64_expand_call (rtx, rtx, rtx, bool);
bool aarch64_expand_cpymem (rtx *);
+bool aarch64_expand_setmem (rtx *);
bool aarch64_float_const_zero_rtx_p (rtx);
bool aarch64_float_const_rtx_p (rtx);
bool aarch64_function_arg_regno_p (unsigned);
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 5bc596d..b70056a 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -47,7 +47,7 @@
VAR1 (COMBINEP, combine, 0, ALL, di)
BUILTIN_VB (BINOP, pmul, 0, NONE)
BUILTIN_VHSDF_HSDF (BINOP, fmulx, 0, FP)
- BUILTIN_VHSDF_DF (UNOP, sqrt, 2, ALL)
+ BUILTIN_VHSDF_DF (UNOP, sqrt, 2, FP)
BUILTIN_VD_BHSI (BINOP, addp, 0, NONE)
VAR1 (UNOP, addp, 0, NONE, di)
BUILTIN_VDQ_BHSI (UNOP, clrsb, 2, ALL)
@@ -111,13 +111,13 @@
BUILTIN_VALLDIF (LOADSTRUCT_LANE, ld3_lane, 0, ALL)
BUILTIN_VALLDIF (LOADSTRUCT_LANE, ld4_lane, 0, ALL)
/* Implemented by aarch64_st<VSTRUCT:nregs><VDC:mode>. */
- BUILTIN_VDC (STORESTRUCT, st2, 0, ALL)
- BUILTIN_VDC (STORESTRUCT, st3, 0, ALL)
- BUILTIN_VDC (STORESTRUCT, st4, 0, ALL)
+ BUILTIN_VDC (STORESTRUCT, st2, 0, STORE)
+ BUILTIN_VDC (STORESTRUCT, st3, 0, STORE)
+ BUILTIN_VDC (STORESTRUCT, st4, 0, STORE)
/* Implemented by aarch64_st<VSTRUCT:nregs><VQ:mode>. */
- BUILTIN_VQ (STORESTRUCT, st2, 0, ALL)
- BUILTIN_VQ (STORESTRUCT, st3, 0, ALL)
- BUILTIN_VQ (STORESTRUCT, st4, 0, ALL)
+ BUILTIN_VQ (STORESTRUCT, st2, 0, STORE)
+ BUILTIN_VQ (STORESTRUCT, st3, 0, STORE)
+ BUILTIN_VQ (STORESTRUCT, st4, 0, STORE)
BUILTIN_VALLDIF (STORESTRUCT_LANE, st2_lane, 0, ALL)
BUILTIN_VALLDIF (STORESTRUCT_LANE, st3_lane, 0, ALL)
@@ -229,9 +229,9 @@
BUILTIN_VSDQ_I_DI (BINOP_UUS, urshl, 0, ALL)
/* Implemented by aarch64_<sur><dotprod>{_lane}{q}<dot_mode>. */
- BUILTIN_VB (TERNOP, sdot, 0, ALL)
- BUILTIN_VB (TERNOPU, udot, 0, ALL)
- BUILTIN_VB (TERNOP_SSUS, usdot, 0, ALL)
+ BUILTIN_VB (TERNOP, sdot, 0, NONE)
+ BUILTIN_VB (TERNOPU, udot, 0, NONE)
+ BUILTIN_VB (TERNOP_SSUS, usdot, 0, NONE)
BUILTIN_VB (QUADOP_LANE, sdot_lane, 0, ALL)
BUILTIN_VB (QUADOPU_LANE, udot_lane, 0, ALL)
BUILTIN_VB (QUADOP_LANE, sdot_laneq, 0, ALL)
@@ -285,6 +285,13 @@
BUILTIN_VSQN_HSDI (USHIFTIMM, uqshrn_n, 0, ALL)
BUILTIN_VSQN_HSDI (SHIFTIMM, sqrshrn_n, 0, ALL)
BUILTIN_VSQN_HSDI (USHIFTIMM, uqrshrn_n, 0, ALL)
+ /* Implemented by aarch64_<sur>q<r>shr<u>n2_n<mode>. */
+ BUILTIN_VQN (SHIFT2IMM_UUSS, sqshrun2_n, 0, NONE)
+ BUILTIN_VQN (SHIFT2IMM_UUSS, sqrshrun2_n, 0, NONE)
+ BUILTIN_VQN (SHIFT2IMM, sqshrn2_n, 0, NONE)
+ BUILTIN_VQN (USHIFT2IMM, uqshrn2_n, 0, NONE)
+ BUILTIN_VQN (SHIFT2IMM, sqrshrn2_n, 0, NONE)
+ BUILTIN_VQN (USHIFT2IMM, uqrshrn2_n, 0, NONE)
/* Implemented by aarch64_<sur>s<lr>i_n<mode>. */
BUILTIN_VSDQ_I_DI (SHIFTINSERT, ssri_n, 0, ALL)
BUILTIN_VSDQ_I_DI (USHIFTACC, usri_n, 0, ALL)
@@ -297,7 +304,7 @@
BUILTIN_VSDQ_I (USHIFTIMM, uqshl_n, 0, ALL)
/* Implemented by aarch64_reduc_plus_<mode>. */
- BUILTIN_VALL (UNOP, reduc_plus_scal_, 10, ALL)
+ BUILTIN_VALL (UNOP, reduc_plus_scal_, 10, NONE)
/* Implemented by reduc_<maxmin_uns>_scal_<mode> (producing scalar). */
BUILTIN_VDQIF_F16 (UNOP, reduc_smax_scal_, 10, NONE)
@@ -430,17 +437,17 @@
VAR1 (UNOPUS, lfrintnudf, 2, FP, di)
/* Implemented by <optab><fcvt_target><VDQF:mode>2. */
- VAR1 (UNOP, floatv4hi, 2, ALL, v4hf)
- VAR1 (UNOP, floatv8hi, 2, ALL, v8hf)
- VAR1 (UNOP, floatv2si, 2, ALL, v2sf)
- VAR1 (UNOP, floatv4si, 2, ALL, v4sf)
- VAR1 (UNOP, floatv2di, 2, ALL, v2df)
-
- VAR1 (UNOP, floatunsv4hi, 2, ALL, v4hf)
- VAR1 (UNOP, floatunsv8hi, 2, ALL, v8hf)
- VAR1 (UNOP, floatunsv2si, 2, ALL, v2sf)
- VAR1 (UNOP, floatunsv4si, 2, ALL, v4sf)
- VAR1 (UNOP, floatunsv2di, 2, ALL, v2df)
+ VAR1 (UNOP, floatv4hi, 2, FP, v4hf)
+ VAR1 (UNOP, floatv8hi, 2, FP, v8hf)
+ VAR1 (UNOP, floatv2si, 2, FP, v2sf)
+ VAR1 (UNOP, floatv4si, 2, FP, v4sf)
+ VAR1 (UNOP, floatv2di, 2, FP, v2df)
+
+ VAR1 (UNOP, floatunsv4hi, 2, FP, v4hf)
+ VAR1 (UNOP, floatunsv8hi, 2, FP, v8hf)
+ VAR1 (UNOP, floatunsv2si, 2, FP, v2sf)
+ VAR1 (UNOP, floatunsv4si, 2, FP, v4sf)
+ VAR1 (UNOP, floatunsv2di, 2, FP, v2df)
VAR5 (UNOPU, bswap, 2, ALL, v4hi, v8hi, v2si, v4si, v2di)
@@ -455,35 +462,35 @@
BUILTIN_VALL (BINOP, trn1, 0, ALL)
BUILTIN_VALL (BINOP, trn2, 0, ALL)
- BUILTIN_GPF_F16 (UNOP, frecpe, 0, ALL)
- BUILTIN_GPF_F16 (UNOP, frecpx, 0, ALL)
+ BUILTIN_GPF_F16 (UNOP, frecpe, 0, FP)
+ BUILTIN_GPF_F16 (UNOP, frecpx, 0, FP)
- BUILTIN_VDQ_SI (UNOP, urecpe, 0, ALL)
+ BUILTIN_VDQ_SI (UNOP, urecpe, 0, NONE)
- BUILTIN_VHSDF (UNOP, frecpe, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP, frecps, 0, ALL)
+ BUILTIN_VHSDF (UNOP, frecpe, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP, frecps, 0, FP)
/* Implemented by a mixture of abs2 patterns. Note the DImode builtin is
only ever used for the int64x1_t intrinsic, there is no scalar version. */
- BUILTIN_VSDQ_I_DI (UNOP, abs, 0, ALL)
- BUILTIN_VHSDF (UNOP, abs, 2, ALL)
- VAR1 (UNOP, abs, 2, ALL, hf)
+ BUILTIN_VSDQ_I_DI (UNOP, abs, 0, AUTO_FP)
+ BUILTIN_VHSDF (UNOP, abs, 2, AUTO_FP)
+ VAR1 (UNOP, abs, 2, AUTO_FP, hf)
- BUILTIN_VQ_HSF (UNOP, vec_unpacks_hi_, 10, ALL)
- VAR1 (BINOP, float_truncate_hi_, 0, ALL, v4sf)
- VAR1 (BINOP, float_truncate_hi_, 0, ALL, v8hf)
+ BUILTIN_VQ_HSF (UNOP, vec_unpacks_hi_, 10, FP)
+ VAR1 (BINOP, float_truncate_hi_, 0, FP, v4sf)
+ VAR1 (BINOP, float_truncate_hi_, 0, FP, v8hf)
- VAR1 (UNOP, float_extend_lo_, 0, ALL, v2df)
- VAR1 (UNOP, float_extend_lo_, 0, ALL, v4sf)
- BUILTIN_VDF (UNOP, float_truncate_lo_, 0, ALL)
+ VAR1 (UNOP, float_extend_lo_, 0, FP, v2df)
+ VAR1 (UNOP, float_extend_lo_, 0, FP, v4sf)
+ BUILTIN_VDF (UNOP, float_truncate_lo_, 0, FP)
/* Implemented by aarch64_ld1<VALL_F16:mode>. */
BUILTIN_VALL_F16 (LOAD1, ld1, 0, ALL)
VAR1(STORE1P, ld1, 0, ALL, v2di)
/* Implemented by aarch64_st1<VALL_F16:mode>. */
- BUILTIN_VALL_F16 (STORE1, st1, 0, ALL)
- VAR1(STORE1P, st1, 0, ALL, v2di)
+ BUILTIN_VALL_F16 (STORE1, st1, 0, STORE)
+ VAR1 (STORE1P, st1, 0, STORE, v2di)
/* Implemented by aarch64_ld1x3<VALLDIF:mode>. */
BUILTIN_VALLDIF (LOADSTRUCT, ld1x3, 0, ALL)
@@ -492,20 +499,20 @@
BUILTIN_VALLDIF (LOADSTRUCT, ld1x4, 0, ALL)
/* Implemented by aarch64_st1x2<VALLDIF:mode>. */
- BUILTIN_VALLDIF (STORESTRUCT, st1x2, 0, ALL)
+ BUILTIN_VALLDIF (STORESTRUCT, st1x2, 0, STORE)
/* Implemented by aarch64_st1x3<VALLDIF:mode>. */
- BUILTIN_VALLDIF (STORESTRUCT, st1x3, 0, ALL)
+ BUILTIN_VALLDIF (STORESTRUCT, st1x3, 0, STORE)
/* Implemented by aarch64_st1x4<VALLDIF:mode>. */
- BUILTIN_VALLDIF (STORESTRUCT, st1x4, 0, ALL)
+ BUILTIN_VALLDIF (STORESTRUCT, st1x4, 0, STORE)
/* Implemented by fma<mode>4. */
- BUILTIN_VHSDF (TERNOP, fma, 4, ALL)
- VAR1 (TERNOP, fma, 4, ALL, hf)
+ BUILTIN_VHSDF (TERNOP, fma, 4, FP)
+ VAR1 (TERNOP, fma, 4, FP, hf)
/* Implemented by fnma<mode>4. */
- BUILTIN_VHSDF (TERNOP, fnma, 4, ALL)
- VAR1 (TERNOP, fnma, 4, ALL, hf)
+ BUILTIN_VHSDF (TERNOP, fnma, 4, FP)
+ VAR1 (TERNOP, fnma, 4, FP, hf)
/* Implemented by aarch64_simd_bsl<mode>. */
BUILTIN_VDQQH (BSL_P, simd_bsl, 0, ALL)
@@ -514,52 +521,52 @@
BUILTIN_VALLDIF (BSL_S, simd_bsl, 0, ALL)
/* Implemented by aarch64_crypto_aes<op><mode>. */
- VAR1 (BINOPU, crypto_aese, 0, ALL, v16qi)
- VAR1 (BINOPU, crypto_aesd, 0, ALL, v16qi)
- VAR1 (UNOPU, crypto_aesmc, 0, ALL, v16qi)
- VAR1 (UNOPU, crypto_aesimc, 0, ALL, v16qi)
+ VAR1 (BINOPU, crypto_aese, 0, NONE, v16qi)
+ VAR1 (BINOPU, crypto_aesd, 0, NONE, v16qi)
+ VAR1 (UNOPU, crypto_aesmc, 0, NONE, v16qi)
+ VAR1 (UNOPU, crypto_aesimc, 0, NONE, v16qi)
/* Implemented by aarch64_crypto_sha1<op><mode>. */
- VAR1 (UNOPU, crypto_sha1h, 0, ALL, si)
- VAR1 (BINOPU, crypto_sha1su1, 0, ALL, v4si)
- VAR1 (TERNOPU, crypto_sha1c, 0, ALL, v4si)
- VAR1 (TERNOPU, crypto_sha1m, 0, ALL, v4si)
- VAR1 (TERNOPU, crypto_sha1p, 0, ALL, v4si)
- VAR1 (TERNOPU, crypto_sha1su0, 0, ALL, v4si)
+ VAR1 (UNOPU, crypto_sha1h, 0, NONE, si)
+ VAR1 (BINOPU, crypto_sha1su1, 0, NONE, v4si)
+ VAR1 (TERNOPU, crypto_sha1c, 0, NONE, v4si)
+ VAR1 (TERNOPU, crypto_sha1m, 0, NONE, v4si)
+ VAR1 (TERNOPU, crypto_sha1p, 0, NONE, v4si)
+ VAR1 (TERNOPU, crypto_sha1su0, 0, NONE, v4si)
/* Implemented by aarch64_crypto_sha256<op><mode>. */
- VAR1 (TERNOPU, crypto_sha256h, 0, ALL, v4si)
- VAR1 (TERNOPU, crypto_sha256h2, 0, ALL, v4si)
- VAR1 (BINOPU, crypto_sha256su0, 0, ALL, v4si)
- VAR1 (TERNOPU, crypto_sha256su1, 0, ALL, v4si)
+ VAR1 (TERNOPU, crypto_sha256h, 0, NONE, v4si)
+ VAR1 (TERNOPU, crypto_sha256h2, 0, NONE, v4si)
+ VAR1 (BINOPU, crypto_sha256su0, 0, NONE, v4si)
+ VAR1 (TERNOPU, crypto_sha256su1, 0, NONE, v4si)
/* Implemented by aarch64_crypto_pmull<mode>. */
VAR1 (BINOPP, crypto_pmull, 0, NONE, di)
VAR1 (BINOPP, crypto_pmull, 0, NONE, v2di)
/* Implemented by aarch64_tbl3<mode>. */
- VAR1 (BINOP, tbl3, 0, ALL, v8qi)
- VAR1 (BINOP, tbl3, 0, ALL, v16qi)
+ VAR1 (BINOP, tbl3, 0, NONE, v8qi)
+ VAR1 (BINOP, tbl3, 0, NONE, v16qi)
/* Implemented by aarch64_qtbl3<mode>. */
- VAR1 (BINOP, qtbl3, 0, ALL, v8qi)
- VAR1 (BINOP, qtbl3, 0, ALL, v16qi)
+ VAR1 (BINOP, qtbl3, 0, NONE, v8qi)
+ VAR1 (BINOP, qtbl3, 0, NONE, v16qi)
/* Implemented by aarch64_qtbl4<mode>. */
- VAR1 (BINOP, qtbl4, 0, ALL, v8qi)
- VAR1 (BINOP, qtbl4, 0, ALL, v16qi)
+ VAR1 (BINOP, qtbl4, 0, NONE, v8qi)
+ VAR1 (BINOP, qtbl4, 0, NONE, v16qi)
/* Implemented by aarch64_tbx4<mode>. */
- VAR1 (TERNOP, tbx4, 0, ALL, v8qi)
- VAR1 (TERNOP, tbx4, 0, ALL, v16qi)
+ VAR1 (TERNOP, tbx4, 0, NONE, v8qi)
+ VAR1 (TERNOP, tbx4, 0, NONE, v16qi)
/* Implemented by aarch64_qtbx3<mode>. */
- VAR1 (TERNOP, qtbx3, 0, ALL, v8qi)
- VAR1 (TERNOP, qtbx3, 0, ALL, v16qi)
+ VAR1 (TERNOP, qtbx3, 0, NONE, v8qi)
+ VAR1 (TERNOP, qtbx3, 0, NONE, v16qi)
/* Implemented by aarch64_qtbx4<mode>. */
- VAR1 (TERNOP, qtbx4, 0, ALL, v8qi)
- VAR1 (TERNOP, qtbx4, 0, ALL, v16qi)
+ VAR1 (TERNOP, qtbx4, 0, NONE, v8qi)
+ VAR1 (TERNOP, qtbx4, 0, NONE, v16qi)
/* Builtins for ARMv8.1-A Adv.SIMD instructions. */
@@ -588,72 +595,72 @@
BUILTIN_GPI (SHIFTIMM_USS, fcvtzuhf, 3, ALL)
/* Implemented by aarch64_rsqrte<mode>. */
- BUILTIN_VHSDF_HSDF (UNOP, rsqrte, 0, ALL)
+ BUILTIN_VHSDF_HSDF (UNOP, rsqrte, 0, FP)
/* Implemented by aarch64_rsqrts<mode>. */
- BUILTIN_VHSDF_HSDF (BINOP, rsqrts, 0, ALL)
+ BUILTIN_VHSDF_HSDF (BINOP, rsqrts, 0, FP)
/* Implemented by fabd<mode>3. */
- BUILTIN_VHSDF_HSDF (BINOP, fabd, 3, ALL)
+ BUILTIN_VHSDF_HSDF (BINOP, fabd, 3, FP)
/* Implemented by aarch64_faddp<mode>. */
BUILTIN_VHSDF (BINOP, faddp, 0, FP)
/* Implemented by aarch64_cm<optab><mode>. */
- BUILTIN_VHSDF_HSDF (BINOP_USS, cmeq, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, cmge, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, cmgt, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, cmle, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, cmlt, 0, ALL)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, cmeq, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, cmge, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, cmgt, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, cmle, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, cmlt, 0, FP)
/* Implemented by neg<mode>2. */
BUILTIN_VHSDF_HSDF (UNOP, neg, 2, ALL)
/* Implemented by aarch64_fac<optab><mode>. */
- BUILTIN_VHSDF_HSDF (BINOP_USS, faclt, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, facle, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, facgt, 0, ALL)
- BUILTIN_VHSDF_HSDF (BINOP_USS, facge, 0, ALL)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, faclt, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, facle, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, facgt, 0, FP)
+ BUILTIN_VHSDF_HSDF (BINOP_USS, facge, 0, FP)
/* Implemented by sqrt<mode>2. */
- VAR1 (UNOP, sqrt, 2, ALL, hf)
+ VAR1 (UNOP, sqrt, 2, FP, hf)
/* Implemented by <optab><mode>hf2. */
- VAR1 (UNOP, floatdi, 2, ALL, hf)
- VAR1 (UNOP, floatsi, 2, ALL, hf)
- VAR1 (UNOP, floathi, 2, ALL, hf)
- VAR1 (UNOPUS, floatunsdi, 2, ALL, hf)
- VAR1 (UNOPUS, floatunssi, 2, ALL, hf)
- VAR1 (UNOPUS, floatunshi, 2, ALL, hf)
- BUILTIN_GPI_I16 (UNOP, fix_trunchf, 2, ALL)
- BUILTIN_GPI (UNOP, fix_truncsf, 2, ALL)
- BUILTIN_GPI (UNOP, fix_truncdf, 2, ALL)
- BUILTIN_GPI_I16 (UNOPUS, fixuns_trunchf, 2, ALL)
- BUILTIN_GPI (UNOPUS, fixuns_truncsf, 2, ALL)
- BUILTIN_GPI (UNOPUS, fixuns_truncdf, 2, ALL)
+ VAR1 (UNOP, floatdi, 2, FP, hf)
+ VAR1 (UNOP, floatsi, 2, FP, hf)
+ VAR1 (UNOP, floathi, 2, FP, hf)
+ VAR1 (UNOPUS, floatunsdi, 2, FP, hf)
+ VAR1 (UNOPUS, floatunssi, 2, FP, hf)
+ VAR1 (UNOPUS, floatunshi, 2, FP, hf)
+ BUILTIN_GPI_I16 (UNOP, fix_trunchf, 2, FP)
+ BUILTIN_GPI (UNOP, fix_truncsf, 2, FP)
+ BUILTIN_GPI (UNOP, fix_truncdf, 2, FP)
+ BUILTIN_GPI_I16 (UNOPUS, fixuns_trunchf, 2, FP)
+ BUILTIN_GPI (UNOPUS, fixuns_truncsf, 2, FP)
+ BUILTIN_GPI (UNOPUS, fixuns_truncdf, 2, FP)
/* Implemented by aarch64_sm3ss1qv4si. */
- VAR1 (TERNOPU, sm3ss1q, 0, ALL, v4si)
+ VAR1 (TERNOPU, sm3ss1q, 0, NONE, v4si)
/* Implemented by aarch64_sm3tt<sm3tt_op>qv4si. */
- VAR1 (QUADOPUI, sm3tt1aq, 0, ALL, v4si)
- VAR1 (QUADOPUI, sm3tt1bq, 0, ALL, v4si)
- VAR1 (QUADOPUI, sm3tt2aq, 0, ALL, v4si)
- VAR1 (QUADOPUI, sm3tt2bq, 0, ALL, v4si)
+ VAR1 (QUADOPUI, sm3tt1aq, 0, NONE, v4si)
+ VAR1 (QUADOPUI, sm3tt1bq, 0, NONE, v4si)
+ VAR1 (QUADOPUI, sm3tt2aq, 0, NONE, v4si)
+ VAR1 (QUADOPUI, sm3tt2bq, 0, NONE, v4si)
/* Implemented by aarch64_sm3partw<sm3part_op>qv4si. */
- VAR1 (TERNOPU, sm3partw1q, 0, ALL, v4si)
- VAR1 (TERNOPU, sm3partw2q, 0, ALL, v4si)
+ VAR1 (TERNOPU, sm3partw1q, 0, NONE, v4si)
+ VAR1 (TERNOPU, sm3partw2q, 0, NONE, v4si)
/* Implemented by aarch64_sm4eqv4si. */
- VAR1 (BINOPU, sm4eq, 0, ALL, v4si)
+ VAR1 (BINOPU, sm4eq, 0, NONE, v4si)
/* Implemented by aarch64_sm4ekeyqv4si. */
- VAR1 (BINOPU, sm4ekeyq, 0, ALL, v4si)
+ VAR1 (BINOPU, sm4ekeyq, 0, NONE, v4si)
/* Implemented by aarch64_crypto_sha512hqv2di. */
- VAR1 (TERNOPU, crypto_sha512hq, 0, ALL, v2di)
+ VAR1 (TERNOPU, crypto_sha512hq, 0, NONE, v2di)
/* Implemented by aarch64_sha512h2qv2di. */
- VAR1 (TERNOPU, crypto_sha512h2q, 0, ALL, v2di)
+ VAR1 (TERNOPU, crypto_sha512h2q, 0, NONE, v2di)
/* Implemented by aarch64_crypto_sha512su0qv2di. */
- VAR1 (BINOPU, crypto_sha512su0q, 0, ALL, v2di)
+ VAR1 (BINOPU, crypto_sha512su0q, 0, NONE, v2di)
/* Implemented by aarch64_crypto_sha512su1qv2di. */
- VAR1 (TERNOPU, crypto_sha512su1q, 0, ALL, v2di)
+ VAR1 (TERNOPU, crypto_sha512su1q, 0, NONE, v2di)
/* Implemented by eor3q<mode>4. */
BUILTIN_VQ_I (TERNOPU, eor3q, 4, ALL)
BUILTIN_VQ_I (TERNOP, eor3q, 4, ALL)
@@ -701,13 +708,13 @@
VAR1 (QUADOP_LANE, fmlslq_laneq_high, 0, ALL, v4sf)
/* Implemented by aarch64_<frintnzs_op><mode>. */
- BUILTIN_VSFDF (UNOP, frint32z, 0, ALL)
- BUILTIN_VSFDF (UNOP, frint32x, 0, ALL)
- BUILTIN_VSFDF (UNOP, frint64z, 0, ALL)
- BUILTIN_VSFDF (UNOP, frint64x, 0, ALL)
+ BUILTIN_VSFDF (UNOP, frint32z, 0, FP)
+ BUILTIN_VSFDF (UNOP, frint32x, 0, FP)
+ BUILTIN_VSFDF (UNOP, frint64z, 0, FP)
+ BUILTIN_VSFDF (UNOP, frint64x, 0, FP)
/* Implemented by aarch64_bfdot{_lane}{q}<mode>. */
- VAR2 (TERNOP, bfdot, 0, ALL, v2sf, v4sf)
+ VAR2 (TERNOP, bfdot, 0, AUTO_FP, v2sf, v4sf)
VAR2 (QUADOP_LANE_PAIR, bfdot_lane, 0, ALL, v2sf, v4sf)
VAR2 (QUADOP_LANE_PAIR, bfdot_laneq, 0, ALL, v2sf, v4sf)
@@ -722,13 +729,22 @@
VAR1 (QUADOP_LANE, bfmlalb_lane_q, 0, ALL, v4sf)
VAR1 (QUADOP_LANE, bfmlalt_lane_q, 0, ALL, v4sf)
+ /* Implemented by aarch64_vget_lo/hi_halfv8bf. */
+ VAR1 (UNOP, vget_lo_half, 0, AUTO_FP, v8bf)
+ VAR1 (UNOP, vget_hi_half, 0, AUTO_FP, v8bf)
+
/* Implemented by aarch64_simd_<sur>mmlav16qi. */
VAR1 (TERNOP, simd_smmla, 0, NONE, v16qi)
VAR1 (TERNOPU, simd_ummla, 0, NONE, v16qi)
VAR1 (TERNOP_SSUS, simd_usmmla, 0, NONE, v16qi)
/* Implemented by aarch64_bfcvtn{q}{2}<mode> */
- VAR1 (UNOP, bfcvtn, 0, ALL, v4bf)
- VAR1 (UNOP, bfcvtn_q, 0, ALL, v8bf)
- VAR1 (BINOP, bfcvtn2, 0, ALL, v8bf)
- VAR1 (UNOP, bfcvt, 0, ALL, bf)
+ VAR1 (UNOP, bfcvtn, 0, FP, v4bf)
+ VAR1 (UNOP, bfcvtn_q, 0, FP, v8bf)
+ VAR1 (BINOP, bfcvtn2, 0, FP, v8bf)
+ VAR1 (UNOP, bfcvt, 0, FP, bf)
+
+ /* Implemented by aarch64_{v}bfcvt{_high}<mode>. */
+ VAR2 (UNOP, vbfcvt, 0, AUTO_FP, v4bf, v8bf)
+ VAR1 (UNOP, vbfcvt_high, 0, AUTO_FP, v8bf)
+ VAR1 (UNOP, bfcvt, 0, AUTO_FP, sf)
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 381a702..05d18f8 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -449,6 +449,14 @@
[(set_attr "type" "neon_fcadd")]
)
+(define_expand "cadd<rot><mode>3"
+ [(set (match_operand:VHSDF 0 "register_operand")
+ (unspec:VHSDF [(match_operand:VHSDF 1 "register_operand")
+ (match_operand:VHSDF 2 "register_operand")]
+ FCADD))]
+ "TARGET_COMPLEX && !BYTES_BIG_ENDIAN"
+)
+
(define_insn "aarch64_fcmla<rot><mode>"
[(set (match_operand:VHSDF 0 "register_operand" "=w")
(plus:VHSDF (match_operand:VHSDF 1 "register_operand" "0")
@@ -3382,6 +3390,53 @@
[(set_attr "type" "neon_<ADDSUB:optab>_long")]
)
+(define_expand "vec_widen_<su>addl_lo_<mode>"
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand"))]
+ "TARGET_SIMD"
+{
+ rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
+ emit_insn (gen_aarch64_<su>addl<mode>_lo_internal (operands[0], operands[1],
+ operands[2], p));
+ DONE;
+})
+
+(define_expand "vec_widen_<su>addl_hi_<mode>"
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand"))]
+ "TARGET_SIMD"
+{
+ rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
+ emit_insn (gen_aarch64_<su>addl<mode>_hi_internal (operands[0], operands[1],
+ operands[2], p));
+ DONE;
+})
+
+(define_expand "vec_widen_<su>subl_lo_<mode>"
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand"))]
+ "TARGET_SIMD"
+{
+ rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
+ emit_insn (gen_aarch64_<su>subl<mode>_lo_internal (operands[0], operands[1],
+ operands[2], p));
+ DONE;
+})
+
+(define_expand "vec_widen_<su>subl_hi_<mode>"
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand"))]
+ "TARGET_SIMD"
+{
+ rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
+ emit_insn (gen_aarch64_<su>subl<mode>_hi_internal (operands[0], operands[1],
+ operands[2], p));
+ DONE;
+})
(define_expand "aarch64_saddl2<mode>"
[(match_operand:<VWIDE> 0 "register_operand")
@@ -4617,8 +4672,74 @@
[(set_attr "type" "neon_sat_shift_reg<q>")]
)
+(define_expand "vec_widen_<sur>shiftl_lo_<mode>"
+ [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
+ (unspec:<VWIDE> [(match_operand:VQW 1 "register_operand" "w")
+ (match_operand:SI 2
+ "aarch64_simd_shift_imm_bitsize_<ve_mode>" "i")]
+ VSHLL))]
+ "TARGET_SIMD"
+ {
+ rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
+ emit_insn (gen_aarch64_<sur>shll<mode>_internal (operands[0], operands[1],
+ p, operands[2]));
+ DONE;
+ }
+)
+
+(define_expand "vec_widen_<sur>shiftl_hi_<mode>"
+ [(set (match_operand:<VWIDE> 0 "register_operand")
+ (unspec:<VWIDE> [(match_operand:VQW 1 "register_operand" "w")
+ (match_operand:SI 2
+ "immediate_operand" "i")]
+ VSHLL))]
+ "TARGET_SIMD"
+ {
+ rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
+ emit_insn (gen_aarch64_<sur>shll2<mode>_internal (operands[0], operands[1],
+ p, operands[2]));
+ DONE;
+ }
+)
+
;; vshll_n
+(define_insn "aarch64_<sur>shll<mode>_internal"
+ [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
+ (unspec:<VWIDE> [(vec_select:<VHALF>
+ (match_operand:VQW 1 "register_operand" "w")
+ (match_operand:VQW 2 "vect_par_cnst_lo_half" ""))
+ (match_operand:SI 3
+ "aarch64_simd_shift_imm_bitsize_<ve_mode>" "i")]
+ VSHLL))]
+ "TARGET_SIMD"
+ {
+ if (INTVAL (operands[3]) == GET_MODE_UNIT_BITSIZE (<MODE>mode))
+ return "shll\\t%0.<Vwtype>, %1.<Vhalftype>, %3";
+ else
+ return "<sur>shll\\t%0.<Vwtype>, %1.<Vhalftype>, %3";
+ }
+ [(set_attr "type" "neon_shift_imm_long")]
+)
+
+(define_insn "aarch64_<sur>shll2<mode>_internal"
+ [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
+ (unspec:<VWIDE> [(vec_select:<VHALF>
+ (match_operand:VQW 1 "register_operand" "w")
+ (match_operand:VQW 2 "vect_par_cnst_hi_half" ""))
+ (match_operand:SI 3
+ "aarch64_simd_shift_imm_bitsize_<ve_mode>" "i")]
+ VSHLL))]
+ "TARGET_SIMD"
+ {
+ if (INTVAL (operands[3]) == GET_MODE_UNIT_BITSIZE (<MODE>mode))
+ return "shll2\\t%0.<Vwtype>, %1.<Vtype>, %3";
+ else
+ return "<sur>shll2\\t%0.<Vwtype>, %1.<Vtype>, %3";
+ }
+ [(set_attr "type" "neon_shift_imm_long")]
+)
+
(define_insn "aarch64_<sur>shll_n<mode>"
[(set (match_operand:<VWIDE> 0 "register_operand" "=w")
(unspec:<VWIDE> [(match_operand:VD_BHSI 1 "register_operand" "w")
@@ -4720,6 +4841,17 @@
[(set_attr "type" "neon_sat_shift_imm_narrow_q")]
)
+(define_insn "aarch64_<sur>q<r>shr<u>n2_n<mode>"
+ [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w")
+ (unspec:<VNARROWQ2> [(match_operand:<VNARROWQ> 1 "register_operand" "0")
+ (match_operand:VQN 2 "register_operand" "w")
+ (match_operand:SI 3 "aarch64_simd_shift_imm_offset_<ve_mode>" "i")]
+ VQSHRN_N))]
+ "TARGET_SIMD"
+ "<sur>q<r>shr<u>n2\\t%<vn2>0.<V2ntype>, %<v>2.<Vtype>, %3"
+ [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
+)
+
;; cm(eq|ge|gt|lt|le)
;; Note, we have constraints for Dz and Z as different expanders
@@ -7159,6 +7291,27 @@
[(set_attr "type" "neon_dot<VDQSF:q>")]
)
+;; vget_low/high_bf16
+(define_expand "aarch64_vget_lo_halfv8bf"
+ [(match_operand:V4BF 0 "register_operand")
+ (match_operand:V8BF 1 "register_operand")]
+ "TARGET_BF16_SIMD"
+{
+ rtx p = aarch64_simd_vect_par_cnst_half (V8BFmode, 8, false);
+ emit_insn (gen_aarch64_get_halfv8bf (operands[0], operands[1], p));
+ DONE;
+})
+
+(define_expand "aarch64_vget_hi_halfv8bf"
+ [(match_operand:V4BF 0 "register_operand")
+ (match_operand:V8BF 1 "register_operand")]
+ "TARGET_BF16_SIMD"
+{
+ rtx p = aarch64_simd_vect_par_cnst_half (V8BFmode, 8, true);
+ emit_insn (gen_aarch64_get_halfv8bf (operands[0], operands[1], p));
+ DONE;
+})
+
;; bfmmla
(define_insn "aarch64_bfmmlaqv4sf"
[(set (match_operand:V4SF 0 "register_operand" "=w")
@@ -7238,3 +7391,31 @@
"bfcvt\\t%h0, %s1"
[(set_attr "type" "f_cvt")]
)
+
+;; Use shl/shll/shll2 to convert BF scalar/vector modes to SF modes.
+(define_insn "aarch64_vbfcvt<mode>"
+ [(set (match_operand:V4SF 0 "register_operand" "=w")
+ (unspec:V4SF [(match_operand:VBF 1 "register_operand" "w")]
+ UNSPEC_BFCVTN))]
+ "TARGET_BF16_SIMD"
+ "shll\\t%0.4s, %1.4h, #16"
+ [(set_attr "type" "neon_shift_imm_long")]
+)
+
+(define_insn "aarch64_vbfcvt_highv8bf"
+ [(set (match_operand:V4SF 0 "register_operand" "=w")
+ (unspec:V4SF [(match_operand:V8BF 1 "register_operand" "w")]
+ UNSPEC_BFCVTN2))]
+ "TARGET_BF16_SIMD"
+ "shll2\\t%0.4s, %1.8h, #16"
+ [(set_attr "type" "neon_shift_imm_long")]
+)
+
+(define_insn "aarch64_bfcvtsf"
+ [(set (match_operand:SF 0 "register_operand" "=w")
+ (unspec:SF [(match_operand:BF 1 "register_operand" "w")]
+ UNSPEC_BFCVT))]
+ "TARGET_BF16_FP"
+ "shl\\t%d0, %d1, #16"
+ [(set_attr "type" "neon_shift_imm")]
+)
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index 9b63ea7..4223125 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -2295,17 +2295,6 @@ public:
CONSTEXPR svundef_impl (unsigned int vectors_per_tuple)
: quiet<multi_vector_function> (vectors_per_tuple) {}
- gimple *
- fold (gimple_folder &f) const OVERRIDE
- {
- /* Don't fold svundef at the gimple level. There's no exact
- correspondence for SSA_NAMEs, and we explicitly don't want
- to generate a specific value (like an all-zeros vector). */
- if (vectors_per_tuple () == 1)
- return NULL;
- return gimple_build_assign (f.lhs, build_clobber (TREE_TYPE (f.lhs)));
- }
-
rtx
expand (function_expander &e) const OVERRIDE
{
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index 31a8c5a..6a5194f 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -2925,14 +2925,17 @@
;; Integer unary arithmetic predicated with a PTRUE.
(define_insn "@aarch64_pred_<optab><mode>"
- [(set (match_operand:SVE_I 0 "register_operand" "=w")
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(SVE_INT_UNARY:SVE_I
- (match_operand:SVE_I 2 "register_operand" "w"))]
+ (match_operand:SVE_I 2 "register_operand" "0, w"))]
UNSPEC_PRED_X))]
"TARGET_SVE"
- "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated integer unary arithmetic with merging.
@@ -2998,15 +3001,37 @@
;; Predicated integer unary operations.
(define_insn "@aarch64_pred_<optab><mode>"
- [(set (match_operand:SVE_FULL_I 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(unspec:SVE_FULL_I
- [(match_operand:SVE_FULL_I 2 "register_operand" "w")]
+ [(match_operand:SVE_FULL_I 2 "register_operand" "0, w")]
SVE_INT_UNARY)]
UNSPEC_PRED_X))]
"TARGET_SVE && <elem_bits> >= <min_elem_bits>"
- "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Another way of expressing the REVB, REVH and REVW patterns, with this
+;; form being easier for permutes. The predicate mode determines the number
+;; of lanes and the data mode decides the granularity of the reversal within
+;; each lane.
+(define_insn "@aarch64_sve_revbhw_<SVE_ALL:mode><PRED_HSD:mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_ALL
+ [(match_operand:PRED_HSD 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_ALL
+ [(match_operand:SVE_ALL 2 "register_operand" "0, w")]
+ UNSPEC_REVBHW)]
+ UNSPEC_PRED_X))]
+ "TARGET_SVE && <PRED_HSD:elem_bits> > <SVE_ALL:container_bits>"
+ "@
+ rev<SVE_ALL:Vcwtype>\t%0.<PRED_HSD:Vetype>, %1/m, %2.<PRED_HSD:Vetype>
+ movprfx\t%0, %2\;rev<SVE_ALL:Vcwtype>\t%0.<PRED_HSD:Vetype>, %1/m, %2.<PRED_HSD:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated integer unary operations with merging.
@@ -3055,28 +3080,34 @@
;; Predicated sign and zero extension from a narrower mode.
(define_insn "*<optab><SVE_PARTIAL_I:mode><SVE_HSDI:mode>2"
- [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
+ [(set (match_operand:SVE_HSDI 0 "register_operand" "=w, ?&w")
(unspec:SVE_HSDI
- [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl, Upl")
(ANY_EXTEND:SVE_HSDI
- (match_operand:SVE_PARTIAL_I 2 "register_operand" "w"))]
+ (match_operand:SVE_PARTIAL_I 2 "register_operand" "0, w"))]
UNSPEC_PRED_X))]
"TARGET_SVE && (~<SVE_HSDI:narrower_mask> & <SVE_PARTIAL_I:self_mask>) == 0"
- "<su>xt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
+ "@
+ <su>xt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+ movprfx\t%0, %2\;<su>xt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated truncate-and-sign-extend operations.
(define_insn "@aarch64_pred_sxt<SVE_FULL_HSDI:mode><SVE_PARTIAL_I:mode>"
- [(set (match_operand:SVE_FULL_HSDI 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_HSDI 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_HSDI
- [(match_operand:<SVE_FULL_HSDI:VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<SVE_FULL_HSDI:VPRED> 1 "register_operand" "Upl, Upl")
(sign_extend:SVE_FULL_HSDI
(truncate:SVE_PARTIAL_I
- (match_operand:SVE_FULL_HSDI 2 "register_operand" "w")))]
+ (match_operand:SVE_FULL_HSDI 2 "register_operand" "0, w")))]
UNSPEC_PRED_X))]
"TARGET_SVE
&& (~<SVE_FULL_HSDI:narrower_mask> & <SVE_PARTIAL_I:self_mask>) == 0"
- "sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>"
+ "@
+ sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
+ movprfx\t%0, %2\;sxt<SVE_PARTIAL_I:Vesize>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated truncate-and-sign-extend operations with merging.
@@ -3196,20 +3227,23 @@
)
(define_insn "*cnot<mode>"
- [(set (match_operand:SVE_FULL_I 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_I
[(unspec:<VPRED>
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 5 "aarch64_sve_ptrue_flag")
(eq:<VPRED>
- (match_operand:SVE_FULL_I 2 "register_operand" "w")
+ (match_operand:SVE_FULL_I 2 "register_operand" "0, w")
(match_operand:SVE_FULL_I 3 "aarch64_simd_imm_zero"))]
UNSPEC_PRED_Z)
(match_operand:SVE_FULL_I 4 "aarch64_simd_imm_one")
(match_dup 3)]
UNSPEC_SEL))]
"TARGET_SVE"
- "cnot\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ "@
+ cnot\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %2\;cnot\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated logical inverse with merging.
@@ -3367,14 +3401,17 @@
;; Predicated floating-point unary operations.
(define_insn "@aarch64_pred_<optab><mode>"
- [(set (match_operand:SVE_FULL_F 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_F 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:SVE_FULL_F 2 "register_operand" "w")]
+ (match_operand:SVE_FULL_F 2 "register_operand" "0, w")]
SVE_COND_FP_UNARY))]
"TARGET_SVE"
- "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated floating-point unary arithmetic with merging.
@@ -5443,6 +5480,20 @@
"TARGET_SVE"
)
+;; Predicated FCADD using ptrue for unpredicated optab for auto-vectorizer
+(define_expand "@cadd<rot><mode>3"
+ [(set (match_operand:SVE_FULL_F 0 "register_operand")
+ (unspec:SVE_FULL_F
+ [(match_dup 3)
+ (const_int SVE_RELAXED_GP)
+ (match_operand:SVE_FULL_F 1 "register_operand")
+ (match_operand:SVE_FULL_F 2 "register_operand")]
+ SVE_COND_FCADD))]
+ "TARGET_SVE"
+{
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
+})
+
;; Predicated FCADD, merging with the first input.
(define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
[(set (match_operand:SVE_FULL_F 0 "register_operand" "=w, ?&w")
@@ -7363,11 +7414,11 @@
;; UNSPEC_SEL operand order: mask, true, false (as for VEC_COND_EXPR)
;; SEL operand order: mask, true, false
(define_expand "@vcond_mask_<mode><vpred>"
- [(set (match_operand:SVE_FULL 0 "register_operand")
- (unspec:SVE_FULL
+ [(set (match_operand:SVE_ALL 0 "register_operand")
+ (unspec:SVE_ALL
[(match_operand:<VPRED> 3 "register_operand")
- (match_operand:SVE_FULL 1 "aarch64_sve_reg_or_dup_imm")
- (match_operand:SVE_FULL 2 "aarch64_simd_reg_or_zero")]
+ (match_operand:SVE_ALL 1 "aarch64_sve_reg_or_dup_imm")
+ (match_operand:SVE_ALL 2 "aarch64_simd_reg_or_zero")]
UNSPEC_SEL))]
"TARGET_SVE"
{
@@ -7380,12 +7431,25 @@
;; - two registers
;; - a duplicated immediate and a register
;; - a duplicated immediate and zero
+;;
+;; For unpacked vectors, it doesn't really matter whether SEL uses the
+;; the container size or the element size. If SEL used the container size,
+;; it would ignore undefined bits of the predicate but would copy the
+;; upper (undefined) bits of each container along with the defined bits.
+;; If SEL used the element size, it would use undefined bits of the predicate
+;; to select between undefined elements in each input vector. Thus the only
+;; difference is whether the undefined bits in a container always come from
+;; the same input as the defined bits, or whether the choice can vary
+;; independently of the defined bits.
+;;
+;; For the other instructions, using the element size is more natural,
+;; so we do that for SEL as well.
(define_insn "*vcond_mask_<mode><vpred>"
- [(set (match_operand:SVE_FULL 0 "register_operand" "=w, w, w, w, ?w, ?&w, ?&w")
- (unspec:SVE_FULL
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w, w, w, ?w, ?&w, ?&w")
+ (unspec:SVE_ALL
[(match_operand:<VPRED> 3 "register_operand" "Upa, Upa, Upa, Upa, Upl, Upl, Upl")
- (match_operand:SVE_FULL 1 "aarch64_sve_reg_or_dup_imm" "w, vss, vss, Ufc, Ufc, vss, Ufc")
- (match_operand:SVE_FULL 2 "aarch64_simd_reg_or_zero" "w, 0, Dz, 0, Dz, w, w")]
+ (match_operand:SVE_ALL 1 "aarch64_sve_reg_or_dup_imm" "w, vss, vss, Ufc, Ufc, vss, Ufc")
+ (match_operand:SVE_ALL 2 "aarch64_simd_reg_or_zero" "w, 0, Dz, 0, Dz, w, w")]
UNSPEC_SEL))]
"TARGET_SVE
&& (!register_operand (operands[1], <MODE>mode)
@@ -7406,12 +7470,12 @@
;; of GPRs as being more expensive than duplicates of FPRs, since they
;; involve a cross-file move.
(define_insn "@aarch64_sel_dup<mode>"
- [(set (match_operand:SVE_FULL 0 "register_operand" "=?w, w, ??w, ?&w, ??&w, ?&w")
- (unspec:SVE_FULL
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=?w, w, ??w, ?&w, ??&w, ?&w")
+ (unspec:SVE_ALL
[(match_operand:<VPRED> 3 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
- (vec_duplicate:SVE_FULL
+ (vec_duplicate:SVE_ALL
(match_operand:<VEL> 1 "register_operand" "r, w, r, w, r, w"))
- (match_operand:SVE_FULL 2 "aarch64_simd_reg_or_zero" "0, 0, Dz, Dz, w, w")]
+ (match_operand:SVE_ALL 2 "aarch64_simd_reg_or_zero" "0, 0, Dz, Dz, w, w")]
UNSPEC_SEL))]
"TARGET_SVE"
"@
@@ -7432,34 +7496,34 @@
;; Integer (signed) vcond. Don't enforce an immediate range here, since it
;; depends on the comparison; leave it to aarch64_expand_sve_vcond instead.
-(define_expand "vcond<mode><v_int_equiv>"
- [(set (match_operand:SVE_FULL 0 "register_operand")
- (if_then_else:SVE_FULL
+(define_expand "vcond<SVE_ALL:mode><SVE_I:mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand")
+ (if_then_else:SVE_ALL
(match_operator 3 "comparison_operator"
- [(match_operand:<V_INT_EQUIV> 4 "register_operand")
- (match_operand:<V_INT_EQUIV> 5 "nonmemory_operand")])
- (match_operand:SVE_FULL 1 "nonmemory_operand")
- (match_operand:SVE_FULL 2 "nonmemory_operand")))]
- "TARGET_SVE"
+ [(match_operand:SVE_I 4 "register_operand")
+ (match_operand:SVE_I 5 "nonmemory_operand")])
+ (match_operand:SVE_ALL 1 "nonmemory_operand")
+ (match_operand:SVE_ALL 2 "nonmemory_operand")))]
+ "TARGET_SVE && <SVE_ALL:container_bits> == <SVE_I:container_bits>"
{
- aarch64_expand_sve_vcond (<MODE>mode, <V_INT_EQUIV>mode, operands);
+ aarch64_expand_sve_vcond (<SVE_ALL:MODE>mode, <SVE_I:MODE>mode, operands);
DONE;
}
)
;; Integer vcondu. Don't enforce an immediate range here, since it
;; depends on the comparison; leave it to aarch64_expand_sve_vcond instead.
-(define_expand "vcondu<mode><v_int_equiv>"
- [(set (match_operand:SVE_FULL 0 "register_operand")
- (if_then_else:SVE_FULL
+(define_expand "vcondu<SVE_ALL:mode><SVE_I:mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand")
+ (if_then_else:SVE_ALL
(match_operator 3 "comparison_operator"
- [(match_operand:<V_INT_EQUIV> 4 "register_operand")
- (match_operand:<V_INT_EQUIV> 5 "nonmemory_operand")])
- (match_operand:SVE_FULL 1 "nonmemory_operand")
- (match_operand:SVE_FULL 2 "nonmemory_operand")))]
- "TARGET_SVE"
+ [(match_operand:SVE_I 4 "register_operand")
+ (match_operand:SVE_I 5 "nonmemory_operand")])
+ (match_operand:SVE_ALL 1 "nonmemory_operand")
+ (match_operand:SVE_ALL 2 "nonmemory_operand")))]
+ "TARGET_SVE && <SVE_ALL:container_bits> == <SVE_I:container_bits>"
{
- aarch64_expand_sve_vcond (<MODE>mode, <V_INT_EQUIV>mode, operands);
+ aarch64_expand_sve_vcond (<SVE_ALL:MODE>mode, <SVE_I:MODE>mode, operands);
DONE;
}
)
@@ -7504,8 +7568,8 @@
[(parallel
[(set (match_operand:<VPRED> 0 "register_operand")
(match_operator:<VPRED> 1 "comparison_operator"
- [(match_operand:SVE_FULL_I 2 "register_operand")
- (match_operand:SVE_FULL_I 3 "nonmemory_operand")]))
+ [(match_operand:SVE_I 2 "register_operand")
+ (match_operand:SVE_I 3 "nonmemory_operand")]))
(clobber (reg:CC_NZC CC_REGNUM))])]
"TARGET_SVE"
{
@@ -7522,8 +7586,8 @@
[(parallel
[(set (match_operand:<VPRED> 0 "register_operand")
(match_operator:<VPRED> 1 "comparison_operator"
- [(match_operand:SVE_FULL_I 2 "register_operand")
- (match_operand:SVE_FULL_I 3 "nonmemory_operand")]))
+ [(match_operand:SVE_I 2 "register_operand")
+ (match_operand:SVE_I 3 "nonmemory_operand")]))
(clobber (reg:CC_NZC CC_REGNUM))])]
"TARGET_SVE"
{
@@ -7534,14 +7598,38 @@
)
;; Predicated integer comparisons.
+;;
+;; For unpacked vectors, only the lowpart element in each input container
+;; has a defined value, and only the predicate bits associated with
+;; those elements are defined. For example, when comparing two VNx2SIs:
+;;
+;; - The VNx2SIs can be seem as VNx2DIs in which the low halves of each
+;; DI container store an SI element. The upper bits of each DI container
+;; are undefined.
+;;
+;; - Alternatively, the VNx2SIs can be seen as VNx4SIs in which the
+;; even elements are defined and the odd elements are undefined.
+;;
+;; - The associated predicate mode is VNx2BI. This means that only the
+;; low bit in each predicate byte is defined (on input and on output).
+;;
+;; - We use a .s comparison to compare VNx2SIs, under the control of a
+;; VNx2BI governing predicate, to produce a VNx2BI result. If we view
+;; the .s operation as operating on VNx4SIs then for odd lanes:
+;;
+;; - the input governing predicate bit is undefined
+;; - the SI elements being compared are undefined
+;; - the predicate result bit is therefore undefined, but
+;; - the predicate result bit is in the undefined part of a VNx2BI,
+;; so its value doesn't matter anyway.
(define_insn "@aarch64_pred_cmp<cmp_op><mode>"
[(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
(unspec:<VPRED>
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 2 "aarch64_sve_ptrue_flag")
(SVE_INT_CMP:<VPRED>
- (match_operand:SVE_FULL_I 3 "register_operand" "w, w")
- (match_operand:SVE_FULL_I 4 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ (match_operand:SVE_I 3 "register_operand" "w, w")
+ (match_operand:SVE_I 4 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
UNSPEC_PRED_Z))
(clobber (reg:CC_NZC CC_REGNUM))]
"TARGET_SVE"
@@ -7562,8 +7650,8 @@
[(match_operand 6)
(match_operand:SI 7 "aarch64_sve_ptrue_flag")
(SVE_INT_CMP:<VPRED>
- (match_operand:SVE_FULL_I 2 "register_operand" "w, w")
- (match_operand:SVE_FULL_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
UNSPEC_PRED_Z)]
UNSPEC_PTEST))
(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
@@ -7598,8 +7686,8 @@
[(match_operand 6)
(match_operand:SI 7 "aarch64_sve_ptrue_flag")
(SVE_INT_CMP:<VPRED>
- (match_operand:SVE_FULL_I 2 "register_operand" "w, w")
- (match_operand:SVE_FULL_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
UNSPEC_PRED_Z)]
UNSPEC_PTEST))
(clobber (match_scratch:<VPRED> 0 "=Upa, Upa"))]
@@ -7626,8 +7714,8 @@
[(match_operand 4)
(const_int SVE_KNOWN_PTRUE)
(SVE_INT_CMP:<VPRED>
- (match_operand:SVE_FULL_I 2 "register_operand" "w, w")
- (match_operand:SVE_FULL_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
UNSPEC_PRED_Z)
(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")))
(clobber (reg:CC_NZC CC_REGNUM))]
@@ -8273,14 +8361,14 @@
;; Duplicate one element of a vector.
(define_insn "@aarch64_sve_dup_lane<mode>"
- [(set (match_operand:SVE_FULL 0 "register_operand" "=w")
- (vec_duplicate:SVE_FULL
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+ (vec_duplicate:SVE_ALL
(vec_select:<VEL>
- (match_operand:SVE_FULL 1 "register_operand" "w")
+ (match_operand:SVE_ALL 1 "register_operand" "w")
(parallel [(match_operand:SI 2 "const_int_operand")]))))]
"TARGET_SVE
- && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 0, 63)"
- "dup\t%0.<Vetype>, %1.<Vetype>[%2]"
+ && IN_RANGE (INTVAL (operands[2]) * <container_bits> / 8, 0, 63)"
+ "dup\t%0.<Vctype>, %1.<Vctype>[%2]"
)
;; Use DUP.Q to duplicate a 128-bit segment of a register.
@@ -8321,17 +8409,18 @@
;; Reverse the order of elements within a full vector.
(define_insn "@aarch64_sve_rev<mode>"
- [(set (match_operand:SVE_FULL 0 "register_operand" "=w")
- (unspec:SVE_FULL
- [(match_operand:SVE_FULL 1 "register_operand" "w")]
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+ (unspec:SVE_ALL
+ [(match_operand:SVE_ALL 1 "register_operand" "w")]
UNSPEC_REV))]
"TARGET_SVE"
- "rev\t%0.<Vetype>, %1.<Vetype>")
+ "rev\t%0.<Vctype>, %1.<Vctype>")
;; -------------------------------------------------------------------------
;; ---- [INT,FP] Special-purpose binary permutes
;; -------------------------------------------------------------------------
;; Includes:
+;; - EXT
;; - SPLICE
;; - TRN1
;; - TRN2
@@ -8359,13 +8448,13 @@
;; Permutes that take half the elements from one vector and half the
;; elements from the other.
(define_insn "@aarch64_sve_<perm_insn><mode>"
- [(set (match_operand:SVE_FULL 0 "register_operand" "=w")
- (unspec:SVE_FULL
- [(match_operand:SVE_FULL 1 "register_operand" "w")
- (match_operand:SVE_FULL 2 "register_operand" "w")]
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+ (unspec:SVE_ALL
+ [(match_operand:SVE_ALL 1 "register_operand" "w")
+ (match_operand:SVE_ALL 2 "register_operand" "w")]
PERMUTE))]
"TARGET_SVE"
- "<perm_insn>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+ "<perm_insn>\t%0.<Vctype>, %1.<Vctype>, %2.<Vctype>"
)
;; Apply PERMUTE to 128-bit sequences. The behavior of these patterns
@@ -8383,16 +8472,16 @@
;; Concatenate two vectors and extract a subvector. Note that the
;; immediate (third) operand is the lane index not the byte index.
(define_insn "@aarch64_sve_ext<mode>"
- [(set (match_operand:SVE_FULL 0 "register_operand" "=w, ?&w")
- (unspec:SVE_FULL
- [(match_operand:SVE_FULL 1 "register_operand" "0, w")
- (match_operand:SVE_FULL 2 "register_operand" "w, w")
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_ALL
+ [(match_operand:SVE_ALL 1 "register_operand" "0, w")
+ (match_operand:SVE_ALL 2 "register_operand" "w, w")
(match_operand:SI 3 "const_int_operand")]
UNSPEC_EXT))]
"TARGET_SVE
- && IN_RANGE (INTVAL (operands[3]) * GET_MODE_SIZE (<VEL>mode), 0, 255)"
+ && IN_RANGE (INTVAL (operands[3]) * <container_bits> / 8, 0, 255)"
{
- operands[3] = GEN_INT (INTVAL (operands[3]) * GET_MODE_SIZE (<VEL>mode));
+ operands[3] = GEN_INT (INTVAL (operands[3]) * <container_bits> / 8);
return (which_alternative == 0
? "ext\\t%0.b, %0.b, %2.b, #%3"
: "movprfx\t%0, %1\;ext\\t%0.b, %0.b, %2.b, #%3");
@@ -8521,26 +8610,32 @@
;; Predicated float-to-integer conversion, either to the same width or wider.
(define_insn "@aarch64_sve_<optab>_nontrunc<SVE_FULL_F:mode><SVE_FULL_HSDI:mode>"
- [(set (match_operand:SVE_FULL_HSDI 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_HSDI 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_HSDI
- [(match_operand:<SVE_FULL_HSDI:VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<SVE_FULL_HSDI:VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:SVE_FULL_F 2 "register_operand" "w")]
+ (match_operand:SVE_FULL_F 2 "register_operand" "0, w")]
SVE_COND_FCVTI))]
"TARGET_SVE && <SVE_FULL_HSDI:elem_bits> >= <SVE_FULL_F:elem_bits>"
- "fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>"
+ "@
+ fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>
+ movprfx\t%0, %2\;fcvtz<su>\t%0.<SVE_FULL_HSDI:Vetype>, %1/m, %2.<SVE_FULL_F:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated narrowing float-to-integer conversion.
(define_insn "@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
- [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w")
+ [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w, ?&w")
(unspec:VNx4SI_ONLY
- [(match_operand:VNx2BI 1 "register_operand" "Upl")
+ [(match_operand:VNx2BI 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:VNx2DF_ONLY 2 "register_operand" "w")]
+ (match_operand:VNx2DF_ONLY 2 "register_operand" "0, w")]
SVE_COND_FCVTI))]
"TARGET_SVE"
- "fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>"
+ "@
+ fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+ movprfx\t%0, %2\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated float-to-integer conversion with merging, either to the same
@@ -8702,26 +8797,32 @@
;; Predicated integer-to-float conversion, either to the same width or
;; narrower.
(define_insn "@aarch64_sve_<optab>_nonextend<SVE_FULL_HSDI:mode><SVE_FULL_F:mode>"
- [(set (match_operand:SVE_FULL_F 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_F 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_F
- [(match_operand:<SVE_FULL_HSDI:VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<SVE_FULL_HSDI:VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:SVE_FULL_HSDI 2 "register_operand" "w")]
+ (match_operand:SVE_FULL_HSDI 2 "register_operand" "0, w")]
SVE_COND_ICVTF))]
"TARGET_SVE && <SVE_FULL_HSDI:elem_bits> >= <SVE_FULL_F:elem_bits>"
- "<su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>"
+ "@
+ <su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>
+ movprfx\t%0, %2\;<su>cvtf\t%0.<SVE_FULL_F:Vetype>, %1/m, %2.<SVE_FULL_HSDI:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated widening integer-to-float conversion.
(define_insn "@aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
- [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w")
+ [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w, ?&w")
(unspec:VNx2DF_ONLY
- [(match_operand:VNx2BI 1 "register_operand" "Upl")
+ [(match_operand:VNx2BI 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:VNx4SI_ONLY 2 "register_operand" "w")]
+ (match_operand:VNx4SI_ONLY 2 "register_operand" "0, w")]
SVE_COND_ICVTF))]
"TARGET_SVE"
- "<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>"
+ "@
+ <su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
+ movprfx\t%0, %2\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated integer-to-float conversion with merging, either to the same
@@ -8894,14 +8995,17 @@
;; Predicated float-to-float truncation.
(define_insn "@aarch64_sve_<optab>_trunc<SVE_FULL_SDF:mode><SVE_FULL_HSF:mode>"
- [(set (match_operand:SVE_FULL_HSF 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_HSF 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_HSF
- [(match_operand:<SVE_FULL_SDF:VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<SVE_FULL_SDF:VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:SVE_FULL_SDF 2 "register_operand" "w")]
+ (match_operand:SVE_FULL_SDF 2 "register_operand" "0, w")]
SVE_COND_FCVT))]
"TARGET_SVE && <SVE_FULL_SDF:elem_bits> > <SVE_FULL_HSF:elem_bits>"
- "fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>"
+ "@
+ fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>
+ movprfx\t%0, %2\;fcvt\t%0.<SVE_FULL_HSF:Vetype>, %1/m, %2.<SVE_FULL_SDF:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated float-to-float truncation with merging.
@@ -8948,14 +9052,17 @@
;; Predicated BFCVT.
(define_insn "@aarch64_sve_<optab>_trunc<VNx4SF_ONLY:mode><VNx8BF_ONLY:mode>"
- [(set (match_operand:VNx8BF_ONLY 0 "register_operand" "=w")
+ [(set (match_operand:VNx8BF_ONLY 0 "register_operand" "=w, ?&w")
(unspec:VNx8BF_ONLY
- [(match_operand:VNx4BI 1 "register_operand" "Upl")
+ [(match_operand:VNx4BI 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:VNx4SF_ONLY 2 "register_operand" "w")]
+ (match_operand:VNx4SF_ONLY 2 "register_operand" "0, w")]
SVE_COND_FCVT))]
"TARGET_SVE_BF16"
- "bfcvt\t%0.h, %1/m, %2.s"
+ "@
+ bfcvt\t%0.h, %1/m, %2.s
+ movprfx\t%0, %2\;bfcvt\t%0.h, %1/m, %2.s"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated BFCVT with merging.
@@ -9045,14 +9152,17 @@
;; Predicated float-to-float extension.
(define_insn "@aarch64_sve_<optab>_nontrunc<SVE_FULL_HSF:mode><SVE_FULL_SDF:mode>"
- [(set (match_operand:SVE_FULL_SDF 0 "register_operand" "=w")
+ [(set (match_operand:SVE_FULL_SDF 0 "register_operand" "=w, ?&w")
(unspec:SVE_FULL_SDF
- [(match_operand:<SVE_FULL_SDF:VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<SVE_FULL_SDF:VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:SVE_FULL_HSF 2 "register_operand" "w")]
+ (match_operand:SVE_FULL_HSF 2 "register_operand" "0, w")]
SVE_COND_FCVT))]
"TARGET_SVE && <SVE_FULL_SDF:elem_bits> > <SVE_FULL_HSF:elem_bits>"
- "fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>"
+ "@
+ fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>
+ movprfx\t%0, %2\;fcvt\t%0.<SVE_FULL_SDF:Vetype>, %1/m, %2.<SVE_FULL_HSF:Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated float-to-float extension with merging.
diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md
index 0cafd0b..1897ddf 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -786,17 +786,42 @@
;; -------------------------------------------------------------------------
;; Unpredicated exclusive OR of AND.
-(define_insn "@aarch64_sve2_bcax<mode>"
+(define_expand "@aarch64_sve2_bcax<mode>"
+ [(set (match_operand:SVE_FULL_I 0 "register_operand")
+ (xor:SVE_FULL_I
+ (and:SVE_FULL_I
+ (unspec:SVE_FULL_I
+ [(match_dup 4)
+ (not:SVE_FULL_I
+ (match_operand:SVE_FULL_I 3 "register_operand"))]
+ UNSPEC_PRED_X)
+ (match_operand:SVE_FULL_I 2 "register_operand"))
+ (match_operand:SVE_FULL_I 1 "register_operand")))]
+ "TARGET_SVE2"
+ {
+ operands[4] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve2_bcax<mode>"
[(set (match_operand:SVE_FULL_I 0 "register_operand" "=w, ?&w")
(xor:SVE_FULL_I
(and:SVE_FULL_I
- (match_operand:SVE_FULL_I 2 "register_operand" "w, w")
- (match_operand:SVE_FULL_I 3 "register_operand" "w, w"))
+ (unspec:SVE_FULL_I
+ [(match_operand 4)
+ (not:SVE_FULL_I
+ (match_operand:SVE_FULL_I 3 "register_operand" "w, w"))]
+ UNSPEC_PRED_X)
+ (match_operand:SVE_FULL_I 2 "register_operand" "w, w"))
(match_operand:SVE_FULL_I 1 "register_operand" "0, w")))]
"TARGET_SVE2"
"@
bcax\t%0.d, %0.d, %2.d, %3.d
movprfx\t%0, %1\;bcax\t%0.d, %0.d, %2.d, %3.d"
+ "&& !CONSTANT_P (operands[4])"
+ {
+ operands[4] = CONSTM1_RTX (<VPRED>mode);
+ }
[(set_attr "movprfx" "*,yes")]
)
@@ -1774,6 +1799,16 @@
[(set_attr "movprfx" "*,yes")]
)
+;; unpredicated optab pattern for auto-vectorizer
+(define_expand "cadd<rot><mode>3"
+ [(set (match_operand:SVE_FULL_I 0 "register_operand")
+ (unspec:SVE_FULL_I
+ [(match_operand:SVE_FULL_I 1 "register_operand")
+ (match_operand:SVE_FULL_I 2 "register_operand")]
+ SVE2_INT_CADD_OP))]
+ "TARGET_SVE2"
+)
+
;; -------------------------------------------------------------------------
;; ---- [INT] Complex ternary operations
;; -------------------------------------------------------------------------
@@ -1868,10 +1903,10 @@
(unspec:SVE_FULL_SDF
[(match_operand:<VPRED> 1 "register_operand" "Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:<VNARROW> 2 "register_operand" "w")]
+ (match_operand:<VNARROW> 2 "register_operand" "0")]
SVE2_COND_FP_UNARY_LONG))]
"TARGET_SVE2"
- "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Ventype>"
+ "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Ventype>"
)
;; Predicated convert long top with merging.
@@ -1953,14 +1988,17 @@
;; Predicated FCVTX (equivalent to what would be FCVTXNB, except that
;; it supports MOVPRFX).
(define_insn "@aarch64_pred_<sve_fp_op><mode>"
- [(set (match_operand:VNx4SF_ONLY 0 "register_operand" "=w")
+ [(set (match_operand:VNx4SF_ONLY 0 "register_operand" "=w, ?&w")
(unspec:VNx4SF_ONLY
- [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
+ [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:<VWIDE> 2 "register_operand" "w")]
+ (match_operand:<VWIDE> 2 "register_operand" "0, w")]
SVE2_COND_FP_UNARY_NARROWB))]
"TARGET_SVE2"
- "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vewtype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated FCVTX with merging.
@@ -2051,15 +2089,18 @@
;; Predicated integer unary operations.
(define_insn "@aarch64_pred_<sve_int_op><mode>"
- [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w")
+ [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w, ?&w")
(unspec:VNx4SI_ONLY
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(unspec:VNx4SI_ONLY
- [(match_operand:VNx4SI_ONLY 2 "register_operand" "w")]
+ [(match_operand:VNx4SI_ONLY 2 "register_operand" "0, w")]
SVE2_U32_UNARY)]
UNSPEC_PRED_X))]
"TARGET_SVE2"
- "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated integer unary operations with merging.
@@ -2114,14 +2155,17 @@
;; Predicated FLOGB.
(define_insn "@aarch64_pred_<sve_fp_op><mode>"
- [(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w")
+ [(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w, ?&w")
(unspec:<V_INT_EQUIV>
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SI 3 "aarch64_sve_gp_strictness")
- (match_operand:SVE_FULL_F 2 "register_operand" "w")]
+ (match_operand:SVE_FULL_F 2 "register_operand" "0, w")]
SVE2_COND_INT_UNARY_FP))]
"TARGET_SVE2"
- "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Predicated FLOGB with merging.
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index e060302..af66c11 100644
--- a/gcc/config/aarch64/aarch64-tune.md
+++ b/gcc/config/aarch64/aarch64-tune.md
@@ -1,5 +1,5 @@
;; -*- buffer-read-only: t -*-
;; Generated automatically by gentune.sh from aarch64-cores.def
(define_attr "tune"
- "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,saphira,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82"
+ "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,saphira,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82"
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/config/aarch64/aarch64-vxworks.h b/gcc/config/aarch64/aarch64-vxworks.h
index e22f2f5..9e172c1 100644
--- a/gcc/config/aarch64/aarch64-vxworks.h
+++ b/gcc/config/aarch64/aarch64-vxworks.h
@@ -60,12 +60,14 @@ along with GCC; see the file COPYING3. If not see
#undef STACK_CHECK_PROTECT
#define STACK_CHECK_PROTECT 16384
-/* The VxWorks environment on aarch64 is llvm-based only, uses R18 as
- a TCB pointer. */
-
+/* The VxWorks environment on aarch64 is llvm-based. */
#undef VXWORKS_PERSONALITY
#define VXWORKS_PERSONALITY "llvm"
-#undef TARGET_OS_USES_R18
-#define TARGET_OS_USES_R18 1
+/* VxWorks uses R18 as a TCB pointer. We must pick something else as
+ the static chain and R18 needs to be claimed "fixed". Until we
+ arrange to override the common parts of the port family to
+ acknowledge the latter, configure --with-specs="-ffixed-r18". */
+#undef STATIC_CHAIN_REGNUM
+#define STATIC_CHAIN_REGNUM 9
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index a8cc545..70ddd70 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -559,6 +559,34 @@ static const struct cpu_regmove_cost tsv110_regmove_cost =
2 /* FP2FP */
};
+/* Generic costs for Advanced SIMD vector operations. */
+static const advsimd_vec_cost generic_advsimd_vector_cost =
+{
+ 1, /* int_stmt_cost */
+ 1, /* fp_stmt_cost */
+ 2, /* permute_cost */
+ 2, /* vec_to_scalar_cost */
+ 1, /* scalar_to_vec_cost */
+ 1, /* align_load_cost */
+ 1, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
+};
+
+/* Generic costs for SVE vector operations. */
+static const sve_vec_cost generic_sve_vector_cost =
+{
+ 1, /* int_stmt_cost */
+ 1, /* fp_stmt_cost */
+ 2, /* permute_cost */
+ 2, /* vec_to_scalar_cost */
+ 1, /* scalar_to_vec_cost */
+ 1, /* align_load_cost */
+ 1, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
+};
+
/* Generic costs for vector insn classes. */
static const struct cpu_vector_cost generic_vector_cost =
{
@@ -566,17 +594,23 @@ static const struct cpu_vector_cost generic_vector_cost =
1, /* scalar_fp_stmt_cost */
1, /* scalar_load_cost */
1, /* scalar_store_cost */
- 1, /* vec_int_stmt_cost */
- 1, /* vec_fp_stmt_cost */
- 2, /* vec_permute_cost */
- 2, /* vec_to_scalar_cost */
- 1, /* scalar_to_vec_cost */
- 1, /* vec_align_load_cost */
- 1, /* vec_unalign_load_cost */
- 1, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
3, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &generic_advsimd_vector_cost, /* advsimd */
+ &generic_sve_vector_cost /* sve */
+};
+
+static const advsimd_vec_cost qdf24xx_advsimd_vector_cost =
+{
+ 1, /* int_stmt_cost */
+ 3, /* fp_stmt_cost */
+ 2, /* permute_cost */
+ 1, /* vec_to_scalar_cost */
+ 1, /* scalar_to_vec_cost */
+ 1, /* align_load_cost */
+ 1, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
};
/* QDF24XX costs for vector insn classes. */
@@ -586,17 +620,24 @@ static const struct cpu_vector_cost qdf24xx_vector_cost =
1, /* scalar_fp_stmt_cost */
1, /* scalar_load_cost */
1, /* scalar_store_cost */
- 1, /* vec_int_stmt_cost */
- 3, /* vec_fp_stmt_cost */
- 2, /* vec_permute_cost */
- 1, /* vec_to_scalar_cost */
- 1, /* scalar_to_vec_cost */
- 1, /* vec_align_load_cost */
- 1, /* vec_unalign_load_cost */
- 1, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
3, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &qdf24xx_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
+};
+
+
+static const advsimd_vec_cost thunderx_advsimd_vector_cost =
+{
+ 4, /* int_stmt_cost */
+ 1, /* fp_stmt_cost */
+ 4, /* permute_cost */
+ 2, /* vec_to_scalar_cost */
+ 2, /* scalar_to_vec_cost */
+ 3, /* align_load_cost */
+ 5, /* unalign_load_cost */
+ 5, /* unalign_store_cost */
+ 1 /* store_cost */
};
/* ThunderX costs for vector insn classes. */
@@ -606,17 +647,23 @@ static const struct cpu_vector_cost thunderx_vector_cost =
1, /* scalar_fp_stmt_cost */
3, /* scalar_load_cost */
1, /* scalar_store_cost */
- 4, /* vec_int_stmt_cost */
- 1, /* vec_fp_stmt_cost */
- 4, /* vec_permute_cost */
- 2, /* vec_to_scalar_cost */
- 2, /* scalar_to_vec_cost */
- 3, /* vec_align_load_cost */
- 5, /* vec_unalign_load_cost */
- 5, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
3, /* cond_taken_branch_cost */
- 3 /* cond_not_taken_branch_cost */
+ 3, /* cond_not_taken_branch_cost */
+ &thunderx_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
+};
+
+static const advsimd_vec_cost tsv110_advsimd_vector_cost =
+{
+ 2, /* int_stmt_cost */
+ 2, /* fp_stmt_cost */
+ 2, /* permute_cost */
+ 3, /* vec_to_scalar_cost */
+ 2, /* scalar_to_vec_cost */
+ 5, /* align_load_cost */
+ 5, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
};
static const struct cpu_vector_cost tsv110_vector_cost =
@@ -625,37 +672,49 @@ static const struct cpu_vector_cost tsv110_vector_cost =
1, /* scalar_fp_stmt_cost */
5, /* scalar_load_cost */
1, /* scalar_store_cost */
- 2, /* vec_int_stmt_cost */
- 2, /* vec_fp_stmt_cost */
- 2, /* vec_permute_cost */
- 3, /* vec_to_scalar_cost */
- 2, /* scalar_to_vec_cost */
- 5, /* vec_align_load_cost */
- 5, /* vec_unalign_load_cost */
- 1, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
1, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &tsv110_advsimd_vector_cost, /* advsimd */
+ NULL, /* sve */
};
-/* Generic costs for vector insn classes. */
+static const advsimd_vec_cost cortexa57_advsimd_vector_cost =
+{
+ 2, /* int_stmt_cost */
+ 2, /* fp_stmt_cost */
+ 3, /* permute_cost */
+ 8, /* vec_to_scalar_cost */
+ 8, /* scalar_to_vec_cost */
+ 4, /* align_load_cost */
+ 4, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
+};
+
+/* Cortex-A57 costs for vector insn classes. */
static const struct cpu_vector_cost cortexa57_vector_cost =
{
1, /* scalar_int_stmt_cost */
1, /* scalar_fp_stmt_cost */
4, /* scalar_load_cost */
1, /* scalar_store_cost */
- 2, /* vec_int_stmt_cost */
- 2, /* vec_fp_stmt_cost */
- 3, /* vec_permute_cost */
- 8, /* vec_to_scalar_cost */
- 8, /* scalar_to_vec_cost */
- 4, /* vec_align_load_cost */
- 4, /* vec_unalign_load_cost */
- 1, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
1, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &cortexa57_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
+};
+
+static const advsimd_vec_cost exynosm1_advsimd_vector_cost =
+{
+ 3, /* int_stmt_cost */
+ 3, /* fp_stmt_cost */
+ 3, /* permute_cost */
+ 3, /* vec_to_scalar_cost */
+ 3, /* scalar_to_vec_cost */
+ 5, /* align_load_cost */
+ 5, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
};
static const struct cpu_vector_cost exynosm1_vector_cost =
@@ -664,17 +723,23 @@ static const struct cpu_vector_cost exynosm1_vector_cost =
1, /* scalar_fp_stmt_cost */
5, /* scalar_load_cost */
1, /* scalar_store_cost */
- 3, /* vec_int_stmt_cost */
- 3, /* vec_fp_stmt_cost */
- 3, /* vec_permute_cost */
- 3, /* vec_to_scalar_cost */
- 3, /* scalar_to_vec_cost */
- 5, /* vec_align_load_cost */
- 5, /* vec_unalign_load_cost */
- 1, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
1, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &exynosm1_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
+};
+
+static const advsimd_vec_cost xgene1_advsimd_vector_cost =
+{
+ 2, /* int_stmt_cost */
+ 2, /* fp_stmt_cost */
+ 2, /* permute_cost */
+ 4, /* vec_to_scalar_cost */
+ 4, /* scalar_to_vec_cost */
+ 10, /* align_load_cost */
+ 10, /* unalign_load_cost */
+ 2, /* unalign_store_cost */
+ 2 /* store_cost */
};
/* Generic costs for vector insn classes. */
@@ -684,17 +749,23 @@ static const struct cpu_vector_cost xgene1_vector_cost =
1, /* scalar_fp_stmt_cost */
5, /* scalar_load_cost */
1, /* scalar_store_cost */
- 2, /* vec_int_stmt_cost */
- 2, /* vec_fp_stmt_cost */
- 2, /* vec_permute_cost */
- 4, /* vec_to_scalar_cost */
- 4, /* scalar_to_vec_cost */
- 10, /* vec_align_load_cost */
- 10, /* vec_unalign_load_cost */
- 2, /* vec_unalign_store_cost */
- 2, /* vec_store_cost */
2, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &xgene1_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
+};
+
+static const advsimd_vec_cost thunderx2t99_advsimd_vector_cost =
+{
+ 4, /* int_stmt_cost */
+ 5, /* fp_stmt_cost */
+ 10, /* permute_cost */
+ 6, /* vec_to_scalar_cost */
+ 5, /* scalar_to_vec_cost */
+ 4, /* align_load_cost */
+ 4, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
};
/* Costs for vector insn classes for Vulcan. */
@@ -704,17 +775,23 @@ static const struct cpu_vector_cost thunderx2t99_vector_cost =
6, /* scalar_fp_stmt_cost */
4, /* scalar_load_cost */
1, /* scalar_store_cost */
- 4, /* vec_int_stmt_cost */
- 5, /* vec_fp_stmt_cost */
- 10, /* vec_permute_cost */
- 6, /* vec_to_scalar_cost */
- 5, /* scalar_to_vec_cost */
- 4, /* vec_align_load_cost */
- 4, /* vec_unalign_load_cost */
- 1, /* vec_unalign_store_cost */
- 1, /* vec_store_cost */
2, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &thunderx2t99_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
+};
+
+static const advsimd_vec_cost thunderx3t110_advsimd_vector_cost =
+{
+ 5, /* int_stmt_cost */
+ 5, /* fp_stmt_cost */
+ 10, /* permute_cost */
+ 5, /* vec_to_scalar_cost */
+ 5, /* scalar_to_vec_cost */
+ 4, /* align_load_cost */
+ 4, /* unalign_load_cost */
+ 4, /* unalign_store_cost */
+ 4 /* store_cost */
};
static const struct cpu_vector_cost thunderx3t110_vector_cost =
@@ -723,17 +800,10 @@ static const struct cpu_vector_cost thunderx3t110_vector_cost =
5, /* scalar_fp_stmt_cost */
4, /* scalar_load_cost */
1, /* scalar_store_cost */
- 5, /* vec_int_stmt_cost */
- 5, /* vec_fp_stmt_cost */
- 10, /* vec_permute_cost */
- 5, /* vec_to_scalar_cost */
- 5, /* scalar_to_vec_cost */
- 4, /* vec_align_load_cost */
- 4, /* vec_unalign_load_cost */
- 4, /* vec_unalign_store_cost */
- 4, /* vec_store_cost */
2, /* cond_taken_branch_cost */
- 1 /* cond_not_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &thunderx3t110_advsimd_vector_cost, /* advsimd */
+ NULL /* sve */
};
@@ -1312,7 +1382,7 @@ static const struct tune_params thunderx3t110_tunings =
static const struct tune_params neoversen1_tunings =
{
- &cortexa57_extra_costs,
+ &cortexa76_extra_costs,
&generic_addrcost_table,
&generic_regmove_cost,
&cortexa57_vector_cost,
@@ -1338,7 +1408,7 @@ static const struct tune_params neoversen1_tunings =
static const struct tune_params neoversev1_tunings =
{
- &cortexa57_extra_costs,
+ &cortexa76_extra_costs,
&generic_addrcost_table,
&generic_regmove_cost,
&cortexa57_vector_cost,
@@ -1364,7 +1434,7 @@ static const struct tune_params neoversev1_tunings =
static const struct tune_params neoversen2_tunings =
{
- &cortexa57_extra_costs,
+ &cortexa76_extra_costs,
&generic_addrcost_table,
&generic_regmove_cost,
&cortexa57_vector_cost,
@@ -2226,6 +2296,9 @@ aarch64_classify_vector_mode (machine_mode mode)
/* Partial SVE HF vectors. */
case E_VNx2HFmode:
case E_VNx4HFmode:
+ /* Partial SVE BF vectors. */
+ case E_VNx2BFmode:
+ case E_VNx4BFmode:
/* Partial SVE SF vector. */
case E_VNx2SFmode:
return TARGET_SVE ? VEC_SVE_DATA | VEC_PARTIAL : 0;
@@ -2886,33 +2959,6 @@ aarch64_is_noplt_call_p (rtx sym)
return false;
}
-/* Return true if the offsets to a zero/sign-extract operation
- represent an expression that matches an extend operation. The
- operands represent the parameters from
-
- (extract:MODE (mult (reg) (MULT_IMM)) (EXTRACT_IMM) (const_int 0)). */
-bool
-aarch64_is_extend_from_extract (scalar_int_mode mode, rtx mult_imm,
- rtx extract_imm)
-{
- HOST_WIDE_INT mult_val, extract_val;
-
- if (! CONST_INT_P (mult_imm) || ! CONST_INT_P (extract_imm))
- return false;
-
- mult_val = INTVAL (mult_imm);
- extract_val = INTVAL (extract_imm);
-
- if (extract_val > 8
- && extract_val < GET_MODE_BITSIZE (mode)
- && exact_log2 (extract_val & ~7) > 0
- && (extract_val & 7) <= 4
- && mult_val == (1 << (extract_val & 7)))
- return true;
-
- return false;
-}
-
/* Emit an insn that's a simple single-set. Both the operands must be
known to be valid. */
inline static rtx_insn *
@@ -3009,7 +3055,7 @@ tls_symbolic_operand_type (rtx addr)
enum tls_model tls_kind = TLS_MODEL_NONE;
poly_int64 offset;
addr = strip_offset_and_salt (addr, &offset);
- if (GET_CODE (addr) == SYMBOL_REF)
+ if (SYMBOL_REF_P (addr))
tls_kind = SYMBOL_REF_TLS_MODEL (addr);
return tls_kind;
@@ -3150,7 +3196,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
/* The operand is expected to be MEM. Whenever the related insn
pattern changed, above code which calculate mem should be
updated. */
- gcc_assert (GET_CODE (mem) == MEM);
+ gcc_assert (MEM_P (mem));
MEM_READONLY_P (mem) = 1;
MEM_NOTRAP_P (mem) = 1;
emit_insn (insn);
@@ -3193,7 +3239,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
mem = XVECEXP (XEXP (SET_SRC (insn), 0), 0, 0);
}
- gcc_assert (GET_CODE (mem) == MEM);
+ gcc_assert (MEM_P (mem));
MEM_READONLY_P (mem) = 1;
MEM_NOTRAP_P (mem) = 1;
emit_insn (insn);
@@ -4259,7 +4305,7 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
bool
aarch64_mov128_immediate (rtx imm)
{
- if (GET_CODE (imm) == CONST_INT)
+ if (CONST_INT_P (imm))
return true;
gcc_assert (CONST_WIDE_INT_NUNITS (imm) == 2);
@@ -5123,8 +5169,8 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
/* Check on what type of symbol it is. */
scalar_int_mode int_mode;
- if ((GET_CODE (imm) == SYMBOL_REF
- || GET_CODE (imm) == LABEL_REF
+ if ((SYMBOL_REF_P (imm)
+ || LABEL_REF_P (imm)
|| GET_CODE (imm) == CONST
|| GET_CODE (imm) == CONST_POLY_INT)
&& is_a <scalar_int_mode> (mode, &int_mode))
@@ -5414,9 +5460,35 @@ bool
aarch64_maybe_expand_sve_subreg_move (rtx dest, rtx src)
{
gcc_assert (BYTES_BIG_ENDIAN);
- if (GET_CODE (dest) == SUBREG)
+
+ /* Do not try to optimize subregs that LRA has created for matched
+ reloads. These subregs only exist as a temporary measure to make
+ the RTL well-formed, but they are exempt from the usual
+ TARGET_CAN_CHANGE_MODE_CLASS rules.
+
+ For example, if we have:
+
+ (set (reg:VNx8HI R1) (foo:VNx8HI (reg:VNx4SI R2)))
+
+ and the constraints require R1 and R2 to be in the same register,
+ LRA may need to create RTL such as:
+
+ (set (subreg:VNx4SI (reg:VNx8HI TMP) 0) (reg:VNx4SI R2))
+ (set (reg:VNx8HI TMP) (foo:VNx8HI (subreg:VNx4SI (reg:VNx8HI TMP) 0)))
+ (set (reg:VNx8HI R1) (reg:VNx8HI TMP))
+
+ which forces both the input and output of the original instruction
+ to use the same hard register. But for this to work, the normal
+ rules have to be suppressed on the subreg input, otherwise LRA
+ would need to reload that input too, meaning that the process
+ would never terminate. To compensate for this, the normal rules
+ are also suppressed for the subreg output of the first move.
+ Ignoring the special case and handling the first move normally
+ would therefore generate wrong code: we would reverse the elements
+ for the first subreg but not reverse them back for the second subreg. */
+ if (SUBREG_P (dest) && !LRA_SUBREG_P (dest))
dest = SUBREG_REG (dest);
- if (GET_CODE (src) == SUBREG)
+ if (SUBREG_P (src) && !LRA_SUBREG_P (src))
src = SUBREG_REG (src);
/* The optimization handles two single SVE REGs with different element
@@ -6299,10 +6371,6 @@ aarch64_libgcc_cmp_return_mode (void)
#error Cannot use simple address calculation for stack probing
#endif
-/* The pair of scratch registers used for stack probing. */
-#define PROBE_STACK_FIRST_REG R9_REGNUM
-#define PROBE_STACK_SECOND_REG R10_REGNUM
-
/* Emit code to probe a range of stack addresses from FIRST to FIRST+POLY_SIZE,
inclusive. These are offsets from the current stack pointer. */
@@ -6316,7 +6384,7 @@ aarch64_emit_probe_stack_range (HOST_WIDE_INT first, poly_int64 poly_size)
return;
}
- rtx reg1 = gen_rtx_REG (Pmode, PROBE_STACK_FIRST_REG);
+ rtx reg1 = gen_rtx_REG (Pmode, PROBE_STACK_FIRST_REGNUM);
/* See the same assertion on PROBE_INTERVAL above. */
gcc_assert ((first % ARITH_FACTOR) == 0);
@@ -6374,7 +6442,7 @@ aarch64_emit_probe_stack_range (HOST_WIDE_INT first, poly_int64 poly_size)
equality test for the loop condition. */
else
{
- rtx reg2 = gen_rtx_REG (Pmode, PROBE_STACK_SECOND_REG);
+ rtx reg2 = gen_rtx_REG (Pmode, PROBE_STACK_SECOND_REGNUM);
/* Step 1: round SIZE to the previous multiple of the interval. */
@@ -7058,6 +7126,9 @@ aarch64_gen_store_pair (machine_mode mode, rtx mem1, rtx reg1, rtx mem2,
case E_V4SImode:
return gen_vec_store_pairv4siv4si (mem1, reg1, mem2, reg2);
+ case E_V16QImode:
+ return gen_vec_store_pairv16qiv16qi (mem1, reg1, mem2, reg2);
+
default:
gcc_unreachable ();
}
@@ -8561,7 +8632,7 @@ aarch64_tls_referenced_p (rtx x)
FOR_EACH_SUBRTX (iter, array, x, ALL)
{
const_rtx x = *iter;
- if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0)
+ if (SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0)
return true;
/* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
TLS offsets, not real symbol references. */
@@ -8787,7 +8858,7 @@ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
poly_int64 offset;
rtx base = strip_offset_and_salt (x, &offset);
- if (GET_CODE (base) == SYMBOL_REF || GET_CODE (base) == LABEL_REF)
+ if (SYMBOL_REF_P (base) || LABEL_REF_P (base))
{
/* We checked for POLY_INT_CST offsets above. */
if (aarch64_classify_symbol (base, offset.to_constant ())
@@ -8873,7 +8944,7 @@ static bool
aarch64_base_register_rtx_p (rtx x, bool strict_p)
{
if (!strict_p
- && GET_CODE (x) == SUBREG
+ && SUBREG_P (x)
&& contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (x))])
x = SUBREG_REG (x);
@@ -8892,7 +8963,7 @@ aarch64_classify_index (struct aarch64_address_info *info, rtx x,
int shift;
/* (reg:P) */
- if ((REG_P (x) || GET_CODE (x) == SUBREG)
+ if ((REG_P (x) || SUBREG_P (x))
&& GET_MODE (x) == Pmode)
{
type = ADDRESS_REG_REG;
@@ -8936,22 +9007,6 @@ aarch64_classify_index (struct aarch64_address_info *info, rtx x,
index = XEXP (XEXP (x, 0), 0);
shift = INTVAL (XEXP (x, 1));
}
- /* (sign_extract:DI (mult:DI (reg:DI) (const_int scale)) 32+shift 0) */
- else if ((GET_CODE (x) == SIGN_EXTRACT
- || GET_CODE (x) == ZERO_EXTRACT)
- && GET_MODE (x) == DImode
- && GET_CODE (XEXP (x, 0)) == MULT
- && GET_MODE (XEXP (XEXP (x, 0), 0)) == DImode
- && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
- {
- type = (GET_CODE (x) == SIGN_EXTRACT)
- ? ADDRESS_REG_SXTW : ADDRESS_REG_UXTW;
- index = XEXP (XEXP (x, 0), 0);
- shift = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)));
- if (INTVAL (XEXP (x, 1)) != 32 + shift
- || INTVAL (XEXP (x, 2)) != 0)
- shift = -1;
- }
/* (and:DI (mult:DI (reg:DI) (const_int scale))
(const_int 0xffffffff<<shift)) */
else if (GET_CODE (x) == AND
@@ -8967,22 +9022,6 @@ aarch64_classify_index (struct aarch64_address_info *info, rtx x,
if (INTVAL (XEXP (x, 1)) != (HOST_WIDE_INT)0xffffffff << shift)
shift = -1;
}
- /* (sign_extract:DI (ashift:DI (reg:DI) (const_int shift)) 32+shift 0) */
- else if ((GET_CODE (x) == SIGN_EXTRACT
- || GET_CODE (x) == ZERO_EXTRACT)
- && GET_MODE (x) == DImode
- && GET_CODE (XEXP (x, 0)) == ASHIFT
- && GET_MODE (XEXP (XEXP (x, 0), 0)) == DImode
- && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
- {
- type = (GET_CODE (x) == SIGN_EXTRACT)
- ? ADDRESS_REG_SXTW : ADDRESS_REG_UXTW;
- index = XEXP (XEXP (x, 0), 0);
- shift = INTVAL (XEXP (XEXP (x, 0), 1));
- if (INTVAL (XEXP (x, 1)) != 32 + shift
- || INTVAL (XEXP (x, 2)) != 0)
- shift = -1;
- }
/* (and:DI (ashift:DI (reg:DI) (const_int shift))
(const_int 0xffffffff<<shift)) */
else if (GET_CODE (x) == AND
@@ -9022,7 +9061,7 @@ aarch64_classify_index (struct aarch64_address_info *info, rtx x,
return false;
if (!strict_p
- && GET_CODE (index) == SUBREG
+ && SUBREG_P (index)
&& contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))])
index = SUBREG_REG (index);
@@ -9318,8 +9357,8 @@ aarch64_classify_address (struct aarch64_address_info *info,
{
poly_int64 offset;
rtx sym = strip_offset_and_salt (x, &offset);
- return ((GET_CODE (sym) == LABEL_REF
- || (GET_CODE (sym) == SYMBOL_REF
+ return ((LABEL_REF_P (sym)
+ || (SYMBOL_REF_P (sym)
&& CONSTANT_POOL_ADDRESS_P (sym)
&& aarch64_pcrelative_literal_loads)));
}
@@ -9335,7 +9374,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
poly_int64 offset;
HOST_WIDE_INT const_offset;
rtx sym = strip_offset_and_salt (info->offset, &offset);
- if (GET_CODE (sym) == SYMBOL_REF
+ if (SYMBOL_REF_P (sym)
&& offset.is_constant (&const_offset)
&& (aarch64_classify_symbol (sym, const_offset)
== SYMBOL_SMALL_ABSOLUTE))
@@ -9397,7 +9436,7 @@ aarch64_symbolic_address_p (rtx x)
{
poly_int64 offset;
x = strip_offset_and_salt (x, &offset);
- return GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF;
+ return SYMBOL_REF_P (x) || LABEL_REF_P (x);
}
/* Classify the base of symbolic expression X. */
@@ -9522,7 +9561,7 @@ aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval)
}
scalar_float_mode mode;
- if (GET_CODE (value) != CONST_DOUBLE
+ if (!CONST_DOUBLE_P (value)
|| !is_a <scalar_float_mode> (GET_MODE (value), &mode)
|| GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
/* Only support up to DF mode. */
@@ -9562,7 +9601,7 @@ aarch64_float_const_rtx_p (rtx x)
mov/movk pairs over ldr/adrp pairs. */
unsigned HOST_WIDE_INT ival;
- if (GET_CODE (x) == CONST_DOUBLE
+ if (CONST_DOUBLE_P (x)
&& SCALAR_FLOAT_MODE_P (mode)
&& aarch64_reinterpret_float_as_int (x, &ival))
{
@@ -9601,7 +9640,7 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
scalar_int_mode imode;
unsigned HOST_WIDE_INT ival;
- if (GET_CODE (x) == CONST_DOUBLE
+ if (CONST_DOUBLE_P (x)
&& SCALAR_FLOAT_MODE_P (mode))
{
if (!aarch64_reinterpret_float_as_int (x, &ival))
@@ -9613,7 +9652,7 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
imode = int_mode_for_mode (mode).require ();
}
- else if (GET_CODE (x) == CONST_INT
+ else if (CONST_INT_P (x)
&& is_a <scalar_int_mode> (mode, &imode))
ival = INTVAL (x);
else
@@ -9764,7 +9803,7 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
the comparison will have to be swapped when we emit the assembly
code. */
if ((mode_x == SImode || mode_x == DImode)
- && (REG_P (y) || GET_CODE (y) == SUBREG || y == const0_rtx)
+ && (REG_P (y) || SUBREG_P (y) || y == const0_rtx)
&& (code_x == ASHIFT || code_x == ASHIFTRT
|| code_x == LSHIFTRT
|| code_x == ZERO_EXTEND || code_x == SIGN_EXTEND))
@@ -9773,7 +9812,7 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
/* Similarly for a negated operand, but we can only do this for
equalities. */
if ((mode_x == SImode || mode_x == DImode)
- && (REG_P (y) || GET_CODE (y) == SUBREG)
+ && (REG_P (y) || SUBREG_P (y))
&& (code == EQ || code == NE)
&& code_x == NEG)
return CC_Zmode;
@@ -10567,7 +10606,7 @@ aarch64_print_operand (FILE *f, rtx x, int code)
{
machine_mode mode = GET_MODE (x);
- if (GET_CODE (x) != MEM
+ if (!MEM_P (x)
|| (code == 'y' && maybe_ne (GET_MODE_SIZE (mode), 16)))
{
output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -10730,7 +10769,7 @@ aarch64_label_mentioned_p (rtx x)
const char *fmt;
int i;
- if (GET_CODE (x) == LABEL_REF)
+ if (LABEL_REF_P (x))
return true;
/* UNSPEC_TLS entries for a symbol include a LABEL_REF for the
@@ -10912,7 +10951,7 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
/* If we have to disable direct literal pool loads and stores because the
function is too big, then we need a scratch register. */
- if (MEM_P (x) && GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)
+ if (MEM_P (x) && SYMBOL_REF_P (x) && CONSTANT_POOL_ADDRESS_P (x)
&& (SCALAR_FLOAT_MODE_P (GET_MODE (x))
|| targetm.vector_mode_supported_p (GET_MODE (x)))
&& !aarch64_pcrelative_literal_loads)
@@ -11068,10 +11107,10 @@ aarch64_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
/* XXX We should really define a "clear_cache" pattern and use
gen_clear_cache(). */
a_tramp = XEXP (m_tramp, 0);
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
- LCT_NORMAL, VOIDmode, a_tramp, ptr_mode,
- plus_constant (ptr_mode, a_tramp, TRAMPOLINE_SIZE),
- ptr_mode);
+ maybe_emit_call_builtin___clear_cache (a_tramp,
+ plus_constant (ptr_mode,
+ a_tramp,
+ TRAMPOLINE_SIZE));
}
static unsigned char
@@ -11143,7 +11182,7 @@ aarch64_preferred_reload_class (rtx x, reg_class_t regclass)
rtx lhs = XEXP (x, 0);
/* Look through a possible SUBREG introduced by ILP32. */
- if (GET_CODE (lhs) == SUBREG)
+ if (SUBREG_P (lhs))
lhs = SUBREG_REG (lhs);
gcc_assert (REG_P (lhs));
@@ -11360,16 +11399,6 @@ aarch64_strip_extend (rtx x, bool strip_shift)
if (!is_a <scalar_int_mode> (GET_MODE (op), &mode))
return op;
- /* Zero and sign extraction of a widened value. */
- if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT)
- && XEXP (op, 2) == const0_rtx
- && GET_CODE (XEXP (op, 0)) == MULT
- && aarch64_is_extend_from_extract (mode, XEXP (XEXP (op, 0), 1),
- XEXP (op, 1)))
- return XEXP (XEXP (op, 0), 0);
-
- /* It can also be represented (for zero-extend) as an AND with an
- immediate. */
if (GET_CODE (op) == AND
&& GET_CODE (XEXP (op, 0)) == MULT
&& CONST_INT_P (XEXP (XEXP (op, 0), 1))
@@ -11613,7 +11642,7 @@ aarch64_address_cost (rtx x,
if (!aarch64_classify_address (&info, x, mode, false))
{
- if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF)
+ if (GET_CODE (x) == CONST || SYMBOL_REF_P (x))
{
/* This is a CONST or SYMBOL ref which will be split
in a different way depending on the code model in use.
@@ -11704,35 +11733,15 @@ aarch64_branch_cost (bool speed_p, bool predictable_p)
return branch_costs->unpredictable;
}
-/* Return true if the RTX X in mode MODE is a zero or sign extract
+/* Return true if X is a zero or sign extract
usable in an ADD or SUB (extended register) instruction. */
static bool
-aarch64_rtx_arith_op_extract_p (rtx x, scalar_int_mode mode)
-{
- /* Catch add with a sign extract.
- This is add_<optab><mode>_multp2. */
- if (GET_CODE (x) == SIGN_EXTRACT
- || GET_CODE (x) == ZERO_EXTRACT)
- {
- rtx op0 = XEXP (x, 0);
- rtx op1 = XEXP (x, 1);
- rtx op2 = XEXP (x, 2);
-
- if (GET_CODE (op0) == MULT
- && CONST_INT_P (op1)
- && op2 == const0_rtx
- && CONST_INT_P (XEXP (op0, 1))
- && aarch64_is_extend_from_extract (mode,
- XEXP (op0, 1),
- op1))
- {
- return true;
- }
- }
+aarch64_rtx_arith_op_extract_p (rtx x)
+{
/* The simple case <ARITH>, XD, XN, XM, [us]xt.
No shift. */
- else if (GET_CODE (x) == SIGN_EXTEND
- || GET_CODE (x) == ZERO_EXTEND)
+ if (GET_CODE (x) == SIGN_EXTEND
+ || GET_CODE (x) == ZERO_EXTEND)
return REG_P (XEXP (x, 0));
return false;
@@ -12419,8 +12428,8 @@ cost_minus:
}
/* Look for SUB (extended register). */
- if (is_a <scalar_int_mode> (mode, &int_mode)
- && aarch64_rtx_arith_op_extract_p (op1, int_mode))
+ if (is_a <scalar_int_mode> (mode)
+ && aarch64_rtx_arith_op_extract_p (op1))
{
if (speed)
*cost += extra_cost->alu.extend_arith;
@@ -12499,8 +12508,8 @@ cost_plus:
*cost += rtx_cost (op1, mode, PLUS, 1, speed);
/* Look for ADD (extended register). */
- if (is_a <scalar_int_mode> (mode, &int_mode)
- && aarch64_rtx_arith_op_extract_p (op0, int_mode))
+ if (is_a <scalar_int_mode> (mode)
+ && aarch64_rtx_arith_op_extract_p (op0))
{
if (speed)
*cost += extra_cost->alu.extend_arith;
@@ -13773,6 +13782,13 @@ aarch64_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
if (vectype != NULL)
fp = FLOAT_TYPE_P (vectype);
+ const simd_vec_cost *simd_costs;
+ if (vectype != NULL && aarch64_sve_mode_p (TYPE_MODE (vectype))
+ && costs->sve != NULL)
+ simd_costs = costs->sve;
+ else
+ simd_costs = costs->advsimd;
+
switch (type_of_cost)
{
case scalar_stmt:
@@ -13785,27 +13801,28 @@ aarch64_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
return costs->scalar_store_cost;
case vector_stmt:
- return fp ? costs->vec_fp_stmt_cost : costs->vec_int_stmt_cost;
+ return fp ? simd_costs->fp_stmt_cost
+ : simd_costs->int_stmt_cost;
case vector_load:
- return costs->vec_align_load_cost;
+ return simd_costs->align_load_cost;
case vector_store:
- return costs->vec_store_cost;
+ return simd_costs->store_cost;
case vec_to_scalar:
- return costs->vec_to_scalar_cost;
+ return simd_costs->vec_to_scalar_cost;
case scalar_to_vec:
- return costs->scalar_to_vec_cost;
+ return simd_costs->scalar_to_vec_cost;
case unaligned_load:
case vector_gather_load:
- return costs->vec_unalign_load_cost;
+ return simd_costs->unalign_load_cost;
case unaligned_store:
case vector_scatter_store:
- return costs->vec_unalign_store_cost;
+ return simd_costs->unalign_store_cost;
case cond_branch_taken:
return costs->cond_taken_branch_cost;
@@ -13814,10 +13831,11 @@ aarch64_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
return costs->cond_not_taken_branch_cost;
case vec_perm:
- return costs->vec_permute_cost;
+ return simd_costs->permute_cost;
case vec_promote_demote:
- return fp ? costs->vec_fp_stmt_cost : costs->vec_int_stmt_cost;
+ return fp ? simd_costs->fp_stmt_cost
+ : simd_costs->int_stmt_cost;
case vec_construct:
elements = estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype));
@@ -14503,6 +14521,12 @@ aarch64_override_options_internal (struct gcc_options *opts)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_sched_autopref_queue_depth, queue_depth);
+ /* If using Advanced SIMD only for autovectorization disable SVE vector costs
+ comparison. */
+ if (aarch64_autovec_preference == 1)
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ aarch64_sve_compare_costs, 0);
+
/* Set up parameters to be used in prefetching algorithm. Do not
override the defaults unless we are tuning for a core we have
researched values for. */
@@ -16034,7 +16058,7 @@ aarch64_tls_symbol_p (rtx x)
return false;
x = strip_salt (x);
- if (GET_CODE (x) != SYMBOL_REF)
+ if (!SYMBOL_REF_P (x))
return false;
return SYMBOL_REF_TLS_MODEL (x) != 0;
@@ -16091,7 +16115,7 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
{
x = strip_salt (x);
- if (GET_CODE (x) == LABEL_REF)
+ if (LABEL_REF_P (x))
{
switch (aarch64_cmodel)
{
@@ -16112,7 +16136,7 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
}
}
- if (GET_CODE (x) == SYMBOL_REF)
+ if (SYMBOL_REF_P (x))
{
if (aarch64_tls_symbol_p (x))
return aarch64_classify_tls_symbol (x);
@@ -16192,7 +16216,7 @@ aarch64_legitimate_pic_operand_p (rtx x)
{
poly_int64 offset;
x = strip_offset_and_salt (x, &offset);
- if (GET_CODE (x) == SYMBOL_REF)
+ if (SYMBOL_REF_P (x))
return false;
return true;
@@ -16253,7 +16277,7 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
return true;
/* Label references are always constant. */
- if (GET_CODE (x) == LABEL_REF)
+ if (LABEL_REF_P (x))
return true;
return false;
@@ -17343,12 +17367,65 @@ aarch64_simd_container_mode (scalar_mode mode, poly_int64 width)
return word_mode;
}
+/* Compare an SVE mode SVE_M and an Advanced SIMD mode ASIMD_M
+ and return whether the SVE mode should be preferred over the
+ Advanced SIMD one in aarch64_autovectorize_vector_modes. */
+static bool
+aarch64_cmp_autovec_modes (machine_mode sve_m, machine_mode asimd_m)
+{
+ /* Take into account the aarch64-autovec-preference param if non-zero. */
+ bool only_asimd_p = aarch64_autovec_preference == 1;
+ bool only_sve_p = aarch64_autovec_preference == 2;
+
+ if (only_asimd_p)
+ return false;
+ if (only_sve_p)
+ return true;
+
+ /* The preference in case of a tie in costs. */
+ bool prefer_asimd = aarch64_autovec_preference == 3;
+ bool prefer_sve = aarch64_autovec_preference == 4;
+
+ aarch64_sve_vector_bits_enum tune_width = aarch64_tune_params.sve_width;
+
+ poly_int64 nunits_sve = GET_MODE_NUNITS (sve_m);
+ poly_int64 nunits_asimd = GET_MODE_NUNITS (asimd_m);
+ /* If the CPU information does not have an SVE width registered use the
+ generic poly_int comparison that prefers SVE. If a preference is
+ explicitly requested avoid this path. */
+ if (tune_width == SVE_SCALABLE
+ && !prefer_asimd
+ && !prefer_sve)
+ return maybe_gt (nunits_sve, nunits_asimd);
+
+ /* Otherwise estimate the runtime width of the modes involved. */
+ HOST_WIDE_INT est_sve = estimated_poly_value (nunits_sve);
+ HOST_WIDE_INT est_asimd = estimated_poly_value (nunits_asimd);
+
+ /* Preferring SVE means picking it first unless the Advanced SIMD mode
+ is clearly wider. */
+ if (prefer_sve)
+ return est_sve >= est_asimd;
+ /* Conversely, preferring Advanced SIMD means picking SVE only if SVE
+ is clearly wider. */
+ if (prefer_asimd)
+ return est_sve > est_asimd;
+
+ /* In the default case prefer Advanced SIMD over SVE in case of a tie. */
+ return est_sve > est_asimd;
+}
+
/* Return 128-bit container as the preferred SIMD mode for MODE. */
static machine_mode
aarch64_preferred_simd_mode (scalar_mode mode)
{
- poly_int64 bits = TARGET_SVE ? BITS_PER_SVE_VECTOR : 128;
- return aarch64_simd_container_mode (mode, bits);
+ /* Take into account explicit auto-vectorization ISA preferences through
+ aarch64_cmp_autovec_modes. */
+ if (TARGET_SVE && aarch64_cmp_autovec_modes (VNx16QImode, V16QImode))
+ return aarch64_full_sve_mode (mode).else_mode (word_mode);
+ if (TARGET_SIMD)
+ return aarch64_vq_mode (mode).else_mode (word_mode);
+ return word_mode;
}
/* Return a list of possible vector sizes for the vectorizer
@@ -17409,19 +17486,24 @@ aarch64_autovectorize_vector_modes (vector_modes *modes, bool)
- If an Advanced SIMD main loop with N bytes ends up being cheaper
than an SVE main loop with N bytes then by default we'll try to
use the SVE loop to vectorize the epilogue instead. */
- unsigned int sve_i = TARGET_SVE ? 0 : ARRAY_SIZE (sve_modes);
+
+ bool only_asimd_p = aarch64_autovec_preference == 1;
+ bool only_sve_p = aarch64_autovec_preference == 2;
+
+ unsigned int sve_i = (TARGET_SVE && !only_asimd_p) ? 0 : ARRAY_SIZE (sve_modes);
unsigned int advsimd_i = 0;
- while (advsimd_i < ARRAY_SIZE (advsimd_modes))
+
+ while (!only_sve_p && advsimd_i < ARRAY_SIZE (advsimd_modes))
{
if (sve_i < ARRAY_SIZE (sve_modes)
- && maybe_gt (GET_MODE_NUNITS (sve_modes[sve_i]),
- GET_MODE_NUNITS (advsimd_modes[advsimd_i])))
+ && aarch64_cmp_autovec_modes (sve_modes[sve_i],
+ advsimd_modes[advsimd_i]))
modes->safe_push (sve_modes[sve_i++]);
else
modes->safe_push (advsimd_modes[advsimd_i++]);
}
while (sve_i < ARRAY_SIZE (sve_modes))
- modes->safe_push (sve_modes[sve_i++]);
+ modes->safe_push (sve_modes[sve_i++]);
unsigned int flags = 0;
/* Consider enabling VECT_COMPARE_COSTS for SVE, both so that we
@@ -17696,7 +17778,7 @@ aarch64_sve_float_arith_immediate_p (rtx x, bool negate_p)
REAL_VALUE_TYPE r;
if (!const_vec_duplicate_p (x, &elt)
- || GET_CODE (elt) != CONST_DOUBLE)
+ || !CONST_DOUBLE_P (elt))
return false;
r = *CONST_DOUBLE_REAL_VALUE (elt);
@@ -17720,7 +17802,7 @@ aarch64_sve_float_mul_immediate_p (rtx x)
rtx elt;
return (const_vec_duplicate_p (x, &elt)
- && GET_CODE (elt) == CONST_DOUBLE
+ && CONST_DOUBLE_P (elt)
&& (real_equal (CONST_DOUBLE_REAL_VALUE (elt), &dconsthalf)
|| real_equal (CONST_DOUBLE_REAL_VALUE (elt), &dconst2)));
}
@@ -18139,7 +18221,7 @@ aarch64_mov_operand_p (rtx x, machine_mode mode)
}
x = strip_salt (x);
- if (GET_CODE (x) == SYMBOL_REF && mode == DImode && CONSTANT_ADDRESS_P (x))
+ if (SYMBOL_REF_P (x) && mode == DImode && CONSTANT_ADDRESS_P (x))
return true;
if (TARGET_SVE && aarch64_sve_cnt_immediate_p (x))
@@ -20561,18 +20643,21 @@ aarch64_evpc_rev_local (struct expand_vec_perm_d *d)
|| !diff)
return false;
- size = (diff + 1) * GET_MODE_UNIT_SIZE (d->vmode);
- if (size == 8)
+ if (d->vec_flags & VEC_SVE_DATA)
+ size = (diff + 1) * aarch64_sve_container_bits (d->vmode);
+ else
+ size = (diff + 1) * GET_MODE_UNIT_BITSIZE (d->vmode);
+ if (size == 64)
{
unspec = UNSPEC_REV64;
pred_mode = VNx2BImode;
}
- else if (size == 4)
+ else if (size == 32)
{
unspec = UNSPEC_REV32;
pred_mode = VNx4BImode;
}
- else if (size == 2)
+ else if (size == 16)
{
unspec = UNSPEC_REV16;
pred_mode = VNx8BImode;
@@ -20589,28 +20674,11 @@ aarch64_evpc_rev_local (struct expand_vec_perm_d *d)
if (d->testing_p)
return true;
- if (d->vec_flags == VEC_SVE_DATA)
- {
- machine_mode int_mode = aarch64_sve_int_mode (pred_mode);
- rtx target = gen_reg_rtx (int_mode);
- if (BYTES_BIG_ENDIAN)
- /* The act of taking a subreg between INT_MODE and d->vmode
- is itself a reversing operation on big-endian targets;
- see the comment at the head of aarch64-sve.md for details.
- First reinterpret OP0 as INT_MODE without using a subreg
- and without changing the contents. */
- emit_insn (gen_aarch64_sve_reinterpret (int_mode, target, d->op0));
- else
- {
- /* For SVE we use REV[BHW] unspecs derived from the element size
- of v->mode and vector modes whose elements have SIZE bytes.
- This ensures that the vector modes match the predicate modes. */
- int unspec = aarch64_sve_rev_unspec (d->vmode);
- rtx pred = aarch64_ptrue_reg (pred_mode);
- emit_insn (gen_aarch64_pred (unspec, int_mode, target, pred,
- gen_lowpart (int_mode, d->op0)));
- }
- emit_move_insn (d->target, gen_lowpart (d->vmode, target));
+ if (d->vec_flags & VEC_SVE_DATA)
+ {
+ rtx pred = aarch64_ptrue_reg (pred_mode);
+ emit_insn (gen_aarch64_sve_revbhw (d->vmode, pred_mode,
+ d->target, pred, d->op0));
return true;
}
rtx src = gen_rtx_UNSPEC (d->vmode, gen_rtvec (1, d->op0), unspec);
@@ -20655,7 +20723,8 @@ aarch64_evpc_dup (struct expand_vec_perm_d *d)
|| !d->perm[0].is_constant (&elt))
return false;
- if (d->vec_flags == VEC_SVE_DATA && elt >= 64 * GET_MODE_UNIT_SIZE (vmode))
+ if ((d->vec_flags & VEC_SVE_DATA)
+ && elt * (aarch64_sve_container_bits (vmode) / 8) >= 64)
return false;
/* Success! */
@@ -20875,6 +20944,7 @@ aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
if ((d->vec_flags == VEC_ADVSIMD
|| d->vec_flags == VEC_SVE_DATA
+ || d->vec_flags == (VEC_SVE_DATA | VEC_PARTIAL)
|| d->vec_flags == VEC_SVE_PRED)
&& known_gt (nelt, 1))
{
@@ -21299,29 +21369,38 @@ aarch64_copy_one_block_and_progress_pointers (rtx *src, rtx *dst,
bool
aarch64_expand_cpymem (rtx *operands)
{
- int n, mode_bits;
+ int mode_bits;
rtx dst = operands[0];
rtx src = operands[1];
rtx base;
- machine_mode cur_mode = BLKmode, next_mode;
- bool speed_p = !optimize_function_for_size_p (cfun);
-
- /* When optimizing for size, give a better estimate of the length of a
- memcpy call, but use the default otherwise. Moves larger than 8 bytes
- will always require an even number of instructions to do now. And each
- operation requires both a load+store, so devide the max number by 2. */
- int max_num_moves = (speed_p ? 16 : AARCH64_CALL_RATIO) / 2;
+ machine_mode cur_mode = BLKmode;
- /* We can't do anything smart if the amount to copy is not constant. */
+ /* Only expand fixed-size copies. */
if (!CONST_INT_P (operands[2]))
return false;
- n = INTVAL (operands[2]);
+ unsigned HOST_WIDE_INT size = INTVAL (operands[2]);
- /* Try to keep the number of instructions low. For all cases we will do at
- most two moves for the residual amount, since we'll always overlap the
- remainder. */
- if (((n / 16) + (n % 16 ? 2 : 0)) > max_num_moves)
+ /* Inline up to 256 bytes when optimizing for speed. */
+ unsigned HOST_WIDE_INT max_copy_size = 256;
+
+ if (optimize_function_for_size_p (cfun))
+ max_copy_size = 128;
+
+ int copy_bits = 256;
+
+ /* Default to 256-bit LDP/STP on large copies, however small copies, no SIMD
+ support or slow 256-bit LDP/STP fall back to 128-bit chunks. */
+ if (size <= 24
+ || !TARGET_SIMD
+ || (aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS))
+ {
+ copy_bits = 128;
+ max_copy_size = max_copy_size / 2;
+ }
+
+ if (size > max_copy_size)
return false;
base = copy_to_mode_reg (Pmode, XEXP (dst, 0));
@@ -21330,15 +21409,8 @@ aarch64_expand_cpymem (rtx *operands)
base = copy_to_mode_reg (Pmode, XEXP (src, 0));
src = adjust_automodify_address (src, VOIDmode, base, 0);
- /* Convert n to bits to make the rest of the code simpler. */
- n = n * BITS_PER_UNIT;
-
- /* Maximum amount to copy in one go. We allow 256-bit chunks based on the
- AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS tuning parameter and TARGET_SIMD. */
- const int copy_limit = ((aarch64_tune_params.extra_tuning_flags
- & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS)
- || !TARGET_SIMD)
- ? GET_MODE_BITSIZE (TImode) : 256;
+ /* Convert size to bits to make the rest of the code simpler. */
+ int n = size * BITS_PER_UNIT;
while (n > 0)
{
@@ -21346,25 +21418,157 @@ aarch64_expand_cpymem (rtx *operands)
or writing. */
opt_scalar_int_mode mode_iter;
FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
- if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_limit))
+ if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_bits))
cur_mode = mode_iter.require ();
gcc_assert (cur_mode != BLKmode);
mode_bits = GET_MODE_BITSIZE (cur_mode).to_constant ();
+
+ /* Prefer Q-register accesses for the last bytes. */
+ if (mode_bits == 128 && copy_bits == 256)
+ cur_mode = V4SImode;
+
aarch64_copy_one_block_and_progress_pointers (&src, &dst, cur_mode);
n -= mode_bits;
+ /* Emit trailing copies using overlapping unaligned accesses - this is
+ smaller and faster. */
+ if (n > 0 && n < copy_bits / 2)
+ {
+ machine_mode next_mode = smallest_mode_for_size (n, MODE_INT);
+ int n_bits = GET_MODE_BITSIZE (next_mode).to_constant ();
+ gcc_assert (n_bits <= mode_bits);
+ src = aarch64_move_pointer (src, (n - n_bits) / BITS_PER_UNIT);
+ dst = aarch64_move_pointer (dst, (n - n_bits) / BITS_PER_UNIT);
+ n = n_bits;
+ }
+ }
+
+ return true;
+}
+
+/* Like aarch64_copy_one_block_and_progress_pointers, except for memset where
+ SRC is a register we have created with the duplicated value to be set. */
+static void
+aarch64_set_one_block_and_progress_pointer (rtx src, rtx *dst,
+ machine_mode mode)
+{
+ /* If we are copying 128bits or 256bits, we can do that straight from
+ the SIMD register we prepared. */
+ if (known_eq (GET_MODE_BITSIZE (mode), 256))
+ {
+ mode = GET_MODE (src);
+ /* "Cast" the *dst to the correct mode. */
+ *dst = adjust_address (*dst, mode, 0);
+ /* Emit the memset. */
+ emit_insn (aarch64_gen_store_pair (mode, *dst, src,
+ aarch64_progress_pointer (*dst), src));
+
+ /* Move the pointers forward. */
+ *dst = aarch64_move_pointer (*dst, 32);
+ return;
+ }
+ if (known_eq (GET_MODE_BITSIZE (mode), 128))
+ {
+ /* "Cast" the *dst to the correct mode. */
+ *dst = adjust_address (*dst, GET_MODE (src), 0);
+ /* Emit the memset. */
+ emit_move_insn (*dst, src);
+ /* Move the pointers forward. */
+ *dst = aarch64_move_pointer (*dst, 16);
+ return;
+ }
+ /* For copying less, we have to extract the right amount from src. */
+ rtx reg = lowpart_subreg (mode, src, GET_MODE (src));
+
+ /* "Cast" the *dst to the correct mode. */
+ *dst = adjust_address (*dst, mode, 0);
+ /* Emit the memset. */
+ emit_move_insn (*dst, reg);
+ /* Move the pointer forward. */
+ *dst = aarch64_progress_pointer (*dst);
+}
+
+/* Expand setmem, as if from a __builtin_memset. Return true if
+ we succeed, otherwise return false. */
+
+bool
+aarch64_expand_setmem (rtx *operands)
+{
+ int n, mode_bits;
+ unsigned HOST_WIDE_INT len;
+ rtx dst = operands[0];
+ rtx val = operands[2], src;
+ rtx base;
+ machine_mode cur_mode = BLKmode, next_mode;
+
+ /* We can't do anything smart if the amount to copy is not constant. */
+ if (!CONST_INT_P (operands[1]))
+ return false;
+
+ bool speed_p = !optimize_function_for_size_p (cfun);
+
+ /* Default the maximum to 256-bytes. */
+ unsigned max_set_size = 256;
+
+ /* In case we are optimizing for size or if the core does not
+ want to use STP Q regs, lower the max_set_size. */
+ max_set_size = (!speed_p
+ || (aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS))
+ ? max_set_size / 2 : max_set_size;
+
+ len = INTVAL (operands[1]);
+
+ /* Upper bound check. */
+ if (len > max_set_size)
+ return false;
+
+ base = copy_to_mode_reg (Pmode, XEXP (dst, 0));
+ dst = adjust_automodify_address (dst, VOIDmode, base, 0);
+
+ /* Prepare the val using a DUP/MOVI v0.16B, val. */
+ src = expand_vector_broadcast (V16QImode, val);
+ src = force_reg (V16QImode, src);
+
+ /* Convert len to bits to make the rest of the code simpler. */
+ n = len * BITS_PER_UNIT;
+
+ /* Maximum amount to copy in one go. We allow 256-bit chunks based on the
+ AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS tuning parameter. setmem expand
+ pattern is only turned on for TARGET_SIMD. */
+ const int copy_limit = (speed_p
+ && (aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS))
+ ? GET_MODE_BITSIZE (TImode) : 256;
+
+ while (n > 0)
+ {
+ /* Find the largest mode in which to do the copy without
+ over writing. */
+ opt_scalar_int_mode mode_iter;
+ FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
+ if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_limit))
+ cur_mode = mode_iter.require ();
+
+ gcc_assert (cur_mode != BLKmode);
+
+ mode_bits = GET_MODE_BITSIZE (cur_mode).to_constant ();
+ aarch64_set_one_block_and_progress_pointer (src, &dst, cur_mode);
+
+ n -= mode_bits;
+
/* Do certain trailing copies as overlapping if it's going to be
cheaper. i.e. less instructions to do so. For instance doing a 15
byte copy it's more efficient to do two overlapping 8 byte copies than
- 8 + 6 + 1. */
- if (n > 0 && n <= 8 * BITS_PER_UNIT)
+ 8 + 4 + 2 + 1. */
+ if (n > 0 && n < copy_limit / 2)
{
next_mode = smallest_mode_for_size (n, MODE_INT);
int n_bits = GET_MODE_BITSIZE (next_mode).to_constant ();
- src = aarch64_move_pointer (src, (n - n_bits) / BITS_PER_UNIT);
+ gcc_assert (n_bits <= mode_bits);
dst = aarch64_move_pointer (dst, (n - n_bits) / BITS_PER_UNIT);
n = n_bits;
}
@@ -21373,6 +21577,7 @@ aarch64_expand_cpymem (rtx *operands)
return true;
}
+
/* Split a DImode store of a CONST_INT SRC to MEM DST as two
SImode stores. Handle the case when the constant has identical
bottom and top halves. This is beneficial when the two stores can be
@@ -22048,20 +22253,20 @@ fusion_load_store (rtx_insn *insn, rtx *base, rtx *offset)
{
fusion = SCHED_FUSION_LD_SIGN_EXTEND;
src = XEXP (src, 0);
- if (GET_CODE (src) != MEM || GET_MODE (src) != SImode)
+ if (!MEM_P (src) || GET_MODE (src) != SImode)
return SCHED_FUSION_NONE;
}
else if (GET_CODE (src) == ZERO_EXTEND)
{
fusion = SCHED_FUSION_LD_ZERO_EXTEND;
src = XEXP (src, 0);
- if (GET_CODE (src) != MEM || GET_MODE (src) != SImode)
+ if (!MEM_P (src) || GET_MODE (src) != SImode)
return SCHED_FUSION_NONE;
}
- if (GET_CODE (src) == MEM && REG_P (dest))
+ if (MEM_P (src) && REG_P (dest))
extract_base_offset_in_addr (src, base, offset);
- else if (GET_CODE (dest) == MEM && (REG_P (src) || src == const0_rtx))
+ else if (MEM_P (dest) && (REG_P (src) || src == const0_rtx))
{
fusion = SCHED_FUSION_ST;
extract_base_offset_in_addr (dest, base, offset);
@@ -22989,19 +23194,38 @@ aarch64_speculation_safe_value (machine_mode mode,
/* Implement TARGET_ESTIMATED_POLY_VALUE.
Look into the tuning structure for an estimate.
- VAL.coeffs[1] is multiplied by the number of VQ chunks over the initial
- Advanced SIMD 128 bits. */
+ KIND specifies the type of requested estimate: min, max or likely.
+ For cores with a known SVE width all three estimates are the same.
+ For generic SVE tuning we want to distinguish the maximum estimate from
+ the minimum and likely ones.
+ The likely estimate is the same as the minimum in that case to give a
+ conservative behavior of auto-vectorizing with SVE when it is a win
+ even for 128-bit SVE.
+ When SVE width information is available VAL.coeffs[1] is multiplied by
+ the number of VQ chunks over the initial Advanced SIMD 128 bits. */
static HOST_WIDE_INT
-aarch64_estimated_poly_value (poly_int64 val)
+aarch64_estimated_poly_value (poly_int64 val,
+ poly_value_estimate_kind kind
+ = POLY_VALUE_LIKELY)
{
enum aarch64_sve_vector_bits_enum width_source
= aarch64_tune_params.sve_width;
- /* If we still don't have an estimate, use the default. */
+ /* If there is no core-specific information then the minimum and likely
+ values are based on 128-bit vectors and the maximum is based on
+ the architectural maximum of 2048 bits. */
if (width_source == SVE_SCALABLE)
- return default_estimated_poly_value (val);
+ switch (kind)
+ {
+ case POLY_VALUE_MIN:
+ case POLY_VALUE_LIKELY:
+ return val.coeffs[0];
+ case POLY_VALUE_MAX:
+ return val.coeffs[0] + val.coeffs[1] * 15;
+ }
+ /* If the core provides width information, use that. */
HOST_WIDE_INT over_128 = width_source - 128;
return val.coeffs[0] + val.coeffs[1] * over_128 / 128;
}
@@ -23044,18 +23268,23 @@ aarch64_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
tree base_type, int num)
{
tree t, ret_type, arg_type;
- unsigned int elt_bits, vec_bits, count;
+ unsigned int elt_bits, count;
+ unsigned HOST_WIDE_INT const_simdlen;
+ poly_uint64 vec_bits;
if (!TARGET_SIMD)
return 0;
- if (clonei->simdlen
- && (clonei->simdlen < 2
- || clonei->simdlen > 1024
- || (clonei->simdlen & (clonei->simdlen - 1)) != 0))
+ /* For now, SVE simdclones won't produce illegal simdlen, So only check
+ const simdlens here. */
+ if (maybe_ne (clonei->simdlen, 0U)
+ && clonei->simdlen.is_constant (&const_simdlen)
+ && (const_simdlen < 2
+ || const_simdlen > 1024
+ || (const_simdlen & (const_simdlen - 1)) != 0))
{
warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
- "unsupported simdlen %d", clonei->simdlen);
+ "unsupported simdlen %wd", const_simdlen);
return 0;
}
@@ -23099,21 +23328,24 @@ aarch64_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
clonei->vecsize_mangle = 'n';
clonei->mask_mode = VOIDmode;
elt_bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type));
- if (clonei->simdlen == 0)
+ if (known_eq (clonei->simdlen, 0U))
{
count = 2;
vec_bits = (num == 0 ? 64 : 128);
- clonei->simdlen = vec_bits / elt_bits;
+ clonei->simdlen = exact_div (vec_bits, elt_bits);
}
else
{
count = 1;
vec_bits = clonei->simdlen * elt_bits;
- if (vec_bits != 64 && vec_bits != 128)
+ /* For now, SVE simdclones won't produce illegal simdlen, So only check
+ const simdlens here. */
+ if (clonei->simdlen.is_constant (&const_simdlen)
+ && maybe_ne (vec_bits, 64U) && maybe_ne (vec_bits, 128U))
{
warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
- "GCC does not currently support simdlen %d for type %qT",
- clonei->simdlen, base_type);
+ "GCC does not currently support simdlen %wd for type %qT",
+ const_simdlen, base_type);
return 0;
}
}
@@ -23251,6 +23483,15 @@ aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
return NULL;
}
+/* Implement TARGET_MEMTAG_CAN_TAG_ADDRESSES. Here we tell the rest of the
+ compiler that we automatically ignore the top byte of our pointers, which
+ allows using -fsanitize=hwaddress. */
+bool
+aarch64_can_tag_addresses ()
+{
+ return !TARGET_ILP32;
+}
+
/* Implement TARGET_ASM_FILE_END for AArch64. This adds the AArch64 GNU NOTE
section at the end if needed. */
#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
@@ -24070,6 +24311,9 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_FNTYPE_ABI
#define TARGET_FNTYPE_ABI aarch64_fntype_abi
+#undef TARGET_MEMTAG_CAN_TAG_ADDRESSES
+#define TARGET_MEMTAG_CAN_TAG_ADDRESSES aarch64_can_tag_addresses
+
#if CHECKING_P
#undef TARGET_RUN_TARGET_SELFTESTS
#define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 00b5f84..74bb3b5 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -224,6 +224,12 @@ extern unsigned aarch64_architecture_version;
/* 64-bit Floating-point Matrix Multiply (F64MM) extensions. */
#define AARCH64_FL_F64MM (1ULL << 38)
+/* Flag Manipulation Instructions (FLAGM) extension. */
+#define AARCH64_FL_FLAGM (1ULL << 39)
+
+/* Pointer Authentication (PAUTH) extension. */
+#define AARCH64_FL_PAUTH (1ULL << 40)
+
/* Has FP and SIMD. */
#define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -238,10 +244,10 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_FL_FOR_ARCH8_2 \
(AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2)
#define AARCH64_FL_FOR_ARCH8_3 \
- (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3)
+ (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3 | AARCH64_FL_PAUTH)
#define AARCH64_FL_FOR_ARCH8_4 \
(AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_V8_4 | AARCH64_FL_F16FML \
- | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4)
+ | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4 | AARCH64_FL_FLAGM)
#define AARCH64_FL_FOR_ARCH8_5 \
(AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_5 \
| AARCH64_FL_SB | AARCH64_FL_SSBS | AARCH64_FL_PREDRES)
@@ -287,6 +293,7 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_ISA_BF16 (aarch64_isa_flags & AARCH64_FL_BF16)
#define AARCH64_ISA_SB (aarch64_isa_flags & AARCH64_FL_SB)
#define AARCH64_ISA_V8_R (aarch64_isa_flags & AARCH64_FL_V8_R)
+#define AARCH64_ISA_PAUTH (aarch64_isa_flags & AARCH64_FL_PAUTH)
/* Crypto is an optional extension to AdvSIMD. */
#define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -375,6 +382,9 @@ extern unsigned aarch64_architecture_version;
#define TARGET_BF16_SIMD (AARCH64_ISA_BF16 && TARGET_SIMD)
#define TARGET_SVE_BF16 (TARGET_SVE && AARCH64_ISA_BF16)
+/* PAUTH instructions are enabled through +pauth. */
+#define TARGET_PAUTH (AARCH64_ISA_PAUTH)
+
/* Make sure this is always defined so we don't have to check for ifdefs
but rather use normal ifs. */
#ifndef TARGET_FIX_ERR_A53_835769_DEFAULT
@@ -1024,16 +1034,19 @@ typedef struct
#define MOVE_RATIO(speed) \
(!STRICT_ALIGNMENT ? 2 : (((speed) ? 15 : AARCH64_CALL_RATIO) / 2))
-/* For CLEAR_RATIO, when optimizing for size, give a better estimate
- of the length of a memset call, but use the default otherwise. */
+/* Like MOVE_RATIO, without -mstrict-align, make decisions in "setmem" when
+ we would use more than 3 scalar instructions.
+ Otherwise follow a sensible default: when optimizing for size, give a better
+ estimate of the length of a memset call, but use the default otherwise. */
#define CLEAR_RATIO(speed) \
- ((speed) ? 15 : AARCH64_CALL_RATIO)
+ (!STRICT_ALIGNMENT ? 4 : (speed) ? 15 : AARCH64_CALL_RATIO)
-/* SET_RATIO is similar to CLEAR_RATIO, but for a non-zero constant, so when
- optimizing for size adjust the ratio to account for the overhead of loading
- the constant. */
+/* SET_RATIO is similar to CLEAR_RATIO, but for a non-zero constant. Without
+ -mstrict-align, make decisions in "setmem". Otherwise follow a sensible
+ default: when optimizing for size adjust the ratio to account for the
+ overhead of loading the constant. */
#define SET_RATIO(speed) \
- ((speed) ? 15 : AARCH64_CALL_RATIO - 2)
+ (!STRICT_ALIGNMENT ? 0 : (speed) ? 15 : AARCH64_CALL_RATIO - 2)
/* Disable auto-increment in move_by_pieces et al. Use of auto-increment is
rarely a good idea in straight-line code since it adds an extra address
@@ -1206,12 +1219,14 @@ extern enum aarch64_code_model aarch64_cmodel;
#define ENDIAN_LANE_N(NUNITS, N) \
(BYTES_BIG_ENDIAN ? NUNITS - 1 - N : N)
-/* Support for a configure-time default CPU, etc. We currently support
- --with-arch and --with-cpu. Both are ignored if either is specified
- explicitly on the command line at run time. */
+/* Support for configure-time --with-arch, --with-cpu and --with-tune.
+ --with-arch and --with-cpu are ignored if either -mcpu or -march is used.
+ --with-tune is ignored if either -mtune or -mcpu is used (but is not
+ affected by -march). */
#define OPTION_DEFAULT_SPECS \
{"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \
- {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" },
+ {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
+ {"tune", "%{!mcpu=*:%{!mtune=*:-mtune=%(VALUE)}}"},
#define MCPU_TO_MARCH_SPEC \
" %{mcpu=*:-march=%:rewrite_mcpu(%{mcpu=*:%*})}"
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 78fe7c43..751ef0d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -111,6 +111,13 @@
;; "FFR token": a fake register used for representing the scheduling
;; restrictions on FFR-related operations.
(FFRT_REGNUM 85)
+ ;; The pair of scratch registers used for stack probing with -fstack-check.
+ ;; Leave R9 alone as a possible choice for the static chain.
+ ;; Note that the use of these registers is mutually exclusive with the use
+ ;; of STACK_CLASH_SVE_CFA_REGNUM, which is for -fstack-clash-protection
+ ;; rather than -fstack-check.
+ (PROBE_STACK_FIRST_REGNUM 10)
+ (PROBE_STACK_SECOND_REGNUM 11)
;; Scratch register used by stack clash protection to calculate
;; SVE CFA offsets during probing.
(STACK_CLASH_SVE_CFA_REGNUM 11)
@@ -866,7 +873,7 @@
{
const char *ret = NULL;
if (aarch64_return_address_signing_enabled ()
- && TARGET_ARMV8_3
+ && (TARGET_PAUTH)
&& !crtl->calls_eh_return)
{
if (aarch64_ra_sign_key == AARCH64_KEY_B)
@@ -1564,6 +1571,24 @@
}
)
+;; 0 is dst
+;; 1 is val
+;; 2 is size of copy in bytes
+;; 3 is alignment
+
+(define_expand "setmemdi"
+ [(set (match_operand:BLK 0 "memory_operand") ;; Dest
+ (match_operand:QI 2 "nonmemory_operand")) ;; Value
+ (use (match_operand:DI 1 "immediate_operand")) ;; Length
+ (match_operand 3 "immediate_operand")] ;; Align
+ "TARGET_SIMD"
+{
+ if (aarch64_expand_setmem (operands))
+ DONE;
+
+ FAIL;
+})
+
;; Operands 1 and 3 are tied together by the final condition; so we allow
;; fairly lax checking on the second memory operation.
(define_insn "load_pair_sw_<SX:mode><SX2:mode>"
@@ -2449,7 +2474,7 @@
(match_operand:GPI 3 "register_operand" "r")))]
""
"add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
- [(set_attr "type" "alu_shift_imm")]
+ [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
)
;; zero_extend version of above
@@ -2461,7 +2486,7 @@
(match_operand:SI 3 "register_operand" "r"))))]
""
"add\\t%w0, %w3, %w1, <shift> %2"
- [(set_attr "type" "alu_shift_imm")]
+ [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
)
(define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
@@ -3096,7 +3121,7 @@
(match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
""
"sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
- [(set_attr "type" "alu_shift_imm")]
+ [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
)
;; zero_extend version of above
@@ -3109,7 +3134,7 @@
(match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
""
"sub\\t%w0, %w3, %w1, <shift> %2"
- [(set_attr "type" "alu_shift_imm")]
+ [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
)
(define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
@@ -3510,7 +3535,7 @@
(match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
""
"neg\\t%<w>0, %<w>1, <shift> %2"
- [(set_attr "type" "alu_shift_imm")]
+ [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
)
;; zero_extend version of above
@@ -3522,7 +3547,7 @@
(match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
""
"neg\\t%w0, %w1, <shift> %2"
- [(set_attr "type" "alu_shift_imm")]
+ [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
)
(define_insn "mul<mode>3"
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 5170361..ded13a5 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -64,11 +64,11 @@ EnumValue
Enum(cmodel) String(large) Value(AARCH64_CMODEL_LARGE)
mbig-endian
-Target Report RejectNegative Mask(BIG_END)
+Target RejectNegative Mask(BIG_END)
Assume target CPU is configured as big endian.
mgeneral-regs-only
-Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Save
+Target RejectNegative Mask(GENERAL_REGS_ONLY) Save
Generate code which uses only the general registers.
mharden-sls=
@@ -76,15 +76,15 @@ Target RejectNegative Joined Var(aarch64_harden_sls_string)
Generate code to mitigate against straight line speculation.
mfix-cortex-a53-835769
-Target Report Var(aarch64_fix_a53_err835769) Init(2) Save
+Target Var(aarch64_fix_a53_err835769) Init(2) Save
Workaround for ARM Cortex-A53 Erratum number 835769.
mfix-cortex-a53-843419
-Target Report Var(aarch64_fix_a53_err843419) Init(2) Save
+Target Var(aarch64_fix_a53_err843419) Init(2) Save
Workaround for ARM Cortex-A53 Erratum number 843419.
mlittle-endian
-Target Report RejectNegative InverseMask(BIG_END)
+Target RejectNegative InverseMask(BIG_END)
Assume target CPU is configured as little endian.
mcmodel=
@@ -92,11 +92,11 @@ Target RejectNegative Joined Enum(cmodel) Var(aarch64_cmodel_var) Init(AARCH64_C
Specify the code model.
mstrict-align
-Target Report Mask(STRICT_ALIGN) Save
+Target Mask(STRICT_ALIGN) Save
Don't assume that unaligned accesses are handled by the system.
momit-leaf-frame-pointer
-Target Report Var(flag_omit_leaf_frame_pointer) Init(2) Save
+Target Var(flag_omit_leaf_frame_pointer) Init(2) Save
Omit the frame pointer in leaf functions.
mtls-dialect=
@@ -153,7 +153,7 @@ EnumValue
Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64)
mpc-relative-literal-loads
-Target Report Save Var(pcrelative_literal_loads) Init(2) Save
+Target Save Var(pcrelative_literal_loads) Init(2) Save
PC relative literal loads.
mbranch-protection=
@@ -260,7 +260,7 @@ TargetVariable
long aarch64_stack_protector_guard_offset = 0
moutline-atomics
-Target Report Var(aarch64_flag_outline_atomics) Init(2) Save
+Target Var(aarch64_flag_outline_atomics) Init(2) Save
Generate local calls to out-of-line atomic operations.
-param=aarch64-sve-compare-costs=
@@ -275,3 +275,5 @@ The number of Newton iterations for calculating the reciprocal for float type.
Target Joined UInteger Var(aarch64_double_recp_precision) Init(2) IntegerRange(1, 5) Param
The number of Newton iterations for calculating the reciprocal for double type. The precision of division is proportional to this param when division approximation is enabled. The default value is 2.
+-param=aarch64-autovec-preference=
+Target Joined UInteger Var(aarch64_autovec_preference) Init(0) IntegerRange(0, 4) Param
diff --git a/gcc/config/aarch64/arm_bf16.h b/gcc/config/aarch64/arm_bf16.h
index 984875d..8816154 100644
--- a/gcc/config/aarch64/arm_bf16.h
+++ b/gcc/config/aarch64/arm_bf16.h
@@ -40,6 +40,13 @@ vcvth_bf16_f32 (float32_t __a)
return __builtin_aarch64_bfcvtbf (__a);
}
+__extension__ extern __inline float32_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcvtah_f32_bf16 (bfloat16_t __a)
+{
+ return __builtin_aarch64_bfcvtsf (__a);
+}
+
#pragma GCC pop_options
#endif
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 85c0d62..d79c1a2 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -9993,275 +9993,131 @@ vqrdmulhq_n_s32 (int32x4_t __a, int32_t __b)
return __result;
}
-#define vqrshrn_high_n_s16(a, b, c) \
- __extension__ \
- ({ \
- int16x8_t b_ = (b); \
- int8x8_t a_ = (a); \
- int8x16_t result = vcombine_s8 \
- (a_, vcreate_s8 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqrshrn2 %0.16b, %1.8h, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline int8x16_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrn_high_n_s16 (int8x8_t __a, int16x8_t __b, const int __c)
+{
+ return __builtin_aarch64_sqrshrn2_nv8hi (__a, __b, __c);
+}
-#define vqrshrn_high_n_s32(a, b, c) \
- __extension__ \
- ({ \
- int32x4_t b_ = (b); \
- int16x4_t a_ = (a); \
- int16x8_t result = vcombine_s16 \
- (a_, vcreate_s16 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqrshrn2 %0.8h, %1.4s, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline int16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrn_high_n_s32 (int16x4_t __a, int32x4_t __b, const int __c)
+{
+ return __builtin_aarch64_sqrshrn2_nv4si (__a, __b, __c);
+}
-#define vqrshrn_high_n_s64(a, b, c) \
- __extension__ \
- ({ \
- int64x2_t b_ = (b); \
- int32x2_t a_ = (a); \
- int32x4_t result = vcombine_s32 \
- (a_, vcreate_s32 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqrshrn2 %0.4s, %1.2d, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline int32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrn_high_n_s64 (int32x2_t __a, int64x2_t __b, const int __c)
+{
+ return __builtin_aarch64_sqrshrn2_nv2di (__a, __b, __c);
+}
-#define vqrshrn_high_n_u16(a, b, c) \
- __extension__ \
- ({ \
- uint16x8_t b_ = (b); \
- uint8x8_t a_ = (a); \
- uint8x16_t result = vcombine_u8 \
- (a_, vcreate_u8 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("uqrshrn2 %0.16b, %1.8h, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint8x16_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrn_high_n_u16 (uint8x8_t __a, uint16x8_t __b, const int __c)
+{
+ return __builtin_aarch64_uqrshrn2_nv8hi_uuus (__a, __b, __c);
+}
-#define vqrshrn_high_n_u32(a, b, c) \
- __extension__ \
- ({ \
- uint32x4_t b_ = (b); \
- uint16x4_t a_ = (a); \
- uint16x8_t result = vcombine_u16 \
- (a_, vcreate_u16 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("uqrshrn2 %0.8h, %1.4s, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrn_high_n_u32 (uint16x4_t __a, uint32x4_t __b, const int __c)
+{
+ return __builtin_aarch64_uqrshrn2_nv4si_uuus (__a, __b, __c);
+}
-#define vqrshrn_high_n_u64(a, b, c) \
- __extension__ \
- ({ \
- uint64x2_t b_ = (b); \
- uint32x2_t a_ = (a); \
- uint32x4_t result = vcombine_u32 \
- (a_, vcreate_u32 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("uqrshrn2 %0.4s, %1.2d, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrn_high_n_u64 (uint32x2_t __a, uint64x2_t __b, const int __c)
+{
+ return __builtin_aarch64_uqrshrn2_nv2di_uuus (__a, __b, __c);
+}
-#define vqrshrun_high_n_s16(a, b, c) \
- __extension__ \
- ({ \
- int16x8_t b_ = (b); \
- uint8x8_t a_ = (a); \
- uint8x16_t result = vcombine_u8 \
- (a_, vcreate_u8 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqrshrun2 %0.16b, %1.8h, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint8x16_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrun_high_n_s16 (uint8x8_t __a, int16x8_t __b, const int __c)
+{
+ return __builtin_aarch64_sqrshrun2_nv8hi_uuss (__a, __b, __c);
+}
-#define vqrshrun_high_n_s32(a, b, c) \
- __extension__ \
- ({ \
- int32x4_t b_ = (b); \
- uint16x4_t a_ = (a); \
- uint16x8_t result = vcombine_u16 \
- (a_, vcreate_u16 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqrshrun2 %0.8h, %1.4s, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrun_high_n_s32 (uint16x4_t __a, int32x4_t __b, const int __c)
+{
+ return __builtin_aarch64_sqrshrun2_nv4si_uuss (__a, __b, __c);
+}
-#define vqrshrun_high_n_s64(a, b, c) \
- __extension__ \
- ({ \
- int64x2_t b_ = (b); \
- uint32x2_t a_ = (a); \
- uint32x4_t result = vcombine_u32 \
- (a_, vcreate_u32 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqrshrun2 %0.4s, %1.2d, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqrshrun_high_n_s64 (uint32x2_t __a, int64x2_t __b, const int __c)
+{
+ return __builtin_aarch64_sqrshrun2_nv2di_uuss (__a, __b, __c);
+}
-#define vqshrn_high_n_s16(a, b, c) \
- __extension__ \
- ({ \
- int16x8_t b_ = (b); \
- int8x8_t a_ = (a); \
- int8x16_t result = vcombine_s8 \
- (a_, vcreate_s8 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqshrn2 %0.16b, %1.8h, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline int8x16_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrn_high_n_s16 (int8x8_t __a, int16x8_t __b, const int __c)
+{
+ return __builtin_aarch64_sqshrn2_nv8hi (__a, __b, __c);
+}
-#define vqshrn_high_n_s32(a, b, c) \
- __extension__ \
- ({ \
- int32x4_t b_ = (b); \
- int16x4_t a_ = (a); \
- int16x8_t result = vcombine_s16 \
- (a_, vcreate_s16 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqshrn2 %0.8h, %1.4s, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline int16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrn_high_n_s32 (int16x4_t __a, int32x4_t __b, const int __c)
+{
+ return __builtin_aarch64_sqshrn2_nv4si (__a, __b, __c);
+}
-#define vqshrn_high_n_s64(a, b, c) \
- __extension__ \
- ({ \
- int64x2_t b_ = (b); \
- int32x2_t a_ = (a); \
- int32x4_t result = vcombine_s32 \
- (a_, vcreate_s32 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqshrn2 %0.4s, %1.2d, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline int32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrn_high_n_s64 (int32x2_t __a, int64x2_t __b, const int __c)
+{
+ return __builtin_aarch64_sqshrn2_nv2di (__a, __b, __c);
+}
-#define vqshrn_high_n_u16(a, b, c) \
- __extension__ \
- ({ \
- uint16x8_t b_ = (b); \
- uint8x8_t a_ = (a); \
- uint8x16_t result = vcombine_u8 \
- (a_, vcreate_u8 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("uqshrn2 %0.16b, %1.8h, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint8x16_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrn_high_n_u16 (uint8x8_t __a, uint16x8_t __b, const int __c)
+{
+ return __builtin_aarch64_uqshrn2_nv8hi_uuus (__a, __b, __c);
+}
-#define vqshrn_high_n_u32(a, b, c) \
- __extension__ \
- ({ \
- uint32x4_t b_ = (b); \
- uint16x4_t a_ = (a); \
- uint16x8_t result = vcombine_u16 \
- (a_, vcreate_u16 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("uqshrn2 %0.8h, %1.4s, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrn_high_n_u32 (uint16x4_t __a, uint32x4_t __b, const int __c)
+{
+ return __builtin_aarch64_uqshrn2_nv4si_uuus (__a, __b, __c);
+}
-#define vqshrn_high_n_u64(a, b, c) \
- __extension__ \
- ({ \
- uint64x2_t b_ = (b); \
- uint32x2_t a_ = (a); \
- uint32x4_t result = vcombine_u32 \
- (a_, vcreate_u32 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("uqshrn2 %0.4s, %1.2d, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrn_high_n_u64 (uint32x2_t __a, uint64x2_t __b, const int __c)
+{
+ return __builtin_aarch64_uqshrn2_nv2di_uuus (__a, __b, __c);
+}
-#define vqshrun_high_n_s16(a, b, c) \
- __extension__ \
- ({ \
- int16x8_t b_ = (b); \
- uint8x8_t a_ = (a); \
- uint8x16_t result = vcombine_u8 \
- (a_, vcreate_u8 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqshrun2 %0.16b, %1.8h, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint8x16_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrun_high_n_s16 (uint8x8_t __a, int16x8_t __b, const int __c)
+{
+ return __builtin_aarch64_sqshrun2_nv8hi_uuss (__a, __b, __c);
+}
-#define vqshrun_high_n_s32(a, b, c) \
- __extension__ \
- ({ \
- int32x4_t b_ = (b); \
- uint16x4_t a_ = (a); \
- uint16x8_t result = vcombine_u16 \
- (a_, vcreate_u16 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqshrun2 %0.8h, %1.4s, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrun_high_n_s32 (uint16x4_t __a, int32x4_t __b, const int __c)
+{
+ return __builtin_aarch64_sqshrun2_nv4si_uuss (__a, __b, __c);
+}
-#define vqshrun_high_n_s64(a, b, c) \
- __extension__ \
- ({ \
- int64x2_t b_ = (b); \
- uint32x2_t a_ = (a); \
- uint32x4_t result = vcombine_u32 \
- (a_, vcreate_u32 \
- (__AARCH64_UINT64_C (0x0))); \
- __asm__ ("sqshrun2 %0.4s, %1.2d, #%2" \
- : "+w"(result) \
- : "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
+__extension__ extern __inline uint32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vqshrun_high_n_s64 (uint32x2_t __a, int64x2_t __b, const int __c)
+{
+ return __builtin_aarch64_sqshrun2_nv2di_uuss (__a, __b, __c);
+}
#define vrshrn_high_n_s16(a, b, c) \
__extension__ \
@@ -10926,8 +10782,7 @@ __ST2_LANE_FUNC (uint32x2x2_t, uint32x4x2_t, uint32_t, v2si, v4si, si, u32,
__ST2_LANE_FUNC (uint64x1x2_t, uint64x2x2_t, uint64_t, di, v2di, di, u64,
int64x2_t)
-#undef __ST2_LANE_FUNC
-#define __ST2_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \
+#define __ST2Q_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \
__extension__ extern __inline void \
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \
vst2q_lane_ ## funcsuffix (ptrtype *__ptr, \
@@ -10939,20 +10794,20 @@ vst2q_lane_ ## funcsuffix (ptrtype *__ptr, \
__ptr, __temp.__o, __c); \
}
-__ST2_LANE_FUNC (float16x8x2_t, float16_t, v8hf, hf, f16)
-__ST2_LANE_FUNC (float32x4x2_t, float32_t, v4sf, sf, f32)
-__ST2_LANE_FUNC (float64x2x2_t, float64_t, v2df, df, f64)
-__ST2_LANE_FUNC (poly8x16x2_t, poly8_t, v16qi, qi, p8)
-__ST2_LANE_FUNC (poly16x8x2_t, poly16_t, v8hi, hi, p16)
-__ST2_LANE_FUNC (poly64x2x2_t, poly64_t, v2di, di, p64)
-__ST2_LANE_FUNC (int8x16x2_t, int8_t, v16qi, qi, s8)
-__ST2_LANE_FUNC (int16x8x2_t, int16_t, v8hi, hi, s16)
-__ST2_LANE_FUNC (int32x4x2_t, int32_t, v4si, si, s32)
-__ST2_LANE_FUNC (int64x2x2_t, int64_t, v2di, di, s64)
-__ST2_LANE_FUNC (uint8x16x2_t, uint8_t, v16qi, qi, u8)
-__ST2_LANE_FUNC (uint16x8x2_t, uint16_t, v8hi, hi, u16)
-__ST2_LANE_FUNC (uint32x4x2_t, uint32_t, v4si, si, u32)
-__ST2_LANE_FUNC (uint64x2x2_t, uint64_t, v2di, di, u64)
+__ST2Q_LANE_FUNC (float16x8x2_t, float16_t, v8hf, hf, f16)
+__ST2Q_LANE_FUNC (float32x4x2_t, float32_t, v4sf, sf, f32)
+__ST2Q_LANE_FUNC (float64x2x2_t, float64_t, v2df, df, f64)
+__ST2Q_LANE_FUNC (poly8x16x2_t, poly8_t, v16qi, qi, p8)
+__ST2Q_LANE_FUNC (poly16x8x2_t, poly16_t, v8hi, hi, p16)
+__ST2Q_LANE_FUNC (poly64x2x2_t, poly64_t, v2di, di, p64)
+__ST2Q_LANE_FUNC (int8x16x2_t, int8_t, v16qi, qi, s8)
+__ST2Q_LANE_FUNC (int16x8x2_t, int16_t, v8hi, hi, s16)
+__ST2Q_LANE_FUNC (int32x4x2_t, int32_t, v4si, si, s32)
+__ST2Q_LANE_FUNC (int64x2x2_t, int64_t, v2di, di, s64)
+__ST2Q_LANE_FUNC (uint8x16x2_t, uint8_t, v16qi, qi, u8)
+__ST2Q_LANE_FUNC (uint16x8x2_t, uint16_t, v8hi, hi, u16)
+__ST2Q_LANE_FUNC (uint32x4x2_t, uint32_t, v4si, si, u32)
+__ST2Q_LANE_FUNC (uint64x2x2_t, uint64_t, v2di, di, u64)
#define __ST3_LANE_FUNC(intype, largetype, ptrtype, mode, \
qmode, ptr_mode, funcsuffix, signedtype) \
@@ -11011,8 +10866,7 @@ __ST3_LANE_FUNC (uint32x2x3_t, uint32x4x3_t, uint32_t, v2si, v4si, si, u32,
__ST3_LANE_FUNC (uint64x1x3_t, uint64x2x3_t, uint64_t, di, v2di, di, u64,
int64x2_t)
-#undef __ST3_LANE_FUNC
-#define __ST3_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \
+#define __ST3Q_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \
__extension__ extern __inline void \
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \
vst3q_lane_ ## funcsuffix (ptrtype *__ptr, \
@@ -11024,20 +10878,20 @@ vst3q_lane_ ## funcsuffix (ptrtype *__ptr, \
__ptr, __temp.__o, __c); \
}
-__ST3_LANE_FUNC (float16x8x3_t, float16_t, v8hf, hf, f16)
-__ST3_LANE_FUNC (float32x4x3_t, float32_t, v4sf, sf, f32)
-__ST3_LANE_FUNC (float64x2x3_t, float64_t, v2df, df, f64)
-__ST3_LANE_FUNC (poly8x16x3_t, poly8_t, v16qi, qi, p8)
-__ST3_LANE_FUNC (poly16x8x3_t, poly16_t, v8hi, hi, p16)
-__ST3_LANE_FUNC (poly64x2x3_t, poly64_t, v2di, di, p64)
-__ST3_LANE_FUNC (int8x16x3_t, int8_t, v16qi, qi, s8)
-__ST3_LANE_FUNC (int16x8x3_t, int16_t, v8hi, hi, s16)
-__ST3_LANE_FUNC (int32x4x3_t, int32_t, v4si, si, s32)
-__ST3_LANE_FUNC (int64x2x3_t, int64_t, v2di, di, s64)
-__ST3_LANE_FUNC (uint8x16x3_t, uint8_t, v16qi, qi, u8)
-__ST3_LANE_FUNC (uint16x8x3_t, uint16_t, v8hi, hi, u16)
-__ST3_LANE_FUNC (uint32x4x3_t, uint32_t, v4si, si, u32)
-__ST3_LANE_FUNC (uint64x2x3_t, uint64_t, v2di, di, u64)
+__ST3Q_LANE_FUNC (float16x8x3_t, float16_t, v8hf, hf, f16)
+__ST3Q_LANE_FUNC (float32x4x3_t, float32_t, v4sf, sf, f32)
+__ST3Q_LANE_FUNC (float64x2x3_t, float64_t, v2df, df, f64)
+__ST3Q_LANE_FUNC (poly8x16x3_t, poly8_t, v16qi, qi, p8)
+__ST3Q_LANE_FUNC (poly16x8x3_t, poly16_t, v8hi, hi, p16)
+__ST3Q_LANE_FUNC (poly64x2x3_t, poly64_t, v2di, di, p64)
+__ST3Q_LANE_FUNC (int8x16x3_t, int8_t, v16qi, qi, s8)
+__ST3Q_LANE_FUNC (int16x8x3_t, int16_t, v8hi, hi, s16)
+__ST3Q_LANE_FUNC (int32x4x3_t, int32_t, v4si, si, s32)
+__ST3Q_LANE_FUNC (int64x2x3_t, int64_t, v2di, di, s64)
+__ST3Q_LANE_FUNC (uint8x16x3_t, uint8_t, v16qi, qi, u8)
+__ST3Q_LANE_FUNC (uint16x8x3_t, uint16_t, v8hi, hi, u16)
+__ST3Q_LANE_FUNC (uint32x4x3_t, uint32_t, v4si, si, u32)
+__ST3Q_LANE_FUNC (uint64x2x3_t, uint64_t, v2di, di, u64)
#define __ST4_LANE_FUNC(intype, largetype, ptrtype, mode, \
qmode, ptr_mode, funcsuffix, signedtype) \
@@ -11101,8 +10955,7 @@ __ST4_LANE_FUNC (uint32x2x4_t, uint32x4x4_t, uint32_t, v2si, v4si, si, u32,
__ST4_LANE_FUNC (uint64x1x4_t, uint64x2x4_t, uint64_t, di, v2di, di, u64,
int64x2_t)
-#undef __ST4_LANE_FUNC
-#define __ST4_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \
+#define __ST4Q_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \
__extension__ extern __inline void \
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \
vst4q_lane_ ## funcsuffix (ptrtype *__ptr, \
@@ -11114,20 +10967,20 @@ vst4q_lane_ ## funcsuffix (ptrtype *__ptr, \
__ptr, __temp.__o, __c); \
}
-__ST4_LANE_FUNC (float16x8x4_t, float16_t, v8hf, hf, f16)
-__ST4_LANE_FUNC (float32x4x4_t, float32_t, v4sf, sf, f32)
-__ST4_LANE_FUNC (float64x2x4_t, float64_t, v2df, df, f64)
-__ST4_LANE_FUNC (poly8x16x4_t, poly8_t, v16qi, qi, p8)
-__ST4_LANE_FUNC (poly16x8x4_t, poly16_t, v8hi, hi, p16)
-__ST4_LANE_FUNC (poly64x2x4_t, poly64_t, v2di, di, p64)
-__ST4_LANE_FUNC (int8x16x4_t, int8_t, v16qi, qi, s8)
-__ST4_LANE_FUNC (int16x8x4_t, int16_t, v8hi, hi, s16)
-__ST4_LANE_FUNC (int32x4x4_t, int32_t, v4si, si, s32)
-__ST4_LANE_FUNC (int64x2x4_t, int64_t, v2di, di, s64)
-__ST4_LANE_FUNC (uint8x16x4_t, uint8_t, v16qi, qi, u8)
-__ST4_LANE_FUNC (uint16x8x4_t, uint16_t, v8hi, hi, u16)
-__ST4_LANE_FUNC (uint32x4x4_t, uint32_t, v4si, si, u32)
-__ST4_LANE_FUNC (uint64x2x4_t, uint64_t, v2di, di, u64)
+__ST4Q_LANE_FUNC (float16x8x4_t, float16_t, v8hf, hf, f16)
+__ST4Q_LANE_FUNC (float32x4x4_t, float32_t, v4sf, sf, f32)
+__ST4Q_LANE_FUNC (float64x2x4_t, float64_t, v2df, df, f64)
+__ST4Q_LANE_FUNC (poly8x16x4_t, poly8_t, v16qi, qi, p8)
+__ST4Q_LANE_FUNC (poly16x8x4_t, poly16_t, v8hi, hi, p16)
+__ST4Q_LANE_FUNC (poly64x2x4_t, poly64_t, v2di, di, p64)
+__ST4Q_LANE_FUNC (int8x16x4_t, int8_t, v16qi, qi, s8)
+__ST4Q_LANE_FUNC (int16x8x4_t, int16_t, v8hi, hi, s16)
+__ST4Q_LANE_FUNC (int32x4x4_t, int32_t, v4si, si, s32)
+__ST4Q_LANE_FUNC (int64x2x4_t, int64_t, v2di, di, s64)
+__ST4Q_LANE_FUNC (uint8x16x4_t, uint8_t, v16qi, qi, u8)
+__ST4Q_LANE_FUNC (uint16x8x4_t, uint16_t, v8hi, hi, u16)
+__ST4Q_LANE_FUNC (uint32x4x4_t, uint32_t, v4si, si, u32)
+__ST4Q_LANE_FUNC (uint64x2x4_t, uint64_t, v2di, di, u64)
__extension__ extern __inline int64_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
@@ -20848,11 +20701,9 @@ __LD2_LANE_FUNC (uint32x2x2_t, uint32x2_t, uint32x4x2_t, uint32_t, v2si, v4si, s
__LD2_LANE_FUNC (uint64x1x2_t, uint64x1_t, uint64x2x2_t, uint64_t, di, v2di, di,
u64, int64x2_t)
-#undef __LD2_LANE_FUNC
-
/* vld2q_lane */
-#define __LD2_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \
+#define __LD2Q_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \
__extension__ extern __inline intype \
__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \
vld2q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \
@@ -20868,22 +20719,20 @@ vld2q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \
return ret; \
}
-__LD2_LANE_FUNC (float16x8x2_t, float16x8_t, float16_t, v8hf, hf, f16)
-__LD2_LANE_FUNC (float32x4x2_t, float32x4_t, float32_t, v4sf, sf, f32)
-__LD2_LANE_FUNC (float64x2x2_t, float64x2_t, float64_t, v2df, df, f64)
-__LD2_LANE_FUNC (poly8x16x2_t, poly8x16_t, poly8_t, v16qi, qi, p8)
-__LD2_LANE_FUNC (poly16x8x2_t, poly16x8_t, poly16_t, v8hi, hi, p16)
-__LD2_LANE_FUNC (poly64x2x2_t, poly64x2_t, poly64_t, v2di, di, p64)
-__LD2_LANE_FUNC (int8x16x2_t, int8x16_t, int8_t, v16qi, qi, s8)
-__LD2_LANE_FUNC (int16x8x2_t, int16x8_t, int16_t, v8hi, hi, s16)
-__LD2_LANE_FUNC (int32x4x2_t, int32x4_t, int32_t, v4si, si, s32)
-__LD2_LANE_FUNC (int64x2x2_t, int64x2_t, int64_t, v2di, di, s64)
-__LD2_LANE_FUNC (uint8x16x2_t, uint8x16_t, uint8_t, v16qi, qi, u8)
-__LD2_LANE_FUNC (uint16x8x2_t, uint16x8_t, uint16_t, v8hi, hi, u16)
-__LD2_LANE_FUNC (uint32x4x2_t, uint32x4_t, uint32_t, v4si, si, u32)
-__LD2_LANE_FUNC (uint64x2x2_t, uint64x2_t, uint64_t, v2di, di, u64)
-
-#undef __LD2_LANE_FUNC
+__LD2Q_LANE_FUNC (float16x8x2_t, float16x8_t, float16_t, v8hf, hf, f16)
+__LD2Q_LANE_FUNC (float32x4x2_t, float32x4_t, float32_t, v4sf, sf, f32)
+__LD2Q_LANE_FUNC (float64x2x2_t, float64x2_t, float64_t, v2df, df, f64)
+__LD2Q_LANE_FUNC (poly8x16x2_t, poly8x16_t, poly8_t, v16qi, qi, p8)
+__LD2Q_LANE_FUNC (poly16x8x2_t, poly16x8_t, poly16_t, v8hi, hi, p16)
+__LD2Q_LANE_FUNC (poly64x2x2_t, poly64x2_t, poly64_t, v2di, di, p64)
+__LD2Q_LANE_FUNC (int8x16x2_t, int8x16_t, int8_t, v16qi, qi, s8)
+__LD2Q_LANE_FUNC (int16x8x2_t, int16x8_t, int16_t, v8hi, hi, s16)
+__LD2Q_LANE_FUNC (int32x4x2_t, int32x4_t, int32_t, v4si, si, s32)
+__LD2Q_LANE_FUNC (int64x2x2_t, int64x2_t, int64_t, v2di, di, s64)
+__LD2Q_LANE_FUNC (uint8x16x2_t, uint8x16_t, uint8_t, v16qi, qi, u8)
+__LD2Q_LANE_FUNC (uint16x8x2_t, uint16x8_t, uint16_t, v8hi, hi, u16)
+__LD2Q_LANE_FUNC (uint32x4x2_t, uint32x4_t, uint32_t, v4si, si, u32)
+__LD2Q_LANE_FUNC (uint64x2x2_t, uint64x2_t, uint64_t, v2di, di, u64)
/* vld3_lane */
@@ -20947,11 +20796,9 @@ __LD3_LANE_FUNC (uint32x2x3_t, uint32x2_t, uint32x4x3_t, uint32_t, v2si, v4si, s
__LD3_LANE_FUNC (uint64x1x3_t, uint64x1_t, uint64x2x3_t, uint64_t, di, v2di, di,
u64, int64x2_t)
-#undef __LD3_LANE_FUNC
-
/* vld3q_lane */
-#define __LD3_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \
+#define __LD3Q_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \
__extension__ extern __inline intype \
__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \
vld3q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \
@@ -20969,22 +20816,20 @@ vld3q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \
return ret; \
}
-__LD3_LANE_FUNC (float16x8x3_t, float16x8_t, float16_t, v8hf, hf, f16)
-__LD3_LANE_FUNC (float32x4x3_t, float32x4_t, float32_t, v4sf, sf, f32)
-__LD3_LANE_FUNC (float64x2x3_t, float64x2_t, float64_t, v2df, df, f64)
-__LD3_LANE_FUNC (poly8x16x3_t, poly8x16_t, poly8_t, v16qi, qi, p8)
-__LD3_LANE_FUNC (poly16x8x3_t, poly16x8_t, poly16_t, v8hi, hi, p16)
-__LD3_LANE_FUNC (poly64x2x3_t, poly64x2_t, poly64_t, v2di, di, p64)
-__LD3_LANE_FUNC (int8x16x3_t, int8x16_t, int8_t, v16qi, qi, s8)
-__LD3_LANE_FUNC (int16x8x3_t, int16x8_t, int16_t, v8hi, hi, s16)
-__LD3_LANE_FUNC (int32x4x3_t, int32x4_t, int32_t, v4si, si, s32)
-__LD3_LANE_FUNC (int64x2x3_t, int64x2_t, int64_t, v2di, di, s64)
-__LD3_LANE_FUNC (uint8x16x3_t, uint8x16_t, uint8_t, v16qi, qi, u8)
-__LD3_LANE_FUNC (uint16x8x3_t, uint16x8_t, uint16_t, v8hi, hi, u16)
-__LD3_LANE_FUNC (uint32x4x3_t, uint32x4_t, uint32_t, v4si, si, u32)
-__LD3_LANE_FUNC (uint64x2x3_t, uint64x2_t, uint64_t, v2di, di, u64)
-
-#undef __LD3_LANE_FUNC
+__LD3Q_LANE_FUNC (float16x8x3_t, float16x8_t, float16_t, v8hf, hf, f16)
+__LD3Q_LANE_FUNC (float32x4x3_t, float32x4_t, float32_t, v4sf, sf, f32)
+__LD3Q_LANE_FUNC (float64x2x3_t, float64x2_t, float64_t, v2df, df, f64)
+__LD3Q_LANE_FUNC (poly8x16x3_t, poly8x16_t, poly8_t, v16qi, qi, p8)
+__LD3Q_LANE_FUNC (poly16x8x3_t, poly16x8_t, poly16_t, v8hi, hi, p16)
+__LD3Q_LANE_FUNC (poly64x2x3_t, poly64x2_t, poly64_t, v2di, di, p64)
+__LD3Q_LANE_FUNC (int8x16x3_t, int8x16_t, int8_t, v16qi, qi, s8)
+__LD3Q_LANE_FUNC (int16x8x3_t, int16x8_t, int16_t, v8hi, hi, s16)
+__LD3Q_LANE_FUNC (int32x4x3_t, int32x4_t, int32_t, v4si, si, s32)
+__LD3Q_LANE_FUNC (int64x2x3_t, int64x2_t, int64_t, v2di, di, s64)
+__LD3Q_LANE_FUNC (uint8x16x3_t, uint8x16_t, uint8_t, v16qi, qi, u8)
+__LD3Q_LANE_FUNC (uint16x8x3_t, uint16x8_t, uint16_t, v8hi, hi, u16)
+__LD3Q_LANE_FUNC (uint32x4x3_t, uint32x4_t, uint32_t, v4si, si, u32)
+__LD3Q_LANE_FUNC (uint64x2x3_t, uint64x2_t, uint64_t, v2di, di, u64)
/* vld4_lane */
@@ -21056,11 +20901,9 @@ __LD4_LANE_FUNC (uint32x2x4_t, uint32x2_t, uint32x4x4_t, uint32_t, v2si, v4si, s
__LD4_LANE_FUNC (uint64x1x4_t, uint64x1_t, uint64x2x4_t, uint64_t, di, v2di, di,
u64, int64x2_t)
-#undef __LD4_LANE_FUNC
-
/* vld4q_lane */
-#define __LD4_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \
+#define __LD4Q_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \
__extension__ extern __inline intype \
__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \
vld4q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \
@@ -21080,22 +20923,20 @@ vld4q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \
return ret; \
}
-__LD4_LANE_FUNC (float16x8x4_t, float16x8_t, float16_t, v8hf, hf, f16)
-__LD4_LANE_FUNC (float32x4x4_t, float32x4_t, float32_t, v4sf, sf, f32)
-__LD4_LANE_FUNC (float64x2x4_t, float64x2_t, float64_t, v2df, df, f64)
-__LD4_LANE_FUNC (poly8x16x4_t, poly8x16_t, poly8_t, v16qi, qi, p8)
-__LD4_LANE_FUNC (poly16x8x4_t, poly16x8_t, poly16_t, v8hi, hi, p16)
-__LD4_LANE_FUNC (poly64x2x4_t, poly64x2_t, poly64_t, v2di, di, p64)
-__LD4_LANE_FUNC (int8x16x4_t, int8x16_t, int8_t, v16qi, qi, s8)
-__LD4_LANE_FUNC (int16x8x4_t, int16x8_t, int16_t, v8hi, hi, s16)
-__LD4_LANE_FUNC (int32x4x4_t, int32x4_t, int32_t, v4si, si, s32)
-__LD4_LANE_FUNC (int64x2x4_t, int64x2_t, int64_t, v2di, di, s64)
-__LD4_LANE_FUNC (uint8x16x4_t, uint8x16_t, uint8_t, v16qi, qi, u8)
-__LD4_LANE_FUNC (uint16x8x4_t, uint16x8_t, uint16_t, v8hi, hi, u16)
-__LD4_LANE_FUNC (uint32x4x4_t, uint32x4_t, uint32_t, v4si, si, u32)
-__LD4_LANE_FUNC (uint64x2x4_t, uint64x2_t, uint64_t, v2di, di, u64)
-
-#undef __LD4_LANE_FUNC
+__LD4Q_LANE_FUNC (float16x8x4_t, float16x8_t, float16_t, v8hf, hf, f16)
+__LD4Q_LANE_FUNC (float32x4x4_t, float32x4_t, float32_t, v4sf, sf, f32)
+__LD4Q_LANE_FUNC (float64x2x4_t, float64x2_t, float64_t, v2df, df, f64)
+__LD4Q_LANE_FUNC (poly8x16x4_t, poly8x16_t, poly8_t, v16qi, qi, p8)
+__LD4Q_LANE_FUNC (poly16x8x4_t, poly16x8_t, poly16_t, v8hi, hi, p16)
+__LD4Q_LANE_FUNC (poly64x2x4_t, poly64x2_t, poly64_t, v2di, di, p64)
+__LD4Q_LANE_FUNC (int8x16x4_t, int8x16_t, int8_t, v16qi, qi, s8)
+__LD4Q_LANE_FUNC (int16x8x4_t, int16x8_t, int16_t, v8hi, hi, s16)
+__LD4Q_LANE_FUNC (int32x4x4_t, int32x4_t, int32_t, v4si, si, s32)
+__LD4Q_LANE_FUNC (int64x2x4_t, int64x2_t, int64_t, v2di, di, s64)
+__LD4Q_LANE_FUNC (uint8x16x4_t, uint8x16_t, uint8_t, v16qi, qi, u8)
+__LD4Q_LANE_FUNC (uint16x8x4_t, uint16x8_t, uint16_t, v8hi, hi, u16)
+__LD4Q_LANE_FUNC (uint32x4x4_t, uint32x4_t, uint32_t, v4si, si, u32)
+__LD4Q_LANE_FUNC (uint64x2x4_t, uint64x2_t, uint64_t, v2di, di, u64)
/* vmax */
@@ -35697,6 +35538,41 @@ vbfmlaltq_laneq_f32 (float32x4_t __r, bfloat16x8_t __a, bfloat16x8_t __b,
__extension__ extern __inline bfloat16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vget_low_bf16 (bfloat16x8_t __a)
+{
+ return __builtin_aarch64_vget_lo_halfv8bf (__a);
+}
+
+__extension__ extern __inline bfloat16x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vget_high_bf16 (bfloat16x8_t __a)
+{
+ return __builtin_aarch64_vget_hi_halfv8bf (__a);
+}
+
+__extension__ extern __inline float32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcvt_f32_bf16 (bfloat16x4_t __a)
+{
+ return __builtin_aarch64_vbfcvtv4bf (__a);
+}
+
+__extension__ extern __inline float32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcvtq_low_f32_bf16 (bfloat16x8_t __a)
+{
+ return __builtin_aarch64_vbfcvtv8bf (__a);
+}
+
+__extension__ extern __inline float32x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcvtq_high_f32_bf16 (bfloat16x8_t __a)
+{
+ return __builtin_aarch64_vbfcvt_highv8bf (__a);
+}
+
+__extension__ extern __inline bfloat16x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcvt_bf16_f32 (float32x4_t __a)
{
return __builtin_aarch64_bfcvtnv4bf (__a);
@@ -35716,6 +35592,62 @@ vcvtq_high_bf16_f32 (bfloat16x8_t __inactive, float32x4_t __a)
return __builtin_aarch64_bfcvtn2v8bf (__inactive, __a);
}
+__extension__ extern __inline bfloat16x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcopy_lane_bf16 (bfloat16x4_t __a, const int __lane1,
+ bfloat16x4_t __b, const int __lane2)
+{
+ return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2),
+ __a, __lane1);
+}
+
+__extension__ extern __inline bfloat16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcopyq_lane_bf16 (bfloat16x8_t __a, const int __lane1,
+ bfloat16x4_t __b, const int __lane2)
+{
+ return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2),
+ __a, __lane1);
+}
+
+__extension__ extern __inline bfloat16x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcopy_laneq_bf16 (bfloat16x4_t __a, const int __lane1,
+ bfloat16x8_t __b, const int __lane2)
+{
+ return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2),
+ __a, __lane1);
+}
+
+__extension__ extern __inline bfloat16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vcopyq_laneq_bf16 (bfloat16x8_t __a, const int __lane1,
+ bfloat16x8_t __b, const int __lane2)
+{
+ return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2),
+ __a, __lane1);
+}
+
+__LD2_LANE_FUNC (bfloat16x4x2_t, bfloat16x4_t, bfloat16x8x2_t, bfloat16_t, v4bf,
+ v8bf, bf, bf16, bfloat16x8_t)
+__LD2Q_LANE_FUNC (bfloat16x8x2_t, bfloat16x8_t, bfloat16_t, v8bf, bf, bf16)
+__LD3_LANE_FUNC (bfloat16x4x3_t, bfloat16x4_t, bfloat16x8x3_t, bfloat16_t, v4bf,
+ v8bf, bf, bf16, bfloat16x8_t)
+__LD3Q_LANE_FUNC (bfloat16x8x3_t, bfloat16x8_t, bfloat16_t, v8bf, bf, bf16)
+__LD4_LANE_FUNC (bfloat16x4x4_t, bfloat16x4_t, bfloat16x8x4_t, bfloat16_t, v4bf,
+ v8bf, bf, bf16, bfloat16x8_t)
+__LD4Q_LANE_FUNC (bfloat16x8x4_t, bfloat16x8_t, bfloat16_t, v8bf, bf, bf16)
+
+__ST2_LANE_FUNC (bfloat16x4x2_t, bfloat16x8x2_t, bfloat16_t, v4bf, v8bf, bf,
+ bf16, bfloat16x8_t)
+__ST2Q_LANE_FUNC (bfloat16x8x2_t, bfloat16_t, v8bf, bf, bf16)
+__ST3_LANE_FUNC (bfloat16x4x3_t, bfloat16x8x3_t, bfloat16_t, v4bf, v8bf, bf,
+ bf16, bfloat16x8_t)
+__ST3Q_LANE_FUNC (bfloat16x8x3_t, bfloat16_t, v8bf, bf, bf16)
+__ST4_LANE_FUNC (bfloat16x4x4_t, bfloat16x8x4_t, bfloat16_t, v4bf, v8bf, bf,
+ bf16, bfloat16x8_t)
+__ST4Q_LANE_FUNC (bfloat16x8x4_t, bfloat16_t, v8bf, bf, bf16)
+
#pragma GCC pop_options
/* AdvSIMD 8-bit Integer Matrix Multiply (I8MM) intrinsics. */
@@ -35929,4 +35861,17 @@ vaddq_p128 (poly128_t __a, poly128_t __b)
#undef __aarch64_vdupq_laneq_u32
#undef __aarch64_vdupq_laneq_u64
+#undef __LD2_LANE_FUNC
+#undef __LD2Q_LANE_FUNC
+#undef __LD3_LANE_FUNC
+#undef __LD3Q_LANE_FUNC
+#undef __LD4_LANE_FUNC
+#undef __LD4Q_LANE_FUNC
+#undef __ST2_LANE_FUNC
+#undef __ST2Q_LANE_FUNC
+#undef __ST3_LANE_FUNC
+#undef __ST3Q_LANE_FUNC
+#undef __ST4_LANE_FUNC
+#undef __ST4Q_LANE_FUNC
+
#endif
diff --git a/gcc/config/aarch64/falkor.md b/gcc/config/aarch64/falkor.md
index b501771..ecfe4d4 100644
--- a/gcc/config/aarch64/falkor.md
+++ b/gcc/config/aarch64/falkor.md
@@ -302,7 +302,7 @@
(define_insn_reservation "falkor_alu_1_xyz" 1
(and (eq_attr "tune" "falkor")
- (eq_attr "type" "alus_sreg,alus_imm,alus_shift_imm,csel,adc_reg,alu_imm,alu_sreg,alu_shift_imm,alu_ext,alus_ext,logic_imm,logic_reg,logic_shift_imm,logics_imm,logics_reg,logics_shift_imm,mov_reg"))
+ (eq_attr "type" "alus_sreg,alus_imm,alus_shift_imm,csel,adc_reg,alu_imm,alu_sreg,alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_ext,alus_ext,logic_imm,logic_reg,logic_shift_imm,logics_imm,logics_reg,logics_shift_imm,mov_reg"))
"falkor_xyz")
;; SIMD Miscellaneous Instructions
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 054fd85..b8ee422 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -400,7 +400,7 @@
(define_mode_iterator SVE_ALL [VNx16QI VNx8QI VNx4QI VNx2QI
VNx8HI VNx4HI VNx2HI
VNx8HF VNx4HF VNx2HF
- VNx8BF
+ VNx8BF VNx4BF VNx2BF
VNx4SI VNx2SI
VNx4SF VNx2SF
VNx2DI
@@ -418,11 +418,13 @@
VNx2DI])
;; SVE modes with 2 or 4 elements.
-(define_mode_iterator SVE_24 [VNx2QI VNx2HI VNx2HF VNx2SI VNx2SF VNx2DI VNx2DF
- VNx4QI VNx4HI VNx4HF VNx4SI VNx4SF])
+(define_mode_iterator SVE_24 [VNx2QI VNx2HI VNx2HF VNx2BF VNx2SI VNx2SF
+ VNx2DI VNx2DF
+ VNx4QI VNx4HI VNx4HF VNx4BF VNx4SI VNx4SF])
;; SVE modes with 2 elements.
-(define_mode_iterator SVE_2 [VNx2QI VNx2HI VNx2HF VNx2SI VNx2SF VNx2DI VNx2DF])
+(define_mode_iterator SVE_2 [VNx2QI VNx2HI VNx2HF VNx2BF
+ VNx2SI VNx2SF VNx2DI VNx2DF])
;; SVE integer modes with 2 elements, excluding the widest element.
(define_mode_iterator SVE_2BHSI [VNx2QI VNx2HI VNx2SI])
@@ -431,7 +433,7 @@
(define_mode_iterator SVE_2HSDI [VNx2HI VNx2SI VNx2DI])
;; SVE modes with 4 elements.
-(define_mode_iterator SVE_4 [VNx4QI VNx4HI VNx4HF VNx4SI VNx4SF])
+(define_mode_iterator SVE_4 [VNx4QI VNx4HI VNx4HF VNx4BF VNx4SI VNx4SF])
;; SVE integer modes with 4 elements, excluding the widest element.
(define_mode_iterator SVE_4BHI [VNx4QI VNx4HI])
@@ -621,6 +623,7 @@
UNSPEC_REVB ; Used in aarch64-sve.md.
UNSPEC_REVH ; Used in aarch64-sve.md.
UNSPEC_REVW ; Used in aarch64-sve.md.
+ UNSPEC_REVBHW ; Used in aarch64-sve.md.
UNSPEC_SMUL_HIGHPART ; Used in aarch64-sve.md.
UNSPEC_UMUL_HIGHPART ; Used in aarch64-sve.md.
UNSPEC_FMLA ; Used in aarch64-sve.md.
@@ -968,6 +971,16 @@
(VNx4SI "32") (VNx2DI "64")
(VNx8HF "16") (VNx4SF "32") (VNx2DF "64")])
+;; The number of bits in a vector container.
+(define_mode_attr container_bits [(VNx16QI "8")
+ (VNx8HI "16") (VNx8QI "16") (VNx8HF "16")
+ (VNx8BF "16")
+ (VNx4SI "32") (VNx4HI "32") (VNx4QI "32")
+ (VNx4SF "32") (VNx4HF "32") (VNx4BF "32")
+ (VNx2DI "64") (VNx2SI "64") (VNx2HI "64")
+ (VNx2QI "64") (VNx2DF "64") (VNx2SF "64")
+ (VNx2HF "64") (VNx2BF "64")])
+
;; Attribute to describe constants acceptable in logical operations
(define_mode_attr lconst [(SI "K") (DI "L")])
@@ -1029,7 +1042,7 @@
(VNx16QI "b") (VNx8QI "b") (VNx4QI "b") (VNx2QI "b")
(VNx8HI "h") (VNx4HI "h") (VNx2HI "h")
(VNx8HF "h") (VNx4HF "h") (VNx2HF "h")
- (VNx8BF "h")
+ (VNx8BF "h") (VNx4BF "h") (VNx2BF "h")
(VNx4SI "s") (VNx2SI "s")
(VNx4SF "s") (VNx2SF "s")
(VNx2DI "d")
@@ -1047,7 +1060,7 @@
(define_mode_attr Vesize [(VNx16QI "b") (VNx8QI "b") (VNx4QI "b") (VNx2QI "b")
(VNx8HI "h") (VNx4HI "h") (VNx2HI "h")
(VNx8HF "h") (VNx4HF "h") (VNx2HF "h")
- (VNx8BF "h")
+ (VNx8BF "h") (VNx4BF "h") (VNx2BF "h")
(VNx4SI "w") (VNx2SI "w")
(VNx4SF "w") (VNx2SF "w")
(VNx2DI "d")
@@ -1066,12 +1079,23 @@
(define_mode_attr Vctype [(VNx16QI "b") (VNx8QI "h") (VNx4QI "s") (VNx2QI "d")
(VNx8HI "h") (VNx4HI "s") (VNx2HI "d")
(VNx8HF "h") (VNx4HF "s") (VNx2HF "d")
- (VNx8BF "h")
+ (VNx8BF "h") (VNx4BF "s") (VNx2BF "d")
(VNx4SI "s") (VNx2SI "d")
(VNx4SF "s") (VNx2SF "d")
(VNx2DI "d")
(VNx2DF "d")])
+;; The instruction mnemonic suffix for an SVE mode's element container,
+;; i.e. the Vewtype of full SVE modes that have the same number of elements.
+(define_mode_attr Vcwtype [(VNx16QI "b") (VNx8QI "h") (VNx4QI "w") (VNx2QI "d")
+ (VNx8HI "h") (VNx4HI "w") (VNx2HI "d")
+ (VNx8HF "h") (VNx4HF "w") (VNx2HF "d")
+ (VNx8BF "h") (VNx4BF "w") (VNx2BF "d")
+ (VNx4SI "w") (VNx2SI "d")
+ (VNx4SF "w") (VNx2SF "d")
+ (VNx2DI "d")
+ (VNx2DF "d")])
+
;; Vetype is used everywhere in scheduling type and assembly output,
;; sometimes they are not the same, for example HF modes on some
;; instructions. stype is defined to represent scheduling type
@@ -1107,7 +1131,7 @@
(VNx16QI "QI") (VNx8QI "QI") (VNx4QI "QI") (VNx2QI "QI")
(VNx8HI "HI") (VNx4HI "HI") (VNx2HI "HI")
(VNx8HF "HF") (VNx4HF "HF") (VNx2HF "HF")
- (VNx8BF "BF")
+ (VNx8BF "BF") (VNx4BF "BF") (VNx2BF "BF")
(VNx4SI "SI") (VNx2SI "SI")
(VNx4SF "SF") (VNx2SF "SF")
(VNx2DI "DI")
@@ -1127,7 +1151,7 @@
(VNx16QI "qi") (VNx8QI "qi") (VNx4QI "qi") (VNx2QI "qi")
(VNx8HI "hi") (VNx4HI "hi") (VNx2HI "hi")
(VNx8HF "hf") (VNx4HF "hf") (VNx2HF "hf")
- (VNx8BF "bf")
+ (VNx8BF "bf") (VNx4BF "bf") (VNx2BF "bf")
(VNx4SI "si") (VNx2SI "si")
(VNx4SF "sf") (VNx2SF "sf")
(VNx2DI "di")
@@ -1310,7 +1334,7 @@
(VNx16QI "w") (VNx8QI "w") (VNx4QI "w") (VNx2QI "w")
(VNx8HI "w") (VNx4HI "w") (VNx2HI "w")
(VNx8HF "w") (VNx4HF "w") (VNx2HF "w")
- (VNx8BF "w")
+ (VNx8BF "w") (VNx4BF "w") (VNx2BF "w")
(VNx4SI "w") (VNx2SI "w")
(VNx4SF "w") (VNx2SF "w")
(VNx2DI "x")
@@ -1380,6 +1404,8 @@
(VNx2DI "VNx2DI")
(VNx8HF "VNx8HI") (VNx4HF "VNx4SI")
(VNx2HF "VNx2DI")
+ (VNx8BF "VNx8HI") (VNx4BF "VNx4SI")
+ (VNx2BF "VNx2DI")
(VNx4SF "VNx4SI") (VNx2SF "VNx2DI")
(VNx2DF "VNx2DI")])
@@ -1392,6 +1418,8 @@
(VNx2DI "vnx2di")
(VNx8HF "vnx8hi") (VNx4HF "vnx4si")
(VNx2HF "vnx2di")
+ (VNx8BF "vnx8hi") (VNx4BF "vnx4si")
+ (VNx2BF "vnx2di")
(VNx4SF "vnx4si") (VNx2SF "vnx2di")
(VNx2DF "vnx2di")])
@@ -1617,7 +1645,7 @@
(VNx4QI "VNx4BI") (VNx2QI "VNx2BI")
(VNx8HI "VNx8BI") (VNx4HI "VNx4BI") (VNx2HI "VNx2BI")
(VNx8HF "VNx8BI") (VNx4HF "VNx4BI") (VNx2HF "VNx2BI")
- (VNx8BF "VNx8BI")
+ (VNx8BF "VNx8BI") (VNx4BF "VNx4BI") (VNx2BF "VNx2BI")
(VNx4SI "VNx4BI") (VNx2SI "VNx2BI")
(VNx4SF "VNx4BI") (VNx2SF "VNx2BI")
(VNx2DI "VNx2BI")
@@ -1643,7 +1671,7 @@
(VNx4QI "vnx4bi") (VNx2QI "vnx2bi")
(VNx8HI "vnx8bi") (VNx4HI "vnx4bi") (VNx2HI "vnx2bi")
(VNx8HF "vnx8bi") (VNx4HF "vnx4bi") (VNx2HF "vnx2bi")
- (VNx8BF "vnx8bi")
+ (VNx8BF "vnx8bi") (VNx4BF "vnx4bi") (VNx2BF "vnx2bi")
(VNx4SI "vnx4bi") (VNx2SI "vnx2bi")
(VNx4SF "vnx4bi") (VNx2SF "vnx2bi")
(VNx2DI "vnx2bi")
@@ -2570,6 +2598,10 @@
UNSPEC_SQRDCMLAH180
UNSPEC_SQRDCMLAH270])
+;; Same as SVE2_INT_CADD but exclude the saturating instructions
+(define_int_iterator SVE2_INT_CADD_OP [UNSPEC_CADD90
+ UNSPEC_CADD270])
+
(define_int_iterator SVE2_INT_CDOT [UNSPEC_CDOT
UNSPEC_CDOT90
UNSPEC_CDOT180
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 91b5148..4f074a2 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -18,6 +18,8 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(include "../arm/common.md")
+
(define_special_predicate "cc_register"
(and (match_code "reg")
(and (match_test "REGNO (op) == CC_REGNUM")
diff --git a/gcc/config/aarch64/saphira.md b/gcc/config/aarch64/saphira.md
index 78a495b..6e623c4 100644
--- a/gcc/config/aarch64/saphira.md
+++ b/gcc/config/aarch64/saphira.md
@@ -224,7 +224,7 @@
(define_insn_reservation "saphira_alu_1_xyz" 1
(and (eq_attr "tune" "saphira")
- (eq_attr "type" "alus_sreg,alus_imm,alus_shift_imm,csel,adc_reg,alu_imm,alu_sreg,alu_shift_imm,alu_ext,alus_ext,logic_imm,logic_reg,logic_shift_imm,logics_imm,logics_reg,logics_shift_imm,mov_reg"))
+ (eq_attr "type" "alus_sreg,alus_imm,alus_shift_imm,csel,adc_reg,alu_imm,alu_sreg,alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_ext,alus_ext,logic_imm,logic_reg,logic_shift_imm,logics_imm,logics_reg,logics_shift_imm,mov_reg"))
"saphira_xyzb")
;; SIMD Miscellaneous Instructions
diff --git a/gcc/config/aarch64/thunderx.md b/gcc/config/aarch64/thunderx.md
index 52cd171..c8c9f5c 100644
--- a/gcc/config/aarch64/thunderx.md
+++ b/gcc/config/aarch64/thunderx.md
@@ -51,7 +51,7 @@
(define_insn_reservation "thunderx_arith_shift" 2
(and (eq_attr "tune" "thunderx")
- (eq_attr "type" "alu_ext,alu_shift_imm,alu_shift_reg,alus_ext,logic_shift_imm,logic_shift_reg,logics_shift_imm,logics_shift_reg,alus_shift_imm"))
+ (eq_attr "type" "alu_ext,alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_shift_reg,alus_ext,logic_shift_imm,logic_shift_reg,logics_shift_imm,logics_shift_reg,alus_shift_imm"))
"thunderx_pipe0 | thunderx_pipe1")
(define_insn_reservation "thunderx_csel" 2
diff --git a/gcc/config/aarch64/thunderx2t99.md b/gcc/config/aarch64/thunderx2t99.md
index 064e1ca..d9da80d 100644
--- a/gcc/config/aarch64/thunderx2t99.md
+++ b/gcc/config/aarch64/thunderx2t99.md
@@ -109,7 +109,7 @@
(define_insn_reservation "thunderx2t99_alu_shift" 2
(and (eq_attr "tune" "thunderx2t99")
- (eq_attr "type" "alu_shift_imm,alu_ext,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_ext,\
alus_shift_imm,alus_ext,\
logic_shift_imm,logics_shift_imm"))
"thunderx2t99_i012,thunderx2t99_i012")
diff --git a/gcc/config/aarch64/thunderx3t110.md b/gcc/config/aarch64/thunderx3t110.md
index f8d6204..ee1dd96 100644
--- a/gcc/config/aarch64/thunderx3t110.md
+++ b/gcc/config/aarch64/thunderx3t110.md
@@ -126,14 +126,14 @@
; is it actually 1,1/2,{i0,i1} vs 2,1/4,{i0,i1,i2,i3}
(define_insn_reservation "thunderx3t110_alu_shift" 2
(and (eq_attr "tune" "thunderx3t110")
- (eq_attr "type" "alu_shift_imm,alu_ext,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_ext,\
alus_shift_imm,alus_ext,\
logic_shift_imm,logics_shift_imm"))
"thunderx3t110_i0123")
(define_insn_reservation "thunderx3t110_alu_shift1" 1
(and (eq_attr "tune" "thunderx3t110")
- (eq_attr "type" "alu_shift_imm,alu_ext,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_ext,\
alus_shift_imm,alus_ext,\
logic_shift_imm,logics_shift_imm"))
"thunderx3t110_i01")
diff --git a/gcc/config/aarch64/tsv110.md b/gcc/config/aarch64/tsv110.md
index 53293f5..b35ff2d 100644
--- a/gcc/config/aarch64/tsv110.md
+++ b/gcc/config/aarch64/tsv110.md
@@ -295,7 +295,7 @@
(define_insn_reservation "tsv110_alu_shift" 2
(and (eq_attr "tune" "tsv110")
(eq_attr "type" "extend,\
- alu_shift_imm,alu_shift_reg,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_shift_reg,\
crc,logic_shift_imm,logic_shift_reg,\
mov_shift,mvn_shift,\
mov_shift_reg,mvn_shift_reg"))
diff --git a/gcc/config/alpha/alpha.opt b/gcc/config/alpha/alpha.opt
index 43b35e2..36dcdca 100644
--- a/gcc/config/alpha/alpha.opt
+++ b/gcc/config/alpha/alpha.opt
@@ -19,11 +19,11 @@
; <http://www.gnu.org/licenses/>.
msoft-float
-Target Report Mask(SOFT_FP)
+Target Mask(SOFT_FP)
Do not use hardware fp.
mfp-regs
-Target Report Mask(FPREGS)
+Target Mask(FPREGS)
Use fp registers.
mgas
@@ -35,70 +35,70 @@ Target RejectNegative Mask(IEEE_CONFORMANT)
Request IEEE-conformant math library routines (OSF/1).
mieee
-Target Report RejectNegative Mask(IEEE)
+Target RejectNegative Mask(IEEE)
Emit IEEE-conformant code, without inexact exceptions.
mieee-with-inexact
-Target Report RejectNegative Mask(IEEE_WITH_INEXACT)
+Target RejectNegative Mask(IEEE_WITH_INEXACT)
mbuild-constants
-Target Report Mask(BUILD_CONSTANTS)
+Target Mask(BUILD_CONSTANTS)
Do not emit complex integer constants to read-only memory.
mfloat-vax
-Target Report RejectNegative Mask(FLOAT_VAX)
+Target RejectNegative Mask(FLOAT_VAX)
Use VAX fp.
mfloat-ieee
-Target Report RejectNegative InverseMask(FLOAT_VAX)
+Target RejectNegative InverseMask(FLOAT_VAX)
Do not use VAX fp.
mbwx
-Target Report Mask(BWX)
+Target Mask(BWX)
Emit code for the byte/word ISA extension.
mmax
-Target Report Mask(MAX)
+Target Mask(MAX)
Emit code for the motion video ISA extension.
mfix
-Target Report Mask(FIX)
+Target Mask(FIX)
Emit code for the fp move and sqrt ISA extension.
mcix
-Target Report Mask(CIX)
+Target Mask(CIX)
Emit code for the counting ISA extension.
mexplicit-relocs
-Target Report Mask(EXPLICIT_RELOCS)
+Target Mask(EXPLICIT_RELOCS)
Emit code using explicit relocation directives.
msmall-data
-Target Report RejectNegative Mask(SMALL_DATA)
+Target RejectNegative Mask(SMALL_DATA)
Emit 16-bit relocations to the small data areas.
mlarge-data
-Target Report RejectNegative InverseMask(SMALL_DATA)
+Target RejectNegative InverseMask(SMALL_DATA)
Emit 32-bit relocations to the small data areas.
msmall-text
-Target Report RejectNegative Mask(SMALL_TEXT)
+Target RejectNegative Mask(SMALL_TEXT)
Emit direct branches to local functions.
mlarge-text
-Target Report RejectNegative InverseMask(SMALL_TEXT)
+Target RejectNegative InverseMask(SMALL_TEXT)
Emit indirect branches to local functions.
mtls-kernel
-Target Report Mask(TLS_KERNEL)
+Target Mask(TLS_KERNEL)
Emit rdval instead of rduniq for thread pointer.
mlong-double-128
-Target Report RejectNegative Mask(LONG_DOUBLE_128)
+Target RejectNegative Mask(LONG_DOUBLE_128)
Use 128-bit long double.
mlong-double-64
-Target Report RejectNegative InverseMask(LONG_DOUBLE_128)
+Target RejectNegative InverseMask(LONG_DOUBLE_128)
Use 64-bit long double.
mcpu=
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index c72d78e..de4cf47 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -90,10 +90,7 @@ extern void split_subsi (rtx *);
extern void arc_split_move (rtx *);
extern const char *arc_short_long (rtx_insn *insn, const char *, const char *);
extern rtx arc_regno_use_in (unsigned int, rtx);
-extern bool arc_scheduling_not_expected (void);
-extern bool arc_sets_cc_p (rtx_insn *insn);
extern int arc_label_align (rtx_insn *label);
-extern bool arc_need_delay (rtx_insn *insn);
extern bool arc_text_label (rtx_insn *insn);
extern bool arc_short_comparison_p (rtx, int);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 6b96c5e..fb672c7 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -901,7 +901,7 @@ arc_secondary_reload (bool in_p,
/* It is a pseudo that ends in a stack location. This
procedure only works with the old reload step. */
- if (reg_equiv_mem (REGNO (x)) && !lra_in_progress)
+ if (!lra_in_progress && reg_equiv_mem (REGNO (x)))
{
/* Get the equivalent address and check the range of the
offset. */
@@ -4418,10 +4418,10 @@ arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
emit_move_insn (adjust_address (tramp, SImode, 8), fnaddr);
emit_move_insn (adjust_address (tramp, SImode, 12), cxt);
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
- LCT_NORMAL, VOIDmode, XEXP (tramp, 0), Pmode,
- plus_constant (Pmode, XEXP (tramp, 0), TRAMPOLINE_SIZE),
- Pmode);
+ maybe_emit_call_builtin___clear_cache (XEXP (tramp, 0),
+ plus_constant (Pmode,
+ XEXP (tramp, 0),
+ TRAMPOLINE_SIZE));
}
/* Add the given function declaration to emit code in JLI section. */
@@ -7663,11 +7663,18 @@ arc_invalid_within_doloop (const rtx_insn *insn)
static rtx_insn *
arc_active_insn (rtx_insn *insn)
{
- rtx_insn *nxt = next_active_insn (insn);
-
- if (nxt && GET_CODE (PATTERN (nxt)) == ASM_INPUT)
- nxt = next_active_insn (nxt);
- return nxt;
+ while (insn)
+ {
+ insn = NEXT_INSN (insn);
+ if (insn == 0
+ || (active_insn_p (insn)
+ && NONDEBUG_INSN_P (insn)
+ && !NOTE_P (insn)
+ && GET_CODE (PATTERN (insn)) != UNSPEC_VOLATILE
+ && GET_CODE (PATTERN (insn)) != PARALLEL))
+ break;
+ }
+ return insn;
}
/* Search for a sequence made out of two stores and a given number of
@@ -7686,11 +7693,10 @@ check_store_cacheline_hazard (void)
if (!succ0)
return;
- if (!single_set (insn) || !single_set (succ0))
+ if (!single_set (insn))
continue;
- if ((get_attr_type (insn) != TYPE_STORE)
- || (get_attr_type (succ0) != TYPE_STORE))
+ if ((get_attr_type (insn) != TYPE_STORE))
continue;
/* Found at least two consecutive stores. Goto the end of the
@@ -7699,6 +7705,9 @@ check_store_cacheline_hazard (void)
if (!single_set (insn1) || get_attr_type (insn1) != TYPE_STORE)
break;
+ /* Save were we are. */
+ succ0 = insn1;
+
/* Now, check the next two instructions for the following cases:
1. next instruction is a LD => insert 2 nops between store
sequence and load.
@@ -7730,9 +7739,13 @@ check_store_cacheline_hazard (void)
}
}
- insn = insn1;
if (found)
- found = false;
+ {
+ insn = insn1;
+ found = false;
+ }
+ else
+ insn = succ0;
}
}
@@ -7807,7 +7820,6 @@ static void
workaround_arc_anomaly (void)
{
rtx_insn *insn, *succ0;
- rtx_insn *succ1;
/* For any architecture: call arc_hazard here. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -7826,24 +7838,6 @@ workaround_arc_anomaly (void)
nops between any sequence of stores and a load. */
if (arc_tune != ARC_TUNE_ARC7XX)
check_store_cacheline_hazard ();
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- succ0 = next_real_insn (insn);
- if (arc_store_addr_hazard_internal_p (insn, succ0))
- {
- emit_insn_after (gen_nopv (), insn);
- emit_insn_after (gen_nopv (), insn);
- continue;
- }
-
- /* Avoid adding nops if the instruction between the ST and LD is
- a call or jump. */
- succ1 = next_real_insn (succ0);
- if (succ0 && !JUMP_P (succ0) && !CALL_P (succ0)
- && arc_store_addr_hazard_internal_p (insn, succ1))
- emit_insn_after (gen_nopv (), insn);
- }
}
/* A callback for the hw-doloop pass. Called when a loop we have discovered
@@ -8589,6 +8583,7 @@ arc_reorg (void)
if (!brcc_nolimm_operator (op, VOIDmode)
&& !long_immediate_operand (op1, VOIDmode)
&& (TARGET_ARC700
+ || (TARGET_V2 && optimize_size)
|| next_active_insn (link_insn) != insn))
continue;
@@ -9239,13 +9234,21 @@ prepare_move_operands (rtx *operands, machine_mode mode)
}
if (arc_is_uncached_mem_p (operands[1]))
{
+ rtx tmp = operands[0];
+
if (MEM_P (operands[0]))
- operands[0] = force_reg (mode, operands[0]);
+ tmp = gen_reg_rtx (mode);
+
emit_insn (gen_rtx_SET
- (operands[0],
+ (tmp,
gen_rtx_UNSPEC_VOLATILE
(mode, gen_rtvec (1, operands[1]),
VUNSPEC_ARC_LDDI)));
+ if (MEM_P (operands[0]))
+ {
+ operands[1] = tmp;
+ return false;
+ }
return true;
}
}
@@ -10155,6 +10158,14 @@ arc_split_move (rtx *operands)
}
if (TARGET_PLUS_QMACW
+ && even_register_operand (operands[0], mode)
+ && even_register_operand (operands[1], mode))
+ {
+ emit_move_insn (operands[0], operands[1]);
+ return;
+ }
+
+ if (TARGET_PLUS_QMACW
&& GET_CODE (operands[1]) == CONST_VECTOR)
{
HOST_WIDE_INT intval0, intval1;
@@ -10291,59 +10302,6 @@ arc_attr_type (rtx_insn *insn)
return get_attr_type (insn);
}
-/* Return true if insn sets the condition codes. */
-
-bool
-arc_sets_cc_p (rtx_insn *insn)
-{
- if (NONJUMP_INSN_P (insn))
- if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
- insn = seq->insn (seq->len () - 1);
- return arc_attr_type (insn) == TYPE_COMPARE;
-}
-
-/* Return true if INSN is an instruction with a delay slot we may want
- to fill. */
-
-bool
-arc_need_delay (rtx_insn *insn)
-{
- rtx_insn *next;
-
- if (!flag_delayed_branch)
- return false;
- /* The return at the end of a function needs a delay slot. */
- if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
- && (!(next = next_active_insn (insn))
- || ((!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) != SEQUENCE)
- && arc_attr_type (next) == TYPE_RETURN))
- && (!TARGET_PAD_RETURN
- || (prev_active_insn (insn)
- && prev_active_insn (prev_active_insn (insn))
- && prev_active_insn (prev_active_insn (prev_active_insn (insn))))))
- return true;
- if (NONJUMP_INSN_P (insn)
- ? (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER
- || GET_CODE (PATTERN (insn)) == SEQUENCE)
- : JUMP_P (insn)
- ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
- : !CALL_P (insn))
- return false;
- return num_delay_slots (insn) != 0;
-}
-
-/* Return true if the scheduling pass(es) has/have already run,
- i.e. where possible, we should try to mitigate high latencies
- by different instruction selection. */
-
-bool
-arc_scheduling_not_expected (void)
-{
- return cfun->machine->arc_reorg_started;
-}
-
/* Code has a minimum p2 alignment of 1, which we must restore after
an ADDR_DIFF_VEC. */
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index fd6e21a..c388633 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -588,7 +588,7 @@ extern enum reg_class arc_regno_reg_class[];
|| ((REGNO) == ARG_POINTER_REGNUM) \
|| ((REGNO) == FRAME_POINTER_REGNUM) \
|| ((REGNO) == PCL_REG) \
- || ((unsigned) reg_renumber[REGNO] < 29) \
+ || (reg_renumber && ((unsigned) reg_renumber[REGNO] < 29)) \
|| ((unsigned) (REGNO) == (unsigned) arc_tp_regno) \
|| (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59)) \
|| (fixed_regs[REGNO] == 0 && (REGNO) == R30_REG))
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index a7f4056..b616c7f 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -871,6 +871,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(define_code_iterator SEZ [sign_extend zero_extend])
(define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")])
+; Optab prefix for sign/zero-extending operations
+(define_code_attr su_optab [(sign_extend "") (zero_extend "u")])
(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"
[(set (match_operand 0 "cc_set_register" "")
@@ -1322,8 +1324,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
")
(define_insn_and_split "*movdi_insn"
- [(set (match_operand:DI 0 "move_dest_operand" "=w, w,r, m")
- (match_operand:DI 1 "move_double_src_operand" "c,Hi,m,cCm3"))]
+ [(set (match_operand:DI 0 "move_dest_operand" "=r, r,r, m")
+ (match_operand:DI 1 "move_double_src_operand" "r,Hi,m,rCm3"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)
|| (satisfies_constraint_Cm3 (operands[1])
@@ -1335,6 +1337,13 @@ core_3, archs4x, archs4xd, archs4xd_slow"
default:
return \"#\";
+ case 0:
+ if (TARGET_PLUS_QMACW
+ && even_register_operand (operands[0], DImode)
+ && even_register_operand (operands[1], DImode))
+ return \"vadd2%?\\t%0,%1,0\";
+ return \"#\";
+
case 2:
if (TARGET_LL64
&& memory_operand (operands[1], DImode)
@@ -1351,7 +1360,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"
return \"#\";
}
}"
- "reload_completed"
+ "&& reload_completed"
[(const_int 0)]
{
arc_split_move (operands);
@@ -1397,15 +1406,24 @@ core_3, archs4x, archs4xd, archs4xd_slow"
"if (prepare_move_operands (operands, DFmode)) DONE;")
(define_insn_and_split "*movdf_insn"
- [(set (match_operand:DF 0 "move_dest_operand" "=D,r,c,c,r,m")
- (match_operand:DF 1 "move_double_src_operand" "r,D,c,E,m,c"))]
- "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
+ [(set (match_operand:DF 0 "move_dest_operand" "=D,r,r,r,r,m")
+ (match_operand:DF 1 "move_double_src_operand" "r,D,r,E,m,r"))]
+ "register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode)"
"*
{
switch (which_alternative)
{
default:
return \"#\";
+
+ case 2:
+ if (TARGET_PLUS_QMACW
+ && even_register_operand (operands[0], DFmode)
+ && even_register_operand (operands[1], DFmode))
+ return \"vadd2%?\\t%0,%1,0\";
+ return \"#\";
+
case 4:
if (TARGET_LL64
&& ((even_register_operand (operands[0], DFmode)
@@ -1432,7 +1450,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"
DONE;
}
[(set_attr "type" "move,move,move,move,load,store")
- (set_attr "predicable" "no,no,yes,yes,no,no")
+ (set_attr "predicable" "no,no,no,yes,no,no")
;; ??? The ld/st values could be 16 if it's [reg,bignum].
(set_attr "length" "4,16,8,16,16,16")])
@@ -2824,43 +2842,25 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "type" "compare")
(set_attr "length" "4,4,8")])
-; w/c/c comes first (rather than w/0/C_0) to prevent the middle-end
-; needlessly prioritizing the matching constraint.
-; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional
-; execution is used where possible.
-(define_insn_and_split "adc"
- [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
- (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
- (match_operand:SI 1 "nonmemory_operand"
- "%c,0,c,0,cCal"))
- (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
+(define_insn "adc"
+ [(set (match_operand:SI 0 "register_operand" "=r, r,r,r, r,r")
+ (plus:SI
+ (plus:SI
+ (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+ (match_operand:SI 1 "nonmemory_operand" "%r, 0,r,0,Cal,r"))
+ (match_operand:SI 2 "nonmemory_operand" "r,C_0,L,I, r,Cal")))]
"register_operand (operands[1], SImode)
|| register_operand (operands[2], SImode)"
"@
- adc %0,%1,%2
- add.cs %0,%1,1
- adc %0,%1,%2
- adc %0,%1,%2
- adc %0,%1,%2"
- ; if we have a bad schedule after sched2, split.
- "reload_completed
- && !optimize_size && (!TARGET_ARC600_FAMILY)
- && arc_scheduling_not_expected ()
- && arc_sets_cc_p (prev_nonnote_insn (insn))
- /* If next comes a return or other insn that needs a delay slot,
- expect the adc to get into the delay slot. */
- && next_nonnote_insn (insn)
- && !arc_need_delay (next_nonnote_insn (insn))
- /* Restore operands before emitting. */
- && (extract_insn_cached (insn), 1)"
- [(set (match_dup 0) (match_dup 3))
- (cond_exec
- (ltu (reg:CC_C CC_REG) (const_int 0))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))))]
- "operands[3] = simplify_gen_binary (PLUS, SImode, operands[1], operands[2]);"
+ adc\\t%0,%1,%2
+ add.cs\\t%0,%1,1
+ adc\\t%0,%1,%2
+ adc\\t%0,%1,%2
+ adc\\t%0,%1,%2
+ adc\\t%0,%1,%2"
[(set_attr "cond" "use")
(set_attr "type" "cc_arith")
- (set_attr "length" "4,4,4,4,8")])
+ (set_attr "length" "4,4,4,4,8,8")])
; combiner-splitter cmp / scc -> cmp / adc
(define_split
@@ -2992,7 +2992,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"
DONE;
}
emit_insn (gen_sub_f (l0, l1, l2));
- emit_insn (gen_sbc (h0, h1, h2, gen_rtx_REG (CCmode, CC_REG)));
+ emit_insn (gen_sbc (h0, h1, h2));
DONE;
")
@@ -3007,44 +3007,25 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "type" "cc_arith")
(set_attr "length" "4")])
-; w/c/c comes first (rather than Rcw/0/C_0) to prevent the middle-end
-; needlessly prioritizing the matching constraint.
-; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional execution
-; is used where possible.
-(define_insn_and_split "sbc"
- [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
- (minus:SI (minus:SI (match_operand:SI 1 "nonmemory_operand"
- "c,0,c,0,cCal")
- (ltu:SI (match_operand:CC_C 3 "cc_use_register")
- (const_int 0)))
- (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
+(define_insn "sbc"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r,r,r,r,r,r")
+ (minus:SI
+ (minus:SI
+ (match_operand:SI 1 "nonmemory_operand" "r, 0,r,0, r,Cal")
+ (ltu:SI (reg:CC_C CC_REG) (const_int 0)))
+ (match_operand:SI 2 "nonmemory_operand" "r,C_0,L,I,Cal,r")))]
"register_operand (operands[1], SImode)
|| register_operand (operands[2], SImode)"
"@
- sbc %0,%1,%2
- sub.cs %0,%1,1
- sbc %0,%1,%2
- sbc %0,%1,%2
- sbc %0,%1,%2"
- ; if we have a bad schedule after sched2, split.
- "reload_completed
- && !optimize_size && (!TARGET_ARC600_FAMILY)
- && arc_scheduling_not_expected ()
- && arc_sets_cc_p (prev_nonnote_insn (insn))
- /* If next comes a return or other insn that needs a delay slot,
- expect the adc to get into the delay slot. */
- && next_nonnote_insn (insn)
- && !arc_need_delay (next_nonnote_insn (insn))
- /* Restore operands before emitting. */
- && (extract_insn_cached (insn), 1)"
- [(set (match_dup 0) (match_dup 4))
- (cond_exec
- (ltu (reg:CC_C CC_REG) (const_int 0))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))))]
- "operands[4] = simplify_gen_binary (MINUS, SImode, operands[1], operands[2]);"
+ sbc\\t%0,%1,%2
+ sub.cs\\t%0,%1,1
+ sbc\\t%0,%1,%2
+ sbc\\t%0,%1,%2
+ sbc\\t%0,%1,%2
+ sbc\\t%0,%1,%2"
[(set_attr "cond" "use")
(set_attr "type" "cc_arith")
- (set_attr "length" "4,4,4,4,8")])
+ (set_attr "length" "4,4,4,4,8,8")])
(define_insn "sub_f"
[(set (reg:CC CC_REG)
@@ -6126,6 +6107,49 @@ core_3, archs4x, archs4xd, archs4xd_slow"
[(set_attr "length" "0")])
;; MAC and DMPY instructions
+
+; Use MAC instruction to emulate 16bit mac.
+(define_expand "maddhisi4"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")
+ (match_operand:HI 2 "extend_operand" "")
+ (match_operand:SI 3 "register_operand" "")]
+ "TARGET_PLUS_DMPY"
+ "{
+ rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
+ rtx tmp1 = gen_reg_rtx (SImode);
+ rtx tmp2 = gen_reg_rtx (SImode);
+ rtx accl = gen_lowpart (SImode, acc_reg);
+
+ emit_move_insn (accl, operands[3]);
+ emit_insn (gen_rtx_SET (tmp1, gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+ emit_insn (gen_rtx_SET (tmp2, gen_rtx_SIGN_EXTEND (SImode, operands[2])));
+ emit_insn (gen_mac (tmp1, tmp2));
+ emit_move_insn (operands[0], accl);
+ DONE;
+ }")
+
+; The same for the unsigned variant, but using MACU instruction.
+(define_expand "umaddhisi4"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")
+ (match_operand:HI 2 "extend_operand" "")
+ (match_operand:SI 3 "register_operand" "")]
+ "TARGET_PLUS_DMPY"
+ "{
+ rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
+ rtx tmp1 = gen_reg_rtx (SImode);
+ rtx tmp2 = gen_reg_rtx (SImode);
+ rtx accl = gen_lowpart (SImode, acc_reg);
+
+ emit_move_insn (accl, operands[3]);
+ emit_insn (gen_rtx_SET (tmp1, gen_rtx_ZERO_EXTEND (SImode, operands[1])));
+ emit_insn (gen_rtx_SET (tmp2, gen_rtx_ZERO_EXTEND (SImode, operands[2])));
+ emit_insn (gen_macu (tmp1, tmp2));
+ emit_move_insn (operands[0], accl);
+ DONE;
+ }")
+
(define_expand "maddsidi4"
[(match_operand:DI 0 "register_operand" "")
(match_operand:SI 1 "register_operand" "")
@@ -6152,12 +6176,14 @@ core_3, archs4x, archs4xd, archs4xd_slow"
"{
rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
emit_move_insn (acc_reg, operands[3]);
- if (TARGET_PLUS_MACD && even_register_operand (operands[0], DImode))
- emit_insn (gen_macd (operands[0], operands[1], operands[2]));
+ if (TARGET_PLUS_MACD && even_register_operand (operands[0], DImode)
+ && REGNO (operands[0]) != ACCL_REGNO)
+ emit_insn (gen_macd (operands[0], operands[1], operands[2]));
else
{
emit_insn (gen_mac (operands[1], operands[2]));
- emit_move_insn (operands[0], acc_reg);
+ if (REGNO (operands[0]) != ACCL_REGNO)
+ emit_move_insn (operands[0], acc_reg);
}
DONE;
}"
@@ -6168,8 +6194,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
[(set (match_operand:DI 0 "even_register_operand" "=Rcr,r,r")
(plus:DI
(mult:DI
- (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c"))
- (sign_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,Cal")))
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,r,r"))
+ (sign_extend:DI (match_operand:SI 2 "extend_operand" "r,rI,Cal")))
(reg:DI ARCV2_ACC)))
(set (reg:DI ARCV2_ACC)
(plus:DI
@@ -6252,12 +6278,14 @@ core_3, archs4x, archs4xd, archs4xd_slow"
"{
rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
emit_move_insn (acc_reg, operands[3]);
- if (TARGET_PLUS_MACD && even_register_operand (operands[0], DImode))
- emit_insn (gen_macdu (operands[0], operands[1], operands[2]));
+ if (TARGET_PLUS_MACD && even_register_operand (operands[0], DImode)
+ && REGNO (operands[0]) != ACCL_REGNO)
+ emit_insn (gen_macdu (operands[0], operands[1], operands[2]));
else
{
emit_insn (gen_macu (operands[1], operands[2]));
- emit_move_insn (operands[0], acc_reg);
+ if (REGNO (operands[0]) != ACCL_REGNO)
+ emit_move_insn (operands[0], acc_reg);
}
DONE;
}"
@@ -6268,8 +6296,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
[(set (match_operand:DI 0 "even_register_operand" "=Rcr,r,r")
(plus:DI
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c"))
- (zero_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,i")))
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,r,r"))
+ (zero_extend:DI (match_operand:SI 2 "extend_operand" "r,rI,i")))
(reg:DI ARCV2_ACC)))
(set (reg:DI ARCV2_ACC)
(plus:DI
@@ -6326,66 +6354,65 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
-(define_insn "mpyd_arcv2hs"
- [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " 0, c"))
- (sign_extend:DI (match_operand:SI 2 "register_operand" " c, c"))))
+(define_insn "mpyd<su_optab>_arcv2hs"
+ [(set (match_operand:DI 0 "even_register_operand" "=r")
+ (mult:DI (SEZ:DI (match_operand:SI 1 "register_operand" "r"))
+ (SEZ:DI (match_operand:SI 2 "register_operand" "r"))))
(set (reg:DI ARCV2_ACC)
(mult:DI
- (sign_extend:DI (match_dup 1))
- (sign_extend:DI (match_dup 2))))]
+ (SEZ:DI (match_dup 1))
+ (SEZ:DI (match_dup 2))))]
"TARGET_PLUS_MACD"
- "mpyd%? %0,%1,%2"
- [(set_attr "length" "4,4")
- (set_attr "iscompact" "false")
- (set_attr "type" "multi")
- (set_attr "predicable" "yes,no")
- (set_attr "cond" "canuse,nocond")])
-
-(define_insn "mpyd_imm_arcv2hs"
- [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r,r,Rcr, r")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " 0, c,0, 0, c"))
- (match_operand 2 "immediate_operand" " L, L,I,Cal,Cal")))
+ "mpyd<su_optab>%?\\t%0,%1,%2"
+ [(set_attr "length" "4")
+ (set_attr "iscompact" "false")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "no")])
+
+(define_insn "*pmpyd<su_optab>_arcv2hs"
+ [(set (match_operand:DI 0 "even_register_operand" "=r")
+ (mult:DI
+ (SEZ:DI (match_operand:SI 1 "even_register_operand" "%0"))
+ (SEZ:DI (match_operand:SI 2 "register_operand" "r"))))
(set (reg:DI ARCV2_ACC)
- (mult:DI (sign_extend:DI (match_dup 1))
- (match_dup 2)))]
+ (mult:DI
+ (SEZ:DI (match_dup 1))
+ (SEZ:DI (match_dup 2))))]
"TARGET_PLUS_MACD"
- "mpyd%? %0,%1,%2"
- [(set_attr "length" "4,4,4,8,8")
- (set_attr "iscompact" "false")
- (set_attr "type" "multi")
- (set_attr "predicable" "yes,no,no,yes,no")
- (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
-
-(define_insn "mpydu_arcv2hs"
- [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c"))
- (zero_extend:DI (match_operand:SI 2 "register_operand" " c, c"))))
+ "mpyd<su_optab>%?\\t%0,%1,%2"
+ [(set_attr "length" "4")
+ (set_attr "iscompact" "false")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "yes")])
+
+(define_insn "mpyd<su_optab>_imm_arcv2hs"
+ [(set (match_operand:DI 0 "even_register_operand" "=r,r, r")
+ (mult:DI (SEZ:DI (match_operand:SI 1 "register_operand" "r,0, r"))
+ (match_operand 2 "immediate_operand" "L,I,Cal")))
(set (reg:DI ARCV2_ACC)
- (mult:DI (zero_extend:DI (match_dup 1))
- (zero_extend:DI (match_dup 2))))]
+ (mult:DI (SEZ:DI (match_dup 1))
+ (match_dup 2)))]
"TARGET_PLUS_MACD"
- "mpydu%? %0,%1,%2"
- [(set_attr "length" "4,4")
- (set_attr "iscompact" "false")
- (set_attr "type" "multi")
- (set_attr "predicable" "yes,no")
- (set_attr "cond" "canuse,nocond")])
-
-(define_insn "mpydu_imm_arcv2hs"
- [(set (match_operand:DI 0 "even_register_operand" "=Rcr, r,r,Rcr, r")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c,0, 0, c"))
- (match_operand 2 "immediate_operand" " L, L,I,Cal,Cal")))
+ "mpyd<su_optab>%?\\t%0,%1,%2"
+ [(set_attr "length" "4,4,8")
+ (set_attr "iscompact" "false")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "no")])
+
+(define_insn "*pmpyd<su_optab>_imm_arcv2hs"
+ [(set (match_operand:DI 0 "even_register_operand" "=r,r")
+ (mult:DI
+ (SEZ:DI (match_operand:SI 1 "even_register_operand" "0,0"))
+ (match_operand 2 "immediate_operand" "L,Cal")))
(set (reg:DI ARCV2_ACC)
- (mult:DI (zero_extend:DI (match_dup 1))
+ (mult:DI (SEZ:DI (match_dup 1))
(match_dup 2)))]
"TARGET_PLUS_MACD"
- "mpydu%? %0,%1,%2"
- [(set_attr "length" "4,4,4,8,8")
- (set_attr "iscompact" "false")
- (set_attr "type" "multi")
- (set_attr "predicable" "yes,no,no,yes,no")
- (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
+ "mpyd<su_optab>%?\\t%0,%1,%2"
+ [(set_attr "length" "4,8")
+ (set_attr "iscompact" "false")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "yes")])
(define_insn "*add_shift"
[(set (match_operand:SI 0 "register_operand" "=q,r,r")
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index c6c64af..3696a1d 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -22,39 +22,39 @@ HeaderInclude
config/arc/arc-opts.h
mbig-endian
-Target Report RejectNegative Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Compile code for big endian mode.
mlittle-endian
-Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN)
Compile code for little endian mode. This is the default.
mno-cond-exec
-Target Report RejectNegative Mask(NO_COND_EXEC)
+Target RejectNegative Mask(NO_COND_EXEC)
Disable ARCompact specific pass to generate conditional execution instructions.
mA6
-Target Report
+Target
Generate ARCompact 32-bit code for ARC600 processor.
mARC600
-Target Report
+Target
Same as -mA6.
mARC601
-Target Report
+Target
Generate ARCompact 32-bit code for ARC601 processor.
mA7
-Target Report
+Target
Generate ARCompact 32-bit code for ARC700 processor.
mARC700
-Target Report
+Target
Same as -mA7.
mjli-always
-Target Report Mask(JLI_ALWAYS)
+Target Mask(JLI_ALWAYS)
Force all calls to be made via a jli instruction.
mmpy-option=
@@ -128,15 +128,15 @@ EnumValue
Enum(arc_mpy) String(plus_qmacw) Value(9) Canonical
mdiv-rem
-Target Report Mask(DIVREM)
+Target Mask(DIVREM)
Enable DIV-REM instructions for ARCv2.
mcode-density
-Target Report Mask(CODE_DENSITY)
+Target Mask(CODE_DENSITY)
Enable code density instructions for ARCv2.
mmixed-code
-Target Report Mask(MIXED_CODE_SET)
+Target Mask(MIXED_CODE_SET)
Tweak register allocation to help 16-bit instruction generation.
; originally this was:
;Generate ARCompact 16-bit instructions intermixed with 32-bit instructions
@@ -146,91 +146,91 @@ Tweak register allocation to help 16-bit instruction generation.
; We use an explict definition for the negative form because that is the
; actually interesting option, and we want that to have its own comment.
mvolatile-cache
-Target Report RejectNegative Mask(VOLATILE_CACHE_SET)
+Target RejectNegative Mask(VOLATILE_CACHE_SET)
Use ordinarily cached memory accesses for volatile references.
mno-volatile-cache
-Target Report RejectNegative InverseMask(VOLATILE_CACHE_SET)
+Target RejectNegative InverseMask(VOLATILE_CACHE_SET)
Enable cache bypass for volatile references.
mbarrel-shifter
-Target Report Mask(BARREL_SHIFTER)
+Target Mask(BARREL_SHIFTER)
Generate instructions supported by barrel shifter.
mnorm
-Target Report Mask(NORM_SET)
+Target Mask(NORM_SET)
Generate norm instruction.
mswap
-Target Report Mask(SWAP_SET)
+Target Mask(SWAP_SET)
Generate swap instruction.
mmul64
-Target Report Mask(MUL64_SET)
+Target Mask(MUL64_SET)
Generate mul64 and mulu64 instructions.
mno-mpy
-Target Report Mask(NOMPY_SET) Warn(%qs is deprecated)
+Target Mask(NOMPY_SET) Warn(%qs is deprecated)
Do not generate mpy instructions for ARC700.
mea
-Target Report Mask(EA_SET)
+Target Mask(EA_SET)
Generate extended arithmetic instructions, only valid for ARC700.
msoft-float
-Target Report Mask(0)
+Target Mask(0)
Dummy flag. This is the default unless FPX switches are provided explicitly.
mlong-calls
-Target Report Mask(LONG_CALLS_SET)
+Target Mask(LONG_CALLS_SET)
Generate call insns as register indirect calls.
mno-brcc
-Target Report Mask(NO_BRCC_SET)
+Target Mask(NO_BRCC_SET)
Do no generate BRcc instructions in arc_reorg.
msdata
-Target Report InverseMask(NO_SDATA_SET)
+Target InverseMask(NO_SDATA_SET)
Generate sdata references. This is the default, unless you compile for PIC.
mmillicode
-Target Report Mask(MILLICODE_THUNK_SET)
+Target Mask(MILLICODE_THUNK_SET)
Generate millicode thunks.
mspfp
-Target Report Mask(SPFP_COMPACT_SET)
+Target Mask(SPFP_COMPACT_SET)
FPX: Generate Single Precision FPX (compact) instructions.
mspfp-compact
-Target Report Mask(SPFP_COMPACT_SET) MaskExists
+Target Mask(SPFP_COMPACT_SET) MaskExists
FPX: Generate Single Precision FPX (compact) instructions.
mspfp-fast
-Target Report Mask(SPFP_FAST_SET)
+Target Mask(SPFP_FAST_SET)
FPX: Generate Single Precision FPX (fast) instructions.
margonaut
-Target Report Mask(ARGONAUT_SET)
+Target Mask(ARGONAUT_SET)
FPX: Enable Argonaut ARC CPU Double Precision Floating Point extensions.
mdpfp
-Target Report Mask(DPFP_COMPACT_SET)
+Target Mask(DPFP_COMPACT_SET)
FPX: Generate Double Precision FPX (compact) instructions.
mdpfp-compact
-Target Report Mask(DPFP_COMPACT_SET) MaskExists
+Target Mask(DPFP_COMPACT_SET) MaskExists
FPX: Generate Double Precision FPX (compact) instructions.
mdpfp-fast
-Target Report Mask(DPFP_FAST_SET)
+Target Mask(DPFP_FAST_SET)
FPX: Generate Double Precision FPX (fast) instructions.
mno-dpfp-lrsr
-Target Report Mask(DPFP_DISABLE_LRSR)
+Target Mask(DPFP_DISABLE_LRSR)
Disable LR and SR instructions from using FPX extension aux registers.
msimd
-Target Report Mask(SIMD_SET)
+Target Mask(SIMD_SET)
Enable generation of ARC SIMD instructions via target-specific builtins.
mcpu=
@@ -242,7 +242,7 @@ Target RejectNegative Joined UInteger Var(arc_size_opt_level) Init(-1)
Size optimization level: 0:none 1:opportunistic 2: regalloc 3:drop align, -Os.
misize
-Target Report PchIgnore Var(TARGET_DUMPISIZE)
+Target PchIgnore Var(TARGET_DUMPISIZE)
Annotate assembler instructions with estimated addresses.
mmultcost=
@@ -289,7 +289,7 @@ Target Var(TARGET_AUTO_MODIFY_REG) Init(TARGET_AUTO_MODIFY_REG_DEFAULT)
Enable the use of pre/post modify with register displacement.
mmul32x16
-Target Report Mask(MULMAC_32BY16_SET)
+Target Mask(MULMAC_32BY16_SET)
Generate 32x16 multiply and mac instructions.
; the initializer is supposed to be: Init(REG_BR_PROB_BASE/2) ,
@@ -346,42 +346,42 @@ Expand adddi3 and subdi3 at rtl generation time into add.f / adc etc.
; Flags used by the assembler, but for which we define preprocessor
; macro symbols as well.
mcrc
-Target Report Warn(%qs is deprecated)
+Target Warn(%qs is deprecated)
Enable variable polynomial CRC extension.
mdsp-packa
-Target Report Warn(%qs is deprecated)
+Target Warn(%qs is deprecated)
Enable DSP 3.1 Pack A extensions.
mdvbf
-Target Report Warn(%qs is deprecated)
+Target Warn(%qs is deprecated)
Enable dual viterbi butterfly extension.
mmac-d16
-Target Report Undocumented Warn(%qs is deprecated)
+Target Undocumented Warn(%qs is deprecated)
mmac-24
-Target Report Undocumented Warn(%qs is deprecated)
+Target Undocumented Warn(%qs is deprecated)
mtelephony
-Target Report RejectNegative Warn(%qs is deprecated)
+Target RejectNegative Warn(%qs is deprecated)
Enable Dual and Single Operand Instructions for Telephony.
mxy
-Target Report
+Target
Enable XY Memory extension (DSP version 3).
; ARC700 4.10 extension instructions
mlock
-Target Report
+Target
Enable Locked Load/Store Conditional extension.
mswape
-Target Report
+Target
Enable swap byte ordering extension instruction.
mrtsc
-Target Report Warn(%qs is deprecated)
+Target Warn(%qs is deprecated)
Enable 64-bit Time-Stamp Counter extension instruction.
EB
@@ -402,7 +402,7 @@ Pass -marclinux_prof option through to linker.
;; lra is still unproven for ARC, so allow to fall back to reload with -mno-lra.
mlra
-Target Report Var(arc_lra_flag) Init(1) Save
+Target Var(arc_lra_flag) Init(1) Save
Use LRA instead of reload.
mlra-priority-none
@@ -426,11 +426,11 @@ multcost=
Target RejectNegative Joined
matomic
-Target Report Mask(ATOMIC)
+Target Mask(ATOMIC)
Enable atomic instructions.
mll64
-Target Report Mask(LL64)
+Target Mask(LL64)
Enable double load/store instructions for ARC HS.
mfpu=
@@ -484,15 +484,15 @@ mtp-regno=none
Target RejectNegative Var(arc_tp_regno,-1)
mbitops
-Target Report Var(TARGET_NPS_BITOPS) Init(TARGET_NPS_BITOPS_DEFAULT)
+Target Var(TARGET_NPS_BITOPS) Init(TARGET_NPS_BITOPS_DEFAULT)
Enable use of NPS400 bit operations.
mcmem
-Target Report Var(TARGET_NPS_CMEM) Init(TARGET_NPS_CMEM_DEFAULT)
+Target Var(TARGET_NPS_CMEM) Init(TARGET_NPS_CMEM_DEFAULT)
Enable use of NPS400 xld/xst extension.
munaligned-access
-Target Report Var(unaligned_access) Init(UNALIGNED_ACCESS_DEFAULT)
+Target Var(unaligned_access) Init(UNALIGNED_ACCESS_DEFAULT)
Enable unaligned word and halfword accesses to packed data.
mirq-ctrl-saved=
@@ -529,13 +529,13 @@ EnumValue
Enum(arc_lpc) String(32) Value(32)
mrf16
-Target Report Mask(RF16)
+Target Mask(RF16)
Enable 16-entry register file.
mbranch-index
-Target Report Var(TARGET_BRANCH_INDEX) Init(DEFAULT_BRANCH_INDEX)
+Target Var(TARGET_BRANCH_INDEX) Init(DEFAULT_BRANCH_INDEX)
Enable use of BI/BIH instructions when available.
mcode-density-frame
-Target Report Var(TARGET_CODE_DENSITY_FRAME) Init(TARGET_CODE_DENSITY_FRAME_DEFAULT)
+Target Var(TARGET_CODE_DENSITY_FRAME) Init(TARGET_CODE_DENSITY_FRAME_DEFAULT)
Enable ENTER_S and LEAVE_S opcodes for ARCv2.
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index b7a563a..a2a8e84 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -493,6 +493,11 @@
Condition Codes"
(and (match_code "reg") (match_test "cc_register (op, VOIDmode)")))
+(define_constraint "Ral"
+ "@internal
+ Accumulator register @code{ACCL} - do not reload into its class"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == ACCL_REGNO")))
(define_constraint "Q"
"@internal
diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
index 0e88b3dd8..58651b5 100644
--- a/gcc/config/arc/simdext.md
+++ b/gcc/config/arc/simdext.md
@@ -1400,8 +1400,7 @@
(define_insn_and_split "*mov<mode>_insn"
[(set (match_operand:VWH 0 "move_dest_operand" "=r,r,r,m")
(match_operand:VWH 1 "general_operand" "i,r,m,r"))]
- "TARGET_PLUS_QMACW
- && (register_operand (operands[0], <MODE>mode)
+ "(register_operand (operands[0], <MODE>mode)
|| register_operand (operands[1], <MODE>mode))"
"*
{
@@ -1411,7 +1410,11 @@
return \"#\";
case 1:
- return \"vadd2 %0, %1, 0\";
+ if (TARGET_PLUS_QMACW
+ && even_register_operand (operands[0], <MODE>mode)
+ && even_register_operand (operands[1], <MODE>mode))
+ return \"vadd2%?\\t%0,%1,0\";
+ return \"#\";
case 2:
if (TARGET_LL64)
@@ -1430,8 +1433,8 @@
arc_split_move (operands);
DONE;
}
- [(set_attr "type" "move,move,load,store")
- (set_attr "predicable" "yes,no,no,no")
+ [(set_attr "type" "move,multi,load,store")
+ (set_attr "predicable" "no,no,no,no")
(set_attr "iscompact" "false,false,false,false")
])
@@ -1612,6 +1615,44 @@
DONE;
})
+(define_expand "sdot_prodv4hi"
+ [(match_operand:V2SI 0 "register_operand" "")
+ (match_operand:V4HI 1 "register_operand" "")
+ (match_operand:V4HI 2 "register_operand" "")
+ (match_operand:V2SI 3 "register_operand" "")]
+ "TARGET_PLUS_MACD"
+{
+ rtx acc_reg = gen_rtx_REG (V2SImode, ACC_REG_FIRST);
+ rtx op1_low = gen_lowpart (V2HImode, operands[1]);
+ rtx op1_high = gen_highpart (V2HImode, operands[1]);
+ rtx op2_low = gen_lowpart (V2HImode, operands[2]);
+ rtx op2_high = gen_highpart (V2HImode, operands[2]);
+
+ emit_move_insn (acc_reg, operands[3]);
+ emit_insn (gen_arc_vec_smac_v2hiv2si_zero (op1_low, op2_low));
+ emit_insn (gen_arc_vec_smac_v2hiv2si (operands[0], op1_high, op2_high));
+ DONE;
+})
+
+(define_expand "udot_prodv4hi"
+ [(match_operand:V2SI 0 "register_operand" "")
+ (match_operand:V4HI 1 "register_operand" "")
+ (match_operand:V4HI 2 "register_operand" "")
+ (match_operand:V2SI 3 "register_operand" "")]
+ "TARGET_PLUS_MACD"
+{
+ rtx acc_reg = gen_rtx_REG (V2SImode, ACC_REG_FIRST);
+ rtx op1_low = gen_lowpart (V2HImode, operands[1]);
+ rtx op1_high = gen_highpart (V2HImode, operands[1]);
+ rtx op2_low = gen_lowpart (V2HImode, operands[2]);
+ rtx op2_high = gen_highpart (V2HImode, operands[2]);
+
+ emit_move_insn (acc_reg, operands[3]);
+ emit_insn (gen_arc_vec_umac_v2hiv2si_zero (op1_low, op2_low));
+ emit_insn (gen_arc_vec_umac_v2hiv2si (operands[0], op1_high, op2_high));
+ DONE;
+})
+
(define_insn "arc_vec_<V_US>mult_lo_v4hi"
[(set (match_operand:V2SI 0 "even_register_operand" "=r,r")
(mult:V2SI (SE:V2SI (vec_select:V2HI
@@ -1704,30 +1745,37 @@
}
)
-(define_insn "arc_vec_<V_US>mac_hi_v4hi"
- [(set (match_operand:V2SI 0 "even_register_operand" "=r,r")
+(define_insn "arc_vec_<V_US>mac_v2hiv2si"
+ [(set (match_operand:V2SI 0 "even_register_operand" "=r,Ral,r")
(plus:V2SI
- (reg:V2SI ARCV2_ACC)
- (mult:V2SI (SE:V2SI (vec_select:V2HI
- (match_operand:V4HI 1 "even_register_operand" "0,r")
- (parallel [(const_int 2) (const_int 3)])))
- (SE:V2SI (vec_select:V2HI
- (match_operand:V4HI 2 "even_register_operand" "r,r")
- (parallel [(const_int 2) (const_int 3)]))))))
+ (mult:V2SI (SE:V2SI (match_operand:V2HI 1 "register_operand" "0, r,r"))
+ (SE:V2SI (match_operand:V2HI 2 "register_operand" "r, r,r")))
+ (reg:V2SI ARCV2_ACC)))
(set (reg:V2SI ARCV2_ACC)
(plus:V2SI
- (reg:V2SI ARCV2_ACC)
- (mult:V2SI (SE:V2SI (vec_select:V2HI (match_dup 1)
- (parallel [(const_int 2) (const_int 3)])))
- (SE:V2SI (vec_select:V2HI (match_dup 2)
- (parallel [(const_int 2) (const_int 3)]))))))
+ (mult:V2SI (SE:V2SI (match_dup 1))
+ (SE:V2SI (match_dup 2)))
+ (reg:V2SI ARCV2_ACC)))
]
"TARGET_PLUS_MACD"
- "vmac2h<V_US_suffix>%? %0, %R1, %R2"
+ "@
+ vmac2h<V_US_suffix>%?\\t%0,%1,%2
+ vmac2h<V_US_suffix>%?\\t0,%1,%2
+ vmac2h<V_US_suffix>%?\\t%0,%1,%2"
[(set_attr "length" "4")
(set_attr "type" "multi")
- (set_attr "predicable" "yes,no")
- (set_attr "cond" "canuse,nocond")])
+ (set_attr "predicable" "yes,no,no")])
+
+(define_insn "arc_vec_<V_US>mac_v2hiv2si_zero"
+ [(set (reg:V2SI ARCV2_ACC)
+ (plus:V2SI
+ (mult:V2SI (SE:V2SI (match_operand:V2HI 0 "register_operand" "r"))
+ (SE:V2SI (match_operand:V2HI 1 "register_operand" "r")))
+ (reg:V2SI ARCV2_ACC)))]
+ "TARGET_PLUS_MACD"
+ "vmac2h<V_US_suffix>%?\\t0,%0,%1"
+ [(set_attr "length" "4")
+ (set_attr "type" "multi")])
;; Builtins
(define_insn "dmach"
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index 6bc6ccf..e7b13f0 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -485,7 +485,7 @@ aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer)
return 0;
}
- if (GET_CODE (accumulator) == SUBREG)
+ if (SUBREG_P (accumulator))
accumulator = SUBREG_REG (accumulator);
if (!REG_P (accumulator))
diff --git a/gcc/config/arm/aarch-cost-tables.h b/gcc/config/arm/aarch-cost-tables.h
index cf81865..1b9d53d 100644
--- a/gcc/config/arm/aarch-cost-tables.h
+++ b/gcc/config/arm/aarch-cost-tables.h
@@ -331,6 +331,109 @@ const struct cpu_cost_table cortexa57_extra_costs =
}
};
+const struct cpu_cost_table cortexa76_extra_costs =
+{
+ /* ALU */
+ {
+ 0, /* arith. */
+ 0, /* logical. */
+ 0, /* shift. */
+ 0, /* shift_reg. */
+ COSTS_N_INSNS (1), /* arith_shift. */
+ COSTS_N_INSNS (1), /* arith_shift_reg. */
+ 0, /* log_shift. */
+ COSTS_N_INSNS (1), /* log_shift_reg. */
+ 0, /* extend. */
+ COSTS_N_INSNS (1), /* extend_arith. */
+ COSTS_N_INSNS (1), /* bfi. */
+ 0, /* bfx. */
+ 0, /* clz. */
+ 0, /* rev. */
+ 0, /* non_exec. */
+ true /* non_exec_costs_exec. */
+ },
+ {
+ /* MULT SImode */
+ {
+ COSTS_N_INSNS (1), /* simple. */
+ COSTS_N_INSNS (2), /* flag_setting. */
+ COSTS_N_INSNS (1), /* extend. */
+ COSTS_N_INSNS (1), /* add. */
+ COSTS_N_INSNS (1), /* extend_add. */
+ COSTS_N_INSNS (6) /* idiv. */
+ },
+ /* MULT DImode */
+ {
+ COSTS_N_INSNS (3), /* simple. */
+ 0, /* flag_setting (N/A). */
+ COSTS_N_INSNS (1), /* extend. */
+ COSTS_N_INSNS (3), /* add. */
+ COSTS_N_INSNS (1), /* extend_add. */
+ COSTS_N_INSNS (10) /* idiv. */
+ }
+ },
+ /* LD/ST */
+ {
+ COSTS_N_INSNS (3), /* load. */
+ COSTS_N_INSNS (3), /* load_sign_extend. */
+ COSTS_N_INSNS (3), /* ldrd. */
+ COSTS_N_INSNS (2), /* ldm_1st. */
+ 1, /* ldm_regs_per_insn_1st. */
+ 2, /* ldm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (4), /* loadf. */
+ COSTS_N_INSNS (4), /* loadd. */
+ COSTS_N_INSNS (5), /* load_unaligned. */
+ 0, /* store. */
+ 0, /* strd. */
+ 0, /* stm_1st. */
+ 1, /* stm_regs_per_insn_1st. */
+ 2, /* stm_regs_per_insn_subsequent. */
+ 0, /* storef. */
+ 0, /* stored. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
+ },
+ {
+ /* FP SFmode */
+ {
+ COSTS_N_INSNS (10), /* div. */
+ COSTS_N_INSNS (2), /* mult. */
+ COSTS_N_INSNS (3), /* mult_addsub. */
+ COSTS_N_INSNS (3), /* fma. */
+ COSTS_N_INSNS (1), /* addsub. */
+ 0, /* fpconst. */
+ 0, /* neg. */
+ 0, /* compare. */
+ COSTS_N_INSNS (1), /* widen. */
+ COSTS_N_INSNS (1), /* narrow. */
+ COSTS_N_INSNS (1), /* toint. */
+ COSTS_N_INSNS (1), /* fromint. */
+ COSTS_N_INSNS (1) /* roundint. */
+ },
+ /* FP DFmode */
+ {
+ COSTS_N_INSNS (15), /* div. */
+ COSTS_N_INSNS (2), /* mult. */
+ COSTS_N_INSNS (3), /* mult_addsub. */
+ COSTS_N_INSNS (3), /* fma. */
+ COSTS_N_INSNS (1), /* addsub. */
+ 0, /* fpconst. */
+ 0, /* neg. */
+ 0, /* compare. */
+ COSTS_N_INSNS (1), /* widen. */
+ COSTS_N_INSNS (1), /* narrow. */
+ COSTS_N_INSNS (1), /* toint. */
+ COSTS_N_INSNS (1), /* fromint. */
+ COSTS_N_INSNS (1) /* roundint. */
+ }
+ },
+ /* Vector */
+ {
+ COSTS_N_INSNS (1) /* alu. */
+ }
+};
+
const struct cpu_cost_table exynosm1_extra_costs =
{
/* ALU */
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index db505a4..51e3180 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -946,6 +946,9 @@ typedef struct {
#define VAR13(T, N, A, B, C, D, E, F, G, H, I, J, K, L, M) \
VAR12 (T, N, A, B, C, D, E, F, G, H, I, J, K, L) \
VAR1 (T, N, M)
+#define VAR14(T, N, A, B, C, D, E, F, G, H, I, J, K, L, M, O) \
+ VAR13 (T, N, A, B, C, D, E, F, G, H, I, J, K, L, M) \
+ VAR1 (T, N, O)
/* The builtin data can be found in arm_neon_builtins.def, arm_vfp_builtins.def
and arm_acle_builtins.def. The entries in arm_neon_builtins.def require
diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
index 8c61ad0..896948f 100644
--- a/gcc/config/arm/arm-cpus.in
+++ b/gcc/config/arm/arm-cpus.in
@@ -1477,6 +1477,17 @@ begin cpu cortex-a78ae
part d42
end cpu cortex-a78ae
+begin cpu cortex-a78c
+ cname cortexa78c
+ tune for cortex-a57
+ tune flags LDSCHED
+ architecture armv8.2-a+fp16+dotprod
+ option crypto add FP_ARMv8 CRYPTO
+ costs cortex_a57
+ vendor 41
+ part d4b
+end cpu cortex-a78c
+
begin cpu cortex-x1
cname cortexx1
tune for cortex-a57
diff --git a/gcc/config/arm/arm-fixed.md b/gcc/config/arm/arm-fixed.md
index c8ebf1b..ee18eee 100644
--- a/gcc/config/arm/arm-fixed.md
+++ b/gcc/config/arm/arm-fixed.md
@@ -482,7 +482,7 @@
"ssat%?\\t%0, #16, %2%S1"
[(set_attr "predicable" "yes")
(set_attr "shift" "1")
- (set_attr "type" "alu_shift_imm")])
+ (set_attr "autodetect_type" "alu_shift_operator1")])
(define_insn "arm_usatsihi"
[(set (match_operand:HI 0 "s_register_operand" "=r")
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 703d616..1ba318a 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -74,7 +74,8 @@ extern bool arm_small_register_classes_for_mode_p (machine_mode);
extern int const_ok_for_arm (HOST_WIDE_INT);
extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
-extern void thumb1_gen_const_int (rtx, HOST_WIDE_INT);
+extern void thumb1_gen_const_int_rtl (rtx, HOST_WIDE_INT);
+extern void thumb1_gen_const_int_print (rtx, HOST_WIDE_INT);
extern int arm_split_constant (RTX_CODE, machine_mode, rtx,
HOST_WIDE_INT, rtx, rtx, int);
extern int legitimate_pic_operand_p (rtx);
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index 05f5c08..8637933 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -247,6 +247,9 @@ EnumValue
Enum(processor_type) String(cortex-a78ae) Value( TARGET_CPU_cortexa78ae)
EnumValue
+Enum(processor_type) String(cortex-a78c) Value( TARGET_CPU_cortexa78c)
+
+EnumValue
Enum(processor_type) String(cortex-x1) Value( TARGET_CPU_cortexx1)
EnumValue
diff --git a/gcc/config/arm/arm-tune.md b/gcc/config/arm/arm-tune.md
index 32657da..e10d73e 100644
--- a/gcc/config/arm/arm-tune.md
+++ b/gcc/config/arm/arm-tune.md
@@ -45,9 +45,9 @@
cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,
cortexa73cortexa53,cortexa55,cortexa75,
cortexa76,cortexa76ae,cortexa77,
- cortexa78,cortexa78ae,cortexx1,
- neoversen1,cortexa75cortexa55,cortexa76cortexa55,
- neoversev1,neoversen2,cortexm23,
- cortexm33,cortexm35p,cortexm55,
- cortexr52"
+ cortexa78,cortexa78ae,cortexa78c,
+ cortexx1,neoversen1,cortexa75cortexa55,
+ cortexa76cortexa55,neoversev1,neoversen2,
+ cortexm23,cortexm33,cortexm35p,
+ cortexm55,cortexr52"
(const (symbol_ref "((enum attr_tune) arm_tune)")))
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index dfadaca..11bec2a 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4170,9 +4170,10 @@ arm_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
}
a_tramp = XEXP (m_tramp, 0);
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
- LCT_NORMAL, VOIDmode, a_tramp, Pmode,
- plus_constant (Pmode, a_tramp, TRAMPOLINE_SIZE), Pmode);
+ maybe_emit_call_builtin___clear_cache (a_tramp,
+ plus_constant (ptr_mode,
+ a_tramp,
+ TRAMPOLINE_SIZE));
}
/* Thumb trampolines should be entered in thumb mode, so set
@@ -4528,38 +4529,6 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code)
}
}
-/* Emit a sequence of movs/adds/shift to produce a 32-bit constant.
- Avoid generating useless code when one of the bytes is zero. */
-void
-thumb1_gen_const_int (rtx op0, HOST_WIDE_INT op1)
-{
- bool mov_done_p = false;
- int i;
-
- /* Emit upper 3 bytes if needed. */
- for (i = 0; i < 3; i++)
- {
- int byte = (op1 >> (8 * (3 - i))) & 0xff;
-
- if (byte)
- {
- emit_set_insn (op0, mov_done_p
- ? gen_rtx_PLUS (SImode,op0, GEN_INT (byte))
- : GEN_INT (byte));
- mov_done_p = true;
- }
-
- if (mov_done_p)
- emit_set_insn (op0, gen_rtx_ASHIFT (SImode, op0, GEN_INT (8)));
- }
-
- /* Emit lower byte if needed. */
- if (!mov_done_p)
- emit_set_insn (op0, GEN_INT (op1 & 0xff));
- else if (op1 & 0xff)
- emit_set_insn (op0, gen_rtx_PLUS (SImode, op0, GEN_INT (op1 & 0xff)));
-}
-
/* Emit a sequence of insns to handle a large constant.
CODE is the code of the operation required, it can be any of SET, PLUS,
IOR, AND, XOR, MINUS;
@@ -7807,7 +7776,7 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
int
legitimate_pic_operand_p (rtx x)
{
- if (GET_CODE (x) == SYMBOL_REF
+ if (SYMBOL_REF_P (x)
|| (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
@@ -7936,8 +7905,8 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg, rtx pic_reg,
{
gcc_assert (compute_now == (pic_reg != NULL_RTX));
- if (GET_CODE (orig) == SYMBOL_REF
- || GET_CODE (orig) == LABEL_REF)
+ if (SYMBOL_REF_P (orig)
+ || LABEL_REF_P (orig))
{
if (reg == 0)
{
@@ -7954,8 +7923,8 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg, rtx pic_reg,
/* References to weak symbols cannot be resolved locally: they
may be overridden by a non-weak definition at link time. */
rtx_insn *insn;
- if ((GET_CODE (orig) == LABEL_REF
- || (GET_CODE (orig) == SYMBOL_REF
+ if ((LABEL_REF_P (orig)
+ || (SYMBOL_REF_P (orig)
&& SYMBOL_REF_LOCAL_P (orig)
&& (SYMBOL_REF_DECL (orig)
? !DECL_WEAK (SYMBOL_REF_DECL (orig)) : 1)
@@ -8209,7 +8178,7 @@ arm_is_segment_info_known (rtx orig, bool *is_readonly)
{
*is_readonly = false;
- if (GET_CODE (orig) == LABEL_REF)
+ if (LABEL_REF_P (orig))
{
*is_readonly = true;
return true;
@@ -8469,7 +8438,7 @@ can_avoid_literal_pool_for_label_p (rtx x)
(set (reg r0) (mem (reg r0))).
No extra register is required, and (mem (reg r0)) won't cause the use
of literal pools. */
- if (arm_disable_literal_pool && GET_CODE (x) == SYMBOL_REF
+ if (arm_disable_literal_pool && SYMBOL_REF_P (x)
&& CONSTANT_POOL_ADDRESS_P (x))
return 1;
return 0;
@@ -8848,7 +8817,7 @@ thumb1_legitimate_address_p (machine_mode mode, rtx x, int strict_p)
/* This is PC relative data before arm_reorg runs. */
else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
- && GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_P (x)
&& CONSTANT_POOL_ADDRESS_P (x) && !flag_pic
&& !arm_disable_literal_pool)
return 1;
@@ -8856,7 +8825,7 @@ thumb1_legitimate_address_p (machine_mode mode, rtx x, int strict_p)
/* This is PC relative data after arm_reorg runs. */
else if ((GET_MODE_SIZE (mode) >= 4 || mode == HFmode)
&& reload_completed
- && (GET_CODE (x) == LABEL_REF
+ && (LABEL_REF_P (x)
|| (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
@@ -8916,7 +8885,7 @@ thumb1_legitimate_address_p (machine_mode mode, rtx x, int strict_p)
else if (GET_MODE_CLASS (mode) != MODE_FLOAT
&& GET_MODE_SIZE (mode) == 4
- && GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_P (x)
&& CONSTANT_POOL_ADDRESS_P (x)
&& !arm_disable_literal_pool
&& ! (flag_pic
@@ -9244,7 +9213,7 @@ arm_legitimize_address (rtx x, rtx orig_x, machine_mode mode)
x = XEXP (XEXP (x, 0), 0);
}
- if (GET_CODE (x) != SYMBOL_REF)
+ if (!SYMBOL_REF_P (x))
return x;
gcc_assert (SYMBOL_REF_TLS_MODEL (x) != 0);
@@ -9453,7 +9422,7 @@ arm_tls_referenced_p (rtx x)
FOR_EACH_SUBRTX (iter, array, x, ALL)
{
const_rtx x = *iter;
- if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0)
+ if (SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0)
{
/* ARM currently does not provide relocations to encode TLS variables
into AArch32 instructions, only data, so there is no way to
@@ -9499,7 +9468,14 @@ thumb_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
return (CONST_INT_P (x)
|| CONST_DOUBLE_P (x)
|| CONSTANT_ADDRESS_P (x)
- || (TARGET_HAVE_MOVT && GET_CODE (x) == SYMBOL_REF)
+ || (TARGET_HAVE_MOVT && SYMBOL_REF_P (x))
+ /* On Thumb-1 without MOVT/MOVW and literal pool disabled,
+ we build the symbol address with upper/lower
+ relocations. */
+ || (TARGET_THUMB1
+ && !label_mentioned_p (x)
+ && arm_valid_symbolic_address_p (x)
+ && arm_disable_literal_pool)
|| flag_pic);
}
@@ -9536,7 +9512,7 @@ arm_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
#define REG_OR_SUBREG_REG(X) \
(REG_P (X) \
- || (GET_CODE (X) == SUBREG && REG_P (SUBREG_REG (X))))
+ || (SUBREG_P (X) && REG_P (SUBREG_REG (X))))
#define REG_OR_SUBREG_RTX(X) \
(REG_P (X) ? (X) : SUBREG_REG (X))
@@ -9647,7 +9623,7 @@ thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
/* Memory costs quite a lot for the first word, but subsequent words
load at the equivalent of a single insn each. */
return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ + ((SYMBOL_REF_P (x) && CONSTANT_POOL_ADDRESS_P (x))
? 4 : 0));
case IF_THEN_ELSE:
@@ -9804,7 +9780,7 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
return (COSTS_N_INSNS (1)
+ COSTS_N_INSNS (1)
* ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ + ((SYMBOL_REF_P (x) && CONSTANT_POOL_ADDRESS_P (x))
? COSTS_N_INSNS (1) : 0));
case IF_THEN_ELSE:
@@ -11913,7 +11889,8 @@ xscale_sched_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep,
instruction we depend on is another ALU instruction, then we may
have to account for an additional stall. */
if (shift_opnum != 0
- && (attr_type == TYPE_ALU_SHIFT_IMM
+ && (attr_type == TYPE_ALU_SHIFT_IMM_LSL_1TO4
+ || attr_type == TYPE_ALU_SHIFT_IMM_OTHER
|| attr_type == TYPE_ALUS_SHIFT_IMM
|| attr_type == TYPE_LOGIC_SHIFT_IMM
|| attr_type == TYPE_LOGICS_SHIFT_IMM
@@ -12424,7 +12401,7 @@ arm_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep, int cost,
constant pool are cached, and that others will miss. This is a
hack. */
- if ((GET_CODE (src_mem) == SYMBOL_REF
+ if ((SYMBOL_REF_P (src_mem)
&& CONSTANT_POOL_ADDRESS_P (src_mem))
|| reg_mentioned_p (stack_pointer_rtx, src_mem)
|| reg_mentioned_p (frame_pointer_rtx, src_mem)
@@ -13259,7 +13236,7 @@ arm_coproc_mem_operand_wb (rtx op, int wb_level)
ind = XEXP (op, 0);
if (reload_completed
- && (GET_CODE (ind) == LABEL_REF
+ && (LABEL_REF_P (ind)
|| (GET_CODE (ind) == CONST
&& GET_CODE (XEXP (ind, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
@@ -13435,7 +13412,7 @@ neon_vector_mem_operand (rtx op, int type, bool strict)
ind = XEXP (op, 0);
if (reload_completed
- && (GET_CODE (ind) == LABEL_REF
+ && (LABEL_REF_P (ind)
|| (GET_CODE (ind) == CONST
&& GET_CODE (XEXP (ind, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
@@ -13454,7 +13431,9 @@ neon_vector_mem_operand (rtx op, int type, bool strict)
/* Allow post-increment by register for VLDn */
if (type == 2 && GET_CODE (ind) == POST_MODIFY
&& GET_CODE (XEXP (ind, 1)) == PLUS
- && REG_P (XEXP (XEXP (ind, 1), 1)))
+ && REG_P (XEXP (XEXP (ind, 1), 1))
+ && REG_P (XEXP (ind, 0))
+ && rtx_equal_p (XEXP (ind, 0), XEXP (XEXP (ind, 1), 0)))
return true;
/* Match:
@@ -13501,7 +13480,7 @@ neon_struct_mem_operand (rtx op)
ind = XEXP (op, 0);
if (reload_completed
- && (GET_CODE (ind) == LABEL_REF
+ && (LABEL_REF_P (ind)
|| (GET_CODE (ind) == CONST
&& GET_CODE (XEXP (ind, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
@@ -13617,7 +13596,7 @@ symbol_mentioned_p (rtx x)
const char * fmt;
int i;
- if (GET_CODE (x) == SYMBOL_REF)
+ if (SYMBOL_REF_P (x))
return 1;
/* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
@@ -13651,7 +13630,7 @@ label_mentioned_p (rtx x)
const char * fmt;
int i;
- if (GET_CODE (x) == LABEL_REF)
+ if (LABEL_REF_P (x))
return 1;
/* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
@@ -14289,11 +14268,11 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
offset = const0_rtx;
if ((REG_P (reg = XEXP (operands[nops + i], 0))
- || (GET_CODE (reg) == SUBREG
+ || (SUBREG_P (reg)
&& REG_P (reg = SUBREG_REG (reg))))
|| (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
&& ((REG_P (reg = XEXP (XEXP (operands[nops + i], 0), 0)))
- || (GET_CODE (reg) == SUBREG
+ || (SUBREG_P (reg)
&& REG_P (reg = SUBREG_REG (reg))))
&& (CONST_INT_P (offset
= XEXP (XEXP (operands[nops + i], 0), 1)))))
@@ -14443,11 +14422,11 @@ store_multiple_sequence (rtx *operands, int nops, int nops_total,
offset = const0_rtx;
if ((REG_P (reg = XEXP (operands[nops + i], 0))
- || (GET_CODE (reg) == SUBREG
+ || (SUBREG_P (reg)
&& REG_P (reg = SUBREG_REG (reg))))
|| (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
&& ((REG_P (reg = XEXP (XEXP (operands[nops + i], 0), 0)))
- || (GET_CODE (reg) == SUBREG
+ || (SUBREG_P (reg)
&& REG_P (reg = SUBREG_REG (reg))))
&& (CONST_INT_P (offset
= XEXP (XEXP (operands[nops + i], 0), 1)))))
@@ -15777,7 +15756,7 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
/* A compare with a shifted operand. Because of canonicalization, the
comparison will have to be swapped when we emit the assembler. */
if (GET_MODE (y) == SImode
- && (REG_P (y) || (GET_CODE (y) == SUBREG))
+ && (REG_P (y) || (SUBREG_P (y)))
&& (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
|| GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE
|| GET_CODE (x) == ROTATERT))
@@ -15801,14 +15780,14 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
non-canonical, but arm_gen_compare_reg uses this to generate the
correct canonical form. */
if (GET_MODE (y) == SImode
- && (REG_P (y) || GET_CODE (y) == SUBREG)
+ && (REG_P (y) || SUBREG_P (y))
&& CONST_INT_P (x))
return CC_RSBmode;
/* This operation is performed swapped, but since we only rely on the Z
flag we don't need an additional mode. */
if (GET_MODE (y) == SImode
- && (REG_P (y) || (GET_CODE (y) == SUBREG))
+ && (REG_P (y) || (SUBREG_P (y)))
&& GET_CODE (x) == NEG
&& (op == EQ || op == NE))
return CC_Zmode;
@@ -16200,7 +16179,7 @@ arm_reload_in_hi (rtx *operands)
rtx base, scratch;
HOST_WIDE_INT offset = 0;
- if (GET_CODE (ref) == SUBREG)
+ if (SUBREG_P (ref))
{
offset = SUBREG_BYTE (ref);
ref = SUBREG_REG (ref);
@@ -16328,7 +16307,7 @@ arm_reload_out_hi (rtx *operands)
rtx base, scratch;
HOST_WIDE_INT offset = 0;
- if (GET_CODE (ref) == SUBREG)
+ if (SUBREG_P (ref))
{
offset = SUBREG_BYTE (ref);
ref = SUBREG_REG (ref);
@@ -16659,7 +16638,7 @@ mem_ok_for_ldrd_strd (rtx mem, rtx *base, rtx *offset, HOST_WIDE_INT *align)
return false;
/* Can't deal with subregs. */
- if (GET_CODE (mem) == SUBREG)
+ if (SUBREG_P (mem))
return false;
gcc_assert (MEM_P (mem));
@@ -19559,7 +19538,7 @@ arm_emit_call_insn (rtx pat, rtx addr, bool sibcall)
if (TARGET_VXWORKS_RTP
&& flag_pic
&& !sibcall
- && GET_CODE (addr) == SYMBOL_REF
+ && SYMBOL_REF_P (addr)
&& (SYMBOL_REF_DECL (addr)
? !targetm.binds_local_p (SYMBOL_REF_DECL (addr))
: !SYMBOL_REF_LOCAL_P (addr)))
@@ -20406,7 +20385,7 @@ output_move_neon (rtx *operands)
}
else
{
- if (TARGET_HAVE_MVE && GET_CODE (addr) == LABEL_REF)
+ if (TARGET_HAVE_MVE && LABEL_REF_P (addr))
sprintf (buff, "v%sr.64\t%%P0, %%1", load ? "ld" : "st");
else
sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st");
@@ -20417,7 +20396,7 @@ output_move_neon (rtx *operands)
{
ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * overlap);
ops[1] = adjust_address (mem, SImode, 8 * overlap);
- if (TARGET_HAVE_MVE && GET_CODE (addr) == LABEL_REF)
+ if (TARGET_HAVE_MVE && LABEL_REF_P (addr))
sprintf (buff, "v%sr.32\t%%P0, %%1", load ? "ld" : "st");
else
sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st");
@@ -20477,7 +20456,7 @@ arm_attr_length_move_neon (rtx_insn *insn)
if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS)
addr = XEXP (addr, 0);
- if (GET_CODE (addr) == LABEL_REF || GET_CODE (addr) == PLUS)
+ if (LABEL_REF_P (addr) || GET_CODE (addr) == PLUS)
{
int insns = REG_NREGS (reg) / 2;
return insns * 4;
@@ -24471,7 +24450,7 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
/* Mark symbols as position independent. We only do this in the
.text segment, not in the .data segment. */
if (NEED_GOT_RELOC && flag_pic && making_const_table &&
- (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
+ (SYMBOL_REF_P (x) || LABEL_REF_P (x)))
{
/* See legitimize_pic_address for an explanation of the
TARGET_VXWORKS_RTP check. */
@@ -24479,7 +24458,7 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
they may be overridden by a non-weak definition at link
time. */
if (!arm_pic_data_is_text_relative
- || (GET_CODE (x) == SYMBOL_REF
+ || (SYMBOL_REF_P (x)
&& (!SYMBOL_REF_LOCAL_P (x)
|| (SYMBOL_REF_DECL (x)
? DECL_WEAK (SYMBOL_REF_DECL (x)) : 0)
@@ -28256,6 +28235,205 @@ arm_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
default_internal_label (stream, prefix, labelno);
}
+/* Define classes to generate code as RTL or output asm to a file.
+ Using templates then allows to use the same code to output code
+ sequences in the two formats. */
+class thumb1_const_rtl
+{
+ public:
+ thumb1_const_rtl (rtx dst) : dst (dst) {}
+
+ void mov (HOST_WIDE_INT val)
+ {
+ emit_set_insn (dst, GEN_INT (val));
+ }
+
+ void add (HOST_WIDE_INT val)
+ {
+ emit_set_insn (dst, gen_rtx_PLUS (SImode, dst, GEN_INT (val)));
+ }
+
+ void ashift (HOST_WIDE_INT shift)
+ {
+ emit_set_insn (dst, gen_rtx_ASHIFT (SImode, dst, GEN_INT (shift)));
+ }
+
+ void neg ()
+ {
+ emit_set_insn (dst, gen_rtx_NEG (SImode, dst));
+ }
+
+ private:
+ rtx dst;
+};
+
+class thumb1_const_print
+{
+ public:
+ thumb1_const_print (FILE *f, int regno)
+ {
+ t_file = f;
+ dst_regname = reg_names[regno];
+ }
+
+ void mov (HOST_WIDE_INT val)
+ {
+ asm_fprintf (t_file, "\tmovs\t%s, #" HOST_WIDE_INT_PRINT_DEC "\n",
+ dst_regname, val);
+ }
+
+ void add (HOST_WIDE_INT val)
+ {
+ asm_fprintf (t_file, "\tadds\t%s, #" HOST_WIDE_INT_PRINT_DEC "\n",
+ dst_regname, val);
+ }
+
+ void ashift (HOST_WIDE_INT shift)
+ {
+ asm_fprintf (t_file, "\tlsls\t%s, #" HOST_WIDE_INT_PRINT_DEC "\n",
+ dst_regname, shift);
+ }
+
+ void neg ()
+ {
+ asm_fprintf (t_file, "\trsbs\t%s, #0\n", dst_regname);
+ }
+
+ private:
+ FILE *t_file;
+ const char *dst_regname;
+};
+
+/* Emit a sequence of movs/adds/shift to produce a 32-bit constant.
+ Avoid generating useless code when one of the bytes is zero. */
+template <class T>
+void
+thumb1_gen_const_int_1 (T dst, HOST_WIDE_INT op1)
+{
+ bool mov_done_p = false;
+ unsigned HOST_WIDE_INT val = op1;
+ int shift = 0;
+ int i;
+
+ gcc_assert (op1 == trunc_int_for_mode (op1, SImode));
+
+ if (val <= 255)
+ {
+ dst.mov (val);
+ return;
+ }
+
+ /* For negative numbers with the first nine bits set, build the
+ opposite of OP1, then negate it, it's generally shorter and not
+ longer. */
+ if ((val & 0xFF800000) == 0xFF800000)
+ {
+ thumb1_gen_const_int_1 (dst, -op1);
+ dst.neg ();
+ return;
+ }
+
+ /* In the general case, we need 7 instructions to build
+ a 32 bits constant (1 movs, 3 lsls, 3 adds). We can
+ do better if VAL is small enough, or
+ right-shiftable by a suitable amount. If the
+ right-shift enables to encode at least one less byte,
+ it's worth it: we save a adds and a lsls at the
+ expense of a final lsls. */
+ int final_shift = number_of_first_bit_set (val);
+
+ int leading_zeroes = clz_hwi (val);
+ int number_of_bytes_needed
+ = ((HOST_BITS_PER_WIDE_INT - 1 - leading_zeroes)
+ / BITS_PER_UNIT) + 1;
+ int number_of_bytes_needed2
+ = ((HOST_BITS_PER_WIDE_INT - 1 - leading_zeroes - final_shift)
+ / BITS_PER_UNIT) + 1;
+
+ if (number_of_bytes_needed2 < number_of_bytes_needed)
+ val >>= final_shift;
+ else
+ final_shift = 0;
+
+ /* If we are in a very small range, we can use either a single movs
+ or movs+adds. */
+ if (val <= 510)
+ {
+ if (val > 255)
+ {
+ unsigned HOST_WIDE_INT high = val - 255;
+
+ dst.mov (high);
+ dst.add (255);
+ }
+ else
+ dst.mov (val);
+
+ if (final_shift > 0)
+ dst.ashift (final_shift);
+ }
+ else
+ {
+ /* General case, emit upper 3 bytes as needed. */
+ for (i = 0; i < 3; i++)
+ {
+ unsigned HOST_WIDE_INT byte = (val >> (8 * (3 - i))) & 0xff;
+
+ if (byte)
+ {
+ /* We are about to emit new bits, stop accumulating a
+ shift amount, and left-shift only if we have already
+ emitted some upper bits. */
+ if (mov_done_p)
+ {
+ dst.ashift (shift);
+ dst.add (byte);
+ }
+ else
+ dst.mov (byte);
+
+ /* Stop accumulating shift amount since we've just
+ emitted some bits. */
+ shift = 0;
+
+ mov_done_p = true;
+ }
+
+ if (mov_done_p)
+ shift += 8;
+ }
+
+ /* Emit lower byte. */
+ if (!mov_done_p)
+ dst.mov (val & 0xff);
+ else
+ {
+ dst.ashift (shift);
+ if (val & 0xff)
+ dst.add (val & 0xff);
+ }
+
+ if (final_shift > 0)
+ dst.ashift (final_shift);
+ }
+}
+
+/* Proxies for thumb1.md, since the thumb1_const_print and
+ thumb1_const_rtl classes are not exported. */
+void
+thumb1_gen_const_int_rtl (rtx dst, HOST_WIDE_INT op1)
+{
+ thumb1_const_rtl t (dst);
+ thumb1_gen_const_int_1 (t, op1);
+}
+
+void
+thumb1_gen_const_int_print (rtx dst, HOST_WIDE_INT op1)
+{
+ thumb1_const_print t (asm_out_file, REGNO (dst));
+ thumb1_gen_const_int_1 (t, op1);
+}
+
/* Output code to add DELTA to the first argument, and then jump
to FUNCTION. Used for C++ multiple inheritance. */
@@ -28354,9 +28532,19 @@ arm_thumb1_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
{
if (mi_delta > 255)
{
- fputs ("\tldr\tr3, ", file);
- assemble_name (file, label);
- fputs ("+4\n", file);
+ /* With -mpure-code, we cannot load MI_DELTA from the
+ constant pool: we build it explicitly. */
+ if (target_pure_code)
+ {
+ thumb1_const_print r3 (file, 3);
+ thumb1_gen_const_int_1 (r3, mi_delta);
+ }
+ else
+ {
+ fputs ("\tldr\tr3, ", file);
+ assemble_name (file, label);
+ fputs ("+4\n", file);
+ }
asm_fprintf (file, "\t%ss\t%r, %r, r3\n",
mi_op, this_regno, this_regno);
}
@@ -28392,30 +28580,37 @@ arm_thumb1_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
fputs ("\tpop\t{r3}\n", file);
fprintf (file, "\tbx\tr12\n");
- ASM_OUTPUT_ALIGN (file, 2);
- assemble_name (file, label);
- fputs (":\n", file);
- if (flag_pic)
+
+ /* With -mpure-code, we don't need to emit literals for the
+ function address and delta since we emitted code to build
+ them. */
+ if (!target_pure_code)
{
- /* Output ".word .LTHUNKn-[3,7]-.LTHUNKPCn". */
- rtx tem = XEXP (DECL_RTL (function), 0);
- /* For TARGET_THUMB1_ONLY the thunk is in Thumb mode, so the PC
- pipeline offset is four rather than eight. Adjust the offset
- accordingly. */
- tem = plus_constant (GET_MODE (tem), tem,
- TARGET_THUMB1_ONLY ? -3 : -7);
- tem = gen_rtx_MINUS (GET_MODE (tem),
- tem,
- gen_rtx_SYMBOL_REF (Pmode,
- ggc_strdup (labelpc)));
- assemble_integer (tem, 4, BITS_PER_WORD, 1);
- }
- else
- /* Output ".word .LTHUNKn". */
- assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1);
+ ASM_OUTPUT_ALIGN (file, 2);
+ assemble_name (file, label);
+ fputs (":\n", file);
+ if (flag_pic)
+ {
+ /* Output ".word .LTHUNKn-[3,7]-.LTHUNKPCn". */
+ rtx tem = XEXP (DECL_RTL (function), 0);
+ /* For TARGET_THUMB1_ONLY the thunk is in Thumb mode, so the PC
+ pipeline offset is four rather than eight. Adjust the offset
+ accordingly. */
+ tem = plus_constant (GET_MODE (tem), tem,
+ TARGET_THUMB1_ONLY ? -3 : -7);
+ tem = gen_rtx_MINUS (GET_MODE (tem),
+ tem,
+ gen_rtx_SYMBOL_REF (Pmode,
+ ggc_strdup (labelpc)));
+ assemble_integer (tem, 4, BITS_PER_WORD, 1);
+ }
+ else
+ /* Output ".word .LTHUNKn". */
+ assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1);
- if (TARGET_THUMB1_ONLY && mi_delta > 255)
- assemble_integer (GEN_INT(mi_delta), 4, BITS_PER_WORD, 1);
+ if (TARGET_THUMB1_ONLY && mi_delta > 255)
+ assemble_integer (GEN_INT (mi_delta), 4, BITS_PER_WORD, 1);
+ }
}
else
{
@@ -28936,6 +29131,8 @@ arm_preferred_simd_mode (scalar_mode mode)
if (TARGET_NEON)
switch (mode)
{
+ case E_HFmode:
+ return TARGET_NEON_VECTORIZE_DOUBLE ? V4HFmode : V8HFmode;
case E_SFmode:
return TARGET_NEON_VECTORIZE_DOUBLE ? V2SFmode : V4SFmode;
case E_SImode:
@@ -30631,7 +30828,7 @@ arm_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
case MINUS:
if (CONST_INT_P (value))
{
- value = GEN_INT (-INTVAL (value));
+ value = gen_int_mode (-INTVAL (value), wmode);
code = PLUS;
}
/* FALLTHRU */
@@ -31429,13 +31626,13 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in,
gcc_assert (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
gcc_assert (out
- && (REG_P (out) || GET_CODE (out) == SUBREG)
+ && (REG_P (out) || SUBREG_P (out))
&& GET_MODE (out) == DImode);
gcc_assert (in
- && (REG_P (in) || GET_CODE (in) == SUBREG)
+ && (REG_P (in) || SUBREG_P (in))
&& GET_MODE (in) == DImode);
gcc_assert (amount
- && (((REG_P (amount) || GET_CODE (amount) == SUBREG)
+ && (((REG_P (amount) || SUBREG_P (amount))
&& GET_MODE (amount) == SImode)
|| CONST_INT_P (amount)));
gcc_assert (scratch1 == NULL
@@ -31653,7 +31850,12 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in,
According to the ARM ELF ABI, the initial addend of REL-type relocations
processing MOVW and MOVT instructions is formed by interpreting the 16-bit
literal field of the instruction as a 16-bit signed value in the range
- -32768 <= A < 32768. */
+ -32768 <= A < 32768.
+
+ In Thumb-1 mode, we use upper/lower relocations which have an 8-bit
+ unsigned range of 0 <= A < 256 as described in the AAELF32
+ relocation handling documentation: REL-type relocations are encoded
+ as unsigned in this case. */
bool
arm_valid_symbolic_address_p (rtx addr)
@@ -31664,7 +31866,7 @@ arm_valid_symbolic_address_p (rtx addr)
if (target_word_relocations)
return false;
- if (GET_CODE (tmp) == SYMBOL_REF || GET_CODE (tmp) == LABEL_REF)
+ if (SYMBOL_REF_P (tmp) || LABEL_REF_P (tmp))
return true;
/* (const (plus: symbol_ref const_int)) */
@@ -31677,7 +31879,12 @@ arm_valid_symbolic_address_p (rtx addr)
xop1 = XEXP (tmp, 1);
if (GET_CODE (xop0) == SYMBOL_REF && CONST_INT_P (xop1))
- return IN_RANGE (INTVAL (xop1), -0x8000, 0x7fff);
+ {
+ if (TARGET_THUMB1 && !TARGET_HAVE_MOVT)
+ return IN_RANGE (INTVAL (xop1), 0, 0xff);
+ else
+ return IN_RANGE (INTVAL (xop1), -0x8000, 0x7fff);
+ }
}
return false;
@@ -32942,7 +33149,7 @@ extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset)
if (GET_CODE (addr) == CONST)
addr = XEXP (addr, 0);
- if (GET_CODE (addr) == REG)
+ if (REG_P (addr))
{
*base = addr;
*offset = const0_rtx;
@@ -32981,12 +33188,12 @@ fusion_load_store (rtx_insn *insn, rtx *base, rtx *offset, bool *is_load)
src = SET_SRC (x);
dest = SET_DEST (x);
- if (GET_CODE (src) == REG && GET_CODE (dest) == MEM)
+ if (REG_P (src) && MEM_P (dest))
{
*is_load = false;
extract_base_offset_in_addr (dest, base, offset);
}
- else if (GET_CODE (src) == MEM && GET_CODE (dest) == REG)
+ else if (MEM_P (src) && REG_P (dest))
{
*is_load = true;
extract_base_offset_in_addr (src, base, offset);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 1a8e498..13b09c3 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -336,7 +336,8 @@
(define_attr "core_cycles" "single,multi"
(if_then_else (eq_attr "type"
"adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
- alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
+ alu_shift_imm_lsl_1to4, alu_shift_imm_other, alu_shift_reg, alu_dsp_reg,\
+ alus_ext, alus_imm, alus_sreg,\
alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
@@ -1370,7 +1371,7 @@
(set_attr "arch" "32,a")
(set_attr "shift" "3")
(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator2")]
)
(define_insn "*addsi3_carryin_clobercc"
@@ -1679,7 +1680,7 @@
[(set_attr "conds" "use")
(set_attr "arch" "*,a,t2")
(set_attr "predicable" "yes")
- (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
+ (set_attr "type" "adc_reg,adc_imm,alu_shift_imm_lsl_1to4")]
)
;; Special canonicalization of the above when operand1 == (const_int 1):
@@ -1727,7 +1728,7 @@
"rsc%?\\t%0, %4, %1%S3"
[(set_attr "conds" "use")
(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator3")]
)
(define_insn "cmpsi3_carryin_<CC_EXTEND>out"
@@ -1811,7 +1812,7 @@
(set_attr "arch" "32,a")
(set_attr "shift" "3")
(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator2")]
)
(define_insn "*subsi3_carryin_shift_alt"
@@ -1828,7 +1829,7 @@
(set_attr "arch" "32,a")
(set_attr "shift" "3")
(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator2")]
)
;; No RSC in Thumb2
@@ -1844,7 +1845,7 @@
"rsc%?\\t%0, %1, %3%S2"
[(set_attr "conds" "use")
(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator2")]
)
(define_insn "*rsbsi3_carryin_shift_alt"
@@ -1859,7 +1860,7 @@
"rsc%?\\t%0, %1, %3%S2"
[(set_attr "conds" "use")
(set_attr "predicable" "yes")
- (set_attr "type" "alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator2")]
)
; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
@@ -4646,7 +4647,7 @@
(set_attr "predicable_short_it" "yes,yes,no,no")
(set_attr "length" "4")
(set_attr "shift" "1")
- (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
+ (set_attr "autodetect_type" "alu_shift_operator3")]
)
(define_insn "*shiftsi3_compare0"
@@ -9503,7 +9504,7 @@
[(set_attr "predicable" "yes")
(set_attr "shift" "2")
(set_attr "arch" "a,t2")
- (set_attr "type" "alu_shift_imm")])
+ (set_attr "autodetect_type" "alu_shift_mul_op3")])
(define_insn "*<arith_shift_insn>_shiftsi"
[(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
@@ -9517,7 +9518,7 @@
[(set_attr "predicable" "yes")
(set_attr "shift" "3")
(set_attr "arch" "a,t2,a")
- (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
+ (set_attr "autodetect_type" "alu_shift_operator2")])
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
@@ -10856,7 +10857,9 @@
(set_attr "length" "4,8")
(set_attr_alternative "type"
[(if_then_else (match_operand 3 "const_int_operand" "")
- (const_string "alu_shift_imm" )
+ (if_then_else (match_operand 5 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other"))
(const_string "alu_shift_reg"))
(const_string "multiple")])]
)
@@ -10921,7 +10924,9 @@
(set_attr "length" "4,8")
(set_attr_alternative "type"
[(if_then_else (match_operand 3 "const_int_operand" "")
- (const_string "alu_shift_imm" )
+ (if_then_else (match_operand 5 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other"))
(const_string "alu_shift_reg"))
(const_string "multiple")])]
)
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index f01cd65..b849009 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -55,22 +55,22 @@ EnumValue
Enum(arm_abi_type) String(aapcs-linux) Value(ARM_ABI_AAPCS_LINUX)
mabort-on-noreturn
-Target Report Mask(ABORT_NORETURN)
+Target Mask(ABORT_NORETURN)
Generate a call to abort if a noreturn function returns.
mapcs
Target RejectNegative Mask(APCS_FRAME) Undocumented
mapcs-frame
-Target Report Mask(APCS_FRAME)
+Target Mask(APCS_FRAME)
Generate APCS conformant stack frames.
mapcs-reentrant
-Target Report Mask(APCS_REENT)
+Target Mask(APCS_REENT)
Generate re-entrant, PIC code.
mapcs-stack-check
-Target Report Mask(APCS_STACK) Undocumented
+Target Mask(APCS_STACK) Undocumented
march=
Target Save RejectNegative Negative(march=) ToLower Joined Var(arm_arch_string)
@@ -82,19 +82,19 @@ EnumValue
Enum(arm_arch) String(native) Value(-1) DriverOnly
marm
-Target Report RejectNegative Negative(mthumb) InverseMask(THUMB)
+Target RejectNegative Negative(mthumb) InverseMask(THUMB)
Generate code in 32 bit ARM state.
mbig-endian
-Target Report RejectNegative Negative(mlittle-endian) Mask(BIG_END)
+Target RejectNegative Negative(mlittle-endian) Mask(BIG_END)
Assume target CPU is configured as big endian.
mcallee-super-interworking
-Target Report Mask(CALLEE_INTERWORKING)
+Target Mask(CALLEE_INTERWORKING)
Thumb: Assume non-static functions may be called from ARM code.
mcaller-super-interworking
-Target Report Mask(CALLER_INTERWORKING)
+Target Mask(CALLER_INTERWORKING)
Thumb: Assume function pointers may go to non-Thumb aware code.
mcpu=
@@ -123,7 +123,7 @@ EnumValue
Enum(float_abi_type) String(hard) Value(ARM_FLOAT_ABI_HARD)
mflip-thumb
-Target Report Var(TARGET_FLIP_THUMB) Undocumented
+Target Var(TARGET_FLIP_THUMB) Undocumented
Switch ARM/Thumb modes on alternating functions for compiler testing.
mfp16-format=
@@ -151,15 +151,15 @@ mhard-float
Target RejectNegative Alias(mfloat-abi=, hard) Undocumented
mlittle-endian
-Target Report RejectNegative Negative(mbig-endian) InverseMask(BIG_END)
+Target RejectNegative Negative(mbig-endian) InverseMask(BIG_END)
Assume target CPU is configured as little endian.
mlong-calls
-Target Report Mask(LONG_CALLS)
+Target Mask(LONG_CALLS)
Generate call insns as indirect calls, if necessary.
mpic-data-is-text-relative
-Target Report Var(arm_pic_data_is_text_relative) Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE)
+Target Var(arm_pic_data_is_text_relative) Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE)
Assume data segments are relative to text segment.
mpic-register=
@@ -167,15 +167,15 @@ Target RejectNegative Joined Var(arm_pic_register_string)
Specify the register to be used for PIC addressing.
mpoke-function-name
-Target Report Mask(POKE_FUNCTION_NAME)
+Target Mask(POKE_FUNCTION_NAME)
Store function names in object code.
msched-prolog
-Target Report Mask(SCHED_PROLOG)
+Target Mask(SCHED_PROLOG)
Permit scheduling of a function's prologue sequence.
msingle-pic-base
-Target Report Mask(SINGLE_PIC_BASE)
+Target Mask(SINGLE_PIC_BASE)
Do not load the PIC register in function prologues.
msoft-float
@@ -186,11 +186,11 @@ Target RejectNegative Joined UInteger Var(arm_structure_size_boundary) Init(DEFA
Specify the minimum bit alignment of structures. (Deprecated).
mthumb
-Target Report RejectNegative Negative(marm) Mask(THUMB) Save
+Target RejectNegative Negative(marm) Mask(THUMB) Save
Generate code for Thumb state.
mthumb-interwork
-Target Report Mask(INTERWORK)
+Target Mask(INTERWORK)
Support calls between Thumb and ARM instruction sets.
mtls-dialect=
@@ -215,11 +215,11 @@ EnumValue
Enum(arm_tp_type) String(cp15) Value(TP_CP15)
mtpcs-frame
-Target Report Mask(TPCS_FRAME)
+Target Mask(TPCS_FRAME)
Thumb: Generate (non-leaf) stack frames even if not needed.
mtpcs-leaf-frame
-Target Report Mask(TPCS_LEAF_FRAME)
+Target Mask(TPCS_LEAF_FRAME)
Thumb: Generate (leaf) stack frames even if not needed.
mtune=
@@ -227,7 +227,7 @@ Target Save RejectNegative Negative(mtune=) ToLower Joined Var(arm_tune_string)
Tune code for the given processor.
mprint-tune-info
-Target Report RejectNegative Var(print_tune_info) Init(0)
+Target RejectNegative Var(print_tune_info) Init(0)
Print CPU tuning information as comment in assembler file. This is
an option used only for regression testing of the compiler and not
intended for ordinary use in compiling code.
@@ -238,11 +238,11 @@ EnumValue
Enum(processor_type) String(native) Value(-1) DriverOnly
mvectorize-with-neon-quad
-Target Report RejectNegative InverseMask(NEON_VECTORIZE_DOUBLE)
+Target RejectNegative InverseMask(NEON_VECTORIZE_DOUBLE)
Use Neon quad-word (rather than double-word) registers for vectorization.
mvectorize-with-neon-double
-Target Report RejectNegative Mask(NEON_VECTORIZE_DOUBLE)
+Target RejectNegative Mask(NEON_VECTORIZE_DOUBLE)
Use Neon double-word (rather than quad-word) registers for vectorization.
mverbose-cost-dump
@@ -250,20 +250,20 @@ Common Undocumented Var(arm_verbose_cost) Init(0)
Enable more verbose RTX cost dumps during debug. For GCC developers use only.
mword-relocations
-Target Report Var(target_word_relocations) Init(TARGET_DEFAULT_WORD_RELOCATIONS)
+Target Var(target_word_relocations) Init(TARGET_DEFAULT_WORD_RELOCATIONS)
Only generate absolute relocations on word sized values.
mrestrict-it
-Target Report Var(arm_restrict_it) Init(2) Save
+Target Var(arm_restrict_it) Init(2) Save
Generate IT blocks appropriate for ARMv8.
mfix-cortex-m3-ldrd
-Target Report Var(fix_cm3_ldrd) Init(2)
+Target Var(fix_cm3_ldrd) Init(2)
Avoid overlapping destination and address registers on LDRD instructions
that may trigger Cortex-M3 errata.
munaligned-access
-Target Report Var(unaligned_access) Init(2) Save
+Target Var(unaligned_access) Init(2) Save
Enable unaligned word and halfword accesses to packed data.
mneon-for-64bits
@@ -271,23 +271,23 @@ Target WarnRemoved
This option is deprecated and has no effect.
mslow-flash-data
-Target Report Var(target_slow_flash_data) Init(0)
+Target Var(target_slow_flash_data) Init(0)
Assume loading data from flash is slower than fetching instructions.
masm-syntax-unified
-Target Report Var(inline_asm_unified) Init(0) Save
+Target Var(inline_asm_unified) Init(0) Save
Assume unified syntax for inline assembly code.
mpure-code
-Target Report Var(target_pure_code) Init(0)
+Target Var(target_pure_code) Init(0)
Do not allow constant data to be placed in code sections.
mbe8
-Target Report RejectNegative Negative(mbe32) Mask(BE8)
+Target RejectNegative Negative(mbe32) Mask(BE8)
When linking for big-endian targets, generate a BE8 format image.
mbe32
-Target Report RejectNegative Negative(mbe8) InverseMask(BE8)
+Target RejectNegative Negative(mbe8) InverseMask(BE8)
When linking for big-endian targets, generate a legacy BE32 format image.
mbranch-cost=
@@ -295,9 +295,9 @@ Target RejectNegative Joined UInteger Var(arm_branch_cost) Init(-1)
Cost to assume for a branch insn.
mgeneral-regs-only
-Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Save
+Target RejectNegative Mask(GENERAL_REGS_ONLY) Save
Generate code which uses the core registers only (r0-r14).
mfdpic
-Target Report Mask(FDPIC)
+Target Mask(FDPIC)
Enable Function Descriptor PIC mode.
diff --git a/gcc/config/arm/arm1020e.md b/gcc/config/arm/arm1020e.md
index d1043f5..16fbd88 100644
--- a/gcc/config/arm/arm1020e.md
+++ b/gcc/config/arm/arm1020e.md
@@ -78,7 +78,7 @@
;; ALU operations with a shift-by-constant operand
(define_insn_reservation "1020alu_shift_op" 1
(and (eq_attr "tune" "arm10e")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
extend,mov_shift,mvn_shift"))
"1020a_e,1020a_m,1020a_w")
diff --git a/gcc/config/arm/arm1026ejs.md b/gcc/config/arm/arm1026ejs.md
index 5950629..ae8c03f 100644
--- a/gcc/config/arm/arm1026ejs.md
+++ b/gcc/config/arm/arm1026ejs.md
@@ -78,7 +78,7 @@
;; ALU operations with a shift-by-constant operand
(define_insn_reservation "alu_shift_op" 1
(and (eq_attr "tune" "arm1026ejs")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
extend,mov_shift,mvn_shift"))
"a_e,a_m,a_w")
diff --git a/gcc/config/arm/arm1136jfs.md b/gcc/config/arm/arm1136jfs.md
index ead4eef..7968d9d 100644
--- a/gcc/config/arm/arm1136jfs.md
+++ b/gcc/config/arm/arm1136jfs.md
@@ -87,7 +87,7 @@
;; ALU operations with a shift-by-constant operand
(define_insn_reservation "11_alu_shift_op" 2
(and (eq_attr "tune" "arm1136js,arm1136jfs")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
extend,mov_shift,mvn_shift"))
"e_1,e_2,e_3,e_wb")
diff --git a/gcc/config/arm/arm926ejs.md b/gcc/config/arm/arm926ejs.md
index ba9c942..34da6be 100644
--- a/gcc/config/arm/arm926ejs.md
+++ b/gcc/config/arm/arm926ejs.md
@@ -62,7 +62,7 @@
alu_sreg,alus_sreg,logic_reg,logics_reg,\
adc_imm,adcs_imm,adc_reg,adcs_reg,\
adr,bfm,rev,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
shift_imm,shift_reg,extend,\
mov_imm,mov_reg,mov_shift,\
diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h
index 6c0d1e2..4501462 100644
--- a/gcc/config/arm/arm_mve.h
+++ b/gcc/config/arm/arm_mve.h
@@ -3981,14 +3981,16 @@ __extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return __builtin_mve_vcaddq_rot90_uv16qi (__a, __b);
+ return (uint8x16_t)
+ __builtin_mve_vcaddq_rot90v16qi ((int8x16_t)__a, (int8x16_t)__b);
}
__extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return __builtin_mve_vcaddq_rot270_uv16qi (__a, __b);
+ return (uint8x16_t)
+ __builtin_mve_vcaddq_rot270v16qi ((int8x16_t)__a, (int8x16_t)__b);
}
__extension__ extern __inline uint8x16_t
@@ -4520,14 +4522,14 @@ __extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_s8 (int8x16_t __a, int8x16_t __b)
{
- return __builtin_mve_vcaddq_rot90_sv16qi (__a, __b);
+ return __builtin_mve_vcaddq_rot90v16qi (__a, __b);
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_s8 (int8x16_t __a, int8x16_t __b)
{
- return __builtin_mve_vcaddq_rot270_sv16qi (__a, __b);
+ return __builtin_mve_vcaddq_rot270v16qi (__a, __b);
}
__extension__ extern __inline int8x16_t
@@ -4821,14 +4823,16 @@ __extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return __builtin_mve_vcaddq_rot90_uv8hi (__a, __b);
+ return (uint16x8_t)
+ __builtin_mve_vcaddq_rot90v8hi ((int16x8_t)__a, (int16x8_t)__b);
}
__extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return __builtin_mve_vcaddq_rot270_uv8hi (__a, __b);
+ return (uint16x8_t)
+ __builtin_mve_vcaddq_rot270v8hi ((int16x8_t)__a, (int16x8_t)__b);
}
__extension__ extern __inline uint16x8_t
@@ -5360,14 +5364,14 @@ __extension__ extern __inline int16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_s16 (int16x8_t __a, int16x8_t __b)
{
- return __builtin_mve_vcaddq_rot90_sv8hi (__a, __b);
+ return __builtin_mve_vcaddq_rot90v8hi (__a, __b);
}
__extension__ extern __inline int16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_s16 (int16x8_t __a, int16x8_t __b)
{
- return __builtin_mve_vcaddq_rot270_sv8hi (__a, __b);
+ return __builtin_mve_vcaddq_rot270v8hi (__a, __b);
}
__extension__ extern __inline int16x8_t
@@ -5661,14 +5665,16 @@ __extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return __builtin_mve_vcaddq_rot90_uv4si (__a, __b);
+ return (uint32x4_t)
+ __builtin_mve_vcaddq_rot90v4si ((int32x4_t)__a, (int32x4_t)__b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return __builtin_mve_vcaddq_rot270_uv4si (__a, __b);
+ return (uint32x4_t)
+ __builtin_mve_vcaddq_rot270v4si ((int32x4_t)__a, (int32x4_t)__b);
}
__extension__ extern __inline uint32x4_t
@@ -6200,14 +6206,14 @@ __extension__ extern __inline int32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_s32 (int32x4_t __a, int32x4_t __b)
{
- return __builtin_mve_vcaddq_rot90_sv4si (__a, __b);
+ return __builtin_mve_vcaddq_rot90v4si (__a, __b);
}
__extension__ extern __inline int32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_s32 (int32x4_t __a, int32x4_t __b)
{
- return __builtin_mve_vcaddq_rot270_sv4si (__a, __b);
+ return __builtin_mve_vcaddq_rot270v4si (__a, __b);
}
__extension__ extern __inline int32x4_t
@@ -17342,42 +17348,42 @@ __extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_rot90_f16 (float16x8_t __a, float16x8_t __b)
{
- return __builtin_mve_vcmulq_rot90_fv8hf (__a, __b);
+ return __builtin_mve_vcmulq_rot90v8hf (__a, __b);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_rot270_f16 (float16x8_t __a, float16x8_t __b)
{
- return __builtin_mve_vcmulq_rot270_fv8hf (__a, __b);
+ return __builtin_mve_vcmulq_rot270v8hf (__a, __b);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_rot180_f16 (float16x8_t __a, float16x8_t __b)
{
- return __builtin_mve_vcmulq_rot180_fv8hf (__a, __b);
+ return __builtin_mve_vcmulq_rot180v8hf (__a, __b);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_f16 (float16x8_t __a, float16x8_t __b)
{
- return __builtin_mve_vcmulq_fv8hf (__a, __b);
+ return __builtin_mve_vcmulqv8hf (__a, __b);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_f16 (float16x8_t __a, float16x8_t __b)
{
- return __builtin_mve_vcaddq_rot90_fv8hf (__a, __b);
+ return __builtin_mve_vcaddq_rot90v8hf (__a, __b);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_f16 (float16x8_t __a, float16x8_t __b)
{
- return __builtin_mve_vcaddq_rot270_fv8hf (__a, __b);
+ return __builtin_mve_vcaddq_rot270v8hf (__a, __b);
}
__extension__ extern __inline float16x8_t
@@ -17594,42 +17600,42 @@ __extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_rot90_f32 (float32x4_t __a, float32x4_t __b)
{
- return __builtin_mve_vcmulq_rot90_fv4sf (__a, __b);
+ return __builtin_mve_vcmulq_rot90v4sf (__a, __b);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_rot270_f32 (float32x4_t __a, float32x4_t __b)
{
- return __builtin_mve_vcmulq_rot270_fv4sf (__a, __b);
+ return __builtin_mve_vcmulq_rot270v4sf (__a, __b);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_rot180_f32 (float32x4_t __a, float32x4_t __b)
{
- return __builtin_mve_vcmulq_rot180_fv4sf (__a, __b);
+ return __builtin_mve_vcmulq_rot180v4sf (__a, __b);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmulq_f32 (float32x4_t __a, float32x4_t __b)
{
- return __builtin_mve_vcmulq_fv4sf (__a, __b);
+ return __builtin_mve_vcmulqv4sf (__a, __b);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot90_f32 (float32x4_t __a, float32x4_t __b)
{
- return __builtin_mve_vcaddq_rot90_fv4sf (__a, __b);
+ return __builtin_mve_vcaddq_rot90v4sf (__a, __b);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcaddq_rot270_f32 (float32x4_t __a, float32x4_t __b)
{
- return __builtin_mve_vcaddq_rot270_fv4sf (__a, __b);
+ return __builtin_mve_vcaddq_rot270v4sf (__a, __b);
}
__extension__ extern __inline float32x4_t
@@ -17784,28 +17790,28 @@ __extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c)
{
- return __builtin_mve_vcmlaq_fv8hf (__a, __b, __c);
+ return __builtin_mve_vcmlaqv8hf (__a, __b, __c);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_rot180_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c)
{
- return __builtin_mve_vcmlaq_rot180_fv8hf (__a, __b, __c);
+ return __builtin_mve_vcmlaq_rot180v8hf (__a, __b, __c);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_rot270_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c)
{
- return __builtin_mve_vcmlaq_rot270_fv8hf (__a, __b, __c);
+ return __builtin_mve_vcmlaq_rot270v8hf (__a, __b, __c);
}
__extension__ extern __inline float16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_rot90_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c)
{
- return __builtin_mve_vcmlaq_rot90_fv8hf (__a, __b, __c);
+ return __builtin_mve_vcmlaq_rot90v8hf (__a, __b, __c);
}
__extension__ extern __inline float16x8_t
@@ -18092,28 +18098,28 @@ __extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
{
- return __builtin_mve_vcmlaq_fv4sf (__a, __b, __c);
+ return __builtin_mve_vcmlaqv4sf (__a, __b, __c);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_rot180_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
{
- return __builtin_mve_vcmlaq_rot180_fv4sf (__a, __b, __c);
+ return __builtin_mve_vcmlaq_rot180v4sf (__a, __b, __c);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_rot270_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
{
- return __builtin_mve_vcmlaq_rot270_fv4sf (__a, __b, __c);
+ return __builtin_mve_vcmlaq_rot270v4sf (__a, __b, __c);
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
__arm_vcmlaq_rot90_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
{
- return __builtin_mve_vcmlaq_rot90_fv4sf (__a, __b, __c);
+ return __builtin_mve_vcmlaq_rot90v4sf (__a, __b, __c);
}
__extension__ extern __inline float32x4_t
diff --git a/gcc/config/arm/arm_mve_builtins.def b/gcc/config/arm/arm_mve_builtins.def
index f38926f..56b652f 100644
--- a/gcc/config/arm/arm_mve_builtins.def
+++ b/gcc/config/arm/arm_mve_builtins.def
@@ -125,8 +125,6 @@ VAR3 (BINOP_UNONE_UNONE_UNONE, vcmpeqq_u, v16qi, v8hi, v4si)
VAR3 (BINOP_UNONE_UNONE_UNONE, vcmpeqq_n_u, v16qi, v8hi, v4si)
VAR3 (BINOP_UNONE_UNONE_UNONE, vcmpcsq_u, v16qi, v8hi, v4si)
VAR3 (BINOP_UNONE_UNONE_UNONE, vcmpcsq_n_u, v16qi, v8hi, v4si)
-VAR3 (BINOP_UNONE_UNONE_UNONE, vcaddq_rot90_u, v16qi, v8hi, v4si)
-VAR3 (BINOP_UNONE_UNONE_UNONE, vcaddq_rot270_u, v16qi, v8hi, v4si)
VAR3 (BINOP_UNONE_UNONE_UNONE, vbicq_u, v16qi, v8hi, v4si)
VAR3 (BINOP_UNONE_UNONE_UNONE, vandq_u, v16qi, v8hi, v4si)
VAR3 (BINOP_UNONE_UNONE_UNONE, vaddvq_p_u, v16qi, v8hi, v4si)
@@ -202,8 +200,6 @@ VAR3 (BINOP_NONE_NONE_NONE, vhcaddq_rot270_s, v16qi, v8hi, v4si)
VAR3 (BINOP_NONE_NONE_NONE, vhaddq_s, v16qi, v8hi, v4si)
VAR3 (BINOP_NONE_NONE_NONE, vhaddq_n_s, v16qi, v8hi, v4si)
VAR3 (BINOP_NONE_NONE_NONE, veorq_s, v16qi, v8hi, v4si)
-VAR3 (BINOP_NONE_NONE_NONE, vcaddq_rot90_s, v16qi, v8hi, v4si)
-VAR3 (BINOP_NONE_NONE_NONE, vcaddq_rot270_s, v16qi, v8hi, v4si)
VAR3 (BINOP_NONE_NONE_NONE, vbrsrq_n_s, v16qi, v8hi, v4si)
VAR3 (BINOP_NONE_NONE_NONE, vbicq_s, v16qi, v8hi, v4si)
VAR3 (BINOP_NONE_NONE_NONE, vandq_s, v16qi, v8hi, v4si)
@@ -264,12 +260,6 @@ VAR2 (BINOP_NONE_NONE_NONE, vmaxnmq_f, v8hf, v4sf)
VAR2 (BINOP_NONE_NONE_NONE, vmaxnmavq_f, v8hf, v4sf)
VAR2 (BINOP_NONE_NONE_NONE, vmaxnmaq_f, v8hf, v4sf)
VAR2 (BINOP_NONE_NONE_NONE, veorq_f, v8hf, v4sf)
-VAR2 (BINOP_NONE_NONE_NONE, vcmulq_rot90_f, v8hf, v4sf)
-VAR2 (BINOP_NONE_NONE_NONE, vcmulq_rot270_f, v8hf, v4sf)
-VAR2 (BINOP_NONE_NONE_NONE, vcmulq_rot180_f, v8hf, v4sf)
-VAR2 (BINOP_NONE_NONE_NONE, vcmulq_f, v8hf, v4sf)
-VAR2 (BINOP_NONE_NONE_NONE, vcaddq_rot90_f, v8hf, v4sf)
-VAR2 (BINOP_NONE_NONE_NONE, vcaddq_rot270_f, v8hf, v4sf)
VAR2 (BINOP_NONE_NONE_NONE, vbicq_f, v8hf, v4sf)
VAR2 (BINOP_NONE_NONE_NONE, vandq_f, v8hf, v4sf)
VAR2 (BINOP_NONE_NONE_NONE, vaddq_n_f, v8hf, v4sf)
@@ -470,10 +460,6 @@ VAR2 (TERNOP_NONE_NONE_NONE_NONE, vfmsq_f, v8hf, v4sf)
VAR2 (TERNOP_NONE_NONE_NONE_NONE, vfmasq_n_f, v8hf, v4sf)
VAR2 (TERNOP_NONE_NONE_NONE_NONE, vfmaq_n_f, v8hf, v4sf)
VAR2 (TERNOP_NONE_NONE_NONE_NONE, vfmaq_f, v8hf, v4sf)
-VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_rot90_f, v8hf, v4sf)
-VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_rot270_f, v8hf, v4sf)
-VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_rot180_f, v8hf, v4sf)
-VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_f, v8hf, v4sf)
VAR2 (TERNOP_NONE_NONE_NONE_IMM, vshrntq_n_s, v8hi, v4si)
VAR2 (TERNOP_NONE_NONE_NONE_IMM, vshrnbq_n_s, v8hi, v4si)
VAR2 (TERNOP_NONE_NONE_NONE_IMM, vrshrntq_n_s, v8hi, v4si)
@@ -892,3 +878,15 @@ VAR3 (QUADOP_NONE_NONE_UNONE_IMM_UNONE, vshlcq_m_vec_s, v16qi, v8hi, v4si)
VAR3 (QUADOP_NONE_NONE_UNONE_IMM_UNONE, vshlcq_m_carry_s, v16qi, v8hi, v4si)
VAR3 (QUADOP_UNONE_UNONE_UNONE_IMM_UNONE, vshlcq_m_vec_u, v16qi, v8hi, v4si)
VAR3 (QUADOP_UNONE_UNONE_UNONE_IMM_UNONE, vshlcq_m_carry_u, v16qi, v8hi, v4si)
+
+/* optabs without any suffixes. */
+VAR5 (BINOP_NONE_NONE_NONE, vcaddq_rot90, v16qi, v8hi, v4si, v8hf, v4sf)
+VAR5 (BINOP_NONE_NONE_NONE, vcaddq_rot270, v16qi, v8hi, v4si, v8hf, v4sf)
+VAR2 (BINOP_NONE_NONE_NONE, vcmulq_rot90, v8hf, v4sf)
+VAR2 (BINOP_NONE_NONE_NONE, vcmulq_rot270, v8hf, v4sf)
+VAR2 (BINOP_NONE_NONE_NONE, vcmulq_rot180, v8hf, v4sf)
+VAR2 (BINOP_NONE_NONE_NONE, vcmulq, v8hf, v4sf)
+VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_rot90, v8hf, v4sf)
+VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_rot270, v8hf, v4sf)
+VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq_rot180, v8hf, v4sf)
+VAR2 (TERNOP_NONE_NONE_NONE_NONE, vcmlaq, v8hf, v4sf)
diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index aa21730..4029516 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -2667,196 +2667,196 @@ __extension__ extern __inline uint8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_s8 (int8x8_t __a, int8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vcgtv8qi (__a, __b);
+ return (uint8x8_t) (__a > __b);
}
__extension__ extern __inline uint16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_s16 (int16x4_t __a, int16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vcgtv4hi (__a, __b);
+ return (uint16x4_t) (__a > __b);
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_s32 (int32x2_t __a, int32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vcgtv2si (__a, __b);
+ return (uint32x2_t) (__a > __b);
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_f32 (float32x2_t __a, float32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vcgtv2sf (__a, __b);
+ return (uint32x2_t) (__a > __b);
}
__extension__ extern __inline uint8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vcgtuv8qi ((int8x8_t) __a, (int8x8_t) __b);
+ return (__a > __b);
}
__extension__ extern __inline uint16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vcgtuv4hi ((int16x4_t) __a, (int16x4_t) __b);
+ return (__a > __b);
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgt_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vcgtuv2si ((int32x2_t) __a, (int32x2_t) __b);
+ return (__a > __b);
}
__extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vcgtv16qi (__a, __b);
+ return (uint8x16_t) (__a > __b);
}
__extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vcgtv8hi (__a, __b);
+ return (uint16x8_t) (__a > __b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vcgtv4si (__a, __b);
+ return (uint32x4_t) (__a > __b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_f32 (float32x4_t __a, float32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vcgtv4sf (__a, __b);
+ return (uint32x4_t) (__a > __b);
}
__extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vcgtuv16qi ((int8x16_t) __a, (int8x16_t) __b);
+ return (__a > __b);
}
__extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vcgtuv8hi ((int16x8_t) __a, (int16x8_t) __b);
+ return (__a > __b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcgtq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vcgtuv4si ((int32x4_t) __a, (int32x4_t) __b);
+ return (__a > __b);
}
__extension__ extern __inline uint8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_s8 (int8x8_t __a, int8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vcgtv8qi (__b, __a);
+ return (uint8x8_t) (__a < __b);
}
__extension__ extern __inline uint16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_s16 (int16x4_t __a, int16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vcgtv4hi (__b, __a);
+ return (uint16x4_t) (__a < __b);
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_s32 (int32x2_t __a, int32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vcgtv2si (__b, __a);
+ return (uint32x2_t) (__a < __b);
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_f32 (float32x2_t __a, float32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vcgtv2sf (__b, __a);
+ return (uint32x2_t) (__a < __b);
}
__extension__ extern __inline uint8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vcgtuv8qi ((int8x8_t) __b, (int8x8_t) __a);
+ return (__a < __b);
}
__extension__ extern __inline uint16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vcgtuv4hi ((int16x4_t) __b, (int16x4_t) __a);
+ return (__a < __b);
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vclt_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vcgtuv2si ((int32x2_t) __b, (int32x2_t) __a);
+ return (__a < __b);
}
__extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vcgtv16qi (__b, __a);
+ return (uint8x16_t) (__a < __b);
}
__extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vcgtv8hi (__b, __a);
+ return (uint16x8_t) (__a < __b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vcgtv4si (__b, __a);
+ return (uint32x4_t) (__a < __b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_f32 (float32x4_t __a, float32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vcgtv4sf (__b, __a);
+ return (uint32x4_t) (__a < __b);
}
__extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vcgtuv16qi ((int8x16_t) __b, (int8x16_t) __a);
+ return (__a < __b);
}
__extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vcgtuv8hi ((int16x8_t) __b, (int16x8_t) __a);
+ return (__a < __b);
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcltq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vcgtuv4si ((int32x4_t) __b, (int32x4_t) __a);
+ return (__a < __b);
}
__extension__ extern __inline uint32x2_t
@@ -5714,56 +5714,56 @@ __extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vneg_s8 (int8x8_t __a)
{
- return (int8x8_t)__builtin_neon_vnegv8qi (__a);
+ return -__a;
}
__extension__ extern __inline int16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vneg_s16 (int16x4_t __a)
{
- return (int16x4_t)__builtin_neon_vnegv4hi (__a);
+ return -__a;
}
__extension__ extern __inline int32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vneg_s32 (int32x2_t __a)
{
- return (int32x2_t)__builtin_neon_vnegv2si (__a);
+ return -__a;
}
__extension__ extern __inline float32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vneg_f32 (float32x2_t __a)
{
- return (float32x2_t)__builtin_neon_vnegv2sf (__a);
+ return -__a;
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vnegq_s8 (int8x16_t __a)
{
- return (int8x16_t)__builtin_neon_vnegv16qi (__a);
+ return -__a;
}
__extension__ extern __inline int16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vnegq_s16 (int16x8_t __a)
{
- return (int16x8_t)__builtin_neon_vnegv8hi (__a);
+ return -__a;
}
__extension__ extern __inline int32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vnegq_s32 (int32x4_t __a)
{
- return (int32x4_t)__builtin_neon_vnegv4si (__a);
+ return -__a;
}
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vnegq_f32 (float32x4_t __a)
{
- return (float32x4_t)__builtin_neon_vnegv4sf (__a);
+ return -__a;
}
__extension__ extern __inline int8x8_t
@@ -5812,98 +5812,98 @@ __extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_s8 (int8x8_t __a)
{
- return (int8x8_t)__builtin_neon_vmvnv8qi (__a);
+ return ~__a;
}
__extension__ extern __inline int16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_s16 (int16x4_t __a)
{
- return (int16x4_t)__builtin_neon_vmvnv4hi (__a);
+ return ~__a;
}
__extension__ extern __inline int32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_s32 (int32x2_t __a)
{
- return (int32x2_t)__builtin_neon_vmvnv2si (__a);
+ return ~__a;
}
__extension__ extern __inline uint8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_u8 (uint8x8_t __a)
{
- return (uint8x8_t)__builtin_neon_vmvnv8qi ((int8x8_t) __a);
+ return ~__a;
}
__extension__ extern __inline uint16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_u16 (uint16x4_t __a)
{
- return (uint16x4_t)__builtin_neon_vmvnv4hi ((int16x4_t) __a);
+ return ~__a;
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_u32 (uint32x2_t __a)
{
- return (uint32x2_t)__builtin_neon_vmvnv2si ((int32x2_t) __a);
+ return ~__a;
}
__extension__ extern __inline poly8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvn_p8 (poly8x8_t __a)
{
- return (poly8x8_t)__builtin_neon_vmvnv8qi ((int8x8_t) __a);
+ return (poly8x8_t) ~((int8x8_t) __a);
}
__extension__ extern __inline int8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_s8 (int8x16_t __a)
{
- return (int8x16_t)__builtin_neon_vmvnv16qi (__a);
+ return ~__a;
}
__extension__ extern __inline int16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_s16 (int16x8_t __a)
{
- return (int16x8_t)__builtin_neon_vmvnv8hi (__a);
+ return ~__a;
}
__extension__ extern __inline int32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_s32 (int32x4_t __a)
{
- return (int32x4_t)__builtin_neon_vmvnv4si (__a);
+ return ~__a;
}
__extension__ extern __inline uint8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_u8 (uint8x16_t __a)
{
- return (uint8x16_t)__builtin_neon_vmvnv16qi ((int8x16_t) __a);
+ return ~__a;
}
__extension__ extern __inline uint16x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_u16 (uint16x8_t __a)
{
- return (uint16x8_t)__builtin_neon_vmvnv8hi ((int16x8_t) __a);
+ return ~__a;
}
__extension__ extern __inline uint32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_u32 (uint32x4_t __a)
{
- return (uint32x4_t)__builtin_neon_vmvnv4si ((int32x4_t) __a);
+ return ~__a;
}
__extension__ extern __inline poly8x16_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmvnq_p8 (poly8x16_t __a)
{
- return (poly8x16_t)__builtin_neon_vmvnv16qi ((int8x16_t) __a);
+ return (poly8x16_t) ~((int8x16_t) __a);
}
__extension__ extern __inline int8x8_t
@@ -6531,7 +6531,7 @@ __extension__ extern __inline poly64x1_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_p64 (uint64_t __a)
{
- return (poly64x1_t)__builtin_neon_vcreatedi ((__builtin_neon_di) __a);
+ return (poly64x1_t) __a;
}
#pragma GCC pop_options
@@ -6539,28 +6539,28 @@ __extension__ extern __inline int8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_s8 (uint64_t __a)
{
- return (int8x8_t)__builtin_neon_vcreatev8qi ((__builtin_neon_di) __a);
+ return (int8x8_t) __a;
}
__extension__ extern __inline int16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_s16 (uint64_t __a)
{
- return (int16x4_t)__builtin_neon_vcreatev4hi ((__builtin_neon_di) __a);
+ return (int16x4_t) __a;
}
__extension__ extern __inline int32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_s32 (uint64_t __a)
{
- return (int32x2_t)__builtin_neon_vcreatev2si ((__builtin_neon_di) __a);
+ return (int32x2_t) __a;
}
__extension__ extern __inline int64x1_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_s64 (uint64_t __a)
{
- return (int64x1_t)__builtin_neon_vcreatedi ((__builtin_neon_di) __a);
+ return (int64x1_t) {__a};
}
#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE)
@@ -6576,49 +6576,49 @@ __extension__ extern __inline float32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_f32 (uint64_t __a)
{
- return (float32x2_t)__builtin_neon_vcreatev2sf ((__builtin_neon_di) __a);
+ return (float32x2_t) __a;
}
__extension__ extern __inline uint8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_u8 (uint64_t __a)
{
- return (uint8x8_t)__builtin_neon_vcreatev8qi ((__builtin_neon_di) __a);
+ return (uint8x8_t) __a;
}
__extension__ extern __inline uint16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_u16 (uint64_t __a)
{
- return (uint16x4_t)__builtin_neon_vcreatev4hi ((__builtin_neon_di) __a);
+ return (uint16x4_t) __a;
}
__extension__ extern __inline uint32x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_u32 (uint64_t __a)
{
- return (uint32x2_t)__builtin_neon_vcreatev2si ((__builtin_neon_di) __a);
+ return (uint32x2_t) __a;
}
__extension__ extern __inline uint64x1_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_u64 (uint64_t __a)
{
- return (uint64x1_t)__builtin_neon_vcreatedi ((__builtin_neon_di) __a);
+ return (uint64x1_t) {__a};
}
__extension__ extern __inline poly8x8_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_p8 (uint64_t __a)
{
- return (poly8x8_t)__builtin_neon_vcreatev8qi ((__builtin_neon_di) __a);
+ return (poly8x8_t) __a;
}
__extension__ extern __inline poly16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vcreate_p16 (uint64_t __a)
{
- return (poly16x4_t)__builtin_neon_vcreatev4hi ((__builtin_neon_di) __a);
+ return (poly16x4_t) __a;
}
__extension__ extern __inline int8x8_t
@@ -19510,6 +19510,20 @@ vbfmlaltq_laneq_f32 (float32x4_t __r, bfloat16x8_t __a, bfloat16x8_t __b,
}
__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst1_bf16 (bfloat16_t * __a, bfloat16x4_t __b)
+{
+ __builtin_neon_vst1v4bf (__a, __b);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_bf16 (bfloat16_t * __a, bfloat16x8_t __b)
+{
+ __builtin_neon_vst1v8bf (__a, __b);
+}
+
+__extension__ extern __inline void
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vst2_bf16 (bfloat16_t * __ptr, bfloat16x4x2_t __val)
{
@@ -19557,6 +19571,20 @@ vst4q_bf16 (bfloat16_t * __ptr, bfloat16x8x4_t __val)
return __builtin_neon_vst4v8bf (__ptr, __bu.__o);
}
+__extension__ extern __inline bfloat16x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld1_bf16 (bfloat16_t const * __ptr)
+{
+ return __builtin_neon_vld1v4bf (__ptr);
+}
+
+__extension__ extern __inline bfloat16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld1q_bf16 (const bfloat16_t * __ptr)
+{
+ return __builtin_neon_vld1v8bf (__ptr);
+}
+
__extension__ extern __inline bfloat16x4x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vld2_bf16 (bfloat16_t const * __ptr)
@@ -19665,6 +19693,144 @@ vld4q_dup_bf16 (const bfloat16_t * __ptr)
return __rv.__i;
}
+__extension__ extern __inline bfloat16x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld1_lane_bf16 (const bfloat16_t * __a, bfloat16x4_t __b, const int __c)
+{
+ return __builtin_neon_vld1_lanev4bf (__a, __b, __c);
+}
+
+__extension__ extern __inline bfloat16x8_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld1q_lane_bf16 (const bfloat16_t * __a, bfloat16x8_t __b, const int __c)
+{
+ return __builtin_neon_vld1_lanev8bf (__a, __b, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst1_lane_bf16 (bfloat16_t * __a, bfloat16x4_t __b, const int __c)
+{
+ __builtin_neon_vst1_lanev4bf (__a, __b, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_lane_bf16 (bfloat16_t * __a, bfloat16x8_t __b, const int __c)
+{
+ __builtin_neon_vst1_lanev8bf (__a, __b, __c);
+}
+
+__extension__ extern __inline bfloat16x4x2_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld2_lane_bf16 (const bfloat16_t * __a, bfloat16x4x2_t __b, const int __c)
+{
+ union { bfloat16x4x2_t __i; __builtin_neon_ti __o; } __bu = { __b };
+ union { bfloat16x4x2_t __i; __builtin_neon_ti __o; } __rv;
+ __rv.__o = __builtin_neon_vld2_lanev4bf ( __a, __bu.__o, __c);
+ return __rv.__i;
+}
+
+__extension__ extern __inline bfloat16x8x2_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld2q_lane_bf16 (const bfloat16_t * __a, bfloat16x8x2_t __b, const int __c)
+{
+ union { bfloat16x8x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+ union { bfloat16x8x2_t __i; __builtin_neon_oi __o; } __rv;
+ __rv.__o = __builtin_neon_vld2_lanev8bf (__a, __bu.__o, __c);
+ return __rv.__i;
+}
+
+__extension__ extern __inline bfloat16x4x3_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld3_lane_bf16 (const bfloat16_t * __a, bfloat16x4x3_t __b, const int __c)
+{
+ union { bfloat16x4x3_t __i; __builtin_neon_ei __o; } __bu = { __b };
+ union { bfloat16x4x3_t __i; __builtin_neon_ei __o; } __rv;
+ __rv.__o = __builtin_neon_vld3_lanev4bf (__a, __bu.__o, __c);
+ return __rv.__i;
+}
+
+__extension__ extern __inline bfloat16x8x3_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld3q_lane_bf16 (const bfloat16_t * __a, bfloat16x8x3_t __b, const int __c)
+{
+ union { bfloat16x8x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+ union { bfloat16x8x3_t __i; __builtin_neon_ci __o; } __rv;
+ __rv.__o = __builtin_neon_vld3_lanev8bf (__a, __bu.__o, __c);
+ return __rv.__i;
+}
+
+__extension__ extern __inline bfloat16x4x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld4_lane_bf16 (const bfloat16_t * __a, bfloat16x4x4_t __b, const int __c)
+{
+ union { bfloat16x4x4_t __i; __builtin_neon_oi __o; } __bu = { __b };
+ union { bfloat16x4x4_t __i; __builtin_neon_oi __o; } __rv;
+ __rv.__o = __builtin_neon_vld4_lanev4bf (__a,
+ __bu.__o, __c);
+ return __rv.__i;
+}
+
+__extension__ extern __inline bfloat16x8x4_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vld4q_lane_bf16 (const bfloat16_t * __a, bfloat16x8x4_t __b, const int __c)
+{
+ union { bfloat16x8x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+ union { bfloat16x8x4_t __i; __builtin_neon_xi __o; } __rv;
+ __rv.__o = __builtin_neon_vld4_lanev8bf (__a,
+ __bu.__o, __c);
+ return __rv.__i;
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst2_lane_bf16 (bfloat16_t * __a, bfloat16x4x2_t __b, const int __c)
+{
+ union { bfloat16x4x2_t __i; __builtin_neon_ti __o; } __bu = { __b };
+ __builtin_neon_vst2_lanev4bf (__a, __bu.__o, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst2q_lane_bf16 (bfloat16_t * __a, bfloat16x8x2_t __b, const int __c)
+{
+ union { bfloat16x8x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+ __builtin_neon_vst2_lanev8bf (__a, __bu.__o, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst3_lane_bf16 (bfloat16_t * __a, bfloat16x4x3_t __b, const int __c)
+{
+ union { bfloat16x4x3_t __i; __builtin_neon_ei __o; } __bu = { __b };
+ __builtin_neon_vst3_lanev4bf (__a, __bu.__o, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst3q_lane_bf16 (bfloat16_t * __a, bfloat16x8x3_t __b, const int __c)
+{
+ union { bfloat16x8x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+ __builtin_neon_vst3_lanev8bf (__a, __bu.__o, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst4_lane_bf16 (bfloat16_t * __a, bfloat16x4x4_t __b, const int __c)
+{
+ union { bfloat16x4x4_t __i; __builtin_neon_oi __o; } __bu = { __b };
+ __builtin_neon_vst4_lanev4bf (__a, __bu.__o, __c);
+}
+
+__extension__ extern __inline void
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vst4q_lane_bf16 (bfloat16_t * __a, bfloat16x8x4_t __b, const int __c)
+{
+ union { bfloat16x8x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+ __builtin_neon_vst4_lanev8bf (__a, __bu.__o, __c);
+}
+
#pragma GCC pop_options
#ifdef __cplusplus
diff --git a/gcc/config/arm/arm_neon_builtins.def b/gcc/config/arm/arm_neon_builtins.def
index 34c1945..ae104d5 100644
--- a/gcc/config/arm/arm_neon_builtins.def
+++ b/gcc/config/arm/arm_neon_builtins.def
@@ -128,8 +128,6 @@ VAR3 (BINOP, vrsubhn, v8hi, v4si, v2di)
VAR8 (BINOP, vceq, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
VAR8 (BINOP, vcge, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
VAR6 (BINOP, vcgeu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
-VAR8 (BINOP, vcgt, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
-VAR6 (BINOP, vcgtu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (BINOP, vcage, v2sf, v4sf)
VAR2 (BINOP, vcagt, v2sf, v4sf)
VAR2 (BINOP, vcage, v4hf, v8hf)
@@ -195,7 +193,6 @@ VAR8 (UNOP, vabs, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
VAR2 (UNOP, vabs, v8hf, v4hf)
VAR2 (UNOP, vneg, v8hf, v4hf)
VAR6 (UNOP, vqabs, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
-VAR8 (UNOP, vneg, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
VAR6 (UNOP, vqneg, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR6 (UNOP, vcls, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR6 (UNOP, vclz, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
@@ -205,7 +202,6 @@ VAR4 (UNOP, vrecpe, v2si, v2sf, v4si, v4sf)
VAR2 (UNOP, vrecpe, v8hf, v4hf)
VAR4 (UNOP, vrsqrte, v2si, v2sf, v4si, v4sf)
VAR2 (UNOP, vrsqrte, v4hf, v8hf)
-VAR6 (UNOP, vmvn, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (UNOP, vrnd, v8hf, v4hf)
VAR2 (UNOP, vrnda, v8hf, v4hf)
VAR2 (UNOP, vrndm, v8hf, v4hf)
@@ -218,7 +214,6 @@ VAR10 (GETLANE, vget_lane,
VAR6 (GETLANE, vget_laneu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR10 (SETLANE, vset_lane,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
-VAR5 (UNOP, vcreate, v8qi, v4hi, v2si, v2sf, di)
VAR10 (UNOP, vdup_n,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
VAR4 (UNOP, vdup_n, v8hf, v4hf, v8bf, v4bf)
@@ -310,43 +305,45 @@ VAR1 (TERNOP, vtbx1, v8qi)
VAR1 (TERNOP, vtbx2, v8qi)
VAR1 (TERNOP, vtbx3, v8qi)
VAR1 (TERNOP, vtbx4, v8qi)
-VAR12 (LOAD1, vld1,
- v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v2di)
-VAR10 (LOAD1LANE, vld1_lane,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
+VAR14 (LOAD1, vld1,
+ v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v2di,
+ v4bf, v8bf)
+VAR12 (LOAD1LANE, vld1_lane,
+ v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di, v4bf, v8bf)
VAR10 (LOAD1, vld1_dup,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
-VAR12 (STORE1, vst1,
- v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v2di)
-VAR12 (STORE1LANE, vst1_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v2di)
+VAR14 (STORE1, vst1,
+ v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v2di,
+ v4bf, v8bf)
+VAR14 (STORE1LANE, vst1_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v2di, v4bf, v8bf)
VAR13 (LOAD1, vld2,
v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
-VAR9 (LOAD1LANE, vld2_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf)
+VAR11 (LOAD1LANE, vld2_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
VAR8 (LOAD1, vld2_dup, v8qi, v4hi, v4hf, v2si, v2sf, di, v4bf, v8bf)
VAR13 (STORE1, vst2,
v8qi, v4hi, v4hf, v4bf, v2si, v2sf, di, v16qi, v8hi, v8hf, v8bf, v4si, v4sf)
-VAR9 (STORE1LANE, vst2_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf)
+VAR11 (STORE1LANE, vst2_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
VAR13 (LOAD1, vld3,
v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
-VAR9 (LOAD1LANE, vld3_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf)
+VAR11 (LOAD1LANE, vld3_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
VAR8 (LOAD1, vld3_dup, v8qi, v4hi, v4hf, v2si, v2sf, di, v4bf, v8bf)
VAR13 (STORE1, vst3,
v8qi, v4hi, v4hf, v4bf, v2si, v2sf, di, v16qi, v8hi, v8hf, v8bf, v4si, v4sf)
-VAR9 (STORE1LANE, vst3_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf)
+VAR11 (STORE1LANE, vst3_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
VAR13 (LOAD1, vld4,
v8qi, v4hi, v4hf, v2si, v2sf, di, v16qi, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
-VAR9 (LOAD1LANE, vld4_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf)
+VAR11 (LOAD1LANE, vld4_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
VAR8 (LOAD1, vld4_dup, v8qi, v4hi, v4hf, v2si, v2sf, di, v4bf, v8bf)
VAR13 (STORE1, vst4,
v8qi, v4hi, v4hf, v4bf, v2si, v2sf, di, v16qi, v8hi, v8hf, v8bf, v4si, v4sf)
-VAR9 (STORE1LANE, vst4_lane,
- v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf)
+VAR11 (STORE1LANE, vst4_lane,
+ v8qi, v4hi, v4hf, v2si, v2sf, v8hi, v8hf, v4si, v4sf, v4bf, v8bf)
VAR2 (TERNOP, sdot, v8qi, v16qi)
VAR2 (UTERNOP, udot, v8qi, v16qi)
VAR2 (MAC_LANE, sdot_lane, v8qi, v16qi)
diff --git a/gcc/config/arm/common.md b/gcc/config/arm/common.md
new file mode 100644
index 0000000..df601f4
--- /dev/null
+++ b/gcc/config/arm/common.md
@@ -0,0 +1,41 @@
+;; Common predicate definitions for ARM, Thumb and AArch64
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+;; Contributed by Fujitsu Ltd.
+
+;; 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/>.
+
+;; Return true if constant is CONST_INT >= 1 and <= 4
+(define_predicate "const_1_to_4_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 1, 4)")))
+
+;; Return true if constant is 2 or 4 or 8 or 16
+(define_predicate "const_2_4_8_16_operand"
+ (and (match_code "const_int")
+ (match_test (" INTVAL (op) == 2
+ || INTVAL (op) == 4
+ || INTVAL (op) == 8
+ || INTVAL (op) == 16 "))))
+
+;; Return true if shift type is lsl and amount is in[1,4].
+(define_predicate "alu_shift_operator_lsl_1_to_4"
+ (and (match_code "ashift")
+ (match_test "const_1_to_4_operand (XEXP (op, 1), mode)")))
+
+;; Return true if the operand is register.
+(define_predicate "alu_shift_reg_p"
+ (match_test "register_operand (XEXP (op, 1), mode)"))
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index 789e333..6ebddb9 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -310,7 +310,7 @@
"@internal
In ARM/Thumb-2 state a vector of constant zeros."
(and (match_code "const_vector")
- (match_test "TARGET_NEON && op == CONST0_RTX (mode)")))
+ (match_test "(TARGET_NEON || TARGET_HAVE_MVE) && op == CONST0_RTX (mode)")))
(define_constraint "Da"
"@internal
diff --git a/gcc/config/arm/cortex-a15.md b/gcc/config/arm/cortex-a15.md
index 3cd1c43..3d22eb3 100644
--- a/gcc/config/arm/cortex-a15.md
+++ b/gcc/config/arm/cortex-a15.md
@@ -78,7 +78,7 @@
(define_insn_reservation "cortex_a15_alu_shift" 3
(and (eq_attr "tune" "cortexa15")
(eq_attr "type" "extend,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
crc,logic_shift_imm,logics_shift_imm,\
mov_shift,mvn_shift"))
"ca15_issue1,(ca15_sx1,ca15_sx1+ca15_sx1_shf,ca15_sx1_alu)\
diff --git a/gcc/config/arm/cortex-a17.md b/gcc/config/arm/cortex-a17.md
index ad524c6..dfd0343 100644
--- a/gcc/config/arm/cortex-a17.md
+++ b/gcc/config/arm/cortex-a17.md
@@ -47,7 +47,7 @@
(define_insn_reservation "cortex_a17_alu_shiftimm" 2
(and (eq_attr "tune" "cortexa17")
- (eq_attr "type" "bfm,clz,rev,rbit, alu_shift_imm, alus_shift_imm,
+ (eq_attr "type" "bfm,clz,rev,rbit, alu_shift_imm_lsl_1to4,alu_shift_imm_other, alus_shift_imm,
logic_shift_imm,alu_dsp_reg, logics_shift_imm,shift_imm,\
shift_reg, mov_shift,mvn_shift"))
"ca17_alu")
diff --git a/gcc/config/arm/cortex-a5.md b/gcc/config/arm/cortex-a5.md
index fd34696..e9ee730 100644
--- a/gcc/config/arm/cortex-a5.md
+++ b/gcc/config/arm/cortex-a5.md
@@ -70,7 +70,7 @@
(define_insn_reservation "cortex_a5_alu_shift" 2
(and (eq_attr "tune" "cortexa5")
(eq_attr "type" "extend,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/cortex-a53.md b/gcc/config/arm/cortex-a53.md
index afa3b78..a7c8666 100644
--- a/gcc/config/arm/cortex-a53.md
+++ b/gcc/config/arm/cortex-a53.md
@@ -91,7 +91,7 @@
(define_insn_reservation "cortex_a53_alu_shift" 3
(and (eq_attr "tune" "cortexa53")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,
crc,logic_shift_imm,logics_shift_imm,
alu_ext,alus_ext,bfm,bfx,extend,mvn_shift"))
"cortex_a53_slot_any")
diff --git a/gcc/config/arm/cortex-a57.md b/gcc/config/arm/cortex-a57.md
index 93d756b..ac5876f 100644
--- a/gcc/config/arm/cortex-a57.md
+++ b/gcc/config/arm/cortex-a57.md
@@ -313,7 +313,7 @@
(define_insn_reservation "cortex_a57_alu_shift" 3
(and (eq_attr "tune" "cortexa57")
(eq_attr "type" "bfm,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
crc,logic_shift_imm,logics_shift_imm,\
mov_shift,mvn_shift"))
"ca57_mx")
diff --git a/gcc/config/arm/cortex-a7.md b/gcc/config/arm/cortex-a7.md
index 1106cf8..254b2cc 100644
--- a/gcc/config/arm/cortex-a7.md
+++ b/gcc/config/arm/cortex-a7.md
@@ -143,7 +143,7 @@
(define_insn_reservation "cortex_a7_alu_shift" 2
(and (eq_attr "tune" "cortexa7")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/cortex-a8.md b/gcc/config/arm/cortex-a8.md
index 9032cb3..23c617d 100644
--- a/gcc/config/arm/cortex-a8.md
+++ b/gcc/config/arm/cortex-a8.md
@@ -95,7 +95,7 @@
(define_insn_reservation "cortex_a8_alu_shift" 2
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
extend"))
"cortex_a8_default")
diff --git a/gcc/config/arm/cortex-a9.md b/gcc/config/arm/cortex-a9.md
index 3a880d7..6ddc120 100644
--- a/gcc/config/arm/cortex-a9.md
+++ b/gcc/config/arm/cortex-a9.md
@@ -93,7 +93,7 @@ cortex_a9_p1_e2 + cortex_a9_p0_e1 + cortex_a9_p1_e1")
;; An instruction using the shifter will go down E1.
(define_insn_reservation "cortex_a9_dp_shift" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/cortex-m4.md b/gcc/config/arm/cortex-m4.md
index 20037ca..4367b76 100644
--- a/gcc/config/arm/cortex-m4.md
+++ b/gcc/config/arm/cortex-m4.md
@@ -36,7 +36,7 @@
adc_imm,adcs_imm,adc_reg,adcs_reg,\
adr,bfm,clz,rbit,rev,alu_dsp_reg,\
shift_imm,shift_reg,extend,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/cortex-m7.md b/gcc/config/arm/cortex-m7.md
index b616a95..df03e06 100644
--- a/gcc/config/arm/cortex-m7.md
+++ b/gcc/config/arm/cortex-m7.md
@@ -54,7 +54,7 @@
;; Simple alu with inline shift operation.
(define_insn_reservation "cortex_m7_alu_shift" 2
(and (eq_attr "tune" "cortexm7")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm"))
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm"))
"cm7_i0|cm7_i1,(cm7_a0|cm7_a1)+cm7_shf+cm7_branch")
;; Only one ALU can be used for DSP instructions.
diff --git a/gcc/config/arm/cortex-r4.md b/gcc/config/arm/cortex-r4.md
index e8fad30..9be4b4c 100644
--- a/gcc/config/arm/cortex-r4.md
+++ b/gcc/config/arm/cortex-r4.md
@@ -92,7 +92,7 @@
(define_insn_reservation "cortex_r4_alu_shift" 2
(and (eq_attr "tune_cortexr4" "yes")
- (eq_attr "type" "alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
extend,mov_shift,mvn_shift"))
"cortex_r4_alu")
diff --git a/gcc/config/arm/exynos-m1.md b/gcc/config/arm/exynos-m1.md
index 48d0e9e..c31c850 100644
--- a/gcc/config/arm/exynos-m1.md
+++ b/gcc/config/arm/exynos-m1.md
@@ -386,7 +386,7 @@
(define_insn_reservation "exynos_m1_alu_shift" 2
(and (eq_attr "tune" "exynosm1")
(eq_attr "type" "alu_ext, alus_ext,\
- alu_shift_imm, alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other, alus_shift_imm,\
logic_shift_imm, logics_shift_imm,\
mov_shift, mvn_shift"))
"(em1_alu)")
diff --git a/gcc/config/arm/fa526.md b/gcc/config/arm/fa526.md
index e854be1..c8a2311 100644
--- a/gcc/config/arm/fa526.md
+++ b/gcc/config/arm/fa526.md
@@ -74,7 +74,7 @@
(define_insn_reservation "526_alu_shift_op" 2
(and (eq_attr "tune" "fa526")
(eq_attr "type" "extend,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/fa606te.md b/gcc/config/arm/fa606te.md
index d5dc24f..11e1484 100644
--- a/gcc/config/arm/fa606te.md
+++ b/gcc/config/arm/fa606te.md
@@ -67,7 +67,7 @@
adc_imm,adcs_imm,adc_reg,adcs_reg,\
adr,bfm,rev,\
shift_imm,shift_reg,extend,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/fa626te.md b/gcc/config/arm/fa626te.md
index 8901965..00cf7f6 100644
--- a/gcc/config/arm/fa626te.md
+++ b/gcc/config/arm/fa626te.md
@@ -80,7 +80,7 @@
(define_insn_reservation "626te_alu_shift_op" 2
(and (eq_attr "tune" "fa626,fa626te")
(eq_attr "type" "extend,\
- alu_shift_imm,alus_shift_imm,\
+ alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm,\
alu_shift_reg,alus_shift_reg,\
logic_shift_reg,logics_shift_reg,\
diff --git a/gcc/config/arm/fa726te.md b/gcc/config/arm/fa726te.md
index 4d52246..2fc54a8 100644
--- a/gcc/config/arm/fa726te.md
+++ b/gcc/config/arm/fa726te.md
@@ -100,7 +100,7 @@
;; it takes 3 cycles.
(define_insn_reservation "726te_alu_shift_op" 3
(and (eq_attr "tune" "fa726te")
- (eq_attr "type" "extend,alu_shift_imm,alus_shift_imm,\
+ (eq_attr "type" "extend,alu_shift_imm_lsl_1to4,alu_shift_imm_other,alus_shift_imm,\
logic_shift_imm,logics_shift_imm"))
"fa726te_issue+(fa726te_alu0_pipe|fa726te_alu1_pipe)")
diff --git a/gcc/config/arm/fmp626.md b/gcc/config/arm/fmp626.md
index 8fee678..b0f96ac 100644
--- a/gcc/config/arm/fmp626.md
+++ b/gcc/config/arm/fmp626.md
@@ -73,7 +73,7 @@
(define_insn_reservation "mp626_alu_shift_op" 2
(and (eq_attr "tune" "fmp626")
- (eq_attr "type" "alu_shift_imm,logic_shift_imm,alus_shift_imm,logics_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,logic_shift_imm,alus_shift_imm,logics_shift_imm,\
alu_shift_reg,logic_shift_reg,alus_shift_reg,logics_shift_reg,\
extend,\
mov_shift,mov_shift_reg,\
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index f934872..ecbc672 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -116,7 +116,7 @@
(define_mode_iterator VQ2BF [V16QI V8HI V8HF (V8BF "TARGET_BF16_SIMD") V4SI V4SF])
;; Quad-width vector modes with 16- or 32-bit elements
-(define_mode_iterator VQ_HS [V8HI V8HF V4SI V4SF])
+(define_mode_iterator VQ_HS [V8HI V8HF V4SI V4SF (V8BF "TARGET_BF16_SIMD")])
;; Quad-width vector modes plus 64-bit elements.
(define_mode_iterator VQX [V16QI V8HI V8HF V8BF V4SI V4SF V2DI])
@@ -1177,11 +1177,29 @@
(define_int_attr rot [(UNSPEC_VCADD90 "90")
(UNSPEC_VCADD270 "270")
+ (UNSPEC_VCMUL "0")
+ (UNSPEC_VCMUL90 "90")
+ (UNSPEC_VCMUL180 "180")
+ (UNSPEC_VCMUL270 "270")
(UNSPEC_VCMLA "0")
(UNSPEC_VCMLA90 "90")
(UNSPEC_VCMLA180 "180")
(UNSPEC_VCMLA270 "270")])
+(define_int_attr mve_rot [(UNSPEC_VCADD90 "_rot90")
+ (UNSPEC_VCADD270 "_rot270")
+ (UNSPEC_VCMLA "")
+ (UNSPEC_VCMLA90 "_rot90")
+ (UNSPEC_VCMLA180 "_rot180")
+ (UNSPEC_VCMLA270 "_rot270")
+ (UNSPEC_VCMUL "")
+ (UNSPEC_VCMUL90 "_rot90")
+ (UNSPEC_VCMUL180 "_rot180")
+ (UNSPEC_VCMUL270 "_rot270")])
+
+(define_int_iterator VCMUL [UNSPEC_VCMUL UNSPEC_VCMUL90
+ UNSPEC_VCMUL180 UNSPEC_VCMUL270])
+
(define_int_attr simd32_op [(UNSPEC_QADD8 "qadd8") (UNSPEC_QSUB8 "qsub8")
(UNSPEC_SHADD8 "shadd8") (UNSPEC_SHSUB8 "shsub8")
(UNSPEC_UHADD8 "uhadd8") (UNSPEC_UHSUB8 "uhsub8")
@@ -1216,7 +1234,7 @@
(define_int_attr supf [(VCVTQ_TO_F_S "s") (VCVTQ_TO_F_U "u") (VREV16Q_S "s")
(VREV16Q_U "u") (VMVNQ_N_S "s") (VMVNQ_N_U "u")
(VCVTAQ_U "u") (VCVTAQ_S "s") (VREV64Q_S "s")
- (VREV64Q_U "u") (VMVNQ_S "s") (VMVNQ_U "u")
+ (VREV64Q_U "u")
(VDUPQ_N_U "u") (VDUPQ_N_S"s") (VADDVQ_S "s")
(VADDVQ_U "u") (VADDVQ_S "s") (VADDVQ_U "u")
(VMOVLTQ_U "u") (VMOVLTQ_S "s") (VMOVLBQ_S "s")
@@ -1232,13 +1250,10 @@
(VADDLVQ_P_U "u") (VCMPNEQ_U "u") (VCMPNEQ_S "s")
(VABDQ_M_S "s") (VABDQ_M_U "u") (VABDQ_S "s")
(VABDQ_U "u") (VADDQ_N_S "s") (VADDQ_N_U "u")
- (VADDVQ_P_S "s") (VADDVQ_P_U "u") (VANDQ_S "s")
- (VANDQ_U "u") (VBICQ_S "s") (VBICQ_U "u")
- (VBRSRQ_N_S "s") (VBRSRQ_N_U "u") (VCADDQ_ROT270_S "s")
- (VCADDQ_ROT270_U "u") (VCADDQ_ROT90_S "s")
- (VCMPEQQ_S "s") (VCMPEQQ_U "u") (VCADDQ_ROT90_U "u")
+ (VADDVQ_P_S "s") (VADDVQ_P_U "u") (VBRSRQ_N_S "s")
+ (VBRSRQ_N_U "u") (VCMPEQQ_S "s") (VCMPEQQ_U "u")
(VCMPEQQ_N_S "s") (VCMPEQQ_N_U "u") (VCMPNEQ_N_S "s")
- (VCMPNEQ_N_U "u") (VEORQ_S "s") (VEORQ_U "u")
+ (VCMPNEQ_N_U "u")
(VHADDQ_N_S "s") (VHADDQ_N_U "u") (VHADDQ_S "s")
(VHADDQ_U "u") (VHSUBQ_N_S "s") (VHSUBQ_N_U "u")
(VHSUBQ_S "s") (VMAXQ_S "s") (VMAXQ_U "u") (VHSUBQ_U "u")
@@ -1248,8 +1263,8 @@
(VMULLBQ_INT_S "s") (VMULLBQ_INT_U "u") (VQADDQ_S "s")
(VMULLTQ_INT_S "s") (VMULLTQ_INT_U "u") (VQADDQ_U "u")
(VMULQ_N_S "s") (VMULQ_N_U "u") (VMULQ_S "s")
- (VMULQ_U "u") (VORNQ_S "s") (VORNQ_U "u") (VORRQ_S "s")
- (VORRQ_U "u") (VQADDQ_N_S "s") (VQADDQ_N_U "u")
+ (VMULQ_U "u") (VORNQ_S "s") (VORNQ_U "u")
+ (VQADDQ_N_S "s") (VQADDQ_N_U "u")
(VQRSHLQ_N_S "s") (VQRSHLQ_N_U "u") (VQRSHLQ_S "s")
(VQRSHLQ_U "u") (VQSHLQ_N_S "s") (VQSHLQ_N_U "u")
(VQSHLQ_R_S "s") (VQSHLQ_R_U "u") (VQSHLQ_S "s")
@@ -1477,7 +1492,6 @@
(define_int_iterator VCVTQ_FROM_F [VCVTQ_FROM_F_S VCVTQ_FROM_F_U])
(define_int_iterator VREV16Q [VREV16Q_U VREV16Q_S])
(define_int_iterator VCVTAQ [VCVTAQ_U VCVTAQ_S])
-(define_int_iterator VMVNQ [VMVNQ_U VMVNQ_S])
(define_int_iterator VDUPQ_N [VDUPQ_N_U VDUPQ_N_S])
(define_int_iterator VCLZQ [VCLZQ_U VCLZQ_S])
(define_int_iterator VADDVQ [VADDVQ_U VADDVQ_S])
@@ -1501,15 +1515,10 @@
(define_int_iterator VADDQ_N [VADDQ_N_S VADDQ_N_U])
(define_int_iterator VADDVAQ [VADDVAQ_S VADDVAQ_U])
(define_int_iterator VADDVQ_P [VADDVQ_P_U VADDVQ_P_S])
-(define_int_iterator VANDQ [VANDQ_U VANDQ_S])
-(define_int_iterator VBICQ [VBICQ_S VBICQ_U])
(define_int_iterator VBRSRQ_N [VBRSRQ_N_U VBRSRQ_N_S])
-(define_int_iterator VCADDQ_ROT270 [VCADDQ_ROT270_S VCADDQ_ROT270_U])
-(define_int_iterator VCADDQ_ROT90 [VCADDQ_ROT90_U VCADDQ_ROT90_S])
(define_int_iterator VCMPEQQ [VCMPEQQ_U VCMPEQQ_S])
(define_int_iterator VCMPEQQ_N [VCMPEQQ_N_S VCMPEQQ_N_U])
(define_int_iterator VCMPNEQ_N [VCMPNEQ_N_U VCMPNEQ_N_S])
-(define_int_iterator VEORQ [VEORQ_U VEORQ_S])
(define_int_iterator VHADDQ [VHADDQ_S VHADDQ_U])
(define_int_iterator VHADDQ_N [VHADDQ_N_U VHADDQ_N_S])
(define_int_iterator VHSUBQ [VHSUBQ_S VHSUBQ_U])
@@ -1525,7 +1534,6 @@
(define_int_iterator VMULQ [VMULQ_U VMULQ_S])
(define_int_iterator VMULQ_N [VMULQ_N_U VMULQ_N_S])
(define_int_iterator VORNQ [VORNQ_U VORNQ_S])
-(define_int_iterator VORRQ [VORRQ_S VORRQ_U])
(define_int_iterator VQADDQ [VQADDQ_U VQADDQ_S])
(define_int_iterator VQADDQ_N [VQADDQ_N_S VQADDQ_N_U])
(define_int_iterator VQRSHLQ [VQRSHLQ_S VQRSHLQ_U])
diff --git a/gcc/config/arm/marvell-pj4.md b/gcc/config/arm/marvell-pj4.md
index c415e0d..0255810 100644
--- a/gcc/config/arm/marvell-pj4.md
+++ b/gcc/config/arm/marvell-pj4.md
@@ -73,7 +73,7 @@
(define_insn_reservation "pj4_shift" 1
(and (eq_attr "tune" "marvell_pj4")
- (eq_attr "type" "alu_shift_imm,logic_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,logic_shift_imm,\
alus_shift_imm,logics_shift_imm,\
alu_shift_reg,logic_shift_reg,\
alus_shift_reg,logics_shift_reg,\
@@ -84,7 +84,7 @@
(define_insn_reservation "pj4_shift_conds" 4
(and (eq_attr "tune" "marvell_pj4")
- (eq_attr "type" "alu_shift_imm,logic_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,logic_shift_imm,\
alus_shift_imm,logics_shift_imm,\
alu_shift_reg,logic_shift_reg,\
alus_shift_reg,logics_shift_reg,\
@@ -96,7 +96,7 @@
(define_insn_reservation "pj4_alu_shift" 1
(and (eq_attr "tune" "marvell_pj4")
(not (eq_attr "conds" "set"))
- (eq_attr "type" "alu_shift_imm,logic_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,logic_shift_imm,\
alus_shift_imm,logics_shift_imm,\
alu_shift_reg,logic_shift_reg,\
alus_shift_reg,logics_shift_reg,\
@@ -107,7 +107,7 @@
(define_insn_reservation "pj4_alu_shift_conds" 4
(and (eq_attr "tune" "marvell_pj4")
(eq_attr "conds" "set")
- (eq_attr "type" "alu_shift_imm,logic_shift_imm,alus_shift_imm,logics_shift_imm,\
+ (eq_attr "type" "alu_shift_imm_lsl_1to4,alu_shift_imm_other,logic_shift_imm,alus_shift_imm,logics_shift_imm,\
alu_shift_reg,logic_shift_reg,alus_shift_reg,logics_shift_reg,\
extend,\
mov_shift,mvn_shift,mov_shift_reg,mvn_shift_reg"))
diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md
index ecbaaa9..d3f1cc1 100644
--- a/gcc/config/arm/mve.md
+++ b/gcc/config/arm/mve.md
@@ -271,8 +271,7 @@
(define_insn "mve_vnegq_f<mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")]
- VNEGQ_F))
+ (neg:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vneg.f%#<V_sz_elem> %q0, %q1"
@@ -422,8 +421,7 @@
(define_insn "mve_vnegq_s<mode>"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")]
- VNEGQ_S))
+ (neg:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
"vneg.s%#<V_sz_elem> %q0, %q1"
@@ -433,16 +431,22 @@
;;
;; [vmvnq_u, vmvnq_s])
;;
-(define_insn "mve_vmvnq_<supf><mode>"
+(define_insn "mve_vmvnq_u<mode>"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")]
- VMVNQ))
+ (not:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
- "vmvn %q0, %q1"
+ "vmvn\t%q0, %q1"
[(set_attr "type" "mve_move")
])
+(define_expand "mve_vmvnq_s<mode>"
+ [
+ (set (match_operand:MVE_2 0 "s_register_operand")
+ (not:MVE_2 (match_operand:MVE_2 1 "s_register_operand")))
+ ]
+ "TARGET_HAVE_MVE"
+)
;;
;; [vdupq_n_u, vdupq_n_s])
@@ -894,33 +898,54 @@
;;
;; [vandq_u, vandq_s])
;;
-(define_insn "mve_vandq_<supf><mode>"
+;; signed and unsigned versions are the same: define the unsigned
+;; insn, and use an expander for the signed one as we still reference
+;; both names from arm_mve.h.
+;; We use the same code as in neon.md (TODO: avoid this duplication).
+(define_insn "mve_vandq_u<mode>"
[
- (set (match_operand:MVE_2 0 "s_register_operand" "=w")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
- (match_operand:MVE_2 2 "s_register_operand" "w")]
- VANDQ))
+ (set (match_operand:MVE_2 0 "s_register_operand" "=w,w")
+ (and:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w,0")
+ (match_operand:MVE_2 2 "neon_inv_logic_op2" "w,DL")))
]
"TARGET_HAVE_MVE"
- "vand %q0, %q1, %q2"
+ "@
+ vand\t%q0, %q1, %q2
+ * return neon_output_logic_immediate (\"vand\", &operands[2], <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode));"
[(set_attr "type" "mve_move")
])
+(define_expand "mve_vandq_s<mode>"
+ [
+ (set (match_operand:MVE_2 0 "s_register_operand")
+ (and:MVE_2 (match_operand:MVE_2 1 "s_register_operand")
+ (match_operand:MVE_2 2 "neon_inv_logic_op2")))
+ ]
+ "TARGET_HAVE_MVE"
+)
;;
;; [vbicq_s, vbicq_u])
;;
-(define_insn "mve_vbicq_<supf><mode>"
+(define_insn "mve_vbicq_u<mode>"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
- (match_operand:MVE_2 2 "s_register_operand" "w")]
- VBICQ))
+ (and:MVE_2 (not:MVE_2 (match_operand:MVE_2 2 "s_register_operand" "w"))
+ (match_operand:MVE_2 1 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
- "vbic %q0, %q1, %q2"
+ "vbic\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
+(define_expand "mve_vbicq_s<mode>"
+ [
+ (set (match_operand:MVE_2 0 "s_register_operand")
+ (and:MVE_2 (not:MVE_2 (match_operand:MVE_2 2 "s_register_operand"))
+ (match_operand:MVE_2 1 "s_register_operand")))
+ ]
+ "TARGET_HAVE_MVE"
+)
+
;;
;; [vbrsrq_n_u, vbrsrq_n_s])
;;
@@ -937,34 +962,28 @@
])
;;
-;; [vcaddq_rot270_s, vcaddq_rot270_u])
+;; [vcaddq, vcaddq_rot90, vcadd_rot180, vcadd_rot270])
;;
-(define_insn "mve_vcaddq_rot270_<supf><mode>"
+(define_insn "mve_vcaddq<mve_rot><mode>"
[
(set (match_operand:MVE_2 0 "s_register_operand" "<earlyclobber_32>")
(unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
(match_operand:MVE_2 2 "s_register_operand" "w")]
- VCADDQ_ROT270))
+ VCADD))
]
"TARGET_HAVE_MVE"
- "vcadd.i%#<V_sz_elem> %q0, %q1, %q2, #270"
+ "vcadd.i%#<V_sz_elem> %q0, %q1, %q2, #<rot>"
[(set_attr "type" "mve_move")
])
-;;
-;; [vcaddq_rot90_u, vcaddq_rot90_s])
-;;
-(define_insn "mve_vcaddq_rot90_<supf><mode>"
- [
- (set (match_operand:MVE_2 0 "s_register_operand" "<earlyclobber_32>")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
- (match_operand:MVE_2 2 "s_register_operand" "w")]
- VCADDQ_ROT90))
- ]
- "TARGET_HAVE_MVE"
- "vcadd.i%#<V_sz_elem> %q0, %q1, %q2, #90"
- [(set_attr "type" "mve_move")
-])
+;; Auto vectorizer pattern for int vcadd
+(define_expand "cadd<rot><mode>3"
+ [(set (match_operand:MVE_2 0 "register_operand")
+ (unspec:MVE_2 [(match_operand:MVE_2 1 "register_operand")
+ (match_operand:MVE_2 2 "register_operand")]
+ VCADD))]
+ "TARGET_HAVE_MVE && !BYTES_BIG_ENDIAN"
+)
;;
;; [vcmpcsq_n_u])
@@ -1194,17 +1213,24 @@
;;
;; [veorq_u, veorq_s])
;;
-(define_insn "mve_veorq_<supf><mode>"
+(define_insn "mve_veorq_u<mode>"
[
(set (match_operand:MVE_2 0 "s_register_operand" "=w")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
- (match_operand:MVE_2 2 "s_register_operand" "w")]
- VEORQ))
+ (xor:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
+ (match_operand:MVE_2 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE"
- "veor %q0, %q1, %q2"
+ "veor\t%q0, %q1, %q2"
[(set_attr "type" "mve_move")
])
+(define_expand "mve_veorq_s<mode>"
+ [
+ (set (match_operand:MVE_2 0 "s_register_operand")
+ (xor:MVE_2 (match_operand:MVE_2 1 "s_register_operand")
+ (match_operand:MVE_2 2 "s_register_operand")))
+ ]
+ "TARGET_HAVE_MVE"
+)
;;
;; [vhaddq_n_u, vhaddq_n_s])
@@ -1600,17 +1626,30 @@
;;
;; [vorrq_s, vorrq_u])
;;
-(define_insn "mve_vorrq_<supf><mode>"
+;; signed and unsigned versions are the same: define the unsigned
+;; insn, and use an expander for the signed one as we still reference
+;; both names from arm_mve.h.
+;; We use the same code as in neon.md (TODO: avoid this duplication).
+(define_insn "mve_vorrq_s<mode>"
[
- (set (match_operand:MVE_2 0 "s_register_operand" "=w")
- (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
- (match_operand:MVE_2 2 "s_register_operand" "w")]
- VORRQ))
+ (set (match_operand:MVE_2 0 "s_register_operand" "=w,w")
+ (ior:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w,0")
+ (match_operand:MVE_2 2 "neon_logic_op2" "w,Dl")))
]
"TARGET_HAVE_MVE"
- "vorr %q0, %q1, %q2"
+ "@
+ vorr\t%q0, %q1, %q2
+ * return neon_output_logic_immediate (\"vorr\", &operands[2], <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode));"
[(set_attr "type" "mve_move")
])
+(define_expand "mve_vorrq_u<mode>"
+ [
+ (set (match_operand:MVE_2 0 "s_register_operand")
+ (ior:MVE_2 (match_operand:MVE_2 1 "s_register_operand")
+ (match_operand:MVE_2 2 "neon_logic_op2")))
+ ]
+ "TARGET_HAVE_MVE"
+)
;;
;; [vqaddq_n_s, vqaddq_n_u])
@@ -2019,9 +2058,8 @@
(define_insn "mve_vandq_f<mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VANDQ_F))
+ (and:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")
+ (match_operand:MVE_0 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vand %q0, %q1, %q2"
@@ -2034,9 +2072,8 @@
(define_insn "mve_vbicq_f<mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VBICQ_F))
+ (and:MVE_0 (not:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w"))
+ (match_operand:MVE_0 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vbic %q0, %q1, %q2"
@@ -2059,32 +2096,17 @@
])
;;
-;; [vcaddq_rot270_f])
+;; [vcaddq, vcaddq_rot90, vcadd_rot180, vcadd_rot270])
;;
-(define_insn "mve_vcaddq_rot270_f<mode>"
+(define_insn "mve_vcaddq<mve_rot><mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "<earlyclobber_32>")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
(match_operand:MVE_0 2 "s_register_operand" "w")]
- VCADDQ_ROT270_F))
+ VCADD))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcadd.f%#<V_sz_elem> %q0, %q1, %q2, #270"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcaddq_rot90_f])
-;;
-(define_insn "mve_vcaddq_rot90_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "<earlyclobber_32>")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VCADDQ_ROT90_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcadd.f%#<V_sz_elem> %q0, %q1, %q2, #90"
+ "vcadd.f%#<V_sz_elem> %q0, %q1, %q2, #<rot>"
[(set_attr "type" "mve_move")
])
@@ -2269,62 +2291,17 @@
])
;;
-;; [vcmulq_f])
+;; [vcmulq, vcmulq_rot90, vcmulq_rot180, vcmulq_rot270])
;;
-(define_insn "mve_vcmulq_f<mode>"
+(define_insn "mve_vcmulq<mve_rot><mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "<earlyclobber_32>")
(unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
(match_operand:MVE_0 2 "s_register_operand" "w")]
- VCMULQ_F))
+ VCMUL))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmul.f%#<V_sz_elem> %q0, %q1, %q2, #0"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcmulq_rot180_f])
-;;
-(define_insn "mve_vcmulq_rot180_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "<earlyclobber_32>")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VCMULQ_ROT180_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmul.f%#<V_sz_elem> %q0, %q1, %q2, #180"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcmulq_rot270_f])
-;;
-(define_insn "mve_vcmulq_rot270_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "<earlyclobber_32>")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VCMULQ_ROT270_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmul.f%#<V_sz_elem> %q0, %q1, %q2, #270"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcmulq_rot90_f])
-;;
-(define_insn "mve_vcmulq_rot90_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "<earlyclobber_32>")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VCMULQ_ROT90_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmul.f%#<V_sz_elem> %q0, %q1, %q2, #90"
+ "vcmul.f%#<V_sz_elem> %q0, %q1, %q2, #<rot>"
[(set_attr "type" "mve_move")
])
@@ -2379,9 +2356,8 @@
(define_insn "mve_veorq_f<mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VEORQ_F))
+ (xor:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")
+ (match_operand:MVE_0 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"veor %q0, %q1, %q2"
@@ -2646,9 +2622,8 @@
(define_insn "mve_vorrq_f<mode>"
[
(set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
- (match_operand:MVE_0 2 "s_register_operand" "w")]
- VORRQ_F))
+ (ior:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")
+ (match_operand:MVE_0 2 "s_register_operand" "w")))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
"vorr %q0, %q1, %q2"
@@ -4098,66 +4073,20 @@
[(set_attr "type" "mve_move")
(set_attr "length""8")])
;;
-;; [vcmlaq_f])
-;;
-(define_insn "mve_vcmlaq_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "0")
- (match_operand:MVE_0 2 "s_register_operand" "w")
- (match_operand:MVE_0 3 "s_register_operand" "w")]
- VCMLAQ_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmla.f%#<V_sz_elem> %q0, %q2, %q3, #0"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcmlaq_rot180_f])
+;; [vcmlaq, vcmlaq_rot90, vcmlaq_rot180, vcmlaq_rot270])
;;
-(define_insn "mve_vcmlaq_rot180_f<mode>"
+(define_insn "mve_vcmlaq<mve_rot><mode>"
[
- (set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "0")
- (match_operand:MVE_0 2 "s_register_operand" "w")
- (match_operand:MVE_0 3 "s_register_operand" "w")]
- VCMLAQ_ROT180_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmla.f%#<V_sz_elem> %q0, %q2, %q3, #180"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcmlaq_rot270_f])
-;;
-(define_insn "mve_vcmlaq_rot270_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "0")
- (match_operand:MVE_0 2 "s_register_operand" "w")
- (match_operand:MVE_0 3 "s_register_operand" "w")]
- VCMLAQ_ROT270_F))
- ]
- "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmla.f%#<V_sz_elem> %q0, %q2, %q3, #270"
- [(set_attr "type" "mve_move")
-])
-
-;;
-;; [vcmlaq_rot90_f])
-;;
-(define_insn "mve_vcmlaq_rot90_f<mode>"
- [
- (set (match_operand:MVE_0 0 "s_register_operand" "=w")
- (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "0")
- (match_operand:MVE_0 2 "s_register_operand" "w")
- (match_operand:MVE_0 3 "s_register_operand" "w")]
- VCMLAQ_ROT90_F))
+ (set (match_operand:MVE_0 0 "s_register_operand" "=w,w")
+ (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "0,Dz")
+ (match_operand:MVE_0 2 "s_register_operand" "w,w")
+ (match_operand:MVE_0 3 "s_register_operand" "w,w")]
+ VCMLA))
]
"TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
- "vcmla.f%#<V_sz_elem> %q0, %q2, %q3, #90"
+ "@
+ vcmla.f%#<V_sz_elem> %q0, %q2, %q3, #<rot>
+ vcmul.f%#<V_sz_elem> %q0, %q2, %q3, #<rot>"
[(set_attr "type" "mve_move")
])
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 2d76769..d2e92ba 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -690,7 +690,7 @@
(set_attr "predicable" "no")]
)
-(define_insn "ior<mode>3"
+(define_insn "ior<mode>3_neon"
[(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
(ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
(match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))]
@@ -712,7 +712,7 @@
;; corresponds to the canonical form the middle-end expects to use for
;; immediate bitwise-ANDs.
-(define_insn "and<mode>3"
+(define_insn "and<mode>3_neon"
[(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
(and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
(match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))]
@@ -747,7 +747,7 @@
[(set_attr "type" "neon_logic<q>")]
)
-(define_insn "xor<mode>3"
+(define_insn "xor<mode>3_neon"
[(set (match_operand:VDQ 0 "s_register_operand" "=w")
(xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
(match_operand:VDQ 2 "s_register_operand" "w")))]
@@ -756,7 +756,7 @@
[(set_attr "type" "neon_logic<q>")]
)
-(define_insn "one_cmpl<mode>2"
+(define_insn "one_cmpl<mode>2_neon"
[(set (match_operand:VDQ 0 "s_register_operand" "=w")
(not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
"TARGET_NEON"
@@ -775,7 +775,7 @@
(const_string "neon_abs<q>")))]
)
-(define_insn "neg<mode>2"
+(define_insn "neon_neg<mode>2"
[(set (match_operand:VDQW 0 "s_register_operand" "=w")
(neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))]
"TARGET_NEON"
@@ -786,7 +786,7 @@
(const_string "neon_neg<q>")))]
)
-(define_insn "<absneg_str><mode>2"
+(define_insn "neon_<absneg_str><mode>2"
[(set (match_operand:VH 0 "s_register_operand" "=w")
(ABSNEG:VH (match_operand:VH 1 "s_register_operand" "w")))]
"TARGET_NEON_FP16INST"
@@ -800,7 +800,7 @@
(ABSNEG:VH (match_operand:VH 1 "s_register_operand")))]
"TARGET_NEON_FP16INST"
{
- emit_insn (gen_<absneg_str><mode>2 (operands[0], operands[1]));
+ emit_insn (gen_neon_<absneg_str><mode>2 (operands[0], operands[1]));
DONE;
})
@@ -952,7 +952,7 @@
if (s_register_operand (operands[2], <MODE>mode))
{
rtx neg = gen_reg_rtx (<MODE>mode);
- emit_insn (gen_neg<mode>2 (neg, operands[2]));
+ emit_insn (gen_neon_neg<mode>2 (neg, operands[2]));
emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg));
}
else
@@ -969,7 +969,7 @@
if (s_register_operand (operands[2], <MODE>mode))
{
rtx neg = gen_reg_rtx (<MODE>mode);
- emit_insn (gen_neg<mode>2 (neg, operands[2]));
+ emit_insn (gen_neon_neg<mode>2 (neg, operands[2]));
emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg));
}
else
@@ -2953,7 +2953,7 @@
(match_operand:VDQW 1 "s_register_operand")]
"TARGET_NEON"
{
- emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
+ emit_insn (gen_neon_neg<mode>2 (operands[0], operands[1]));
DONE;
})
@@ -3240,7 +3240,7 @@
(match_operand:VDQIW 1 "s_register_operand")]
"TARGET_NEON"
{
- emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
+ emit_insn (gen_one_cmpl<mode>2_neon (operands[0], operands[1]));
DONE;
})
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 2144520..a24cdb7 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -18,6 +18,8 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(include "common.md")
+
(define_predicate "s_register_operand"
(match_code "reg,subreg")
{
@@ -107,7 +109,7 @@
(define_predicate "imm_for_neon_inv_logic_operand"
(match_code "const_vector")
{
- return (TARGET_NEON
+ return ((TARGET_NEON || TARGET_HAVE_MVE)
&& neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL));
})
@@ -118,7 +120,7 @@
(define_predicate "imm_for_neon_logic_operand"
(match_code "const_vector")
{
- return (TARGET_NEON
+ return ((TARGET_NEON || TARGET_HAVE_MVE)
&& neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL));
})
diff --git a/gcc/config/arm/t-rtems b/gcc/config/arm/t-rtems
index 94a2eb7..b2fcf57 100644
--- a/gcc/config/arm/t-rtems
+++ b/gcc/config/arm/t-rtems
@@ -17,8 +17,8 @@ MULTILIB_DIRNAMES += eb
MULTILIB_OPTIONS += mthumb
MULTILIB_DIRNAMES += thumb
-MULTILIB_OPTIONS += march=armv5te+fp/march=armv6-m/march=armv7-a/march=armv7-a+simd/march=armv7-r/march=armv7-r+fp/mcpu=cortex-m3/mcpu=cortex-m4/mcpu=cortex-m4+nofp/mcpu=cortex-m7
-MULTILIB_DIRNAMES += armv5te+fp armv6-m armv7-a armv7-a+simd armv7-r armv7-r+fp cortex-m3 cortex-m4 cortex-m4+nofp cortex-m7
+MULTILIB_OPTIONS += march=armv5te+fp/march=armv6-m/march=armv7-a/march=armv7-a+simd/march=armv7-r/march=armv7-r+fp/mcpu=cortex-r52/mcpu=cortex-m3/mcpu=cortex-m4/mcpu=cortex-m4+nofp/mcpu=cortex-m7
+MULTILIB_DIRNAMES += armv5te+fp armv6-m armv7-a armv7-a+simd armv7-r armv7-r+fp cortex-r52 cortex-m3 cortex-m4 cortex-m4+nofp cortex-m7
MULTILIB_OPTIONS += mfloat-abi=hard
MULTILIB_DIRNAMES += hard
@@ -31,6 +31,7 @@ MULTILIB_REQUIRED += mthumb/march=armv7-a+simd/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb/march=armv7-a
MULTILIB_REQUIRED += mthumb/march=armv7-r+fp/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb/march=armv7-r
+MULTILIB_REQUIRED += mthumb/mcpu=cortex-r52/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb/mcpu=cortex-m3
MULTILIB_REQUIRED += mthumb/mcpu=cortex-m4/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb/mcpu=cortex-m4+nofp
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index b5377a3..56705c9 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -43,27 +43,6 @@
-(define_insn "thumb1_movsi_symbol_ref"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "general_operand" ""))
- ]
- "TARGET_THUMB1
- && arm_disable_literal_pool
- && GET_CODE (operands[1]) == SYMBOL_REF"
- "*
- output_asm_insn (\"movs\\t%0, #:upper8_15:%1\", operands);
- output_asm_insn (\"lsls\\t%0, #8\", operands);
- output_asm_insn (\"adds\\t%0, #:upper0_7:%1\", operands);
- output_asm_insn (\"lsls\\t%0, #8\", operands);
- output_asm_insn (\"adds\\t%0, #:lower8_15:%1\", operands);
- output_asm_insn (\"lsls\\t%0, #8\", operands);
- output_asm_insn (\"adds\\t%0, #:lower0_7:%1\", operands);
- return \"\";
- "
- [(set_attr "length" "14")
- (set_attr "conds" "clob")]
-)
-
(define_insn "*thumb1_adddi3"
[(set (match_operand:DI 0 "register_operand" "=l")
(plus:DI (match_operand:DI 1 "register_operand" "%0")
@@ -696,40 +675,25 @@
case 7:
/* pure-code alternative: build the constant byte by byte,
instead of loading it from a constant pool. */
- {
- int i;
- HOST_WIDE_INT op1 = INTVAL (operands[1]);
- bool mov_done_p = false;
- rtx ops[2];
- ops[0] = operands[0];
+ if (arm_valid_symbolic_address_p (operands[1]))
+ {
+ output_asm_insn (\"movs\\t%0, #:upper8_15:%1\", operands);
+ output_asm_insn (\"lsls\\t%0, #8\", operands);
+ output_asm_insn (\"adds\\t%0, #:upper0_7:%1\", operands);
+ output_asm_insn (\"lsls\\t%0, #8\", operands);
+ output_asm_insn (\"adds\\t%0, #:lower8_15:%1\", operands);
+ output_asm_insn (\"lsls\\t%0, #8\", operands);
+ output_asm_insn (\"adds\\t%0, #:lower0_7:%1\", operands);
+ return \"\";
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ thumb1_gen_const_int_print (operands[0], INTVAL (operands[1]));
+ return \"\";
+ }
- /* Emit upper 3 bytes if needed. */
- for (i = 0; i < 3; i++)
- {
- int byte = (op1 >> (8 * (3 - i))) & 0xff;
-
- if (byte)
- {
- ops[1] = GEN_INT (byte);
- if (mov_done_p)
- output_asm_insn ("adds\t%0, %1", ops);
- else
- output_asm_insn ("movs\t%0, %1", ops);
- mov_done_p = true;
- }
-
- if (mov_done_p)
- output_asm_insn ("lsls\t%0, #8", ops);
- }
+ gcc_unreachable ();
- /* Emit lower byte if needed. */
- ops[1] = GEN_INT (op1 & 0xff);
- if (!mov_done_p)
- output_asm_insn ("movs\t%0, %1", ops);
- else if (op1 & 0xff)
- output_asm_insn ("adds\t%0, %1", ops);
- return "";
- }
case 8: return "ldr\t%0, %1";
case 9: return "str\t%1, %0";
case 10: return "mov\t%0, %1";
@@ -740,7 +704,7 @@
(set_attr "pool_range" "*,*,*,*,*,*,*, *,1018,*,*")
(set_attr "arch" "t1,t1,v8mb,t1,t1,t1,t1,t1,t1,t1,t1")
(set_attr "required_for_purecode" "no,no,no,no,no,no,no,yes,no,no,no")
- (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,nocond,nocond,nocond,nocond")])
+ (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,clob,nocond,nocond,nocond")])
; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively
; to see if we can load them in fewer instructions or fewer cycles.
@@ -827,7 +791,7 @@
&& !satisfies_constraint_K (operands[1])"
[(clobber (const_int 0))]
"
- thumb1_gen_const_int (operands[0], INTVAL (operands[1]));
+ thumb1_gen_const_int_rtl (operands[0], INTVAL (operands[1]));
DONE;
"
)
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 2a8fdf2..d502db4 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -1261,7 +1261,9 @@
(set_attr "shift" "1")
(set_attr "length" "2")
(set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "alu_shift_imm")
+ (if_then_else (match_operand 3 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other"))
(const_string "alu_shift_reg")))]
)
@@ -1530,7 +1532,7 @@
"orn%?\\t%0, %1, %2%S4"
[(set_attr "predicable" "yes")
(set_attr "shift" "2")
- (set_attr "type" "alu_shift_imm")]
+ (set_attr "autodetect_type" "alu_shift_operator4")]
)
(define_peephole2
diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md
index 83983452..3cf2cad 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -19,6 +19,19 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+; The insn need to autodetect for specific type attribute
+(define_attr "autodetect_type"
+ "none,
+ alu_shift_lsl_op2,
+ alu_shift_lsr_op2,
+ alu_shift_asr_op2,
+ alu_shift_mul_op3,
+ alu_shift_operator1,
+ alu_shift_operator2,
+ alu_shift_operator3,
+ alu_shift_operator4"
+ (const_string "none"))
+
; TYPE attribute is used to classify instructions for use in scheduling.
;
; Instruction classification:
@@ -39,16 +52,21 @@
; or an immediate operand. This excludes
; MOV and MVN but includes MOVT. This also excludes
; DSP-kind instructions. This is also the default.
-; alu_shift_imm any arithmetic instruction that has a source operand
-; shifted by a constant. This excludes simple shifts.
-; alu_shift_reg as alu_shift_imm, with the shift amount specified in a
+; alu_shift_imm_lsl_1to4
+; any arithmetic instruction that has a source operand
+; shifted left by a constant in range 1 to 4. This
+; excludes simple shifts.
+; alu_shift_imm_other
+; as alu_shift_imm_lsl_1to4, with the shift type is LSR or
+; ASR, or the shift amount is greater than or equal 5.
+; alu_shift_reg as alu_shift_imm_*, with the shift amount specified in a
; register.
; alu_dsp_reg any DSP-kind instruction like QSUB8.
; alus_ext From ARMv8-A: as alu_ext, setting condition flags.
; AArch64 Only.
; alus_imm as alu_imm, setting condition flags.
; alus_sreg as alu_sreg, setting condition flags.
-; alus_shift_imm as alu_shift_imm, setting condition flags.
+; alus_shift_imm as alu_shift_imm_*, setting condition flags.
; alus_shift_reg as alu_shift_reg, setting condition flags.
; bfm bitfield move operation.
; bfx bitfield extract operation.
@@ -565,7 +583,8 @@
alu_ext,\
alu_imm,\
alu_sreg,\
- alu_shift_imm,\
+ alu_shift_imm_lsl_1to4,\
+ alu_shift_imm_other,\
alu_shift_reg,\
alu_dsp_reg,\
alus_ext,\
@@ -1106,7 +1125,43 @@
mve_move,\
mve_store,\
mve_load"
- (const_string "untyped"))
+ (cond [(eq_attr "autodetect_type" "alu_shift_lsr_op2,alu_shift_asr_op2")
+ (const_string "alu_shift_imm_other")
+ (eq_attr "autodetect_type" "alu_shift_lsl_op2")
+ (if_then_else (match_operand 2 "const_1_to_4_operand")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other"))
+ (eq_attr "autodetect_type" "alu_shift_mul_op3")
+ (if_then_else (match_operand 3 "const_2_4_8_16_operand")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other"))
+ (eq_attr "autodetect_type" "alu_shift_operator1")
+ (if_then_else (match_operand 1 "alu_shift_reg_p")
+ (const_string "alu_shift_reg")
+ (if_then_else (match_operand 1 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other")))
+ (eq_attr "autodetect_type" "alu_shift_operator2")
+ (if_then_else (match_operand 2 "alu_shift_reg_p")
+ (const_string "alu_shift_reg")
+ (if_then_else (match_operand 2 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other")))
+ (eq_attr "autodetect_type" "alu_shift_operator3")
+ (if_then_else (match_operand 3 "alu_shift_reg_p")
+ (const_string "alu_shift_reg")
+ (if_then_else (match_operand 3 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other")))
+ (eq_attr "autodetect_type" "alu_shift_operator4")
+ (if_then_else (match_operand 4 "alu_shift_reg_p")
+ (const_string "alu_shift_reg")
+ (if_then_else (match_operand 4 "alu_shift_operator_lsl_1_to_4")
+ (const_string "alu_shift_imm_lsl_1to4")
+ (const_string "alu_shift_imm_other")))
+ ]
+ (const_string "untyped")))
+
; Is this an (integer side) multiply with a 32-bit (or smaller) result?
(define_attr "mul32" "no,yes"
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index a3844e9..6ed23a9 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -510,6 +510,10 @@
UNSPEC_VCMLA90
UNSPEC_VCMLA180
UNSPEC_VCMLA270
+ UNSPEC_VCMUL
+ UNSPEC_VCMUL90
+ UNSPEC_VCMUL180
+ UNSPEC_VCMUL270
UNSPEC_MATMUL_S
UNSPEC_MATMUL_U
UNSPEC_MATMUL_US
@@ -530,7 +534,6 @@
VRNDMQ_F
VRNDAQ_F
VREV64Q_F
- VNEGQ_F
VDUPQ_N_F
VABSQ_F
VREV32Q_F
@@ -549,9 +552,6 @@
VREV64Q_S
VREV64Q_U
VQABSQ_S
- VNEGQ_S
- VMVNQ_S
- VMVNQ_U
VDUPQ_N_U
VDUPQ_N_S
VCLZQ_U
@@ -601,15 +601,10 @@
VADDQ_N_S
VADDVAQ_S
VADDVQ_P_S
- VANDQ_S
- VBICQ_S
VBRSRQ_N_S
- VCADDQ_ROT270_S
- VCADDQ_ROT90_S
VCMPEQQ_S
VCMPEQQ_N_S
VCMPNEQ_N_S
- VEORQ_S
VHADDQ_S
VHADDQ_N_S
VHSUBQ_S
@@ -625,7 +620,6 @@
VMULQ_S
VMULQ_N_S
VORNQ_S
- VORRQ_S
VQADDQ_S
VQADDQ_N_S
VQRSHLQ_S
@@ -648,15 +642,10 @@
VADDQ_N_U
VADDVAQ_U
VADDVQ_P_U
- VANDQ_U
- VBICQ_U
VBRSRQ_N_U
- VCADDQ_ROT270_U
- VCADDQ_ROT90_U
VCMPEQQ_U
VCMPEQQ_N_U
VCMPNEQ_N_U
- VEORQ_U
VHADDQ_U
VHADDQ_N_U
VHSUBQ_U
@@ -672,7 +661,6 @@
VMULQ_U
VMULQ_N_U
VORNQ_U
- VORRQ_U
VQADDQ_U
VQADDQ_N_U
VQRSHLQ_U
@@ -721,10 +709,6 @@
VABDQ_M_U
VABDQ_F
VADDQ_N_F
- VANDQ_F
- VBICQ_F
- VCADDQ_ROT270_F
- VCADDQ_ROT90_F
VCMPEQQ_F
VCMPEQQ_N_F
VCMPGEQ_F
@@ -737,11 +721,6 @@
VCMPLTQ_N_F
VCMPNEQ_F
VCMPNEQ_N_F
- VCMULQ_F
- VCMULQ_ROT180_F
- VCMULQ_ROT270_F
- VCMULQ_ROT90_F
- VEORQ_F
VMAXNMAQ_F
VMAXNMAVQ_F
VMAXNMQ_F
@@ -753,7 +732,6 @@
VMULQ_F
VMULQ_N_F
VORNQ_F
- VORRQ_F
VSUBQ_F
VADDLVAQ_U
VADDLVAQ_S
@@ -914,7 +892,6 @@
VMLSLDAVAQ_S
VQSHRUNBQ_N_S
VQRSHRUNTQ_N_S
- VCMLAQ_F
VMINNMAQ_M_F
VFMASQ_N_F
VDUPQ_M_N_F
@@ -936,14 +913,12 @@
VADDLVAQ_P_S
VQMOVUNBQ_M_S
VCMPLEQ_M_F
- VCMLAQ_ROT180_F
VMLSLDAVAXQ_S
VRNDXQ_M_F
VFMSQ_F
VMINNMVQ_P_F
VMAXNMVQ_P_F
VPSELQ_F
- VCMLAQ_ROT90_F
VQMOVUNTQ_M_S
VREV64Q_M_F
VNEGQ_M_F
@@ -956,7 +931,6 @@
VRMLALDAVHQ_P_S
VRMLALDAVHXQ_P_S
VCMPEQQ_M_N_F
- VCMLAQ_ROT270_F
VMAXNMAQ_M_F
VRNDQ_M_F
VMLALDAVQ_P_U
diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md
index 250e503..ce1ea96 100644
--- a/gcc/config/arm/vec-common.md
+++ b/gcc/config/arm/vec-common.md
@@ -172,3 +172,46 @@
GEN_INT (elem), operands[0]));
DONE;
})
+
+(define_expand "and<mode>3"
+ [(set (match_operand:VDQ 0 "s_register_operand" "")
+ (and:VDQ (match_operand:VDQ 1 "s_register_operand" "")
+ (match_operand:VDQ 2 "neon_inv_logic_op2" "")))]
+ "ARM_HAVE_<MODE>_ARITH"
+)
+
+(define_expand "ior<mode>3"
+ [(set (match_operand:VDQ 0 "s_register_operand" "")
+ (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "")
+ (match_operand:VDQ 2 "neon_logic_op2" "")))]
+ "ARM_HAVE_<MODE>_ARITH"
+)
+
+(define_expand "xor<mode>3"
+ [(set (match_operand:VDQ 0 "s_register_operand" "")
+ (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "")
+ (match_operand:VDQ 2 "s_register_operand" "")))]
+ "ARM_HAVE_<MODE>_ARITH"
+)
+
+(define_expand "one_cmpl<mode>2"
+ [(set (match_operand:VDQ 0 "s_register_operand")
+ (not:VDQ (match_operand:VDQ 1 "s_register_operand")))]
+ "ARM_HAVE_<MODE>_ARITH"
+)
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:VDQWH 0 "s_register_operand" "")
+ (neg:VDQWH (match_operand:VDQWH 1 "s_register_operand" "")))]
+ "ARM_HAVE_<MODE>_ARITH"
+)
+
+(define_expand "cadd<rot><mode>3"
+ [(set (match_operand:VF 0 "register_operand")
+ (unspec:VF [(match_operand:VF 1 "register_operand")
+ (match_operand:VF 2 "register_operand")]
+ VCADD))]
+ "(TARGET_COMPLEX || (TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT
+ && ARM_HAVE_<MODE>_ARITH)) && !BYTES_BIG_ENDIAN"
+)
+
diff --git a/gcc/config/arm/xgene1.md b/gcc/config/arm/xgene1.md
index a2f6b8a1..5860adc 100644
--- a/gcc/config/arm/xgene1.md
+++ b/gcc/config/arm/xgene1.md
@@ -132,7 +132,7 @@
(define_insn_reservation "xgene1_alu" 1
(and (eq_attr "tune" "xgene1")
- (eq_attr "type" "alu_imm,alu_sreg,alu_shift_imm,\
+ (eq_attr "type" "alu_imm,alu_sreg,alu_shift_imm_lsl_1to4,alu_shift_imm_other,\
alu_ext,adc_reg,logic_imm,\
logic_reg,logic_shift_imm,clz,\
rbit,adr,mov_reg,shift_imm,\
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index fac3114..5d849da 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -19,7 +19,7 @@
; <http://www.gnu.org/licenses/>.
mcall-prologues
-Target Report Mask(CALL_PROLOGUES)
+Target Mask(CALL_PROLOGUES)
Use subroutines for function prologues and epilogues.
mmcu=
@@ -27,7 +27,7 @@ Target RejectNegative Joined Var(avr_mmcu) MissingArgError(missing device or arc
-mmcu=MCU Select the target MCU.
mgas-isr-prologues
-Target Report Var(avr_gasisr_prologues) UInteger Init(0)
+Target Var(avr_gasisr_prologues) UInteger Init(0)
Allow usage of __gcc_isr pseudo instructions in ISR prologues and epilogues.
mn-flash=
@@ -35,100 +35,100 @@ Target RejectNegative Joined Var(avr_n_flash) UInteger Init(-1)
Set the number of 64 KiB flash segments.
mskip-bug
-Target Report Mask(SKIP_BUG)
+Target Mask(SKIP_BUG)
Indicate presence of a processor erratum.
mrmw
-Target Report Mask(RMW)
+Target Mask(RMW)
Enable Read-Modify-Write (RMW) instructions support/use.
mdeb
-Target Report Undocumented Mask(ALL_DEBUG)
+Target Undocumented Mask(ALL_DEBUG)
mlog=
Target RejectNegative Joined Undocumented Var(avr_log_details)
mshort-calls
-Target Report RejectNegative Mask(SHORT_CALLS)
+Target RejectNegative Mask(SHORT_CALLS)
Use RJMP / RCALL even though CALL / JMP are available.
mint8
-Target Report Mask(INT8)
+Target Mask(INT8)
Use an 8-bit 'int' type.
mno-interrupts
-Target Report RejectNegative Mask(NO_INTERRUPTS)
+Target RejectNegative Mask(NO_INTERRUPTS)
Change the stack pointer without disabling interrupts.
mbranch-cost=
-Target Report Joined RejectNegative UInteger Var(avr_branch_cost) Init(0)
+Target Joined RejectNegative UInteger Var(avr_branch_cost) Init(0)
Set the branch costs for conditional branch instructions. Reasonable values are small, non-negative integers. The default branch cost is 0.
mmain-is-OS_task
-Target Report Mask(MAIN_IS_OS_TASK)
+Target Mask(MAIN_IS_OS_TASK)
Treat main as if it had attribute OS_task.
morder1
-Target Report Undocumented Mask(ORDER_1)
+Target Undocumented Mask(ORDER_1)
morder2
-Target Report Undocumented Mask(ORDER_2)
+Target Undocumented Mask(ORDER_2)
mtiny-stack
-Target Report Mask(TINY_STACK)
+Target Mask(TINY_STACK)
Change only the low 8 bits of the stack pointer.
mrelax
-Target Report
+Target
Relax branches.
mpmem-wrap-around
-Target Report
+Target
Make the linker relaxation machine assume that a program counter wrap-around occurs.
maccumulate-args
-Target Report Mask(ACCUMULATE_OUTGOING_ARGS)
+Target Mask(ACCUMULATE_OUTGOING_ARGS)
Accumulate outgoing function arguments and acquire/release the needed stack space for outgoing function arguments in function prologue/epilogue. Without this option, outgoing arguments are pushed before calling a function and popped afterwards. This option can lead to reduced code size for functions that call many functions that get their arguments on the stack like, for example printf.
mstrict-X
-Target Report Var(avr_strict_X) Init(0)
+Target Var(avr_strict_X) Init(0)
When accessing RAM, use X as imposed by the hardware, i.e. just use pre-decrement, post-increment and indirect addressing with the X register. Without this option, the compiler may assume that there is an addressing mode X+const similar to Y+const and Z+const and emit instructions to emulate such an addressing mode for X.
;; For rationale behind -msp8 see explanation in avr.h.
msp8
-Target Report RejectNegative Var(avr_sp8) Init(0)
+Target RejectNegative Var(avr_sp8) Init(0)
The device has no SPH special function register. This option will be overridden by the compiler driver with the correct setting if presence/absence of SPH can be deduced from -mmcu=MCU.
Waddr-space-convert
-Warning C Report Var(avr_warn_addr_space_convert) Init(0)
+Warning C Var(avr_warn_addr_space_convert) Init(0)
Warn if the address space of an address is changed.
Wmisspelled-isr
-Warning C C++ Report Var(avr_warn_misspelled_isr) Init(1)
+Warning C C++ Var(avr_warn_misspelled_isr) Init(1)
Warn if the ISR is misspelled, i.e. without __vector prefix. Enabled by default.
mfract-convert-truncate
-Target Report Mask(FRACT_CONV_TRUNC)
+Target Mask(FRACT_CONV_TRUNC)
Allow to use truncation instead of rounding towards zero for fractional fixed-point types.
mabsdata
-Target Report Mask(ABSDATA)
+Target Mask(ABSDATA)
Assume that all data in static storage can be accessed by LDS / STS. This option is only useful for reduced Tiny devices.
mdouble=
-Target Report Joined RejectNegative Var(avr_double) Init(0) Enum(avr_bits_e)
+Target Joined RejectNegative Var(avr_double) Init(0) Enum(avr_bits_e)
-mdouble=<BITS> Use <BITS> bits wide double type.
mlong-double=
-Target Report Joined RejectNegative Var(avr_long_double) Init(0) Enum(avr_bits_e)
+Target Joined RejectNegative Var(avr_long_double) Init(0) Enum(avr_bits_e)
-mlong-double=<BITS> Use <BITS> bits wide long double type.
nodevicelib
-Driver Target Report RejectNegative
+Driver Target RejectNegative
Do not link against the device-specific library lib<MCU>.a.
nodevicespecs
-Driver Target Report RejectNegative
+Driver Target RejectNegative
Do not use the device-specific specs file device-specs/specs-<MCU>.
Enum
diff --git a/gcc/config/bfin/bfin.opt b/gcc/config/bfin/bfin.opt
index afda508..cf5ba80 100644
--- a/gcc/config/bfin/bfin.opt
+++ b/gcc/config/bfin/bfin.opt
@@ -44,28 +44,28 @@ Target RejectNegative Joined
Specify the name of the target CPU.
momit-leaf-frame-pointer
-Target Report Mask(OMIT_LEAF_FRAME_POINTER)
+Target Mask(OMIT_LEAF_FRAME_POINTER)
Omit frame pointer for leaf functions.
mlow64k
-Target Report Mask(LOW_64K)
+Target Mask(LOW_64K)
Program is entirely located in low 64k of memory.
mcsync-anomaly
-Target Report Var(bfin_csync_anomaly) Init(-1)
+Target Var(bfin_csync_anomaly) Init(-1)
Work around a hardware anomaly by adding a number of NOPs before a
CSYNC or SSYNC instruction.
mspecld-anomaly
-Target Report Var(bfin_specld_anomaly) Init(-1)
+Target Var(bfin_specld_anomaly) Init(-1)
Avoid speculative loads to work around a hardware anomaly.
mid-shared-library
-Target Report Mask(ID_SHARED_LIBRARY)
+Target Mask(ID_SHARED_LIBRARY)
Enabled ID based shared library.
mleaf-id-shared-library
-Target Report Mask(LEAF_ID_SHARED_LIBRARY)
+Target Mask(LEAF_ID_SHARED_LIBRARY)
Generate code that won't be linked against any other ID shared libraries,
but may be used as a shared library.
@@ -74,45 +74,45 @@ Target RejectNegative Joined UInteger Var(bfin_library_id)
ID of shared library to build.
msep-data
-Target Report Mask(SEP_DATA)
+Target Mask(SEP_DATA)
Enable separate data segment.
mlong-calls
-Target Report Mask(LONG_CALLS)
+Target Mask(LONG_CALLS)
Avoid generating pc-relative calls; use indirection.
mfast-fp
-Target Report Mask(FAST_FP)
+Target Mask(FAST_FP)
Link with the fast floating-point library.
mfdpic
-Target Report Mask(FDPIC)
+Target Mask(FDPIC)
Enable Function Descriptor PIC mode.
minline-plt
-Target Report Mask(INLINE_PLT)
+Target Mask(INLINE_PLT)
Enable inlining of PLT in function calls.
mstack-check-l1
-Target Report Mask(STACK_CHECK_L1)
+Target Mask(STACK_CHECK_L1)
Do stack checking using bounds in L1 scratch memory.
mmulticore
-Target Report Mask(MULTICORE)
+Target Mask(MULTICORE)
Enable multicore support.
mcorea
-Target Report Mask(COREA)
+Target Mask(COREA)
Build for Core A.
mcoreb
-Target Report Mask(COREB)
+Target Mask(COREB)
Build for Core B.
msdram
-Target Report Mask(SDRAM)
+Target Mask(SDRAM)
Build for SDRAM.
micplb
-Target Report Mask(ICPLB)
+Target Mask(ICPLB)
Assume ICPLBs are enabled at runtime.
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index 6aa8584..1782718 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -111,17 +111,17 @@ Enum(bpf_kernel) String(5.2) Value(LINUX_V5_2)
; Use xBPF extensions.
mxbpf
-Target Report Mask(XBPF)
+Target Mask(XBPF)
Generate xBPF.
; Selecting big endian or little endian targets.
mbig-endian
-Target RejectNegative Report Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Generate big-endian eBPF.
mlittle-endian
-Target RejectNegative Report InverseMask(BIG_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN)
Generate little-endian eBPF.
mframe-limit=
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 9aa7ef0..78b2bff 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -725,9 +725,10 @@ c6x_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
}
#ifdef CLEAR_INSN_CACHE
tramp = XEXP (tramp, 0);
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__gnu_clear_cache"),
- LCT_NORMAL, VOIDmode, tramp, Pmode,
- plus_constant (Pmode, tramp, TRAMPOLINE_SIZE), Pmode);
+ maybe_emit_call_builtin___clear_cache (tramp,
+ plus_constant (Pmode,
+ tramp,
+ TRAMPOLINE_SIZE));
#endif
}
diff --git a/gcc/config/c6x/c6x.opt b/gcc/config/c6x/c6x.opt
index 16867a6..d0042fa 100644
--- a/gcc/config/c6x/c6x.opt
+++ b/gcc/config/c6x/c6x.opt
@@ -26,11 +26,11 @@ SourceInclude
config/c6x/c6x-opts.h
mbig-endian
-Target Report RejectNegative Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Use big-endian byte order.
mlittle-endian
-Target Report RejectNegative InverseMask(BIG_ENDIAN, LITTLE_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN, LITTLE_ENDIAN)
Use little-endian byte order.
msim
@@ -59,7 +59,7 @@ Target Mask(DSBT)
Compile for the DSBT shared library ABI.
mlong-calls
-Target Report Mask(LONG_CALLS)
+Target Mask(LONG_CALLS)
Avoid generating pc-relative calls; use indirection.
march=
diff --git a/gcc/config/cr16/cr16.opt b/gcc/config/cr16/cr16.opt
index f82c1d6..1d2a6a1 100644
--- a/gcc/config/cr16/cr16.opt
+++ b/gcc/config/cr16/cr16.opt
@@ -23,11 +23,11 @@ Target
Use simulator runtime.
mbit-ops
-Target Report Mask(BIT_OPS)
+Target Mask(BIT_OPS)
Generate SBIT, CBIT instructions.
mmac
-Target Report Mask(MAC)
+Target Mask(MAC)
Support multiply accumulate instructions.
mdebug-addr
diff --git a/gcc/config/cris/cris.opt b/gcc/config/cris/cris.opt
index e574a0a..f1f66e7 100644
--- a/gcc/config/cris/cris.opt
+++ b/gcc/config/cris/cris.opt
@@ -41,111 +41,111 @@
; driver-like program that gets a mapping of I/O registers (all
; on the same page, including the TLB registers).
mmul-bug-workaround
-Target Report Mask(MUL_BUG)
+Target Mask(MUL_BUG)
Work around bug in multiplication instruction.
; TARGET_ETRAX4_ADD: Instruction-set additions from Etrax 4 and up.
; (Just "lz".)
metrax4
-Target Report Mask(ETRAX4_ADD)
+Target Mask(ETRAX4_ADD)
Compile for ETRAX 4 (CRIS v3).
; See cris_handle_option.
metrax100
-Target Report RejectNegative
+Target RejectNegative
Compile for ETRAX 100 (CRIS v8).
; See cris_handle_option.
mno-etrax100
-Target Report RejectNegative Undocumented
+Target RejectNegative Undocumented
mpdebug
-Target Report Mask(PDEBUG)
+Target Mask(PDEBUG)
Emit verbose debug information in assembly code.
; TARGET_CCINIT: Whether to use condition-codes generated by
; insns other than the immediately preceding compare/test insn.
; Used to check for errors in notice_update_cc.
mcc-init
-Target Report Mask(CCINIT)
+Target Mask(CCINIT)
Do not use condition codes from normal instructions.
; TARGET_SIDE_EFFECT_PREFIXES: Whether to use side-effect
; patterns. Used to debug the [rx=ry+i] type patterns.
mside-effects
-Target Report RejectNegative Mask(SIDE_EFFECT_PREFIXES) Undocumented
+Target RejectNegative Mask(SIDE_EFFECT_PREFIXES) Undocumented
mno-side-effects
-Target Report RejectNegative InverseMask(SIDE_EFFECT_PREFIXES)
+Target RejectNegative InverseMask(SIDE_EFFECT_PREFIXES)
Do not emit addressing modes with side-effect assignment.
; TARGET_STACK_ALIGN: Whether to *keep* (not force) alignment of
; stack at 16 (or 32, depending on TARGET_ALIGN_BY_32) bits.
mstack-align
-Target Report RejectNegative Mask(STACK_ALIGN) Undocumented
+Target RejectNegative Mask(STACK_ALIGN) Undocumented
mno-stack-align
-Target Report RejectNegative InverseMask(STACK_ALIGN)
+Target RejectNegative InverseMask(STACK_ALIGN)
Do not tune stack alignment.
; TARGET_DATA_ALIGN: Whether to do alignment on individual
; modifiable objects.
mdata-align
-Target Report RejectNegative Mask(DATA_ALIGN) Undocumented
+Target RejectNegative Mask(DATA_ALIGN) Undocumented
mno-data-align
-Target Report RejectNegative InverseMask(DATA_ALIGN)
+Target RejectNegative InverseMask(DATA_ALIGN)
Do not tune writable data alignment.
; TARGET_CONST_ALIGN: Whether to do alignment on individual
; non-modifiable objects.
mconst-align
-Target Report RejectNegative Mask(CONST_ALIGN) Undocumented
+Target RejectNegative Mask(CONST_ALIGN) Undocumented
mno-const-align
-Target Report RejectNegative InverseMask(CONST_ALIGN)
+Target RejectNegative InverseMask(CONST_ALIGN)
Do not tune code and read-only data alignment.
; See cris_handle_option.
m32-bit
-Target Report RejectNegative Undocumented
+Target RejectNegative Undocumented
; See cris_handle_option.
m32bit
-Target Report RejectNegative
+Target RejectNegative
Align code and data to 32 bits.
; See cris_handle_option.
m16-bit
-Target Report RejectNegative Undocumented
+Target RejectNegative Undocumented
; See cris_handle_option.
m16bit
-Target Report RejectNegative Undocumented
+Target RejectNegative Undocumented
; See cris_handle_option.
m8-bit
-Target Report RejectNegative Undocumented
+Target RejectNegative Undocumented
; See cris_handle_option.
m8bit
-Target Report RejectNegative
+Target RejectNegative
Don't align items in code or data.
; TARGET_PROLOGUE_EPILOGUE: Whether or not to omit function
; prologue and epilogue.
mprologue-epilogue
-Target Report RejectNegative Mask(PROLOGUE_EPILOGUE) Undocumented
+Target RejectNegative Mask(PROLOGUE_EPILOGUE) Undocumented
mno-prologue-epilogue
-Target Report RejectNegative InverseMask(PROLOGUE_EPILOGUE)
+Target RejectNegative InverseMask(PROLOGUE_EPILOGUE)
Do not emit function prologue or epilogue.
; We have to handle this m-option here since we can't wash it
; off in both CC1_SPEC and CC1PLUS_SPEC.
mbest-lib-options
-Target Report RejectNegative
+Target RejectNegative
Use the most feature-enabling options allowed by other options.
; FIXME: The following comment relates to gcc before cris.opt.
@@ -154,37 +154,37 @@ Use the most feature-enabling options allowed by other options.
; gcc.c to forget it, if there's a "later" -mbest-lib-options.
; Kludgy, but needed for some multilibbed files.
moverride-best-lib-options
-Target Report RejectNegative
+Target RejectNegative
Override -mbest-lib-options.
mcpu=
-Target Report RejectNegative Joined Undocumented Var(cris_cpu_str)
+Target RejectNegative Joined Undocumented Var(cris_cpu_str)
march=
-Target Report RejectNegative Joined Var(cris_cpu_str)
+Target RejectNegative Joined Var(cris_cpu_str)
-march=ARCH Generate code for the specified chip or CPU version.
mtune=
-Target Report RejectNegative Joined Var(cris_tune_str)
+Target RejectNegative Joined Var(cris_tune_str)
-mtune=ARCH Tune alignment for the specified chip or CPU version.
mmax-stackframe=
-Target Report RejectNegative Joined Var(cris_max_stackframe_str)
+Target RejectNegative Joined Var(cris_max_stackframe_str)
-mmax-stackframe=SIZE Warn when a stackframe is larger than the specified size.
max-stackframe=
-Target Report RejectNegative Joined Undocumented Var(cris_max_stackframe_str)
+Target RejectNegative Joined Undocumented Var(cris_max_stackframe_str)
mtrap-using-break8
-Target Report Var(cris_trap_using_break8) Init(2)
+Target Var(cris_trap_using_break8) Init(2)
Emit traps as \"break 8\", default for CRIS v3 and up. If disabled, calls to abort() are used.
mtrap-unaligned-atomic
-Target Report Var(cris_trap_unaligned_atomic) Init(2)
+Target Var(cris_trap_unaligned_atomic) Init(2)
Emit checks causing \"break 8\" instructions to execute when applying atomic builtins on misaligned memory.
munaligned-atomic-may-use-library
-Target Report Var(cris_atomics_calling_libfunc) Init(2)
+Target Var(cris_atomics_calling_libfunc) Init(2)
Handle atomic builtins that may be applied to unaligned data by calling library functions. Overrides -mtrap-unaligned-atomic.
; TARGET_SVINTO: Currently this just affects alignment. FIXME:
diff --git a/gcc/config/cris/elf.opt b/gcc/config/cris/elf.opt
index 103c712..f32b0c6 100644
--- a/gcc/config/cris/elf.opt
+++ b/gcc/config/cris/elf.opt
@@ -19,7 +19,7 @@
; <http://www.gnu.org/licenses/>.
melf
-Target Report RejectNegative Undocumented
+Target RejectNegative Undocumented
sim
Driver JoinedOrMissing
diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
index 5aa2336..3b03f3f 100644
--- a/gcc/config/csky/csky.c
+++ b/gcc/config/csky/csky.c
@@ -5917,9 +5917,10 @@ csky_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
emit_move_insn (mem, fnaddr);
a_tramp = XEXP (m_tramp, 0);
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
- LCT_NORMAL, VOIDmode, a_tramp, Pmode,
- plus_constant (Pmode, a_tramp, TRAMPOLINE_SIZE), Pmode);
+ maybe_emit_call_builtin___clear_cache (a_tramp,
+ plus_constant (Pmode,
+ a_tramp,
+ TRAMPOLINE_SIZE));
}
diff --git a/gcc/config/csky/csky.opt b/gcc/config/csky/csky.opt
index 505a764..d5fbbdc 100644
--- a/gcc/config/csky/csky.opt
+++ b/gcc/config/csky/csky.opt
@@ -27,7 +27,7 @@ config/csky/csky_opts.h
; For backward compatibility only.
march=ck803s
-Target Report Var(flag_arch_ck803s) Undocumented
+Target Var(flag_arch_ck803s) Undocumented
march=
Target RejectNegative ToLower Joined Enum(csky_arch) Var(csky_arch_option) Save
@@ -40,18 +40,18 @@ Specify the target processor.
;; Endianness options.
mbig-endian
-Target RejectNegative Report Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Generate big-endian code.
EB
-Target RejectNegative Report Alias(mbig-endian) Undocumented
+Target RejectNegative Alias(mbig-endian) Undocumented
mlittle-endian
-Target RejectNegative Report InverseMask(BIG_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN)
Generate little-endian code.
EL
-Target RejectNegative Report Alias(mlittle-endian) Undocumented
+Target RejectNegative Alias(mlittle-endian) Undocumented
;; Floating point options. These affect code generation but not
;; assembly.
@@ -90,11 +90,11 @@ Target RejectNegative Joined Enum(csky_fpu) Var(csky_fpu_index) Init(TARGET_FPU_
Specify the target floating-point hardware/format.
mdouble-float
-Target Report Var(TARGET_DOUBLE_FLOAT) Init(-1)
+Target Var(TARGET_DOUBLE_FLOAT) Init(-1)
Generate C-SKY FPU double float instructions (default for hard float).
mfdivdu
-Target Report Var(TARGET_FDIVDU) Init(-1)
+Target Var(TARGET_FDIVDU) Init(-1)
Generate frecipd/fsqrtd/fdivd instructions (default for hard float).
;; Instruction set extensions. Most of these don't affect code
@@ -102,95 +102,95 @@ Generate frecipd/fsqrtd/fdivd instructions (default for hard float).
;; There are builtin preprocessor defines for each of these.
melrw
-Target Report Var(TARGET_ELRW) Init(-1)
+Target Var(TARGET_ELRW) Init(-1)
Enable the extended LRW instruction (default for CK801).
mistack
-Target Report Mask(ISTACK)
+Target Mask(ISTACK)
Enable interrupt stack instructions.
mmp
-Target Report RejectNegative Mask(MP)
+Target RejectNegative Mask(MP)
Enable multiprocessor instructions.
mcp
-Target Report RejectNegative Mask(CP)
+Target RejectNegative Mask(CP)
Enable coprocessor instructions.
mcache
-Target Report RejectNegative Mask(CACHE)
+Target RejectNegative Mask(CACHE)
Enable cache prefetch instructions.
msecurity
-Target Report RejectNegative Mask(SECURITY)
+Target RejectNegative Mask(SECURITY)
Enable C-SKY SECURE instructions.
mmac
-Target Report RejectNegative Alias(msecurity) Undocumented
+Target RejectNegative Alias(msecurity) Undocumented
mtrust
-Target Report RejectNegative Mask(TRUST)
+Target RejectNegative Mask(TRUST)
Enable C-SKY TRUST instructions.
mdsp
-Target Report RejectNegative Var(TARGET_DSP)
+Target RejectNegative Var(TARGET_DSP)
Enable C-SKY DSP instructions.
medsp
-Target Report RejectNegative Mask(EDSP)
+Target RejectNegative Mask(EDSP)
Enable C-SKY Enhanced DSP instructions.
mvdsp
-Target Report RejectNegative Mask(VDSP)
+Target RejectNegative Mask(VDSP)
Enable C-SKY Vector DSP instructions.
;; Code generation options not passed to the assembler.
mdiv
-Target Report Var(TARGET_DIV) Init(-1)
+Target Var(TARGET_DIV) Init(-1)
Generate divide instructions.
msmart
-Target Report Var(TARGET_MINI_REGISTERS) Init(-1)
+Target Var(TARGET_MINI_REGISTERS) Init(-1)
Generate code for Smart Mode.
mhigh-registers
-Target Report Var(TARGET_HIGH_REGISTERS) Init(-1)
+Target Var(TARGET_HIGH_REGISTERS) Init(-1)
Enable use of R16-R31 (default).
manchor
-Target Report Var(TARGET_ANCHOR)
+Target Var(TARGET_ANCHOR)
Generate code using global anchor symbol addresses.
mpushpop
-Target Report Var(TARGET_PUSHPOP) Init(1)
+Target Var(TARGET_PUSHPOP) Init(1)
Generate push/pop instructions (default).
mmultiple-stld
-Target Report Var(TARGET_MULTIPLE_STLD) Init(-1)
+Target Var(TARGET_MULTIPLE_STLD) Init(-1)
Generate stm/ldm instructions (default).
mstm
-Target Report Alias(mmultiple-stld) Undocumented
+Target Alias(mmultiple-stld) Undocumented
mconstpool
-Target Report Var(TARGET_CONSTANT_POOL) Init(-1)
+Target Var(TARGET_CONSTANT_POOL) Init(-1)
Generate constant pools in the compiler instead of assembler.
mstack-size
-Target Report Var(TARGET_STACK_SIZE) Init(0)
+Target Var(TARGET_STACK_SIZE) Init(0)
Emit .stack_size directives.
mccrt
-Target Report Var(TARGET_LIBCCRT) Init(0)
+Target Var(TARGET_LIBCCRT) Init(0)
Generate code for C-SKY compiler runtime instead of libgcc.
mbranch-cost=
-Target Report Joined RejectNegative UInteger Var(csky_branch_cost) Init(1)
+Target Joined RejectNegative UInteger Var(csky_branch_cost) Init(1)
Set the branch costs to roughly the specified number of instructions.
msched-prolog
-Target Report Var(flag_sched_prolog) Init(0)
+Target Var(flag_sched_prolog) Init(0)
Permit scheduling of function prologue and epilogue sequences.
msim
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
index e3b999e..9617230 100644
--- a/gcc/config/darwin-c.c
+++ b/gcc/config/darwin-c.c
@@ -44,13 +44,12 @@ static bool using_frameworks = false;
static const char *find_subframework_header (cpp_reader *pfile, const char *header,
cpp_dir **dirp);
-typedef struct align_stack
-{
- int alignment;
- struct align_stack * prev;
-} align_stack;
+struct fld_align_stack {
+ int alignment;
+ struct fld_align_stack * prev;
+};
-static struct align_stack * field_align_stack = NULL;
+static struct fld_align_stack * field_align_stack;
/* Maintain a small stack of alignments. This is similar to pragma
pack's stack, but simpler. */
@@ -58,7 +57,7 @@ static struct align_stack * field_align_stack = NULL;
static void
push_field_alignment (int bit_alignment)
{
- align_stack *entry = XNEW (align_stack);
+ fld_align_stack *entry = XNEW (fld_align_stack);
entry->alignment = maximum_field_alignment;
entry->prev = field_align_stack;
@@ -72,7 +71,7 @@ pop_field_alignment (void)
{
if (field_align_stack)
{
- align_stack *entry = field_align_stack;
+ fld_align_stack *entry = field_align_stack;
maximum_field_alignment = entry->alignment;
field_align_stack = entry->prev;
@@ -692,10 +691,10 @@ macosx_version_as_macro (void)
if (!version_array)
goto fail;
- if (version_array[MAJOR] != 10)
+ if (version_array[MAJOR] < 10 || version_array[MAJOR] > 11)
goto fail;
- if (version_array[MINOR] < 10)
+ if (version_array[MAJOR] == 10 && version_array[MINOR] < 10)
version_macro = version_as_legacy_macro (version_array);
else
version_macro = version_as_modern_macro (version_array);
diff --git a/gcc/config/darwin-d.c b/gcc/config/darwin-d.c
new file mode 100644
index 0000000..ced07ce
--- /dev/null
+++ b/gcc/config/darwin-d.c
@@ -0,0 +1,49 @@
+/* Darwin support needed only by D front-end.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+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 "tm_d.h"
+#include "d/d-target.h"
+#include "d/d-target-def.h"
+
+/* Implement TARGET_D_OS_VERSIONS for Darwin targets. */
+
+static void
+darwin_d_os_builtins (void)
+{
+ d_add_builtin_version ("Posix");
+ d_add_builtin_version ("OSX");
+ d_add_builtin_version ("darwin");
+}
+
+#undef TARGET_D_OS_VERSIONS
+#define TARGET_D_OS_VERSIONS darwin_d_os_builtins
+
+/* Define TARGET_D_MINFO_SECTION for Darwin targets. */
+
+#undef TARGET_D_MINFO_SECTION
+#define TARGET_D_MINFO_SECTION "__DATA,__minfodata"
+
+#undef TARGET_D_MINFO_START_NAME
+#define TARGET_D_MINFO_START_NAME "*section$start$__DATA$__minfodata"
+
+#undef TARGET_D_MINFO_END_NAME
+#define TARGET_D_MINFO_END_NAME "*section$end$__DATA$__minfodata"
+
+struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c
index 8fdd32e..c5ad441 100644
--- a/gcc/config/darwin-driver.c
+++ b/gcc/config/darwin-driver.c
@@ -43,13 +43,13 @@ static const char *
validate_macosx_version_min (const char *version_str)
{
size_t version_len;
- unsigned long major, minor, tiny = 0;
+ unsigned long major, minor = 0, tiny = 0;
char *end;
const char *old_version = version_str;
bool need_rewrite = false;
version_len = strlen (version_str);
- if (version_len < 4) /* The minimum would be 10.x */
+ if (version_len < 2) /* The minimum would be 11 */
return NULL;
/* Version string must consist of digits and periods only. */
@@ -63,18 +63,27 @@ validate_macosx_version_min (const char *version_str)
need_rewrite = true;
major = strtoul (version_str, &end, 10);
- version_str = end + ((*end == '.') ? 1 : 0);
- if (major != 10) /* So far .. all MacOS 10 ... */
+ if (major < 10 || major > 11 ) /* MacOS 10 and 11 are known. */
return NULL;
- /* Version string components must be present and numeric. */
- if (!ISDIGIT (version_str[0]))
+ /* Skip a separating period, if there's one. */
+ version_str = end + ((*end == '.') ? 1 : 0);
+
+ if (major == 11 && *end != '\0' && !ISDIGIT (version_str[0]))
+ /* For MacOS 11, we allow just the major number, but if the minor is
+ there it must be numeric. */
+ return NULL;
+ else if (major == 11 && *end == '\0')
+ /* We will rewrite 11 => 11.0.0. */
+ need_rewrite = true;
+ else if (major == 10 && (*end == '\0' || !ISDIGIT (version_str[0])))
+ /* Otherwise, minor version components must be present and numeric. */
return NULL;
/* If we have one or more leading zeros on a component, then rewrite the
version string. */
- if (version_str[0] == '0' && version_str[1] != '\0'
+ if (*end != '\0' && version_str[0] == '0' && version_str[1] != '\0'
&& version_str[1] != '.')
need_rewrite = true;
@@ -104,7 +113,7 @@ validate_macosx_version_min (const char *version_str)
if (need_rewrite)
{
char *new_version;
- asprintf (&new_version, "10.%lu.%lu", minor, tiny);
+ asprintf (&new_version, "%2lu.%lu.%lu", major, minor, tiny);
return new_version;
}
@@ -115,6 +124,12 @@ validate_macosx_version_min (const char *version_str)
#include <sys/sysctl.h>
#include "xregex.h"
+/* Determine the version of the running OS.
+ We only look at the first two components (ignoring the patch one) and
+ report NN.MM.0 where NN is currently either 10 or 11 and MM is the OS
+ minor release number.
+ If we can't parse what the kernel gives us, warn the user, and do nothing. */
+
static char *
darwin_find_version_from_kernel (void)
{
@@ -125,8 +140,6 @@ darwin_find_version_from_kernel (void)
char * version_p;
char * new_flag;
- /* Determine the version of the running OS. If we can't, warn user,
- and do nothing. */
if (sysctl (osversion_name, ARRAY_SIZE (osversion_name), osversion,
&osversion_len, NULL, 0) == -1)
{
@@ -144,10 +157,24 @@ darwin_find_version_from_kernel (void)
major_vers = major_vers * 10 + (*version_p++ - '0');
if (*version_p++ != '.')
goto parse_failed;
-
- /* The major kernel version number is 4 plus the second OS version
- component. */
- if (major_vers - 4 <= 4)
+
+ /* Darwin20 sees a transition to macOS 11. In this, it seems that the
+ mapping to macOS minor version is now shifted to the kernel minor
+ version - 1 (at least for the initial releases). At this stage, we
+ don't know what macOS version will correspond to Darwin21. */
+ if (major_vers >= 20)
+ {
+ int minor_vers = *version_p++ - '0';
+ if (ISDIGIT (*version_p))
+ minor_vers = minor_vers * 10 + (*version_p++ - '0');
+ if (*version_p++ != '.')
+ goto parse_failed;
+ if (minor_vers > 0)
+ minor_vers -= 1; /* Kernel 20.3 => macOS 11.2. */
+ /* It's not yet clear whether patch level will be considered. */
+ asprintf (&new_flag, "11.%02d.00", minor_vers);
+ }
+ else if (major_vers - 4 <= 4)
/* On 10.4 and earlier, the old linker is used which does not
support three-component system versions.
FIXME: we should not assume this - a newer linker could be used. */
@@ -202,7 +229,7 @@ darwin_default_min_version (void)
const char *checked = validate_macosx_version_min (new_flag);
if (checked == NULL)
{
- warning (0, "couldn%'t understand version %s", new_flag);
+ warning (0, "could not understand version %s", new_flag);
return NULL;
}
new_flag = xstrndup (checked, strlen (checked));
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index 49c540f..3f222c3 100644
--- a/gcc/config/darwin-protos.h
+++ b/gcc/config/darwin-protos.h
@@ -69,6 +69,7 @@ extern void darwin_non_lazy_pcrel (FILE *, rtx);
extern void darwin_emit_unwind_label (FILE *, tree, int, int);
extern void darwin_emit_except_table_label (FILE *);
+extern rtx darwin_make_eh_symbol_indirect (rtx, bool);
extern void darwin_pragma_ignore (struct cpp_reader *);
extern void darwin_pragma_options (struct cpp_reader *);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index dd4857f..3265e3e 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -2225,6 +2225,17 @@ darwin_emit_except_table_label (FILE *file)
ASM_OUTPUT_LABEL (file, section_start_label);
}
+rtx
+darwin_make_eh_symbol_indirect (rtx orig, bool ARG_UNUSED (pubvis))
+{
+ if (DARWIN_PPC == 0 && TARGET_64BIT)
+ return orig;
+
+ return gen_rtx_SYMBOL_REF (Pmode,
+ machopic_indirection_name (orig,
+ /*stub_p=*/false));
+}
+
/* Return, and mark as used, the name of the stub for the mcount function.
Currently, this is only called by X86 code in the expansion of the
FUNCTION_PROFILER macro, when stubs are enabled. */
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index f9d4fec..da40a08 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -135,7 +135,7 @@ extern GTY(()) int darwin_ms_struct;
"%{shared:-Zdynamiclib} %<shared", \
"%{static:%{Zdynamic:%e conflicting code gen style switches are used}}",\
"%{y*:%nthe y option is obsolete and ignored} %<y*", \
-"%<Mach %<X"
+"%<Mach "
#if LD64_HAS_EXPORT_DYNAMIC
#define DARWIN_RDYNAMIC "%{rdynamic:-export_dynamic}"
@@ -237,7 +237,7 @@ extern GTY(()) int darwin_ms_struct;
DARWIN_NOPIE_SPEC \
DARWIN_RDYNAMIC \
DARWIN_NOCOMPACT_UNWIND \
- "}}}}}}} %<pie %<no-pie %<rdynamic "
+ "}}}}}}} %<pie %<no-pie %<rdynamic %<X "
#define DSYMUTIL "\ndsymutil"
@@ -591,6 +591,9 @@ extern GTY(()) int darwin_ms_struct;
/* Emit a label to separate the exception table. */
#define TARGET_ASM_EMIT_EXCEPT_TABLE_LABEL darwin_emit_except_table_label
+/* Make an EH (personality or LDSA) symbol indirect as needed. */
+#define TARGET_ASM_MAKE_EH_SYMBOL_INDIRECT darwin_make_eh_symbol_indirect
+
/* Our profiling scheme doesn't LP labels and counter words. */
#define NO_PROFILE_COUNTERS 1
diff --git a/gcc/config/darwin.opt b/gcc/config/darwin.opt
index 5b75536..aa4dea2 100644
--- a/gcc/config/darwin.opt
+++ b/gcc/config/darwin.opt
@@ -30,7 +30,7 @@ dependency-file
C ObjC C++ ObjC++ Separate Alias(MF) MissingArgError(missing filename after %qs)
fapple-kext
-Target Report C++ Var(flag_apple_kext)
+Target C++ Var(flag_apple_kext)
Generate code for darwin loadable kernel extensions.
iframework
@@ -38,28 +38,28 @@ Target RejectNegative C ObjC C++ ObjC++ Joined Separate
-iframework <dir> Add <dir> to the end of the system framework include path.
mconstant-cfstrings
-Target Report Var(darwin_constant_cfstrings) Init(1)
+Target Var(darwin_constant_cfstrings) Init(1)
Generate compile-time CFString objects.
Wnonportable-cfstrings
-Target Report Var(darwin_warn_nonportable_cfstrings) Init(1) Warning
+Target Var(darwin_warn_nonportable_cfstrings) Init(1) Warning
Warn if constant CFString objects contain non-portable characters.
; Use new-style pic stubs if this is true, x86 only so far.
matt-stubs
-Target Report Var(darwin_macho_att_stub) Init(1)
+Target Var(darwin_macho_att_stub) Init(1)
Generate AT&T-style stubs for Mach-O.
mdynamic-no-pic
-Target Common Report Mask(MACHO_DYNAMIC_NO_PIC)
+Target Common Mask(MACHO_DYNAMIC_NO_PIC)
Generate code suitable for executables (NOT shared libs).
mfix-and-continue
-Target Report Var(darwin_fix_and_continue)
+Target Var(darwin_fix_and_continue)
Generate code suitable for fast turn around debugging.
mkernel
-Target Report Var(flag_mkernel)
+Target Var(flag_mkernel)
Generate code for the kernel or loadable kernel extensions.
; The Init here is for the convenience of GCC developers, so that cc1
@@ -67,24 +67,24 @@ Generate code for the kernel or loadable kernel extensions.
; driver will always pass a -mmacosx-version-min, so in normal use the
; Init is never used.
mmacosx-version-min=
-Target RejectNegative Joined Report Var(darwin_macosx_version_min) Init(DEF_MIN_OSX_VERSION)
+Target RejectNegative Joined Var(darwin_macosx_version_min) Init(DEF_MIN_OSX_VERSION)
The earliest macOS version on which this program will run.
; Really, only relevant to PowerPC which has a 4 byte bool by default.
mone-byte-bool
-Target RejectNegative Report Var(darwin_one_byte_bool)
+Target RejectNegative Var(darwin_one_byte_bool)
Set sizeof(bool) to 1.
msymbol-stubs
-Target Report Var(darwin_symbol_stubs) Init(0)
+Target Var(darwin_symbol_stubs) Init(0)
Force generation of external symbol indirection stubs.
; Some code-gen may be improved / adjusted if the linker is sufficiently modern.
mtarget-linker=
-Target RejectNegative Joined Report Alias(mtarget-linker)
+Target RejectNegative Joined Alias(mtarget-linker)
mtarget-linker
-Target RejectNegative Joined Separate Report Var(darwin_target_linker) Init(LD64_VERSION)
+Target RejectNegative Joined Separate Var(darwin_target_linker) Init(LD64_VERSION)
-mtarget-linker <version> Specify that ld64 <version> is the toolchain linker for the current invocation.
; Driver options.
diff --git a/gcc/config/dragonfly-d.c b/gcc/config/dragonfly-d.c
new file mode 100644
index 0000000..70ec820
--- /dev/null
+++ b/gcc/config/dragonfly-d.c
@@ -0,0 +1,37 @@
+/* DragonFly support needed only by D front-end.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+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 "tm_d.h"
+#include "d/d-target.h"
+#include "d/d-target-def.h"
+
+/* Implement TARGET_D_OS_VERSIONS for DragonFly targets. */
+
+static void
+dragonfly_d_os_builtins (void)
+{
+ d_add_builtin_version ("DragonFlyBSD");
+ d_add_builtin_version ("Posix");
+}
+
+#undef TARGET_D_OS_VERSIONS
+#define TARGET_D_OS_VERSIONS dragonfly_d_os_builtins
+
+struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 74a3eaf..d8f169f 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -474,3 +474,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#undef TARGET_LIBC_HAS_FUNCTION
#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
+
+/* ELF support needed only by D front-end. */
+
+#define TARGET_D_MINFO_SECTION "minfo"
+#define TARGET_D_MINFO_START_NAME "__start_minfo"
+#define TARGET_D_MINFO_END_NAME "__stop_minfo"
diff --git a/gcc/config/fr30/fr30.opt b/gcc/config/fr30/fr30.opt
index 0a65cc4..5178b0c 100644
--- a/gcc/config/fr30/fr30.opt
+++ b/gcc/config/fr30/fr30.opt
@@ -19,7 +19,7 @@
; <http://www.gnu.org/licenses/>.
msmall-model
-Target Report Mask(SMALL_MODEL)
+Target Mask(SMALL_MODEL)
Assume small address space.
mno-lsim
diff --git a/gcc/config/freebsd-d.c b/gcc/config/freebsd-d.c
new file mode 100644
index 0000000..d79d82b
--- /dev/null
+++ b/gcc/config/freebsd-d.c
@@ -0,0 +1,42 @@
+/* FreeBSD support needed only by D front-end.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+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 "tm.h"
+#include "tm_p.h"
+#include "d/d-target.h"
+#include "d/d-target-def.h"
+
+/* Implement TARGET_D_OS_VERSIONS for FreeBSD targets. */
+
+static void
+freebsd_d_os_builtins (void)
+{
+ char buf[16];
+ snprintf (buf, sizeof (buf), "FreeBSD_%d", FBSD_MAJOR);
+
+ d_add_builtin_version ("FreeBSD");
+ d_add_builtin_version (xstrdup (buf));
+ d_add_builtin_version ("Posix");
+}
+
+#undef TARGET_D_OS_VERSIONS
+#define TARGET_D_OS_VERSIONS freebsd_d_os_builtins
+
+struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/frv/frv.opt b/gcc/config/frv/frv.opt
index 4b4fe70..f75f2ea 100644
--- a/gcc/config/frv/frv.opt
+++ b/gcc/config/frv/frv.opt
@@ -26,19 +26,19 @@ Variable
frv_cpu_t frv_cpu_type = CPU_TYPE
macc-4
-Target Report RejectNegative Mask(ACC_4)
+Target RejectNegative Mask(ACC_4)
Use 4 media accumulators.
macc-8
-Target Report RejectNegative InverseMask(ACC_4, ACC_8)
+Target RejectNegative InverseMask(ACC_4, ACC_8)
Use 8 media accumulators.
malign-labels
-Target Report Mask(ALIGN_LABELS)
+Target Mask(ALIGN_LABELS)
Enable label alignment optimizations.
malloc-cc
-Target Report RejectNegative Mask(ALLOC_CC)
+Target RejectNegative Mask(ALLOC_CC)
Dynamically allocate cc registers.
; We used to default the branch cost to 2, but it was changed it to 1 to avoid
@@ -49,7 +49,7 @@ Target RejectNegative Joined UInteger Var(frv_branch_cost_int) Init(1)
Set the cost of branches.
mcond-exec
-Target Report Mask(COND_EXEC)
+Target Mask(COND_EXEC)
Enable conditional execution other than moves/scc.
mcond-exec-insns=
@@ -61,7 +61,7 @@ Target RejectNegative Joined UInteger Var(frv_condexec_temps) Init(4)
Change the number of temporary registers that are available to conditionally-executed sequences.
mcond-move
-Target Report Mask(COND_MOVE)
+Target Mask(COND_MOVE)
Enable conditional moves.
mcpu=
@@ -118,75 +118,75 @@ mdebug-stack
Target Undocumented Var(TARGET_DEBUG_STACK)
mdouble
-Target Report Mask(DOUBLE)
+Target Mask(DOUBLE)
Use fp double instructions.
mdword
-Target Report Mask(DWORD)
+Target Mask(DWORD)
Change the ABI to allow double word insns.
mfdpic
-Target Report Mask(FDPIC)
+Target Mask(FDPIC)
Enable Function Descriptor PIC mode.
mfixed-cc
-Target Report RejectNegative InverseMask(ALLOC_CC, FIXED_CC)
+Target RejectNegative InverseMask(ALLOC_CC, FIXED_CC)
Just use icc0/fcc0.
mfpr-32
-Target Report RejectNegative Mask(FPR_32)
+Target RejectNegative Mask(FPR_32)
Only use 32 FPRs.
mfpr-64
-Target Report RejectNegative InverseMask(FPR_32, FPR_64)
+Target RejectNegative InverseMask(FPR_32, FPR_64)
Use 64 FPRs.
mgpr-32
-Target Report RejectNegative Mask(GPR_32)
+Target RejectNegative Mask(GPR_32)
Only use 32 GPRs.
mgpr-64
-Target Report RejectNegative InverseMask(GPR_32, GPR_64)
+Target RejectNegative InverseMask(GPR_32, GPR_64)
Use 64 GPRs.
mgprel-ro
-Target Report Mask(GPREL_RO)
+Target Mask(GPREL_RO)
Enable use of GPREL for read-only data in FDPIC.
mhard-float
-Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
+Target RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
Use hardware floating point.
minline-plt
-Target Report Mask(INLINE_PLT)
+Target Mask(INLINE_PLT)
Enable inlining of PLT in function calls.
mlibrary-pic
-Target Report Mask(LIBPIC)
+Target Mask(LIBPIC)
Enable PIC support for building libraries.
mlinked-fp
-Target Report Mask(LINKED_FP)
+Target Mask(LINKED_FP)
Follow the EABI linkage requirements.
mlong-calls
-Target Report Mask(LONG_CALLS)
+Target Mask(LONG_CALLS)
Disallow direct calls to global functions.
mmedia
-Target Report Mask(MEDIA)
+Target Mask(MEDIA)
Use media instructions.
mmuladd
-Target Report Mask(MULADD)
+Target Mask(MULADD)
Use multiply add/subtract instructions.
mmulti-cond-exec
-Target Report Mask(MULTI_CE)
+Target Mask(MULTI_CE)
Enable optimizing &&/|| in conditional execution.
mnested-cond-exec
-Target Report Mask(NESTED_CE)
+Target Mask(NESTED_CE)
Enable nested conditional execution optimizations.
; Not used by the compiler proper.
@@ -195,15 +195,15 @@ Target RejectNegative
Do not mark ABI switches in e_flags.
moptimize-membar
-Target Report Mask(OPTIMIZE_MEMBAR)
+Target Mask(OPTIMIZE_MEMBAR)
Remove redundant membars.
mpack
-Target Report Mask(PACK)
+Target Mask(PACK)
Pack VLIW instructions.
mscc
-Target Report Mask(SCC)
+Target Mask(SCC)
Enable setting GPRs to the result of comparisons.
msched-lookahead=
@@ -211,15 +211,15 @@ Target RejectNegative Joined UInteger Var(frv_sched_lookahead) Init(4)
Change the amount of scheduler lookahead.
msoft-float
-Target Report RejectNegative Mask(SOFT_FLOAT)
+Target RejectNegative Mask(SOFT_FLOAT)
Use software floating point.
mTLS
-Target Report RejectNegative Mask(BIG_TLS)
+Target RejectNegative Mask(BIG_TLS)
Assume a large TLS segment.
mtls
-Target Report RejectNegative InverseMask(BIG_TLS)
+Target RejectNegative InverseMask(BIG_TLS)
Do not assume a large TLS segment.
; Not used by the compiler proper.
@@ -233,5 +233,5 @@ Target RejectNegative
Link with the library-pic libraries.
mvliw-branch
-Target Report Mask(VLIW_BRANCH)
+Target Mask(VLIW_BRANCH)
Allow branches to be packed with other instructions.
diff --git a/gcc/config/ft32/ft32.md b/gcc/config/ft32/ft32.md
index 8918bb7..1a2380f 100644
--- a/gcc/config/ft32/ft32.md
+++ b/gcc/config/ft32/ft32.md
@@ -89,9 +89,9 @@
"mul.l %0,%1,%2")
(define_insn "umulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (zero_extend:DI (match_operand:SI 2 "ft32_rimm_operand" "r,KA"))))
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
(clobber (reg:CC CC_REG))]
""
"mul.l $cc,%1,%2\;muluh.l %h0,%1,%2\;move.l %0,$cc")
diff --git a/gcc/config/ft32/ft32.opt b/gcc/config/ft32/ft32.opt
index cabe4b2..0283037 100644
--- a/gcc/config/ft32/ft32.opt
+++ b/gcc/config/ft32/ft32.opt
@@ -19,25 +19,25 @@
; <http://www.gnu.org/licenses/>.
msim
-Target Report Mask(SIM)
+Target Mask(SIM)
Target the software simulator.
mlra
-Target Report Var(ft32_lra_flag) Init(0) Save
+Target Var(ft32_lra_flag) Init(0) Save
Use LRA instead of reload.
mnodiv
-Target Report Mask(NODIV)
+Target Mask(NODIV)
Avoid use of the DIV and MOD instructions.
mft32b
-Target Report Mask(FT32B)
+Target Mask(FT32B)
Target the FT32B architecture.
mcompress
-Target Report Mask(COMPRESS)
+Target Mask(COMPRESS)
Enable FT32B code compression.
mnopm
-Target Report Mask(NOPM)
+Target Mask(NOPM)
Avoid placing any readable data in program memory.
diff --git a/gcc/config/gcn/gcn.opt b/gcc/config/gcn/gcn.opt
index b1ea56e..a0d791f 100644
--- a/gcc/config/gcn/gcn.opt
+++ b/gcc/config/gcn/gcn.opt
@@ -43,31 +43,31 @@ Target RejectNegative Joined ToLower Enum(gpu_type) Var(gcn_tune) Init(PROCESSOR
Specify the name of the target GPU.
m32
-Target Report RejectNegative InverseMask(ABI64)
+Target RejectNegative InverseMask(ABI64)
Generate code for a 32-bit ABI.
m64
-Target Report RejectNegative Mask(ABI64)
+Target RejectNegative Mask(ABI64)
Generate code for a 64-bit ABI.
mgomp
-Target Report RejectNegative
+Target RejectNegative
Enable OpenMP GPU offloading.
bool flag_bypass_init_error = false
mbypass-init-error
-Target Report RejectNegative Var(flag_bypass_init_error)
+Target RejectNegative Var(flag_bypass_init_error)
bool flag_worker_partitioning = false
macc-experimental-workers
-Target Report Var(flag_worker_partitioning) Init(0)
+Target Var(flag_worker_partitioning) Init(0)
int stack_size_opt = -1
mstack-size=
-Target Report RejectNegative Joined UInteger Var(stack_size_opt) Init(-1)
+Target RejectNegative Joined UInteger Var(stack_size_opt) Init(-1)
-mstack-size=<number> Set the private segment size per wave-front, in bytes.
Wopenacc-dims
diff --git a/gcc/config/gcn/mkoffload.c b/gcc/config/gcn/mkoffload.c
index f7589a5..fad0fb3 100644
--- a/gcc/config/gcn/mkoffload.c
+++ b/gcc/config/gcn/mkoffload.c
@@ -336,19 +336,24 @@ copy_early_debug_info (const char *infile, const char *outfile)
{
case R_X86_64_32:
case R_X86_64_32S:
- reloc->r_info = R_AMDGPU_ABS32;
+ reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
+ R_AMDGPU_ABS32);
break;
case R_X86_64_PC32:
- reloc->r_info = R_AMDGPU_REL32;
+ reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
+ R_AMDGPU_REL32);
break;
case R_X86_64_PC64:
- reloc->r_info = R_AMDGPU_REL64;
+ reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
+ R_AMDGPU_REL64);
break;
case R_X86_64_64:
- reloc->r_info = R_AMDGPU_ABS64;
+ reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
+ R_AMDGPU_ABS64);
break;
case R_X86_64_RELATIVE:
- reloc->r_info = R_AMDGPU_RELATIVE64;
+ reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
+ R_AMDGPU_RELATIVE64);
break;
default:
gcc_unreachable ();
diff --git a/gcc/config/glibc-d.c b/gcc/config/glibc-d.c
index bdacdac..7eb9e31 100644
--- a/gcc/config/glibc-d.c
+++ b/gcc/config/glibc-d.c
@@ -42,23 +42,7 @@ glibc_d_os_builtins (void)
#endif
}
-/* Implement TARGET_D_CRITSEC_SIZE for Glibc targets. */
-
-static unsigned
-glibc_d_critsec_size (void)
-{
- /* This is the sizeof pthread_mutex_t. */
-#ifdef GNU_USER_TARGET_D_CRITSEC_SIZE
- return GNU_USER_TARGET_D_CRITSEC_SIZE;
-#else
- return (POINTER_SIZE == 64) ? 40 : 24;
-#endif
-}
-
#undef TARGET_D_OS_VERSIONS
#define TARGET_D_OS_VERSIONS glibc_d_os_builtins
-#undef TARGET_D_CRITSEC_SIZE
-#define TARGET_D_CRITSEC_SIZE glibc_d_critsec_size
-
struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index ff2e880..9295024 100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -129,14 +129,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Link -lasan early on the command line. For -static-libasan, don't link
it for -shared link, the executable should be compiled with -static-libasan
in that case, and for executable link with --{,no-}whole-archive around
- it to force everything into the executable. And similarly for -ltsan
- and -llsan. */
+ it to force everything into the executable. And similarly for -ltsan,
+ -lhwasan, and -llsan. */
#if defined(HAVE_LD_STATIC_DYNAMIC)
#undef LIBASAN_EARLY_SPEC
#define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \
"%{static-libasan:%{!shared:" \
LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \
LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}"
+#undef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC "%{static-libhwasan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -lhwasan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-libhwasan:-lhwasan}"
#undef LIBTSAN_EARLY_SPEC
#define LIBTSAN_EARLY_SPEC "%{!shared:libtsan_preinit%O%s} " \
"%{static-libtsan:%{!shared:" \
diff --git a/gcc/config/h8300/addsub.md b/gcc/config/h8300/addsub.md
index f339285..3585bff 100644
--- a/gcc/config/h8300/addsub.md
+++ b/gcc/config/h8300/addsub.md
@@ -9,64 +9,101 @@
""
"")
-(define_insn "*addqi3"
+(define_insn_and_split "*addqi3"
[(set (match_operand:QI 0 "h8300_dst_operand" "=rQ")
(plus:QI (match_operand:QI 1 "h8300_dst_operand" "%0")
(match_operand:QI 2 "h8300_src_operand" "rQi")))]
"h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (plus:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*addqi3_flags<cczn>"
+ [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ")
+ (plus:QI (match_operand:QI 1 "h8300_dst_operand" "%0")
+ (match_operand:QI 2 "h8300_src_operand" "rQi")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed && h8300_operands_match_p (operands)"
"add.b %X2,%X0"
- [(set_attr "length_table" "add")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length_table" "add")])
-(define_insn "*addhi3_h8300hs"
+(define_insn_and_split "*addhi"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0")
(match_operand:HI 2 "h8300_src_operand" "L,N,J,n,r")))]
"!TARGET_H8300SX"
- "@
- adds %2,%S0
- subs %G2,%S0
- add.b %t2,%t0
- add.w %T2,%T0
- add.w %T2,%T0"
- [(set_attr "length" "2,2,2,4,2")
- (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
-
-(define_insn "*add<mode>3_incdec"
- [(set (match_operand:HSI 0 "register_operand" "=r,r")
- (unspec:HSI [(match_operand:HSI 1 "register_operand" "0,0")
- (match_operand:HSI 2 "incdec_operand" "M,O")]
- UNSPEC_INCDEC))]
- ""
- {
- if (which_alternative == 0)
- return <MODE>mode == HImode ? "inc.w\t%2,%T0" : "inc.l\t%2,%S0";
- else if (which_alternative == 1)
- return <MODE>mode == HImode ? "dec.w\t%G2,%T0" : "dec.l\t%G2,%S0";
- gcc_unreachable ();
- }
- [(set_attr "length" "2,2")
- (set_attr "cc" "set_zn,set_zn")])
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (plus:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
-(define_insn "*addhi3_h8sx"
+(define_insn "*addhi3_flags<cczn>"
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0")
+ (match_operand:HI 2 "h8300_src_operand" "M,O,J,n,r")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed && !TARGET_H8300SX"
+ "*
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return \"inc %T2,%T0\";
+ case 1:
+ return \"dec %G2,%T0\";
+ case 2:
+ return \"add.b %t2,%t0\";
+ case 3:
+ {
+ /* If the constant is 4 or -4 and we do not need the
+ flags, then we can use adds/subs which is two bytes
+ shorter. */
+ rtx x = XVECEXP (PATTERN (insn), 0, 1);
+ bool clobber = GET_CODE (x) == CLOBBER;
+ if (clobber && INTVAL (operands[2]) == 4)
+ return \"adds %2,%S0\";
+ if (clobber && INTVAL (operands[2]) == -4)
+ return \"subs %G2,%S0\";
+ return \"add.w %T2,%T0\";
+ }
+ case 4:
+ return \"add.w %T2,%T0\";
+ default:
+ gcc_unreachable ();
+ }
+ }"
+ [(set_attr "length" "2,2,2,4,2")])
+
+(define_insn_and_split "*addhi3_h8sx"
[(set (match_operand:HI 0 "h8300_dst_operand" "=rU,rU,r,rQ")
(plus:HI (match_operand:HI 1 "h8300_dst_operand" "%0,0,0,0")
(match_operand:HI 2 "h8300_src_operand" "P3>X,P3<X,J,rQi")))]
"TARGET_H8300SX && h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (plus:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*addhi3_h8sx_flags<cczn>"
+ [(set (match_operand:HI 0 "h8300_dst_operand" "=rU,rU,r,rQ")
+ (plus:HI (match_operand:HI 1 "h8300_dst_operand" "%0,0,0,0")
+ (match_operand:HI 2 "h8300_src_operand" "P3>X,P3<X,J,rQi")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed && TARGET_H8300SX && h8300_operands_match_p (operands)"
"@
add.w %T2:3,%T0
sub.w %G2:3,%T0
add.b %t2,%t0
add.w %T2,%T0"
[(set_attr "length_table" "short_immediate,short_immediate,*,add")
- (set_attr "length" "*,*,2,*")
- (set_attr "cc" "set_zn")])
+ (set_attr "length" "*,*,2,*")])
(define_split
[(set (match_operand:HSI 0 "register_operand" "")
(plus:HSI (match_dup 0)
(match_operand:HSI 1 "two_insn_adds_subs_operand" "")))]
- ""
+ "!reload_completed"
[(const_int 0)]
{
split_adds_subs (<MODE>mode, operands);
@@ -74,18 +111,28 @@
})
-(define_insn "*addsi_h8300hs"
+(define_insn_and_split "*addsi"
[(set (match_operand:SI 0 "h8300_dst_operand" "=rQ,rQ")
(plus:SI (match_operand:SI 1 "h8300_dst_operand" "%0,0")
(match_operand:SI 2 "h8300_src_operand" "i,rQ")))]
"h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*addsi_flags<cczn>"
+ [(set (match_operand:SI 0 "h8300_dst_operand" "=rQ,rQ")
+ (plus:SI (match_operand:SI 1 "h8300_dst_operand" "%0,0")
+ (match_operand:SI 2 "h8300_src_operand" "i,rQ")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed && h8300_operands_match_p (operands)"
{
- return output_plussi (operands);
+ rtx x = XVECEXP (PATTERN (insn), 0, 1);
+ return output_plussi (operands, GET_CODE (x) != CLOBBER);
}
[(set (attr "length")
- (symbol_ref "compute_plussi_length (operands)"))
- (set (attr "cc")
- (symbol_ref "compute_plussi_cc (operands)"))])
+ (symbol_ref "compute_plussi_length (operands, false)"))])
;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
@@ -95,24 +142,43 @@
[(set (match_operand:QHSI 0 "register_operand" "")
(minus:QHSI (match_operand:QHSI 1 "register_operand" "")
(match_operand:QHSI 2 "h8300_src_operand" "")))]
- ""
- {
- })
+ "")
-(define_insn "*subqi3"
+(define_insn_and_split "*subqi3"
[(set (match_operand:QI 0 "h8300_dst_operand" "=rQ")
(minus:QI (match_operand:QI 1 "h8300_dst_operand" "0")
(match_operand:QI 2 "h8300_dst_operand" "rQ")))]
"h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (minus:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*subqi3_flags<cczn>"
+ [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ")
+ (minus:QI (match_operand:QI 1 "h8300_dst_operand" "0")
+ (match_operand:QI 2 "h8300_dst_operand" "rQ")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed && h8300_operands_match_p (operands)"
"sub.b %X2,%X0"
- [(set_attr "length_table" "add")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length_table" "add")])
-(define_insn "*sub<mode>3_h8300hs"
+(define_insn_and_split "*sub<mode>3"
[(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ,rQ")
(minus:HSI (match_operand:HSI 1 "h8300_dst_operand" "0,0")
(match_operand:HSI 2 "h8300_src_operand" "rQ,i")))]
"h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (minus:HSI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*sub<mode>3_flags<cczn>"
+ [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ,rQ")
+ (minus:HSI (match_operand:HSI 1 "h8300_dst_operand" "0,0")
+ (match_operand:HSI 2 "h8300_src_operand" "rQ,i")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed && h8300_operands_match_p (operands)"
{
if (<MODE>mode == HImode)
return "sub.w %T2,%T0";
@@ -120,8 +186,7 @@
return "sub.l %S2,%S0";
gcc_unreachable ();
}
- [(set_attr "length_table" "add")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length_table" "add")])
;; ----------------------------------------------------------------------
;; NEGATION INSTRUCTIONS
@@ -133,10 +198,20 @@
""
"")
-(define_insn "*neg<mode>2"
+(define_insn_and_split "*neg<mode>2"
[(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
(neg:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (neg:QHSI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*neg<mode>2_flags<cczn>"
+ [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
+ (neg:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed"
{
if (<MODE>mode == E_QImode)
return "neg %X0";
@@ -146,14 +221,21 @@
return "neg.l %S0";
gcc_unreachable ();
}
- [(set_attr "length_table" "unary")
- (set_attr "cc" "set_zn")])
-
+ [(set_attr "length_table" "unary")])
-(define_insn "*negsf2_h8300hs"
+(define_insn_and_split "*negsf2"
[(set (match_operand:SF 0 "register_operand" "=r")
- (neg:SF (match_operand:SF 1 "register_operand" "0")))]
+ (neg:SF (match_operand:SF 1 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (neg:SF (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*negsf2_clobber_flags"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (neg:SF (match_operand:SF 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "reload_completed"
"xor.w\\t#32768,%e0"
[(set_attr "length" "4")])
-
diff --git a/gcc/config/h8300/bitfield.md b/gcc/config/h8300/bitfield.md
index bed712d..722c147 100644
--- a/gcc/config/h8300/bitfield.md
+++ b/gcc/config/h8300/bitfield.md
@@ -15,7 +15,7 @@
;; Inverted loads with a 16bit destination.
;;
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:HI 0 "register_operand" "=&r")
(zero_extract:HI (xor:HI (match_operand:HI 1 "register_operand" "r")
(match_operand:HI 3 "const_int_operand" "n"))
@@ -23,6 +23,23 @@
(match_operand:HI 2 "const_int_operand" "n")))]
"(TARGET_H8300SX)
&& (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:HI (xor:HI (match_dup 1) (match_dup 3))
+ (const_int 1)
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (zero_extract:HI (xor:HI (match_operand:HI 1 "register_operand" "r")
+ (match_operand:HI 3 "const_int_operand" "n"))
+ (const_int 1)
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (clobber (reg:CC CC_REG))]
+ "(TARGET_H8300SX)
+ && (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
"sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
[(set_attr "length" "8")])
@@ -30,23 +47,35 @@
;; Normal loads with a 32bit destination.
;;
-(define_insn "*extzv_1_r_h8300hs"
+(define_insn_and_split "*extzv_1_r"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r")
(const_int 1)
(match_operand 2 "const_int_operand" "n,n")))]
"INTVAL (operands[2]) < 16"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1) (const_int 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extzv_1_r_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" "n,n")))
+ (clobber (reg:CC CC_REG))]
+ "INTVAL (operands[2]) < 16"
{
return output_simode_bld (0, operands);
}
- [(set_attr "cc" "set_znv,set_znv")
- (set_attr "length" "8,6")])
+ [(set_attr "length" "8,6")])
;;
;; Inverted loads with a 32bit destination.
;;
-(define_insn "*extzv_1_r_inv_h8300hs"
+(define_insn_and_split "*extzv_1_r_inv"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "?0,r")
(match_operand 3 "const_int_operand" "n,n"))
@@ -54,11 +83,27 @@
(match_operand 2 "const_int_operand" "n,n")))]
"INTVAL (operands[2]) < 16
&& (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:SI (xor:SI (match_dup 1) (match_dup 3))
+ (const_int 1)
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extzv_1_r_inv_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "?0,r")
+ (match_operand 3 "const_int_operand" "n,n"))
+ (const_int 1)
+ (match_operand 2 "const_int_operand" "n,n")))
+ (clobber (reg:CC CC_REG))]
+ "INTVAL (operands[2]) < 16
+ && (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
{
return output_simode_bld (1, operands);
}
- [(set_attr "cc" "set_znv,set_znv")
- (set_attr "length" "8,6")])
+ [(set_attr "length" "8,6")])
(define_expand "insv"
[(set (zero_extract:HI (match_operand:HI 0 "general_operand" "")
@@ -107,12 +152,25 @@
FAIL;
})
-(define_insn ""
+(define_insn_and_split ""
[(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r")
(const_int 1)
(match_operand:HI 1 "immediate_operand" "n"))
(match_operand:HI 2 "register_operand" "r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:HI (match_dup 0) (const_int 1) (match_dup 1))
+ (match_dup 2))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:HI 1 "immediate_operand" "n"))
+ (match_operand:HI 2 "register_operand" "r"))
+ (clobber (reg:CC CC_REG))]
+ ""
"bld #0,%R2\;bst %Z1,%Y0 ; i1"
[(set_attr "length" "4")])
@@ -164,7 +222,7 @@
;; BAND, BOR, and BXOR patterns
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operator:HI 4 "bit_operator"
[(zero_extract:HI (match_operand:HI 1 "register_operand" "r")
@@ -172,10 +230,28 @@
(match_operand:HI 2 "immediate_operand" "n"))
(match_operand:HI 3 "bit_operand" "0")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 4 [(zero_extract:HI (match_dup 1)
+ (const_int 1)
+ (match_dup 2))
+ (match_dup 3)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "bit_operand" "=Ur")
+ (match_operator:HI 4 "bit_operator"
+ [(zero_extract:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 2 "immediate_operand" "n"))
+ (match_operand:HI 3 "bit_operand" "0")]))
+ (clobber (reg:CC CC_REG))]
+ ""
"bld %Z2,%Y1\;b%c4 #0,%R0\;bst #0,%R0; bl1"
[(set_attr "length" "6")])
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operator:HI 5 "bit_operator"
[(zero_extract:HI (match_operand:HI 1 "register_operand" "r")
@@ -185,256 +261,268 @@
(const_int 1)
(match_operand:HI 4 "immediate_operand" "n"))]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 5 [(zero_extract:HI (match_dup 1)
+ (const_int 1)
+ (match_dup 2))
+ (zero_extract:HI (match_dup 3)
+ (const_int 1)
+ (match_dup 4))]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "bit_operand" "=Ur")
+ (match_operator:HI 5 "bit_operator"
+ [(zero_extract:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 2 "immediate_operand" "n"))
+ (zero_extract:HI (match_operand:HI 3 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 4 "immediate_operand" "n"))]))
+ (clobber (reg:CC CC_REG))]
+ ""
"bld %Z2,%Y1\;b%c5 %Z4,%Y3\;bst #0,%R0; bl3"
[(set_attr "length" "6")])
-(define_insn "bfld"
+(define_insn_and_split "bfld"
[(set (match_operand:QI 0 "register_operand" "=r")
(zero_extract:QI (match_operand:QI 1 "bit_memory_operand" "WU")
(match_operand:QI 2 "immediate_operand" "n")
(match_operand:QI 3 "immediate_operand" "n")))]
"TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:QI (match_dup 1) (match_dup 2) (match_dup 3)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "bfld_clobber_flags"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (zero_extract:QI (match_operand:QI 1 "bit_memory_operand" "WU")
+ (match_operand:QI 2 "immediate_operand" "n")
+ (match_operand:QI 3 "immediate_operand" "n")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8"
{
operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3])))
- (1 << INTVAL (operands[3])));
return "bfld %2,%1,%R0";
}
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "bitfield")])
+ [(set_attr "length_table" "bitfield")])
-(define_insn "bfst"
+(define_insn_and_split "bfst"
[(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU")
(match_operand:QI 2 "immediate_operand" "n")
(match_operand:QI 3 "immediate_operand" "n"))
(match_operand:QI 1 "register_operand" "r"))]
"TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8"
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:QI (match_dup 0) (match_dup 2) (match_dup 3))
+ (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "bfst_clobber_flags"
+ [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU")
+ (match_operand:QI 2 "immediate_operand" "n")
+ (match_operand:QI 3 "immediate_operand" "n"))
+ (match_operand:QI 1 "register_operand" "r"))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8"
{
operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3])))
- (1 << INTVAL (operands[3])));
return "bfst %R1,%2,%0";
}
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "bitfield")])
-
-(define_expand "cstoreqi4"
- [(use (match_operator 1 "eqne_operator"
- [(match_operand:QI 2 "h8300_dst_operand" "")
- (match_operand:QI 3 "h8300_src_operand" "")]))
- (clobber (match_operand:HI 0 "register_operand"))]
- "TARGET_H8300SX"
- {
- h8300_expand_store (operands);
- DONE;
- })
-
-(define_expand "cstorehi4"
- [(use (match_operator 1 "eqne_operator"
- [(match_operand:HI 2 "h8300_dst_operand" "")
- (match_operand:HI 3 "h8300_src_operand" "")]))
- (clobber (match_operand:HI 0 "register_operand"))]
- "TARGET_H8300SX"
- {
- h8300_expand_store (operands);
- DONE;
- })
-
-(define_expand "cstoresi4"
- [(use (match_operator 1 "eqne_operator"
- [(match_operand:SI 2 "h8300_dst_operand" "")
- (match_operand:SI 3 "h8300_src_operand" "")]))
- (clobber (match_operand:HI 0 "register_operand"))]
- "TARGET_H8300SX"
- {
- h8300_expand_store (operands);
- DONE;
- })
-
-(define_insn "*bstzhireg"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (match_operator:HI 1 "eqne_operator" [(cc0) (const_int 0)]))]
- "TARGET_H8300SX"
- "mulu.w #0,%T0\;b%k1 .Lh8BR%=\;inc.w #1,%T0\\n.Lh8BR%=:"
- [(set_attr "cc" "clobber")])
-
-(define_insn_and_split "*cmpstz"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,WU")
- (const_int 1)
- (match_operand:QI 1 "immediate_operand" "n,n"))
- (match_operator:QI 2 "eqne_operator"
- [(match_operand 3 "h8300_dst_operand" "r,rQ")
- (match_operand 4 "h8300_src_operand" "I,rQi")]))]
- "TARGET_H8300SX
- && (GET_MODE (operands[3]) == GET_MODE (operands[4])
- || GET_CODE (operands[4]) == CONST_INT)
- && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_INT
- && GET_MODE_SIZE (GET_MODE (operands[3])) <= 4"
- "#"
- "reload_completed"
- [(set (cc0) (match_dup 5))
- (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1))
- (match_op_dup:QI 2 [(cc0) (const_int 0)]))]
- {
- operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);
- }
- [(set_attr "cc" "set_znv,compare")])
-
-(define_insn "*bstz"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU")
- (const_int 1)
- (match_operand:QI 1 "immediate_operand" "n"))
- (eq:QI (cc0) (const_int 0)))]
- "TARGET_H8300SX && reload_completed"
- "bstz %1,%0"
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "unary")])
-
-(define_insn "*bistz"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU")
- (const_int 1)
- (match_operand:QI 1 "immediate_operand" "n"))
- (ne:QI (cc0) (const_int 0)))]
- "TARGET_H8300SX && reload_completed"
- "bistz %1,%0"
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "unary")])
-
-(define_insn_and_split "*cmpcondbset"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
- (if_then_else:QI (match_operator 1 "eqne_operator"
- [(match_operand 2 "h8300_dst_operand" "r,rQ")
- (match_operand 3 "h8300_src_operand" "I,rQi")])
- (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
- (match_operand:QI 5 "single_one_operand" "n,n"))
- (match_dup 4)))]
- "TARGET_H8300SX"
- "#"
- "reload_completed"
- [(set (cc0) (match_dup 6))
- (set (match_dup 0)
- (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
- (ior:QI (match_dup 4) (match_dup 5))
- (match_dup 4)))]
- {
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
- }
- [(set_attr "cc" "set_znv,compare")])
-
-(define_insn "*condbset"
- [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
- (if_then_else:QI (match_operator:QI 2 "eqne_operator"
- [(cc0) (const_int 0)])
- (ior:QI (match_operand:QI 3 "bit_memory_operand" "0")
- (match_operand:QI 1 "single_one_operand" "n"))
- (match_dup 3)))]
- "TARGET_H8300SX && reload_completed"
- "bset/%j2\t%V1,%0"
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "logicb")])
-
-(define_insn_and_split "*cmpcondbclr"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
- (if_then_else:QI (match_operator 1 "eqne_operator"
- [(match_operand 2 "h8300_dst_operand" "r,rQ")
- (match_operand 3 "h8300_src_operand" "I,rQi")])
- (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
- (match_operand:QI 5 "single_zero_operand" "n,n"))
- (match_dup 4)))]
- "TARGET_H8300SX"
- "#"
- "reload_completed"
- [(set (cc0) (match_dup 6))
- (set (match_dup 0)
- (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
- (and:QI (match_dup 4) (match_dup 5))
- (match_dup 4)))]
- {
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
- }
- [(set_attr "cc" "set_znv,compare")])
-
-(define_insn "*condbclr"
- [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
- (if_then_else:QI (match_operator:QI 2 "eqne_operator"
- [(cc0) (const_int 0)])
- (and:QI (match_operand:QI 3 "bit_memory_operand" "0")
- (match_operand:QI 1 "single_zero_operand" "n"))
- (match_dup 3)))]
- "TARGET_H8300SX && reload_completed"
- "bclr/%j2\t%W1,%0"
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "logicb")])
-
-(define_insn_and_split "*cmpcondbsetreg"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
- (if_then_else:QI (match_operator 1 "eqne_operator"
- [(match_operand 2 "h8300_dst_operand" "r,rQ")
- (match_operand 3 "h8300_src_operand" "I,rQi")])
- (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
- (ashift:QI (const_int 1)
- (match_operand:QI 5 "register_operand" "r,r")))
- (match_dup 4)))]
- "TARGET_H8300SX"
- "#"
- "reload_completed"
- [(set (cc0) (match_dup 6))
- (set (match_dup 0)
- (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
- (ior:QI (match_dup 4)
- (ashift:QI (const_int 1)
- (match_operand:QI 5 "register_operand" "r,r")))
- (match_dup 4)))]
- {
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
- }
- [(set_attr "cc" "set_znv,compare")])
-
-(define_insn "*condbsetreg"
- [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
- (if_then_else:QI (match_operator:QI 2 "eqne_operator"
- [(cc0) (const_int 0)])
- (ior:QI (match_operand:QI 3 "bit_memory_operand" "0")
- (ashift:QI (const_int 1)
- (match_operand:QI 1 "register_operand" "r")))
- (match_dup 3)))]
- "TARGET_H8300SX && reload_completed"
- "bset/%j2\t%R1,%0"
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "logicb")])
-
-(define_insn_and_split "*cmpcondbclrreg"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
- (if_then_else:QI (match_operator 1 "eqne_operator"
- [(match_operand 2 "h8300_dst_operand" "r,rQ")
- (match_operand 3 "h8300_src_operand" "I,rQi")])
- (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
- (ashift:QI (const_int 1)
- (match_operand:QI 5 "register_operand" "r,r")))
- (match_dup 4)))]
- "TARGET_H8300SX"
- "#"
- "reload_completed"
- [(set (cc0) (match_dup 6))
- (set (match_dup 0)
- (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
- (and:QI (match_dup 4)
- (ashift:QI (const_int 1)
- (match_operand:QI 5 "register_operand" "r,r")))
- (match_dup 4)))]
- {
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
- }
- [(set_attr "cc" "set_znv,compare")])
-
-(define_insn "*condbclrreg"
- [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
- (if_then_else:QI (match_operator:QI 2 "eqne_operator"
- [(cc0) (const_int 0)])
- (and:QI (match_operand:QI 3 "bit_memory_operand" "0")
- (ashift:QI (const_int 1)
- (match_operand:QI 1 "register_operand" "r")))
- (match_dup 3)))]
- "TARGET_H8300SX && reload_completed"
- "bclr/%j2\t%R1,%0"
- [(set_attr "cc" "none_0hit")
- (set_attr "length_table" "logicb")])
+ [(set_attr "length_table" "bitfield")])
+
+;;(define_expand "cstore<mode>4"
+;; [(use (match_operator 1 "eqne_operator"
+;; [(match_operand:QHSI 2 "h8300_dst_operand" "")
+;; (match_operand:QHSI 3 "h8300_src_operand" "")]))
+;; (clobber (match_operand:QHSI 0 "register_operand"))]
+;; "TARGET_H8300SX"
+;; {
+;; h8300_expand_store (operands);
+;; DONE;
+;; })
+
+;;(define_insn "*bstzhireg"
+;; [(set (match_operand:HI 0 "register_operand" "=r")
+;; (match_operator:HI 1 "eqne_operator" [(cc0) (const_int 0)]))]
+;; "TARGET_H8300SX"
+;; "mulu.w #0,%T0\;b%k1 .Lh8BR%=\;inc.w #1,%T0\\n.Lh8BR%=:")
+
+;;(define_insn_and_split "*cmpstz"
+;; [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,WU")
+;; (const_int 1)
+;; (match_operand:QI 1 "immediate_operand" "n,n"))
+;; (match_operator:QI 2 "eqne_operator"
+;; [(match_operand 3 "h8300_dst_operand" "r,rQ")
+;; (match_operand 4 "h8300_src_operand" "I,rQi")]))]
+;; "TARGET_H8300SX
+;; && (GET_MODE (operands[3]) == GET_MODE (operands[4])
+;; || GET_CODE (operands[4]) == CONST_INT)
+;; && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_INT
+;; && GET_MODE_SIZE (GET_MODE (operands[3])) <= 4"
+;; "#"
+;; "reload_completed"
+;; [(set (cc0) (match_dup 5))
+;; (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1))
+;; (match_op_dup:QI 2 [(cc0) (const_int 0)]))]
+;; {
+;; operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);
+;; })
+
+;;(define_insn "*bstz"
+;; [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU")
+;; (const_int 1)
+;; (match_operand:QI 1 "immediate_operand" "n"))
+;; (eq:QI (cc0) (const_int 0)))]
+;; "TARGET_H8300SX && reload_completed"
+;; "bstz %1,%0"
+;; [(set_attr "length_table" "unary")])
+
+;;(define_insn "*bistz"
+;; [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU")
+;; (const_int 1)
+;; (match_operand:QI 1 "immediate_operand" "n"))
+;; (ne:QI (cc0) (const_int 0)))]
+;; "TARGET_H8300SX && reload_completed"
+;; "bistz %1,%0"
+;; [(set_attr "length_table" "unary")])
+
+;;(define_insn_and_split "*cmpcondbset"
+;; [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
+;; (if_then_else:QI (match_operator 1 "eqne_operator"
+;; [(match_operand 2 "h8300_dst_operand" "r,rQ")
+;; (match_operand 3 "h8300_src_operand" "I,rQi")])
+;; (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
+;; (match_operand:QI 5 "single_one_operand" "n,n"))
+;; (match_dup 4)))]
+;; "TARGET_H8300SX"
+;; "#"
+;; "reload_completed"
+;; [(set (cc0) (match_dup 6))
+;; (set (match_dup 0)
+;; (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
+;; (ior:QI (match_dup 4) (match_dup 5))
+;; (match_dup 4)))]
+;; {
+;; operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
+;; })
+
+;;(define_insn "*condbset"
+;; [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
+;; (if_then_else:QI (match_operator:QI 2 "eqne_operator"
+;; [(cc0) (const_int 0)])
+;; (ior:QI (match_operand:QI 3 "bit_memory_operand" "0")
+;; (match_operand:QI 1 "single_one_operand" "n"))
+;; (match_dup 3)))]
+;; "TARGET_H8300SX && reload_completed"
+;; "bset/%j2\t%V1,%0"
+;; [(set_attr "length_table" "logicb")])
+
+;;(define_insn_and_split "*cmpcondbclr"
+;; [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
+;; (if_then_else:QI (match_operator 1 "eqne_operator"
+;; [(match_operand 2 "h8300_dst_operand" "r,rQ")
+;; (match_operand 3 "h8300_src_operand" "I,rQi")])
+;; (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
+;; (match_operand:QI 5 "single_zero_operand" "n,n"))
+;; (match_dup 4)))]
+;; "TARGET_H8300SX"
+;; "#"
+;; "reload_completed"
+;; [(set (cc0) (match_dup 6))
+;; (set (match_dup 0)
+;; (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
+;; (and:QI (match_dup 4) (match_dup 5))
+;; (match_dup 4)))]
+;; {
+;; operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
+;; })
+
+;;(define_insn "*condbclr"
+;; [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
+;; (if_then_else:QI (match_operator:QI 2 "eqne_operator"
+;; [(cc0) (const_int 0)])
+;; (and:QI (match_operand:QI 3 "bit_memory_operand" "0")
+;; (match_operand:QI 1 "single_zero_operand" "n"))
+;; (match_dup 3)))]
+;; "TARGET_H8300SX && reload_completed"
+;; "bclr/%j2\t%W1,%0"
+;; [(set_attr "length_table" "logicb")])
+
+;;(define_insn_and_split "*cmpcondbsetreg"
+;; [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
+;; (if_then_else:QI (match_operator 1 "eqne_operator"
+;; [(match_operand 2 "h8300_dst_operand" "r,rQ")
+;; (match_operand 3 "h8300_src_operand" "I,rQi")])
+;; (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
+;; (ashift:QI (const_int 1)
+;; (match_operand:QI 5 "register_operand" "r,r")))
+;; (match_dup 4)))]
+;; "TARGET_H8300SX"
+;; "#"
+;; "reload_completed"
+;; [(set (cc0) (match_dup 6))
+;; (set (match_dup 0)
+;; (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
+;; (ior:QI (match_dup 4)
+;; (ashift:QI (const_int 1)
+;; (match_operand:QI 5 "register_operand" "r,r")))
+;; (match_dup 4)))]
+;; {
+;; operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
+;; })
+
+;;(define_insn "*condbsetreg"
+;; [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
+;; (if_then_else:QI (match_operator:QI 2 "eqne_operator"
+;; [(cc0) (const_int 0)])
+;; (ior:QI (match_operand:QI 3 "bit_memory_operand" "0")
+;; (ashift:QI (const_int 1)
+;; (match_operand:QI 1 "register_operand" "r")))
+;; (match_dup 3)))]
+;; "TARGET_H8300SX && reload_completed"
+;; "bset/%j2\t%R1,%0"
+;; [(set_attr "length_table" "logicb")])
+
+;;(define_insn_and_split "*cmpcondbclrreg"
+;; [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU")
+;; (if_then_else:QI (match_operator 1 "eqne_operator"
+;; [(match_operand 2 "h8300_dst_operand" "r,rQ")
+;; (match_operand 3 "h8300_src_operand" "I,rQi")])
+;; (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0")
+;; (ashift:QI (const_int 1)
+;; (match_operand:QI 5 "register_operand" "r,r")))
+;; (match_dup 4)))]
+;; "TARGET_H8300SX"
+;; "#"
+;; "reload_completed"
+;; [(set (cc0) (match_dup 6))
+;; (set (match_dup 0)
+;; (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)])
+;; (and:QI (match_dup 4)
+;; (ashift:QI (const_int 1)
+;; (match_operand:QI 5 "register_operand" "r,r")))
+;; (match_dup 4)))]
+;; {
+;; operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
+;; })
+
+;;(define_insn "*condbclrreg"
+;; [(set (match_operand:QI 0 "bit_memory_operand" "=WU")
+;; (if_then_else:QI (match_operator:QI 2 "eqne_operator"
+;; [(cc0) (const_int 0)])
+;; (and:QI (match_operand:QI 3 "bit_memory_operand" "0")
+;; (ashift:QI (const_int 1)
+;; (match_operand:QI 1 "register_operand" "r")))
+;; (match_dup 3)))]
+;; "TARGET_H8300SX && reload_completed"
+;; "bclr/%j2\t%R1,%0"
+;; [(set_attr "length_table" "logicb")])
diff --git a/gcc/config/h8300/combiner.md b/gcc/config/h8300/combiner.md
index 4f49c7f..20e19da 100644
--- a/gcc/config/h8300/combiner.md
+++ b/gcc/config/h8300/combiner.md
@@ -4,88 +4,193 @@
;; insv:SI
-(define_insn "*insv_si_1_n"
+(define_insn_and_split "*insv_si_1_n"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(const_int 1)
(match_operand:SI 1 "const_int_operand" "n"))
(match_operand:SI 2 "register_operand" "r"))]
"INTVAL (operands[1]) < 16"
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
+ (match_dup 2))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*insv_si_1_n_clobber_flags"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (clobber (reg:CC CC_REG))]
+ "INTVAL (operands[1]) < 16"
"bld\\t#0,%w2\;bst\\t%Z1,%Y0"
[(set_attr "length" "4")])
-(define_insn "*insv_si_1_n_lshiftrt"
+(define_insn_and_split "*insv_si_1_n_lshiftrt"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(const_int 1)
(match_operand:SI 1 "const_int_operand" "n"))
(lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "const_int_operand" "n")))]
"INTVAL (operands[1]) < 16 && INTVAL (operands[3]) < 16"
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
+ (lshiftrt:SI (match_dup 2) (match_dup 3)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*insv_si_1_n_lshiftrt_clobber_flags"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:CC CC_REG))]
+ "INTVAL (operands[1]) < 16 && INTVAL (operands[3]) < 16"
"bld\\t%Z3,%Y2\;bst\\t%Z1,%Y0"
[(set_attr "length" "4")])
-(define_insn "*insv_si_1_n_lshiftrt_16"
+(define_insn_and_split "*insv_si_1_n_lshiftrt_16"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(const_int 1)
(match_operand:SI 1 "const_int_operand" "n"))
(lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
(const_int 16)))]
"INTVAL (operands[1]) < 16"
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
+ (lshiftrt:SI (match_dup 2) (const_int 16)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*insv_si_1_n_lshiftrt_16_clobber_flags"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 16)))
+ (clobber (reg:CC CC_REG))]
+ "INTVAL (operands[1]) < 16"
"rotr.w\\t%e2\;rotl.w\\t%e2\;bst\\t%Z1,%Y0"
[(set_attr "length" "6")])
-(define_insn "*insv_si_8_8"
+(define_insn_and_split "*insv_si_8_8"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(const_int 8)
(const_int 8))
(match_operand:SI 1 "register_operand" "r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*insv_si_8_8_clobber_flags"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (const_int 8)
+ (const_int 8))
+ (match_operand:SI 1 "register_operand" "r"))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.b\\t%w1,%x0"
[(set_attr "length" "2")])
-(define_insn "*insv_si_8_8_lshiftrt_8"
+(define_insn_and_split "*insv_si_8_8_lshiftrt_8"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(const_int 8)
(const_int 8))
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 8)))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (lshiftrt:SI (match_dup 1) (const_int 8)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*insv_si_8_8_lshiftrt_8_clobber_flags"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (const_int 8)
+ (const_int 8))
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.b\\t%x1,%x0"
[(set_attr "length" "2")])
;; extzv:SI
-(define_insn "*extzv_8_8"
+(define_insn_and_split "*extzv_8_8"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r")
(const_int 8)
(const_int 8)))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extzv_8_8_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r")
+ (const_int 8)
+ (const_int 8)))
+ (clobber (reg:CC CC_REG))]
+ ""
"@
mov.b\\t%x1,%w0\;extu.w\\t%f0\;extu.l\\t%S0
sub.l\\t%S0,%S0\;mov.b\\t%x1,%w0"
- [(set_attr "cc" "set_znv,clobber")
- (set_attr "length" "6,4")])
+ [(set_attr "length" "6,4")])
-(define_insn "*extzv_8_16"
+(define_insn_and_split "*extzv_8_16"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(const_int 8)
(const_int 16)))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1) (const_int 8) (const_int 16)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extzv_8_16_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (const_int 16)))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.w\\t%e1,%f0\;extu.w\\t%f0\;extu.l\\t%S0"
- [(set_attr "cc" "set_znv")
- (set_attr "length" "6")])
+ [(set_attr "length" "6")])
-(define_insn "*extzv_16_8"
+(define_insn_and_split "*extzv_16_8"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(const_int 16)
(const_int 8)))
(clobber (match_scratch:SI 2 "=&r"))]
"TARGET_H8300H"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1) (const_int 16) (const_int 8)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extzv_16_8_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 16)
+ (const_int 8)))
+ (clobber (match_scratch:SI 2 "=&r"))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300H"
"mov.w\\t%e1,%f2\;mov.b\\t%x1,%w0\;mov.b\\t%w2,%x0\;extu.l\\t%S0"
- [(set_attr "length" "8")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "8")])
;; Extract the exponent of a float.
@@ -100,12 +205,13 @@
[(parallel [(set (match_dup 0)
(ashift:SI (match_dup 0)
(const_int 1)))
- (clobber (scratch:QI))])
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 0)
(lshiftrt:SI (match_dup 0)
(const_int 24)))
- (clobber (scratch:QI))])]
- "")
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])])
;; and:SI
@@ -122,12 +228,13 @@
[(parallel [(set (match_dup 0)
(ashift:SI (match_dup 0)
(const_int 16)))
- (clobber (scratch:QI))])
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 0)
(lshiftrt:SI (match_dup 0)
(const_int 1)))
- (clobber (scratch:QI))])]
- "")
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])])
;; Transform (SImode << B) & 0xffff into (SImode) (HImode << B).
@@ -145,22 +252,39 @@
[(parallel [(set (match_dup 5)
(ashift:HI (match_dup 5)
(match_dup 2)))
- (clobber (match_dup 4))])
- (set (match_dup 0)
- (zero_extend:SI (match_dup 5)))]
+ (clobber (match_dup 4))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0)
+ (zero_extend:SI (match_dup 5)))
+ (clobber (reg:CC CC_REG))])]
{
operands[5] = gen_rtx_REG (HImode, REGNO (operands[0]));
})
;; Accept (A >> 30) & 2 and the like.
-(define_insn "*andsi3_lshiftrt_n_sb"
+(define_insn_and_split "*andsi3_lshiftrt_n_sb"
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "single_one_operand" "n")))]
"exact_log2 (INTVAL (operands[3])) < 16
&& INTVAL (operands[2]) + exact_log2 (INTVAL (operands[3])) == 31"
+ "#"
+ ""
+ [(parallel [(set (match_dup 0)
+ (and:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
+ (match_dup 3)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*andsi3_lshiftrt_n_sb"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "single_one_operand" "n")))
+ (clobber (reg:CC CC_REG))]
+ "exact_log2 (INTVAL (operands[3])) < 16
+ && INTVAL (operands[2]) + exact_log2 (INTVAL (operands[3])) == 31"
{
operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
return "shll.l\\t%S0\;xor.l\\t%S0,%S0\;bst\\t%Z3,%Y0";
@@ -175,172 +299,330 @@
""
"#"
"&& reload_completed"
- [(set (match_dup 0)
- (and:SI (lshiftrt:SI (match_dup 0)
- (const_int 25))
- (const_int 64)))
+ [(parallel [(set (match_dup 0)
+ (and:SI (lshiftrt:SI (match_dup 0) (const_int 25))
+ (const_int 64)))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 0)
(ashift:SI (match_dup 0)
(const_int 16)))
- (clobber (scratch:QI))])]
- "")
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])])
;; plus:SI
-(define_insn "*addsi3_upper"
+(define_insn_and_split "*addsi3_upper"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
(const_int 65536))
(match_operand:SI 2 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 1) (const_int 65536))
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*addsi3_upper_clobber_regs"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 65536))
+ (match_operand:SI 2 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"add.w\\t%f1,%e0"
[(set_attr "length" "2")])
-(define_insn "*addsi3_lshiftrt_16_zexthi"
+(define_insn_and_split "*addsi3_lshiftrt_16_zexthi"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 16))
(zero_extend:SI (match_operand:HI 2 "register_operand" "0"))))]
""
- "add.w\\t%e1,%f0\;xor.w\\t%e0,%e0\;rotxl.w\\t%e0"
- [(set_attr "length" "6")])
-
-(define_insn_and_split "*addsi3_and_r_1"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (and:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 1))
- (match_operand:SI 2 "register_operand" "0")))]
- ""
"#"
- "&& reload_completed"
- [(set (cc0) (compare (zero_extract:SI (match_dup 1)
- (const_int 1)
- (const_int 0))
- (const_int 0)))
- (set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_dup 3))
- (pc)))
- (set (match_dup 2)
- (plus:SI (match_dup 2)
- (const_int 1)))
- (match_dup 3)]
- {
- operands[3] = gen_label_rtx ();
- })
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (lshiftrt:SI (match_dup 1) (const_int 16))
+ (zero_extend:SI (match_dup 2))))
+ (clobber (reg:CC CC_REG))])])
-(define_insn_and_split "*addsi3_and_not_r_1"
+(define_insn "*addsi3_lshiftrt_16_zexthi_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
- (const_int 1))
- (match_operand:SI 2 "register_operand" "0")))]
+ (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 16))
+ (zero_extend:SI (match_operand:HI 2 "register_operand" "0"))))
+ (clobber (reg:CC CC_REG))]
""
- "#"
- "&& reload_completed"
- [(set (cc0) (compare (zero_extract:SI (match_dup 1)
- (const_int 1)
- (const_int 0))
- (const_int 0)))
- (set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_dup 3))
- (pc)))
- (set (match_dup 2)
- (plus:SI (match_dup 2)
- (const_int 1)))
- (match_dup 3)]
- {
- operands[3] = gen_label_rtx ();
- })
+ "add.w\\t%e1,%f0\;xor.w\\t%e0,%e0\;rotxl.w\\t%e0"
+ [(set_attr "length" "6")])
+
+;;(define_insn_and_split "*addsi3_and_r_1"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (plus:SI (and:SI (match_operand:SI 1 "register_operand" "r")
+;; (const_int 1))
+;; (match_operand:SI 2 "register_operand" "0")))]
+;; ""
+;; "#"
+;; "&& reload_completed"
+;; [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+;; (const_int 1)
+;; (const_int 0))
+;; (const_int 0)))
+;; (set (pc)
+;; (if_then_else (eq (cc0)
+;; (const_int 0))
+;; (label_ref (match_dup 3))
+;; (pc)))
+;; (set (match_dup 2)
+;; (plus:SI (match_dup 2)
+;; (const_int 1)))
+;; (match_dup 3)]
+;; {
+;; operands[3] = gen_label_rtx ();
+;; })
+
+;;(define_insn_and_split "*addsi3_and_not_r_1"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (plus:SI (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
+;; (const_int 1))
+;; (match_operand:SI 2 "register_operand" "0")))]
+;; ""
+;; "#"
+;; "&& reload_completed"
+;; [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+;; (const_int 1)
+;; (const_int 0))
+;; (const_int 0)))
+;; (set (pc)
+;; (if_then_else (ne (cc0)
+;; (const_int 0))
+;; (label_ref (match_dup 3))
+;; (pc)))
+;; (set (match_dup 2)
+;; (plus:SI (match_dup 2)
+;; (const_int 1)))
+;; (match_dup 3)]
+;; {
+;; operands[3] = gen_label_rtx ();
+;; })
;; [ix]or:HI
-(define_insn "*ixorhi3_zext"
+(define_insn_and_split "*ixorhi3_zext"
[(set (match_operand:HI 0 "register_operand" "=r")
(match_operator:HI 1 "iorxor_operator"
[(zero_extend:HI (match_operand:QI 2 "register_operand" "r"))
(match_operand:HI 3 "register_operand" "0")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 1 [(zero_extend:HI (match_dup 2))
+ (match_dup 3)]))
+ (clobber (reg:CC CC_REG))])])
+
+
+(define_insn "*ixorhi3_zext_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (match_operator:HI 1 "iorxor_operator"
+ [(zero_extend:HI (match_operand:QI 2 "register_operand" "r"))
+ (match_operand:HI 3 "register_operand" "0")]))
+ (clobber (reg:CC CC_REG))]
+ ""
"%c1.b\\t%X2,%s0"
[(set_attr "length" "2")])
;; [ix]or:SI
-(define_insn "*ixorsi3_zext_qi"
+(define_insn_and_split "*ixorsi3_zext_qi"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "iorxor_operator"
[(zero_extend:SI (match_operand:QI 2 "register_operand" "r"))
(match_operand:SI 3 "register_operand" "0")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 1 [(zero_extend:SI (match_dup 2))
+ (match_dup 3)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*ixorsi3_zext_qi_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "iorxor_operator"
+ [(zero_extend:SI (match_operand:QI 2 "register_operand" "r"))
+ (match_operand:SI 3 "register_operand" "0")]))
+ (clobber (reg:CC CC_REG))]
+ ""
"%c1.b\\t%X2,%w0"
[(set_attr "length" "2")])
-(define_insn "*ixorsi3_zext_hi"
+(define_insn_and_split "*ixorsi3_zext_hi"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "iorxor_operator"
[(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))
(match_operand:SI 3 "register_operand" "0")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 1 [(zero_extend:SI (match_dup 2))
+ (match_dup 3)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*ixorsi3_zext_hi_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "iorxor_operator"
+ [(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))
+ (match_operand:SI 3 "register_operand" "0")]))
+ (clobber (reg:CC CC_REG))]
+ ""
"%c1.w\\t%T2,%f0"
[(set_attr "length" "2")])
-(define_insn "*ixorsi3_ashift_16"
+(define_insn_and_split "*ixorsi3_ashift_16"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "iorxor_operator"
[(ashift:SI (match_operand:SI 2 "register_operand" "r")
(const_int 16))
(match_operand:SI 3 "register_operand" "0")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 1 [(ashift:SI (match_dup 2) (const_int 16))
+ (match_dup 3)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*ixorsi3_ashift_16_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "iorxor_operator"
+ [(ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 16))
+ (match_operand:SI 3 "register_operand" "0")]))
+ (clobber (reg:CC CC_REG))]
+ ""
"%c1.w\\t%f2,%e0"
[(set_attr "length" "2")])
-(define_insn "*ixorsi3_lshiftrt_16"
+(define_insn_and_split "*ixorsi3_lshiftrt_16"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "iorxor_operator"
[(lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
(const_int 16))
(match_operand:SI 3 "register_operand" "0")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 1 [(lshiftrt:SI (match_dup 2) (const_int 16))
+ (match_dup 3)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*ixorsi3_lshiftrt_16_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "iorxor_operator"
+ [(lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 16))
+ (match_operand:SI 3 "register_operand" "0")]))
+ (clobber (reg:CC CC_REG))]
+ ""
"%c1.w\\t%e2,%f0"
[(set_attr "length" "2")])
;; ior:HI
-(define_insn "*iorhi3_ashift_8"
+(define_insn_and_split "*iorhi3_ashift_8"
[(set (match_operand:HI 0 "register_operand" "=r")
(ior:HI (ashift:HI (match_operand:HI 1 "register_operand" "r")
(const_int 8))
(match_operand:HI 2 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:HI (ashift:HI (match_dup 1) (const_int 8))
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorhi3_ashift_8_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ior:HI (ashift:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 8))
+ (match_operand:HI 2 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"or.b\\t%s1,%t0"
[(set_attr "length" "2")])
-(define_insn "*iorhi3_lshiftrt_8"
+(define_insn_and_split "*iorhi3_lshiftrt_8"
[(set (match_operand:HI 0 "register_operand" "=r")
(ior:HI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
(const_int 8))
(match_operand:HI 2 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:HI (lshiftrt:HI (match_dup 1) (const_int 8))
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorhi3_lshiftrt_8_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ior:HI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 8))
+ (match_operand:HI 2 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"or.b\\t%t1,%s0"
[(set_attr "length" "2")])
-(define_insn "*iorhi3_two_qi"
+(define_insn_and_split "*iorhi3_two_qi"
[(set (match_operand:HI 0 "register_operand" "=r")
(ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
(ashift:HI (match_operand:HI 2 "register_operand" "r")
(const_int 8))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:HI (zero_extend:HI (match_dup 1))
+ (ashift:HI (match_dup 2) (const_int 8))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorhi3_two_qi_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
+ (ashift:HI (match_operand:HI 2 "register_operand" "r")
+ (const_int 8))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.b\\t%s2,%t0"
[(set_attr "length" "2")])
-(define_insn "*iorhi3_two_qi_mem"
+(define_insn_and_split "*iorhi3_two_qi_mem"
[(set (match_operand:HI 0 "register_operand" "=&r")
(ior:HI (zero_extend:HI (match_operand:QI 1 "memory_operand" "m"))
(ashift:HI (subreg:HI (match_operand:QI 2 "memory_operand" "m") 0)
(const_int 8))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:HI (zero_extend:HI (match_dup 1))
+ (ashift:HI (subreg:HI (match_dup 2) 0)
+ (const_int 8))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorhi3_two_qi_mem_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (ior:HI (zero_extend:HI (match_operand:QI 1 "memory_operand" "m"))
+ (ashift:HI (subreg:HI (match_operand:QI 2 "memory_operand" "m") 0)
+ (const_int 8))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.b\\t%X2,%t0\;mov.b\\t%X1,%s0"
[(set_attr "length" "16")])
@@ -351,20 +633,34 @@
(const_int 8))))]
"reload_completed
&& byte_accesses_mergeable_p (XEXP (operands[2], 0), XEXP (operands[1], 0))"
- [(set (match_dup 0)
- (match_dup 3))]
+ [(parallel [(set (match_dup 0) (match_dup 3))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_MEM (HImode, XEXP (operands[2], 0));
})
;; ior:SI
-(define_insn "*iorsi3_two_hi"
+(define_insn_and_split "*iorsi3_two_hi"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
(ashift:SI (match_operand:SI 2 "register_operand" "r")
(const_int 16))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (zero_extend:SI (match_dup 1))
+ (ashift:SI (match_dup 2) (const_int 16))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_two_hi_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
+ (ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 16))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.w\\t%f2,%e0"
[(set_attr "length" "2")])
@@ -377,23 +673,39 @@
""
"#"
"&& reload_completed"
- [(set (match_dup 3)
- (ior:HI (zero_extend:HI (match_dup 1))
- (ashift:HI (subreg:HI (match_dup 2) 0)
- (const_int 8))))
- (set (match_dup 0)
- (zero_extend:SI (match_dup 3)))]
+ [(parallel [(set (match_dup 3)
+ (ior:HI (zero_extend:HI (match_dup 1))
+ (ashift:HI (subreg:HI (match_dup 2) 0)
+ (const_int 8))))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0) (zero_extend:SI (match_dup 3)))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
})
-(define_insn "*iorsi3_e2f"
+(define_insn_and_split "*iorsi3_e2f"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
(const_int -65536))
(lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
(const_int 16))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (match_dup 1) (const_int -65536))
+ (lshiftrt:SI (match_dup 2) (const_int 16))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_e2f_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int -65536))
+ (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 16))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.w\\t%e2,%f0"
[(set_attr "length" "2")])
@@ -405,43 +717,86 @@
""
"#"
"&& reload_completed"
- [(set (match_dup 3)
- (ior:HI (zero_extend:HI (match_dup 1))
- (ashift:HI (match_dup 4)
- (const_int 8))))
- (set (match_dup 0)
- (sign_extend:SI (match_dup 3)))]
+ [(parallel [(set (match_dup 3)
+ (ior:HI (zero_extend:HI (match_dup 1))
+ (ashift:HI (match_dup 4) (const_int 8))))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0) (sign_extend:SI (match_dup 3)))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
})
-(define_insn "*iorsi3_w"
+(define_insn_and_split "*iorsi3_w"
[(set (match_operand:SI 0 "register_operand" "=r,&r")
(ior:SI (and:SI (match_operand:SI 1 "register_operand" "0,0")
(const_int -256))
(zero_extend:SI (match_operand:QI 2 "general_operand_src" "r,g>"))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (match_dup 1) (const_int -256))
+ (zero_extend:SI (match_dup 2))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_w_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0,0")
+ (const_int -256))
+ (zero_extend:SI (match_operand:QI 2 "general_operand_src" "r,g>"))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.b\\t%X2,%w0"
[(set_attr "length" "2,8")])
-(define_insn "*iorsi3_ashift_31"
+(define_insn_and_split "*iorsi3_ashift_31"
[(set (match_operand:SI 0 "register_operand" "=&r")
(ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
(const_int 31))
(match_operand:SI 2 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (ashift:SI (match_dup 1) (const_int 31))
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_ashift_31_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 31))
+ (match_operand:SI 2 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"rotxl.l\\t%S0\;bor\\t#0,%w1\;rotxr.l\\t%S0"
- [(set_attr "length" "6")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "6")])
-(define_insn "*iorsi3_and_ashift"
+(define_insn_and_split "*iorsi3_and_ashift"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "single_one_operand" "n"))
(match_operand:SI 4 "register_operand" "0")))]
"(INTVAL (operands[3]) & ~0xffff) == 0"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (ashift:SI (match_dup 1) (match_dup 2))
+ (match_dup 3))
+ (match_dup 4)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_and_ashift_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "single_one_operand" "n"))
+ (match_operand:SI 4 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "(INTVAL (operands[3]) & ~0xffff) == 0"
{
rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3]))
- INTVAL (operands[2]));
@@ -452,13 +807,29 @@
}
[(set_attr "length" "6")])
-(define_insn "*iorsi3_and_lshiftrt"
+(define_insn_and_split "*iorsi3_and_lshiftrt"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "single_one_operand" "n"))
(match_operand:SI 4 "register_operand" "0")))]
"((INTVAL (operands[3]) << INTVAL (operands[2])) & ~0xffff) == 0"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
+ (match_dup 3))
+ (match_dup 4)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_and_lshiftrt_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "single_one_operand" "n"))
+ (match_operand:SI 4 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "((INTVAL (operands[3]) << INTVAL (operands[2])) & ~0xffff) == 0"
{
rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3]))
+ INTVAL (operands[2]));
@@ -469,27 +840,60 @@
}
[(set_attr "length" "6")])
-(define_insn "*iorsi3_zero_extract"
+(define_insn_and_split "*iorsi3_zero_extract"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(const_int 1)
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "register_operand" "0")))]
"INTVAL (operands[2]) < 16"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (zero_extract:SI (match_dup 1)
+ (const_int 1)
+ (match_dup 2))
+ (match_dup 3)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_zero_extract_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "INTVAL (operands[2]) < 16"
"bld\\t%Z2,%Y1\;bor\\t#0,%w0\;bst\\t#0,%w0"
[(set_attr "length" "6")])
-(define_insn "*iorsi3_and_lshiftrt_n_sb"
+(define_insn_and_split "*iorsi3_and_lshiftrt_n_sb"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 30))
(const_int 2))
(match_operand:SI 2 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (lshiftrt:SI (match_dup 1) (const_int 30))
+ (const_int 2))
+ (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi3_and_lshiftrt_n_sb_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 30))
+ (const_int 2))
+ (match_operand:SI 2 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"rotl.l\\t%S1\;rotr.l\\t%S1\;bor\\t#1,%w0\;bst\\t#1,%w0"
[(set_attr "length" "8")])
-(define_insn "*iorsi3_and_lshiftrt_9_sb"
+(define_insn_and_split "*iorsi3_and_lshiftrt_9_sb"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 9))
@@ -497,6 +901,25 @@
(match_operand:SI 2 "register_operand" "0")))
(clobber (match_scratch:HI 3 "=&r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (lshiftrt:SI (match_dup 1) (const_int 9))
+ (const_int 4194304))
+ (match_dup 2)))
+ (clobber (match_dup 3))
+ (clobber (reg:CC CC_REG))])])
+
+
+(define_insn "*iorsi3_and_lshiftrt_9_sb_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 9))
+ (const_int 4194304))
+ (match_operand:SI 2 "register_operand" "0")))
+ (clobber (match_scratch:HI 3 "=&r"))
+ (clobber (reg:CC CC_REG))]
+ ""
{
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
return "shll.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0";
@@ -528,11 +951,12 @@
[(parallel [(set (match_dup 3)
(ashift:HI (match_dup 3)
(const_int 7)))
- (clobber (scratch:QI))])
- (set (match_dup 0)
- (ior:SI (ashift:SI (match_dup 1)
- (const_int 16))
- (match_dup 0)))]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0)
+ (ior:SI (ashift:SI (match_dup 1) (const_int 16))
+ (match_dup 0)))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
})
@@ -546,27 +970,43 @@
"epilogue_completed
&& !(find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1]))"
- [(set (match_dup 2)
- (match_dup 1))
+ [(parallel [(set (match_dup 2) (match_dup 1))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 3)
(ashift:HI (match_dup 3)
(const_int 7)))
- (clobber (scratch:QI))])
- (set (match_dup 0)
- (ior:SI (ashift:SI (match_dup 2)
- (const_int 16))
- (match_dup 0)))]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0)
+ (ior:SI (ashift:SI (match_dup 2) (const_int 16))
+ (match_dup 0)))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[2]));
})
-(define_insn "*iorsi2_and_1_lshiftrt_1"
+(define_insn_and_split "*iorsi2_and_1_lshiftrt_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
(const_int 1))
(lshiftrt:SI (match_dup 1)
(const_int 1))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (ior:SI (and:SI (match_dup 1) (const_int 1))
+ (lshiftrt:SI (match_dup 1) (const_int 1))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*iorsi2_and_1_lshiftrt_1_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 1))
+ (lshiftrt:SI (match_dup 1)
+ (const_int 1))))
+ (clobber (reg:CC CC_REG))]
+ ""
"shlr.l\\t%S0\;bor\\t#0,%w0\;bst\\t#0,%w0"
[(set_attr "length" "6")])
@@ -579,14 +1019,15 @@
""
"#"
"&& reload_completed"
- [(set (match_dup 3)
- (ior:HI (ashift:HI (match_dup 4)
- (const_int 8))
- (match_dup 3)))
+ [(parallel [(set (match_dup 3)
+ (ior:HI (ashift:HI (match_dup 4) (const_int 8))
+ (match_dup 3)))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 0)
(ashift:SI (match_dup 0)
(const_int 16)))
- (clobber (scratch:QI))])]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
operands[4] = gen_rtx_REG (HImode, REGNO (operands[2]));
@@ -602,14 +1043,16 @@
""
"#"
"&& reload_completed"
- [(set (match_dup 3)
- (ior:HI (zero_extend:HI (match_dup 1))
- (ashift:HI (subreg:HI (match_dup 2) 0)
- (const_int 8))))
+ [(parallel [(set (match_dup 3)
+ (ior:HI (zero_extend:HI (match_dup 1))
+ (ashift:HI (subreg:HI (match_dup 2) 0)
+ (const_int 8))))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 0)
(ashift:SI (match_dup 0)
(const_int 16)))
- (clobber (scratch:QI))])]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
})
@@ -637,11 +1080,12 @@
[(parallel [(set (match_dup 3)
(ashift:HI (match_dup 3)
(const_int 7)))
- (clobber (scratch:QI))])
- (set (match_dup 0)
- (plus:SI (mult:SI (match_dup 1)
- (const_int 65536))
- (match_dup 0)))]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 1) (const_int 65536))
+ (match_dup 0)))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
})
@@ -655,16 +1099,17 @@
"epilogue_completed
&& !(find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1]))"
- [(set (match_dup 2)
- (match_dup 1))
+ [(parallel [(set (match_dup 2) (match_dup 1))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 3)
(ashift:HI (match_dup 3)
(const_int 7)))
- (clobber (scratch:QI))])
- (set (match_dup 0)
- (plus:SI (mult:SI (match_dup 2)
- (const_int 65536))
- (match_dup 0)))]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 2) (const_int 65536))
+ (match_dup 0)))
+ (clobber (reg:CC CC_REG))])]
{
operands[3] = gen_rtx_REG (HImode, REGNO (operands[2]));
})
@@ -681,93 +1126,145 @@
[(parallel [(set (match_dup 2)
(ashift:HI (match_dup 2)
(const_int 8)))
- (clobber (scratch:QI))])
- (set (match_dup 0)
- (sign_extend:SI (match_dup 2)))
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0) (sign_extend:SI (match_dup 2)))
+ (clobber (reg:CC CC_REG))])
(parallel [(set (match_dup 0)
(ashiftrt:SI (match_dup 0)
(const_int 1)))
- (clobber (scratch:QI))])]
+ (clobber (scratch:QI))
+ (clobber (reg:CC CC_REG))])]
{
operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
})
;; Storing a part of HImode to QImode.
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:QI 0 "general_operand_dst" "=rm<")
(subreg:QI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
(const_int 8)) 1))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (subreg:QI (lshiftrt:HI (match_dup 1)
+ (const_int 8)) 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+ (subreg:QI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 8)) 1))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.b\\t%t1,%R0"
- [(set_attr "cc" "set_znv")
- (set_attr "length" "8")])
+ [(set_attr "length" "8")])
;; Storing a part of SImode to QImode.
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:QI 0 "general_operand_dst" "=rm<")
(subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 8)) 3))]
""
- "mov.b\\t%x1,%R0"
- [(set_attr "cc" "set_znv")
- (set_attr "length" "8")])
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (subreg:QI (lshiftrt:SI (match_dup 1) (const_int 8)) 3))
+ (clobber (reg:CC CC_REG))])])
(define_insn ""
[(set (match_operand:QI 0 "general_operand_dst" "=rm<")
(subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)) 3))
+ (clobber (reg:CC CC_REG))]
+ ""
+ "mov.b\\t%x1,%R0"
+ [(set_attr "length" "8")])
+
+(define_insn_and_split ""
+ [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+ (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 16)) 3))
(clobber (match_scratch:SI 2 "=&r"))]
""
- "mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0"
- [(set_attr "cc" "set_znv")
- (set_attr "length" "10")])
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (subreg:QI (lshiftrt:SI (match_dup 1) (const_int 16)) 3))
+ (clobber (match_dup 2))
+ (clobber (reg:CC CC_REG))])])
(define_insn ""
[(set (match_operand:QI 0 "general_operand_dst" "=rm<")
(subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 16)) 3))
+ (clobber (match_scratch:SI 2 "=&r"))
+ (clobber (reg:CC CC_REG))]
+ ""
+ "mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0"
+ [(set_attr "length" "10")])
+
+(define_insn_and_split ""
+ [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+ (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(const_int 24)) 3))
(clobber (match_scratch:SI 2 "=&r"))]
""
- "mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0"
- [(set_attr "cc" "set_znv")
- (set_attr "length" "10")])
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (subreg:QI (lshiftrt:SI (match_dup 1) (const_int 24)) 3))
+ (clobber (match_dup 2))
+ (clobber (reg:CC CC_REG))])])
-(define_insn_and_split ""
- [(set (pc)
- (if_then_else (eq (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0)
- (const_int 1)
- (const_int 7))
- (const_int 0))
- (match_operand 1 "pc_or_label_operand" "")
- (match_operand 2 "pc_or_label_operand" "")))]
- "operands[1] == pc_rtx || operands[2] == pc_rtx"
- "#"
- ""
- [(set (cc0) (compare (match_dup 0)
- (const_int 0)))
- (set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))])
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+ (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 24)) 3))
+ (clobber (match_scratch:SI 2 "=&r"))
+ (clobber (reg:CC CC_REG))]
+ ""
+ "mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0"
+ [(set_attr "length" "10")])
-(define_insn_and_split ""
- [(set (pc)
- (if_then_else (ne (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0)
- (const_int 1)
- (const_int 7))
- (const_int 0))
- (match_operand 1 "pc_or_label_operand" "")
- (match_operand 2 "pc_or_label_operand" "")))]
- "operands[1] == pc_rtx || operands[2] == pc_rtx"
- "#"
- ""
- [(set (cc0) (compare (match_dup 0)
- (const_int 0)))
- (set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))])
+;;(define_insn_and_split ""
+;; [(set (pc)
+;; (if_then_else (eq (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0)
+;; (const_int 1)
+;; (const_int 7))
+;; (const_int 0))
+;; (label_ref (match_operand 1 "" ""))
+;; (pc)))]
+;; ""
+;; "#"
+;; ""
+;; [(set (cc0) (compare (match_dup 0)
+;; (const_int 0)))
+;; (set (pc)
+;; (if_then_else (ge (cc0)
+;; (const_int 0))
+;; (label_ref (match_dup 1))
+;; (pc)))]
+;; "")
+;;
+;; (define_insn_and_split ""
+;; [(set (pc)
+;; (if_then_else (ne (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0)
+;; (const_int 1)
+;; (const_int 7))
+;; (const_int 0))
+;; (label_ref (match_operand 1 "" ""))
+;; (pc)))]
+;; ""
+;; "#"
+;; ""
+;; [(set (cc0) (compare (match_dup 0)
+;; (const_int 0)))
+;; (set (pc)
+;; (if_then_else (lt (cc0)
+;; (const_int 0))
+;; (label_ref (match_dup 1))
+;; (pc)))]
+;; "")
diff --git a/gcc/config/h8300/constraints.md b/gcc/config/h8300/constraints.md
index d245182..1d80152 100644
--- a/gcc/config/h8300/constraints.md
+++ b/gcc/config/h8300/constraints.md
@@ -152,7 +152,7 @@
(define_constraint "R"
"@internal"
(and (match_code "const_int")
- (match_test "!h8300_shift_needs_scratch_p (ival, QImode)")))
+ (match_test "!h8300_shift_needs_scratch_p (ival, QImode, CLOBBER)")))
(define_constraint "C"
"@internal"
@@ -161,12 +161,12 @@
(define_constraint "S"
"@internal"
(and (match_code "const_int")
- (match_test "!h8300_shift_needs_scratch_p (ival, HImode)")))
+ (match_test "!h8300_shift_needs_scratch_p (ival, HImode, CLOBBER)")))
(define_constraint "T"
"@internal"
(and (match_code "const_int")
- (match_test "!h8300_shift_needs_scratch_p (ival, SImode)")))
+ (match_test "!h8300_shift_needs_scratch_p (ival, SImode, CLOBBER)")))
(define_constraint "U"
"An operand valid for a bset destination."
diff --git a/gcc/config/h8300/divmod.md b/gcc/config/h8300/divmod.md
index 7e0d7f0..b5ab6b7 100644
--- a/gcc/config/h8300/divmod.md
+++ b/gcc/config/h8300/divmod.md
@@ -2,23 +2,45 @@
;; DIVIDE/MOD INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "udiv<mode>3"
+(define_insn_and_split "udiv<mode>3"
[(set (match_operand:HSI 0 "register_operand" "=r")
(udiv:HSI (match_operand:HSI 1 "register_operand" "0")
(match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (udiv:HSI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "udiv<mode>3_clobber_flags"
+ [(set (match_operand:HSI 0 "register_operand" "=r")
+ (udiv:HSI (match_operand:HSI 1 "register_operand" "0")
+ (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
{ return <MODE>mode == HImode ? "divu.w\\t%T2,%T0" : "divu.l\\t%S2,%S0"; }
[(set_attr "length" "4")])
-(define_insn "div<mode>3"
+(define_insn_and_split "div<mode>3"
[(set (match_operand:HSI 0 "register_operand" "=r")
(div:HSI (match_operand:HSI 1 "register_operand" "0")
(match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (div:HSI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "div<mode>3_clobber_flags"
+ [(set (match_operand:HSI 0 "register_operand" "=r")
+ (div:HSI (match_operand:HSI 1 "register_operand" "0")
+ (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
{ return <MODE>mode == HImode ? "divs.w\\t%T2,%T0" : "divs.l\\t%S2,%S0"; }
[(set_attr "length" "4")])
-(define_insn "udivmodqi4"
+(define_insn_and_split "udivmodqi4"
[(set (match_operand:QI 0 "register_operand" "=r")
(truncate:QI
(udiv:HI
@@ -30,6 +52,30 @@
(match_dup 1)
(zero_extend:HI (match_dup 2)))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (truncate:QI
+ (udiv:HI (match_dup 1)
+ (zero_extend:HI (match_dup 2)))))
+ (set (match_dup 3) (truncate:QI
+ (umod:HI (match_dup 1)
+ (zero_extend:HI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))])])
+
+
+(define_insn "udivmodqi4_clobber_flags"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI
+ (udiv:HI
+ (match_operand:HI 1 "register_operand" "0")
+ (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))))
+ (set (match_operand:QI 3 "register_operand" "=r")
+ (truncate:QI
+ (umod:HI
+ (match_dup 1)
+ (zero_extend:HI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))]
+ ""
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "divxu.b\\t%X2,%T0";
@@ -38,7 +84,7 @@
}
[(set_attr "length" "4")])
-(define_insn "divmodqi4"
+(define_insn_and_split "divmodqi4"
[(set (match_operand:QI 0 "register_operand" "=r")
(truncate:QI
(div:HI
@@ -50,6 +96,29 @@
(match_dup 1)
(sign_extend:HI (match_dup 2)))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (truncate:QI
+ (div:HI (match_dup 1)
+ (sign_extend:HI (match_dup 2)))))
+ (set (match_dup 3) (truncate:QI
+ (mod:HI (match_dup 1)
+ (sign_extend:HI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "divmodqi4_clobber_flags"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI
+ (div:HI
+ (match_operand:HI 1 "register_operand" "0")
+ (sign_extend:HI (match_operand:QI 2 "register_operand" "r")))))
+ (set (match_operand:QI 3 "register_operand" "=r")
+ (truncate:QI
+ (mod:HI
+ (match_dup 1)
+ (sign_extend:HI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))]
+ ""
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "divxs.b\\t%X2,%T0";
@@ -58,7 +127,7 @@
}
[(set_attr "length" "6")])
-(define_insn "udivmodhi4"
+(define_insn_and_split "udivmodhi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(truncate:HI
(udiv:SI
@@ -70,6 +139,29 @@
(match_dup 1)
(zero_extend:SI (match_dup 2)))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (truncate:HI
+ (udiv:SI (match_dup 1)
+ (zero_extend:SI (match_dup 2)))))
+ (set (match_dup 3) (truncate:HI
+ (umod:SI (match_dup 1)
+ (zero_extend:SI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "udivmodhi4_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (truncate:HI
+ (udiv:SI
+ (match_operand:SI 1 "register_operand" "0")
+ (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))))
+ (set (match_operand:HI 3 "register_operand" "=r")
+ (truncate:HI
+ (umod:SI
+ (match_dup 1)
+ (zero_extend:SI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))]
+ ""
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "divxu.w\\t%T2,%S0";
@@ -78,7 +170,7 @@
}
[(set_attr "length" "4")])
-(define_insn "divmodhi4"
+(define_insn_and_split "divmodhi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(truncate:HI
(div:SI
@@ -90,6 +182,29 @@
(match_dup 1)
(sign_extend:SI (match_dup 2)))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (truncate:HI
+ (div:SI (match_dup 1)
+ (sign_extend:SI (match_dup 2)))))
+ (set (match_dup 3) (truncate:HI
+ (mod:SI (match_dup 1)
+ (sign_extend:SI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "divmodhi4_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (truncate:HI
+ (div:SI
+ (match_operand:SI 1 "register_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))))
+ (set (match_operand:HI 3 "register_operand" "=r")
+ (truncate:HI
+ (mod:SI
+ (match_dup 1)
+ (sign_extend:SI (match_dup 2)))))
+ (clobber (reg:CC CC_REG))]
+ ""
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return "divxs.w\\t%T2,%S0";
diff --git a/gcc/config/h8300/extensions.md b/gcc/config/h8300/extensions.md
index cf6fb6d1..7631230 100644
--- a/gcc/config/h8300/extensions.md
+++ b/gcc/config/h8300/extensions.md
@@ -11,15 +11,24 @@
operands[1] = force_reg (QImode, operands[1]);
})
-(define_insn "*zero_extendqihi2_h8300hs"
+(define_insn_and_split "*zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*zero_extendqihi2_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))
+ (clobber (reg:CC CC_REG))]
+ ""
"@
extu.w %T0
#"
- [(set_attr "length" "2,10")
- (set_attr "cc" "set_znv,set_znv")])
+ [(set_attr "length" "2,10")])
;; Split the zero extension of a general operand (actually a memory
;; operand) into a load of the operand and the actual zero extension
@@ -28,34 +37,36 @@
(define_split
[(set (match_operand:HI 0 "register_operand" "")
- (zero_extend:HI (match_operand:QI 1 "general_operand_src" "")))]
+ (zero_extend:HI (match_operand:QI 1 "general_operand_src" "")))
+ (clobber (reg:CC CC_REG))]
"reload_completed"
- [(set (match_dup 2)
- (match_dup 1))
- (set (match_dup 0)
- (zero_extend:HI (match_dup 2)))]
+ [(set (match_dup 2) (match_dup 1))
+ (parallel [(set (match_dup 0) (zero_extend:HI (match_dup 2)))
+ (clobber (reg:CC CC_REG))])]
{
operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));
})
-(define_insn "*zero_extendqisi2_h8300hs"
+(define_insn "*zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))]
- "!TARGET_H8300SX"
+ "!reload_completed && !TARGET_H8300SX"
"#")
+;; Two cases for the !H8/SX target. One where there is an overlap
+;; between the source and destination, one where there is no overlap
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:QI 1 "general_operand_src" "")))]
"!TARGET_H8300SX
&& reg_overlap_mentioned_p (operands[0], operands[1])
&& reload_completed"
- [(set (match_dup 2)
- (match_dup 1))
- (set (match_dup 3)
- (zero_extend:HI (match_dup 2)))
- (set (match_dup 0)
- (zero_extend:SI (match_dup 3)))]
+ [(parallel [(set (match_dup 2) (match_dup 1))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 3) (zero_extend:HI (match_dup 2)))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0) (zero_extend:SI (match_dup 3)))
+ (clobber (reg:CC CC_REG))])]
{
operands[2] = gen_lowpart (QImode, operands[0]);
operands[3] = gen_lowpart (HImode, operands[0]);
@@ -67,21 +78,30 @@
"!TARGET_H8300SX
&& !reg_overlap_mentioned_p (operands[0], operands[1])
&& reload_completed"
- [(set (match_dup 0)
- (const_int 0))
- (set (strict_low_part (match_dup 2))
- (match_dup 1))]
+ [(parallel [(set (match_dup 0) (const_int 0))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (strict_low_part (match_dup 2)) (match_dup 1))
+ (clobber (reg:CC CC_REG))])]
{
operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));
})
-(define_insn "*zero_extendqisi2_h8sx"
+(define_insn_and_split "*zero_extendqisi2_h8sx"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:QI 1 "register_operand" "0")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*zero_extendqisi2_h8sx_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"extu.l\t#2,%0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
(define_expand "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -89,13 +109,22 @@
""
"")
-(define_insn "*zero_extendhisi2_h8300hs"
+(define_insn_and_split "*zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*zero_extendhisi2_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"extu.l %S0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
(define_expand "extendqi<mode>2"
[(set (match_operand:HSI 0 "register_operand" "")
@@ -103,39 +132,57 @@
""
"")
-(define_insn "*extendqihi2_h8300hs"
+(define_insn_and_split "*extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI (match_operand:QI 1 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extendqihi2_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"exts.w %T0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
;; The following pattern is needed because without the pattern, the
;; combiner would split (sign_extend:SI (reg:QI)) into two 24-bit
;; shifts, one ashift and one ashiftrt.
-(define_insn_and_split "*extendqisi2_h8300hs"
+(define_insn_and_split "*extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:QI 1 "register_operand" "0")))]
"!TARGET_H8300SX"
"#"
"&& reload_completed"
- [(set (match_dup 2)
- (sign_extend:HI (match_dup 1)))
- (set (match_dup 0)
- (sign_extend:SI (match_dup 2)))]
+ [(parallel [(set (match_dup 2) (sign_extend:HI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0) (sign_extend:SI (match_dup 2)))
+ (clobber (reg:CC CC_REG))])]
{
operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
})
-(define_insn "*extendqisi2_h8sx"
+(define_insn_and_split "*extendqisi2_h8sx"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:QI 1 "register_operand" "0")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extendqisi2_h8sx_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"exts.l\t#2,%0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
(define_expand "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -143,10 +190,19 @@
""
"")
-(define_insn "*extendhisi2_h8300hs"
+(define_insn_and_split "*extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:HI 1 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*extendhisi2_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"exts.l %S0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
diff --git a/gcc/config/h8300/genmova.sh b/gcc/config/h8300/genmova.sh
index 22b01cc..8ab018f 100644
--- a/gcc/config/h8300/genmova.sh
+++ b/gcc/config/h8300/genmova.sh
@@ -71,8 +71,7 @@ for s in QI HI; do
(match_operand:$d 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/b.l @(%o2%C2,$src),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
EOF
;;
@@ -115,8 +114,7 @@ EOF
(match_operand:$d 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/$opsize.l @(%o2%C2,$src),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
EOF
;;
@@ -134,8 +132,7 @@ EOF
(const_int $amount)))]
"TARGET_H8300SX"
"mova/$opsize.l @(0,$src),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r,r")
@@ -144,8 +141,7 @@ EOF
(match_operand:$d 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/$opsize.l @(%o2%C2,$src),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
EOF
@@ -174,8 +170,7 @@ EOF
(const_int $mask)))]
"TARGET_H8300SX"
"mova/$opsize.l @(0,$src),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r")
@@ -185,8 +180,7 @@ EOF
(match_operand:$d 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/$opsize.l @(%o2%C2,$src),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
EOF
done
diff --git a/gcc/config/h8300/h8300-modes.def b/gcc/config/h8300/h8300-modes.def
new file mode 100644
index 0000000..2f36c7e
--- /dev/null
+++ b/gcc/config/h8300/h8300-modes.def
@@ -0,0 +1,21 @@
+/* Definitions of target machine for GNU compiler.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+CC_MODE (CCZN);
+CC_MODE (CCZNV);
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 2416741..2d90036 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -26,8 +26,8 @@ along with GCC; see the file COPYING3. If not see
/* Declarations for functions used in insn-output.c. */
#ifdef RTX_CODE
extern unsigned int compute_mov_length (rtx *);
-extern const char *output_plussi (rtx *);
-extern unsigned int compute_plussi_length (rtx *);
+extern const char *output_plussi (rtx *, bool);
+extern unsigned int compute_plussi_length (rtx *, bool);
extern const char *output_a_shift (rtx *);
extern unsigned int compute_a_shift_length (rtx, rtx *);
extern const char *output_a_rotate (enum rtx_code, rtx *);
@@ -35,19 +35,21 @@ extern unsigned int compute_a_rotate_length (rtx *);
extern const char *output_simode_bld (int, rtx[]);
extern void final_prescan_insn (rtx_insn *, rtx *, int);
extern int h8300_expand_movsi (rtx[]);
+extern machine_mode h8300_select_cc_mode (RTX_CODE, rtx, rtx);
extern void notice_update_cc (rtx, rtx_insn *);
extern const char *output_logical_op (machine_mode, rtx *);
extern unsigned int compute_logical_op_length (machine_mode,
rtx *);
+
+extern int compute_logical_op_cc (machine_mode, rtx *);
+extern int compute_a_shift_cc (rtx, rtx *);
#ifdef HAVE_ATTR_cc
extern enum attr_cc compute_plussi_cc (rtx *);
-extern enum attr_cc compute_a_shift_cc (rtx, rtx *);
-extern enum attr_cc compute_logical_op_cc (machine_mode, rtx *);
#endif
extern void h8300_expand_branch (rtx[]);
extern void h8300_expand_store (rtx[]);
extern bool expand_a_shift (machine_mode, enum rtx_code, rtx[]);
-extern int h8300_shift_needs_scratch_p (int, machine_mode);
+extern int h8300_shift_needs_scratch_p (int, machine_mode, rtx_code);
extern int expand_a_rotate (rtx[]);
extern int fix_bit_operand (rtx *, enum rtx_code);
extern int h8300_adjust_insn_length (rtx, int);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 6875cd9..31e23b2 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -132,13 +132,13 @@ static int pragma_interrupt;
static int pragma_saveall;
static const char *const names_big[] =
-{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "cc" };
static const char *const names_extended[] =
-{ "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7" };
+{ "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7", "cc" };
static const char *const names_upper_extended[] =
-{ "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7" };
+{ "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "cc" };
/* Points to one of the above. */
/* ??? The above could be put in an array indexed by CPU_TYPE. */
@@ -469,11 +469,11 @@ h8300_emit_stack_adjustment (int sign, HOST_WIDE_INT size, bool in_prologue)
stack_pointer_rtx,
GEN_INT (sign * size)));
if (size < 4)
- F (x, in_prologue);
+ F (x, 0);
}
else
F (emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (sign * size))), in_prologue);
+ stack_pointer_rtx, GEN_INT (sign * size))), 0);
}
/* Round up frame size SIZE. */
@@ -520,7 +520,7 @@ push (int rn, bool in_prologue)
x = gen_push_h8300hs_advanced (reg);
else
x = gen_push_h8300hs_normal (reg);
- x = F (emit_insn (x), in_prologue);
+ x = F (emit_insn (x), 0);
add_reg_note (x, REG_INC, stack_pointer_rtx);
return x;
}
@@ -756,7 +756,7 @@ h8300_expand_prologue (void)
{
/* Push fp. */
push (HARD_FRAME_POINTER_REGNUM, true);
- F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx), true);
+ F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx), 0);
}
/* Push the rest of the registers in ascending order. */
@@ -1199,6 +1199,16 @@ h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
return true;
case COMPARE:
+ case NE:
+ case EQ:
+ case GE:
+ case GT:
+ case LE:
+ case LT:
+ case GEU:
+ case GTU:
+ case LEU:
+ case LTU:
if (XEXP (x, 1) == const0_rtx)
*total = 0;
return false;
@@ -1508,10 +1518,20 @@ h8300_print_operand (FILE *file, rtx x, int code)
}
break;
case 'j':
- fputs (cond_string (GET_CODE (x)), file);
+ if (GET_CODE (x) == LT && GET_MODE (XEXP (x, 0)) == E_CCZNmode)
+ fputs ("mi", file);
+ else if (GET_CODE (x) == GE && GET_MODE (XEXP (x, 0)) == E_CCZNmode)
+ fputs ("pl", file);
+ else
+ fputs (cond_string (GET_CODE (x)), file);
break;
case 'k':
- fputs (cond_string (reverse_condition (GET_CODE (x))), file);
+ if (GET_CODE (x) == LT && GET_MODE (XEXP (x, 0)) == E_CCZNmode)
+ fputs ("pl", file);
+ else if (GET_CODE (x) == GE && GET_MODE (XEXP (x, 0)) == E_CCZNmode)
+ fputs ("mi", file);
+ else
+ fputs (cond_string (reverse_condition (GET_CODE (x))), file);
break;
case 'm':
gcc_assert (GET_CODE (x) == CONST_INT);
@@ -1920,72 +1940,22 @@ h8300_return_addr_rtx (int count, rtx frame)
return ret;
}
-/* Update the condition code from the insn. */
-void
-notice_update_cc (rtx body, rtx_insn *insn)
+machine_mode
+h8300_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1)
{
- rtx set;
+ if (op1 == const0_rtx
+ && (cond == EQ || cond == NE || cond == LT || cond == GE)
+ && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
+ || GET_CODE (op0) == NEG || GET_CODE (op0) == AND
+ || GET_CODE (op0) == IOR || GET_CODE (op0) == XOR
+ || GET_CODE (op0) == NOT || GET_CODE (op0) == ASHIFT
+ || GET_CODE (op0) == REG || GET_CODE (op0) == MULT))
+ return CCZNmode;
- switch (get_attr_cc (insn))
- {
- case CC_NONE:
- /* Insn does not affect CC at all. */
- break;
-
- case CC_NONE_0HIT:
- /* Insn does not change CC, but the 0'th operand has been changed. */
- if (cc_status.value1 != 0
- && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
- cc_status.value1 = 0;
- if (cc_status.value2 != 0
- && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))
- cc_status.value2 = 0;
- break;
-
- case CC_SET_ZN:
- /* Insn sets the Z,N flags of CC to recog_data.operand[0].
- The V flag is unusable. The C flag may or may not be known but
- that's ok because alter_cond will change tests to use EQ/NE. */
- CC_STATUS_INIT;
- cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
- set = single_set (insn);
- cc_status.value1 = SET_SRC (set);
- if (SET_DEST (set) != cc0_rtx)
- cc_status.value2 = SET_DEST (set);
- break;
-
- case CC_SET_ZNV:
- /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].
- The C flag may or may not be known but that's ok because
- alter_cond will change tests to use EQ/NE. */
- CC_STATUS_INIT;
- cc_status.flags |= CC_NO_CARRY;
- set = single_set (insn);
- cc_status.value1 = SET_SRC (set);
- if (SET_DEST (set) != cc0_rtx)
- {
- /* If the destination is STRICT_LOW_PART, strip off
- STRICT_LOW_PART. */
- if (GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
- cc_status.value2 = XEXP (SET_DEST (set), 0);
- else
- cc_status.value2 = SET_DEST (set);
- }
- break;
-
- case CC_COMPARE:
- /* The insn is a compare instruction. */
- CC_STATUS_INIT;
- cc_status.value1 = SET_SRC (body);
- break;
-
- case CC_CLOBBER:
- /* Insn doesn't leave CC in a usable state. */
- CC_STATUS_INIT;
- break;
- }
+ return CCmode;
}
+
/* Given that X occurs in an address of the form (plus X constant),
return the part of X that is expected to be a register. There are
@@ -2344,8 +2314,18 @@ static unsigned int
h8300_binary_length (rtx_insn *insn, const h8300_length_table *table)
{
rtx set;
+ rtx pattern;
- set = single_set (insn);
+ if (GET_CODE (insn) != INSN)
+ gcc_unreachable ();
+
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) == PARALLEL
+ && GET_CODE (XVECEXP (pattern, 0, 0)) == SET
+ && GET_CODE (SET_SRC (XVECEXP (pattern, 0, 0))) == COMPARE)
+ set = XVECEXP (pattern, 0, 1);
+ else
+ set = single_set (insn);
gcc_assert (set);
if (BINARY_P (SET_SRC (set)))
@@ -2678,7 +2658,7 @@ compute_mov_length (rtx *operands)
/* Output an addition insn. */
const char *
-output_plussi (rtx *operands)
+output_plussi (rtx *operands, bool need_flags)
{
machine_mode mode = GET_MODE (operands[0]);
@@ -2698,25 +2678,54 @@ output_plussi (rtx *operands)
switch ((unsigned int) intval & 0xffffffff)
{
+ /* INC/DEC set the flags, but adds/subs do not. So if we
+ need flags, use the former and not the latter. */
case 0x00000001:
+ if (need_flags)
+ return "inc.l\t#1,%S0";
+ else
+ return "adds\t%2,%S0";
case 0x00000002:
- case 0x00000004:
- return "adds\t%2,%S0";
-
+ if (need_flags)
+ return "inc.l\t#2,%S0";
+ else
+ return "adds\t%2,%S0";
case 0xffffffff:
+ if (need_flags)
+ return "dec.l\t#1,%S0";
+ else
+ return "subs\t%G2,%S0";
case 0xfffffffe:
+ if (need_flags)
+ return "dec.l\t#2,%S0";
+ else
+ return "subs\t%G2,%S0";
+
+ /* These six cases have optimized paths when we do not
+ need flags. Otherwise we let them fallthru. */
+ case 0x00000004:
+ if (!need_flags)
+ return "adds\t%2,%S0";
+
case 0xfffffffc:
- return "subs\t%G2,%S0";
+ if (!need_flags)
+ return "subs\t%G2,%S0";
case 0x00010000:
case 0x00020000:
- operands[2] = GEN_INT (intval >> 16);
- return "inc.w\t%2,%e0";
+ if (!need_flags)
+ {
+ operands[2] = GEN_INT (intval >> 16);
+ return "inc.w\t%2,%e0";
+ }
case 0xffff0000:
case 0xfffe0000:
- operands[2] = GEN_INT (intval >> 16);
- return "dec.w\t%G2,%e0";
+ if (!need_flags)
+ {
+ operands[2] = GEN_INT (intval >> 16);
+ return "dec.w\t%G2,%e0";
+ }
}
/* See if we can finish with 4 bytes. */
@@ -2740,7 +2749,7 @@ output_plussi (rtx *operands)
/* Compute the length of an addition insn. */
unsigned int
-compute_plussi_length (rtx *operands)
+compute_plussi_length (rtx *operands, bool need_flags)
{
machine_mode mode = GET_MODE (operands[0]);
@@ -2762,21 +2771,31 @@ compute_plussi_length (rtx *operands)
{
case 0x00000001:
case 0x00000002:
- case 0x00000004:
return 2;
+ case 0x00000004:
+ if (need_flags)
+ return 6;
+ else
+ return 2;
case 0xffffffff:
case 0xfffffffe:
- case 0xfffffffc:
return 2;
+ case 0xfffffffc:
+ if (need_flags)
+ return 6;
+ else
+ return 2;
case 0x00010000:
case 0x00020000:
- return 2;
+ if (!need_flags)
+ return 2;
case 0xffff0000:
case 0xfffe0000:
- return 2;
+ if (!need_flags)
+ return 2;
}
/* See if we can finish with 4 bytes. */
@@ -2795,7 +2814,7 @@ compute_plussi_length (rtx *operands)
/* Compute which flag bits are valid after an addition insn. */
-enum attr_cc
+enum attr_old_cc
compute_plussi_cc (rtx *operands)
{
machine_mode mode = GET_MODE (operands[0]);
@@ -2808,9 +2827,9 @@ compute_plussi_cc (rtx *operands)
HOST_WIDE_INT intval = INTVAL (operands[2]);
if (TARGET_H8300SX && (intval >= 1 && intval <= 7))
- return CC_SET_ZN;
+ return OLD_CC_SET_ZN;
if (TARGET_H8300SX && (intval >= -7 && intval <= -1))
- return CC_SET_ZN;
+ return OLD_CC_SET_ZN;
/* See if we can finish with 2 bytes. */
@@ -2819,28 +2838,28 @@ compute_plussi_cc (rtx *operands)
case 0x00000001:
case 0x00000002:
case 0x00000004:
- return CC_NONE_0HIT;
+ return OLD_CC_NONE_0HIT;
case 0xffffffff:
case 0xfffffffe:
case 0xfffffffc:
- return CC_NONE_0HIT;
+ return OLD_CC_NONE_0HIT;
case 0x00010000:
case 0x00020000:
- return CC_CLOBBER;
+ return OLD_CC_CLOBBER;
case 0xffff0000:
case 0xfffe0000:
- return CC_CLOBBER;
+ return OLD_CC_CLOBBER;
}
/* See if we can finish with 4 bytes. */
if ((intval & 0xffff) == 0)
- return CC_CLOBBER;
+ return OLD_CC_CLOBBER;
}
- return CC_SET_ZN;
+ return OLD_CC_SET_ZN;
}
/* Output a logical insn. */
@@ -3122,7 +3141,7 @@ compute_logical_op_length (machine_mode mode, rtx *operands)
/* Compute which flag bits are valid after a logical insn. */
-enum attr_cc
+int
compute_logical_op_cc (machine_mode mode, rtx *operands)
{
/* Figure out the logical op that we need to perform. */
@@ -3147,7 +3166,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
int lower_half_easy_p = 0;
int upper_half_easy_p = 0;
/* Condition code. */
- enum attr_cc cc = CC_CLOBBER;
+ enum attr_old_cc cc = OLD_CC_CLOBBER;
switch (mode)
{
@@ -3155,7 +3174,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
/* First, see if we can finish with one insn. */
if (b0 != 0 && b1 != 0)
{
- cc = CC_SET_ZNV;
+ cc = OLD_CC_SET_ZNV;
}
break;
case E_SImode:
@@ -3177,7 +3196,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
&& !(code == IOR && w1 == 0xffff
&& (w0 & 0x8000) != 0 && lower_half_easy_p))
{
- cc = CC_SET_ZNV;
+ cc = OLD_CC_SET_ZNV;
}
else
{
@@ -3185,7 +3204,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
&& w1 == 0xffff
&& (w0 & 0x8000) != 0)
{
- cc = CC_SET_ZNV;
+ cc = OLD_CC_SET_ZNV;
}
}
break;
@@ -3195,6 +3214,7 @@ compute_logical_op_cc (machine_mode mode, rtx *operands)
return cc;
}
+#if 0
/* Expand a conditional branch. */
void
@@ -3234,6 +3254,7 @@ h8300_expand_store (rtx operands[])
tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx);
emit_insn (gen_rtx_SET (dest, tmp));
}
+#endif
/* Shifts.
@@ -3381,19 +3402,25 @@ expand_a_shift (machine_mode mode, enum rtx_code code, rtx operands[])
break;
}
- emit_move_insn (copy_rtx (operands[0]), operands[1]);
-
/* Need a loop to get all the bits we want - we generate the
code at emit time, but need to allocate a scratch reg now. */
-
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (copy_rtx (operands[0]),
- gen_rtx_fmt_ee (code, mode,
- copy_rtx (operands[0]), operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (QImode)))));
+ emit_move_insn (copy_rtx (operands[0]), operands[1]);
+ if (operands[2] == CONST0_RTX (QImode))
+ ;
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), mode, code))
+ emit_insn (gen_rtx_SET (copy_rtx (operands[0]),
+ gen_rtx_fmt_ee (code, mode,
+ copy_rtx (operands[1]), operands[2])));
+ else
+ emit_insn (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (copy_rtx (operands[0]),
+ gen_rtx_fmt_ee (code, mode,
+ copy_rtx (operands[0]), operands[2])),
+ gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_SCRATCH (QImode)))));
return true;
}
@@ -3405,13 +3432,13 @@ enum shift_mode
};
/* For single bit shift insns, record assembler and what bits of the
- condition code are valid afterwards (represented as various CC_FOO
+ condition code are valid afterwards (represented as various OLD_CC_FOO
bits, 0 means CC isn't left in a usable state). */
struct shift_insn
{
const char *const assembler;
- const enum attr_cc cc_valid;
+ const enum attr_old_cc cc_valid;
};
/* Assembler instruction shift table.
@@ -3425,42 +3452,42 @@ static const struct shift_insn shift_one[2][3][3] =
{
/* SHIFT_ASHIFT */
{
- { "shll\t%X0", CC_SET_ZNV },
- { "add.w\t%T0,%T0", CC_SET_ZN },
- { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", CC_CLOBBER }
+ { "shll\t%X0", OLD_CC_SET_ZNV },
+ { "add.w\t%T0,%T0", OLD_CC_SET_ZN },
+ { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", OLD_CC_CLOBBER }
},
/* SHIFT_LSHIFTRT */
{
- { "shlr\t%X0", CC_SET_ZNV },
- { "shlr\t%t0\n\trotxr\t%s0", CC_CLOBBER },
- { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", CC_CLOBBER }
+ { "shlr\t%X0", OLD_CC_SET_ZNV },
+ { "shlr\t%t0\n\trotxr\t%s0", OLD_CC_CLOBBER },
+ { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", OLD_CC_CLOBBER }
},
/* SHIFT_ASHIFTRT */
{
- { "shar\t%X0", CC_SET_ZNV },
- { "shar\t%t0\n\trotxr\t%s0", CC_CLOBBER },
- { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", CC_CLOBBER }
+ { "shar\t%X0", OLD_CC_SET_ZNV },
+ { "shar\t%t0\n\trotxr\t%s0", OLD_CC_CLOBBER },
+ { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", OLD_CC_CLOBBER }
}
},
/* H8/300H */
{
/* SHIFT_ASHIFT */
{
- { "shll.b\t%X0", CC_SET_ZNV },
- { "shll.w\t%T0", CC_SET_ZNV },
- { "shll.l\t%S0", CC_SET_ZNV }
+ { "shll.b\t%X0", OLD_CC_SET_ZNV },
+ { "shll.w\t%T0", OLD_CC_SET_ZNV },
+ { "shll.l\t%S0", OLD_CC_SET_ZNV }
},
/* SHIFT_LSHIFTRT */
{
- { "shlr.b\t%X0", CC_SET_ZNV },
- { "shlr.w\t%T0", CC_SET_ZNV },
- { "shlr.l\t%S0", CC_SET_ZNV }
+ { "shlr.b\t%X0", OLD_CC_SET_ZNV },
+ { "shlr.w\t%T0", OLD_CC_SET_ZNV },
+ { "shlr.l\t%S0", OLD_CC_SET_ZNV }
},
/* SHIFT_ASHIFTRT */
{
- { "shar.b\t%X0", CC_SET_ZNV },
- { "shar.w\t%T0", CC_SET_ZNV },
- { "shar.l\t%S0", CC_SET_ZNV }
+ { "shar.b\t%X0", OLD_CC_SET_ZNV },
+ { "shar.w\t%T0", OLD_CC_SET_ZNV },
+ { "shar.l\t%S0", OLD_CC_SET_ZNV }
}
}
};
@@ -3469,21 +3496,21 @@ static const struct shift_insn shift_two[3][3] =
{
/* SHIFT_ASHIFT */
{
- { "shll.b\t#2,%X0", CC_SET_ZNV },
- { "shll.w\t#2,%T0", CC_SET_ZNV },
- { "shll.l\t#2,%S0", CC_SET_ZNV }
+ { "shll.b\t#2,%X0", OLD_CC_SET_ZNV },
+ { "shll.w\t#2,%T0", OLD_CC_SET_ZNV },
+ { "shll.l\t#2,%S0", OLD_CC_SET_ZNV }
},
/* SHIFT_LSHIFTRT */
{
- { "shlr.b\t#2,%X0", CC_SET_ZNV },
- { "shlr.w\t#2,%T0", CC_SET_ZNV },
- { "shlr.l\t#2,%S0", CC_SET_ZNV }
+ { "shlr.b\t#2,%X0", OLD_CC_SET_ZNV },
+ { "shlr.w\t#2,%T0", OLD_CC_SET_ZNV },
+ { "shlr.l\t#2,%S0", OLD_CC_SET_ZNV }
},
/* SHIFT_ASHIFTRT */
{
- { "shar.b\t#2,%X0", CC_SET_ZNV },
- { "shar.w\t#2,%T0", CC_SET_ZNV },
- { "shar.l\t#2,%S0", CC_SET_ZNV }
+ { "shar.b\t#2,%X0", OLD_CC_SET_ZNV },
+ { "shar.w\t#2,%T0", OLD_CC_SET_ZNV },
+ { "shar.l\t#2,%S0", OLD_CC_SET_ZNV }
}
};
@@ -3579,10 +3606,10 @@ struct shift_info {
const char *shift2;
/* CC status for SHIFT_INLINE. */
- enum attr_cc cc_inline;
+ enum attr_old_cc cc_inline;
/* CC status for SHIFT_SPECIAL. */
- enum attr_cc cc_special;
+ enum attr_old_cc cc_special;
};
static void get_shift_alg (enum shift_type,
@@ -3651,7 +3678,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
case SHIFT_ROT_AND:
info->shift1 = rotate_one[cpu_type][shift_type][shift_mode];
info->shift2 = rotate_two[shift_type][shift_mode];
- info->cc_inline = CC_CLOBBER;
+ info->cc_inline = OLD_CC_CLOBBER;
goto end;
case SHIFT_SPECIAL:
@@ -3660,7 +3687,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
info->shift2 = shift_two[shift_type][shift_mode].assembler;
info->cc_inline = shift_one[cpu_type][shift_type][shift_mode].cc_valid;
- info->cc_special = CC_CLOBBER;
+ info->cc_special = OLD_CC_CLOBBER;
break;
}
@@ -3702,11 +3729,11 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
goto end;
case SHIFT_LSHIFTRT:
info->special = "mov.b\t%t0,%s0\n\textu.w\t%T0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_ASHIFTRT:
info->special = "mov.b\t%t0,%s0\n\texts.w\t%T0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
}
}
@@ -3722,7 +3749,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
if (TARGET_H8300H)
{
info->special = "shll.b\t%t0\n\tsubx.b\t%s0,%s0\n\tshll.b\t%t0\n\trotxl.b\t%s0\n\texts.w\t%T0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
}
else /* TARGET_H8300S */
gcc_unreachable ();
@@ -3768,11 +3795,11 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
{
case SHIFT_ASHIFT:
info->special = "shlr.w\t%e0\n\tmov.w\t%f0,%e0\n\txor.w\t%f0,%f0\n\trotxr.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_LSHIFTRT:
info->special = "shll.w\t%f0\n\tmov.w\t%e0,%f0\n\txor.w\t%e0,%e0\n\trotxl.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_ASHIFTRT:
gcc_unreachable ();
@@ -3790,11 +3817,11 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
goto end;
case SHIFT_LSHIFTRT:
info->special = "mov.w\t%e0,%f0\n\textu.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_ASHIFTRT:
info->special = "mov.w\t%e0,%f0\n\texts.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
}
}
@@ -3810,11 +3837,11 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
goto end;
case SHIFT_LSHIFTRT:
info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\textu.w\t%f0\n\textu.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_ASHIFTRT:
info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\texts.w\t%f0\n\texts.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
}
}
@@ -3832,7 +3859,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
if (TARGET_H8300H)
{
info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
}
else
info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\trotl.l\t#2,%S0\n\textu.l\t%S0";
@@ -3855,12 +3882,12 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
if (TARGET_H8300H)
{
info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
}
else
{
info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
}
goto end;
case SHIFT_ASHIFTRT:
@@ -3893,15 +3920,15 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
{
case SHIFT_ASHIFT:
info->special = "shlr.l\t%S0\n\txor.l\t%S0,%S0\n\trotxr.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_LSHIFTRT:
info->special = "shll.l\t%S0\n\txor.l\t%S0,%S0\n\trotxl.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
case SHIFT_ASHIFTRT:
info->special = "shll\t%e0\n\tsubx\t%w0,%w0\n\texts.w\t%T0\n\texts.l\t%S0";
- info->cc_special = CC_SET_ZNV;
+ info->cc_special = OLD_CC_SET_ZNV;
goto end;
}
}
@@ -3920,7 +3947,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
needed for some shift with COUNT and MODE. Return 0 otherwise. */
int
-h8300_shift_needs_scratch_p (int count, machine_mode mode)
+h8300_shift_needs_scratch_p (int count, machine_mode mode, enum rtx_code type)
{
enum h8_cpu cpu;
int a, lr, ar;
@@ -3960,8 +3987,18 @@ h8300_shift_needs_scratch_p (int count, machine_mode mode)
}
/* On H8/300H, count == 8 uses a scratch register. */
- return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
- || (TARGET_H8300H && mode == SImode && count == 8));
+ if (type == CLOBBER)
+ return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
+ else if (type == ASHIFT)
+ return (a == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
+ else if (type == LSHIFTRT)
+ return (lr == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
+ else if (type == ASHIFTRT)
+ return (ar == SHIFT_LOOP
+ || (TARGET_H8300H && mode == SImode && count == 8));
}
/* Output the assembler code for doing shifts. */
@@ -4283,7 +4320,7 @@ compute_a_shift_length (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
/* Compute which flag bits are valid after a shift insn. */
-enum attr_cc
+int
compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
{
rtx shift = operands[3];
@@ -4354,7 +4391,7 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
case SHIFT_ROT_AND:
/* This case always ends with an and instruction. */
- return CC_SET_ZNV;
+ return OLD_CC_SET_ZNV;
case SHIFT_LOOP:
/* A loop to shift by a "large" constant value.
@@ -4364,7 +4401,7 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
if (n % 2)
return info.cc_inline;
}
- return CC_CLOBBER;
+ return OLD_CC_CLOBBER;
default:
gcc_unreachable ();
@@ -5517,4 +5554,7 @@ h8300_push_rounding (poly_int64 bytes)
#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+#undef TARGET_FLAGS_REGNUM
+#define TARGET_FLAGS_REGNUM 12
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h
index bf20ce2..99d85ff 100644
--- a/gcc/config/h8300/h8300.h
+++ b/gcc/config/h8300/h8300.h
@@ -195,14 +195,14 @@ extern const char * const *h8_reg_names;
eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 12
+#define FIRST_PSEUDO_REGISTER 13
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
#define FIXED_REGISTERS \
-/* r0 r1 r2 r3 r4 r5 r6 r7 mac ap rap fp */ \
- { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 }
+/* r0 r1 r2 r3 r4 r5 r6 r7 mac ap rap fp cc */ \
+ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1 }
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -216,11 +216,11 @@ extern const char * const *h8_reg_names;
#define CALL_USED_REGISTERS \
/* r0 r1 r2 r3 r4 r5 r6 r7 mac ap rap fp */ \
- { 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1 }
+ { 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }
#define REG_ALLOC_ORDER \
/* r0 r1 r2 r3 r4 r5 r6 r7 mac ap rap fp */ \
- { 2, 3, 0, 1, 4, 5, 6, 8, 7, 9, 10, 11 }
+ { 2, 3, 0, 1, 4, 5, 6, 8, 7, 9, 10, 11, 12 }
/* A C expression that is nonzero if hard register NEW_REG can be
considered for use as a rename register for OLD_REG register */
@@ -521,6 +521,8 @@ struct cum_arg
#define MOVE_MAX 4
#define MAX_MOVE_MAX 4
+#define SELECT_CC_MODE(OP, X, Y) h8300_select_cc_mode (OP, X, Y)
+
/* Nonzero if access to memory by bytes is slow and undesirable. */
#define SLOW_BYTE_ACCESS TARGET_SLOWBYTE
@@ -633,7 +635,7 @@ struct cum_arg
This sequence is indexed by compiler's hard-register-number (see above). */
#define REGISTER_NAMES \
-{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "mac", "ap", "rap", "fp" }
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "mac", "ap", "rap", "fp", "cc" }
#define ADDITIONAL_REGISTER_NAMES \
{ {"er0", 0}, {"er1", 1}, {"er2", 2}, {"er3", 3}, {"er4", 4}, \
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 46ab244..932f74e 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -65,7 +65,8 @@
(MAC_REG 8)
(AP_REG 9)
(RAP_REG 10)
- (FP_REG 11)])
+ (FP_REG 11)
+ (CC_REG 12)])
;; ----------------------------------------------------------------------
;; ATTRIBUTES
@@ -130,9 +131,42 @@
;; compare - compare instruction
;; clobber - value of cc is unknown
-(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber"
+(define_attr "old_cc" "none,none_0hit,set_znv,set_zn,compare,clobber"
(const_string "clobber"))
+;; So the idea here is to define iterators and substitutions so that we
+;; can easily modify the patterns with CC clobbers into a pattern
+;; which sets appropriate condition codes
+
+;; The modes we're supporting. This is used when we want to generate
+;; multiple patterns where only the mode differs from a single template
+(define_mode_iterator H8cc [CC CCZN])
+
+;; This is used to generate multiple define_substs from a single
+;; template for the different variants we might have.
+(define_mode_attr cc [(CC "cc") (CCZN "cczn")])
+
+;; The primary substitution pattern. <cc> is used to create multiple
+;; substitutions based on the CC bits that are set.
+;;
+;; The mode iterator sets the actual mode on the condition code
+;; REG expression.
+(define_subst "subst_<cc>"
+ [(set (match_operand 0 "")
+ (match_operand 1 ""))
+ (clobber (reg:CC CC_REG))]
+ ""
+ [(set (reg:H8cc CC_REG)
+ (compare:H8cc (match_dup 1) (const_int 0)))
+ (set (match_dup 0) (match_dup 1))])
+
+
+;; So when we see <cc> or <cczn> in a define_insn pattern, we'll
+;; apply the subst_cczn or subset_cc define_subst to generate a
+;; new pattern that compare-elim can use
+(define_subst_attr "cczn" "subst_cczn" "" "_cczn")
+(define_subst_attr "cc" "subst_cc" "" "_cc")
+
;; Type of delay slot. NONE means the instruction has no delay slot.
;; JUMP means it is an unconditional jump that (if short enough)
;; could be implemented using bra/s.
@@ -211,4 +245,4 @@
(include "shiftrotate.md")
(include "bitfield.md")
(include "combiner.md")
-(include "peepholes.md")
+;;(include "peepholes.md")
diff --git a/gcc/config/h8300/jumpcall.md b/gcc/config/h8300/jumpcall.md
index 3917cf1..49d1e43 100644
--- a/gcc/config/h8300/jumpcall.md
+++ b/gcc/config/h8300/jumpcall.md
@@ -4,78 +4,67 @@
;; Conditional jump instructions
-(define_expand "cbranchqi4"
- [(use (match_operator 0 "ordered_comparison_operator"
- [(match_operand:QI 1 "h8300_dst_operand" "")
- (match_operand:QI 2 "h8300_src_operand" "")]))
- (use (match_operand 3 ""))]
- ""
- {
- h8300_expand_branch (operands);
- DONE;
- })
-
-(define_expand "cbranchhi4"
- [(use (match_operator 0 "ordered_comparison_operator"
- [(match_operand:HI 1 "h8300_dst_operand" "")
- (match_operand:HI 2 "h8300_src_operand" "")]))
- (use (match_operand 3 ""))]
- ""
- {
- h8300_expand_branch (operands);
- DONE;
- })
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:QHSI 1 "h8300_dst_operand")
+ (match_operand:QHSI 2 "h8300_src_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "")
-(define_expand "cbranchsi4"
- [(use (match_operator 0 "ordered_comparison_operator"
- [(match_operand:SI 1 "h8300_dst_operand" "")
- (match_operand:SI 2 "h8300_src_operand" "")]))
- (use (match_operand 3 ""))]
+(define_insn_and_split "*branch"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:QHSI 1 "h8300_dst_operand" "rQ")
+ (match_operand:QHSI 2 "h8300_src_operand" "rQi")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
- {
- h8300_expand_branch (operands);
- DONE;
- })
+ "#"
+ "reload_completed"
+ [(set (reg:H8cc CC_REG)
+ (compare:H8cc (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (match_op_dup 0
+ [(reg:H8cc CC_REG) (const_int 0)])
+ (label_ref (match_dup 3)) (pc)))]
+ "")
-(define_insn "branch"
+(define_insn "*branch_1"
[(set (pc)
- (if_then_else (match_operator 2 "comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
- "operands[0] == pc_rtx || operands[1] == pc_rtx"
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(reg:H8cc CC_REG) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "reload_completed"
{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
- && (GET_CODE (operands[2]) == GT
- || GET_CODE (operands[2]) == GE
- || GET_CODE (operands[2]) == LE
- || GET_CODE (operands[2]) == LT))
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
+ if (get_attr_length (insn) == 2)
+ return "b%j1 %l0";
+ else if (get_attr_length (insn) == 4)
+ return "b%j1 %l0:16";
+ else
+ return "b%k1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:";
+}
+ [(set_attr "type" "branch")])
- if (operands[0] != pc_rtx)
- {
- if (get_attr_length (insn) == 2)
- return "b%j2 %l0";
- else if (get_attr_length (insn) == 4)
- return "b%j2 %l0:16";
- else
- return "b%k2 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:";
- }
+
+(define_insn "*branch_1_false"
+ [(set (pc)
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(reg:H8cc CC_REG) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ "reload_completed"
+{
+ if (get_attr_length (insn) == 2)
+ return "b%k1 %l0";
+ else if (get_attr_length (insn) == 4)
+ return "b%k1 %l0:16";
else
- {
- if (get_attr_length (insn) == 2)
- return "b%k2 %l1";
- else if (get_attr_length (insn) == 4)
- return "b%k2 %l1:16";
- else
- return "b%j2 .Lh8BR%=\;jmp @%l1\\n.Lh8BR%=:";
- }
+ return "b%j1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:";
}
- [(set_attr "type" "branch")
- (set_attr "cc" "none")])
+ [(set_attr "type" "branch")])
;; The brabc/brabs patterns have been disabled because their length computation
;; is horribly broken. When we call out to a function via a SYMBOL_REF we get
@@ -109,8 +98,7 @@
}
}
[(set_attr "type" "bitbranch")
- (set_attr "length_table" "bitbranch")
- (set_attr "cc" "none")])
+ (set_attr "length_table" "bitbranch")])
(define_insn "*brabs"
[(set (pc)
@@ -134,8 +122,7 @@
}
}
[(set_attr "type" "bitbranch")
- (set_attr "length_table" "bitbranch")
- (set_attr "cc" "none")])
+ (set_attr "length_table" "bitbranch")])
;; Unconditional and other jump instructions.
@@ -179,8 +166,7 @@
(set (attr "delay_slot")
(if_then_else (match_test "TARGET_H8300SX")
(const_string "jump")
- (const_string "none")))
- (set_attr "cc" "none")])
+ (const_string "none")))])
;; This is a define expand, because pointers may be either 16 or 32 bits.
@@ -201,8 +187,7 @@
return "jmp @%S0";
abort ();
}
- [(set_attr "cc" "none")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
;; This is a define expand, because pointers may be either 16 or 32 bits.
@@ -221,8 +206,7 @@
return "jmp @%S0";
abort ();
}
- [(set_attr "cc" "none")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
;; Call subroutine with no return value.
diff --git a/gcc/config/h8300/logical.md b/gcc/config/h8300/logical.md
index 7d24fad..eb99c20 100644
--- a/gcc/config/h8300/logical.md
+++ b/gcc/config/h8300/logical.md
@@ -24,30 +24,59 @@
operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8);
})
-(define_insn "*andqi3_2"
+(define_insn "bclrhi_msx"
+ [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m")
+ (and:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+ (match_operand:HI 2 "single_zero_operand" "Y0")))]
+ "TARGET_H8300SX"
+ "bclr\\t%W2,%0"
+ [(set_attr "length" "8")])
+
+(define_insn_and_split "*andqi3_2"
[(set (match_operand:QI 0 "bit_operand" "=U,rQ,r")
(and:QI (match_operand:QI 1 "bit_operand" "%0,0,WU")
(match_operand:QI 2 "h8300_src_operand" "Y0,rQi,IP1>X")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (and:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*andqi3_2_clobber_flags"
+ [(set (match_operand:QI 0 "bit_operand" "=U,rQ,r")
+ (and:QI (match_operand:QI 1 "bit_operand" "%0,0,WU")
+ (match_operand:QI 2 "h8300_src_operand" "Y0,rQi,IP1>X")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"@
bclr\\t %W2,%R0
and %X2,%X0
bfld %2,%1,%R0"
[(set_attr "length" "8,*,8")
- (set_attr "length_table" "*,logicb,*")
- (set_attr "cc" "none_0hit,set_znv,none_0hit")])
+ (set_attr "length_table" "*,logicb,*")])
-(define_insn "andqi3_1"
+(define_insn_and_split "andqi3_1"
[(set (match_operand:QI 0 "bit_operand" "=U,r")
(and:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "h8300_src_operand" "Y0,rn")))]
"register_operand (operands[0], QImode)
|| single_zero_operand (operands[2], QImode)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (and:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "andqi3_1_clobber_flags"
+ [(set (match_operand:QI 0 "bit_operand" "=U,r")
+ (and:QI (match_operand:QI 1 "bit_operand" "%0,0")
+ (match_operand:QI 2 "h8300_src_operand" "Y0,rn")))
+ (clobber (reg:CC CC_REG))]
+ "register_operand (operands[0], QImode)
+ || single_zero_operand (operands[2], QImode)"
"@
bclr %W2,%R0
and %X2,%X0"
- [(set_attr "length" "2,8")
- (set_attr "cc" "none_0hit,set_znv")])
+ [(set_attr "length" "2,8")])
(define_expand "and<mode>3"
[(set (match_operand:QHSI 0 "register_operand" "")
@@ -56,7 +85,7 @@
""
"")
-(define_insn "*andor<mode>3"
+(define_insn_and_split "*andor<mode>3"
[(set (match_operand:QHSI 0 "register_operand" "=r")
(ior:QHSI (and:QHSI (match_operand:QHSI 2 "register_operand" "r")
(match_operand:QHSI 3 "single_one_operand" "n"))
@@ -65,6 +94,23 @@
|| <MODE>mode == HImode
|| (<MODE>mode == SImode
&& (INTVAL (operands[3]) & 0xffff) != 0))"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (ior:QHSI (and:QHSI (match_dup 2)
+ (match_dup 3))
+ (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*andor<mode>3_clobber_flags"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (ior:QHSI (and:QHSI (match_operand:QHSI 2 "register_operand" "r")
+ (match_operand:QHSI 3 "single_one_operand" "n"))
+ (match_operand:QHSI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ "(<MODE>mode == QImode
+ || <MODE>mode == HImode
+ || (<MODE>mode == SImode
+ && (INTVAL (operands[3]) & 0xffff) != 0))"
{
if (<MODE>mode == QImode)
return "bld\\t%V3,%X2\;bor\\t%V3,%X0\;bst\\t%V3,%X0";
@@ -96,13 +142,29 @@
}
[(set_attr "length" "6")])
-(define_insn "*andorsi3_shift_8"
+(define_insn_and_split "*andorsi3_shift_8"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r")
(const_int 8))
(const_int 65280))
(match_operand:SI 1 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (ior:SI (and:SI (ashift:SI (match_dup 2)
+ (const_int 8))
+ (const_int 65280))
+ (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*andorsi3_shift_8_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 8))
+ (const_int 65280))
+ (match_operand:SI 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"or.b\\t%w2,%x0"
[(set_attr "length" "2")])
@@ -118,36 +180,41 @@
{ return <CODE> == IOR ? "bset\\t%V2,%0" : "bnot\\t%V2,%0"; }
[(set_attr "length" "8")])
-(define_split
- [(set (match_operand:HI 0 "bit_register_indirect_operand")
- (ors:HI (match_operand:HI 1 "bit_register_indirect_operand")
- (match_operand:HI 2 "single_one_operand")))]
- "TARGET_H8300SX && abs (INTVAL (operands[2])) > 0xff"
- [(set (match_dup 0)
- (and:QI (match_dup 1)
- (match_dup 2)))]
- {
- operands[0] = adjust_address (operands[0], QImode, 0);
- operands[1] = adjust_address (operands[1], QImode, 0);
- operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8);
- })
+(define_insn "b<code>hi_msx"
+ [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m")
+ (ors:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0")
+ (match_operand:HI 2 "single_one_operand" "Y2")))]
+ "TARGET_H8300SX"
+ { return <CODE> == IOR ? "bset\\t%V2,%0" : "bnot\\t%V2,%0"; }
+ [(set_attr "length" "8")])
-(define_insn "<code>qi3_1"
+(define_insn_and_split "<code>qi3_1"
[(set (match_operand:QI 0 "bit_operand" "=U,rQ")
(ors:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "h8300_src_operand" "Y2,rQi")))]
"TARGET_H8300SX || register_operand (operands[0], QImode)
|| single_one_operand (operands[2], QImode)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (ors:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "<code>qi3_1_clobber_flags"
+ [(set (match_operand:QI 0 "bit_operand" "=U,rQ")
+ (ors:QI (match_operand:QI 1 "bit_operand" "%0,0")
+ (match_operand:QI 2 "h8300_src_operand" "Y2,rQi")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX || register_operand (operands[0], QImode)
+ || single_one_operand (operands[2], QImode)"
{
if (which_alternative == 0)
- return <CODE> == IOR ? "bset\\t%V2,%R0" : "bnot\\t%V2,%R0";
+ return <CODE> == IOR ? "bset\\t%V2,%R0" : "bnot\\t%V2,%R0";
else if (which_alternative == 1)
return <CODE> == IOR ? "or\\t%X2,%X0" : "xor\\t%X2,%X0";
gcc_unreachable ();
}
[(set_attr "length" "8,*")
- (set_attr "length_table" "*,logicb")
- (set_attr "cc" "none_0hit,set_znv")])
+ (set_attr "length_table" "*,logicb")])
(define_expand "<code><mode>3"
[(set (match_operand:QHSI 0 "register_operand" "")
@@ -160,27 +227,48 @@
;; {AND,IOR,XOR}{HI3,SI3} PATTERNS
;; ----------------------------------------------------------------------
-(define_insn "*logical<mode>3"
+(define_insn_and_split "*logical<mode>3"
[(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ")
(match_operator:HSI 3 "bit_operator"
[(match_operand:HSI 1 "h8300_dst_operand" "%0")
(match_operand:HSI 2 "h8300_src_operand" "rQi")]))]
"h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*logical<mode>3_clobber_flags"
+ [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ")
+ (match_operator:HSI 3 "bit_operator"
+ [(match_operand:HSI 1 "h8300_dst_operand" "%0")
+ (match_operand:HSI 2 "h8300_src_operand" "rQi")]))
+ (clobber (reg:CC CC_REG))]
+ "h8300_operands_match_p (operands)"
{ return output_logical_op (<MODE>mode, operands); }
[(set (attr "length")
- (symbol_ref "compute_logical_op_length (<MODE>mode, operands)"))
- (set (attr "cc")
- (symbol_ref "compute_logical_op_cc (<MODE>mode, operands)"))])
+ (symbol_ref "compute_logical_op_length (<MODE>mode, operands)"))])
;; ----------------------------------------------------------------------
;; NOT INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "one_cmpl<mode>2"
+(define_insn_and_split "one_cmpl<mode>2"
[(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
(not:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (not:QHSI (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "one_cmpl<mode>2_clobber_flags"
+ [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
+ (not:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
{
if (<MODE>mode == E_QImode)
return "not %X0";
@@ -190,5 +278,93 @@
return "not.l %S0";
gcc_unreachable ();
}
- [(set_attr "length_table" "unary")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length_table" "unary")])
+
+;; The next four peephole2's will try to transform
+;;
+;; mov.b A,r0l (or mov.l A,er0)
+;; and.l #CST,er0
+;;
+;; into
+;;
+;; sub.l er0
+;; mov.b A,r0l
+;; and.b #CST,r0l (if CST is not 255)
+
+(define_peephole2
+ [(parallel [(set (match_operand:QI 0 "register_operand" "")
+ (match_operand:QI 1 "general_operand" ""))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_operand:SI 2 "register_operand" "")
+ (and:SI (match_dup 2) (const_int 255)))
+ (clobber (reg:CC CC_REG))])]
+ "!reg_overlap_mentioned_p (operands[2], operands[1])
+ && REGNO (operands[0]) == REGNO (operands[2])"
+ [(parallel [(set (match_dup 2) (const_int 0))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_peephole2
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "nonimmediate_operand" ""))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0)
+ (and:SI (match_dup 0) (const_int 255)))
+ (clobber (reg:CC CC_REG))])]
+ "!reg_overlap_mentioned_p (operands[0], operands[1])
+ && !(GET_CODE (operands[1]) == MEM && !offsettable_memref_p (operands[1]))
+ && !(GET_CODE (operands[1]) == MEM && MEM_VOLATILE_P (operands[1]))"
+ [(parallel [(set (match_dup 0) (const_int 0))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (strict_low_part (match_dup 2)) (match_dup 3))
+ (clobber (reg:CC CC_REG))])]
+ {
+ operands[2] = gen_lowpart (QImode, operands[0]);
+ operands[3] = gen_lowpart (QImode, operands[1]);
+ })
+
+(define_peephole2
+ [(parallel [(set (match_operand 0 "register_operand" "")
+ (match_operand 1 "nonimmediate_operand" ""))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_operand:SI 2 "register_operand" "")
+ (and:SI (match_dup 2)
+ (match_operand:SI 3 "const_int_qi_operand" "")))
+ (clobber (reg:CC CC_REG))])]
+ "(GET_MODE (operands[0]) == QImode
+ || GET_MODE (operands[0]) == HImode
+ || GET_MODE (operands[0]) == SImode)
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[2])
+ && !reg_overlap_mentioned_p (operands[2], operands[1])
+ && !(GET_MODE (operands[1]) != QImode
+ && GET_CODE (operands[1]) == MEM
+ && !offsettable_memref_p (operands[1]))
+ && !(GET_MODE (operands[1]) != QImode
+ && GET_CODE (operands[1]) == MEM
+ && MEM_VOLATILE_P (operands[1]))"
+ [(parallel [(set (match_dup 2) (const_int 0))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (strict_low_part (match_dup 4)) (match_dup 5))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 2) (and:SI (match_dup 2) (match_dup 6)))
+ (clobber (reg:CC CC_REG))])]
+ {
+ operands[4] = gen_lowpart (QImode, operands[0]);
+ operands[5] = gen_lowpart (QImode, operands[1]);
+ operands[6] = GEN_INT (~0xff | INTVAL (operands[3]));
+ })
+
+(define_peephole2
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65280)))
+ (clobber (reg:CC CC_REG))])]
+ "!reg_overlap_mentioned_p (operands[0], operands[1])"
+ [(parallel [(set (match_dup 0) (const_int 0))
+ (clobber (reg:CC CC_REG))])
+ (parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (lshiftrt:SI (match_dup 1) (const_int 8)))
+ (clobber (reg:CC CC_REG))])])
diff --git a/gcc/config/h8300/mova.md b/gcc/config/h8300/mova.md
index 926edbb..cdcd4b8 100644
--- a/gcc/config/h8300/mova.md
+++ b/gcc/config/h8300/mova.md
@@ -24,8 +24,7 @@
(match_operand:QI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
@@ -34,8 +33,7 @@
(match_operand:QI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
@@ -44,8 +42,7 @@
(match_operand:QI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
@@ -54,8 +51,7 @@
(match_operand:QI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -63,8 +59,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/b.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -72,8 +67,7 @@
(const_int 2)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -82,8 +76,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -92,8 +85,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -103,8 +95,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -113,8 +104,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -124,8 +114,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -133,8 +122,7 @@
(const_int 1)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -143,8 +131,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -153,8 +140,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -164,8 +150,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -174,8 +159,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -185,8 +169,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -194,8 +177,7 @@
(const_int 4)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -204,8 +186,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -214,8 +195,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -225,8 +205,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -235,8 +214,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -246,8 +224,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -255,8 +232,7 @@
(const_int 2)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -265,8 +241,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -275,8 +250,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -286,8 +260,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -296,8 +269,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -307,8 +279,7 @@
(match_operand:HI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -316,8 +287,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/b.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -325,8 +295,7 @@
(const_int 2)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -335,8 +304,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -345,8 +313,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -356,8 +323,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -366,8 +332,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -377,8 +342,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -386,8 +350,7 @@
(const_int 1)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -396,8 +359,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -406,8 +368,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -417,8 +378,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -427,8 +387,7 @@
(const_int 510)))]
"TARGET_H8300SX"
"mova/w.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -438,8 +397,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -447,8 +405,7 @@
(const_int 4)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -457,8 +414,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -467,8 +423,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -478,8 +433,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -488,8 +442,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -499,8 +452,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -508,8 +460,7 @@
(const_int 2)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -518,8 +469,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -528,8 +478,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -539,8 +488,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -549,8 +497,7 @@
(const_int 1020)))]
"TARGET_H8300SX"
"mova/l.l @(0,%X1.b),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -560,8 +507,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%X1.b),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -570,8 +516,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -580,8 +525,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -590,8 +534,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -600,8 +543,7 @@
(match_operand:HI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -609,8 +551,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/b.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -618,8 +559,7 @@
(const_int 2)))]
"TARGET_H8300SX"
"mova/w.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -628,8 +568,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -638,8 +577,7 @@
(const_int 131070)))]
"TARGET_H8300SX"
"mova/w.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -649,8 +587,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -659,8 +596,7 @@
(const_int 131070)))]
"TARGET_H8300SX"
"mova/w.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -670,8 +606,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -679,8 +614,7 @@
(const_int 1)))]
"TARGET_H8300SX"
"mova/w.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -689,8 +623,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -699,8 +632,7 @@
(const_int 131070)))]
"TARGET_H8300SX"
"mova/w.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -710,8 +642,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -720,8 +651,7 @@
(const_int 131070)))]
"TARGET_H8300SX"
"mova/w.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -731,8 +661,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/w.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -740,8 +669,7 @@
(const_int 4)))]
"TARGET_H8300SX"
"mova/l.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -750,8 +678,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -760,8 +687,7 @@
(const_int 262140)))]
"TARGET_H8300SX"
"mova/l.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -771,8 +697,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -781,8 +706,7 @@
(const_int 262140)))]
"TARGET_H8300SX"
"mova/l.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -792,8 +716,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -801,8 +724,7 @@
(const_int 2)))]
"TARGET_H8300SX"
"mova/l.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -811,8 +733,7 @@
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -821,8 +742,7 @@
(const_int 262140)))]
"TARGET_H8300SX"
"mova/l.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -832,8 +752,7 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -842,8 +761,7 @@
(const_int 262140)))]
"TARGET_H8300SX"
"mova/l.l @(0,%T1.w),%S0"
- [(set_attr "length_table" "mova_zero")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova_zero")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -853,6 +771,5 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/l.l @(%o2%C2,%T1.w),%S0"
- [(set_attr "length_table" "mova")
- (set_attr "cc" "none")])
+ [(set_attr "length_table" "mova")])
diff --git a/gcc/config/h8300/movepush.md b/gcc/config/h8300/movepush.md
index a8241b9..b106cd5 100644
--- a/gcc/config/h8300/movepush.md
+++ b/gcc/config/h8300/movepush.md
@@ -4,11 +4,20 @@
;; movqi
-(define_insn "*movqi_h8nosx"
+(define_insn_and_split "*movqi"
[(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m")
(match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
- "!TARGET_H8300SX
- && h8300_move_ok (operands[0], operands[1])"
+ "!TARGET_H8300SX && h8300_move_ok (operands[0], operands[1])"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movqi_clobber_flags"
+ [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m")
+ (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))
+ (clobber (reg:CC CC_REG))]
+ "!TARGET_H8300SX && h8300_move_ok (operands[0], operands[1])"
"@
sub.b %X0,%X0
mov.b %R1,%X0
@@ -16,19 +25,26 @@
mov.b %R1,%X0
mov.b %R1,%X0
mov.b %X1,%R0"
- [(set (attr "length")
- (symbol_ref "compute_mov_length (operands)"))
- (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
+ [(set (attr "length") (symbol_ref "compute_mov_length (operands)"))])
-(define_insn "*movqi_h8sx"
+(define_insn_and_split "*movqi_h8sx"
[(set (match_operand:QI 0 "general_operand_dst" "=Z,rQ")
(match_operand:QI 1 "general_operand_src" "P4>X,rQi"))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movqi_h8sx_clobber_flags"
+ [(set (match_operand:QI 0 "general_operand_dst" "=Z,rQ")
+ (match_operand:QI 1 "general_operand_src" "P4>X,rQi"))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"@
mov.b %X1:4,%X0
mov.b %X1,%X0"
- [(set_attr "length_table" "mov_imm4,movb")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length_table" "mov_imm4,movb")])
(define_expand "mov<mode>"
[(set (match_operand:QHSIF 0 "general_operand_dst" "")
@@ -48,24 +64,45 @@
}
})
-(define_insn "movstrictqi"
+(define_insn_and_split "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r"))
(match_operand:QI 1 "general_operand_src" "I,rmi>"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+
+(define_insn "movstrictqi_clobber_flags"
+ [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r"))
+ (match_operand:QI 1 "general_operand_src" "I,rmi>"))
+ (clobber (reg:CC CC_REG))]
+ ""
"@
sub.b %X0,%X0
mov.b %X1,%X0"
[(set_attr "length" "2,*")
- (set_attr "length_table" "*,movb")
- (set_attr "cc" "set_zn,set_znv")])
+ (set_attr "length_table" "*,movb")])
;; movhi
-(define_insn "*movhi_h8nosx"
+(define_insn_and_split "*movhi"
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
(match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
"!TARGET_H8300SX
&& h8300_move_ok (operands[0], operands[1])"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movhi_clobber_flags"
+ [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
+ (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))
+ (clobber (reg:CC CC_REG))]
+ "!TARGET_H8300SX
+ && h8300_move_ok (operands[0], operands[1])"
"@
sub.w %T0,%T0
mov.w %T1,%T0
@@ -73,14 +110,22 @@
mov.w %T1,%T0
mov.w %T1,%T0
mov.w %T1,%T0"
- [(set (attr "length")
- (symbol_ref "compute_mov_length (operands)"))
- (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
+ [(set (attr "length") (symbol_ref "compute_mov_length (operands)"))])
-(define_insn "*movhi_h8sx"
+(define_insn_and_split "*movhi_h8sx"
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,Z,Q,rQ")
(match_operand:HI 1 "general_operand_src" "I,P3>X,P4>X,IP8>X,rQi"))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movhi_h8sx_clobber_flags"
+ [(set (match_operand:HI 0 "general_operand_dst" "=r,r,Z,Q,rQ")
+ (match_operand:HI 1 "general_operand_src" "I,P3>X,P4>X,IP8>X,rQi"))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"@
sub.w %T0,%T0
mov.w %T1:3,%T0
@@ -88,27 +133,46 @@
mov.w %T1,%T0
mov.w %T1,%T0"
[(set_attr "length_table" "*,*,mov_imm4,short_immediate,movw")
- (set_attr "length" "2,2,*,*,*")
- (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv")])
+ (set_attr "length" "2,2,*,*,*")])
-(define_insn "movstricthi"
+(define_insn_and_split "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r"))
(match_operand:HI 1 "general_operand_src" "I,P3>X,rmi"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (strict_low_part (match_dup 0)) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "movstricthi_clobber_flags"
+ [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r"))
+ (match_operand:HI 1 "general_operand_src" "I,P3>X,rmi"))
+ (clobber (reg:CC CC_REG))]
+ ""
"@
sub.w %T0,%T0
mov.w %T1,%T0
mov.w %T1,%T0"
[(set_attr "length" "2,2,*")
- (set_attr "length_table" "*,*,movw")
- (set_attr "cc" "set_zn,set_znv,set_znv")])
+ (set_attr "length_table" "*,*,movw")])
;; movsi
-(define_insn "*movsi_h8300hs"
+(define_insn_and_split "*movsi"
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r")
(match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))]
"(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX
&& h8300_move_ok (operands[0], operands[1])"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movsi_clobber_flags"
+ [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r")
+ (match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))
+ (clobber (reg:CC CC_REG))]
+ "(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX
+ && h8300_move_ok (operands[0], operands[1])"
{
switch (which_alternative)
{
@@ -169,14 +233,22 @@
}
return "mov.l %S1,%S0";
}
- [(set (attr "length")
- (symbol_ref "compute_mov_length (operands)"))
- (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
+ [(set (attr "length") (symbol_ref "compute_mov_length (operands)"))])
-(define_insn "*movsi_h8sx"
+(define_insn_and_split "*movsi_h8sx"
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,Q,rQ,*a,*a,r")
(match_operand:SI 1 "general_operand_src" "I,P3>X,IP8>X,rQi,I,r,*a"))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movsi_h8sx_clobber_flags"
+ [(set (match_operand:SI 0 "general_operand_dst" "=r,r,Q,rQ,*a,*a,r")
+ (match_operand:SI 1 "general_operand_src" "I,P3>X,IP8>X,rQi,I,r,*a"))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"@
sub.l %S0,%S0
mov.l %S1:3,%S0
@@ -186,26 +258,46 @@
clrmac\;ldmac %1,macl
stmac macl,%0"
[(set_attr "length_table" "*,*,short_immediate,movl,*,*,*")
- (set_attr "length" "2,2,*,*,2,6,4")
- (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
+ (set_attr "length" "2,2,*,*,2,6,4")])
-(define_insn "*movsf_h8sx"
+(define_insn_and_split "*movsf_h8sx"
[(set (match_operand:SF 0 "general_operand_dst" "=r,rQ")
(match_operand:SF 1 "general_operand_src" "G,rQi"))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movsf_h8sx_clobber_flags"
+ [(set (match_operand:SF 0 "general_operand_dst" "=r,rQ")
+ (match_operand:SF 1 "general_operand_src" "G,rQi"))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"@
sub.l %S0,%S0
mov.l %S1,%S0"
[(set_attr "length" "2,*")
- (set_attr "length_table" "*,movl")
- (set_attr "cc" "set_zn,set_znv")])
+ (set_attr "length_table" "*,movl")])
-(define_insn "*movsf_h8300hs"
+(define_insn_and_split "*movsf"
[(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r")
(match_operand:SF 1 "general_operand_src" "G,r,im,r,r,>"))]
"!TARGET_H8300SX
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*movsf_clobber_flags"
+ [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r")
+ (match_operand:SF 1 "general_operand_src" "G,r,im,r,r,>"))
+ (clobber (reg:CC CC_REG))]
+ "!TARGET_H8300SX
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode))"
"@
sub.l %S0,%S0
mov.l %S1,%S0
@@ -213,21 +305,35 @@
mov.l %S1,%S0
mov.l %S1,%S0
mov.l %S1,%S0"
- [(set (attr "length")
- (symbol_ref "compute_mov_length (operands)"))
- (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
+ [(set (attr "length") (symbol_ref "compute_mov_length (operands)"))])
;; ----------------------------------------------------------------------
;; PUSH INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "*push1_h8300hs_<QHI:mode>"
+(define_insn_and_split "*push1_<QHI:mode>"
[(set (mem:QHI
(pre_modify:P
(reg:P SP_REG)
(plus:P (reg:P SP_REG) (const_int -4))))
(match_operand:QHI 0 "register_no_sp_elim_operand" "r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (mem:QHI
+ (pre_modify:P (reg:P SP_REG)
+ (plus:P (reg:P SP_REG) (const_int -4))))
+ (match_dup 0))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*push1_<QHI:mode>_clobber_flags"
+ [(set (mem:QHI
+ (pre_modify:P
+ (reg:P SP_REG)
+ (plus:P (reg:P SP_REG) (const_int -4))))
+ (match_operand:QHI 0 "register_no_sp_elim_operand" "r"))
+ (clobber (reg:CC CC_REG))]
+ ""
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")])
diff --git a/gcc/config/h8300/multiply.md b/gcc/config/h8300/multiply.md
index 4e9112f..56f2b6f 100644
--- a/gcc/config/h8300/multiply.md
+++ b/gcc/config/h8300/multiply.md
@@ -15,23 +15,46 @@
operands[2] = gen_rtx_SIGN_EXTEND (HImode, operands[2]);
})
-(define_insn "*mulqihi3_const"
+(define_insn_and_split "*mulqihi3_const"
[(set (match_operand:HI 0 "register_operand" "=r")
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
(match_operand:QI 2 "nibble_operand" "IP4>X")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (mult:HI (sign_extend:HI (match_dup 1)) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*mulqihi3_const_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+ (match_operand:QI 2 "nibble_operand" "IP4>X")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"mulxs.b %X2,%T0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
-(define_insn "*mulqihi3"
+(define_insn_and_split "*mulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
(sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (mult:HI (sign_extend:HI (match_dup 1))
+ (sign_extend:HI (match_dup 2))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*mulqihi3_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
+ (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mulxs.b %X2,%T0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
(define_expand "mulhisi3"
[(set (match_operand:SI 0 "register_operand" "")
@@ -44,23 +67,46 @@
operands[2] = gen_rtx_SIGN_EXTEND (SImode, operands[2]);
})
-(define_insn "*mulhisi3_const"
+(define_insn_and_split "*mulhisi3_const"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
(match_operand:SI 2 "nibble_operand" "IP4>X")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (mult:SI (sign_extend:SI (match_dup 1)) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*mulhisi3_const_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
+ (match_operand:SI 2 "nibble_operand" "IP4>X")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
"mulxs.w %T2,%S0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
-(define_insn "*mulhisi3"
+(define_insn_and_split "*mulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
(sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (mult:SI (sign_extend:SI (match_dup 1))
+ (sign_extend:SI (match_dup 2))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*mulhisi3_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))
+ (clobber (reg:CC CC_REG))]
+ ""
"mulxs.w %T2,%S0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
(define_expand "umulqihi3"
[(set (match_operand:HI 0 "register_operand" "")
@@ -79,8 +125,7 @@
(match_operand:QI 2 "nibble_operand" "IP4>X")))]
"TARGET_H8300SX"
"mulxu.b %X2,%T0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
(define_insn "*umulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -88,8 +133,7 @@
(zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
""
"mulxu.b %X2,%T0"
- [(set_attr "length" "2")
- (set_attr "cc" "none_0hit")])
+ [(set_attr "length" "2")])
(define_expand "umulhisi3"
[(set (match_operand:SI 0 "register_operand" "")
@@ -108,8 +152,7 @@
(match_operand:SI 2 "nibble_operand" "IP4>X")))]
"TARGET_H8300SX"
"mulxu.w %T2,%S0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
(define_insn "*umulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -117,23 +160,32 @@
(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
""
"mulxu.w %T2,%S0"
- [(set_attr "length" "2")
- (set_attr "cc" "none_0hit")])
+ [(set_attr "length" "2")])
;; We could have used mulu.[wl] here, but mulu.[lw] is only available
;; on a H8SX with a multiplier, whereas muls.w seems to be available
;; on all H8SX variants.
-(define_insn "mul<mode>3"
+(define_insn_and_split "mul<mode>3"
[(set (match_operand:HSI 0 "register_operand" "=r")
(mult:HSI (match_operand:HSI 1 "register_operand" "%0")
(match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))]
"TARGET_H8300SX"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (mult:HSI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "mul<mode>3_clobber_flags"
+ [(set (match_operand:HSI 0 "register_operand" "=r")
+ (mult:HSI (match_operand:HSI 1 "register_operand" "%0")
+ (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SX"
{ return <MODE>mode == HImode ? "muls.w\\t%T2,%T0" : "muls.l\\t%S2,%S0"; }
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
-(define_insn "smulsi3_highpart"
+(define_insn_and_split "smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI
@@ -142,9 +194,27 @@
(sign_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X")))
(const_int 32))))]
"TARGET_H8300SXMUL"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0)
+ (truncate:SI (lshiftrt:DI (mult:DI
+ (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2)))
+ (const_int 32))))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "smulsi3_highpart_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
+ (sign_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X")))
+ (const_int 32))))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_H8300SXMUL"
"muls/u.l\\t%S2,%S0"
- [(set_attr "length" "4")
- (set_attr "cc" "set_zn")])
+ [(set_attr "length" "4")])
(define_insn "umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -156,8 +226,7 @@
(const_int 32))))]
"TARGET_H8300SX"
"mulu/u.l\\t%S2,%S0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
+ [(set_attr "length" "4")])
;; This is a "bridge" instruction. Combine can't cram enough insns
;; together to crate a MAC instruction directly, but it can create
@@ -176,8 +245,7 @@
(mem:HI (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))))]
"TARGET_MAC"
"clrmac\;mac @%2+,@%1+"
- [(set_attr "length" "6")
- (set_attr "cc" "none_0hit")])
+ [(set_attr "length" "6")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a")
@@ -189,6 +257,5 @@
(match_operand:SI 3 "register_operand" "0")))]
"TARGET_MAC"
"mac @%2+,@%1+"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
+ [(set_attr "length" "4")])
diff --git a/gcc/config/h8300/other.md b/gcc/config/h8300/other.md
index 4b96a7c..572a29f 100644
--- a/gcc/config/h8300/other.md
+++ b/gcc/config/h8300/other.md
@@ -2,10 +2,20 @@
;; ABSOLUTE VALUE INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "abssf2"
+(define_insn_and_split "abssf2"
[(set (match_operand:SF 0 "register_operand" "=r")
(abs:SF (match_operand:SF 1 "register_operand" "0")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (abs:SF (match_dup 1)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "abssf2_clobber_flags"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (abs:SF (match_operand:SF 1 "register_operand" "0")))
+ (clobber (reg:CC CC_REG))]
+ ""
"and.w\\t#32767,%e0"
[(set_attr "length" "4")])
@@ -13,5 +23,4 @@
[(const_int 0)]
""
"nop"
- [(set_attr "cc" "none")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
diff --git a/gcc/config/h8300/peepholes.md b/gcc/config/h8300/peepholes.md
index 8442cd8..bd69018 100644
--- a/gcc/config/h8300/peepholes.md
+++ b/gcc/config/h8300/peepholes.md
@@ -433,96 +433,6 @@
: gen_rtx_LT (VOIDmode, cc0_rtx, const0_rtx));
})
-;; The next three peephole2's will try to transform
-;;
-;; mov.b A,r0l (or mov.l A,er0)
-;; and.l #CST,er0
-;;
-;; into
-;;
-;; sub.l er0
-;; mov.b A,r0l
-;; and.b #CST,r0l (if CST is not 255)
-
-(define_peephole2
- [(set (match_operand:QI 0 "register_operand" "")
- (match_operand:QI 1 "general_operand" ""))
- (set (match_operand:SI 2 "register_operand" "")
- (and:SI (match_dup 2)
- (const_int 255)))]
- "!reg_overlap_mentioned_p (operands[2], operands[1])
- && REGNO (operands[0]) == REGNO (operands[2])"
- [(set (match_dup 2)
- (const_int 0))
- (set (strict_low_part (match_dup 0))
- (match_dup 1))]
- "")
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonimmediate_operand" ""))
- (set (match_dup 0)
- (and:SI (match_dup 0)
- (const_int 255)))]
- "!reg_overlap_mentioned_p (operands[0], operands[1])
- && !(GET_CODE (operands[1]) == MEM && !offsettable_memref_p (operands[1]))
- && !(GET_CODE (operands[1]) == MEM && MEM_VOLATILE_P (operands[1]))"
- [(set (match_dup 0)
- (const_int 0))
- (set (strict_low_part (match_dup 2))
- (match_dup 3))]
- {
- operands[2] = gen_lowpart (QImode, operands[0]);
- operands[3] = gen_lowpart (QImode, operands[1]);
- })
-
-(define_peephole2
- [(set (match_operand 0 "register_operand" "")
- (match_operand 1 "nonimmediate_operand" ""))
- (set (match_operand:SI 2 "register_operand" "")
- (and:SI (match_dup 2)
- (match_operand:SI 3 "const_int_qi_operand" "")))]
- "(GET_MODE (operands[0]) == QImode
- || GET_MODE (operands[0]) == HImode
- || GET_MODE (operands[0]) == SImode)
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && REGNO (operands[0]) == REGNO (operands[2])
- && !reg_overlap_mentioned_p (operands[2], operands[1])
- && !(GET_MODE (operands[1]) != QImode
- && GET_CODE (operands[1]) == MEM
- && !offsettable_memref_p (operands[1]))
- && !(GET_MODE (operands[1]) != QImode
- && GET_CODE (operands[1]) == MEM
- && MEM_VOLATILE_P (operands[1]))"
- [(set (match_dup 2)
- (const_int 0))
- (set (strict_low_part (match_dup 4))
- (match_dup 5))
- (set (match_dup 2)
- (and:SI (match_dup 2)
- (match_dup 6)))]
- {
- operands[4] = gen_lowpart (QImode, operands[0]);
- operands[5] = gen_lowpart (QImode, operands[1]);
- operands[6] = GEN_INT (~0xff | INTVAL (operands[3]));
- })
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "register_operand" ""))
- (set (match_dup 0)
- (and:SI (match_dup 0)
- (const_int 65280)))]
- "!reg_overlap_mentioned_p (operands[0], operands[1])"
- [(set (match_dup 0)
- (const_int 0))
- (set (zero_extract:SI (match_dup 0)
- (const_int 8)
- (const_int 8))
- (lshiftrt:SI (match_dup 1)
- (const_int 8)))]
- "")
-
;; If a load of mem:SI is followed by an AND that turns off the upper
;; half, then we can load mem:HI instead.
@@ -546,20 +456,6 @@
operands[4] = gen_lowpart (HImode, operands[1]);
})
-;; Convert a memory comparison to a move if there is a scratch register.
-
-(define_peephole2
- [(match_scratch:QHSI 1 "r")
- (set (cc0)
- (compare (match_operand:QHSI 0 "memory_operand" "")
- (const_int 0)))]
- ""
- [(set (match_dup 1)
- (match_dup 0))
- (set (cc0) (compare (match_dup 1)
- (const_int 0)))]
- "")
-
;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve
;; the equivalent with shorter sequences. Here is the summary. Cases
;; are grouped for each define_peephole2.
diff --git a/gcc/config/h8300/predicates.md b/gcc/config/h8300/predicates.md
index b530c2c..7c4e12a 100644
--- a/gcc/config/h8300/predicates.md
+++ b/gcc/config/h8300/predicates.md
@@ -501,3 +501,12 @@
(define_predicate "pc_or_label_operand"
(match_code "pc,label_ref"))
+(define_predicate "simple_memory_operand"
+ (match_code "mem")
+{
+ if (GET_MODE (op) == mode
+ && (GET_CODE (XEXP (op, 0)) != PRE_DEC
+ && GET_CODE (XEXP (op, 0)) != POST_INC))
+ return 1;
+ return 0;
+})
diff --git a/gcc/config/h8300/proepi.md b/gcc/config/h8300/proepi.md
index 9d19ff5..44d5968 100644
--- a/gcc/config/h8300/proepi.md
+++ b/gcc/config/h8300/proepi.md
@@ -36,8 +36,7 @@
XVECLEN (operands[0], 0) - 2));
return "ldm.l\t@er7+,%S1-%S3";
}
- [(set_attr "cc" "none")
- (set_attr "length" "4")])
+ [(set_attr "length" "4")])
(define_insn "stm_h8300sx"
[(match_parallel 0 "h8300_stm_parallel"
@@ -49,8 +48,7 @@
XVECLEN (operands[0], 0) - 2));
return "stm.l\t%S2-%S3,@-er7";
}
- [(set_attr "cc" "none")
- (set_attr "length" "4")])
+ [(set_attr "length" "4")])
(define_insn "return_h8sx"
[(match_parallel 0 "h8300_return_parallel"
@@ -67,8 +65,7 @@
else
return "rts/l\t%S1-%S3";
}
- [(set_attr "cc" "none")
- (set_attr "can_delay" "no")
+ [(set_attr "can_delay" "no")
(set_attr "length" "2")])
(define_expand "return"
@@ -86,8 +83,7 @@
else
return "rts";
}
- [(set_attr "cc" "none")
- (set_attr "can_delay" "no")
+ [(set_attr "can_delay" "no")
(set_attr "length" "2")])
(define_expand "prologue"
diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md
index 75606d7..f1c86f7 100644
--- a/gcc/config/h8300/shiftrotate.md
+++ b/gcc/config/h8300/shiftrotate.md
@@ -50,12 +50,24 @@
;; QI/HI/SI BIT SHIFTS
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
(match_operator:QHSI 3 "h8sx_unary_shift_operator"
[(match_operand:QHSI 1 "h8300_dst_operand" "0")
(match_operand:QI 2 "const_int_operand" "")]))]
"h8300_operands_match_p (operands)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
+ (match_operator:QHSI 3 "h8sx_unary_shift_operator"
+ [(match_operand:QHSI 1 "h8300_dst_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "")]))
+ (clobber (reg:CC CC_REG))]
+ "h8300_operands_match_p (operands)"
{
if (<MODE>mode == E_QImode)
return output_h8sx_shift (operands, 'b', 'X');
@@ -65,15 +77,68 @@
return output_h8sx_shift (operands, 'l', 'S');
gcc_unreachable ();
}
- [(set_attr "length_table" "unary")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length_table" "unary")])
(define_insn ""
+ [(set (reg:CCZN CC_REG)
+ (compare:CCZN
+ (match_operator:QHSI 3 "h8sx_unary_shift_operator"
+ [(match_operand:QHSI 1 "h8300_dst_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "")])
+ (const_int 0)))
+ (set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
+ "h8300_operands_match_p (operands)"
+{
+ if (<MODE>mode == E_QImode)
+ return output_h8sx_shift (operands, 'b', 'X');
+ if (<MODE>mode == E_HImode)
+ return output_h8sx_shift (operands, 'w', 'T');
+ if (<MODE>mode == E_SImode)
+ return output_h8sx_shift (operands, 'l', 'S');
+ gcc_unreachable ();
+}
+ [(set_attr "length_table" "unary")])
+
+(define_insn_and_split ""
[(set (match_operand:QHSI 0 "register_operand" "=r")
(match_operator:QHSI 3 "h8sx_binary_shift_operator"
[(match_operand:QHSI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "r P5>X")]))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (match_operator:QHSI 3 "h8sx_binary_shift_operator"
+ [(match_operand:QHSI 1 "register_operand" "0")
+ (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))
+ (clobber (reg:CC CC_REG))]
+ ""
+{
+ if (<MODE>mode == QImode)
+ return output_h8sx_shift (operands, 'b', 'X');
+ if (<MODE>mode == HImode)
+ return output_h8sx_shift (operands, 'w', 'T');
+ if (<MODE>mode == SImode)
+ return output_h8sx_shift (operands, 'l', 'S');
+ gcc_unreachable ();
+}
+ [(set_attr "length" "4")])
+
+(define_insn ""
+ [(set (reg:CCZN CC_REG)
+ (compare:CCZN
+ (match_operator:QHSI 3 "h8sx_binary_shift_operator"
+ [(match_operand:QHSI 1 "register_operand" "0")
+ (match_operand:QI 2 "nonmemory_operand" "r P5>X")])
+ (const_int 0)))
+ (set (match_operand:QHSI 0 "register_operand" "=r")
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
+ ""
{
if (<MODE>mode == QImode)
return output_h8sx_shift (operands, 'b', 'X');
@@ -83,54 +148,172 @@
return output_h8sx_shift (operands, 'l', 'S');
gcc_unreachable ();
}
- [(set_attr "length" "4")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "4")])
-(define_insn "*shiftqi"
+(define_insn_and_split "*shiftqi"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(match_operator:QI 3 "nshift_operator"
[(match_operand:QI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "R,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (match_dup 4))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*shiftqi_clobber_flags"
+ [(set (match_operand:QI 0 "register_operand" "=r,r")
+ (match_operator:QI 3 "nshift_operator"
+ [(match_operand:QI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "R,rn")]))
+ (clobber (match_scratch:QI 4 "=X,&r"))
+ (clobber (reg:CC CC_REG))]
+ ""
{
return output_a_shift (operands);
}
[(set (attr "length")
- (symbol_ref "compute_a_shift_length (insn, operands)"))
- (set (attr "cc")
- (symbol_ref "compute_a_shift_cc (insn, operands)"))])
+ (symbol_ref "compute_a_shift_length (insn, operands)"))])
+
+(define_insn_and_split "*shiftqi_noscratch"
+ [(set (match_operand:QI 0 "register_operand" "=r,r")
+ (match_operator:QI 3 "nshift_operator"
+ [(match_operand:QI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "R,rn")]))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
+ GET_CODE (operands[3])))"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REG))])])
-(define_insn "*shifthi"
+(define_insn "*shiftqi_noscratch_clobber_flags"
+ [(set (match_operand:QI 0 "register_operand" "=r,r")
+ (match_operator:QI 3 "nshift_operator"
+ [(match_operand:QI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "R,rn")]))
+ (clobber (reg:CC CC_REG))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
+ GET_CODE (operands[3])))"
+{
+ return output_a_shift (operands);
+}
+ [(set (attr "length")
+ (symbol_ref "compute_a_shift_length (insn, operands)"))])
+
+(define_insn_and_split "*shifthi"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI 3 "nshift_operator"
[(match_operand:HI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "S,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (match_dup 4))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*shifthi_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (match_operator:HI 3 "nshift_operator"
+ [(match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "S,rn")]))
+ (clobber (match_scratch:QI 4 "=X,&r"))
+ (clobber (reg:CC CC_REG))]
+ ""
{
return output_a_shift (operands);
}
[(set (attr "length")
- (symbol_ref "compute_a_shift_length (insn, operands)"))
- (set (attr "cc")
- (symbol_ref "compute_a_shift_cc (insn, operands)"))])
+ (symbol_ref "compute_a_shift_length (insn, operands)"))])
-(define_insn "*shiftsi"
+(define_insn_and_split "*shifthi_noscratch"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (match_operator:HI 3 "nshift_operator"
+ [(match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:HI 2 "nonmemory_operand" "S,rn")]))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode,
+ GET_CODE (operands[3])))"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*shifthi_noscratch_clobber_flags"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (match_operator:HI 3 "nshift_operator"
+ [(match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:HI 2 "nonmemory_operand" "S,rn")]))
+ (clobber (reg:CC CC_REG))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode,
+ GET_CODE (operands[3])))"
+{
+ return output_a_shift (operands);
+}
+ [(set (attr "length")
+ (symbol_ref "compute_a_shift_length (insn, operands)"))])
+
+(define_insn_and_split "*shiftsi"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 3 "nshift_operator"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "T,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (match_dup 4))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "*shiftsi_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (match_operator:SI 3 "nshift_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "T,rn")]))
+ (clobber (match_scratch:QI 4 "=X,&r"))
+ (clobber (reg:CC CC_REG))]
+ ""
{
return output_a_shift (operands);
}
[(set (attr "length")
- (symbol_ref "compute_a_shift_length (insn, operands)"))
- (set (attr "cc")
- (symbol_ref "compute_a_shift_cc (insn, operands)"))])
+ (symbol_ref "compute_a_shift_length (insn, operands)"))])
+
+(define_insn_and_split "*shiftsi_noscratch"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (match_operator:SI 3 "nshift_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "T,rn")]))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode,
+ GET_CODE (operands[3])))"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REG))])])
+(define_insn "*shiftsi_noscratch_clobber_flags"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (match_operator:SI 3 "nshift_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "T,rn")]))
+ (clobber (reg:CC CC_REG))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode,
+ GET_CODE (operands[3])))"
+{
+ return output_a_shift (operands);
+}
+ [(set (attr "length")
+ (symbol_ref "compute_a_shift_length (insn, operands)"))])
;; Split a variable shift into a loop. If the register containing
;; the shift count dies, then we just use that register.
@@ -140,12 +323,12 @@
(match_operator 2 "nshift_operator"
[(match_dup 0)
(match_operand:QI 1 "register_operand" "")]))
- (clobber (match_operand:QI 3 "register_operand" ""))]
+ (clobber (match_operand:QI 3 "register_operand" ""))
+ (clobber (reg:CC CC_REG))]
"epilogue_completed
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
- [(set (cc0) (compare (match_dup 1) (const_int 0)))
- (set (pc)
- (if_then_else (le (cc0) (const_int 0))
+ [(set (pc)
+ (if_then_else (le (match_dup 1) (const_int 0))
(label_ref (match_dup 5))
(pc)))
(match_dup 4)
@@ -154,9 +337,8 @@
(match_op_dup 2 [(match_dup 0) (const_int 1)]))
(clobber (scratch:QI))])
(set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))
- (set (cc0) (compare (match_dup 1) (const_int 0)))
(set (pc)
- (if_then_else (ne (cc0) (const_int 0))
+ (if_then_else (ne (match_dup 1) (const_int 0))
(label_ref (match_dup 4))
(pc)))
(match_dup 5)]
@@ -170,14 +352,14 @@
(match_operator 2 "nshift_operator"
[(match_dup 0)
(match_operand:QI 1 "register_operand" "")]))
- (clobber (match_operand:QI 3 "register_operand" ""))]
+ (clobber (match_operand:QI 3 "register_operand" ""))
+ (clobber (reg:CC CC_REG))]
"epilogue_completed
&& !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
[(set (match_dup 3)
(match_dup 1))
- (set (cc0) (compare (match_dup 3) (const_int 0)))
(set (pc)
- (if_then_else (le (cc0) (const_int 0))
+ (if_then_else (le (match_dup 3) (const_int 0))
(label_ref (match_dup 5))
(pc)))
(match_dup 4)
@@ -186,9 +368,8 @@
(match_op_dup 2 [(match_dup 0) (const_int 1)]))
(clobber (scratch:QI))])
(set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))
- (set (cc0) (compare (match_dup 3) (const_int 0)))
(set (pc)
- (if_then_else (ne (cc0) (const_int 0))
+ (if_then_else (ne (match_dup 3) (const_int 0))
(label_ref (match_dup 4))
(pc)))
(match_dup 5)]
@@ -196,6 +377,18 @@
operands[4] = gen_label_rtx ();
operands[5] = gen_label_rtx ();
})
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 3 "nshift_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:QI 2 "nonmemory_operand")]))
+ (clobber (match_scratch:QI 4))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (match_dup 4))
+ (clobber (reg:CC CC_REG))])])
+
;; ----------------------------------------------------------------------
;; ROTATIONS
@@ -211,11 +404,22 @@
DONE;
})
-(define_insn "rotl<mode>3_1"
+(define_insn_and_split "rotl<mode>3_1"
[(set (match_operand:QHSI 0 "register_operand" "=r")
(rotate:QHSI (match_operand:QHSI 1 "register_operand" "0")
(match_operand:QI 2 "immediate_operand" "")))]
""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (rotate:QHSI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REG))])])
+
+(define_insn "rotl<mode>3_1_clobber_flags"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC CC_REG))]
+ ""
{
return output_a_rotate (ROTATE, operands);
}
diff --git a/gcc/config/h8300/testcompare.md b/gcc/config/h8300/testcompare.md
index 118db14..e9f6ddc 100644
--- a/gcc/config/h8300/testcompare.md
+++ b/gcc/config/h8300/testcompare.md
@@ -2,164 +2,149 @@
;; TEST INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn_and_split "*tst_extzv_1_n"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n,n,n"))
- (const_int 0)))
- (clobber (match_scratch:QI 2 "=X,X,&r"))]
- "!CONSTANT_P (operands[0])"
- "@
- btst\\t%Z1,%Y0
- btst\\t%Z1,%Y0
- #"
- "&& reload_completed
- && !satisfies_constraint_U (operands[0])"
- [(set (match_dup 2)
- (match_dup 0))
- (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2)
- (const_int 1)
- (match_dup 1))
- (const_int 0)))
- (clobber (scratch:QI))])]
- ""
- [(set_attr "length" "2,8,10")
- (set_attr "cc" "set_zn,set_zn,set_zn")])
-
-(define_insn ""
- [(set (cc0)
- (compare (zero_extract:HSI (match_operand:HSI 0 "register_operand" "r")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n"))
- (const_int 0)))]
- "INTVAL (operands[1]) <= 15"
- "btst %Z1,%Y0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_zn")])
-
-(define_insn_and_split "*tstsi_upper_bit"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 2 "=&r"))]
- "INTVAL (operands[1]) >= 16"
- "#"
- "&& reload_completed"
- [(set (match_dup 2)
- (ior:SI (and:SI (match_dup 2)
- (const_int -65536))
- (lshiftrt:SI (match_dup 0)
- (const_int 16))))
- (set (cc0)
- (compare (zero_extract:SI (match_dup 2)
- (const_int 1)
- (match_dup 3))
- (const_int 0)))]
- {
- operands[3] = GEN_INT (INTVAL (operands[1]) - 16);
- })
-
-(define_insn "*tstsi_variable_bit"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 1)
- (and:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 7)))
- (const_int 0)))]
- ""
- "btst %w1,%w0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_zn")])
-
-(define_insn_and_split "*tstsi_variable_bit_qi"
- [(set (cc0)
- (compare (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>"))
- (const_int 1)
- (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
- (const_int 7)))
- (const_int 0)))
- (clobber (match_scratch:QI 2 "=X,X,&r"))]
- "!CONSTANT_P (operands[0])"
- "@
- btst\\t%w1,%X0
- btst\\t%w1,%X0
- #"
- "&& reload_completed
- && !satisfies_constraint_U (operands[0])"
- [(set (match_dup 2)
- (match_dup 0))
- (parallel [(set (cc0)
- (compare (zero_extract:SI (zero_extend:SI (match_dup 2))
- (const_int 1)
- (and:SI (match_dup 1)
- (const_int 7)))
- (const_int 0)))
- (clobber (scratch:QI))])]
- ""
- [(set_attr "length" "2,8,10")
- (set_attr "cc" "set_zn,set_zn,set_zn")])
+;; (define_insn_and_split "*tst_extzv_1_n"
+;; [(set (cc0)
+;; (compare (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
+;; (const_int 1)
+;; (match_operand 1 "const_int_operand" "n,n,n"))
+;; (const_int 0)))
+;; (clobber (match_scratch:QI 2 "=X,X,&r"))]
+;; "!CONSTANT_P (operands[0])"
+;; "@
+;; btst\\t%Z1,%Y0
+;; btst\\t%Z1,%Y0
+;; #"
+;; "&& reload_completed
+;; && !satisfies_constraint_U (operands[0])"
+;; [(set (match_dup 2)
+;; (match_dup 0))
+;; (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2)
+;; (const_int 1)
+;; (match_dup 1))
+;; (const_int 0)))
+;; (clobber (scratch:QI))])]
+;; ""
+;; [(set_attr "length" "2,8,10")])
+;;
+;;(define_insn ""
+;; [(set (cc0)
+;; (compare (zero_extract:HSI (match_operand:HSI 0 "register_operand" "r")
+;; (const_int 1)
+;; (match_operand 1 "const_int_operand" "n"))
+;; (const_int 0)))]
+;; "INTVAL (operands[1]) <= 15"
+;; "btst %Z1,%Y0"
+;; [(set_attr "length" "2")])
+;;
+;;(define_insn_and_split "*tstsi_upper_bit"
+;; [(set (cc0)
+;; (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+;; (const_int 1)
+;; (match_operand 1 "const_int_operand" "n"))
+;; (const_int 0)))
+;; (clobber (match_scratch:SI 2 "=&r"))]
+;; "INTVAL (operands[1]) >= 16"
+;; "#"
+;; "&& reload_completed"
+;; [(set (match_dup 2)
+;; (ior:SI (and:SI (match_dup 2)
+;; (const_int -65536))
+;; (lshiftrt:SI (match_dup 0)
+;; (const_int 16))))
+;; (set (cc0)
+;; (compare (zero_extract:SI (match_dup 2)
+;; (const_int 1)
+;; (match_dup 3))
+;; (const_int 0)))]
+;; {
+;; operands[3] = GEN_INT (INTVAL (operands[1]) - 16);
+;; })
+;;
+;;(define_insn "*tstsi_variable_bit"
+;; [(set (cc0)
+;; (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+;; (const_int 1)
+;; (and:SI (match_operand:SI 1 "register_operand" "r")
+;; (const_int 7)))
+;; (const_int 0)))]
+;; ""
+;; "btst %w1,%w0"
+;; [(set_attr "length" "2")])
+;;
+;;(define_insn_and_split "*tstsi_variable_bit_qi"
+;; [(set (cc0)
+;; (compare (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>"))
+;; (const_int 1)
+;; (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
+;; (const_int 7)))
+;; (const_int 0)))
+;; (clobber (match_scratch:QI 2 "=X,X,&r"))]
+;; "!CONSTANT_P (operands[0])"
+;; "@
+;; btst\\t%w1,%X0
+;; btst\\t%w1,%X0
+;; #"
+;; "&& reload_completed
+;; && !satisfies_constraint_U (operands[0])"
+;; [(set (match_dup 2)
+;; (match_dup 0))
+;; (parallel [(set (cc0)
+;; (compare (zero_extract:SI (zero_extend:SI (match_dup 2))
+;; (const_int 1)
+;; (and:SI (match_dup 1)
+;; (const_int 7)))
+;; (const_int 0)))
+;; (clobber (scratch:QI))])]
+;; ""
+;; [(set_attr "length" "2,8,10")])
(define_insn "*tst<mode>"
- [(set (cc0)
- (compare (match_operand:QHI 0 "register_operand" "r")
- (const_int 0)))]
+ [(set (reg:CCZN CC_REG)
+ (compare:CCZN (match_operand:QHSI 0 "register_operand" "r")
+ (const_int 0)))]
""
{
if (<MODE>mode == QImode)
return "mov.b %X0,%X0";
else if (<MODE>mode == HImode)
return "mov.w %T0,%T0";
+ else if (<MODE>mode == SImode)
+ return "mov.l %S0,%S0";
gcc_unreachable ();
}
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
(define_insn "*tsthi_upper"
- [(set (cc0)
+ [(set (reg:CCZN CC_REG)
(compare (and:HI (match_operand:HI 0 "register_operand" "r")
(const_int -256))
(const_int 0)))]
- ""
+ "reload_completed"
"mov.b %t0,%t0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
-
-(define_insn "*tstsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "r")
- (const_int 0)))]
- ""
- "mov.l %S0,%S0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
(define_insn "*tstsi_upper"
- [(set (cc0)
+ [(set (reg:CCZN CC_REG)
(compare (and:SI (match_operand:SI 0 "register_operand" "r")
(const_int -65536))
(const_int 0)))]
- ""
+ "reload_completed"
"mov.w %e0,%e0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+ [(set_attr "length" "2")])
(define_insn "*cmpqi"
- [(set (cc0)
+ [(set (reg:CC CC_REG)
(compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
(match_operand:QI 1 "h8300_src_operand" "rQi")))]
- ""
+ "reload_completed"
"cmp.b %X1,%X0"
- [(set_attr "length_table" "add")
- (set_attr "cc" "compare")])
+ [(set_attr "length_table" "add")])
-(define_insn "*cmphi_h8300hs_znvc"
- [(set (cc0)
+(define_insn "*cmphi"
+ [(set (reg:CC CC_REG)
(compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ")
(match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))]
- ""
+ "reload_completed"
{
switch (which_alternative)
{
@@ -174,14 +159,13 @@
gcc_unreachable ();
}
}
- [(set_attr "length_table" "short_immediate,add")
- (set_attr "cc" "compare,compare")])
+ [(set_attr "length_table" "short_immediate,add")])
(define_insn "cmpsi"
- [(set (cc0)
+ [(set (reg:CC CC_REG)
(compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ")
(match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))]
- ""
+ "reload_completed"
{
switch (which_alternative)
{
@@ -197,5 +181,28 @@
}
}
[(set_attr "length" "2,*")
- (set_attr "length_table" "*,add")
- (set_attr "cc" "compare,compare")])
+ (set_attr "length_table" "*,add")])
+
+;; Convert a memory comparison to a move if there is a scratch register.
+
+(define_peephole2
+ [(match_scratch:QHSI 1 "r")
+ (set (reg:CC CC_REG)
+ (compare (match_operand:QHSI 0 "memory_operand" "")
+ (const_int 0)))]
+ ""
+ [(parallel [(set (match_dup 1) (match_dup 0)) (clobber (reg:CC CC_REG))])
+ (set (reg:CC CC_REG) (compare:CC (match_dup 1) (const_int 0)))])
+
+;; The compare-elimination pass does not handle memory reference. So this
+;; little peephole helps fill the gap and avoid code quality regressions.
+(define_peephole2
+ [(parallel [(set (match_operand:QHSI 0 "register_operand" "")
+ (match_operand:QHSI 1 "simple_memory_operand" ""))
+ (clobber (reg:CC CC_REG))])
+ (set (reg:CCZN CC_REG)
+ (compare:CCZN (match_dup 0) (const_int 0)))]
+ ""
+ [(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0)))
+ (set (match_dup 0) (match_dup 1))])])
+
diff --git a/gcc/config/host-darwin.c b/gcc/config/host-darwin.c
index 0face6c..c862935 100644
--- a/gcc/config/host-darwin.c
+++ b/gcc/config/host-darwin.c
@@ -24,7 +24,10 @@
#include "config/host-darwin.h"
/* Yes, this is really supposed to work. */
-static char pch_address_space[1024*1024*1024] __attribute__((aligned (4096)));
+/* This allows for a pagesize of 16384, which we have on Darwin20, but should
+ continue to work OK for pagesize 4096 which we have on earlier versions.
+ The size is 1 (binary) Gb. */
+static char pch_address_space[65536*16384] __attribute__((aligned (16384)));
/* Return the address of the PCH address space, if the PCH will fit in it. */
diff --git a/gcc/config/i386/avx512vnnivlintrin.h b/gcc/config/i386/avx512vnnivlintrin.h
index b4a6db3..3845b03 100644
--- a/gcc/config/i386/avx512vnnivlintrin.h
+++ b/gcc/config/i386/avx512vnnivlintrin.h
@@ -34,13 +34,10 @@
#define __DISABLE_AVX512VNNIVL__
#endif /* __AVX512VNNIVL__ */
-extern __inline __m256i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm256_dpbusd_epi32 (__m256i __A, __m256i __B, __m256i __C)
-{
- return (__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si)__A, (__v8si) __B,
- (__v8si) __C);
-}
+#define _mm256_dpbusd_epi32(A, B, C) \
+ ((__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) (A), \
+ (__v8si) (B), \
+ (__v8si) (C)))
extern __inline __m256i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -58,13 +55,10 @@ _mm256_maskz_dpbusd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D)
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
}
-extern __inline __m128i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_dpbusd_epi32 (__m128i __A, __m128i __B, __m128i __C)
-{
- return (__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si)__A, (__v4si) __B,
- (__v4si) __C);
-}
+#define _mm_dpbusd_epi32(A, B, C) \
+ ((__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) (A), \
+ (__v4si) (B), \
+ (__v4si) (C)))
extern __inline __m128i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -82,13 +76,10 @@ _mm_maskz_dpbusd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
}
-extern __inline __m256i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm256_dpbusds_epi32 (__m256i __A, __m256i __B, __m256i __C)
-{
- return (__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si)__A, (__v8si) __B,
- (__v8si) __C);
-}
+#define _mm256_dpbusds_epi32(A, B, C) \
+ ((__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) (A), \
+ (__v8si) (B), \
+ (__v8si) (C)))
extern __inline __m256i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -107,13 +98,10 @@ _mm256_maskz_dpbusds_epi32 (__mmask8 __A, __m256i __B, __m256i __C,
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
}
-extern __inline __m128i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_dpbusds_epi32 (__m128i __A, __m128i __B, __m128i __C)
-{
- return (__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si)__A, (__v4si) __B,
- (__v4si) __C);
-}
+#define _mm_dpbusds_epi32(A, B, C) \
+ ((__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) (A), \
+ (__v4si) (B), \
+ (__v4si) (C)))
extern __inline __m128i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -131,13 +119,10 @@ _mm_maskz_dpbusds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
}
-extern __inline __m256i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm256_dpwssd_epi32 (__m256i __A, __m256i __B, __m256i __C)
-{
- return (__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si)__A, (__v8si) __B,
- (__v8si) __C);
-}
+#define _mm256_dpwssd_epi32(A, B, C) \
+ ((__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) (A), \
+ (__v8si) (B), \
+ (__v8si) (C)))
extern __inline __m256i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -155,13 +140,10 @@ _mm256_maskz_dpwssd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D)
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
}
-extern __inline __m128i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_dpwssd_epi32 (__m128i __A, __m128i __B, __m128i __C)
-{
- return (__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si)__A, (__v4si) __B,
- (__v4si) __C);
-}
+#define _mm_dpwssd_epi32(A, B, C) \
+ ((__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) (A), \
+ (__v4si) (B), \
+ (__v4si) (C)))
extern __inline __m128i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -179,13 +161,10 @@ _mm_maskz_dpwssd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
}
-extern __inline __m256i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm256_dpwssds_epi32 (__m256i __A, __m256i __B, __m256i __C)
-{
- return (__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si)__A, (__v8si) __B,
- (__v8si) __C);
-}
+#define _mm256_dpwssds_epi32(A, B, C) \
+ ((__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) (A), \
+ (__v8si) (B), \
+ (__v8si) (C)))
extern __inline __m256i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -204,13 +183,10 @@ _mm256_maskz_dpwssds_epi32 (__mmask8 __A, __m256i __B, __m256i __C,
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
}
-extern __inline __m128i
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_dpwssds_epi32 (__m128i __A, __m128i __B, __m128i __C)
-{
- return (__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si)__A, (__v4si) __B,
- (__v4si) __C);
-}
+#define _mm_dpwssds_epi32(A, B, C) \
+ ((__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) (A), \
+ (__v4si) (B), \
+ (__v4si) (C)))
extern __inline __m128i
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
diff --git a/gcc/config/i386/avxvnniintrin.h b/gcc/config/i386/avxvnniintrin.h
new file mode 100644
index 0000000..de7e6a9
--- /dev/null
+++ b/gcc/config/i386/avxvnniintrin.h
@@ -0,0 +1,113 @@
+/* Copyright (C) 2020 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _IMMINTRIN_H_INCLUDED
+#error "Never use <avxvnniintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef _AVXVNNIINTRIN_H_INCLUDED
+#define _AVXVNNIINTRIN_H_INCLUDED
+
+#if !defined(__AVXVNNI__)
+#pragma GCC push_options
+#pragma GCC target("avxvnni")
+#define __DISABLE_AVXVNNIVL__
+#endif /* __AVXVNNIVL__ */
+
+extern __inline __m256i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_dpbusd_avx_epi32(__m256i __A, __m256i __B, __m256i __C)
+{
+ return (__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __C);
+}
+
+extern __inline __m128i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_dpbusd_avx_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+ return (__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __C);
+}
+
+extern __inline __m256i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_dpbusds_avx_epi32(__m256i __A, __m256i __B, __m256i __C)
+{
+ return (__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __C);
+}
+
+extern __inline __m128i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_dpbusds_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
+{
+ return (__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __C);
+}
+
+extern __inline __m256i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_dpwssd_avx_epi32(__m256i __A,__m256i __B,__m256i __C)
+{
+ return (__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __C);
+}
+
+extern __inline __m128i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_dpwssd_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
+{
+ return (__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __C);
+}
+
+extern __inline __m256i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_dpwssds_avx_epi32(__m256i __A,__m256i __B,__m256i __C)
+{
+ return (__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __C);
+}
+
+extern __inline __m128i
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_dpwssds_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
+{
+ return (__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __C);
+}
+
+#ifdef __DISABLE_AVXVNNIVL__
+#undef __DISABLE_AVXVNNIVL__
+#pragma GCC pop_options
+#endif /* __DISABLE_AVXVNNIVL__ */
+#endif /* _AVXVNNIINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/cet.c b/gcc/config/i386/cet.c
deleted file mode 100644
index 5450ac3..0000000
--- a/gcc/config/i386/cet.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Functions for CET/x86.
- Copyright (C) 2017-2020 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "output.h"
-#include "linux-common.h"
-
-void
-file_end_indicate_exec_stack_and_cet (void)
-{
- file_end_indicate_exec_stack ();
-
- if (flag_cf_protection == CF_NONE)
- return;
-
- unsigned int feature_1 = 0;
-
- if (flag_cf_protection & CF_BRANCH)
- /* GNU_PROPERTY_X86_FEATURE_1_IBT. */
- feature_1 |= 0x1;
-
- if (flag_cf_protection & CF_RETURN)
- /* GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
- feature_1 |= 0x2;
-
- if (feature_1)
- {
- int p2align = ptr_mode == SImode ? 2 : 3;
-
- /* Generate GNU_PROPERTY_X86_FEATURE_1_XXX. */
- switch_to_section (get_section (".note.gnu.property",
- SECTION_NOTYPE, NULL));
-
- ASM_OUTPUT_ALIGN (asm_out_file, p2align);
- /* name length. */
- fprintf (asm_out_file, ASM_LONG " 1f - 0f\n");
- /* data length. */
- fprintf (asm_out_file, ASM_LONG " 4f - 1f\n");
- /* note type: NT_GNU_PROPERTY_TYPE_0. */
- fprintf (asm_out_file, ASM_LONG " 5\n");
- fprintf (asm_out_file, "0:\n");
- /* vendor name: "GNU". */
- fprintf (asm_out_file, STRING_ASM_OP " \"GNU\"\n");
- fprintf (asm_out_file, "1:\n");
- ASM_OUTPUT_ALIGN (asm_out_file, p2align);
- /* pr_type: GNU_PROPERTY_X86_FEATURE_1_AND. */
- fprintf (asm_out_file, ASM_LONG " 0xc0000002\n");
- /* pr_datasz. */\
- fprintf (asm_out_file, ASM_LONG " 3f - 2f\n");
- fprintf (asm_out_file, "2:\n");
- /* GNU_PROPERTY_X86_FEATURE_1_XXX. */
- fprintf (asm_out_file, ASM_LONG " 0x%x\n", feature_1);
- fprintf (asm_out_file, "3:\n");
- ASM_OUTPUT_ALIGN (asm_out_file, p2align);
- fprintf (asm_out_file, "4:\n");
- }
-}
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 22d284e..d2d42f7 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -25,6 +25,7 @@
#define _CPUID_H_INCLUDED
/* %eax */
+#define bit_AVXVNNI (1 << 4)
#define bit_AVX512BF16 (1 << 5)
#define bit_HRESET (1 << 22)
@@ -119,6 +120,7 @@
#define bit_MOVDIR64B (1 << 28)
#define bit_ENQCMD (1 << 29)
#define bit_CLDEMOTE (1 << 25)
+#define bit_KL (1 << 23)
/* %edx */
#define bit_AVX5124VNNIW (1 << 2)
@@ -146,6 +148,12 @@
/* %ebx */
#define bit_PTWRITE (1 << 4)
+/* Keylocker leaf (%eax == 0x19) */
+/* %ebx */
+#define bit_AESKLE ( 1<<0 )
+#define bit_WIDEKL ( 1<<2 )
+
+
/* Signatures for different CPU implementations as returned in uses
of cpuid with level 0. */
#define signature_AMD_ebx 0x68747541
diff --git a/gcc/config/i386/cygming.opt b/gcc/config/i386/cygming.opt
index 73f1438..f9d6d97 100644
--- a/gcc/config/i386/cygming.opt
+++ b/gcc/config/i386/cygming.opt
@@ -27,7 +27,7 @@ Target RejectNegative
Generate code for a DLL.
mnop-fun-dllimport
-Target Report Var(TARGET_NOP_FUN_DLLIMPORT)
+Target Var(TARGET_NOP_FUN_DLLIMPORT)
Ignore dllimport for functions.
mthreads
@@ -51,14 +51,14 @@ Target Condition({defined (USE_CYGWIN_LIBSTDCXX_WRAPPERS)})
Compile code that relies on Cygwin DLL wrappers to support C++ operator new/delete replacement.
fset-stack-executable
-Common Report Var(flag_setstackexecutable) Init(1) Optimization
+Common Var(flag_setstackexecutable) Init(1) Optimization
For nested functions on stack executable permission is set.
posix
Driver
fwritable-relocated-rdata
-Common Report Var(flag_writable_rel_rdata) Init(0)
+Common Var(flag_writable_rel_rdata) Init(0)
Put relocated read-only data into .data section.
; Retain blank line above
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index ecdad57..2bfa037 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -455,6 +455,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
processor = PROCESSOR_GEODE;
else if (has_feature (FEATURE_MOVBE) && family == 22)
processor = PROCESSOR_BTVER2;
+ else if (has_feature (FEATURE_VAES))
+ processor = PROCESSOR_ZNVER3;
else if (has_feature (FEATURE_CLWB))
processor = PROCESSOR_ZNVER2;
else if (has_feature (FEATURE_CLZERO))
@@ -753,6 +755,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
case PROCESSOR_ZNVER2:
cpu = "znver2";
break;
+ case PROCESSOR_ZNVER3:
+ cpu = "znver3";
+ break;
case PROCESSOR_BTVER1:
cpu = "btver1";
break;
diff --git a/gcc/config/i386/gnu-property.c b/gcc/config/i386/gnu-property.c
new file mode 100644
index 0000000..1288325
--- /dev/null
+++ b/gcc/config/i386/gnu-property.c
@@ -0,0 +1,124 @@
+/* Functions for x86 GNU property.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "output.h"
+#include "linux-common.h"
+
+static void
+emit_gnu_property (unsigned int type, unsigned int data)
+{
+ int p2align = ptr_mode == SImode ? 2 : 3;
+
+ switch_to_section (get_section (".note.gnu.property",
+ SECTION_NOTYPE, NULL));
+
+ ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+ /* name length. */
+ fprintf (asm_out_file, ASM_LONG "1f - 0f\n");
+ /* data length. */
+ fprintf (asm_out_file, ASM_LONG "4f - 1f\n");
+ /* note type: NT_GNU_PROPERTY_TYPE_0. */
+ fprintf (asm_out_file, ASM_LONG "5\n");
+ fprintf (asm_out_file, "0:\n");
+ /* vendor name: "GNU". */
+ fprintf (asm_out_file, STRING_ASM_OP "\"GNU\"\n");
+ fprintf (asm_out_file, "1:\n");
+ ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+ /* pr_type. */
+ fprintf (asm_out_file, ASM_LONG "0x%x\n", type);
+ /* pr_datasz. */
+ fprintf (asm_out_file, ASM_LONG "3f - 2f\n");
+ fprintf (asm_out_file, "2:\n");
+ fprintf (asm_out_file, ASM_LONG "0x%x\n", data);
+ fprintf (asm_out_file, "3:\n");
+ ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+ fprintf (asm_out_file, "4:\n");
+}
+
+void
+file_end_indicate_exec_stack_and_gnu_property (void)
+{
+ file_end_indicate_exec_stack ();
+
+ if (flag_cf_protection == CF_NONE && !ix86_needed)
+ return;
+
+ unsigned int feature_1 = 0;
+
+ if (flag_cf_protection & CF_BRANCH)
+ /* GNU_PROPERTY_X86_FEATURE_1_IBT. */
+ feature_1 |= 0x1;
+
+ if (flag_cf_protection & CF_RETURN)
+ /* GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
+ feature_1 |= 0x2;
+
+ /* Generate GNU_PROPERTY_X86_FEATURE_1_AND. */
+ if (feature_1)
+ emit_gnu_property (0xc0000002, feature_1);
+
+ unsigned int isa_1 = 0;
+ if (ix86_needed)
+ {
+ /* GNU_PROPERTY_X86_ISA_1_BASELINE. */
+ if (TARGET_64BIT
+ || TARGET_FXSR
+ || TARGET_80387
+ || TARGET_MMX
+ || TARGET_SSE
+ || TARGET_SSE2)
+ isa_1 |= 1 << 0;
+
+ /* GNU_PROPERTY_X86_ISA_1_V2. */
+ if (TARGET_CMPXCHG16B
+ || (TARGET_64BIT && TARGET_SAHF)
+ || TARGET_POPCNT
+ || TARGET_SSE3
+ || TARGET_SSSE3
+ || TARGET_SSE4_1
+ || TARGET_SSE4_2)
+ isa_1 |= 1 << 1;
+
+ /* GNU_PROPERTY_X86_ISA_1_V3. */
+ if (TARGET_AVX
+ || TARGET_AVX2
+ || TARGET_F16C
+ || TARGET_FMA
+ || TARGET_LZCNT
+ || TARGET_MOVBE
+ || TARGET_XSAVE)
+ isa_1 |= 1 << 2;
+
+ /* GNU_PROPERTY_X86_ISA_1_V4. */
+ if (TARGET_AVX512F
+ || TARGET_AVX512BW
+ || TARGET_AVX512CD
+ || TARGET_AVX512DQ
+ || TARGET_AVX512VL)
+ isa_1 |= 1 << 3;
+ }
+
+ /* Generate GNU_PROPERTY_X86_ISA_1_NEEDED. */
+ if (isa_1)
+ emit_gnu_property (0xc0008002, isa_1);
+}
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 964633d..3ca313c 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -1290,3 +1290,10 @@ DEF_FUNCTION_TYPE (V8SF, V8SF, V16HI, V16HI)
DEF_FUNCTION_TYPE (V8SF, V8SF, V16HI, V16HI, UQI)
DEF_FUNCTION_TYPE (V4SF, V4SF, V8HI, V8HI)
DEF_FUNCTION_TYPE (V4SF, V4SF, V8HI, V8HI, UQI)
+
+# KEYLOCKER builtins
+DEF_FUNCTION_TYPE (UINT, UINT, V2DI, V2DI, PVOID)
+DEF_FUNCTION_TYPE (UINT, UINT, V2DI, PVOID)
+DEF_FUNCTION_TYPE (VOID, V2DI, V2DI, V2DI, UINT)
+DEF_FUNCTION_TYPE (UINT8, PV2DI, V2DI, PCVOID)
+DEF_FUNCTION_TYPE (UINT8, PV2DI, PCV2DI, PCVOID) \ No newline at end of file
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 882cba5..67d5f2ef 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -460,6 +460,19 @@ BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA2_UINTR, CODE_FOR_senduipi, "__buil
/* HRESET */
BDESC (0, OPTION_MASK_ISA2_HRESET, CODE_FOR_hreset, "__builtin_ia32_hreset", IX86_BUILTIN_HRESET, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
+/* KEYLOCKER */
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_loadiwkey", IX86_BUILTIN_LOADIWKEY, UNKNOWN, (int) VOID_FTYPE_V2DI_V2DI_V2DI_UINT)
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_aesdec128kl_u8", IX86_BUILTIN_AESDEC128KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_V2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_aesdec256kl_u8", IX86_BUILTIN_AESDEC256KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_V2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_aesenc128kl_u8", IX86_BUILTIN_AESENC128KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_V2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_aesenc256kl_u8", IX86_BUILTIN_AESENC256KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_V2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_encodekey128_u32", IX86_BUILTIN_ENCODEKEY128U32, UNKNOWN, (int) UINT_FTYPE_UINT_V2DI_PVOID)
+BDESC (0, OPTION_MASK_ISA2_KL, CODE_FOR_nothing, "__builtin_ia32_encodekey256_u32", IX86_BUILTIN_ENCODEKEY256U32, UNKNOWN, (int) UINT_FTYPE_UINT_V2DI_V2DI_PVOID)
+BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesdecwide128kl_u8", IX86_BUILTIN_AESDECWIDE128KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesdecwide256kl_u8", IX86_BUILTIN_AESDECWIDE256KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesencwide128kl_u8", IX86_BUILTIN_AESENCWIDE128KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesencwide256kl_u8", IX86_BUILTIN_AESENCWIDE256KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+
BDESC_END (SPECIAL_ARGS, ARGS)
/* Builtins with variable number of arguments. */
@@ -2613,45 +2626,45 @@ BDESC (OPTION_MASK_ISA_GFNI | OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA_AVX512B
BDESC (OPTION_MASK_ISA_GFNI | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_vgf2p8mulb_v16qi, "__builtin_ia32_vgf2p8mulb_v16qi", IX86_BUILTIN_VGF2P8MULB128, UNKNOWN, (int) V16QI_FTYPE_V16QI_V16QI)
BDESC (OPTION_MASK_ISA_GFNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vgf2p8mulb_v16qi_mask, "__builtin_ia32_vgf2p8mulb_v16qi_mask", IX86_BUILTIN_VGF2P8MULB128MASK, UNKNOWN, (int) V16QI_FTYPE_V16QI_V16QI_V16QI_UHI)
-/* VNNI */
+/* AVX512_VNNI */
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si, "__builtin_ia32_vpdpbusd_v16si", IX86_BUILTIN_VPDPBUSDV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si_mask, "__builtin_ia32_vpdpbusd_v16si_mask", IX86_BUILTIN_VPDPBUSDV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si_maskz, "__builtin_ia32_vpdpbusd_v16si_maskz", IX86_BUILTIN_VPDPBUSDV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si, "__builtin_ia32_vpdpbusd_v8si", IX86_BUILTIN_VPDPBUSDV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpbusd_v8si, "__builtin_ia32_vpdpbusd_v8si", IX86_BUILTIN_VPDPBUSDV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si_mask, "__builtin_ia32_vpdpbusd_v8si_mask", IX86_BUILTIN_VPDPBUSDV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si_maskz, "__builtin_ia32_vpdpbusd_v8si_maskz", IX86_BUILTIN_VPDPBUSDV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si, "__builtin_ia32_vpdpbusd_v4si", IX86_BUILTIN_VPDPBUSDV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpbusd_v4si, "__builtin_ia32_vpdpbusd_v4si", IX86_BUILTIN_VPDPBUSDV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si_mask, "__builtin_ia32_vpdpbusd_v4si_mask", IX86_BUILTIN_VPDPBUSDV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si_maskz, "__builtin_ia32_vpdpbusd_v4si_maskz", IX86_BUILTIN_VPDPBUSDV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si, "__builtin_ia32_vpdpbusds_v16si", IX86_BUILTIN_VPDPBUSDSV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si_mask, "__builtin_ia32_vpdpbusds_v16si_mask", IX86_BUILTIN_VPDPBUSDSV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si_maskz, "__builtin_ia32_vpdpbusds_v16si_maskz", IX86_BUILTIN_VPDPBUSDSV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si, "__builtin_ia32_vpdpbusds_v8si", IX86_BUILTIN_VPDPBUSDSV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpbusds_v8si, "__builtin_ia32_vpdpbusds_v8si", IX86_BUILTIN_VPDPBUSDSV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si_mask, "__builtin_ia32_vpdpbusds_v8si_mask", IX86_BUILTIN_VPDPBUSDSV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si_maskz, "__builtin_ia32_vpdpbusds_v8si_maskz", IX86_BUILTIN_VPDPBUSDSV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si, "__builtin_ia32_vpdpbusds_v4si", IX86_BUILTIN_VPDPBUSDSV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpbusds_v4si, "__builtin_ia32_vpdpbusds_v4si", IX86_BUILTIN_VPDPBUSDSV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si_mask, "__builtin_ia32_vpdpbusds_v4si_mask", IX86_BUILTIN_VPDPBUSDSV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si_maskz, "__builtin_ia32_vpdpbusds_v4si_maskz", IX86_BUILTIN_VPDPBUSDSV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si, "__builtin_ia32_vpdpwssd_v16si", IX86_BUILTIN_VPDPWSSDV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si_mask, "__builtin_ia32_vpdpwssd_v16si_mask", IX86_BUILTIN_VPDPWSSDV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si_maskz, "__builtin_ia32_vpdpwssd_v16si_maskz", IX86_BUILTIN_VPDPWSSDV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si, "__builtin_ia32_vpdpwssd_v8si", IX86_BUILTIN_VPDPWSSDV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpwssd_v8si, "__builtin_ia32_vpdpwssd_v8si", IX86_BUILTIN_VPDPWSSDV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si_mask, "__builtin_ia32_vpdpwssd_v8si_mask", IX86_BUILTIN_VPDPWSSDV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si_maskz, "__builtin_ia32_vpdpwssd_v8si_maskz", IX86_BUILTIN_VPDPWSSDV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si, "__builtin_ia32_vpdpwssd_v4si", IX86_BUILTIN_VPDPWSSDV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpwssd_v4si, "__builtin_ia32_vpdpwssd_v4si", IX86_BUILTIN_VPDPWSSDV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si_mask, "__builtin_ia32_vpdpwssd_v4si_mask", IX86_BUILTIN_VPDPWSSDV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si_maskz, "__builtin_ia32_vpdpwssd_v4si_maskz", IX86_BUILTIN_VPDPWSSDV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si, "__builtin_ia32_vpdpwssds_v16si", IX86_BUILTIN_VPDPWSSDSV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si_mask, "__builtin_ia32_vpdpwssds_v16si_mask", IX86_BUILTIN_VPDPWSSDSV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si_maskz, "__builtin_ia32_vpdpwssds_v16si_maskz", IX86_BUILTIN_VPDPWSSDSV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si, "__builtin_ia32_vpdpwssds_v8si", IX86_BUILTIN_VPDPWSSDSV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpwssds_v8si, "__builtin_ia32_vpdpwssds_v8si", IX86_BUILTIN_VPDPWSSDSV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si_mask, "__builtin_ia32_vpdpwssds_v8si_mask", IX86_BUILTIN_VPDPWSSDSV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si_maskz, "__builtin_ia32_vpdpwssds_v8si_maskz", IX86_BUILTIN_VPDPWSSDSV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI)
-BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si, "__builtin_ia32_vpdpwssds_v4si", IX86_BUILTIN_VPDPWSSDSV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
+BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVXVNNI, CODE_FOR_vpdpwssds_v4si, "__builtin_ia32_vpdpwssds_v4si", IX86_BUILTIN_VPDPWSSDSV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si_mask, "__builtin_ia32_vpdpwssds_v4si_mask", IX86_BUILTIN_VPDPWSSDSV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si_maskz, "__builtin_ia32_vpdpwssds_v4si_maskz", IX86_BUILTIN_VPDPWSSDSV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI)
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index 504987a..d8ec1e5 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -274,6 +274,10 @@ def_builtin (HOST_WIDE_INT mask, HOST_WIDE_INT mask2,
if (((mask2 == 0 || (mask2 & ix86_isa_flags2) != 0)
&& (mask == 0 || (mask & ix86_isa_flags) != 0))
|| ((mask & OPTION_MASK_ISA_MMX) != 0 && TARGET_MMX_WITH_SSE)
+ /* "Unified" builtin used by either AVXVNNI intrinsics or AVX512VNNIVL
+ non-mask intrinsics should be defined whenever avxvnni
+ or avx512vnni && avx512vl exist. */
+ || (mask2 == OPTION_MASK_ISA2_AVXVNNI)
|| (lang_hooks.builtin_function
== lang_hooks.builtin_function_ext_scope))
{
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index bbe9ac5..6d690e0 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -128,6 +128,10 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__znver2");
def_or_undef (parse_in, "__znver2__");
break;
+ case PROCESSOR_ZNVER3:
+ def_or_undef (parse_in, "__znver3");
+ def_or_undef (parse_in, "__znver3__");
+ break;
case PROCESSOR_BTVER1:
def_or_undef (parse_in, "__btver1");
def_or_undef (parse_in, "__btver1__");
@@ -315,6 +319,9 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
case PROCESSOR_ZNVER2:
def_or_undef (parse_in, "__tune_znver2__");
break;
+ case PROCESSOR_ZNVER3:
+ def_or_undef (parse_in, "__tune_znver3__");
+ break;
case PROCESSOR_BTVER1:
def_or_undef (parse_in, "__tune_btver1__");
break;
@@ -602,6 +609,12 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__UINTR__");
if (isa_flag2 & OPTION_MASK_ISA2_HRESET)
def_or_undef (parse_in, "__HRESET__");
+ if (isa_flag2 & OPTION_MASK_ISA2_KL)
+ def_or_undef (parse_in, "__KL__");
+ if (isa_flag2 & OPTION_MASK_ISA2_WIDEKL)
+ def_or_undef (parse_in, "__WIDEKL__");
+ if (isa_flag2 & OPTION_MASK_ISA2_AVXVNNI)
+ def_or_undef (parse_in, "__AVXVNNI__");
if (TARGET_IAMCU)
{
def_or_undef (parse_in, "__iamcu");
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 3e8afe6..6e08fd3 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -196,6 +196,17 @@ ix86_expand_move (machine_mode mode, rtx operands[])
op0 = operands[0];
op1 = operands[1];
+ /* Avoid complex sets of likely spilled hard registers before reload. */
+ if (!ix86_hardreg_mov_ok (op0, op1))
+ {
+ tmp = gen_reg_rtx (mode);
+ operands[0] = tmp;
+ ix86_expand_move (mode, operands);
+ operands[0] = op0;
+ operands[1] = tmp;
+ op1 = tmp;
+ }
+
switch (GET_CODE (op1))
{
case CONST:
@@ -7673,6 +7684,85 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
return true;
}
+/* Expand cmpstrn or memcmp. */
+
+bool
+ix86_expand_cmpstrn_or_cmpmem (rtx result, rtx src1, rtx src2,
+ rtx length, rtx align, bool is_cmpstrn)
+{
+ /* Expand strncmp and memcmp only with -minline-all-stringops since
+ "repz cmpsb" can be much slower than strncmp and memcmp functions
+ implemented with vector instructions, see
+
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
+ */
+ if (!TARGET_INLINE_ALL_STRINGOPS)
+ return false;
+
+ /* Can't use this if the user has appropriated ecx, esi or edi. */
+ if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ return false;
+
+ if (is_cmpstrn)
+ {
+ /* For strncmp, length is the maximum length, which can be larger
+ than actual string lengths. We can expand the cmpstrn pattern
+ to "repz cmpsb" only if one of the strings is a constant so
+ that expand_builtin_strncmp() can write the length argument to
+ be the minimum of the const string length and the actual length
+ argument. Otherwise, "repz cmpsb" may pass the 0 byte. */
+ tree t1 = MEM_EXPR (src1);
+ tree t2 = MEM_EXPR (src2);
+ if (!((t1 && TREE_CODE (t1) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0))
+ == STRING_CST))
+ || (t2 && TREE_CODE (t2) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0))
+ == STRING_CST))))
+ return false;
+ }
+
+ rtx addr1 = copy_addr_to_reg (XEXP (src1, 0));
+ rtx addr2 = copy_addr_to_reg (XEXP (src2, 0));
+ if (addr1 != XEXP (src1, 0))
+ src1 = replace_equiv_address_nv (src1, addr1);
+ if (addr2 != XEXP (src2, 0))
+ src2 = replace_equiv_address_nv (src2, addr2);
+
+ /* NB: Make a copy of the data length to avoid changing the original
+ data length by cmpstrnqi patterns. */
+ length = ix86_zero_extend_to_Pmode (length);
+ rtx lengthreg = gen_reg_rtx (Pmode);
+ emit_move_insn (lengthreg, length);
+
+ /* If we are testing strict equality, we can use known alignment to
+ good advantage. This may be possible with combine, particularly
+ once cc0 is dead. */
+ if (CONST_INT_P (length))
+ {
+ if (length == const0_rtx)
+ {
+ emit_move_insn (result, const0_rtx);
+ return true;
+ }
+ emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, lengthreg, align,
+ src1, src2));
+ }
+ else
+ {
+ emit_insn (gen_cmp_1 (Pmode, lengthreg, lengthreg));
+ emit_insn (gen_cmpstrnqi_1 (addr1, addr2, lengthreg, align,
+ src1, src2));
+ }
+
+ rtx out = gen_lowpart (QImode, result);
+ emit_insn (gen_cmpintqi (out));
+ emit_move_insn (result, gen_rtx_SIGN_EXTEND (SImode, out));
+
+ return true;
+}
/* Expand the appropriate insns for doing strlen if not just doing
repnz; scasb
@@ -7973,7 +8063,17 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
}
else if (!TARGET_PECOFF && !TARGET_MACHO)
{
- if (TARGET_64BIT)
+ if (TARGET_64BIT
+ && ix86_cmodel == CM_LARGE_PIC
+ && DEFAULT_ABI != MS_ABI)
+ {
+ fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+ UNSPEC_GOT);
+ fnaddr = gen_rtx_CONST (Pmode, fnaddr);
+ fnaddr = force_reg (Pmode, fnaddr);
+ fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, fnaddr);
+ }
+ else if (TARGET_64BIT)
{
fnaddr = gen_rtx_UNSPEC (Pmode,
gen_rtvec (1, addr),
@@ -8209,16 +8309,12 @@ ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
enum rtx_code sub_code)
{
rtx pat;
- int i;
- int nargs;
+ unsigned int i, nargs;
bool comparison_p = false;
bool tf_p = false;
bool last_arg_constant = false;
int num_memory = 0;
- struct {
- rtx op;
- machine_mode mode;
- } args[4];
+ rtx xops[4];
machine_mode tmode = insn_data[icode].operand[0].mode;
@@ -8312,7 +8408,7 @@ ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
else if (memory_operand (target, tmode))
num_memory++;
- gcc_assert (nargs <= 4);
+ gcc_assert (nargs <= ARRAY_SIZE (xops));
for (i = 0; i < nargs; i++)
{
@@ -8392,38 +8488,36 @@ ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
op = force_reg (mode, op);
}
- args[i].op = op;
- args[i].mode = mode;
+ xops[i] = op;
}
switch (nargs)
{
case 1:
- pat = GEN_FCN (icode) (target, args[0].op);
+ pat = GEN_FCN (icode) (target, xops[0]);
break;
case 2:
if (tf_p)
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
+ pat = GEN_FCN (icode) (target, xops[0], xops[1],
GEN_INT ((int)sub_code));
else if (! comparison_p)
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1]);
else
{
rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
- args[0].op,
- args[1].op);
+ xops[0], xops[1]);
- pat = GEN_FCN (icode) (target, cmp_op, args[0].op, args[1].op);
+ pat = GEN_FCN (icode) (target, cmp_op, xops[0], xops[1]);
}
break;
case 3:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
break;
case 4:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op, args[3].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
break;
default:
@@ -8903,11 +8997,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
unsigned int nargs_constant = 0;
unsigned int mask_pos = 0;
int num_memory = 0;
- struct
- {
- rtx op;
- machine_mode mode;
- } args[6];
+ rtx xops[6];
bool second_arg_count = false;
enum insn_code icode = d->icode;
const struct insn_data_d *insn_p = &insn_data[icode];
@@ -9667,7 +9757,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
gcc_unreachable ();
}
- gcc_assert (nargs <= ARRAY_SIZE (args));
+ gcc_assert (nargs <= ARRAY_SIZE (xops));
if (comparison != UNKNOWN)
{
@@ -9874,34 +9964,31 @@ ix86_expand_args_builtin (const struct builtin_description *d,
}
}
- args[i].op = op;
- args[i].mode = mode;
+ xops[i] = op;
}
switch (nargs)
{
case 1:
- pat = GEN_FCN (icode) (real_target, args[0].op);
+ pat = GEN_FCN (icode) (real_target, xops[0]);
break;
case 2:
- pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op);
+ pat = GEN_FCN (icode) (real_target, xops[0], xops[1]);
break;
case 3:
- pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
- args[2].op);
+ pat = GEN_FCN (icode) (real_target, xops[0], xops[1], xops[2]);
break;
case 4:
- pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
- args[2].op, args[3].op);
+ pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
+ xops[2], xops[3]);
break;
case 5:
- pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
- args[2].op, args[3].op, args[4].op);
+ pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
+ xops[2], xops[3], xops[4]);
break;
case 6:
- pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
- args[2].op, args[3].op, args[4].op,
- args[5].op);
+ pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
+ xops[2], xops[3], xops[4], xops[5]);
break;
default:
gcc_unreachable ();
@@ -10168,11 +10255,7 @@ ix86_expand_round_builtin (const struct builtin_description *d,
{
rtx pat;
unsigned int i, nargs;
- struct
- {
- rtx op;
- machine_mode mode;
- } args[6];
+ rtx xops[6];
enum insn_code icode = d->icode;
const struct insn_data_d *insn_p = &insn_data[icode];
machine_mode tmode = insn_p->operand[0].mode;
@@ -10272,7 +10355,7 @@ ix86_expand_round_builtin (const struct builtin_description *d,
default:
gcc_unreachable ();
}
- gcc_assert (nargs <= ARRAY_SIZE (args));
+ gcc_assert (nargs <= ARRAY_SIZE (xops));
if (optimize
|| target == 0
@@ -10344,34 +10427,31 @@ ix86_expand_round_builtin (const struct builtin_description *d,
}
}
- args[i].op = op;
- args[i].mode = mode;
+ xops[i] = op;
}
switch (nargs)
{
case 1:
- pat = GEN_FCN (icode) (target, args[0].op);
+ pat = GEN_FCN (icode) (target, xops[0]);
break;
case 2:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1]);
break;
case 3:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
- args[2].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
break;
case 4:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
- args[2].op, args[3].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1],
+ xops[2], xops[3]);
break;
case 5:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
- args[2].op, args[3].op, args[4].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1],
+ xops[2], xops[3], xops[4]);
break;
case 6:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
- args[2].op, args[3].op, args[4].op,
- args[5].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1],
+ xops[2], xops[3], xops[4], xops[5]);
break;
default:
gcc_unreachable ();
@@ -10398,13 +10478,8 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
rtx pat, op;
unsigned int i, nargs, arg_adjust, memory;
bool aligned_mem = false;
- struct
- {
- rtx op;
- machine_mode mode;
- } args[3];
+ rtx xops[3];
enum insn_code icode = d->icode;
- bool last_arg_constant = false;
const struct insn_data_d *insn_p = &insn_data[icode];
machine_mode tmode = insn_p->operand[0].mode;
enum { load, store } klass;
@@ -10477,7 +10552,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
nargs = 1;
klass = store;
/* Reserve memory operand for target. */
- memory = ARRAY_SIZE (args);
+ memory = ARRAY_SIZE (xops);
switch (icode)
{
/* These builtins and instructions require the memory
@@ -10614,7 +10689,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
nargs = 2;
klass = store;
/* Reserve memory operand for target. */
- memory = ARRAY_SIZE (args);
+ memory = ARRAY_SIZE (xops);
break;
case V4SF_FTYPE_PCV4SF_V4SF_UQI:
case V8SF_FTYPE_PCV8SF_V8SF_UQI:
@@ -10688,7 +10763,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
gcc_unreachable ();
}
- gcc_assert (nargs <= ARRAY_SIZE (args));
+ gcc_assert (nargs <= ARRAY_SIZE (xops));
if (klass == store)
{
@@ -10728,59 +10803,51 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
for (i = 0; i < nargs; i++)
{
machine_mode mode = insn_p->operand[i + 1].mode;
- bool match;
arg = CALL_EXPR_ARG (exp, i + arg_adjust);
op = expand_normal (arg);
- match = insn_p->operand[i + 1].predicate (op, mode);
- if (last_arg_constant && (i + 1) == nargs)
+ if (i == memory)
{
- if (!match)
- {
- error ("the last argument must be an 8-bit immediate");
- return const0_rtx;
- }
+ /* This must be the memory operand. */
+ op = ix86_zero_extend_to_Pmode (op);
+ op = gen_rtx_MEM (mode, op);
+ /* op at this point has just BITS_PER_UNIT MEM_ALIGN
+ on it. Try to improve it using get_pointer_alignment,
+ and if the special builtin is one that requires strict
+ mode alignment, also from it's GET_MODE_ALIGNMENT.
+ Failure to do so could lead to ix86_legitimate_combined_insn
+ rejecting all changes to such insns. */
+ unsigned int align = get_pointer_alignment (arg);
+ if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
+ align = GET_MODE_ALIGNMENT (mode);
+ if (MEM_ALIGN (op) < align)
+ set_mem_align (op, align);
}
else
{
- if (i == memory)
- {
- /* This must be the memory operand. */
- op = ix86_zero_extend_to_Pmode (op);
- op = gen_rtx_MEM (mode, op);
- /* op at this point has just BITS_PER_UNIT MEM_ALIGN
- on it. Try to improve it using get_pointer_alignment,
- and if the special builtin is one that requires strict
- mode alignment, also from it's GET_MODE_ALIGNMENT.
- Failure to do so could lead to ix86_legitimate_combined_insn
- rejecting all changes to such insns. */
- unsigned int align = get_pointer_alignment (arg);
- if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
- align = GET_MODE_ALIGNMENT (mode);
- if (MEM_ALIGN (op) < align)
- set_mem_align (op, align);
- }
- else
- {
- /* This must be register. */
- if (VECTOR_MODE_P (mode))
- op = safe_vector_operand (op, mode);
+ /* This must be register. */
+ if (VECTOR_MODE_P (mode))
+ op = safe_vector_operand (op, mode);
- op = fixup_modeless_constant (op, mode);
+ op = fixup_modeless_constant (op, mode);
- if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- op = copy_to_mode_reg (mode, op);
- else
- {
- op = copy_to_reg (op);
- op = lowpart_subreg (mode, op, GET_MODE (op));
- }
+ /* NB: 3-operands load implied it's a mask load,
+ and that mask operand shoud be at the end.
+ Keep all-ones mask which would be simplified by the expander. */
+ if (nargs == 3 && i == 2 && klass == load
+ && constm1_operand (op, mode))
+ ;
+ else if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
+ op = copy_to_mode_reg (mode, op);
+ else
+ {
+ op = copy_to_reg (op);
+ op = lowpart_subreg (mode, op, GET_MODE (op));
}
}
- args[i].op = op;
- args[i].mode = mode;
+ xops[i]= op;
}
switch (nargs)
@@ -10789,13 +10856,13 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
pat = GEN_FCN (icode) (target);
break;
case 1:
- pat = GEN_FCN (icode) (target, args[0].op);
+ pat = GEN_FCN (icode) (target, xops[0]);
break;
case 2:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1]);
break;
case 3:
- pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
+ pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
break;
default:
gcc_unreachable ();
@@ -10803,6 +10870,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
if (! pat)
return 0;
+
emit_insn (pat);
return klass == store ? 0 : target;
}
@@ -10980,6 +11048,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A
OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32
OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4
+ (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL) or
+ OPTION_MASK_ISA2_AVXVNNI
where for each such pair it is sufficient if either of the ISAs is
enabled, plus if it is ored with other options also those others.
OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */
@@ -10987,19 +11057,36 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
== (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A))
&& (isa & (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A)) != 0)
isa |= (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A);
+
if (((bisa & (OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32))
== (OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32))
&& (isa & (OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32)) != 0)
isa |= (OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32);
+
if (((bisa & (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4))
== (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4))
&& (isa & (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4)) != 0)
isa |= (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4);
- if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE)
+
+ if ((((bisa & (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL))
+ == (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL))
+ || (bisa2 & OPTION_MASK_ISA2_AVXVNNI) != 0)
+ && (((isa & (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL))
+ == (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL))
+ || (isa2 & OPTION_MASK_ISA2_AVXVNNI) != 0))
+ {
+ isa |= OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL;
+ isa2 |= OPTION_MASK_ISA2_AVXVNNI;
+ }
+
+ if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE
+ /* __builtin_ia32_maskmovq requires MMX registers. */
+ && fcode != IX86_BUILTIN_MASKMOVQ)
{
bisa &= ~OPTION_MASK_ISA_MMX;
bisa |= OPTION_MASK_ISA_SSE2;
}
+
if ((bisa & isa) != bisa || (bisa2 & isa2) != bisa2)
{
bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
@@ -11247,6 +11334,226 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
emit_insn (gen_cldemote (op0));
return 0;
+ case IX86_BUILTIN_LOADIWKEY:
+ {
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
+ arg3 = CALL_EXPR_ARG (exp, 3);
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+ op3 = expand_normal (arg3);
+
+ if (!REG_P (op0))
+ op0 = copy_to_mode_reg (V2DImode, op0);
+ if (!REG_P (op1))
+ op1 = copy_to_mode_reg (V2DImode, op1);
+ if (!REG_P (op2))
+ op2 = copy_to_mode_reg (V2DImode, op2);
+ if (!REG_P (op3))
+ op3 = copy_to_mode_reg (SImode, op3);
+
+ emit_insn (gen_loadiwkey (op0, op1, op2, op3));
+
+ return 0;
+ }
+
+ case IX86_BUILTIN_AESDEC128KLU8:
+ icode = CODE_FOR_aesdec128klu8;
+ goto aesdecenc_expand;
+
+ case IX86_BUILTIN_AESDEC256KLU8:
+ icode = CODE_FOR_aesdec256klu8;
+ goto aesdecenc_expand;
+
+ case IX86_BUILTIN_AESENC128KLU8:
+ icode = CODE_FOR_aesenc128klu8;
+ goto aesdecenc_expand;
+
+ case IX86_BUILTIN_AESENC256KLU8:
+ icode = CODE_FOR_aesenc256klu8;
+
+ aesdecenc_expand:
+
+ arg0 = CALL_EXPR_ARG (exp, 0); // __m128i *odata
+ arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
+ arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+
+ if (!address_operand (op0, V2DImode))
+ {
+ op0 = convert_memory_address (Pmode, op0);
+ op0 = copy_addr_to_reg (op0);
+ }
+ op0 = gen_rtx_MEM (V2DImode, op0);
+
+ if (!REG_P (op1))
+ op1 = copy_to_mode_reg (V2DImode, op1);
+
+ if (!address_operand (op2, VOIDmode))
+ {
+ op2 = convert_memory_address (Pmode, op2);
+ op2 = copy_addr_to_reg (op2);
+ }
+ op2 = gen_rtx_MEM (BLKmode, op2);
+
+ emit_insn (GEN_FCN (icode) (op1, op1, op2));
+
+ if (target == 0)
+ target = gen_reg_rtx (QImode);
+
+ pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCZmode, FLAGS_REG),
+ const0_rtx);
+ emit_insn (gen_rtx_SET (target, pat));
+
+ emit_insn (gen_rtx_SET (op0, op1));
+
+ return target;
+
+ case IX86_BUILTIN_AESDECWIDE128KLU8:
+ icode = CODE_FOR_aesdecwide128klu8;
+ goto wideaesdecenc_expand;
+
+ case IX86_BUILTIN_AESDECWIDE256KLU8:
+ icode = CODE_FOR_aesdecwide256klu8;
+ goto wideaesdecenc_expand;
+
+ case IX86_BUILTIN_AESENCWIDE128KLU8:
+ icode = CODE_FOR_aesencwide128klu8;
+ goto wideaesdecenc_expand;
+
+ case IX86_BUILTIN_AESENCWIDE256KLU8:
+ icode = CODE_FOR_aesencwide256klu8;
+
+ wideaesdecenc_expand:
+
+ rtx xmm_regs[8];
+ rtx op;
+
+ arg0 = CALL_EXPR_ARG (exp, 0); // __m128i * odata
+ arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
+ arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+
+ if (!address_operand (op2, VOIDmode))
+ {
+ op2 = convert_memory_address (Pmode, op2);
+ op2 = copy_addr_to_reg (op2);
+ }
+ op2 = gen_rtx_MEM (BLKmode, op2);
+
+ for (i = 0; i < 8; i++)
+ {
+ xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
+
+ op = gen_rtx_MEM (V2DImode,
+ plus_constant (Pmode, op1, (i * 16)));
+
+ emit_move_insn (xmm_regs[i], op);
+ }
+
+ emit_insn (GEN_FCN (icode) (op2));
+
+ if (target == 0)
+ target = gen_reg_rtx (QImode);
+
+ pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCZmode, FLAGS_REG),
+ const0_rtx);
+ emit_insn (gen_rtx_SET (target, pat));
+
+ for (i = 0; i < 8; i++)
+ {
+ op = gen_rtx_MEM (V2DImode,
+ plus_constant (Pmode, op0, (i * 16)));
+ emit_move_insn (op, xmm_regs[i]);
+ }
+
+ return target;
+
+ case IX86_BUILTIN_ENCODEKEY128U32:
+ {
+ rtx op, xmm_regs[7];
+
+ arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
+ arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
+ arg2 = CALL_EXPR_ARG (exp, 2); // void *h
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+
+ if (!REG_P (op0))
+ op0 = copy_to_mode_reg (SImode, op0);
+
+ op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
+ emit_move_insn (op, op1);
+
+ for (i = 0; i < 3; i++)
+ xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
+
+ if (target == 0)
+ target = gen_reg_rtx (SImode);
+
+ emit_insn (gen_encodekey128u32 (target, op0));
+
+ for (i = 0; i < 3; i++)
+ {
+ op = gen_rtx_MEM (V2DImode,
+ plus_constant (Pmode, op2, (i * 16)));
+ emit_move_insn (op, xmm_regs[i]);
+ }
+
+ return target;
+ }
+ case IX86_BUILTIN_ENCODEKEY256U32:
+ {
+ rtx op, xmm_regs[7];
+
+ arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
+ arg1 = CALL_EXPR_ARG (exp, 1); // __m128i keylow
+ arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
+ arg3 = CALL_EXPR_ARG (exp, 3); // void *h
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+ op3 = expand_normal (arg3);
+
+ if (!REG_P (op0))
+ op0 = copy_to_mode_reg (SImode, op0);
+
+ /* Force to use xmm0, xmm1 for keylow, keyhi*/
+ op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
+ emit_move_insn (op, op1);
+ op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (1));
+ emit_move_insn (op, op2);
+
+ for (i = 0; i < 4; i++)
+ xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
+
+ if (target == 0)
+ target = gen_reg_rtx (SImode);
+
+ emit_insn (gen_encodekey256u32 (target, op0));
+
+ for (i = 0; i < 4; i++)
+ {
+ op = gen_rtx_MEM (V2DImode,
+ plus_constant (Pmode, op3, (i * 16)));
+ emit_move_insn (op, xmm_regs[i]);
+ }
+
+ return target;
+ }
+
case IX86_BUILTIN_VEC_INIT_V2SI:
case IX86_BUILTIN_VEC_INIT_V4HI:
case IX86_BUILTIN_VEC_INIT_V8QI:
@@ -14235,6 +14542,112 @@ ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
}
+/* Implemented as
+ V setg (V v, int idx, T val)
+ {
+ V idxv = (V){idx, idx, idx, idx, idx, idx, idx, idx};
+ V valv = (V){val, val, val, val, val, val, val, val};
+ V mask = ((V){0, 1, 2, 3, 4, 5, 6, 7} == idxv);
+ v = (v & ~mask) | (valv & mask);
+ return v;
+ }. */
+void
+ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
+{
+ rtx vec[64];
+ machine_mode mode = GET_MODE (target);
+ machine_mode cmp_mode = mode;
+ int n_elts = GET_MODE_NUNITS (mode);
+ rtx valv,idxv,constv,idx_tmp;
+ bool ok = false;
+
+ /* 512-bits vector byte/word broadcast and comparison only available
+ under TARGET_AVX512BW, break 512-bits vector into two 256-bits vector
+ when without TARGET_AVX512BW. */
+ if ((mode == V32HImode || mode == V64QImode) && !TARGET_AVX512BW)
+ {
+ gcc_assert (TARGET_AVX512F);
+ rtx vhi, vlo, idx_hi;
+ machine_mode half_mode;
+ rtx (*extract_hi)(rtx, rtx);
+ rtx (*extract_lo)(rtx, rtx);
+
+ if (mode == V32HImode)
+ {
+ half_mode = V16HImode;
+ extract_hi = gen_vec_extract_hi_v32hi;
+ extract_lo = gen_vec_extract_lo_v32hi;
+ }
+ else
+ {
+ half_mode = V32QImode;
+ extract_hi = gen_vec_extract_hi_v64qi;
+ extract_lo = gen_vec_extract_lo_v64qi;
+ }
+
+ vhi = gen_reg_rtx (half_mode);
+ vlo = gen_reg_rtx (half_mode);
+ idx_hi = gen_reg_rtx (GET_MODE (idx));
+ emit_insn (extract_hi (vhi, target));
+ emit_insn (extract_lo (vlo, target));
+ vec[0] = idx_hi;
+ vec[1] = idx;
+ vec[2] = GEN_INT (n_elts/2);
+ ix86_expand_binary_operator (MINUS, GET_MODE (idx), vec);
+ ix86_expand_vector_set_var (vhi, val, idx_hi);
+ ix86_expand_vector_set_var (vlo, val, idx);
+ emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, vlo, vhi)));
+ return;
+ }
+
+ if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
+ {
+ switch (mode)
+ {
+ case E_V2DFmode:
+ cmp_mode = V2DImode;
+ break;
+ case E_V4DFmode:
+ cmp_mode = V4DImode;
+ break;
+ case E_V8DFmode:
+ cmp_mode = V8DImode;
+ break;
+ case E_V4SFmode:
+ cmp_mode = V4SImode;
+ break;
+ case E_V8SFmode:
+ cmp_mode = V8SImode;
+ break;
+ case E_V16SFmode:
+ cmp_mode = V16SImode;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ for (int i = 0; i != n_elts; i++)
+ vec[i] = GEN_INT (i);
+ constv = gen_rtx_CONST_VECTOR (cmp_mode, gen_rtvec_v (n_elts, vec));
+ valv = gen_reg_rtx (mode);
+ idxv = gen_reg_rtx (cmp_mode);
+ idx_tmp = convert_to_mode (GET_MODE_INNER (cmp_mode), idx, 1);
+
+ ok = ix86_expand_vector_init_duplicate (false, mode, valv, val);
+ gcc_assert (ok);
+ ok = ix86_expand_vector_init_duplicate (false, cmp_mode, idxv, idx_tmp);
+ gcc_assert (ok);
+ vec[0] = target;
+ vec[1] = valv;
+ vec[2] = target;
+ vec[3] = gen_rtx_EQ (mode, idxv, constv);
+ vec[4] = idxv;
+ vec[5] = constv;
+ ok = ix86_expand_int_vcond (vec);
+ gcc_assert (ok);
+}
+
void
ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
{
@@ -15801,8 +16214,8 @@ void
ix86_expand_lround (rtx op0, rtx op1)
{
/* C code for the stuff we're doing below:
- tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
- return (long)tmp;
+ tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
+ return (long)tmp;
*/
machine_mode mode = GET_MODE (op1);
const struct real_format *fmt;
@@ -15833,8 +16246,8 @@ ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
{
/* C code for the stuff we're doing below (for do_floor):
xi = (long)op1;
- xi -= (double)xi > op1 ? 1 : 0;
- return xi;
+ xi -= (double)xi > op1 ? 1 : 0;
+ return xi;
*/
machine_mode fmode = GET_MODE (op1);
machine_mode imode = GET_MODE (op0);
@@ -15868,10 +16281,12 @@ ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
static rtx
ix86_gen_TWO52 (machine_mode mode)
{
+ const struct real_format *fmt;
REAL_VALUE_TYPE TWO52r;
rtx TWO52;
- real_ldexp (&TWO52r, &dconst1, mode == DFmode ? 52 : 23);
+ fmt = REAL_MODE_FORMAT (mode);
+ real_2expN (&TWO52r, fmt->p - 1, mode);
TWO52 = const_double_from_real_value (TWO52r, mode);
TWO52 = force_reg (mode, TWO52);
@@ -15885,41 +16300,45 @@ ix86_expand_rint (rtx operand0, rtx operand1)
{
/* C code for the stuff we're doing below:
xa = fabs (operand1);
- if (!isless (xa, 2**52))
+ if (!isless (xa, 2**52))
return operand1;
- two52 = 2**52;
- if (flag_rounding_math)
+ two52 = 2**52;
+ if (flag_rounding_math)
{
two52 = copysign (two52, operand1);
xa = operand1;
}
- xa = xa + two52 - two52;
- return copysign (xa, operand1);
+ xa = xa + two52 - two52;
+ return copysign (xa, operand1);
*/
machine_mode mode = GET_MODE (operand0);
- rtx res, xa, TWO52, two52, mask;
+ rtx res, xa, TWO52, mask;
rtx_code_label *label;
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ TWO52 = ix86_gen_TWO52 (mode);
+
+ /* Temporary for holding the result, initialized to the input
+ operand to ease control flow. */
+ res = copy_to_reg (operand1);
/* xa = abs (operand1) */
xa = ix86_expand_sse_fabs (res, &mask);
/* if (!isless (xa, TWO52)) goto label; */
- TWO52 = ix86_gen_TWO52 (mode);
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
- two52 = TWO52;
if (flag_rounding_math)
{
- two52 = gen_reg_rtx (mode);
- ix86_sse_copysign_to_positive (two52, TWO52, res, mask);
+ ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
xa = res;
}
- xa = expand_simple_binop (mode, PLUS, xa, two52, NULL_RTX, 0, OPTAB_DIRECT);
- xa = expand_simple_binop (mode, MINUS, xa, two52, xa, 0, OPTAB_DIRECT);
+ xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
+ xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
+
+ /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
+ if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
+ xa = ix86_expand_sse_fabs (xa, NULL);
ix86_sse_copysign_to_positive (res, xa, res, mask);
@@ -15936,15 +16355,17 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
{
/* C code for the stuff we expand below.
double xa = fabs (x), x2;
- if (!isless (xa, TWO52))
- return x;
+ if (!isless (xa, TWO52))
+ return x;
x2 = (double)(long)x;
+
Compensate. Floor:
if (x2 > x)
x2 -= 1;
Compensate. Ceil:
if (x2 < x)
x2 += 1;
+
if (HONOR_SIGNED_ZEROS (mode))
return copysign (x2, x);
return x2;
@@ -15957,8 +16378,7 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
/* Temporary for holding the result, initialized to the input
operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ res = copy_to_reg (operand1);
/* xa = abs (operand1) */
xa = ix86_expand_sse_fabs (res, &mask);
@@ -15967,7 +16387,7 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
/* xa = (double)(long)x */
- xi = gen_reg_rtx (mode == DFmode ? DImode : SImode);
+ xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
expand_fix (xi, res, 0);
expand_float (xa, xi, 0);
@@ -15979,10 +16399,15 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
- emit_move_insn (res, tmp);
-
if (HONOR_SIGNED_ZEROS (mode))
- ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), mask);
+ {
+ /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
+ if (do_floor && flag_rounding_math)
+ tmp = ix86_expand_sse_fabs (tmp, NULL);
+
+ ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ }
+ emit_move_insn (res, tmp);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -15997,17 +16422,19 @@ void
ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
{
/* C code for the stuff we expand below.
- double xa = fabs (x), x2;
- if (!isless (xa, TWO52))
- return x;
- xa = xa + TWO52 - TWO52;
- x2 = copysign (xa, x);
+ double xa = fabs (x), x2;
+ if (!isless (xa, TWO52))
+ return x;
+ xa = xa + TWO52 - TWO52;
+ x2 = copysign (xa, x);
+
Compensate. Floor:
- if (x2 > x)
- x2 -= 1;
+ if (x2 > x)
+ x2 -= 1;
Compensate. Ceil:
- if (x2 < x)
- x2 += 1;
+ if (x2 < x)
+ x2 += 1;
+
if (HONOR_SIGNED_ZEROS (mode))
x2 = copysign (x2, x);
return x2;
@@ -16020,8 +16447,7 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
/* Temporary for holding the result, initialized to the input
operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ res = copy_to_reg (operand1);
/* xa = abs (operand1) */
xa = ix86_expand_sse_fabs (res, &mask);
@@ -16044,8 +16470,14 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
- if (!do_floor && HONOR_SIGNED_ZEROS (mode))
- ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ if (HONOR_SIGNED_ZEROS (mode))
+ {
+ /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
+ if (do_floor && flag_rounding_math)
+ tmp = ix86_expand_sse_fabs (tmp, NULL);
+
+ ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ }
emit_move_insn (res, tmp);
emit_label (label);
@@ -16060,10 +16492,10 @@ void
ix86_expand_trunc (rtx operand0, rtx operand1)
{
/* C code for SSE variant we expand below.
- double xa = fabs (x), x2;
- if (!isless (xa, TWO52))
- return x;
- x2 = (double)(long)x;
+ double xa = fabs (x), x2;
+ if (!isless (xa, TWO52))
+ return x;
+ x2 = (double)(long)x;
if (HONOR_SIGNED_ZEROS (mode))
return copysign (x2, x);
return x2;
@@ -16076,8 +16508,7 @@ ix86_expand_trunc (rtx operand0, rtx operand1)
/* Temporary for holding the result, initialized to the input
operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ res = copy_to_reg (operand1);
/* xa = abs (operand1) */
xa = ix86_expand_sse_fabs (res, &mask);
@@ -16085,13 +16516,15 @@ ix86_expand_trunc (rtx operand0, rtx operand1)
/* if (!isless (xa, TWO52)) goto label; */
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
- /* x = (double)(long)x */
- xi = gen_reg_rtx (mode == DFmode ? DImode : SImode);
+ /* xa = (double)(long)x */
+ xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
expand_fix (xi, res, 0);
- expand_float (res, xi, 0);
+ expand_float (xa, xi, 0);
if (HONOR_SIGNED_ZEROS (mode))
- ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), mask);
+ ix86_sse_copysign_to_positive (xa, xa, res, mask);
+
+ emit_move_insn (res, xa);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -16106,51 +16539,51 @@ void
ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
{
machine_mode mode = GET_MODE (operand0);
- rtx xa, mask, TWO52, one, res, smask, tmp;
+ rtx xa, xa2, TWO52, tmp, one, res, mask;
rtx_code_label *label;
/* C code for SSE variant we expand below.
- double xa = fabs (x), x2;
- if (!isless (xa, TWO52))
- return x;
- xa2 = xa + TWO52 - TWO52;
+ double xa = fabs (x), x2;
+ if (!isless (xa, TWO52))
+ return x;
+ xa2 = xa + TWO52 - TWO52;
Compensate:
- if (xa2 > xa)
- xa2 -= 1.0;
- x2 = copysign (xa2, x);
- return x2;
+ if (xa2 > xa)
+ xa2 -= 1.0;
+ x2 = copysign (xa2, x);
+ return x2;
*/
TWO52 = ix86_gen_TWO52 (mode);
/* Temporary for holding the result, initialized to the input
operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ res =copy_to_reg (operand1);
/* xa = abs (operand1) */
- xa = ix86_expand_sse_fabs (res, &smask);
+ xa = ix86_expand_sse_fabs (res, &mask);
/* if (!isless (xa, TWO52)) goto label; */
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
- /* res = xa + TWO52 - TWO52; */
- tmp = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
- tmp = expand_simple_binop (mode, MINUS, tmp, TWO52, tmp, 0, OPTAB_DIRECT);
- emit_move_insn (res, tmp);
+ /* xa2 = xa + TWO52 - TWO52; */
+ xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
+ xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
/* generate 1.0 */
one = force_reg (mode, const_double_from_real_value (dconst1, mode));
- /* Compensate: res = xa2 - (res > xa ? 1 : 0) */
- mask = ix86_expand_sse_compare_mask (UNGT, res, xa, false);
- emit_insn (gen_rtx_SET (mask, gen_rtx_AND (mode, mask, one)));
+ /* Compensate: xa2 = xa2 - (xa2 > xa ? 1 : 0) */
+ tmp = ix86_expand_sse_compare_mask (UNGT, xa2, xa, false);
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
tmp = expand_simple_binop (mode, MINUS,
- res, mask, NULL_RTX, 0, OPTAB_DIRECT);
- emit_move_insn (res, tmp);
+ xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
+ /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
+ if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
+ tmp = ix86_expand_sse_fabs (tmp, NULL);
- /* res = copysign (res, operand1) */
- ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), smask);
+ /* res = copysign (xa2, operand1) */
+ ix86_sse_copysign_to_positive (res, tmp, res, mask);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -16164,11 +16597,11 @@ void
ix86_expand_round (rtx operand0, rtx operand1)
{
/* C code for the stuff we're doing below:
- double xa = fabs (x);
- if (!isless (xa, TWO52))
- return x;
- xa = (double)(long)(xa + nextafter (0.5, 0.0));
- return copysign (xa, x);
+ double xa = fabs (x);
+ if (!isless (xa, TWO52))
+ return x;
+ xa = (double)(long)(xa + nextafter (0.5, 0.0));
+ return copysign (xa, x);
*/
machine_mode mode = GET_MODE (operand0);
rtx res, TWO52, xa, xi, half, mask;
@@ -16178,8 +16611,7 @@ ix86_expand_round (rtx operand0, rtx operand1)
/* Temporary for holding the result, initialized to the input
operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ res = copy_to_reg (operand1);
TWO52 = ix86_gen_TWO52 (mode);
xa = ix86_expand_sse_fabs (res, &mask);
@@ -16195,12 +16627,12 @@ ix86_expand_round (rtx operand0, rtx operand1)
xa = expand_simple_binop (mode, PLUS, xa, half, NULL_RTX, 0, OPTAB_DIRECT);
/* xa = (double)(int64_t)xa */
- xi = gen_reg_rtx (mode == DFmode ? DImode : SImode);
+ xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
expand_fix (xi, xa, 0);
expand_float (xa, xi, 0);
/* res = copysign (xa, operand1) */
- ix86_sse_copysign_to_positive (res, xa, force_reg (mode, operand1), mask);
+ ix86_sse_copysign_to_positive (res, xa, res, mask);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -16215,20 +16647,20 @@ void
ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
{
/* C code for the stuff we expand below.
- double xa = fabs (x), xa2, x2;
- if (!isless (xa, TWO52))
- return x;
+ double xa = fabs (x), xa2, x2;
+ if (!isless (xa, TWO52))
+ return x;
Using the absolute value and copying back sign makes
-0.0 -> -0.0 correct.
- xa2 = xa + TWO52 - TWO52;
+ xa2 = xa + TWO52 - TWO52;
Compensate.
dxa = xa2 - xa;
- if (dxa <= -0.5)
- xa2 += 1;
- else if (dxa > 0.5)
- xa2 -= 1;
- x2 = copysign (xa2, x);
- return x2;
+ if (dxa <= -0.5)
+ xa2 += 1;
+ else if (dxa > 0.5)
+ xa2 -= 1;
+ x2 = copysign (xa2, x);
+ return x2;
*/
machine_mode mode = GET_MODE (operand0);
rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
@@ -16238,8 +16670,7 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
/* Temporary for holding the result, initialized to the input
operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
+ res = copy_to_reg (operand1);
/* xa = abs (operand1) */
xa = ix86_expand_sse_fabs (res, &mask);
@@ -16271,7 +16702,7 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
/* res = copysign (xa2, operand1) */
- ix86_sse_copysign_to_positive (res, xa2, force_reg (mode, operand1), mask);
+ ix86_sse_copysign_to_positive (res, xa2, res, mask);
emit_label (label);
LABEL_NUSES (label) = 1;
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index 620f7f1..c61685b 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -581,7 +581,8 @@ general_scalar_chain::compute_convert_gain ()
else if (GET_CODE (src) == NEG
|| GET_CODE (src) == NOT)
igain += m * ix86_cost->add - ix86_cost->sse_op - COSTS_N_INSNS (1);
- else if (GET_CODE (src) == SMAX
+ else if (GET_CODE (src) == ABS
+ || GET_CODE (src) == SMAX
|| GET_CODE (src) == SMIN
|| GET_CODE (src) == UMAX
|| GET_CODE (src) == UMIN)
@@ -986,13 +987,6 @@ general_scalar_chain::convert_insn (rtx_insn *insn)
switch (GET_CODE (src))
{
- case ASHIFT:
- case ASHIFTRT:
- case LSHIFTRT:
- convert_op (&XEXP (src, 0), insn);
- PUT_MODE (src, vmode);
- break;
-
case PLUS:
case MINUS:
case IOR:
@@ -1002,8 +996,14 @@ general_scalar_chain::convert_insn (rtx_insn *insn)
case SMIN:
case UMAX:
case UMIN:
- convert_op (&XEXP (src, 0), insn);
convert_op (&XEXP (src, 1), insn);
+ /* FALLTHRU */
+
+ case ABS:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ convert_op (&XEXP (src, 0), insn);
PUT_MODE (src, vmode);
break;
@@ -1266,9 +1266,10 @@ pseudo_reg_set (rtx_insn *insn)
return NULL;
/* Check pseudo register push first. */
+ machine_mode mode = TARGET_64BIT ? TImode : DImode;
if (REG_P (SET_SRC (set))
&& !HARD_REGISTER_P (SET_SRC (set))
- && push_operand (SET_DEST (set), GET_MODE (SET_DEST (set))))
+ && push_operand (SET_DEST (set), mode))
return set;
df_ref ref;
@@ -1414,6 +1415,12 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode)
return false;
break;
+ case ABS:
+ if ((mode == DImode && !TARGET_AVX512VL)
+ || (mode == SImode && !TARGET_SSSE3))
+ return false;
+ break;
+
case NEG:
case NOT:
break;
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index 82c8091..2999b61 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -147,11 +147,12 @@ along with GCC; see the file COPYING3. If not see
#define m_BDVER4 (HOST_WIDE_INT_1U<<PROCESSOR_BDVER4)
#define m_ZNVER1 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER1)
#define m_ZNVER2 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER2)
+#define m_ZNVER3 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER3)
#define m_BTVER1 (HOST_WIDE_INT_1U<<PROCESSOR_BTVER1)
#define m_BTVER2 (HOST_WIDE_INT_1U<<PROCESSOR_BTVER2)
#define m_BDVER (m_BDVER1 | m_BDVER2 | m_BDVER3 | m_BDVER4)
#define m_BTVER (m_BTVER1 | m_BTVER2)
-#define m_ZNVER (m_ZNVER1 | m_ZNVER2)
+#define m_ZNVER (m_ZNVER1 | m_ZNVER2 | m_ZNVER3)
#define m_AMD_MULTIPLE (m_ATHLON_K8 | m_AMDFAM10 | m_BDVER | m_BTVER \
| m_ZNVER)
@@ -214,7 +215,10 @@ static struct ix86_target_opts isa2_opts[] =
{ "-mamx-int8", OPTION_MASK_ISA2_AMX_INT8 },
{ "-mamx-bf16", OPTION_MASK_ISA2_AMX_BF16 },
{ "-muintr", OPTION_MASK_ISA2_UINTR },
- { "-mhreset", OPTION_MASK_ISA2_HRESET }
+ { "-mhreset", OPTION_MASK_ISA2_HRESET },
+ { "-mkl", OPTION_MASK_ISA2_KL },
+ { "-mwidekl", OPTION_MASK_ISA2_WIDEKL },
+ { "-mavxvnni", OPTION_MASK_ISA2_AVXVNNI }
};
static struct ix86_target_opts isa_opts[] =
{
@@ -742,6 +746,7 @@ static const struct processor_costs *processor_cost_table[] =
&btver1_cost,
&btver2_cost,
&znver1_cost,
+ &znver2_cost,
&znver2_cost
};
@@ -1035,6 +1040,8 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
IX86_ATTR_ISA ("cldemote", OPT_mcldemote),
IX86_ATTR_ISA ("uintr", OPT_muintr),
IX86_ATTR_ISA ("ptwrite", OPT_mptwrite),
+ IX86_ATTR_ISA ("kl", OPT_mkl),
+ IX86_ATTR_ISA ("widekl", OPT_mwidekl),
IX86_ATTR_ISA ("avx512bf16", OPT_mavx512bf16),
IX86_ATTR_ISA ("enqcmd", OPT_menqcmd),
IX86_ATTR_ISA ("serialize", OPT_mserialize),
@@ -1043,6 +1050,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
IX86_ATTR_ISA ("amx-int8", OPT_mamx_int8),
IX86_ATTR_ISA ("amx-bf16", OPT_mamx_bf16),
IX86_ATTR_ISA ("hreset", OPT_mhreset),
+ IX86_ATTR_ISA ("avxvnni", OPT_mavxvnni),
/* enum options */
IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
@@ -1203,7 +1211,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
{
if (!opt_set_p)
{
- error_at (loc, "pragma or attribute %<target(\"%s\")%> "
+ error_at (loc, "pragma or attribute %<target(\"%s\")%> "
"does not allow a negated form", p);
return false;
}
@@ -1366,6 +1374,14 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
/* Add any builtin functions with the new isa if any. */
ix86_add_new_builtins (opts->x_ix86_isa_flags, opts->x_ix86_isa_flags2);
+ enum excess_precision orig_ix86_excess_precision
+ = opts->x_ix86_excess_precision;
+ bool orig_ix86_unsafe_math_optimizations
+ = opts->x_ix86_unsafe_math_optimizations;
+ opts->x_ix86_excess_precision = opts->x_flag_excess_precision;
+ opts->x_ix86_unsafe_math_optimizations
+ = opts->x_flag_unsafe_math_optimizations;
+
/* Save the current options unless we are validating options for
#pragma. */
t = build_target_option_node (opts, opts_set);
@@ -1374,6 +1390,9 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
opts->x_ix86_tune_string = orig_tune_string;
opts_set->x_ix86_fpmath = orig_fpmath_set;
opts_set->x_prefer_vector_width_type = orig_pvw_set;
+ opts->x_ix86_excess_precision = orig_ix86_excess_precision;
+ opts->x_ix86_unsafe_math_optimizations
+ = orig_ix86_unsafe_math_optimizations;
release_options_strings (option_strings);
}
@@ -1730,7 +1749,7 @@ ix86_recompute_optlev_based_flags (struct gcc_options *opts,
if (opts->x_flag_pcc_struct_return == 2)
{
/* Intel MCU psABI specifies that -freg-struct-return should
- be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 1,
+ be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 0,
we check -miamcu so that -freg-struct-return is always
turned on if -miamcu is used. */
if (TARGET_IAMCU_P (opts->x_target_flags))
@@ -1865,9 +1884,7 @@ ix86_option_override_internal (bool main_args_p,
as -mtune=generic. With native compilers we won't see the
-mtune=native, as it was changed by the driver. */
if (!strcmp (opts->x_ix86_tune_string, "native"))
- {
- opts->x_ix86_tune_string = "generic";
- }
+ opts->x_ix86_tune_string = "generic";
else if (!strcmp (opts->x_ix86_tune_string, "x86-64"))
warning (OPT_Wdeprecated,
main_args_p
@@ -1889,10 +1906,12 @@ ix86_option_override_internal (bool main_args_p,
/* opts->x_ix86_tune_string is set to opts->x_ix86_arch_string
or defaulted. We need to use a sensible tune option. */
- if (!strcmp (opts->x_ix86_tune_string, "x86-64"))
- {
- opts->x_ix86_tune_string = "generic";
- }
+ if (!strncmp (opts->x_ix86_tune_string, "x86-64", 6)
+ && (opts->x_ix86_tune_string[6] == '\0'
+ || (!strcmp (opts->x_ix86_tune_string + 6, "-v2")
+ || !strcmp (opts->x_ix86_tune_string + 6, "-v3")
+ || !strcmp (opts->x_ix86_tune_string + 6, "-v4"))))
+ opts->x_ix86_tune_string = "generic";
}
if (opts->x_ix86_stringop_alg == rep_prefix_8_byte
@@ -2065,17 +2084,6 @@ ix86_option_override_internal (bool main_args_p,
return false;
}
- /* The feature-only micro-architecture levels that use
- PTA_NO_TUNE are only defined for the x86-64 psABI. */
- if ((processor_alias_table[i].flags & PTA_NO_TUNE) != 0
- && (!TARGET_64BIT_P (opts->x_ix86_isa_flags)
- || opts->x_ix86_abi != SYSV_ABI))
- {
- error (G_("%<%s%> architecture level is only defined"
- " for the x86-64 psABI"), opts->x_ix86_arch_string);
- return false;
- }
-
ix86_schedule = processor_alias_table[i].schedule;
ix86_arch = processor_alias_table[i].processor;
@@ -2300,6 +2308,10 @@ ix86_option_override_internal (bool main_args_p,
&& !(opts->x_ix86_isa_flags2_explicit
& OPTION_MASK_ISA2_AMX_BF16))
opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AMX_BF16;
+ if (((processor_alias_table[i].flags & PTA_AVXVNNI) != 0)
+ && !(opts->x_ix86_isa_flags2_explicit
+ & OPTION_MASK_ISA2_AVXVNNI))
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVXVNNI;
if (((processor_alias_table[i].flags & PTA_MOVDIRI) != 0)
&& !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVDIRI))
opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MOVDIRI;
@@ -2339,6 +2351,12 @@ ix86_option_override_internal (bool main_args_p,
if (((processor_alias_table[i].flags & PTA_TSXLDTRK) != 0)
&& !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_TSXLDTRK))
opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_TSXLDTRK;
+ if (((processor_alias_table[i].flags & PTA_KL) != 0)
+ && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_KL))
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_KL;
+ if (((processor_alias_table[i].flags & PTA_WIDEKL) != 0)
+ && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_WIDEKL))
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_WIDEKL;
if ((processor_alias_table[i].flags
& (PTA_PREFETCH_SSE | PTA_SSE)) != 0)
@@ -3001,8 +3019,14 @@ ix86_option_override_internal (bool main_args_p,
/* Save the initial options in case the user does function specific
options. */
if (main_args_p)
- target_option_default_node = target_option_current_node
- = build_target_option_node (opts, opts_set);
+ {
+ opts->x_ix86_excess_precision
+ = opts->x_flag_excess_precision;
+ opts->x_ix86_unsafe_math_optimizations
+ = opts->x_flag_unsafe_math_optimizations;
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (opts, opts_set);
+ }
if (opts->x_flag_cf_protection != CF_NONE)
opts->x_flag_cf_protection
@@ -3308,6 +3332,24 @@ ix86_set_current_function (tree fndecl)
else
TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
}
+ else if (flag_unsafe_math_optimizations
+ != TREE_TARGET_OPTION (new_tree)->x_ix86_unsafe_math_optimizations
+ || (flag_excess_precision
+ != TREE_TARGET_OPTION (new_tree)->x_ix86_excess_precision))
+ {
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (new_tree));
+ ix86_excess_precision = flag_excess_precision;
+ ix86_unsafe_math_optimizations = flag_unsafe_math_optimizations;
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_tree
+ = build_target_option_node (&global_options, &global_options_set);
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else if (new_tree == target_option_default_node)
+ restore_target_globals (&default_target_globals);
+ else
+ TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+ }
ix86_previous_fndecl = fndecl;
static bool prev_no_caller_saved_registers;
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index c5b700e..65347a5 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -26,6 +26,7 @@ extern bool ix86_handle_option (struct gcc_options *opts,
/* Functions in i386.c */
extern bool ix86_target_stack_probe (void);
extern bool ix86_can_use_return_insn_p (void);
+extern bool ix86_function_ms_hook_prologue (const_tree fn);
extern void ix86_setup_frame_addresses (void);
extern bool ix86_rip_relative_addr_p (struct ix86_address *parts);
@@ -71,6 +72,7 @@ extern int avx_vperm2f128_parallel (rtx par, machine_mode mode);
extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx);
extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, rtx, rtx,
rtx, rtx, rtx, rtx, bool);
+extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, rtx, rtx, rtx, bool);
extern bool constant_address_p (rtx);
extern bool legitimate_pic_operand_p (rtx);
@@ -161,6 +163,7 @@ extern rtx ix86_find_base_term (rtx);
extern bool ix86_check_movabs (rtx, int);
extern bool ix86_check_no_addr_space (rtx);
extern void ix86_split_idivmod (machine_mode, rtx[], bool);
+extern bool ix86_hardreg_mov_ok (rtx, rtx);
extern rtx assign_386_stack_local (machine_mode, enum ix86_stack_slot);
extern int ix86_attr_length_immediate_default (rtx_insn *, bool);
@@ -242,6 +245,7 @@ extern rtx ix86_rewrite_tls_address (rtx);
extern void ix86_expand_vector_init (bool, rtx, rtx);
extern void ix86_expand_vector_set (bool, rtx, rtx, int);
+extern void ix86_expand_vector_set_var (rtx, rtx, rtx);
extern void ix86_expand_vector_extract (bool, rtx, rtx, int);
extern void ix86_expand_reduc (rtx (*)(rtx, rtx, rtx), rtx, rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 502d240..54b7e10 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -939,6 +939,19 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
decl_or_type = type;
}
+ /* If outgoing reg parm stack space changes, we cannot do sibcall. */
+ if ((OUTGOING_REG_PARM_STACK_SPACE (type)
+ != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)))
+ || (REG_PARM_STACK_SPACE (decl_or_type)
+ != REG_PARM_STACK_SPACE (current_function_decl)))
+ {
+ maybe_complain_about_tail_call (exp,
+ "inconsistent size of stack space"
+ " allocated for arguments which are"
+ " passed in registers");
+ return false;
+ }
+
/* Check that the return value locations are the same. Like
if we are returning floats on the 80387 register stack, we cannot
make a sibcall from a function that doesn't return a float to a
@@ -1410,23 +1423,15 @@ ix86_function_arg_regno_p (int regno)
enum calling_abi call_abi;
const int *parm_regs;
- if (!TARGET_64BIT)
- {
- if (TARGET_MACHO)
- return (regno < REGPARM_MAX
- || (TARGET_SSE && SSE_REGNO_P (regno) && !fixed_regs[regno]));
- else
- return (regno < REGPARM_MAX
- || (TARGET_MMX && MMX_REGNO_P (regno)
- && (regno < FIRST_MMX_REG + MMX_REGPARM_MAX))
- || (TARGET_SSE && SSE_REGNO_P (regno)
- && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX)));
- }
-
if (TARGET_SSE && SSE_REGNO_P (regno)
- && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX))
+ && regno < FIRST_SSE_REG + SSE_REGPARM_MAX)
return true;
+ if (!TARGET_64BIT)
+ return (regno < REGPARM_MAX
+ || (TARGET_MMX && MMX_REGNO_P (regno)
+ && regno < FIRST_MMX_REG + MMX_REGPARM_MAX));
+
/* TODO: The function should depend on current function ABI but
builtins.c would need updating then. Therefore we use the
default ABI. */
@@ -3551,6 +3556,302 @@ ix86_function_value_regno_p (const unsigned int regno)
return false;
}
+/* Check whether the register REGNO should be zeroed on X86.
+ When ALL_SSE_ZEROED is true, all SSE registers have been zeroed
+ together, no need to zero it again.
+ When NEED_ZERO_MMX is true, MMX registers should be cleared. */
+
+static bool
+zero_call_used_regno_p (const unsigned int regno,
+ bool all_sse_zeroed,
+ bool need_zero_mmx)
+{
+ return GENERAL_REGNO_P (regno)
+ || (!all_sse_zeroed && SSE_REGNO_P (regno))
+ || MASK_REGNO_P (regno)
+ || (need_zero_mmx && MMX_REGNO_P (regno));
+}
+
+/* Return the machine_mode that is used to zero register REGNO. */
+
+static machine_mode
+zero_call_used_regno_mode (const unsigned int regno)
+{
+ /* NB: We only need to zero the lower 32 bits for integer registers
+ and the lower 128 bits for vector registers since destination are
+ zero-extended to the full register width. */
+ if (GENERAL_REGNO_P (regno))
+ return SImode;
+ else if (SSE_REGNO_P (regno))
+ return V4SFmode;
+ else if (MASK_REGNO_P (regno))
+ return HImode;
+ else if (MMX_REGNO_P (regno))
+ return V4HImode;
+ else
+ gcc_unreachable ();
+}
+
+/* Generate a rtx to zero all vector registers together if possible,
+ otherwise, return NULL. */
+
+static rtx
+zero_all_vector_registers (HARD_REG_SET need_zeroed_hardregs)
+{
+ if (!TARGET_AVX)
+ return NULL;
+
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if ((IN_RANGE (regno, FIRST_SSE_REG, LAST_SSE_REG)
+ || (TARGET_64BIT
+ && (REX_SSE_REGNO_P (regno)
+ || (TARGET_AVX512F && EXT_REX_SSE_REGNO_P (regno)))))
+ && !TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+ return NULL;
+
+ return gen_avx_vzeroall ();
+}
+
+/* Generate insns to zero all st registers together.
+ Return true when zeroing instructions are generated.
+ Assume the number of st registers that are zeroed is num_of_st,
+ we will emit the following sequence to zero them together:
+ fldz; \
+ fldz; \
+ ...
+ fldz; \
+ fstp %%st(0); \
+ fstp %%st(0); \
+ ...
+ fstp %%st(0);
+ i.e., num_of_st fldz followed by num_of_st fstp to clear the stack
+ mark stack slots empty.
+
+ How to compute the num_of_st:
+ There is no direct mapping from stack registers to hard register
+ numbers. If one stack register needs to be cleared, we don't know
+ where in the stack the value remains. So, if any stack register
+ needs to be cleared, the whole stack should be cleared. However,
+ x87 stack registers that hold the return value should be excluded.
+ x87 returns in the top (two for complex values) register, so
+ num_of_st should be 7/6 when x87 returns, otherwise it will be 8. */
+
+
+static bool
+zero_all_st_registers (HARD_REG_SET need_zeroed_hardregs)
+{
+
+ /* If the FPU is disabled, no need to zero all st registers. */
+ if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387))
+ return false;
+
+ unsigned int num_of_st = 0;
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if ((STACK_REGNO_P (regno) || MMX_REGNO_P (regno))
+ && TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+ {
+ num_of_st++;
+ break;
+ }
+
+ if (num_of_st == 0)
+ return false;
+
+ bool return_with_x87 = false;
+ return_with_x87 = (crtl->return_rtx
+ && (STACK_REG_P (crtl->return_rtx)));
+
+ bool complex_return = false;
+ complex_return = (crtl->return_rtx
+ && COMPLEX_MODE_P (GET_MODE (crtl->return_rtx)));
+
+ if (return_with_x87)
+ if (complex_return)
+ num_of_st = 6;
+ else
+ num_of_st = 7;
+ else
+ num_of_st = 8;
+
+ rtx st_reg = gen_rtx_REG (XFmode, FIRST_STACK_REG);
+ for (unsigned int i = 0; i < num_of_st; i++)
+ emit_insn (gen_rtx_SET (st_reg, CONST0_RTX (XFmode)));
+
+ for (unsigned int i = 0; i < num_of_st; i++)
+ {
+ rtx insn;
+ insn = emit_insn (gen_rtx_SET (st_reg, st_reg));
+ add_reg_note (insn, REG_DEAD, st_reg);
+ }
+ return true;
+}
+
+
+/* When the routine exit in MMX mode, if any ST register needs
+ to be zeroed, we should clear all MMX registers except the
+ RET_MMX_REGNO that holds the return value. */
+static bool
+zero_all_mm_registers (HARD_REG_SET need_zeroed_hardregs,
+ unsigned int ret_mmx_regno)
+{
+ bool need_zero_all_mm = false;
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (STACK_REGNO_P (regno)
+ && TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+ {
+ need_zero_all_mm = true;
+ break;
+ }
+
+ if (!need_zero_all_mm)
+ return false;
+
+ rtx zero_mmx = NULL_RTX;
+ machine_mode mode = V4HImode;
+ for (unsigned int regno = FIRST_MMX_REG; regno <= LAST_MMX_REG; regno++)
+ if (regno != ret_mmx_regno)
+ {
+ rtx reg = gen_rtx_REG (mode, regno);
+ if (zero_mmx == NULL_RTX)
+ {
+ zero_mmx = reg;
+ emit_insn (gen_rtx_SET (reg, CONST0_RTX (mode)));
+ }
+ else
+ emit_move_insn (reg, zero_mmx);
+ }
+ return true;
+}
+
+/* TARGET_ZERO_CALL_USED_REGS. */
+/* Generate a sequence of instructions that zero registers specified by
+ NEED_ZEROED_HARDREGS. Return the ZEROED_HARDREGS that are actually
+ zeroed. */
+static HARD_REG_SET
+ix86_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+ HARD_REG_SET zeroed_hardregs;
+ bool all_sse_zeroed = false;
+ bool all_st_zeroed = false;
+ bool all_mm_zeroed = false;
+
+ CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+ /* first, let's see whether we can zero all vector registers together. */
+ rtx zero_all_vec_insn = zero_all_vector_registers (need_zeroed_hardregs);
+ if (zero_all_vec_insn)
+ {
+ emit_insn (zero_all_vec_insn);
+ all_sse_zeroed = true;
+ }
+
+ /* mm/st registers are shared registers set, we should follow the following
+ rules to clear them:
+ MMX exit mode x87 exit mode
+ -------------|----------------------|---------------
+ uses x87 reg | clear all MMX | clear all x87
+ uses MMX reg | clear individual MMX | clear all x87
+ x87 + MMX | clear all MMX | clear all x87
+
+ first, we should decide which mode (MMX mode or x87 mode) the function
+ exit with. */
+
+ bool exit_with_mmx_mode = (crtl->return_rtx
+ && (MMX_REG_P (crtl->return_rtx)));
+
+ if (!exit_with_mmx_mode)
+ /* x87 exit mode, we should zero all st registers together. */
+ {
+ all_st_zeroed = zero_all_st_registers (need_zeroed_hardregs);
+ if (all_st_zeroed)
+ SET_HARD_REG_BIT (zeroed_hardregs, FIRST_STACK_REG);
+ }
+ else
+ /* MMX exit mode, check whether we can zero all mm registers. */
+ {
+ unsigned int exit_mmx_regno = REGNO (crtl->return_rtx);
+ all_mm_zeroed = zero_all_mm_registers (need_zeroed_hardregs,
+ exit_mmx_regno);
+ if (all_mm_zeroed)
+ for (unsigned int regno = FIRST_MMX_REG; regno <= LAST_MMX_REG; regno++)
+ if (regno != exit_mmx_regno)
+ SET_HARD_REG_BIT (zeroed_hardregs, regno);
+ }
+
+ /* Now, generate instructions to zero all the other registers. */
+
+ rtx zero_gpr = NULL_RTX;
+ rtx zero_vector = NULL_RTX;
+ rtx zero_mask = NULL_RTX;
+ rtx zero_mmx = NULL_RTX;
+
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ if (!TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+ continue;
+ if (!zero_call_used_regno_p (regno, all_sse_zeroed,
+ exit_with_mmx_mode && !all_mm_zeroed))
+ continue;
+
+ SET_HARD_REG_BIT (zeroed_hardregs, regno);
+
+ rtx reg, tmp, zero_rtx;
+ machine_mode mode = zero_call_used_regno_mode (regno);
+
+ reg = gen_rtx_REG (mode, regno);
+ zero_rtx = CONST0_RTX (mode);
+
+ if (mode == SImode)
+ if (zero_gpr == NULL_RTX)
+ {
+ zero_gpr = reg;
+ tmp = gen_rtx_SET (reg, zero_rtx);
+ if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
+ {
+ rtx clob = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (CCmode,
+ FLAGS_REG));
+ tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
+ tmp,
+ clob));
+ }
+ emit_insn (tmp);
+ }
+ else
+ emit_move_insn (reg, zero_gpr);
+ else if (mode == V4SFmode)
+ if (zero_vector == NULL_RTX)
+ {
+ zero_vector = reg;
+ tmp = gen_rtx_SET (reg, zero_rtx);
+ emit_insn (tmp);
+ }
+ else
+ emit_move_insn (reg, zero_vector);
+ else if (mode == HImode)
+ if (zero_mask == NULL_RTX)
+ {
+ zero_mask = reg;
+ tmp = gen_rtx_SET (reg, zero_rtx);
+ emit_insn (tmp);
+ }
+ else
+ emit_move_insn (reg, zero_mask);
+ else if (mode == V4HImode)
+ if (zero_mmx == NULL_RTX)
+ {
+ zero_mmx = reg;
+ tmp = gen_rtx_SET (reg, zero_rtx);
+ emit_insn (tmp);
+ }
+ else
+ emit_move_insn (reg, zero_mmx);
+ else
+ gcc_unreachable ();
+ }
+ return zeroed_hardregs;
+}
+
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
If the precise function being called is known, FUNC is its FUNCTION_DECL;
@@ -3796,9 +4097,6 @@ ix86_libcall_value (machine_mode mode)
static bool
ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
-#ifdef SUBTARGET_RETURN_IN_MEMORY
- return SUBTARGET_RETURN_IN_MEMORY (type, fntype);
-#else
const machine_mode mode = type_natural_mode (type, NULL, true);
HOST_WIDE_INT size;
@@ -3879,7 +4177,6 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
return false;
}
-#endif
}
@@ -5197,6 +5494,9 @@ symbolic_reference_mentioned_p (rtx op)
bool
ix86_can_use_return_insn_p (void)
{
+ if (ix86_function_ms_hook_prologue (current_function_decl))
+ return false;
+
if (ix86_function_naked (current_function_decl))
return false;
@@ -7851,7 +8151,11 @@ ix86_expand_prologue (void)
rtx static_chain = NULL_RTX;
if (ix86_function_naked (current_function_decl))
- return;
+ {
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = 0;
+ return;
+ }
ix86_finalize_stack_frame_flags ();
@@ -18585,6 +18889,22 @@ ix86_class_likely_spilled_p (reg_class_t rclass)
return false;
}
+/* Return true if a set of DST by the expression SRC should be allowed.
+ This prevents complex sets of likely_spilled hard regs before reload. */
+
+bool
+ix86_hardreg_mov_ok (rtx dst, rtx src)
+{
+ /* Avoid complex sets of likely_spilled hard registers before reload. */
+ if (REG_P (dst) && HARD_REGISTER_P (dst)
+ && !REG_P (src) && !MEM_P (src)
+ && !x86_64_immediate_operand (src, GET_MODE (dst))
+ && ix86_class_likely_spilled_p (REGNO_REG_CLASS (REGNO (dst)))
+ && !reload_completed)
+ return false;
+ return true;
+}
+
/* If we are copying between registers from different register sets
(e.g. FP and integer), we may need a memory location.
@@ -21188,40 +21508,18 @@ ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
continue;
}
- if (dest_mode == DImode && !TARGET_64BIT)
- dest_mode = SImode;
-
- if (dest_mode != QImode)
- {
- rtx destqi = gen_reg_rtx (QImode);
- emit_insn (gen_rtx_SET (destqi, x));
-
- if (TARGET_ZERO_EXTEND_WITH_AND
- && optimize_function_for_speed_p (cfun))
- {
- x = force_reg (dest_mode, const0_rtx);
-
- emit_insn (gen_movstrictqi (gen_lowpart (QImode, x), destqi));
- }
- else
- {
- x = gen_rtx_ZERO_EXTEND (dest_mode, destqi);
- if (dest_mode == GET_MODE (dest)
- && !register_operand (dest, GET_MODE (dest)))
- x = force_reg (dest_mode, x);
- }
- }
-
- if (dest_mode != GET_MODE (dest))
+ if (dest_mode == QImode)
+ emit_insn (gen_rtx_SET (dest, x));
+ else
{
- rtx tmp = gen_reg_rtx (SImode);
+ rtx reg = gen_reg_rtx (QImode);
+ emit_insn (gen_rtx_SET (reg, x));
- emit_insn (gen_rtx_SET (tmp, x));
- emit_insn (gen_zero_extendsidi2 (dest, tmp));
+ reg = convert_to_mode (dest_mode, reg, 1);
+ emit_move_insn (dest, reg);
}
- else
- emit_insn (gen_rtx_SET (dest, x));
}
+
rtx_insn *seq = get_insns ();
end_sequence ();
@@ -21678,8 +21976,9 @@ ix86_reassociation_width (unsigned int op, machine_mode mode)
/* Integer vector instructions execute in FP unit
and can execute 3 additions and one multiplication per cycle. */
- if ((ix86_tune == PROCESSOR_ZNVER1 || ix86_tune == PROCESSOR_ZNVER2)
- && INTEGRAL_MODE_P (mode) && op != PLUS && op != MINUS)
+ if ((ix86_tune == PROCESSOR_ZNVER1 || ix86_tune == PROCESSOR_ZNVER2
+ || ix86_tune == PROCESSOR_ZNVER3)
+ && INTEGRAL_MODE_P (mode) && op != PLUS && op != MINUS)
return 1;
/* Account for targets that splits wide vectors into multiple parts. */
@@ -22177,7 +22476,7 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
|| (clonei->simdlen & (clonei->simdlen - 1)) != 0))
{
warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
- "unsupported simdlen %d", clonei->simdlen);
+ "unsupported simdlen %wd", clonei->simdlen.to_constant ());
return 0;
}
@@ -22282,7 +22581,8 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
clonei->simdlen = clonei->vecsize_int;
else
clonei->simdlen = clonei->vecsize_float;
- clonei->simdlen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
+ clonei->simdlen = clonei->simdlen
+ / GET_MODE_BITSIZE (TYPE_MODE (base_type));
}
else if (clonei->simdlen > 16)
{
@@ -22304,7 +22604,8 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
if (cnt > (TARGET_64BIT ? 16 : 8))
{
warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
- "unsupported simdlen %d", clonei->simdlen);
+ "unsupported simdlen %wd",
+ clonei->simdlen.to_constant ());
return 0;
}
}
@@ -22700,7 +23001,7 @@ ix86_init_libfuncs (void)
apparently at random. */
static enum flt_eval_method
-ix86_excess_precision (enum excess_precision_type type)
+ix86_get_excess_precision (enum excess_precision_type type)
{
switch (type)
{
@@ -23226,7 +23527,7 @@ ix86_run_selftests (void)
#define TARGET_MD_ASM_ADJUST ix86_md_asm_adjust
#undef TARGET_C_EXCESS_PRECISION
-#define TARGET_C_EXCESS_PRECISION ix86_excess_precision
+#define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
#undef TARGET_SETUP_INCOMING_VARARGS
@@ -23310,6 +23611,9 @@ ix86_run_selftests (void)
#undef TARGET_FUNCTION_VALUE_REGNO_P
#define TARGET_FUNCTION_VALUE_REGNO_P ix86_function_value_regno_p
+#undef TARGET_ZERO_CALL_USED_REGS
+#define TARGET_ZERO_CALL_USED_REGS ix86_zero_call_used_regs
+
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE ix86_promote_function_mode
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 24207d0..e88738c 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -213,6 +213,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_UINTR_P(x) TARGET_ISA2_UINTR_P(x)
#define TARGET_HRESET TARGET_ISA2_HRESET
#define TARGET_HRESET_P(x) TARGET_ISA2_HRESET_P(x)
+#define TARGET_KL TARGET_ISA2_KL
+#define TARGET_KL_P(x) TARGET_ISA2_KL_P(x)
+#define TARGET_WIDEKL TARGET_ISA2_WIDEKL
+#define TARGET_WIDEKL_P(x) TARGET_ISA2_WIDEKL_P(x)
+#define TARGET_AVXVNNI TARGET_ISA2_AVXVNNI
+#define TARGET_AVXVNNI_P(x) TARGET_ISA2_AVXVNNI_P(x)
#define TARGET_LP64 TARGET_ABI_64
#define TARGET_LP64_P(x) TARGET_ABI_64_P(x)
@@ -478,6 +484,7 @@ extern const struct processor_costs ix86_size_cost;
#define TARGET_BTVER2 (ix86_tune == PROCESSOR_BTVER2)
#define TARGET_ZNVER1 (ix86_tune == PROCESSOR_ZNVER1)
#define TARGET_ZNVER2 (ix86_tune == PROCESSOR_ZNVER2)
+#define TARGET_ZNVER3 (ix86_tune == PROCESSOR_ZNVER3)
/* Feature tests against the various tunings. */
enum ix86_tune_indices {
@@ -822,15 +829,15 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
SFmode, DFmode and XFmode) in the current excess precision
configuration. */
#define X87_ENABLE_ARITH(MODE) \
- (flag_unsafe_math_optimizations \
- || flag_excess_precision == EXCESS_PRECISION_FAST \
+ (ix86_unsafe_math_optimizations \
+ || ix86_excess_precision == EXCESS_PRECISION_FAST \
|| (MODE) == XFmode)
/* Likewise, whether to allow direct conversions from integer mode
IMODE (HImode, SImode or DImode) to MODE. */
#define X87_ENABLE_FLOAT(MODE, IMODE) \
- (flag_unsafe_math_optimizations \
- || flag_excess_precision == EXCESS_PRECISION_FAST \
+ (ix86_unsafe_math_optimizations \
+ || ix86_excess_precision == EXCESS_PRECISION_FAST \
|| (MODE) == XFmode \
|| ((MODE) == DFmode && (IMODE) == SImode) \
|| (IMODE) == HImode)
@@ -1156,22 +1163,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
1, 1, 1, 1, 1, 1, 1, 1 }
-/* Order in which to allocate registers. Each register must be
- listed once, even those in FIXED_REGISTERS. List frame pointer
- late and fixed registers last. Note that, in general, we prefer
- registers listed in CALL_USED_REGISTERS, keeping the others
- available for storage of persistent values.
-
- The ADJUST_REG_ALLOC_ORDER actually overwrite the order,
- so this is just empty initializer for array. */
-
-#define REG_ALLOC_ORDER \
-{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75 }
-
/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
to be rearranged based on a particular function. When using sse math,
we want to allocate SSE before x87 registers and vice versa. */
@@ -1946,7 +1937,9 @@ typedef struct ix86_args {
: X86_64_SSE_REGPARM_MAX) \
: X86_32_SSE_REGPARM_MAX)
-#define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : (TARGET_MMX ? 3 : 0))
+#define X86_32_MMX_REGPARM_MAX (TARGET_MMX ? (TARGET_MACHO ? 0 : 3) : 0)
+
+#define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : X86_32_MMX_REGPARM_MAX)
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
@@ -2389,6 +2382,7 @@ enum processor_type
PROCESSOR_BTVER2,
PROCESSOR_ZNVER1,
PROCESSOR_ZNVER2,
+ PROCESSOR_ZNVER3,
PROCESSOR_max
};
@@ -2474,17 +2468,20 @@ const wide_int_bitmask PTA_AVX512VP2INTERSECT (0, HOST_WIDE_INT_1U << 9);
const wide_int_bitmask PTA_PTWRITE (0, HOST_WIDE_INT_1U << 10);
const wide_int_bitmask PTA_AVX512BF16 (0, HOST_WIDE_INT_1U << 11);
const wide_int_bitmask PTA_WAITPKG (0, HOST_WIDE_INT_1U << 12);
-const wide_int_bitmask PTA_MOVDIRI(0, HOST_WIDE_INT_1U << 13);
-const wide_int_bitmask PTA_MOVDIR64B(0, HOST_WIDE_INT_1U << 14);
+const wide_int_bitmask PTA_MOVDIRI (0, HOST_WIDE_INT_1U << 13);
+const wide_int_bitmask PTA_MOVDIR64B (0, HOST_WIDE_INT_1U << 14);
const wide_int_bitmask PTA_ENQCMD (0, HOST_WIDE_INT_1U << 15);
const wide_int_bitmask PTA_CLDEMOTE (0, HOST_WIDE_INT_1U << 16);
const wide_int_bitmask PTA_SERIALIZE (0, HOST_WIDE_INT_1U << 17);
const wide_int_bitmask PTA_TSXLDTRK (0, HOST_WIDE_INT_1U << 18);
-const wide_int_bitmask PTA_AMX_TILE(0, HOST_WIDE_INT_1U << 19);
-const wide_int_bitmask PTA_AMX_INT8(0, HOST_WIDE_INT_1U << 20);
-const wide_int_bitmask PTA_AMX_BF16(0, HOST_WIDE_INT_1U << 21);
+const wide_int_bitmask PTA_AMX_TILE (0, HOST_WIDE_INT_1U << 19);
+const wide_int_bitmask PTA_AMX_INT8 (0, HOST_WIDE_INT_1U << 20);
+const wide_int_bitmask PTA_AMX_BF16 (0, HOST_WIDE_INT_1U << 21);
const wide_int_bitmask PTA_UINTR (0, HOST_WIDE_INT_1U << 22);
-const wide_int_bitmask PTA_HRESET(0, HOST_WIDE_INT_1U << 23);
+const wide_int_bitmask PTA_HRESET (0, HOST_WIDE_INT_1U << 23);
+const wide_int_bitmask PTA_KL (0, HOST_WIDE_INT_1U << 24);
+const wide_int_bitmask PTA_WIDEKL (0, HOST_WIDE_INT_1U << 25);
+const wide_int_bitmask PTA_AVXVNNI (0, HOST_WIDE_INT_1U << 26);
const wide_int_bitmask PTA_X86_64_BASELINE = PTA_64BIT | PTA_MMX | PTA_SSE
| PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR;
@@ -2507,8 +2504,8 @@ const wide_int_bitmask PTA_IVYBRIDGE = PTA_SANDYBRIDGE | PTA_FSGSBASE
| PTA_RDRND | PTA_F16C;
const wide_int_bitmask PTA_HASWELL = PTA_IVYBRIDGE | PTA_AVX2 | PTA_BMI
| PTA_BMI2 | PTA_LZCNT | PTA_FMA | PTA_MOVBE | PTA_HLE;
-const wide_int_bitmask PTA_BROADWELL = PTA_HASWELL | PTA_ADX | PTA_PRFCHW
- | PTA_RDSEED;
+const wide_int_bitmask PTA_BROADWELL = PTA_HASWELL | PTA_ADX | PTA_RDSEED
+ | PTA_PRFCHW;
const wide_int_bitmask PTA_SKYLAKE = PTA_BROADWELL | PTA_AES | PTA_CLFLUSHOPT
| PTA_XSAVEC | PTA_XSAVES | PTA_SGX;
const wide_int_bitmask PTA_SKYLAKE_AVX512 = PTA_SKYLAKE | PTA_AVX512F
@@ -2525,24 +2522,25 @@ const wide_int_bitmask PTA_ICELAKE_CLIENT = PTA_CANNONLAKE | PTA_AVX512VNNI
const wide_int_bitmask PTA_ICELAKE_SERVER = PTA_ICELAKE_CLIENT | PTA_PCONFIG
| PTA_WBNOINVD | PTA_CLWB;
const wide_int_bitmask PTA_TIGERLAKE = PTA_ICELAKE_CLIENT | PTA_MOVDIRI
- | PTA_MOVDIR64B | PTA_CLWB | PTA_AVX512VP2INTERSECT;
+ | PTA_MOVDIR64B | PTA_CLWB | PTA_AVX512VP2INTERSECT | PTA_KL | PTA_WIDEKL;
const wide_int_bitmask PTA_SAPPHIRERAPIDS = PTA_COOPERLAKE | PTA_MOVDIRI
| PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_ENQCMD | PTA_CLDEMOTE
| PTA_PTWRITE | PTA_WAITPKG | PTA_SERIALIZE | PTA_TSXLDTRK | PTA_AMX_TILE
- | PTA_AMX_INT8 | PTA_AMX_BF16 | PTA_UINTR;
+ | PTA_AMX_INT8 | PTA_AMX_BF16 | PTA_UINTR | PTA_AVXVNNI;
const wide_int_bitmask PTA_ALDERLAKE = PTA_SKYLAKE | PTA_CLDEMOTE | PTA_PTWRITE
- | PTA_WAITPKG | PTA_SERIALIZE | PTA_HRESET;
+ | PTA_WAITPKG | PTA_SERIALIZE | PTA_HRESET | PTA_KL | PTA_WIDEKL | PTA_AVXVNNI;
const wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF | PTA_AVX512ER
- | PTA_AVX512F | PTA_AVX512CD;
+ | PTA_AVX512F | PTA_AVX512CD | PTA_PREFETCHWT1;
const wide_int_bitmask PTA_BONNELL = PTA_CORE2 | PTA_MOVBE;
-const wide_int_bitmask PTA_SILVERMONT = PTA_WESTMERE | PTA_MOVBE | PTA_RDRND;
+const wide_int_bitmask PTA_SILVERMONT = PTA_WESTMERE | PTA_MOVBE | PTA_RDRND
+ | PTA_PRFCHW;
const wide_int_bitmask PTA_GOLDMONT = PTA_SILVERMONT | PTA_AES | PTA_SHA | PTA_XSAVE
| PTA_RDSEED | PTA_XSAVEC | PTA_XSAVES | PTA_CLFLUSHOPT | PTA_XSAVEOPT
| PTA_FSGSBASE;
const wide_int_bitmask PTA_GOLDMONT_PLUS = PTA_GOLDMONT | PTA_RDPID
| PTA_SGX | PTA_PTWRITE;
const wide_int_bitmask PTA_TREMONT = PTA_GOLDMONT_PLUS | PTA_CLWB
- | PTA_GFNI;
+ | PTA_GFNI | PTA_MOVDIRI | PTA_MOVDIR64B | PTA_CLDEMOTE | PTA_WAITPKG;
const wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
| PTA_AVX5124FMAPS | PTA_AVX512VPOPCNTDQ;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 8730816..ea1a070 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -458,7 +458,7 @@
;; Processor type.
(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,nehalem,
atom,slm,glm,haswell,generic,amdfam10,bdver1,bdver2,bdver3,
- bdver4,btver2,znver1,znver2"
+ bdver4,btver2,znver1,znver2,znver3"
(const (symbol_ref "ix86_schedule")))
;; A basic instruction type. Refinements due to arguments to be
@@ -818,7 +818,8 @@
sse_noavx,sse2,sse2_noavx,sse3,sse3_noavx,sse4,sse4_noavx,
avx,noavx,avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,noavx512f,
avx512bw,noavx512bw,avx512dq,noavx512dq,
- avx512vl,noavx512vl,x64_avx512dq,x64_avx512bw"
+ avx512vl,noavx512vl,x64_avx512dq,x64_avx512bw,
+ avxvnni,avx512vnnivl"
(const_string "base"))
;; Define instruction set of MMX instructions
@@ -867,6 +868,8 @@
(eq_attr "isa" "noavx512dq") (symbol_ref "!TARGET_AVX512DQ")
(eq_attr "isa" "avx512vl") (symbol_ref "TARGET_AVX512VL")
(eq_attr "isa" "noavx512vl") (symbol_ref "!TARGET_AVX512VL")
+ (eq_attr "isa" "avxvnni") (symbol_ref "TARGET_AVXVNNI")
+ (eq_attr "isa" "avx512vnnivl") (symbol_ref "TARGET_AVX512VNNI && TARGET_AVX512VL")
(eq_attr "mmx_isa" "native")
(symbol_ref "!TARGET_MMX_WITH_SSE")
@@ -977,6 +980,10 @@
;; Used in signed and unsigned widening multiplications.
(define_code_iterator any_extend [sign_extend zero_extend])
+;; Used for representing standard name for extend
+(define_code_attr optab [(sign_extend "extend")
+ (zero_extend "zero_extend")])
+
;; Prefix for insn menmonic.
(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")
(div "i") (udiv "")])
@@ -2086,7 +2093,8 @@
"=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
(match_operand:DI 1 "general_operand"
"riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ix86_hardreg_mov_ok (operands[0], operands[1])"
{
switch (get_attr_type (insn))
{
@@ -2306,7 +2314,8 @@
"=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
(match_operand:SI 1 "general_operand"
"g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ix86_hardreg_mov_ok (operands[0], operands[1])"
{
switch (get_attr_type (insn))
{
@@ -2414,7 +2423,9 @@
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,m ,*k,*k ,*r,*m,*k")
(match_operand:HI 1 "general_operand" "r ,rn,rm,rn,*r,*km,*k,*k,CBC"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ix86_hardreg_mov_ok (operands[0], operands[1])"
+
{
switch (get_attr_type (insn))
{
@@ -2503,7 +2514,9 @@
"=Q,R,r,q,q,r,r ,?r,m ,*k,*k,*r,*m,*k,*k,*k")
(match_operand:QI 1 "general_operand"
"Q ,R,r,n,m,q,rn, m,qn,*r,*k,*k,*k,*m,C,BC"))]
- "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && ix86_hardreg_mov_ok (operands[0], operands[1])"
+
{
char buf[128];
const char *ops;
@@ -5171,7 +5184,7 @@
(define_insn_and_split "*lea<mode>"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(match_operand:SWI48 1 "address_no_seg_operand" "Ts"))]
- ""
+ "ix86_hardreg_mov_ok (operands[0], operands[1])"
{
if (SImode_address_operand (operands[1], VOIDmode))
{
@@ -10053,8 +10066,8 @@
"#"
"reload_completed"
[(parallel
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ (neg:DWIH (match_dup 1)) (const_int 0)))
+ [(set (reg:CCC FLAGS_REG)
+ (ne:CCC (match_dup 1) (const_int 0)))
(set (match_dup 0) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 2)
@@ -10068,7 +10081,7 @@
(clobber (reg:CC FLAGS_REG))])]
"split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[2]);")
-(define_insn "*neg<mode>2_1"
+(define_insn "*neg<mode>_1"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")))
(clobber (reg:CC FLAGS_REG))]
@@ -10077,7 +10090,7 @@
[(set_attr "type" "negnot")
(set_attr "mode" "<MODE>")])
-(define_insn "*negsi2_1_zext"
+(define_insn "*negsi_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(neg:SI (match_operand:SI 1 "register_operand" "0"))))
@@ -10087,36 +10100,46 @@
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
-;; The problem with neg is that it does not perform (compare x 0),
-;; it really performs (compare 0 x), which leaves us with the zero
-;; flag being the only useful item.
-
-(define_insn "*neg<mode>2_cmpz"
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ
+(define_insn "*neg<mode>_2"
+ [(set (reg FLAGS_REG)
+ (compare
(neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))
- (const_int 0)))
+ (const_int 0)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(neg:SWI (match_dup 1)))]
- "ix86_unary_operator_ok (NEG, <MODE>mode, operands)"
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_unary_operator_ok (NEG, <MODE>mode, operands)"
"neg{<imodesuffix>}\t%0"
[(set_attr "type" "negnot")
(set_attr "mode" "<MODE>")])
-(define_insn "*negsi2_cmpz_zext"
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ
+(define_insn "*negsi_2_zext"
+ [(set (reg FLAGS_REG)
+ (compare
(neg:SI (match_operand:SI 1 "register_operand" "0"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(neg:SI (match_dup 1))))]
- "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_unary_operator_ok (NEG, SImode, operands)"
"neg{l}\t%k0"
[(set_attr "type" "negnot")
(set_attr "mode" "SI")])
-(define_insn "*neg<mode>_ccc"
+(define_insn "*neg<mode>_ccc_1"
+ [(set (reg:CCC FLAGS_REG)
+ (ne:CCC
+ (match_operand:SWI 1 "nonimmediate_operand" "0")
+ (const_int 0)))
+ (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+ (neg:SWI (match_dup 1)))]
+ ""
+ "neg{<imodesuffix>}\t%0"
+ [(set_attr "type" "negnot")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*neg<mode>_ccc_2"
[(set (reg:CCC FLAGS_REG)
(ne:CCC
(match_operand:SWI 1 "nonimmediate_operand" "0")
@@ -10160,27 +10183,105 @@
;; Special expand pattern to handle integer mode abs
(define_expand "abs<mode>2"
- [(set (match_operand:SWI48x 0 "register_operand")
- (abs:SWI48x
- (match_operand:SWI48x 1 "register_operand")))]
- "TARGET_EXPAND_ABS"
- {
- machine_mode mode = <MODE>mode;
-
- /* Generate rtx abs using abs (x) = (((signed) x >> (W-1)) ^ x) -
- ((signed) x >> (W-1)) */
- rtx shift_amount = gen_int_mode (GET_MODE_PRECISION (mode) - 1, QImode);
- rtx shift_dst = expand_simple_binop (mode, ASHIFTRT, operands[1],
- shift_amount, NULL_RTX,
- 0, OPTAB_DIRECT);
- rtx xor_dst = expand_simple_binop (mode, XOR, shift_dst, operands[1],
- operands[0], 0, OPTAB_DIRECT);
- rtx minus_dst = expand_simple_binop (mode, MINUS, xor_dst, shift_dst,
- operands[0], 0, OPTAB_DIRECT);
- if (!rtx_equal_p (minus_dst, operands[0]))
- emit_move_insn (operands[0], minus_dst);
- DONE;
- })
+ [(parallel
+ [(set (match_operand:SDWIM 0 "register_operand")
+ (abs:SDWIM
+ (match_operand:SDWIM 1 "general_operand")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_CMOVE
+ && (<MODE>mode != QImode || !TARGET_PARTIAL_REG_STALL)"
+{
+ if (TARGET_EXPAND_ABS)
+ {
+ machine_mode mode = <MODE>mode;
+ operands[1] = force_reg (mode, operands[1]);
+
+ /* Generate rtx abs using:
+ abs (x) = (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)) */
+
+ rtx shift_amount = gen_int_mode (GET_MODE_PRECISION (mode) - 1, QImode);
+ rtx shift_dst = expand_simple_binop (mode, ASHIFTRT, operands[1],
+ shift_amount, NULL_RTX,
+ 0, OPTAB_DIRECT);
+ rtx xor_dst = expand_simple_binop (mode, XOR, shift_dst, operands[1],
+ operands[0], 0, OPTAB_DIRECT);
+ rtx minus_dst = expand_simple_binop (mode, MINUS, xor_dst, shift_dst,
+ operands[0], 0, OPTAB_DIRECT);
+ if (!rtx_equal_p (minus_dst, operands[0]))
+ emit_move_insn (operands[0], minus_dst);
+ DONE;
+ }
+})
+
+(define_insn_and_split "*abs<dwi>2_doubleword"
+ [(set (match_operand:<DWI> 0 "register_operand")
+ (abs:<DWI>
+ (match_operand:<DWI> 1 "general_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_CMOVE
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(parallel
+ [(set (reg:CCC FLAGS_REG)
+ (ne:CCC (match_dup 1) (const_int 0)))
+ (set (match_dup 2) (neg:DWIH (match_dup 1)))])
+ (parallel
+ [(set (match_dup 5)
+ (plus:DWIH (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 4))
+ (const_int 0)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (reg:CCGOC FLAGS_REG)
+ (compare:CCGOC
+ (neg:DWIH (match_dup 5))
+ (const_int 0)))
+ (set (match_dup 5)
+ (neg:DWIH (match_dup 5)))])
+ (set (match_dup 0)
+ (if_then_else:DWIH
+ (ge (reg:CCGOC FLAGS_REG) (const_int 0))
+ (match_dup 2)
+ (match_dup 1)))
+ (set (match_dup 3)
+ (if_then_else:DWIH
+ (ge (reg:CCGOC FLAGS_REG) (const_int 0))
+ (match_dup 5)
+ (match_dup 4)))]
+{
+ operands[1] = force_reg (<DWI>mode, operands[1]);
+ operands[2] = gen_reg_rtx (<DWI>mode);
+
+ split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
+})
+
+(define_insn_and_split "*abs<mode>2_1"
+ [(set (match_operand:SWI 0 "register_operand")
+ (abs:SWI
+ (match_operand:SWI 1 "general_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_CMOVE
+ && (<MODE>mode != QImode || !TARGET_PARTIAL_REG_STALL)
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(parallel
+ [(set (reg:CCGOC FLAGS_REG)
+ (compare:CCGOC
+ (neg:SWI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 2)
+ (neg:SWI (match_dup 1)))])
+ (set (match_dup 0)
+ (if_then_else:SWI
+ (ge (reg:CCGOC FLAGS_REG) (const_int 0))
+ (match_dup 2)
+ (match_dup 1)))]
+{
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ operands[2] = gen_reg_rtx (<MODE>mode);
+})
(define_expand "<code>tf2"
[(set (match_operand:TF 0 "register_operand")
@@ -10249,7 +10350,7 @@
(absneg:X87MODEF
(match_operand:X87MODEF 1 "register_operand" "0,0")))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_80387"
+ "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
"#")
(define_split
@@ -10464,7 +10565,7 @@
not{<imodesuffix>}\t%0
#"
[(set (attr "isa")
- (cond [(eq_attr "alternative" "2")
+ (cond [(eq_attr "alternative" "1")
(if_then_else (eq_attr "mode" "SI,DI")
(const_string "avx512bw")
(const_string "avx512f"))
@@ -11878,6 +11979,22 @@
(clobber (reg:CC FLAGS_REG))])]
"operands[2] = gen_lowpart (QImode, operands[2]);")
+(define_split
+ [(set (match_operand:SWI48 0 "register_operand")
+ (any_rotate:SWI48
+ (match_operand:SWI48 1 "const_int_operand")
+ (subreg:QI
+ (and:SI
+ (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "const_int_operand")) 0)))]
+ "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
+ == GET_MODE_BITSIZE (<MODE>mode) - 1"
+ [(set (match_dup 4) (match_dup 1))
+ (set (match_dup 0)
+ (any_rotate:SWI48 (match_dup 4)
+ (subreg:QI (match_dup 2) 0)))]
+ "operands[4] = gen_reg_rtx (<MODE>mode);")
+
(define_insn_and_split "*<rotate_insn><mode>3_mask_1"
[(set (match_operand:SWI48 0 "nonimmediate_operand")
(any_rotate:SWI48
@@ -11898,6 +12015,20 @@
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])])
+(define_split
+ [(set (match_operand:SWI48 0 "register_operand")
+ (any_rotate:SWI48
+ (match_operand:SWI48 1 "const_int_operand")
+ (and:QI
+ (match_operand:QI 2 "register_operand")
+ (match_operand:QI 3 "const_int_operand"))))]
+ "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
+ == GET_MODE_BITSIZE (<MODE>mode) - 1"
+ [(set (match_dup 4) (match_dup 1))
+ (set (match_dup 0)
+ (any_rotate:SWI48 (match_dup 4) (match_dup 2)))]
+ "operands[4] = gen_reg_rtx (<MODE>mode);")
+
;; Implement rotation using two double-precision
;; shift instructions and a scratch register.
@@ -12562,12 +12693,10 @@
[(not:SWI (match_operand:SWI 2 "register_operand"))
(match_operand:SWI 3 "nonimmediate_operand")]))]
""
- [(parallel
- [(set (reg:CCC FLAGS_REG)
- (compare:CCC
- (plus:SWI (match_dup 2) (match_dup 3))
- (match_dup 2)))
- (clobber (scratch:SWI))])
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plus:SWI (match_dup 2) (match_dup 3))
+ (match_dup 2)))
(set (match_dup 0)
(match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)]))])
@@ -12578,12 +12707,10 @@
(match_operand 3 "const_int_operand")]))]
"TARGET_64BIT
&& IN_RANGE (exact_log2 (UINTVAL (operands[3]) + 1), 32, 63)"
- [(parallel
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ
- (lshiftrt:DI (match_dup 2) (match_dup 4))
- (const_int 0)))
- (clobber (scratch:DI))])
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ
+ (lshiftrt:DI (match_dup 2) (match_dup 4))
+ (const_int 0)))
(set (match_dup 0)
(match_op_dup 1 [(reg:CCZ FLAGS_REG) (const_int 0)]))]
{
@@ -12619,9 +12746,9 @@
operands[2] = gen_lowpart (QImode, operands[0]);
})
-(define_insn_and_split "*setcc_si_1_and"
- [(set (match_operand:SI 0 "register_operand" "=q")
- (match_operator:SI 1 "ix86_comparison_operator"
+(define_insn_and_split "*setcc_<mode>_1_and"
+ [(set (match_operand:SWI24 0 "register_operand" "=q")
+ (match_operator:SWI24 1 "ix86_comparison_operator"
[(reg FLAGS_REG) (const_int 0)]))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL
@@ -12629,7 +12756,7 @@
"#"
"&& reload_completed"
[(set (match_dup 2) (match_dup 1))
- (parallel [(set (match_dup 0) (zero_extend:SI (match_dup 2)))
+ (parallel [(set (match_dup 0) (zero_extend:SWI24 (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
{
operands[1] = shallow_copy_rtx (operands[1]);
@@ -12637,16 +12764,16 @@
operands[2] = gen_lowpart (QImode, operands[0]);
})
-(define_insn_and_split "*setcc_si_1_movzbl"
- [(set (match_operand:SI 0 "register_operand" "=q")
- (match_operator:SI 1 "ix86_comparison_operator"
+(define_insn_and_split "*setcc_<mode>_1_movzbl"
+ [(set (match_operand:SWI24 0 "register_operand" "=q")
+ (match_operator:SWI24 1 "ix86_comparison_operator"
[(reg FLAGS_REG) (const_int 0)]))]
"!TARGET_PARTIAL_REG_STALL
&& (!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun))"
"#"
"&& reload_completed"
[(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
+ (set (match_dup 0) (zero_extend:SWI24 (match_dup 2)))]
{
operands[1] = shallow_copy_rtx (operands[1]);
PUT_MODE (operands[1], QImode);
@@ -12774,12 +12901,10 @@
(label_ref (match_operand 0))
(pc)))]
""
- [(parallel
- [(set (reg:CCC FLAGS_REG)
- (compare:CCC
- (plus:SWI (match_dup 2) (match_dup 3))
- (match_dup 2)))
- (clobber (scratch:SWI))])
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plus:SWI (match_dup 2) (match_dup 3))
+ (match_dup 2)))
(set (pc)
(if_then_else (match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)])
(label_ref (match_operand 0))
@@ -12795,12 +12920,10 @@
(pc)))]
"TARGET_64BIT
&& IN_RANGE (exact_log2 (UINTVAL (operands[3]) + 1), 32, 63)"
- [(parallel
- [(set (reg:CCZ FLAGS_REG)
- (compare:CCZ
- (lshiftrt:DI (match_dup 2) (match_dup 4))
- (const_int 0)))
- (clobber (scratch:DI))])
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ
+ (lshiftrt:DI (match_dup 2) (match_dup 4))
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 1 [(reg:CCZ FLAGS_REG) (const_int 0)])
(label_ref (match_operand 0))
@@ -13662,10 +13785,13 @@
;; static chain pointer - the first instruction has to be pushl %esi
;; and it can't be moved around, as we use alternate entry points
;; in that case.
+;; Also disallow for ms_hook_prologue functions which have frame
+;; pointer set up in function label which is correctly handled in
+;; ix86_expand_{prologue|epligoue}() only.
(define_expand "simple_return"
[(simple_return)]
- "!TARGET_SEH && !ix86_static_chain_on_stack"
+ "!TARGET_SEH && !ix86_static_chain_on_stack && !ix86_function_ms_hook_prologue (cfun->decl)"
{
if (crtl->args.pops_args)
{
@@ -18115,6 +18241,22 @@
(const_string "*")))
(set_attr "mode" "QI")])
+(define_expand "cmpmemsi"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (compare:SI (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:BLK 2 "memory_operand" "") ) )
+ (use (match_operand 3 "general_operand"))
+ (use (match_operand 4 "immediate_operand"))]
+ ""
+{
+ if (ix86_expand_cmpstrn_or_cmpmem (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4], false))
+ DONE;
+ else
+ FAIL;
+})
+
(define_expand "cmpstrnsi"
[(set (match_operand:SI 0 "register_operand")
(compare:SI (match_operand:BLK 1 "general_operand")
@@ -18123,70 +18265,12 @@
(use (match_operand 4 "immediate_operand"))]
""
{
- rtx addr1, addr2, countreg, align, out;
-
- if (optimize_insn_for_size_p () && !TARGET_INLINE_ALL_STRINGOPS)
- FAIL;
-
- /* Can't use this if the user has appropriated ecx, esi or edi. */
- if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
- FAIL;
-
- /* One of the strings must be a constant. If so, expand_builtin_strncmp()
- will have rewritten the length arg to be the minimum of the const string
- length and the actual length arg. If both strings are the same and
- shorter than the length arg, repz cmpsb will not stop at the 0 byte and
- will incorrectly base the results on chars past the 0 byte. */
- tree t1 = MEM_EXPR (operands[1]);
- tree t2 = MEM_EXPR (operands[2]);
- if (!((t1 && TREE_CODE (t1) == MEM_REF
- && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0)) == STRING_CST)
- || (t2 && TREE_CODE (t2) == MEM_REF
- && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0)) == STRING_CST)))
- FAIL;
-
- addr1 = copy_addr_to_reg (XEXP (operands[1], 0));
- addr2 = copy_addr_to_reg (XEXP (operands[2], 0));
- if (addr1 != XEXP (operands[1], 0))
- operands[1] = replace_equiv_address_nv (operands[1], addr1);
- if (addr2 != XEXP (operands[2], 0))
- operands[2] = replace_equiv_address_nv (operands[2], addr2);
-
- /* NB: Make a copy of the data length to avoid changing the original
- data length by cmpstrnqi patterns. */
- rtx count = ix86_zero_extend_to_Pmode (operands[3]);
- countreg = gen_reg_rtx (Pmode);
- emit_move_insn (countreg, count);
-
- /* %%% Iff we are testing strict equality, we can use known alignment
- to good advantage. This may be possible with combine, particularly
- once cc0 is dead. */
- align = operands[4];
-
- if (CONST_INT_P (operands[3]))
- {
- if (operands[3] == const0_rtx)
- {
- emit_move_insn (operands[0], const0_rtx);
- DONE;
- }
- emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
- operands[1], operands[2]));
- }
+ if (ix86_expand_cmpstrn_or_cmpmem (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4], true))
+ DONE;
else
- {
- emit_insn (gen_cmp_1 (Pmode, countreg, countreg));
- emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
- operands[1], operands[2]));
- }
-
- out = gen_lowpart (QImode, operands[0]);
- emit_insn (gen_cmpintqi (out));
- emit_move_insn (operands[0], gen_rtx_SIGN_EXTEND (SImode, out));
-
- DONE;
+ FAIL;
})
;; Produce a tri-state integer (-1, 0, 1) from condition codes.
@@ -18489,9 +18573,8 @@
&& INTVAL (operands[2]) != -1
&& INTVAL (operands[2]) != 2147483647"
[(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
- (parallel [(set (match_dup 0)
- (neg:SWI48 (ltu:SWI48 (reg:CC FLAGS_REG) (const_int 0))))
- (clobber (reg:CC FLAGS_REG))])]
+ (set (match_dup 0)
+ (neg:SWI48 (ltu:SWI48 (reg:CC FLAGS_REG) (const_int 0))))]
"operands[2] = GEN_INT (INTVAL (operands[2]) + 1);")
(define_split
@@ -18502,9 +18585,8 @@
(const_int 0))))]
""
[(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (const_int 1)))
- (parallel [(set (match_dup 0)
- (neg:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))))
- (clobber (reg:CC FLAGS_REG))])])
+ (set (match_dup 0)
+ (neg:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))))])
(define_split
[(set (match_operand:SWI 0 "register_operand")
@@ -18513,13 +18595,10 @@
(match_operand 1 "int_nonimmediate_operand")
(const_int 0))))]
""
- [(parallel [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
- (clobber (match_dup 2))])
- (parallel [(set (match_dup 0)
- (neg:SWI (ltu:SWI (reg:CCC FLAGS_REG) (const_int 0))))
- (clobber (reg:CC FLAGS_REG))])]
- "operands[2] = gen_rtx_SCRATCH (GET_MODE (operands[1]));")
+ [(set (reg:CCC FLAGS_REG)
+ (ne:CCC (match_dup 1) (const_int 0)))
+ (set (match_dup 0)
+ (neg:SWI (ltu:SWI (reg:CCC FLAGS_REG) (const_int 0))))])
(define_insn "*mov<mode>cc_noc"
[(set (match_operand:SWI248 0 "register_operand" "=r,r")
@@ -18911,33 +18990,92 @@
(define_expand "<code><mode>3"
[(parallel
- [(set (match_operand:SWI248 0 "register_operand")
- (maxmin:SWI248
- (match_operand:SWI248 1 "register_operand")
- (match_operand:SWI248 2 "general_operand")))
+ [(set (match_operand:SDWIM 0 "register_operand")
+ (maxmin:SDWIM
+ (match_operand:SDWIM 1 "register_operand")
+ (match_operand:SDWIM 2 "general_operand")))
(clobber (reg:CC FLAGS_REG))])]
- "TARGET_CMOVE")
+ "TARGET_CMOVE
+ && (<MODE>mode != QImode || !TARGET_PARTIAL_REG_STALL)")
+
+(define_insn_and_split "*<code><dwi>3_doubleword"
+ [(set (match_operand:<DWI> 0 "register_operand")
+ (maxmin:<DWI>
+ (match_operand:<DWI> 1 "register_operand")
+ (match_operand:<DWI> 2 "general_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_CMOVE
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (if_then_else:DWIH (match_dup 6)
+ (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 3)
+ (if_then_else:DWIH (match_dup 6)
+ (match_dup 4)
+ (match_dup 5)))]
+{
+ operands[2] = force_reg (<DWI>mode, operands[2]);
+
+ split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
+
+ rtx cmplo[2] = { operands[1], operands[2] };
+ rtx cmphi[2] = { operands[4], operands[5] };
+
+ enum rtx_code code = <maxmin_rel>;
+
+ switch (code)
+ {
+ case LE: case LEU:
+ std::swap (cmplo[0], cmplo[1]);
+ std::swap (cmphi[0], cmphi[1]);
+ code = swap_condition (code);
+ /* FALLTHRU */
+
+ case GE: case GEU:
+ {
+ bool uns = (code == GEU);
+ rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
+ = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
+
+ emit_insn (gen_cmp_1 (<MODE>mode, cmplo[0], cmplo[1]));
+
+ rtx tmp = gen_rtx_SCRATCH (<MODE>mode);
+ emit_insn (sbb_insn (<MODE>mode, tmp, cmphi[0], cmphi[1]));
+
+ rtx flags = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
+ operands[6] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
+
+ break;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+})
(define_insn_and_split "*<code><mode>3_1"
- [(set (match_operand:SWI248 0 "register_operand")
- (maxmin:SWI248
- (match_operand:SWI248 1 "register_operand")
- (match_operand:SWI248 2 "general_operand")))
+ [(set (match_operand:SWI 0 "register_operand")
+ (maxmin:SWI
+ (match_operand:SWI 1 "register_operand")
+ (match_operand:SWI 2 "general_operand")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_CMOVE
+ && (<MODE>mode != QImode || !TARGET_PARTIAL_REG_STALL)
&& ix86_pre_reload_split ()"
"#"
"&& 1"
[(set (match_dup 0)
- (if_then_else:SWI248 (match_dup 3)
+ (if_then_else:SWI (match_dup 3)
(match_dup 1)
(match_dup 2)))]
{
machine_mode mode = <MODE>mode;
rtx cmp_op = operands[2];
- if (!register_operand (cmp_op, mode))
- operands[2] = force_reg (mode, cmp_op);
+ operands[2] = force_reg (mode, cmp_op);
enum rtx_code code = <maxmin_rel>;
@@ -18973,64 +19111,6 @@
operands[3] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
})
-(define_insn_and_split "*<code>di3_doubleword"
- [(set (match_operand:DI 0 "register_operand")
- (maxmin:DI (match_operand:DI 1 "register_operand")
- (match_operand:DI 2 "general_operand")))
- (clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT && TARGET_CMOVE
- && ix86_pre_reload_split ()"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (if_then_else:SI (match_dup 6)
- (match_dup 1)
- (match_dup 2)))
- (set (match_dup 3)
- (if_then_else:SI (match_dup 6)
- (match_dup 4)
- (match_dup 5)))]
-{
- if (!register_operand (operands[2], DImode))
- operands[2] = force_reg (DImode, operands[2]);
-
- split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
-
- rtx cmplo[2] = { operands[1], operands[2] };
- rtx cmphi[2] = { operands[4], operands[5] };
-
- enum rtx_code code = <maxmin_rel>;
-
- switch (code)
- {
- case LE: case LEU:
- std::swap (cmplo[0], cmplo[1]);
- std::swap (cmphi[0], cmphi[1]);
- code = swap_condition (code);
- /* FALLTHRU */
-
- case GE: case GEU:
- {
- bool uns = (code == GEU);
- rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
- = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
-
- emit_insn (gen_cmp_1 (SImode, cmplo[0], cmplo[1]));
-
- rtx tmp = gen_rtx_SCRATCH (SImode);
- emit_insn (sbb_insn (SImode, tmp, cmphi[0], cmphi[1]));
-
- rtx flags = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
- operands[6] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
-
- break;
- }
-
- default:
- gcc_unreachable ();
- }
-})
-
;; Avoid clearing a register between a flags setting comparison and its use,
;; i.e. prefer "xorl %eax,%eax; test/cmp" over "test/cmp; movl $0, %eax".
(define_peephole2
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index e6b1695..be3a6cd 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -49,6 +49,16 @@ int recip_mask_explicit
TargetSave
int x_recip_mask_explicit
+;; A copy of flag_excess_precision as a target variable that should
+;; force a different DECL_FUNCTION_SPECIFIC_TARGET upon
+;; flag_excess_precision changes.
+TargetVariable
+enum excess_precision ix86_excess_precision = EXCESS_PRECISION_DEFAULT
+
+;; Similarly for flag_unsafe_math_optimizations.
+TargetVariable
+bool ix86_unsafe_math_optimizations = false
+
;; Definitions to add to the cl_target_option structure
;; -march= processor
TargetSave
@@ -184,35 +194,35 @@ enum ix86_veclibabi x_ix86_veclibabi_type
;; x86 options
m128bit-long-double
-Target RejectNegative Report Mask(128BIT_LONG_DOUBLE) Save
+Target RejectNegative Mask(128BIT_LONG_DOUBLE) Save
sizeof(long double) is 16.
m80387
-Target Report Mask(80387) Save
+Target Mask(80387) Save
Use hardware fp.
m96bit-long-double
-Target RejectNegative Report InverseMask(128BIT_LONG_DOUBLE) Save
+Target RejectNegative InverseMask(128BIT_LONG_DOUBLE) Save
sizeof(long double) is 12.
mlong-double-80
-Target Report RejectNegative Negative(mlong-double-64) InverseMask(LONG_DOUBLE_64) Save
+Target RejectNegative Negative(mlong-double-64) InverseMask(LONG_DOUBLE_64) Save
Use 80-bit long double.
mlong-double-64
-Target Report RejectNegative Negative(mlong-double-128) Mask(LONG_DOUBLE_64) InverseMask(LONG_DOUBLE_128) Save
+Target RejectNegative Negative(mlong-double-128) Mask(LONG_DOUBLE_64) InverseMask(LONG_DOUBLE_128) Save
Use 64-bit long double.
mlong-double-128
-Target Report RejectNegative Negative(mlong-double-80) Mask(LONG_DOUBLE_128) InverseMask(LONG_DOUBLE_64) Save
+Target RejectNegative Negative(mlong-double-80) Mask(LONG_DOUBLE_128) InverseMask(LONG_DOUBLE_64) Save
Use 128-bit long double.
maccumulate-outgoing-args
-Target Report Mask(ACCUMULATE_OUTGOING_ARGS) Save
+Target Mask(ACCUMULATE_OUTGOING_ARGS) Save
Reserve space for outgoing arguments in the function prologue.
malign-double
-Target Report Mask(ALIGN_DOUBLE) Save
+Target Mask(ALIGN_DOUBLE) Save
Align some doubles on dword boundary.
malign-functions=
@@ -228,7 +238,7 @@ Target RejectNegative Joined UInteger
Loop code aligned to this power of 2.
malign-stringops
-Target RejectNegative Report InverseMask(NO_ALIGN_STRINGOPS, ALIGN_STRINGOPS) Save
+Target RejectNegative InverseMask(NO_ALIGN_STRINGOPS, ALIGN_STRINGOPS) Save
Align destination of the string operations.
malign-data=
@@ -315,15 +325,15 @@ mcpu=
Target RejectNegative Joined Undocumented Alias(mtune=) Warn(%<-mcpu=%> is deprecated; use %<-mtune=%> or %<-march=%> instead)
mfancy-math-387
-Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save
+Target RejectNegative InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save
Generate sin, cos, sqrt for FPU.
mforce-drap
-Target Report Var(ix86_force_drap)
+Target Var(ix86_force_drap)
Always use Dynamic Realigned Argument Pointer (DRAP) to realign stack.
mfp-ret-in-387
-Target Report Mask(FLOAT_RETURNS) Save
+Target Mask(FLOAT_RETURNS) Save
Return values of functions in FPU registers.
mfpmath=
@@ -360,50 +370,50 @@ Target RejectNegative Mask(80387) Save
Use hardware fp.
mieee-fp
-Target Report Mask(IEEE_FP) Save
+Target Mask(IEEE_FP) Save
Use IEEE math for fp comparisons.
minline-all-stringops
-Target Report Mask(INLINE_ALL_STRINGOPS) Save
+Target Mask(INLINE_ALL_STRINGOPS) Save
Inline all known string operations.
minline-stringops-dynamically
-Target Report Mask(INLINE_STRINGOPS_DYNAMICALLY) Save
+Target Mask(INLINE_STRINGOPS_DYNAMICALLY) Save
Inline memset/memcpy string operations, but perform inline version only for small blocks.
mintel-syntax
Target Undocumented Alias(masm=, intel, att) Warn(%<-mintel-syntax%> and %<-mno-intel-syntax%> are deprecated; use %<-masm=intel%> and %<-masm=att%> instead)
mms-bitfields
-Target Report Mask(MS_BITFIELD_LAYOUT) Save
+Target Mask(MS_BITFIELD_LAYOUT) Save
Use native (MS) bitfield layout.
mno-align-stringops
-Target RejectNegative Report Mask(NO_ALIGN_STRINGOPS) Undocumented Save
+Target RejectNegative Mask(NO_ALIGN_STRINGOPS) Undocumented Save
mno-fancy-math-387
-Target RejectNegative Report Mask(NO_FANCY_MATH_387) Undocumented Save
+Target RejectNegative Mask(NO_FANCY_MATH_387) Undocumented Save
mno-push-args
-Target RejectNegative Report Mask(NO_PUSH_ARGS) Undocumented Save
+Target RejectNegative Mask(NO_PUSH_ARGS) Undocumented Save
mno-red-zone
-Target RejectNegative Report Mask(NO_RED_ZONE) Undocumented Save
+Target RejectNegative Mask(NO_RED_ZONE) Undocumented Save
momit-leaf-frame-pointer
-Target Report Mask(OMIT_LEAF_FRAME_POINTER) Save
+Target Mask(OMIT_LEAF_FRAME_POINTER) Save
Omit the frame pointer in leaf functions.
mpc32
-Target RejectNegative Report
+Target RejectNegative
Set 80387 floating-point precision to 32-bit.
mpc64
-Target RejectNegative Report
+Target RejectNegative
Set 80387 floating-point precision to 64-bit.
mpc80
-Target RejectNegative Report
+Target RejectNegative
Set 80387 floating-point precision to 80-bit.
mpreferred-stack-boundary=
@@ -415,11 +425,11 @@ Target RejectNegative Joined UInteger Var(ix86_incoming_stack_boundary_arg)
Assume incoming stack aligned to this power of 2.
mpush-args
-Target Report InverseMask(NO_PUSH_ARGS, PUSH_ARGS) Save
+Target InverseMask(NO_PUSH_ARGS, PUSH_ARGS) Save
Use push instructions to save outgoing arguments.
mred-zone
-Target RejectNegative Report InverseMask(NO_RED_ZONE, RED_ZONE) Save
+Target RejectNegative InverseMask(NO_RED_ZONE, RED_ZONE) Save
Use red-zone in the x86-64 code.
mregparm=
@@ -427,7 +437,7 @@ Target RejectNegative Joined UInteger Var(ix86_regparm)
Number of registers used to pass integer arguments.
mrtd
-Target Report Mask(RTD) Save
+Target Mask(RTD) Save
Alternate calling convention.
msoft-float
@@ -439,11 +449,11 @@ Target RejectNegative Mask(SSEREGPARM) Save
Use SSE register passing conventions for SF and DF mode.
mstackrealign
-Target Report Var(ix86_force_align_arg_pointer)
+Target Var(ix86_force_align_arg_pointer)
Realign stack in prologue.
mstack-arg-probe
-Target Report Mask(STACK_PROBE) Save
+Target Mask(STACK_PROBE) Save
Enable stack probing.
mmemcpy-strategy=
@@ -501,7 +511,7 @@ EnumValue
Enum(tls_dialect) String(gnu2) Value(TLS_DIALECT_GNU2)
mtls-direct-seg-refs
-Target Report Mask(TLS_DIRECT_SEG_REFS)
+Target Mask(TLS_DIRECT_SEG_REFS)
Use direct references against %gs when accessing tls data.
mtune=
@@ -520,7 +530,7 @@ mdump-tune-features
Target RejectNegative Var(ix86_dump_tunes)
miamcu
-Target Report Mask(IAMCU)
+Target Mask(IAMCU)
Generate code that conforms to Intel MCU psABI.
mabi=
@@ -538,7 +548,7 @@ EnumValue
Enum(calling_abi) String(ms) Value(MS_ABI)
mcall-ms2sysv-xlogues
-Target Report Mask(CALL_MS2SYSV_XLOGUES) Save
+Target Mask(CALL_MS2SYSV_XLOGUES) Save
Use libgcc stubs to save and restore registers clobbered by 64-bit Microsoft to System V ABI calls.
mveclibabi=
@@ -556,28 +566,28 @@ EnumValue
Enum(ix86_veclibabi) String(acml) Value(ix86_veclibabi_type_acml)
mvect8-ret-in-mem
-Target Report Mask(VECT8_RETURNS) Save
+Target Mask(VECT8_RETURNS) Save
Return 8-byte vectors in memory.
mrecip
-Target Report Mask(RECIP) Save
+Target Mask(RECIP) Save
Generate reciprocals instead of divss and sqrtss.
mrecip=
-Target Report RejectNegative Joined Var(ix86_recip_name)
+Target RejectNegative Joined Var(ix86_recip_name)
Control generation of reciprocal estimates.
mcld
-Target Report Mask(CLD) Save
+Target Mask(CLD) Save
Generate cld instruction in the function prologue.
mvzeroupper
-Target Report Mask(VZEROUPPER) Save
+Target Mask(VZEROUPPER) Save
Generate vzeroupper instruction before a transfer of control flow out of
the function.
mstv
-Target Report Mask(STV) Save
+Target Mask(STV) Save
Disable Scalar to Vector optimization pass transforming 64-bit integer
computations into a vector ones.
@@ -591,7 +601,7 @@ Target Alias(mprefer-vector-width=, 128, 256)
Use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer.
mprefer-vector-width=
-Target Report RejectNegative Joined Var(prefer_vector_width_type) Enum(prefer_vector_width) Init(PVW_NONE) Save
+Target RejectNegative Joined Var(prefer_vector_width_type) Enum(prefer_vector_width) Init(PVW_NONE) Save
Use given register vector width instructions instead of maximum register width in the auto-vectorizer.
Enum
@@ -613,63 +623,63 @@ Enum(prefer_vector_width) String(512) Value(PVW_AVX512)
;; ISA support
m32
-Target RejectNegative Negative(m64) Report InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
+Target RejectNegative Negative(m64) InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
Generate 32bit i386 code.
m64
-Target RejectNegative Negative(mx32) Report Mask(ABI_64) Var(ix86_isa_flags) Save
+Target RejectNegative Negative(mx32) Mask(ABI_64) Var(ix86_isa_flags) Save
Generate 64bit x86-64 code.
mx32
-Target RejectNegative Negative(m16) Report Mask(ABI_X32) Var(ix86_isa_flags) Save
+Target RejectNegative Negative(m16) Mask(ABI_X32) Var(ix86_isa_flags) Save
Generate 32bit x86-64 code.
m16
-Target RejectNegative Negative(m32) Report Mask(CODE16) InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
+Target RejectNegative Negative(m32) Mask(CODE16) InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
Generate 16bit i386 code.
mmmx
-Target Report Mask(ISA_MMX) Var(ix86_isa_flags) Save
+Target Mask(ISA_MMX) Var(ix86_isa_flags) Save
Support MMX built-in functions.
m3dnow
-Target Report Mask(ISA_3DNOW) Var(ix86_isa_flags) Save
+Target Mask(ISA_3DNOW) Var(ix86_isa_flags) Save
Support 3DNow! built-in functions.
m3dnowa
-Target Report Mask(ISA_3DNOW_A) Var(ix86_isa_flags) Save
+Target Mask(ISA_3DNOW_A) Var(ix86_isa_flags) Save
Support Athlon 3Dnow! built-in functions.
msse
-Target Report Mask(ISA_SSE) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSE) Var(ix86_isa_flags) Save
Support MMX and SSE built-in functions and code generation.
msse2
-Target Report Mask(ISA_SSE2) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSE2) Var(ix86_isa_flags) Save
Support MMX, SSE and SSE2 built-in functions and code generation.
msse3
-Target Report Mask(ISA_SSE3) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSE3) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2 and SSE3 built-in functions and code generation.
mssse3
-Target Report Mask(ISA_SSSE3) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSSE3) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3 and SSSE3 built-in functions and code generation.
msse4.1
-Target Report Mask(ISA_SSE4_1) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSE4_1) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 built-in functions and code generation.
msse4.2
-Target Report Mask(ISA_SSE4_2) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSE4_2) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation.
msse4
-Target RejectNegative Report Mask(ISA_SSE4_2) Var(ix86_isa_flags) Save
+Target RejectNegative Mask(ISA_SSE4_2) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation.
mno-sse4
-Target RejectNegative Report InverseMask(ISA_SSE4_1) Var(ix86_isa_flags) Save
+Target RejectNegative InverseMask(ISA_SSE4_1) Var(ix86_isa_flags) Save
Do not support SSE4.1 and SSE4.2 built-in functions and code generation.
msse5
@@ -677,262 +687,262 @@ Target Undocumented Alias(mavx) Warn(%<-msse5%> was removed)
;; Deprecated
mavx
-Target Report Mask(ISA_AVX) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX built-in functions and code generation.
mavx2
-Target Report Mask(ISA_AVX2) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX2) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 built-in functions and code generation.
mavx512f
-Target Report Mask(ISA_AVX512F) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512F) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F built-in functions and code generation.
mavx512pf
-Target Report Mask(ISA_AVX512PF) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512PF) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512PF built-in functions and code generation.
mavx512er
-Target Report Mask(ISA_AVX512ER) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512ER) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512ER built-in functions and code generation.
mavx512cd
-Target Report Mask(ISA_AVX512CD) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512CD) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512CD built-in functions and code generation.
mavx512dq
-Target Report Mask(ISA_AVX512DQ) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512DQ) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512DQ built-in functions and code generation.
mavx512bw
-Target Report Mask(ISA_AVX512BW) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512BW) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512BW built-in functions and code generation.
mavx512vl
-Target Report Mask(ISA_AVX512VL) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512VL) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512VL built-in functions and code generation.
mavx512ifma
-Target Report Mask(ISA_AVX512IFMA) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512IFMA) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512IFMA built-in functions and code generation.
mavx512vbmi
-Target Report Mask(ISA_AVX512VBMI) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512VBMI) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512VBMI built-in functions and code generation.
mavx5124fmaps
-Target Report Mask(ISA2_AVX5124FMAPS) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AVX5124FMAPS) Var(ix86_isa_flags2) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX5124FMAPS built-in functions and code generation.
mavx5124vnniw
-Target Report Mask(ISA2_AVX5124VNNIW) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AVX5124VNNIW) Var(ix86_isa_flags2) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX5124VNNIW built-in functions and code generation.
mavx512vpopcntdq
-Target Report Mask(ISA_AVX512VPOPCNTDQ) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512VPOPCNTDQ) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VPOPCNTDQ built-in functions and code generation.
mavx512vbmi2
-Target Report Mask(ISA_AVX512VBMI2) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512VBMI2) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VBMI2 built-in functions and code generation.
mavx512vnni
-Target Report Mask(ISA_AVX512VNNI) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512VNNI) Var(ix86_isa_flags) Save
Support AVX512VNNI built-in functions and code generation.
mavx512bitalg
-Target Report Mask(ISA_AVX512BITALG) Var(ix86_isa_flags) Save
+Target Mask(ISA_AVX512BITALG) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512BITALG built-in functions and code generation.
mavx512vp2intersect
-Target Report Mask(ISA2_AVX512VP2INTERSECT) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AVX512VP2INTERSECT) Var(ix86_isa_flags2) Save
Support AVX512VP2INTERSECT built-in functions and code generation.
mfma
-Target Report Mask(ISA_FMA) Var(ix86_isa_flags) Save
+Target Mask(ISA_FMA) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation.
msse4a
-Target Report Mask(ISA_SSE4A) Var(ix86_isa_flags) Save
+Target Mask(ISA_SSE4A) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3 and SSE4A built-in functions and code generation.
mfma4
-Target Report Mask(ISA_FMA4) Var(ix86_isa_flags) Save
+Target Mask(ISA_FMA4) Var(ix86_isa_flags) Save
Support FMA4 built-in functions and code generation.
mxop
-Target Report Mask(ISA_XOP) Var(ix86_isa_flags) Save
+Target Mask(ISA_XOP) Var(ix86_isa_flags) Save
Support XOP built-in functions and code generation.
mlwp
-Target Report Mask(ISA_LWP) Var(ix86_isa_flags) Save
+Target Mask(ISA_LWP) Var(ix86_isa_flags) Save
Support LWP built-in functions and code generation.
mabm
-Target Report Mask(ISA_ABM) Var(ix86_isa_flags) Save
+Target Mask(ISA_ABM) Var(ix86_isa_flags) Save
Support code generation of Advanced Bit Manipulation (ABM) instructions.
mpopcnt
-Target Report Mask(ISA_POPCNT) Var(ix86_isa_flags) Save
+Target Mask(ISA_POPCNT) Var(ix86_isa_flags) Save
Support code generation of popcnt instruction.
mpconfig
-Target Report Mask(ISA2_PCONFIG) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_PCONFIG) Var(ix86_isa_flags2) Save
Support PCONFIG built-in functions and code generation.
mwbnoinvd
-Target Report Mask(ISA2_WBNOINVD) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_WBNOINVD) Var(ix86_isa_flags2) Save
Support WBNOINVD built-in functions and code generation.
mptwrite
-Target Report Mask(ISA2_PTWRITE) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_PTWRITE) Var(ix86_isa_flags2) Save
Support PTWRITE built-in functions and code generation.
muintr
-Target Report Mask(ISA2_UINTR) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_UINTR) Var(ix86_isa_flags2) Save
Support UINTR built-in functions and code generation.
msgx
-Target Report Mask(ISA2_SGX) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_SGX) Var(ix86_isa_flags2) Save
Support SGX built-in functions and code generation.
mrdpid
-Target Report Mask(ISA2_RDPID) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_RDPID) Var(ix86_isa_flags2) Save
Support RDPID built-in functions and code generation.
mgfni
-Target Report Mask(ISA_GFNI) Var(ix86_isa_flags) Save
+Target Mask(ISA_GFNI) Var(ix86_isa_flags) Save
Support GFNI built-in functions and code generation.
mvaes
-Target Report Mask(ISA2_VAES) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_VAES) Var(ix86_isa_flags2) Save
Support VAES built-in functions and code generation.
mvpclmulqdq
-Target Report Mask(ISA_VPCLMULQDQ) Var(ix86_isa_flags) Save
+Target Mask(ISA_VPCLMULQDQ) Var(ix86_isa_flags) Save
Support VPCLMULQDQ built-in functions and code generation.
mbmi
-Target Report Mask(ISA_BMI) Var(ix86_isa_flags) Save
+Target Mask(ISA_BMI) Var(ix86_isa_flags) Save
Support BMI built-in functions and code generation.
mbmi2
-Target Report Mask(ISA_BMI2) Var(ix86_isa_flags) Save
+Target Mask(ISA_BMI2) Var(ix86_isa_flags) Save
Support BMI2 built-in functions and code generation.
mlzcnt
-Target Report Mask(ISA_LZCNT) Var(ix86_isa_flags) Save
+Target Mask(ISA_LZCNT) Var(ix86_isa_flags) Save
Support LZCNT built-in function and code generation.
mhle
-Target Report Mask(ISA2_HLE) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_HLE) Var(ix86_isa_flags2) Save
Support Hardware Lock Elision prefixes.
mrdseed
-Target Report Mask(ISA_RDSEED) Var(ix86_isa_flags) Save
+Target Mask(ISA_RDSEED) Var(ix86_isa_flags) Save
Support RDSEED instruction.
mprfchw
-Target Report Mask(ISA_PRFCHW) Var(ix86_isa_flags) Save
+Target Mask(ISA_PRFCHW) Var(ix86_isa_flags) Save
Support PREFETCHW instruction.
madx
-Target Report Mask(ISA_ADX) Var(ix86_isa_flags) Save
+Target Mask(ISA_ADX) Var(ix86_isa_flags) Save
Support flag-preserving add-carry instructions.
mclflushopt
-Target Report Mask(ISA_CLFLUSHOPT) Var(ix86_isa_flags) Save
+Target Mask(ISA_CLFLUSHOPT) Var(ix86_isa_flags) Save
Support CLFLUSHOPT instructions.
mclwb
-Target Report Mask(ISA_CLWB) Var(ix86_isa_flags) Save
+Target Mask(ISA_CLWB) Var(ix86_isa_flags) Save
Support CLWB instruction.
mpcommit
Target WarnRemoved
mfxsr
-Target Report Mask(ISA_FXSR) Var(ix86_isa_flags) Save
+Target Mask(ISA_FXSR) Var(ix86_isa_flags) Save
Support FXSAVE and FXRSTOR instructions.
mxsave
-Target Report Mask(ISA_XSAVE) Var(ix86_isa_flags) Save
+Target Mask(ISA_XSAVE) Var(ix86_isa_flags) Save
Support XSAVE and XRSTOR instructions.
mxsaveopt
-Target Report Mask(ISA_XSAVEOPT) Var(ix86_isa_flags) Save
+Target Mask(ISA_XSAVEOPT) Var(ix86_isa_flags) Save
Support XSAVEOPT instruction.
mxsavec
-Target Report Mask(ISA_XSAVEC) Var(ix86_isa_flags) Save
+Target Mask(ISA_XSAVEC) Var(ix86_isa_flags) Save
Support XSAVEC instructions.
mxsaves
-Target Report Mask(ISA_XSAVES) Var(ix86_isa_flags) Save
+Target Mask(ISA_XSAVES) Var(ix86_isa_flags) Save
Support XSAVES and XRSTORS instructions.
mtbm
-Target Report Mask(ISA_TBM) Var(ix86_isa_flags) Save
+Target Mask(ISA_TBM) Var(ix86_isa_flags) Save
Support TBM built-in functions and code generation.
mcx16
-Target Report Mask(ISA2_CX16) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_CX16) Var(ix86_isa_flags2) Save
Support code generation of cmpxchg16b instruction.
msahf
-Target Report Mask(ISA_SAHF) Var(ix86_isa_flags) Save
+Target Mask(ISA_SAHF) Var(ix86_isa_flags) Save
Support code generation of sahf instruction in 64bit x86-64 code.
mmovbe
-Target Report Mask(ISA2_MOVBE) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_MOVBE) Var(ix86_isa_flags2) Save
Support code generation of movbe instruction.
mcrc32
-Target Report Mask(ISA_CRC32) Var(ix86_isa_flags) Save
+Target Mask(ISA_CRC32) Var(ix86_isa_flags) Save
Support code generation of crc32 instruction.
maes
-Target Report Mask(ISA_AES) Var(ix86_isa_flags) Save
+Target Mask(ISA_AES) Var(ix86_isa_flags) Save
Support AES built-in functions and code generation.
msha
-Target Report Mask(ISA_SHA) Var(ix86_isa_flags) Save
+Target Mask(ISA_SHA) Var(ix86_isa_flags) Save
Support SHA1 and SHA256 built-in functions and code generation.
mpclmul
-Target Report Mask(ISA_PCLMUL) Var(ix86_isa_flags) Save
+Target Mask(ISA_PCLMUL) Var(ix86_isa_flags) Save
Support PCLMUL built-in functions and code generation.
msse2avx
-Target Report Var(ix86_sse2avx)
+Target Var(ix86_sse2avx)
Encode SSE instructions with VEX prefix.
mfsgsbase
-Target Report Mask(ISA_FSGSBASE) Var(ix86_isa_flags) Save
+Target Mask(ISA_FSGSBASE) Var(ix86_isa_flags) Save
Support FSGSBASE built-in functions and code generation.
mrdrnd
-Target Report Mask(ISA_RDRND) Var(ix86_isa_flags) Save
+Target Mask(ISA_RDRND) Var(ix86_isa_flags) Save
Support RDRND built-in functions and code generation.
mf16c
-Target Report Mask(ISA_F16C) Var(ix86_isa_flags) Save
+Target Mask(ISA_F16C) Var(ix86_isa_flags) Save
Support F16C built-in functions and code generation.
mprefetchwt1
-Target Report Mask(ISA_PREFETCHWT1) Var(ix86_isa_flags) Save
+Target Mask(ISA_PREFETCHWT1) Var(ix86_isa_flags) Save
Support PREFETCHWT1 built-in functions and code generation.
mfentry
-Target Report Var(flag_fentry)
+Target Var(flag_fentry)
Emit profiling counter call at function entry before prologue.
mrecord-mcount
-Target Report Var(flag_record_mcount)
+Target Var(flag_record_mcount)
Generate __mcount_loc section with all mcount or __fentry__ calls.
mnop-mcount
-Target Report Var(flag_nop_mcount)
+Target Var(flag_nop_mcount)
Generate mcount/__fentry__ calls as nops. To activate they need to be
patched in.
@@ -945,23 +955,23 @@ Target RejectNegative Joined Var(fentry_section)
Set name of section to record mrecord-mcount calls.
mskip-rax-setup
-Target Report Var(flag_skip_rax_setup)
+Target Var(flag_skip_rax_setup)
Skip setting up RAX register when passing variable arguments.
m8bit-idiv
-Target Report Mask(USE_8BIT_IDIV) Save
+Target Mask(USE_8BIT_IDIV) Save
Expand 32bit/64bit integer divide into 8bit unsigned integer divide with run-time check.
mavx256-split-unaligned-load
-Target Report Mask(AVX256_SPLIT_UNALIGNED_LOAD) Save
+Target Mask(AVX256_SPLIT_UNALIGNED_LOAD) Save
Split 32-byte AVX unaligned load.
mavx256-split-unaligned-store
-Target Report Mask(AVX256_SPLIT_UNALIGNED_STORE) Save
+Target Mask(AVX256_SPLIT_UNALIGNED_STORE) Save
Split 32-byte AVX unaligned store.
mrtm
-Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save
+Target Mask(ISA_RTM) Var(ix86_isa_flags) Save
Support RTM built-in functions and code generation.
mmpx
@@ -969,15 +979,15 @@ Target WarnRemoved
Removed in GCC 9. This switch has no effect.
mmwaitx
-Target Report Mask(ISA2_MWAITX) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_MWAITX) Var(ix86_isa_flags2) Save
Support MWAITX and MONITORX built-in functions and code generation.
mclzero
-Target Report Mask(ISA2_CLZERO) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_CLZERO) Var(ix86_isa_flags2) Save
Support CLZERO built-in functions and code generation.
mpku
-Target Report Mask(ISA_PKU) Var(ix86_isa_flags) Save
+Target Mask(ISA_PKU) Var(ix86_isa_flags) Save
Support PKU built-in functions and code generation.
mstack-protector-guard=
@@ -1016,34 +1026,34 @@ mmitigate-rop
Target WarnRemoved
mgeneral-regs-only
-Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
+Target RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
Generate code which uses only the general registers.
mshstk
-Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags) Save
+Target Mask(ISA_SHSTK) Var(ix86_isa_flags) Save
Enable shadow stack built-in functions from Control-flow Enforcement
Technology (CET).
mcet-switch
-Target Report Undocumented Var(flag_cet_switch) Init(0)
+Target Undocumented Var(flag_cet_switch) Init(0)
Turn on CET instrumentation for switch statements that use a jump table and
an indirect jump.
mmanual-endbr
-Target Report Var(flag_manual_endbr) Init(0)
+Target Var(flag_manual_endbr) Init(0)
Insert ENDBR instruction at function entry only via cf_check attribute
for CET instrumentation.
mforce-indirect-call
-Target Report Var(flag_force_indirect_call) Init(0)
+Target Var(flag_force_indirect_call) Init(0)
Make all function calls indirect.
mindirect-branch=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
Convert indirect call and jump to call and return thunks.
mfunction-return=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
Convert function return to call and return thunk.
Enum
@@ -1063,27 +1073,27 @@ EnumValue
Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
mindirect-branch-register
-Target Report Var(ix86_indirect_branch_register) Init(0)
+Target Var(ix86_indirect_branch_register) Init(0)
Force indirect call and jump via register.
mmovdiri
-Target Report Mask(ISA_MOVDIRI) Var(ix86_isa_flags) Save
+Target Mask(ISA_MOVDIRI) Var(ix86_isa_flags) Save
Support MOVDIRI built-in functions and code generation.
mmovdir64b
-Target Report Mask(ISA2_MOVDIR64B) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_MOVDIR64B) Var(ix86_isa_flags2) Save
Support MOVDIR64B built-in functions and code generation.
mwaitpkg
-Target Report Mask(ISA2_WAITPKG) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_WAITPKG) Var(ix86_isa_flags2) Save
Support WAITPKG built-in functions and code generation.
mcldemote
-Target Report Mask(ISA2_CLDEMOTE) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_CLDEMOTE) Var(ix86_isa_flags2) Save
Support CLDEMOTE built-in functions and code generation.
minstrument-return=
-Target Report RejectNegative Joined Enum(instrument_return) Var(ix86_instrument_return) Init(instrument_return_none)
+Target RejectNegative Joined Enum(instrument_return) Var(ix86_instrument_return) Init(instrument_return_none)
Instrument function exit in instrumented functions with __fentry__.
Enum
@@ -1100,38 +1110,55 @@ EnumValue
Enum(instrument_return) String(nop5) Value(instrument_return_nop5)
mrecord-return
-Target Report Var(ix86_flag_record_return) Init(0)
+Target Var(ix86_flag_record_return) Init(0)
Generate a __return_loc section pointing to all return instrumentation code.
mavx512bf16
-Target Report Mask(ISA2_AVX512BF16) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AVX512BF16) Var(ix86_isa_flags2) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and
AVX512BF16 built-in functions and code generation.
menqcmd
-Target Report Mask(ISA2_ENQCMD) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_ENQCMD) Var(ix86_isa_flags2) Save
Support ENQCMD built-in functions and code generation.
mserialize
-Target Report Mask(ISA2_SERIALIZE) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_SERIALIZE) Var(ix86_isa_flags2) Save
Support SERIALIZE built-in functions and code generation.
mtsxldtrk
-Target Report Mask(ISA2_TSXLDTRK) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_TSXLDTRK) Var(ix86_isa_flags2) Save
Support TSXLDTRK built-in functions and code generation.
mamx-tile
-Target Report Mask(ISA2_AMX_TILE) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AMX_TILE) Var(ix86_isa_flags2) Save
Support AMX-TILE built-in functions and code generation.
mamx-int8
-Target Report Mask(ISA2_AMX_INT8) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AMX_INT8) Var(ix86_isa_flags2) Save
Support AMX-INT8 built-in functions and code generation.
mamx-bf16
-Target Report Mask(ISA2_AMX_BF16) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_AMX_BF16) Var(ix86_isa_flags2) Save
Support AMX-BF16 built-in functions and code generation.
mhreset
-Target Report Mask(ISA2_HRESET) Var(ix86_isa_flags2) Save
+Target Mask(ISA2_HRESET) Var(ix86_isa_flags2) Save
Support HRESET built-in functions and code generation.
+
+mkl
+Target Mask(ISA2_KL) Var(ix86_isa_flags2) Save
+Support KL built-in functions and code generation.
+
+mwidekl
+Target Mask(ISA2_WIDEKL) Var(ix86_isa_flags2) Save
+Support WIDEKL built-in functions and code generation.
+
+mavxvnni
+Target Mask(ISA2_AVXVNNI) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and
+AVXVNNI built-in functions and code generation.
+
+mneeded
+Target Var(ix86_needed) Save
+Emit GNU_PROPERTY_X86_ISA_1_NEEDED GNU property.
diff --git a/gcc/config/i386/i386elf.h b/gcc/config/i386/i386elf.h
index eb2203c..05cee89 100644
--- a/gcc/config/i386/i386elf.h
+++ b/gcc/config/i386/i386elf.h
@@ -19,12 +19,12 @@ 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/>. */
-/* The ELF ABI for the i386 says that records and unions are returned
- in memory. */
-
-#define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \
- (TYPE_MODE (TYPE) == BLKmode \
- || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8))
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 because the i386 SVR4 ABI returns
+ records and unions in memory. ix86_option_override_internal will overide
+ this flag when compiling 64-bit code as we never do pcc_struct_return
+ scheme on x86-64. */
+#undef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 1
#undef CPP_SPEC
#define CPP_SPEC ""
@@ -40,56 +40,6 @@ along with GCC; see the file COPYING3. If not see
#define DBX_REGISTER_NUMBER(n) \
(TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n])
-/* The routine used to output sequences of byte values. We use a special
- version of this for most svr4 targets because doing so makes the
- generated assembly code more compact (and thus faster to assemble)
- as well as more readable. Note that if we find subparts of the
- character sequence which end with NUL (and which are shorter than
- ELF_STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
-
-#undef ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
- do \
- { \
- const unsigned char *_ascii_bytes = \
- (const unsigned char *) (STR); \
- const unsigned char *limit = _ascii_bytes + (LENGTH); \
- unsigned bytes_in_chunk = 0; \
- for (; _ascii_bytes < limit; _ascii_bytes++) \
- { \
- const unsigned char *p; \
- if (bytes_in_chunk >= 64) \
- { \
- fputc ('\n', (FILE)); \
- bytes_in_chunk = 0; \
- } \
- for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
- continue; \
- if (p < limit && (p - _ascii_bytes) <= (long) ELF_STRING_LIMIT) \
- { \
- if (bytes_in_chunk > 0) \
- { \
- fputc ('\n', (FILE)); \
- bytes_in_chunk = 0; \
- } \
- ASM_OUTPUT_LIMITED_STRING ((FILE), (const char *) _ascii_bytes); \
- _ascii_bytes = p; \
- } \
- else \
- { \
- if (bytes_in_chunk == 0) \
- fputs (ASM_BYTE, (FILE)); \
- else \
- fputc (',', (FILE)); \
- fprintf ((FILE), "0x%02x", *_ascii_bytes); \
- bytes_in_chunk += 5; \
- } \
- } \
- if (bytes_in_chunk > 0) \
- fputc ('\n', (FILE)); \
- } \
- while (0)
-
#define LOCAL_LABEL_PREFIX "."
/* Switch into a generic section. */
diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
index 71eae83..b787967 100644
--- a/gcc/config/i386/immintrin.h
+++ b/gcc/config/i386/immintrin.h
@@ -42,6 +42,8 @@
#include <avxintrin.h>
+#include <avxvnniintrin.h>
+
#include <avx2intrin.h>
#include <avx512fintrin.h>
@@ -118,4 +120,6 @@
#include <prfchwintrin.h>
+#include <keylockerintrin.h>
+
#endif /* _IMMINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/keylockerintrin.h b/gcc/config/i386/keylockerintrin.h
new file mode 100644
index 0000000..a5f29fd
--- /dev/null
+++ b/gcc/config/i386/keylockerintrin.h
@@ -0,0 +1,129 @@
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _IMMINTRIN_H_INCLUDED
+# error "Never use <keylockerintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _KEYLOCKERINTRIN_H_INCLUDED
+#define _KEYLOCKERINTRIN_H_INCLUDED
+
+#ifndef __KL__
+#pragma GCC push_options
+#pragma GCC target("kl")
+#define __DISABLE_KL__
+#endif /* __KL__ */
+
+
+extern __inline
+void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_loadiwkey (unsigned int __I, __m128i __A, __m128i __B, __m128i __C)
+{
+ __builtin_ia32_loadiwkey ((__v2di) __B, (__v2di) __C, (__v2di) __A, __I);
+}
+
+extern __inline
+unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_encodekey128_u32 (unsigned int __I, __m128i __A, void * __P)
+{
+ return __builtin_ia32_encodekey128_u32 (__I, (__v2di)__A, __P);
+}
+
+extern __inline
+unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_encodekey256_u32 (unsigned int __I, __m128i __A, __m128i __B, void * __P)
+{
+ return __builtin_ia32_encodekey256_u32 (__I, (__v2di)__A, (__v2di)__B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesdec128kl_u8 (__m128i * __A, __m128i __B, const void * __P)
+{
+ return __builtin_ia32_aesdec128kl_u8 ((__v2di *) __A, (__v2di) __B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesdec256kl_u8 (__m128i * __A, __m128i __B, const void * __P)
+{
+ return __builtin_ia32_aesdec256kl_u8 ((__v2di *) __A, (__v2di) __B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesenc128kl_u8 (__m128i * __A, __m128i __B, const void * __P)
+{
+ return __builtin_ia32_aesenc128kl_u8 ((__v2di *) __A, (__v2di) __B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesenc256kl_u8 (__m128i * __A, __m128i __B, const void * __P)
+{
+ return __builtin_ia32_aesenc256kl_u8 ((__v2di *) __A, (__v2di) __B, __P);
+}
+
+#ifdef __DISABLE_KL__
+#undef __DISABLE_KL__
+#pragma GCC pop_options
+#endif /* __DISABLE_KL__ */
+
+#ifndef __WIDEKL__
+#pragma GCC push_options
+#pragma GCC target("widekl")
+#define __DISABLE_WIDEKL__
+#endif /* __WIDEKL__ */
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesdecwide128kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P)
+{
+ return __builtin_ia32_aesdecwide128kl_u8 ((__v2di *) __A, (__v2di *) __B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesdecwide256kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P)
+{
+ return __builtin_ia32_aesdecwide256kl_u8 ((__v2di *) __A, (__v2di *) __B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesencwide128kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P)
+{
+ return __builtin_ia32_aesencwide128kl_u8 ((__v2di *) __A, (__v2di *) __B, __P);
+}
+
+extern __inline
+unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesencwide256kl_u8(__m128i __A[8], const __m128i __B[8], const void * __P)
+{
+ return __builtin_ia32_aesencwide256kl_u8 ((__v2di *) __A, (__v2di *) __B, __P);
+}
+#ifdef __DISABLE_WIDEKL__
+#undef __DISABLE_WIDEKL__
+#pragma GCC pop_options
+#endif /* __DISABLE_WIDEKL__ */
+#endif /* _KEYLOCKERINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h
index 1ae6b3f..da0fabb 100644
--- a/gcc/config/i386/linux-common.h
+++ b/gcc/config/i386/linux-common.h
@@ -30,9 +30,6 @@ along with GCC; see the file COPYING3. If not see
#define EXTRA_TARGET_D_OS_VERSIONS() \
ANDROID_TARGET_D_OS_VERSIONS();
-#define GNU_USER_TARGET_D_CRITSEC_SIZE \
- (TARGET_64BIT ? (POINTER_SIZE == 64 ? 40 : 32) : 24)
-
#undef CC1_SPEC
#define CC1_SPEC \
LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC, \
@@ -68,7 +65,7 @@ along with GCC; see the file COPYING3. If not see
#define MPX_LD_AS_NEEDED_GUARD_POP ""
#endif
-extern void file_end_indicate_exec_stack_and_cet (void);
+extern void file_end_indicate_exec_stack_and_gnu_property (void);
#undef TARGET_ASM_FILE_END
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_cet
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_gnu_property
diff --git a/gcc/config/i386/msformat-c.c b/gcc/config/i386/msformat-c.c
index 4ceec63..085ac88 100644
--- a/gcc/config/i386/msformat-c.c
+++ b/gcc/config/i386/msformat-c.c
@@ -32,10 +32,11 @@ along with GCC; see the file COPYING3. If not see
static format_length_info ms_printf_length_specs[] =
{
{ "h", FMT_LEN_h, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 },
- { "l", FMT_LEN_l, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 },
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
+ { "L", FMT_LEN_L, STD_C89, NULL, FMT_LEN_none, STD_C89, 1 },
{ "I32", FMT_LEN_l, STD_EXT, NULL, FMT_LEN_none, STD_C89, 1 },
{ "I64", FMT_LEN_ll, STD_EXT, NULL, FMT_LEN_none, STD_C89, 1 },
- { "I", FMT_LEN_L, STD_EXT, NULL, FMT_LEN_none, STD_C89, 1 },
+ { "I", FMT_LEN_z, STD_EXT, NULL, FMT_LEN_none, STD_C89, 1 },
{ NULL, FMT_LEN_none, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 }
};
@@ -90,33 +91,35 @@ static const format_flag_pair ms_strftime_flag_pairs[] =
static const format_char_info ms_print_char_table[] =
{
/* C89 conversion specifiers. */
- { "di", 0, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, T99_SST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +'", "i", NULL },
- { "oxX", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
- { "u", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0'", "i", NULL },
- { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "", NULL },
- { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL },
- { "c", 0, STD_C89, { T89_I, BADLEN, T89_S, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL },
- { "n", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
+ { "di", 0, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +'", "i", NULL },
+ { "oxX", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
+ { "u", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0'", "i", NULL },
+ { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "", NULL },
+ { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL },
+ { "c", 0, STD_C89, { T89_I, BADLEN, T89_S, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
+ { "s", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
+ { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL },
+ { "n", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
+ /* C99 conversion specifiers. */
+ { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL },
/* X/Open conversion specifiers. */
- { "C", 0, STD_EXT, { TEX_WI, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
- { "S", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
+ { "C", 0, STD_EXT, { TEX_WI, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
+ { "S", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
static const format_char_info ms_scan_char_table[] =
{
/* C89 conversion specifiers. */
- { "di", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, T99_SST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
- { "u", 1, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
- { "oxX", 1, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
- { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
- { "c", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW", NULL },
- { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[", NULL },
- { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
- { "n", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
+ { "di", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "u", 1, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "oxX", 1, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
+ { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "c", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL },
+ { "s", 1, STD_C89, { T89_C, BADLEN, T89_S, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW", NULL },
+ { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[", NULL },
+ { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
+ { "n", 1, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
/* X/Open conversion specifiers. */
{ "C", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, T89_S, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W", NULL },
@@ -182,9 +185,9 @@ extern void TARGET_OVERRIDES_FORMAT_INIT (void);
void
TARGET_OVERRIDES_FORMAT_INIT (void)
{
- ms_printf_length_specs[2].std = C89_OR_EXT; /* I32 */
- ms_printf_length_specs[3].std = C89_OR_EXT; /* I64 */
- ms_printf_length_specs[4].std = C89_OR_EXT; /* I */
+ ms_printf_length_specs[3].std = C89_OR_EXT; /* I32 */
+ ms_printf_length_specs[4].std = C89_OR_EXT; /* I64 */
+ ms_printf_length_specs[5].std = C89_OR_EXT; /* I */
}
#undef C89_OR_EXT
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index be57cda..be5aaa4 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1023,6 +1023,12 @@
return op == const1_rtx || op == constm1_rtx;
})
+;; True for registers, or const_int_operand, used to vec_setm expander.
+(define_predicate "vec_setm_operand"
+ (ior (and (match_operand 0 "register_operand")
+ (match_test "TARGET_AVX2"))
+ (match_code "const_int")))
+
;; True for registers, or 1 or -1. Used to optimize double-word shifts.
(define_predicate "reg_or_pm1_operand"
(ior (match_operand 0 "register_operand")
@@ -1726,3 +1732,121 @@
}
return (i >= 12 && i <= 18);
})
+
+;; Keylocker specific predicates
+(define_predicate "encodekey128_operation"
+ (match_code "parallel")
+{
+ unsigned i;
+ rtx elt;
+
+ if (XVECLEN (op, 0) != 8)
+ return false;
+
+ for(i = 0; i < 3; i++)
+ {
+ elt = XVECEXP (op, 0, i + 1);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V2DImode
+ || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
+ || GET_CODE (SET_SRC (elt)) != UNSPEC_VOLATILE
+ || GET_MODE (SET_SRC (elt)) != V2DImode
+ || XVECLEN(SET_SRC (elt), 0) != 1
+ || XVECEXP(SET_SRC (elt), 0, 0) != const0_rtx)
+ return false;
+ }
+
+ for(i = 4; i < 7; i++)
+ {
+ elt = XVECEXP (op, 0, i);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V2DImode
+ || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
+ || SET_SRC (elt) != CONST0_RTX (V2DImode))
+ return false;
+ }
+
+ elt = XVECEXP (op, 0, 7);
+ if (GET_CODE (elt) != CLOBBER
+ || GET_MODE (elt) != VOIDmode
+ || GET_CODE (XEXP (elt, 0)) != REG
+ || GET_MODE (XEXP (elt, 0)) != CCmode
+ || REGNO (XEXP (elt, 0)) != FLAGS_REG)
+ return false;
+ return true;
+})
+
+(define_predicate "encodekey256_operation"
+ (match_code "parallel")
+{
+ unsigned i;
+ rtx elt;
+
+ if (XVECLEN (op, 0) != 9)
+ return false;
+
+ elt = SET_SRC (XVECEXP (op, 0, 0));
+ elt = XVECEXP (elt, 0, 2);
+ if (!REG_P (elt)
+ || REGNO(elt) != GET_SSE_REGNO (1))
+ return false;
+
+ for(i = 0; i < 4; i++)
+ {
+ elt = XVECEXP (op, 0, i + 1);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V2DImode
+ || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
+ || GET_CODE (SET_SRC (elt)) != UNSPEC_VOLATILE
+ || GET_MODE (SET_SRC (elt)) != V2DImode
+ || XVECLEN(SET_SRC (elt), 0) != 1
+ || XVECEXP(SET_SRC (elt), 0, 0) != const0_rtx)
+ return false;
+ }
+
+ for(i = 4; i < 7; i++)
+ {
+ elt = XVECEXP (op, 0, i + 1);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V2DImode
+ || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
+ || SET_SRC (elt) != CONST0_RTX (V2DImode))
+ return false;
+ }
+
+ elt = XVECEXP (op, 0, 8);
+ if (GET_CODE (elt) != CLOBBER
+ || GET_MODE (elt) != VOIDmode
+ || GET_CODE (XEXP (elt, 0)) != REG
+ || GET_MODE (XEXP (elt, 0)) != CCmode
+ || REGNO (XEXP (elt, 0)) != FLAGS_REG)
+ return false;
+ return true;
+})
+
+
+(define_predicate "aeswidekl_operation"
+ (match_code "parallel")
+{
+ unsigned i;
+ rtx elt;
+
+ for (i = 0; i < 8; i++)
+ {
+ elt = XVECEXP (op, 0, i + 1);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V2DImode
+ || REGNO (SET_DEST (elt)) != GET_SSE_REGNO (i)
+ || GET_CODE (SET_SRC (elt)) != UNSPEC_VOLATILE
+ || GET_MODE (SET_SRC (elt)) != V2DImode
+ || XVECLEN (SET_SRC (elt), 0) != 1
+ || REGNO (XVECEXP (SET_SRC (elt), 0, 0)) != GET_SSE_REGNO (i))
+ return false;
+ }
+ return true;
+})
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 52635f6..d841038 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -111,6 +111,8 @@
UNSPEC_MASKOP
UNSPEC_KORTEST
UNSPEC_KTEST
+ ;; Mask load
+ UNSPEC_MASKLOAD
;; For embed. rounding feature
UNSPEC_EMBEDDED_ROUNDING
@@ -205,6 +207,19 @@
UNSPECV_MWAIT
UNSPECV_VZEROALL
UNSPECV_VZEROUPPER
+
+ ;; For KEYLOCKER
+ UNSPECV_LOADIWKEY
+ UNSPECV_AESDEC128KLU8
+ UNSPECV_AESENC128KLU8
+ UNSPECV_AESDEC256KLU8
+ UNSPECV_AESENC256KLU8
+ UNSPECV_AESDECWIDE128KLU8
+ UNSPECV_AESENCWIDE128KLU8
+ UNSPECV_AESDECWIDE256KLU8
+ UNSPECV_AESENCWIDE256KLU8
+ UNSPECV_ENCODEKEY128U32
+ UNSPECV_ENCODEKEY256U32
])
;; All vector modes including V?TImode, used in move patterns.
@@ -453,6 +468,10 @@
[(V4TI "TARGET_AVX512BW") (V2TI "TARGET_AVX2") TI])
(define_mode_iterator VI12_AVX2
+ [(V32QI "TARGET_AVX2") V16QI
+ (V16HI "TARGET_AVX2") V8HI])
+
+(define_mode_iterator VI12_AVX2_AVX512BW
[(V64QI "TARGET_AVX512BW") (V32QI "TARGET_AVX2") V16QI
(V32HI "TARGET_AVX512BW") (V16HI "TARGET_AVX2") V8HI])
@@ -1052,18 +1071,39 @@
]
(symbol_ref "true")))])
-(define_insn "<avx512>_load<mode>_mask"
- [(set (match_operand:V48_AVX512VL 0 "register_operand" "=v,v")
+;; If mem_addr points to a memory region with less than whole vector size bytes
+;; of accessible memory and k is a mask that would prevent reading the inaccessible
+;; bytes from mem_addr, add UNSPEC_MASKLOAD to prevent it to be transformed to vpblendd
+;; See pr97642.
+(define_expand "<avx512>_load<mode>_mask"
+ [(set (match_operand:V48_AVX512VL 0 "register_operand")
(vec_merge:V48_AVX512VL
- (match_operand:V48_AVX512VL 1 "nonimmediate_operand" "vm,vm")
- (match_operand:V48_AVX512VL 2 "nonimm_or_0_operand" "0C,v")
- (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk,Yk")))]
+ (match_operand:V48_AVX512VL 1 "nonimmediate_operand")
+ (match_operand:V48_AVX512VL 2 "nonimm_or_0_operand")
+ (match_operand:<avx512fmaskmode> 3 "register_or_constm1_operand")))]
"TARGET_AVX512F"
{
- if (REG_P (operands[2])
- && REGNO (operands[2]) != REGNO (operands[0]))
- return "v<sseintprefix>blendm<ssemodesuffix>\t{%1, %2, %0%{%3%}|%0%{%3%}, %2, %1}";
+ if (CONST_INT_P (operands[3]))
+ {
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
+ DONE;
+ }
+ else if (MEM_P (operands[1]))
+ operands[1] = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec(1, operands[1]),
+ UNSPEC_MASKLOAD);
+})
+(define_insn "*<avx512>_load<mode>_mask"
+ [(set (match_operand:V48_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:V48_AVX512VL
+ (unspec:V48_AVX512VL
+ [(match_operand:V48_AVX512VL 1 "memory_operand" "m")]
+ UNSPEC_MASKLOAD)
+ (match_operand:V48_AVX512VL 2 "nonimm_or_0_operand" "0C")
+ (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk")))]
+ "TARGET_AVX512F"
+{
if (FLOAT_MODE_P (GET_MODE_INNER (<MODE>mode)))
{
if (misaligned_operand (operands[1], <MODE>mode))
@@ -1083,20 +1123,60 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "<avx512>_load<mode>_mask"
- [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v,v")
+(define_insn_and_split "*<avx512>_load<mode>"
+ [(set (match_operand:V48_AVX512VL 0 "register_operand")
+ (unspec:V48_AVX512VL
+ [(match_operand:V48_AVX512VL 1 "memory_operand")]
+ UNSPEC_MASKLOAD))]
+ "TARGET_AVX512F"
+ "#"
+ "&& 1"
+ [(set (match_dup 0) (match_dup 1))])
+
+(define_expand "<avx512>_load<mode>_mask"
+ [(set (match_operand:VI12_AVX512VL 0 "register_operand")
(vec_merge:VI12_AVX512VL
- (match_operand:VI12_AVX512VL 1 "nonimmediate_operand" "vm,vm")
- (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand" "0C,v")
- (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk,Yk")))]
+ (match_operand:VI12_AVX512VL 1 "nonimmediate_operand")
+ (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand")
+ (match_operand:<avx512fmaskmode> 3 "register_or_constm1_operand")))]
"TARGET_AVX512BW"
- "@
- vmovdqu<ssescalarsize>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}
- vpblendm<ssemodesuffix>\t{%1, %2, %0%{%3%}|%0%{%3%}, %2, %1}"
+{
+ if (CONST_INT_P (operands[3]))
+ {
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
+ DONE;
+ }
+ else if (MEM_P (operands[1]))
+ operands[1] = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec(1, operands[1]),
+ UNSPEC_MASKLOAD);
+
+})
+
+(define_insn "*<avx512>_load<mode>_mask"
+ [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
+ (vec_merge:VI12_AVX512VL
+ (unspec:VI12_AVX512VL
+ [(match_operand:VI12_AVX512VL 1 "memory_operand" "m")]
+ UNSPEC_MASKLOAD)
+ (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand" "0C")
+ (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk")))]
+ "TARGET_AVX512BW"
+ "vmovdqu<ssescalarsize>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn_and_split "*<avx512>_load<mode>"
+ [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
+ (unspec:VI12_AVX512VL
+ [(match_operand:VI12_AVX512VL 1 "memory_operand" "m")]
+ UNSPEC_MASKLOAD))]
+ "TARGET_AVX512BW"
+ "#"
+ "&& 1"
+ [(set (match_dup 0) (match_dup 1))])
+
(define_insn "avx512f_mov<ssescalarmodelower>_mask"
[(set (match_operand:VF_128 0 "register_operand" "=v")
(vec_merge:VF_128
@@ -1158,21 +1238,50 @@
(set_attr "memory" "store")
(set_attr "mode" "<MODE>")])
-(define_expand "<avx512>_blendm<mode>"
- [(set (match_operand:V48_AVX512VL 0 "register_operand" "=v")
+(define_insn "<avx512>_blendm<mode>"
+ [(set (match_operand:V48_AVX512VL 0 "register_operand" "=v,v")
(vec_merge:V48_AVX512VL
- (match_operand:V48_AVX512VL 2 "nonimmediate_operand" "vm")
- (match_operand:V48_AVX512VL 1 "register_operand" "v")
- (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk")))]
- "TARGET_AVX512F")
+ (match_operand:V48_AVX512VL 2 "nonimmediate_operand" "vm,vm")
+ (match_operand:V48_AVX512VL 1 "nonimm_or_0_operand" "0C,v")
+ (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk,Yk")))]
+ "TARGET_AVX512F"
+{
+ if (REG_P (operands[1])
+ && REGNO (operands[1]) != REGNO (operands[0]))
+ return "v<sseintprefix>blendm<ssemodesuffix>\t{%2, %1, %0%{%3%}|%0%{%3%}, %1, %2}";
-(define_expand "<avx512>_blendm<mode>"
- [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
+ if (FLOAT_MODE_P (GET_MODE_INNER (<MODE>mode)))
+ {
+ if (misaligned_operand (operands[2], <MODE>mode))
+ return "vmovu<ssemodesuffix>\t{%2, %0%{%3%}%N1|%0%{%3%}%N1, %2}";
+ else
+ return "vmova<ssemodesuffix>\t{%2, %0%{%3%}%N1|%0%{%3%}%N1, %2}";
+ }
+ else
+ {
+ if (misaligned_operand (operands[2], <MODE>mode))
+ return "vmovdqu<ssescalarsize>\t{%2, %0%{%3%}%N1|%0%{%3%}%N1, %2}";
+ else
+ return "vmovdqa<ssescalarsize>\t{%2, %0%{%3%}%N1|%0%{%3%}%N1, %2}";
+ }
+}
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "<avx512>_blendm<mode>"
+ [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v,v")
(vec_merge:VI12_AVX512VL
- (match_operand:VI12_AVX512VL 2 "nonimmediate_operand" "vm")
- (match_operand:VI12_AVX512VL 1 "register_operand" "v")
- (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk")))]
- "TARGET_AVX512BW")
+ (match_operand:VI12_AVX512VL 2 "nonimmediate_operand" "vm,vm")
+ (match_operand:VI12_AVX512VL 1 "nonimm_or_0_operand" "0C,v")
+ (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk,Yk")))]
+ "TARGET_AVX512BW"
+ "@
+ vmovdqu<ssescalarsize>\t{%2, %0%{%3%}%N1|%0%{%3%}%N1, %2}
+ vpblendm<ssemodesuffix>\t{%2, %1, %0%{%3%}|%0%{%3%}, %1, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
(define_insn "<avx512>_store<mode>_mask"
[(set (match_operand:V48_AVX512VL 0 "memory_operand" "=m")
@@ -2989,6 +3098,44 @@
(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_int_iterator UNSPEC_PCMP_ITER
+ [UNSPEC_PCMP UNSPEC_UNSIGNED_PCMP])
+
+(define_int_attr pcmp_signed_mask
+ [(UNSPEC_PCMP "3") (UNSPEC_UNSIGNED_PCMP "1")])
+
+;; PR96906 - optimize vpsubusw compared to 0 into vpcmpleuw or vpcmpnltuw.
+;; For signed comparison, handle EQ 0: NEQ 4,
+;; for unsigned comparison extra handle LE:2, NLE:6, equivalent to EQ and NEQ.
+
+(define_split
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
+ (unspec:<avx512fmaskmode>
+ [(us_minus:VI12_AVX512VL
+ (match_operand:VI12_AVX512VL 1 "vector_operand")
+ (match_operand:VI12_AVX512VL 2 "vector_operand"))
+ (match_operand:VI12_AVX512VL 3 "const0_operand")
+ (match_operand:SI 4 "const_0_to_7_operand")]
+ UNSPEC_PCMP_ITER))]
+ "TARGET_AVX512BW
+ && ix86_binary_operator_ok (US_MINUS, <MODE>mode, operands)
+ && (INTVAL (operands[4]) & <pcmp_signed_mask>) == 0"
+ [(const_int 0)]
+ {
+ /* LE: 2, NLT: 5, NLE: 6, LT: 1 */
+ int cmp_predicate = 2; /* LE */
+ if (MEM_P (operands[1]))
+ {
+ std::swap (operands[1], operands[2]);
+ cmp_predicate = 5; /* NLT (GE) */
+ }
+ if ((INTVAL (operands[4]) & 4) != 0)
+ cmp_predicate ^= 4; /* Invert the comparison to NLE (GT) or LT. */
+ emit_insn (gen_<avx512>_ucmp<mode>3 (operands[0], operands[1],operands[2],
+ GEN_INT (cmp_predicate)));
+ DONE;
+ })
+
(define_insn "avx512f_vmcmp<mode>3<round_saeonly_name>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(and:<avx512fmaskmode>
@@ -8085,11 +8232,14 @@
(define_expand "vec_set<mode>"
[(match_operand:V 0 "register_operand")
(match_operand:<ssescalarmode> 1 "register_operand")
- (match_operand 2 "const_int_operand")]
+ (match_operand 2 "vec_setm_operand")]
"TARGET_SSE"
{
- ix86_expand_vector_set (false, operands[0], operands[1],
- INTVAL (operands[2]));
+ if (CONST_INT_P (operands[2]))
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ else
+ ix86_expand_vector_set_var (operands[0], operands[1], operands[2]);
DONE;
})
@@ -11379,18 +11529,18 @@
(set_attr "mode" "<sseinsnmode>")])
(define_expand "<sse2_avx2>_<plusminus_insn><mode>3<mask_name>"
- [(set (match_operand:VI12_AVX2 0 "register_operand")
- (sat_plusminus:VI12_AVX2
- (match_operand:VI12_AVX2 1 "vector_operand")
- (match_operand:VI12_AVX2 2 "vector_operand")))]
+ [(set (match_operand:VI12_AVX2_AVX512BW 0 "register_operand")
+ (sat_plusminus:VI12_AVX2_AVX512BW
+ (match_operand:VI12_AVX2_AVX512BW 1 "vector_operand")
+ (match_operand:VI12_AVX2_AVX512BW 2 "vector_operand")))]
"TARGET_SSE2 && <mask_mode512bit_condition> && <mask_avx512bw_condition>"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*<sse2_avx2>_<plusminus_insn><mode>3<mask_name>"
- [(set (match_operand:VI12_AVX2 0 "register_operand" "=x,v")
- (sat_plusminus:VI12_AVX2
- (match_operand:VI12_AVX2 1 "vector_operand" "<comm>0,v")
- (match_operand:VI12_AVX2 2 "vector_operand" "xBm,vm")))]
+ [(set (match_operand:VI12_AVX2_AVX512BW 0 "register_operand" "=x,v")
+ (sat_plusminus:VI12_AVX2_AVX512BW
+ (match_operand:VI12_AVX2_AVX512BW 1 "vector_operand" "<comm>0,v")
+ (match_operand:VI12_AVX2_AVX512BW 2 "vector_operand" "xBm,vm")))]
"TARGET_SSE2 && <mask_mode512bit_condition> && <mask_avx512bw_condition>
&& ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
"@
@@ -11402,6 +11552,23 @@
(set_attr "prefix" "orig,maybe_evex")
(set_attr "mode" "TI")])
+;; PR96906 - optimize psubusw compared to 0 into pminuw compared to op0.
+(define_split
+ [(set (match_operand:VI12_AVX2 0 "register_operand")
+ (eq:VI12_AVX2
+ (us_minus:VI12_AVX2
+ (match_operand:VI12_AVX2 1 "vector_operand")
+ (match_operand:VI12_AVX2 2 "vector_operand"))
+ (match_operand:VI12_AVX2 3 "const0_operand")))]
+ "TARGET_SSE2
+ && (<MODE>mode != V8HImode || TARGET_SSE4_1)
+ && ix86_binary_operator_ok (US_MINUS, <MODE>mode, operands)"
+ [(set (match_dup 4)
+ (umin:VI12_AVX2 (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (eq:VI12_AVX2 (match_dup 4) (match_dup 1)))]
+ "operands[4] = gen_reg_rtx (<MODE>mode);")
+
(define_expand "mulv8qi3"
[(set (match_operand:V8QI 0 "register_operand")
(mult:V8QI (match_operand:V8QI 1 "register_operand")
@@ -12006,15 +12173,15 @@
})
(define_expand "uavg<mode>3_ceil"
- [(set (match_operand:VI12_AVX2 0 "register_operand")
- (truncate:VI12_AVX2
+ [(set (match_operand:VI12_AVX2_AVX512BW 0 "register_operand")
+ (truncate:VI12_AVX2_AVX512BW
(lshiftrt:<ssedoublemode>
(plus:<ssedoublemode>
(plus:<ssedoublemode>
(zero_extend:<ssedoublemode>
- (match_operand:VI12_AVX2 1 "vector_operand"))
+ (match_operand:VI12_AVX2_AVX512BW 1 "vector_operand"))
(zero_extend:<ssedoublemode>
- (match_operand:VI12_AVX2 2 "vector_operand")))
+ (match_operand:VI12_AVX2_AVX512BW 2 "vector_operand")))
(match_dup 3))
(const_int 1))))]
"TARGET_SSE2"
@@ -15728,15 +15895,15 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expand "<sse2_avx2>_uavg<mode>3<mask_name>"
- [(set (match_operand:VI12_AVX2 0 "register_operand")
- (truncate:VI12_AVX2
+ [(set (match_operand:VI12_AVX2_AVX512BW 0 "register_operand")
+ (truncate:VI12_AVX2_AVX512BW
(lshiftrt:<ssedoublemode>
(plus:<ssedoublemode>
(plus:<ssedoublemode>
(zero_extend:<ssedoublemode>
- (match_operand:VI12_AVX2 1 "vector_operand"))
+ (match_operand:VI12_AVX2_AVX512BW 1 "vector_operand"))
(zero_extend:<ssedoublemode>
- (match_operand:VI12_AVX2 2 "vector_operand")))
+ (match_operand:VI12_AVX2_AVX512BW 2 "vector_operand")))
(match_dup <mask_expand_op3>))
(const_int 1))))]
"TARGET_SSE2 && <mask_mode512bit_condition> && <mask_avx512bw_condition>"
@@ -15746,15 +15913,15 @@
})
(define_insn "*<sse2_avx2>_uavg<mode>3<mask_name>"
- [(set (match_operand:VI12_AVX2 0 "register_operand" "=x,v")
- (truncate:VI12_AVX2
+ [(set (match_operand:VI12_AVX2_AVX512BW 0 "register_operand" "=x,v")
+ (truncate:VI12_AVX2_AVX512BW
(lshiftrt:<ssedoublemode>
(plus:<ssedoublemode>
(plus:<ssedoublemode>
(zero_extend:<ssedoublemode>
- (match_operand:VI12_AVX2 1 "vector_operand" "%0,v"))
+ (match_operand:VI12_AVX2_AVX512BW 1 "vector_operand" "%0,v"))
(zero_extend:<ssedoublemode>
- (match_operand:VI12_AVX2 2 "vector_operand" "xBm,vm")))
+ (match_operand:VI12_AVX2_AVX512BW 2 "vector_operand" "xBm,vm")))
(match_operand:<ssedoublemode> <mask_expand_op3> "const1_operand"))
(const_int 1))))]
"TARGET_SSE2 && <mask_mode512bit_condition> && <mask_avx512bw_condition>
@@ -15932,6 +16099,53 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "SI")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec:SI
+ [(not:VI1_AVX2 (match_operand:VI1_AVX2 1 "register_operand"))]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE2"
+ [(set (match_dup 2)
+ (unspec:SI [(match_dup 1)] UNSPEC_MOVMSK))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = gen_reg_rtx (SImode);
+ if (GET_MODE_NUNITS (<MODE>mode) == 32)
+ operands[3] = gen_rtx_NOT (SImode, operands[2]);
+ else
+ {
+ operands[3]
+ = gen_int_mode ((HOST_WIDE_INT_1 << GET_MODE_NUNITS (<MODE>mode)) - 1,
+ SImode);
+ operands[3] = gen_rtx_XOR (SImode, operands[2], operands[3]);
+ }
+})
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec:SI
+ [(subreg:VI1_AVX2 (not (match_operand 1 "register_operand")) 0)]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE2
+ && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_VECTOR_INT
+ && GET_MODE_SIZE (GET_MODE (operands[1])) == <MODE_SIZE>"
+ [(set (match_dup 2)
+ (unspec:SI [(match_dup 1)] UNSPEC_MOVMSK))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = gen_reg_rtx (SImode);
+ operands[1] = gen_lowpart (<MODE>mode, operands[1]);
+ if (GET_MODE_NUNITS (<MODE>mode) == 32)
+ operands[3] = gen_rtx_NOT (SImode, operands[2]);
+ else
+ {
+ operands[3]
+ = gen_int_mode ((HOST_WIDE_INT_1 << GET_MODE_NUNITS (<MODE>mode)) - 1,
+ SImode);
+ operands[3] = gen_rtx_XOR (SImode, operands[2], operands[3]);
+ }
+})
+
(define_insn_and_split "*<sse2_avx2>_pmovmskb_lt"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI
@@ -17335,7 +17549,7 @@
(set_attr "prefix" "maybe_evex")
(set_attr "mode" "OI")])
-(define_expand "<code>v16qiv16hi2"
+(define_expand "<optab>v16qiv16hi2"
[(set (match_operand:V16HI 0 "register_operand")
(any_extend:V16HI
(match_operand:V16QI 1 "nonimmediate_operand")))]
@@ -17352,7 +17566,7 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_expand "<code>v32qiv32hi2"
+(define_expand "<optab>v32qiv32hi2"
[(set (match_operand:V32HI 0 "register_operand")
(any_extend:V32HI
(match_operand:V32QI 1 "nonimmediate_operand")))]
@@ -17407,7 +17621,7 @@
(any_extend:V8HI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V8QImode, 0);")
-(define_expand "<code>v8qiv8hi2"
+(define_expand "<optab>v8qiv8hi2"
[(set (match_operand:V8HI 0 "register_operand")
(any_extend:V8HI
(match_operand:V8QI 1 "nonimmediate_operand")))]
@@ -17431,7 +17645,7 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_expand "<code>v16qiv16si2"
+(define_expand "<optab>v16qiv16si2"
[(set (match_operand:V16SI 0 "register_operand")
(any_extend:V16SI
(match_operand:V16QI 1 "nonimmediate_operand")))]
@@ -17484,7 +17698,7 @@
(any_extend:V8SI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V8QImode, 0);")
-(define_expand "<code>v8qiv8si2"
+(define_expand "<optab>v8qiv8si2"
[(set (match_operand:V8SI 0 "register_operand")
(any_extend:V8SI
(match_operand:V8QI 1 "nonimmediate_operand")))]
@@ -17547,7 +17761,7 @@
(any_extend:V4SI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V4QImode, 0);")
-(define_expand "<code>v4qiv4si2"
+(define_expand "<optab>v4qiv4si2"
[(set (match_operand:V4SI 0 "register_operand")
(any_extend:V4SI
(match_operand:V4QI 1 "nonimmediate_operand")))]
@@ -17571,7 +17785,7 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_expand "<code>v16hiv16si2"
+(define_expand "<optab>v16hiv16si2"
[(set (match_operand:V16SI 0 "register_operand")
(any_extend:V16SI
(match_operand:V16HI 1 "nonimmediate_operand")))]
@@ -17588,7 +17802,7 @@
(set_attr "prefix" "maybe_evex")
(set_attr "mode" "OI")])
-(define_expand "<code>v8hiv8si2"
+(define_expand "<optab>v8hiv8si2"
[(set (match_operand:V8SI 0 "register_operand")
(any_extend:V8SI
(match_operand:V8HI 1 "nonimmediate_operand")))]
@@ -17639,7 +17853,7 @@
(any_extend:V4SI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V4HImode, 0);")
-(define_expand "<code>v4hiv4si2"
+(define_expand "<optab>v4hiv4si2"
[(set (match_operand:V4SI 0 "register_operand")
(any_extend:V4SI
(match_operand:V4HI 1 "nonimmediate_operand")))]
@@ -17697,7 +17911,7 @@
(any_extend:V8DI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V8QImode, 0);")
-(define_expand "<code>v8qiv8di2"
+(define_expand "<optab>v8qiv8di2"
[(set (match_operand:V8DI 0 "register_operand")
(any_extend:V8DI
(match_operand:V8QI 1 "nonimmediate_operand")))]
@@ -17758,7 +17972,7 @@
(any_extend:V4DI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V4QImode, 0);")
-(define_expand "<code>v4qiv4di2"
+(define_expand "<optab>v4qiv4di2"
[(set (match_operand:V4DI 0 "register_operand")
(any_extend:V4DI
(match_operand:V4QI 1 "nonimmediate_operand")))]
@@ -17786,7 +18000,7 @@
(set_attr "prefix" "orig,orig,maybe_evex")
(set_attr "mode" "TI")])
-(define_expand "<code>v2qiv2di2"
+(define_expand "<optab>v2qiv2di2"
[(set (match_operand:V2DI 0 "register_operand")
(any_extend:V2DI
(match_operand:V2QI 1 "register_operand")))]
@@ -17807,7 +18021,7 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_expand "<code>v8hiv8di2"
+(define_expand "<optab>v8hiv8di2"
[(set (match_operand:V8DI 0 "register_operand")
(any_extend:V8DI
(match_operand:V8HI 1 "nonimmediate_operand")))]
@@ -17856,7 +18070,7 @@
(any_extend:V4DI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V4HImode, 0);")
-(define_expand "<code>v4hiv4di2"
+(define_expand "<optab>v4hiv4di2"
[(set (match_operand:V4DI 0 "register_operand")
(any_extend:V4DI
(match_operand:V4HI 1 "nonimmediate_operand")))]
@@ -17917,7 +18131,7 @@
(any_extend:V2DI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V2HImode, 0);")
-(define_expand "<code>v2hiv2di2"
+(define_expand "<optab>v2hiv2di2"
[(set (match_operand:V2DI 0 "register_operand")
(any_extend:V2DI
(match_operand:V2HI 1 "nonimmediate_operand")))]
@@ -17941,7 +18155,7 @@
(set_attr "prefix" "evex")
(set_attr "mode" "XI")])
-(define_expand "<code>v8siv8di2"
+(define_expand "<optab>v8siv8di2"
[(set (match_operand:V8DI 0 "register_operand" "=v")
(any_extend:V8DI
(match_operand:V8SI 1 "nonimmediate_operand" "vm")))]
@@ -17958,7 +18172,7 @@
(set_attr "prefix_extra" "1")
(set_attr "mode" "OI")])
-(define_expand "<code>v4siv4di2"
+(define_expand "<optab>v4siv4di2"
[(set (match_operand:V4DI 0 "register_operand" "=v")
(any_extend:V4DI
(match_operand:V4SI 1 "nonimmediate_operand" "vm")))]
@@ -18007,7 +18221,7 @@
(any_extend:V2DI (match_dup 1)))]
"operands[1] = adjust_address_nv (operands[1], V2SImode, 0);")
-(define_expand "<code>v2siv2di2"
+(define_expand "<optab>v2siv2di2"
[(set (match_operand:V2DI 0 "register_operand")
(any_extend:V2DI
(match_operand:V2SI 1 "nonimmediate_operand")))]
@@ -22665,6 +22879,12 @@
(set_attr ("prefix") ("evex"))
(set_attr ("mode") ("TI"))])
+(define_expand "popcount<mode>2"
+ [(set (match_operand:VI48_AVX512VL 0 "register_operand")
+ (popcount:VI48_AVX512VL
+ (match_operand:VI48_AVX512VL 1 "nonimmediate_operand")))]
+ "TARGET_AVX512VPOPCNTDQ")
+
(define_insn "vpopcount<mode><mask_name>"
[(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v")
(popcount:VI48_AVX512VL
@@ -22709,6 +22929,12 @@
"TARGET_SSE && TARGET_64BIT"
"jmp\t%P1")
+(define_expand "popcount<mode>2"
+ [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
+ (popcount:VI12_AVX512VL
+ (match_operand:VI12_AVX512VL 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512BITALG")
+
(define_insn "vpopcount<mode><mask_name>"
[(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
(popcount:VI12_AVX512VL
@@ -22902,16 +23128,30 @@
[(set_attr ("prefix") ("evex"))
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "vpdpbusd_<mode>"
- [(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
- (unspec:VI4_AVX512VL
- [(match_operand:VI4_AVX512VL 1 "register_operand" "0")
- (match_operand:VI4_AVX512VL 2 "register_operand" "v")
- (match_operand:VI4_AVX512VL 3 "nonimmediate_operand" "vm")]
+(define_insn "vpdpbusd_v16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (unspec:V16SI
+ [(match_operand:V16SI 1 "register_operand" "0")
+ (match_operand:V16SI 2 "register_operand" "v")
+ (match_operand:V16SI 3 "nonimmediate_operand" "vm")]
UNSPEC_VPMADDUBSWACCD))]
"TARGET_AVX512VNNI"
- "vpdpbusd\t{%3, %2, %0|%0, %2, %3 }"
- [(set_attr ("prefix") ("evex"))])
+ "vpdpbusd\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("evex"))])
+
+(define_insn "vpdpbusd_<mode>"
+ [(set (match_operand:VI4_AVX2 0 "register_operand" "=x,v")
+ (unspec:VI4_AVX2
+ [(match_operand:VI4_AVX2 1 "register_operand" "0,0")
+ (match_operand:VI4_AVX2 2 "register_operand" "x,v")
+ (match_operand:VI4_AVX2 3 "nonimmediate_operand" "xm,vm")]
+ UNSPEC_VPMADDUBSWACCD))]
+ "TARGET_AVXVNNI || (TARGET_AVX512VNNI && TARGET_AVX512VL)"
+ "@
+ %{vex%} vpdpbusd\t{%3, %2, %0|%0, %2, %3}
+ vpdpbusd\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("vex,evex"))
+ (set_attr ("isa") ("avxvnni,avx512vnnivl"))])
(define_insn "vpdpbusd_<mode>_mask"
[(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
@@ -22956,17 +23196,30 @@
"vpdpbusd\t{%3, %2, %0%{%5%}%{z%}|%0%{%5%}%{z%}, %2, %3 }"
[(set_attr ("prefix") ("evex"))])
+(define_insn "vpdpbusds_v16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (unspec:V16SI
+ [(match_operand:V16SI 1 "register_operand" "0")
+ (match_operand:V16SI 2 "register_operand" "v")
+ (match_operand:V16SI 3 "nonimmediate_operand" "vm")]
+ UNSPEC_VPMADDUBSWACCSSD))]
+ "TARGET_AVX512VNNI"
+ "vpdpbusds\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("evex"))])
(define_insn "vpdpbusds_<mode>"
- [(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
- (unspec:VI4_AVX512VL
- [(match_operand:VI4_AVX512VL 1 "register_operand" "0")
- (match_operand:VI4_AVX512VL 2 "register_operand" "v")
- (match_operand:VI4_AVX512VL 3 "nonimmediate_operand" "vm")]
+ [(set (match_operand:VI4_AVX2 0 "register_operand" "=x,v")
+ (unspec:VI4_AVX2
+ [(match_operand:VI4_AVX2 1 "register_operand" "0,0")
+ (match_operand:VI4_AVX2 2 "register_operand" "x,v")
+ (match_operand:VI4_AVX2 3 "nonimmediate_operand" "xm,vm")]
UNSPEC_VPMADDUBSWACCSSD))]
- "TARGET_AVX512VNNI"
- "vpdpbusds\t{%3, %2, %0|%0, %2, %3 }"
- [(set_attr ("prefix") ("evex"))])
+ "TARGET_AVXVNNI || (TARGET_AVX512VNNI && TARGET_AVX512VL)"
+ "@
+ %{vex%} vpdpbusds\t{%3, %2, %0|%0, %2, %3}
+ vpdpbusds\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("vex,evex"))
+ (set_attr ("isa") ("avxvnni,avx512vnnivl"))])
(define_insn "vpdpbusds_<mode>_mask"
[(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
@@ -23011,17 +23264,30 @@
"vpdpbusds\t{%3, %2, %0%{%5%}%{z%}|%0%{%5%}%{z%}, %2, %3 }"
[(set_attr ("prefix") ("evex"))])
+(define_insn "vpdpwssd_v16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (unspec:V16SI
+ [(match_operand:V16SI 1 "register_operand" "0")
+ (match_operand:V16SI 2 "register_operand" "v")
+ (match_operand:V16SI 3 "nonimmediate_operand" "vm")]
+ UNSPEC_VPMADDWDACCD))]
+ "TARGET_AVX512VNNI"
+ "vpdpwssd\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("evex"))])
(define_insn "vpdpwssd_<mode>"
- [(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
- (unspec:VI4_AVX512VL
- [(match_operand:VI4_AVX512VL 1 "register_operand" "0")
- (match_operand:VI4_AVX512VL 2 "register_operand" "v")
- (match_operand:VI4_AVX512VL 3 "nonimmediate_operand" "vm")]
+ [(set (match_operand:VI4_AVX2 0 "register_operand" "=x,v")
+ (unspec:VI4_AVX2
+ [(match_operand:VI4_AVX2 1 "register_operand" "0,0")
+ (match_operand:VI4_AVX2 2 "register_operand" "x,v")
+ (match_operand:VI4_AVX2 3 "nonimmediate_operand" "xm,vm")]
UNSPEC_VPMADDWDACCD))]
- "TARGET_AVX512VNNI"
- "vpdpwssd\t{%3, %2, %0|%0, %2, %3 }"
- [(set_attr ("prefix") ("evex"))])
+ "TARGET_AVXVNNI || (TARGET_AVX512VNNI && TARGET_AVX512VL)"
+ "@
+ %{vex%} vpdpwssd\t{%3, %2, %0|%0, %2, %3}
+ vpdpwssd\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("vex,evex"))
+ (set_attr ("isa") ("avxvnni,avx512vnnivl"))])
(define_insn "vpdpwssd_<mode>_mask"
[(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
@@ -23066,17 +23332,30 @@
"vpdpwssd\t{%3, %2, %0%{%5%}%{z%}|%0%{%5%}%{z%}, %2, %3 }"
[(set_attr ("prefix") ("evex"))])
+(define_insn "vpdpwssds_v16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (unspec:V16SI
+ [(match_operand:V16SI 1 "register_operand" "0")
+ (match_operand:V16SI 2 "register_operand" "v")
+ (match_operand:V16SI 3 "nonimmediate_operand" "vm")]
+ UNSPEC_VPMADDWDACCSSD))]
+ "TARGET_AVX512VNNI"
+ "vpdpwssds\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("evex"))])
(define_insn "vpdpwssds_<mode>"
- [(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
- (unspec:VI4_AVX512VL
- [(match_operand:VI4_AVX512VL 1 "register_operand" "0")
- (match_operand:VI4_AVX512VL 2 "register_operand" "v")
- (match_operand:VI4_AVX512VL 3 "nonimmediate_operand" "vm")]
+ [(set (match_operand:VI4_AVX2 0 "register_operand" "=x,v")
+ (unspec:VI4_AVX2
+ [(match_operand:VI4_AVX2 1 "register_operand" "0,0")
+ (match_operand:VI4_AVX2 2 "register_operand" "x,v")
+ (match_operand:VI4_AVX2 3 "nonimmediate_operand" "xm,vm")]
UNSPEC_VPMADDWDACCSSD))]
- "TARGET_AVX512VNNI"
- "vpdpwssds\t{%3, %2, %0|%0, %2, %3 }"
- [(set_attr ("prefix") ("evex"))])
+ "TARGET_AVXVNNI || (TARGET_AVX512VNNI && TARGET_AVX512VL)"
+ "@
+ %{vex%} vpdpwssds\t{%3, %2, %0|%0, %2, %3}
+ vpdpwssds\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr ("prefix") ("vex,evex"))
+ (set_attr ("isa") ("avxvnni,avx512vnnivl"))])
(define_insn "vpdpwssds_<mode>_mask"
[(set (match_operand:VI4_AVX512VL 0 "register_operand" "=v")
@@ -23316,3 +23595,211 @@
(match_operand:<avx512fmaskhalfmode> 4 "register_operand" "Yk")))]
"TARGET_AVX512BF16"
"vdpbf16ps\t{%3, %2, %0%{%4%}|%0%{%4%}, %2, %3}")
+
+;; KEYLOCKER
+(define_insn "loadiwkey"
+ [(unspec_volatile:V2DI [(match_operand:V2DI 0 "register_operand" "v")
+ (match_operand:V2DI 1 "register_operand" "v")
+ (match_operand:V2DI 2 "register_operand" "Yz")
+ (match_operand:SI 3 "register_operand" "a")]
+ UNSPECV_LOADIWKEY)
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_KL"
+ "loadiwkey\t{%0, %1|%1, %0}"
+ [(set_attr "type" "other")])
+
+(define_expand "encodekey128u32"
+ [(match_par_dup 2
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand")
+ (reg:V2DI XMM0_REG)]
+ UNSPECV_ENCODEKEY128U32))])]
+ "TARGET_KL"
+{
+ rtx xmm_regs[7];
+ rtx tmp_unspec;
+ unsigned i;
+
+ /* parallel rtx for encodekey128 predicate */
+ operands[2] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (8));
+
+ for (i = 0; i < 7; i++)
+ xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
+
+ tmp_unspec
+ = gen_rtx_UNSPEC_VOLATILE (SImode,
+ gen_rtvec (2, operands[1], xmm_regs[0]),
+ UNSPECV_ENCODEKEY128U32);
+
+ XVECEXP (operands[2], 0, 0)
+ = gen_rtx_SET (operands[0], tmp_unspec);
+
+ tmp_unspec
+ = gen_rtx_UNSPEC_VOLATILE (V2DImode,
+ gen_rtvec (1, const0_rtx),
+ UNSPECV_ENCODEKEY128U32);
+
+ for (i = 0; i < 3; i++)
+ XVECEXP (operands[2], 0, i + 1)
+ = gen_rtx_SET (xmm_regs[i], tmp_unspec);
+
+ for (i = 4; i < 7; i++)
+ XVECEXP (operands[2], 0, i)
+ = gen_rtx_SET (xmm_regs[i], CONST0_RTX (V2DImode));
+
+ XVECEXP (operands[2], 0, 7)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+})
+
+(define_insn "*encodekey128u32"
+ [(match_parallel 2 "encodekey128_operation"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand" "r")
+ (reg:V2DI XMM0_REG)]
+ UNSPECV_ENCODEKEY128U32))])]
+ "TARGET_KL"
+ "encodekey128\t{%1, %0|%0, %1}"
+ [(set_attr "type" "other")])
+
+(define_expand "encodekey256u32"
+ [(match_par_dup 2
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand")
+ (reg:V2DI XMM0_REG)
+ (reg:V2DI XMM1_REG)]
+ UNSPECV_ENCODEKEY256U32))])]
+ "TARGET_KL"
+{
+ rtx xmm_regs[7];
+ rtx tmp_unspec;
+ unsigned i;
+
+ /* parallel rtx for encodekey256 predicate */
+ operands[2] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (9));
+
+ for (i = 0; i < 7; i++)
+ xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
+
+ tmp_unspec
+ = gen_rtx_UNSPEC_VOLATILE (SImode,
+ gen_rtvec (3, operands[1],
+ xmm_regs[0], xmm_regs[1]),
+ UNSPECV_ENCODEKEY256U32);
+
+ XVECEXP (operands[2], 0, 0)
+ = gen_rtx_SET (operands[0], tmp_unspec);
+
+ tmp_unspec
+ = gen_rtx_UNSPEC_VOLATILE (V2DImode,
+ gen_rtvec (1, const0_rtx),
+ UNSPECV_ENCODEKEY256U32);
+
+ for (i = 0; i < 4; i++)
+ XVECEXP (operands[2], 0, i + 1)
+ = gen_rtx_SET (xmm_regs[i], tmp_unspec);
+
+ for (i = 4; i < 7; i++)
+ XVECEXP (operands[2], 0, i + 1)
+ = gen_rtx_SET (xmm_regs[i], CONST0_RTX (V2DImode));
+
+ XVECEXP (operands[2], 0, 8)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+})
+
+(define_insn "*encodekey256u32"
+ [(match_parallel 2 "encodekey256_operation"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand" "r")
+ (reg:V2DI XMM0_REG)
+ (reg:V2DI XMM1_REG)]
+ UNSPECV_ENCODEKEY256U32))])]
+ "TARGET_KL"
+ "encodekey256\t{%1, %0|%0, %1}"
+ [(set_attr "type" "other")])
+
+(define_int_iterator AESDECENCKL
+ [UNSPECV_AESDEC128KLU8 UNSPECV_AESDEC256KLU8
+ UNSPECV_AESENC128KLU8 UNSPECV_AESENC256KLU8])
+
+(define_int_attr aesklvariant
+ [(UNSPECV_AESDEC128KLU8 "dec128kl")
+ (UNSPECV_AESDEC256KLU8 "dec256kl")
+ (UNSPECV_AESENC128KLU8 "enc128kl")
+ (UNSPECV_AESENC256KLU8 "enc256kl")])
+
+(define_insn "aes<aesklvariant>u8"
+ [(set (match_operand:V2DI 0 "register_operand" "=v")
+ (unspec_volatile:V2DI [(match_operand:V2DI 1 "register_operand" "0")
+ (match_operand:BLK 2 "memory_operand" "m")]
+ AESDECENCKL))
+ (set (reg:CCZ FLAGS_REG)
+ (unspec_volatile:CCZ [(match_dup 1) (match_dup 2)] AESDECENCKL))]
+ "TARGET_KL"
+ "aes<aesklvariant>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "other")])
+
+(define_int_iterator AESDECENCWIDEKL
+ [UNSPECV_AESDECWIDE128KLU8 UNSPECV_AESDECWIDE256KLU8
+ UNSPECV_AESENCWIDE128KLU8 UNSPECV_AESENCWIDE256KLU8])
+
+(define_int_attr aeswideklvariant
+ [(UNSPECV_AESDECWIDE128KLU8 "decwide128kl")
+ (UNSPECV_AESDECWIDE256KLU8 "decwide256kl")
+ (UNSPECV_AESENCWIDE128KLU8 "encwide128kl")
+ (UNSPECV_AESENCWIDE256KLU8 "encwide256kl")])
+
+(define_int_attr AESWIDEKLVARIANT
+ [(UNSPECV_AESDECWIDE128KLU8 "AESDECWIDE128KLU8")
+ (UNSPECV_AESDECWIDE256KLU8 "AESDECWIDE256KLU8")
+ (UNSPECV_AESENCWIDE128KLU8 "AESENCWIDE128KLU8")
+ (UNSPECV_AESENCWIDE256KLU8 "AESENCWIDE256KLU8")])
+
+(define_expand "aes<aeswideklvariant>u8"
+ [(match_par_dup 1
+ [(set (reg:CCZ FLAGS_REG)
+ (unspec_volatile:CCZ
+ [(match_operand:BLK 0 "memory_operand")]
+ AESDECENCWIDEKL))])]
+ "TARGET_WIDEKL"
+{
+ rtx tmp_unspec;
+ unsigned i;
+
+ /* parallel rtx for widekl predicate */
+ operands[1] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (9));
+
+ tmp_unspec
+ = gen_rtx_UNSPEC_VOLATILE (CCZmode,
+ gen_rtvec (1, operands[0]),
+ UNSPECV_<AESWIDEKLVARIANT>);
+
+ XVECEXP (operands[1], 0, 0)
+ = gen_rtx_SET (gen_rtx_REG (CCZmode, FLAGS_REG),
+ tmp_unspec);
+
+ for (i = 0; i < 8; i++)
+ {
+ rtx xmm_reg = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
+
+ tmp_unspec
+ = gen_rtx_UNSPEC_VOLATILE (V2DImode,
+ gen_rtvec (1, xmm_reg),
+ UNSPECV_<AESWIDEKLVARIANT>);
+ XVECEXP (operands[1], 0, i + 1)
+ = gen_rtx_SET (xmm_reg, tmp_unspec);
+ }
+})
+
+(define_insn "*aes<aeswideklvariant>u8"
+ [(match_parallel 1 "aeswidekl_operation"
+ [(set (reg:CCZ FLAGS_REG)
+ (unspec_volatile:CCZ
+ [(match_operand:BLK 0 "memory_operand" "m")]
+ AESDECENCWIDEKL))])]
+ "TARGET_WIDEKL"
+ "aes<aeswideklvariant>\t{%0}"
+ [(set_attr "type" "other")])
diff --git a/gcc/config/i386/t-cet b/gcc/config/i386/t-cet
deleted file mode 100644
index d685d31..0000000
--- a/gcc/config/i386/t-cet
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2017-2020 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-cet.o: $(srcdir)/config/i386/cet.c
- $(COMPILE) $<
- $(POSTCOMPILE)
diff --git a/gcc/config/i386/t-gnu-property b/gcc/config/i386/t-gnu-property
new file mode 100644
index 0000000..fd8bbce
--- /dev/null
+++ b/gcc/config/i386/t-gnu-property
@@ -0,0 +1,21 @@
+# Copyright (C) 2017-2020 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+gnu-property.o: $(srcdir)/config/i386/gnu-property.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/i386/t-vxworks b/gcc/config/i386/t-vxworks
index c440b1f..8f5e8c7 100644
--- a/gcc/config/i386/t-vxworks
+++ b/gcc/config/i386/t-vxworks
@@ -1,8 +1,19 @@
# Multilibs for VxWorks.
-# Build multilibs for normal, -mrtp, and -mrtp -fPIC.
-MULTILIB_OPTIONS = mrtp fPIC
-MULTILIB_DIRNAMES =
+# The common variant across the board is for -mrtp
+MULTILIB_OPTIONS = mrtp
+MULTILIB_DIRNAMES = mrtp
+
+# Then variants for the "large" code model on x86_64, or fPIC on x86,
+# RTP only. -fPIC -mrtp -mcmodel=large is not functional yet.
+ifneq (,$(findstring x86_64, $(target)))
+MULTILIB_OPTIONS += mcmodel=large
+MULTILIB_DIRNAMES += large
+else
+MULTILIB_OPTIONS += fPIC
+MULTILIB_DIRNAMES += fPIC
MULTILIB_MATCHES = fPIC=fpic
-MULTILIB_EXCEPTIONS = fPIC
+# -fPIC is only supported in combination with -mrtp
+MULTILIB_EXCEPTIONS = fPIC
+endif
diff --git a/gcc/config/i386/uintrintrin.h b/gcc/config/i386/uintrintrin.h
index 991f642..4606caf 100644
--- a/gcc/config/i386/uintrintrin.h
+++ b/gcc/config/i386/uintrintrin.h
@@ -38,9 +38,6 @@
struct __uintr_frame
{
- /* The position of the most significant bit set in user-interrupt
- request register. */
- unsigned long long uirrv;
/* RIP of the interrupted user process. */
unsigned long long rip;
/* RFLAGS of the interrupted user process. */
diff --git a/gcc/config/i386/vxworks.h b/gcc/config/i386/vxworks.h
index ad9404b..891b4ff 100644
--- a/gcc/config/i386/vxworks.h
+++ b/gcc/config/i386/vxworks.h
@@ -18,12 +18,21 @@ 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/>. */
+/* VxWorks after 7 SR0600 use the ELF ABI and the system environment is llvm
+ based. Earlier versions have GNU based environment components and use the
+ same ABI as Solaris 2. */
+
+#if TARGET_VXWORKS7
+
+#undef VXWORKS_PERSONALITY
+#define VXWORKS_PERSONALITY "llvm"
+
+#else
+
#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
-/* VxWorks uses the same ABI as Solaris 2, so use i386/sol2.h version. */
-
#undef TARGET_SUBTARGET_DEFAULT
#define TARGET_SUBTARGET_DEFAULT \
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_VECT8_RETURNS)
@@ -41,43 +50,73 @@ along with GCC; see the file COPYING3. If not see
#undef SIZE_TYPE
#define SIZE_TYPE (TARGET_LP64 ? "long unsigned int" : "unsigned int")
+/* We cannot use PC-relative accesses for VxWorks PIC because there is no
+ fixed gap between segments. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+
#if TARGET_64BIT_DEFAULT
#undef VXWORKS_SYSCALL_LIBS_RTP
#define VXWORKS_SYSCALL_LIBS_RTP "-lsyscall"
#endif
+#endif
+
+/* CPU macro definitions, ordered to account for VxWorks 7 not
+ supporting CPUs older than PENTIUM4 since SR0650. */
+
+#define VX_CPUDEF(CPU) builtin_define(VX_CPU_PREFIX "CPU=" #CPU)
+#define VX_CPUVDEF(CPU) builtin_define(VX_CPU_PREFIX "CPU_VARIANT=" #CPU)
+
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
VXWORKS_OS_CPP_BUILTINS (); \
- if (TARGET_386) \
- builtin_define ("CPU=I80386"); \
+ if (TARGET_64BIT) \
+ VX_CPUDEF (X86_64); \
+ else if (TARGET_PENTIUM4) \
+ { \
+ VX_CPUDEF (PENTIUM4); \
+ VX_CPUVDEF (PENTIUM4); \
+ } \
+ else if (TARGET_CORE2) \
+ VX_CPUDEF (CORE2); \
+ else if (TARGET_NEHALEM) \
+ VX_CPUDEF (NEHALEM); \
+ else if (TARGET_SANDYBRIDGE) \
+ VX_CPUDEF (SANDYBRIDGE); \
+ else if (TARGET_HASWELL) \
+ VX_CPUDEF (HASWELL); \
+ else if (TARGET_SILVERMONT) \
+ VX_CPUDEF (SILVERMONT); \
+ else if (TARGET_SKYLAKE || TARGET_SKYLAKE_AVX512) \
+ VX_CPUDEF (SKYLAKE); \
+ else if (TARGET_GOLDMONT) \
+ VX_CPUDEF (GOLDMONT); \
+ else if (TARGET_VXWORKS7) \
+ VX_CPUDEF (PENTIUM4); \
+ else if (TARGET_386) \
+ VX_CPUDEF (I80386); \
else if (TARGET_486) \
- builtin_define ("CPU=I80486"); \
+ VX_CPUDEF (I80486); \
else if (TARGET_PENTIUM) \
- { \
- builtin_define ("CPU=PENTIUM"); \
- builtin_define ("CPU_VARIANT=PENTIUM"); \
- } \
+ { \
+ VX_CPUDEF (PENTIUM); \
+ VX_CPUVDEF (PENTIUM); \
+ } \
else if (TARGET_PENTIUMPRO) \
- { \
- builtin_define ("CPU=PENTIUM2"); \
- builtin_define ("CPU_VARIANT=PENTIUMPRO"); \
- } \
- else if (TARGET_PENTIUM4) \
- { \
- builtin_define ("CPU=PENTIUM4"); \
- builtin_define ("CPU_VARIANT=PENTIUM4"); \
- } \
- else if (TARGET_64BIT) \
- builtin_define ("CPU=X86_64"); \
+ { \
+ VX_CPUDEF (PENTIUM2); \
+ VX_CPUVDEF (PENTIUMPRO); \
+ } \
else \
- builtin_define ("CPU=I80386"); \
- } \
+ VX_CPUDEF (I80386); \
+ } \
while (0)
#undef CPP_SPEC
#define CPP_SPEC VXWORKS_ADDITIONAL_CPP_SPEC
+#undef CC1_SPEC
+#define CC1_SPEC VXWORKS_CC1_SPEC
#undef LIB_SPEC
#define LIB_SPEC VXWORKS_LIB_SPEC
#undef STARTFILE_SPEC
@@ -97,18 +136,11 @@ along with GCC; see the file COPYING3. If not see
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE,LABELNO) VXWORKS_FUNCTION_PROFILER(FILE,LABELNO)
-/* We cannot use PC-relative accesses for VxWorks PIC because there is no
- fixed gap between segments. */
-#undef ASM_PREFERRED_EH_DATA_FORMAT
-
/* Define this to be nonzero if static stack checking is supported. */
#define STACK_CHECK_STATIC_BUILTIN 1
/* This platform supports the probing method of stack checking (RTP mode).
- 8K is reserved in the stack to propagate exceptions in case of overflow.
+ 8K is reserved in the stack to propagate exceptions in case of overflow.
On 64-bit targets, we double that size. */
-#if TARGET_64BIT_DEFAULT
-#define STACK_CHECK_PROTECT 16384
-#else
-#define STACK_CHECK_PROTECT 8192
-#endif
+
+#define STACK_CHECK_PROTECT (TARGET_64BIT_DEFAULT ? 16 * 1024 : 8 * 1024)
diff --git a/gcc/config/i386/x86-tune-sched.c b/gcc/config/i386/x86-tune-sched.c
index d4d8a12..404b5b1 100644
--- a/gcc/config/i386/x86-tune-sched.c
+++ b/gcc/config/i386/x86-tune-sched.c
@@ -66,6 +66,7 @@ ix86_issue_rate (void)
case PROCESSOR_BDVER4:
case PROCESSOR_ZNVER1:
case PROCESSOR_ZNVER2:
+ case PROCESSOR_ZNVER3:
case PROCESSOR_CORE2:
case PROCESSOR_NEHALEM:
case PROCESSOR_SANDYBRIDGE:
@@ -396,6 +397,7 @@ ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
case PROCESSOR_ZNVER1:
case PROCESSOR_ZNVER2:
+ case PROCESSOR_ZNVER3:
/* Stack engine allows to execute push&pop instructions in parall. */
if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
&& (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
index 6eff825..ed4d74c 100644
--- a/gcc/config/i386/x86-tune.def
+++ b/gcc/config/i386/x86-tune.def
@@ -444,7 +444,7 @@ DEF_TUNE (X86_TUNE_AVOID_128FMA_CHAINS, "avoid_fma_chains", m_ZNVER)
/* X86_TUNE_AVOID_256FMA_CHAINS: Avoid creating loops with tight 256bit or
smaller FMA chain. */
-DEF_TUNE (X86_TUNE_AVOID_256FMA_CHAINS, "avoid_fma256_chains", m_ZNVER2)
+DEF_TUNE (X86_TUNE_AVOID_256FMA_CHAINS, "avoid_fma256_chains", m_ZNVER2 | m_ZNVER3)
/*****************************************************************************/
/* AVX instruction selection tuning (some of SSE flags affects AVX, too) */
diff --git a/gcc/config/i386/znver1.md b/gcc/config/i386/znver1.md
index 6812a3d..b0edfab 100644
--- a/gcc/config/i386/znver1.md
+++ b/gcc/config/i386/znver1.md
@@ -21,7 +21,7 @@
(define_attr "znver1_decode" "direct,vector,double"
(const_string "direct"))
-;; AMD znver1 and znver2 Scheduling
+;; AMD znver1, znver2 and znver3 Scheduling
;; Modeling automatons for zen decoders, integer execution pipes,
;; AGU pipes and floating point execution units.
(define_automaton "znver1, znver1_ieu, znver1_fp, znver1_agu")
@@ -52,7 +52,7 @@
(define_cpu_unit "znver1-ieu3" "znver1_ieu")
(define_reservation "znver1-ieu" "znver1-ieu0|znver1-ieu1|znver1-ieu2|znver1-ieu3")
-;; 2 AGU pipes in znver1 and 3 AGU pipes in znver2
+;; 2 AGU pipes in znver1 and 3 AGU pipes in znver2 and znver3
;; According to CPU diagram last AGU unit is used only for stores.
(define_cpu_unit "znver1-agu0" "znver1_agu")
(define_cpu_unit "znver1-agu1" "znver1_agu")
@@ -63,7 +63,7 @@
;; Load is 4 cycles. We do not model reservation of load unit.
;;(define_reservation "znver1-load" "znver1-agu-reserve, nothing, nothing, nothing")
(define_reservation "znver1-load" "znver1-agu-reserve")
-;; Store operations differs between znver1 and znver2 because extra AGU
+;; Store operations differs between znver1, znver2 and znver3 because extra AGU
;; was added.
(define_reservation "znver1-store" "znver1-agu-reserve")
(define_reservation "znver2-store" "znver2-store-agu-reserve")
@@ -77,6 +77,7 @@
(define_reservation "znver2-ivector" "znver1-ieu0+znver1-ieu1
+znver1-ieu2+znver1-ieu3
+znver1-agu0+znver1-agu1+znver2-agu2")
+
;; Floating point unit 4 FP pipes.
(define_cpu_unit "znver1-fp0" "znver1_fp")
(define_cpu_unit "znver1-fp1" "znver1_fp")
@@ -99,7 +100,7 @@
"znver1-double,znver1-store,znver1-ieu0|znver1-ieu3")
(define_insn_reservation "znver2_call" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(eq_attr "type" "call,callv"))
"znver1-double,znver2-store,znver1-ieu0|znver1-ieu3")
@@ -110,10 +111,10 @@
(eq_attr "memory" "store")))
"znver1-direct,znver1-store")
(define_insn_reservation "znver2_push" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "push")
(eq_attr "memory" "store")))
- "znver1-direct,znver1-store")
+ "znver1-direct,znver2-store")
(define_insn_reservation "znver1_push_load" 4
(and (eq_attr "cpu" "znver1")
@@ -121,13 +122,13 @@
(eq_attr "memory" "both")))
"znver1-direct,znver1-load,znver1-store")
(define_insn_reservation "znver2_push_load" 4
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "push")
(eq_attr "memory" "both")))
"znver1-direct,znver1-load,znver2-store")
(define_insn_reservation "znver1_pop" 4
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "pop")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load")
@@ -138,7 +139,7 @@
(eq_attr "memory" "both")))
"znver1-direct,znver1-load,znver1-store")
(define_insn_reservation "znver2_pop_mem" 4
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "pop")
(eq_attr "memory" "both")))
"znver1-direct,znver1-load,znver2-store")
@@ -149,7 +150,7 @@
(eq_attr "type" "leave"))
"znver1-double,znver1-ieu, znver1-store")
(define_insn_reservation "znver2_leave" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(eq_attr "type" "leave"))
"znver1-double,znver1-ieu, znver2-store")
@@ -157,13 +158,13 @@
;; Multiplications
;; Reg operands
(define_insn_reservation "znver1_imul" 3
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "imul")
(eq_attr "memory" "none")))
"znver1-direct,znver1-ieu1")
(define_insn_reservation "znver1_imul_mem" 7
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "imul")
(eq_attr "memory" "!none")))
"znver1-direct,znver1-load, znver1-ieu1")
@@ -227,6 +228,62 @@
(eq_attr "memory" "none"))))
"znver1-direct,znver1-load,znver1-ieu2*12")
+(define_insn_reservation "znver3_idiv_DI" 18
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI")
+ (eq_attr "memory" "none"))))
+ "znver1-double,znver1-ieu2*18")
+
+(define_insn_reservation "znver3_idiv_SI" 12
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI")
+ (eq_attr "memory" "none"))))
+ "znver1-double,znver1-ieu2*12")
+
+(define_insn_reservation "znver3_idiv_HI" 10
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "HI")
+ (eq_attr "memory" "none"))))
+ "znver1-double,znver1-ieu2*10")
+
+(define_insn_reservation "znver3_idiv_QI" 9
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "QI")
+ (eq_attr "memory" "none"))))
+ "znver1-direct,znver1-ieu2*9")
+
+(define_insn_reservation "znver3_idiv_mem_DI" 22
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI")
+ (eq_attr "memory" "load"))))
+ "znver1-double,znver1-load,znver1-ieu2*22")
+
+(define_insn_reservation "znver3_idiv_mem_SI" 16
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI")
+ (eq_attr "memory" "load"))))
+ "znver1-double,znver1-load,znver1-ieu2*16")
+
+(define_insn_reservation "znver3_idiv_mem_HI" 14
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "HI")
+ (eq_attr "memory" "load"))))
+ "znver1-double,znver1-load,znver1-ieu2*10")
+
+(define_insn_reservation "znver3_idiv_mem_QI" 13
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "QI")
+ (eq_attr "memory" "load"))))
+ "znver1-direct,znver1-load,znver1-ieu2*9")
+
;; STR ISHIFT which are micro coded.
;; Fix me: Latency need to be rechecked.
(define_insn_reservation "znver1_str_ishift" 6
@@ -236,15 +293,16 @@
"znver1-vector,znver1-ivector")
(define_insn_reservation "znver2_str_ishift" 3
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "ishift")
(eq_attr "memory" "both,store")))
"znver1-vector,znver1-ivector")
(define_insn_reservation "znver2_str_istr" 19
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "str")
(eq_attr "memory" "both,store")))
"znver1-vector,znver1-ivector")
+
;; MOV - integer moves
(define_insn_reservation "znver1_load_imov_double" 2
(and (eq_attr "cpu" "znver1")
@@ -254,14 +312,14 @@
"znver1-double,znver1-ieu|znver1-ieu")
(define_insn_reservation "znver2_load_imov_double" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "znver1_decode" "double")
(and (eq_attr "type" "imovx")
(eq_attr "memory" "none"))))
"znver1-double,znver1-ieu|znver1-ieu")
(define_insn_reservation "znver1_load_imov_direct" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "imov,imovx")
(eq_attr "memory" "none")))
"znver1-direct,znver1-ieu")
@@ -274,7 +332,7 @@
"znver1-double,znver1-ieu|znver1-ieu,znver1-store")
(define_insn_reservation "znver2_load_imov_double_store" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "znver1_decode" "double")
(and (eq_attr "type" "imovx")
(eq_attr "memory" "store"))))
@@ -287,7 +345,7 @@
"znver1-direct,znver1-ieu,znver1-store")
(define_insn_reservation "znver2_load_imov_direct_store" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "imov,imovx")
(eq_attr "memory" "store")))
"znver1-direct,znver1-ieu,znver2-store")
@@ -300,14 +358,14 @@
"znver1-double,znver1-load,znver1-ieu|znver1-ieu")
(define_insn_reservation "znver2_load_imov_double_load" 4
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "znver1_decode" "double")
(and (eq_attr "type" "imovx")
(eq_attr "memory" "load"))))
"znver1-double,znver1-load,znver1-ieu|znver1-ieu")
(define_insn_reservation "znver1_load_imov_direct_load" 4
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "imov,imovx")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load")
@@ -315,13 +373,13 @@
;; INTEGER/GENERAL instructions
;; register/imm operands only: ALU, ICMP, NEG, NOT, ROTATE, ISHIFT, TEST
(define_insn_reservation "znver1_insn" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift,ishift1,test,setcc,incdec,icmov")
(eq_attr "memory" "none,unknown")))
"znver1-direct,znver1-ieu")
(define_insn_reservation "znver1_insn_load" 5
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift,ishift1,test,setcc,incdec,icmov")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-ieu")
@@ -333,7 +391,7 @@
"znver1-direct,znver1-ieu,znver1-store")
(define_insn_reservation "znver2_insn_store" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift1,test,setcc,incdec")
(eq_attr "memory" "store")))
"znver1-direct,znver1-ieu,znver2-store")
@@ -345,7 +403,7 @@
"znver1-direct,znver1-load,znver1-ieu,znver1-store")
(define_insn_reservation "znver2_insn_both" 5
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift1,test,setcc,incdec")
(eq_attr "memory" "both")))
"znver1-direct,znver1-load,znver1-ieu,znver2-store")
@@ -357,7 +415,7 @@
"znver1-vector,znver1-ivector")
(define_insn_reservation "znver2_ieu_vector" 5
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(eq_attr "type" "other,str,multi"))
"znver1-vector,znver2-ivector")
@@ -370,21 +428,21 @@
"znver1-vector,znver1-ivector")
(define_insn_reservation "znver2_alu1_vector" 3
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "znver1_decode" "vector")
(and (eq_attr "type" "alu1")
(eq_attr "memory" "none,unknown"))))
"znver1-vector,znver2-ivector")
(define_insn_reservation "znver1_alu1_double" 2
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "znver1_decode" "double")
(and (eq_attr "type" "alu1")
(eq_attr "memory" "none,unknown"))))
"znver1-double,znver1-ieu")
(define_insn_reservation "znver1_alu1_direct" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "znver1_decode" "direct")
(and (eq_attr "type" "alu1")
(eq_attr "memory" "none,unknown"))))
@@ -392,45 +450,45 @@
;; Branches : Fix me need to model conditional branches.
(define_insn_reservation "znver1_branch" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "ibr")
- (eq_attr "memory" "none")))
+ (eq_attr "memory" "none")))
"znver1-direct")
;; Indirect branches check latencies.
(define_insn_reservation "znver1_indirect_branch_mem" 6
(and (eq_attr "cpu" "znver1")
(and (eq_attr "type" "ibr")
- (eq_attr "memory" "load")))
+ (eq_attr "memory" "load")))
"znver1-vector,znver1-ivector")
(define_insn_reservation "znver2_indirect_branch_mem" 6
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "ibr")
- (eq_attr "memory" "load")))
+ (eq_attr "memory" "load")))
"znver1-vector,znver2-ivector")
;; LEA executes in ALU units with 1 cycle latency.
(define_insn_reservation "znver1_lea" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(eq_attr "type" "lea"))
"znver1-direct,znver1-ieu")
;; Other integer instrucions
(define_insn_reservation "znver1_idirect" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "none,unknown")))
"znver1-direct,znver1-ieu")
;; Floating point
(define_insn_reservation "znver1_fp_cmov" 6
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(eq_attr "type" "fcmov"))
"znver1-vector,znver1-fvector")
(define_insn_reservation "znver1_fp_mov_direct_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "znver1_decode" "direct")
(and (eq_attr "type" "fmov")
(eq_attr "memory" "load"))))
@@ -443,41 +501,34 @@
(eq_attr "memory" "store"))))
"znver1-direct,znver1-fp2|znver1-fp3,znver1-store")
(define_insn_reservation "znver2_fp_mov_direct_store" 5
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "znver1_decode" "direct")
(and (eq_attr "type" "fmov")
(eq_attr "memory" "store"))))
"znver1-direct,znver1-fp2|znver1-fp3,znver2-store")
(define_insn_reservation "znver1_fp_mov_double" 4
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "znver1_decode" "double")
(and (eq_attr "type" "fmov")
(eq_attr "memory" "none"))))
"znver1-double,znver1-fp3")
(define_insn_reservation "znver1_fp_mov_double_load" 12
- (and (eq_attr "cpu" "znver1")
- (and (eq_attr "znver1_decode" "double")
- (and (eq_attr "type" "fmov")
- (eq_attr "memory" "load"))))
- "znver1-double,znver1-load,znver1-fp3")
-
-(define_insn_reservation "znver2_fp_mov_double_load" 12
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "znver1_decode" "double")
(and (eq_attr "type" "fmov")
(eq_attr "memory" "load"))))
"znver1-double,znver1-load,znver1-fp3")
(define_insn_reservation "znver1_fp_mov_direct" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(eq_attr "type" "fmov"))
"znver1-direct,znver1-fp3")
;; TODO: AGU?
(define_insn_reservation "znver1_fp_spc_direct" 5
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "fpspc")
(eq_attr "memory" "store")))
"znver1-direct,znver1-fp3,znver1-fp2")
@@ -488,26 +539,26 @@
(eq_attr "type" "fpspc,mmxcvt,sselog1,ssemul,ssemov")))
"znver1-vector,znver1-fvector")
(define_insn_reservation "znver2_fp_insn_vector" 6
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "znver1_decode" "vector")
(eq_attr "type" "fpspc,mmxcvt,sselog1,ssemul,ssemov")))
"znver1-vector,znver2-fvector")
;; FABS
(define_insn_reservation "znver1_fp_fsgn" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(eq_attr "type" "fsgn"))
"znver1-direct,znver1-fp3")
(define_insn_reservation "znver1_fp_fcmp" 2
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "memory" "none")
(and (eq_attr "znver1_decode" "double")
(eq_attr "type" "fcmp"))))
"znver1-double,znver1-fp0,znver1-fp2")
(define_insn_reservation "znver1_fp_fcmp_load" 9
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "memory" "none")
(and (eq_attr "znver1_decode" "double")
(eq_attr "type" "fcmp"))))
@@ -515,32 +566,32 @@
;;FADD FSUB FMUL
(define_insn_reservation "znver1_fp_op_mul" 5
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "fop,fmul")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0*5")
(define_insn_reservation "znver1_fp_op_mul_load" 12
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "fop,fmul")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0*5")
(define_insn_reservation "znver1_fp_op_imul_load" 16
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "fop,fmul")
(and (eq_attr "fp_int_src" "true")
(eq_attr "memory" "load"))))
"znver1-double,znver1-load,znver1-fp3,znver1-fp0")
(define_insn_reservation "znver1_fp_op_div" 15
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "fdiv")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp3*15")
(define_insn_reservation "znver1_fp_op_div_load" 22
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "fdiv")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp3*15")
@@ -553,62 +604,63 @@
"znver1-double,znver1-load,znver1-fp3*19")
(define_insn_reservation "znver2_fp_op_idiv_load" 26
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "fdiv")
(and (eq_attr "fp_int_src" "true")
(eq_attr "memory" "load"))))
"znver1-double,znver1-load,znver1-fp3*19")
+
;; MMX, SSE, SSEn.n, AVX, AVX2 instructions
(define_insn_reservation "znver1_fp_insn" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(eq_attr "type" "mmx"))
"znver1-direct,znver1-fpu")
(define_insn_reservation "znver1_mmx_add" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxadd")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0|znver1-fp1|znver1-fp3")
(define_insn_reservation "znver1_mmx_add_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxadd")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0|znver1-fp1|znver1-fp3")
(define_insn_reservation "znver1_mmx_cmp" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxcmp")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0|znver1-fp3")
(define_insn_reservation "znver1_mmx_cmp_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxcmp")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0|znver1-fp3")
(define_insn_reservation "znver1_mmx_cvt_pck_shuf" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxcvt,sseshuf,sseshuf1")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp1|znver1-fp2")
(define_insn_reservation "znver1_mmx_cvt_pck_shuf_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxcvt,sseshuf,sseshuf1")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp1|znver1-fp2")
(define_insn_reservation "znver1_mmx_shift_move" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxshft,mmxmov")
(eq_attr "memory" "none")))
- "znver1-direct,znver1-fp2")
+ "znver1-direct,znver1-fp2")
(define_insn_reservation "znver1_mmx_shift_move_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxshft,mmxmov")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp2")
@@ -619,19 +671,19 @@
(eq_attr "memory" "store,both")))
"znver1-direct,znver1-fp2,znver1-store")
(define_insn_reservation "znver2_mmx_move_store" 1
- (and (eq_attr "cpu" "znver1")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "mmxshft,mmxmov")
(eq_attr "memory" "store,both")))
"znver1-direct,znver1-fp2,znver2-store")
(define_insn_reservation "znver1_mmx_mul" 3
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxmul")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0*3")
(define_insn_reservation "znver1_mmx_load" 10
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "mmxmul")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0*3")
@@ -652,13 +704,13 @@
"znver1-double,znver1-load,znver1-fpu")
(define_insn_reservation "znver1_sse_log" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "sselog")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fpu")
(define_insn_reservation "znver1_sse_log_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "sselog")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fpu")
@@ -678,13 +730,13 @@
"znver1-double,znver1-load,znver1-fp1|znver1-fp2")
(define_insn_reservation "znver1_sse_log1" 1
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "sselog1")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp1|znver1-fp2")
(define_insn_reservation "znver1_sse_log1_load" 8
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "sselog1")
(eq_attr "memory" "!none")))
"znver1-direct,znver1-load,znver1-fp1|znver1-fp2")
@@ -701,7 +753,8 @@
(define_insn_reservation "znver1_sse_comi_load" 8
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "prefix_extra" "0")
(and (eq_attr "type" "ssecomi")
(eq_attr "memory" "load"))))
@@ -710,7 +763,8 @@
(define_insn_reservation "znver1_sse_comi_double" 2
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "prefix" "vex")
(and (eq_attr "prefix_extra" "0")
(and (eq_attr "type" "ssecomi")
@@ -720,7 +774,8 @@
(define_insn_reservation "znver1_sse_comi_double_load" 10
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "prefix" "vex")
(and (eq_attr "prefix_extra" "0")
(and (eq_attr "type" "ssecomi")
@@ -730,7 +785,8 @@
(define_insn_reservation "znver1_sse_test" 1
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "prefix_extra" "1")
(and (eq_attr "type" "ssecomi")
(eq_attr "memory" "none"))))
@@ -739,7 +795,8 @@
(define_insn_reservation "znver1_sse_test_load" 8
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "prefix_extra" "1")
(and (eq_attr "type" "ssecomi")
(eq_attr "memory" "load"))))
@@ -757,7 +814,7 @@
"znver1-direct,znver1-ieu0")
(define_insn_reservation "znver2_sse_mov" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "mode" "SI")
(and (eq_attr "isa" "avx")
(and (eq_attr "type" "ssemov")
@@ -774,7 +831,7 @@
"znver1-direct,znver1-ieu2")
(define_insn_reservation "znver2_avx_mov" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "mode" "TI")
(and (eq_attr "isa" "avx")
(and (eq_attr "type" "ssemov")
@@ -785,7 +842,8 @@
(define_insn_reservation "znver1_sseavx_mov" 1
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "type" "ssemov")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fpu")
@@ -797,7 +855,7 @@
(eq_attr "memory" "store"))))
"znver1-direct,znver1-fpu,znver1-store")
(define_insn_reservation "znver2_sseavx_mov_store" 1
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "ssemov")
(eq_attr "memory" "store")))
"znver1-direct,znver1-fpu,znver2-store")
@@ -805,7 +863,8 @@
(define_insn_reservation "znver1_sseavx_mov_load" 8
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "type" "ssemov")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fpu")
@@ -835,7 +894,8 @@
(define_insn_reservation "znver1_sseavx_add" 3
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "type" "sseadd")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp2|znver1-fp3")
@@ -843,7 +903,8 @@
(define_insn_reservation "znver1_sseavx_add_load" 10
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "type" "sseadd")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp2|znver1-fp3")
@@ -892,10 +953,39 @@
(eq_attr "memory" "load"))))
"znver1-double,znver1-load,znver1-fp0|znver1-fp1")
+(define_insn_reservation "znver3_sseavx_fma" 4
+ (and (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "SF,DF,V4SF,V2DF"))
+ (and (eq_attr "type" "ssemuladd")
+ (eq_attr "memory" "none")))
+ "znver1-direct,znver1-fp0|znver1-fp1")
+
+(define_insn_reservation "znver3_sseavx_fma_load" 11
+ (and (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "SF,DF,V4SF,V2DF"))
+ (and (eq_attr "type" "ssemuladd")
+ (eq_attr "memory" "load")))
+ "znver1-direct,znver1-load,znver1-fp0|znver1-fp1")
+
+(define_insn_reservation "znver3_avx256_fma" 4
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "mode" "V8SF,V4DF")
+ (and (eq_attr "type" "ssemuladd")
+ (eq_attr "memory" "none"))))
+ "znver1-double,znver1-fp0|znver1-fp1")
+
+(define_insn_reservation "znver3_avx256_fma_load" 11
+ (and (eq_attr "cpu" "znver3")
+ (and (eq_attr "mode" "V8SF,V4DF")
+ (and (eq_attr "type" "ssemuladd")
+ (eq_attr "memory" "load"))))
+ "znver1-double,znver1-load,znver1-fp0|znver1-fp1")
+
(define_insn_reservation "znver1_sseavx_iadd" 1
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "DI,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "type" "sseiadd")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0|znver1-fp1|znver1-fp3")
@@ -903,7 +993,8 @@
(define_insn_reservation "znver1_sseavx_iadd_load" 8
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "DI,TI"))
- (eq_attr "cpu" "znver2"))
+ (ior (eq_attr "cpu" "znver2")
+ (eq_attr "cpu" "znver3")))
(and (eq_attr "type" "sseiadd")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0|znver1-fp1|znver1-fp3")
@@ -924,7 +1015,7 @@
;; SSE conversions.
(define_insn_reservation "znver1_ssecvtsf_si_load" 12
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "mode" "SI")
(and (eq_attr "type" "sseicvt")
(and (match_operand:SF 1 "memory_operand")
@@ -939,7 +1030,7 @@
(eq_attr "memory" "none")))))
"znver1-double,znver1-fp3,znver1-ieu0")
(define_insn_reservation "znver2_ssecvtdf_si" 4
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "mode" "SI")
(and (match_operand:DF 1 "register_operand")
(and (eq_attr "type" "sseicvt")
@@ -955,13 +1046,14 @@
"znver1-double,znver1-load,znver1-fp3,znver1-ieu0")
(define_insn_reservation "znver2_ssecvtdf_si_load" 11
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "mode" "SI")
(and (eq_attr "type" "sseicvt")
(and (match_operand:DF 1 "memory_operand")
(eq_attr "memory" "load")))))
"znver1-double,znver1-load,znver1-fp3,znver1-ieu0")
+
;; All other used ssecvt fp3 pipes
;; Check: Need to revisit this again.
;; Some SSE converts may use different pipe combinations.
@@ -972,19 +1064,13 @@
"znver1-direct,znver1-fp3")
(define_insn_reservation "znver2_ssecvt" 3
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "ssecvt")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp3")
(define_insn_reservation "znver1_ssecvt_load" 11
- (and (eq_attr "cpu" "znver1")
- (and (eq_attr "type" "ssecvt")
- (eq_attr "memory" "load")))
- "znver1-direct,znver1-load,znver1-fp3")
-
-(define_insn_reservation "znver2_ssecvt_load" 11
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "type" "ssecvt")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp3")
@@ -994,7 +1080,9 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V4SF,SF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "V8SF,V4SF,SF")))
+ (eq_attr "mode" "V8SF,V4SF,SF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "V8SF,V4SF,SF")))
(and (eq_attr "type" "ssediv")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp3*10")
@@ -1003,7 +1091,9 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V4SF,SF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "V8SF,V4SF,SF")))
+ (eq_attr "mode" "V8SF,V4SF,SF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "V8SF,V4SF,SF")))
(and (eq_attr "type" "ssediv")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp3*10")
@@ -1012,16 +1102,20 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V2DF,DF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "V4DF,V2DF,DF")))
+ (eq_attr "mode" "V4DF,V2DF,DF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "V4DF,V2DF,DF")))
(and (eq_attr "type" "ssediv")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp3*13")
(define_insn_reservation "znver1_ssediv_sd_pd_load" 20
(and (ior (and (eq_attr "cpu" "znver1")
- (eq_attr "mode" "V2DF,DF"))
+ (eq_attr "mode" "V2DF,DF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "V4DF,V2DF,DF")))
+ (eq_attr "mode" "V4DF,V2DF,DF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "V4DF,V2DF,DF")))
(and (eq_attr "type" "ssediv")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp3*13")
@@ -1058,7 +1152,9 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V4SF,SF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "V8SF,V4SF,SF,V4DF,V2DF,DF")))
+ (eq_attr "mode" "V8SF,V4SF,SF,V4DF,V2DF,DF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "V8SF,V4SF,SF,V4DF,V2DF,DF")))
(and (eq_attr "type" "ssemul")
(eq_attr "memory" "none")))
"znver1-direct,(znver1-fp0|znver1-fp1)*3")
@@ -1067,7 +1163,9 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "V4SF,SF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "V8SF,V4SF,SF")))
+ (eq_attr "mode" "V8SF,V4SF,SF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "V8SF,V4SF,SF")))
(and (eq_attr "type" "ssemul")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,(znver1-fp0|znver1-fp1)*3")
@@ -1101,17 +1199,18 @@
"znver1-direct,znver1-load,(znver1-fp0|znver1-fp1)*4")
(define_insn_reservation "znver2_ssemul_sd_pd" 3
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "ssemul")
(eq_attr "memory" "none")))
"znver1-direct,(znver1-fp0|znver1-fp1)*3")
(define_insn_reservation "znver2_ssemul_sd_pd_load" 10
- (and (eq_attr "cpu" "znver2")
+ (and (eq_attr "cpu" "znver2,znver3")
(and (eq_attr "type" "ssemul")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,(znver1-fp0|znver1-fp1)*3")
+
(define_insn_reservation "znver1_ssemul_avx256_pd" 5
(and (eq_attr "cpu" "znver1")
(and (eq_attr "mode" "V4DF")
@@ -1131,13 +1230,15 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "TI"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "TI,OI")))
+ (eq_attr "mode" "TI,OI"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "TI,OI")))
(and (eq_attr "type" "sseimul")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0*3")
(define_insn_reservation "znver1_sseimul_avx256" 4
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "mode" "OI")
(and (eq_attr "type" "sseimul")
(eq_attr "memory" "none"))))
@@ -1147,27 +1248,29 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "TI"))
(and (eq_attr "cpu" "znver2")
+ (eq_attr "mode" "TI,OI"))
+ (and (eq_attr "cpu" "znver3")
(eq_attr "mode" "TI,OI")))
(and (eq_attr "type" "sseimul")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0*3")
(define_insn_reservation "znver1_sseimul_avx256_load" 11
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "mode" "OI")
(and (eq_attr "type" "sseimul")
(eq_attr "memory" "load"))))
"znver1-double,znver1-load,znver1-fp0*4")
(define_insn_reservation "znver1_sseimul_di" 3
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "mode" "DI")
(and (eq_attr "memory" "none")
(eq_attr "type" "sseimul"))))
"znver1-direct,znver1-fp0*3")
(define_insn_reservation "znver1_sseimul_load_di" 10
- (and (eq_attr "cpu" "znver1,znver2")
+ (and (eq_attr "cpu" "znver1,znver2,znver3")
(and (eq_attr "mode" "DI")
(and (eq_attr "type" "sseimul")
(eq_attr "memory" "load"))))
@@ -1178,16 +1281,20 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "SF,DF,V4SF,V2DF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF")))
+ (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF")))
(and (eq_attr "type" "ssecmp")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0|znver1-fp1")
(define_insn_reservation "znver1_sse_cmp_load" 8
(and (ior (and (eq_attr "cpu" "znver1")
- (eq_attr "mode" "SF,DF,V4SF,V2DF"))
+ (eq_attr "mode" "SF,DF,V4SF,V2DF"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF")))
+ (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF")))
(and (eq_attr "type" "ssecmp")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0|znver1-fp1")
@@ -1208,9 +1315,11 @@
(define_insn_reservation "znver1_sse_icmp" 1
(and (ior (and (eq_attr "cpu" "znver1")
- (eq_attr "mode" "QI,HI,SI,DI,TI"))
+ (eq_attr "mode" "QI,HI,SI,DI,TI"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "QI,HI,SI,DI,TI,OI")))
+ (eq_attr "mode" "QI,HI,SI,DI,TI,OI"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "QI,HI,SI,DI,TI,OI")))
(and (eq_attr "type" "ssecmp")
(eq_attr "memory" "none")))
"znver1-direct,znver1-fp0|znver1-fp3")
@@ -1219,7 +1328,9 @@
(and (ior (and (eq_attr "cpu" "znver1")
(eq_attr "mode" "QI,HI,SI,DI,TI"))
(and (eq_attr "cpu" "znver2")
- (eq_attr "mode" "QI,HI,SI,DI,TI,OI")))
+ (eq_attr "mode" "QI,HI,SI,DI,TI,OI"))
+ (and (eq_attr "cpu" "znver3")
+ (eq_attr "mode" "QI,HI,SI,DI,TI,OI")))
(and (eq_attr "type" "ssecmp")
(eq_attr "memory" "load")))
"znver1-direct,znver1-load,znver1-fp0|znver1-fp3")
diff --git a/gcc/config/ia64/ia64.opt b/gcc/config/ia64/ia64.opt
index 05b9d32..5646d29 100644
--- a/gcc/config/ia64/ia64.opt
+++ b/gcc/config/ia64/ia64.opt
@@ -24,23 +24,23 @@ Variable
enum processor_type ia64_tune = PROCESSOR_ITANIUM2
mbig-endian
-Target Report RejectNegative Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Generate big endian code.
mlittle-endian
-Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN)
Generate little endian code.
mgnu-as
-Target Report Mask(GNU_AS)
+Target Mask(GNU_AS)
Generate code for GNU as.
mgnu-ld
-Target Report Mask(GNU_LD)
+Target Mask(GNU_LD)
Generate code for GNU ld.
mvolatile-asm-stop
-Target Report Mask(VOL_ASM_STOP)
+Target Mask(VOL_ASM_STOP)
Emit stop bits before and after volatile extended asms.
mregister-names
@@ -48,65 +48,65 @@ Target Mask(REG_NAMES)
Use in/loc/out register names.
mno-sdata
-Target Report RejectNegative Mask(NO_SDATA)
+Target RejectNegative Mask(NO_SDATA)
msdata
-Target Report RejectNegative InverseMask(NO_SDATA)
+Target RejectNegative InverseMask(NO_SDATA)
Enable use of sdata/scommon/sbss.
mno-pic
-Target Report RejectNegative Mask(NO_PIC)
+Target RejectNegative Mask(NO_PIC)
Generate code without GP reg.
mconstant-gp
-Target Report RejectNegative Mask(CONST_GP)
+Target RejectNegative Mask(CONST_GP)
gp is constant (but save/restore gp on indirect calls).
mauto-pic
-Target Report RejectNegative Mask(AUTO_PIC)
+Target RejectNegative Mask(AUTO_PIC)
Generate self-relocatable code.
minline-float-divide-min-latency
-Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 1)
+Target RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 1)
Generate inline floating point division, optimize for latency.
minline-float-divide-max-throughput
-Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 2) Init(2)
+Target RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 2) Init(2)
Generate inline floating point division, optimize for throughput.
mno-inline-float-divide
-Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 0)
+Target RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 0)
minline-int-divide-min-latency
-Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 1)
+Target RejectNegative Var(TARGET_INLINE_INT_DIV, 1)
Generate inline integer division, optimize for latency.
minline-int-divide-max-throughput
-Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 2)
+Target RejectNegative Var(TARGET_INLINE_INT_DIV, 2)
Generate inline integer division, optimize for throughput.
mno-inline-int-divide
-Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 0)
+Target RejectNegative Var(TARGET_INLINE_INT_DIV, 0)
Do not inline integer division.
minline-sqrt-min-latency
-Target Report RejectNegative Var(TARGET_INLINE_SQRT, 1)
+Target RejectNegative Var(TARGET_INLINE_SQRT, 1)
Generate inline square root, optimize for latency.
minline-sqrt-max-throughput
-Target Report RejectNegative Var(TARGET_INLINE_SQRT, 2)
+Target RejectNegative Var(TARGET_INLINE_SQRT, 2)
Generate inline square root, optimize for throughput.
mno-inline-sqrt
-Target Report RejectNegative Var(TARGET_INLINE_SQRT, 0)
+Target RejectNegative Var(TARGET_INLINE_SQRT, 0)
Do not inline square root.
mdwarf2-asm
-Target Report Mask(DWARF2_ASM)
+Target Mask(DWARF2_ASM)
Enable DWARF line debug info via GNU as.
mearly-stop-bits
-Target Report Mask(EARLY_STOP_BITS)
+Target Mask(EARLY_STOP_BITS)
Enable earlier placing stop bits for better scheduling.
mfixed-range=
@@ -132,35 +132,35 @@ EnumValue
Enum(ia64_tune) String(mckinley) Value(PROCESSOR_ITANIUM2)
msched-br-data-spec
-Target Report Var(mflag_sched_br_data_spec) Init(0)
+Target Var(mflag_sched_br_data_spec) Init(0)
Use data speculation before reload.
msched-ar-data-spec
-Target Report Var(mflag_sched_ar_data_spec) Init(1)
+Target Var(mflag_sched_ar_data_spec) Init(1)
Use data speculation after reload.
msched-control-spec
-Target Report Var(mflag_sched_control_spec) Init(2)
+Target Var(mflag_sched_control_spec) Init(2)
Use control speculation.
msched-br-in-data-spec
-Target Report Var(mflag_sched_br_in_data_spec) Init(1)
+Target Var(mflag_sched_br_in_data_spec) Init(1)
Use in block data speculation before reload.
msched-ar-in-data-spec
-Target Report Var(mflag_sched_ar_in_data_spec) Init(1)
+Target Var(mflag_sched_ar_in_data_spec) Init(1)
Use in block data speculation after reload.
msched-in-control-spec
-Target Report Var(mflag_sched_in_control_spec) Init(1)
+Target Var(mflag_sched_in_control_spec) Init(1)
Use in block control speculation.
msched-spec-ldc
-Target Report Var(mflag_sched_spec_ldc) Init(1)
+Target Var(mflag_sched_spec_ldc) Init(1)
Use simple data speculation check.
msched-spec-control-ldc
-Target Report Var(mflag_sched_spec_control_ldc) Init(0)
+Target Var(mflag_sched_spec_control_ldc) Init(0)
Use simple data speculation check for control speculation.
msched-prefer-non-data-spec-insns
@@ -170,15 +170,15 @@ msched-prefer-non-control-spec-insns
Target WarnRemoved
msched-count-spec-in-critical-path
-Target Report Var(mflag_sched_count_spec_in_critical_path) Init(0)
+Target Var(mflag_sched_count_spec_in_critical_path) Init(0)
Count speculative dependencies while calculating priority of instructions.
msched-stop-bits-after-every-cycle
-Target Report Var(mflag_sched_stop_bits_after_every_cycle) Init(1)
+Target Var(mflag_sched_stop_bits_after_every_cycle) Init(1)
Place a stop bit after every cycle when scheduling.
msched-fp-mem-deps-zero-cost
-Target Report Var(mflag_sched_fp_mem_deps_zero_cost) Init(0)
+Target Var(mflag_sched_fp_mem_deps_zero_cost) Init(0)
Assume that floating-point stores and loads are not likely to cause conflict when placed into one instruction group.
msched-max-memory-insns=
@@ -186,11 +186,11 @@ Target RejectNegative Joined UInteger Var(ia64_max_memory_insns) Init(1)
Soft limit on number of memory insns per instruction group, giving lower priority to subsequent memory insns attempting to schedule in the same insn group. Frequently useful to prevent cache bank conflicts. Default value is 1.
msched-max-memory-insns-hard-limit
-Target Report Var(mflag_sched_mem_insns_hard_limit) Init(0)
+Target Var(mflag_sched_mem_insns_hard_limit) Init(0)
Disallow more than 'msched-max-memory-insns' in instruction group. Otherwise, limit is 'soft' (prefer non-memory operations when limit is reached).
msel-sched-dont-check-control-spec
-Target Report Var(mflag_sel_sched_dont_check_control_spec) Init(0)
+Target Var(mflag_sel_sched_dont_check_control_spec) Init(0)
Don't generate checks for control speculation in selective scheduling.
; This comment is to ensure we retain the blank line above.
diff --git a/gcc/config/ia64/ilp32.opt b/gcc/config/ia64/ilp32.opt
index 2083a25..5c9a5a3 100644
--- a/gcc/config/ia64/ilp32.opt
+++ b/gcc/config/ia64/ilp32.opt
@@ -1,7 +1,7 @@
milp32
-Target Report RejectNegative Mask(ILP32)
+Target RejectNegative Mask(ILP32)
Generate ILP32 code.
mlp64
-Target Report RejectNegative InverseMask(ILP32)
+Target RejectNegative InverseMask(ILP32)
Generate LP64 code.
diff --git a/gcc/config/linux-android.opt b/gcc/config/linux-android.opt
index 665387e..2d60704 100644
--- a/gcc/config/linux-android.opt
+++ b/gcc/config/linux-android.opt
@@ -19,7 +19,7 @@
; <http://www.gnu.org/licenses/>.
mandroid
-Target Report Mask(ANDROID) Var(flag_android) Init(ANDROID_DEFAULT ? OPTION_MASK_ANDROID : 0)
+Target Mask(ANDROID) Var(flag_android) Init(ANDROID_DEFAULT ? OPTION_MASK_ANDROID : 0)
Generate code for the Android platform.
tno-android-cc
diff --git a/gcc/config/linux.opt b/gcc/config/linux.opt
index bd4a625..34b0a9e 100644
--- a/gcc/config/linux.opt
+++ b/gcc/config/linux.opt
@@ -20,17 +20,17 @@
; <http://www.gnu.org/licenses/>.
mbionic
-Target Report RejectNegative Var(linux_libc,LIBC_BIONIC) Init(DEFAULT_LIBC) Negative(mglibc)
+Target RejectNegative Var(linux_libc,LIBC_BIONIC) Init(DEFAULT_LIBC) Negative(mglibc)
Use Bionic C library.
mglibc
-Target Report RejectNegative Var(linux_libc,LIBC_GLIBC) Negative(muclibc)
+Target RejectNegative Var(linux_libc,LIBC_GLIBC) Negative(muclibc)
Use GNU C library.
muclibc
-Target Report RejectNegative Var(linux_libc,LIBC_UCLIBC) Negative(mmusl)
+Target RejectNegative Var(linux_libc,LIBC_UCLIBC) Negative(mmusl)
Use uClibc C library.
mmusl
-Target Report RejectNegative Var(linux_libc,LIBC_MUSL) Negative(mbionic)
+Target RejectNegative Var(linux_libc,LIBC_MUSL) Negative(mbionic)
Use musl C library.
diff --git a/gcc/config/lm32/lm32.opt b/gcc/config/lm32/lm32.opt
index c19a183..1260b48 100644
--- a/gcc/config/lm32/lm32.opt
+++ b/gcc/config/lm32/lm32.opt
@@ -20,21 +20,21 @@
; <http://www.gnu.org/licenses/>.
mmultiply-enabled
-Target Report Mask(MULTIPLY_ENABLED)
+Target Mask(MULTIPLY_ENABLED)
Enable multiply instructions.
mdivide-enabled
-Target Report Mask(DIVIDE_ENABLED)
+Target Mask(DIVIDE_ENABLED)
Enable divide and modulus instructions.
mbarrel-shift-enabled
-Target Report Mask(BARREL_SHIFT_ENABLED)
+Target Mask(BARREL_SHIFT_ENABLED)
Enable barrel shift instructions.
msign-extend-enabled
-Target Report Mask(SIGN_EXTEND_ENABLED)
+Target Mask(SIGN_EXTEND_ENABLED)
Enable sign extend instructions.
muser-enabled
-Target Report Mask(USER_ENABLED)
+Target Mask(USER_ENABLED)
Enable user-defined instructions.
diff --git a/gcc/config/m32r/m32r.opt b/gcc/config/m32r/m32r.opt
index 0ecafc9..b9a33c6 100644
--- a/gcc/config/m32r/m32r.opt
+++ b/gcc/config/m32r/m32r.opt
@@ -30,11 +30,11 @@ Variable
enum m32r_sdata m32r_sdata_selected = M32R_SDATA_DEFAULT
m32rx
-Target Report RejectNegative Mask(M32RX)
+Target RejectNegative Mask(M32RX)
Compile for the m32rx.
m32r2
-Target Report RejectNegative Mask(M32R2)
+Target RejectNegative Mask(M32R2)
Compile for the m32r2.
m32r
@@ -42,15 +42,15 @@ Target RejectNegative
Compile for the m32r.
malign-loops
-Target Report Mask(ALIGN_LOOPS)
+Target Mask(ALIGN_LOOPS)
Align all loops to 32 byte boundary.
mbranch-cost=1
-Target Report RejectNegative Mask(BRANCH_COST)
+Target RejectNegative Mask(BRANCH_COST)
Prefer branches over conditional execution.
mbranch-cost=2
-Target Report RejectNegative InverseMask(BRANCH_COST)
+Target RejectNegative InverseMask(BRANCH_COST)
Give branches their default cost.
mdebug
@@ -66,11 +66,11 @@ Target RejectNegative Joined UInteger Var(m32r_cache_flush_trap) Init(CACHE_FLUS
Specify cache flush trap number.
missue-rate=1
-Target Report RejectNegative Mask(LOW_ISSUE_RATE)
+Target RejectNegative Mask(LOW_ISSUE_RATE)
Only issue one instruction per cycle.
missue-rate=2
-Target Report RejectNegative InverseMask(LOW_ISSUE_RATE)
+Target RejectNegative InverseMask(LOW_ISSUE_RATE)
Allow two instructions to be issued per cycle.
mmodel=
diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
index 0d18e5a..a01647c 100644
--- a/gcc/config/m68k/linux.h
+++ b/gcc/config/m68k/linux.h
@@ -194,10 +194,10 @@ along with GCC; see the file COPYING3. If not see
#undef FINALIZE_TRAMPOLINE
#define FINALIZE_TRAMPOLINE(TRAMP) \
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
- LCT_NORMAL, VOIDmode, TRAMP, Pmode, \
- plus_constant (Pmode, TRAMP, TRAMPOLINE_SIZE), \
- Pmode);
+ maybe_emit_call_builtin___clear_cache ((TRAMP), \
+ plus_constant (Pmode, \
+ (TRAMP), \
+ TRAMPOLINE_SIZE))
/* Clear the instruction cache from `beg' to `end'. This makes an
inline system call to SYS_cacheflush. The arguments are as
diff --git a/gcc/config/m68k/m68k.opt b/gcc/config/m68k/m68k.opt
index 3ff0545..14d09d4 100644
--- a/gcc/config/m68k/m68k.opt
+++ b/gcc/config/m68k/m68k.opt
@@ -95,7 +95,7 @@ Target RejectNegative Mask(HARD_FLOAT)
Generate code that uses 68881 floating-point instructions.
malign-int
-Target Report Mask(ALIGN_INT)
+Target Mask(ALIGN_INT)
Align variables on a 32-bit boundary.
march=
@@ -103,7 +103,7 @@ Target RejectNegative Joined Enum(m68k_isa) Var(m68k_arch_option)
Specify the name of the target architecture.
mbitfield
-Target Report Mask(BITFIELD)
+Target Mask(BITFIELD)
Use the bit-field instructions.
mc68000
@@ -127,7 +127,7 @@ Target RejectNegative Alias(mcpu=, 68332)
Generate code for a cpu32.
mdiv
-Target Report Mask(CF_HWDIV)
+Target Mask(CF_HWDIV)
Use hardware division instructions on ColdFire.
mfidoa
@@ -139,11 +139,11 @@ Target RejectNegative Mask(HARD_FLOAT)
Generate code which uses hardware floating point instructions.
mid-shared-library
-Target Report Mask(ID_SHARED_LIBRARY)
+Target Mask(ID_SHARED_LIBRARY)
Enable ID based shared library.
mlong-jump-table-offsets
-Target Report RejectNegative Mask(LONG_JUMP_TABLE_OFFSETS)
+Target RejectNegative Mask(LONG_JUMP_TABLE_OFFSETS)
Use 32-bit offsets in jump tables rather than 16-bit offsets.
mnobitfield
@@ -159,15 +159,15 @@ Target RejectNegative InverseMask(SHORT)
Consider type 'int' to be 32 bits wide.
mpcrel
-Target Report Mask(PCREL)
+Target Mask(PCREL)
Generate pc-relative code.
mrtd
-Target Report Mask(RTD)
+Target Mask(RTD)
Use different calling convention using 'rtd'.
msep-data
-Target Report Mask(SEP_DATA)
+Target Mask(SEP_DATA)
Enable separate data segment.
mshared-library-id=
@@ -175,7 +175,7 @@ Target RejectNegative Joined UInteger
ID of shared library to build.
mshort
-Target Report Mask(SHORT)
+Target Mask(SHORT)
Consider type 'int' to be 16 bits wide.
msoft-float
@@ -183,7 +183,7 @@ Target RejectNegative InverseMask(HARD_FLOAT)
Generate code with library calls for floating point.
mstrict-align
-Target Report Mask(STRICT_ALIGNMENT)
+Target Mask(STRICT_ALIGNMENT)
Do not use unaligned memory references.
mtune=
@@ -191,9 +191,9 @@ Target RejectNegative Joined Enum(uarch_type) Var(m68k_tune_option) Init(unk_arc
Tune for the specified target CPU or architecture.
mxgot
-Target Report Mask(XGOT)
+Target Mask(XGOT)
Support more than 8192 GOT entries on ColdFire.
mxtls
-Target Report Mask(XTLS)
+Target Mask(XTLS)
Support TLS segment larger than 64K.
diff --git a/gcc/config/mcore/mcore.opt b/gcc/config/mcore/mcore.opt
index dc25e2b..3b3e556 100644
--- a/gcc/config/mcore/mcore.opt
+++ b/gcc/config/mcore/mcore.opt
@@ -19,35 +19,35 @@
; <http://www.gnu.org/licenses/>.
m210
-Target RejectNegative Report InverseMask(M340)
+Target RejectNegative InverseMask(M340)
Generate code for the M*Core M210.
m340
-Target RejectNegative Report Mask(M340)
+Target RejectNegative Mask(M340)
Generate code for the M*Core M340.
m4byte-functions
-Target Report Mask(OVERALIGN_FUNC)
+Target Mask(OVERALIGN_FUNC)
Force functions to be aligned to a 4 byte boundary.
mbig-endian
-Target RejectNegative Report InverseMask(LITTLE_END)
+Target RejectNegative InverseMask(LITTLE_END)
Generate big-endian code.
mcallgraph-data
-Target Report Mask(CG_DATA)
+Target Mask(CG_DATA)
Emit call graph information.
mdiv
-Target Report Mask(DIV)
+Target Mask(DIV)
Use the divide instruction.
mhardlit
-Target Report Mask(HARDLIT)
+Target Mask(HARDLIT)
Inline constants if it can be done in 2 insns or less.
mlittle-endian
-Target RejectNegative Report Mask(LITTLE_END)
+Target RejectNegative Mask(LITTLE_END)
Generate little-endian code.
; Not used by the compiler proper.
@@ -56,11 +56,11 @@ Target RejectNegative
Assume that run-time support has been provided, so omit -lsim from the linker command line.
mrelax-immediates
-Target Report Mask(RELAX_IMM)
+Target Mask(RELAX_IMM)
Use arbitrary sized immediates in bit operations.
mslow-bytes
-Target Report Mask(SLOW_BYTES)
+Target Mask(SLOW_BYTES)
Prefer word accesses over byte accesses.
; Maximum size we are allowed to grow the stack in a single operation.
@@ -71,5 +71,5 @@ Target RejectNegative Joined UInteger Var(mcore_stack_increment) Init(STACK_UNIT
Set the maximum amount for a single stack increment operation.
mwide-bitfields
-Target Report Mask(W_FIELD)
+Target Mask(W_FIELD)
Always treat bitfields as int-sized.
diff --git a/gcc/config/mcore/t-mcore b/gcc/config/mcore/t-mcore
index 0c8763a..638a2e0 100644
--- a/gcc/config/mcore/t-mcore
+++ b/gcc/config/mcore/t-mcore
@@ -23,7 +23,7 @@
# MULTILIB_DIRNAMES = align8 align4
# MULTILIB_MATCHES =
# MULTILIB_EXTRA_OPTS =
-# MULTILIB_EXCEPTIONS =
+MULTILIB_EXCEPTIONS = mlittle-endian/m210
MULTILIB_OPTIONS = mbig-endian/mlittle-endian m210/m340
MULTILIB_DIRNAMES = big little m210 m340
diff --git a/gcc/config/microblaze/microblaze.opt b/gcc/config/microblaze/microblaze.opt
index 725c2fa..8b3c2c1 100644
--- a/gcc/config/microblaze/microblaze.opt
+++ b/gcc/config/microblaze/microblaze.opt
@@ -36,11 +36,11 @@ Zxl-mode-xmdstub
Driver
msoft-float
-Target Report RejectNegative Mask(SOFT_FLOAT)
+Target RejectNegative Mask(SOFT_FLOAT)
Use software emulation for floating point (default).
mhard-float
-Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
+Target RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
Use hardware floating point instructions.
msmall-divides
@@ -56,11 +56,11 @@ Target Mask(MEMCPY)
Don't optimize block moves, use memcpy.
mbig-endian
-Target Report RejectNegative InverseMask(LITTLE_ENDIAN)
+Target RejectNegative InverseMask(LITTLE_ENDIAN)
Assume target CPU is configured as big endian.
mlittle-endian
-Target Report RejectNegative Mask(LITTLE_ENDIAN)
+Target RejectNegative Mask(LITTLE_ENDIAN)
Assume target CPU is configured as little endian.
mxl-soft-mul
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 513fc5f..58e474e 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -9315,10 +9315,10 @@ mips_select_rtx_section (machine_mode mode, rtx x,
default_function_rodata_section. */
static section *
-mips_function_rodata_section (tree decl)
+mips_function_rodata_section (tree decl, bool)
{
if (!TARGET_ABICALLS || TARGET_ABSOLUTE_ABICALLS || TARGET_GPWORD)
- return default_function_rodata_section (decl);
+ return default_function_rodata_section (decl, false);
if (decl && DECL_SECTION_NAME (decl))
{
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 1f19296..d2bfa9c 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -51,15 +51,15 @@ EnumValue
Enum(mips_abi) String(eabi) Value(ABI_EABI)
mabicalls
-Target Report Mask(ABICALLS)
+Target Mask(ABICALLS)
Generate code that can be used in SVR4-style dynamic objects.
mmad
-Target Report Var(TARGET_MAD)
+Target Var(TARGET_MAD)
Use PMC-style 'mad' instructions.
mimadd
-Target Report Mask(IMADD)
+Target Mask(IMADD)
Use integer madd/msub instructions.
march=
@@ -71,15 +71,15 @@ Target RejectNegative Joined UInteger Var(mips_branch_cost)
-mbranch-cost=COST Set the cost of branches to roughly COST instructions.
mbranch-likely
-Target Report Mask(BRANCHLIKELY)
+Target Mask(BRANCHLIKELY)
Use Branch Likely instructions, overriding the architecture default.
mflip-mips16
-Target Report Var(TARGET_FLIP_MIPS16)
+Target Var(TARGET_FLIP_MIPS16)
Switch on/off MIPS16 ASE on alternating functions for compiler testing.
mcheck-zero-division
-Target Report Mask(CHECK_ZERO_DIV)
+Target Mask(CHECK_ZERO_DIV)
Trap on integer divide by zero.
mcode-readable=
@@ -100,27 +100,27 @@ EnumValue
Enum(mips_code_readable_setting) String(no) Value(CODE_READABLE_NO)
mdivide-breaks
-Target Report RejectNegative Mask(DIVIDE_BREAKS)
+Target RejectNegative Mask(DIVIDE_BREAKS)
Use branch-and-break sequences to check for integer divide by zero.
mdivide-traps
-Target Report RejectNegative InverseMask(DIVIDE_BREAKS, DIVIDE_TRAPS)
+Target RejectNegative InverseMask(DIVIDE_BREAKS, DIVIDE_TRAPS)
Use trap instructions to check for integer divide by zero.
mdmx
-Target Report RejectNegative Var(TARGET_MDMX)
+Target RejectNegative Var(TARGET_MDMX)
Allow the use of MDMX instructions.
mdouble-float
-Target Report RejectNegative InverseMask(SINGLE_FLOAT, DOUBLE_FLOAT)
+Target RejectNegative InverseMask(SINGLE_FLOAT, DOUBLE_FLOAT)
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
mdsp
-Target Report Var(TARGET_DSP)
+Target Var(TARGET_DSP)
Use MIPS-DSP instructions.
mdspr2
-Target Report Var(TARGET_DSPR2)
+Target Var(TARGET_DSPR2)
Use MIPS-DSP REV 2 instructions.
mdebug
@@ -130,83 +130,83 @@ mdebugd
Target Var(TARGET_DEBUG_D_MODE) Undocumented
meb
-Target Report RejectNegative Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Use big-endian byte order.
mel
-Target Report RejectNegative InverseMask(BIG_ENDIAN, LITTLE_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN, LITTLE_ENDIAN)
Use little-endian byte order.
membedded-data
-Target Report Var(TARGET_EMBEDDED_DATA)
+Target Var(TARGET_EMBEDDED_DATA)
Use ROM instead of RAM.
meva
-Target Report Var(TARGET_EVA)
+Target Var(TARGET_EVA)
Use Enhanced Virtual Addressing instructions.
mexplicit-relocs
-Target Report Mask(EXPLICIT_RELOCS)
+Target Mask(EXPLICIT_RELOCS)
Use NewABI-style %reloc() assembly operators.
mextern-sdata
-Target Report Var(TARGET_EXTERN_SDATA) Init(1)
+Target Var(TARGET_EXTERN_SDATA) Init(1)
Use -G for data that is not defined by the current object.
mfix-24k
-Target Report Var(TARGET_FIX_24K)
+Target Var(TARGET_FIX_24K)
Work around certain 24K errata.
mfix-r4000
-Target Report Mask(FIX_R4000)
+Target Mask(FIX_R4000)
Work around certain R4000 errata.
mfix-r4400
-Target Report Mask(FIX_R4400)
+Target Mask(FIX_R4400)
Work around certain R4400 errata.
mfix-r5900
-Target Report Mask(FIX_R5900)
+Target Mask(FIX_R5900)
Work around the R5900 short loop erratum.
mfix-rm7000
-Target Report Var(TARGET_FIX_RM7000)
+Target Var(TARGET_FIX_RM7000)
Work around certain RM7000 errata.
mfix-r10000
-Target Report Mask(FIX_R10000)
+Target Mask(FIX_R10000)
Work around certain R10000 errata.
mfix-sb1
-Target Report Var(TARGET_FIX_SB1)
+Target Var(TARGET_FIX_SB1)
Work around errata for early SB-1 revision 2 cores.
mfix-vr4120
-Target Report Var(TARGET_FIX_VR4120)
+Target Var(TARGET_FIX_VR4120)
Work around certain VR4120 errata.
mfix-vr4130
-Target Report Var(TARGET_FIX_VR4130)
+Target Var(TARGET_FIX_VR4130)
Work around VR4130 mflo/mfhi errata.
mfix4300
-Target Report Var(TARGET_4300_MUL_FIX)
+Target Var(TARGET_4300_MUL_FIX)
Work around an early 4300 hardware bug.
mfp-exceptions
-Target Report Var(TARGET_FP_EXCEPTIONS) Init(1)
+Target Var(TARGET_FP_EXCEPTIONS) Init(1)
FP exceptions are enabled.
mfp32
-Target Report RejectNegative InverseMask(FLOAT64)
+Target RejectNegative InverseMask(FLOAT64)
Use 32-bit floating-point registers.
mfpxx
-Target Report RejectNegative Mask(FLOATXX)
+Target RejectNegative Mask(FLOATXX)
Conform to the o32 FPXX ABI.
mfp64
-Target Report RejectNegative Mask(FLOAT64)
+Target RejectNegative Mask(FLOAT64)
Use 64-bit floating-point registers.
mflush-func=
@@ -232,31 +232,31 @@ EnumValue
Enum(mips_ieee_754_value) String(legacy) Value(MIPS_IEEE_754_LEGACY)
mgp32
-Target Report RejectNegative InverseMask(64BIT)
+Target RejectNegative InverseMask(64BIT)
Use 32-bit general registers.
mgp64
-Target Report RejectNegative Mask(64BIT)
+Target RejectNegative Mask(64BIT)
Use 64-bit general registers.
mgpopt
-Target Report Var(TARGET_GPOPT) Init(1)
+Target Var(TARGET_GPOPT) Init(1)
Use GP-relative addressing to access small data.
mplt
-Target Report Var(TARGET_PLT)
+Target Var(TARGET_PLT)
When generating -mabicalls code, allow executables to use PLTs and copy relocations.
mhard-float
-Target Report RejectNegative InverseMask(SOFT_FLOAT_ABI, HARD_FLOAT_ABI)
+Target RejectNegative InverseMask(SOFT_FLOAT_ABI, HARD_FLOAT_ABI)
Allow the use of hardware floating-point ABI and instructions.
minterlink-compressed
-Target Report Var(TARGET_INTERLINK_COMPRESSED) Init(0)
+Target Var(TARGET_INTERLINK_COMPRESSED) Init(0)
Generate code that is link-compatible with MIPS16 and microMIPS code.
minterlink-mips16
-Target Report Var(TARGET_INTERLINK_COMPRESSED) Init(0)
+Target Var(TARGET_INTERLINK_COMPRESSED) Init(0)
An alias for minterlink-compressed provided for backward-compatibility.
mips
@@ -264,59 +264,59 @@ Target RejectNegative Joined ToLower Enum(mips_mips_opt_value) Var(mips_isa_opti
-mipsN Generate code for ISA level N.
mips16
-Target Report RejectNegative Mask(MIPS16)
+Target RejectNegative Mask(MIPS16)
Generate MIPS16 code.
mips3d
-Target Report RejectNegative Var(TARGET_MIPS3D)
+Target RejectNegative Var(TARGET_MIPS3D)
Use MIPS-3D instructions.
mllsc
-Target Report Mask(LLSC)
+Target Mask(LLSC)
Use ll, sc and sync instructions.
mlocal-sdata
-Target Report Var(TARGET_LOCAL_SDATA) Init(1)
+Target Var(TARGET_LOCAL_SDATA) Init(1)
Use -G for object-local data.
mlong-calls
-Target Report Var(TARGET_LONG_CALLS)
+Target Var(TARGET_LONG_CALLS)
Use indirect calls.
mlong32
-Target Report RejectNegative InverseMask(LONG64, LONG32)
+Target RejectNegative InverseMask(LONG64, LONG32)
Use a 32-bit long type.
mlong64
-Target Report RejectNegative Mask(LONG64)
+Target RejectNegative Mask(LONG64)
Use a 64-bit long type.
mmcount-ra-address
-Target Report Var(TARGET_MCOUNT_RA_ADDRESS)
+Target Var(TARGET_MCOUNT_RA_ADDRESS)
Pass the address of the ra save location to _mcount in $12.
mmemcpy
-Target Report Mask(MEMCPY)
+Target Mask(MEMCPY)
Don't optimize block moves.
mmicromips
-Target Report Mask(MICROMIPS)
+Target Mask(MICROMIPS)
Use microMIPS instructions.
mmsa
-Target Report Mask(MSA)
+Target Mask(MSA)
Use MIPS MSA Extension instructions.
mmt
-Target Report Var(TARGET_MT)
+Target Var(TARGET_MT)
Allow the use of MT instructions.
mno-float
-Target Report RejectNegative Var(TARGET_NO_FLOAT) Condition(TARGET_SUPPORTS_NO_FLOAT)
+Target RejectNegative Var(TARGET_NO_FLOAT) Condition(TARGET_SUPPORTS_NO_FLOAT)
Prevent the use of all floating-point operations.
mmcu
-Target Report Var(TARGET_MCU)
+Target Var(TARGET_MCU)
Use MCU instructions.
mno-flush-func
@@ -324,19 +324,19 @@ Target RejectNegative
Do not use a cache-flushing function before calling stack trampolines.
mno-mdmx
-Target Report RejectNegative Var(TARGET_MDMX, 0)
+Target RejectNegative Var(TARGET_MDMX, 0)
Do not use MDMX instructions.
mno-mips16
-Target Report RejectNegative InverseMask(MIPS16)
+Target RejectNegative InverseMask(MIPS16)
Generate normal-mode code.
mno-mips3d
-Target Report RejectNegative Var(TARGET_MIPS3D, 0)
+Target RejectNegative Var(TARGET_MIPS3D, 0)
Do not use MIPS-3D instructions.
mpaired-single
-Target Report Mask(PAIRED_SINGLE_FLOAT)
+Target Mask(PAIRED_SINGLE_FLOAT)
Use paired-single floating-point instructions.
mr10k-cache-barrier=
@@ -357,47 +357,47 @@ EnumValue
Enum(mips_r10k_cache_barrier_setting) String(none) Value(R10K_CACHE_BARRIER_NONE)
mrelax-pic-calls
-Target Report Mask(RELAX_PIC_CALLS)
+Target Mask(RELAX_PIC_CALLS)
Try to allow the linker to turn PIC calls into direct calls.
mshared
-Target Report Var(TARGET_SHARED) Init(1)
+Target Var(TARGET_SHARED) Init(1)
When generating -mabicalls code, make the code suitable for use in shared libraries.
msingle-float
-Target Report RejectNegative Mask(SINGLE_FLOAT)
+Target RejectNegative Mask(SINGLE_FLOAT)
Restrict the use of hardware floating-point instructions to 32-bit operations.
msmartmips
-Target Report Mask(SMARTMIPS)
+Target Mask(SMARTMIPS)
Use SmartMIPS instructions.
msoft-float
-Target Report RejectNegative Mask(SOFT_FLOAT_ABI)
+Target RejectNegative Mask(SOFT_FLOAT_ABI)
Prevent the use of all hardware floating-point instructions.
msplit-addresses
-Target Report Mask(SPLIT_ADDRESSES)
+Target Mask(SPLIT_ADDRESSES)
Optimize lui/addiu address loads.
msym32
-Target Report Var(TARGET_SYM32)
+Target Var(TARGET_SYM32)
Assume all symbols have 32-bit values.
msynci
-Target Report Mask(SYNCI)
+Target Mask(SYNCI)
Use synci instruction to invalidate i-cache.
mlra
-Target Report Var(mips_lra_flag) Init(1) Save
+Target Var(mips_lra_flag) Init(1) Save
Use LRA instead of reload.
mlxc1-sxc1
-Target Report Var(mips_lxc1_sxc1) Init(1)
+Target Var(mips_lxc1_sxc1) Init(1)
Use lwxc1/swxc1/ldxc1/sdxc1 instructions where applicable.
mmadd4
-Target Report Var(mips_madd4) Init(1)
+Target Var(mips_madd4) Init(1)
Use 4-operand madd.s/madd.d and related instructions where applicable.
mtune=
@@ -405,50 +405,50 @@ Target RejectNegative Joined Var(mips_tune_option) ToLower Enum(mips_arch_opt_va
-mtune=PROCESSOR Optimize the output for PROCESSOR.
muninit-const-in-rodata
-Target Report Var(TARGET_UNINIT_CONST_IN_RODATA)
+Target Var(TARGET_UNINIT_CONST_IN_RODATA)
Put uninitialized constants in ROM (needs -membedded-data).
mvirt
-Target Report Var(TARGET_VIRT)
+Target Var(TARGET_VIRT)
Use Virtualization (VZ) instructions.
mxpa
-Target Report Var(TARGET_XPA)
+Target Var(TARGET_XPA)
Use eXtended Physical Address (XPA) instructions.
mcrc
-Target Report Var(TARGET_CRC)
+Target Var(TARGET_CRC)
Use Cyclic Redundancy Check (CRC) instructions.
mginv
-Target Report Var(TARGET_GINV)
+Target Var(TARGET_GINV)
Use Global INValidate (GINV) instructions.
mvr4130-align
-Target Report Mask(VR4130_ALIGN)
+Target Mask(VR4130_ALIGN)
Perform VR4130-specific alignment optimizations.
mxgot
-Target Report Var(TARGET_XGOT)
+Target Var(TARGET_XGOT)
Lift restrictions on GOT size.
modd-spreg
-Target Report Mask(ODD_SPREG)
+Target Mask(ODD_SPREG)
Enable use of odd-numbered single-precision registers.
mframe-header-opt
-Target Report Var(flag_frame_header_optimization) Optimization
+Target Var(flag_frame_header_optimization) Optimization
Optimize frame header.
noasmopt
Driver
mload-store-pairs
-Target Report Var(TARGET_LOAD_STORE_PAIRS) Init(1)
+Target Var(TARGET_LOAD_STORE_PAIRS) Init(1)
Enable load/store bonding.
mcompact-branches=
-Target RejectNegative JoinedOrMissing Var(mips_cb) Report Enum(mips_cb_setting) Init(MIPS_CB_OPTIMAL)
+Target RejectNegative JoinedOrMissing Var(mips_cb) Enum(mips_cb_setting) Init(MIPS_CB_OPTIMAL)
Specify the compact branch usage policy.
Enum
@@ -465,13 +465,13 @@ EnumValue
Enum(mips_cb_setting) String(always) Value(MIPS_CB_ALWAYS)
mloongson-mmi
-Target Report Mask(LOONGSON_MMI)
+Target Mask(LOONGSON_MMI)
Use Loongson MultiMedia extensions Instructions (MMI) instructions.
mloongson-ext
-Target Report Mask(LOONGSON_EXT)
+Target Mask(LOONGSON_EXT)
Use Loongson EXTension (EXT) instructions.
mloongson-ext2
-Target Report Var(TARGET_LOONGSON_EXT2)
+Target Var(TARGET_LOONGSON_EXT2)
Use Loongson EXTension R2 (EXT2) instructions.
diff --git a/gcc/config/mmix/mmix.opt b/gcc/config/mmix/mmix.opt
index c0d3be3..38e5c59 100644
--- a/gcc/config/mmix/mmix.opt
+++ b/gcc/config/mmix/mmix.opt
@@ -20,48 +20,48 @@
; FIXME: Get rid of this one.
mlibfuncs
-Target Report Mask(LIBFUNC)
+Target Mask(LIBFUNC)
For intrinsics library: pass all parameters in registers.
mabi=mmixware
-Target Report RejectNegative InverseMask(ABI_GNU)
+Target RejectNegative InverseMask(ABI_GNU)
Use register stack for parameters and return value.
mabi=gnu
-Target Report RejectNegative Mask(ABI_GNU)
+Target RejectNegative Mask(ABI_GNU)
Use call-clobbered registers for parameters and return value.
; FIXME: Provide a way to *load* the epsilon register.
mepsilon
-Target Report Mask(FCMP_EPSILON)
+Target Mask(FCMP_EPSILON)
Use epsilon-respecting floating point compare instructions.
mzero-extend
-Target Report Mask(ZERO_EXTEND)
+Target Mask(ZERO_EXTEND)
Use zero-extending memory loads, not sign-extending ones.
mknuthdiv
-Target Report Mask(KNUTH_DIVISION)
+Target Mask(KNUTH_DIVISION)
Generate divide results with reminder having the same sign as the divisor (not the dividend).
mtoplevel-symbols
-Target Report Mask(TOPLEVEL_SYMBOLS)
+Target Mask(TOPLEVEL_SYMBOLS)
Prepend global symbols with \":\" (for use with PREFIX).
mno-set-program-start
-Target Report RejectNegative
+Target RejectNegative
Do not provide a default start-address 0x100 of the program.
melf
-Target Report RejectNegative
+Target RejectNegative
Link to emit program in ELF format (rather than mmo).
mbranch-predict
-Target Report RejectNegative Mask(BRANCH_PREDICT)
+Target RejectNegative Mask(BRANCH_PREDICT)
Use P-mnemonics for branches statically predicted as taken.
mno-branch-predict
-Target Report RejectNegative InverseMask(BRANCH_PREDICT)
+Target RejectNegative InverseMask(BRANCH_PREDICT)
Don't use P-mnemonics for branches.
; We use the term "base address" since that's what Knuth uses. The base
@@ -75,25 +75,25 @@ Don't use P-mnemonics for branches.
; registers, and you'll not find out until link time whether you
; should have compiled with -mno-base-addresses.
mbase-addresses
-Target Report RejectNegative Mask(BASE_ADDRESSES)
+Target RejectNegative Mask(BASE_ADDRESSES)
Use addresses that allocate global registers.
mno-base-addresses
-Target Report RejectNegative InverseMask(BASE_ADDRESSES)
+Target RejectNegative InverseMask(BASE_ADDRESSES)
Do not use addresses that allocate global registers.
msingle-exit
-Target Report RejectNegative InverseMask(USE_RETURN_INSN)
+Target RejectNegative InverseMask(USE_RETURN_INSN)
Generate a single exit point for each function.
mno-single-exit
-Target Report RejectNegative Mask(USE_RETURN_INSN)
+Target RejectNegative Mask(USE_RETURN_INSN)
Do not generate a single exit point for each function.
mset-program-start=
-Target Report RejectNegative Joined
+Target RejectNegative Joined
Set start-address of the program.
mset-data-start=
-Target Report RejectNegative Joined
+Target RejectNegative Joined
Set start-address of data.
diff --git a/gcc/config/mn10300/mn10300.opt b/gcc/config/mn10300/mn10300.opt
index 13b45e1..b1b9c8b 100644
--- a/gcc/config/mn10300/mn10300.opt
+++ b/gcc/config/mn10300/mn10300.opt
@@ -34,7 +34,7 @@ Target
Target the AM33/2.0 processor.
mam34
-Target Report
+Target
Target the AM34 processor.
mtune=
@@ -42,7 +42,7 @@ Target RejectNegative Joined Var(mn10300_tune_string)
Tune code for the given processor.
mmult-bug
-Target Report Mask(MULT_BUG)
+Target Mask(MULT_BUG)
Work around hardware multiply bug.
; Ignored by the compiler
@@ -55,13 +55,13 @@ Target RejectNegative
Enable linker relaxations.
mreturn-pointer-on-d0
-Target Report Mask(PTR_A0D0)
+Target Mask(PTR_A0D0)
Return pointers in both a0 and d0.
mliw
-Target Report Mask(ALLOW_LIW)
+Target Mask(ALLOW_LIW)
Allow gcc to generate LIW instructions.
msetlb
-Target Report Mask(ALLOW_SETLB)
+Target Mask(ALLOW_SETLB)
Allow gcc to generate the SETLB and Lcc instructions.
diff --git a/gcc/config/moxie/moxie.opt b/gcc/config/moxie/moxie.opt
index e84edd3..7c77823 100644
--- a/gcc/config/moxie/moxie.opt
+++ b/gcc/config/moxie/moxie.opt
@@ -19,15 +19,15 @@
; <http://www.gnu.org/licenses/>.
meb
-Target RejectNegative Report InverseMask(LITTLE_ENDIAN)
+Target RejectNegative InverseMask(LITTLE_ENDIAN)
Generate big-endian code.
mel
-Target RejectNegative Report Mask(LITTLE_ENDIAN)
+Target RejectNegative Mask(LITTLE_ENDIAN)
Generate little-endian code.
mmul.x
-Target Report Mask(HAS_MULX)
+Target Mask(HAS_MULX)
Enable MUL.X and UMUL.X instructions.
; Ignored by the compiler
diff --git a/gcc/config/msp430/msp430-protos.h b/gcc/config/msp430/msp430-protos.h
index 0b4d9a4..33ad1ad 100644
--- a/gcc/config/msp430/msp430-protos.h
+++ b/gcc/config/msp430/msp430-protos.h
@@ -26,7 +26,7 @@ void msp430_expand_eh_return (rtx);
void msp430_expand_epilogue (int);
void msp430_expand_helper (rtx *operands, const char *, bool);
void msp430_expand_prologue (void);
-const char * msp430x_extendhisi (rtx *);
+int msp430x_extendhisi (rtx *, bool);
void msp430_fixup_compare_operands (machine_mode, rtx *);
int msp430_hard_regno_nregs_has_padding (int, machine_mode);
int msp430_hard_regno_nregs_with_padding (int, machine_mode);
@@ -49,10 +49,11 @@ rtx msp430_subreg (machine_mode, rtx, machine_mode, int);
bool msp430_use_f5_series_hwmult (void);
bool msp430_has_hwmult (void);
bool msp430_op_not_in_high_mem (rtx op);
+bool msp430x_insn_required (rtx op);
#ifdef RTX_CODE
int msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands);
-const char * msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, rtx *operands);
+int msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, rtx *operands, bool);
#endif
#endif /* GCC_MSP430_PROTOS_H */
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index de4b16b..db3a9ff 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -49,13 +49,18 @@
#include "msp430-devices.h"
#include "incpath.h"
#include "prefix.h"
+#include "insn-config.h"
+#include "insn-attr.h"
+#include "recog.h"
/* This file should be included last. */
#include "target-def.h"
static void msp430_compute_frame_info (void);
-static bool use_32bit_hwmult (void);
+static bool msp430_use_16bit_hwmult (void);
+static bool msp430_use_32bit_hwmult (void);
+static bool use_helper_for_const_shift (machine_mode mode, HOST_WIDE_INT amt);
@@ -1031,30 +1036,635 @@ msp430_legitimate_constant (machine_mode mode, rtx x)
}
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS msp430_rtx_costs
+/* Describing Relative Costs of Operations
+ To model the cost of an instruction, use the number of cycles when
+ optimizing for speed, and the number of words when optimizing for size.
+ The cheapest instruction will execute in one cycle and cost one word.
+ The cycle and size costs correspond to 430 ISA instructions, not 430X
+ instructions or 430X "address" instructions. The relative costs of 430X
+ instructions is accurately modeled with the 430 costs. The relative costs
+ of some "address" instructions can differ, but these are not yet handled.
+ Adding support for this could improve performance/code size. */
+
+struct single_op_cost
+{
+ const int reg;
+ /* Indirect register (@Rn) or indirect autoincrement (@Rn+). */
+ const int ind;
+ const int mem;
+};
+
+static const struct single_op_cost cycle_cost_single_op =
+{
+ 1, 3, 4
+};
+
+static const struct single_op_cost size_cost_single_op =
+{
+ 1, 1, 2
+};
+
+/* When the destination of an insn is memory, the cost is always the same
+ regardless of whether that memory is accessed using indirect register,
+ indexed or absolute addressing.
+ When the source operand is memory, indirect register and post-increment have
+ the same cost, which is lower than indexed and absolute, which also have
+ the same cost. */
+struct double_op_cost
+{
+ /* Source operand is a register. */
+ const int r2r;
+ const int r2pc;
+ const int r2m;
+
+ /* Source operand is memory, using indirect register (@Rn) or indirect
+ autoincrement (@Rn+) addressing modes. */
+ const int ind2r;
+ const int ind2pc;
+ const int ind2m;
+
+ /* Source operand is an immediate. */
+ const int imm2r;
+ const int imm2pc;
+ const int imm2m;
+
+ /* Source operand is memory, using indexed (x(Rn)) or absolute (&ADDR)
+ addressing modes. */
+ const int mem2r;
+ const int mem2pc;
+ const int mem2m;
+};
+
+/* These structures describe the cost of MOV, BIT and CMP instructions, in terms
+ of clock cycles or words. */
+static const struct double_op_cost cycle_cost_double_op_mov =
+{
+ 1, 3, 3,
+ 2, 4, 4,
+ 2, 3, 4,
+ 3, 5, 5
+};
+
+/* Cycle count when memory is the destination operand is one larger than above
+ for instructions that aren't MOV, BIT or CMP. */
+static const struct double_op_cost cycle_cost_double_op =
+{
+ 1, 3, 4,
+ 2, 4, 5,
+ 2, 3, 5,
+ 3, 5, 6
+};
+
+static const struct double_op_cost size_cost_double_op =
+{
+ 1, 1, 2,
+ 1, 1, 2,
+ 2, 2, 3,
+ 2, 2, 3
+};
+
+struct msp430_multlib_costs
+{
+ const int mulhi;
+ const int mulsi;
+ const int muldi;
+};
+
+/* There is no precise size cost when using libcalls, instead it is disparaged
+ relative to other instructions.
+ The cycle costs are from the CALL to the RET, inclusive.
+ FIXME muldi cost is not accurate. */
+static const struct msp430_multlib_costs cycle_cost_multlib_32bit =
+{
+ 27, 33, 66
+};
+
+/* 32bit multiply takes a few more instructions on 16bit hwmult. */
+static const struct msp430_multlib_costs cycle_cost_multlib_16bit =
+{
+ 27, 42, 66
+};
+
+/* TARGET_REGISTER_MOVE_COST
+ There is only one class of general-purpose, non-fixed registers, and the
+ relative cost of moving data between them is always the same.
+ Therefore, the default of 2 is optimal. */
+
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST msp430_memory_move_cost
+
+/* Return the cost of moving data between registers and memory.
+ The returned cost must be relative to the default TARGET_REGISTER_MOVE_COST
+ of 2.
+ IN is false if the value is to be written to memory. */
+static int
+msp430_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
+ reg_class_t rclass ATTRIBUTE_UNUSED,
+ bool in)
+{
+ int cost;
+ const struct double_op_cost *cost_p;
+ /* Optimize with a code size focus by default, unless -O2 or above is
+ specified. */
+ bool speed = (!optimize_size && optimize >= 2);
+
+ cost_p = (speed ? &cycle_cost_double_op_mov : &size_cost_double_op);
+
+ if (in)
+ /* Reading from memory using indirect addressing is assumed to be the more
+ common case. */
+ cost = cost_p->ind2r;
+ else
+ cost = cost_p->r2m;
+
+ /* All register to register moves cost 1 cycle or 1 word, so multiply by 2
+ to get the costs relative to TARGET_REGISTER_MOVE_COST of 2. */
+ return 2 * cost;
+}
+
+/* For X, which must be a MEM RTX, return TRUE if it is an indirect memory
+ reference, @Rn or @Rn+. */
+static bool
+msp430_is_mem_indirect (rtx x)
+{
+ gcc_assert (GET_CODE (x) == MEM);
+ rtx op0 = XEXP (x, 0);
+ return (GET_CODE (op0) == REG || GET_CODE (op0) == POST_INC);
+}
+
+/* Costs of MSP430 instructions are generally based on the addressing mode
+ combination of the source and destination operands.
+ Given source operand SRC (which may be NULL to indicate a single-operand
+ instruction) and destination operand DST return the cost of this
+ expression. */
+static int
+msp430_costs (rtx src, rtx dst, bool speed, rtx outer_rtx)
+{
+ enum rtx_code src_code = GET_CODE (src);
+ enum rtx_code dst_code = GET_CODE (dst);
+ enum rtx_code outer_code = GET_CODE (outer_rtx);
+ machine_mode outer_mode = GET_MODE (outer_rtx);
+ const struct double_op_cost *cost_p;
+ cost_p = (speed ? &cycle_cost_double_op : &size_cost_double_op);
+
+ if (outer_code == TRUNCATE
+ && (outer_mode == QImode
+ || outer_mode == HImode
+ || outer_mode == PSImode))
+ /* Truncation to these modes is normally free as a side effect of the
+ instructions themselves. */
+ return 0;
+
+ if (dst_code == SYMBOL_REF
+ || dst_code == LABEL_REF
+ || dst_code == CONST_INT)
+ /* Catch RTX like (minus (const_int 0) (reg)) but don't add any cost. */
+ return 0;
+
+ switch (src_code)
+ {
+ case REG:
+ return (dst_code == REG ? cost_p->r2r
+ : (dst_code == PC ? cost_p->r2pc : cost_p->r2m));
+
+ case CONST_INT:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ return (dst_code == REG ? cost_p->imm2r
+ : (dst_code == PC ? cost_p->imm2pc : cost_p->imm2m));
+
+
+ case MEM:
+ if (msp430_is_mem_indirect (src))
+ return (dst_code == REG ? cost_p->ind2r : (dst_code == PC
+ ? cost_p->ind2pc
+ : cost_p->ind2m));
+ else
+ return (dst_code == REG ? cost_p->mem2r : (dst_code == PC
+ ? cost_p->mem2pc
+ : cost_p->mem2m));
+ default:
+ return cost_p->mem2m;
+ }
+}
+
+/* Given source operand SRC and destination operand DST from the shift or
+ rotate RTX OUTER_RTX, return the cost of performing that shift, assuming
+ optimization for speed when SPEED is true. */
+static int
+msp430_shift_costs (rtx src, rtx dst, bool speed, rtx outer_rtx)
+{
+ int amt;
+ enum rtx_code src_code = GET_CODE (src);
+ enum rtx_code dst_code = GET_CODE (dst);
+ const struct single_op_cost *cost_p;
+
+ cost_p = (speed ? &cycle_cost_single_op : &size_cost_single_op);
+
+ if (src_code != CONST_INT)
+ /* The size or speed cost when the shift amount is unknown cannot be
+ accurately calculated, so just disparage it slightly. */
+ return 2 * msp430_costs (src, dst, speed, outer_rtx);
+
+ if (use_helper_for_const_shift (GET_MODE (outer_rtx), amt = INTVAL (src)))
+ {
+ /* GCC sometimes tries to perform shifts in some very inventive ways,
+ resulting in much larger code size usage than necessary, if
+ they are disparaged too much here. So in general, if
+ use_helper_for_const_shift thinks a helper should be used, obey
+ that and don't disparage the shift any more than a regular
+ instruction, even though the shift may actually cost more.
+ This ensures that the RTL generated at the initial expand pass has the
+ expected shift instructions, which can be mapped to the helper
+ functions. */
+ return msp430_costs (src, dst, speed, outer_rtx);
+ }
+
+ if (!msp430x)
+ {
+ /* Each shift by one place will be emitted individually. */
+ switch (dst_code)
+ {
+ case REG:
+ case CONST_INT:
+ return amt * cost_p->reg;
+ case MEM:
+ if (msp430_is_mem_indirect (dst))
+ return amt * cost_p->ind;
+ else
+ return amt * cost_p->mem;
+ default:
+ return amt * cost_p->mem;
+ }
+ }
+
+ /* RRAM, RRCM, RRUM, RLAM are used for shift counts <= 4, otherwise, the 'X'
+ versions are used.
+ Instructions which shift a MEM operand will never actually be output. It
+ will always be copied into a register to allow for efficient shifting. So
+ the cost just takes into account the cost of an additional copy in that
+ case. */
+ return (amt <= 4 ? (speed ? amt : 1) : (speed ? amt + 1 : 2)
+ + (dst_code == REG ? 0
+ : msp430_costs (dst, gen_rtx_REG (HImode, 10), speed, outer_rtx)));
+}
-static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
- machine_mode mode,
- int outer_code ATTRIBUTE_UNUSED,
- int opno ATTRIBUTE_UNUSED,
- int * total,
- bool speed ATTRIBUTE_UNUSED)
+/* Given source operand SRC and destination operand DST from the MULT/DIV/MOD
+ RTX OUTER_RTX, return the cost of performing that operation, assuming
+ optimization for speed when SPEED is true. */
+static int
+msp430_muldiv_costs (rtx src, rtx dst, bool speed, rtx outer_rtx,
+ machine_mode outer_mode)
{
- int code = GET_CODE (x);
+ enum rtx_code outer_code = GET_CODE (outer_rtx);
+ const struct msp430_multlib_costs *cost_p;
+ cost_p = (msp430_use_16bit_hwmult ()
+ ? &cycle_cost_multlib_32bit
+ : &cycle_cost_multlib_16bit);
+
+ int factor = 1;
+ /* Only used in some calculations. */
+ int mode_factor = 1;
+ if (outer_mode == SImode)
+ mode_factor = 2;
+ else if (outer_mode == PSImode)
+ /* PSImode multiplication is performed using SImode operands, so has extra
+ cost to factor in the conversions necessary before/after the
+ operation. */
+ mode_factor = 3;
+ else if (outer_mode == DImode)
+ mode_factor = 4;
+
+ if (!speed)
+ {
+ /* The codesize cost of using a helper function to perform the
+ multiplication or division cannot be accurately calculated, since the
+ cost depends on how many times the operation is performed in the
+ entire program. */
+ if (outer_code != MULT)
+ /* Division is always expensive. */
+ factor = 7;
+ else if (((msp430_use_16bit_hwmult () && outer_mode != DImode)
+ || msp430_use_32bit_hwmult ()
+ || msp430_use_f5_series_hwmult ()))
+ /* When the hardware multiplier is available, only disparage
+ slightly. */
+ factor = 2;
+ else
+ factor = 5;
+ return factor * mode_factor * msp430_costs (src, dst, speed, outer_rtx);
+ }
+ /* When there is hardware multiply support, there is a relatively low, fixed
+ cycle cost to performing any multiplication, but when there is no hardware
+ multiply support it is very costly. That precise cycle cost has not been
+ calculated here.
+ Division is extra slow since it always uses a software library.
+ The 16-bit hardware multiply library cannot be used to produce 64-bit
+ results. */
+ if (outer_code != MULT || !msp430_has_hwmult ()
+ || (outer_mode == DImode && msp430_use_16bit_hwmult ()))
+ {
+ factor = (outer_code == MULT ? 50 : 70);
+ return factor * mode_factor * msp430_costs (src, dst, speed, outer_rtx);
+ }
+
+ switch (outer_mode)
+ {
+ case E_QImode:
+ case E_HImode:
+ /* Include the cost of copying the operands into and out of the hardware
+ multiply routine. */
+ return cost_p->mulhi + (3 * msp430_costs (src, dst, speed, outer_rtx));
+
+ case E_PSImode:
+ /* Extra factor for the conversions necessary to do PSI->SI before the
+ operation. */
+ factor = 2;
+ /* fallthru. */
+ case E_SImode:
+ return factor * (cost_p->mulsi
+ + (6 * msp430_costs (src, dst, speed, outer_rtx)));
+
+ case E_DImode:
+ default:
+ return cost_p->muldi + (12 * msp430_costs (src, dst, speed, outer_rtx));
+ }
+}
+
+/* Recurse within X to find the actual destination operand of the expression.
+ For example:
+ (plus (ashift (minus (ashift (reg)
+ (const_int) ......
+ should return the reg RTX. */
+static rtx
+msp430_get_inner_dest_code (rtx x)
+{
+ enum rtx_code code = GET_CODE (x);
+ rtx op0 = XEXP (x, 0);
switch (code)
{
- case SIGN_EXTEND:
- if (mode == SImode && outer_code == SET)
+ case REG:
+ case SYMBOL_REF:
+ case CONST_INT:
+ case CONST:
+ case LABEL_REF:
+ return x;
+
+ case MEM:
+ /* Return the MEM expr not the inner REG for these cases. */
+ switch (GET_CODE (op0))
{
- *total = COSTS_N_INSNS (4);
- return true;
+ case REG:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ case POST_INC:
+ return x;
+
+ case PLUS:
+ /* return MEM (PLUS (REG) (CONST)) */
+ if (GET_CODE (XEXP (op0, 0)) == REG)
+ {
+ if (GET_CODE (XEXP (op0, 1)) == CONST_INT
+ || GET_CODE (XEXP (op0, 1)) == CONST
+ || GET_CODE (XEXP (op0, 1)) == LABEL_REF
+ || GET_CODE (XEXP (op0, 1)) == SYMBOL_REF)
+ return x;
+ else
+ return msp430_get_inner_dest_code (op0);
+ }
+ return msp430_get_inner_dest_code (op0);
+
+ default:
+ if (GET_RTX_FORMAT (code)[0] != 'e')
+ return x;
+ return msp430_get_inner_dest_code (op0);
}
break;
+
+ default:
+ if (op0 == NULL_RTX)
+ gcc_unreachable ();
+ else
+ {
+ if (GET_RTX_FORMAT (code)[0] != 'e'
+ && code != ENTRY_VALUE)
+ return x;
+ return msp430_get_inner_dest_code (op0);
+ }
+ }
+}
+
+/* Calculate the cost of an MSP430 single-operand instruction, for operand DST
+ within the RTX OUTER_RTX, optimizing for speed if SPEED is true. */
+static int
+msp430_single_op_cost (rtx dst, bool speed, rtx outer_rtx)
+{
+ enum rtx_code dst_code = GET_CODE (dst);
+ const struct single_op_cost *cost_p;
+ const struct double_op_cost *double_op_cost_p;
+
+ cost_p = (speed ? &cycle_cost_single_op : &size_cost_single_op);
+ double_op_cost_p = (speed ? &cycle_cost_double_op : &size_cost_double_op);
+
+ switch (dst_code)
+ {
+ case REG:
+ return cost_p->reg;
+ case MEM:
+ if (msp430_is_mem_indirect (dst))
+ return cost_p->ind;
+ else
+ return cost_p->mem;
+
+ case CONST_INT:
+ case CONST_FIXED:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case CONST:
+ /* A constant value would need to be copied into a register first. */
+ return double_op_cost_p->imm2r + cost_p->reg;
+
+ default:
+ return cost_p->mem;
}
- return false;
}
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS msp430_rtx_costs
+
+/* This target hook describes the relative costs of RTL expressions.
+ The function recurses to just before the lowest level of the expression,
+ when both of the operands of the expression can be examined at the same time.
+ This is because the cost of the expression depends on the specific
+ addressing mode combination of the operands.
+ The hook returns true when all subexpressions of X have been processed, and
+ false when rtx_cost should recurse. */
+static bool
+msp430_rtx_costs (rtx x,
+ machine_mode mode,
+ int outer_code ATTRIBUTE_UNUSED,
+ int opno ATTRIBUTE_UNUSED,
+ int * total,
+ bool speed)
+{
+ enum rtx_code code = GET_CODE (x);
+ rtx dst, src;
+ rtx dst_inner, src_inner;
+
+ *total = 0;
+ dst = XEXP (x, 0);
+ if (GET_RTX_LENGTH (code) == 1)
+ /* Some RTX that are single-op in GCC are double-op when translated to
+ MSP430 instructions e.g NOT, NEG, ZERO_EXTEND. */
+ src = dst;
+ else
+ src = XEXP (x, 1);
+
+
+ switch (code)
+ {
+ case SET:
+ /* Ignoring SET improves codesize. */
+ if (!speed)
+ return true;
+ /* fallthru. */
+ case PLUS:
+ if (outer_code == MEM)
+ /* Do not add any cost for the plus itself, but recurse in case there
+ are more complicated RTX inside. */
+ return false;
+ /* fallthru. */
+ case MINUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case NOT:
+ case ZERO_EXTEND:
+ case TRUNCATE:
+ case NEG:
+ case ZERO_EXTRACT:
+ case SIGN_EXTRACT:
+ case IF_THEN_ELSE:
+ dst_inner = msp430_get_inner_dest_code (dst);
+ src_inner = msp430_get_inner_dest_code (src);
+ *total = COSTS_N_INSNS (msp430_costs (src_inner, dst_inner, speed, x));
+ if (mode == SImode)
+ *total *= 2;
+ if (mode == DImode)
+ *total *= 4;
+ return false;
+
+ case ROTATE:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ dst_inner = msp430_get_inner_dest_code (dst);
+ src_inner = msp430_get_inner_dest_code (src);
+ *total = COSTS_N_INSNS (msp430_shift_costs (src_inner, dst_inner,
+ speed, x));
+ if (mode == SImode)
+ *total *= 2;
+ if (mode == DImode)
+ *total *= 4;
+ return false;
+
+ case MULT:
+ case DIV:
+ case MOD:
+ case UDIV:
+ case UMOD:
+ dst_inner = msp430_get_inner_dest_code (dst);
+ src_inner = msp430_get_inner_dest_code (src);
+ *total = COSTS_N_INSNS (msp430_muldiv_costs (src_inner, dst_inner, speed,
+ x, mode));
+ return false;
+
+ case CALL:
+ case SIGN_EXTEND:
+ dst_inner = msp430_get_inner_dest_code (dst);
+ *total = COSTS_N_INSNS (msp430_single_op_cost (dst_inner, speed, x));
+ if (mode == SImode)
+ *total *= 2;
+ if (mode == DImode)
+ *total *= 4;
+ return false;
+
+ case CONST_INT:
+ case CONST_FIXED:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case CONST:
+ case LABEL_REF:
+ case REG:
+ case PC:
+ case POST_INC:
+ if (mode == SImode)
+ *total = COSTS_N_INSNS (2);
+ else if (mode == DImode)
+ *total = COSTS_N_INSNS (4);
+ return true;
+
+ case MEM:
+ /* PSImode operands are expensive when in memory. */
+ if (mode == PSImode)
+ *total = COSTS_N_INSNS (1);
+ else if (mode == SImode)
+ *total = COSTS_N_INSNS (2);
+ else if (mode == DImode)
+ *total = COSTS_N_INSNS (4);
+ /* Recurse into the MEM. */
+ return false;
+
+ case EQ:
+ case NE:
+ case GT:
+ case GTU:
+ case GE:
+ case GEU:
+ case LT:
+ case LTU:
+ case LE:
+ case LEU:
+ /* Conditions are mostly equivalent, changing their relative
+ costs has no effect. */
+ return false;
+
+ case ASM_OPERANDS:
+ case ASM_INPUT:
+ case CLOBBER:
+ case COMPARE:
+ case CONCAT:
+ case ENTRY_VALUE:
+ /* Other unhandled expressions. */
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+#undef TARGET_INSN_COST
+#define TARGET_INSN_COST msp430_insn_cost
+
+static int
+msp430_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED)
+{
+ if (recog_memoized (insn) < 0)
+ return 0;
+
+ /* The returned cost must be relative to COSTS_N_INSNS (1). An insn with a
+ length of 2 bytes is the smallest possible size and so must be equivalent
+ to COSTS_N_INSNS (1). */
+ return COSTS_N_INSNS (get_attr_length (insn) / 2);
+
+ /* FIXME Add more detailed costs when optimizing for speed.
+ For now the length of the instruction is a good approximiation and roughly
+ correlates with cycle cost. */
+}
+
/* Function Entry and Exit */
@@ -1358,15 +1968,18 @@ msp430_section_attr (tree * node,
const char * message = NULL;
- /* The "noinit" and "section" attributes are handled generically, so we
- cannot set up additional target-specific attribute exclusions using the
- existing mechanism. */
- if (has_attr (ATTR_NOINIT, *node))
+ /* The "noinit", "persistent", and "section" attributes are handled
+ generically, so we cannot set up additional target-specific attribute
+ exclusions using the existing mechanism. */
+ if (has_attr (ATTR_NOINIT, *node) && !TREE_NAME_EQ (name, "lower"))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<noinit%>");
else if (has_attr ("section", *node) && !TREE_NAME_EQ (name, "lower"))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<section%>");
+ else if (has_attr (ATTR_PERSIST, *node) && !TREE_NAME_EQ (name, "lower"))
+ message = G_("ignoring attribute %qE because it conflicts with "
+ "attribute %<persistent%>");
/* It does not make sense to use upper/lower/either attributes without
-mlarge.
Without -mlarge, "lower" is the default and only region, so is redundant.
@@ -1387,56 +2000,6 @@ msp430_section_attr (tree * node,
return NULL_TREE;
}
-static tree
-msp430_persist_attr (tree *node,
- tree name,
- tree args,
- int flags ATTRIBUTE_UNUSED,
- bool * no_add_attrs ATTRIBUTE_UNUSED)
-{
- const char * message = NULL;
-
- gcc_assert (DECL_P (* node));
- gcc_assert (args == NULL);
- gcc_assert (TREE_NAME_EQ (name, ATTR_PERSIST));
-
- /* Check for the section attribute separately from DECL_SECTION_NAME so
- we can provide a clearer warning. */
- if (has_attr ("section", *node))
- message = G_("ignoring attribute %qE because it conflicts with "
- "attribute %<section%>");
- /* Check that it's possible for the variable to have a section. */
- else if ((TREE_STATIC (*node) || DECL_EXTERNAL (*node) || in_lto_p)
- && (DECL_SECTION_NAME (*node)))
- message = G_("%qE attribute cannot be applied to variables with specific "
- "sections");
- else if (has_attr (ATTR_NOINIT, *node))
- message = G_("ignoring attribute %qE because it conflicts with "
- "attribute %<noinit%>");
- else if (TREE_CODE (*node) != VAR_DECL)
- message = G_("%qE attribute only applies to variables");
- else if (!TREE_STATIC (*node) && !TREE_PUBLIC (*node)
- && !DECL_EXTERNAL (*node))
- message = G_("%qE attribute has no effect on automatic variables");
- else if (DECL_COMMON (*node) || DECL_INITIAL (*node) == NULL)
- message = G_("variables marked with %qE attribute must be initialized");
- else
- /* It's not clear if there is anything that can be set here to prevent the
- front end placing the variable before the back end can handle it, in a
- similar way to how DECL_COMMON is cleared for .noinit variables in
- handle_noinit_attribute (gcc/c-family/c-attribs.c).
- So just place the variable in the .persistent section now. */
- set_decl_section_name (* node, ".persistent");
-
- if (message)
- {
- warning (OPT_Wattributes, message, name);
- * no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
/* Helper to define attribute exclusions. */
#define ATTR_EXCL(name, function, type, variable) \
{ name, function, type, variable }
@@ -1471,7 +2034,6 @@ static const struct attribute_spec::exclusions attr_lower_exclusions[] =
{
ATTR_EXCL (ATTR_UPPER, true, true, true),
ATTR_EXCL (ATTR_EITHER, true, true, true),
- ATTR_EXCL (ATTR_PERSIST, true, true, true),
ATTR_EXCL (NULL, false, false, false)
};
@@ -1479,7 +2041,6 @@ static const struct attribute_spec::exclusions attr_upper_exclusions[] =
{
ATTR_EXCL (ATTR_LOWER, true, true, true),
ATTR_EXCL (ATTR_EITHER, true, true, true),
- ATTR_EXCL (ATTR_PERSIST, true, true, true),
ATTR_EXCL (NULL, false, false, false)
};
@@ -1487,15 +2048,6 @@ static const struct attribute_spec::exclusions attr_either_exclusions[] =
{
ATTR_EXCL (ATTR_LOWER, true, true, true),
ATTR_EXCL (ATTR_UPPER, true, true, true),
- ATTR_EXCL (ATTR_PERSIST, true, true, true),
- ATTR_EXCL (NULL, false, false, false)
-};
-
-static const struct attribute_spec::exclusions attr_persist_exclusions[] =
-{
- ATTR_EXCL (ATTR_LOWER, true, true, true),
- ATTR_EXCL (ATTR_UPPER, true, true, true),
- ATTR_EXCL (ATTR_EITHER, true, true, true),
ATTR_EXCL (NULL, false, false, false)
};
@@ -1523,9 +2075,6 @@ const struct attribute_spec msp430_attribute_table[] =
{ ATTR_EITHER, 0, 0, true, false, false, false, msp430_section_attr,
attr_either_exclusions },
- { ATTR_PERSIST, 0, 0, true, false, false, false, msp430_persist_attr,
- attr_persist_exclusions },
-
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -1542,14 +2091,13 @@ msp430_handle_generic_attribute (tree *node,
{
const char *message = NULL;
- /* The front end has set up an exclusion between the "noinit" and "section"
- attributes. */
- if (!(TREE_NAME_EQ (name, ATTR_NOINIT) || TREE_NAME_EQ (name, "section")))
- return NULL_TREE;
-
- /* We allow the "lower" attribute to be used on variables with the "section"
- attribute. */
- if (has_attr (ATTR_LOWER, *node) && !TREE_NAME_EQ (name, "section"))
+ /* Permit the "lower" attribute to be set on variables with the "section",
+ "noinit" and "persistent" attributes. This is used to indicate that the
+ corresponding output section will be in lower memory, so a 430X
+ instruction is not required to handle it. */
+ if (has_attr (ATTR_LOWER, *node)
+ && !(TREE_NAME_EQ (name, "section") || TREE_NAME_EQ (name, ATTR_PERSIST)
+ || TREE_NAME_EQ (name, ATTR_NOINIT)))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<lower%>");
else if (has_attr (ATTR_UPPER, *node))
@@ -1558,9 +2106,6 @@ msp430_handle_generic_attribute (tree *node,
else if (has_attr (ATTR_EITHER, *node))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<either%>");
- else if (has_attr (ATTR_PERSIST, *node))
- message = G_("ignoring attribute %qE because it conflicts with "
- "attribute %<persistent%>");
if (message)
{
@@ -1818,18 +2363,6 @@ gen_prefix (tree decl)
return NULL;
}
-static section * persist_section;
-
-#undef TARGET_ASM_INIT_SECTIONS
-#define TARGET_ASM_INIT_SECTIONS msp430_init_sections
-
-static void
-msp430_init_sections (void)
-{
- persist_section = get_unnamed_section (0, output_section_asm_op,
- ".section .persistent,\"aw\"");
-}
-
#undef TARGET_ASM_SELECT_SECTION
#define TARGET_ASM_SELECT_SECTION msp430_select_section
@@ -1855,11 +2388,8 @@ msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
&& is_interrupt_func (decl))
return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
- if (has_attr (ATTR_PERSIST, decl))
- return persist_section;
-
- /* ATTR_NOINIT is handled generically. */
- if (has_attr (ATTR_NOINIT, decl))
+ /* The "noinit" and "persistent" attributes are handled generically. */
+ if (has_attr (ATTR_NOINIT, decl) || has_attr (ATTR_PERSIST, decl))
return default_elf_select_section (decl, reloc, align);
prefix = gen_prefix (decl);
@@ -1955,8 +2485,6 @@ msp430_section_type_flags (tree decl, const char * name, int reloc)
name += strlen (upper_prefix);
else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
name += strlen (either_prefix);
- else if (strcmp (name, ".persistent") == 0)
- return SECTION_WRITE | SECTION_NOTYPE;
return default_section_type_flags (decl, name, reloc);
}
@@ -2769,7 +3297,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
if (msp430_use_f5_series_hwmult ())
fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
"_f5hw", NULL));
- else if (use_32bit_hwmult ())
+ else if (msp430_use_32bit_hwmult ())
{
/* When the arguments are 16-bits, the 16-bit hardware multiplier is
used. */
@@ -2780,8 +3308,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
"_hw32", NULL));
}
- /* 16-bit hardware multiply. */
- else if (msp430_has_hwmult ())
+ else if (msp430_use_16bit_hwmult ())
fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
"_hw", NULL));
else
@@ -2818,8 +3345,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
/* Return TRUE if the helper function should be used and FALSE if the shifts
insns should be emitted inline. */
static bool
-use_helper_for_const_shift (enum rtx_code code, machine_mode mode,
- HOST_WIDE_INT amt)
+use_helper_for_const_shift (machine_mode mode, HOST_WIDE_INT amt)
{
const int default_inline_shift = 4;
/* We initialize the option to 65 so we know if the user set it or not. */
@@ -2830,6 +3356,9 @@ use_helper_for_const_shift (enum rtx_code code, machine_mode mode,
the heuristic accordingly. */
int max_inline_32 = max_inline / 2;
+ if (mode == E_DImode)
+ return true;
+
/* Don't use helpers for these modes on 430X, when optimizing for speed, or
when emitting a small number of insns. */
if ((mode == E_QImode || mode == E_HImode || mode == E_PSImode)
@@ -2867,7 +3396,7 @@ msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands)
constant. */
if (!CONST_INT_P (operands[2])
|| mode == E_DImode
- || use_helper_for_const_shift (code, mode, INTVAL (operands[2])))
+ || use_helper_for_const_shift (mode, INTVAL (operands[2])))
{
const char *helper_name = NULL;
/* The const variants of mspabi shifts have significantly larger code
@@ -2923,18 +3452,22 @@ msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands)
For 430X it is inneficient to do so for any modes except SI and DI, since we
can make use of R*M insns or RPT with 430X insns, so this function is only
used for SImode in that case. */
-const char *
+int
msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode,
- rtx *operands)
+ rtx *operands, bool return_length)
{
int i;
int amt;
int max_shift = GET_MODE_BITSIZE (mode) - 1;
+ int length = 0;
+
gcc_assert (CONST_INT_P (operands[2]));
amt = INTVAL (operands[2]);
if (amt == 0 || amt > max_shift)
{
+ if (return_length)
+ return 0;
switch (code)
{
case ASHIFT:
@@ -2952,17 +3485,28 @@ msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode,
default:
gcc_unreachable ();
}
- return "";
+ return 0;
}
if (code == ASHIFT)
{
if (!msp430x && mode == HImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("RLA.W\t%0", operands);
+ {
+ if (return_length)
+ length = 2 + (MEM_P (operands[0]) ? 2 : 0);
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("RLA.W\t%0", operands);
+ }
else if (mode == SImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("RLA%X0.W\t%L0 { RLC%X0.W\t%H0", operands);
+ {
+ if (return_length)
+ length = 4 + (MEM_P (operands[0]) ? 4 : 0)
+ + (4 * msp430x_insn_required (operands[0]));
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("RLA%X0.W\t%L0 { RLC%X0.W\t%H0", operands);
+ }
else
/* Catch unhandled cases. */
gcc_unreachable ();
@@ -2970,33 +3514,61 @@ msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode,
else if (code == ASHIFTRT)
{
if (!msp430x && mode == HImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("RRA.W\t%0", operands);
+ {
+ if (return_length)
+ length = 2 + (MEM_P (operands[0]) ? 2 : 0);
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("RRA.W\t%0", operands);
+ }
else if (mode == SImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("RRA%X0.W\t%H0 { RRC%X0.W\t%L0", operands);
+ {
+ if (return_length)
+ length = 4 + (MEM_P (operands[0]) ? 4 : 0)
+ + (4 * msp430x_insn_required (operands[0]));
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("RRA%X0.W\t%H0 { RRC%X0.W\t%L0", operands);
+ }
else
gcc_unreachable ();
}
else if (code == LSHIFTRT)
{
if (!msp430x && mode == HImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("CLRC { RRC.W\t%0", operands);
+ {
+ if (return_length)
+ length = 4 + (MEM_P (operands[0]) ? 2 : 0);
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("CLRC { RRC.W\t%0", operands);
+ }
else if (mode == SImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0", operands);
+ {
+ if (return_length)
+ length = 6 + (MEM_P (operands[0]) ? 4 : 0)
+ + (4 * msp430x_insn_required (operands[0]));
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0",
+ operands);
+ }
/* FIXME: Why doesn't "RRUX.W\t%H0 { RRC%X0.W\t%L0" work for msp430x?
It causes execution timeouts e.g. pr41963.c. */
#if 0
else if (msp430x && mode == SImode)
- for (i = 0; i < amt; i++)
- output_asm_insn ("RRUX.W\t%H0 { RRC%X0.W\t%L0", operands);
+ {
+ if (return_length)
+ length = 2;
+ else
+ for (i = 0; i < amt; i++)
+ output_asm_insn ("RRUX.W\t%H0 { RRC%X0.W\t%L0", operands);
+ }
#endif
else
gcc_unreachable ();
}
- return "";
+ return length * amt;
}
/* Called by cbranch<mode>4 to coerce operands into usable forms. */
@@ -3277,7 +3849,7 @@ msp430_use_f5_series_hwmult (void)
32-bit hardware multiplier. */
static bool
-use_32bit_hwmult (void)
+msp430_use_32bit_hwmult (void)
{
static const char * cached_match = NULL;
static bool cached_result;
@@ -3300,6 +3872,34 @@ use_32bit_hwmult (void)
return cached_result = false;
}
+/* Returns true if the current MCU has a first generation
+ 16-bit hardware multiplier. */
+
+static bool
+msp430_use_16bit_hwmult (void)
+{
+ static const char * cached_match = NULL;
+ static bool cached_result;
+
+ if (msp430_hwmult_type == MSP430_HWMULT_SMALL)
+ return true;
+
+ if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
+ return false;
+
+ if (target_mcu == cached_match)
+ return cached_result;
+
+ cached_match = target_mcu;
+
+ msp430_extract_mcu_data (target_mcu);
+ if (extracted_mcu_data.name != NULL)
+ return cached_result = (extracted_mcu_data.hwmpy == 1
+ || extracted_mcu_data.hwmpy == 2);
+
+ return cached_result = false;
+}
+
/* Returns true if the current MCU does not have a
hardware multiplier of any kind. */
@@ -3349,28 +3949,6 @@ msp430_output_labelref (FILE *file, const char *name)
break;
}
- /* If we have been given a specific MCU name then we may be
- able to make use of its hardware multiply capabilities. */
- if (msp430_has_hwmult ())
- {
- if (strcmp ("__mspabi_mpyi", name) == 0)
- {
- if (msp430_use_f5_series_hwmult ())
- name = "__mulhi2_f5";
- else
- name = "__mulhi2";
- }
- else if (strcmp ("__mspabi_mpyl", name) == 0)
- {
- if (msp430_use_f5_series_hwmult ())
- name = "__mulsi2_f5";
- else if (use_32bit_hwmult ())
- name = "__mulsi2_hw32";
- else
- name = "__mulsi2";
- }
- }
-
if (user_label_prefix[0] != 0)
fputs (user_label_prefix, file);
@@ -3518,6 +4096,20 @@ msp430_op_not_in_high_mem (rtx op)
return false;
}
+/* Based on the operand OP, is a 430X insn required to handle it?
+ There are only 3 conditions for which a 430X insn is required:
+ - PSImode operand
+ - memory reference to a symbol which could be in upper memory
+ (so its address is > 0xFFFF)
+ - absolute address which has VOIDmode, i.e. (mem:HI (const_int))
+ Use a 430 insn if none of these conditions are true. */
+bool
+msp430x_insn_required (rtx op)
+{
+ return (GET_MODE (op) == PSImode
+ || !msp430_op_not_in_high_mem (op));
+}
+
#undef TARGET_PRINT_OPERAND
#define TARGET_PRINT_OPERAND msp430_print_operand
@@ -3858,35 +4450,52 @@ msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED,
/* Generate a sequence of instructions to sign-extend an HI
value into an SI value. Handles the tricky case where
- we are overwriting the destination. */
-
-const char *
-msp430x_extendhisi (rtx * operands)
+ we are overwriting the destination.
+ Return the number of bytes used by the emitted instructions.
+ If RETURN_LENGTH is true then do not emit the assembly instruction
+ sequence. */
+int
+msp430x_extendhisi (rtx * operands, bool return_length)
{
if (REGNO (operands[0]) == REGNO (operands[1]))
- /* Low word of dest == source word. 8-byte sequence. */
- return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0";
-
- if (! msp430x)
- /* Note: This sequence is approximately the same length as invoking a helper
- function to perform the sign-extension, as in:
-
- MOV.W %1, %L0
- MOV.W %1, r12
- CALL __mspabi_srai_15
- MOV.W r12, %H0
-
- but this version does not involve any function calls or using argument
- registers, so it reduces register pressure. 10-byte sequence. */
- return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 "
- "{ INV.W\t%H0, %H0";
-
- if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
- /* High word of dest == source word. 6-byte sequence. */
- return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0";
+ {
+ /* Low word of dest == source word. */
+ if (!return_length)
+ output_asm_insn ("BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0",
+ operands);
+ return 8;
+ }
+ else if (! msp430x)
+ {
+ /* Note: This sequence is approximately the same length as invoking a
+ helper function to perform the sign-extension, as in:
+
+ MOV.W %1, %L0
+ MOV.W %1, r12
+ CALL __mspabi_srai_15
+ MOV.W r12, %H0
+
+ but this version does not involve any function calls or using argument
+ registers, so it reduces register pressure. */
+ if (!return_length)
+ output_asm_insn ("MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0",
+ operands);
+ return 10;
+ }
+ else if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
+ {
+ /* High word of dest == source word. */
+ if (!return_length)
+ output_asm_insn ("MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0",
+ operands);
+ return 6;
+ }
- /* No overlap between dest and source. 8-byte sequence. */
- return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0";
+ /* No overlap between dest and source. */
+ if (!return_length)
+ output_asm_insn ("MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0",
+ operands);
+ return 8;
}
/* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index 2500771..049151e 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -243,6 +243,14 @@ extern const char *msp430_get_linker_devices_include_path (int, const char **);
#define HAS_LONG_COND_BRANCH 0
#define HAS_LONG_UNCOND_BRANCH 0
+/* The cost of a branch sequence is roughly 3 "cheap" instructions. */
+#define BRANCH_COST(speed_p, predictable_p) 3
+
+/* Override the default BRANCH_COST heuristic to indicate that it is preferable
+ to retain short-circuit operations, this results in significantly better
+ codesize and performance. */
+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
+
#define LOAD_EXTEND_OP(M) ZERO_EXTEND
#define WORD_REGISTER_OPERATIONS 1
@@ -530,3 +538,13 @@ void msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED,
#define SYMBOL_FLAG_LOW_MEM (SYMBOL_FLAG_MACH_DEP << 0)
+
+#define ADJUST_INSN_LENGTH(insn, length) \
+ do \
+ { \
+ if (recog_memoized (insn) >= 0) \
+ { \
+ length += get_attr_extra_length (insn); \
+ length *= get_attr_length_multiplier (insn); \
+ } \
+ } while (0)
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index ad244bb..1ec219c 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -58,8 +58,100 @@
UNS_DELAY_END
])
-;; This is an approximation.
-(define_attr "length" "" (const_int 4))
+;; Instruction length is calculated by examining the type and number of
+;; operands.
+;; Whether the insn uses the 430X extension word, or is a 430X address
+;; instruction also has an effect.
+;; "Cheap" source operands do not contribute to the overall length of the insn
+;; and are register (Rn), indirect post-increment (@Rn+) and indirect register
+;; (@Rn).
+;; The lengths of instructions in bytes are:
+;; Single-op 430: Cheap op == 2
+;; (also CALLA) Other op == 4
+;; Double-op 430: Source is not cheap == 2
+;; (also MOVA, Dest is register == 2
+;; CMPA, ADDA, Dest is not a register == 4
+;; SUBA) (sum the source and dest cost)
+;; Single-op 430X: For insn names ending in 'X' add 2 to single-op 430 cost.
+;; Double-op 430X: Insn name ends in 'M' == 2
+;; Others have the same cost as double-op 430 but add 2.
+;;
+;; The insn type describes whether it is a single or double operand MSP430
+;; instruction (some single-operand GCC instructions are actually
+;; double-operand on the target).
+;; "triple" and "cmp" types use the costs of a double operand type but
+;; instead assume that the src operand is in op2, and also cmp types assume the
+;; dst operand is in op1.
+;; This attribute also describes which operands are safe to examine
+;; when calculating the length or extension. GCC will segfault trying to
+;; examine a non-existant operand of an insn.
+(define_attr "type" "none,single,double,triple,cmp" (const_string "none"))
+
+;; The M extension is for instructions like RRAM - they always
+;; only, and the operand must be a register.
+(define_attr "extension" "none,x,a,m"
+ (cond [(eq_attr "type" "none")
+ (const_string "none")
+ (match_operand 0 "msp430_high_memory_operand" "")
+ (const_string "x")
+ (and (eq_attr "type" "double")
+ (match_operand 1 "msp430_high_memory_operand" ""))
+ (const_string "x")
+ (and (ior (eq_attr "type" "triple") (eq_attr "type" "cmp"))
+ (ior (match_operand 1 "msp430_high_memory_operand" "")
+ (match_operand 2 "msp430_high_memory_operand" "")))
+ (const_string "x")]
+ (const_string "none")))
+
+;; Multiply the default length by this constant value.
+(define_attr "length_multiplier" "" (const_int 1))
+
+;; Add an additional amount to the total length of the insn.
+(define_attr "extra_length" "" (const_int 0))
+
+;; FIXME for some reason if we move the addition of 2 for extension == x to
+;; ADJUST_INSN_LENGTH, codesize gets much worse.
+(define_attr "length" ""
+ (cond [(eq_attr "extension" "m")
+ (const_int 2)
+ (eq_attr "type" "single")
+ (plus (if_then_else (match_operand 0 "msp430_cheap_operand" "")
+ (const_int 2)
+ (const_int 4))
+ (if_then_else (eq_attr "extension" "x")
+ (const_int 2)
+ (const_int 0)))
+ (eq_attr "type" "double")
+ (plus (plus (if_then_else (match_operand 0 "register_operand" "")
+ (const_int 2)
+ (const_int 4))
+ (if_then_else (match_operand 1 "msp430_cheap_operand" "")
+ (const_int 0)
+ (const_int 2)))
+ (if_then_else (eq_attr "extension" "x")
+ (const_int 2)
+ (const_int 0)))
+ (eq_attr "type" "triple")
+ (plus (plus (if_then_else (match_operand 0 "register_operand" "")
+ (const_int 2)
+ (const_int 4))
+ (if_then_else (match_operand 2 "msp430_cheap_operand" "")
+ (const_int 0)
+ (const_int 2)))
+ (if_then_else (eq_attr "extension" "x")
+ (const_int 2)
+ (const_int 0)))
+ (eq_attr "type" "cmp")
+ (plus (plus (if_then_else (match_operand 1 "register_operand" "")
+ (const_int 2)
+ (const_int 4))
+ (if_then_else (match_operand 2 "msp430_cheap_operand" "")
+ (const_int 0)
+ (const_int 2)))
+ (if_then_else (eq_attr "extension" "x")
+ (const_int 2)
+ (const_int 0)))]
+ (const_int 2)))
(include "predicates.md")
(include "constraints.md")
@@ -97,35 +189,43 @@
(match_operand:HI 0 "register_operand" "r"))]
""
"PUSH\t%0"
- )
+ [(set_attr "type" "single")]
+)
(define_insn "pusha"
[(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
(match_operand:PSI 0 "register_operand" "r"))]
"TARGET_LARGE"
"PUSHX.A\t%0"
- )
+ [(set_attr "type" "single")
+ (set_attr "extension" "x")]
+)
(define_insn "pushm"
[(unspec_volatile [(match_operand 0 "register_operand" "r")
(match_operand 1 "immediate_operand" "n")] UNS_PUSHM)]
""
"PUSHM%b0\t%1, %0"
- )
+ [(set_attr "type" "single")
+ (set_attr "extension" "m")]
+)
(define_insn "pop"
[(set (match_operand:HI 0 "register_operand" "=r")
(mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
""
"POP\t%0"
- )
+ [(set_attr "type" "single")]
+)
(define_insn "popa"
[(set (match_operand:PSI 0 "register_operand" "=r")
(mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
"TARGET_LARGE"
"POPX.A\t%0"
- )
+ [(set_attr "type" "single")
+ (set_attr "extension" "x")]
+)
;; This is nasty. Operand0 is bogus. It is only there so that we can get a
;; mode for the %b0 to work. We should use operand1 for this, but that does
@@ -144,7 +244,9 @@
(match_operand 2 "immediate_operand" "i")] UNS_POPM)]
""
"POPM%b0\t%2, r%J1"
- )
+ [(set_attr "type" "single")
+ (set_attr "extension" "m")]
+)
;; The next two patterns are here to support a "feature" of how GCC implements
;; varargs. When a function uses varargs and the *second* to last named
@@ -170,6 +272,10 @@
return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\";
return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\";
"
+ [(set (attr "length")
+ (if_then_else (match_test "TARGET_LARGE")
+ (const_int 8)
+ (const_int 6)))]
)
(define_insn "swap_and_shrink"
@@ -178,7 +284,12 @@
"* return TARGET_LARGE
? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\"
: \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\";
- ")
+ "
+ [(set (attr "length")
+ (if_then_else (match_test "TARGET_LARGE")
+ (const_int 10)
+ (const_int 8)))]
+)
; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a
; zero_extend anyway. Catch it here.
@@ -189,6 +300,7 @@
"@
MOV.B\t%1, %0
MOV%X1.B\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_insn "movqi_topbyte"
@@ -196,6 +308,8 @@
(subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
"msp430x"
"PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
+ [(set_attr "length" "6")
+ (set_attr "type" "double")]
)
(define_insn "movqi"
@@ -205,6 +319,7 @@
"@
MOV.B\t%1, %0
MOVX.B\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_insn "movhi"
@@ -215,6 +330,7 @@
MOV.B\t%1, %0
MOV.W\t%1, %0
MOVX.W\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_expand "movsi"
@@ -222,7 +338,7 @@
(match_operand:SI 1 "general_operand"))]
""
""
- )
+)
(define_insn_and_split "movsi_s"
[(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
@@ -235,7 +351,8 @@
(set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
(match_operand:HI 5 "general_operand"))]
"msp430_split_movsi (operands);"
- )
+ [(set_attr "type" "double")]
+)
(define_insn_and_split "movsi_x"
[(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
@@ -248,6 +365,7 @@
(set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
(match_operand:HI 5 "general_operand"))]
"msp430_split_movsi (operands);"
+ [(set_attr "type" "double")]
)
;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
@@ -260,7 +378,10 @@
MOV.W\t%1, %0
MOVA\t%1, %0
MOVA\t%1, %0
- MOVX.A\t%1, %0")
+ MOVX.A\t%1, %0"
+ [(set_attr "extension" "none,none,a,a,x")
+ (set_attr "type" "double")]
+)
; This pattern is identical to the truncsipsi2 pattern except
; that it uses a SUBREG instead of a TRUNC. It is needed in
@@ -274,6 +395,8 @@
(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
"msp430x"
"PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
+ [(set_attr "length" "6")
+ (set_attr "type" "double")]
)
;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c.
@@ -282,6 +405,8 @@
(subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
"msp430x"
"MOVA\t%1, %0"
+ [(set_attr "extension" "a")
+ (set_attr "type" "double")]
)
;;------------------------------------------------------------
@@ -295,6 +420,8 @@
"@
ADDA\t%2, %0
ADDX.A\t%2, %0"
+ [(set_attr "extension" "a,x")
+ (set_attr "type" "triple")]
)
(define_insn "addqi3"
@@ -305,6 +432,7 @@
"@
ADD.B\t%2, %0
ADDX.B\t%2, %0"
+ [(set_attr "type" "triple")]
)
(define_insn "addhi3"
@@ -315,6 +443,7 @@
"@
ADD.W\t%2, %0
ADDX.W\t%2, %0"
+ [(set_attr "type" "triple")]
)
; This pattern is needed in order to avoid reload problems.
@@ -327,6 +456,13 @@
(match_operand 2 "general_operand" "rmi")))]
""
"ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
+ [(set (attr "length")
+ (if_then_else (match_operand 2 "register_operand" "")
+ (const_int 10)
+ (if_then_else (match_operand 2 "msp430_high_memory_operand" "")
+ (const_int 18)
+ (const_int 14))))
+ (set_attr "type" "triple")]
)
(define_insn "addsi3"
@@ -337,6 +473,8 @@
"@
ADD\t%L2, %L0 { ADDC\t%H2, %H0
ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
+ [(set_attr "length_multiplier" "2")
+ (set_attr "type" "triple")]
)
; Version of addhi that exposes the carry operations, for SImode adds.
@@ -382,7 +520,8 @@
"@
ADD\t%2, %1 ; cy
ADDX\t%2, %1 ; cy"
- )
+ [(set_attr "type" "triple")]
+)
(define_insn "addhi3_cy_i"
[(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm")
@@ -397,7 +536,8 @@
"@
ADD\t%2, %1 ; cy
ADD%X0\t%2, %1 ; cy"
- )
+ [(set_attr "type" "triple")]
+)
; Version of addhi that adds the carry, for SImode adds.
(define_insn "addchi4_cy"
@@ -410,7 +550,8 @@
"@
ADDC\t%2, %1
ADDCX\t%2, %1"
- )
+ [(set_attr "type" "triple")]
+)
; Split an SImode add into two HImode adds, keeping track of the carry
; so that gcc knows when it can and can't optimize away the two
@@ -440,7 +581,7 @@
if (msp430_split_addsi (operands))
FAIL;
"
- )
+)
;; Alternatives 2 and 3 are to handle cases generated by reload.
@@ -454,6 +595,9 @@
SUBX.A\t%2, %0
MOVX.A\t%1, %0 { SUBX.A\t%2, %0
MOVX.A\t%1, %0 { SUBA\t%2, %0"
+ [(set_attr "type" "triple")
+ (set_attr "extension" "a,x,x,x")
+ (set_attr "length_multiplier" "1,1,2,2")]
)
;; Alternatives 2 and 3 are to handle cases generated by reload.
@@ -467,6 +611,8 @@
SUBX.B\t%2, %0
MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
+ [(set_attr "length_multiplier" "1,1,2,2")
+ (set_attr "type" "triple")]
)
;; Alternatives 2 and 3 are to handle cases generated by reload.
@@ -480,6 +626,8 @@
SUBX.W\t%2, %0
MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
+ [(set_attr "length_multiplier" "1,1,2,2")
+ (set_attr "type" "triple")]
)
(define_insn "subsi3"
@@ -490,6 +638,8 @@
"@
SUB\t%L2, %L0 { SUBC\t%H2, %H0
SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
+ [(set_attr "length_multiplier" "2")
+ (set_attr "type" "triple")]
)
(define_insn "*bic<mode>_cg"
@@ -500,6 +650,8 @@
"@
BIC%x0%b0\t#%I2, %0
BIC%X0%b0\t#%I2, %0"
+ [(set_attr "length" "2") ; Smaller length achieved by using constant generator
+ (set_attr "type" "double")]
)
(define_insn "bic<mode>3"
@@ -510,6 +662,7 @@
"@
BIC%x0%b0\t%1, %0
BICX%b0\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_insn "and<mode>3"
@@ -521,6 +674,7 @@
AND%x0.B\t%2, %0
AND%x0%b0\t%2, %0
ANDX%b0\t%2, %0"
+ [(set_attr "type" "triple")]
)
(define_insn "ior<mode>3"
@@ -531,6 +685,7 @@
"@
BIS%x0%b0\t%2, %0
BISX%b0\t%2, %0"
+ [(set_attr "type" "triple")]
)
(define_insn "xor<mode>3"
@@ -541,6 +696,7 @@
"@
XOR%x0%b0\t%2, %0
XORX%b0\t%2, %0"
+ [(set_attr "type" "triple")]
)
;; Macro : XOR #~0, %0
@@ -551,6 +707,7 @@
"@
INV%x0%b0\t%0
INV%X0%b0\t%0"
+ [(set_attr "type" "double")]
)
(define_insn "extendqihi2"
@@ -560,6 +717,7 @@
"@
SXT%X0\t%0
SXT%X0\t%0"
+ [(set_attr "type" "single")]
)
(define_insn "extendqipsi2"
@@ -569,6 +727,8 @@
"@
SXT\t%0
SXTX.A\t%0"
+ [(set_attr "type" "single")
+ (set_attr "extension" "none,x")]
)
;; ------------------------
@@ -590,6 +750,7 @@
MOV.B\t%1, %0
MOV%X1.B\t%1, %0
AND%X0\t#0xff, %0"
+ [(set_attr "type" "double")]
)
(define_insn "zero_extendqipsi2"
@@ -599,6 +760,7 @@
"@
MOV.B\t%1, %0
MOV%X1.B\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_insn "zero_extendqisi2"
@@ -608,6 +770,9 @@
"@
CLR\t%H0
MOV%X1.B\t%1,%L0 { CLR\t%H0"
+ [(set_attr "extra_length" "2")
+ (set_attr "length_multiplier" "1,2")
+ (set_attr "type" "double")]
)
(define_insn "zero_extendhipsi2"
@@ -618,6 +783,7 @@
MOV.W\t%1, %0
MOV%X1\t%1, %0
MOVX.A\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_insn "zero_extendhisi2"
@@ -627,6 +793,8 @@
"@
MOV%X0.W\t#0,%H0
MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
+ [(set_attr "length_multiplier" "1,2")
+ (set_attr "type" "double")]
)
(define_insn "zero_extendhisipsi2"
@@ -636,6 +804,8 @@
"@
AND.W\t#-1,%0
MOV.W\t%1,%0"
+ [(set_attr "length" "4,2")
+ (set_attr "type" "double")]
)
; Nasty - we are sign-extending a 20-bit PSI value in one register into
@@ -671,6 +841,13 @@
else \
return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\";
MOVX.A %1, %0"
+ [(set (attr "length")
+ (cond [(match_test "REGNO (operands[1]) == SP_REGNO")
+ (const_int 18)
+ (eq_attr "alternative" "1")
+ (const_int 6)]
+ (const_int 10)))
+ (set_attr "type" "double")]
)
;; Below are unnamed insn patterns to catch pointer manipulation insns
@@ -687,6 +864,7 @@
(sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))]
"msp430x"
"MOV%X1.B\t%1, %0"
+ [(set_attr "type" "double")]
)
(define_insn ""
@@ -696,6 +874,7 @@
"@
MOV.B\t%1, %0
MOV%X1.B\t%1, %0"
+ [(set_attr "type" "double")]
)
;; The next three insns emit identical assembly code.
@@ -711,6 +890,9 @@
RLAM.W %2, %L0 { CLR %H0
MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0
MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0"
+ [(set_attr "length" "4,*,*")
+ (set_attr "extra_length" "0,4,6")
+ (set_attr "type" "double")]
)
(define_insn ""
@@ -722,6 +904,9 @@
RLAM.W %2, %L0 { CLR %H0
MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0
MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0"
+ [(set_attr "length" "4,*,*")
+ (set_attr "extra_length" "0,4,6")
+ (set_attr "type" "double")]
)
;; Same as above but with a NOP sign_extend round the subreg
@@ -734,6 +919,9 @@
RLAM.W %2, %L0 { CLR %H0
MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0
MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0"
+ [(set_attr "length" "4,*,*")
+ (set_attr "extra_length" "0,4,6")
+ (set_attr "type" "double")]
)
(define_insn ""
@@ -741,6 +929,8 @@
(zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))))]
"msp430x"
"MOV%X1.B %1, %L0 { CLR %H0"
+ [(set_attr "extra_length" "4")
+ (set_attr "type" "double")]
)
(define_insn ""
@@ -752,6 +942,9 @@
RLAM.W %2, %0
MOV%X1.B %1, %0 { RLAM.W %2, %0
MOV%X1.B %1, %0 { RPT %2 { RLAX.A %0"
+ [(set_attr "length" "2,*,*")
+ (set_attr "extra_length" "0,2,4")
+ (set_attr "type" "double")]
)
;; END msp430 pointer manipulation combine insn patterns
@@ -771,13 +964,18 @@
(truncate:HI (match_operand:PSI 1 "register_operand" "r")))]
""
"MOVX\t%1, %0"
+ [(set_attr "extension" "m")
+ (set_attr "type" "double")]
)
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
""
- { return msp430x_extendhisi (operands); }
+ { msp430x_extendhisi (operands, 0); return ""; }
+ [(set (attr "length")
+ (symbol_ref "msp430x_extendhisi (operands, 1)"))
+ (set_attr "type" "double")]
)
(define_insn "extendhipsi2"
@@ -785,6 +983,9 @@
(subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))]
"msp430x"
"RLAM.A #4, %0 { RRAM.A #4, %0"
+ [(set_attr "length_multiplier" "2")
+ (set_attr "extension" "m")
+ (set_attr "type" "double")]
)
;; Look for cases where integer/pointer conversions are suboptimal due
@@ -798,6 +999,9 @@
(const_int 1)))]
"msp430x"
"RLAM.A #4, %0 { RRAM.A #3, %0"
+ [(set_attr "length_multiplier" "2")
+ (set_attr "extension" "m")
+ (set_attr "type" "double")]
)
(define_insn "extend_and_shift2_hipsi2"
@@ -806,6 +1010,9 @@
(const_int 2)))]
"msp430x"
"RLAM.A #4, %0 { RRAM.A #2, %0"
+ [(set_attr "length_multiplier" "2")
+ (set_attr "extension" "m")
+ (set_attr "type" "double")]
)
;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
@@ -827,6 +1034,8 @@
else
return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
"
+ [(set_attr "length" "10")
+ (set_attr "type" "double")]
)
; See the movsipsi2 pattern above for another way that GCC performs this
@@ -836,6 +1045,8 @@
(truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
""
"PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
+ [(set_attr "length" "6")
+ (set_attr "type" "single")]
)
;;------------------------------------------------------------
@@ -886,7 +1097,10 @@
(any_shift:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "const_int_operand" "n")))]
"!msp430x"
- "* return msp430_output_asm_shift_insns (<CODE>, HImode, operands);"
+ "* msp430_output_asm_shift_insns (<CODE>, HImode, operands, false); return \"\";"
+ [(set (attr "length")
+ (symbol_ref "msp430_output_asm_shift_insns (<CODE>, HImode, operands, true)"))
+ (set_attr "type" "single")]
)
;; All 430 and 430X SImode constant shifts
@@ -895,7 +1109,10 @@
(any_shift:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
- "* return msp430_output_asm_shift_insns (<CODE>, SImode, operands);"
+ "* msp430_output_asm_shift_insns (<CODE>, SImode, operands, false); return \"\";"
+ [(set (attr "length")
+ (symbol_ref "msp430_output_asm_shift_insns (<CODE>, SImode, operands, true)"))
+ (set_attr "type" "single")]
)
(define_insn "ashl<mode>3_430x"
@@ -908,6 +1125,8 @@
RPT\t%2 { RLAX%b0\t%0
RPT\t#16 { RLAX%b0\t%0 { RPT\t%W2 { RLAX%b0\t%0
# undefined behavior left shift of %1 by %2"
+ [(set_attr "length" "2,4,8,0")
+ (set_attr "type" "single")]
)
(define_insn "ashr<mode>3_430x"
@@ -920,6 +1139,8 @@
RPT\t%2 { RRAX%b0\t%0
RPT\t#16 { RRAX%b0\t%0 { RPT\t%W2 { RRAX%b0\t%0
# undefined behavior arithmetic right shift of %1 by %2"
+ [(set_attr "length" "2,4,8,0")
+ (set_attr "type" "single")]
)
(define_insn "lshr<mode>3_430x"
@@ -932,6 +1153,8 @@
RPT\t%2 { RRUX%b0\t%0
RPT\t#16 { RRUX%b0\t%0 { RPT\t%W2 { RRUX%b0\t%0
# undefined behavior logical right shift of %1 by %2"
+ [(set_attr "length" "2,4,8,0")
+ (set_attr "type" "single")]
)
;;------------------------------------------------------------
@@ -941,39 +1164,43 @@
[(const_int 0)]
""
"msp430_expand_prologue (); DONE;"
- )
+)
(define_expand "epilogue"
[(const_int 0)]
""
"msp430_expand_epilogue (0); DONE;"
- )
+)
(define_insn "epilogue_helper"
[(set (pc)
- (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER))
+ (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER))
(return)]
- ""
+ "!msp430x"
"BR%Q0\t#__mspabi_func_epilog_%J0"
- )
+ [(set_attr "length" "2")]
+)
(define_insn "prologue_start_marker"
[(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
""
"; start of prologue"
- )
+ [(set_attr "length" "0")]
+)
(define_insn "prologue_end_marker"
[(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
""
"; end of prologue"
- )
+ [(set_attr "length" "0")]
+)
(define_insn "epilogue_start_marker"
[(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
""
"; start of epilogue"
- )
+ [(set_attr "length" "0")]
+)
;; This makes the linker add a call to exit() after the call to main()
;; in crt0
@@ -981,7 +1208,8 @@
[(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
""
".refsym\t__crt0_call_exit"
- )
+ [(set_attr "length" "0")]
+)
;;------------------------------------------------------------
;; Jumps
@@ -998,6 +1226,8 @@
(match_operand 1 ""))]
""
"CALL%Q0\t%0"
+ [(set_attr "extension" "none")
+ (set_attr "type" "single")]
)
(define_expand "call_value"
@@ -1014,12 +1244,15 @@
(match_operand 2 "")))]
""
"CALL%Q0\t%1"
+ [(set_attr "extension" "none")
+ (set_attr "type" "single")]
)
(define_insn "msp430_return"
[(return)]
""
{ return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
+ [(set_attr "length" "2")]
)
;; This pattern is NOT, as expected, a return pattern. It's called
@@ -1045,13 +1278,15 @@
"reload_completed"
[(const_int 0)]
"msp430_expand_epilogue (1); DONE;"
- )
+ [(set_attr "length" "40")]
+)
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
"BR%Q0\t#%l0"
+ [(set_attr "length" "4")]
)
;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
@@ -1061,6 +1296,10 @@
(match_operand 0 "nonimmediate_operand" "rYl"))]
""
"BR%Q0\t%0"
+ [(set (attr "length")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_int 2)
+ (const_int 4)))]
)
;;------------------------------------------------------------
@@ -1077,14 +1316,14 @@
)]
""
"msp430_fixup_compare_operands (<MODE>mode, operands);"
- )
+)
(define_insn "cbranchpsi4_real"
[(set (pc) (if_then_else
(match_operator 0 "msp430_cmp_operator"
[(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm")
(match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")])
- (label_ref (match_operand 3 "" ""))
+ (label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
@@ -1093,7 +1332,9 @@
CMP%Q0\t%2, %1 { J%0\t%l3
CMPX.A\t%2, %1 { J%0\t%l3
CMPX.A\t%2, %1 { J%0\t%l3"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "cmp")]
+)
(define_insn "cbranchqi4_real"
[(set (pc) (if_then_else
@@ -1108,7 +1349,9 @@
"@
CMP.B\t%2, %1 { J%0\t%l3
CMPX.B\t%2, %1 { J%0\t%l3"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "cmp")]
+)
(define_insn "cbranchhi4_real"
[(set (pc) (if_then_else
@@ -1123,6 +1366,8 @@
"@
CMP.W\t%2, %1 { J%0\t%l3
CMPX.W\t%2, %1 { J%0\t%l3"
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "cmp")]
)
(define_insn "cbranchpsi4_reversed"
@@ -1139,7 +1384,9 @@
CMP%Q0\t%1, %2 { J%R0\t%l3
CMPX.A\t%1, %2 { J%R0\t%l3
CMPX.A\t%1, %2 { J%R0\t%l3"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "cmp")]
+)
(define_insn "cbranchqi4_reversed"
[(set (pc) (if_then_else
@@ -1154,7 +1401,9 @@
"@
CMP.B\t%1, %2 { J%R0\t%l3
CMPX.B\t%1, %2 { J%R0\t%l3"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "cmp")]
+)
(define_insn "cbranchhi4_reversed"
[(set (pc) (if_then_else
@@ -1169,14 +1418,16 @@
"@
CMP.W\t%1, %2 { J%R0\t%l3
CMPX.W\t%1, %2 { J%R0\t%l3"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "cmp")]
+)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
(ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
(match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
- (label_ref (match_operand 2 "" ""))
+ (label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
@@ -1184,14 +1435,16 @@
"@
BIT%x0%b0\t%1, %0 { JNE\t%l2
BITX%b0\t%1, %0 { JNE\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
(eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
(match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
- (label_ref (match_operand 2 "" ""))
+ (label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
@@ -1199,14 +1452,16 @@
"@
BIT%x0%b0\t%1, %0 { JEQ\t%l2
BITX%b0\t%1, %0 { JEQ\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
(eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
(match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
- (pc)
+ (pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
@@ -1214,14 +1469,16 @@
"@
BIT%x0%b0\t%1, %0 { JNE\t%l2
BITX%b0\t%1, %0 { JNE\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
(ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
(match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
- (pc)
+ (pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
@@ -1229,7 +1486,9 @@
"@
BIT%x0%b0\t%1, %0 { JEQ\t%l2
BITX%b0\t%1, %0 { JEQ\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
;;------------------------------------------------------------
;; zero-extract versions of the above
@@ -1240,7 +1499,7 @@
(const_int 1)
(match_operand 1 "const_0_to_15_operand" "i,i"))
(const_int 0))
- (label_ref (match_operand 2 "" ""))
+ (label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
@@ -1248,7 +1507,9 @@
"@
BIT%x0%b0\t%p1, %0 { JNE\t%l2
BIT%X0%b0\t%p1, %0 { JNE\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
@@ -1256,13 +1517,15 @@
(const_int 1)
(match_operand 1 "const_0_to_15_operand" "i"))
(const_int 0))
- (label_ref (match_operand 2 "" ""))
+ (label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
""
"BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
@@ -1270,13 +1533,15 @@
(const_int 1)
(match_operand 1 "const_0_to_15_operand" "i"))
(const_int 0))
- (pc)
+ (pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
""
"BIT%X0%b0\t%p1, %0 { JNE\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
@@ -1284,13 +1549,15 @@
(const_int 1)
(match_operand 1 "const_0_to_15_operand" "i"))
(const_int 0))
- (pc)
+ (pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
""
"BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
- )
+ [(set_attr "extra_length" "2")
+ (set_attr "type" "double")]
+)
;;------------------------------------------------------------
;; Misc
@@ -1299,31 +1566,36 @@
[(const_int 0)]
"1"
"NOP"
+ [(set_attr "length" "2")]
)
(define_insn "disable_interrupts"
[(unspec_volatile [(const_int 0)] UNS_DINT)]
""
"DINT \; NOP"
- )
+ [(set_attr "length" "2")]
+)
(define_insn "enable_interrupts"
[(unspec_volatile [(const_int 0)] UNS_EINT)]
""
"EINT"
- )
+ [(set_attr "length" "2")]
+)
(define_insn "push_intr_state"
[(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
""
"PUSH\tSR"
- )
+ [(set_attr "length" "2")]
+)
(define_insn "pop_intr_state"
[(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
""
"POP\tSR"
- )
+ [(set_attr "length" "2")]
+)
;; Clear bits in the copy of the status register that is currently
;; saved on the stack at the top of the interrupt handler.
@@ -1331,7 +1603,9 @@
[(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
""
"BIC.W\t%0, %O0(SP)"
- )
+ [(set_attr "type" "single")
+ (set_attr "extra_length" "2")]
+)
;; Set bits in the copy of the status register that is currently
;; saved on the stack at the top of the interrupt handler.
@@ -1339,30 +1613,33 @@
[(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
""
"BIS.W\t%0, %O0(SP)"
- )
+ [(set_attr "type" "single")
+ (set_attr "extra_length" "2")]
+)
;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
;; very late on in the compilation and not splitting it into separate
;; instructions, so we provide a pattern to support it here.
(define_insn "andneghi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (and:HI (neg:HI (match_operand:HI 1 "general_operand" "rm"))
- (match_operand 2 "immediate_operand" "n")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (and:HI (neg:HI (match_operand:HI 1 "general_operand" "0,rm"))
+ (match_operand 2 "immediate_operand" "n,n")))]
""
- "*
- if (REGNO (operands[0]) != REGNO (operands[1]))
- return \"MOV%X1.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
- else
- return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
- "
- )
+ "@
+ INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0
+ MOV%X1.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0"
+ [(set_attr "length" "12,14")
+ (set_attr "type" "double")]
+)
+
(define_insn "delay_cycles_start"
[(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
UNS_DELAY_START)]
""
"; Begin %J0 cycle delay"
- )
+ [(set_attr "length" "0")]
+)
(define_insn "delay_cycles_end"
[(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
@@ -1387,7 +1664,8 @@
JNE 1b
POP r14
POP r13"
- )
+ [(set_attr "length" "32")]
+)
(define_insn "delay_cycles_32x"
[(unspec_volatile [(match_operand 0 "immediate_operand" "i")
@@ -1403,7 +1681,8 @@
TST.W r13
JNE 1b
POPM.A #2,r14"
- )
+ [(set_attr "length" "28")]
+)
(define_insn "delay_cycles_16"
[(unspec_volatile [(match_operand 0 "immediate_operand" "i")
@@ -1415,7 +1694,8 @@
1: SUB.W #1, r13
JNE 1b
POP r13"
- )
+ [(set_attr "length" "14")]
+)
(define_insn "delay_cycles_16x"
[(unspec_volatile [(match_operand 0 "immediate_operand" "i")
@@ -1427,19 +1707,44 @@
1: SUB.W #1, r13
JNE 1b
POPM.A #1,r13"
- )
+ [(set_attr "length" "14")]
+)
(define_insn "delay_cycles_2"
[(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
""
"JMP .+2"
- )
+ [(set_attr "length" "2")]
+)
(define_insn "delay_cycles_1"
[(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
""
"NOP"
- )
+ [(set_attr "length" "2")]
+)
+
+(define_expand "mulhi3"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mult:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "register_operand" "r")))]
+ "msp430_has_hwmult ()"
+ {
+ msp430_expand_helper (operands, "__mspabi_mpyi", false);
+ DONE;
+ }
+)
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "msp430_has_hwmult ()"
+ {
+ msp430_expand_helper (operands, "__mspabi_mpyl", false);
+ DONE;
+ }
+)
; libgcc helper functions for widening multiplication aren't currently
; generated by gcc, so we can't catch them later and map them to the mspabi
@@ -1450,9 +1755,7 @@
; If we don't have hardware multiply support, it will generally be slower and
; result in larger code to call the mspabi library function to perform the
; widening multiplication than just leaving GCC to widen the arguments itself.
-;
-; We don't use library functions for SImode->DImode widening since its always
-; larger and slower than letting GCC widen the arguments inline.
+
(define_expand "mulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
@@ -1483,6 +1786,37 @@
}
)
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "msp430_has_hwmult ()"
+ {
+ /* Leave the other case for the inline insn. */
+ if (!(optimize > 2 && msp430_has_hwmult ()))
+ {
+ msp430_expand_helper (operands, "__mspabi_mpysll", false);
+ DONE;
+ }
+ }
+)
+
+(define_expand "umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "msp430_has_hwmult ()"
+ {
+ /* Leave the other case for the inline insn. */
+ if (!(optimize > 2 && msp430_has_hwmult ()))
+ {
+ msp430_expand_helper (operands, "__mspabi_mpyull", false);
+ DONE;
+ }
+ }
+)
+
+
(define_insn "*mulhisi3_inline"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
@@ -1494,6 +1828,7 @@
else
return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
"
+ [(set_attr "length" "24")]
)
(define_insn "*umulhisi3_inline"
@@ -1507,9 +1842,10 @@
else
return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
"
+ [(set_attr "length" "24")]
)
-(define_insn "mulsidi3"
+(define_insn "*mulsidi3_inline"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
@@ -1520,9 +1856,10 @@
else
return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
"
+ [(set_attr "length" "40")]
)
-(define_insn "umulsidi3"
+(define_insn "*umulsidi3_inline"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
@@ -1533,4 +1870,5 @@
else
return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
"
+ [(set_attr "length" "40")]
)
diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt
index 692e7dc..56dc996 100644
--- a/gcc/config/msp430/msp430.opt
+++ b/gcc/config/msp430/msp430.opt
@@ -3,7 +3,7 @@ Target
Use simulator runtime.
mtiny-printf
-Target Report Mask(TINY_PRINTF)
+Target Mask(TINY_PRINTF)
Use a lightweight configuration of printf and puts to reduce code size. For single-threaded applications, not requiring reentrant I/O only. Requires Newlib Nano IO.
masm-hex
@@ -11,19 +11,19 @@ Target Mask(ASM_HEX)
Force assembly output to always use hex constants.
mmcu=
-Target Report ToLower Joined RejectNegative Var(target_mcu)
+Target ToLower Joined RejectNegative Var(target_mcu)
Specify the MCU to build for.
mwarn-mcu
-Target Report Var(msp430_warn_mcu) Init(1)
+Target Var(msp430_warn_mcu) Init(1)
Warn if an MCU name is unrecognized or conflicts with other options (default: on).
mwarn-devices-csv
-Target Report Var(msp430_warn_devices_csv) Init(1)
+Target Var(msp430_warn_devices_csv) Init(1)
Warn if devices.csv is not found or there are problem parsing it (default: on).
mcpu=
-Target Report Joined RejectNegative Var(target_cpu) ToLower Enum(msp430_cpu_types) Init(MSP430_CPU_MSP430X_DEFAULT)
+Target Joined RejectNegative Var(target_cpu) ToLower Enum(msp430_cpu_types) Init(MSP430_CPU_MSP430X_DEFAULT)
Specify the ISA to build for: msp430, msp430x, msp430xv2.
Enum
@@ -48,29 +48,29 @@ EnumValue
Enum(msp430_cpu_types) String(430xv2) Value(MSP430_CPU_MSP430XV2)
mlarge
-Target Report Mask(LARGE) RejectNegative
+Target Mask(LARGE) RejectNegative
Select large model - 20-bit addresses/pointers.
msmall
-Target Report InverseMask(LARGE) RejectNegative
+Target InverseMask(LARGE) RejectNegative
Select small model - 16-bit addresses/pointers (default).
mrelax
-Target Report
+Target
Optimize opcode sizes at link time.
mOs
Target Undocumented Mask(OPT_SPACE)
minrt
-Target Report Mask(MINRT) RejectNegative
+Target Mask(MINRT) RejectNegative
Use a minimum runtime (no static initializers or ctors) for memory-constrained devices.
HeaderInclude
config/msp430/msp430-opts.h
mhwmult=
-Target Joined RejectNegative Report ToLower Var(msp430_hwmult_type) Enum(msp430_hwmult_types) Init(MSP430_HWMULT_AUTO)
+Target Joined RejectNegative ToLower Var(msp430_hwmult_type) Enum(msp430_hwmult_types) Init(MSP430_HWMULT_AUTO)
Specify the type of hardware multiply to support.
Enum
@@ -92,15 +92,15 @@ EnumValue
Enum(msp430_hwmult_types) String(f5series) Value(MSP430_HWMULT_F5SERIES)
mcode-region=
-Target Joined RejectNegative Report ToLower Var(msp430_code_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
+Target Joined RejectNegative ToLower Var(msp430_code_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
Specify whether functions should be placed into the lower or upper memory regions, or if they should be shuffled between the regions (either) for best fit (default: lower).
mdata-region=
-Target Joined RejectNegative Report ToLower Var(msp430_data_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
+Target Joined RejectNegative ToLower Var(msp430_data_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
Specify whether variables should be placed into the lower or upper memory regions, or if they should be shuffled between the regions (either) for best fit (default: lower).
muse-lower-region-prefix
-Target Mask(USE_LOWER_REGION_PREFIX) Report
+Target Mask(USE_LOWER_REGION_PREFIX)
Add the .lower prefix to section names when compiling with -m{code,data}-region=lower (disabled by default).
Enum
@@ -119,20 +119,20 @@ EnumValue
Enum(msp430_regions) String(upper) Value(MSP430_REGION_UPPER)
msilicon-errata=
-Target Joined RejectNegative Report ToLower
+Target Joined RejectNegative ToLower
Passes on a request to the assembler to enable fixes for various silicon errata.
msilicon-errata-warn=
-Target Joined RejectNegative Report ToLower
+Target Joined RejectNegative ToLower
Passes on a request to the assembler to warn about various silicon errata.
mdevices-csv-loc=
-Target Joined Var(msp430_devices_csv_loc) RejectNegative Report
+Target Joined Var(msp430_devices_csv_loc) RejectNegative
The path to devices.csv. The GCC driver can normally locate devices.csv itself
and pass this option to the compiler, so the user shouldn't need to pass this.
mmax-inline-shift=
-Target RejectNegative Joined UInteger IntegerRange(0,65) Var(msp430_max_inline_shift) Init(65) Report
+Target RejectNegative Joined UInteger IntegerRange(0,65) Var(msp430_max_inline_shift) Init(65)
For shift operations by a constant amount, which require an individual instruction to shift by one
position, set the maximum number of inline shift instructions (maximum value 64) to emit instead of using the corresponding __mspabi helper function.
The default value is 4.
diff --git a/gcc/config/msp430/predicates.md b/gcc/config/msp430/predicates.md
index 4bfa0c0..eb1f61d 100644
--- a/gcc/config/msp430/predicates.md
+++ b/gcc/config/msp430/predicates.md
@@ -131,3 +131,16 @@
(define_predicate "msp430_symbol_operand"
(match_code "symbol_ref")
)
+
+; Used in length attribute tests - if a source operand is a reg,
+; (mem (post_inc)), or (mem (reg)) then it is cheap compared to other operand
+; types.
+(define_predicate "msp430_cheap_operand"
+ (ior (match_code "reg")
+ (and (match_code "mem")
+ (ior (match_code "reg" "0")
+ (match_code "post_inc" "0")))))
+
+; Used for insn attributes only. For insn patterns themselves, use constraints.
+(define_predicate "msp430_high_memory_operand"
+ (match_test "msp430x_insn_required (op)"))
diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt
index 053e810..dcd05c9 100644
--- a/gcc/config/nds32/nds32.opt
+++ b/gcc/config/nds32/nds32.opt
@@ -67,11 +67,11 @@ Specify use soft floating point ABI which mean alias to -mabi=2fp+.
; ---------------------------------------------------------------
mreduced-regs
-Target Report RejectNegative Negative(mfull-regs) Mask(REDUCED_REGS)
+Target RejectNegative Negative(mfull-regs) Mask(REDUCED_REGS)
Use reduced-set registers for register allocation.
mfull-regs
-Target Report RejectNegative Negative(mreduced-regs) InverseMask(REDUCED_REGS)
+Target RejectNegative Negative(mreduced-regs) InverseMask(REDUCED_REGS)
Use full-set registers for register allocation.
; ---------------------------------------------------------------
@@ -115,43 +115,43 @@ EnumValue
Enum(nds32_ict_model_type) String(large) Value(ICT_MODEL_LARGE)
mcmov
-Target Report Mask(CMOV)
+Target Mask(CMOV)
Generate conditional move instructions.
mhw-abs
-Target Report Mask(HW_ABS)
+Target Mask(HW_ABS)
Generate hardware abs instructions.
mext-perf
-Target Report Mask(EXT_PERF)
+Target Mask(EXT_PERF)
Generate performance extension instructions.
mext-perf2
-Target Report Mask(EXT_PERF2)
+Target Mask(EXT_PERF2)
Generate performance extension version 2 instructions.
mext-string
-Target Report Mask(EXT_STRING)
+Target Mask(EXT_STRING)
Generate string extension instructions.
mext-dsp
-Target Report Mask(EXT_DSP)
+Target Mask(EXT_DSP)
Generate DSP extension instructions.
mv3push
-Target Report Mask(V3PUSH)
+Target Mask(V3PUSH)
Generate v3 push25/pop25 instructions.
m16-bit
-Target Report Mask(16_BIT)
+Target Mask(16_BIT)
Generate 16-bit instructions.
mrelax-hint
-Target Report Mask(RELAX_HINT)
+Target Mask(RELAX_HINT)
Insert relax hint for linker to do relaxation.
mvh
-Target Report Mask(VH) Condition(!TARGET_LINUX_ABI)
+Target Mask(VH) Condition(!TARGET_LINUX_ABI)
Enable Virtual Hosting support.
misr-vector-size=
@@ -421,27 +421,27 @@ EnumValue
Enum(nds32_register_ports) String(2r1w) Value(REG_PORT_2R1W)
mctor-dtor
-Target Report
+Target
Enable constructor/destructor feature.
mrelax
-Target Report
+Target
Guide linker to relax instructions.
mext-fpu-fma
-Target Report Mask(EXT_FPU_FMA)
+Target Mask(EXT_FPU_FMA)
Generate floating-point multiply-accumulation instructions.
mext-fpu-sp
-Target Report Mask(FPU_SINGLE)
+Target Mask(FPU_SINGLE)
Generate single-precision floating-point instructions.
mext-fpu-dp
-Target Report Mask(FPU_DOUBLE)
+Target Mask(FPU_DOUBLE)
Generate double-precision floating-point instructions.
mforce-no-ext-dsp
-Target Undocumented Report Mask(FORCE_NO_EXT_DSP)
+Target Undocumented Mask(FORCE_NO_EXT_DSP)
Force disable hardware loop, even use -mext-dsp.
msched-prolog-epilog
@@ -457,9 +457,9 @@ Target Var(flag_always_save_lp) Init(0)
Always save $lp in the stack.
munaligned-access
-Target Report Var(flag_unaligned_access) Init(0)
+Target Var(flag_unaligned_access) Init(0)
Enable unaligned word and halfword accesses to packed data.
minline-asm-r15
-Target Report Var(flag_inline_asm_r15) Init(0)
+Target Var(flag_inline_asm_r15) Init(0)
Allow use r15 for inline ASM.
diff --git a/gcc/config/nios2/elf.opt b/gcc/config/nios2/elf.opt
index 1a0a13e..e8626e0 100644
--- a/gcc/config/nios2/elf.opt
+++ b/gcc/config/nios2/elf.opt
@@ -22,7 +22,7 @@
; toolchains.
msmallc
-Target Report RejectNegative
+Target RejectNegative
Link with a limited version of the C library.
msys-lib=
@@ -34,5 +34,5 @@ Target RejectNegative Joined Var(nios2_sys_crt0_string)
Name of the startfile.
mhal
-Target Report RejectNegative
+Target RejectNegative
Link with HAL BSP.
diff --git a/gcc/config/nios2/nios2.opt b/gcc/config/nios2/nios2.opt
index 4c6a62b..39d278a 100644
--- a/gcc/config/nios2/nios2.opt
+++ b/gcc/config/nios2/nios2.opt
@@ -31,31 +31,31 @@ TargetSave
int saved_custom_code_index[256]
mhw-div
-Target Report Mask(HAS_DIV)
+Target Mask(HAS_DIV)
Enable DIV, DIVU.
mhw-mul
-Target Report Mask(HAS_MUL)
+Target Mask(HAS_MUL)
Enable MUL instructions.
mhw-mulx
-Target Report Mask(HAS_MULX)
+Target Mask(HAS_MULX)
Enable MULX instructions, assume fast shifter.
mfast-sw-div
-Target Report Mask(FAST_SW_DIV)
+Target Mask(FAST_SW_DIV)
Use table based fast divide (default at -O3).
mbypass-cache
-Target Report Mask(BYPASS_CACHE)
+Target Mask(BYPASS_CACHE)
All memory accesses use I/O load/store instructions.
mno-cache-volatile
-Target Report RejectNegative Mask(BYPASS_CACHE_VOLATILE)
+Target RejectNegative Mask(BYPASS_CACHE_VOLATILE)
Volatile memory accesses use I/O load/store instructions.
mcache-volatile
-Target Report RejectNegative Undocumented InverseMask(BYPASS_CACHE_VOLATILE)
+Target RejectNegative Undocumented InverseMask(BYPASS_CACHE_VOLATILE)
Volatile memory accesses do not use I/O load/store instructions.
mgpopt=
@@ -82,19 +82,19 @@ EnumValue
Enum(nios2_gpopt_type) String(all) Value(gpopt_all)
mgpopt
-Target Report RejectNegative Var(nios2_gpopt_option, gpopt_local)
+Target RejectNegative Var(nios2_gpopt_option, gpopt_local)
Equivalent to -mgpopt=local.
mno-gpopt
-Target Report RejectNegative Var(nios2_gpopt_option, gpopt_none)
+Target RejectNegative Var(nios2_gpopt_option, gpopt_none)
Equivalent to -mgpopt=none.
meb
-Target Report RejectNegative Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Use big-endian byte order.
mel
-Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN)
Use little-endian byte order.
mcustom-fpu-cfg=
@@ -102,467 +102,467 @@ Target RejectNegative Joined Var(nios2_custom_fpu_cfg_string)
Floating point custom instruction configuration name.
mno-custom-ftruncds
-Target Report RejectNegative Var(nios2_custom_ftruncds, -1)
+Target RejectNegative Var(nios2_custom_ftruncds, -1)
Do not use the ftruncds custom instruction.
mcustom-ftruncds=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_ftruncds) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_ftruncds) Init(-1)
Integer id (N) of ftruncds custom instruction.
mno-custom-fextsd
-Target Report RejectNegative Var(nios2_custom_fextsd, -1)
+Target RejectNegative Var(nios2_custom_fextsd, -1)
Do not use the fextsd custom instruction.
mcustom-fextsd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fextsd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fextsd) Init(-1)
Integer id (N) of fextsd custom instruction.
mno-custom-fixdu
-Target Report RejectNegative Var(nios2_custom_fixdu, -1)
+Target RejectNegative Var(nios2_custom_fixdu, -1)
Do not use the fixdu custom instruction.
mcustom-fixdu=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdu) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fixdu) Init(-1)
Integer id (N) of fixdu custom instruction.
mno-custom-fixdi
-Target Report RejectNegative Var(nios2_custom_fixdi, -1)
+Target RejectNegative Var(nios2_custom_fixdi, -1)
Do not use the fixdi custom instruction.
mcustom-fixdi=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdi) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fixdi) Init(-1)
Integer id (N) of fixdi custom instruction.
mno-custom-fixsu
-Target Report RejectNegative Var(nios2_custom_fixsu, -1)
+Target RejectNegative Var(nios2_custom_fixsu, -1)
Do not use the fixsu custom instruction.
mcustom-fixsu=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsu) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fixsu) Init(-1)
Integer id (N) of fixsu custom instruction.
mno-custom-fixsi
-Target Report RejectNegative Var(nios2_custom_fixsi, -1)
+Target RejectNegative Var(nios2_custom_fixsi, -1)
Do not use the fixsi custom instruction.
mcustom-fixsi=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsi) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fixsi) Init(-1)
Integer id (N) of fixsi custom instruction.
mno-custom-floatud
-Target Report RejectNegative Var(nios2_custom_floatud, -1)
+Target RejectNegative Var(nios2_custom_floatud, -1)
Do not use the floatud custom instruction.
mcustom-floatud=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_floatud) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_floatud) Init(-1)
Integer id (N) of floatud custom instruction.
mno-custom-floatid
-Target Report RejectNegative Var(nios2_custom_floatid, -1)
+Target RejectNegative Var(nios2_custom_floatid, -1)
Do not use the floatid custom instruction.
mcustom-floatid=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_floatid) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_floatid) Init(-1)
Integer id (N) of floatid custom instruction.
mno-custom-floatus
-Target Report RejectNegative Var(nios2_custom_floatus, -1)
+Target RejectNegative Var(nios2_custom_floatus, -1)
Do not use the floatus custom instruction.
mcustom-floatus=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_floatus) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_floatus) Init(-1)
Integer id (N) of floatus custom instruction.
mno-custom-floatis
-Target Report RejectNegative Var(nios2_custom_floatis, -1)
+Target RejectNegative Var(nios2_custom_floatis, -1)
Do not use the floatis custom instruction.
mcustom-floatis=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_floatis) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_floatis) Init(-1)
Integer id (N) of floatis custom instruction.
mno-custom-fcmpned
-Target Report RejectNegative Var(nios2_custom_fcmpned, -1)
+Target RejectNegative Var(nios2_custom_fcmpned, -1)
Do not use the fcmpned custom instruction.
mcustom-fcmpned=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpned) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpned) Init(-1)
Integer id (N) of fcmpned custom instruction.
mno-custom-fcmpeqd
-Target Report RejectNegative Var(nios2_custom_fcmpeqd, -1)
+Target RejectNegative Var(nios2_custom_fcmpeqd, -1)
Do not use the fcmpeqd custom instruction.
mcustom-fcmpeqd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpeqd) Init(-1)
Integer id (N) of fcmpeqd custom instruction.
mno-custom-fcmpged
-Target Report RejectNegative Var(nios2_custom_fcmpged, -1)
+Target RejectNegative Var(nios2_custom_fcmpged, -1)
Do not use the fcmpged custom instruction.
mcustom-fcmpged=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpged) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpged) Init(-1)
Integer id (N) of fcmpged custom instruction.
mno-custom-fcmpgtd
-Target Report RejectNegative Var(nios2_custom_fcmpgtd, -1)
+Target RejectNegative Var(nios2_custom_fcmpgtd, -1)
Do not use the fcmpgtd custom instruction.
mcustom-fcmpgtd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgtd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpgtd) Init(-1)
Integer id (N) of fcmpgtd custom instruction.
mno-custom-fcmpled
-Target Report RejectNegative Var(nios2_custom_fcmpled, -1)
+Target RejectNegative Var(nios2_custom_fcmpled, -1)
Do not use the fcmpled custom instruction.
mcustom-fcmpled=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpled) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpled) Init(-1)
Integer id (N) of fcmpled custom instruction.
mno-custom-fcmpltd
-Target Report RejectNegative Var(nios2_custom_fcmpltd, -1)
+Target RejectNegative Var(nios2_custom_fcmpltd, -1)
Do not use the fcmpltd custom instruction.
mcustom-fcmpltd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpltd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpltd) Init(-1)
Integer id (N) of fcmpltd custom instruction.
mno-custom-flogd
-Target Report RejectNegative Var(nios2_custom_flogd, -1)
+Target RejectNegative Var(nios2_custom_flogd, -1)
Do not use the flogd custom instruction.
mcustom-flogd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_flogd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_flogd) Init(-1)
Integer id (N) of flogd custom instruction.
mno-custom-fexpd
-Target Report RejectNegative Var(nios2_custom_fexpd, -1)
+Target RejectNegative Var(nios2_custom_fexpd, -1)
Do not use the fexpd custom instruction.
mcustom-fexpd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fexpd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fexpd) Init(-1)
Integer id (N) of fexpd custom instruction.
mno-custom-fatand
-Target Report RejectNegative Var(nios2_custom_fatand, -1)
+Target RejectNegative Var(nios2_custom_fatand, -1)
Do not use the fatand custom instruction.
mcustom-fatand=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fatand) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fatand) Init(-1)
Integer id (N) of fatand custom instruction.
mno-custom-ftand
-Target Report RejectNegative Var(nios2_custom_ftand, -1)
+Target RejectNegative Var(nios2_custom_ftand, -1)
Do not use the ftand custom instruction.
mcustom-ftand=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_ftand) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_ftand) Init(-1)
Integer id (N) of ftand custom instruction.
mno-custom-fsind
-Target Report RejectNegative Var(nios2_custom_fsind, -1)
+Target RejectNegative Var(nios2_custom_fsind, -1)
Do not use the fsind custom instruction.
mcustom-fsind=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fsind) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fsind) Init(-1)
Integer id (N) of fsind custom instruction.
mno-custom-fcosd
-Target Report RejectNegative Var(nios2_custom_fcosd, -1)
+Target RejectNegative Var(nios2_custom_fcosd, -1)
Do not use the fcosd custom instruction.
mcustom-fcosd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcosd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcosd) Init(-1)
Integer id (N) of fcosd custom instruction.
mno-custom-fsqrtd
-Target Report RejectNegative Var(nios2_custom_fsqrtd, -1)
+Target RejectNegative Var(nios2_custom_fsqrtd, -1)
Do not use the fsqrtd custom instruction.
mcustom-fsqrtd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrtd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fsqrtd) Init(-1)
Integer id (N) of fsqrtd custom instruction.
mno-custom-fabsd
-Target Report RejectNegative Var(nios2_custom_fabsd, -1)
+Target RejectNegative Var(nios2_custom_fabsd, -1)
Do not use the fabsd custom instruction.
mcustom-fabsd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fabsd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fabsd) Init(-1)
Integer id (N) of fabsd custom instruction.
mno-custom-fnegd
-Target Report RejectNegative Var(nios2_custom_fnegd, -1)
+Target RejectNegative Var(nios2_custom_fnegd, -1)
Do not use the fnegd custom instruction.
mcustom-fnegd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fnegd) Init(-1)
Integer id (N) of fnegd custom instruction.
mno-custom-fmaxd
-Target Report RejectNegative Var(nios2_custom_fmaxd, -1)
+Target RejectNegative Var(nios2_custom_fmaxd, -1)
Do not use the fmaxd custom instruction.
mcustom-fmaxd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fmaxd) Init(-1)
Integer id (N) of fmaxd custom instruction.
mno-custom-fmind
-Target Report RejectNegative Var(nios2_custom_fmind, -1)
+Target RejectNegative Var(nios2_custom_fmind, -1)
Do not use the fmind custom instruction.
mcustom-fmind=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fmind) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fmind) Init(-1)
Integer id (N) of fmind custom instruction.
mno-custom-fdivd
-Target Report RejectNegative Var(nios2_custom_fdivd, -1)
+Target RejectNegative Var(nios2_custom_fdivd, -1)
Do not use the fdivd custom instruction.
mcustom-fdivd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fdivd) Init(-1)
Integer id (N) of fdivd custom instruction.
mno-custom-fmuld
-Target Report RejectNegative Var(nios2_custom_fmuld, -1)
+Target RejectNegative Var(nios2_custom_fmuld, -1)
Do not use the fmuld custom instruction.
mcustom-fmuld=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuld) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fmuld) Init(-1)
Integer id (N) of fmuld custom instruction.
mno-custom-fsubd
-Target Report RejectNegative Var(nios2_custom_fsubd, -1)
+Target RejectNegative Var(nios2_custom_fsubd, -1)
Do not use the fsubd custom instruction.
mcustom-fsubd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fsubd) Init(-1)
Integer id (N) of fsubd custom instruction.
mno-custom-faddd
-Target Report RejectNegative Var(nios2_custom_faddd, -1)
+Target RejectNegative Var(nios2_custom_faddd, -1)
Do not use the faddd custom instruction.
mcustom-faddd=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_faddd) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_faddd) Init(-1)
Integer id (N) of faddd custom instruction.
mno-custom-fcmpnes
-Target Report RejectNegative Var(nios2_custom_fcmpnes, -1)
+Target RejectNegative Var(nios2_custom_fcmpnes, -1)
Do not use the fcmpnes custom instruction.
mcustom-fcmpnes=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpnes) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpnes) Init(-1)
Integer id (N) of fcmpnes custom instruction.
mno-custom-fcmpeqs
-Target Report RejectNegative Var(nios2_custom_fcmpeqs, -1)
+Target RejectNegative Var(nios2_custom_fcmpeqs, -1)
Do not use the fcmpeqs custom instruction.
mcustom-fcmpeqs=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqs) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpeqs) Init(-1)
Integer id (N) of fcmpeqs custom instruction.
mno-custom-fcmpges
-Target Report RejectNegative Var(nios2_custom_fcmpges, -1)
+Target RejectNegative Var(nios2_custom_fcmpges, -1)
Do not use the fcmpges custom instruction.
mcustom-fcmpges=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpges) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpges) Init(-1)
Integer id (N) of fcmpges custom instruction.
mno-custom-fcmpgts
-Target Report RejectNegative Var(nios2_custom_fcmpgts, -1)
+Target RejectNegative Var(nios2_custom_fcmpgts, -1)
Do not use the fcmpgts custom instruction.
mcustom-fcmpgts=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgts) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmpgts) Init(-1)
Integer id (N) of fcmpgts custom instruction.
mno-custom-fcmples
-Target Report RejectNegative Var(nios2_custom_fcmples, -1)
+Target RejectNegative Var(nios2_custom_fcmples, -1)
Do not use the fcmples custom instruction.
mcustom-fcmples=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmples) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmples) Init(-1)
Integer id (N) of fcmples custom instruction.
mno-custom-fcmplts
-Target Report RejectNegative Var(nios2_custom_fcmplts, -1)
+Target RejectNegative Var(nios2_custom_fcmplts, -1)
Do not use the fcmplts custom instruction.
mcustom-fcmplts=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmplts) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcmplts) Init(-1)
Integer id (N) of fcmplts custom instruction.
mno-custom-flogs
-Target Report RejectNegative Var(nios2_custom_flogs, -1)
+Target RejectNegative Var(nios2_custom_flogs, -1)
Do not use the flogs custom instruction.
mcustom-flogs=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_flogs) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_flogs) Init(-1)
Integer id (N) of flogs custom instruction.
mno-custom-fexps
-Target Report RejectNegative Var(nios2_custom_fexps, -1)
+Target RejectNegative Var(nios2_custom_fexps, -1)
Do not use the fexps custom instruction.
mcustom-fexps=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fexps) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fexps) Init(-1)
Integer id (N) of fexps custom instruction.
mno-custom-fatans
-Target Report RejectNegative Var(nios2_custom_fatans, -1)
+Target RejectNegative Var(nios2_custom_fatans, -1)
Do not use the fatans custom instruction.
mcustom-fatans=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fatans) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fatans) Init(-1)
Integer id (N) of fatans custom instruction.
mno-custom-ftans
-Target Report RejectNegative Var(nios2_custom_ftans, -1)
+Target RejectNegative Var(nios2_custom_ftans, -1)
Do not use the ftans custom instruction.
mcustom-ftans=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_ftans) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_ftans) Init(-1)
Integer id (N) of ftans custom instruction.
mno-custom-fsins
-Target Report RejectNegative Var(nios2_custom_fsins, -1)
+Target RejectNegative Var(nios2_custom_fsins, -1)
Do not use the fsins custom instruction.
mcustom-fsins=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fsins) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fsins) Init(-1)
Integer id (N) of fsins custom instruction.
mno-custom-fcoss
-Target Report RejectNegative Var(nios2_custom_fcoss, -1)
+Target RejectNegative Var(nios2_custom_fcoss, -1)
Do not use the fcoss custom instruction.
mcustom-fcoss=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fcoss) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fcoss) Init(-1)
Integer id (N) of fcoss custom instruction.
mno-custom-fsqrts
-Target Report RejectNegative Var(nios2_custom_fsqrts, -1)
+Target RejectNegative Var(nios2_custom_fsqrts, -1)
Do not use the fsqrts custom instruction.
mcustom-fsqrts=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrts) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fsqrts) Init(-1)
Integer id (N) of fsqrts custom instruction.
mno-custom-fabss
-Target Report RejectNegative Var(nios2_custom_fabss, -1)
+Target RejectNegative Var(nios2_custom_fabss, -1)
Do not use the fabss custom instr.
mcustom-fabss=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fabss) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fabss) Init(-1)
Integer id (N) of fabss custom instruction.
mno-custom-fnegs
-Target Report RejectNegative Var(nios2_custom_fnegs, -1)
+Target RejectNegative Var(nios2_custom_fnegs, -1)
Do not use the fnegs custom instruction.
mcustom-fnegs=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegs) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fnegs) Init(-1)
Integer id (N) of fnegs custom instruction.
mno-custom-fmaxs
-Target Report RejectNegative Var(nios2_custom_fmaxs, -1)
+Target RejectNegative Var(nios2_custom_fmaxs, -1)
Do not use the fmaxs custom instruction.
mcustom-fmaxs=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxs) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fmaxs) Init(-1)
Integer id (N) of fmaxs custom instruction.
mno-custom-fmins
-Target Report RejectNegative Var(nios2_custom_fmins, -1)
+Target RejectNegative Var(nios2_custom_fmins, -1)
Do not use the fmins custom instruction.
mcustom-fmins=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fmins) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fmins) Init(-1)
Integer id (N) of fmins custom instruction.
mno-custom-fdivs
-Target Report RejectNegative Var(nios2_custom_fdivs, -1)
+Target RejectNegative Var(nios2_custom_fdivs, -1)
Do not use the fdivs custom instruction.
mcustom-fdivs=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivs) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fdivs) Init(-1)
Integer id (N) of fdivs custom instruction.
mno-custom-fmuls
-Target Report RejectNegative Var(nios2_custom_fmuls, -1)
+Target RejectNegative Var(nios2_custom_fmuls, -1)
Do not use the fmuls custom instruction.
mcustom-fmuls=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuls) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fmuls) Init(-1)
Integer id (N) of fmuls custom instruction.
mno-custom-fsubs
-Target Report RejectNegative Var(nios2_custom_fsubs, -1)
+Target RejectNegative Var(nios2_custom_fsubs, -1)
Do not use the fsubs custom instruction.
mcustom-fsubs=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubs) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fsubs) Init(-1)
Integer id (N) of fsubs custom instruction.
mno-custom-fadds
-Target Report RejectNegative Var(nios2_custom_fadds, -1)
+Target RejectNegative Var(nios2_custom_fadds, -1)
Do not use the fadds custom instruction.
mcustom-fadds=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fadds) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fadds) Init(-1)
Integer id (N) of fadds custom instruction.
mno-custom-frdy
-Target Report RejectNegative Var(nios2_custom_frdy, -1)
+Target RejectNegative Var(nios2_custom_frdy, -1)
Do not use the frdy custom instruction.
mcustom-frdy=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_frdy) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_frdy) Init(-1)
Integer id (N) of frdy custom instruction.
mno-custom-frdxhi
-Target Report RejectNegative Var(nios2_custom_frdxhi, -1)
+Target RejectNegative Var(nios2_custom_frdxhi, -1)
Do not use the frdxhi custom instruction.
mcustom-frdxhi=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxhi) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_frdxhi) Init(-1)
Integer id (N) of frdxhi custom instruction.
mno-custom-frdxlo
-Target Report RejectNegative Var(nios2_custom_frdxlo, -1)
+Target RejectNegative Var(nios2_custom_frdxlo, -1)
Do not use the frdxlo custom instruction.
mcustom-frdxlo=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxlo) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_frdxlo) Init(-1)
Integer id (N) of frdxlo custom instruction.
mno-custom-fwry
-Target Report RejectNegative Var(nios2_custom_fwry, -1)
+Target RejectNegative Var(nios2_custom_fwry, -1)
Do not use the fwry custom instruction.
mcustom-fwry=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fwry) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fwry) Init(-1)
Integer id (N) of fwry custom instruction.
mno-custom-fwrx
-Target Report RejectNegative Var(nios2_custom_fwrx, -1)
+Target RejectNegative Var(nios2_custom_fwrx, -1)
Do not use the fwrx custom instruction.
mcustom-fwrx=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_fwrx) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_fwrx) Init(-1)
Integer id (N) of fwrx custom instruction.
mno-custom-round
-Target Report RejectNegative Var(nios2_custom_round, -1)
+Target RejectNegative Var(nios2_custom_round, -1)
Do not use the round custom instruction.
mcustom-round=
-Target Report RejectNegative Joined UInteger Var(nios2_custom_round) Init(-1)
+Target RejectNegative Joined UInteger Var(nios2_custom_round) Init(-1)
Integer id (N) of round custom instruction.
march=
@@ -580,11 +580,11 @@ EnumValue
Enum(nios2_arch_type) String(r2) Value(ARCH_R2)
mbmx
-Target Report Mask(HAS_BMX)
+Target Mask(HAS_BMX)
Enable generation of R2 BMX instructions.
mcdx
-Target Report Mask(HAS_CDX)
+Target Mask(HAS_CDX)
Enable generation of R2 CDX instructions.
mgprel-sec=
diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt
index 045e354..465f20e 100644
--- a/gcc/config/nvptx/nvptx.opt
+++ b/gcc/config/nvptx/nvptx.opt
@@ -20,35 +20,35 @@
; It's not clear whether this was ever build/tested/used, so this is no longer
; exposed to the user.
;m32
-;Target Report RejectNegative InverseMask(ABI64)
+;Target RejectNegative InverseMask(ABI64)
;Generate code for a 32-bit ABI.
m64
-Target Report RejectNegative Mask(ABI64)
+Target RejectNegative Mask(ABI64)
Generate code for a 64-bit ABI.
mmainkernel
-Target Report RejectNegative
+Target RejectNegative
Link in code for a __main kernel.
moptimize
-Target Report Var(nvptx_optimize) Init(-1)
+Target Var(nvptx_optimize) Init(-1)
Optimize partition neutering.
msoft-stack
-Target Report Mask(SOFT_STACK)
+Target Mask(SOFT_STACK)
Use custom stacks instead of local memory for automatic storage.
msoft-stack-reserve-local=
-Target Report Joined RejectNegative UInteger Var(nvptx_softstack_size) Init(128)
+Target Joined RejectNegative UInteger Var(nvptx_softstack_size) Init(128)
Specify size of .local memory used for stack when the exact amount is not known.
muniform-simt
-Target Report Mask(UNIFORM_SIMT)
+Target Mask(UNIFORM_SIMT)
Generate code that can keep local state uniform across all lanes.
mgomp
-Target Report Mask(GOMP)
+Target Mask(GOMP)
Generate code for OpenMP offloading: enables -msoft-stack and -muniform-simt.
Enum
diff --git a/gcc/config/pa/pa.opt b/gcc/config/pa/pa.opt
index c286663..402a88b 100644
--- a/gcc/config/pa/pa.opt
+++ b/gcc/config/pa/pa.opt
@@ -42,23 +42,23 @@ Target Ignore
Does nothing. Preserved for backward compatibility.
mcaller-copies
-Target Report Mask(CALLER_COPIES)
+Target Mask(CALLER_COPIES)
Caller copies function arguments passed by hidden reference.
mcoherent-ldcw
-Target Report Var(TARGET_COHERENT_LDCW) Init(1)
+Target Var(TARGET_COHERENT_LDCW) Init(1)
Use ldcw/ldcd coherent cache-control hint.
mdisable-fpregs
-Target Report Mask(DISABLE_FPREGS)
+Target Mask(DISABLE_FPREGS)
Disable FP regs.
mdisable-indexing
-Target Report Mask(DISABLE_INDEXING)
+Target Mask(DISABLE_INDEXING)
Disable indexed addressing.
mfast-indirect-calls
-Target Report Mask(FAST_INDIRECT_CALLS)
+Target Mask(FAST_INDIRECT_CALLS)
Generate fast indirect calls.
mfixed-range=
@@ -66,7 +66,7 @@ Target RejectNegative Joined Var(pa_deferred_options) Defer
Specify range of registers to make fixed.
mgas
-Target Report Mask(GAS)
+Target Mask(GAS)
Assume code will be assembled by GAS.
mjump-in-delay
@@ -79,11 +79,11 @@ Target RejectNegative
Enable linker optimizations.
mlong-calls
-Target Report Mask(LONG_CALLS)
+Target Mask(LONG_CALLS)
Always generate long calls.
mlong-load-store
-Target Report Mask(LONG_LOAD_STORE)
+Target Mask(LONG_LOAD_STORE)
Emit long load/store sequences.
mnosnake
@@ -91,11 +91,11 @@ Target RejectNegative
Generate PA1.0 code.
mno-space-regs
-Target RejectNegative Report Mask(NO_SPACE_REGS)
+Target RejectNegative Mask(NO_SPACE_REGS)
Disable space regs.
mordered
-Target Report Var(TARGET_ORDERED) Init(0)
+Target Var(TARGET_ORDERED) Init(0)
Assume memory references are ordered and barriers are not needed.
mpa-risc-1-0
@@ -111,7 +111,7 @@ Target RejectNegative Mask(PA_20)
Generate PA2.0 code (requires binutils 2.10 or later).
mportable-runtime
-Target Report Mask(PORTABLE_RUNTIME)
+Target Mask(PORTABLE_RUNTIME)
Use portable calling conventions.
mschedule=
@@ -140,7 +140,7 @@ EnumValue
Enum(pa_schedule) String(7300) Value(PROCESSOR_7300)
msoft-float
-Target Report Mask(SOFT_FLOAT)
+Target Mask(SOFT_FLOAT)
Use software floating point.
msnake
@@ -148,5 +148,5 @@ Target RejectNegative
Generate PA1.1 code.
mspace-regs
-Target RejectNegative Report InverseMask(NO_SPACE_REGS)
+Target RejectNegative InverseMask(NO_SPACE_REGS)
Do not disable space regs.
diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md
index 7a4d50f..cdef49f 100644
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ -105,7 +105,7 @@
(clobber (reg FCC_REGNUM))]
""
[(set (reg:CC FCC_REGNUM)
- (compare:CC (match_dup 1) (const_int 0)))
+ (compare:CC (match_dup 1) (const_double_zero)))
(set (match_dup 0) (match_dup 1))])
(define_subst "fcc_ccnz"
@@ -113,7 +113,7 @@
(clobber (reg FCC_REGNUM))]
""
[(set (reg:CCNZ FCC_REGNUM)
- (compare:CCNZ (match_dup 1) (const_int 0)))
+ (compare:CCNZ (match_dup 1) (const_double_zero)))
(set (match_dup 0) (match_dup 1))])
(define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
diff --git a/gcc/config/pdp11/pdp11.opt b/gcc/config/pdp11/pdp11.opt
index 66095a5..17a452a 100644
--- a/gcc/config/pdp11/pdp11.opt
+++ b/gcc/config/pdp11/pdp11.opt
@@ -23,49 +23,49 @@ Target RejectNegative
Generate code for an 11/10.
m40
-Target Report Mask(40)
+Target Mask(40)
Generate code for an 11/40.
m45
-Target Report Mask(45)
+Target Mask(45)
Generate code for an 11/45.
mac0
-Target Report Mask(AC0)
+Target Mask(AC0)
Return floating-point results in ac0 (fr0 in Unix assembler syntax).
mdec-asm
-Target RejectNegative Report Mask(DEC_ASM) Negative(mgnu-asm)
+Target RejectNegative Mask(DEC_ASM) Negative(mgnu-asm)
Use the DEC assembler syntax.
mgnu-asm
-Target RejectNegative Report Mask(GNU_ASM) Negative(munix-asm)
+Target RejectNegative Mask(GNU_ASM) Negative(munix-asm)
Use the GNU assembler syntax.
mfpu
-Target RejectNegative Report Mask(FPU)
+Target RejectNegative Mask(FPU)
Use hardware floating point.
mint16
-Target Report InverseMask(INT32, INT16)
+Target InverseMask(INT32, INT16)
Use 16 bit int.
mint32
-Target Report Mask(INT32)
+Target Mask(INT32)
Use 32 bit int.
msoft-float
-Target RejectNegative Report InverseMask(FPU, SOFT_FLOAT)
+Target RejectNegative InverseMask(FPU, SOFT_FLOAT)
Do not use hardware floating point.
msplit
-Target Report Mask(SPLIT)
+Target Mask(SPLIT)
Target has split I&D.
munix-asm
-Target RejectNegative Report Mask(UNIX_ASM) Negative(mdec-asm)
+Target RejectNegative Mask(UNIX_ASM) Negative(mdec-asm)
Use UNIX assembler syntax.
mlra
-Target Report Mask(LRA)
+Target Mask(LRA)
Use LRA register allocator.
diff --git a/gcc/config/pru/alu-zext.md b/gcc/config/pru/alu-zext.md
index 65916c7..35a6dbd 100644
--- a/gcc/config/pru/alu-zext.md
+++ b/gcc/config/pru/alu-zext.md
@@ -37,6 +37,10 @@
(define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2")
(define_subst_attr "alu3_zext" "alu3_zext_subst" "_z" "_noz")
+(define_subst_attr "lmbd_zext_op1" "lmbd_zext_op1_subst" "_z1" "_noz1")
+(define_subst_attr "lmbd_zext_op2" "lmbd_zext_op2_subst" "_z2" "_noz2")
+(define_subst_attr "lmbd_zext" "lmbd_zext_subst" "_z" "_noz")
+
(define_subst_attr "bitalu_zext" "bitalu_zext_subst" "_z" "_noz")
(define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift lshiftrt])
@@ -72,6 +76,19 @@
[(set_attr "type" "alu")])
+;; Left Most Bit Detect instruction.
+(define_insn "pru_lmbd_impl<EQD:mode><EQS0:mode><EQS1:mode>_<lmbd_zext><lmbd_zext_op1><lmbd_zext_op2>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (unspec:EQD
+ [(zero_extend:EQD
+ (match_operand:EQS0 1 "register_operand" "r"))
+ (zero_extend:EQD
+ (match_operand:EQS1 2 "reg_or_ubyte_operand" "r<EQS1:ubyte_constr>"))]
+ UNSPEC_LMBD))]
+ ""
+ "lmbd\t%0, %1, %2"
+ [(set_attr "type" "alu")])
+
(define_insn "neg_impl<EQD:mode><EQS0:mode>_<alu2_zext>"
[(set (match_operand:EQD 0 "register_operand" "=r")
(neg:EQD
@@ -179,3 +196,37 @@
[(set (match_dup 0)
(ALUOP3:EQD (zero_extend:EQD (match_dup 1))
(match_dup 2)))])
+
+
+(define_subst "lmbd_zext_subst"
+ [(set (match_operand:EQD 0)
+ (unspec:EQD [(zero_extend:EQD (match_operand:EQD 1))
+ (zero_extend:EQD (match_operand:EQD 2))]
+ UNSPEC_LMBD))]
+ ""
+ [(set (match_dup 0)
+ (unspec:EQD [(match_dup 1)
+ (match_dup 2)]
+ UNSPEC_LMBD))])
+
+(define_subst "lmbd_zext_op1_subst"
+ [(set (match_operand:EQD 0)
+ (unspec:EQD [(zero_extend:EQD (match_operand:EQD 1))
+ (zero_extend:EQD (match_operand:EQS1 2))]
+ UNSPEC_LMBD))]
+ ""
+ [(set (match_dup 0)
+ (unspec:EQD [(match_dup 1)
+ (zero_extend:EQD (match_dup 2))]
+ UNSPEC_LMBD))])
+
+(define_subst "lmbd_zext_op2_subst"
+ [(set (match_operand:EQD 0)
+ (unspec:EQD [(zero_extend:EQD (match_operand:EQD 1))
+ (zero_extend:EQD (match_operand:EQD 2))]
+ UNSPEC_LMBD))]
+ ""
+ [(set (match_dup 0)
+ (unspec:EQD [(zero_extend:EQD (match_dup 1))
+ (match_dup 2)]
+ UNSPEC_LMBD))])
diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c
index 39104e5..65ad687 100644
--- a/gcc/config/pru/pru.c
+++ b/gcc/config/pru/pru.c
@@ -2705,6 +2705,8 @@ pru_reorg (void)
enum pru_builtin
{
PRU_BUILTIN_DELAY_CYCLES,
+ PRU_BUILTIN_HALT,
+ PRU_BUILTIN_LMBD,
PRU_BUILTIN_max
};
@@ -2719,11 +2721,31 @@ pru_init_builtins (void)
= build_function_type_list (void_type_node,
long_long_integer_type_node,
NULL);
+ tree uint_ftype_uint_uint
+ = build_function_type_list (unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ NULL);
+
+ tree void_ftype_void
+ = build_function_type_list (void_type_node,
+ void_type_node,
+ NULL);
pru_builtins[PRU_BUILTIN_DELAY_CYCLES]
= add_builtin_function ("__delay_cycles", void_ftype_longlong,
PRU_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL,
NULL_TREE);
+
+ pru_builtins[PRU_BUILTIN_HALT]
+ = add_builtin_function ("__halt", void_ftype_void,
+ PRU_BUILTIN_HALT, BUILT_IN_MD, NULL,
+ NULL_TREE);
+
+ pru_builtins[PRU_BUILTIN_LMBD]
+ = add_builtin_function ("__lmbd", uint_ftype_uint_uint,
+ PRU_BUILTIN_LMBD, BUILT_IN_MD, NULL,
+ NULL_TREE);
}
/* Implement TARGET_BUILTIN_DECL. */
@@ -2734,6 +2756,8 @@ pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
switch (code)
{
case PRU_BUILTIN_DELAY_CYCLES:
+ case PRU_BUILTIN_HALT:
+ case PRU_BUILTIN_LMBD:
return pru_builtins[code];
default:
return error_mark_node;
@@ -2806,19 +2830,45 @@ pru_expand_delay_cycles (rtx arg)
IGNORE is nonzero if the value is to be ignored. */
static rtx
-pru_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+pru_expand_builtin (tree exp, rtx target,
rtx subtarget ATTRIBUTE_UNUSED,
- machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode,
int ignore ATTRIBUTE_UNUSED)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
- rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
- if (fcode == PRU_BUILTIN_DELAY_CYCLES)
- return pru_expand_delay_cycles (arg1);
+ switch (fcode)
+ {
+ case PRU_BUILTIN_DELAY_CYCLES:
+ {
+ rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+ return pru_expand_delay_cycles (arg1);
+ }
+ break;
+ case PRU_BUILTIN_HALT:
+ {
+ emit_insn (gen_pru_halt ());
+ return NULL_RTX;
+ }
+ break;
+ case PRU_BUILTIN_LMBD:
+ {
+ rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+ rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
+
+ if (target == NULL_RTX || GET_MODE (target) != mode)
+ {
+ target = gen_reg_rtx (mode);
+ }
- internal_error ("bad builtin code");
+ emit_insn (gen_pru_lmbd (mode, target, arg1, arg2));
+ return target;
+ }
+ break;
+ default:
+ internal_error ("bad builtin code");
+ }
return NULL_RTX;
}
diff --git a/gcc/config/pru/pru.h b/gcc/config/pru/pru.h
index 314e877..7f217fe 100644
--- a/gcc/config/pru/pru.h
+++ b/gcc/config/pru/pru.h
@@ -562,6 +562,9 @@ do { \
#define CASE_VECTOR_MODE Pmode
+/* See definition of clz pattern for rationale of value -1. */
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = -1, 2)
+
/* Jumps are cheap on PRU. */
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 2f1bc21..125444c 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -51,6 +51,10 @@
;; Enumeration of UNSPECs.
+(define_c_enum "unspec" [
+ UNSPEC_LMBD
+])
+
(define_c_enum "unspecv" [
UNSPECV_DELAY_CYCLES_START
UNSPECV_DELAY_CYCLES_END
@@ -61,6 +65,8 @@
UNSPECV_LOOP_BEGIN
UNSPECV_LOOP_END
+ UNSPECV_HALT
+
UNSPECV_BLOCKAGE
])
@@ -1020,3 +1026,37 @@
""
"nop\\t# Loop end guard"
[(set_attr "type" "alu")])
+
+;; HALT instruction.
+(define_insn "pru_halt"
+ [(unspec_volatile [(const_int 0)] UNSPECV_HALT)]
+ ""
+ "halt"
+ [(set_attr "type" "control")])
+
+;; Count Leading Zeros implemented using LMBD.
+;; LMBD returns 32 if bit value is not present, and we subtract 31 to get CLZ.
+;; Hence we get a defined value -1 for CLZ_DEFINED_VALUE_AT_ZERO.
+(define_expand "clz<mode>2"
+ [(set (match_operand:QISI 0 "register_operand")
+ (clz:QISI (match_operand:QISI 1 "register_operand")))]
+ ""
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+ rtx tmpval = gen_reg_rtx (<MODE>mode);
+
+ emit_insn (gen_pru_lmbd (<MODE>mode, tmpval, src, const1_rtx));
+ emit_insn (gen_sub3_insn (dst, GEN_INT (31), tmpval));
+ DONE;
+})
+
+;; Left Most Bit Detect operation, which maps to a single instruction.
+(define_expand "@pru_lmbd<mode>"
+ [(set (match_operand:QISI 0 "register_operand")
+ (unspec:QISI
+ [(match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "reg_or_ubyte_operand")]
+ UNSPEC_LMBD))]
+ ""
+ "")
diff --git a/gcc/config/pru/pru.opt b/gcc/config/pru/pru.opt
index 5fe716d..f44a8f8 100644
--- a/gcc/config/pru/pru.opt
+++ b/gcc/config/pru/pru.opt
@@ -22,7 +22,7 @@ HeaderInclude
config/pru/pru-opts.h
minrt
-Target Report Mask(MINRT) RejectNegative
+Target Mask(MINRT) RejectNegative
Use a minimum runtime (no static initializers or ctors) for memory-constrained
devices.
@@ -31,7 +31,7 @@ Target RejectNegative Joined
-mmcu=MCU Select the target System-On-Chip variant that embeds this PRU.
mno-relax
-Target Report RejectNegative
+Target RejectNegative
Make GCC pass the --no-relax command-line option to the linker instead of
the --relax option.
@@ -40,7 +40,7 @@ Target Mask(OPT_LOOP)
Allow (or do not allow) gcc to use the LOOP instruction.
mabi=
-Target RejectNegative Report Joined Enum(pru_abi_t) Var(pru_current_abi) Init(PRU_ABI_GNU) Save
+Target RejectNegative Joined Enum(pru_abi_t) Var(pru_current_abi) Init(PRU_ABI_GNU) Save
Select target ABI variant.
Enum
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
new file mode 100755
index 0000000..2b4289e
--- /dev/null
+++ b/gcc/config/riscv/arch-canonicalize
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+# Tool for canonical RISC-V architecture string.
+# Copyright (C) 2011-2020 Free Software Foundation, Inc.
+# Contributed by Andrew Waterman (andrew@sifive.com).
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+
+from __future__ import print_function
+import sys
+import collections
+import itertools
+from functools import reduce
+
+
+CANONICAL_ORDER = "mafdgqlcbjtpvn"
+LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
+
+#
+# IMPLIED_EXT(ext) -> implied extension list.
+#
+IMPLIED_EXT = {
+ "d" : ["f"],
+}
+
+def arch_canonicalize(arch):
+ # TODO: Support extension version.
+ new_arch = ""
+ if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']:
+ # TODO: We should expand g to imad_zifencei once we support newer spec.
+ new_arch = arch[:5].replace("g", "imafd")
+ else:
+ raise Exception("Unexpected arch: `%s`" % arch[:5])
+
+ # Find any Z, S, H or X
+ long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES)
+
+ # Filter out any non-existent index.
+ long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx))
+ if long_ext_prefixes_idx:
+ first_long_ext_idx = min(long_ext_prefixes_idx)
+ long_exts = arch[first_long_ext_idx:].split("_")
+ std_exts = list(arch[5:first_long_ext_idx])
+ else:
+ long_exts = []
+ std_exts = list(arch[5:])
+
+ #
+ # Handle implied extensions.
+ #
+ for ext in std_exts + long_exts:
+ if ext in IMPLIED_EXT:
+ implied_exts = IMPLIED_EXT[ext]
+ for implied_ext in implied_exts:
+ if implied_ext not in std_exts + long_exts:
+ long_exts.append(implied_ext)
+
+ # Single letter extension might appear in the long_exts list,
+ # becasue we just append extensions list to the arch string.
+ std_exts += list(filter(lambda x:len(x) == 1, long_exts))
+
+ # Multi-letter extension must be in lexicographic order.
+ long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts)))
+
+ # Put extensions in canonical order.
+ for ext in CANONICAL_ORDER:
+ if ext in std_exts:
+ new_arch += ext
+
+ # Check every extension is processed.
+ for ext in std_exts:
+ if ext == '_':
+ continue
+ if ext not in CANONICAL_ORDER:
+ raise Exception("Unsupported extension `%s`" % ext)
+
+ # Concat rest of the multi-char extensions.
+ if long_exts:
+ new_arch += "_" + "_".join(long_exts)
+ return new_arch
+
+if len(sys.argv) < 2:
+ print ("Usage: %s <arch_str> [<arch_str>*]" % sys.argv)
+ sys.exit(1)
+
+for arg in sys.argv[1:]:
+ print (arch_canonicalize(arg))
diff --git a/gcc/config/riscv/multilib-generator b/gcc/config/riscv/multilib-generator
index 57ee7c3..64ff15f 100755
--- a/gcc/config/riscv/multilib-generator
+++ b/gcc/config/riscv/multilib-generator
@@ -35,9 +35,11 @@
from __future__ import print_function
import sys
+import os
import collections
import itertools
from functools import reduce
+import subprocess
#
# TODO: Add test for this script.
@@ -48,82 +50,14 @@ abis = collections.OrderedDict()
required = []
reuse = []
-canonical_order = "mafdgqlcbjtpvn"
-LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
-
-#
-# IMPLIED_EXT(ext) -> implied extension list.
-#
-IMPLIED_EXT = {
- "d" : ["f"],
-}
-
def arch_canonicalize(arch):
- # TODO: Support extension version.
- new_arch = ""
- if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']:
- # TODO: We should expand g to imad_zifencei once we support newer spec.
- new_arch = arch[:5].replace("g", "imafd")
- else:
- raise Exception("Unexpected arch: `%s`" % arch[:5])
-
- # Find any Z, S, H or X
- long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES)
-
- # Filter out any non-existent index.
- long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx))
- if long_ext_prefixes_idx:
- first_long_ext_idx = min(long_ext_prefixes_idx)
- long_exts = arch[first_long_ext_idx:].split("_")
- std_exts = list(arch[5:first_long_ext_idx])
- else:
- long_exts = []
- std_exts = list(arch[5:])
-
- #
- # Handle implied extensions.
- #
- for ext in std_exts + long_exts:
- if ext in IMPLIED_EXT:
- implied_exts = IMPLIED_EXT[ext]
- for implied_ext in implied_exts:
- if implied_ext not in std_exts + long_exts:
- long_exts.append(implied_ext)
-
- # Single letter extension might appear in the long_exts list,
- # becasue we just append extensions list to the arch string.
- std_exts += list(filter(lambda x:len(x) == 1, long_exts))
-
- # Multi-letter extension must be in lexicographic order.
- long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts)))
-
- # Put extensions in canonical order.
- for ext in canonical_order:
- if ext in std_exts:
- new_arch += ext
-
- # Check every extension is processed.
- for ext in std_exts:
- if ext == '_':
- continue
- if ext not in canonical_order:
- raise Exception("Unsupported extension `%s`" % ext)
-
- # Concat rest of the multi-char extensions.
- if long_exts:
- new_arch += "_" + "_".join(long_exts)
- return new_arch
-
-#
-# add underline for each multi-char extensions.
-# e.g. ["a", "zfh"] -> ["a", "_zfh"]
-#
-def add_underline_prefix(ext):
- for long_ext_prefix in LONG_EXT_PREFIXES:
- if ext.startswith(long_ext_prefix):
- return "_" + ext
-
- return ext
+ this_file = os.path.abspath(os.path.join( __file__))
+ arch_can_script = \
+ os.path.join(os.path.dirname(this_file), "arch-canonicalize")
+ proc = subprocess.Popen([sys.executable, arch_can_script, arch],
+ stdout=subprocess.PIPE)
+ out, err = proc.communicate()
+ return out.decode().strip()
#
# Handle expansion operation.
@@ -194,7 +128,14 @@ def expand_combination(ext):
return ext
for cfg in sys.argv[1:]:
- (arch, abi, extra, ext) = cfg.split('-')
+ try:
+ (arch, abi, extra, ext) = cfg.split('-')
+ except:
+ print ("Invalid configure string %s, <arch>-<abi>-<extra>-<extensions>\n"
+ "<extra> and <extensions> can be empty, "
+ "e.g. rv32imafd-ilp32--" % cfg)
+ sys.exit(1)
+
arch = arch_canonicalize (arch)
arches[arch] = 1
abis[abi] = 1
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 2a3f9d9..0b83f17 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -39,6 +39,16 @@ enum riscv_code_model {
};
extern enum riscv_code_model riscv_cmodel;
+enum riscv_isa_spec_class {
+ ISA_SPEC_CLASS_NONE,
+
+ ISA_SPEC_CLASS_2P2,
+ ISA_SPEC_CLASS_20190608,
+ ISA_SPEC_CLASS_20191213
+};
+
+extern enum riscv_isa_spec_class riscv_isa_spec;
+
/* Keep this list in sync with define_attr "tune" in riscv.md. */
enum riscv_microarchitecture_type {
generic,
@@ -57,4 +67,10 @@ enum stack_protector_guard {
SSP_GLOBAL /* global canary */
};
+#define MASK_ZICSR (1 << 0)
+#define MASK_ZIFENCEI (1 << 1)
+
+#define TARGET_ZICSR ((riscv_zi_subext & MASK_ZICSR) != 0)
+#define TARGET_ZIFENCEI ((riscv_zi_subext & MASK_ZIFENCEI) != 0)
+
#endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 989a9f1..9b83da0 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -3110,7 +3110,7 @@ riscv_legitimize_call_address (rtx addr)
{
if (!call_insn_operand (addr, VOIDmode))
{
- rtx reg = RISCV_PROLOGUE_TEMP (Pmode);
+ rtx reg = RISCV_CALL_ADDRESS_TEMP (Pmode);
riscv_emit_move (reg, addr);
return reg;
}
@@ -3707,18 +3707,18 @@ riscv_compute_frame_info (void)
{
struct riscv_frame_info *frame;
HOST_WIDE_INT offset;
- bool interrupt_save_t1 = false;
+ bool interrupt_save_prologue_temp = false;
unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
frame = &cfun->machine->frame;
/* In an interrupt function, if we have a large frame, then we need to
- save/restore t1. We check for this before clearing the frame struct. */
+ save/restore t0. We check for this before clearing the frame struct. */
if (cfun->machine->interrupt_handler_p)
{
HOST_WIDE_INT step1 = riscv_first_stack_step (frame);
if (! SMALL_OPERAND (frame->total_size - step1))
- interrupt_save_t1 = true;
+ interrupt_save_prologue_temp = true;
}
memset (frame, 0, sizeof (*frame));
@@ -3728,7 +3728,8 @@ riscv_compute_frame_info (void)
/* Find out which GPRs we need to save. */
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (riscv_save_reg_p (regno)
- || (interrupt_save_t1 && (regno == T1_REGNUM)))
+ || (interrupt_save_prologue_temp
+ && (regno == RISCV_PROLOGUE_TEMP_REGNUM)))
frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
/* If this function calls eh_return, we must also save and restore the
@@ -4902,9 +4903,9 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
rtx target_function = force_reg (Pmode, XEXP (DECL_RTL (fndecl), 0));
/* lui t2, hi(chain)
- lui t1, hi(func)
+ lui t0, hi(func)
addi t2, t2, lo(chain)
- jr r1, lo(func)
+ jr t0, lo(func)
*/
unsigned HOST_WIDE_INT lui_hi_chain_code, lui_hi_func_code;
unsigned HOST_WIDE_INT lo_chain_code, lo_func_code;
@@ -4929,7 +4930,7 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
mem = adjust_address (m_tramp, SImode, 0);
riscv_emit_move (mem, lui_hi_chain);
- /* Gen lui t1, hi(func). */
+ /* Gen lui t0, hi(func). */
rtx hi_func = riscv_force_binary (SImode, PLUS, target_function,
fixup_value);
hi_func = riscv_force_binary (SImode, AND, hi_func,
@@ -4956,7 +4957,7 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
mem = adjust_address (m_tramp, SImode, 2 * GET_MODE_SIZE (SImode));
riscv_emit_move (mem, addi_lo_chain);
- /* Gen jr r1, lo(func). */
+ /* Gen jr t0, lo(func). */
rtx lo_func = riscv_force_binary (SImode, AND, target_function,
imm12_mask);
lo_func = riscv_force_binary (SImode, ASHIFT, lo_func, GEN_INT (20));
@@ -4975,9 +4976,9 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode);
/* auipc t2, 0
- l[wd] t1, target_function_offset(t2)
+ l[wd] t0, target_function_offset(t2)
l[wd] t2, static_chain_offset(t2)
- jr t1
+ jr t0
*/
trampoline[0] = OPCODE_AUIPC | (STATIC_CHAIN_REGNUM << SHIFT_RD);
trampoline[1] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW)
@@ -5299,6 +5300,19 @@ riscv_gpr_save_operation_p (rtx op)
return true;
}
+/* Implement TARGET_ASAN_SHADOW_OFFSET. */
+
+static unsigned HOST_WIDE_INT
+riscv_asan_shadow_offset (void)
+{
+ /* We only have libsanitizer support for RV64 at present.
+
+ This number must match kRiscv*_ShadowOffset* in the file
+ libsanitizer/asan/asan_mapping.h which is currently 1<<29 for rv64,
+ even though 1<<36 makes more sense. */
+ return TARGET_64BIT ? (HOST_WIDE_INT_1 << 29) : 0;
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -5482,6 +5496,9 @@ riscv_gpr_save_operation_p (rtx op)
#undef TARGET_NEW_ADDRESS_PROFITABLE_P
#define TARGET_NEW_ADDRESS_PROFITABLE_P riscv_new_address_profitable_p
+#undef TARGET_ASAN_SHADOW_OFFSET
+#define TARGET_ASAN_SHADOW_OFFSET riscv_asan_shadow_offset
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-riscv.h"
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 172c7ca..df3003f 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -70,13 +70,29 @@ extern const char *riscv_default_mtune (int argc, const char **argv);
#define TARGET_64BIT (__riscv_xlen == 64)
#endif /* IN_LIBGCC2 */
+#ifdef HAVE_AS_MISA_SPEC
+#define ASM_MISA_SPEC "%{misa-spec=*}"
+#else
+#define ASM_MISA_SPEC ""
+#endif
+
+/* Reference:
+ https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing */
+#define STRINGIZING(s) __STRINGIZING(s)
+#define __STRINGIZING(s) #s
+
+#define MULTILIB_DEFAULTS \
+ {"march=" STRINGIZING (TARGET_RISCV_DEFAULT_ARCH), \
+ "mabi=" STRINGIZING (TARGET_RISCV_DEFAULT_ABI) }
+
#undef ASM_SPEC
#define ASM_SPEC "\
%(subtarget_asm_debugging_spec) \
%{" FPIE_OR_FPIC_SPEC ":-fpic} \
%{march=*} \
%{mabi=*} \
-%(subtarget_asm_spec)"
+%(subtarget_asm_spec)" \
+ASM_MISA_SPEC
#undef DRIVER_SELF_SPECS
#define DRIVER_SELF_SPECS \
@@ -342,9 +358,13 @@ extern const char *riscv_default_mtune (int argc, const char **argv);
The epilogue temporary mustn't conflict with the return registers,
the frame pointer, the EH stack adjustment, or the EH data registers. */
-#define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST + 1)
+#define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST)
#define RISCV_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_PROLOGUE_TEMP_REGNUM)
+#define RISCV_CALL_ADDRESS_TEMP_REGNUM (GP_TEMP_FIRST + 1)
+#define RISCV_CALL_ADDRESS_TEMP(MODE) \
+ gen_rtx_REG (MODE, RISCV_CALL_ADDRESS_TEMP_REGNUM)
+
#define MCOUNT_NAME "_mcount"
#define NO_PROFILE_COUNTERS 1
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index f15bad3..254147c 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1543,7 +1543,8 @@
LCT_NORMAL, VOIDmode, operands[0], Pmode,
operands[1], Pmode, const0_rtx, Pmode);
#else
- emit_insn (gen_fence_i ());
+ if (TARGET_ZIFENCEI)
+ emit_insn (gen_fence_i ());
#endif
DONE;
})
@@ -1555,7 +1556,7 @@
(define_insn "fence_i"
[(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
- ""
+ "TARGET_ZIFENCEI"
"fence.i")
;;
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 808b4a0..25120e2 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -26,11 +26,11 @@ Target RejectNegative Joined UInteger Var(riscv_branch_cost)
-mbranch-cost=N Set the cost of branches to roughly N instructions.
mplt
-Target Report Var(TARGET_PLT) Init(1)
+Target Var(TARGET_PLT) Init(1)
When generating -fpic code, allow the use of PLTs. Ignored for fno-pic.
mabi=
-Target Report RejectNegative Joined Enum(abi_type) Var(riscv_abi) Init(ABI_ILP32)
+Target RejectNegative Joined Enum(abi_type) Var(riscv_abi) Init(ABI_ILP32)
Specify integer and floating-point calling convention.
mpreferred-stack-boundary=
@@ -63,15 +63,15 @@ EnumValue
Enum(abi_type) String(lp64d) Value(ABI_LP64D)
mfdiv
-Target Report Mask(FDIV)
+Target Mask(FDIV)
Use hardware floating-point divide and square root instructions.
mdiv
-Target Report Mask(DIV)
+Target Mask(DIV)
Use hardware instructions for integer division.
march=
-Target Report RejectNegative Joined
+Target RejectNegative Joined
-march= Generate code for given RISC-V ISA (e.g. RV64IM). ISA strings must be
lower-case.
@@ -88,7 +88,7 @@ Target Joined Separate UInteger Var(g_switch_value) Init(8)
-msmall-data-limit=N Put global and static data smaller than <number> bytes into a special section (on some targets).
msave-restore
-Target Report Mask(SAVE_RESTORE)
+Target Mask(SAVE_RESTORE)
Use smaller but slower prologue and epilogue code.
mshorten-memrefs
@@ -98,11 +98,11 @@ memory accesses to be generated as compressed instructions. Currently targets
32-bit integer load/stores.
mcmodel=
-Target Report RejectNegative Joined Enum(code_model) Var(riscv_cmodel) Init(TARGET_DEFAULT_CMODEL)
+Target RejectNegative Joined Enum(code_model) Var(riscv_cmodel) Init(TARGET_DEFAULT_CMODEL)
Specify the code model.
mstrict-align
-Target Report Mask(STRICT_ALIGN) Save
+Target Mask(STRICT_ALIGN) Save
Do not generate unaligned memory accesses.
Enum
@@ -116,7 +116,7 @@ EnumValue
Enum(code_model) String(medany) Value(CM_MEDANY)
mexplicit-relocs
-Target Report Mask(EXPLICIT_RELOCS)
+Target Mask(EXPLICIT_RELOCS)
Use %reloc() operators, rather than assembly macros, to load addresses.
mrelax
@@ -139,7 +139,7 @@ Mask(RVC)
Mask(RVE)
mriscv-attribute
-Target Report Var(riscv_emit_attribute_p) Init(-1)
+Target Var(riscv_emit_attribute_p) Init(-1)
Emit RISC-V ELF attribute.
malign-data=
@@ -183,3 +183,23 @@ Use the given offset for addressing the stack-protector guard.
TargetVariable
long riscv_stack_protector_guard_offset = 0
+
+TargetVariable
+int riscv_zi_subext
+
+Enum
+Name(isa_spec_class) Type(enum riscv_isa_spec_class)
+Supported ISA specs (for use with the -misa-spec= option):
+
+EnumValue
+Enum(isa_spec_class) String(2.2) Value(ISA_SPEC_CLASS_2P2)
+
+EnumValue
+Enum(isa_spec_class) String(20190608) Value(ISA_SPEC_CLASS_20190608)
+
+EnumValue
+Enum(isa_spec_class) String(20191213) Value(ISA_SPEC_CLASS_20191213)
+
+misa-spec=
+Target RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC)
+Set the version of RISC-V ISA spec.
diff --git a/gcc/config/riscv/t-withmultilib-generator b/gcc/config/riscv/t-withmultilib-generator
new file mode 100644
index 0000000..1a35cc0b
--- /dev/null
+++ b/gcc/config/riscv/t-withmultilib-generator
@@ -0,0 +1,2 @@
+# t-multilib-config will generated in build folder by configure script.
+include t-multilib-config
diff --git a/gcc/config/riscv/withmultilib.h b/gcc/config/riscv/withmultilib.h
deleted file mode 100644
index d022716..0000000
--- a/gcc/config/riscv/withmultilib.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* MULTILIB_DEFAULTS definitions for --with-multilib-list.
- Copyright (C) 2018-2020 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
-
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#if TARGET_MLIB_ARCH == 1
-
-# if TARGET_MLIB_ABI == 1
-# define MULTILIB_DEFAULTS {"march=rv32gc", "mabi=ilp32" }
-# elif TARGET_MLIB_ABI == 2
-# define MULTILIB_DEFAULTS {"march=rv32gc", "mabi=ilp32f" }
-# elif TARGET_MLIB_ABI == 3
-# define MULTILIB_DEFAULTS {"march=rv32gc", "mabi=ilp32d" }
-# else
-# error "unsupported TARGET_MLIB_ABI value for rv32gc"
-# endif
-
-#elif TARGET_MLIB_ARCH == 2
-
-# if TARGET_MLIB_ABI == 4
-# define MULTILIB_DEFAULTS {"march=rv64gc", "mabi=lp64" }
-# elif TARGET_MLIB_ABI == 5
-# define MULTILIB_DEFAULTS {"march=rv64gc", "mabi=lp64f" }
-# elif TARGET_MLIB_ABI == 6
-# define MULTILIB_DEFAULTS {"march=rv64gc", "mabi=lp64d" }
-# else
-# error "unsupported TARGET_MLIB_ABI value for rv64gc"
-# endif
-
-#else
-# error "unsupported TARGET_MLIB_ARCH value"
-#endif
diff --git a/gcc/config/rl78/rl78.opt b/gcc/config/rl78/rl78.opt
index 489697b..619e0fd 100644
--- a/gcc/config/rl78/rl78.opt
+++ b/gcc/config/rl78/rl78.opt
@@ -23,11 +23,11 @@ HeaderInclude
config/rl78/rl78-opts.h
msim
-Target Report
+Target
Use the simulator runtime.
mmul=
-Target RejectNegative Joined Var(rl78_mul_type) Report Tolower Enum(rl78_mul_types) Init(MUL_UNINIT)
+Target RejectNegative Joined Var(rl78_mul_type) Tolower Enum(rl78_mul_types) Init(MUL_UNINIT)
Selects the type of hardware multiplication and division to use (none/g13/g14).
Enum
@@ -46,15 +46,15 @@ EnumValue
Enum(rl78_mul_types) String(rl78) Value(MUL_G14)
mallregs
-Target Mask(ALLREGS) Report Optimization
+Target Mask(ALLREGS) Optimization
Use all registers, reserving none for interrupt handlers.
mrelax
-Target Report Optimization
+Target Optimization
Enable assembler and linker relaxation. Enabled by default at -Os.
mcpu=
-Target RejectNegative Joined Var(rl78_cpu_type) Report ToLower Enum(rl78_cpu_types) Init(CPU_UNINIT)
+Target RejectNegative Joined Var(rl78_cpu_type) ToLower Enum(rl78_cpu_types) Init(CPU_UNINIT)
Selects the type of RL78 core being targeted (g10/g13/g14). The default is the G14. If set, also selects the hardware multiply support to be used.
Enum
@@ -73,19 +73,19 @@ EnumValue
Enum(rl78_cpu_types) String(rl78) Value(CPU_G14)
mg10
-Target RejectNegative Report Alias(mcpu=, g10)
+Target RejectNegative Alias(mcpu=, g10)
Alias for -mcpu=g10.
mg13
-Target RejectNegative Report Alias(mcpu=, g13)
+Target RejectNegative Alias(mcpu=, g13)
Alias for -mcpu=g13.
mg14
-Target RejectNegative Report Alias(mcpu=, g14)
+Target RejectNegative Alias(mcpu=, g14)
Alias for -mcpu=g14.
mrl78
-Target RejectNegative Report Alias(mcpu=, g14)
+Target RejectNegative Alias(mcpu=, g14)
Alias for -mcpu=g14.
mes0
diff --git a/gcc/config/rs6000/aix64.opt b/gcc/config/rs6000/aix64.opt
index 48135ce..51d1668 100644
--- a/gcc/config/rs6000/aix64.opt
+++ b/gcc/config/rs6000/aix64.opt
@@ -20,11 +20,11 @@
; <http://www.gnu.org/licenses/>.
maix64
-Target Report RejectNegative Negative(maix32) Mask(64BIT) Var(rs6000_isa_flags)
+Target RejectNegative Negative(maix32) Mask(64BIT) Var(rs6000_isa_flags)
Compile for 64-bit pointers.
maix32
-Target Report RejectNegative Negative(maix64) InverseMask(64BIT) Var(rs6000_isa_flags)
+Target RejectNegative Negative(maix64) InverseMask(64BIT) Var(rs6000_isa_flags)
Compile for 32-bit pointers.
mcmodel=
@@ -45,7 +45,7 @@ EnumValue
Enum(rs6000_cmodel) String(large) Value(CMODEL_LARGE)
mpe
-Target Report RejectNegative Var(internal_nothing_1) Save
+Target RejectNegative Var(internal_nothing_1) Save
Support message passing with the Parallel Environment.
posix
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index df10a8c..e1884f5 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -497,8 +497,33 @@
#define vec_xlx __builtin_vec_vextulx
#define vec_xrx __builtin_vec_vexturx
+
#endif
+/* BCD builtins, map ABI builtin name to existing builtin name. */
+#define __builtin_bcdadd __builtin_vec_bcdadd
+#define __builtin_bcdadd_lt __builtin_vec_bcdadd_lt
+#define __builtin_bcdadd_eq __builtin_vec_bcdadd_eq
+#define __builtin_bcdadd_gt __builtin_vec_bcdadd_gt
+#define __builtin_bcdadd_ofl __builtin_vec_bcdadd_ov
+#define __builtin_bcdadd_ov __builtin_vec_bcdadd_ov
+#define __builtin_bcdsub __builtin_vec_bcdsub
+#define __builtin_bcdsub_lt __builtin_vec_bcdsub_lt
+#define __builtin_bcdsub_eq __builtin_vec_bcdsub_eq
+#define __builtin_bcdsub_gt __builtin_vec_bcdsub_gt
+#define __builtin_bcdsub_ofl __builtin_vec_bcdsub_ov
+#define __builtin_bcdsub_ov __builtin_vec_bcdsub_ov
+#define __builtin_bcdinvalid __builtin_vec_bcdinvalid
+#define __builtin_bcdmul10 __builtin_vec_bcdmul10
+#define __builtin_bcddiv10 __builtin_vec_bcddiv10
+#define __builtin_bcd2dfp __builtin_vec_denb2dfp
+#define __builtin_bcdcmpeq(a,b) __builtin_vec_bcdsub_eq(a,b,0)
+#define __builtin_bcdcmpgt(a,b) __builtin_vec_bcdsub_gt(a,b,0)
+#define __builtin_bcdcmplt(a,b) __builtin_vec_bcdsub_lt(a,b,0)
+#define __builtin_bcdcmpge(a,b) __builtin_vec_bcdsub_ge(a,b,0)
+#define __builtin_bcdcmple(a,b) __builtin_vec_bcdsub_le(a,b,0)
+
+
/* Predicates.
For C++, we use templates in order to allow non-parenthesized arguments.
For C, instead, we use macros since non-parenthesized arguments were
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 0a2e634..6a6ce0f 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -160,6 +160,7 @@
UNSPEC_BCDADD
UNSPEC_BCDSUB
UNSPEC_BCD_OVERFLOW
+ UNSPEC_BCDSHIFT
UNSPEC_VRLMI
UNSPEC_VRLNM
UNSPEC_VCFUGED
@@ -4410,12 +4411,13 @@
(define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
(UNSPEC_BCDSUB "sub")])
-(define_code_iterator BCD_TEST [eq lt gt unordered])
+(define_code_iterator BCD_TEST [eq lt le gt ge unordered])
+(define_mode_iterator VBCD [V1TI V16QI])
-(define_insn "bcd<bcd_add_sub>"
- [(set (match_operand:V1TI 0 "gpc_reg_operand" "=v")
- (unspec:V1TI [(match_operand:V1TI 1 "gpc_reg_operand" "v")
- (match_operand:V1TI 2 "gpc_reg_operand" "v")
+(define_insn "bcd<bcd_add_sub>_<mode>"
+ [(set (match_operand:VBCD 0 "register_operand" "=v")
+ (unspec:VBCD [(match_operand:VBCD 1 "register_operand" "v")
+ (match_operand:VBCD 2 "register_operand" "v")
(match_operand:QI 3 "const_0_to_1_operand" "n")]
UNSPEC_BCD_ADD_SUB))
(clobber (reg:CCFP CR6_REGNO))]
@@ -4428,23 +4430,23 @@
;; UNORDERED test on an integer type (like V1TImode) is not defined. The type
;; probably should be one that can go in the VMX (Altivec) registers, so we
;; can't use DDmode or DFmode.
-(define_insn "*bcd<bcd_add_sub>_test"
+(define_insn "*bcd<bcd_add_sub>_test_<mode>"
[(set (reg:CCFP CR6_REGNO)
(compare:CCFP
- (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
- (match_operand:V1TI 2 "register_operand" "v")
+ (unspec:V2DF [(match_operand:VBCD 1 "register_operand" "v")
+ (match_operand:VBCD 2 "register_operand" "v")
(match_operand:QI 3 "const_0_to_1_operand" "i")]
UNSPEC_BCD_ADD_SUB)
(match_operand:V2DF 4 "zero_constant" "j")))
- (clobber (match_scratch:V1TI 0 "=v"))]
+ (clobber (match_scratch:VBCD 0 "=v"))]
"TARGET_P8_VECTOR"
"bcd<bcd_add_sub>. %0,%1,%2,%3"
[(set_attr "type" "vecsimple")])
-(define_insn "*bcd<bcd_add_sub>_test2"
- [(set (match_operand:V1TI 0 "register_operand" "=v")
- (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
- (match_operand:V1TI 2 "register_operand" "v")
+(define_insn "*bcd<bcd_add_sub>_test2_<mode>"
+ [(set (match_operand:VBCD 0 "register_operand" "=v")
+ (unspec:VBCD [(match_operand:VBCD 1 "register_operand" "v")
+ (match_operand:VBCD 2 "register_operand" "v")
(match_operand:QI 3 "const_0_to_1_operand" "i")]
UNSPEC_BCD_ADD_SUB))
(set (reg:CCFP CR6_REGNO)
@@ -4540,15 +4542,15 @@
}
[(set_attr "type" "vecsimple")])
-(define_expand "bcd<bcd_add_sub>_<code>"
+(define_expand "bcd<bcd_add_sub>_<code>_<mode>"
[(parallel [(set (reg:CCFP CR6_REGNO)
(compare:CCFP
- (unspec:V2DF [(match_operand:V1TI 1 "register_operand")
- (match_operand:V1TI 2 "register_operand")
+ (unspec:V2DF [(match_operand:VBCD 1 "register_operand")
+ (match_operand:VBCD 2 "register_operand")
(match_operand:QI 3 "const_0_to_1_operand")]
UNSPEC_BCD_ADD_SUB)
(match_dup 4)))
- (clobber (match_scratch:V1TI 5))])
+ (clobber (match_scratch:VBCD 5))])
(set (match_operand:SI 0 "register_operand")
(BCD_TEST:SI (reg:CCFP CR6_REGNO)
(const_int 0)))]
@@ -4557,6 +4559,74 @@
operands[4] = CONST0_RTX (V2DFmode);
})
+(define_insn "*bcdinvalid_<mode>"
+ [(set (reg:CCFP CR6_REGNO)
+ (compare:CCFP
+ (unspec:V2DF [(match_operand:VBCD 1 "register_operand" "v")]
+ UNSPEC_BCDADD)
+ (match_operand:V2DF 2 "zero_constant" "j")))
+ (clobber (match_scratch:VBCD 0 "=v"))]
+ "TARGET_P8_VECTOR"
+ "bcdadd. %0,%1,%1,0"
+ [(set_attr "type" "vecsimple")])
+
+(define_expand "bcdinvalid_<mode>"
+ [(parallel [(set (reg:CCFP CR6_REGNO)
+ (compare:CCFP
+ (unspec:V2DF [(match_operand:VBCD 1 "register_operand")]
+ UNSPEC_BCDADD)
+ (match_dup 2)))
+ (clobber (match_scratch:VBCD 3))])
+ (set (match_operand:SI 0 "register_operand")
+ (unordered:SI (reg:CCFP CR6_REGNO)
+ (const_int 0)))]
+ "TARGET_P8_VECTOR"
+{
+ operands[2] = CONST0_RTX (V2DFmode);
+})
+
+(define_insn "bcdshift_v16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:QI 3 "const_0_to_1_operand" "n")]
+ UNSPEC_BCDSHIFT))
+ (clobber (reg:CCFP CR6_REGNO))]
+ "TARGET_P8_VECTOR"
+ "bcds. %0,%1,%2,%3"
+ [(set_attr "type" "vecsimple")])
+
+(define_expand "bcdmul10_v16qi"
+ [(set (match_operand:V16QI 0 "register_operand")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand")]
+ UNSPEC_BCDSHIFT))
+ (clobber (reg:CCFP CR6_REGNO))]
+ "TARGET_P9_VECTOR"
+{
+ rtx one = gen_reg_rtx (V16QImode);
+
+ emit_insn (gen_altivec_vspltisb (one, const1_rtx));
+ emit_insn (gen_bcdshift_v16qi (operands[0], one, operands[1], const0_rtx));
+
+ DONE;
+})
+
+(define_expand "bcddiv10_v16qi"
+ [(set (match_operand:V16QI 0 "register_operand")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand")]
+ UNSPEC_BCDSHIFT))
+ (clobber (reg:CCFP CR6_REGNO))]
+ "TARGET_P9_VECTOR"
+{
+ rtx one = gen_reg_rtx (V16QImode);
+
+ emit_insn (gen_altivec_vspltisb (one, constm1_rtx));
+ emit_insn (gen_bcdshift_v16qi (operands[0], one, operands[1], const0_rtx));
+
+ DONE;
+})
+
+
;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
;; the bcdadd/bcdsub that tests the value. The combiner won't work since
;; CR6 is a hard coded register. Unfortunately, all of the Altivec predicate
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index 8f82273..9a95230 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -273,6 +273,28 @@
"denbcd<q> %1,%0,%2"
[(set_attr "type" "dfp")])
+(define_insn "dfp_denbcd_v16qi_inst"
+ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
+ (unspec:TD [(match_operand:QI 1 "const_0_to_1_operand" "i")
+ (match_operand:V16QI 2 "register_operand" "d")]
+ UNSPEC_DENBCD))]
+ "TARGET_DFP"
+ "denbcdq %1,%0,%2"
+ [(set_attr "type" "dfp")])
+
+(define_expand "dfp_denbcd_v16qi"
+ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
+ (unspec:TD [(match_operand:V16QI 1 "register_operand" "v")]
+ UNSPEC_DENBCD))]
+ "TARGET_DFP"
+ {
+ // Move vs128 upper 64-bits and lower 64-bits to fp register pair
+ convert_move (operands[0], operands[1], true);
+ emit_insn (gen_dfp_denbcd_v16qi_inst (operands[0], GEN_INT(1),
+ operands[0]));
+ DONE;
+ })
+
(define_insn "dfp_dxex_<mode>"
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")]
diff --git a/gcc/config/rs6000/freebsd64.h b/gcc/config/rs6000/freebsd64.h
index 6984ca5..390bc4b 100644
--- a/gcc/config/rs6000/freebsd64.h
+++ b/gcc/config/rs6000/freebsd64.h
@@ -51,11 +51,10 @@ extern int dot_symbols;
#define SET_CMODEL(opt) do {} while (0)
#endif
-/* Until now the 970 is the only Processor where FreeBSD 64-bit runs on. */
#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_POWER4
+#define PROCESSOR_DEFAULT PROCESSOR_PPC7450
#undef PROCESSOR_DEFAULT64
-#define PROCESSOR_DEFAULT64 PROCESSOR_POWER4
+#define PROCESSOR_DEFAULT64 PROCESSOR_POWER8
/* We don't need to generate entries in .fixup, except when
-mrelocatable or -mrelocatable-lib is given. */
@@ -100,8 +99,8 @@ extern int dot_symbols;
#define ASM_SPEC64 "-a64"
#define ASM_SPEC_COMMON "%(asm_cpu) \
-%{,assembler|,assembler-with-cpp: %{mregnames} %{mno-regnames}} \
-%{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian}"
+%{,assembler|,assembler-with-cpp: %{mregnames} %{mno-regnames}}" \
+ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
#undef SUBSUBTARGET_EXTRA_SPECS
#define SUBSUBTARGET_EXTRA_SPECS \
@@ -123,9 +122,15 @@ extern int dot_symbols;
%{static:-Bstatic}} \
%{symbolic:-Bsymbolic}"
+#undef DEFAULT_ASM_ENDIAN
#define LINK_OS_FREEBSD_SPEC32 "-melf32ppc_fbsd " LINK_OS_FREEBSD_SPEC_DEF
-
+#if (TARGET_DEFAULT & MASK_LITTLE_ENDIAN)
+#define DEFAULT_ASM_ENDIAN " -mlittle"
+#define LINK_OS_FREEBSD_SPEC64 "-melf64lppc_fbsd " LINK_OS_FREEBSD_SPEC_DEF
+#else
+#define DEFAULT_ASM_ENDIAN " -mbig"
#define LINK_OS_FREEBSD_SPEC64 "-melf64ppc_fbsd " LINK_OS_FREEBSD_SPEC_DEF
+#endif
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS { "m64" }
diff --git a/gcc/config/rs6000/linux64.opt b/gcc/config/rs6000/linux64.opt
index a0d7864..cafeb1e 100644
--- a/gcc/config/rs6000/linux64.opt
+++ b/gcc/config/rs6000/linux64.opt
@@ -20,7 +20,7 @@
; <http://www.gnu.org/licenses/>.
mprofile-kernel
-Target Report Var(profile_kernel) Save
+Target Var(profile_kernel) Save
Call mcount for profiling before a function prologue.
mcmodel=
diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index a3fd28b..ef43944 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -19,24 +19,18 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-;; The MMA patterns use the multi-register PXImode and POImode partial
-;; integer modes to implement the target specific __vector_quad and
-;; __vector_pair types that the MMA built-in functions reference.
-;; To use these modes, we must define XImode and OImode move patterns
-;; so the independent parts of the compiler can use our large partial
-;; integer modes. However, if we enable the XImode and OImode move
-;; patterns, then the compiler will attempt to use them and this can
-;; cause byte swapping issues on litte-endian systems. We don't need
-;; the XImode and OImode move patterns for actual code generation,
-;; therefore, we define the XImode and OImode move patterns, but we
-;; disable their use with a "false" condition flag.
+;; The MMA patterns use the multi-register XOmode and OOmode opaque
+;; modes to implement the target specific __vector_quad and
+;; __vector_pair types that the MMA built-in functions reference. We
+;; use OPAQUE_MODE to prevent anything from trying to open them up.
(define_constants [(MAX_MMA_OPERANDS 7)])
;; Constants for creating unspecs
(define_c_enum "unspec"
- [UNSPEC_MMA_ASSEMBLE_ACC
+ [UNSPEC_MMA_ASSEMBLE
+ UNSPEC_MMA_EXTRACT
UNSPEC_MMA_PMXVBF16GER2
UNSPEC_MMA_PMXVBF16GER2NN
UNSPEC_MMA_PMXVBF16GER2NP
@@ -97,6 +91,7 @@
UNSPEC_MMA_XVI8GER4SPP
UNSPEC_MMA_XXMFACC
UNSPEC_MMA_XXMTACC
+ UNSPEC_MMA_XXSETACCZ
])
;; MMA instructions with 1 accumulator argument
@@ -265,31 +260,22 @@
(UNSPEC_MMA_PMXVI8GER4SPP "pmxvi8ger4spp")])
-;; Define a disabled OImode move pattern, so we can use POImode.
-(define_expand "movoi"
- [(set (match_operand:OI 0 "nonimmediate_operand")
- (match_operand:OI 1 "input_operand"))]
- "0"
-{
- gcc_unreachable ();
-})
-
-;; Vector pair support. POImode can only live in VSRs.
-(define_expand "movpoi"
- [(set (match_operand:POI 0 "nonimmediate_operand")
- (match_operand:POI 1 "input_operand"))]
+;; Vector pair support. OOmode can only live in VSRs.
+(define_expand "movoo"
+ [(set (match_operand:OO 0 "nonimmediate_operand")
+ (match_operand:OO 1 "input_operand"))]
"TARGET_MMA"
{
- rs6000_emit_move (operands[0], operands[1], POImode);
+ rs6000_emit_move (operands[0], operands[1], OOmode);
DONE;
})
-(define_insn_and_split "*movpoi"
- [(set (match_operand:POI 0 "nonimmediate_operand" "=wa,m,wa")
- (match_operand:POI 1 "input_operand" "m,wa,wa"))]
+(define_insn_and_split "*movoo"
+ [(set (match_operand:OO 0 "nonimmediate_operand" "=wa,m,wa")
+ (match_operand:OO 1 "input_operand" "m,wa,wa"))]
"TARGET_MMA
- && (gpc_reg_operand (operands[0], POImode)
- || gpc_reg_operand (operands[1], POImode))"
+ && (gpc_reg_operand (operands[0], OOmode)
+ || gpc_reg_operand (operands[1], OOmode))"
"@
lxvp%X1 %x0,%1
stxvp%X0 %x1,%0
@@ -305,288 +291,361 @@
(set_attr "length" "*,*,8")])
-;; Define a disabled XImode move pattern, so we can use PXImode.
-(define_expand "movxi"
- [(set (match_operand:XI 0 "nonimmediate_operand")
- (match_operand:XI 1 "input_operand"))]
- "0"
-{
- gcc_unreachable ();
-})
-
-;; Vector quad support. PXImode can only live in FPRs.
-(define_expand "movpxi"
- [(set (match_operand:PXI 0 "nonimmediate_operand")
- (match_operand:PXI 1 "input_operand"))]
+;; Vector quad support. XOmode can only live in FPRs.
+(define_expand "movxo"
+ [(set (match_operand:XO 0 "nonimmediate_operand")
+ (match_operand:XO 1 "input_operand"))]
"TARGET_MMA"
{
- rs6000_emit_move (operands[0], operands[1], PXImode);
+ rs6000_emit_move (operands[0], operands[1], XOmode);
DONE;
})
-(define_insn_and_split "*movpxi"
- [(set (match_operand:PXI 0 "nonimmediate_operand" "=d,m,d,d")
- (match_operand:PXI 1 "input_operand" "m,d,d,O"))]
+(define_insn_and_split "*movxo"
+ [(set (match_operand:XO 0 "nonimmediate_operand" "=d,m,d")
+ (match_operand:XO 1 "input_operand" "m,d,d"))]
"TARGET_MMA
- && (gpc_reg_operand (operands[0], PXImode)
- || gpc_reg_operand (operands[1], PXImode))"
+ && (gpc_reg_operand (operands[0], XOmode)
+ || gpc_reg_operand (operands[1], XOmode))"
"@
#
#
- #
- xxsetaccz %A0"
- "&& reload_completed
- && !(fpr_reg_operand (operands[0], PXImode) && operands[1] == const0_rtx)"
+ #"
+ "&& reload_completed"
[(const_int 0)]
{
rs6000_split_multireg_move (operands[0], operands[1]);
DONE;
}
- [(set_attr "type" "vecload,vecstore,veclogical,mma")
- (set_attr "length" "8,8,16,*")
- (set_attr "max_prefixed_insns" "2,2,*,*")])
+ [(set_attr "type" "vecload,vecstore,veclogical")
+ (set_attr "length" "*,*,16")
+ (set_attr "max_prefixed_insns" "2,2,*")])
(define_expand "mma_assemble_pair"
- [(match_operand:POI 0 "vsx_register_operand")
- (match_operand:V16QI 1 "input_operand")
- (match_operand:V16QI 2 "input_operand")]
+ [(match_operand:OO 0 "vsx_register_operand")
+ (match_operand:V16QI 1 "mma_assemble_input_operand")
+ (match_operand:V16QI 2 "mma_assemble_input_operand")]
"TARGET_MMA"
{
- rtx dst;
+ rtx src = gen_rtx_UNSPEC (OOmode,
+ gen_rtvec (2, operands[1], operands[2]),
+ UNSPEC_MMA_ASSEMBLE);
+ emit_move_insn (operands[0], src);
+ DONE;
+})
- /* Let the compiler know the code below fully defines our output value. */
- emit_clobber (operands[0]);
+(define_insn_and_split "*mma_assemble_pair"
+ [(set (match_operand:OO 0 "vsx_register_operand" "=wa")
+ (unspec:OO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
+ (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")]
+ UNSPEC_MMA_ASSEMBLE))]
+ "TARGET_MMA"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx src = gen_rtx_UNSPEC (OOmode,
+ gen_rtvec (2, operands[1], operands[2]),
+ UNSPEC_MMA_ASSEMBLE);
+ rs6000_split_multireg_move (operands[0], src);
+ DONE;
+})
+
+(define_expand "mma_disassemble_pair"
+ [(match_operand:V16QI 0 "mma_disassemble_output_operand")
+ (match_operand:OO 1 "vsx_register_operand")
+ (match_operand 2 "const_0_to_1_operand")]
+ "TARGET_MMA"
+{
+ rtx src;
+ int regoff = INTVAL (operands[2]);
+ src = gen_rtx_UNSPEC (V16QImode,
+ gen_rtvec (2, operands[1], GEN_INT (regoff)),
+ UNSPEC_MMA_EXTRACT);
+ emit_move_insn (operands[0], src);
+ DONE;
+})
- dst = simplify_gen_subreg (V16QImode, operands[0], POImode, 0);
- emit_move_insn (dst, operands[1]);
- dst = simplify_gen_subreg (V16QImode, operands[0], POImode, 16);
- emit_move_insn (dst, operands[2]);
+(define_insn_and_split "*mma_disassemble_pair"
+ [(set (match_operand:V16QI 0 "mma_disassemble_output_operand" "=mwa")
+ (unspec:V16QI [(match_operand:OO 1 "vsx_register_operand" "wa")
+ (match_operand 2 "const_0_to_1_operand")]
+ UNSPEC_MMA_EXTRACT))]
+ "TARGET_MMA
+ && vsx_register_operand (operands[1], OOmode)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ int reg = REGNO (operands[1]);
+ int regoff = INTVAL (operands[2]);
+ rtx src = gen_rtx_REG (V16QImode, reg + regoff);
+ emit_move_insn (operands[0], src);
DONE;
})
(define_expand "mma_assemble_acc"
- [(match_operand:PXI 0 "fpr_reg_operand")
- (match_operand:V16QI 1 "input_operand")
- (match_operand:V16QI 2 "input_operand")
- (match_operand:V16QI 3 "input_operand")
- (match_operand:V16QI 4 "input_operand")]
+ [(match_operand:XO 0 "fpr_reg_operand")
+ (match_operand:V16QI 1 "mma_assemble_input_operand")
+ (match_operand:V16QI 2 "mma_assemble_input_operand")
+ (match_operand:V16QI 3 "mma_assemble_input_operand")
+ (match_operand:V16QI 4 "mma_assemble_input_operand")]
"TARGET_MMA"
{
- rtx src = gen_rtx_UNSPEC (PXImode,
+ rtx src = gen_rtx_UNSPEC (XOmode,
gen_rtvec (4, operands[1], operands[2],
operands[3], operands[4]),
- UNSPEC_MMA_ASSEMBLE_ACC);
+ UNSPEC_MMA_ASSEMBLE);
emit_move_insn (operands[0], src);
DONE;
})
(define_insn_and_split "*mma_assemble_acc"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=d")
- (unspec:PXI [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
- (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")
- (match_operand:V16QI 3 "mma_assemble_input_operand" "mwa")
- (match_operand:V16QI 4 "mma_assemble_input_operand" "mwa")]
- UNSPEC_MMA_ASSEMBLE_ACC))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=d")
+ (unspec:XO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
+ (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")
+ (match_operand:V16QI 3 "mma_assemble_input_operand" "mwa")
+ (match_operand:V16QI 4 "mma_assemble_input_operand" "mwa")]
+ UNSPEC_MMA_ASSEMBLE))]
"TARGET_MMA
- && fpr_reg_operand (operands[0], PXImode)"
+ && fpr_reg_operand (operands[0], XOmode)"
"#"
"&& reload_completed"
[(const_int 0)]
{
- rtx src = gen_rtx_UNSPEC (PXImode,
+ rtx src = gen_rtx_UNSPEC (XOmode,
gen_rtvec (4, operands[1], operands[2],
operands[3], operands[4]),
- UNSPEC_MMA_ASSEMBLE_ACC);
+ UNSPEC_MMA_ASSEMBLE);
rs6000_split_multireg_move (operands[0], src);
DONE;
})
+(define_expand "mma_disassemble_acc"
+ [(match_operand:V16QI 0 "mma_disassemble_output_operand")
+ (match_operand:XO 1 "fpr_reg_operand")
+ (match_operand 2 "const_0_to_3_operand")]
+ "TARGET_MMA"
+{
+ rtx src;
+ int regoff = INTVAL (operands[2]);
+ src = gen_rtx_UNSPEC (V16QImode,
+ gen_rtvec (2, operands[1], GEN_INT (regoff)),
+ UNSPEC_MMA_EXTRACT);
+ emit_move_insn (operands[0], src);
+ DONE;
+})
+
+(define_insn_and_split "*mma_disassemble_acc"
+ [(set (match_operand:V16QI 0 "mma_disassemble_output_operand" "=mwa")
+ (unspec:V16QI [(match_operand:XO 1 "fpr_reg_operand" "d")
+ (match_operand 2 "const_0_to_3_operand")]
+ UNSPEC_MMA_EXTRACT))]
+ "TARGET_MMA
+ && fpr_reg_operand (operands[1], XOmode)"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ int reg = REGNO (operands[1]);
+ int regoff = INTVAL (operands[2]);
+ rtx src = gen_rtx_REG (V16QImode, reg + regoff);
+ emit_move_insn (operands[0], src);
+ DONE;
+})
+
;; MMA instructions that do not use their accumulators as an input, still
;; must not allow their vector operands to overlap the registers used by
;; the accumulator. We enforce this by marking the output as early clobber.
(define_insn "mma_<acc>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")]
MMA_ACC))]
"TARGET_MMA"
"<acc> %A0"
[(set_attr "type" "mma")])
+;; We can't have integer constants in XOmode so we wrap this in an UNSPEC.
+
(define_expand "mma_xxsetaccz"
- [(set (match_operand:PXI 0 "fpr_reg_operand")
+ [(set (match_operand:XO 0 "fpr_reg_operand")
(const_int 0))]
"TARGET_MMA"
{
- emit_insn (gen_movpxi (operands[0], const0_rtx));
+ rtx xo0 = gen_rtx_UNSPEC (XOmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_MMA_XXSETACCZ);
+ emit_insn (gen_rtx_SET (operands[0], xo0));
DONE;
})
+(define_insn_and_split "*mma_xxsetaccz"
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=d")
+ (unspec:XO [(match_operand 1 "const_0_to_1_operand" "O")]
+ UNSPEC_MMA_XXSETACCZ))]
+ "TARGET_MMA"
+ "xxsetaccz %A0"
+ "&& reload_completed"
+ [(set (match_dup 0) (unspec:XO [(match_dup 1)] UNSPEC_MMA_XXSETACCZ))]
+ ""
+ [(set_attr "type" "mma")
+ (set_attr "length" "4")])
+
(define_insn "mma_<vv>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")]
- MMA_VV))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")]
+ MMA_VV))]
"TARGET_MMA"
"<vv> %A0,%x1,%x2"
[(set_attr "type" "mma")])
(define_insn "mma_<avv>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")]
- MMA_AVV))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")]
+ MMA_AVV))]
"TARGET_MMA"
"<avv> %A0,%x2,%x3"
[(set_attr "type" "mma")])
(define_insn "mma_<pv>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:POI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")]
- MMA_PV))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:OO 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")]
+ MMA_PV))]
"TARGET_MMA"
"<pv> %A0,%x1,%x2"
[(set_attr "type" "mma")])
(define_insn "mma_<apv>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:POI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")]
- MMA_APV))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:OO 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")]
+ MMA_APV))]
"TARGET_MMA"
"<apv> %A0,%x2,%x3"
[(set_attr "type" "mma")])
(define_insn "mma_<vvi4i4i8>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:SI 3 "const_0_to_15_operand" "n")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "u8bit_cint_operand" "n")]
- MMA_VVI4I4I8))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:SI 3 "const_0_to_15_operand" "n")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "u8bit_cint_operand" "n")]
+ MMA_VVI4I4I8))]
"TARGET_MMA"
"<vvi4i4i8> %A0,%x1,%x2,%3,%4,%5"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<avvi4i4i8>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_15_operand" "n")
- (match_operand:SI 6 "u8bit_cint_operand" "n")]
- MMA_AVVI4I4I8))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_15_operand" "n")
+ (match_operand:SI 6 "u8bit_cint_operand" "n")]
+ MMA_AVVI4I4I8))]
"TARGET_MMA"
"<avvi4i4i8> %A0,%x2,%x3,%4,%5,%6"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<vvi4i4i2>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:SI 3 "const_0_to_15_operand" "n")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_3_operand" "n")]
- MMA_VVI4I4I2))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:SI 3 "const_0_to_15_operand" "n")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_3_operand" "n")]
+ MMA_VVI4I4I2))]
"TARGET_MMA"
"<vvi4i4i2> %A0,%x1,%x2,%3,%4,%5"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<avvi4i4i2>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_15_operand" "n")
- (match_operand:SI 6 "const_0_to_3_operand" "n")]
- MMA_AVVI4I4I2))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_15_operand" "n")
+ (match_operand:SI 6 "const_0_to_3_operand" "n")]
+ MMA_AVVI4I4I2))]
"TARGET_MMA"
"<avvi4i4i2> %A0,%x2,%x3,%4,%5,%6"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<vvi4i4>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:SI 3 "const_0_to_15_operand" "n")
- (match_operand:SI 4 "const_0_to_15_operand" "n")]
- MMA_VVI4I4))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:SI 3 "const_0_to_15_operand" "n")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")]
+ MMA_VVI4I4))]
"TARGET_MMA"
"<vvi4i4> %A0,%x1,%x2,%3,%4"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<avvi4i4>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_15_operand" "n")]
- MMA_AVVI4I4))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_15_operand" "n")]
+ MMA_AVVI4I4))]
"TARGET_MMA"
"<avvi4i4> %A0,%x2,%x3,%4,%5"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<pvi4i2>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:POI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:SI 3 "const_0_to_15_operand" "n")
- (match_operand:SI 4 "const_0_to_3_operand" "n")]
- MMA_PVI4I2))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:OO 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:SI 3 "const_0_to_15_operand" "n")
+ (match_operand:SI 4 "const_0_to_3_operand" "n")]
+ MMA_PVI4I2))]
"TARGET_MMA"
"<pvi4i2> %A0,%x1,%x2,%3,%4"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<apvi4i2>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:POI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_3_operand" "n")]
- MMA_APVI4I2))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:OO 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_3_operand" "n")]
+ MMA_APVI4I2))]
"TARGET_MMA"
"<apvi4i2> %A0,%x2,%x3,%4,%5"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<vvi4i4i4>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:SI 3 "const_0_to_15_operand" "n")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_15_operand" "n")]
- MMA_VVI4I4I4))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:SI 3 "const_0_to_15_operand" "n")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_15_operand" "n")]
+ MMA_VVI4I4I4))]
"TARGET_MMA"
"<vvi4i4i4> %A0,%x1,%x2,%3,%4,%5"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
(define_insn "mma_<avvi4i4i4>"
- [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d")
- (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")
- (match_operand:V16QI 2 "vsx_register_operand" "wa")
- (match_operand:V16QI 3 "vsx_register_operand" "wa")
- (match_operand:SI 4 "const_0_to_15_operand" "n")
- (match_operand:SI 5 "const_0_to_15_operand" "n")
- (match_operand:SI 6 "const_0_to_15_operand" "n")]
- MMA_AVVI4I4I4))]
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")
+ (match_operand:V16QI 2 "vsx_register_operand" "wa")
+ (match_operand:V16QI 3 "vsx_register_operand" "wa")
+ (match_operand:SI 4 "const_0_to_15_operand" "n")
+ (match_operand:SI 5 "const_0_to_15_operand" "n")
+ (match_operand:SI 6 "const_0_to_15_operand" "n")]
+ MMA_AVVI4I4I4))]
"TARGET_MMA"
"<avvi4i4i4> %A0,%x2,%x3,%4,%5,%6"
- [(set_attr "type" "mma")
- (set_attr "length" "8")])
+ [(set_attr "type" "mma")])
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 4c2fe7f..9ad5ae6 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1144,6 +1144,18 @@
(match_test "(mode == V16QImode
&& (vsx_register_operand (op, mode) || MEM_P (op)))"))
+;; Return 1 if this operand is valid for an MMA disassemble insn.
+(define_predicate "mma_disassemble_output_operand"
+ (match_code "reg,subreg,mem")
+{
+ if (SUBREG_P (op))
+ op = SUBREG_REG (op);
+ if (!REG_P (op))
+ return true;
+
+ return vsx_register_operand (op, mode);
+})
+
;; Return true if operand is an operator used in rotate-and-mask instructions.
(define_predicate "rotate_mask_operator"
(match_code "rotate,ashift,lshiftrt"))
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 5b05da8..47b1f74 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -352,7 +352,7 @@
| RS6000_BTC_UNARY), \
CODE_FOR_ ## ICODE) /* ICODE */
-#define BU_MMA_V2(ENUM, NAME, ATTR, ICODE) \
+#define BU_MMA_2(ENUM, NAME, ATTR, ICODE) \
RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \
"__builtin_mma_" NAME, /* NAME */ \
RS6000_BTM_MMA, /* MASK */ \
@@ -360,7 +360,13 @@
| RS6000_BTC_BINARY \
| RS6000_BTC_VOID \
| RS6000_BTC_GIMPLE), \
- CODE_FOR_nothing) /* ICODE */
+ CODE_FOR_nothing) /* ICODE */ \
+ RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM ## _INTERNAL, /* ENUM */ \
+ "__builtin_mma_" NAME "_internal", /* NAME */ \
+ RS6000_BTM_MMA, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
#define BU_MMA_3(ENUM, NAME, ATTR, ICODE) \
RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \
@@ -696,6 +702,14 @@
/* Miscellaneous builtins for instructions added in ISA 2.07. These
instructions do require the ISA 2.07 vector support, but they aren't vector
instructions. */
+#define BU_P8V_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_P8_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
#define BU_P8V_MISC_3(ENUM, NAME, ATTR, ICODE) \
RS6000_BUILTIN_3 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
"__builtin_" NAME, /* NAME */ \
@@ -2668,16 +2682,55 @@ BU_P7_MISC_1 (CBCDTD, "cbcdtd", CONST, cbcdtd)
BU_P7_MISC_2 (ADDG6S, "addg6s", CONST, addg6s)
/* 3 argument BCD functions added in ISA 2.07. */
-BU_P8V_MISC_3 (BCDADD, "bcdadd", CONST, bcdadd)
-BU_P8V_MISC_3 (BCDADD_LT, "bcdadd_lt", CONST, bcdadd_lt)
-BU_P8V_MISC_3 (BCDADD_EQ, "bcdadd_eq", CONST, bcdadd_eq)
-BU_P8V_MISC_3 (BCDADD_GT, "bcdadd_gt", CONST, bcdadd_gt)
-BU_P8V_MISC_3 (BCDADD_OV, "bcdadd_ov", CONST, bcdadd_unordered)
-BU_P8V_MISC_3 (BCDSUB, "bcdsub", CONST, bcdsub)
-BU_P8V_MISC_3 (BCDSUB_LT, "bcdsub_lt", CONST, bcdsub_lt)
-BU_P8V_MISC_3 (BCDSUB_EQ, "bcdsub_eq", CONST, bcdsub_eq)
-BU_P8V_MISC_3 (BCDSUB_GT, "bcdsub_gt", CONST, bcdsub_gt)
-BU_P8V_MISC_3 (BCDSUB_OV, "bcdsub_ov", CONST, bcdsub_unordered)
+BU_P8V_MISC_3 (BCDADD_V1TI, "bcdadd_v1ti", CONST, bcdadd_v1ti)
+BU_P8V_MISC_3 (BCDADD_V16QI, "bcdadd_v16qi", CONST, bcdadd_v16qi)
+BU_P8V_MISC_3 (BCDADD_LT_V1TI, "bcdadd_lt_v1ti", CONST, bcdadd_lt_v1ti)
+BU_P8V_MISC_3 (BCDADD_LT_V16QI, "bcdadd_lt_v16qi", CONST, bcdadd_lt_v16qi)
+BU_P8V_MISC_3 (BCDADD_EQ_V1TI, "bcdadd_eq_v1ti", CONST, bcdadd_eq_v1ti)
+BU_P8V_MISC_3 (BCDADD_EQ_V16QI, "bcdadd_eq_v16qi", CONST, bcdadd_eq_v16qi)
+BU_P8V_MISC_3 (BCDADD_GT_V1TI, "bcdadd_gt_v1ti", CONST, bcdadd_gt_v1ti)
+BU_P8V_MISC_3 (BCDADD_GT_V16QI, "bcdadd_gt_v16qi", CONST, bcdadd_gt_v16qi)
+BU_P8V_MISC_3 (BCDADD_OV_V1TI, "bcdadd_ov_v1ti", CONST, bcdadd_unordered_v1ti)
+BU_P8V_MISC_3 (BCDADD_OV_V16QI, "bcdadd_ov_v16qi", CONST, bcdadd_unordered_v16qi)
+
+BU_P8V_MISC_3 (BCDSUB_V1TI, "bcdsub_v1ti", CONST, bcdsub_v1ti)
+BU_P8V_MISC_3 (BCDSUB_V16QI, "bcdsub_v16qi", CONST, bcdsub_v16qi)
+BU_P8V_MISC_3 (BCDSUB_LT_V1TI, "bcdsub_lt_v1ti", CONST, bcdsub_lt_v1ti)
+BU_P8V_MISC_3 (BCDSUB_LT_V16QI, "bcdsub_lt_v16qi", CONST, bcdsub_lt_v16qi)
+BU_P8V_MISC_3 (BCDSUB_LE_V1TI, "bcdsub_le_v1ti", CONST, bcdsub_le_v1ti)
+BU_P8V_MISC_3 (BCDSUB_LE_V16QI, "bcdsub_le_v16qi", CONST, bcdsub_le_v16qi)
+BU_P8V_MISC_3 (BCDSUB_EQ_V1TI, "bcdsub_eq_v1ti", CONST, bcdsub_eq_v1ti)
+BU_P8V_MISC_3 (BCDSUB_EQ_V16QI, "bcdsub_eq_v16qi", CONST, bcdsub_eq_v16qi)
+BU_P8V_MISC_3 (BCDSUB_GT_V1TI, "bcdsub_gt_v1ti", CONST, bcdsub_gt_v1ti)
+BU_P8V_MISC_3 (BCDSUB_GT_V16QI, "bcdsub_gt_v16qi", CONST, bcdsub_gt_v16qi)
+BU_P8V_MISC_3 (BCDSUB_GE_V1TI, "bcdsub_ge_v1ti", CONST, bcdsub_ge_v1ti)
+BU_P8V_MISC_3 (BCDSUB_GE_V16QI, "bcdsub_ge_v16qi", CONST, bcdsub_ge_v16qi)
+BU_P8V_MISC_3 (BCDSUB_OV_V1TI, "bcdsub_ov_v1ti", CONST, bcdsub_unordered_v1ti)
+BU_P8V_MISC_3 (BCDSUB_OV_V16QI, "bcdsub_ov_v16qi", CONST, bcdsub_unordered_v16qi)
+
+BU_P8V_MISC_1 (BCDINVALID_V1TI, "bcdinvalid_v1ti", CONST, bcdinvalid_v1ti)
+BU_P8V_MISC_1 (BCDINVALID_V16QI, "bcdinvalid_v16qi", CONST, bcdinvalid_v16qi)
+
+BU_P9V_AV_1 (BCDMUL10_V16QI, "bcdmul10_v16qi", CONST, bcdmul10_v16qi)
+BU_P9V_AV_1 (BCDDIV10_V16QI, "bcddiv10_v16qi", CONST, bcddiv10_v16qi)
+BU_P8V_MISC_1 (DENBCD_V16QI, "denb2dfp_v16qi", CONST, dfp_denbcd_v16qi)
+
+BU_P8V_OVERLOAD_3 (BCDADD, "bcdadd")
+BU_P8V_OVERLOAD_3 (BCDADD_LT, "bcdadd_lt")
+BU_P8V_OVERLOAD_3 (BCDADD_EQ, "bcdadd_eq")
+BU_P8V_OVERLOAD_3 (BCDADD_GT, "bcdadd_gt")
+BU_P8V_OVERLOAD_3 (BCDADD_OV, "bcdadd_ov")
+BU_P8V_OVERLOAD_3 (BCDSUB, "bcdsub")
+BU_P8V_OVERLOAD_3 (BCDSUB_LT, "bcdsub_lt")
+BU_P8V_OVERLOAD_3 (BCDSUB_LE, "bcdsub_le")
+BU_P8V_OVERLOAD_3 (BCDSUB_EQ, "bcdsub_eq")
+BU_P8V_OVERLOAD_3 (BCDSUB_GT, "bcdsub_gt")
+BU_P8V_OVERLOAD_3 (BCDSUB_GE, "bcdsub_ge")
+BU_P8V_OVERLOAD_3 (BCDSUB_OV, "bcdsub_ov")
+BU_P8V_OVERLOAD_1 (BCDINVALID, "bcdinvalid")
+BU_P9V_OVERLOAD_1 (BCDMUL10, "bcdmul10")
+BU_P9V_OVERLOAD_1 (BCDDIV10, "bcddiv10")
+BU_P8V_OVERLOAD_1 (DENBCD, "denb2dfp")
/* 2 argument pack/unpack 128-bit floating point types. */
BU_DFP_MISC_2 (PACK_TD, "pack_dec128", CONST, packtd)
@@ -3061,8 +3114,8 @@ BU_MMA_1 (XXMFACC, "xxmfacc", QUAD, mma_xxmfacc)
BU_MMA_1 (XXMTACC, "xxmtacc", QUAD, mma_xxmtacc)
BU_MMA_1 (XXSETACCZ, "xxsetaccz", MISC, mma_xxsetaccz)
-BU_MMA_V2 (DISASSEMBLE_ACC, "disassemble_acc", QUAD, nothing)
-BU_MMA_V2 (DISASSEMBLE_PAIR,"disassemble_pair", PAIR, nothing)
+BU_MMA_2 (DISASSEMBLE_ACC, "disassemble_acc", QUAD, mma_disassemble_acc)
+BU_MMA_2 (DISASSEMBLE_PAIR,"disassemble_pair", PAIR, mma_disassemble_pair)
BU_MMA_3 (ASSEMBLE_PAIR, "assemble_pair", MISC, mma_assemble_pair)
BU_MMA_3 (XVBF16GER2, "xvbf16ger2", MISC, mma_xvbf16ger2)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index b044778..45bc048 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -985,6 +985,82 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
{ ALTIVEC_BUILTIN_VEC_CTU, VSX_BUILTIN_XVCVDPUXDS_SCALE,
RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DF, RS6000_BTI_INTSI, 0 },
+
+ { P8V_BUILTIN_VEC_BCDADD, MISC_BUILTIN_BCDADD_V1TI,
+ RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD, MISC_BUILTIN_BCDADD_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_LT, MISC_BUILTIN_BCDADD_LT_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_LT, MISC_BUILTIN_BCDADD_LT_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_EQ, MISC_BUILTIN_BCDADD_EQ_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_EQ, MISC_BUILTIN_BCDADD_EQ_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_GT, MISC_BUILTIN_BCDADD_GT_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_GT, MISC_BUILTIN_BCDADD_GT_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_OV, MISC_BUILTIN_BCDADD_OV_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDADD_OV, MISC_BUILTIN_BCDADD_OV_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDINVALID, MISC_BUILTIN_BCDINVALID_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, 0, 0 },
+ { P8V_BUILTIN_VEC_BCDINVALID, MISC_BUILTIN_BCDINVALID_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_BCDMUL10, P9V_BUILTIN_BCDMUL10_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+ { P9V_BUILTIN_VEC_BCDDIV10, P9V_BUILTIN_BCDDIV10_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+ { P8V_BUILTIN_VEC_DENBCD, MISC_BUILTIN_DENBCD_V16QI,
+ RS6000_BTI_dfloat128, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+ { P8V_BUILTIN_VEC_BCDSUB, MISC_BUILTIN_BCDSUB_V1TI,
+ RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB, MISC_BUILTIN_BCDSUB_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_LT, MISC_BUILTIN_BCDSUB_LT_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_LT, MISC_BUILTIN_BCDSUB_LT_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_LE, MISC_BUILTIN_BCDSUB_LE_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_LE, MISC_BUILTIN_BCDSUB_LE_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_EQ, MISC_BUILTIN_BCDSUB_EQ_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_EQ, MISC_BUILTIN_BCDSUB_EQ_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_GT, MISC_BUILTIN_BCDSUB_GT_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_GT, MISC_BUILTIN_BCDSUB_GT_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_GE, MISC_BUILTIN_BCDSUB_GE_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_GE, MISC_BUILTIN_BCDSUB_GE_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_OV, MISC_BUILTIN_BCDSUB_OV_V1TI,
+ RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+ { P8V_BUILTIN_VEC_BCDSUB_OV, MISC_BUILTIN_BCDSUB_OV_V16QI,
+ RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+
+
{ VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVSP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVDP,
@@ -6249,6 +6325,22 @@ rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type,
bool
rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
+ /* We do not allow MMA types being used as return values. Only report
+ the invalid return value usage the first time we encounter it. */
+ if (cfun
+ && !cfun->machine->mma_return_type_error
+ && TREE_TYPE (cfun->decl) == fntype
+ && (TYPE_MODE (type) == OOmode || TYPE_MODE (type) == XOmode))
+ {
+ /* Record we have now handled function CFUN, so the next time we
+ are called, we do not re-report the same error. */
+ cfun->machine->mma_return_type_error = true;
+ if (TYPE_CANONICAL (type) != NULL_TREE)
+ type = TYPE_CANONICAL (type);
+ error ("invalid use of MMA type %qs as a function return value",
+ IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+ }
+
/* For the Darwin64 ABI, test if we can fit the return value in regs. */
if (TARGET_MACHO
&& rs6000_darwin64_abi
@@ -6501,30 +6593,8 @@ machine_mode
rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
machine_mode mode,
int *punsignedp ATTRIBUTE_UNUSED,
- const_tree, int for_return)
+ const_tree, int for_return ATTRIBUTE_UNUSED)
{
- /* Warning: this is a static local variable and not always NULL!
- This function is called multiple times for the same function
- and return value. PREV_FUNC is used to keep track of the
- first time we encounter a function's return value in order
- to not report an error with that return value multiple times. */
- static struct function *prev_func = NULL;
-
- /* We do not allow MMA types being used as return values. Only report
- the invalid return value usage the first time we encounter it. */
- if (for_return
- && prev_func != cfun
- && (mode == POImode || mode == PXImode))
- {
- /* Record we have now handled function CFUN, so the next time we
- are called, we do not re-report the same error. */
- prev_func = cfun;
- if (TYPE_CANONICAL (type) != NULL_TREE)
- type = TYPE_CANONICAL (type);
- error ("invalid use of MMA type %qs as a function return value",
- IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
- }
-
PROMOTE_MODE (mode, *punsignedp, type);
return mode;
@@ -7476,7 +7546,7 @@ rs6000_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
int n_elts;
/* We do not allow MMA types being used as function arguments. */
- if (mode == POImode || mode == PXImode)
+ if (mode == OOmode || mode == XOmode)
{
if (TYPE_CANONICAL (type) != NULL_TREE)
type = TYPE_CANONICAL (type);
@@ -9997,7 +10067,8 @@ mma_expand_builtin (tree exp, rtx target, bool *expandedp)
}
unsigned attr_args = attr & RS6000_BTC_OPND_MASK;
- if (attr & RS6000_BTC_QUAD)
+ if (attr & RS6000_BTC_QUAD
+ || fcode == MMA_BUILTIN_DISASSEMBLE_PAIR_INTERNAL)
attr_args++;
gcc_assert (nopnds == attr_args);
@@ -10570,14 +10641,22 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
}
else if (icode == CODE_FOR_vsx_set_v2df
|| icode == CODE_FOR_vsx_set_v2di
- || icode == CODE_FOR_bcdadd
- || icode == CODE_FOR_bcdadd_lt
- || icode == CODE_FOR_bcdadd_eq
- || icode == CODE_FOR_bcdadd_gt
- || icode == CODE_FOR_bcdsub
- || icode == CODE_FOR_bcdsub_lt
- || icode == CODE_FOR_bcdsub_eq
- || icode == CODE_FOR_bcdsub_gt)
+ || icode == CODE_FOR_bcdadd_v16qi
+ || icode == CODE_FOR_bcdadd_v1ti
+ || icode == CODE_FOR_bcdadd_lt_v16qi
+ || icode == CODE_FOR_bcdadd_lt_v1ti
+ || icode == CODE_FOR_bcdadd_eq_v16qi
+ || icode == CODE_FOR_bcdadd_eq_v1ti
+ || icode == CODE_FOR_bcdadd_gt_v16qi
+ || icode == CODE_FOR_bcdadd_gt_v1ti
+ || icode == CODE_FOR_bcdsub_v16qi
+ || icode == CODE_FOR_bcdsub_v1ti
+ || icode == CODE_FOR_bcdsub_lt_v16qi
+ || icode == CODE_FOR_bcdsub_lt_v1ti
+ || icode == CODE_FOR_bcdsub_eq_v16qi
+ || icode == CODE_FOR_bcdsub_eq_v1ti
+ || icode == CODE_FOR_bcdsub_gt_v16qi
+ || icode == CODE_FOR_bcdsub_gt_v1ti)
{
/* Only allow 1-bit unsigned literals. */
STRIP_NOPS (arg2);
@@ -10601,7 +10680,8 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
}
}
else if (icode == CODE_FOR_dfp_denbcd_dd
- || icode == CODE_FOR_dfp_denbcd_td)
+ || icode == CODE_FOR_dfp_denbcd_td
+ || icode == CODE_FOR_dfp_denbcd_v16qi)
{
/* Only allow 1-bit unsigned literals. */
STRIP_NOPS (arg0);
@@ -10810,7 +10890,7 @@ altivec_expand_vec_set_builtin (tree exp)
op0 = force_reg (tmode, op0);
op1 = force_reg (mode1, op1);
- rs6000_expand_vector_set (op0, op1, elt);
+ rs6000_expand_vector_set (op0, op1, GEN_INT (elt));
return op0;
}
@@ -11602,23 +11682,24 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi)
gimple *new_call;
tree new_decl;
- if (rs6000_builtin_info[fncode + 1].icode == CODE_FOR_nothing)
+ if (fncode == MMA_BUILTIN_DISASSEMBLE_ACC
+ || fncode == MMA_BUILTIN_DISASSEMBLE_PAIR)
{
/* This is an MMA disassemble built-in function. */
- gcc_assert (fncode == MMA_BUILTIN_DISASSEMBLE_ACC
- || fncode == MMA_BUILTIN_DISASSEMBLE_PAIR);
-
push_gimplify_context (true);
+ unsigned nvec = (fncode == MMA_BUILTIN_DISASSEMBLE_ACC) ? 4 : 2;
tree dst_ptr = gimple_call_arg (stmt, 0);
tree src_ptr = gimple_call_arg (stmt, 1);
tree src_type = TREE_TYPE (src_ptr);
tree src = make_ssa_name (TREE_TYPE (src_type));
gimplify_assign (src, build_simple_mem_ref (src_ptr), &new_seq);
- /* If we are not disassembling an accumulator or our destination is
- another accumulator, then just copy the entire thing as is. */
- if (fncode != MMA_BUILTIN_DISASSEMBLE_ACC
- || TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_quad_type_node)
+ /* If we are not disassembling an accumulator/pair or our destination is
+ another accumulator/pair, then just copy the entire thing as is. */
+ if ((fncode == MMA_BUILTIN_DISASSEMBLE_ACC
+ && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_quad_type_node)
+ || (fncode == MMA_BUILTIN_DISASSEMBLE_PAIR
+ && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_pair_type_node))
{
tree dst = build_simple_mem_ref (build1 (VIEW_CONVERT_EXPR,
src_type, dst_ptr));
@@ -11628,29 +11709,33 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi)
return true;
}
- /* We're disassembling an accumulator into a different type, so we need
+ /* If we're disassembling an accumulator into a different type, we need
to emit a xxmfacc instruction now, since we cannot do it later. */
- new_decl = rs6000_builtin_decls[MMA_BUILTIN_XXMFACC_INTERNAL];
- new_call = gimple_build_call (new_decl, 1, src);
- src = make_ssa_name (vector_quad_type_node);
- gimple_call_set_lhs (new_call, src);
- gimple_seq_add_stmt (&new_seq, new_call);
+ if (fncode == MMA_BUILTIN_DISASSEMBLE_ACC)
+ {
+ new_decl = rs6000_builtin_decls[MMA_BUILTIN_XXMFACC_INTERNAL];
+ new_call = gimple_build_call (new_decl, 1, src);
+ src = make_ssa_name (vector_quad_type_node);
+ gimple_call_set_lhs (new_call, src);
+ gimple_seq_add_stmt (&new_seq, new_call);
+ }
- /* Copy the accumulator vector by vector. */
+ /* Copy the accumulator/pair vector by vector. */
+ new_decl = rs6000_builtin_decls[fncode + 1];
tree dst_type = build_pointer_type_for_mode (unsigned_V16QI_type_node,
ptr_mode, true);
tree dst_base = build1 (VIEW_CONVERT_EXPR, dst_type, dst_ptr);
- tree array_type = build_array_type_nelts (unsigned_V16QI_type_node, 4);
- tree src_array = build1 (VIEW_CONVERT_EXPR, array_type, src);
- for (unsigned i = 0; i < 4; i++)
+ for (unsigned i = 0; i < nvec; i++)
{
- unsigned index = WORDS_BIG_ENDIAN ? i : 3 - i;
- tree ref = build4 (ARRAY_REF, unsigned_V16QI_type_node, src_array,
- build_int_cst (size_type_node, i),
- NULL_TREE, NULL_TREE);
+ unsigned index = WORDS_BIG_ENDIAN ? i : nvec - 1 - i;
tree dst = build2 (MEM_REF, unsigned_V16QI_type_node, dst_base,
build_int_cst (dst_type, index * 16));
- gimplify_assign (dst, ref, &new_seq);
+ tree dstssa = make_ssa_name (unsigned_V16QI_type_node);
+ new_call = gimple_build_call (new_decl, 2, src,
+ build_int_cstu (uint16_type_node, i));
+ gimple_call_set_lhs (new_call, dstssa);
+ gimple_seq_add_stmt (&new_seq, new_call);
+ gimplify_assign (dst, dstssa, &new_seq);
}
pop_gimplify_context (NULL);
gsi_replace_with_seq (gsi, new_seq, true);
@@ -12723,6 +12808,22 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break;
case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break;
case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break;
+
+ case CODE_FOR_xscmpexpqp_eq_kf:
+ icode = CODE_FOR_xscmpexpqp_eq_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_lt_kf:
+ icode = CODE_FOR_xscmpexpqp_lt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_gt_kf:
+ icode = CODE_FOR_xscmpexpqp_gt_tf;
+ break;
+
+ case CODE_FOR_xscmpexpqp_unordered_kf:
+ icode = CODE_FOR_xscmpexpqp_unordered_tf;
+ break;
}
if (TARGET_DEBUG_BUILTIN)
@@ -13105,15 +13206,23 @@ rs6000_init_builtins (void)
/* Vector pair and vector quad support. */
if (TARGET_EXTRA_BUILTINS)
{
- vector_pair_type_node = make_unsigned_type (256);
- SET_TYPE_MODE (vector_pair_type_node, POImode);
- layout_type (vector_pair_type_node);
+ vector_pair_type_node = make_node (OPAQUE_TYPE);
+ SET_TYPE_MODE (vector_pair_type_node, OOmode);
+ TYPE_SIZE (vector_pair_type_node) = bitsize_int (GET_MODE_BITSIZE (OOmode));
+ TYPE_PRECISION (vector_pair_type_node) = GET_MODE_BITSIZE (OOmode);
+ TYPE_SIZE_UNIT (vector_pair_type_node) = size_int (GET_MODE_SIZE (OOmode));
+ SET_TYPE_ALIGN (vector_pair_type_node, 256);
+ TYPE_USER_ALIGN (vector_pair_type_node) = 0;
lang_hooks.types.register_builtin_type (vector_pair_type_node,
"__vector_pair");
- vector_quad_type_node = make_unsigned_type (512);
- SET_TYPE_MODE (vector_quad_type_node, PXImode);
- layout_type (vector_quad_type_node);
+ vector_quad_type_node = make_node (OPAQUE_TYPE);
+ SET_TYPE_MODE (vector_quad_type_node, XOmode);
+ TYPE_SIZE (vector_quad_type_node) = bitsize_int (GET_MODE_BITSIZE (XOmode));
+ TYPE_PRECISION (vector_quad_type_node) = GET_MODE_BITSIZE (XOmode);
+ TYPE_SIZE_UNIT (vector_quad_type_node) = size_int (GET_MODE_SIZE (XOmode));
+ SET_TYPE_ALIGN (vector_quad_type_node, 512);
+ TYPE_USER_ALIGN (vector_quad_type_node) = 0;
lang_hooks.types.register_builtin_type (vector_quad_type_node,
"__vector_quad");
}
@@ -13149,8 +13258,8 @@ rs6000_init_builtins (void)
builtin_mode_to_type[V8HImode][1] = unsigned_V8HI_type_node;
builtin_mode_to_type[V16QImode][0] = V16QI_type_node;
builtin_mode_to_type[V16QImode][1] = unsigned_V16QI_type_node;
- builtin_mode_to_type[POImode][1] = vector_pair_type_node;
- builtin_mode_to_type[PXImode][1] = vector_quad_type_node;
+ builtin_mode_to_type[OOmode][1] = vector_pair_type_node;
+ builtin_mode_to_type[XOmode][1] = vector_quad_type_node;
tdecl = add_builtin_type ("__bool char", bool_char_type_node);
TYPE_NAME (bool_char_type_node) = tdecl;
@@ -13962,21 +14071,21 @@ mma_init_builtins (void)
}
else
{
- if ((attr & RS6000_BTC_QUAD) == 0)
+ if (!(d->code == MMA_BUILTIN_DISASSEMBLE_ACC_INTERNAL
+ || d->code == MMA_BUILTIN_DISASSEMBLE_PAIR_INTERNAL)
+ && (attr & RS6000_BTC_QUAD) == 0)
attr_args--;
/* Ensure we have the correct number and type of operands. */
gcc_assert (attr_args == insn_data[icode].n_operands - 1);
}
- if (icode == CODE_FOR_nothing)
+ /* This is a disassemble pair/acc function. */
+ if (d->code == MMA_BUILTIN_DISASSEMBLE_ACC
+ || d->code == MMA_BUILTIN_DISASSEMBLE_PAIR)
{
- /* This is a disassemble MMA built-in function. */
- gcc_assert (attr_args == RS6000_BTC_BINARY
- && (d->code == MMA_BUILTIN_DISASSEMBLE_ACC
- || d->code == MMA_BUILTIN_DISASSEMBLE_PAIR));
op[nopnds++] = build_pointer_type (void_type_node);
- if (attr & RS6000_BTC_QUAD)
+ if (d->code == MMA_BUILTIN_DISASSEMBLE_ACC)
op[nopnds++] = build_pointer_type (vector_quad_type_node);
else
op[nopnds++] = build_pointer_type (vector_pair_type_node);
@@ -13984,13 +14093,17 @@ mma_init_builtins (void)
else
{
/* This is a normal MMA built-in function. */
- unsigned j = (attr & RS6000_BTC_QUAD) ? 1 : 0;
+ unsigned j = 0;
+ if (attr & RS6000_BTC_QUAD
+ && d->code != MMA_BUILTIN_DISASSEMBLE_ACC_INTERNAL
+ && d->code != MMA_BUILTIN_DISASSEMBLE_PAIR_INTERNAL)
+ j = 1;
for (; j < (unsigned) insn_data[icode].n_operands; j++)
{
machine_mode mode = insn_data[icode].operand[j].mode;
- if (gimple_func && mode == PXImode)
+ if (gimple_func && mode == XOmode)
op[nopnds++] = build_pointer_type (vector_quad_type_node);
- else if (gimple_func && mode == POImode
+ else if (gimple_func && mode == OOmode
&& d->code == MMA_BUILTIN_ASSEMBLE_PAIR)
op[nopnds++] = build_pointer_type (vector_pair_type_node);
else
@@ -14622,7 +14735,7 @@ rs6000_common_init_builtins (void)
continue;
}
- if (icode == CODE_FOR_nothing)
+ if (icode == CODE_FOR_nothing)
{
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "rs6000_builtin, skip ternary %s (no code)\n",
@@ -14688,7 +14801,7 @@ rs6000_common_init_builtins (void)
continue;
}
- if (icode == CODE_FOR_nothing)
+ if (icode == CODE_FOR_nothing)
{
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "rs6000_builtin, skip binary %s (no code)\n",
@@ -14697,9 +14810,9 @@ rs6000_common_init_builtins (void)
continue;
}
- mode0 = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
- mode2 = insn_data[icode].operand[2].mode;
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+ mode2 = insn_data[icode].operand[2].mode;
type = builtin_function_type (mode0, mode1, mode2, VOIDmode,
d->code, d->name);
@@ -14732,7 +14845,7 @@ rs6000_common_init_builtins (void)
NULL_TREE);
}
else
- {
+ {
enum insn_code icode = d->icode;
if (d->name == 0)
{
@@ -14743,7 +14856,7 @@ rs6000_common_init_builtins (void)
continue;
}
- if (icode == CODE_FOR_nothing)
+ if (icode == CODE_FOR_nothing)
{
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "rs6000_builtin, skip unary %s (no code)\n",
@@ -14752,8 +14865,8 @@ rs6000_common_init_builtins (void)
continue;
}
- mode0 = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode,
d->code, d->name);
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index 8d2c1ff..482e1b6 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -51,7 +51,6 @@
| OPTION_MASK_CRYPTO \
| OPTION_MASK_DIRECT_MOVE \
| OPTION_MASK_EFFICIENT_UNALIGNED_VSX \
- | OPTION_MASK_HTM \
| OPTION_MASK_QUAD_MEMORY \
| OPTION_MASK_QUAD_MEMORY_ATOMIC)
@@ -240,10 +239,13 @@ RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
| MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
| MASK_CMPB | MASK_DFP | MASK_RECIP_PRECISION)
RS6000_CPU ("power7", PROCESSOR_POWER7, MASK_POWERPC64 | ISA_2_6_MASKS_SERVER)
-RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
-RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER)
+RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER
+ | OPTION_MASK_HTM)
+RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER
+ | OPTION_MASK_HTM)
RS6000_CPU ("power10", PROCESSOR_POWER10, MASK_POWERPC64 | ISA_3_1_MASKS_SERVER)
RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
-RS6000_CPU ("powerpc64le", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
+RS6000_CPU ("powerpc64le", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER
+ | OPTION_MASK_HTM)
RS6000_CPU ("rs64", PROCESSOR_RS64A, MASK_PPC_GFXOPT | MASK_POWERPC64)
diff --git a/gcc/config/rs6000/rs6000-modes.def b/gcc/config/rs6000/rs6000-modes.def
index ddb218b..e81a32c 100644
--- a/gcc/config/rs6000/rs6000-modes.def
+++ b/gcc/config/rs6000/rs6000-modes.def
@@ -83,12 +83,6 @@ VECTOR_MODE (INT, SI, 2); /* V2SI */
combination. */
PARTIAL_INT_MODE (TI, 128, PTI);
-/* Define, but don't use the larger integer modes. We need an integer mode
- defined that is the same size as the vector pair and vector quad modes. */
-
-INT_MODE (OI, 32);
-INT_MODE (XI, 64);
-
/* Modes used by __vector_pair and __vector_quad. */
-PARTIAL_INT_MODE (OI, 256, POI); /* __vector_pair. */
-PARTIAL_INT_MODE (XI, 512, PXI); /* __vector_quad. */
+OPAQUE_MODE (OO, 32);
+OPAQUE_MODE (XO, 64);
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 25fa5dd..3c4682b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -57,7 +57,7 @@ extern bool rs6000_move_128bit_ok_p (rtx []);
extern bool rs6000_split_128bit_ok_p (rtx []);
extern void rs6000_expand_float128_convert (rtx, rtx, bool);
extern void rs6000_expand_vector_init (rtx, rtx);
-extern void rs6000_expand_vector_set (rtx, rtx, int);
+extern void rs6000_expand_vector_set (rtx, rtx, rtx);
extern void rs6000_expand_vector_extract (rtx, rtx, rtx);
extern void rs6000_split_vec_extract_var (rtx, rtx, rtx, rtx, rtx);
extern rtx rs6000_adjust_vec_address (rtx, rtx, rtx, rtx, machine_mode);
@@ -155,6 +155,7 @@ extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool);
extern bool rs6000_function_pcrel_p (struct function *);
extern bool rs6000_pcrel_p (void);
extern bool rs6000_fndecl_pcrel_p (const_tree);
+extern void rs6000_output_addr_vec_elt (FILE *, int);
/* Different PowerPC instruction formats that are used by GCC. There are
various other instruction formats used by the PowerPC hardware, but these
diff --git a/gcc/config/rs6000/rs6000-string.c b/gcc/config/rs6000/rs6000-string.c
index 82cc24e..a2e6821 100644
--- a/gcc/config/rs6000/rs6000-string.c
+++ b/gcc/config/rs6000/rs6000-string.c
@@ -2787,7 +2787,7 @@ expand_block_move (rtx operands[], bool might_overlap)
rtx src, dest;
bool move_with_length = false;
- /* Use POImode for paired vsx load/store. Use V2DI for single
+ /* Use OOmode for paired vsx load/store. Use V2DI for single
unaligned vsx load/store, for consistency with what other
expansions (compare) already do, and so we can use lxvd2x on
p8. Order is VSX pair unaligned, VSX unaligned, Altivec, VSX
@@ -2799,8 +2799,8 @@ expand_block_move (rtx operands[], bool might_overlap)
&& (align >= 256 || !STRICT_ALIGNMENT))
{
move_bytes = 32;
- mode = POImode;
- gen_func.mov = gen_movpoi;
+ mode = OOmode;
+ gen_func.mov = gen_movoo;
}
else if (TARGET_POWERPC64 && TARGET_BLOCK_OPS_UNALIGNED_VSX
&& VECTOR_MEM_VSX_P (V2DImode)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 4d528a3..cf17213 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1367,6 +1367,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA rs6000_output_addr_const_extra
+#undef TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC
+#define TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC rs6000_gen_pic_addr_diff_vec
+
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS rs6000_legitimize_address
@@ -1826,15 +1829,12 @@ rs6000_hard_regno_mode_ok_uncached (int regno, machine_mode mode)
mode = GET_MODE_INNER (mode);
/* Vector pair modes need even/odd VSX register pairs. Only allow vector
- registers. We need to allow OImode to have the same registers as POImode,
- even though we do not enable the move pattern for OImode. */
- if (mode == POImode || mode == OImode)
+ registers. */
+ if (mode == OOmode)
return (TARGET_MMA && VSX_REGNO_P (regno) && (regno & 1) == 0);
- /* MMA accumulator modes need FPR registers divisible by 4. We need to allow
- XImode to have the same registers as PXImode, even though we do not enable
- the move pattern for XImode. */
- if (mode == PXImode || mode == XImode)
+ /* MMA accumulator modes need FPR registers divisible by 4. */
+ if (mode == XOmode)
return (TARGET_MMA && FP_REGNO_P (regno) && (regno & 3) == 0);
/* PTImode can only go in GPRs. Quad word memory operations require even/odd
@@ -1941,8 +1941,8 @@ rs6000_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
GPR registers, and TImode can go in any GPR as well as VSX registers (PR
57744).
- Similarly, don't allow POImode (vector pair, restricted to even VSX
- registers) or PXImode (vector quad, restricted to FPR registers divisible
+ Similarly, don't allow OOmode (vector pair, restricted to even VSX
+ registers) or XOmode (vector quad, restricted to FPR registers divisible
by 4) to tie with other modes.
Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
@@ -1951,8 +1951,8 @@ rs6000_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
static bool
rs6000_modes_tieable_p (machine_mode mode1, machine_mode mode2)
{
- if (mode1 == PTImode || mode1 == POImode || mode1 == PXImode
- || mode2 == PTImode || mode2 == POImode || mode2 == PXImode)
+ if (mode1 == PTImode || mode1 == OOmode || mode1 == XOmode
+ || mode2 == PTImode || mode2 == OOmode || mode2 == XOmode)
return mode1 == mode2;
if (ALTIVEC_OR_VSX_VECTOR_MODE (mode1))
@@ -2241,10 +2241,8 @@ rs6000_debug_reg_global (void)
V2DFmode,
V8SFmode,
V4DFmode,
- OImode,
- XImode,
- POImode,
- PXImode,
+ OOmode,
+ XOmode,
CCmode,
CCUNSmode,
CCEQmode,
@@ -2706,13 +2704,13 @@ rs6000_setup_reg_addr_masks (void)
since it will be broken into two vector moves. Vector quads can
only do offset loads. */
else if ((addr_mask != 0) && TARGET_MMA
- && (m2 == POImode || m2 == PXImode))
+ && (m2 == OOmode || m2 == XOmode))
{
addr_mask |= RELOAD_REG_OFFSET;
if (rc == RELOAD_REG_FPR || rc == RELOAD_REG_VMX)
{
addr_mask |= RELOAD_REG_QUAD_OFFSET;
- if (m2 == POImode)
+ if (m2 == OOmode)
addr_mask |= RELOAD_REG_INDEXED;
}
}
@@ -2921,13 +2919,13 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
/* Add support for vector pairs and vector quad registers. */
if (TARGET_MMA)
{
- rs6000_vector_unit[POImode] = VECTOR_NONE;
- rs6000_vector_mem[POImode] = VECTOR_VSX;
- rs6000_vector_align[POImode] = 256;
+ rs6000_vector_unit[OOmode] = VECTOR_NONE;
+ rs6000_vector_mem[OOmode] = VECTOR_VSX;
+ rs6000_vector_align[OOmode] = 256;
- rs6000_vector_unit[PXImode] = VECTOR_NONE;
- rs6000_vector_mem[PXImode] = VECTOR_VSX;
- rs6000_vector_align[PXImode] = 512;
+ rs6000_vector_unit[XOmode] = VECTOR_NONE;
+ rs6000_vector_mem[XOmode] = VECTOR_VSX;
+ rs6000_vector_align[XOmode] = 512;
}
/* Register class constraints for the constraints that depend on compile
@@ -3064,10 +3062,10 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_MMA)
{
- reg_addr[POImode].reload_store = CODE_FOR_reload_poi_di_store;
- reg_addr[POImode].reload_load = CODE_FOR_reload_poi_di_load;
- reg_addr[PXImode].reload_store = CODE_FOR_reload_pxi_di_store;
- reg_addr[PXImode].reload_load = CODE_FOR_reload_pxi_di_load;
+ reg_addr[OOmode].reload_store = CODE_FOR_reload_oo_di_store;
+ reg_addr[OOmode].reload_load = CODE_FOR_reload_oo_di_load;
+ reg_addr[XOmode].reload_store = CODE_FOR_reload_xo_di_store;
+ reg_addr[XOmode].reload_load = CODE_FOR_reload_xo_di_load;
}
}
}
@@ -3539,6 +3537,20 @@ rs6000_linux64_override_options ()
}
#endif
+/* Return true if we are using GLIBC, and it supports IEEE 128-bit long double.
+ This support is only in little endian GLIBC 2.32 or newer. */
+static bool
+glibc_supports_ieee_128bit (void)
+{
+#ifdef OPTION_GLIBC
+ if (OPTION_GLIBC && !BYTES_BIG_ENDIAN
+ && ((TARGET_GLIBC_MAJOR * 1000) + TARGET_GLIBC_MINOR) >= 2032)
+ return true;
+#endif /* OPTION_GLIBC. */
+
+ return false;
+}
+
/* Override command line options.
Combine build-specific configuration information with options
@@ -3796,9 +3808,10 @@ rs6000_option_override_internal (bool global_init_p)
}
/* If little-endian, default to -mstrict-align on older processors.
- Testing for htm matches power8 and later. */
+ Testing for direct_move matches power8 and later. */
if (!BYTES_BIG_ENDIAN
- && !(processor_target_table[tune_index].target_enable & OPTION_MASK_HTM))
+ && !(processor_target_table[tune_index].target_enable
+ & OPTION_MASK_DIRECT_MOVE))
rs6000_isa_flags |= ~rs6000_isa_flags_explicit & OPTION_MASK_STRICT_ALIGN;
if (!rs6000_fold_gimple)
@@ -3851,6 +3864,12 @@ rs6000_option_override_internal (bool global_init_p)
if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags);
+#ifdef XCOFF_DEBUGGING_INFO
+ /* For AIX default to 64-bit DWARF. */
+ if (!global_options_set.x_dwarf_offset_size)
+ dwarf_offset_size = POINTER_SIZE_UNITS;
+#endif
+
/* Handle explicit -mno-{altivec,vsx,power8-vector,power9-vector} and turn
off all of the options that depend on those flags. */
ignore_masks = rs6000_disable_incompatible_switches ();
@@ -4108,11 +4127,10 @@ rs6000_option_override_internal (bool global_init_p)
if (!(rs6000_isa_flags_explicit & OPTION_MASK_BLOCK_OPS_VECTOR_PAIR))
{
- /* When the POImode issues of PR96791 are resolved, then we can
- once again enable use of vector pair for memcpy/memmove on
- P10 if we have TARGET_MMA. For now we make it disabled by
- default for all targets. */
- rs6000_isa_flags &= ~OPTION_MASK_BLOCK_OPS_VECTOR_PAIR;
+ if (TARGET_MMA && TARGET_EFFICIENT_UNALIGNED_VSX)
+ rs6000_isa_flags |= OPTION_MASK_BLOCK_OPS_VECTOR_PAIR;
+ else
+ rs6000_isa_flags &= ~OPTION_MASK_BLOCK_OPS_VECTOR_PAIR;
}
/* Use long double size to select the appropriate long double. We use
@@ -4158,8 +4176,14 @@ rs6000_option_override_internal (bool global_init_p)
if (rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT && TARGET_LONG_DOUBLE_128)
{
+ /* Determine if the user can change the default long double type at
+ compilation time. Only C and C++ support this, and you need GLIBC
+ 2.32 or newer. Only issue one warning. */
static bool warned_change_long_double;
- if (!warned_change_long_double)
+
+ if (!warned_change_long_double
+ && (!glibc_supports_ieee_128bit ()
+ || (!lang_GNU_C () && !lang_GNU_CXX ())))
{
warned_change_long_double = true;
if (TARGET_IEEEQUAD)
@@ -4767,10 +4791,13 @@ rs6000_option_override_internal (bool global_init_p)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_max_completely_peeled_insns, 400);
- /* Temporarily disable it for now since lxvl/stxvl on the default
- supported hardware Power9 has unexpected performance behaviors. */
- SET_OPTION_IF_UNSET (&global_options, &global_options_set,
- param_vect_partial_vector_usage, 0);
+ /* The lxvl/stxvl instructions don't perform well before Power10. */
+ if (TARGET_POWER10)
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_vect_partial_vector_usage, 1);
+ else
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_vect_partial_vector_usage, 0);
/* Use the 'model' -fsched-pressure algorithm by default. */
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
@@ -6502,11 +6529,11 @@ rs6000_expand_vector_init (rtx target, rtx vals)
{
machine_mode mode = GET_MODE (target);
machine_mode inner_mode = GET_MODE_INNER (mode);
- int n_elts = GET_MODE_NUNITS (mode);
+ unsigned int n_elts = GET_MODE_NUNITS (mode);
int n_var = 0, one_var = -1;
bool all_same = true, all_const_zero = true;
rtx x, mem;
- int i;
+ unsigned int i;
for (i = 0; i < n_elts; ++i)
{
@@ -6768,7 +6795,175 @@ rs6000_expand_vector_init (rtx target, rtx vals)
rs6000_expand_vector_init (target, copy);
/* Insert variable. */
- rs6000_expand_vector_set (target, XVECEXP (vals, 0, one_var), one_var);
+ rs6000_expand_vector_set (target, XVECEXP (vals, 0, one_var),
+ GEN_INT (one_var));
+ return;
+ }
+
+ if (TARGET_DIRECT_MOVE && (mode == V16QImode || mode == V8HImode))
+ {
+ rtx op[16];
+ /* Force the values into word_mode registers. */
+ for (i = 0; i < n_elts; i++)
+ {
+ rtx tmp = force_reg (inner_mode, XVECEXP (vals, 0, i));
+ machine_mode tmode = TARGET_POWERPC64 ? DImode : SImode;
+ op[i] = simplify_gen_subreg (tmode, tmp, inner_mode, 0);
+ }
+
+ /* Take unsigned char big endianness on 64bit as example for below
+ construction, the input values are: A, B, C, D, ..., O, P. */
+
+ if (TARGET_DIRECT_MOVE_128)
+ {
+ /* Move to VSX register with vec_concat, each has 2 values.
+ eg: vr1[0] = { xxxxxxxA, xxxxxxxB };
+ vr1[1] = { xxxxxxxC, xxxxxxxD };
+ ...
+ vr1[7] = { xxxxxxxO, xxxxxxxP }; */
+ rtx vr1[8];
+ for (i = 0; i < n_elts / 2; i++)
+ {
+ vr1[i] = gen_reg_rtx (V2DImode);
+ emit_insn (gen_vsx_concat_v2di (vr1[i], op[i * 2],
+ op[i * 2 + 1]));
+ }
+
+ /* Pack vectors with 2 values into vectors with 4 values.
+ eg: vr2[0] = { xxxAxxxB, xxxCxxxD };
+ vr2[1] = { xxxExxxF, xxxGxxxH };
+ vr2[1] = { xxxIxxxJ, xxxKxxxL };
+ vr2[3] = { xxxMxxxN, xxxOxxxP }; */
+ rtx vr2[4];
+ for (i = 0; i < n_elts / 4; i++)
+ {
+ vr2[i] = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vpkudum (vr2[i], vr1[i * 2],
+ vr1[i * 2 + 1]));
+ }
+
+ /* Pack vectors with 4 values into vectors with 8 values.
+ eg: vr3[0] = { xAxBxCxD, xExFxGxH };
+ vr3[1] = { xIxJxKxL, xMxNxOxP }; */
+ rtx vr3[2];
+ for (i = 0; i < n_elts / 8; i++)
+ {
+ vr3[i] = gen_reg_rtx (V8HImode);
+ emit_insn (gen_altivec_vpkuwum (vr3[i], vr2[i * 2],
+ vr2[i * 2 + 1]));
+ }
+
+ /* If it's V8HImode, it's done and return it. */
+ if (mode == V8HImode)
+ {
+ emit_insn (gen_rtx_SET (target, vr3[0]));
+ return;
+ }
+
+ /* Pack vectors with 8 values into 16 values. */
+ rtx res = gen_reg_rtx (V16QImode);
+ emit_insn (gen_altivec_vpkuhum (res, vr3[0], vr3[1]));
+ emit_insn (gen_rtx_SET (target, res));
+ }
+ else
+ {
+ rtx (*merge_v16qi) (rtx, rtx, rtx) = NULL;
+ rtx (*merge_v8hi) (rtx, rtx, rtx) = NULL;
+ rtx (*merge_v4si) (rtx, rtx, rtx) = NULL;
+ rtx perm_idx;
+
+ /* Set up some common gen routines and values. */
+ if (BYTES_BIG_ENDIAN)
+ {
+ if (mode == V16QImode)
+ {
+ merge_v16qi = gen_altivec_vmrghb;
+ merge_v8hi = gen_altivec_vmrglh;
+ }
+ else
+ merge_v8hi = gen_altivec_vmrghh;
+
+ merge_v4si = gen_altivec_vmrglw;
+ perm_idx = GEN_INT (3);
+ }
+ else
+ {
+ if (mode == V16QImode)
+ {
+ merge_v16qi = gen_altivec_vmrglb;
+ merge_v8hi = gen_altivec_vmrghh;
+ }
+ else
+ merge_v8hi = gen_altivec_vmrglh;
+
+ merge_v4si = gen_altivec_vmrghw;
+ perm_idx = GEN_INT (0);
+ }
+
+ /* Move to VSX register with direct move.
+ eg: vr_qi[0] = { xxxxxxxA, xxxxxxxx };
+ vr_qi[1] = { xxxxxxxB, xxxxxxxx };
+ ...
+ vr_qi[15] = { xxxxxxxP, xxxxxxxx }; */
+ rtx vr_qi[16];
+ for (i = 0; i < n_elts; i++)
+ {
+ vr_qi[i] = gen_reg_rtx (V16QImode);
+ if (TARGET_POWERPC64)
+ emit_insn (gen_p8_mtvsrd_v16qidi2 (vr_qi[i], op[i]));
+ else
+ emit_insn (gen_p8_mtvsrwz_v16qisi2 (vr_qi[i], op[i]));
+ }
+
+ /* Merge/move to vector short.
+ eg: vr_hi[0] = { xxxxxxxx, xxxxxxAB };
+ vr_hi[1] = { xxxxxxxx, xxxxxxCD };
+ ...
+ vr_hi[7] = { xxxxxxxx, xxxxxxOP }; */
+ rtx vr_hi[8];
+ for (i = 0; i < 8; i++)
+ {
+ rtx tmp = vr_qi[i];
+ if (mode == V16QImode)
+ {
+ tmp = gen_reg_rtx (V16QImode);
+ emit_insn (merge_v16qi (tmp, vr_qi[2 * i], vr_qi[2 * i + 1]));
+ }
+ vr_hi[i] = gen_reg_rtx (V8HImode);
+ emit_move_insn (vr_hi[i], gen_lowpart (V8HImode, tmp));
+ }
+
+ /* Merge vector short to vector int.
+ eg: vr_si[0] = { xxxxxxxx, xxxxABCD };
+ vr_si[1] = { xxxxxxxx, xxxxEFGH };
+ ...
+ vr_si[3] = { xxxxxxxx, xxxxMNOP }; */
+ rtx vr_si[4];
+ for (i = 0; i < 4; i++)
+ {
+ rtx tmp = gen_reg_rtx (V8HImode);
+ emit_insn (merge_v8hi (tmp, vr_hi[2 * i], vr_hi[2 * i + 1]));
+ vr_si[i] = gen_reg_rtx (V4SImode);
+ emit_move_insn (vr_si[i], gen_lowpart (V4SImode, tmp));
+ }
+
+ /* Merge vector int to vector long.
+ eg: vr_di[0] = { xxxxxxxx, ABCDEFGH };
+ vr_di[1] = { xxxxxxxx, IJKLMNOP }; */
+ rtx vr_di[2];
+ for (i = 0; i < 2; i++)
+ {
+ rtx tmp = gen_reg_rtx (V4SImode);
+ emit_insn (merge_v4si (tmp, vr_si[2 * i], vr_si[2 * i + 1]));
+ vr_di[i] = gen_reg_rtx (V2DImode);
+ emit_move_insn (vr_di[i], gen_lowpart (V2DImode, tmp));
+ }
+
+ rtx res = gen_reg_rtx (V2DImode);
+ emit_insn (gen_vsx_xxpermdi_v2di (res, vr_di[0], vr_di[1], perm_idx));
+ emit_insn (gen_rtx_SET (target, gen_lowpart (mode, res)));
+ }
+
return;
}
@@ -6782,10 +6977,10 @@ rs6000_expand_vector_init (rtx target, rtx vals)
emit_move_insn (target, mem);
}
-/* Set field ELT of TARGET to VAL. */
+/* Set field ELT_RTX of TARGET to VAL. */
void
-rs6000_expand_vector_set (rtx target, rtx val, int elt)
+rs6000_expand_vector_set (rtx target, rtx val, rtx elt_rtx)
{
machine_mode mode = GET_MODE (target);
machine_mode inner_mode = GET_MODE_INNER (mode);
@@ -6799,7 +6994,6 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
if (VECTOR_MEM_VSX_P (mode))
{
rtx insn = NULL_RTX;
- rtx elt_rtx = GEN_INT (elt);
if (mode == V2DFmode)
insn = gen_vsx_set_v2df (target, target, val, elt_rtx);
@@ -6826,8 +7020,11 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
}
}
+ gcc_assert (CONST_INT_P (elt_rtx));
+
/* Simplify setting single element vectors like V1TImode. */
- if (GET_MODE_SIZE (mode) == GET_MODE_SIZE (inner_mode) && elt == 0)
+ if (GET_MODE_SIZE (mode) == GET_MODE_SIZE (inner_mode)
+ && INTVAL (elt_rtx) == 0)
{
emit_move_insn (target, gen_lowpart (mode, val));
return;
@@ -6850,8 +7047,7 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
/* Set permute mask to insert element into target. */
for (i = 0; i < width; ++i)
- XVECEXP (mask, 0, elt*width + i)
- = GEN_INT (i + 0x10);
+ XVECEXP (mask, 0, INTVAL (elt_rtx) * width + i) = GEN_INT (i + 0x10);
x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0));
if (BYTES_BIG_ENDIAN)
@@ -7934,8 +8130,8 @@ reg_offset_addressing_ok_p (machine_mode mode)
/* The vector pair/quad types support offset addressing if the
underlying vectors support offset addressing. */
- case E_POImode:
- case E_PXImode:
+ case E_OOmode:
+ case E_XOmode:
return TARGET_MMA;
case E_SDmode:
@@ -10128,11 +10324,11 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
operands[1] = force_const_mem (mode, operands[1]);
break;
- case E_POImode:
- case E_PXImode:
+ case E_OOmode:
+ case E_XOmode:
if (CONST_INT_P (operands[1]) && INTVAL (operands[1]) != 0)
error ("%qs is an opaque type, and you can't set it to other values.",
- (mode == POImode) ? "__vector_pair" : "__vector_quad");
+ (mode == OOmode) ? "__vector_pair" : "__vector_quad");
break;
case E_SImode:
@@ -12401,10 +12597,10 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
the GPR registers. */
if (rclass == GEN_OR_FLOAT_REGS)
{
- if (mode == POImode)
+ if (mode == OOmode)
return VSX_REGS;
- if (mode == PXImode)
+ if (mode == XOmode)
return FLOAT_REGS;
if (GET_MODE_CLASS (mode) == MODE_INT)
@@ -14392,22 +14588,10 @@ rs6000_invalid_binary_op (int op ATTRIBUTE_UNUSED,
if (!TARGET_FLOAT128_CVT)
{
- if ((mode1 == KFmode && mode2 == IFmode)
- || (mode1 == IFmode && mode2 == KFmode))
- return N_("__float128 and __ibm128 cannot be used in the same "
- "expression");
-
- if (TARGET_IEEEQUAD
- && ((mode1 == IFmode && mode2 == TFmode)
- || (mode1 == TFmode && mode2 == IFmode)))
- return N_("__ibm128 and long double cannot be used in the same "
- "expression");
-
- if (!TARGET_IEEEQUAD
- && ((mode1 == KFmode && mode2 == TFmode)
- || (mode1 == TFmode && mode2 == KFmode)))
- return N_("__float128 and long double cannot be used in the same "
- "expression");
+ if ((FLOAT128_IEEE_P (mode1) && FLOAT128_IBM_P (mode2))
+ || (FLOAT128_IBM_P (mode1) && FLOAT128_IEEE_P (mode2)))
+ return N_("Invalid mixing of IEEE 128-bit and IBM 128-bit floating "
+ "point types");
}
return NULL;
@@ -16140,15 +16324,15 @@ rs6000_split_multireg_move (rtx dst, rtx src)
/* If we have a vector quad register for MMA, and this is a load or store,
see if we can use vector paired load/stores. */
- if (mode == PXImode && TARGET_MMA
+ if (mode == XOmode && TARGET_MMA
&& (MEM_P (dst) || MEM_P (src)))
{
- reg_mode = POImode;
+ reg_mode = OOmode;
nregs /= 2;
}
/* If we have a vector pair/quad mode, split it into two/four separate
vectors. */
- else if (mode == POImode || mode == PXImode)
+ else if (mode == OOmode || mode == XOmode)
reg_mode = V1TImode;
else if (FP_REGNO_P (reg))
reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode :
@@ -16194,12 +16378,16 @@ rs6000_split_multireg_move (rtx dst, rtx src)
return;
}
- /* The __vector_pair and __vector_quad modes are multi-register modes,
- so if have to load or store the registers, we have to be careful to
- properly swap them if we're in little endian mode below. This means
- the last register gets the first memory location. */
- if (mode == POImode || mode == PXImode)
+ /* The __vector_pair and __vector_quad modes are multi-register
+ modes, so if we have to load or store the registers, we have to be
+ careful to properly swap them if we're in little endian mode
+ below. This means the last register gets the first memory
+ location. We also need to be careful of using the right register
+ numbers if we are splitting XO to OO. */
+ if (mode == OOmode || mode == XOmode)
{
+ nregs = hard_regno_nregs (reg, mode);
+ int reg_mode_nregs = hard_regno_nregs (reg, reg_mode);
if (MEM_P (dst))
{
unsigned offset = 0;
@@ -16208,15 +16396,15 @@ rs6000_split_multireg_move (rtx dst, rtx src)
/* If we are reading an accumulator register, we have to
deprime it before we can access it. */
if (TARGET_MMA
- && GET_MODE (src) == PXImode && FP_REGNO_P (REGNO (src)))
+ && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
emit_insn (gen_mma_xxmfacc (src, src));
- for (int i = 0; i < nregs; i++)
+ for (int i = 0; i < nregs; i += reg_mode_nregs)
{
- unsigned subreg = (WORDS_BIG_ENDIAN)
- ? i * size : (nregs - 1 - i) * size;
+ unsigned subreg =
+ (WORDS_BIG_ENDIAN) ? i : (nregs - reg_mode_nregs - i);
rtx dst2 = adjust_address (dst, reg_mode, offset);
- rtx src2 = simplify_gen_subreg (reg_mode, src, mode, subreg);
+ rtx src2 = gen_rtx_REG (reg_mode, reg + subreg);
offset += size;
emit_insn (gen_rtx_SET (dst2, src2));
}
@@ -16229,11 +16417,11 @@ rs6000_split_multireg_move (rtx dst, rtx src)
unsigned offset = 0;
unsigned size = GET_MODE_SIZE (reg_mode);
- for (int i = 0; i < nregs; i++)
+ for (int i = 0; i < nregs; i += reg_mode_nregs)
{
- unsigned subreg = (WORDS_BIG_ENDIAN)
- ? i * size : (nregs - 1 - i) * size;
- rtx dst2 = simplify_gen_subreg (reg_mode, dst, mode, subreg);
+ unsigned subreg =
+ (WORDS_BIG_ENDIAN) ? i : (nregs - reg_mode_nregs - i);
+ rtx dst2 = gen_rtx_REG (reg_mode, reg + subreg);
rtx src2 = adjust_address (src, reg_mode, offset);
offset += size;
emit_insn (gen_rtx_SET (dst2, src2));
@@ -16242,7 +16430,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
/* If we are writing an accumulator register, we have to
prime it after we've written it. */
if (TARGET_MMA
- && GET_MODE (dst) == PXImode && FP_REGNO_P (REGNO (dst)))
+ && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
emit_insn (gen_mma_xxmtacc (dst, dst));
return;
@@ -16250,9 +16438,12 @@ rs6000_split_multireg_move (rtx dst, rtx src)
if (GET_CODE (src) == UNSPEC)
{
- gcc_assert (REG_P (dst)
- && FP_REGNO_P (REGNO (dst))
- && XINT (src, 1) == UNSPEC_MMA_ASSEMBLE_ACC);
+ gcc_assert (XINT (src, 1) == UNSPEC_MMA_ASSEMBLE);
+ gcc_assert (REG_P (dst));
+ if (GET_MODE (src) == XOmode)
+ gcc_assert (FP_REGNO_P (REGNO (dst)));
+ if (GET_MODE (src) == OOmode)
+ gcc_assert (VSX_REGNO_P (REGNO (dst)));
reg_mode = GET_MODE (XVECEXP (src, 0, 0));
for (int i = 0; i < XVECLEN (src, 0); i++)
@@ -16263,7 +16454,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
/* We are writing an accumulator register, so we have to
prime it after we've written it. */
- emit_insn (gen_mma_xxmtacc (dst, dst));
+ if (GET_MODE (src) == XOmode)
+ emit_insn (gen_mma_xxmtacc (dst, dst));
return;
}
@@ -16276,22 +16468,35 @@ rs6000_split_multireg_move (rtx dst, rtx src)
/* If we are reading an accumulator register, we have to
deprime it before we can access it. */
if (TARGET_MMA
- && GET_MODE (src) == PXImode && FP_REGNO_P (REGNO (src)))
+ && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
emit_insn (gen_mma_xxmfacc (src, src));
/* Move register range backwards, if we might have destructive
overlap. */
int i;
- for (i = nregs - 1; i >= 0; i--)
- emit_insn (gen_rtx_SET (simplify_gen_subreg (reg_mode, dst, mode,
- i * reg_mode_size),
- simplify_gen_subreg (reg_mode, src, mode,
- i * reg_mode_size)));
+ /* XO/OO are opaque so cannot use subregs. */
+ if (mode == OOmode || mode == XOmode )
+ {
+ for (i = nregs - 1; i >= 0; i--)
+ {
+ rtx dst_i = gen_rtx_REG (reg_mode, REGNO (dst) + i);
+ rtx src_i = gen_rtx_REG (reg_mode, REGNO (src) + i);
+ emit_insn (gen_rtx_SET (dst_i, src_i));
+ }
+ }
+ else
+ {
+ for (i = nregs - 1; i >= 0; i--)
+ emit_insn (gen_rtx_SET (simplify_gen_subreg (reg_mode, dst, mode,
+ i * reg_mode_size),
+ simplify_gen_subreg (reg_mode, src, mode,
+ i * reg_mode_size)));
+ }
/* If we are writing an accumulator register, we have to
prime it after we've written it. */
if (TARGET_MMA
- && GET_MODE (dst) == PXImode && FP_REGNO_P (REGNO (dst)))
+ && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
emit_insn (gen_mma_xxmtacc (dst, dst));
}
else
@@ -16428,7 +16633,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
/* If we are reading an accumulator register, we have to
deprime it before we can access it. */
if (TARGET_MMA && REG_P (src)
- && GET_MODE (src) == PXImode && FP_REGNO_P (REGNO (src)))
+ && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
emit_insn (gen_mma_xxmfacc (src, src));
for (i = 0; i < nregs; i++)
@@ -16443,16 +16648,24 @@ rs6000_split_multireg_move (rtx dst, rtx src)
if (j == 0 && used_update)
continue;
- emit_insn (gen_rtx_SET (simplify_gen_subreg (reg_mode, dst, mode,
- j * reg_mode_size),
- simplify_gen_subreg (reg_mode, src, mode,
- j * reg_mode_size)));
+ /* XO/OO are opaque so cannot use subregs. */
+ if (mode == OOmode || mode == XOmode )
+ {
+ rtx dst_i = gen_rtx_REG (reg_mode, REGNO (dst) + j);
+ rtx src_i = gen_rtx_REG (reg_mode, REGNO (src) + j);
+ emit_insn (gen_rtx_SET (dst_i, src_i));
+ }
+ else
+ emit_insn (gen_rtx_SET (simplify_gen_subreg (reg_mode, dst, mode,
+ j * reg_mode_size),
+ simplify_gen_subreg (reg_mode, src, mode,
+ j * reg_mode_size)));
}
/* If we are writing an accumulator register, we have to
prime it after we've written it. */
if (TARGET_MMA && REG_P (dst)
- && GET_MODE (dst) == PXImode && FP_REGNO_P (REGNO (dst)))
+ && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
emit_insn (gen_mma_xxmtacc (dst, dst));
if (restore_basereg != NULL_RTX)
@@ -19682,7 +19895,8 @@ rs6000_mangle_type (const_tree type)
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) != VOID_TYPE && TREE_CODE (type) != BOOLEAN_TYPE
- && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+ && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE
+ && TREE_CODE (type) != OPAQUE_TYPE)
return NULL;
if (type == bool_char_type_node) return "U6__boolc";
@@ -21570,6 +21784,14 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
}
break;
+ case UNSPEC:
+ if (XINT (x, 1) == UNSPEC_MMA_XXSETACCZ)
+ {
+ *total = 0;
+ return true;
+ }
+ break;
+
default:
break;
}
@@ -26901,7 +27123,8 @@ static tree
rs6000_mangle_decl_assembler_name (tree decl, tree id)
{
if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
- && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl) )
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_IS_UNDECLARED_BUILTIN (decl))
{
size_t len = IDENTIFIER_LENGTH (id);
const char *name = IDENTIFIER_POINTER (id);
@@ -27002,14 +27225,14 @@ rs6000_invalid_conversion (const_tree fromtype, const_tree totype)
if (frommode != tomode)
{
- /* Do not allow conversions to/from PXImode and POImode types. */
- if (frommode == PXImode)
+ /* Do not allow conversions to/from XOmode and OOmode types. */
+ if (frommode == XOmode)
return N_("invalid conversion from type %<__vector_quad%>");
- if (tomode == PXImode)
+ if (tomode == XOmode)
return N_("invalid conversion to type %<__vector_quad%>");
- if (frommode == POImode)
+ if (frommode == OOmode)
return N_("invalid conversion from type %<__vector_pair%>");
- if (tomode == POImode)
+ if (tomode == OOmode)
return N_("invalid conversion to type %<__vector_pair%>");
}
else if (POINTER_TYPE_P (fromtype) && POINTER_TYPE_P (totype))
@@ -27018,19 +27241,19 @@ rs6000_invalid_conversion (const_tree fromtype, const_tree totype)
frommode = TYPE_MODE (TREE_TYPE (fromtype));
tomode = TYPE_MODE (TREE_TYPE (totype));
- /* Do not allow conversions to/from PXImode and POImode pointer
+ /* Do not allow conversions to/from XOmode and OOmode pointer
types, except to/from void pointers. */
if (frommode != tomode
&& frommode != VOIDmode
&& tomode != VOIDmode)
{
- if (frommode == PXImode)
+ if (frommode == XOmode)
return N_("invalid conversion from type %<* __vector_quad%>");
- if (tomode == PXImode)
+ if (tomode == XOmode)
return N_("invalid conversion to type %<* __vector_quad%>");
- if (frommode == POImode)
+ if (frommode == OOmode)
return N_("invalid conversion from type %<* __vector_pair%>");
- if (tomode == POImode)
+ if (tomode == OOmode)
return N_("invalid conversion to type %<* __vector_pair%>");
}
}
@@ -27060,6 +27283,26 @@ rs6000_emit_xxspltidp_v2df (rtx dst, long value)
emit_insn( gen_xxspltidp_v2df_inst (dst, GEN_INT (value)));
}
+/* Implement TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC. */
+
+static bool
+rs6000_gen_pic_addr_diff_vec (void)
+{
+ return rs6000_relative_jumptables;
+}
+
+void
+rs6000_output_addr_vec_elt (FILE *file, int value)
+{
+ const char *directive = TARGET_64BIT ? DOUBLE_INT_ASM_OP : "\t.long\t";
+ char buf[100];
+
+ fprintf (file, "%s", directive);
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", value);
+ assemble_name (file, buf);
+ fprintf (file, "\n");
+}
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rs6000.h"
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index bbd8060..5bf9c83 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -776,8 +776,10 @@ extern unsigned rs6000_pointer_size;
/* Allocation boundary (in *bits*) for the code of a function. */
#define FUNCTION_BOUNDARY 32
-/* No data type wants to be aligned rounder than this. */
-#define BIGGEST_ALIGNMENT (TARGET_MMA ? 512 : 128)
+/* No data type is required to be aligned rounder than this. Warning, if
+ BIGGEST_ALIGNMENT is changed, then this may be an ABI break. An example
+ of where this can break an ABI is in GLIBC's struct _Unwind_Exception. */
+#define BIGGEST_ALIGNMENT 128
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 32
@@ -1039,7 +1041,7 @@ enum data_align { align_abi, align_opt, align_both };
/* Modes that are not vectors, but require vector alignment. Treat these like
vectors in terms of loads and stores. */
#define VECTOR_ALIGNMENT_P(MODE) \
- (FLOAT128_VECTOR_P (MODE) || (MODE) == POImode || (MODE) == PXImode)
+ (FLOAT128_VECTOR_P (MODE) || (MODE) == OOmode || (MODE) == XOmode)
#define ALTIVEC_VECTOR_MODE(MODE) \
((MODE) == V16QImode \
@@ -1754,15 +1756,15 @@ typedef struct rs6000_args
/* #define LEGITIMATE_PIC_OPERAND_P (X) */
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE SImode
-
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
table.
Do not define this if the table should contain absolute addresses. */
-#define CASE_VECTOR_PC_RELATIVE 1
+#define CASE_VECTOR_PC_RELATIVE rs6000_relative_jumptables
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE (rs6000_relative_jumptables ? SImode : Pmode)
/* Define this as 1 if `char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 0
@@ -2192,6 +2194,11 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
putc ('\n', FILE); \
} while (0)
+/* This is how to output an element of a case-vector
+ that is non-relative. */
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ rs6000_output_addr_vec_elt ((FILE), (VALUE))
+
/* This is how to output an assembler line
that says to advance the location counter
to a multiple of 2**LOG bytes. */
@@ -2554,6 +2561,7 @@ typedef struct GTY(()) machine_function
bool fpr_is_wrapped_separately[32];
bool lr_is_wrapped_separately;
bool toc_is_wrapped_separately;
+ bool mma_return_type_error;
} machine_function;
#endif
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index dc06014..b89990f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -778,7 +778,7 @@
;; supplement addressing modes.
(define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
SF SD SI DF DD DI TI PTI KF IF TF
- POI PXI])
+ OO XO])
;; Iterate over smin, smax
(define_code_iterator fp_minmax [smin smax])
@@ -8713,6 +8713,22 @@
"mtvsrwz %x0,%1"
[(set_attr "type" "mtvsr")])
+(define_insn "p8_mtvsrwz_v16qisi2"
+ [(set (match_operand:V16QI 0 "register_operand" "=wa")
+ (unspec:V16QI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPEC_P8V_MTVSRWZ))]
+ "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+ "mtvsrwz %x0,%1"
+ [(set_attr "type" "mtvsr")])
+
+(define_insn "p8_mtvsrd_v16qidi2"
+ [(set (match_operand:V16QI 0 "register_operand" "=wa")
+ (unspec:V16QI [(match_operand:DI 1 "register_operand" "r")]
+ UNSPEC_P8V_MTVSRD))]
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+ "mtvsrd %x0,%1"
+ [(set_attr "type" "mtvsr")])
+
(define_insn_and_split "reload_fpr_from_gpr<mode>"
[(set (match_operand:FMOVE64X 0 "register_operand" "=d")
(unspec:FMOVE64X [(match_operand:FMOVE64X 1 "register_operand" "r")]
@@ -8745,7 +8761,7 @@
UNSPEC_P8V_MTVSRD))]
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"mtvsrd %x0,%1"
- [(set_attr "type" "mfvsr")])
+ [(set_attr "type" "mtvsr")])
(define_insn "p8_xxpermdi_<mode>"
[(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa")
@@ -12697,15 +12713,22 @@
""
{
if (rs6000_speculate_indirect_jumps)
- emit_jump_insn (gen_tablejump_normal (Pmode, operands[0], operands[1]));
+ {
+ if (rs6000_relative_jumptables)
+ emit_jump_insn (gen_tablejump_normal (Pmode, operands[0], operands[1]));
+ else
+ emit_jump_insn (gen_tablejump_absolute (Pmode, operands[0],
+ operands[1]));
+ }
else
{
rtx ccreg = gen_reg_rtx (CCmode);
rtx jump;
- if (TARGET_32BIT)
- jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg);
+ if (rs6000_relative_jumptables)
+ jump = gen_tablejump_nospec (Pmode, operands[0], operands[1], ccreg);
else
- jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg);
+ jump = gen_tablejump_absolute_nospec (Pmode, operands[0], operands[1],
+ ccreg);
emit_jump_insn (jump);
}
DONE;
@@ -12714,16 +12737,13 @@
(define_expand "@tablejump<mode>_normal"
[(use (match_operand:SI 0))
(use (match_operand:P 1))]
- "rs6000_speculate_indirect_jumps"
+ "rs6000_speculate_indirect_jumps && rs6000_relative_jumptables"
{
- rtx off;
- operands[0] = force_reg (SImode, operands[0]);
- if (<MODE>mode == SImode)
- off = operands[0];
- else
+ rtx off = force_reg (SImode, operands[0]);
+ if (<MODE>mode != SImode)
{
+ rtx src = gen_rtx_fmt_e (SIGN_EXTEND, Pmode, off);
off = gen_reg_rtx (Pmode);
- rtx src = gen_rtx_fmt_e (SIGN_EXTEND, Pmode, operands[0]);
emit_move_insn (off, src);
}
@@ -12735,20 +12755,29 @@
DONE;
})
+(define_expand "@tablejump<mode>_absolute"
+ [(use (match_operand:P 0))
+ (use (match_operand:P 1))]
+ "rs6000_speculate_indirect_jumps && !rs6000_relative_jumptables"
+{
+ rtx addr = gen_reg_rtx (Pmode);
+ emit_move_insn (addr, operands[0]);
+
+ emit_jump_insn (gen_tablejump_insn_normal (Pmode, addr, operands[1]));
+ DONE;
+})
+
(define_expand "@tablejump<mode>_nospec"
[(use (match_operand:SI 0))
(use (match_operand:P 1))
(use (match_operand:CC 2))]
- "!rs6000_speculate_indirect_jumps"
+ "!rs6000_speculate_indirect_jumps && rs6000_relative_jumptables"
{
- rtx off;
- operands[0] = force_reg (SImode, operands[0]);
- if (<MODE>mode == SImode)
- off = operands[0];
- else
+ rtx off = force_reg (SImode, operands[0]);
+ if (<MODE>mode != SImode)
{
+ rtx src = gen_rtx_fmt_e (SIGN_EXTEND, Pmode, off);
off = gen_reg_rtx (Pmode);
- rtx src = gen_rtx_fmt_e (SIGN_EXTEND, Pmode, operands[0]);
emit_move_insn (off, src);
}
@@ -12761,6 +12790,20 @@
DONE;
})
+(define_expand "@tablejump<mode>_absolute_nospec"
+ [(use (match_operand:P 0))
+ (use (match_operand:P 1))
+ (use (match_operand:CC 2))]
+ "!rs6000_speculate_indirect_jumps && !rs6000_relative_jumptables"
+{
+ rtx addr = gen_reg_rtx (Pmode);
+ emit_move_insn (addr, operands[0]);
+
+ emit_jump_insn (gen_tablejump_insn_nospec (Pmode, addr, operands[1],
+ operands[2]));
+ DONE;
+})
+
(define_insn "@tablejump<mode>_insn_normal"
[(set (pc)
(match_operand:P 0 "register_operand" "c,*l"))
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index b2a70e8..6efeafd 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -117,31 +117,31 @@ mpowerpc
Target RejectNegative Undocumented Ignore
mpowerpc64
-Target Report Mask(POWERPC64) Var(rs6000_isa_flags)
+Target Mask(POWERPC64) Var(rs6000_isa_flags)
Use PowerPC-64 instruction set.
mpowerpc-gpopt
-Target Report Mask(PPC_GPOPT) Var(rs6000_isa_flags)
+Target Mask(PPC_GPOPT) Var(rs6000_isa_flags)
Use PowerPC General Purpose group optional instructions.
mpowerpc-gfxopt
-Target Report Mask(PPC_GFXOPT) Var(rs6000_isa_flags)
+Target Mask(PPC_GFXOPT) Var(rs6000_isa_flags)
Use PowerPC Graphics group optional instructions.
mmfcrf
-Target Report Mask(MFCRF) Var(rs6000_isa_flags)
+Target Mask(MFCRF) Var(rs6000_isa_flags)
Use PowerPC V2.01 single field mfcr instruction.
mpopcntb
-Target Report Mask(POPCNTB) Var(rs6000_isa_flags)
+Target Mask(POPCNTB) Var(rs6000_isa_flags)
Use PowerPC V2.02 popcntb instruction.
mfprnd
-Target Report Mask(FPRND) Var(rs6000_isa_flags)
+Target Mask(FPRND) Var(rs6000_isa_flags)
Use PowerPC V2.02 floating point rounding instructions.
mcmpb
-Target Report Mask(CMPB) Var(rs6000_isa_flags)
+Target Mask(CMPB) Var(rs6000_isa_flags)
Use PowerPC V2.05 compare bytes instruction.
;; This option existed in the past, but now is always off.
@@ -152,27 +152,27 @@ mmfpgpr
Target RejectNegative Undocumented WarnRemoved
maltivec
-Target Report Mask(ALTIVEC) Var(rs6000_isa_flags)
+Target Mask(ALTIVEC) Var(rs6000_isa_flags)
Use AltiVec instructions.
mfold-gimple
-Target Report Var(rs6000_fold_gimple) Init(1)
+Target Var(rs6000_fold_gimple) Init(1)
Enable early gimple folding of builtins.
mhard-dfp
-Target Report Mask(DFP) Var(rs6000_isa_flags)
+Target Mask(DFP) Var(rs6000_isa_flags)
Use decimal floating point instructions.
mmulhw
-Target Report Mask(MULHW) Var(rs6000_isa_flags)
+Target Mask(MULHW) Var(rs6000_isa_flags)
Use 4xx half-word multiply instructions.
mdlmzb
-Target Report Mask(DLMZB) Var(rs6000_isa_flags)
+Target Mask(DLMZB) Var(rs6000_isa_flags)
Use 4xx string-search dlmzb instruction.
mmultiple
-Target Report Mask(MULTIPLE) Var(rs6000_isa_flags)
+Target Mask(MULTIPLE) Var(rs6000_isa_flags)
Generate load/store multiple instructions.
;; This option existed in the past, but now is always off.
@@ -183,19 +183,19 @@ mstring
Target RejectNegative Undocumented WarnRemoved
msoft-float
-Target Report RejectNegative Mask(SOFT_FLOAT) Var(rs6000_isa_flags)
+Target RejectNegative Mask(SOFT_FLOAT) Var(rs6000_isa_flags)
Do not use hardware floating point.
mhard-float
-Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT) Var(rs6000_isa_flags)
+Target RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT) Var(rs6000_isa_flags)
Use hardware floating point.
mpopcntd
-Target Report Mask(POPCNTD) Var(rs6000_isa_flags)
+Target Mask(POPCNTD) Var(rs6000_isa_flags)
Use PowerPC V2.06 popcntd instruction.
mfriz
-Target Report Var(TARGET_FRIZ) Init(-1) Save
+Target Var(TARGET_FRIZ) Init(-1) Save
Under -ffast-math, generate a FRIZ instruction for (double)(long long) conversions.
mveclibabi=
@@ -203,11 +203,11 @@ Target RejectNegative Joined Var(rs6000_veclibabi_name)
Vector library ABI to use.
mvsx
-Target Report Mask(VSX) Var(rs6000_isa_flags)
+Target Mask(VSX) Var(rs6000_isa_flags)
Use vector/scalar (VSX) instructions.
mvsx-align-128
-Target Undocumented Report Var(TARGET_VSX_ALIGN_128) Save
+Target Undocumented Var(TARGET_VSX_ALIGN_128) Save
; If -mvsx, set alignment to 128 bits instead of 32/64
mallow-movmisalign
@@ -215,74 +215,74 @@ Target Undocumented Var(TARGET_ALLOW_MOVMISALIGN) Init(-1) Save
; Allow the movmisalign in DF/DI vectors
mefficient-unaligned-vsx
-Target Undocumented Report Mask(EFFICIENT_UNALIGNED_VSX) Var(rs6000_isa_flags)
+Target Undocumented Mask(EFFICIENT_UNALIGNED_VSX) Var(rs6000_isa_flags)
; Consider unaligned VSX vector and fp accesses to be efficient
msched-groups
-Target Undocumented Report Var(TARGET_SCHED_GROUPS) Init(-1) Save
+Target Undocumented Var(TARGET_SCHED_GROUPS) Init(-1) Save
; Explicitly set rs6000_sched_groups
malways-hint
-Target Undocumented Report Var(TARGET_ALWAYS_HINT) Init(-1) Save
+Target Undocumented Var(TARGET_ALWAYS_HINT) Init(-1) Save
; Explicitly set rs6000_always_hint
malign-branch-targets
-Target Undocumented Report Var(TARGET_ALIGN_BRANCH_TARGETS) Init(-1) Save
+Target Undocumented Var(TARGET_ALIGN_BRANCH_TARGETS) Init(-1) Save
; Explicitly set rs6000_align_branch_targets
mno-update
-Target Report RejectNegative Mask(NO_UPDATE) Var(rs6000_isa_flags)
+Target RejectNegative Mask(NO_UPDATE) Var(rs6000_isa_flags)
Do not generate load/store with update instructions.
mupdate
-Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE) Var(rs6000_isa_flags)
+Target RejectNegative InverseMask(NO_UPDATE, UPDATE) Var(rs6000_isa_flags)
Generate load/store with update instructions.
msingle-pic-base
-Target Report Var(TARGET_SINGLE_PIC_BASE) Init(0)
+Target Var(TARGET_SINGLE_PIC_BASE) Init(0)
Do not load the PIC register in function prologues.
mavoid-indexed-addresses
-Target Report Var(TARGET_AVOID_XFORM) Init(-1) Save
+Target Var(TARGET_AVOID_XFORM) Init(-1) Save
Avoid generation of indexed load/store instructions when possible.
msched-epilog
Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1) Save
msched-prolog
-Target Report Var(TARGET_SCHED_PROLOG) Save
+Target Var(TARGET_SCHED_PROLOG) Save
Schedule the start and end of the procedure.
maix-struct-return
-Target Report RejectNegative Var(aix_struct_return) Save
+Target RejectNegative Var(aix_struct_return) Save
Return all structures in memory (AIX default).
msvr4-struct-return
-Target Report RejectNegative Var(aix_struct_return,0) Save
+Target RejectNegative Var(aix_struct_return,0) Save
Return small structures in registers (SVR4 default).
mxl-compat
-Target Report Var(TARGET_XL_COMPAT) Save
+Target Var(TARGET_XL_COMPAT) Save
Conform more closely to IBM XLC semantics.
mrecip
-Target Report
+Target
Generate software reciprocal divide and square root for better throughput.
mrecip=
-Target Report RejectNegative Joined Var(rs6000_recip_name)
+Target RejectNegative Joined Var(rs6000_recip_name)
Generate software reciprocal divide and square root for better throughput.
mrecip-precision
-Target Report Mask(RECIP_PRECISION) Var(rs6000_isa_flags)
+Target Mask(RECIP_PRECISION) Var(rs6000_isa_flags)
Assume that the reciprocal estimate instructions provide more accuracy.
mno-fp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC) Save
+Target RejectNegative Var(TARGET_NO_FP_IN_TOC) Save
Do not place floating point constants in TOC.
mfp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0) Save
+Target RejectNegative Var(TARGET_NO_FP_IN_TOC,0) Save
Place floating point constants in TOC.
mno-sum-in-toc
@@ -301,15 +301,15 @@ Place symbol+offset constants in TOC.
; This is at the cost of having 2 extra loads and one extra store per
; function, and one less allocable register.
mminimal-toc
-Target Report Mask(MINIMAL_TOC) Var(rs6000_isa_flags)
+Target Mask(MINIMAL_TOC) Var(rs6000_isa_flags)
Use only one TOC entry per procedure.
mfull-toc
-Target Report
+Target
Put everything in the regular TOC.
mvrsave
-Target Report Var(TARGET_ALTIVEC_VRSAVE) Save
+Target Var(TARGET_ALTIVEC_VRSAVE) Save
Generate VRSAVE instructions when generating AltiVec code.
mvrsave=no
@@ -321,11 +321,11 @@ Target RejectNegative Alias(mvrsave) Warn(%<-mvrsave=yes%> is deprecated; use %<
Deprecated option. Use -mvrsave instead.
mblock-move-inline-limit=
-Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger Save
+Target Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger Save
Max number of bytes to move inline.
mblock-ops-unaligned-vsx
-Target Report Mask(BLOCK_OPS_UNALIGNED_VSX) Var(rs6000_isa_flags)
+Target Mask(BLOCK_OPS_UNALIGNED_VSX) Var(rs6000_isa_flags)
Generate unaligned VSX load/store for inline expansion of memcpy/memmove.
mblock-ops-vector-pair
@@ -333,19 +333,19 @@ Target Undocumented Mask(BLOCK_OPS_VECTOR_PAIR) Var(rs6000_isa_flags)
Generate unaligned VSX vector pair load/store for inline expansion of memcpy/memmove.
mblock-compare-inline-limit=
-Target Report Var(rs6000_block_compare_inline_limit) Init(63) RejectNegative Joined UInteger Save
+Target Var(rs6000_block_compare_inline_limit) Init(63) RejectNegative Joined UInteger Save
Max number of bytes to compare without loops.
mblock-compare-inline-loop-limit=
-Target Report Var(rs6000_block_compare_inline_loop_limit) Init(-1) RejectNegative Joined UInteger Save
+Target Var(rs6000_block_compare_inline_loop_limit) Init(-1) RejectNegative Joined UInteger Save
Max number of bytes to compare with loops.
mstring-compare-inline-limit=
-Target Report Var(rs6000_string_compare_inline_limit) Init(64) RejectNegative Joined UInteger Save
+Target Var(rs6000_string_compare_inline_limit) Init(64) RejectNegative Joined UInteger Save
Max number of bytes to compare.
misel
-Target Report Mask(ISEL) Var(rs6000_isa_flags)
+Target Mask(ISEL) Var(rs6000_isa_flags)
Generate isel instructions.
mdebug=
@@ -409,7 +409,7 @@ EnumValue
Enum(rs6000_traceback_type) String(no) Value(traceback_none)
mlongcall
-Target Report Var(rs6000_default_long_calls) Save
+Target Var(rs6000_default_long_calls) Save
Avoid all range limits on call instructions.
; This option existed in the past, but now is always on.
@@ -456,11 +456,11 @@ Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority
Specify scheduling priority for dispatch slot restricted insns.
mpointers-to-nested-functions
-Target Report Var(TARGET_POINTERS_TO_NESTED_FUNCTIONS) Init(1) Save
+Target Var(TARGET_POINTERS_TO_NESTED_FUNCTIONS) Init(1) Save
Use r11 to hold the static link in calls to functions via pointers.
msave-toc-indirect
-Target Report Mask(SAVE_TOC_INDIRECT) Var(rs6000_isa_flags)
+Target Mask(SAVE_TOC_INDIRECT) Var(rs6000_isa_flags)
Save the TOC in the prologue for indirect calls rather than inline.
; This option existed in the past, but now is always the same as -mvsx.
@@ -468,7 +468,7 @@ mvsx-timode
Target RejectNegative Undocumented Ignore
mpower8-fusion
-Target Report Mask(P8_FUSION) Var(rs6000_isa_flags)
+Target Mask(P8_FUSION) Var(rs6000_isa_flags)
Fuse certain integer operations together for better performance on power8.
mpower8-fusion-sign
@@ -476,30 +476,30 @@ Target Undocumented Mask(P8_FUSION_SIGN) Var(rs6000_isa_flags)
Allow sign extension in fusion operations.
mpower8-vector
-Target Report Mask(P8_VECTOR) Var(rs6000_isa_flags)
+Target Mask(P8_VECTOR) Var(rs6000_isa_flags)
Use vector and scalar instructions added in ISA 2.07.
mcrypto
-Target Report Mask(CRYPTO) Var(rs6000_isa_flags)
+Target Mask(CRYPTO) Var(rs6000_isa_flags)
Use ISA 2.07 Category:Vector.AES and Category:Vector.SHA2 instructions.
mdirect-move
Target Undocumented Mask(DIRECT_MOVE) Var(rs6000_isa_flags) WarnRemoved
mhtm
-Target Report Mask(HTM) Var(rs6000_isa_flags)
+Target Mask(HTM) Var(rs6000_isa_flags)
Use ISA 2.07 transactional memory (HTM) instructions.
mquad-memory
-Target Report Mask(QUAD_MEMORY) Var(rs6000_isa_flags)
+Target Mask(QUAD_MEMORY) Var(rs6000_isa_flags)
Generate the quad word memory instructions (lq/stq).
mquad-memory-atomic
-Target Report Mask(QUAD_MEMORY_ATOMIC) Var(rs6000_isa_flags)
+Target Mask(QUAD_MEMORY_ATOMIC) Var(rs6000_isa_flags)
Generate the quad word memory atomic instructions (lqarx/stqcx).
mcompat-align-parm
-Target Report Var(rs6000_compat_align_parm) Init(0) Save
+Target Var(rs6000_compat_align_parm) Init(0) Save
Generate aggregate parameter passing code with at most 64-bit alignment.
moptimize-swaps
@@ -511,11 +511,11 @@ Target Undocumented Var(unroll_only_small_loops) Init(0) Save
; Use conservative small loop unrolling.
mpower9-misc
-Target Undocumented Report Mask(P9_MISC) Var(rs6000_isa_flags)
+Target Undocumented Mask(P9_MISC) Var(rs6000_isa_flags)
Use certain scalar instructions added in ISA 3.0.
mpower9-vector
-Target Undocumented Report Mask(P9_VECTOR) Var(rs6000_isa_flags)
+Target Undocumented Mask(P9_VECTOR) Var(rs6000_isa_flags)
Use vector instructions added in ISA 3.0.
mpower9-minmax
@@ -527,15 +527,15 @@ Target Undocumented Mask(TOC_FUSION) Var(rs6000_isa_flags)
Fuse medium/large code model toc references with the memory instruction.
mmodulo
-Target Undocumented Report Mask(MODULO) Var(rs6000_isa_flags)
+Target Undocumented Mask(MODULO) Var(rs6000_isa_flags)
Generate the integer modulo instructions.
mfloat128
-Target Report Mask(FLOAT128_KEYWORD) Var(rs6000_isa_flags)
+Target Mask(FLOAT128_KEYWORD) Var(rs6000_isa_flags)
Enable IEEE 128-bit floating point via the __float128 keyword.
mfloat128-hardware
-Target Report Mask(FLOAT128_HW) Var(rs6000_isa_flags)
+Target Mask(FLOAT128_HW) Var(rs6000_isa_flags)
Enable using IEEE 128-bit floating point instructions.
mfloat128-convert
@@ -579,13 +579,16 @@ mpower10
Target Undocumented Mask(POWER10) Var(rs6000_isa_flags) WarnRemoved
mprefixed
-Target Report Mask(PREFIXED) Var(rs6000_isa_flags)
+Target Mask(PREFIXED) Var(rs6000_isa_flags)
Generate (do not generate) prefixed memory instructions.
mpcrel
-Target Report Mask(PCREL) Var(rs6000_isa_flags)
+Target Mask(PCREL) Var(rs6000_isa_flags)
Generate (do not generate) pc-relative memory addressing.
mmma
-Target Report Mask(MMA) Var(rs6000_isa_flags)
+Target Mask(MMA) Var(rs6000_isa_flags)
Generate (do not generate) MMA instructions.
+
+mrelative-jumptables
+Target Undocumented Var(rs6000_relative_jumptables) Init(1) Save
diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt
index b49ba26..85729f3 100644
--- a/gcc/config/rs6000/sysv4.opt
+++ b/gcc/config/rs6000/sysv4.opt
@@ -28,7 +28,7 @@ Target RejectNegative Joined Var(rs6000_sdata_name)
-msdata=[none,data,sysv,eabi] Select method for sdata handling.
mreadonly-in-sdata
-Target Report Var(rs6000_readonly_in_sdata) Init(1) Save
+Target Var(rs6000_readonly_in_sdata) Init(1) Save
Allow readonly data in sdata.
mtls-size=
@@ -48,16 +48,16 @@ EnumValue
Enum(rs6000_tls_size) String(64) Value(64)
mbit-align
-Target Report Var(TARGET_NO_BITFIELD_TYPE) Save
+Target Var(TARGET_NO_BITFIELD_TYPE) Save
Align to the base type of the bit-field.
mstrict-align
-Target Report Mask(STRICT_ALIGN) Var(rs6000_isa_flags)
+Target Mask(STRICT_ALIGN) Var(rs6000_isa_flags)
Align to the base type of the bit-field.
Don't assume that unaligned accesses are handled by the system.
mrelocatable
-Target Report Mask(RELOCATABLE) Var(rs6000_isa_flags)
+Target Mask(RELOCATABLE) Var(rs6000_isa_flags)
Produce code relocatable at runtime.
mrelocatable-lib
@@ -65,19 +65,19 @@ Target
Produce code relocatable at runtime.
mlittle-endian
-Target Report RejectNegative Mask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
+Target RejectNegative Mask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
Produce little endian code.
mlittle
-Target Report RejectNegative Mask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
+Target RejectNegative Mask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
Produce little endian code.
mbig-endian
-Target Report RejectNegative InverseMask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
+Target RejectNegative InverseMask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
Produce big endian code.
mbig
-Target Report RejectNegative InverseMask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
+Target RejectNegative InverseMask(LITTLE_ENDIAN) Var(rs6000_isa_flags)
Produce big endian code.
;; FIXME: This does nothing. What should be done?
@@ -99,11 +99,11 @@ Target RejectNegative
No description yet.
meabi
-Target Report Mask(EABI) Var(rs6000_isa_flags)
+Target Mask(EABI) Var(rs6000_isa_flags)
Use EABI.
mbit-word
-Target Report Var(TARGET_NO_BITFIELD_WORD) Save
+Target Var(TARGET_NO_BITFIELD_WORD) Save
Allow bit-fields to cross word boundaries.
mregnames
@@ -141,11 +141,11 @@ Target RejectNegative
No description yet.
m64
-Target Report RejectNegative Negative(m32) Mask(64BIT) Var(rs6000_isa_flags)
+Target RejectNegative Negative(m32) Mask(64BIT) Var(rs6000_isa_flags)
Generate 64-bit code.
m32
-Target Report RejectNegative Negative(m64) InverseMask(64BIT) Var(rs6000_isa_flags)
+Target RejectNegative Negative(m64) InverseMask(64BIT) Var(rs6000_isa_flags)
Generate 32-bit code.
mnewlib
@@ -153,17 +153,17 @@ Target RejectNegative
No description yet.
msecure-plt
-Target Report RejectNegative Var(secure_plt, 1) Save
+Target RejectNegative Var(secure_plt, 1) Save
Generate code to use a non-exec PLT and GOT.
mbss-plt
-Target Report RejectNegative Var(secure_plt, 0) Save
+Target RejectNegative Var(secure_plt, 0) Save
Generate code for old exec BSS PLT.
mpltseq
-Target Report Var(rs6000_pltseq) Init(1) Save
+Target Var(rs6000_pltseq) Init(1) Save
Use inline plt sequences to implement long calls and -fno-plt.
mgnu-attribute
-Target Report Var(rs6000_gnu_attr) Init(1) Save
+Target Var(rs6000_gnu_attr) Init(1) Save
Emit .gnu_attribute tags.
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 796345c..7aab188 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -1227,10 +1227,10 @@
(define_expand "vec_set<mode>"
[(match_operand:VEC_E 0 "vlogical_operand")
(match_operand:<VEC_base> 1 "register_operand")
- (match_operand 2 "const_int_operand")]
+ (match_operand 2 "reg_or_cint_operand")]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
- rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+ rs6000_expand_vector_set (operands[0], operands[1], operands[2]);
DONE;
})
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index d6347db..947631d 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -3109,7 +3109,7 @@
[(match_operand:VSX_EXTRACT_I4 1 "altivec_register_operand" "v")
(match_operand:QI 2 "const_0_to_3_operand" "n")]
UNSPEC_XXGENPCV))]
- "TARGET_POWER10 && TARGET_64BIT"
+ "TARGET_POWER10"
"xxgenpcv<wd>m %x0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -3717,7 +3717,7 @@
(vec_select:<VS_scalar>
(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "<VSX_EX>,v")
(parallel [(match_operand:QI 2 "const_int_operand" "n,n")])))
- (clobber (match_scratch:<VS_scalar> 3 "=<VSX_EX>,&r"))
+ (clobber (match_scratch:<VS_scalar> 3 "=<VSX_EX>,&*r"))
(clobber (match_scratch:SI 4 "=X,&r"))]
"VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
"#"
diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h
index 87ca3af..51a3250 100644
--- a/gcc/config/rs6000/vxworks.h
+++ b/gcc/config/rs6000/vxworks.h
@@ -70,6 +70,12 @@ along with GCC; see the file COPYING3. If not see
builtin_define ("__PPC"); \
builtin_define ("__powerpc"); \
} \
+ \
+ /* __ppc isn't emitted by the system compiler \
+ any more but a few system headers still depend \
+ on it, as well as on __ppc__. */ \
+ builtin_define ("__ppc"); \
+ builtin_define ("__ppc__"); \
} \
\
/* Asserts for #cpu and #machine. */ \
@@ -97,18 +103,6 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
-/* Specific CPU macro definitions expected by the system headers,
- inferred from -mcpu requests by the user. Different versions of
- VxWorks expect different forms of macros, such as
-
- -D_VX_CPU=_VX_PPC403 on Vx7 and some variants of Vx6,
- -DCPU=PPC403 on all Vx6 and earlier. */
-
-#if TARGET_VXWORKS7
-#define VX_CPU_PREFIX "_VX_"
-#else
-#define VX_CPU_PREFIX ""
-#endif
#define VX_CPUDEF(CPUID) \
":-D" VX_CPU_PREFIX "CPU=" VX_CPU_PREFIX #CPUID
@@ -127,7 +121,7 @@ along with GCC; see the file COPYING3. If not see
VX_MCPU(603, PPC603) ";" \
VX_MCPU(604, PPC604) ";" \
VX_MCPU(860, PPC860) ";" \
- VX_MCPU(e6500, E6500) ";" \
+ VX_MCPU(e6500, PPCE6500) ";" \
VX_MCPU(8540, PPC85XX) ";" \
VX_MCPU(8548, PPC85XX) ";" \
VX_CPUDEF(PPC604) \
diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h
index 0f40b45..fe6221a 100644
--- a/gcc/config/rs6000/xcoff.h
+++ b/gcc/config/rs6000/xcoff.h
@@ -273,7 +273,9 @@
We still need to define this macro to let middle-end know that aliases are
supported.
*/
-#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) do { } while (0)
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) do { (void) (FILE); \
+ (void) (LABEL1); \
+ (void) (LABEL2); } while (0)
/* Used by rs6000_assemble_integer, among others. */
diff --git a/gcc/config/rx/elf.opt b/gcc/config/rx/elf.opt
index f130e79..6145b4d 100644
--- a/gcc/config/rx/elf.opt
+++ b/gcc/config/rx/elf.opt
@@ -28,7 +28,7 @@ Use the simulator runtime.
;---------------------------------------------------
mas100-syntax
-Target Mask(AS100_SYNTAX) Report
+Target Mask(AS100_SYNTAX)
Generate assembler output that is compatible with the Renesas AS100 assembler. This may restrict some of the compiler's capabilities. The default is to generate GAS compatible syntax.
;---------------------------------------------------
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 151ad39..dfb4bd4 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -639,6 +639,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
switch (INTVAL (op))
{
case CTRLREG_PSW: fprintf (file, "psw"); break;
+ case CTRLREG_PC: fprintf (file, "pc"); break;
case CTRLREG_USP: fprintf (file, "usp"); break;
case CTRLREG_FPSW: fprintf (file, "fpsw"); break;
case CTRLREG_BPSW: fprintf (file, "bpsw"); break;
@@ -2474,6 +2475,13 @@ rx_expand_builtin_mvtc (tree exp)
if (! REG_P (arg2))
arg2 = force_reg (SImode, arg2);
+ if (INTVAL (arg1) == 1)
+ {
+ warning (0, "invalid control register for mvtc : %d - using 'psw'",
+ (int) INTVAL (arg1));
+ arg1 = const0_rtx;
+ }
+
emit_insn (gen_mvtc (arg1, arg2));
return NULL_RTX;
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index df08a9e..6e5c546 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -77,6 +77,7 @@
(UNSPEC_PID_ADDR 52)
(CTRLREG_PSW 0)
+ (CTRLREG_PC 1)
(CTRLREG_USP 2)
(CTRLREG_FPSW 3)
(CTRLREG_BPSW 8)
diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt
index d6426f4..274e187 100644
--- a/gcc/config/rx/rx.opt
+++ b/gcc/config/rx/rx.opt
@@ -25,11 +25,11 @@ config/rx/rx-opts.h
; The default is -fpu -m32bit-doubles.
m64bit-doubles
-Target RejectNegative Mask(64BIT_DOUBLES) Report
+Target RejectNegative Mask(64BIT_DOUBLES)
Store doubles in 64 bits.
m32bit-doubles
-Target RejectNegative InverseMask(64BIT_DOUBLES) Report
+Target RejectNegative InverseMask(64BIT_DOUBLES)
Stores doubles in 32 bits. This is the default.
nofpu
@@ -37,16 +37,16 @@ Target RejectNegative Alias(mnofpu)
Disable the use of RX FPU instructions.
mnofpu
-Target RejectNegative Mask(NO_USE_FPU) Report Undocumented
+Target RejectNegative Mask(NO_USE_FPU) Undocumented
fpu
-Target RejectNegative InverseMask(NO_USE_FPU) Report
+Target RejectNegative InverseMask(NO_USE_FPU)
Enable the use of RX FPU instructions. This is the default.
;---------------------------------------------------
mcpu=
-Target RejectNegative Joined Var(rx_cpu_type) Report ToLower Enum(rx_cpu_types) Init(RX600)
+Target RejectNegative Joined Var(rx_cpu_type) ToLower Enum(rx_cpu_types) Init(RX600)
Specify the target RX cpu type.
Enum
@@ -67,11 +67,11 @@ Enum(rx_cpu_types) String(rx100) Value(RX100)
;---------------------------------------------------
mbig-endian-data
-Target RejectNegative Mask(BIG_ENDIAN_DATA) Report
+Target RejectNegative Mask(BIG_ENDIAN_DATA)
Data is stored in big-endian format.
mlittle-endian-data
-Target RejectNegative InverseMask(BIG_ENDIAN_DATA) Report
+Target RejectNegative InverseMask(BIG_ENDIAN_DATA)
Data is stored in little-endian format. (Default).
;---------------------------------------------------
@@ -113,33 +113,33 @@ Enables Position-Independent-Data (PID) mode.
;---------------------------------------------------
mwarn-multiple-fast-interrupts
-Target Report Var(rx_warn_multiple_fast_interrupts) Init(1) Warning
+Target Var(rx_warn_multiple_fast_interrupts) Init(1) Warning
Warn when multiple, different, fast interrupt handlers are in the compilation unit.
;---------------------------------------------------
mgcc-abi
-Target RejectNegative Report Mask(GCC_ABI)
+Target RejectNegative Mask(GCC_ABI)
Enable the use of the old, broken, ABI where all stacked function arguments are aligned to 32-bits.
mrx-abi
-Target RejectNegative Report InverseMask(GCC_ABI)
+Target RejectNegative InverseMask(GCC_ABI)
Enable the use the standard RX ABI where all stacked function arguments are naturally aligned. This is the default.
;---------------------------------------------------
mlra
-Target Report Mask(ENABLE_LRA)
+Target Mask(ENABLE_LRA)
Enable the use of the LRA register allocator.
;---------------------------------------------------
mallow-string-insns
-Target Report Var(rx_allow_string_insns) Init(1)
+Target Var(rx_allow_string_insns) Init(1)
Enables or disables the use of the SMOVF, SMOVB, SMOVU, SUNTIL, SWHILE and RMPA instructions. Enabled by default.
;---------------------------------------------------
mjsr
-Target Report Mask(JSR)
+Target Mask(JSR)
Always use JSR, never BSR, for calls.
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index b1f8e1f..316ca5c 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -22,9 +22,12 @@ along with GCC; see the file COPYING3. If not see
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
INT_MODE (OI, 32);
-/* Define TFmode to work around reload problem PR 20927. */
+/* 128-bit float stored in a VR on z14+ or a FPR pair on older machines. */
FLOAT_MODE (TF, 16, ieee_quad_format);
+/* 128-bit float stored in a FPR pair. */
+FLOAT_MODE (FPRX2, 16, ieee_quad_format);
+
/* Add any extra modes needed to represent the condition code. */
/*
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 029f728..eb10c3f 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -51,6 +51,7 @@ extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
extern int s390_class_max_nregs (enum reg_class, machine_mode);
extern bool s390_function_arg_vector (machine_mode, const_tree);
extern bool s390_return_addr_from_memory(void);
+extern bool s390_fma_allowed_p (machine_mode);
#if S390_USE_TARGET_ATTRIBUTE
extern tree s390_valid_target_attribute_tree (tree args,
struct gcc_options *opts,
@@ -134,6 +135,7 @@ extern void s390_split_access_reg (rtx, rtx *, rtx *);
extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int);
extern void s390_output_pool_entry (rtx, machine_mode, unsigned int);
+extern bool s390_const_int_pool_entry_p (rtx, HOST_WIDE_INT *);
extern int s390_label_align (rtx_insn *);
extern int s390_agen_dep_p (rtx_insn *, rtx_insn *);
extern rtx_insn *s390_load_got (void);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index f9b27f9..2f83988 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -456,6 +456,16 @@ s390_return_addr_from_memory ()
return cfun_gpr_save_slot(RETURN_REGNUM) == SAVE_SLOT_STACK;
}
+/* Return nonzero if it's OK to use fused multiply-add for MODE. */
+bool
+s390_fma_allowed_p (machine_mode mode)
+{
+ if (TARGET_VXE && mode == TFmode)
+ return flag_vx_long_double_fma;
+
+ return true;
+}
+
/* Indicate which ABI has been used for passing vector args.
0 - no vector type arguments have been passed where the ABI is relevant
1 - the old ABI has been used
@@ -1850,6 +1860,10 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
machine_mode mode = s390_select_ccmode (code, op0, op1);
rtx cc;
+ /* Force OP1 into register in order to satisfy VXE TFmode patterns. */
+ if (TARGET_VXE && GET_MODE (op1) == TFmode)
+ op1 = force_reg (TFmode, op1);
+
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
{
/* Do not output a redundant compare instruction if a
@@ -6959,6 +6973,13 @@ s390_expand_vec_init (rtx target, rtx vals)
extern rtx
s390_build_signbit_mask (machine_mode mode)
{
+ if (mode == TFmode && TARGET_VXE)
+ {
+ wide_int mask_val = wi::set_bit_in_zero (127, 128);
+ rtx mask = immed_wide_int_const (mask_val, TImode);
+ return gen_lowpart (TFmode, mask);
+ }
+
/* Generate the integral element mask value. */
machine_mode inner_mode = GET_MODE_INNER (mode);
int inner_bitsize = GET_MODE_BITSIZE (inner_mode);
@@ -7902,6 +7923,7 @@ print_operand_address (FILE *file, rtx addr)
CONST_VECTOR: Generate a bitmask for vgbm instruction.
'x': print integer X as if it's an unsigned halfword.
'v': print register number as vector register (v1 instead of f1).
+ 'V': print the second word of a TFmode operand as vector register.
*/
void
@@ -8071,13 +8093,13 @@ print_operand (FILE *file, rtx x, int code)
case REG:
/* Print FP regs as fx instead of vx when they are accessed
through non-vector mode. */
- if (code == 'v'
+ if ((code == 'v' || code == 'V')
|| VECTOR_NOFP_REG_P (x)
|| (FP_REG_P (x) && VECTOR_MODE_P (GET_MODE (x)))
|| (VECTOR_REG_P (x)
&& (GET_MODE_SIZE (GET_MODE (x)) /
s390_class_max_nregs (FP_REGS, GET_MODE (x))) > 8))
- fprintf (file, "%%v%s", reg_names[REGNO (x)] + 2);
+ fprintf (file, "%%v%s", reg_names[REGNO (x) + (code == 'V')] + 2);
else
fprintf (file, "%s", reg_names[REGNO (x)]);
break;
@@ -8621,10 +8643,9 @@ replace_constant_pool_ref (rtx_insn *insn, rtx ref, rtx offset)
/* We keep a list of constants which we have to add to internal
constant tables in the middle of large functions. */
-#define NR_C_MODES 32
-machine_mode constant_modes[NR_C_MODES] =
+static machine_mode constant_modes[] =
{
- TFmode, TImode, TDmode,
+ TFmode, FPRX2mode, TImode, TDmode,
V16QImode, V8HImode, V4SImode, V2DImode, V1TImode,
V4SFmode, V2DFmode, V1TFmode,
DFmode, DImode, DDmode,
@@ -8636,6 +8657,7 @@ machine_mode constant_modes[NR_C_MODES] =
QImode,
V1QImode
};
+#define NR_C_MODES (sizeof (constant_modes) / sizeof (constant_modes[0]))
struct constant
{
@@ -8664,7 +8686,7 @@ static struct constant_pool *
s390_alloc_pool (void)
{
struct constant_pool *pool;
- int i;
+ size_t i;
pool = (struct constant_pool *) xmalloc (sizeof *pool);
pool->next = NULL;
@@ -8743,7 +8765,7 @@ static void
s390_add_constant (struct constant_pool *pool, rtx val, machine_mode mode)
{
struct constant *c;
- int i;
+ size_t i;
for (i = 0; i < NR_C_MODES; i++)
if (constant_modes[i] == mode)
@@ -8788,7 +8810,7 @@ s390_find_constant (struct constant_pool *pool, rtx val,
machine_mode mode)
{
struct constant *c;
- int i;
+ size_t i;
for (i = 0; i < NR_C_MODES; i++)
if (constant_modes[i] == mode)
@@ -8895,7 +8917,7 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
{
struct constant *c;
rtx_insn *insn = pool->pool_insn;
- int i;
+ size_t i;
/* Switch to rodata section. */
insn = emit_insn_after (gen_pool_section_start (), insn);
@@ -8966,7 +8988,7 @@ static void
s390_free_pool (struct constant_pool *pool)
{
struct constant *c, *next;
- int i;
+ size_t i;
for (i = 0; i < NR_C_MODES; i++)
for (c = pool->constants[i]; c; c = next)
@@ -9378,6 +9400,37 @@ s390_output_pool_entry (rtx exp, machine_mode mode, unsigned int align)
}
}
+/* Return true if MEM refers to an integer constant in the literal pool. If
+ VAL is not nullptr, then also fill it with the constant's value. */
+
+bool
+s390_const_int_pool_entry_p (rtx mem, HOST_WIDE_INT *val)
+{
+ /* Try to match the following:
+ - (mem (unspec [(symbol_ref) (reg)] UNSPEC_LTREF)).
+ - (mem (symbol_ref)). */
+
+ if (!MEM_P (mem))
+ return false;
+
+ rtx addr = XEXP (mem, 0);
+ rtx sym;
+ if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_LTREF)
+ sym = XVECEXP (addr, 0, 0);
+ else
+ sym = addr;
+
+ if (!SYMBOL_REF_P (sym) || !CONSTANT_POOL_ADDRESS_P (sym))
+ return false;
+
+ rtx val_rtx = get_pool_constant (sym);
+ if (!CONST_INT_P (val_rtx))
+ return false;
+
+ if (val != nullptr)
+ *val = INTVAL (val_rtx);
+ return true;
+}
/* Return an RTL expression representing the value of the return address
for the frame COUNT steps up from the current frame. FRAME is the
@@ -10376,9 +10429,16 @@ static bool
s390_hard_regno_call_part_clobbered (unsigned int, unsigned int regno,
machine_mode mode)
{
+ /* For r12 we know that the only bits we actually care about are
+ preserved across function calls. Since r12 is a fixed reg all
+ accesses to r12 are generated by the backend.
+
+ This workaround is necessary until gcse implements proper
+ tracking of partially clobbered registers. */
if (!TARGET_64BIT
&& TARGET_ZARCH
&& GET_MODE_SIZE (mode) > 4
+ && (!flag_pic || regno != PIC_OFFSET_TABLE_REGNUM)
&& ((regno >= 6 && regno <= 15) || regno == 32))
return true;
@@ -10411,7 +10471,8 @@ s390_class_max_nregs (enum reg_class rclass, machine_mode mode)
full VRs. */
if (TARGET_VX
&& SCALAR_FLOAT_MODE_P (mode)
- && GET_MODE_SIZE (mode) >= 16)
+ && GET_MODE_SIZE (mode) >= 16
+ && !(TARGET_VXE && mode == TFmode))
reg_pair_required_p = true;
/* Even if complex types would fit into a single FPR/VR we force
@@ -10434,6 +10495,24 @@ s390_class_max_nregs (enum reg_class rclass, machine_mode mode)
return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
}
+/* Return nonzero if mode M describes a 128-bit float in a floating point
+ register pair. */
+
+static bool
+s390_is_fpr128 (machine_mode m)
+{
+ return m == FPRX2mode || (!TARGET_VXE && m == TFmode);
+}
+
+/* Return nonzero if mode M describes a 128-bit float in a vector
+ register. */
+
+static bool
+s390_is_vr128 (machine_mode m)
+{
+ return m == V1TFmode || (TARGET_VXE && m == TFmode);
+}
+
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
static bool
@@ -10444,11 +10523,11 @@ s390_can_change_mode_class (machine_mode from_mode,
machine_mode small_mode;
machine_mode big_mode;
- /* V1TF and TF have different representations in vector
- registers. */
+ /* 128-bit values have different representations in floating point and
+ vector registers. */
if (reg_classes_intersect_p (VEC_REGS, rclass)
- && ((from_mode == V1TFmode && to_mode == TFmode)
- || (from_mode == TFmode && to_mode == V1TFmode)))
+ && ((s390_is_fpr128 (from_mode) && s390_is_vr128 (to_mode))
+ || (s390_is_vr128 (from_mode) && s390_is_fpr128 (to_mode))))
return false;
if (GET_MODE_SIZE (from_mode) == GET_MODE_SIZE (to_mode))
@@ -11003,7 +11082,7 @@ s390_prologue_plus_offset (rtx target, rtx reg, rtx offset, bool frame_related_p
static void
s390_emit_stack_probe (rtx addr)
{
- rtx mem = gen_rtx_MEM (Pmode, addr);
+ rtx mem = gen_rtx_MEM (word_mode, addr);
MEM_VOLATILE_P (mem) = 1;
emit_insn (gen_probe_stack (mem));
}
@@ -11698,7 +11777,7 @@ s390_output_split_stack_data (rtx parm_block, rtx call_done,
rtx ops[] = { parm_block, call_done };
switch_to_section (targetm.asm_out.function_rodata_section
- (current_function_decl));
+ (current_function_decl, false));
if (TARGET_64BIT)
output_asm_insn (".align\t8", NULL);
@@ -15462,13 +15541,6 @@ s390_option_override_internal (struct gcc_options *opts,
SET_OPTION_IF_UNSET (opts, opts_set, param_sched_pressure_algorithm, 2);
SET_OPTION_IF_UNSET (opts, opts_set, param_min_vect_loop_bound, 2);
- /* Use aggressive inlining parameters. */
- if (opts->x_s390_tune >= PROCESSOR_2964_Z13)
- {
- SET_OPTION_IF_UNSET (opts, opts_set, param_inline_min_speedup, 2);
- SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_auto, 80);
- }
-
/* Set the default alignment. */
s390_default_align (opts);
@@ -16335,20 +16407,28 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
return NULL;
}
-/* Implement TARGET_C_EXCESS_PRECISION.
+#if ENABLE_S390_EXCESS_FLOAT_PRECISION == 1
+/* Implement TARGET_C_EXCESS_PRECISION to maintain historic behavior with older
+ glibc versions
- FIXME: For historical reasons, float_t and double_t are typedef'ed to
+ For historical reasons, float_t and double_t had been typedef'ed to
double on s390, causing operations on float_t to operate in a higher
precision than is necessary. However, it is not the case that SFmode
operations have implicit excess precision, and we generate more optimal
code if we let the compiler know no implicit extra precision is added.
- That means when we are compiling with -fexcess-precision=fast, the value
- we set for FLT_EVAL_METHOD will be out of line with the actual precision of
- float_t (though they would be correct for -fexcess-precision=standard).
+ With a glibc with that "historic" definition, configure will enable this hook
+ to set FLT_EVAL_METHOD to 1 for -fexcess-precision=standard (e.g., as implied
+ by -std=cXY). That means when we are compiling with -fexcess-precision=fast,
+ the value we set for FLT_EVAL_METHOD will be out of line with the actual
+ precision of float_t.
- A complete fix would modify glibc to remove the unnecessary typedef
- of float_t to double. */
+ Newer versions of glibc will be modified to derive the definition of float_t
+ from FLT_EVAL_METHOD on s390x, as on many other architectures. There,
+ configure will disable this hook by default, so that we defer to the default
+ of FLT_EVAL_METHOD_PROMOTE_TO_FLOAT and a resulting typedef of float_t to
+ float. Note that in that scenario, float_t and FLT_EVAL_METHOD will be in
+ line independent of -fexcess-precision. */
static enum flt_eval_method
s390_excess_precision (enum excess_precision_type type)
@@ -16371,6 +16451,7 @@ s390_excess_precision (enum excess_precision_type type)
}
return FLT_EVAL_METHOD_UNPREDICTABLE;
}
+#endif
/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */
@@ -16667,8 +16748,12 @@ s390_shift_truncation_mask (machine_mode mode)
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
+#if ENABLE_S390_EXCESS_FLOAT_PRECISION == 1
+/* This hook is only needed to maintain the historic behavior with glibc
+ versions that typedef float_t to double. */
#undef TARGET_C_EXCESS_PRECISION
#define TARGET_C_EXCESS_PRECISION s390_excess_precision
+#endif
#undef TARGET_SCHED_ADJUST_PRIORITY
#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index ec5128c..bc579a3 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1186,5 +1186,41 @@ struct GTY(()) machine_function
#define TARGET_INDIRECT_BRANCH_TABLE s390_indirect_branch_table
+#ifdef GENERATOR_FILE
+/* gencondmd.c is built before insn-flags.h. Use an arbitrary opaque value
+ that cannot be optimized away by gen_insn. */
+#define HAVE_TF(icode) TARGET_HARD_FLOAT
+#else
+#define HAVE_TF(icode) (HAVE_##icode##_fpr || HAVE_##icode##_vr)
+#endif
+
+/* Dispatcher for movtf. */
+#define EXPAND_MOVTF(icode) \
+ do \
+ { \
+ if (TARGET_VXE) \
+ emit_insn (gen_##icode##_vr (operands[0], operands[1])); \
+ else \
+ emit_insn (gen_##icode##_fpr (operands[0], operands[1])); \
+ DONE; \
+ } \
+ while (false)
+
+/* Like EXPAND_MOVTF, but also legitimizes operands. */
+#define EXPAND_TF(icode, nops) \
+ do \
+ { \
+ const size_t __nops = (nops); \
+ expand_operand ops[__nops]; \
+ create_output_operand (&ops[0], operands[0], GET_MODE (operands[0])); \
+ for (size_t i = 1; i < __nops; i++) \
+ create_input_operand (&ops[i], operands[i], GET_MODE (operands[i])); \
+ if (TARGET_VXE) \
+ expand_insn (CODE_FOR_##icode##_vr, __nops, ops); \
+ else \
+ expand_insn (CODE_FOR_##icode##_fpr, __nops, ops); \
+ DONE; \
+ } \
+ while (false)
#endif /* S390_H */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 18edea1..d6d8965 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -405,6 +405,7 @@
(PFPO_OP_TYPE_SF 0x5)
(PFPO_OP_TYPE_DF 0x6)
(PFPO_OP_TYPE_TF 0x7)
+ (PFPO_OP_TYPE_FPRX2 0x7)
(PFPO_OP_TYPE_SD 0x8)
(PFPO_OP_TYPE_DD 0x9)
(PFPO_OP_TYPE_TD 0xa)
@@ -627,20 +628,29 @@
;; Iterators
-(define_mode_iterator ALL [TI DI SI HI QI TF DF SF TD DD SD V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF V2SF V4SF V1TI V1DF V2DF V1TF])
+(define_mode_iterator ALL [TI DI SI HI QI TF FPRX2 DF SF TD DD SD V1QI V2QI
+ V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI
+ V1DI V2DI V1SF V2SF V4SF V1TI V1DF V2DF V1TF])
;; These mode iterators allow floating point patterns to be generated from the
;; same template.
-(define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
+(define_mode_iterator FP_ALL [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") DF SF
+ (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
(SD "TARGET_HARD_DFP")])
-(define_mode_iterator FP [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
-(define_mode_iterator BFP [TF DF SF])
+(define_mode_iterator FP [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") DF SF
+ (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
+;; Like FP, but without a condition on TF. Useful for expanders that must be
+;; the same for FP and VR variants of TF.
+(define_mode_iterator FP_ANYTF [TF (FPRX2 "TARGET_VXE") DF SF
+ (TD "TARGET_HARD_DFP")
+ (DD "TARGET_HARD_DFP")])
+(define_mode_iterator BFP [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") DF SF])
(define_mode_iterator DFP [TD DD])
(define_mode_iterator DFP_ALL [TD DD SD])
(define_mode_iterator DSF [DF SF])
(define_mode_iterator SD_SF [SF SD])
(define_mode_iterator DD_DF [DF DD])
-(define_mode_iterator TD_TF [TF TD])
+(define_mode_iterator TD_TF [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") TD])
; 32 bit int<->fp conversion instructions are available since VXE2 (z15).
(define_mode_iterator VX_CONV_BFP [DF (SF "TARGET_VXE2")])
@@ -714,37 +724,36 @@
;; In FP templates, a string like "lt<de>br" will expand to "ltxbr" in
;; TF/TDmode, "ltdbr" in DF/DDmode, and "ltebr" in SF/SDmode.
-(define_mode_attr xde [(TF "x") (DF "d") (SF "e") (TD "x") (DD "d") (SD "e") (V4SF "e") (V2DF "d")])
+(define_mode_attr xde [(TF "x") (FPRX2 "x") (DF "d") (SF "e") (TD "x")
+ (DD "d") (SD "e") (V4SF "e") (V2DF "d")])
;; In FP templates, a <dee> in "m<dee><bt>r" will expand to "mx<bt>r" in
;; TF/TDmode, "md<bt>r" in DF/DDmode, "mee<bt>r" in SFmode and "me<bt>r in
;; SDmode.
(define_mode_attr xdee [(TF "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")])
-;; In FP templates, "<RRe>" will expand to "RRE" in TFmode and "RR" otherwise.
-;; Likewise for "<RXe>".
-(define_mode_attr RRe [(TF "RRE") (DF "RR") (SF "RR")])
-(define_mode_attr RXe [(TF "RXE") (DF "RX") (SF "RX")])
-
;; The decimal floating point variants of add, sub, div and mul support 3
;; fp register operands. The following attributes allow to merge the bfp and
;; dfp variants in a single insn definition.
;; These mode attributes are supposed to be used in the `enabled' insn
;; attribute to disable certain alternatives for certain modes.
-(define_mode_attr nBFP [(TF "0") (DF "0") (SF "0") (TD "*") (DD "*") (DD "*")])
-(define_mode_attr nDFP [(TF "*") (DF "*") (SF "*") (TD "0") (DD "0") (DD "0")])
-(define_mode_attr DSF [(TF "0") (DF "*") (SF "*") (TD "0") (DD "0") (SD "0")])
-(define_mode_attr DFDI [(TF "0") (DF "*") (SF "0")
+(define_mode_attr nBFP [(TF "0") (FPRX2 "0") (DF "0") (SF "0") (TD "*")
+ (DD "*") (DD "*")])
+(define_mode_attr nDFP [(TF "*") (FPRX2 "*") (DF "*") (SF "*") (TD "0")
+ (DD "0") (DD "0")])
+(define_mode_attr DSF [(TF "0") (FPRX2 "0") (DF "*") (SF "*") (TD "0")
+ (DD "0") (SD "0")])
+(define_mode_attr DFDI [(TF "0") (FPRX2 "0") (DF "*") (SF "0")
(TD "0") (DD "0") (DD "0")
(TI "0") (DI "*") (SI "0")])
-(define_mode_attr SFSI [(TF "0") (DF "0") (SF "*")
+(define_mode_attr SFSI [(TF "0") (FPRX2 "0") (DF "0") (SF "*")
(TD "0") (DD "0") (DD "0")
(TI "0") (DI "0") (SI "*")])
-(define_mode_attr DF [(TF "0") (DF "*") (SF "0")
+(define_mode_attr DF [(TF "0") (FPRX2 "0") (DF "*") (SF "0")
(TD "0") (DD "0") (DD "0")
(TI "0") (DI "0") (SI "0")])
-(define_mode_attr SF [(TF "0") (DF "0") (SF "*")
+(define_mode_attr SF [(TF "0") (FPRX2 "0") (DF "0") (SF "*")
(TD "0") (DD "0") (DD "0")
(TI "0") (DI "0") (SI "0")])
@@ -754,15 +763,17 @@
;; sign bit instructions only handle single source and target fp registers
;; these instructions can only be used for TFmode values if the source and
;; target operand uses the same fp register.
-(define_mode_attr fT0 [(TF "0") (DF "f") (SF "f")])
+(define_mode_attr fT0 [(TF "0") (FPRX2 "0") (DF "f") (SF "f")])
;; This attribute adds b for bfp instructions and t for dfp instructions and is used
;; within instruction mnemonics.
-(define_mode_attr bt [(TF "b") (DF "b") (SF "b") (TD "t") (DD "t") (SD "t")])
+(define_mode_attr bt [(TF "b") (FPRX2 "b") (DF "b") (SF "b") (TD "t") (DD "t")
+ (SD "t")])
;; This attribute is used within instruction mnemonics. It evaluates to d for dfp
;; modes and to an empty string for bfp modes.
-(define_mode_attr _d [(TF "") (DF "") (SF "") (TD "d") (DD "d") (SD "d")])
+(define_mode_attr _d [(TF "") (FPRX2 "") (DF "") (SF "") (TD "d") (DD "d")
+ (SD "d")])
;; In GPR and P templates, a constraint like "<d0>" will expand to "d" in DImode
;; and "0" in SImode. This allows to combine instructions of which the 31bit
@@ -834,7 +845,7 @@
;; This attribute expands to DF for TFmode and to DD for TDmode . It is
;; used for Txmode splitters splitting a Txmode copy into 2 Dxmode copies.
-(define_mode_attr HALF_TMODE [(TF "DF") (TD "DD")])
+(define_mode_attr HALF_TMODE [(TF "DF") (FPRX2 "DF") (TD "DD")])
;; Maximum unsigned integer that fits in MODE.
(define_mode_attr max_uint [(HI "65535") (QI "255")])
@@ -855,6 +866,13 @@
;; Allow return and simple_return to be defined from a single template.
(define_code_iterator ANY_RETURN [return simple_return])
+;; Facilitate dispatching TFmode expanders on z14+.
+(define_mode_attr tf_fpr [(TF "_fpr") (FPRX2 "") (DF "") (SF "") (TD "")
+ (DD "") (SD "")])
+
+;; Mode names as seen in type mode_attr values.
+(define_mode_attr type [(TF "tf") (FPRX2 "tf") (DF "df") (SF "sf") (TD "td")
+ (DD "dd") (SD "sd")])
; Condition code modes generated by vector fp comparisons. These will
@@ -1426,7 +1444,7 @@
"TARGET_HARD_FLOAT"
"lt<xde><bt>r\t%0,%0"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
(define_insn "*cmp<mode>_ccs_0_fastmath"
[(set (reg CC_REGNUM)
@@ -1438,7 +1456,7 @@
&& !flag_signaling_nans"
"lt<xde><bt>r\t%0,%0"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; VX: TFmode in FPR pairs: use cxbr instead of wfcxb
; cxtr, cdtr, cxbr, cdbr, cebr, cdb, ceb, wfcsb, wfcdb
@@ -1456,6 +1474,18 @@
(set_attr "cpu_facility" "*,*,vx,vxe")
(set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
+; VX: TFmode in VR: use wfcxb
+(define_insn "*cmptf_ccs"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:TF 0 "register_operand" "v")
+ (match_operand:TF 1 "register_operand" "v")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_VXE"
+ "wfcxb\t%0,%1"
+ [(set_attr "op_type" "VRR")
+ (set_attr "cpu_facility" "vxe")])
+
+; VX: TFmode in FPR pairs: use kxbr instead of wfkxb
+; kxtr, kdtr, kxbr, kdbr, kebr, kdb, keb, wfksb, wfkdb
(define_insn "*cmp<mode>_ccsfps"
[(set (reg CC_REGNUM)
(compare (match_operand:FP 0 "register_operand" "f,f,v,v")
@@ -1470,6 +1500,16 @@
(set_attr "cpu_facility" "*,*,vx,vxe")
(set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
+; VX: TFmode in VR: use wfkxb
+(define_insn "*cmptf_ccsfps"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:TF 0 "register_operand" "v")
+ (match_operand:TF 1 "register_operand" "v")))]
+ "s390_match_ccmode (insn, CCSFPSmode) && TARGET_VXE"
+ "wfkxb\t%0,%1"
+ [(set_attr "op_type" "VRR")
+ (set_attr "cpu_facility" "vxe")])
+
; Compare and Branch instructions
; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
@@ -2076,6 +2116,29 @@
[(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
"")
+; Split loading of 64-bit constants into GPRs into llihf + oilf -
+; counterintuitively, using oilf is faster than iilf. oilf clobbers
+; cc, so cc must be dead.
+(define_peephole2
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "memory_operand" ""))]
+ "TARGET_64BIT
+ && TARGET_EXTIMM
+ && GENERAL_REG_P (operands[0])
+ && s390_const_int_pool_entry_p (operands[1], nullptr)
+ && peep2_reg_dead_p (1, gen_rtx_REG (CCmode, CC_REGNUM))"
+ [(set (match_dup 0) (match_dup 2))
+ (parallel
+ [(set (match_dup 0) (ior:DI (match_dup 0) (match_dup 3)))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ HOST_WIDE_INT val;
+ bool ok = s390_const_int_pool_entry_p (operands[1], &val);
+ gcc_assert (ok);
+ operands[2] = GEN_INT (val & 0xFFFFFFFF00000000ULL);
+ operands[3] = GEN_INT (val & 0x00000000FFFFFFFFULL);
+})
+
;
; movsi instruction pattern(s).
;
@@ -2494,7 +2557,7 @@
; mov(tf|td) instruction pattern(s).
;
-(define_expand "mov<mode>"
+(define_expand "mov<mode><tf_fpr>"
[(set (match_operand:TD_TF 0 "nonimmediate_operand" "")
(match_operand:TD_TF 1 "general_operand" ""))]
""
@@ -3423,7 +3486,7 @@
; Test data class.
;
-(define_expand "signbit<mode>2"
+(define_expand "signbit<mode>2<tf_fpr>"
[(set (reg:CCZ CC_REGNUM)
(unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
(match_dup 2)]
@@ -3435,7 +3498,7 @@
operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
})
-(define_expand "isinf<mode>2"
+(define_expand "isinf<mode>2<tf_fpr>"
[(set (reg:CCZ CC_REGNUM)
(unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
(match_dup 2)]
@@ -3473,7 +3536,7 @@
"TARGET_HARD_FLOAT"
"t<_d>c<xde><bt>\t%0,%1"
[(set_attr "op_type" "RXE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
@@ -4989,7 +5052,7 @@
; This is the only entry point for fixuns_trunc. It multiplexes the
; expansion to either the *_emu expanders below for pre z196 machines
; or emits the default pattern otherwise.
-(define_expand "fixuns_trunc<FP:mode><GPR:mode>2"
+(define_expand "fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>"
[(parallel
[(set (match_operand:GPR 0 "register_operand" "")
(unsigned_fix:GPR (match_operand:FP 1 "register_operand" "")))
@@ -5252,12 +5315,12 @@
; fix_trunctf(si|di)2 instruction pattern(s).
;
-(define_expand "fix_trunctf<mode>2"
+(define_expand "fix_trunctf<mode>2_fpr"
[(parallel [(set (match_operand:GPR 0 "register_operand" "")
(fix:GPR (match_operand:TF 1 "register_operand" "")))
(unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
(clobber (reg:CC CC_REGNUM))])]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && !TARGET_VXE"
"")
@@ -5266,7 +5329,7 @@
;
; cxgbr, cdgbr, cegbr, cxgtr, cdgtr
-(define_insn "floatdi<mode>2"
+(define_insn "floatdi<mode>2<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "=f,v")
(float:FP (match_operand:DI 1 "register_operand" "d,v")))]
"TARGET_ZARCH && TARGET_HARD_FLOAT"
@@ -5274,12 +5337,12 @@
c<xde>g<bt>r\t%0,%1
wcdgb\t%v0,%v1,0,0"
[(set_attr "op_type" "RRE,VRR")
- (set_attr "type" "itof<mode>" )
+ (set_attr "type" "itof<type>" )
(set_attr "cpu_facility" "*,vx")
(set_attr "enabled" "*,<DFDI>")])
; cxfbr, cdfbr, cefbr, wcefb
-(define_insn "floatsi<mode>2"
+(define_insn "floatsi<mode>2<tf_fpr>"
[(set (match_operand:BFP 0 "register_operand" "=f,v")
(float:BFP (match_operand:SI 1 "register_operand" "d,v")))]
"TARGET_HARD_FLOAT"
@@ -5287,7 +5350,7 @@
c<xde>fbr\t%0,%1
wcefb\t%v0,%v1,0,0"
[(set_attr "op_type" "RRE,VRR")
- (set_attr "type" "itof<mode>" )
+ (set_attr "type" "itof<type>" )
(set_attr "cpu_facility" "*,vxe2")
(set_attr "enabled" "*,<SFSI>")])
@@ -5298,7 +5361,7 @@
"TARGET_Z196 && TARGET_HARD_FLOAT"
"c<xde>ftr\t%0,0,%1,0"
[(set_attr "op_type" "RRE")
- (set_attr "type" "itof<mode>" )])
+ (set_attr "type" "itof<type>")])
;
; floatuns(si|di)(tf|df|sf|td|dd)2 instruction pattern(s).
@@ -5324,9 +5387,9 @@
&& (!TARGET_VX || <FP:MODE>mode != DFmode || <GPR:MODE>mode != DImode)"
"c<FP:xde>l<GPR:gf><FP:bt>r\t%0,0,%1,0"
[(set_attr "op_type" "RRE")
- (set_attr "type" "itof<FP:mode>")])
+ (set_attr "type" "itof<FP:type>")])
-(define_expand "floatuns<GPR:mode><FP:mode>2"
+(define_expand "floatuns<GPR:mode><FP:mode>2<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "")
(unsigned_float:FP (match_operand:GPR 1 "register_operand" "")))]
"TARGET_Z196 && TARGET_HARD_FLOAT")
@@ -5352,7 +5415,7 @@
;
; ldxbr, lexbr
-(define_insn "trunctf<mode>2"
+(define_insn "trunctf<mode>2_fpr"
[(set (match_operand:DSF 0 "register_operand" "=f")
(float_truncate:DSF (match_operand:TF 1 "register_operand" "f")))
(clobber (match_scratch:TF 2 "=f"))]
@@ -5432,9 +5495,9 @@
l<BFP:xde><DSF:xde>br\t%0,%1
l<BFP:xde><DSF:xde>b\t%0,%1"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimp<BFP:mode>, fload<BFP:mode>")])
+ (set_attr "type" "fsimp<BFP:type>, fload<BFP:type>")])
-(define_expand "extend<DSF:mode><BFP:mode>2"
+(define_expand "extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>"
[(set (match_operand:BFP 0 "register_operand" "")
(float_extend:BFP (match_operand:DSF 1 "nonimmediate_operand" "")))]
"TARGET_HARD_FLOAT
@@ -5476,27 +5539,27 @@
; For all of them the inexact exceptions are suppressed.
; fiebra, fidbra, fixbra
-(define_insn "<FPINT:fpint_name><BFP:mode>2"
+(define_insn "<FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>"
[(set (match_operand:BFP 0 "register_operand" "=f")
(unspec:BFP [(match_operand:BFP 1 "register_operand" "f")]
FPINT))]
"TARGET_Z196"
"fi<BFP:xde>bra\t%0,<FPINT:fpint_roundingmode>,%1,4"
[(set_attr "op_type" "RRF")
- (set_attr "type" "fsimp<BFP:mode>")])
+ (set_attr "type" "fsimp<BFP:type>")])
; rint is supposed to raise an inexact exception so we can use the
; older instructions.
; fiebr, fidbr, fixbr
-(define_insn "rint<BFP:mode>2"
+(define_insn "rint<BFP:mode>2<BFP:tf_fpr>"
[(set (match_operand:BFP 0 "register_operand" "=f")
(unspec:BFP [(match_operand:BFP 1 "register_operand" "f")]
UNSPEC_FPINT_RINT))]
""
"fi<BFP:xde>br\t%0,0,%1"
[(set_attr "op_type" "RRF")
- (set_attr "type" "fsimp<BFP:mode>")])
+ (set_attr "type" "fsimp<BFP:type>")])
; Decimal Floating Point - load fp integer
@@ -5509,7 +5572,7 @@
"TARGET_HARD_DFP"
"fi<DFP:xde>tr\t%0,<FPINT:fpint_roundingmode>,%1,4"
[(set_attr "op_type" "RRF")
- (set_attr "type" "fsimp<DFP:mode>")])
+ (set_attr "type" "fsimp<DFP:type>")])
; fidtr, fixtr
(define_insn "rint<DFP:mode>2"
@@ -5519,7 +5582,7 @@
"TARGET_HARD_DFP"
"fi<DFP:xde>tr\t%0,0,%1,0"
[(set_attr "op_type" "RRF")
- (set_attr "type" "fsimp<DFP:mode>")])
+ (set_attr "type" "fsimp<DFP:type>")])
;
; Binary <-> Decimal floating point trunc patterns
@@ -5543,7 +5606,7 @@
"TARGET_HARD_DFP"
"pfpo")
-(define_expand "trunc<BFP:mode><DFP_ALL:mode>2"
+(define_expand "trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>"
[(set (reg:BFP FPR4_REGNUM) (match_operand:BFP 1 "nonimmediate_operand" ""))
(set (reg:SI GPR0_REGNUM) (match_dup 2))
(parallel
@@ -5570,7 +5633,7 @@
operands[2] = GEN_INT (flags);
})
-(define_expand "trunc<DFP_ALL:mode><BFP:mode>2"
+(define_expand "trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>"
[(set (reg:DFP_ALL FPR4_REGNUM)
(match_operand:DFP_ALL 1 "nonimmediate_operand" ""))
(set (reg:SI GPR0_REGNUM) (match_dup 2))
@@ -5616,7 +5679,7 @@
"TARGET_HARD_DFP"
"pfpo")
-(define_expand "extend<BFP:mode><DFP_ALL:mode>2"
+(define_expand "extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>"
[(set (reg:BFP FPR4_REGNUM) (match_operand:BFP 1 "nonimmediate_operand" ""))
(set (reg:SI GPR0_REGNUM) (match_dup 2))
(parallel
@@ -5643,7 +5706,7 @@
operands[2] = GEN_INT (flags);
})
-(define_expand "extend<DFP_ALL:mode><BFP:mode>2"
+(define_expand "extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>"
[(set (reg:DFP_ALL FPR4_REGNUM)
(match_operand:DFP_ALL 1 "nonimmediate_operand" ""))
(set (reg:SI GPR0_REGNUM) (match_dup 2))
@@ -6122,7 +6185,7 @@
; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
; FIXME: wfadb does not clobber cc
-(define_insn "add<mode>3"
+(define_insn "add<mode>3<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "=f,f,f,v,v")
(plus:FP (match_operand:FP 1 "nonimmediate_operand" "%f,0,0,v,v")
(match_operand:FP 2 "general_operand" "f,f,R,v,v")))
@@ -6135,7 +6198,7 @@
wfadb\t%v0,%v1,%v2
wfasb\t%v0,%v1,%v2"
[(set_attr "op_type" "RRF,RRE,RXE,VRR,VRR")
- (set_attr "type" "fsimp<mode>")
+ (set_attr "type" "fsimp<type>")
(set_attr "cpu_facility" "*,*,*,vx,vxe")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
@@ -6153,7 +6216,7 @@
a<xde>br\t%0,%2
a<xde>b\t%0,%2"
[(set_attr "op_type" "RRF,RRE,RXE")
- (set_attr "type" "fsimp<mode>")
+ (set_attr "type" "fsimp<type>")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>")])
; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
@@ -6169,7 +6232,7 @@
a<xde>br\t%0,%2
a<xde>b\t%0,%2"
[(set_attr "op_type" "RRF,RRE,RXE")
- (set_attr "type" "fsimp<mode>")
+ (set_attr "type" "fsimp<type>")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>")])
;
@@ -6567,7 +6630,7 @@
; FIXME: (clobber (match_scratch:CC 3 "=c,c,c,X,X")) does not work - why?
; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
-(define_insn "sub<mode>3"
+(define_insn "sub<mode>3<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "=f,f,f,v,v")
(minus:FP (match_operand:FP 1 "register_operand" "f,0,0,v,v")
(match_operand:FP 2 "general_operand" "f,f,R,v,v")))
@@ -6580,7 +6643,7 @@
wfsdb\t%v0,%v1,%v2
wfssb\t%v0,%v1,%v2"
[(set_attr "op_type" "RRF,RRE,RXE,VRR,VRR")
- (set_attr "type" "fsimp<mode>")
+ (set_attr "type" "fsimp<type>")
(set_attr "cpu_facility" "*,*,*,vx,vxe")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
@@ -6598,7 +6661,7 @@
s<xde>br\t%0,%2
s<xde>b\t%0,%2"
[(set_attr "op_type" "RRF,RRE,RXE")
- (set_attr "type" "fsimp<mode>")
+ (set_attr "type" "fsimp<type>")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>")])
; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
@@ -6614,7 +6677,7 @@
s<xde>br\t%0,%2
s<xde>b\t%0,%2"
[(set_attr "op_type" "RRF,RRE,RXE")
- (set_attr "type" "fsimp<mode>")
+ (set_attr "type" "fsimp<type>")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>")])
@@ -7148,7 +7211,7 @@
;
; mxbr, mdbr, meebr, mxb, mxb, meeb, mdtr, mxtr
-(define_insn "mul<mode>3"
+(define_insn "mul<mode>3<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "=f,f,f,v,v")
(mult:FP (match_operand:FP 1 "nonimmediate_operand" "%f,0,0,v,v")
(match_operand:FP 2 "general_operand" "f,f,R,v,v")))]
@@ -7160,7 +7223,7 @@
wfmdb\t%v0,%v1,%v2
wfmsb\t%v0,%v1,%v2"
[(set_attr "op_type" "RRF,RRE,RXE,VRR,VRR")
- (set_attr "type" "fmul<mode>")
+ (set_attr "type" "fmul<type>")
(set_attr "cpu_facility" "*,*,*,vx,vxe")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
@@ -7170,7 +7233,7 @@
(fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f,v,v")
(match_operand:DSF 2 "nonimmediate_operand" "f,R,v,v")
(match_operand:DSF 3 "register_operand" "0,0,v,v")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && s390_fma_allowed_p (<MODE>mode)"
"@
ma<xde>br\t%0,%1,%2
ma<xde>b\t%0,%1,%2
@@ -7187,7 +7250,7 @@
(fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f,v,v")
(match_operand:DSF 2 "nonimmediate_operand" "f,R,v,v")
(neg:DSF (match_operand:DSF 3 "register_operand" "0,0,v,v"))))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && s390_fma_allowed_p (<MODE>mode)"
"@
ms<xde>br\t%0,%1,%2
ms<xde>b\t%0,%1,%2
@@ -7453,7 +7516,7 @@
;
; dxbr, ddbr, debr, dxb, ddb, deb, ddtr, dxtr
-(define_insn "div<mode>3"
+(define_insn "div<mode>3<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "=f,f,f,v,v")
(div:FP (match_operand:FP 1 "register_operand" "f,0,0,v,v")
(match_operand:FP 2 "general_operand" "f,f,R,v,v")))]
@@ -7465,7 +7528,7 @@
wfddb\t%v0,%v1,%v2
wfdsb\t%v0,%v1,%v2"
[(set_attr "op_type" "RRF,RRE,RXE,VRR,VRR")
- (set_attr "type" "fdiv<mode>")
+ (set_attr "type" "fdiv<type>")
(set_attr "cpu_facility" "*,*,*,vx,vxe")
(set_attr "enabled" "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
@@ -8782,10 +8845,10 @@
operands[6] = gen_label_rtx ();")
;
-; neg(df|sf)2 instruction pattern(s).
+; neg(tf|df|sf)2 instruction pattern(s).
;
-(define_expand "neg<mode>2"
+(define_expand "neg<mode>2<tf_fpr>"
[(parallel
[(set (match_operand:BFP 0 "register_operand")
(neg:BFP (match_operand:BFP 1 "register_operand")))
@@ -8802,7 +8865,7 @@
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
"lc<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lcxbr, lcdbr, lcebr
(define_insn "*neg<mode>2_cconly"
@@ -8813,7 +8876,7 @@
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
"lc<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lcdfr
(define_insn "*neg<mode>2_nocc"
@@ -8822,7 +8885,7 @@
"TARGET_DFP"
"lcdfr\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lcxbr, lcdbr, lcebr
; FIXME: wflcdb does not clobber cc
@@ -8838,7 +8901,7 @@
wflcsb\t%0,%1"
[(set_attr "op_type" "RRE,VRR,VRR")
(set_attr "cpu_facility" "*,vx,vxe")
- (set_attr "type" "fsimp<mode>,*,*")
+ (set_attr "type" "fsimp<type>,*,*")
(set_attr "enabled" "*,<DF>,<SF>")])
@@ -8906,10 +8969,10 @@
(set_attr "z10prop" "z10_c")])
;
-; abs(df|sf)2 instruction pattern(s).
+; abs(tf|df|sf)2 instruction pattern(s).
;
-(define_expand "abs<mode>2"
+(define_expand "abs<mode>2<tf_fpr>"
[(parallel
[(set (match_operand:BFP 0 "register_operand" "=f")
(abs:BFP (match_operand:BFP 1 "register_operand" "f")))
@@ -8927,7 +8990,7 @@
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
"lp<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lpxbr, lpdbr, lpebr
(define_insn "*abs<mode>2_cconly"
@@ -8938,7 +9001,7 @@
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
"lp<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lpdfr
(define_insn "*abs<mode>2_nocc"
@@ -8947,7 +9010,7 @@
"TARGET_DFP"
"lpdfr\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lpxbr, lpdbr, lpebr
; FIXME: wflpdb does not clobber cc
@@ -8961,7 +9024,7 @@
wflpdb\t%0,%1"
[(set_attr "op_type" "RRE,VRR")
(set_attr "cpu_facility" "*,vx")
- (set_attr "type" "fsimp<mode>,*")
+ (set_attr "type" "fsimp<type>,*")
(set_attr "enabled" "*,<DFDI>")])
@@ -9043,7 +9106,7 @@
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
"ln<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lnxbr, lndbr, lnebr
(define_insn "*negabs<mode>2_cconly"
@@ -9054,7 +9117,7 @@
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
"ln<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lndfr
(define_insn "*negabs<mode>2_nocc"
@@ -9063,7 +9126,7 @@
"TARGET_DFP"
"lndfr\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
; lnxbr, lndbr, lnebr
; FIXME: wflndb does not clobber cc
@@ -9077,7 +9140,7 @@
wflndb\t%0,%1"
[(set_attr "op_type" "RRE,VRR")
(set_attr "cpu_facility" "*,vx")
- (set_attr "type" "fsimp<mode>,*")
+ (set_attr "type" "fsimp<type>,*")
(set_attr "enabled" "*,<DFDI>")])
;;
@@ -9089,7 +9152,7 @@
;
; sqxbr, sqdbr, sqebr, sqdb, sqeb
-(define_insn "sqrt<mode>2"
+(define_insn "sqrt<mode>2<tf_fpr>"
[(set (match_operand:BFP 0 "register_operand" "=f,f,v")
(sqrt:BFP (match_operand:BFP 1 "general_operand" "f,R,v")))]
"TARGET_HARD_FLOAT"
@@ -9098,7 +9161,7 @@
sq<xde>b\t%0,%1
wfsqdb\t%v0,%v1"
[(set_attr "op_type" "RRE,RXE,VRR")
- (set_attr "type" "fsqrt<mode>")
+ (set_attr "type" "fsqrt<type>")
(set_attr "cpu_facility" "*,*,vx")
(set_attr "enabled" "*,<DSF>,<DFDI>")])
@@ -9299,8 +9362,8 @@
(define_expand "cbranch<mode>4"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:FP 1 "register_operand" "")
- (match_operand:FP 2 "general_operand" "")])
+ [(match_operand:FP_ANYTF 1 "register_operand" "")
+ (match_operand:FP_ANYTF 2 "general_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_HARD_FLOAT"
@@ -11053,8 +11116,8 @@
(define_expand "@probe_stack2<mode>"
[(set (reg:CCZ CC_REGNUM)
- (compare:CCZ (reg:P 0)
- (match_operand 0 "memory_operand")))
+ (compare:CCZ (reg:W 0)
+ (match_operand:W 0 "memory_operand")))
(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
"")
@@ -11062,7 +11125,7 @@
[(match_operand 0 "memory_operand")]
""
{
- emit_insn (gen_probe_stack2 (Pmode, operands[0]));
+ emit_insn (gen_probe_stack2 (word_mode, operands[0]));
DONE;
})
@@ -11250,7 +11313,7 @@
""
{
switch_to_section (targetm.asm_out.function_rodata_section
- (current_function_decl));
+ (current_function_decl, false));
return "";
}
[(set_attr "length" "0")])
@@ -11795,7 +11858,7 @@
;;- Copy sign instructions
;;
-(define_insn "copysign<mode>3"
+(define_insn "copysign<mode>3<tf_fpr>"
[(set (match_operand:FP 0 "register_operand" "=f")
(unspec:FP [(match_operand:FP 1 "register_operand" "<fT0>")
(match_operand:FP 2 "register_operand" "f")]
@@ -11803,7 +11866,7 @@
"TARGET_Z196"
"cpsdr\t%0,%2,%1"
[(set_attr "op_type" "RRF")
- (set_attr "type" "fsimp<mode>")])
+ (set_attr "type" "fsimp<type>")])
;;
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index 300309c..4bee312 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -44,11 +44,11 @@ Variable
long s390_cost_pointer
m31
-Target Report RejectNegative Negative(m64) InverseMask(64BIT)
+Target RejectNegative Negative(m64) InverseMask(64BIT)
31 bit ABI.
m64
-Target Report RejectNegative Negative(m31) Mask(64BIT)
+Target RejectNegative Negative(m31) Mask(64BIT)
64 bit ABI.
march=
@@ -119,27 +119,27 @@ EnumValue
Enum(processor_type) String(native) Value(PROCESSOR_NATIVE) DriverOnly
mbackchain
-Target Report Mask(BACKCHAIN) Save
+Target Mask(BACKCHAIN) Save
Maintain backchain pointer.
mdebug
-Target Report Mask(DEBUG_ARG) Save
+Target Mask(DEBUG_ARG) Save
Additional debug prints.
mesa
-Target Report RejectNegative Negative(mzarch) InverseMask(ZARCH)
+Target RejectNegative Negative(mzarch) InverseMask(ZARCH)
ESA/390 architecture.
mhard-dfp
-Target Report Mask(HARD_DFP) Save
+Target Mask(HARD_DFP) Save
Enable decimal floating point hardware support.
mhard-float
-Target Report RejectNegative Negative(msoft-float) InverseMask(SOFT_FLOAT, HARD_FLOAT) Save
+Target RejectNegative Negative(msoft-float) InverseMask(SOFT_FLOAT, HARD_FLOAT) Save
Enable hardware floating point.
mhotpatch=
-Target RejectNegative Report Joined Var(s390_deferred_options) Defer
+Target RejectNegative Joined Var(s390_deferred_options) Defer
Takes two non-negative integer numbers separated by a comma.
Prepend the function label with the number of two-byte Nop
instructions indicated by the first. Append Nop instructions
@@ -149,31 +149,31 @@ label. Nop instructions of the largest possible size are used
size. Using 0 for both values disables hotpatching.
mlong-double-128
-Target Report RejectNegative Negative(mlong-double-64) Mask(LONG_DOUBLE_128)
+Target RejectNegative Negative(mlong-double-64) Mask(LONG_DOUBLE_128)
Use 128-bit long double.
mlong-double-64
-Target Report RejectNegative Negative(mlong-double-128) InverseMask(LONG_DOUBLE_128)
+Target RejectNegative Negative(mlong-double-128) InverseMask(LONG_DOUBLE_128)
Use 64-bit long double.
mhtm
-Target Report Mask(OPT_HTM) Save
+Target Mask(OPT_HTM) Save
Use hardware transactional execution instructions.
mvx
-Target Report Mask(OPT_VX) Save
+Target Mask(OPT_VX) Save
Use hardware vector facility instructions and enable the vector ABI.
mpacked-stack
-Target Report Mask(PACKED_STACK) Save
+Target Mask(PACKED_STACK) Save
Use packed stack layout.
msmall-exec
-Target Report Mask(SMALL_EXEC) Save
+Target Mask(SMALL_EXEC) Save
Use bras for executable < 64k.
msoft-float
-Target Report RejectNegative Negative(mhard-float) Mask(SOFT_FLOAT) Save
+Target RejectNegative Negative(mhard-float) Mask(SOFT_FLOAT) Save
Disable hardware floating point.
mstack-guard=
@@ -197,11 +197,11 @@ Target RejectNegative Joined Enum(processor_type) Var(s390_tune) Init(PROCESSOR_
Schedule code for given CPU.
mmvcle
-Target Report Mask(MVCLE) Save
+Target Mask(MVCLE) Save
Use the mvcle instruction for block moves.
mzvector
-Target Report Mask(ZVECTOR) Save
+Target Mask(ZVECTOR) Save
Enable the z vector language extension providing the context-sensitive
vector macro and enable the Altivec-style builtins in vecintrin.h.
@@ -214,31 +214,31 @@ Target RejectNegative Joined UInteger Var(s390_warn_framesize) Save
Warn if a single function's framesize exceeds the given framesize.
mzarch
-Target Report RejectNegative Negative(mesa) Mask(ZARCH)
+Target RejectNegative Negative(mesa) Mask(ZARCH)
z/Architecture.
mbranch-cost=
-Target Report Joined RejectNegative UInteger Var(s390_branch_cost) Init(1) Save
+Target Joined RejectNegative UInteger Var(s390_branch_cost) Init(1) Save
Set the branch costs for conditional branch instructions. Reasonable
values are small, non-negative integers. The default branch cost is
1.
mlra
-Target Report Var(s390_lra_flag) Init(1) Save
+Target Var(s390_lra_flag) Init(1) Save
Use LRA instead of reload.
mpic-data-is-text-relative
-Target Report Var(s390_pic_data_is_text_relative) Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE)
+Target Var(s390_pic_data_is_text_relative) Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE)
Assume data segments are relative to text segment.
mindirect-branch=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch) Init(indirect_branch_keep)
Wrap all indirect branches into execute in order to disable branch
prediction.
mindirect-branch-jump=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch_jump) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch_jump) Init(indirect_branch_keep)
Wrap indirect table jumps and computed gotos into execute in order to
disable branch prediction. Using thunk or thunk-extern with this
option requires the thunks to be considered signal handlers to order to
@@ -246,22 +246,22 @@ generate correct CFI. For environments where unwinding (e.g. for
exceptions) is required please use thunk-inline instead.
mindirect-branch-call=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch_call) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch_call) Init(indirect_branch_keep)
Wrap all indirect calls into execute in order to disable branch prediction.
mfunction-return=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_function_return) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(s390_function_return) Init(indirect_branch_keep)
Wrap all indirect return branches into execute in order to disable branch
prediction.
mfunction-return-mem=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_function_return_mem) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(s390_function_return_mem) Init(indirect_branch_keep)
Wrap indirect return branches into execute in order to disable branch
prediction. This affects only branches where the return address is
going to be restored from memory.
mfunction-return-reg=
-Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_function_return_reg) Init(indirect_branch_keep)
+Target RejectNegative Joined Enum(indirect_branch) Var(s390_function_return_reg) Init(indirect_branch_keep)
Wrap indirect return branches into execute in order to disable branch
prediction. This affects only branches where the return address
doesn't need to be restored from memory.
@@ -283,7 +283,7 @@ EnumValue
Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
mindirect-branch-table
-Target Report Var(s390_indirect_branch_table) Init(TARGET_DEFAULT_INDIRECT_BRANCH_TABLE)
+Target Var(s390_indirect_branch_table) Init(TARGET_DEFAULT_INDIRECT_BRANCH_TABLE)
Generate sections .s390_indirect_jump, .s390_indirect_call,
.s390_return_reg, and .s390_return_mem to contain the indirect branch
locations which have been patched as part of using one of the
@@ -292,15 +292,26 @@ consist of an array of 32 bit elements. Each entry holds the offset
from the entry to the patched location.
mfentry
-Target Report Var(flag_fentry)
+Target Var(flag_fentry)
Emit profiling counter call at function entry before prologue. The compiled
code will require a 64-bit CPU and glibc 2.29 or newer to run.
mrecord-mcount
-Target Report Var(flag_record_mcount)
+Target Var(flag_record_mcount)
Generate __mcount_loc section with all _mcount and __fentry__ calls.
mnop-mcount
-Target Report Var(flag_nop_mcount)
+Target Var(flag_nop_mcount)
Generate mcount/__fentry__ calls as nops. To activate they need to be
patched in.
+
+mvx-long-double-fma
+Target Undocumented Var(flag_vx_long_double_fma)
+Emit fused multiply-add instructions for long doubles in vector registers
+(wfmaxb, wfmsxb, wfnmaxb, wfnmsxb). Reassociation pass does not handle
+fused multiply-adds, therefore code generated by the middle-end is prone to
+having long fused multiply-add chains. This is not pipeline-friendly,
+and the default behavior is to emit separate multiplication and addition
+instructions for long doubles in vector registers, because measurements show
+that this improves performance. This option allows overriding it for testing
+purposes.
diff --git a/gcc/config/s390/tpf.opt b/gcc/config/s390/tpf.opt
index 9876a55..6132803 100644
--- a/gcc/config/s390/tpf.opt
+++ b/gcc/config/s390/tpf.opt
@@ -19,29 +19,29 @@
; <http://www.gnu.org/licenses/>.
mtpf-trace
-Target Report Mask(TPF_PROFILING)
+Target Mask(TPF_PROFILING)
Enable TPF-OS tracing code.
mtpf-trace-hook-prologue-check=
-Target RejectNegative Report Joined UInteger Var(s390_tpf_trace_hook_prologue_check) Init(TPF_TRACE_PROLOGUE_CHECK)
+Target RejectNegative Joined UInteger Var(s390_tpf_trace_hook_prologue_check) Init(TPF_TRACE_PROLOGUE_CHECK)
Set the trace check address for prologue tpf hook
mtpf-trace-hook-prologue-target=
-Target RejectNegative Report Joined UInteger Var(s390_tpf_trace_hook_prologue_target) Init(TPF_TRACE_PROLOGUE_TARGET)
+Target RejectNegative Joined UInteger Var(s390_tpf_trace_hook_prologue_target) Init(TPF_TRACE_PROLOGUE_TARGET)
Set the trace jump address for prologue tpf hook
mtpf-trace-hook-epilogue-check=
-Target RejectNegative Report Joined UInteger Var(s390_tpf_trace_hook_epilogue_check) Init(TPF_TRACE_EPILOGUE_CHECK)
+Target RejectNegative Joined UInteger Var(s390_tpf_trace_hook_epilogue_check) Init(TPF_TRACE_EPILOGUE_CHECK)
Set the trace check address for epilogue tpf hook
mtpf-trace-hook-epilogue-target=
-Target RejectNegative Report Joined UInteger Var(s390_tpf_trace_hook_epilogue_target) Init(TPF_TRACE_EPILOGUE_TARGET)
+Target RejectNegative Joined UInteger Var(s390_tpf_trace_hook_epilogue_target) Init(TPF_TRACE_EPILOGUE_TARGET)
Set the trace jump address for epilogue tpf hook
mtpf-trace-skip
-Target Report Var(s390_tpf_trace_skip) Init(0)
+Target Var(s390_tpf_trace_skip) Init(0)
Set the prologue and epilogue hook addresses to TPF_TRACE_PROLOGUE_SKIP_TARGET and TPF_TRACE_EPILOGUE_SKIP_TARGET. Equivalent to using -mtpf-trace-hook-prologue-target=TPF_TRACE_PROLOGUE_SKIP_TARGET and -mtpf-trace-hook-epilogue-target=TPF_TRACE_EPILOGUE_SKIP_TARGET
mmain
-Target Report
+Target
Specify main object for TPF-OS.
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 3c01cd1..029ee08 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -27,10 +27,14 @@
V2SF V4SF V1DF V2DF V1TF V1TI TI])
; All modes directly supported by the hardware having full vector reg size
-; V_HW2 is duplicate of V_HW for having two iterators expanding
-; independently e.g. vcond
-(define_mode_iterator V_HW [V16QI V8HI V4SI V2DI (V1TI "TARGET_VXE") V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
-(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
+; V_HW2 is for having two iterators expanding independently e.g. vcond.
+; It's similar to V_HW, but not fully identical: V1TI is not included, because
+; there are no 128-bit compares.
+(define_mode_iterator V_HW [V16QI V8HI V4SI V2DI (V1TI "TARGET_VXE") V2DF
+ (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")
+ (TF "TARGET_VXE")])
+(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE")
+ (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
(define_mode_iterator V_HW_64 [V2DI V2DF])
(define_mode_iterator VT_HW_HSDT [V8HI V4SI V4SF V2DI V2DF V1TI V1TF TI TF])
@@ -55,19 +59,20 @@
(define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
V1DF V2DF
- (V1TF "TARGET_VXE")])
+ (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
; FP vector modes directly supported by the HW. This does not include
; vector modes using only part of a vector register and should be used
; for instructions which might trigger IEEE exceptions.
-(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")])
+(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")
+ (TF "TARGET_VXE")])
(define_mode_iterator V_8 [V1QI])
(define_mode_iterator V_16 [V2QI V1HI])
(define_mode_iterator V_32 [V4QI V2HI V1SI V1SF])
(define_mode_iterator V_64 [V8QI V4HI V2SI V2SF V1DI V1DF])
-(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF])
-
+(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF
+ (TF "TARGET_VXE")])
(define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF])
; 32 bit int<->fp vector conversion instructions are available since VXE2 (z15).
@@ -86,6 +91,11 @@
(V1DF "") (V2DF "")
(V1TF "") (TF "")])
+;; Facilitate dispatching TFmode expanders on z14+.
+(define_mode_attr tf_vr [(TF "_vr") (V4SF "") (V2DF "") (V1TF "") (V1SF "")
+ (V2SF "") (V1DF "") (V16QI "") (V8HI "") (V4SI "")
+ (V2DI "") (V1TI "")])
+
; The element type of the vector.
(define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
(V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
@@ -127,14 +137,24 @@
; Resulting mode of a vector comparison. For floating point modes an
; integer vector mode with the same element size is picked.
-(define_mode_attr tointvec [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI")
+(define_mode_attr TOINTVEC [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8QI") (V16QI "V16QI")
(V1HI "V1HI") (V2HI "V2HI") (V4HI "V4HI") (V8HI "V8HI")
(V1SI "V1SI") (V2SI "V2SI") (V4SI "V4SI")
(V1DI "V1DI") (V2DI "V2DI")
(V1TI "V1TI")
(V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
(V1DF "V1DI") (V2DF "V2DI")
- (V1TF "V1TI")])
+ (V1TF "V1TI") (TF "V1TI")])
+
+(define_mode_attr tointvec [(V1QI "v1qi") (V2QI "v2qi") (V4QI "v4qi") (V8QI "v8qi") (V16QI "v16qi")
+ (V1HI "v1hi") (V2HI "v2hi") (V4HI "v4hi") (V8HI "v8hi")
+ (V1SI "v1si") (V2SI "v2si") (V4SI "v4si")
+ (V1DI "v1di") (V2DI "v2di")
+ (V1TI "v1ti")
+ (V1SF "v1si") (V2SF "v2si") (V4SF "v4si")
+ (V1DF "v1di") (V2DF "v2di")
+ (V1TF "v1ti") (TF "v1ti")])
+
(define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v")
(DF "w") (V1DF "w") (V2DF "v")
(TF "w") (V1TF "w")])
@@ -194,7 +214,7 @@
; for TImode (use double-int for the calculations)
; vgmb, vgmh, vgmf, vgmg, vrepib, vrepih, vrepif, vrepig
-(define_insn "mov<mode>"
+(define_insn "mov<mode><tf_vr>"
[(set (match_operand:V_128 0 "nonimmediate_operand" "=v,v,R, v, v, v, v, v,v,*d,*d,?o")
(match_operand:V_128 1 "general_operand" " v,R,v,j00,jm1,jyy,jxx,jKK,d, v,dT,*d"))]
""
@@ -214,6 +234,12 @@
[(set_attr "cpu_facility" "vx,vx,vx,vx,vx,vx,vx,vx,vx,vx,*,*")
(set_attr "op_type" "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*,*,*")])
+(define_expand "movtf"
+ [(match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "general_operand" "")]
+ ""
+ { EXPAND_MOVTF(movtf); })
+
; VR -> GPR, no instruction so split it into 64 element sets.
(define_split
[(set (match_operand:V_128 0 "register_operand" "")
@@ -565,10 +591,10 @@
; A TFmode operand resides in FPR register pairs while V1TF is in a
; single vector register.
-(define_insn "*vec_tf_to_v1tf"
+(define_insn "*vec_tf_to_v1tf_fpr"
[(set (match_operand:V1TF 0 "nonimmediate_operand" "=v,v,R,v,v")
(vec_duplicate:V1TF (match_operand:TF 1 "general_operand" "f,R,f,G,d")))]
- "TARGET_VX"
+ "TARGET_VX && !TARGET_VXE"
"@
vmrhg\t%v0,%1,%N1
vl\t%v0,%1%A1
@@ -577,6 +603,26 @@
vlvgp\t%v0,%1,%N1"
[(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
+; Both TFmode and V1TFmode operands reside in vector registers.
+(define_insn "*vec_tf_to_v1tf_vr"
+ [(set (match_operand:V1TF 0 "nonimmediate_operand" "=v,v,R,v,v")
+ (vec_duplicate:V1TF (match_operand:TF 1 "general_operand" "v,R,v,G,d")))]
+ "TARGET_VXE"
+ "@
+ vlr\t%v0,%1
+ vl\t%v0,%1%A1
+ vst\t%v1,%0%A0
+ vzero\t%v0
+ vlvgp\t%v0,%1,%N1"
+ [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
+
+(define_insn "*fprx2_to_tf"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=v")
+ (subreg:TF (match_operand:FPRX2 1 "general_operand" "f") 0))]
+ "TARGET_VXE"
+ "vmrhg\t%v0,%1,%N1"
+ [(set_attr "op_type" "VRR")])
+
(define_insn "*vec_ti_to_v1ti"
[(set (match_operand:V1TI 0 "nonimmediate_operand" "=v,v,R, v, v,v")
(vec_duplicate:V1TI (match_operand:TI 1 "general_operand" "v,R,v,j00,jm1,d")))]
@@ -658,6 +704,17 @@
DONE;
})
+(define_expand "vcond_mask_<mode><mode>"
+ [(set (match_operand:V 0 "register_operand" "")
+ (if_then_else:V
+ (eq (match_operand:<TOINTVEC> 3 "register_operand" "")
+ (match_dup 4))
+ (match_operand:V 2 "register_operand" "")
+ (match_operand:V 1 "register_operand" "")))]
+ "TARGET_VX"
+ "operands[4] = CONST0_RTX (<TOINTVEC>mode);")
+
+
; We only have HW support for byte vectors. The middle-end is
; supposed to lower the mode if required.
(define_insn "vec_permv16qi"
@@ -680,6 +737,21 @@
"vperm\t%v0,%v1,%v2,%v3"
[(set_attr "op_type" "VRR")])
+(define_insn "*mov_tf_to_fprx2_0"
+ [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "=f") 0)
+ (subreg:DF (match_operand:TF 1 "general_operand" "v") 0))]
+ "TARGET_VXE"
+ ; M4 == 1 corresponds to %v0[0] = %v1[0]; %v0[1] = %v0[1];
+ "vpdi\t%v0,%v1,%v0,1"
+ [(set_attr "op_type" "VRR")])
+
+(define_insn "*mov_tf_to_fprx2_1"
+ [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "=f") 8)
+ (subreg:DF (match_operand:TF 1 "general_operand" "v") 8))]
+ "TARGET_VXE"
+ ; M4 == 5 corresponds to %V0[0] = %v1[1]; %V0[1] = %V0[1];
+ "vpdi\t%V0,%v1,%V0,5"
+ [(set_attr "op_type" "VRR")])
; vec_perm_const for V2DI using vpdi?
@@ -1242,7 +1314,7 @@
;;
; vfasb, vfadb, wfasb, wfadb, wfaxb
-(define_insn "add<mode>3"
+(define_insn "add<mode>3<tf_vr>"
[(set (match_operand:VF_HW 0 "register_operand" "=v")
(plus:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))]
@@ -1250,8 +1322,15 @@
"<vw>fa<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
+(define_expand "addtf3"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "nonimmediate_operand" "")
+ (match_operand:TF 2 "general_operand" "")]
+ "HAVE_TF (addtf3)"
+ { EXPAND_TF (addtf3, 3); })
+
; vfssb, vfsdb, wfssb, wfsdb, wfsxb
-(define_insn "sub<mode>3"
+(define_insn "sub<mode>3<tf_vr>"
[(set (match_operand:VF_HW 0 "register_operand" "=v")
(minus:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))]
@@ -1259,8 +1338,15 @@
"<vw>fs<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
+(define_expand "subtf3"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")
+ (match_operand:TF 2 "general_operand" "")]
+ "HAVE_TF (subtf3)"
+ { EXPAND_TF (subtf3, 3); })
+
; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
-(define_insn "mul<mode>3"
+(define_insn "mul<mode>3<tf_vr>"
[(set (match_operand:VF_HW 0 "register_operand" "=v")
(mult:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))]
@@ -1268,8 +1354,15 @@
"<vw>fm<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
+(define_expand "multf3"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "nonimmediate_operand" "")
+ (match_operand:TF 2 "general_operand" "")]
+ "HAVE_TF (multf3)"
+ { EXPAND_TF (multf3, 3); })
+
; vfdsb, vfddb, wfdsb, wfddb, wfdxb
-(define_insn "div<mode>3"
+(define_insn "div<mode>3<tf_vr>"
[(set (match_operand:VF_HW 0 "register_operand" "=v")
(div:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))]
@@ -1277,21 +1370,34 @@
"<vw>fd<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
+(define_expand "divtf3"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")
+ (match_operand:TF 2 "general_operand" "")]
+ "HAVE_TF (divtf3)"
+ { EXPAND_TF (divtf3, 3); })
+
; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
-(define_insn "sqrt<mode>2"
- [(set (match_operand:VF_HW 0 "register_operand" "=v")
+(define_insn "sqrt<mode>2<tf_vr>"
+ [(set (match_operand:VF_HW 0 "register_operand" "=v")
(sqrt:VF_HW (match_operand:VF_HW 1 "register_operand" "v")))]
"TARGET_VX"
"<vw>fsq<sdx>b\t%v0,%v1"
[(set_attr "op_type" "VRR")])
+(define_expand "sqrttf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "general_operand" "")]
+ "HAVE_TF (sqrttf2)"
+ { EXPAND_TF (sqrttf2, 2); })
+
; vfmasb, vfmadb, wfmasb, wfmadb, wfmaxb
(define_insn "fma<mode>4"
[(set (match_operand:VF_HW 0 "register_operand" "=v")
(fma:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")
(match_operand:VF_HW 3 "register_operand" "v")))]
- "TARGET_VX"
+ "TARGET_VX && s390_fma_allowed_p (<MODE>mode)"
"<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
[(set_attr "op_type" "VRR")])
@@ -1301,7 +1407,7 @@
(fma:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")
(neg:VF_HW (match_operand:VF_HW 3 "register_operand" "v"))))]
- "TARGET_VX"
+ "TARGET_VX && s390_fma_allowed_p (<MODE>mode)"
"<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
[(set_attr "op_type" "VRR")])
@@ -1312,7 +1418,7 @@
(fma:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")
(match_operand:VF_HW 3 "register_operand" "v"))))]
- "TARGET_VXE"
+ "TARGET_VXE && s390_fma_allowed_p (<MODE>mode)"
"<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
[(set_attr "op_type" "VRR")])
@@ -1323,26 +1429,38 @@
(fma:VF_HW (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")
(neg:VF_HW (match_operand:VF_HW 3 "register_operand" "v")))))]
- "TARGET_VXE"
+ "TARGET_VXE && s390_fma_allowed_p (<MODE>mode)"
"<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
[(set_attr "op_type" "VRR")])
; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
-(define_insn "neg<mode>2"
+(define_insn "neg<mode>2<tf_vr>"
[(set (match_operand:VFT 0 "register_operand" "=v")
(neg:VFT (match_operand:VFT 1 "register_operand" "v")))]
"TARGET_VX"
"<vw>flc<sdx>b\t%v0,%v1"
[(set_attr "op_type" "VRR")])
+(define_expand "negtf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (negtf2)"
+ { EXPAND_TF (negtf2, 2); })
+
; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
-(define_insn "abs<mode>2"
+(define_insn "abs<mode>2<tf_vr>"
[(set (match_operand:VFT 0 "register_operand" "=v")
(abs:VFT (match_operand:VFT 1 "register_operand" "v")))]
"TARGET_VX"
"<vw>flp<sdx>b\t%v0,%v1"
[(set_attr "op_type" "VRR")])
+(define_expand "abstf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (abstf2)"
+ { EXPAND_TF (abstf2, 2); })
+
; vflnsb, vflndb, wflnsb, wflndb, wflnxb
(define_insn "negabs<mode>2"
[(set (match_operand:VFT 0 "register_operand" "=v")
@@ -1438,14 +1556,14 @@
})
;;
-;; Integer compares
+;; Compares
;;
-(define_expand "vec_cmp<VI_HW:mode><VI_HW:mode>"
- [(set (match_operand:VI_HW 0 "register_operand" "")
- (match_operator:VI_HW 1 ""
- [(match_operand:VI_HW 2 "register_operand" "")
- (match_operand:VI_HW 3 "register_operand" "")]))]
+(define_expand "vec_cmp<mode><tointvec>"
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "")
+ (match_operator:<TOINTVEC> 1 "vcond_comparison_operator"
+ [(match_operand:V_HW 2 "register_operand" "")
+ (match_operand:V_HW 3 "register_operand" "")]))]
"TARGET_VX"
{
s390_expand_vec_compare (operands[0], GET_CODE(operands[1]), operands[2], operands[3]);
@@ -1478,8 +1596,8 @@
; vfcesb, vfcedb, wfcexb: non-signaling "==" comparison (a == b)
(define_insn "*vec_cmpeq<mode>_quiet_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (eq:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (eq:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))]
"TARGET_VX"
"<vw>fce<sdx>b\t%v0,%v1,%v2"
@@ -1487,45 +1605,45 @@
; vfchsb, vfchdb, wfchxb: non-signaling > comparison (!(b u>= a))
(define_insn "vec_cmpgt<mode>_quiet_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unge:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unge:<TOINTVEC> (match_operand:VFT 2 "register_operand" "v")
(match_operand:VFT 1 "register_operand" "v"))))]
"TARGET_VX"
"<vw>fch<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
(define_expand "vec_cmplt<mode>_quiet_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v"))))]
"TARGET_VX")
; vfchesb, vfchedb, wfchexb: non-signaling >= comparison (!(a u< b))
(define_insn "vec_cmpge<mode>_quiet_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unlt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v"))))]
"TARGET_VX"
"<vw>fche<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
(define_expand "vec_cmple<mode>_quiet_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unlt:<TOINTVEC> (match_operand:VFT 2 "register_operand" "v")
(match_operand:VFT 1 "register_operand" "v"))))]
"TARGET_VX")
; vfkesb, vfkedb, wfkexb: signaling == comparison ((a >= b) & (b >= a))
(define_insn "*vec_cmpeq<mode>_signaling_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (and:<tointvec>
- (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (and:<TOINTVEC>
+ (ge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v"))
- (ge:<tointvec> (match_dup 2)
+ (ge:<TOINTVEC> (match_dup 2)
(match_dup 1))))]
"TARGET_VXE"
"<vw>fke<sdx>b\t%v0,%v1,%v2"
@@ -1533,16 +1651,16 @@
; vfkhsb, vfkhdb, wfkhxb: signaling > comparison (a > b)
(define_insn "*vec_cmpgt<mode>_signaling_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (gt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))]
"TARGET_VXE"
"<vw>fkh<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
(define_insn "*vec_cmpgt<mode>_signaling_finite_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (gt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))]
"TARGET_NONSIGNALING_VECTOR_COMPARE_OK"
"<vw>fch<sdx>b\t%v0,%v1,%v2"
@@ -1550,16 +1668,16 @@
; vfkhesb, vfkhedb, wfkhexb: signaling >= comparison (a >= b)
(define_insn "*vec_cmpge<mode>_signaling_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (ge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))]
"TARGET_VXE"
"<vw>fkhe<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
(define_insn "*vec_cmpge<mode>_signaling_finite_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (ge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))]
"TARGET_NONSIGNALING_VECTOR_COMPARE_OK"
"<vw>fche<sdx>b\t%v0,%v1,%v2"
@@ -1571,84 +1689,84 @@
; UNGT a u> b -> !!(b u< a)
(define_expand "vec_cmpungt<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unlt:<TOINTVEC> (match_operand:VFT 2 "register_operand" "v")
(match_operand:VFT 1 "register_operand" "v"))))
(set (match_dup 0)
- (not:<tointvec> (match_dup 0)))]
+ (not:<TOINTVEC> (match_dup 0)))]
"TARGET_VX")
; UNGE a u>= b -> !!(a u>= b)
(define_expand "vec_cmpunge<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v"))))
(set (match_dup 0)
- (not:<tointvec> (match_dup 0)))]
+ (not:<TOINTVEC> (match_dup 0)))]
"TARGET_VX")
; UNEQ a u== b -> !(!(a u>= b) | !(b u>= a))
(define_expand "vec_cmpuneq<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unge:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v"))))
(set (match_dup 3)
- (not:<tointvec>
- (unge:<tointvec> (match_dup 2)
+ (not:<TOINTVEC>
+ (unge:<TOINTVEC> (match_dup 2)
(match_dup 1))))
(set (match_dup 0)
- (ior:<tointvec> (match_dup 0)
+ (ior:<TOINTVEC> (match_dup 0)
(match_dup 3)))
(set (match_dup 0)
- (not:<tointvec> (match_dup 0)))]
+ (not:<TOINTVEC> (match_dup 0)))]
"TARGET_VX"
{
- operands[3] = gen_reg_rtx (<tointvec>mode);
+ operands[3] = gen_reg_rtx (<TOINTVEC>mode);
})
; LTGT a <> b -> a > b | b > a
(define_expand "vec_cmpltgt<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (gt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))
- (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
- (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
+ (set (match_dup 3) (gt:<TOINTVEC> (match_dup 2) (match_dup 1)))
+ (set (match_dup 0) (ior:<TOINTVEC> (match_dup 0) (match_dup 3)))]
"TARGET_VXE"
{
- operands[3] = gen_reg_rtx (<tointvec>mode);
+ operands[3] = gen_reg_rtx (<TOINTVEC>mode);
})
; ORDERED (a, b): !(a u< b) | !(a u>= b)
(define_expand "vec_cmpordered<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (not:<tointvec>
- (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (not:<TOINTVEC>
+ (unlt:<TOINTVEC> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v"))))
(set (match_dup 3)
- (not:<tointvec>
- (unge:<tointvec> (match_dup 1)
+ (not:<TOINTVEC>
+ (unge:<TOINTVEC> (match_dup 1)
(match_dup 2))))
(set (match_dup 0)
- (ior:<tointvec> (match_dup 0)
+ (ior:<TOINTVEC> (match_dup 0)
(match_dup 3)))]
"TARGET_VX"
{
- operands[3] = gen_reg_rtx (<tointvec>mode);
+ operands[3] = gen_reg_rtx (<TOINTVEC>mode);
})
; UNORDERED (a, b): !ORDERED (a, b)
(define_expand "vec_cmpunordered<mode>"
- [(match_operand:<tointvec> 0 "register_operand" "=v")
+ [(match_operand:<TOINTVEC> 0 "register_operand" "=v")
(match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")]
"TARGET_VX"
{
emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
emit_insn (gen_rtx_SET (operands[0],
- gen_rtx_NOT (<tointvec>mode, operands[0])));
+ gen_rtx_NOT (<TOINTVEC>mode, operands[0])));
DONE;
})
@@ -1727,7 +1845,7 @@
(define_split
[(set (match_operand:V 0 "register_operand" "")
(if_then_else:V
- (eq (match_operand:<tointvec> 3 "register_operand" "")
+ (eq (match_operand:<TOINTVEC> 3 "register_operand" "")
(match_operand:V 4 "const0_operand" ""))
(match_operand:V 1 "const0_operand" "")
(match_operand:V 2 "all_ones_operand" "")))]
@@ -1741,7 +1859,7 @@
(define_split
[(set (match_operand:V 0 "register_operand" "")
(if_then_else:V
- (eq (match_operand:<tointvec> 3 "register_operand" "")
+ (eq (match_operand:<TOINTVEC> 3 "register_operand" "")
(match_operand:V 4 "const0_operand" ""))
(match_operand:V 1 "all_ones_operand" "")
(match_operand:V 2 "const0_operand" "")))]
@@ -1755,7 +1873,7 @@
(define_split
[(set (match_operand:V 0 "register_operand" "")
(if_then_else:V
- (ne (match_operand:<tointvec> 3 "register_operand" "")
+ (ne (match_operand:<TOINTVEC> 3 "register_operand" "")
(match_operand:V 4 "const0_operand" ""))
(match_operand:V 1 "all_ones_operand" "")
(match_operand:V 2 "const0_operand" "")))]
@@ -1769,7 +1887,7 @@
(define_split
[(set (match_operand:V 0 "register_operand" "")
(if_then_else:V
- (ne (match_operand:<tointvec> 3 "register_operand" "")
+ (ne (match_operand:<TOINTVEC> 3 "register_operand" "")
(match_operand:V 4 "const0_operand" ""))
(match_operand:V 1 "const0_operand" "")
(match_operand:V 2 "all_ones_operand" "")))]
@@ -1783,8 +1901,8 @@
(define_insn "*vec_sel0<mode>"
[(set (match_operand:V 0 "register_operand" "=v")
(if_then_else:V
- (eq (match_operand:<tointvec> 3 "register_operand" "v")
- (match_operand:<tointvec> 4 "const0_operand" ""))
+ (eq (match_operand:<TOINTVEC> 3 "register_operand" "v")
+ (match_operand:<TOINTVEC> 4 "const0_operand" ""))
(match_operand:V 1 "register_operand" "v")
(match_operand:V 2 "register_operand" "v")))]
"TARGET_VX"
@@ -1795,8 +1913,8 @@
(define_insn "*vec_sel0<mode>"
[(set (match_operand:V 0 "register_operand" "=v")
(if_then_else:V
- (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
- (match_operand:<tointvec> 4 "const0_operand" ""))
+ (eq (not:<TOINTVEC> (match_operand:<TOINTVEC> 3 "register_operand" "v"))
+ (match_operand:<TOINTVEC> 4 "const0_operand" ""))
(match_operand:V 1 "register_operand" "v")
(match_operand:V 2 "register_operand" "v")))]
"TARGET_VX"
@@ -1807,8 +1925,8 @@
(define_insn "*vec_sel1<mode>"
[(set (match_operand:V 0 "register_operand" "=v")
(if_then_else:V
- (eq (match_operand:<tointvec> 3 "register_operand" "v")
- (match_operand:<tointvec> 4 "all_ones_operand" ""))
+ (eq (match_operand:<TOINTVEC> 3 "register_operand" "v")
+ (match_operand:<TOINTVEC> 4 "all_ones_operand" ""))
(match_operand:V 1 "register_operand" "v")
(match_operand:V 2 "register_operand" "v")))]
"TARGET_VX"
@@ -1819,8 +1937,8 @@
(define_insn "*vec_sel1<mode>"
[(set (match_operand:V 0 "register_operand" "=v")
(if_then_else:V
- (eq (not:<tointvec> (match_operand:<tointvec> 3 "register_operand" "v"))
- (match_operand:<tointvec> 4 "all_ones_operand" ""))
+ (eq (not:<TOINTVEC> (match_operand:<TOINTVEC> 3 "register_operand" "v"))
+ (match_operand:<TOINTVEC> 4 "all_ones_operand" ""))
(match_operand:V 1 "register_operand" "v")
(match_operand:V 2 "register_operand" "v")))]
"TARGET_VX"
@@ -2141,6 +2259,24 @@
"vc<VX_VEC_CONV_BFP:xde><VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
[(set_attr "op_type" "VRR")])
+; There is no instruction for loading a signed integer into an extended BFP
+; operand in a VR, therefore we need to load it into a FPR pair first.
+(define_expand "float<mode>tf2_vr"
+ [(set (match_dup 2)
+ (float:FPRX2 (match_operand:DSI 1 "register_operand" "")))
+ (set (match_operand:TF 0 "register_operand" "")
+ (subreg:TF (match_dup 2) 0))]
+ "TARGET_VXE"
+{
+ operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "float<mode>tf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:DSI 1 "register_operand" "")]
+ "HAVE_TF (float<mode>tf2)"
+ { EXPAND_TF (float<mode>tf2, 2); })
+
; unsigned integer to floating point
; op2: inexact exception not suppressed (IEEE 754 2008)
@@ -2154,6 +2290,24 @@
"vc<VX_VEC_CONV_BFP:xde>l<VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
[(set_attr "op_type" "VRR")])
+; There is no instruction for loading an unsigned integer into an extended BFP
+; operand in a VR, therefore load it into a FPR pair first.
+(define_expand "floatuns<mode>tf2_vr"
+ [(set (match_dup 2)
+ (unsigned_float:FPRX2 (match_operand:GPR 1 "register_operand" "")))
+ (set (match_operand:TF 0 "register_operand" "")
+ (subreg:TF (match_dup 2) 0))]
+ "TARGET_VXE"
+{
+ operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "floatuns<mode>tf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:GPR 1 "register_operand" "")]
+ "HAVE_TF (floatuns<mode>tf2)"
+ { EXPAND_TF (floatuns<mode>tf2, 2); })
+
; floating point to signed integer
; op2: inexact exception not suppressed (IEEE 754 2008)
@@ -2167,6 +2321,27 @@
"vc<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
[(set_attr "op_type" "VRR")])
+; There is no instruction for rounding an extended BFP operand in a VR into
+; a signed integer, therefore copy it into a FPR pair first.
+(define_expand "fix_trunctf<mode>2_vr"
+ [(set (subreg:DF (match_dup 2) 0)
+ (subreg:DF (match_operand:TF 1 "register_operand" "") 0))
+ (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
+ (parallel [(set (match_operand:GPR 0 "register_operand" "")
+ (fix:GPR (match_dup 2)))
+ (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_VXE"
+{
+ operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "fix_trunctf<mode>2"
+ [(match_operand:GPR 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (fix_trunctf<mode>2)"
+ { EXPAND_TF (fix_trunctf<mode>2, 2); })
+
; floating point to unsigned integer
; op2: inexact exception not suppressed (IEEE 754 2008)
@@ -2180,6 +2355,186 @@
"vcl<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
[(set_attr "op_type" "VRR")])
+; There is no instruction for rounding an extended BFP operand in a VR into
+; an unsigned integer, therefore copy it into a FPR pair first.
+(define_expand "fixuns_trunctf<mode>2_vr"
+ [(set (subreg:DF (match_dup 2) 0)
+ (subreg:DF (match_operand:TF 1 "register_operand" "") 0))
+ (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
+ (parallel [(set (match_operand:GPR 0 "register_operand" "")
+ (unsigned_fix:GPR (match_dup 2)))
+ (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_VXE"
+{
+ operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "fixuns_trunctf<mode>2"
+ [(match_operand:GPR 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (fixuns_trunctf<mode>2)"
+ { EXPAND_TF (fixuns_trunctf<mode>2, 2); })
+
+; load fp integer
+
+; vfisb, wfisb, vfidb, wfidb, wfixb; suppress inexact exceptions
+(define_insn "<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>"
+ [(set (match_operand:VF_HW 0 "register_operand" "=v")
+ (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v")]
+ FPINT))]
+ "TARGET_VX"
+ "<vw>fi<VF_HW:sdx>b\t%v0,%v1,4,<FPINT:fpint_roundingmode>"
+ [(set_attr "op_type" "VRR")])
+
+(define_expand "<FPINT:fpint_name>tf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")
+ ; recognize FPINT as an iterator
+ (unspec:TF [(match_dup 1)] FPINT)]
+ "HAVE_TF (<FPINT:fpint_name>tf2)"
+ { EXPAND_TF (<FPINT:fpint_name>tf2, 2); })
+
+; vfisb, wfisb, vfidb, wfidb, wfixb; raise inexact exceptions
+(define_insn "rint<mode>2<tf_vr>"
+ [(set (match_operand:VF_HW 0 "register_operand" "=v")
+ (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v")]
+ UNSPEC_FPINT_RINT))]
+ "TARGET_VX"
+ "<vw>fi<sdx>b\t%v0,%v1,0,0"
+ [(set_attr "op_type" "VRR")])
+
+(define_expand "rinttf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (rinttf2)"
+ { EXPAND_TF (rinttf2, 2); })
+
+; load rounded
+
+; wflrx
+(define_insn "*trunctfdf2_vr"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_truncate:DF (match_operand:TF 1 "register_operand" "v")))
+ (unspec:DF [(match_operand 2 "const_int_operand" "")]
+ UNSPEC_ROUND)]
+ "TARGET_VXE"
+ "wflrx\t%v0,%v1,0,%2"
+ [(set_attr "op_type" "VRR")])
+
+(define_expand "trunctfdf2_vr"
+ [(parallel [
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
+ (unspec:DF [(const_int BFP_RND_CURRENT)] UNSPEC_ROUND)])]
+ "TARGET_VXE")
+
+(define_expand "trunctfdf2"
+ [(match_operand:DF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (trunctfdf2)"
+ { EXPAND_TF (trunctfdf2, 2); })
+
+; wflrx + (ledbr|wledb)
+(define_expand "trunctfsf2_vr"
+ [(parallel [
+ (set (match_dup 2)
+ (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
+ (unspec:DF [(const_int BFP_RND_PREP_FOR_SHORT_PREC)] UNSPEC_ROUND)])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 2)))]
+ "TARGET_VXE"
+{
+ operands[2] = gen_reg_rtx(DFmode);
+})
+
+(define_expand "trunctfsf2"
+ [(match_operand:SF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (trunctfsf2)"
+ { EXPAND_TF (trunctfsf2, 2); })
+
+; load lengthened
+
+(define_insn "extenddftf2_vr"
+ [(set (match_operand:TF 0 "register_operand" "=v")
+ (float_extend:TF (match_operand:DF 1 "register_operand" "f")))]
+ "TARGET_VXE"
+ "wflld\t%v0,%v1"
+ [(set_attr "op_type" "VRR")])
+
+(define_expand "extenddftf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:DF 1 "nonimmediate_operand" "")]
+ "HAVE_TF (extenddftf2)"
+ { EXPAND_TF (extenddftf2, 2); })
+
+(define_expand "extendsftf2_vr"
+ [(set (match_dup 2)
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))
+ (set (match_operand:TF 0 "register_operand" "")
+ (float_extend:TF (match_dup 2)))]
+ "TARGET_VXE"
+{
+ operands[2] = gen_reg_rtx(DFmode);
+})
+
+(define_expand "extendsftf2"
+ [(match_operand:TF 0 "register_operand" "")
+ (match_operand:SF 1 "nonimmediate_operand" "")]
+ "HAVE_TF (extendsftf2)"
+ { EXPAND_TF (extendsftf2, 2); })
+
+; test data class
+
+(define_expand "signbittf2_vr"
+ [(parallel
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
+ (match_dup 2)]
+ UNSPEC_VEC_VFTCICC))
+ (clobber (scratch:V1TI))])
+ (set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
+ (const_int 1)
+ (match_dup 0)))]
+ "TARGET_VXE"
+{
+ operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
+})
+
+(define_expand "signbittf2"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (signbittf2)"
+ { EXPAND_TF (signbittf2, 2); })
+
+(define_expand "isinftf2_vr"
+ [(parallel
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
+ (match_dup 2)]
+ UNSPEC_VEC_VFTCICC))
+ (clobber (scratch:V1TI))])
+ (set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
+ (const_int 1)
+ (match_dup 0)))]
+ "TARGET_VXE"
+{
+ operands[2] = GEN_INT (S390_TDC_INFINITY);
+})
+
+(define_expand "isinftf2"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" "")]
+ "HAVE_TF (isinftf2)"
+ { EXPAND_TF (isinftf2, 2); })
+
;
; Vector byte swap patterns
;
diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md
index 6f1add0..2bbed19 100644
--- a/gcc/config/s390/vx-builtins.md
+++ b/gcc/config/s390/vx-builtins.md
@@ -76,7 +76,7 @@
(define_insn "vec_gather_element<mode>"
[(set (match_operand:V_HW_32_64 0 "register_operand" "=v")
(unspec:V_HW_32_64 [(match_operand:V_HW_32_64 1 "register_operand" "0")
- (match_operand:<tointvec> 2 "register_operand" "v")
+ (match_operand:<TOINTVEC> 2 "register_operand" "v")
(match_operand:BLK 3 "memory_operand" "R")
(match_operand:QI 4 "const_mask_operand" "C")]
UNSPEC_VEC_GATHER))]
@@ -477,7 +477,7 @@
(define_insn "vec_scatter_element<mode>_<non_vec_int>"
[(set (mem:<non_vec>
(plus:<non_vec_int> (unspec:<non_vec_int>
- [(match_operand:<tointvec> 1 "register_operand" "v")
+ [(match_operand:<TOINTVEC> 1 "register_operand" "v")
(match_operand:QI 3 "const_mask_operand" "C")]
UNSPEC_VEC_EXTRACT)
(match_operand:DI 2 "address_operand" "ZQ")))
@@ -492,7 +492,7 @@
; multiplexing here in the expander.
(define_expand "vec_scatter_element<V_HW_32_64:mode>"
[(match_operand:V_HW_32_64 0 "register_operand" "")
- (match_operand:<tointvec> 1 "register_operand" "")
+ (match_operand:<TOINTVEC> 1 "register_operand" "")
(match_operand 2 "address_operand" "")
(match_operand:QI 3 "const_mask_operand" "")]
"TARGET_VX"
@@ -813,8 +813,8 @@
})
(define_expand "vec_cmp<fpcmp:code><mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (fpcmp:<tointvec> (match_operand:VF_HW 1 "register_operand" "v")
+ [(set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (fpcmp:<TOINTVEC> (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))]
"TARGET_VX"
{
@@ -1050,7 +1050,7 @@
(define_expand "vec_slb<mode>"
[(set (match_operand:V_HW 0 "register_operand" "")
(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "")
- (match_operand:<tointvec> 2 "register_operand" "")]
+ (match_operand:<TOINTVEC> 2 "register_operand" "")]
UNSPEC_VEC_SLB))]
"TARGET_VX"
{
@@ -1121,7 +1121,7 @@
(define_insn "vec_srab<mode>"
[(set (match_operand:V_HW 0 "register_operand" "=v")
(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "v")
- (match_operand:<tointvec> 2 "register_operand" "v")]
+ (match_operand:<TOINTVEC> 2 "register_operand" "v")]
UNSPEC_VEC_SRAB))]
"TARGET_VX"
"vsrab\t%v0,%v1,%v2"
@@ -1146,7 +1146,7 @@
(define_expand "vec_srb<mode>"
[(set (match_operand:V_HW 0 "register_operand" "")
(unspec:V_HW [(match_operand:V_HW 1 "register_operand" "")
- (match_operand:<tointvec> 2 "register_operand" "")]
+ (match_operand:<TOINTVEC> 2 "register_operand" "")]
UNSPEC_VEC_SRLB))]
"TARGET_VX"
{
@@ -1229,7 +1229,7 @@
(define_expand "vec_test_mask_int<mode>"
[(set (reg:CCRAW CC_REGNUM)
(unspec:CCRAW [(match_operand:V_HW 1 "register_operand" "")
- (match_operand:<tointvec> 2 "register_operand" "")]
+ (match_operand:<TOINTVEC> 2 "register_operand" "")]
UNSPEC_VEC_TEST_MASK))
(set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
@@ -1238,7 +1238,7 @@
(define_insn "*vec_test_mask<mode>"
[(set (reg:CCRAW CC_REGNUM)
(unspec:CCRAW [(match_operand:V_HW 0 "register_operand" "v")
- (match_operand:<tointvec> 1 "register_operand" "v")]
+ (match_operand:<TOINTVEC> 1 "register_operand" "v")]
UNSPEC_VEC_TEST_MASK))]
"TARGET_VX"
"vtm\t%v0,%v1"
@@ -1940,24 +1940,24 @@
; These ignore the vector result and only want CC stored to an int
; pointer.
-; vftcisb, vftcidb
+; vftcisb, vftcidb, wftcixb
(define_insn "*vftci<mode>_cconly"
[(set (reg:CCRAW CC_REGNUM)
- (unspec:CCRAW [(match_operand:VECF_HW 1 "register_operand")
- (match_operand:HI 2 "const_int_operand")]
+ (unspec:CCRAW [(match_operand:VF_HW 1 "register_operand" "v")
+ (match_operand:HI 2 "const_int_operand" "J")]
UNSPEC_VEC_VFTCICC))
- (clobber (match_scratch:<tointvec> 0))]
+ (clobber (match_scratch:<TOINTVEC> 0 "=v"))]
"TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")"
- "vftci<sdx>b\t%v0,%v1,%x2"
+ "<vw>ftci<sdx>b\t%v0,%v1,%x2"
[(set_attr "op_type" "VRR")])
(define_expand "vftci<mode>_intcconly"
[(parallel
[(set (reg:CCRAW CC_REGNUM)
- (unspec:CCRAW [(match_operand:VECF_HW 0 "register_operand")
- (match_operand:HI 1 "const_int_operand")]
+ (unspec:CCRAW [(match_operand:VF_HW 0 "register_operand")
+ (match_operand:HI 1 "const_int_operand")]
UNSPEC_VEC_VFTCICC))
- (clobber (scratch:<tointvec>))])
+ (clobber (scratch:<TOINTVEC>))])
(set (match_operand:SI 2 "register_operand" "")
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'J', \"J\")")
@@ -1965,27 +1965,27 @@
; vec_fp_test_data_class wants the result vector and the CC stored to
; an int pointer.
-; vftcisb, vftcidb
-(define_insn "*vftci<mode>"
- [(set (match_operand:VECF_HW 0 "register_operand" "=v")
- (unspec:VECF_HW [(match_operand:VECF_HW 1 "register_operand" "v")
- (match_operand:HI 2 "const_int_operand" "J")]
- UNSPEC_VEC_VFTCI))
+; vftcisb, vftcidb, wftcixb
+(define_insn "vftci<mode>"
+ [(set (match_operand:VF_HW 0 "register_operand" "=v")
+ (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v")
+ (match_operand:HI 2 "const_int_operand" "J")]
+ UNSPEC_VEC_VFTCI))
(set (reg:CCRAW CC_REGNUM)
(unspec:CCRAW [(match_dup 1) (match_dup 2)] UNSPEC_VEC_VFTCICC))]
"TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")"
- "vftci<sdx>b\t%v0,%v1,%x2"
+ "<vw>ftci<sdx>b\t%v0,%v1,%x2"
[(set_attr "op_type" "VRR")])
(define_expand "vftci<mode>_intcc"
[(parallel
- [(set (match_operand:VECF_HW 0 "register_operand")
- (unspec:VECF_HW [(match_operand:VECF_HW 1 "register_operand")
- (match_operand:HI 2 "const_int_operand")]
- UNSPEC_VEC_VFTCI))
+ [(set (match_operand:VF_HW 0 "register_operand")
+ (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand")
+ (match_operand:HI 2 "const_int_operand")]
+ UNSPEC_VEC_VFTCI))
(set (reg:CCRAW CC_REGNUM)
(unspec:CCRAW [(match_dup 1) (match_dup 2)] UNSPEC_VEC_VFTCICC))])
- (set (match_operand:SI 3 "memory_operand" "")
+ (set (match_operand:SI 3 "nonimmediate_operand")
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")")
@@ -2083,7 +2083,7 @@
[(set (reg:VFCMP CC_REGNUM)
(compare:VFCMP (match_operand:VF_HW 0 "register_operand" "v")
(match_operand:VF_HW 1 "register_operand" "v")))
- (clobber (match_scratch:<tointvec> 2 "=v"))]
+ (clobber (match_scratch:<TOINTVEC> 2 "=v"))]
"TARGET_VX"
"<vw>fc<asm_fcmp><sdx>bs\t%v2,%v0,%v1"
[(set_attr "op_type" "VRR")])
@@ -2094,8 +2094,8 @@
[(set (reg:CCVEQ CC_REGNUM)
(compare:CCVEQ (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))
- (set (match_operand:<tointvec> 0 "register_operand" "=v")
- (eq:<tointvec> (match_dup 1) (match_dup 2)))])
+ (set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (eq:<TOINTVEC> (match_dup 1) (match_dup 2)))])
(set (match_operand:SI 3 "memory_operand" "")
(unspec:SI [(reg:CCVEQ CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_VX")
@@ -2105,8 +2105,8 @@
[(set (reg:CCVFH CC_REGNUM)
(compare:CCVFH (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))
- (set (match_operand:<tointvec> 0 "register_operand" "=v")
- (gt:<tointvec> (match_dup 1) (match_dup 2)))])
+ (set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (gt:<TOINTVEC> (match_dup 1) (match_dup 2)))])
(set (match_operand:SI 3 "memory_operand" "")
(unspec:SI [(reg:CCVIH CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_VX")
@@ -2116,8 +2116,8 @@
[(set (reg:CCVFHE CC_REGNUM)
(compare:CCVFHE (match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")))
- (set (match_operand:<tointvec> 0 "register_operand" "=v")
- (ge:<tointvec> (match_dup 1) (match_dup 2)))])
+ (set (match_operand:<TOINTVEC> 0 "register_operand" "=v")
+ (ge:<TOINTVEC> (match_dup 1) (match_dup 2)))])
(set (match_operand:SI 3 "memory_operand" "")
(unspec:SI [(reg:CCVFHE CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_VX")
@@ -2131,8 +2131,8 @@
[(set (reg:CCVEQ CC_REGNUM)
(compare:CCVEQ (match_operand:VF_HW 0 "register_operand" "v")
(match_operand:VF_HW 1 "register_operand" "v")))
- (set (match_operand:<tointvec> 2 "register_operand" "=v")
- (eq:<tointvec> (match_dup 0) (match_dup 1)))]
+ (set (match_operand:<TOINTVEC> 2 "register_operand" "=v")
+ (eq:<TOINTVEC> (match_dup 0) (match_dup 1)))]
"TARGET_VX"
"<vw>fce<sdx>bs\t%v2,%v0,%v1"
[(set_attr "op_type" "VRR")])
@@ -2142,8 +2142,8 @@
[(set (reg:CCVFH CC_REGNUM)
(compare:CCVFH (match_operand:VF_HW 0 "register_operand" "v")
(match_operand:VF_HW 1 "register_operand" "v")))
- (set (match_operand:<tointvec> 2 "register_operand" "=v")
- (gt:<tointvec> (match_dup 0) (match_dup 1)))]
+ (set (match_operand:<TOINTVEC> 2 "register_operand" "=v")
+ (gt:<TOINTVEC> (match_dup 0) (match_dup 1)))]
"TARGET_VX"
"<vw>fch<sdx>bs\t%v2,%v0,%v1"
[(set_attr "op_type" "VRR")])
@@ -2153,8 +2153,8 @@
[(set (reg:CCVFHE CC_REGNUM)
(compare:CCVFHE (match_operand:VF_HW 0 "register_operand" "v")
(match_operand:VF_HW 1 "register_operand" "v")))
- (set (match_operand:<tointvec> 2 "register_operand" "=v")
- (ge:<tointvec> (match_dup 0) (match_dup 1)))]
+ (set (match_operand:<TOINTVEC> 2 "register_operand" "=v")
+ (ge:<TOINTVEC> (match_dup 0) (match_dup 1)))]
"TARGET_VX"
"<vw>fche<sdx>bs\t%v2,%v0,%v1"
[(set_attr "op_type" "VRR")])
diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt
index 908603b..fb6d829 100644
--- a/gcc/config/sh/sh.opt
+++ b/gcc/config/sh/sh.opt
@@ -175,19 +175,19 @@ Target RejectNegative Condition(SUPPORT_SH4AL)
Generate SH4al-dsp code.
maccumulate-outgoing-args
-Target Report Var(TARGET_ACCUMULATE_OUTGOING_ARGS) Init(1)
+Target Var(TARGET_ACCUMULATE_OUTGOING_ARGS) Init(1)
Reserve space for outgoing arguments in the function prologue.
mb
-Target Report RejectNegative InverseMask(LITTLE_ENDIAN)
+Target RejectNegative InverseMask(LITTLE_ENDIAN)
Generate code in big endian mode.
mbigtable
-Target Report RejectNegative Mask(BIGTABLE)
+Target RejectNegative Mask(BIGTABLE)
Generate 32-bit offsets in switch tables.
mbitops
-Target Report RejectNegative Mask(BITOPS)
+Target RejectNegative Mask(BITOPS)
Generate bit instructions.
mbranch-cost=
@@ -195,15 +195,15 @@ Target RejectNegative Joined UInteger Var(sh_branch_cost) Init(-1)
Cost to assume for a branch insn.
mzdcbranch
-Target Report Var(TARGET_ZDCBRANCH)
+Target Var(TARGET_ZDCBRANCH)
Assume that zero displacement conditional branches are fast.
mcbranch-force-delay-slot
-Target Report RejectNegative Var(TARGET_CBRANCH_FORCE_DELAY_SLOT) Init(0)
+Target RejectNegative Var(TARGET_CBRANCH_FORCE_DELAY_SLOT) Init(0)
Force the usage of delay slots for conditional branches.
mdalign
-Target Report RejectNegative Mask(ALIGN_DOUBLE)
+Target RejectNegative Mask(ALIGN_DOUBLE)
Align doubles at 64-bit boundaries.
mdiv=
@@ -215,7 +215,7 @@ Target RejectNegative Joined Var(sh_divsi3_libfunc) Init("")
Specify name for 32 bit signed division function.
mfdpic
-Target Report Var(TARGET_FDPIC) Init(0)
+Target Var(TARGET_FDPIC) Init(0)
Generate ELF FDPIC code.
mfmovd
@@ -227,7 +227,7 @@ Target RejectNegative Joined Var(sh_fixed_range_str)
Specify range of registers to make fixed.
mhitachi
-Target Report RejectNegative Mask(HITACHI)
+Target RejectNegative Mask(HITACHI)
Follow Renesas (formerly Hitachi) / SuperH calling conventions.
mieee
@@ -235,33 +235,33 @@ Target Var(TARGET_IEEE)
Increase the IEEE compliance for floating-point comparisons.
minline-ic_invalidate
-Target Report Var(TARGET_INLINE_IC_INVALIDATE)
+Target Var(TARGET_INLINE_IC_INVALIDATE)
Inline code to invalidate instruction cache entries after setting up nested function trampolines.
misize
-Target Report RejectNegative Mask(DUMPISIZE)
+Target RejectNegative Mask(DUMPISIZE)
Annotate assembler instructions with estimated addresses.
ml
-Target Report RejectNegative Mask(LITTLE_ENDIAN)
+Target RejectNegative Mask(LITTLE_ENDIAN)
Generate code in little endian mode.
mnomacsave
-Target Report RejectNegative Mask(NOMACSAVE)
+Target RejectNegative Mask(NOMACSAVE)
Mark MAC register as call-clobbered.
;; ??? This option is not useful, but is retained in case there are people
;; who are still relying on it. It may be deleted in the future.
mpadstruct
-Target Report RejectNegative Mask(PADSTRUCT)
+Target RejectNegative Mask(PADSTRUCT)
Make structs a multiple of 4 bytes (warning: ABI altered).
mprefergot
-Target Report RejectNegative Mask(PREFERGOT)
+Target RejectNegative Mask(PREFERGOT)
Emit function-calls using global offset table when generating PIC.
mrelax
-Target Report RejectNegative Mask(RELAX)
+Target RejectNegative Mask(RELAX)
Shorten address references during linking.
mrenesas
@@ -269,11 +269,11 @@ Target Mask(HITACHI)
Follow Renesas (formerly Hitachi) / SuperH calling conventions.
matomic-model=
-Target Report RejectNegative Joined Var(sh_atomic_model_str)
+Target RejectNegative Joined Var(sh_atomic_model_str)
Specify the model for atomic operations.
mtas
-Target Report RejectNegative Var(TARGET_ENABLE_TAS)
+Target RejectNegative Var(TARGET_ENABLE_TAS)
Use tas.b instruction for __atomic_test_and_set.
multcost=
@@ -299,5 +299,5 @@ Target Var(TARGET_FSRRA)
Enable the use of the fsrra instruction.
mlra
-Target Report Var(sh_lra_flag) Init(0) Save
+Target Var(sh_lra_flag) Init(0) Save
Use LRA instead of reload (transitional).
diff --git a/gcc/config/sol2-d.c b/gcc/config/sol2-d.c
index 73ca786..27068f8 100644
--- a/gcc/config/sol2-d.c
+++ b/gcc/config/sol2-d.c
@@ -33,19 +33,7 @@ solaris_d_os_builtins (void)
d_add_builtin_version ("Solaris"); \
}
-/* Implement TARGET_D_CRITSEC_SIZE for Solaris targets. */
-
-static unsigned
-solaris_d_critsec_size (void)
-{
- /* This is the sizeof pthread_mutex_t. */
- return 24;
-}
-
#undef TARGET_D_OS_VERSIONS
#define TARGET_D_OS_VERSIONS solaris_d_os_builtins
-#undef TARGET_D_CRITSEC_SIZE
-#define TARGET_D_CRITSEC_SIZE solaris_d_critsec_size
-
struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index 91b4602..7a21f22 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -381,9 +381,6 @@ along with GCC; see the file COPYING3. If not see
{ "endfile_vtv", ENDFILE_VTV_SPEC }, \
SUBTARGET_CPU_EXTRA_SPECS
-/* C++11 programs need -lrt for nanosleep. */
-#define TIME_LIBRARY "rt"
-
#ifndef USE_GLD
/* With Sun ld, -rdynamic is a no-op. */
#define RDYNAMIC_SPEC ""
diff --git a/gcc/config/sol2.opt b/gcc/config/sol2.opt
index a432ab5..99cb263 100644
--- a/gcc/config/sol2.opt
+++ b/gcc/config/sol2.opt
@@ -28,11 +28,11 @@ Ym,
Driver Joined
mclear-hwcap
-Target Report
+Target
Clear hardware capabilities when linking.
mimpure-text
-Target Report
+Target
Pass -z text to linker.
pthread
diff --git a/gcc/config/sparc/long-double-switch.opt b/gcc/config/sparc/long-double-switch.opt
index 8139ae6..76e25de 100644
--- a/gcc/config/sparc/long-double-switch.opt
+++ b/gcc/config/sparc/long-double-switch.opt
@@ -19,9 +19,9 @@
; <http://www.gnu.org/licenses/>.
mlong-double-128
-Target Report RejectNegative Mask(LONG_DOUBLE_128)
+Target RejectNegative Mask(LONG_DOUBLE_128)
Use 128-bit long double.
mlong-double-64
-Target Report RejectNegative InverseMask(LONG_DOUBLE_128)
+Target RejectNegative InverseMask(LONG_DOUBLE_128)
Use 64-bit long double.
diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md
index 3d49972..42316ad 100644
--- a/gcc/config/sparc/predicates.md
+++ b/gcc/config/sparc/predicates.md
@@ -296,6 +296,8 @@
if (arith_double_operand (op, mode))
return true;
+ /* Turning an add/sub instruction into the other changes the Carry flag
+ so the 4096 trick cannot be used for double operations in 32-bit mode. */
return TARGET_ARCH64 && const_4096_operand (op, mode);
})
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index f525cd7..5f9999a 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -86,7 +86,6 @@ extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
extern rtx widen_mem_for_ldd_peep (rtx, rtx, machine_mode);
extern int empty_delay_slot (rtx_insn *);
extern int emit_cbcond_nop (rtx_insn *);
-extern int eligible_for_call_delay (rtx_insn *);
extern int eligible_for_return_delay (rtx_insn *);
extern int eligible_for_sibcall_delay (rtx_insn *);
extern int emit_move_sequence (rtx, machine_mode);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 2780b42..ec0921b 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -708,6 +708,7 @@ static HOST_WIDE_INT sparc_constant_alignment (const_tree, HOST_WIDE_INT);
static bool sparc_vectorize_vec_perm_const (machine_mode, rtx, rtx, rtx,
const vec_perm_indices &);
static bool sparc_can_follow_jump (const rtx_insn *, const rtx_insn *);
+static HARD_REG_SET sparc_zero_call_used_regs (HARD_REG_SET);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */
@@ -959,6 +960,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_CAN_FOLLOW_JUMP
#define TARGET_CAN_FOLLOW_JUMP sparc_can_follow_jump
+#undef TARGET_ZERO_CALL_USED_REGS
+#define TARGET_ZERO_CALL_USED_REGS sparc_zero_call_used_regs
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Return the memory reference contained in X if any, zero otherwise. */
@@ -3949,41 +3953,6 @@ emit_cbcond_nop (rtx_insn *insn)
return 1;
}
-/* Return nonzero if TRIAL can go into the call delay slot. */
-
-int
-eligible_for_call_delay (rtx_insn *trial)
-{
- rtx pat;
-
- if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE)
- return 0;
-
- /* The only problematic cases are TLS sequences with Sun as/ld. */
- if ((TARGET_GNU_TLS && HAVE_GNU_LD) || !TARGET_TLS)
- return 1;
-
- pat = PATTERN (trial);
-
- /* We must reject tgd_add{32|64}, i.e.
- (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSGD)))
- and tldm_add{32|64}, i.e.
- (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSLDM)))
- for Sun as/ld. */
- if (GET_CODE (pat) == SET
- && GET_CODE (SET_SRC (pat)) == PLUS)
- {
- rtx unspec = XEXP (SET_SRC (pat), 1);
-
- if (GET_CODE (unspec) == UNSPEC
- && (XINT (unspec, 1) == UNSPEC_TLSGD
- || XINT (unspec, 1) == UNSPEC_TLSLDM))
- return 0;
- }
-
- return 1;
-}
-
/* Return nonzero if TRIAL, an insn, can be combined with a 'restore'
instruction. RETURN_P is true if the v9 variant 'return' is to be
considered in the test too.
@@ -13845,4 +13814,50 @@ sparc_constant_alignment (const_tree exp, HOST_WIDE_INT align)
return align;
}
+/* Implement TARGET_ZERO_CALL_USED_REGS.
+
+ Generate a sequence of instructions that zero registers specified by
+ NEED_ZEROED_HARDREGS. Return the ZEROED_HARDREGS that are actually
+ zeroed. */
+
+static HARD_REG_SET
+sparc_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+ {
+ /* Do not touch the CC registers or the FP registers if no VIS. */
+ if (regno >= SPARC_FCC_REG
+ || (regno >= SPARC_FIRST_FP_REG && !TARGET_VIS))
+ CLEAR_HARD_REG_BIT (need_zeroed_hardregs, regno);
+
+ /* Do not access the odd upper FP registers individually. */
+ else if (regno >= SPARC_FIRST_V9_FP_REG && (regno & 1))
+ ;
+
+ /* Use the most natural mode for the registers, which is not given by
+ regno_reg_rtx/reg_raw_mode for the FP registers on the SPARC. */
+ else
+ {
+ machine_mode mode;
+ rtx reg;
+
+ if (regno < SPARC_FIRST_FP_REG)
+ {
+ reg = regno_reg_rtx[regno];
+ mode = GET_MODE (reg);
+ }
+ else
+ {
+ mode = regno < SPARC_FIRST_V9_FP_REG ? SFmode : DFmode;
+ reg = gen_raw_REG (mode, regno);
+ }
+
+ emit_move_insn (reg, CONST0_RTX (mode));
+ }
+ }
+
+ return need_zeroed_hardregs;
+}
+
#include "gt-sparc.h"
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 231c0d8..6e9ccb4 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -561,9 +561,9 @@
(set_attr "type" "multi")])
;; Attributes for branch scheduling
-(define_attr "in_call_delay" "false,true"
- (symbol_ref "(eligible_for_call_delay (insn)
- ? IN_CALL_DELAY_TRUE : IN_CALL_DELAY_FALSE)"))
+(define_attr "tls_delay_slot" "false,true"
+ (symbol_ref "((TARGET_GNU_TLS && HAVE_GNU_LD) != 0
+ ? TLS_DELAY_SLOT_TRUE : TLS_DELAY_SLOT_FALSE)"))
(define_attr "in_sibcall_delay" "false,true"
(symbol_ref "(eligible_for_sibcall_delay (insn)
@@ -613,27 +613,24 @@
(const_string "true")
] (const_string "false")))
-(define_delay (eq_attr "type" "call")
- [(eq_attr "in_call_delay" "true") (nil) (nil)])
-
(define_delay (eq_attr "type" "sibcall")
[(eq_attr "in_sibcall_delay" "true") (nil) (nil)])
(define_delay (eq_attr "type" "return")
[(eq_attr "in_return_delay" "true") (nil) (nil)])
-(define_delay (and (eq_attr "type" "branch")
- (not (eq_attr "branch_type" "icc")))
- [(eq_attr "in_branch_delay" "true") (nil) (eq_attr "in_branch_delay" "true")])
-
-(define_delay (and (eq_attr "type" "branch")
- (eq_attr "branch_type" "icc"))
- [(eq_attr "in_branch_delay" "true") (nil)
- (eq_attr "in_integer_branch_annul_delay" "true")])
-
-(define_delay (eq_attr "type" "uncond_branch")
+(define_delay (ior (eq_attr "type" "call") (eq_attr "type" "uncond_branch"))
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
+(define_delay (and (eq_attr "type" "branch") (not (eq_attr "branch_type" "icc")))
+ [(eq_attr "in_branch_delay" "true")
+ (nil)
+ (eq_attr "in_branch_delay" "true")])
+
+(define_delay (and (eq_attr "type" "branch") (eq_attr "branch_type" "icc"))
+ [(eq_attr "in_branch_delay" "true")
+ (nil)
+ (eq_attr "in_integer_branch_annul_delay" "true")])
;; Include SPARC DFA schedulers
@@ -3771,10 +3768,13 @@ visl")
}
})
+;; Turning an add/sub instruction into the other changes the Carry flag
+;; so the 4096 trick cannot be used for operations in CCXCmode.
+
(define_expand "uaddvdi4"
[(parallel [(set (reg:CCXC CC_REG)
(compare:CCXC (plus:DI (match_operand:DI 1 "register_operand")
- (match_operand:DI 2 "arith_add_operand"))
+ (match_operand:DI 2 "arith_double_operand"))
(match_dup 1)))
(set (match_operand:DI 0 "register_operand")
(plus:DI (match_dup 1) (match_dup 2)))])
@@ -3793,10 +3793,13 @@ visl")
}
})
+;; Turning an add/sub instruction into the other does not change the Overflow
+;; flag so the 4096 trick can be used for operations in CCXVmode.
+
(define_expand "addvdi4"
[(parallel [(set (reg:CCXV CC_REG)
(compare:CCXV (plus:DI (match_operand:DI 1 "register_operand")
- (match_operand:DI 2 "arith_add_operand"))
+ (match_operand:DI 2 "arith_double_add_operand"))
(unspec:DI [(match_dup 1) (match_dup 2)]
UNSPEC_ADDV)))
(set (match_operand:DI 0 "register_operand")
@@ -3969,9 +3972,10 @@ visl")
""
"@
add\t%1, %2, %0
- sub\t%1, -%2, %0"
- [(set_attr "type" "*,*")
- (set_attr "fptype" "*,*")])
+ sub\t%1, -%2, %0")
+
+;; Turning an add/sub instruction into the other changes the Carry flag
+;; so the 4096 trick cannot be used for operations in CCCmode.
(define_expand "uaddvsi4"
[(parallel [(set (reg:CCC CC_REG)
@@ -3985,10 +3989,13 @@ visl")
(pc)))]
"")
+;; Turning an add/sub instruction into the other does not change the Overflow
+;; flag so the 4096 trick can be used for operations in CCVmode.
+
(define_expand "addvsi4"
[(parallel [(set (reg:CCV CC_REG)
(compare:CCV (plus:SI (match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "arith_operand"))
+ (match_operand:SI 2 "arith_add_operand"))
(unspec:SI [(match_dup 1) (match_dup 2)]
UNSPEC_ADDV)))
(set (match_operand:SI 0 "register_operand")
@@ -4097,42 +4104,50 @@ visl")
(define_insn "*cmp_ccv_plus"
[(set (reg:CCV CC_REG)
- (compare:CCV (plus:SI (match_operand:SI 0 "register_operand" "%r")
- (match_operand:SI 1 "arith_operand" "rI"))
+ (compare:CCV (plus:SI (match_operand:SI 0 "register_operand" "%r,r")
+ (match_operand:SI 1 "arith_add_operand" "rI,O"))
(unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_ADDV)))]
""
- "addcc\t%0, %1, %%g0"
+ "@
+ addcc\t%0, %1, %%g0
+ subcc\t%0, -%1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccxv_plus"
[(set (reg:CCXV CC_REG)
- (compare:CCXV (plus:DI (match_operand:DI 0 "register_operand" "%r")
- (match_operand:DI 1 "arith_operand" "rI"))
+ (compare:CCXV (plus:DI (match_operand:DI 0 "register_operand" "%r,r")
+ (match_operand:DI 1 "arith_add_operand" "rI,O"))
(unspec:DI [(match_dup 0) (match_dup 1)] UNSPEC_ADDV)))]
"TARGET_ARCH64"
- "addcc\t%0, %1, %%g0"
+ "@
+ addcc\t%0, %1, %%g0
+ subcc\t%0, -%1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccv_plus_set"
[(set (reg:CCV CC_REG)
- (compare:CCV (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "arith_operand" "rI"))
+ (compare:CCV (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "arith_add_operand" "rI,O"))
(unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_ADDV)))
- (set (match_operand:SI 0 "register_operand" "=r")
+ (set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "addcc\t%1, %2, %0"
+ "@
+ addcc\t%1, %2, %0
+ subcc\t%1, -%2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccxv_plus_set"
[(set (reg:CCXV CC_REG)
- (compare:CCXV (plus:DI (match_operand:DI 1 "register_operand" "%r")
- (match_operand:DI 2 "arith_operand" "rI"))
+ (compare:CCXV (plus:DI (match_operand:DI 1 "register_operand" "%r,r")
+ (match_operand:DI 2 "arith_add_operand" "rI,O"))
(unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_ADDV)))
- (set (match_operand:DI 0 "register_operand" "=r")
+ (set (match_operand:DI 0 "register_operand" "=r,r")
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
- "addcc\t%1, %2, %0"
+ "@
+ addcc\t%1, %2, %0
+ subcc\t%1, -%2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccv_plus_sltu_set"
@@ -4164,10 +4179,13 @@ visl")
}
})
+;; Turning an add/sub instruction into the other changes the Carry flag
+;; so the 4096 trick cannot be used for operations in CCXmode.
+
(define_expand "usubvdi4"
[(parallel [(set (reg:CCX CC_REG)
(compare:CCX (match_operand:DI 1 "register_or_zero_operand")
- (match_operand:DI 2 "arith_add_operand")))
+ (match_operand:DI 2 "arith_double_operand")))
(set (match_operand:DI 0 "register_operand")
(minus:DI (match_dup 1) (match_dup 2)))])
(set (pc) (if_then_else (ltu (reg:CCX CC_REG) (const_int 0))
@@ -4191,10 +4209,13 @@ visl")
}
})
+;; Turning an add/sub instruction into the other does not change the Overflow
+;; flag so the 4096 trick can be used for operations in CCXVmode.
+
(define_expand "subvdi4"
[(parallel [(set (reg:CCXV CC_REG)
(compare:CCXV (minus:DI (match_operand:DI 1 "register_operand")
- (match_operand:DI 2 "arith_add_operand"))
+ (match_operand:DI 2 "arith_double_add_operand"))
(unspec:DI [(match_dup 1) (match_dup 2)]
UNSPEC_SUBV)))
(set (match_operand:DI 0 "register_operand")
@@ -4365,9 +4386,10 @@ visl")
""
"@
sub\t%1, %2, %0
- add\t%1, -%2, %0"
- [(set_attr "type" "*,*")
- (set_attr "fptype" "*,*")])
+ add\t%1, -%2, %0")
+
+;; Turning an add/sub instruction into the other changes the Carry flag
+;; so the 4096 trick cannot be used for operations in CCmode.
(define_expand "usubvsi4"
[(parallel [(set (reg:CC CC_REG)
@@ -4387,10 +4409,13 @@ visl")
}
})
+;; Turning an add/sub instruction into the other does not change the Overflow
+;; flag so the 4096 trick can be used for operations in CCVmode.
+
(define_expand "subvsi4"
[(parallel [(set (reg:CCV CC_REG)
(compare:CCV (minus:SI (match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "arith_operand"))
+ (match_operand:SI 2 "arith_add_operand"))
(unspec:SI [(match_dup 1) (match_dup 2)]
UNSPEC_SUBV)))
(set (match_operand:SI 0 "register_operand")
@@ -4483,42 +4508,50 @@ visl")
(define_insn "*cmp_ccv_minus"
[(set (reg:CCV CC_REG)
- (compare:CCV (minus:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
- (match_operand:SI 1 "arith_operand" "rI"))
+ (compare:CCV (minus:SI (match_operand:SI 0 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 1 "arith_add_operand" "rI,O"))
(unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_SUBV)))]
""
- "subcc\t%r0, %1, %%g0"
+ "@
+ subcc\t%r0, %1, %%g0
+ addcc\t%r0, -%1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccxv_minus"
[(set (reg:CCXV CC_REG)
- (compare:CCXV (minus:DI (match_operand:DI 0 "register_or_zero_operand" "rJ")
- (match_operand:DI 1 "arith_operand" "rI"))
+ (compare:CCXV (minus:DI (match_operand:DI 0 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:DI 1 "arith_add_operand" "rI,O"))
(unspec:DI [(match_dup 0) (match_dup 1)] UNSPEC_SUBV)))]
"TARGET_ARCH64"
- "subcc\t%r0, %1, %%g0"
+ "@
+ subcc\t%r0, %1, %%g0
+ addcc\t%r0, -%1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccv_minus_set"
[(set (reg:CCV CC_REG)
- (compare:CCV (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
+ (compare:CCV (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "arith_add_operand" "rI,O"))
(unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_SUBV)))
- (set (match_operand:SI 0 "register_operand" "=r")
+ (set (match_operand:SI 0 "register_operand" "=r,r")
(minus:SI (match_dup 1) (match_dup 2)))]
""
- "subcc\t%r1, %2, %0"
+ "@
+ subcc\t%r1, %2, %0
+ addcc\t%r1, -%2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccxv_minus_set"
[(set (reg:CCXV CC_REG)
- (compare:CCXV (minus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
- (match_operand:DI 2 "arith_operand" "rI"))
+ (compare:CCXV (minus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:DI 2 "arith_add_operand" "rI,O"))
(unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_SUBV)))
- (set (match_operand:DI 0 "register_operand" "=r")
+ (set (match_operand:DI 0 "register_operand" "=r,r")
(minus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
- "subcc\t%r1, %2, %0"
+ "@
+ subcc\t%r1, %2, %0
+ addcc\t%r1, -%2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccv_minus_sltu_set"
@@ -5769,13 +5802,13 @@ visl")
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
""
"sub\t%%g0, %1, %0")
(define_expand "unegvsi3"
[(parallel [(set (reg:CCC CC_REG)
- (compare:CCC (not:SI (match_operand:SI 1 "arith_operand" ""))
+ (compare:CCC (not:SI (match_operand:SI 1 "register_operand" ""))
(const_int -1)))
(set (match_operand:SI 0 "register_operand" "")
(neg:SI (match_dup 1)))])
@@ -5787,7 +5820,7 @@ visl")
(define_expand "negvsi3"
[(parallel [(set (reg:CCV CC_REG)
- (compare:CCV (neg:SI (match_operand:SI 1 "arith_operand" ""))
+ (compare:CCV (neg:SI (match_operand:SI 1 "register_operand" ""))
(unspec:SI [(match_dup 1)] UNSPEC_NEGV)))
(set (match_operand:SI 0 "register_operand" "")
(neg:SI (match_dup 1)))])
@@ -5799,7 +5832,7 @@ visl")
(define_insn "*cmp_ccnz_neg"
[(set (reg:CCNZ CC_REG)
- (compare:CCNZ (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
+ (compare:CCNZ (neg:SI (match_operand:SI 0 "register_operand" "r"))
(const_int 0)))]
""
"subcc\t%%g0, %0, %%g0"
@@ -5807,7 +5840,7 @@ visl")
(define_insn "*cmp_ccxnz_neg"
[(set (reg:CCXNZ CC_REG)
- (compare:CCXNZ (neg:DI (match_operand:DI 0 "arith_operand" "rI"))
+ (compare:CCXNZ (neg:DI (match_operand:DI 0 "register_operand" "r"))
(const_int 0)))]
"TARGET_ARCH64"
"subcc\t%%g0, %0, %%g0"
@@ -5815,7 +5848,7 @@ visl")
(define_insn "*cmp_ccnz_neg_set"
[(set (reg:CCNZ CC_REG)
- (compare:CCNZ (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
+ (compare:CCNZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
@@ -5825,7 +5858,7 @@ visl")
(define_insn "*cmp_ccxnz_neg_set"
[(set (reg:CCXNZ CC_REG)
- (compare:CCXNZ (neg:DI (match_operand:DI 1 "arith_operand" "rI"))
+ (compare:CCXNZ (neg:DI (match_operand:DI 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_dup 1)))]
@@ -5835,7 +5868,7 @@ visl")
(define_insn "*cmp_ccc_neg_set"
[(set (reg:CCC CC_REG)
- (compare:CCC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
+ (compare:CCC (not:SI (match_operand:SI 1 "register_operand" "r"))
(const_int -1)))
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
@@ -5845,7 +5878,7 @@ visl")
(define_insn "*cmp_ccxc_neg_set"
[(set (reg:CCXC CC_REG)
- (compare:CCXC (not:DI (match_operand:DI 1 "arith_operand" "rI"))
+ (compare:CCXC (not:DI (match_operand:DI 1 "register_operand" "r"))
(const_int -1)))
(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_dup 1)))]
@@ -5856,7 +5889,7 @@ visl")
(define_insn "*cmp_ccc_neg_sltu_set"
[(set (reg:CCC CC_REG)
(compare:CCC (zero_extend:DI
- (neg:SI (plus:SI (match_operand:SI 1 "arith_operand" "rI")
+ (neg:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
(ltu:SI (reg:CCC CC_REG)
(const_int 0)))))
(neg:DI (plus:DI (zero_extend:DI (match_dup 1))
@@ -5871,7 +5904,7 @@ visl")
(define_insn "*cmp_ccv_neg"
[(set (reg:CCV CC_REG)
- (compare:CCV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
+ (compare:CCV (neg:SI (match_operand:SI 0 "register_operand" "r"))
(unspec:SI [(match_dup 0)] UNSPEC_NEGV)))]
""
"subcc\t%%g0, %0, %%g0"
@@ -5879,7 +5912,7 @@ visl")
(define_insn "*cmp_ccxv_neg"
[(set (reg:CCXV CC_REG)
- (compare:CCXV (neg:DI (match_operand:DI 0 "arith_operand" "rI"))
+ (compare:CCXV (neg:DI (match_operand:DI 0 "register_operand" "r"))
(unspec:DI [(match_dup 0)] UNSPEC_NEGV)))]
"TARGET_ARCH64"
"subcc\t%%g0, %0, %%g0"
@@ -5887,7 +5920,7 @@ visl")
(define_insn "*cmp_ccv_neg_set"
[(set (reg:CCV CC_REG)
- (compare:CCV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
+ (compare:CCV (neg:SI (match_operand:SI 1 "register_operand" "r"))
(unspec:SI [(match_dup 1)] UNSPEC_NEGV)))
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
@@ -5897,7 +5930,7 @@ visl")
(define_insn "*cmp_ccxv_neg_set"
[(set (reg:CCXV CC_REG)
- (compare:CCXV (neg:DI (match_operand:DI 1 "arith_operand" "rI"))
+ (compare:CCXV (neg:DI (match_operand:DI 1 "register_operand" "r"))
(unspec:DI [(match_dup 1)] UNSPEC_NEGV)))
(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_dup 1)))]
@@ -5907,7 +5940,7 @@ visl")
(define_insn "*cmp_ccv_neg_sltu_set"
[(set (reg:CCV CC_REG)
- (compare:CCV (neg:SI (plus:SI (match_operand:SI 1 "arith_operand" "rI")
+ (compare:CCV (neg:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
(ltu:SI (reg:CCC CC_REG) (const_int 0))))
(unspec:SI [(plus:SI (match_dup 1)
(ltu:SI (reg:CCC CC_REG)
@@ -7935,7 +7968,9 @@ visl")
(clobber (reg:P O7_REG))]
"TARGET_TLS"
"call\t%a1, %%tgd_call(%a2)%#"
- [(set_attr "type" "call")])
+ [(set (attr "type") (if_then_else (eq_attr "tls_delay_slot" "true")
+ (const_string "call")
+ (const_string "call_no_delay_slot")))])
(define_insn "tldm_hi22<P:mode>"
[(set (match_operand:P 0 "register_operand" "=r")
@@ -7966,7 +8001,9 @@ visl")
(clobber (reg:P O7_REG))]
"TARGET_TLS"
"call\t%a1, %%tldm_call(%&)%#"
- [(set_attr "type" "call")])
+ [(set (attr "type") (if_then_else (eq_attr "tls_delay_slot" "true")
+ (const_string "call")
+ (const_string "call_no_delay_slot")))])
(define_insn "tldo_hix22<P:mode>"
[(set (match_operand:P 0 "register_operand" "=r")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index b3d688b..7731e7e 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -26,7 +26,7 @@ TargetVariable
unsigned int sparc_debug
mfpu
-Target Report Mask(FPU)
+Target Mask(FPU)
Use hardware FP.
mhard-float
@@ -38,95 +38,95 @@ Target RejectNegative InverseMask(FPU)
Do not use hardware FP.
mflat
-Target Report Mask(FLAT)
+Target Mask(FLAT)
Use flat register window model.
munaligned-doubles
-Target Report Mask(UNALIGNED_DOUBLES)
+Target Mask(UNALIGNED_DOUBLES)
Assume possible double misalignment.
mapp-regs
-Target Report Mask(APP_REGS)
+Target Mask(APP_REGS)
Use ABI reserved registers.
mhard-quad-float
-Target Report RejectNegative Mask(HARD_QUAD)
+Target RejectNegative Mask(HARD_QUAD)
Use hardware quad FP instructions.
msoft-quad-float
-Target Report RejectNegative InverseMask(HARD_QUAD)
+Target RejectNegative InverseMask(HARD_QUAD)
Do not use hardware quad fp instructions.
mlra
-Target Report Mask(LRA)
+Target Mask(LRA)
Enable Local Register Allocation.
mv8plus
-Target Report Mask(V8PLUS)
+Target Mask(V8PLUS)
Compile for V8+ ABI.
mvis
-Target Report Mask(VIS)
+Target Mask(VIS)
Use UltraSPARC Visual Instruction Set version 1.0 extensions.
mvis2
-Target Report Mask(VIS2)
+Target Mask(VIS2)
Use UltraSPARC Visual Instruction Set version 2.0 extensions.
mvis3
-Target Report Mask(VIS3)
+Target Mask(VIS3)
Use UltraSPARC Visual Instruction Set version 3.0 extensions.
mvis4
-Target Report Mask(VIS4)
+Target Mask(VIS4)
Use UltraSPARC Visual Instruction Set version 4.0 extensions.
mvis4b
-Target Report Mask(VIS4B)
+Target Mask(VIS4B)
Use additional VIS instructions introduced in OSA2017.
mcbcond
-Target Report Mask(CBCOND)
+Target Mask(CBCOND)
Use UltraSPARC Compare-and-Branch extensions.
mfmaf
-Target Report Mask(FMAF)
+Target Mask(FMAF)
Use UltraSPARC Fused Multiply-Add extensions.
mfsmuld
-Target Report Mask(FSMULD)
+Target Mask(FSMULD)
Use Floating-point Multiply Single to Double (FsMULd) instruction.
mpopc
-Target Report Mask(POPC)
+Target Mask(POPC)
Use UltraSPARC Population-Count instruction.
msubxc
-Target Report Mask(SUBXC)
+Target Mask(SUBXC)
Use UltraSPARC Subtract-Extended-with-Carry instruction.
mptr64
-Target Report RejectNegative Mask(PTR64)
+Target RejectNegative Mask(PTR64)
Pointers are 64-bit.
mptr32
-Target Report RejectNegative InverseMask(PTR64)
+Target RejectNegative InverseMask(PTR64)
Pointers are 32-bit.
m64
-Target Report RejectNegative Mask(64BIT)
+Target RejectNegative Mask(64BIT)
Use 64-bit ABI.
m32
-Target Report RejectNegative InverseMask(64BIT)
+Target RejectNegative InverseMask(64BIT)
Use 32-bit ABI.
mstack-bias
-Target Report Mask(STACK_BIAS)
+Target Mask(STACK_BIAS)
Use stack bias.
mfaster-structs
-Target Report Mask(FASTER_STRUCTS)
+Target Mask(FASTER_STRUCTS)
Use structs on stronger alignment for double-word copies.
mrelax
@@ -134,7 +134,7 @@ Target
Optimize tail call instructions in assembler and linker.
muser-mode
-Target Report InverseMask(SV_MODE)
+Target InverseMask(SV_MODE)
Do not generate code that can only run in supervisor mode (default).
mcpu=
@@ -247,24 +247,24 @@ Target RejectNegative Joined Undocumented Var(sparc_debug_string)
Enable debug output.
mstd-struct-return
-Target Report Var(sparc_std_struct_return)
+Target Var(sparc_std_struct_return)
Enable strict 32-bit psABI struct return checking.
mfix-at697f
-Target Report RejectNegative Var(sparc_fix_at697f)
+Target RejectNegative Var(sparc_fix_at697f)
Enable workaround for single erratum of AT697F processor
(corresponding to erratum #13 of AT697E processor).
mfix-ut699
-Target Report RejectNegative Var(sparc_fix_ut699)
+Target RejectNegative Var(sparc_fix_ut699)
Enable workarounds for the errata of the UT699 processor.
mfix-ut700
-Target Report RejectNegative Var(sparc_fix_ut700)
+Target RejectNegative Var(sparc_fix_ut700)
Enable workarounds for the errata of the UT699E/UT700 processor.
mfix-gr712rc
-Target Report RejectNegative Var(sparc_fix_gr712rc)
+Target RejectNegative Var(sparc_fix_gr712rc)
Enable workarounds for the errata of the GR712RC processor.
;; Enable workaround for back-to-back store errata
diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin
index 7f2ac28..355389c 100644
--- a/gcc/config/t-darwin
+++ b/gcc/config/t-darwin
@@ -26,6 +26,9 @@ darwin-c.o: $(srcdir)/config/darwin-c.c
$(COMPILE) $(PREPROCESSOR_DEFINES) $<
$(POSTCOMPILE)
+darwin-d.o: $(srcdir)/config/darwin-d.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
darwin-f.o: $(srcdir)/config/darwin-f.c
$(COMPILE) $<
diff --git a/gcc/config/t-dragonfly b/gcc/config/t-dragonfly
new file mode 100644
index 0000000..764ced9
--- /dev/null
+++ b/gcc/config/t-dragonfly
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+dragonfly-d.o: $(srcdir)/config/dragonfly-d.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/t-freebsd b/gcc/config/t-freebsd
new file mode 100644
index 0000000..ca0cb2e
--- /dev/null
+++ b/gcc/config/t-freebsd
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+freebsd-d.o: $(srcdir)/config/freebsd-d.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 92a1655..142e342 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -5049,9 +5049,7 @@ tilegx_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
end_addr = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0),
TRAMPOLINE_SIZE));
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
- LCT_NORMAL, VOIDmode, begin_addr, Pmode,
- end_addr, Pmode);
+ maybe_emit_call_builtin___clear_cache (begin_addr, end_addr);
}
diff --git a/gcc/config/tilegx/tilegx.opt b/gcc/config/tilegx/tilegx.opt
index bcbadb9..883e09a 100644
--- a/gcc/config/tilegx/tilegx.opt
+++ b/gcc/config/tilegx/tilegx.opt
@@ -33,19 +33,19 @@ EnumValue
Enum(tilegx_cpu) String(tilegx) Value(0)
m32
-Target Report RejectNegative Negative(m64) Mask(32BIT)
+Target RejectNegative Negative(m64) Mask(32BIT)
Compile with 32 bit longs and pointers.
m64
-Target Report RejectNegative Negative(m32) InverseMask(32BIT, 64BIT)
+Target RejectNegative Negative(m32) InverseMask(32BIT, 64BIT)
Compile with 64 bit longs and pointers.
mbig-endian
-Target Report RejectNegative Mask(BIG_ENDIAN)
+Target RejectNegative Mask(BIG_ENDIAN)
Use big-endian byte order.
mlittle-endian
-Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Target RejectNegative InverseMask(BIG_ENDIAN)
Use little-endian byte order.
mcmodel=
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index 540c635..3990194 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -4458,9 +4458,7 @@ tilepro_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
end_addr = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0),
TRAMPOLINE_SIZE));
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
- LCT_NORMAL, VOIDmode, begin_addr, Pmode,
- end_addr, Pmode);
+ maybe_emit_call_builtin___clear_cache (begin_addr, end_addr);
}
diff --git a/gcc/config/tilepro/tilepro.opt b/gcc/config/tilepro/tilepro.opt
index d97eb04..e4ed3a0 100644
--- a/gcc/config/tilepro/tilepro.opt
+++ b/gcc/config/tilepro/tilepro.opt
@@ -19,7 +19,7 @@
; <http://www.gnu.org/licenses/>.
m32
-Target Report RejectNegative
+Target RejectNegative
Compile with 32 bit longs and pointers, which is the only supported
behavior and thus the flag is ignored.
diff --git a/gcc/config/v850/v850.opt b/gcc/config/v850/v850.opt
index 723b5a3..69d62f3 100644
--- a/gcc/config/v850/v850.opt
+++ b/gcc/config/v850/v850.opt
@@ -25,34 +25,34 @@ Variable
int small_memory_max[(int)SMALL_MEMORY_max] = { 0, 0, 0 }
mapp-regs
-Target Report Mask(APP_REGS)
+Target Mask(APP_REGS)
Use registers r2 and r5.
mbig-switch
-Target Report Mask(BIG_SWITCH)
+Target Mask(BIG_SWITCH)
Use 4 byte entries in switch tables.
mdebug
-Target Report Mask(DEBUG)
+Target Mask(DEBUG)
Enable backend debugging.
mdisable-callt
-Target Report Mask(DISABLE_CALLT)
+Target Mask(DISABLE_CALLT)
Do not use the callt instruction (default).
mep
-Target Report Mask(EP)
+Target Mask(EP)
Reuse r30 on a per function basis.
mghs
Target RejectNegative InverseMask(GCC_ABI) MaskExists
mlong-calls
-Target Report Mask(LONG_CALLS)
+Target Mask(LONG_CALLS)
Prohibit PC relative function calls.
mprolog-function
-Target Report Mask(PROLOG_FUNCTION)
+Target Mask(PROLOG_FUNCTION)
Use stubs for function prologues.
msda=
@@ -63,7 +63,7 @@ msda-
Target RejectNegative Joined Undocumented Alias(msda=)
msmall-sld
-Target Report Mask(SMALL_SLD)
+Target Mask(SMALL_SLD)
Enable the use of the short load instructions.
mspace
@@ -78,22 +78,22 @@ mtda-
Target RejectNegative Joined Undocumented Alias(mtda=)
mno-strict-align
-Target Report Mask(NO_STRICT_ALIGN)
+Target Mask(NO_STRICT_ALIGN)
Do not enforce strict alignment.
mjump-tables-in-data-section
-Target Report Mask(JUMP_TABLES_IN_DATA_SECTION)
+Target Mask(JUMP_TABLES_IN_DATA_SECTION)
Put jump tables for switch statements into the .data section rather than the .code section.
mUS-bit-set
-Target Report Mask(US_BIT_SET)
+Target Mask(US_BIT_SET)
mv850
-Target Report RejectNegative Mask(V850)
+Target RejectNegative Mask(V850)
Compile for the v850 processor.
mv850e
-Target Report RejectNegative Mask(V850E)
+Target RejectNegative Mask(V850E)
Compile for the v850e processor.
mv850e1
@@ -105,22 +105,22 @@ Target RejectNegative Mask(V850E1)
Compile for the v850es variant of the v850e1.
mv850e2
-Target Report RejectNegative Mask(V850E2)
+Target RejectNegative Mask(V850E2)
Compile for the v850e2 processor.
mv850e2v3
-Target Report RejectNegative Mask(V850E2V3)
+Target RejectNegative Mask(V850E2V3)
Compile for the v850e2v3 processor.
mv850e3v5
-Target Report RejectNegative Mask(V850E3V5)
+Target RejectNegative Mask(V850E3V5)
Compile for the v850e3v5 processor.
mv850e2v4
Target RejectNegative Mask(V850E3V5) MaskExists
mloop
-Target Report Mask(LOOP)
+Target Mask(LOOP)
Enable v850e3v5 loop instructions.
mzda=
@@ -131,29 +131,29 @@ mzda-
Target RejectNegative Joined Undocumented Alias(mzda=)
mrelax
-Target Report Mask(RELAX)
+Target Mask(RELAX)
Enable relaxing in the assembler.
mlong-jumps
-Target Report Mask(BIG_SWITCH) MaskExists
+Target Mask(BIG_SWITCH) MaskExists
Prohibit PC relative jumps.
msoft-float
-Target Report RejectNegative Mask(SOFT_FLOAT)
+Target RejectNegative Mask(SOFT_FLOAT)
Inhibit the use of hardware floating point instructions.
mhard-float
-Target Report RejectNegative InverseMask(SOFT_FLOAT) MaskExists
+Target RejectNegative InverseMask(SOFT_FLOAT) MaskExists
Allow the use of hardware floating point instructions for V850E2V3 and up.
mrh850-abi
-Target RejectNegative Report InverseMask(GCC_ABI) MaskExists
+Target RejectNegative InverseMask(GCC_ABI) MaskExists
Enable support for the RH850 ABI. This is the default.
mgcc-abi
-Target RejectNegative Report Mask(GCC_ABI)
+Target RejectNegative Mask(GCC_ABI)
Enable support for the old GCC ABI.
m8byte-align
-Target Report Mask(8BYTE_ALIGN)
+Target Mask(8BYTE_ALIGN)
Support alignments of up to 64-bits.
diff --git a/gcc/config/vax/builtins.md b/gcc/config/vax/builtins.md
index ac0e027..846d1f3 100644
--- a/gcc/config/vax/builtins.md
+++ b/gcc/config/vax/builtins.md
@@ -19,38 +19,151 @@
(define_constants
[
- (VUNSPEC_LOCK 100) ; sync lock and test
- (VUNSPEC_UNLOCK 101) ; sync lock release
+ (VUNSPEC_LOCK 100) ; sync lock operations
]
)
-(define_expand "ffssi2"
+(define_mode_attr width [(QI "8") (HI "16") (SI "32")])
+(define_mode_attr bb_mem [(QI "m") (HI "Q") (SI "Q")])
+
+(define_int_iterator bit [0 1])
+(define_int_attr ccss [(0 "cc") (1 "ss")])
+
+(define_code_iterator any_extend [sign_extend zero_extend])
+
+(define_expand "ffs<mode>2"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
- (ffs:SI (match_operand:SI 1 "general_operand" "")))]
+ (ffs:SI (match_operand:VAXint 1 "general_operand" "")))]
""
"
{
rtx label = gen_label_rtx ();
- emit_insn (gen_ffssi2_internal (operands[0], operands[1]));
- emit_jump_insn (gen_bne (label));
- emit_insn (gen_negsi2 (operands[0], const1_rtx));
+ rtx label_ref = gen_rtx_LABEL_REF (VOIDmode, label);
+ rtx cond = gen_rtx_NE (VOIDmode, operands[1], const0_rtx);
+ rtx target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label_ref, pc_rtx);
+
+ emit_insn (gen_ctz<mode>2_ccz (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx_SET (pc_rtx, target));
+ emit_insn (gen_neg<mode>2 (operands[0], const1_rtx));
emit_label (label);
- emit_insn (gen_addsi3 (operands[0], operands[0], const1_rtx));
+ emit_insn (gen_add<mode>3 (operands[0], operands[0], const1_rtx));
DONE;
}")
-(define_insn "ffssi2_internal"
+(define_insn_and_split "ctz<mode>2"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
+ (ctz:SI (match_operand:VAXint 1 "general_operand" "nrQT")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ctz:SI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ctz<mode>2"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
+ (ctz:SI (match_operand:VAXint 1 "general_operand" "nrQT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
+ "ffs $0,$<width>,%1,%0")
+
+(define_insn_and_split "ctz<mode>2_ccz"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
- (ffs:SI (match_operand:SI 1 "general_operand" "nrQt")))
- (set (cc0) (match_dup 0))]
+ (ctz:SI (match_operand:VAXint 1 "general_operand" "nrQT")))]
""
- "ffs $0,$32,%1,%0")
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (reg:CCZ VAX_PSL_REGNUM)
+ (compare:CCZ (match_dup 1)
+ (const_int 0)))
+ (set (match_dup 0)
+ (ctz:SI (match_dup 1)))])]
+ "")
+
+(define_insn "*ctz<mode>2_ccz"
+ [(set (reg:CCZ VAX_PSL_REGNUM)
+ (compare:CCZ (match_operand:VAXint 1 "general_operand" "nrQT")
+ (const_int 0)))
+ (set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
+ (ctz:SI (match_dup 1)))]
+ "reload_completed"
+ "ffs $0,$<width>,%1,%0")
+
+;; Our FFS hardware instruction supports any field width,
+;; so handle narrower inputs directly as well.
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (any_extend:SI (match_operand:VAXintQH 1 "general_operand")))
+ (clobber (reg:CC VAX_PSL_REGNUM))])
+ (parallel
+ [(set (match_operand:SI 2 "nonimmediate_operand")
+ (ctz:SI (match_dup 0)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "rtx_equal_p (operands[0], operands[2]) || peep2_reg_dead_p (2, operands[0])"
+ [(parallel
+ [(set (match_dup 2)
+ (ctz:SI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+;; The FFS hardware instruction sets the Z condition code based on
+;; the input field rather than the output operand, so the compare
+;; elimination pass cannot handle it. Try to get rid of the extra
+;; operation by hand.
+;;
+;; The "ctz<mode>2_ccz" patterns require their `operands[1]' not to
+;; have a mode dependent address, so all we need to verify is that
+;; the two operands are not the same, in which case it's the FFS
+;; output rather than input that condition codes are checked for.
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "nonimmediate_operand")
+ (ctz:SI (match_operand:VAXint 1 "general_operand")))
+ (clobber (reg:CC VAX_PSL_REGNUM))])
+ (set (reg:CCZ VAX_PSL_REGNUM)
+ (compare:CCZ (match_dup 1)
+ (const_int 0)))]
+ "!rtx_equal_p (operands[0], operands[1])"
+ [(parallel
+ [(set (reg:CCZ VAX_PSL_REGNUM)
+ (compare:CCZ (match_dup 1)
+ (const_int 0)))
+ (set (match_dup 0)
+ (ctz:SI (match_dup 1)))])]
+ "")
+
+;; This effectively combines the two peepholes above,
+;; matching the sequence produced by `ffs<mode>2'.
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (any_extend:SI (match_operand:VAXintQH 1 "general_operand")))
+ (clobber (reg:CC VAX_PSL_REGNUM))])
+ (parallel
+ [(set (match_operand:SI 2 "nonimmediate_operand")
+ (ctz:SI (match_dup 0)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])
+ (set (reg:CCZ VAX_PSL_REGNUM)
+ (compare:CCZ (match_dup 0)
+ (const_int 0)))]
+ "!rtx_equal_p (operands[0], operands[2])
+ && peep2_reg_dead_p (3, operands[0])"
+ [(parallel
+ [(set (reg:CCZ VAX_PSL_REGNUM)
+ (compare:CCZ (match_dup 1)
+ (const_int 0)))
+ (set (match_dup 2)
+ (ctz:SI (match_dup 1)))])]
+ "")
(define_expand "sync_lock_test_and_set<mode>"
- [(set (match_operand:VAXint 0 "nonimmediate_operand" "=&g")
- (unspec:VAXint [(match_operand:VAXint 1 "memory_operand" "+m")
- (match_operand:VAXint 2 "const_int_operand" "n")
- ] VUNSPEC_LOCK))]
+ [(match_operand:VAXint 0 "nonimmediate_operand" "=&g")
+ (match_operand:VAXint 1 "memory_operand" "+m")
+ (match_operand:VAXint 2 "const_int_operand" "n")]
""
"
{
@@ -61,132 +174,46 @@
label = gen_label_rtx ();
emit_move_insn (operands[0], const1_rtx);
- emit_jump_insn (gen_jbbssi<mode> (operands[1], const0_rtx, label, operands[1]));
+ emit_jump_insn (gen_jbbssi<mode> (operands[1], const0_rtx, label,
+ operands[1]));
emit_move_insn (operands[0], const0_rtx);
emit_label (label);
DONE;
}")
-(define_insn "jbbssiqi"
- [(parallel
- [(set (pc)
- (if_then_else
- (ne (zero_extract:SI (match_operand:QI 0 "memory_operand" "g")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "nrm"))
- (const_int 0))
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (zero_extract:SI (match_operand:QI 3 "memory_operand" "+0")
- (const_int 1)
- (match_dup 1))
- (const_int 1))])]
- ""
- "jbssi %1,%0,%l2")
-
-(define_insn "jbbssihi"
- [(parallel
- [(set (pc)
- (if_then_else
- (ne (zero_extract:SI (match_operand:HI 0 "memory_operand" "Q")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "nrm"))
- (const_int 0))
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (zero_extract:SI (match_operand:HI 3 "memory_operand" "+0")
- (const_int 1)
- (match_dup 1))
- (const_int 1))])]
- ""
- "jbssi %1,%0,%l2")
-
-(define_insn "jbbssisi"
- [(parallel
- [(set (pc)
- (if_then_else
- (ne (zero_extract:SI (match_operand:SI 0 "memory_operand" "Q")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "nrm"))
- (const_int 0))
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (zero_extract:SI (match_operand:SI 3 "memory_operand" "+0")
- (const_int 1)
- (match_dup 1))
- (const_int 1))])]
- ""
- "jbssi %1,%0,%l2")
-
-
(define_expand "sync_lock_release<mode>"
- [(set (match_operand:VAXint 0 "memory_operand" "+m")
- (unspec:VAXint [(match_operand:VAXint 1 "const_int_operand" "n")
- ] VUNSPEC_UNLOCK))]
+ [(match_operand:VAXint 0 "memory_operand" "+m")
+ (match_operand:VAXint 1 "const_int_operand" "n")]
""
"
{
rtx label;
+
if (operands[1] != const0_rtx)
FAIL;
-#if 1
+
label = gen_label_rtx ();
- emit_jump_insn (gen_jbbcci<mode> (operands[0], const0_rtx, label, operands[0]));
+ emit_jump_insn (gen_jbbcci<mode> (operands[0], const0_rtx, label,
+ operands[0]));
emit_label (label);
-#else
- emit_move_insn (operands[0], const0_rtx);
-#endif
DONE;
}")
-(define_insn "jbbcciqi"
- [(parallel
- [(set (pc)
- (if_then_else
- (eq (zero_extract:SI (match_operand:QI 0 "memory_operand" "g")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "nrm"))
- (const_int 0))
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (zero_extract:SI (match_operand:QI 3 "memory_operand" "+0")
- (const_int 1)
- (match_dup 1))
- (const_int 0))])]
- ""
- "jbcci %1,%0,%l2")
-
-(define_insn "jbbccihi"
- [(parallel
- [(set (pc)
- (if_then_else
- (eq (zero_extract:SI (match_operand:HI 0 "memory_operand" "Q")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "nrm"))
- (const_int 0))
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (zero_extract:SI (match_operand:HI 3 "memory_operand" "+0")
- (const_int 1)
- (match_dup 1))
- (const_int 0))])]
- ""
- "jbcci %1,%0,%l2")
-
-(define_insn "jbbccisi"
- [(parallel
+(define_insn "jbb<ccss>i<mode>"
+ [(unspec_volatile
[(set (pc)
(if_then_else
- (eq (zero_extract:SI (match_operand:SI 0 "memory_operand" "Q")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "nrm"))
- (const_int 0))
+ (eq (zero_extract:SI
+ (match_operand:VAXint 0 "any_memory_operand" "<bb_mem>")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "nrmT"))
+ (const_int bit))
(label_ref (match_operand 2 "" ""))
(pc)))
- (set (zero_extract:SI (match_operand:SI 3 "memory_operand" "+0")
+ (set (zero_extract:SI (match_operand:VAXint 3 "any_memory_operand" "+0")
(const_int 1)
(match_dup 1))
- (const_int 0))])]
+ (const_int bit))]
+ VUNSPEC_LOCK)]
""
- "jbcci %1,%0,%l2")
-
+ "jb<ccss>i %1,%0,%l2")
diff --git a/gcc/config/vax/constraints.md b/gcc/config/vax/constraints.md
index b8262b6..d4eddb8 100644
--- a/gcc/config/vax/constraints.md
+++ b/gcc/config/vax/constraints.md
@@ -112,6 +112,10 @@
(and (match_operand:DI 0 "memory_operand")
(not (match_operand:DI 0 "illegal_addsub_di_memory_operand" ""))))
+(define_constraint "A"
+ "@internal An integer constant suitable for address load operations."
+ (match_test ("CONSTANT_P (op) && pic_symbolic_operand (op, mode)")))
+
(define_constraint "T"
"@internal satisfies CONSTANT_P and, if pic is enabled, is not a SYMBOL_REF, LABEL_REF, or CONST."
(and (match_test ("CONSTANT_P (op)"))
diff --git a/gcc/config/vax/elf.h b/gcc/config/vax/elf.h
index 555ccef..f6485eca 100644
--- a/gcc/config/vax/elf.h
+++ b/gcc/config/vax/elf.h
@@ -26,7 +26,8 @@ along with GCC; see the file COPYING3. If not see
#define REGISTER_PREFIX "%"
#define REGISTER_NAMES \
{ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", \
- "%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", }
+ "%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", \
+ "%psl" }
#undef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
@@ -89,6 +90,16 @@ along with GCC; see the file COPYING3. If not see
%{!fpic: \
%{!fPIC:-fPIC}}}"
+/* Don't let the LTO compiler switch the PIC options off. */
+#define VAX_CC1_SPEC \
+ VAX_CC1_AND_CC1PLUS_SPEC \
+ " %{flinker-output=exec" \
+ ":%{no-pie:-flinker-output=exec;:-flinker-output=pie};" \
+ ":%{flinker-output=*}}" \
+ "%<flinker-output*"
+#define VAX_CC1PLUS_SPEC \
+ VAX_CC1_AND_CC1PLUS_SPEC
+
/* VAX ELF is always gas; override the generic VAX ASM_SPEC. */
#undef ASM_SPEC
diff --git a/gcc/config/vax/netbsd-elf.h b/gcc/config/vax/netbsd-elf.h
index 26b98ef..9a01fdd 100644
--- a/gcc/config/vax/netbsd-elf.h
+++ b/gcc/config/vax/netbsd-elf.h
@@ -35,10 +35,10 @@ along with GCC; see the file COPYING3. If not see
#endif
#undef CC1_SPEC
-#define CC1_SPEC NETBSD_CC1_AND_CC1PLUS_SPEC VAX_CC1_AND_CC1PLUS_SPEC
+#define CC1_SPEC NETBSD_CC1_AND_CC1PLUS_SPEC VAX_CC1_SPEC
#undef CC1PLUS_SPEC
-#define CC1PLUS_SPEC NETBSD_CC1_AND_CC1PLUS_SPEC VAX_CC1_AND_CC1PLUS_SPEC
+#define CC1PLUS_SPEC NETBSD_CC1_AND_CC1PLUS_SPEC VAX_CC1PLUS_SPEC
#define NETBSD_ENTRY_POINT "__start"
diff --git a/gcc/config/vax/predicates.md b/gcc/config/vax/predicates.md
index 7eefc60..92caf83 100644
--- a/gcc/config/vax/predicates.md
+++ b/gcc/config/vax/predicates.md
@@ -17,39 +17,27 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Return true if OP is a constant zero operand.
+(define_predicate "const_zero_operand"
+ (match_test "op == CONST0_RTX (mode)"))
+
;; Special case of a symbolic operand that's used as a
;; operand.
(define_predicate "symbolic_operand"
(match_code "const,symbol_ref,label_ref"))
-(define_predicate "local_symbolic_operand"
- (match_code "const,symbol_ref,label_ref")
-{
- if (GET_CODE (op) == LABEL_REF)
- return 1;
- if (GET_CODE (op) == SYMBOL_REF)
- return !flag_pic || SYMBOL_REF_LOCAL_P (op);
- if (GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF)
- return 1;
- return !flag_pic || SYMBOL_REF_LOCAL_P (XEXP (XEXP (op, 0), 0));
-})
-
-(define_predicate "external_symbolic_operand"
- (and (match_code "symbol_ref")
- (not (match_operand 0 "local_symbolic_operand" ""))))
-
-(define_predicate "external_const_operand"
- (and (match_code "const")
- (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
- && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (op, 0), 0))")))
+(define_predicate "pic_symbolic_operand"
+ (and (match_code "const,symbol_ref,label_ref")
+ (match_test "!flag_pic
+ || vax_acceptable_pic_operand_p (op, false, true)")))
(define_predicate "nonsymbolic_operand"
(and (ior (match_test "!flag_pic")
(not (match_operand 0 "symbolic_operand")))
(match_operand 0 "general_operand" "")))
-(define_predicate "external_memory_operand"
+(define_predicate "non_pic_external_memory_operand"
(match_code "mem")
{
rtx addr = XEXP (op, 0);
@@ -61,8 +49,8 @@
addr = XEXP (addr, 0);
if (GET_CODE (addr) == PLUS)
addr = XEXP (addr, 1);
- return external_symbolic_operand (addr, SImode)
- || external_const_operand (addr, SImode);
+ return (symbolic_operand (addr, SImode)
+ && !vax_acceptable_pic_operand_p (addr, true, true));
})
(define_predicate "indirect_memory_operand"
@@ -87,7 +75,7 @@
(define_predicate "illegal_blk_memory_operand"
(and (match_code "mem")
(ior (and (match_test "flag_pic")
- (match_operand 0 "external_memory_operand" ""))
+ (match_operand 0 "non_pic_external_memory_operand" ""))
(ior (match_operand 0 "indexed_memory_operand" "")
(ior (match_operand 0 "indirect_memory_operand" "")
(match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))))))
@@ -95,7 +83,7 @@
(define_predicate "illegal_addsub_di_memory_operand"
(and (match_code "mem")
(ior (and (match_test "flag_pic")
- (match_operand 0 "external_memory_operand" ""))
+ (match_operand 0 "non_pic_external_memory_operand" ""))
(ior (match_operand 0 "indexed_memory_operand" "")
(ior (match_operand 0 "indirect_memory_operand" "")
(match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))))))
@@ -109,3 +97,35 @@
(and (match_code "const_int,const_double,subreg,reg,mem")
(and (match_operand:DI 0 "general_operand" "")
(not (match_operand:DI 0 "illegal_addsub_di_memory_operand")))))
+
+;; Return 1 if the operand is in volatile memory. Note that during the
+;; RTL generation phase, `memory_operand' does not return TRUE for
+;; volatile memory references. So this function allows us to recognize
+;; volatile references where it's safe.
+(define_predicate "volatile_mem_operand"
+ (and (match_code "mem")
+ (match_test "MEM_VOLATILE_P (op)")
+ (if_then_else (match_test "reload_completed")
+ (match_operand 0 "memory_operand")
+ (match_test "memory_address_p (mode, XEXP (op, 0))"))))
+
+;; Return 1 if the operand is a volatile or non-volatile memory operand.
+(define_predicate "any_memory_operand"
+ (ior (match_operand 0 "memory_operand")
+ (match_operand 0 "volatile_mem_operand")))
+
+;; Return true if OP is a comparison operator that requires at least CCmode.
+(define_predicate "vax_cc_comparison_operator"
+ (match_code "geu,gtu,leu,ltu"))
+
+;; Return true if OP is a comparison operator that requires at least CCNmode.
+(define_predicate "vax_ccn_comparison_operator"
+ (match_code "ge,lt"))
+
+;; Return true if OP is a comparison operator that requires at least CCNZmode.
+(define_predicate "vax_ccnz_comparison_operator"
+ (match_code "gt,le"))
+
+;; Return true if OP is a comparison operator that requires at least CCZmode.
+(define_predicate "vax_ccz_comparison_operator"
+ (match_code "ne,eq"))
diff --git a/gcc/config/vax/vax-modes.def b/gcc/config/vax/vax-modes.def
index 5f1c994..2a7438e 100644
--- a/gcc/config/vax/vax-modes.def
+++ b/gcc/config/vax/vax-modes.def
@@ -20,3 +20,14 @@ along with GCC; see the file COPYING3. If not see
/* We just need to reset the floating point formats. */
RESET_FLOAT_FORMAT (SF, vax_f_format);
RESET_FLOAT_FORMAT (DF, vax_d_format);
+
+/* `DImode' addition and subtraction operations do their calculation
+ on the low and then the high longword with separate instructions,
+ and therefore only usably set N. */
+CC_MODE (CCN);
+/* Non-arithmetic integer instructions such as MOV or XOR as well as
+ instructions that produce a floating-point result only usably set
+ N and Z. */
+CC_MODE (CCNZ);
+/* The FFC and FFS instructions only usably set Z. */
+CC_MODE (CCZ);
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index cda2544..aa949c5 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -21,13 +21,15 @@ extern bool legitimate_constant_address_p (rtx);
extern void vax_expand_prologue (void);
#ifdef RTX_CODE
+extern bool vax_acceptable_pic_operand_p (rtx, bool, bool);
+extern machine_mode vax_select_cc_mode (enum rtx_code, rtx, rtx);
extern const char *cond_name (rtx);
extern bool adjacent_operands_p (rtx, rtx, machine_mode);
extern const char *rev_cond_name (rtx);
extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int);
-extern void vax_notice_update_cc (rtx, rtx);
extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code);
+extern bool vax_maybe_split_dimode_move (rtx *);
extern const char * vax_output_int_move (rtx, rtx *, machine_mode);
extern const char * vax_output_int_add (rtx_insn *, rtx *, machine_mode);
extern const char * vax_output_int_subtract (rtx_insn *, rtx *, machine_mode);
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 4a1ecfa..f5968d6 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -54,6 +54,10 @@ static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
static int vax_address_cost_1 (rtx);
static int vax_address_cost (rtx, machine_mode, addr_space_t, bool);
static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+static machine_mode vax_cc_modes_compatible (machine_mode, machine_mode);
+static rtx_insn *vax_md_asm_adjust (vec<rtx> &, vec<rtx> &,
+ vec<const char *> &,
+ vec<rtx> &, HARD_REG_SET &);
static rtx vax_function_arg (cumulative_args_t, const function_arg_info &);
static void vax_function_arg_advance (cumulative_args_t,
const function_arg_info &);
@@ -81,11 +85,23 @@ static HOST_WIDE_INT vax_starting_frame_offset (void);
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+/* Enable compare elimination pass. */
+#undef TARGET_FLAGS_REGNUM
+#define TARGET_FLAGS_REGNUM VAX_PSL_REGNUM
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS vax_rtx_costs
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST vax_address_cost
+/* Return the narrowest CC mode that spans both modes offered. */
+#undef TARGET_CC_MODES_COMPATIBLE
+#define TARGET_CC_MODES_COMPATIBLE vax_cc_modes_compatible
+
+/* Mark PSL as clobbered for compatibility with the CC0 representation. */
+#undef TARGET_MD_ASM_ADJUST
+#define TARGET_MD_ASM_ADJUST vax_md_asm_adjust
+
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
@@ -509,9 +525,9 @@ print_operand (FILE *file, rtx x, int code)
fputc (ASM_DOUBLE_CHAR, file);
else if (code == '|')
fputs (REGISTER_PREFIX, file);
- else if (code == 'c')
+ else if (code == 'k')
fputs (cond_name (x), file);
- else if (code == 'C')
+ else if (code == 'K')
fputs (rev_cond_name (x), file);
else if (code == 'D' && CONST_INT_P (x) && INTVAL (x) < 0)
fprintf (file, "$" NEG_HWI_PRINT_HEX16, INTVAL (x));
@@ -748,7 +764,7 @@ vax_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
addr_space_t as ATTRIBUTE_UNUSED,
bool speed ATTRIBUTE_UNUSED)
{
- return (1 + (REG_P (x) ? 0 : vax_address_cost_1 (x)));
+ return COSTS_N_INSNS (1 + (REG_P (x) ? 0 : vax_address_cost_1 (x)));
}
/* Cost of an expression on a VAX. This version has costs tuned for the
@@ -764,7 +780,7 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
int opno ATTRIBUTE_UNUSED,
int *total, bool speed ATTRIBUTE_UNUSED)
{
- int code = GET_CODE (x);
+ enum rtx_code code = GET_CODE (x);
int i = 0; /* may be modified in switch */
const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
@@ -778,12 +794,13 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST_INT:
if (INTVAL (x) == 0)
{
- *total = 0;
+ *total = COSTS_N_INSNS (1) / 2;
return true;
}
if (outer_code == AND)
{
- *total = ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077) ? 1 : 2;
+ *total = ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077
+ ? COSTS_N_INSNS (1) : COSTS_N_INSNS (2));
return true;
}
if ((unsigned HOST_WIDE_INT) INTVAL (x) <= 077
@@ -792,7 +809,7 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
|| ((outer_code == PLUS || outer_code == MINUS)
&& (unsigned HOST_WIDE_INT) -INTVAL (x) <= 077))
{
- *total = 1;
+ *total = COSTS_N_INSNS (1);
return true;
}
/* FALLTHRU */
@@ -800,48 +817,48 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST:
case LABEL_REF:
case SYMBOL_REF:
- *total = 3;
+ *total = COSTS_N_INSNS (3);
return true;
case CONST_DOUBLE:
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- *total = vax_float_literal (x) ? 5 : 8;
+ *total = vax_float_literal (x) ? COSTS_N_INSNS (5) : COSTS_N_INSNS (8);
else
*total = ((CONST_DOUBLE_HIGH (x) == 0
&& (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x) < 64)
|| (outer_code == PLUS
&& CONST_DOUBLE_HIGH (x) == -1
- && (unsigned HOST_WIDE_INT)-CONST_DOUBLE_LOW (x) < 64))
- ? 2 : 5;
+ && (unsigned HOST_WIDE_INT)-CONST_DOUBLE_LOW (x) < 64)
+ ? COSTS_N_INSNS (2) : COSTS_N_INSNS (5));
return true;
case POST_INC:
- *total = 2;
- return true; /* Implies register operand. */
+ *total = COSTS_N_INSNS (2);
+ return true; /* Implies register operand. */
case PRE_DEC:
- *total = 3;
- return true; /* Implies register operand. */
+ *total = COSTS_N_INSNS (3);
+ return true; /* Implies register operand. */
case MULT:
switch (mode)
{
case E_DFmode:
- *total = 16; /* 4 on VAX 9000 */
+ *total = COSTS_N_INSNS (16); /* 4 on VAX 9000 */
break;
case E_SFmode:
- *total = 9; /* 4 on VAX 9000, 12 on VAX 2 */
+ *total = COSTS_N_INSNS (9); /* 4 on VAX 9000, 12 on VAX 2 */
break;
case E_DImode:
- *total = 16; /* 6 on VAX 9000, 28 on VAX 2 */
+ *total = COSTS_N_INSNS (16); /* 6 on VAX 9000, 28 on VAX 2 */
break;
case E_SImode:
case E_HImode:
case E_QImode:
- *total = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
+ *total = COSTS_N_INSNS (10); /* 3-4 on VAX 9000, 20-28 on VAX 2 */
break;
default:
- *total = MAX_COST; /* Mode is not supported. */
+ *total = MAX_COST; /* Mode is not supported. */
return true;
}
break;
@@ -849,63 +866,65 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
case UDIV:
if (mode != SImode)
{
- *total = MAX_COST; /* Mode is not supported. */
+ *total = MAX_COST; /* Mode is not supported. */
return true;
}
- *total = 17;
+ *total = COSTS_N_INSNS (17);
break;
case DIV:
if (mode == DImode)
- *total = 30; /* Highly variable. */
+ *total = COSTS_N_INSNS (30); /* Highly variable. */
else if (mode == DFmode)
/* divide takes 28 cycles if the result is not zero, 13 otherwise */
- *total = 24;
+ *total = COSTS_N_INSNS (24);
else
- *total = 11; /* 25 on VAX 2 */
+ *total = COSTS_N_INSNS (11); /* 25 on VAX 2 */
break;
case MOD:
- *total = 23;
+ *total = COSTS_N_INSNS (23);
break;
case UMOD:
if (mode != SImode)
{
- *total = MAX_COST; /* Mode is not supported. */
+ *total = MAX_COST; /* Mode is not supported. */
return true;
}
- *total = 29;
+ *total = COSTS_N_INSNS (29);
break;
case FLOAT:
- *total = (6 /* 4 on VAX 9000 */
- + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode));
+ *total = COSTS_N_INSNS (6 /* 4 on VAX 9000 */
+ + (mode == DFmode)
+ + (GET_MODE (XEXP (x, 0)) != SImode));
break;
case FIX:
- *total = 7; /* 17 on VAX 2 */
+ *total = COSTS_N_INSNS (7); /* 17 on VAX 2 */
break;
case ASHIFT:
case LSHIFTRT:
case ASHIFTRT:
if (mode == DImode)
- *total = 12;
+ *total = COSTS_N_INSNS (12);
else
- *total = 10; /* 6 on VAX 9000 */
+ *total = COSTS_N_INSNS (10); /* 6 on VAX 9000 */
break;
case ROTATE:
case ROTATERT:
- *total = 6; /* 5 on VAX 2, 4 on VAX 9000 */
+ *total = COSTS_N_INSNS (6); /* 5 on VAX 2, 4 on VAX 9000 */
if (CONST_INT_P (XEXP (x, 1)))
fmt = "e"; /* all constant rotate counts are short */
break;
case PLUS:
case MINUS:
- *total = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
+ *total = (mode == DFmode /* 6/8 on VAX 9000, 16/15 on VAX 2 */
+ ? COSTS_N_INSNS (13) : COSTS_N_INSNS (8));
/* Small integer operands can use subl2 and addl2. */
if ((CONST_INT_P (XEXP (x, 1)))
&& (unsigned HOST_WIDE_INT)(INTVAL (XEXP (x, 1)) + 63) < 127)
@@ -914,16 +933,16 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
case IOR:
case XOR:
- *total = 3;
+ *total = COSTS_N_INSNS (3);
break;
case AND:
/* AND is special because the first operand is complemented. */
- *total = 3;
+ *total = COSTS_N_INSNS (3);
if (CONST_INT_P (XEXP (x, 0)))
{
if ((unsigned HOST_WIDE_INT)~INTVAL (XEXP (x, 0)) > 63)
- *total = 4;
+ *total = COSTS_N_INSNS (4);
fmt = "e";
i = 1;
}
@@ -931,38 +950,38 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
case NEG:
if (mode == DFmode)
- *total = 9;
+ *total = COSTS_N_INSNS (9);
else if (mode == SFmode)
- *total = 6;
+ *total = COSTS_N_INSNS (6);
else if (mode == DImode)
- *total = 4;
+ *total = COSTS_N_INSNS (4);
else
- *total = 2;
+ *total = COSTS_N_INSNS (2);
break;
case NOT:
- *total = 2;
+ *total = COSTS_N_INSNS (2);
break;
case ZERO_EXTRACT:
case SIGN_EXTRACT:
- *total = 15;
+ *total = COSTS_N_INSNS (15);
break;
case MEM:
if (mode == DImode || mode == DFmode)
- *total = 5; /* 7 on VAX 2 */
+ *total = COSTS_N_INSNS (5); /* 7 on VAX 2 */
else
- *total = 3; /* 4 on VAX 2 */
+ *total = COSTS_N_INSNS (3); /* 4 on VAX 2 */
x = XEXP (x, 0);
if (!REG_P (x) && GET_CODE (x) != POST_INC)
- *total += vax_address_cost_1 (x);
+ *total += COSTS_N_INSNS (vax_address_cost_1 (x));
return true;
case FLOAT_EXTEND:
case FLOAT_TRUNCATE:
case TRUNCATE:
- *total = 3; /* FIXME: Costs need to be checked */
+ *total = COSTS_N_INSNS (3); /* FIXME: Costs need to be checked */
break;
default:
@@ -993,12 +1012,12 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST_INT:
if ((unsigned HOST_WIDE_INT)INTVAL (op) > 63
&& mode != QImode)
- *total += 1; /* 2 on VAX 2 */
+ *total += COSTS_N_INSNS (1); /* 2 on VAX 2 */
break;
case CONST:
case LABEL_REF:
case SYMBOL_REF:
- *total += 1; /* 2 on VAX 2 */
+ *total += COSTS_N_INSNS (1); /* 2 on VAX 2 */
break;
case CONST_DOUBLE:
if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
@@ -1006,33 +1025,163 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
/* Registers are faster than floating point constants -- even
those constants which can be encoded in a single byte. */
if (vax_float_literal (op))
- *total += 1;
+ *total += COSTS_N_INSNS (1);
else
- *total += (GET_MODE (x) == DFmode) ? 3 : 2;
+ *total += (GET_MODE (x) == DFmode
+ ? COSTS_N_INSNS (3) : COSTS_N_INSNS (2));
}
else
{
if (CONST_DOUBLE_HIGH (op) != 0
|| (unsigned HOST_WIDE_INT)CONST_DOUBLE_LOW (op) > 63)
- *total += 2;
+ *total += COSTS_N_INSNS (2);
}
break;
case MEM:
- *total += 1; /* 2 on VAX 2 */
+ *total += COSTS_N_INSNS (1); /* 2 on VAX 2 */
if (!REG_P (XEXP (op, 0)))
- *total += vax_address_cost_1 (XEXP (op, 0));
+ *total += COSTS_N_INSNS (vax_address_cost_1 (XEXP (op, 0)));
break;
case REG:
case SUBREG:
break;
default:
- *total += 1;
+ *total += COSTS_N_INSNS (1);
break;
}
}
return true;
}
+/* With ELF we do not support GOT entries for external `symbol+offset'
+ references, so do not accept external symbol references if an offset
+ is to be added. Do not accept external symbol references at all if
+ LOCAL_P is set. This is for cases where making a reference indirect
+ would make it invalid. Do not accept any kind of symbols if SYMBOL_P
+ is clear. This is for situations where the a reference is used as an
+ immediate value for operations other than address loads (MOVA/PUSHA),
+ as those operations do not support PC-relative immediates. */
+
+bool
+vax_acceptable_pic_operand_p (rtx x ATTRIBUTE_UNUSED,
+ bool local_p ATTRIBUTE_UNUSED,
+ bool symbol_p ATTRIBUTE_UNUSED)
+{
+#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
+ {
+ x = XEXP (XEXP (x, 0), 0);
+ local_p = true;
+ }
+ switch (GET_CODE (x))
+ {
+ case SYMBOL_REF:
+ return symbol_p && !(local_p && !SYMBOL_REF_LOCAL_P (x));
+ case LABEL_REF:
+ return symbol_p && !(local_p && LABEL_REF_NONLOCAL_P (x));
+ default:
+ break;
+ }
+#endif
+ return true;
+}
+
+/* Given a comparison code (NE, EQ, etc.) and the operands of a COMPARE,
+ return the mode to be used for the comparison. As we have the same
+ interpretation of condition codes across all the instructions we just
+ return the narrowest mode suitable for the comparison code requested. */
+
+extern machine_mode
+vax_select_cc_mode (enum rtx_code op,
+ rtx x ATTRIBUTE_UNUSED, rtx y ATTRIBUTE_UNUSED)
+{
+ switch (op)
+ {
+ default:
+ gcc_unreachable ();
+ case NE:
+ case EQ:
+ return CCZmode;
+ case GE:
+ case LT:
+ return CCNmode;
+ case GT:
+ case LE:
+ return CCNZmode;
+ case GEU:
+ case GTU:
+ case LEU:
+ case LTU:
+ return CCmode;
+ }
+}
+
+/* Return the narrowest CC mode that spans both modes offered. If they
+ intersect, this will be the wider of the two, and if they do not then
+ find find one that is a superset of both (i.e. CCNZmode for a pair
+ consisting of CCNmode and CCZmode). A wider CC writer will satisfy
+ a narrower CC reader, e.g. a comparison operator that uses CCZmode
+ can use a CCNZmode output of a previous instruction. */
+
+static machine_mode
+vax_cc_modes_compatible (machine_mode m1, machine_mode m2)
+{
+ switch (m1)
+ {
+ default:
+ gcc_unreachable ();
+ case E_CCmode:
+ switch (m2)
+ {
+ default:
+ gcc_unreachable ();
+ case E_CCmode:
+ case E_CCNZmode:
+ case E_CCNmode:
+ case E_CCZmode:
+ return m1;
+ }
+ case E_CCNZmode:
+ switch (m2)
+ {
+ default:
+ gcc_unreachable ();
+ case E_CCmode:
+ return m2;
+ case E_CCNmode:
+ case E_CCNZmode:
+ case E_CCZmode:
+ return m1;
+ }
+ case E_CCNmode:
+ case E_CCZmode:
+ switch (m2)
+ {
+ default:
+ gcc_unreachable ();
+ case E_CCmode:
+ case E_CCNZmode:
+ return m2;
+ case E_CCNmode:
+ case E_CCZmode:
+ return m1 == m2 ? m1 : E_CCNZmode;
+ }
+ }
+}
+
+/* Mark PSL as clobbered for compatibility with the CC0 representation. */
+
+static rtx_insn *
+vax_md_asm_adjust (vec<rtx> &outputs ATTRIBUTE_UNUSED,
+ vec<rtx> &inputs ATTRIBUTE_UNUSED,
+ vec<const char *> &constraints ATTRIBUTE_UNUSED,
+ vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs)
+{
+ clobbers.safe_push (gen_rtx_REG (CCmode, VAX_PSL_REGNUM));
+ SET_HARD_REG_BIT (clobbered_regs, VAX_PSL_REGNUM);
+ return NULL;
+}
+
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance.
.mask ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> #conservative entry mask
@@ -1065,84 +1214,28 @@ vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM);
}
-/* Worker function for NOTICE_UPDATE_CC. */
+/* Output integer move instructions. */
-void
-vax_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
+bool
+vax_maybe_split_dimode_move (rtx *operands)
{
- if (GET_CODE (exp) == SET)
- {
- if (GET_CODE (SET_SRC (exp)) == CALL)
- CC_STATUS_INIT;
- else if (GET_CODE (SET_DEST (exp)) != ZERO_EXTRACT
- && GET_CODE (SET_DEST (exp)) != PC)
- {
- cc_status.flags = 0;
- /* The integer operations below don't set carry or
- set it in an incompatible way. That's ok though
- as the Z bit is all we need when doing unsigned
- comparisons on the result of these insns (since
- they're always with 0). Set CC_NO_OVERFLOW to
- generate the correct unsigned branches. */
- switch (GET_CODE (SET_SRC (exp)))
- {
- case NEG:
- if (GET_MODE_CLASS (GET_MODE (exp)) == MODE_FLOAT)
- break;
- /* FALLTHRU */
- case AND:
- case IOR:
- case XOR:
- case NOT:
- case MEM:
- case REG:
- cc_status.flags = CC_NO_OVERFLOW;
- break;
- default:
- break;
- }
- cc_status.value1 = SET_DEST (exp);
- cc_status.value2 = SET_SRC (exp);
- }
- }
- else if (GET_CODE (exp) == PARALLEL
- && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
- {
- if (GET_CODE (SET_SRC (XVECEXP (exp, 0, 0))) == CALL)
- CC_STATUS_INIT;
- else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) != PC)
- {
- cc_status.flags = 0;
- cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0));
- cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0));
- }
- else
- /* PARALLELs whose first element sets the PC are aob,
- sob insns. They do change the cc's. */
- CC_STATUS_INIT;
- }
- else
- CC_STATUS_INIT;
- if (cc_status.value1 && REG_P (cc_status.value1)
- && cc_status.value2
- && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
- cc_status.value2 = 0;
- if (cc_status.value1 && MEM_P (cc_status.value1)
- && cc_status.value2
- && MEM_P (cc_status.value2))
- cc_status.value2 = 0;
- /* Actual condition, one line up, should be that value2's address
- depends on value1, but that is too much of a pain. */
+ return (TARGET_QMATH
+ && (!MEM_P (operands[0])
+ || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+ || GET_CODE (XEXP (operands[0], 0)) == POST_INC
+ || !illegal_addsub_di_memory_operand (operands[0], DImode))
+ && ((CONST_INT_P (operands[1])
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64)
+ || GET_CODE (operands[1]) == CONST_DOUBLE));
}
-/* Output integer move instructions. */
-
const char *
vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
machine_mode mode)
{
rtx hi[3], lo[3];
const char *pattern_hi, *pattern_lo;
+ bool push_p;
switch (mode)
{
@@ -1212,14 +1305,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
}
}
- if (TARGET_QMATH
- && (!MEM_P (operands[0])
- || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
- || GET_CODE (XEXP (operands[0], 0)) == POST_INC
- || !illegal_addsub_di_memory_operand (operands[0], DImode))
- && ((CONST_INT_P (operands[1])
- && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64)
- || GET_CODE (operands[1]) == CONST_DOUBLE))
+ if (vax_maybe_split_dimode_move (operands))
{
hi[0] = operands[0];
hi[1] = operands[1];
@@ -1260,19 +1346,13 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
return "movq %1,%0";
case E_SImode:
+ push_p = push_operand (operands[0], SImode);
+
if (symbolic_operand (operands[1], SImode))
- {
- if (push_operand (operands[0], SImode))
- return "pushab %a1";
- return "movab %a1,%0";
- }
+ return push_p ? "pushab %a1" : "movab %a1,%0";
if (operands[1] == const0_rtx)
- {
- if (push_operand (operands[1], SImode))
- return "pushl %1";
- return "clrl %0";
- }
+ return push_p ? "pushl %1" : "clrl %0";
if (CONST_INT_P (operands[1])
&& (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64)
@@ -1298,9 +1378,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
if (i >= -0x8000 && i < 0)
return "cvtwl %1,%0";
}
- if (push_operand (operands[0], SImode))
- return "pushl %1";
- return "movl %1,%0";
+ return push_p ? "pushl %1" : "movl %1,%0";
case E_HImode:
if (CONST_INT_P (operands[1]))
@@ -1369,9 +1447,11 @@ vax_output_int_add (rtx_insn *insn, rtx *operands, machine_mode mode)
if (TARGET_QMATH)
{
gcc_assert (rtx_equal_p (operands[0], operands[1]));
-#ifdef NO_EXTERNAL_INDIRECT_ADDRESSS
- gcc_assert (!flag_pic || !external_memory_operand (low[2], SImode));
- gcc_assert (!flag_pic || !external_memory_operand (low[0], SImode));
+#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
+ gcc_assert (!flag_pic
+ || !non_pic_external_memory_operand (low[2], SImode));
+ gcc_assert (!flag_pic
+ || !non_pic_external_memory_operand (low[0], SImode));
#endif
/* No reason to add a 0 to the low part and thus no carry, so just
@@ -1511,7 +1591,7 @@ vax_output_int_add (rtx_insn *insn, rtx *operands, machine_mode mode)
if (flag_pic
&& (symbolic_operand (operands[1], SImode)
- || symbolic_operand (operands[1], SImode)))
+ || symbolic_operand (operands[2], SImode)))
debug_rtx (insn);
return "addl3 %1,%2,%0";
@@ -1955,12 +2035,14 @@ vax_expand_addsub_di_operands (rtx * operands, enum rtx_code code)
}
else
{
- /* If are adding the same value together, that's really a multiply by 2,
- and that's just a left shift of 1. */
+ /* If we are adding a value to itself, that's really a multiply by 2,
+ and that's just a left shift by 1. If subtracting, it's just 0. */
if (rtx_equal_p (operands[1], operands[2]))
{
- gcc_assert (code != MINUS);
- emit_insn (gen_ashldi3 (operands[0], operands[1], const1_rtx));
+ if (code == PLUS)
+ emit_insn (gen_ashldi3 (operands[0], operands[1], const1_rtx));
+ else
+ emit_move_insn (operands[0], const0_rtx);
return;
}
@@ -1979,6 +2061,19 @@ vax_expand_addsub_di_operands (rtx * operands, enum rtx_code code)
else
operands[2] = fixup_mathdi_operand (operands[2], DImode);
+ /* If we are adding or subtracting 0, then this is a move. */
+ if (code == PLUS && operands[1] == const0_rtx)
+ {
+ temp = operands[2];
+ operands[2] = operands[1];
+ operands[1] = temp;
+ }
+ if (operands[2] == const0_rtx)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ return;
+ }
+
/* If we are subtracting not from ourselves [d = a - b], and because the
carry ops are two operand only, we would need to do a move prior to
the subtract. And if d == b, we would need a temp otherwise
@@ -1995,7 +2090,6 @@ vax_expand_addsub_di_operands (rtx * operands, enum rtx_code code)
{
if (code == MINUS && CONSTANT_P (operands[1]))
{
- temp = gen_reg_rtx (DImode);
emit_insn (gen_sbcdi3 (operands[0], const0_rtx, operands[2]));
code = PLUS;
gen_insn = gen_adcdi3;
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index c1d0171..8b2b2d1 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -120,12 +120,12 @@ along with GCC; see the file COPYING3. If not see
from 0 to just below FIRST_PSEUDO_REGISTER.
All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers. */
-#define FIRST_PSEUDO_REGISTER 16
+#define FIRST_PSEUDO_REGISTER 17
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
On the VAX, these are the AP, FP, SP and PC. */
-#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -133,7 +133,7 @@ along with GCC; see the file COPYING3. If not see
The latter must include the registers where values are returned
and the register where structure-value addresses are passed.
Aside from that, you can include as many other registers as you like. */
-#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
@@ -442,6 +442,11 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
of a shift count. */
/* #define SHIFT_COUNT_TRUNCATED */
+/* We need to reject symbol references in PIC code except for address
+ loads, handled elsewhere. */
+#define LEGITIMATE_PIC_OPERAND_P(x) \
+ vax_acceptable_pic_operand_p ((x), false, false)
+
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
@@ -460,24 +465,11 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define BRANCH_COST(speed_p, predictable_p) 0
-/* Tell final.c how to eliminate redundant test instructions. */
-
-/* Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). No extra ones are needed for the VAX. */
-
-/* Store in cc_status the expressions
- that the condition codes will describe
- after execution of an instruction whose pattern is EXP.
- Do not alter them if the instruction would not alter the cc's. */
-
-#define NOTICE_UPDATE_CC(EXP, INSN) \
- vax_notice_update_cc ((EXP), (INSN))
-
-#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
- { if (cc_status.flags & CC_NO_OVERFLOW) \
- return NO_OV; \
- return NORMAL; \
- }
+/* Given a comparison code (NE, EQ, etc.) and the operands of a COMPARE,
+ return the mode to be used for the comparison. As we have the same
+ interpretation of condition codes across all the instructions we just
+ return the narrowest mode suitable for the comparison code requested. */
+#define SELECT_CC_MODE(OP, X, Y) vax_select_cc_mode (OP, X, Y)
/* Control the assembler format that we output. */
@@ -512,7 +504,8 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define REGISTER_PREFIX ""
#define REGISTER_NAMES \
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", }
+ "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", \
+ "psl" }
/* This is BSD, so it wants DBX format. */
@@ -678,3 +671,7 @@ VAX operand formatting codes:
by the proper FDE definition. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, PC_REGNUM)
+/* Upon failure to find the bit the FFS hardware instruction returns
+ the position of the bit immediately following the field specified. */
+#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
+ ((VALUE) = GET_MODE_BITSIZE (MODE), 2)
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index 4897ce4..ecde0cd 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -22,9 +22,6 @@
;;- the first one in the file is chosen.
;;-
;;- See file "rtl.def" for documentation on define_insn, match_*, et al.
-;;-
-;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
-;;- updates for most instructions.
;; UNSPEC_VOLATILE usage:
@@ -40,6 +37,8 @@
(VAX_FP_REGNUM 13) ; Register 13 contains the frame pointer
(VAX_SP_REGNUM 14) ; Register 14 contains the stack pointer
(VAX_PC_REGNUM 15) ; Register 15 contains the program counter
+ (VAX_PSL_REGNUM 16) ; Register 16 contains the processor status
+ ; and condition codes in particular
]
)
@@ -57,34 +56,96 @@
;; Some output patterns want integer immediates with a prefix...
(define_mode_attr iprefx [(QI "B") (HI "H") (SI "N")])
+(define_mode_iterator VAXcc [CC CCN CCNZ CCZ])
+(define_mode_iterator VAXccnz [CCN CCNZ CCZ])
+(define_mode_attr cc [(CC "cc") (CCN "ccn") (CCNZ "ccnz") (CCZ "ccz")])
+
+(define_code_iterator any_extract [sign_extract zero_extract])
+
;;
(include "constraints.md")
(include "predicates.md")
-(define_insn "*cmp<mode>"
- [(set (cc0)
- (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT,nrmT")
- (match_operand:VAXint 1 "general_operand" "I,nrmT")))]
+;; Make instructions that set the N, N+Z, and Z condition codes respectively.
+(define_subst "subst_<cc>"
+ [(set (match_operand 0 "")
+ (match_operand 1 ""))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ ""
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz (match_dup 1)
+ (const_int 0)))
+ (set (match_dup 0)
+ (match_dup 1))])
+
+(define_subst "subst_f<cc>"
+ [(set (match_operand 0 "")
+ (match_operand 1 ""))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
""
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz (match_dup 1)
+ (const_double_zero)))
+ (set (match_dup 0)
+ (match_dup 1))])
+
+;; Select all from the attributes below that apply to a given insn that
+;; has a clobber on CC for the comparison elimination pass to use it in
+;; place of a subsequent comparison instruction matching the mode used
+;; by a comparison operator in branch.
+;;
+;; For example a branch doing `eq' in SImode will use `*cmpsi_ccz', so
+;; to eliminate it a `*movsi_ccz', etc. pattern will be required via the
+;; `ccz' substitution. Analogously for the other CC modes.
+;;
+;; The general `cc' mode, which sets all of the C, N, V and Z condition
+;; codes, has to be handled specially as it makes no sense for the usual
+;; comparison against zero, so no substitution has been defined for it.
+(define_subst_attr "ccn" "subst_ccn" "" "_ccn")
+(define_subst_attr "ccnz" "subst_ccnz" "" "_ccnz")
+(define_subst_attr "ccz" "subst_ccz" "" "_ccz")
+(define_subst_attr "fccn" "subst_fccn" "" "_ccn")
+(define_subst_attr "fccnz" "subst_fccnz" "" "_ccnz")
+(define_subst_attr "fccz" "subst_fccz" "" "_ccz")
+
+(define_insn "*cmp<VAXint:mode>_<VAXcc:mode>"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc (match_operand:VAXint 0 "general_operand" "nrmT,nrmT")
+ (match_operand:VAXint 1 "general_operand" "I,nrmT")))]
+ "reload_completed"
"@
tst<VAXint:isfx> %0
cmp<VAXint:isfx> %0,%1")
-(define_insn "*cmp<mode>"
- [(set (cc0)
- (compare (match_operand:VAXfp 0 "general_operand" "gF,gF")
- (match_operand:VAXfp 1 "general_operand" "G,gF")))]
- ""
+;; We don't have a CMPQ instruction, but we can set the N and Z condition
+;; codes with MOVQ, and also this comparison can be folded into a preceding
+;; operation by the post-reload comparison elimination pass.
+(define_insn "*cmpdi_<VAXccnz:mode>"
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz (match_operand:DI 0 "general_operand" "r,nmT")
+ (match_operand:DI 1 "const_zero_operand" "I,I")))
+ (clobber (match_scratch:DI 2 "=X,r"))]
+ "reload_completed"
+ "@
+ movq %0,%0
+ movq %0,%2")
+
+(define_insn "*cmp<VAXfp:mode>_<VAXccnz:mode>"
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz (match_operand:VAXfp 0 "general_operand" "gF,gF")
+ (match_operand:VAXfp 1 "general_operand" "G,gF")))]
+ "reload_completed"
"@
tst<VAXfp:fsfx> %0
cmp<VAXfp:fsfx> %0,%1")
-(define_insn "*bit<mode>"
- [(set (cc0)
- (compare (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
- (match_operand:VAXint 1 "general_operand" "nrmT"))
- (const_int 0)))]
- ""
+(define_insn "*bit<VAXint:mode>_<VAXccnz:mode>"
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz
+ (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
+ (match_operand:VAXint 1 "general_operand" "nrmT"))
+ (const_int 0)))]
+ "reload_completed"
"bit<VAXint:isfx> %0,%1")
;; The VAX has no sCOND insns. It does have add/subtract with carry
@@ -95,25 +156,76 @@
;; and has been deleted.
-(define_insn "mov<mode>"
+(define_insn_and_split "mov<mode>"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(match_operand:VAXfp 1 "general_operand" "G,gF"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*mov<mode><fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
+ (match_operand:VAXfp 1 "general_operand" "G,gF"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
clr<VAXfp:fsfx> %0
mov<VAXfp:fsfx> %1,%0")
;; Some VAXen don't support this instruction.
-;;(define_insn "movti"
-;; [(set (match_operand:TI 0 "general_operand" "=g")
+;;(define_insn_and_split "movti"
+;; [(set (match_operand:TI 0 "nonimmediate_operand" "=g")
;; (match_operand:TI 1 "general_operand" "g"))]
;; ""
-;; "movh %1,%0")
-
-(define_insn "movdi"
+;; "#"
+;; "reload_completed"
+;; [(parallel
+;; [(set (match_dup 0)
+;; (match_dup 1))
+;; (clobber (reg:CC VAX_PSL_REGNUM))])]
+;; "")
+;;
+;;(define_insn "*movti<ccn><ccnz><ccz>"
+;; [(set (match_operand:TI 0 "nonimmediate_operand" "=g")
+;; (match_operand:TI 1 "general_operand" "g"))
+;; (clobber (reg:CC VAX_PSL_REGNUM))]
+;; "reload_completed"
+;; "movo %1,%0")
+
+(define_insn_and_split "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(match_operand:DI 1 "general_operand" "g"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+;; In some cases `vax_output_int_move' splits a `DImode' move into a pair
+;; of `SImode' moves, in which case the flags aren't usefully set. Have
+;; separate patterns then, for the cases where the move may and may not be
+;; split each. We use the outer condition only so in some cases we will
+;; fail to notice the move does not actually get split, but this is OK.
+(define_insn "*movdi_maybe_split"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (match_operand:DI 1 "general_operand" "g"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed && vax_maybe_split_dimode_move (operands)"
+ "* return vax_output_int_move (insn, operands, DImode);")
+
+(define_insn "*movdi_unsplit<ccn><ccnz><ccz>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (match_operand:DI 1 "general_operand" "g"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed && !vax_maybe_split_dimode_move (operands)"
"* return vax_output_int_move (insn, operands, DImode);")
;; The VAX move instructions have space-time tradeoffs. On a MicroVAX
@@ -155,22 +267,61 @@
#endif
}")
-(define_insn "movsi_2"
+(define_insn_and_split "movsi_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(match_operand:SI 1 "nonsymbolic_operand" "nrmT"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movsi_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (match_operand:SI 1 "nonsymbolic_operand" "nrmT"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"* return vax_output_int_move (insn, operands, SImode);")
-(define_insn "mov<mode>"
+(define_insn_and_split "mov<mode>"
[(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g")
(match_operand:VAXintQH 1 "general_operand" "g"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*mov<mode><ccn><ccnz><ccz>"
+ [(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g")
+ (match_operand:VAXintQH 1 "general_operand" "g"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"* return vax_output_int_move (insn, operands, <MODE>mode);")
-(define_insn "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+g"))
+(define_insn_and_split "movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
(match_operand:HI 1 "general_operand" "g"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (strict_low_part (match_dup 0))
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movstricthi<ccn><ccnz><ccz>"
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
+ (match_operand:HI 1 "general_operand" "g"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (CONST_INT_P (operands[1]))
@@ -188,10 +339,23 @@
return \"movw %1,%0\";
}")
-(define_insn "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "register_operand" "+g"))
+(define_insn_and_split "movstrictqi"
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
(match_operand:QI 1 "general_operand" "g"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (strict_low_part (match_dup 0))
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movstrictqi<ccn><ccnz><ccz>"
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
+ (match_operand:QI 1 "general_operand" "g"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (CONST_INT_P (operands[1]))
@@ -206,16 +370,28 @@
}")
;; This is here to accept 4 arguments and pass the first 3 along
-;; to the cpymemhi1 pattern that really does the work.
+;; to the movmemhi1 pattern that really does the work.
(define_expand "cpymemhi"
- [(set (match_operand:BLK 0 "general_operand" "=g")
- (match_operand:BLK 1 "general_operand" "g"))
- (use (match_operand:HI 2 "general_operand" "g"))
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand:HI 2 "general_operand" ""))
(match_operand 3 "" "")]
""
"
{
- emit_insn (gen_cpymemhi1 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_movmemhi1 (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_expand "movmemhi"
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand:HI 2 "general_operand" ""))
+ (match_operand 3 "" "")]
+ ""
+ "
+{
+ emit_insn (gen_movmemhi1 (operands[0], operands[1], operands[2]));
DONE;
}")
@@ -224,7 +400,7 @@
;; that anything generated as this insn will be recognized as one
;; and that it won't successfully combine with anything.
-(define_insn "cpymemhi1"
+(define_insn_and_split "movmemhi1"
[(set (match_operand:BLK 0 "memory_operand" "=o")
(match_operand:BLK 1 "memory_operand" "o"))
(use (match_operand:HI 2 "general_operand" "g"))
@@ -235,90 +411,286 @@
(clobber (reg:SI 4))
(clobber (reg:SI 5))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (use (match_dup 2))
+ (clobber (reg:SI 0))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:SI 3))
+ (clobber (reg:SI 4))
+ (clobber (reg:SI 5))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movmemhi1"
+ [(set (match_operand:BLK 0 "memory_operand" "=o")
+ (match_operand:BLK 1 "memory_operand" "o"))
+ (use (match_operand:HI 2 "general_operand" "g"))
+ (clobber (reg:SI 0))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:SI 3))
+ (clobber (reg:SI 4))
+ (clobber (reg:SI 5))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"movc3 %2,%1,%0")
;; Extension and truncation insns.
-(define_insn "truncsiqi2"
+(define_insn_and_split "truncsiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=g")
(truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (truncate:QI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*truncsiqi2<ccn><ccnz><ccz>"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
+ (truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtlb %1,%0")
-(define_insn "truncsihi2"
+(define_insn_and_split "truncsihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (truncate:HI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*truncsihi2<ccn><ccnz><ccz>"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
+ (truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtlw %1,%0")
-(define_insn "trunchiqi2"
+(define_insn_and_split "trunchiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=g")
(truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (truncate:QI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*trunchiqi2<ccn><ccnz><ccz>"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
+ (truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtwb %1,%0")
-(define_insn "extendhisi2"
+(define_insn_and_split "extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (sign_extend:SI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extendhisi2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtwl %1,%0")
-(define_insn "extendqihi2"
+(define_insn_and_split "extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (sign_extend:HI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extendqihi2<ccn><ccnz><ccz>"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtbw %1,%0")
-(define_insn "extendqisi2"
+(define_insn_and_split "extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (sign_extend:SI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extendqisi2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtbl %1,%0")
-(define_insn "extendsfdf2"
+(define_insn_and_split "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "=g")
(float_extend:DF (match_operand:SF 1 "general_operand" "gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (float_extend:DF (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extendsfdf2<fccn><fccnz><fccz>"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=g")
+ (float_extend:DF (match_operand:SF 1 "general_operand" "gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvtf%# %1,%0")
-(define_insn "truncdfsf2"
+(define_insn_and_split "truncdfsf2"
[(set (match_operand:SF 0 "nonimmediate_operand" "=g")
(float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (float_truncate:SF (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*truncdfsf2<fccn><fccnz><fccz>"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=g")
+ (float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvt%#f %1,%0")
-(define_insn "zero_extendhisi2"
+(define_insn_and_split "zero_extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (zero_extend:SI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*zero_extendhisi2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"movzwl %1,%0")
-(define_insn "zero_extendqihi2"
+(define_insn_and_split "zero_extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (zero_extend:HI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*zero_extendqihi2<ccn><ccnz><ccz>"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"movzbw %1,%0")
-(define_insn "zero_extendqisi2"
+(define_insn_and_split "zero_extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (zero_extend:SI (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*zero_extendqisi2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"movzbl %1,%0")
;; Fix-to-float conversion insns.
-(define_insn "float<VAXint:mode><VAXfp:mode>2"
+(define_insn_and_split "float<VAXint:mode><VAXfp:mode>2"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
(float:VAXfp (match_operand:VAXint 1 "nonimmediate_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (float:VAXfp (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*float<VAXint:mode><VAXfp:mode>2<fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
+ (float:VAXfp (match_operand:VAXint 1 "nonimmediate_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvt<VAXint:isfx><VAXfp:fsfx> %1,%0")
;; Float-to-fix conversion insns.
-(define_insn "fix_trunc<VAXfp:mode><VAXint:mode>2"
+(define_insn_and_split "fix_trunc<VAXfp:mode><VAXint:mode>2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(fix:VAXint (match_operand:VAXfp 1 "general_operand" "gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (fix:VAXint (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*fix_trunc<VAXfp:mode><VAXint:mode>2<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+ (fix:VAXint (match_operand:VAXfp 1 "general_operand" "gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"cvt<VAXfp:fsfx><VAXint:isfx> %1,%0")
(define_expand "fixuns_trunc<VAXfp:mode><VAXint:mode>2"
@@ -328,49 +700,51 @@
;;- All kinds of add instructions.
-(define_insn "add<mode>3"
+(define_insn_and_split "add<mode>3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
(plus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
(match_operand:VAXfp 2 "general_operand" "gF,0,gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:VAXfp (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*add<mode>3<fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
+ (plus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
+ (match_operand:VAXfp 2 "general_operand" "gF,0,gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
add<VAXfp:fsfx>2 %2,%0
add<VAXfp:fsfx>2 %1,%0
add<VAXfp:fsfx>3 %1,%2,%0")
-(define_insn "pushlclsymreg"
- [(set (match_operand:SI 0 "push_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "local_symbolic_operand" "i")))]
- "flag_pic"
- "pushab %a2[%1]")
-
-(define_insn "pushextsymreg"
- [(set (match_operand:SI 0 "push_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "external_symbolic_operand" "i")))]
- "flag_pic"
- "pushab %a2[%1]")
-
-(define_insn "movlclsymreg"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "local_symbolic_operand" "i")))]
- "flag_pic"
- "movab %a2[%1],%0")
-
-(define_insn "movextsymreg"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "external_symbolic_operand" "i")))]
- "flag_pic"
- "movab %a2[%1],%0")
-
-(define_insn "add<mode>3"
+(define_insn_and_split "add<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*add<mode>3<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+ (plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"* return vax_output_int_add (insn, operands, <MODE>mode);")
(define_expand "adddi3"
@@ -380,37 +754,109 @@
"!reload_in_progress"
"vax_expand_addsub_di_operands (operands, PLUS); DONE;")
-(define_insn "adcdi3"
+(define_insn_and_split "adcdi3"
[(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr")
(plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
(match_operand:DI 2 "general_addsub_di_operand" "nRr")))]
"TARGET_QMATH"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*adcdi3<ccn>"
+ [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr")
+ (plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
+ (match_operand:DI 2 "general_addsub_di_operand" "nRr")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "TARGET_QMATH && reload_completed"
"* return vax_output_int_add (insn, operands, DImode);")
;; The add-with-carry (adwc) instruction only accepts two operands.
-(define_insn "adddi3_old"
+(define_insn_and_split "adddi3_old"
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>")
(plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
(match_operand:DI 2 "general_operand" "Fsro,Fs")))]
"!TARGET_QMATH"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*adddi3_old<ccn>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>")
+ (plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
+ (match_operand:DI 2 "general_operand" "Fsro,Fs")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_QMATH && reload_completed"
"* return vax_output_int_add (insn, operands, DImode);")
;;- All kinds of subtract instructions.
-(define_insn "sub<mode>3"
+(define_insn_and_split "sub<mode>3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(minus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
(match_operand:VAXfp 2 "general_operand" "gF,gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (minus:VAXfp (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*sub<mode>3<fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
+ (minus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
+ (match_operand:VAXfp 2 "general_operand" "gF,gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
sub<VAXfp:fsfx>2 %2,%0
sub<VAXfp:fsfx>3 %2,%1,%0")
-(define_insn "sub<mode>3"
+(define_insn_and_split "sub<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (minus:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*sub<mode>3<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+ (minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
+ "@
+ sub<VAXint:isfx>2 %2,%0
+ sub<VAXint:isfx>3 %2,%1,%0")
+
+(define_insn "*sub<mode>3_cc"
+ [(set (reg:CC VAX_PSL_REGNUM)
+ (compare:CC (match_operand:VAXint 1 "general_operand" "0,nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
+ (set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+ (minus:VAXint (match_dup 1)
+ (match_dup 2)))]
+ "reload_completed"
"@
sub<VAXint:isfx>2 %2,%0
sub<VAXint:isfx>3 %2,%1,%0")
@@ -422,74 +868,192 @@
"!reload_in_progress"
"vax_expand_addsub_di_operands (operands, MINUS); DONE;")
-(define_insn "sbcdi3"
+(define_insn_and_split "sbcdi3"
[(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
(match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))]
"TARGET_QMATH"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (minus:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*sbcdi3<ccn>"
+ [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
+ (minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
+ (match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "TARGET_QMATH && reload_completed"
"* return vax_output_int_subtract (insn, operands, DImode);")
;; The subtract-with-carry (sbwc) instruction only takes two operands.
-(define_insn "subdi3_old"
+(define_insn_and_split "subdi3_old"
[(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>")
(minus:DI (match_operand:DI 1 "general_operand" "0,or>")
(match_operand:DI 2 "general_operand" "Fsor,Fs")))]
"!TARGET_QMATH"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (minus:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*subdi3_old<ccn>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>")
+ (minus:DI (match_operand:DI 1 "general_operand" "0,or>")
+ (match_operand:DI 2 "general_operand" "Fsor,Fs")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_QMATH && reload_completed"
"* return vax_output_int_subtract (insn, operands, DImode);")
;;- Multiply instructions.
-(define_insn "mul<mode>3"
+(define_insn_and_split "mul<mode>3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
(mult:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
(match_operand:VAXfp 2 "general_operand" "gF,0,gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (mult:VAXfp (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*mul<mode>3<fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
+ (mult:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
+ (match_operand:VAXfp 2 "general_operand" "gF,0,gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
mul<VAXfp:fsfx>2 %2,%0
mul<VAXfp:fsfx>2 %1,%0
mul<VAXfp:fsfx>3 %1,%2,%0")
-(define_insn "mul<mode>3"
+(define_insn_and_split "mul<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (mult:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*mul<mode>3<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
+ (mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
mul<VAXint:isfx>2 %2,%0
mul<VAXint:isfx>2 %1,%0
mul<VAXint:isfx>3 %1,%2,%0")
-(define_insn "mulsidi3"
+(define_insn_and_split "mulsidi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
- (mult:DI (sign_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "nrmT"))
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "nrmT"))))]
- ""
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (mult:DI
+ (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2))))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*mulsidi3<ccn><ccnz><ccz>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT"))))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"emul %1,%2,$0,%0")
-(define_insn ""
+(define_insn_and_split "*maddsidi4"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI
- (mult:DI (sign_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "nrmT"))
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "nrmT")))
- (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "g"))))]
- ""
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
+ (sign_extend:DI (match_operand:SI 3 "general_operand" "g"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:DI
+ (mult:DI
+ (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2)))
+ (sign_extend:DI (match_dup 3))))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*maddsidi4_2<ccn><ccnz><ccz>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (plus:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
+ (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "g"))))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"emul %1,%2,%3,%0")
;; 'F' constraint means type CONST_DOUBLE
-(define_insn ""
+(define_insn_and_split "*maddsidi4_const"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (plus:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
+ (match_operand:DI 3 "immediate_operand" "F")))]
+ "GET_CODE (operands[3]) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:DI
+ (mult:DI
+ (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2)))
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*maddsidi4_const_2<ccn><ccnz><ccz>"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI
- (mult:DI (sign_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "nrmT"))
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "nrmT")))
- (match_operand:DI 3 "immediate_operand" "F")))]
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
+ (match_operand:DI 3 "immediate_operand" "F")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
"GET_CODE (operands[3]) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)"
+ && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)
+ && reload_completed"
"*
{
if (CONST_DOUBLE_HIGH (operands[3]))
@@ -499,35 +1063,86 @@
;;- Divide instructions.
-(define_insn "div<mode>3"
+(define_insn_and_split "div<mode>3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(div:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
(match_operand:VAXfp 2 "general_operand" "gF,gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (div:VAXfp (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*div<mode>3<fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
+ (div:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
+ (match_operand:VAXfp 2 "general_operand" "gF,gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
div<VAXfp:fsfx>2 %2,%0
div<VAXfp:fsfx>3 %2,%1,%0")
-(define_insn "div<mode>3"
+(define_insn_and_split "div<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (div:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*div<mode>3<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+ (div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
div<VAXint:isfx>2 %2,%0
div<VAXint:isfx>3 %2,%1,%0")
-;This is left out because it is very slow;
-;we are better off programming around the "lack" of this insn.
-;(define_insn "divmoddisi4"
-; [(set (match_operand:SI 0 "general_operand" "=g")
-; (div:SI (match_operand:DI 1 "general_operand" "g")
-; (match_operand:SI 2 "general_operand" "g")))
-; (set (match_operand:SI 3 "general_operand" "=g")
-; (mod:SI (match_operand:DI 1 "general_operand" "g")
-; (match_operand:SI 2 "general_operand" "g")))]
-; ""
-; "ediv %2,%1,%0,%3")
+;; This is left out because it is very slow;
+;; we are better off programming around the "lack" of this insn.
+;;(define_insn_and_split "divmoddisi4"
+;; [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;; (div:SI (match_operand:DI 1 "general_operand" "g")
+;; (match_operand:SI 2 "general_operand" "g")))
+;; (set (match_operand:SI 3 "nonimmediate_operand" "=g")
+;; (mod:SI (match_dup 1)
+;; (match_dup 2)))]
+;; ""
+;; "#"
+;; "reload_completed"
+;; [(parallel
+;; [(set (match_dup 0)
+;; (div:SI (match_dup 1)
+;; (match_dup 2)))
+;; (set (match_dup 3)
+;; (mod:SI (match_dup 1)
+;; (match_dup 2)))
+;; (clobber (reg:CC VAX_PSL_REGNUM))])]
+;; "")
+;;
+;;(define_insn "*divmoddisi4<ccn><ccnz><ccz>"
+;; [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;; (div:SI (match_operand:DI 1 "general_operand" "g")
+;; (match_operand:SI 2 "general_operand" "g")))
+;; (set (match_operand:SI 3 "nonimmediate_operand" "=g")
+;; (mod:SI (match_dup 1)
+;; (match_dup 2)))
+;; (clobber (reg:CC VAX_PSL_REGNUM))]
+;; "reload_completed"
+;; "ediv %2,%1,%0,%3")
;; Bit-and on the VAX is done with a clear-bits insn.
(define_expand "and<mode>3"
@@ -553,11 +1168,29 @@
operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
}")
-(define_insn "*and<mode>"
+(define_insn_and_split "*and<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
- (and:VAXint (not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
+ (and:VAXint (not:VAXint
+ (match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
(match_operand:VAXint 2 "general_operand" "0,nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (and:VAXint (not:VAXint
+ (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*and<mode>3_2<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+ (and:VAXint (not:VAXint
+ (match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
+ (match_operand:VAXint 2 "general_operand" "0,nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
bic<VAXint:isfx>2 %1,%0
bic<VAXint:isfx>3 %1,%2,%0")
@@ -567,23 +1200,80 @@
;; longer a problem. However, having these patterns allows optimization
;; opportunities in combine.c.
-(define_insn "*and<mode>_const_int"
+(define_insn_and_split "*and<mode>3_const_int"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "const_int_operand" "n,n")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (and:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*and<mode>3_2_const_int<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+ (and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
+ (match_operand:VAXint 2 "const_int_operand" "n,n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
bic<VAXint:isfx>2 %<VAXint:iprefx>2,%0
bic<VAXint:isfx>3 %<VAXint:iprefx>2,%1,%0")
+;; We have no direct AND operation and consequently the RTL sequence
+;; the "and<mode>3" pattern produces does not match the instruction
+;; the "*bit<mode>" pattern does for the purpose of the compare
+;; elimination pass. Try to get rid of the extra operation by hand
+;; and where the sequence is used to set the condition codes only
+;; convert MNEG/BIC => BIT.
+(define_peephole2
+ [(parallel
+ [(set (match_operand:VAXint 0 "register_operand")
+ (not:VAXint (match_operand:VAXint 1 "general_operand")))
+ (clobber (reg:CC VAX_PSL_REGNUM))])
+ (parallel
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz
+ (and:VAXint (not:VAXint (match_dup 0))
+ (match_operand:VAXint 3 "general_operand"))
+ (const_int 0)))
+ (set (match_operand:VAXint 2 "register_operand")
+ (and:VAXint (not:VAXint (match_dup 0))
+ (match_dup 3)))])]
+ "peep2_reg_dead_p (2, operands[0]) && peep2_reg_dead_p (2, operands[2])"
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz
+ (and:VAXint (match_dup 1)
+ (match_dup 3))
+ (const_int 0)))]
+ "")
;;- Bit set instructions.
-(define_insn "ior<mode>3"
+(define_insn_and_split "ior<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ior:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ior<mode>3<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
+ (ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
bis<VAXint:isfx>2 %2,%0
bis<VAXint:isfx>2 %1,%0
@@ -591,35 +1281,97 @@
;;- xor instructions.
-(define_insn "xor<mode>3"
+(define_insn_and_split "xor<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (xor:VAXint (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*xor<mode>3<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
+ (xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"@
xor<VAXint:isfx>2 %2,%0
xor<VAXint:isfx>2 %1,%0
xor<VAXint:isfx>3 %2,%1,%0")
-
-(define_insn "neg<mode>2"
+(define_insn_and_split "neg<mode>2"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
(neg:VAXfp (match_operand:VAXfp 1 "general_operand" "gF")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (neg:VAXfp (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*neg<mode>2<fccn><fccnz><fccz>"
+ [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
+ (neg:VAXfp (match_operand:VAXfp 1 "general_operand" "gF")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"mneg<VAXfp:fsfx> %1,%0")
-(define_insn "neg<mode>2"
+(define_insn_and_split "neg<mode>2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (neg:VAXint (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*neg<mode>2<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+ (neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"mneg<VAXint:isfx> %1,%0")
-(define_insn "one_cmpl<mode>2"
+(define_insn "*neg<mode>2_cc"
+ [(set (reg:CC VAX_PSL_REGNUM)
+ (compare:CC (const_int 0)
+ (neg:VAXint
+ (match_operand:VAXint 1 "general_operand" "0,nrmT"))))
+ (set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+ (neg:VAXint (match_dup 1)))]
+ "reload_completed"
+ "mneg<VAXint:isfx> %1,%0")
+
+(define_insn_and_split "one_cmpl<mode>2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))]
""
- "mcom<VAXint:isfx> %1,%0")
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (not:VAXint (match_dup 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+(define_insn "*one_cmpl<mode>2<ccn><ccnz><ccz>"
+ [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+ (not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
+ "mcom<VAXint:isfx> %1,%0")
;; Arithmetic right shift on the VAX works by negating the shift count,
;; then emitting a right shift with the shift count negated. This means
@@ -637,25 +1389,70 @@
operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
}")
-(define_insn ""
+(define_insn_and_split "*ashlnegsi3_const_int"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ashiftrt:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ashlnegsi3_const_int_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (match_operand:QI 2 "const_int_operand" "n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"ashl $%n2,%1,%0")
-(define_insn ""
+(define_insn_and_split "*ashlnegsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ashiftrt:SI (match_dup 1)
+ (neg:QI (match_dup 2))))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ashlnegsi3_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (neg:QI (match_operand:QI 2 "general_operand" "g"))))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"ashl %2,%1,%0")
-(define_insn "ashlsi3"
+(define_insn_and_split "ashlsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "general_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ashift:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ashlsi3<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (match_operand:QI 2 "general_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1]))
@@ -692,18 +1489,48 @@
operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
}")
-(define_insn "ashldi3"
+(define_insn_and_split "ashldi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashift:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:QI 2 "general_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ashift:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ashldi3<ccn><ccnz><ccz>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (ashift:DI (match_operand:DI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"ashq %2,%D1,%0")
-(define_insn ""
+(define_insn_and_split "*ashlnegdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ashiftrt:DI (match_dup 1)
+ (neg:QI (match_dup 2))))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*ashlnegdi3_2<ccn><ccnz><ccz>"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+ (ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
+ (neg:QI (match_operand:QI 2 "general_operand" "g"))))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"ashq %2,%D1,%0")
;; We used to have expand_shift handle logical right shifts by using extzv,
@@ -738,146 +1565,300 @@
operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
}")
-(define_insn "rotlsi3"
+(define_insn_and_split "rotlsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotate:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "general_operand" "g")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (rotate:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*rotlsi3<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (rotate:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (match_operand:QI 2 "general_operand" "g")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"rotl %2,%1,%0")
-(define_insn ""
+(define_insn_and_split "*rotrsi3_const_int"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (rotatert:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*rotrsi3_const_int_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (match_operand:QI 2 "const_int_operand" "n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"rotl %R2,%1,%0")
-(define_insn ""
+(define_insn_and_split "*rotrnegsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (rotatert:SI (match_dup 1)
+ (neg:QI (match_dup 2))))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*rotrnegsi3_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (neg:QI (match_operand:QI 2 "general_operand" "g"))))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"rotl %2,%1,%0")
-;This insn is probably slower than a multiply and an add.
-;(define_insn ""
-; [(set (match_operand:SI 0 "general_operand" "=g")
-; (mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g")
-; (match_operand:SI 2 "general_operand" "g"))
-; (match_operand:SI 3 "general_operand" "g")))]
-; ""
-; "index %1,$0x80000000,$0x7fffffff,%3,%2,%0")
+;; This insn is probably slower than a multiply and an add.
+;;(define_insn_and_split "*amulsi4"
+;; [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;; (mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g")
+;; (match_operand:SI 2 "general_operand" "g"))
+;; (match_operand:SI 3 "general_operand" "g")))]
+;; ""
+;; "#"
+;; "reload_completed"
+;; [(parallel
+;; [(set (match_dup 0)
+;; (mult:SI (plus:SI (match_dup 1)
+;; (match_dup 2))
+;; (match_dup 3)))
+;; (clobber (reg:CC VAX_PSL_REGNUM))])]
+;; "")
+;;
+;;(define_insn "*amulsi4_2<ccn><ccnz><ccz>"
+;; [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;; (mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g")
+;; (match_operand:SI 2 "general_operand" "g"))
+;; (match_operand:SI 3 "general_operand" "g")))
+;; (clobber (reg:CC VAX_PSL_REGNUM))]
+;; "reload_completed"
+;; "index %1,$0x80000000,$0x7fffffff,%3,%2,%0")
;; Special cases of bit-field insns which we should
;; recognize in preference to the general case.
-;; These handle aligned 8-bit and 16-bit fields,
-;; which can usually be done with move instructions.
+;; These handle aligned 8-bit and 16-bit fields
+;; that can be done with move or convert instructions.
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+ro")
+(define_insn_and_split "*insv_aligned"
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+ro")
(match_operand:QI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "general_operand" "g"))]
- "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
&& INTVAL (operands[2]) % INTVAL (operands[1]) == 0
&& (!MEM_P (operands[0])
- || ! mode_dependent_address_p (XEXP (operands[0], 0),
- MEM_ADDR_SPACE (operands[0])))"
+ || ((!flag_pic
+ || vax_acceptable_pic_operand_p (XEXP (operands[0], 0),
+ true, true))
+ && !mode_dependent_address_p (XEXP (operands[0], 0),
+ MEM_ADDR_SPACE (operands[0]))))
+ && (!(REG_P (operands[0])
+ || (SUBREG_P (operands[0]) && REG_P (SUBREG_REG (operands[0]))))
+ || INTVAL (operands[2]) == 0)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (zero_extract:SI (match_dup 0)
+ (match_dup 1)
+ (match_dup 2))
+ (match_dup 3))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*insv_aligned_2<ccn><ccnz><ccz>"
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+ro")
+ (match_operand:QI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "general_operand" "g"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+ && (!MEM_P (operands[0])
+ || ((!flag_pic
+ || vax_acceptable_pic_operand_p (XEXP (operands[0], 0),
+ true, true))
+ && !mode_dependent_address_p (XEXP (operands[0], 0),
+ MEM_ADDR_SPACE (operands[0]))))
+ && (!(REG_P (operands[0])
+ || (SUBREG_P (operands[0]) && REG_P (SUBREG_REG (operands[0]))))
+ || INTVAL (operands[2]) == 0)
+ && reload_completed"
"*
{
- if (REG_P (operands[0]))
- {
- if (INTVAL (operands[2]) != 0)
- return \"insv %3,%2,%1,%0\";
- }
- else
+ if (!REG_P (operands[0]))
operands[0]
= adjust_address (operands[0],
INTVAL (operands[1]) == 8 ? QImode : HImode,
INTVAL (operands[2]) / 8);
+ else
+ gcc_assert (INTVAL (operands[2]) == 0);
- CC_STATUS_INIT;
if (INTVAL (operands[1]) == 8)
return \"movb %3,%0\";
return \"movw %3,%0\";
}")
-(define_insn ""
+(define_insn_and_split "*extzv_aligned"
[(set (match_operand:SI 0 "nonimmediate_operand" "=&g")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "ro")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
(match_operand:QI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
"(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0
&& (!MEM_P (operands[1])
- || ! mode_dependent_address_p (XEXP (operands[1], 0),
- MEM_ADDR_SPACE (operands[1])))"
+ || ((!flag_pic
+ || vax_acceptable_pic_operand_p (XEXP (operands[1], 0),
+ true, true))
+ && !mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))))
+ && (!(REG_P (operands[1])
+ || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
+ || INTVAL (operands[3]) == 0)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extzv_aligned_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&g")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+ (match_operand:QI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (!MEM_P (operands[1])
+ || ((!flag_pic
+ || vax_acceptable_pic_operand_p (XEXP (operands[1], 0),
+ true, true))
+ && !mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))))
+ && (!(REG_P (operands[1])
+ || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
+ || INTVAL (operands[3]) == 0)
+ && reload_completed"
"*
{
- if (REG_P (operands[1]))
- {
- if (INTVAL (operands[3]) != 0)
- return \"extzv %3,%2,%1,%0\";
- }
- else
+ if (!REG_P (operands[1]))
operands[1]
= adjust_address (operands[1],
INTVAL (operands[2]) == 8 ? QImode : HImode,
INTVAL (operands[3]) / 8);
+ else
+ gcc_assert (INTVAL (operands[3]) == 0);
if (INTVAL (operands[2]) == 8)
return \"movzbl %1,%0\";
return \"movzwl %1,%0\";
}")
-(define_insn ""
+(define_insn_and_split "*extv_aligned"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (sign_extract:SI (match_operand:SI 1 "register_operand" "ro")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
(match_operand:QI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
"(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0
&& (!MEM_P (operands[1])
- || ! mode_dependent_address_p (XEXP (operands[1], 0),
- MEM_ADDR_SPACE (operands[1])))"
+ || ((!flag_pic
+ || vax_acceptable_pic_operand_p (XEXP (operands[1], 0),
+ true, true))
+ && !mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))))
+ && (!(REG_P (operands[1])
+ || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
+ || INTVAL (operands[3]) == 0)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (sign_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extv_aligned_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+ (match_operand:QI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (!MEM_P (operands[1])
+ || ((!flag_pic
+ || vax_acceptable_pic_operand_p (XEXP (operands[1], 0),
+ true, true))
+ && !mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))))
+ && (!(REG_P (operands[1])
+ || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
+ || INTVAL (operands[3]) == 0)
+ && reload_completed"
"*
{
- if (REG_P (operands[1]))
- {
- if (INTVAL (operands[3]) != 0)
- return \"extv %3,%2,%1,%0\";
- }
- else
+ if (!REG_P (operands[1]))
operands[1]
= adjust_address (operands[1],
INTVAL (operands[2]) == 8 ? QImode : HImode,
INTVAL (operands[3]) / 8);
+ else
+ gcc_assert (INTVAL (operands[3]) == 0);
if (INTVAL (operands[2]) == 8)
return \"cvtbl %1,%0\";
return \"cvtwl %1,%0\";
}")
-;; Register-only SImode cases of bit-field insns.
+;; Register and non-offsettable-memory SImode cases of bit-field insns.
-(define_insn ""
- [(set (cc0)
- (compare
- (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
+(define_insn "*cmpv_<mode>"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc
+ (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "ro")
(match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "nrmT"))
(match_operand:SI 3 "general_operand" "nrmT")))]
- ""
+ "reload_completed"
"cmpv %2,%1,%0,%3")
-(define_insn ""
- [(set (cc0)
- (compare
- (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+(define_insn "*cmpzv_<mode>"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "ro")
(match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "nrmT"))
(match_operand:SI 3 "general_operand" "nrmT")))]
- ""
+ "reload_completed"
"cmpzv %2,%1,%0,%3")
;; When the field position and size are constant and the destination
@@ -885,12 +1866,29 @@
;; by a bicl or sign extension. Because we might end up choosing ext[z]v
;; anyway, we can't allow immediate values for the primary source operand.
-(define_insn ""
+(define_insn_and_split "*extv_non_const"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (sign_extract:SI (match_operand:SI 1 "register_operand" "ro")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
(match_operand:QI 2 "general_operand" "g")
(match_operand:SI 3 "general_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (sign_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extv_non_const_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+ (match_operand:QI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2])
@@ -902,12 +1900,29 @@
return \"rotl %R3,%1,%0\;cvtwl %0,%0\";
}")
-(define_insn ""
+(define_insn_and_split "*extzv_non_const"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "ro")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
(match_operand:QI 2 "general_operand" "g")
(match_operand:SI 3 "general_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extzv_non_const_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+ (match_operand:QI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2])
@@ -928,32 +1943,57 @@
;; nonimmediate_operand is used to make sure that mode-ambiguous cases
;; don't match these (and therefore match the cases above instead).
-(define_insn ""
- [(set (cc0)
- (compare
+(define_insn "*cmpv_2_<mode>"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc
(sign_extract:SI (match_operand:QI 0 "memory_operand" "m")
(match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "nrmT"))
(match_operand:SI 3 "general_operand" "nrmT")))]
- ""
+ "reload_completed"
"cmpv %2,%1,%0,%3")
-(define_insn ""
- [(set (cc0)
- (compare
- (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rm")
+(define_insn "*cmpzv_2_<mode>"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
(match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "nrmT"))
(match_operand:SI 3 "general_operand" "nrmT")))]
- ""
+ "reload_completed"
"cmpzv %2,%1,%0,%3")
-(define_insn "extv"
+(define_expand "extv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:QI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ ""
+ "")
+
+(define_insn_and_split "*extv"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
(match_operand:QI 2 "general_operand" "g")
(match_operand:SI 3 "general_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (sign_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extv_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
+ (match_operand:QI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (!REG_P (operands[0]) || !CONST_INT_P (operands[2])
@@ -978,12 +2018,29 @@
""
"")
-(define_insn ""
+(define_insn_and_split "*extzv"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
(match_operand:QI 2 "general_operand" "g")
(match_operand:SI 3 "general_operand" "nrmT")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (zero_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*extzv_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
+ (match_operand:QI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "nrmT")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
if (!REG_P (operands[0]) || !CONST_INT_P (operands[2])
@@ -1023,6 +2080,28 @@
return \"rotl %R3,%1,%0\;bicl2 %M2,%0\";
}")
+;; Combine EXTV/CMPL and EXTZV/CMPL sequences where the output of
+;; extraction is used for the comparison only into CMPV and CMPZV
+;; respectively.
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (any_extract:SI (match_operand 1 "general_operand")
+ (match_operand:QI 2 "general_operand")
+ (match_operand:SI 3 "general_operand")))
+ (clobber (reg:CC VAX_PSL_REGNUM))])
+ (set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc (match_dup 0)
+ (match_operand:SI 4 "general_operand")))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc
+ (any_extract:SI (match_dup 1)
+ (match_dup 2)
+ (match_dup 3))
+ (match_dup 4)))]
+ "")
+
(define_expand "insv"
[(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" "")
@@ -1031,8 +2110,9 @@
""
"")
-(define_insn ""
- [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+g")
+;; This one actually doesn't change CC.
+(define_insn "*insv"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
(match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "nrmT"))
(match_operand:SI 3 "general_operand" "nrmT"))]
@@ -1062,8 +2142,9 @@
return \"insv %3,%2,%1,%0\";
}")
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+;; This one actually doesn't change CC.
+(define_insn "*insv_2"
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+ro")
(match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "nrmT"))
(match_operand:SI 3 "general_operand" "nrmT"))]
@@ -1080,49 +2161,89 @@
;; Conditional jumps
(define_expand "cbranch<mode>4"
- [(set (cc0)
- (compare (match_operand:VAXint 1 "nonimmediate_operand" "")
- (match_operand:VAXint 2 "general_operand" "")))
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:VAXint 1 "general_operand" "")
+ (match_operand:VAXint 2 "general_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_insn_and_split "*cbranch<VAXint:mode>4_<VAXcc:mode>"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "vax_<cc>_comparison_operator"
+ [(match_operand:VAXint 1 "general_operand" "nrmT")
+ (match_operand:VAXint 2 "general_operand" "nrmT")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (reg:VAXcc VAX_PSL_REGNUM)
+ (compare:VAXcc (match_dup 1) (match_dup 2)))
(set (pc)
- (if_then_else
- (match_operator 0 "ordered_comparison_operator" [(cc0)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "")
+ (if_then_else
+ (match_op_dup 0 [(reg:VAXcc VAX_PSL_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
(define_expand "cbranch<mode>4"
- [(set (cc0)
- (compare (match_operand:VAXfp 1 "general_operand" "")
- (match_operand:VAXfp 2 "general_operand" "")))
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:VAXfp 1 "general_operand" "")
+ (match_operand:VAXfp 2 "general_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_insn_and_split "*cbranch<VAXfp:mode>4_<VAXccnz:mode>"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "vax_<cc>_comparison_operator"
+ [(match_operand:VAXfp 1 "general_operand" "gF")
+ (match_operand:VAXfp 2 "general_operand" "gF")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (reg:VAXccnz VAX_PSL_REGNUM)
+ (compare:VAXccnz (match_dup 1) (match_dup 2)))
(set (pc)
- (if_then_else
- (match_operator 0 "ordered_comparison_operator" [(cc0)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "")
-
-(define_insn "*branch"
+ (if_then_else
+ (match_op_dup 0 [(reg:VAXccnz VAX_PSL_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
+
+(define_insn "*branch_<mode>"
[(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0)
+ (if_then_else (match_operator 0 "vax_<cc>_comparison_operator"
+ [(reg:VAXcc VAX_PSL_REGNUM)
(const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
- ""
- "j%c0 %l1")
+ "reload_completed"
+ "j%k0 %l1")
;; Recognize reversed jumps.
-(define_insn "*branch_reversed"
+(define_insn "*branch_<mode>_reversed"
[(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0)
+ (if_then_else (match_operator 0 "vax_<cc>_comparison_operator"
+ [(reg:VAXcc VAX_PSL_REGNUM)
(const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
- ""
- "j%C0 %l1") ; %C0 negates condition
+ "reload_completed"
+ "j%K0 %l1") ; %K0 negates condition
;; Recognize jbs, jlbs, jbc and jlbc instructions. Note that the operand
;; of jlbs and jlbc insns are SImode in the hardware. However, if it is
@@ -1191,7 +2312,7 @@
;; Normal sob insns.
-(define_insn ""
+(define_insn_and_split "*jsobgtr"
[(set (pc)
(if_then_else
(gt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1203,9 +2324,38 @@
(plus:SI (match_dup 0)
(const_int -1)))]
"!TARGET_UNIX_ASM"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (gt (plus:SI (match_dup 0)
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_dup 1))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jsobgtr_2"
+ [(set (pc)
+ (if_then_else
+ (gt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_UNIX_ASM && reload_completed"
"jsobgtr %0,%l1")
-(define_insn ""
+(define_insn_and_split "*jsobgeq"
[(set (pc)
(if_then_else
(ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1217,10 +2367,39 @@
(plus:SI (match_dup 0)
(const_int -1)))]
"!TARGET_UNIX_ASM"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_dup 0)
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_dup 1))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jsobgeq_2"
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_UNIX_ASM && reload_completed"
"jsobgeq %0,%l1")
;; Normal aob insns. Define a version for when operands[1] is a constant.
-(define_insn ""
+(define_insn_and_split "*jaoblss"
[(set (pc)
(if_then_else
(lt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1232,9 +2411,38 @@
(plus:SI (match_dup 0)
(const_int 1)))]
"!TARGET_UNIX_ASM"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (lt (plus:SI (match_dup 0)
+ (const_int 1))
+ (match_dup 1))
+ (label_ref (match_dup 2))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jaoblss_2"
+ [(set (pc)
+ (if_then_else
+ (lt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (const_int 1))
+ (match_operand:SI 1 "general_operand" "nrmT"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_UNIX_ASM && reload_completed"
"jaoblss %1,%0,%l2")
-(define_insn ""
+(define_insn_and_split "*jaoblss_const"
[(set (pc)
(if_then_else
(lt (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1245,9 +2453,36 @@
(plus:SI (match_dup 0)
(const_int 1)))]
"!TARGET_UNIX_ASM && CONST_INT_P (operands[1])"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (lt (match_dup 0)
+ (match_dup 1))
+ (label_ref (match_dup 2))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jaoblss_const_2"
+ [(set (pc)
+ (if_then_else
+ (lt (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (match_operand:SI 1 "general_operand" "nrmT"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_UNIX_ASM && CONST_INT_P (operands[1]) && reload_completed"
"jaoblss %P1,%0,%l2")
-(define_insn ""
+(define_insn_and_split "*jaobleq"
[(set (pc)
(if_then_else
(le (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1259,9 +2494,38 @@
(plus:SI (match_dup 0)
(const_int 1)))]
"!TARGET_UNIX_ASM"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (le (plus:SI (match_dup 0)
+ (const_int 1))
+ (match_dup 1))
+ (label_ref (match_dup 2))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jaobleq_2"
+ [(set (pc)
+ (if_then_else
+ (le (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (const_int 1))
+ (match_operand:SI 1 "general_operand" "nrmT"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_UNIX_ASM && reload_completed"
"jaobleq %1,%0,%l2")
-(define_insn ""
+(define_insn_and_split "*jaobleq_const"
[(set (pc)
(if_then_else
(le (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1272,12 +2536,39 @@
(plus:SI (match_dup 0)
(const_int 1)))]
"!TARGET_UNIX_ASM && CONST_INT_P (operands[1])"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (le (match_dup 0)
+ (match_dup 1))
+ (label_ref (match_dup 2))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jaobleq_const_2"
+ [(set (pc)
+ (if_then_else
+ (le (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (match_operand:SI 1 "general_operand" "nrmT"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "!TARGET_UNIX_ASM && CONST_INT_P (operands[1]) && reload_completed"
"jaobleq %P1,%0,%l2")
;; Something like a sob insn, but compares against -1.
;; This finds `while (foo--)' which was changed to `while (--foo != -1)'.
-(define_insn ""
+(define_insn_and_split "*jsobneq_minus_one"
[(set (pc)
(if_then_else
(ne (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1288,6 +2579,33 @@
(plus:SI (match_dup 0)
(const_int -1)))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (pc)
+ (if_then_else
+ (ne (match_dup 0)
+ (const_int 0))
+ (label_ref (match_dup 1))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*jsobneq_minus_one_2"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 0 "nonimmediate_operand" "+g")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"decl %0\;jgequ %l1")
(define_expand "call_pop"
@@ -1498,7 +2816,7 @@
rtx index = gen_reg_rtx (SImode);
emit_insn (gen_addsi3 (index,
operands[0],
- GEN_INT (-INTVAL (operands[1]))));
+ gen_int_mode (-INTVAL (operands[1]), SImode)));
operands[0] = index;
}
@@ -1514,40 +2832,127 @@
;; This insn is a bit of a lier. It actually falls through if no case
;; matches. But, we prevent that from ever happening by emitting a jump
;; before this, see the define_expand above.
-(define_insn "casesi1"
+(define_insn_and_split "casesi1"
[(match_operand:SI 1 "const_int_operand" "n")
(set (pc)
(plus:SI (sign_extend:SI
- (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "general_operand" "nrmT")
- (const_int 2))
- (pc))))
+ (mem:HI (plus:SI
+ (mult:SI
+ (match_operand:SI 0 "general_operand" "nrmT")
+ (const_int 2))
+ (pc))))
(label_ref:SI (match_operand 2 "" ""))))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(match_dup 1)
+ (set (pc)
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI
+ (mult:SI
+ (match_dup 0)
+ (const_int 2))
+ (pc))))
+ (label_ref:SI (match_dup 2))))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*casesi1"
+ [(match_operand:SI 1 "const_int_operand" "n")
+ (set (pc)
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI
+ (mult:SI
+ (match_operand:SI 0 "general_operand" "nrmT")
+ (const_int 2))
+ (pc))))
+ (label_ref:SI (match_operand 2 "" ""))))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"casel %0,$0,%1")
-(define_insn "pushextsym"
+(define_insn_and_split "*pushsym"
[(set (match_operand:SI 0 "push_operand" "=g")
- (match_operand:SI 1 "external_symbolic_operand" "i"))]
- ""
+ (match_operand:SI 1 "pic_symbolic_operand" "A"))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*pushsym_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "push_operand" "=g")
+ (match_operand:SI 1 "pic_symbolic_operand" "A"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"pushab %a1")
-(define_insn "movextsym"
+(define_insn_and_split "*movsym"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (match_operand:SI 1 "external_symbolic_operand" "i"))]
- ""
+ (match_operand:SI 1 "pic_symbolic_operand" "A"))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movsym_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (match_operand:SI 1 "pic_symbolic_operand" "A"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"movab %a1,%0")
-(define_insn "pushlclsym"
+(define_insn_and_split "*pushsymreg"
[(set (match_operand:SI 0 "push_operand" "=g")
- (match_operand:SI 1 "local_symbolic_operand" "i"))]
- ""
- "pushab %a1")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "pic_symbolic_operand" "A")))]
+ "flag_pic"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
-(define_insn "movlclsym"
+(define_insn "*pushsymreg_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "push_operand" "=g")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "pic_symbolic_operand" "A")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "flag_pic && reload_completed"
+ "pushab %a2[%1]")
+
+(define_insn_and_split "*movsymreg"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (match_operand:SI 1 "local_symbolic_operand" "i"))]
- ""
- "movab %a1,%0")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "pic_symbolic_operand" "A")))]
+ "flag_pic"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movsymreg_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "pic_symbolic_operand" "A")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "flag_pic && reload_completed"
+ "movab %a2[%1],%0")
;;- load or push effective address
;; These come after the move and add/sub patterns
@@ -1557,28 +2962,80 @@
;; It does not work to use constraints to distinguish pushes from moves,
;; because < matches any autodecrement, not just a push.
-(define_insn "pushaddr<mode>"
+(define_insn_and_split "pushaddr<mode>"
[(set (match_operand:SI 0 "push_operand" "=g")
(match_operand:VAXintQHSD 1 "address_operand" "p"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*pushaddr<mode><ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "push_operand" "=g")
+ (match_operand:VAXintQHSD 1 "address_operand" "p"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"pusha<VAXintQHSD:isfx> %a1")
-(define_insn "movaddr<mode>"
+(define_insn_and_split "movaddr<mode>"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(match_operand:VAXintQHSD 1 "address_operand" "p"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movaddr<mode><ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (match_operand:VAXintQHSD 1 "address_operand" "p"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"mova<VAXintQHSD:isfx> %a1,%0")
-(define_insn "pushaddr<mode>"
+(define_insn_and_split "pushaddr<mode>"
[(set (match_operand:SI 0 "push_operand" "=g")
(match_operand:VAXfp 1 "address_operand" "p"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*pushaddr<mode><ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "push_operand" "=g")
+ (match_operand:VAXfp 1 "address_operand" "p"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"pusha<VAXfp:fsfx> %a1")
-(define_insn "movaddr<mode>"
+(define_insn_and_split "movaddr<mode>"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(match_operand:VAXfp 1 "address_operand" "p"))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*movaddr<mode>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+ (match_operand:VAXfp 1 "address_operand" "p"))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"mova<VAXfp:fsfx> %a1,%0")
;; These used to be peepholes, but it is more straightforward to do them
@@ -1594,12 +3051,30 @@
;; with other operands constant. This is what the combiner converts the
;; above sequences to before attempting to recognize the new insn.
-(define_insn ""
+(define_insn_and_split "*andashlnegsi4"
[(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
(and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n"))
(match_operand:SI 3 "const_int_operand" "n")))]
"(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (and:SI (ashiftrt:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*andashlnegsi4_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
+ (and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (match_operand:QI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0
+ && reload_completed"
"*
{
unsigned long mask1 = INTVAL (operands[3]);
@@ -1616,12 +3091,29 @@
;; bits that the ashl would anyways, in which case it should have been
;; optimized away.
-(define_insn ""
+(define_insn_and_split "*andashlsi4"
[(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
(and:SI (ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n"))
(match_operand:SI 3 "const_int_operand" "n")))]
""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (and:SI (ashift:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 3)))
+ (clobber (reg:CC VAX_PSL_REGNUM))])]
+ "")
+
+(define_insn "*andashlsi4_2<ccn><ccnz><ccz>"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
+ (and:SI (ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
+ (match_operand:QI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:CC VAX_PSL_REGNUM))]
+ "reload_completed"
"*
{
operands[3]
@@ -1660,3 +3152,5 @@
emit_barrier ();
DONE;
})
+
+(include "builtins.md")
diff --git a/gcc/config/visium/visium.opt b/gcc/config/visium/visium.opt
index 9c2bf6d..efb792a 100644
--- a/gcc/config/visium/visium.opt
+++ b/gcc/config/visium/visium.opt
@@ -29,7 +29,7 @@ Target RejectNegative
Link with libc.a and libsim.a.
mfpu
-Target Report Mask(FPU)
+Target Mask(FPU)
Use hardware FP (default).
mhard-float
@@ -61,11 +61,11 @@ EnumValue
Enum(visium_processor_type) String(gr6) Value(PROCESSOR_GR6)
msv-mode
-Target RejectNegative Report Mask(SV_MODE)
+Target RejectNegative Mask(SV_MODE)
Generate code for the supervisor mode (default).
muser-mode
-Target RejectNegative Report InverseMask(SV_MODE)
+Target RejectNegative InverseMask(SV_MODE)
Generate code for the user mode.
menable-trampolines
diff --git a/gcc/config/vms/vms.opt b/gcc/config/vms/vms.opt
index 2dda12e..827e95f 100644
--- a/gcc/config/vms/vms.opt
+++ b/gcc/config/vms/vms.opt
@@ -23,7 +23,7 @@ map
Target RejectNegative
mmalloc64
-Target Report Var(flag_vms_malloc64) Init(1)
+Target Var(flag_vms_malloc64) Init(1)
Malloc data into P2 space.
mdebug-main=
@@ -31,11 +31,11 @@ Target RejectNegative Joined Var(vms_debug_main)
Set name of main routine for the debugger.
mvms-return-codes
-Target Report Var(flag_vms_return_codes)
+Target Var(flag_vms_return_codes)
Use VMS exit codes instead of posix ones.
mpointer-size=
-Target Joined Report RejectNegative Enum(vms_pointer_size) Var(flag_vms_pointer_size) Init(VMS_POINTER_SIZE_NONE)
+Target Joined RejectNegative Enum(vms_pointer_size) Var(flag_vms_pointer_size) Init(VMS_POINTER_SIZE_NONE)
-mpointer-size=[no,32,short,64,long] Set the default pointer size.
Enum
diff --git a/gcc/config/vxworks.c b/gcc/config/vxworks.c
index ca0f5de..b67d21d 100644
--- a/gcc/config/vxworks.c
+++ b/gcc/config/vxworks.c
@@ -27,6 +27,9 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "output.h"
#include "fold-const.h"
+#include "rtl.h"
+#include "memmodel.h"
+#include "optabs.h"
#if !HAVE_INITFINI_ARRAY_SUPPORT
/* Like default_named_section_asm_out_constructor, except that even
@@ -169,4 +172,25 @@ vxworks_override_options (void)
if (!global_options_set.x_dwarf_version)
dwarf_version = VXWORKS_DWARF_VERSION_DEFAULT;
+
+}
+
+/* We don't want to use library symbol __clear_cache on SR0640. Avoid
+ it and issue a direct call to cacheTextUpdate. It takes a size_t
+ length rather than the END address, so we have to compute it. */
+
+void
+vxworks_emit_call_builtin___clear_cache (rtx begin, rtx end)
+{
+ /* STATUS cacheTextUpdate (void *, size_t); */
+ rtx callee = gen_rtx_SYMBOL_REF (Pmode, "cacheTextUpdate");
+
+ enum machine_mode size_mode = TYPE_MODE (sizetype);
+
+ rtx len = simplify_gen_binary (MINUS, size_mode, end, begin);
+
+ emit_library_call (callee,
+ LCT_NORMAL, VOIDmode,
+ begin, ptr_mode,
+ len, size_mode);
}
diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h
index b7e5970..cd43139 100644
--- a/gcc/config/vxworks.h
+++ b/gcc/config/vxworks.h
@@ -265,15 +265,30 @@ extern void vxworks_asm_out_destructor (rtx symbol, int priority);
} \
while (0)
+/* For specific CPU macro definitions expected by the system headers,
+ different versions of VxWorks expect different forms of macros,
+ such as "_VX_CPU=..." on Vx7 and some variants of Vx6, or "CPU=..."
+ on all Vx6 and earlier. Setup a common prefix macro here, that
+ arch specific ports can reuse. */
+
+#if TARGET_VXWORKS7
+#define VX_CPU_PREFIX "_VX_"
+#else
+#define VX_CPU_PREFIX ""
+#endif
+
#define VXWORKS_KIND VXWORKS_KIND_NORMAL
/* The diab linker does not handle .gnu_attribute sections. */
#undef HAVE_AS_GNU_ATTRIBUTE
-/* We provide our own version of __clear_cache in libgcc, using a separate C
- file to facilitate #inclusion of VxWorks header files. */
-#undef CLEAR_INSN_CACHE
-#define CLEAR_INSN_CACHE 1
+/* We call vxworks's cacheTextUpdate instead of CLEAR_INSN_CACHE if
+ needed. We don't want to force a call on targets that don't define
+ cache-clearing insns nor CLEAR_INSN_CACHE. */
+#undef TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE
+#define TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE \
+ vxworks_emit_call_builtin___clear_cache
+extern void vxworks_emit_call_builtin___clear_cache (rtx begin, rtx end);
/* Default dwarf control values, for non-gdb debuggers that come with
VxWorks. */
diff --git a/gcc/config/vxworks.opt b/gcc/config/vxworks.opt
index 65295f1..9e0aaf2 100644
--- a/gcc/config/vxworks.opt
+++ b/gcc/config/vxworks.opt
@@ -32,7 +32,7 @@ Xbind-now
Driver Condition(VXWORKS_KIND == VXWORKS_KIND_NORMAL)
mrtp
-Target Report RejectNegative Mask(VXWORKS_RTP) Condition(VXWORKS_KIND == VXWORKS_KIND_NORMAL)
+Target RejectNegative Mask(VXWORKS_RTP) Condition(VXWORKS_KIND == VXWORKS_KIND_NORMAL)
Assume the VxWorks RTP environment.
; VxWorks AE has two modes: kernel mode and vThreads mode. In
diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md
index 1721640..eb52b05 100644
--- a/gcc/config/xtensa/predicates.md
+++ b/gcc/config/xtensa/predicates.md
@@ -25,9 +25,8 @@
(define_predicate "addsubx_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) == 2
- || INTVAL (op) == 4
- || INTVAL (op) == 8")))
+ (match_test "INTVAL (op) >= 1
+ && INTVAL (op) <= 3")))
(define_predicate "arith_operand"
(ior (and (match_code "const_int")
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index be1eb21..1cdc39a 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -1082,6 +1082,21 @@ xtensa_emit_move_sequence (rtx *operands, machine_mode mode)
if (! TARGET_AUTO_LITPOOLS && ! TARGET_CONST16)
{
+ /* Try to emit MOVI + SLLI sequence, that is smaller
+ than L32R + literal. */
+ if (optimize_size && mode == SImode && register_operand (dst, mode))
+ {
+ HOST_WIDE_INT srcval = INTVAL (src);
+ int shift = ctz_hwi (srcval);
+
+ if (xtensa_simm12b (srcval >> shift))
+ {
+ emit_move_insn (dst, GEN_INT (srcval >> shift));
+ emit_insn (gen_ashlsi3_internal (dst, dst, GEN_INT (shift)));
+ return 1;
+ }
+ }
+
src = force_const_mem (SImode, src);
operands[1] = src;
}
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 749fe47..cfb6a54 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -162,11 +162,14 @@
(define_insn "*addx"
[(set (match_operand:SI 0 "register_operand" "=a")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 3 "addsubx_operand" "i"))
+ (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 3 "addsubx_operand" "i"))
(match_operand:SI 2 "register_operand" "r")))]
"TARGET_ADDX"
- "addx%3\t%0, %1, %2"
+{
+ operands[3] = GEN_INT (1 << INTVAL (operands[3]));
+ return "addx%3\t%0, %1, %2";
+}
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "3")])
@@ -196,11 +199,14 @@
(define_insn "*subx"
[(set (match_operand:SI 0 "register_operand" "=a")
- (minus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 3 "addsubx_operand" "i"))
+ (minus:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 3 "addsubx_operand" "i"))
(match_operand:SI 2 "register_operand" "r")))]
"TARGET_ADDX"
- "subx%3\t%0, %1, %2"
+{
+ operands[3] = GEN_INT (1 << INTVAL (operands[3]));
+ return "subx%3\t%0, %1, %2";
+}
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "3")])
@@ -463,6 +469,27 @@
})
+;; Byte swap.
+
+(define_insn "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=&a")
+ (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
+ "!optimize_size"
+ "ssai\t8\;srli\t%0, %1, 16\;src\t%0, %0, %1\;src\t%0, %0, %0\;src\t%0, %1, %0"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "15")])
+
+(define_insn "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "=&a")
+ (bswap:DI (match_operand:DI 1 "register_operand" "r")))]
+ "!optimize_size"
+ "ssai\t8\;srli\t%0, %D1, 16\;src\t%0, %0, %D1\;src\t%0, %0, %0\;src\t%0, %D1, %0\;srli\t%D0, %1, 16\;src\t%D0, %D0, %1\;src\t%D0, %D0, %D0\;src\t%D0, %1, %D0"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")
+ (set_attr "length" "27")])
+
+
;; Negation and one's complement.
(define_insn "negsi2"
@@ -721,8 +748,23 @@
(match_operand:DI 1 "general_operand" ""))]
""
{
- if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
- operands[1] = force_const_mem (DImode, operands[1]);
+ if (CONSTANT_P (operands[1]))
+ {
+ /* Split in halves if 64-bit Const-to-Reg moves
+ because of offering further optimization opportunities. */
+ if (register_operand (operands[0], DImode))
+ {
+ rtx first, second;
+
+ split_double (operands[1], &first, &second);
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), first));
+ emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), second));
+ DONE;
+ }
+
+ if (!TARGET_CONST16)
+ operands[1] = force_const_mem (DImode, operands[1]);
+ }
if (!register_operand (operands[0], DImode)
&& !register_operand (operands[1], DImode))
@@ -1050,6 +1092,16 @@
operands[1] = xtensa_copy_incoming_a7 (operands[1]);
})
+(define_insn "*ashlsi3_1"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1)))]
+ "TARGET_DENSITY"
+ "add.n\t%0, %1, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2")])
+
(define_insn "ashlsi3_internal"
[(set (match_operand:SI 0 "register_operand" "=a,a")
(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -1062,6 +1114,17 @@
(set_attr "mode" "SI")
(set_attr "length" "3,6")])
+(define_insn "*ashlsi3_3x"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 3))))]
+ ""
+ "ssa8b\t%2\;sll\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "6")])
+
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=a,a")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -1074,6 +1137,17 @@
(set_attr "mode" "SI")
(set_attr "length" "3,6")])
+(define_insn "*ashrsi3_3x"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 3))))]
+ ""
+ "ssa8l\t%2\;sra\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "6")])
+
(define_insn "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=a,a")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -1093,6 +1167,17 @@
(set_attr "mode" "SI")
(set_attr "length" "3,6")])
+(define_insn "*lshrsi3_3x"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (ashift:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 3))))]
+ ""
+ "ssa8l\t%2\;srl\t%0, %1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "6")])
+
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "register_operand" "=a,a")
(rotate:SI (match_operand:SI 1 "register_operand" "r,r")
diff --git a/gcc/config/xtensa/xtensa.opt b/gcc/config/xtensa/xtensa.opt
index 0c4aa92..4887f5a 100644
--- a/gcc/config/xtensa/xtensa.opt
+++ b/gcc/config/xtensa/xtensa.opt
@@ -19,11 +19,11 @@
; <http://www.gnu.org/licenses/>.
mconst16
-Target Report Mask(CONST16)
+Target Mask(CONST16)
Use CONST16 instruction to load constants.
mforce-no-pic
-Target Report Mask(FORCE_NO_PIC)
+Target Mask(FORCE_NO_PIC)
Disable position-independent code (PIC) for use in OS kernel code.
mlongcalls
@@ -39,20 +39,20 @@ Target
Intersperse literal pools with code in the text section.
mauto-litpools
-Target Report Mask(AUTO_LITPOOLS)
+Target Mask(AUTO_LITPOOLS)
Relax literals in assembler and place them automatically in the text section.
mserialize-volatile
-Target Report Mask(SERIALIZE_VOLATILE)
+Target Mask(SERIALIZE_VOLATILE)
-mno-serialize-volatile Do not serialize volatile memory references with MEMW instructions.
TargetVariable
int xtensa_windowed_abi = -1
mabi=call0
-Target Report RejectNegative Var(xtensa_windowed_abi, 0)
+Target RejectNegative Var(xtensa_windowed_abi, 0)
Use call0 ABI.
mabi=windowed
-Target Report RejectNegative Var(xtensa_windowed_abi, 1)
+Target RejectNegative Var(xtensa_windowed_abi, 1)
Use windowed registers ABI.
diff --git a/gcc/configure b/gcc/configure
index f96a89e..ee97603 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -675,6 +675,8 @@ host_xm_defines
host_xm_include_list
host_xm_file_list
host_exeext
+gcc_gxx_libcxx_include_dir_add_sysroot
+gcc_gxx_libcxx_include_dir
gcc_gxx_include_dir_add_sysroot
gcc_gxx_include_dir
gcc_config_arguments
@@ -710,6 +712,7 @@ subdirs
dollar
gcc_tooldir
enable_lto
+DO_LINK_SERIALIZATION
DO_LINK_MUTEX
MAINT
zlibinc
@@ -936,6 +939,7 @@ with_native_system_header_dir
with_build_sysroot
with_sysroot
with_gxx_include_dir
+with_gxx_libcxx_include_dir
with_cpp_install_dir
enable_generated_files_in_srcdir
with_gnu_ld
@@ -972,6 +976,7 @@ with_documentation_root_url
with_changes_root_url
enable_languages
with_multilib_list
+with_multilib_generator
with_zstd
with_zstd_include
with_zstd_lib
@@ -1012,6 +1017,7 @@ with_gc
with_system_zlib
enable_maintainer_mode
enable_link_mutex
+enable_link_serialization
enable_version_specific_runtime_libs
enable_plugin
enable_host_shared
@@ -1021,6 +1027,7 @@ with_diagnostics_color
with_diagnostics_urls
enable_default_pie
enable_cet
+enable_s390_excess_float_precision
'
ac_precious_vars='build_alias
host_alias
@@ -1767,6 +1774,10 @@ Optional Features:
sometimes confusing) to the casual installer
--enable-link-mutex avoid linking multiple front-ends at once to avoid
thrashing on the build machine
+ --enable-link-serialization
+ avoid linking multiple GCC front-ends at once using
+ make dependencies to avoid thrashing on the build
+ machine
--enable-version-specific-runtime-libs
specify that runtime libraries should be installed
in a compiler-specific directory
@@ -1776,6 +1787,9 @@ Optional Features:
disable libquadmath support for Fortran
--enable-default-pie enable Position Independent Executable as default
--enable-cet enable Intel CET in host libraries [default=auto]
+ --enable-s390-excess-float-precision
+ on s390 targets, evaluate float with double
+ precision when in standards-conforming mode
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1790,6 +1804,8 @@ Optional Packages:
--with-sysroot[=DIR] search for usr/lib, usr/include, et al, within DIR
--with-gxx-include-dir=DIR
specifies directory to put g++ header files
+ --with-gxx-libcxx-include-dir=DIR
+ specifies directory to find libc++ header files
--with-cpp-install-dir=DIR
install the user visible C preprocessor in DIR
(relative to PREFIX) as well as PREFIX/bin
@@ -1811,6 +1827,8 @@ Optional Packages:
--with-changes-root-url=URL
Root for GCC changes URLs
--with-multilib-list select multilibs (AArch64, SH and x86-64 only)
+ --with-multilib-generator
+ Multi-libs configuration string (RISC-V only)
--with-zstd=PATH specify prefix directory for installed zstd library.
Equivalent to --with-zstd-include=PATH/include plus
--with-zstd-lib=PATH/lib
@@ -3718,6 +3736,52 @@ elif test "${with_sysroot+set}" = set; then
fi
fi
+# Configuration for an alternate set of C++ headers.
+gcc_gxx_libcxx_include_dir=
+# Specify the alternate g++ header file directory
+
+# Check whether --with-gxx-libcxx-include-dir was given.
+if test "${with_gxx_libcxx_include_dir+set}" = set; then :
+ withval=$with_gxx_libcxx_include_dir; case "${withval}" in
+yes) as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
+no) ;;
+*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac
+fi
+
+
+# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
+# check to see if the latter starts with the former and, upon success, compute
+# gcc_gxx_libcxx_include_dir as relative to the sysroot.
+gcc_gxx_libcxx_include_dir_add_sysroot=0
+
+if test x${gcc_gxx_libcxx_include_dir} != x; then
+
+$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h
+
+else
+ $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h
+
+fi
+# ??? This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_libcxx_include_dir} = x; then
+ if test x${enable_version_specific_runtime_libs} = xyes; then
+ gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'
+ else
+ libcxx_incdir='libc++_include/c++/$(version)/v1'
+ if test x$host != x$target; then
+ libcxx_incdir="$target_alias/$libcxx_incdir"
+ fi
+ gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir"
+ fi
+elif test "${with_sysroot+set}" = set; then
+ gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" : "${with_sysroot}"'\(.*\)'`
+ if test "${gcc_gxx_libcxx_without_sysroot}"; then
+ gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"
+ gcc_gxx_libcxx_include_dir_add_sysroot=1
+ fi
+fi
+
# Check whether --with-cpp_install_dir was given.
if test "${with_cpp_install_dir+set}" = set; then :
@@ -8002,6 +8066,15 @@ else
fi
+
+# Check whether --with-multilib-generator was given.
+if test "${with_multilib_generator+set}" = set; then :
+ withval=$with_multilib_generator; :
+else
+ with_multilib_generator=default
+fi
+
+
# -------------------------
# Checks for other programs
# -------------------------
@@ -10124,8 +10197,8 @@ fi
for ac_func in times clock kill getrlimit setrlimit atoq \
popen sysconf strsignal getrusage nl_langinfo \
- gettimeofday mbstowcs wcswidth mmap setlocale \
- clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked madvise mallinfo mallinfo2
+ gettimeofday mbstowcs wcswidth mmap posix_fallocate setlocale \
+ clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked madvise mallinfo mallinfo2 fstatat
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -10197,6 +10270,14 @@ _ACEOF
fi
+ac_fn_cxx_check_type "$LINENO" "sighander_t" "ac_cv_type_sighander_t" "signal.h
+"
+if test "x$ac_cv_type_sighander_t" = xyes; then :
+
+$as_echo "#define HAVE_SIGHANDLER_T 1" >>confdefs.h
+
+fi
+
ac_fn_cxx_check_header_preproc "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h"
@@ -11920,6 +12001,142 @@ $as_echo "#define HOST_HAS_F_SETLKW 1" >>confdefs.h
fi
+# Check if O_CLOEXEC is defined by fcntl
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for O_CLOEXEC" >&5
+$as_echo_n "checking for O_CLOEXEC... " >&6; }
+if ${ac_cv_o_cloexec+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <fcntl.h>
+int
+main ()
+{
+
+return open ("/dev/null", O_RDONLY | O_CLOEXEC);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_o_cloexec=yes
+else
+ ac_cv_o_cloexec=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_o_cloexec" >&5
+$as_echo "$ac_cv_o_cloexec" >&6; }
+if test $ac_cv_o_cloexec = yes; then
+
+$as_echo "#define HOST_HAS_O_CLOEXEC 1" >>confdefs.h
+
+fi
+
+# C++ Modules would like some networking features to provide the mapping
+# server. You can still use modules without them though.
+# The following network-related checks could probably do with some
+# Windows and other non-linux defenses and checking.
+
+# Local socket connectivity wants AF_UNIX networking
+# Check for AF_UNIX networking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AF_UNIX" >&5
+$as_echo_n "checking for AF_UNIX... " >&6; }
+if ${ac_cv_af_unix+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+int
+main ()
+{
+
+sockaddr_un un;
+un.sun_family = AF_UNSPEC;
+int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&un, sizeof (un));
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_af_unix=yes
+else
+ ac_cv_af_unix=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_af_unix" >&5
+$as_echo "$ac_cv_af_unix" >&6; }
+if test $ac_cv_af_unix = yes; then
+
+$as_echo "#define HAVE_AF_UNIX 1" >>confdefs.h
+
+fi
+
+# Remote socket connectivity wants AF_INET6 networking
+# Check for AF_INET6 networking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AF_INET6" >&5
+$as_echo_n "checking for AF_INET6... " >&6; }
+if ${ac_cv_af_inet6+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+int
+main ()
+{
+
+sockaddr_in6 in6;
+in6.sin6_family = AF_UNSPEC;
+struct addrinfo *addrs = 0;
+struct addrinfo hints;
+hints.ai_flags = 0;
+hints.ai_family = AF_INET6;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_protocol = 0;
+hints.ai_canonname = 0;
+hints.ai_addr = 0;
+hints.ai_next = 0;
+int e = getaddrinfo ("localhost", 0, &hints, &addrs);
+const char *str = gai_strerror (e);
+freeaddrinfo (addrs);
+int fd = socket (AF_INET6, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&in6, sizeof (in6));
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_af_inet6=yes
+else
+ ac_cv_af_inet6=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_af_inet6" >&5
+$as_echo "$ac_cv_af_inet6" >&6; }
+if test $ac_cv_af_inet6 = yes; then
+
+$as_echo "#define HAVE_AF_INET6 1" >>confdefs.h
+
+fi
+
# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
CXXFLAGS="$saved_CXXFLAGS"
@@ -15488,23 +15705,25 @@ _LT_EOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
$as_echo "$lt_cv_ld_force_load" >&6; }
- case $host_os in
- rhapsody* | darwin1.[012])
+ # Allow for Darwin 4-7 (macOS 10.0-10.3) although these are not expect to
+ # build without first building modern cctools / linker.
+ case $host_cpu-$host_os in
+ *-rhapsody* | *-darwin1.[012])
_lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
- darwin1.*)
+ *-darwin1.*)
_lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ *-darwin*)
+ # darwin 5.x (macOS 10.1) onwards we only need to adjust when the
+ # deployment target is forced to an earlier version.
+ case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host in
+ UNSET,*-darwin[89]*|UNSET,*-darwin[12][0123456789]*)
+ ;;
10.[012][,.]*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- esac
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ *)
+ ;;
+ esac
;;
esac
if test "$lt_cv_apple_cc_single_mod" = "yes"; then
@@ -17302,7 +17521,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
if test "$GCC" = yes && test "$with_gnu_ld" = no; then
case $host_cpu in
hppa*64*)
- archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -17314,7 +17533,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
else
case $host_cpu in
hppa*64*)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -19018,7 +19237,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 19021 "configure"
+#line 19240 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19124,7 +19343,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 19127 "configure"
+#line 19346 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -20146,7 +20365,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
aCC*)
case $host_cpu in
hppa*64*)
- archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
@@ -20170,7 +20389,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
if test $with_gnu_ld = no; then
case $host_cpu in
hppa*64*)
- archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
@@ -23395,6 +23614,43 @@ else
fi
+case "${target}" in
+ riscv*-*-linux*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker ifunc IRELATIVE support" >&5
+$as_echo_n "checking linker ifunc IRELATIVE support... " >&6; }
+ cat > conftest.s <<EOF
+ .text
+ .type foo_resolver, @function
+foo_resolver:
+ ret
+ .size foo_resolver, .-foo_resolver
+
+ .globl foo
+ .type foo, %gnu_indirect_function
+ .set foo, foo_resolver
+
+ .globl bar
+ .type bar, @function
+bar:
+ call foo
+ ret
+ .size bar, .-bar
+EOF
+ if test x$gcc_cv_as != x \
+ && test x$gcc_cv_ld != x \
+ && test x$gcc_cv_readelf != x \
+ && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_readelf --relocs --wide conftest \
+ | grep R_RISCV_IRELATIVE > /dev/null 2>&1; then
+ enable_gnu_indirect_function=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gnu_indirect_function" >&5
+$as_echo "$enable_gnu_indirect_function" >&6; }
+ ;;
+esac
+
gif=`if test x$enable_gnu_indirect_function = xyes; then echo 1; else echo 0; fi`
cat >>confdefs.h <<_ACEOF
@@ -23750,6 +24006,8 @@ _ACEOF
# Check if we have .[us]leb128, and support symbol arithmetic with it.
+# Older versions of GAS and some non-GNU assemblers, have a bugs handling
+# these directives, even when they appear to accept them.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .sleb128 and .uleb128" >&5
$as_echo_n "checking assembler for .sleb128 and .uleb128... " >&6; }
if ${gcc_cv_as_leb128+:} false; then :
@@ -23767,7 +24025,9 @@ fi
L1:
.uleb128 1280
.sleb128 -1010
-L2:' > conftest.s
+L2:
+ .uleb128 0x8000000000000000
+' > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
@@ -23775,22 +24035,22 @@ L2:' > conftest.s
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
- # GAS versions before 2.11 do not support uleb128,
- # despite appearing to.
- # ??? There exists an elf-specific test that will crash
- # the assembler. Perhaps it's better to figure out whether
- # arbitrary sections are supported and try the test.
- as_ver=`$gcc_cv_as --version 2>/dev/null | sed 1q`
- if echo "$as_ver" | grep GNU > /dev/null; then
- as_vers=`echo $as_ver | sed -n \
- -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
- as_major=`expr "$as_vers" : '\([0-9]*\)'`
- as_minor=`expr "$as_vers" : '[0-9]*\.\([0-9]*\)'`
- if test $as_major -eq 2 && test $as_minor -lt 11
- then :
- else gcc_cv_as_leb128=yes
- fi
+
+if test "x$gcc_cv_objdump" != x; then
+ if $gcc_cv_objdump -s conftest.o 2>/dev/null \
+ | grep '04800a8e 78808080 80808080 808001' >/dev/null; then
+ gcc_cv_as_leb128=yes
fi
+elif test "x$gcc_cv_otool" != x; then
+ if $gcc_cv_otool -d conftest.o 2>/dev/null \
+ | grep '04 80 0a 8e 78 80 80 80 80 80 80 80 80 80 01' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+else
+ # play safe, assume the assembler is broken.
+ :
+fi
+
else
echo "configure: failed program was" >&5
cat conftest.s >&5
@@ -24223,6 +24483,109 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 36 \) \* 1000 + 0`
+ then gcc_cv_as_shf_gnu_retain=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_shf_gnu_retain=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+# Test if the assembler supports the section flag 'o' for specifying
+# section with link-order.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'o', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_section_link_order=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'o' flag" >&5
+$as_echo_n "checking assembler for section 'o' flag... " >&6; }
+if ${gcc_cv_as_section_link_order+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_section_link_order=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 35 \) \* 1000 + 0`
+ then gcc_cv_as_section_link_order=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"a"
+.byte 0
+.section __patchable_function_entries,"awo",%progbits,.foo
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_section_link_order=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_section_link_order" >&5
+$as_echo "$gcc_cv_as_section_link_order" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SECTION_LINK_ORDER `if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
$as_echo_n "checking assembler for section merging support... " >&6; }
if ${gcc_cv_as_shf_merge+:} false; then :
@@ -28089,6 +28452,68 @@ $as_echo "#define HAVE_AS_RISCV_ATTRIBUTE 1" >>confdefs.h
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -misa-spec= support" >&5
+$as_echo_n "checking assembler for -misa-spec= support... " >&6; }
+if ${gcc_cv_as_riscv_isa_spec+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_riscv_isa_spec=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -misa-spec=2.2 -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_riscv_isa_spec=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_isa_spec" >&5
+$as_echo "$gcc_cv_as_riscv_isa_spec" >&6; }
+if test $gcc_cv_as_riscv_isa_spec = yes; then
+
+$as_echo "#define HAVE_AS_MISA_SPEC 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zifencei support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zifencei support... " >&6; }
+if ${gcc_cv_as_riscv_march_zifencei+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_riscv_march_zifencei=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zifencei -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_riscv_march_zifencei=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_march_zifencei" >&5
+$as_echo "$gcc_cv_as_riscv_march_zifencei" >&6; }
+if test $gcc_cv_as_riscv_march_zifencei = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZIFENCEI 1" >>confdefs.h
+
+fi
+
;;
s390*-*-*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
@@ -29811,6 +30236,9 @@ case "$target:$tm_file" in
*-*-linux*)
emul_name="-melf64ppc"
;;
+ *le-*-freebsd*)
+ emul_name="-melf64lppc_fbsd"
+ ;;
*-*-freebsd*)
emul_name="-melf64ppc_fbsd"
;;
@@ -30462,6 +30890,31 @@ else
fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to serialize linking of multiple front-ends" >&5
+$as_echo_n "checking whether to serialize linking of multiple front-ends... " >&6; }
+ # Check whether --enable-link-serialization was given.
+if test "${enable_link_serialization+set}" = set; then :
+ enableval=$enable_link_serialization; do_link_serialization=$enableval
+else
+ do_link_serialization=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $do_link_serialization" >&5
+$as_echo "$do_link_serialization" >&6; }
+
+case "$do_link_serialization" in
+ yes)
+ DO_LINK_SERIALIZATION=1;;
+ [1-9] | [1-9][0-9] | [1-9][0-9][0-9])
+ DO_LINK_SERIALIZATION=$do_link_serialization;;
+ no)
+ DO_LINK_SERIALIZATION=;;
+ *)
+ as_fn_error $? "bad value ${do_link_serialization} given for --enable-link-serialization" "$LINENO" 5 ;;
+esac
+
+
# --------------
# Language hooks
# --------------
@@ -30622,6 +31075,43 @@ do
echo "lang.$t: $x" >> Make-hooks
done
+echo "ifeq (\$(DO_LINK_SERIALIZATION),)" >> Make-hooks
+echo "SERIAL_LIST =" >> Make-hooks
+echo else >> Make-hooks
+lang_cnt=0
+lang_list=
+prev=c
+serialization_languages=c
+for lang in $all_selected_languages
+do
+ test $lang = c && continue
+ if test $lang = lto; then
+ serialization_languages="$serialization_languages lto1 lto2"
+ else
+ serialization_languages="$serialization_languages $lang"
+ fi
+done
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ lang_cnt=`expr $lang_cnt + 1`
+ lang_list=" $prev$lang_list"
+ prev=${lang}
+done
+echo "SERIAL_LIST = \$(wordlist \$(DO_LINK_SERIALIZATION),$lang_cnt,$lang_list)" >> Make-hooks
+echo endif >> Make-hooks
+echo "SERIAL_COUNT = `expr $lang_cnt + 1`" >> Make-hooks
+echo "INDEX.c = 0" >> Make-hooks
+lang_idx=1
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ echo "$lang.prev = \$(if \$(word $lang_cnt,\$(SERIAL_LIST)),\$(\$(word $lang_cnt,\$(SERIAL_LIST)).serial))" >> Make-hooks
+ echo "INDEX.$lang = $lang_idx" >> Make-hooks
+ lang_cnt=`expr $lang_cnt - 1`
+ lang_idx=`expr $lang_idx + 1`
+done
+
# --------
# Option include files
# --------
@@ -30739,6 +31229,8 @@ fi
+
+
# Echo link setup.
if test x${build} = x${host} ; then
if test x${host} = x${target} ; then
@@ -31408,6 +31900,96 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_pushpopstate_support" >&5
$as_echo "$ld_pushpopstate_support" >&6; }
+# On s390, float_t has historically been statically defined as double for no
+# good reason. To comply with the C standard in the light of this definition,
+# gcc has evaluated float expressions in double precision when in
+# standards-compatible mode or when given -fexcess-precision=standard. To enable
+# a smooth transition towards the new model used by most architectures, where
+# gcc describes its behavior via the macro __FLT_EVAL_METHOD__ and glibc derives
+# float_t from that, this behavior can be configured with
+# --enable-s390-excess-float-precision. When given as enabled, that flag selects
+# the old model. When omitted, native builds and cross compiles that have target
+# libc headers will detect whether libc clamps float_t to double and in that
+# case maintain the old model. Otherwise, they will default to the new model.
+# Check whether --enable-s390-excess-float-precision was given.
+if test "${enable_s390_excess_float_precision+set}" = set; then :
+ enableval=$enable_s390_excess_float_precision;
+else
+ enable_s390_excess_float_precision=auto
+fi
+
+
+case $target in
+ s390*-linux*)
+ if test x"$enable_s390_excess_float_precision" = xauto; then
+ # Can we autodetect the behavior of the target libc?
+ if test "$target" = "$host" -a "$host" = "$build"; then
+ enable_s390_excess_float_precision=autodetect
+ elif test "x$with_headers" != xno; then
+ # cross build. are target headers available?
+ # carefully coerce the build-system compiler to use target headers
+ saved_CXXFLAGS="$CXXFLAGS"
+ CROSS_TEST_CXXFLAGS="-nostdinc ${XGCC_FLAGS_FOR_TARGET//-B/-idirafter/}"
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <math.h>
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ enable_s390_excess_float_precision=autodetect
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXXFLAGS="$saved_CXXFLAGS"
+ fi
+
+ if test x"$enable_s390_excess_float_precision" = xautodetect; then
+ saved_CXXFLAGS="$CXXFLAGS"
+ if ! test "$target" = "$host" -a "$host" = "$build"; then
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ unset CROSS_TEST_CXXFLAGS
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glibc clamping float_t to double" >&5
+$as_echo_n "checking for glibc clamping float_t to double... " >&6; }
+if ${gcc_cv_float_t_clamped_to_double+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define __FLT_EVAL_METHOD__ 0
+#include <math.h>
+int dummy[sizeof(float_t) == sizeof(double) ? 1 : -1];
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_float_t_clamped_to_double=yes
+else
+ gcc_cv_float_t_clamped_to_double=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_float_t_clamped_to_double" >&5
+$as_echo "$gcc_cv_float_t_clamped_to_double" >&6; }
+ CXXFLAGS="$saved_CXXFLAGS"
+ enable_s390_excess_float_precision="$gcc_cv_float_t_clamped_to_double"
+ else
+ # no way to detect behavior of target libc, default to new model
+ enable_s390_excess_float_precision=no
+ fi
+ fi
+
+
+ if test x"$enable_s390_excess_float_precision" = xyes; then
+
+$as_echo "#define ENABLE_S390_EXCESS_FLOAT_PRECISION 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)
@@ -32757,7 +33339,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
"depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;;
"gccdepdir":C)
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
- for lang in $subdirs c-family common analyzer
+ for lang in $subdirs c-family common analyzer rtl-ssa
do
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
done ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 9154a54..6fcf154 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -228,6 +228,48 @@ elif test "${with_sysroot+set}" = set; then
fi
fi
+# Configuration for an alternate set of C++ headers.
+gcc_gxx_libcxx_include_dir=
+# Specify the alternate g++ header file directory
+AC_ARG_WITH(gxx-libcxx-include-dir,
+[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR],
+ [specifies directory to find libc++ header files])],
+[case "${withval}" in
+yes) AC_MSG_ERROR(bad value ${withval} given for libc++ include directory) ;;
+no) ;;
+*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac])
+
+# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
+# check to see if the latter starts with the former and, upon success, compute
+# gcc_gxx_libcxx_include_dir as relative to the sysroot.
+gcc_gxx_libcxx_include_dir_add_sysroot=0
+
+if test x${gcc_gxx_libcxx_include_dir} != x; then
+ AC_DEFINE(ENABLE_STDLIB_OPTION, 1,
+ [Define if the -stdlib= option should be enabled.])
+else
+ AC_DEFINE(ENABLE_STDLIB_OPTION, 0)
+fi
+# ??? This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_libcxx_include_dir} = x; then
+ if test x${enable_version_specific_runtime_libs} = xyes; then
+ gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'
+ else
+ libcxx_incdir='libc++_include/c++/$(version)/v1'
+ if test x$host != x$target; then
+ libcxx_incdir="$target_alias/$libcxx_incdir"
+ fi
+ gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir"
+ fi
+elif test "${with_sysroot+set}" = set; then
+ gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" : "${with_sysroot}"'\(.*\)'`
+ if test "${gcc_gxx_libcxx_without_sysroot}"; then
+ gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"
+ gcc_gxx_libcxx_include_dir_add_sysroot=1
+ fi
+fi
+
AC_ARG_WITH(cpp_install_dir,
[AC_HELP_STRING([--with-cpp-install-dir=DIR],
[install the user visible C preprocessor in DIR
@@ -1102,6 +1144,11 @@ AC_ARG_WITH(multilib-list,
:,
with_multilib_list=default)
+AC_ARG_WITH(multilib-generator,
+[AS_HELP_STRING([--with-multilib-generator], [Multi-libs configuration string (RISC-V only)])],
+:,
+with_multilib_generator=default)
+
# -------------------------
# Checks for other programs
# -------------------------
@@ -1237,7 +1284,7 @@ AC_CHECK_HEADERS(ext/hash_map)
ZW_CREATE_DEPDIR
AC_CONFIG_COMMANDS([gccdepdir],[
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
- for lang in $subdirs c-family common analyzer
+ for lang in $subdirs c-family common analyzer rtl-ssa
do
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR])
@@ -1412,8 +1459,8 @@ define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl
putchar_unlocked putc_unlocked)
AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoq \
popen sysconf strsignal getrusage nl_langinfo \
- gettimeofday mbstowcs wcswidth mmap setlocale \
- gcc_UNLOCKED_FUNCS madvise mallinfo mallinfo2)
+ gettimeofday mbstowcs wcswidth mmap posix_fallocate setlocale \
+ gcc_UNLOCKED_FUNCS madvise mallinfo mallinfo2 fstatat)
if test x$ac_cv_func_mbstowcs = xyes; then
AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
@@ -1435,6 +1482,10 @@ fi
AC_CHECK_TYPE(ssize_t, int)
AC_CHECK_TYPE(caddr_t, char *)
+AC_CHECK_TYPE(sighander_t,
+ AC_DEFINE(HAVE_SIGHANDLER_T, 1,
+ [Define if <sys/signal.h> defines sighandler_t]),
+ ,signal.h)
GCC_AC_FUNC_MMAP_BLACKLIST
@@ -1580,6 +1631,72 @@ if test $ac_cv_f_setlkw = yes; then
[Define if F_SETLKW supported by fcntl.])
fi
+# Check if O_CLOEXEC is defined by fcntl
+AC_CACHE_CHECK(for O_CLOEXEC, ac_cv_o_cloexec, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <fcntl.h>]], [[
+return open ("/dev/null", O_RDONLY | O_CLOEXEC);]])],
+[ac_cv_o_cloexec=yes],[ac_cv_o_cloexec=no])])
+if test $ac_cv_o_cloexec = yes; then
+ AC_DEFINE(HOST_HAS_O_CLOEXEC, 1,
+ [Define if O_CLOEXEC supported by fcntl.])
+fi
+
+# C++ Modules would like some networking features to provide the mapping
+# server. You can still use modules without them though.
+# The following network-related checks could probably do with some
+# Windows and other non-linux defenses and checking.
+
+# Local socket connectivity wants AF_UNIX networking
+# Check for AF_UNIX networking
+AC_CACHE_CHECK(for AF_UNIX, ac_cv_af_unix, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>]],[[
+sockaddr_un un;
+un.sun_family = AF_UNSPEC;
+int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&un, sizeof (un));]])],
+[ac_cv_af_unix=yes],
+[ac_cv_af_unix=no])])
+if test $ac_cv_af_unix = yes; then
+ AC_DEFINE(HAVE_AF_UNIX, 1,
+ [Define if AF_UNIX supported.])
+fi
+
+# Remote socket connectivity wants AF_INET6 networking
+# Check for AF_INET6 networking
+AC_CACHE_CHECK(for AF_INET6, ac_cv_af_inet6, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>]],[[
+sockaddr_in6 in6;
+in6.sin6_family = AF_UNSPEC;
+struct addrinfo *addrs = 0;
+struct addrinfo hints;
+hints.ai_flags = 0;
+hints.ai_family = AF_INET6;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_protocol = 0;
+hints.ai_canonname = 0;
+hints.ai_addr = 0;
+hints.ai_next = 0;
+int e = getaddrinfo ("localhost", 0, &hints, &addrs);
+const char *str = gai_strerror (e);
+freeaddrinfo (addrs);
+int fd = socket (AF_INET6, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&in6, sizeof (in6));]])],
+[ac_cv_af_inet6=yes],
+[ac_cv_af_inet6=no])])
+if test $ac_cv_af_inet6 = yes; then
+ AC_DEFINE(HAVE_AF_INET6, 1,
+ [Define if AF_INET6 supported.])
+fi
+
# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
CXXFLAGS="$saved_CXXFLAGS"
@@ -2802,6 +2919,41 @@ Valid choices are 'yes' and 'no'.]) ;;
esac],
[enable_gnu_indirect_function="$default_gnu_indirect_function"])
+case "${target}" in
+ riscv*-*-linux*)
+ AC_MSG_CHECKING(linker ifunc IRELATIVE support)
+ cat > conftest.s <<EOF
+ .text
+ .type foo_resolver, @function
+foo_resolver:
+ ret
+ .size foo_resolver, .-foo_resolver
+
+ .globl foo
+ .type foo, %gnu_indirect_function
+ .set foo, foo_resolver
+
+ .globl bar
+ .type bar, @function
+bar:
+ call foo
+ ret
+ .size bar, .-bar
+EOF
+ if test x$gcc_cv_as != x \
+ && test x$gcc_cv_ld != x \
+ && test x$gcc_cv_readelf != x \
+ && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_readelf --relocs --wide conftest \
+ | grep R_RISCV_IRELATIVE > /dev/null 2>&1; then
+ enable_gnu_indirect_function=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ AC_MSG_RESULT($enable_gnu_indirect_function)
+ ;;
+esac
+
gif=`if test x$enable_gnu_indirect_function = xyes; then echo 1; else echo 0; fi`
AC_DEFINE_UNQUOTED(HAVE_GNU_INDIRECT_FUNCTION, $gif,
[Define if your system supports gnu indirect functions.])
@@ -2962,34 +3114,38 @@ AC_MSG_RESULT($gcc_cv_ld_ro_rw_mix)
gcc_AC_INITFINI_ARRAY
# Check if we have .[us]leb128, and support symbol arithmetic with it.
+# Older versions of GAS and some non-GNU assemblers, have a bugs handling
+# these directives, even when they appear to accept them.
gcc_GAS_CHECK_FEATURE([.sleb128 and .uleb128], gcc_cv_as_leb128,
- [elf,2,11,0],,
+ [elf,2,11,0],,
[ .data
.uleb128 L2 - L1
L1:
.uleb128 1280
.sleb128 -1010
-L2:],
-[[# GAS versions before 2.11 do not support uleb128,
- # despite appearing to.
- # ??? There exists an elf-specific test that will crash
- # the assembler. Perhaps it's better to figure out whether
- # arbitrary sections are supported and try the test.
- as_ver=`$gcc_cv_as --version 2>/dev/null | sed 1q`
- if echo "$as_ver" | grep GNU > /dev/null; then
- as_vers=`echo $as_ver | sed -n \
- -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
- as_major=`expr "$as_vers" : '\([0-9]*\)'`
- as_minor=`expr "$as_vers" : '[0-9]*\.\([0-9]*\)'`
- if test $as_major -eq 2 && test $as_minor -lt 11
- then :
- else gcc_cv_as_leb128=yes
- fi
- fi]],
- [AC_DEFINE(HAVE_AS_LEB128, 1,
- [Define if your assembler supports .sleb128 and .uleb128.])],
- [AC_DEFINE(HAVE_AS_LEB128, 0,
- [Define if your assembler supports .sleb128 and .uleb128.])])
+L2:
+ .uleb128 0x8000000000000000
+],
+[[
+if test "x$gcc_cv_objdump" != x; then
+ if $gcc_cv_objdump -s conftest.o 2>/dev/null \
+ | grep '04800a8e 78808080 80808080 808001' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+elif test "x$gcc_cv_otool" != x; then
+ if $gcc_cv_otool -d conftest.o 2>/dev/null \
+ | grep '04 80 0a 8e 78 80 80 80 80 80 80 80 80 80 01' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+else
+ # play safe, assume the assembler is broken.
+ :
+fi
+]],
+ [AC_DEFINE(HAVE_AS_LEB128, 1,
+ [Define if your assembler supports .sleb128 and .uleb128.])],
+ [AC_DEFINE(HAVE_AS_LEB128, 0,
+ [Define if your assembler supports .sleb128 and .uleb128.])])
# Determine if an .eh_frame section is read-only.
gcc_fn_eh_frame_ro () {
@@ -3216,6 +3372,48 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
[`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
[Define if your assembler supports specifying the exclude section flag.])
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [elf,2,36,0], [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
+# Test if the assembler supports the section flag 'o' for specifying
+# section with link-order.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'o', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_section_link_order=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'o' flag], gcc_cv_as_section_link_order,
+ [2,35,0], [--fatal-warnings],
+ [.section .foo,"a"
+.byte 0
+.section __patchable_function_entries,"awo",%progbits,.foo
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_LINK_ORDER,
+ [`if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports 'o' flag in .section directive.])
+
gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", @progbits, 1])
@@ -5071,6 +5269,16 @@ configured with --enable-newlib-nano-formatted-io.])
[.attribute stack_align,4],,
[AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
[Define if your assembler supports .attribute.])])
+ gcc_GAS_CHECK_FEATURE([-misa-spec= support],
+ gcc_cv_as_riscv_isa_spec,,
+ [-misa-spec=2.2],,,
+ [AC_DEFINE(HAVE_AS_MISA_SPEC, 1,
+ [Define if the assembler understands -misa-spec=.])])
+ gcc_GAS_CHECK_FEATURE([-march=rv32i_zifencei support],
+ gcc_cv_as_riscv_march_zifencei,,
+ [-march=rv32i_zifencei],,,
+ [AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1,
+ [Define if the assembler understands -march=rv*_zifencei.])])
;;
s390*-*-*)
gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
@@ -6108,6 +6316,9 @@ case "$target:$tm_file" in
*-*-linux*)
emul_name="-melf64ppc"
;;
+ *le-*-freebsd*)
+ emul_name="-melf64lppc_fbsd"
+ ;;
*-*-freebsd*)
emul_name="-melf64ppc_fbsd"
;;
@@ -6626,6 +6837,29 @@ else
fi
AC_SUBST(DO_LINK_MUTEX)
+dnl Whether to prevent multiple GCC front-ends from linking at the same time
+
+AC_MSG_CHECKING([whether to serialize linking of multiple front-ends])
+ AC_ARG_ENABLE(link-serialization,
+[AS_HELP_STRING([--enable-link-serialization],
+ [avoid linking multiple GCC front-ends at once using make
+ dependencies to avoid thrashing on the build machine])],
+ do_link_serialization=$enableval,
+ do_link_serialization=no)
+AC_MSG_RESULT($do_link_serialization)
+
+case "$do_link_serialization" in
+ yes)
+ DO_LINK_SERIALIZATION=1;;
+ [[1-9]] | [[1-9]][[0-9]] | [[1-9]][[0-9]][[0-9]])
+ DO_LINK_SERIALIZATION=$do_link_serialization;;
+ no)
+ DO_LINK_SERIALIZATION=;;
+ *)
+ AC_MSG_ERROR(bad value ${do_link_serialization} given for --enable-link-serialization) ;;
+esac
+AC_SUBST(DO_LINK_SERIALIZATION)
+
# --------------
# Language hooks
# --------------
@@ -6786,6 +7020,43 @@ do
echo "lang.$t: $x" >> Make-hooks
done
+echo "ifeq (\$(DO_LINK_SERIALIZATION),)" >> Make-hooks
+echo "SERIAL_LIST =" >> Make-hooks
+echo else >> Make-hooks
+lang_cnt=0
+lang_list=
+prev=c
+serialization_languages=c
+for lang in $all_selected_languages
+do
+ test $lang = c && continue
+ if test $lang = lto; then
+ serialization_languages="$serialization_languages lto1 lto2"
+ else
+ serialization_languages="$serialization_languages $lang"
+ fi
+done
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ lang_cnt=`expr $lang_cnt + 1`
+ lang_list=" $prev$lang_list"
+ prev=${lang}
+done
+echo "SERIAL_LIST = \$(wordlist \$(DO_LINK_SERIALIZATION),$lang_cnt,$lang_list)" >> Make-hooks
+echo endif >> Make-hooks
+echo "SERIAL_COUNT = `expr $lang_cnt + 1`" >> Make-hooks
+echo "INDEX.c = 0" >> Make-hooks
+lang_idx=1
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ echo "$lang.prev = \$(if \$(word $lang_cnt,\$(SERIAL_LIST)),\$(\$(word $lang_cnt,\$(SERIAL_LIST)).serial))" >> Make-hooks
+ echo "INDEX.$lang = $lang_idx" >> Make-hooks
+ lang_cnt=`expr $lang_cnt - 1`
+ lang_idx=`expr $lang_idx + 1`
+done
+
# --------
# Option include files
# --------
@@ -6867,6 +7138,8 @@ AC_SUBST(float_h_file)
AC_SUBST(gcc_config_arguments)
AC_SUBST(gcc_gxx_include_dir)
AC_SUBST(gcc_gxx_include_dir_add_sysroot)
+AC_SUBST(gcc_gxx_libcxx_include_dir)
+AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot)
AC_SUBST(host_exeext)
AC_SUBST(host_xm_file_list)
AC_SUBST(host_xm_include_list)
@@ -7138,6 +7411,73 @@ if test x"$ld_pushpopstate_support" = xyes; then
fi
AC_MSG_RESULT($ld_pushpopstate_support)
+# On s390, float_t has historically been statically defined as double for no
+# good reason. To comply with the C standard in the light of this definition,
+# gcc has evaluated float expressions in double precision when in
+# standards-compatible mode or when given -fexcess-precision=standard. To enable
+# a smooth transition towards the new model used by most architectures, where
+# gcc describes its behavior via the macro __FLT_EVAL_METHOD__ and glibc derives
+# float_t from that, this behavior can be configured with
+# --enable-s390-excess-float-precision. When given as enabled, that flag selects
+# the old model. When omitted, native builds and cross compiles that have target
+# libc headers will detect whether libc clamps float_t to double and in that
+# case maintain the old model. Otherwise, they will default to the new model.
+AC_ARG_ENABLE(s390-excess-float-precision,
+ [AS_HELP_STRING([--enable-s390-excess-float-precision],
+ [on s390 targets, evaluate float with double precision
+ when in standards-conforming mode])],
+ [],[enable_s390_excess_float_precision=auto])
+
+case $target in
+ s390*-linux*)
+ if test x"$enable_s390_excess_float_precision" = xauto; then
+ # Can we autodetect the behavior of the target libc?
+ if test "$target" = "$host" -a "$host" = "$build"; then
+ enable_s390_excess_float_precision=autodetect
+ elif test "x$with_headers" != xno; then
+ # cross build. are target headers available?
+ # carefully coerce the build-system compiler to use target headers
+ saved_CXXFLAGS="$CXXFLAGS"
+ CROSS_TEST_CXXFLAGS="-nostdinc ${XGCC_FLAGS_FOR_TARGET//-B/-idirafter/}"
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <math.h>
+]])], [enable_s390_excess_float_precision=autodetect], [])
+ CXXFLAGS="$saved_CXXFLAGS"
+ fi
+
+ if test x"$enable_s390_excess_float_precision" = xautodetect; then
+ saved_CXXFLAGS="$CXXFLAGS"
+ if ! test "$target" = "$host" -a "$host" = "$build"; then
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ unset CROSS_TEST_CXXFLAGS
+ fi
+ AC_CACHE_CHECK([for glibc clamping float_t to double],
+ gcc_cv_float_t_clamped_to_double, [
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#define __FLT_EVAL_METHOD__ 0
+#include <math.h>
+int dummy[sizeof(float_t) == sizeof(double) ? 1 : -1];
+]])],
+ [gcc_cv_float_t_clamped_to_double=yes],
+ [gcc_cv_float_t_clamped_to_double=no])])
+ CXXFLAGS="$saved_CXXFLAGS"
+ enable_s390_excess_float_precision="$gcc_cv_float_t_clamped_to_double"
+ else
+ # no way to detect behavior of target libc, default to new model
+ enable_s390_excess_float_precision=no
+ fi
+ fi
+
+ GCC_TARGET_TEMPLATE(ENABLE_S390_EXCESS_FLOAT_PRECISION)
+ if test x"$enable_s390_excess_float_precision" = xyes; then
+ AC_DEFINE(ENABLE_S390_EXCESS_FLOAT_PRECISION, 1,
+[Define to enable evaluating float expressions with double precision in
+standards-compatible mode on s390 targets.])
+ fi
+ ;;
+esac
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 81a1b59..043df12 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -367,23 +367,6 @@ struct kv_pair
const ValueType value; /* the value of the name */
};
-/* Iterator pair used for a collection iteration with range-based loops. */
-
-template<typename T>
-struct iterator_range
-{
-public:
- iterator_range (const T &begin, const T &end)
- : m_begin (begin), m_end (end) {}
-
- T begin () const { return m_begin; }
- T end () const { return m_end; }
-
-private:
- T m_begin;
- T m_end;
-};
-
#else
struct _dont_use_rtx_here_;
@@ -444,6 +427,18 @@ enum excess_precision_type
EXCESS_PRECISION_TYPE_FAST
};
+/* Level of size optimization. */
+
+enum optimize_size_level
+{
+ /* Do not optimize for size. */
+ OPTIMIZE_SIZE_NO,
+ /* Optimize for size but not at extreme performance costs. */
+ OPTIMIZE_SIZE_BALANCED,
+ /* Optimize for size as much as possible. */
+ OPTIMIZE_SIZE_MAX
+};
+
/* Support for user-provided GGC and PCH markers. The first parameter
is a pointer to a pointer, the second a cookie. */
typedef void (*gt_pointer_operator) (void *, void *);
@@ -479,6 +474,7 @@ typedef unsigned char uchar;
#include "align.h"
/* Most host source files will require the following headers. */
#if !defined (GENERATOR_FILE)
+#include "iterator-utils.h"
#include "real.h"
#include "fixed-value.h"
#include "hash-table.h"
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 7711412..d299e48 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1097,6 +1097,25 @@ build_gcov_exit_decl (void)
cgraph_build_static_cdtor ('D', dtor, priority);
}
+/* Generate the pointer to the gcov_info_var in a dedicated section. */
+
+static void
+build_gcov_info_var_registration (tree gcov_info_type)
+{
+ tree var = build_decl (BUILTINS_LOCATION,
+ VAR_DECL, NULL_TREE,
+ build_pointer_type (gcov_info_type));
+ TREE_STATIC (var) = 1;
+ TREE_READONLY (var) = 1;
+ char name_buf[32];
+ ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 2);
+ DECL_NAME (var) = get_identifier (name_buf);
+ get_section (profile_info_section, SECTION_UNNAMED, NULL);
+ set_decl_section_name (var, profile_info_section);
+ DECL_INITIAL (var) = build_fold_addr_expr (gcov_info_var);
+ varpool_node::finalize_decl (var);
+}
+
/* Create the gcov_info types and object. Generate the constructor
function to call __gcov_init. Does not generate the initializer
for the object. Returns TRUE if coverage data is being emitted. */
@@ -1151,8 +1170,13 @@ coverage_obj_init (void)
ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
DECL_NAME (gcov_info_var) = get_identifier (name_buf);
- build_init_ctor (gcov_info_type);
- build_gcov_exit_decl ();
+ if (profile_info_section)
+ build_gcov_info_var_registration (gcov_info_type);
+ else
+ {
+ build_init_ctor (gcov_info_type);
+ build_gcov_exit_decl ();
+ }
return true;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3fe4931..593627c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,1757 @@
+2020-12-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++spec.c (LIBCXX, LIBCXX_PROFILE, LIBCXX_STATIC): New.
+ (LIBCXXABI, LIBCXXABI_PROFILE, LIBCXXABI_STATIC): New.
+ (enum stdcxxlib_kind): New.
+ (lang_specific_driver): Allow selection amongst multiple
+ c++ runtime libraries.
+
+2020-12-23 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/96045
+ * parser.c (cp_lexer_new_main): Adjust EOF token location.
+
+2020-12-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/97597
+ * class.c (is_empty_base_ref): New.
+ (build_base_path): Add NOP_EXPR after offset.
+ * cp-tree.h (is_empty_base_ref): Declare it.
+ * call.c (unsafe_return_slot_p): Call it.
+
+2020-12-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98353
+ * init.c (build_zero_init_1): Use build_zero_cst for SCALAR_TYPE_P
+ zero initializers.
+
+2020-12-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/98332
+ * constexpr.c (unshare_constructor): Check for NULL.
+ (cxx_eval_vec_init_1): Always exit early if non-constant.
+
+2020-12-22 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc (has_definition): Check DECL_LANG_SPECIFIC.
+
+2020-12-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/93480
+ * method.c (common_comparison_type): If comps[i] is a TREE_LIST,
+ use its TREE_VALUE instead.
+ (build_comparison_op): Handle array members.
+
+2020-12-22 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * module.cc (INCLUDE_STRING): Define.
+ (INCLUDE_VECTOR): Ditto.
+
+2020-12-22 Jason Merrill <jason@redhat.com>
+
+ * mangle.c (write_member_name): Add assert.
+ (write_expression): Add asserts.
+
+2020-12-21 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc (create_dirs): Add logging.
+ (finish_module_processing): Unlink before rename.
+
+2020-12-21 Nathan Sidwell <nathan@acm.org>
+
+ PR bootstrap/98412
+ * mapper-client.cc: INCLUDE_STRING, INCLUDE_VECTOR.
+ (module_client::open_module_client): Avoid std::stoul.
+ * mapper-resolver.cc: INCLUDE_STRING, INCLUDE_VECTOR.
+
+2020-12-18 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * cp-lang.c (cxx_get_decl_init): New.
+ (cxx_omp_finish_decl_inits): New.
+ (LANG_HOOKS_GET_DECL_INIT): New.
+ (LANG_HOOKS_OMP_FINISH_DECL_INITS): New.
+ * cp-tree.h (dynamic_initializers): New.
+ * decl.c (dynamic_initializers): New.
+ * decl2.c (c_parse_final_cleanups): Add initializer entries
+ from vars to dynamic_initializers.
+
+2020-12-18 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc (O_CLOEXEC, O_BINARY): Add window's support.
+ (elf_in::defrost, module_state::do_import)
+ (finish_module_processing): Use O_BINARY.
+
+2020-12-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98343
+ * cp-gimplify.c (source_location_table_entry_hash::pch_nx): Override
+ static member functions from ggc_remove.
+
+2020-12-18 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (satisfying_constraint): Move up definition
+ and give it bool type.
+ (failed_type_completion_count): Replace with ...
+ (failed_type_completions): ... this.
+ (note_failed_type_completion_for_satisfaction): Append the
+ supplied argument to failed_type_completions.
+ (some_type_complete_p): Define.
+ (sat_entry::maybe_unstable): Replace with ...
+ (sat_entry::ftc_begin, sat_entry::ftc_end): ... these.
+ (satisfaction_cache::ftc_count): Replace with ...
+ (satisfaction_cache::ftc_begin): ... this.
+ (satisfaction_cache::satisfaction_cache): Adjust accordingly.
+ (satisfaction_cache::get): Adjust accordingly, using
+ some_type_complete_p.
+ (satisfaction_cache::save): Adjust accordingly.
+ (satisfying_constraint_p): Remove unused function.
+ (satisfy_constraint): Set satisfying_constraint.
+ (satisfy_declaration_constraints): Likewise.
+ * decl.c (require_deduced_type): Call
+ note_failed_type_completion_for_satisfaction.
+
+2020-12-18 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (sat_entry::evaluating): New member.
+ (satisfaction_cache::get): If entry->evaluating, diagnose
+ self-recursive satisfaction. Otherwise, set entry->evaluating
+ if we're not reusing a cached satisfaction result.
+ (satisfaction_cache::save): Clear entry->evaluating.
+ (satisfy_atom): Set up diagnosing_failed_constraint before the
+ first call to get().
+
+2020-12-18 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (failed_type_completion_count): New.
+ (note_failed_type_completion_for_satisfaction): New.
+ (sat_entry::constr): Rename to ...
+ (sat_entry::atom): ... this.
+ (sat_entry::location): New member.
+ (sat_entry::maybe_unstable): New member.
+ (sat_entry::diagnose_instability): New member.
+ (struct sat_hasher): Adjust after the above renaming.
+ (get_satisfaction, save_satisfaction): Remove.
+ (satisfaction_cache): Rewrite completely.
+ (satisfy_atom): When instantiation of the parameter mapping
+ fails, set diagnose_instability. Propagate location from
+ inst_cache.entry to cache.entry if the secondary lookup
+ succeeded.
+ (satisfy_declaration_constraints): When
+ failed_type_completion_count differs before and after
+ satisfaction, then don't cache the satisfaction result.
+ * cp-tree.h (note_failed_type_completion_for_satisfaction):
+ Declare.
+ * pt.c (tsubst) <case TYPENAME_TYPE>: Use
+ complete_type_or_maybe_complain instead of open-coding it.
+ * typeck.c (complete_type_or_maybe_complain): Call
+ note_failed_type_completion_for_satisfaction when type
+ completion fails.
+
+2020-12-17 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98340
+ * module.cc (uintset<T>::hash::add): Use uintset (0u).MEMBER,
+ rather than uintset::MEMBER.
+
+2020-12-17 Nathan Sidwell <nathan@acm.org>
+
+ PR bootstrap/98300
+ * module.cc: Fix ::read, ::write result signedness comparisons.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * mapper-resolver.cc: Remove early include of
+ sys/socket.h. Specify no CODY_NETWORKING instead.
+ * module.cc: Specify no CODY_NETWORKING.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_elaborated_type_specifier): Test
+ BOUND_TEMPLATE_TEMPLATE_PARM before checking for instantiation.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc (dumper::push): Clangify offsetof use.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * mapper-resolver.cc: #include sys/socket before system.h
+ due to poisoned bcopy use.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc (loc_spans): Make spans a pointer, not inline.
+ Adjust all accesses.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * mapper-client.cc: Include sys/socket.h before system.h.
+
+2020-12-15 Patrick Palka <ppalka@redhat.com>
+
+ * pt.c (in_template_function): Inspect cfun->decl instead of
+ current_function_decl.
+
+2020-12-15 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc: Replace stubs with implementation.
+
+2020-12-15 Nathan Sidwell <nathan@acm.org>
+
+ * Make-lang.in (CXX_AND_OBJCXX_OBJS): Add mapper-client &
+ mapper-resolver.
+ * mapper-client.h: New.
+ * mapper-client.cc: New.
+ * mapper-resolver.cc: New.
+
+2020-12-15 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (do_namespace_alias): Set originating module
+ before pushing.
+
+2020-12-11 Jason Merrill <jason@redhat.com>
+
+ PR libstdc++/97600
+ * call.c (build_user_type_conversion_1): Avoid considering
+ conversion functions that return a clearly unsuitable type.
+
+2020-12-11 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (make_binding_vec): Add CXX_MEM_STAT_INFO.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * config-lang.in (gtfiles): Add cp/module.cc.
+ * decl2.c (c_parse_final_cleanups): Add module support.
+ * lambda.c (record_lambda_scope): Call maybe_attach_decl.
+ * module.cc (maybe_attach_decl, lazy_load_specializations): Stubs.
+ (finish_module_procesing): Stub.
+ * pt.c (lookup_template_class_1): Lazy load specializations.
+ (instantiate_template_1): Likewise.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * decl2.c (c_parse_final_cleanups): Refactor loop.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (map_context_from, map_context_to): Declare.
+ * module.cc (map_context_from, map_context_to): Define.
+ * tree.c (cp_tree_equal): Check map_context_{from,to} for parm
+ context difference. Allow NON_LVALUE_EXPR and VIEW_CONVERT_EXPR
+ with null types.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * cp-lang.c (LANG_HOOKS_PREPROCESS_MAIN_FILE): Override.
+ (LANG_HOOKS_PREPROCESS_OPTIONS): Override.
+ (LANG_HOOKS_PREPROCESS_TOKEN): Override.
+ * cp-objcp-common.c (cp_register_dumps): Add module dump.
+ (cp_handle_option): New.
+ * cp-objcp-common.h (cp_handle_option): Declare.
+ (LANG_HOOKS_HANDLE_OPTION): Override.
+ * cp-tree.h (module_dump_id): Declare.
+ * module.cc (module_dump_id): Define.
+ (module_begin_main_file, handle_module_option)
+ (module_preproces_options): Stubs.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc (lazy_specializations_p): Stub.
+ * name-lookup.h (append_imported_binding_slot)
+ (mergeable_namespacE_slots, lookup_class_binding)
+ (walk_module_binding, import_module_binding, set_module_binding)
+ (note_pending_specializations, load_pending_specializations)
+ (add_module_decl, add_imported_namespace): Declare.
+ (get_cxx_dialect_name): Declare.
+ (enum WMB_flags): New.
+ * name-lookup.c (append_imported_binding_slot)
+ (mergeable_namespacE_slots, lookup_class_binding)
+ (walk_module_binding, import_module_binding, set_module_binding)
+ (note_pending_specializations, load_pending_specializations)
+ (add_module_decl, add_imported_namespace): New.
+ (get_cxx_dialect_name): Make extern.
+
+2020-12-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/78173
+ * typeck.c (pointer_diff): Use complete_type_or_maybe_complain
+ instead of complete_type_or_else.
+
+2020-12-10 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (struct type_identity): New.
+ (make_temp_override): New.
+ * decl.c (grokdeclarator): Use it.
+ * except.c (maybe_noexcept_warning): Use it.
+ * parser.c (cp_parser_enum_specifier): Use it.
+ (cp_parser_parameter_declaration_clause): Use it.
+ (cp_parser_gnu_attributes_opt): Use it.
+ (cp_parser_std_attribute): Use it.
+
+2020-12-10 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (do_nonmember_using_decl): Add INSERT_P parm.
+ Deal with exporting using decls.
+ (finish_nonmember_using_decl): Examine BINDING_VECTOR.
+
+2020-12-10 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (visible_instantiation_path): Renamed.
+ * module.cc (get_originating_module_decl, lazy_load_binding)
+ (lazy_load_members, visible_instantiation_path): Stubs.
+ * name-lookup.c (STAT_TYPE_VISIBLE_P, STAT_VISIBLE): New.
+ (search_imported_binding_slot, init_global_partition)
+ (get_fixed_binding_slot): New.
+ (name_lookup::process_module_binding): New.
+ (name_lookup::search_namespace_only): Search BINDING_VECTOR.
+ (name_lookup::adl_namespace_fns): Likewise.
+ (name_lookip::search_adl): Search visible instantiation path.
+ (maybe_lazily_declare): Maybe lazy load members.
+ (implicitly_exporT_namespace): New.
+ (maybe_record_mergeable_decl): New.
+ (check_module_override): New.
+ (do_pushdecl): Deal with BINDING_VECTOR, check override.
+ (add_mergeable_namespace_entity): New.
+ (get_namespace_binding): Deal with BINDING_VECTOR.
+ (do_namespace_alias): Call set_originating_module.
+ (lookup_elaborated_type_1): Deal with BINDING_VECTOR.
+ (do_pushtag): Call set_originating_module.
+ (reuse_namespace): New.
+ (make_namespace_finish): Add FROM_IMPORT parm.
+ (push_namespace): Deal with BINDING_VECTOR & namespace reuse.
+ (maybe_save_operator_binding): Save when module CMI in play.
+ * name-lookup.h (add_mergeable_namespace_entity): Declare.
+
+2020-12-10 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c: Include bitmap.h.
+ (enum binding_slots): New.
+ (maybe_add_fuzzy_binding): Return bool true if found.
+ (consider_binding_level): Add module support.
+ * module.cc (get_import_bitmap): Stub.
+
+2020-12-10 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (pop_local_binding): Check for IDENTIFIER_ANON_P.
+ (update_binding): Level may be null, don't add namespaces to
+ level.
+ (newbinding_bookkeeping): New, broken out of ...
+ (do_pushdecl): ... here, call it. Don't push anonymous decls.
+ (pushdecl, add_using_namespace): Correct comments.
+ (do_push_nested_namespace): Remove assert.
+ (make_namespace, make_namespace_finish): New, broken out of ...
+ (push_namespace): ... here. Call them. Add namespace to level
+ here.
+
+2020-12-10 Nathan Sidwell <nathan@acm.org>
+
+ * error.c (dump_module_suffix): New.
+ (dump_aggr_type, dump_simple_decl, dump_function_name): Call it.
+ * ptree.c (cxx_print_decl): Print module information.
+ * module.cc (module_name, get_importing_module): Stubs.
+
+2020-12-10 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.h (set_class_bindings): Return vector, take signed
+ 'extra' parm.
+ * name-lookup.c (maybe_lazily_declare): Break out ...
+ (get_class_binding): .. of here, call it.
+ (find_member_slot): Adjust get_class_bindings call.
+ (set_class_bindings): Allow -ve extra. Return the vector.
+ (set_identifier_type_value_with_scope): Remove checking assert.
+ (lookup_using_decl): Set decl's context.
+ (do_pushtag): Adjust set_identifier_type_value_with_scope handling.
+
+2020-12-09 Nathan Sidwell <nathan@acm.org>
+
+ * parser.h (struct cp_token): Add main_source_p field.
+ * parser.c (cp_lexer_new_main): Pass thought module token filter.
+ Check macros.
+ (cp_lexer_get_preprocessor_token): Set main_source_p.
+ (enum module_parse): New.
+ (cp_parser_diagnose_invalid_type_name): Deal with unrecognized
+ module-directives.
+ (cp_parser_skip_to_closing_parenthesize_1): Skip module-directivres.
+ (cp_parser_skip_to_end_of_statement): Likewise.
+ (cp_parser_skiup_to_end_of_block_or_statement): Likewise.
+ (cp_parser_translation_unit): Add module parsing calls.
+ (cp_parser_module_name, cp_parser_module_declaration): New.
+ (cp_parser_import_declaration, cp_parser_module_export): New.
+ (cp_parser_declaration): Add module export detection.
+ (cp_parser_template_declaration): Adjust 'export' error message.
+ (cp_parser_function_definition_after_declarator): Add
+ module-specific logic.
+ * module.cc (import_module, declare_module)
+ (maybe_check_all_macros): Stubs.
+
+2020-12-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97517
+ * cxx-pretty-print.c (cxx_pretty_printer::simple_type_specifier): Handle
+ NULLPTR_TYPE.
+ (pp_cxx_type_specifier_seq): Likewise.
+ (cxx_pretty_printer::type_id): Likewise.
+
+2020-12-09 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (duplicate_decls): Add module-specific redeclaration
+ logic.
+ (cxx_init_decl_processing): Export the global namespace, maybe
+ initialize modules.
+ (start_decl): Reject local-extern in a module, adjust linkage of
+ template var.
+ (xref_tag_1): Add module-specific redeclaration logic.
+ (start_enum): Likewise.
+ (finish_enum_value_list): Export unscoped members of an exported
+ enum.
+ (grokmethod): Implement p1779 linkage of in-class defined
+ functions.
+ * decl2.c (no_linkage_error): Imports are ok.
+ (c_parse_final_cleanups): Call fini_modules.
+ * lex.c (cxx_dup_lang_specific): Clear some module flags in the
+ copy.
+ * module.cc (module_kind): Define.
+ (module_may_redeclare, set_defining_module): Stubs.
+ (init_modules): Error on modules.
+ (fini_modules): Stub.
+ * rtti.c (push_abi_namespace): Save and reset module_kind.
+ (pop_abi_namespace): Restore module kind.
+ (build_dynamic_cast_1, tinfo_base_init): Adjust.
+ * semantics.c (begin_class_definition): Add module-specific logic.
+ (expand_or_defer_fn_1): Keep bodies of more fns when modules_p.
+
+2020-12-09 Tobias Burnus <tobias@codesourcery.com>
+
+ * parser.c (cp_parser_omp_allocate): New.
+ (cp_parser_omp_construct, cp_parser_pragma): Call it.
+
+2020-12-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/98019
+ * cvt.c (maybe_warn_nodiscard): Check c_inhibit_evaluation_warnings.
+
+2020-12-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/59238
+ * init.c (expand_default_init): Pass tf_no_cleanup when building
+ a TARGET_EXPR to go on the RHS of an INIT_EXPR.
+ * typeck.c (cp_build_modify_expr): Likewise.
+
+2020-12-08 Marek Polacek <polacek@redhat.com>
+
+ PR c++/98103
+ * constexpr.c (cxx_eval_dynamic_cast_fn): If the evaluating of vtable
+ yields a null pointer, give an error and return. Use objtype.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (layout_class_type): Call set_instantiating_module.
+ (build_self_reference): Likewise.
+ * decl.c (grokfndecl): Call set_originating_module.
+ (grokvardecl): Likewise.
+ (grokdeclarator): Likewise.
+ * pt.c (maybe_new_partial_specialization): Call
+ set_instantiating_module, propagate DECL_MODULE_EXPORT_P.
+ (lookup_template_class_1): Likewise.
+ (tsubst_function_decl): Likewise.
+ (tsubst_decl, instantiate_template_1): Likewise.
+ (build_template_decl): Propagate module flags.
+ (tsubst_template_dcl): Likewise.
+ (finish_concept_definition): Call set_originating_module.
+ * module.cc (set_instantiating_module, set_originating_module): Stubs.
+
+2020-12-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/96299
+ * cp-tree.h (build_new_op): Add overload that omits some parms.
+ (genericize_spaceship): Add location_t parm.
+ * constexpr.c (cxx_eval_binary_expression): Pass it.
+ * cp-gimplify.c (genericize_spaceship): Pass it.
+ * method.c (genericize_spaceship): Handle class-type arguments.
+ (build_comparison_op): Fall back to op</== when appropriate.
+
+2020-12-08 Jason Merrill <jason@redhat.com>
+
+ * call.c (build_new_op_1): Set *overload for ambiguity.
+ (build_new_method_call_1): Likewise.
+
+2020-12-08 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * decl2.c: (is_atomic_expensive_p): New helper function.
+ (build_atomic_load_byte): Rename to...
+ (build_atomic_load_type): ... and add new parameter type.
+ (get_guard_cond): Skip the atomic here if that is expensive.
+ Use the correct type for the atomic load on certain targets.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct tinst_level): Add path & visible fields.
+ (build_cdtor_clones): Declare.
+ (match_mergeable_specialization): Use a spec_entry, add insert parm.
+ * class.c (build_cdtor_clones): Externalize.
+ * pt.c (push_tinst_level_loc): Clear new fields.
+ (match_mergeable_specialization): Adjust API.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * decl2.c (start_objects): Refactor and adjust for named module
+ initializers.
+ (finish_objects): Likewise.
+ (generate_ctor_or_dtor_function): Likewise.
+ * module.cc (module_initializer_kind)
+ (module_add_import_initializers): Stubs.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * Make-lang.in (MODULE_VERSION): Override when DEVPHASE not empty.
+ * module.cc: Comment.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (mangle_module_substitution, mangle_identifier)
+ (mangle_module_global_init): Declare.
+ * mangle.c (struct globals): Add mod field.
+ (mangle_module_substitution, mangle_identifier)
+ (mangle_module_global_init): Define.
+ (write_module, maybe_write_module): New.
+ (write_name): Call it.
+ (start_mangling): Clear mod field.
+ (finish_mangling_internal): Adjust.
+ * module.cc (mangle_module, mangle_module_fini)
+ (get_originating_module): Stubs.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (module_token_pre, module_token_cdtor)
+ (module_token_lang): Declare.
+ * lex.c: Include langhooks.
+ (struct module_token_filter): New.
+ * cp-tree.h (module_token_pre, module_token_cdtor)
+ (module_token_lang): Define.
+ * module.cc (get_module, preprocess_module, preprocessed_module):
+ Nop stubs.
+
+2020-12-08 Nathan Sidwell <nathan@acm.org>
+
+ * Make-lang.in (MODULE_VERSION): Define.
+ * module.cc: Add includes.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98187
+ * parser.c (cp_parser_omp_parallel): For parallel master with
+ -fopenmp-simd only, just call cp_parser_omp_master instead of
+ wrapping it in OMP_PARALLEL.
+
+2020-12-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/98043
+ * decl.c (pop_switch): If SWITCH_STMT_TYPE is a scoped enum type,
+ set it to the type of SWITCH_STMT_COND.
+
+2020-12-07 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (build_cplus_array_type): Add defaulted DEP parm.
+ * tree.c (set_array_type_common): Add DEP parm.
+ (build_cplus_array_type): Add DEP parm, determine dependency if
+ needed. Mark dependency of new types.
+ (cp_build_qualified_type_real): Adjust array-building call, assert
+ no surprising dependency.
+ (strip_typedefs): Likewise.
+
+2020-12-07 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98116
+ * typeck.c (structural_comptypes): Move early outs to comptype.
+ Always check template-alias match when comparing_specializations.
+ (comptypes): Do early out checking here.
+
+2020-12-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97093
+ * constraint.cc (parameter_mapping_equivalent_p): Add some
+ sanity checks. Clarify comment.
+ (tsubst_nested_requirement): Always perform satisfaction
+ quietly first. If that yields an erroneous result, emit a
+ context message and replay satisfaction noisily with the
+ diagnostic normal form.
+ (finish_nested_requirement): Normalize the constraint-expression
+ twice, once with diagnostic information and once without. Store
+ them in a TREE_LIST within the TREE_TYPE.
+ (diagnose_nested_requirement): When replaying satisfaction, use
+ the diagnostic normal form instead of renormalizing on the spot.
+
+2020-12-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97093
+ * constraint.cc (struct sat_info): Define.
+ (tsubst_nested_requirement): Pass a sat_info object to
+ satisfy_constraint.
+ (satisfy_constraint_r): Take a sat_info argument instead of
+ subst_info.
+ (satisfy_conjunction): Likewise.
+ (satisfy_disjunction): Likewise. Instead of first evaluating
+ each branch quietly, evaluate each branch only with
+ unsatisfaction diagnostics disabled. Exit early if evaluation
+ of a branch returns error_mark_node.
+ (satisfy_atom): Take a sat_info argument instead of subst_info.
+ Fix a comment. Check diagnose_unsatisfaction_p() instead of
+ noisy() before replaying a substitution failure.
+ (satisfy_constraint): Take a sat_info argument instead of
+ subst_info.
+ (satisfy_associated_constraints): Likewise.
+ (satisfy_constraint_expression): Likewise.
+ (satisfy_declaration_constraints): Likewise.
+ (constraint_satisfaction_value): Likewise and adjust
+ accordingly. Fix formatting.
+ (constraints_satisfied_p): Pass a sat_info object to
+ constraint_satisfaction_value.
+ (evaluate_concept_check): Pass a sat_info object to
+ satisfy_constraint_expression.
+ (diagnose_nested_requirement): Likewise.
+ (diagnose_constraints): Pass an appropriate sat_info object to
+ constraint_satisfaction_value.
+
+2020-12-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98122
+ * constexpr.c (cxx_union_active_member): New function.
+ (cxx_fold_indirect_ref_1): Add ctx argument, pass it through to
+ recursive call. Handle UNION_TYPE.
+ (cxx_fold_indirect_ref): Add ctx argument, pass it to recursive calls
+ and cxx_fold_indirect_ref_1.
+ (cxx_eval_indirect_ref): Adjust cxx_fold_indirect_ref calls.
+
+2020-12-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/93083
+ * pt.c (convert_template_argument): Handle equivalent placeholders.
+ (do_class_deduction): Look through EXPR_PACK_EXPANSION, too.
+
+2020-12-04 Jason Merrill <jason@redhat.com>
+
+ * decl2.c (clear_consteval_vfns): Remove *.
+ * pt.c (do_auto_deduction): Remove *.
+ * parser.c (cp_parser_late_parsing_default_args): Change loop
+ to use range 'for'.
+
+2020-12-04 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98116
+ * cp-tree.h (comparing_typenames): Delete.
+ (cplus_build_array_type): Remove default parm.
+ * pt.c (comparing_typenames): Delete.
+ (spec_hasher::equal): Don't increment it.
+ * tree.c (set_array_type_canon): Remove dep parm.
+ (build_cplus_array_type): Remove dep parm changes.
+ (cp_build_qualified_type_real): Remove dependent array type
+ changes.
+ (strip_typedefs): Likewise.
+ * typeck.c (structural_comptypes): Revert comparing_typename
+ changes.
+
+2020-12-04 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h: Add various inline module state predicates, and
+ declare the API that will be provided by modules.cc
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/80780
+ * cp-gimplify.c (fold_builtin_source_location): Use 2 instead of 0
+ as last argument to cxx_printable_name.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (releasing_vec::operator[]): Change parameter type to
+ ptrdiff_t.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (OVL_EXPORT): New.
+ (class ovl_iterator): Add get_using, exporting_p.
+ * tree.c (ovl_insert): Extend using_or_hidden meaning to include
+ an exported using.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_UNINSTANTIATED_TEMPLATE_FRIEND): New.
+ * pt.c (push_template_decl): Set it.
+ (tsubst_friend_function): Clear it.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (make_unbound_class_template_raw): Declare.
+ (canonical_type_parameter): Declare.
+ * decl.c (make_unbound_class_template_raw): Break out of ...
+ (make_unboud_class_template): ... here. Call it.
+ * pt.c (canonical_type_parameter): Externalize. Refactor & set
+ structural_equality for type parms.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98107
+ * tree.c (build_cplus_array_type): Mark dependency of new variant.
+ (cp_build_qualified_type_real, strip_typedefs): Assert
+ TYPE_DEPENDENT_P_VALID, or not a dependent type.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * cp-tree.h (cp_build_bit_cast): Declare.
+ * cp-tree.def (BIT_CAST_EXPR): New tree code.
+ * cp-objcp-common.c (names_builtin_p): Handle RID_BUILTIN_BIT_CAST.
+ (cp_common_init_ts): Handle BIT_CAST_EXPR.
+ * cxx-pretty-print.c (cxx_pretty_printer::postfix_expression):
+ Likewise.
+ * parser.c (cp_parser_postfix_expression): Handle
+ RID_BUILTIN_BIT_CAST.
+ * semantics.c (cp_build_bit_cast): New function.
+ * tree.c (cp_tree_equal): Handle BIT_CAST_EXPR.
+ (cp_walk_subtrees): Likewise.
+ * pt.c (tsubst_copy): Likewise.
+ * constexpr.c (check_bit_cast_type, cxx_eval_bit_cast): New functions.
+ (cxx_eval_constant_expression): Handle BIT_CAST_EXPR.
+ (potential_constant_expression_1): Likewise.
+ * cp-gimplify.c (cp_genericize_r): Likewise.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * parser.c (cp_parser_primary_expression): Distinguish
+ parms from vars in error.
+ (cp_parser_late_parsing_default_args): Pushdecl parms
+ as we go.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * name-lookup.c (begin_scope): Set immediate_fn_ctx_p.
+ * parser.c (cp_parser_late_parsing_default_args): Push
+ sk_function_parms scope.
+
+2020-12-03 Peter Bergner <bergner@linux.ibm.com>
+
+ PR c++/97947
+ * typeck2.c (digest_init_r): Handle OPAQUE_TYPE as an aggregate type.
+
+2020-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/80780
+ PR c++/93093
+ * cp-tree.h (source_location_current_p): Declare.
+ * tree.c (source_location_current_p): New function.
+ * call.c (immediate_invocation_p): New function.
+ (build_over_call): Use it to resolve LWG3396.
+ * constexpr.c (cxx_eval_builtin_function_call): Temporarily set
+ current_function_decl from ctx->call->fundef->decl if any.
+ * cp-gimplify.c (cp_genericize_r) <case CALL_EXPR>: Fold calls
+ to immediate function std::source_location::current ().
+
+2020-12-02 Jason Merrill <jason@redhat.com>
+
+ * decl.c (grokdeclarator): Improve diagnostic for
+ disallowed CTAD placeholder.
+
+2020-12-02 Jason Merrill <jason@redhat.com>
+
+ * decl.c (check_initializer): Also look through STMT_EXPR
+ and BIND_EXPR.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (comparing_typenames): Declare.
+ * pt.c (comparing_typenames): Define.
+ (spec_hasher::equal): Increment it around comparisons.
+ * typeck.c (structural_comptypes): Adjust TYPENAME resolution
+ check.
+
+2020-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97975
+ * constexpr.c (fold_non_dependent_init): Add a tree parameter.
+ Use it.
+ * cp-tree.h (fold_non_dependent_init): Add a tree parameter with
+ a default value.
+ * typeck2.c (store_init_value): Call fold_non_dependent_expr
+ only when checking the initializer for constexpr variables.
+ Call fold_non_dependent_init instead of maybe_constant_init.
+
+2020-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97187
+ PR c++/97993
+ * pt.c (tsubst_copy_and_build) <case NEW_EXPR>: Return error_mark_node
+ if init is erroneous.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_MODULE_PURVIEW_P, DECL_MODULE_IMPORT_P)
+ (DECL_MODULE_ENTITY_P): New.
+ (DECL_MODULE_PENDING_SPECIALIZATIONS_P): New.
+ (DECL_MODULE_PENDING_MEMBERS_P): New.
+ (DECL_MODULE_ATTACHMENTS_P): New.
+ (DECL_MODULE_EXPORT_P): New.
+ (struct lang_decl_base): Shrink sel field. Add new
+ module-specific fields.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_TINFO_P): Also for TYPE_DECLs.
+ (get_tinfo_decl_direct): Declare.
+ (get_pseudo_tinfo_index, get_pseudo_tinfo_type): Declare.
+ * rtti.c (get_tinfo_decl_direct): Externalize.
+ (get_tinfo_desc): Set DECL_TINFO_P on the typedef.
+ (get_pseudo_tinfo_index, get_pseudo_tinfo_type): New.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (maybe_add_lang_decl_raw, maybe_add_lang_type_raw):
+ Declare.
+ * lex.c (maybe_add_lang_decl_raw, maybe_add_lang_type_raw):
+ Externalize, reformat.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (build_cplus_array_type): Add defaulted DEP parm.
+ * tree.c (set_array_type_common): Add DEP parm.
+ (build_cplus_array_type): Add DEP parm, determine dependency if
+ needed.
+ (cp_build_qualified_type_real): Adjust array-building call.
+ (strip_typedefs): Likewise.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * ptree.c (cxx_print_xnode): Increase binding-vector prefix size.
+
+2020-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.def (BINDING_VECTOR): New.
+ * name-lookup.h (struct binding_slot): New.
+ (BINDING_VECTOR_SLOTS_PER_CLUSTER): New.
+ (struct binding_index, struct binding_cluster): New.
+ (BINDING_VECTOR_ALLOC_CLUSTERS, BINDING_VECTOR_CLUSTER_BASE)
+ (BINDING_VECTOR_CLUSTER): New.
+ (struct tree_binding_vec): New.
+ (BINDING_VECTOR_NAME, BINDING_VECTOR_GLOBAL_DUPS_P)
+ (BINDING_VECTOR_PARTITION_DUPS_P): New.
+ (BINDING_BINDING_GLOBAL_P, BINDING_BINDING_PARTITION_P): New.
+ (BINDING_VECTOR_PENDING_SPECIALIZATIONS)
+ (BINDING_VECTOR_PENDING_IS_HEADER_P)
+ (BINDING_VECTOR_PENDING_IS_PARTITION_P): New.
+ * cp-tree.h (enum cp_tree_node_structure_enum): Add
+ TS_CP_BINDING_VECTOR.
+ (union lang_tree_node): Add binding_vec field.
+ (make_binding_vec): Declare.
+ (named_decl_hash::hash, named_decl_hash::equal): Check for binding
+ vector.
+ * decl.c (cp_tree_node_structure): Add BINDING_VECTOR case.
+ * ptree.c (cxx_print_xnode): Add BINDING_VECTOR case.
+ * tree.c (make_binding_vec): New.
+
+2020-12-01 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/98054
+ * cxx-pretty-print.c (pp_cxx_trait_expression):
+ Add support for __is_nothrow_{assignable,constructible}.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98072
+ * parser.c (cp_parser_omp_depobj): Suppress location wrappers when
+ parsing depend clause.
+
+2020-12-01 Nathan Sidwell <nathan@acm.org>
+
+ * lex.c (init_reswords): Maybe enable module keywords.
+
+2020-12-01 Nathan Sidwell <nathan@acm.org>
+
+ * lang-specs.h: Add module-related options.
+
+2020-12-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_declaration): Add a not about where
+ attributes may be placed.
+
+2020-11-27 Martin Sebor <msebor@redhat.com>
+
+ * error.c (add_quotes): Revert previous change and use pragma to
+ suppress -Wformat-diag.
+
+2020-11-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * g++spec.c (TIMELIB, TIME_LIBRARY): Remove.
+ (lang_specific_driver): Remove TIME_LIBRARY handling.
+
+2020-11-26 Thomas Schwinge <thomas@codesourcery.com>
+
+ * parser.c (cp_parser_omp_var_list_no_open): Assert that array
+ section's 'low_bound', 'length' are not location wrapper nodes.
+ (cp_parser_oacc_all_clauses, cp_parser_oacc_cache): Instantiate
+ 'auto_suppress_location_wrappers'.
+
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR bootstrap/94982
+ * constraint.cc (debug_argument_list): Avoid -Wformat-diag.
+ * error.c (function_category): Same.
+ (print_template_differences): Same.
+ * logic.cc (debug): Same.
+ * name-lookup.c (lookup_using_decl): Same.
+ * parser.c (maybe_add_cast_fixit): Same.
+ (cp_parser_template_introduction): Same.
+ * typeck.c (access_failure_info::add_fixit_hint): Same.
+
+2020-11-25 Thomas Schwinge <thomas@codesourcery.com>
+
+ * pt.c (tsubst_omp_clauses): Handle 'OMP_CLAUSE__CACHE_'.
+ (tsubst_expr): Handle 'OACC_CACHE'.
+
+2020-11-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/97899
+ * typeck2.c (store_init_value): Don't split_nonconstant_init in a
+ template.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96929
+ * constexpr.c (cxx_eval_binary_expression): For shifts by constant
+ with MSB set, emulate older wide_int_binop behavior to preserve
+ diagnostics and -fpermissive behavior.
+
+2020-11-23 Nathan Sidwell <nathan@acm.org>
+
+ * module.cc: New dummy file.
+ * Make-lang.in: Add rules to build module.o
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * decl.c (start_decl): Set DECL_INITIAL for initialized decls
+ before attribute processing.
+
+2020-11-23 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR c++/97904
+ * pt.c (tsubst): Use verify_type_context to check the type
+ of an array element.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94695
+ * parser.c (warn_for_range_copy): Warn when the loop variable is
+ initialized with a value of a different type resulting in a copy.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97846
+ * constexpr.c (potential_constant_expression_1): Reject
+ LABEL_EXPRs that use non-artifical LABEL_DECLs.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97881
+ * parser.c (warn_about_ambiguous_parse): Only assume "int" if we
+ actually saw any type-specifiers.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97839
+ * parser.c (cp_parser_lambda_declarator_opt): Don't require ().
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97427
+ * constexpr.c (cxx_set_object_constness): New function.
+ (cxx_eval_call_expression): Set new_obj for destructors too.
+ Call cxx_set_object_constness to set/unset TREE_READONLY of
+ the object under construction/destruction.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * error.c (dump_type): Handle opaque types.
+ (dump_type_prefix): Handle opaque types.
+ (dump_type_suffix): Handle opaque types.
+ (dump_expr): Handle opaque types.
+ * pt.c (tsubst): Allow opaque types in templates.
+ (unify): Allow opaque types in templates.
+ * typeck.c (structural_comptypes): Handle comparison
+ of opaque types.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (c++.serial): Change from goal to a variable.
+ (.PHONY): Drop c++.serial and c++.prev.
+ (cc1plus$(exeext)): Depend on $(c++.serial) rather than c++.serial.
+
+2020-11-19 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct spec_entry): Moved from pt.c.
+ (walk_specializations, match_mergeable_specialization)
+ (get_mergeable_specialization_flags)
+ (add_mergeable_specialization): Declare.
+ * pt.c (struct spec_entry): Moved to cp-tree.h.
+ (walk_specializations, match_mergeable_specialization)
+ (get_mergeable_specialization_flags)
+ (add_mergeable_specialization): New.
+
+2020-11-19 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct constexpr_fundef): Moved from constexpr.c.
+ (maybe_save_constexpr_fundef): Declare.
+ (register_constexpr_fundef): Take constexpr_fundef object, return
+ void.
+ * decl.c (mabe_save_function_definition): Delete, functionality
+ moved to maybe_save_constexpr_fundef.
+ (emit_coro_helper, finish_function): Adjust.
+ * constexpr.c (struct constexpr_fundef): Moved to cp-tree.h.
+ (constexpr_fundef_hasher::equal): Constify.
+ (constexpr_fundef_hasher::hash): Constify.
+ (retrieve_constexpr_fundef): Make non-static.
+ (maybe_save_constexpr_fundef): Break out checking and duplication
+ from ...
+ (register_constexpr_fundef): ... here. Just register the constexpr.
+
+2020-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97523
+ * init.c (build_new): When value-initializing an array new,
+ leave the INIT as an empty vector.
+
+2020-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97895
+ * pt.c (do_auto_deduction): Don't crash when the constructor has
+ zero elements.
+
+2020-11-19 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97905
+ * decl.c (duplicate_decls): Relax new assert.
+
+2020-11-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_valid_prefix_attributes): Check
+ for empty attributes.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (c++.serial): New goal.
+ (.PHONY): Add c++.serial c++.prev.
+ (cc1plus$(exeext)): Depend on c++.prev. Call LINK_PROGRESS.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97877
+ * decl.c (duplicate_decls): Deal with duplicated DECL_LOCAL_DECL_P
+ decls. Extend decl_lang_specific checking assert.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (enum cp_tree_index): Reorder to place lazy fields
+ after newly-added CPTI_MODULE_HWM.
+
+2020-11-17 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/97871
+ * parser.c (cp_parser_declaration): Remove checking assert.
+
+2020-11-15 Jason Merrill <jason@redhat.com>
+
+ * decl.c (cp_finish_decl): Only check abstractness on definition.
+ (require_complete_types_for_parms): Check abstractness here.
+ (create_array_type_for_decl): Not here.
+ (grokdeclarator, grokparms, complete_vars): Not here.
+ * pt.c (tsubst, tsubst_arg_types, tsubst_function_type): Not here.
+ * typeck2.c (struct pending_abstract_type): Remove.
+ (struct abstract_type_hasher): Remove.
+ (abstract_pending_vars, complete_type_check_abstract): Remove.
+ (abstract_virtuals_error_sfinae): Handle arrays.
+ * call.c (conv_is_prvalue): Split out from...
+ (conv_binds_ref_to_prvalue): ...here.
+ (implicit_conversion_1): Rename from implicit_conversion.
+ (implicit_conversion): An abstract prvalue is bad.
+ (convert_like_internal): Don't complain if expr is already
+ error_mark_node.
+
+2020-11-13 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (USING_DECL_UNRELATED_P): New.
+ (CONST_DECL_USING_P): New.
+ * class.c (handle_using_decl): If USING_DECL_UNRELATED_P,
+ clone the CONST_DECL.
+ * name-lookup.c (supplement_binding_1): A clone hides its
+ using-declaration.
+ (lookup_using_decl): Rewrite to separate lookup and validation.
+ (do_class_using_decl): Adjust.
+ (finish_nonmember_using_decl): Adjust.
+ * parser.c (make_location): Add cp_token overload.
+ (finish_using_decl): Split out from...
+ (cp_parser_using_declaration): ...here. Don't look through enums.
+ (cp_parser_using_enum): New.
+ (cp_parser_block_declaration): Call it.
+ (cp_parser_member_declaration): Call it.
+ * semantics.c (finish_id_expression_1): Handle enumerator
+ used from class scope.
+
+2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * parser.c (cp_parser_asm_definition): Parse outputs for asm
+ goto too.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * parser.c (cp_parser_objc_class_interface): Pass the
+ location of the class name to the interface declaration.
+
+2020-11-13 Patrick Palka <ppalka@redhat.com>
+
+ * semantics.c (finish_compound_literal): Don't wrap the original
+ compound literal in a TARGET_EXPR when inside a template.
+
+2020-11-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97790
+ * constexpr.c (cxx_eval_constant_expression) <case CLEANUP_POINT_EXPR,
+ case TRY_FINALLY_EXPR, case CLEANUP_STMT>: Don't pass jump_target to
+ cxx_eval_constant_expression when evaluating the cleanups.
+
+2020-11-11 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_declaration): Unless we are compiling for
+ Ojective-C++, warn about and discard any attributes that prefix
+ a linkage specification.
+
+2020-11-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ * mangle.c (write_expression): Mangle __alignof_ differently
+ from alignof when the ABI version is at least 15.
+
+2020-11-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ * cp-tree.h (cxx_sizeof_or_alignof_expr): Add bool parameter.
+ * decl.c (fold_sizeof_expr): Pass false to
+ cxx_sizeof_or_alignof_expr.
+ * parser.c (cp_parser_unary_expression): Pass std_alignof to
+ cxx_sizeof_or_alignof_expr.
+ * pt.c (tsubst_copy): Pass false to cxx_sizeof_or_alignof_expr.
+ (tsubst_copy_and_build): Pass std_alignof to
+ cxx_sizeof_or_alignof_expr.
+ * typeck.c (cxx_alignof_expr): Add std_alignof bool parameter
+ and pass it to cxx_sizeof_or_alignof_type. Set ALIGNOF_EXPR_STD_P
+ appropriately.
+ (cxx_sizeof_or_alignof_expr): Add std_alignof bool parameter
+ and pass it to cxx_alignof_expr. Assert op is either
+ SIZEOF_EXPR or ALIGNOF_EXPR.
+
+2020-11-11 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97518
+ * pt.c (tsubst_qualified_id): Use EXPR_LOCATION of the qualified-id.
+ Use it to maybe_wrap_with_location the final expression.
+
+2020-11-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97518
+ * cp-tree.h (finish_static_assert): Adjust declaration.
+ * parser.c (cp_parser_static_assert): Pass false to
+ finish_static_assert.
+ * pt.c (tsubst_expr): Pass true to finish_static_assert.
+ * semantics.c (find_failing_clause_r): New function.
+ (find_failing_clause): New function.
+ (finish_static_assert): Add a bool parameter. Use
+ iloc_sentinel. Call contextual_conv_bool instead of
+ perform_implicit_conversion_flags. Don't check for INTEGER_CST before
+ calling integer_zerop. Call find_failing_clause and maybe use its
+ location. Print the original condition or the failing clause if
+ SHOW_EXPR_P.
+
+2020-11-10 Strager Neds <strager.nds@gmail.com>
+
+ * decl.c (duplicate_decls): Use new overload of
+ set_decl_section_name.
+ * method.c (use_thunk): Same.
+ * optimize.c (maybe_clone_body): Same.
+ * coroutines.cc (act_des_fn): Same.
+
+2020-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97748
+ * cvt.c (convert_to_void): Check (complain & tf_warning) in the outer
+ if rather than twice times in the inner one. Use warn_if_unused_value.
+ Formatting fix.
+
+2020-11-10 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * parser.c (cp_parser_omp_target_data): Add use of
+ new c_omp_adjust_map_clauses function. Add GOMP_MAP_ATTACH_DETACH as
+ handled map clause kind.
+ (cp_parser_omp_target_enter_data): Likewise.
+ (cp_parser_omp_target_exit_data): Likewise.
+ (cp_parser_omp_target): Likewise.
+ * semantics.c (handle_omp_array_sections): Adjust COMPONENT_REF case to
+ use GOMP_MAP_ATTACH_DETACH map kind for C_ORT_OMP region type. Fix
+ interaction between reference case and attach/detach.
+ (finish_omp_clauses): Adjust bitmap checks to allow struct decl and
+ same struct field access to co-exist on OpenMP construct.
+
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ DR 1914
+ * parser.c (cp_parser_check_std_attribute): Return bool. Add a
+ location_t parameter. Return true if the attribute wasn't duplicated.
+ Give a warning instead of an error. Check more attributes.
+ (cp_parser_std_attribute_list): Don't add duplicated attributes to
+ the list. Pass location to cp_parser_check_std_attribute.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (norm_info::norm_info): Initialize orig_decl.
+ (norm_info::orig_decl): New data member.
+ (normalize_atom): When caching an atom for the first time,
+ compute a list of template parameters used in the targets of the
+ parameter mapping and store it in the TREE_TYPE of the mapping.
+ (get_normalized_constraints_from_decl): Set current_function_decl
+ appropriately when normalizing. As an optimization, don't
+ set up a push_nested_class_guard when decl has no constraints.
+ (sat_hasher::hash): Use this list to hash only the template
+ arguments that are relevant to the atom.
+ (satisfy_atom): Use this list to compare only the template
+ arguments that are relevant to the atom.
+ * pt.c (keep_template_parm): Do a sanity check on the parameter's
+ index when flag_checking.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * cp-tree.h (ATOMIC_CONSTR_MAP_INSTANTIATED_P): Define this flag
+ for ATOMIC_CONSTRs.
+ * constraint.cc (sat_hasher::hash): Use hash_atomic_constraint
+ if the flag is set, otherwise keep using a pointer hash.
+ (sat_hasher::equal): Return false if the flag's setting differs
+ on two atoms. Call atomic_constraints_identical_p if the flag
+ is set, otherwise keep using a pointer equality test.
+ (satisfy_atom): After instantiating the parameter mapping, form
+ another ATOMIC_CONSTR using the instantiated mapping and query
+ the cache again. Cache the satisfaction value of both atoms.
+ (diagnose_atomic_constraint): Simplify now that the supplied
+ atom has an instantiated mapping.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (atom_cache): Define this deletable hash_table.
+ (normalize_atom): Use it to cache ATOMIC_CONSTRs when not
+ generating diagnostics.
+ (sat_hasher::hash): Use htab_hash_pointer instead of
+ hash_atomic_constraint.
+ (sat_hasher::equal): Test for pointer equality instead of
+ atomic_constraints_identical_p.
+ * cp-tree.h (struct atom_hasher): Moved and renamed from ...
+ * logic.cc (struct constraint_hash): ... here.
+ (clause::m_set): Adjust accordingly.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/93907
+ * constraint.cc (tsubst_parameter_mapping): Also canonicalize
+ the type arguments of a TYPE_ARGUMENT_PACk.
+
+2020-11-09 Jason Merrill <jason@redhat.com>
+
+ * pt.c (tsubst): Replace *_ARGUMENT_PACK code with
+ a call to tsubst_argument_pack.
+
+2020-11-09 Jason Merrill <jason@redhat.com>
+
+ * class.c (handle_using_decl): Add an iloc_sentinel.
+
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97762
+ * parser.c (warn_about_ambiguous_parse): Handle the case when
+ there is no type in the decl-specifiers.
+
+2020-11-09 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (LOOKUP_FOUND_P): Add ENUMERAL_TYPE.
+ * name-lookup.c (class name_lookup): Add comments.
+ (name_lookup::adl_namespace_only): Replace with ...
+ (name_lookup::adl_class_fns): ... this and ...
+ (name_lookup::adl_namespace_fns): ... this.
+ (name_lookup::adl_namespace): Deal with inline nests here.
+ (name_lookup::adl_class): Complete the type here.
+ (name_lookup::adl_type): Call broken-out enum ..
+ (name_lookup::adl_enum): New. No need to call the namespace adl
+ if it is class-scope.
+ (name_lookup::search_adl): Iterate over collected scopes here.
+
+2020-11-09 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (lookup_qualified_name): Expose an overload of a
+ singleton with known type.
+ (lookup_name_1): Just check the overload's type to expose it.
+ * parser.c (cp_parser_lookup_name): Do not do that check here.
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_at_property_declaration): Handle
+ class keywords in @property attribute context.
+
+2020-11-06 Marek Polacek <polacek@redhat.com>
+
+ PR c++/81660
+ * except.c (can_convert_eh): Change the return type to bool. If
+ the type TO and FROM are the same, return true.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_at_property_declaration):
+ Improve parsing fidelity. Associate better location info
+ with @property attributes. Clean up the interface to
+ objc_add_property_declaration ().
+
+2020-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/67453
+ * decl.c (duplicate_decls): Propagate DECL_ATTRIBUTES and
+ DECL_PRESERVE_P from olddecl to its clones if any.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_UNDECLARED_BUILTIN_P): Delete.
+ * cp-objcp-common.c (names_bultin_p): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+ * decl.c (decls_match): Likewise. Replace
+ DECL_UNDECLARED_BUILTIN_P with DECL_IS_UNDECLARED_BUILTIN.
+ (duplicate_decls): Likewise.
+ * decl2.c (collect_source_refs): Likewise.
+ * name-lookup.c (anticipated_builtin_p, print_binding_level)
+ (do_nonmember_using_decl): Likewise.
+ * pt.c (builtin_pack_fn_p): Likewise.
+ * typeck.c (error_args_num): Likewise.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_template_declaration): Adjust 'export' warning.
+ (cp_parser_explicit_specialization): Remove unneeded bool setting.
+
+2020-11-06 Jan Hubicka <jh@suse.cz>
+
+ * tree.c (cp_fix_function_decl_p): Do not access ipa_ref_list dirrectly.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * parser.c (cp_parser_omp_atomic): Add openacc parameter and update
+ OpenACC matching.
+ (cp_parser_omp_construct): Update call.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ * except.c (check_handlers_1): Add auto_diagnostic_group.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/78209
+ * pt.c (do_auto_deduction): If init is REFERENCE_REF_P, use its
+ first operand.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97675
+ * except.c (check_handlers_1): Use OPT_Wexceptions for the
+ warning. Use inform for the second part of the warning.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/25814
+ * cp-tree.h (enum cp_tree_index): Add CPTI_EXPLICIT_VOID_LIST.
+ (explicit_void_list_node): Define.
+ (PARENTHESIZED_LIST_P): New macro.
+ (struct cp_declarator): Add function::parens_loc.
+ * decl.c (cxx_init_decl_processing): Initialize explicit_void_list_node.
+ (grokparms): Also break when explicit_void_list_node.
+ * parser.c (make_call_declarator): New location_t parameter. Use it
+ to set declarator->u.function.parens_loc.
+ (cp_parser_lambda_declarator_opt): Pass UNKNOWN_LOCATION to
+ make_call_declarator.
+ (warn_about_ambiguous_parse): New function.
+ (cp_parser_init_declarator): Call warn_about_ambiguous_parse.
+ (cp_parser_declarator): Set *parenthesized_p to false rather than to
+ true.
+ (cp_parser_direct_declarator): Create a location for the function's
+ parentheses and pass it to make_call_declarator.
+ (cp_parser_parameter_declaration_clause): Return explicit_void_list_node
+ for (void).
+ (cp_parser_parameter_declaration_list): Set PARENTHESIZED_LIST_P
+ in the parameters tree.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97670
+ * semantics.c (finish_omp_clauses): Look through array reductions to
+ find underlying decl to clear in the aligned_head bitmap. Use
+ DECL_UID (t) instead of DECL_UID (OMP_CLAUSE_DECL (c)) when clearing
+ in the bitmap. Only diagnose errors about allocate vars not being
+ privatized on the same construct on allocate clause if it has
+ a DECL_P OMP_CLAUSE_DECL.
+
+2020-11-04 Iain Sandoe <iain@sandoe.co.uk>
+
+ * constexpr.c (potential_constant_expression_1): Handle
+ expressions known to be non-constant for Objective-C.
+
+2020-11-03 Jason Merrill <jason@redhat.com>
+
+ * tree.c (is_byte_access_type): Don't use char_type_p.
+
+2020-11-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97663
+ * parser.c (cp_parser_init_declarator): Don't try to parse
+ C++17 deduction guides if there are any type specifiers even when
+ type is NULL.
+
+2020-11-03 Kamlesh Kumar <kamleshbhalui@gmail.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/97453
+ DR2303
+ * pt.c (get_template_base): Consider closest base in template
+ deduction when base of base also matches.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (tsubst_expr): Simplify using decl instantiation, add
+ asserts.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (copy_fndecl_with_name): Always not top level.
+ (build_cdtor_clones): Add update_methods parm, use it to
+ conditionally update the method vec. Return void
+ (clone_cdtor): Adjust.
+ (clone_constructors_and_destructors): Adjust comment.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (primary_template_specialization_p): Use
+ VAR_OR_FUNCTION_DECL_P.
+ (tsubst_template_decl): Check for FUNCTION_DECL, not !TYPE && !VAR
+ for registering a specialization.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (fixup_deferred_exception_variants): Declare.
+ * parser.c (cp_parser_class_specifier_1): Call it when
+ completing deferred parses rather than creating a variant.
+ (cp_parser_member_declaration): Move comment from ...
+ (cp_parser_noexcept_specification_opt): ... here. Refactor the
+ deferred parse.
+ * tree.c (fixup_deferred_exception_variants): New.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (tsubst_lambda_expr): Reorder extra-scope handling to match
+ the non-template case.
+ (instantiate_body): Move a couple of declarations to their
+ initializers.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (duplicate_decls): Return error_mark_node fo extern-c
+ mismatch.
+
+2020-11-03 Marek Polacek <polacek@redhat.com>
+
+ * constexpr.c (potential_constant_expression_1): Treat
+ __PRETTY_FUNCTION__ inside a template function as
+ potentially-constant.
+ * pt.c (uses_template_parms): Call
+ instantiation_dependent_expression_p instead of
+ value_dependent_expression_p.
+ (instantiation_dependent_expression_p): Check
+ potential_constant_expression before calling
+ value_dependent_expression_p.
+
+2020-11-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97632
+ * init.c (build_new_1): Disable -Winit-list-lifetime for an unevaluated
+ operand.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * tree.c (bind_template_template_parm): Mark the parm as a
+ template parm.
+ (cp_tree_equal): Refactor CALL_EXPR. Use comp_template_args for
+ TREE_VECs.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * rtti.c (init_rtti_processing): Move var decl to its init.
+ (get_tinfo_decl): Likewise. Break out creation to called helper
+ ...
+ (get_tinfo_decl_direct): ... here.
+ (build_dynamic_cast_1): Move var decls to their initializers.
+ (tinfo_base_init): Set decl's location to BUILTINS_LOCATION.
+ (get_tinfo_desc): Only push ABI namespace when needed. Set type's
+ context.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (start_decl_1): Refactor declarations. Fixup some
+ whitespace.
+ (lookup_and_check_tag): Fixup some whitespace.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (duplicate_decls): Refactor some template & builtin
+ handling.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct cxx_int_tree_map): Delete.
+ (struct cxx_int_tree_map_hasher): Delete.
+ * cp-gimplify.c (cxx_int_tree_map_hasher::equal): Delete.
+ (cxx_int_tree_map_hasher::hash): Delete.
+
+2020-11-02 Patrick Palka <ppalka@redhat.com>
+
+ * class.c (finish_struct_1): Don't call clear_satisfaction_cache.
+ * constexpr.c (clear_cv_and_fold_caches): Likewise. Remove bool
+ parameter.
+ * constraint.cc (clear_satisfaction_cache): Remove definition.
+ * cp-tree.h (clear_satisfaction_cache): Remove declaration.
+ (clear_cv_and_fold_caches): Remove bool parameter.
+ * typeck2.c (store_init_value): Remove argument to
+ clear_cv_and_fold_caches.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_at_property_declaration): Use any
+ exisiting syntax error to suppress complaints about a missing
+ closing parenthesis in parsing property attributes.
+
+2020-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (finish_omp_clauses) <case OMP_CLAUSE_ALLOCATE>: Handle
+ non-static members in methods.
+ * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_ALLOCATE.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ DR 625
+ PR c++/97479
+ * parser.c (cp_parser_type_id_1): Reject using auto as
+ a template-argument in C++20.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ PR c++/93107
+ * pt.c (do_auto_deduction): Call resolve_nondeduced_context for
+ the elements of a { } list.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ * typeck.c (do_warn_enum_conversions): Don't warn for SPACESHIP_EXPR.
+ (cp_build_binary_op): Reject float <=> enum or enum <=> float. Use
+ CP_INTEGRAL_TYPE_P instead of INTEGRAL_OR_ENUMERATION_TYPE_P.
+
+2020-10-29 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (get_normalized_constraints): Remove 'args'
+ parameter. Pass NULL_TREE as the initial template arguments to
+ normalize_expression.
+ (get_normalized_constraints_from_info): Remove 'args' parameter
+ and adjust the call to get_normalized_constraints.
+ (get_normalized_constraints_from_decl): Remove 'args' local
+ variable and adjust call to get_normalized_constraints_from_info.
+ (normalize_concept_definition): Remove 'args' local variable
+ and adjust call to get_normalized_constraints.
+ (normalize_constraint_expression): Remove the two-parameter
+ overload. Remove 'args' parameter from the three-parameter
+ overload and update function comment accordingly. Remove
+ default argument from 'diag' parameter. Adjust call to
+ get_normalized_constraints.
+ (finish_nested_requirement): Adjust call to
+ normalize_constraint_expression.
+ (strictly_subsumes): Remove 'args' parameter. Adjust call to
+ get_normalized_constraints_from_info.
+ (weakly_subsumes): Likewise.
+ * cp-tree.h (strictly_subsumes): Remove 'args' parameter.
+ (weakly_subsumes): Likewise.
+ * pt.c (process_partial_specialization): Adjust call to
+ strictly_subsumes.
+ (is_compatible_template_arg): Adjust call to weakly_subsumes.
+
+2020-10-29 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97412
+ * constraint.cc (normalize_concept_check): Don't call
+ tsubst_template_args when 'args' is NULL.
+
+2020-10-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/97388
+ * constexpr.c (cxx_eval_outermost_constant_expr): Revert to
+ original expression if evaluation sets non_constant_p.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/97388
+ * constexpr.c (cxx_bind_parameters_in_call): Set non_constant_args
+ if the parameter type has a non-trivial destructor.
+ (cxx_eval_call_expression): Only unshare arguments if we're
+ memoizing this evaluation.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/95808
+ * cp-tree.h (enum cp_tree_index): Add CPTI_HEAP_VEC_UNINIT_IDENTIFIER
+ and CPTI_HEAP_VEC_IDENTIFIER.
+ (heap_vec_uninit_identifier, heap_vec_identifier): Define.
+ * decl.c (initialize_predefined_identifiers): Initialize those
+ identifiers.
+ * constexpr.c (cxx_eval_call_expression): Reject array allocations
+ deallocated with non-array deallocation or non-array allocations
+ deallocated with array deallocation.
+ (non_const_var_error): Handle heap_vec_uninit_identifier and
+ heap_vec_identifier too.
+ (cxx_eval_constant_expression): Handle also heap_vec_uninit_identifier
+ and in that case during initialization replace it with
+ heap_vec_identifier.
+ (find_heap_var_refs): Handle heap_vec_uninit_identifier and
+ heap_vec_identifier too.
+
+2020-10-29 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (push_template_decl): Do not give function-scope entities
+ other than implicit typedefs a template header. Do not readd
+ template info to a redeclared template.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ * decl.c (grokdeclarator): Offer a fix-it hint for the "unnecessary
+ parentheses in declaration" warning.
+ * parser.c (cp_parser_direct_declarator): When setting
+ declarator->parenthesized, use a location range.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * call.c (build_conditional_expr_1): Warn about the deprecated
+ enum/real type conversion in C++20. Also warn about a non-enumerated
+ and enumerated type in ?: when -Wenum-conversion is on.
+ * typeck.c (do_warn_enum_conversions): New function.
+ (cp_build_binary_op): Call it.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/96675
+ PR c++/96742
+ * pt.c (tsubst_copy_and_build): Call value_dependent_expression_p or
+ type_dependent_expression_p instead of type_dependent_expression_p_push.
+ But only call value_dependent_expression_p for expressions that are
+ potential_constant_expression.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94799
+ * parser.c (cp_parser_class_name): Use parser->scope when
+ setting typename_p.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86773
+ * parser.c (cp_parser_fold_expression): Return error_mark_node
+ if a left fold is preceded by an expression.
+
+2020-10-28 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_omp_declare_reduction): Set
+ DECL_LOCAL_DECL_P before push_template_decl.
+ * pt.c (instantiate_body): Nested fns do not have template_info.
+
+2020-10-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95132
+ * decl2.c (mark_used): Move up the constraints_satisfied_p check
+ so that we check constraints before calling maybe_instantiate_decl.
+
+2020-10-28 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (push_template_decl): Refactor for some RAII.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_name): Handle allocate.
+ (cp_parser_omp_clause_allocate): New function.
+ (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ALLOCATE.
+ (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK,
+ OMP_PARALLEL_CLAUSE_MASK, OMP_SINGLE_CLAUSE_MASK,
+ OMP_TASK_CLAUSE_MASK, OMP_TASKGROUP_CLAUSE_MASK,
+ OMP_DISTRIBUTE_CLAUSE_MASK, OMP_TEAMS_CLAUSE_MASK,
+ OMP_TARGET_CLAUSE_MASK, OMP_TASKLOOP_CLAUSE_MASK): Add
+ PRAGMA_OMP_CLAUSE_ALLOCATE.
+ * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_ALLOCATE.
+ * pt.c (tsubst_omp_clauses): Likewise.
+
+2020-10-27 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct lang_type): Delete nested_udts field.
+ (CLASSTYPE_NESTED_UTDS): Delete.
+ * name-lookup.h (binding_table, binding_entry): Delete typedefs.
+ (bt_foreach_proc): Likewise.
+ (struct binding_entry_s): Delete.
+ (SCOPE_DEFAULT_HT_SIZE, CLASS_SCOPE_HT_SIZE)
+ (NAMESPACE_ORDINARY_HT_SIZE, NAMESPACE_STD_HT_SIZE)
+ (GLOBAL_SCOPE_HT_SIZE): Delete.
+ (binding_table_foreach, binding_table_find): Delete declarations.
+ * name-lookup.c (ENTRY_INDEX): Delete.
+ (free_binding_entry): Delete.
+ (binding_entry_make, binding_entry_free): Delete.
+ (struct binding_table_s): Delete.
+ (binding_table_construct, binding_table_free): Delete.
+ (binding_table_new, binding_table_expand): Delete.
+ (binding_table_insert, binding_table_find): Delete.
+ (binding_table_foreach): Delete.
+ (maybe_process_template_type_declaration): Delete
+ CLASSTYPE_NESTED_UTDS insertion.
+ (do_pushtag): Likewise.
+ * decl2.c (bt_reset_linkage_1): Fold into reset_type_linkage_1.
+ (reset_type_linkage_2, bt_reset_linkage_2): Fold into
+ reset_type_linkage.
+ * pt.c (instantiate_class_template_1): Delete NESTED_UTDs comment.
+ (bt_instantiate_type_proc): Delete.
+ (do_type_instantiation): Instantiate implicit typedef fields.
+ Delete NESTED_UTD walk.
+ * search.c (lookup_field_r): Delete unreachable NESTED_UTD
+ search.
+
+2020-10-27 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_explicit_instantiation): Refactor some RAII.
+ * pt.c (bt_instantiate_type_proc): DATA is the tree, pass type to
+ do_type_instantiation.
+ (do_type_instantiation): Require T to be a type. Refactor for
+ some RAII.
+
+2020-10-26 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ * cp-tree.h (CPTK_IS_NOTHROW_ASSIGNABLE): New.
+ (CPTK_IS_NOTHROW_CONSTRUCTIBLE): Likewise.
+ (is_nothrow_xible): Likewise.
+ * method.c (is_nothrow_xible): New.
+ (is_trivially_xible): Tweak.
+ * parser.c (cp_parser_primary_expression): Handle the new RID_*.
+ (cp_parser_trait_expr): Likewise.
+ * semantics.c (trait_expr_value): Handle the new RID_*.
+ (finish_trait_expr): Likewise.
+
2020-10-24 Marek Polacek <polacek@redhat.com>
PR c++/96241
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 6ee4e41..4927246 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -47,12 +47,26 @@ CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h ope
# into the C++ rule, but that needs a little bit of work
# to do the right thing within all.cross.
c++: cc1plus$(exeext)
+c++.serial = cc1plus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: c++
CFLAGS-cp/g++spec.o += $(DRIVER_DEFINES)
+CFLAGS-cp/module.o += -DHOST_MACHINE=\"$(host)\" \
+ -DTARGET_MACHINE=\"$(target)\"
+
+# In non-release builds, use a date-related module version.
+ifneq ($(DEVPHASE_c),)
+# Some date's don't grok 'r', if so, simply use today's
+# date (don't bootstrap at midnight).
+MODULE_VERSION := $(shell date -r $(srcdir)/cp/module.cc '+%y%m%d-%H%M' \
+ 2>/dev/null || date '+%y%m%d-0000' 2>/dev/null || echo 0)
+
+CFLAGS-cp/module.o += -DMODULE_VERSION='($(subst -,,$(MODULE_VERSION))U)'
+endif
+
# Create the compiler driver for g++.
GXX_OBJS = $(GCC_OBJS) cp/g++spec.o
xg++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
@@ -80,7 +94,8 @@ CXX_AND_OBJCXX_OBJS = \
cp/error.o cp/except.o cp/expr.o \
cp/friend.o cp/init.o \
cp/lambda.o cp/lex.o cp/logic.o \
- cp/mangle.o cp/method.o \
+ cp/mangle.o cp/mapper-client.o cp/mapper-resolver.o \
+ cp/method.o cp/module.o \
cp/name-lookup.o cp/optimize.o \
cp/parser.o cp/pt.o cp/ptree.o \
cp/rtti.o \
@@ -116,9 +131,11 @@ cc1plus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
$(srcdir)/../move-if-change cc1plus-checksum.c.tmp cc1plus-checksum.c; \
fi
-cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS)
+cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS) $(c++.prev)
+ @$(call LINK_PROGRESS,$(INDEX.c++),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.c++),end)
ifeq ($(ENABLE_MAINTAINER_RULES), true)
# Special build rule. This is a maintainer rule, that is only
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bd66251..65a4d73 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -213,6 +213,7 @@ static conversion *merge_conversion_sequences (conversion *, conversion *);
static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
static conversion *build_identity_conv (tree, tree);
static inline bool conv_binds_to_array_of_unknown_bound (conversion *);
+static bool conv_is_prvalue (conversion *);
static tree prevent_lifetime_extension (tree);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
@@ -1963,14 +1964,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
return conv;
}
-/* Returns the implicit conversion sequence (see [over.ics]) from type
- FROM to type TO. The optional expression EXPR may affect the
- conversion. FLAGS are the usual overloading flags. If C_CAST_P is
- true, this conversion is coming from a C-style cast. */
+/* Most of the implementation of implicit_conversion, with the same
+ parameters. */
static conversion *
-implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
- int flags, tsubst_flags_t complain)
+implicit_conversion_1 (tree to, tree from, tree expr, bool c_cast_p,
+ int flags, tsubst_flags_t complain)
{
conversion *conv;
@@ -2096,6 +2095,26 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
return NULL;
}
+/* Returns the implicit conversion sequence (see [over.ics]) from type
+ FROM to type TO. The optional expression EXPR may affect the
+ conversion. FLAGS are the usual overloading flags. If C_CAST_P is
+ true, this conversion is coming from a C-style cast. */
+
+static conversion *
+implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
+ int flags, tsubst_flags_t complain)
+{
+ conversion *conv = implicit_conversion_1 (to, from, expr, c_cast_p,
+ flags, complain);
+ if (!conv || conv->bad_p)
+ return conv;
+ if (conv_is_prvalue (conv)
+ && CLASS_TYPE_P (conv->type)
+ && CLASSTYPE_PURE_VIRTUALS (conv->type))
+ conv->bad_p = true;
+ return conv;
+}
+
/* Like implicit_conversion, but return NULL if the conversion is bad.
This is not static so that check_non_deducible_conversion can call it within
@@ -4006,9 +4025,9 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
creating a garbage BASELINK; constructors can't be inherited. */
ctors = get_class_binding (totype, complete_ctor_identifier);
+ tree to_nonref = non_reference (totype);
if (MAYBE_CLASS_TYPE_P (fromtype))
{
- tree to_nonref = non_reference (totype);
if (same_type_ignoring_top_level_qualifiers_p (to_nonref, fromtype) ||
(CLASS_TYPE_P (to_nonref) && CLASS_TYPE_P (fromtype)
&& DERIVED_FROM_P (to_nonref, fromtype)))
@@ -4092,6 +4111,22 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
tree conversion_path = TREE_PURPOSE (conv_fns);
struct z_candidate *old_candidates;
+ /* If LOOKUP_NO_CONVERSION, don't consider a conversion function that
+ would need an addional user-defined conversion, i.e. if the return
+ type differs in class-ness from the desired type. So we avoid
+ considering operator bool when calling a copy constructor.
+
+ This optimization avoids the failure in PR97600, and is allowed by
+ [temp.inst]/9: "If the function selected by overload resolution can be
+ determined without instantiating a class template definition, it is
+ unspecified whether that instantiation actually takes place." */
+ tree convtype = non_reference (TREE_TYPE (conv_fns));
+ if ((flags & LOOKUP_NO_CONVERSION)
+ && !WILDCARD_TYPE_P (convtype)
+ && (CLASS_TYPE_P (to_nonref)
+ != CLASS_TYPE_P (convtype)))
+ continue;
+
/* If we are called to convert to a reference type, we are trying to
find a direct binding, so don't even consider temporaries. If
we don't find a direct binding, the caller will try again to
@@ -5643,17 +5678,40 @@ build_conditional_expr_1 (const op_location_t &loc,
"in conditional expression: %qT vs %qT",
arg2_type, arg3_type);
}
- else if (extra_warnings
+ else if ((complain & tf_warning)
+ && warn_deprecated_enum_float_conv
+ && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
+ && TREE_CODE (arg3_type) == REAL_TYPE)
+ || (TREE_CODE (arg2_type) == REAL_TYPE
+ && TREE_CODE (arg3_type) == ENUMERAL_TYPE)))
+ {
+ if (TREE_CODE (arg2_type) == ENUMERAL_TYPE)
+ warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
+ "conditional expression between enumeration type "
+ "%qT and floating-point type %qT is deprecated",
+ arg2_type, arg3_type);
+ else
+ warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
+ "conditional expression between floating-point "
+ "type %qT and enumeration type %qT is deprecated",
+ arg2_type, arg3_type);
+ }
+ else if ((extra_warnings || warn_enum_conversion)
&& ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& !same_type_p (arg3_type, type_promotes_to (arg2_type)))
|| (TREE_CODE (arg3_type) == ENUMERAL_TYPE
&& !same_type_p (arg2_type,
type_promotes_to (arg3_type)))))
- {
- if (complain & tf_warning)
- warning_at (loc, OPT_Wextra, "enumerated and non-enumerated "
- "type in conditional expression");
- }
+ {
+ if (complain & tf_warning)
+ {
+ enum opt_code opt = (warn_enum_conversion
+ ? OPT_Wenum_conversion
+ : OPT_Wextra);
+ warning_at (loc, opt, "enumerated and "
+ "non-enumerated type in conditional expression");
+ }
+ }
arg2 = perform_implicit_conversion (result_type, arg2, complain);
arg3 = perform_implicit_conversion (result_type, arg3, complain);
@@ -6315,6 +6373,8 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
print_z_candidates (loc, candidates);
}
result = error_mark_node;
+ if (overload)
+ *overload = error_mark_node;
}
else if (TREE_CODE (cand->fn) == FUNCTION_DECL)
{
@@ -7384,7 +7444,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
else if (t->kind == ck_identity)
break;
}
- if (!complained)
+ if (!complained && expr != error_mark_node)
{
range_label_for_type_mismatch label (TREE_TYPE (expr), totype);
gcc_rich_location richloc (loc, &label);
@@ -8366,6 +8426,10 @@ call_copy_ctor (tree a, tsubst_flags_t complain)
bool
unsafe_return_slot_p (tree t)
{
+ /* Check empty bases separately, they don't have fields. */
+ if (is_empty_base_ref (t))
+ return true;
+
STRIP_NOPS (t);
if (TREE_CODE (t) == ADDR_EXPR)
t = TREE_OPERAND (t, 0);
@@ -8415,20 +8479,15 @@ unsafe_copy_elision_p (tree target, tree exp)
&& !AGGR_INIT_VIA_CTOR_P (init));
}
-/* True iff C is a conversion that binds a reference to a prvalue. */
+/* True IFF the result of the conversion C is a prvalue. */
static bool
-conv_binds_ref_to_prvalue (conversion *c)
+conv_is_prvalue (conversion *c)
{
- if (c->kind != ck_ref_bind)
- return false;
- if (c->need_temporary_p)
- return true;
-
- c = next_conversion (c);
-
if (c->kind == ck_rvalue)
return true;
+ if (c->kind == ck_base && c->need_temporary_p)
+ return true;
if (c->kind == ck_user && !TYPE_REF_P (c->type))
return true;
if (c->kind == ck_identity && c->u.expr
@@ -8438,6 +8497,19 @@ conv_binds_ref_to_prvalue (conversion *c)
return false;
}
+/* True iff C is a conversion that binds a reference to a prvalue. */
+
+static bool
+conv_binds_ref_to_prvalue (conversion *c)
+{
+ if (c->kind != ck_ref_bind)
+ return false;
+ if (c->need_temporary_p)
+ return true;
+
+ return conv_is_prvalue (next_conversion (c));
+}
+
/* True iff converting EXPR to a reference type TYPE does not involve
creating a temporary. */
@@ -8490,6 +8562,25 @@ build_trivial_dtor_call (tree instance, bool no_ptr_deref)
instance, clobber);
}
+/* Return true if a call to FN with number of arguments NARGS
+ is an immediate invocation. */
+
+static bool
+immediate_invocation_p (tree fn, int nargs)
+{
+ return (TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_IMMEDIATE_FUNCTION_P (fn)
+ && cp_unevaluated_operand == 0
+ && (current_function_decl == NULL_TREE
+ || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
+ && (current_binding_level->kind != sk_function_parms
+ || !current_binding_level->immediate_fn_ctx_p)
+ /* As an exception, we defer std::source_location::current ()
+ invocations until genericization because LWG3396 mandates
+ special behavior for it. */
+ && (nargs > 1 || !source_location_current_p (fn)));
+}
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
@@ -8557,13 +8648,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
addr, nargs, argarray);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
- if (TREE_CODE (fn) == FUNCTION_DECL
- && DECL_IMMEDIATE_FUNCTION_P (fn)
- && cp_unevaluated_operand == 0
- && (current_function_decl == NULL_TREE
- || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
- && (current_binding_level->kind != sk_function_parms
- || !current_binding_level->immediate_fn_ctx_p))
+ if (immediate_invocation_p (fn, nargs))
{
tree obj_arg = NULL_TREE, exprimm = expr;
if (DECL_CONSTRUCTOR_P (fn))
@@ -9201,13 +9286,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (TREE_CODE (fn) == ADDR_EXPR)
{
tree fndecl = STRIP_TEMPLATE (TREE_OPERAND (fn, 0));
- if (TREE_CODE (fndecl) == FUNCTION_DECL
- && DECL_IMMEDIATE_FUNCTION_P (fndecl)
- && cp_unevaluated_operand == 0
- && (current_function_decl == NULL_TREE
- || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
- && (current_binding_level->kind != sk_function_parms
- || !current_binding_level->immediate_fn_ctx_p))
+ if (immediate_invocation_p (fndecl, nargs))
{
tree obj_arg = NULL_TREE;
if (DECL_CONSTRUCTOR_P (fndecl))
@@ -10381,6 +10460,8 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
free (pretty_name);
}
call = error_mark_node;
+ if (fn_p)
+ *fn_p = error_mark_node;
}
else
{
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 26f996b..fc5502a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1,4 +1,4 @@
-/* Functions related to building classes and their related objects.
+/* Functions related to building -*- C++ -*- classes and their related objects.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -494,8 +494,6 @@ build_base_path (enum tree_code code,
if (want_pointer)
target_type = ptr_target_type;
- expr = build1 (NOP_EXPR, ptr_target_type, expr);
-
if (!integer_zerop (offset))
{
offset = fold_convert (sizetype, offset);
@@ -506,6 +504,8 @@ build_base_path (enum tree_code code,
else
null_test = NULL;
+ expr = build1 (NOP_EXPR, ptr_target_type, expr);
+
indout:
if (!want_pointer)
{
@@ -659,6 +659,33 @@ convert_to_base_statically (tree expr, tree base)
return expr;
}
+/* True IFF EXPR is a reference to an empty base class "subobject", as built in
+ convert_to_base_statically. We look for the result of the fold_convert
+ call, a NOP_EXPR from one pointer type to another, where the target is an
+ empty base of the original type. */
+
+bool
+is_empty_base_ref (tree expr)
+{
+ if (TREE_CODE (expr) == INDIRECT_REF)
+ expr = TREE_OPERAND (expr, 0);
+ if (TREE_CODE (expr) != NOP_EXPR)
+ return false;
+ tree type = TREE_TYPE (expr);
+ if (!POINTER_TYPE_P (type))
+ return false;
+ type = TREE_TYPE (type);
+ if (!is_empty_class (type))
+ return false;
+ STRIP_NOPS (expr);
+ tree fromtype = TREE_TYPE (expr);
+ if (!POINTER_TYPE_P (fromtype))
+ return false;
+ fromtype = TREE_TYPE (fromtype);
+ return (CLASS_TYPE_P (fromtype)
+ && !same_type_ignoring_top_level_qualifiers_p (fromtype, type)
+ && DERIVED_FROM_P (type, fromtype));
+}
tree
build_vfield_ref (tree datum, tree type)
@@ -1322,6 +1349,8 @@ handle_using_decl (tree using_decl, tree t)
return;
}
+ iloc_sentinel ils (DECL_SOURCE_LOCATION (using_decl));
+
/* Make type T see field decl FDECL with access ACCESS. */
if (flist)
for (ovl_iterator iter (flist); iter; ++iter)
@@ -1329,6 +1358,23 @@ handle_using_decl (tree using_decl, tree t)
add_method (t, *iter, true);
alter_access (t, *iter, access);
}
+ else if (USING_DECL_UNRELATED_P (using_decl))
+ {
+ /* C++20 using enum can import non-inherited enumerators into class
+ scope. We implement that by making a copy of the CONST_DECL for which
+ CONST_DECL_USING_P is true. */
+ gcc_assert (TREE_CODE (decl) == CONST_DECL);
+
+ tree copy = copy_decl (decl);
+ DECL_CONTEXT (copy) = t;
+ DECL_ARTIFICIAL (copy) = true;
+ /* We emitted debug info for the USING_DECL above; make sure we don't
+ also emit anything for this clone. */
+ DECL_IGNORED_P (copy) = true;
+ DECL_SOURCE_LOCATION (copy) = DECL_SOURCE_LOCATION (using_decl);
+ finish_member_declaration (copy);
+ DECL_ABSTRACT_ORIGIN (copy) = decl;
+ }
else
alter_access (t, decl, access);
}
@@ -4838,7 +4884,10 @@ copy_fndecl_with_name (tree fn, tree name, tree_code code,
/* Create the RTL for this function. */
SET_DECL_RTL (clone, NULL);
- rest_of_decl_compilation (clone, namespace_bindings_p (), at_eof);
+
+ /* Regardless of the current scope, this is a member function, so
+ not at namespace scope. */
+ rest_of_decl_compilation (clone, /*top_level=*/0, at_eof);
return clone;
}
@@ -4898,8 +4947,9 @@ build_clone (tree fn, tree name, bool need_vtt_parm_p,
/* Build the clones of FN, return the number of clones built. These
will be inserted onto DECL_CHAIN of FN. */
-static unsigned
-build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p)
+void
+build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p,
+ bool update_methods)
{
unsigned count = 0;
@@ -4935,7 +4985,16 @@ build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p)
count += 2;
}
- return count;
+ /* The original is now an abstract function that is never
+ emitted. */
+ DECL_ABSTRACT_P (fn) = true;
+
+ if (update_methods)
+ for (tree clone = fn; count--;)
+ {
+ clone = DECL_CHAIN (clone);
+ add_method (DECL_CONTEXT (clone), clone, false);
+ }
}
/* Produce declarations for all appropriate clones of FN. If
@@ -4958,17 +5017,7 @@ clone_cdtor (tree fn, bool update_methods)
bool base_omits_inherited = (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
&& base_ctor_omit_inherited_parms (fn));
- unsigned count = build_cdtor_clones (fn, vtt, base_omits_inherited);
-
- /* Note that this is an abstract function that is never emitted. */
- DECL_ABSTRACT_P (fn) = true;
-
- if (update_methods)
- for (tree clone = fn; count--;)
- {
- clone = DECL_CHAIN (clone);
- add_method (DECL_CONTEXT (clone), clone, false);
- }
+ build_cdtor_clones (fn, vtt, base_omits_inherited, update_methods);
}
/* DECL is an in charge constructor, which is being defined. This will
@@ -5055,8 +5104,8 @@ adjust_clone_args (tree decl)
static void
clone_constructors_and_destructors (tree t)
{
- /* While constructors can be via a using declaration, at this point
- we no longer need to know that. */
+ /* We do not need to propagate the usingness to the clone, at this
+ point that is not needed. */
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
clone_cdtor (*iter, /*update_methods=*/true);
@@ -6737,6 +6786,8 @@ layout_class_type (tree t, tree *virtuals_p)
TYPE_CONTEXT (base_t) = t;
DECL_CONTEXT (base_d) = t;
+ set_instantiating_module (base_d);
+
/* If the ABI version is not at least two, and the last
field was a bit-field, RLI may not be on a byte
boundary. In particular, rli_size_unit_so_far might
@@ -7472,9 +7523,6 @@ finish_struct_1 (tree t)
/* Finish debugging output for this type. */
rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
- /* Recalculate satisfaction that might depend on completeness. */
- clear_satisfaction_cache ();
-
if (TYPE_TRANSPARENT_AGGR (t))
{
tree field = first_field (t);
@@ -8719,6 +8767,7 @@ build_self_reference (void)
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_SELF_REFERENCE_P (decl);
set_underlying_type (decl);
+ set_instantiating_module (decl);
if (processing_template_decl)
decl = push_template_decl (decl);
diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in
index da70b35..4f5f8ec 100644
--- a/gcc/cp/config-lang.in
+++ b/gcc/cp/config-lang.in
@@ -47,7 +47,7 @@ gtfiles="\
\$(srcdir)/cp/friend.c \
\$(srcdir)/cp/init.c \
\$(srcdir)/cp/lambda.c \$(srcdir)/cp/lex.c \$(srcdir)/cp/logic.cc \
-\$(srcdir)/cp/mangle.c \$(srcdir)/cp/method.c \
+\$(srcdir)/cp/mangle.c \$(srcdir)/cp/method.c \$(srcdir)/cp/module.cc \
\$(srcdir)/cp/name-lookup.c \
\$(srcdir)/cp/parser.c \$(srcdir)/cp/pt.c \
\$(srcdir)/cp/rtti.c \
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7ebdd30..f7cc413 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -133,19 +133,10 @@ ensure_literal_type_for_constexpr_object (tree decl)
return decl;
}
-/* Representation of entries in the constexpr function definition table. */
-
-struct GTY((for_user)) constexpr_fundef {
- tree decl;
- tree body;
- tree parms;
- tree result;
-};
-
struct constexpr_fundef_hasher : ggc_ptr_hash<constexpr_fundef>
{
- static hashval_t hash (constexpr_fundef *);
- static bool equal (constexpr_fundef *, constexpr_fundef *);
+ static hashval_t hash (const constexpr_fundef *);
+ static bool equal (const constexpr_fundef *, const constexpr_fundef *);
};
/* This table holds all constexpr function definitions seen in
@@ -158,7 +149,8 @@ static GTY (()) hash_table<constexpr_fundef_hasher> *constexpr_fundef_table;
same constexpr function. */
inline bool
-constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs)
+constexpr_fundef_hasher::equal (const constexpr_fundef *lhs,
+ const constexpr_fundef *rhs)
{
return lhs->decl == rhs->decl;
}
@@ -167,20 +159,20 @@ constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs)
Return a hash value for the entry pointed to by Q. */
inline hashval_t
-constexpr_fundef_hasher::hash (constexpr_fundef *fundef)
+constexpr_fundef_hasher::hash (const constexpr_fundef *fundef)
{
return DECL_UID (fundef->decl);
}
/* Return a previously saved definition of function FUN. */
-static constexpr_fundef *
+constexpr_fundef *
retrieve_constexpr_fundef (tree fun)
{
if (constexpr_fundef_table == NULL)
return NULL;
- constexpr_fundef fundef = { fun, NULL, NULL, NULL };
+ constexpr_fundef fundef = { fun, NULL_TREE, NULL_TREE, NULL_TREE };
return constexpr_fundef_table->find (&fundef);
}
@@ -669,7 +661,7 @@ get_function_named_in_call (tree t)
return fun;
}
-/* Subroutine of register_constexpr_fundef. BODY is the body of a function
+/* Subroutine of check_constexpr_fundef. BODY is the body of a function
declared to be constexpr, or a sub-statement thereof. Returns the
return value if suitable, error_mark_node for a statement not allowed in
a constexpr function, or NULL_TREE if no return value was found. */
@@ -738,7 +730,7 @@ constexpr_fn_retval (tree body)
}
}
-/* Subroutine of register_constexpr_fundef. BODY is the DECL_SAVED_TREE of
+/* Subroutine of check_constexpr_fundef. BODY is the DECL_SAVED_TREE of
FUN; do the necessary transformations to turn it into a single expression
that we can store in the hash table. */
@@ -868,27 +860,28 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
}
/* We are processing the definition of the constexpr function FUN.
- Check that its BODY fulfills the propriate requirements and
- enter it in the constexpr function definition table.
- For constructor BODY is actually the TREE_LIST of the
- member-initializer list. */
+ Check that its body fulfills the apropriate requirements and
+ enter it in the constexpr function definition table. */
-tree
-register_constexpr_fundef (tree fun, tree body)
+void
+maybe_save_constexpr_fundef (tree fun)
{
- constexpr_fundef entry;
- constexpr_fundef **slot;
+ if (processing_template_decl
+ || !DECL_DECLARED_CONSTEXPR_P (fun)
+ || cp_function_chain->invalid_constexpr
+ || DECL_CLONED_FUNCTION_P (fun))
+ return;
if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
- return NULL;
+ return;
- tree massaged = massage_constexpr_body (fun, body);
+ tree massaged = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
if (massaged == NULL_TREE || massaged == error_mark_node)
{
if (!DECL_CONSTRUCTOR_P (fun))
error ("body of %<constexpr%> function %qD not a return-statement",
fun);
- return NULL;
+ return;
}
bool potential = potential_rvalue_constant_expression (massaged);
@@ -901,39 +894,47 @@ register_constexpr_fundef (tree fun, tree body)
potential = false;
if (!potential && !DECL_GENERATED_P (fun))
- return NULL;
-
- /* Create the constexpr function table if necessary. */
- if (constexpr_fundef_table == NULL)
- constexpr_fundef_table
- = hash_table<constexpr_fundef_hasher>::create_ggc (101);
+ return;
- entry.decl = fun;
- tree saved_fn = current_function_decl;
+ constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE};
bool clear_ctx = false;
- current_function_decl = fun;
if (DECL_RESULT (fun) && DECL_CONTEXT (DECL_RESULT (fun)) == NULL_TREE)
{
clear_ctx = true;
DECL_CONTEXT (DECL_RESULT (fun)) = fun;
}
- entry.body = copy_fn (fun, entry.parms, entry.result);
+ tree saved_fn = current_function_decl;
+ current_function_decl = fun;
+ entry.body = copy_fn (entry.decl, entry.parms, entry.result);
current_function_decl = saved_fn;
- slot = constexpr_fundef_table->find_slot (&entry, INSERT);
if (clear_ctx)
- DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE;
-
+ DECL_CONTEXT (DECL_RESULT (entry.decl)) = NULL_TREE;
if (!potential)
/* For a template instantiation, we want to remember the pre-generic body
for explain_invalid_constexpr_fn, but do tell cxx_eval_call_expression
that it doesn't need to bother trying to expand the function. */
entry.result = error_mark_node;
+ register_constexpr_fundef (entry);
+}
+
+/* BODY is a validated and massaged definition of a constexpr
+ function. Register it in the hash table. */
+
+void
+register_constexpr_fundef (const constexpr_fundef &value)
+{
+ /* Create the constexpr function table if necessary. */
+ if (constexpr_fundef_table == NULL)
+ constexpr_fundef_table
+ = hash_table<constexpr_fundef_hasher>::create_ggc (101);
+
+ constexpr_fundef **slot = constexpr_fundef_table->find_slot
+ (const_cast<constexpr_fundef *> (&value), INSERT);
+
gcc_assert (*slot == NULL);
*slot = ggc_alloc<constexpr_fundef> ();
- **slot = entry;
-
- return fun;
+ **slot = value;
}
/* FUN is a non-constexpr function called in a context that requires a
@@ -1331,7 +1332,12 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
}
if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
- return fold_builtin_source_location (EXPR_LOCATION (t));
+ {
+ temp_override<tree> ovr (current_function_decl);
+ if (ctx->call && ctx->call->fundef)
+ current_function_decl = ctx->call->fundef->decl;
+ return fold_builtin_source_location (EXPR_LOCATION (t));
+ }
int strops = 0;
int strret = 0;
@@ -1518,7 +1524,7 @@ unshare_constructor (tree t MEM_STAT_DECL)
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (n);
constructor_elt *ce;
for (HOST_WIDE_INT i = 0; vec_safe_iterate (v, i, &ce); ++i)
- if (TREE_CODE (ce->value) == CONSTRUCTOR)
+ if (ce->value && TREE_CODE (ce->value) == CONSTRUCTOR)
ptrs.safe_push (&ce->value);
}
return t;
@@ -1602,6 +1608,11 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
arg = adjust_temp_type (type, arg);
if (!TREE_CONSTANT (arg))
*non_constant_args = true;
+ else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ /* The destructor needs to see any modifications the callee makes
+ to the argument. */
+ *non_constant_args = true;
+
/* For virtual calls, adjust the this argument, so that it is
the object on which the method is called, rather than
one of its bases. */
@@ -1987,11 +1998,20 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call,
to the object under construction or destruction, this object is
considered to be a most derived object that has the type of the
constructor or destructor's class. */
- tree vtable = build_vfield_ref (obj, TREE_TYPE (obj));
+ tree vtable = build_vfield_ref (obj, objtype);
vtable = cxx_eval_constant_expression (ctx, vtable, /*lval*/false,
non_constant_p, overflow_p);
if (*non_constant_p)
return call;
+ /* With -fsanitize=vptr, we initialize all vtable pointers to null,
+ so it's possible that we got a null pointer now. */
+ if (integer_zerop (vtable))
+ {
+ if (!ctx->quiet)
+ error_at (loc, "virtual table pointer is used uninitialized");
+ *non_constant_p = true;
+ return integer_zero_node;
+ }
/* VTABLE will be &_ZTV1A + 16 or similar, get _ZTV1A. */
vtable = extract_obj_from_addr_offset (vtable);
const tree mdtype = DECL_CONTEXT (vtable);
@@ -2181,6 +2201,27 @@ cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl,
non_constant_p, overflow_p);
}
+/* If OBJECT is of const class type, evaluate it to a CONSTRUCTOR and set
+ its TREE_READONLY flag according to READONLY_P. Used for constexpr
+ 'tors to detect modifying const objects in a constexpr context. */
+
+static void
+cxx_set_object_constness (const constexpr_ctx *ctx, tree object,
+ bool readonly_p, bool *non_constant_p,
+ bool *overflow_p)
+{
+ if (CLASS_TYPE_P (TREE_TYPE (object))
+ && CP_TYPE_CONST_P (TREE_TYPE (object)))
+ {
+ /* Subobjects might not be stored in ctx->global->values but we
+ can get its CONSTRUCTOR by evaluating *this. */
+ tree e = cxx_eval_constant_expression (ctx, object, /*lval*/false,
+ non_constant_p, overflow_p);
+ if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p)
+ TREE_READONLY (e) = readonly_p;
+ }
+}
+
/* Subroutine of cxx_eval_constant_expression.
Evaluate the call expression tree T in the context of OLD_CALL expression
evaluation. */
@@ -2288,7 +2329,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{
tree type = build_array_type_nelts (char_type_node,
tree_to_uhwi (arg0));
- tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier,
+ tree var = build_decl (loc, VAR_DECL,
+ (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC)
+ ? heap_vec_uninit_identifier
+ : heap_uninit_identifier,
type);
DECL_ARTIFICIAL (var) = 1;
TREE_STATIC (var) = 1;
@@ -2306,6 +2351,42 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
if (DECL_NAME (var) == heap_uninit_identifier
|| DECL_NAME (var) == heap_identifier)
{
+ if (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC)
+ {
+ if (!ctx->quiet)
+ {
+ error_at (loc, "array deallocation of object "
+ "allocated with non-array "
+ "allocation");
+ inform (DECL_SOURCE_LOCATION (var),
+ "allocation performed here");
+ }
+ *non_constant_p = true;
+ return t;
+ }
+ DECL_NAME (var) = heap_deleted_identifier;
+ ctx->global->values.remove (var);
+ ctx->global->heap_dealloc_count++;
+ return void_node;
+ }
+ else if (DECL_NAME (var) == heap_vec_uninit_identifier
+ || DECL_NAME (var) == heap_vec_identifier)
+ {
+ if ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC) == 0)
+ {
+ if (!ctx->quiet)
+ {
+ error_at (loc, "non-array deallocation of "
+ "object allocated with array "
+ "allocation");
+ inform (DECL_SOURCE_LOCATION (var),
+ "allocation performed here");
+ }
+ *non_constant_p = true;
+ return t;
+ }
DECL_NAME (var) = heap_deleted_identifier;
ctx->global->values.remove (var);
ctx->global->heap_dealloc_count++;
@@ -2469,11 +2550,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
depth_ok = push_cx_call_context (t);
- /* Remember the object we are constructing. */
+ /* Remember the object we are constructing or destructing. */
tree new_obj = NULL_TREE;
- if (DECL_CONSTRUCTOR_P (fun))
+ if (DECL_CONSTRUCTOR_P (fun) || DECL_DESTRUCTOR_P (fun))
{
- /* In a constructor, it should be the first `this' argument.
+ /* In a cdtor, it should be the first `this' argument.
At this point it has already been evaluated in the call
to cxx_bind_parameters_in_call. */
new_obj = TREE_VEC_ELT (new_call.bindings, 0);
@@ -2586,14 +2667,14 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
problems with verify_gimple. */
arg = unshare_expr_without_location (arg);
TREE_VEC_ELT (bound, i) = arg;
+
+ /* And then unshare again so the callee doesn't change the
+ argument values in the hash table. XXX Could we unshare
+ lazily in cxx_eval_store_expression? */
+ arg = unshare_constructor (arg);
+ if (TREE_CODE (arg) == CONSTRUCTOR)
+ vec_safe_push (ctors, arg);
}
- /* Don't share a CONSTRUCTOR that might be changed. This is not
- redundant with the unshare just above; we also don't want to
- change the argument values in the hash table. XXX Could we
- unshare lazily in cxx_eval_store_expression? */
- arg = unshare_constructor (arg);
- if (TREE_CODE (arg) == CONSTRUCTOR)
- vec_safe_push (ctors, arg);
ctx->global->values.put (remapped, arg);
remapped = DECL_CHAIN (remapped);
}
@@ -2610,6 +2691,12 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
+ /* If this is a constexpr destructor, the object's const and volatile
+ semantics are no longer in effect; see [class.dtor]p5. */
+ if (new_obj && DECL_DESTRUCTOR_P (fun))
+ cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/false,
+ non_constant_p, overflow_p);
+
tree jump_target = NULL_TREE;
cxx_eval_constant_expression (&ctx_with_save_exprs, body,
lval, non_constant_p, overflow_p,
@@ -2640,19 +2727,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
the object is no longer under construction, and its possible
'const' semantics now apply. Make a note of this fact by
marking the CONSTRUCTOR TREE_READONLY. */
- if (new_obj
- && CLASS_TYPE_P (TREE_TYPE (new_obj))
- && CP_TYPE_CONST_P (TREE_TYPE (new_obj)))
- {
- /* Subobjects might not be stored in ctx->global->values but we
- can get its CONSTRUCTOR by evaluating *this. */
- tree e = cxx_eval_constant_expression (ctx, new_obj,
- /*lval*/false,
- non_constant_p,
- overflow_p);
- if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p)
- TREE_READONLY (e) = true;
- }
+ if (new_obj && DECL_CONSTRUCTOR_P (fun))
+ cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/true,
+ non_constant_p, overflow_p);
/* Forget the saved values of the callee's SAVE_EXPRs and
TARGET_EXPRs. */
@@ -3091,7 +3168,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
overflow_p);
else if (code == SPACESHIP_EXPR)
{
- r = genericize_spaceship (type, lhs, rhs);
+ r = genericize_spaceship (loc, type, lhs, rhs);
return cxx_eval_constant_expression (ctx, r, lval, non_constant_p,
overflow_p);
}
@@ -3099,6 +3176,21 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
if (r == NULL_TREE)
r = fold_binary_loc (loc, code, type, lhs, rhs);
+ if (r == NULL_TREE
+ && (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+ && TREE_CODE (lhs) == INTEGER_CST
+ && TREE_CODE (rhs) == INTEGER_CST
+ && wi::neg_p (wi::to_wide (rhs)))
+ {
+ /* For diagnostics and -fpermissive emulate previous behavior of
+ handling shifts by negative amount. */
+ tree nrhs = const_unop (NEGATE_EXPR, TREE_TYPE (rhs), rhs);
+ if (nrhs)
+ r = fold_binary_loc (loc,
+ code == LSHIFT_EXPR ? RSHIFT_EXPR : LSHIFT_EXPR,
+ type, lhs, nrhs);
+ }
+
if (r == NULL_TREE)
{
if (lhs == orig_lhs && rhs == orig_rhs)
@@ -3867,6 +3959,205 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
return error_mark_node;
}
+/* Helper for cxx_eval_bit_cast.
+ Check [bit.cast]/3 rules, bit_cast is constexpr only if the To and From
+ types and types of all subobjects have is_union_v<T>, is_pointer_v<T>,
+ is_member_pointer_v<T>, is_volatile_v<T> false and has no non-static
+ data members of reference type. */
+
+static bool
+check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type,
+ tree orig_type)
+{
+ if (TREE_CODE (type) == UNION_TYPE)
+ {
+ if (!ctx->quiet)
+ {
+ if (type == orig_type)
+ error_at (loc, "%qs is not a constant expression because %qT is "
+ "a union type", "__builtin_bit_cast", type);
+ else
+ error_at (loc, "%qs is not a constant expression because %qT "
+ "contains a union type", "__builtin_bit_cast",
+ orig_type);
+ }
+ return true;
+ }
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ if (!ctx->quiet)
+ {
+ if (type == orig_type)
+ error_at (loc, "%qs is not a constant expression because %qT is "
+ "a pointer type", "__builtin_bit_cast", type);
+ else
+ error_at (loc, "%qs is not a constant expression because %qT "
+ "contains a pointer type", "__builtin_bit_cast",
+ orig_type);
+ }
+ return true;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ if (!ctx->quiet)
+ {
+ if (type == orig_type)
+ error_at (loc, "%qs is not a constant expression because %qT is "
+ "a reference type", "__builtin_bit_cast", type);
+ else
+ error_at (loc, "%qs is not a constant expression because %qT "
+ "contains a reference type", "__builtin_bit_cast",
+ orig_type);
+ }
+ return true;
+ }
+ if (TYPE_PTRMEM_P (type))
+ {
+ if (!ctx->quiet)
+ {
+ if (type == orig_type)
+ error_at (loc, "%qs is not a constant expression because %qT is "
+ "a pointer to member type", "__builtin_bit_cast",
+ type);
+ else
+ error_at (loc, "%qs is not a constant expression because %qT "
+ "contains a pointer to member type",
+ "__builtin_bit_cast", orig_type);
+ }
+ return true;
+ }
+ if (TYPE_VOLATILE (type))
+ {
+ if (!ctx->quiet)
+ {
+ if (type == orig_type)
+ error_at (loc, "%qs is not a constant expression because %qT is "
+ "volatile", "__builtin_bit_cast", type);
+ else
+ error_at (loc, "%qs is not a constant expression because %qT "
+ "contains a volatile subobject",
+ "__builtin_bit_cast", orig_type);
+ }
+ return true;
+ }
+ if (TREE_CODE (type) == RECORD_TYPE)
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && check_bit_cast_type (ctx, loc, TREE_TYPE (field), orig_type))
+ return true;
+ return false;
+}
+
+/* Subroutine of cxx_eval_constant_expression.
+ Attempt to evaluate a BIT_CAST_EXPR. */
+
+static tree
+cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
+ bool *overflow_p)
+{
+ if (check_bit_cast_type (ctx, EXPR_LOCATION (t), TREE_TYPE (t),
+ TREE_TYPE (t))
+ || check_bit_cast_type (ctx, cp_expr_loc_or_loc (TREE_OPERAND (t, 0),
+ EXPR_LOCATION (t)),
+ TREE_TYPE (TREE_OPERAND (t, 0)),
+ TREE_TYPE (TREE_OPERAND (t, 0))))
+ {
+ *non_constant_p = true;
+ return t;
+ }
+
+ tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
+ non_constant_p, overflow_p);
+ if (*non_constant_p)
+ return t;
+
+ location_t loc = EXPR_LOCATION (t);
+ if (BITS_PER_UNIT != 8 || CHAR_BIT != 8)
+ {
+ if (!ctx->quiet)
+ sorry_at (loc, "%qs cannot be constant evaluated on the target",
+ "__builtin_bit_cast");
+ *non_constant_p = true;
+ return t;
+ }
+
+ if (!tree_fits_shwi_p (TYPE_SIZE_UNIT (TREE_TYPE (t))))
+ {
+ if (!ctx->quiet)
+ sorry_at (loc, "%qs cannot be constant evaluated because the "
+ "type is too large", "__builtin_bit_cast");
+ *non_constant_p = true;
+ return t;
+ }
+
+ HOST_WIDE_INT len = tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (t)));
+ if (len < 0 || (int) len != len)
+ {
+ if (!ctx->quiet)
+ sorry_at (loc, "%qs cannot be constant evaluated because the "
+ "type is too large", "__builtin_bit_cast");
+ *non_constant_p = true;
+ return t;
+ }
+
+ unsigned char buf[64];
+ unsigned char *ptr, *mask;
+ size_t alen = (size_t) len * 2;
+ if (alen <= sizeof (buf))
+ ptr = buf;
+ else
+ ptr = XNEWVEC (unsigned char, alen);
+ mask = ptr + (size_t) len;
+ /* At the beginning consider everything indeterminate. */
+ memset (mask, ~0, (size_t) len);
+
+ if (native_encode_initializer (op, ptr, len, 0, mask) != len)
+ {
+ if (!ctx->quiet)
+ sorry_at (loc, "%qs cannot be constant evaluated because the "
+ "argument cannot be encoded", "__builtin_bit_cast");
+ *non_constant_p = true;
+ if (ptr != buf)
+ XDELETE (ptr);
+ return t;
+ }
+
+ tree r = NULL_TREE;
+ if (can_native_interpret_type_p (TREE_TYPE (t)))
+ r = native_interpret_expr (TREE_TYPE (t), ptr, len);
+ else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
+ {
+ r = native_interpret_aggregate (TREE_TYPE (t), ptr, 0, len);
+ if (r != NULL_TREE)
+ clear_type_padding_in_mask (TREE_TYPE (t), mask);
+ }
+
+ if (r != NULL_TREE)
+ {
+ for (int i = 0; i < len; i++)
+ if (mask[i])
+ {
+ if (!ctx->quiet)
+ error_at (loc, "%qs accessing uninitialized byte at offset %d",
+ "__builtin_bit_cast", i);
+ *non_constant_p = true;
+ r = t;
+ break;
+ }
+ if (ptr != buf)
+ XDELETE (ptr);
+ return r;
+ }
+
+ if (!ctx->quiet)
+ sorry_at (loc, "%qs cannot be constant evaluated because the "
+ "argument cannot be interpreted", "__builtin_bit_cast");
+ *non_constant_p = true;
+ if (ptr != buf)
+ XDELETE (ptr);
+ return t;
+}
+
/* Subroutine of cxx_eval_constant_expression.
Evaluate a short-circuited logical expression T in the context
of a given constexpr CALL. BAILOUT_VALUE is the value for
@@ -4257,7 +4548,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
eltinit = cxx_eval_constant_expression (&new_ctx, eltinit, lval,
non_constant_p, overflow_p);
}
- if (*non_constant_p && !ctx->quiet)
+ if (*non_constant_p)
break;
if (new_ctx.ctor != ctx->ctor)
{
@@ -4329,11 +4620,32 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
return same_type_ignoring_top_level_qualifiers_p (type1, type2);
}
+/* Try to determine the currently active union member for an expression
+ with UNION_TYPE. If it can be determined, return the FIELD_DECL,
+ otherwise return NULL_TREE. */
+
+static tree
+cxx_union_active_member (const constexpr_ctx *ctx, tree t)
+{
+ constexpr_ctx new_ctx = *ctx;
+ new_ctx.quiet = true;
+ bool non_constant_p = false, overflow_p = false;
+ tree ctor = cxx_eval_constant_expression (&new_ctx, t, false,
+ &non_constant_p,
+ &overflow_p);
+ if (TREE_CODE (ctor) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (ctor) == 1
+ && CONSTRUCTOR_ELT (ctor, 0)->index
+ && TREE_CODE (CONSTRUCTOR_ELT (ctor, 0)->index) == FIELD_DECL)
+ return CONSTRUCTOR_ELT (ctor, 0)->index;
+ return NULL_TREE;
+}
+
/* Helper function for cxx_fold_indirect_ref_1, called recursively. */
static tree
-cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op,
- unsigned HOST_WIDE_INT off, bool *empty_base)
+cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
+ tree op, unsigned HOST_WIDE_INT off, bool *empty_base)
{
tree optype = TREE_TYPE (op);
unsigned HOST_WIDE_INT const_nunits;
@@ -4392,13 +4704,29 @@ cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op,
tree index = size_int (idx + tree_to_uhwi (min_val));
op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
NULL_TREE, NULL_TREE);
- return cxx_fold_indirect_ref_1 (loc, type, op, rem,
+ return cxx_fold_indirect_ref_1 (ctx, loc, type, op, rem,
empty_base);
}
}
/* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */
- else if (TREE_CODE (optype) == RECORD_TYPE)
+ else if (TREE_CODE (optype) == RECORD_TYPE
+ || TREE_CODE (optype) == UNION_TYPE)
{
+ if (TREE_CODE (optype) == UNION_TYPE)
+ /* For unions prefer the currently active member. */
+ if (tree field = cxx_union_active_member (ctx, op))
+ {
+ unsigned HOST_WIDE_INT el_sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
+ if (off < el_sz)
+ {
+ tree cop = build3 (COMPONENT_REF, TREE_TYPE (field),
+ op, field, NULL_TREE);
+ if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, type, cop,
+ off, empty_base))
+ return ret;
+ }
+ }
for (tree field = TYPE_FIELDS (optype);
field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
@@ -4409,13 +4737,13 @@ cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op,
if (!tree_fits_uhwi_p (pos))
continue;
unsigned HOST_WIDE_INT upos = tree_to_uhwi (pos);
- unsigned el_sz
+ unsigned HOST_WIDE_INT el_sz
= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
if (upos <= off && off < upos + el_sz)
{
tree cop = build3 (COMPONENT_REF, TREE_TYPE (field),
op, field, NULL_TREE);
- if (tree ret = cxx_fold_indirect_ref_1 (loc, type, cop,
+ if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, type, cop,
off - upos,
empty_base))
return ret;
@@ -4436,7 +4764,8 @@ cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op,
with TBAA in fold_indirect_ref_1. */
static tree
-cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
+cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
+ tree op0, bool *empty_base)
{
tree sub = op0;
tree subtype;
@@ -4474,7 +4803,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
return op;
}
else
- return cxx_fold_indirect_ref_1 (loc, type, op, 0, empty_base);
+ return cxx_fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base);
}
else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
&& tree_fits_uhwi_p (TREE_OPERAND (sub, 1)))
@@ -4484,7 +4813,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
STRIP_NOPS (op00);
if (TREE_CODE (op00) == ADDR_EXPR)
- return cxx_fold_indirect_ref_1 (loc, type, TREE_OPERAND (op00, 0),
+ return cxx_fold_indirect_ref_1 (ctx, loc, type, TREE_OPERAND (op00, 0),
tree_to_uhwi (op01), empty_base);
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -4494,7 +4823,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
tree type_domain;
tree min_val = size_zero_node;
tree newsub
- = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
+ = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL);
if (newsub)
sub = newsub;
else
@@ -4529,8 +4858,8 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
}
/* First try to simplify it directly. */
- tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0,
- &empty_base);
+ tree r = cxx_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t),
+ orig_op0, &empty_base);
if (!r)
{
/* If that didn't work, evaluate the operand first. */
@@ -4549,7 +4878,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
return t;
}
- r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0,
+ r = cxx_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0,
&empty_base);
if (r == NULL_TREE)
{
@@ -4605,7 +4934,9 @@ non_const_var_error (location_t loc, tree r)
auto_diagnostic_group d;
tree type = TREE_TYPE (r);
if (DECL_NAME (r) == heap_uninit_identifier
- || DECL_NAME (r) == heap_identifier)
+ || DECL_NAME (r) == heap_identifier
+ || DECL_NAME (r) == heap_vec_uninit_identifier
+ || DECL_NAME (r) == heap_vec_identifier)
{
error_at (loc, "the content of uninitialized storage is not usable "
"in a constant expression");
@@ -5971,8 +6302,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
/* Evaluate the cleanups. */
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
cxx_eval_constant_expression (ctx, cleanup, false,
- non_constant_p, overflow_p,
- jump_target);
+ non_constant_p, overflow_p);
}
break;
@@ -5983,29 +6313,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (!*non_constant_p)
/* Also evaluate the cleanup. */
cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
- non_constant_p, overflow_p,
- jump_target);
+ non_constant_p, overflow_p);
break;
case CLEANUP_STMT:
- {
- tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
- r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
- non_constant_p, overflow_p,
- jump_target);
- if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
- {
- iloc_sentinel ils (loc);
- /* Also evaluate the cleanup. If we weren't skipping at the
- start of the CLEANUP_BODY, change jump_target temporarily
- to &initial_jump_target, so that even a return or break or
- continue in the body doesn't skip the cleanup. */
- cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
- non_constant_p, overflow_p,
- jump_target ? &initial_jump_target
- : NULL);
- }
- }
+ r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
+ non_constant_p, overflow_p,
+ jump_target);
+ if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
+ {
+ iloc_sentinel ils (loc);
+ /* Also evaluate the cleanup. */
+ cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
+ non_constant_p, overflow_p);
+ }
break;
/* These differ from cxx_eval_unary_expression in that this doesn't
@@ -6365,8 +6686,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
&& TREE_TYPE (op) == ptr_type_node
&& TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
&& VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
- && DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
- 0)) == heap_uninit_identifier)
+ && (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_uninit_identifier
+ || DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_vec_uninit_identifier))
{
tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
@@ -6380,7 +6703,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
elt_type = TREE_TYPE (TREE_TYPE (fld2));
cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
}
- DECL_NAME (var) = heap_identifier;
+ DECL_NAME (var)
+ = (DECL_NAME (var) == heap_uninit_identifier
+ ? heap_identifier : heap_vec_identifier);
TREE_TYPE (var)
= build_new_constexpr_heap_type (elt_type, cookie_size,
var_size);
@@ -6574,6 +6899,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
return t;
+ case BIT_CAST_EXPR:
+ r = cxx_eval_bit_cast (ctx, t, non_constant_p, overflow_p);
+ break;
+
default:
if (STATEMENT_CODE_P (TREE_CODE (t)))
{
@@ -6651,6 +6980,8 @@ find_heap_var_refs (tree *tp, int *walk_subtrees, void */*data*/)
if (VAR_P (*tp)
&& (DECL_NAME (*tp) == heap_uninit_identifier
|| DECL_NAME (*tp) == heap_identifier
+ || DECL_NAME (*tp) == heap_vec_uninit_identifier
+ || DECL_NAME (*tp) == heap_vec_identifier
|| DECL_NAME (*tp) == heap_deleted_identifier))
return *tp;
@@ -6872,6 +7203,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
non_constant_p = true;
}
+ if (non_constant_p)
+ /* If we saw something bad, go back to our argument. The wrapping below is
+ only for the cases of TREE_CONSTANT argument or overflow. */
+ r = t;
if (!non_constant_p && overflow_p)
non_constant_p = true;
@@ -6888,12 +7223,6 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
return r;
else if (non_constant_p && TREE_CONSTANT (r))
{
- /* If __builtin_is_constant_evaluated () was evaluated to true
- and the result is not a valid constant expression, we need to
- punt. */
- if (manifestly_const_eval)
- return cxx_eval_outermost_constant_expr (t, true, strict,
- false, false, object);
/* This isn't actually constant, so unset TREE_CONSTANT.
Don't clear TREE_CONSTANT on ADDR_EXPR, as the middle-end requires
it to be set if it is invariant address, even when it is not
@@ -7085,15 +7414,13 @@ clear_cv_cache (void)
cv_cache->empty ();
}
-/* Dispose of the whole CV_CACHE, FOLD_CACHE, and satisfaction caches. */
+/* Dispose of the whole CV_CACHE and FOLD_CACHE. */
void
-clear_cv_and_fold_caches (bool sat /*= true*/)
+clear_cv_and_fold_caches ()
{
clear_cv_cache ();
clear_fold_cache ();
- if (sat)
- clear_satisfaction_cache ();
}
/* Internal function handling expressions in templates for
@@ -7199,7 +7526,8 @@ maybe_fold_non_dependent_expr (tree expr,
tree
fold_non_dependent_init (tree t,
tsubst_flags_t complain /*=tf_warning_or_error*/,
- bool manifestly_const_eval /*=false*/)
+ bool manifestly_const_eval /*=false*/,
+ tree object /* = NULL_TREE */)
{
if (t == NULL_TREE)
return NULL_TREE;
@@ -7207,7 +7535,7 @@ fold_non_dependent_init (tree t,
if (processing_template_decl)
{
t = fold_non_dependent_expr_template (t, complain,
- manifestly_const_eval, NULL_TREE);
+ manifestly_const_eval, object);
/* maybe_constant_init does this stripping, so do it here too. */
if (TREE_CODE (t) == TARGET_EXPR)
{
@@ -7218,7 +7546,7 @@ fold_non_dependent_init (tree t,
return t;
}
- return maybe_constant_init (t, NULL_TREE, manifestly_const_eval);
+ return maybe_constant_init (t, object, manifestly_const_eval);
}
/* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
@@ -7445,7 +7773,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case OVERLOAD:
case TEMPLATE_ID_EXPR:
case LABEL_DECL:
- case LABEL_EXPR:
case CASE_LABEL_EXPR:
case PREDICT_EXPR:
case CONST_DECL:
@@ -7665,6 +7992,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
}
return false;
}
+ /* Treat __PRETTY_FUNCTION__ inside a template function as
+ potentially-constant. */
+ else if (DECL_PRETTY_FUNCTION_P (t)
+ && DECL_VALUE_EXPR (t) == error_mark_node)
+ return true;
return RECUR (DECL_VALUE_EXPR (t), rval);
}
if (want_rval
@@ -8349,9 +8681,20 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false;
}
+ case LABEL_EXPR:
+ t = LABEL_EXPR_LABEL (t);
+ if (DECL_ARTIFICIAL (t))
+ return true;
+ else if (flags & tf_error)
+ error_at (loc, "label definition is not a constant expression");
+ return false;
+
case ANNOTATE_EXPR:
return RECUR (TREE_OPERAND (t, 0), rval);
+ case BIT_CAST_EXPR:
+ return RECUR (TREE_OPERAND (t, 0), rval);
+
/* Coroutine await, yield and return expressions are not. */
case CO_AWAIT_EXPR:
case CO_YIELD_EXPR:
@@ -8359,7 +8702,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false;
default:
- if (objc_is_property_ref (t))
+ if (objc_non_constant_expr_p (t))
return false;
sorry ("unexpected AST of kind %s", get_tree_code_name (TREE_CODE (t)));
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f4f5174..24fcbaa 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -98,7 +98,42 @@ struct subst_info
tree in_decl;
};
-static tree satisfy_constraint (tree, tree, subst_info);
+/* Provides additional context for satisfaction.
+
+ The flag noisy() controls whether to diagnose ill-formed satisfaction,
+ such as the satisfaction value of an atom being non-bool or non-constant.
+
+ The flag diagnose_unsatisfaction_p() controls whether to explain why
+ a constraint is not satisfied.
+
+ The entrypoints to satisfaction for which we set noisy+unsat are
+ diagnose_constraints and diagnose_nested_requirement. The entrypoints for
+ which we set noisy-unsat are the replays inside constraint_satisfaction_value,
+ evaluate_concept_check and tsubst_nested_requirement. In other entrypoints,
+ e.g. constraints_satisfied_p, we enter satisfaction quietly (both flags
+ cleared). */
+
+struct sat_info : subst_info
+{
+ sat_info (tsubst_flags_t cmp, tree in, bool diag_unsat = false)
+ : subst_info (cmp, in), diagnose_unsatisfaction (diag_unsat)
+ {
+ if (diagnose_unsatisfaction_p ())
+ gcc_checking_assert (noisy ());
+ }
+
+ /* True if we should diagnose the cause of satisfaction failure.
+ Implies noisy(). */
+ bool
+ diagnose_unsatisfaction_p () const
+ {
+ return diagnose_unsatisfaction;
+ }
+
+ bool diagnose_unsatisfaction;
+};
+
+static tree satisfy_constraint (tree, tree, sat_info);
/* True if T is known to be some type other than bool. Note that this
is false for dependent types and errors. */
@@ -533,9 +568,9 @@ debug_argument_list (tree args)
{
tree arg = TREE_VEC_ELT (args, i);
if (TYPE_P (arg))
- verbatim ("ARG %qT", arg);
+ verbatim ("argument %qT", arg);
else
- verbatim ("ARG %qE", arg);
+ verbatim ("argument %qE", arg);
}
}
@@ -584,7 +619,8 @@ build_parameter_mapping (tree expr, tree args, tree decl)
return map;
}
-/* True if the parameter mappings of two atomic constraints are equivalent. */
+/* True if the parameter mappings of two atomic constraints formed
+ from the same expression are equivalent. */
static bool
parameter_mapping_equivalent_p (tree t1, tree t2)
@@ -593,6 +629,7 @@ parameter_mapping_equivalent_p (tree t1, tree t2)
tree map2 = ATOMIC_CONSTR_MAP (t2);
while (map1 && map2)
{
+ gcc_checking_assert (TREE_VALUE (map1) == TREE_VALUE (map2));
tree arg1 = TREE_PURPOSE (map1);
tree arg2 = TREE_PURPOSE (map2);
if (!template_args_equal (arg1, arg2))
@@ -600,6 +637,7 @@ parameter_mapping_equivalent_p (tree t1, tree t2)
map1 = TREE_CHAIN (map1);
map2 = TREE_CHAIN (map2);
}
+ gcc_checking_assert (!map1 && !map2);
return true;
}
@@ -616,7 +654,8 @@ struct norm_info : subst_info
norm_info (tree in_decl, tsubst_flags_t complain)
: subst_info (tf_warning_or_error | complain, in_decl),
- context (make_context (in_decl))
+ context (make_context (in_decl)),
+ orig_decl (in_decl)
{}
bool generate_diagnostics() const
@@ -647,6 +686,12 @@ struct norm_info : subst_info
for that check. */
tree context;
+
+ /* The declaration whose constraints we're normalizing. The targets
+ of the parameter mapping of each atom will be in terms of the
+ template parameters of ORIG_DECL. */
+
+ tree orig_decl = NULL_TREE;
};
static tree normalize_expression (tree, tree, norm_info);
@@ -686,7 +731,8 @@ normalize_concept_check (tree check, tree args, norm_info info)
}
/* Substitute through the arguments of the concept check. */
- targs = tsubst_template_args (targs, args, info.complain, info.in_decl);
+ if (args)
+ targs = tsubst_template_args (targs, args, info.complain, info.in_decl);
if (targs == error_mark_node)
return error_mark_node;
@@ -709,6 +755,10 @@ normalize_concept_check (tree check, tree args, norm_info info)
return normalize_expression (def, subst, info);
}
+/* Used by normalize_atom to cache ATOMIC_CONSTRs. */
+
+static GTY((deletable)) hash_table<atom_hasher> *atom_cache;
+
/* The normal form of an atom depends on the expression. The normal
form of a function call to a function concept is a check constraint
for that concept. The normal form of a reference to a variable
@@ -728,7 +778,41 @@ normalize_atom (tree t, tree args, norm_info info)
/* Build a new info object for the atom. */
tree ci = build_tree_list (t, info.context);
- return build1 (ATOMIC_CONSTR, ci, map);
+ tree atom = build1 (ATOMIC_CONSTR, ci, map);
+ if (!info.generate_diagnostics ())
+ {
+ /* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal
+ later can cheaply compare two atoms using just pointer equality. */
+ if (!atom_cache)
+ atom_cache = hash_table<atom_hasher>::create_ggc (31);
+ tree *slot = atom_cache->find_slot (atom, INSERT);
+ if (*slot)
+ return *slot;
+
+ /* Find all template parameters used in the targets of the parameter
+ mapping, and store a list of them in the TREE_TYPE of the mapping.
+ This list will be used by sat_hasher to determine the subset of
+ supplied template arguments that the satisfaction value of the atom
+ depends on. */
+ if (map)
+ {
+ tree targets = make_tree_vec (list_length (map));
+ int i = 0;
+ for (tree node = map; node; node = TREE_CHAIN (node))
+ {
+ tree target = TREE_PURPOSE (node);
+ TREE_VEC_ELT (targets, i++) = target;
+ }
+ tree ctx_parms = (info.orig_decl
+ ? DECL_TEMPLATE_PARMS (info.orig_decl)
+ : current_template_parms);
+ tree target_parms = find_template_parameters (targets, ctx_parms);
+ TREE_TYPE (map) = target_parms;
+ }
+
+ *slot = atom;
+ }
+ return atom;
}
/* Returns the normal form of an expression. */
@@ -758,20 +842,18 @@ normalize_expression (tree t, tree args, norm_info info)
static GTY((deletable)) hash_map<tree,tree> *normalized_map;
static tree
-get_normalized_constraints (tree t, tree args, norm_info info)
+get_normalized_constraints (tree t, norm_info info)
{
auto_timevar time (TV_CONSTRAINT_NORM);
- return normalize_expression (t, args, info);
+ return normalize_expression (t, NULL_TREE, info);
}
/* Returns the normalized constraints from a constraint-info object
- or NULL_TREE if the constraints are null. ARGS provide the initial
- arguments for normalization and IN_DECL provides the declaration
- to which the constraints belong. */
+ or NULL_TREE if the constraints are null. IN_DECL provides the
+ declaration to which the constraints belong. */
static tree
-get_normalized_constraints_from_info (tree ci, tree args, tree in_decl,
- bool diag = false)
+get_normalized_constraints_from_info (tree ci, tree in_decl, bool diag = false)
{
if (ci == NULL_TREE)
return NULL_TREE;
@@ -779,8 +861,7 @@ get_normalized_constraints_from_info (tree ci, tree args, tree in_decl,
/* Substitution errors during normalization are fatal. */
++processing_template_decl;
norm_info info (in_decl, diag ? tf_norm : tf_none);
- tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci),
- args, info);
+ tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci), info);
--processing_template_decl;
return t;
@@ -840,11 +921,17 @@ get_normalized_constraints_from_decl (tree d, bool diag = false)
if (tree *p = hash_map_safe_get (normalized_map, tmpl))
return *p;
- push_nested_class_guard pncs (DECL_CONTEXT (d));
+ tree norm = NULL_TREE;
+ if (tree ci = get_constraints (decl))
+ {
+ push_nested_class_guard pncs (DECL_CONTEXT (d));
+
+ temp_override<tree> ovr (current_function_decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ current_function_decl = decl;
- tree args = generic_targs_for (tmpl);
- tree ci = get_constraints (decl);
- tree norm = get_normalized_constraints_from_info (ci, args, tmpl, diag);
+ norm = get_normalized_constraints_from_info (ci, tmpl, diag);
+ }
if (!diag)
hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
@@ -865,11 +952,10 @@ normalize_concept_definition (tree tmpl, bool diag = false)
if (OVL_P (tmpl))
tmpl = OVL_FIRST (tmpl);
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
- tree args = generic_targs_for (tmpl);
tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl));
++processing_template_decl;
norm_info info (tmpl, diag ? tf_norm : tf_none);
- tree norm = get_normalized_constraints (def, args, info);
+ tree norm = get_normalized_constraints (def, info);
--processing_template_decl;
if (!diag)
@@ -894,42 +980,20 @@ normalize_nontemplate_requirements (tree decl, bool diag = false)
return get_normalized_constraints_from_decl (decl, diag);
}
-/* Normalize an EXPR as a constraint using ARGS. */
+/* Normalize an EXPR as a constraint. */
static tree
-normalize_constraint_expression (tree expr, tree args, bool diag = false)
+normalize_constraint_expression (tree expr, bool diag)
{
if (!expr || expr == error_mark_node)
return expr;
++processing_template_decl;
norm_info info (diag ? tf_norm : tf_none);
- tree norm = get_normalized_constraints (expr, args, info);
+ tree norm = get_normalized_constraints (expr, info);
--processing_template_decl;
return norm;
}
-/* Normalize an EXPR as a constraint. */
-
-static tree
-normalize_constraint_expression (tree expr, bool diag = false)
-{
- if (!expr || expr == error_mark_node)
- return expr;
-
- /* For concept checks, use the supplied template arguments as those used
- for normalization. Otherwise, there are no template arguments. */
- tree args;
- if (concept_check_p (expr))
- {
- tree id = unpack_concept_check (expr);
- args = TREE_OPERAND (id, 1);
- }
- else
- args = NULL_TREE;
-
- return normalize_constraint_expression (expr, args, diag);
-}
-
/* 17.4.1.2p2. Two constraints are identical if they are formed
from the same expression and the targets of the parameter mapping
are equivalent. */
@@ -2031,13 +2095,16 @@ tsubst_compound_requirement (tree t, tree args, subst_info info)
static tree
tsubst_nested_requirement (tree t, tree args, subst_info info)
{
- /* Ensure that we're in an evaluation context prior to satisfaction. */
- tree norm = TREE_TYPE (t);
- tree result = satisfy_constraint (norm, args, info);
- if (result == error_mark_node && info.quiet ())
+ /* Perform satisfaction quietly with the regular normal form. */
+ sat_info quiet (tf_none, info.in_decl);
+ tree norm = TREE_VALUE (TREE_TYPE (t));
+ tree diag_norm = TREE_PURPOSE (TREE_TYPE (t));
+ tree result = satisfy_constraint (norm, args, quiet);
+ if (result == error_mark_node)
{
- subst_info noisy (tf_warning_or_error, info.in_decl);
- satisfy_constraint (norm, args, noisy);
+ /* Replay the error using the diagnostic normal form. */
+ sat_info noisy (tf_warning_or_error, info.in_decl);
+ satisfy_constraint (diag_norm, args, noisy);
}
if (result != boolean_true_node)
return error_mark_node;
@@ -2278,6 +2345,16 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info)
new_arg = tsubst_template_arg (arg, args, complain, in_decl);
if (TYPE_P (new_arg))
new_arg = canonicalize_type_argument (new_arg, complain);
+ if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK)
+ {
+ tree pack_args = ARGUMENT_PACK_ARGS (new_arg);
+ for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++)
+ {
+ tree& pack_arg = TREE_VEC_ELT (pack_args, i);
+ if (TYPE_P (pack_arg))
+ pack_arg = canonicalize_type_argument (pack_arg, complain);
+ }
+ }
}
if (new_arg == error_mark_node)
return error_mark_node;
@@ -2297,28 +2374,156 @@ tsubst_parameter_mapping (tree map, tree args, tsubst_flags_t complain, tree in_
Constraint satisfaction
---------------------------------------------------------------------------*/
-/* Hash functions for satisfaction entries. */
+/* True if we are currently satisfying a constraint. */
+
+static bool satisfying_constraint;
+
+/* A vector of incomplete types (and of declarations with undeduced return type),
+ appended to by note_failed_type_completion_for_satisfaction. The
+ satisfaction caches use this in order to keep track of "potentially unstable"
+ satisfaction results.
+
+ Since references to entries in this vector are stored only in the
+ GC-deletable sat_cache, it's safe to make this deletable as well. */
+
+static GTY((deletable)) vec<tree, va_gc> *failed_type_completions;
+
+/* Called whenever a type completion (or return type deduction) failure occurs
+ that definitely affects the meaning of the program, by e.g. inducing
+ substitution failure. */
+
+void
+note_failed_type_completion_for_satisfaction (tree t)
+{
+ if (satisfying_constraint)
+ {
+ gcc_checking_assert ((TYPE_P (t) && !COMPLETE_TYPE_P (t))
+ || (DECL_P (t) && undeduced_auto_decl (t)));
+ vec_safe_push (failed_type_completions, t);
+ }
+}
+
+/* Returns true if the range [BEGIN, END) of elements within the
+ failed_type_completions vector contains a complete type (or a
+ declaration with a non-placeholder return type). */
+
+static bool
+some_type_complete_p (int begin, int end)
+{
+ for (int i = begin; i < end; i++)
+ {
+ tree t = (*failed_type_completions)[i];
+ if (TYPE_P (t) && COMPLETE_TYPE_P (t))
+ return true;
+ if (DECL_P (t) && !undeduced_auto_decl (t))
+ return true;
+ }
+ return false;
+}
+
+/* Hash functions and data types for satisfaction cache entries. */
struct GTY((for_user)) sat_entry
{
- tree constr;
+ /* The relevant ATOMIC_CONSTR. */
+ tree atom;
+
+ /* The relevant template arguments. */
tree args;
+
+ /* The result of satisfaction of ATOM+ARGS.
+ This is either boolean_true_node, boolean_false_node or error_mark_node,
+ where error_mark_node indicates ill-formed satisfaction.
+ It's set to NULL_TREE while computing satisfaction of ATOM+ARGS for
+ the first time. */
tree result;
+
+ /* The value of input_location when satisfaction of ATOM+ARGS was first
+ performed. */
+ location_t location;
+
+ /* The range of elements appended to the failed_type_completions vector
+ during computation of this satisfaction result, encoded as a begin/end
+ pair of offsets. */
+ int ftc_begin, ftc_end;
+
+ /* True if we want to diagnose the above instability when it's detected.
+ We don't always want to do so, in order to avoid emitting duplicate
+ diagnostics in some cases. */
+ bool diagnose_instability;
+
+ /* True if we're in the middle of computing this satisfaction result.
+ Used during both quiet and noisy satisfaction to detect self-recursive
+ satisfaction. */
+ bool evaluating;
};
struct sat_hasher : ggc_ptr_hash<sat_entry>
{
static hashval_t hash (sat_entry *e)
{
- hashval_t value = hash_atomic_constraint (e->constr);
- return iterative_hash_template_arg (e->args, value);
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e->atom))
+ {
+ /* Atoms with instantiated mappings are built during satisfaction.
+ They live only inside the sat_cache, and we build one to query
+ the cache with each time we instantiate a mapping. */
+ gcc_assert (!e->args);
+ return hash_atomic_constraint (e->atom);
+ }
+
+ /* Atoms with uninstantiated mappings are built during normalization.
+ Since normalize_atom caches the atoms it returns, we can assume
+ pointer-based identity for fast hashing and comparison. Even if this
+ assumption is violated, that's okay, we'll just get a cache miss. */
+ hashval_t value = htab_hash_pointer (e->atom);
+
+ if (tree map = ATOMIC_CONSTR_MAP (e->atom))
+ /* Only the parameters that are used in the targets of the mapping
+ affect the satisfaction value of the atom. So we consider only
+ the arguments for these parameters, and ignore the rest. */
+ for (tree target_parms = TREE_TYPE (map);
+ target_parms;
+ target_parms = TREE_CHAIN (target_parms))
+ {
+ int level, index;
+ tree parm = TREE_VALUE (target_parms);
+ template_parm_level_and_index (parm, &level, &index);
+ tree arg = TMPL_ARG (e->args, level, index);
+ value = iterative_hash_template_arg (arg, value);
+ }
+ return value;
}
static bool equal (sat_entry *e1, sat_entry *e2)
{
- if (!atomic_constraints_identical_p (e1->constr, e2->constr))
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e1->atom)
+ != ATOMIC_CONSTR_MAP_INSTANTIATED_P (e2->atom))
return false;
- return template_args_equal (e1->args, e2->args);
+
+ /* See sat_hasher::hash. */
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e1->atom))
+ {
+ gcc_assert (!e1->args && !e2->args);
+ return atomic_constraints_identical_p (e1->atom, e2->atom);
+ }
+
+ if (e1->atom != e2->atom)
+ return false;
+
+ if (tree map = ATOMIC_CONSTR_MAP (e1->atom))
+ for (tree target_parms = TREE_TYPE (map);
+ target_parms;
+ target_parms = TREE_CHAIN (target_parms))
+ {
+ int level, index;
+ tree parm = TREE_VALUE (target_parms);
+ template_parm_level_and_index (parm, &level, &index);
+ tree arg1 = TMPL_ARG (e1->args, level, index);
+ tree arg2 = TMPL_ARG (e2->args, level, index);
+ if (!template_args_equal (arg1, arg2))
+ return false;
+ }
+ return true;
}
};
@@ -2328,82 +2533,168 @@ static GTY((deletable)) hash_table<sat_hasher> *sat_cache;
/* Cache the result of constraint_satisfaction_value. */
static GTY((deletable)) hash_map<tree, tree> *decl_satisfied_cache;
-static tree
-get_satisfaction (tree constr, tree args)
+/* A tool used by satisfy_atom to help manage satisfaction caching and to
+ diagnose "unstable" satisfaction values. We insert into the cache only
+ when performing satisfaction quietly. */
+
+struct satisfaction_cache
{
- if (!sat_cache)
- return NULL_TREE;
- sat_entry elt = { constr, args, NULL_TREE };
- sat_entry* found = sat_cache->find (&elt);
- if (found)
- return found->result;
- else
- return NULL_TREE;
-}
+ satisfaction_cache (tree, tree, sat_info);
+ tree get ();
+ tree save (tree);
-static void
-save_satisfaction (tree constr, tree args, tree result)
+ sat_entry *entry;
+ sat_info info;
+ int ftc_begin;
+};
+
+/* Constructor for the satisfaction_cache class. We're performing satisfaction
+ of ATOM+ARGS according to INFO. */
+
+satisfaction_cache
+::satisfaction_cache (tree atom, tree args, sat_info info)
+ : entry(nullptr), info(info), ftc_begin(-1)
{
if (!sat_cache)
sat_cache = hash_table<sat_hasher>::create_ggc (31);
- sat_entry elt = {constr, args, result};
- sat_entry** slot = sat_cache->find_slot (&elt, INSERT);
- sat_entry* entry = ggc_alloc<sat_entry> ();
- *entry = elt;
- *slot = entry;
-}
-void
-clear_satisfaction_cache ()
-{
- if (sat_cache)
- sat_cache->empty ();
- if (decl_satisfied_cache)
- decl_satisfied_cache->empty ();
+ /* When noisy, we query the satisfaction cache in order to diagnose
+ "unstable" satisfaction values. */
+ if (info.noisy ())
+ {
+ /* When noisy, constraints have been re-normalized, and that breaks the
+ pointer-based identity assumption of sat_cache (for atoms with
+ uninstantiated mappings). So undo this re-normalization by looking in
+ the atom_cache for the corresponding atom that was used during quiet
+ satisfaction. */
+ if (!ATOMIC_CONSTR_MAP_INSTANTIATED_P (atom))
+ {
+ if (tree found = atom_cache->find (atom))
+ atom = found;
+ else
+ /* The lookup should always succeed, but if it fails then let's
+ just leave 'entry' empty, effectively disabling the cache. */
+ return;
+ }
+ }
+
+ /* Look up or create the corresponding satisfaction entry. */
+ sat_entry elt;
+ elt.atom = atom;
+ elt.args = args;
+ sat_entry **slot = sat_cache->find_slot (&elt, INSERT);
+ if (*slot)
+ entry = *slot;
+ else if (info.quiet ())
+ {
+ entry = ggc_alloc<sat_entry> ();
+ entry->atom = atom;
+ entry->args = args;
+ entry->result = NULL_TREE;
+ entry->location = input_location;
+ entry->ftc_begin = entry->ftc_end = -1;
+ entry->diagnose_instability = false;
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (atom))
+ /* We always want to diagnose instability of an atom with an
+ instantiated parameter mapping. For atoms with an uninstantiated
+ mapping, we set this flag (in satisfy_atom) only if substitution
+ into its mapping previously failed. */
+ entry->diagnose_instability = true;
+ entry->evaluating = false;
+ *slot = entry;
+ }
+ else
+ /* We shouldn't get here, but if we do, let's just leave 'entry'
+ empty, effectively disabling the cache. */
+ return;
}
-/* A tool to help manage satisfaction caching in satisfy_constraint_r.
- Note the cache is only used when not diagnosing errors. */
+/* Returns the cached satisfaction result if we have one and we're not
+ recomputing the satisfaction result from scratch. Otherwise returns
+ NULL_TREE. */
-struct satisfaction_cache
+tree
+satisfaction_cache::get ()
{
- satisfaction_cache (tree constr, tree args, tsubst_flags_t complain)
- : constr(constr), args(args), complain(complain)
- { }
-
- tree get ()
- {
- if (complain == tf_none)
- return get_satisfaction (constr, args);
+ if (!entry)
return NULL_TREE;
- }
- tree save (tree result)
- {
- if (complain == tf_none)
- save_satisfaction (constr, args, result);
- return result;
- }
+ if (entry->evaluating)
+ {
+ /* If we get here, it means satisfaction is self-recursive. */
+ gcc_checking_assert (!entry->result);
+ if (info.noisy ())
+ error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom)),
+ "satisfaction of atomic constraint %qE depends on itself",
+ entry->atom);
+ return error_mark_node;
+ }
- tree constr;
- tree args;
- tsubst_flags_t complain;
-};
+ /* This satisfaction result is "potentially unstable" if a type for which
+ type completion failed during its earlier computation is now complete. */
+ bool maybe_unstable = some_type_complete_p (entry->ftc_begin,
+ entry->ftc_end);
-static int satisfying_constraint = 0;
+ if (info.noisy () || maybe_unstable || !entry->result)
+ {
+ /* We're computing the satisfaction result from scratch. */
+ entry->evaluating = true;
+ ftc_begin = vec_safe_length (failed_type_completions);
+ return NULL_TREE;
+ }
+ else
+ return entry->result;
+}
-/* Returns true if we are currently satisfying a constraint.
+/* RESULT is the computed satisfaction result. If RESULT differs from the
+ previously cached result, this routine issues an appropriate error.
+ Otherwise, when evaluating quietly, updates the cache appropriately. */
- This is used to guard against recursive calls to evaluate_concept_check
- during template argument substitution.
+tree
+satisfaction_cache::save (tree result)
+{
+ if (!entry)
+ return result;
- TODO: Do we need this now that we fully normalize prior to evaluation?
- I think not. */
+ gcc_checking_assert (entry->evaluating);
+ entry->evaluating = false;
-bool
-satisfying_constraint_p ()
-{
- return satisfying_constraint;
+ if (entry->result && result != entry->result)
+ {
+ if (info.quiet ())
+ /* Return error_mark_node to force satisfaction to get replayed
+ noisily. */
+ return error_mark_node;
+ else
+ {
+ if (entry->diagnose_instability)
+ {
+ auto_diagnostic_group d;
+ error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom)),
+ "satisfaction value of atomic constraint %qE changed "
+ "from %qE to %qE", entry->atom, entry->result, result);
+ inform (entry->location,
+ "satisfaction value first evaluated to %qE from here",
+ entry->result);
+ }
+ /* For sake of error recovery, allow this latest satisfaction result
+ to prevail. */
+ entry->result = result;
+ return result;
+ }
+ }
+
+ if (info.quiet ())
+ {
+ entry->result = result;
+ /* Store into this entry the list of relevant failed type completions
+ that occurred during (re)computation of the satisfaction result. */
+ gcc_checking_assert (ftc_begin != -1);
+ entry->ftc_begin = ftc_begin;
+ entry->ftc_end = vec_safe_length (failed_type_completions);
+ }
+
+ return result;
}
/* Substitute ARGS into constraint-expression T during instantiation of
@@ -2419,12 +2710,12 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return expr;
}
-static tree satisfy_constraint_r (tree, tree, subst_info info);
+static tree satisfy_constraint_r (tree, tree, sat_info info);
/* Compute the satisfaction of a conjunction. */
static tree
-satisfy_conjunction (tree t, tree args, subst_info info)
+satisfy_conjunction (tree t, tree args, sat_info info)
{
tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0), args, info);
if (lhs == error_mark_node || lhs == boolean_false_node)
@@ -2478,20 +2769,25 @@ collect_operands_of_disjunction (tree t, auto_vec<tree_pair> *operands)
/* Compute the satisfaction of a disjunction. */
static tree
-satisfy_disjunction (tree t, tree args, subst_info info)
+satisfy_disjunction (tree t, tree args, sat_info info)
{
- /* Evaluate the operands quietly. */
- subst_info quiet (tf_none, NULL_TREE);
+ /* Evaluate each operand with unsatisfaction diagnostics disabled. */
+ sat_info sub = info;
+ sub.diagnose_unsatisfaction = false;
- /* Register the constraint for diagnostics, if needed. */
- diagnosing_failed_constraint failure (t, args, info.noisy ());
+ tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0), args, sub);
+ if (lhs == boolean_true_node || lhs == error_mark_node)
+ return lhs;
- tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0), args, quiet);
- if (lhs == boolean_true_node)
- return boolean_true_node;
- tree rhs = satisfy_constraint_r (TREE_OPERAND (t, 1), args, quiet);
- if (rhs != boolean_true_node && info.noisy ())
+ tree rhs = satisfy_constraint_r (TREE_OPERAND (t, 1), args, sub);
+ if (rhs == boolean_true_node || rhs == error_mark_node)
+ return rhs;
+
+ /* Both branches evaluated to false. Explain the satisfaction failure in
+ each branch. */
+ if (info.diagnose_unsatisfaction_p ())
{
+ diagnosing_failed_constraint failure (t, args, info.noisy ());
cp_expr disj_expr = CONSTR_EXPR (t);
inform (disj_expr.get_location (),
"no operand of the disjunction is satisfied");
@@ -2512,7 +2808,8 @@ satisfy_disjunction (tree t, tree args, subst_info info)
}
}
}
- return rhs;
+
+ return boolean_false_node;
}
/* Ensures that T is a truth value and not (accidentally, as sometimes
@@ -2593,31 +2890,51 @@ static void diagnose_atomic_constraint (tree, tree, tree, subst_info);
/* Compute the satisfaction of an atomic constraint. */
static tree
-satisfy_atom (tree t, tree args, subst_info info)
+satisfy_atom (tree t, tree args, sat_info info)
{
- satisfaction_cache cache (t, args, info.complain);
+ /* In case there is a diagnostic, we want to establish the context
+ prior to printing errors. If no errors occur, this context is
+ removed before returning. */
+ diagnosing_failed_constraint failure (t, args, info.noisy ());
+
+ satisfaction_cache cache (t, args, info);
if (tree r = cache.get ())
return r;
/* Perform substitution quietly. */
subst_info quiet (tf_none, NULL_TREE);
- /* In case there is a diagnostic, we want to establish the context
- prior to printing errors. If no errors occur, this context is
- removed before returning. */
- diagnosing_failed_constraint failure (t, args, info.noisy ());
-
/* Instantiate the parameter mapping. */
tree map = tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t), args, quiet);
if (map == error_mark_node)
{
- /* If instantiation of the parameter mapping fails, the program
- is ill-formed. */
- if (info.noisy())
+ /* If instantiation of the parameter mapping fails, the constraint is
+ not satisfied. Replay the substitution. */
+ if (info.diagnose_unsatisfaction_p ())
tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t), args, info);
+ if (info.quiet ())
+ /* Since instantiation of the parameter mapping failed, we
+ want to diagnose potential instability of this satisfaction
+ result. */
+ cache.entry->diagnose_instability = true;
return cache.save (boolean_false_node);
}
+ /* Now build a new atom using the instantiated mapping. We use
+ this atom as a second key to the satisfaction cache, and we
+ also pass it to diagnose_atomic_constraint so that diagnostics
+ which refer to the atom display the instantiated mapping. */
+ t = copy_node (t);
+ ATOMIC_CONSTR_MAP (t) = map;
+ gcc_assert (!ATOMIC_CONSTR_MAP_INSTANTIATED_P (t));
+ ATOMIC_CONSTR_MAP_INSTANTIATED_P (t) = true;
+ satisfaction_cache inst_cache (t, /*args=*/NULL_TREE, info);
+ if (tree r = inst_cache.get ())
+ {
+ cache.entry->location = inst_cache.entry->location;
+ return cache.save (r);
+ }
+
/* Rebuild the argument vector from the parameter mapping. */
args = get_mapped_args (map);
@@ -2628,21 +2945,21 @@ satisfy_atom (tree t, tree args, subst_info info)
{
/* If substitution results in an invalid type or expression, the constraint
is not satisfied. Replay the substitution. */
- if (info.noisy ())
+ if (info.diagnose_unsatisfaction_p ())
tsubst_expr (expr, args, info.complain, info.in_decl, false);
- return cache.save (boolean_false_node);
+ return cache.save (inst_cache.save (boolean_false_node));
}
/* [17.4.1.2] ... lvalue-to-rvalue conversion is performed as necessary,
and EXPR shall be a constant expression of type bool. */
result = force_rvalue (result, info.complain);
if (result == error_mark_node)
- return cache.save (error_mark_node);
+ return cache.save (inst_cache.save (error_mark_node));
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
{
if (info.noisy ())
diagnose_atomic_constraint (t, map, result, info);
- return cache.save (error_mark_node);
+ return cache.save (inst_cache.save (error_mark_node));
}
/* Compute the value of the constraint. */
@@ -2656,10 +2973,10 @@ satisfy_atom (tree t, tree args, subst_info info)
result = error_mark_node;
}
result = satisfaction_value (result);
- if (result == boolean_false_node && info.noisy ())
+ if (result == boolean_false_node && info.diagnose_unsatisfaction_p ())
diagnose_atomic_constraint (t, map, result, info);
- return cache.save (result);
+ return cache.save (inst_cache.save (result));
}
/* Determine if the normalized constraint T is satisfied.
@@ -2674,7 +2991,7 @@ satisfy_atom (tree t, tree args, subst_info info)
constraint only matters for subsumption. */
static tree
-satisfy_constraint_r (tree t, tree args, subst_info info)
+satisfy_constraint_r (tree t, tree args, sat_info info)
{
if (t == error_mark_node)
return error_mark_node;
@@ -2695,10 +3012,12 @@ satisfy_constraint_r (tree t, tree args, subst_info info)
/* Check that the normalized constraint T is satisfied for ARGS. */
static tree
-satisfy_constraint (tree t, tree args, subst_info info)
+satisfy_constraint (tree t, tree args, sat_info info)
{
auto_timevar time (TV_CONSTRAINT_SAT);
+ auto ovr = make_temp_override (satisfying_constraint, true);
+
/* Turn off template processing. Constraint satisfaction only applies
to non-dependent terms, so we want to ensure full checking here. */
processing_template_decl_sentinel proc (true);
@@ -2713,7 +3032,7 @@ satisfy_constraint (tree t, tree args, subst_info info)
value (either true, false, or error). */
static tree
-satisfy_associated_constraints (tree t, tree args, subst_info info)
+satisfy_associated_constraints (tree t, tree args, sat_info info)
{
/* If there are no constraints then this is trivially satisfied. */
if (!t)
@@ -2731,7 +3050,7 @@ satisfy_associated_constraints (tree t, tree args, subst_info info)
satisfaction value. */
static tree
-satisfy_constraint_expression (tree t, tree args, subst_info info)
+satisfy_constraint_expression (tree t, tree args, sat_info info)
{
if (t == error_mark_node)
return error_mark_node;
@@ -2760,12 +3079,12 @@ satisfy_constraint_expression (tree t, tree args, subst_info info)
tree
satisfy_constraint_expression (tree expr)
{
- subst_info info (tf_none, NULL_TREE);
+ sat_info info (tf_none, NULL_TREE);
return satisfy_constraint_expression (expr, NULL_TREE, info);
}
static tree
-satisfy_declaration_constraints (tree t, subst_info info)
+satisfy_declaration_constraints (tree t, sat_info info)
{
gcc_assert (DECL_P (t));
const tree saved_t = t;
@@ -2807,6 +3126,8 @@ satisfy_declaration_constraints (tree t, subst_info info)
norm = normalize_nontemplate_requirements (t, info.noisy ());
}
+ unsigned ftc_count = vec_safe_length (failed_type_completions);
+
tree result = boolean_true_node;
if (norm)
{
@@ -2818,14 +3139,26 @@ satisfy_declaration_constraints (tree t, subst_info info)
pop_tinst_level ();
}
- if (info.quiet ())
+ /* True if this satisfaction is (heuristically) potentially unstable, i.e.
+ if its result may depend on where in the program it was performed. */
+ bool maybe_unstable_satisfaction = false;
+ if (ftc_count != vec_safe_length (failed_type_completions))
+ /* Type completion failure occurred during satisfaction. The satisfaction
+ result may (or may not) materially depend on the completeness of a type,
+ so we consider it potentially unstable. */
+ maybe_unstable_satisfaction = true;
+
+ if (maybe_unstable_satisfaction)
+ /* Don't cache potentially unstable satisfaction, to allow satisfy_atom
+ to check the stability the next time around. */;
+ else if (info.quiet ())
hash_map_safe_put<hm_ggc> (decl_satisfied_cache, saved_t, result);
return result;
}
static tree
-satisfy_declaration_constraints (tree t, tree args, subst_info info)
+satisfy_declaration_constraints (tree t, tree args, sat_info info)
{
/* Update the declaration for diagnostics. */
info.in_decl = t;
@@ -2850,9 +3183,8 @@ satisfy_declaration_constraints (tree t, tree args, subst_info info)
}
static tree
-constraint_satisfaction_value (tree t, tsubst_flags_t complain)
+constraint_satisfaction_value (tree t, sat_info info)
{
- subst_info info (complain, NULL_TREE);
tree r;
if (DECL_P (t))
r = satisfy_declaration_constraints (t, info);
@@ -2860,26 +3192,31 @@ constraint_satisfaction_value (tree t, tsubst_flags_t complain)
r = satisfy_constraint_expression (t, NULL_TREE, info);
if (r == error_mark_node && info.quiet ()
&& !(DECL_P (t) && TREE_NO_WARNING (t)))
- {
- constraint_satisfaction_value (t, tf_warning_or_error);
- if (DECL_P (t))
- /* Avoid giving these errors again. */
- TREE_NO_WARNING (t) = true;
- }
+ {
+ /* Replay the error with re-normalized requirements. */
+ sat_info noisy (tf_warning_or_error, info.in_decl);
+ constraint_satisfaction_value (t, noisy);
+ if (DECL_P (t))
+ /* Avoid giving these errors again. */
+ TREE_NO_WARNING (t) = true;
+ }
return r;
}
static tree
-constraint_satisfaction_value (tree t, tree args, tsubst_flags_t complain)
+constraint_satisfaction_value (tree t, tree args, sat_info info)
{
- subst_info info (complain, NULL_TREE);
tree r;
if (DECL_P (t))
r = satisfy_declaration_constraints (t, args, info);
else
r = satisfy_constraint_expression (t, args, info);
if (r == error_mark_node && info.quiet ())
- constraint_satisfaction_value (t, args, tf_warning_or_error);
+ {
+ /* Replay the error with re-normalized requirements. */
+ sat_info noisy (tf_warning_or_error, info.in_decl);
+ constraint_satisfaction_value (t, args, noisy);
+ }
return r;
}
@@ -2892,7 +3229,8 @@ constraints_satisfied_p (tree t)
if (!flag_concepts)
return true;
- return constraint_satisfaction_value (t, tf_none) == boolean_true_node;
+ sat_info quiet (tf_none, NULL_TREE);
+ return constraint_satisfaction_value (t, quiet) == boolean_true_node;
}
/* True iff the result of satisfying T with ARGS is BOOLEAN_TRUE_NODE
@@ -2904,7 +3242,8 @@ constraints_satisfied_p (tree t, tree args)
if (!flag_concepts)
return true;
- return constraint_satisfaction_value (t, args, tf_none) == boolean_true_node;
+ sat_info quiet (tf_none, NULL_TREE);
+ return constraint_satisfaction_value (t, args, quiet) == boolean_true_node;
}
/* Evaluate a concept check of the form C<ARGS>. This is only used for the
@@ -2919,14 +3258,14 @@ evaluate_concept_check (tree check, tsubst_flags_t complain)
gcc_assert (concept_check_p (check));
/* Check for satisfaction without diagnostics. */
- subst_info quiet (tf_none, NULL_TREE);
+ sat_info quiet (tf_none, NULL_TREE);
tree result = satisfy_constraint_expression (check, NULL_TREE, quiet);
if (result == error_mark_node && (complain & tf_error))
- {
- /* Replay the error with re-normalized requirements. */
- subst_info noisy (tf_warning_or_error, NULL_TREE);
- satisfy_constraint_expression (check, NULL_TREE, noisy);
- }
+ {
+ /* Replay the error with re-normalized requirements. */
+ sat_info noisy (tf_warning_or_error, NULL_TREE);
+ satisfy_constraint_expression (check, NULL_TREE, noisy);
+ }
return result;
}
@@ -2997,12 +3336,15 @@ finish_compound_requirement (location_t loc, tree expr, tree type, bool noexcept
tree
finish_nested_requirement (location_t loc, tree expr)
{
- /* Currently open template headers have dummy arg vectors, so don't
- pass into normalization. */
- tree norm = normalize_constraint_expression (expr, NULL_TREE, false);
+ /* We need to normalize the constraints now, at parse time, while
+ we have the necessary template context. We normalize twice,
+ once without diagnostic information and once with, which we'll
+ later use for quiet and noisy satisfaction respectively. */
+ tree norm = normalize_constraint_expression (expr, /*diag=*/false);
+ tree diag_norm = normalize_constraint_expression (expr, /*diag=*/true);
- /* Build the constraint, saving its normalization as its type. */
- tree r = build1 (NESTED_REQ, norm, expr);
+ /* Build the constraint, saving its two normalizations as its type. */
+ tree r = build1 (NESTED_REQ, build_tree_list (diag_norm, norm), expr);
SET_EXPR_LOCATION (r, loc);
return r;
}
@@ -3104,25 +3446,25 @@ subsumes_constraints (tree a, tree b)
return subsumes (a, b);
}
-/* Returns true when the constraints in CI (with arguments
- ARGS) strictly subsume the associated constraints of TMPL. */
+/* Returns true when the constraints in CI strictly subsume
+ the associated constraints of TMPL. */
bool
-strictly_subsumes (tree ci, tree args, tree tmpl)
+strictly_subsumes (tree ci, tree tmpl)
{
- tree n1 = get_normalized_constraints_from_info (ci, args, NULL_TREE);
+ tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE);
tree n2 = get_normalized_constraints_from_decl (tmpl);
return subsumes (n1, n2) && !subsumes (n2, n1);
}
-/* REturns true when the constraints in CI (with arguments ARGS) subsume
- the associated constraints of TMPL. */
+/* Returns true when the constraints in CI subsume the
+ associated constraints of TMPL. */
bool
-weakly_subsumes (tree ci, tree args, tree tmpl)
+weakly_subsumes (tree ci, tree tmpl)
{
- tree n1 = get_normalized_constraints_from_info (ci, args, NULL_TREE);
+ tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE);
tree n2 = get_normalized_constraints_from_decl (tmpl);
return subsumes (n1, n2);
@@ -3403,10 +3745,11 @@ diagnose_type_requirement (tree req, tree args, tree in_decl)
static void
diagnose_nested_requirement (tree req, tree args)
{
- /* Quietly check for satisfaction first. We can elaborate details
- later if needed. */
- tree norm = TREE_TYPE (req);
- subst_info info (tf_none, NULL_TREE);
+ /* Quietly check for satisfaction first using the regular normal form.
+ We can elaborate details later if needed. */
+ tree norm = TREE_VALUE (TREE_TYPE (req));
+ tree diag_norm = TREE_PURPOSE (TREE_TYPE (req));
+ sat_info info (tf_none, NULL_TREE);
tree result = satisfy_constraint (norm, args, info);
if (result == boolean_true_node)
return;
@@ -3415,10 +3758,10 @@ diagnose_nested_requirement (tree req, tree args)
location_t loc = cp_expr_location (expr);
if (diagnosing_failed_constraint::replay_errors_p ())
{
- /* Replay the substitution error. */
+ /* Replay the substitution error using the diagnostic normal form. */
inform (loc, "nested requirement %qE is not satisfied, because", expr);
- subst_info noisy (tf_warning_or_error, NULL_TREE);
- satisfy_constraint_expression (expr, args, noisy);
+ sat_info noisy (tf_warning_or_error, NULL_TREE, /*diag_unsat=*/true);
+ satisfy_constraint (diag_norm, args, noisy);
}
else
inform (loc, "nested requirement %qE is not satisfied", expr);
@@ -3501,14 +3844,11 @@ diagnose_atomic_constraint (tree t, tree map, tree result, subst_info info)
diagnose_requires_expr (expr, map, info.in_decl);
break;
default:
- tree a = copy_node (t);
- ATOMIC_CONSTR_MAP (a) = map;
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
error_at (loc, "constraint %qE has type %qT, not %<bool%>",
- a, TREE_TYPE (result));
+ t, TREE_TYPE (result));
else
- inform (loc, "the expression %qE evaluated to %<false%>", a);
- ggc_free (a);
+ inform (loc, "the expression %qE evaluated to %<false%>", t);
}
}
@@ -3564,11 +3904,12 @@ diagnose_constraints (location_t loc, tree t, tree args)
if (concepts_diagnostics_max_depth == 0)
return;
- /* Replay satisfaction, but diagnose errors. */
+ /* Replay satisfaction, but diagnose unsatisfaction. */
+ sat_info noisy (tf_warning_or_error, NULL_TREE, /*diag_unsat=*/true);
if (!args)
- constraint_satisfaction_value (t, tf_warning_or_error);
+ constraint_satisfaction_value (t, noisy);
else
- constraint_satisfaction_value (t, args, tf_warning_or_error);
+ constraint_satisfaction_value (t, args, noisy);
static bool suggested_p;
if (concepts_diagnostics_max_depth_exceeded_p
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 9b9141e..fd6cda4 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -3756,7 +3756,7 @@ act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name)
/* Copy selected attributes from the original function. */
TREE_USED (fn) = TREE_USED (orig);
if (DECL_SECTION_NAME (orig))
- set_decl_section_name (fn, DECL_SECTION_NAME (orig));
+ set_decl_section_name (fn, orig);
/* Copy any alignment that the FE added. */
if (DECL_ALIGN (orig))
SET_DECL_ALIGN (fn, DECL_ALIGN (orig));
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 44c9d24..110d25e 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -680,22 +680,6 @@ is_invisiref_parm (const_tree t)
&& DECL_BY_REFERENCE (t));
}
-/* Return true if the uid in both int tree maps are equal. */
-
-bool
-cxx_int_tree_map_hasher::equal (cxx_int_tree_map *a, cxx_int_tree_map *b)
-{
- return (a->uid == b->uid);
-}
-
-/* Hash a UID in a cxx_int_tree_map. */
-
-unsigned int
-cxx_int_tree_map_hasher::hash (cxx_int_tree_map *item)
-{
- return item->uid;
-}
-
/* A stable comparison routine for use with splay trees and DECLs. */
static int
@@ -898,7 +882,7 @@ static tree genericize_spaceship (tree expr)
tree type = TREE_TYPE (expr);
tree op0 = TREE_OPERAND (expr, 0);
tree op1 = TREE_OPERAND (expr, 1);
- return genericize_spaceship (type, op0, op1);
+ return genericize_spaceship (input_location, type, op0, op1);
}
/* If EXPR involves an anonymous VLA type, prepend a DECL_EXPR for that type
@@ -1390,6 +1374,14 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
break;
}
+ if (tree fndecl = cp_get_callee_fndecl (stmt))
+ if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ {
+ gcc_assert (source_location_current_p (fndecl));
+ *stmt_p = cxx_constant_value (stmt);
+ break;
+ }
+
if (!wtd->no_sanitize_p
&& sanitize_flags_p ((SANITIZE_NULL
| SANITIZE_ALIGNMENT | SANITIZE_VPTR)))
@@ -1568,6 +1560,11 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
cp_genericize_r, cp_walk_subtrees);
break;
+ case BIT_CAST_EXPR:
+ *stmt_p = build1_loc (EXPR_LOCATION (stmt), VIEW_CONVERT_EXPR,
+ TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
+ break;
+
default:
if (IS_TYPE_OR_DECL_P (stmt))
*walk_subtrees = 0;
@@ -2934,6 +2931,21 @@ struct source_location_table_entry_hash
&& ref.uid == 0
&& ref.var == NULL_TREE);
}
+
+ static void
+ pch_nx (source_location_table_entry &p)
+ {
+ extern void gt_pch_nx (source_location_table_entry &);
+ gt_pch_nx (p);
+ }
+
+ static void
+ pch_nx (source_location_table_entry &p, gt_pointer_operator op, void *cookie)
+ {
+ extern void gt_pch_nx (source_location_table_entry *, gt_pointer_operator,
+ void *);
+ gt_pch_nx (&p, op, cookie);
+ }
};
static GTY(()) hash_table <source_location_table_entry_hash>
@@ -3008,7 +3020,7 @@ fold_builtin_source_location (location_t loc)
const char *name = "";
if (current_function_decl)
- name = cxx_printable_name (current_function_decl, 0);
+ name = cxx_printable_name (current_function_decl, 2);
val = build_string_literal (strlen (name) + 1, name);
}
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 9e980bc..0c3be0f 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -34,6 +34,8 @@ static tree cp_eh_personality (void);
static tree get_template_innermost_arguments_folded (const_tree);
static tree get_template_argument_pack_elems_folded (const_tree);
static tree cxx_enum_underlying_base_type (const_tree);
+static tree *cxx_omp_get_decl_init (tree);
+static void cxx_omp_finish_decl_inits (void);
/* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
consequently, there should be very few hooks below. */
@@ -77,6 +79,12 @@ static tree cxx_enum_underlying_base_type (const_tree);
#define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
#undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE
#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE cxx_enum_underlying_base_type
+#undef LANG_HOOKS_PREPROCESS_MAIN_FILE
+#define LANG_HOOKS_PREPROCESS_MAIN_FILE module_begin_main_file
+#undef LANG_HOOKS_PREPROCESS_OPTIONS
+#define LANG_HOOKS_PREPROCESS_OPTIONS module_preprocess_options
+#undef LANG_HOOKS_PREPROCESS_TOKEN
+#define LANG_HOOKS_PREPROCESS_TOKEN module_token_pre
#if CHECKING_P
#undef LANG_HOOKS_RUN_LANG_SELFTESTS
@@ -86,6 +94,12 @@ static tree cxx_enum_underlying_base_type (const_tree);
#undef LANG_HOOKS_GET_SUBSTRING_LOCATION
#define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
+#undef LANG_HOOKS_OMP_GET_DECL_INIT
+#define LANG_HOOKS_OMP_GET_DECL_INIT cxx_omp_get_decl_init
+
+#undef LANG_HOOKS_OMP_FINISH_DECL_INITS
+#define LANG_HOOKS_OMP_FINISH_DECL_INITS cxx_omp_finish_decl_inits
+
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -227,6 +241,30 @@ tree cxx_enum_underlying_base_type (const_tree type)
return underlying_type;
}
+/* The C++ version of the omp_get_decl_init langhook returns the static
+ initializer for a variable declaration if present, otherwise it
+ tries to find and return the dynamic initializer. If not present,
+ it returns NULL. */
+
+static tree *
+cxx_omp_get_decl_init (tree decl)
+{
+ if (DECL_INITIAL (decl))
+ return &DECL_INITIAL (decl);
+
+ return hash_map_safe_get (dynamic_initializers, decl);
+}
+
+/* The C++ version of the omp_finish_decl_inits langhook allows GC to
+ reclaim the memory used by the hash-map used to hold dynamic initializer
+ information. */
+
+static void
+cxx_omp_finish_decl_inits (void)
+{
+ dynamic_initializers = NULL;
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index e1397b7..84f0b59 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -366,7 +366,8 @@ names_builtin_p (const char *name)
tree id = get_identifier (name);
if (tree binding = get_global_binding (id))
{
- if (TREE_CODE (binding) == FUNCTION_DECL && DECL_IS_BUILTIN (binding))
+ if (TREE_CODE (binding) == FUNCTION_DECL
+ && DECL_IS_UNDECLARED_BUILTIN (binding))
return true;
/* Handle the case when an overload for a built-in name exists. */
@@ -376,7 +377,7 @@ names_builtin_p (const char *name)
for (ovl_iterator it (binding); it; ++it)
{
tree decl = *it;
- if (DECL_IS_BUILTIN (decl))
+ if (DECL_IS_UNDECLARED_BUILTIN (decl))
return true;
}
}
@@ -390,6 +391,7 @@ names_builtin_p (const char *name)
case RID_BUILTIN_HAS_ATTRIBUTE:
case RID_BUILTIN_SHUFFLE:
case RID_BUILTIN_LAUNDER:
+ case RID_BUILTIN_BIT_CAST:
case RID_OFFSETOF:
case RID_HAS_NOTHROW_ASSIGN:
case RID_HAS_NOTHROW_CONSTRUCTOR:
@@ -436,6 +438,9 @@ cp_register_dumps (gcc::dump_manager *dumps)
class_dump_id = dumps->dump_register
(".class", "lang-class", "lang-class", DK_lang, OPTGROUP_NONE, false);
+ module_dump_id = dumps->dump_register
+ (".module", "lang-module", "lang-module", DK_lang, OPTGROUP_NONE, false);
+
raw_dump_id = dumps->dump_register
(".raw", "lang-raw", "lang-raw", DK_lang, OPTGROUP_NONE, false);
}
@@ -488,6 +493,7 @@ cp_common_init_ts (void)
MARK_TS_EXP (ALIGNOF_EXPR);
MARK_TS_EXP (ARROW_EXPR);
MARK_TS_EXP (AT_ENCODE_EXPR);
+ MARK_TS_EXP (BIT_CAST_EXPR);
MARK_TS_EXP (CAST_EXPR);
MARK_TS_EXP (CONST_CAST_EXPR);
MARK_TS_EXP (CTOR_INITIALIZER);
@@ -548,4 +554,16 @@ cp_common_init_ts (void)
c_common_init_ts ();
}
+/* Handle C++-specficic options here. Punt to c_common otherwise. */
+
+bool
+cp_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
+ int kind, location_t loc,
+ const struct cl_option_handlers *handlers)
+{
+ if (handle_module_option (unsigned (scode), arg, value))
+ return true;
+ return c_common_handle_option (scode, arg, value, kind, loc, handlers);
+}
+
#include "gt-cp-cp-objcp-common.h"
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 0936f16..4b5b96f 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -34,6 +34,8 @@ extern tree cp_unit_size_without_reusable_padding (tree);
extern tree cp_get_global_decls ();
extern tree cp_pushdecl (tree);
extern void cp_register_dumps (gcc::dump_manager *);
+extern bool cp_handle_option (size_t, const char *, HOST_WIDE_INT, int,
+ location_t, const struct cl_option_handlers *);
extern tree cxx_make_type_hook (tree_code);
extern tree cxx_simulate_enum_decl (location_t, const char *,
vec<string_int_pair>);
@@ -63,7 +65,7 @@ extern tree cxx_simulate_enum_decl (location_t, const char *,
#undef LANG_HOOKS_REGISTER_DUMPS
#define LANG_HOOKS_REGISTER_DUMPS cp_register_dumps
#undef LANG_HOOKS_HANDLE_OPTION
-#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
+#define LANG_HOOKS_HANDLE_OPTION cp_handle_option
#undef LANG_HOOKS_HANDLE_FILENAME
#define LANG_HOOKS_HANDLE_FILENAME c_common_handle_filename
#undef LANG_HOOKS_POST_OPTIONS
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index a188576..c58b233 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -233,6 +233,9 @@ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", tcc_expression, 2)
/* One of a set of overloaded functions. */
DEFTREECODE (OVERLOAD, "overload", tcc_exceptional, 0)
+/* A vector of binding slots. */
+DEFTREECODE (BINDING_VECTOR, "binding_vector", tcc_exceptional, 0)
+
/* A pseudo-destructor, of the form "OBJECT.~DESTRUCTOR" or
"OBJECT.SCOPE::~DESTRUCTOR. The first operand is the OBJECT. The
second operand (if non-NULL) is the SCOPE. The third operand is
@@ -437,6 +440,9 @@ DEFTREECODE (UNARY_RIGHT_FOLD_EXPR, "unary_right_fold_expr", tcc_expression, 2)
DEFTREECODE (BINARY_LEFT_FOLD_EXPR, "binary_left_fold_expr", tcc_expression, 3)
DEFTREECODE (BINARY_RIGHT_FOLD_EXPR, "binary_right_fold_expr", tcc_expression, 3)
+/* Represents the __builtin_bit_cast (type, expr) expression.
+ The type is in TREE_TYPE, expression in TREE_OPERAND (bitcast, 0). */
+DEFTREECODE (BIT_CAST_EXPR, "bit_cast_expr", tcc_expression, 1)
/** C++ extensions. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5c06ac3..fc6a789 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -125,14 +125,11 @@ enum cp_tree_index
CPTI_CLASS_TYPE,
CPTI_UNKNOWN_TYPE,
CPTI_INIT_LIST_TYPE,
+ CPTI_EXPLICIT_VOID_LIST,
CPTI_VTBL_TYPE,
CPTI_VTBL_PTR_TYPE,
- CPTI_STD,
- CPTI_ABI,
CPTI_GLOBAL,
CPTI_GLOBAL_TYPE,
- CPTI_CONST_TYPE_INFO_TYPE,
- CPTI_TYPE_INFO_PTR_TYPE,
CPTI_ABORT_FNDECL,
CPTI_AGGR_TAG,
CPTI_CONV_OP_MARKER,
@@ -178,6 +175,8 @@ enum cp_tree_index
CPTI_HEAP_UNINIT_IDENTIFIER,
CPTI_HEAP_IDENTIFIER,
CPTI_HEAP_DELETED_IDENTIFIER,
+ CPTI_HEAP_VEC_UNINIT_IDENTIFIER,
+ CPTI_HEAP_VEC_IDENTIFIER,
CPTI_LANG_NAME_C,
CPTI_LANG_NAME_CPLUSPLUS,
@@ -187,8 +186,28 @@ enum cp_tree_index
CPTI_NOEXCEPT_FALSE_SPEC,
CPTI_NOEXCEPT_DEFERRED_SPEC,
+ CPTI_NULLPTR,
+ CPTI_NULLPTR_TYPE,
+
+ CPTI_ANY_TARG,
+
+ CPTI_MODULE_HWM,
+ /* Nodes after here change during compilation, or should not be in
+ the module's global tree table. */
+
+ /* We must find these via the global namespace. */
+ CPTI_STD,
+ CPTI_ABI,
+
+ /* These are created at init time, but the library/headers provide
+ definitions. */
+ CPTI_ALIGN_TYPE,
+ CPTI_CONST_TYPE_INFO_TYPE,
+ CPTI_TYPE_INFO_PTR_TYPE,
CPTI_TERMINATE_FN,
CPTI_CALL_UNEXPECTED_FN,
+
+ /* These are lazily inited. */
CPTI_GET_EXCEPTION_PTR_FN,
CPTI_BEGIN_CATCH_FN,
CPTI_END_CATCH_FN,
@@ -201,13 +220,6 @@ enum cp_tree_index
CPTI_DSO_HANDLE,
CPTI_DCAST,
- CPTI_NULLPTR,
- CPTI_NULLPTR_TYPE,
-
- CPTI_ALIGN_TYPE,
-
- CPTI_ANY_TARG,
-
CPTI_SOURCE_LOCATION_IMPL,
CPTI_FALLBACK_DFLOAT32_TYPE,
@@ -230,6 +242,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define class_type_node cp_global_trees[CPTI_CLASS_TYPE]
#define unknown_type_node cp_global_trees[CPTI_UNKNOWN_TYPE]
#define init_list_type_node cp_global_trees[CPTI_INIT_LIST_TYPE]
+#define explicit_void_list_node cp_global_trees[CPTI_EXPLICIT_VOID_LIST]
#define vtbl_type_node cp_global_trees[CPTI_VTBL_TYPE]
#define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE]
#define std_node cp_global_trees[CPTI_STD]
@@ -322,6 +335,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define heap_uninit_identifier cp_global_trees[CPTI_HEAP_UNINIT_IDENTIFIER]
#define heap_identifier cp_global_trees[CPTI_HEAP_IDENTIFIER]
#define heap_deleted_identifier cp_global_trees[CPTI_HEAP_DELETED_IDENTIFIER]
+#define heap_vec_uninit_identifier cp_global_trees[CPTI_HEAP_VEC_UNINIT_IDENTIFIER]
+#define heap_vec_identifier cp_global_trees[CPTI_HEAP_VEC_IDENTIFIER]
#define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
#define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
@@ -409,6 +424,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag)
LAMBDA_CAPTURE_EXPLICIT_P (in a TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST)
+ PARENTHESIZED_LIST_P (in the TREE_LIST for a parameter-declaration-list)
CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
@@ -431,6 +447,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
REINTERPRET_CAST_P (in NOP_EXPR)
ALIGNOF_EXPR_STD_P (in ALIGNOF_EXPR)
OVL_DEDUP_P (in OVERLOAD)
+ ATOMIC_CONSTR_MAP_INSTANTIATED_P (in ATOMIC_CONSTR)
1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -473,18 +490,19 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
OVL_NESTED_P (in OVERLOAD)
LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR)
- Reserved for DECL_MODULE_EXPORT (in DECL_)
+ DECL_MODULE_EXPORT_P (in _DECL)
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
- DECL_TINFO_P (in VAR_DECL)
+ DECL_TINFO_P (in VAR_DECL, TYPE_DECL)
FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
OVL_LOOKUP_P (in OVERLOAD)
- LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, NAMESPACE_DECL)
+ LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL)
5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR)
+ OVL_EXPORT_P (in OVERLOAD)
6: TYPE_MARKED_P (in _TYPE)
DECL_NONTRIVIALLY_INITIALIZED_P (in VAR_DECL)
RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
@@ -521,11 +539,13 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL)
DECL_INSTANTIATING_NSDMI_P (in a FIELD_DECL)
LABEL_DECL_CDTOR (in LABEL_DECL)
+ USING_DECL_UNRELATED_P (in USING_DECL)
3: DECL_IN_AGGR_P.
4: DECL_C_BIT_FIELD (in a FIELD_DECL)
DECL_ANON_UNION_VAR_P (in a VAR_DECL)
DECL_SELF_REFERENCE_P (in a TYPE_DECL)
DECL_INVALID_OVERRIDER_P (in a FUNCTION_DECL)
+ DECL_UNINSTANIATED_TEMPLATE_FRIEND_P (in TEMPLATE_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL, FUNCTION_DECL or PARM_DECL)
DECL_FIELD_IS_BASE (in FIELD_DECL)
@@ -738,9 +758,10 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
&& flag_hosted)
/* Lookup walker marking. */
-#define LOOKUP_SEEN_P(NODE) TREE_VISITED(NODE)
+#define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE)
#define LOOKUP_FOUND_P(NODE) \
- TREE_LANG_FLAG_4 (TREE_CHECK3(NODE,RECORD_TYPE,UNION_TYPE,NAMESPACE_DECL))
+ TREE_LANG_FLAG_4 (TREE_CHECK4 (NODE,RECORD_TYPE,UNION_TYPE,ENUMERAL_TYPE,\
+ NAMESPACE_DECL))
/* These two accessors should only be used by OVL manipulators.
Other users should use iterators and convenience functions. */
@@ -759,6 +780,8 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
#define OVL_NESTED_P(NODE) TREE_LANG_FLAG_3 (OVERLOAD_CHECK (NODE))
/* If set, this overload was constructed during lookup. */
#define OVL_LOOKUP_P(NODE) TREE_LANG_FLAG_4 (OVERLOAD_CHECK (NODE))
+/* If set, this OVL_USING_P overload is exported. */
+#define OVL_EXPORT_P(NODE) TREE_LANG_FLAG_5 (OVERLOAD_CHECK (NODE))
/* The first decl of an overload. */
#define OVL_FIRST(NODE) ovl_first (NODE)
@@ -818,6 +841,11 @@ class ovl_iterator {
return fn;
}
+ tree get_using () const
+ {
+ gcc_checking_assert (using_p ());
+ return ovl;
+ }
public:
/* Whether this overload was introduced by a using decl. */
@@ -826,6 +854,12 @@ class ovl_iterator {
return (TREE_CODE (ovl) == USING_DECL
|| (TREE_CODE (ovl) == OVERLOAD && OVL_USING_P (ovl)));
}
+ /* Whether this using is being exported. */
+ bool exporting_p () const
+ {
+ return OVL_EXPORT_P (get_using ());
+ }
+
bool hidden_p () const
{
return TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl);
@@ -941,8 +975,10 @@ public:
operator vec_t *() const { return v; }
vec_t ** operator& () { return &v; }
- /* Breaks pointer/value consistency for convenience. */
- tree& operator[] (unsigned i) const { return (*v)[i]; }
+ /* Breaks pointer/value consistency for convenience. This takes ptrdiff_t
+ rather than unsigned to avoid ambiguity with the built-in operator[]
+ (bootstrap/91828). */
+ tree& operator[] (ptrdiff_t i) const { return (*v)[i]; }
~releasing_vec() { release_tree_vector (v); }
private:
@@ -1323,7 +1359,9 @@ enum cp_trait_kind
CPTK_IS_UNION,
CPTK_UNDERLYING_TYPE,
CPTK_IS_ASSIGNABLE,
- CPTK_IS_CONSTRUCTIBLE
+ CPTK_IS_CONSTRUCTIBLE,
+ CPTK_IS_NOTHROW_ASSIGNABLE,
+ CPTK_IS_NOTHROW_CONSTRUCTIBLE
};
/* The types that we are processing. */
@@ -1587,6 +1625,12 @@ check_constraint_info (tree t)
#define ATOMIC_CONSTR_MAP(NODE) \
TREE_OPERAND (TREE_CHECK (NODE, ATOMIC_CONSTR), 0)
+/* Whether the parameter mapping of this atomic constraint
+ is already instantiated with concrete template arguments.
+ Used only in satisfy_atom and in the satisfaction cache. */
+#define ATOMIC_CONSTR_MAP_INSTANTIATED_P(NODE) \
+ TREE_LANG_FLAG_0 (ATOMIC_CONSTR_CHECK (NODE))
+
/* The expression of an atomic constraint. */
#define ATOMIC_CONSTR_EXPR(NODE) \
CONSTR_EXPR (ATOMIC_CONSTR_CHECK (NODE))
@@ -1617,6 +1661,46 @@ check_constraint_info (tree t)
#define CONSTRAINED_PARM_PROTOTYPE(NODE) \
DECL_INITIAL (TYPE_DECL_CHECK (NODE))
+/* Module defines. */
+// Too many _DECLS: FUNCTION,VAR,TYPE,TEMPLATE,CONCEPT or NAMESPACE
+#define DECL_MODULE_CHECK(NODE) (NODE)
+
+/* In the purview of a module (including header unit). */
+#define DECL_MODULE_PURVIEW_P(N) \
+ (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (N))->u.base.module_purview_p)
+
+/* True if the live version of the decl was imported. */
+#define DECL_MODULE_IMPORT_P(NODE) \
+ (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_import_p)
+
+/* True if this decl is in the entity hash & array. This means that
+ some variant was imported, even if DECL_MODULE_IMPORT_P is false. */
+#define DECL_MODULE_ENTITY_P(NODE) \
+ (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_entity_p)
+
+/* True if there are unloaded specializations keyed to this template. */
+#define DECL_MODULE_PENDING_SPECIALIZATIONS_P(NODE) \
+ (DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE)) \
+ ->u.base.module_pending_p)
+
+/* True if this class has unloaded members. These should be loaded
+ before we do member lookups. */
+#define DECL_MODULE_PENDING_MEMBERS_P(NODE) \
+ (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE)) \
+ ->u.base.module_pending_p)
+
+/* DECL that has attached decls for ODR-relatedness. */
+#define DECL_MODULE_ATTACHMENTS_P(NODE) \
+ (DECL_LANG_SPECIFIC (TREE_CHECK2(NODE,FUNCTION_DECL,VAR_DECL))\
+ ->u.base.module_pending_p)
+
+/* Whether this is an exported DECL. Held on any decl that can appear
+ at namespace scope (function, var, type, template, const or
+ namespace). templates copy from their template_result, consts have
+ it for unscoped enums. */
+#define DECL_MODULE_EXPORT_P(NODE) TREE_LANG_FLAG_3 (NODE)
+
+
/* The list of local parameters introduced by this requires-expression,
in the form of a chain of PARM_DECLs. */
#define REQUIRES_EXPR_PARMS(NODE) \
@@ -1638,6 +1722,7 @@ enum cp_tree_node_structure_enum {
TS_CP_TPI,
TS_CP_PTRMEM,
TS_CP_OVERLOAD,
+ TS_CP_BINDING_VECTOR,
TS_CP_BASELINK,
TS_CP_TEMPLATE_DECL,
TS_CP_DEFERRED_PARSE,
@@ -1659,6 +1744,7 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
struct template_parm_index GTY ((tag ("TS_CP_TPI"))) tpi;
struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem;
struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
+ struct tree_binding_vec GTY ((tag ("TS_CP_BINDING_VECTOR"))) binding_vec;
struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
struct tree_template_decl GTY ((tag ("TS_CP_TEMPLATE_DECL"))) template_decl;
struct tree_deferred_parse GTY ((tag ("TS_CP_DEFERRED_PARSE"))) deferred_parse;
@@ -1846,6 +1932,38 @@ public:
~temp_override() { overridden_variable = saved_value; }
};
+/* Wrapping a template parameter in type_identity_t hides it from template
+ argument deduction. */
+#if __cpp_lib_type_identity
+using std::type_identity_t;
+#else
+template <typename T>
+struct type_identity { typedef T type; };
+template <typename T>
+using type_identity_t = typename type_identity<T>::type;
+#endif
+
+/* Object generator function for temp_override, so you don't need to write the
+ type of the object as a template argument.
+
+ Use as auto x = make_temp_override (flag); */
+
+template <typename T>
+inline temp_override<T>
+make_temp_override (T& var)
+{
+ return { var };
+}
+
+/* Likewise, but use as auto x = make_temp_override (flag, value); */
+
+template <typename T>
+inline temp_override<T>
+make_temp_override (T& var, type_identity_t<T> overrider)
+{
+ return { var, overrider };
+}
+
/* The cached class binding level, from the most recently exited
class, or NULL if none. */
@@ -1861,19 +1979,6 @@ public:
#define cp_noexcept_operand scope_chain->noexcept_operand
-/* A list of private types mentioned, for deferred access checking. */
-
-struct GTY((for_user)) cxx_int_tree_map {
- unsigned int uid;
- tree to;
-};
-
-struct cxx_int_tree_map_hasher : ggc_ptr_hash<cxx_int_tree_map>
-{
- static hashval_t hash (cxx_int_tree_map *);
- static bool equal (cxx_int_tree_map *, cxx_int_tree_map *);
-};
-
struct named_label_entry; /* Defined in decl.c. */
struct named_label_hash : ggc_remove <named_label_entry *>
@@ -2217,7 +2322,6 @@ struct GTY(()) lang_type {
tree vtables;
tree typeinfo_var;
vec<tree, va_gc> *vbases;
- binding_table nested_udts;
tree as_base;
vec<tree, va_gc> *pure_virtuals;
tree friend_classes;
@@ -2370,12 +2474,6 @@ struct GTY(()) lang_type {
#define CLASSTYPE_DESTRUCTOR(NODE) \
(get_class_binding_direct (NODE, dtor_identifier))
-/* A dictionary of the nested user-defined-types (class-types, or enums)
- found within this class. This table includes nested member class
- templates. */
-#define CLASSTYPE_NESTED_UTDS(NODE) \
- (LANG_TYPE_CLASS_CHECK (NODE)->nested_udts)
-
/* Nonzero if NODE has a primary base class, i.e., a base class with
which it shares the virtual function table pointer. */
#define CLASSTYPE_HAS_PRIMARY_BASE_P(NODE) \
@@ -2646,15 +2744,15 @@ enum lang_decl_selector
/* Flags shared by all forms of DECL_LANG_SPECIFIC.
Some of the flags live here only to make lang_decl_min/fn smaller. Do
- not make this struct larger than 32 bits; instead, make sel smaller. */
+ not make this struct larger than 32 bits. */
struct GTY(()) lang_decl_base {
- /* Larger than necessary for faster access. */
- ENUM_BITFIELD(lang_decl_selector) selector : 16;
+ ENUM_BITFIELD(lang_decl_selector) selector : 3;
ENUM_BITFIELD(languages) language : 1;
unsigned use_template : 2;
unsigned not_really_extern : 1; /* var or fn */
unsigned initialized_in_class : 1; /* var or fn */
+
unsigned threadprivate_or_deleted_p : 1; /* var or fn */
/* anticipated_p is no longer used for anticipated_decls (fn, type
or template). It is used as DECL_OMP_PRIVATIZED_MEMBER in
@@ -2663,11 +2761,22 @@ struct GTY(()) lang_decl_base {
unsigned friend_or_tls : 1; /* var, fn, type or template */
unsigned unknown_bound_p : 1; /* var */
unsigned odr_used : 1; /* var or fn */
- unsigned spare : 1;
unsigned concept_p : 1; /* applies to vars and functions */
unsigned var_declared_inline_p : 1; /* var */
unsigned dependent_init_p : 1; /* var */
- /* 2 spare bits */
+
+ /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, TEMPLATE,
+ NAMESPACE decls. */
+ unsigned module_purview_p : 1; /* in module purview (not GMF) */
+ unsigned module_import_p : 1; /* from an import */
+ unsigned module_entity_p : 1; /* is in the entitity ary &
+ hash. */
+ /* TEMPLATE_DECL has specializations or,
+ TYPE_DECL has class members yet to load, or
+ VAR_DECL or FUNCTION_DECL has attached decls. */
+ unsigned module_pending_p : 1;
+
+ /* 12 spare bits. */
};
/* True for DECL codes which have template info and access. */
@@ -3100,6 +3209,13 @@ struct GTY(()) lang_decl {
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
->u.base.friend_or_tls)
+/* True of a TEMPLATE_DECL that is a template class friend. Such
+ decls are not pushed until instantiated (as they may depend on
+ parameters of the befriending class). DECL_CHAIN is the
+ befriending class. */
+#define DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P(NODE) \
+ (DECL_LANG_FLAG_4 (TEMPLATE_DECL_CHECK (NODE)))
+
/* Nonzero if the thread-local variable was declared with __thread as
opposed to thread_local. */
#define DECL_GNU_TLS_P(NODE) \
@@ -3341,7 +3457,8 @@ struct GTY(()) lang_decl {
/* 1 iff VAR_DECL node NODE is a type-info decl. This flag is set for
both the primary typeinfo object and the associated NTBS name. */
-#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE))
+#define DECL_TINFO_P(NODE) \
+ TREE_LANG_FLAG_4 (TREE_CHECK2 (NODE,VAR_DECL,TYPE_DECL))
/* 1 iff VAR_DECL node NODE is virtual table or VTT. We forward to
DECL_VIRTUAL_P from the common code, as that has the semantics we
@@ -3396,6 +3513,10 @@ struct GTY(()) lang_decl {
was inherited from a template parameter, not explicitly indicated. */
#define ABI_TAG_IMPLICIT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
+/* In a TREE_LIST for a parameter-declaration-list, indicates that all the
+ parameters in the list have declarators enclosed in (). */
+#define PARENTHESIZED_LIST_P(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
+
/* Non zero if this is a using decl for a dependent scope. */
#define DECL_DEPENDENT_P(NODE) DECL_LANG_FLAG_0 (USING_DECL_CHECK (NODE))
@@ -3408,6 +3529,16 @@ struct GTY(()) lang_decl {
/* Non zero if the using decl refers to a dependent type. */
#define USING_DECL_TYPENAME_P(NODE) DECL_LANG_FLAG_1 (USING_DECL_CHECK (NODE))
+/* True if member using decl NODE refers to a non-inherited NODE. */
+#define USING_DECL_UNRELATED_P(NODE) DECL_LANG_FLAG_2 (USING_DECL_CHECK (NODE))
+
+/* True iff the CONST_DECL is a class-scope clone from C++20 using enum,
+ created by handle_using_decl. */
+#define CONST_DECL_USING_P(NODE) \
+ (TREE_CODE (NODE) == CONST_DECL \
+ && TREE_CODE (TREE_TYPE (NODE)) == ENUMERAL_TYPE \
+ && DECL_CONTEXT (NODE) != TREE_TYPE (NODE))
+
/* In a FUNCTION_DECL, this is nonzero if this function was defined in
the class definition. We have saved away the text of the function,
but have not yet processed it. */
@@ -4045,11 +4176,6 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define FNDECL_USED_AUTO(NODE) \
TREE_LANG_FLAG_2 (FUNCTION_DECL_CHECK (NODE))
-/* True if NODE is an undeclared builtin decl. As soon as the user
- declares it, the location will be updated. */
-#define DECL_UNDECLARED_BUILTIN_P(NODE) \
- (DECL_SOURCE_LOCATION(NODE) == BUILTINS_LOCATION)
-
/* True for artificial decls added for OpenMP privatized non-static
data members. */
#define DECL_OMP_PRIVATIZED_MEMBER(NODE) \
@@ -5328,6 +5454,10 @@ extern int function_depth;
in structrual_comptypes. */
extern int comparing_specializations;
+/* When comparing specializations permit context _FROM to match _TO. */
+extern tree map_context_from;
+extern tree map_context_to;
+
/* In parser.c. */
/* Nonzero if we are parsing an unevaluated operand: an operand to
@@ -5387,6 +5517,14 @@ public:
hash_map<tree, tree> *saved;
};
+/* Entry in the specialization hash table. */
+struct GTY((for_user)) spec_entry
+{
+ tree tmpl; /* The general template this is a specialization of. */
+ tree args; /* The args for this (maybe-partial) specialization. */
+ tree spec; /* The specialization itself. */
+};
+
/* in class.c */
extern int current_class_depth;
@@ -5493,6 +5631,10 @@ extern GTY(()) tree static_aggregates;
/* Likewise, for thread local storage. */
extern GTY(()) tree tls_aggregates;
+/* A hash-map mapping from variable decls to the dynamic initializer for
+ the decl. This is currently only used by OpenMP. */
+extern GTY(()) decl_tree_map *dynamic_initializers;
+
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
/* These are uses as bits in flags passed to various functions to
@@ -6052,6 +6194,7 @@ struct cp_declarator {
tree late_return_type;
/* The trailing requires-clause, if any. */
tree requires_clause;
+ location_t parens_loc;
} function;
/* For arrays. */
struct {
@@ -6093,6 +6236,13 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
arguments. */
tree tldcl, targs;
+ /* For modules we need to know (a) the modules on the path of
+ instantiation and (b) the transitive imports along that path.
+ Note that these two bitmaps may be inherited from NEXT, if this
+ decl is in the same module as NEXT (or has no new information). */
+ bitmap path;
+ bitmap visible;
+
private:
/* Return TRUE iff the original node is a split list. */
bool split_list_p () const { return targs; }
@@ -6188,6 +6338,7 @@ extern cp_parameter_declarator *no_parameters;
/* Various dump ids. */
extern int class_dump_id;
+extern int module_dump_id;
extern int raw_dump_id;
/* in call.c */
@@ -6225,6 +6376,13 @@ extern tree build_new_op (const op_location_t &,
enum tree_code,
int, tree, tree, tree, tree *,
tsubst_flags_t);
+/* Wrapper that leaves out the usually-null op3 and overload parms. */
+inline tree build_new_op (const op_location_t &loc, enum tree_code code,
+ int flags, tree arg1, tree arg2,
+ tsubst_flags_t complain)
+{
+ return build_new_op (loc, code, flags, arg1, arg2, NULL_TREE, NULL, complain);
+}
extern tree build_op_call (tree, vec<tree, va_gc> **,
tsubst_flags_t);
extern bool aligned_allocation_fn_p (tree);
@@ -6326,6 +6484,7 @@ extern tree build_base_path (enum tree_code, tree,
extern tree convert_to_base (tree, tree, bool, bool,
tsubst_flags_t);
extern tree convert_to_base_statically (tree, tree);
+extern bool is_empty_base_ref (tree);
extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
extern tree get_vtable_decl (tree, int);
@@ -6394,6 +6553,7 @@ extern void check_abi_tags (tree);
extern tree missing_abi_tags (tree);
extern void fixup_type_variants (tree);
extern void fixup_attribute_variants (tree);
+extern void build_cdtor_clones (tree, bool, bool, bool);
extern void clone_cdtor (tree, bool);
extern tree copy_operator_fn (tree, tree_code code);
extern void adjust_clone_args (tree);
@@ -6458,6 +6618,7 @@ extern bool check_omp_return (void);
extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
extern tree build_typename_type (tree, tree, tree, tag_types);
extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
+extern tree make_unbound_class_template_raw (tree, tree, tree);
extern tree build_library_fn_ptr (const char *, tree, int);
extern tree build_cp_library_fn_ptr (const char *, tree, int);
extern tree push_library_fn (tree, tree, tree, int);
@@ -6732,6 +6893,8 @@ extern tree unqualified_fn_lookup_error (cp_expr);
extern tree make_conv_op_name (tree);
extern tree build_lang_decl (enum tree_code, tree, tree);
extern tree build_lang_decl_loc (location_t, enum tree_code, tree, tree);
+extern bool maybe_add_lang_decl_raw (tree, bool decomp_p);
+extern bool maybe_add_lang_type_raw (tree);
extern void retrofit_lang_decl (tree);
extern void fit_decomposition_lang_decl (tree, tree);
extern tree copy_decl (tree CXX_MEM_STAT_INFO);
@@ -6743,6 +6906,10 @@ extern void set_identifier_kind (tree, cp_identifier_kind);
extern bool cxx_init (void);
extern void cxx_finish (void);
extern bool in_main_input_context (void);
+extern uintptr_t module_token_pre (cpp_reader *, const cpp_token *, uintptr_t);
+extern uintptr_t module_token_cdtor (cpp_reader *, uintptr_t);
+extern uintptr_t module_token_lang (int type, int keyword, tree value,
+ location_t, uintptr_t);
/* in method.c */
extern void init_method (void);
@@ -6752,6 +6919,7 @@ extern void use_thunk (tree, bool);
extern bool trivial_fn_p (tree);
extern tree forward_parm (tree);
extern bool is_trivially_xible (enum tree_code, tree, tree);
+extern bool is_nothrow_xible (enum tree_code, tree, tree);
extern bool is_xible (enum tree_code, tree, tree);
extern tree get_defaulted_eh_spec (tree, tsubst_flags_t = tf_warning_or_error);
extern bool maybe_explain_implicit_delete (tree);
@@ -6775,6 +6943,103 @@ extern bool ctor_omit_inherited_parms (tree);
extern tree locate_ctor (tree);
extern tree implicitly_declare_fn (special_function_kind, tree,
bool, tree, tree);
+/* In module.cc */
+class module_state; /* Forward declare. */
+inline bool modules_p () { return flag_modules != 0; }
+
+/* The kind of module or part thereof that we're in. */
+enum module_kind_bits
+{
+ MK_MODULE = 1 << 0, /* This TU is a module. */
+ MK_GLOBAL = 1 << 1, /* Entities are in the global module. */
+ MK_INTERFACE = 1 << 2, /* This TU is an interface. */
+ MK_PARTITION = 1 << 3, /* This TU is a partition. */
+ MK_EXPORTING = 1 << 4, /* We are in an export region. */
+};
+
+/* We do lots of bit-manipulation, so an unsigned is easier. */
+extern unsigned module_kind;
+
+/* MK_MODULE & MK_GLOBAL have the following combined meanings:
+ MODULE GLOBAL
+ 0 0 not a module
+ 0 1 GMF of named module (we've not yet seen module-decl)
+ 1 0 purview of named module
+ 1 1 header unit. */
+
+inline bool module_purview_p ()
+{ return module_kind & MK_MODULE; }
+inline bool global_purview_p ()
+{ return module_kind & MK_GLOBAL; }
+
+inline bool not_module_p ()
+{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == 0; }
+inline bool named_module_p ()
+{ /* This is a named module if exactly one of MODULE and GLOBAL is
+ set. */
+ /* The divides are constant shifts! */
+ return ((module_kind / MK_MODULE) ^ (module_kind / MK_GLOBAL)) & 1;
+}
+inline bool header_module_p ()
+{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == (MK_MODULE | MK_GLOBAL); }
+inline bool named_module_purview_p ()
+{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == MK_MODULE; }
+inline bool module_interface_p ()
+{ return module_kind & MK_INTERFACE; }
+inline bool module_partition_p ()
+{ return module_kind & MK_PARTITION; }
+inline bool module_has_cmi_p ()
+{ return module_kind & (MK_INTERFACE | MK_PARTITION); }
+
+/* We're currently exporting declarations. */
+inline bool module_exporting_p ()
+{ return module_kind & MK_EXPORTING; }
+
+extern module_state *get_module (tree name, module_state *parent = NULL,
+ bool partition = false);
+extern bool module_may_redeclare (tree decl);
+
+extern int module_initializer_kind ();
+extern void module_add_import_initializers ();
+
+/* Where the namespace-scope decl was originally declared. */
+extern void set_originating_module (tree, bool friend_p = false);
+extern tree get_originating_module_decl (tree) ATTRIBUTE_PURE;
+extern int get_originating_module (tree, bool for_mangle = false) ATTRIBUTE_PURE;
+extern unsigned get_importing_module (tree, bool = false) ATTRIBUTE_PURE;
+
+/* Where current instance of the decl got declared/defined/instantiated. */
+extern void set_instantiating_module (tree);
+extern void set_defining_module (tree);
+extern void maybe_attach_decl (tree ctx, tree decl);
+
+extern void mangle_module (int m, bool include_partition);
+extern void mangle_module_fini ();
+extern void lazy_load_binding (unsigned mod, tree ns, tree id,
+ binding_slot *bslot);
+extern void lazy_load_specializations (tree tmpl);
+extern void lazy_load_members (tree decl);
+extern bool lazy_specializations_p (unsigned, bool, bool);
+extern module_state *preprocess_module (module_state *, location_t,
+ bool in_purview,
+ bool is_import, bool export_p,
+ cpp_reader *reader);
+extern void preprocessed_module (cpp_reader *reader);
+extern void import_module (module_state *, location_t, bool export_p,
+ tree attr, cpp_reader *);
+extern void declare_module (module_state *, location_t, bool export_p,
+ tree attr, cpp_reader *);
+extern void init_modules (cpp_reader *);
+extern void fini_modules ();
+extern void maybe_check_all_macros (cpp_reader *);
+extern void finish_module_processing (cpp_reader *);
+extern char const *module_name (unsigned, bool header_ok);
+extern bitmap get_import_bitmap ();
+extern bitmap visible_instantiation_path (bitmap *);
+extern void module_begin_main_file (cpp_reader *, line_maps *,
+ const line_map_ordinary *);
+extern void module_preprocess_options (cpp_reader *);
+extern bool handle_module_option (unsigned opt, const char *arg, int value);
/* In optimize.c */
extern bool maybe_clone_body (tree);
@@ -6793,6 +7058,7 @@ extern void maybe_show_extern_c_location (void);
extern bool literal_integer_zerop (const_tree);
/* in pt.c */
+extern tree canonical_type_parameter (tree);
extern void push_access_scope (tree);
extern void pop_access_scope (tree);
extern bool check_template_shadow (tree);
@@ -6976,6 +7242,15 @@ extern bool copy_guide_p (const_tree);
extern bool template_guide_p (const_tree);
extern bool builtin_guide_p (const_tree);
extern void store_explicit_specifier (tree, tree);
+extern void walk_specializations (bool,
+ void (*)(bool, spec_entry *,
+ void *),
+ void *);
+extern tree match_mergeable_specialization (bool is_decl, spec_entry *,
+ bool insert = true);
+extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
+extern void add_mergeable_specialization (tree tmpl, tree args,
+ tree spec, unsigned);
extern tree add_outermost_template_args (tree, tree);
extern tree add_extra_args (tree, tree);
extern tree build_extra_args (tree, tree, tsubst_flags_t);
@@ -6986,6 +7261,7 @@ extern GTY(()) vec<tree, va_gc> *unemitted_tinfo_decls;
extern void init_rtti_processing (void);
extern tree build_typeid (tree, tsubst_flags_t);
+extern tree get_tinfo_decl_direct (tree, tree, int);
extern tree get_tinfo_decl (tree);
extern tree get_typeid (tree, tsubst_flags_t);
extern tree build_headof (tree);
@@ -6993,6 +7269,8 @@ extern tree build_dynamic_cast (location_t, tree, tree,
tsubst_flags_t);
extern void emit_support_tinfos (void);
extern bool emit_tinfo_decl (tree);
+extern unsigned get_pseudo_tinfo_index (tree);
+extern tree get_pseudo_tinfo_type (unsigned);
/* in search.c */
extern bool accessible_base_p (tree, tree, bool);
@@ -7236,7 +7514,7 @@ extern bool cxx_omp_create_clause_info (tree, tree, bool, bool,
bool, bool);
extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
- bool);
+ bool, bool);
extern tree finish_decltype_type (tree, bool, tsubst_flags_t);
extern tree finish_trait_expr (location_t, enum cp_trait_kind, tree, tree);
extern tree build_lambda_expr (void);
@@ -7273,6 +7551,8 @@ extern tree finish_builtin_launder (location_t, tree,
tsubst_flags_t);
extern tree cp_build_vec_convert (tree, location_t, tree,
tsubst_flags_t);
+extern tree cp_build_bit_cast (location_t, tree, tree,
+ tsubst_flags_t);
extern void start_lambda_scope (tree);
extern void record_lambda_scope (tree);
extern void record_null_lambda_scope (tree);
@@ -7340,7 +7620,7 @@ extern bool is_local_temp (tree);
extern tree build_aggr_init_expr (tree, tree);
extern tree get_target_expr (tree);
extern tree get_target_expr_sfinae (tree, tsubst_flags_t);
-extern tree build_cplus_array_type (tree, tree);
+extern tree build_cplus_array_type (tree, tree, int is_dep = -1);
extern tree build_array_of_n_type (tree, int);
extern bool array_of_runtime_bound_p (tree);
extern bool vla_type_p (tree);
@@ -7351,6 +7631,7 @@ extern tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree);
extern tree build_qualified_name (tree, tree, tree, bool);
extern tree build_ref_qualified_type (tree, cp_ref_qualifier);
+extern tree make_binding_vec (tree, unsigned clusters CXX_MEM_STAT_INFO);
inline tree ovl_first (tree) ATTRIBUTE_PURE;
extern tree ovl_make (tree fn,
tree next = NULL_TREE);
@@ -7373,10 +7654,12 @@ extern const char *cxx_printable_name_translate (tree, int);
extern tree canonical_eh_spec (tree);
extern tree build_cp_fntype_variant (tree, cp_ref_qualifier, tree, bool);
extern tree build_exception_variant (tree, tree);
+extern void fixup_deferred_exception_variants (tree, tree);
extern tree bind_template_template_parm (tree, tree);
extern tree array_type_nelts_total (tree);
extern tree array_type_nelts_top (tree);
extern bool array_of_unknown_bound_p (const_tree);
+extern bool source_location_current_p (tree);
extern tree break_out_target_exprs (tree, bool = false);
extern tree build_ctor_subob_ref (tree, tree, tree);
extern tree replace_placeholders (tree, tree, bool * = NULL);
@@ -7462,7 +7745,7 @@ extern int comp_cv_qualification (const_tree, const_tree);
extern int comp_cv_qualification (int, int);
extern int comp_cv_qual_signature (tree, tree);
extern tree cxx_sizeof_or_alignof_expr (location_t, tree,
- enum tree_code, bool);
+ enum tree_code, bool, bool);
extern tree cxx_sizeof_or_alignof_type (location_t, tree,
enum tree_code, bool, bool);
extern tree cxx_alignas_expr (tree);
@@ -7573,7 +7856,7 @@ extern tree merge_types (tree, tree);
extern tree strip_array_domain (tree);
extern tree check_return_expr (tree, bool *);
extern tree spaceship_type (tree, tsubst_flags_t = tf_warning_or_error);
-extern tree genericize_spaceship (tree, tree, tree);
+extern tree genericize_spaceship (location_t, tree, tree, tree);
extern tree cp_build_binary_op (const op_location_t &,
enum tree_code, tree, tree,
tsubst_flags_t);
@@ -7690,6 +7973,9 @@ extern tree mangle_template_parm_object (tree);
extern char *get_mangled_vtable_map_var_name (tree);
extern bool mangle_return_type_p (tree);
extern tree mangle_decomp (tree, vec<tree> &);
+extern void mangle_module_substitution (int);
+extern void mangle_identifier (char, tree);
+extern tree mangle_module_global_init (int);
/* in dump.c */
extern bool cp_dump_tree (void *, tree);
@@ -7831,15 +8117,14 @@ extern tree evaluate_concept_check (tree, tsubst_flags_t);
extern tree satisfy_constraint_expression (tree);
extern bool constraints_satisfied_p (tree);
extern bool constraints_satisfied_p (tree, tree);
-extern void clear_satisfaction_cache ();
extern bool* lookup_subsumption_result (tree, tree);
extern bool save_subsumption_result (tree, tree, bool);
extern tree find_template_parameters (tree, tree);
extern bool equivalent_constraints (tree, tree);
extern bool equivalently_constrained (tree, tree);
extern bool subsumes_constraints (tree, tree);
-extern bool strictly_subsumes (tree, tree, tree);
-extern bool weakly_subsumes (tree, tree, tree);
+extern bool strictly_subsumes (tree, tree);
+extern bool weakly_subsumes (tree, tree);
extern int more_constrained (tree, tree);
extern bool at_least_as_constrained (tree, tree);
extern bool constraints_equivalent_p (tree, tree);
@@ -7848,6 +8133,23 @@ extern hashval_t iterative_hash_constraint (tree, hashval_t);
extern hashval_t hash_atomic_constraint (tree);
extern void diagnose_constraints (location_t, tree, tree);
+extern void note_failed_type_completion_for_satisfaction (tree);
+
+/* A structural hasher for ATOMIC_CONSTRs. */
+
+struct atom_hasher : default_hash_traits<tree>
+{
+ static hashval_t hash (tree t)
+ {
+ return hash_atomic_constraint (t);
+ }
+
+ static bool equal (tree t1, tree t2)
+ {
+ return atomic_constraints_identical_p (t1, t2);
+ }
+};
+
/* in logic.cc */
extern bool subsumes (tree, tree);
@@ -7862,9 +8164,20 @@ extern void vtv_recover_class_info (void);
extern void vtv_build_vtable_verify_fndecl (void);
/* In constexpr.c */
+/* Representation of entries in the constexpr function definition table. */
+
+struct GTY((for_user)) constexpr_fundef {
+ tree decl;
+ tree body;
+ tree parms;
+ tree result;
+};
+
extern void fini_constexpr (void);
extern bool literal_type_p (tree);
-extern tree register_constexpr_fundef (tree, tree);
+extern void maybe_save_constexpr_fundef (tree);
+extern void register_constexpr_fundef (const constexpr_fundef &);
+extern constexpr_fundef *retrieve_constexpr_fundef (tree);
extern bool is_valid_constexpr_fn (tree, bool);
extern bool check_constexpr_ctor_body (tree, tree, bool);
extern tree constexpr_fn_retval (tree);
@@ -7892,7 +8205,7 @@ extern tree maybe_fold_non_dependent_expr (tree,
tsubst_flags_t = tf_warning_or_error);
extern tree fold_non_dependent_init (tree,
tsubst_flags_t = tf_warning_or_error,
- bool = false);
+ bool = false, tree = NULL_TREE);
extern tree fold_simple (tree);
extern bool reduced_constant_expression_p (tree);
extern bool is_instantiation_of_constexpr (tree);
@@ -7901,7 +8214,7 @@ extern bool var_in_maybe_constexpr_fn (tree);
extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
extern tree fold_sizeof_expr (tree);
-extern void clear_cv_and_fold_caches (bool = true);
+extern void clear_cv_and_fold_caches (void);
extern tree unshare_constructor (tree CXX_MEM_STAT_INFO);
/* An RAII sentinel used to restrict constexpr evaluation so that it
@@ -7959,14 +8272,16 @@ type_unknown_p (const_tree expr)
inline hashval_t
named_decl_hash::hash (const value_type decl)
{
- tree name = OVL_NAME (decl);
+ tree name = (TREE_CODE (decl) == BINDING_VECTOR
+ ? BINDING_VECTOR_NAME (decl) : OVL_NAME (decl));
return name ? IDENTIFIER_HASH_VALUE (name) : 0;
}
inline bool
named_decl_hash::equal (const value_type existing, compare_type candidate)
{
- tree name = OVL_NAME (existing);
+ tree name = (TREE_CODE (existing) == BINDING_VECTOR
+ ? BINDING_VECTOR_NAME (existing) : OVL_NAME (existing));
return candidate == name;
}
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index c9e7b1f..29ceaeb 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1031,6 +1031,9 @@ cp_get_callee_fndecl_nofold (tree call)
static void
maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
{
+ if (!warn_unused_result || c_inhibit_evaluation_warnings)
+ return;
+
tree call = expr;
if (TREE_CODE (expr) == TARGET_EXPR)
call = TARGET_EXPR_INITIAL (expr);
@@ -1568,12 +1571,13 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
&& warn_unused_value
&& !TREE_NO_WARNING (expr)
&& !processing_template_decl
- && !cp_unevaluated_operand)
+ && !cp_unevaluated_operand
+ && (complain & tf_warning))
{
/* The middle end does not warn about expressions that have
been explicitly cast to void, so we must do so here. */
- if (!TREE_SIDE_EFFECTS (expr)) {
- if (complain & tf_warning)
+ if (!TREE_SIDE_EFFECTS (expr))
+ {
switch (implicit)
{
case ICV_SECOND_OF_COND:
@@ -1605,14 +1609,10 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
default:
gcc_unreachable ();
}
- }
+ }
else
{
- tree e;
- enum tree_code code;
- enum tree_code_class tclass;
-
- e = expr;
+ tree e = expr;
/* We might like to warn about (say) "(int) f()", as the
cast has no effect, but the compiler itself will
generate implicit conversions under some
@@ -1626,21 +1626,14 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
while (TREE_CODE (e) == NOP_EXPR)
e = TREE_OPERAND (e, 0);
- code = TREE_CODE (e);
- tclass = TREE_CODE_CLASS (code);
- if ((tclass == tcc_comparison
- || tclass == tcc_unary
- || (tclass == tcc_binary
- && !(code == MODIFY_EXPR
- || code == INIT_EXPR
- || code == PREDECREMENT_EXPR
- || code == PREINCREMENT_EXPR
- || code == POSTDECREMENT_EXPR
- || code == POSTINCREMENT_EXPR))
- || code == VEC_PERM_EXPR
- || code == VEC_COND_EXPR)
- && (complain & tf_warning))
- warning_at (loc, OPT_Wunused_value, "value computed is not used");
+ enum tree_code code = TREE_CODE (e);
+ enum tree_code_class tclass = TREE_CODE_CLASS (code);
+ if (tclass == tcc_comparison
+ || tclass == tcc_unary
+ || tclass == tcc_binary
+ || code == VEC_PERM_EXPR
+ || code == VEC_COND_EXPR)
+ warn_if_unused_value (e, loc);
}
}
expr = build1 (CONVERT_EXPR, void_type_node, expr);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 058b9c2..e189270 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -655,6 +655,15 @@ cxx_pretty_printer::postfix_expression (tree t)
pp_right_paren (this);
break;
+ case BIT_CAST_EXPR:
+ pp_cxx_ws_string (this, "__builtin_bit_cast");
+ pp_left_paren (this);
+ type_id (TREE_TYPE (t));
+ pp_comma (this);
+ expression (TREE_OPERAND (t, 0));
+ pp_right_paren (this);
+ break;
+
case EMPTY_CLASS_EXPR:
type_id (TREE_TYPE (t));
pp_left_paren (this);
@@ -1372,6 +1381,10 @@ cxx_pretty_printer::simple_type_specifier (tree t)
pp_cxx_right_paren (this);
break;
+ case NULLPTR_TYPE:
+ pp_cxx_ws_string (this, "std::nullptr_t");
+ break;
+
default:
c_pretty_printer::simple_type_specifier (t);
break;
@@ -1399,6 +1412,7 @@ pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
case TYPE_DECL:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case DECLTYPE_TYPE:
+ case NULLPTR_TYPE:
pp_cxx_cv_qualifier_seq (pp, t);
pp->simple_type_specifier (t);
break;
@@ -1864,6 +1878,7 @@ cxx_pretty_printer::type_id (tree t)
case TYPEOF_TYPE:
case UNDERLYING_TYPE:
case DECLTYPE_TYPE:
+ case NULLPTR_TYPE:
case TEMPLATE_ID_EXPR:
case OFFSET_TYPE:
pp_cxx_type_specifier_seq (this, t);
@@ -2666,6 +2681,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
case CPTK_IS_CONSTRUCTIBLE:
pp_cxx_ws_string (pp, "__is_constructible");
break;
+ case CPTK_IS_NOTHROW_ASSIGNABLE:
+ pp_cxx_ws_string (pp, "__is_nothrow_assignable");
+ break;
+ case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+ pp_cxx_ws_string (pp, "__is_nothrow_constructible");
+ break;
default:
gcc_unreachable ();
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2de4e16..8e63667 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -138,7 +138,7 @@ static location_t smallest_type_location (const cp_decl_specifier_seq*);
tree cp_global_trees[CPTI_MAX];
/* A list of objects which have constructors or destructors
- which reside in the global scope. The decl is stored in
+ which reside in namespace scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
in the TREE_PURPOSE slot. */
tree static_aggregates;
@@ -146,6 +146,10 @@ tree static_aggregates;
/* Like static_aggregates, but for thread_local variables. */
tree tls_aggregates;
+/* A hash-map mapping from variable decls to the dynamic initializer for
+ the decl. This is currently only used by OpenMP. */
+decl_tree_map *dynamic_initializers;
+
/* -- end of C++ */
/* A node for the integer constant 2. */
@@ -1002,7 +1006,7 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
/* A new declaration doesn't match a built-in one unless it
is also extern "C". */
- if (DECL_IS_BUILTIN (olddecl)
+ if (DECL_IS_UNDECLARED_BUILTIN (olddecl)
&& DECL_EXTERN_C_P (olddecl) && !DECL_EXTERN_C_P (newdecl))
return 0;
@@ -1205,7 +1209,7 @@ check_redeclaration_exception_specification (tree new_decl,
all declarations, including the definition and an explicit
specialization, of that function shall have an
exception-specification with the same set of type-ids. */
- if (! DECL_IS_BUILTIN (old_decl)
+ if (! DECL_IS_UNDECLARED_BUILTIN (old_decl)
&& !comp_except_specs (new_exceptions, old_exceptions, ce_normal))
{
const char *const msg
@@ -1465,7 +1469,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_UNDECLARED_BUILTIN_P (olddecl))
+ && DECL_IS_UNDECLARED_BUILTIN (olddecl))
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
@@ -1517,7 +1521,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* A new declaration doesn't match a built-in one unless it
is also extern "C". */
- gcc_assert (DECL_IS_BUILTIN (olddecl));
+ gcc_assert (DECL_IS_UNDECLARED_BUILTIN (olddecl));
gcc_assert (DECL_EXTERN_C_P (olddecl));
if (!DECL_EXTERN_C_P (newdecl))
return NULL_TREE;
@@ -1627,11 +1631,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* Replace the old RTL to avoid problems with inlining. */
COPY_DECL_RTL (newdecl, olddecl);
}
- /* Even if the types match, prefer the new declarations type for
- built-ins which have not been explicitly declared, for
- exception lists, etc... */
- else if (DECL_IS_BUILTIN (olddecl))
+ else
{
+ /* Even if the types match, prefer the new declarations type
+ for built-ins which have not been explicitly declared,
+ for exception lists, etc... */
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
(TREE_TYPE (olddecl), type);
@@ -1776,7 +1780,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
newdecl);
inform (olddecl_loc,
"previous declaration %q#D", olddecl);
- return NULL_TREE;
+ return error_mark_node;
}
/* For function versions, params and types match, but they
are not ambiguous. */
@@ -2008,6 +2012,39 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
if (!validate_constexpr_redeclaration (olddecl, newdecl))
return error_mark_node;
+ if (modules_p ()
+ && TREE_CODE (CP_DECL_CONTEXT (olddecl)) == NAMESPACE_DECL
+ && TREE_CODE (olddecl) != NAMESPACE_DECL
+ && !hiding)
+ {
+ if (DECL_ARTIFICIAL (olddecl))
+ {
+ gcc_checking_assert (!(DECL_LANG_SPECIFIC (olddecl)
+ && DECL_MODULE_IMPORT_P (olddecl)));
+ if (!(global_purview_p () || not_module_p ()))
+ error ("declaration %qD conflicts with builtin", newdecl);
+ else
+ DECL_MODULE_EXPORT_P (olddecl) = DECL_MODULE_EXPORT_P (newdecl);
+ }
+ else
+ {
+ if (!module_may_redeclare (olddecl))
+ {
+ error ("declaration %qD conflicts with import", newdecl);
+ inform (olddecl_loc, "import declared %q#D here", olddecl);
+
+ return error_mark_node;
+ }
+
+ if (DECL_MODULE_EXPORT_P (newdecl)
+ && !DECL_MODULE_EXPORT_P (olddecl))
+ {
+ error ("conflicting exporting declaration %qD", newdecl);
+ inform (olddecl_loc, "previous declaration %q#D here", olddecl);
+ }
+ }
+ }
+
/* We have committed to returning OLDDECL at this point. */
/* If new decl is `static' and an `extern' was seen previously,
@@ -2218,6 +2255,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
}
}
+ DECL_MODULE_IMPORT_P (olddecl)
+ = DECL_MODULE_IMPORT_P (old_result)
+ = DECL_MODULE_IMPORT_P (newdecl);
+
return olddecl;
}
@@ -2452,6 +2493,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
if (! DECL_COMDAT (olddecl))
DECL_COMDAT (newdecl) = 0;
+ if (VAR_OR_FUNCTION_DECL_P (newdecl) && DECL_LOCAL_DECL_P (newdecl))
+ {
+ if (!DECL_LOCAL_DECL_P (olddecl))
+ /* This can happen if olddecl was brought in from the
+ enclosing namespace via a using-decl. The new decl is
+ then not a block-scope extern at all. */
+ DECL_LOCAL_DECL_P (newdecl) = false;
+ else
+ {
+ retrofit_lang_decl (newdecl);
+ DECL_LOCAL_DECL_ALIAS (newdecl) = DECL_LOCAL_DECL_ALIAS (olddecl);
+ }
+ }
+
new_template_info = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
@@ -2471,22 +2526,27 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
}
- DECL_TEMPLATE_INSTANTIATED (newdecl)
- |= DECL_TEMPLATE_INSTANTIATED (olddecl);
- DECL_ODR_USED (newdecl) |= DECL_ODR_USED (olddecl);
- /* If the OLDDECL is an instantiation and/or specialization,
- then the NEWDECL must be too. But, it may not yet be marked
- as such if the caller has created NEWDECL, but has not yet
- figured out that it is a redeclaration. */
- if (!DECL_USE_TEMPLATE (newdecl))
- DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+ if (TREE_CODE (newdecl) != TYPE_DECL)
+ {
+ DECL_TEMPLATE_INSTANTIATED (newdecl)
+ |= DECL_TEMPLATE_INSTANTIATED (olddecl);
+ DECL_ODR_USED (newdecl) |= DECL_ODR_USED (olddecl);
+
+ /* If the OLDDECL is an instantiation and/or specialization,
+ then the NEWDECL must be too. But, it may not yet be marked
+ as such if the caller has created NEWDECL, but has not yet
+ figured out that it is a redeclaration. */
+ if (!DECL_USE_TEMPLATE (newdecl))
+ DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+
+ DECL_INITIALIZED_IN_CLASS_P (newdecl)
+ |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
+ }
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_INITIALIZED_IN_CLASS_P (newdecl)
- |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
if (LANG_DECL_HAS_MIN (newdecl))
{
@@ -2646,19 +2706,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
{
enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
- switch (fncode)
+ if (builtin_decl_explicit_p (fncode))
{
- /* If a compatible prototype of these builtin functions
- is seen, assume the runtime implements it with the
- expected semantics. */
- case BUILT_IN_STPCPY:
- if (builtin_decl_explicit_p (fncode))
- set_builtin_decl_implicit_p (fncode, true);
- break;
- default:
- if (builtin_decl_explicit_p (fncode))
- set_builtin_decl_declared_p (fncode, true);
- break;
+ /* A compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with
+ the expected semantics. */
+ switch (fncode)
+ {
+ case BUILT_IN_STPCPY:
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ set_builtin_decl_declared_p (fncode, true);
+ break;
+ }
}
copy_attributes_to_builtin (newdecl);
@@ -2729,8 +2790,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
with that from NEWDECL below. */
if (DECL_LANG_SPECIFIC (olddecl))
{
- gcc_assert (DECL_LANG_SPECIFIC (olddecl)
- != DECL_LANG_SPECIFIC (newdecl));
+ gcc_checking_assert (DECL_LANG_SPECIFIC (olddecl)
+ != DECL_LANG_SPECIFIC (newdecl));
ggc_free (DECL_LANG_SPECIFIC (olddecl));
}
@@ -2816,6 +2877,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
+
+ if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl))
+ {
+ /* Repropagate the module information to the template. */
+ tree tmpl = DECL_TI_TEMPLATE (olddecl);
+
+ if (DECL_TEMPLATE_RESULT (tmpl) == olddecl)
+ {
+ DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl);
+ gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl));
+ DECL_MODULE_IMPORT_P (tmpl) = false;
+ }
+ }
+
switch (TREE_CODE (newdecl))
{
case LABEL_DECL:
@@ -2860,7 +2935,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
done later in decl_attributes since we are called before attributes
are assigned. */
if (DECL_SECTION_NAME (newdecl) != NULL)
- set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl));
+ set_decl_section_name (olddecl, newdecl);
if (DECL_ONE_ONLY (newdecl))
{
@@ -2915,6 +2990,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
snode->remove ();
}
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ {
+ tree clone;
+ FOR_EACH_CLONE (clone, olddecl)
+ {
+ DECL_ATTRIBUTES (clone) = DECL_ATTRIBUTES (olddecl);
+ DECL_PRESERVE_P (clone) |= DECL_PRESERVE_P (olddecl);
+ }
+ }
+
/* Remove the associated constraints for newdecl, if any, before
reclaiming memory. */
if (flag_concepts)
@@ -3660,17 +3745,17 @@ void
pop_switch (void)
{
struct cp_switch *cs = switch_stack;
- location_t switch_location;
/* Emit warnings as needed. */
- switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt);
+ location_t switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt);
+ tree cond = SWITCH_STMT_COND (cs->switch_stmt);
const bool bool_cond_p
= (SWITCH_STMT_TYPE (cs->switch_stmt)
&& TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE);
if (!processing_template_decl)
c_do_switch_warnings (cs->cases, switch_location,
- SWITCH_STMT_TYPE (cs->switch_stmt),
- SWITCH_STMT_COND (cs->switch_stmt), bool_cond_p);
+ SWITCH_STMT_TYPE (cs->switch_stmt), cond,
+ bool_cond_p);
/* For the benefit of block_may_fallthru remember if the switch body
case labels cover all possible values and if there are break; stmts. */
@@ -3681,6 +3766,15 @@ pop_switch (void)
SWITCH_STMT_ALL_CASES_P (cs->switch_stmt) = 1;
if (!cs->break_stmt_seen_p)
SWITCH_STMT_NO_BREAK_P (cs->switch_stmt) = 1;
+ /* Now that we're done with the switch warnings, set the switch type
+ to the type of the condition if the index type was of scoped enum type.
+ (Such types don't participate in the integer promotions.) We do this
+ because of bit-fields whose declared type is a scoped enum type:
+ gimplification will use the lowered index type, but convert the
+ case values to SWITCH_STMT_TYPE, which would have been the declared type
+ and verify_gimple_switch doesn't accept that. */
+ if (is_bitfield_expr_with_lowered_type (cond))
+ SWITCH_STMT_TYPE (cs->switch_stmt) = TREE_TYPE (cond);
gcc_assert (!cs->in_loop_body_p);
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
@@ -4102,6 +4196,14 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
return tmpl;
}
+ return make_unbound_class_template_raw (context, name, parm_list);
+}
+
+/* Build an UNBOUND_CLASS_TEMPLATE. */
+
+tree
+make_unbound_class_template_raw (tree context, tree name, tree parm_list)
+{
/* Build the UNBOUND_CLASS_TEMPLATE. */
tree t = cxx_make_type (UNBOUND_CLASS_TEMPLATE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
@@ -4245,6 +4347,8 @@ initialize_predefined_identifiers (void)
{"heap uninit", &heap_uninit_identifier, cik_normal},
{"heap ", &heap_identifier, cik_normal},
{"heap deleted", &heap_deleted_identifier, cik_normal},
+ {"heap [] uninit", &heap_vec_uninit_identifier, cik_normal},
+ {"heap []", &heap_vec_identifier, cik_normal},
{NULL, NULL, cik_normal}
};
@@ -4281,7 +4385,8 @@ cxx_init_decl_processing (void)
gcc_assert (global_namespace == NULL_TREE);
global_namespace = build_lang_decl (NAMESPACE_DECL, global_identifier,
void_type_node);
- TREE_PUBLIC (global_namespace) = 1;
+ TREE_PUBLIC (global_namespace) = true;
+ DECL_MODULE_EXPORT_P (global_namespace) = true;
DECL_CONTEXT (global_namespace)
= build_translation_unit_decl (get_identifier (main_input_filename));
/* Remember whether we want the empty class passing ABI change warning
@@ -4376,6 +4481,9 @@ cxx_init_decl_processing (void)
init_list_type_node = make_node (LANG_TYPE);
record_unknown_type (init_list_type_node, "init list");
+ /* Used when parsing to distinguish parameter-lists () and (void). */
+ explicit_void_list_node = build_void_list_node ();
+
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
@@ -4577,6 +4685,9 @@ cxx_init_decl_processing (void)
if (! supports_one_only ())
flag_weak = 0;
+ if (modules_p ())
+ init_modules (parse_in);
+
make_fname_decl = cp_make_fname_decl;
start_fname_decls ();
@@ -5213,6 +5324,7 @@ start_decl (const cp_declarator *declarator,
bool was_public;
int flags;
bool alias;
+ tree initial;
*pushed_scope_p = NULL_TREE;
@@ -5237,6 +5349,10 @@ start_decl (const cp_declarator *declarator,
return error_mark_node;
}
+ /* Save the DECL_INITIAL value in case it gets clobbered to assist
+ with attribute validation. */
+ initial = DECL_INITIAL (decl);
+
if (initialized)
{
if (! toplevel_bindings_p ()
@@ -5246,6 +5362,10 @@ start_decl (const cp_declarator *declarator,
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
+ /* Tell 'cplus_decl_attributes' this is an initialized decl,
+ even though we might not yet have the initializer expression. */
+ if (!DECL_INITIAL (decl))
+ DECL_INITIAL (decl) = error_mark_node;
}
alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) != 0;
@@ -5264,6 +5384,10 @@ start_decl (const cp_declarator *declarator,
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, flags);
+ /* Restore the original DECL_INITIAL that we may have clobbered earlier to
+ assist with attribute validation. */
+ DECL_INITIAL (decl) = initial;
+
/* Dllimported symbols cannot be defined. Static data members (which
can be initialized in-class and dllimported) go through grokfield,
not here, so we don't need to exclude those decls when checking for
@@ -5388,8 +5512,14 @@ start_decl (const cp_declarator *declarator,
if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL)
&& current_function_decl)
- /* A function-scope decl of some namespace-scope decl. */
- DECL_LOCAL_DECL_P (decl) = true;
+ {
+ /* A function-scope decl of some namespace-scope decl. */
+ DECL_LOCAL_DECL_P (decl) = true;
+ if (named_module_purview_p ())
+ error_at (declarator->id_loc,
+ "block-scope extern declaration %q#D not permitted"
+ " in module purview", decl);
+ }
/* Enter this declaration into the symbol table. Don't push the plain
VAR_DECL for a variable template. */
@@ -5405,7 +5535,9 @@ start_decl (const cp_declarator *declarator,
if (VAR_P (decl)
&& DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
- && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
+ && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl)
+ /* But not templated variables. */
+ && !(DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
{
/* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are
@@ -5450,20 +5582,17 @@ start_decl (const cp_declarator *declarator,
void
start_decl_1 (tree decl, bool initialized)
{
- tree type;
- bool complete_p;
- bool aggregate_definition_p;
-
- gcc_assert (!processing_template_decl);
+ gcc_checking_assert (!processing_template_decl);
if (error_operand_p (decl))
return;
- gcc_assert (VAR_P (decl));
+ gcc_checking_assert (VAR_P (decl));
- type = TREE_TYPE (decl);
- complete_p = COMPLETE_TYPE_P (type);
- aggregate_definition_p = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
+ tree type = TREE_TYPE (decl);
+ bool complete_p = COMPLETE_TYPE_P (type);
+ bool aggregate_definition_p
+ = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
/* If an explicit initializer is present, or if this is a definition
of an aggregate, then we need a complete type at this point.
@@ -5488,6 +5617,7 @@ start_decl_1 (tree decl, bool initialized)
: TCTX_STATIC_STORAGE);
verify_type_context (input_location, context, TREE_TYPE (decl));
}
+
if (initialized)
/* Is it valid for this decl to have an initializer at all? */
{
@@ -6846,9 +6976,17 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
have returned an INIT_EXPR rather than a CALL_EXPR. In that
case, pull the initializer back out and pass it down into
store_init_value. */
- while (TREE_CODE (init_code) == EXPR_STMT
- || TREE_CODE (init_code) == CONVERT_EXPR)
- init_code = TREE_OPERAND (init_code, 0);
+ while (true)
+ {
+ if (TREE_CODE (init_code) == EXPR_STMT
+ || TREE_CODE (init_code) == STMT_EXPR
+ || TREE_CODE (init_code) == CONVERT_EXPR)
+ init_code = TREE_OPERAND (init_code, 0);
+ else if (TREE_CODE (init_code) == BIND_EXPR)
+ init_code = BIND_EXPR_BODY (init_code);
+ else
+ break;
+ }
if (TREE_CODE (init_code) == INIT_EXPR)
{
/* In C++20, the call to build_aggr_init could have created
@@ -7907,10 +8045,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
make_rtl_for_nonlocal_decl (decl, init, asmspec);
- /* Check for abstractness of the type. Notice that there is no
- need to strip array types here since the check for those types
- is already done within create_array_type_for_decl. */
- abstract_virtuals_error (decl, type);
+ /* Check for abstractness of the type. */
+ if (var_definition_p)
+ abstract_virtuals_error (decl, type);
if (TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
@@ -9808,6 +9945,8 @@ grokfndecl (tree ctype,
&& !processing_template_decl)
deduce_noexcept_on_destructor (decl);
+ set_originating_module (decl);
+
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * funcdef_flag +
@@ -10052,6 +10191,8 @@ grokvardecl (tree type,
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
+ set_originating_module (decl);
+
if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
{
if (DECL_EXTERNAL (decl) || TREE_STATIC (decl))
@@ -10316,7 +10457,7 @@ fold_sizeof_expr (tree t)
else
r = cxx_sizeof_or_alignof_expr (EXPR_LOCATION (t),
TREE_OPERAND (t, 0), SIZEOF_EXPR,
- false);
+ false, false);
if (r == error_mark_node)
r = size_one_node;
return r;
@@ -10682,11 +10823,6 @@ create_array_type_for_decl (tree name, tree type, tree size, location_t loc)
itype = compute_array_index_type_loc (loc, name, size,
tf_warning_or_error);
- /* [dcl.array]
- T is called the array element type; this type shall not be [...] an
- abstract class type. */
- abstract_virtuals_error (name, type);
-
return build_cplus_array_type (type, itype);
}
@@ -11381,7 +11517,7 @@ grokdeclarator (const cp_declarator *declarator,
/* An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
- temp_override<deprecated_states> ds (deprecated_state);
+ auto ds = make_temp_override (deprecated_state);
if (attrlist && lookup_attribute ("deprecated", *attrlist))
deprecated_state = DEPRECATED_SUPPRESS;
@@ -12037,8 +12173,17 @@ grokdeclarator (const cp_declarator *declarator,
&& inner_declarator->u.id.qualifying_scope
&& (MAYBE_CLASS_TYPE_P (type)
|| TREE_CODE (type) == ENUMERAL_TYPE)))
- warning_at (declarator->parenthesized, OPT_Wparentheses,
- "unnecessary parentheses in declaration of %qs", name);
+ {
+ if (warning_at (declarator->parenthesized, OPT_Wparentheses,
+ "unnecessary parentheses in declaration of %qs",
+ name))
+ {
+ gcc_rich_location iloc (declarator->parenthesized);
+ iloc.add_fixit_remove (get_start (declarator->parenthesized));
+ iloc.add_fixit_remove (get_finish (declarator->parenthesized));
+ inform (&iloc, "remove parentheses");
+ }
+ }
if (declarator->kind == cdk_id || declarator->kind == cdk_decomp)
break;
@@ -12069,11 +12214,6 @@ grokdeclarator (const cp_declarator *declarator,
/* Declaring a function type. */
- {
- iloc_sentinel ils (declspecs->locations[ds_type_spec]);
- abstract_virtuals_error (ACU_RETURN, type);
- }
-
/* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers;
/* Pick up virt-specifiers. */
@@ -12896,6 +13036,8 @@ grokdeclarator (const cp_declarator *declarator,
revert this subsequently if it determines that
the clones should share a common implementation. */
DECL_ABSTRACT_P (decl) = true;
+
+ set_originating_module (decl);
}
else if (current_class_type
&& constructor_name_p (unqualified_id, current_class_type))
@@ -13093,6 +13235,16 @@ grokdeclarator (const cp_declarator *declarator,
if (decl_context == PARM && AUTO_IS_DECLTYPE (auto_node))
error_at (typespec_loc,
"cannot declare a parameter with %<decltype(auto)%>");
+ else if (tree c = CLASS_PLACEHOLDER_TEMPLATE (auto_node))
+ {
+ auto_diagnostic_group g;
+ error_at (typespec_loc,
+ "class template placeholder %qE not permitted "
+ "in this context", c);
+ if (decl_context == PARM && cxx_dialect >= cxx20)
+ inform (typespec_loc, "use %<auto%> for an "
+ "abbreviated function template");
+ }
else
error_at (typespec_loc,
"%<auto%> parameter not permitted in this context");
@@ -13420,6 +13572,8 @@ grokdeclarator (const cp_declarator *declarator,
; /* We already issued a permerror. */
else if (decl && DECL_NAME (decl))
{
+ set_originating_module (decl, true);
+
if (initialized)
/* Kludge: We need funcdef_flag to be true in do_friend for
in-class defaulted functions, but that breaks grokfndecl.
@@ -13844,6 +13998,7 @@ require_complete_types_for_parms (tree parms)
relayout_decl (parms);
DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
+ abstract_virtuals_error (parms, TREE_TYPE (parms));
maybe_warn_parm_abi (TREE_TYPE (parms),
DECL_SOURCE_LOCATION (parms));
}
@@ -14022,7 +14177,7 @@ grokparms (tree parmlist, tree *parms)
tree init = TREE_PURPOSE (parm);
tree decl = TREE_VALUE (parm);
- if (parm == void_list_node)
+ if (parm == void_list_node || parm == explicit_void_list_node)
break;
if (! decl || TREE_TYPE (decl) == error_mark_node)
@@ -14081,9 +14236,6 @@ grokparms (tree parmlist, tree *parms)
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
- else if (abstract_virtuals_error (decl, type))
- /* Ignore any default argument. */
- init = NULL_TREE;
else if (cxx_dialect < cxx17 && INDIRECT_TYPE_P (type))
{
/* Before C++17 DR 393:
@@ -14860,7 +15012,6 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
else
decl = lookup_elaborated_type (name, how);
-
if (!decl)
/* We found nothing. */
return NULL_TREE;
@@ -14881,8 +15032,8 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
if (TREE_CODE (decl) != TYPE_DECL)
/* Found not-a-type. */
return NULL_TREE;
-
- /* Look for invalid nested type:
+
+ /* Look for invalid nested type:
class C {
class C {};
}; */
@@ -15059,6 +15210,41 @@ xref_tag_1 (enum tag_types tag_code, tree name,
inform (location_of (t), "previous declaration %qD", t);
return error_mark_node;
}
+
+ if (modules_p ()
+ && how == TAG_how::CURRENT_ONLY)
+ {
+ tree decl = TYPE_NAME (t);
+ if (!module_may_redeclare (decl))
+ {
+ error ("cannot declare %qD in a different module", decl);
+ inform (DECL_SOURCE_LOCATION (decl), "declared here");
+ return error_mark_node;
+ }
+
+ tree maybe_tmpl = decl;
+ if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t))
+ maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t);
+
+ if (DECL_LANG_SPECIFIC (decl)
+ && DECL_MODULE_IMPORT_P (decl)
+ && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ {
+ /* Push it into this TU's symbol slot. */
+ gcc_checking_assert (current_namespace == CP_DECL_CONTEXT (decl));
+ if (maybe_tmpl != decl)
+ /* We're in the template parm binding level.
+ Pushtag has logic to slide under that, but we're
+ not pushing a *new* type. */
+ push_nested_namespace (CP_DECL_CONTEXT (decl));
+
+ pushdecl (maybe_tmpl);
+ if (maybe_tmpl != decl)
+ pop_nested_namespace (CP_DECL_CONTEXT (decl));
+ }
+
+ set_instantiating_module (maybe_tmpl);
+ }
}
return t;
@@ -15403,6 +15589,19 @@ start_enum (tree name, tree enumtype, tree underlying_type,
"previous definition here");
underlying_type = NULL_TREE;
}
+
+ if (modules_p ())
+ {
+ if (!module_may_redeclare (TYPE_NAME (enumtype)))
+ {
+ error ("cannot define %qD in different module",
+ TYPE_NAME (enumtype));
+ inform (DECL_SOURCE_LOCATION (TYPE_NAME (enumtype)),
+ "declared here");
+ enumtype = error_mark_node;
+ }
+ set_instantiating_module (TYPE_NAME (enumtype));
+ }
}
if (!enumtype || TREE_CODE (enumtype) != ENUMERAL_TYPE
@@ -15663,6 +15862,11 @@ finish_enum_value_list (tree enumtype)
else
underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
+ /* If the enum is exported, mark the consts too. */
+ bool export_p = (UNSCOPED_ENUM_P (enumtype)
+ && DECL_MODULE_EXPORT_P (TYPE_STUB_DECL (enumtype))
+ && at_namespace_scope_p ());
+
/* Convert each of the enumerators to the type of the underlying
type of the enumeration. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
@@ -15685,6 +15889,8 @@ finish_enum_value_list (tree enumtype)
TREE_TYPE (value) = enumtype;
}
DECL_INITIAL (decl) = value;
+ if (export_p)
+ DECL_MODULE_EXPORT_P (decl) = true;
}
/* Fix up all variant types of this enum type. */
@@ -16844,20 +17050,6 @@ record_key_method_defined (tree fndecl)
}
}
-/* Subroutine of finish_function.
- Save the body of constexpr functions for possible
- future compile time evaluation. */
-
-static void
-maybe_save_function_definition (tree fun)
-{
- if (!processing_template_decl
- && DECL_DECLARED_CONSTEXPR_P (fun)
- && !cp_function_chain->invalid_constexpr
- && !DECL_CLONED_FUNCTION_P (fun))
- register_constexpr_fundef (fun, DECL_SAVED_TREE (fun));
-}
-
/* Attempt to add a fix-it hint to RICHLOC suggesting the insertion
of "return *this;" immediately before its location, using FNDECL's
first statement (if any) to give the indentation, if appropriate. */
@@ -16891,7 +17083,7 @@ emit_coro_helper (tree helper)
allocate_struct_function (helper, false);
cfun->language = ggc_cleared_alloc<language_function> ();
poplevel (1, 0, 1);
- maybe_save_function_definition (helper);
+ maybe_save_constexpr_fundef (helper);
/* We must start each function with a clear fold cache. */
clear_fold_cache ();
cp_fold_function (helper);
@@ -17125,7 +17317,7 @@ finish_function (bool inline_p)
/* Save constexpr function body before it gets munged by
the NRV transformation. */
- maybe_save_function_definition (fndecl);
+ maybe_save_constexpr_fundef (fndecl);
/* Invoke the pre-genericize plugin before we start munging things. */
if (!processing_template_decl)
@@ -17296,10 +17488,25 @@ grokmethod (cp_decl_specifier_seq *declspecs,
check_template_shadow (fndecl);
- if (TREE_PUBLIC (fndecl))
- DECL_COMDAT (fndecl) = 1;
- DECL_DECLARED_INLINE_P (fndecl) = 1;
- DECL_NO_INLINE_WARNING_P (fndecl) = 1;
+ /* p1779 ABI-Isolation makes inline not a default for in-class
+ definitions in named module purview. If the user explicitly
+ made it inline, grokdeclarator will already have done the right
+ things. */
+ if ((!named_module_purview_p ()
+ || flag_module_implicit_inline
+ /* Lambda's operator function remains inline. */
+ || LAMBDA_TYPE_P (DECL_CONTEXT (fndecl)))
+ /* If the user explicitly asked for this to be inline, we don't
+ need to do more, but more importantly we want to warn if we
+ can't inline it. */
+ && !DECL_DECLARED_INLINE_P (fndecl))
+ {
+ if (TREE_PUBLIC (fndecl))
+ DECL_COMDAT (fndecl) = 1;
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
+ /* It's ok if we can't inline this. */
+ DECL_NO_INLINE_WARNING_P (fndecl) = 1;
+ }
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
@@ -17400,9 +17607,6 @@ complete_vars (tree type)
else
ix++;
}
-
- /* Check for pending declarations which may have abstract type. */
- complete_type_check_abstract (type);
}
/* If DECL is of a type which needs a cleanup, build and return an
@@ -17570,6 +17774,7 @@ cp_tree_node_structure (union lang_tree_node * t)
case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
+ case BINDING_VECTOR: return TS_CP_BINDING_VECTOR;
case OVERLOAD: return TS_CP_OVERLOAD;
case PTRMEM_CST: return TS_CP_PTRMEM;
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
@@ -17668,6 +17873,7 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
/* We probably already complained about deduction failure. */;
else if (complain & tf_error)
error ("use of %qD before deduction of %<auto%>", decl);
+ note_failed_type_completion_for_satisfaction (decl);
return false;
}
return true;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2f0d637..af88e7f 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "c-family/c-ada-spec.h"
#include "asan.h"
+#include "optabs-query.h"
/* Id for dumping the raw trees. */
int raw_dump_id;
@@ -1928,7 +1929,7 @@ static void
clear_consteval_vfns (vec<tree> &consteval_vtables)
{
for (tree vtable : consteval_vtables)
- for (constructor_elt &elt : *CONSTRUCTOR_ELTS (DECL_INITIAL (vtable)))
+ for (constructor_elt &elt : CONSTRUCTOR_ELTS (DECL_INITIAL (vtable)))
{
tree fn = cp_get_fndecl_from_callee (elt.value, /*fold*/false);
if (fn && DECL_IMMEDIATE_FUNCTION_P (fn))
@@ -2894,9 +2895,8 @@ constrain_class_visibility (tree type)
/* Functions for adjusting the visibility of a tagged type and its nested
types and declarations when it gets a name for linkage purposes from a
typedef. */
-
-static void bt_reset_linkage_1 (binding_entry, void *);
-static void bt_reset_linkage_2 (binding_entry, void *);
+// FIXME: It is now a DR for such a class type to contain anything
+// other than C. So at minium most of this can probably be deleted.
/* First reset the visibility of all the types. */
@@ -2905,13 +2905,9 @@ reset_type_linkage_1 (tree type)
{
set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
if (CLASS_TYPE_P (type))
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (type),
- bt_reset_linkage_1, NULL);
-}
-static void
-bt_reset_linkage_1 (binding_entry b, void */*data*/)
-{
- reset_type_linkage_1 (b->type);
+ for (tree member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
+ if (DECL_IMPLICIT_TYPEDEF_P (member))
+ reset_type_linkage_1 (TREE_TYPE (member));
}
/* Then reset the visibility of any static data members or member
@@ -2930,9 +2926,10 @@ reset_decl_linkage (tree decl)
tentative_decl_linkage (decl);
}
-static void
-reset_type_linkage_2 (tree type)
+void
+reset_type_linkage (tree type)
{
+ reset_type_linkage_1 (type);
if (CLASS_TYPE_P (type))
{
if (tree vt = CLASSTYPE_VTABLES (type))
@@ -2955,24 +2952,12 @@ reset_type_linkage_2 (tree type)
tree mem = STRIP_TEMPLATE (m);
if (TREE_CODE (mem) == VAR_DECL || TREE_CODE (mem) == FUNCTION_DECL)
reset_decl_linkage (mem);
+ else if (DECL_IMPLICIT_TYPEDEF_P (mem))
+ reset_type_linkage (TREE_TYPE (mem));
}
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (type),
- bt_reset_linkage_2, NULL);
}
}
-static void
-bt_reset_linkage_2 (binding_entry b, void */*data*/)
-{
- reset_type_linkage_2 (b->type);
-}
-void
-reset_type_linkage (tree type)
-{
- reset_type_linkage_1 (type);
- reset_type_linkage_2 (type);
-}
-
/* Set up our initial idea of what the linkage of DECL should be. */
void
@@ -3313,18 +3298,34 @@ get_guard (tree decl)
return guard;
}
+/* Returns true if accessing the GUARD atomic is expensive,
+ i.e. involves a call to __sync_synchronize or similar.
+ In this case let __cxa_guard_acquire handle the atomics. */
+
+static bool
+is_atomic_expensive_p (machine_mode mode)
+{
+ if (!flag_inline_atomics)
+ return true;
+
+ if (!can_compare_and_swap_p (mode, false) || !can_atomic_load_p (mode))
+ return true;
+
+ return false;
+}
+
/* Return an atomic load of src with the appropriate memory model. */
static tree
-build_atomic_load_byte (tree src, HOST_WIDE_INT model)
+build_atomic_load_type (tree src, HOST_WIDE_INT model, tree type)
{
- tree ptr_type = build_pointer_type (char_type_node);
+ tree ptr_type = build_pointer_type (type);
tree mem_model = build_int_cst (integer_type_node, model);
tree t, addr, val;
unsigned int size;
int fncode;
- size = tree_to_uhwi (TYPE_SIZE_UNIT (char_type_node));
+ size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
fncode = BUILT_IN_ATOMIC_LOAD_N + exact_log2 (size) + 1;
t = builtin_decl_implicit ((enum built_in_function) fncode);
@@ -3367,7 +3368,15 @@ get_guard_cond (tree guard, bool thread_safe)
if (!thread_safe)
guard = get_guard_bits (guard);
else
- guard = build_atomic_load_byte (guard, MEMMODEL_ACQUIRE);
+ {
+ tree type = targetm.cxx.guard_mask_bit ()
+ ? TREE_TYPE (guard) : char_type_node;
+
+ if (is_atomic_expensive_p (TYPE_MODE (type)))
+ guard = integer_zero_node;
+ else
+ guard = build_atomic_load_type (guard, MEMMODEL_ACQUIRE, type);
+ }
/* Mask off all but the low bit. */
if (targetm.cxx.guard_mask_bit ())
@@ -3652,35 +3661,45 @@ generate_tls_wrapper (tree fn)
static tree
start_objects (int method_type, int initp)
{
- tree body;
- tree fndecl;
- char type[14];
-
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
+ int module_init = 0;
+
+ if (initp == DEFAULT_INIT_PRIORITY && method_type == 'I')
+ module_init = module_initializer_kind ();
- if (initp != DEFAULT_INIT_PRIORITY)
+ tree name = NULL_TREE;
+ if (module_init > 0)
+ name = mangle_module_global_init (0);
+ else
{
- char joiner;
+ char type[14];
+ unsigned len = sprintf (type, "sub_%c", method_type);
+ if (initp != DEFAULT_INIT_PRIORITY)
+ {
+ char joiner = '_';
#ifdef JOINER
- joiner = JOINER;
-#else
- joiner = '_';
+ joiner = JOINER;
#endif
+ type[len++] = joiner;
+ sprintf (type + len, "%.5u", initp);
+ }
+ name = get_file_function_name (type);
+ }
- sprintf (type, "sub_%c%c%.5u", method_type, joiner, initp);
+ tree fntype = build_function_type (void_type_node, void_list_node);
+ tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype);
+ DECL_CONTEXT (fndecl) = FROB_CONTEXT (global_namespace);
+ if (module_init > 0)
+ {
+ SET_DECL_ASSEMBLER_NAME (fndecl, name);
+ TREE_PUBLIC (fndecl) = true;
+ determine_visibility (fndecl);
}
else
- sprintf (type, "sub_%c", method_type);
-
- fndecl = build_lang_decl (FUNCTION_DECL,
- get_file_function_name (type),
- build_function_type_list (void_type_node,
- NULL_TREE));
+ TREE_PUBLIC (fndecl) = 0;
start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
- TREE_PUBLIC (current_function_decl) = 0;
-
/* Mark as artificial because it's not explicitly in the user's
source code. */
DECL_ARTIFICIAL (current_function_decl) = 1;
@@ -3694,7 +3713,35 @@ start_objects (int method_type, int initp)
else
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
- body = begin_compound_stmt (BCS_FN_BODY);
+ tree body = begin_compound_stmt (BCS_FN_BODY);
+
+ if (module_init > 0)
+ {
+ // 'static bool __in_chrg = false;
+ // if (__inchrg) return;
+ // __inchrg = true
+ tree var = build_lang_decl (VAR_DECL, in_charge_identifier,
+ boolean_type_node);
+ DECL_CONTEXT (var) = fndecl;
+ DECL_ARTIFICIAL (var) = true;
+ TREE_STATIC (var) = true;
+ pushdecl (var);
+ cp_finish_decl (var, NULL_TREE, false, NULL_TREE, 0);
+
+ tree if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (var, if_stmt);
+ finish_return_stmt (NULL_TREE);
+ finish_then_clause (if_stmt);
+ finish_if_stmt (if_stmt);
+
+ tree assign = build2 (MODIFY_EXPR, boolean_type_node,
+ var, boolean_true_node);
+ TREE_SIDE_EFFECTS (assign) = true;
+ finish_expr_stmt (assign);
+ }
+
+ if (module_init)
+ module_add_import_initializers ();
return body;
}
@@ -3705,11 +3752,9 @@ start_objects (int method_type, int initp)
static void
finish_objects (int method_type, int initp, tree body)
{
- tree fn;
-
/* Finish up. */
finish_compound_stmt (body);
- fn = finish_function (/*inline_p=*/false);
+ tree fn = finish_function (/*inline_p=*/false);
if (method_type == 'I')
{
@@ -4244,50 +4289,50 @@ static void
generate_ctor_or_dtor_function (bool constructor_p, int priority,
location_t *locus)
{
- char function_key;
- tree fndecl;
- tree body;
- size_t i;
-
input_location = *locus;
- /* ??? */
- /* Was: locus->line++; */
/* We use `I' to indicate initialization and `D' to indicate
destruction. */
- function_key = constructor_p ? 'I' : 'D';
+ char function_key = constructor_p ? 'I' : 'D';
/* We emit the function lazily, to avoid generating empty
global constructors and destructors. */
- body = NULL_TREE;
+ tree body = NULL_TREE;
- /* For Objective-C++, we may need to initialize metadata found in this module.
- This must be done _before_ any other static initializations. */
- if (c_dialect_objc () && (priority == DEFAULT_INIT_PRIORITY)
- && constructor_p && objc_static_init_needed_p ())
+ if (constructor_p && priority == DEFAULT_INIT_PRIORITY)
{
- body = start_objects (function_key, priority);
- objc_generate_static_init_call (NULL_TREE);
+ bool objc = c_dialect_objc () && objc_static_init_needed_p ();
+
+ /* We may have module initialization to emit and/or insert
+ before other intializations. */
+ if (module_initializer_kind () || objc)
+ body = start_objects (function_key, priority);
+
+ /* For Objective-C++, we may need to initialize metadata found
+ in this module. This must be done _before_ any other static
+ initializations. */
+ if (objc)
+ objc_generate_static_init_call (NULL_TREE);
}
/* Call the static storage duration function with appropriate
arguments. */
+ tree fndecl;
+ size_t i;
FOR_EACH_VEC_SAFE_ELT (ssdf_decls, i, fndecl)
{
/* Calls to pure or const functions will expand to nothing. */
if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
{
- tree call;
-
if (! body)
body = start_objects (function_key, priority);
- call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
- build_int_cst (NULL_TREE,
- constructor_p),
- build_int_cst (NULL_TREE,
- priority),
- NULL_TREE);
+ tree call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
+ build_int_cst (NULL_TREE,
+ constructor_p),
+ build_int_cst (NULL_TREE,
+ priority),
+ NULL_TREE);
finish_expr_stmt (call);
}
}
@@ -4363,7 +4408,7 @@ collect_source_refs (tree namespc)
{
/* Iterate over names in this name space. */
for (tree t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
- if (DECL_IS_BUILTIN (t))
+ if (DECL_IS_UNDECLARED_BUILTIN (t))
;
else if (TREE_CODE (t) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (t))
collect_source_refs (t);
@@ -4486,6 +4531,10 @@ no_linkage_error (tree decl)
/* In C++11 it's ok if the decl is defined. */
return;
+ if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl))
+ /* An imported decl is ok. */
+ return;
+
tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
if (t == NULL_TREE)
/* The type that got us on no_linkage_decls must have gotten a name for
@@ -4838,11 +4887,7 @@ lower_var_init ()
void
c_parse_final_cleanups (void)
{
- tree vars;
- bool reconsider;
size_t i;
- unsigned ssdf_count = 0;
- int retries = 0;
tree decl;
locus_at_end_of_parsing = input_location;
@@ -4908,11 +4953,10 @@ c_parse_final_cleanups (void)
/* Track vtables we want to emit that refer to consteval functions. */
auto_vec<tree> consteval_vtables;
- do
+ int retries = 0;
+ unsigned ssdf_count = 0;
+ for (bool reconsider = true; reconsider; retries++)
{
- tree t;
- tree decl;
-
reconsider = false;
/* If there are templates that we've put off instantiating, do
@@ -4920,11 +4964,17 @@ c_parse_final_cleanups (void)
instantiate_pending_templates (retries);
ggc_collect ();
+ if (header_module_p ())
+ /* A header modules initializations are handled in its
+ importer. */
+ continue;
+
/* Write out virtual tables as required. Writing out the
virtual table for a template class may cause the
instantiation of members of that class. If we write out
vtables then we remove the class from our list so we don't
have to look at it again. */
+ tree t;
for (i = keyed_classes->length ();
keyed_classes->iterate (--i, &t);)
if (maybe_emit_vtables (t, consteval_vtables))
@@ -4954,10 +5004,15 @@ c_parse_final_cleanups (void)
aggregates added during the initialization of these will be
initialized in the correct order when we next come around the
loop. */
- vars = prune_vars_needing_no_initialization (&static_aggregates);
-
- if (vars)
+ if (tree vars = prune_vars_needing_no_initialization (&static_aggregates))
{
+ if (flag_openmp)
+ /* Add initializer information from VARS into
+ DYNAMIC_INITIALIZERS. */
+ for (t = vars; t; t = TREE_CHAIN (t))
+ hash_map_safe_put<hm_ggc> (dynamic_initializers,
+ TREE_VALUE (t), TREE_PURPOSE (t));
+
/* We need to start a new initialization function each time
through the loop. That's because we need to know which
vtables have been referenced, and TREE_SYMBOL_REFERENCED
@@ -5003,7 +5058,6 @@ c_parse_final_cleanups (void)
instantiations, etc. */
reconsider = true;
ssdf_count++;
- /* ??? was: locus_at_end_of_parsing.line++; */
}
/* Now do the same for thread_local variables. */
@@ -5113,14 +5167,14 @@ c_parse_final_cleanups (void)
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
DECL_EXTERNAL (decl) = 0;
}
+
if (vec_safe_length (pending_statics) != 0
&& wrapup_global_declarations (pending_statics->address (),
pending_statics->length ()))
reconsider = true;
-
- retries++;
}
- while (reconsider);
+
+ finish_module_processing (parse_in);
lower_var_init ();
@@ -5137,6 +5191,10 @@ c_parse_final_cleanups (void)
#pragma interface, etc.) we decided not to emit the
definition here. */
&& !DECL_INITIAL (decl)
+ /* A defaulted fn in a header module can be synthesized on
+ demand later. (In non-header modules we should have
+ synthesized it above.) */
+ && !(DECL_DEFAULTED_FN (decl) && header_module_p ())
/* Don't complain if the template was defined. */
&& !(DECL_TEMPLATE_INSTANTIATION (decl)
&& DECL_INITIAL (DECL_TEMPLATE_RESULT
@@ -5170,9 +5228,8 @@ c_parse_final_cleanups (void)
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
/*data=*/&locus_at_end_of_parsing);
- else if (c_dialect_objc () && objc_static_init_needed_p ())
- /* If this is obj-c++ and we need a static init, call
- generate_ctor_or_dtor_function. */
+ else if ((c_dialect_objc () && objc_static_init_needed_p ())
+ || module_initializer_kind ())
generate_ctor_or_dtor_function (/*constructor_p=*/true,
DEFAULT_INIT_PRIORITY,
&locus_at_end_of_parsing);
@@ -5181,6 +5238,8 @@ c_parse_final_cleanups (void)
if (priority_info_map)
splay_tree_delete (priority_info_map);
+ fini_modules ();
+
/* Generate any missing aliases. */
maybe_apply_pending_pragma_weaks ();
@@ -5604,16 +5663,6 @@ mark_used (tree decl, tsubst_flags_t complain)
if (DECL_ODR_USED (decl))
return true;
- /* Normally, we can wait until instantiation-time to synthesize DECL.
- However, if DECL is a static data member initialized with a constant
- or a constexpr function, we need it right now because a reference to
- such a data member or a call to such function is not value-dependent.
- For a function that uses auto in the return type, we need to instantiate
- it to find out its type. For OpenMP user defined reductions, we need
- them instantiated for reduction clauses which inline them by hand
- directly. */
- maybe_instantiate_decl (decl);
-
if (flag_concepts && TREE_CODE (decl) == FUNCTION_DECL
&& !constraints_satisfied_p (decl))
{
@@ -5629,6 +5678,16 @@ mark_used (tree decl, tsubst_flags_t complain)
return false;
}
+ /* Normally, we can wait until instantiation-time to synthesize DECL.
+ However, if DECL is a static data member initialized with a constant
+ or a constexpr function, we need it right now because a reference to
+ such a data member or a call to such function is not value-dependent.
+ For a function that uses auto in the return type, we need to instantiate
+ it to find out its type. For OpenMP user defined reductions, we need
+ them instantiated for reduction clauses which inline them by hand
+ directly. */
+ maybe_instantiate_decl (decl);
+
if (processing_template_decl || in_template_function ())
return true;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 396558b..4572f6e 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -179,6 +179,38 @@ cxx_initialize_diagnostics (diagnostic_context *context)
pp->m_format_postprocessor = new cxx_format_postprocessor ();
}
+/* Dump an '@module' name suffix for DECL, if any. */
+
+static void
+dump_module_suffix (cxx_pretty_printer *pp, tree decl)
+{
+ if (!modules_p ())
+ return;
+
+ if (!DECL_CONTEXT (decl))
+ return;
+
+ if (TREE_CODE (decl) != CONST_DECL
+ || !UNSCOPED_ENUM_P (DECL_CONTEXT (decl)))
+ {
+ if (!DECL_NAMESPACE_SCOPE_P (decl))
+ return;
+
+ if (TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl)
+ && (TREE_PUBLIC (decl) || !TREE_PUBLIC (CP_DECL_CONTEXT (decl))))
+ return;
+ }
+
+ if (unsigned m = get_originating_module (decl))
+ if (const char *n = module_name (m, false))
+ {
+ pp_character (pp, '@');
+ pp->padding = pp_none;
+ pp_string (pp, n);
+ }
+}
+
/* Dump a scope, if deemed necessary. */
static void
@@ -529,6 +561,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
case INTEGER_TYPE:
case REAL_TYPE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case BOOLEAN_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
@@ -770,6 +803,8 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags)
else
pp_cxx_tree_identifier (pp, DECL_NAME (decl));
+ dump_module_suffix (pp, decl);
+
if (tmplate)
dump_template_parms (pp, TYPE_TEMPLATE_INFO (t),
!CLASSTYPE_USE_TEMPLATE (t),
@@ -874,6 +909,7 @@ dump_type_prefix (cxx_pretty_printer *pp, tree t, int flags)
case UNION_TYPE:
case LANG_TYPE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
@@ -997,6 +1033,7 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
case UNION_TYPE:
case LANG_TYPE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
@@ -1074,6 +1111,9 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
pp_string (pp, M_("<structured bindings>"));
else
pp_string (pp, M_("<anonymous>"));
+
+ dump_module_suffix (pp, t);
+
if (flags & TFF_DECL_SPECIFIERS)
dump_type_suffix (pp, type, flags);
}
@@ -1891,6 +1931,8 @@ dump_function_name (cxx_pretty_printer *pp, tree t, int flags)
else
dump_decl (pp, name, flags);
+ dump_module_suffix (pp, t);
+
if (DECL_TEMPLATE_INFO (t)
&& !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
&& (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
@@ -2810,6 +2852,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
case ENUMERAL_TYPE:
case REAL_TYPE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case BOOLEAN_TYPE:
case INTEGER_TYPE:
case COMPLEX_TYPE:
@@ -3549,6 +3592,14 @@ function_category (tree fn)
return _("In function %qs");
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the pp_verbatim calls. Their format strings deliberately don't
+ follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Report the full context of a current template instantiation,
onto BUFFER. */
static void
@@ -4149,12 +4200,17 @@ add_quotes (const char *content, bool show_color)
pp_show_color (&tmp_pp) = show_color;
/* We have to use "%<%s%>" rather than "%qs" here in order to avoid
- quoting colorization bytes within the results. */
+ quoting colorization bytes within the results and using either
+ pp_quote or pp_begin_quote doesn't work the same. */
pp_printf (&tmp_pp, "%<%s%>", content);
return pp_ggc_formatted_text (&tmp_pp);
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
+
/* If we had %H and %I, and hence deferred printing them,
print them now, storing the result into the chunk_info
for pp_format. Quote them if 'q' was provided.
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index cb1a410..e76ade2 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -41,7 +41,6 @@ static tree do_allocate_exception (tree);
static tree wrap_cleanups_r (tree *, int *, void *);
static int complete_ptr_ref_or_void_ptr_p (tree, tree);
static bool is_admissible_throw_operand_or_catch_parameter (tree, bool);
-static int can_convert_eh (tree, tree);
/* Sets up all the global eh stuff that needs to be initialized at the
start of compilation. */
@@ -932,31 +931,34 @@ nothrow_libfn_p (const_tree fn)
/* Returns nonzero if an exception of type FROM will be caught by a
handler for type TO, as per [except.handle]. */
-static int
+static bool
can_convert_eh (tree to, tree from)
{
to = non_reference (to);
from = non_reference (from);
+ if (same_type_ignoring_top_level_qualifiers_p (to, from))
+ return true;
+
if (TYPE_PTR_P (to) && TYPE_PTR_P (from))
{
to = TREE_TYPE (to);
from = TREE_TYPE (from);
if (! at_least_as_qualified_p (to, from))
- return 0;
+ return false;
if (VOID_TYPE_P (to))
- return 1;
+ return true;
/* Else fall through. */
}
if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
&& publicly_uniquely_derived_p (to, from))
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Check whether any of the handlers in I are shadowed by another handler
@@ -975,11 +977,11 @@ check_handlers_1 (tree master, tree_stmt_iterator i)
tree handler = tsi_stmt (i);
if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
{
- warning_at (EXPR_LOCATION (handler), 0,
- "exception of type %qT will be caught",
- TREE_TYPE (handler));
- warning_at (EXPR_LOCATION (master), 0,
- " by earlier handler for %qT", type);
+ auto_diagnostic_group d;
+ if (warning_at (EXPR_LOCATION (handler), OPT_Wexceptions,
+ "exception of type %qT will be caught by earlier "
+ "handler", TREE_TYPE (handler)))
+ inform (EXPR_LOCATION (master), "for type %qT", type);
break;
}
}
@@ -1099,7 +1101,7 @@ maybe_noexcept_warning (tree fn)
&& (!DECL_IN_SYSTEM_HEADER (fn)
|| global_dc->dc_warn_system_headers))
{
- temp_override<bool> s (global_dc->dc_warn_system_headers, true);
+ auto s = make_temp_override (global_dc->dc_warn_system_headers, true);
auto_diagnostic_group d;
if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
"because of a call to %qD", fn))
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 0ab63bc..a8254cd 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -27,12 +27,10 @@ along with GCC; see the file COPYING3. If not see
#define LANGSPEC (1<<1)
/* This bit is set if they did `-lm' or `-lmath'. */
#define MATHLIB (1<<2)
-/* This bit is set if they did `-lrt' or equivalent. */
-#define TIMELIB (1<<3)
/* This bit is set if they did `-lc'. */
-#define WITHLIBC (1<<4)
+#define WITHLIBC (1<<3)
/* Skip this option. */
-#define SKIPOPT (1<<5)
+#define SKIPOPT (1<<4)
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "m"
@@ -41,10 +39,6 @@ along with GCC; see the file COPYING3. If not see
#define MATH_LIBRARY_PROFILE MATH_LIBRARY
#endif
-#ifndef TIME_LIBRARY
-#define TIME_LIBRARY ""
-#endif
-
#ifndef LIBSTDCXX
#define LIBSTDCXX "stdc++"
#endif
@@ -55,6 +49,34 @@ along with GCC; see the file COPYING3. If not see
#define LIBSTDCXX_STATIC NULL
#endif
+#ifndef LIBCXX
+#define LIBCXX "c++"
+#endif
+#ifndef LIBCXX_PROFILE
+#define LIBCXX_PROFILE LIBCXX
+#endif
+#ifndef LIBCXX_STATIC
+#define LIBCXX_STATIC NULL
+#endif
+
+#ifndef LIBCXXABI
+#define LIBCXXABI "c++abi"
+#endif
+#ifndef LIBCXXABI_PROFILE
+#define LIBCXXABI_PROFILE LIBCXXABI
+#endif
+#ifndef LIBCXXABI_STATIC
+#define LIBCXXABI_STATIC NULL
+#endif
+
+/* The values used here must match those of the stdlib_kind enumeration
+ in c.opt. */
+enum stdcxxlib_kind
+{
+ USE_LIBSTDCXX = 1,
+ USE_LIBCXX = 2
+};
+
void
lang_specific_driver (struct cl_decoded_option **in_decoded_options,
unsigned int *in_decoded_options_count,
@@ -65,13 +87,16 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
/* If nonzero, the user gave us the `-p' or `-pg' flag. */
int saw_profile_flag = 0;
- /* What do with libstdc++:
- -1 means we should not link in libstdc++
- 0 means we should link in libstdc++ if it is needed
- 1 means libstdc++ is needed and should be linked in.
- 2 means libstdc++ is needed and should be linked statically. */
+ /* What action to take for the c++ runtime library:
+ -1 means we should not link it in.
+ 0 means we should link it if it is needed.
+ 1 means it is needed and should be linked in.
+ 2 means it is needed but should be linked statically. */
int library = 0;
+ /* Which c++ runtime library to link. */
+ stdcxxlib_kind which_library = USE_LIBSTDCXX;
+
/* The number of arguments being added to what's in argv, other than
libraries. We use this to track the number of times we've inserted
-xc++/-xnone. */
@@ -95,15 +120,12 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
const struct cl_decoded_option *saw_libc = NULL;
/* An array used to flag each argument that needs a bit set for
- LANGSPEC, MATHLIB, TIMELIB, or WITHLIBC. */
+ LANGSPEC, MATHLIB, or WITHLIBC. */
int *args;
/* By default, we throw on the math library if we have one. */
int need_math = (MATH_LIBRARY[0] != '\0');
- /* By default, we throw on the time library if we have one. */
- int need_time = (TIME_LIBRARY[0] != '\0');
-
/* True if we saw -static. */
int static_link = 0;
@@ -147,11 +169,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
args[i] |= MATHLIB;
need_math = 0;
}
- else if (strcmp (arg, TIME_LIBRARY) == 0)
- {
- args[i] |= TIMELIB;
- need_time = 0;
- }
else if (strcmp (arg, "c") == 0)
args[i] |= WITHLIBC;
else
@@ -208,6 +225,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
args[i] |= SKIPOPT;
break;
+ case OPT_stdlib_:
+ which_library = (stdcxxlib_kind) decoded_options[i].value;
+ break;
+
case OPT_SPECIAL_input_file:
{
int len;
@@ -264,6 +285,13 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
/* Add one for shared_libgcc or extra static library. */
num_args = argc + added + need_math + (library > 0) * 4 + 1;
+ /* For libc++, on most platforms, the ABI library (usually called libc++abi)
+ is provided as a separate DSO, which we must also append.
+ However, a platform might have the ability to forward the ABI library
+ from libc++, or combine it in some other way; in that case, LIBCXXABI
+ should be set to NULL to signal that it need not be appended. */
+ if (which_library == USE_LIBCXX && LIBCXXABI != NULL)
+ num_args += 4;
new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
i = 0;
@@ -285,12 +313,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
saw_math = &decoded_options[i];
}
- if (!saw_time && (args[i] & TIMELIB) && library > 0)
- {
- --j;
- saw_time = &decoded_options[i];
- }
-
if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
{
--j;
@@ -343,9 +365,25 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
j++;
}
#endif
- generate_option (OPT_l,
- saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,
- CL_DRIVER, &new_decoded_options[j]);
+ if (which_library == USE_LIBCXX)
+ {
+ generate_option (OPT_l,
+ saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1,
+ CL_DRIVER, &new_decoded_options[j]);
+ if (LIBCXXABI != NULL)
+ {
+ j++;
+ added_libraries++;
+ generate_option (OPT_l,
+ saw_profile_flag ? LIBCXXABI_PROFILE
+ : LIBCXXABI, 1,
+ CL_DRIVER, &new_decoded_options[j]);
+ }
+ }
+ else
+ generate_option (OPT_l,
+ saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,
+ CL_DRIVER, &new_decoded_options[j]);
added_libraries++;
j++;
/* Add target-dependent static library, if necessary. */
@@ -377,13 +415,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
}
if (saw_time)
new_decoded_options[j++] = *saw_time;
- else if (library > 0 && need_time)
- {
- generate_option (OPT_l, TIME_LIBRARY, 1, CL_DRIVER,
- &new_decoded_options[j]);
- added_libraries++;
- j++;
- }
if (saw_libc)
new_decoded_options[j++] = *saw_libc;
if (shared_libgcc && !static_link)
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1bddb655..903d17f 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -187,7 +187,7 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
else if (NULLPTR_TYPE_P (type))
init = build_int_cst (type, 0);
else if (SCALAR_TYPE_P (type))
- init = fold (convert (type, integer_zero_node));
+ init = build_zero_cst (type);
else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
{
tree field;
@@ -1922,7 +1922,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
in an exception region. */;
else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP,
- flags, complain);
+ flags, complain | tf_no_cleanup);
if (TREE_CODE (init) == MUST_NOT_THROW_EXPR)
/* We need to protect the initialization of a catch parm with a
@@ -2957,7 +2957,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
return error_mark_node;
}
- if (is_std_init_list (elt_type))
+ if (is_std_init_list (elt_type) && !cp_unevaluated_operand)
warning (OPT_Winit_list_lifetime,
"%<new%> of %<initializer_list%> does not "
"extend the lifetime of the underlying array");
@@ -3766,7 +3766,11 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type,
/* P1009: Array size deduction in new-expressions. */
const bool array_p = TREE_CODE (type) == ARRAY_TYPE;
- if (*init && (array_p || (nelts && cxx_dialect >= cxx20)))
+ if (*init
+ /* If ARRAY_P, we have to deduce the array bound. For C++20 paren-init,
+ we have to process the parenthesized-list. But don't do it for (),
+ which is value-initialization, and INIT should stay empty. */
+ && (array_p || (cxx_dialect >= cxx20 && nelts && !(*init)->is_empty ())))
{
/* This means we have 'new T[]()'. */
if ((*init)->is_empty ())
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 1a1647f..f6746d7 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -1114,6 +1114,8 @@ maybe_add_lambda_conv_op (tree type)
while (src)
{
tree new_node = copy_node (src);
+ /* We set DECL_CONTEXT of NEW_NODE to the statfn below.
+ Notice this is creating a recursive type! */
/* Clear TREE_ADDRESSABLE on thunk arguments. */
TREE_ADDRESSABLE (new_node) = 0;
@@ -1393,6 +1395,12 @@ record_lambda_scope (tree lambda)
{
LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;
LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;
+ if (lambda_scope)
+ {
+ tree closure = LAMBDA_EXPR_CLOSURE (lambda);
+ gcc_checking_assert (closure);
+ maybe_attach_decl (lambda_scope, TYPE_NAME (closure));
+ }
}
/* This lambda is an instantiation of a lambda in a template default argument
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index 0ad4a33..1388aae 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -40,17 +40,57 @@ along with GCC; see the file COPYING3. If not see
{".tcc", "@c++-header", 0, 0, 0},
{".hh", "@c++-header", 0, 0, 0},
{"@c++-header",
- "%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}"
+ "%{E|M|MM:cc1plus -E %{fmodules-ts:-fdirectives-only -fmodule-header}"
+ " %(cpp_options) %2 %(cpp_debug_options)}"
+ "%{!E:%{!M:%{!MM:"
+ " %{save-temps*|no-integrated-cpp:cc1plus -E"
+ " %{fmodules-ts:-fdirectives-only -fmodule-header}"
+ " %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}"
+ " cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
+ " %{fmodules-ts:-fdirectives-only}"
+ " %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
+ " %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+ " %{fmodules-ts:-fmodule-header %{fpreprocessed:-fdirectives-only}}"
+ " %(cc1_options) %2"
+ " %{!S:-o %g.s%V}"
+ " %{!fsyntax-only:%{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
+ " %{!o*:--output-pch=%i.gch}%W{o*:--output-pch=%*}}}}}}}}",
+ CPLUSPLUS_CPP_SPEC, 0, 0},
+ {"@c++-system-header",
+ "%{E|M|MM:cc1plus -E"
+ " %{fmodules-ts:-fdirectives-only -fmodule-header=system}"
+ " %(cpp_options) %2 %(cpp_debug_options)}"
"%{!E:%{!M:%{!MM:"
" %{save-temps*|no-integrated-cpp:cc1plus -E"
+ " %{fmodules-ts:-fdirectives-only -fmodule-header=system}"
" %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}"
" cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
+ " %{fmodules-ts:-fdirectives-only}"
" %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
" %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+ " %{fmodules-ts:-fmodule-header=system %{fpreprocessed:-fdirectives-only}}"
" %(cc1_options) %2"
- " %{!fsyntax-only:%{!S:-o %g.s}"
- " %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}"
- " %W{o*:--output-pch=%*}}%V}}}}",
+ " %{!S:-o %g.s%V}"
+ " %{!fsyntax-only:%{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
+ " %{!o*:--output-pch=%i.gch}%W{o*:--output-pch=%*}}}}}}}}",
+ CPLUSPLUS_CPP_SPEC, 0, 0},
+ {"@c++-user-header",
+ "%{E|M|MM:cc1plus -E"
+ " %{fmodules-ts:-fdirectives-only -fmodule-header=user}"
+ " %(cpp_options) %2 %(cpp_debug_options)}"
+ "%{!E:%{!M:%{!MM:"
+ " %{save-temps*|no-integrated-cpp:cc1plus -E"
+ " %{fmodules-ts:-fdirectives-only -fmodule-header=user}"
+ " %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}"
+ " cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
+ " %{fmodules-ts:-fdirectives-only}"
+ " %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
+ " %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+ " %{fmodules-ts:-fmodule-header=user %{fpreprocessed:-fdirectives-only}}"
+ " %(cc1_options) %2"
+ " %{!S:-o %g.s%V}"
+ " %{!fsyntax-only:%{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
+ " %{!o*:--output-pch=%i.gch}%W{o*:--output-pch=%*}}}}}}}}",
CPLUSPLUS_CPP_SPEC, 0, 0},
{"@c++",
"%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}"
@@ -60,11 +100,14 @@ along with GCC; see the file COPYING3. If not see
" cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
" %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
" %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
- " %(cc1_options) %2"
- " %{!fsyntax-only:%(invoke_as)}}}}",
+ " %(cc1_options) %2"
+ " %{fmodule-only:%{!S:-o %g.s%V}}"
+ " %{!fsyntax-only:%{!fmodule-only:%(invoke_as)}}}}}",
CPLUSPLUS_CPP_SPEC, 0, 0},
{".ii", "@c++-cpp-output", 0, 0, 0},
{"@c++-cpp-output",
"%{!E:%{!M:%{!MM:"
" cc1plus -fpreprocessed %i %(cc1_options) %2"
- " %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+ " %{fmodule-only:%{!S:-o %g.s%V}}"
+ " %{!fsyntax-only:%{!fmodule-only:%{!fmodule-header*:"
+ " %(invoke_as)}}}}}}", 0, 0, 0},
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 8a69bc4..339ed47 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "gcc-rich-location.h"
#include "cp-name-hint.h"
+#include "langhooks.h"
static int interface_strcmp (const char *);
static void init_cp_pragma (void);
@@ -235,6 +236,8 @@ init_reswords (void)
mask |= D_CXX_CONCEPTS;
if (!flag_coroutines)
mask |= D_CXX_COROUTINES;
+ if (!flag_modules)
+ mask |= D_CXX_MODULES;
if (!flag_tm)
mask |= D_TRANSMEM;
if (!flag_char8_t)
@@ -378,7 +381,206 @@ interface_strcmp (const char* s)
return 1;
}
-
+/* We've just read a cpp-token, figure out our next state. Hey, this
+ is a hand-coded co-routine! */
+
+struct module_token_filter
+{
+ enum state
+ {
+ idle,
+ module_first,
+ module_cont,
+ module_end,
+ };
+
+ enum state state : 8;
+ bool is_import : 1;
+ bool got_export : 1;
+ bool got_colon : 1;
+ bool want_dot : 1;
+
+ location_t token_loc;
+ cpp_reader *reader;
+ module_state *module;
+ module_state *import;
+
+ module_token_filter (cpp_reader *reader)
+ : state (idle), is_import (false),
+ got_export (false), got_colon (false), want_dot (false),
+ token_loc (UNKNOWN_LOCATION),
+ reader (reader), module (NULL), import (NULL)
+ {
+ };
+
+ /* Process the next token. Note we cannot see CPP_EOF inside a
+ pragma -- a CPP_PRAGMA_EOL always happens. */
+ uintptr_t resume (int type, int keyword, tree value, location_t loc)
+ {
+ unsigned res = 0;
+
+ switch (state)
+ {
+ case idle:
+ if (type == CPP_KEYWORD)
+ switch (keyword)
+ {
+ default:
+ break;
+
+ case RID__EXPORT:
+ got_export = true;
+ res = lang_hooks::PT_begin_pragma;
+ break;
+
+ case RID__IMPORT:
+ is_import = true;
+ /* FALLTHRU */
+ case RID__MODULE:
+ state = module_first;
+ want_dot = false;
+ got_colon = false;
+ token_loc = loc;
+ import = NULL;
+ if (!got_export)
+ res = lang_hooks::PT_begin_pragma;
+ break;
+ }
+ break;
+
+ case module_first:
+ if (is_import && type == CPP_HEADER_NAME)
+ {
+ /* A header name. The preprocessor will have already
+ done include searching and canonicalization. */
+ state = module_end;
+ goto header_unit;
+ }
+
+ if (type == CPP_PADDING || type == CPP_COMMENT)
+ break;
+
+ state = module_cont;
+ if (type == CPP_COLON && module)
+ {
+ got_colon = true;
+ import = module;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case module_cont:
+ switch (type)
+ {
+ case CPP_PADDING:
+ case CPP_COMMENT:
+ break;
+
+ default:
+ /* If we ever need to pay attention to attributes for
+ header modules, more logic will be needed. */
+ state = module_end;
+ break;
+
+ case CPP_COLON:
+ if (got_colon)
+ state = module_end;
+ got_colon = true;
+ /* FALLTHROUGH */
+ case CPP_DOT:
+ if (!want_dot)
+ state = module_end;
+ want_dot = false;
+ break;
+
+ case CPP_PRAGMA_EOL:
+ goto module_end;
+
+ case CPP_NAME:
+ if (want_dot)
+ {
+ /* Got name instead of [.:]. */
+ state = module_end;
+ break;
+ }
+ header_unit:
+ import = get_module (value, import, got_colon);
+ want_dot = true;
+ break;
+ }
+ break;
+
+ case module_end:
+ if (type == CPP_PRAGMA_EOL)
+ {
+ module_end:;
+ /* End of the directive, handle the name. */
+ if (import)
+ if (module_state *m
+ = preprocess_module (import, token_loc, module != NULL,
+ is_import, got_export, reader))
+ if (!module)
+ module = m;
+
+ is_import = got_export = false;
+ state = idle;
+ }
+ break;
+ }
+
+ return res;
+ }
+};
+
+/* Initialize or teardown. */
+
+uintptr_t
+module_token_cdtor (cpp_reader *pfile, uintptr_t data_)
+{
+ if (module_token_filter *filter = reinterpret_cast<module_token_filter *> (data_))
+ {
+ preprocessed_module (pfile);
+ delete filter;
+ data_ = 0;
+ }
+ else if (modules_p ())
+ data_ = reinterpret_cast<uintptr_t > (new module_token_filter (pfile));
+
+ return data_;
+}
+
+uintptr_t
+module_token_lang (int type, int keyword, tree value, location_t loc,
+ uintptr_t data_)
+{
+ module_token_filter *filter = reinterpret_cast<module_token_filter *> (data_);
+ return filter->resume (type, keyword, value, loc);
+}
+
+uintptr_t
+module_token_pre (cpp_reader *pfile, const cpp_token *tok, uintptr_t data_)
+{
+ if (!tok)
+ return module_token_cdtor (pfile, data_);
+
+ int type = tok->type;
+ int keyword = RID_MAX;
+ tree value = NULL_TREE;
+
+ if (tok->type == CPP_NAME)
+ {
+ value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node.node));
+ if (IDENTIFIER_KEYWORD_P (value))
+ {
+ keyword = C_RID_CODE (value);
+ type = CPP_KEYWORD;
+ }
+ }
+ else if (tok->type == CPP_HEADER_NAME)
+ value = build_string (tok->val.str.len, (const char *)tok->val.str.text);
+
+ return module_token_lang (type, keyword, value, tok->src_loc, data_);
+}
/* Parse a #pragma whose sole argument is a string constant.
If OPT is true, the argument is optional. */
@@ -678,7 +880,7 @@ build_lang_decl_loc (location_t loc, enum tree_code code, tree name, tree type)
/* Maybe add a raw lang_decl to T, a decl. Return true if it needed
one. */
-static bool
+bool
maybe_add_lang_decl_raw (tree t, bool decomp_p)
{
size_t size;
@@ -804,6 +1006,12 @@ cxx_dup_lang_specific_decl (tree node)
memcpy (ld, DECL_LANG_SPECIFIC (node), size);
DECL_LANG_SPECIFIC (node) = ld;
+ /* Directly clear some flags that do not apply to the copy
+ (module_purview_p still does). */
+ ld->u.base.module_entity_p = false;
+ ld->u.base.module_import_p = false;
+ ld->u.base.module_pending_p = false;
+
if (GATHER_STATISTICS)
{
tree_node_counts[(int)lang_decl] += 1;
@@ -831,8 +1039,7 @@ copy_lang_type (tree node)
if (! TYPE_LANG_SPECIFIC (node))
return;
- struct lang_type *lt
- = (struct lang_type *) ggc_internal_alloc (sizeof (struct lang_type));
+ auto *lt = (struct lang_type *) ggc_internal_alloc (sizeof (struct lang_type));
memcpy (lt, TYPE_LANG_SPECIFIC (node), (sizeof (struct lang_type)));
TYPE_LANG_SPECIFIC (node) = lt;
@@ -858,15 +1065,15 @@ copy_type (tree type MEM_STAT_DECL)
/* Add a raw lang_type to T, a type, should it need one. */
-static bool
+bool
maybe_add_lang_type_raw (tree t)
{
if (!RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
return false;
- TYPE_LANG_SPECIFIC (t)
- = (struct lang_type *) (ggc_internal_cleared_alloc
- (sizeof (struct lang_type)));
+ auto *lt = (struct lang_type *) (ggc_internal_cleared_alloc
+ (sizeof (struct lang_type)));
+ TYPE_LANG_SPECIFIC (t) = lt;
if (GATHER_STATISTICS)
{
diff --git a/gcc/cp/logic.cc b/gcc/cp/logic.cc
index 194b743..5592680 100644
--- a/gcc/cp/logic.cc
+++ b/gcc/cp/logic.cc
@@ -47,21 +47,6 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h"
#include "type-utils.h"
-/* Hash functions for atomic constrains. */
-
-struct constraint_hash : default_hash_traits<tree>
-{
- static hashval_t hash (tree t)
- {
- return hash_atomic_constraint (t);
- }
-
- static bool equal (tree t1, tree t2)
- {
- return atomic_constraints_identical_p (t1, t2);
- }
-};
-
/* A conjunctive or disjunctive clause.
Each clause maintains an iterator that refers to the current
@@ -219,7 +204,7 @@ struct clause
}
std::list<tree> m_terms; /* The list of terms. */
- hash_set<tree, false, constraint_hash> m_set; /* The set of atomic constraints. */
+ hash_set<tree, false, atom_hasher> m_set; /* The set of atomic constraints. */
iterator m_current; /* The current term. */
};
@@ -318,9 +303,10 @@ debug (formula& f)
{
for (formula::iterator i = f.begin(); i != f.end(); ++i)
{
- verbatim ("(((");
+ /* Format punctuators via %s to avoid -Wformat-diag. */
+ verbatim ("%s", "(((");
debug (*i);
- verbatim (")))");
+ verbatim ("%s", ")))");
}
}
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 9fd3001..7c32e22 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -117,6 +117,9 @@ struct GTY(()) globals {
/* True if the mangling will be different in C++17 mode. */
bool need_cxx17_warning;
+
+ /* True if we mangled a module name. */
+ bool mod;
};
static GTY (()) globals G;
@@ -832,6 +835,62 @@ write_encoding (const tree decl)
}
}
+/* Interface to substitution and identifer mangling, used by the
+ module name mangler. */
+
+void
+mangle_module_substitution (int v)
+{
+ if (v < 10)
+ {
+ write_char ('_');
+ write_char ('0' + v);
+ }
+ else
+ {
+ write_char ('W');
+ write_unsigned_number (v - 10);
+ write_char ('_');
+ }
+}
+
+void
+mangle_identifier (char c, tree id)
+{
+ if (c)
+ write_char (c);
+ write_source_name (id);
+}
+
+/* If the outermost non-namespace context (including DECL itself) is
+ a module-linkage decl, mangle the module information. For module
+ global initializers we need to include the partition part.
+
+ <module-name> ::= W <module-id>+ E
+ <module-id> :: <unqualified-name>
+ || _ <digit> ;; short backref
+ || W <number> _ ;; long backref
+ || P <module-id> ;; partition introducer
+*/
+
+static void
+write_module (int m, bool include_partition)
+{
+ G.mod = true;
+
+ write_char ('W');
+ mangle_module (m, include_partition);
+ write_char ('E');
+}
+
+static void
+maybe_write_module (tree decl)
+{
+ int m = get_originating_module (decl, true);
+ if (m >= 0)
+ write_module (m, false);
+}
+
/* Lambdas can have a bit more context for mangling, specifically VAR_DECL
or PARM_DECL context, which doesn't belong in DECL_CONTEXT. */
@@ -894,6 +953,9 @@ write_name (tree decl, const int ignore_local_scope)
decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
}
+ if (modules_p ())
+ maybe_write_module (decl);
+
context = decl_mangling_context (decl);
gcc_assert (context != NULL_TREE);
@@ -2815,7 +2877,10 @@ write_member_name (tree member)
write_unqualified_id (member);
}
else if (DECL_P (member))
- write_unqualified_name (member);
+ {
+ gcc_assert (!DECL_OVERLOADED_OPERATOR_P (member));
+ write_unqualified_name (member);
+ }
else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
{
tree name = TREE_OPERAND (member, 0);
@@ -3049,11 +3114,30 @@ write_expression (tree expr)
else
goto normal_expr;
}
- else if (TREE_CODE (expr) == ALIGNOF_EXPR
- && TYPE_P (TREE_OPERAND (expr, 0)))
+ else if (TREE_CODE (expr) == ALIGNOF_EXPR)
{
- write_string ("at");
- write_type (TREE_OPERAND (expr, 0));
+ if (!ALIGNOF_EXPR_STD_P (expr))
+ {
+ if (abi_warn_or_compat_version_crosses (15))
+ G.need_abi_warning = true;
+ if (abi_version_at_least (15))
+ {
+ /* We used to mangle __alignof__ like alignof. */
+ write_string ("v111__alignof__");
+ if (TYPE_P (TREE_OPERAND (expr, 0)))
+ write_type (TREE_OPERAND (expr, 0));
+ else
+ write_expression (TREE_OPERAND (expr, 0));
+ return;
+ }
+ }
+ if (TYPE_P (TREE_OPERAND (expr, 0)))
+ {
+ write_string ("at");
+ write_type (TREE_OPERAND (expr, 0));
+ }
+ else
+ goto normal_expr;
}
else if (code == SCOPE_REF
|| code == BASELINK)
@@ -3081,6 +3165,7 @@ write_expression (tree expr)
write_expression (member);
else
{
+ gcc_assert (code != BASELINK || BASELINK_QUALIFIED_P (expr));
write_string ("sr");
write_type (scope);
write_member_name (member);
@@ -3263,7 +3348,9 @@ write_expression (tree expr)
}
else if (dependent_name (expr))
{
- write_unqualified_id (dependent_name (expr));
+ tree name = dependent_name (expr);
+ gcc_assert (!IDENTIFIER_ANY_OP_P (name));
+ write_unqualified_id (name);
}
else
{
@@ -3806,14 +3893,13 @@ start_mangling (const tree entity)
G.entity = entity;
G.need_abi_warning = false;
G.need_cxx17_warning = false;
+ G.mod = false;
obstack_free (&name_obstack, name_base);
mangle_obstack = &name_obstack;
name_base = obstack_alloc (&name_obstack, 0);
}
-/* Done with mangling. If WARN is true, and the name of G.entity will
- be mangled differently in a future version of the ABI, issue a
- warning. */
+/* Done with mangling. Release the data. */
static void
finish_mangling_internal (void)
@@ -3821,6 +3907,9 @@ finish_mangling_internal (void)
/* Clear all the substitutions. */
vec_safe_truncate (G.substitutions, 0);
+ if (G.mod)
+ mangle_module_fini ();
+
/* Null-terminate the string. */
write_char ('\0');
}
@@ -3865,6 +3954,20 @@ init_mangle (void)
subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream");
}
+/* Generate a mangling for MODULE's global initializer fn. */
+
+tree
+mangle_module_global_init (int module)
+{
+ start_mangling (NULL_TREE);
+
+ write_string ("_ZGI");
+ write_module (module, true);
+ write_char ('v');
+
+ return finish_mangling_get_identifier ();
+}
+
/* Generate the mangled name of DECL. */
static tree
diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc
new file mode 100644
index 0000000..df821ba
--- /dev/null
+++ b/gcc/cp/mapper-client.cc
@@ -0,0 +1,373 @@
+/* C++ modules. Experimental!
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+ 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"
+#if defined (__unix__)
+// Solaris11's socket header used bcopy, which we poison. cody.hh
+// will include it later under the above check
+#include <sys/socket.h>
+#endif
+#define INCLUDE_STRING
+#define INCLUDE_VECTOR
+#include "system.h"
+
+#include "line-map.h"
+#include "diagnostic-core.h"
+#include "mapper-client.h"
+#include "intl.h"
+
+#include "../../c++tools/resolver.h"
+
+#if !HOST_HAS_O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+module_client::module_client (pex_obj *p, int fd_from, int fd_to)
+ : Client (fd_from, fd_to), pex (p)
+{
+}
+
+static module_client *
+spawn_mapper_program (char const **errmsg, std::string &name,
+ char const *full_program_name)
+{
+ /* Split writable at white-space. No space-containing args for
+ you! */
+ // At most every other char could be an argument
+ char **argv = new char *[name.size () / 2 + 2];
+ unsigned arg_no = 0;
+ char *str = new char[name.size ()];
+ memcpy (str, name.c_str () + 1, name.size ());
+
+ for (auto ptr = str; ; ++ptr)
+ {
+ while (*ptr == ' ')
+ ptr++;
+ if (!*ptr)
+ break;
+
+ if (!arg_no)
+ {
+ /* @name means look in the compiler's install dir. */
+ if (ptr[0] == '@')
+ ptr++;
+ else
+ full_program_name = nullptr;
+ }
+
+ argv[arg_no++] = ptr;
+ while (*ptr && *ptr != ' ')
+ ptr++;
+ if (!*ptr)
+ break;
+ *ptr = 0;
+ }
+ argv[arg_no] = nullptr;
+
+ auto *pex = pex_init (PEX_USE_PIPES, progname, NULL);
+ FILE *to = pex_input_pipe (pex, false);
+ name = argv[0];
+ if (!to)
+ *errmsg = "connecting input";
+ else
+ {
+ int flags = PEX_SEARCH;
+
+ if (full_program_name)
+ {
+ /* Prepend the invoking path, if the mapper is a simple
+ file name. */
+ size_t dir_len = progname - full_program_name;
+ std::string argv0;
+ argv0.reserve (dir_len + name.size ());
+ argv0.append (full_program_name, dir_len).append (name);
+ name = std::move (argv0);
+ argv[0] = const_cast <char *> (name.c_str ());
+ flags = 0;
+ }
+ int err;
+ *errmsg = pex_run (pex, flags, argv[0], argv, NULL, NULL, &err);
+ }
+ delete[] str;
+ delete[] argv;
+
+ int fd_from = -1, fd_to = -1;
+ if (!*errmsg)
+ {
+ FILE *from = pex_read_output (pex, false);
+ if (from && (fd_to = dup (fileno (to))) >= 0)
+ fd_from = fileno (from);
+ else
+ *errmsg = "connecting output";
+ fclose (to);
+ }
+
+ if (*errmsg)
+ {
+ pex_free (pex);
+ return nullptr;
+ }
+
+ return new module_client (pex, fd_from, fd_to);
+}
+
+module_client *
+module_client::open_module_client (location_t loc, const char *o,
+ void (*set_repo) (const char *),
+ char const *full_program_name)
+{
+ module_client *c = nullptr;
+ std::string ident;
+ std::string name;
+ char const *errmsg = nullptr;
+ unsigned line = 0;
+
+ if (o && o[0])
+ {
+ /* Maybe a local or ipv6 address. */
+ name = o;
+ auto last = name.find_last_of ('?');
+ if (last != name.npos)
+ {
+ ident = name.substr (last + 1);
+ name.erase (last);
+ }
+
+ if (name.size ())
+ {
+ switch (name[0])
+ {
+ case '<':
+ // <from>to or <>fromto, or <>
+ {
+ size_t pos = name.find ('>', 1);
+ if (pos == std::string::npos)
+ pos = name.size ();
+ std::string from (name, 1, pos - 1);
+ std::string to;
+ if (pos != name.size ())
+ to.append (name, pos + 1, std::string::npos);
+
+ int fd_from = -1, fd_to = -1;
+ if (from.empty () && to.empty ())
+ {
+ fd_from = fileno (stdin);
+ fd_to = fileno (stdout);
+ }
+ else
+ {
+ char *ptr;
+ if (!from.empty ())
+ {
+ /* Sadly str::stoul is not portable. */
+ const char *cstr = from.c_str ();
+ fd_from = strtoul (cstr, &ptr, 10);
+ if (*ptr)
+ {
+ /* Not a number -- a named pipe. */
+ int dir = to.empty ()
+ ? O_RDWR | O_CLOEXEC : O_RDONLY | O_CLOEXEC;
+ fd_from = open (cstr, dir);
+ }
+ if (to.empty ())
+ fd_to = fd_from;
+ }
+
+ if (!from.empty () && fd_from < 0)
+ ;
+ else if (to.empty ())
+ ;
+ else
+ {
+ const char *cstr = to.c_str ();
+ fd_to = strtoul (cstr, &ptr, 10);
+ if (*ptr)
+ {
+ /* Not a number, a named pipe. */
+ int dir = from.empty ()
+ ? O_RDWR | O_CLOEXEC : O_WRONLY | O_CLOEXEC;
+ fd_to = open (cstr, dir);
+ if (fd_to < 0)
+ close (fd_from);
+ }
+ if (from.empty ())
+ fd_from = fd_to;
+ }
+ }
+
+ if (fd_from < 0 || fd_to < 0)
+ errmsg = "opening";
+ else
+ c = new module_client (fd_from, fd_to);
+ }
+ break;
+
+ case '=':
+ // =localsocket
+ {
+ int fd = -1;
+#if CODY_NETWORKING
+ fd = Cody::OpenLocal (&errmsg, name.c_str () + 1);
+#endif
+ if (fd >= 0)
+ c = new module_client (fd, fd);
+ }
+ break;
+
+ case '|':
+ // |program and args
+ c = spawn_mapper_program (&errmsg, name, full_program_name);
+ break;
+
+ default:
+ // file or hostname:port
+ {
+ auto colon = name.find_last_of (':');
+ if (colon != name.npos)
+ {
+ char const *cptr = name.c_str () + colon;
+ char *endp;
+ unsigned port = strtoul (cptr + 1, &endp, 10);
+
+ if (port && endp != cptr + 1 && !*endp)
+ {
+ name[colon] = 0;
+ int fd = 01;
+#if CODY_NETWORKING
+ fd = Cody::OpenInet6 (&errmsg, name.c_str (), port);
+#endif
+ name[colon] = ':';
+
+ if (fd >= 0)
+ c = new module_client (fd, fd);
+ }
+ }
+
+ }
+ break;
+ }
+ }
+ }
+
+ if (!c)
+ {
+ // Make a default in-process client
+ bool file = !errmsg && !name.empty ();
+ auto r = new module_resolver (!file, true);
+
+ if (file)
+ {
+ int fd = open (name.c_str (), O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ errmsg = "opening";
+ else
+ {
+ if (int l = r->read_tuple_file (fd, ident, false))
+ {
+ if (l > 0)
+ line = l;
+ errmsg = "reading";
+ }
+
+ close (fd);
+ }
+ }
+ else
+ r->set_repo ("gcm.cache");
+
+ auto *s = new Cody::Server (r);
+ c = new module_client (s);
+ }
+
+#ifdef SIGPIPE
+ if (!c->IsDirect ())
+ /* We need to ignore sig pipe for a while. */
+ c->sigpipe = signal (SIGPIPE, SIG_IGN);
+#endif
+
+ if (errmsg)
+ error_at (loc, line ? G_("failed %s mapper %qs line %u")
+ : G_("failed %s mapper %qs"), errmsg, name.c_str (), line);
+
+ // now wave hello!
+ c->Cork ();
+ c->Connect (std::string ("GCC"), ident);
+ c->ModuleRepo ();
+ auto packets = c->Uncork ();
+
+ auto &connect = packets[0];
+ if (connect.GetCode () == Cody::Client::PC_CONNECT)
+ c->flags = Cody::Flags (connect.GetInteger ());
+ else if (connect.GetCode () == Cody::Client::PC_ERROR)
+ error_at (loc, "failed mapper handshake %s", connect.GetString ().c_str ());
+
+ auto &repo = packets[1];
+ if (repo.GetCode () == Cody::Client::PC_PATHNAME)
+ set_repo (repo.GetString ().c_str ());
+
+ return c;
+}
+
+void
+module_client::close_module_client (location_t loc, module_client *mapper)
+{
+ if (mapper->IsDirect ())
+ {
+ auto *s = mapper->GetServer ();
+ auto *r = s->GetResolver ();
+ delete s;
+ delete r;
+ }
+ else
+ {
+ if (mapper->pex)
+ {
+ int fd_write = mapper->GetFDWrite ();
+ if (fd_write >= 0)
+ close (fd_write);
+
+ int status;
+ pex_get_status (mapper->pex, 1, &status);
+
+ pex_free (mapper->pex);
+ mapper->pex = NULL;
+
+ if (WIFSIGNALED (status))
+ error_at (loc, "mapper died by signal %s",
+ strsignal (WTERMSIG (status)));
+ else if (WIFEXITED (status) && WEXITSTATUS (status) != 0)
+ error_at (loc, "mapper exit status %d",
+ WEXITSTATUS (status));
+ }
+ else
+ {
+ int fd_read = mapper->GetFDRead ();
+ close (fd_read);
+ }
+
+#ifdef SIGPIPE
+ // Restore sigpipe
+ if (mapper->sigpipe != SIG_IGN)
+ signal (SIGPIPE, mapper->sigpipe);
+#endif
+ }
+
+ delete mapper;
+}
diff --git a/gcc/cp/mapper-client.h b/gcc/cp/mapper-client.h
new file mode 100644
index 0000000..ca1a0aa
--- /dev/null
+++ b/gcc/cp/mapper-client.h
@@ -0,0 +1,63 @@
+/* C++ modules. Experimental! -*- c++ -*-
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+ 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/>. */
+
+/* Forward to the header in c++tools. */
+
+#ifndef MAPPER_CLIENT_H
+#define MAPPER_CLIENT_H 1
+
+#include "cody.hh"
+
+#ifndef HAVE_SIGHANDLER_T
+typedef void (*sighandler_t) (int);
+#endif
+
+class module_client : public Cody::Client
+{
+ pex_obj *pex = nullptr;
+ sighandler_t sigpipe = SIG_IGN;
+ Cody::Flags flags = Cody::Flags::None;
+
+public:
+ module_client (Cody::Server *s)
+ : Client (s)
+ {
+ }
+ module_client (pex_obj *pex, int fd_from, int fd_to);
+
+ module_client (int fd_from, int fd_to)
+ : Client (fd_from, fd_to)
+ {
+ }
+
+public:
+ Cody::Flags get_flags () const
+ {
+ return flags;
+ }
+
+public:
+ static module_client *open_module_client (location_t loc, const char *option,
+ void (*set_repo) (const char *),
+ char const *);
+ static void close_module_client (location_t loc, module_client *);
+};
+
+#endif
diff --git a/gcc/cp/mapper-resolver.cc b/gcc/cp/mapper-resolver.cc
new file mode 100644
index 0000000..e348757
--- /dev/null
+++ b/gcc/cp/mapper-resolver.cc
@@ -0,0 +1,31 @@
+/* C++ modules. Experimental! -*- c++ -*-
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+ 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/>. */
+
+/* Forward to the resolver in c++tools. */
+
+#include "config.h"
+#define INCLUDE_STRING
+#define INCLUDE_VECTOR
+#define INCLUDE_ALGORITHM
+#include "system.h"
+
+// We don't want or need to be aware of networking
+#define CODY_NETWORKING 0
+#include "../../c++tools/resolver.cc"
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 6e4c5f7..dd35173 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -351,7 +351,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
/* Output the thunk into the same section as function. */
- set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (fn));
+ set_decl_section_name (thunk_fndecl, fn);
symtab_node::get (thunk_fndecl)->implicit_section
= symtab_node::get (fn)->implicit_section;
}
@@ -1063,43 +1063,60 @@ spaceship_type (tree optype, tsubst_flags_t complain)
return lookup_comparison_category (tag, complain);
}
-/* Turn <=> with type TYPE and operands OP0 and OP1 into GENERIC. */
+/* Turn <=> with type TYPE and operands OP0 and OP1 into GENERIC.
+ This is also used by build_comparison_op for fallback to op< and op==
+ in a defaulted op<=>. */
tree
-genericize_spaceship (tree type, tree op0, tree op1)
+genericize_spaceship (location_t loc, tree type, tree op0, tree op1)
{
/* ??? maybe optimize based on knowledge of representation? */
comp_cat_tag tag = cat_tag_for (type);
+
+ if (tag == cc_last && is_auto (type))
+ {
+ /* build_comparison_op is checking to see if we want to suggest changing
+ the op<=> return type from auto to a specific comparison category; any
+ category will do for now. */
+ tag = cc_strong_ordering;
+ type = lookup_comparison_category (tag, tf_none);
+ if (type == error_mark_node)
+ return error_mark_node;
+ }
+
gcc_checking_assert (tag < cc_last);
tree r;
- op0 = save_expr (op0);
- op1 = save_expr (op1);
+ if (SCALAR_TYPE_P (TREE_TYPE (op0)))
+ {
+ op0 = save_expr (op0);
+ op1 = save_expr (op1);
+ }
tree gt = lookup_comparison_result (tag, type, 1);
+ int flags = LOOKUP_NORMAL;
+ tsubst_flags_t complain = tf_none;
+
if (tag == cc_partial_ordering)
{
/* op0 == op1 ? equivalent : op0 < op1 ? less :
- op0 > op1 ? greater : unordered */
+ op1 < op0 ? greater : unordered */
tree uo = lookup_comparison_result (tag, type, 3);
- tree comp = fold_build2 (GT_EXPR, boolean_type_node, op0, op1);
- r = fold_build3 (COND_EXPR, type, comp, gt, uo);
+ tree comp = build_new_op (loc, LT_EXPR, flags, op1, op0, complain);
+ r = build_conditional_expr (loc, comp, gt, uo, complain);
}
else
/* op0 == op1 ? equal : op0 < op1 ? less : greater */
r = gt;
tree lt = lookup_comparison_result (tag, type, 2);
- tree comp = fold_build2 (LT_EXPR, boolean_type_node, op0, op1);
- r = fold_build3 (COND_EXPR, type, comp, lt, r);
+ tree comp = build_new_op (loc, LT_EXPR, flags, op0, op1, complain);
+ r = build_conditional_expr (loc, comp, lt, r, complain);
tree eq = lookup_comparison_result (tag, type, 0);
- comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1);
- r = fold_build3 (COND_EXPR, type, comp, eq, r);
-
- /* Wrap the whole thing in a TARGET_EXPR like build_conditional_expr_1. */
- r = get_target_expr (r);
+ comp = build_new_op (loc, EQ_EXPR, flags, op0, op1, complain);
+ r = build_conditional_expr (loc, comp, eq, r, complain);
return r;
}
@@ -1213,6 +1230,8 @@ common_comparison_type (vec<tree> &comps)
for (unsigned i = 0; i < comps.length(); ++i)
{
tree comp = comps[i];
+ if (TREE_CODE (comp) == TREE_LIST)
+ comp = TREE_VALUE (comp);
tree ctype = TREE_TYPE (comp);
comp_cat_tag tag = cat_tag_for (ctype);
/* build_comparison_op already checked this. */
@@ -1323,7 +1342,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
if (!info.defining && !(complain & tf_error) && !DECL_MAYBE_DELETED (fndecl))
return;
- int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED;
+ int flags = LOOKUP_NORMAL;
const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (DECL_NAME (fndecl));
tree_code code = op->tree_code;
@@ -1364,6 +1383,10 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
if (code == EQ_EXPR || code == SPACESHIP_EXPR)
{
+ comp_cat_tag retcat = cc_last;
+ if (code == SPACESHIP_EXPR && !FNDECL_USED_AUTO (fndecl))
+ retcat = cat_tag_for (rettype);
+
bool bad = false;
auto_vec<tree> comps;
@@ -1375,13 +1398,15 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
{
tree expr_type = TREE_TYPE (field);
+ location_t field_loc = DECL_SOURCE_LOCATION (field);
+
/* A defaulted comparison operator function for class C is defined as
deleted if any non-static data member of C is of reference type or
C has variant members. */
if (TREE_CODE (expr_type) == REFERENCE_TYPE)
{
if (complain & tf_error)
- inform (DECL_SOURCE_LOCATION (field), "cannot default compare "
+ inform (field_loc, "cannot default compare "
"reference member %qD", field);
bad = true;
continue;
@@ -1390,35 +1415,128 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
&& next_initializable_field (TYPE_FIELDS (expr_type)))
{
if (complain & tf_error)
- inform (DECL_SOURCE_LOCATION (field), "cannot default compare "
+ inform (field_loc, "cannot default compare "
"anonymous union member");
bad = true;
continue;
}
- tree lhs_mem = build3 (COMPONENT_REF, expr_type, lhs, field,
- NULL_TREE);
- tree rhs_mem = build3 (COMPONENT_REF, expr_type, rhs, field,
- NULL_TREE);
- tree comp = build_new_op (info.loc, code, flags, lhs_mem, rhs_mem,
- NULL_TREE, NULL, complain);
+ tree lhs_mem = build3_loc (field_loc, COMPONENT_REF, expr_type, lhs,
+ field, NULL_TREE);
+ tree rhs_mem = build3_loc (field_loc, COMPONENT_REF, expr_type, rhs,
+ field, NULL_TREE);
+ tree loop_indexes = NULL_TREE;
+ while (TREE_CODE (expr_type) == ARRAY_TYPE)
+ {
+ /* Flexible array member. */
+ if (TYPE_DOMAIN (expr_type) == NULL_TREE
+ || TYPE_MAX_VALUE (TYPE_DOMAIN (expr_type)) == NULL_TREE)
+ {
+ if (complain & tf_error)
+ inform (field_loc, "cannot default compare "
+ "flexible array member");
+ bad = true;
+ break;
+ }
+ tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (expr_type));
+ /* [0] array. No subobjects to compare, just skip it. */
+ if (integer_all_onesp (maxval))
+ break;
+ tree idx;
+ /* [1] array, no loop needed, just add [0] ARRAY_REF.
+ Similarly if !info.defining. */
+ if (integer_zerop (maxval) || !info.defining)
+ idx = size_zero_node;
+ /* Some other array, will need runtime loop. */
+ else
+ {
+ idx = force_target_expr (sizetype, maxval, complain);
+ loop_indexes = tree_cons (idx, NULL_TREE, loop_indexes);
+ }
+ expr_type = TREE_TYPE (expr_type);
+ lhs_mem = build4_loc (field_loc, ARRAY_REF, expr_type, lhs_mem,
+ idx, NULL_TREE, NULL_TREE);
+ rhs_mem = build4_loc (field_loc, ARRAY_REF, expr_type, rhs_mem,
+ idx, NULL_TREE, NULL_TREE);
+ }
+ if (TREE_CODE (expr_type) == ARRAY_TYPE)
+ continue;
+
+ tree overload = NULL_TREE;
+ tree comp = build_new_op (field_loc, code, flags, lhs_mem, rhs_mem,
+ NULL_TREE, &overload,
+ retcat != cc_last ? tf_none : complain);
if (comp == error_mark_node)
{
- bad = true;
- continue;
+ if (overload == NULL_TREE && code == SPACESHIP_EXPR
+ && (retcat != cc_last || complain))
+ {
+ tree comptype = (retcat != cc_last ? rettype
+ : DECL_SAVED_AUTO_RETURN_TYPE (fndecl));
+ /* No viable <=>, try using op< and op==. */
+ tree lteq = genericize_spaceship (field_loc, comptype,
+ lhs_mem, rhs_mem);
+ if (lteq != error_mark_node)
+ {
+ /* We found usable < and ==. */
+ if (retcat != cc_last)
+ /* Return type is a comparison category, use them. */
+ comp = lteq;
+ else if (complain & tf_error)
+ /* Return type is auto, suggest changing it. */
+ inform (info.loc, "changing the return type from %qs "
+ "to a comparison category type will allow the "
+ "comparison to use %qs and %qs", "auto",
+ "operator<", "operator==");
+ }
+ else if (retcat != cc_last && complain != tf_none)
+ /* No usable < and ==, give an error for op<=>. */
+ build_new_op (field_loc, code, flags, lhs_mem, rhs_mem,
+ complain);
+ }
+ if (comp == error_mark_node)
+ {
+ bad = true;
+ continue;
+ }
}
- if (code == SPACESHIP_EXPR
- && cat_tag_for (TREE_TYPE (comp)) == cc_last)
+ if (code != SPACESHIP_EXPR)
+ ;
+ else if (FNDECL_USED_AUTO (fndecl)
+ && cat_tag_for (TREE_TYPE (comp)) == cc_last)
{
/* The operator function is defined as deleted if ... Ri is not a
comparison category type. */
if (complain & tf_error)
- inform (DECL_SOURCE_LOCATION (field),
+ inform (field_loc,
"three-way comparison of %qD has type %qT, not a "
"comparison category type", field, TREE_TYPE (comp));
bad = true;
continue;
}
+ else if (!FNDECL_USED_AUTO (fndecl)
+ && !can_convert (rettype, TREE_TYPE (comp), complain))
+ {
+ if (complain & tf_error)
+ error_at (field_loc,
+ "three-way comparison of %qD has type %qT, which "
+ "does not convert to %qT",
+ field, TREE_TYPE (comp), rettype);
+ bad = true;
+ continue;
+ }
+ /* Most of the time, comp is the expression that should be evaluated
+ to compare the two members. If the expression needs to be
+ evaluated more than once in a loop, it will be a TREE_LIST
+ instead, whose TREE_VALUE is the expression for one array element,
+ TREE_PURPOSE is innermost iterator temporary and if the array
+ is multidimensional, TREE_CHAIN will contain another TREE_LIST
+ with second innermost iterator in its TREE_PURPOSE and so on. */
+ if (loop_indexes)
+ {
+ TREE_VALUE (loop_indexes) = comp;
+ comp = loop_indexes;
+ }
comps.safe_push (comp);
}
if (code == SPACESHIP_EXPR && is_auto (rettype))
@@ -1435,8 +1553,38 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
{
tree comp = comps[i];
tree eq, retval = NULL_TREE, if_ = NULL_TREE;
+ tree loop_indexes = NULL_TREE;
if (info.defining)
- if_ = begin_if_stmt ();
+ {
+ if (TREE_CODE (comp) == TREE_LIST)
+ {
+ loop_indexes = comp;
+ comp = TREE_VALUE (comp);
+ loop_indexes = nreverse (loop_indexes);
+ for (tree loop_index = loop_indexes; loop_index;
+ loop_index = TREE_CHAIN (loop_index))
+ {
+ tree for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
+ tree idx = TREE_PURPOSE (loop_index);
+ tree maxval = TARGET_EXPR_INITIAL (idx);
+ TARGET_EXPR_INITIAL (idx) = size_zero_node;
+ add_stmt (idx);
+ finish_init_stmt (for_stmt);
+ finish_for_cond (build2 (LE_EXPR, boolean_type_node, idx,
+ maxval), for_stmt, false, 0);
+ finish_for_expr (cp_build_unary_op (PREINCREMENT_EXPR,
+ TARGET_EXPR_SLOT (idx),
+ false, complain),
+ for_stmt);
+ /* Store in TREE_VALUE the for_stmt tree, so that we can
+ later on call finish_for_stmt on it (in the reverse
+ order). */
+ TREE_VALUE (loop_index) = for_stmt;
+ }
+ loop_indexes = nreverse (loop_indexes);
+ }
+ if_ = begin_if_stmt ();
+ }
/* Spaceship is specified to use !=, but for the comparison category
types, != is equivalent to !(==), so let's use == directly. */
if (code == EQ_EXPR)
@@ -1475,6 +1623,9 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
finish_return_stmt (retval);
finish_else_clause (if_);
finish_if_stmt (if_);
+ for (tree loop_index = loop_indexes; loop_index;
+ loop_index = TREE_CHAIN (loop_index))
+ finish_for_stmt (TREE_VALUE (loop_index));
}
}
if (info.defining)
@@ -1924,15 +2075,26 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
bool
is_trivially_xible (enum tree_code code, tree to, tree from)
{
- tree expr;
- expr = is_xible_helper (code, to, from, /*trivial*/true);
-
+ tree expr = is_xible_helper (code, to, from, /*trivial*/true);
if (expr == NULL_TREE || expr == error_mark_node)
return false;
tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL);
return !nt;
}
+/* Returns true iff TO is nothrow assignable (if CODE is MODIFY_EXPR) or
+ constructible (otherwise) from FROM, which is a single type for
+ assignment or a list of types for construction. */
+
+bool
+is_nothrow_xible (enum tree_code code, tree to, tree from)
+{
+ tree expr = is_xible_helper (code, to, from, /*trivial*/false);
+ if (expr == NULL_TREE || expr == error_mark_node)
+ return false;
+ return expr_noexcept_p (expr, tf_none);
+}
+
/* Returns true iff TO is assignable (if CODE is MODIFY_EXPR) or
constructible (otherwise) from FROM, which is a single type for
assignment or a list of types for construction. */
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
new file mode 100644
index 0000000..19fe663
--- /dev/null
+++ b/gcc/cp/module.cc
@@ -0,0 +1,19947 @@
+/* C++ modules. Experimental!
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+ 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/>. */
+
+/* Comments in this file have a non-negligible chance of being wrong
+ or at least inaccurate. Due to (a) my misunderstanding, (b)
+ ambiguities that I have interpretted differently to original intent
+ (c) changes in the specification, (d) my poor wording, (e) source
+ changes. */
+
+/* (Incomplete) Design Notes
+
+ A hash table contains all module names. Imported modules are
+ present in a modules array, which by construction places an
+ import's dependencies before the import itself. The single
+ exception is the current TU, which always occupies slot zero (even
+ when it is not a module).
+
+ Imported decls occupy an entity_ary, an array of binding_slots, indexed
+ by importing module and index within that module. A flat index is
+ used, as each module reserves a contiguous range of indices.
+ Initially each slot indicates the CMI section containing the
+ streamed decl. When the decl is imported it will point to the decl
+ itself.
+
+ Additionally each imported decl is mapped in the entity_map via its
+ DECL_UID to the flat index in the entity_ary. Thus we can locate
+ the index for any imported decl by using this map and then
+ de-flattening the index via a binary seach of the module vector.
+ Cross-module references are by (remapped) module number and
+ module-local index.
+
+ Each importable DECL contains several flags. The simple set are
+ DECL_EXPORT_P, DECL_MODULE_PURVIEW_P and DECL_MODULE_IMPORT_P. The
+ first indicates whether it is exported, the second whether it is in
+ the module purview (as opposed to the global module fragment), and
+ the third indicates whether it was an import into this TU or not.
+
+ The more detailed flags are DECL_MODULE_PARTITION_P,
+ DECL_MODULE_ENTITY_P & DECL_MODULE_PENDING_SPECIALIZATIONS_P. The
+ first is set in a primary interface unit on decls that were read
+ from module partitions (these will have DECL_MODULE_IMPORT_P set
+ too). Such decls will be streamed out to the primary's CMI.
+ DECL_MODULE_ENTITY_P is set when an entity is imported, even if it
+ matched a non-imported entity. Such a decl will not have
+ DECL_MODULE_IMPORT_P set, even though it has an entry in the entity
+ map and array. DECL_MODULE_PENDING_SPECIALIZATIONS_P is set on a
+ primary template, and indicates there are specializations that
+ should be streamed in before trying to specialize this template.
+
+ Header units are module-like.
+
+ For namespace-scope lookup, the decls for a particular module are
+ held located in a sparse array hanging off the binding of the name.
+ This is partitioned into two: a few fixed slots at the start
+ followed by the sparse slots afterwards. By construction we only
+ need to append new slots to the end -- there is never a need to
+ insert in the middle. The fixed slots are MODULE_SLOT_CURRENT for
+ the current TU (regardless of whether it is a module or not),
+ MODULE_SLOT_GLOBAL and MODULE_SLOT_PARTITION. These latter two
+ slots are used for merging entities across the global module and
+ module partitions respectively. MODULE_SLOT_PARTITION is only
+ present in a module. Neither of those two slots is searched during
+ name lookup -- they are internal use only. This vector is created
+ lazily once we require it, if there is only a declaration from the
+ current TU, a regular binding is present. It is converted on
+ demand.
+
+ OPTIMIZATION: Outside of the current TU, we only need ADL to work.
+ We could optimize regular lookup for the current TU by glomming all
+ the visible decls on its slot. Perhaps wait until design is a
+ little more settled though.
+
+ There is only one instance of each extern-linkage namespace. It
+ appears in every module slot that makes it visible. It also
+ appears in MODULE_SLOT_GLOBAL. (It is an ODR violation if they
+ collide with some other global module entity.) We also have an
+ optimization that shares the slot for adjacent modules that declare
+ the same such namespace.
+
+ A module interface compilation produces a Compiled Module Interface
+ (CMI). The format used is Encapsulated Lazy Records Of Numbered
+ Declarations, which is essentially ELF's section encapsulation. (As
+ all good nerds are aware, Elrond is half Elf.) Some sections are
+ named, and contain information about the module as a whole (indices
+ etc), and other sections are referenced by number. Although I
+ don't defend against actively hostile CMIs, there is some
+ checksumming involved to verify data integrity. When dumping out
+ an interface, we generate a graph of all the
+ independently-redeclarable DECLS that are needed, and the decls
+ they reference. From that we determine the strongly connected
+ components (SCC) within this TU. Each SCC is dumped to a separate
+ numbered section of the CMI. We generate a binding table section,
+ mapping each namespace&name to a defining section. This allows
+ lazy loading.
+
+ Lazy loading employs mmap to map a read-only image of the CMI.
+ It thus only occupies address space and is paged in on demand,
+ backed by the CMI file itself. If mmap is unavailable, regular
+ FILEIO is used. Also, there's a bespoke ELF reader/writer here,
+ which implements just the section table and sections (including
+ string sections) of a 32-bit ELF in host byte-order. You can of
+ course inspect it with readelf. I figured 32-bit is sufficient,
+ for a single module. I detect running out of section numbers, but
+ do not implement the ELF overflow mechanism. At least you'll get
+ an error if that happens.
+
+ We do not separate declarations and definitions. My guess is that
+ if you refer to the declaration, you'll also need the definition
+ (template body, inline function, class definition etc). But this
+ does mean we can get larger SCCs than if we separated them. It is
+ unclear whether this is a win or not.
+
+ Notice that we embed section indices into the contents of other
+ sections. Thus random manipulation of the CMI file by ELF tools
+ may well break it. The kosher way would probably be to introduce
+ indirection via section symbols, but that would require defining a
+ relocation type.
+
+ Notice that lazy loading of one module's decls can cause lazy
+ loading of other decls in the same or another module. Clearly we
+ want to avoid loops. In a correct program there can be no loops in
+ the module dependency graph, and the above-mentioned SCC algorithm
+ places all intra-module circular dependencies in the same SCC. It
+ also orders the SCCs wrt each other, so dependent SCCs come first.
+ As we load dependent modules first, we know there can be no
+ reference to a higher-numbered module, and because we write out
+ dependent SCCs first, likewise for SCCs within the module. This
+ allows us to immediately detect broken references. When loading,
+ we must ensure the rest of the compiler doesn't cause some
+ unconnected load to occur (for instance, instantiate a template).
+
+Classes used:
+
+ dumper - logger
+
+ data - buffer
+
+ bytes - data streamer
+ bytes_in : bytes - scalar reader
+ bytes_out : bytes - scalar writer
+
+ elf - ELROND format
+ elf_in : elf - ELROND reader
+ elf_out : elf - ELROND writer
+
+ trees_in : bytes_in - tree reader
+ trees_out : bytes_out - tree writer
+
+ depset - dependency set
+ depset::hash - hash table of depsets
+ depset::tarjan - SCC determinator
+
+ uidset<T> - set T's related to a UID
+ uidset<T>::hash hash table of uidset<T>
+
+ loc_spans - location map data
+
+ module_state - module object
+
+ slurping - data needed during loading
+
+ macro_import - imported macro data
+ macro_export - exported macro data
+
+ The ELROND objects use mmap, for both reading and writing. If mmap
+ is unavailable, fileno IO is used to read and write blocks of data.
+
+ The mapper object uses fileno IO to communicate with the server or
+ program. */
+
+/* In expermental (trunk) sources, MODULE_VERSION is a #define passed
+ in from the Makefile. It records the modification date of the
+ source directory -- that's the only way to stay sane. In release
+ sources, we (plan to) use the compiler's major.minor versioning.
+ While the format might not change between at minor versions, it
+ seems simplest to tie the two together. There's no concept of
+ inter-version compatibility. */
+#define IS_EXPERIMENTAL(V) ((V) >= (1U << 20))
+#define MODULE_MAJOR(V) ((V) / 10000)
+#define MODULE_MINOR(V) ((V) % 10000)
+#define EXPERIMENT(A,B) (IS_EXPERIMENTAL (MODULE_VERSION) ? (A) : (B))
+#ifndef MODULE_VERSION
+// Be sure you're ready! Remove #error this before release!
+#error "Shtopp! What are you doing? This is not ready yet."
+#include "bversion.h"
+#define MODULE_VERSION (BUILDING_GCC_MAJOR * 10000U + BUILDING_GCC_MINOR)
+#elif !IS_EXPERIMENTAL (MODULE_VERSION)
+#error "This is not the version I was looking for."
+#endif
+
+#define _DEFAULT_SOURCE 1 /* To get TZ field of struct tm, if available. */
+#include "config.h"
+#define INCLUDE_STRING
+#define INCLUDE_VECTOR
+#include "system.h"
+#include "coretypes.h"
+#include "cp-tree.h"
+#include "timevar.h"
+#include "stringpool.h"
+#include "dumpfile.h"
+#include "bitmap.h"
+#include "cgraph.h"
+#include "tree-iterator.h"
+#include "cpplib.h"
+#include "mkdeps.h"
+#include "incpath.h"
+#include "libiberty.h"
+#include "stor-layout.h"
+#include "version.h"
+#include "tree-diagnostic.h"
+#include "toplev.h"
+#include "opts.h"
+#include "attribs.h"
+#include "intl.h"
+#include "langhooks.h"
+/* This TU doesn't need or want to see the networking. */
+#define CODY_NETWORKING 0
+#include "mapper-client.h"
+
+#if 0 // 1 for testing no mmap
+#define MAPPED_READING 0
+#define MAPPED_WRITING 0
+#else
+#if HAVE_MMAP_FILE && _POSIX_MAPPED_FILES > 0
+/* mmap, munmap. */
+#define MAPPED_READING 1
+#if HAVE_SYSCONF && defined (_SC_PAGE_SIZE)
+/* msync, sysconf (_SC_PAGE_SIZE), ftruncate */
+/* posix_fallocate used if available. */
+#define MAPPED_WRITING 1
+#else
+#define MAPPED_WRITING 0
+#endif
+#else
+#define MAPPED_READING 0
+#define MAPPED_WRITING 0
+#endif
+#endif
+
+/* Some open(2) flag differences, what a colourful world it is! */
+#if defined (O_CLOEXEC)
+// OK
+#elif defined (_O_NOINHERIT)
+/* Windows' _O_NOINHERIT matches O_CLOEXEC flag */
+#define O_CLOEXEC _O_NOINHERIT
+#else
+#define O_CLOEXEC 0
+#endif
+#if defined (O_BINARY)
+// Ok?
+#elif defined (_O_BINARY)
+/* Windows' open(2) call defaults to text! */
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0
+#endif
+
+static inline cpp_hashnode *cpp_node (tree id)
+{
+ return CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (id));
+}
+static inline tree identifier (cpp_hashnode *node)
+{
+ return HT_IDENT_TO_GCC_IDENT (HT_NODE (node));
+}
+static inline const_tree identifier (const cpp_hashnode *node)
+{
+ return identifier (const_cast <cpp_hashnode *> (node));
+}
+
+/* During duplicate detection we need to tell some comparators that
+ these are equivalent. */
+tree map_context_from;
+tree map_context_to;
+
+/* Id for dumping module information. */
+int module_dump_id;
+
+/* We have a special module owner. */
+#define MODULE_UNKNOWN (~0U) /* Not yet known. */
+
+/* Prefix for section names. */
+#define MOD_SNAME_PFX ".gnu.c++"
+
+/* Format a version for user consumption. */
+
+typedef char verstr_t[32];
+static void
+version2string (unsigned version, verstr_t &out)
+{
+ unsigned major = MODULE_MAJOR (version);
+ unsigned minor = MODULE_MINOR (version);
+
+ if (IS_EXPERIMENTAL (version))
+ sprintf (out, "%04u/%02u/%02u-%02u:%02u%s",
+ 2000 + major / 10000, (major / 100) % 100, (major % 100),
+ minor / 100, minor % 100,
+ EXPERIMENT ("", " (experimental)"));
+ else
+ sprintf (out, "%u.%u", major, minor);
+}
+
+/* Include files to note translation for. */
+static vec<const char *, va_heap, vl_embed> *note_includes;
+
+/* Traits to hash an arbitrary pointer. Entries are not deletable,
+ and removal is a noop (removal needed upon destruction). */
+template <typename T>
+struct nodel_ptr_hash : pointer_hash<T>, typed_noop_remove <T *> {
+ /* Nothing is deletable. Everything is insertable. */
+ static bool is_deleted (T *) { return false; }
+ static void mark_deleted (T *) { gcc_unreachable (); }
+};
+
+/* Map from pointer to signed integer. */
+typedef simple_hashmap_traits<nodel_ptr_hash<void>, int> ptr_int_traits;
+typedef hash_map<void *,signed,ptr_int_traits> ptr_int_hash_map;
+
+/********************************************************************/
+/* Basic streaming & ELF. Serialization is usually via mmap. For
+ writing we slide a buffer over the output file, syncing it
+ approproiately. For reading we simply map the whole file (as a
+ file-backed read-only map -- it's just address space, leaving the
+ OS pager to deal with getting the data to us). Some buffers need
+ to be more conventional malloc'd contents. */
+
+/* Variable length buffer. */
+
+class data {
+public:
+ class allocator {
+ public:
+ /* Tools tend to moan if the dtor's not virtual. */
+ virtual ~allocator () {}
+
+ public:
+ void grow (data &obj, unsigned needed, bool exact);
+ void shrink (data &obj);
+
+ public:
+ virtual char *grow (char *ptr, unsigned needed);
+ virtual void shrink (char *ptr);
+ };
+
+public:
+ char *buffer; /* Buffer being transferred. */
+ /* Although size_t would be the usual size, we know we never get
+ more than 4GB of buffer -- because that's the limit of the
+ encapsulation format. And if you need bigger imports, you're
+ doing it wrong. */
+ unsigned size; /* Allocated size of buffer. */
+ unsigned pos; /* Position in buffer. */
+
+public:
+ data ()
+ :buffer (NULL), size (0), pos (0)
+ {
+ }
+ ~data ()
+ {
+ /* Make sure the derived and/or using class know what they're
+ doing. */
+ gcc_checking_assert (!buffer);
+ }
+
+protected:
+ char *use (unsigned count)
+ {
+ if (size < pos + count)
+ return NULL;
+ char *res = &buffer[pos];
+ pos += count;
+ return res;
+ }
+
+public:
+ void unuse (unsigned count)
+ {
+ pos -= count;
+ }
+
+public:
+ static allocator simple_memory;
+};
+
+/* The simple data allocator. */
+data::allocator data::simple_memory;
+
+/* Grow buffer to at least size NEEDED. */
+
+void
+data::allocator::grow (data &obj, unsigned needed, bool exact)
+{
+ gcc_checking_assert (needed ? needed > obj.size : !obj.size);
+ if (!needed)
+ /* Pick a default size. */
+ needed = EXPERIMENT (100, 1000);
+
+ if (!exact)
+ needed *= 2;
+ obj.buffer = grow (obj.buffer, needed);
+ if (obj.buffer)
+ obj.size = needed;
+ else
+ obj.pos = obj.size = 0;
+}
+
+/* Free a buffer. */
+
+void
+data::allocator::shrink (data &obj)
+{
+ shrink (obj.buffer);
+ obj.buffer = NULL;
+ obj.size = 0;
+}
+
+char *
+data::allocator::grow (char *ptr, unsigned needed)
+{
+ return XRESIZEVAR (char, ptr, needed);
+}
+
+void
+data::allocator::shrink (char *ptr)
+{
+ XDELETEVEC (ptr);
+}
+
+/* Byte streamer base. Buffer with read/write position and smarts
+ for single bits. */
+
+class bytes : public data {
+public:
+ typedef data parent;
+
+protected:
+ uint32_t bit_val; /* Bit buffer. */
+ unsigned bit_pos; /* Next bit in bit buffer. */
+
+public:
+ bytes ()
+ :parent (), bit_val (0), bit_pos (0)
+ {}
+ ~bytes ()
+ {
+ }
+
+protected:
+ unsigned calc_crc (unsigned) const;
+
+protected:
+ /* Finish bit packet. Rewind the bytes not used. */
+ unsigned bit_flush ()
+ {
+ gcc_assert (bit_pos);
+ unsigned bytes = (bit_pos + 7) / 8;
+ unuse (4 - bytes);
+ bit_pos = 0;
+ bit_val = 0;
+ return bytes;
+ }
+};
+
+/* Calculate the crc32 of the buffer. Note the CRC is stored in the
+ first 4 bytes, so don't include them. */
+
+unsigned
+bytes::calc_crc (unsigned l) const
+{
+ unsigned crc = 0;
+ for (size_t ix = 4; ix < l; ix++)
+ crc = crc32_byte (crc, buffer[ix]);
+ return crc;
+}
+
+class elf_in;
+
+/* Byte stream reader. */
+
+class bytes_in : public bytes {
+ typedef bytes parent;
+
+protected:
+ bool overrun; /* Sticky read-too-much flag. */
+
+public:
+ bytes_in ()
+ : parent (), overrun (false)
+ {
+ }
+ ~bytes_in ()
+ {
+ }
+
+public:
+ /* Begin reading a named section. */
+ bool begin (location_t loc, elf_in *src, const char *name);
+ /* Begin reading a numbered section with optional name. */
+ bool begin (location_t loc, elf_in *src, unsigned, const char * = NULL);
+ /* Complete reading a buffer. Propagate errors and return true on
+ success. */
+ bool end (elf_in *src);
+ /* Return true if there is unread data. */
+ bool more_p () const
+ {
+ return pos != size;
+ }
+
+public:
+ /* Start reading at OFFSET. */
+ void random_access (unsigned offset)
+ {
+ if (offset > size)
+ set_overrun ();
+ pos = offset;
+ bit_pos = bit_val = 0;
+ }
+
+public:
+ void align (unsigned boundary)
+ {
+ if (unsigned pad = pos & (boundary - 1))
+ read (boundary - pad);
+ }
+
+public:
+ const char *read (unsigned count)
+ {
+ char *ptr = use (count);
+ if (!ptr)
+ set_overrun ();
+ return ptr;
+ }
+
+public:
+ bool check_crc () const;
+ /* We store the CRC in the first 4 bytes, using host endianness. */
+ unsigned get_crc () const
+ {
+ return *(const unsigned *)&buffer[0];
+ }
+
+public:
+ /* Manipulate the overrun flag. */
+ bool get_overrun () const
+ {
+ return overrun;
+ }
+ void set_overrun ()
+ {
+ overrun = true;
+ }
+
+public:
+ unsigned u32 (); /* Read uncompressed integer. */
+
+public:
+ bool b (); /* Read a bool. */
+ void bflush (); /* Completed a block of bools. */
+
+private:
+ void bfill (); /* Get the next block of bools. */
+
+public:
+ int c (); /* Read a char. */
+ int i (); /* Read a signed int. */
+ unsigned u (); /* Read an unsigned int. */
+ size_t z (); /* Read a size_t. */
+ HOST_WIDE_INT wi (); /* Read a HOST_WIDE_INT. */
+ unsigned HOST_WIDE_INT wu (); /* Read an unsigned HOST_WIDE_INT. */
+ const char *str (size_t * = NULL); /* Read a string. */
+ const void *buf (size_t); /* Read a fixed-length buffer. */
+ cpp_hashnode *cpp_node (); /* Read a cpp node. */
+};
+
+/* Verify the buffer's CRC is correct. */
+
+bool
+bytes_in::check_crc () const
+{
+ if (size < 4)
+ return false;
+
+ unsigned c_crc = calc_crc (size);
+ if (c_crc != get_crc ())
+ return false;
+
+ return true;
+}
+
+class elf_out;
+
+/* Byte stream writer. */
+
+class bytes_out : public bytes {
+ typedef bytes parent;
+
+public:
+ allocator *memory; /* Obtainer of memory. */
+
+public:
+ bytes_out (allocator *memory)
+ : parent (), memory (memory)
+ {
+ }
+ ~bytes_out ()
+ {
+ }
+
+public:
+ bool streaming_p () const
+ {
+ return memory != NULL;
+ }
+
+public:
+ void set_crc (unsigned *crc_ptr);
+
+public:
+ /* Begin writing, maybe reserve space for CRC. */
+ void begin (bool need_crc = true);
+ /* Finish writing. Spill to section by number. */
+ unsigned end (elf_out *, unsigned, unsigned *crc_ptr = NULL);
+
+public:
+ void align (unsigned boundary)
+ {
+ if (unsigned pad = pos & (boundary - 1))
+ write (boundary - pad);
+ }
+
+public:
+ char *write (unsigned count, bool exact = false)
+ {
+ if (size < pos + count)
+ memory->grow (*this, pos + count, exact);
+ return use (count);
+ }
+
+public:
+ void u32 (unsigned); /* Write uncompressed integer. */
+
+public:
+ void b (bool); /* Write bool. */
+ void bflush (); /* Finish block of bools. */
+
+public:
+ void c (unsigned char); /* Write unsigned char. */
+ void i (int); /* Write signed int. */
+ void u (unsigned); /* Write unsigned int. */
+ void z (size_t s); /* Write size_t. */
+ void wi (HOST_WIDE_INT); /* Write HOST_WIDE_INT. */
+ void wu (unsigned HOST_WIDE_INT); /* Write unsigned HOST_WIDE_INT. */
+ void str (const char *ptr)
+ {
+ str (ptr, strlen (ptr));
+ }
+ void cpp_node (const cpp_hashnode *node)
+ {
+ str ((const char *)NODE_NAME (node), NODE_LEN (node));
+ }
+ void str (const char *, size_t); /* Write string of known length. */
+ void buf (const void *, size_t); /* Write fixed length buffer. */
+ void *buf (size_t); /* Create a writable buffer */
+
+public:
+ /* Format a NUL-terminated raw string. */
+ void printf (const char *, ...) ATTRIBUTE_PRINTF_2;
+ void print_time (const char *, const tm *, const char *);
+
+public:
+ /* Dump instrumentation. */
+ static void instrument ();
+
+protected:
+ /* Instrumentation. */
+ static unsigned spans[4];
+ static unsigned lengths[4];
+ static int is_set;
+};
+
+/* Instrumentation. */
+unsigned bytes_out::spans[4];
+unsigned bytes_out::lengths[4];
+int bytes_out::is_set = -1;
+
+/* If CRC_PTR non-null, set the CRC of the buffer. Mix the CRC into
+ that pointed to by CRC_PTR. */
+
+void
+bytes_out::set_crc (unsigned *crc_ptr)
+{
+ if (crc_ptr)
+ {
+ gcc_checking_assert (pos >= 4);
+
+ unsigned crc = calc_crc (pos);
+ unsigned accum = *crc_ptr;
+ /* Only mix the existing *CRC_PTR if it is non-zero. */
+ accum = accum ? crc32_unsigned (accum, crc) : crc;
+ *crc_ptr = accum;
+
+ /* Buffer will be sufficiently aligned. */
+ *(unsigned *)buffer = crc;
+ }
+}
+
+/* Finish a set of bools. */
+
+void
+bytes_out::bflush ()
+{
+ if (bit_pos)
+ {
+ u32 (bit_val);
+ lengths[2] += bit_flush ();
+ }
+ spans[2]++;
+ is_set = -1;
+}
+
+void
+bytes_in::bflush ()
+{
+ if (bit_pos)
+ bit_flush ();
+}
+
+/* When reading, we don't know how many bools we'll read in. So read
+ 4 bytes-worth, and then rewind when flushing if we didn't need them
+ all. You can't have a block of bools closer than 4 bytes to the
+ end of the buffer. */
+
+void
+bytes_in::bfill ()
+{
+ bit_val = u32 ();
+}
+
+/* Bools are packed into bytes. You cannot mix bools and non-bools.
+ You must call bflush before emitting another type. So batch your
+ bools.
+
+ It may be worth optimizing for most bools being zero. Some kind of
+ run-length encoding? */
+
+void
+bytes_out::b (bool x)
+{
+ if (is_set != x)
+ {
+ is_set = x;
+ spans[x]++;
+ }
+ lengths[x]++;
+ bit_val |= unsigned (x) << bit_pos++;
+ if (bit_pos == 32)
+ {
+ u32 (bit_val);
+ lengths[2] += bit_flush ();
+ }
+}
+
+bool
+bytes_in::b ()
+{
+ if (!bit_pos)
+ bfill ();
+ bool v = (bit_val >> bit_pos++) & 1;
+ if (bit_pos == 32)
+ bit_flush ();
+ return v;
+}
+
+/* Exactly 4 bytes. Used internally for bool packing and a few other
+ places. We can't simply use uint32_t because (a) alignment and
+ (b) we need little-endian for the bool streaming rewinding to make
+ sense. */
+
+void
+bytes_out::u32 (unsigned val)
+{
+ if (char *ptr = write (4))
+ {
+ ptr[0] = val;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+ }
+}
+
+unsigned
+bytes_in::u32 ()
+{
+ unsigned val = 0;
+ if (const char *ptr = read (4))
+ {
+ val |= (unsigned char)ptr[0];
+ val |= (unsigned char)ptr[1] << 8;
+ val |= (unsigned char)ptr[2] << 16;
+ val |= (unsigned char)ptr[3] << 24;
+ }
+
+ return val;
+}
+
+/* Chars are unsigned and written as single bytes. */
+
+void
+bytes_out::c (unsigned char v)
+{
+ if (char *ptr = write (1))
+ *ptr = v;
+}
+
+int
+bytes_in::c ()
+{
+ int v = 0;
+ if (const char *ptr = read (1))
+ v = (unsigned char)ptr[0];
+ return v;
+}
+
+/* Ints 7-bit as a byte. Otherwise a 3bit count of following bytes in
+ big-endian form. 4 bits are in the first byte. */
+
+void
+bytes_out::i (int v)
+{
+ if (char *ptr = write (1))
+ {
+ if (v <= 0x3f && v >= -0x40)
+ *ptr = v & 0x7f;
+ else
+ {
+ unsigned bytes = 0;
+ int probe;
+ if (v >= 0)
+ for (probe = v >> 8; probe > 0x7; probe >>= 8)
+ bytes++;
+ else
+ for (probe = v >> 8; probe < -0x8; probe >>= 8)
+ bytes++;
+ *ptr = 0x80 | bytes << 4 | (probe & 0xf);
+ if ((ptr = write (++bytes)))
+ for (; bytes--; v >>= 8)
+ ptr[bytes] = v & 0xff;
+ }
+ }
+}
+
+int
+bytes_in::i ()
+{
+ int v = 0;
+ if (const char *ptr = read (1))
+ {
+ v = *ptr & 0xff;
+ if (v & 0x80)
+ {
+ unsigned bytes = (v >> 4) & 0x7;
+ v &= 0xf;
+ if (v & 0x8)
+ v |= -1 ^ 0x7;
+ if ((ptr = read (++bytes)))
+ while (bytes--)
+ v = (v << 8) | (*ptr++ & 0xff);
+ }
+ else if (v & 0x40)
+ v |= -1 ^ 0x3f;
+ }
+
+ return v;
+}
+
+void
+bytes_out::u (unsigned v)
+{
+ if (char *ptr = write (1))
+ {
+ if (v <= 0x7f)
+ *ptr = v;
+ else
+ {
+ unsigned bytes = 0;
+ unsigned probe;
+ for (probe = v >> 8; probe > 0xf; probe >>= 8)
+ bytes++;
+ *ptr = 0x80 | bytes << 4 | probe;
+ if ((ptr = write (++bytes)))
+ for (; bytes--; v >>= 8)
+ ptr[bytes] = v & 0xff;
+ }
+ }
+}
+
+unsigned
+bytes_in::u ()
+{
+ unsigned v = 0;
+
+ if (const char *ptr = read (1))
+ {
+ v = *ptr & 0xff;
+ if (v & 0x80)
+ {
+ unsigned bytes = (v >> 4) & 0x7;
+ v &= 0xf;
+ if ((ptr = read (++bytes)))
+ while (bytes--)
+ v = (v << 8) | (*ptr++ & 0xff);
+ }
+ }
+
+ return v;
+}
+
+void
+bytes_out::wi (HOST_WIDE_INT v)
+{
+ if (char *ptr = write (1))
+ {
+ if (v <= 0x3f && v >= -0x40)
+ *ptr = v & 0x7f;
+ else
+ {
+ unsigned bytes = 0;
+ HOST_WIDE_INT probe;
+ if (v >= 0)
+ for (probe = v >> 8; probe > 0x7; probe >>= 8)
+ bytes++;
+ else
+ for (probe = v >> 8; probe < -0x8; probe >>= 8)
+ bytes++;
+ *ptr = 0x80 | bytes << 4 | (probe & 0xf);
+ if ((ptr = write (++bytes)))
+ for (; bytes--; v >>= 8)
+ ptr[bytes] = v & 0xff;
+ }
+ }
+}
+
+HOST_WIDE_INT
+bytes_in::wi ()
+{
+ HOST_WIDE_INT v = 0;
+ if (const char *ptr = read (1))
+ {
+ v = *ptr & 0xff;
+ if (v & 0x80)
+ {
+ unsigned bytes = (v >> 4) & 0x7;
+ v &= 0xf;
+ if (v & 0x8)
+ v |= -1 ^ 0x7;
+ if ((ptr = read (++bytes)))
+ while (bytes--)
+ v = (v << 8) | (*ptr++ & 0xff);
+ }
+ else if (v & 0x40)
+ v |= -1 ^ 0x3f;
+ }
+
+ return v;
+}
+
+/* unsigned wide ints are just written as signed wide ints. */
+
+inline void
+bytes_out::wu (unsigned HOST_WIDE_INT v)
+{
+ wi ((HOST_WIDE_INT) v);
+}
+
+inline unsigned HOST_WIDE_INT
+bytes_in::wu ()
+{
+ return (unsigned HOST_WIDE_INT) wi ();
+}
+
+/* size_t written as unsigned or unsigned wide int. */
+
+inline void
+bytes_out::z (size_t s)
+{
+ if (sizeof (s) == sizeof (unsigned))
+ u (s);
+ else
+ wu (s);
+}
+
+inline size_t
+bytes_in::z ()
+{
+ if (sizeof (size_t) == sizeof (unsigned))
+ return u ();
+ else
+ return wu ();
+}
+
+/* Buffer simply memcpied. */
+void *
+bytes_out::buf (size_t len)
+{
+ align (sizeof (void *) * 2);
+ return write (len);
+}
+
+void
+bytes_out::buf (const void *src, size_t len)
+{
+ if (void *ptr = buf (len))
+ memcpy (ptr, src, len);
+}
+
+const void *
+bytes_in::buf (size_t len)
+{
+ align (sizeof (void *) * 2);
+ const char *ptr = read (len);
+
+ return ptr;
+}
+
+/* strings as an size_t length, followed by the buffer. Make sure
+ there's a NUL terminator on read. */
+
+void
+bytes_out::str (const char *string, size_t len)
+{
+ z (len);
+ if (len)
+ {
+ gcc_checking_assert (!string[len]);
+ buf (string, len + 1);
+ }
+}
+
+const char *
+bytes_in::str (size_t *len_p)
+{
+ size_t len = z ();
+
+ /* We're about to trust some user data. */
+ if (overrun)
+ len = 0;
+ if (len_p)
+ *len_p = len;
+ const char *str = NULL;
+ if (len)
+ {
+ str = reinterpret_cast<const char *> (buf (len + 1));
+ if (!str || str[len])
+ {
+ set_overrun ();
+ str = NULL;
+ }
+ }
+ return str ? str : "";
+}
+
+cpp_hashnode *
+bytes_in::cpp_node ()
+{
+ size_t len;
+ const char *s = str (&len);
+ if (!len)
+ return NULL;
+ return ::cpp_node (get_identifier_with_length (s, len));
+}
+
+/* Format a string directly to the buffer, including a terminating
+ NUL. Intended for human consumption. */
+
+void
+bytes_out::printf (const char *format, ...)
+{
+ va_list args;
+ /* Exercise buffer expansion. */
+ size_t len = EXPERIMENT (10, 500);
+
+ while (char *ptr = write (len))
+ {
+ va_start (args, format);
+ size_t actual = vsnprintf (ptr, len, format, args) + 1;
+ va_end (args);
+ if (actual <= len)
+ {
+ unuse (len - actual);
+ break;
+ }
+ unuse (len);
+ len = actual;
+ }
+}
+
+void
+bytes_out::print_time (const char *kind, const tm *time, const char *tz)
+{
+ printf ("%stime: %4u/%02u/%02u %02u:%02u:%02u %s",
+ kind, time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec, tz);
+}
+
+/* Encapsulated Lazy Records Of Named Declarations.
+ Header: Stunningly Elf32_Ehdr-like
+ Sections: Sectional data
+ [1-N) : User data sections
+ N .strtab : strings, stunningly ELF STRTAB-like
+ Index: Section table, stunningly ELF32_Shdr-like. */
+
+class elf {
+protected:
+ /* Constants used within the format. */
+ enum private_constants {
+ /* File kind. */
+ ET_NONE = 0,
+ EM_NONE = 0,
+ OSABI_NONE = 0,
+
+ /* File format. */
+ EV_CURRENT = 1,
+ CLASS32 = 1,
+ DATA2LSB = 1,
+ DATA2MSB = 2,
+
+ /* Section numbering. */
+ SHN_UNDEF = 0,
+ SHN_LORESERVE = 0xff00,
+ SHN_XINDEX = 0xffff,
+
+ /* Section types. */
+ SHT_NONE = 0, /* No contents. */
+ SHT_PROGBITS = 1, /* Random bytes. */
+ SHT_STRTAB = 3, /* A string table. */
+
+ /* Section flags. */
+ SHF_NONE = 0x00, /* Nothing. */
+ SHF_STRINGS = 0x20, /* NUL-Terminated strings. */
+
+ /* I really hope we do not get CMI files larger than 4GB. */
+ MY_CLASS = CLASS32,
+ /* It is host endianness that is relevant. */
+ MY_ENDIAN = DATA2LSB
+#ifdef WORDS_BIGENDIAN
+ ^ DATA2LSB ^ DATA2MSB
+#endif
+ };
+
+public:
+ /* Constants visible to users. */
+ enum public_constants {
+ /* Special error codes. Breaking layering a bit. */
+ E_BAD_DATA = -1, /* Random unexpected data errors. */
+ E_BAD_LAZY = -2, /* Badly ordered laziness. */
+ E_BAD_IMPORT = -3 /* A nested import failed. */
+ };
+
+protected:
+ /* File identification. On-disk representation. */
+ struct ident {
+ uint8_t magic[4]; /* 0x7f, 'E', 'L', 'F' */
+ uint8_t klass; /* 4:CLASS32 */
+ uint8_t data; /* 5:DATA2[LM]SB */
+ uint8_t version; /* 6:EV_CURRENT */
+ uint8_t osabi; /* 7:OSABI_NONE */
+ uint8_t abiver; /* 8: 0 */
+ uint8_t pad[7]; /* 9-15 */
+ };
+ /* File header. On-disk representation. */
+ struct header {
+ struct ident ident;
+ uint16_t type; /* ET_NONE */
+ uint16_t machine; /* EM_NONE */
+ uint32_t version; /* EV_CURRENT */
+ uint32_t entry; /* 0 */
+ uint32_t phoff; /* 0 */
+ uint32_t shoff; /* Section Header Offset in file */
+ uint32_t flags;
+ uint16_t ehsize; /* ELROND Header SIZE -- sizeof (header) */
+ uint16_t phentsize; /* 0 */
+ uint16_t phnum; /* 0 */
+ uint16_t shentsize; /* Section Header SIZE -- sizeof (section) */
+ uint16_t shnum; /* Section Header NUM */
+ uint16_t shstrndx; /* Section Header STRing iNDeX */
+ };
+ /* File section. On-disk representation. */
+ struct section {
+ uint32_t name; /* String table offset. */
+ uint32_t type; /* SHT_* */
+ uint32_t flags; /* SHF_* */
+ uint32_t addr; /* 0 */
+ uint32_t offset; /* OFFSET in file */
+ uint32_t size; /* SIZE of section */
+ uint32_t link; /* 0 */
+ uint32_t info; /* 0 */
+ uint32_t addralign; /* 0 */
+ uint32_t entsize; /* ENTry SIZE, usually 0 */
+ };
+
+protected:
+ data hdr; /* The header. */
+ data sectab; /* The section table. */
+ data strtab; /* String table. */
+ int fd; /* File descriptor we're reading or writing. */
+ int err; /* Sticky error code. */
+
+public:
+ /* Construct from STREAM. E is errno if STREAM NULL. */
+ elf (int fd, int e)
+ :hdr (), sectab (), strtab (), fd (fd), err (fd >= 0 ? 0 : e)
+ {}
+ ~elf ()
+ {
+ gcc_checking_assert (fd < 0 && !hdr.buffer
+ && !sectab.buffer && !strtab.buffer);
+ }
+
+public:
+ /* Return the error, if we have an error. */
+ int get_error () const
+ {
+ return err;
+ }
+ /* Set the error, unless it's already been set. */
+ void set_error (int e = E_BAD_DATA)
+ {
+ if (!err)
+ err = e;
+ }
+ /* Get an error string. */
+ const char *get_error (const char *) const;
+
+public:
+ /* Begin reading/writing file. Return false on error. */
+ bool begin () const
+ {
+ return !get_error ();
+ }
+ /* Finish reading/writing file. Return false on error. */
+ bool end ();
+};
+
+/* Return error string. */
+
+const char *
+elf::get_error (const char *name) const
+{
+ if (!name)
+ return "Unknown CMI mapping";
+
+ switch (err)
+ {
+ case 0:
+ gcc_unreachable ();
+ case E_BAD_DATA:
+ return "Bad file data";
+ case E_BAD_IMPORT:
+ return "Bad import dependency";
+ case E_BAD_LAZY:
+ return "Bad lazy ordering";
+ default:
+ return xstrerror (err);
+ }
+}
+
+/* Finish file, return true if there's an error. */
+
+bool
+elf::end ()
+{
+ /* Close the stream and free the section table. */
+ if (fd >= 0 && close (fd))
+ set_error (errno);
+ fd = -1;
+
+ return !get_error ();
+}
+
+/* ELROND reader. */
+
+class elf_in : public elf {
+ typedef elf parent;
+
+private:
+ /* For freezing & defrosting. */
+#if !defined (HOST_LACKS_INODE_NUMBERS)
+ dev_t device;
+ ino_t inode;
+#endif
+
+public:
+ elf_in (int fd, int e)
+ :parent (fd, e)
+ {
+ }
+ ~elf_in ()
+ {
+ }
+
+public:
+ bool is_frozen () const
+ {
+ return fd < 0 && hdr.pos;
+ }
+ bool is_freezable () const
+ {
+ return fd >= 0 && hdr.pos;
+ }
+ void freeze ();
+ bool defrost (const char *);
+
+ /* If BYTES is in the mmapped area, allocate a new buffer for it. */
+ void preserve (bytes_in &bytes ATTRIBUTE_UNUSED)
+ {
+#if MAPPED_READING
+ if (hdr.buffer && bytes.buffer >= hdr.buffer
+ && bytes.buffer < hdr.buffer + hdr.pos)
+ {
+ char *buf = bytes.buffer;
+ bytes.buffer = data::simple_memory.grow (NULL, bytes.size);
+ memcpy (bytes.buffer, buf, bytes.size);
+ }
+#endif
+ }
+ /* If BYTES is not in SELF's mmapped area, free it. SELF might be
+ NULL. */
+ static void release (elf_in *self ATTRIBUTE_UNUSED, bytes_in &bytes)
+ {
+#if MAPPED_READING
+ if (!(self && self->hdr.buffer && bytes.buffer >= self->hdr.buffer
+ && bytes.buffer < self->hdr.buffer + self->hdr.pos))
+#endif
+ data::simple_memory.shrink (bytes.buffer);
+ bytes.buffer = NULL;
+ bytes.size = 0;
+ }
+
+public:
+ static void grow (data &data, unsigned needed)
+ {
+ gcc_checking_assert (!data.buffer);
+#if !MAPPED_READING
+ data.buffer = XNEWVEC (char, needed);
+#endif
+ data.size = needed;
+ }
+ static void shrink (data &data)
+ {
+#if !MAPPED_READING
+ XDELETEVEC (data.buffer);
+#endif
+ data.buffer = NULL;
+ data.size = 0;
+ }
+
+public:
+ const section *get_section (unsigned s) const
+ {
+ if (s * sizeof (section) < sectab.size)
+ return reinterpret_cast<const section *>
+ (&sectab.buffer[s * sizeof (section)]);
+ else
+ return NULL;
+ }
+ unsigned get_section_limit () const
+ {
+ return sectab.size / sizeof (section);
+ }
+
+protected:
+ const char *read (data *, unsigned, unsigned);
+
+public:
+ /* Read section by number. */
+ bool read (data *d, const section *s)
+ {
+ return s && read (d, s->offset, s->size);
+ }
+
+ /* Find section by name. */
+ unsigned find (const char *name);
+ /* Find section by index. */
+ const section *find (unsigned snum, unsigned type = SHT_PROGBITS);
+
+public:
+ /* Release the string table, when we're done with it. */
+ void release ()
+ {
+ shrink (strtab);
+ }
+
+public:
+ bool begin (location_t);
+ bool end ()
+ {
+ release ();
+#if MAPPED_READING
+ if (hdr.buffer)
+ munmap (hdr.buffer, hdr.pos);
+ hdr.buffer = NULL;
+#endif
+ shrink (sectab);
+
+ return parent::end ();
+ }
+
+public:
+ /* Return string name at OFFSET. Checks OFFSET range. Always
+ returns non-NULL. We know offset 0 is an empty string. */
+ const char *name (unsigned offset)
+ {
+ return &strtab.buffer[offset < strtab.size ? offset : 0];
+ }
+};
+
+/* ELROND writer. */
+
+class elf_out : public elf, public data::allocator {
+ typedef elf parent;
+ /* Desired section alignment on disk. */
+ static const int SECTION_ALIGN = 16;
+
+private:
+ ptr_int_hash_map identtab; /* Map of IDENTIFIERS to strtab offsets. */
+ unsigned pos; /* Write position in file. */
+#if MAPPED_WRITING
+ unsigned offset; /* Offset of the mapping. */
+ unsigned extent; /* Length of mapping. */
+ unsigned page_size; /* System page size. */
+#endif
+
+public:
+ elf_out (int fd, int e)
+ :parent (fd, e), identtab (500), pos (0)
+ {
+#if MAPPED_WRITING
+ offset = extent = 0;
+ page_size = sysconf (_SC_PAGE_SIZE);
+ if (page_size < SECTION_ALIGN)
+ /* Something really strange. */
+ set_error (EINVAL);
+#endif
+ }
+ ~elf_out ()
+ {
+ data::simple_memory.shrink (hdr);
+ data::simple_memory.shrink (sectab);
+ data::simple_memory.shrink (strtab);
+ }
+
+#if MAPPED_WRITING
+private:
+ void create_mapping (unsigned ext, bool extending = true);
+ void remove_mapping ();
+#endif
+
+protected:
+ using allocator::grow;
+ virtual char *grow (char *, unsigned needed);
+#if MAPPED_WRITING
+ using allocator::shrink;
+ virtual void shrink (char *);
+#endif
+
+public:
+ unsigned get_section_limit () const
+ {
+ return sectab.pos / sizeof (section);
+ }
+
+protected:
+ unsigned add (unsigned type, unsigned name = 0,
+ unsigned off = 0, unsigned size = 0, unsigned flags = SHF_NONE);
+ unsigned write (const data &);
+#if MAPPED_WRITING
+ unsigned write (const bytes_out &);
+#endif
+
+public:
+ /* IDENTIFIER to strtab offset. */
+ unsigned name (tree ident);
+ /* String literal to strtab offset. */
+ unsigned name (const char *n);
+ /* Qualified name of DECL to strtab offset. */
+ unsigned qualified_name (tree decl, bool is_defn);
+
+private:
+ unsigned strtab_write (const char *s, unsigned l);
+ void strtab_write (tree decl, int);
+
+public:
+ /* Add a section with contents or strings. */
+ unsigned add (const bytes_out &, bool string_p, unsigned name);
+
+public:
+ /* Begin and end writing. */
+ bool begin ();
+ bool end ();
+};
+
+/* Begin reading section NAME (of type PROGBITS) from SOURCE.
+ Data always checked for CRC. */
+
+bool
+bytes_in::begin (location_t loc, elf_in *source, const char *name)
+{
+ unsigned snum = source->find (name);
+
+ return begin (loc, source, snum, name);
+}
+
+/* Begin reading section numbered SNUM with NAME (may be NULL). */
+
+bool
+bytes_in::begin (location_t loc, elf_in *source, unsigned snum, const char *name)
+{
+ if (!source->read (this, source->find (snum))
+ || !size || !check_crc ())
+ {
+ source->set_error (elf::E_BAD_DATA);
+ source->shrink (*this);
+ if (name)
+ error_at (loc, "section %qs is missing or corrupted", name);
+ else
+ error_at (loc, "section #%u is missing or corrupted", snum);
+ return false;
+ }
+ pos = 4;
+ return true;
+}
+
+/* Finish reading a section. */
+
+bool
+bytes_in::end (elf_in *src)
+{
+ if (more_p ())
+ set_overrun ();
+ if (overrun)
+ src->set_error ();
+
+ src->shrink (*this);
+
+ return !overrun;
+}
+
+/* Begin writing buffer. */
+
+void
+bytes_out::begin (bool need_crc)
+{
+ if (need_crc)
+ pos = 4;
+ memory->grow (*this, 0, false);
+}
+
+/* Finish writing buffer. Stream out to SINK as named section NAME.
+ Return section number or 0 on failure. If CRC_PTR is true, crc
+ the data. Otherwise it is a string section. */
+
+unsigned
+bytes_out::end (elf_out *sink, unsigned name, unsigned *crc_ptr)
+{
+ lengths[3] += pos;
+ spans[3]++;
+
+ set_crc (crc_ptr);
+ unsigned sec_num = sink->add (*this, !crc_ptr, name);
+ memory->shrink (*this);
+
+ return sec_num;
+}
+
+/* Close and open the file, without destroying it. */
+
+void
+elf_in::freeze ()
+{
+ gcc_checking_assert (!is_frozen ());
+#if MAPPED_READING
+ if (munmap (hdr.buffer, hdr.pos) < 0)
+ set_error (errno);
+#endif
+ if (close (fd) < 0)
+ set_error (errno);
+ fd = -1;
+}
+
+bool
+elf_in::defrost (const char *name)
+{
+ gcc_checking_assert (is_frozen ());
+ struct stat stat;
+
+ fd = open (name, O_RDONLY | O_CLOEXEC | O_BINARY);
+ if (fd < 0 || fstat (fd, &stat) < 0)
+ set_error (errno);
+ else
+ {
+ bool ok = hdr.pos == unsigned (stat.st_size);
+#ifndef HOST_LACKS_INODE_NUMBERS
+ if (device != stat.st_dev
+ || inode != stat.st_ino)
+ ok = false;
+#endif
+ if (!ok)
+ set_error (EMFILE);
+#if MAPPED_READING
+ if (ok)
+ {
+ char *mapping = reinterpret_cast<char *>
+ (mmap (NULL, hdr.pos, PROT_READ, MAP_SHARED, fd, 0));
+ if (mapping == MAP_FAILED)
+ fail:
+ set_error (errno);
+ else
+ {
+ if (madvise (mapping, hdr.pos, MADV_RANDOM))
+ goto fail;
+
+ /* These buffers are never NULL in this case. */
+ strtab.buffer = mapping + strtab.pos;
+ sectab.buffer = mapping + sectab.pos;
+ hdr.buffer = mapping;
+ }
+ }
+#endif
+ }
+
+ return !get_error ();
+}
+
+/* Read at current position into BUFFER. Return true on success. */
+
+const char *
+elf_in::read (data *data, unsigned pos, unsigned length)
+{
+#if MAPPED_READING
+ if (pos + length > hdr.pos)
+ {
+ set_error (EINVAL);
+ return NULL;
+ }
+#else
+ if (pos != ~0u && lseek (fd, pos, SEEK_SET) < 0)
+ {
+ set_error (errno);
+ return NULL;
+ }
+#endif
+ grow (*data, length);
+#if MAPPED_READING
+ data->buffer = hdr.buffer + pos;
+#else
+ if (::read (fd, data->buffer, data->size) != ssize_t (length))
+ {
+ set_error (errno);
+ shrink (*data);
+ return NULL;
+ }
+#endif
+
+ return data->buffer;
+}
+
+/* Read section SNUM of TYPE. Return section pointer or NULL on error. */
+
+const elf::section *
+elf_in::find (unsigned snum, unsigned type)
+{
+ const section *sec = get_section (snum);
+ if (!snum || !sec || sec->type != type)
+ return NULL;
+ return sec;
+}
+
+/* Find a section NAME and TYPE. Return section number, or zero on
+ failure. */
+
+unsigned
+elf_in::find (const char *sname)
+{
+ for (unsigned pos = sectab.size; pos -= sizeof (section); )
+ {
+ const section *sec
+ = reinterpret_cast<const section *> (&sectab.buffer[pos]);
+
+ if (0 == strcmp (sname, name (sec->name)))
+ return pos / sizeof (section);
+ }
+
+ return 0;
+}
+
+/* Begin reading file. Verify header. Pull in section and string
+ tables. Return true on success. */
+
+bool
+elf_in::begin (location_t loc)
+{
+ if (!parent::begin ())
+ return false;
+
+ struct stat stat;
+ unsigned size = 0;
+ if (!fstat (fd, &stat))
+ {
+#if !defined (HOST_LACKS_INODE_NUMBERS)
+ device = stat.st_dev;
+ inode = stat.st_ino;
+#endif
+ /* Never generate files > 4GB, check we've not been given one. */
+ if (stat.st_size == unsigned (stat.st_size))
+ size = unsigned (stat.st_size);
+ }
+
+#if MAPPED_READING
+ /* MAP_SHARED so that the file is backing store. If someone else
+ concurrently writes it, they're wrong. */
+ void *mapping = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (mapping == MAP_FAILED)
+ {
+ fail:
+ set_error (errno);
+ return false;
+ }
+ /* We'll be hopping over this randomly. Some systems declare the
+ first parm as char *, and other declare it as void *. */
+ if (madvise (reinterpret_cast <char *> (mapping), size, MADV_RANDOM))
+ goto fail;
+
+ hdr.buffer = (char *)mapping;
+#else
+ read (&hdr, 0, sizeof (header));
+#endif
+ hdr.pos = size; /* Record size of the file. */
+
+ const header *h = reinterpret_cast<const header *> (hdr.buffer);
+ if (!h)
+ return false;
+
+ if (h->ident.magic[0] != 0x7f
+ || h->ident.magic[1] != 'E'
+ || h->ident.magic[2] != 'L'
+ || h->ident.magic[3] != 'F')
+ {
+ error_at (loc, "not Encapsulated Lazy Records of Named Declarations");
+ failed:
+ shrink (hdr);
+ return false;
+ }
+
+ /* We expect a particular format -- the ELF is not intended to be
+ distributable. */
+ if (h->ident.klass != MY_CLASS
+ || h->ident.data != MY_ENDIAN
+ || h->ident.version != EV_CURRENT
+ || h->type != ET_NONE
+ || h->machine != EM_NONE
+ || h->ident.osabi != OSABI_NONE)
+ {
+ error_at (loc, "unexpected encapsulation format or type");
+ goto failed;
+ }
+
+ int e = -1;
+ if (!h->shoff || h->shentsize != sizeof (section))
+ {
+ malformed:
+ set_error (e);
+ error_at (loc, "encapsulation is malformed");
+ goto failed;
+ }
+
+ unsigned strndx = h->shstrndx;
+ unsigned shnum = h->shnum;
+ if (shnum == SHN_XINDEX)
+ {
+ if (!read (&sectab, h->shoff, sizeof (section)))
+ {
+ section_table_fail:
+ e = errno;
+ goto malformed;
+ }
+ shnum = get_section (0)->size;
+ /* Freeing does mean we'll re-read it in the case we're not
+ mapping, but this is going to be rare. */
+ shrink (sectab);
+ }
+
+ if (!shnum)
+ goto malformed;
+
+ if (!read (&sectab, h->shoff, shnum * sizeof (section)))
+ goto section_table_fail;
+
+ if (strndx == SHN_XINDEX)
+ strndx = get_section (0)->link;
+
+ if (!read (&strtab, find (strndx, SHT_STRTAB)))
+ goto malformed;
+
+ /* The string table should be at least one byte, with NUL chars
+ at either end. */
+ if (!(strtab.size && !strtab.buffer[0]
+ && !strtab.buffer[strtab.size - 1]))
+ goto malformed;
+
+#if MAPPED_READING
+ /* Record the offsets of the section and string tables. */
+ sectab.pos = h->shoff;
+ strtab.pos = shnum * sizeof (section);
+#else
+ shrink (hdr);
+#endif
+
+ return true;
+}
+
+/* Create a new mapping. */
+
+#if MAPPED_WRITING
+void
+elf_out::create_mapping (unsigned ext, bool extending)
+{
+#ifndef HAVE_POSIX_FALLOCATE
+#define posix_fallocate(fd,off,len) ftruncate (fd, off + len)
+#endif
+ void *mapping = MAP_FAILED;
+ if (extending && ext < 1024 * 1024)
+ {
+ if (!posix_fallocate (fd, offset, ext * 2))
+ mapping = mmap (NULL, ext * 2, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, offset);
+ if (mapping != MAP_FAILED)
+ ext *= 2;
+ }
+ if (mapping == MAP_FAILED)
+ {
+ if (!extending || !posix_fallocate (fd, offset, ext))
+ mapping = mmap (NULL, ext, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, offset);
+ if (mapping == MAP_FAILED)
+ {
+ set_error (errno);
+ mapping = NULL;
+ ext = 0;
+ }
+ }
+#undef posix_fallocate
+ hdr.buffer = (char *)mapping;
+ extent = ext;
+}
+#endif
+
+/* Flush out the current mapping. */
+
+#if MAPPED_WRITING
+void
+elf_out::remove_mapping ()
+{
+ if (hdr.buffer)
+ {
+ /* MS_ASYNC dtrt with the removed mapping, including a
+ subsequent overlapping remap. */
+ if (msync (hdr.buffer, extent, MS_ASYNC)
+ || munmap (hdr.buffer, extent))
+ /* We're somewhat screwed at this point. */
+ set_error (errno);
+ }
+
+ hdr.buffer = NULL;
+}
+#endif
+
+/* Grow a mapping of PTR to be NEEDED bytes long. This gets
+ interesting if the new size grows the EXTENT. */
+
+char *
+elf_out::grow (char *data, unsigned needed)
+{
+ if (!data)
+ {
+ /* First allocation, check we're aligned. */
+ gcc_checking_assert (!(pos & (SECTION_ALIGN - 1)));
+#if MAPPED_WRITING
+ data = hdr.buffer + (pos - offset);
+#endif
+ }
+
+#if MAPPED_WRITING
+ unsigned off = data - hdr.buffer;
+ if (off + needed > extent)
+ {
+ /* We need to grow the mapping. */
+ unsigned lwm = off & ~(page_size - 1);
+ unsigned hwm = (off + needed + page_size - 1) & ~(page_size - 1);
+
+ gcc_checking_assert (hwm > extent);
+
+ remove_mapping ();
+
+ offset += lwm;
+ create_mapping (extent < hwm - lwm ? hwm - lwm : extent);
+
+ data = hdr.buffer + (off - lwm);
+ }
+#else
+ data = allocator::grow (data, needed);
+#endif
+
+ return data;
+}
+
+#if MAPPED_WRITING
+/* Shrinking is a NOP. */
+void
+elf_out::shrink (char *)
+{
+}
+#endif
+
+/* Write S of length L to the strtab buffer. L must include the ending
+ NUL, if that's what you want. */
+
+unsigned
+elf_out::strtab_write (const char *s, unsigned l)
+{
+ if (strtab.pos + l > strtab.size)
+ data::simple_memory.grow (strtab, strtab.pos + l, false);
+ memcpy (strtab.buffer + strtab.pos, s, l);
+ unsigned res = strtab.pos;
+ strtab.pos += l;
+ return res;
+}
+
+/* Write qualified name of decl. INNER >0 if this is a definition, <0
+ if this is a qualifier of an outer name. */
+
+void
+elf_out::strtab_write (tree decl, int inner)
+{
+ tree ctx = CP_DECL_CONTEXT (decl);
+ if (TYPE_P (ctx))
+ ctx = TYPE_NAME (ctx);
+ if (ctx != global_namespace)
+ strtab_write (ctx, -1);
+
+ tree name = DECL_NAME (decl);
+ if (!name)
+ name = DECL_ASSEMBLER_NAME_RAW (decl);
+ strtab_write (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name));
+
+ if (inner)
+ strtab_write (&"::{}"[inner+1], 2);
+}
+
+/* Map IDENTIFIER IDENT to strtab offset. Inserts into strtab if not
+ already there. */
+
+unsigned
+elf_out::name (tree ident)
+{
+ unsigned res = 0;
+ if (ident)
+ {
+ bool existed;
+ int *slot = &identtab.get_or_insert (ident, &existed);
+ if (!existed)
+ *slot = strtab_write (IDENTIFIER_POINTER (ident),
+ IDENTIFIER_LENGTH (ident) + 1);
+ res = *slot;
+ }
+ return res;
+}
+
+/* Map LITERAL to strtab offset. Does not detect duplicates and
+ expects LITERAL to remain live until strtab is written out. */
+
+unsigned
+elf_out::name (const char *literal)
+{
+ return strtab_write (literal, strlen (literal) + 1);
+}
+
+/* Map a DECL's qualified name to strtab offset. Does not detect
+ duplicates. */
+
+unsigned
+elf_out::qualified_name (tree decl, bool is_defn)
+{
+ gcc_checking_assert (DECL_P (decl) && decl != global_namespace);
+ unsigned result = strtab.pos;
+
+ strtab_write (decl, is_defn);
+ strtab_write ("", 1);
+
+ return result;
+}
+
+/* Add section to file. Return section number. TYPE & NAME identify
+ the section. OFF and SIZE identify the file location of its
+ data. FLAGS contains additional info. */
+
+unsigned
+elf_out::add (unsigned type, unsigned name, unsigned off, unsigned size,
+ unsigned flags)
+{
+ gcc_checking_assert (!(off & (SECTION_ALIGN - 1)));
+ if (sectab.pos + sizeof (section) > sectab.size)
+ data::simple_memory.grow (sectab, sectab.pos + sizeof (section), false);
+ section *sec = reinterpret_cast<section *> (sectab.buffer + sectab.pos);
+ memset (sec, 0, sizeof (section));
+ sec->type = type;
+ sec->flags = flags;
+ sec->name = name;
+ sec->offset = off;
+ sec->size = size;
+ if (flags & SHF_STRINGS)
+ sec->entsize = 1;
+
+ unsigned res = sectab.pos;
+ sectab.pos += sizeof (section);
+ return res / sizeof (section);
+}
+
+/* Pad to the next alignment boundary, then write BUFFER to disk.
+ Return the position of the start of the write, or zero on failure. */
+
+unsigned
+elf_out::write (const data &buffer)
+{
+#if MAPPED_WRITING
+ /* HDR is always mapped. */
+ if (&buffer != &hdr)
+ {
+ bytes_out out (this);
+ grow (out, buffer.pos, true);
+ if (out.buffer)
+ memcpy (out.buffer, buffer.buffer, buffer.pos);
+ shrink (out);
+ }
+ else
+ /* We should have been aligned during the first allocation. */
+ gcc_checking_assert (!(pos & (SECTION_ALIGN - 1)));
+#else
+ if (::write (fd, buffer.buffer, buffer.pos) != ssize_t (buffer.pos))
+ {
+ set_error (errno);
+ return 0;
+ }
+#endif
+ unsigned res = pos;
+ pos += buffer.pos;
+
+ if (unsigned padding = -pos & (SECTION_ALIGN - 1))
+ {
+#if !MAPPED_WRITING
+ /* Align the section on disk, should help the necessary copies.
+ fseeking to extend is non-portable. */
+ static char zero[SECTION_ALIGN];
+ if (::write (fd, &zero, padding) != ssize_t (padding))
+ set_error (errno);
+#endif
+ pos += padding;
+ }
+ return res;
+}
+
+/* Write a streaming buffer. It must be using us as an allocator. */
+
+#if MAPPED_WRITING
+unsigned
+elf_out::write (const bytes_out &buf)
+{
+ gcc_checking_assert (buf.memory == this);
+ /* A directly mapped buffer. */
+ gcc_checking_assert (buf.buffer - hdr.buffer >= 0
+ && buf.buffer - hdr.buffer + buf.size <= extent);
+ unsigned res = pos;
+ pos += buf.pos;
+
+ /* Align up. We're not going to advance into the next page. */
+ pos += -pos & (SECTION_ALIGN - 1);
+
+ return res;
+}
+#endif
+
+/* Write data and add section. STRING_P is true for a string
+ section, false for PROGBITS. NAME identifies the section (0 is the
+ empty name). DATA is the contents. Return section number or 0 on
+ failure (0 is the undef section). */
+
+unsigned
+elf_out::add (const bytes_out &data, bool string_p, unsigned name)
+{
+ unsigned off = write (data);
+
+ return add (string_p ? SHT_STRTAB : SHT_PROGBITS, name,
+ off, data.pos, string_p ? SHF_STRINGS : SHF_NONE);
+}
+
+/* Begin writing the file. Initialize the section table and write an
+ empty header. Return false on failure. */
+
+bool
+elf_out::begin ()
+{
+ if (!parent::begin ())
+ return false;
+
+ /* Let the allocators pick a default. */
+ data::simple_memory.grow (strtab, 0, false);
+ data::simple_memory.grow (sectab, 0, false);
+
+ /* The string table starts with an empty string. */
+ name ("");
+
+ /* Create the UNDEF section. */
+ add (SHT_NONE);
+
+#if MAPPED_WRITING
+ /* Start a mapping. */
+ create_mapping (EXPERIMENT (page_size,
+ (32767 + page_size) & ~(page_size - 1)));
+ if (!hdr.buffer)
+ return false;
+#endif
+
+ /* Write an empty header. */
+ grow (hdr, sizeof (header), true);
+ header *h = reinterpret_cast<header *> (hdr.buffer);
+ memset (h, 0, sizeof (header));
+ hdr.pos = hdr.size;
+ write (hdr);
+ return !get_error ();
+}
+
+/* Finish writing the file. Write out the string & section tables.
+ Fill in the header. Return true on error. */
+
+bool
+elf_out::end ()
+{
+ if (fd >= 0)
+ {
+ /* Write the string table. */
+ unsigned strnam = name (".strtab");
+ unsigned stroff = write (strtab);
+ unsigned strndx = add (SHT_STRTAB, strnam, stroff, strtab.pos,
+ SHF_STRINGS);
+
+ /* Store escape values in section[0]. */
+ if (strndx >= SHN_LORESERVE)
+ {
+ reinterpret_cast<section *> (sectab.buffer)->link = strndx;
+ strndx = SHN_XINDEX;
+ }
+ unsigned shnum = sectab.pos / sizeof (section);
+ if (shnum >= SHN_LORESERVE)
+ {
+ reinterpret_cast<section *> (sectab.buffer)->size = shnum;
+ shnum = SHN_XINDEX;
+ }
+
+ unsigned shoff = write (sectab);
+
+#if MAPPED_WRITING
+ if (offset)
+ {
+ remove_mapping ();
+ offset = 0;
+ create_mapping ((sizeof (header) + page_size - 1) & ~(page_size - 1),
+ false);
+ }
+ unsigned length = pos;
+#else
+ if (lseek (fd, 0, SEEK_SET) < 0)
+ set_error (errno);
+#endif
+ /* Write header. */
+ if (!get_error ())
+ {
+ /* Write the correct header now. */
+ header *h = reinterpret_cast<header *> (hdr.buffer);
+ h->ident.magic[0] = 0x7f;
+ h->ident.magic[1] = 'E'; /* Elrond */
+ h->ident.magic[2] = 'L'; /* is an */
+ h->ident.magic[3] = 'F'; /* elf. */
+ h->ident.klass = MY_CLASS;
+ h->ident.data = MY_ENDIAN;
+ h->ident.version = EV_CURRENT;
+ h->ident.osabi = OSABI_NONE;
+ h->type = ET_NONE;
+ h->machine = EM_NONE;
+ h->version = EV_CURRENT;
+ h->shoff = shoff;
+ h->ehsize = sizeof (header);
+ h->shentsize = sizeof (section);
+ h->shnum = shnum;
+ h->shstrndx = strndx;
+
+ pos = 0;
+ write (hdr);
+ }
+
+#if MAPPED_WRITING
+ remove_mapping ();
+ if (ftruncate (fd, length))
+ set_error (errno);
+#endif
+ }
+
+ data::simple_memory.shrink (sectab);
+ data::simple_memory.shrink (strtab);
+
+ return parent::end ();
+}
+
+/********************************************************************/
+
+/* A dependency set. This is used during stream out to determine the
+ connectivity of the graph. Every namespace-scope declaration that
+ needs writing has a depset. The depset is filled with the (depsets
+ of) declarations within this module that it references. For a
+ declaration that'll generally be named types. For definitions
+ it'll also be declarations in the body.
+
+ From that we can convert the graph to a DAG, via determining the
+ Strongly Connected Clusters. Each cluster is streamed
+ independently, and thus we achieve lazy loading.
+
+ Other decls that get a depset are namespaces themselves and
+ unnameable declarations. */
+
+class depset {
+private:
+ tree entity; /* Entity, or containing namespace. */
+ uintptr_t discriminator; /* Flags or identifier. */
+
+public:
+ /* The kinds of entity the depset could describe. The ordering is
+ significant, see entity_kind_name. */
+ enum entity_kind
+ {
+ EK_DECL, /* A decl. */
+ EK_SPECIALIZATION, /* A specialization. */
+ EK_PARTIAL, /* A partial specialization. */
+ EK_USING, /* A using declaration (at namespace scope). */
+ EK_NAMESPACE, /* A namespace. */
+ EK_REDIRECT, /* Redirect to a template_decl. */
+ EK_EXPLICIT_HWM,
+ EK_BINDING = EK_EXPLICIT_HWM, /* Implicitly encoded. */
+ EK_FOR_BINDING, /* A decl being inserted for a binding. */
+ EK_INNER_DECL, /* A decl defined outside of it's imported
+ context. */
+ EK_DIRECT_HWM = EK_PARTIAL + 1,
+
+ EK_BITS = 3 /* Only need to encode below EK_EXPLICIT_HWM. */
+ };
+
+private:
+ /* Placement of bit fields in discriminator. */
+ enum disc_bits
+ {
+ DB_ZERO_BIT, /* Set to disambiguate identifier from flags */
+ DB_SPECIAL_BIT, /* First dep slot is special. */
+ DB_KIND_BIT, /* Kind of the entity. */
+ DB_KIND_BITS = EK_BITS,
+ DB_DEFN_BIT = DB_KIND_BIT + DB_KIND_BITS,
+ DB_IS_MEMBER_BIT, /* Is an out-of-class member. */
+ DB_IS_INTERNAL_BIT, /* It is an (erroneous)
+ internal-linkage entity. */
+ DB_REFS_INTERNAL_BIT, /* Refers to an internal-linkage
+ entity. */
+ DB_IMPORTED_BIT, /* An imported entity. */
+ DB_UNREACHED_BIT, /* A yet-to-be reached entity. */
+ DB_HIDDEN_BIT, /* A hidden binding. */
+ /* The following bits are not independent, but enumerating them is
+ awkward. */
+ DB_ALIAS_TMPL_INST_BIT, /* An alias template instantiation. */
+ DB_ALIAS_SPEC_BIT, /* Specialization of an alias template
+ (in both spec tables). */
+ DB_TYPE_SPEC_BIT, /* Specialization in the type table.
+ */
+ DB_FRIEND_SPEC_BIT, /* An instantiated template friend. */
+ };
+
+public:
+ /* The first slot is special for EK_SPECIALIZATIONS it is a
+ spec_entry pointer. It is not relevant for the SCC
+ determination. */
+ vec<depset *> deps; /* Depsets we reference. */
+
+public:
+ unsigned cluster; /* Strongly connected cluster, later entity number */
+ unsigned section; /* Section written to. */
+ /* During SCC construction, section is lowlink, until the depset is
+ removed from the stack. See Tarjan algorithm for details. */
+
+private:
+ /* Construction via factories. Destruction via hash traits. */
+ depset (tree entity);
+ ~depset ();
+
+public:
+ static depset *make_binding (tree, tree);
+ static depset *make_entity (tree, entity_kind, bool = false);
+ /* Late setting a binding name -- /then/ insert into hash! */
+ inline void set_binding_name (tree name)
+ {
+ gcc_checking_assert (!get_name ());
+ discriminator = reinterpret_cast<uintptr_t> (name);
+ }
+
+private:
+ template<unsigned I> void set_flag_bit ()
+ {
+ gcc_checking_assert (I < 2 || !is_binding ());
+ discriminator |= 1u << I;
+ }
+ template<unsigned I> void clear_flag_bit ()
+ {
+ gcc_checking_assert (I < 2 || !is_binding ());
+ discriminator &= ~(1u << I);
+ }
+ template<unsigned I> bool get_flag_bit () const
+ {
+ gcc_checking_assert (I < 2 || !is_binding ());
+ return bool ((discriminator >> I) & 1);
+ }
+
+public:
+ bool is_binding () const
+ {
+ return !get_flag_bit<DB_ZERO_BIT> ();
+ }
+ entity_kind get_entity_kind () const
+ {
+ if (is_binding ())
+ return EK_BINDING;
+ return entity_kind ((discriminator >> DB_KIND_BIT) & ((1u << EK_BITS) - 1));
+ }
+ const char *entity_kind_name () const;
+
+public:
+ bool has_defn () const
+ {
+ return get_flag_bit<DB_DEFN_BIT> ();
+ }
+
+public:
+ bool is_member () const
+ {
+ return get_flag_bit<DB_IS_MEMBER_BIT> ();
+ }
+public:
+ bool is_internal () const
+ {
+ return get_flag_bit<DB_IS_INTERNAL_BIT> ();
+ }
+ bool refs_internal () const
+ {
+ return get_flag_bit<DB_REFS_INTERNAL_BIT> ();
+ }
+ bool is_import () const
+ {
+ return get_flag_bit<DB_IMPORTED_BIT> ();
+ }
+ bool is_unreached () const
+ {
+ return get_flag_bit<DB_UNREACHED_BIT> ();
+ }
+ bool is_alias_tmpl_inst () const
+ {
+ return get_flag_bit<DB_ALIAS_TMPL_INST_BIT> ();
+ }
+ bool is_alias () const
+ {
+ return get_flag_bit<DB_ALIAS_SPEC_BIT> ();
+ }
+ bool is_hidden () const
+ {
+ return get_flag_bit<DB_HIDDEN_BIT> ();
+ }
+ bool is_type_spec () const
+ {
+ return get_flag_bit<DB_TYPE_SPEC_BIT> ();
+ }
+ bool is_friend_spec () const
+ {
+ return get_flag_bit<DB_FRIEND_SPEC_BIT> ();
+ }
+
+public:
+ /* We set these bit outside of depset. */
+ void set_hidden_binding ()
+ {
+ set_flag_bit<DB_HIDDEN_BIT> ();
+ }
+ void clear_hidden_binding ()
+ {
+ clear_flag_bit<DB_HIDDEN_BIT> ();
+ }
+
+public:
+ bool is_special () const
+ {
+ return get_flag_bit<DB_SPECIAL_BIT> ();
+ }
+ void set_special ()
+ {
+ set_flag_bit<DB_SPECIAL_BIT> ();
+ }
+
+public:
+ tree get_entity () const
+ {
+ return entity;
+ }
+ tree get_name () const
+ {
+ gcc_checking_assert (is_binding ());
+ return reinterpret_cast <tree> (discriminator);
+ }
+
+public:
+ /* Traits for a hash table of pointers to bindings. */
+ struct traits {
+ /* Each entry is a pointer to a depset. */
+ typedef depset *value_type;
+ /* We lookup by container:maybe-identifier pair. */
+ typedef std::pair<tree,tree> compare_type;
+
+ static const bool empty_zero_p = true;
+
+ /* hash and equality for compare_type. */
+ inline static hashval_t hash (const compare_type &p)
+ {
+ hashval_t h = pointer_hash<tree_node>::hash (p.first);
+ if (p.second)
+ {
+ hashval_t nh = IDENTIFIER_HASH_VALUE (p.second);
+ h = iterative_hash_hashval_t (h, nh);
+ }
+ return h;
+ }
+ inline static bool equal (const value_type b, const compare_type &p)
+ {
+ if (b->entity != p.first)
+ return false;
+
+ if (p.second)
+ return b->discriminator == reinterpret_cast<uintptr_t> (p.second);
+ else
+ return !b->is_binding ();
+ }
+
+ /* (re)hasher for a binding itself. */
+ inline static hashval_t hash (const value_type b)
+ {
+ hashval_t h = pointer_hash<tree_node>::hash (b->entity);
+ if (b->is_binding ())
+ {
+ hashval_t nh = IDENTIFIER_HASH_VALUE (b->get_name ());
+ h = iterative_hash_hashval_t (h, nh);
+ }
+ return h;
+ }
+
+ /* Empty via NULL. */
+ static inline void mark_empty (value_type &p) {p = NULL;}
+ static inline bool is_empty (value_type p) {return !p;}
+
+ /* Nothing is deletable. Everything is insertable. */
+ static bool is_deleted (value_type) { return false; }
+ static void mark_deleted (value_type) { gcc_unreachable (); }
+
+ /* We own the entities in the hash table. */
+ static void remove (value_type p)
+ {
+ delete (p);
+ }
+ };
+
+public:
+ class hash : public hash_table<traits> {
+ typedef traits::compare_type key_t;
+ typedef hash_table<traits> parent;
+
+ public:
+ vec<depset *> worklist; /* Worklist of decls to walk. */
+ hash *chain; /* Original table. */
+ depset *current; /* Current depset being depended. */
+ unsigned section; /* When writing out, the section. */
+ bool sneakoscope; /* Detecting dark magic (of a voldemort). */
+ bool reached_unreached; /* We reached an unreached entity. */
+
+ public:
+ hash (size_t size, hash *c = NULL)
+ : parent (size), chain (c), current (NULL), section (0),
+ sneakoscope (false), reached_unreached (false)
+ {
+ worklist.create (size);
+ }
+ ~hash ()
+ {
+ worklist.release ();
+ }
+
+ public:
+ bool is_key_order () const
+ {
+ return chain != NULL;
+ }
+
+ private:
+ depset **entity_slot (tree entity, bool = true);
+ depset **binding_slot (tree ctx, tree name, bool = true);
+ depset *maybe_add_declaration (tree decl);
+
+ public:
+ depset *find_dependency (tree entity);
+ depset *find_binding (tree ctx, tree name);
+ depset *make_dependency (tree decl, entity_kind);
+ void add_dependency (depset *);
+
+ public:
+ void add_mergeable (depset *);
+ depset *add_dependency (tree decl, entity_kind);
+ void add_namespace_context (depset *, tree ns);
+
+ private:
+ static bool add_binding_entity (tree, WMB_Flags, void *);
+
+ public:
+ bool add_namespace_entities (tree ns, bitmap partitions);
+ void add_specializations (bool decl_p);
+ void add_partial_entities (vec<tree, va_gc> *);
+ void add_class_entities (vec<tree, va_gc> *);
+
+ public:
+ void find_dependencies ();
+ bool finalize_dependencies ();
+ vec<depset *> connect ();
+ };
+
+public:
+ struct tarjan {
+ vec<depset *> result;
+ vec<depset *> stack;
+ unsigned index;
+
+ tarjan (unsigned size)
+ : index (0)
+ {
+ result.create (size);
+ stack.create (50);
+ }
+ ~tarjan ()
+ {
+ gcc_assert (!stack.length ());
+ stack.release ();
+ }
+
+ public:
+ void connect (depset *);
+ };
+};
+
+inline
+depset::depset (tree entity)
+ :entity (entity), discriminator (0), cluster (0), section (0)
+{
+ deps.create (0);
+}
+
+inline
+depset::~depset ()
+{
+ deps.release ();
+}
+
+const char *
+depset::entity_kind_name () const
+{
+ /* Same order as entity_kind. */
+ static const char *const names[] =
+ {"decl", "specialization", "partial", "using",
+ "namespace", "redirect", "binding"};
+ entity_kind kind = get_entity_kind ();
+ gcc_checking_assert (kind < sizeof (names) / sizeof(names[0]));
+ return names[kind];
+}
+
+/* Create a depset for a namespace binding NS::NAME. */
+
+depset *depset::make_binding (tree ns, tree name)
+{
+ depset *binding = new depset (ns);
+
+ binding->discriminator = reinterpret_cast <uintptr_t> (name);
+
+ return binding;
+}
+
+depset *depset::make_entity (tree entity, entity_kind ek, bool is_defn)
+{
+ depset *r = new depset (entity);
+
+ r->discriminator = ((1 << DB_ZERO_BIT)
+ | (ek << DB_KIND_BIT)
+ | is_defn << DB_DEFN_BIT);
+
+ return r;
+}
+
+/* Values keyed to some unsigned integer. This is not GTY'd, so if
+ T is tree they must be reachable via some other path. */
+
+template<typename T>
+class uintset {
+public:
+ unsigned key; /* Entity index of the other entity. */
+
+ /* Payload. */
+ unsigned allocp2 : 5; /* log(2) allocated pending */
+ unsigned num : 27; /* Number of pending. */
+
+ /* Trailing array of values. */
+ T values[1];
+
+public:
+ /* Even with ctors, we're very pod-like. */
+ uintset (unsigned uid)
+ : key (uid), allocp2 (0), num (0)
+ {
+ }
+ /* Copy constructor, which is exciting because of the trailing
+ array. */
+ uintset (const uintset *from)
+ {
+ size_t size = (offsetof (uintset, values)
+ + sizeof (uintset::values) * from->num);
+ memmove (this, from, size);
+ if (from->num)
+ allocp2++;
+ }
+
+public:
+ struct traits : delete_ptr_hash<uintset> {
+ typedef unsigned compare_type;
+ typedef typename delete_ptr_hash<uintset>::value_type value_type;
+
+ /* Hash and equality for compare_type. */
+ inline static hashval_t hash (const compare_type k)
+ {
+ return hashval_t (k);
+ }
+ inline static hashval_t hash (const value_type v)
+ {
+ return hash (v->key);
+ }
+
+ inline static bool equal (const value_type v, const compare_type k)
+ {
+ return v->key == k;
+ }
+ };
+
+public:
+ class hash : public hash_table<traits>
+ {
+ typedef typename traits::compare_type key_t;
+ typedef hash_table<traits> parent;
+
+ public:
+ hash (size_t size)
+ : parent (size)
+ {
+ }
+ ~hash ()
+ {
+ }
+
+ private:
+ uintset **find_slot (key_t key, insert_option insert)
+ {
+ return this->find_slot_with_hash (key, traits::hash (key), insert);
+ }
+
+ public:
+ uintset *get (key_t key, bool extract = false);
+ bool add (key_t key, T value);
+ uintset *create (key_t key, unsigned num, T init = 0);
+ };
+};
+
+/* Add VALUE to KEY's uintset, creating it if necessary. Returns true
+ if we created the uintset. */
+
+template<typename T>
+bool
+uintset<T>::hash::add (typename uintset<T>::hash::key_t key, T value)
+{
+ uintset **slot = this->find_slot (key, INSERT);
+ uintset *set = *slot;
+ bool is_new = !set;
+
+ if (is_new || set->num == (1u << set->allocp2))
+ {
+ if (set)
+ {
+ unsigned n = set->num * 2;
+ size_t new_size = (offsetof (uintset, values)
+ + sizeof (uintset (0u).values) * n);
+ uintset *new_set = new (::operator new (new_size)) uintset (set);
+ delete set;
+ set = new_set;
+ }
+ else
+ set = new (::operator new (sizeof (*set))) uintset (key);
+ *slot = set;
+ }
+
+ set->values[set->num++] = value;
+
+ return is_new;
+}
+
+template<typename T>
+uintset<T> *
+uintset<T>::hash::create (typename uintset<T>::hash::key_t key, unsigned num,
+ T init)
+{
+ unsigned p2alloc = 0;
+ for (unsigned v = num; v != 1; v = (v >> 1) | (v & 1))
+ p2alloc++;
+
+ size_t new_size = (offsetof (uintset, values)
+ + (sizeof (uintset (0u).values) << p2alloc));
+ uintset *set = new (::operator new (new_size)) uintset (key);
+ set->allocp2 = p2alloc;
+ set->num = num;
+ while (num--)
+ set->values[num] = init;
+
+ uintset **slot = this->find_slot (key, INSERT);
+ gcc_checking_assert (!*slot);
+ *slot = set;
+
+ return set;
+}
+
+/* Locate KEY's uintset, potentially removing it from the hash table */
+
+template<typename T>
+uintset<T> *
+uintset<T>::hash::get (typename uintset<T>::hash::key_t key, bool extract)
+{
+ uintset *res = NULL;
+
+ if (uintset **slot = this->find_slot (key, NO_INSERT))
+ {
+ res = *slot;
+ if (extract)
+ /* We need to remove the pendset without deleting it. */
+ traits::mark_deleted (*slot);
+ }
+
+ return res;
+}
+
+/* Entities keyed to some other entity. When we load the other
+ entity, we mark it in some way to indicate there are further
+ entities to load when you start looking inside it. For instance
+ template specializations are keyed to their most general template.
+ When we instantiate that, we need to know all the partial
+ specializations (to pick the right template), and all the known
+ specializations (to avoid reinstantiating it, and/or whether it's
+ extern). The values split into two ranges. If !MSB set, indices
+ into the entity array. If MSB set, an indirection to another
+ pendset. */
+
+typedef uintset<unsigned> pendset;
+static pendset::hash *pending_table;
+
+/* Some entities are attached to another entitity for ODR purposes.
+ For example, at namespace scope, 'inline auto var = []{};', that
+ lambda is attached to 'var', and follows its ODRness. */
+typedef uintset<tree> attachset;
+static attachset::hash *attached_table;
+
+/********************************************************************/
+/* Tree streaming. The tree streaming is very specific to the tree
+ structures themselves. A tag indicates the kind of tree being
+ streamed. -ve tags indicate backreferences to already-streamed
+ trees. Backreferences are auto-numbered. */
+
+/* Tree tags. */
+enum tree_tag {
+ tt_null, /* NULL_TREE. */
+ tt_fixed, /* Fixed vector index. */
+
+ tt_node, /* By-value node. */
+ tt_decl, /* By-value mergeable decl. */
+ tt_tpl_parm, /* Template parm. */
+
+ /* The ordering of the following 4 is relied upon in
+ trees_out::tree_node. */
+ tt_id, /* Identifier node. */
+ tt_conv_id, /* Conversion operator name. */
+ tt_anon_id, /* Anonymous name. */
+ tt_lambda_id, /* Lambda name. */
+
+ tt_typedef_type, /* A (possibly implicit) typedefed type. */
+ tt_derived_type, /* A type derived from another type. */
+ tt_variant_type, /* A variant of another type. */
+
+ tt_tinfo_var, /* Typeinfo object. */
+ tt_tinfo_typedef, /* Typeinfo typedef. */
+ tt_ptrmem_type, /* Pointer to member type. */
+
+ tt_parm, /* Function parameter or result. */
+ tt_enum_value, /* An enum value. */
+ tt_enum_decl, /* An enum decl. */
+ tt_data_member, /* Data member/using-decl. */
+
+ tt_binfo, /* A BINFO. */
+ tt_vtable, /* A vtable. */
+ tt_thunk, /* A thunk. */
+ tt_clone_ref,
+
+ tt_entity, /* A extra-cluster entity. */
+
+ tt_template, /* The TEMPLATE_RESULT of a template. */
+};
+
+enum walk_kind {
+ WK_none, /* No walk to do (a back- or fixed-ref happened). */
+ WK_normal, /* Normal walk (by-name if possible). */
+
+ WK_value, /* By-value walk. */
+};
+
+enum merge_kind
+{
+ MK_unique, /* Known unique. */
+ MK_named, /* Found by CTX, NAME + maybe_arg types etc. */
+ MK_field, /* Found by CTX and index on TYPE_FIELDS */
+ MK_vtable, /* Found by CTX and index on TYPE_VTABLES */
+ MK_as_base, /* Found by CTX. */
+
+ MK_partial,
+
+ MK_enum, /* Found by CTX, & 1stMemberNAME. */
+ MK_attached, /* Found by attachee & index. */
+
+ MK_friend_spec, /* Like named, but has a tmpl & args too. */
+ MK_local_friend, /* Found by CTX, index. */
+
+ MK_indirect_lwm = MK_enum,
+
+ /* Template specialization kinds below. These are all found via
+ primary template and specialization args. */
+ MK_template_mask = 0x10, /* A template specialization. */
+
+ MK_tmpl_decl_mask = 0x4, /* In decl table. */
+ MK_tmpl_alias_mask = 0x2, /* Also in type table */
+
+ MK_tmpl_tmpl_mask = 0x1, /* We want TEMPLATE_DECL. */
+
+ MK_type_spec = MK_template_mask,
+ MK_type_tmpl_spec = MK_type_spec | MK_tmpl_tmpl_mask,
+
+ MK_decl_spec = MK_template_mask | MK_tmpl_decl_mask,
+ MK_decl_tmpl_spec = MK_decl_spec | MK_tmpl_tmpl_mask,
+
+ MK_alias_spec = MK_decl_spec | MK_tmpl_alias_mask,
+
+ MK_hwm = 0x20
+};
+/* This is more than a debugging array. NULLs are used to determine
+ an invalid merge_kind number. */
+static char const *const merge_kind_name[MK_hwm] =
+ {
+ "unique", "named", "field", "vtable", /* 0...3 */
+ "asbase", "partial", "enum", "attached", /* 4...7 */
+
+ "friend spec", "local friend", NULL, NULL, /* 8...11 */
+ NULL, NULL, NULL, NULL,
+
+ "type spec", "type tmpl spec", /* 16,17 type (template). */
+ NULL, NULL,
+
+ "decl spec", "decl tmpl spec", /* 20,21 decl (template). */
+ "alias spec", NULL, /* 22,23 alias. */
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ };
+
+/* Mergeable entity location data. */
+struct merge_key {
+ cp_ref_qualifier ref_q : 2;
+ unsigned index;
+
+ tree ret; /* Return type, if appropriate. */
+ tree args; /* Arg types, if appropriate. */
+
+ tree constraints; /* Constraints. */
+
+ merge_key ()
+ :ref_q (REF_QUAL_NONE), index (0),
+ ret (NULL_TREE), args (NULL_TREE),
+ constraints (NULL_TREE)
+ {
+ }
+};
+
+struct duplicate_hash : nodel_ptr_hash<tree_node>
+{
+ inline static hashval_t hash (value_type decl)
+ {
+ if (TREE_CODE (decl) == TREE_BINFO)
+ decl = TYPE_NAME (BINFO_TYPE (decl));
+ return hashval_t (DECL_UID (decl));
+ }
+};
+
+/* Hashmap of merged duplicates. Usually decls, but can contain
+ BINFOs. */
+typedef hash_map<tree,uintptr_t,
+ simple_hashmap_traits<duplicate_hash,uintptr_t> >
+duplicate_hash_map;
+
+/* Tree stream reader. Note that reading a stream doesn't mark the
+ read trees with TREE_VISITED. Thus it's quite safe to have
+ multiple concurrent readers. Which is good, because lazy
+ loading. */
+class trees_in : public bytes_in {
+ typedef bytes_in parent;
+
+private:
+ module_state *state; /* Module being imported. */
+ vec<tree> back_refs; /* Back references. */
+ duplicate_hash_map *duplicates; /* Map from existings to duplicate. */
+ vec<tree> post_decls; /* Decls to post process. */
+ unsigned unused; /* Inhibit any interior TREE_USED
+ marking. */
+
+public:
+ trees_in (module_state *);
+ ~trees_in ();
+
+public:
+ int insert (tree);
+ tree back_ref (int);
+
+private:
+ tree start (unsigned = 0);
+
+public:
+ /* Needed for binfo writing */
+ bool core_bools (tree);
+
+private:
+ /* Stream tree_core, lang_decl_specific and lang_type_specific
+ bits. */
+ bool core_vals (tree);
+ bool lang_type_bools (tree);
+ bool lang_type_vals (tree);
+ bool lang_decl_bools (tree);
+ bool lang_decl_vals (tree);
+ bool lang_vals (tree);
+ bool tree_node_bools (tree);
+ bool tree_node_vals (tree);
+ tree tree_value ();
+ tree decl_value ();
+ tree tpl_parm_value ();
+
+private:
+ tree chained_decls (); /* Follow DECL_CHAIN. */
+ vec<tree, va_heap> *vec_chained_decls ();
+ vec<tree, va_gc> *tree_vec (); /* vec of tree. */
+ vec<tree_pair_s, va_gc> *tree_pair_vec (); /* vec of tree_pair. */
+ tree tree_list (bool has_purpose);
+
+public:
+ /* Read a tree node. */
+ tree tree_node (bool is_use = false);
+
+private:
+ bool install_entity (tree decl);
+ tree tpl_parms (unsigned &tpl_levels);
+ bool tpl_parms_fini (tree decl, unsigned tpl_levels);
+ bool tpl_header (tree decl, unsigned *tpl_levels);
+ int fn_parms_init (tree);
+ void fn_parms_fini (int tag, tree fn, tree existing, bool has_defn);
+ unsigned add_indirect_tpl_parms (tree);
+public:
+ bool add_indirects (tree);
+
+public:
+ /* Serialize various definitions. */
+ bool read_definition (tree decl);
+
+private:
+ bool is_matching_decl (tree existing, tree decl);
+ static bool install_implicit_member (tree decl);
+ bool read_function_def (tree decl, tree maybe_template);
+ bool read_var_def (tree decl, tree maybe_template);
+ bool read_class_def (tree decl, tree maybe_template);
+ bool read_enum_def (tree decl, tree maybe_template);
+
+public:
+ tree decl_container ();
+ tree key_mergeable (int tag, merge_kind, tree decl, tree inner, tree type,
+ tree container, bool is_mod);
+ unsigned binfo_mergeable (tree *);
+
+private:
+ uintptr_t *find_duplicate (tree existing);
+ void register_duplicate (tree decl, tree existing);
+ /* Mark as an already diagnosed bad duplicate. */
+ void unmatched_duplicate (tree existing)
+ {
+ *find_duplicate (existing) |= 1;
+ }
+
+public:
+ bool is_duplicate (tree decl)
+ {
+ return find_duplicate (decl) != NULL;
+ }
+ tree maybe_duplicate (tree decl)
+ {
+ if (uintptr_t *dup = find_duplicate (decl))
+ return reinterpret_cast<tree> (*dup & ~uintptr_t (1));
+ return decl;
+ }
+ tree odr_duplicate (tree decl, bool has_defn);
+
+public:
+ /* Return the next decl to postprocess, or NULL. */
+ tree post_process ()
+ {
+ return post_decls.length () ? post_decls.pop () : NULL_TREE;
+ }
+private:
+ /* Register DECL for postprocessing. */
+ void post_process (tree decl)
+ {
+ post_decls.safe_push (decl);
+ }
+
+private:
+ void assert_definition (tree, bool installing);
+};
+
+trees_in::trees_in (module_state *state)
+ :parent (), state (state), unused (0)
+{
+ duplicates = NULL;
+ back_refs.create (500);
+ post_decls.create (0);
+}
+
+trees_in::~trees_in ()
+{
+ delete (duplicates);
+ back_refs.release ();
+ post_decls.release ();
+}
+
+/* Tree stream writer. */
+class trees_out : public bytes_out {
+ typedef bytes_out parent;
+
+private:
+ module_state *state; /* The module we are writing. */
+ ptr_int_hash_map tree_map; /* Trees to references */
+ depset::hash *dep_hash; /* Dependency table. */
+ int ref_num; /* Back reference number. */
+ unsigned section;
+#if CHECKING_P
+ int importedness; /* Checker that imports not occurring
+ inappropriately. */
+#endif
+
+public:
+ trees_out (allocator *, module_state *, depset::hash &deps, unsigned sec = 0);
+ ~trees_out ();
+
+private:
+ void mark_trees ();
+ void unmark_trees ();
+
+public:
+ /* Hey, let's ignore the well known STL iterator idiom. */
+ void begin ();
+ unsigned end (elf_out *sink, unsigned name, unsigned *crc_ptr);
+ void end ();
+
+public:
+ enum tags
+ {
+ tag_backref = -1, /* Upper bound on the backrefs. */
+ tag_value = 0, /* Write by value. */
+ tag_fixed /* Lower bound on the fixed trees. */
+ };
+
+public:
+ bool is_key_order () const
+ {
+ return dep_hash->is_key_order ();
+ }
+
+public:
+ int insert (tree, walk_kind = WK_normal);
+
+private:
+ void start (tree, bool = false);
+
+private:
+ walk_kind ref_node (tree);
+public:
+ int get_tag (tree);
+ void set_importing (int i ATTRIBUTE_UNUSED)
+ {
+#if CHECKING_P
+ importedness = i;
+#endif
+ }
+
+private:
+ void core_bools (tree);
+ void core_vals (tree);
+ void lang_type_bools (tree);
+ void lang_type_vals (tree);
+ void lang_decl_bools (tree);
+ void lang_decl_vals (tree);
+ void lang_vals (tree);
+ void tree_node_bools (tree);
+ void tree_node_vals (tree);
+
+private:
+ void chained_decls (tree);
+ void vec_chained_decls (tree);
+ void tree_vec (vec<tree, va_gc> *);
+ void tree_pair_vec (vec<tree_pair_s, va_gc> *);
+ void tree_list (tree, bool has_purpose);
+
+public:
+ /* Mark a node for by-value walking. */
+ void mark_by_value (tree);
+
+public:
+ void tree_node (tree);
+
+private:
+ void install_entity (tree decl, depset *);
+ void tpl_parms (tree parms, unsigned &tpl_levels);
+ void tpl_parms_fini (tree decl, unsigned tpl_levels);
+ void fn_parms_fini (tree) {}
+ unsigned add_indirect_tpl_parms (tree);
+public:
+ void add_indirects (tree);
+ void fn_parms_init (tree);
+ void tpl_header (tree decl, unsigned *tpl_levels);
+
+public:
+ merge_kind get_merge_kind (tree decl, depset *maybe_dep);
+ tree decl_container (tree decl);
+ void key_mergeable (int tag, merge_kind, tree decl, tree inner,
+ tree container, depset *maybe_dep);
+ void binfo_mergeable (tree binfo);
+
+private:
+ bool decl_node (tree, walk_kind ref);
+ void type_node (tree);
+ void tree_value (tree);
+ void tpl_parm_value (tree);
+
+public:
+ void decl_value (tree, depset *);
+
+public:
+ /* Serialize various definitions. */
+ void write_definition (tree decl);
+ void mark_declaration (tree decl, bool do_defn);
+
+private:
+ void mark_function_def (tree decl);
+ void mark_var_def (tree decl);
+ void mark_class_def (tree decl);
+ void mark_enum_def (tree decl);
+ void mark_class_member (tree decl, bool do_defn = true);
+ void mark_binfos (tree type);
+
+private:
+ void write_var_def (tree decl);
+ void write_function_def (tree decl);
+ void write_class_def (tree decl);
+ void write_enum_def (tree decl);
+
+private:
+ static void assert_definition (tree);
+
+public:
+ static void instrument ();
+
+private:
+ /* Tree instrumentation. */
+ static unsigned tree_val_count;
+ static unsigned decl_val_count;
+ static unsigned back_ref_count;
+ static unsigned null_count;
+};
+
+/* Instrumentation counters. */
+unsigned trees_out::tree_val_count;
+unsigned trees_out::decl_val_count;
+unsigned trees_out::back_ref_count;
+unsigned trees_out::null_count;
+
+trees_out::trees_out (allocator *mem, module_state *state, depset::hash &deps,
+ unsigned section)
+ :parent (mem), state (state), tree_map (500),
+ dep_hash (&deps), ref_num (0), section (section)
+{
+#if CHECKING_P
+ importedness = 0;
+#endif
+}
+
+trees_out::~trees_out ()
+{
+}
+
+/********************************************************************/
+/* Location. We're aware of the line-map concept and reproduce it
+ here. Each imported module allocates a contiguous span of ordinary
+ maps, and of macro maps. adhoc maps are serialized by contents,
+ not pre-allocated. The scattered linemaps of a module are
+ coalesced when writing. */
+
+
+/* I use half-open [first,second) ranges. */
+typedef std::pair<unsigned,unsigned> range_t;
+
+/* A range of locations. */
+typedef std::pair<location_t,location_t> loc_range_t;
+
+/* Spans of the line maps that are occupied by this TU. I.e. not
+ within imports. Only extended when in an interface unit.
+ Interval zero corresponds to the forced header linemap(s). This
+ is a singleton object. */
+
+class loc_spans {
+public:
+ /* An interval of line maps. The line maps here represent a contiguous
+ non-imported range. */
+ struct span {
+ loc_range_t ordinary; /* Ordinary map location range. */
+ loc_range_t macro; /* Macro map location range. */
+ int ordinary_delta; /* Add to ordinary loc to get serialized loc. */
+ int macro_delta; /* Likewise for macro loc. */
+ };
+
+private:
+ vec<span> *spans;
+
+public:
+ loc_spans ()
+ /* Do not preallocate spans, as that causes
+ --enable-detailed-mem-stats problems. */
+ : spans (nullptr)
+ {
+ }
+ ~loc_spans ()
+ {
+ delete spans;
+ }
+
+public:
+ span &operator[] (unsigned ix)
+ {
+ return (*spans)[ix];
+ }
+ unsigned length () const
+ {
+ return spans->length ();
+ }
+
+public:
+ bool init_p () const
+ {
+ return spans != nullptr;
+ }
+ /* Initializer. */
+ void init (const line_maps *lmaps, const line_map_ordinary *map);
+
+ /* Slightly skewed preprocessed files can cause us to miss an
+ initialization in some places. Fallback initializer. */
+ void maybe_init ()
+ {
+ if (!init_p ())
+ init (line_table, nullptr);
+ }
+
+public:
+ enum {
+ SPAN_RESERVED = 0, /* Reserved (fixed) locations. */
+ SPAN_FIRST = 1, /* LWM of locations to stream */
+ SPAN_MAIN = 2 /* Main file and onwards. */
+ };
+
+public:
+ location_t main_start () const
+ {
+ return (*spans)[SPAN_MAIN].ordinary.first;
+ }
+
+public:
+ void open (location_t);
+ void close ();
+
+public:
+ /* Propagate imported linemaps to us, if needed. */
+ bool maybe_propagate (module_state *import, location_t loc);
+
+public:
+ const span *ordinary (location_t);
+ const span *macro (location_t);
+};
+
+static loc_spans spans;
+
+/********************************************************************/
+/* Data needed by a module during the process of loading. */
+struct GTY(()) slurping {
+
+ /* Remap import's module numbering to our numbering. Values are
+ shifted by 1. Bit0 encodes if the import is direct. */
+ vec<unsigned, va_heap, vl_embed> *
+ GTY((skip)) remap; /* Module owner remapping. */
+
+ elf_in *GTY((skip)) from; /* The elf loader. */
+
+ /* This map is only for header imports themselves -- the global
+ headers bitmap hold it for the current TU. */
+ bitmap headers; /* Transitive set of direct imports, including
+ self. Used for macro visibility and
+ priority. */
+
+ /* These objects point into the mmapped area, unless we're not doing
+ that, or we got frozen or closed. In those cases they point to
+ buffers we own. */
+ bytes_in macro_defs; /* Macro definitions. */
+ bytes_in macro_tbl; /* Macro table. */
+
+ /* Location remapping. first->ordinary, second->macro. */
+ range_t GTY((skip)) loc_deltas;
+
+ unsigned current; /* Section currently being loaded. */
+ unsigned remaining; /* Number of lazy sections yet to read. */
+ unsigned lru; /* An LRU counter. */
+
+ public:
+ slurping (elf_in *);
+ ~slurping ();
+
+ public:
+ /* Close the ELF file, if it's open. */
+ void close ()
+ {
+ if (from)
+ {
+ from->end ();
+ delete from;
+ from = NULL;
+ }
+ }
+
+ public:
+ void release_macros ();
+
+ public:
+ void alloc_remap (unsigned size)
+ {
+ gcc_assert (!remap);
+ vec_safe_reserve (remap, size);
+ for (unsigned ix = size; ix--;)
+ remap->quick_push (0);
+ }
+ unsigned remap_module (unsigned owner)
+ {
+ if (owner < remap->length ())
+ return (*remap)[owner] >> 1;
+ return 0;
+ }
+
+ public:
+ /* GC allocation. But we must explicitly delete it. */
+ static void *operator new (size_t x)
+ {
+ return ggc_alloc_atomic (x);
+ }
+ static void operator delete (void *p)
+ {
+ ggc_free (p);
+ }
+};
+
+slurping::slurping (elf_in *from)
+ : remap (NULL), from (from),
+ headers (BITMAP_GGC_ALLOC ()), macro_defs (), macro_tbl (),
+ loc_deltas (0, 0),
+ current (~0u), remaining (0), lru (0)
+{
+}
+
+slurping::~slurping ()
+{
+ vec_free (remap);
+ remap = NULL;
+ release_macros ();
+ close ();
+}
+
+void slurping::release_macros ()
+{
+ if (macro_defs.size)
+ elf_in::release (from, macro_defs);
+ if (macro_tbl.size)
+ elf_in::release (from, macro_tbl);
+}
+
+/* Information about location maps used during writing. */
+
+struct location_map_info {
+ range_t num_maps;
+
+ unsigned max_range;
+};
+
+/* Flage for extensions that end up being streamed. */
+
+enum streamed_extensions {
+ SE_OPENMP = 1 << 0,
+ SE_BITS = 1
+};
+
+/********************************************************************/
+struct module_state_config;
+
+/* Increasing levels of loadedness. */
+enum module_loadedness {
+ ML_NONE, /* Not loaded. */
+ ML_CONFIG, /* Config loaed. */
+ ML_PREPROCESSOR, /* Preprocessor loaded. */
+ ML_LANGUAGE, /* Language loaded. */
+};
+
+/* Increasing levels of directness (toplevel) of import. */
+enum module_directness {
+ MD_NONE, /* Not direct. */
+ MD_PARTITION_DIRECT, /* Direct import of a partition. */
+ MD_DIRECT, /* Direct import. */
+ MD_PURVIEW_DIRECT, /* direct import in purview. */
+};
+
+/* State of a particular module. */
+
+class GTY((chain_next ("%h.parent"), for_user)) module_state {
+ public:
+ /* We always import & export ourselves. */
+ bitmap imports; /* Transitive modules we're importing. */
+ bitmap exports; /* Subset of that, that we're exporting. */
+
+ module_state *parent;
+ tree name; /* Name of the module. */
+
+ slurping *slurp; /* Data for loading. */
+
+ const char *flatname; /* Flatname of module. */
+ char *filename; /* CMI Filename */
+
+ /* Indices into the entity_ary. */
+ unsigned entity_lwm;
+ unsigned entity_num;
+
+ /* Location ranges for this module. adhoc-locs are decomposed, so
+ don't have a range. */
+ loc_range_t GTY((skip)) ordinary_locs;
+ loc_range_t GTY((skip)) macro_locs;
+
+ /* LOC is first set too the importing location. When initially
+ loaded it refers to a module loc whose parent is the importing
+ location. */
+ location_t loc; /* Location referring to module itself. */
+ unsigned crc; /* CRC we saw reading it in. */
+
+ unsigned mod; /* Module owner number. */
+ unsigned remap; /* Remapping during writing. */
+
+ unsigned short subst; /* Mangle subst if !0. */
+
+ /* How loaded this module is. */
+ enum module_loadedness loadedness : 2;
+
+ bool module_p : 1; /* /The/ module of this TU. */
+ bool header_p : 1; /* Is a header unit. */
+ bool interface_p : 1; /* An interface. */
+ bool partition_p : 1; /* A partition. */
+
+ /* How directly this module is imported. */
+ enum module_directness directness : 2;
+
+ bool exported_p : 1; /* directness != MD_NONE && exported. */
+ bool cmi_noted_p : 1; /* We've told the user about the CMI, don't
+ do it again */
+ bool call_init_p : 1; /* This module's global initializer needs
+ calling. */
+ /* Record extensions emitted or permitted. */
+ unsigned extensions : SE_BITS;
+ /* 12 bits used, 4 bits remain */
+
+ public:
+ module_state (tree name, module_state *, bool);
+ ~module_state ();
+
+ public:
+ void release ()
+ {
+ imports = exports = NULL;
+ slurped ();
+ }
+ void slurped ()
+ {
+ delete slurp;
+ slurp = NULL;
+ }
+ elf_in *from () const
+ {
+ return slurp->from;
+ }
+
+ public:
+ /* Kind of this module. */
+ bool is_module () const
+ {
+ return module_p;
+ }
+ bool is_header () const
+ {
+ return header_p;
+ }
+ bool is_interface () const
+ {
+ return interface_p;
+ }
+ bool is_partition () const
+ {
+ return partition_p;
+ }
+
+ /* How this module is used in the current TU. */
+ bool is_exported () const
+ {
+ return exported_p;
+ }
+ bool is_direct () const
+ {
+ return directness >= MD_DIRECT;
+ }
+ bool is_purview_direct () const
+ {
+ return directness == MD_PURVIEW_DIRECT;
+ }
+ bool is_partition_direct () const
+ {
+ return directness == MD_PARTITION_DIRECT;
+ }
+
+ public:
+ /* Is this not a real module? */
+ bool is_rooted () const
+ {
+ return loc != UNKNOWN_LOCATION;
+ }
+
+ public:
+ bool check_not_purview (location_t loc);
+
+ public:
+ void mangle (bool include_partition);
+
+ public:
+ void set_import (module_state const *, bool is_export);
+ void announce (const char *) const;
+
+ public:
+ /* Read and write module. */
+ void write (elf_out *to, cpp_reader *);
+ bool read_initial (cpp_reader *);
+ bool read_preprocessor (bool);
+ bool read_language (bool);
+
+ public:
+ /* Read a section. */
+ bool load_section (unsigned snum, binding_slot *mslot);
+ /* Lazily read a section. */
+ bool lazy_load (unsigned index, binding_slot *mslot);
+
+ public:
+ /* Juggle a limited number of file numbers. */
+ static void freeze_an_elf ();
+ bool maybe_defrost ();
+
+ public:
+ void maybe_completed_reading ();
+ bool check_read (bool outermost, bool ok);
+
+ private:
+ /* The README, for human consumption. */
+ void write_readme (elf_out *to, cpp_reader *,
+ const char *dialect, unsigned extensions);
+ void write_env (elf_out *to);
+
+ private:
+ /* Import tables. */
+ void write_imports (bytes_out &cfg, bool direct);
+ unsigned read_imports (bytes_in &cfg, cpp_reader *, line_maps *maps);
+
+ private:
+ void write_imports (elf_out *to, unsigned *crc_ptr);
+ bool read_imports (cpp_reader *, line_maps *);
+
+ private:
+ void write_partitions (elf_out *to, unsigned, unsigned *crc_ptr);
+ bool read_partitions (unsigned);
+
+ private:
+ void write_config (elf_out *to, struct module_state_config &, unsigned crc);
+ bool read_config (struct module_state_config &);
+ static void write_counts (elf_out *to, unsigned [], unsigned *crc_ptr);
+ bool read_counts (unsigned []);
+
+ public:
+ void note_cmi_name ();
+
+ private:
+ static unsigned write_bindings (elf_out *to, vec<depset *> depsets,
+ unsigned *crc_ptr);
+ bool read_bindings (unsigned count, unsigned lwm, unsigned hwm);
+
+ static void write_namespace (bytes_out &sec, depset *ns_dep);
+ tree read_namespace (bytes_in &sec);
+
+ void write_namespaces (elf_out *to, vec<depset *> spaces,
+ unsigned, unsigned *crc_ptr);
+ bool read_namespaces (unsigned);
+
+ unsigned write_cluster (elf_out *to, depset *depsets[], unsigned size,
+ depset::hash &, unsigned *counts, unsigned *crc_ptr);
+ bool read_cluster (unsigned snum);
+
+ private:
+ unsigned write_inits (elf_out *to, depset::hash &, unsigned *crc_ptr);
+ bool read_inits (unsigned count);
+
+ private:
+ void write_pendings (elf_out *to, vec<depset *> depsets,
+ depset::hash &, unsigned count, unsigned *crc_ptr);
+ bool read_pendings (unsigned count);
+
+ private:
+ void write_entities (elf_out *to, vec<depset *> depsets,
+ unsigned count, unsigned *crc_ptr);
+ bool read_entities (unsigned count, unsigned lwm, unsigned hwm);
+
+ private:
+ location_map_info write_prepare_maps (module_state_config *);
+ bool read_prepare_maps (const module_state_config *);
+
+ void write_ordinary_maps (elf_out *to, location_map_info &,
+ module_state_config *, bool, unsigned *crc_ptr);
+ bool read_ordinary_maps ();
+ void write_macro_maps (elf_out *to, location_map_info &,
+ module_state_config *, unsigned *crc_ptr);
+ bool read_macro_maps ();
+
+ private:
+ void write_define (bytes_out &, const cpp_macro *, bool located = true);
+ cpp_macro *read_define (bytes_in &, cpp_reader *, bool located = true) const;
+ unsigned write_macros (elf_out *to, cpp_reader *, unsigned *crc_ptr);
+ bool read_macros ();
+ void install_macros ();
+
+ public:
+ void import_macros ();
+
+ public:
+ static void undef_macro (cpp_reader *, location_t, cpp_hashnode *);
+ static cpp_macro *deferred_macro (cpp_reader *, location_t, cpp_hashnode *);
+
+ public:
+ void write_location (bytes_out &, location_t);
+ location_t read_location (bytes_in &) const;
+
+ public:
+ void set_flatname ();
+ const char *get_flatname () const
+ {
+ return flatname;
+ }
+ location_t imported_from () const;
+
+ public:
+ void set_filename (const Cody::Packet &);
+ bool do_import (cpp_reader *, bool outermost);
+};
+
+/* Hash module state by name. This cannot be a member of
+ module_state, because of GTY restrictions. We never delete from
+ the hash table, but ggc_ptr_hash doesn't support that
+ simplification. */
+
+struct module_state_hash : ggc_ptr_hash<module_state> {
+ typedef std::pair<tree,uintptr_t> compare_type; /* {name,parent} */
+
+ static inline hashval_t hash (const value_type m);
+ static inline hashval_t hash (const compare_type &n);
+ static inline bool equal (const value_type existing,
+ const compare_type &candidate);
+};
+
+module_state::module_state (tree name, module_state *parent, bool partition)
+ : imports (BITMAP_GGC_ALLOC ()), exports (BITMAP_GGC_ALLOC ()),
+ parent (parent), name (name), slurp (NULL),
+ flatname (NULL), filename (NULL),
+ entity_lwm (~0u >> 1), entity_num (0),
+ ordinary_locs (0, 0), macro_locs (0, 0),
+ loc (UNKNOWN_LOCATION),
+ crc (0), mod (MODULE_UNKNOWN), remap (0), subst (0)
+{
+ loadedness = ML_NONE;
+
+ module_p = header_p = interface_p = partition_p = false;
+
+ directness = MD_NONE;
+ exported_p = false;
+
+ cmi_noted_p = false;
+ call_init_p = false;
+
+ partition_p = partition;
+
+ extensions = 0;
+ if (name && TREE_CODE (name) == STRING_CST)
+ {
+ header_p = true;
+
+ const char *string = TREE_STRING_POINTER (name);
+ gcc_checking_assert (string[0] == '.'
+ ? IS_DIR_SEPARATOR (string[1])
+ : IS_ABSOLUTE_PATH (string));
+ }
+
+ gcc_checking_assert (!(parent && header_p));
+}
+
+module_state::~module_state ()
+{
+ release ();
+}
+
+/* Hash module state. */
+static hashval_t
+module_name_hash (const_tree name)
+{
+ if (TREE_CODE (name) == STRING_CST)
+ return htab_hash_string (TREE_STRING_POINTER (name));
+ else
+ return IDENTIFIER_HASH_VALUE (name);
+}
+
+hashval_t
+module_state_hash::hash (const value_type m)
+{
+ hashval_t ph = pointer_hash<void>::hash
+ (reinterpret_cast<void *> (reinterpret_cast<uintptr_t> (m->parent)
+ | m->is_partition ()));
+ hashval_t nh = module_name_hash (m->name);
+ return iterative_hash_hashval_t (ph, nh);
+}
+
+/* Hash a name. */
+hashval_t
+module_state_hash::hash (const compare_type &c)
+{
+ hashval_t ph = pointer_hash<void>::hash (reinterpret_cast<void *> (c.second));
+ hashval_t nh = module_name_hash (c.first);
+
+ return iterative_hash_hashval_t (ph, nh);
+}
+
+bool
+module_state_hash::equal (const value_type existing,
+ const compare_type &candidate)
+{
+ uintptr_t ep = (reinterpret_cast<uintptr_t> (existing->parent)
+ | existing->is_partition ());
+ if (ep != candidate.second)
+ return false;
+
+ /* Identifier comparison is by pointer. If the string_csts happen
+ to be the same object, then they're equal too. */
+ if (existing->name == candidate.first)
+ return true;
+
+ /* If neither are string csts, they can't be equal. */
+ if (TREE_CODE (candidate.first) != STRING_CST
+ || TREE_CODE (existing->name) != STRING_CST)
+ return false;
+
+ /* String equality. */
+ if (TREE_STRING_LENGTH (existing->name)
+ == TREE_STRING_LENGTH (candidate.first)
+ && !memcmp (TREE_STRING_POINTER (existing->name),
+ TREE_STRING_POINTER (candidate.first),
+ TREE_STRING_LENGTH (existing->name)))
+ return true;
+
+ return false;
+}
+
+/********************************************************************/
+/* Global state */
+
+/* Mapper name. */
+static const char *module_mapper_name;
+
+/* CMI repository path and workspace. */
+static char *cmi_repo;
+static size_t cmi_repo_length;
+static char *cmi_path;
+static size_t cmi_path_alloc;
+
+/* Count of available and loaded clusters. */
+static unsigned available_clusters;
+static unsigned loaded_clusters;
+
+/* What the current TU is. */
+unsigned module_kind;
+
+/* Number of global init calls needed. */
+unsigned num_init_calls_needed = 0;
+
+/* Global trees. */
+static const std::pair<tree *, unsigned> global_tree_arys[] =
+ {
+ std::pair<tree *, unsigned> (sizetype_tab, stk_type_kind_last),
+ std::pair<tree *, unsigned> (integer_types, itk_none),
+ std::pair<tree *, unsigned> (global_trees, TI_MODULE_HWM),
+ std::pair<tree *, unsigned> (c_global_trees, CTI_MODULE_HWM),
+ std::pair<tree *, unsigned> (cp_global_trees, CPTI_MODULE_HWM),
+ std::pair<tree *, unsigned> (NULL, 0)
+ };
+static GTY(()) vec<tree, va_gc> *fixed_trees;
+static unsigned global_crc;
+
+/* Lazy loading can open many files concurrently, there are
+ per-process limits on that. We pay attention to the process limit,
+ and attempt to increase it when we run out. Otherwise we use an
+ LRU scheme to figure out who to flush. Note that if the import
+ graph /depth/ exceeds lazy_limit, we'll exceed the limit. */
+static unsigned lazy_lru; /* LRU counter. */
+static unsigned lazy_open; /* Number of open modules */
+static unsigned lazy_limit; /* Current limit of open modules. */
+static unsigned lazy_hard_limit; /* Hard limit on open modules. */
+/* Account for source, assembler and dump files & directory searches.
+ We don't keep the source file's open, so we don't have to account
+ for #include depth. I think dump files are opened and closed per
+ pass, but ICBW. */
+#define LAZY_HEADROOM 15 /* File descriptor headroom. */
+
+/* Vector of module state. Indexed by OWNER. Has at least 2 slots. */
+static GTY(()) vec<module_state *, va_gc> *modules;
+
+/* Hash of module state, findable by {name, parent}. */
+static GTY(()) hash_table<module_state_hash> *modules_hash;
+
+/* Map of imported entities. We map DECL_UID to index of entity
+ vector. */
+typedef hash_map<unsigned/*UID*/, unsigned/*index*/,
+ simple_hashmap_traits<int_hash<unsigned,0>, unsigned>
+ > entity_map_t;
+static entity_map_t *entity_map;
+/* Doesn't need GTYing, because any tree referenced here is also
+ findable by, symbol table, specialization table, return type of
+ reachable function. */
+static vec<binding_slot, va_heap, vl_embed> *entity_ary;
+
+/* Members entities of imported classes that are defined in this TU.
+ These are where the entity's context is not from the current TU.
+ We need to emit the definition (but not the enclosing class).
+
+ We could find these by walking ALL the imported classes that we
+ could provide a member definition. But that's expensive,
+ especially when you consider lazy implicit member declarations,
+ which could be ANY imported class. */
+static GTY(()) vec<tree, va_gc> *class_members;
+
+/* The same problem exists for class template partial
+ specializations. Now that we have constraints, the invariant of
+ expecting them in the instantiation table no longer holds. One of
+ the constrained partial specializations will be there, but the
+ others not so much. It's not even an unconstrained partial
+ spacialization in the table :( so any partial template declaration
+ is added to this list too. */
+static GTY(()) vec<tree, va_gc> *partial_specializations;
+
+/********************************************************************/
+
+/* Our module mapper (created lazily). */
+module_client *mapper;
+
+static module_client *make_mapper (location_t loc);
+inline module_client *get_mapper (location_t loc)
+{
+ auto *res = mapper;
+ if (!res)
+ res = make_mapper (loc);
+ return res;
+}
+
+/********************************************************************/
+static tree
+get_clone_target (tree decl)
+{
+ tree target;
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ tree res_orig = DECL_CLONED_FUNCTION (DECL_TEMPLATE_RESULT (decl));
+
+ target = DECL_TI_TEMPLATE (res_orig);
+ }
+ else
+ target = DECL_CLONED_FUNCTION (decl);
+
+ gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (target));
+
+ return target;
+}
+
+/* Like FOR_EACH_CLONE, but will walk cloned templates. */
+#define FOR_EVERY_CLONE(CLONE, FN) \
+ if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (FN)); \
+ else \
+ for (CLONE = DECL_CHAIN (FN); \
+ CLONE && DECL_CLONED_FUNCTION_P (CLONE); \
+ CLONE = DECL_CHAIN (CLONE))
+
+/* It'd be nice if USE_TEMPLATE was a field of template_info
+ (a) it'd solve the enum case dealt with below,
+ (b) both class templates and decl templates would store this in the
+ same place
+ (c) this function wouldn't need the by-ref arg, which is annoying. */
+
+static tree
+node_template_info (tree decl, int &use)
+{
+ tree ti = NULL_TREE;
+ int use_tpl = -1;
+ if (DECL_IMPLICIT_TYPEDEF_P (decl))
+ {
+ tree type = TREE_TYPE (decl);
+
+ ti = TYPE_TEMPLATE_INFO (type);
+ if (ti)
+ {
+ if (TYPE_LANG_SPECIFIC (type))
+ use_tpl = CLASSTYPE_USE_TEMPLATE (type);
+ else
+ {
+ /* An enum, where we don't explicitly encode use_tpl.
+ If the containing context (a type or a function), is
+ an ({im,ex}plicit) instantiation, then this is too.
+ If it's a partial or explicit specialization, then
+ this is not!. */
+ tree ctx = CP_DECL_CONTEXT (decl);
+ if (TYPE_P (ctx))
+ ctx = TYPE_NAME (ctx);
+ node_template_info (ctx, use);
+ use_tpl = use != 2 ? use : 0;
+ }
+ }
+ }
+ else if (DECL_LANG_SPECIFIC (decl)
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == FIELD_DECL
+ || TREE_CODE (decl) == TEMPLATE_DECL))
+ {
+ use_tpl = DECL_USE_TEMPLATE (decl);
+ ti = DECL_TEMPLATE_INFO (decl);
+ }
+
+ use = use_tpl;
+ return ti;
+}
+
+/* Find the index in entity_ary for an imported DECL. It should
+ always be there, but bugs can cause it to be missing, and that can
+ crash the crash reporting -- let's not do that! When streaming
+ out we place entities from this module there too -- with negated
+ indices. */
+
+static unsigned
+import_entity_index (tree decl, bool null_ok = false)
+{
+ if (unsigned *slot = entity_map->get (DECL_UID (decl)))
+ return *slot;
+
+ gcc_checking_assert (null_ok);
+ return ~(~0u >> 1);
+}
+
+/* Find the module for an imported entity at INDEX in the entity ary.
+ There must be one. */
+
+static module_state *
+import_entity_module (unsigned index)
+{
+ if (index > ~(~0u >> 1))
+ /* This is an index for an exported entity. */
+ return (*modules)[0];
+
+ unsigned pos = 1;
+ unsigned len = modules->length () - pos;
+ while (len)
+ {
+ unsigned half = len / 2;
+ module_state *probe = (*modules)[pos + half];
+ if (index < probe->entity_lwm)
+ len = half;
+ else if (index < probe->entity_lwm + probe->entity_num)
+ return probe;
+ else
+ {
+ pos += half + 1;
+ len = len - (half + 1);
+ }
+ }
+ gcc_unreachable ();
+}
+
+
+/********************************************************************/
+/* A dumping machinery. */
+
+class dumper {
+public:
+ enum {
+ LOCATION = TDF_LINENO, /* -lineno:Source location streaming. */
+ DEPEND = TDF_GRAPH, /* -graph:Dependency graph construction. */
+ CLUSTER = TDF_BLOCKS, /* -blocks:Clusters. */
+ TREE = TDF_UID, /* -uid:Tree streaming. */
+ MERGE = TDF_ALIAS, /* -alias:Mergeable Entities. */
+ ELF = TDF_ASMNAME, /* -asmname:Elf data. */
+ MACRO = TDF_VOPS /* -vops:Macros. */
+ };
+
+private:
+ struct impl {
+ typedef vec<module_state *, va_heap, vl_embed> stack_t;
+
+ FILE *stream; /* Dump stream. */
+ unsigned indent; /* Local indentation. */
+ bool bol; /* Beginning of line. */
+ stack_t stack; /* Trailing array of module_state. */
+
+ bool nested_name (tree); /* Dump a name following DECL_CONTEXT. */
+ };
+
+public:
+ /* The dumper. */
+ impl *dumps;
+ dump_flags_t flags;
+
+public:
+ /* Push/pop module state dumping. */
+ unsigned push (module_state *);
+ void pop (unsigned);
+
+public:
+ /* Change local indentation. */
+ void indent ()
+ {
+ if (dumps)
+ dumps->indent++;
+ }
+ void outdent ()
+ {
+ if (dumps)
+ {
+ gcc_checking_assert (dumps->indent);
+ dumps->indent--;
+ }
+ }
+
+public:
+ /* Is dump enabled?. */
+ bool operator () (int mask = 0)
+ {
+ if (!dumps || !dumps->stream)
+ return false;
+ if (mask && !(mask & flags))
+ return false;
+ return true;
+ }
+ /* Dump some information. */
+ bool operator () (const char *, ...);
+};
+
+/* The dumper. */
+static dumper dump = {0, dump_flags_t (0)};
+
+/* Push to dumping M. Return previous indentation level. */
+
+unsigned
+dumper::push (module_state *m)
+{
+ FILE *stream = NULL;
+ if (!dumps || !dumps->stack.length ())
+ {
+ stream = dump_begin (module_dump_id, &flags);
+ if (!stream)
+ return 0;
+ }
+
+ if (!dumps || !dumps->stack.space (1))
+ {
+ /* Create or extend the dump implementor. */
+ unsigned current = dumps ? dumps->stack.length () : 0;
+ unsigned count = current ? current * 2 : EXPERIMENT (1, 20);
+ size_t alloc = (offsetof (impl, stack)
+ + impl::stack_t::embedded_size (count));
+ dumps = XRESIZEVAR (impl, dumps, alloc);
+ dumps->stack.embedded_init (count, current);
+ }
+ if (stream)
+ dumps->stream = stream;
+
+ unsigned n = dumps->indent;
+ dumps->indent = 0;
+ dumps->bol = true;
+ dumps->stack.quick_push (m);
+ if (m)
+ {
+ module_state *from = NULL;
+
+ if (dumps->stack.length () > 1)
+ from = dumps->stack[dumps->stack.length () - 2];
+ else
+ dump ("");
+ dump (from ? "Starting module %M (from %M)"
+ : "Starting module %M", m, from);
+ }
+
+ return n;
+}
+
+/* Pop from dumping. Restore indentation to N. */
+
+void dumper::pop (unsigned n)
+{
+ if (!dumps)
+ return;
+
+ gcc_checking_assert (dump () && !dumps->indent);
+ if (module_state *m = dumps->stack[dumps->stack.length () - 1])
+ {
+ module_state *from = (dumps->stack.length () > 1
+ ? dumps->stack[dumps->stack.length () - 2] : NULL);
+ dump (from ? "Finishing module %M (returning to %M)"
+ : "Finishing module %M", m, from);
+ }
+ dumps->stack.pop ();
+ dumps->indent = n;
+ if (!dumps->stack.length ())
+ {
+ dump_end (module_dump_id, dumps->stream);
+ dumps->stream = NULL;
+ }
+}
+
+/* Dump a nested name for arbitrary tree T. Sometimes it won't have a
+ name. */
+
+bool
+dumper::impl::nested_name (tree t)
+{
+ tree ti = NULL_TREE;
+ int origin = -1;
+ tree name = NULL_TREE;
+
+ if (t && TREE_CODE (t) == TREE_BINFO)
+ t = BINFO_TYPE (t);
+
+ if (t && TYPE_P (t))
+ t = TYPE_NAME (t);
+
+ if (t && DECL_P (t))
+ {
+ if (t == global_namespace || DECL_TEMPLATE_PARM_P (t))
+ ;
+ else if (tree ctx = DECL_CONTEXT (t))
+ if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
+ || nested_name (ctx))
+ fputs ("::", stream);
+
+ int use_tpl;
+ ti = node_template_info (t, use_tpl);
+ if (ti && TREE_CODE (TI_TEMPLATE (ti)) == TEMPLATE_DECL
+ && (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti)) == t))
+ t = TI_TEMPLATE (ti);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ fputs ("template ", stream);
+
+ if (DECL_LANG_SPECIFIC (t) && DECL_MODULE_IMPORT_P (t))
+ {
+ /* We need to be careful here, so as to not explode on
+ inconsistent data -- we're probably debugging, because
+ Something Is Wrong. */
+ unsigned index = import_entity_index (t, true);
+ if (!(index & ~(~0u >> 1)))
+ origin = import_entity_module (index)->mod;
+ else if (index > ~(~0u >> 1))
+ /* An imported partition member that we're emitting. */
+ origin = 0;
+ else
+ origin = -2;
+ }
+
+ name = DECL_NAME (t) ? DECL_NAME (t)
+ : HAS_DECL_ASSEMBLER_NAME_P (t) ? DECL_ASSEMBLER_NAME_RAW (t)
+ : NULL_TREE;
+ }
+ else
+ name = t;
+
+ if (name)
+ switch (TREE_CODE (name))
+ {
+ default:
+ fputs ("#unnamed#", stream);
+ break;
+
+ case IDENTIFIER_NODE:
+ fwrite (IDENTIFIER_POINTER (name), 1, IDENTIFIER_LENGTH (name), stream);
+ break;
+
+ case INTEGER_CST:
+ print_hex (wi::to_wide (name), stream);
+ break;
+
+ case STRING_CST:
+ /* If TREE_TYPE is NULL, this is a raw string. */
+ fwrite (TREE_STRING_POINTER (name), 1,
+ TREE_STRING_LENGTH (name) - (TREE_TYPE (name) != NULL_TREE),
+ stream);
+ break;
+ }
+ else
+ fputs ("#null#", stream);
+
+ if (origin >= 0)
+ {
+ const module_state *module = (*modules)[origin];
+ fprintf (stream, "@%s:%d", !module ? "" : !module->name ? "(unnamed)"
+ : module->get_flatname (), origin);
+ }
+ else if (origin == -2)
+ fprintf (stream, "@???");
+
+ if (ti)
+ {
+ tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti));
+ fputs ("<", stream);
+ if (args)
+ for (int ix = 0; ix != TREE_VEC_LENGTH (args); ix++)
+ {
+ if (ix)
+ fputs (",", stream);
+ nested_name (TREE_VEC_ELT (args, ix));
+ }
+ fputs (">", stream);
+ }
+
+ return true;
+}
+
+/* Formatted dumping. FORMAT begins with '+' do not emit a trailing
+ new line. (Normally it is appended.)
+ Escapes:
+ %C - tree_code
+ %I - identifier
+ %M - module_state
+ %N - name -- DECL_NAME
+ %P - context:name pair
+ %R - unsigned:unsigned ratio
+ %S - symbol -- DECL_ASSEMBLER_NAME
+ %U - long unsigned
+ %V - version
+ --- the following are printf-like, but without its flexibility
+ %d - decimal int
+ %p - pointer
+ %s - string
+ %u - unsigned int
+ %x - hex int
+
+ We do not implement the printf modifiers. */
+
+bool
+dumper::operator () (const char *format, ...)
+{
+ if (!(*this) ())
+ return false;
+
+ bool no_nl = format[0] == '+';
+ format += no_nl;
+
+ if (dumps->bol)
+ {
+ /* Module import indent. */
+ if (unsigned depth = dumps->stack.length () - 1)
+ {
+ const char *prefix = ">>>>";
+ fprintf (dumps->stream, (depth <= strlen (prefix)
+ ? &prefix[strlen (prefix) - depth]
+ : ">.%d.>"), depth);
+ }
+
+ /* Local indent. */
+ if (unsigned indent = dumps->indent)
+ {
+ const char *prefix = " ";
+ fprintf (dumps->stream, (indent <= strlen (prefix)
+ ? &prefix[strlen (prefix) - indent]
+ : " .%d. "), indent);
+ }
+ dumps->bol = false;
+ }
+
+ va_list args;
+ va_start (args, format);
+ while (const char *esc = strchr (format, '%'))
+ {
+ fwrite (format, 1, (size_t)(esc - format), dumps->stream);
+ format = ++esc;
+ switch (*format++)
+ {
+ default:
+ gcc_unreachable ();
+
+ case '%':
+ fputc ('%', dumps->stream);
+ break;
+
+ case 'C': /* Code */
+ {
+ tree_code code = (tree_code)va_arg (args, unsigned);
+ fputs (get_tree_code_name (code), dumps->stream);
+ }
+ break;
+
+ case 'I': /* Identifier. */
+ {
+ tree t = va_arg (args, tree);
+ dumps->nested_name (t);
+ }
+ break;
+
+ case 'M': /* Module. */
+ {
+ const char *str = "(none)";
+ if (module_state *m = va_arg (args, module_state *))
+ {
+ if (!m->is_rooted ())
+ str = "(detached)";
+ else
+ str = m->get_flatname ();
+ }
+ fputs (str, dumps->stream);
+ }
+ break;
+
+ case 'N': /* Name. */
+ {
+ tree t = va_arg (args, tree);
+ if (t && TREE_CODE (t) == OVERLOAD)
+ t = OVL_FIRST (t);
+ fputc ('\'', dumps->stream);
+ dumps->nested_name (t);
+ fputc ('\'', dumps->stream);
+ }
+ break;
+
+ case 'P': /* Pair. */
+ {
+ tree ctx = va_arg (args, tree);
+ tree name = va_arg (args, tree);
+ fputc ('\'', dumps->stream);
+ dumps->nested_name (ctx);
+ if (ctx && ctx != global_namespace)
+ fputs ("::", dumps->stream);
+ dumps->nested_name (name);
+ fputc ('\'', dumps->stream);
+ }
+ break;
+
+ case 'R': /* Ratio */
+ {
+ unsigned a = va_arg (args, unsigned);
+ unsigned b = va_arg (args, unsigned);
+ fprintf (dumps->stream, "%.1f", (float) a / (b + !b));
+ }
+ break;
+
+ case 'S': /* Symbol name */
+ {
+ tree t = va_arg (args, tree);
+ if (t && TYPE_P (t))
+ t = TYPE_NAME (t);
+ if (t && HAS_DECL_ASSEMBLER_NAME_P (t)
+ && DECL_ASSEMBLER_NAME_SET_P (t))
+ {
+ fputc ('(', dumps->stream);
+ fputs (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t)),
+ dumps->stream);
+ fputc (')', dumps->stream);
+ }
+ }
+ break;
+
+ case 'U': /* long unsigned. */
+ {
+ unsigned long u = va_arg (args, unsigned long);
+ fprintf (dumps->stream, "%lu", u);
+ }
+ break;
+
+ case 'V': /* Verson. */
+ {
+ unsigned v = va_arg (args, unsigned);
+ verstr_t string;
+
+ version2string (v, string);
+ fputs (string, dumps->stream);
+ }
+ break;
+
+ case 'c': /* Character. */
+ {
+ int c = va_arg (args, int);
+ fputc (c, dumps->stream);
+ }
+ break;
+
+ case 'd': /* Decimal Int. */
+ {
+ int d = va_arg (args, int);
+ fprintf (dumps->stream, "%d", d);
+ }
+ break;
+
+ case 'p': /* Pointer. */
+ {
+ void *p = va_arg (args, void *);
+ fprintf (dumps->stream, "%p", p);
+ }
+ break;
+
+ case 's': /* String. */
+ {
+ const char *s = va_arg (args, char *);
+ gcc_checking_assert (s);
+ fputs (s, dumps->stream);
+ }
+ break;
+
+ case 'u': /* Unsigned. */
+ {
+ unsigned u = va_arg (args, unsigned);
+ fprintf (dumps->stream, "%u", u);
+ }
+ break;
+
+ case 'x': /* Hex. */
+ {
+ unsigned x = va_arg (args, unsigned);
+ fprintf (dumps->stream, "%x", x);
+ }
+ break;
+ }
+ }
+ fputs (format, dumps->stream);
+ va_end (args);
+ if (!no_nl)
+ {
+ dumps->bol = true;
+ fputc ('\n', dumps->stream);
+ }
+ return true;
+}
+
+struct note_def_cache_hasher : ggc_cache_ptr_hash<tree_node>
+{
+ static int keep_cache_entry (tree t)
+ {
+ if (!CHECKING_P)
+ /* GTY is unfortunately not clever enough to conditionalize
+ this. */
+ gcc_unreachable ();
+
+ if (ggc_marked_p (t))
+ return -1;
+
+ unsigned n = dump.push (NULL);
+ /* This might or might not be an error. We should note its
+ dropping whichever. */
+ dump () && dump ("Dropping %N from note_defs table", t);
+ dump.pop (n);
+
+ return 0;
+ }
+};
+
+/* We should stream each definition at most once.
+ This needs to be a cache because there are cases where a definition
+ ends up being not retained, and we need to drop those so we don't
+ get confused if memory is reallocated. */
+typedef hash_table<note_def_cache_hasher> note_defs_table_t;
+static GTY((cache)) note_defs_table_t *note_defs;
+
+void
+trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED,
+ bool installing ATTRIBUTE_UNUSED)
+{
+#if CHECKING_P
+ tree *slot = note_defs->find_slot (decl, installing ? INSERT : NO_INSERT);
+ if (installing)
+ {
+ /* We must be inserting for the first time. */
+ gcc_assert (!*slot);
+ *slot = decl;
+ }
+ else
+ /* If this is not the mergeable entity, it should not be in the
+ table. If it is a non-global-module mergeable entity, it
+ should be in the table. Global module entities could have been
+ defined textually in the current TU and so might or might not
+ be present. */
+ gcc_assert (!is_duplicate (decl)
+ ? !slot
+ : (slot
+ || !DECL_LANG_SPECIFIC (decl)
+ || !DECL_MODULE_PURVIEW_P (decl)
+ || (!DECL_MODULE_IMPORT_P (decl)
+ && header_module_p ())));
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ gcc_assert (!note_defs->find_slot (DECL_TEMPLATE_RESULT (decl), NO_INSERT));
+#endif
+}
+
+void
+trees_out::assert_definition (tree decl ATTRIBUTE_UNUSED)
+{
+#if CHECKING_P
+ tree *slot = note_defs->find_slot (decl, INSERT);
+ gcc_assert (!*slot);
+ *slot = decl;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ gcc_assert (!note_defs->find_slot (DECL_TEMPLATE_RESULT (decl), NO_INSERT));
+#endif
+}
+
+/********************************************************************/
+static bool
+noisy_p ()
+{
+ if (quiet_flag)
+ return false;
+
+ pp_needs_newline (global_dc->printer) = true;
+ diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL);
+
+ return true;
+}
+
+/* Set the cmi repo. Strip trailing '/', '.' becomes NULL. */
+
+static void
+set_cmi_repo (const char *r)
+{
+ XDELETEVEC (cmi_repo);
+ XDELETEVEC (cmi_path);
+ cmi_path_alloc = 0;
+
+ cmi_repo = NULL;
+ cmi_repo_length = 0;
+
+ if (!r || !r[0])
+ return;
+
+ size_t len = strlen (r);
+ cmi_repo = XNEWVEC (char, len + 1);
+ memcpy (cmi_repo, r, len + 1);
+
+ if (len > 1 && IS_DIR_SEPARATOR (cmi_repo[len-1]))
+ len--;
+ if (len == 1 && cmi_repo[0] == '.')
+ len--;
+ cmi_repo[len] = 0;
+ cmi_repo_length = len;
+}
+
+/* TO is a repo-relative name. Provide one that we may use from where
+ we are. */
+
+static const char *
+maybe_add_cmi_prefix (const char *to, size_t *len_p = NULL)
+{
+ size_t len = len_p || cmi_repo_length ? strlen (to) : 0;
+
+ if (cmi_repo_length && !IS_ABSOLUTE_PATH (to))
+ {
+ if (cmi_path_alloc < cmi_repo_length + len + 2)
+ {
+ XDELETEVEC (cmi_path);
+ cmi_path_alloc = cmi_repo_length + len * 2 + 2;
+ cmi_path = XNEWVEC (char, cmi_path_alloc);
+
+ memcpy (cmi_path, cmi_repo, cmi_repo_length);
+ cmi_path[cmi_repo_length] = DIR_SEPARATOR;
+ }
+
+ memcpy (&cmi_path[cmi_repo_length + 1], to, len + 1);
+ len += cmi_repo_length + 1;
+ to = cmi_path;
+ }
+
+ if (len_p)
+ *len_p = len;
+
+ return to;
+}
+
+/* Try and create the directories of PATH. */
+
+static void
+create_dirs (char *path)
+{
+ /* Try and create the missing directories. */
+ for (char *base = path; *base; base++)
+ if (IS_DIR_SEPARATOR (*base))
+ {
+ char sep = *base;
+ *base = 0;
+ int failed = mkdir (path, S_IRWXU | S_IRWXG | S_IRWXO);
+ dump () && dump ("Mkdir ('%s') errno:=%u", path, failed ? errno : 0);
+ *base = sep;
+ if (failed
+ /* Maybe racing with another creator (of a *different*
+ module). */
+ && errno != EEXIST)
+ break;
+ }
+}
+
+/* Given a CLASSTYPE_DECL_LIST VALUE get the the template friend decl,
+ if that's what this is. */
+
+static tree
+friend_from_decl_list (tree frnd)
+{
+ tree res = frnd;
+
+ if (TREE_CODE (frnd) != TEMPLATE_DECL)
+ {
+ tree tmpl = NULL_TREE;
+ if (TYPE_P (frnd))
+ {
+ res = TYPE_NAME (frnd);
+ if (CLASSTYPE_TEMPLATE_INFO (frnd))
+ tmpl = CLASSTYPE_TI_TEMPLATE (frnd);
+ }
+ else if (DECL_TEMPLATE_INFO (frnd))
+ {
+ tmpl = DECL_TI_TEMPLATE (frnd);
+ if (TREE_CODE (tmpl) != TEMPLATE_DECL)
+ tmpl = NULL_TREE;
+ }
+
+ if (tmpl && DECL_TEMPLATE_RESULT (tmpl) == res)
+ res = tmpl;
+ }
+
+ return res;
+}
+
+static tree
+find_enum_member (tree ctx, tree name)
+{
+ for (tree values = TYPE_VALUES (ctx);
+ values; values = TREE_CHAIN (values))
+ if (DECL_NAME (TREE_VALUE (values)) == name)
+ return TREE_VALUE (values);
+
+ return NULL_TREE;
+}
+
+/********************************************************************/
+/* Instrumentation gathered writing bytes. */
+
+void
+bytes_out::instrument ()
+{
+ dump ("Wrote %u bytes in %u blocks", lengths[3], spans[3]);
+ dump ("Wrote %u bits in %u bytes", lengths[0] + lengths[1], lengths[2]);
+ for (unsigned ix = 0; ix < 2; ix++)
+ dump (" %u %s spans of %R bits", spans[ix],
+ ix ? "one" : "zero", lengths[ix], spans[ix]);
+ dump (" %u blocks with %R bits padding", spans[2],
+ lengths[2] * 8 - (lengths[0] + lengths[1]), spans[2]);
+}
+
+/* Instrumentation gathered writing trees. */
+void
+trees_out::instrument ()
+{
+ if (dump (""))
+ {
+ bytes_out::instrument ();
+ dump ("Wrote:");
+ dump (" %u decl trees", decl_val_count);
+ dump (" %u other trees", tree_val_count);
+ dump (" %u back references", back_ref_count);
+ dump (" %u null trees", null_count);
+ }
+}
+
+/* Setup and teardown for a tree walk. */
+
+void
+trees_out::begin ()
+{
+ gcc_assert (!streaming_p () || !tree_map.elements ());
+
+ mark_trees ();
+ if (streaming_p ())
+ parent::begin ();
+}
+
+unsigned
+trees_out::end (elf_out *sink, unsigned name, unsigned *crc_ptr)
+{
+ gcc_checking_assert (streaming_p ());
+
+ unmark_trees ();
+ return parent::end (sink, name, crc_ptr);
+}
+
+void
+trees_out::end ()
+{
+ gcc_assert (!streaming_p ());
+
+ unmark_trees ();
+ /* Do not parent::end -- we weren't streaming. */
+}
+
+void
+trees_out::mark_trees ()
+{
+ if (size_t size = tree_map.elements ())
+ {
+ /* This isn't our first rodeo, destroy and recreate the
+ tree_map. I'm a bad bad man. Use the previous size as a
+ guess for the next one (so not all bad). */
+ tree_map.~ptr_int_hash_map ();
+ new (&tree_map) ptr_int_hash_map (size);
+ }
+
+ /* Install the fixed trees, with +ve references. */
+ unsigned limit = fixed_trees->length ();
+ for (unsigned ix = 0; ix != limit; ix++)
+ {
+ tree val = (*fixed_trees)[ix];
+ bool existed = tree_map.put (val, ix + tag_fixed);
+ gcc_checking_assert (!TREE_VISITED (val) && !existed);
+ TREE_VISITED (val) = true;
+ }
+
+ ref_num = 0;
+}
+
+/* Unmark the trees we encountered */
+
+void
+trees_out::unmark_trees ()
+{
+ ptr_int_hash_map::iterator end (tree_map.end ());
+ for (ptr_int_hash_map::iterator iter (tree_map.begin ()); iter != end; ++iter)
+ {
+ tree node = reinterpret_cast<tree> ((*iter).first);
+ int ref = (*iter).second;
+ /* We should have visited the node, and converted its mergeable
+ reference to a regular reference. */
+ gcc_checking_assert (TREE_VISITED (node)
+ && (ref <= tag_backref || ref >= tag_fixed));
+ TREE_VISITED (node) = false;
+ }
+}
+
+/* Mark DECL for by-value walking. We do this by inserting it into
+ the tree map with a reference of zero. May be called multiple
+ times on the same node. */
+
+void
+trees_out::mark_by_value (tree decl)
+{
+ gcc_checking_assert (DECL_P (decl)
+ /* Enum consts are INTEGER_CSTS. */
+ || TREE_CODE (decl) == INTEGER_CST
+ || TREE_CODE (decl) == TREE_BINFO);
+
+ if (TREE_VISITED (decl))
+ /* Must already be forced or fixed. */
+ gcc_checking_assert (*tree_map.get (decl) >= tag_value);
+ else
+ {
+ bool existed = tree_map.put (decl, tag_value);
+ gcc_checking_assert (!existed);
+ TREE_VISITED (decl) = true;
+ }
+}
+
+int
+trees_out::get_tag (tree t)
+{
+ gcc_checking_assert (TREE_VISITED (t));
+ return *tree_map.get (t);
+}
+
+/* Insert T into the map, return its tag number. */
+
+int
+trees_out::insert (tree t, walk_kind walk)
+{
+ gcc_checking_assert (walk != WK_normal || !TREE_VISITED (t));
+ int tag = --ref_num;
+ bool existed;
+ int &slot = tree_map.get_or_insert (t, &existed);
+ gcc_checking_assert (TREE_VISITED (t) == existed
+ && (!existed
+ || (walk == WK_value && slot == tag_value)));
+ TREE_VISITED (t) = true;
+ slot = tag;
+
+ return tag;
+}
+
+/* Insert T into the backreference array. Return its back reference
+ number. */
+
+int
+trees_in::insert (tree t)
+{
+ gcc_checking_assert (t || get_overrun ());
+ back_refs.safe_push (t);
+ return -(int)back_refs.length ();
+}
+
+/* A chained set of decls. */
+
+void
+trees_out::chained_decls (tree decls)
+{
+ for (; decls; decls = DECL_CHAIN (decls))
+ {
+ if (VAR_OR_FUNCTION_DECL_P (decls)
+ && DECL_LOCAL_DECL_P (decls))
+ {
+ /* Make sure this is the first encounter, and mark for
+ walk-by-value. */
+ gcc_checking_assert (!TREE_VISITED (decls)
+ && !DECL_TEMPLATE_INFO (decls));
+ mark_by_value (decls);
+ }
+ tree_node (decls);
+ }
+ tree_node (NULL_TREE);
+}
+
+tree
+trees_in::chained_decls ()
+{
+ tree decls = NULL_TREE;
+ for (tree *chain = &decls;;)
+ if (tree decl = tree_node ())
+ {
+ if (!DECL_P (decl) || DECL_CHAIN (decl))
+ {
+ set_overrun ();
+ break;
+ }
+ *chain = decl;
+ chain = &DECL_CHAIN (decl);
+ }
+ else
+ break;
+
+ return decls;
+}
+
+/* A vector of decls following DECL_CHAIN. */
+
+void
+trees_out::vec_chained_decls (tree decls)
+{
+ if (streaming_p ())
+ {
+ unsigned len = 0;
+
+ for (tree decl = decls; decl; decl = DECL_CHAIN (decl))
+ len++;
+ u (len);
+ }
+
+ for (tree decl = decls; decl; decl = DECL_CHAIN (decl))
+ {
+ if (DECL_IMPLICIT_TYPEDEF_P (decl)
+ && TYPE_NAME (TREE_TYPE (decl)) != decl)
+ /* An anonynmous struct with a typedef name. An odd thing to
+ write. */
+ tree_node (NULL_TREE);
+ else
+ tree_node (decl);
+ }
+}
+
+vec<tree, va_heap> *
+trees_in::vec_chained_decls ()
+{
+ vec<tree, va_heap> *v = NULL;
+
+ if (unsigned len = u ())
+ {
+ vec_alloc (v, len);
+
+ for (unsigned ix = 0; ix < len; ix++)
+ {
+ tree decl = tree_node ();
+ if (decl && !DECL_P (decl))
+ {
+ set_overrun ();
+ break;
+ }
+ v->quick_push (decl);
+ }
+
+ if (get_overrun ())
+ {
+ vec_free (v);
+ v = NULL;
+ }
+ }
+
+ return v;
+}
+
+/* A vector of trees. */
+
+void
+trees_out::tree_vec (vec<tree, va_gc> *v)
+{
+ unsigned len = vec_safe_length (v);
+ if (streaming_p ())
+ u (len);
+ for (unsigned ix = 0; ix != len; ix++)
+ tree_node ((*v)[ix]);
+}
+
+vec<tree, va_gc> *
+trees_in::tree_vec ()
+{
+ vec<tree, va_gc> *v = NULL;
+ if (unsigned len = u ())
+ {
+ vec_alloc (v, len);
+ for (unsigned ix = 0; ix != len; ix++)
+ v->quick_push (tree_node ());
+ }
+ return v;
+}
+
+/* A vector of tree pairs. */
+
+void
+trees_out::tree_pair_vec (vec<tree_pair_s, va_gc> *v)
+{
+ unsigned len = vec_safe_length (v);
+ if (streaming_p ())
+ u (len);
+ if (len)
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree_pair_s const &s = (*v)[ix];
+ tree_node (s.purpose);
+ tree_node (s.value);
+ }
+}
+
+vec<tree_pair_s, va_gc> *
+trees_in::tree_pair_vec ()
+{
+ vec<tree_pair_s, va_gc> *v = NULL;
+ if (unsigned len = u ())
+ {
+ vec_alloc (v, len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree_pair_s s;
+ s.purpose = tree_node ();
+ s.value = tree_node ();
+ v->quick_push (s);
+ }
+ }
+ return v;
+}
+
+void
+trees_out::tree_list (tree list, bool has_purpose)
+{
+ for (; list; list = TREE_CHAIN (list))
+ {
+ gcc_checking_assert (TREE_VALUE (list));
+ tree_node (TREE_VALUE (list));
+ if (has_purpose)
+ tree_node (TREE_PURPOSE (list));
+ }
+ tree_node (NULL_TREE);
+}
+
+tree
+trees_in::tree_list (bool has_purpose)
+{
+ tree res = NULL_TREE;
+
+ for (tree *chain = &res; tree value = tree_node ();
+ chain = &TREE_CHAIN (*chain))
+ {
+ tree purpose = has_purpose ? tree_node () : NULL_TREE;
+ *chain = build_tree_list (purpose, value);
+ }
+
+ return res;
+}
+/* Start tree write. Write information to allocate the receiving
+ node. */
+
+void
+trees_out::start (tree t, bool code_streamed)
+{
+ if (TYPE_P (t))
+ {
+ enum tree_code code = TREE_CODE (t);
+ gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
+ /* All these types are TYPE_NON_COMMON. */
+ gcc_checking_assert (code == RECORD_TYPE
+ || code == UNION_TYPE
+ || code == ENUMERAL_TYPE
+ || code == TEMPLATE_TYPE_PARM
+ || code == TEMPLATE_TEMPLATE_PARM
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM);
+ }
+
+ if (!code_streamed)
+ u (TREE_CODE (t));
+
+ switch (TREE_CODE (t))
+ {
+ default:
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_vl_exp)
+ u (VL_EXP_OPERAND_LENGTH (t));
+ break;
+
+ case INTEGER_CST:
+ u (TREE_INT_CST_NUNITS (t));
+ u (TREE_INT_CST_EXT_NUNITS (t));
+ u (TREE_INT_CST_OFFSET_NUNITS (t));
+ break;
+
+ case OMP_CLAUSE:
+ state->extensions |= SE_OPENMP;
+ u (OMP_CLAUSE_CODE (t));
+ break;
+
+ case STRING_CST:
+ str (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t));
+ break;
+
+ case VECTOR_CST:
+ u (VECTOR_CST_LOG2_NPATTERNS (t));
+ u (VECTOR_CST_NELTS_PER_PATTERN (t));
+ break;
+
+ case TREE_BINFO:
+ u (BINFO_N_BASE_BINFOS (t));
+ break;
+
+ case TREE_VEC:
+ u (TREE_VEC_LENGTH (t));
+ break;
+
+ case FIXED_CST:
+ case POLY_INT_CST:
+ gcc_unreachable (); /* Not supported in C++. */
+ break;
+
+ case IDENTIFIER_NODE:
+ case SSA_NAME:
+ case TARGET_MEM_REF:
+ case TRANSLATION_UNIT_DECL:
+ /* We shouldn't meet these. */
+ gcc_unreachable ();
+ break;
+ }
+}
+
+/* Start tree read. Allocate the receiving node. */
+
+tree
+trees_in::start (unsigned code)
+{
+ tree t = NULL_TREE;
+
+ if (!code)
+ code = u ();
+
+ switch (code)
+ {
+ default:
+ if (code >= MAX_TREE_CODES)
+ {
+ fail:
+ set_overrun ();
+ return NULL_TREE;
+ }
+ else if (TREE_CODE_CLASS (code) == tcc_vl_exp)
+ {
+ unsigned ops = u ();
+ t = build_vl_exp (tree_code (code), ops);
+ }
+ else
+ t = make_node (tree_code (code));
+ break;
+
+ case INTEGER_CST:
+ {
+ unsigned n = u ();
+ unsigned e = u ();
+ t = make_int_cst (n, e);
+ TREE_INT_CST_OFFSET_NUNITS(t) = u ();
+ }
+ break;
+
+ case OMP_CLAUSE:
+ {
+ if (!(state->extensions & SE_OPENMP))
+ goto fail;
+
+ unsigned omp_code = u ();
+ t = build_omp_clause (UNKNOWN_LOCATION, omp_clause_code (omp_code));
+ }
+ break;
+
+ case STRING_CST:
+ {
+ size_t l;
+ const char *chars = str (&l);
+ t = build_string (l, chars);
+ }
+ break;
+
+ case VECTOR_CST:
+ {
+ unsigned log2_npats = u ();
+ unsigned elts_per = u ();
+ t = make_vector (log2_npats, elts_per);
+ }
+ break;
+
+ case TREE_BINFO:
+ t = make_tree_binfo (u ());
+ break;
+
+ case TREE_VEC:
+ t = make_tree_vec (u ());
+ break;
+
+ case FIXED_CST:
+ case IDENTIFIER_NODE:
+ case POLY_INT_CST:
+ case SSA_NAME:
+ case TARGET_MEM_REF:
+ case TRANSLATION_UNIT_DECL:
+ goto fail;
+ }
+
+ return t;
+}
+
+/* The structure streamers access the raw fields, because the
+ alternative, of using the accessor macros can require using
+ different accessors for the same underlying field, depending on the
+ tree code. That's both confusing and annoying. */
+
+/* Read & write the core boolean flags. */
+
+void
+trees_out::core_bools (tree t)
+{
+#define WB(X) (b (X))
+ tree_code code = TREE_CODE (t);
+
+ WB (t->base.side_effects_flag);
+ WB (t->base.constant_flag);
+ WB (t->base.addressable_flag);
+ WB (t->base.volatile_flag);
+ WB (t->base.readonly_flag);
+ /* base.asm_written_flag is a property of the current TU's use of
+ this decl. */
+ WB (t->base.nowarning_flag);
+ /* base.visited read as zero (it's set for writer, because that's
+ how we mark nodes). */
+ /* base.used_flag is not streamed. Readers may set TREE_USED of
+ decls they use. */
+ WB (t->base.nothrow_flag);
+ WB (t->base.static_flag);
+ if (TREE_CODE_CLASS (code) != tcc_type)
+ /* This is TYPE_CACHED_VALUES_P for types. */
+ WB (t->base.public_flag);
+ WB (t->base.private_flag);
+ WB (t->base.protected_flag);
+ WB (t->base.deprecated_flag);
+ WB (t->base.default_def_flag);
+
+ switch (code)
+ {
+ case CALL_EXPR:
+ case INTEGER_CST:
+ case SSA_NAME:
+ case TARGET_MEM_REF:
+ case TREE_VEC:
+ /* These use different base.u fields. */
+ break;
+
+ default:
+ WB (t->base.u.bits.lang_flag_0);
+ bool flag_1 = t->base.u.bits.lang_flag_1;
+ if (!flag_1)
+ ;
+ else if (code == TEMPLATE_INFO)
+ /* This is TI_PENDING_TEMPLATE_FLAG, not relevant to reader. */
+ flag_1 = false;
+ else if (code == VAR_DECL)
+ {
+ /* This is DECL_INITIALIZED_P. */
+ if (DECL_CONTEXT (t)
+ && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
+ /* We'll set this when reading the definition. */
+ flag_1 = false;
+ }
+ WB (flag_1);
+ WB (t->base.u.bits.lang_flag_2);
+ WB (t->base.u.bits.lang_flag_3);
+ WB (t->base.u.bits.lang_flag_4);
+ WB (t->base.u.bits.lang_flag_5);
+ WB (t->base.u.bits.lang_flag_6);
+ WB (t->base.u.bits.saturating_flag);
+ WB (t->base.u.bits.unsigned_flag);
+ WB (t->base.u.bits.packed_flag);
+ WB (t->base.u.bits.user_align);
+ WB (t->base.u.bits.nameless_flag);
+ WB (t->base.u.bits.atomic_flag);
+ break;
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+ {
+ WB (t->type_common.no_force_blk_flag);
+ WB (t->type_common.needs_constructing_flag);
+ WB (t->type_common.transparent_aggr_flag);
+ WB (t->type_common.restrict_flag);
+ WB (t->type_common.string_flag);
+ WB (t->type_common.lang_flag_0);
+ WB (t->type_common.lang_flag_1);
+ WB (t->type_common.lang_flag_2);
+ WB (t->type_common.lang_flag_3);
+ WB (t->type_common.lang_flag_4);
+ WB (t->type_common.lang_flag_5);
+ WB (t->type_common.lang_flag_6);
+ WB (t->type_common.typeless_storage);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ WB (t->decl_common.nonlocal_flag);
+ WB (t->decl_common.virtual_flag);
+ WB (t->decl_common.ignored_flag);
+ WB (t->decl_common.abstract_flag);
+ WB (t->decl_common.artificial_flag);
+ WB (t->decl_common.preserve_flag);
+ WB (t->decl_common.debug_expr_is_from);
+ WB (t->decl_common.lang_flag_0);
+ WB (t->decl_common.lang_flag_1);
+ WB (t->decl_common.lang_flag_2);
+ WB (t->decl_common.lang_flag_3);
+ WB (t->decl_common.lang_flag_4);
+ WB (t->decl_common.lang_flag_5);
+ WB (t->decl_common.lang_flag_6);
+ WB (t->decl_common.lang_flag_7);
+ WB (t->decl_common.lang_flag_8);
+ WB (t->decl_common.decl_flag_0);
+
+ {
+ /* DECL_EXTERNAL -> decl_flag_1
+ == it is defined elsewhere
+ DECL_NOT_REALLY_EXTERN -> base.not_really_extern
+ == that was a lie, it is here */
+
+ bool is_external = t->decl_common.decl_flag_1;
+ if (!is_external)
+ /* decl_flag_1 is DECL_EXTERNAL. Things we emit here, might
+ well be external from the POV of an importer. */
+ // FIXME: Do we need to know if this is a TEMPLATE_RESULT --
+ // a flag from the caller?
+ switch (code)
+ {
+ default:
+ break;
+
+ case VAR_DECL:
+ if (TREE_PUBLIC (t)
+ && !DECL_VAR_DECLARED_INLINE_P (t))
+ is_external = true;
+ break;
+
+ case FUNCTION_DECL:
+ if (TREE_PUBLIC (t)
+ && !DECL_DECLARED_INLINE_P (t))
+ is_external = true;
+ break;
+ }
+ WB (is_external);
+ }
+
+ WB (t->decl_common.decl_flag_2);
+ WB (t->decl_common.decl_flag_3);
+ WB (t->decl_common.not_gimple_reg_flag);
+ WB (t->decl_common.decl_by_reference_flag);
+ WB (t->decl_common.decl_read_flag);
+ WB (t->decl_common.decl_nonshareable_flag);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+ {
+ WB (t->decl_with_vis.defer_output);
+ WB (t->decl_with_vis.hard_register);
+ WB (t->decl_with_vis.common_flag);
+ WB (t->decl_with_vis.in_text_section);
+ WB (t->decl_with_vis.in_constant_pool);
+ WB (t->decl_with_vis.dllimport_flag);
+ WB (t->decl_with_vis.weak_flag);
+ WB (t->decl_with_vis.seen_in_bind_expr);
+ WB (t->decl_with_vis.comdat_flag);
+ WB (t->decl_with_vis.visibility_specified);
+ WB (t->decl_with_vis.init_priority_p);
+ WB (t->decl_with_vis.shadowed_for_var_p);
+ WB (t->decl_with_vis.cxx_constructor);
+ WB (t->decl_with_vis.cxx_destructor);
+ WB (t->decl_with_vis.final);
+ WB (t->decl_with_vis.regdecl_flag);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
+ {
+ WB (t->function_decl.static_ctor_flag);
+ WB (t->function_decl.static_dtor_flag);
+ WB (t->function_decl.uninlinable);
+ WB (t->function_decl.possibly_inlined);
+ WB (t->function_decl.novops_flag);
+ WB (t->function_decl.returns_twice_flag);
+ WB (t->function_decl.malloc_flag);
+ WB (t->function_decl.declared_inline_flag);
+ WB (t->function_decl.no_inline_warning_flag);
+ WB (t->function_decl.no_instrument_function_entry_exit);
+ WB (t->function_decl.no_limit_stack);
+ WB (t->function_decl.disregard_inline_limits);
+ WB (t->function_decl.pure_flag);
+ WB (t->function_decl.looping_const_or_pure_flag);
+
+ WB (t->function_decl.has_debug_args_flag);
+ WB (t->function_decl.versioned_function);
+
+ /* decl_type is a (misnamed) 2 bit discriminator. */
+ unsigned kind = t->function_decl.decl_type;
+ WB ((kind >> 0) & 1);
+ WB ((kind >> 1) & 1);
+ }
+#undef WB
+}
+
+bool
+trees_in::core_bools (tree t)
+{
+#define RB(X) ((X) = b ())
+ tree_code code = TREE_CODE (t);
+
+ RB (t->base.side_effects_flag);
+ RB (t->base.constant_flag);
+ RB (t->base.addressable_flag);
+ RB (t->base.volatile_flag);
+ RB (t->base.readonly_flag);
+ /* base.asm_written_flag is not streamed. */
+ RB (t->base.nowarning_flag);
+ /* base.visited is not streamed. */
+ /* base.used_flag is not streamed. */
+ RB (t->base.nothrow_flag);
+ RB (t->base.static_flag);
+ if (TREE_CODE_CLASS (code) != tcc_type)
+ RB (t->base.public_flag);
+ RB (t->base.private_flag);
+ RB (t->base.protected_flag);
+ RB (t->base.deprecated_flag);
+ RB (t->base.default_def_flag);
+
+ switch (code)
+ {
+ case CALL_EXPR:
+ case INTEGER_CST:
+ case SSA_NAME:
+ case TARGET_MEM_REF:
+ case TREE_VEC:
+ /* These use different base.u fields. */
+ break;
+
+ default:
+ RB (t->base.u.bits.lang_flag_0);
+ RB (t->base.u.bits.lang_flag_1);
+ RB (t->base.u.bits.lang_flag_2);
+ RB (t->base.u.bits.lang_flag_3);
+ RB (t->base.u.bits.lang_flag_4);
+ RB (t->base.u.bits.lang_flag_5);
+ RB (t->base.u.bits.lang_flag_6);
+ RB (t->base.u.bits.saturating_flag);
+ RB (t->base.u.bits.unsigned_flag);
+ RB (t->base.u.bits.packed_flag);
+ RB (t->base.u.bits.user_align);
+ RB (t->base.u.bits.nameless_flag);
+ RB (t->base.u.bits.atomic_flag);
+ break;
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+ {
+ RB (t->type_common.no_force_blk_flag);
+ RB (t->type_common.needs_constructing_flag);
+ RB (t->type_common.transparent_aggr_flag);
+ RB (t->type_common.restrict_flag);
+ RB (t->type_common.string_flag);
+ RB (t->type_common.lang_flag_0);
+ RB (t->type_common.lang_flag_1);
+ RB (t->type_common.lang_flag_2);
+ RB (t->type_common.lang_flag_3);
+ RB (t->type_common.lang_flag_4);
+ RB (t->type_common.lang_flag_5);
+ RB (t->type_common.lang_flag_6);
+ RB (t->type_common.typeless_storage);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ RB (t->decl_common.nonlocal_flag);
+ RB (t->decl_common.virtual_flag);
+ RB (t->decl_common.ignored_flag);
+ RB (t->decl_common.abstract_flag);
+ RB (t->decl_common.artificial_flag);
+ RB (t->decl_common.preserve_flag);
+ RB (t->decl_common.debug_expr_is_from);
+ RB (t->decl_common.lang_flag_0);
+ RB (t->decl_common.lang_flag_1);
+ RB (t->decl_common.lang_flag_2);
+ RB (t->decl_common.lang_flag_3);
+ RB (t->decl_common.lang_flag_4);
+ RB (t->decl_common.lang_flag_5);
+ RB (t->decl_common.lang_flag_6);
+ RB (t->decl_common.lang_flag_7);
+ RB (t->decl_common.lang_flag_8);
+ RB (t->decl_common.decl_flag_0);
+ RB (t->decl_common.decl_flag_1);
+ RB (t->decl_common.decl_flag_2);
+ RB (t->decl_common.decl_flag_3);
+ RB (t->decl_common.not_gimple_reg_flag);
+ RB (t->decl_common.decl_by_reference_flag);
+ RB (t->decl_common.decl_read_flag);
+ RB (t->decl_common.decl_nonshareable_flag);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+ {
+ RB (t->decl_with_vis.defer_output);
+ RB (t->decl_with_vis.hard_register);
+ RB (t->decl_with_vis.common_flag);
+ RB (t->decl_with_vis.in_text_section);
+ RB (t->decl_with_vis.in_constant_pool);
+ RB (t->decl_with_vis.dllimport_flag);
+ RB (t->decl_with_vis.weak_flag);
+ RB (t->decl_with_vis.seen_in_bind_expr);
+ RB (t->decl_with_vis.comdat_flag);
+ RB (t->decl_with_vis.visibility_specified);
+ RB (t->decl_with_vis.init_priority_p);
+ RB (t->decl_with_vis.shadowed_for_var_p);
+ RB (t->decl_with_vis.cxx_constructor);
+ RB (t->decl_with_vis.cxx_destructor);
+ RB (t->decl_with_vis.final);
+ RB (t->decl_with_vis.regdecl_flag);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
+ {
+ RB (t->function_decl.static_ctor_flag);
+ RB (t->function_decl.static_dtor_flag);
+ RB (t->function_decl.uninlinable);
+ RB (t->function_decl.possibly_inlined);
+ RB (t->function_decl.novops_flag);
+ RB (t->function_decl.returns_twice_flag);
+ RB (t->function_decl.malloc_flag);
+ RB (t->function_decl.declared_inline_flag);
+ RB (t->function_decl.no_inline_warning_flag);
+ RB (t->function_decl.no_instrument_function_entry_exit);
+ RB (t->function_decl.no_limit_stack);
+ RB (t->function_decl.disregard_inline_limits);
+ RB (t->function_decl.pure_flag);
+ RB (t->function_decl.looping_const_or_pure_flag);
+
+ RB (t->function_decl.has_debug_args_flag);
+ RB (t->function_decl.versioned_function);
+
+ /* decl_type is a (misnamed) 2 bit discriminator. */
+ unsigned kind = 0;
+ kind |= unsigned (b ()) << 0;
+ kind |= unsigned (b ()) << 1;
+ t->function_decl.decl_type = function_decl_type (kind);
+ }
+#undef RB
+ return !get_overrun ();
+}
+
+void
+trees_out::lang_decl_bools (tree t)
+{
+#define WB(X) (b (X))
+ const struct lang_decl *lang = DECL_LANG_SPECIFIC (t);
+
+ WB (lang->u.base.language == lang_cplusplus);
+ WB ((lang->u.base.use_template >> 0) & 1);
+ WB ((lang->u.base.use_template >> 1) & 1);
+ /* Do not write lang->u.base.not_really_extern, importer will set
+ when reading the definition (if any). */
+ WB (lang->u.base.initialized_in_class);
+ WB (lang->u.base.threadprivate_or_deleted_p);
+ /* Do not write lang->u.base.anticipated_p, it is a property of the
+ current TU. */
+ WB (lang->u.base.friend_or_tls);
+ WB (lang->u.base.unknown_bound_p);
+ /* Do not write lang->u.base.odr_used, importer will recalculate if
+ they do ODR use this decl. */
+ WB (lang->u.base.concept_p);
+ WB (lang->u.base.var_declared_inline_p);
+ WB (lang->u.base.dependent_init_p);
+ WB (lang->u.base.module_purview_p);
+ if (VAR_OR_FUNCTION_DECL_P (t))
+ WB (lang->u.base.module_pending_p);
+ switch (lang->u.base.selector)
+ {
+ default:
+ gcc_unreachable ();
+
+ case lds_fn: /* lang_decl_fn. */
+ WB (lang->u.fn.global_ctor_p);
+ WB (lang->u.fn.global_dtor_p);
+ WB (lang->u.fn.static_function);
+ WB (lang->u.fn.pure_virtual);
+ WB (lang->u.fn.defaulted_p);
+ WB (lang->u.fn.has_in_charge_parm_p);
+ WB (lang->u.fn.has_vtt_parm_p);
+ /* There shouldn't be a pending inline at this point. */
+ gcc_assert (!lang->u.fn.pending_inline_p);
+ WB (lang->u.fn.nonconverting);
+ WB (lang->u.fn.thunk_p);
+ WB (lang->u.fn.this_thunk_p);
+ /* Do not stream lang->u.hidden_friend_p, it is a property of
+ the TU. */
+ WB (lang->u.fn.omp_declare_reduction_p);
+ WB (lang->u.fn.has_dependent_explicit_spec_p);
+ WB (lang->u.fn.immediate_fn_p);
+ WB (lang->u.fn.maybe_deleted);
+ goto lds_min;
+
+ case lds_decomp: /* lang_decl_decomp. */
+ /* No bools. */
+ goto lds_min;
+
+ case lds_min: /* lang_decl_min. */
+ lds_min:
+ /* No bools. */
+ break;
+
+ case lds_ns: /* lang_decl_ns. */
+ /* No bools. */
+ break;
+
+ case lds_parm: /* lang_decl_parm. */
+ /* No bools. */
+ break;
+ }
+#undef WB
+}
+
+bool
+trees_in::lang_decl_bools (tree t)
+{
+#define RB(X) ((X) = b ())
+ struct lang_decl *lang = DECL_LANG_SPECIFIC (t);
+
+ lang->u.base.language = b () ? lang_cplusplus : lang_c;
+ unsigned v;
+ v = b () << 0;
+ v |= b () << 1;
+ lang->u.base.use_template = v;
+ /* lang->u.base.not_really_extern is not streamed. */
+ RB (lang->u.base.initialized_in_class);
+ RB (lang->u.base.threadprivate_or_deleted_p);
+ /* lang->u.base.anticipated_p is not streamed. */
+ RB (lang->u.base.friend_or_tls);
+ RB (lang->u.base.unknown_bound_p);
+ /* lang->u.base.odr_used is not streamed. */
+ RB (lang->u.base.concept_p);
+ RB (lang->u.base.var_declared_inline_p);
+ RB (lang->u.base.dependent_init_p);
+ RB (lang->u.base.module_purview_p);
+ if (VAR_OR_FUNCTION_DECL_P (t))
+ RB (lang->u.base.module_pending_p);
+ switch (lang->u.base.selector)
+ {
+ default:
+ gcc_unreachable ();
+
+ case lds_fn: /* lang_decl_fn. */
+ RB (lang->u.fn.global_ctor_p);
+ RB (lang->u.fn.global_dtor_p);
+ RB (lang->u.fn.static_function);
+ RB (lang->u.fn.pure_virtual);
+ RB (lang->u.fn.defaulted_p);
+ RB (lang->u.fn.has_in_charge_parm_p);
+ RB (lang->u.fn.has_vtt_parm_p);
+ RB (lang->u.fn.nonconverting);
+ RB (lang->u.fn.thunk_p);
+ RB (lang->u.fn.this_thunk_p);
+ /* lang->u.fn.hidden_friend_p is not streamed. */
+ RB (lang->u.fn.omp_declare_reduction_p);
+ RB (lang->u.fn.has_dependent_explicit_spec_p);
+ RB (lang->u.fn.immediate_fn_p);
+ RB (lang->u.fn.maybe_deleted);
+ goto lds_min;
+
+ case lds_decomp: /* lang_decl_decomp. */
+ /* No bools. */
+ goto lds_min;
+
+ case lds_min: /* lang_decl_min. */
+ lds_min:
+ /* No bools. */
+ break;
+
+ case lds_ns: /* lang_decl_ns. */
+ /* No bools. */
+ break;
+
+ case lds_parm: /* lang_decl_parm. */
+ /* No bools. */
+ break;
+ }
+#undef RB
+ return !get_overrun ();
+}
+
+void
+trees_out::lang_type_bools (tree t)
+{
+#define WB(X) (b (X))
+ const struct lang_type *lang = TYPE_LANG_SPECIFIC (t);
+
+ WB (lang->has_type_conversion);
+ WB (lang->has_copy_ctor);
+ WB (lang->has_default_ctor);
+ WB (lang->const_needs_init);
+ WB (lang->ref_needs_init);
+ WB (lang->has_const_copy_assign);
+ WB ((lang->use_template >> 0) & 1);
+ WB ((lang->use_template >> 1) & 1);
+
+ WB (lang->has_mutable);
+ WB (lang->com_interface);
+ WB (lang->non_pod_class);
+ WB (lang->nearly_empty_p);
+ WB (lang->user_align);
+ WB (lang->has_copy_assign);
+ WB (lang->has_new);
+ WB (lang->has_array_new);
+
+ WB ((lang->gets_delete >> 0) & 1);
+ WB ((lang->gets_delete >> 1) & 1);
+ // Interfaceness is recalculated upon reading. May have to revisit?
+ // How do dllexport and dllimport interact across a module?
+ // lang->interface_only
+ // lang->interface_unknown
+ WB (lang->contains_empty_class_p);
+ WB (lang->anon_aggr);
+ WB (lang->non_zero_init);
+ WB (lang->empty_p);
+
+ WB (lang->vec_new_uses_cookie);
+ WB (lang->declared_class);
+ WB (lang->diamond_shaped);
+ WB (lang->repeated_base);
+ gcc_assert (!lang->being_defined);
+ // lang->debug_requested
+ WB (lang->fields_readonly);
+ WB (lang->ptrmemfunc_flag);
+
+ WB (lang->lazy_default_ctor);
+ WB (lang->lazy_copy_ctor);
+ WB (lang->lazy_copy_assign);
+ WB (lang->lazy_destructor);
+ WB (lang->has_const_copy_ctor);
+ WB (lang->has_complex_copy_ctor);
+ WB (lang->has_complex_copy_assign);
+ WB (lang->non_aggregate);
+
+ WB (lang->has_complex_dflt);
+ WB (lang->has_list_ctor);
+ WB (lang->non_std_layout);
+ WB (lang->is_literal);
+ WB (lang->lazy_move_ctor);
+ WB (lang->lazy_move_assign);
+ WB (lang->has_complex_move_ctor);
+ WB (lang->has_complex_move_assign);
+
+ WB (lang->has_constexpr_ctor);
+ WB (lang->unique_obj_representations);
+ WB (lang->unique_obj_representations_set);
+#undef WB
+}
+
+bool
+trees_in::lang_type_bools (tree t)
+{
+#define RB(X) ((X) = b ())
+ struct lang_type *lang = TYPE_LANG_SPECIFIC (t);
+
+ RB (lang->has_type_conversion);
+ RB (lang->has_copy_ctor);
+ RB (lang->has_default_ctor);
+ RB (lang->const_needs_init);
+ RB (lang->ref_needs_init);
+ RB (lang->has_const_copy_assign);
+ unsigned v;
+ v = b () << 0;
+ v |= b () << 1;
+ lang->use_template = v;
+
+ RB (lang->has_mutable);
+ RB (lang->com_interface);
+ RB (lang->non_pod_class);
+ RB (lang->nearly_empty_p);
+ RB (lang->user_align);
+ RB (lang->has_copy_assign);
+ RB (lang->has_new);
+ RB (lang->has_array_new);
+
+ v = b () << 0;
+ v |= b () << 1;
+ lang->gets_delete = v;
+ // lang->interface_only
+ // lang->interface_unknown
+ lang->interface_unknown = true; // Redetermine interface
+ RB (lang->contains_empty_class_p);
+ RB (lang->anon_aggr);
+ RB (lang->non_zero_init);
+ RB (lang->empty_p);
+
+ RB (lang->vec_new_uses_cookie);
+ RB (lang->declared_class);
+ RB (lang->diamond_shaped);
+ RB (lang->repeated_base);
+ gcc_assert (!lang->being_defined);
+ gcc_assert (!lang->debug_requested);
+ RB (lang->fields_readonly);
+ RB (lang->ptrmemfunc_flag);
+
+ RB (lang->lazy_default_ctor);
+ RB (lang->lazy_copy_ctor);
+ RB (lang->lazy_copy_assign);
+ RB (lang->lazy_destructor);
+ RB (lang->has_const_copy_ctor);
+ RB (lang->has_complex_copy_ctor);
+ RB (lang->has_complex_copy_assign);
+ RB (lang->non_aggregate);
+
+ RB (lang->has_complex_dflt);
+ RB (lang->has_list_ctor);
+ RB (lang->non_std_layout);
+ RB (lang->is_literal);
+ RB (lang->lazy_move_ctor);
+ RB (lang->lazy_move_assign);
+ RB (lang->has_complex_move_ctor);
+ RB (lang->has_complex_move_assign);
+
+ RB (lang->has_constexpr_ctor);
+ RB (lang->unique_obj_representations);
+ RB (lang->unique_obj_representations_set);
+#undef RB
+ return !get_overrun ();
+}
+
+/* Read & write the core values and pointers. */
+
+void
+trees_out::core_vals (tree t)
+{
+#define WU(X) (u (X))
+#define WT(X) (tree_node (X))
+ tree_code code = TREE_CODE (t);
+
+ /* First by shape of the tree. */
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
+ {
+ /* Write this early, for better log information. */
+ WT (t->decl_minimal.name);
+ if (!DECL_TEMPLATE_PARM_P (t))
+ WT (t->decl_minimal.context);
+
+ state->write_location (*this, t->decl_minimal.locus);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+ {
+ /* The only types we write also have TYPE_NON_COMMON. */
+ gcc_checking_assert (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON));
+
+ /* We only stream the main variant. */
+ gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
+
+ /* Stream the name & context first, for better log information */
+ WT (t->type_common.name);
+ WT (t->type_common.context);
+
+ /* By construction we want to make sure we have the canonical
+ and main variants already in the type table, so emit them
+ now. */
+ WT (t->type_common.main_variant);
+
+ tree canonical = t->type_common.canonical;
+ if (canonical && DECL_TEMPLATE_PARM_P (TYPE_NAME (t)))
+ /* We do not want to wander into different templates.
+ Reconstructed on stream in. */
+ canonical = t;
+ WT (canonical);
+
+ /* type_common.next_variant is internally manipulated. */
+ /* type_common.pointer_to, type_common.reference_to. */
+
+ if (streaming_p ())
+ {
+ WU (t->type_common.precision);
+ WU (t->type_common.contains_placeholder_bits);
+ WU (t->type_common.mode);
+ WU (t->type_common.align);
+ }
+
+ if (!RECORD_OR_UNION_CODE_P (code))
+ {
+ WT (t->type_common.size);
+ WT (t->type_common.size_unit);
+ }
+ WT (t->type_common.attributes);
+
+ WT (t->type_common.common.chain); /* TYPE_STUB_DECL. */
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ if (streaming_p ())
+ {
+ WU (t->decl_common.mode);
+ WU (t->decl_common.off_align);
+ WU (t->decl_common.align);
+ }
+
+ /* For templates these hold instantiation (partial and/or
+ specialization) information. */
+ if (code != TEMPLATE_DECL)
+ {
+ WT (t->decl_common.size);
+ WT (t->decl_common.size_unit);
+ }
+
+ WT (t->decl_common.attributes);
+ // FIXME: Does this introduce cross-decl links? For instance
+ // from instantiation to the template. If so, we'll need more
+ // deduplication logic. I think we'll need to walk the blocks
+ // of the owning function_decl's abstract origin in tandem, to
+ // generate the locating data needed?
+ WT (t->decl_common.abstract_origin);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+ {
+ WT (t->decl_with_vis.assembler_name);
+ if (streaming_p ())
+ WU (t->decl_with_vis.visibility);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
+ {
+ /* Records and unions hold FIELDS, VFIELD & BINFO on these
+ things. */
+ if (!RECORD_OR_UNION_CODE_P (code) && code != ENUMERAL_TYPE)
+ {
+ // FIXME: These are from tpl_parm_value's 'type' writing.
+ // Perhaps it should just be doing them directly?
+ gcc_checking_assert (code == TEMPLATE_TYPE_PARM
+ || code == TEMPLATE_TEMPLATE_PARM
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM);
+ gcc_checking_assert (!TYPE_CACHED_VALUES_P (t));
+ WT (t->type_non_common.values);
+ WT (t->type_non_common.maxval);
+ WT (t->type_non_common.minval);
+ }
+
+ WT (t->type_non_common.lang_1);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_EXP))
+ {
+ state->write_location (*this, t->exp.locus);
+
+ /* Walk in forward order, as (for instance) REQUIRES_EXPR has a
+ bunch of unscoped parms on its first operand. It's safer to
+ create those in order. */
+ bool vl = TREE_CODE_CLASS (code) == tcc_vl_exp;
+ for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)
+ : TREE_OPERAND_LENGTH (t)),
+ ix = unsigned (vl); ix != limit; ix++)
+ WT (TREE_OPERAND (t, ix));
+ }
+ else
+ /* The CODE_CONTAINS tables were inaccurate when I started. */
+ gcc_checking_assert (TREE_CODE_CLASS (code) != tcc_expression
+ && TREE_CODE_CLASS (code) != tcc_binary
+ && TREE_CODE_CLASS (code) != tcc_unary
+ && TREE_CODE_CLASS (code) != tcc_reference
+ && TREE_CODE_CLASS (code) != tcc_comparison
+ && TREE_CODE_CLASS (code) != tcc_statement
+ && TREE_CODE_CLASS (code) != tcc_vl_exp);
+
+ /* Then by CODE. Special cases and/or 1:1 tree shape
+ correspondance. */
+ switch (code)
+ {
+ default:
+ break;
+
+ case ARGUMENT_PACK_SELECT: /* Transient during instantiation. */
+ case DEFERRED_PARSE: /* Expanded upon completion of
+ outermost class. */
+ case IDENTIFIER_NODE: /* Streamed specially. */
+ case BINDING_VECTOR: /* Only in namespace-scope symbol
+ table. */
+ case SSA_NAME:
+ case TRANSLATION_UNIT_DECL: /* There is only one, it is a
+ global_tree. */
+ case USERDEF_LITERAL: /* Expanded during parsing. */
+ gcc_unreachable (); /* Should never meet. */
+
+ /* Constants. */
+ case COMPLEX_CST:
+ WT (TREE_REALPART (t));
+ WT (TREE_IMAGPART (t));
+ break;
+
+ case FIXED_CST:
+ gcc_unreachable (); /* Not supported in C++. */
+
+ case INTEGER_CST:
+ if (streaming_p ())
+ {
+ unsigned num = TREE_INT_CST_EXT_NUNITS (t);
+ for (unsigned ix = 0; ix != num; ix++)
+ wu (TREE_INT_CST_ELT (t, ix));
+ }
+ break;
+
+ case POLY_INT_CST:
+ gcc_unreachable (); /* Not supported in C++. */
+
+ case REAL_CST:
+ if (streaming_p ())
+ buf (TREE_REAL_CST_PTR (t), sizeof (real_value));
+ break;
+
+ case STRING_CST:
+ /* Streamed during start. */
+ break;
+
+ case VECTOR_CST:
+ for (unsigned ix = vector_cst_encoded_nelts (t); ix--;)
+ WT (VECTOR_CST_ENCODED_ELT (t, ix));
+ break;
+
+ /* Decls. */
+ case VAR_DECL:
+ if (DECL_CONTEXT (t)
+ && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
+ break;
+ /* FALLTHROUGH */
+
+ case RESULT_DECL:
+ case PARM_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (t))
+ WT (DECL_VALUE_EXPR (t));
+ /* FALLTHROUGH */
+
+ case CONST_DECL:
+ case IMPORTED_DECL:
+ WT (t->decl_common.initial);
+ break;
+
+ case FIELD_DECL:
+ WT (t->field_decl.offset);
+ WT (t->field_decl.bit_field_type);
+ WT (t->field_decl.qualifier); /* bitfield unit. */
+ WT (t->field_decl.bit_offset);
+ WT (t->field_decl.fcontext);
+ WT (t->decl_common.initial);
+ break;
+
+ case LABEL_DECL:
+ if (streaming_p ())
+ {
+ WU (t->label_decl.label_decl_uid);
+ WU (t->label_decl.eh_landing_pad_nr);
+ }
+ break;
+
+ case FUNCTION_DECL:
+ if (streaming_p ())
+ {
+ /* Builtins can be streamed by value when a header declares
+ them. */
+ WU (DECL_BUILT_IN_CLASS (t));
+ if (DECL_BUILT_IN_CLASS (t) != NOT_BUILT_IN)
+ WU (DECL_UNCHECKED_FUNCTION_CODE (t));
+ }
+
+ WT (t->function_decl.personality);
+ WT (t->function_decl.function_specific_target);
+ WT (t->function_decl.function_specific_optimization);
+ WT (t->function_decl.vindex);
+ break;
+
+ case USING_DECL:
+ /* USING_DECL_DECLS */
+ WT (t->decl_common.initial);
+ /* FALLTHROUGH */
+
+ case TYPE_DECL:
+ /* USING_DECL: USING_DECL_SCOPE */
+ /* TYPE_DECL: DECL_ORIGINAL_TYPE */
+ WT (t->decl_non_common.result);
+ break;
+
+ /* Miscellaneous common nodes. */
+ case BLOCK:
+ state->write_location (*this, t->block.locus);
+ state->write_location (*this, t->block.end_locus);
+
+ /* DECL_LOCAL_DECL_P decls are first encountered here and
+ streamed by value. */
+ chained_decls (t->block.vars);
+ /* nonlocalized_vars is a middle-end thing. */
+ WT (t->block.subblocks);
+ WT (t->block.supercontext);
+ // FIXME: As for decl's abstract_origin, does this introduce crosslinks?
+ WT (t->block.abstract_origin);
+ /* fragment_origin, fragment_chain are middle-end things. */
+ WT (t->block.chain);
+ /* nonlocalized_vars, block_num & die are middle endy/debug
+ things. */
+ break;
+
+ case CALL_EXPR:
+ if (streaming_p ())
+ WU (t->base.u.ifn);
+ break;
+
+ case CONSTRUCTOR:
+ {
+ unsigned len = vec_safe_length (t->constructor.elts);
+ if (streaming_p ())
+ WU (len);
+ if (len)
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ const constructor_elt &elt = (*t->constructor.elts)[ix];
+
+ WT (elt.index);
+ WT (elt.value);
+ }
+ }
+ break;
+
+ case OMP_CLAUSE:
+ {
+ /* The ompcode is serialized in start. */
+ if (streaming_p ())
+ WU (t->omp_clause.subcode.map_kind);
+ state->write_location (*this, t->omp_clause.locus);
+
+ unsigned len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)];
+ for (unsigned ix = 0; ix != len; ix++)
+ WT (t->omp_clause.ops[ix]);
+ }
+ break;
+
+ case STATEMENT_LIST:
+ for (tree_stmt_iterator iter = tsi_start (t);
+ !tsi_end_p (iter); tsi_next (&iter))
+ if (tree stmt = tsi_stmt (iter))
+ WT (stmt);
+ WT (NULL_TREE);
+ break;
+
+ case OPTIMIZATION_NODE:
+ case TARGET_OPTION_NODE:
+ // FIXME: Our representation for these two nodes is a cache of
+ // the resulting set of options. Not a record of the options
+ // that got changed by a particular attribute or pragma. Should
+ // we record that, or should we record the diff from the command
+ // line options? The latter seems the right behaviour, but is
+ // (a) harder, and I guess could introduce strangeness if the
+ // importer has set some incompatible set of optimization flags?
+ gcc_unreachable ();
+ break;
+
+ case TREE_BINFO:
+ {
+ WT (t->binfo.common.chain);
+ WT (t->binfo.offset);
+ WT (t->binfo.inheritance);
+ WT (t->binfo.vptr_field);
+
+ WT (t->binfo.vtable);
+ WT (t->binfo.virtuals);
+ WT (t->binfo.vtt_subvtt);
+ WT (t->binfo.vtt_vptr);
+
+ tree_vec (BINFO_BASE_ACCESSES (t));
+ unsigned num = vec_safe_length (BINFO_BASE_ACCESSES (t));
+ for (unsigned ix = 0; ix != num; ix++)
+ WT (BINFO_BASE_BINFO (t, ix));
+ }
+ break;
+
+ case TREE_LIST:
+ WT (t->list.purpose);
+ WT (t->list.value);
+ WT (t->list.common.chain);
+ break;
+
+ case TREE_VEC:
+ for (unsigned ix = TREE_VEC_LENGTH (t); ix--;)
+ WT (TREE_VEC_ELT (t, ix));
+ /* We stash NON_DEFAULT_TEMPLATE_ARGS_COUNT on TREE_CHAIN! */
+ gcc_checking_assert (!t->type_common.common.chain
+ || (TREE_CODE (t->type_common.common.chain)
+ == INTEGER_CST));
+ WT (t->type_common.common.chain);
+ break;
+
+ /* C++-specific nodes ... */
+ case BASELINK:
+ WT (((lang_tree_node *)t)->baselink.binfo);
+ WT (((lang_tree_node *)t)->baselink.functions);
+ WT (((lang_tree_node *)t)->baselink.access_binfo);
+ break;
+
+ case CONSTRAINT_INFO:
+ WT (((lang_tree_node *)t)->constraint_info.template_reqs);
+ WT (((lang_tree_node *)t)->constraint_info.declarator_reqs);
+ WT (((lang_tree_node *)t)->constraint_info.associated_constr);
+ break;
+
+ case DEFERRED_NOEXCEPT:
+ WT (((lang_tree_node *)t)->deferred_noexcept.pattern);
+ WT (((lang_tree_node *)t)->deferred_noexcept.args);
+ break;
+
+ case LAMBDA_EXPR:
+ WT (((lang_tree_node *)t)->lambda_expression.capture_list);
+ WT (((lang_tree_node *)t)->lambda_expression.this_capture);
+ WT (((lang_tree_node *)t)->lambda_expression.extra_scope);
+ /* pending_proxies is a parse-time thing. */
+ gcc_assert (!((lang_tree_node *)t)->lambda_expression.pending_proxies);
+ state->write_location
+ (*this, ((lang_tree_node *)t)->lambda_expression.locus);
+ if (streaming_p ())
+ {
+ WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode);
+ WU (((lang_tree_node *)t)->lambda_expression.discriminator);
+ }
+ break;
+
+ case OVERLOAD:
+ WT (((lang_tree_node *)t)->overload.function);
+ WT (t->common.chain);
+ break;
+
+ case PTRMEM_CST:
+ WT (((lang_tree_node *)t)->ptrmem.member);
+ break;
+
+ case STATIC_ASSERT:
+ WT (((lang_tree_node *)t)->static_assertion.condition);
+ WT (((lang_tree_node *)t)->static_assertion.message);
+ state->write_location
+ (*this, ((lang_tree_node *)t)->static_assertion.location);
+ break;
+
+ case TEMPLATE_DECL:
+ /* Streamed with the template_decl node itself. */
+ gcc_checking_assert
+ (TREE_VISITED (((lang_tree_node *)t)->template_decl.arguments));
+ gcc_checking_assert
+ (TREE_VISITED (((lang_tree_node *)t)->template_decl.result)
+ || dep_hash->find_dependency (t)->is_alias_tmpl_inst ());
+ if (DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (t))
+ WT (DECL_CHAIN (t));
+ break;
+
+ case TEMPLATE_INFO:
+ {
+ WT (((lang_tree_node *)t)->template_info.tmpl);
+ WT (((lang_tree_node *)t)->template_info.args);
+
+ const auto *ac = (((lang_tree_node *)t)
+ ->template_info.deferred_access_checks);
+ unsigned len = vec_safe_length (ac);
+ if (streaming_p ())
+ u (len);
+ if (len)
+ {
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ const auto &m = (*ac)[ix];
+ WT (m.binfo);
+ WT (m.decl);
+ WT (m.diag_decl);
+ state->write_location (*this, m.loc);
+ }
+ }
+ }
+ break;
+
+ case TEMPLATE_PARM_INDEX:
+ if (streaming_p ())
+ {
+ WU (((lang_tree_node *)t)->tpi.index);
+ WU (((lang_tree_node *)t)->tpi.level);
+ WU (((lang_tree_node *)t)->tpi.orig_level);
+ }
+ WT (((lang_tree_node *)t)->tpi.decl);
+ /* TEMPLATE_PARM_DESCENDANTS (AKA TREE_CHAIN) is an internal
+ cache, do not stream. */
+ break;
+
+ case TRAIT_EXPR:
+ WT (((lang_tree_node *)t)->trait_expression.type1);
+ WT (((lang_tree_node *)t)->trait_expression.type2);
+ if (streaming_p ())
+ WU (((lang_tree_node *)t)->trait_expression.kind);
+ break;
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
+ {
+ /* We want to stream the type of a expression-like nodes /after/
+ we've streamed the operands. The type often contains (bits
+ of the) types of the operands, and with things like decltype
+ and noexcept in play, we really want to stream the decls
+ defining the type before we try and stream the type on its
+ own. Otherwise we can find ourselves trying to read in a
+ decl, when we're already partially reading in a component of
+ its type. And that's bad. */
+ tree type = t->typed.type;
+ unsigned prec = 0;
+
+ switch (code)
+ {
+ default:
+ break;
+
+ case TEMPLATE_DECL:
+ /* We fill in the template's type separately. */
+ type = NULL_TREE;
+ break;
+
+ case TYPE_DECL:
+ if (DECL_ORIGINAL_TYPE (t) && t == TYPE_NAME (type))
+ /* This is a typedef. We set its type separately. */
+ type = NULL_TREE;
+ break;
+
+ case ENUMERAL_TYPE:
+ if (type && !ENUM_FIXED_UNDERLYING_TYPE_P (t))
+ {
+ /* Type is a restricted range integer type derived from the
+ integer_types. Find the right one. */
+ prec = TYPE_PRECISION (type);
+ tree name = DECL_NAME (TYPE_NAME (type));
+
+ for (unsigned itk = itk_none; itk--;)
+ if (integer_types[itk]
+ && DECL_NAME (TYPE_NAME (integer_types[itk])) == name)
+ {
+ type = integer_types[itk];
+ break;
+ }
+ gcc_assert (type != t->typed.type);
+ }
+ break;
+ }
+
+ WT (type);
+ if (prec && streaming_p ())
+ WU (prec);
+ }
+
+#undef WT
+#undef WU
+}
+
+// Streaming in a reference to a decl can cause that decl to be
+// TREE_USED, which is the mark_used behaviour we need most of the
+// time. The trees_in::unused can be incremented to inhibit this,
+// which is at least needed for vtables.
+
+bool
+trees_in::core_vals (tree t)
+{
+#define RU(X) ((X) = u ())
+#define RUC(T,X) ((X) = T (u ()))
+#define RT(X) ((X) = tree_node ())
+#define RTU(X) ((X) = tree_node (true))
+ tree_code code = TREE_CODE (t);
+
+ /* First by tree shape. */
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
+ {
+ RT (t->decl_minimal.name);
+ if (!DECL_TEMPLATE_PARM_P (t))
+ RT (t->decl_minimal.context);
+
+ /* Don't zap the locus just yet, we don't record it correctly
+ and thus lose all location information. */
+ t->decl_minimal.locus = state->read_location (*this);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+ {
+ RT (t->type_common.name);
+ RT (t->type_common.context);
+
+ RT (t->type_common.main_variant);
+ RT (t->type_common.canonical);
+
+ /* type_common.next_variant is internally manipulated. */
+ /* type_common.pointer_to, type_common.reference_to. */
+
+ RU (t->type_common.precision);
+ RU (t->type_common.contains_placeholder_bits);
+ RUC (machine_mode, t->type_common.mode);
+ RU (t->type_common.align);
+
+ if (!RECORD_OR_UNION_CODE_P (code))
+ {
+ RT (t->type_common.size);
+ RT (t->type_common.size_unit);
+ }
+ RT (t->type_common.attributes);
+
+ RT (t->type_common.common.chain); /* TYPE_STUB_DECL. */
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ RUC (machine_mode, t->decl_common.mode);
+ RU (t->decl_common.off_align);
+ RU (t->decl_common.align);
+
+ if (code != TEMPLATE_DECL)
+ {
+ RT (t->decl_common.size);
+ RT (t->decl_common.size_unit);
+ }
+
+ RT (t->decl_common.attributes);
+ RT (t->decl_common.abstract_origin);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+ {
+ RT (t->decl_with_vis.assembler_name);
+ RUC (symbol_visibility, t->decl_with_vis.visibility);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
+ {
+ /* Records and unions hold FIELDS, VFIELD & BINFO on these
+ things. */
+ if (!RECORD_OR_UNION_CODE_P (code) && code != ENUMERAL_TYPE)
+ {
+ /* This is not clobbering TYPE_CACHED_VALUES, because this
+ is a type that doesn't have any. */
+ gcc_checking_assert (!TYPE_CACHED_VALUES_P (t));
+ RT (t->type_non_common.values);
+ RT (t->type_non_common.maxval);
+ RT (t->type_non_common.minval);
+ }
+
+ RT (t->type_non_common.lang_1);
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_EXP))
+ {
+ t->exp.locus = state->read_location (*this);
+
+ bool vl = TREE_CODE_CLASS (code) == tcc_vl_exp;
+ for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)
+ : TREE_OPERAND_LENGTH (t)),
+ ix = unsigned (vl); ix != limit; ix++)
+ RTU (TREE_OPERAND (t, ix));
+ }
+
+ /* Then by CODE. Special cases and/or 1:1 tree shape
+ correspondance. */
+ switch (code)
+ {
+ default:
+ break;
+
+ case ARGUMENT_PACK_SELECT:
+ case DEFERRED_PARSE:
+ case IDENTIFIER_NODE:
+ case BINDING_VECTOR:
+ case SSA_NAME:
+ case TRANSLATION_UNIT_DECL:
+ case USERDEF_LITERAL:
+ return false; /* Should never meet. */
+
+ /* Constants. */
+ case COMPLEX_CST:
+ RT (TREE_REALPART (t));
+ RT (TREE_IMAGPART (t));
+ break;
+
+ case FIXED_CST:
+ /* Not suported in C++. */
+ return false;
+
+ case INTEGER_CST:
+ {
+ unsigned num = TREE_INT_CST_EXT_NUNITS (t);
+ for (unsigned ix = 0; ix != num; ix++)
+ TREE_INT_CST_ELT (t, ix) = wu ();
+ }
+ break;
+
+ case POLY_INT_CST:
+ /* Not suported in C++. */
+ return false;
+
+ case REAL_CST:
+ if (const void *bytes = buf (sizeof (real_value)))
+ TREE_REAL_CST_PTR (t)
+ = reinterpret_cast<real_value *> (memcpy (ggc_alloc<real_value> (),
+ bytes, sizeof (real_value)));
+ break;
+
+ case STRING_CST:
+ /* Streamed during start. */
+ break;
+
+ case VECTOR_CST:
+ for (unsigned ix = vector_cst_encoded_nelts (t); ix--;)
+ RT (VECTOR_CST_ENCODED_ELT (t, ix));
+ break;
+
+ /* Decls. */
+ case VAR_DECL:
+ if (DECL_CONTEXT (t)
+ && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL)
+ break;
+ /* FALLTHROUGH */
+
+ case RESULT_DECL:
+ case PARM_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (t))
+ {
+ /* The DECL_VALUE hash table is a cache, thus if we're
+ reading a duplicate (which we end up discarding), the
+ value expr will also be cleaned up at the next gc. */
+ tree val = tree_node ();
+ SET_DECL_VALUE_EXPR (t, val);
+ }
+ /* FALLTHROUGH */
+
+ case CONST_DECL:
+ case IMPORTED_DECL:
+ RT (t->decl_common.initial);
+ break;
+
+ case FIELD_DECL:
+ RT (t->field_decl.offset);
+ RT (t->field_decl.bit_field_type);
+ RT (t->field_decl.qualifier);
+ RT (t->field_decl.bit_offset);
+ RT (t->field_decl.fcontext);
+ RT (t->decl_common.initial);
+ break;
+
+ case LABEL_DECL:
+ RU (t->label_decl.label_decl_uid);
+ RU (t->label_decl.eh_landing_pad_nr);
+ break;
+
+ case FUNCTION_DECL:
+ {
+ unsigned bltin = u ();
+ t->function_decl.built_in_class = built_in_class (bltin);
+ if (bltin != NOT_BUILT_IN)
+ {
+ bltin = u ();
+ DECL_UNCHECKED_FUNCTION_CODE (t) = built_in_function (bltin);
+ }
+
+ RT (t->function_decl.personality);
+ RT (t->function_decl.function_specific_target);
+ RT (t->function_decl.function_specific_optimization);
+ RT (t->function_decl.vindex);
+ }
+ break;
+
+ case USING_DECL:
+ /* USING_DECL_DECLS */
+ RT (t->decl_common.initial);
+ /* FALLTHROUGH */
+
+ case TYPE_DECL:
+ /* USING_DECL: USING_DECL_SCOPE */
+ /* TYPE_DECL: DECL_ORIGINAL_TYPE */
+ RT (t->decl_non_common.result);
+ break;
+
+ /* Miscellaneous common nodes. */
+ case BLOCK:
+ t->block.locus = state->read_location (*this);
+ t->block.end_locus = state->read_location (*this);
+ t->block.vars = chained_decls ();
+ /* nonlocalized_vars is middle-end. */
+ RT (t->block.subblocks);
+ RT (t->block.supercontext);
+ RT (t->block.abstract_origin);
+ /* fragment_origin, fragment_chain are middle-end. */
+ RT (t->block.chain);
+ /* nonlocalized_vars, block_num, die are middle endy/debug
+ things. */
+ break;
+
+ case CALL_EXPR:
+ RUC (internal_fn, t->base.u.ifn);
+ break;
+
+ case CONSTRUCTOR:
+ if (unsigned len = u ())
+ {
+ vec_alloc (t->constructor.elts, len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ constructor_elt elt;
+
+ RT (elt.index);
+ RTU (elt.value);
+ t->constructor.elts->quick_push (elt);
+ }
+ }
+ break;
+
+ case OMP_CLAUSE:
+ {
+ RU (t->omp_clause.subcode.map_kind);
+ t->omp_clause.locus = state->read_location (*this);
+
+ unsigned len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)];
+ for (unsigned ix = 0; ix != len; ix++)
+ RT (t->omp_clause.ops[ix]);
+ }
+ break;
+
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator iter = tsi_start (t);
+ for (tree stmt; RT (stmt);)
+ tsi_link_after (&iter, stmt, TSI_CONTINUE_LINKING);
+ }
+ break;
+
+ case OPTIMIZATION_NODE:
+ case TARGET_OPTION_NODE:
+ /* Not yet implemented, see trees_out::core_vals. */
+ gcc_unreachable ();
+ break;
+
+ case TREE_BINFO:
+ RT (t->binfo.common.chain);
+ RT (t->binfo.offset);
+ RT (t->binfo.inheritance);
+ RT (t->binfo.vptr_field);
+
+ /* Do not mark the vtables as USED in the address expressions
+ here. */
+ unused++;
+ RT (t->binfo.vtable);
+ RT (t->binfo.virtuals);
+ RT (t->binfo.vtt_subvtt);
+ RT (t->binfo.vtt_vptr);
+ unused--;
+
+ BINFO_BASE_ACCESSES (t) = tree_vec ();
+ if (!get_overrun ())
+ {
+ unsigned num = vec_safe_length (BINFO_BASE_ACCESSES (t));
+ for (unsigned ix = 0; ix != num; ix++)
+ BINFO_BASE_APPEND (t, tree_node ());
+ }
+ break;
+
+ case TREE_LIST:
+ RT (t->list.purpose);
+ RT (t->list.value);
+ RT (t->list.common.chain);
+ break;
+
+ case TREE_VEC:
+ for (unsigned ix = TREE_VEC_LENGTH (t); ix--;)
+ RT (TREE_VEC_ELT (t, ix));
+ RT (t->type_common.common.chain);
+ break;
+
+ /* C++-specific nodes ... */
+ case BASELINK:
+ RT (((lang_tree_node *)t)->baselink.binfo);
+ RTU (((lang_tree_node *)t)->baselink.functions);
+ RT (((lang_tree_node *)t)->baselink.access_binfo);
+ break;
+
+ case CONSTRAINT_INFO:
+ RT (((lang_tree_node *)t)->constraint_info.template_reqs);
+ RT (((lang_tree_node *)t)->constraint_info.declarator_reqs);
+ RT (((lang_tree_node *)t)->constraint_info.associated_constr);
+ break;
+
+ case DEFERRED_NOEXCEPT:
+ RT (((lang_tree_node *)t)->deferred_noexcept.pattern);
+ RT (((lang_tree_node *)t)->deferred_noexcept.args);
+ break;
+
+ case LAMBDA_EXPR:
+ RT (((lang_tree_node *)t)->lambda_expression.capture_list);
+ RT (((lang_tree_node *)t)->lambda_expression.this_capture);
+ RT (((lang_tree_node *)t)->lambda_expression.extra_scope);
+ /* lambda_expression.pending_proxies is NULL */
+ ((lang_tree_node *)t)->lambda_expression.locus
+ = state->read_location (*this);
+ RUC (cp_lambda_default_capture_mode_type,
+ ((lang_tree_node *)t)->lambda_expression.default_capture_mode);
+ RU (((lang_tree_node *)t)->lambda_expression.discriminator);
+ break;
+
+ case OVERLOAD:
+ RT (((lang_tree_node *)t)->overload.function);
+ RT (t->common.chain);
+ break;
+
+ case PTRMEM_CST:
+ RT (((lang_tree_node *)t)->ptrmem.member);
+ break;
+
+ case STATIC_ASSERT:
+ RT (((lang_tree_node *)t)->static_assertion.condition);
+ RT (((lang_tree_node *)t)->static_assertion.message);
+ ((lang_tree_node *)t)->static_assertion.location
+ = state->read_location (*this);
+ break;
+
+ case TEMPLATE_DECL:
+ /* Streamed when reading the raw template decl itself. */
+ gcc_assert (((lang_tree_node *)t)->template_decl.arguments);
+ gcc_assert (((lang_tree_node *)t)->template_decl.result);
+ if (DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (t))
+ RT (DECL_CHAIN (t));
+ break;
+
+ case TEMPLATE_INFO:
+ RT (((lang_tree_node *)t)->template_info.tmpl);
+ RT (((lang_tree_node *)t)->template_info.args);
+ if (unsigned len = u ())
+ {
+ auto &ac = (((lang_tree_node *)t)
+ ->template_info.deferred_access_checks);
+ vec_alloc (ac, len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ deferred_access_check m;
+
+ RT (m.binfo);
+ RT (m.decl);
+ RT (m.diag_decl);
+ m.loc = state->read_location (*this);
+ ac->quick_push (m);
+ }
+ }
+ break;
+
+ case TEMPLATE_PARM_INDEX:
+ RU (((lang_tree_node *)t)->tpi.index);
+ RU (((lang_tree_node *)t)->tpi.level);
+ RU (((lang_tree_node *)t)->tpi.orig_level);
+ RT (((lang_tree_node *)t)->tpi.decl);
+ break;
+
+ case TRAIT_EXPR:
+ RT (((lang_tree_node *)t)->trait_expression.type1);
+ RT (((lang_tree_node *)t)->trait_expression.type2);
+ RUC (cp_trait_kind, ((lang_tree_node *)t)->trait_expression.kind);
+ break;
+ }
+
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
+ {
+ tree type = tree_node ();
+
+ if (type && code == ENUMERAL_TYPE && !ENUM_FIXED_UNDERLYING_TYPE_P (t))
+ {
+ unsigned precision = u ();
+
+ type = build_distinct_type_copy (type);
+ TYPE_PRECISION (type) = precision;
+ set_min_and_max_values_for_integral_type (type, precision,
+ TYPE_SIGN (type));
+ }
+
+ if (code != TEMPLATE_DECL)
+ t->typed.type = type;
+ }
+
+#undef RT
+#undef RM
+#undef RU
+ return !get_overrun ();
+}
+
+void
+trees_out::lang_decl_vals (tree t)
+{
+ const struct lang_decl *lang = DECL_LANG_SPECIFIC (t);
+#define WU(X) (u (X))
+#define WT(X) (tree_node (X))
+ /* Module index already written. */
+ switch (lang->u.base.selector)
+ {
+ default:
+ gcc_unreachable ();
+
+ case lds_fn: /* lang_decl_fn. */
+ if (streaming_p ())
+ {
+ if (DECL_NAME (t) && IDENTIFIER_OVL_OP_P (DECL_NAME (t)))
+ WU (lang->u.fn.ovl_op_code);
+ }
+
+ if (DECL_CLASS_SCOPE_P (t))
+ WT (lang->u.fn.context);
+
+ if (lang->u.fn.thunk_p)
+ {
+ /* The thunked-to function. */
+ WT (lang->u.fn.befriending_classes);
+ if (streaming_p ())
+ wi (lang->u.fn.u5.fixed_offset);
+ }
+ else
+ WT (lang->u.fn.u5.cloned_function);
+
+ if (FNDECL_USED_AUTO (t))
+ WT (lang->u.fn.u.saved_auto_return_type);
+
+ goto lds_min;
+
+ case lds_decomp: /* lang_decl_decomp. */
+ WT (lang->u.decomp.base);
+ goto lds_min;
+
+ case lds_min: /* lang_decl_min. */
+ lds_min:
+ WT (lang->u.min.template_info);
+ {
+ tree access = lang->u.min.access;
+
+ /* DECL_ACCESS needs to be maintained by the definition of the
+ (derived) class that changes the access. The other users
+ of DECL_ACCESS need to write it here. */
+ if (!DECL_THUNK_P (t)
+ && (DECL_CONTEXT (t) && TYPE_P (DECL_CONTEXT (t))))
+ access = NULL_TREE;
+
+ WT (access);
+ }
+ break;
+
+ case lds_ns: /* lang_decl_ns. */
+ break;
+
+ case lds_parm: /* lang_decl_parm. */
+ if (streaming_p ())
+ {
+ WU (lang->u.parm.level);
+ WU (lang->u.parm.index);
+ }
+ break;
+ }
+#undef WU
+#undef WT
+}
+
+bool
+trees_in::lang_decl_vals (tree t)
+{
+ struct lang_decl *lang = DECL_LANG_SPECIFIC (t);
+#define RU(X) ((X) = u ())
+#define RT(X) ((X) = tree_node ())
+
+ /* Module index already read. */
+ switch (lang->u.base.selector)
+ {
+ default:
+ gcc_unreachable ();
+
+ case lds_fn: /* lang_decl_fn. */
+ if (DECL_NAME (t) && IDENTIFIER_OVL_OP_P (DECL_NAME (t)))
+ {
+ unsigned code = u ();
+
+ /* Check consistency. */
+ if (code >= OVL_OP_MAX
+ || (ovl_op_info[IDENTIFIER_ASSIGN_OP_P (DECL_NAME (t))][code]
+ .ovl_op_code) == OVL_OP_ERROR_MARK)
+ set_overrun ();
+ else
+ lang->u.fn.ovl_op_code = code;
+ }
+
+ if (DECL_CLASS_SCOPE_P (t))
+ RT (lang->u.fn.context);
+
+ if (lang->u.fn.thunk_p)
+ {
+ RT (lang->u.fn.befriending_classes);
+ lang->u.fn.u5.fixed_offset = wi ();
+ }
+ else
+ RT (lang->u.fn.u5.cloned_function);
+
+ if (FNDECL_USED_AUTO (t))
+ RT (lang->u.fn.u.saved_auto_return_type);
+ goto lds_min;
+
+ case lds_decomp: /* lang_decl_decomp. */
+ RT (lang->u.decomp.base);
+ goto lds_min;
+
+ case lds_min: /* lang_decl_min. */
+ lds_min:
+ RT (lang->u.min.template_info);
+ RT (lang->u.min.access);
+ break;
+
+ case lds_ns: /* lang_decl_ns. */
+ break;
+
+ case lds_parm: /* lang_decl_parm. */
+ RU (lang->u.parm.level);
+ RU (lang->u.parm.index);
+ break;
+ }
+#undef RU
+#undef RT
+ return !get_overrun ();
+}
+
+/* Most of the value contents of lang_type is streamed in
+ define_class. */
+
+void
+trees_out::lang_type_vals (tree t)
+{
+ const struct lang_type *lang = TYPE_LANG_SPECIFIC (t);
+#define WU(X) (u (X))
+#define WT(X) (tree_node (X))
+ if (streaming_p ())
+ WU (lang->align);
+#undef WU
+#undef WT
+}
+
+bool
+trees_in::lang_type_vals (tree t)
+{
+ struct lang_type *lang = TYPE_LANG_SPECIFIC (t);
+#define RU(X) ((X) = u ())
+#define RT(X) ((X) = tree_node ())
+ RU (lang->align);
+#undef RU
+#undef RT
+ return !get_overrun ();
+}
+
+/* Write out the bools of T, including information about any
+ LANG_SPECIFIC information. Including allocation of any lang
+ specific object. */
+
+void
+trees_out::tree_node_bools (tree t)
+{
+ gcc_checking_assert (streaming_p ());
+
+ /* We should never stream a namespace. */
+ gcc_checking_assert (TREE_CODE (t) != NAMESPACE_DECL
+ || DECL_NAMESPACE_ALIAS (t));
+
+ core_bools (t);
+
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case tcc_declaration:
+ {
+ bool specific = DECL_LANG_SPECIFIC (t) != NULL;
+ b (specific);
+ if (specific && VAR_P (t))
+ b (DECL_DECOMPOSITION_P (t));
+ if (specific)
+ lang_decl_bools (t);
+ }
+ break;
+
+ case tcc_type:
+ {
+ bool specific = (TYPE_MAIN_VARIANT (t) == t
+ && TYPE_LANG_SPECIFIC (t) != NULL);
+ gcc_assert (TYPE_LANG_SPECIFIC (t)
+ == TYPE_LANG_SPECIFIC (TYPE_MAIN_VARIANT (t)));
+
+ b (specific);
+ if (specific)
+ lang_type_bools (t);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ bflush ();
+}
+
+bool
+trees_in::tree_node_bools (tree t)
+{
+ bool ok = core_bools (t);
+
+ if (ok)
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case tcc_declaration:
+ if (b ())
+ {
+ bool decomp = VAR_P (t) && b ();
+
+ ok = maybe_add_lang_decl_raw (t, decomp);
+ if (ok)
+ ok = lang_decl_bools (t);
+ }
+ break;
+
+ case tcc_type:
+ if (b ())
+ {
+ ok = maybe_add_lang_type_raw (t);
+ if (ok)
+ ok = lang_type_bools (t);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ bflush ();
+ if (!ok || get_overrun ())
+ return false;
+
+ return true;
+}
+
+
+/* Write out the lang-specifc vals of node T. */
+
+void
+trees_out::lang_vals (tree t)
+{
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case tcc_declaration:
+ if (DECL_LANG_SPECIFIC (t))
+ lang_decl_vals (t);
+ break;
+
+ case tcc_type:
+ if (TYPE_MAIN_VARIANT (t) == t && TYPE_LANG_SPECIFIC (t))
+ lang_type_vals (t);
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool
+trees_in::lang_vals (tree t)
+{
+ bool ok = true;
+
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case tcc_declaration:
+ if (DECL_LANG_SPECIFIC (t))
+ ok = lang_decl_vals (t);
+ break;
+
+ case tcc_type:
+ if (TYPE_LANG_SPECIFIC (t))
+ ok = lang_type_vals (t);
+ else
+ TYPE_LANG_SPECIFIC (t) = TYPE_LANG_SPECIFIC (TYPE_MAIN_VARIANT (t));
+ break;
+
+ default:
+ break;
+ }
+
+ return ok;
+}
+
+/* Write out the value fields of node T. */
+
+void
+trees_out::tree_node_vals (tree t)
+{
+ core_vals (t);
+ lang_vals (t);
+}
+
+bool
+trees_in::tree_node_vals (tree t)
+{
+ bool ok = core_vals (t);
+ if (ok)
+ ok = lang_vals (t);
+
+ return ok;
+}
+
+
+/* If T is a back reference, fixed reference or NULL, write out it's
+ code and return WK_none. Otherwise return WK_value if we must write
+ by value, or WK_normal otherwise. */
+
+walk_kind
+trees_out::ref_node (tree t)
+{
+ if (!t)
+ {
+ if (streaming_p ())
+ {
+ /* NULL_TREE -> tt_null. */
+ null_count++;
+ i (tt_null);
+ }
+ return WK_none;
+ }
+
+ if (!TREE_VISITED (t))
+ return WK_normal;
+
+ /* An already-visited tree. It must be in the map. */
+ int val = get_tag (t);
+
+ if (val == tag_value)
+ /* An entry we should walk into. */
+ return WK_value;
+
+ const char *kind;
+
+ if (val <= tag_backref)
+ {
+ /* Back reference -> -ve number */
+ if (streaming_p ())
+ i (val);
+ kind = "backref";
+ }
+ else if (val >= tag_fixed)
+ {
+ /* Fixed reference -> tt_fixed */
+ val -= tag_fixed;
+ if (streaming_p ())
+ i (tt_fixed), u (val);
+ kind = "fixed";
+ }
+
+ if (streaming_p ())
+ {
+ back_ref_count++;
+ dump (dumper::TREE)
+ && dump ("Wrote %s:%d %C:%N%S", kind, val, TREE_CODE (t), t, t);
+ }
+ return WK_none;
+}
+
+tree
+trees_in::back_ref (int tag)
+{
+ tree res = NULL_TREE;
+
+ if (tag < 0 && unsigned (~tag) < back_refs.length ())
+ res = back_refs[~tag];
+
+ if (!res
+ /* Checking TREE_CODE is a dereference, so we know this is not a
+ wild pointer. Checking the code provides evidence we've not
+ corrupted something. */
+ || TREE_CODE (res) >= MAX_TREE_CODES)
+ set_overrun ();
+ else
+ dump (dumper::TREE) && dump ("Read backref:%d found %C:%N%S", tag,
+ TREE_CODE (res), res, res);
+ return res;
+}
+
+unsigned
+trees_out::add_indirect_tpl_parms (tree parms)
+{
+ unsigned len = 0;
+ for (; parms; parms = TREE_CHAIN (parms), len++)
+ {
+ if (TREE_VISITED (parms))
+ break;
+
+ int tag = insert (parms);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Indirect:%d template's parameter %u %C:%N",
+ tag, len, TREE_CODE (parms), parms);
+ }
+
+ if (streaming_p ())
+ u (len);
+
+ return len;
+}
+
+unsigned
+trees_in::add_indirect_tpl_parms (tree parms)
+{
+ unsigned len = u ();
+ for (unsigned ix = 0; ix != len; parms = TREE_CHAIN (parms), ix++)
+ {
+ int tag = insert (parms);
+ dump (dumper::TREE)
+ && dump ("Indirect:%d template's parameter %u %C:%N",
+ tag, ix, TREE_CODE (parms), parms);
+ }
+
+ return len;
+}
+
+/* We've just found DECL by name. Insert nodes that come with it, but
+ cannot be found by name, so we'll not accidentally walk into them. */
+
+void
+trees_out::add_indirects (tree decl)
+{
+ unsigned count = 0;
+
+ // FIXME:OPTIMIZATION We'll eventually want default fn parms of
+ // templates and perhaps default template parms too. The former can
+ // be referenced from instantiations (as they are lazily
+ // instantiated). Also (deferred?) exception specifications of
+ // templates. See the note about PARM_DECLs in trees_out::decl_node.
+ tree inner = decl;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ count += add_indirect_tpl_parms (DECL_TEMPLATE_PARMS (decl));
+
+ inner = DECL_TEMPLATE_RESULT (decl);
+ int tag = insert (inner);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Indirect:%d template's result %C:%N",
+ tag, TREE_CODE (inner), inner);
+ count++;
+ }
+
+ if (TREE_CODE (inner) == TYPE_DECL)
+ {
+ /* Make sure the type is in the map too. Otherwise we get
+ different RECORD_TYPEs for the same type, and things go
+ south. */
+ tree type = TREE_TYPE (inner);
+ gcc_checking_assert (DECL_ORIGINAL_TYPE (inner)
+ || TYPE_NAME (type) == inner);
+ int tag = insert (type);
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Indirect:%d decl's type %C:%N", tag,
+ TREE_CODE (type), type);
+ count++;
+ }
+
+ if (streaming_p ())
+ {
+ u (count);
+ dump (dumper::TREE) && dump ("Inserted %u indirects", count);
+ }
+}
+
+bool
+trees_in::add_indirects (tree decl)
+{
+ unsigned count = 0;
+
+ tree inner = decl;
+ if (TREE_CODE (inner) == TEMPLATE_DECL)
+ {
+ count += add_indirect_tpl_parms (DECL_TEMPLATE_PARMS (decl));
+
+ inner = DECL_TEMPLATE_RESULT (decl);
+ int tag = insert (inner);
+ dump (dumper::TREE)
+ && dump ("Indirect:%d templates's result %C:%N", tag,
+ TREE_CODE (inner), inner);
+ count++;
+ }
+
+ if (TREE_CODE (inner) == TYPE_DECL)
+ {
+ tree type = TREE_TYPE (inner);
+ gcc_checking_assert (DECL_ORIGINAL_TYPE (inner)
+ || TYPE_NAME (type) == inner);
+ int tag = insert (type);
+ dump (dumper::TREE)
+ && dump ("Indirect:%d decl's type %C:%N", tag, TREE_CODE (type), type);
+ count++;
+ }
+
+ dump (dumper::TREE) && dump ("Inserted %u indirects", count);
+ return count == u ();
+}
+
+/* Stream a template parameter. There are 4.5 kinds of parameter:
+ a) Template - TEMPLATE_DECL->TYPE_DECL->TEMPLATE_TEMPLATE_PARM
+ TEMPLATE_TYPE_PARM_INDEX TPI
+ b) Type - TYPE_DECL->TEMPLATE_TYPE_PARM TEMPLATE_TYPE_PARM_INDEX TPI
+ c.1) NonTYPE - PARM_DECL DECL_INITIAL TPI We meet this first
+ c.2) NonTYPE - CONST_DECL DECL_INITIAL Same TPI
+ d) BoundTemplate - TYPE_DECL->BOUND_TEMPLATE_TEMPLATE_PARM
+ TEMPLATE_TYPE_PARM_INDEX->TPI
+ TEMPLATE_TEMPLATE_PARM_INFO->TEMPLATE_INFO
+
+ All of these point to a TEMPLATE_PARM_INDEX, and #B also has a TEMPLATE_INFO
+*/
+
+void
+trees_out::tpl_parm_value (tree parm)
+{
+ gcc_checking_assert (DECL_P (parm) && DECL_TEMPLATE_PARM_P (parm));
+
+ int parm_tag = insert (parm);
+ if (streaming_p ())
+ {
+ i (tt_tpl_parm);
+ dump (dumper::TREE) && dump ("Writing template parm:%d %C:%N",
+ parm_tag, TREE_CODE (parm), parm);
+ start (parm);
+ tree_node_bools (parm);
+ }
+
+ tree inner = parm;
+ if (TREE_CODE (inner) == TEMPLATE_DECL)
+ {
+ inner = DECL_TEMPLATE_RESULT (inner);
+ int inner_tag = insert (inner);
+ if (streaming_p ())
+ {
+ dump (dumper::TREE) && dump ("Writing inner template parm:%d %C:%N",
+ inner_tag, TREE_CODE (inner), inner);
+ start (inner);
+ tree_node_bools (inner);
+ }
+ }
+
+ tree type = NULL_TREE;
+ if (TREE_CODE (inner) == TYPE_DECL)
+ {
+ type = TREE_TYPE (inner);
+ int type_tag = insert (type);
+ if (streaming_p ())
+ {
+ dump (dumper::TREE) && dump ("Writing template parm type:%d %C:%N",
+ type_tag, TREE_CODE (type), type);
+ start (type);
+ tree_node_bools (type);
+ }
+ }
+
+ if (inner != parm)
+ {
+ /* This is a template-template parameter. */
+ unsigned tpl_levels = 0;
+ tpl_header (parm, &tpl_levels);
+ tpl_parms_fini (parm, tpl_levels);
+ }
+
+ tree_node_vals (parm);
+ if (inner != parm)
+ tree_node_vals (inner);
+ if (type)
+ {
+ tree_node_vals (type);
+ if (DECL_NAME (inner) == auto_identifier
+ || DECL_NAME (inner) == decltype_auto_identifier)
+ {
+ /* Placeholder auto. */
+ tree_node (DECL_INITIAL (inner));
+ tree_node (DECL_SIZE_UNIT (inner));
+ }
+ }
+
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Wrote template parm:%d %C:%N",
+ parm_tag, TREE_CODE (parm), parm);
+}
+
+tree
+trees_in::tpl_parm_value ()
+{
+ tree parm = start ();
+ if (!parm || !tree_node_bools (parm))
+ return NULL_TREE;
+
+ int parm_tag = insert (parm);
+ dump (dumper::TREE) && dump ("Reading template parm:%d %C:%N",
+ parm_tag, TREE_CODE (parm), parm);
+
+ tree inner = parm;
+ if (TREE_CODE (inner) == TEMPLATE_DECL)
+ {
+ inner = start ();
+ if (!inner || !tree_node_bools (inner))
+ return NULL_TREE;
+ int inner_tag = insert (inner);
+ dump (dumper::TREE) && dump ("Reading inner template parm:%d %C:%N",
+ inner_tag, TREE_CODE (inner), inner);
+ DECL_TEMPLATE_RESULT (parm) = inner;
+ }
+
+ tree type = NULL_TREE;
+ if (TREE_CODE (inner) == TYPE_DECL)
+ {
+ type = start ();
+ if (!type || !tree_node_bools (type))
+ return NULL_TREE;
+ int type_tag = insert (type);
+ dump (dumper::TREE) && dump ("Reading template parm type:%d %C:%N",
+ type_tag, TREE_CODE (type), type);
+
+ TREE_TYPE (inner) = TREE_TYPE (parm) = type;
+ TYPE_NAME (type) = parm;
+ }
+
+ if (inner != parm)
+ {
+ /* A template template parameter. */
+ unsigned tpl_levels = 0;
+ tpl_header (parm, &tpl_levels);
+ tpl_parms_fini (parm, tpl_levels);
+ }
+
+ tree_node_vals (parm);
+ if (inner != parm)
+ tree_node_vals (inner);
+ if (type)
+ {
+ tree_node_vals (type);
+ if (DECL_NAME (inner) == auto_identifier
+ || DECL_NAME (inner) == decltype_auto_identifier)
+ {
+ /* Placeholder auto. */
+ DECL_INITIAL (inner) = tree_node ();
+ DECL_SIZE_UNIT (inner) = tree_node ();
+ }
+ if (TYPE_CANONICAL (type))
+ {
+ gcc_checking_assert (TYPE_CANONICAL (type) == type);
+ TYPE_CANONICAL (type) = canonical_type_parameter (type);
+ }
+ }
+
+ dump (dumper::TREE) && dump ("Read template parm:%d %C:%N",
+ parm_tag, TREE_CODE (parm), parm);
+
+ return parm;
+}
+
+void
+trees_out::install_entity (tree decl, depset *dep)
+{
+ gcc_checking_assert (streaming_p ());
+
+ /* Write the entity index, so we can insert it as soon as we
+ know this is new. */
+ u (dep ? dep->cluster + 1 : 0);
+ if (CHECKING_P && dep)
+ {
+ /* Add it to the entity map, such that we can tell it is
+ part of us. */
+ bool existed;
+ unsigned *slot = &entity_map->get_or_insert
+ (DECL_UID (decl), &existed);
+ if (existed)
+ /* If it existed, it should match. */
+ gcc_checking_assert (decl == (*entity_ary)[*slot]);
+ *slot = ~dep->cluster;
+ }
+}
+
+bool
+trees_in::install_entity (tree decl)
+{
+ unsigned entity_index = u ();
+ if (!entity_index)
+ return false;
+
+ if (entity_index > state->entity_num)
+ {
+ set_overrun ();
+ return false;
+ }
+
+ /* Insert the real decl into the entity ary. */
+ unsigned ident = state->entity_lwm + entity_index - 1;
+ binding_slot &elt = (*entity_ary)[ident];
+
+ /* See module_state::read_pendings for how this got set. */
+ int pending = elt.get_lazy () & 3;
+
+ elt = decl;
+
+ /* And into the entity map, if it's not already there. */
+ if (!DECL_LANG_SPECIFIC (decl)
+ || !DECL_MODULE_ENTITY_P (decl))
+ {
+ retrofit_lang_decl (decl);
+ DECL_MODULE_ENTITY_P (decl) = true;
+
+ /* Insert into the entity hash (it cannot already be there). */
+ bool existed;
+ unsigned &slot = entity_map->get_or_insert (DECL_UID (decl), &existed);
+ gcc_checking_assert (!existed);
+ slot = ident;
+ }
+ else if (pending != 0)
+ {
+ unsigned key_ident = import_entity_index (decl);
+ if (pending & 1)
+ if (!pending_table->add (key_ident, ~ident))
+ pending &= ~1;
+
+ if (pending & 2)
+ if (!pending_table->add (~key_ident, ~ident))
+ pending &= ~2;
+ }
+
+ if (pending & 1)
+ DECL_MODULE_PENDING_SPECIALIZATIONS_P (decl) = true;
+
+ if (pending & 2)
+ {
+ DECL_MODULE_PENDING_MEMBERS_P (decl) = true;
+ gcc_checking_assert (TREE_CODE (decl) != TEMPLATE_DECL);
+ }
+
+ return true;
+}
+
+static bool has_definition (tree decl);
+
+/* DECL is a decl node that must be written by value. DEP is the
+ decl's depset. */
+
+void
+trees_out::decl_value (tree decl, depset *dep)
+{
+ /* We should not be writing clones or template parms. */
+ gcc_checking_assert (DECL_P (decl)
+ && !DECL_CLONED_FUNCTION_P (decl)
+ && !DECL_TEMPLATE_PARM_P (decl));
+
+ /* We should never be writing non-typedef ptrmemfuncs by value. */
+ gcc_checking_assert (TREE_CODE (decl) != TYPE_DECL
+ || DECL_ORIGINAL_TYPE (decl)
+ || !TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)));
+
+ merge_kind mk = get_merge_kind (decl, dep);
+
+ if (CHECKING_P)
+ {
+ /* Never start in the middle of a template. */
+ int use_tpl = -1;
+ if (tree ti = node_template_info (decl, use_tpl))
+ gcc_checking_assert (TREE_CODE (TI_TEMPLATE (ti)) == OVERLOAD
+ || TREE_CODE (TI_TEMPLATE (ti)) == FIELD_DECL
+ || (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti))
+ != decl));
+ }
+
+ if (streaming_p ())
+ {
+ /* A new node -> tt_decl. */
+ decl_val_count++;
+ i (tt_decl);
+ u (mk);
+ start (decl);
+
+ if (mk != MK_unique)
+ {
+ if (!(mk & MK_template_mask) && !state->is_header ())
+ {
+ /* Tell the importer whether this is a global module entity,
+ or a module entity. This bool merges into the next block
+ of bools. Sneaky. */
+ tree o = get_originating_module_decl (decl);
+ bool is_mod = false;
+
+ if (dep && dep->is_alias_tmpl_inst ())
+ /* Alias template instantiations are templatey, but
+ found by name. */
+ is_mod = false;
+ else if (DECL_LANG_SPECIFIC (o) && DECL_MODULE_PURVIEW_P (o))
+ is_mod = true;
+ b (is_mod);
+ }
+ b (dep && dep->has_defn ());
+ }
+ tree_node_bools (decl);
+ }
+
+ int tag = insert (decl, WK_value);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Writing %s:%d %C:%N%S", merge_kind_name[mk], tag,
+ TREE_CODE (decl), decl, decl);
+
+ tree inner = decl;
+ int inner_tag = 0;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ if (dep && dep->is_alias_tmpl_inst ())
+ inner = NULL_TREE;
+ else
+ {
+ inner = DECL_TEMPLATE_RESULT (decl);
+ inner_tag = insert (inner, WK_value);
+ }
+
+ if (streaming_p ())
+ {
+ int code = inner ? TREE_CODE (inner) : 0;
+ u (code);
+ if (inner)
+ {
+ start (inner, true);
+ tree_node_bools (inner);
+ dump (dumper::TREE)
+ && dump ("Writing %s:%d %C:%N%S", merge_kind_name[mk], inner_tag,
+ TREE_CODE (inner), inner, inner);
+ }
+ }
+ }
+
+ tree type = NULL_TREE;
+ int type_tag = 0;
+ tree stub_decl = NULL_TREE;
+ int stub_tag = 0;
+ if (inner && TREE_CODE (inner) == TYPE_DECL)
+ {
+ type = TREE_TYPE (inner);
+ bool has_type = (type == TYPE_MAIN_VARIANT (type)
+ && TYPE_NAME (type) == inner);
+
+ if (streaming_p ())
+ u (has_type ? TREE_CODE (type) : 0);
+
+ if (has_type)
+ {
+ type_tag = insert (type, WK_value);
+ if (streaming_p ())
+ {
+ start (type, true);
+ tree_node_bools (type);
+ dump (dumper::TREE)
+ && dump ("Writing type:%d %C:%N", type_tag,
+ TREE_CODE (type), type);
+ }
+
+ stub_decl = TYPE_STUB_DECL (type);
+ bool has_stub = inner != stub_decl;
+ if (streaming_p ())
+ u (has_stub ? TREE_CODE (stub_decl) : 0);
+ if (has_stub)
+ {
+ stub_tag = insert (stub_decl);
+ if (streaming_p ())
+ {
+ start (stub_decl, true);
+ tree_node_bools (stub_decl);
+ dump (dumper::TREE)
+ && dump ("Writing stub_decl:%d %C:%N", stub_tag,
+ TREE_CODE (stub_decl), stub_decl);
+ }
+ }
+ else
+ stub_decl = NULL_TREE;
+ }
+ else
+ /* Regular typedef. */
+ type = NULL_TREE;
+ }
+
+ /* Stream the container, we want it correctly canonicalized before
+ we start emitting keys for this decl. */
+ tree container = decl_container (decl);
+
+ unsigned tpl_levels = 0;
+ if (decl != inner)
+ tpl_header (decl, &tpl_levels);
+ if (inner && TREE_CODE (inner) == FUNCTION_DECL)
+ fn_parms_init (inner);
+
+ /* Now write out the merging information, and then really
+ install the tag values. */
+ key_mergeable (tag, mk, decl, inner, container, dep);
+
+ if (streaming_p ())
+ dump (dumper::MERGE)
+ && dump ("Wrote:%d's %s merge key %C:%N", tag,
+ merge_kind_name[mk], TREE_CODE (decl), decl);
+
+ if (inner && TREE_CODE (inner) == FUNCTION_DECL)
+ fn_parms_fini (inner);
+
+ if (!is_key_order ())
+ tree_node_vals (decl);
+
+ if (inner_tag)
+ {
+ if (!is_key_order ())
+ tree_node_vals (inner);
+ tpl_parms_fini (decl, tpl_levels);
+ }
+ else if (!inner)
+ {
+ /* A template alias instantiation. */
+ inner = DECL_TEMPLATE_RESULT (decl);
+ if (!is_key_order ())
+ tree_node (inner);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote(%d) alias template %C:%N",
+ get_tag (inner), TREE_CODE (inner), inner);
+ inner = NULL_TREE;
+ }
+
+ if (type && !is_key_order ())
+ {
+ tree_node_vals (type);
+ if (stub_decl)
+ tree_node_vals (stub_decl);
+ }
+
+ if (!is_key_order ())
+ tree_node (get_constraints (decl));
+
+ if (streaming_p ())
+ {
+ /* Do not stray outside this section. */
+ gcc_checking_assert (!dep || dep->section == dep_hash->section);
+
+ /* Write the entity index, so we can insert it as soon as we
+ know this is new. */
+ install_entity (decl, dep);
+ }
+
+ if (inner
+ && VAR_OR_FUNCTION_DECL_P (inner)
+ && DECL_LANG_SPECIFIC (inner)
+ && DECL_MODULE_ATTACHMENTS_P (inner)
+ && !is_key_order ())
+ {
+ /* Stream the attached entities. */
+ attachset *set = attached_table->get (DECL_UID (inner));
+ unsigned num = set->num;
+ if (streaming_p ())
+ u (num);
+ for (unsigned ix = 0; ix != num; ix++)
+ {
+ tree attached = set->values[ix];
+ tree_node (attached);
+ if (streaming_p ())
+ dump (dumper::MERGE)
+ && dump ("Written %d[%u] attached decl %N", tag, ix, attached);
+ }
+ }
+
+ bool is_typedef = (!type && inner
+ && TREE_CODE (inner) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (inner)
+ && TYPE_NAME (TREE_TYPE (inner)) == inner);
+ if (is_typedef)
+ {
+ /* A typedef type. */
+ int type_tag = insert (TREE_TYPE (inner));
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Cloned:%d typedef %C:%N", type_tag,
+ TREE_CODE (TREE_TYPE (inner)), TREE_TYPE (inner));
+ }
+
+ if (streaming_p () && DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
+ {
+ bool cloned_p
+ = (DECL_CHAIN (decl) && DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl)));
+ bool needs_vtt_parm_p
+ = (cloned_p && CLASSTYPE_VBASECLASSES (DECL_CONTEXT (decl)));
+ bool omit_inherited_parms_p
+ = (cloned_p && DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
+ && base_ctor_omit_inherited_parms (decl));
+ unsigned flags = (int (cloned_p) << 0
+ | int (needs_vtt_parm_p) << 1
+ | int (omit_inherited_parms_p) << 2);
+ u (flags);
+ dump (dumper::TREE) && dump ("CDTOR %N is %scloned",
+ decl, cloned_p ? "" : "not ");
+ }
+
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Written decl:%d %C:%N", tag,
+ TREE_CODE (decl), decl);
+
+ if (!inner || NAMESPACE_SCOPE_P (inner))
+ gcc_checking_assert (!inner
+ || !dep == (VAR_OR_FUNCTION_DECL_P (inner)
+ && DECL_LOCAL_DECL_P (inner)));
+ else if ((TREE_CODE (inner) == TYPE_DECL
+ && TYPE_NAME (TREE_TYPE (inner)) == inner
+ && !is_typedef)
+ || TREE_CODE (inner) == FUNCTION_DECL)
+ {
+ bool write_defn = !dep && has_definition (decl);
+ if (streaming_p ())
+ u (write_defn);
+ if (write_defn)
+ write_definition (decl);
+ }
+}
+
+tree
+trees_in::decl_value ()
+{
+ int tag = 0;
+ bool is_mod = false;
+ bool has_defn = false;
+ unsigned mk_u = u ();
+ if (mk_u >= MK_hwm || !merge_kind_name[mk_u])
+ {
+ set_overrun ();
+ return NULL_TREE;
+ }
+
+ unsigned saved_unused = unused;
+ unused = 0;
+
+ merge_kind mk = merge_kind (mk_u);
+
+ tree decl = start ();
+ if (decl)
+ {
+ if (mk != MK_unique)
+ {
+ if (!(mk & MK_template_mask) && !state->is_header ())
+ /* See note in trees_out about where this bool is sequenced. */
+ is_mod = b ();
+
+ has_defn = b ();
+ }
+
+ if (!tree_node_bools (decl))
+ decl = NULL_TREE;
+ }
+
+ /* Insert into map. */
+ tag = insert (decl);
+ if (decl)
+ dump (dumper::TREE)
+ && dump ("Reading:%d %C", tag, TREE_CODE (decl));
+
+ tree inner = decl;
+ int inner_tag = 0;
+ if (decl && TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ int code = u ();
+ if (!code)
+ {
+ inner = NULL_TREE;
+ DECL_TEMPLATE_RESULT (decl) = error_mark_node;
+ }
+ else
+ {
+ inner = start (code);
+ if (inner && tree_node_bools (inner))
+ DECL_TEMPLATE_RESULT (decl) = inner;
+ else
+ decl = NULL_TREE;
+
+ inner_tag = insert (inner);
+ if (decl)
+ dump (dumper::TREE)
+ && dump ("Reading:%d %C", inner_tag, TREE_CODE (inner));
+ }
+ }
+
+ tree type = NULL_TREE;
+ int type_tag = 0;
+ tree stub_decl = NULL_TREE;
+ int stub_tag = 0;
+ if (decl && inner && TREE_CODE (inner) == TYPE_DECL)
+ {
+ if (unsigned type_code = u ())
+ {
+ type = start (type_code);
+ if (type && tree_node_bools (type))
+ {
+ TREE_TYPE (inner) = type;
+ TYPE_NAME (type) = inner;
+ }
+ else
+ decl = NULL_TREE;
+
+ type_tag = insert (type);
+ if (decl)
+ dump (dumper::TREE)
+ && dump ("Reading type:%d %C", type_tag, TREE_CODE (type));
+
+ if (unsigned stub_code = u ())
+ {
+ stub_decl = start (stub_code);
+ if (stub_decl && tree_node_bools (stub_decl))
+ {
+ TREE_TYPE (stub_decl) = type;
+ TYPE_STUB_DECL (type) = stub_decl;
+ }
+ else
+ decl = NULL_TREE;
+
+ stub_tag = insert (stub_decl);
+ if (decl)
+ dump (dumper::TREE)
+ && dump ("Reading stub_decl:%d %C", stub_tag,
+ TREE_CODE (stub_decl));
+ }
+ }
+ }
+
+ if (!decl)
+ {
+ bail:
+ if (inner_tag != 0)
+ back_refs[~inner_tag] = NULL_TREE;
+ if (type_tag != 0)
+ back_refs[~type_tag] = NULL_TREE;
+ if (stub_tag != 0)
+ back_refs[~stub_tag] = NULL_TREE;
+ if (tag != 0)
+ back_refs[~tag] = NULL_TREE;
+ set_overrun ();
+ /* Bail. */
+ unused = saved_unused;
+ return NULL_TREE;
+ }
+
+ /* Read the container, to ensure it's already been streamed in. */
+ tree container = decl_container ();
+ unsigned tpl_levels = 0;
+
+ /* Figure out if this decl is already known about. */
+ int parm_tag = 0;
+
+ if (decl != inner)
+ if (!tpl_header (decl, &tpl_levels))
+ goto bail;
+ if (inner && TREE_CODE (inner) == FUNCTION_DECL)
+ parm_tag = fn_parms_init (inner);
+
+ tree existing = key_mergeable (tag, mk, decl, inner, type, container, is_mod);
+ tree existing_inner = existing;
+ if (existing)
+ {
+ if (existing == error_mark_node)
+ goto bail;
+
+ if (TREE_CODE (STRIP_TEMPLATE (existing)) == TYPE_DECL)
+ {
+ tree etype = TREE_TYPE (existing);
+ if (TYPE_LANG_SPECIFIC (etype)
+ && COMPLETE_TYPE_P (etype)
+ && !CLASSTYPE_MEMBER_VEC (etype))
+ /* Give it a member vec, we're likely gonna be looking
+ inside it. */
+ set_class_bindings (etype, -1);
+ }
+
+ /* Install the existing decl into the back ref array. */
+ register_duplicate (decl, existing);
+ back_refs[~tag] = existing;
+ if (inner_tag != 0)
+ {
+ existing_inner = DECL_TEMPLATE_RESULT (existing);
+ back_refs[~inner_tag] = existing_inner;
+ }
+
+ if (type_tag != 0)
+ {
+ tree existing_type = TREE_TYPE (existing);
+ back_refs[~type_tag] = existing_type;
+ if (stub_tag != 0)
+ back_refs[~stub_tag] = TYPE_STUB_DECL (existing_type);
+ }
+ }
+
+ if (parm_tag)
+ fn_parms_fini (parm_tag, inner, existing_inner, has_defn);
+
+ if (!tree_node_vals (decl))
+ goto bail;
+
+ if (inner_tag)
+ {
+ gcc_checking_assert (DECL_TEMPLATE_RESULT (decl) == inner);
+
+ if (!tree_node_vals (inner))
+ goto bail;
+
+ if (!tpl_parms_fini (decl, tpl_levels))
+ goto bail;
+ }
+ else if (!inner)
+ {
+ inner = tree_node ();
+ DECL_TEMPLATE_RESULT (decl) = inner;
+ TREE_TYPE (decl) = TREE_TYPE (inner);
+ dump (dumper::TREE)
+ && dump ("Read alias template %C:%N", TREE_CODE (inner), inner);
+ inner = NULL_TREE;
+ }
+
+ if (type && (!tree_node_vals (type)
+ || (stub_decl && !tree_node_vals (stub_decl))))
+ goto bail;
+
+ tree constraints = tree_node ();
+
+ dump (dumper::TREE) && dump ("Read:%d %C:%N", tag, TREE_CODE (decl), decl);
+
+ /* Regular typedefs will have a NULL TREE_TYPE at this point. */
+ bool is_typedef = (!type && inner
+ && TREE_CODE (inner) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (inner)
+ && !TREE_TYPE (inner));
+ if (is_typedef)
+ {
+ /* Frob it to be ready for cloning. */
+ TREE_TYPE (inner) = DECL_ORIGINAL_TYPE (inner);
+ DECL_ORIGINAL_TYPE (inner) = NULL_TREE;
+ }
+
+ existing = back_refs[~tag];
+ bool installed = install_entity (existing);
+ bool is_new = existing == decl;
+
+ if (inner
+ && VAR_OR_FUNCTION_DECL_P (inner)
+ && DECL_LANG_SPECIFIC (inner)
+ && DECL_MODULE_ATTACHMENTS_P (inner))
+ {
+ /* Read and maybe install the attached entities. */
+ attachset *set
+ = attached_table->get (DECL_UID (STRIP_TEMPLATE (existing)));
+ unsigned num = u ();
+ if (!is_new == !set)
+ set_overrun ();
+ if (is_new)
+ set = attached_table->create (DECL_UID (inner), num, NULL_TREE);
+ for (unsigned ix = 0; !get_overrun () && ix != num; ix++)
+ {
+ tree attached = tree_node ();
+ dump (dumper::MERGE)
+ && dump ("Read %d[%u] %s attached decl %N", tag, ix,
+ is_new ? "new" : "matched", attached);
+ if (is_new)
+ set->values[ix] = attached;
+ else if (set->values[ix] != attached)
+ set_overrun ();
+ }
+ }
+
+ if (is_new)
+ {
+ /* A newly discovered node. */
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
+ /* Mark this identifier as naming a virtual function --
+ lookup_overrides relies on this optimization. */
+ IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = true;
+
+ if (installed)
+ {
+ /* Mark the entity as imported and add it to the entity
+ array and map. */
+ retrofit_lang_decl (decl);
+ DECL_MODULE_IMPORT_P (decl) = true;
+ if (inner_tag)
+ {
+ retrofit_lang_decl (inner);
+ DECL_MODULE_IMPORT_P (inner) = true;
+ }
+ }
+
+ if (constraints)
+ set_constraints (decl, constraints);
+
+ if (TREE_CODE (decl) == INTEGER_CST && !TREE_OVERFLOW (decl))
+ {
+ decl = cache_integer_cst (decl, true);
+ back_refs[~tag] = decl;
+ }
+
+ if (is_typedef)
+ set_underlying_type (inner);
+
+ if (inner_tag)
+ /* Set the TEMPLATE_DECL's type. */
+ TREE_TYPE (decl) = TREE_TYPE (inner);
+
+ /* The late insertion of an alias here or an implicit member
+ (next block), is ok, because we ensured that all imports were
+ loaded up before we started this cluster. Thus an insertion
+ from some other import cannot have happened between the
+ merged insertion above and these insertions down here. */
+ if (mk == MK_alias_spec)
+ {
+ /* Insert into type table. */
+ tree ti = DECL_TEMPLATE_INFO (inner);
+ spec_entry elt =
+ {TI_TEMPLATE (ti), TI_ARGS (ti), TREE_TYPE (inner)};
+ tree texist = match_mergeable_specialization (false, &elt);
+ if (texist)
+ set_overrun ();
+ }
+
+ if (DECL_ARTIFICIAL (decl)
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && !DECL_TEMPLATE_INFO (decl)
+ && DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
+ && TYPE_SIZE (DECL_CONTEXT (decl))
+ && !DECL_THUNK_P (decl))
+ /* A new implicit member function, when the class is
+ complete. This means the importee declared it, and
+ we must now add it to the class. Note that implicit
+ member fns of template instantiations do not themselves
+ look like templates. */
+ if (!install_implicit_member (inner))
+ set_overrun ();
+ }
+ else
+ {
+ /* DECL is the to-be-discarded decl. Its internal pointers will
+ be to the EXISTING's structure. Frob it to point to its
+ own other structures, so loading its definition will alter
+ it, and not the existing decl. */
+ dump (dumper::MERGE) && dump ("Deduping %N", existing);
+
+ if (inner_tag)
+ DECL_TEMPLATE_RESULT (decl) = inner;
+
+ if (type)
+ {
+ /* Point at the to-be-discarded type & decl. */
+ TYPE_NAME (type) = inner;
+ TREE_TYPE (inner) = type;
+
+ TYPE_STUB_DECL (type) = stub_decl ? stub_decl : inner;
+ if (stub_decl)
+ TREE_TYPE (stub_decl) = type;
+ }
+
+ if (inner_tag)
+ /* Set the TEMPLATE_DECL's type. */
+ TREE_TYPE (decl) = TREE_TYPE (inner);
+
+ if (!is_matching_decl (existing, decl))
+ unmatched_duplicate (existing);
+
+ /* And our result is the existing node. */
+ decl = existing;
+ }
+
+ if (is_typedef)
+ {
+ /* Insert the type into the array now. */
+ tag = insert (TREE_TYPE (decl));
+ dump (dumper::TREE)
+ && dump ("Cloned:%d typedef %C:%N",
+ tag, TREE_CODE (TREE_TYPE (decl)), TREE_TYPE (decl));
+ }
+
+ unused = saved_unused;
+
+ if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
+ {
+ unsigned flags = u ();
+
+ if (is_new)
+ {
+ bool cloned_p = flags & 1;
+ dump (dumper::TREE) && dump ("CDTOR %N is %scloned",
+ decl, cloned_p ? "" : "not ");
+ if (cloned_p)
+ build_cdtor_clones (decl, flags & 2, flags & 4,
+ /* Update the member vec, if there is
+ one (we're in a different cluster
+ to the class defn). */
+ CLASSTYPE_MEMBER_VEC (DECL_CONTEXT (decl)));
+ }
+ }
+
+ if (inner
+ && !NAMESPACE_SCOPE_P (inner)
+ && ((TREE_CODE (inner) == TYPE_DECL
+ && TYPE_NAME (TREE_TYPE (inner)) == inner
+ && !is_typedef)
+ || TREE_CODE (inner) == FUNCTION_DECL)
+ && u ())
+ read_definition (decl);
+
+ return decl;
+}
+
+/* DECL is an unnameable member of CTX. Return a suitable identifying
+ index. */
+
+static unsigned
+get_field_ident (tree ctx, tree decl)
+{
+ gcc_checking_assert (TREE_CODE (decl) == USING_DECL
+ || !DECL_NAME (decl)
+ || IDENTIFIER_ANON_P (DECL_NAME (decl)));
+
+ unsigned ix = 0;
+ for (tree fields = TYPE_FIELDS (ctx);
+ fields; fields = DECL_CHAIN (fields))
+ {
+ if (fields == decl)
+ return ix;
+
+ if (DECL_CONTEXT (fields) == ctx
+ && (TREE_CODE (fields) == USING_DECL
+ || (TREE_CODE (fields) == FIELD_DECL
+ && (!DECL_NAME (fields)
+ || IDENTIFIER_ANON_P (DECL_NAME (fields))))))
+ /* Count this field. */
+ ix++;
+ }
+ gcc_unreachable ();
+}
+
+static tree
+lookup_field_ident (tree ctx, unsigned ix)
+{
+ for (tree fields = TYPE_FIELDS (ctx);
+ fields; fields = DECL_CHAIN (fields))
+ if (DECL_CONTEXT (fields) == ctx
+ && (TREE_CODE (fields) == USING_DECL
+ || (TREE_CODE (fields) == FIELD_DECL
+ && (!DECL_NAME (fields)
+ || IDENTIFIER_ANON_P (DECL_NAME (fields))))))
+ if (!ix--)
+ return fields;
+
+ return NULL_TREE;
+}
+
+/* Reference DECL. REF indicates the walk kind we are performing.
+ Return true if we should write this decl by value. */
+
+bool
+trees_out::decl_node (tree decl, walk_kind ref)
+{
+ gcc_checking_assert (DECL_P (decl) && !DECL_TEMPLATE_PARM_P (decl)
+ && DECL_CONTEXT (decl));
+
+ if (ref == WK_value)
+ {
+ depset *dep = dep_hash->find_dependency (decl);
+ decl_value (decl, dep);
+ return false;
+ }
+
+ switch (TREE_CODE (decl))
+ {
+ default:
+ break;
+
+ case FUNCTION_DECL:
+ gcc_checking_assert (!DECL_LOCAL_DECL_P (decl));
+ break;
+
+ case RESULT_DECL:
+ /* Unlike PARM_DECLs, RESULT_DECLs are only generated and
+ referenced when we're inside the function itself. */
+ return true;
+
+ case PARM_DECL:
+ {
+ if (streaming_p ())
+ i (tt_parm);
+ tree_node (DECL_CONTEXT (decl));
+ if (streaming_p ())
+ {
+ /* That must have put this in the map. */
+ walk_kind ref = ref_node (decl);
+ if (ref != WK_none)
+ // FIXME:OPTIMIZATION We can wander into bits of the
+ // template this was instantiated from. For instance
+ // deferred noexcept and default parms. Currently we'll
+ // end up cloning those bits of tree. It would be nice
+ // to reference those specific nodes. I think putting
+ // those things in the map when we reference their
+ // template by name. See the note in add_indirects.
+ return true;
+
+ dump (dumper::TREE)
+ && dump ("Wrote %s reference %N",
+ TREE_CODE (decl) == PARM_DECL ? "parameter" : "result",
+ decl);
+ }
+ }
+ return false;
+
+ case IMPORTED_DECL:
+ /* This describes a USING_DECL to the ME's debug machinery. It
+ originates from the fortran FE, and has nothing to do with
+ C++ modules. */
+ return true;
+
+ case LABEL_DECL:
+ return true;
+
+ case CONST_DECL:
+ {
+ /* If I end up cloning enum decls, implementing C++20 using
+ E::v, this will need tweaking. */
+ if (streaming_p ())
+ i (tt_enum_decl);
+ tree ctx = DECL_CONTEXT (decl);
+ gcc_checking_assert (TREE_CODE (ctx) == ENUMERAL_TYPE);
+ tree_node (ctx);
+ tree_node (DECL_NAME (decl));
+
+ int tag = insert (decl);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote enum decl:%d %C:%N", tag, TREE_CODE (decl), decl);
+ return false;
+ }
+ break;
+
+ case USING_DECL:
+ if (TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ break;
+ /* FALLTHROUGH */
+
+ case FIELD_DECL:
+ {
+ if (streaming_p ())
+ i (tt_data_member);
+
+ tree ctx = DECL_CONTEXT (decl);
+ tree_node (ctx);
+
+ tree name = NULL_TREE;
+
+ if (TREE_CODE (decl) == USING_DECL)
+ ;
+ else
+ {
+ name = DECL_NAME (decl);
+ if (name && IDENTIFIER_ANON_P (name))
+ name = NULL_TREE;
+ }
+
+ tree_node (name);
+ if (!name && streaming_p ())
+ {
+ unsigned ix = get_field_ident (ctx, decl);
+ u (ix);
+ }
+
+ int tag = insert (decl);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote member:%d %C:%N", tag, TREE_CODE (decl), decl);
+ return false;
+ }
+ break;
+
+ case VAR_DECL:
+ gcc_checking_assert (!DECL_LOCAL_DECL_P (decl));
+ if (DECL_VTABLE_OR_VTT_P (decl))
+ {
+ /* VTT or VTABLE, they are all on the vtables list. */
+ tree ctx = CP_DECL_CONTEXT (decl);
+ tree vtable = CLASSTYPE_VTABLES (ctx);
+ for (unsigned ix = 0; ; vtable = DECL_CHAIN (vtable), ix++)
+ if (vtable == decl)
+ {
+ gcc_checking_assert (DECL_VIRTUAL_P (decl));
+ if (streaming_p ())
+ {
+ u (tt_vtable);
+ u (ix);
+ dump (dumper::TREE)
+ && dump ("Writing vtable %N[%u]", ctx, ix);
+ }
+ tree_node (ctx);
+ return false;
+ }
+ gcc_unreachable ();
+ }
+
+ if (DECL_TINFO_P (decl))
+ {
+ tinfo:
+ /* A typeinfo, tt_tinfo_typedef or tt_tinfo_var. */
+ bool is_var = TREE_CODE (decl) == VAR_DECL;
+ tree type = TREE_TYPE (decl);
+ unsigned ix = get_pseudo_tinfo_index (type);
+ if (streaming_p ())
+ {
+ i (is_var ? tt_tinfo_var : tt_tinfo_typedef);
+ u (ix);
+ }
+
+ if (is_var)
+ {
+ /* We also need the type it is for and mangled name, so
+ the reader doesn't need to complete the type (which
+ would break section ordering). The type it is for is
+ stashed on the name's TREE_TYPE. */
+ tree name = DECL_NAME (decl);
+ tree_node (name);
+ type = TREE_TYPE (name);
+ tree_node (type);
+ }
+
+ int tag = insert (decl);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote tinfo_%s:%d %u %N", is_var ? "var" : "type",
+ tag, ix, type);
+
+ if (!is_var)
+ {
+ tag = insert (type);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote tinfo_type:%d %u %N", tag, ix, type);
+ }
+ return false;
+ }
+ break;
+
+ case TYPE_DECL:
+ if (DECL_TINFO_P (decl))
+ goto tinfo;
+ break;
+ }
+
+ if (DECL_THUNK_P (decl))
+ {
+ /* Thunks are similar to binfos -- write the thunked-to decl and
+ then thunk-specific key info. */
+ if (streaming_p ())
+ {
+ i (tt_thunk);
+ i (THUNK_FIXED_OFFSET (decl));
+ }
+
+ tree target = decl;
+ while (DECL_THUNK_P (target))
+ target = THUNK_TARGET (target);
+ tree_node (target);
+ tree_node (THUNK_VIRTUAL_OFFSET (decl));
+ int tag = insert (decl);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote:%d thunk %N to %N", tag, DECL_NAME (decl), target);
+ return false;
+ }
+
+ if (DECL_CLONED_FUNCTION_P (decl))
+ {
+ tree target = get_clone_target (decl);
+ if (streaming_p ())
+ i (tt_clone_ref);
+
+ tree_node (target);
+ tree_node (DECL_NAME (decl));
+ int tag = insert (decl);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote:%d clone %N of %N", tag, DECL_NAME (decl), target);
+ return false;
+ }
+
+ /* Everything left should be a thing that is in the entity table.
+ Mostly things that can be defined outside of their (original
+ declaration) context. */
+ gcc_checking_assert (TREE_CODE (decl) == TEMPLATE_DECL
+ || TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == USING_DECL
+ || TREE_CODE (decl) == CONCEPT_DECL
+ || TREE_CODE (decl) == NAMESPACE_DECL);
+
+ int use_tpl = -1;
+ tree ti = node_template_info (decl, use_tpl);
+ tree tpl = NULL_TREE;
+
+ /* If this is the TEMPLATE_DECL_RESULT of a TEMPLATE_DECL, get the
+ TEMPLATE_DECL. Note TI_TEMPLATE is not a TEMPLATE_DECL for
+ (some) friends, so we need to check that. */
+ // FIXME: Should local friend template specializations be by value?
+ // They don't get idents so we'll never know they're imported, but I
+ // think we can only reach them from the TU that defines the
+ // befriending class?
+ if (ti && TREE_CODE (TI_TEMPLATE (ti)) == TEMPLATE_DECL
+ && DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti)) == decl)
+ {
+ tpl = TI_TEMPLATE (ti);
+ partial_template:
+ if (streaming_p ())
+ {
+ i (tt_template);
+ dump (dumper::TREE)
+ && dump ("Writing implicit template %C:%N%S",
+ TREE_CODE (tpl), tpl, tpl);
+ }
+ tree_node (tpl);
+
+ /* Streaming TPL caused us to visit DECL and maybe its type. */
+ gcc_checking_assert (TREE_VISITED (decl));
+ if (DECL_IMPLICIT_TYPEDEF_P (decl))
+ gcc_checking_assert (TREE_VISITED (TREE_TYPE (decl)));
+ return false;
+ }
+
+ tree ctx = CP_DECL_CONTEXT (decl);
+ depset *dep = NULL;
+ if (streaming_p ())
+ dep = dep_hash->find_dependency (decl);
+ else if (TREE_CODE (ctx) != FUNCTION_DECL
+ || TREE_CODE (decl) == TEMPLATE_DECL
+ || (dep_hash->sneakoscope && DECL_IMPLICIT_TYPEDEF_P (decl))
+ || (DECL_LANG_SPECIFIC (decl)
+ && DECL_MODULE_IMPORT_P (decl)))
+ dep = dep_hash->add_dependency (decl,
+ TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl)
+ ? depset::EK_NAMESPACE : depset::EK_DECL);
+
+ if (!dep)
+ {
+ /* Some internal entity of context. Do by value. */
+ decl_value (decl, NULL);
+ return false;
+ }
+
+ if (dep->get_entity_kind () == depset::EK_REDIRECT)
+ {
+ /* The DECL_TEMPLATE_RESULT of a partial specialization.
+ Write the partial specialization's template. */
+ depset *redirect = dep->deps[0];
+ gcc_checking_assert (redirect->get_entity_kind () == depset::EK_PARTIAL);
+ tpl = redirect->get_entity ();
+ goto partial_template;
+ }
+
+ if (streaming_p ())
+ {
+ /* Locate the entity. */
+ unsigned index = dep->cluster;
+ unsigned import = 0;
+
+ if (dep->is_import ())
+ import = dep->section;
+ else if (CHECKING_P)
+ /* It should be what we put there. */
+ gcc_checking_assert (index == ~import_entity_index (decl));
+
+#if CHECKING_P
+ if (importedness)
+ gcc_assert (!import == (importedness < 0));
+#endif
+ i (tt_entity);
+ u (import);
+ u (index);
+ }
+
+ int tag = insert (decl);
+ if (streaming_p () && dump (dumper::TREE))
+ {
+ char const *kind = "import";
+ module_state *from = (*modules)[0];
+ if (dep->is_import ())
+ /* Rediscover the unremapped index. */
+ from = import_entity_module (import_entity_index (decl));
+ else
+ {
+ tree o = get_originating_module_decl (decl);
+ kind = (DECL_LANG_SPECIFIC (o) && DECL_MODULE_PURVIEW_P (o)
+ ? "purview" : "GMF");
+ }
+ dump ("Wrote %s:%d %C:%N@%M", kind,
+ tag, TREE_CODE (decl), decl, from);
+ }
+
+ add_indirects (decl);
+
+ return false;
+}
+
+void
+trees_out::type_node (tree type)
+{
+ gcc_assert (TYPE_P (type));
+
+ tree root = (TYPE_NAME (type)
+ ? TREE_TYPE (TYPE_NAME (type)) : TYPE_MAIN_VARIANT (type));
+
+ if (type != root)
+ {
+ if (streaming_p ())
+ i (tt_variant_type);
+ tree_node (root);
+
+ int flags = -1;
+
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ int quals = type_memfn_quals (type);
+ int rquals = type_memfn_rqual (type);
+ tree raises = TYPE_RAISES_EXCEPTIONS (type);
+ bool late = TYPE_HAS_LATE_RETURN_TYPE (type);
+
+ if (raises != TYPE_RAISES_EXCEPTIONS (root)
+ || rquals != type_memfn_rqual (root)
+ || quals != type_memfn_quals (root)
+ || late != TYPE_HAS_LATE_RETURN_TYPE (root))
+ flags = rquals | (int (late) << 2) | (quals << 3);
+ }
+ else
+ {
+ if (TYPE_USER_ALIGN (type))
+ flags = exact_log2 (TYPE_ALIGN (type));
+ }
+
+ if (streaming_p ())
+ i (flags);
+
+ if (flags < 0)
+ ;
+ else if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ tree raises = TYPE_RAISES_EXCEPTIONS (type);
+ if (raises == TYPE_RAISES_EXCEPTIONS (root))
+ raises = error_mark_node;
+ tree_node (raises);
+ }
+
+ tree_node (TYPE_ATTRIBUTES (type));
+
+ if (streaming_p ())
+ {
+ /* Qualifiers. */
+ int rquals = cp_type_quals (root);
+ int quals = cp_type_quals (type);
+ if (quals == rquals)
+ quals = -1;
+ i (quals);
+ }
+
+ if (ref_node (type) != WK_none)
+ {
+ int tag = insert (type);
+ if (streaming_p ())
+ {
+ i (0);
+ dump (dumper::TREE)
+ && dump ("Wrote:%d variant type %C", tag, TREE_CODE (type));
+ }
+ }
+ return;
+ }
+
+ if (tree name = TYPE_NAME (type))
+ if ((TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name))
+ || DECL_TEMPLATE_PARM_P (name)
+ || TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ {
+ /* We can meet template parms that we didn't meet in the
+ tpl_parms walk, because we're referring to a derived type
+ that was previously constructed from equivalent template
+ parms. */
+ if (streaming_p ())
+ {
+ i (tt_typedef_type);
+ dump (dumper::TREE)
+ && dump ("Writing %stypedef %C:%N",
+ DECL_IMPLICIT_TYPEDEF_P (name) ? "implicit " : "",
+ TREE_CODE (name), name);
+ }
+ tree_node (name);
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Wrote typedef %C:%N%S",
+ TREE_CODE (name), name, name);
+ gcc_checking_assert (TREE_VISITED (type));
+ return;
+ }
+
+ if (TYPE_PTRMEMFUNC_P (type))
+ {
+ /* This is a distinct type node, masquerading as a structure. */
+ tree fn_type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ if (streaming_p ())
+ i (tt_ptrmem_type);
+ tree_node (fn_type);
+ int tag = insert (type);
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Written:%d ptrmem type", tag);
+ return;
+ }
+
+ if (streaming_p ())
+ {
+ u (tt_derived_type);
+ u (TREE_CODE (type));
+ }
+
+ tree_node (TREE_TYPE (type));
+ switch (TREE_CODE (type))
+ {
+ default:
+ /* We should never meet a type here that is indescribable in
+ terms of other types. */
+ gcc_unreachable ();
+
+ case ARRAY_TYPE:
+ tree_node (TYPE_DOMAIN (type));
+ if (streaming_p ())
+ /* Dependent arrays are constructed with TYPE_DEPENENT_P
+ already set. */
+ u (TYPE_DEPENDENT_P (type));
+ break;
+
+ case COMPLEX_TYPE:
+ /* No additional data. */
+ break;
+
+ case BOOLEAN_TYPE:
+ /* A non-standard boolean type. */
+ if (streaming_p ())
+ u (TYPE_PRECISION (type));
+ break;
+
+ case INTEGER_TYPE:
+ if (TREE_TYPE (type))
+ {
+ /* A range type (representing an array domain). */
+ tree_node (TYPE_MIN_VALUE (type));
+ tree_node (TYPE_MAX_VALUE (type));
+ }
+ else
+ {
+ /* A new integral type (representing a bitfield). */
+ if (streaming_p ())
+ {
+ unsigned prec = TYPE_PRECISION (type);
+ bool unsigned_p = TYPE_UNSIGNED (type);
+
+ u ((prec << 1) | unsigned_p);
+ }
+ }
+ break;
+
+ case METHOD_TYPE:
+ case FUNCTION_TYPE:
+ {
+ gcc_checking_assert (type_memfn_rqual (type) == REF_QUAL_NONE);
+
+ tree arg_types = TYPE_ARG_TYPES (type);
+ if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ tree_node (TREE_TYPE (TREE_VALUE (arg_types)));
+ arg_types = TREE_CHAIN (arg_types);
+ }
+ tree_node (arg_types);
+ }
+ break;
+
+ case OFFSET_TYPE:
+ tree_node (TYPE_OFFSET_BASETYPE (type));
+ break;
+
+ case POINTER_TYPE:
+ /* No additional data. */
+ break;
+
+ case REFERENCE_TYPE:
+ if (streaming_p ())
+ u (TYPE_REF_IS_RVALUE (type));
+ break;
+
+ case DECLTYPE_TYPE:
+ case TYPEOF_TYPE:
+ case UNDERLYING_TYPE:
+ tree_node (TYPE_VALUES_RAW (type));
+ if (TREE_CODE (type) == DECLTYPE_TYPE)
+ /* We stash a whole bunch of things into decltype's
+ flags. */
+ if (streaming_p ())
+ tree_node_bools (type);
+ break;
+
+ case TYPE_ARGUMENT_PACK:
+ /* No additional data. */
+ break;
+
+ case TYPE_PACK_EXPANSION:
+ if (streaming_p ())
+ u (PACK_EXPANSION_LOCAL_P (type));
+ tree_node (PACK_EXPANSION_PARAMETER_PACKS (type));
+ break;
+
+ case TYPENAME_TYPE:
+ {
+ tree_node (TYPE_CONTEXT (type));
+ tree_node (DECL_NAME (TYPE_NAME (type)));
+ tree_node (TYPENAME_TYPE_FULLNAME (type));
+ if (streaming_p ())
+ {
+ enum tag_types tag_type = none_type;
+ if (TYPENAME_IS_ENUM_P (type))
+ tag_type = enum_type;
+ else if (TYPENAME_IS_CLASS_P (type))
+ tag_type = class_type;
+ u (int (tag_type));
+ }
+ }
+ break;
+
+ case UNBOUND_CLASS_TEMPLATE:
+ {
+ tree decl = TYPE_NAME (type);
+ tree_node (DECL_CONTEXT (decl));
+ tree_node (DECL_NAME (decl));
+ tree_node (DECL_TEMPLATE_PARMS (decl));
+ }
+ break;
+
+ case VECTOR_TYPE:
+ if (streaming_p ())
+ {
+ poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (type);
+ /* to_constant asserts that only coeff[0] is of interest. */
+ wu (static_cast<unsigned HOST_WIDE_INT> (nunits.to_constant ()));
+ }
+ break;
+ }
+
+ /* We may have met the type during emitting the above. */
+ if (ref_node (type) != WK_none)
+ {
+ int tag = insert (type);
+ if (streaming_p ())
+ {
+ i (0);
+ dump (dumper::TREE)
+ && dump ("Wrote:%d derived type %C", tag, TREE_CODE (type));
+ }
+ }
+
+ return;
+}
+
+/* T is (mostly*) a non-mergeable node that must be written by value.
+ The mergeable case is a BINFO, which are as-if DECLSs. */
+
+void
+trees_out::tree_value (tree t)
+{
+ /* We should never be writing a type by value. tree_type should
+ have streamed it, or we're going via its TYPE_DECL. */
+ gcc_checking_assert (!TYPE_P (t));
+
+ if (DECL_P (t))
+ /* No template, type, var or function, except anonymous
+ non-context vars. */
+ gcc_checking_assert ((TREE_CODE (t) != TEMPLATE_DECL
+ && TREE_CODE (t) != TYPE_DECL
+ && (TREE_CODE (t) != VAR_DECL
+ || (!DECL_NAME (t) && !DECL_CONTEXT (t)))
+ && TREE_CODE (t) != FUNCTION_DECL));
+
+ if (streaming_p ())
+ {
+ /* A new node -> tt_node. */
+ tree_val_count++;
+ i (tt_node);
+ start (t);
+ tree_node_bools (t);
+ }
+
+ if (TREE_CODE (t) == TREE_BINFO)
+ /* Binfos are decl-like and need merging information. */
+ binfo_mergeable (t);
+
+ int tag = insert (t, WK_value);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Writing tree:%d %C:%N", tag, TREE_CODE (t), t);
+
+ tree_node_vals (t);
+
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Written tree:%d %C:%N", tag, TREE_CODE (t), t);
+}
+
+tree
+trees_in::tree_value ()
+{
+ tree t = start ();
+ if (!t || !tree_node_bools (t))
+ return NULL_TREE;
+
+ tree existing = t;
+ if (TREE_CODE (t) == TREE_BINFO)
+ {
+ tree type;
+ unsigned ix = binfo_mergeable (&type);
+ if (TYPE_BINFO (type))
+ {
+ /* We already have a definition, this must be a duplicate. */
+ dump (dumper::MERGE)
+ && dump ("Deduping binfo %N[%u]", type, ix);
+ existing = TYPE_BINFO (type);
+ while (existing && ix)
+ existing = TREE_CHAIN (existing);
+ if (existing)
+ register_duplicate (t, existing);
+ else
+ /* Error, mismatch -- diagnose in read_class_def's
+ checking. */
+ existing = t;
+ }
+ }
+
+ /* Insert into map. */
+ int tag = insert (existing);
+ dump (dumper::TREE)
+ && dump ("Reading tree:%d %C", tag, TREE_CODE (t));
+
+ if (!tree_node_vals (t))
+ {
+ back_refs[~tag] = NULL_TREE;
+ set_overrun ();
+ /* Bail. */
+ return NULL_TREE;
+ }
+
+ dump (dumper::TREE) && dump ("Read tree:%d %C:%N", tag, TREE_CODE (t), t);
+
+ if (TREE_CODE (existing) == INTEGER_CST && !TREE_OVERFLOW (existing))
+ {
+ existing = cache_integer_cst (t, true);
+ back_refs[~tag] = existing;
+ }
+
+ return existing;
+}
+
+/* Stream out tree node T. We automatically create local back
+ references, which is essentially a single pass lisp
+ self-referential structure pretty-printer. */
+
+void
+trees_out::tree_node (tree t)
+{
+ dump.indent ();
+ walk_kind ref = ref_node (t);
+ if (ref == WK_none)
+ goto done;
+
+ if (ref != WK_normal)
+ goto skip_normal;
+
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ {
+ /* An identifier node -> tt_id, tt_conv_id, tt_anon_id, tt_lambda_id. */
+ int code = tt_id;
+ if (IDENTIFIER_ANON_P (t))
+ code = IDENTIFIER_LAMBDA_P (t) ? tt_lambda_id : tt_anon_id;
+ else if (IDENTIFIER_CONV_OP_P (t))
+ code = tt_conv_id;
+
+ if (streaming_p ())
+ i (code);
+
+ if (code == tt_conv_id)
+ {
+ tree type = TREE_TYPE (t);
+ gcc_checking_assert (type || t == conv_op_identifier);
+ tree_node (type);
+ }
+ else if (code == tt_id && streaming_p ())
+ str (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
+
+ int tag = insert (t);
+ if (streaming_p ())
+ {
+ /* We know the ordering of the 4 id tags. */
+ static const char *const kinds[] =
+ {"", "conv_op ", "anon ", "lambda "};
+ dump (dumper::TREE)
+ && dump ("Written:%d %sidentifier:%N", tag,
+ kinds[code - tt_id],
+ code == tt_conv_id ? TREE_TYPE (t) : t);
+ }
+ goto done;
+ }
+
+ if (TREE_CODE (t) == TREE_BINFO)
+ {
+ /* A BINFO -> tt_binfo.
+ We must do this by reference. We stream the binfo tree
+ itself when streaming its owning RECORD_TYPE. That we got
+ here means the dominating type is not in this SCC. */
+ if (streaming_p ())
+ i (tt_binfo);
+ binfo_mergeable (t);
+ gcc_checking_assert (!TREE_VISITED (t));
+ int tag = insert (t);
+ if (streaming_p ())
+ dump (dumper::TREE) && dump ("Inserting binfo:%d %N", tag, t);
+ goto done;
+ }
+
+ if (TREE_CODE (t) == INTEGER_CST
+ && !TREE_OVERFLOW (t)
+ && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
+ {
+ /* An integral constant of enumeral type. See if it matches one
+ of the enumeration values. */
+ for (tree values = TYPE_VALUES (TREE_TYPE (t));
+ values; values = TREE_CHAIN (values))
+ {
+ tree decl = TREE_VALUE (values);
+ if (tree_int_cst_equal (DECL_INITIAL (decl), t))
+ {
+ if (streaming_p ())
+ u (tt_enum_value);
+ tree_node (decl);
+ dump (dumper::TREE) && dump ("Written enum value %N", decl);
+ goto done;
+ }
+ }
+ /* It didn't match. We'll write it a an explicit INTEGER_CST
+ node. */
+ }
+
+ if (TYPE_P (t))
+ {
+ type_node (t);
+ goto done;
+ }
+
+ if (DECL_P (t))
+ {
+ if (DECL_TEMPLATE_PARM_P (t))
+ {
+ tpl_parm_value (t);
+ goto done;
+ }
+
+ if (!DECL_CONTEXT (t))
+ {
+ /* There are a few cases of decls with no context. We'll write
+ these by value, but first assert they are cases we expect. */
+ gcc_checking_assert (ref == WK_normal);
+ switch (TREE_CODE (t))
+ {
+ default: gcc_unreachable ();
+
+ case LABEL_DECL:
+ /* CASE_LABEL_EXPRs contain uncontexted LABEL_DECLs. */
+ gcc_checking_assert (!DECL_NAME (t));
+ break;
+
+ case VAR_DECL:
+ /* AGGR_INIT_EXPRs cons up anonymous uncontexted VAR_DECLs. */
+ gcc_checking_assert (!DECL_NAME (t)
+ && DECL_ARTIFICIAL (t));
+ break;
+
+ case PARM_DECL:
+ /* REQUIRES_EXPRs have a tree list of uncontexted
+ PARM_DECLS. It'd be nice if they had a
+ distinguishing flag to double check. */
+ break;
+ }
+ goto by_value;
+ }
+ }
+
+ skip_normal:
+ if (DECL_P (t) && !decl_node (t, ref))
+ goto done;
+
+ /* Otherwise by value */
+ by_value:
+ tree_value (t);
+
+ done:
+ /* And, breath out. */
+ dump.outdent ();
+}
+
+/* Stream in a tree node. */
+
+tree
+trees_in::tree_node (bool is_use)
+{
+ if (get_overrun ())
+ return NULL_TREE;
+
+ dump.indent ();
+ int tag = i ();
+ tree res = NULL_TREE;
+ switch (tag)
+ {
+ default:
+ /* backref, pull it out of the map. */
+ res = back_ref (tag);
+ break;
+
+ case tt_null:
+ /* NULL_TREE. */
+ break;
+
+ case tt_fixed:
+ /* A fixed ref, find it in the fixed_ref array. */
+ {
+ unsigned fix = u ();
+ if (fix < (*fixed_trees).length ())
+ {
+ res = (*fixed_trees)[fix];
+ dump (dumper::TREE) && dump ("Read fixed:%u %C:%N%S", fix,
+ TREE_CODE (res), res, res);
+ }
+
+ if (!res)
+ set_overrun ();
+ }
+ break;
+
+ case tt_parm:
+ {
+ tree fn = tree_node ();
+ if (fn && TREE_CODE (fn) == FUNCTION_DECL)
+ res = tree_node ();
+ if (res)
+ dump (dumper::TREE)
+ && dump ("Read %s reference %N",
+ TREE_CODE (res) == PARM_DECL ? "parameter" : "result",
+ res);
+ }
+ break;
+
+ case tt_node:
+ /* A new node. Stream it in. */
+ res = tree_value ();
+ break;
+
+ case tt_decl:
+ /* A new decl. Stream it in. */
+ res = decl_value ();
+ break;
+
+ case tt_tpl_parm:
+ /* A template parameter. Stream it in. */
+ res = tpl_parm_value ();
+ break;
+
+ case tt_id:
+ /* An identifier node. */
+ {
+ size_t l;
+ const char *chars = str (&l);
+ res = get_identifier_with_length (chars, l);
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("Read identifier:%d %N", tag, res);
+ }
+ break;
+
+ case tt_conv_id:
+ /* A conversion operator. Get the type and recreate the
+ identifier. */
+ {
+ tree type = tree_node ();
+ if (!get_overrun ())
+ {
+ res = type ? make_conv_op_name (type) : conv_op_identifier;
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("Created conv_op:%d %S for %N", tag, res, type);
+ }
+ }
+ break;
+
+ case tt_anon_id:
+ case tt_lambda_id:
+ /* An anonymous or lambda id. */
+ {
+ res = make_anon_name ();
+ if (tag == tt_lambda_id)
+ IDENTIFIER_LAMBDA_P (res) = true;
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("Read %s identifier:%d %N",
+ IDENTIFIER_LAMBDA_P (res) ? "lambda" : "anon", tag, res);
+ }
+ break;
+
+ case tt_typedef_type:
+ res = tree_node ();
+ if (res)
+ {
+ dump (dumper::TREE)
+ && dump ("Read %stypedef %C:%N",
+ DECL_IMPLICIT_TYPEDEF_P (res) ? "implicit " : "",
+ TREE_CODE (res), res);
+ res = TREE_TYPE (res);
+ }
+ break;
+
+ case tt_derived_type:
+ /* A type derived from some other type. */
+ {
+ enum tree_code code = tree_code (u ());
+ res = tree_node ();
+
+ switch (code)
+ {
+ default:
+ set_overrun ();
+ break;
+
+ case ARRAY_TYPE:
+ {
+ tree domain = tree_node ();
+ int dep = u ();
+ if (!get_overrun ())
+ res = build_cplus_array_type (res, domain, dep);
+ }
+ break;
+
+ case COMPLEX_TYPE:
+ if (!get_overrun ())
+ res = build_complex_type (res);
+ break;
+
+ case BOOLEAN_TYPE:
+ {
+ unsigned precision = u ();
+ if (!get_overrun ())
+ res = build_nonstandard_boolean_type (precision);
+ }
+ break;
+
+ case INTEGER_TYPE:
+ if (res)
+ {
+ /* A range type (representing an array domain). */
+ tree min = tree_node ();
+ tree max = tree_node ();
+
+ if (!get_overrun ())
+ res = build_range_type (res, min, max);
+ }
+ else
+ {
+ /* A new integral type (representing a bitfield). */
+ unsigned enc = u ();
+ if (!get_overrun ())
+ res = build_nonstandard_integer_type (enc >> 1, enc & 1);
+ }
+ break;
+
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ tree klass = code == METHOD_TYPE ? tree_node () : NULL_TREE;
+ tree args = tree_node ();
+ if (!get_overrun ())
+ {
+ if (klass)
+ res = build_method_type_directly (klass, res, args);
+ else
+ res = build_function_type (res, args);
+ }
+ }
+ break;
+
+ case OFFSET_TYPE:
+ {
+ tree base = tree_node ();
+ if (!get_overrun ())
+ res = build_offset_type (base, res);
+ }
+ break;
+
+ case POINTER_TYPE:
+ if (!get_overrun ())
+ res = build_pointer_type (res);
+ break;
+
+ case REFERENCE_TYPE:
+ {
+ bool rval = bool (u ());
+ if (!get_overrun ())
+ res = cp_build_reference_type (res, rval);
+ }
+ break;
+
+ case DECLTYPE_TYPE:
+ case TYPEOF_TYPE:
+ case UNDERLYING_TYPE:
+ {
+ tree expr = tree_node ();
+ if (!get_overrun ())
+ {
+ res = cxx_make_type (code);
+ TYPE_VALUES_RAW (res) = expr;
+ if (code == DECLTYPE_TYPE)
+ tree_node_bools (res);
+ SET_TYPE_STRUCTURAL_EQUALITY (res);
+ }
+ }
+ break;
+
+ case TYPE_ARGUMENT_PACK:
+ if (!get_overrun ())
+ {
+ tree pack = cxx_make_type (TYPE_ARGUMENT_PACK);
+ SET_ARGUMENT_PACK_ARGS (pack, res);
+ res = pack;
+ }
+ break;
+
+ case TYPE_PACK_EXPANSION:
+ {
+ bool local = u ();
+ tree param_packs = tree_node ();
+ if (!get_overrun ())
+ {
+ tree expn = cxx_make_type (TYPE_PACK_EXPANSION);
+ SET_TYPE_STRUCTURAL_EQUALITY (expn);
+ SET_PACK_EXPANSION_PATTERN (expn, res);
+ PACK_EXPANSION_PARAMETER_PACKS (expn) = param_packs;
+ PACK_EXPANSION_LOCAL_P (expn) = local;
+ res = expn;
+ }
+ }
+ break;
+
+ case TYPENAME_TYPE:
+ {
+ tree ctx = tree_node ();
+ tree name = tree_node ();
+ tree fullname = tree_node ();
+ enum tag_types tag_type = tag_types (u ());
+
+ if (!get_overrun ())
+ res = build_typename_type (ctx, name, fullname, tag_type);
+ }
+ break;
+
+ case UNBOUND_CLASS_TEMPLATE:
+ {
+ tree ctx = tree_node ();
+ tree name = tree_node ();
+ tree parms = tree_node ();
+
+ if (!get_overrun ())
+ res = make_unbound_class_template_raw (ctx, name, parms);
+ }
+ break;
+
+ case VECTOR_TYPE:
+ {
+ unsigned HOST_WIDE_INT nunits = wu ();
+ if (!get_overrun ())
+ res = build_vector_type (res, static_cast<poly_int64> (nunits));
+ }
+ break;
+ }
+
+ int tag = i ();
+ if (!tag)
+ {
+ tag = insert (res);
+ if (res)
+ dump (dumper::TREE)
+ && dump ("Created:%d derived type %C", tag, code);
+ }
+ else
+ res = back_ref (tag);
+ }
+ break;
+
+ case tt_variant_type:
+ /* Variant of some type. */
+ {
+ res = tree_node ();
+ int flags = i ();
+ if (get_overrun ())
+ ;
+ else if (flags < 0)
+ /* No change. */;
+ else if (TREE_CODE (res) == FUNCTION_TYPE
+ || TREE_CODE (res) == METHOD_TYPE)
+ {
+ cp_ref_qualifier rqual = cp_ref_qualifier (flags & 3);
+ bool late = (flags >> 2) & 1;
+ cp_cv_quals quals = cp_cv_quals (flags >> 3);
+
+ tree raises = tree_node ();
+ if (raises == error_mark_node)
+ raises = TYPE_RAISES_EXCEPTIONS (res);
+
+ res = build_cp_fntype_variant (res, rqual, raises, late);
+ if (TREE_CODE (res) == FUNCTION_TYPE)
+ res = apply_memfn_quals (res, quals, rqual);
+ }
+ else
+ {
+ res = build_aligned_type (res, 1u << flags);
+ TYPE_USER_ALIGN (res) = true;
+ }
+
+ if (tree attribs = tree_node ())
+ res = cp_build_type_attribute_variant (res, attribs);
+
+ int quals = i ();
+ if (quals >= 0 && !get_overrun ())
+ res = cp_build_qualified_type (res, quals);
+
+ int tag = i ();
+ if (!tag)
+ {
+ tag = insert (res);
+ if (res)
+ dump (dumper::TREE)
+ && dump ("Created:%d variant type %C", tag, TREE_CODE (res));
+ }
+ else
+ res = back_ref (tag);
+ }
+ break;
+
+ case tt_tinfo_var:
+ case tt_tinfo_typedef:
+ /* A tinfo var or typedef. */
+ {
+ bool is_var = tag == tt_tinfo_var;
+ unsigned ix = u ();
+ tree type = NULL_TREE;
+
+ if (is_var)
+ {
+ tree name = tree_node ();
+ type = tree_node ();
+
+ if (!get_overrun ())
+ res = get_tinfo_decl_direct (type, name, int (ix));
+ }
+ else
+ {
+ if (!get_overrun ())
+ {
+ type = get_pseudo_tinfo_type (ix);
+ res = TYPE_NAME (type);
+ }
+ }
+ if (res)
+ {
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("Created tinfo_%s:%d %S:%u for %N",
+ is_var ? "var" : "decl", tag, res, ix, type);
+ if (!is_var)
+ {
+ tag = insert (type);
+ dump (dumper::TREE)
+ && dump ("Created tinfo_type:%d %u %N", tag, ix, type);
+ }
+ }
+ }
+ break;
+
+ case tt_ptrmem_type:
+ /* A pointer to member function. */
+ {
+ tree type = tree_node ();
+ if (type && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+ {
+ res = build_ptrmemfunc_type (type);
+ int tag = insert (res);
+ dump (dumper::TREE) && dump ("Created:%d ptrmem type", tag);
+ }
+ else
+ set_overrun ();
+ }
+ break;
+
+ case tt_enum_value:
+ /* An enum const value. */
+ {
+ if (tree decl = tree_node ())
+ {
+ dump (dumper::TREE) && dump ("Read enum value %N", decl);
+ res = DECL_INITIAL (decl);
+ }
+
+ if (!res)
+ set_overrun ();
+ }
+ break;
+
+ case tt_enum_decl:
+ /* An enum decl. */
+ {
+ tree ctx = tree_node ();
+ tree name = tree_node ();
+
+ if (!get_overrun ()
+ && TREE_CODE (ctx) == ENUMERAL_TYPE)
+ res = find_enum_member (ctx, name);
+
+ if (!res)
+ set_overrun ();
+ else
+ {
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("Read enum decl:%d %C:%N", tag, TREE_CODE (res), res);
+ }
+ }
+ break;
+
+ case tt_data_member:
+ /* A data member. */
+ {
+ tree ctx = tree_node ();
+ tree name = tree_node ();
+
+ if (!get_overrun ()
+ && RECORD_OR_UNION_TYPE_P (ctx))
+ {
+ if (name)
+ res = lookup_class_binding (ctx, name);
+ else
+ res = lookup_field_ident (ctx, u ());
+
+ if (!res
+ || TREE_CODE (res) != FIELD_DECL
+ || DECL_CONTEXT (res) != ctx)
+ res = NULL_TREE;
+ }
+
+ if (!res)
+ set_overrun ();
+ else
+ {
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("Read member:%d %C:%N", tag, TREE_CODE (res), res);
+ }
+ }
+ break;
+
+ case tt_binfo:
+ /* A BINFO. Walk the tree of the dominating type. */
+ {
+ tree type;
+ unsigned ix = binfo_mergeable (&type);
+ if (type)
+ {
+ res = TYPE_BINFO (type);
+ for (; ix && res; res = TREE_CHAIN (res))
+ ix--;
+ if (!res)
+ set_overrun ();
+ }
+
+ if (get_overrun ())
+ break;
+
+ /* Insert binfo into backreferences. */
+ tag = insert (res);
+ dump (dumper::TREE) && dump ("Read binfo:%d %N", tag, res);
+ }
+ break;
+
+ case tt_vtable:
+ {
+ unsigned ix = u ();
+ tree ctx = tree_node ();
+ dump (dumper::TREE) && dump ("Reading vtable %N[%u]", ctx, ix);
+ if (TREE_CODE (ctx) == RECORD_TYPE && TYPE_LANG_SPECIFIC (ctx))
+ for (res = CLASSTYPE_VTABLES (ctx); res; res = DECL_CHAIN (res))
+ if (!ix--)
+ break;
+ if (!res)
+ set_overrun ();
+ }
+ break;
+
+ case tt_thunk:
+ {
+ int fixed = i ();
+ tree target = tree_node ();
+ tree virt = tree_node ();
+
+ for (tree thunk = DECL_THUNKS (target);
+ thunk; thunk = DECL_CHAIN (thunk))
+ if (THUNK_FIXED_OFFSET (thunk) == fixed
+ && !THUNK_VIRTUAL_OFFSET (thunk) == !virt
+ && (!virt
+ || tree_int_cst_equal (virt, THUNK_VIRTUAL_OFFSET (thunk))))
+ {
+ res = thunk;
+ break;
+ }
+
+ int tag = insert (res);
+ if (res)
+ dump (dumper::TREE)
+ && dump ("Read:%d thunk %N to %N", tag, DECL_NAME (res), target);
+ else
+ set_overrun ();
+ }
+ break;
+
+ case tt_clone_ref:
+ {
+ tree target = tree_node ();
+ tree name = tree_node ();
+
+ if (DECL_P (target) && DECL_MAYBE_IN_CHARGE_CDTOR_P (target))
+ {
+ tree clone;
+ FOR_EVERY_CLONE (clone, target)
+ if (DECL_NAME (clone) == name)
+ {
+ res = clone;
+ break;
+ }
+ }
+
+ if (!res)
+ set_overrun ();
+ int tag = insert (res);
+ if (res)
+ dump (dumper::TREE)
+ && dump ("Read:%d clone %N of %N", tag, DECL_NAME (res), target);
+ else
+ set_overrun ();
+ }
+ break;
+
+ case tt_entity:
+ /* Index into the entity table. Perhaps not loaded yet! */
+ {
+ unsigned origin = state->slurp->remap_module (u ());
+ unsigned ident = u ();
+ module_state *from = (*modules)[origin];
+
+ if (!origin || ident >= from->entity_num)
+ set_overrun ();
+ if (!get_overrun ())
+ {
+ binding_slot *slot = &(*entity_ary)[from->entity_lwm + ident];
+ if (slot->is_lazy ())
+ if (!from->lazy_load (ident, slot))
+ set_overrun ();
+ res = *slot;
+ }
+
+ if (res)
+ {
+ const char *kind = (origin != state->mod ? "Imported" : "Named");
+ int tag = insert (res);
+ dump (dumper::TREE)
+ && dump ("%s:%d %C:%N@%M", kind, tag, TREE_CODE (res),
+ res, (*modules)[origin]);
+
+ if (!add_indirects (res))
+ {
+ set_overrun ();
+ res = NULL_TREE;
+ }
+ }
+ }
+ break;
+
+ case tt_template:
+ /* A template. */
+ if (tree tpl = tree_node ())
+ {
+ res = DECL_TEMPLATE_RESULT (tpl);
+ dump (dumper::TREE)
+ && dump ("Read template %C:%N", TREE_CODE (res), res);
+ }
+ break;
+ }
+
+ if (is_use && !unused && res && DECL_P (res) && !TREE_USED (res))
+ {
+ /* Mark decl used as mark_used does -- we cannot call
+ mark_used in the middle of streaming, we only need a subset
+ of its functionality. */
+ TREE_USED (res) = true;
+
+ /* And for structured bindings also the underlying decl. */
+ if (DECL_DECOMPOSITION_P (res) && DECL_DECOMP_BASE (res))
+ TREE_USED (DECL_DECOMP_BASE (res)) = true;
+
+ if (DECL_CLONED_FUNCTION_P (res))
+ TREE_USED (DECL_CLONED_FUNCTION (res)) = true;
+ }
+
+ dump.outdent ();
+ return res;
+}
+
+void
+trees_out::tpl_parms (tree parms, unsigned &tpl_levels)
+{
+ if (!parms)
+ return;
+
+ if (TREE_VISITED (parms))
+ {
+ ref_node (parms);
+ return;
+ }
+
+ tpl_parms (TREE_CHAIN (parms), tpl_levels);
+
+ tree vec = TREE_VALUE (parms);
+ unsigned len = TREE_VEC_LENGTH (vec);
+ /* Depth. */
+ int tag = insert (parms);
+ if (streaming_p ())
+ {
+ i (len + 1);
+ dump (dumper::TREE)
+ && dump ("Writing template parms:%d level:%N length:%d",
+ tag, TREE_PURPOSE (parms), len);
+ }
+ tree_node (TREE_PURPOSE (parms));
+
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree parm = TREE_VEC_ELT (vec, ix);
+ tree decl = TREE_VALUE (parm);
+
+ gcc_checking_assert (DECL_TEMPLATE_PARM_P (decl));
+ if (CHECKING_P)
+ switch (TREE_CODE (decl))
+ {
+ default: gcc_unreachable ();
+
+ case TEMPLATE_DECL:
+ gcc_assert ((TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == TYPE_DECL)
+ && (TYPE_NAME (TREE_TYPE (decl)) == decl));
+ break;
+
+ case TYPE_DECL:
+ gcc_assert ((TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM)
+ && (TYPE_NAME (TREE_TYPE (decl)) == decl));
+ break;
+
+ case PARM_DECL:
+ gcc_assert ((TREE_CODE (DECL_INITIAL (decl)) == TEMPLATE_PARM_INDEX)
+ && (TREE_CODE (TEMPLATE_PARM_DECL (DECL_INITIAL (decl)))
+ == CONST_DECL)
+ && (DECL_TEMPLATE_PARM_P
+ (TEMPLATE_PARM_DECL (DECL_INITIAL (decl)))));
+ break;
+ }
+
+ tree_node (decl);
+ tree_node (TEMPLATE_PARM_CONSTRAINTS (parm));
+ }
+
+ tpl_levels++;
+}
+
+tree
+trees_in::tpl_parms (unsigned &tpl_levels)
+{
+ tree parms = NULL_TREE;
+
+ while (int len = i ())
+ {
+ if (len < 0)
+ {
+ parms = back_ref (len);
+ continue;
+ }
+
+ len -= 1;
+ parms = tree_cons (NULL_TREE, NULL_TREE, parms);
+ int tag = insert (parms);
+ TREE_PURPOSE (parms) = tree_node ();
+
+ dump (dumper::TREE)
+ && dump ("Reading template parms:%d level:%N length:%d",
+ tag, TREE_PURPOSE (parms), len);
+
+ tree vec = make_tree_vec (len);
+ for (int ix = 0; ix != len; ix++)
+ {
+ tree decl = tree_node ();
+ if (!decl)
+ return NULL_TREE;
+
+ tree parm = build_tree_list (NULL, decl);
+ TEMPLATE_PARM_CONSTRAINTS (parm) = tree_node ();
+
+ TREE_VEC_ELT (vec, ix) = parm;
+ }
+
+ TREE_VALUE (parms) = vec;
+ tpl_levels++;
+ }
+
+ return parms;
+}
+
+void
+trees_out::tpl_parms_fini (tree tmpl, unsigned tpl_levels)
+{
+ for (tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ tpl_levels--; parms = TREE_CHAIN (parms))
+ {
+ tree vec = TREE_VALUE (parms);
+
+ tree_node (TREE_TYPE (vec));
+ tree dflt = error_mark_node;
+ for (unsigned ix = TREE_VEC_LENGTH (vec); ix--;)
+ {
+ tree parm = TREE_VEC_ELT (vec, ix);
+ if (dflt)
+ {
+ dflt = TREE_PURPOSE (parm);
+ tree_node (dflt);
+ }
+
+ if (streaming_p ())
+ {
+ tree decl = TREE_VALUE (parm);
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ tree ctx = DECL_CONTEXT (decl);
+ tree inner = DECL_TEMPLATE_RESULT (decl);
+ tree tpi = (TREE_CODE (inner) == TYPE_DECL
+ ? TEMPLATE_TYPE_PARM_INDEX (TREE_TYPE (decl))
+ : DECL_INITIAL (inner));
+ bool original = (TEMPLATE_PARM_LEVEL (tpi)
+ == TEMPLATE_PARM_ORIG_LEVEL (tpi));
+ /* Original template template parms have a context
+ of their owning template. Reduced ones do not. */
+ gcc_checking_assert (original ? ctx == tmpl : !ctx);
+ }
+ }
+ }
+ }
+}
+
+bool
+trees_in::tpl_parms_fini (tree tmpl, unsigned tpl_levels)
+{
+ for (tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ tpl_levels--; parms = TREE_CHAIN (parms))
+ {
+ tree vec = TREE_VALUE (parms);
+ tree dflt = error_mark_node;
+
+ TREE_TYPE (vec) = tree_node ();
+ for (unsigned ix = TREE_VEC_LENGTH (vec); ix--;)
+ {
+ tree parm = TREE_VEC_ELT (vec, ix);
+ if (dflt)
+ {
+ dflt = tree_node ();
+ if (get_overrun ())
+ return false;
+ TREE_PURPOSE (parm) = dflt;
+ }
+
+ tree decl = TREE_VALUE (parm);
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ tree inner = DECL_TEMPLATE_RESULT (decl);
+ tree tpi = (TREE_CODE (inner) == TYPE_DECL
+ ? TEMPLATE_TYPE_PARM_INDEX (TREE_TYPE (decl))
+ : DECL_INITIAL (inner));
+ bool original = (TEMPLATE_PARM_LEVEL (tpi)
+ == TEMPLATE_PARM_ORIG_LEVEL (tpi));
+ /* Original template template parms have a context
+ of their owning template. Reduced ones do not. */
+ if (original)
+ DECL_CONTEXT (decl) = tmpl;
+ }
+ }
+ }
+ return true;
+}
+
+/* PARMS is a LIST, one node per level.
+ TREE_VALUE is a TREE_VEC of parm info for that level.
+ each ELT is a TREE_LIST
+ TREE_VALUE is PARM_DECL, TYPE_DECL or TEMPLATE_DECL
+ TREE_PURPOSE is the default value. */
+
+void
+trees_out::tpl_header (tree tpl, unsigned *tpl_levels)
+{
+ tree parms = DECL_TEMPLATE_PARMS (tpl);
+ tpl_parms (parms, *tpl_levels);
+
+ /* Mark end. */
+ if (streaming_p ())
+ u (0);
+
+ if (*tpl_levels)
+ tree_node (TEMPLATE_PARMS_CONSTRAINTS (parms));
+}
+
+bool
+trees_in::tpl_header (tree tpl, unsigned *tpl_levels)
+{
+ tree parms = tpl_parms (*tpl_levels);
+ if (!parms)
+ return false;
+
+ DECL_TEMPLATE_PARMS (tpl) = parms;
+
+ if (*tpl_levels)
+ TEMPLATE_PARMS_CONSTRAINTS (parms) = tree_node ();
+
+ return true;
+}
+
+/* Stream skeleton parm nodes, with their flags, type & parm indices.
+ All the parms will have consecutive tags. */
+
+void
+trees_out::fn_parms_init (tree fn)
+{
+ /* First init them. */
+ int base_tag = ref_num - 1;
+ int ix = 0;
+ for (tree parm = DECL_ARGUMENTS (fn);
+ parm; parm = DECL_CHAIN (parm), ix++)
+ {
+ if (streaming_p ())
+ {
+ start (parm);
+ tree_node_bools (parm);
+ }
+ int tag = insert (parm);
+ gcc_checking_assert (base_tag - ix == tag);
+ }
+ /* Mark the end. */
+ if (streaming_p ())
+ u (0);
+
+ /* Now stream their contents. */
+ ix = 0;
+ for (tree parm = DECL_ARGUMENTS (fn);
+ parm; parm = DECL_CHAIN (parm), ix++)
+ {
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Writing parm:%d %u (%N) of %N",
+ base_tag - ix, ix, parm, fn);
+ tree_node_vals (parm);
+ }
+}
+
+/* Build skeleton parm nodes, read their flags, type & parm indices. */
+
+int
+trees_in::fn_parms_init (tree fn)
+{
+ int base_tag = ~(int)back_refs.length ();
+
+ tree *parm_ptr = &DECL_ARGUMENTS (fn);
+ int ix = 0;
+ for (; int code = u (); ix++)
+ {
+ tree parm = start (code);
+ if (!tree_node_bools (parm))
+ return 0;
+
+ int tag = insert (parm);
+ gcc_checking_assert (base_tag - ix == tag);
+ *parm_ptr = parm;
+ parm_ptr = &DECL_CHAIN (parm);
+ }
+
+ ix = 0;
+ for (tree parm = DECL_ARGUMENTS (fn);
+ parm; parm = DECL_CHAIN (parm), ix++)
+ {
+ dump (dumper::TREE)
+ && dump ("Reading parm:%d %u (%N) of %N",
+ base_tag - ix, ix, parm, fn);
+ if (!tree_node_vals (parm))
+ return 0;
+ }
+
+ return base_tag;
+}
+
+/* Read the remaining parm node data. Replace with existing (if
+ non-null) in the map. */
+
+void
+trees_in::fn_parms_fini (int tag, tree fn, tree existing, bool is_defn)
+{
+ tree existing_parm = existing ? DECL_ARGUMENTS (existing) : NULL_TREE;
+ tree parms = DECL_ARGUMENTS (fn);
+ unsigned ix = 0;
+ for (tree parm = parms; parm; parm = DECL_CHAIN (parm), ix++)
+ {
+ if (existing_parm)
+ {
+ if (is_defn && !DECL_SAVED_TREE (existing))
+ {
+ /* If we're about to become the definition, set the
+ names of the parms from us. */
+ DECL_NAME (existing_parm) = DECL_NAME (parm);
+ DECL_SOURCE_LOCATION (existing_parm) = DECL_SOURCE_LOCATION (parm);
+ }
+
+ back_refs[~tag] = existing_parm;
+ existing_parm = DECL_CHAIN (existing_parm);
+ }
+ tag--;
+ }
+}
+
+/* DEP is the depset of some decl we're streaming by value. Determine
+ the merging behaviour. */
+
+merge_kind
+trees_out::get_merge_kind (tree decl, depset *dep)
+{
+ if (!dep)
+ {
+ if (VAR_OR_FUNCTION_DECL_P (decl))
+ {
+ /* Any var or function with template info should have DEP. */
+ gcc_checking_assert (!DECL_LANG_SPECIFIC (decl)
+ || !DECL_TEMPLATE_INFO (decl));
+ if (DECL_LOCAL_DECL_P (decl))
+ return MK_unique;
+ }
+
+ /* Either unique, or some member of a class that cannot have an
+ out-of-class definition. For instance a FIELD_DECL. */
+ tree ctx = CP_DECL_CONTEXT (decl);
+ if (TREE_CODE (ctx) == FUNCTION_DECL)
+ {
+ /* USING_DECLs cannot have DECL_TEMPLATE_INFO -- this isn't
+ permitting them to have one. */
+ gcc_checking_assert (TREE_CODE (decl) == USING_DECL
+ || !DECL_LANG_SPECIFIC (decl)
+ || !DECL_TEMPLATE_INFO (decl));
+
+ return MK_unique;
+ }
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
+ return MK_local_friend;
+
+ gcc_checking_assert (TYPE_P (ctx));
+ if (TREE_CODE (decl) == USING_DECL)
+ return MK_field;
+
+ if (TREE_CODE (decl) == FIELD_DECL)
+ {
+ if (DECL_NAME (decl))
+ {
+ /* Anonymous FIELD_DECLs have a NULL name. */
+ gcc_checking_assert (!IDENTIFIER_ANON_P (DECL_NAME (decl)));
+ return MK_named;
+ }
+
+ if (!DECL_NAME (decl)
+ && !RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+ && !DECL_BIT_FIELD_REPRESENTATIVE (decl))
+ {
+ /* The underlying storage unit for a bitfield. We do not
+ need to dedup it, because it's only reachable through
+ the bitfields it represents. And those are deduped. */
+ // FIXME: Is that assertion correct -- do we ever fish it
+ // out and put it in an expr?
+ gcc_checking_assert ((TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+ ? TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
+ : TREE_CODE (TREE_TYPE (decl)))
+ == INTEGER_TYPE);
+ return MK_unique;
+ }
+
+ return MK_field;
+ }
+
+ if (TREE_CODE (decl) == CONST_DECL)
+ return MK_named;
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_VTABLE_OR_VTT_P (decl))
+ return MK_vtable;
+
+ if (DECL_THUNK_P (decl))
+ /* Thunks are unique-enough, because they're only referenced
+ from the vtable. And that's either new (so we want the
+ thunks), or it's a duplicate (so it will be dropped). */
+ return MK_unique;
+
+ /* There should be no other cases. */
+ gcc_unreachable ();
+ }
+
+ gcc_checking_assert (TREE_CODE (decl) != FIELD_DECL
+ && TREE_CODE (decl) != USING_DECL
+ && TREE_CODE (decl) != CONST_DECL);
+
+ if (is_key_order ())
+ {
+ /* When doing the mergeablilty graph, there's an indirection to
+ the actual depset. */
+ gcc_assert (dep->is_special ());
+ dep = dep->deps[0];
+ }
+
+ gcc_checking_assert (decl == dep->get_entity ());
+
+ merge_kind mk = MK_named;
+ switch (dep->get_entity_kind ())
+ {
+ default:
+ gcc_unreachable ();
+
+ case depset::EK_PARTIAL:
+ mk = MK_partial;
+ break;
+
+ case depset::EK_DECL:
+ {
+ tree ctx = CP_DECL_CONTEXT (decl);
+
+ switch (TREE_CODE (ctx))
+ {
+ default:
+ gcc_unreachable ();
+
+ case FUNCTION_DECL:
+ // FIXME: This can occur for (a) voldemorty TYPE_DECLS
+ // (which are returned from a function), or (b)
+ // block-scope class definitions in template functions.
+ // These are as unique as the containing function. While
+ // on read-back we can discover if the CTX was a
+ // duplicate, we don't have a mechanism to get from the
+ // existing CTX to the existing version of this decl.
+ gcc_checking_assert
+ (DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (decl)));
+
+ mk = MK_unique;
+ break;
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ if (DECL_NAME (decl) == as_base_identifier)
+ mk = MK_as_base;
+ else if (IDENTIFIER_ANON_P (DECL_NAME (decl)))
+ mk = MK_field;
+ break;
+
+ case NAMESPACE_DECL:
+ if (DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (decl))
+ && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+ if (tree scope
+ = LAMBDA_EXPR_EXTRA_SCOPE (CLASSTYPE_LAMBDA_EXPR
+ (TREE_TYPE (decl))))
+ if (TREE_CODE (scope) == VAR_DECL
+ && DECL_MODULE_ATTACHMENTS_P (scope))
+ {
+ mk = MK_attached;
+ break;
+ }
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
+ mk = MK_local_friend;
+ else if (IDENTIFIER_ANON_P (DECL_NAME (decl)))
+ {
+ if (DECL_IMPLICIT_TYPEDEF_P (decl)
+ && UNSCOPED_ENUM_P (TREE_TYPE (decl))
+ && TYPE_VALUES (TREE_TYPE (decl)))
+ /* Keyed by first enum value, and underlying type. */
+ mk = MK_enum;
+ else
+ /* No way to merge it, it is an ODR land-mine. */
+ mk = MK_unique;
+ }
+ }
+ }
+ break;
+
+ case depset::EK_SPECIALIZATION:
+ {
+ gcc_checking_assert (dep->is_special ());
+ spec_entry *entry = reinterpret_cast <spec_entry *> (dep->deps[0]);
+
+ if (TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ /* An block-scope classes of templates are themselves
+ templates. */
+ gcc_checking_assert (DECL_IMPLICIT_TYPEDEF_P (decl));
+
+ if (dep->is_friend_spec ())
+ mk = MK_friend_spec;
+ else if (dep->is_type_spec ())
+ mk = MK_type_spec;
+ else if (dep->is_alias ())
+ mk = MK_alias_spec;
+ else
+ mk = MK_decl_spec;
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ tree res = DECL_TEMPLATE_RESULT (decl);
+ if (!(mk & MK_tmpl_decl_mask))
+ res = TREE_TYPE (res);
+
+ if (res == entry->spec)
+ /* We check we can get back to the template during
+ streaming. */
+ mk = merge_kind (mk | MK_tmpl_tmpl_mask);
+ }
+ }
+ break;
+ }
+
+ return mk;
+}
+
+
+/* The container of DECL -- not necessarily its context! */
+
+tree
+trees_out::decl_container (tree decl)
+{
+ int use_tpl;
+ tree tpl = NULL_TREE;
+ if (tree template_info = node_template_info (decl, use_tpl))
+ tpl = TI_TEMPLATE (template_info);
+ if (tpl == decl)
+ tpl = nullptr;
+
+ /* Stream the template we're instantiated from. */
+ tree_node (tpl);
+
+ tree container = NULL_TREE;
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
+ container = DECL_CHAIN (decl);
+ else
+ container = CP_DECL_CONTEXT (decl);
+
+ if (TYPE_P (container))
+ container = TYPE_NAME (container);
+
+ tree_node (container);
+
+ return container;
+}
+
+tree
+trees_in::decl_container ()
+{
+ /* The maybe-template. */
+ (void)tree_node ();
+
+ tree container = tree_node ();
+
+ return container;
+}
+
+/* Write out key information about a mergeable DEP. Does not write
+ the contents of DEP itself. The context has already been
+ written. The container has already been streamed. */
+
+void
+trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
+ tree container, depset *dep)
+{
+ if (dep && is_key_order ())
+ {
+ gcc_checking_assert (dep->is_special ());
+ dep = dep->deps[0];
+ }
+
+ if (streaming_p ())
+ dump (dumper::MERGE)
+ && dump ("Writing:%d's %s merge key (%s) %C:%N", tag, merge_kind_name[mk],
+ dep ? dep->entity_kind_name () : "contained",
+ TREE_CODE (decl), decl);
+
+ /* Now write the locating information. */
+ if (mk & MK_template_mask)
+ {
+ /* Specializations are located via their originating template,
+ and the set of template args they specialize. */
+ gcc_checking_assert (dep && dep->is_special ());
+ spec_entry *entry = reinterpret_cast <spec_entry *> (dep->deps[0]);
+
+ tree_node (entry->tmpl);
+ tree_node (entry->args);
+ if (streaming_p ())
+ u (get_mergeable_specialization_flags (entry->tmpl, decl));
+ if (mk & MK_tmpl_decl_mask)
+ if (flag_concepts && TREE_CODE (inner) == VAR_DECL)
+ {
+ /* Variable template partial specializations might need
+ constraints (see spec_hasher::equal). It's simpler to
+ write NULL when we don't need them. */
+ tree constraints = NULL_TREE;
+
+ if (uses_template_parms (entry->args))
+ constraints = get_constraints (inner);
+ tree_node (constraints);
+ }
+
+ if (CHECKING_P)
+ {
+ /* Make sure we can locate the decl. */
+ tree existing = match_mergeable_specialization
+ (bool (mk & MK_tmpl_decl_mask), entry, false);
+
+ gcc_assert (existing);
+ if (mk & MK_tmpl_decl_mask)
+ {
+ if (mk & MK_tmpl_alias_mask)
+ /* It should be in both tables. */
+ gcc_assert (match_mergeable_specialization (false, entry, false)
+ == TREE_TYPE (existing));
+ else if (mk & MK_tmpl_tmpl_mask)
+ if (tree ti = DECL_TEMPLATE_INFO (existing))
+ existing = TI_TEMPLATE (ti);
+ }
+ else
+ {
+ if (!(mk & MK_tmpl_tmpl_mask))
+ existing = TYPE_NAME (existing);
+ else if (tree ti = CLASSTYPE_TEMPLATE_INFO (existing))
+ existing = TI_TEMPLATE (ti);
+ }
+
+ /* The walkabout should have found ourselves. */
+ gcc_assert (existing == decl);
+ }
+ }
+ else if (mk != MK_unique)
+ {
+ merge_key key;
+ tree name = DECL_NAME (decl);
+
+ switch (mk)
+ {
+ default:
+ gcc_unreachable ();
+
+ case MK_named:
+ case MK_friend_spec:
+ if (IDENTIFIER_CONV_OP_P (name))
+ name = conv_op_identifier;
+
+ if (inner && TREE_CODE (inner) == FUNCTION_DECL)
+ {
+ /* Functions are distinguished by parameter types. */
+ tree fn_type = TREE_TYPE (inner);
+
+ key.ref_q = type_memfn_rqual (fn_type);
+ key.args = TYPE_ARG_TYPES (fn_type);
+
+ if (tree reqs = get_constraints (inner))
+ {
+ if (cxx_dialect < cxx20)
+ reqs = CI_ASSOCIATED_CONSTRAINTS (reqs);
+ else
+ reqs = CI_DECLARATOR_REQS (reqs);
+ key.constraints = reqs;
+ }
+
+ if (IDENTIFIER_CONV_OP_P (name)
+ || (decl != inner
+ && !(name == fun_identifier
+ /* In case the user names something _FUN */
+ && LAMBDA_TYPE_P (DECL_CONTEXT (inner)))))
+ /* And a function template, or conversion operator needs
+ the return type. Except for the _FUN thunk of a
+ generic lambda, which has a recursive decl_type'd
+ return type. */
+ // FIXME: What if the return type is a voldemort?
+ key.ret = fndecl_declared_return_type (inner);
+ }
+
+ if (mk == MK_friend_spec)
+ {
+ gcc_checking_assert (dep && dep->is_special ());
+ spec_entry *entry = reinterpret_cast <spec_entry *> (dep->deps[0]);
+
+ tree_node (entry->tmpl);
+ tree_node (entry->args);
+ if (streaming_p ())
+ u (get_mergeable_specialization_flags (entry->tmpl, decl));
+ }
+ break;
+
+ case MK_field:
+ {
+ unsigned ix = 0;
+ if (TREE_CODE (inner) != FIELD_DECL)
+ name = NULL_TREE;
+ else
+ gcc_checking_assert (!name || !IDENTIFIER_ANON_P (name));
+
+ for (tree field = TYPE_FIELDS (TREE_TYPE (container));
+ ; field = DECL_CHAIN (field))
+ {
+ tree finner = STRIP_TEMPLATE (field);
+ if (TREE_CODE (finner) == TREE_CODE (inner))
+ {
+ if (finner == inner)
+ break;
+ ix++;
+ }
+ }
+ key.index = ix;
+ }
+ break;
+
+ case MK_vtable:
+ {
+ tree vtable = CLASSTYPE_VTABLES (TREE_TYPE (container));
+ for (unsigned ix = 0; ; vtable = DECL_CHAIN (vtable), ix++)
+ if (vtable == decl)
+ {
+ key.index = ix;
+ break;
+ }
+ name = NULL_TREE;
+ }
+ break;
+
+ case MK_as_base:
+ gcc_checking_assert
+ (decl == TYPE_NAME (CLASSTYPE_AS_BASE (TREE_TYPE (container))));
+ break;
+
+ case MK_local_friend:
+ {
+ /* Find by index on the class's DECL_LIST */
+ unsigned ix = 0;
+ for (tree decls = CLASSTYPE_DECL_LIST (TREE_CHAIN (decl));
+ decls; decls = TREE_CHAIN (decls))
+ if (!TREE_PURPOSE (decls))
+ {
+ tree frnd = friend_from_decl_list (TREE_VALUE (decls));
+ if (frnd == decl)
+ break;
+ ix++;
+ }
+ key.index = ix;
+ name = NULL_TREE;
+ }
+ break;
+
+ case MK_enum:
+ {
+ /* Anonymous enums are located by their first identifier,
+ and underlying type. */
+ tree type = TREE_TYPE (decl);
+
+ gcc_checking_assert (UNSCOPED_ENUM_P (type));
+ /* Using the type name drops the bit precision we might
+ have been using on the enum. */
+ key.ret = TYPE_NAME (ENUM_UNDERLYING_TYPE (type));
+ if (tree values = TYPE_VALUES (type))
+ name = DECL_NAME (TREE_VALUE (values));
+ }
+ break;
+
+ case MK_attached:
+ {
+ gcc_checking_assert (LAMBDA_TYPE_P (TREE_TYPE (inner)));
+ tree scope = LAMBDA_EXPR_EXTRA_SCOPE (CLASSTYPE_LAMBDA_EXPR
+ (TREE_TYPE (inner)));
+ gcc_checking_assert (TREE_CODE (scope) == VAR_DECL);
+ attachset *root = attached_table->get (DECL_UID (scope));
+ unsigned ix = root->num;
+ /* If we don't find it, we'll write a really big number
+ that the reader will ignore. */
+ while (ix--)
+ if (root->values[ix] == inner)
+ break;
+
+ /* Use the attached-to decl as the 'name'. */
+ name = scope;
+ key.index = ix;
+ }
+ break;
+
+ case MK_partial:
+ {
+ key.constraints = get_constraints (inner);
+ key.ret = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (inner));
+ key.args = CLASSTYPE_TI_ARGS (TREE_TYPE (inner));
+ }
+ break;
+ }
+
+ tree_node (name);
+ if (streaming_p ())
+ {
+ unsigned code = (key.ref_q << 0) | (key.index << 2);
+ u (code);
+ }
+
+ if (mk == MK_enum)
+ tree_node (key.ret);
+ else if (mk == MK_partial
+ || (mk == MK_named && inner
+ && TREE_CODE (inner) == FUNCTION_DECL))
+ {
+ tree_node (key.ret);
+ tree arg = key.args;
+ if (mk == MK_named)
+ while (arg && arg != void_list_node)
+ {
+ tree_node (TREE_VALUE (arg));
+ arg = TREE_CHAIN (arg);
+ }
+ tree_node (arg);
+ tree_node (key.constraints);
+ }
+ }
+}
+
+/* DECL is a new declaration that may be duplicated in OVL. Use RET &
+ ARGS to find its clone, or NULL. If DECL's DECL_NAME is NULL, this
+ has been found by a proxy. It will be an enum type located by it's
+ first member.
+
+ We're conservative with matches, so ambiguous decls will be
+ registered as different, then lead to a lookup error if the two
+ modules are both visible. Perhaps we want to do something similar
+ to duplicate decls to get ODR errors on loading? We already have
+ some special casing for namespaces. */
+
+static tree
+check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key)
+{
+ tree found = NULL_TREE;
+ for (ovl_iterator iter (ovl); !found && iter; ++iter)
+ {
+ tree match = *iter;
+
+ tree d_inner = decl;
+ tree m_inner = match;
+
+ again:
+ if (TREE_CODE (d_inner) != TREE_CODE (m_inner))
+ {
+ if (TREE_CODE (match) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (match))
+ /* Namespaces are never overloaded. */
+ found = match;
+
+ continue;
+ }
+
+ switch (TREE_CODE (d_inner))
+ {
+ case TEMPLATE_DECL:
+ if (template_heads_equivalent_p (d_inner, m_inner))
+ {
+ d_inner = DECL_TEMPLATE_RESULT (d_inner);
+ m_inner = DECL_TEMPLATE_RESULT (m_inner);
+ if (d_inner == error_mark_node
+ && TYPE_DECL_ALIAS_P (m_inner))
+ {
+ found = match;
+ break;
+ }
+ goto again;
+ }
+ break;
+
+ case FUNCTION_DECL:
+ map_context_from = d_inner;
+ map_context_to = m_inner;
+ if (tree m_type = TREE_TYPE (m_inner))
+ if ((!key.ret
+ || same_type_p (key.ret, fndecl_declared_return_type (m_inner)))
+ && type_memfn_rqual (m_type) == key.ref_q
+ && compparms (key.args, TYPE_ARG_TYPES (m_type))
+ /* Reject if old is a "C" builtin and new is not "C".
+ Matches decls_match behaviour. */
+ && (!DECL_IS_UNDECLARED_BUILTIN (m_inner)
+ || !DECL_EXTERN_C_P (m_inner)
+ || DECL_EXTERN_C_P (d_inner)))
+ {
+ tree m_reqs = get_constraints (m_inner);
+ if (m_reqs)
+ {
+ if (cxx_dialect < cxx20)
+ m_reqs = CI_ASSOCIATED_CONSTRAINTS (m_reqs);
+ else
+ m_reqs = CI_DECLARATOR_REQS (m_reqs);
+ }
+
+ if (cp_tree_equal (key.constraints, m_reqs))
+ found = match;
+ }
+ map_context_from = map_context_to = NULL_TREE;
+ break;
+
+ case TYPE_DECL:
+ if (DECL_IMPLICIT_TYPEDEF_P (d_inner)
+ == DECL_IMPLICIT_TYPEDEF_P (m_inner))
+ {
+ if (!IDENTIFIER_ANON_P (DECL_NAME (m_inner)))
+ return match;
+ else if (mk == MK_enum
+ && (TYPE_NAME (ENUM_UNDERLYING_TYPE (TREE_TYPE (m_inner)))
+ == key.ret))
+ found = match;
+ }
+ break;
+
+ default:
+ found = match;
+ break;
+ }
+ }
+
+ return found;
+}
+
+/* DECL, INNER & TYPE are a skeleton set of nodes for a decl. Only
+ the bools have been filled in. Read its merging key and merge it.
+ Returns the existing decl if there is one. */
+
+tree
+trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
+ tree type, tree container, bool is_mod)
+{
+ const char *kind = "new";
+ tree existing = NULL_TREE;
+
+ if (mk & MK_template_mask)
+ {
+ spec_entry spec;
+ spec.tmpl = tree_node ();
+ spec.args = tree_node ();
+ unsigned flags = u ();
+
+ DECL_NAME (decl) = DECL_NAME (spec.tmpl);
+ DECL_CONTEXT (decl) = DECL_CONTEXT (spec.tmpl);
+ DECL_NAME (inner) = DECL_NAME (decl);
+ DECL_CONTEXT (inner) = DECL_CONTEXT (decl);
+
+ spec.spec = decl;
+ if (mk & MK_tmpl_tmpl_mask)
+ {
+ if (inner == decl)
+ return error_mark_node;
+ spec.spec = inner;
+ }
+ tree constr = NULL_TREE;
+ bool is_decl = mk & MK_tmpl_decl_mask;
+ if (is_decl)
+ {
+ if (flag_concepts && TREE_CODE (inner) == VAR_DECL)
+ {
+ constr = tree_node ();
+ if (constr)
+ set_constraints (inner, constr);
+ }
+ }
+ else
+ {
+ if (mk == MK_type_spec && inner != decl)
+ return error_mark_node;
+ spec.spec = type;
+ }
+ existing = match_mergeable_specialization (is_decl, &spec);
+ if (constr)
+ /* We'll add these back later, if this is the new decl. */
+ remove_constraints (inner);
+
+ if (!existing)
+ add_mergeable_specialization (spec.tmpl, spec.args, decl, flags);
+ else if (mk & MK_tmpl_decl_mask)
+ {
+ /* A declaration specialization. */
+ if (mk & MK_tmpl_tmpl_mask)
+ if (tree ti = DECL_TEMPLATE_INFO (existing))
+ {
+ tree tmpl = TI_TEMPLATE (ti);
+ if (DECL_TEMPLATE_RESULT (tmpl) == existing)
+ existing = tmpl;
+ }
+ }
+ else
+ {
+ /* A type specialization. */
+ if (!(mk & MK_tmpl_tmpl_mask))
+ existing = TYPE_NAME (existing);
+ else if (tree ti = CLASSTYPE_TEMPLATE_INFO (existing))
+ {
+ tree tmpl = TI_TEMPLATE (ti);
+ if (DECL_TEMPLATE_RESULT (tmpl) == TYPE_NAME (existing))
+ existing = tmpl;
+ }
+ }
+ }
+ else if (mk == MK_unique)
+ kind = "unique";
+ else
+ {
+ tree name = tree_node ();
+
+ merge_key key;
+ unsigned code = u ();
+ key.ref_q = cp_ref_qualifier ((code >> 0) & 3);
+ key.index = code >> 2;
+
+ if (mk == MK_enum)
+ key.ret = tree_node ();
+ else if (mk == MK_partial
+ || ((mk == MK_named || mk == MK_friend_spec)
+ && inner && TREE_CODE (inner) == FUNCTION_DECL))
+ {
+ key.ret = tree_node ();
+ tree arg, *arg_ptr = &key.args;
+ while ((arg = tree_node ())
+ && arg != void_list_node
+ && mk != MK_partial)
+ {
+ *arg_ptr = tree_cons (NULL_TREE, arg, NULL_TREE);
+ arg_ptr = &TREE_CHAIN (*arg_ptr);
+ }
+ *arg_ptr = arg;
+ key.constraints = tree_node ();
+ }
+
+ if (get_overrun ())
+ return error_mark_node;
+
+ if (mk < MK_indirect_lwm)
+ {
+ DECL_NAME (decl) = name;
+ DECL_CONTEXT (decl) = FROB_CONTEXT (container);
+ }
+ if (inner)
+ {
+ DECL_NAME (inner) = DECL_NAME (decl);
+ DECL_CONTEXT (inner) = DECL_CONTEXT (decl);
+ }
+
+ if (mk == MK_partial)
+ {
+ for (tree spec = DECL_TEMPLATE_SPECIALIZATIONS (key.ret);
+ spec; spec = TREE_CHAIN (spec))
+ {
+ tree tmpl = TREE_VALUE (spec);
+ if (template_args_equal (key.args,
+ CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)))
+ && cp_tree_equal (key.constraints,
+ get_constraints
+ (DECL_TEMPLATE_RESULT (tmpl))))
+ {
+ existing = tmpl;
+ break;
+ }
+ }
+ if (!existing)
+ add_mergeable_specialization (key.ret, key.args, decl, 2);
+ }
+ else
+ switch (TREE_CODE (container))
+ {
+ default:
+ gcc_unreachable ();
+
+ case NAMESPACE_DECL:
+ if (mk == MK_attached)
+ {
+ if (DECL_LANG_SPECIFIC (name)
+ && VAR_OR_FUNCTION_DECL_P (name)
+ && DECL_MODULE_ATTACHMENTS_P (name))
+ if (attachset *set = attached_table->get (DECL_UID (name)))
+ if (key.index < set->num)
+ {
+ existing = set->values[key.index];
+ if (existing)
+ {
+ gcc_checking_assert
+ (DECL_IMPLICIT_TYPEDEF_P (existing));
+ if (inner != decl)
+ existing
+ = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (existing));
+ }
+ }
+ }
+ else if (is_mod && !(state->is_module () || state->is_partition ()))
+ kind = "unique";
+ else
+ {
+ gcc_checking_assert (mk == MK_named || mk == MK_enum);
+ tree mvec;
+ tree *vslot = mergeable_namespace_slots (container, name,
+ !is_mod, &mvec);
+ existing = check_mergeable_decl (mk, decl, *vslot, key);
+ if (!existing)
+ add_mergeable_namespace_entity (vslot, decl);
+ else
+ {
+ /* Note that we now have duplicates to deal with in
+ name lookup. */
+ if (is_mod)
+ BINDING_VECTOR_PARTITION_DUPS_P (mvec) = true;
+ else
+ BINDING_VECTOR_GLOBAL_DUPS_P (mvec) = true;
+ }
+ }
+ break;
+
+ case FUNCTION_DECL:
+ // FIXME: What about a voldemort? how do we find what it
+ // duplicates? Do we have to number vmorts relative to
+ // their containing function? But how would that work
+ // when matching an in-TU declaration?
+ kind = "unique";
+ break;
+
+ case TYPE_DECL:
+ if (is_mod && !(state->is_module () || state->is_partition ())
+ /* Implicit member functions can come from
+ anywhere. */
+ && !(DECL_ARTIFICIAL (decl)
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && !DECL_THUNK_P (decl)))
+ kind = "unique";
+ else
+ {
+ tree ctx = TREE_TYPE (container);
+
+ /* For some reason templated enumeral types are not marked
+ as COMPLETE_TYPE_P, even though they have members.
+ This may well be a bug elsewhere. */
+ if (TREE_CODE (ctx) == ENUMERAL_TYPE)
+ existing = find_enum_member (ctx, name);
+ else if (COMPLETE_TYPE_P (ctx))
+ {
+ switch (mk)
+ {
+ default:
+ gcc_unreachable ();
+
+ case MK_named:
+ existing = lookup_class_binding (ctx, name);
+ if (existing)
+ {
+ tree inner = decl;
+ if (TREE_CODE (inner) == TEMPLATE_DECL
+ && !DECL_MEMBER_TEMPLATE_P (inner))
+ inner = DECL_TEMPLATE_RESULT (inner);
+
+ existing = check_mergeable_decl
+ (mk, inner, existing, key);
+
+ if (!existing && DECL_ALIAS_TEMPLATE_P (decl))
+ {} // FIXME: Insert into specialization
+ // tables, we'll need the arguments for that!
+ }
+ break;
+
+ case MK_field:
+ {
+ unsigned ix = key.index;
+ for (tree field = TYPE_FIELDS (ctx);
+ field; field = DECL_CHAIN (field))
+ {
+ tree finner = STRIP_TEMPLATE (field);
+ if (TREE_CODE (finner) == TREE_CODE (inner))
+ if (!ix--)
+ {
+ existing = field;
+ break;
+ }
+ }
+ }
+ break;
+
+ case MK_vtable:
+ {
+ unsigned ix = key.index;
+ for (tree vtable = CLASSTYPE_VTABLES (ctx);
+ vtable; vtable = DECL_CHAIN (vtable))
+ if (!ix--)
+ {
+ existing = vtable;
+ break;
+ }
+ }
+ break;
+
+ case MK_as_base:
+ {
+ tree as_base = CLASSTYPE_AS_BASE (ctx);
+ if (as_base && as_base != ctx)
+ existing = TYPE_NAME (as_base);
+ }
+ break;
+
+ case MK_local_friend:
+ {
+ unsigned ix = key.index;
+ for (tree decls = CLASSTYPE_DECL_LIST (ctx);
+ decls; decls = TREE_CHAIN (decls))
+ if (!TREE_PURPOSE (decls) && !ix--)
+ {
+ existing
+ = friend_from_decl_list (TREE_VALUE (decls));
+ break;
+ }
+ }
+ break;
+ }
+
+ if (existing && mk < MK_indirect_lwm && mk != MK_partial
+ && TREE_CODE (decl) == TEMPLATE_DECL
+ && !DECL_MEMBER_TEMPLATE_P (decl))
+ {
+ tree ti;
+ if (DECL_IMPLICIT_TYPEDEF_P (existing))
+ ti = TYPE_TEMPLATE_INFO (TREE_TYPE (existing));
+ else
+ ti = DECL_TEMPLATE_INFO (existing);
+ existing = TI_TEMPLATE (ti);
+ }
+ }
+ }
+ }
+
+ if (mk == MK_friend_spec)
+ {
+ spec_entry spec;
+ spec.tmpl = tree_node ();
+ spec.args = tree_node ();
+ spec.spec = decl;
+ unsigned flags = u ();
+
+ tree e = match_mergeable_specialization (true, &spec);
+ if (!e)
+ add_mergeable_specialization (spec.tmpl, spec.args,
+ existing ? existing : decl, flags);
+ else if (e != existing)
+ set_overrun ();
+ }
+ }
+
+ dump (dumper::MERGE)
+ && dump ("Read:%d's %s merge key (%s) %C:%N", tag, merge_kind_name[mk],
+ existing ? "matched" : kind, TREE_CODE (decl), decl);
+
+ return existing;
+}
+
+void
+trees_out::binfo_mergeable (tree binfo)
+{
+ tree dom = binfo;
+ while (tree parent = BINFO_INHERITANCE_CHAIN (dom))
+ dom = parent;
+ tree type = BINFO_TYPE (dom);
+ gcc_checking_assert (TYPE_BINFO (type) == dom);
+ tree_node (type);
+ if (streaming_p ())
+ {
+ unsigned ix = 0;
+ for (; dom != binfo; dom = TREE_CHAIN (dom))
+ ix++;
+ u (ix);
+ }
+}
+
+unsigned
+trees_in::binfo_mergeable (tree *type)
+{
+ *type = tree_node ();
+ return u ();
+}
+
+/* DECL is a just streamed mergeable decl that should match EXISTING. Check
+ it does and issue an appropriate diagnostic if not. Merge any
+ bits from DECL to EXISTING. This is stricter matching than
+ decls_match, because we can rely on ODR-sameness, and we cannot use
+ decls_match because it can cause instantiations of constraints. */
+
+bool
+trees_in::is_matching_decl (tree existing, tree decl)
+{
+ // FIXME: We should probably do some duplicate decl-like stuff here
+ // (beware, default parms should be the same?) Can we just call
+ // duplicate_decls and teach it how to handle the module-specific
+ // permitted/required duplications?
+
+ // We know at this point that the decls have matched by key, so we
+ // can elide some of the checking
+ gcc_checking_assert (TREE_CODE (existing) == TREE_CODE (decl));
+
+ tree inner = decl;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ inner = DECL_TEMPLATE_RESULT (decl);
+ gcc_checking_assert (TREE_CODE (DECL_TEMPLATE_RESULT (existing))
+ == TREE_CODE (inner));
+ }
+
+ gcc_checking_assert (!map_context_from);
+ /* This mapping requres the new decl on the lhs and the existing
+ entity on the rhs of the comparitors below. */
+ map_context_from = inner;
+ map_context_to = STRIP_TEMPLATE (existing);
+
+ if (TREE_CODE (inner) == FUNCTION_DECL)
+ {
+ tree e_ret = fndecl_declared_return_type (existing);
+ tree d_ret = fndecl_declared_return_type (decl);
+
+ if (decl != inner && DECL_NAME (inner) == fun_identifier
+ && LAMBDA_TYPE_P (DECL_CONTEXT (inner)))
+ /* This has a recursive type that will compare different. */;
+ else if (!same_type_p (d_ret, e_ret))
+ goto mismatch;
+
+ tree e_type = TREE_TYPE (existing);
+ tree d_type = TREE_TYPE (decl);
+
+ if (DECL_EXTERN_C_P (decl) != DECL_EXTERN_C_P (existing))
+ goto mismatch;
+
+ for (tree e_args = TYPE_ARG_TYPES (e_type),
+ d_args = TYPE_ARG_TYPES (d_type);
+ e_args != d_args && (e_args || d_args);
+ e_args = TREE_CHAIN (e_args), d_args = TREE_CHAIN (d_args))
+ {
+ if (!(e_args && d_args))
+ goto mismatch;
+
+ if (!same_type_p (TREE_VALUE (d_args), TREE_VALUE (e_args)))
+ goto mismatch;
+
+ // FIXME: Check default values
+ }
+
+ /* If EXISTING has an undeduced or uninstantiated exception
+ specification, but DECL does not, propagate the exception
+ specification. Otherwise we end up asserting or trying to
+ instantiate it in the middle of loading. */
+ tree e_spec = TYPE_RAISES_EXCEPTIONS (e_type);
+ tree d_spec = TYPE_RAISES_EXCEPTIONS (d_type);
+ if (DEFERRED_NOEXCEPT_SPEC_P (e_spec))
+ {
+ if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
+ || (UNEVALUATED_NOEXCEPT_SPEC_P (e_spec)
+ && !UNEVALUATED_NOEXCEPT_SPEC_P (d_spec)))
+ {
+ dump (dumper::MERGE)
+ && dump ("Propagating instantiated noexcept to %N", existing);
+ TREE_TYPE (existing) = d_type;
+
+ /* Propagate to existing clones. */
+ tree clone;
+ FOR_EACH_CLONE (clone, existing)
+ {
+ if (TREE_TYPE (clone) == e_type)
+ TREE_TYPE (clone) = d_type;
+ else
+ TREE_TYPE (clone)
+ = build_exception_variant (TREE_TYPE (clone), d_spec);
+ }
+ }
+ }
+ else if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
+ && !comp_except_specs (d_spec, e_spec, ce_type))
+ goto mismatch;
+ }
+ /* Using cp_tree_equal because we can meet TYPE_ARGUMENT_PACKs
+ here. I suspect the entities that directly do that are things
+ that shouldn't go to duplicate_decls (FIELD_DECLs etc). */
+ else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing)))
+ {
+ mismatch:
+ map_context_from = map_context_to = NULL_TREE;
+ if (DECL_IS_UNDECLARED_BUILTIN (existing))
+ /* Just like duplicate_decls, presum the user knows what
+ they're doing in overriding a builtin. */
+ TREE_TYPE (existing) = TREE_TYPE (decl);
+ else
+ {
+ // FIXME:QOI Might be template specialization from a module,
+ // not necessarily global module
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "conflicting global module declaration %#qD", decl);
+ inform (DECL_SOURCE_LOCATION (existing),
+ "existing declaration %#qD", existing);
+ return false;
+ }
+ }
+
+ map_context_from = map_context_to = NULL_TREE;
+
+ if (DECL_IS_UNDECLARED_BUILTIN (existing)
+ && !DECL_IS_UNDECLARED_BUILTIN (decl))
+ {
+ /* We're matching a builtin that the user has yet to declare.
+ We are the one! This is very much duplicate-decl
+ shenanigans. */
+ DECL_SOURCE_LOCATION (existing) = DECL_SOURCE_LOCATION (decl);
+ if (TREE_CODE (decl) != TYPE_DECL)
+ {
+ /* Propagate exceptions etc. */
+ TREE_TYPE (existing) = TREE_TYPE (decl);
+ TREE_NOTHROW (existing) = TREE_NOTHROW (decl);
+ }
+ /* This is actually an import! */
+ DECL_MODULE_IMPORT_P (existing) = true;
+
+ /* Yay, sliced! */
+ existing->base = decl->base;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ /* Ew :( */
+ memcpy (&existing->decl_common.size,
+ &decl->decl_common.size,
+ (offsetof (tree_decl_common, pt_uid)
+ - offsetof (tree_decl_common, size)));
+ auto bltin_class = DECL_BUILT_IN_CLASS (decl);
+ existing->function_decl.built_in_class = bltin_class;
+ auto fncode = DECL_UNCHECKED_FUNCTION_CODE (decl);
+ DECL_UNCHECKED_FUNCTION_CODE (existing) = fncode;
+ if (existing->function_decl.built_in_class == BUILT_IN_NORMAL)
+ {
+ if (builtin_decl_explicit_p (built_in_function (fncode)))
+ switch (fncode)
+ {
+ case BUILT_IN_STPCPY:
+ set_builtin_decl_implicit_p
+ (built_in_function (fncode), true);
+ break;
+ default:
+ set_builtin_decl_declared_p
+ (built_in_function (fncode), true);
+ break;
+ }
+ copy_attributes_to_builtin (decl);
+ }
+ }
+ }
+
+ if (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_TEMPLATE_INSTANTIATED (decl))
+ /* Don't instantiate again! */
+ DECL_TEMPLATE_INSTANTIATED (existing) = true;
+
+ tree e_inner = inner == decl ? existing : DECL_TEMPLATE_RESULT (existing);
+
+ if (TREE_CODE (inner) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (inner))
+ DECL_DECLARED_INLINE_P (e_inner) = true;
+ if (!DECL_EXTERNAL (inner))
+ DECL_EXTERNAL (e_inner) = false;
+
+ // FIXME: Check default tmpl and fn parms here
+
+ return true;
+}
+
+/* FN is an implicit member function that we've discovered is new to
+ the class. Add it to the TYPE_FIELDS chain and the method vector.
+ Reset the appropriate classtype lazy flag. */
+
+bool
+trees_in::install_implicit_member (tree fn)
+{
+ tree ctx = DECL_CONTEXT (fn);
+ tree name = DECL_NAME (fn);
+ /* We know these are synthesized, so the set of expected prototypes
+ is quite restricted. We're not validating correctness, just
+ distinguishing beteeen the small set of possibilities. */
+ tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (fn));
+ if (IDENTIFIER_CTOR_P (name))
+ {
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (ctx)
+ && VOID_TYPE_P (parm_type))
+ CLASSTYPE_LAZY_DEFAULT_CTOR (ctx) = false;
+ else if (!TYPE_REF_P (parm_type))
+ return false;
+ else if (CLASSTYPE_LAZY_COPY_CTOR (ctx)
+ && !TYPE_REF_IS_RVALUE (parm_type))
+ CLASSTYPE_LAZY_COPY_CTOR (ctx) = false;
+ else if (CLASSTYPE_LAZY_MOVE_CTOR (ctx))
+ CLASSTYPE_LAZY_MOVE_CTOR (ctx) = false;
+ else
+ return false;
+ }
+ else if (IDENTIFIER_DTOR_P (name))
+ {
+ if (CLASSTYPE_LAZY_DESTRUCTOR (ctx))
+ CLASSTYPE_LAZY_DESTRUCTOR (ctx) = false;
+ else
+ return false;
+ if (DECL_VIRTUAL_P (fn))
+ /* A virtual dtor should have been created when the class
+ became complete. */
+ return false;
+ }
+ else if (name == assign_op_identifier)
+ {
+ if (!TYPE_REF_P (parm_type))
+ return false;
+ else if (CLASSTYPE_LAZY_COPY_ASSIGN (ctx)
+ && !TYPE_REF_IS_RVALUE (parm_type))
+ CLASSTYPE_LAZY_COPY_ASSIGN (ctx) = false;
+ else if (CLASSTYPE_LAZY_MOVE_ASSIGN (ctx))
+ CLASSTYPE_LAZY_MOVE_ASSIGN (ctx) = false;
+ else
+ return false;
+ }
+ else
+ return false;
+
+ dump (dumper::MERGE) && dump ("Adding implicit member %N", fn);
+
+ DECL_CHAIN (fn) = TYPE_FIELDS (ctx);
+ TYPE_FIELDS (ctx) = fn;
+
+ add_method (ctx, fn, false);
+
+ /* Propagate TYPE_FIELDS. */
+ fixup_type_variants (ctx);
+
+ return true;
+}
+
+/* Return non-zero if DECL has a definition that would be interesting to
+ write out. */
+
+static bool
+has_definition (tree decl)
+{
+ bool is_tmpl = TREE_CODE (decl) == TEMPLATE_DECL;
+ if (is_tmpl)
+ decl = DECL_TEMPLATE_RESULT (decl);
+
+ switch (TREE_CODE (decl))
+ {
+ default:
+ break;
+
+ case FUNCTION_DECL:
+ if (!DECL_SAVED_TREE (decl))
+ /* Not defined. */
+ break;
+
+ if (DECL_DECLARED_INLINE_P (decl))
+ return true;
+
+ if (DECL_THIS_STATIC (decl)
+ && (header_module_p ()
+ || (!DECL_LANG_SPECIFIC (decl) || !DECL_MODULE_PURVIEW_P (decl))))
+ /* GM static function. */
+ return true;
+
+ if (DECL_TEMPLATE_INFO (decl))
+ {
+ int use_tpl = DECL_USE_TEMPLATE (decl);
+
+ // FIXME: Partial specializations have definitions too.
+ if (use_tpl < 2)
+ return true;
+ }
+ break;
+
+ case TYPE_DECL:
+ {
+ tree type = TREE_TYPE (decl);
+ if (type == TYPE_MAIN_VARIANT (type)
+ && decl == TYPE_NAME (type)
+ && (TREE_CODE (type) == ENUMERAL_TYPE
+ ? TYPE_VALUES (type) : TYPE_FIELDS (type)))
+ return true;
+ }
+ break;
+
+ case VAR_DECL:
+ if (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl)
+ && DECL_USE_TEMPLATE (decl) < 2)
+ return DECL_INITIAL (decl);
+ else
+ {
+ if (!DECL_INITIALIZED_P (decl))
+ return false;
+
+ if (header_module_p ()
+ || (!DECL_LANG_SPECIFIC (decl) || !DECL_MODULE_PURVIEW_P (decl)))
+ /* GM static variable. */
+ return true;
+
+ if (!TREE_CONSTANT (decl))
+ return false;
+
+ return true;
+ }
+ break;
+
+ case CONCEPT_DECL:
+ if (DECL_INITIAL (decl))
+ return true;
+
+ break;
+ }
+
+ return false;
+}
+
+uintptr_t *
+trees_in::find_duplicate (tree existing)
+{
+ if (!duplicates)
+ return NULL;
+
+ return duplicates->get (existing);
+}
+
+/* We're starting to read a duplicate DECL. EXISTING is the already
+ known node. */
+
+void
+trees_in::register_duplicate (tree decl, tree existing)
+{
+ if (!duplicates)
+ duplicates = new duplicate_hash_map (40);
+
+ bool existed;
+ uintptr_t &slot = duplicates->get_or_insert (existing, &existed);
+ gcc_checking_assert (!existed);
+ slot = reinterpret_cast<uintptr_t> (decl);
+}
+
+/* We've read a definition of MAYBE_EXISTING. If not a duplicate,
+ return MAYBE_EXISTING (into which the definition should be
+ installed). Otherwise return NULL if already known bad, or the
+ duplicate we read (for ODR checking, or extracting addtional merge
+ information). */
+
+tree
+trees_in::odr_duplicate (tree maybe_existing, bool has_defn)
+{
+ tree res = NULL_TREE;
+
+ if (uintptr_t *dup = find_duplicate (maybe_existing))
+ {
+ if (!(*dup & 1))
+ res = reinterpret_cast<tree> (*dup);
+ }
+ else
+ res = maybe_existing;
+
+ assert_definition (maybe_existing, res && !has_defn);
+
+ // FIXME: We probably need to return the template, so that the
+ // template header can be checked?
+ return res ? STRIP_TEMPLATE (res) : NULL_TREE;
+}
+
+/* The following writer functions rely on the current behaviour of
+ depset::hash::add_dependency making the decl and defn depset nodes
+ depend on eachother. That way we don't have to worry about seeding
+ the tree map with named decls that cannot be looked up by name (I.e
+ template and function parms). We know the decl and definition will
+ be in the same cluster, which is what we want. */
+
+void
+trees_out::write_function_def (tree decl)
+{
+ tree_node (DECL_RESULT (decl));
+ tree_node (DECL_INITIAL (decl));
+ tree_node (DECL_SAVED_TREE (decl));
+ tree_node (DECL_FRIEND_CONTEXT (decl));
+
+ constexpr_fundef *cexpr = retrieve_constexpr_fundef (decl);
+ int tag = 0;
+ if (cexpr)
+ {
+ if (cexpr->result == error_mark_node)
+ /* We'll stream the RESULT_DECL naturally during the
+ serialization. We never need to fish it back again, so
+ that's ok. */
+ tag = 0;
+ else
+ tag = insert (cexpr->result);
+ }
+ if (streaming_p ())
+ {
+ i (tag);
+ if (tag)
+ dump (dumper::TREE)
+ && dump ("Constexpr:%d result %N", tag, cexpr->result);
+ }
+ if (tag)
+ {
+ unsigned ix = 0;
+ for (tree parm = cexpr->parms; parm; parm = DECL_CHAIN (parm), ix++)
+ {
+ tag = insert (parm);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Constexpr:%d parm:%u %N", tag, ix, parm);
+ }
+ tree_node (cexpr->body);
+ }
+
+ if (streaming_p ())
+ {
+ unsigned flags = 0;
+
+ if (DECL_NOT_REALLY_EXTERN (decl))
+ flags |= 1;
+
+ u (flags);
+ }
+}
+
+void
+trees_out::mark_function_def (tree)
+{
+}
+
+bool
+trees_in::read_function_def (tree decl, tree maybe_template)
+{
+ dump () && dump ("Reading function definition %N", decl);
+ tree result = tree_node ();
+ tree initial = tree_node ();
+ tree saved = tree_node ();
+ tree context = tree_node ();
+ constexpr_fundef cexpr;
+
+ tree maybe_dup = odr_duplicate (maybe_template, DECL_SAVED_TREE (decl));
+ bool installing = maybe_dup && !DECL_SAVED_TREE (decl);
+
+ if (maybe_dup)
+ for (auto parm = DECL_ARGUMENTS (maybe_dup); parm; parm = DECL_CHAIN (parm))
+ DECL_CONTEXT (parm) = decl;
+
+ if (int wtag = i ())
+ {
+ int tag = 1;
+ cexpr.result = error_mark_node;
+
+ cexpr.result = copy_decl (result);
+ tag = insert (cexpr.result);
+
+ if (wtag != tag)
+ set_overrun ();
+ dump (dumper::TREE)
+ && dump ("Constexpr:%d result %N", tag, cexpr.result);
+
+ cexpr.parms = NULL_TREE;
+ tree *chain = &cexpr.parms;
+ unsigned ix = 0;
+ for (tree parm = DECL_ARGUMENTS (maybe_dup ? maybe_dup : decl);
+ parm; parm = DECL_CHAIN (parm), ix++)
+ {
+ tree p = copy_decl (parm);
+ tag = insert (p);
+ dump (dumper::TREE)
+ && dump ("Constexpr:%d parm:%u %N", tag, ix, p);
+ *chain = p;
+ chain = &DECL_CHAIN (p);
+ }
+ cexpr.body = tree_node ();
+ cexpr.decl = decl;
+ }
+ else
+ cexpr.decl = NULL_TREE;
+
+ unsigned flags = u ();
+
+ if (get_overrun ())
+ return NULL_TREE;
+
+ if (installing)
+ {
+ DECL_NOT_REALLY_EXTERN (decl) = flags & 1;
+ DECL_RESULT (decl) = result;
+ DECL_INITIAL (decl) = initial;
+ DECL_SAVED_TREE (decl) = saved;
+ if (maybe_dup)
+ DECL_ARGUMENTS (decl) = DECL_ARGUMENTS (maybe_dup);
+
+ if (context)
+ SET_DECL_FRIEND_CONTEXT (decl, context);
+ if (cexpr.decl)
+ register_constexpr_fundef (cexpr);
+ post_process (maybe_template);
+ }
+ else if (maybe_dup)
+ {
+ // FIXME:QOI Check matching defn
+ }
+
+ return true;
+}
+
+/* Also for CONCEPT_DECLs. */
+
+void
+trees_out::write_var_def (tree decl)
+{
+ tree init = DECL_INITIAL (decl);
+ tree_node (init);
+ if (!init)
+ {
+ tree dyn_init = NULL_TREE;
+
+ if (DECL_NONTRIVIALLY_INITIALIZED_P (decl))
+ {
+ dyn_init = value_member (decl,
+ CP_DECL_THREAD_LOCAL_P (decl)
+ ? tls_aggregates : static_aggregates);
+ gcc_checking_assert (dyn_init);
+ /* Mark it so write_inits knows this is needed. */
+ TREE_LANG_FLAG_0 (dyn_init) = true;
+ dyn_init = TREE_PURPOSE (dyn_init);
+ }
+ tree_node (dyn_init);
+ }
+}
+
+void
+trees_out::mark_var_def (tree)
+{
+}
+
+bool
+trees_in::read_var_def (tree decl, tree maybe_template)
+{
+ /* Do not mark the virtual table entries as used. */
+ bool vtable = TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl);
+ unused += vtable;
+ tree init = tree_node ();
+ tree dyn_init = init ? NULL_TREE : tree_node ();
+ unused -= vtable;
+
+ if (get_overrun ())
+ return false;
+
+ bool initialized = (VAR_P (decl) ? bool (DECL_INITIALIZED_P (decl))
+ : bool (DECL_INITIAL (decl)));
+ tree maybe_dup = odr_duplicate (maybe_template, initialized);
+ bool installing = maybe_dup && !initialized;
+ if (installing)
+ {
+ if (DECL_EXTERNAL (decl))
+ DECL_NOT_REALLY_EXTERN (decl) = true;
+ if (VAR_P (decl))
+ DECL_INITIALIZED_P (decl) = true;
+ DECL_INITIAL (decl) = init;
+ if (!dyn_init)
+ ;
+ else if (CP_DECL_THREAD_LOCAL_P (decl))
+ tls_aggregates = tree_cons (dyn_init, decl, tls_aggregates);
+ else
+ static_aggregates = tree_cons (dyn_init, decl, static_aggregates);
+ }
+ else if (maybe_dup)
+ {
+ // FIXME:QOI Check matching defn
+ }
+
+ return true;
+}
+
+/* If MEMBER doesn't have an independent life outside the class,
+ return it (or it's TEMPLATE_DECL). Otherwise NULL. */
+
+static tree
+member_owned_by_class (tree member)
+{
+ gcc_assert (DECL_P (member));
+
+ /* Clones are owned by their origin. */
+ if (DECL_CLONED_FUNCTION_P (member))
+ return NULL;
+
+ if (TREE_CODE (member) == FIELD_DECL)
+ /* FIELD_DECLS can have template info in some cases. We always
+ want the FIELD_DECL though, as there's never a TEMPLATE_DECL
+ wrapping them. */
+ return member;
+
+ int use_tpl = -1;
+ if (tree ti = node_template_info (member, use_tpl))
+ {
+ // FIXME: Don't bail on things that CANNOT have their own
+ // template header. No, make sure they're in the same cluster.
+ if (use_tpl > 0)
+ return NULL_TREE;
+
+ if (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti)) == member)
+ member = TI_TEMPLATE (ti);
+ }
+ return member;
+}
+
+void
+trees_out::write_class_def (tree defn)
+{
+ gcc_assert (DECL_P (defn));
+ if (streaming_p ())
+ dump () && dump ("Writing class definition %N", defn);
+
+ tree type = TREE_TYPE (defn);
+ tree_node (TYPE_SIZE (type));
+ tree_node (TYPE_SIZE_UNIT (type));
+ tree_node (TYPE_VFIELD (type));
+ tree_node (TYPE_BINFO (type));
+
+ vec_chained_decls (TYPE_FIELDS (type));
+
+ /* Every class but __as_base has a type-specific. */
+ gcc_checking_assert (!TYPE_LANG_SPECIFIC (type) == IS_FAKE_BASE_TYPE (type));
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ {
+ vec<tree, va_gc> *v = CLASSTYPE_MEMBER_VEC (type);
+ if (!v)
+ {
+ gcc_checking_assert (!streaming_p ());
+ /* Force a class vector. */
+ v = set_class_bindings (type, -1);
+ gcc_checking_assert (v);
+ }
+
+ unsigned len = v->length ();
+ if (streaming_p ())
+ u (len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree m = (*v)[ix];
+ if (TREE_CODE (m) == TYPE_DECL
+ && DECL_ARTIFICIAL (m)
+ && TYPE_STUB_DECL (TREE_TYPE (m)) == m)
+ /* This is a using-decl for a type, or an anonymous
+ struct (maybe with a typedef name). Write the type. */
+ m = TREE_TYPE (m);
+ tree_node (m);
+ }
+ }
+ tree_node (CLASSTYPE_LAMBDA_EXPR (type));
+
+ /* TYPE_CONTAINS_VPTR_P looks at the vbase vector, which the
+ reader won't know at this point. */
+ int has_vptr = TYPE_CONTAINS_VPTR_P (type);
+
+ if (streaming_p ())
+ {
+ unsigned nvbases = vec_safe_length (CLASSTYPE_VBASECLASSES (type));
+ u (nvbases);
+ i (has_vptr);
+ }
+
+ if (has_vptr)
+ {
+ tree_vec (CLASSTYPE_PURE_VIRTUALS (type));
+ tree_pair_vec (CLASSTYPE_VCALL_INDICES (type));
+ tree_node (CLASSTYPE_KEY_METHOD (type));
+ }
+ }
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ tree_node (CLASSTYPE_PRIMARY_BINFO (type));
+
+ tree as_base = CLASSTYPE_AS_BASE (type);
+ if (as_base)
+ as_base = TYPE_NAME (as_base);
+ tree_node (as_base);
+
+ /* Write the vtables. */
+ tree vtables = CLASSTYPE_VTABLES (type);
+ vec_chained_decls (vtables);
+ for (; vtables; vtables = TREE_CHAIN (vtables))
+ write_definition (vtables);
+
+ /* Write the friend classes. */
+ tree_list (CLASSTYPE_FRIEND_CLASSES (type), false);
+
+ /* Write the friend functions. */
+ for (tree friends = DECL_FRIENDLIST (defn);
+ friends; friends = TREE_CHAIN (friends))
+ {
+ /* Name of these friends. */
+ tree_node (TREE_PURPOSE (friends));
+ tree_list (TREE_VALUE (friends), false);
+ }
+ /* End of friend fns. */
+ tree_node (NULL_TREE);
+
+ /* Write the decl list. */
+ tree_list (CLASSTYPE_DECL_LIST (type), true);
+
+ if (TYPE_CONTAINS_VPTR_P (type))
+ {
+ /* Write the thunks. */
+ for (tree decls = TYPE_FIELDS (type);
+ decls; decls = DECL_CHAIN (decls))
+ if (TREE_CODE (decls) == FUNCTION_DECL
+ && DECL_VIRTUAL_P (decls)
+ && DECL_THUNKS (decls))
+ {
+ tree_node (decls);
+ /* Thunks are always unique, so chaining is ok. */
+ chained_decls (DECL_THUNKS (decls));
+ }
+ tree_node (NULL_TREE);
+ }
+ }
+}
+
+void
+trees_out::mark_class_member (tree member, bool do_defn)
+{
+ gcc_assert (DECL_P (member));
+
+ member = member_owned_by_class (member);
+ if (member)
+ mark_declaration (member, do_defn && has_definition (member));
+}
+
+void
+trees_out::mark_class_def (tree defn)
+{
+ gcc_assert (DECL_P (defn));
+ tree type = TREE_TYPE (defn);
+ /* Mark the class members that are not type-decls and cannot have
+ independent definitions. */
+ for (tree member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
+ if (TREE_CODE (member) == FIELD_DECL
+ || TREE_CODE (member) == USING_DECL
+ /* A cloned enum-decl from 'using enum unrelated;' */
+ || (TREE_CODE (member) == CONST_DECL
+ && DECL_CONTEXT (member) == type))
+ {
+ mark_class_member (member);
+ if (TREE_CODE (member) == FIELD_DECL)
+ if (tree repr = DECL_BIT_FIELD_REPRESENTATIVE (member))
+ mark_declaration (repr, false);
+ }
+
+ /* Mark the binfo hierarchy. */
+ for (tree child = TYPE_BINFO (type); child; child = TREE_CHAIN (child))
+ mark_by_value (child);
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ for (tree vtable = CLASSTYPE_VTABLES (type);
+ vtable; vtable = TREE_CHAIN (vtable))
+ mark_declaration (vtable, true);
+
+ if (TYPE_CONTAINS_VPTR_P (type))
+ /* Mark the thunks, they belong to the class definition,
+ /not/ the thunked-to function. */
+ for (tree decls = TYPE_FIELDS (type);
+ decls; decls = DECL_CHAIN (decls))
+ if (TREE_CODE (decls) == FUNCTION_DECL)
+ for (tree thunks = DECL_THUNKS (decls);
+ thunks; thunks = DECL_CHAIN (thunks))
+ mark_declaration (thunks, false);
+ }
+}
+
+/* Nop sorting, needed for resorting the member vec. */
+
+static void
+nop (void *, void *)
+{
+}
+
+bool
+trees_in::read_class_def (tree defn, tree maybe_template)
+{
+ gcc_assert (DECL_P (defn));
+ dump () && dump ("Reading class definition %N", defn);
+ tree type = TREE_TYPE (defn);
+ tree size = tree_node ();
+ tree size_unit = tree_node ();
+ tree vfield = tree_node ();
+ tree binfo = tree_node ();
+ vec<tree, va_gc> *vbase_vec = NULL;
+ vec<tree, va_gc> *member_vec = NULL;
+ vec<tree, va_gc> *pure_virts = NULL;
+ vec<tree_pair_s, va_gc> *vcall_indices = NULL;
+ tree key_method = NULL_TREE;
+ tree lambda = NULL_TREE;
+
+ /* Read the fields. */
+ vec<tree, va_heap> *fields = vec_chained_decls ();
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ if (unsigned len = u ())
+ {
+ vec_alloc (member_vec, len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree m = tree_node ();
+ if (get_overrun ())
+ break;
+ if (TYPE_P (m))
+ m = TYPE_STUB_DECL (m);
+ member_vec->quick_push (m);
+ }
+ }
+ lambda = tree_node ();
+
+ if (!get_overrun ())
+ {
+ unsigned nvbases = u ();
+ if (nvbases)
+ {
+ vec_alloc (vbase_vec, nvbases);
+ for (tree child = binfo; child; child = TREE_CHAIN (child))
+ if (BINFO_VIRTUAL_P (child))
+ vbase_vec->quick_push (child);
+ }
+ }
+
+ if (!get_overrun ())
+ {
+ int has_vptr = i ();
+ if (has_vptr)
+ {
+ pure_virts = tree_vec ();
+ vcall_indices = tree_pair_vec ();
+ key_method = tree_node ();
+ }
+ }
+ }
+
+ tree maybe_dup = odr_duplicate (maybe_template, TYPE_SIZE (type));
+ bool installing = maybe_dup && !TYPE_SIZE (type);
+ if (installing)
+ {
+ if (DECL_EXTERNAL (defn) && TYPE_LANG_SPECIFIC (type))
+ {
+ /* We don't deal with not-really-extern, because, for a
+ module you want the import to be the interface, and for a
+ header-unit, you're doing it wrong. */
+ CLASSTYPE_INTERFACE_UNKNOWN (type) = false;
+ CLASSTYPE_INTERFACE_ONLY (type) = true;
+ }
+
+ if (maybe_dup != defn)
+ {
+ // FIXME: This is needed on other defns too, almost
+ // duplicate-decl like? See is_matching_decl too.
+ /* Copy flags from the duplicate. */
+ tree type_dup = TREE_TYPE (maybe_dup);
+
+ /* Core pieces. */
+ TYPE_MODE_RAW (type) = TYPE_MODE_RAW (type_dup);
+ SET_DECL_MODE (defn, DECL_MODE (maybe_dup));
+ TREE_ADDRESSABLE (type) = TREE_ADDRESSABLE (type_dup);
+ DECL_SIZE (defn) = DECL_SIZE (maybe_dup);
+ DECL_SIZE_UNIT (defn) = DECL_SIZE_UNIT (maybe_dup);
+ DECL_ALIGN_RAW (defn) = DECL_ALIGN_RAW (maybe_dup);
+ DECL_WARN_IF_NOT_ALIGN_RAW (defn)
+ = DECL_WARN_IF_NOT_ALIGN_RAW (maybe_dup);
+ DECL_USER_ALIGN (defn) = DECL_USER_ALIGN (maybe_dup);
+
+ /* C++ pieces. */
+ TYPE_POLYMORPHIC_P (type) = TYPE_POLYMORPHIC_P (type_dup);
+ TYPE_HAS_USER_CONSTRUCTOR (type)
+ = TYPE_HAS_USER_CONSTRUCTOR (type_dup);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type_dup);
+
+ if (auto ls = TYPE_LANG_SPECIFIC (type_dup))
+ {
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ CLASSTYPE_BEFRIENDING_CLASSES (type_dup)
+ = CLASSTYPE_BEFRIENDING_CLASSES (type);
+ CLASSTYPE_TYPEINFO_VAR (type_dup)
+ = CLASSTYPE_TYPEINFO_VAR (type);
+ }
+ for (tree v = type; v; v = TYPE_NEXT_VARIANT (v))
+ TYPE_LANG_SPECIFIC (v) = ls;
+ }
+ }
+
+ TYPE_SIZE (type) = size;
+ TYPE_SIZE_UNIT (type) = size_unit;
+
+ if (fields)
+ {
+ tree *chain = &TYPE_FIELDS (type);
+ unsigned len = fields->length ();
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree decl = (*fields)[ix];
+
+ if (!decl)
+ {
+ /* An anonymous struct with typedef name. */
+ tree tdef = (*fields)[ix+1];
+ decl = TYPE_STUB_DECL (TREE_TYPE (tdef));
+ gcc_checking_assert (IDENTIFIER_ANON_P (DECL_NAME (decl))
+ && decl != tdef);
+ }
+
+ gcc_checking_assert (!*chain == !DECL_CLONED_FUNCTION_P (decl));
+ *chain = decl;
+ chain = &DECL_CHAIN (decl);
+
+ if (TREE_CODE (decl) == USING_DECL
+ && TREE_CODE (USING_DECL_SCOPE (decl)) == RECORD_TYPE)
+ {
+ /* Reconstruct DECL_ACCESS. */
+ tree decls = USING_DECL_DECLS (decl);
+ tree access = declared_access (decl);
+
+ for (ovl_iterator iter (decls); iter; ++iter)
+ {
+ tree d = *iter;
+
+ retrofit_lang_decl (d);
+ tree list = DECL_ACCESS (d);
+
+ if (!purpose_member (type, list))
+ DECL_ACCESS (d) = tree_cons (type, access, list);
+ }
+ }
+ }
+ }
+
+ TYPE_VFIELD (type) = vfield;
+ TYPE_BINFO (type) = binfo;
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ CLASSTYPE_LAMBDA_EXPR (type) = lambda;
+
+ CLASSTYPE_MEMBER_VEC (type) = member_vec;
+ CLASSTYPE_PURE_VIRTUALS (type) = pure_virts;
+ CLASSTYPE_VCALL_INDICES (type) = vcall_indices;
+
+ CLASSTYPE_KEY_METHOD (type) = key_method;
+
+ CLASSTYPE_VBASECLASSES (type) = vbase_vec;
+
+ /* Resort the member vector. */
+ resort_type_member_vec (member_vec, NULL, nop, NULL);
+ }
+ }
+ else if (maybe_dup)
+ {
+ // FIXME:QOI Check matching defn
+ }
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ tree primary = tree_node ();
+ tree as_base = tree_node ();
+
+ if (as_base)
+ as_base = TREE_TYPE (as_base);
+
+ /* Read the vtables. */
+ vec<tree, va_heap> *vtables = vec_chained_decls ();
+ if (vtables)
+ {
+ unsigned len = vtables->length ();
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree vtable = (*vtables)[ix];
+ read_var_def (vtable, vtable);
+ }
+ }
+
+ tree friend_classes = tree_list (false);
+ tree friend_functions = NULL_TREE;
+ for (tree *chain = &friend_functions;
+ tree name = tree_node (); chain = &TREE_CHAIN (*chain))
+ {
+ tree val = tree_list (false);
+ *chain = build_tree_list (name, val);
+ }
+ tree decl_list = tree_list (true);
+
+ if (installing)
+ {
+ CLASSTYPE_PRIMARY_BINFO (type) = primary;
+ CLASSTYPE_AS_BASE (type) = as_base;
+
+ if (vtables)
+ {
+ if (!CLASSTYPE_KEY_METHOD (type)
+ /* Sneaky user may have defined it inline
+ out-of-class. */
+ || DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type)))
+ vec_safe_push (keyed_classes, type);
+ unsigned len = vtables->length ();
+ tree *chain = &CLASSTYPE_VTABLES (type);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ tree vtable = (*vtables)[ix];
+ gcc_checking_assert (!*chain);
+ *chain = vtable;
+ chain = &DECL_CHAIN (vtable);
+ }
+ }
+ CLASSTYPE_FRIEND_CLASSES (type) = friend_classes;
+ DECL_FRIENDLIST (defn) = friend_functions;
+ CLASSTYPE_DECL_LIST (type) = decl_list;
+
+ for (; friend_classes; friend_classes = TREE_CHAIN (friend_classes))
+ {
+ tree f = TREE_VALUE (friend_classes);
+
+ if (TYPE_P (f))
+ {
+ CLASSTYPE_BEFRIENDING_CLASSES (f)
+ = tree_cons (NULL_TREE, type,
+ CLASSTYPE_BEFRIENDING_CLASSES (f));
+ dump () && dump ("Class %N befriending %C:%N",
+ type, TREE_CODE (f), f);
+ }
+ }
+
+ for (; friend_functions;
+ friend_functions = TREE_CHAIN (friend_functions))
+ for (tree friend_decls = TREE_VALUE (friend_functions);
+ friend_decls; friend_decls = TREE_CHAIN (friend_decls))
+ {
+ tree f = TREE_VALUE (friend_decls);
+
+ DECL_BEFRIENDING_CLASSES (f)
+ = tree_cons (NULL_TREE, type, DECL_BEFRIENDING_CLASSES (f));
+ dump () && dump ("Class %N befriending %C:%N",
+ type, TREE_CODE (f), f);
+ }
+ }
+
+ if (TYPE_CONTAINS_VPTR_P (type))
+ /* Read and install the thunks. */
+ while (tree vfunc = tree_node ())
+ {
+ tree thunks = chained_decls ();
+ if (installing)
+ SET_DECL_THUNKS (vfunc, thunks);
+ }
+
+ vec_free (vtables);
+ }
+
+ /* Propagate to all variants. */
+ if (installing)
+ fixup_type_variants (type);
+
+ /* IS_FAKE_BASE_TYPE is inaccurate at this point, because if this is
+ the fake base, we've not hooked it into the containing class's
+ data structure yet. Fortunately it has a unique name. */
+ if (installing
+ && DECL_NAME (defn) != as_base_identifier
+ && (!CLASSTYPE_TEMPLATE_INFO (type)
+ || !uses_template_parms (TI_ARGS (CLASSTYPE_TEMPLATE_INFO (type)))))
+ /* Emit debug info. It'd be nice to know if the interface TU
+ already emitted this. */
+ rest_of_type_compilation (type, !LOCAL_CLASS_P (type));
+
+ vec_free (fields);
+
+ return !get_overrun ();
+}
+
+void
+trees_out::write_enum_def (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+
+ tree_node (TYPE_VALUES (type));
+ tree_node (TYPE_MIN_VALUE (type));
+ tree_node (TYPE_MAX_VALUE (type));
+}
+
+void
+trees_out::mark_enum_def (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+
+ for (tree values = TYPE_VALUES (type); values; values = TREE_CHAIN (values))
+ {
+ tree cst = TREE_VALUE (values);
+ mark_by_value (cst);
+ /* We must mark the init to avoid circularity in tt_enum_int. */
+ if (tree init = DECL_INITIAL (cst))
+ if (TREE_CODE (init) == INTEGER_CST)
+ mark_by_value (init);
+ }
+}
+
+bool
+trees_in::read_enum_def (tree defn, tree maybe_template)
+{
+ tree type = TREE_TYPE (defn);
+ tree values = tree_node ();
+ tree min = tree_node ();
+ tree max = tree_node ();
+
+ if (get_overrun ())
+ return false;
+
+ tree maybe_dup = odr_duplicate (maybe_template, TYPE_VALUES (type));
+ bool installing = maybe_dup && !TYPE_VALUES (type);
+
+ if (installing)
+ {
+ TYPE_VALUES (type) = values;
+ TYPE_MIN_VALUE (type) = min;
+ TYPE_MAX_VALUE (type) = max;
+
+ rest_of_type_compilation (type, DECL_NAMESPACE_SCOPE_P (defn));
+ }
+ else if (maybe_dup)
+ {
+ tree known = TYPE_VALUES (type);
+ for (; known && values;
+ known = TREE_CHAIN (known), values = TREE_CHAIN (values))
+ {
+ tree known_decl = TREE_VALUE (known);
+ tree new_decl = TREE_VALUE (values);
+
+ if (DECL_NAME (known_decl) != DECL_NAME (new_decl))
+ goto bad;
+
+ new_decl = maybe_duplicate (new_decl);
+
+ if (!cp_tree_equal (DECL_INITIAL (known_decl),
+ DECL_INITIAL (new_decl)))
+ goto bad;
+ }
+
+ if (known || values)
+ goto bad;
+
+ if (!cp_tree_equal (TYPE_MIN_VALUE (type), min)
+ || !cp_tree_equal (TYPE_MAX_VALUE (type), max))
+ {
+ bad:;
+ error_at (DECL_SOURCE_LOCATION (maybe_dup),
+ "definition of %qD does not match", maybe_dup);
+ inform (DECL_SOURCE_LOCATION (defn),
+ "existing definition %qD", defn);
+
+ tree known_decl = NULL_TREE, new_decl = NULL_TREE;
+
+ if (known)
+ known_decl = TREE_VALUE (known);
+ if (values)
+ new_decl = maybe_duplicate (TREE_VALUE (values));
+
+ if (known_decl && new_decl)
+ {
+ inform (DECL_SOURCE_LOCATION (new_decl),
+ "... this enumerator %qD", new_decl);
+ inform (DECL_SOURCE_LOCATION (known_decl),
+ "enumerator %qD does not match ...", known_decl);
+ }
+ else if (known_decl || new_decl)
+ {
+ tree extra = known_decl ? known_decl : new_decl;
+ inform (DECL_SOURCE_LOCATION (extra),
+ "additional enumerators beginning with %qD", extra);
+ }
+ else
+ inform (DECL_SOURCE_LOCATION (maybe_dup),
+ "enumeration range differs");
+
+ /* Mark it bad. */
+ unmatched_duplicate (maybe_template);
+ }
+ }
+
+ return true;
+}
+
+/* Write out the body of DECL. See above circularity note. */
+
+void
+trees_out::write_definition (tree decl)
+{
+ if (streaming_p ())
+ {
+ assert_definition (decl);
+ dump ()
+ && dump ("Writing definition %C:%N", TREE_CODE (decl), decl);
+ }
+ else
+ dump (dumper::DEPEND)
+ && dump ("Depending definition %C:%N", TREE_CODE (decl), decl);
+
+ again:
+ switch (TREE_CODE (decl))
+ {
+ default:
+ gcc_unreachable ();
+
+ case TEMPLATE_DECL:
+ decl = DECL_TEMPLATE_RESULT (decl);
+ goto again;
+
+ case FUNCTION_DECL:
+ write_function_def (decl);
+ break;
+
+ case TYPE_DECL:
+ {
+ tree type = TREE_TYPE (decl);
+ gcc_assert (TYPE_MAIN_VARIANT (type) == type
+ && TYPE_NAME (type) == decl);
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ write_enum_def (decl);
+ else
+ write_class_def (decl);
+ }
+ break;
+
+ case VAR_DECL:
+ case CONCEPT_DECL:
+ write_var_def (decl);
+ break;
+ }
+}
+
+/* Mark a declaration for by-value walking. If DO_DEFN is true, mark
+ its body too. */
+
+void
+trees_out::mark_declaration (tree decl, bool do_defn)
+{
+ mark_by_value (decl);
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ decl = DECL_TEMPLATE_RESULT (decl);
+
+ if (!do_defn)
+ return;
+
+ switch (TREE_CODE (decl))
+ {
+ default:
+ gcc_unreachable ();
+
+ case FUNCTION_DECL:
+ mark_function_def (decl);
+ break;
+
+ case TYPE_DECL:
+ {
+ tree type = TREE_TYPE (decl);
+ gcc_assert (TYPE_MAIN_VARIANT (type) == type
+ && TYPE_NAME (type) == decl);
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ mark_enum_def (decl);
+ else
+ mark_class_def (decl);
+ }
+ break;
+
+ case VAR_DECL:
+ case CONCEPT_DECL:
+ mark_var_def (decl);
+ break;
+ }
+}
+
+/* Read in the body of DECL. See above circularity note. */
+
+bool
+trees_in::read_definition (tree decl)
+{
+ dump () && dump ("Reading definition %C %N", TREE_CODE (decl), decl);
+
+ tree maybe_template = decl;
+
+ again:
+ switch (TREE_CODE (decl))
+ {
+ default:
+ break;
+
+ case TEMPLATE_DECL:
+ decl = DECL_TEMPLATE_RESULT (decl);
+ goto again;
+
+ case FUNCTION_DECL:
+ return read_function_def (decl, maybe_template);
+
+ case TYPE_DECL:
+ {
+ tree type = TREE_TYPE (decl);
+ gcc_assert (TYPE_MAIN_VARIANT (type) == type
+ && TYPE_NAME (type) == decl);
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ return read_enum_def (decl, maybe_template);
+ else
+ return read_class_def (decl, maybe_template);
+ }
+ break;
+
+ case VAR_DECL:
+ case CONCEPT_DECL:
+ return read_var_def (decl, maybe_template);
+ }
+
+ return false;
+}
+
+/* Lookup an maybe insert a slot for depset for KEY. */
+
+depset **
+depset::hash::entity_slot (tree entity, bool insert)
+{
+ traits::compare_type key (entity, NULL);
+ depset **slot = find_slot_with_hash (key, traits::hash (key),
+ insert ? INSERT : NO_INSERT);
+
+ return slot;
+}
+
+depset **
+depset::hash::binding_slot (tree ctx, tree name, bool insert)
+{
+ traits::compare_type key (ctx, name);
+ depset **slot = find_slot_with_hash (key, traits::hash (key),
+ insert ? INSERT : NO_INSERT);
+
+ return slot;
+}
+
+depset *
+depset::hash::find_dependency (tree decl)
+{
+ depset **slot = entity_slot (decl, false);
+
+ return slot ? *slot : NULL;
+}
+
+depset *
+depset::hash::find_binding (tree ctx, tree name)
+{
+ depset **slot = binding_slot (ctx, name, false);
+
+ return slot ? *slot : NULL;
+}
+
+/* DECL is a newly discovered dependency. Create the depset, if it
+ doesn't already exist. Add it to the worklist if so.
+
+ DECL will be an OVL_USING_P OVERLOAD, if it's from a binding that's
+ a using decl.
+
+ We do not have to worry about adding the same dependency more than
+ once. First it's harmless, but secondly the TREE_VISITED marking
+ prevents us wanting to do it anyway. */
+
+depset *
+depset::hash::make_dependency (tree decl, entity_kind ek)
+{
+ /* Make sure we're being told consistent information. */
+ gcc_checking_assert ((ek == EK_NAMESPACE)
+ == (TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl)));
+ gcc_checking_assert (ek != EK_BINDING && ek != EK_REDIRECT);
+ gcc_checking_assert (TREE_CODE (decl) != FIELD_DECL
+ && (TREE_CODE (decl) != USING_DECL
+ || TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL));
+ gcc_checking_assert (!is_key_order ());
+ if (ek == EK_USING)
+ gcc_checking_assert (TREE_CODE (decl) == OVERLOAD);
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ /* The template should have copied these from its result decl. */
+ tree res = DECL_TEMPLATE_RESULT (decl);
+
+ gcc_checking_assert (DECL_MODULE_EXPORT_P (decl)
+ == DECL_MODULE_EXPORT_P (res));
+ if (DECL_LANG_SPECIFIC (res))
+ {
+ gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl)
+ == DECL_MODULE_PURVIEW_P (res));
+ gcc_checking_assert ((DECL_MODULE_IMPORT_P (decl)
+ == DECL_MODULE_IMPORT_P (res)));
+ }
+ }
+
+ depset **slot = entity_slot (decl, true);
+ depset *dep = *slot;
+ bool for_binding = ek == EK_FOR_BINDING;
+
+ if (!dep)
+ {
+ if (DECL_IMPLICIT_TYPEDEF_P (decl)
+ /* ... not an enum, for instance. */
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+ && TYPE_LANG_SPECIFIC (TREE_TYPE (decl))
+ && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)) == 2)
+ {
+ /* A partial or explicit specialization. Partial
+ specializations might not be in the hash table, because
+ there can be multiple differently-constrained variants.
+
+ template<typename T> class silly;
+ template<typename T> requires true class silly {};
+
+ We need to find them, insert their TEMPLATE_DECL in the
+ dep_hash, and then convert the dep we just found into a
+ redirect. */
+
+ tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (decl));
+ tree tmpl = TI_TEMPLATE (ti);
+ tree partial = NULL_TREE;
+ for (tree spec = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ spec; spec = TREE_CHAIN (spec))
+ if (DECL_TEMPLATE_RESULT (TREE_VALUE (spec)) == decl)
+ {
+ partial = TREE_VALUE (spec);
+ break;
+ }
+
+ if (partial)
+ {
+ /* Eagerly create an empty redirect. The following
+ make_dependency call could cause hash reallocation,
+ and invalidate slot's value. */
+ depset *redirect = make_entity (decl, EK_REDIRECT);
+
+ /* Redirects are never reached -- always snap to their target. */
+ redirect->set_flag_bit<DB_UNREACHED_BIT> ();
+
+ *slot = redirect;
+
+ depset *tmpl_dep = make_dependency (partial, EK_PARTIAL);
+ gcc_checking_assert (tmpl_dep->get_entity_kind () == EK_PARTIAL);
+
+ redirect->deps.safe_push (tmpl_dep);
+
+ return redirect;
+ }
+ }
+
+ bool has_def = ek != EK_USING && has_definition (decl);
+ if (ek > EK_BINDING)
+ ek = EK_DECL;
+
+ /* The only OVERLOADS we should see are USING decls from
+ bindings. */
+ *slot = dep = make_entity (decl, ek, has_def);
+
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ if (DECL_ALIAS_TEMPLATE_P (decl) && DECL_TEMPLATE_INFO (decl))
+ dep->set_flag_bit<DB_ALIAS_TMPL_INST_BIT> ();
+ else if (CHECKING_P)
+ /* The template_result should otherwise not be in the
+ table, or be an empty redirect (created above). */
+ if (auto *eslot = entity_slot (DECL_TEMPLATE_RESULT (decl), false))
+ gcc_checking_assert ((*eslot)->get_entity_kind () == EK_REDIRECT
+ && !(*eslot)->deps.length ());
+ }
+
+ if (ek != EK_USING
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_MODULE_IMPORT_P (decl))
+ {
+ /* Store the module number and index in cluster/section, so
+ we don't have to look them up again. */
+ unsigned index = import_entity_index (decl);
+ module_state *from = import_entity_module (index);
+ /* Remap will be zero for imports from partitions, which we
+ want to treat as-if declared in this TU. */
+ if (from->remap)
+ {
+ dep->cluster = index - from->entity_lwm;
+ dep->section = from->remap;
+ dep->set_flag_bit<DB_IMPORTED_BIT> ();
+ }
+ }
+
+ if (ek == EK_DECL
+ && !dep->is_import ()
+ && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL
+ && !(TREE_CODE (decl) == TEMPLATE_DECL
+ && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)))
+ {
+ tree ctx = CP_DECL_CONTEXT (decl);
+ tree not_tmpl = STRIP_TEMPLATE (decl);
+
+ if (!TREE_PUBLIC (ctx))
+ /* Member of internal namespace. */
+ dep->set_flag_bit<DB_IS_INTERNAL_BIT> ();
+ else if (VAR_OR_FUNCTION_DECL_P (not_tmpl)
+ && DECL_THIS_STATIC (not_tmpl))
+ {
+ /* An internal decl. This is ok in a GM entity. */
+ if (!(header_module_p ()
+ || !DECL_LANG_SPECIFIC (not_tmpl)
+ || !DECL_MODULE_PURVIEW_P (not_tmpl)))
+ dep->set_flag_bit<DB_IS_INTERNAL_BIT> ();
+ }
+
+ }
+
+ if (!dep->is_import ())
+ worklist.safe_push (dep);
+ }
+
+ dump (dumper::DEPEND)
+ && dump ("%s on %s %C:%N found",
+ ek == EK_REDIRECT ? "Redirect"
+ : for_binding ? "Binding" : "Dependency",
+ dep->entity_kind_name (), TREE_CODE (decl), decl);
+
+ return dep;
+}
+
+/* DEP is a newly discovered dependency. Append it to current's
+ depset. */
+
+void
+depset::hash::add_dependency (depset *dep)
+{
+ gcc_checking_assert (current && !is_key_order ());
+ current->deps.safe_push (dep);
+
+ if (dep->is_internal () && !current->is_internal ())
+ current->set_flag_bit<DB_REFS_INTERNAL_BIT> ();
+
+ if (current->get_entity_kind () == EK_USING
+ && DECL_IMPLICIT_TYPEDEF_P (dep->get_entity ())
+ && TREE_CODE (TREE_TYPE (dep->get_entity ())) == ENUMERAL_TYPE)
+ {
+ /* CURRENT is an unwrapped using-decl and DECL is an enum's
+ implicit typedef. Is CURRENT a member of the enum? */
+ tree c_decl = OVL_FUNCTION (current->get_entity ());
+
+ if (TREE_CODE (c_decl) == CONST_DECL
+ && (current->deps[0]->get_entity ()
+ == CP_DECL_CONTEXT (dep->get_entity ())))
+ /* Make DECL depend on CURRENT. */
+ dep->deps.safe_push (current);
+ }
+
+ if (dep->is_unreached ())
+ {
+ /* The dependency is reachable now. */
+ reached_unreached = true;
+ dep->clear_flag_bit<DB_UNREACHED_BIT> ();
+ dump (dumper::DEPEND)
+ && dump ("Reaching unreached %s %C:%N", dep->entity_kind_name (),
+ TREE_CODE (dep->get_entity ()), dep->get_entity ());
+ }
+}
+
+depset *
+depset::hash::add_dependency (tree decl, entity_kind ek)
+{
+ depset *dep;
+
+ if (is_key_order ())
+ {
+ dep = find_dependency (decl);
+ if (dep)
+ {
+ current->deps.safe_push (dep);
+ dump (dumper::MERGE)
+ && dump ("Key dependency on %s %C:%N found",
+ dep->entity_kind_name (), TREE_CODE (decl), decl);
+ }
+ else
+ {
+ /* It's not a mergeable decl, look for it in the original
+ table. */
+ dep = chain->find_dependency (decl);
+ gcc_checking_assert (dep);
+ }
+ }
+ else
+ {
+ dep = make_dependency (decl, ek);
+ if (dep->get_entity_kind () != EK_REDIRECT)
+ add_dependency (dep);
+ }
+
+ return dep;
+}
+
+void
+depset::hash::add_namespace_context (depset *dep, tree ns)
+{
+ depset *ns_dep = make_dependency (ns, depset::EK_NAMESPACE);
+ dep->deps.safe_push (ns_dep);
+
+ /* Mark it as special if imported so we don't walk connect when
+ SCCing. */
+ if (!dep->is_binding () && ns_dep->is_import ())
+ dep->set_special ();
+}
+
+struct add_binding_data
+{
+ tree ns;
+ bitmap partitions;
+ depset *binding;
+ depset::hash *hash;
+ bool met_namespace;
+};
+
+bool
+depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
+{
+ auto data = static_cast <add_binding_data *> (data_);
+
+ if (TREE_CODE (decl) != NAMESPACE_DECL || DECL_NAMESPACE_ALIAS (decl))
+ {
+ tree inner = decl;
+
+ if (TREE_CODE (inner) == CONST_DECL
+ && TREE_CODE (DECL_CONTEXT (inner)) == ENUMERAL_TYPE)
+ inner = TYPE_NAME (DECL_CONTEXT (inner));
+ else if (TREE_CODE (inner) == TEMPLATE_DECL)
+ inner = DECL_TEMPLATE_RESULT (inner);
+
+ if (!DECL_LANG_SPECIFIC (inner) || !DECL_MODULE_PURVIEW_P (inner))
+ /* Ignore global module fragment entities. */
+ return false;
+
+ if (VAR_OR_FUNCTION_DECL_P (inner)
+ && DECL_THIS_STATIC (inner))
+ {
+ if (!header_module_p ())
+ /* Ignore internal-linkage entitites. */
+ return false;
+ }
+
+ if ((TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == TYPE_DECL)
+ && DECL_TINFO_P (decl))
+ /* Ignore TINFO things. */
+ return false;
+
+ if (!(flags & WMB_Using) && CP_DECL_CONTEXT (decl) != data->ns)
+ {
+ /* A using that lost its wrapper or an unscoped enum
+ constant. */
+ flags = WMB_Flags (flags | WMB_Using);
+ if (DECL_MODULE_EXPORT_P (TREE_CODE (decl) == CONST_DECL
+ ? TYPE_NAME (TREE_TYPE (decl))
+ : STRIP_TEMPLATE (decl)))
+ flags = WMB_Flags (flags | WMB_Export);
+ }
+
+ if (!data->binding)
+ /* No binding to check. */;
+ else if (flags & WMB_Using)
+ {
+ /* Look in the binding to see if we already have this
+ using. */
+ for (unsigned ix = data->binding->deps.length (); --ix;)
+ {
+ depset *d = data->binding->deps[ix];
+ if (d->get_entity_kind () == EK_USING
+ && OVL_FUNCTION (d->get_entity ()) == decl)
+ {
+ if (!(flags & WMB_Hidden))
+ d->clear_hidden_binding ();
+ if (flags & WMB_Export)
+ OVL_EXPORT_P (d->get_entity ()) = true;
+ return false;
+ }
+ }
+ }
+ else if (flags & WMB_Dups)
+ {
+ /* Look in the binding to see if we already have this decl. */
+ for (unsigned ix = data->binding->deps.length (); --ix;)
+ {
+ depset *d = data->binding->deps[ix];
+ if (d->get_entity () == decl)
+ {
+ if (!(flags & WMB_Hidden))
+ d->clear_hidden_binding ();
+ return false;
+ }
+ }
+ }
+
+ /* We're adding something. */
+ if (!data->binding)
+ {
+ data->binding = make_binding (data->ns, DECL_NAME (decl));
+ data->hash->add_namespace_context (data->binding, data->ns);
+
+ depset **slot = data->hash->binding_slot (data->ns,
+ DECL_NAME (decl), true);
+ gcc_checking_assert (!*slot);
+ *slot = data->binding;
+ }
+
+ if (flags & WMB_Using)
+ {
+ decl = ovl_make (decl, NULL_TREE);
+ if (flags & WMB_Export)
+ OVL_EXPORT_P (decl) = true;
+ }
+
+ depset *dep = data->hash->make_dependency
+ (decl, flags & WMB_Using ? EK_USING : EK_FOR_BINDING);
+ if (flags & WMB_Hidden)
+ dep->set_hidden_binding ();
+ data->binding->deps.safe_push (dep);
+ /* Binding and contents are mutually dependent. */
+ dep->deps.safe_push (data->binding);
+
+ return true;
+ }
+ else if (DECL_NAME (decl) && !data->met_namespace)
+ {
+ /* Namespace, walk exactly once. */
+ gcc_checking_assert (TREE_PUBLIC (decl));
+ data->met_namespace = true;
+ if (data->hash->add_namespace_entities (decl, data->partitions)
+ || DECL_MODULE_EXPORT_P (decl))
+ {
+ data->hash->make_dependency (decl, depset::EK_NAMESPACE);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Recursively find all the namespace bindings of NS.
+ Add a depset for every binding that contains an export or
+ module-linkage entity. Add a defining depset for every such decl
+ that we need to write a definition. Such defining depsets depend
+ on the binding depset. Returns true if we contain something
+ explicitly exported. */
+
+bool
+depset::hash::add_namespace_entities (tree ns, bitmap partitions)
+{
+ dump () && dump ("Looking for writables in %N", ns);
+ dump.indent ();
+
+ unsigned count = 0;
+ add_binding_data data;
+ data.ns = ns;
+ data.partitions = partitions;
+ data.hash = this;
+
+ hash_table<named_decl_hash>::iterator end
+ (DECL_NAMESPACE_BINDINGS (ns)->end ());
+ for (hash_table<named_decl_hash>::iterator iter
+ (DECL_NAMESPACE_BINDINGS (ns)->begin ()); iter != end; ++iter)
+ {
+ data.binding = nullptr;
+ data.met_namespace = false;
+ if (walk_module_binding (*iter, partitions, add_binding_entity, &data))
+ count++;
+ }
+
+ if (count)
+ dump () && dump ("Found %u entries", count);
+ dump.outdent ();
+
+ return count != 0;
+}
+
+void
+depset::hash::add_partial_entities (vec<tree, va_gc> *partial_classes)
+{
+ for (unsigned ix = 0; ix != partial_classes->length (); ix++)
+ {
+ tree inner = (*partial_classes)[ix];
+
+ depset *dep = make_dependency (inner, depset::EK_DECL);
+
+ if (dep->get_entity_kind () == depset::EK_REDIRECT)
+ /* We should have recorded the template as a partial
+ specialization. */
+ gcc_checking_assert (dep->deps[0]->get_entity_kind ()
+ == depset::EK_PARTIAL);
+ else
+ /* It was an explicit specialization, not a partial one. */
+ gcc_checking_assert (dep->get_entity_kind ()
+ == depset::EK_SPECIALIZATION);
+ }
+}
+
+/* Add the members of imported classes that we defined in this TU.
+ This will also include lazily created implicit member function
+ declarations. (All others will be definitions.) */
+
+void
+depset::hash::add_class_entities (vec<tree, va_gc> *class_members)
+{
+ for (unsigned ix = 0; ix != class_members->length (); ix++)
+ {
+ tree defn = (*class_members)[ix];
+ depset *dep = make_dependency (defn, EK_INNER_DECL);
+
+ if (dep->get_entity_kind () == EK_REDIRECT)
+ dep = dep->deps[0];
+
+ /* Only non-instantiations need marking as members. */
+ if (dep->get_entity_kind () == EK_DECL)
+ dep->set_flag_bit <DB_IS_MEMBER_BIT> ();
+ }
+}
+
+/* We add the partial & explicit specializations, and the explicit
+ instantiations. */
+
+static void
+specialization_add (bool decl_p, spec_entry *entry, void *data_)
+{
+ vec<spec_entry *> *data = reinterpret_cast <vec<spec_entry *> *> (data_);
+
+ if (!decl_p)
+ {
+ /* We exclusively use decls to locate things. Make sure there's
+ no mismatch between the two specialization tables we keep.
+ pt.c optimizes instantiation lookup using a complicated
+ heuristic. We don't attempt to replicate that algorithm, but
+ observe its behaviour and reproduce it upon read back. */
+
+ gcc_checking_assert (DECL_ALIAS_TEMPLATE_P (entry->tmpl)
+ || TREE_CODE (entry->spec) == ENUMERAL_TYPE
+ || DECL_CLASS_TEMPLATE_P (entry->tmpl));
+
+ /* Only alias templates can appear in both tables (and
+ if they're in the type table they must also be in the decl table). */
+ gcc_checking_assert
+ (!match_mergeable_specialization (true, entry, false)
+ == (decl_p || !DECL_ALIAS_TEMPLATE_P (entry->tmpl)));
+ }
+ else if (VAR_OR_FUNCTION_DECL_P (entry->spec))
+ gcc_checking_assert (!DECL_LOCAL_DECL_P (entry->spec));
+
+ data->safe_push (entry);
+}
+
+/* Arbitrary stable comparison. */
+
+static int
+specialization_cmp (const void *a_, const void *b_)
+{
+ const spec_entry *ea = *reinterpret_cast<const spec_entry *const *> (a_);
+ const spec_entry *eb = *reinterpret_cast<const spec_entry *const *> (b_);
+
+ if (ea == eb)
+ return 0;
+
+ tree a = ea->spec;
+ tree b = eb->spec;
+ if (TYPE_P (a))
+ {
+ a = TYPE_NAME (a);
+ b = TYPE_NAME (b);
+ }
+
+ if (a == b)
+ /* This can happen with friend specializations. Just order by
+ entry address. See note in depset_cmp. */
+ return ea < eb ? -1 : +1;
+
+ return DECL_UID (a) < DECL_UID (b) ? -1 : +1;
+}
+
+/* We add all kinds of specialializations. Implicit specializations
+ should only streamed and walked if they are reachable from
+ elsewhere. Hence the UNREACHED flag. This is making the
+ assumption that it is cheaper to reinstantiate them on demand
+ elsewhere, rather than stream them in when we instantiate their
+ general template. Also, if we do stream them, we can only do that
+ if they are not internal (which they can become if they themselves
+ touch an internal entity?). */
+
+void
+depset::hash::add_specializations (bool decl_p)
+{
+ vec<spec_entry *> data;
+ data.create (100);
+ walk_specializations (decl_p, specialization_add, &data);
+ data.qsort (specialization_cmp);
+ while (data.length ())
+ {
+ spec_entry *entry = data.pop ();
+ tree spec = entry->spec;
+ int use_tpl = 0;
+ bool is_alias = false;
+ bool is_friend = false;
+
+ if (decl_p && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (entry->tmpl))
+ /* A friend of a template. This is keyed to the
+ instantiation. */
+ is_friend = true;
+
+ if (!decl_p && DECL_ALIAS_TEMPLATE_P (entry->tmpl))
+ {
+ spec = TYPE_NAME (spec);
+ is_alias = true;
+ }
+
+ if (decl_p || is_alias)
+ {
+ if (tree ti = DECL_TEMPLATE_INFO (spec))
+ {
+ tree tmpl = TI_TEMPLATE (ti);
+
+ use_tpl = DECL_USE_TEMPLATE (spec);
+ if (spec == DECL_TEMPLATE_RESULT (tmpl))
+ {
+ spec = tmpl;
+ gcc_checking_assert (DECL_USE_TEMPLATE (spec) == use_tpl);
+ }
+ else if (is_friend)
+ {
+ if (TI_TEMPLATE (ti) != entry->tmpl
+ || !template_args_equal (TI_ARGS (ti), entry->tmpl))
+ goto template_friend;
+ }
+ }
+ else
+ {
+ template_friend:;
+ gcc_checking_assert (is_friend);
+ /* This is a friend of a template class, but not the one
+ that generated entry->spec itself (i.e. it's an
+ equivalent clone). We do not need to record
+ this. */
+ continue;
+ }
+ }
+ else
+ {
+ if (TREE_CODE (spec) == ENUMERAL_TYPE)
+ {
+ tree ctx = DECL_CONTEXT (TYPE_NAME (spec));
+
+ if (TYPE_P (ctx))
+ use_tpl = CLASSTYPE_USE_TEMPLATE (ctx);
+ else
+ use_tpl = DECL_USE_TEMPLATE (ctx);
+ }
+ else
+ use_tpl = CLASSTYPE_USE_TEMPLATE (spec);
+
+ tree ti = TYPE_TEMPLATE_INFO (spec);
+ tree tmpl = TI_TEMPLATE (ti);
+
+ spec = TYPE_NAME (spec);
+ if (spec == DECL_TEMPLATE_RESULT (tmpl))
+ {
+ spec = tmpl;
+ use_tpl = DECL_USE_TEMPLATE (spec);
+ }
+ }
+
+ bool needs_reaching = false;
+ if (use_tpl == 1)
+ /* Implicit instantiations only walked if we reach them. */
+ needs_reaching = true;
+ else if (!DECL_LANG_SPECIFIC (spec)
+ || !DECL_MODULE_PURVIEW_P (spec))
+ /* Likewise, GMF explicit or partial specializations. */
+ needs_reaching = true;
+
+#if false && CHECKING_P
+ /* The instantiation isn't always on
+ DECL_TEMPLATE_INSTANTIATIONS, */
+ // FIXME: we probably need to remember this information?
+ /* Verify the specialization is on the
+ DECL_TEMPLATE_INSTANTIATIONS of the template. */
+ for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (entry->tmpl);
+ cons; cons = TREE_CHAIN (cons))
+ if (TREE_VALUE (cons) == entry->spec)
+ {
+ gcc_assert (entry->args == TREE_PURPOSE (cons));
+ goto have_spec;
+ }
+ gcc_unreachable ();
+ have_spec:;
+#endif
+
+ depset *dep = make_dependency (spec, depset::EK_SPECIALIZATION);
+ if (dep->is_special ())
+ {
+ /* An already located specialization, this must be the TYPE
+ corresponding to an alias_decl we found in the decl
+ table. */
+ spec_entry *other = reinterpret_cast <spec_entry *> (dep->deps[0]);
+ gcc_checking_assert (!decl_p && is_alias && !dep->is_type_spec ());
+ gcc_checking_assert (other->tmpl == entry->tmpl
+ && template_args_equal (other->args, entry->args)
+ && TREE_TYPE (other->spec) == entry->spec);
+ dep->set_flag_bit<DB_ALIAS_SPEC_BIT> ();
+ }
+ else
+ {
+ gcc_checking_assert (decl_p || !is_alias);
+ if (dep->get_entity_kind () == depset::EK_REDIRECT)
+ dep = dep->deps[0];
+ else if (dep->get_entity_kind () == depset::EK_SPECIALIZATION)
+ {
+ dep->set_special ();
+ dep->deps.safe_push (reinterpret_cast<depset *> (entry));
+ if (!decl_p)
+ dep->set_flag_bit<DB_TYPE_SPEC_BIT> ();
+ }
+
+ if (needs_reaching)
+ dep->set_flag_bit<DB_UNREACHED_BIT> ();
+ if (is_friend)
+ dep->set_flag_bit<DB_FRIEND_SPEC_BIT> ();
+ }
+ }
+ data.release ();
+}
+
+/* Add a depset into the mergeable hash. */
+
+void
+depset::hash::add_mergeable (depset *mergeable)
+{
+ gcc_checking_assert (is_key_order ());
+ entity_kind ek = mergeable->get_entity_kind ();
+ tree decl = mergeable->get_entity ();
+ gcc_checking_assert (ek < EK_DIRECT_HWM);
+
+ depset **slot = entity_slot (decl, true);
+ gcc_checking_assert (!*slot);
+ depset *dep = make_entity (decl, ek);
+ *slot = dep;
+
+ worklist.safe_push (dep);
+
+ /* So we can locate the mergeable depset this depset refers to,
+ mark the first dep. */
+ dep->set_special ();
+ dep->deps.safe_push (mergeable);
+}
+
+/* Iteratively find dependencies. During the walk we may find more
+ entries on the same binding that need walking. */
+
+void
+depset::hash::find_dependencies ()
+{
+ trees_out walker (NULL, NULL, *this);
+ vec<depset *> unreached;
+ unreached.create (worklist.length ());
+
+ for (;;)
+ {
+ reached_unreached = false;
+ while (worklist.length ())
+ {
+ depset *item = worklist.pop ();
+
+ gcc_checking_assert (!item->is_binding ());
+ if (item->is_unreached ())
+ unreached.quick_push (item);
+ else
+ {
+ current = item;
+ tree decl = current->get_entity ();
+ dump (is_key_order () ? dumper::MERGE : dumper::DEPEND)
+ && dump ("Dependencies of %s %C:%N",
+ is_key_order () ? "key-order"
+ : current->entity_kind_name (), TREE_CODE (decl), decl);
+ dump.indent ();
+ walker.begin ();
+ if (current->get_entity_kind () == EK_USING)
+ walker.tree_node (OVL_FUNCTION (decl));
+ else if (TREE_VISITED (decl))
+ /* A global tree. */;
+ else if (TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl))
+ add_namespace_context (current, CP_DECL_CONTEXT (decl));
+ else
+ {
+ walker.mark_declaration (decl, current->has_defn ());
+
+ // FIXME: Perhaps p1815 makes this redundant? Or at
+ // least simplifies it. Voldemort types are only
+ // ever emissable when containing (inline) function
+ // definition is emitted?
+ /* Turn the Sneakoscope on when depending the decl. */
+ sneakoscope = true;
+ walker.decl_value (decl, current);
+ sneakoscope = false;
+ if (current->has_defn ())
+ walker.write_definition (decl);
+ }
+ walker.end ();
+
+ if (!walker.is_key_order ()
+ && TREE_CODE (decl) == TEMPLATE_DECL
+ && !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
+ /* Mark all the explicit & partial specializations as
+ reachable. */
+ for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl);
+ cons; cons = TREE_CHAIN (cons))
+ {
+ tree spec = TREE_VALUE (cons);
+ if (TYPE_P (spec))
+ spec = TYPE_NAME (spec);
+ int use_tpl;
+ node_template_info (spec, use_tpl);
+ if (use_tpl & 2)
+ {
+ depset *spec_dep = find_dependency (spec);
+ if (spec_dep->get_entity_kind () == EK_REDIRECT)
+ spec_dep = spec_dep->deps[0];
+ if (spec_dep->is_unreached ())
+ {
+ reached_unreached = true;
+ spec_dep->clear_flag_bit<DB_UNREACHED_BIT> ();
+ dump (dumper::DEPEND)
+ && dump ("Reaching unreached specialization"
+ " %C:%N", TREE_CODE (spec), spec);
+ }
+ }
+ }
+
+ dump.outdent ();
+ current = NULL;
+ }
+ }
+
+ if (!reached_unreached)
+ break;
+
+ /* It's possible the we reached the unreached before we
+ processed it in the above loop, so we'll be doing this an
+ extra time. However, to avoid that we have to do some
+ bit shuffling that also involves a scan of the list.
+ Swings & roundabouts I guess. */
+ std::swap (worklist, unreached);
+ }
+
+ unreached.release ();
+}
+
+/* Compare two entries of a single binding. TYPE_DECL before
+ non-exported before exported. */
+
+static int
+binding_cmp (const void *a_, const void *b_)
+{
+ depset *a = *(depset *const *)a_;
+ depset *b = *(depset *const *)b_;
+
+ tree a_ent = a->get_entity ();
+ tree b_ent = b->get_entity ();
+ gcc_checking_assert (a_ent != b_ent
+ && !a->is_binding ()
+ && !b->is_binding ());
+
+ /* Implicit typedefs come first. */
+ bool a_implicit = DECL_IMPLICIT_TYPEDEF_P (a_ent);
+ bool b_implicit = DECL_IMPLICIT_TYPEDEF_P (b_ent);
+ if (a_implicit || b_implicit)
+ {
+ /* A binding with two implicit type decls? That's unpossible! */
+ gcc_checking_assert (!(a_implicit && b_implicit));
+ return a_implicit ? -1 : +1; /* Implicit first. */
+ }
+
+ /* Hidden before non-hidden. */
+ bool a_hidden = a->is_hidden ();
+ bool b_hidden = b->is_hidden ();
+ if (a_hidden != b_hidden)
+ return a_hidden ? -1 : +1;
+
+ bool a_using = a->get_entity_kind () == depset::EK_USING;
+ bool a_export;
+ if (a_using)
+ {
+ a_export = OVL_EXPORT_P (a_ent);
+ a_ent = OVL_FUNCTION (a_ent);
+ }
+ else
+ a_export = DECL_MODULE_EXPORT_P (TREE_CODE (a_ent) == CONST_DECL
+ ? TYPE_NAME (TREE_TYPE (a_ent))
+ : STRIP_TEMPLATE (a_ent));
+
+ bool b_using = b->get_entity_kind () == depset::EK_USING;
+ bool b_export;
+ if (b_using)
+ {
+ b_export = OVL_EXPORT_P (b_ent);
+ b_ent = OVL_FUNCTION (b_ent);
+ }
+ else
+ b_export = DECL_MODULE_EXPORT_P (TREE_CODE (b_ent) == CONST_DECL
+ ? TYPE_NAME (TREE_TYPE (b_ent))
+ : STRIP_TEMPLATE (b_ent));
+
+ /* Non-exports before exports. */
+ if (a_export != b_export)
+ return a_export ? +1 : -1;
+
+ /* At this point we don't care, but want a stable sort. */
+
+ if (a_using != b_using)
+ /* using first. */
+ return a_using? -1 : +1;
+
+ return DECL_UID (a_ent) < DECL_UID (b_ent) ? -1 : +1;
+}
+
+/* Sort the bindings, issue errors about bad internal refs. */
+
+bool
+depset::hash::finalize_dependencies ()
+{
+ bool ok = true;
+ depset::hash::iterator end (this->end ());
+ for (depset::hash::iterator iter (begin ()); iter != end; ++iter)
+ {
+ depset *dep = *iter;
+ if (dep->is_binding ())
+ {
+ /* Keep the containing namespace dep first. */
+ gcc_checking_assert (dep->deps.length () > 1
+ && (dep->deps[0]->get_entity_kind ()
+ == EK_NAMESPACE)
+ && (dep->deps[0]->get_entity ()
+ == dep->get_entity ()));
+ if (dep->deps.length () > 2)
+ gcc_qsort (&dep->deps[1], dep->deps.length () - 1,
+ sizeof (dep->deps[1]), binding_cmp);
+ }
+ else if (dep->refs_internal ())
+ {
+ for (unsigned ix = dep->deps.length (); ix--;)
+ {
+ depset *rdep = dep->deps[ix];
+ if (rdep->is_internal ())
+ {
+ // FIXME:QOI Better location information? We're
+ // losing, so it doesn't matter about efficiency
+ tree decl = dep->get_entity ();
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%q#D references internal linkage entity %q#D",
+ decl, rdep->get_entity ());
+ break;
+ }
+ }
+ ok = false;
+ }
+ }
+
+ return ok;
+}
+
+/* Core of TARJAN's algorithm to find Strongly Connected Components
+ within a graph. See https://en.wikipedia.org/wiki/
+ Tarjan%27s_strongly_connected_components_algorithm for details.
+
+ We use depset::section as lowlink. Completed nodes have
+ depset::cluster containing the cluster number, with the top
+ bit set.
+
+ A useful property is that the output vector is a reverse
+ topological sort of the resulting DAG. In our case that means
+ dependent SCCs are found before their dependers. We make use of
+ that property. */
+
+void
+depset::tarjan::connect (depset *v)
+{
+ gcc_checking_assert (v->is_binding ()
+ || !(v->is_unreached () || v->is_import ()));
+
+ v->cluster = v->section = ++index;
+ stack.safe_push (v);
+
+ /* Walk all our dependencies, ignore a first marked slot */
+ for (unsigned ix = v->is_special (); ix != v->deps.length (); ix++)
+ {
+ depset *dep = v->deps[ix];
+
+ if (dep->is_binding () || !dep->is_import ())
+ {
+ unsigned lwm = dep->cluster;
+
+ if (!dep->cluster)
+ {
+ /* A new node. Connect it. */
+ connect (dep);
+ lwm = dep->section;
+ }
+
+ if (dep->section && v->section > lwm)
+ v->section = lwm;
+ }
+ }
+
+ if (v->section == v->cluster)
+ {
+ /* Root of a new SCC. Push all the members onto the result list. */
+ unsigned num = v->cluster;
+ depset *p;
+ do
+ {
+ p = stack.pop ();
+ p->cluster = num;
+ p->section = 0;
+ result.quick_push (p);
+ }
+ while (p != v);
+ }
+}
+
+/* Compare two depsets. The specific ordering is unimportant, we're
+ just trying to get consistency. */
+
+static int
+depset_cmp (const void *a_, const void *b_)
+{
+ depset *a = *(depset *const *)a_;
+ depset *b = *(depset *const *)b_;
+
+ depset::entity_kind a_kind = a->get_entity_kind ();
+ depset::entity_kind b_kind = b->get_entity_kind ();
+
+ if (a_kind != b_kind)
+ /* Different entity kinds, order by that. */
+ return a_kind < b_kind ? -1 : +1;
+
+ tree a_decl = a->get_entity ();
+ tree b_decl = b->get_entity ();
+ if (a_kind == depset::EK_USING)
+ {
+ /* If one is a using, the other must be too. */
+ a_decl = OVL_FUNCTION (a_decl);
+ b_decl = OVL_FUNCTION (b_decl);
+ }
+
+ if (a_decl != b_decl)
+ /* Different entities, order by their UID. */
+ return DECL_UID (a_decl) < DECL_UID (b_decl) ? -1 : +1;
+
+ if (a_kind == depset::EK_BINDING)
+ {
+ /* Both are bindings. Order by identifier hash. */
+ gcc_checking_assert (a->get_name () != b->get_name ());
+ return (IDENTIFIER_HASH_VALUE (a->get_name ())
+ < IDENTIFIER_HASH_VALUE (b->get_name ())
+ ? -1 : +1);
+ }
+
+ /* They are the same decl. This can happen with two using decls
+ pointing to the same target. The best we can aim for is
+ consistently telling qsort how to order them. Hopefully we'll
+ never have to debug a case that depends on this. Oh, who am I
+ kidding? Good luck. */
+ gcc_checking_assert (a_kind == depset::EK_USING);
+
+ /* Order by depset address. Not the best, but it is something. */
+ return a < b ? -1 : +1;
+}
+
+/* Sort the clusters in SCC such that those that depend on one another
+ are placed later. */
+
+// FIXME: I am not convinced this is needed and, if needed,
+// sufficient. We emit the decls in this order but that emission
+// could walk into later decls (from the body of the decl, or default
+// arg-like things). Why doesn't that walk do the right thing? And
+// if it DTRT why do we need to sort here -- won't things naturally
+// work? I think part of the issue is that when we're going to refer
+// to an entity by name, and that entity is in the same cluster as us,
+// we need to actually walk that entity, if we've not already walked
+// it.
+static void
+sort_cluster (depset::hash *original, depset *scc[], unsigned size)
+{
+ depset::hash table (size, original);
+
+ dump.indent ();
+
+ /* Place bindings last, usings before that. It's not strictly
+ necessary, but it does make things neater. Says Mr OCD. */
+ unsigned bind_lwm = size;
+ unsigned use_lwm = size;
+ for (unsigned ix = 0; ix != use_lwm;)
+ {
+ depset *dep = scc[ix];
+ switch (dep->get_entity_kind ())
+ {
+ case depset::EK_BINDING:
+ /* Move to end. No increment. Notice this could be moving
+ a using decl, which we'll then move again. */
+ if (--bind_lwm != ix)
+ {
+ scc[ix] = scc[bind_lwm];
+ scc[bind_lwm] = dep;
+ }
+ if (use_lwm > bind_lwm)
+ {
+ use_lwm--;
+ break;
+ }
+ /* We must have copied a using, so move it too. */
+ dep = scc[ix];
+ gcc_checking_assert (dep->get_entity_kind () == depset::EK_USING);
+ /* FALLTHROUGH */
+
+ case depset::EK_USING:
+ if (--use_lwm != ix)
+ {
+ scc[ix] = scc[use_lwm];
+ scc[use_lwm] = dep;
+ }
+ break;
+
+ case depset::EK_DECL:
+ case depset::EK_SPECIALIZATION:
+ case depset::EK_PARTIAL:
+ table.add_mergeable (dep);
+ ix++;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ gcc_checking_assert (use_lwm <= bind_lwm);
+ dump (dumper::MERGE) && dump ("Ordering %u/%u depsets", use_lwm, size);
+
+ table.find_dependencies ();
+
+ vec<depset *> order = table.connect ();
+ gcc_checking_assert (order.length () == use_lwm);
+
+ /* Now rewrite entries [0,lwm), in the dependency order we
+ discovered. Usually each entity is in its own cluster. Rarely,
+ we can get multi-entity clusters, in which case all but one must
+ only be reached from within the cluster. This happens for
+ something like:
+
+ template<typename T>
+ auto Foo (const T &arg) -> TPL<decltype (arg)>;
+
+ The instantiation of TPL will be in the specialization table, and
+ refer to Foo via arg. But we can only get to that specialization
+ from Foo's declaration, so we only need to treat Foo as mergable
+ (We'll do structural comparison of TPL<decltype (arg)>).
+
+ Finding the single cluster entry dep is very tricky and
+ expensive. Let's just not do that. It's harmless in this case
+ anyway. */
+ unsigned pos = 0;
+ unsigned cluster = ~0u;
+ for (unsigned ix = 0; ix != order.length (); ix++)
+ {
+ gcc_checking_assert (order[ix]->is_special ());
+ depset *dep = order[ix]->deps[0];
+ scc[pos++] = dep;
+ dump (dumper::MERGE)
+ && dump ("Mergeable %u is %N%s", ix, dep->get_entity (),
+ order[ix]->cluster == cluster ? " (tight)" : "");
+ cluster = order[ix]->cluster;
+ }
+
+ gcc_checking_assert (pos == use_lwm);
+
+ order.release ();
+ dump (dumper::MERGE) && dump ("Ordered %u keys", pos);
+ dump.outdent ();
+}
+
+/* Reduce graph to SCCS clusters. SCCS will be populated with the
+ depsets in dependency order. Each depset's CLUSTER field contains
+ its cluster number. Each SCC has a unique cluster number, and are
+ contiguous in SCCS. Cluster numbers are otherwise arbitrary. */
+
+vec<depset *>
+depset::hash::connect ()
+{
+ tarjan connector (size ());
+ vec<depset *> deps;
+ deps.create (size ());
+ iterator end (this->end ());
+ for (iterator iter (begin ()); iter != end; ++iter)
+ {
+ depset *item = *iter;
+
+ entity_kind kind = item->get_entity_kind ();
+ if (kind == EK_BINDING
+ || !(kind == EK_REDIRECT
+ || item->is_unreached ()
+ || item->is_import ()))
+ deps.quick_push (item);
+ }
+
+ /* Iteration over the hash table is an unspecified ordering. While
+ that has advantages, it causes 2 problems. Firstly repeatable
+ builds are tricky. Secondly creating testcases that check
+ dependencies are correct by making sure a bad ordering would
+ happen if that was wrong. */
+ deps.qsort (depset_cmp);
+
+ while (deps.length ())
+ {
+ depset *v = deps.pop ();
+ dump (dumper::CLUSTER) &&
+ (v->is_binding ()
+ ? dump ("Connecting binding %P", v->get_entity (), v->get_name ())
+ : dump ("Connecting %s %s %C:%N",
+ is_key_order () ? "key-order"
+ : !v->has_defn () ? "declaration" : "definition",
+ v->entity_kind_name (), TREE_CODE (v->get_entity ()),
+ v->get_entity ()));
+ if (!v->cluster)
+ connector.connect (v);
+ }
+
+ deps.release ();
+ return connector.result;
+}
+
+/* Load the entities referred to by this pendset. */
+
+static bool
+pendset_lazy_load (pendset *pendings, bool specializations_p)
+{
+ bool ok = true;
+
+ for (unsigned ix = 0; ok && ix != pendings->num; ix++)
+ {
+ unsigned index = pendings->values[ix];
+ if (index & ~(~0u >> 1))
+ {
+ /* An indirection. */
+ if (specializations_p)
+ index = ~index;
+ pendset *other = pending_table->get (index, true);
+ if (!pendset_lazy_load (other, specializations_p))
+ ok = false;
+ }
+ else
+ {
+ module_state *module = import_entity_module (index);
+ binding_slot *slot = &(*entity_ary)[index];
+ if (!slot->is_lazy ())
+ dump () && dump ("Specialiation %M[%u] already loaded",
+ module, index - module->entity_lwm);
+ else if (!module->lazy_load (index - module->entity_lwm, slot))
+ ok = false;
+ }
+ }
+
+ /* We own set, so delete it now. */
+ delete pendings;
+
+ return ok;
+}
+
+/* Initialize location spans. */
+
+void
+loc_spans::init (const line_maps *lmaps, const line_map_ordinary *map)
+{
+ gcc_checking_assert (!init_p ());
+ spans = new vec<span> ();
+ spans->reserve (20);
+
+ span interval;
+ interval.ordinary.first = 0;
+ interval.macro.second = MAX_LOCATION_T + 1;
+ interval.ordinary_delta = interval.macro_delta = 0;
+
+ /* A span for reserved fixed locs. */
+ interval.ordinary.second
+ = MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (line_table, 0));
+ interval.macro.first = interval.macro.second;
+ dump (dumper::LOCATION)
+ && dump ("Fixed span %u ordinary:[%u,%u) macro:[%u,%u)", spans->length (),
+ interval.ordinary.first, interval.ordinary.second,
+ interval.macro.first, interval.macro.second);
+ spans->quick_push (interval);
+
+ /* A span for command line & forced headers. */
+ interval.ordinary.first = interval.ordinary.second;
+ interval.macro.second = interval.macro.first;
+ if (map)
+ {
+ interval.ordinary.second = map->start_location;
+ interval.macro.first = LINEMAPS_MACRO_LOWEST_LOCATION (lmaps);
+ }
+ dump (dumper::LOCATION)
+ && dump ("Pre span %u ordinary:[%u,%u) macro:[%u,%u)", spans->length (),
+ interval.ordinary.first, interval.ordinary.second,
+ interval.macro.first, interval.macro.second);
+ spans->quick_push (interval);
+
+ /* Start an interval for the main file. */
+ interval.ordinary.first = interval.ordinary.second;
+ interval.macro.second = interval.macro.first;
+ dump (dumper::LOCATION)
+ && dump ("Main span %u ordinary:[%u,*) macro:[*,%u)", spans->length (),
+ interval.ordinary.first, interval.macro.second);
+ spans->quick_push (interval);
+}
+
+/* Reopen the span, if we want the about-to-be-inserted set of maps to
+ be propagated in our own location table. I.e. we are the primary
+ interface and we're importing a partition. */
+
+bool
+loc_spans::maybe_propagate (module_state *import,
+ location_t loc = UNKNOWN_LOCATION)
+{
+ bool opened = (module_interface_p () && !module_partition_p ()
+ && import->is_partition ());
+ if (opened)
+ open (loc);
+ return opened;
+}
+
+/* Open a new linemap interval. The just-created ordinary map is the
+ first map of the interval. */
+
+void
+loc_spans::open (location_t hwm = UNKNOWN_LOCATION)
+{
+ if (hwm == UNKNOWN_LOCATION)
+ hwm = MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (line_table));
+
+ span interval;
+ interval.ordinary.first = interval.ordinary.second = hwm;
+ interval.macro.first = interval.macro.second
+ = LINEMAPS_MACRO_LOWEST_LOCATION (line_table);
+ interval.ordinary_delta = interval.macro_delta = 0;
+ dump (dumper::LOCATION)
+ && dump ("Opening span %u ordinary:[%u,... macro:...,%u)",
+ spans->length (), interval.ordinary.first,
+ interval.macro.second);
+ spans->safe_push (interval);
+}
+
+/* Close out the current linemap interval. The last maps are within
+ the interval. */
+
+void
+loc_spans::close ()
+{
+ span &interval = spans->last ();
+
+ interval.ordinary.second
+ = ((line_table->highest_location + (1 << line_table->default_range_bits))
+ & ~((1u << line_table->default_range_bits) - 1));
+ interval.macro.first = LINEMAPS_MACRO_LOWEST_LOCATION (line_table);
+ dump (dumper::LOCATION)
+ && dump ("Closing span %u ordinary:[%u,%u) macro:[%u,%u)",
+ spans->length () - 1,
+ interval.ordinary.first,interval.ordinary.second,
+ interval.macro.first, interval.macro.second);
+}
+
+/* Given an ordinary location LOC, return the lmap_interval it resides
+ in. NULL if it is not in an interval. */
+
+const loc_spans::span *
+loc_spans::ordinary (location_t loc)
+{
+ unsigned len = spans->length ();
+ unsigned pos = 0;
+ while (len)
+ {
+ unsigned half = len / 2;
+ const span &probe = (*spans)[pos + half];
+ if (loc < probe.ordinary.first)
+ len = half;
+ else if (loc < probe.ordinary.second)
+ return &probe;
+ else
+ {
+ pos += half + 1;
+ len = len - (half + 1);
+ }
+ }
+ return NULL;
+}
+
+/* Likewise, given a macro location LOC, return the lmap interval it
+ resides in. */
+
+const loc_spans::span *
+loc_spans::macro (location_t loc)
+{
+ unsigned len = spans->length ();
+ unsigned pos = 0;
+ while (len)
+ {
+ unsigned half = len / 2;
+ const span &probe = (*spans)[pos + half];
+ if (loc >= probe.macro.second)
+ len = half;
+ else if (loc >= probe.macro.first)
+ return &probe;
+ else
+ {
+ pos += half + 1;
+ len = len - (half + 1);
+ }
+ }
+ return NULL;
+}
+
+/* Return the ordinary location closest to FROM. */
+
+static location_t
+ordinary_loc_of (line_maps *lmaps, location_t from)
+{
+ while (!IS_ORDINARY_LOC (from))
+ {
+ if (IS_ADHOC_LOC (from))
+ from = get_location_from_adhoc_loc (lmaps, from);
+ if (IS_MACRO_LOC (from))
+ {
+ /* Find the ordinary location nearest FROM. */
+ const line_map *map = linemap_lookup (lmaps, from);
+ const line_map_macro *mac_map = linemap_check_macro (map);
+ from = MACRO_MAP_EXPANSION_POINT_LOCATION (mac_map);
+ }
+ }
+ return from;
+}
+
+static module_state **
+get_module_slot (tree name, module_state *parent, bool partition, bool insert)
+{
+ module_state_hash::compare_type ct (name, uintptr_t (parent) | partition);
+ hashval_t hv = module_state_hash::hash (ct);
+
+ return modules_hash->find_slot_with_hash (ct, hv, insert ? INSERT : NO_INSERT);
+}
+
+static module_state *
+get_primary (module_state *parent)
+{
+ while (parent->is_partition ())
+ parent = parent->parent;
+
+ if (!parent->name)
+ // Implementation unit has null name
+ parent = parent->parent;
+
+ return parent;
+}
+
+/* Find or create module NAME & PARENT in the hash table. */
+
+module_state *
+get_module (tree name, module_state *parent, bool partition)
+{
+ if (partition)
+ {
+ if (!parent)
+ parent = get_primary ((*modules)[0]);
+
+ if (!parent->is_partition () && !parent->flatname)
+ parent->set_flatname ();
+ }
+
+ module_state **slot = get_module_slot (name, parent, partition, true);
+ module_state *state = *slot;
+ if (!state)
+ {
+ state = (new (ggc_alloc<module_state> ())
+ module_state (name, parent, partition));
+ *slot = state;
+ }
+ return state;
+}
+
+/* Process string name PTR into a module_state. */
+
+static module_state *
+get_module (const char *ptr)
+{
+ if (ptr[0] == '.' ? IS_DIR_SEPARATOR (ptr[1]) : IS_ABSOLUTE_PATH (ptr))
+ /* A header name. */
+ return get_module (build_string (strlen (ptr), ptr));
+
+ bool partition = false;
+ module_state *mod = NULL;
+
+ for (const char *probe = ptr;; probe++)
+ if (!*probe || *probe == '.' || *probe == ':')
+ {
+ if (probe == ptr)
+ return NULL;
+
+ mod = get_module (get_identifier_with_length (ptr, probe - ptr),
+ mod, partition);
+ ptr = probe;
+ if (*ptr == ':')
+ {
+ if (partition)
+ return NULL;
+ partition = true;
+ }
+
+ if (!*ptr++)
+ break;
+ }
+ else if (!(ISALPHA (*probe) || *probe == '_'
+ || (probe != ptr && ISDIGIT (*probe))))
+ return NULL;
+
+ return mod;
+}
+
+/* Create a new mapper connecting to OPTION. */
+
+module_client *
+make_mapper (location_t loc)
+{
+ timevar_start (TV_MODULE_MAPPER);
+ const char *option = module_mapper_name;
+ if (!option)
+ option = getenv ("CXX_MODULE_MAPPER");
+
+ mapper = module_client::open_module_client
+ (loc, option, &set_cmi_repo,
+ (save_decoded_options[0].opt_index == OPT_SPECIAL_program_name)
+ && save_decoded_options[0].arg != progname
+ ? save_decoded_options[0].arg : nullptr);
+
+ timevar_stop (TV_MODULE_MAPPER);
+
+ return mapper;
+}
+
+/* If THIS is the current purview, issue an import error and return false. */
+
+bool
+module_state::check_not_purview (location_t from)
+{
+ module_state *imp = (*modules)[0];
+ if (imp && !imp->name)
+ imp = imp->parent;
+ if (imp == this)
+ {
+ /* Cannot import the current module. */
+ error_at (from, "cannot import module in its own purview");
+ inform (loc, "module %qs declared here", get_flatname ());
+ return false;
+ }
+ return true;
+}
+
+/* Module name substitutions. */
+static vec<module_state *,va_heap> substs;
+
+void
+module_state::mangle (bool include_partition)
+{
+ if (subst)
+ mangle_module_substitution (subst - 1);
+ else
+ {
+ if (parent)
+ parent->mangle (include_partition);
+ if (include_partition || !is_partition ())
+ {
+ char p = 0;
+ // Partitions are significant for global initializer functions
+ if (is_partition () && !parent->is_partition ())
+ p = 'P';
+ substs.safe_push (this);
+ subst = substs.length ();
+ mangle_identifier (p, name);
+ }
+ }
+}
+
+void
+mangle_module (int mod, bool include_partition)
+{
+ module_state *imp = (*modules)[mod];
+
+ if (!imp->name)
+ /* Set when importing the primary module interface. */
+ imp = imp->parent;
+
+ imp->mangle (include_partition);
+}
+
+/* Clean up substitutions. */
+void
+mangle_module_fini ()
+{
+ while (substs.length ())
+ substs.pop ()->subst = 0;
+}
+
+/* Announce WHAT about the module. */
+
+void
+module_state::announce (const char *what) const
+{
+ if (noisy_p ())
+ {
+ fprintf (stderr, " %s:%s", what, get_flatname ());
+ fflush (stderr);
+ }
+}
+
+/* A human-readable README section. The contents of this section to
+ not contribute to the CRC, so the contents can change per
+ compilation. That allows us to embed CWD, hostname, build time and
+ what not. It is a STRTAB that may be extracted with:
+ readelf -pgnu.c++.README $(module).gcm */
+
+void
+module_state::write_readme (elf_out *to, cpp_reader *reader,
+ const char *dialect, unsigned extensions)
+{
+ bytes_out readme (to);
+
+ readme.begin (false);
+
+ readme.printf ("GNU C++ %smodule%s%s",
+ is_header () ? "header " : is_partition () ? "" : "primary ",
+ is_header () ? ""
+ : is_interface () ? " interface" : " implementation",
+ is_partition () ? " partition" : "");
+
+ /* Compiler's version. */
+ readme.printf ("compiler: %s", version_string);
+
+ /* Module format version. */
+ verstr_t string;
+ version2string (MODULE_VERSION, string);
+ readme.printf ("version: %s", string);
+
+ /* Module information. */
+ readme.printf ("module: %s", get_flatname ());
+ readme.printf ("source: %s", main_input_filename);
+ readme.printf ("dialect: %s", dialect);
+ if (extensions)
+ readme.printf ("extensions: %s",
+ extensions & SE_OPENMP ? "-fopenmp" : "");
+
+ /* The following fields could be expected to change between
+ otherwise identical compilations. Consider a distributed build
+ system. We should have a way of overriding that. */
+ if (char *cwd = getcwd (NULL, 0))
+ {
+ readme.printf ("cwd: %s", cwd);
+ free (cwd);
+ }
+ readme.printf ("repository: %s", cmi_repo ? cmi_repo : ".");
+#if NETWORKING
+ {
+ char hostname[64];
+ if (!gethostname (hostname, sizeof (hostname)))
+ readme.printf ("host: %s", hostname);
+ }
+#endif
+ {
+ /* This of course will change! */
+ time_t stampy;
+ auto kind = cpp_get_date (reader, &stampy);
+ if (kind != CPP_time_kind::UNKNOWN)
+ {
+ struct tm *time;
+
+ time = gmtime (&stampy);
+ readme.print_time ("build", time, "UTC");
+
+ if (kind == CPP_time_kind::DYNAMIC)
+ {
+ time = localtime (&stampy);
+ readme.print_time ("local", time,
+#if defined (__USE_MISC) || defined (__USE_BSD) /* Is there a better way? */
+ time->tm_zone
+#else
+ ""
+#endif
+ );
+ }
+ }
+ }
+
+ /* Its direct imports. */
+ for (unsigned ix = 1; ix < modules->length (); ix++)
+ {
+ module_state *state = (*modules)[ix];
+
+ if (state->is_direct ())
+ readme.printf ("%s: %s %s", state->exported_p ? "export" : "import",
+ state->get_flatname (), state->filename);
+ }
+
+ readme.end (to, to->name (MOD_SNAME_PFX ".README"), NULL);
+}
+
+/* Sort environment var names in reverse order. */
+
+static int
+env_var_cmp (const void *a_, const void *b_)
+{
+ const unsigned char *a = *(const unsigned char *const *)a_;
+ const unsigned char *b = *(const unsigned char *const *)b_;
+
+ for (unsigned ix = 0; ; ix++)
+ {
+ bool a_end = !a[ix] || a[ix] == '=';
+ if (a[ix] == b[ix])
+ {
+ if (a_end)
+ break;
+ }
+ else
+ {
+ bool b_end = !b[ix] || b[ix] == '=';
+
+ if (!a_end && !b_end)
+ return a[ix] < b[ix] ? +1 : -1;
+ if (a_end && b_end)
+ break;
+ return a_end ? +1 : -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Write the environment. It is a STRTAB that may be extracted with:
+ readelf -pgnu.c++.ENV $(module).gcm */
+
+void
+module_state::write_env (elf_out *to)
+{
+ vec<const char *> vars;
+ vars.create (20);
+
+ extern char **environ;
+ while (const char *var = environ[vars.length ()])
+ vars.safe_push (var);
+ vars.qsort (env_var_cmp);
+
+ bytes_out env (to);
+ env.begin (false);
+ while (vars.length ())
+ env.printf ("%s", vars.pop ());
+ env.end (to, to->name (MOD_SNAME_PFX ".ENV"), NULL);
+
+ vars.release ();
+}
+
+/* Write the direct or indirect imports.
+ u:N
+ {
+ u:index
+ s:name
+ u32:crc
+ s:filename (direct)
+ u:exported (direct)
+ } imports[N]
+ */
+
+void
+module_state::write_imports (bytes_out &sec, bool direct)
+{
+ unsigned count = 0;
+
+ for (unsigned ix = 1; ix < modules->length (); ix++)
+ {
+ module_state *imp = (*modules)[ix];
+
+ if (imp->remap && imp->is_direct () == direct)
+ count++;
+ }
+
+ gcc_assert (!direct || count);
+
+ sec.u (count);
+ for (unsigned ix = 1; ix < modules->length (); ix++)
+ {
+ module_state *imp = (*modules)[ix];
+
+ if (imp->remap && imp->is_direct () == direct)
+ {
+ dump () && dump ("Writing %simport:%u->%u %M (crc=%x)",
+ !direct ? "indirect "
+ : imp->exported_p ? "exported " : "",
+ ix, imp->remap, imp, imp->crc);
+ sec.u (imp->remap);
+ sec.str (imp->get_flatname ());
+ sec.u32 (imp->crc);
+ if (direct)
+ {
+ write_location (sec, imp->imported_from ());
+ sec.str (imp->filename);
+ int exportedness = 0;
+ if (imp->exported_p)
+ exportedness = +1;
+ else if (!imp->is_purview_direct ())
+ exportedness = -1;
+ sec.i (exportedness);
+ }
+ }
+ }
+}
+
+/* READER, LMAPS != NULL == direct imports,
+ == NUL == indirect imports. */
+
+unsigned
+module_state::read_imports (bytes_in &sec, cpp_reader *reader, line_maps *lmaps)
+{
+ unsigned count = sec.u ();
+ unsigned loaded = 0;
+
+ while (count--)
+ {
+ unsigned ix = sec.u ();
+ if (ix >= slurp->remap->length () || !ix || (*slurp->remap)[ix])
+ {
+ sec.set_overrun ();
+ break;
+ }
+
+ const char *name = sec.str (NULL);
+ module_state *imp = get_module (name);
+ unsigned crc = sec.u32 ();
+ int exportedness = 0;
+
+ /* If the import is a partition, it must be the same primary
+ module as this TU. */
+ if (imp && imp->is_partition () &&
+ (!named_module_p ()
+ || (get_primary ((*modules)[0]) != get_primary (imp))))
+ imp = NULL;
+
+ if (!imp)
+ sec.set_overrun ();
+ if (sec.get_overrun ())
+ break;
+
+ if (lmaps)
+ {
+ /* A direct import, maybe load it. */
+ location_t floc = read_location (sec);
+ const char *fname = sec.str (NULL);
+ exportedness = sec.i ();
+
+ if (sec.get_overrun ())
+ break;
+
+ if (!imp->check_not_purview (loc))
+ continue;
+
+ if (imp->loadedness == ML_NONE)
+ {
+ imp->loc = floc;
+ imp->crc = crc;
+ if (!imp->get_flatname ())
+ imp->set_flatname ();
+
+ unsigned n = dump.push (imp);
+
+ if (!imp->filename && fname)
+ imp->filename = xstrdup (fname);
+
+ if (imp->is_partition ())
+ dump () && dump ("Importing elided partition %M", imp);
+
+ if (!imp->do_import (reader, false))
+ imp = NULL;
+ dump.pop (n);
+ if (!imp)
+ continue;
+ }
+
+ if (is_partition ())
+ {
+ if (!imp->is_direct ())
+ imp->directness = MD_PARTITION_DIRECT;
+ if (exportedness > 0)
+ imp->exported_p = true;
+ }
+ }
+ else
+ {
+ /* An indirect import, find it, it should already be here. */
+ if (imp->loadedness == ML_NONE)
+ {
+ error_at (loc, "indirect import %qs is not already loaded", name);
+ continue;
+ }
+ }
+
+ if (imp->crc != crc)
+ error_at (loc, "import %qs has CRC mismatch", imp->get_flatname ());
+
+ (*slurp->remap)[ix] = (imp->mod << 1) | (lmaps != NULL);
+
+ if (lmaps && exportedness >= 0)
+ set_import (imp, bool (exportedness));
+ dump () && dump ("Found %simport:%u %M->%u", !lmaps ? "indirect "
+ : exportedness > 0 ? "exported "
+ : exportedness < 0 ? "gmf" : "", ix, imp,
+ imp->mod);
+ loaded++;
+ }
+
+ return loaded;
+}
+
+/* Write the import table to MOD_SNAME_PFX.imp. */
+
+void
+module_state::write_imports (elf_out *to, unsigned *crc_ptr)
+{
+ dump () && dump ("Writing imports");
+ dump.indent ();
+
+ bytes_out sec (to);
+ sec.begin ();
+
+ write_imports (sec, true);
+ write_imports (sec, false);
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".imp"), crc_ptr);
+ dump.outdent ();
+}
+
+bool
+module_state::read_imports (cpp_reader *reader, line_maps *lmaps)
+{
+ bytes_in sec;
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".imp"))
+ return false;
+
+ dump () && dump ("Reading %u imports", slurp->remap->length () - 1);
+ dump.indent ();
+
+ /* Read the imports. */
+ unsigned direct = read_imports (sec, reader, lmaps);
+ unsigned indirect = read_imports (sec, NULL, NULL);
+ if (direct + indirect + 1 != slurp->remap->length ())
+ from ()->set_error (elf::E_BAD_IMPORT);
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+/* We're the primary module interface, but have partitions. Document
+ them so that non-partition module implementation units know which
+ have already been loaded. */
+
+void
+module_state::write_partitions (elf_out *to, unsigned count, unsigned *crc_ptr)
+{
+ dump () && dump ("Writing %u elided partitions", count);
+ dump.indent ();
+
+ bytes_out sec (to);
+ sec.begin ();
+
+ for (unsigned ix = 1; ix != modules->length (); ix++)
+ {
+ module_state *imp = (*modules)[ix];
+ if (imp->is_partition ())
+ {
+ dump () && dump ("Writing elided partition %M (crc=%x)",
+ imp, imp->crc);
+ sec.str (imp->get_flatname ());
+ sec.u32 (imp->crc);
+ write_location (sec, imp->is_direct ()
+ ? imp->imported_from () : UNKNOWN_LOCATION);
+ sec.str (imp->filename);
+ }
+ }
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".prt"), crc_ptr);
+ dump.outdent ();
+}
+
+bool
+module_state::read_partitions (unsigned count)
+{
+ bytes_in sec;
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".prt"))
+ return false;
+
+ dump () && dump ("Reading %u elided partitions", count);
+ dump.indent ();
+
+ while (count--)
+ {
+ const char *name = sec.str (NULL);
+ unsigned crc = sec.u32 ();
+ location_t floc = read_location (sec);
+ const char *fname = sec.str (NULL);
+
+ if (sec.get_overrun ())
+ break;
+
+ dump () && dump ("Reading elided partition %s (crc=%x)", name, crc);
+
+ module_state *imp = get_module (name);
+ if (!imp || !imp->is_partition () || imp->is_rooted ()
+ || get_primary (imp) != this)
+ {
+ sec.set_overrun ();
+ break;
+ }
+
+ /* Attach the partition without loading it. We'll have to load
+ for real if it's indirectly imported. */
+ imp->loc = floc;
+ imp->crc = crc;
+ if (!imp->filename && fname[0])
+ imp->filename = xstrdup (fname);
+ }
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+/* Counter indices. */
+enum module_state_counts
+{
+ MSC_sec_lwm,
+ MSC_sec_hwm,
+ MSC_pendings,
+ MSC_entities,
+ MSC_namespaces,
+ MSC_bindings,
+ MSC_macros,
+ MSC_inits,
+ MSC_HWM
+};
+
+/* Data for config reading and writing. */
+struct module_state_config {
+ const char *dialect_str;
+ unsigned num_imports;
+ unsigned num_partitions;
+ unsigned ordinary_locs;
+ unsigned macro_locs;
+ unsigned ordinary_loc_align;
+
+public:
+ module_state_config ()
+ :dialect_str (get_dialect ()),
+ num_imports (0), num_partitions (0),
+ ordinary_locs (0), macro_locs (0), ordinary_loc_align (0)
+ {
+ }
+
+ static void release ()
+ {
+ XDELETEVEC (dialect);
+ dialect = NULL;
+ }
+
+private:
+ static const char *get_dialect ();
+ static char *dialect;
+};
+
+char *module_state_config::dialect;
+
+/* Generate a string of the significant compilation options.
+ Generally assume the user knows what they're doing, in the same way
+ that object files can be mixed. */
+
+const char *
+module_state_config::get_dialect ()
+{
+ if (!dialect)
+ dialect = concat (get_cxx_dialect_name (cxx_dialect),
+ /* C++ implies these, only show if disabled. */
+ flag_exceptions ? "" : "/no-exceptions",
+ flag_rtti ? "" : "/no-rtti",
+ flag_new_inheriting_ctors ? "" : "/old-inheriting-ctors",
+ /* C++ 20 implies concepts. */
+ cxx_dialect < cxx20 && flag_concepts ? "/concepts" : "",
+ flag_coroutines ? "/coroutines" : "",
+ flag_module_implicit_inline ? "/implicit-inline" : "",
+ NULL);
+
+ return dialect;
+}
+
+/* Contents of a cluster. */
+enum cluster_tag {
+ ct_decl, /* A decl. */
+ ct_defn, /* A definition. */
+ ct_bind, /* A binding. */
+ ct_hwm
+};
+
+/* Binding modifiers. */
+enum ct_bind_flags
+{
+ cbf_export = 0x1, /* An exported decl. */
+ cbf_hidden = 0x2, /* A hidden (friend) decl. */
+ cbf_using = 0x4, /* A using decl. */
+ cbf_wrapped = 0x8, /* ... that is wrapped. */
+};
+
+/* Write the cluster of depsets in SCC[0-SIZE). */
+
+unsigned
+module_state::write_cluster (elf_out *to, depset *scc[], unsigned size,
+ depset::hash &table, unsigned *counts,
+ unsigned *crc_ptr)
+{
+ dump () && dump ("Writing section:%u %u depsets", table.section, size);
+ dump.indent ();
+
+ trees_out sec (to, this, table, table.section);
+ sec.begin ();
+
+ /* Determine entity numbers, mark for writing. */
+ dump (dumper::CLUSTER) && dump ("Cluster members:") && (dump.indent (), true);
+ for (unsigned ix = 0; ix != size; ix++)
+ {
+ depset *b = scc[ix];
+
+ switch (b->get_entity_kind ())
+ {
+ default:
+ gcc_unreachable ();
+
+ case depset::EK_BINDING:
+ dump (dumper::CLUSTER)
+ && dump ("[%u]=%s %P", ix, b->entity_kind_name (),
+ b->get_entity (), b->get_name ());
+ for (unsigned jx = b->deps.length (); jx--;)
+ {
+ depset *dep = b->deps[jx];
+ if (jx)
+ gcc_checking_assert (dep->get_entity_kind () == depset::EK_USING
+ || TREE_VISITED (dep->get_entity ()));
+ else
+ gcc_checking_assert (dep->get_entity_kind ()
+ == depset::EK_NAMESPACE
+ && dep->get_entity () == b->get_entity ());
+ }
+ break;
+
+ case depset::EK_DECL:
+ if (b->is_member ())
+ {
+ case depset::EK_SPECIALIZATION: /* Yowzer! */
+ case depset::EK_PARTIAL: /* Hey, let's do it again! */
+ counts[MSC_pendings]++;
+ }
+ b->cluster = counts[MSC_entities]++;
+ sec.mark_declaration (b->get_entity (), b->has_defn ());
+ /* FALLTHROUGH */
+
+ case depset::EK_USING:
+ gcc_checking_assert (!b->is_import ()
+ && !b->is_unreached ());
+ dump (dumper::CLUSTER)
+ && dump ("[%u]=%s %s %N", ix, b->entity_kind_name (),
+ b->has_defn () ? "definition" : "declaration",
+ b->get_entity ());
+ break;
+ }
+ }
+ dump (dumper::CLUSTER) && (dump.outdent (), true);
+
+ /* Ensure every imported decl is referenced before we start
+ streaming. This ensures that we never encounter the
+ situation where this cluster instantiates some implicit
+ member that importing some other decl causes to be
+ instantiated. */
+ sec.set_importing (+1);
+ for (unsigned ix = 0; ix != size; ix++)
+ {
+ depset *b = scc[ix];
+ for (unsigned jx = (b->get_entity_kind () == depset::EK_BINDING
+ || b->is_special ()) ? 1 : 0;
+ jx != b->deps.length (); jx++)
+ {
+ depset *dep = b->deps[jx];
+
+ if (!dep->is_binding ()
+ && dep->is_import () && !TREE_VISITED (dep->get_entity ()))
+ {
+ tree import = dep->get_entity ();
+
+ sec.tree_node (import);
+ dump (dumper::CLUSTER) && dump ("Seeded import %N", import);
+ }
+ }
+ }
+ sec.tree_node (NULL_TREE);
+ /* We're done importing now. */
+ sec.set_importing (-1);
+
+ /* Write non-definitions. */
+ for (unsigned ix = 0; ix != size; ix++)
+ {
+ depset *b = scc[ix];
+ tree decl = b->get_entity ();
+ switch (b->get_entity_kind ())
+ {
+ default:
+ gcc_unreachable ();
+ break;
+
+ case depset::EK_BINDING:
+ {
+ gcc_assert (TREE_CODE (decl) == NAMESPACE_DECL);
+ dump () && dump ("Depset:%u binding %C:%P", ix, TREE_CODE (decl),
+ decl, b->get_name ());
+ sec.u (ct_bind);
+ sec.tree_node (decl);
+ sec.tree_node (b->get_name ());
+
+ /* Write in reverse order, so reading will see the exports
+ first, thus building the overload chain will be
+ optimized. */
+ for (unsigned jx = b->deps.length (); --jx;)
+ {
+ depset *dep = b->deps[jx];
+ tree bound = dep->get_entity ();
+ unsigned flags = 0;
+ if (dep->get_entity_kind () == depset::EK_USING)
+ {
+ tree ovl = bound;
+ bound = OVL_FUNCTION (bound);
+ if (!(TREE_CODE (bound) == CONST_DECL
+ && UNSCOPED_ENUM_P (TREE_TYPE (bound))
+ && decl == TYPE_NAME (TREE_TYPE (bound))))
+ {
+ /* An unscope enumerator in its enumeration's
+ scope is not a using. */
+ flags |= cbf_using;
+ if (OVL_USING_P (ovl))
+ flags |= cbf_wrapped;
+ }
+ if (OVL_EXPORT_P (ovl))
+ flags |= cbf_export;
+ }
+ else
+ {
+ /* An implicit typedef must be at one. */
+ gcc_assert (!DECL_IMPLICIT_TYPEDEF_P (bound) || jx == 1);
+ if (dep->is_hidden ())
+ flags |= cbf_hidden;
+ else if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (bound)))
+ flags |= cbf_export;
+ }
+
+ gcc_checking_assert (DECL_P (bound));
+
+ sec.i (flags);
+ sec.tree_node (bound);
+ }
+
+ /* Terminate the list. */
+ sec.i (-1);
+ }
+ break;
+
+ case depset::EK_USING:
+ dump () && dump ("Depset:%u %s %C:%N", ix, b->entity_kind_name (),
+ TREE_CODE (decl), decl);
+ break;
+
+ case depset::EK_SPECIALIZATION:
+ case depset::EK_PARTIAL:
+ case depset::EK_DECL:
+ dump () && dump ("Depset:%u %s entity:%u %C:%N", ix,
+ b->entity_kind_name (), b->cluster,
+ TREE_CODE (decl), decl);
+
+ sec.u (ct_decl);
+ sec.tree_node (decl);
+
+ dump () && dump ("Wrote declaration entity:%u %C:%N",
+ b->cluster, TREE_CODE (decl), decl);
+ break;
+ }
+ }
+
+ depset *namer = NULL;
+
+ /* Write out definitions */
+ for (unsigned ix = 0; ix != size; ix++)
+ {
+ depset *b = scc[ix];
+ tree decl = b->get_entity ();
+ switch (b->get_entity_kind ())
+ {
+ default:
+ break;
+
+ case depset::EK_SPECIALIZATION:
+ case depset::EK_PARTIAL:
+ case depset::EK_DECL:
+ if (!namer)
+ namer = b;
+
+ if (b->has_defn ())
+ {
+ sec.u (ct_defn);
+ sec.tree_node (decl);
+ dump () && dump ("Writing definition %N", decl);
+ sec.write_definition (decl);
+
+ if (!namer->has_defn ())
+ namer = b;
+ }
+ break;
+ }
+ }
+
+ /* We don't find the section by name. Use depset's decl's name for
+ human friendliness. */
+ unsigned name = 0;
+ tree naming_decl = NULL_TREE;
+ if (namer)
+ {
+ naming_decl = namer->get_entity ();
+ if (namer->get_entity_kind () == depset::EK_USING)
+ /* This unfortunately names the section from the target of the
+ using decl. But the name is only a guide, so Do Not Care. */
+ naming_decl = OVL_FUNCTION (naming_decl);
+ if (DECL_IMPLICIT_TYPEDEF_P (naming_decl))
+ /* Lose any anonymousness. */
+ naming_decl = TYPE_NAME (TREE_TYPE (naming_decl));
+ name = to->qualified_name (naming_decl, namer->has_defn ());
+ }
+
+ unsigned bytes = sec.pos;
+ unsigned snum = sec.end (to, name, crc_ptr);
+
+ for (unsigned ix = size; ix--;)
+ gcc_checking_assert (scc[ix]->section == snum);
+
+ dump.outdent ();
+ dump () && dump ("Wrote section:%u named-by:%N", table.section, naming_decl);
+
+ return bytes;
+}
+
+/* Read a cluster from section SNUM. */
+
+bool
+module_state::read_cluster (unsigned snum)
+{
+ trees_in sec (this);
+
+ if (!sec.begin (loc, from (), snum))
+ return false;
+
+ dump () && dump ("Reading section:%u", snum);
+ dump.indent ();
+
+ /* We care about structural equality. */
+ comparing_specializations++;
+
+ /* First seed the imports. */
+ while (tree import = sec.tree_node ())
+ dump (dumper::CLUSTER) && dump ("Seeded import %N", import);
+
+ while (!sec.get_overrun () && sec.more_p ())
+ {
+ unsigned ct = sec.u ();
+ switch (ct)
+ {
+ default:
+ sec.set_overrun ();
+ break;
+
+ case ct_bind:
+ /* A set of namespace bindings. */
+ {
+ tree ns = sec.tree_node ();
+ tree name = sec.tree_node ();
+ tree decls = NULL_TREE;
+ tree visible = NULL_TREE;
+ tree type = NULL_TREE;
+ bool dedup = false;
+
+ /* We rely on the bindings being in the reverse order of
+ the resulting overload set. */
+ for (;;)
+ {
+ int flags = sec.i ();
+ if (flags < 0)
+ break;
+
+ if ((flags & cbf_hidden)
+ && (flags & (cbf_using | cbf_export)))
+ sec.set_overrun ();
+
+ tree decl = sec.tree_node ();
+ if (sec.get_overrun ())
+ break;
+
+ if (decls && TREE_CODE (decl) == TYPE_DECL)
+ {
+ /* Stat hack. */
+ if (type || !DECL_IMPLICIT_TYPEDEF_P (decl))
+ sec.set_overrun ();
+ type = decl;
+ }
+ else
+ {
+ if (decls
+ || (flags & (cbf_hidden | cbf_wrapped))
+ || DECL_FUNCTION_TEMPLATE_P (decl))
+ {
+ decls = ovl_make (decl, decls);
+ if (flags & cbf_using)
+ {
+ dedup = true;
+ OVL_USING_P (decls) = true;
+ if (flags & cbf_export)
+ OVL_EXPORT_P (decls) = true;
+ }
+
+ if (flags & cbf_hidden)
+ OVL_HIDDEN_P (decls) = true;
+ else if (dedup)
+ OVL_DEDUP_P (decls) = true;
+ }
+ else
+ decls = decl;
+
+ if (flags & cbf_export
+ || (!(flags & cbf_hidden)
+ && (is_module () || is_partition ())))
+ visible = decls;
+ }
+ }
+
+ if (!decls)
+ sec.set_overrun ();
+
+ if (sec.get_overrun ())
+ break; /* Bail. */
+
+ dump () && dump ("Binding of %P", ns, name);
+ if (!set_module_binding (ns, name, mod,
+ is_header () ? -1
+ : is_module () || is_partition () ? 1
+ : 0,
+ decls, type, visible))
+ sec.set_overrun ();
+
+ if (type
+ && CP_DECL_CONTEXT (type) == ns
+ && !sec.is_duplicate (type))
+ add_module_decl (ns, name, type);
+
+ for (ovl_iterator iter (decls); iter; ++iter)
+ if (!iter.using_p ())
+ {
+ tree decl = *iter;
+ if (CP_DECL_CONTEXT (decl) == ns
+ && !sec.is_duplicate (decl))
+ add_module_decl (ns, name, decl);
+ }
+ }
+ break;
+
+ case ct_decl:
+ /* A decl. */
+ {
+ tree decl = sec.tree_node ();
+ dump () && dump ("Read declaration of %N", decl);
+ }
+ break;
+
+ case ct_defn:
+ {
+ tree decl = sec.tree_node ();
+ dump () && dump ("Reading definition of %N", decl);
+ sec.read_definition (decl);
+ }
+ break;
+ }
+ }
+
+ /* When lazy loading is in effect, we can be in the middle of
+ parsing or instantiating a function. Save it away.
+ push_function_context does too much work. */
+ tree old_cfd = current_function_decl;
+ struct function *old_cfun = cfun;
+ while (tree decl = sec.post_process ())
+ {
+ bool abstract = false;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ abstract = true;
+ decl = DECL_TEMPLATE_RESULT (decl);
+ }
+
+ current_function_decl = decl;
+ allocate_struct_function (decl, abstract);
+ cfun->language = ggc_cleared_alloc<language_function> ();
+ cfun->language->base.x_stmt_tree.stmts_are_full_exprs_p = 1;
+
+ if (abstract)
+ ;
+ else if (DECL_ABSTRACT_P (decl))
+ {
+ bool cloned = maybe_clone_body (decl);
+ if (!cloned)
+ from ()->set_error ();
+ }
+ else
+ {
+ bool aggr = aggregate_value_p (DECL_RESULT (decl), decl);
+#ifdef PCC_STATIC_STRUCT_RETURN
+ cfun->returns_pcc_struct = aggr;
+#endif
+ cfun->returns_struct = aggr;
+
+ if (DECL_COMDAT (decl))
+ // FIXME: Comdat grouping?
+ comdat_linkage (decl);
+ note_vague_linkage_fn (decl);
+ cgraph_node::finalize_function (decl, true);
+ }
+
+ }
+ /* Look, function.c's interface to cfun does too much for us, we
+ just need to restore the old value. I do not want to go
+ redesigning that API right now. */
+#undef cfun
+ cfun = old_cfun;
+ current_function_decl = old_cfd;
+ comparing_specializations--;
+
+ dump.outdent ();
+ dump () && dump ("Read section:%u", snum);
+
+ loaded_clusters++;
+
+ if (!sec.end (from ()))
+ return false;
+
+ return true;
+}
+
+void
+module_state::write_namespace (bytes_out &sec, depset *dep)
+{
+ unsigned ns_num = dep->cluster;
+ unsigned ns_import = 0;
+
+ if (dep->is_import ())
+ ns_import = dep->section;
+ else if (dep->get_entity () != global_namespace)
+ ns_num++;
+
+ sec.u (ns_import);
+ sec.u (ns_num);
+}
+
+tree
+module_state::read_namespace (bytes_in &sec)
+{
+ unsigned ns_import = sec.u ();
+ unsigned ns_num = sec.u ();
+ tree ns = NULL_TREE;
+
+ if (ns_import || ns_num)
+ {
+ if (!ns_import)
+ ns_num--;
+
+ if (unsigned origin = slurp->remap_module (ns_import))
+ {
+ module_state *from = (*modules)[origin];
+ if (ns_num < from->entity_num)
+ {
+ binding_slot &slot = (*entity_ary)[from->entity_lwm + ns_num];
+
+ if (!slot.is_lazy ())
+ ns = slot;
+ }
+ }
+ else
+ sec.set_overrun ();
+ }
+ else
+ ns = global_namespace;
+
+ return ns;
+}
+
+/* SPACES is a sorted vector of namespaces. Write out the namespaces
+ to MOD_SNAME_PFX.nms section. */
+
+void
+module_state::write_namespaces (elf_out *to, vec<depset *> spaces,
+ unsigned num, unsigned *crc_p)
+{
+ dump () && dump ("Writing namespaces");
+ dump.indent ();
+
+ bytes_out sec (to);
+ sec.begin ();
+
+ for (unsigned ix = 0; ix != num; ix++)
+ {
+ depset *b = spaces[ix];
+ tree ns = b->get_entity ();
+
+ gcc_checking_assert (TREE_CODE (ns) == NAMESPACE_DECL);
+
+ bool export_p = DECL_MODULE_EXPORT_P (ns);
+ bool inline_p = DECL_NAMESPACE_INLINE_P (ns);
+ bool public_p = TREE_PUBLIC (ns);
+
+ /* We should only be naming public namespaces, or our own
+ private ones. Internal linkage ones never get to be written
+ out -- because that means something erroneously referred to a
+ member. However, Davis Herring's paper probably changes that
+ by permitting them to be written out, but then an error if on
+ touches them. (Certain cases cannot be detected until that
+ point.) */
+ gcc_checking_assert (public_p || !DECL_MODULE_IMPORT_P (ns));
+ unsigned flags = 0;
+ if (export_p)
+ flags |= 1;
+ if (inline_p)
+ flags |= 2;
+ if (public_p)
+ flags |= 4;
+ dump () && dump ("Writing namespace:%u %N%s%s%s",
+ b->cluster, ns, export_p ? ", export" : "",
+ public_p ? ", public" : "",
+ inline_p ? ", inline" : "");
+ sec.u (b->cluster);
+ sec.u (to->name (DECL_NAME (ns)));
+ write_namespace (sec, b->deps[0]);
+
+ /* Don't use bools, because this can be near the end of the
+ section, and it won't save anything anyway. */
+ sec.u (flags);
+ write_location (sec, DECL_SOURCE_LOCATION (ns));
+ }
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".nms"), crc_p);
+ dump.outdent ();
+}
+
+/* Read the namespace hierarchy from MOD_SNAME_PFX.namespace. Fill in
+ SPACES from that data. */
+
+bool
+module_state::read_namespaces (unsigned num)
+{
+ bytes_in sec;
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".nms"))
+ return false;
+
+ dump () && dump ("Reading namespaces");
+ dump.indent ();
+
+ for (unsigned ix = 0; ix != num; ix++)
+ {
+ unsigned entity_index = sec.u ();
+ unsigned name = sec.u ();
+
+ tree parent = read_namespace (sec);
+
+ /* See comment in write_namespace about why not bits. */
+ unsigned flags = sec.u ();
+ location_t src_loc = read_location (sec);
+
+ if (entity_index >= entity_num || !parent)
+ sec.set_overrun ();
+ if (sec.get_overrun ())
+ break;
+
+ tree id = name ? get_identifier (from ()->name (name)) : NULL_TREE;
+ bool public_p = flags & 4;
+ bool inline_p = flags & 2;
+ bool export_p = flags & 1;
+
+ dump () && dump ("Read namespace:%u %P%s%s%s",
+ entity_index, parent, id, export_p ? ", export" : "",
+ public_p ? ", public" : "",
+ inline_p ? ", inline" : "");
+ bool visible_p = (export_p
+ || (public_p && (is_partition () || is_module ())));
+ tree inner = add_imported_namespace (parent, id, mod,
+ src_loc, visible_p, inline_p);
+ if (export_p && is_partition ())
+ DECL_MODULE_EXPORT_P (inner) = true;
+
+ /* Install the namespace. */
+ (*entity_ary)[entity_lwm + entity_index] = inner;
+ if (DECL_MODULE_IMPORT_P (inner))
+ {
+ bool existed;
+ unsigned *slot = &entity_map->get_or_insert
+ (DECL_UID (inner), &existed);
+ if (existed)
+ /* If it existed, it should match. */
+ gcc_checking_assert (inner == (*entity_ary)[*slot]);
+ else
+ *slot = entity_lwm + entity_index;
+ }
+ }
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+/* Write the binding TABLE to MOD_SNAME_PFX.bnd */
+
+unsigned
+module_state::write_bindings (elf_out *to, vec<depset *> sccs, unsigned *crc_p)
+{
+ dump () && dump ("Writing binding table");
+ dump.indent ();
+
+ unsigned num = 0;
+ bytes_out sec (to);
+ sec.begin ();
+
+ for (unsigned ix = 0; ix != sccs.length (); ix++)
+ {
+ depset *b = sccs[ix];
+ if (b->is_binding ())
+ {
+ tree ns = b->get_entity ();
+ dump () && dump ("Bindings %P section:%u", ns, b->get_name (),
+ b->section);
+ sec.u (to->name (b->get_name ()));
+ write_namespace (sec, b->deps[0]);
+ sec.u (b->section);
+ num++;
+ }
+ }
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".bnd"), crc_p);
+ dump.outdent ();
+
+ return num;
+}
+
+/* Read the binding table from MOD_SNAME_PFX.bind. */
+
+bool
+module_state::read_bindings (unsigned num, unsigned lwm, unsigned hwm)
+{
+ bytes_in sec;
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".bnd"))
+ return false;
+
+ dump () && dump ("Reading binding table");
+ dump.indent ();
+ for (; !sec.get_overrun () && num--;)
+ {
+ const char *name = from ()->name (sec.u ());
+ tree ns = read_namespace (sec);
+ unsigned snum = sec.u ();
+
+ if (!ns || !name || (snum - lwm) >= (hwm - lwm))
+ sec.set_overrun ();
+ if (!sec.get_overrun ())
+ {
+ tree id = get_identifier (name);
+ dump () && dump ("Bindings %P section:%u", ns, id, snum);
+ if (mod && !import_module_binding (ns, id, mod, snum))
+ break;
+ }
+ }
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+/* Write the entity table to MOD_SNAME_PFX.ent
+
+ Each entry is a section number. */
+
+void
+module_state::write_entities (elf_out *to, vec<depset *> depsets,
+ unsigned count, unsigned *crc_p)
+{
+ dump () && dump ("Writing entities");
+ dump.indent ();
+
+ bytes_out sec (to);
+ sec.begin ();
+
+ unsigned current = 0;
+ for (unsigned ix = 0; ix < depsets.length (); ix++)
+ {
+ depset *d = depsets[ix];
+
+ switch (d->get_entity_kind ())
+ {
+ default:
+ break;
+
+ case depset::EK_NAMESPACE:
+ if (!d->is_import () && d->get_entity () != global_namespace)
+ {
+ gcc_checking_assert (d->cluster == current);
+ current++;
+ sec.u (0);
+ }
+ break;
+
+ case depset::EK_DECL:
+ case depset::EK_SPECIALIZATION:
+ case depset::EK_PARTIAL:
+ gcc_checking_assert (!d->is_unreached ()
+ && !d->is_import ()
+ && d->cluster == current
+ && d->section);
+ current++;
+ sec.u (d->section);
+ break;
+ }
+ }
+ gcc_assert (count == current);
+ sec.end (to, to->name (MOD_SNAME_PFX ".ent"), crc_p);
+ dump.outdent ();
+}
+
+bool
+module_state::read_entities (unsigned count, unsigned lwm, unsigned hwm)
+{
+ trees_in sec (this);
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".ent"))
+ return false;
+
+ dump () && dump ("Reading entities");
+ dump.indent ();
+
+ vec_safe_reserve (entity_ary, count);
+ unsigned ix;
+ for (ix = 0; ix != count; ix++)
+ {
+ unsigned snum = sec.u ();
+ if (snum && (snum - lwm) >= (hwm - lwm))
+ sec.set_overrun ();
+ if (sec.get_overrun ())
+ break;
+
+ binding_slot slot;
+ slot.u.binding = NULL_TREE;
+ if (snum)
+ slot.set_lazy (snum << 2);
+ entity_ary->quick_push (slot);
+ }
+ entity_num = ix;
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+/* Write the pending table to MOD_SNAME_PFX.pnd
+
+ Specializations & partials are keyed to their primary template.
+ Members are keyed to their context.
+
+ For specializations & partials, primary templates are keyed to the
+ (namespace name) of their originating decl (because that's the only
+ handle we have). */
+
+void
+module_state::write_pendings (elf_out *to, vec<depset *> depsets,
+ depset::hash &table,
+ unsigned count, unsigned *crc_p)
+{
+ dump () && dump ("Writing %u pendings", count);
+ dump.indent ();
+
+ trees_out sec (to, this, table);
+ sec.begin ();
+
+ for (unsigned ix = 0; ix < depsets.length (); ix++)
+ {
+ depset *d = depsets[ix];
+ depset::entity_kind kind = d->get_entity_kind ();
+ tree key = NULL_TREE;
+ bool is_spec = false;
+
+
+ if (kind == depset::EK_SPECIALIZATION)
+ {
+ is_spec = true;
+ key = reinterpret_cast <spec_entry *> (d->deps[0])->tmpl;
+ }
+ else if (kind == depset::EK_PARTIAL)
+ {
+ is_spec = true;
+ key = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d->get_entity ()));
+ }
+ else if (kind == depset::EK_DECL && d->is_member ())
+ {
+ tree ctx = DECL_CONTEXT (d->get_entity ());
+ key = TYPE_NAME (ctx);
+ if (tree ti = CLASSTYPE_TEMPLATE_INFO (ctx))
+ if (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti)) == key)
+ key = TI_TEMPLATE (ti);
+ }
+
+ // FIXME:OPTIMIZATION More than likely when there is one pending
+ // member, there will be others. All written in the same
+ // section and keyed to the same class. We only need to record
+ // one of them. The same is not true for specializations
+
+ if (key)
+ {
+ gcc_checking_assert (!d->is_import ());
+
+ {
+ /* Key the entity to its key. */
+ depset *key_dep = table.find_dependency (key);
+ if (key_dep->get_entity_kind () == depset::EK_REDIRECT)
+ key_dep = key_dep->deps[0];
+ unsigned key_origin
+ = key_dep->is_import () ? key_dep->section : 0;
+ sec.u (key_origin);
+ sec.u (key_dep->cluster);
+ sec.u (d->cluster);
+ dump () && dump ("%s %N entity:%u keyed to %M[%u] %N",
+ is_spec ? "Specialization" : "Member",
+ d->get_entity (),
+ d->cluster, (*modules)[key_origin],
+ key_dep->cluster, key);
+ }
+
+ if (is_spec)
+ {
+ /* Key the general template to the originating decl. */
+ tree origin = get_originating_module_decl (key);
+ sec.tree_node (CP_DECL_CONTEXT (origin));
+ sec.tree_node (DECL_NAME (origin));
+
+ unsigned origin_ident = import_entity_index (origin);
+ module_state *origin_from = this;
+ if (!(origin_ident & ~(~0u>>1)))
+ origin_from = import_entity_module (origin_ident);
+ sec.u (origin_from->remap);
+ }
+ else
+ sec.tree_node (NULL);
+ count--;
+ }
+ }
+ gcc_assert (!count);
+ sec.end (to, to->name (MOD_SNAME_PFX ".pnd"), crc_p);
+ dump.outdent ();
+}
+
+bool
+module_state::read_pendings (unsigned count)
+{
+ trees_in sec (this);
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".pnd"))
+ return false;
+
+ dump () && dump ("Reading %u pendings", count);
+ dump.indent ();
+
+ for (unsigned ix = 0; ix != count; ix++)
+ {
+ unsigned key_origin = slurp->remap_module (sec.u ());
+ unsigned key_index = sec.u ();
+ unsigned ent_index = sec.u ();
+ module_state *from = (*modules)[key_origin];
+ tree ns = sec.tree_node ();
+
+ if (!key_origin
+ || key_index >= from->entity_num || ent_index >= entity_num
+ || (ns && TREE_CODE (ns) != NAMESPACE_DECL))
+ sec.set_overrun ();
+
+ if (sec.get_overrun ())
+ break;
+
+ bool loaded = false;
+ dump () && dump ("%s keyed to %M[%u] entity:%u",
+ ns ? "Specialization" : "Member",
+ from, key_index, ent_index);
+ unsigned key_ident = from->entity_lwm + key_index;
+ if (pending_table->add (ns ? key_ident : ~key_ident,
+ ent_index + entity_lwm))
+ {
+ binding_slot &slot = (*entity_ary)[key_ident];
+ if (slot.is_lazy ())
+ slot.or_lazy (ns ? 1 : 2);
+ else
+ {
+ tree key = slot;
+
+ loaded = true;
+ if (ns)
+ {
+ if (key && TREE_CODE (key) == TEMPLATE_DECL)
+ DECL_MODULE_PENDING_SPECIALIZATIONS_P (key) = true;
+ else
+ sec.set_overrun ();
+ }
+ else
+ {
+ if (key && TREE_CODE (key) == TYPE_DECL)
+ DECL_MODULE_PENDING_MEMBERS_P (key) = true;
+ else
+ sec.set_overrun ();
+ }
+ }
+ }
+
+ if (ns)
+ {
+ /* We also need to mark the namespace binding of the
+ originating template, so we know to set its pending
+ specializations flag, when we load it. */
+ tree name = sec.tree_node ();
+ unsigned origin = slurp->remap_module (sec.u ());
+ if (!origin || !name || TREE_CODE (name) != IDENTIFIER_NODE)
+ sec.set_overrun ();
+ if (sec.get_overrun ())
+ break;
+
+ module_state *origin_from = (*modules)[origin];
+ if (!loaded
+ && (origin_from->is_header ()
+ || (origin_from->is_partition ()
+ || origin_from->is_module ())))
+ note_pending_specializations (ns, name, origin_from->is_header ());
+ }
+ }
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+/* Return true if module MOD cares about lazy specializations keyed to
+ possibly duplicated entity bindings. */
+
+bool
+lazy_specializations_p (unsigned mod, bool header_p, bool partition_p)
+{
+ module_state *module = (*modules)[mod];
+
+ if (module->is_header ())
+ return header_p;
+
+ if (module->is_module () || module->is_partition ())
+ return partition_p;
+
+ return false;
+}
+
+/* Read & write locations. */
+enum loc_kind {
+ LK_ORDINARY,
+ LK_MACRO,
+ LK_IMPORT_ORDINARY,
+ LK_IMPORT_MACRO,
+ LK_ADHOC,
+ LK_RESERVED,
+};
+
+static const module_state *
+module_for_ordinary_loc (location_t loc)
+{
+ unsigned pos = 1;
+ unsigned len = modules->length () - pos;
+
+ while (len)
+ {
+ unsigned half = len / 2;
+ module_state *probe = (*modules)[pos + half];
+ if (loc < probe->ordinary_locs.first)
+ len = half;
+ else if (loc < probe->ordinary_locs.second)
+ return probe;
+ else
+ {
+ pos += half + 1;
+ len = len - (half + 1);
+ }
+ }
+
+ return NULL;
+}
+
+static const module_state *
+module_for_macro_loc (location_t loc)
+{
+ unsigned pos = 1;
+ unsigned len = modules->length () - pos;
+
+ while (len)
+ {
+ unsigned half = len / 2;
+ module_state *probe = (*modules)[pos + half];
+ if (loc >= probe->macro_locs.second)
+ len = half;
+ else if (loc >= probe->macro_locs.first)
+ return probe;
+ else
+ {
+ pos += half + 1;
+ len = len - (half + 1);
+ }
+ }
+
+ return NULL;
+}
+
+location_t
+module_state::imported_from () const
+{
+ location_t from = loc;
+ line_map_ordinary const *fmap
+ = linemap_check_ordinary (linemap_lookup (line_table, from));
+
+ if (MAP_MODULE_P (fmap))
+ from = linemap_included_from (fmap);
+
+ return from;
+}
+
+/* If we're not streaming, record that we need location LOC.
+ Otherwise stream it. */
+
+void
+module_state::write_location (bytes_out &sec, location_t loc)
+{
+ if (!sec.streaming_p ())
+ /* This is where we should note we use this location. See comment
+ about write_ordinary_maps. */
+ return;
+
+ if (loc < RESERVED_LOCATION_COUNT)
+ {
+ dump (dumper::LOCATION) && dump ("Reserved location %u", unsigned (loc));
+ sec.u (LK_RESERVED + loc);
+ }
+ else if (IS_ADHOC_LOC (loc))
+ {
+ dump (dumper::LOCATION) && dump ("Adhoc location");
+ sec.u (LK_ADHOC);
+ location_t locus = get_location_from_adhoc_loc (line_table, loc);
+ write_location (sec, locus);
+ source_range range = get_range_from_loc (line_table, loc);
+ if (range.m_start == locus)
+ /* Compress. */
+ range.m_start = UNKNOWN_LOCATION;
+ write_location (sec, range.m_start);
+ write_location (sec, range.m_finish);
+ }
+ else if (IS_MACRO_LOC (loc))
+ {
+ if (const loc_spans::span *span = spans.macro (loc))
+ {
+ unsigned off = MAX_LOCATION_T - loc;
+
+ off -= span->macro_delta;
+
+ sec.u (LK_MACRO);
+ sec.u (off);
+ dump (dumper::LOCATION)
+ && dump ("Macro location %u output %u", loc, off);
+ }
+ else if (const module_state *import = module_for_macro_loc (loc))
+ {
+ unsigned off = import->macro_locs.second - loc - 1;
+ sec.u (LK_IMPORT_MACRO);
+ sec.u (import->remap);
+ sec.u (off);
+ dump (dumper::LOCATION)
+ && dump ("Imported macro location %u output %u:%u",
+ loc, import->remap, off);
+ }
+ else
+ gcc_unreachable ();
+ }
+ else if (IS_ORDINARY_LOC (loc))
+ {
+ if (const loc_spans::span *span = spans.ordinary (loc))
+ {
+ unsigned off = loc;
+
+ off += span->ordinary_delta;
+ sec.u (LK_ORDINARY);
+ sec.u (off);
+
+ dump (dumper::LOCATION)
+ && dump ("Ordinary location %u output %u", loc, off);
+ }
+ else if (const module_state *import = module_for_ordinary_loc (loc))
+ {
+ unsigned off = loc - import->ordinary_locs.first;
+ sec.u (LK_IMPORT_ORDINARY);
+ sec.u (import->remap);
+ sec.u (off);
+ dump (dumper::LOCATION)
+ && dump ("Imported ordinary location %u output %u:%u",
+ import->remap, import->remap, off);
+ }
+ else
+ gcc_unreachable ();
+ }
+ else
+ gcc_unreachable ();
+}
+
+location_t
+module_state::read_location (bytes_in &sec) const
+{
+ location_t locus = UNKNOWN_LOCATION;
+ unsigned kind = sec.u ();
+ switch (kind)
+ {
+ default:
+ {
+ if (kind < LK_RESERVED + RESERVED_LOCATION_COUNT)
+ locus = location_t (kind - LK_RESERVED);
+ else
+ sec.set_overrun ();
+ dump (dumper::LOCATION)
+ && dump ("Reserved location %u", unsigned (locus));
+ }
+ break;
+
+ case LK_ADHOC:
+ {
+ dump (dumper::LOCATION) && dump ("Adhoc location");
+ locus = read_location (sec);
+ source_range range;
+ range.m_start = read_location (sec);
+ if (range.m_start == UNKNOWN_LOCATION)
+ range.m_start = locus;
+ range.m_finish = read_location (sec);
+ if (locus != loc && range.m_start != loc && range.m_finish != loc)
+ locus = get_combined_adhoc_loc (line_table, locus, range, NULL);
+ }
+ break;
+
+ case LK_MACRO:
+ {
+ unsigned off = sec.u ();
+
+ if (macro_locs.first)
+ {
+ location_t adjusted = MAX_LOCATION_T - off;
+ adjusted -= slurp->loc_deltas.second;
+ if (adjusted < macro_locs.first)
+ sec.set_overrun ();
+ else if (adjusted < macro_locs.second)
+ locus = adjusted;
+ else
+ sec.set_overrun ();
+ }
+ else
+ locus = loc;
+ dump (dumper::LOCATION)
+ && dump ("Macro %u becoming %u", off, locus);
+ }
+ break;
+
+ case LK_ORDINARY:
+ {
+ unsigned off = sec.u ();
+ if (ordinary_locs.second)
+ {
+ location_t adjusted = off;
+
+ adjusted += slurp->loc_deltas.first;
+ if (adjusted >= ordinary_locs.second)
+ sec.set_overrun ();
+ else if (adjusted >= ordinary_locs.first)
+ locus = adjusted;
+ else if (adjusted < spans.main_start ())
+ locus = off;
+ }
+ else
+ locus = loc;
+
+ dump (dumper::LOCATION)
+ && dump ("Ordinary location %u becoming %u", off, locus);
+ }
+ break;
+
+ case LK_IMPORT_MACRO:
+ case LK_IMPORT_ORDINARY:
+ {
+ unsigned mod = sec.u ();
+ unsigned off = sec.u ();
+ const module_state *import = NULL;
+
+ if (!mod && !slurp->remap)
+ /* This is an early read of a partition location during the
+ read of our ordinary location map. */
+ import = this;
+ else
+ {
+ mod = slurp->remap_module (mod);
+ if (!mod)
+ sec.set_overrun ();
+ else
+ import = (*modules)[mod];
+ }
+
+ if (import)
+ {
+ if (kind == LK_IMPORT_MACRO)
+ {
+ if (!import->macro_locs.first)
+ locus = import->loc;
+ else if (off < import->macro_locs.second - macro_locs.first)
+ locus = import->macro_locs.second - off - 1;
+ else
+ sec.set_overrun ();
+ }
+ else
+ {
+ if (!import->ordinary_locs.second)
+ locus = import->loc;
+ else if (off < (import->ordinary_locs.second
+ - import->ordinary_locs.first))
+ locus = import->ordinary_locs.first + off;
+ else
+ sec.set_overrun ();
+ }
+ }
+ }
+ break;
+ }
+
+ return locus;
+}
+
+/* Prepare the span adjustments. */
+
+// FIXME:QOI I do not prune the unreachable locations. Modules with
+// textually-large GMFs could well cause us to run out of locations.
+// Regular single-file modules could also be affected. We should
+// determine which locations we need to represent, so that we do not
+// grab more locations than necessary. An example is in
+// write_macro_maps where we work around macro expansions that are not
+// covering any locations -- the macro expands to nothing. Perhaps we
+// should decompose locations so that we can have a more graceful
+// degradation upon running out?
+
+location_map_info
+module_state::write_prepare_maps (module_state_config *)
+{
+ dump () && dump ("Preparing locations");
+ dump.indent ();
+
+ dump () && dump ("Reserved locations [%u,%u) macro [%u,%u)",
+ spans[loc_spans::SPAN_RESERVED].ordinary.first,
+ spans[loc_spans::SPAN_RESERVED].ordinary.second,
+ spans[loc_spans::SPAN_RESERVED].macro.first,
+ spans[loc_spans::SPAN_RESERVED].macro.second);
+
+ location_map_info info;
+
+ info.num_maps.first = info.num_maps.second = 0;
+
+ /* Figure the alignment of ordinary location spans. */
+ unsigned max_range = 0;
+ for (unsigned ix = loc_spans::SPAN_FIRST; ix != spans.length (); ix++)
+ {
+ loc_spans::span &span = spans[ix];
+ line_map_ordinary const *omap
+ = linemap_check_ordinary (linemap_lookup (line_table,
+ span.ordinary.first));
+
+ /* We should exactly match up. */
+ gcc_checking_assert (MAP_START_LOCATION (omap) == span.ordinary.first);
+
+ line_map_ordinary const *fmap = omap;
+ for (; MAP_START_LOCATION (omap) < span.ordinary.second; omap++)
+ {
+ /* We should never find a module linemap in an interval. */
+ gcc_checking_assert (!MAP_MODULE_P (omap));
+
+ if (max_range < omap->m_range_bits)
+ max_range = omap->m_range_bits;
+ }
+
+ unsigned count = omap - fmap;
+ info.num_maps.first += count;
+
+ if (span.macro.first != span.macro.second)
+ {
+ count = linemap_lookup_macro_index (line_table, span.macro.first) + 1;
+ count -= linemap_lookup_macro_index (line_table,
+ span.macro.second - 1);
+ dump (dumper::LOCATION) && dump ("Span:%u %u macro maps", ix, count);
+ info.num_maps.second += count;
+ }
+ }
+
+ /* Adjust the maps. Ordinary ones ascend, and we must maintain
+ alignment. Macro ones descend, but are unaligned. */
+ location_t ord_off = spans[loc_spans::SPAN_FIRST].ordinary.first;
+ location_t mac_off = spans[loc_spans::SPAN_FIRST].macro.second;
+ location_t range_mask = (1u << max_range) - 1;
+
+ dump () && dump ("Ordinary maps range bits:%u, preserve:%x, zero:%u",
+ max_range, ord_off & range_mask, ord_off & ~range_mask);
+
+ for (unsigned ix = loc_spans::SPAN_FIRST; ix != spans.length (); ix++)
+ {
+ loc_spans::span &span = spans[ix];
+
+ span.macro_delta = mac_off - span.macro.second;
+ mac_off -= span.macro.second - span.macro.first;
+ dump () && dump ("Macro span:%u [%u,%u):%u->%d(%u)", ix,
+ span.macro.first, span.macro.second,
+ span.macro.second - span.macro.first,
+ span.macro_delta, span.macro.first + span.macro_delta);
+
+ line_map_ordinary const *omap
+ = linemap_check_ordinary (linemap_lookup (line_table,
+ span.ordinary.first));
+ location_t base = MAP_START_LOCATION (omap);
+
+ /* Preserve the low MAX_RANGE bits of base by incrementing ORD_OFF. */
+ unsigned low_bits = base & range_mask;
+ if ((ord_off & range_mask) > low_bits)
+ low_bits += range_mask + 1;
+ ord_off = (ord_off & ~range_mask) + low_bits;
+ span.ordinary_delta = ord_off - base;
+
+ for (; MAP_START_LOCATION (omap) < span.ordinary.second; omap++)
+ {
+ location_t start_loc = MAP_START_LOCATION (omap);
+ unsigned to = start_loc + span.ordinary_delta;
+ location_t end_loc = MAP_START_LOCATION (omap + 1);
+
+ dump () && dump ("Ordinary span:%u [%u,%u):%u->%d(%u)", ix, start_loc,
+ end_loc, end_loc - start_loc,
+ span.ordinary_delta, to);
+
+ /* There should be no change in the low order bits. */
+ gcc_checking_assert (((start_loc ^ to) & range_mask) == 0);
+ }
+ /* The ending serialized value. */
+ ord_off = span.ordinary.second + span.ordinary_delta;
+ }
+
+ dump () && dump ("Ordinary hwm:%u macro lwm:%u", ord_off, mac_off);
+
+ dump.outdent ();
+
+ info.max_range = max_range;
+
+ return info;
+}
+
+bool
+module_state::read_prepare_maps (const module_state_config *cfg)
+{
+ location_t ordinary = line_table->highest_location + 1;
+ ordinary = ((ordinary + (1u << cfg->ordinary_loc_align))
+ & ~((1u << cfg->ordinary_loc_align) - 1));
+ ordinary += cfg->ordinary_locs;
+
+ location_t macro = LINEMAPS_MACRO_LOWEST_LOCATION (line_table);
+ macro -= cfg->macro_locs;
+
+ if (ordinary < LINE_MAP_MAX_LOCATION_WITH_COLS
+ && macro >= LINE_MAP_MAX_LOCATION)
+ /* OK, we have enough locations. */
+ return true;
+
+ ordinary_locs.first = ordinary_locs.second = 0;
+ macro_locs.first = macro_locs.second = 0;
+
+ static bool informed = false;
+ if (!informed)
+ {
+ /* Just give the notice once. */
+ informed = true;
+ inform (loc, "unable to represent further imported source locations");
+ }
+
+ return false;
+}
+
+/* Write the location maps. This also determines the shifts for the
+ location spans. */
+
+void
+module_state::write_ordinary_maps (elf_out *to, location_map_info &info,
+ module_state_config *cfg, bool has_partitions,
+ unsigned *crc_p)
+{
+ dump () && dump ("Writing ordinary location maps");
+ dump.indent ();
+
+ vec<const char *> filenames;
+ filenames.create (20);
+
+ /* Determine the unique filenames. */
+ // FIXME:QOI We should find the set of filenames when working out
+ // which locations we actually need. See write_prepare_maps.
+ for (unsigned ix = loc_spans::SPAN_FIRST; ix != spans.length (); ix++)
+ {
+ loc_spans::span &span = spans[ix];
+ line_map_ordinary const *omap
+ = linemap_check_ordinary (linemap_lookup (line_table,
+ span.ordinary.first));
+
+ /* We should exactly match up. */
+ gcc_checking_assert (MAP_START_LOCATION (omap) == span.ordinary.first);
+
+ for (; MAP_START_LOCATION (omap) < span.ordinary.second; omap++)
+ {
+ const char *fname = ORDINARY_MAP_FILE_NAME (omap);
+
+ /* We should never find a module linemap in an interval. */
+ gcc_checking_assert (!MAP_MODULE_P (omap));
+
+ /* We expect very few filenames, so just an array. */
+ for (unsigned jx = filenames.length (); jx--;)
+ {
+ const char *name = filenames[jx];
+ if (0 == strcmp (name, fname))
+ {
+ /* Reset the linemap's name, because for things like
+ preprocessed input we could have multple
+ instances of the same name, and we'd rather not
+ percolate that. */
+ const_cast<line_map_ordinary *> (omap)->to_file = name;
+ fname = NULL;
+ break;
+ }
+ }
+ if (fname)
+ filenames.safe_push (fname);
+ }
+ }
+
+ bytes_out sec (to);
+ sec.begin ();
+
+ /* Write the filenames. */
+ unsigned len = filenames.length ();
+ sec.u (len);
+ dump () && dump ("%u source file names", len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ const char *fname = filenames[ix];
+ dump (dumper::LOCATION) && dump ("Source file[%u]=%s", ix, fname);
+ sec.str (fname);
+ }
+
+ location_t offset = spans[loc_spans::SPAN_FIRST].ordinary.first;
+ location_t range_mask = (1u << info.max_range) - 1;
+
+ dump () && dump ("Ordinary maps:%u, range bits:%u, preserve:%x, zero:%u",
+ info.num_maps.first, info.max_range, offset & range_mask,
+ offset & ~range_mask);
+ sec.u (info.num_maps.first); /* Num maps. */
+ sec.u (info.max_range); /* Maximum range bits */
+ sec.u (offset & range_mask); /* Bits to preserve. */
+ sec.u (offset & ~range_mask);
+
+ for (unsigned ix = loc_spans::SPAN_FIRST; ix != spans.length (); ix++)
+ {
+ loc_spans::span &span = spans[ix];
+ line_map_ordinary const *omap
+ = linemap_check_ordinary (linemap_lookup (line_table,
+ span.ordinary.first));
+ for (; MAP_START_LOCATION (omap) < span.ordinary.second; omap++)
+ {
+ location_t start_loc = MAP_START_LOCATION (omap);
+ unsigned to = start_loc + span.ordinary_delta;
+
+ dump (dumper::LOCATION)
+ && dump ("Span:%u ordinary [%u,%u)->%u", ix, start_loc,
+ MAP_START_LOCATION (omap + 1), to);
+
+ /* There should be no change in the low order bits. */
+ gcc_checking_assert (((start_loc ^ to) & range_mask) == 0);
+ sec.u (to);
+
+ /* Making accessors just for here, seems excessive. */
+ sec.u (omap->reason);
+ sec.u (omap->sysp);
+ sec.u (omap->m_range_bits);
+ sec.u (omap->m_column_and_range_bits - omap->m_range_bits);
+
+ const char *fname = ORDINARY_MAP_FILE_NAME (omap);
+ for (unsigned ix = 0; ix != filenames.length (); ix++)
+ if (filenames[ix] == fname)
+ {
+ sec.u (ix);
+ break;
+ }
+ sec.u (ORDINARY_MAP_STARTING_LINE_NUMBER (omap));
+
+ /* Write the included from location, which means reading it
+ while reading in the ordinary maps. So we'd better not
+ be getting ahead of ourselves. */
+ location_t from = linemap_included_from (omap);
+ gcc_checking_assert (from < MAP_START_LOCATION (omap));
+ if (from != UNKNOWN_LOCATION && has_partitions)
+ {
+ /* A partition's span will have a from pointing at a
+ MODULE_INC. Find that map's from. */
+ line_map_ordinary const *fmap
+ = linemap_check_ordinary (linemap_lookup (line_table, from));
+ if (MAP_MODULE_P (fmap))
+ from = linemap_included_from (fmap);
+ }
+ write_location (sec, from);
+ }
+ /* The ending serialized value. */
+ offset = MAP_START_LOCATION (omap) + span.ordinary_delta;
+ }
+ dump () && dump ("Ordinary location hwm:%u", offset);
+ sec.u (offset);
+
+ // Record number of locations and alignment.
+ cfg->ordinary_loc_align = info.max_range;
+ cfg->ordinary_locs = offset;
+
+ filenames.release ();
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".olm"), crc_p);
+ dump.outdent ();
+}
+
+void
+module_state::write_macro_maps (elf_out *to, location_map_info &info,
+ module_state_config *cfg, unsigned *crc_p)
+{
+ dump () && dump ("Writing macro location maps");
+ dump.indent ();
+
+ bytes_out sec (to);
+ sec.begin ();
+
+ dump () && dump ("Macro maps:%u", info.num_maps.second);
+ sec.u (info.num_maps.second);
+
+ location_t offset = spans[loc_spans::SPAN_FIRST].macro.second;
+ sec.u (offset);
+
+ unsigned macro_num = 0;
+ for (unsigned ix = loc_spans::SPAN_FIRST; ix != spans.length (); ix++)
+ {
+ loc_spans::span &span = spans[ix];
+ if (span.macro.first == span.macro.second)
+ continue;
+
+ for (unsigned first
+ = linemap_lookup_macro_index (line_table, span.macro.second - 1);
+ first < LINEMAPS_MACRO_USED (line_table);
+ first++)
+ {
+ line_map_macro const *mmap
+ = LINEMAPS_MACRO_MAP_AT (line_table, first);
+ location_t start_loc = MAP_START_LOCATION (mmap);
+ if (start_loc < span.macro.first)
+ break;
+ if (macro_num == info.num_maps.second)
+ {
+ /* We're ending on an empty macro expansion. The
+ preprocessor doesn't prune such things. */
+ // FIXME:QOI This is an example of the non-pruning of
+ // locations. See write_prepare_maps.
+ gcc_checking_assert (!mmap->n_tokens);
+ continue;
+ }
+
+ sec.u (offset);
+ sec.u (mmap->n_tokens);
+ sec.cpp_node (mmap->macro);
+ write_location (sec, mmap->expansion);
+ const location_t *locs = mmap->macro_locations;
+ /* There are lots of identical runs. */
+ location_t prev = UNKNOWN_LOCATION;
+ unsigned count = 0;
+ unsigned runs = 0;
+ for (unsigned jx = mmap->n_tokens * 2; jx--;)
+ {
+ location_t tok_loc = locs[jx];
+ if (tok_loc == prev)
+ {
+ count++;
+ continue;
+ }
+ runs++;
+ sec.u (count);
+ count = 1;
+ prev = tok_loc;
+ write_location (sec, tok_loc);
+ }
+ sec.u (count);
+ dump (dumper::LOCATION)
+ && dump ("Span:%u macro:%u %I %u/%u*2 locations [%u,%u)->%u",
+ ix, macro_num, identifier (mmap->macro),
+ runs, mmap->n_tokens,
+ start_loc, start_loc + mmap->n_tokens,
+ start_loc + span.macro_delta);
+ macro_num++;
+ offset -= mmap->n_tokens;
+ gcc_checking_assert (offset == start_loc + span.macro_delta);
+ }
+ }
+ dump () && dump ("Macro location lwm:%u", offset);
+ sec.u (offset);
+ gcc_assert (macro_num == info.num_maps.second);
+
+ cfg->macro_locs = MAX_LOCATION_T + 1 - offset;
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".mlm"), crc_p);
+ dump.outdent ();
+}
+
+bool
+module_state::read_ordinary_maps ()
+{
+ bytes_in sec;
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".olm"))
+ return false;
+ dump () && dump ("Reading ordinary location maps");
+ dump.indent ();
+
+ /* Read the filename table. */
+ unsigned len = sec.u ();
+ dump () && dump ("%u source file names", len);
+ vec<const char *> filenames;
+ filenames.create (len);
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ size_t l;
+ const char *buf = sec.str (&l);
+ char *fname = XNEWVEC (char, l + 1);
+ memcpy (fname, buf, l + 1);
+ dump (dumper::LOCATION) && dump ("Source file[%u]=%s", ix, fname);
+ /* We leak these names into the line-map table. But it
+ doesn't own them. */
+ filenames.quick_push (fname);
+ }
+
+ unsigned num_ordinary = sec.u ();
+ unsigned max_range = sec.u ();
+ unsigned low_bits = sec.u ();
+ location_t zero = sec.u ();
+ location_t range_mask = (1u << max_range) - 1;
+
+ dump () && dump ("Ordinary maps:%u, range bits:%u, preserve:%x, zero:%u",
+ num_ordinary, max_range, low_bits, zero);
+
+ location_t offset = line_table->highest_location + 1;
+ /* Ensure offset doesn't go backwards at the start. */
+ if ((offset & range_mask) > low_bits)
+ offset += range_mask + 1;
+ offset = (offset & ~range_mask);
+
+ bool propagated = spans.maybe_propagate (this, offset + low_bits);
+
+ line_map_ordinary *maps = static_cast<line_map_ordinary *>
+ (line_map_new_raw (line_table, false, num_ordinary));
+
+ location_t lwm = offset;
+ slurp->loc_deltas.first = offset - zero;
+ ordinary_locs.first = zero + low_bits + slurp->loc_deltas.first;
+ dump () && dump ("Ordinary loc delta %d", slurp->loc_deltas.first);
+
+ for (unsigned ix = 0; ix != num_ordinary && !sec.get_overrun (); ix++)
+ {
+ line_map_ordinary *map = &maps[ix];
+ unsigned hwm = sec.u ();
+
+ /* Record the current HWM so that the below read_location is
+ ok. */
+ ordinary_locs.second = hwm + slurp->loc_deltas.first;
+ map->start_location = hwm + (offset - zero);
+ if (map->start_location < lwm)
+ sec.set_overrun ();
+ lwm = map->start_location;
+ dump (dumper::LOCATION) && dump ("Map:%u %u->%u", ix, hwm, lwm);
+ map->reason = lc_reason (sec.u ());
+ map->sysp = sec.u ();
+ map->m_range_bits = sec.u ();
+ map->m_column_and_range_bits = map->m_range_bits + sec.u ();
+
+ unsigned fnum = sec.u ();
+ map->to_file = (fnum < filenames.length () ? filenames[fnum] : "");
+ map->to_line = sec.u ();
+
+ /* Root the outermost map at our location. */
+ location_t from = read_location (sec);
+ map->included_from = from != UNKNOWN_LOCATION ? from : loc;
+ }
+
+ location_t hwm = sec.u ();
+ ordinary_locs.second = hwm + slurp->loc_deltas.first;
+
+ /* highest_location is the one handed out, not the next one to
+ hand out. */
+ line_table->highest_location = ordinary_locs.second - 1;
+
+ if (line_table->highest_location >= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* We shouldn't run out of locations, as we checked before
+ starting. */
+ sec.set_overrun ();
+ dump () && dump ("Ordinary location hwm:%u", ordinary_locs.second);
+
+ if (propagated)
+ spans.close ();
+
+ filenames.release ();
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+
+ return true;
+}
+
+bool
+module_state::read_macro_maps ()
+{
+ bytes_in sec;
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".mlm"))
+ return false;
+ dump () && dump ("Reading macro location maps");
+ dump.indent ();
+
+ unsigned num_macros = sec.u ();
+ location_t zero = sec.u ();
+ dump () && dump ("Macro maps:%u zero:%u", num_macros, zero);
+
+ bool propagated = spans.maybe_propagate (this);
+
+ location_t offset = LINEMAPS_MACRO_LOWEST_LOCATION (line_table);
+ slurp->loc_deltas.second = zero - offset;
+ macro_locs.second = zero - slurp->loc_deltas.second;
+ dump () && dump ("Macro loc delta %d", slurp->loc_deltas.second);
+
+ for (unsigned ix = 0; ix != num_macros && !sec.get_overrun (); ix++)
+ {
+ unsigned lwm = sec.u ();
+ /* Record the current LWM so that the below read_location is
+ ok. */
+ macro_locs.first = lwm - slurp->loc_deltas.second;
+
+ unsigned n_tokens = sec.u ();
+ cpp_hashnode *node = sec.cpp_node ();
+ location_t exp_loc = read_location (sec);
+
+ const line_map_macro *macro
+ = linemap_enter_macro (line_table, node, exp_loc, n_tokens);
+ if (!macro)
+ /* We shouldn't run out of locations, as we checked that we
+ had enough before starting. */
+ break;
+
+ location_t *locs = macro->macro_locations;
+ location_t tok_loc = UNKNOWN_LOCATION;
+ unsigned count = sec.u ();
+ unsigned runs = 0;
+ for (unsigned jx = macro->n_tokens * 2; jx-- && !sec.get_overrun ();)
+ {
+ while (!count-- && !sec.get_overrun ())
+ {
+ runs++;
+ tok_loc = read_location (sec);
+ count = sec.u ();
+ }
+ locs[jx] = tok_loc;
+ }
+ if (count)
+ sec.set_overrun ();
+ dump (dumper::LOCATION)
+ && dump ("Macro:%u %I %u/%u*2 locations [%u,%u)",
+ ix, identifier (node), runs, n_tokens,
+ MAP_START_LOCATION (macro),
+ MAP_START_LOCATION (macro) + n_tokens);
+ }
+ location_t lwm = sec.u ();
+ macro_locs.first = lwm - slurp->loc_deltas.second;
+
+ dump () && dump ("Macro location lwm:%u", macro_locs.first);
+
+ if (propagated)
+ spans.close ();
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+
+ return true;
+}
+
+/* Serialize the definition of MACRO. */
+
+void
+module_state::write_define (bytes_out &sec, const cpp_macro *macro, bool located)
+{
+ sec.u (macro->count);
+
+ sec.b (macro->fun_like);
+ sec.b (macro->variadic);
+ sec.b (macro->syshdr);
+ sec.bflush ();
+
+ if (located)
+ write_location (sec, macro->line);
+ if (macro->fun_like)
+ {
+ sec.u (macro->paramc);
+ const cpp_hashnode *const *parms = macro->parm.params;
+ for (unsigned ix = 0; ix != macro->paramc; ix++)
+ sec.cpp_node (parms[ix]);
+ }
+
+ unsigned len = 0;
+ for (unsigned ix = 0; ix != macro->count; ix++)
+ {
+ const cpp_token *token = &macro->exp.tokens[ix];
+ if (located)
+ write_location (sec, token->src_loc);
+ sec.u (token->type);
+ sec.u (token->flags);
+ switch (cpp_token_val_index (token))
+ {
+ default:
+ gcc_unreachable ();
+
+ case CPP_TOKEN_FLD_ARG_NO:
+ /* An argument reference. */
+ sec.u (token->val.macro_arg.arg_no);
+ sec.cpp_node (token->val.macro_arg.spelling);
+ break;
+
+ case CPP_TOKEN_FLD_NODE:
+ /* An identifier. */
+ sec.cpp_node (token->val.node.node);
+ if (token->val.node.spelling == token->val.node.node)
+ /* The spelling will usually be the same. so optimize
+ that. */
+ sec.str (NULL, 0);
+ else
+ sec.cpp_node (token->val.node.spelling);
+ break;
+
+ case CPP_TOKEN_FLD_NONE:
+ break;
+
+ case CPP_TOKEN_FLD_STR:
+ /* A string, number or comment. Not always NUL terminated,
+ we stream out in a single contatenation with embedded
+ NULs as that's a safe default. */
+ len += token->val.str.len + 1;
+ sec.u (token->val.str.len);
+ break;
+
+ case CPP_TOKEN_FLD_SOURCE:
+ case CPP_TOKEN_FLD_TOKEN_NO:
+ case CPP_TOKEN_FLD_PRAGMA:
+ /* These do not occur inside a macro itself. */
+ gcc_unreachable ();
+ }
+ }
+
+ if (len)
+ {
+ char *ptr = reinterpret_cast<char *> (sec.buf (len));
+ len = 0;
+ for (unsigned ix = 0; ix != macro->count; ix++)
+ {
+ const cpp_token *token = &macro->exp.tokens[ix];
+ if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
+ {
+ memcpy (ptr + len, token->val.str.text,
+ token->val.str.len);
+ len += token->val.str.len;
+ ptr[len++] = 0;
+ }
+ }
+ }
+}
+
+/* Read a macro definition. */
+
+cpp_macro *
+module_state::read_define (bytes_in &sec, cpp_reader *reader, bool located) const
+{
+ unsigned count = sec.u ();
+ /* We rely on knowing cpp_reader's hash table is ident_hash, and
+ it's subobject allocator is stringpool_ggc_alloc and that is just
+ a wrapper for ggc_alloc_atomic. */
+ cpp_macro *macro
+ = (cpp_macro *)ggc_alloc_atomic (sizeof (cpp_macro)
+ + sizeof (cpp_token) * (count - !!count));
+ memset (macro, 0, sizeof (cpp_macro) + sizeof (cpp_token) * (count - !!count));
+
+ macro->count = count;
+ macro->kind = cmk_macro;
+ macro->imported_p = true;
+
+ macro->fun_like = sec.b ();
+ macro->variadic = sec.b ();
+ macro->syshdr = sec.b ();
+ sec.bflush ();
+
+ macro->line = located ? read_location (sec) : loc;
+
+ if (macro->fun_like)
+ {
+ unsigned paramc = sec.u ();
+ cpp_hashnode **params
+ = (cpp_hashnode **)ggc_alloc_atomic (sizeof (cpp_hashnode *) * paramc);
+ macro->paramc = paramc;
+ macro->parm.params = params;
+ for (unsigned ix = 0; ix != paramc; ix++)
+ params[ix] = sec.cpp_node ();
+ }
+
+ unsigned len = 0;
+ for (unsigned ix = 0; ix != count && !sec.get_overrun (); ix++)
+ {
+ cpp_token *token = &macro->exp.tokens[ix];
+ token->src_loc = located ? read_location (sec) : loc;
+ token->type = cpp_ttype (sec.u ());
+ token->flags = sec.u ();
+ switch (cpp_token_val_index (token))
+ {
+ default:
+ sec.set_overrun ();
+ break;
+
+ case CPP_TOKEN_FLD_ARG_NO:
+ /* An argument reference. */
+ {
+ unsigned arg_no = sec.u ();
+ if (arg_no - 1 >= macro->paramc)
+ sec.set_overrun ();
+ token->val.macro_arg.arg_no = arg_no;
+ token->val.macro_arg.spelling = sec.cpp_node ();
+ }
+ break;
+
+ case CPP_TOKEN_FLD_NODE:
+ /* An identifier. */
+ token->val.node.node = sec.cpp_node ();
+ token->val.node.spelling = sec.cpp_node ();
+ if (!token->val.node.spelling)
+ token->val.node.spelling = token->val.node.node;
+ break;
+
+ case CPP_TOKEN_FLD_NONE:
+ break;
+
+ case CPP_TOKEN_FLD_STR:
+ /* A string, number or comment. */
+ token->val.str.len = sec.u ();
+ len += token->val.str.len + 1;
+ break;
+ }
+ }
+
+ if (len)
+ if (const char *ptr = reinterpret_cast<const char *> (sec.buf (len)))
+ {
+ /* There should be a final NUL. */
+ if (ptr[len-1])
+ sec.set_overrun ();
+ /* cpp_alloc_token_string will add a final NUL. */
+ const unsigned char *buf
+ = cpp_alloc_token_string (reader, (const unsigned char *)ptr, len - 1);
+ len = 0;
+ for (unsigned ix = 0; ix != count && !sec.get_overrun (); ix++)
+ {
+ cpp_token *token = &macro->exp.tokens[ix];
+ if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
+ {
+ token->val.str.text = buf + len;
+ len += token->val.str.len;
+ if (buf[len++])
+ sec.set_overrun ();
+ }
+ }
+ }
+
+ if (sec.get_overrun ())
+ return NULL;
+ return macro;
+}
+
+/* Exported macro data. */
+struct macro_export {
+ cpp_macro *def;
+ location_t undef_loc;
+
+ macro_export ()
+ :def (NULL), undef_loc (UNKNOWN_LOCATION)
+ {
+ }
+};
+
+/* Imported macro data. */
+class macro_import {
+public:
+ struct slot {
+#if defined (WORDS_BIGENDIAN) && SIZEOF_VOID_P == 8
+ int offset;
+#endif
+ /* We need to ensure we don't use the LSB for representation, as
+ that's the union discriminator below. */
+ unsigned bits;
+
+#if !(defined (WORDS_BIGENDIAN) && SIZEOF_VOID_P == 8)
+ int offset;
+#endif
+
+ public:
+ enum Layout {
+ L_DEF = 1,
+ L_UNDEF = 2,
+ L_BOTH = 3,
+ L_MODULE_SHIFT = 2
+ };
+
+ public:
+ /* Not a regular ctor, because we put it in a union, and that's
+ not allowed in C++ 98. */
+ static slot ctor (unsigned module, unsigned defness)
+ {
+ gcc_checking_assert (defness);
+ slot s;
+ s.bits = defness | (module << L_MODULE_SHIFT);
+ s.offset = -1;
+ return s;
+ }
+
+ public:
+ unsigned get_defness () const
+ {
+ return bits & L_BOTH;
+ }
+ unsigned get_module () const
+ {
+ return bits >> L_MODULE_SHIFT;
+ }
+ void become_undef ()
+ {
+ bits &= ~unsigned (L_DEF);
+ bits |= unsigned (L_UNDEF);
+ }
+ };
+
+private:
+ typedef vec<slot, va_heap, vl_embed> ary_t;
+ union either {
+ /* Discriminated by bits 0|1 != 0. The expected case is that
+ there will be exactly one slot per macro, hence the effort of
+ packing that. */
+ ary_t *ary;
+ slot single;
+ } u;
+
+public:
+ macro_import ()
+ {
+ u.ary = NULL;
+ }
+
+private:
+ bool single_p () const
+ {
+ return u.single.bits & slot::L_BOTH;
+ }
+ bool occupied_p () const
+ {
+ return u.ary != NULL;
+ }
+
+public:
+ unsigned length () const
+ {
+ gcc_checking_assert (occupied_p ());
+ return single_p () ? 1 : u.ary->length ();
+ }
+ slot &operator[] (unsigned ix)
+ {
+ gcc_checking_assert (occupied_p ());
+ if (single_p ())
+ {
+ gcc_checking_assert (!ix);
+ return u.single;
+ }
+ else
+ return (*u.ary)[ix];
+ }
+
+public:
+ slot &exported ();
+ slot &append (unsigned module, unsigned defness);
+};
+
+/* O is a new import to append to the list for. If we're an empty
+ set, initialize us. */
+
+macro_import::slot &
+macro_import::append (unsigned module, unsigned defness)
+{
+ if (!occupied_p ())
+ {
+ u.single = slot::ctor (module, defness);
+ return u.single;
+ }
+ else
+ {
+ bool single = single_p ();
+ ary_t *m = single ? NULL : u.ary;
+ vec_safe_reserve (m, 1 + single);
+ if (single)
+ m->quick_push (u.single);
+ u.ary = m;
+ return *u.ary->quick_push (slot::ctor (module, defness));
+ }
+}
+
+/* We're going to export something. Make sure the first import slot
+ is us. */
+
+macro_import::slot &
+macro_import::exported ()
+{
+ if (occupied_p () && !(*this)[0].get_module ())
+ {
+ slot &res = (*this)[0];
+ res.bits |= slot::L_DEF;
+ return res;
+ }
+
+ slot *a = &append (0, slot::L_DEF);
+ if (!single_p ())
+ {
+ slot &f = (*this)[0];
+ std::swap (f, *a);
+ a = &f;
+ }
+ return *a;
+}
+
+/* The import (&exported) macros. cpp_hasnode's deferred field
+ indexes this array (offset by 1, so zero means 'not present'. */
+
+static vec<macro_import, va_heap, vl_embed> *macro_imports;
+
+/* The exported macros. A macro_import slot's zeroth element's offset
+ indexes this array. If the zeroth slot is not for module zero,
+ there is no export. */
+
+static vec<macro_export, va_heap, vl_embed> *macro_exports;
+
+/* The reachable set of header imports from this TU. */
+
+static GTY(()) bitmap headers;
+
+/* Get the (possibly empty) macro imports for NODE. */
+
+static macro_import &
+get_macro_imports (cpp_hashnode *node)
+{
+ if (node->deferred)
+ return (*macro_imports)[node->deferred - 1];
+
+ vec_safe_reserve (macro_imports, 1);
+ node->deferred = macro_imports->length () + 1;
+ return *vec_safe_push (macro_imports, macro_import ());
+}
+
+/* Get the macro export for export EXP of NODE. */
+
+static macro_export &
+get_macro_export (macro_import::slot &slot)
+{
+ if (slot.offset >= 0)
+ return (*macro_exports)[slot.offset];
+
+ vec_safe_reserve (macro_exports, 1);
+ slot.offset = macro_exports->length ();
+ return *macro_exports->quick_push (macro_export ());
+}
+
+/* If NODE is an exportable macro, add it to the export set. */
+
+static int
+maybe_add_macro (cpp_reader *, cpp_hashnode *node, void *data_)
+{
+ bool exporting = false;
+
+ if (cpp_user_macro_p (node))
+ if (cpp_macro *macro = node->value.macro)
+ /* Ignore imported, builtins, command line and forced header macros. */
+ if (!macro->imported_p
+ && !macro->lazy && macro->line >= spans.main_start ())
+ {
+ gcc_checking_assert (macro->kind == cmk_macro);
+ /* I don't want to deal with this corner case, that I suspect is
+ a devil's advocate reading of the standard. */
+ gcc_checking_assert (!macro->extra_tokens);
+
+ macro_import::slot &slot = get_macro_imports (node).exported ();
+ macro_export &exp = get_macro_export (slot);
+ exp.def = macro;
+ exporting = true;
+ }
+
+ if (!exporting && node->deferred)
+ {
+ macro_import &imports = (*macro_imports)[node->deferred - 1];
+ macro_import::slot &slot = imports[0];
+ if (!slot.get_module ())
+ {
+ gcc_checking_assert (slot.get_defness ());
+ exporting = true;
+ }
+ }
+
+ if (exporting)
+ static_cast<vec<cpp_hashnode *> *> (data_)->safe_push (node);
+
+ return 1; /* Don't stop. */
+}
+
+/* Order cpp_hashnodes A_ and B_ by their exported macro locations. */
+
+static int
+macro_loc_cmp (const void *a_, const void *b_)
+{
+ const cpp_hashnode *node_a = *(const cpp_hashnode *const *)a_;
+ macro_import &import_a = (*macro_imports)[node_a->deferred - 1];
+ const macro_export &export_a = (*macro_exports)[import_a[0].offset];
+ location_t loc_a = export_a.def ? export_a.def->line : export_a.undef_loc;
+
+ const cpp_hashnode *node_b = *(const cpp_hashnode *const *)b_;
+ macro_import &import_b = (*macro_imports)[node_b->deferred - 1];
+ const macro_export &export_b = (*macro_exports)[import_b[0].offset];
+ location_t loc_b = export_b.def ? export_b.def->line : export_b.undef_loc;
+
+ if (loc_a < loc_b)
+ return +1;
+ else if (loc_a > loc_b)
+ return -1;
+ else
+ return 0;
+}
+
+/* Write out the exported defines. This is two sections, one
+ containing the definitions, the other a table of node names. */
+
+unsigned
+module_state::write_macros (elf_out *to, cpp_reader *reader, unsigned *crc_p)
+{
+ dump () && dump ("Writing macros");
+ dump.indent ();
+
+ vec<cpp_hashnode *> macros;
+ macros.create (100);
+ cpp_forall_identifiers (reader, maybe_add_macro, &macros);
+
+ dump (dumper::MACRO) && dump ("No more than %u macros", macros.length ());
+
+ macros.qsort (macro_loc_cmp);
+
+ /* Write the defs */
+ bytes_out sec (to);
+ sec.begin ();
+
+ unsigned count = 0;
+ for (unsigned ix = macros.length (); ix--;)
+ {
+ cpp_hashnode *node = macros[ix];
+ macro_import::slot &slot = (*macro_imports)[node->deferred - 1][0];
+ gcc_assert (!slot.get_module () && slot.get_defness ());
+
+ macro_export &mac = (*macro_exports)[slot.offset];
+ gcc_assert (!!(slot.get_defness () & macro_import::slot::L_UNDEF)
+ == (mac.undef_loc != UNKNOWN_LOCATION)
+ && !!(slot.get_defness () & macro_import::slot::L_DEF)
+ == (mac.def != NULL));
+
+ if (IDENTIFIER_KEYWORD_P (identifier (node)))
+ {
+ warning_at (mac.def->line, 0,
+ "not exporting %<#define %E%> as it is a keyword",
+ identifier (node));
+ slot.offset = 0;
+ continue;
+ }
+
+ count++;
+ slot.offset = sec.pos;
+ dump (dumper::MACRO)
+ && dump ("Writing macro %s%s%s %I at %u",
+ slot.get_defness () & macro_import::slot::L_UNDEF
+ ? "#undef" : "",
+ slot.get_defness () == macro_import::slot::L_BOTH
+ ? " & " : "",
+ slot.get_defness () & macro_import::slot::L_DEF
+ ? "#define" : "",
+ identifier (node), slot.offset);
+ if (mac.undef_loc != UNKNOWN_LOCATION)
+ write_location (sec, mac.undef_loc);
+ if (mac.def)
+ write_define (sec, mac.def);
+ }
+ sec.end (to, to->name (MOD_SNAME_PFX ".def"), crc_p);
+
+ if (count)
+ {
+ /* Write the table. */
+ bytes_out sec (to);
+ sec.begin ();
+ sec.u (count);
+
+ for (unsigned ix = macros.length (); ix--;)
+ {
+ const cpp_hashnode *node = macros[ix];
+ macro_import::slot &slot = (*macro_imports)[node->deferred - 1][0];
+
+ if (slot.offset)
+ {
+ sec.cpp_node (node);
+ sec.u (slot.get_defness ());
+ sec.u (slot.offset);
+ }
+ }
+ sec.end (to, to->name (MOD_SNAME_PFX ".mac"), crc_p);
+ }
+
+ macros.release ();
+ dump.outdent ();
+ return count;
+}
+
+bool
+module_state::read_macros ()
+{
+ /* Get the def section. */
+ if (!slurp->macro_defs.begin (loc, from (), MOD_SNAME_PFX ".def"))
+ return false;
+
+ /* Get the tbl section, if there are defs. */
+ if (slurp->macro_defs.more_p ()
+ && !slurp->macro_tbl.begin (loc, from (), MOD_SNAME_PFX ".mac"))
+ return false;
+
+ return true;
+}
+
+/* Install the macro name table. */
+
+void
+module_state::install_macros ()
+{
+ bytes_in &sec = slurp->macro_tbl;
+ if (!sec.size)
+ return;
+
+ dump () && dump ("Reading macro table %M", this);
+ dump.indent ();
+
+ unsigned count = sec.u ();
+ dump () && dump ("%u macros", count);
+ while (count--)
+ {
+ cpp_hashnode *node = sec.cpp_node ();
+ macro_import &imp = get_macro_imports (node);
+ unsigned flags = sec.u () & macro_import::slot::L_BOTH;
+ if (!flags)
+ sec.set_overrun ();
+
+ if (sec.get_overrun ())
+ break;
+
+ macro_import::slot &slot = imp.append (mod, flags);
+ slot.offset = sec.u ();
+
+ dump (dumper::MACRO)
+ && dump ("Read %s macro %s%s%s %I at %u",
+ imp.length () > 1 ? "add" : "new",
+ flags & macro_import::slot::L_UNDEF ? "#undef" : "",
+ flags == macro_import::slot::L_BOTH ? " & " : "",
+ flags & macro_import::slot::L_DEF ? "#define" : "",
+ identifier (node), slot.offset);
+
+ /* We'll leak an imported definition's TOKEN_FLD_STR's data
+ here. But that only happens when we've had to resolve the
+ deferred macro before this import -- why are you doing
+ that? */
+ if (cpp_macro *cur = cpp_set_deferred_macro (node))
+ if (!cur->imported_p)
+ {
+ macro_import::slot &slot = imp.exported ();
+ macro_export &exp = get_macro_export (slot);
+ exp.def = cur;
+ dump (dumper::MACRO)
+ && dump ("Saving current #define %I", identifier (node));
+ }
+ }
+
+ /* We're now done with the table. */
+ elf_in::release (slurp->from, sec);
+
+ dump.outdent ();
+}
+
+/* Import the transitive macros. */
+
+void
+module_state::import_macros ()
+{
+ bitmap_ior_into (headers, slurp->headers);
+
+ bitmap_iterator bititer;
+ unsigned bitnum;
+ EXECUTE_IF_SET_IN_BITMAP (slurp->headers, 0, bitnum, bititer)
+ (*modules)[bitnum]->install_macros ();
+}
+
+/* NODE is being undefined at LOC. Record it in the export table, if
+ necessary. */
+
+void
+module_state::undef_macro (cpp_reader *, location_t loc, cpp_hashnode *node)
+{
+ if (!node->deferred)
+ /* The macro is not imported, so our undef is irrelevant. */
+ return;
+
+ unsigned n = dump.push (NULL);
+
+ macro_import::slot &slot = (*macro_imports)[node->deferred - 1].exported ();
+ macro_export &exp = get_macro_export (slot);
+
+ exp.undef_loc = loc;
+ slot.become_undef ();
+ exp.def = NULL;
+
+ dump (dumper::MACRO) && dump ("Recording macro #undef %I", identifier (node));
+
+ dump.pop (n);
+}
+
+/* NODE is a deferred macro node. Determine the definition and return
+ it, with NULL if undefined. May issue diagnostics.
+
+ This can leak memory, when merging declarations -- the string
+ contents (TOKEN_FLD_STR) of each definition are allocated in
+ unreclaimable cpp objstack. Only one will win. However, I do not
+ expect this to be common -- mostly macros have a single point of
+ definition. Perhaps we could restore the objstack to its position
+ after the first imported definition (if that wins)? The macros
+ themselves are GC'd. */
+
+cpp_macro *
+module_state::deferred_macro (cpp_reader *reader, location_t loc,
+ cpp_hashnode *node)
+{
+ macro_import &imports = (*macro_imports)[node->deferred - 1];
+
+ unsigned n = dump.push (NULL);
+ dump (dumper::MACRO) && dump ("Deferred macro %I", identifier (node));
+
+ bitmap visible (BITMAP_GGC_ALLOC ());
+
+ if (!((imports[0].get_defness () & macro_import::slot::L_UNDEF)
+ && !imports[0].get_module ()))
+ {
+ /* Calculate the set of visible header imports. */
+ bitmap_copy (visible, headers);
+ for (unsigned ix = imports.length (); ix--;)
+ {
+ const macro_import::slot &slot = imports[ix];
+ unsigned mod = slot.get_module ();
+ if ((slot.get_defness () & macro_import::slot::L_UNDEF)
+ && bitmap_bit_p (visible, mod))
+ {
+ bitmap arg = mod ? (*modules)[mod]->slurp->headers : headers;
+ bitmap_and_compl_into (visible, arg);
+ bitmap_set_bit (visible, mod);
+ }
+ }
+ }
+ bitmap_set_bit (visible, 0);
+
+ /* Now find the macros that are still visible. */
+ bool failed = false;
+ cpp_macro *def = NULL;
+ vec<macro_export> defs;
+ defs.create (imports.length ());
+ for (unsigned ix = imports.length (); ix--;)
+ {
+ const macro_import::slot &slot = imports[ix];
+ unsigned mod = slot.get_module ();
+ if (bitmap_bit_p (visible, mod))
+ {
+ macro_export *pushed = NULL;
+ if (mod)
+ {
+ const module_state *imp = (*modules)[mod];
+ bytes_in &sec = imp->slurp->macro_defs;
+ if (!sec.get_overrun ())
+ {
+ dump (dumper::MACRO)
+ && dump ("Reading macro %s%s%s %I module %M at %u",
+ slot.get_defness () & macro_import::slot::L_UNDEF
+ ? "#undef" : "",
+ slot.get_defness () == macro_import::slot::L_BOTH
+ ? " & " : "",
+ slot.get_defness () & macro_import::slot::L_DEF
+ ? "#define" : "",
+ identifier (node), imp, slot.offset);
+ sec.random_access (slot.offset);
+
+ macro_export exp;
+ if (slot.get_defness () & macro_import::slot::L_UNDEF)
+ exp.undef_loc = imp->read_location (sec);
+ if (slot.get_defness () & macro_import::slot::L_DEF)
+ exp.def = imp->read_define (sec, reader);
+ if (sec.get_overrun ())
+ error_at (loc, "macro definitions of %qE corrupted",
+ imp->name);
+ else
+ pushed = defs.quick_push (exp);
+ }
+ }
+ else
+ pushed = defs.quick_push ((*macro_exports)[slot.offset]);
+ if (pushed && pushed->def)
+ {
+ if (!def)
+ def = pushed->def;
+ else if (cpp_compare_macros (def, pushed->def))
+ failed = true;
+ }
+ }
+ }
+
+ if (failed)
+ {
+ /* If LOC is the first loc, this is the end of file check, which
+ is a warning. */
+ if (loc == MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (line_table, 0)))
+ warning_at (loc, OPT_Winvalid_imported_macros,
+ "inconsistent imported macro definition %qE",
+ identifier (node));
+ else
+ error_at (loc, "inconsistent imported macro definition %qE",
+ identifier (node));
+ for (unsigned ix = defs.length (); ix--;)
+ {
+ macro_export &exp = defs[ix];
+ if (exp.undef_loc)
+ inform (exp.undef_loc, "%<#undef %E%>", identifier (node));
+ if (exp.def)
+ inform (exp.def->line, "%<#define %s%>",
+ cpp_macro_definition (reader, node, exp.def));
+ }
+ def = NULL;
+ }
+
+ defs.release ();
+
+ dump.pop (n);
+
+ return def;
+}
+
+/* Stream the static aggregates. Sadly some headers (ahem:
+ iostream) contain static vars, and rely on them to run global
+ ctors. */
+unsigned
+module_state::write_inits (elf_out *to, depset::hash &table, unsigned *crc_ptr)
+{
+ if (!static_aggregates && !tls_aggregates)
+ return 0;
+
+ dump () && dump ("Writing initializers");
+ dump.indent ();
+
+ static_aggregates = nreverse (static_aggregates);
+ tls_aggregates = nreverse (tls_aggregates);
+
+ unsigned count = 0;
+ trees_out sec (to, this, table, ~0u);
+ sec.begin ();
+
+ tree list = static_aggregates;
+ for (int passes = 0; passes != 2; passes++)
+ {
+ for (tree init = list; init; init = TREE_CHAIN (init), count++)
+ if (TREE_LANG_FLAG_0 (init))
+ {
+ tree decl = TREE_VALUE (init);
+
+ dump ("Initializer:%u for %N", count, decl);
+ sec.tree_node (decl);
+ }
+
+ list = tls_aggregates;
+ }
+
+ sec.end (to, to->name (MOD_SNAME_PFX ".ini"), crc_ptr);
+ dump.outdent ();
+
+ return count;
+}
+
+bool
+module_state::read_inits (unsigned count)
+{
+ trees_in sec (this);
+ if (!sec.begin (loc, from (), from ()->find (MOD_SNAME_PFX ".ini")))
+ return false;
+ dump () && dump ("Reading %u initializers", count);
+ dump.indent ();
+
+ for (unsigned ix = 0; ix != count; ix++)
+ {
+ /* Merely referencing the decl causes its initializer to be read
+ and added to the correct list. */
+ tree decl = sec.tree_node ();
+
+ if (sec.get_overrun ())
+ break;
+ if (decl)
+ dump ("Initializer:%u for %N", count, decl);
+ }
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+ return true;
+}
+
+void
+module_state::write_counts (elf_out *to, unsigned counts[MSC_HWM],
+ unsigned *crc_ptr)
+{
+ bytes_out cfg (to);
+
+ cfg.begin ();
+
+ for (unsigned ix = MSC_HWM; ix--;)
+ cfg.u (counts[ix]);
+
+ if (dump ())
+ {
+ dump ("Cluster sections are [%u,%u)",
+ counts[MSC_sec_lwm], counts[MSC_sec_hwm]);
+ dump ("Bindings %u", counts[MSC_bindings]);
+ dump ("Pendings %u", counts[MSC_pendings]);
+ dump ("Entities %u", counts[MSC_entities]);
+ dump ("Namespaces %u", counts[MSC_namespaces]);
+ dump ("Macros %u", counts[MSC_macros]);
+ dump ("Initializers %u", counts[MSC_inits]);
+ }
+
+ cfg.end (to, to->name (MOD_SNAME_PFX ".cnt"), crc_ptr);
+}
+
+bool
+module_state::read_counts (unsigned counts[MSC_HWM])
+{
+ bytes_in cfg;
+
+ if (!cfg.begin (loc, from (), MOD_SNAME_PFX ".cnt"))
+ return false;
+
+ for (unsigned ix = MSC_HWM; ix--;)
+ counts[ix] = cfg.u ();
+
+ if (dump ())
+ {
+ dump ("Declaration sections are [%u,%u)",
+ counts[MSC_sec_lwm], counts[MSC_sec_hwm]);
+ dump ("Bindings %u", counts[MSC_bindings]);
+ dump ("Pendings %u", counts[MSC_pendings]);
+ dump ("Entities %u", counts[MSC_entities]);
+ dump ("Namespaces %u", counts[MSC_namespaces]);
+ dump ("Macros %u", counts[MSC_macros]);
+ dump ("Initializers %u", counts[MSC_inits]);
+ }
+
+ return cfg.end (from ());
+}
+
+/* Tool configuration: MOD_SNAME_PFX .config
+
+ This is data that confirms current state (or fails). */
+
+void
+module_state::write_config (elf_out *to, module_state_config &config,
+ unsigned inner_crc)
+{
+ bytes_out cfg (to);
+
+ cfg.begin ();
+
+ /* Write version and inner crc as u32 values, for easier
+ debug inspection. */
+ dump () && dump ("Writing version=%V, inner_crc=%x",
+ MODULE_VERSION, inner_crc);
+ cfg.u32 (unsigned (MODULE_VERSION));
+ cfg.u32 (inner_crc);
+
+ cfg.u (to->name (is_header () ? "" : get_flatname ()));
+
+ /* Configuration. */
+ dump () && dump ("Writing target='%s', host='%s'",
+ TARGET_MACHINE, HOST_MACHINE);
+ unsigned target = to->name (TARGET_MACHINE);
+ unsigned host = (!strcmp (TARGET_MACHINE, HOST_MACHINE)
+ ? target : to->name (HOST_MACHINE));
+ cfg.u (target);
+ cfg.u (host);
+
+ cfg.str (config.dialect_str);
+ cfg.u (extensions);
+
+ /* Global tree information. We write the globals crc separately,
+ rather than mix it directly into the overall crc, as it is used
+ to ensure data match between instances of the compiler, not
+ integrity of the file. */
+ dump () && dump ("Writing globals=%u, crc=%x",
+ fixed_trees->length (), global_crc);
+ cfg.u (fixed_trees->length ());
+ cfg.u32 (global_crc);
+
+ if (is_partition ())
+ cfg.u (is_interface ());
+
+ cfg.u (config.num_imports);
+ cfg.u (config.num_partitions);
+
+ cfg.u (config.ordinary_locs);
+ cfg.u (config.macro_locs);
+ cfg.u (config.ordinary_loc_align);
+
+ /* Now generate CRC, we'll have incorporated the inner CRC because
+ of its serialization above. */
+ cfg.end (to, to->name (MOD_SNAME_PFX ".cfg"), &crc);
+ dump () && dump ("Writing CRC=%x", crc);
+}
+
+void
+module_state::note_cmi_name ()
+{
+ if (!cmi_noted_p && filename)
+ {
+ cmi_noted_p = true;
+ inform (loc, "compiled module file is %qs",
+ maybe_add_cmi_prefix (filename));
+ }
+}
+
+bool
+module_state::read_config (module_state_config &config)
+{
+ bytes_in cfg;
+
+ if (!cfg.begin (loc, from (), MOD_SNAME_PFX ".cfg"))
+ return false;
+
+ /* Check version. */
+ unsigned my_ver = MODULE_VERSION;
+ unsigned their_ver = cfg.u32 ();
+ dump () && dump (my_ver == their_ver ? "Version %V"
+ : "Expecting %V found %V", my_ver, their_ver);
+ if (their_ver != my_ver)
+ {
+ /* The compiler versions differ. Close enough? */
+ verstr_t my_string, their_string;
+
+ version2string (my_ver, my_string);
+ version2string (their_ver, their_string);
+
+ /* Reject when either is non-experimental or when experimental
+ major versions differ. */
+ bool reject_p = ((!IS_EXPERIMENTAL (my_ver)
+ || !IS_EXPERIMENTAL (their_ver)
+ || MODULE_MAJOR (my_ver) != MODULE_MAJOR (their_ver))
+ /* The 'I know what I'm doing' switch. */
+ && !flag_module_version_ignore);
+ bool inform_p = true;
+ if (reject_p)
+ {
+ cfg.set_overrun ();
+ error_at (loc, "compiled module is %sversion %s",
+ IS_EXPERIMENTAL (their_ver) ? "experimental " : "",
+ their_string);
+ }
+ else
+ inform_p = warning_at (loc, 0, "compiled module is %sversion %s",
+ IS_EXPERIMENTAL (their_ver) ? "experimental " : "",
+ their_string);
+
+ if (inform_p)
+ {
+ inform (loc, "compiler is %sversion %s%s%s",
+ IS_EXPERIMENTAL (my_ver) ? "experimental " : "",
+ my_string,
+ reject_p ? "" : flag_module_version_ignore
+ ? ", be it on your own head!" : ", close enough?",
+ reject_p ? "" : " \xc2\xaf\\_(\xe3\x83\x84)_/\xc2\xaf");
+ note_cmi_name ();
+ }
+
+ if (reject_p)
+ goto done;
+ }
+
+ /* We wrote the inner crc merely to merge it, so simply read it
+ back and forget it. */
+ cfg.u32 ();
+
+ /* Check module name. */
+ {
+ const char *their_name = from ()->name (cfg.u ());
+ const char *our_name = "";
+
+ if (!is_header ())
+ our_name = get_flatname ();
+
+ /* Header units can be aliased, so name checking is
+ inappropriate. */
+ if (0 != strcmp (their_name, our_name))
+ {
+ error_at (loc,
+ their_name[0] && our_name[0] ? G_("module %qs found")
+ : their_name[0]
+ ? G_("header module expected, module %qs found")
+ : G_("module %qs expected, header module found"),
+ their_name[0] ? their_name : our_name);
+ cfg.set_overrun ();
+ goto done;
+ }
+ }
+
+ /* Check the CRC after the above sanity checks, so that the user is
+ clued in. */
+ {
+ unsigned e_crc = crc;
+ crc = cfg.get_crc ();
+ dump () && dump ("Reading CRC=%x", crc);
+ if (!is_direct () && crc != e_crc)
+ {
+ error_at (loc, "module %qs CRC mismatch", get_flatname ());
+ cfg.set_overrun ();
+ goto done;
+ }
+ }
+
+ /* Check target & host. */
+ {
+ const char *their_target = from ()->name (cfg.u ());
+ const char *their_host = from ()->name (cfg.u ());
+ dump () && dump ("Read target='%s', host='%s'", their_target, their_host);
+ if (strcmp (their_target, TARGET_MACHINE)
+ || strcmp (their_host, HOST_MACHINE))
+ {
+ error_at (loc, "target & host is %qs:%qs, expected %qs:%qs",
+ their_target, TARGET_MACHINE, their_host, HOST_MACHINE);
+ cfg.set_overrun ();
+ goto done;
+ }
+ }
+
+ /* Check compilation dialect. This must match. */
+ {
+ const char *their_dialect = cfg.str ();
+ if (strcmp (their_dialect, config.dialect_str))
+ {
+ error_at (loc, "language dialect differs %qs, expected %qs",
+ their_dialect, config.dialect_str);
+ cfg.set_overrun ();
+ goto done;
+ }
+ }
+
+ /* Check for extensions. If they set any, we must have them set
+ too. */
+ {
+ unsigned ext = cfg.u ();
+ unsigned allowed = (flag_openmp ? SE_OPENMP : 0);
+
+ if (unsigned bad = ext & ~allowed)
+ {
+ if (bad & SE_OPENMP)
+ error_at (loc, "module contains OpenMP, use %<-fopenmp%> to enable");
+ cfg.set_overrun ();
+ goto done;
+ }
+ extensions = ext;
+ }
+
+ /* Check global trees. */
+ {
+ unsigned their_fixed_length = cfg.u ();
+ unsigned their_fixed_crc = cfg.u32 ();
+ dump () && dump ("Read globals=%u, crc=%x",
+ their_fixed_length, their_fixed_crc);
+ if (!flag_preprocess_only
+ && (their_fixed_length != fixed_trees->length ()
+ || their_fixed_crc != global_crc))
+ {
+ error_at (loc, "fixed tree mismatch");
+ cfg.set_overrun ();
+ goto done;
+ }
+ }
+
+ /* All non-partitions are interfaces. */
+ interface_p = !is_partition () || cfg.u ();
+
+ config.num_imports = cfg.u ();
+ config.num_partitions = cfg.u ();
+
+ config.ordinary_locs = cfg.u ();
+ config.macro_locs = cfg.u ();
+ config.ordinary_loc_align = cfg.u ();
+
+ done:
+ return cfg.end (from ());
+}
+
+/* Use ELROND format to record the following sections:
+ qualified-names : binding value(s)
+ MOD_SNAME_PFX.README : human readable, strings
+ MOD_SNAME_PFX.ENV : environment strings, strings
+ MOD_SNAME_PFX.nms : namespace hierarchy
+ MOD_SNAME_PFX.bnd : binding table
+ MOD_SNAME_PFX.spc : specialization table
+ MOD_SNAME_PFX.imp : import table
+ MOD_SNAME_PFX.ent : entity table
+ MOD_SNAME_PFX.prt : partitions table
+ MOD_SNAME_PFX.olm : ordinary line maps
+ MOD_SNAME_PFX.mlm : macro line maps
+ MOD_SNAME_PFX.def : macro definitions
+ MOD_SNAME_PFX.mac : macro index
+ MOD_SNAME_PFX.ini : inits
+ MOD_SNAME_PFX.cnt : counts
+ MOD_SNAME_PFX.cfg : config data
+*/
+
+void
+module_state::write (elf_out *to, cpp_reader *reader)
+{
+ /* Figure out remapped module numbers, which might elide
+ partitions. */
+ bitmap partitions = NULL;
+ if (!is_header () && !is_partition ())
+ partitions = BITMAP_GGC_ALLOC ();
+
+ unsigned mod_hwm = 1;
+ for (unsigned ix = 1; ix != modules->length (); ix++)
+ {
+ module_state *imp = (*modules)[ix];
+
+ /* Promote any non-partition direct import from a partition, unless
+ we're a partition. */
+ if (!is_partition () && !imp->is_partition ()
+ && imp->is_partition_direct ())
+ imp->directness = MD_PURVIEW_DIRECT;
+
+ /* Write any import that is not a partition, unless we're a
+ partition. */
+ if (!partitions || !imp->is_partition ())
+ imp->remap = mod_hwm++;
+ else
+ {
+ dump () && dump ("Partition %M %u", imp, ix);
+ bitmap_set_bit (partitions, ix);
+ imp->remap = 0;
+ /* All interface partitions must be exported. */
+ if (imp->is_interface () && !bitmap_bit_p (exports, imp->mod))
+ {
+ error_at (imp->loc, "interface partition is not exported");
+ bitmap_set_bit (exports, imp->mod);
+ }
+
+ /* All the partition entities should have been loaded when
+ loading the partition. */
+ if (CHECKING_P)
+ for (unsigned jx = 0; jx != imp->entity_num; jx++)
+ {
+ binding_slot *slot = &(*entity_ary)[imp->entity_lwm + jx];
+ gcc_checking_assert (!slot->is_lazy ());
+ }
+ }
+ }
+
+ if (partitions && bitmap_empty_p (partitions))
+ /* No partitions present. */
+ partitions = nullptr;
+
+ /* Find the set of decls we must write out. */
+ depset::hash table (DECL_NAMESPACE_BINDINGS (global_namespace)->size () * 8);
+ /* Add the specializations before the writables, so that we can
+ detect injected friend specializations. */
+ table.add_specializations (true);
+ table.add_specializations (false);
+ if (partial_specializations)
+ {
+ table.add_partial_entities (partial_specializations);
+ partial_specializations = NULL;
+ }
+ table.add_namespace_entities (global_namespace, partitions);
+ if (class_members)
+ {
+ table.add_class_entities (class_members);
+ class_members = NULL;
+ }
+
+ /* Now join everything up. */
+ table.find_dependencies ();
+
+ if (!table.finalize_dependencies ())
+ {
+ to->set_error ();
+ return;
+ }
+
+#if CHECKING_P
+ /* We're done verifying at-most once reading, reset to verify
+ at-most once writing. */
+ note_defs = note_defs_table_t::create_ggc (1000);
+#endif
+
+ /* Determine Strongy Connected Components. */
+ vec<depset *> sccs = table.connect ();
+
+ unsigned crc = 0;
+ module_state_config config;
+ location_map_info map_info = write_prepare_maps (&config);
+ unsigned counts[MSC_HWM];
+
+ config.num_imports = mod_hwm;
+ config.num_partitions = modules->length () - mod_hwm;
+ memset (counts, 0, sizeof (counts));
+
+ /* depset::cluster is the cluster number,
+ depset::section is unspecified scratch value.
+
+ The following loops make use of the tarjan property that
+ dependencies will be earlier in the SCCS array. */
+
+ /* This first loop determines the number of depsets in each SCC, and
+ also the number of namespaces we're dealing with. During the
+ loop, the meaning of a couple of depset fields now change:
+
+ depset::cluster -> size_of cluster, if first of cluster & !namespace
+ depset::section -> section number of cluster (if !namespace). */
+
+ unsigned n_spaces = 0;
+ counts[MSC_sec_lwm] = counts[MSC_sec_hwm] = to->get_section_limit ();
+ for (unsigned size, ix = 0; ix < sccs.length (); ix += size)
+ {
+ depset **base = &sccs[ix];
+
+ if (base[0]->get_entity_kind () == depset::EK_NAMESPACE)
+ {
+ n_spaces++;
+ size = 1;
+ }
+ else
+ {
+ /* Count the members in this cluster. */
+ for (size = 1; ix + size < sccs.length (); size++)
+ if (base[size]->cluster != base[0]->cluster)
+ break;
+
+ for (unsigned jx = 0; jx != size; jx++)
+ {
+ /* Set the section number. */
+ base[jx]->cluster = ~(~0u >> 1); /* A bad value. */
+ base[jx]->section = counts[MSC_sec_hwm];
+ }
+
+ /* Save the size in the first member's cluster slot. */
+ base[0]->cluster = size;
+
+ counts[MSC_sec_hwm]++;
+ }
+ }
+
+ /* Write the clusters. Namespace decls are put in the spaces array.
+ The meaning of depset::cluster changes to provide the
+ unnamed-decl count of the depset's decl (and remains zero for
+ non-decls and non-unnamed). */
+ unsigned bytes = 0;
+ vec<depset *> spaces;
+ spaces.create (n_spaces);
+
+ for (unsigned size, ix = 0; ix < sccs.length (); ix += size)
+ {
+ depset **base = &sccs[ix];
+
+ if (base[0]->get_entity_kind () == depset::EK_NAMESPACE)
+ {
+ tree decl = base[0]->get_entity ();
+ if (decl == global_namespace)
+ base[0]->cluster = 0;
+ else if (!base[0]->is_import ())
+ {
+ base[0]->cluster = counts[MSC_entities]++;
+ spaces.quick_push (base[0]);
+ counts[MSC_namespaces]++;
+ if (CHECKING_P)
+ {
+ /* Add it to the entity map, such that we can tell it is
+ part of us. */
+ bool existed;
+ unsigned *slot = &entity_map->get_or_insert
+ (DECL_UID (decl), &existed);
+ if (existed)
+ /* It must have come from a partition. */
+ gcc_checking_assert
+ (import_entity_module (*slot)->is_partition ());
+ *slot = ~base[0]->cluster;
+ }
+ dump (dumper::CLUSTER) && dump ("Cluster namespace %N", decl);
+ }
+ size = 1;
+ }
+ else
+ {
+ size = base[0]->cluster;
+
+ /* Cluster is now used to number entities. */
+ base[0]->cluster = ~(~0u >> 1); /* A bad value. */
+
+ sort_cluster (&table, base, size);
+
+ /* Record the section for consistency checking during stream
+ out -- we don't want to start writing decls in different
+ sections. */
+ table.section = base[0]->section;
+ bytes += write_cluster (to, base, size, table, counts, &crc);
+ table.section = 0;
+ }
+ }
+
+ /* We'd better have written as many sections and found as many
+ namespaces as we predicted. */
+ gcc_assert (counts[MSC_sec_hwm] == to->get_section_limit ()
+ && spaces.length () == counts[MSC_namespaces]);
+
+ /* Write the entitites. None happens if we contain namespaces or
+ nothing. */
+ if (counts[MSC_entities])
+ write_entities (to, sccs, counts[MSC_entities], &crc);
+
+ /* Write the namespaces. */
+ if (counts[MSC_namespaces])
+ write_namespaces (to, spaces, counts[MSC_namespaces], &crc);
+
+ /* Write the bindings themselves. */
+ counts[MSC_bindings] = write_bindings (to, sccs, &crc);
+
+ /* Write the unnamed. */
+ if (counts[MSC_pendings])
+ write_pendings (to, sccs, table, counts[MSC_pendings], &crc);
+
+ /* Write the import table. */
+ if (config.num_imports > 1)
+ write_imports (to, &crc);
+
+ /* Write elided partition table. */
+ if (config.num_partitions)
+ write_partitions (to, config.num_partitions, &crc);
+
+ /* Write the line maps. */
+ write_ordinary_maps (to, map_info, &config, config.num_partitions, &crc);
+ write_macro_maps (to, map_info, &config, &crc);
+
+ if (is_header ())
+ {
+ counts[MSC_macros] = write_macros (to, reader, &crc);
+ counts[MSC_inits] = write_inits (to, table, &crc);
+ }
+
+ unsigned clusters = counts[MSC_sec_hwm] - counts[MSC_sec_lwm];
+ dump () && dump ("Wrote %u clusters, average %u bytes/cluster",
+ clusters, (bytes + clusters / 2) / (clusters + !clusters));
+
+ write_counts (to, counts, &crc);
+
+ /* And finish up. */
+ write_config (to, config, crc);
+
+ spaces.release ();
+ sccs.release ();
+
+ /* Human-readable info. */
+ write_readme (to, reader, config.dialect_str, extensions);
+
+ // FIXME:QOI: Have a command line switch to control more detailed
+ // information (which might leak data you do not want to leak).
+ // Perhaps (some of) the write_readme contents should also be
+ // so-controlled.
+ if (false)
+ write_env (to);
+
+ trees_out::instrument ();
+ dump () && dump ("Wrote %u sections", to->get_section_limit ());
+}
+
+/* Initial read of a CMI. Checks config, loads up imports and line
+ maps. */
+
+bool
+module_state::read_initial (cpp_reader *reader)
+{
+ module_state_config config;
+ bool ok = true;
+
+ if (ok && !from ()->begin (loc))
+ ok = false;
+
+ if (ok && !read_config (config))
+ ok = false;
+
+ bool have_locs = ok && read_prepare_maps (&config);
+
+ /* Ordinary maps before the imports. */
+ if (have_locs && !read_ordinary_maps ())
+ ok = false;
+
+ /* Allocate the REMAP vector. */
+ slurp->alloc_remap (config.num_imports);
+
+ if (ok)
+ {
+ /* Read the import table. Decrement current to stop this CMI
+ from being evicted during the import. */
+ slurp->current--;
+ if (config.num_imports > 1 && !read_imports (reader, line_table))
+ ok = false;
+ slurp->current++;
+ }
+
+ /* Read the elided partition table, if we're the primary partition. */
+ if (ok && config.num_partitions && is_module ()
+ && !read_partitions (config.num_partitions))
+ ok = false;
+
+ /* Determine the module's number. */
+ gcc_checking_assert (mod == MODULE_UNKNOWN);
+ gcc_checking_assert (this != (*modules)[0]);
+
+ /* We'll run out of other resources before we run out of module
+ indices. */
+ mod = modules->length ();
+ vec_safe_push (modules, this);
+
+ /* We always import and export ourselves. */
+ bitmap_set_bit (imports, mod);
+ bitmap_set_bit (exports, mod);
+
+ if (ok)
+ (*slurp->remap)[0] = mod << 1;
+ dump () && dump ("Assigning %M module number %u", this, mod);
+
+ /* We should not have been frozen during the importing done by
+ read_config. */
+ gcc_assert (!from ()->is_frozen ());
+
+ /* Macro maps after the imports. */
+ if (ok && have_locs && !read_macro_maps ())
+ ok = false;
+
+ gcc_assert (slurp->current == ~0u);
+ return ok;
+}
+
+/* Read a preprocessor state. */
+
+bool
+module_state::read_preprocessor (bool outermost)
+{
+ gcc_checking_assert (is_header () && slurp
+ && slurp->remap_module (0) == mod);
+
+ if (loadedness == ML_PREPROCESSOR)
+ return !(from () && from ()->get_error ());
+
+ bool ok = true;
+
+ /* Read direct header imports. */
+ unsigned len = slurp->remap->length ();
+ for (unsigned ix = 1; ok && ix != len; ix++)
+ {
+ unsigned map = (*slurp->remap)[ix];
+ if (map & 1)
+ {
+ module_state *import = (*modules)[map >> 1];
+ if (import->is_header ())
+ {
+ ok = import->read_preprocessor (false);
+ bitmap_ior_into (slurp->headers, import->slurp->headers);
+ }
+ }
+ }
+
+ /* Record as a direct header. */
+ if (ok)
+ bitmap_set_bit (slurp->headers, mod);
+
+ if (ok && !read_macros ())
+ ok = false;
+
+ loadedness = ML_PREPROCESSOR;
+ announce ("macros");
+
+ if (flag_preprocess_only)
+ /* We're done with the string table. */
+ from ()->release ();
+
+ return check_read (outermost, ok);
+}
+
+static unsigned lazy_snum;
+
+static bool
+recursive_lazy (unsigned snum = ~0u)
+{
+ if (lazy_snum)
+ {
+ error_at (input_location, "recursive lazy load");
+ return true;
+ }
+
+ lazy_snum = snum;
+ return false;
+}
+
+/* Read language state. */
+
+bool
+module_state::read_language (bool outermost)
+{
+ gcc_checking_assert (!lazy_snum);
+
+ if (loadedness == ML_LANGUAGE)
+ return !(slurp && from () && from ()->get_error ());
+
+ gcc_checking_assert (slurp && slurp->current == ~0u
+ && slurp->remap_module (0) == mod);
+
+ bool ok = true;
+
+ /* Read direct imports. */
+ unsigned len = slurp->remap->length ();
+ for (unsigned ix = 1; ok && ix != len; ix++)
+ {
+ unsigned map = (*slurp->remap)[ix];
+ if (map & 1)
+ {
+ module_state *import = (*modules)[map >> 1];
+ if (!import->read_language (false))
+ ok = false;
+ }
+ }
+
+ unsigned counts[MSC_HWM];
+
+ if (ok && !read_counts (counts))
+ ok = false;
+
+ function_depth++; /* Prevent unexpected GCs. */
+
+ /* Read the entity table. */
+ entity_lwm = vec_safe_length (entity_ary);
+ if (ok && counts[MSC_entities]
+ && !read_entities (counts[MSC_entities],
+ counts[MSC_sec_lwm], counts[MSC_sec_hwm]))
+ ok = false;
+
+ /* Read the namespace hierarchy. */
+ if (ok && counts[MSC_namespaces]
+ && !read_namespaces (counts[MSC_namespaces]))
+ ok = false;
+
+ if (ok && !read_bindings (counts[MSC_bindings],
+ counts[MSC_sec_lwm], counts[MSC_sec_hwm]))
+ ok = false;
+
+ /* And unnamed. */
+ if (ok && counts[MSC_pendings] && !read_pendings (counts[MSC_pendings]))
+ ok = false;
+
+ if (ok)
+ {
+ slurp->remaining = counts[MSC_sec_hwm] - counts[MSC_sec_lwm];
+ available_clusters += counts[MSC_sec_hwm] - counts[MSC_sec_lwm];
+ }
+
+ if (!flag_module_lazy
+ || (is_partition ()
+ && module_interface_p ()
+ && !module_partition_p ()))
+ {
+ /* Read the sections in forward order, so that dependencies are read
+ first. See note about tarjan_connect. */
+ ggc_collect ();
+
+ lazy_snum = ~0u;
+
+ unsigned hwm = counts[MSC_sec_hwm];
+ for (unsigned ix = counts[MSC_sec_lwm]; ok && ix != hwm; ix++)
+ {
+ if (!load_section (ix, NULL))
+ {
+ ok = false;
+ break;
+ }
+ ggc_collect ();
+ }
+
+ lazy_snum = 0;
+
+ if (ok && CHECKING_P)
+ for (unsigned ix = 0; ix != entity_num; ix++)
+ gcc_assert (!(*entity_ary)[ix + entity_lwm].is_lazy ());
+ }
+
+ // If the import is a header-unit, we need to register initializers
+ // of any static objects it contains (looking at you _Ioinit).
+ // Notice, the ordering of these initializers will be that of a
+ // dynamic initializer at this point in the current TU. (Other
+ // instances of these objects in other TUs will be initialized as
+ // part of that TU's global initializers.)
+ if (ok && counts[MSC_inits] && !read_inits (counts[MSC_inits]))
+ ok = false;
+
+ function_depth--;
+
+ announce (flag_module_lazy ? "lazy" : "imported");
+ loadedness = ML_LANGUAGE;
+
+ gcc_assert (slurp->current == ~0u);
+
+ /* We're done with the string table. */
+ from ()->release ();
+
+ return check_read (outermost, ok);
+}
+
+bool
+module_state::maybe_defrost ()
+{
+ bool ok = true;
+ if (from ()->is_frozen ())
+ {
+ if (lazy_open >= lazy_limit)
+ freeze_an_elf ();
+ dump () && dump ("Defrosting '%s'", filename);
+ ok = from ()->defrost (maybe_add_cmi_prefix (filename));
+ lazy_open++;
+ }
+
+ return ok;
+}
+
+/* Load section SNUM, dealing with laziness. It doesn't matter if we
+ have multiple concurrent loads, because we do not use TREE_VISITED
+ when reading back in. */
+
+bool
+module_state::load_section (unsigned snum, binding_slot *mslot)
+{
+ if (from ()->get_error ())
+ return false;
+
+ if (snum >= slurp->current)
+ from ()->set_error (elf::E_BAD_LAZY);
+ else if (maybe_defrost ())
+ {
+ unsigned old_current = slurp->current;
+ slurp->current = snum;
+ slurp->lru = 0; /* Do not swap out. */
+ slurp->remaining--;
+ read_cluster (snum);
+ slurp->lru = ++lazy_lru;
+ slurp->current = old_current;
+ }
+
+ if (mslot && mslot->is_lazy ())
+ {
+ /* Oops, the section didn't set this slot. */
+ from ()->set_error (elf::E_BAD_DATA);
+ *mslot = NULL_TREE;
+ }
+
+ bool ok = !from ()->get_error ();
+ if (!ok)
+ {
+ error_at (loc, "failed to read compiled module cluster %u: %s",
+ snum, from ()->get_error (filename));
+ note_cmi_name ();
+ }
+
+ maybe_completed_reading ();
+
+ return ok;
+}
+
+void
+module_state::maybe_completed_reading ()
+{
+ if (loadedness == ML_LANGUAGE && slurp->current == ~0u && !slurp->remaining)
+ {
+ lazy_open--;
+ /* We no longer need the macros, all tokenizing has been done. */
+ slurp->release_macros ();
+
+ from ()->end ();
+ slurp->close ();
+ slurped ();
+ }
+}
+
+/* After a reading operation, make sure things are still ok. If not,
+ emit an error and clean up. */
+
+bool
+module_state::check_read (bool outermost, bool ok)
+{
+ gcc_checking_assert (!outermost || slurp->current == ~0u);
+
+ if (!ok)
+ from ()->set_error ();
+
+ if (int e = from ()->get_error ())
+ {
+ error_at (loc, "failed to read compiled module: %s",
+ from ()->get_error (filename));
+ note_cmi_name ();
+
+ if (e == EMFILE
+ || e == ENFILE
+#if MAPPED_READING
+ || e == ENOMEM
+#endif
+ || false)
+ inform (loc, "consider using %<-fno-module-lazy%>,"
+ " increasing %<-param-lazy-modules=%u%> value,"
+ " or increasing the per-process file descriptor limit",
+ param_lazy_modules);
+ else if (e == ENOENT)
+ inform (loc, "imports must be built before being imported");
+
+ if (outermost)
+ fatal_error (loc, "returning to the gate for a mechanical issue");
+
+ ok = false;
+ }
+
+ maybe_completed_reading ();
+
+ return ok;
+}
+
+/* Return the IDENTIFIER_NODE naming module IX. This is the name
+ including dots. */
+
+char const *
+module_name (unsigned ix, bool header_ok)
+{
+ if (modules)
+ {
+ module_state *imp = (*modules)[ix];
+
+ if (ix && !imp->name)
+ imp = imp->parent;
+
+ if (header_ok || !imp->is_header ())
+ return imp->get_flatname ();
+ }
+
+ return NULL;
+}
+
+/* Return the bitmap describing what modules are imported. Remember,
+ we always import ourselves. */
+
+bitmap
+get_import_bitmap ()
+{
+ return (*modules)[0]->imports;
+}
+
+/* Return the visible imports and path of instantiation for an
+ instantiation at TINST. If TINST is nullptr, we're not in an
+ instantiation, and thus will return the visible imports of the
+ current TU (and NULL *PATH_MAP_P). We cache the information on
+ the tinst level itself. */
+
+static bitmap
+path_of_instantiation (tinst_level *tinst, bitmap *path_map_p)
+{
+ gcc_checking_assert (modules_p ());
+
+ if (!tinst)
+ {
+ /* Not inside an instantiation, just the regular case. */
+ *path_map_p = nullptr;
+ return get_import_bitmap ();
+ }
+
+ if (!tinst->path)
+ {
+ /* Calculate. */
+ bitmap visible = path_of_instantiation (tinst->next, path_map_p);
+ bitmap path_map = *path_map_p;
+
+ if (!path_map)
+ {
+ path_map = BITMAP_GGC_ALLOC ();
+ bitmap_set_bit (path_map, 0);
+ }
+
+ tree decl = tinst->tldcl;
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_PURPOSE (decl);
+ if (TYPE_P (decl))
+ decl = TYPE_NAME (decl);
+
+ if (unsigned mod = get_originating_module (decl))
+ if (!bitmap_bit_p (path_map, mod))
+ {
+ /* This is brand new information! */
+ bitmap new_path = BITMAP_GGC_ALLOC ();
+ bitmap_copy (new_path, path_map);
+ bitmap_set_bit (new_path, mod);
+ path_map = new_path;
+
+ bitmap imports = (*modules)[mod]->imports;
+ if (bitmap_intersect_compl_p (imports, visible))
+ {
+ /* IMPORTS contains additional modules to VISIBLE. */
+ bitmap new_visible = BITMAP_GGC_ALLOC ();
+
+ bitmap_ior (new_visible, visible, imports);
+ visible = new_visible;
+ }
+ }
+
+ tinst->path = path_map;
+ tinst->visible = visible;
+ }
+
+ *path_map_p = tinst->path;
+ return tinst->visible;
+}
+
+/* Return the bitmap describing what modules are visible along the
+ path of instantiation. If we're not an instantiation, this will be
+ the visible imports of the TU. *PATH_MAP_P is filled in with the
+ modules owning the instantiation path -- we see the module-linkage
+ entities of those modules. */
+
+bitmap
+visible_instantiation_path (bitmap *path_map_p)
+{
+ if (!modules_p ())
+ return NULL;
+
+ return path_of_instantiation (current_instantiation (), path_map_p);
+}
+
+/* We've just directly imported IMPORT. Update our import/export
+ bitmaps. IS_EXPORT is true if we're reexporting the OTHER. */
+
+void
+module_state::set_import (module_state const *import, bool is_export)
+{
+ gcc_checking_assert (this != import);
+
+ /* We see IMPORT's exports (which includes IMPORT). If IMPORT is
+ the primary interface or a partition we'll see its imports. */
+ bitmap_ior_into (imports, import->is_module () || import->is_partition ()
+ ? import->imports : import->exports);
+
+ if (is_export)
+ /* We'll export OTHER's exports. */
+ bitmap_ior_into (exports, import->exports);
+}
+
+/* Return the declaring entity of DECL. That is the decl determining
+ how to decorate DECL with module information. Returns NULL_TREE if
+ it's the global module. */
+
+tree
+get_originating_module_decl (tree decl)
+{
+ /* An enumeration constant. */
+ if (TREE_CODE (decl) == CONST_DECL
+ && DECL_CONTEXT (decl)
+ && (TREE_CODE (DECL_CONTEXT (decl)) == ENUMERAL_TYPE))
+ decl = TYPE_NAME (DECL_CONTEXT (decl));
+ else if (TREE_CODE (decl) == FIELD_DECL
+ || TREE_CODE (decl) == USING_DECL)
+ {
+ decl = DECL_CONTEXT (decl);
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ decl = TYPE_NAME (decl);
+ }
+
+ gcc_checking_assert (TREE_CODE (decl) == TEMPLATE_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == CONCEPT_DECL
+ || TREE_CODE (decl) == NAMESPACE_DECL);
+
+ for (;;)
+ {
+ /* Uninstantiated template friends are owned by the befriending
+ class -- not their context. */
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
+ decl = TYPE_NAME (DECL_CHAIN (decl));
+
+ int use;
+ if (tree ti = node_template_info (decl, use))
+ {
+ decl = TI_TEMPLATE (ti);
+ if (TREE_CODE (decl) != TEMPLATE_DECL)
+ {
+ /* A friend template specialization. */
+ gcc_checking_assert (OVL_P (decl));
+ return global_namespace;
+ }
+ }
+ else
+ {
+ tree ctx = CP_DECL_CONTEXT (decl);
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ break;
+
+ if (TYPE_P (ctx))
+ {
+ ctx = TYPE_NAME (ctx);
+ if (!ctx)
+ {
+ /* Some kind of internal type. */
+ gcc_checking_assert (DECL_ARTIFICIAL (decl));
+ return global_namespace;
+ }
+ }
+ decl = ctx;
+ }
+ }
+
+ return decl;
+}
+
+int
+get_originating_module (tree decl, bool for_mangle)
+{
+ tree owner = get_originating_module_decl (decl);
+
+ if (!DECL_LANG_SPECIFIC (owner))
+ return for_mangle ? -1 : 0;
+
+ if (for_mangle
+ && (DECL_MODULE_EXPORT_P (owner) || !DECL_MODULE_PURVIEW_P (owner)))
+ return -1;
+
+ if (!DECL_MODULE_IMPORT_P (owner))
+ return 0;
+
+ return get_importing_module (owner);
+}
+
+unsigned
+get_importing_module (tree decl, bool flexible)
+{
+ unsigned index = import_entity_index (decl, flexible);
+ if (index == ~(~0u >> 1))
+ return -1;
+ module_state *module = import_entity_module (index);
+
+ return module->mod;
+}
+
+/* Is it permissible to redeclare DECL. */
+
+bool
+module_may_redeclare (tree decl)
+{
+ module_state *me = (*modules)[0];
+ module_state *them = me;
+ if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl))
+ {
+ /* We can be given the TEMPLATE_RESULT. We want the
+ TEMPLATE_DECL. */
+ int use_tpl = -1;
+ if (tree ti = node_template_info (decl, use_tpl))
+ {
+ tree tmpl = TI_TEMPLATE (ti);
+ if (DECL_TEMPLATE_RESULT (tmpl) == decl)
+ decl = tmpl;
+ // FIXME: What about partial specializations? We need to
+ // look at the specialization list in that case. Unless our
+ // caller's given us the right thing. An alternative would
+ // be to put both the template and the result into the
+ // entity hash, but that seems expensive?
+ }
+ unsigned index = import_entity_index (decl);
+ them = import_entity_module (index);
+ }
+
+ if (them->is_header ())
+ {
+ if (!header_module_p ())
+ return !module_purview_p ();
+
+ if (DECL_SOURCE_LOCATION (decl) == BUILTINS_LOCATION)
+ /* This is a builtin, being declared in header-unit. We
+ now need to mark it as an export. */
+ DECL_MODULE_EXPORT_P (decl) = true;
+
+ /* If it came from a header, it's in the global module. */
+ return true;
+ }
+
+ if (me == them)
+ return ((DECL_LANG_SPECIFIC (decl) && DECL_MODULE_PURVIEW_P (decl))
+ == module_purview_p ());
+
+ if (!me->name)
+ me = me->parent;
+
+ /* We can't have found a GMF entity from a named module. */
+ gcc_checking_assert (DECL_LANG_SPECIFIC (decl)
+ && DECL_MODULE_PURVIEW_P (decl));
+
+ return me && get_primary (them) == get_primary (me);
+}
+
+/* DECL is being created by this TU. Record it came from here. We
+ record module purview, so we can see if partial or explicit
+ specialization needs to be written out, even though its purviewness
+ comes from the most general template. */
+
+void
+set_instantiating_module (tree decl)
+{
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == CONCEPT_DECL
+ || TREE_CODE (decl) == TEMPLATE_DECL
+ || (TREE_CODE (decl) == NAMESPACE_DECL
+ && DECL_NAMESPACE_ALIAS (decl)));
+
+ if (!modules_p ())
+ return;
+
+ if (!DECL_LANG_SPECIFIC (decl) && module_purview_p ())
+ retrofit_lang_decl (decl);
+ if (DECL_LANG_SPECIFIC (decl))
+ {
+ DECL_MODULE_PURVIEW_P (decl) = module_purview_p ();
+ /* If this was imported, we'll still be in the entity_hash. */
+ DECL_MODULE_IMPORT_P (decl) = false;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ tree res = DECL_TEMPLATE_RESULT (decl);
+ retrofit_lang_decl (res);
+ DECL_MODULE_PURVIEW_P (res) = DECL_MODULE_PURVIEW_P (decl);
+ DECL_MODULE_IMPORT_P (res) = false;
+ }
+ }
+}
+
+/* If DECL is a class member, whose class is not defined in this TU
+ (it was imported), remember this decl. */
+
+void
+set_defining_module (tree decl)
+{
+ gcc_checking_assert (!DECL_LANG_SPECIFIC (decl)
+ || !DECL_MODULE_IMPORT_P (decl));
+
+ if (module_has_cmi_p ())
+ {
+ tree ctx = DECL_CONTEXT (decl);
+ if (ctx
+ && (TREE_CODE (ctx) == RECORD_TYPE || TREE_CODE (ctx) == UNION_TYPE)
+ && DECL_LANG_SPECIFIC (TYPE_NAME (ctx))
+ && DECL_MODULE_IMPORT_P (TYPE_NAME (ctx)))
+ {
+ /* This entity's context is from an import. We may need to
+ record this entity to make sure we emit it in the CMI.
+ Template specializations are in the template hash tables,
+ so we don't need to record them here as well. */
+ int use_tpl = -1;
+ tree ti = node_template_info (decl, use_tpl);
+ if (use_tpl <= 0)
+ {
+ if (ti)
+ {
+ gcc_checking_assert (!use_tpl);
+ /* Get to the TEMPLATE_DECL. */
+ decl = TI_TEMPLATE (ti);
+ }
+
+ /* Record it on the class_members list. */
+ vec_safe_push (class_members, decl);
+ }
+ }
+ else if (DECL_IMPLICIT_TYPEDEF_P (decl)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ /* This is a partial or explicit specialization. */
+ vec_safe_push (partial_specializations, decl);
+ }
+}
+
+void
+set_originating_module (tree decl, bool friend_p ATTRIBUTE_UNUSED)
+{
+ set_instantiating_module (decl);
+
+ if (TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+ return;
+
+ gcc_checking_assert (friend_p || decl == get_originating_module_decl (decl));
+
+ if (!module_exporting_p ())
+ return;
+
+ // FIXME: Check ill-formed linkage
+ DECL_MODULE_EXPORT_P (decl) = true;
+}
+
+/* DECL is attached to ROOT for odr purposes. */
+
+void
+maybe_attach_decl (tree ctx, tree decl)
+{
+ if (!modules_p ())
+ return;
+
+ // FIXME: For now just deal with lambdas attached to var decls.
+ // This might be sufficient?
+ if (TREE_CODE (ctx) != VAR_DECL)
+ return;
+
+ gcc_checking_assert (DECL_NAMESPACE_SCOPE_P (ctx));
+
+ if (!attached_table)
+ attached_table = new attachset::hash (EXPERIMENT (1, 400));
+
+ if (attached_table->add (DECL_UID (ctx), decl))
+ {
+ retrofit_lang_decl (ctx);
+ DECL_MODULE_ATTACHMENTS_P (ctx) = true;
+ }
+}
+
+/* Create the flat name string. It is simplest to have it handy. */
+
+void
+module_state::set_flatname ()
+{
+ gcc_checking_assert (!flatname);
+ if (parent)
+ {
+ auto_vec<tree,5> ids;
+ size_t len = 0;
+ char const *primary = NULL;
+ size_t pfx_len = 0;
+
+ for (module_state *probe = this;
+ probe;
+ probe = probe->parent)
+ if (is_partition () && !probe->is_partition ())
+ {
+ primary = probe->get_flatname ();
+ pfx_len = strlen (primary);
+ break;
+ }
+ else
+ {
+ ids.safe_push (probe->name);
+ len += IDENTIFIER_LENGTH (probe->name) + 1;
+ }
+
+ char *flat = XNEWVEC (char, pfx_len + len + is_partition ());
+ flatname = flat;
+
+ if (primary)
+ {
+ memcpy (flat, primary, pfx_len);
+ flat += pfx_len;
+ *flat++ = ':';
+ }
+
+ for (unsigned len = 0; ids.length ();)
+ {
+ if (len)
+ flat[len++] = '.';
+ tree elt = ids.pop ();
+ unsigned l = IDENTIFIER_LENGTH (elt);
+ memcpy (flat + len, IDENTIFIER_POINTER (elt), l + 1);
+ len += l;
+ }
+ }
+ else if (is_header ())
+ flatname = TREE_STRING_POINTER (name);
+ else
+ flatname = IDENTIFIER_POINTER (name);
+}
+
+/* Read the CMI file for a module. */
+
+bool
+module_state::do_import (cpp_reader *reader, bool outermost)
+{
+ gcc_assert (global_namespace == current_scope () && loadedness == ML_NONE);
+
+ loc = linemap_module_loc (line_table, loc, get_flatname ());
+
+ if (lazy_open >= lazy_limit)
+ freeze_an_elf ();
+
+ int fd = -1;
+ int e = ENOENT;
+ if (filename)
+ {
+ const char *file = maybe_add_cmi_prefix (filename);
+ dump () && dump ("CMI is %s", file);
+ fd = open (file, O_RDONLY | O_CLOEXEC | O_BINARY);
+ e = errno;
+ }
+
+ gcc_checking_assert (!slurp);
+ slurp = new slurping (new elf_in (fd, e));
+
+ bool ok = true;
+ if (!from ()->get_error ())
+ {
+ announce ("importing");
+ loadedness = ML_CONFIG;
+ lazy_open++;
+ ok = read_initial (reader);
+ slurp->lru = ++lazy_lru;
+ }
+
+ gcc_assert (slurp->current == ~0u);
+
+ return check_read (outermost, ok);
+}
+
+/* Attempt to increase the file descriptor limit. */
+
+static bool
+try_increase_lazy (unsigned want)
+{
+ gcc_checking_assert (lazy_open >= lazy_limit);
+
+ /* If we're increasing, saturate at hard limit. */
+ if (want > lazy_hard_limit && lazy_limit < lazy_hard_limit)
+ want = lazy_hard_limit;
+
+#if HAVE_SETRLIMIT
+ if ((!lazy_limit || !param_lazy_modules)
+ && lazy_hard_limit
+ && want <= lazy_hard_limit)
+ {
+ struct rlimit rlimit;
+ rlimit.rlim_cur = want + LAZY_HEADROOM;
+ rlimit.rlim_max = lazy_hard_limit + LAZY_HEADROOM;
+ if (!setrlimit (RLIMIT_NOFILE, &rlimit))
+ lazy_limit = want;
+ }
+#endif
+
+ return lazy_open < lazy_limit;
+}
+
+/* Pick a victim module to freeze its reader. */
+
+void
+module_state::freeze_an_elf ()
+{
+ if (try_increase_lazy (lazy_open * 2))
+ return;
+
+ module_state *victim = NULL;
+ for (unsigned ix = modules->length (); ix--;)
+ {
+ module_state *candidate = (*modules)[ix];
+ if (candidate && candidate->slurp && candidate->slurp->lru
+ && candidate->from ()->is_freezable ()
+ && (!victim || victim->slurp->lru > candidate->slurp->lru))
+ victim = candidate;
+ }
+
+ if (victim)
+ {
+ dump () && dump ("Freezing '%s'", victim->filename);
+ if (victim->slurp->macro_defs.size)
+ /* Save the macro definitions to a buffer. */
+ victim->from ()->preserve (victim->slurp->macro_defs);
+ if (victim->slurp->macro_tbl.size)
+ /* Save the macro definitions to a buffer. */
+ victim->from ()->preserve (victim->slurp->macro_tbl);
+ victim->from ()->freeze ();
+ lazy_open--;
+ }
+ else
+ dump () && dump ("No module available for freezing");
+}
+
+/* Load the lazy slot *MSLOT, INDEX'th slot of the module. */
+
+bool
+module_state::lazy_load (unsigned index, binding_slot *mslot)
+{
+ unsigned n = dump.push (this);
+
+ gcc_checking_assert (function_depth);
+
+ unsigned cookie = mslot->get_lazy ();
+ unsigned snum = cookie >> 2;
+ dump () && dump ("Loading entity %M[%u] section:%u", this, index, snum);
+
+ bool ok = load_section (snum, mslot);
+
+ dump.pop (n);
+
+ return ok;
+}
+
+/* Load MOD's binding for NS::ID into *MSLOT. *MSLOT contains the
+ lazy cookie. OUTER is true if this is the outermost lazy, (used
+ for diagnostics). */
+
+void
+lazy_load_binding (unsigned mod, tree ns, tree id, binding_slot *mslot)
+{
+ int count = errorcount + warningcount;
+
+ timevar_start (TV_MODULE_IMPORT);
+
+ /* Stop GC happening, even in outermost loads (because our caller
+ could well be building up a lookup set). */
+ function_depth++;
+
+ gcc_checking_assert (mod);
+ module_state *module = (*modules)[mod];
+ unsigned n = dump.push (module);
+
+ unsigned snum = mslot->get_lazy ();
+ dump () && dump ("Lazily binding %P@%N section:%u", ns, id,
+ module->name, snum);
+
+ bool ok = !recursive_lazy (snum);
+ if (ok)
+ {
+ ok = module->load_section (snum, mslot);
+ lazy_snum = 0;
+ }
+
+ dump.pop (n);
+
+ function_depth--;
+
+ timevar_stop (TV_MODULE_IMPORT);
+
+ if (!ok)
+ fatal_error (input_location,
+ module->is_header ()
+ ? G_("failed to load binding %<%E%s%E%>")
+ : G_("failed to load binding %<%E%s%E@%s%>"),
+ ns, &"::"[ns == global_namespace ? 2 : 0], id,
+ module->get_flatname ());
+
+ if (count != errorcount + warningcount)
+ inform (input_location,
+ module->is_header ()
+ ? G_("during load of binding %<%E%s%E%>")
+ : G_("during load of binding %<%E%s%E@%s%>"),
+ ns, &"::"[ns == global_namespace ? 2 : 0], id,
+ module->get_flatname ());
+}
+
+/* Load any pending specializations of TMPL. Called just before
+ instantiating TMPL. */
+
+void
+lazy_load_specializations (tree tmpl)
+{
+ gcc_checking_assert (DECL_MODULE_PENDING_SPECIALIZATIONS_P (tmpl)
+ && DECL_MODULE_ENTITY_P (tmpl));
+
+ int count = errorcount + warningcount;
+
+ timevar_start (TV_MODULE_IMPORT);
+ bool ok = !recursive_lazy ();
+ if (ok)
+ {
+ unsigned ident = import_entity_index (tmpl);
+ if (pendset *set = pending_table->get (ident, true))
+ {
+ function_depth++; /* Prevent GC */
+ unsigned n = dump.push (NULL);
+ dump ()
+ && dump ("Reading %u pending specializations keyed to %M[%u] %N",
+ set->num, import_entity_module (ident),
+ ident - import_entity_module (ident)->entity_lwm, tmpl);
+ if (!pendset_lazy_load (set, true))
+ ok = false;
+ dump.pop (n);
+
+ function_depth--;
+ }
+ lazy_snum = 0;
+ }
+
+ timevar_stop (TV_MODULE_IMPORT);
+
+ if (!ok)
+ fatal_error (input_location, "failed to load specializations keyed to %qD",
+ tmpl);
+
+ if (count != errorcount + warningcount)
+ inform (input_location,
+ "during load of specializations keyed to %qD", tmpl);
+}
+
+void
+lazy_load_members (tree decl)
+{
+ gcc_checking_assert (DECL_MODULE_PENDING_MEMBERS_P (decl));
+ if (!DECL_MODULE_ENTITY_P (decl))
+ {
+ // FIXME: I can't help feeling that DECL_TEMPLATE_RESULT should
+ // be inserted into the entity map, or perhaps have the same
+ // DECL_UID as the template, so I don't have to do this dance
+ // here and elsewhere. It also simplifies when DECL is a
+ // partial specialization. (also noted elsewhere as an issue)
+ tree ti = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl));
+ tree tmpl = TI_TEMPLATE (ti);
+ gcc_checking_assert (DECL_TEMPLATE_RESULT (tmpl) == decl);
+ decl = tmpl;
+ }
+
+ timevar_start (TV_MODULE_IMPORT);
+ unsigned ident = import_entity_index (decl);
+ if (pendset *set = pending_table->get (~ident, true))
+ {
+ function_depth++; /* Prevent GC */
+ unsigned n = dump.push (NULL);
+ dump () && dump ("Reading %u pending members keyed to %M[%u] %N",
+ set->num, import_entity_module (ident),
+ ident - import_entity_module (ident)->entity_lwm, decl);
+ pendset_lazy_load (set, false);
+ dump.pop (n);
+
+ function_depth--;
+ }
+ timevar_stop (TV_MODULE_IMPORT);
+}
+
+static void
+direct_import (module_state *import, cpp_reader *reader)
+{
+ timevar_start (TV_MODULE_IMPORT);
+ unsigned n = dump.push (import);
+
+ gcc_checking_assert (import->is_direct () && import->is_rooted ());
+ if (import->loadedness == ML_NONE)
+ if (!import->do_import (reader, true))
+ gcc_unreachable ();
+
+ if (import->loadedness < ML_LANGUAGE)
+ {
+ if (!attached_table)
+ attached_table = new attachset::hash (EXPERIMENT (1, 400));
+ import->read_language (true);
+ }
+
+ (*modules)[0]->set_import (import, import->exported_p);
+
+ dump.pop (n);
+ timevar_stop (TV_MODULE_IMPORT);
+}
+
+/* Import module IMPORT. */
+
+void
+import_module (module_state *import, location_t from_loc, bool exporting_p,
+ tree, cpp_reader *reader)
+{
+ if (!import->check_not_purview (from_loc))
+ return;
+
+ if (!import->is_header () && current_lang_depth ())
+ /* Only header units should appear inside language
+ specifications. The std doesn't specify this, but I think
+ that's an error in resolving US 033, because language linkage
+ is also our escape clause to getting things into the global
+ module, so we don't want to confuse things by having to think
+ about whether 'extern "C++" { import foo; }' puts foo's
+ contents into the global module all of a sudden. */
+ warning (0, "import of named module %qs inside language-linkage block",
+ import->get_flatname ());
+
+ if (exporting_p || module_exporting_p ())
+ import->exported_p = true;
+
+ if (import->loadedness != ML_NONE)
+ {
+ from_loc = ordinary_loc_of (line_table, from_loc);
+ linemap_module_reparent (line_table, import->loc, from_loc);
+ }
+ gcc_checking_assert (!import->module_p);
+ gcc_checking_assert (import->is_direct () && import->is_rooted ());
+
+ direct_import (import, reader);
+}
+
+/* Declare the name of the current module to be NAME. EXPORTING_p is
+ true if this TU is the exporting module unit. */
+
+void
+declare_module (module_state *module, location_t from_loc, bool exporting_p,
+ tree, cpp_reader *reader)
+{
+ gcc_assert (global_namespace == current_scope ());
+
+ module_state *current = (*modules)[0];
+ if (module_purview_p () || module->loadedness != ML_NONE)
+ {
+ error_at (from_loc, module_purview_p ()
+ ? G_("module already declared")
+ : G_("module already imported"));
+ if (module_purview_p ())
+ module = current;
+ inform (module->loc, module_purview_p ()
+ ? G_("module %qs declared here")
+ : G_("module %qs imported here"),
+ module->get_flatname ());
+ return;
+ }
+
+ gcc_checking_assert (module->module_p);
+ gcc_checking_assert (module->is_direct () && module->is_rooted ());
+
+ /* Yer a module, 'arry. */
+ module_kind &= ~MK_GLOBAL;
+ module_kind |= MK_MODULE;
+
+ if (module->is_partition () || exporting_p)
+ {
+ gcc_checking_assert (module->get_flatname ());
+
+ if (module->is_partition ())
+ module_kind |= MK_PARTITION;
+
+ if (exporting_p)
+ {
+ module->interface_p = true;
+ module_kind |= MK_INTERFACE;
+ }
+
+ if (module->is_header ())
+ module_kind |= MK_GLOBAL | MK_EXPORTING;
+
+ /* Copy the importing information we may have already done. We
+ do not need to separate out the imports that only happen in
+ the GMF, inspite of what the literal wording of the std
+ might imply. See p2191, the core list had a discussion
+ where the module implementors agreed that the GMF of a named
+ module is invisible to importers. */
+ module->imports = current->imports;
+
+ module->mod = 0;
+ (*modules)[0] = module;
+ }
+ else
+ {
+ module->interface_p = true;
+ current->parent = module; /* So mangler knows module identity. */
+ direct_import (module, reader);
+ }
+}
+
+/* +1, we're the primary or a partition. Therefore emitting a
+ globally-callable idemportent initializer function.
+ -1, we have direct imports. Therefore emitting calls to their
+ initializers. */
+
+int
+module_initializer_kind ()
+{
+ int result = 0;
+
+ if (module_has_cmi_p () && !header_module_p ())
+ result = +1;
+ else if (num_init_calls_needed)
+ result = -1;
+
+ return result;
+}
+
+/* Emit calls to each direct import's global initializer. Including
+ direct imports of directly imported header units. The initializers
+ of (static) entities in header units will be called by their
+ importing modules (for the instance contained within that), or by
+ the current TU (for the instances we've brought in). Of course
+ such header unit behaviour is evil, but iostream went through that
+ door some time ago. */
+
+void
+module_add_import_initializers ()
+{
+ unsigned calls = 0;
+ if (modules)
+ {
+ tree fntype = build_function_type (void_type_node, void_list_node);
+ vec<tree, va_gc> *args = NULL;
+
+ for (unsigned ix = modules->length (); --ix;)
+ {
+ module_state *import = (*modules)[ix];
+ if (import->call_init_p)
+ {
+ tree name = mangle_module_global_init (ix);
+ tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype);
+
+ DECL_CONTEXT (fndecl) = FROB_CONTEXT (global_namespace);
+ SET_DECL_ASSEMBLER_NAME (fndecl, name);
+ TREE_PUBLIC (fndecl) = true;
+ determine_visibility (fndecl);
+
+ tree call = cp_build_function_call_vec (fndecl, &args,
+ tf_warning_or_error);
+ finish_expr_stmt (call);
+
+ calls++;
+ }
+ }
+ }
+
+ gcc_checking_assert (calls == num_init_calls_needed);
+}
+
+/* NAME & LEN are a preprocessed header name, possibly including the
+ surrounding "" or <> characters. Return the raw string name of the
+ module to which it refers. This will be an absolute path, or begin
+ with ./, so it is immediately distinguishable from a (non-header
+ unit) module name. If READER is non-null, ask the preprocessor to
+ locate the header to which it refers using the appropriate include
+ path. Note that we do never do \ processing of the string, as that
+ matches the preprocessor's behaviour. */
+
+static const char *
+canonicalize_header_name (cpp_reader *reader, location_t loc, bool unquoted,
+ const char *str, size_t &len_r)
+{
+ size_t len = len_r;
+ static char *buf = 0;
+ static size_t alloc = 0;
+
+ if (!unquoted)
+ {
+ gcc_checking_assert (len >= 2
+ && ((reader && str[0] == '<' && str[len-1] == '>')
+ || (str[0] == '"' && str[len-1] == '"')));
+ str += 1;
+ len -= 2;
+ }
+
+ if (reader)
+ {
+ gcc_assert (!unquoted);
+
+ if (len >= alloc)
+ {
+ alloc = len + 1;
+ buf = XRESIZEVEC (char, buf, alloc);
+ }
+ memcpy (buf, str, len);
+ buf[len] = 0;
+
+ if (const char *hdr
+ = cpp_find_header_unit (reader, buf, str[-1] == '<', loc))
+ {
+ len = strlen (hdr);
+ str = hdr;
+ }
+ else
+ str = buf;
+ }
+
+ if (!(str[0] == '.' ? IS_DIR_SEPARATOR (str[1]) : IS_ABSOLUTE_PATH (str)))
+ {
+ /* Prepend './' */
+ if (len + 3 > alloc)
+ {
+ alloc = len + 3;
+ buf = XRESIZEVEC (char, buf, alloc);
+ }
+
+ buf[0] = '.';
+ buf[1] = DIR_SEPARATOR;
+ memmove (buf + 2, str, len);
+ len += 2;
+ buf[len] = 0;
+ str = buf;
+ }
+
+ len_r = len;
+ return str;
+}
+
+/* Set the CMI name from a cody packet. Issue an error if
+ ill-formed. */
+
+void module_state::set_filename (const Cody::Packet &packet)
+{
+ gcc_checking_assert (!filename);
+ if (packet.GetCode () == Cody::Client::PC_PATHNAME)
+ filename = xstrdup (packet.GetString ().c_str ());
+ else
+ {
+ gcc_checking_assert (packet.GetCode () == Cody::Client::PC_ERROR);
+ error_at (loc, "unknown Compiled Module Interface: %s",
+ packet.GetString ().c_str ());
+ }
+}
+
+/* Figure out whether to treat HEADER as an include or an import. */
+
+static char *
+maybe_translate_include (cpp_reader *reader, line_maps *lmaps, location_t loc,
+ const char *path)
+{
+ if (!modules_p ())
+ {
+ /* Turn off. */
+ cpp_get_callbacks (reader)->translate_include = NULL;
+ return nullptr;
+ }
+
+ if (!spans.init_p ())
+ /* Before the main file, don't divert. */
+ return nullptr;
+
+ dump.push (NULL);
+
+ dump () && dump ("Checking include translation '%s'", path);
+ auto *mapper = get_mapper (cpp_main_loc (reader));
+
+ size_t len = strlen (path);
+ path = canonicalize_header_name (NULL, loc, true, path, len);
+ auto packet = mapper->IncludeTranslate (path, Cody::Flags::None, len);
+ int xlate = false;
+ if (packet.GetCode () == Cody::Client::PC_BOOL)
+ xlate = -int (packet.GetInteger ());
+ else if (packet.GetCode () == Cody::Client::PC_PATHNAME)
+ {
+ /* Record the CMI name for when we do the import. */
+ module_state *import = get_module (build_string (len, path));
+ import->set_filename (packet);
+ xlate = +1;
+ }
+ else
+ {
+ gcc_checking_assert (packet.GetCode () == Cody::Client::PC_ERROR);
+ error_at (loc, "cannot determine %<#include%> translation of %s: %s",
+ path, packet.GetString ().c_str ());
+ }
+
+ bool note = false;
+ if (note_include_translate_yes && xlate > 1)
+ note = true;
+ else if (note_include_translate_no && xlate == 0)
+ note = true;
+ else if (note_includes)
+ {
+ /* We do not expect the note_includes vector to be large, so O(N)
+ iteration. */
+ for (unsigned ix = note_includes->length (); !note && ix--;)
+ {
+ const char *hdr = (*note_includes)[ix];
+ size_t hdr_len = strlen (hdr);
+ if ((hdr_len == len
+ || (hdr_len < len && IS_DIR_SEPARATOR (path[len - hdr_len - 1])))
+ && !memcmp (hdr, path + len - hdr_len, hdr_len))
+ note = true;
+ }
+ }
+
+ if (note)
+ inform (loc, xlate
+ ? G_("include %qs translated to import")
+ : G_("include %qs processed textually") , path);
+
+ dump () && dump (xlate ? "Translating include to import"
+ : "Keeping include as include");
+ dump.pop (0);
+
+ if (!(xlate > 0))
+ return nullptr;
+
+ /* Create the translation text. */
+ loc = ordinary_loc_of (lmaps, loc);
+ const line_map_ordinary *map
+ = linemap_check_ordinary (linemap_lookup (lmaps, loc));
+ unsigned col = SOURCE_COLUMN (map, loc);
+ col -= (col != 0); /* Columns are 1-based. */
+
+ unsigned alloc = len + col + 60;
+ char *res = XNEWVEC (char, alloc);
+
+ strcpy (res, "__import");
+ unsigned actual = 8;
+ if (col > actual)
+ {
+ /* Pad out so the filename appears at the same position. */
+ memset (res + actual, ' ', col - actual);
+ actual = col;
+ }
+ /* No need to encode characters, that's not how header names are
+ handled. */
+ actual += snprintf (res + actual, alloc - actual,
+ "\"%s\" [[__translated]];\n", path);
+ gcc_checking_assert (actual < alloc);
+
+ /* cpplib will delete the buffer. */
+ return res;
+}
+
+static void
+begin_header_unit (cpp_reader *reader)
+{
+ /* Set the module header name from the main_input_filename. */
+ const char *main = main_input_filename;
+ size_t len = strlen (main);
+ main = canonicalize_header_name (NULL, 0, true, main, len);
+ module_state *module = get_module (build_string (len, main));
+
+ preprocess_module (module, cpp_main_loc (reader), false, false, true, reader);
+}
+
+/* We've just properly entered the main source file. I.e. after the
+ command line, builtins and forced headers. Record the line map and
+ location of this map. Note we may be called more than once. The
+ first call sticks. */
+
+void
+module_begin_main_file (cpp_reader *reader, line_maps *lmaps,
+ const line_map_ordinary *map)
+{
+ gcc_checking_assert (lmaps == line_table);
+ if (modules_p () && !spans.init_p ())
+ {
+ unsigned n = dump.push (NULL);
+ spans.init (lmaps, map);
+ dump.pop (n);
+ if (flag_header_unit && !cpp_get_options (reader)->preprocessed)
+ {
+ /* Tell the preprocessor this is an include file. */
+ cpp_retrofit_as_include (reader);
+ begin_header_unit (reader);
+ }
+ }
+}
+
+/* We've just lexed a module-specific control line for MODULE. Mark
+ the module as a direct import, and possibly load up its macro
+ state. Returns the primary module, if this is a module
+ declaration. */
+/* Perhaps we should offer a preprocessing mode where we read the
+ directives from the header unit, rather than require the header's
+ CMI. */
+
+module_state *
+preprocess_module (module_state *module, location_t from_loc,
+ bool in_purview, bool is_import, bool is_export,
+ cpp_reader *reader)
+{
+ if (!is_import)
+ {
+ if (module->loc)
+ /* It's already been mentioned, so ignore its module-ness. */
+ is_import = true;
+ else
+ {
+ /* Record it is the module. */
+ module->module_p = true;
+ if (is_export)
+ {
+ module->exported_p = true;
+ module->interface_p = true;
+ }
+ }
+ }
+
+ if (module->directness < MD_DIRECT + in_purview)
+ {
+ /* Mark as a direct import. */
+ module->directness = module_directness (MD_DIRECT + in_purview);
+
+ /* Set the location to be most informative for users. */
+ from_loc = ordinary_loc_of (line_table, from_loc);
+ if (module->loadedness != ML_NONE)
+ linemap_module_reparent (line_table, module->loc, from_loc);
+ else
+ {
+ module->loc = from_loc;
+ if (!module->flatname)
+ module->set_flatname ();
+ }
+ }
+
+ if (is_import
+ && !module->is_module () && module->is_header ()
+ && module->loadedness < ML_PREPROCESSOR
+ && (!cpp_get_options (reader)->preprocessed
+ || cpp_get_options (reader)->directives_only))
+ {
+ timevar_start (TV_MODULE_IMPORT);
+ unsigned n = dump.push (module);
+
+ if (module->loadedness == ML_NONE)
+ {
+ unsigned pre_hwm = 0;
+
+ /* Preserve the state of the line-map. */
+ pre_hwm = LINEMAPS_ORDINARY_USED (line_table);
+ /* We only need to close the span, if we're going to emit a
+ CMI. But that's a little tricky -- our token scanner
+ needs to be smarter -- and this isn't much state.
+ Remember, we've not parsed anything at this point, so
+ our module state flags are inadequate. */
+ spans.maybe_init ();
+ spans.close ();
+
+ if (!module->filename)
+ {
+ auto *mapper = get_mapper (cpp_main_loc (reader));
+ auto packet = mapper->ModuleImport (module->get_flatname ());
+ module->set_filename (packet);
+ }
+ module->do_import (reader, true);
+
+ /* Restore the line-map state. */
+ linemap_module_restore (line_table, pre_hwm);
+ spans.open ();
+ }
+
+ if (module->loadedness < ML_PREPROCESSOR)
+ if (module->read_preprocessor (true))
+ module->import_macros ();
+
+ dump.pop (n);
+ timevar_stop (TV_MODULE_IMPORT);
+ }
+
+ return is_import ? NULL : get_primary (module);
+}
+
+/* We've completed phase-4 translation. Emit any dependency
+ information for the not-yet-loaded direct imports, and fill in
+ their file names. We'll have already loaded up the direct header
+ unit wavefront. */
+
+void
+preprocessed_module (cpp_reader *reader)
+{
+ auto *mapper = get_mapper (cpp_main_loc (reader));
+
+ spans.maybe_init ();
+ spans.close ();
+
+ /* Stupid GTY doesn't grok a typedef here. And using type = is, too
+ modern. */
+#define iterator hash_table<module_state_hash>::iterator
+ /* using iterator = hash_table<module_state_hash>::iterator; */
+
+ /* Walk the module hash, asking for the names of all unknown
+ direct imports and informing of an export (if that's what we
+ are). Notice these are emitted even when preprocessing as they
+ inform the server of dependency edges. */
+ timevar_start (TV_MODULE_MAPPER);
+
+ dump.push (NULL);
+ dump () && dump ("Resolving direct import names");
+
+ if (!flag_preprocess_only
+ || bool (mapper->get_flags () & Cody::Flags::NameOnly)
+ || cpp_get_deps (reader))
+ {
+ mapper->Cork ();
+ iterator end = modules_hash->end ();
+ for (iterator iter = modules_hash->begin (); iter != end; ++iter)
+ {
+ module_state *module = *iter;
+ if (module->is_direct () && !module->filename)
+ {
+ Cody::Flags flags
+ = (flag_preprocess_only ? Cody::Flags::None
+ : Cody::Flags::NameOnly);
+
+ if (module->module_p
+ && (module->is_partition () || module->exported_p))
+ mapper->ModuleExport (module->get_flatname (), flags);
+ else
+ mapper->ModuleImport (module->get_flatname (), flags);
+ }
+ }
+
+ auto response = mapper->Uncork ();
+ auto r_iter = response.begin ();
+ for (iterator iter = modules_hash->begin (); iter != end; ++iter)
+ {
+ module_state *module = *iter;
+
+ if (module->is_direct () && !module->filename)
+ {
+ Cody::Packet const &p = *r_iter;
+ ++r_iter;
+
+ module->set_filename (p);
+ }
+ }
+ }
+
+ dump.pop (0);
+
+ timevar_stop (TV_MODULE_MAPPER);
+
+ if (mkdeps *deps = cpp_get_deps (reader))
+ {
+ /* Walk the module hash, informing the dependency machinery. */
+ iterator end = modules_hash->end ();
+ for (iterator iter = modules_hash->begin (); iter != end; ++iter)
+ {
+ module_state *module = *iter;
+
+ if (module->is_direct ())
+ {
+ if (module->is_module ()
+ && (module->is_interface () || module->is_partition ()))
+ deps_add_module_target (deps, module->get_flatname (),
+ maybe_add_cmi_prefix (module->filename),
+ module->is_header());
+ else
+ deps_add_module_dep (deps, module->get_flatname ());
+ }
+ }
+ }
+
+ if (flag_header_unit && !flag_preprocess_only)
+ {
+ iterator end = modules_hash->end ();
+ for (iterator iter = modules_hash->begin (); iter != end; ++iter)
+ {
+ module_state *module = *iter;
+ if (module->is_module ())
+ {
+ declare_module (module, cpp_main_loc (reader), true, NULL, reader);
+ break;
+ }
+ }
+ }
+#undef iterator
+}
+
+/* VAL is a global tree, add it to the global vec if it is
+ interesting. Add some of its targets, if they too are
+ interesting. We do not add identifiers, as they can be re-found
+ via the identifier hash table. There is a cost to the number of
+ global trees. */
+
+static int
+maybe_add_global (tree val, unsigned &crc)
+{
+ int v = 0;
+
+ if (val && !(identifier_p (val) || TREE_VISITED (val)))
+ {
+ TREE_VISITED (val) = true;
+ crc = crc32_unsigned (crc, fixed_trees->length ());
+ vec_safe_push (fixed_trees, val);
+ v++;
+
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (val), TS_TYPED))
+ v += maybe_add_global (TREE_TYPE (val), crc);
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (val), TS_TYPE_COMMON))
+ v += maybe_add_global (TYPE_NAME (val), crc);
+ }
+
+ return v;
+}
+
+/* Initialize module state. Create the hash table, determine the
+ global trees. Create the module for current TU. */
+
+void
+init_modules (cpp_reader *reader)
+{
+ /* PCH should not be reachable because of lang-specs, but the
+ user could have overriden that. */
+ if (pch_file)
+ fatal_error (input_location,
+ "C++ modules are incompatible with precompiled headers");
+
+ if (cpp_get_options (reader)->traditional)
+ fatal_error (input_location,
+ "C++ modules are incompatible with traditional preprocessing");
+
+ if (flag_preprocess_only)
+ {
+ cpp_options *cpp_opts = cpp_get_options (reader);
+ if (flag_no_output
+ || (cpp_opts->deps.style != DEPS_NONE
+ && !cpp_opts->deps.need_preprocessor_output))
+ {
+ warning (0, flag_dump_macros == 'M'
+ ? G_("macro debug output may be incomplete with modules")
+ : G_("module dependencies require preprocessing"));
+ if (cpp_opts->deps.style != DEPS_NONE)
+ inform (input_location, "you should use the %<-%s%> option",
+ cpp_opts->deps.style == DEPS_SYSTEM ? "MD" : "MMD");
+ }
+ }
+
+ /* :: is always exported. */
+ DECL_MODULE_EXPORT_P (global_namespace) = true;
+
+ modules_hash = hash_table<module_state_hash>::create_ggc (31);
+ vec_safe_reserve (modules, 20);
+
+ /* Create module for current TU. */
+ module_state *current
+ = new (ggc_alloc<module_state> ()) module_state (NULL_TREE, NULL, false);
+ current->mod = 0;
+ bitmap_set_bit (current->imports, 0);
+ modules->quick_push (current);
+
+ gcc_checking_assert (!fixed_trees);
+
+ headers = BITMAP_GGC_ALLOC ();
+
+ if (note_includes)
+ for (unsigned ix = 0; ix != note_includes->length (); ix++)
+ {
+ const char *hdr = (*note_includes)[ix];
+ size_t len = strlen (hdr);
+
+ bool system = hdr[0] == '<';
+ bool user = hdr[0] == '"';
+ bool delimed = system || user;
+
+ if (len <= (delimed ? 2 : 0)
+ || (delimed && hdr[len-1] != (system ? '>' : '"')))
+ error ("invalid header name %qs", hdr);
+
+ hdr = canonicalize_header_name (delimed ? reader : NULL,
+ 0, !delimed, hdr, len);
+ char *path = XNEWVEC (char, len + 1);
+ memcpy (path, hdr, len);
+ path[len+1] = 0;
+
+ (*note_includes)[ix] = path;
+ }
+
+ dump.push (NULL);
+
+ /* Determine lazy handle bound. */
+ {
+ unsigned limit = 1000;
+#if HAVE_GETRLIMIT
+ struct rlimit rlimit;
+ if (!getrlimit (RLIMIT_NOFILE, &rlimit))
+ {
+ lazy_hard_limit = (rlimit.rlim_max < 1000000
+ ? unsigned (rlimit.rlim_max) : 1000000);
+ lazy_hard_limit = (lazy_hard_limit > LAZY_HEADROOM
+ ? lazy_hard_limit - LAZY_HEADROOM : 0);
+ if (rlimit.rlim_cur < limit)
+ limit = unsigned (rlimit.rlim_cur);
+ }
+#endif
+ limit = limit > LAZY_HEADROOM ? limit - LAZY_HEADROOM : 1;
+
+ if (unsigned parm = param_lazy_modules)
+ {
+ if (parm <= limit || !lazy_hard_limit || !try_increase_lazy (parm))
+ lazy_limit = parm;
+ }
+ else
+ lazy_limit = limit;
+ }
+
+ if (dump ())
+ {
+ verstr_t ver;
+ version2string (MODULE_VERSION, ver);
+ dump ("Source: %s", main_input_filename);
+ dump ("Compiler: %s", version_string);
+ dump ("Modules: %s", ver);
+ dump ("Checking: %s",
+#if CHECKING_P
+ "checking"
+#elif ENABLE_ASSERT_CHECKING
+ "asserting"
+#else
+ "release"
+#endif
+ );
+ dump ("Compiled by: "
+#ifdef __GNUC__
+ "GCC %d.%d, %s", __GNUC__, __GNUC_MINOR__,
+#ifdef __OPTIMIZE__
+ "optimizing"
+#else
+ "not optimizing"
+#endif
+#else
+ "not GCC"
+#endif
+ );
+ dump ("Reading: %s", MAPPED_READING ? "mmap" : "fileio");
+ dump ("Writing: %s", MAPPED_WRITING ? "mmap" : "fileio");
+ dump ("Lazy limit: %u", lazy_limit);
+ dump ("Lazy hard limit: %u", lazy_hard_limit);
+ dump ("");
+ }
+
+ /* Construct the global tree array. This is an array of unique
+ global trees (& types). Do this now, rather than lazily, as
+ some global trees are lazily created and we don't want that to
+ mess with our syndrome of fixed trees. */
+ unsigned crc = 0;
+ vec_alloc (fixed_trees, 200);
+
+ dump () && dump ("+Creating globals");
+ /* Insert the TRANSLATION_UNIT_DECL. */
+ TREE_VISITED (DECL_CONTEXT (global_namespace)) = true;
+ fixed_trees->quick_push (DECL_CONTEXT (global_namespace));
+ for (unsigned jx = 0; global_tree_arys[jx].first; jx++)
+ {
+ const tree *ptr = global_tree_arys[jx].first;
+ unsigned limit = global_tree_arys[jx].second;
+
+ for (unsigned ix = 0; ix != limit; ix++, ptr++)
+ {
+ !(ix & 31) && dump ("") && dump ("+\t%u:%u:", jx, ix);
+ unsigned v = maybe_add_global (*ptr, crc);
+ dump () && dump ("+%u", v);
+ }
+ }
+ global_crc = crc32_unsigned (crc, fixed_trees->length ());
+ dump ("") && dump ("Created %u unique globals, crc=%x",
+ fixed_trees->length (), global_crc);
+ for (unsigned ix = fixed_trees->length (); ix--;)
+ TREE_VISITED ((*fixed_trees)[ix]) = false;
+
+ dump.pop (0);
+
+ if (!flag_module_lazy)
+ /* Get the mapper now, if we're not being lazy. */
+ get_mapper (cpp_main_loc (reader));
+
+ if (!flag_preprocess_only)
+ {
+ pending_table = new pendset::hash (EXPERIMENT (1, 400));
+
+ entity_map = new entity_map_t (EXPERIMENT (1, 400));
+ vec_safe_reserve (entity_ary, EXPERIMENT (1, 400));
+ }
+
+#if CHECKING_P
+ note_defs = note_defs_table_t::create_ggc (1000);
+#endif
+
+ if (flag_header_unit && cpp_get_options (reader)->preprocessed)
+ begin_header_unit (reader);
+
+ /* Collect here to make sure things are tagged correctly (when
+ aggressively GC'd). */
+ ggc_collect ();
+}
+
+/* If NODE is a deferred macro, load it. */
+
+static int
+load_macros (cpp_reader *reader, cpp_hashnode *node, void *)
+{
+ location_t main_loc
+ = MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (line_table, 0));
+
+ if (cpp_user_macro_p (node)
+ && !node->value.macro)
+ {
+ cpp_macro *macro = cpp_get_deferred_macro (reader, node, main_loc);
+ dump () && dump ("Loaded macro #%s %I",
+ macro ? "define" : "undef", identifier (node));
+ }
+
+ return 1;
+}
+
+/* At the end of tokenizing, we no longer need the macro tables of
+ imports. But the user might have requested some checking. */
+
+void
+maybe_check_all_macros (cpp_reader *reader)
+{
+ if (!warn_imported_macros)
+ return;
+
+ /* Force loading of any remaining deferred macros. This will
+ produce diagnostics if they are ill-formed. */
+ unsigned n = dump.push (NULL);
+ cpp_forall_identifiers (reader, load_macros, NULL);
+ dump.pop (n);
+}
+
+/* Write the CMI, if we're a module interface. */
+
+void
+finish_module_processing (cpp_reader *reader)
+{
+ if (header_module_p ())
+ module_kind &= ~MK_EXPORTING;
+
+ if (!modules || !(*modules)[0]->name)
+ {
+ if (flag_module_only)
+ warning (0, "%<-fmodule-only%> used for non-interface");
+ }
+ else if (!flag_syntax_only)
+ {
+ int fd = -1;
+ int e = ENOENT;
+
+ timevar_start (TV_MODULE_EXPORT);
+
+ /* Force a valid but empty line map at the end. This simplifies
+ the line table preparation and writing logic. */
+ linemap_add (line_table, LC_ENTER, false, "", 0);
+
+ /* We write to a tmpname, and then atomically rename. */
+ const char *path = NULL;
+ char *tmp_name = NULL;
+ module_state *state = (*modules)[0];
+
+ unsigned n = dump.push (state);
+ state->announce ("creating");
+ if (state->filename)
+ {
+ size_t len = 0;
+ path = maybe_add_cmi_prefix (state->filename, &len);
+ tmp_name = XNEWVEC (char, len + 3);
+ memcpy (tmp_name, path, len);
+ strcpy (&tmp_name[len], "~");
+
+ if (!errorcount)
+ for (unsigned again = 2; ; again--)
+ {
+ fd = open (tmp_name,
+ O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ e = errno;
+ if (fd >= 0 || !again || e != ENOENT)
+ break;
+ create_dirs (tmp_name);
+ }
+ dump () && dump ("CMI is %s", path);
+ }
+
+ if (errorcount)
+ warning_at (state->loc, 0, "not writing module %qs due to errors",
+ state->get_flatname ());
+ else
+ {
+ elf_out to (fd, e);
+ if (to.begin ())
+ {
+ auto loc = input_location;
+ /* So crashes finger point the module decl. */
+ input_location = state->loc;
+ state->write (&to, reader);
+ input_location = loc;
+ }
+ if (to.end ())
+ {
+ /* Some OS's do not replace NEWNAME if it already
+ exists. This'll have a race condition in erroneous
+ concurrent builds. */
+ unlink (path);
+ if (rename (tmp_name, path))
+ {
+ dump () && dump ("Rename ('%s','%s') errno=%u", errno);
+ to.set_error (errno);
+ }
+ }
+
+ if (to.get_error ())
+ {
+ error_at (state->loc, "failed to write compiled module: %s",
+ to.get_error (state->filename));
+ state->note_cmi_name ();
+ }
+ }
+
+ if (!errorcount)
+ {
+ auto *mapper = get_mapper (cpp_main_loc (reader));
+
+ mapper->ModuleCompiled (state->get_flatname ());
+ }
+ else if (path)
+ {
+ /* We failed, attempt to erase all evidence we even tried. */
+ unlink (tmp_name);
+ unlink (path);
+ XDELETEVEC (tmp_name);
+ }
+
+ dump.pop (n);
+ timevar_stop (TV_MODULE_EXPORT);
+
+ ggc_collect ();
+ }
+
+ if (modules)
+ {
+ unsigned n = dump.push (NULL);
+ dump () && dump ("Imported %u modules", modules->length () - 1);
+ dump () && dump ("Containing %u clusters", available_clusters);
+ dump () && dump ("Loaded %u clusters (%u%%)", loaded_clusters,
+ (loaded_clusters * 100 + available_clusters / 2) /
+ (available_clusters + !available_clusters));
+ dump.pop (n);
+ }
+
+ if (modules && !header_module_p ())
+ {
+ /* Determine call_init_p. We need the same bitmap allocation
+ scheme as for the imports member. */
+ function_depth++; /* Disable GC. */
+ bitmap indirect_imports (BITMAP_GGC_ALLOC ());
+
+ /* Because indirect imports are before their direct import, and
+ we're scanning the array backwards, we only need one pass! */
+ for (unsigned ix = modules->length (); --ix;)
+ {
+ module_state *import = (*modules)[ix];
+
+ if (!import->is_header ()
+ && !bitmap_bit_p (indirect_imports, ix))
+ {
+ /* Everything this imports is therefore indirectly
+ imported. */
+ bitmap_ior_into (indirect_imports, import->imports);
+ /* We don't have to worry about the self-import bit,
+ because of the single pass. */
+
+ import->call_init_p = true;
+ num_init_calls_needed++;
+ }
+ }
+ function_depth--;
+ }
+}
+
+void
+fini_modules ()
+{
+ /* We're done with the macro tables now. */
+ vec_free (macro_exports);
+ vec_free (macro_imports);
+ headers = NULL;
+
+ /* We're now done with everything but the module names. */
+ set_cmi_repo (NULL);
+ if (mapper)
+ {
+ timevar_start (TV_MODULE_MAPPER);
+ module_client::close_module_client (0, mapper);
+ mapper = nullptr;
+ timevar_stop (TV_MODULE_MAPPER);
+ }
+ module_state_config::release ();
+
+#if CHECKING_P
+ note_defs = NULL;
+#endif
+
+ if (modules)
+ for (unsigned ix = modules->length (); --ix;)
+ if (module_state *state = (*modules)[ix])
+ state->release ();
+
+ /* No need to lookup modules anymore. */
+ modules_hash = NULL;
+
+ /* Or entity array. We still need the entity map to find import numbers. */
+ delete entity_ary;
+ entity_ary = NULL;
+
+ /* Or remember any pending entities. */
+ delete pending_table;
+ pending_table = NULL;
+
+ /* Or any attachments -- Let it go! */
+ delete attached_table;
+ attached_table = NULL;
+
+ /* Allow a GC, we've possibly made much data unreachable. */
+ ggc_collect ();
+}
+
+/* If CODE is a module option, handle it & return true. Otherwise
+ return false. For unknown reasons I cannot get the option
+ generation machinery to set fmodule-mapper or -fmodule-header to
+ make a string type option variable. */
+
+bool
+handle_module_option (unsigned code, const char *str, int)
+{
+ auto hdr = CMS_header;
+
+ switch (opt_code (code))
+ {
+ case OPT_fmodule_mapper_:
+ module_mapper_name = str;
+ return true;
+
+ case OPT_fmodule_header_:
+ {
+ if (!strcmp (str, "user"))
+ hdr = CMS_user;
+ else if (!strcmp (str, "system"))
+ hdr = CMS_system;
+ else
+ error ("unknown header kind %qs", str);
+ }
+ /* Fallthrough. */
+
+ case OPT_fmodule_header:
+ flag_header_unit = hdr;
+ flag_modules = 1;
+ return true;
+
+ case OPT_flang_info_include_translate_:
+ vec_safe_push (note_includes, str);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Set preprocessor callbacks and options for modules. */
+
+void
+module_preprocess_options (cpp_reader *reader)
+{
+ gcc_checking_assert (!lang_hooks.preprocess_undef);
+ if (modules_p ())
+ {
+ auto *cb = cpp_get_callbacks (reader);
+
+ cb->translate_include = maybe_translate_include;
+ cb->user_deferred_macro = module_state::deferred_macro;
+ if (flag_header_unit)
+ {
+ /* If the preprocessor hook is already in use, that
+ implementation will call the undef langhook. */
+ if (cb->undef)
+ lang_hooks.preprocess_undef = module_state::undef_macro;
+ else
+ cb->undef = module_state::undef_macro;
+ }
+ auto *opt = cpp_get_options (reader);
+ opt->module_directives = true;
+ opt->main_search = cpp_main_search (flag_header_unit);
+ }
+}
+
+#include "gt-cp-module.h"
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 4637427..ab669bc 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/name-hint.h"
#include "c-family/known-headers.h"
#include "c-family/c-spellcheck.h"
+#include "bitmap.h"
static cxx_binding *cxx_binding_make (tree value, tree type);
static cp_binding_level *innermost_nonclass_level (void);
@@ -46,16 +47,33 @@ static name_hint maybe_suggest_missing_std_header (location_t location,
static name_hint suggest_alternatives_for_1 (location_t location, tree name,
bool suggest_misspellings);
+/* Slots in BINDING_VECTOR. */
+enum binding_slots
+{
+ BINDING_SLOT_CURRENT, /* Slot for current TU. */
+ BINDING_SLOT_GLOBAL, /* Slot for merged global module. */
+ BINDING_SLOT_PARTITION, /* Slot for merged partition entities
+ (optional). */
+
+ /* Number of always-allocated slots. */
+ BINDING_SLOTS_FIXED = BINDING_SLOT_GLOBAL + 1
+};
+
/* Create an overload suitable for recording an artificial TYPE_DECL
and another decl. We use this machanism to implement the struct
- stat hack within a namespace. It'd be nice to use it everywhere. */
+ stat hack. */
#define STAT_HACK_P(N) ((N) && TREE_CODE (N) == OVERLOAD && OVL_LOOKUP_P (N))
+#define STAT_TYPE_VISIBLE_P(N) TREE_USED (OVERLOAD_CHECK (N))
#define STAT_TYPE(N) TREE_TYPE (N)
#define STAT_DECL(N) OVL_FUNCTION (N)
+#define STAT_VISIBLE(N) OVL_CHAIN (N)
#define MAYBE_STAT_DECL(N) (STAT_HACK_P (N) ? STAT_DECL (N) : N)
#define MAYBE_STAT_TYPE(N) (STAT_HACK_P (N) ? STAT_TYPE (N) : NULL_TREE)
+/* When a STAT_HACK_P is true, OVL_USING_P and OVL_EXPORT_P are valid
+ and apply to the hacked type. */
+
/* For regular (maybe) overloaded functions, we have OVL_HIDDEN_P.
But we also need to indicate hiddenness on implicit type decls
(injected friend classes), and (coming soon) decls injected from
@@ -116,7 +134,246 @@ find_namespace_value (tree ns, tree name)
return b ? MAYBE_STAT_DECL (*b) : NULL_TREE;
}
-/* Add DECL to the list of things declared in B. */
+/* Look in *SLOT for a the binding of NAME in imported module IX.
+ Returns pointer to binding's slot, or NULL if not found. Does a
+ binary search, as this is mainly used for random access during
+ importing. Do not use for the fixed slots. */
+
+static binding_slot *
+search_imported_binding_slot (tree *slot, unsigned ix)
+{
+ gcc_assert (ix);
+
+ if (!*slot)
+ return NULL;
+
+ if (TREE_CODE (*slot) != BINDING_VECTOR)
+ return NULL;
+
+ unsigned clusters = BINDING_VECTOR_NUM_CLUSTERS (*slot);
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (*slot);
+
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ clusters--;
+ cluster++;
+ }
+
+ while (clusters > 1)
+ {
+ unsigned half = clusters / 2;
+ gcc_checking_assert (cluster[half].indices[0].span);
+ if (cluster[half].indices[0].base > ix)
+ clusters = half;
+ else
+ {
+ clusters -= half;
+ cluster += half;
+ }
+ }
+
+ if (clusters)
+ /* Is it in this cluster? */
+ for (unsigned off = 0; off != BINDING_VECTOR_SLOTS_PER_CLUSTER; off++)
+ {
+ if (!cluster->indices[off].span)
+ break;
+ if (cluster->indices[off].base > ix)
+ break;
+
+ if (cluster->indices[off].base + cluster->indices[off].span > ix)
+ return &cluster->slots[off];
+ }
+
+ return NULL;
+}
+
+static void
+init_global_partition (binding_cluster *cluster, tree decl)
+{
+ bool purview = true;
+
+ if (header_module_p ())
+ purview = false;
+ else if (TREE_PUBLIC (decl)
+ && TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl))
+ purview = false;
+ else if (!get_originating_module (decl))
+ purview = false;
+
+ binding_slot *mslot;
+ if (!purview)
+ mslot = &cluster[0].slots[BINDING_SLOT_GLOBAL];
+ else
+ mslot = &cluster[BINDING_SLOT_PARTITION
+ / BINDING_VECTOR_SLOTS_PER_CLUSTER]
+ .slots[BINDING_SLOT_PARTITION
+ % BINDING_VECTOR_SLOTS_PER_CLUSTER];
+
+ if (*mslot)
+ decl = ovl_make (decl, *mslot);
+ *mslot = decl;
+
+ if (TREE_CODE (decl) == CONST_DECL)
+ {
+ tree type = TREE_TYPE (decl);
+ if (TREE_CODE (type) == ENUMERAL_TYPE
+ && IDENTIFIER_ANON_P (DECL_NAME (TYPE_NAME (type)))
+ && decl == TREE_VALUE (TYPE_VALUES (type)))
+ /* Anonymous enums are keyed by their first enumerator, put
+ the TYPE_DECL here too. */
+ *mslot = ovl_make (TYPE_NAME (type), *mslot);
+ }
+}
+
+/* Get the fixed binding slot IX. Creating the vector if CREATE is
+ non-zero. If CREATE is < 0, make sure there is at least 1 spare
+ slot for an import. (It is an error for CREATE < 0 and the slot to
+ already exist.) */
+
+static tree *
+get_fixed_binding_slot (tree *slot, tree name, unsigned ix, int create)
+{
+ gcc_checking_assert (ix <= BINDING_SLOT_PARTITION);
+
+ /* An assumption is that the fixed slots all reside in one cluster. */
+ gcc_checking_assert (BINDING_VECTOR_SLOTS_PER_CLUSTER >= BINDING_SLOTS_FIXED);
+
+ if (!*slot || TREE_CODE (*slot) != BINDING_VECTOR)
+ {
+ if (ix == BINDING_SLOT_CURRENT)
+ /* The current TU can just use slot directly. */
+ return slot;
+
+ if (!create)
+ return NULL;
+
+ /* The partition slot is only needed when we know we're a named
+ module. */
+ bool partition_slot = named_module_p ();
+ unsigned want = ((BINDING_SLOTS_FIXED + partition_slot + (create < 0)
+ + BINDING_VECTOR_SLOTS_PER_CLUSTER - 1)
+ / BINDING_VECTOR_SLOTS_PER_CLUSTER);
+ tree new_vec = make_binding_vec (name, want);
+ BINDING_VECTOR_NUM_CLUSTERS (new_vec) = want;
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (new_vec);
+
+ /* Initialize the fixed slots. */
+ for (unsigned jx = BINDING_SLOTS_FIXED; jx--;)
+ {
+ cluster[0].indices[jx].base = 0;
+ cluster[0].indices[jx].span = 1;
+ cluster[0].slots[jx] = NULL_TREE;
+ }
+
+ if (partition_slot)
+ {
+ unsigned off = BINDING_SLOT_PARTITION % BINDING_VECTOR_SLOTS_PER_CLUSTER;
+ unsigned ind = BINDING_SLOT_PARTITION / BINDING_VECTOR_SLOTS_PER_CLUSTER;
+ cluster[ind].indices[off].base = 0;
+ cluster[ind].indices[off].span = 1;
+ cluster[ind].slots[off] = NULL_TREE;
+ }
+
+ if (tree orig = *slot)
+ {
+ /* Propagate existing value to current slot. */
+
+ /* Propagate global & module entities to the global and
+ partition slots. */
+ if (tree type = MAYBE_STAT_TYPE (orig))
+ init_global_partition (cluster, type);
+
+ for (ovl_iterator iter (MAYBE_STAT_DECL (orig)); iter; ++iter)
+ {
+ tree decl = *iter;
+
+ /* Internal linkage entities are in deduplicateable. */
+ init_global_partition (cluster, decl);
+ }
+
+ if (cluster[0].slots[BINDING_SLOT_GLOBAL]
+ && !(TREE_CODE (orig) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (orig)))
+ {
+ /* Note that we had some GMF entries. */
+ if (!STAT_HACK_P (orig))
+ orig = stat_hack (orig);
+
+ MODULE_BINDING_GLOBAL_P (orig) = true;
+ }
+
+ cluster[0].slots[BINDING_SLOT_CURRENT] = orig;
+ }
+
+ *slot = new_vec;
+ }
+ else
+ gcc_checking_assert (create >= 0);
+
+ unsigned off = ix % BINDING_VECTOR_SLOTS_PER_CLUSTER;
+ binding_cluster &cluster
+ = BINDING_VECTOR_CLUSTER (*slot, ix / BINDING_VECTOR_SLOTS_PER_CLUSTER);
+
+ /* There must always be slots for these indices */
+ gcc_checking_assert (cluster.indices[off].span == 1
+ && !cluster.indices[off].base
+ && !cluster.slots[off].is_lazy ());
+
+ return reinterpret_cast<tree *> (&cluster.slots[off]);
+}
+
+/* *SLOT is a namespace binding slot. Append a slot for imported
+ module IX. */
+
+static binding_slot *
+append_imported_binding_slot (tree *slot, tree name, unsigned ix)
+{
+ gcc_checking_assert (ix);
+
+ if (!*slot || TREE_CODE (*slot) != BINDING_VECTOR)
+ /* Make an initial module vector. */
+ get_fixed_binding_slot (slot, name, BINDING_SLOT_GLOBAL, -1);
+ else if (!BINDING_VECTOR_CLUSTER_LAST (*slot)
+ ->indices[BINDING_VECTOR_SLOTS_PER_CLUSTER - 1].span)
+ /* There is space in the last cluster. */;
+ else if (BINDING_VECTOR_NUM_CLUSTERS (*slot)
+ != BINDING_VECTOR_ALLOC_CLUSTERS (*slot))
+ /* There is space in the vector. */
+ BINDING_VECTOR_NUM_CLUSTERS (*slot)++;
+ else
+ {
+ /* Extend the vector. */
+ unsigned have = BINDING_VECTOR_NUM_CLUSTERS (*slot);
+ unsigned want = (have * 3 + 1) / 2;
+
+ if (want > (unsigned short)~0)
+ want = (unsigned short)~0;
+
+ tree new_vec = make_binding_vec (name, want);
+ BINDING_VECTOR_NUM_CLUSTERS (new_vec) = have + 1;
+ memcpy (BINDING_VECTOR_CLUSTER_BASE (new_vec),
+ BINDING_VECTOR_CLUSTER_BASE (*slot),
+ have * sizeof (binding_cluster));
+ *slot = new_vec;
+ }
+
+ binding_cluster *last = BINDING_VECTOR_CLUSTER_LAST (*slot);
+ for (unsigned off = 0; off != BINDING_VECTOR_SLOTS_PER_CLUSTER; off++)
+ if (!last->indices[off].span)
+ {
+ /* Fill the free slot of the cluster. */
+ last->indices[off].base = ix;
+ last->indices[off].span = 1;
+ last->slots[off] = NULL_TREE;
+ return &last->slots[off];
+ }
+
+ gcc_unreachable ();
+}
+
+/* Add DECL to the list of things declared in binding level B. */
static void
add_decl_to_level (cp_binding_level *b, tree decl)
@@ -171,8 +428,13 @@ public:
public:
tree name; /* The identifier being looked for. */
+
+ /* Usually we just add things to the VALUE binding, but we record
+ (hidden) IMPLICIT_TYPEDEFs on the type binding, which is used for
+ using-decl resolution. */
tree value; /* A (possibly ambiguous) set of things found. */
tree type; /* A type that has been found. */
+
LOOK_want want; /* What kind of entity we want. */
bool deduping; /* Full deduping is needed because using declarations
@@ -238,7 +500,7 @@ private:
void add_value (tree new_val);
void add_type (tree new_type);
bool process_binding (tree val_bind, tree type_bind);
-
+ unsigned process_module_binding (tree val_bind, tree type_bind, unsigned);
/* Look in only namespace. */
bool search_namespace_only (tree scope);
/* Look in namespace and its (recursive) inlines. Ignore using
@@ -263,14 +525,17 @@ private:
private:
void add_fns (tree);
+ private:
void adl_expr (tree);
void adl_type (tree);
void adl_template_arg (tree);
void adl_class (tree);
+ void adl_enum (tree);
void adl_bases (tree);
void adl_class_only (tree);
void adl_namespace (tree);
- void adl_namespace_only (tree);
+ void adl_class_fns (tree);
+ void adl_namespace_fns (tree, bitmap);
public:
/* Search namespace + inlines + maybe usings as qualified lookup. */
@@ -433,8 +698,8 @@ name_lookup::add_overload (tree fns)
if (probe && TREE_CODE (probe) == OVERLOAD
&& OVL_DEDUP_P (probe))
{
- /* We're about to add something found by a using
- declaration, so need to engage deduping mode. */
+ /* We're about to add something found by multiple paths, so
+ need to engage deduping mode. */
lookup_mark (value, true);
deduping = true;
}
@@ -540,36 +805,190 @@ name_lookup::process_binding (tree new_val, tree new_type)
return new_val != NULL_TREE;
}
+/* If we're importing a module containing this binding, add it to the
+ lookup set. The trickiness is with namespaces, we only want to
+ find it once. */
+
+unsigned
+name_lookup::process_module_binding (tree new_val, tree new_type,
+ unsigned marker)
+{
+ /* Optimize for (re-)finding a public namespace. We only need to
+ look once. */
+ if (new_val && !new_type
+ && TREE_CODE (new_val) == NAMESPACE_DECL
+ && TREE_PUBLIC (new_val)
+ && !DECL_NAMESPACE_ALIAS (new_val))
+ {
+ if (marker & 2)
+ return marker;
+ marker |= 2;
+ }
+
+ if (new_type || new_val)
+ marker |= process_binding (new_val, new_type);
+
+ return marker;
+}
+
/* Look in exactly namespace SCOPE. */
bool
name_lookup::search_namespace_only (tree scope)
{
bool found = false;
-
if (tree *binding = find_namespace_slot (scope, name))
{
- tree value = *binding, type = NULL_TREE;
-
- if (STAT_HACK_P (value))
+ tree val = *binding;
+ if (TREE_CODE (val) == BINDING_VECTOR)
{
- type = STAT_TYPE (value);
- value = STAT_DECL (value);
-
- if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+ /* I presume the binding list is going to be sparser than
+ the import bitmap. Hence iterate over the former
+ checking for bits set in the bitmap. */
+ bitmap imports = get_import_bitmap ();
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (val);
+ int marker = 0;
+ int dup_detect = 0;
+
+ if (tree bind = cluster->slots[BINDING_SLOT_CURRENT])
{
- if (STAT_TYPE_HIDDEN_P (*binding))
- type = NULL_TREE;
- if (STAT_DECL_HIDDEN_P (*binding))
- value = NULL_TREE;
- else
+ if (!deduping)
+ {
+ if (named_module_purview_p ())
+ {
+ dup_detect |= 2;
+
+ if (STAT_HACK_P (bind) && MODULE_BINDING_GLOBAL_P (bind))
+ dup_detect |= 1;
+ }
+ else
+ dup_detect |= 1;
+ }
+ tree type = NULL_TREE;
+ tree value = bind;
+
+ if (STAT_HACK_P (bind))
+ {
+ type = STAT_TYPE (bind);
+ value = STAT_DECL (bind);
+
+ if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+ {
+ if (STAT_TYPE_HIDDEN_P (bind))
+ type = NULL_TREE;
+ if (STAT_DECL_HIDDEN_P (bind))
+ value = NULL_TREE;
+ else
+ value = ovl_skip_hidden (value);
+ }
+ }
+ else if (!bool (want & LOOK_want::HIDDEN_FRIEND))
value = ovl_skip_hidden (value);
+
+ marker = process_module_binding (value, type, marker);
}
+
+ /* Scan the imported bindings. */
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (val);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ /* Do this in forward order, so we load modules in an order
+ the user expects. */
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ {
+ /* Are we importing this module? */
+ if (unsigned base = cluster->indices[jx].base)
+ if (unsigned span = cluster->indices[jx].span)
+ do
+ if (bitmap_bit_p (imports, base))
+ goto found;
+ while (++base, --span);
+ continue;
+
+ found:;
+ /* Is it loaded? */
+ if (cluster->slots[jx].is_lazy ())
+ {
+ gcc_assert (cluster->indices[jx].span == 1);
+ lazy_load_binding (cluster->indices[jx].base,
+ scope, name, &cluster->slots[jx]);
+ }
+ tree bind = cluster->slots[jx];
+ if (!bind)
+ /* Load errors could mean there's nothing here. */
+ continue;
+
+ /* Extract what we can see from here. If there's no
+ stat_hack, then everything was exported. */
+ tree type = NULL_TREE;
+
+
+ /* If STAT_HACK_P is false, everything is visible, and
+ there's no duplication possibilities. */
+ if (STAT_HACK_P (bind))
+ {
+ if (!deduping)
+ {
+ /* Do we need to engage deduplication? */
+ int dup = 0;
+ if (MODULE_BINDING_GLOBAL_P (bind))
+ dup = 1;
+ else if (MODULE_BINDING_PARTITION_P (bind))
+ dup = 2;
+ if (unsigned hit = dup_detect & dup)
+ {
+ if ((hit & 1 && BINDING_VECTOR_GLOBAL_DUPS_P (val))
+ || (hit & 2
+ && BINDING_VECTOR_PARTITION_DUPS_P (val)))
+ {
+ lookup_mark (value, true);
+ deduping = true;
+ }
+ }
+ dup_detect |= dup;
+ }
+
+ if (STAT_TYPE_VISIBLE_P (bind))
+ type = STAT_TYPE (bind);
+ bind = STAT_VISIBLE (bind);
+ }
+
+ /* And process it. */
+ marker = process_module_binding (bind, type, marker);
+ }
+ found |= marker & 1;
}
- else if (!bool (want & LOOK_want::HIDDEN_FRIEND))
- value = ovl_skip_hidden (value);
+ else
+ {
+ /* Only a current module binding, visible from the current module. */
+ tree bind = *binding;
+ tree value = bind, type = NULL_TREE;
+
+ if (STAT_HACK_P (bind))
+ {
+ type = STAT_TYPE (bind);
+ value = STAT_DECL (bind);
- found |= process_binding (value, type);
+ if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+ {
+ if (STAT_TYPE_HIDDEN_P (bind))
+ type = NULL_TREE;
+ if (STAT_DECL_HIDDEN_P (bind))
+ value = NULL_TREE;
+ else
+ value = ovl_skip_hidden (value);
+ }
+ }
+ else if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+ value = ovl_skip_hidden (value);
+
+ found |= process_binding (value, type);
+ }
}
return found;
@@ -777,20 +1196,147 @@ name_lookup::add_fns (tree fns)
add_overload (fns);
}
-/* Add functions of a namespace to the lookup structure. */
+/* Add the overloaded fns of SCOPE. */
void
-name_lookup::adl_namespace_only (tree scope)
+name_lookup::adl_namespace_fns (tree scope, bitmap imports)
{
- mark_seen (scope);
+ if (tree *binding = find_namespace_slot (scope, name))
+ {
+ tree val = *binding;
+ if (TREE_CODE (val) != BINDING_VECTOR)
+ add_fns (ovl_skip_hidden (MAYBE_STAT_DECL (val)));
+ else
+ {
+ /* I presume the binding list is going to be sparser than
+ the import bitmap. Hence iterate over the former
+ checking for bits set in the bitmap. */
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (val);
+ int dup_detect = 0;
- /* Look down into inline namespaces. */
- if (vec<tree, va_gc> *inlinees = DECL_NAMESPACE_INLINEES (scope))
- for (unsigned ix = inlinees->length (); ix--;)
- adl_namespace_only ((*inlinees)[ix]);
+ if (tree bind = cluster->slots[BINDING_SLOT_CURRENT])
+ {
+ /* The current TU's bindings must be visible, we don't
+ need to check the bitmaps. */
+
+ if (!deduping)
+ {
+ if (named_module_purview_p ())
+ {
+ dup_detect |= 2;
+
+ if (STAT_HACK_P (bind) && MODULE_BINDING_GLOBAL_P (bind))
+ dup_detect |= 1;
+ }
+ else
+ dup_detect |= 1;
+ }
+
+ add_fns (ovl_skip_hidden (MAYBE_STAT_DECL (bind)));
+ }
+
+ /* Scan the imported bindings. */
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (val);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ /* Do this in forward order, so we load modules in an order
+ the user expects. */
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ {
+ /* Functions are never on merged slots. */
+ if (!cluster->indices[jx].base
+ || cluster->indices[jx].span != 1)
+ continue;
+
+ /* Is this slot visible? */
+ if (!bitmap_bit_p (imports, cluster->indices[jx].base))
+ continue;
+
+ /* Is it loaded. */
+ if (cluster->slots[jx].is_lazy ())
+ lazy_load_binding (cluster->indices[jx].base,
+ scope, name, &cluster->slots[jx]);
+
+ tree bind = cluster->slots[jx];
+ if (!bind)
+ /* Load errors could mean there's nothing here. */
+ continue;
+
+ if (STAT_HACK_P (bind))
+ {
+ if (!deduping)
+ {
+ /* Do we need to engage deduplication? */
+ int dup = 0;
+ if (MODULE_BINDING_GLOBAL_P (bind))
+ dup = 1;
+ else if (MODULE_BINDING_PARTITION_P (bind))
+ dup = 2;
+ if (unsigned hit = dup_detect & dup)
+ {
+ if ((hit & 1 && BINDING_VECTOR_GLOBAL_DUPS_P (val))
+ || (hit & 2
+ && BINDING_VECTOR_PARTITION_DUPS_P (val)))
+ {
+ lookup_mark (value, true);
+ deduping = true;
+ }
+ }
+ dup_detect |= dup;
+ }
+
+ bind = STAT_VISIBLE (bind);
+ }
+
+ add_fns (bind);
+ }
+ }
+ }
+}
+
+/* Add the hidden friends of SCOPE. */
+
+void
+name_lookup::adl_class_fns (tree type)
+{
+ /* Add friends. */
+ for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
+ list; list = TREE_CHAIN (list))
+ if (name == FRIEND_NAME (list))
+ {
+ tree context = NULL_TREE; /* Lazily computed. */
+ for (tree friends = FRIEND_DECLS (list); friends;
+ friends = TREE_CHAIN (friends))
+ {
+ tree fn = TREE_VALUE (friends);
+
+ /* Only interested in global functions with potentially hidden
+ (i.e. unqualified) declarations. */
+ if (!context)
+ context = decl_namespace_context (type);
+ if (CP_DECL_CONTEXT (fn) != context)
+ continue;
+
+ if (!deduping)
+ {
+ lookup_mark (value, true);
+ deduping = true;
+ }
+
+ /* Template specializations are never found by name lookup.
+ (Templates themselves can be found, but not template
+ specializations.) */
+ if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn))
+ continue;
- if (tree fns = find_namespace_value (scope, name))
- add_fns (ovl_skip_hidden (fns));
+ add_fns (fn);
+ }
+ }
}
/* Find the containing non-inlined namespace, add it and all its
@@ -799,14 +1345,17 @@ name_lookup::adl_namespace_only (tree scope)
void
name_lookup::adl_namespace (tree scope)
{
- if (seen_p (scope))
+ if (see_and_mark (scope))
return;
- /* Find the containing non-inline namespace. */
- while (DECL_NAMESPACE_INLINE_P (scope))
- scope = CP_DECL_CONTEXT (scope);
+ /* Look down into inline namespaces. */
+ if (vec<tree, va_gc> *inlinees = DECL_NAMESPACE_INLINEES (scope))
+ for (unsigned ix = inlinees->length (); ix--;)
+ adl_namespace ((*inlinees)[ix]);
- adl_namespace_only (scope);
+ if (DECL_NAMESPACE_INLINE_P (scope))
+ /* Mark parent. */
+ adl_namespace (CP_DECL_CONTEXT (scope));
}
/* Adds the class and its friends to the lookup structure. */
@@ -826,31 +1375,6 @@ name_lookup::adl_class_only (tree type)
tree context = decl_namespace_context (type);
adl_namespace (context);
-
- complete_type (type);
-
- /* Add friends. */
- for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
- list = TREE_CHAIN (list))
- if (name == FRIEND_NAME (list))
- for (tree friends = FRIEND_DECLS (list); friends;
- friends = TREE_CHAIN (friends))
- {
- tree fn = TREE_VALUE (friends);
-
- /* Only interested in global functions with potentially hidden
- (i.e. unqualified) declarations. */
- if (CP_DECL_CONTEXT (fn) != context)
- continue;
-
- /* Template specializations are never found by name lookup.
- (Templates themselves can be found, but not template
- specializations.) */
- if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn))
- continue;
-
- add_fns (fn);
- }
}
/* Adds the class and its bases to the lookup structure.
@@ -873,7 +1397,7 @@ name_lookup::adl_bases (tree type)
}
/* Adds everything associated with a class argument type to the lookup
- structure. Returns true on error.
+ structure.
If T is a class type (including unions), its associated classes are: the
class itself; the class of which it is a member, if any; and its direct
@@ -897,11 +1421,13 @@ name_lookup::adl_class (tree type)
return;
type = TYPE_MAIN_VARIANT (type);
+
/* We don't set found here because we have to have set seen first,
which is done in the adl_bases walk. */
if (found_p (type))
return;
+ complete_type (type);
adl_bases (type);
mark_found (type);
@@ -919,6 +1445,19 @@ name_lookup::adl_class (tree type)
}
void
+name_lookup::adl_enum (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ if (see_and_mark (type))
+ return;
+
+ if (TYPE_CLASS_SCOPE_P (type))
+ adl_class_only (TYPE_CONTEXT (type));
+ else
+ adl_namespace (decl_namespace_context (type));
+}
+
+void
name_lookup::adl_expr (tree expr)
{
if (!expr)
@@ -1003,9 +1542,7 @@ name_lookup::adl_type (tree type)
return;
case ENUMERAL_TYPE:
- if (TYPE_CLASS_SCOPE_P (type))
- adl_class_only (TYPE_CONTEXT (type));
- adl_namespace (decl_namespace_context (type));
+ adl_enum (type);
return;
case LANG_TYPE:
@@ -1074,10 +1611,9 @@ name_lookup::adl_template_arg (tree arg)
tree
name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
{
- deduping = true;
- lookup_mark (fns, true);
- value = fns;
-
+ gcc_checking_assert (!vec_safe_length (scopes));
+
+ /* Gather each associated entity onto the lookup's scope list. */
unsigned ix;
tree arg;
@@ -1089,7 +1625,91 @@ name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
else
adl_expr (arg);
- fns = value;
+ if (vec_safe_length (scopes))
+ {
+ /* Now do the lookups. */
+ if (fns)
+ {
+ deduping = true;
+ lookup_mark (fns, true);
+ }
+ value = fns;
+
+ /* INST_PATH will be NULL, if this is /not/ 2nd-phase ADL. */
+ bitmap inst_path = NULL;
+ /* VISIBLE is the regular import bitmap. */
+ bitmap visible = visible_instantiation_path (&inst_path);
+
+ for (unsigned ix = scopes->length (); ix--;)
+ {
+ tree scope = (*scopes)[ix];
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ adl_namespace_fns (scope, visible);
+ else
+ {
+ if (RECORD_OR_UNION_TYPE_P (scope))
+ adl_class_fns (scope);
+
+ /* During 2nd phase ADL: Any exported declaration D in N
+ declared within the purview of a named module M
+ (10.2) is visible if there is an associated entity
+ attached to M with the same innermost enclosing
+ non-inline namespace as D.
+ [basic.lookup.argdep]/4.4 */
+
+ if (!inst_path)
+ /* Not 2nd phase. */
+ continue;
+
+ tree ctx = CP_DECL_CONTEXT (TYPE_NAME (scope));
+ if (TREE_CODE (ctx) != NAMESPACE_DECL)
+ /* Not namespace-scope class. */
+ continue;
+
+ tree origin = get_originating_module_decl (TYPE_NAME (scope));
+ if (!DECL_LANG_SPECIFIC (origin)
+ || !DECL_MODULE_IMPORT_P (origin))
+ /* Not imported. */
+ continue;
+
+ unsigned module = get_importing_module (origin);
+
+ if (!bitmap_bit_p (inst_path, module))
+ /* Not on path of instantiation. */
+ continue;
+
+ if (bitmap_bit_p (visible, module))
+ /* If the module was in the visible set, we'll look at
+ its namespace partition anyway. */
+ continue;
+
+ if (tree *slot = find_namespace_slot (ctx, name, false))
+ if (binding_slot *mslot = search_imported_binding_slot (slot, module))
+ {
+ if (mslot->is_lazy ())
+ lazy_load_binding (module, ctx, name, mslot);
+
+ if (tree bind = *mslot)
+ {
+ if (!deduping)
+ {
+ /* We must turn on deduping, because some
+ other class from this module might also
+ be in this namespace. */
+ deduping = true;
+ lookup_mark (value, true);
+ }
+
+ /* Add the exported fns */
+ if (STAT_HACK_P (bind))
+ add_fns (STAT_VISIBLE (bind));
+ }
+ }
+ }
+ }
+
+ fns = value;
+ }
return fns;
}
@@ -1284,6 +1904,41 @@ get_class_binding_direct (tree klass, tree name, bool want_type)
return val;
}
+/* We're about to lookup NAME in KLASS. Make sure any lazily declared
+ members are now declared. */
+
+static void
+maybe_lazily_declare (tree klass, tree name)
+{
+ tree main_decl = TYPE_NAME (TYPE_MAIN_VARIANT (klass));
+ if (DECL_LANG_SPECIFIC (main_decl)
+ && DECL_MODULE_PENDING_MEMBERS_P (main_decl))
+ lazy_load_members (main_decl);
+
+ /* Lazily declare functions, if we're going to search these. */
+ if (IDENTIFIER_CTOR_P (name))
+ {
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (klass))
+ lazily_declare_fn (sfk_constructor, klass);
+ if (CLASSTYPE_LAZY_COPY_CTOR (klass))
+ lazily_declare_fn (sfk_copy_constructor, klass);
+ if (CLASSTYPE_LAZY_MOVE_CTOR (klass))
+ lazily_declare_fn (sfk_move_constructor, klass);
+ }
+ else if (IDENTIFIER_DTOR_P (name))
+ {
+ if (CLASSTYPE_LAZY_DESTRUCTOR (klass))
+ lazily_declare_fn (sfk_destructor, klass);
+ }
+ else if (name == assign_op_identifier)
+ {
+ if (CLASSTYPE_LAZY_COPY_ASSIGN (klass))
+ lazily_declare_fn (sfk_copy_assignment, klass);
+ if (CLASSTYPE_LAZY_MOVE_ASSIGN (klass))
+ lazily_declare_fn (sfk_move_assignment, klass);
+ }
+}
+
/* Look for NAME's binding in exactly KLASS. See
get_class_binding_direct for argument description. Does lazy
special function creation as necessary. */
@@ -1294,30 +1949,7 @@ get_class_binding (tree klass, tree name, bool want_type /*=false*/)
klass = complete_type (klass);
if (COMPLETE_TYPE_P (klass))
- {
- /* Lazily declare functions, if we're going to search these. */
- if (IDENTIFIER_CTOR_P (name))
- {
- if (CLASSTYPE_LAZY_DEFAULT_CTOR (klass))
- lazily_declare_fn (sfk_constructor, klass);
- if (CLASSTYPE_LAZY_COPY_CTOR (klass))
- lazily_declare_fn (sfk_copy_constructor, klass);
- if (CLASSTYPE_LAZY_MOVE_CTOR (klass))
- lazily_declare_fn (sfk_move_constructor, klass);
- }
- else if (IDENTIFIER_DTOR_P (name))
- {
- if (CLASSTYPE_LAZY_DESTRUCTOR (klass))
- lazily_declare_fn (sfk_destructor, klass);
- }
- else if (name == assign_op_identifier)
- {
- if (CLASSTYPE_LAZY_COPY_ASSIGN (klass))
- lazily_declare_fn (sfk_copy_assignment, klass);
- if (CLASSTYPE_LAZY_MOVE_ASSIGN (klass))
- lazily_declare_fn (sfk_move_assignment, klass);
- }
- }
+ maybe_lazily_declare (klass, name);
return get_class_binding_direct (klass, name, want_type);
}
@@ -1338,14 +1970,11 @@ find_member_slot (tree klass, tree name)
vec_alloc (member_vec, 8);
CLASSTYPE_MEMBER_VEC (klass) = member_vec;
if (complete_p)
- {
- /* If the class is complete but had no member_vec, we need
- to add the TYPE_FIELDS into it. We're also most likely
- to be adding ctors & dtors, so ask for 6 spare slots (the
- abstract cdtors and their clones). */
- set_class_bindings (klass, 6);
- member_vec = CLASSTYPE_MEMBER_VEC (klass);
- }
+ /* If the class is complete but had no member_vec, we need to
+ add the TYPE_FIELDS into it. We're also most likely to be
+ adding ctors & dtors, so ask for 6 spare slots (the
+ abstract cdtors and their clones). */
+ member_vec = set_class_bindings (klass, 6);
}
if (IDENTIFIER_CONV_OP_P (name))
@@ -1687,18 +2316,18 @@ member_vec_dedup (vec<tree, va_gc> *member_vec)
no existing MEMBER_VEC and fewer than 8 fields, do nothing. We
know there must be at least 1 field -- the self-reference
TYPE_DECL, except for anon aggregates, which will have at least
- one field anyway. */
+ one field anyway. If EXTRA < 0, always create the vector. */
-void
-set_class_bindings (tree klass, unsigned extra)
+vec<tree, va_gc> *
+set_class_bindings (tree klass, int extra)
{
unsigned n_fields = count_class_fields (klass);
vec<tree, va_gc> *member_vec = CLASSTYPE_MEMBER_VEC (klass);
- if (member_vec || n_fields >= 8)
+ if (member_vec || n_fields >= 8 || extra < 0)
{
/* Append the new fields. */
- vec_safe_reserve_exact (member_vec, extra + n_fields);
+ vec_safe_reserve_exact (member_vec, n_fields + (extra >= 0 ? extra : 0));
member_vec_append_class_fields (member_vec, klass);
}
@@ -1708,6 +2337,8 @@ set_class_bindings (tree klass, unsigned extra)
member_vec->qsort (member_name_cmp);
member_vec_dedup (member_vec);
}
+
+ return member_vec;
}
/* Insert lately defined enum ENUMTYPE into KLASS for the sorted case. */
@@ -1738,16 +2369,6 @@ insert_late_enum_def_bindings (tree klass, tree enumtype)
}
}
-/* Compute the chain index of a binding_entry given the HASH value of its
- name and the total COUNT of chains. COUNT is assumed to be a power
- of 2. */
-
-#define ENTRY_INDEX(HASH, COUNT) (((HASH) >> 3) & ((COUNT) - 1))
-
-/* A free list of "binding_entry"s awaiting for re-use. */
-
-static GTY((deletable)) binding_entry free_binding_entry = NULL;
-
/* The binding oracle; see cp-tree.h. */
cp_binding_oracle_function *cp_binding_oracle;
@@ -1770,180 +2391,6 @@ query_oracle (tree name)
cp_binding_oracle (CP_ORACLE_IDENTIFIER, name);
}
-/* Create a binding_entry object for (NAME, TYPE). */
-
-static inline binding_entry
-binding_entry_make (tree name, tree type)
-{
- binding_entry entry;
-
- if (free_binding_entry)
- {
- entry = free_binding_entry;
- free_binding_entry = entry->chain;
- }
- else
- entry = ggc_alloc<binding_entry_s> ();
-
- entry->name = name;
- entry->type = type;
- entry->chain = NULL;
-
- return entry;
-}
-
-/* Put ENTRY back on the free list. */
-#if 0
-static inline void
-binding_entry_free (binding_entry entry)
-{
- entry->name = NULL;
- entry->type = NULL;
- entry->chain = free_binding_entry;
- free_binding_entry = entry;
-}
-#endif
-
-/* The datatype used to implement the mapping from names to types at
- a given scope. */
-struct GTY(()) binding_table_s {
- /* Array of chains of "binding_entry"s */
- binding_entry * GTY((length ("%h.chain_count"))) chain;
-
- /* The number of chains in this table. This is the length of the
- member "chain" considered as an array. */
- size_t chain_count;
-
- /* Number of "binding_entry"s in this table. */
- size_t entry_count;
-};
-
-/* Construct TABLE with an initial CHAIN_COUNT. */
-
-static inline void
-binding_table_construct (binding_table table, size_t chain_count)
-{
- table->chain_count = chain_count;
- table->entry_count = 0;
- table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
-}
-
-/* Make TABLE's entries ready for reuse. */
-#if 0
-static void
-binding_table_free (binding_table table)
-{
- size_t i;
- size_t count;
-
- if (table == NULL)
- return;
-
- for (i = 0, count = table->chain_count; i < count; ++i)
- {
- binding_entry temp = table->chain[i];
- while (temp != NULL)
- {
- binding_entry entry = temp;
- temp = entry->chain;
- binding_entry_free (entry);
- }
- table->chain[i] = NULL;
- }
- table->entry_count = 0;
-}
-#endif
-
-/* Allocate a table with CHAIN_COUNT, assumed to be a power of two. */
-
-static inline binding_table
-binding_table_new (size_t chain_count)
-{
- binding_table table = ggc_alloc<binding_table_s> ();
- table->chain = NULL;
- binding_table_construct (table, chain_count);
- return table;
-}
-
-/* Expand TABLE to twice its current chain_count. */
-
-static void
-binding_table_expand (binding_table table)
-{
- const size_t old_chain_count = table->chain_count;
- const size_t old_entry_count = table->entry_count;
- const size_t new_chain_count = 2 * old_chain_count;
- binding_entry *old_chains = table->chain;
- size_t i;
-
- binding_table_construct (table, new_chain_count);
- for (i = 0; i < old_chain_count; ++i)
- {
- binding_entry entry = old_chains[i];
- for (; entry != NULL; entry = old_chains[i])
- {
- const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
- const size_t j = ENTRY_INDEX (hash, new_chain_count);
-
- old_chains[i] = entry->chain;
- entry->chain = table->chain[j];
- table->chain[j] = entry;
- }
- }
- table->entry_count = old_entry_count;
-}
-
-/* Insert a binding for NAME to TYPE into TABLE. */
-
-static void
-binding_table_insert (binding_table table, tree name, tree type)
-{
- const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
- const size_t i = ENTRY_INDEX (hash, table->chain_count);
- binding_entry entry = binding_entry_make (name, type);
-
- entry->chain = table->chain[i];
- table->chain[i] = entry;
- ++table->entry_count;
-
- if (3 * table->chain_count < 5 * table->entry_count)
- binding_table_expand (table);
-}
-
-/* Return the binding_entry, if any, that maps NAME. */
-
-binding_entry
-binding_table_find (binding_table table, tree name)
-{
- const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
- binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
-
- while (entry != NULL && entry->name != name)
- entry = entry->chain;
-
- return entry;
-}
-
-/* Apply PROC -- with DATA -- to all entries in TABLE. */
-
-void
-binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
-{
- size_t chain_count;
- size_t i;
-
- if (!table)
- return;
-
- chain_count = table->chain_count;
- for (i = 0; i < chain_count; ++i)
- {
- binding_entry entry = table->chain[i];
- for (; entry != NULL; entry = entry->chain)
- proc (entry, data);
- }
-}
-
#ifndef ENABLE_SCOPE_CHECKING
# define ENABLE_SCOPE_CHECKING 0
#else
@@ -2040,7 +2487,7 @@ push_binding (tree id, tree decl, cp_binding_level* level)
void
pop_local_binding (tree id, tree decl)
{
- if (id == NULL_TREE)
+ if (!id || IDENTIFIER_ANON_P (id))
/* It's easiest to write the loops that call this function without
checking whether or not the entities involved have names. We
get here for such an entity. */
@@ -2130,7 +2577,7 @@ anticipated_builtin_p (tree ovl)
{
return (TREE_CODE (ovl) == OVERLOAD
&& OVL_HIDDEN_P (ovl)
- && DECL_UNDECLARED_BUILTIN_P (OVL_FUNCTION (ovl)));
+ && DECL_IS_UNDECLARED_BUILTIN (OVL_FUNCTION (ovl)));
}
/* BINDING records an existing declaration for a name in the current scope.
@@ -2255,6 +2702,10 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
region to refer only to the namespace to which it already
refers. */
ok = false;
+ else if (TREE_CODE (bval) == USING_DECL
+ && CONST_DECL_USING_P (decl))
+ /* Let the clone hide the using-decl that introduced it. */
+ binding->value = decl;
else
{
if (!error_operand_p (bval))
@@ -2386,8 +2837,9 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
tree to_type = old_type;
bool local_overload = false;
- gcc_assert (level->kind == sk_namespace ? !binding
+ gcc_assert (!level || level->kind == sk_namespace ? !binding
: level->kind != sk_class && !slot);
+
if (old == error_mark_node)
old = NULL_TREE;
@@ -2463,7 +2915,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
warning (OPT_Wshadow, "%q#D hides constructor for %q#D",
decl, to_type);
- local_overload = old && level->kind != sk_namespace;
+ local_overload = old && level && level->kind != sk_namespace;
to_val = ovl_insert (decl, old, -int (hiding));
}
else if (old)
@@ -2474,11 +2926,8 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
else if (TREE_CODE (old) == TYPE_DECL)
{
if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
- {
- /* Two type decls to the same type. Do nothing. */
- gcc_checking_assert (!hiding);
- return old;
- }
+ /* Two type decls to the same type. Do nothing. */
+ return old;
else
goto conflict;
}
@@ -2490,7 +2939,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
goto conflict;
/* The new one must be an alias at this point. */
- gcc_assert (DECL_NAMESPACE_ALIAS (decl) && !hiding);
+ gcc_assert (DECL_NAMESPACE_ALIAS (decl));
return old;
}
else if (TREE_CODE (old) == VAR_DECL)
@@ -2525,7 +2974,11 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
gcc_checking_assert (binding->value && OVL_P (binding->value));
update_local_overload (binding, to_val);
}
- else
+ else if (level
+ && !(TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl)))
+ /* Don't add namespaces here. They're done in
+ push_namespace. */
add_decl_to_level (level, decl);
if (slot)
@@ -3031,6 +3484,182 @@ push_local_extern_decl_alias (tree decl)
DECL_LOCAL_DECL_ALIAS (decl) = alias;
}
+/* NS needs to be exported, mark it and all its parents as exported. */
+
+static void
+implicitly_export_namespace (tree ns)
+{
+ while (!DECL_MODULE_EXPORT_P (ns))
+ {
+ DECL_MODULE_EXPORT_P (ns) = true;
+ ns = CP_DECL_CONTEXT (ns);
+ }
+}
+
+/* DECL has just been bound at LEVEL. finish up the bookkeeping. */
+
+static void
+newbinding_bookkeeping (tree name, tree decl, cp_binding_level *level)
+{
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ tree type = TREE_TYPE (decl);
+
+ if (type != error_mark_node)
+ {
+ if (TYPE_NAME (type) != decl)
+ set_underlying_type (decl);
+
+ set_identifier_type_value_with_scope (name, decl, level);
+
+ if (level->kind != sk_namespace
+ && !instantiating_current_function_p ())
+ /* This is a locally defined typedef in a function that
+ is not a template instantation, record it to implement
+ -Wunused-local-typedefs. */
+ record_locally_defined_typedef (decl);
+ }
+ }
+ else
+ {
+ if (VAR_P (decl) && !DECL_LOCAL_DECL_P (decl))
+ maybe_register_incomplete_var (decl);
+
+ if (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_EXTERN_C_P (decl))
+ check_extern_c_conflict (decl);
+ }
+}
+
+/* DECL is a global or module-purview entity. If it has non-internal
+ linkage, and we have a module vector, record it in the appropriate
+ slot. We have already checked for duplicates. */
+
+static void
+maybe_record_mergeable_decl (tree *slot, tree name, tree decl)
+{
+ if (TREE_CODE (*slot) != BINDING_VECTOR)
+ return;
+
+ if (!TREE_PUBLIC (CP_DECL_CONTEXT (decl)))
+ /* Member of internal namespace. */
+ return;
+
+ tree not_tmpl = STRIP_TEMPLATE (decl);
+ if ((TREE_CODE (not_tmpl) == FUNCTION_DECL
+ || TREE_CODE (not_tmpl) == VAR_DECL)
+ && DECL_THIS_STATIC (not_tmpl))
+ /* Internal linkage. */
+ return;
+
+ bool partition = named_module_p ();
+ tree *gslot = get_fixed_binding_slot
+ (slot, name, partition ? BINDING_SLOT_PARTITION : BINDING_SLOT_GLOBAL, true);
+
+ if (!partition)
+ {
+ binding_slot &orig
+ = BINDING_VECTOR_CLUSTER (*gslot, 0).slots[BINDING_SLOT_CURRENT];
+
+ if (!STAT_HACK_P (tree (orig)))
+ orig = stat_hack (tree (orig));
+
+ MODULE_BINDING_GLOBAL_P (tree (orig)) = true;
+ }
+
+ add_mergeable_namespace_entity (gslot, decl);
+}
+
+/* DECL is being pushed. Check whether it hides or ambiguates
+ something seen as an import. This include decls seen in our own
+ interface, which is OK. Also, check for merging a
+ global/partition decl. */
+
+static tree
+check_module_override (tree decl, tree mvec, bool hiding,
+ tree scope, tree name)
+{
+ bitmap imports = get_import_bitmap ();
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (mvec);
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (mvec);
+
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ cluster++;
+ ix--;
+ }
+
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ {
+ /* Are we importing this module? */
+ if (cluster->indices[jx].span != 1)
+ continue;
+ if (!cluster->indices[jx].base)
+ continue;
+ if (!bitmap_bit_p (imports, cluster->indices[jx].base))
+ continue;
+ /* Is it loaded? */
+ if (cluster->slots[jx].is_lazy ())
+ {
+ gcc_assert (cluster->indices[jx].span == 1);
+ lazy_load_binding (cluster->indices[jx].base,
+ scope, name, &cluster->slots[jx]);
+ }
+ tree bind = cluster->slots[jx];
+ if (!bind)
+ /* Errors could cause there to be nothing. */
+ continue;
+
+ if (STAT_HACK_P (bind))
+ /* We do not have to check STAT_TYPE here, the xref_tag
+ machinery deals with that problem. */
+ bind = STAT_VISIBLE (bind);
+
+ for (ovl_iterator iter (bind); iter; ++iter)
+ if (iter.using_p ())
+ ;
+ else if (tree match = duplicate_decls (decl, *iter, hiding))
+ {
+ if (TREE_CODE (match) == TYPE_DECL)
+ /* The IDENTIFIER will have the type referring to the
+ now-smashed TYPE_DECL, because ...? Reset it. */
+ SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (match));
+
+ return match;
+ }
+ }
+
+ if (TREE_PUBLIC (scope) && TREE_PUBLIC (decl) && !not_module_p ()
+ /* Namespaces are dealt with specially in
+ make_namespace_finish. */
+ && !(TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl)))
+ {
+ /* Look in the appropriate mergeable decl slot. */
+ tree mergeable = NULL_TREE;
+ if (named_module_p ())
+ mergeable = BINDING_VECTOR_CLUSTER (mvec, BINDING_SLOT_PARTITION
+ / BINDING_VECTOR_SLOTS_PER_CLUSTER)
+ .slots[BINDING_SLOT_PARTITION % BINDING_VECTOR_SLOTS_PER_CLUSTER];
+ else
+ mergeable = BINDING_VECTOR_CLUSTER (mvec, 0).slots[BINDING_SLOT_GLOBAL];
+
+ for (ovl_iterator iter (mergeable); iter; ++iter)
+ {
+ tree match = *iter;
+
+ if (duplicate_decls (decl, match, hiding))
+ {
+ if (TREE_CODE (match) == TYPE_DECL)
+ SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (match));
+ return match;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
/* Record DECL as belonging to the current lexical scope. Check for
errors (such as an incompatible declaration for the same name
already seen in the same scope). IS_FRIEND is true if DECL is
@@ -3059,11 +3688,12 @@ do_pushdecl (tree decl, bool hiding)
/* An anonymous namespace has a NULL DECL_NAME, but we still want to
insert it. Other NULL-named decls, not so much. */
tree name = DECL_NAME (decl);
- if (name || TREE_CODE (decl) == NAMESPACE_DECL)
+ if (name ? !IDENTIFIER_ANON_P (name) : TREE_CODE (decl) == NAMESPACE_DECL)
{
cxx_binding *binding = NULL; /* Local scope binding. */
tree ns = NULL_TREE; /* Searched namespace. */
tree *slot = NULL; /* Binding slot in namespace. */
+ tree *mslot = NULL; /* Current module slot in namespace. */
tree old = NULL_TREE;
if (level->kind == sk_namespace)
@@ -3077,7 +3707,11 @@ do_pushdecl (tree decl, bool hiding)
that's where we'll be pushing anyway. */
slot = find_namespace_slot (ns, name, ns == current_namespace);
if (slot)
- old = MAYBE_STAT_DECL (*slot);
+ {
+ mslot = get_fixed_binding_slot (slot, name, BINDING_SLOT_CURRENT,
+ ns == current_namespace);
+ old = MAYBE_STAT_DECL (*mslot);
+ }
}
else
{
@@ -3092,6 +3726,10 @@ do_pushdecl (tree decl, bool hiding)
for (ovl_iterator iter (old); iter; ++iter)
if (iter.using_p ())
; /* Ignore using decls here. */
+ else if (iter.hidden_p ()
+ && DECL_LANG_SPECIFIC (*iter)
+ && DECL_MODULE_IMPORT_P (*iter))
+ ; /* An undeclared builtin imported from elsewhere. */
else if (tree match
= duplicate_decls (decl, *iter, hiding, iter.hidden_p ()))
{
@@ -3130,6 +3768,26 @@ do_pushdecl (tree decl, bool hiding)
return match;
}
+ /* Check for redeclaring an import. */
+ if (slot && *slot && TREE_CODE (*slot) == BINDING_VECTOR)
+ if (tree match
+ = check_module_override (decl, *slot, hiding, ns, name))
+ {
+ if (match == error_mark_node)
+ return match;
+
+ /* We found a decl in an interface, push it into this
+ binding. */
+ decl = update_binding (NULL, binding, mslot, old,
+ match, hiding);
+
+ if (match == decl && DECL_MODULE_EXPORT_P (decl)
+ && !DECL_MODULE_EXPORT_P (level->this_entity))
+ implicitly_export_namespace (level->this_entity);
+
+ return decl;
+ }
+
/* We are pushing a new decl. */
/* Skip a hidden builtin we failed to match already. There can
@@ -3174,47 +3832,36 @@ do_pushdecl (tree decl, bool hiding)
{
ns = current_namespace;
slot = find_namespace_slot (ns, name, true);
+ mslot = get_fixed_binding_slot (slot, name, BINDING_SLOT_CURRENT, true);
/* Update OLD to reflect the namespace we're going to be
pushing into. */
- old = MAYBE_STAT_DECL (*slot);
+ old = MAYBE_STAT_DECL (*mslot);
}
- old = update_binding (level, binding, slot, old, decl, hiding);
+ old = update_binding (level, binding, mslot, old, decl, hiding);
if (old != decl)
/* An existing decl matched, use it. */
decl = old;
- else if (TREE_CODE (decl) == TYPE_DECL)
- {
- tree type = TREE_TYPE (decl);
-
- if (type != error_mark_node)
- {
- if (TYPE_NAME (type) != decl)
- set_underlying_type (decl);
-
- set_identifier_type_value_with_scope (name, decl, level);
- }
-
- /* If this is a locally defined typedef in a function that
- is not a template instantation, record it to implement
- -Wunused-local-typedefs. */
- if (!instantiating_current_function_p ())
- record_locally_defined_typedef (decl);
- }
else
{
- if (VAR_P (decl) && !DECL_LOCAL_DECL_P (decl))
- maybe_register_incomplete_var (decl);
+ newbinding_bookkeeping (name, decl, level);
- if (VAR_OR_FUNCTION_DECL_P (decl))
+ if (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_LOCAL_DECL_P (decl)
+ && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ push_local_extern_decl_alias (decl);
+
+ if (level->kind == sk_namespace
+ && TREE_PUBLIC (level->this_entity))
{
- if (DECL_LOCAL_DECL_P (decl)
- && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL)
- push_local_extern_decl_alias (decl);
+ if (TREE_CODE (decl) != CONST_DECL
+ && DECL_MODULE_EXPORT_P (decl)
+ && !DECL_MODULE_EXPORT_P (level->this_entity))
+ implicitly_export_namespace (level->this_entity);
- if (DECL_EXTERN_C_P (decl))
- check_extern_c_conflict (decl);
+ if (!not_module_p ())
+ maybe_record_mergeable_decl (slot, name, decl);
}
}
}
@@ -3225,8 +3872,8 @@ do_pushdecl (tree decl, bool hiding)
}
/* Record a decl-node X as belonging to the current lexical scope.
- It's a friend if IS_FRIEND is true -- which affects exactly where
- we push it. */
+ The new binding is hidden if HIDING is true (an anticipated builtin
+ or hidden friend). */
tree
pushdecl (tree x, bool hiding)
@@ -3237,6 +3884,312 @@ pushdecl (tree x, bool hiding)
return ret;
}
+/* A mergeable entity is being loaded into namespace NS slot NAME.
+ Create and return the appropriate vector slot for that. Either a
+ GMF slot or a module-specific one. */
+
+tree *
+mergeable_namespace_slots (tree ns, tree name, bool is_global, tree *vec)
+{
+ tree *mslot = find_namespace_slot (ns, name, true);
+ tree *vslot = get_fixed_binding_slot
+ (mslot, name, is_global ? BINDING_SLOT_GLOBAL : BINDING_SLOT_PARTITION, true);
+
+ gcc_checking_assert (TREE_CODE (*mslot) == BINDING_VECTOR);
+ *vec = *mslot;
+
+ return vslot;
+}
+
+/* DECL is a new mergeable namespace-scope decl. Add it to the
+ mergeable entities on GSLOT. */
+
+void
+add_mergeable_namespace_entity (tree *gslot, tree decl)
+{
+ *gslot = ovl_make (decl, *gslot);
+}
+
+/* A mergeable entity of KLASS called NAME is being loaded. Return
+ the set of things it could be. All such non-as_base classes have
+ been given a member vec. */
+
+tree
+lookup_class_binding (tree klass, tree name)
+{
+ tree found = NULL_TREE;
+
+ if (!COMPLETE_TYPE_P (klass))
+ ;
+ else if (TYPE_LANG_SPECIFIC (klass))
+ {
+ vec<tree, va_gc> *member_vec = CLASSTYPE_MEMBER_VEC (klass);
+
+ found = member_vec_binary_search (member_vec, name);
+ if (IDENTIFIER_CONV_OP_P (name))
+ {
+ gcc_checking_assert (name == conv_op_identifier);
+ if (found)
+ found = OVL_CHAIN (found);
+ }
+ }
+ else
+ {
+ gcc_checking_assert (IS_FAKE_BASE_TYPE (klass)
+ || TYPE_PTRMEMFUNC_P (klass));
+ found = fields_linear_search (klass, name, false);
+ }
+
+ return found;
+}
+
+/* Given a namespace-level binding BINDING, walk it, calling CALLBACK
+ for all decls of the current module. When partitions are involved,
+ decls might be mentioned more than once. */
+
+unsigned
+walk_module_binding (tree binding, bitmap partitions,
+ bool (*callback) (tree decl, WMB_Flags, void *data),
+ void *data)
+{
+ // FIXME: We don't quite deal with using decls naming stat hack
+ // type. Also using decls exporting something from the same scope.
+ tree current = binding;
+ unsigned count = 0;
+
+ if (TREE_CODE (binding) == BINDING_VECTOR)
+ current = BINDING_VECTOR_CLUSTER (binding, 0).slots[BINDING_SLOT_CURRENT];
+
+ bool decl_hidden = false;
+ if (tree type = MAYBE_STAT_TYPE (current))
+ {
+ WMB_Flags flags = WMB_None;
+ if (STAT_TYPE_HIDDEN_P (current))
+ flags = WMB_Flags (flags | WMB_Hidden);
+ count += callback (type, flags, data);
+ decl_hidden = STAT_DECL_HIDDEN_P (current);
+ }
+
+ for (ovl_iterator iter (MAYBE_STAT_DECL (current)); iter; ++iter)
+ {
+ if (iter.hidden_p ())
+ decl_hidden = true;
+ if (!(decl_hidden && DECL_IS_UNDECLARED_BUILTIN (*iter)))
+ {
+ WMB_Flags flags = WMB_None;
+ if (decl_hidden)
+ flags = WMB_Flags (flags | WMB_Hidden);
+ if (iter.using_p ())
+ {
+ flags = WMB_Flags (flags | WMB_Using);
+ if (iter.exporting_p ())
+ flags = WMB_Flags (flags | WMB_Export);
+ }
+ count += callback (*iter, flags, data);
+ }
+ decl_hidden = false;
+ }
+
+ if (partitions && TREE_CODE (binding) == BINDING_VECTOR)
+ {
+ /* Process partition slots. */
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (binding);
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (binding);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ bool maybe_dups = BINDING_VECTOR_PARTITION_DUPS_P (binding);
+
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ if (!cluster->slots[jx].is_lazy ())
+ if (tree bind = cluster->slots[jx])
+ {
+ if (TREE_CODE (bind) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (bind))
+ {
+ if (unsigned base = cluster->indices[jx].base)
+ if (unsigned span = cluster->indices[jx].span)
+ do
+ if (bitmap_bit_p (partitions, base))
+ goto found;
+ while (++base, --span);
+ /* Not a partition's namespace. */
+ continue;
+ found:
+
+ WMB_Flags flags = WMB_None;
+ if (maybe_dups)
+ flags = WMB_Flags (flags | WMB_Dups);
+ count += callback (bind, flags, data);
+ }
+ else if (STAT_HACK_P (bind) && MODULE_BINDING_PARTITION_P (bind))
+ {
+ if (tree btype = STAT_TYPE (bind))
+ {
+ WMB_Flags flags = WMB_None;
+ if (maybe_dups)
+ flags = WMB_Flags (flags | WMB_Dups);
+ if (STAT_TYPE_HIDDEN_P (bind))
+ flags = WMB_Flags (flags | WMB_Hidden);
+
+ count += callback (btype, flags, data);
+ }
+ bool hidden = STAT_DECL_HIDDEN_P (bind);
+ for (ovl_iterator iter (MAYBE_STAT_DECL (STAT_DECL (bind)));
+ iter; ++iter)
+ {
+ if (iter.hidden_p ())
+ hidden = true;
+ gcc_checking_assert
+ (!(hidden && DECL_IS_UNDECLARED_BUILTIN (*iter)));
+
+ WMB_Flags flags = WMB_None;
+ if (maybe_dups)
+ flags = WMB_Flags (flags | WMB_Dups);
+ if (decl_hidden)
+ flags = WMB_Flags (flags | WMB_Hidden);
+ if (iter.using_p ())
+ {
+ flags = WMB_Flags (flags | WMB_Using);
+ if (iter.exporting_p ())
+ flags = WMB_Flags (flags | WMB_Export);
+ }
+ count += callback (*iter, flags, data);
+ hidden = false;
+ }
+ }
+ }
+ }
+
+ return count;
+}
+
+/* Imported module MOD has a binding to NS::NAME, stored in section
+ SNUM. */
+
+bool
+import_module_binding (tree ns, tree name, unsigned mod, unsigned snum)
+{
+ tree *slot = find_namespace_slot (ns, name, true);
+ binding_slot *mslot = append_imported_binding_slot (slot, name, mod);
+
+ if (mslot->is_lazy () || *mslot)
+ /* Oops, something was already there. */
+ return false;
+
+ mslot->set_lazy (snum);
+ return true;
+}
+
+/* An import of MODULE is binding NS::NAME. There should be no
+ existing binding for >= MODULE. MOD_GLOB indicates whether MODULE
+ is a header_unit (-1) or part of the current module (+1). VALUE
+ and TYPE are the value and type bindings. VISIBLE are the value
+ bindings being exported. */
+
+bool
+set_module_binding (tree ns, tree name, unsigned mod, int mod_glob,
+ tree value, tree type, tree visible)
+{
+ if (!value)
+ /* Bogus BMIs could give rise to nothing to bind. */
+ return false;
+
+ gcc_assert (TREE_CODE (value) != NAMESPACE_DECL
+ || DECL_NAMESPACE_ALIAS (value));
+ gcc_checking_assert (mod);
+
+ tree *slot = find_namespace_slot (ns, name, true);
+ binding_slot *mslot = search_imported_binding_slot (slot, mod);
+
+ if (!mslot || !mslot->is_lazy ())
+ /* Again, bogus BMI could give find to missing or already loaded slot. */
+ return false;
+
+ tree bind = value;
+ if (type || visible != bind || mod_glob)
+ {
+ bind = stat_hack (bind, type);
+ STAT_VISIBLE (bind) = visible;
+ if ((mod_glob > 0 && TREE_PUBLIC (ns))
+ || (type && DECL_MODULE_EXPORT_P (type)))
+ STAT_TYPE_VISIBLE_P (bind) = true;
+ }
+
+ /* Note if this is this-module or global binding. */
+ if (mod_glob > 0)
+ MODULE_BINDING_PARTITION_P (bind) = true;
+ else if (mod_glob < 0)
+ MODULE_BINDING_GLOBAL_P (bind) = true;
+
+ *mslot = bind;
+
+ return true;
+}
+
+void
+note_pending_specializations (tree ns, tree name, bool is_header)
+{
+ if (tree *slot = find_namespace_slot (ns, name, false))
+ if (TREE_CODE (*slot) == BINDING_VECTOR)
+ {
+ tree vec = *slot;
+ BINDING_VECTOR_PENDING_SPECIALIZATIONS_P (vec) = true;
+ if (is_header)
+ BINDING_VECTOR_PENDING_IS_HEADER_P (vec) = true;
+ else
+ BINDING_VECTOR_PENDING_IS_PARTITION_P (vec) = true;
+ }
+}
+
+void
+load_pending_specializations (tree ns, tree name)
+{
+ tree *slot = find_namespace_slot (ns, name, false);
+
+ if (!slot || TREE_CODE (*slot) != BINDING_VECTOR
+ || !BINDING_VECTOR_PENDING_SPECIALIZATIONS_P (*slot))
+ return;
+
+ tree vec = *slot;
+ BINDING_VECTOR_PENDING_SPECIALIZATIONS_P (vec) = false;
+
+ bool do_header = BINDING_VECTOR_PENDING_IS_HEADER_P (vec);
+ bool do_partition = BINDING_VECTOR_PENDING_IS_PARTITION_P (vec);
+ BINDING_VECTOR_PENDING_IS_HEADER_P (vec) = false;
+ BINDING_VECTOR_PENDING_IS_PARTITION_P (vec) = false;
+
+ gcc_checking_assert (do_header | do_partition);
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (vec);
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (vec);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ if (cluster->indices[jx].span
+ && cluster->slots[jx].is_lazy ()
+ && lazy_specializations_p (cluster->indices[jx].base,
+ do_header, do_partition))
+ lazy_load_binding (cluster->indices[jx].base, ns, name,
+ &cluster->slots[jx]);
+}
+
+void
+add_module_decl (tree ns, tree name, tree decl)
+{
+ gcc_assert (!DECL_CHAIN (decl));
+ add_decl_to_level (NAMESPACE_LEVEL (ns), decl);
+ newbinding_bookkeeping (name, decl, NAMESPACE_LEVEL (ns));
+}
+
/* Enter DECL into the symbol table, if that's appropriate. Returns
DECL, or a modified version thereof. */
@@ -3417,12 +4370,17 @@ begin_scope (scope_kind kind, tree entity)
case sk_cond:
case sk_class:
case sk_scoped_enum:
- case sk_function_parms:
case sk_transaction:
case sk_omp:
scope->keep = keep_next_level_flag;
break;
+ case sk_function_parms:
+ scope->keep = keep_next_level_flag;
+ if (entity)
+ scope->immediate_fn_ctx_p = DECL_IMMEDIATE_FUNCTION_P (entity);
+ break;
+
case sk_namespace:
NAMESPACE_LEVEL (entity) = scope;
break;
@@ -3692,7 +4650,7 @@ print_binding_level (cp_binding_level* lvl)
continue;
if (no_print_builtins
&& (TREE_CODE (t) == TYPE_DECL)
- && DECL_IS_BUILTIN (t))
+ && DECL_IS_UNDECLARED_BUILTIN (t))
continue;
/* Function decls tend to have longer names. */
@@ -3838,13 +4796,6 @@ set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b)
else
{
gcc_assert (decl);
- if (CHECKING_P)
- {
- tree *slot = find_namespace_slot (current_namespace, id);
- gcc_checking_assert (slot
- && (decl == MAYBE_STAT_TYPE (*slot)
- || decl == MAYBE_STAT_DECL (*slot)));
- }
/* Store marker instead of real type. */
type = global_type_node;
@@ -3962,7 +4913,7 @@ pushdecl_outermost_localscope (tree x)
static bool
do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
- tree *value_p, tree *type_p)
+ bool insert_p, tree *value_p, tree *type_p)
{
tree value = *value_p;
tree type = *type_p;
@@ -3982,13 +4933,33 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
lookup.value = NULL_TREE;
}
+ /* Only process exporting if we're going to be inserting. */
+ bool revealing_p = insert_p && !fn_scope_p && module_has_cmi_p ();
+
+ /* First do the value binding. */
if (!lookup.value)
- /* Nothing. */;
+ /* Nothing (only implicit typedef found). */
+ gcc_checking_assert (lookup.type);
else if (OVL_P (lookup.value) && (!value || OVL_P (value)))
{
for (lkp_iterator usings (lookup.value); usings; ++usings)
{
tree new_fn = *usings;
+ bool exporting = revealing_p && module_exporting_p ();
+ if (exporting)
+ {
+ /* If the using decl is exported, the things it refers
+ to must also be exported (or not in module purview). */
+ if (!DECL_MODULE_EXPORT_P (new_fn)
+ && (DECL_LANG_SPECIFIC (new_fn)
+ && DECL_MODULE_PURVIEW_P (new_fn)))
+ {
+ error ("%q#D does not have external linkage", new_fn);
+ inform (DECL_SOURCE_LOCATION (new_fn),
+ "%q#D declared here", new_fn);
+ exporting = false;
+ }
+ }
/* [namespace.udecl]
@@ -3996,6 +4967,10 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
scope has the same name and the same parameter types as a
function introduced by a using declaration the program is
ill-formed. */
+ /* This seems overreaching, asking core -- why do we care
+ about decls in the namespace that we cannot name (because
+ they are not transitively imported. We just check the
+ decls that are in this TU. */
bool found = false;
for (ovl_iterator old (value); !found && old; ++old)
{
@@ -4004,13 +4979,30 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
if (new_fn == old_fn)
{
/* The function already exists in the current
- namespace. */
+ namespace. We will still want to insert it if
+ it is revealing a not-revealed thing. */
found = true;
+ if (!revealing_p)
+ ;
+ else if (old.using_p ())
+ {
+ if (exporting)
+ /* Update in place. 'tis ok. */
+ OVL_EXPORT_P (old.get_using ()) = true;
+ ;
+ }
+ else if (DECL_MODULE_EXPORT_P (new_fn))
+ ;
+ else
+ {
+ value = old.remove_node (value);
+ found = false;
+ }
break;
}
else if (old.using_p ())
continue; /* This is a using decl. */
- else if (old.hidden_p () && DECL_UNDECLARED_BUILTIN_P (old_fn))
+ else if (old.hidden_p () && DECL_IS_UNDECLARED_BUILTIN (old_fn))
continue; /* This is an anticipated builtin. */
else if (!matching_fn_p (new_fn, old_fn))
continue; /* Parameters do not match. */
@@ -4029,11 +5021,11 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
}
}
- if (!found)
+ if (!found && insert_p)
/* Unlike the decl-pushing case we don't drop anticipated
builtins here. They don't cause a problem, and we'd
like to match them with a future declaration. */
- value = ovl_insert (new_fn, value, true);
+ value = ovl_insert (new_fn, value, 1 + exporting);
}
}
else if (value
@@ -4044,28 +5036,34 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
diagnose_name_conflict (lookup.value, value);
failed = true;
}
- else
+ else if (insert_p)
+ // FIXME:what if we're newly exporting lookup.value
value = lookup.value;
-
+
+ /* Now the type binding. */
if (lookup.type && lookup.type != type)
{
+ // FIXME: What if we're exporting lookup.type?
if (type && !decls_match (lookup.type, type))
{
diagnose_name_conflict (lookup.type, type);
failed = true;
}
- else
+ else if (insert_p)
type = lookup.type;
}
- /* If value is empty, shift any class or enumeration name back. */
- if (!value)
+ if (insert_p)
{
- value = type;
- type = NULL_TREE;
+ /* If value is empty, shift any class or enumeration name back. */
+ if (!value)
+ {
+ value = type;
+ type = NULL_TREE;
+ }
+ *value_p = value;
+ *type_p = type;
}
- *value_p = value;
- *type_p = type;
return failed;
}
@@ -4668,45 +5666,69 @@ push_class_level_binding (tree name, tree x)
}
/* Process and lookup a using decl SCOPE::lookup.name, filling in
- lookup.values & lookup.type. Return true if ok. */
+ lookup.values & lookup.type. Return a USING_DECL, or NULL_TREE on
+ failure. */
-static bool
+static tree
lookup_using_decl (tree scope, name_lookup &lookup)
{
tree current = current_scope ();
bool dependent_p = false;
+ tree binfo = NULL_TREE;
+ base_kind b_kind = bk_not_base;
+
+ /* Because C++20 breaks the invariant that only member using-decls
+ refer to members and only non-member using-decls refer to
+ non-members, we first do the lookups, and then do validation that
+ what we found is ok. */
+
+ if (TREE_CODE (scope) == ENUMERAL_TYPE
+ && cxx_dialect < cxx20
+ && UNSCOPED_ENUM_P (scope)
+ && !TYPE_FUNCTION_SCOPE_P (scope))
+ {
+ /* PR c++/60265 argued that since C++11 added explicit enum scope, we
+ should allow it as meaning the enclosing scope. I don't see any
+ justification for this in C++11, but let's keep allowing it. */
+ tree ctx = CP_TYPE_CONTEXT (scope);
+ if (CLASS_TYPE_P (ctx) == CLASS_TYPE_P (current))
+ scope = ctx;
+ }
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
/* Naming a namespace member. */
- if (TYPE_P (current))
+ qualified_namespace_lookup (scope, &lookup);
+
+ if (TYPE_P (current)
+ && (!lookup.value
+ || lookup.type
+ || cxx_dialect < cxx20
+ || TREE_CODE (lookup.value) != CONST_DECL))
{
error ("using-declaration for non-member at class scope");
- return false;
+ return NULL_TREE;
}
-
- qualified_namespace_lookup (scope, &lookup);
}
else if (TREE_CODE (scope) == ENUMERAL_TYPE)
{
- error ("using-declaration may not name enumerator %<%E::%D%>",
- scope, lookup.name);
- return false;
+ /* Naming an enumeration member. */
+ if (cxx_dialect < cxx20)
+ error ("%<using%> with enumeration scope %q#T "
+ "only available with %<-std=c++20%> or %<-std=gnu++20%>",
+ scope);
+ lookup.value = lookup_enumerator (scope, lookup.name);
}
else
{
- /* Naming a class member. */
- if (!TYPE_P (current))
- {
- error ("using-declaration for member at non-class scope");
- return false;
- }
+ /* Naming a class member. This is awkward in C++20, because we
+ might be naming an enumerator of an unrelated class. */
- /* Make sure the name is not invalid */
+ /* You cannot using-decl a destructor. */
if (TREE_CODE (lookup.name) == BIT_NOT_EXPR)
{
error ("%<%T::%D%> names destructor", scope, lookup.name);
- return false;
+ return NULL_TREE;
}
/* Using T::T declares inheriting ctors, even if T is a typedef. */
@@ -4714,91 +5736,152 @@ lookup_using_decl (tree scope, name_lookup &lookup)
&& (lookup.name == TYPE_IDENTIFIER (scope)
|| constructor_name_p (lookup.name, scope)))
{
+ if (!TYPE_P (current))
+ {
+ error ("non-member using-declaration names constructor of %qT",
+ scope);
+ return NULL_TREE;
+ }
maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
lookup.name = ctor_identifier;
CLASSTYPE_NON_AGGREGATE (current) = true;
}
- /* Cannot introduce a constructor name. */
- if (constructor_name_p (lookup.name, current))
+ if (!MAYBE_CLASS_TYPE_P (scope))
+ ;
+ else if (TYPE_P (current))
{
- error ("%<%T::%D%> names constructor in %qT",
- scope, lookup.name, current);
- return false;
- }
-
- /* Member using decls finish processing when completing the
- class. */
- /* From [namespace.udecl]:
-
- A using-declaration used as a member-declaration shall refer
- to a member of a base class of the class being defined.
+ dependent_p = dependent_scope_p (scope);
+ if (!dependent_p)
+ {
+ binfo = lookup_base (current, scope, ba_any, &b_kind, tf_none);
+ gcc_checking_assert (b_kind >= bk_not_base);
- In general, we cannot check this constraint in a template
- because we do not know the entire set of base classes of the
- current class type. Morover, if SCOPE is dependent, it might
- match a non-dependent base. */
+ if (lookup.name == ctor_identifier)
+ {
+ /* Even if there are dependent bases, SCOPE will not
+ be direct base, no matter. */
+ if (b_kind < bk_proper_base || !binfo_direct_p (binfo))
+ {
+ error ("%qT is not a direct base of %qT", scope, current);
+ return NULL_TREE;
+ }
+ }
+ else if (b_kind < bk_proper_base)
+ binfo = TYPE_BINFO (scope);
+ else if (IDENTIFIER_CONV_OP_P (lookup.name)
+ && dependent_type_p (TREE_TYPE (lookup.name)))
+ dependent_p = true;
+ }
+ }
+ else
+ binfo = TYPE_BINFO (scope);
- dependent_p = dependent_scope_p (scope);
if (!dependent_p)
{
- base_kind b_kind;
- tree binfo = lookup_base (current, scope, ba_any, &b_kind,
- tf_warning_or_error);
- if (b_kind < bk_proper_base)
+ if (binfo)
+ lookup.value = lookup_member (binfo, lookup.name, /*protect=*/2,
+ /*want_type=*/false, tf_none);
+
+ tree saved_value = lookup.value;
+ if (lookup.value
+ && b_kind < bk_proper_base)
{
- /* If there are dependent bases, scope might resolve at
- instantiation time, even if it isn't exactly one of
- the dependent bases. */
- if (b_kind == bk_same_type || !any_dependent_bases_p ())
+ if (cxx_dialect >= cxx20
+ && TREE_CODE (lookup.value) == CONST_DECL)
{
- error_not_base_type (scope, current);
- return false;
+ /* Using an unrelated enum; check access here rather
+ than separately for class and non-class using. */
+ perform_or_defer_access_check
+ (binfo, lookup.value, lookup.value, tf_warning_or_error);
+ /* And then if this is a copy from handle_using_decl, look
+ through to the original enumerator. */
+ if (CONST_DECL_USING_P (lookup.value))
+ lookup.value = DECL_ABSTRACT_ORIGIN (lookup.value);
}
- /* Treat as-if dependent. */
- dependent_p = true;
+ else
+ lookup.value = NULL_TREE;
}
- else if (lookup.name == ctor_identifier && !binfo_direct_p (binfo))
+
+ if (!lookup.value)
{
- error ("cannot inherit constructors from indirect base %qT",
- scope);
- return false;
+ if (!TYPE_P (current))
+ {
+ error ("using-declaration for member at non-class scope");
+ return NULL_TREE;
+ }
+
+ if (b_kind < bk_proper_base)
+ {
+ if (b_kind == bk_not_base && any_dependent_bases_p ())
+ /* Treat as-if dependent. */
+ dependent_p = true;
+ else
+ {
+ auto_diagnostic_group g;
+ error_not_base_type (scope, current);
+ if (saved_value && DECL_IMPLICIT_TYPEDEF_P (saved_value)
+ && (TREE_CODE (TREE_TYPE (saved_value))
+ == ENUMERAL_TYPE))
+ inform (input_location,
+ "did you mean %<using enum %T::%D%>?",
+ scope, lookup.name);
+ return NULL_TREE;
+ }
+ }
}
- else if (IDENTIFIER_CONV_OP_P (lookup.name)
- && dependent_type_p (TREE_TYPE (lookup.name)))
- dependent_p = true;
- else
- lookup.value = lookup_member (binfo, lookup.name, 0,
- false, tf_warning_or_error);
}
}
- if (!dependent_p)
+ /* Did we find anything sane? */
+ if (dependent_p)
+ ;
+ else if (!lookup.value)
{
- if (!lookup.value)
- {
- error ("%qD has not been declared in %qE", lookup.name, scope);
- return false;
- }
+ error ("%qD has not been declared in %qD", lookup.name, scope);
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (lookup.value) == TREE_LIST
+ /* We can (independently) have ambiguous implicit typedefs. */
+ || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
+ {
+ error ("reference to %qD is ambiguous", lookup.name);
+ print_candidates (TREE_CODE (lookup.value) == TREE_LIST
+ ? lookup.value : lookup.type);
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
+ {
+ error ("using-declaration may not name namespace %qD", lookup.value);
+ return NULL_TREE;
+ }
- if (TREE_CODE (lookup.value) == TREE_LIST
- /* We can (independently) have ambiguous implicit typedefs. */
- || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
- {
- error ("reference to %qD is ambiguous", lookup.name);
- print_candidates (TREE_CODE (lookup.value) == TREE_LIST
- ? lookup.value : lookup.type);
- return false;
- }
+ if (TYPE_P (current))
+ {
+ /* In class scope. */
- if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
+ /* Cannot introduce a constructor name. */
+ if (constructor_name_p (lookup.name, current))
{
- error ("using-declaration may not name namespace %qD", lookup.value);
- return false;
+ error ("%<%T::%D%> names constructor in %qT",
+ scope, lookup.name, current);
+ return NULL_TREE;
}
+
+ if (lookup.value && BASELINK_P (lookup.value))
+ /* The binfo from which the functions came does not matter. */
+ lookup.value = BASELINK_FUNCTIONS (lookup.value);
}
- return true;
+ tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
+ USING_DECL_SCOPE (using_decl) = scope;
+ USING_DECL_DECLS (using_decl) = lookup.value;
+ DECL_DEPENDENT_P (using_decl) = dependent_p;
+ DECL_CONTEXT (using_decl) = current;
+ if (TYPE_P (current) && b_kind == bk_not_base)
+ USING_DECL_UNRELATED_P (using_decl) = true;
+
+ return using_decl;
}
/* Process "using SCOPE::NAME" in a class scope. Return the
@@ -4812,25 +5895,14 @@ do_class_using_decl (tree scope, tree name)
return NULL_TREE;
name_lookup lookup (name);
- if (!lookup_using_decl (scope, lookup))
- return NULL_TREE;
-
- tree found = lookup.value;
- if (found && BASELINK_P (found))
- /* The binfo from which the functions came does not matter. */
- found = BASELINK_FUNCTIONS (found);
-
- tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
- USING_DECL_SCOPE (using_decl) = scope;
- USING_DECL_DECLS (using_decl) = found;
- DECL_DEPENDENT_P (using_decl) = !found;
-
- return using_decl;
+ return lookup_using_decl (scope, lookup);
}
-/* Return the binding for NAME in NS. If NS is NULL, look in
- global_namespace. */
+/* Return the binding for NAME in NS in the current TU. If NS is
+ NULL, look in global_namespace. We will not find declarations
+ from imports. Users of this who, having found nothing, push a new
+ decl must be prepared for that pushing to match an existing decl. */
tree
get_namespace_binding (tree ns, tree name)
@@ -4839,7 +5911,18 @@ get_namespace_binding (tree ns, tree name)
if (!ns)
ns = global_namespace;
gcc_checking_assert (!DECL_NAMESPACE_ALIAS (ns));
- tree ret = find_namespace_value (ns, name);
+ tree ret = NULL_TREE;
+
+ if (tree *b = find_namespace_slot (ns, name))
+ {
+ ret = *b;
+
+ if (TREE_CODE (ret) == BINDING_VECTOR)
+ ret = BINDING_VECTOR_CLUSTER (ret, 0).slots[0];
+ if (ret)
+ ret = MAYBE_STAT_DECL (ret);
+ }
+
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
@@ -5140,6 +6223,8 @@ do_namespace_alias (tree alias, tree name_space)
DECL_NAMESPACE_ALIAS (alias) = name_space;
DECL_EXTERNAL (alias) = 1;
DECL_CONTEXT (alias) = FROB_CONTEXT (current_scope ());
+ set_originating_module (alias);
+
pushdecl (alias);
/* Emit debug info for namespace alias. */
@@ -5206,7 +6291,8 @@ finish_nonmember_using_decl (tree scope, tree name)
name_lookup lookup (name);
- if (!lookup_using_decl (scope, lookup))
+ tree using_decl = lookup_using_decl (scope, lookup);
+ if (!using_decl)
return;
/* Emit debug info. */
@@ -5217,26 +6303,97 @@ finish_nonmember_using_decl (tree scope, tree name)
if (current_binding_level->kind == sk_namespace)
{
tree *slot = find_namespace_slot (current_namespace, name, true);
+ tree *mslot = get_fixed_binding_slot (slot, name,
+ BINDING_SLOT_CURRENT, true);
+ bool failed = false;
+
+ if (mslot != slot)
+ {
+ /* A module vector. I presume the binding list is going to
+ be sparser than the import bitmap. Hence iterate over
+ the former checking for bits set in the bitmap. */
+ bitmap imports = get_import_bitmap ();
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (*slot);
+
+ /* Scan the imported bindings. */
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (*slot);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ /* Do this in forward order, so we load modules in an order
+ the user expects. */
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ {
+ /* Are we importing this module? */
+ if (unsigned base = cluster->indices[jx].base)
+ if (unsigned span = cluster->indices[jx].span)
+ do
+ if (bitmap_bit_p (imports, base))
+ goto found;
+ while (++base, --span);
+ continue;
- tree value = MAYBE_STAT_DECL (*slot);
- tree type = MAYBE_STAT_TYPE (*slot);
+ found:;
+ /* Is it loaded? */
+ if (cluster->slots[jx].is_lazy ())
+ {
+ gcc_assert (cluster->indices[jx].span == 1);
+ lazy_load_binding (cluster->indices[jx].base,
+ scope, name, &cluster->slots[jx]);
+ }
- do_nonmember_using_decl (lookup, false, &value, &type);
+ tree value = cluster->slots[jx];
+ if (!value)
+ /* Load errors could mean there's nothing here. */
+ continue;
+
+ /* Extract what we can see from here. If there's no
+ stat_hack, then everything was exported. */
+ tree type = NULL_TREE;
+
+ /* If no stat hack, everything is visible. */
+ if (STAT_HACK_P (value))
+ {
+ if (STAT_TYPE_VISIBLE_P (value))
+ type = STAT_TYPE (value);
+ value = STAT_VISIBLE (value);
+ }
+
+ if (do_nonmember_using_decl (lookup, false, false,
+ &value, &type))
+ {
+ failed = true;
+ break;
+ }
+ }
+ }
- if (STAT_HACK_P (*slot))
+ if (!failed)
{
- STAT_DECL (*slot) = value;
- STAT_TYPE (*slot) = type;
+ /* Now do the current slot. */
+ tree value = MAYBE_STAT_DECL (*mslot);
+ tree type = MAYBE_STAT_TYPE (*mslot);
+
+ do_nonmember_using_decl (lookup, false, true, &value, &type);
+
+ // FIXME: Partition mergeableness?
+ if (STAT_HACK_P (*mslot))
+ {
+ STAT_DECL (*mslot) = value;
+ STAT_TYPE (*mslot) = type;
+ }
+ else if (type)
+ *mslot = stat_hack (value, type);
+ else
+ *mslot = value;
}
- else if (type)
- *slot = stat_hack (value, type);
- else
- *slot = value;
}
else
{
- tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
- USING_DECL_SCOPE (using_decl) = scope;
add_decl_expr (using_decl);
cxx_binding *binding = find_local_binding (current_binding_level, name);
@@ -5251,7 +6408,7 @@ finish_nonmember_using_decl (tree scope, tree name)
/* DR 36 questions why using-decls at function scope may not be
duplicates. Disallow it, as C++11 claimed and PR 20420
implemented. */
- do_nonmember_using_decl (lookup, true, &value, &type);
+ do_nonmember_using_decl (lookup, true, true, &value, &type);
if (!value)
;
@@ -5903,7 +7060,7 @@ get_std_name_hint (const char *name)
/* Describe DIALECT. */
-static const char *
+const char *
get_cxx_dialect_name (enum cxx_dialect dialect)
{
switch (dialect)
@@ -6069,7 +7226,14 @@ lookup_qualified_name (tree scope, tree name, LOOK_want want, bool complain)
name_lookup lookup (name, want);
if (qualified_namespace_lookup (scope, &lookup))
- t = lookup.value;
+ {
+ t = lookup.value;
+
+ /* If we have a known type overload, pull it out. This can happen
+ for using decls. */
+ if (TREE_CODE (t) == OVERLOAD && TREE_TYPE (t) != unknown_type_node)
+ t = OVL_FUNCTION (t);
+ }
}
else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE)
t = lookup_enumerator (scope, name);
@@ -6167,9 +7331,10 @@ maybe_add_fuzzy_decl (auto_vec<tree> &vec, tree decl)
}
/* Examing the namespace binding BINDING, and add at most one instance
- of the name, if it contains a visible entity of interest. */
+ of the name, if it contains a visible entity of interest. Return
+ true if we added something. */
-void
+bool
maybe_add_fuzzy_binding (auto_vec<tree> &vec, tree binding,
lookup_name_fuzzy_kind kind)
{
@@ -6181,7 +7346,7 @@ maybe_add_fuzzy_binding (auto_vec<tree> &vec, tree binding,
&& STAT_TYPE (binding))
{
if (maybe_add_fuzzy_decl (vec, STAT_TYPE (binding)))
- return;
+ return true;
}
else if (!STAT_DECL_HIDDEN_P (binding))
value = STAT_DECL (binding);
@@ -6196,8 +7361,11 @@ maybe_add_fuzzy_binding (auto_vec<tree> &vec, tree binding,
if (kind != FUZZY_LOOKUP_TYPENAME
|| TREE_CODE (STRIP_TEMPLATE (value)) == TYPE_DECL)
if (maybe_add_fuzzy_decl (vec, value))
- return;
+ return true;
}
+
+ /* Nothing found. */
+ return false;
}
/* Helper function for lookup_name_fuzzy.
@@ -6263,8 +7431,54 @@ consider_binding_level (tree name, best_match <tree, const char *> &bm,
(DECL_NAMESPACE_BINDINGS (ns)->end ());
for (hash_table<named_decl_hash>::iterator iter
(DECL_NAMESPACE_BINDINGS (ns)->begin ()); iter != end; ++iter)
- maybe_add_fuzzy_binding (vec, *iter, kind);
+ {
+ tree binding = *iter;
+
+ if (TREE_CODE (binding) == BINDING_VECTOR)
+ {
+ bitmap imports = get_import_bitmap ();
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (binding);
+ if (tree bind = cluster->slots[BINDING_SLOT_CURRENT])
+ if (maybe_add_fuzzy_binding (vec, bind, kind))
+ continue;
+
+ /* Scan the imported bindings. */
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (binding);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER;
+ jx++)
+ {
+ /* Are we importing this module? */
+ if (unsigned base = cluster->indices[jx].base)
+ if (unsigned span = cluster->indices[jx].span)
+ do
+ if (bitmap_bit_p (imports, base))
+ goto found;
+ while (++base, --span);
+ continue;
+
+ found:;
+ /* Is it loaded? */
+ if (cluster->slots[jx].is_lazy ())
+ /* Let's not read in everything on the first
+ spello! **/
+ continue;
+ if (tree bind = cluster->slots[jx])
+ if (maybe_add_fuzzy_binding (vec, bind, kind))
+ break;
+ }
+ }
+ else
+ maybe_add_fuzzy_binding (vec, binding, kind);
+ }
+
vec.qsort ([] (const void *a_, const void *b_)
{
return strcmp (IDENTIFIER_POINTER (*(const tree *)a_),
@@ -6699,8 +7913,9 @@ lookup_name_1 (tree name, LOOK_where where, LOOK_want want)
found:;
- /* If we have a single function from a using decl, pull it out. */
- if (val && TREE_CODE (val) == OVERLOAD && !really_overloaded_fn (val))
+ /* If we have a known type overload, pull it out. This can happen
+ for both using decls and unhidden functions. */
+ if (val && TREE_CODE (val) == OVERLOAD && TREE_TYPE (val) != unknown_type_node)
val = OVL_FUNCTION (val);
return val;
@@ -6806,31 +8021,115 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
tree ns = b->this_entity;
if (tree *slot = find_namespace_slot (ns, name))
{
- /* If this is the kind of thing we're looking for, we're done. */
- if (tree type = MAYBE_STAT_TYPE (*slot))
- {
- if (how != TAG_how::HIDDEN_FRIEND)
- /* No longer hidden. */
- STAT_TYPE_HIDDEN_P (*slot) = false;
+ tree bind = *slot;
+ if (TREE_CODE (bind) == BINDING_VECTOR)
+ bind = BINDING_VECTOR_CLUSTER (bind, 0).slots[BINDING_SLOT_CURRENT];
- return type;
- }
- else if (tree decl = MAYBE_STAT_DECL (*slot))
+ if (bind)
{
- if (qualify_lookup (decl, LOOK_want::TYPE))
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (tree type = MAYBE_STAT_TYPE (bind))
{
- if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot)
- && STAT_DECL_HIDDEN_P (*slot))
+ if (how != TAG_how::HIDDEN_FRIEND)
+ /* No longer hidden. */
+ STAT_TYPE_HIDDEN_P (*slot) = false;
+
+ return type;
+ }
+ else if (tree decl = MAYBE_STAT_DECL (bind))
+ {
+ if (qualify_lookup (decl, LOOK_want::TYPE))
{
- if (STAT_TYPE (*slot))
- STAT_DECL_HIDDEN_P (*slot) = false;
- else
- /* There is no type, just remove the stat
- hack. */
- *slot = decl;
+ if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (bind)
+ && STAT_DECL_HIDDEN_P (bind))
+ {
+ if (STAT_TYPE (bind))
+ STAT_DECL_HIDDEN_P (bind) = false;
+ else
+ {
+ /* There is no type, just remove the stat
+ hack. */
+ if (*slot == bind)
+ *slot = decl;
+ else
+ BINDING_VECTOR_CLUSTER (bind, 0)
+ .slots[BINDING_SLOT_CURRENT] = decl;
+ }
+ }
+ return decl;
}
+ }
+ }
+
+ if (TREE_CODE (*slot) == BINDING_VECTOR)
+ {
+ /* We could be redeclaring a global module entity, (from GMF
+ or header unit), or from another partition, or
+ specializing an imported template. */
+ bitmap imports = get_import_bitmap ();
+ binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (*slot);
+
+ /* Scan the imported bindings. */
+ unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (*slot);
+ if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
+ {
+ ix--;
+ cluster++;
+ }
+
+ /* Do this in forward order, so we load modules in an order
+ the user expects. */
+ for (; ix--; cluster++)
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ {
+ /* Are we importing this module? */
+ if (unsigned base = cluster->indices[jx].base)
+ if (unsigned span = cluster->indices[jx].span)
+ do
+ if (bitmap_bit_p (imports, base))
+ goto found;
+ while (++base, --span);
+ continue;
+
+ found:;
+ /* Is it loaded? */
+ if (cluster->slots[jx].is_lazy ())
+ {
+ gcc_assert (cluster->indices[jx].span == 1);
+ lazy_load_binding (cluster->indices[jx].base,
+ ns, name, &cluster->slots[jx]);
+ }
+ tree bind = cluster->slots[jx];
+ if (!bind)
+ /* Load errors could mean there's nothing here. */
+ continue;
+
+ /* Extract what we can see from here. If there's no
+ stat_hack, then everything was exported. */
+ tree type = NULL_TREE;
- return decl;
+ /* If no stat hack, everything is visible. */
+ if (STAT_HACK_P (bind))
+ {
+ if (STAT_TYPE_VISIBLE_P (bind))
+ type = STAT_TYPE (bind);
+ bind = STAT_VISIBLE (bind);
+ }
+
+ if (type && qualify_lookup (type, LOOK_want::TYPE))
+ return type;
+
+ if (bind && qualify_lookup (bind, LOOK_want::TYPE))
+ return bind;
+ }
+
+ if (!module_purview_p ())
+ {
+ /* We're in the global module, perhaps there's a tag
+ there? */
+ // FIXME: This isn't quite right, if we find something
+ // here, from the language PoV we're not supposed to
+ // know it?
}
}
}
@@ -6884,10 +8183,6 @@ maybe_process_template_type_declaration (tree type, int is_friend,
if (processing_template_decl)
{
- /* This may change after the call to push_template_decl, but
- we want the original value. */
- tree name = DECL_NAME (decl);
-
decl = push_template_decl (decl, is_friend);
if (decl == error_mark_node)
return error_mark_node;
@@ -6906,17 +8201,8 @@ maybe_process_template_type_declaration (tree type, int is_friend,
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
if (!COMPLETE_TYPE_P (current_class_type))
- {
- maybe_add_class_template_decl_list (current_class_type,
- type, /*friend_p=*/0);
- /* Put this UTD in the table of UTDs for the class. */
- if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
- CLASSTYPE_NESTED_UTDS (current_class_type) =
- binding_table_new (SCOPE_DEFAULT_HT_SIZE);
-
- binding_table_insert
- (CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
- }
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
}
}
}
@@ -6975,7 +8261,6 @@ do_pushtag (tree name, tree type, TAG_how how)
if (identifier_type_value_1 (name) != type)
{
tree tdef;
- int in_class = 0;
tree context = TYPE_CONTEXT (type);
if (! context)
@@ -7006,20 +8291,19 @@ do_pushtag (tree name, tree type, TAG_how how)
if (!context)
context = current_namespace;
- if (b->kind == sk_class
- || (b->kind == sk_template_parms
- && b->level_chain->kind == sk_class))
- in_class = 1;
-
tdef = create_implicit_typedef (name, type);
DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
+ set_originating_module (tdef);
+
decl = maybe_process_template_type_declaration
(type, how == TAG_how::HIDDEN_FRIEND, b);
if (decl == error_mark_node)
return decl;
+ bool in_class = false;
if (b->kind == sk_class)
{
+ in_class = true;
if (!TYPE_BEING_DEFINED (current_class_type))
/* Don't push anywhere if the class is complete; a lambda in an
NSDMI is not a member of the class. */
@@ -7033,7 +8317,9 @@ do_pushtag (tree name, tree type, TAG_how how)
else
pushdecl_class_level (decl);
}
- else if (b->kind != sk_template_parms)
+ else if (b->kind == sk_template_parms)
+ in_class = b->level_chain->kind == sk_class;
+ else
{
decl = do_pushdecl_with_scope
(decl, b, /*hiding=*/(how == TAG_how::HIDDEN_FRIEND));
@@ -7050,7 +8336,7 @@ do_pushtag (tree name, tree type, TAG_how how)
}
}
- if (! in_class)
+ if (!in_class)
set_identifier_type_value_with_scope (name, tdef, b);
TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
@@ -7077,17 +8363,8 @@ do_pushtag (tree name, tree type, TAG_how how)
if (b->kind == sk_class
&& !COMPLETE_TYPE_P (current_class_type))
- {
- maybe_add_class_template_decl_list (current_class_type,
- type, /*friend_p=*/0);
-
- if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
- CLASSTYPE_NESTED_UTDS (current_class_type)
- = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
-
- binding_table_insert
- (CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
- }
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
decl = TYPE_NAME (type);
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
@@ -7346,8 +8623,6 @@ do_push_nested_namespace (tree ns)
else
{
do_push_nested_namespace (CP_DECL_CONTEXT (ns));
- gcc_checking_assert
- (find_namespace_value (current_namespace, DECL_NAME (ns)) == ns);
resume_scope (NAMESPACE_LEVEL (ns));
current_namespace = ns;
}
@@ -7369,10 +8644,10 @@ do_pop_nested_namespace (tree ns)
do_pop_from_top_level ();
}
-/* Add TARGET to USINGS, if it does not already exist there.
- We used to build the complete graph of usings at this point, from
- the POV of the source namespaces. Now we build that as we perform
- the unqualified search. */
+/* Add TARGET to USINGS, if it does not already exist there. We used
+ to build the complete graph of usings at this point, from the POV
+ of the source namespaces. Now we build that as we perform the
+ unqualified search. */
static void
add_using_namespace (vec<tree, va_gc> *&usings, tree target)
@@ -7479,6 +8754,87 @@ push_inline_namespaces (tree ns)
return count;
}
+/* SLOT is the (possibly empty) binding slot for NAME in CTX.
+ Reuse or create a namespace NAME. NAME is null for the anonymous
+ namespace. */
+
+static tree
+reuse_namespace (tree *slot, tree ctx, tree name)
+{
+ if (modules_p () && *slot && TREE_PUBLIC (ctx) && name)
+ {
+ /* Public namespace. Shared. */
+ tree *global_slot = slot;
+ if (TREE_CODE (*slot) == BINDING_VECTOR)
+ global_slot = get_fixed_binding_slot (slot, name,
+ BINDING_SLOT_GLOBAL, false);
+
+ for (ovl_iterator iter (*global_slot); iter; ++iter)
+ {
+ tree decl = *iter;
+
+ if (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl))
+ return decl;
+ }
+ }
+ return NULL_TREE;
+}
+
+static tree
+make_namespace (tree ctx, tree name, location_t loc, bool inline_p)
+{
+ /* Create the namespace. */
+ tree ns = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
+ DECL_SOURCE_LOCATION (ns) = loc;
+ SCOPE_DEPTH (ns) = SCOPE_DEPTH (ctx) + 1;
+ if (!SCOPE_DEPTH (ns))
+ /* We only allow depth 255. */
+ sorry ("cannot nest more than %d namespaces", SCOPE_DEPTH (ctx));
+ DECL_CONTEXT (ns) = FROB_CONTEXT (ctx);
+
+ if (!name)
+ /* Anon-namespaces in different header-unit imports are distinct.
+ But that's ok as their contents all have internal linkage.
+ (This is different to how they'd behave as textual includes,
+ but doing this at all is really odd source.) */
+ SET_DECL_ASSEMBLER_NAME (ns, anon_identifier);
+ else if (TREE_PUBLIC (ctx))
+ TREE_PUBLIC (ns) = true;
+
+ if (inline_p)
+ DECL_NAMESPACE_INLINE_P (ns) = true;
+
+ return ns;
+}
+
+/* NS was newly created, finish off making it. */
+
+static void
+make_namespace_finish (tree ns, tree *slot, bool from_import = false)
+{
+ if (modules_p () && TREE_PUBLIC (ns) && (from_import || *slot != ns))
+ {
+ /* Merge into global slot. */
+ tree *gslot = get_fixed_binding_slot (slot, DECL_NAME (ns),
+ BINDING_SLOT_GLOBAL, true);
+ *gslot = ns;
+ }
+
+ tree ctx = CP_DECL_CONTEXT (ns);
+ cp_binding_level *scope = ggc_cleared_alloc<cp_binding_level> ();
+ scope->this_entity = ns;
+ scope->more_cleanups_ok = true;
+ scope->kind = sk_namespace;
+ scope->level_chain = NAMESPACE_LEVEL (ctx);
+ NAMESPACE_LEVEL (ns) = scope;
+
+ if (DECL_NAMESPACE_INLINE_P (ns))
+ vec_safe_push (DECL_NAMESPACE_INLINEES (ctx), ns);
+
+ if (DECL_NAMESPACE_INLINE_P (ns) || !DECL_NAME (ns))
+ emit_debug_info_using_namespace (ctx, ns, true);
+}
+
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE,
then we enter an anonymous namespace. If MAKE_INLINE is true, then
we create an inline namespace (it is up to the caller to check upon
@@ -7555,59 +8911,80 @@ push_namespace (tree name, bool make_inline)
}
}
- bool new_ns = false;
if (ns)
- /* DR2061. NS might be a member of an inline namespace. We
- need to push into those namespaces. */
- count += push_inline_namespaces (CP_DECL_CONTEXT (ns));
+ {
+ /* DR2061. NS might be a member of an inline namespace. We
+ need to push into those namespaces. */
+ if (modules_p ())
+ {
+ for (tree parent, ctx = ns; ctx != current_namespace;
+ ctx = parent)
+ {
+ parent = CP_DECL_CONTEXT (ctx);
+
+ tree bind = *find_namespace_slot (parent, DECL_NAME (ctx), false);
+ if (bind != ctx)
+ {
+ auto &cluster = BINDING_VECTOR_CLUSTER (bind, 0);
+ binding_slot &slot = cluster.slots[BINDING_SLOT_CURRENT];
+ gcc_checking_assert (!(tree)slot || (tree)slot == ctx);
+ slot = ctx;
+ }
+ }
+ }
+
+ count += push_inline_namespaces (CP_DECL_CONTEXT (ns));
+ if (DECL_SOURCE_LOCATION (ns) == BUILTINS_LOCATION)
+ /* It's not builtin now. */
+ DECL_SOURCE_LOCATION (ns) = input_location;
+ }
else
{
- ns = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
- SCOPE_DEPTH (ns) = SCOPE_DEPTH (current_namespace) + 1;
- if (!SCOPE_DEPTH (ns))
- /* We only allow depth 255. */
- sorry ("cannot nest more than %d namespaces",
- SCOPE_DEPTH (current_namespace));
- DECL_CONTEXT (ns) = FROB_CONTEXT (current_namespace);
- new_ns = true;
+ /* Before making a new namespace, see if we already have one in
+ the existing partitions of the current namespace. */
+ tree *slot = find_namespace_slot (current_namespace, name, false);
+ if (slot)
+ ns = reuse_namespace (slot, current_namespace, name);
+ if (!ns)
+ ns = make_namespace (current_namespace, name,
+ input_location, make_inline);
if (pushdecl (ns) == error_mark_node)
ns = NULL_TREE;
else
{
- if (!name)
- {
- SET_DECL_ASSEMBLER_NAME (ns, anon_identifier);
-
- if (!make_inline)
- add_using_namespace (current_binding_level->using_directives,
- ns);
- }
- else if (TREE_PUBLIC (current_namespace))
- TREE_PUBLIC (ns) = 1;
-
- if (make_inline)
+ /* Finish up making the namespace. */
+ add_decl_to_level (NAMESPACE_LEVEL (current_namespace), ns);
+ if (!slot)
{
- DECL_NAMESPACE_INLINE_P (ns) = true;
- vec_safe_push (DECL_NAMESPACE_INLINEES (current_namespace), ns);
+ slot = find_namespace_slot (current_namespace, name);
+ /* This should find the slot created by pushdecl. */
+ gcc_checking_assert (slot && *slot == ns);
}
+ make_namespace_finish (ns, slot);
- if (!name || make_inline)
- emit_debug_info_using_namespace (current_namespace, ns, true);
+ /* Add the anon using-directive here, we don't do it in
+ make_namespace_finish. */
+ if (!DECL_NAMESPACE_INLINE_P (ns) && !name)
+ add_using_namespace (current_binding_level->using_directives, ns);
}
}
if (ns)
{
+ /* A public namespace is exported only if explicitly marked, or
+ it contains exported entities. */
+ if (!DECL_MODULE_EXPORT_P (ns) && TREE_PUBLIC (ns)
+ && module_exporting_p ())
+ implicitly_export_namespace (ns);
+
if (make_inline && !DECL_NAMESPACE_INLINE_P (ns))
{
- error ("inline namespace must be specified at initial definition");
+ error_at (input_location,
+ "inline namespace must be specified at initial definition");
inform (DECL_SOURCE_LOCATION (ns), "%qD defined here", ns);
}
- if (new_ns)
- begin_scope (sk_namespace, ns);
- else
- resume_scope (NAMESPACE_LEVEL (ns));
+ resume_scope (NAMESPACE_LEVEL (ns));
current_namespace = ns;
count++;
}
@@ -7631,6 +9008,69 @@ pop_namespace (void)
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
}
+/* An import is defining namespace NAME inside CTX. Find or create
+ that namespace and add it to the container's binding-vector. */
+
+tree
+add_imported_namespace (tree ctx, tree name, unsigned origin, location_t loc,
+ bool visible_p, bool inline_p)
+{
+ // FIXME: Something is not correct about the VISIBLE_P handling. We
+ // need to insert this namespace into
+ // (a) the GLOBAL or PARTITION slot, if it is TREE_PUBLIC
+ // (b) The importing module's slot (always)
+ // (c) Do we need to put it in the CURRENT slot? This is the
+ // confused piece.
+
+ gcc_checking_assert (origin);
+ tree *slot = find_namespace_slot (ctx, name, true);
+ tree decl = reuse_namespace (slot, ctx, name);
+ if (!decl)
+ {
+ decl = make_namespace (ctx, name, loc, inline_p);
+ DECL_MODULE_IMPORT_P (decl) = true;
+ make_namespace_finish (decl, slot, true);
+ }
+ else if (DECL_NAMESPACE_INLINE_P (decl) != inline_p)
+ {
+ error_at (loc, "%s namespace %qD conflicts with reachable definition",
+ inline_p ? "inline" : "non-inline", decl);
+ inform (DECL_SOURCE_LOCATION (decl), "reachable %s definition here",
+ inline_p ? "non-inline" : "inline");
+ }
+
+ if (TREE_PUBLIC (decl) && TREE_CODE (*slot) == BINDING_VECTOR)
+ {
+ /* See if we can extend the final slot. */
+ binding_cluster *last = BINDING_VECTOR_CLUSTER_LAST (*slot);
+ gcc_checking_assert (last->indices[0].span);
+ unsigned jx = BINDING_VECTOR_SLOTS_PER_CLUSTER;
+
+ while (--jx)
+ if (last->indices[jx].span)
+ break;
+ tree final = last->slots[jx];
+ if (visible_p == !STAT_HACK_P (final)
+ && MAYBE_STAT_DECL (final) == decl
+ && last->indices[jx].base + last->indices[jx].span == origin
+ && (BINDING_VECTOR_NUM_CLUSTERS (*slot) > 1
+ || (BINDING_VECTOR_SLOTS_PER_CLUSTER > BINDING_SLOTS_FIXED
+ && jx >= BINDING_SLOTS_FIXED)))
+ {
+ last->indices[jx].span++;
+ return decl;
+ }
+ }
+
+ /* Append a new slot. */
+ tree *mslot = &(tree &)*append_imported_binding_slot (slot, name, origin);
+
+ gcc_assert (!*mslot);
+ *mslot = visible_p ? decl : stat_hack (decl, NULL_TREE);
+
+ return decl;
+}
+
/* External entry points for do_{push_to/pop_from}_top_level. */
void
@@ -7786,8 +9226,8 @@ maybe_save_operator_binding (tree e)
/* Do this for lambdas and code that will emit a CMI. In a module's
GMF we don't yet know whether there will be a CMI. */
- if (!current_lambda_expr ())
- return;
+ if (!module_has_cmi_p () && !global_purview_p () && !current_lambda_expr())
+ return;
tree fnname = ovl_op_identifier (false, TREE_CODE (e));
if (!fnname)
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index d63ff10..66fc351 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -23,29 +23,6 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-common.h"
-/* The type of dictionary used to map names to types declared at
- a given scope. */
-typedef struct binding_table_s *binding_table;
-typedef struct binding_entry_s *binding_entry;
-
-/* The type of a routine repeatedly called by binding_table_foreach. */
-typedef void (*bt_foreach_proc) (binding_entry, void *);
-
-struct GTY(()) binding_entry_s {
- binding_entry chain;
- tree name;
- tree type;
-};
-
-/* These macros indicate the initial chains count for binding_table. */
-#define SCOPE_DEFAULT_HT_SIZE (1 << 3)
-#define CLASS_SCOPE_HT_SIZE (1 << 3)
-#define NAMESPACE_ORDINARY_HT_SIZE (1 << 5)
-#define NAMESPACE_STD_HT_SIZE (1 << 8)
-#define GLOBAL_SCOPE_HT_SIZE (1 << 8)
-
-extern void binding_table_foreach (binding_table, bt_foreach_proc, void *);
-extern binding_entry binding_table_find (binding_table, tree);
/* The datatype used to implement C++ scope. */
struct cp_binding_level;
@@ -91,6 +68,125 @@ struct GTY(()) cxx_saved_binding {
tree real_type_value;
};
+/* To support lazy module loading, we squirrel away a section number
+ (and a couple of flags) in the binding slot of unloaded bindings.
+ We rely on pointers being aligned and setting the bottom bit to
+ mark a lazy value. GTY doesn't like an array of union, so we have
+ a containing struct. */
+
+struct GTY(()) binding_slot {
+ union GTY((desc ("%1.is_lazy ()"))) binding_slot_lazy {
+ tree GTY((tag ("false"))) binding;
+ } u;
+
+ operator tree & ()
+ {
+ gcc_checking_assert (!is_lazy ());
+ return u.binding;
+ }
+ binding_slot &operator= (tree t)
+ {
+ u.binding = t;
+ return *this;
+ }
+ bool is_lazy () const
+ {
+ return bool (uintptr_t (u.binding) & 1);
+ }
+ void set_lazy (unsigned snum)
+ {
+ gcc_checking_assert (!u.binding);
+ u.binding = tree (uintptr_t ((snum << 1) | 1));
+ }
+ void or_lazy (unsigned snum)
+ {
+ gcc_checking_assert (is_lazy ());
+ u.binding = tree (uintptr_t (u.binding) | (snum << 1));
+ }
+ unsigned get_lazy () const
+ {
+ gcc_checking_assert (is_lazy ());
+ return unsigned (uintptr_t (u.binding) >> 1);
+ }
+};
+
+/* Bindings for modules are held in a sparse array. There is always a
+ current TU slot, others are allocated as needed. By construction
+ of the importing mechanism we only ever need to append to the
+ array. Rather than have straight index/slot tuples, we bunch them
+ up for greater packing.
+
+ The cluster representation packs well on a 64-bit system. */
+
+#define BINDING_VECTOR_SLOTS_PER_CLUSTER 2
+struct binding_index {
+ unsigned short base;
+ unsigned short span;
+};
+
+struct GTY(()) binding_cluster
+{
+ binding_index GTY((skip)) indices[BINDING_VECTOR_SLOTS_PER_CLUSTER];
+ binding_slot slots[BINDING_VECTOR_SLOTS_PER_CLUSTER];
+};
+
+/* These two fields overlay lang flags. So don't use those. */
+#define BINDING_VECTOR_ALLOC_CLUSTERS(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.u.dependence_info.clique)
+#define BINDING_VECTOR_NUM_CLUSTERS(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.u.dependence_info.base)
+#define BINDING_VECTOR_CLUSTER_BASE(NODE) \
+ (((tree_binding_vec *)BINDING_VECTOR_CHECK (NODE))->vec)
+#define BINDING_VECTOR_CLUSTER_LAST(NODE) \
+ (&BINDING_VECTOR_CLUSTER (NODE, BINDING_VECTOR_NUM_CLUSTERS (NODE) - 1))
+#define BINDING_VECTOR_CLUSTER(NODE,IX) \
+ (((tree_binding_vec *)BINDING_VECTOR_CHECK (NODE))->vec[IX])
+
+struct GTY(()) tree_binding_vec {
+ struct tree_base base;
+ tree name;
+ binding_cluster GTY((length ("%h.base.u.dependence_info.base"))) vec[1];
+};
+
+/* The name of a module vector. */
+#define BINDING_VECTOR_NAME(NODE) \
+ (((tree_binding_vec *)BINDING_VECTOR_CHECK (NODE))->name)
+
+/* tree_binding_vec does uses base.u.dependence_info.base field for
+ length. It does not have lang_flag etc available! */
+
+/* These two flags note if a module-vector contains deduplicated
+ bindings (i.e. multiple declarations in different imports). */
+/* This binding contains duplicate references to a global module
+ entity. */
+#define BINDING_VECTOR_GLOBAL_DUPS_P(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.static_flag)
+/* This binding contains duplicate references to a partioned module
+ entity. */
+#define BINDING_VECTOR_PARTITION_DUPS_P(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.volatile_flag)
+
+/* These two flags indicate the provenence of the bindings on this
+ particular vector slot. We can of course determine this from slot
+ number, but that's a relatively expensive lookup. This avoids
+ that when iterating. */
+/* This slot is part of the global module (a header unit). */
+#define MODULE_BINDING_GLOBAL_P(NODE) \
+ (OVERLOAD_CHECK (NODE)->base.static_flag)
+/* This slot is part of the current module (a partition or primary). */
+#define MODULE_BINDING_PARTITION_P(NODE) \
+ (OVERLOAD_CHECK (NODE)->base.volatile_flag)
+
+/* There are specializations of a template keyed to this binding. */
+#define BINDING_VECTOR_PENDING_SPECIALIZATIONS_P(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.public_flag)
+/* The key is in a header unit (not a named module partition or
+ primary). */
+#define BINDING_VECTOR_PENDING_IS_HEADER_P(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.protected_flag)
+/* The key is in a named module (primary or partition). */
+#define BINDING_VECTOR_PENDING_IS_PARTITION_P(NODE) \
+ (BINDING_VECTOR_CHECK (NODE)->base.private_flag)
extern tree identifier_type_value (tree);
extern void set_identifier_type_value (tree, tree);
@@ -361,7 +457,7 @@ extern tree *find_member_slot (tree klass, tree name);
extern tree *add_member_slot (tree klass, tree name);
extern void resort_type_member_vec (void *, void *,
gt_pointer_operator, void *);
-extern void set_class_bindings (tree, unsigned extra = 0);
+extern vec<tree, va_gc> *set_class_bindings (tree, int extra = 0);
extern void insert_late_enum_def_bindings (tree, tree);
extern tree innermost_non_namespace_value (tree);
extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
@@ -384,4 +480,34 @@ extern void maybe_save_operator_binding (tree);
extern void push_operator_bindings (void);
extern void discard_operator_bindings (tree);
+/* Lower level interface for modules. */
+extern tree *mergeable_namespace_slots (tree ns, tree name, bool is_global,
+ tree *mvec);
+extern void add_mergeable_namespace_entity (tree *slot, tree decl);
+extern tree lookup_class_binding (tree ctx, tree name);
+extern bool import_module_binding (tree ctx, tree name, unsigned mod,
+ unsigned snum);
+extern bool set_module_binding (tree ctx, tree name, unsigned mod,
+ int mod_glob_flag,
+ tree value, tree type, tree visible);
+extern void add_module_decl (tree ctx, tree name, tree decl);
+
+enum WMB_Flags
+{
+ WMB_None = 0,
+ WMB_Dups = 1 << 0,
+ WMB_Export = 1 << 1,
+ WMB_Using = 1 << 2,
+ WMB_Hidden = 1 << 3,
+};
+
+extern unsigned walk_module_binding (tree binding, bitmap partitions,
+ bool (*)(tree decl, WMB_Flags, void *data),
+ void *data);
+extern tree add_imported_namespace (tree ctx, tree name, unsigned module,
+ location_t, bool visible_p, bool inline_p);
+extern void note_pending_specializations (tree ns, tree name, bool is_header);
+extern void load_pending_specializations (tree ns, tree name);
+extern const char *get_cxx_dialect_name (enum cxx_dialect dialect);
+
#endif /* GCC_CP_NAME_LOOKUP_H */
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 00621d6..127d7fa 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -512,7 +512,7 @@ maybe_clone_body (tree fn)
DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
- set_decl_section_name (clone, DECL_SECTION_NAME (fn));
+ set_decl_section_name (clone, fn);
/* Adjust the parameter names and locations. */
parm = DECL_ARGUMENTS (fn);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7ec7d42..dd8e808 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -646,9 +646,17 @@ cp_lexer_new_main (void)
/* Put the first token in the buffer. */
cp_token *tok = lexer->buffer->quick_push (token);
+ uintptr_t filter = 0;
+ if (modules_p ())
+ filter = module_token_cdtor (parse_in, filter);
+
/* Get the remaining tokens from the preprocessor. */
while (tok->type != CPP_EOF)
{
+ if (filter)
+ /* Process the previous token. */
+ module_token_lang (tok->type, tok->keyword, tok->u.value,
+ tok->location, filter);
tok = vec_safe_push (lexer->buffer, cp_token ());
cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, tok);
}
@@ -658,10 +666,25 @@ cp_lexer_new_main (void)
+ lexer->buffer->length ()
- 1;
+ if (lexer->buffer->length () != 1)
+ {
+ /* Set the EOF token's location to be the just after the previous
+ token's range. That way 'at-eof' diagnostics point at something
+ meaninful. */
+ auto range = get_range_from_loc (line_table, tok[-1].location);
+ tok[0].location
+ = linemap_position_for_loc_and_offset (line_table, range.m_finish, 1);
+ }
+
+ if (filter)
+ module_token_cdtor (parse_in, filter);
+
/* Subsequent preprocessor diagnostics should use compiler
diagnostic functions to get the compiler source location. */
done_lexing = true;
+ maybe_check_all_macros (parse_in);
+
gcc_assert (!lexer->next_token->purged_p);
return lexer;
}
@@ -808,6 +831,14 @@ make_location (location_t caret, location_t start, cp_lexer *lexer)
return make_location (caret, start, t->location);
}
+/* Overload for make_location taking tokens instead of locations. */
+
+static inline location_t
+make_location (cp_token *caret, cp_token *start, cp_token *end)
+{
+ return make_location (caret->location, start->location, end->location);
+}
+
/* nonzero if we are presently saving tokens. */
static inline int
@@ -834,6 +865,8 @@ cp_lexer_get_preprocessor_token (unsigned flags, cp_token *token)
token->purged_p = false;
token->error_reported = false;
token->tree_check_p = false;
+ /* Usually never see a zero, but just in case ... */
+ token->main_source_p = line_table->depth <= 1;
/* On some systems, some header files are surrounded by an
implicit extern "C" block. Set a flag in the token if it
@@ -1438,7 +1471,8 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_call_declarator
- (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree, tree, tree);
+ (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier,
+ tree, tree, tree, tree, location_t);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
@@ -1621,7 +1655,8 @@ make_call_declarator (cp_declarator *target,
tree tx_qualifier,
tree exception_specification,
tree late_return_type,
- tree requires_clause)
+ tree requires_clause,
+ location_t parens_loc)
{
cp_declarator *declarator;
@@ -1635,6 +1670,7 @@ make_call_declarator (cp_declarator *target,
declarator->u.function.exception_specification = exception_specification;
declarator->u.function.late_return_type = late_return_type;
declarator->u.function.requires_clause = requires_clause;
+ declarator->u.function.parens_loc = parens_loc;
if (target)
{
declarator->id_loc = target->id_loc;
@@ -2179,12 +2215,34 @@ static tree cp_parser_implicitly_scoped_statement
static void cp_parser_already_scoped_statement
(cp_parser *, bool *, const token_indent_info &);
+/* State of module-declaration parsing. */
+enum module_parse
+{
+ MP_NOT_MODULE, /* Not a module. */
+
+ _MP_UNUSED,
+
+ MP_FIRST, /* First declaration of TU. */
+ MP_GLOBAL, /* Global Module Fragment. */
+
+ MP_PURVIEW_IMPORTS, /* Imports of a module. */
+ MP_PURVIEW, /* Purview of a named module. */
+
+ MP_PRIVATE_IMPORTS, /* Imports of a Private Module Fragment. */
+ MP_PRIVATE, /* Private Module Fragment. */
+};
+
+static module_parse cp_parser_module_declaration
+ (cp_parser *parser, module_parse, bool exporting);
+static void cp_parser_import_declaration
+ (cp_parser *parser, module_parse, bool exporting);
+
/* Declarations [gram.dcl.dcl] */
static void cp_parser_declaration_seq_opt
(cp_parser *);
static void cp_parser_declaration
- (cp_parser *);
+ (cp_parser *, tree);
static void cp_parser_toplevel_declaration
(cp_parser *);
static void cp_parser_block_declaration
@@ -2230,12 +2288,14 @@ static bool cp_parser_using_declaration
(cp_parser *, bool);
static void cp_parser_using_directive
(cp_parser *);
+static void cp_parser_using_enum
+ (cp_parser *);
static tree cp_parser_alias_declaration
(cp_parser *);
static void cp_parser_asm_definition
(cp_parser *);
static void cp_parser_linkage_specification
- (cp_parser *);
+ (cp_parser *, tree);
static void cp_parser_static_assert
(cp_parser *, bool);
static tree cp_parser_decltype
@@ -3406,6 +3466,15 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
else if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_NOEXCEPT])
inform (location, "C++11 %<noexcept%> only available with "
"%<-std=c++11%> or %<-std=gnu++11%>");
+ else if (TREE_CODE (id) == IDENTIFIER_NODE
+ && (id_equal (id, "module") || id_equal (id, "import")))
+ {
+ if (!modules_p ())
+ inform (location, "%qE only available with %<-fmodules-ts%>", id);
+ else
+ inform (location, "%qE was not recognized as a module control-line",
+ id);
+ }
else if (cxx_dialect < cxx11
&& TREE_CODE (id) == IDENTIFIER_NODE
&& id_equal (id, "thread_local"))
@@ -3699,6 +3768,13 @@ cp_parser_skip_to_closing_parenthesis_1 (cp_parser *parser,
condop_depth--;
break;
+ case CPP_KEYWORD:
+ if (token->keyword != RID__EXPORT
+ && token->keyword != RID__MODULE
+ && token->keyword != RID__IMPORT)
+ break;
+ /* FALLTHROUGH */
+
case CPP_PRAGMA:
/* We fell into a pragma. Skip it, and continue. */
cp_parser_skip_to_pragma_eol (parser, recovering ? token : nullptr);
@@ -3795,6 +3871,13 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
++nesting_depth;
break;
+ case CPP_KEYWORD:
+ if (token->keyword != RID__EXPORT
+ && token->keyword != RID__MODULE
+ && token->keyword != RID__IMPORT)
+ break;
+ /* FALLTHROUGH */
+
case CPP_PRAGMA:
/* We fell into a pragma. Skip it, and continue or return. */
cp_parser_skip_to_pragma_eol (parser, token);
@@ -3877,6 +3960,13 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
nesting_depth++;
break;
+ case CPP_KEYWORD:
+ if (token->keyword != RID__EXPORT
+ && token->keyword != RID__MODULE
+ && token->keyword != RID__IMPORT)
+ break;
+ /* FALLTHROUGH */
+
case CPP_PRAGMA:
/* Skip it, and continue or return. */
cp_parser_skip_to_pragma_eol (parser, token);
@@ -4758,6 +4848,10 @@ cp_parser_translation_unit (cp_parser* parser)
push_deferring_access_checks (flag_access_control
? dk_no_deferred : dk_no_check);
+ module_parse mp_state = MP_NOT_MODULE;
+ if (modules_p () && !header_module_p ())
+ mp_state = MP_FIRST;
+
bool implicit_extern_c = false;
/* Parse until EOF. */
@@ -4781,6 +4875,55 @@ cp_parser_translation_unit (cp_parser* parser)
if (token->type == CPP_EOF)
break;
+ if (modules_p ())
+ {
+ /* Top-level module declarations are ok, and change the
+ portion of file we're in. Top-level import declarations
+ are significant for the import portions. */
+
+ cp_token *next = token;
+ bool exporting = token->keyword == RID__EXPORT;
+ if (exporting)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ next = cp_lexer_peek_token (parser->lexer);
+ }
+ if (next->keyword == RID__MODULE)
+ {
+ mp_state
+ = cp_parser_module_declaration (parser, mp_state, exporting);
+ continue;
+ }
+ else if (next->keyword == RID__IMPORT)
+ {
+ if (mp_state == MP_FIRST)
+ mp_state = MP_NOT_MODULE;
+ cp_parser_import_declaration (parser, mp_state, exporting);
+ continue;
+ }
+ else
+ gcc_checking_assert (!exporting);
+
+ if (mp_state == MP_GLOBAL && token->main_source_p)
+ {
+ static bool warned = false;
+ if (!warned)
+ {
+ warned = true;
+ error_at (token->location,
+ "global module fragment contents must be"
+ " from preprocessor inclusion");
+ }
+ }
+ }
+
+ /* This relies on the ordering of module_parse values. */
+ if (mp_state == MP_PURVIEW_IMPORTS || mp_state == MP_PRIVATE_IMPORTS)
+ /* We're no longer in the import portion of a named module. */
+ mp_state = module_parse (mp_state + 1);
+ else if (mp_state == MP_FIRST)
+ mp_state = MP_NOT_MODULE;
+
if (token->type == CPP_CLOSE_BRACE)
{
cp_parser_error (parser, "expected declaration");
@@ -5138,6 +5281,8 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
// Left fold.
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
+ if (expr1)
+ return error_mark_node;
cp_lexer_consume_token (parser->lexer);
int op = cp_parser_fold_operator (parser);
if (op == ERROR_MARK)
@@ -5637,6 +5782,8 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_IS_UNION:
case RID_IS_ASSIGNABLE:
case RID_IS_CONSTRUCTIBLE:
+ case RID_IS_NOTHROW_ASSIGNABLE:
+ case RID_IS_NOTHROW_CONSTRUCTIBLE:
return cp_parser_trait_expr (parser, token->keyword);
// C++ concepts
@@ -5797,8 +5944,11 @@ cp_parser_primary_expression (cp_parser *parser,
if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN)
&& local_variable_p (decl))
{
- error_at (id_expression.get_location (),
- "local variable %qD may not appear in this context",
+ const char *msg
+ = (TREE_CODE (decl) == PARM_DECL
+ ? _("parameter %qD may not appear in this context")
+ : _("local variable %qD may not appear in this context"));
+ error_at (id_expression.get_location (), msg,
decl.get_value ());
return error_mark_node;
}
@@ -7230,6 +7380,32 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
tf_warning_or_error);
}
+ case RID_BUILTIN_BIT_CAST:
+ {
+ tree expression;
+ tree type;
+ /* Consume the `__builtin_bit_cast' token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Look for the opening `('. */
+ matching_parens parens;
+ parens.require_open (parser);
+ location_t type_location
+ = cp_lexer_peek_token (parser->lexer)->location;
+ /* Parse the type-id. */
+ {
+ type_id_in_expr_sentinel s (parser);
+ type = cp_parser_type_id (parser);
+ }
+ /* Look for the `,'. */
+ cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+ /* Now, parse the assignment-expression. */
+ expression = cp_parser_assignment_expression (parser);
+ /* Look for the closing `)'. */
+ parens.require_close (parser);
+ return cp_build_bit_cast (type_location, type, expression,
+ tf_warning_or_error);
+ }
+
default:
{
tree type;
@@ -8328,8 +8504,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
"ISO C++ does not allow %<alignof%> "
"with a non-type");
- ret = cxx_sizeof_or_alignof_expr (compound_loc,
- operand, op, true);
+ ret = cxx_sizeof_or_alignof_expr (compound_loc, operand, op,
+ std_alignof, true);
}
/* For SIZEOF_EXPR, just issue diagnostics, but keep
SIZEOF_EXPR with the original operand. */
@@ -9365,7 +9541,8 @@ maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc,
/* Replace the open paren with "CAST_SUGGESTION<". */
pretty_printer pp;
- pp_printf (&pp, "%s<", cast_suggestion);
+ pp_string (&pp, cast_suggestion);
+ pp_less (&pp);
rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text (&pp));
/* Replace the close paren with "> (". */
@@ -10501,6 +10678,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
kind = CPTK_IS_CONSTRUCTIBLE;
variadic = true;
break;
+ case RID_IS_NOTHROW_ASSIGNABLE:
+ kind = CPTK_IS_NOTHROW_ASSIGNABLE;
+ binary = true;
+ break;
+ case RID_IS_NOTHROW_CONSTRUCTIBLE:
+ kind = CPTK_IS_NOTHROW_CONSTRUCTIBLE;
+ variadic = true;
+ break;
default:
gcc_unreachable ();
}
@@ -10579,6 +10764,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
lambda-expression:
lambda-introducer lambda-declarator [opt] compound-statement
+ lambda-introducer < template-parameter-list > requires-clause [opt]
+ lambda-declarator [opt] compound-statement
Returns a representation of the expression. */
@@ -11036,13 +11223,11 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/* Parse the (optional) middle of a lambda expression.
lambda-declarator:
- < template-parameter-list [opt] >
- requires-clause [opt]
- ( parameter-declaration-clause [opt] )
- attribute-specifier [opt]
+ ( parameter-declaration-clause )
decl-specifier-seq [opt]
- exception-specification [opt]
- lambda-return-type-clause [opt]
+ noexcept-specifier [opt]
+ attribute-specifier-seq [opt]
+ trailing-return-type [opt]
requires-clause [opt]
LAMBDA_EXPR is the current representation of the lambda expression. */
@@ -11192,8 +11377,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
trailing-return-type in case of decltype. */
pop_bindings_and_leave_scope ();
}
- else if (template_param_list != NULL_TREE) // generate diagnostic
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
/* Create the function call operator.
@@ -11234,7 +11417,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
tx_qual,
exception_spec,
return_type,
- trailing_requires_clause);
+ trailing_requires_clause,
+ UNKNOWN_LOCATION);
declarator->std_attributes = std_attrs;
fco = grokmethod (&return_type_specs,
@@ -12655,8 +12839,15 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
for (const auto &x : range)
- if this version doesn't make a copy. DECL is the RANGE_DECL; EXPR is the
- *__for_begin expression.
+ if this version doesn't make a copy.
+
+ This function also warns when the loop variable is initialized with
+ a value of a different type resulting in a copy:
+
+ int arr[10];
+ for (const double &x : arr)
+
+ DECL is the RANGE_DECL; EXPR is the *__for_begin expression.
This function is never called when processing_template_decl is on. */
static void
@@ -12674,7 +12865,22 @@ warn_for_range_copy (tree decl, tree expr)
if (TYPE_REF_P (type))
{
- /* TODO: Implement reference warnings. */
+ if (glvalue_p (expr) && !ref_conv_binds_directly_p (type, expr))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wrange_loop_construct,
+ "loop variable %qD of type %qT binds to a temporary "
+ "constructed from type %qT", decl, type,
+ TREE_TYPE (expr)))
+ {
+ tree ref = cp_build_qualified_type (TREE_TYPE (expr),
+ TYPE_QUAL_CONST);
+ ref = cp_build_reference_type (ref, /*rval*/false);
+ inform (loc, "use non-reference type %qT to make the copy "
+ "explicit or %qT to prevent copying",
+ non_reference (type), ref);
+ }
+ }
return;
}
else if (!CP_TYPE_CONST_P (type))
@@ -13437,9 +13643,236 @@ cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p,
}
}
+/* Modules */
+
+/* Parse a module-name,
+ identifier
+ module-name . identifier
+ header-name
+
+ Returns a pointer to module object, NULL. */
+
+static module_state *
+cp_parser_module_name (cp_parser *parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_HEADER_NAME)
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ return get_module (token->u.value);
+ }
+
+ module_state *parent = NULL;
+ bool partitioned = false;
+ if (token->type == CPP_COLON && named_module_p ())
+ {
+ partitioned = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ for (;;)
+ {
+ if (cp_lexer_peek_token (parser->lexer)->type != CPP_NAME)
+ {
+ cp_parser_error (parser, "expected module-name");
+ break;
+ }
+
+ tree name = cp_lexer_consume_token (parser->lexer)->u.value;
+ parent = get_module (name, parent, partitioned);
+ token = cp_lexer_peek_token (parser->lexer);
+ if (!partitioned && token->type == CPP_COLON)
+ partitioned = true;
+ else if (token->type != CPP_DOT)
+ break;
+
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ return parent;
+}
+
+/* Named module-declaration
+ __module ; PRAGMA_EOL
+ __module private ; PRAGMA_EOL (unimplemented)
+ [__export] __module module-name attr-spec-seq-opt ; PRAGMA_EOL
+*/
+
+static module_parse
+cp_parser_module_declaration (cp_parser *parser, module_parse mp_state,
+ bool exporting)
+{
+ /* We're a pseudo pragma. */
+ parser->lexer->in_pragma = true;
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+ if (mp_state == MP_FIRST && !exporting
+ && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ {
+ /* Start global module fragment. */
+ cp_lexer_consume_token (parser->lexer);
+ module_kind |= MK_GLOBAL;
+ mp_state = MP_GLOBAL;
+ cp_parser_require_pragma_eol (parser, token);
+ }
+ else if (!exporting
+ && cp_lexer_next_token_is (parser->lexer, CPP_COLON)
+ && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_PRIVATE)
+ && cp_lexer_nth_token_is (parser->lexer, 3, CPP_SEMICOLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_require_pragma_eol (parser, token);
+
+ if ((mp_state != MP_PURVIEW && mp_state != MP_PURVIEW_IMPORTS)
+ || !module_interface_p () || module_partition_p ())
+ error_at (token->location,
+ "private module fragment not permitted here");
+ else
+ {
+ mp_state = MP_PRIVATE_IMPORTS;
+ sorry_at (token->location, "private module fragment");
+ }
+ }
+ else if (mp_state != MP_FIRST && mp_state != MP_GLOBAL)
+ {
+ error_at (token->location, "module-declaration not permitted here");
+ skip_eol:
+ cp_parser_skip_to_pragma_eol (parser, token);
+ }
+ else
+ {
+ module_state *mod = cp_parser_module_name (parser);
+ tree attrs = cp_parser_attributes_opt (parser);
+
+ mp_state = MP_PURVIEW_IMPORTS;
+ if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ goto skip_eol;
+
+ declare_module (mod, token->location, exporting, attrs, parse_in);
+ cp_parser_require_pragma_eol (parser, token);
+ }
+
+ return mp_state;
+}
+
+/* Import-declaration
+ [__export] __import module-name attr-spec-seq-opt ; PRAGMA_EOL */
+
+static void
+cp_parser_import_declaration (cp_parser *parser, module_parse mp_state,
+ bool exporting)
+{
+ /* We're a pseudo pragma. */
+ parser->lexer->in_pragma = true;
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+ if (mp_state != MP_PURVIEW_IMPORTS
+ && mp_state != MP_PRIVATE_IMPORTS
+ && module_purview_p ()
+ && !global_purview_p ())
+ {
+ error_at (token->location, "post-module-declaration"
+ " imports must be contiguous");
+ note_lexer:
+ inform (token->location, "perhaps insert a line break, or other"
+ " disambiguation, to prevent this being considered a"
+ " module control-line");
+ skip_eol:
+ cp_parser_skip_to_pragma_eol (parser, token);
+ }
+ else if (current_scope () != global_namespace)
+ {
+ error_at (token->location, "import-declaration must be at global scope");
+ goto note_lexer;
+ }
+ else
+ {
+ module_state *mod = cp_parser_module_name (parser);
+ tree attrs = cp_parser_attributes_opt (parser);
+
+ if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ goto skip_eol;
+ cp_parser_require_pragma_eol (parser, token);
+
+ if (parser->in_unbraced_linkage_specification_p)
+ error_at (token->location, "import cannot appear directly in"
+ " a linkage-specification");
+
+ /* Module-purview imports must not be from source inclusion
+ [cpp.import]/7 */
+ if (attrs && module_purview_p () && !global_purview_p ()
+ && private_lookup_attribute ("__translated",
+ strlen ("__translated"), attrs))
+ error_at (token->location, "post-module-declaration imports"
+ " must not be include-translated");
+ else if ((mp_state == MP_PURVIEW_IMPORTS
+ || mp_state == MP_PRIVATE_IMPORTS)
+ && !token->main_source_p)
+ error_at (token->location, "post-module-declaration imports"
+ " must not be from header inclusion");
+
+ import_module (mod, token->location, exporting, attrs, parse_in);
+ }
+}
+
+/* export-declaration.
+
+ export declaration
+ export { declaration-seq-opt } */
+
+static void
+cp_parser_module_export (cp_parser *parser)
+{
+ gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_EXPORT));
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+ if (!module_interface_p ())
+ error_at (token->location,
+ "%qE may only occur after a module interface declaration",
+ token->u.value);
+
+ bool braced = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE);
+
+ unsigned mk = module_kind;
+ if (module_exporting_p ())
+ error_at (token->location,
+ "%qE may only occur once in an export declaration",
+ token->u.value);
+ module_kind |= MK_EXPORTING;
+
+ if (braced)
+ {
+ cp_ensure_no_omp_declare_simd (parser);
+ cp_ensure_no_oacc_routine (parser);
+
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_declaration_seq_opt (parser);
+ cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ }
+ else
+ {
+ /* Explicitly check if the next tokens might be a
+ module-directive line, so we can give a clearer error message
+ about why the directive will be rejected. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID__MODULE)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID__IMPORT)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID__EXPORT))
+ error_at (token->location, "%<export%> not part of following"
+ " module-directive");
+ cp_parser_declaration (parser, NULL_TREE);
+ }
+
+ module_kind = mk;
+}
+
/* Declarations [gram.dcl.dcl] */
-/* Parse an optional declaration-sequence.
+/* Parse an optional declaration-sequence. TOP_LEVEL is true, if this
+ is the top-level declaration sequence. That affects whether we
+ deal with module-preamble.
declaration-seq:
declaration
@@ -13474,13 +13907,21 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
C++17:
deduction-guide
+ modules:
+ (all these are only allowed at the outermost level, check
+ that semantically, for better diagnostics)
+ module-declaration
+ module-export-declaration
+ module-import-declaration
+ export-declaration
+
GNU extension:
declaration:
__extension__ declaration */
static void
-cp_parser_declaration (cp_parser* parser)
+cp_parser_declaration (cp_parser* parser, tree prefix_attrs)
{
int saved_pedantic;
@@ -13488,7 +13929,7 @@ cp_parser_declaration (cp_parser* parser)
if (cp_parser_extension_opt (parser, &saved_pedantic))
{
/* Parse the qualified declaration. */
- cp_parser_declaration (parser);
+ cp_parser_declaration (parser, prefix_attrs);
/* Restore the PEDANTIC flag. */
pedantic = saved_pedantic;
@@ -13505,11 +13946,52 @@ cp_parser_declaration (cp_parser* parser)
tree attributes = NULL_TREE;
+ /* Conditionally, allow attributes to precede a linkage specification. */
+ if (token1->keyword == RID_ATTRIBUTE)
+ {
+ cp_lexer_save_tokens (parser->lexer);
+ attributes = cp_parser_attributes_opt (parser);
+ cp_token *t1 = cp_lexer_peek_token (parser->lexer);
+ cp_token *t2 = (t1->type == CPP_EOF
+ ? t1 : cp_lexer_peek_nth_token (parser->lexer, 2));
+ if (t1->keyword == RID_EXTERN
+ && cp_parser_is_pure_string_literal (t2))
+ {
+ cp_lexer_commit_tokens (parser->lexer);
+ /* We might have already been here. */
+ if (!c_dialect_objc ())
+ {
+ location_t where = get_finish (t2->location);
+ warning_at (token1->location, OPT_Wattributes, "attributes are"
+ " not permitted in this position");
+ where = linemap_position_for_loc_and_offset (line_table,
+ where, 1);
+ inform (where, "attributes may be inserted here");
+ attributes = NULL_TREE;
+ }
+ token1 = t1;
+ token2 = t2;
+ }
+ else
+ {
+ cp_lexer_rollback_tokens (parser->lexer);
+ attributes = NULL_TREE;
+ }
+ }
+ /* If we already had some attributes, and we've added more, then prepend.
+ Otherwise attributes just contains any that we just read. */
+ if (prefix_attrs)
+ {
+ if (attributes)
+ TREE_CHAIN (prefix_attrs) = attributes;
+ attributes = prefix_attrs;
+ }
+
/* If the next token is `extern' and the following token is a string
literal, then we have a linkage specification. */
if (token1->keyword == RID_EXTERN
&& cp_parser_is_pure_string_literal (token2))
- cp_parser_linkage_specification (parser);
+ cp_parser_linkage_specification (parser, attributes);
/* If the next token is `template', then we have either a template
declaration, an explicit instantiation, or an explicit
specialization. */
@@ -13526,10 +14008,28 @@ cp_parser_declaration (cp_parser* parser)
else
cp_parser_explicit_instantiation (parser);
}
- /* If the next token is `export', then we have a template
- declaration. */
+ /* If the next token is `export', it's new-style modules or
+ old-style template. */
else if (token1->keyword == RID_EXPORT)
- cp_parser_template_declaration (parser, /*member_p=*/false);
+ {
+ if (!modules_p ())
+ cp_parser_template_declaration (parser, /*member_p=*/false);
+ else
+ cp_parser_module_export (parser);
+ }
+ else if (token1->keyword == RID__EXPORT
+ || token1->keyword == RID__IMPORT
+ || token1->keyword == RID__MODULE)
+ {
+ bool exporting = token1->keyword == RID__EXPORT;
+ cp_token *next = exporting ? token2 : token1;
+ if (exporting)
+ cp_lexer_consume_token (parser->lexer);
+ if (next->keyword == RID__MODULE)
+ cp_parser_module_declaration (parser, MP_NOT_MODULE, exporting);
+ else
+ cp_parser_import_declaration (parser, MP_NOT_MODULE, exporting);
+ }
/* If the next token is `extern', 'static' or 'inline' and the one
after that is `template', we have a GNU extended explicit
instantiation directive. */
@@ -13559,7 +14059,7 @@ cp_parser_declaration (cp_parser* parser)
cp_parser_namespace_definition (parser);
/* Objective-C++ declaration/definition. */
else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1->keyword))
- cp_parser_objc_declaration (parser, NULL_TREE);
+ cp_parser_objc_declaration (parser, attributes);
else if (c_dialect_objc ()
&& token1->keyword == RID_ATTRIBUTE
&& cp_parser_objc_valid_prefix_attributes (parser, &attributes))
@@ -13601,7 +14101,7 @@ cp_parser_toplevel_declaration (cp_parser* parser)
}
else
/* Parse the declaration itself. */
- cp_parser_declaration (parser);
+ cp_parser_declaration (parser, NULL_TREE);
}
/* Parse a block-declaration.
@@ -13671,6 +14171,8 @@ cp_parser_block_declaration (cp_parser *parser,
token2 = cp_lexer_peek_nth_token (parser->lexer, 2);
if (token2->keyword == RID_NAMESPACE)
cp_parser_using_directive (parser);
+ else if (token2->keyword == RID_ENUM)
+ cp_parser_using_enum (parser);
/* If the second token after 'using' is '=', then we have an
alias-declaration. */
else if (cxx_dialect >= cxx11
@@ -14710,7 +15212,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
extern string-literal declaration */
static void
-cp_parser_linkage_specification (cp_parser* parser)
+cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr)
{
tree linkage;
@@ -14775,7 +15277,7 @@ cp_parser_linkage_specification (cp_parser* parser)
saved_in_unbraced_linkage_specification_p
= parser->in_unbraced_linkage_specification_p;
parser->in_unbraced_linkage_specification_p = true;
- cp_parser_declaration (parser);
+ cp_parser_declaration (parser, prefix_attr);
parser->in_unbraced_linkage_specification_p
= saved_in_unbraced_linkage_specification_p;
}
@@ -14870,7 +15372,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
/* Complete the static assertion, which may mean either processing
the static assert now or saving it for template instantiation. */
- finish_static_assert (condition, message, assert_loc, member_p);
+ finish_static_assert (condition, message, assert_loc, member_p,
+ /*show_expr_p=*/false);
}
/* Parse the expression in decltype ( expression ). */
@@ -16015,8 +16518,13 @@ cp_parser_template_declaration (cp_parser* parser, bool member_p)
{
/* Consume the `export' token. */
cp_lexer_consume_token (parser->lexer);
- /* Warn that we do not support `export'. */
- warning (0, "keyword %<export%> not implemented, and will be ignored");
+ /* Warn that this use of export is deprecated. */
+ if (cxx_dialect < cxx11)
+ warning (0, "keyword %<export%> not implemented, and will be ignored");
+ else if (cxx_dialect < cxx20)
+ warning (0, "keyword %<export%> is deprecated, and is ignored");
+ else
+ warning (0, "keyword %<export%> is enabled with %<-fmodules-ts%>");
}
cp_parser_template_declaration_after_export (parser, member_p);
@@ -17632,10 +18140,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
instantiation. */
if (declares_class_or_enum && cp_parser_declares_only_class_p (parser))
{
- tree type;
-
- type = check_tag_decl (&decl_specifiers,
- /*explicit_type_instantiation_p=*/true);
+ tree type = check_tag_decl (&decl_specifiers,
+ /*explicit_type_instantiation_p=*/true);
/* Turn access control back on for names used during
template instantiation. */
pop_deferring_access_checks ();
@@ -17739,7 +18245,6 @@ cp_parser_explicit_specialization (cp_parser* parser)
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
- need_lang_pop = true;
}
/* Let the front end know that we are beginning a specialization. */
@@ -19155,7 +19660,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
if (TREE_CODE (type) == TYPENAME_TYPE)
warning (OPT_Wattributes,
"attributes ignored on uninstantiated type");
- else if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+ else if (tag_type != enum_type
+ && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
&& ! processing_explicit_instantiation)
warning (OPT_Wattributes,
"attributes ignored on template instantiation");
@@ -19237,7 +19744,7 @@ cp_parser_enum_specifier (cp_parser* parser)
bool is_unnamed = false;
tree underlying_type = NULL_TREE;
cp_token *type_start_token = NULL;
- temp_override<bool> cleanup (parser->colon_corrects_to_scope_p, false);
+ auto cleanup = make_temp_override (parser->colon_corrects_to_scope_p, false);
/* Parse tentatively so that we can back up if we don't find a
enum-specifier. */
@@ -19952,6 +20459,31 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
return cp_parser_namespace_name (parser);
}
+/* Subroutine of cp_parser_using_declaration. */
+
+static tree
+finish_using_decl (tree qscope, tree identifier, bool typename_p = false)
+{
+ tree decl = NULL_TREE;
+ if (at_class_scope_p ())
+ {
+ /* Create the USING_DECL. */
+ decl = do_class_using_decl (qscope, identifier);
+
+ if (check_for_bare_parameter_packs (decl))
+ return error_mark_node;
+
+ if (decl && typename_p)
+ USING_DECL_TYPENAME_P (decl) = 1;
+
+ /* Add it to the list of members in this class. */
+ finish_member_declaration (decl);
+ }
+ else
+ finish_nonmember_using_decl (qscope, identifier);
+ return decl;
+}
+
/* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an
access declaration.
@@ -19971,7 +20503,6 @@ cp_parser_using_declaration (cp_parser* parser,
cp_token *token;
bool typename_p = false;
bool global_scope_p;
- tree decl;
tree identifier;
tree qscope;
int oldcount = errorcount;
@@ -20030,9 +20561,6 @@ cp_parser_using_declaration (cp_parser* parser,
/*is_declaration=*/true);
if (!qscope)
qscope = global_namespace;
- else if (UNSCOPED_ENUM_P (qscope)
- && !TYPE_FUNCTION_SCOPE_P (qscope))
- qscope = CP_TYPE_CONTEXT (qscope);
cp_warn_deprecated_use_scopes (qscope);
@@ -20080,25 +20608,13 @@ cp_parser_using_declaration (cp_parser* parser,
"a template-id may not appear in a using-declaration");
else
{
- if (at_class_scope_p ())
- {
- /* Create the USING_DECL. */
- decl = do_class_using_decl (qscope, identifier);
+ tree decl = finish_using_decl (qscope, identifier, typename_p);
- if (decl && typename_p)
- USING_DECL_TYPENAME_P (decl) = 1;
-
- if (check_for_bare_parameter_packs (decl))
- {
- cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
- return false;
- }
- else
- /* Add it to the list of members in this class. */
- finish_member_declaration (decl);
+ if (decl == error_mark_node)
+ {
+ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+ return false;
}
- else
- finish_nonmember_using_decl (qscope, identifier);
}
if (!access_declaration_p
@@ -20124,6 +20640,76 @@ cp_parser_using_declaration (cp_parser* parser,
return true;
}
+/* C++20 using enum declaration.
+
+ using-enum-declaration :
+ using elaborated-enum-specifier ; */
+
+static void
+cp_parser_using_enum (cp_parser *parser)
+{
+ cp_parser_require_keyword (parser, RID_USING, RT_USING);
+
+ /* Using cp_parser_elaborated_type_specifier rejects typedef-names, which
+ breaks one of the motivating examples in using-enum-5.C.
+ cp_parser_simple_type_specifier seems to be closer to what we actually
+ want, though that hasn't been properly specified yet. */
+
+ /* Consume 'enum'. */
+ gcc_checking_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM));
+ cp_lexer_consume_token (parser->lexer);
+
+ cp_token *start = cp_lexer_peek_token (parser->lexer);
+
+ tree type = (cp_parser_simple_type_specifier
+ (parser, NULL, CP_PARSER_FLAGS_TYPENAME_OPTIONAL));
+
+ cp_token *end = cp_lexer_previous_token (parser->lexer);
+
+ if (type == error_mark_node
+ || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ {
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+
+ /* The elaborated-enum-specifier shall not name a dependent type and the type
+ shall have a reachable enum-specifier. */
+ const char *msg = nullptr;
+ if (cxx_dialect < cxx20)
+ msg = _("%<using enum%> "
+ "only available with %<-std=c++20%> or %<-std=gnu++20%>");
+ else if (dependent_type_p (type))
+ msg = _("%<using enum%> of dependent type %qT");
+ else if (TREE_CODE (type) != ENUMERAL_TYPE)
+ msg = _("%<using enum%> of non-enumeration type %q#T");
+ else if (!COMPLETE_TYPE_P (type))
+ msg = _("%<using enum%> of incomplete type %qT");
+ else if (OPAQUE_ENUM_P (type))
+ msg = _("%<using enum%> of %qT before its enum-specifier");
+ if (msg)
+ {
+ location_t loc = make_location (start, start, end);
+ auto_diagnostic_group g;
+ error_at (loc, msg, type);
+ loc = location_of (type);
+ if (cxx_dialect < cxx20 || loc == input_location)
+ ;
+ else if (OPAQUE_ENUM_P (type))
+ inform (loc, "opaque-enum-declaration here");
+ else
+ inform (loc, "declared here");
+ }
+
+ /* A using-enum-declaration introduces the enumerator names of the named
+ enumeration as if by a using-declaration for each enumerator. */
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ for (tree v = TYPE_VALUES (type); v; v = TREE_CHAIN (v))
+ finish_using_decl (type, DECL_NAME (TREE_VALUE (v)));
+}
+
/* Parse an alias-declaration.
alias-declaration:
@@ -20476,8 +21062,7 @@ cp_parser_asm_definition (cp_parser* parser)
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_SCOPE)
&& cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN)
- && !goto_p)
+ CPP_CLOSE_PAREN))
{
outputs = cp_parser_asm_operand_list (parser);
if (outputs == error_mark_node)
@@ -20603,6 +21188,139 @@ strip_declarator_types (tree type, cp_declarator *declarator)
return type;
}
+/* Warn about the most vexing parse syntactic ambiguity, i.e., warn when
+ a construct looks like a variable definition but is actually a function
+ declaration. DECL_SPECIFIERS is the decl-specifier-seq and DECLARATOR
+ is the declarator for this function declaration. */
+
+static void
+warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers,
+ const cp_declarator *declarator)
+{
+ /* Only warn if we are declaring a function at block scope. */
+ if (!at_function_scope_p ())
+ return;
+
+ /* And only if there is no storage class specified. */
+ if (decl_specifiers->storage_class != sc_none
+ || decl_spec_seq_has_spec_p (decl_specifiers, ds_typedef))
+ return;
+
+ if (declarator->kind != cdk_function
+ || !declarator->declarator
+ || declarator->declarator->kind != cdk_id
+ || !identifier_p (get_unqualified_id
+ (const_cast<cp_declarator *>(declarator))))
+ return;
+
+ /* Don't warn when the whole declarator (not just the declarator-id!)
+ was parenthesized. That is, don't warn for int(n()) but do warn
+ for int(f)(). */
+ if (declarator->parenthesized != UNKNOWN_LOCATION)
+ return;
+
+ tree type;
+ if (decl_specifiers->type)
+ {
+ type = decl_specifiers->type;
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+
+ /* If the return type is void there is no ambiguity. */
+ if (same_type_p (type, void_type_node))
+ return;
+ }
+ else if (decl_specifiers->any_type_specifiers_p)
+ /* Code like long f(); will have null ->type. If we have any
+ type-specifiers, pretend we've seen int. */
+ type = integer_type_node;
+ else
+ return;
+
+ auto_diagnostic_group d;
+ location_t loc = declarator->u.function.parens_loc;
+ tree params = declarator->u.function.parameters;
+ const bool has_list_ctor_p = CLASS_TYPE_P (type) && TYPE_HAS_LIST_CTOR (type);
+
+ /* The T t() case. */
+ if (params == void_list_node)
+ {
+ if (warning_at (loc, OPT_Wvexing_parse,
+ "empty parentheses were disambiguated as a function "
+ "declaration"))
+ {
+ /* () means value-initialization (C++03 and up); {} (C++11 and up)
+ means value-initialization or aggregate-initialization, nothing
+ means default-initialization. We can only suggest removing the
+ parentheses/adding {} if T has a default constructor. */
+ if (!CLASS_TYPE_P (type) || TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ {
+ gcc_rich_location iloc (loc);
+ iloc.add_fixit_remove ();
+ inform (&iloc, "remove parentheses to default-initialize "
+ "a variable");
+ if (cxx_dialect >= cxx11 && !has_list_ctor_p)
+ {
+ if (CP_AGGREGATE_TYPE_P (type))
+ inform (loc, "or replace parentheses with braces to "
+ "aggregate-initialize a variable");
+ else
+ inform (loc, "or replace parentheses with braces to "
+ "value-initialize a variable");
+ }
+ }
+ }
+ return;
+ }
+
+ /* If we had (...) or the parameter-list wasn't parenthesized,
+ we're done. */
+ if (params == NULL_TREE || !PARENTHESIZED_LIST_P (params))
+ return;
+
+ /* The T t(X()) case. */
+ if (list_length (params) == 2)
+ {
+ if (warning_at (loc, OPT_Wvexing_parse,
+ "parentheses were disambiguated as a function "
+ "declaration"))
+ {
+ gcc_rich_location iloc (loc);
+ /* {}-initialization means that we can use an initializer-list
+ constructor if no default constructor is available, so don't
+ suggest using {} for classes that have an initializer_list
+ constructor. */
+ if (cxx_dialect >= cxx11 && !has_list_ctor_p)
+ {
+ iloc.add_fixit_replace (get_start (loc), "{");
+ iloc.add_fixit_replace (get_finish (loc), "}");
+ inform (&iloc, "replace parentheses with braces to declare a "
+ "variable");
+ }
+ else
+ {
+ iloc.add_fixit_insert_after (get_start (loc), "(");
+ iloc.add_fixit_insert_before (get_finish (loc), ")");
+ inform (&iloc, "add parentheses to declare a variable");
+ }
+ }
+ }
+ /* The T t(X(), X()) case. */
+ else if (warning_at (loc, OPT_Wvexing_parse,
+ "parentheses were disambiguated as a function "
+ "declaration"))
+ {
+ gcc_rich_location iloc (loc);
+ if (cxx_dialect >= cxx11 && !has_list_ctor_p)
+ {
+ iloc.add_fixit_replace (get_start (loc), "{");
+ iloc.add_fixit_replace (get_finish (loc), "}");
+ inform (&iloc, "replace parentheses with braces to declare a "
+ "variable");
+ }
+ }
+}
+
/* Declarators [gram.dcl.decl] */
/* Parse an init-declarator.
@@ -20780,6 +21498,7 @@ cp_parser_init_declarator (cp_parser* parser,
{
/* Handle C++17 deduction guides. */
if (!decl_specifiers->type
+ && !decl_specifiers->any_type_specifiers_p
&& ctor_dtor_or_conv_p <= 0
&& cxx_dialect >= cxx17)
{
@@ -20797,6 +21516,9 @@ cp_parser_init_declarator (cp_parser* parser,
}
}
+ if (!member_p && !cp_parser_error_occurred (parser))
+ warn_about_ambiguous_parse (decl_specifiers, declarator);
+
/* Check to see if the token indicates the start of a
function-definition. */
if (cp_parser_token_starts_function_definition_p (token))
@@ -21191,7 +21913,7 @@ cp_parser_declarator (cp_parser* parser,
/* If a ptr-operator was found, then this declarator was not
parenthesized. */
if (parenthesized_p)
- *parenthesized_p = true;
+ *parenthesized_p = false;
/* The dependent declarator is optional if we are parsing an
abstract-declarator. */
if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)
@@ -21338,6 +22060,7 @@ cp_parser_direct_declarator (cp_parser* parser,
cp_parser_parse_tentatively (parser);
/* Consume the `('. */
+ const location_t parens_start = token->location;
matching_parens parens;
parens.consume_open (parser);
if (first)
@@ -21357,6 +22080,8 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse the parameter-declaration-clause. */
params
= cp_parser_parameter_declaration_clause (parser, flags);
+ const location_t parens_end
+ = cp_lexer_peek_token (parser->lexer)->location;
/* Consume the `)'. */
parens.require_close (parser);
@@ -21421,6 +22146,9 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse the virt-specifier-seq. */
virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+ location_t parens_loc = make_location (parens_start,
+ parens_start,
+ parens_end);
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
@@ -21430,7 +22158,8 @@ cp_parser_direct_declarator (cp_parser* parser,
tx_qual,
exception_specification,
late_return,
- requires_clause);
+ requires_clause,
+ parens_loc);
declarator->std_attributes = attrs;
declarator->attributes = gnu_attrs;
/* Any subsequent parameter lists are to do with
@@ -21856,7 +22585,9 @@ cp_parser_direct_declarator (cp_parser* parser,
open_paren = NULL;
}
if (open_paren)
- declarator->parenthesized = open_paren->location;
+ declarator->parenthesized = make_location (open_paren->location,
+ open_paren->location,
+ close_paren->location);
}
/* If we entered a scope, we must exit it now. */
@@ -22407,9 +23138,20 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
+ bool auto_typeid_ok = false;
+ /* The concepts TS allows 'auto' as a type-id. */
+ if (flag_concepts_ts)
+ auto_typeid_ok = !parser->in_type_id_in_expr_p;
+ /* DR 625 prohibits use of auto as a template-argument. We allow 'auto'
+ outside the template-argument-list context here only for the sake of
+ diagnostic: grokdeclarator then can emit a better error message for
+ e.g. using T = auto. */
+ else if (flag_concepts)
+ auto_typeid_ok = (!parser->in_type_id_in_expr_p
+ && !parser->in_template_argument_list_p);
+
if (type_specifier_seq.type
- /* The concepts TS allows 'auto' as a type-id. */
- && (!flag_concepts || parser->in_type_id_in_expr_p)
+ && !auto_typeid_ok
/* None of the valid uses of 'auto' in C++14 involve the type-id
nonterminal, but it is valid in a trailing-return-type. */
&& !(cxx_dialect >= cxx14 && is_trailing_return))
@@ -22436,6 +23178,9 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here",
tmpl);
}
+ else if (parser->in_template_argument_list_p)
+ error_at (loc, "%qT not permitted in template argument",
+ auto_node);
else
error_at (loc, "invalid use of %qT", auto_node);
return error_mark_node;
@@ -22648,7 +23393,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser,
cp_token *token;
bool ellipsis_p;
- temp_override<bool> cleanup
+ auto cleanup = make_temp_override
(parser->auto_is_implicit_function_template_parm_p);
if (!processing_specialization
@@ -22681,7 +23426,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser,
/* Consume the `void' token. */
cp_lexer_consume_token (parser->lexer);
/* There are no parameters. */
- return void_list_node;
+ return explicit_void_list_node;
}
/* Parse the parameter-declaration-list. */
@@ -22805,6 +23550,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
*tail = build_tree_list (parameter->default_argument, decl);
tail = &TREE_CHAIN (*tail);
+ /* If the parameters were parenthesized, it's the case of
+ T foo(X(x)) which looks like a variable definition but
+ is a function declaration. */
+ if (index == 1 || PARENTHESIZED_LIST_P (parameters))
+ PARENTHESIZED_LIST_P (parameters) = parenthesized_p;
+
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
|| cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
@@ -23784,13 +24535,10 @@ cp_parser_class_name (cp_parser *parser,
bool enum_ok)
{
tree decl;
- tree scope;
- bool typename_p;
- cp_token *token;
tree identifier = NULL_TREE;
/* All class-names start with an identifier. */
- token = cp_lexer_peek_token (parser->lexer);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
{
cp_parser_error (parser, "expected class-name");
@@ -23806,14 +24554,16 @@ cp_parser_class_name (cp_parser *parser,
where we first want to look up A<T>::a in the class of the object
expression, as per [basic.lookup.classref]. */
- scope = parser->scope ? parser->scope : parser->context->object_type;
+ tree scope = parser->scope ? parser->scope : parser->context->object_type;
if (scope == error_mark_node)
return error_mark_node;
/* Any name names a type if we're following the `typename' keyword
in a qualified name where the enclosing scope is type-dependent. */
- typename_p = (typename_keyword_p && scope && TYPE_P (scope)
- && dependent_type_p (scope));
+ const bool typename_p = (typename_keyword_p
+ && parser->scope
+ && TYPE_P (parser->scope)
+ && dependent_type_p (parser->scope));
/* Handle the common case (an identifier, but not a template-id)
efficiently. */
if (token->type == CPP_NAME
@@ -24309,8 +25059,12 @@ cp_parser_class_specifier_1 (cp_parser* parser)
/* Now we can parse the noexcept-specifier. */
spec = cp_parser_late_noexcept_specifier (parser, spec);
- if (spec != error_mark_node)
- TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
+ if (spec == error_mark_node)
+ spec = NULL_TREE;
+
+ /* Update the fn's type directly -- it might have escaped
+ beyond this decl :( */
+ fixup_deferred_exception_variants (TREE_TYPE (decl), spec);
/* Restore the state of local_variables_forbidden_p. */
parser->local_variables_forbidden_p = local_variables_forbidden_p;
@@ -25052,12 +25806,10 @@ cp_parser_member_declaration (cp_parser* parser)
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
{
if (cxx_dialect < cxx11)
- {
- /* Parse the using-declaration. */
- cp_parser_using_declaration (parser,
- /*access_declaration_p=*/false);
- return;
- }
+ /* Parse the using-declaration. */
+ cp_parser_using_declaration (parser, /*access_declaration_p=*/false);
+ else if (cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_ENUM))
+ cp_parser_using_enum (parser);
else
{
tree decl;
@@ -25078,8 +25830,8 @@ cp_parser_member_declaration (cp_parser* parser)
else
cp_parser_using_declaration (parser,
/*access_declaration_p=*/false);
- return;
}
+ return;
}
/* Check for @defs. */
@@ -25146,14 +25898,12 @@ cp_parser_member_declaration (cp_parser* parser)
}
else
{
- tree type;
-
/* See if this declaration is a friend. */
friend_p = cp_parser_friend_p (&decl_specifiers);
/* If there were decl-specifiers, check to see if there was
a class-declaration. */
- type = check_tag_decl (&decl_specifiers,
- /*explicit_type_instantiation_p=*/false);
+ tree type = check_tag_decl (&decl_specifiers,
+ /*explicit_type_instantiation_p=*/false);
/* Nested classes have already been added to the class, but
a `friend' needs to be explicitly registered. */
if (friend_p)
@@ -25348,6 +26098,9 @@ cp_parser_member_declaration (cp_parser* parser)
int ctor_dtor_or_conv_p;
bool static_p = (decl_specifiers.storage_class == sc_static);
cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+ /* We can't delay parsing for friends,
+ alias-declarations, and typedefs, even though the
+ standard seems to require it. */
if (!friend_p
&& !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef))
flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT;
@@ -26036,19 +26789,14 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
a class. So, if the noexcept-specifier has the optional expression,
just save the tokens, and reparse this after we're done with the
class. */
- const bool literal_p
- = ((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
- || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD))
- && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN));
- if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
+ if ((flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
/* No need to delay parsing for a number literal or true/false. */
- && !literal_p
+ && !((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
+ || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD))
+ && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN))
&& at_class_scope_p ()
- /* We don't delay parsing for friend member functions,
- alias-declarations, and typedefs, even though the standard seems
- to require it. */
- && (flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT)
&& TYPE_BEING_DEFINED (current_class_type)
&& !LAMBDA_TYPE_P (current_class_type))
return cp_parser_save_noexcept (parser);
@@ -26752,7 +27500,7 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
{
tree attributes = NULL_TREE;
- temp_override<bool> cleanup
+ auto cleanup = make_temp_override
(parser->auto_is_implicit_function_template_parm_p, false);
while (true)
@@ -26952,7 +27700,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
tree attribute, attr_id = NULL_TREE, arguments;
cp_token *token;
- temp_override<bool> cleanup
+ auto cleanup = make_temp_override
(parser->auto_is_implicit_function_template_parm_p, false);
/* First, parse name of the attribute, a.k.a attribute-token. */
@@ -27096,30 +27844,30 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
return attribute;
}
-/* Check that the attribute ATTRIBUTE appears at most once in the
- attribute-list ATTRIBUTES. This is enforced for noreturn (7.6.3),
- nodiscard, and deprecated (7.6.5). Note that
- carries_dependency (7.6.4) isn't implemented yet in GCC. */
+/* Warn if the attribute ATTRIBUTE appears more than once in the
+ attribute-list ATTRIBUTES. This used to be enforced for certain
+ attributes, but the restriction was removed in P2156. Note that
+ carries_dependency ([dcl.attr.depend]) isn't implemented yet in GCC.
+ LOC is the location of ATTRIBUTE. Returns true if ATTRIBUTE was not
+ found in ATTRIBUTES. */
-static void
-cp_parser_check_std_attribute (tree attributes, tree attribute)
+static bool
+cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute)
{
+ static auto alist = { "noreturn", "deprecated", "nodiscard", "maybe_unused",
+ "likely", "unlikely", "fallthrough",
+ "no_unique_address" };
if (attributes)
- {
- tree name = get_attribute_name (attribute);
- if (is_attribute_p ("noreturn", name)
- && lookup_attribute ("noreturn", attributes))
- error ("attribute %<noreturn%> can appear at most once "
- "in an attribute-list");
- else if (is_attribute_p ("deprecated", name)
- && lookup_attribute ("deprecated", attributes))
- error ("attribute %<deprecated%> can appear at most once "
- "in an attribute-list");
- else if (is_attribute_p ("nodiscard", name)
- && lookup_attribute ("nodiscard", attributes))
- error ("attribute %<nodiscard%> can appear at most once "
- "in an attribute-list");
- }
+ for (const auto &a : alist)
+ if (is_attribute_p (a, get_attribute_name (attribute))
+ && lookup_attribute (a, attributes))
+ {
+ if (!from_macro_expansion_at (loc))
+ warning_at (loc, OPT_Wattributes, "attribute %qs specified "
+ "multiple times", a);
+ return false;
+ }
+ return true;
}
/* Parse a list of standard C++-11 attributes.
@@ -27139,14 +27887,17 @@ cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns)
while (true)
{
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
attribute = cp_parser_std_attribute (parser, attr_ns);
if (attribute == error_mark_node)
break;
if (attribute != NULL_TREE)
{
- cp_parser_check_std_attribute (attributes, attribute);
- TREE_CHAIN (attribute) = attributes;
- attributes = attribute;
+ if (cp_parser_check_std_attribute (loc, attributes, attribute))
+ {
+ TREE_CHAIN (attribute) = attributes;
+ attributes = attribute;
+ }
}
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_ELLIPSIS)
@@ -28460,11 +29211,6 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
prefer_type_arg (tag_type),
/*complain=*/true);
- /* If we have a single function from a using decl, pull it out. */
- if (TREE_CODE (decl) == OVERLOAD
- && !really_overloaded_fn (decl))
- decl = OVL_FUNCTION (decl);
-
if (pushed_scope)
pop_scope (pushed_scope);
}
@@ -29183,6 +29929,14 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
/* Finish the function. */
fn = finish_function (inline_p);
+
+ if (modules_p ()
+ && !inline_p
+ && TYPE_P (DECL_CONTEXT (fn))
+ && (DECL_DECLARED_INLINE_P (fn)
+ || processing_template_decl))
+ set_defining_module (fn);
+
/* Generate code for it, if necessary. */
expand_or_defer_fn (fn);
/* Restore the saved values. */
@@ -29422,7 +30176,8 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p)
{
if (!flag_concepts_ts)
pedwarn (introduction_loc, 0, "template-introductions"
- " are not part of C++20 concepts [-fconcepts-ts]");
+ " are not part of C++20 concepts; use %qs to enable",
+ "-fconcepts-ts");
cp_parser_template_declaration_after_parameters (parser, parms,
member_p);
@@ -30218,7 +30973,6 @@ static void
cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
{
unsigned char saved_local_variables_forbidden_p;
- tree parm, parmdecl;
/* While we're parsing the default args, we might (due to the
statement expression extension) encounter more classes. We want
@@ -30233,17 +30987,26 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
push_defarg_context (fn);
- for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)),
- parmdecl = DECL_ARGUMENTS (fn);
+ begin_scope (sk_function_parms, fn);
+
+ /* Gather the PARM_DECLs into a vec so we can keep track of them when
+ pushdecl clears DECL_CHAIN. */
+ releasing_vec parms;
+ for (tree parmdecl = DECL_ARGUMENTS (fn); parmdecl;
+ parmdecl = DECL_CHAIN (parmdecl))
+ vec_safe_push (parms, parmdecl);
+
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ for (int i = 0;
parm && parm != void_list_node;
parm = TREE_CHAIN (parm),
- parmdecl = DECL_CHAIN (parmdecl))
+ ++i)
{
tree default_arg = TREE_PURPOSE (parm);
tree parsed_arg;
- vec<tree, va_gc> *insts;
- tree copy;
- unsigned ix;
+
+ tree parmdecl = parms[i];
+ pushdecl (parmdecl);
if (!default_arg)
continue;
@@ -30260,11 +31023,20 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
TREE_PURPOSE (parm) = parsed_arg;
/* Update any instantiations we've already created. */
- for (insts = DEFPARSE_INSTANTIATIONS (default_arg), ix = 0;
- vec_safe_iterate (insts, ix, &copy); ix++)
+ for (tree copy : DEFPARSE_INSTANTIATIONS (default_arg))
TREE_PURPOSE (copy) = parsed_arg;
}
+ pop_bindings_and_leave_scope ();
+
+ /* Restore DECL_CHAINs after clobbering by pushdecl. */
+ parm = NULL_TREE;
+ for (int i = parms->length () - 1; i >= 0; --i)
+ {
+ DECL_CHAIN (parms[i]) = parm;
+ parm = parms[i];
+ }
+
pop_defarg_context ();
/* Make sure no default arg is missing. */
@@ -32916,7 +33688,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
if (token->keyword == RID_EXTERN
&& cp_parser_is_pure_string_literal
(cp_lexer_peek_nth_token (parser->lexer, 2)))
- cp_parser_linkage_specification (parser);
+ cp_parser_linkage_specification (parser, NULL_TREE);
/* Handle #pragma, if any. */
else if (token->type == CPP_PRAGMA)
cp_parser_pragma (parser, pragma_objc_icode, NULL);
@@ -33352,6 +34124,7 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
bool is_class_extension;
cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
+ location_t nam_loc = cp_lexer_peek_token (parser->lexer)->location;
name = cp_parser_identifier (parser);
if (name == error_mark_node)
{
@@ -33371,7 +34144,7 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
objc_start_category_interface (name, categ, protos, attributes);
else
{
- objc_start_class_interface (name, super, protos, attributes);
+ objc_start_class_interface (name, nam_loc, super, protos, attributes);
/* Handle instance variable declarations, if any. */
cp_parser_objc_class_ivars (parser);
objc_continue_interface ();
@@ -33681,11 +34454,15 @@ static bool
cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
{
cp_lexer_save_tokens (parser->lexer);
- *attrib = cp_parser_attributes_opt (parser);
- gcc_assert (*attrib);
- if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
+ tree addon = cp_parser_attributes_opt (parser);
+ if (addon
+ && OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
{
cp_lexer_commit_tokens (parser->lexer);
+ if (*attrib)
+ TREE_CHAIN (*attrib) = addon;
+ else
+ *attrib = addon;
return true;
}
cp_lexer_rollback_tokens (parser->lexer);
@@ -33828,30 +34605,11 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
static void
cp_parser_objc_at_property_declaration (cp_parser *parser)
{
- /* The following variables hold the attributes of the properties as
- parsed. They are 'false' or 'NULL_TREE' if the attribute was not
- seen. When we see an attribute, we set them to 'true' (if they
- are boolean properties) or to the identifier (if they have an
- argument, ie, for getter and setter). Note that here we only
- parse the list of attributes, check the syntax and accumulate the
- attributes that we find. objc_add_property_declaration() will
- then process the information. */
- bool property_assign = false;
- bool property_copy = false;
- tree property_getter_ident = NULL_TREE;
- bool property_nonatomic = false;
- bool property_readonly = false;
- bool property_readwrite = false;
- bool property_retain = false;
- tree property_setter_ident = NULL_TREE;
+ /* Parse the optional attribute list.
- /* 'properties' is the list of properties that we read. Usually a
- single one, but maybe more (eg, in "@property int a, b, c;" there
- are three). */
- tree properties;
- location_t loc;
-
- loc = cp_lexer_peek_token (parser->lexer)->location;
+ A list of parsed, but not verified, attributes. */
+ vec<property_attribute_info *> prop_attr_list = vNULL;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */
@@ -33860,132 +34618,176 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
{
/* Eat the '('. */
matching_parens parens;
+ location_t attr_start = cp_lexer_peek_token (parser->lexer)->location;
parens.consume_open (parser);
+ bool syntax_error = false;
- while (true)
+ /* Allow empty @property attribute lists, but with a warning. */
+ location_t attr_end = cp_lexer_peek_token (parser->lexer)->location;
+ location_t attr_comb;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
{
- bool syntax_error = false;
- cp_token *token = cp_lexer_peek_token (parser->lexer);
- enum rid keyword;
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ warning_at (attr_comb, OPT_Wattributes,
+ "empty property attribute list");
+ }
+ else
+ while (true)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ attr_start = token->location;
+ attr_end = get_finish (token->location);
+ attr_comb = make_location (attr_start, attr_start, attr_end);
- if (token->type != CPP_NAME)
- {
- cp_parser_error (parser, "expected identifier");
- break;
- }
- keyword = C_RID_CODE (token->u.value);
- cp_lexer_consume_token (parser->lexer);
- switch (keyword)
- {
- case RID_ASSIGN: property_assign = true; break;
- case RID_COPY: property_copy = true; break;
- case RID_NONATOMIC: property_nonatomic = true; break;
- case RID_READONLY: property_readonly = true; break;
- case RID_READWRITE: property_readwrite = true; break;
- case RID_RETAIN: property_retain = true; break;
-
- case RID_GETTER:
- case RID_SETTER:
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
- {
- if (keyword == RID_GETTER)
- cp_parser_error (parser,
- "missing %<=%> (after %<getter%> attribute)");
- else
- cp_parser_error (parser,
- "missing %<=%> (after %<setter%> attribute)");
- syntax_error = true;
- break;
- }
- cp_lexer_consume_token (parser->lexer); /* eat the = */
- if (!cp_parser_objc_selector_p (cp_lexer_peek_token (parser->lexer)->type))
- {
- cp_parser_error (parser, "expected identifier");
- syntax_error = true;
+ if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
+ {
+ warning_at (attr_comb, OPT_Wattributes,
+ "missing property attribute");
+ if (token->type == CPP_CLOSE_PAREN)
break;
- }
- if (keyword == RID_SETTER)
- {
- if (property_setter_ident != NULL_TREE)
- {
- cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
- cp_lexer_consume_token (parser->lexer);
- }
- else
- property_setter_ident = cp_parser_objc_selector (parser);
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
- cp_parser_error (parser, "setter name must terminate with %<:%>");
- else
- cp_lexer_consume_token (parser->lexer);
- }
- else
- {
- if (property_getter_ident != NULL_TREE)
- {
- cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
- cp_lexer_consume_token (parser->lexer);
- }
- else
- property_getter_ident = cp_parser_objc_selector (parser);
- }
- break;
- default:
- cp_parser_error (parser, "unknown property attribute");
- syntax_error = true;
- break;
- }
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
- if (syntax_error)
- break;
+ tree attr_name = NULL_TREE;
+ if (identifier_p (token->u.value))
+ attr_name = token->u.value;
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ enum rid keyword;
+ if (token->type == CPP_NAME)
+ keyword = C_RID_CODE (token->u.value);
+ else if (token->type == CPP_KEYWORD
+ && token->keyword == RID_CLASS)
+ /* Account for accepting the 'class' keyword in this context. */
+ keyword = RID_CLASS;
+ else
+ keyword = RID_MAX; /* By definition, an unknown property. */
cp_lexer_consume_token (parser->lexer);
- else
- break;
- }
- /* FIXME: "@property (setter, assign);" will generate a spurious
- "error: expected ‘)’ before ‘,’ token". This is because
- cp_parser_require, unlike the C counterpart, will produce an
- error even if we are in error recovery. */
- if (!parens.require_close (parser))
- {
- cp_parser_skip_to_closing_parenthesis (parser,
- /*recovering=*/true,
- /*or_comma=*/false,
- /*consume_paren=*/true);
- }
- }
+ enum objc_property_attribute_kind prop_kind
+ = objc_prop_attr_kind_for_rid (keyword);
+ property_attribute_info *prop
+ = new property_attribute_info (attr_name, attr_comb, prop_kind);
+ prop_attr_list.safe_push (prop);
- /* ... and the property declaration(s). */
- properties = cp_parser_objc_struct_declaration (parser);
+ tree meth_name;
+ switch (prop->prop_kind)
+ {
+ default: break;
+ case OBJC_PROPERTY_ATTR_UNKNOWN:
+ if (attr_name)
+ error_at (attr_start, "unknown property attribute %qE",
+ attr_name);
+ else
+ error_at (attr_start, "unknown property attribute");
+ prop->parse_error = syntax_error = true;
+ break;
- if (properties == error_mark_node)
- {
- cp_parser_skip_to_end_of_statement (parser);
- /* If the next token is now a `;', consume it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- cp_lexer_consume_token (parser->lexer);
- return;
+ case OBJC_PROPERTY_ATTR_GETTER:
+ case OBJC_PROPERTY_ATTR_SETTER:
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %<=%> after Objective-C %qE",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+
+ token = cp_lexer_peek_token (parser->lexer);
+ attr_end = token->location;
+ cp_lexer_consume_token (parser->lexer); /* eat the = */
+
+ if (!cp_parser_objc_selector_p
+ (cp_lexer_peek_token (parser->lexer)->type))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %qE selector name",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+
+ /* Get the end of the method name, and consume the name. */
+ token = cp_lexer_peek_token (parser->lexer);
+ attr_end = get_finish (token->location);
+ /* Because method names may contain C++ keywords, we have a
+ routine to fetch them (this also consumes the token). */
+ meth_name = cp_parser_objc_selector (parser);
+
+ if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
+ {
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ {
+ attr_comb = make_location (attr_end, attr_start,
+ attr_end);
+ error_at (attr_comb, "setter method names must"
+ " terminate with %<:%>");
+ prop->parse_error = syntax_error = true;
+ }
+ else
+ {
+ attr_end = get_finish (cp_lexer_peek_token
+ (parser->lexer)->location);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ }
+ else
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ prop->ident = meth_name;
+ /* Updated location including all that was successfully
+ parsed. */
+ prop->prop_loc = attr_comb;
+ break;
+ }
+
+ /* If we see a comma here, then keep going - even if we already
+ saw a syntax error. For simple mistakes e.g. (asign, getter=x)
+ this makes a more useful output and avoid spurious warnings
+ about missing attributes that are, in fact, specified after the
+ one with the syntax error. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+
+ if (syntax_error || !parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
}
- if (properties == NULL_TREE)
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three).
+ TODO: Update this parsing so that it accepts (erroneous) bitfields so
+ that we can issue a meaningful and consistent (between C/C++) error
+ message from objc_add_property_declaration (). */
+ tree properties = cp_parser_objc_struct_declaration (parser);
+
+ if (properties == error_mark_node)
+ cp_parser_skip_to_end_of_statement (parser);
+ else if (properties == NULL_TREE)
cp_parser_error (parser, "expected identifier");
else
{
- /* Comma-separated properties are chained together in
- reverse order; add them one by one. */
+ /* Comma-separated properties are chained together in reverse order;
+ add them one by one. */
properties = nreverse (properties);
-
for (; properties; properties = TREE_CHAIN (properties))
objc_add_property_declaration (loc, copy_node (properties),
- property_readonly, property_readwrite,
- property_assign, property_retain,
- property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident);
+ prop_attr_list);
}
cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+ while (!prop_attr_list.is_empty())
+ delete prop_attr_list.pop ();
+ prop_attr_list.release ();
}
/* Parse an Objective-C++ @synthesize declaration. The syntax is:
@@ -34121,6 +34923,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
case 'a':
if (!strcmp ("aligned", p))
result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ else if (!strcmp ("allocate", p))
+ result = PRAGMA_OMP_CLAUSE_ALLOCATE;
else if (!strcmp ("async", p))
result = PRAGMA_OACC_CLAUSE_ASYNC;
else if (!strcmp ("attach", p))
@@ -34475,7 +35279,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
parser->colon_corrects_to_scope_p = false;
cp_lexer_consume_token (parser->lexer);
if (!cp_lexer_next_token_is (parser->lexer, CPP_COLON))
- low_bound = cp_parser_expression (parser);
+ {
+ low_bound = cp_parser_expression (parser);
+ /* Later handling is not prepared to see through these. */
+ gcc_checking_assert (!location_wrapper_p (low_bound));
+ }
if (!colon)
parser->colon_corrects_to_scope_p
= saved_colon_corrects_to_scope_p;
@@ -34495,7 +35303,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
cp_parser_commit_to_tentative_parse (parser);
if (!cp_lexer_next_token_is (parser->lexer,
CPP_CLOSE_SQUARE))
- length = cp_parser_expression (parser);
+ {
+ length = cp_parser_expression (parser);
+ /* Later handling is not prepared to see through these. */
+ gcc_checking_assert (!location_wrapper_p (length));
+ }
}
/* Look for the closing `]'. */
if (!cp_parser_require (parser, CPP_CLOSE_SQUARE,
@@ -36276,6 +37088,47 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
return nlist;
}
+/* OpenMP 5.0:
+ allocate ( variable-list )
+ allocate ( expression : variable-list ) */
+
+static tree
+cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
+{
+ tree nlist, c, allocator = NULL_TREE;
+ bool colon;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ cp_parser_parse_tentatively (parser);
+ bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+ parser->colon_corrects_to_scope_p = false;
+ allocator = cp_parser_assignment_expression (parser);
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_parser_parse_definitely (parser);
+ cp_lexer_consume_token (parser->lexer);
+ if (allocator == error_mark_node)
+ allocator = NULL_TREE;
+ }
+ else
+ {
+ cp_parser_abort_tentative_parse (parser);
+ allocator = NULL_TREE;
+ }
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALLOCATE, list,
+ &colon);
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ return nlist;
+}
+
/* OpenMP 2.5:
lastprivate ( variable-list )
@@ -37118,6 +37971,9 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
tree clauses = NULL;
bool first = true;
+ /* Don't create location wrapper nodes within OpenACC clauses. */
+ auto_suppress_location_wrappers sentinel;
+
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
{
location_t here;
@@ -37593,6 +38449,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses = cp_parser_omp_clause_aligned (parser, clauses);
c_name = "aligned";
break;
+ case PRAGMA_OMP_CLAUSE_ALLOCATE:
+ clauses = cp_parser_omp_clause_allocate (parser, clauses);
+ c_name = "allocate";
+ break;
case PRAGMA_OMP_CLAUSE_LINEAR:
{
bool declare_simd = false;
@@ -37731,6 +38591,42 @@ cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
return finish_omp_structured_block (stmt);
}
+/* OpenMP 5.0:
+ # pragma omp allocate (list) [allocator(allocator)] */
+
+static void
+cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree allocator = NULL_TREE;
+ location_t loc = pragma_tok->location;
+ tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ matching_parens parens;
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
+ cp_lexer_consume_token (parser->lexer);
+ if (strcmp (p, "allocator") != 0)
+ error_at (cloc, "expected %<allocator%>");
+ else if (parens.require_open (parser))
+ {
+ allocator = cp_parser_assignment_expression (parser);
+ if (allocator == error_mark_node)
+ allocator = NULL_TREE;
+ parens.require_close (parser);
+ }
+ }
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+
+ if (allocator)
+ for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ sorry_at (loc, "%<#pragma omp allocate%> not yet supported");
+}
+
/* OpenMP 2.5:
# pragma omp atomic new-line
expression-stmt
@@ -37783,7 +38679,7 @@ cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
where x and v are lvalue expressions with scalar type. */
static void
-cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
tree rhs1 = NULL_TREE, orig_lhs;
@@ -37818,6 +38714,12 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
new_code = OMP_ATOMIC;
else if (!strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
+ else if (openacc)
+ {
+ p = NULL;
+ error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+ "or %<capture%> clause");
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -37845,7 +38747,12 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
{
if (new_code != ERROR_MARK)
{
- if (code != ERROR_MARK)
+ /* OpenACC permits 'update capture'. */
+ if (openacc
+ && code == OMP_ATOMIC
+ && new_code == OMP_ATOMIC_CAPTURE_NEW)
+ code = new_code;
+ else if (code != ERROR_MARK)
error_at (cloc, "too many atomic clauses");
else
code = new_code;
@@ -37867,7 +38774,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
- if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+ if (openacc)
+ memory_order = OMP_MEMORY_ORDER_RELAXED;
+ else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
{
omp_requires_mask
= (enum omp_requires) (omp_requires_mask
@@ -38353,6 +39262,8 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
cp_lexer_consume_token (parser->lexer);
if (!strcmp ("depend", p))
{
+ /* Don't create location wrapper nodes within the depend clause. */
+ auto_suppress_location_wrappers sentinel;
clause = cp_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
if (clause)
clause = finish_omp_clauses (clause, C_ORT_OMP);
@@ -39612,6 +40523,7 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
static tree
@@ -39896,6 +40808,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -39946,6 +40859,7 @@ cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
@@ -40006,6 +40920,9 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
cclauses = cclauses_buf;
cp_lexer_consume_token (parser->lexer);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_master (parser, pragma_tok, p_name, mask,
+ cclauses, if_p);
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask,
@@ -40091,6 +41008,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -40123,6 +41041,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
static tree
@@ -40187,7 +41106,8 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
# pragma omp taskgroup taskgroup-clause[optseq] new-line */
#define OMP_TASKGROUP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
static tree
cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
@@ -40296,6 +41216,7 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
@@ -40394,6 +41315,7 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
static tree
@@ -40510,6 +41432,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
"#pragma omp target data", pragma_tok);
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -40528,6 +41451,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -40611,6 +41535,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok,
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
"#pragma omp target enter data", pragma_tok);
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -40625,6 +41550,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok,
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -40699,6 +41625,7 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok,
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
"#pragma omp target exit data", pragma_tok);
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -40714,6 +41641,7 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok,
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -40800,6 +41728,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
static bool
@@ -40962,6 +41891,8 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
OMP_TARGET_CLAUSES (stmt)
= cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
"#pragma omp target", pragma_tok);
+ c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level (true);
OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
@@ -40985,6 +41916,7 @@ check_clauses:
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
error_at (OMP_CLAUSE_LOCATION (*pc),
@@ -41006,6 +41938,10 @@ check_clauses:
static tree
cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok)
{
+ /* Don't create location wrapper nodes within 'OMP_CLAUSE__CACHE_'
+ clauses. */
+ auto_suppress_location_wrappers sentinel;
+
tree stmt, clauses;
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE__CACHE_, NULL_TREE);
@@ -41606,7 +42542,7 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
switch (context)
{
case pragma_external:
- cp_parser_declaration (parser);
+ cp_parser_declaration (parser, NULL_TREE);
break;
case pragma_member:
cp_parser_member_declaration (parser);
@@ -42638,15 +43574,19 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("gnu_inline"), NULL_TREE,
DECL_ATTRIBUTES (fndecl));
- if (processing_template_decl)
- fndecl = push_template_decl (fndecl);
bool block_scope = false;
- tree block = NULL_TREE;
if (current_function_decl)
{
block_scope = true;
DECL_CONTEXT (fndecl) = current_function_decl;
DECL_LOCAL_DECL_P (fndecl) = true;
+ }
+
+ if (processing_template_decl)
+ fndecl = push_template_decl (fndecl);
+
+ if (block_scope)
+ {
if (!processing_template_decl)
pushdecl (fndecl);
}
@@ -42674,6 +43614,8 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
/* We should never meet a matched duplicate decl. */
gcc_checking_assert (d == error_mark_node || d == fndecl);
}
+
+ tree block = NULL_TREE;
if (!block_scope)
start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
else
@@ -42949,6 +43891,7 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
@@ -43156,7 +44099,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
}
/* We only have to consider the pragma_external case here. */
- cp_parser_declaration (parser);
+ cp_parser_declaration (parser, NULL_TREE);
if (parser->oacc_routine
&& !parser->oacc_routine->fndecl_seen)
cp_ensure_no_oacc_routine (parser);
@@ -43290,7 +44233,7 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
switch (cp_parser_pragma_kind (pragma_tok))
{
case PRAGMA_OACC_ATOMIC:
- cp_parser_omp_atomic (parser, pragma_tok);
+ cp_parser_omp_atomic (parser, pragma_tok, true);
return;
case PRAGMA_OACC_CACHE:
stmt = cp_parser_oacc_cache (parser, pragma_tok);
@@ -43324,8 +44267,11 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
case PRAGMA_OACC_WAIT:
stmt = cp_parser_oacc_wait (parser, pragma_tok);
break;
+ case PRAGMA_OMP_ALLOCATE:
+ cp_parser_omp_allocate (parser, pragma_tok);
+ return;
case PRAGMA_OMP_ATOMIC:
- cp_parser_omp_atomic (parser, pragma_tok);
+ cp_parser_omp_atomic (parser, pragma_tok, false);
return;
case PRAGMA_OMP_CRITICAL:
stmt = cp_parser_omp_critical (parser, pragma_tok, if_p);
@@ -43969,7 +44915,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
goto bad_stmt;
cp_parser_omp_construct (parser, pragma_tok, if_p);
return true;
-
+ case PRAGMA_OMP_ALLOCATE:
+ cp_parser_omp_allocate (parser, pragma_tok);
+ return false;
case PRAGMA_OACC_ATOMIC:
case PRAGMA_OACC_CACHE:
case PRAGMA_OACC_DATA:
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index ec487ea..13c37b2 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -58,7 +58,8 @@ struct GTY (()) cp_token {
deleted. */
bool purged_p : 1;
bool tree_check_p : 1;
- /* 4 unused bits. */
+ bool main_source_p : 1;
+ /* 3 unused bits. */
/* The location at which this token was found. */
location_t location;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index dc664ec..ce2e879 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22,7 +22,9 @@ along with GCC; see the file COPYING3. If not see
/* Known bugs or deficiencies include:
all methods must be provided in header files; can't use a source
- file that contains only the method templates and "just win". */
+ file that contains only the method templates and "just win".
+
+ Fixed by: C++20 modules. */
#include "config.h"
#include "system.h"
@@ -103,13 +105,6 @@ local_specialization_stack::~local_specialization_stack ()
/* True if we've recursed into fn_type_unification too many times. */
static bool excessive_deduction_depth;
-struct GTY((for_user)) spec_entry
-{
- tree tmpl;
- tree args;
- tree spec;
-};
-
struct spec_hasher : ggc_ptr_hash<spec_entry>
{
static hashval_t hash (spec_entry *);
@@ -965,6 +960,9 @@ maybe_new_partial_specialization (tree type)
TREE_PRIVATE (d) = (current_access_specifier == access_private_node);
TREE_PROTECTED (d) = (current_access_specifier == access_protected_node);
+ set_instantiating_module (d);
+ DECL_MODULE_EXPORT_P (d) = DECL_MODULE_EXPORT_P (tmpl);
+
return t;
}
@@ -1709,10 +1707,11 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
return spec;
}
-/* Returns true iff two spec_entry nodes are equivalent. */
-
+/* Restricts tree and type comparisons. */
int comparing_specializations;
+/* Returns true iff two spec_entry nodes are equivalent. */
+
bool
spec_hasher::equal (spec_entry *e1, spec_entry *e2)
{
@@ -3634,7 +3633,7 @@ primary_template_specialization_p (const_tree t)
if (!t)
return false;
- if (TREE_CODE (t) == FUNCTION_DECL || VAR_P (t))
+ if (VAR_OR_FUNCTION_DECL_P (t))
return (DECL_LANG_SPECIFIC (t)
&& DECL_USE_TEMPLATE (t)
&& DECL_TEMPLATE_INFO (t)
@@ -3767,7 +3766,7 @@ builtin_pack_fn_p (tree fn)
{
if (!fn
|| TREE_CODE (fn) != FUNCTION_DECL
- || !DECL_IS_BUILTIN (fn))
+ || !DECL_IS_UNDECLARED_BUILTIN (fn))
return false;
if (id_equal (DECL_NAME (fn), "__integer_pack"))
@@ -4435,7 +4434,7 @@ build_template_parm_index (int index,
parameter. Returns the canonical type parameter, which may be TYPE
if no such parameter existed. */
-static tree
+tree
canonical_type_parameter (tree type)
{
int idx = TEMPLATE_TYPE_IDX (type);
@@ -4926,6 +4925,17 @@ build_template_decl (tree decl, tree parms, bool member_template_p)
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
+ if (modules_p ())
+ {
+ /* Propagate module information from the decl. */
+ DECL_MODULE_EXPORT_P (tmpl) = DECL_MODULE_EXPORT_P (decl);
+ if (DECL_LANG_SPECIFIC (decl))
+ {
+ DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (decl);
+ gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl));
+ }
+ }
+
return tmpl;
}
@@ -5089,8 +5099,7 @@ process_partial_specialization (tree decl)
= TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (maintmpl)));
if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args))
&& (!flag_concepts
- || !strictly_subsumes (current_template_constraints (),
- main_args, maintmpl)))
+ || !strictly_subsumes (current_template_constraints (), maintmpl)))
{
if (!flag_concepts)
error ("partial specialization %q+D does not specialize "
@@ -5682,34 +5691,24 @@ template_parm_outer_level (tree t, void *data)
tree
push_template_decl (tree decl, bool is_friend)
{
- tree tmpl;
- tree args;
- tree info;
- tree ctx;
- bool is_primary;
- bool is_partial;
- int new_template_p = 0;
- /* True if the template is a member template, in the sense of
- [temp.mem]. */
- bool member_template_p = false;
-
if (decl == error_mark_node || !current_template_parms)
return error_mark_node;
/* See if this is a partial specialization. */
- is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
- && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- || (VAR_P (decl)
- && DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_SPECIALIZATION (decl)
- && TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
+ bool is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ || (VAR_P (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl)
+ && TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
/* No surprising friend functions. */
gcc_checking_assert (is_friend
|| !(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_UNIQUE_FRIEND_P (decl)));
+ tree ctx;
if (is_friend)
/* For a friend, we want the context of the friend, not
the type of which it is a friend. */
@@ -5731,23 +5730,30 @@ push_template_decl (tree decl, bool is_friend)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* See if this is a primary template. */
+ bool is_primary = false;
if (is_friend && ctx
&& uses_template_parms_level (ctx, processing_template_decl))
/* A friend template that specifies a class context, i.e.
template <typename T> friend void A<T>::f();
is not primary. */
- is_primary = false;
+ ;
else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
- is_primary = false;
+ /* Lambdas are not primary. */
+ ;
else
is_primary = template_parm_scope_p ();
+ /* True if the template is a member template, in the sense of
+ [temp.mem]. */
+ bool member_template_p = false;
+
if (is_primary)
{
warning (OPT_Wtemplates, "template %qD declared", decl);
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
+
if (TREE_CODE (decl) == TYPE_DECL
&& IDENTIFIER_ANON_P (DECL_NAME (decl)))
{
@@ -5815,11 +5821,16 @@ push_template_decl (tree decl, bool is_friend)
}
}
+ bool local_p = (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && ((ctx && TREE_CODE (ctx) == FUNCTION_DECL)
+ || (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_LOCAL_DECL_P (decl))));
+
/* Check to see that the rules regarding the use of default
arguments are not being violated. We check args for a friend
functions when we know whether it's a definition, introducing
declaration or re-declaration. */
- if (!is_friend || TREE_CODE (decl) != FUNCTION_DECL)
+ if (!local_p && (!is_friend || TREE_CODE (decl) != FUNCTION_DECL))
check_default_tmpl_args (decl, current_template_parms,
is_primary, is_partial, is_friend);
@@ -5871,14 +5882,21 @@ push_template_decl (tree decl, bool is_friend)
if (is_partial)
return process_partial_specialization (decl);
- args = current_template_args ();
-
- if (!ctx
- || TREE_CODE (ctx) == FUNCTION_DECL
- || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
- || (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
- || (is_friend && !(DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_INFO (decl))))
+ tree args = current_template_args ();
+ tree tmpl = NULL_TREE;
+ bool new_template_p = false;
+ if (local_p)
+ {
+ /* Does not get a template head. */
+ tmpl = NULL_TREE;
+ gcc_checking_assert (!is_primary);
+ }
+ else if (!ctx
+ || TREE_CODE (ctx) == FUNCTION_DECL
+ || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
+ || (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+ || (is_friend && !(DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl))))
{
if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_INFO (decl)
@@ -5905,7 +5923,7 @@ push_template_decl (tree decl, bool is_friend)
{
tmpl = build_template_decl (decl, current_template_parms,
member_template_p);
- new_template_p = 1;
+ new_template_p = true;
if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl))
@@ -5937,8 +5955,6 @@ push_template_decl (tree decl, bool is_friend)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& DECL_MEMBER_TEMPLATE_P (tmpl))
{
- tree new_tmpl;
-
/* The declaration is a specialization of a member
template, declared outside the class. Therefore, the
innermost template arguments will be NULL, so we
@@ -5946,7 +5962,7 @@ push_template_decl (tree decl, bool is_friend)
earlier call to check_explicit_specialization. */
args = DECL_TI_ARGS (decl);
- new_tmpl
+ tree new_tmpl
= build_template_decl (decl, current_template_parms,
member_template_p);
DECL_TI_TEMPLATE (decl) = new_tmpl;
@@ -6018,7 +6034,7 @@ push_template_decl (tree decl, bool is_friend)
}
}
- gcc_checking_assert (DECL_TEMPLATE_RESULT (tmpl) == decl);
+ gcc_checking_assert (!tmpl || DECL_TEMPLATE_RESULT (tmpl) == decl);
if (new_template_p)
{
@@ -6030,65 +6046,79 @@ push_template_decl (tree decl, bool is_friend)
if (!ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
{
- tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
- if (tmpl == error_mark_node)
+ tree pushed = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
+ if (pushed == error_mark_node)
return error_mark_node;
+
+ /* pushdecl may have found an existing template. */
+ if (pushed != tmpl)
+ {
+ decl = DECL_TEMPLATE_RESULT (pushed);
+ tmpl = NULL_TREE;
+ }
+ }
+ else if (is_friend)
+ {
+ /* Record this decl as belonging to the current class. It's
+ not chained onto anything else. */
+ DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (tmpl) = true;
+ gcc_checking_assert (!DECL_CHAIN (tmpl));
+ DECL_CHAIN (tmpl) = current_scope ();
}
}
- else
+ else if (tmpl)
/* The type may have been completed, or (erroneously) changed. */
TREE_TYPE (tmpl) = TREE_TYPE (decl);
- if (is_primary)
+ if (tmpl)
{
- tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ if (is_primary)
+ {
+ tree parms = DECL_TEMPLATE_PARMS (tmpl);
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
- /* Give template template parms a DECL_CONTEXT of the template
- for which they are a parameter. */
- parms = INNERMOST_TEMPLATE_PARMS (parms);
- for (int i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- if (TREE_CODE (parm) == TEMPLATE_DECL)
- DECL_CONTEXT (parm) = tmpl;
- }
+ /* Give template template parms a DECL_CONTEXT of the template
+ for which they are a parameter. */
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+ for (int i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ if (TREE_CODE (parm) == TEMPLATE_DECL)
+ DECL_CONTEXT (parm) = tmpl;
+ }
- if (TREE_CODE (decl) == TYPE_DECL
- && TYPE_DECL_ALIAS_P (decl))
- {
- if (tree constr
- = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (decl))
{
- /* ??? Why don't we do this here for all templates? */
- constr = build_constraints (constr, NULL_TREE);
- set_constraints (decl, constr);
+ if (tree constr
+ = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+ {
+ /* ??? Why don't we do this here for all templates? */
+ constr = build_constraints (constr, NULL_TREE);
+ set_constraints (decl, constr);
+ }
+ if (complex_alias_template_p (tmpl))
+ TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
}
- if (complex_alias_template_p (tmpl))
- TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
}
- }
- /* The DECL_TI_ARGS of DECL contains full set of arguments referring
- back to its most general template. If TMPL is a specialization,
- ARGS may only have the innermost set of arguments. Add the missing
- argument levels if necessary. */
- if (DECL_TEMPLATE_INFO (tmpl))
- args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
+ /* The DECL_TI_ARGS of DECL contains full set of arguments
+ referring wback to its most general template. If TMPL is a
+ specialization, ARGS may only have the innermost set of
+ arguments. Add the missing argument levels if necessary. */
+ if (DECL_TEMPLATE_INFO (tmpl))
+ args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
- info = build_template_info (tmpl, args);
+ tree info = build_template_info (tmpl, args);
- if (DECL_IMPLICIT_TYPEDEF_P (decl))
- SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
- else
- {
- if (is_primary)
- retrofit_lang_decl (decl);
- if (DECL_LANG_SPECIFIC (decl)
- && !(VAR_OR_FUNCTION_DECL_P (decl)
- && DECL_LOCAL_DECL_P (decl)))
- DECL_TEMPLATE_INFO (decl) = info;
+ if (DECL_IMPLICIT_TYPEDEF_P (decl))
+ SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
+ else
+ {
+ retrofit_lang_decl (decl);
+ DECL_TEMPLATE_INFO (decl) = info;
+ }
}
if (flag_implicit_templates
@@ -6100,7 +6130,9 @@ push_template_decl (tree decl, bool is_friend)
mark_needed will tell cgraph to do the right thing. */
DECL_COMDAT (decl) = true;
- return DECL_TEMPLATE_RESULT (tmpl);
+ gcc_checking_assert (!tmpl || DECL_TEMPLATE_RESULT (tmpl) == decl);
+
+ return decl;
}
/* FN is an inheriting constructor that inherits from the constructor
@@ -8163,7 +8195,7 @@ is_compatible_template_arg (tree parm, tree arg)
return false;
}
- return weakly_subsumes (parm_cons, new_args, arg);
+ return weakly_subsumes (parm_cons, arg);
}
// Convert a placeholder argument into a binding to the original
@@ -8249,7 +8281,7 @@ convert_template_argument (tree parm,
/* When determining whether an argument pack expansion is a template,
look at the pattern. */
- if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
+ if (PACK_EXPANSION_P (arg))
arg = PACK_EXPANSION_PATTERN (arg);
/* Deal with an injected-class-name used as a template template arg. */
@@ -9756,6 +9788,15 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
return error_mark_node;
gen_tmpl = most_general_template (templ);
+ if (modules_p ())
+ {
+ tree origin = get_originating_module_decl (gen_tmpl);
+ load_pending_specializations (CP_DECL_CONTEXT (origin),
+ DECL_NAME (origin));
+ if (DECL_MODULE_PENDING_SPECIALIZATIONS_P (gen_tmpl))
+ lazy_load_specializations (gen_tmpl);
+ }
+
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
@@ -9976,6 +10017,12 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
= DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
}
+ set_instantiating_module (type_decl);
+ /* Although GEN_TMPL is the TEMPLATE_DECL, it has the same value
+ of export flag. We want to propagate this because it might
+ be a friend declaration that pushes a new hidden binding. */
+ DECL_MODULE_EXPORT_P (type_decl) = DECL_MODULE_EXPORT_P (gen_tmpl);
+
if (CLASS_TYPE_P (template_type))
{
TREE_PRIVATE (type_decl)
@@ -10603,6 +10650,16 @@ keep_template_parm (tree t, void* data)
if (!ftpi->parms.add (t))
ftpi->parm_list = tree_cons (NULL_TREE, t, ftpi->parm_list);
+ /* Verify the parameter we found has a valid index. */
+ if (flag_checking)
+ {
+ tree parms = ftpi->ctx_parms;
+ while (TMPL_PARMS_DEPTH (parms) > level)
+ parms = TREE_CHAIN (parms);
+ if (int len = TREE_VEC_LENGTH (TREE_VALUE (parms)))
+ gcc_assert (index < len);
+ }
+
return 0;
}
@@ -10741,21 +10798,23 @@ uses_template_parms (tree t)
else if (t == error_mark_node)
dependent_p = false;
else
- dependent_p = value_dependent_expression_p (t);
+ dependent_p = instantiation_dependent_expression_p (t);
processing_template_decl = saved_processing_template_decl;
return dependent_p;
}
-/* Returns true iff current_function_decl is an incompletely instantiated
+/* Returns true iff we're processing an incompletely instantiated function
template. Useful instead of processing_template_decl because the latter
is set to 0 during instantiate_non_dependent_expr. */
bool
in_template_function (void)
{
- tree fn = current_function_decl;
+ /* Inspect the less volatile cfun->decl instead of current_function_decl;
+ the latter might get set for e.g. access checking during satisfaction. */
+ tree fn = cfun ? cfun->decl : NULL_TREE;
bool ret;
++processing_template_decl;
ret = (fn && DECL_LANG_SPECIFIC (fn)
@@ -10882,6 +10941,7 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
new_level->errors = errorcount + sorrycount;
new_level->next = NULL;
new_level->refcount = 0;
+ new_level->path = new_level->visible = nullptr;
set_refcount_ptr (new_level->next, current_tinst_level);
set_refcount_ptr (current_tinst_level, new_level);
@@ -11032,6 +11092,7 @@ tsubst_friend_function (tree decl, tree args)
DECL_USE_TEMPLATE (new_friend) = 0;
if (TREE_CODE (new_friend) == TEMPLATE_DECL)
{
+ DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (new_friend) = false;
DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
= DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
@@ -11851,7 +11912,6 @@ instantiate_class_template_1 (tree type)
Ignore it; it will be regenerated when needed. */
continue;
- /* Build new CLASSTYPE_NESTED_UTDS. */
bool class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
&& TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_IS_TEMPLATE (t));
@@ -12009,10 +12069,10 @@ instantiate_class_template_1 (tree type)
TREE_TYPE (r) = error_mark_node;
}
- /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
- such a thing will already have been added to the field
- list by tsubst_enum in finish_member_declaration in the
- CLASSTYPE_NESTED_UTDS case above. */
+ /* If it is a TYPE_DECL for a class-scoped
+ ENUMERAL_TYPE, such a thing will already have
+ been added to the field list by tsubst_enum
+ in finish_member_declaration case above. */
if (!(TREE_CODE (r) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
&& DECL_ARTIFICIAL (r)))
@@ -13192,19 +13252,24 @@ tsubst_argument_pack (tree orig_arg, tree args, tsubst_flags_t complain,
tree in_decl)
{
/* Substitute into each of the arguments. */
- tree new_arg = TYPE_P (orig_arg)
- ? cxx_make_type (TREE_CODE (orig_arg))
- : make_node (TREE_CODE (orig_arg));
-
tree pack_args = tsubst_template_args (ARGUMENT_PACK_ARGS (orig_arg),
args, complain, in_decl);
- if (pack_args == error_mark_node)
- new_arg = error_mark_node;
- else
- SET_ARGUMENT_PACK_ARGS (new_arg, pack_args);
+ tree new_arg = error_mark_node;
+ if (pack_args != error_mark_node)
+ {
+ if (TYPE_P (orig_arg))
+ {
+ new_arg = cxx_make_type (TREE_CODE (orig_arg));
+ SET_TYPE_STRUCTURAL_EQUALITY (new_arg);
+ }
+ else
+ {
+ new_arg = make_node (TREE_CODE (orig_arg));
+ TREE_CONSTANT (new_arg) = TREE_CONSTANT (orig_arg);
+ }
- if (TREE_CODE (new_arg) == NONTYPE_ARGUMENT_PACK)
- TREE_CONSTANT (new_arg) = TREE_CONSTANT (orig_arg);
+ SET_ARGUMENT_PACK_ARGS (new_arg, pack_args);
+ }
return new_arg;
}
@@ -13878,6 +13943,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
if (!DECL_DELETED_FN (r))
DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
+ set_instantiating_module (r);
/* Handle explicit(dependent-expr). */
if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
@@ -14201,14 +14267,31 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
TREE_TYPE (r) = TREE_TYPE (inner);
DECL_CONTEXT (r) = DECL_CONTEXT (inner);
+ if (modules_p ())
+ {
+ /* Propagate module information from the decl. */
+ DECL_MODULE_EXPORT_P (r) = DECL_MODULE_EXPORT_P (inner);
+ if (DECL_LANG_SPECIFIC (inner))
+ {
+ DECL_MODULE_PURVIEW_P (r) = DECL_MODULE_PURVIEW_P (inner);
+ /* If this is a constrained template, the above tsubst of
+ inner can find the unconstrained template, which may have
+ come from an import. This is ok, because we don't
+ register this instantiation (see below). */
+ gcc_checking_assert (!DECL_MODULE_IMPORT_P (inner)
+ || (TEMPLATE_PARMS_CONSTRAINTS
+ (DECL_TEMPLATE_PARMS (t))));
+ DECL_MODULE_IMPORT_P (r) = false;
+ }
+ }
+
DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (r) = r;
- if (TREE_CODE (decl) != TYPE_DECL && !VAR_P (decl)
- && !lambda_fntype)
+ if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype)
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
@@ -14756,6 +14839,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
SET_DECL_RTL (r, NULL);
+ set_instantiating_module (r);
+
/* The initializer must not be expanded until it is required;
see [temp.inst]. */
DECL_INITIAL (r) = NULL_TREE;
@@ -14910,9 +14995,6 @@ tsubst_arg_types (tree arg_types,
}
return error_mark_node;
}
- /* DR 657. */
- if (abstract_virtuals_error_sfinae (ACU_PARM, type, complain))
- return error_mark_node;
/* Do array-to-pointer, function-to-pointer conversion, and ignore
top-level qualifiers as required. */
@@ -15030,9 +15112,6 @@ tsubst_function_type (tree t,
}
return error_mark_node;
}
- /* And DR 657. */
- if (abstract_virtuals_error_sfinae (ACU_RETURN, return_type, complain))
- return error_mark_node;
if (!late_return_type_p)
{
@@ -15367,6 +15446,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case ERROR_MARK:
case IDENTIFIER_NODE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
@@ -15858,7 +15938,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
}
- if (abstract_virtuals_error_sfinae (ACU_ARRAY, type, complain))
+ if (!verify_type_context (input_location, TCTX_ARRAY_ELEMENT, type,
+ !(complain & tf_error)))
return error_mark_node;
r = build_cplus_array_type (type, domain);
@@ -15921,13 +16002,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
it's a partial instantiation. */
- ctx = complete_type (ctx);
- if (!COMPLETE_TYPE_P (ctx))
- {
- if (complain & tf_error)
- cxx_incomplete_type_error (NULL_TREE, ctx);
- return error_mark_node;
- }
+ if (!complete_type_or_maybe_complain (ctx, NULL_TREE, complain))
+ return error_mark_node;
}
f = make_typename_type (ctx, f, typename_type,
@@ -16048,20 +16124,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
- {
- tree r;
-
- if (code == NONTYPE_ARGUMENT_PACK)
- r = make_node (code);
- else
- r = cxx_make_type (code);
-
- tree pack_args = ARGUMENT_PACK_ARGS (t);
- pack_args = tsubst_template_args (pack_args, args, complain, in_decl);
- SET_ARGUMENT_PACK_ARGS (r, pack_args);
-
- return r;
- }
+ return tsubst_argument_pack (t, args, complain, in_decl);
case VOID_CST:
case INTEGER_CST:
@@ -16205,7 +16268,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
tree name;
bool is_template;
tree template_args;
- location_t loc = UNKNOWN_LOCATION;
+ location_t loc = EXPR_LOCATION (qualified_id);
gcc_assert (TREE_CODE (qualified_id) == SCOPE_REF);
@@ -16214,7 +16277,6 @@ tsubst_qualified_id (tree qualified_id, tree args,
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
is_template = true;
- loc = EXPR_LOCATION (name);
template_args = TREE_OPERAND (name, 1);
if (template_args)
template_args = tsubst_template_args (template_args, args,
@@ -16342,6 +16404,8 @@ tsubst_qualified_id (tree qualified_id, tree args,
if (REF_PARENTHESIZED_P (qualified_id))
expr = force_paren_expr (expr);
+ expr = maybe_wrap_with_location (expr, loc);
+
return expr;
}
@@ -16728,6 +16792,13 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return build1 (code, type, op0);
}
+ case BIT_CAST_EXPR:
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ return cp_build_bit_cast (EXPR_LOCATION (t), type, op0, complain);
+ }
+
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
@@ -16780,6 +16851,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
return cxx_sizeof_or_alignof_expr (input_location,
expanded, SIZEOF_EXPR,
+ false,
complain & tf_error);
}
else
@@ -17245,6 +17317,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE__CACHE_:
case OMP_CLAUSE_NONTEMPORAL:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_USE_DEVICE_ADDR:
@@ -17307,6 +17380,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
break;
case OMP_CLAUSE_GANG:
case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_ALLOCATE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
in_decl, NULL);
@@ -17376,6 +17450,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_IS_DEVICE_PTR:
case OMP_CLAUSE_INCLUSIVE:
case OMP_CLAUSE_EXCLUSIVE:
+ case OMP_CLAUSE_ALLOCATE:
/* tsubst_expr on SCOPE_REF results in returning
finish_non_static_data_member result. Undo that here. */
if (TREE_CODE (OMP_CLAUSE_DECL (oc)) == SCOPE_REF
@@ -18044,11 +18119,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
{
+ /* We cannot have a member-using decl here (until 'using
+ enum T' is a thing). */
+ gcc_checking_assert (!DECL_DEPENDENT_P (decl));
+
+ /* This must be a non-dependent using-decl, and we'll have
+ used the names it found during template parsing. We do
+ not want to do the lookup again, because we might not
+ find the things we found then. (Again, using enum T
+ might mean we have to do things here.) */
tree scope = USING_DECL_SCOPE (decl);
- tree name = DECL_NAME (decl);
-
- scope = tsubst (scope, args, complain, in_decl);
- finish_nonmember_using_decl (scope, name);
+ gcc_checking_assert (scope
+ == tsubst (scope, args, complain, in_decl));
}
else if (is_capture_proxy (decl)
&& !DECL_TEMPLATE_INSTANTIATION (current_function_decl))
@@ -18474,8 +18556,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
tree condition;
++c_inhibit_evaluation_warnings;
- condition =
- tsubst_expr (STATIC_ASSERT_CONDITION (t),
+ condition =
+ tsubst_expr (STATIC_ASSERT_CONDITION (t),
args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
@@ -18484,7 +18566,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
finish_static_assert (condition,
STATIC_ASSERT_MESSAGE (t),
STATIC_ASSERT_SOURCE_LOCATION (t),
- /*member_p=*/false);
+ /*member_p=*/false, /*show_expr_p=*/true);
}
break;
@@ -18752,6 +18834,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
add_stmt (t);
break;
+ case OACC_CACHE:
case OACC_ENTER_DATA:
case OACC_EXIT_DATA:
case OACC_UPDATE:
@@ -19066,15 +19149,6 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
LAMBDA_EXPR_INSTANTIATED (r) = true;
- if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
- /* A lambda in a default argument outside a class gets no
- LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
- tsubst_default_argument calls start_lambda_scope, so we need to
- specifically ignore it here, and use the global scope. */
- record_null_lambda_scope (r);
- else
- record_lambda_scope (r);
-
gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
&& LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
@@ -19153,6 +19227,15 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (type == error_mark_node)
return error_mark_node;
+ if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
+ /* A lambda in a default argument outside a class gets no
+ LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
+ tsubst_default_argument calls start_lambda_scope, so we need to
+ specifically ignore it here, and use the global scope. */
+ record_null_lambda_scope (r);
+ else
+ record_lambda_scope (r);
+
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
@@ -19618,8 +19701,11 @@ tsubst_copy_and_build (tree t,
{
/* If T was type-dependent, suppress warnings that depend on the range
of the types involved. */
- bool was_dep = type_dependent_expression_p_push (t);
-
+ ++processing_template_decl;
+ const bool was_dep = (potential_constant_expression (t)
+ ? value_dependent_expression_p (t)
+ : type_dependent_expression_p (t));
+ --processing_template_decl;
tree op0 = RECUR (TREE_OPERAND (t, 0));
tree op1 = RECUR (TREE_OPERAND (t, 1));
@@ -19710,7 +19796,7 @@ tsubst_copy_and_build (tree t,
complain & tf_error);
else
r = cxx_sizeof_or_alignof_expr (input_location,
- op1, TREE_CODE (t),
+ op1, TREE_CODE (t), std_alignof,
complain & tf_error);
if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
{
@@ -19815,6 +19901,8 @@ tsubst_copy_and_build (tree t,
parameter packs are of length zero. */
if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE)
init_vec = NULL;
+ else if (init == error_mark_node)
+ RETURN (error_mark_node);
else
{
init_vec = make_tree_vector ();
@@ -20825,6 +20913,15 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
(DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl)),
targ_ptr));
+ if (modules_p ())
+ {
+ tree origin = get_originating_module_decl (gen_tmpl);
+ load_pending_specializations (CP_DECL_CONTEXT (origin),
+ DECL_NAME (origin));
+ if (DECL_MODULE_PENDING_SPECIALIZATIONS_P (gen_tmpl))
+ lazy_load_specializations (gen_tmpl);
+ }
+
/* It would be nice to avoid hashing here and then again in tsubst_decl,
but it doesn't seem to be on the hot path. */
spec = retrieve_specialization (gen_tmpl, targ_ptr, 0);
@@ -20910,6 +21007,8 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
DECL_TI_TEMPLATE (fndecl) = tmpl;
DECL_TI_ARGS (fndecl) = targ_ptr;
+ set_instantiating_module (fndecl);
+
/* Now we know the specialization, compute access previously
deferred. Do no access control for inheriting constructors,
as we already checked access for the inherited constructor. */
@@ -22675,8 +22774,20 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg,
applies. */
if (rval && !same_type_p (r, rval))
{
- *result = NULL_TREE;
- return tbr_ambiguous_baseclass;
+ /* [temp.deduct.call]/4.3: If there is a class C that is a
+ (direct or indirect) base class of D and derived (directly or
+ indirectly) from a class B and that would be a valid deduced
+ A, the deduced A cannot be B or pointer to B, respectively. */
+ if (DERIVED_FROM_P (r, rval))
+ /* Ignore r. */
+ continue;
+ else if (DERIVED_FROM_P (rval, r))
+ /* Ignore rval. */;
+ else
+ {
+ *result = NULL_TREE;
+ return tbr_ambiguous_baseclass;
+ }
}
rval = r;
@@ -23569,6 +23680,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
case VOID_TYPE:
+ case OPAQUE_TYPE:
case NULLPTR_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return unify_type_mismatch (explain_p, parm, arg);
@@ -24959,19 +25071,6 @@ mark_class_instantiated (tree t, int extern_p)
}
}
-/* Called from do_type_instantiation through binding_table_foreach to
- do recursive instantiation for the type bound in ENTRY. */
-static void
-bt_instantiate_type_proc (binding_entry entry, void *data)
-{
- tree storage = *(tree *) data;
-
- if (MAYBE_CLASS_TYPE_P (entry->type)
- && CLASSTYPE_TEMPLATE_INFO (entry->type)
- && !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
- do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
-}
-
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
nonzero if this is called from the parser, zero if called recursively,
@@ -24980,20 +25079,11 @@ bt_instantiate_type_proc (binding_entry entry, void *data)
void
do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
{
- int extern_p = 0;
- int nomem_p = 0;
- int static_p = 0;
- int previous_instantiation_extern_p = 0;
-
- if (TREE_CODE (t) == TYPE_DECL)
- t = TREE_TYPE (t);
-
- if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
+ if (!(CLASS_TYPE_P (t) && CLASSTYPE_TEMPLATE_INFO (t)))
{
- tree tmpl =
- (TYPE_TEMPLATE_INFO (t)) ? TYPE_TI_TEMPLATE (t) : NULL;
- if (tmpl)
- error ("explicit instantiation of non-class template %qD", tmpl);
+ if (tree ti = TYPE_TEMPLATE_INFO (t))
+ error ("explicit instantiation of non-class template %qD",
+ TI_TEMPLATE (ti));
else
error ("explicit instantiation of non-template type %qT", t);
return;
@@ -25009,6 +25099,11 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
return;
}
+ /* At most one of these will be true. */
+ bool extern_p = false;
+ bool nomem_p = false;
+ bool static_p = false;
+
if (storage != NULL_TREE)
{
if (storage == ridpointers[(int) RID_EXTERN])
@@ -25024,52 +25119,45 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
" on explicit instantiations", storage);
if (storage == ridpointers[(int) RID_INLINE])
- nomem_p = 1;
+ nomem_p = true;
else if (storage == ridpointers[(int) RID_EXTERN])
- extern_p = 1;
+ extern_p = true;
else if (storage == ridpointers[(int) RID_STATIC])
- static_p = 1;
+ static_p = true;
else
- {
- error ("storage class %qD applied to template instantiation",
- storage);
- extern_p = 0;
- }
+ error ("storage class %qD applied to template instantiation",
+ storage);
}
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
- {
- /* DR 259 [temp.spec].
+ /* DR 259 [temp.spec].
- Both an explicit instantiation and a declaration of an explicit
- specialization shall not appear in a program unless the explicit
- instantiation follows a declaration of the explicit specialization.
+ Both an explicit instantiation and a declaration of an explicit
+ specialization shall not appear in a program unless the
+ explicit instantiation follows a declaration of the explicit
+ specialization.
- For a given set of template parameters, if an explicit
- instantiation of a template appears after a declaration of an
- explicit specialization for that template, the explicit
- instantiation has no effect. */
- return;
- }
- else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
+ For a given set of template parameters, if an explicit
+ instantiation of a template appears after a declaration of an
+ explicit specialization for that template, the explicit
+ instantiation has no effect. */
+ return;
+
+ if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && !CLASSTYPE_INTERFACE_ONLY (t))
{
+ /* We've already instantiated the template. */
+
/* [temp.spec]
No program shall explicitly instantiate any template more
than once.
- If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
- instantiation was `extern'. If EXTERN_P then the second is.
- These cases are OK. */
- previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
+ If EXTERN_P then this is ok. */
+ if (!extern_p && (complain & tf_error))
+ permerror (input_location,
+ "duplicate explicit instantiation of %q#T", t);
- if (!previous_instantiation_extern_p && !extern_p
- && (complain & tf_error))
- permerror (input_location, "duplicate explicit instantiation of %q#T", t);
-
- /* If we've already instantiated the template, just return now. */
- if (!CLASSTYPE_INTERFACE_ONLY (t))
- return;
+ return;
}
check_explicit_instantiation_namespace (TYPE_NAME (t));
@@ -25106,10 +25194,14 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
instantiate_decl (fld, /*defer_ok=*/true,
/*expl_inst_class_mem_p=*/true);
}
+ else if (DECL_IMPLICIT_TYPEDEF_P (fld))
+ {
+ tree type = TREE_TYPE (fld);
- if (CLASSTYPE_NESTED_UTDS (t))
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
- bt_instantiate_type_proc, &storage);
+ if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ do_type_instantiation (type, storage, 0);
+ }
}
/* Given a function DECL, which is a specialization of TMPL, modify
@@ -25573,9 +25665,6 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
if (VAR_P (d))
{
- tree init;
- bool const_init = false;
-
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL);
@@ -25585,7 +25674,8 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
regenerate_decl_from_template so we don't need to
push/pop_access_scope again here. Pull it out so that
cp_finish_decl can process it. */
- init = DECL_INITIAL (d);
+ bool const_init = false;
+ tree init = DECL_INITIAL (d);
DECL_INITIAL (d) = NULL_TREE;
DECL_INITIALIZED_P (d) = 0;
@@ -25617,9 +25707,11 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
if (nested_p)
block = push_stmt_list ();
else
- start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ {
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
- perform_instantiation_time_access_checks (code_pattern, args);
+ perform_instantiation_time_access_checks (code_pattern, args);
+ }
/* Create substitution entries for the parameters. */
register_parameter_specializations (code_pattern, d);
@@ -25658,7 +25750,8 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
}
/* We're not deferring instantiation any more. */
- TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0;
+ if (!nested_p)
+ TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0;
if (push_to_top)
pop_from_top_level ();
@@ -27293,7 +27386,8 @@ bool
instantiation_dependent_expression_p (tree expression)
{
return (instantiation_dependent_uneval_expression_p (expression)
- || value_dependent_expression_p (expression));
+ || (potential_constant_expression (expression)
+ && value_dependent_expression_p (expression)));
}
/* Like type_dependent_expression_p, but it also works while not processing
@@ -28001,6 +28095,8 @@ finish_concept_definition (cp_expr id, tree init)
DECL_CONTEXT (decl) = current_scope ();
DECL_INITIAL (decl) = init;
+ set_originating_module (decl, false);
+
/* Push the enclosing template. */
return push_template_decl (decl);
}
@@ -28979,6 +29075,12 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
return ptype;
+ /* Initializing one placeholder from another. */
+ if (init && TREE_CODE (init) == TEMPLATE_PARM_INDEX
+ && is_auto (TREE_TYPE (init))
+ && CLASS_PLACEHOLDER_TEMPLATE (TREE_TYPE (init)) == tmpl)
+ return cp_build_qualified_type (TREE_TYPE (init), cp_type_quals (ptype));
+
/* Look through alias templates that just rename another template. */
tmpl = get_underlying_template (tmpl);
if (!ctad_template_p (tmpl))
@@ -28995,10 +29097,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
"with %<-std=c++20%> or %<-std=gnu++20%>");
}
- if (init && TREE_TYPE (init) == ptype)
- /* Using the template parm as its own argument. */
- return ptype;
-
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
@@ -29241,7 +29339,16 @@ do_auto_deduction (tree type, tree init, tree auto_node,
if (type == error_mark_node)
return error_mark_node;
- init = resolve_nondeduced_context (init, complain);
+ if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ {
+ /* We don't recurse here because we can't deduce from a nested
+ initializer_list. */
+ if (CONSTRUCTOR_ELTS (init))
+ for (constructor_elt &elt : CONSTRUCTOR_ELTS (init))
+ elt.value = resolve_nondeduced_context (elt.value, complain);
+ }
+ else
+ init = resolve_nondeduced_context (init, complain);
if (context == adc_decomp_type
&& auto_node == type
@@ -29254,6 +29361,8 @@ do_auto_deduction (tree type, tree init, tree auto_node,
else if (AUTO_IS_DECLTYPE (auto_node))
{
tree stripped_init = tree_strip_any_location_wrapper (init);
+ if (REFERENCE_REF_P (stripped_init))
+ stripped_init = TREE_OPERAND (stripped_init, 0);
bool id = (DECL_P (stripped_init)
|| ((TREE_CODE (init) == COMPONENT_REF
|| TREE_CODE (init) == SCOPE_REF)
@@ -29606,6 +29715,99 @@ declare_integer_pack (void)
CP_BUILT_IN_INTEGER_PACK);
}
+/* Walk the decl or type specialization table calling FN on each
+ entry. */
+
+void
+walk_specializations (bool decls_p,
+ void (*fn) (bool decls_p, spec_entry *entry, void *data),
+ void *data)
+{
+ spec_hash_table *table = decls_p ? decl_specializations
+ : type_specializations;
+ spec_hash_table::iterator end (table->end ());
+ for (spec_hash_table::iterator iter (table->begin ()); iter != end; ++iter)
+ fn (decls_p, *iter, data);
+}
+
+/* Lookup the specialization of *ELT, in the decl or type
+ specialization table. Return the SPEC that's already there (NULL if
+ nothing). If INSERT is true, and there was nothing, add the new
+ spec. */
+
+tree
+match_mergeable_specialization (bool decl_p, spec_entry *elt, bool insert)
+{
+ hash_table<spec_hasher> *specializations
+ = decl_p ? decl_specializations : type_specializations;
+ hashval_t hash = spec_hasher::hash (elt);
+ spec_entry **slot
+ = specializations->find_slot_with_hash (elt, hash,
+ insert ? INSERT : NO_INSERT);
+ if (slot && *slot)
+ return (*slot)->spec;
+
+ if (insert)
+ {
+ auto entry = ggc_alloc<spec_entry> ();
+ *entry = *elt;
+ *slot = entry;
+ }
+
+ return NULL_TREE;
+}
+
+/* Return flags encoding whether SPEC is on the instantiation and/or
+ specialization lists of TMPL. */
+
+unsigned
+get_mergeable_specialization_flags (tree tmpl, tree decl)
+{
+ unsigned flags = 0;
+
+ for (tree inst = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+ inst; inst = TREE_CHAIN (inst))
+ if (TREE_VALUE (inst) == decl)
+ {
+ flags |= 1;
+ break;
+ }
+
+ if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))
+ && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)) == 2)
+ /* Only need to search if DECL is a partial specialization. */
+ for (tree part = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ part; part = TREE_CHAIN (part))
+ if (TREE_VALUE (part) == decl)
+ {
+ flags |= 2;
+ break;
+ }
+
+ return flags;
+}
+
+/* Add a new specialization of TMPL. FLAGS is as returned from
+ get_mergeable_specialization_flags. */
+
+void
+add_mergeable_specialization (tree tmpl, tree args, tree decl, unsigned flags)
+{
+ if (flags & 1)
+ DECL_TEMPLATE_INSTANTIATIONS (tmpl)
+ = tree_cons (args, decl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+
+ if (flags & 2)
+ {
+ /* A partial specialization. */
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+ = tree_cons (args, decl, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (tmpl))
+ = TREE_TYPE (DECL_TEMPLATE_RESULT (decl));
+ }
+}
+
/* Set up the hash tables for template instantiations. */
void
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index a28b722..1e9fdf8 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -59,6 +59,42 @@ cxx_print_decl (FILE *file, tree node, int indent)
bool need_indent = true;
+ if (TREE_CODE (node) == FUNCTION_DECL
+ || TREE_CODE (node) == VAR_DECL
+ || TREE_CODE (node) == TYPE_DECL
+ || TREE_CODE (node) == TEMPLATE_DECL
+ || TREE_CODE (node) == CONCEPT_DECL
+ || TREE_CODE (node) == NAMESPACE_DECL)
+ {
+ unsigned m = 0;
+ if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_IMPORT_P (node))
+ m = get_importing_module (node, true);
+
+ if (const char *name = m == ~0u ? "" : module_name (m, true))
+ {
+ if (need_indent)
+ indent_to (file, indent + 3);
+ fprintf (file, " module %d:%s", m, name);
+ need_indent = false;
+ }
+
+ if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_PURVIEW_P (node))
+ {
+ if (need_indent)
+ indent_to (file, indent + 3);
+ fprintf (file, " purview");
+ need_indent = false;
+ }
+ }
+
+ if (DECL_MODULE_EXPORT_P (node))
+ {
+ if (need_indent)
+ indent_to (file, indent + 3);
+ fprintf (file, " exported");
+ need_indent = false;
+ }
+
if (DECL_EXTERNAL (node) && DECL_NOT_REALLY_EXTERN (node))
{
if (need_indent)
@@ -250,6 +286,44 @@ cxx_print_xnode (FILE *file, tree node, int indent)
print_node (file, "function", OVL_FUNCTION (node), indent + 4);
print_node (file, "next", OVL_CHAIN (node), indent + 4);
break;
+ case BINDING_VECTOR:
+ {
+ unsigned len = BINDING_VECTOR_NUM_CLUSTERS (node);
+ print_node (file, "name", BINDING_VECTOR_NAME (node), indent + 4);
+ fprintf (file, " clusters %u, alloc %u", len,
+ BINDING_VECTOR_ALLOC_CLUSTERS (node));
+ for (unsigned ix = 0; ix != len; ix++)
+ {
+ binding_cluster *cluster = &BINDING_VECTOR_CLUSTER (node, ix);
+ char pfx[24];
+ for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
+ if (cluster->indices[jx].span)
+ {
+ int len = sprintf (pfx, "module:%u",
+ cluster->indices[jx].base);
+ if (cluster->indices[jx].span > 1)
+ len += sprintf (&pfx[len], "(+%u)",
+ cluster->indices[jx].span);
+ len += sprintf (&pfx[len], " cluster:%u/%u", ix, jx);
+ binding_slot &slot = cluster->slots[jx];
+ if (slot.is_lazy ())
+ {
+ indent_to (file, indent + 4);
+ unsigned lazy = slot.get_lazy ();
+ fprintf (file, "%s snum:%u flags:%d",
+ pfx, lazy >> 2, lazy & 3);
+ }
+ else if (slot)
+ print_node (file, pfx, slot, indent + 4);
+ else
+ {
+ indent_to (file, indent + 4);
+ fprintf (file, "%s NULL", pfx);
+ }
+ }
+ }
+ }
+ break;
case TEMPLATE_PARM_INDEX:
print_node (file, "decl", TEMPLATE_PARM_DECL (node), indent+4);
indent_to (file, indent + 3);
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 7c4bff7..0be9eff 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -143,16 +143,20 @@ static bool typeinfo_in_lib_p (tree);
static int doing_runtime = 0;
-static void
+static unsigned
push_abi_namespace (void)
{
push_nested_namespace (abi_node);
push_visibility ("default", 2);
+ unsigned flags = module_kind;
+ module_kind = 0;
+ return flags;
}
static void
-pop_abi_namespace (void)
+pop_abi_namespace (unsigned flags)
{
+ module_kind = flags;
pop_visibility (2);
pop_nested_namespace (abi_node);
}
@@ -166,10 +170,8 @@ pop_abi_namespace (void)
void
init_rtti_processing (void)
{
- tree type_info_type;
-
push_nested_namespace (std_node);
- type_info_type = xref_tag (class_type, get_identifier ("type_info"));
+ tree type_info_type = xref_tag (class_type, get_identifier ("type_info"));
pop_nested_namespace (std_node);
const_type_info_type_node
= cp_build_qualified_type (type_info_type, TYPE_QUAL_CONST);
@@ -414,9 +416,6 @@ tinfo_name (tree type, bool mark_private)
tree
get_tinfo_decl (tree type)
{
- tree name;
- tree d;
-
if (variably_modified_type_p (type, /*fn=*/NULL_TREE))
{
error ("cannot create type information for type %qT because "
@@ -429,25 +428,41 @@ get_tinfo_decl (tree type)
type = build_function_type (TREE_TYPE (type),
TREE_CHAIN (TYPE_ARG_TYPES (type)));
- type = complete_type (type);
+ return get_tinfo_decl_direct (type, NULL, -1);
+}
+
+/* Get or create a tinfo VAR_DECL directly from the provided information.
+ The caller must have already checked it is valid to do so. */
+tree
+get_tinfo_decl_direct (tree type, tree name, int pseudo_ix)
+{
/* For a class type, the variable is cached in the type node
itself. */
+ tree d = NULL_TREE;
+
+ gcc_checking_assert (TREE_CODE (type) != METHOD_TYPE);
+
+ if (pseudo_ix < 0)
+ type = complete_type (type);
+
if (CLASS_TYPE_P (type))
- {
- d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
- if (d)
- return d;
- }
+ d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
+
+ if (!name)
+ name = mangle_typeinfo_for_type (type);
- name = mangle_typeinfo_for_type (type);
+ if (!CLASS_TYPE_P (type))
+ d = get_global_binding (name);
- d = get_global_binding (name);
if (!d)
{
- int ix = get_pseudo_ti_index (type);
- const tinfo_s *ti = get_tinfo_desc (ix);
-
+ /* Create it. */
+ if (pseudo_ix < 0)
+ pseudo_ix = get_pseudo_ti_index (type);
+
+ const tinfo_s *ti = get_tinfo_desc (pseudo_ix);
+
d = build_lang_decl (VAR_DECL, name, ti->type);
SET_DECL_ASSEMBLER_NAME (d, name);
/* Remember the type it is for. */
@@ -754,24 +769,22 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
dcast_fn = dynamic_cast_node;
if (!dcast_fn)
{
- tree tmp;
- tree tinfo_ptr;
- const char *name;
-
- push_abi_namespace ();
- tinfo_ptr = xref_tag (class_type,
- get_identifier ("__class_type_info"));
- tinfo_ptr = build_pointer_type
- (cp_build_qualified_type
- (tinfo_ptr, TYPE_QUAL_CONST));
- name = "__dynamic_cast";
- tmp = build_function_type_list (ptr_type_node,
- const_ptr_type_node,
- tinfo_ptr, tinfo_ptr,
- ptrdiff_type_node, NULL_TREE);
- dcast_fn = build_library_fn_ptr (name, tmp,
- ECF_LEAF | ECF_PURE | ECF_NOTHROW);
- pop_abi_namespace ();
+ unsigned flags = push_abi_namespace ();
+ tree tinfo_ptr = xref_tag (class_type,
+ get_identifier ("__class_type_info"));
+ tinfo_ptr = cp_build_qualified_type (tinfo_ptr, TYPE_QUAL_CONST);
+ tinfo_ptr = build_pointer_type (tinfo_ptr);
+
+ const char *fn_name = "__dynamic_cast";
+ /* void *() (void const *, __class_type_info const *,
+ __class_type_info const *, ptrdiff_t) */
+ tree fn_type = (build_function_type_list
+ (ptr_type_node, const_ptr_type_node,
+ tinfo_ptr, tinfo_ptr, ptrdiff_type_node,
+ NULL_TREE));
+ dcast_fn = (build_library_fn_ptr
+ (fn_name, fn_type, ECF_LEAF | ECF_PURE | ECF_NOTHROW));
+ pop_abi_namespace (flags);
dynamic_cast_node = dcast_fn;
}
result = build_cxx_call (dcast_fn, 4, elems, complain);
@@ -945,9 +958,11 @@ tinfo_base_init (tinfo_s *ti, tree target)
vtable_ptr = ti->vtable;
if (!vtable_ptr)
{
- push_abi_namespace ();
+ int flags = push_abi_namespace ();
tree real_type = xref_tag (class_type, ti->name);
- pop_abi_namespace ();
+ tree real_decl = TYPE_NAME (real_type);
+ DECL_SOURCE_LOCATION (real_decl) = BUILTINS_LOCATION;
+ pop_abi_namespace (flags);
if (!COMPLETE_TYPE_P (real_type))
{
@@ -1450,8 +1465,6 @@ get_tinfo_desc (unsigned ix)
}
}
- push_abi_namespace ();
-
/* Generate the pseudo type name. */
const char *real_name = tinfo_names[ix < TK_VMI_CLASS_TYPES
? ix : unsigned (TK_VMI_CLASS_TYPES)];
@@ -1468,6 +1481,8 @@ get_tinfo_desc (unsigned ix)
/* Pass the fields chained in reverse. */
finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
+ DECL_CONTEXT (TYPE_NAME (pseudo_type)) = FROB_CONTEXT (global_namespace);
+ DECL_TINFO_P (TYPE_NAME (pseudo_type)) = true;
xref_basetypes (pseudo_type, /*bases=*/NULL_TREE);
res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
@@ -1477,10 +1492,39 @@ get_tinfo_desc (unsigned ix)
internal linkage. */
TREE_PUBLIC (TYPE_MAIN_DECL (res->type)) = 1;
- pop_abi_namespace ();
return res;
}
+/* Return an identifying index for the pseudo type_info TYPE.
+ We wrote the index at the end of the name, so just scan it from
+ there. This isn't critical, as it's only on the first use of this
+ type during module stream out. */
+
+unsigned
+get_pseudo_tinfo_index (tree type)
+{
+ tree name = DECL_NAME (TYPE_NAME (type));
+ unsigned ix = 0, scale = 1;
+ size_t len = IDENTIFIER_LENGTH (name);
+ const char *ptr = IDENTIFIER_POINTER (name) + len;
+
+ for (; *--ptr != '_'; scale *= 10)
+ {
+ len--;
+ gcc_checking_assert (len && ISDIGIT (*ptr));
+ ix += (*ptr - '0') * scale;
+ }
+
+ gcc_assert (len != IDENTIFIER_LENGTH (name));
+ return ix;
+}
+
+tree
+get_pseudo_tinfo_type (unsigned ix)
+{
+ return get_tinfo_desc (ix)->type;
+}
+
/* We lazily create the type info types. */
static void
@@ -1608,12 +1652,10 @@ emit_support_tinfos (void)
bool
emit_tinfo_decl (tree decl)
{
- tree type = TREE_TYPE (DECL_NAME (decl));
- int in_library = typeinfo_in_lib_p (type);
-
gcc_assert (DECL_TINFO_P (decl));
- if (in_library)
+ tree type = TREE_TYPE (DECL_NAME (decl));
+ if (typeinfo_in_lib_p (type))
{
if (doing_runtime)
DECL_EXTERNAL (decl) = 0;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index e36a8ae..8a1de7c 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -977,17 +977,6 @@ lookup_field_r (tree binfo, void *data)
nval = get_class_binding (type, lfi->name, lfi->want_type);
- /* If we're looking up a type (as with an elaborated type specifier)
- we ignore all non-types we find. */
- if (lfi->want_type && nval && !DECL_DECLARES_TYPE_P (nval))
- {
- nval = NULL_TREE;
- if (CLASSTYPE_NESTED_UTDS (type))
- if (binding_entry e = binding_table_find (CLASSTYPE_NESTED_UTDS (type),
- lfi->name))
- nval = TYPE_MAIN_DECL (e->type);
- }
-
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
if (!nval)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1e42cd7..92e32c8 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3006,12 +3006,7 @@ finish_compound_literal (tree type, tree compound_literal,
/* If we're in a template, return the original compound literal. */
if (orig_cl)
- {
- if (!VECTOR_TYPE_P (type))
- return get_target_expr_sfinae (orig_cl, complain);
- else
- return orig_cl;
- }
+ return orig_cl;
if (TREE_CODE (compound_literal) == CONSTRUCTOR)
{
@@ -3225,6 +3220,19 @@ begin_class_definition (tree t)
t = make_class_type (TREE_CODE (t));
pushtag (TYPE_IDENTIFIER (t), t);
}
+
+ if (modules_p ())
+ {
+ if (!module_may_redeclare (TYPE_NAME (t)))
+ {
+ error ("cannot declare %qD in a different module", TYPE_NAME (t));
+ inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)), "declared here");
+ return error_mark_node;
+ }
+ set_instantiating_module (TYPE_NAME (t));
+ set_defining_module (TYPE_NAME (t));
+ }
+
maybe_process_partial_specialization (t);
pushclass (t);
TYPE_BEING_DEFINED (t) = 1;
@@ -4024,9 +4032,17 @@ finish_id_expression_1 (tree id_expression,
if (context != current_class_type)
{
tree path = currently_open_derived_class (context);
- perform_or_defer_access_check (TYPE_BINFO (path),
- decl, decl,
- tf_warning_or_error);
+ if (!path)
+ /* PATH can be null for using an enum of an unrelated
+ class; we checked its access in lookup_using_decl.
+
+ ??? Should this case make a clone instead, like
+ handle_using_decl? */
+ gcc_assert (TREE_CODE (decl) == CONST_DECL);
+ else
+ perform_or_defer_access_check (TYPE_BINFO (path),
+ decl, decl,
+ tf_warning_or_error);
}
}
@@ -4503,7 +4519,8 @@ expand_or_defer_fn_1 (tree fn)
it out, even though we haven't. */
TREE_ASM_WRITTEN (fn) = 1;
/* If this is a constexpr function, keep DECL_SAVED_TREE. */
- if (!DECL_DECLARED_CONSTEXPR_P (fn))
+ if (!DECL_DECLARED_CONSTEXPR_P (fn)
+ && !(modules_p () && DECL_DECLARED_INLINE_P (fn)))
DECL_SAVED_TREE (fn) = NULL_TREE;
return false;
}
@@ -5382,11 +5399,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
if ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP && ort != C_ORT_ACC)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
else if (TREE_CODE (t) == COMPONENT_REF)
- {
- gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
- OMP_CLAUSE_SET_MAP_KIND (c2, k);
- }
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else if (REFERENCE_REF_P (t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
{
@@ -5424,8 +5437,12 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (c3, OMP_CLAUSE_MAP_KIND (c2));
OMP_CLAUSE_DECL (c3) = ptr;
- if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER)
- OMP_CLAUSE_DECL (c2) = build_simple_mem_ref (ptr);
+ if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER
+ || OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ATTACH_DETACH)
+ {
+ OMP_CLAUSE_DECL (c2) = build_simple_mem_ref (ptr);
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+ }
else
OMP_CLAUSE_DECL (c2) = convert_from_reference (ptr);
OMP_CLAUSE_SIZE (c3) = size_zero_node;
@@ -6373,6 +6390,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* 1 if normal/task reduction has been seen, -1 if inscan reduction
has been seen, -2 if mixed inscan/normal reduction diagnosed. */
int reduction_seen = 0;
+ bool allocate_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -7198,6 +7216,80 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
break;
+ case OMP_CLAUSE_ALLOCATE:
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (t)
+ omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
+ else
+ t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> not allowed in %<allocate%> clause");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != FIELD_DECL)
+ {
+ if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ break;
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %<allocate%> clause", t);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<allocate%> clause", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%qD appears more than once in %<allocate%> clauses",
+ t);
+ remove = true;
+ }
+ else
+ {
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ allocate_seen = true;
+ }
+ tree allocator;
+ allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ if (error_operand_p (allocator))
+ {
+ remove = true;
+ break;
+ }
+ if (allocator == NULL_TREE)
+ goto handle_field_decl;
+ tree allocatort;
+ allocatort = TYPE_MAIN_VARIANT (TREE_TYPE (allocator));
+ if (!type_dependent_expression_p (allocator)
+ && (TREE_CODE (allocatort) != ENUMERAL_TYPE
+ || TYPE_NAME (allocatort) == NULL_TREE
+ || TREE_CODE (TYPE_NAME (allocatort)) != TYPE_DECL
+ || (DECL_NAME (TYPE_NAME (allocatort))
+ != get_identifier ("omp_allocator_handle_t"))
+ || (TYPE_CONTEXT (allocatort)
+ != DECL_CONTEXT (global_namespace))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause allocator expression has "
+ "type %qT rather than %<omp_allocator_handle_t%>",
+ TREE_TYPE (allocator));
+ remove = true;
+ }
+ else
+ {
+ allocator = mark_rvalue_use (allocator);
+ if (!processing_template_decl)
+ allocator = maybe_constant_value (allocator);
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ }
+ goto handle_field_decl;
+
case OMP_CLAUSE_DEPEND:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
@@ -7411,7 +7503,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t = TREE_OPERAND (t, 0);
OMP_CLAUSE_DECL (c) = t;
}
- if (ort == C_ORT_ACC
+ if ((ort == C_ORT_ACC || ort == C_ORT_OMP)
&& TREE_CODE (t) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF)
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
@@ -7457,7 +7549,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t = TREE_OPERAND (t, 0);
if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
{
- if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
+ if (bitmap_bit_p (&map_field_head, DECL_UID (t))
+ || (ort == C_ORT_OMP
+ && bitmap_bit_p (&map_head, DECL_UID (t))))
goto handle_map_references;
}
}
@@ -7551,13 +7645,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&generic_head, DECL_UID (t));
}
else if (bitmap_bit_p (&map_head, DECL_UID (t))
- && (ort != C_ORT_ACC
- || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
+ && !bitmap_bit_p (&map_field_head, DECL_UID (t)))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in motion clauses", t);
- if (ort == C_ORT_ACC)
+ else if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
else
@@ -7566,7 +7659,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
- || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ && ort == C_ORT_ACC)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -7602,17 +7701,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
&& (OMP_CLAUSE_MAP_KIND (c)
!= GOMP_MAP_FIRSTPRIVATE_REFERENCE)
&& (OMP_CLAUSE_MAP_KIND (c)
- != GOMP_MAP_ALWAYS_POINTER))
+ != GOMP_MAP_ALWAYS_POINTER)
+ && (OMP_CLAUSE_MAP_KIND (c)
+ != GOMP_MAP_ATTACH_DETACH))
{
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
if (TREE_CODE (t) == COMPONENT_REF)
- {
- gomp_map_kind k
- = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
- OMP_CLAUSE_SET_MAP_KIND (c2, k);
- }
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else
OMP_CLAUSE_SET_MAP_KIND (c2,
GOMP_MAP_FIRSTPRIVATE_REFERENCE);
@@ -8115,17 +8211,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
t = OMP_CLAUSE_DECL (c);
- if (processing_template_decl
- && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
- {
- pc = &OMP_CLAUSE_CHAIN (c);
- continue;
- }
-
switch (c_kind)
{
case OMP_CLAUSE_LASTPRIVATE:
- if (!bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ if (DECL_P (t)
+ && !bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
need_default_ctor = true;
need_dtor = true;
@@ -8135,6 +8225,34 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
+ if (allocate_seen)
+ {
+ if (TREE_CODE (t) == MEM_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ }
+ else if (TREE_CODE (t) == TREE_LIST)
+ {
+ while (TREE_CODE (t) == TREE_LIST)
+ t = TREE_CHAIN (t);
+ if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ t = OMP_CLAUSE_DECL (c);
+ }
+ else if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ t = OMP_CLAUSE_DECL (c);
+ }
+ if (processing_template_decl
+ && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ break;
if (finish_omp_reduction_clause (c, &need_default_ctor,
&need_dtor))
remove = true;
@@ -8143,6 +8261,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
case OMP_CLAUSE_COPYIN:
+ if (processing_template_decl
+ && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ break;
if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t))
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -8155,6 +8276,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
+ if (processing_template_decl
+ && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+ }
+
if (need_complete_type || need_copy_assignment)
{
t = require_complete_type (t);
@@ -8169,6 +8297,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
const char *share_name = NULL;
+ if (allocate_seen
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED
+ && DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+
if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
share_name = "threadprivate";
else switch (cxx_omp_predetermined_sharing_1 (t))
@@ -8262,6 +8395,26 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (allocate_seen)
+ for (pc = &clauses, c = clauses; c ; c = *pc)
+ {
+ bool remove = false;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && !OMP_CLAUSE_ALLOCATE_COMBINED (c)
+ && DECL_P (OMP_CLAUSE_DECL (c))
+ && bitmap_bit_p (&aligned_head, DECL_UID (OMP_CLAUSE_DECL (c))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %<allocate%> clause but not in "
+ "an explicit privatization clause", OMP_CLAUSE_DECL (c));
+ remove = true;
+ }
+ if (remove)
+ *pc = OMP_CLAUSE_CHAIN (c);
+ else
+ pc = &OMP_CLAUSE_CHAIN (c);
+ }
+
bitmap_obstack_release (NULL);
return clauses;
}
@@ -9691,13 +9844,53 @@ init_cp_semantics (void)
{
}
+
+/* If we have a condition in conjunctive normal form (CNF), find the first
+ failing clause. In other words, given an expression like
+
+ true && true && false && true && false
+
+ return the first 'false'. EXPR is the expression. */
+
+static tree
+find_failing_clause_r (tree expr)
+{
+ if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR)
+ {
+ /* First check the left side... */
+ tree e = find_failing_clause_r (TREE_OPERAND (expr, 0));
+ if (e == NULL_TREE)
+ /* ...if we didn't find a false clause, check the right side. */
+ e = find_failing_clause_r (TREE_OPERAND (expr, 1));
+ return e;
+ }
+ tree e = contextual_conv_bool (expr, tf_none);
+ e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true);
+ if (integer_zerop (e))
+ /* This is the failing clause. */
+ return expr;
+ return NULL_TREE;
+}
+
+/* Wrapper for find_failing_clause_r. */
+
+static tree
+find_failing_clause (tree expr)
+{
+ if (TREE_CODE (expr) != TRUTH_ANDIF_EXPR)
+ return NULL_TREE;
+ return find_failing_clause_r (expr);
+}
+
/* Build a STATIC_ASSERT for a static assertion with the condition
CONDITION and the message text MESSAGE. LOCATION is the location
of the static assertion in the source code. When MEMBER_P, this
- static assertion is a member of a class. */
+ static assertion is a member of a class. If SHOW_EXPR_P is true,
+ print the condition (because it was instantiation-dependent). */
+
void
finish_static_assert (tree condition, tree message, location_t location,
- bool member_p)
+ bool member_p, bool show_expr_p)
{
tsubst_flags_t complain = tf_warning_or_error;
@@ -9735,8 +9928,7 @@ finish_static_assert (tree condition, tree message, location_t location,
tree orig_condition = condition;
/* Fold the expression and convert it to a boolean value. */
- condition = perform_implicit_conversion_flags (boolean_type_node, condition,
- complain, LOOKUP_NORMAL);
+ condition = contextual_conv_bool (condition, complain);
condition = fold_non_dependent_expr (condition, complain,
/*manifestly_const_eval=*/true);
@@ -9745,21 +9937,32 @@ finish_static_assert (tree condition, tree message, location_t location,
;
else
{
- location_t saved_loc = input_location;
+ iloc_sentinel ils (location);
- input_location = location;
- if (TREE_CODE (condition) == INTEGER_CST
- && integer_zerop (condition))
+ if (integer_zerop (condition))
{
int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT
(TREE_TYPE (TREE_TYPE (message))));
int len = TREE_STRING_LENGTH (message) / sz - 1;
+
+ /* See if we can find which clause was failing (for logical AND). */
+ tree bad = find_failing_clause (orig_condition);
+ /* If not, or its location is unusable, fall back to the previous
+ location. */
+ location_t cloc = location;
+ if (cp_expr_location (bad) != UNKNOWN_LOCATION)
+ cloc = cp_expr_location (bad);
+
/* Report the error. */
if (len == 0)
- error ("static assertion failed");
+ error_at (cloc, "static assertion failed");
else
- error ("static assertion failed: %s",
- TREE_STRING_POINTER (message));
+ error_at (cloc, "static assertion failed: %s",
+ TREE_STRING_POINTER (message));
+ if (show_expr_p)
+ inform (cloc, "%qE evaluates to false",
+ /* Nobody wants to see the artificial (bool) cast. */
+ (bad ? tree_strip_nop_conversions (bad) : orig_condition));
/* Actually explain the failure if this is a concept check or a
requires-expression. */
@@ -9773,7 +9976,6 @@ finish_static_assert (tree condition, tree message, location_t location,
if (require_rvalue_constant_expression (condition))
cxx_constant_value (condition);
}
- input_location = saved_loc;
}
}
@@ -10133,6 +10335,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_CONSTRUCTIBLE:
return is_xible (INIT_EXPR, type1, type2);
+ case CPTK_IS_NOTHROW_ASSIGNABLE:
+ return is_nothrow_xible (MODIFY_EXPR, type1, type2);
+
+ case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+ return is_nothrow_xible (INIT_EXPR, type1, type2);
+
default:
gcc_unreachable ();
return false;
@@ -10213,6 +10421,8 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+ case CPTK_IS_NOTHROW_ASSIGNABLE:
+ case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
if (!check_trait_type (type1)
|| !check_trait_type (type2))
return error_mark_node;
@@ -10483,4 +10693,75 @@ cp_build_vec_convert (tree arg, location_t loc, tree type,
return build_call_expr_internal_loc (loc, IFN_VEC_CONVERT, type, 1, arg);
}
+/* Finish __builtin_bit_cast (type, arg). */
+
+tree
+cp_build_bit_cast (location_t loc, tree type, tree arg,
+ tsubst_flags_t complain)
+{
+ if (error_operand_p (type))
+ return error_mark_node;
+ if (!dependent_type_p (type))
+ {
+ if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
+ return error_mark_node;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ /* std::bit_cast for destination ARRAY_TYPE is not possible,
+ as functions may not return an array, so don't bother trying
+ to support this (and then deal with VLAs etc.). */
+ error_at (loc, "%<__builtin_bit_cast%> destination type %qT "
+ "is an array type", type);
+ return error_mark_node;
+ }
+ if (!trivially_copyable_p (type))
+ {
+ error_at (loc, "%<__builtin_bit_cast%> destination type %qT "
+ "is not trivially copyable", type);
+ return error_mark_node;
+ }
+ }
+
+ if (error_operand_p (arg))
+ return error_mark_node;
+
+ if (!type_dependent_expression_p (arg))
+ {
+ if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
+ {
+ /* Don't perform array-to-pointer conversion. */
+ arg = mark_rvalue_use (arg, loc, true);
+ if (!complete_type_or_maybe_complain (TREE_TYPE (arg), arg, complain))
+ return error_mark_node;
+ }
+ else
+ arg = decay_conversion (arg, complain);
+
+ if (error_operand_p (arg))
+ return error_mark_node;
+
+ if (!trivially_copyable_p (TREE_TYPE (arg)))
+ {
+ error_at (cp_expr_loc_or_loc (arg, loc),
+ "%<__builtin_bit_cast%> source type %qT "
+ "is not trivially copyable", TREE_TYPE (arg));
+ return error_mark_node;
+ }
+ if (!dependent_type_p (type)
+ && !cp_tree_equal (TYPE_SIZE_UNIT (type),
+ TYPE_SIZE_UNIT (TREE_TYPE (arg))))
+ {
+ error_at (loc, "%<__builtin_bit_cast%> source size %qE "
+ "not equal to destination type size %qE",
+ TYPE_SIZE_UNIT (TREE_TYPE (arg)),
+ TYPE_SIZE_UNIT (type));
+ return error_mark_node;
+ }
+ }
+
+ tree ret = build_min (BIT_CAST_EXPR, type, arg);
+ SET_EXPR_LOCATION (ret, loc);
+ return ret;
+}
+
#include "gt-cp-semantics.h"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9bc37ac..0584a7b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -998,7 +998,7 @@ build_min_array_type (tree elt_type, tree index_type)
build_cplus_array_type. */
static void
-set_array_type_canon (tree t, tree elt_type, tree index_type)
+set_array_type_canon (tree t, tree elt_type, tree index_type, bool dep)
{
/* Set the canonical type for this new node. */
if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
@@ -1009,30 +1009,33 @@ set_array_type_canon (tree t, tree elt_type, tree index_type)
TYPE_CANONICAL (t)
= build_cplus_array_type (TYPE_CANONICAL (elt_type),
index_type
- ? TYPE_CANONICAL (index_type) : index_type);
+ ? TYPE_CANONICAL (index_type) : index_type,
+ dep);
else
TYPE_CANONICAL (t) = t;
}
/* Like build_array_type, but handle special C++ semantics: an array of a
variant element type is a variant of the array of the main variant of
- the element type. */
+ the element type. IS_DEPENDENT is -ve if we should determine the
+ dependency. Otherwise its bool value indicates dependency. */
tree
-build_cplus_array_type (tree elt_type, tree index_type)
+build_cplus_array_type (tree elt_type, tree index_type, int dependent)
{
tree t;
if (elt_type == error_mark_node || index_type == error_mark_node)
return error_mark_node;
- bool dependent = (uses_template_parms (elt_type)
- || (index_type && uses_template_parms (index_type)));
+ if (dependent < 0)
+ dependent = (uses_template_parms (elt_type)
+ || (index_type && uses_template_parms (index_type)));
if (elt_type != TYPE_MAIN_VARIANT (elt_type))
/* Start with an array of the TYPE_MAIN_VARIANT. */
t = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
- index_type);
+ index_type, dependent);
else if (dependent)
{
/* Since type_hash_canon calls layout_type, we need to use our own
@@ -1062,13 +1065,20 @@ build_cplus_array_type (tree elt_type, tree index_type)
*e = t;
/* Set the canonical type for this new node. */
- set_array_type_canon (t, elt_type, index_type);
+ set_array_type_canon (t, elt_type, index_type, dependent);
+
+ /* Mark it as dependent now, this saves time later. */
+ TYPE_DEPENDENT_P_VALID (t) = true;
+ TYPE_DEPENDENT_P (t) = true;
}
}
else
{
bool typeless_storage = is_byte_access_type (elt_type);
t = build_array_type (elt_type, index_type, typeless_storage);
+
+ /* Mark as non-dependenty now, this will save time later. */
+ TYPE_DEPENDENT_P_VALID (t) = true;
}
/* Now check whether we already have this array variant. */
@@ -1083,7 +1093,10 @@ build_cplus_array_type (tree elt_type, tree index_type)
if (!t)
{
t = build_min_array_type (elt_type, index_type);
- set_array_type_canon (t, elt_type, index_type);
+ /* Mark dependency now, this saves time later. */
+ TYPE_DEPENDENT_P_VALID (t) = true;
+ TYPE_DEPENDENT_P (t) = dependent;
+ set_array_type_canon (t, elt_type, index_type, dependent);
if (!dependent)
{
layout_type (t);
@@ -1319,7 +1332,10 @@ cp_build_qualified_type_real (tree type,
if (!t)
{
- t = build_cplus_array_type (element_type, TYPE_DOMAIN (type));
+ gcc_checking_assert (TYPE_DEPENDENT_P_VALID (type)
+ || !dependent_type_p (type));
+ t = build_cplus_array_type (element_type, TYPE_DOMAIN (type),
+ TYPE_DEPENDENT_P (type));
/* Keep the typedef name. */
if (TYPE_NAME (t) != TYPE_NAME (type))
@@ -1555,7 +1571,9 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
case ARRAY_TYPE:
type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags);
- result = build_cplus_array_type (type, t0);
+ gcc_checking_assert (TYPE_DEPENDENT_P_VALID (t)
+ || !dependent_type_p (t));
+ result = build_cplus_array_type (type, t0, TYPE_DEPENDENT_P (t));
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
@@ -2218,6 +2236,23 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual)
return build_cp_fntype_variant (type, rqual, raises, late);
}
+tree
+make_binding_vec (tree name, unsigned clusters MEM_STAT_DECL)
+{
+ /* Stored in an unsigned short, but we're limited to the number of
+ modules anyway. */
+ gcc_checking_assert (clusters <= (unsigned short)(~0));
+ size_t length = (offsetof (tree_binding_vec, vec)
+ + clusters * sizeof (binding_cluster));
+ tree vec = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
+ TREE_SET_CODE (vec, BINDING_VECTOR);
+ BINDING_VECTOR_NAME (vec) = name;
+ BINDING_VECTOR_ALLOC_CLUSTERS (vec) = clusters;
+ BINDING_VECTOR_NUM_CLUSTERS (vec) = 0;
+
+ return vec;
+}
+
/* Make a raw overload node containing FN. */
tree
@@ -2237,10 +2272,11 @@ ovl_make (tree fn, tree next)
return result;
}
-/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN
- is > 0, if FN is via a using declaration. USING_OR_HIDDEN is < 0,
- if FN is hidden. (A decl cannot be both using and hidden.) We
- keep the hidden decls first, but remaining ones are unordered. */
+/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN is >
+ zero if this is a using-decl. It is > 1 if we're exporting the
+ using decl. USING_OR_HIDDEN is < 0, if FN is hidden. (A decl
+ cannot be both using and hidden.) We keep the hidden decls first,
+ but remaining ones are unordered. */
tree
ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden)
@@ -2264,7 +2300,11 @@ ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden)
if (using_or_hidden < 0)
OVL_HIDDEN_P (maybe_ovl) = true;
if (using_or_hidden > 0)
- OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true;
+ {
+ OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true;
+ if (using_or_hidden > 1)
+ OVL_EXPORT_P (maybe_ovl) = true;
+ }
}
else
maybe_ovl = fn;
@@ -2676,6 +2716,52 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual,
return v;
}
+/* TYPE is a function or method type with a deferred exception
+ specification that has been parsed to RAISES. Fixup all the type
+ variants that are affected in place. Via decltype &| noexcept
+ tricks, the unparsed spec could have escaped into the type system.
+ The general case is hard to fixup canonical types for. */
+
+void
+fixup_deferred_exception_variants (tree type, tree raises)
+{
+ tree original = TYPE_RAISES_EXCEPTIONS (type);
+ tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE;
+
+ gcc_checking_assert (TREE_CODE (TREE_PURPOSE (original))
+ == DEFERRED_PARSE);
+
+ /* Though sucky, this walk will process the canonical variants
+ first. */
+ for (tree variant = TYPE_MAIN_VARIANT (type);
+ variant; variant = TYPE_NEXT_VARIANT (variant))
+ if (TYPE_RAISES_EXCEPTIONS (variant) == original)
+ {
+ gcc_checking_assert (variant != TYPE_MAIN_VARIANT (type));
+
+ if (!TYPE_STRUCTURAL_EQUALITY_P (variant))
+ {
+ cp_cv_quals var_quals = TYPE_QUALS (variant);
+ cp_ref_qualifier rqual = type_memfn_rqual (variant);
+
+ tree v = TYPE_MAIN_VARIANT (type);
+ for (; v; v = TYPE_NEXT_VARIANT (v))
+ if (TYPE_CANONICAL (v) == v
+ && cp_check_qualified_type (v, variant, var_quals,
+ rqual, cr, false))
+ break;
+ TYPE_RAISES_EXCEPTIONS (variant) = raises;
+
+ if (!v)
+ v = build_cp_fntype_variant (TYPE_CANONICAL (variant),
+ rqual, cr, false);
+ TYPE_CANONICAL (variant) = v;
+ }
+ else
+ TYPE_RAISES_EXCEPTIONS (variant) = raises;
+ }
+}
+
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
@@ -2700,6 +2786,7 @@ bind_template_template_parm (tree t, tree newargs)
t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
decl = build_decl (input_location,
TYPE_DECL, DECL_NAME (decl), NULL_TREE);
+ SET_DECL_TEMPLATE_PARM_P (decl);
/* These nodes have to be created to reflect new TYPE_DECL and template
arguments. */
@@ -2921,6 +3008,32 @@ array_type_nelts_total (tree type)
return sz;
}
+/* Return true if FNDECL is std::source_location::current () method. */
+
+bool
+source_location_current_p (tree fndecl)
+{
+ gcc_checking_assert (TREE_CODE (fndecl) == FUNCTION_DECL
+ && DECL_IMMEDIATE_FUNCTION_P (fndecl));
+ if (DECL_NAME (fndecl) == NULL_TREE
+ || TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != RECORD_TYPE
+ || DECL_CONTEXT (fndecl) != TREE_TYPE (TREE_TYPE (fndecl))
+ || !id_equal (DECL_NAME (fndecl), "current"))
+ return false;
+
+ tree source_location = DECL_CONTEXT (fndecl);
+ if (TYPE_NAME (source_location) == NULL_TREE
+ || TREE_CODE (TYPE_NAME (source_location)) != TYPE_DECL
+ || TYPE_IDENTIFIER (source_location) == NULL_TREE
+ || !id_equal (TYPE_IDENTIFIER (source_location),
+ "source_location")
+ || !decl_in_std_namespace_p (TYPE_NAME (source_location)))
+ return false;
+
+ return true;
+}
+
struct bot_data
{
splay_tree target_remap;
@@ -3671,20 +3784,28 @@ cp_tree_equal (tree t1, tree t2)
case CALL_EXPR:
{
- tree arg1, arg2;
- call_expr_arg_iterator iter1, iter2;
- if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2)
- || !called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+ if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2))
return false;
- for (arg1 = first_call_expr_arg (t1, &iter1),
- arg2 = first_call_expr_arg (t2, &iter2);
- arg1 && arg2;
- arg1 = next_call_expr_arg (&iter1),
- arg2 = next_call_expr_arg (&iter2))
- if (!cp_tree_equal (arg1, arg2))
- return false;
- if (arg1 || arg2)
+
+ if (!called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+ return false;
+
+ call_expr_arg_iterator iter1, iter2;
+ init_call_expr_arg_iterator (t1, &iter1);
+ init_call_expr_arg_iterator (t2, &iter2);
+ if (iter1.n != iter2.n)
return false;
+
+ while (more_call_expr_args_p (&iter1))
+ {
+ tree arg1 = next_call_expr_arg (&iter1);
+ tree arg2 = next_call_expr_arg (&iter2);
+
+ gcc_checking_assert (arg1 && arg2);
+ if (!cp_tree_equal (arg1, arg2))
+ return false;
+ }
+
return true;
}
@@ -3716,7 +3837,12 @@ cp_tree_equal (tree t1, tree t2)
template. */
if (comparing_specializations
- && DECL_CONTEXT (t1) != DECL_CONTEXT (t2))
+ && DECL_CONTEXT (t1) != DECL_CONTEXT (t2)
+ /* Module duplicate checking can have t1 = new, t2 =
+ existing, and they should be considered matching at this
+ point. */
+ && (DECL_CONTEXT (t1) != map_context_from
+ && DECL_CONTEXT (t2) != map_context_to))
/* When comparing hash table entries, only an exact match is
good enough; we don't want to replace 'this' with the
version from another function. But be more flexible
@@ -3779,16 +3905,11 @@ cp_tree_equal (tree t1, tree t2)
CHECK_CONSTR_ARGS (t2)));
case TREE_VEC:
- {
- unsigned ix;
- if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
- return false;
- for (ix = TREE_VEC_LENGTH (t1); ix--;)
- if (!cp_tree_equal (TREE_VEC_ELT (t1, ix),
- TREE_VEC_ELT (t2, ix)))
- return false;
- return true;
- }
+ /* These are template args. Really we should be getting the
+ caller to do this as it knows it to be true. */
+ if (!comp_template_args (t1, t2, NULL, NULL, false))
+ return false;
+ return true;
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -3858,6 +3979,17 @@ cp_tree_equal (tree t1, tree t2)
return same_type_p (TRAIT_EXPR_TYPE1 (t1), TRAIT_EXPR_TYPE1 (t2))
&& cp_tree_equal (TRAIT_EXPR_TYPE2 (t1), TRAIT_EXPR_TYPE2 (t2));
+ case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
+ /* Used for location wrappers with possibly NULL types. */
+ if (!TREE_TYPE (t1) || !TREE_TYPE (t2))
+ {
+ if (TREE_TYPE (t1) || TREE_TYPE (t2))
+ return false;
+ break;
+ }
+ /* FALLTHROUGH */
+
case CAST_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
@@ -3865,9 +3997,8 @@ cp_tree_equal (tree t1, tree t2)
case DYNAMIC_CAST_EXPR:
case IMPLICIT_CONV_EXPR:
case NEW_EXPR:
+ case BIT_CAST_EXPR:
CASE_CONVERT:
- case NON_LVALUE_EXPR:
- case VIEW_CONVERT_EXPR:
if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
return false;
/* Now compare operands as usual. */
@@ -4050,13 +4181,14 @@ is_dummy_object (const_tree ob)
&& TREE_OPERAND (ob, 0) == void_node);
}
-/* Returns true if TYPE is a character type or std::byte. */
+/* Returns true if TYPE is char, unsigned char, or std::byte. */
bool
is_byte_access_type (tree type)
{
type = TYPE_MAIN_VARIANT (type);
- if (char_type_p (type))
+ if (type == char_type_node
+ || type == unsigned_char_type_node)
return true;
return (TREE_CODE (type) == ENUMERAL_TYPE
@@ -5112,6 +5244,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
case CONST_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
case IMPLICIT_CONV_EXPR:
+ case BIT_CAST_EXPR:
if (TREE_TYPE (*tp))
WALK_SUBTREE (TREE_TYPE (*tp));
@@ -5668,8 +5801,7 @@ cp_fix_function_decl_p (tree decl)
/* Don't fix same_body aliases. Although they don't have their own
CFG, they share it with what they alias to. */
- if (!node || !node->alias
- || !vec_safe_length (node->ref_list.references))
+ if (!node || !node->alias || !node->num_references ())
return true;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 48d34f1..c41457b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -154,6 +154,7 @@ complete_type_or_maybe_complain (tree type, tree value, tsubst_flags_t complain)
{
if (complain & tf_error)
cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
+ note_failed_type_completion_for_satisfaction (type);
return NULL_TREE;
}
else
@@ -1247,14 +1248,8 @@ cxx_safe_function_type_cast_p (tree t1, tree t2)
static bool
structural_comptypes (tree t1, tree t2, int strict)
{
- if (t1 == t2)
- return true;
-
- /* Suppress errors caused by previously reported errors. */
- if (t1 == error_mark_node || t2 == error_mark_node)
- return false;
-
- gcc_assert (TYPE_P (t1) && TYPE_P (t2));
+ /* Both should be types that are not obviously the same. */
+ gcc_checking_assert (t1 != t2 && TYPE_P (t1) && TYPE_P (t2));
if (!comparing_specializations)
{
@@ -1300,13 +1295,13 @@ structural_comptypes (tree t1, tree t2, int strict)
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
-
if (TREE_CODE (t1) != ARRAY_TYPE
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return true;
-
+ goto check_alias;
- /* Compare the types. Break out if they could be the same. */
+ /* Compare the types. Return false on known not-same. Break on not
+ known. Never return true from this switch -- you'll break
+ specialization comparison. */
switch (TREE_CODE (t1))
{
case VOID_TYPE:
@@ -1314,6 +1309,7 @@ structural_comptypes (tree t1, tree t2, int strict)
/* All void and bool types are the same. */
break;
+ case OPAQUE_TYPE:
case INTEGER_TYPE:
case FIXED_POINT_TYPE:
case REAL_TYPE:
@@ -1331,7 +1327,11 @@ structural_comptypes (tree t1, tree t2, int strict)
have identical properties, different TYPE_MAIN_VARIANTs, but
represent the same type. The canonical type system keeps
track of equivalence in this case, so we fall back on it. */
- return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+ if (TYPE_CANONICAL (t1) != TYPE_CANONICAL (t2))
+ return false;
+
+ /* We don't need or want the attribute comparison. */
+ goto check_alias;
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -1476,24 +1476,28 @@ structural_comptypes (tree t1, tree t2, int strict)
return false;
}
- /* Don't treat an alias template specialization with dependent
- arguments as equivalent to its underlying type when used as a
- template argument; we need them to be distinct so that we
- substitute into the specialization arguments at instantiation
- time. And aliases can't be equivalent without being ==, so
- we don't need to look any deeper. */
+ /* If we get here, we know that from a target independent POV the
+ types are the same. Make sure the target attributes are also
+ the same. */
+ if (!comp_type_attributes (t1, t2))
+ return false;
+
+ check_alias:
if (comparing_specializations)
{
+ /* Don't treat an alias template specialization with dependent
+ arguments as equivalent to its underlying type when used as a
+ template argument; we need them to be distinct so that we
+ substitute into the specialization arguments at instantiation
+ time. And aliases can't be equivalent without being ==, so
+ we don't need to look any deeper. */
tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent);
tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent);
if ((dep1 || dep2) && dep1 != dep2)
return false;
}
- /* If we get here, we know that from a target independent POV the
- types are the same. Make sure the target attributes are also
- the same. */
- return comp_type_attributes (t1, t2);
+ return true;
}
/* Return true if T1 and T2 are related as allowed by STRICT. STRICT
@@ -1508,6 +1512,13 @@ comptypes (tree t1, tree t2, int strict)
gcc_checking_assert (TREE_CODE (t1) != TYPE_ARGUMENT_PACK
&& TREE_CODE (t2) != TYPE_ARGUMENT_PACK);
+ if (t1 == t2)
+ return true;
+
+ /* Suppress errors caused by previously reported errors. */
+ if (t1 == error_mark_node || t2 == error_mark_node)
+ return false;
+
if (strict == COMPARE_STRICT && comparing_specializations
&& (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2)))
/* If comparing_specializations, treat dependent aliases as distinct. */
@@ -1515,12 +1526,6 @@ comptypes (tree t1, tree t2, int strict)
if (strict == COMPARE_STRICT)
{
- if (t1 == t2)
- return true;
-
- if (t1 == error_mark_node || t2 == error_mark_node)
- return false;
-
if (TYPE_STRUCTURAL_EQUALITY_P (t1) || TYPE_STRUCTURAL_EQUALITY_P (t2))
/* At least one of the types requires structural equality, so
perform a deep check. */
@@ -1832,10 +1837,12 @@ cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t complain)
/* Implement the __alignof keyword: Return the minimum required
alignment of E, measured in bytes. For VAR_DECL's and
FIELD_DECL's return DECL_ALIGN (which can be set from an
- "aligned" __attribute__ specification). */
+ "aligned" __attribute__ specification). STD_ALIGNOF acts
+ like in cxx_sizeof_or_alignof_type. */
static tree
-cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain)
+cxx_alignof_expr (location_t loc, tree e, bool std_alignof,
+ tsubst_flags_t complain)
{
tree t;
@@ -1848,6 +1855,7 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain)
TREE_SIDE_EFFECTS (e) = 0;
TREE_READONLY (e) = 1;
SET_EXPR_LOCATION (e, loc);
+ ALIGNOF_EXPR_STD_P (e) = std_alignof;
return e;
}
@@ -1900,23 +1908,25 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain)
}
else
return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e),
- ALIGNOF_EXPR, false,
+ ALIGNOF_EXPR, std_alignof,
complain & tf_error);
return fold_convert_loc (loc, size_type_node, t);
}
/* Process a sizeof or alignof expression E with code OP where the operand
- is an expression. */
+ is an expression. STD_ALIGNOF acts like in cxx_sizeof_or_alignof_type. */
tree
cxx_sizeof_or_alignof_expr (location_t loc, tree e, enum tree_code op,
- bool complain)
+ bool std_alignof, bool complain)
{
+ gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
if (op == SIZEOF_EXPR)
return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none);
else
- return cxx_alignof_expr (loc, e, complain? tf_warning_or_error : tf_none);
+ return cxx_alignof_expr (loc, e, std_alignof,
+ complain? tf_warning_or_error : tf_none);
}
/* Build a representation of an expression 'alignas(E).' Return the
@@ -2895,7 +2905,8 @@ access_failure_info::add_fixit_hint (rich_location *richloc,
tree accessor_decl)
{
pretty_printer pp;
- pp_printf (&pp, "%s()", IDENTIFIER_POINTER (DECL_NAME (accessor_decl)));
+ pp_string (&pp, IDENTIFIER_POINTER (DECL_NAME (accessor_decl)));
+ pp_string (&pp, "()");
richloc->add_fixit_replace (pp_formatted_text (&pp));
}
@@ -4062,7 +4073,7 @@ error_args_num (location_t loc, tree fndecl, bool too_many_p)
? G_("too many arguments to function %q#D")
: G_("too few arguments to function %q#D"),
fndecl);
- if (!DECL_IS_BUILTIN (fndecl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (fndecl))
inform (DECL_SOURCE_LOCATION (fndecl), "declared here");
}
else
@@ -4428,6 +4439,107 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
}
}
+/* Warn about [expr.arith.conv]/2: If one operand is of enumeration type and
+ the other operand is of a different enumeration type or a floating-point
+ type, this behavior is deprecated ([depr.arith.conv.enum]). CODE is the
+ code of the binary operation, TYPE0 and TYPE1 are the types of the operands,
+ and LOC is the location for the whole binary expression.
+ TODO: Consider combining this with -Wenum-compare in build_new_op_1. */
+
+static void
+do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
+ tree type1)
+{
+ if (TREE_CODE (type0) == ENUMERAL_TYPE
+ && TREE_CODE (type1) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (type0) != TYPE_MAIN_VARIANT (type1))
+ {
+ /* In C++20, -Wdeprecated-enum-enum-conversion is on by default.
+ Otherwise, warn if -Wenum-conversion is on. */
+ enum opt_code opt;
+ if (warn_deprecated_enum_enum_conv)
+ opt = OPT_Wdeprecated_enum_enum_conversion;
+ else if (warn_enum_conversion)
+ opt = OPT_Wenum_conversion;
+ else
+ return;
+
+ switch (code)
+ {
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ /* Comparisons are handled by -Wenum-compare. */
+ return;
+ case SPACESHIP_EXPR:
+ /* This is invalid, don't warn. */
+ return;
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ warning_at (loc, opt, "bitwise operation between different "
+ "enumeration types %qT and %qT is deprecated",
+ type0, type1);
+ return;
+ default:
+ warning_at (loc, opt, "arithmetic between different enumeration "
+ "types %qT and %qT is deprecated", type0, type1);
+ return;
+ }
+ }
+ else if ((TREE_CODE (type0) == ENUMERAL_TYPE
+ && TREE_CODE (type1) == REAL_TYPE)
+ || (TREE_CODE (type0) == REAL_TYPE
+ && TREE_CODE (type1) == ENUMERAL_TYPE))
+ {
+ const bool enum_first_p = TREE_CODE (type0) == ENUMERAL_TYPE;
+ /* In C++20, -Wdeprecated-enum-float-conversion is on by default.
+ Otherwise, warn if -Wenum-conversion is on. */
+ enum opt_code opt;
+ if (warn_deprecated_enum_float_conv)
+ opt = OPT_Wdeprecated_enum_float_conversion;
+ else if (warn_enum_conversion)
+ opt = OPT_Wenum_conversion;
+ else
+ return;
+
+ switch (code)
+ {
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ if (enum_first_p)
+ warning_at (loc, opt, "comparison of enumeration type %qT with "
+ "floating-point type %qT is deprecated",
+ type0, type1);
+ else
+ warning_at (loc, opt, "comparison of floating-point type %qT "
+ "with enumeration type %qT is deprecated",
+ type0, type1);
+ return;
+ case SPACESHIP_EXPR:
+ /* This is invalid, don't warn. */
+ return;
+ default:
+ if (enum_first_p)
+ warning_at (loc, opt, "arithmetic between enumeration type %qT "
+ "and floating-point type %qT is deprecated",
+ type0, type1);
+ else
+ warning_at (loc, opt, "arithmetic between floating-point type %qT "
+ "and enumeration type %qT is deprecated",
+ type0, type1);
+ return;
+ }
+ }
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the location_t of the operator in the source code.
@@ -5445,11 +5557,15 @@ cp_build_binary_op (const op_location_t &location,
{
result_type = cp_common_type (type0, type1);
if (complain & tf_warning)
- do_warn_double_promotion (result_type, type0, type1,
- "implicit conversion from %qH to %qI "
- "to match other operand of binary "
- "expression",
- location);
+ {
+ do_warn_double_promotion (result_type, type0, type1,
+ "implicit conversion from %qH to %qI "
+ "to match other operand of binary "
+ "expression",
+ location);
+ do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0),
+ TREE_TYPE (orig_op1));
+ }
}
if (code == SPACESHIP_EXPR)
@@ -5482,6 +5598,12 @@ cp_build_binary_op (const op_location_t &location,
arithmetic conversions are applied to the operands." So we don't do
arithmetic conversions if the operands both have enumeral type. */
result_type = NULL_TREE;
+ else if ((orig_code0 == ENUMERAL_TYPE && orig_code1 == REAL_TYPE)
+ || (orig_code0 == REAL_TYPE && orig_code1 == ENUMERAL_TYPE))
+ /* [depr.arith.conv.enum]: Three-way comparisons between such operands
+ [where one is of enumeration type and the other is of a different
+ enumeration type or a floating-point type] are ill-formed. */
+ result_type = NULL_TREE;
if (result_type)
{
@@ -5496,12 +5618,12 @@ cp_build_binary_op (const op_location_t &location,
type to a floating point type, the program is ill-formed. */
bool ok = true;
if (TREE_CODE (result_type) == REAL_TYPE
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op0)))
+ && CP_INTEGRAL_TYPE_P (orig_type0))
/* OK */;
else if (!check_narrowing (result_type, orig_op0, complain))
ok = false;
if (TREE_CODE (result_type) == REAL_TYPE
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op1)))
+ && CP_INTEGRAL_TYPE_P (orig_type1))
/* OK */;
else if (!check_narrowing (result_type, orig_op1, complain))
ok = false;
@@ -5863,7 +5985,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree ptrtype,
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
- if (!complete_type_or_else (target_type, NULL_TREE))
+ if (!complete_type_or_maybe_complain (target_type, NULL_TREE, complain))
return error_mark_node;
if (VOID_TYPE_P (target_type))
@@ -8739,7 +8861,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
LOOKUP_ONLYCONVERTING. */
newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
ICR_INIT, NULL_TREE, 0,
- complain);
+ complain | tf_no_cleanup);
else
newrhs = convert_for_assignment (olhstype, newrhs, ICR_ASSIGN,
NULL_TREE, 0, complain, LOOKUP_IMPLICIT);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e259a42..3fd2b17 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -123,123 +123,6 @@ cxx_readonly_error (location_t loc, tree arg, enum lvalue_use errstring)
readonly_error (loc, arg, errstring);
}
-/* Structure that holds information about declarations whose type was
- incomplete and we could not check whether it was abstract or not. */
-
-struct GTY((chain_next ("%h.next"), for_user)) pending_abstract_type {
- /* Declaration which we are checking for abstractness. It is either
- a DECL node, or an IDENTIFIER_NODE if we do not have a full
- declaration available. */
- tree decl;
-
- /* Type which will be checked for abstractness. */
- tree type;
-
- /* Kind of use in an unnamed declarator. */
- enum abstract_class_use use;
-
- /* Position of the declaration. This is only needed for IDENTIFIER_NODEs,
- because DECLs already carry locus information. */
- location_t locus;
-
- /* Link to the next element in list. */
- struct pending_abstract_type* next;
-};
-
-struct abstract_type_hasher : ggc_ptr_hash<pending_abstract_type>
-{
- typedef tree compare_type;
- static hashval_t hash (pending_abstract_type *);
- static bool equal (pending_abstract_type *, tree);
-};
-
-/* Compute the hash value of the node VAL. This function is used by the
- hash table abstract_pending_vars. */
-
-hashval_t
-abstract_type_hasher::hash (pending_abstract_type *pat)
-{
- return (hashval_t) TYPE_UID (pat->type);
-}
-
-
-/* Compare node VAL1 with the type VAL2. This function is used by the
- hash table abstract_pending_vars. */
-
-bool
-abstract_type_hasher::equal (pending_abstract_type *pat1, tree type2)
-{
- return (pat1->type == type2);
-}
-
-/* Hash table that maintains pending_abstract_type nodes, for which we still
- need to check for type abstractness. The key of the table is the type
- of the declaration. */
-static GTY (()) hash_table<abstract_type_hasher> *abstract_pending_vars = NULL;
-
-static int abstract_virtuals_error_sfinae (tree, tree, abstract_class_use, tsubst_flags_t);
-
-/* This function is called after TYPE is completed, and will check if there
- are pending declarations for which we still need to verify the abstractness
- of TYPE, and emit a diagnostic (through abstract_virtuals_error) if TYPE
- turned out to be incomplete. */
-
-void
-complete_type_check_abstract (tree type)
-{
- struct pending_abstract_type *pat;
- location_t cur_loc = input_location;
-
- gcc_assert (COMPLETE_TYPE_P (type));
-
- if (!abstract_pending_vars)
- return;
-
- /* Retrieve the list of pending declarations for this type. */
- pending_abstract_type **slot
- = abstract_pending_vars->find_slot_with_hash (type, TYPE_UID (type),
- NO_INSERT);
- if (!slot)
- return;
- pat = *slot;
- gcc_assert (pat);
-
- /* If the type is not abstract, do not do anything. */
- if (CLASSTYPE_PURE_VIRTUALS (type))
- {
- struct pending_abstract_type *prev = 0, *next;
-
- /* Reverse the list to emit the errors in top-down order. */
- for (; pat; pat = next)
- {
- next = pat->next;
- pat->next = prev;
- prev = pat;
- }
- pat = prev;
-
- /* Go through the list, and call abstract_virtuals_error for each
- element: it will issue a diagnostic if the type is abstract. */
- while (pat)
- {
- gcc_assert (type == pat->type);
-
- /* Tweak input_location so that the diagnostic appears at the correct
- location. Notice that this is only needed if the decl is an
- IDENTIFIER_NODE. */
- input_location = pat->locus;
- abstract_virtuals_error_sfinae (pat->decl, pat->type, pat->use,
- tf_warning_or_error);
- pat = pat->next;
- }
- }
-
- abstract_pending_vars->clear_slot (slot);
-
- input_location = cur_loc;
-}
-
-
/* If TYPE has abstract virtual functions, issue an error about trying
to create an object of that type. DECL is the object declared, or
NULL_TREE if the declaration is unavailable, in which case USE specifies
@@ -252,6 +135,13 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
{
vec<tree, va_gc> *pure;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ decl = NULL_TREE;
+ use = ACU_ARRAY;
+ type = strip_array_types (type);
+ }
+
/* This function applies only to classes. Any other entity can never
be abstract. */
if (!CLASS_TYPE_P (type))
@@ -266,38 +156,6 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
complete_type (type);
#endif
- /* If the type is incomplete, we register it within a hash table,
- so that we can check again once it is completed. This makes sense
- only for objects for which we have a declaration or at least a
- name. */
- if (!COMPLETE_TYPE_P (type) && (complain & tf_error))
- {
- struct pending_abstract_type *pat;
-
- gcc_assert (!decl || DECL_P (decl) || identifier_p (decl));
-
- if (!abstract_pending_vars)
- abstract_pending_vars
- = hash_table<abstract_type_hasher>::create_ggc (31);
-
- pending_abstract_type **slot
- = abstract_pending_vars->find_slot_with_hash (type, TYPE_UID (type),
- INSERT);
-
- pat = ggc_alloc<pending_abstract_type> ();
- pat->type = type;
- pat->decl = decl;
- pat->use = use;
- pat->locus = ((decl && DECL_P (decl))
- ? DECL_SOURCE_LOCATION (decl)
- : input_location);
-
- pat->next = *slot;
- *slot = pat;
-
- return 0;
- }
-
if (!TYPE_SIZE (type))
/* TYPE is being defined, and during that time
CLASSTYPE_PURE_VIRTUALS holds the inline friends. */
@@ -886,11 +744,13 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
{
bool const_init;
tree oldval = value;
- value = fold_non_dependent_expr (value, tf_warning_or_error, true, decl);
if (DECL_DECLARED_CONSTEXPR_P (decl)
|| (DECL_IN_AGGR_P (decl)
&& DECL_INITIALIZED_IN_CLASS_P (decl)))
{
+ value = fold_non_dependent_expr (value, tf_warning_or_error,
+ /*manifestly_const_eval=*/true,
+ decl);
/* Diagnose a non-constant initializer for constexpr variable or
non-inline in-class-initialized static data member. */
if (!require_constant_expression (value))
@@ -904,7 +764,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
value = cxx_constant_init (value, decl);
}
else
- value = maybe_constant_init (value, decl, true);
+ value = fold_non_dependent_init (value, tf_warning_or_error,
+ /*manifestly_const_eval=*/true, decl);
if (TREE_CODE (value) == CONSTRUCTOR && cp_has_mutable_p (type))
/* Poison this CONSTRUCTOR so it can't be copied to another
constexpr variable. */
@@ -948,13 +809,14 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
the bits that are constant, and then return an expression that
will perform the dynamic initialization. */
if (value != error_mark_node
+ && !processing_template_decl
&& (TREE_SIDE_EFFECTS (value)
|| vla_type_p (type)
|| ! reduced_constant_expression_p (value)))
return split_nonconstant_init (decl, value);
/* DECL may change value; purge caches. */
- clear_cv_and_fold_caches (TREE_STATIC (decl));
+ clear_cv_and_fold_caches ();
/* If the value is a constant, just put it in DECL_INITIAL. If DECL
is an automatic variable, the middle end will turn this into a
@@ -1288,6 +1150,7 @@ digest_init_r (tree type, tree init, int nested, int flags,
|| VECTOR_TYPE_P (type)
|| code == RECORD_TYPE
|| code == UNION_TYPE
+ || code == OPAQUE_TYPE
|| code == COMPLEX_TYPE);
/* "If T is a class type and the initializer list has a single
@@ -2594,6 +2457,3 @@ require_complete_eh_spec_types (tree fntype, tree decl)
}
}
}
-
-
-#include "gt-cp-typeck2.h"
diff --git a/gcc/cppbuiltin.c b/gcc/cppbuiltin.c
index 61efe9b..fc61c78 100644
--- a/gcc/cppbuiltin.c
+++ b/gcc/cppbuiltin.c
@@ -93,6 +93,9 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile)
if (flag_sanitize & SANITIZE_ADDRESS)
cpp_define (pfile, "__SANITIZE_ADDRESS__");
+ if (flag_sanitize & SANITIZE_HWADDRESS)
+ cpp_define (pfile, "__SANITIZE_HWADDRESS__");
+
if (flag_sanitize & SANITIZE_THREAD)
cpp_define (pfile, "__SANITIZE_THREAD__");
diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
index af38cc4..eb6f941 100644
--- a/gcc/cppdefault.c
+++ b/gcc/cppdefault.c
@@ -55,6 +55,11 @@ const struct default_include cpp_include_defaults[]
{ GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1,
GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
#endif
+#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR
+ /* Pick up libc++ include files, if we have -stdlib=libc++. */
+ { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1,
+ GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 },
+#endif
#ifdef GCC_INCLUDE_DIR
/* This is the dir for gcc's private headers. */
{ GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },
diff --git a/gcc/cppdefault.h b/gcc/cppdefault.h
index a681264..35cf24e 100644
--- a/gcc/cppdefault.h
+++ b/gcc/cppdefault.h
@@ -36,7 +36,12 @@ struct default_include
const char *const fname; /* The name of the directory. */
const char *const component; /* The component containing the directory
(see update_path in prefix.c) */
- const char cplusplus; /* Only look here if we're compiling C++. */
+ const char cplusplus; /* When this is non-zero, we should only
+ consider this if we're compiling C++.
+ When the -stdlib option is configured, this
+ may take values greater than 1 to indicate
+ which C++ standard library should be
+ used. */
const char cxx_aware; /* Includes in this directory don't need to
be wrapped in extern "C" when compiling
C++. */
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 2d7945c..f81880b2 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,122 @@
+2020-12-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-lang.cc (deps_add_target): Handle quoting ':' character.
+ Reimplement backslash tracking.
+
+2020-12-30 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-tree.h (d_eval_constant_expression): Add location argument.
+ * d-builtins.cc (d_eval_constant_expression): Give generated constants
+ a proper file location.
+ * d-compiler.cc (Compiler::paintAsType): Pass expression location to
+ d_eval_constant_expression.
+ * d-frontend.cc (eval_builtin): Likewise.
+
+2020-12-23 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/98427
+ * types.cc (TypeVisitor::visit (TypeStruct *)): Set TYPE_MODE of all
+ non-trivial types as BLKmode.
+ (TypeVisitor::visit (TypeClass *)): Likewise.
+
+2020-12-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/98277
+ * decl.cc (DeclVisitor::visit (VarDeclaration *)): Move setting of
+ DECL_INITIAL for manifest constants to ...
+ (get_symbol_decl): ... here.
+
+2020-11-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-target.def (d_minfo_section): New hook.
+ (d_minfo_start_name): New hook.
+ (d_minfo_end_name): New hook.
+ * modules.cc: Include d-target.h.
+ (register_moduleinfo): Update to use new targetdm hooks.
+
+2020-11-29 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/87788
+ * dmd/MERGE: Merge upsream dmd 45fa6cfd2.
+
+2020-11-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * dmd/MERGE: Merge upstream dmd db0df3f7e.
+ * types.cc (TypeVisitor::visit (TypeFunction *)): Remove LINKpascal.
+
+2020-11-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * intrinsics.cc (maybe_expand_intrinsic): Handle new intrinsics.
+ * intrinsics.def (INTRINSIC_COS): Add float and double overloads.
+ (INTRINSIC_FABS): Likewise.
+ (INTRINSIC_LDEXP): Likewise.
+ (INTRINSIC_RINT): Likewise.
+ (INTRINSIC_RNDTOL): Likewise.
+ (INTRINSIC_SIN): Likewise.
+ (INTRINSIC_TOPREC): Adjust signature.
+
+2020-11-22 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/97889
+ * expr.cc (ExprVisitor::visit (CatAssignExp *)): Enforce LTR order of
+ evaluation on left and right hand side expressions.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (d.serial): Change from goal to a variable.
+ (.PHONY): Drop d.serial and d.prev.
+ (d21$(exeext)): Depend on $(d.serial) rather than d.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (d.serial): New goal.
+ (.PHONY): Add d.serial d.prev.
+ (d21$(exeext)): Depend on d.prev. Call LINK_PROGRESS.
+
+2020-11-18 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/97843
+ * d-codegen.cc (build_assign): Evaluate TARGET_EXPR before use in
+ the right hand side of an assignment.
+ * expr.cc (ExprVisitor::visit (CatAssignExp *)): Force a TARGET_EXPR
+ on the element to append if it is a CALL_EXPR.
+
+2020-11-18 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/97842
+ * dmd/MERGE: Merge upstream dmd b6a779e49
+
+2020-11-13 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * intrinsics.cc (expand_intrinsic_copysign): Explicitly determine
+ which built-in copysign function to call.
+
+2020-11-13 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/97644
+ * dmd/MERGE: Merge upstream dmd 95044d8e4.
+ * d-target.cc (TargetCPP::thunkMangle): New function.
+ * decl.cc (finish_thunk): Don't force expand thunks for external
+ functions.
+ (make_thunk): Emit thunks only if the function has a definition.
+ Generate correct mangling for thunks to C++ classes.
+
+2020-11-10 Strager Neds <strager.nds@gmail.com>
+
+ * decl.cc (finish_thunk): Use new overload of
+ set_decl_section_name
+
+2020-10-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * dmd/MERGE: Merge upstream dmd bec5973b0.
+ * d-target.cc (Target::critsecsize): Remove.
+ * d-target.def: Remove d_critsec_size.
+
+2020-10-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * dmd/MERGE: Merge upstream dmd 0fcdaab32
+
2020-10-23 Jan Hubicka <hubicka@ucw.cz>
* decl.cc (finish_thunk): Update for new thunk api.
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 18d99ab..8c0c753 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -27,6 +27,7 @@ D_LIBPHOBOS = -DLIBPHOBOS=\"gphobos\"
# The name for selecting d in LANGUAGES.
d: d21$(exeext)
+d.serial = d21$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: d
@@ -162,9 +163,11 @@ D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_GENERATED_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
d_OBJS = $(D_ALL_OBJS) d/d-spec.o
-d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) $(d.prev)
+ @$(call LINK_PROGRESS,$(INDEX.d),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.d),end)
# Documentation.
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 72e2d3a..9c629c7 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -332,11 +332,12 @@ build_frontend_type (tree type)
}
/* Attempt to convert GCC evaluated CST to a D Frontend Expression.
+ LOC is the location in the source file where this CST is being evaluated.
This is used for getting the CTFE value out of a const-folded builtin,
returns NULL if it cannot convert CST. */
Expression *
-d_eval_constant_expression (tree cst)
+d_eval_constant_expression (const Loc &loc, tree cst)
{
STRIP_TYPE_NOPS (cst);
Type *type = build_frontend_type (TREE_TYPE (cst));
@@ -353,23 +354,23 @@ d_eval_constant_expression (tree cst)
real_value re = TREE_REAL_CST (TREE_REALPART (cst));
real_value im = TREE_REAL_CST (TREE_IMAGPART (cst));
complex_t value = complex_t (ldouble (re), ldouble (im));
- return ComplexExp::create (Loc (), value, type);
+ return ComplexExp::create (loc, value, type);
}
else if (code == INTEGER_CST)
{
dinteger_t value = TREE_INT_CST_LOW (cst);
- return IntegerExp::create (Loc (), value, type);
+ return IntegerExp::create (loc, value, type);
}
else if (code == REAL_CST)
{
real_value value = TREE_REAL_CST (cst);
- return RealExp::create (Loc (), ldouble (value), type);
+ return RealExp::create (loc, ldouble (value), type);
}
else if (code == STRING_CST)
{
const void *string = TREE_STRING_POINTER (cst);
size_t len = TREE_STRING_LENGTH (cst);
- return StringExp::create (Loc (), CONST_CAST (void *, string), len);
+ return StringExp::create (loc, CONST_CAST (void *, string), len);
}
else if (code == VECTOR_CST)
{
@@ -380,17 +381,17 @@ d_eval_constant_expression (tree cst)
for (size_t i = 0; i < nunits; i++)
{
Expression *elem
- = d_eval_constant_expression (VECTOR_CST_ELT (cst, i));
+ = d_eval_constant_expression (loc, VECTOR_CST_ELT (cst, i));
if (elem == NULL)
return NULL;
(*elements)[i] = elem;
}
- Expression *e = ArrayLiteralExp::create (Loc (), elements);
+ Expression *e = ArrayLiteralExp::create (loc, elements);
e->type = type->isTypeVector ()->basetype;
- return VectorExp::create (Loc (), e, type);
+ return VectorExp::create (loc, e, type);
}
}
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 1f2d65c..4c16f6a 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -1343,7 +1343,10 @@ build_assign (tree_code code, tree lhs, tree rhs)
since that would cause the LHS to be constructed twice.
So we force the TARGET_EXPR to be expanded without a target. */
if (code != INIT_EXPR)
- rhs = compound_expr (rhs, TARGET_EXPR_SLOT (rhs));
+ {
+ init = compound_expr (init, rhs);
+ rhs = TARGET_EXPR_SLOT (rhs);
+ }
else
{
d_mark_addressable (lhs);
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index ffa7f78..f737d8d 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -133,7 +133,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
cst = native_interpret_expr (vectype, buffer, len);
- Expression *e = d_eval_constant_expression (cst);
+ Expression *e = d_eval_constant_expression (expr->loc, cst);
gcc_assert (e != NULL && e->op == TOKvector);
return e->isVectorExp ()->e1;
@@ -143,7 +143,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
/* Normal interpret cast. */
cst = native_interpret_expr (build_ctype (type), buffer, len);
- Expression *e = d_eval_constant_expression (cst);
+ Expression *e = d_eval_constant_expression (expr->loc, cst);
gcc_assert (e != NULL);
return e;
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index da34e90..9133530 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -195,7 +195,7 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
/* Builtin should be successfully evaluated.
Will only return NULL if we can't convert it. */
if (TREE_CONSTANT (result) && TREE_CODE (result) != CALL_EXPR)
- e = d_eval_constant_expression (result);
+ e = d_eval_constant_expression (loc, result);
return e;
}
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index fb95716..f20d1f0 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -114,26 +114,35 @@ deps_add_target (const char *target, bool quoted)
}
/* Quote characters in target which are significant to Make. */
+ unsigned slashes = 0;
+
for (const char *p = target; *p != '\0'; p++)
{
switch (*p)
{
+ case '\\':
+ slashes++;
+ break;
+
case ' ':
case '\t':
- for (const char *q = p - 1; target <= q && *q == '\\'; q--)
+ while (slashes--)
obstack_1grow (&buffer, '\\');
obstack_1grow (&buffer, '\\');
- break;
+ goto Ldef;
case '$':
obstack_1grow (&buffer, '$');
- break;
+ goto Ldef;
case '#':
+ case ':':
obstack_1grow (&buffer, '\\');
- break;
+ goto Ldef;
default:
+ Ldef:
+ slashes = 0;
break;
}
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 78f1420..cd136524 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -202,16 +202,6 @@ Target::fieldalign (Type *type)
return align / BITS_PER_UNIT;
}
-/* Return size of OS critical section.
- Can't use the sizeof () calls directly since cross compiling is supported
- and would end up using the host sizes rather than the target sizes. */
-
-unsigned
-Target::critsecsize (void)
-{
- return targetdm.d_critsec_size ();
-}
-
/* Returns a Type for the va_list type of the target. */
Type *
@@ -339,6 +329,15 @@ TargetCPP::typeInfoMangle (ClassDeclaration *cd)
return cppTypeInfoMangleItanium (cd);
}
+/* Get mangle name of a this-adjusting thunk to the function declaration FD
+ at call offset OFFSET for C++ linkage. */
+
+const char *
+TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
+{
+ return cppThunkMangleItanium (fd, offset);
+}
+
/* For a vendor-specific type, return a string containing the C++ mangling.
In all other cases, return NULL. */
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index d641c74..728cba7 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,15 +46,30 @@ relating to the target operating system.",
void, (void),
hook_void_void)
-/* The sizeof CRITICAL_SECTION or pthread_mutex_t. */
-DEFHOOK
-(d_critsec_size,
- "Returns the size of the data structure used by the target operating system\n\
-for critical sections and monitors. For example, on Microsoft Windows this\n\
-would return the @code{sizeof(CRITICAL_SECTION)}, while other platforms that\n\
-implement pthreads would return @code{sizeof(pthread_mutex_t)}.",
- unsigned, (void),
- hook_uint_void_0)
+/* ModuleInfo section name and brackets. */
+DEFHOOKPOD
+(d_minfo_section,
+ "Contains the name of the section in which module info references should be\n\
+placed. This section is expected to be bracketed by two symbols to indicate\n\
+the start and end address of the section, so that the runtime library can\n\
+collect all modules for each loaded shared library and executable. The\n\
+default value of @code{NULL} disables the use of sections altogether.",
+ const char *, NULL)
+
+DEFHOOKPOD
+(d_minfo_start_name,
+ "If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined\n\
+as the name of the symbol indicating the start address of the module info\n\
+section",
+ const char *, NULL)
+
+/* The name of the ModuleInfo section. */
+DEFHOOKPOD
+(d_minfo_end_name,
+ "If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined\n\
+as the name of the symbol indicating the end address of the module info\n\
+section",
+ const char *, NULL)
/* Close the 'struct gcc_targetdm' definition. */
HOOK_VECTOR_END (C90_EMPTY_HACK)
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 31fe518..f5cf9d3 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -496,7 +496,7 @@ extern void d_init_builtins (void);
extern void d_register_builtin_type (tree, const char *);
extern void d_build_builtins_module (Module *);
extern void d_maybe_set_builtin (Module *);
-extern Expression *d_eval_constant_expression (tree);
+extern Expression *d_eval_constant_expression (const Loc &, tree);
extern void d_init_versions (void);
/* In d-codegen.cc. */
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 457894f..a3db4ae 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -653,31 +653,13 @@ public:
return;
}
- /* Do not store variables we cannot take the address of,
- but keep the values for purposes of debugging. */
if (!d->canTakeAddressOf ())
{
- /* Don't know if there is a good way to handle instantiations. */
- if (d->isInstantiated ())
- return;
-
- /* Cannot make an expression out of a void initializer. */
- if (!d->_init || d->_init->isVoidInitializer ())
- return;
-
- tree decl = get_symbol_decl (d);
- Expression *ie = initializerToExpression (d->_init);
-
- /* CONST_DECL was initially intended for enumerals and may be used for
- scalars in general, but not for aggregates. Here a non-constant
- value is generated anyway so as the CONST_DECL only serves as a
- placeholder for the value, however the DECL itself should never be
- referenced in any generated code, or passed to the back-end. */
+ /* Do not store variables we cannot take the address of,
+ but keep the values for purposes of debugging. */
if (!d->type->isscalar ())
- DECL_INITIAL (decl) = build_expr (ie, false);
- else
{
- DECL_INITIAL (decl) = build_expr (ie, true);
+ tree decl = get_symbol_decl (d);
d_pushdecl (decl);
rest_of_decl_compilation (decl, 1, 0);
}
@@ -1106,6 +1088,25 @@ get_symbol_decl (Declaration *decl)
if (vd->storage_class & STCextern)
DECL_EXTERNAL (decl->csym) = 1;
+
+ /* CONST_DECL was initially intended for enumerals and may be used for
+ scalars in general, but not for aggregates. Here a non-constant
+ value is generated anyway so as the CONST_DECL only serves as a
+ placeholder for the value, however the DECL itself should never be
+ referenced in any generated code, or passed to the back-end. */
+ if (vd->storage_class & STCmanifest)
+ {
+ /* Cannot make an expression out of a void initializer. */
+ if (vd->_init && !vd->_init->isVoidInitializer ())
+ {
+ Expression *ie = initializerToExpression (vd->_init);
+
+ if (!vd->type->isscalar ())
+ DECL_INITIAL (decl->csym) = build_expr (ie, false);
+ else
+ DECL_INITIAL (decl->csym) = build_expr (ie, true);
+ }
+ }
}
/* Set the declaration mangled identifier if static. */
@@ -1663,7 +1664,7 @@ finish_thunk (tree thunk, tree function)
resolve_unique_section (thunk, 0, flag_function_sections);
/* Output the thunk into the same section as function. */
- set_decl_section_name (thunk, DECL_SECTION_NAME (fn));
+ set_decl_section_name (thunk, fn);
symtab_node::get (thunk)->implicit_section
= symtab_node::get (fn)->implicit_section;
}
@@ -1693,26 +1694,6 @@ finish_thunk (tree thunk, tree function)
if (DECL_ONE_ONLY (function))
thunk_node->add_to_same_comdat_group (funcn);
-
- /* Target assemble_mi_thunk doesn't work across section boundaries
- on many targets, instead force thunk to be expanded in gimple. */
- if (DECL_EXTERNAL (function))
- {
- /* cgraph::expand_thunk writes over current_function_decl, so if this
- could ever be in use by the codegen pass, we want to know about it. */
- gcc_assert (current_function_decl == NULL_TREE);
-
- if (!stdarg_p (TREE_TYPE (thunk)))
- {
- thunk_node->create_edge (funcn, NULL, thunk_node->count);
- expand_thunk (thunk_node, false, true);
- }
-
- /* Tell the back-end to not bother inlining the function, this is
- assumed not to work as it could be referencing symbols outside
- of the current compilation unit. */
- DECL_UNINLINABLE (function) = 1;
- }
}
/* Return a thunk to DECL. Thunks adjust the incoming `this' pointer by OFFSET.
@@ -1789,12 +1770,11 @@ make_thunk (FuncDeclaration *decl, int offset)
DECL_CONTEXT (thunk) = d_decl_context (decl);
- /* Thunks inherit the public access of the function they are targetting.
- When the function is outside the current compilation unit however, then the
- thunk must be kept private to not conflict. */
- TREE_PUBLIC (thunk) = TREE_PUBLIC (function) && !DECL_EXTERNAL (function);
-
- DECL_EXTERNAL (thunk) = 0;
+ /* Thunks inherit the public access of the function they are targeting.
+ Thunks are connected to the definitions of the functions, so thunks are
+ not produced for external functions. */
+ TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
+ DECL_EXTERNAL (thunk) = DECL_EXTERNAL (function);
/* Thunks are always addressable. */
TREE_ADDRESSABLE (thunk) = 1;
@@ -1806,18 +1786,31 @@ make_thunk (FuncDeclaration *decl, int offset)
DECL_COMDAT (thunk) = DECL_COMDAT (function);
DECL_WEAK (thunk) = DECL_WEAK (function);
- tree target_name = DECL_ASSEMBLER_NAME (function);
- unsigned identlen = IDENTIFIER_LENGTH (target_name) + 14;
- const char *ident = XNEWVEC (const char, identlen);
- snprintf (CONST_CAST (char *, ident), identlen,
- "_DT%u%s", offset, IDENTIFIER_POINTER (target_name));
+ /* When the thunk is for an extern C++ function, let C++ do the thunk
+ generation and just reference the symbol as extern, instead of
+ forcing a D local thunk to be emitted. */
+ const char *ident;
+
+ if (decl->linkage == LINKcpp)
+ ident = target.cpp.thunkMangle (decl, offset);
+ else
+ {
+ tree target_name = DECL_ASSEMBLER_NAME (function);
+ unsigned identlen = IDENTIFIER_LENGTH (target_name) + 14;
+ ident = XNEWVEC (const char, identlen);
+
+ snprintf (CONST_CAST (char *, ident), identlen,
+ "_DTi%u%s", offset, IDENTIFIER_POINTER (target_name));
+ }
DECL_NAME (thunk) = get_identifier (ident);
SET_DECL_ASSEMBLER_NAME (thunk, DECL_NAME (thunk));
d_keep (thunk);
+ free (CONST_CAST (char *, ident));
- finish_thunk (thunk, function);
+ if (!DECL_EXTERNAL (function))
+ finish_thunk (thunk, function);
/* Add it to the list of thunks associated with the function. */
DECL_LANG_THUNKS (thunk) = NULL_TREE;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 5f6193f..1f695b9 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-70aabfb511d55f2bfbdccbac7868519d9d4b63da
+2bd4fc3fed8b8cd9760e77c6b2a1905cd84d0e70
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/cond.c b/gcc/d/dmd/cond.c
index beda133..9f76e83 100644
--- a/gcc/d/dmd/cond.c
+++ b/gcc/d/dmd/cond.c
@@ -705,6 +705,10 @@ int StaticIfCondition::include(Scope *sc)
sc = sc->push(sc->scopesym);
bool errors = false;
+
+ if (!exp)
+ goto Lerror;
+
bool result = evalStaticCondition(sc, exp, exp, errors);
sc->pop();
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c
index b361d37..3f571fc 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -582,13 +582,21 @@ class CppMangleVisitor : public Visitor
//printf("mangle_function(%s)\n", d->toChars());
/*
* <mangled-name> ::= _Z <encoding>
+ */
+ buf->writestring("_Z");
+ this->mangle_function_encoding(d);
+ }
+
+ void mangle_function_encoding(FuncDeclaration *d)
+ {
+ //printf("mangle_function_encoding(%s)\n", d->toChars());
+ /*
* <encoding> ::= <function name> <bare-function-type>
* ::= <data name>
* ::= <special-name>
*/
TypeFunction *tf = (TypeFunction *)d->type;
- buf->writestring("_Z");
if (getFuncTemplateDecl(d))
{
/* It's an instance of a function template
@@ -1132,3 +1140,13 @@ const char *cppTypeInfoMangleItanium(Dsymbol *s)
v.cpp_mangle_name(s, false);
return buf.extractChars();
}
+
+const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset)
+{
+ //printf("cppThunkMangleItanium(%s)\n", fd.toChars());
+ OutBuffer buf;
+ buf.printf("_ZThn%u_", offset); // "Th" means thunk, "n%u" is the call offset
+ CppMangleVisitor v(&buf, fd->loc);
+ v.mangle_function_encoding(fd);
+ return buf.extractChars();
+}
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index ea63bf3..f6eee52 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -10,6 +10,7 @@
#include "root/dsystem.h"
#include "root/root.h"
+#include "root/aav.h"
#include "mangle.h"
#include "init.h"
@@ -133,13 +134,114 @@ void MODtoDecoBuffer(OutBuffer *buf, MOD mod)
class Mangler : public Visitor
{
public:
+ AA *types;
+ AA *idents;
OutBuffer *buf;
Mangler(OutBuffer *buf)
{
+ this->types = NULL;
+ this->idents = NULL;
this->buf = buf;
}
+ /**
+ * writes a back reference with the relative position encoded with base 26
+ * using upper case letters for all digits but the last digit which uses
+ * a lower case letter.
+ * The decoder has to look up the referenced position to determine
+ * whether the back reference is an identifer (starts with a digit)
+ * or a type (starts with a letter).
+ *
+ * Params:
+ * pos = relative position to encode
+ */
+ void writeBackRef(size_t pos)
+ {
+ buf->writeByte('Q');
+ const size_t base = 26;
+ size_t mul = 1;
+ while (pos >= mul * base)
+ mul *= base;
+ while (mul >= base)
+ {
+ unsigned char dig = (unsigned char)(pos / mul);
+ buf->writeByte('A' + dig);
+ pos -= dig * mul;
+ mul /= base;
+ }
+ buf->writeByte('a' + (unsigned char)pos);
+ }
+
+ /**
+ * Back references a non-basic type
+ *
+ * The encoded mangling is
+ * 'Q' <relative position of first occurrence of type>
+ *
+ * Params:
+ * t = the type to encode via back referencing
+ *
+ * Returns:
+ * true if the type was found. A back reference has been encoded.
+ * false if the type was not found. The current position is saved for later back references.
+ */
+ bool backrefType(Type *t)
+ {
+ if (!t->isTypeBasic())
+ {
+ size_t *p = (size_t *)dmd_aaGet(&types, (void *)t);
+ if (*p)
+ {
+ writeBackRef(buf->length() - *p);
+ return true;
+ }
+ *p = buf->length();
+ }
+ return false;
+ }
+
+ /**
+ * Back references a single identifier
+ *
+ * The encoded mangling is
+ * 'Q' <relative position of first occurrence of type>
+ *
+ * Params:
+ * id = the identifier to encode via back referencing
+ *
+ * Returns:
+ * true if the identifier was found. A back reference has been encoded.
+ * false if the identifier was not found. The current position is saved for later back references.
+ */
+ bool backrefIdentifier(Identifier *id)
+ {
+ size_t *p = (size_t *)dmd_aaGet(&idents, (void *)id);
+ if (*p)
+ {
+ writeBackRef(buf->length() - *p);
+ return true;
+ }
+ *p = buf->length();
+ return false;
+ }
+
+ void mangleSymbol(Dsymbol *s)
+ {
+ s->accept(this);
+ }
+
+ void mangleType(Type *t)
+ {
+ if (!backrefType(t))
+ t->accept(this);
+ }
+
+ void mangleIdentifier(Identifier *id, Dsymbol *s)
+ {
+ if (!backrefIdentifier(id))
+ toBuffer(id->toChars(), s);
+ }
////////////////////////////////////////////////////////////////////////////
@@ -153,7 +255,7 @@ public:
{
MODtoDecoBuffer(buf, t->mod);
}
- t->accept(this);
+ mangleType(t);
}
void visit(Type *t)
@@ -207,8 +309,9 @@ public:
void mangleFuncType(TypeFunction *t, TypeFunction *ta, unsigned char modMask, Type *tret)
{
//printf("mangleFuncType() %s\n", t->toChars());
- if (t->inuse)
+ if (t->inuse && tret)
{
+ // printf("TypeFunction.mangleFuncType() t = %s inuse\n", t->toChars());
t->inuse = 2; // flag error to caller
return;
}
@@ -223,7 +326,6 @@ public:
case LINKd: mc = 'F'; break;
case LINKc: mc = 'U'; break;
case LINKwindows: mc = 'W'; break;
- case LINKpascal: mc = 'V'; break;
case LINKcpp: mc = 'R'; break;
case LINKobjc: mc = 'Y'; break;
default:
@@ -281,35 +383,29 @@ public:
void visit(TypeEnum *t)
{
visit((Type *)t);
- t->sym->accept(this);
+ mangleSymbol(t->sym);
}
void visit(TypeStruct *t)
{
//printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", t->toChars(), name);
visit((Type *)t);
- t->sym->accept(this);
+ mangleSymbol(t->sym);
}
void visit(TypeClass *t)
{
//printf("TypeClass::toDecoBuffer('%s' mod=%x) = '%s'\n", t->toChars(), mod, name);
visit((Type *)t);
- t->sym->accept(this);
+ mangleSymbol(t->sym);
}
void visit(TypeTuple *t)
{
//printf("TypeTuple::toDecoBuffer() t = %p, %s\n", t, t->toChars());
visit((Type *)t);
-
- OutBuffer buf2;
- buf2.reserve(32);
- Mangler v(&buf2);
- v.paramsToDecoBuffer(t->arguments);
- const char *s = buf2.peekChars();
- int len = (int)buf2.length();
- buf->printf("%d%.*s", len, len, s);
+ paramsToDecoBuffer(t->arguments);
+ buf->writeByte('Z');
}
void visit(TypeNull *t)
@@ -324,16 +420,14 @@ public:
mangleParent(sthis);
assert(sthis->ident);
- const char *id = sthis->ident->toChars();
- toBuffer(id, sthis);
-
+ mangleIdentifier(sthis->ident, sthis);
if (FuncDeclaration *fd = sthis->isFuncDeclaration())
{
mangleFunc(fd, false);
}
- else if (sthis->type->deco)
+ else if (sthis->type)
{
- buf->writestring(sthis->type->deco);
+ visitWithMask(sthis->type, 0);
}
else
assert(0);
@@ -350,12 +444,14 @@ public:
if (p)
{
mangleParent(p);
-
- if (p->getIdent())
+ TemplateInstance *ti = p->isTemplateInstance();
+ if (ti && !ti->isTemplateMixin())
{
- const char *id = p->ident->toChars();
- toBuffer(id, s);
-
+ mangleTemplateInstance(ti);
+ }
+ else if (p->getIdent())
+ {
+ mangleIdentifier(p->ident, s);
if (FuncDeclaration *f = p->isFuncDeclaration())
mangleFunc(f, true);
}
@@ -376,13 +472,13 @@ public:
TypeFunction *tfo = (TypeFunction *)fd->originalType;
mangleFuncType(tf, tfo, 0, NULL);
}
- else if (fd->type->deco)
+ else if (fd->type)
{
- buf->writestring(fd->type->deco);
+ visitWithMask(fd->type, 0);
}
else
{
- printf("[%s] %s %s\n", fd->loc.toChars(), fd->toChars(), fd->type->toChars());
+ printf("[%s] %s no type\n", fd->loc.toChars(), fd->toChars());
assert(0); // don't mangle function until semantic3 done.
}
}
@@ -393,8 +489,8 @@ public:
void toBuffer(const char *id, Dsymbol *s)
{
size_t len = strlen(id);
- if (len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
- s->error("excessive length %llu for symbol, possible recursive expansion?", len);
+ if (buf->length() + len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
+ s->error("excessive length %llu for symbol, possible recursive expansion?", buf->length() + len);
else
{
buf->printf("%llu", (ulonglong)len);
@@ -402,40 +498,40 @@ public:
}
}
- void visit(Declaration *d)
+ static const char *externallyMangledIdentifier(Declaration *d)
{
- //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
- // d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope
{
switch (d->linkage)
{
case LINKd:
break;
-
case LINKc:
case LINKwindows:
- case LINKpascal:
case LINKobjc:
- buf->writestring(d->ident->toChars());
- return;
-
+ return d->ident->toChars();
case LINKcpp:
- buf->writestring(target.cpp.toMangle(d));
- return;
-
+ return target.cpp.toMangle(d);
case LINKdefault:
d->error("forward declaration");
- buf->writestring(d->ident->toChars());
- return;
-
+ return d->ident->toChars();
default:
fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage);
assert(0);
- return;
}
}
+ return NULL;
+ }
+ void visit(Declaration *d)
+ {
+ //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
+ // d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
+ if (const char *id = externallyMangledIdentifier(d))
+ {
+ buf->writestring(id);
+ return;
+ }
buf->writestring("_D");
mangleDecl(d);
}
@@ -483,7 +579,7 @@ public:
}
if (fa)
{
- fa->accept(this);
+ mangleSymbol(fa);
return;
}
visit((Dsymbol *)fd);
@@ -509,7 +605,7 @@ public:
{
if (!od->hasOverloads || td->overnext == NULL)
{
- td->accept(this);
+ mangleSymbol(td);
return;
}
}
@@ -588,20 +684,131 @@ public:
else
mangleParent(ti);
- ti->getIdent();
- const char *id = ti->ident ? ti->ident->toChars() : ti->toChars();
- toBuffer(id, ti);
+ if (ti->isTemplateMixin() && ti->ident)
+ mangleIdentifier(ti->ident, ti);
+ else
+ mangleTemplateInstance(ti);
+ }
+
+ void mangleTemplateInstance(TemplateInstance *ti)
+ {
+ TemplateDeclaration *tempdecl = ti->tempdecl->isTemplateDeclaration();
+ assert(tempdecl);
+
+ // Use "__U" for the symbols declared inside template constraint.
+ const char T = ti->members ? 'T' : 'U';
+ buf->printf("__%c", T);
+ mangleIdentifier(tempdecl->ident, tempdecl);
- //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id);
+ Objects *args = ti->tiargs;
+ size_t nparams = tempdecl->parameters->length - (tempdecl->isVariadic() ? 1 : 0);
+ for (size_t i = 0; i < args->length; i++)
+ {
+ RootObject *o = (*args)[i];
+ Type *ta = isType(o);
+ Expression *ea = isExpression(o);
+ Dsymbol *sa = isDsymbol(o);
+ Tuple *va = isTuple(o);
+ //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
+ if (i < nparams && (*tempdecl->parameters)[i]->specialization())
+ buf->writeByte('H'); // https://issues.dlang.org/show_bug.cgi?id=6574
+ if (ta)
+ {
+ buf->writeByte('T');
+ visitWithMask(ta, 0);
+ }
+ else if (ea)
+ {
+ // Don't interpret it yet, it might actually be an alias template parameter.
+ // Only constfold manifest constants, not const/immutable lvalues, see https://issues.dlang.org/show_bug.cgi?id=17339.
+ const bool keepLvalue = true;
+ ea = ea->optimize(WANTvalue, keepLvalue);
+ if (ea->op == TOKvar)
+ {
+ sa = ((VarExp *)ea)->var;
+ ea = NULL;
+ goto Lsa;
+ }
+ if (ea->op == TOKthis)
+ {
+ sa = ((ThisExp *)ea)->var;
+ ea = NULL;
+ goto Lsa;
+ }
+ if (ea->op == TOKfunction)
+ {
+ if (((FuncExp *)ea)->td)
+ sa = ((FuncExp *)ea)->td;
+ else
+ sa = ((FuncExp *)ea)->fd;
+ ea = NULL;
+ goto Lsa;
+ }
+ buf->writeByte('V');
+ if (ea->op == TOKtuple)
+ {
+ ea->error("tuple is not a valid template value argument");
+ continue;
+ }
+ // Now that we know it is not an alias, we MUST obtain a value
+ unsigned olderr = global.errors;
+ ea = ea->ctfeInterpret();
+ if (ea->op == TOKerror || olderr != global.errors)
+ continue;
+
+ /* Use type mangling that matches what it would be for a function parameter
+ */
+ visitWithMask(ea->type, 0);
+ ea->accept(this);
+ }
+ else if (sa)
+ {
+ Lsa:
+ sa = sa->toAlias();
+ if (Declaration *d = sa->isDeclaration())
+ {
+ if (FuncAliasDeclaration *fad = d->isFuncAliasDeclaration())
+ d = fad->toAliasFunc();
+ if (d->mangleOverride.length)
+ {
+ buf->writeByte('X');
+ toBuffer(d->mangleOverride.ptr, d);
+ continue;
+ }
+ if (const char *id = externallyMangledIdentifier(d))
+ {
+ buf->writeByte('X');
+ toBuffer(id, d);
+ continue;
+ }
+ if (!d->type || !d->type->deco)
+ {
+ ti->error("forward reference of %s %s", d->kind(), d->toChars());
+ continue;
+ }
+ }
+ buf->writeByte('S');
+ mangleSymbol(sa);
+ }
+ else if (va)
+ {
+ assert(i + 1 == args->length); // must be last one
+ args = &va->objects;
+ i = -(size_t)1;
+ }
+ else
+ assert(0);
+ }
+ buf->writeByte('Z');
}
void visit(Dsymbol *s)
{
mangleParent(s);
-
- const char *id = s->ident ? s->ident->toChars() : s->toChars();
- toBuffer(id, s);
-
+ if (s->ident)
+ mangleIdentifier(s->ident, s);
+ else
+ toBuffer(s->toChars(), s);
//printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
}
@@ -861,3 +1068,9 @@ void mangleToBuffer(Dsymbol *s, OutBuffer *buf)
Mangler v(buf);
s->accept(&v);
}
+
+void mangleToBuffer(TemplateInstance *ti, OutBuffer *buf)
+{
+ Mangler v(buf);
+ v.mangleTemplateInstance(ti);
+}
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index a86daee..fe65bd2 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -33,6 +33,7 @@
#include "hdrgen.h"
#include "id.h"
#include "attrib.h"
+#include "cond.h"
#include "tokens.h"
#define IDX_NOTFOUND (0x12345678) // index is not found
@@ -6088,17 +6089,18 @@ Lerror:
if (minst && minst->isRoot() && !(inst->minst && inst->minst->isRoot()))
{
/* Swap the position of 'inst' and 'this' in the instantiation graph.
- * Then, the primary instance `inst` will be changed to a root instance.
+ * Then, the primary instance `inst` will be changed to a root instance,
+ * along with all members of `inst` having their scopes updated.
*
* Before:
- * non-root -> A!() -> B!()[inst] -> C!()
+ * non-root -> A!() -> B!()[inst] -> C!() { members[non-root] }
* |
* root -> D!() -> B!()[this]
*
* After:
* non-root -> A!() -> B!()[this]
* |
- * root -> D!() -> B!()[inst] -> C!()
+ * root -> D!() -> B!()[inst] -> C!() { members[root] }
*/
Module *mi = minst;
TemplateInstance *ti = tinst;
@@ -6107,6 +6109,64 @@ Lerror:
inst->minst = mi;
inst->tinst = ti;
+ /* https://issues.dlang.org/show_bug.cgi?id=21299
+ `minst` has been updated on the primary instance `inst` so it is
+ now coming from a root module, however all Dsymbol `inst.members`
+ of the instance still have their `_scope.minst` pointing at the
+ original non-root module. We must now propagate `minst` to all
+ members so that forward referenced dependencies that get
+ instantiated will also be appended to the root module, otherwise
+ there will be undefined references at link-time. */
+ class InstMemberWalker : public Visitor
+ {
+ public:
+ TemplateInstance *inst;
+
+ InstMemberWalker(TemplateInstance *inst)
+ : inst(inst) { }
+
+ void visit(Dsymbol *d)
+ {
+ if (d->_scope)
+ d->_scope->minst = inst->minst;
+ }
+
+ void visit(ScopeDsymbol *sds)
+ {
+ if (!sds->members)
+ return;
+ for (size_t i = 0; i < sds->members->length; i++)
+ {
+ Dsymbol *s = (*sds->members)[i];
+ s->accept(this);
+ }
+ visit((Dsymbol *)sds);
+ }
+
+ void visit(AttribDeclaration *ad)
+ {
+ Dsymbols *d = ad->include(NULL);
+ if (!d)
+ return;
+ for (size_t i = 0; i < d->length; i++)
+ {
+ Dsymbol *s = (*d)[i];
+ s->accept(this);
+ }
+ visit((Dsymbol *)ad);
+ }
+
+ void visit(ConditionalDeclaration *cd)
+ {
+ if (cd->condition->inc)
+ visit((AttribDeclaration *)cd);
+ else
+ visit((Dsymbol *)cd);
+ }
+ };
+ InstMemberWalker v(inst);
+ inst->accept(&v);
+
if (minst) // if inst was not speculative
{
/* Add 'inst' once again to the root module members[], then the
@@ -7486,122 +7546,12 @@ Dsymbols *TemplateInstance::appendToModuleMember()
Identifier *TemplateInstance::genIdent(Objects *args)
{
- TemplateDeclaration *tempdecl = this->tempdecl->isTemplateDeclaration();
- assert(tempdecl);
-
//printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
+ assert(args == tiargs);
OutBuffer buf;
- const char *id = tempdecl->ident->toChars();
- if (!members)
- {
- // Use "__U" for the symbols declared inside template constraint.
- buf.printf("__U%llu%s", (ulonglong)strlen(id), id);
- }
- else
- buf.printf("__T%llu%s", (ulonglong)strlen(id), id);
- size_t nparams = tempdecl->parameters->length - (tempdecl->isVariadic() ? 1 : 0);
- for (size_t i = 0; i < args->length; i++)
- {
- RootObject *o = (*args)[i];
- Type *ta = isType(o);
- Expression *ea = isExpression(o);
- Dsymbol *sa = isDsymbol(o);
- Tuple *va = isTuple(o);
- //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
- if (i < nparams && (*tempdecl->parameters)[i]->specialization())
- buf.writeByte('H'); // Bugzilla 6574
- if (ta)
- {
- buf.writeByte('T');
- if (ta->deco)
- buf.writestring(ta->deco);
- else
- {
- assert(global.errors);
- }
- }
- else if (ea)
- {
- // Don't interpret it yet, it might actually be an alias template parameter.
- // Only constfold manifest constants, not const/immutable lvalues, see https://issues.dlang.org/show_bug.cgi?id=17339.
- const bool keepLvalue = true;
- ea = ea->optimize(WANTvalue, keepLvalue);
- if (ea->op == TOKvar)
- {
- sa = ((VarExp *)ea)->var;
- ea = NULL;
- goto Lsa;
- }
- if (ea->op == TOKthis)
- {
- sa = ((ThisExp *)ea)->var;
- ea = NULL;
- goto Lsa;
- }
- if (ea->op == TOKfunction)
- {
- if (((FuncExp *)ea)->td)
- sa = ((FuncExp *)ea)->td;
- else
- sa = ((FuncExp *)ea)->fd;
- ea = NULL;
- goto Lsa;
- }
- buf.writeByte('V');
- if (ea->op == TOKtuple)
- {
- ea->error("tuple is not a valid template value argument");
- continue;
- }
- // Now that we know it is not an alias, we MUST obtain a value
- unsigned olderr = global.errors;
- ea = ea->ctfeInterpret();
- if (ea->op == TOKerror || olderr != global.errors)
- continue;
-
- /* Use deco that matches what it would be for a function parameter
- */
- buf.writestring(ea->type->deco);
- mangleToBuffer(ea, &buf);
- }
- else if (sa)
- {
- Lsa:
- buf.writeByte('S');
- sa = sa->toAlias();
- Declaration *d = sa->isDeclaration();
- if (d && (!d->type || !d->type->deco))
- {
- error("forward reference of %s %s", d->kind(), d->toChars());
- continue;
- }
-
- OutBuffer bufsa;
- mangleToBuffer(sa, &bufsa);
- const char *s = bufsa.extractChars();
-
- /* Bugzilla 3043: if the first character of s is a digit this
- * causes ambiguity issues because the digits of the two numbers are adjacent.
- * Current demanglers resolve this by trying various places to separate the
- * numbers until one gets a successful demangle.
- * Unfortunately, fixing this ambiguity will break existing binary
- * compatibility and the demanglers, so we'll leave it as is.
- */
- buf.printf("%u%s", (unsigned)strlen(s), s);
- }
- else if (va)
- {
- assert(i + 1 == args->length); // must be last one
- args = &va->objects;
- i = -(size_t)1;
- }
- else
- assert(0);
- }
- buf.writeByte('Z');
- id = buf.peekChars();
+ mangleToBuffer(this, &buf);
//printf("\tgenIdent = %s\n", id);
- return Identifier::idPool(id);
+ return Identifier::idPool(buf.peekChars());
}
/*************************************
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index 2ad75ed..09dd3af 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -4340,7 +4340,7 @@ Expression *ArrayLiteralExp::syntaxCopy()
arraySyntaxCopy(elements));
}
-Expression *ArrayLiteralExp::getElement(d_size_t i)
+Expression *ArrayLiteralExp::getElement(size_t i)
{
Expression *el = (*elements)[i];
if (!el)
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index fde029c..ccfaa65 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -523,7 +523,7 @@ public:
static ArrayLiteralExp *create(Loc loc, Expressions *elements);
Expression *syntaxCopy();
bool equals(RootObject *o);
- Expression *getElement(d_size_t i);
+ Expression *getElement(size_t i);
static Expressions* copyElements(Expression *e1, Expression *e2 = NULL);
bool isBool(bool result);
StringExp *toStringExp();
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 9d6e1ec..6aff9b4 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -310,7 +310,6 @@ enum LINK
LINKc,
LINKcpp,
LINKwindows,
- LINKpascal,
LINKobjc,
LINKsystem
};
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index 22ae9c8..fd4d162 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -1271,7 +1271,6 @@ public:
case LINKc: p = "C"; break;
case LINKcpp: p = "C++"; break;
case LINKwindows: p = "Windows"; break;
- case LINKpascal: p = "Pascal"; break;
case LINKobjc: p = "Objective-C"; break;
default:
assert(0);
@@ -3367,7 +3366,6 @@ const char *linkageToChars(LINK linkage)
case LINKc: return "C";
case LINKcpp: return "C++";
case LINKwindows: return "Windows";
- case LINKpascal: return "Pascal";
case LINKobjc: return "Objective-C";
case LINKsystem: return "System";
default: assert(0);
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index 2944a79..16f3b5f 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -145,7 +145,6 @@ Msgtable msgtable[] =
{ "C", NULL },
{ "D", NULL },
{ "Windows", NULL },
- { "Pascal", NULL },
{ "System", NULL },
{ "Objective", NULL },
@@ -262,7 +261,7 @@ Msgtable msgtable[] =
{ "aaRehash", "_aaRehash" },
{ "monitorenter", "_d_monitorenter" },
{ "monitorexit", "_d_monitorexit" },
- { "criticalenter", "_d_criticalenter" },
+ { "criticalenter", "_d_criticalenter2" },
{ "criticalexit", "_d_criticalexit" },
{ "__ArrayEq", NULL },
{ "__ArrayPostblit", NULL },
diff --git a/gcc/d/dmd/json.c b/gcc/d/dmd/json.c
index 7da127e..802de81 100644
--- a/gcc/d/dmd/json.c
+++ b/gcc/d/dmd/json.c
@@ -323,9 +323,6 @@ public:
case LINKwindows:
property(name, "windows");
break;
- case LINKpascal:
- property(name, "pascal");
- break;
default:
assert(false);
}
diff --git a/gcc/d/dmd/mangle.h b/gcc/d/dmd/mangle.h
index 77801ab..c60f4a7 100644
--- a/gcc/d/dmd/mangle.h
+++ b/gcc/d/dmd/mangle.h
@@ -20,6 +20,7 @@ struct OutBuffer;
// In cppmangle.c
const char *toCppMangleItanium(Dsymbol *s);
const char *cppTypeInfoMangleItanium(Dsymbol *s);
+const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset);
// In cppmanglewin.c
const char *toCppMangleMSVC(Dsymbol *s);
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index bc66be0..6f0195a 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -7418,6 +7418,12 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
//printf("TypeTypeof::resolve(sc = %p, idents = '%s')\n", sc, toChars());
//static int nest; if (++nest == 50) *(char*)0=0;
+ if (sc == NULL)
+ {
+ *pt = Type::terror;
+ error(loc, "Invalid scope.");
+ return;
+ }
if (inuse)
{
inuse = 2;
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 4e28dea..b0878c8 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -12,7 +12,6 @@
#include "root/root.h"
#include "root/stringtable.h"
-#include "root/dcompat.h" // for d_size_t
#include "arraytypes.h"
#include "ast_node.h"
@@ -635,7 +634,7 @@ public:
static Parameters *arraySyntaxCopy(Parameters *parameters);
static size_t dim(Parameters *parameters);
- static Parameter *getNth(Parameters *parameters, d_size_t nth, d_size_t *pn = NULL);
+ static Parameter *getNth(Parameters *parameters, size_t nth, size_t *pn = NULL);
const char *toChars();
bool isCovariant(bool returnByRef, const Parameter *p) const;
static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to);
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index d1017ac..3e4dd06 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -1294,8 +1294,6 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pc
nextToken();
if (id == Id::Windows)
link = LINKwindows;
- else if (id == Id::Pascal)
- link = LINKpascal;
else if (id == Id::D)
link = LINKd;
else if (id == Id::C)
@@ -1399,7 +1397,7 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pc
else
{
LinvalidLinkage:
- error("valid linkage identifiers are D, C, C++, Objective-C, Pascal, Windows, System");
+ error("valid linkage identifiers are D, C, C++, Objective-C, Windows, System");
link = LINKd;
}
}
diff --git a/gcc/d/dmd/root/array.h b/gcc/d/dmd/root/array.h
index fb838e6..d4eccd8 100644
--- a/gcc/d/dmd/root/array.h
+++ b/gcc/d/dmd/root/array.h
@@ -16,7 +16,7 @@
template <typename TYPE>
struct Array
{
- d_size_t length;
+ size_t length;
private:
DArray<TYPE> data;
@@ -42,8 +42,8 @@ struct Array
char *toChars() const
{
const char **buf = (const char **)mem.xmalloc(length * sizeof(const char *));
- d_size_t len = 2;
- for (d_size_t u = 0; u < length; u++)
+ size_t len = 2;
+ for (size_t u = 0; u < length; u++)
{
buf[u] = ((RootObject *)data.ptr[u])->toChars();
len += strlen(buf[u]) + 1;
@@ -52,7 +52,7 @@ struct Array
str[0] = '[';
char *p = str + 1;
- for (d_size_t u = 0; u < length; u++)
+ for (size_t u = 0; u < length; u++)
{
if (u)
*p++ = ',';
@@ -77,7 +77,7 @@ struct Array
insert(length, a);
}
- void reserve(d_size_t nentries)
+ void reserve(size_t nentries)
{
//printf("Array::reserve: length = %d, data.length = %d, nentries = %d\n", (int)length, (int)data.length, (int)nentries);
if (data.length - length < nentries)
@@ -106,7 +106,7 @@ struct Array
{
/* Increase size by 1.5x to avoid excessive memory fragmentation
*/
- d_size_t increment = length / 2;
+ size_t increment = length / 2;
if (nentries > increment) // if 1.5 is not enough
increment = nentries;
data.length = length + increment;
@@ -115,18 +115,18 @@ struct Array
}
}
- void remove(d_size_t i)
+ void remove(size_t i)
{
if (length - i - 1)
memmove(data.ptr + i, data.ptr + i + 1, (length - i - 1) * sizeof(TYPE));
length--;
}
- void insert(d_size_t index, Array *a)
+ void insert(size_t index, Array *a)
{
if (a)
{
- d_size_t d = a->length;
+ size_t d = a->length;
reserve(d);
if (length != index)
memmove(data.ptr + index + d, data.ptr + index, (length - index) * sizeof(TYPE));
@@ -135,7 +135,7 @@ struct Array
}
}
- void insert(d_size_t index, TYPE ptr)
+ void insert(size_t index, TYPE ptr)
{
reserve(1);
memmove(data.ptr + index + 1, data.ptr + index, (length - index) * sizeof(TYPE));
@@ -143,7 +143,7 @@ struct Array
length++;
}
- void setDim(d_size_t newdim)
+ void setDim(size_t newdim)
{
if (length < newdim)
{
@@ -152,9 +152,9 @@ struct Array
length = newdim;
}
- d_size_t find(TYPE ptr) const
+ size_t find(TYPE ptr) const
{
- for (d_size_t i = 0; i < length; i++)
+ for (size_t i = 0; i < length; i++)
{
if (data.ptr[i] == ptr)
return i;
@@ -167,7 +167,7 @@ struct Array
return find(ptr) != SIZE_MAX;
}
- TYPE& operator[] (d_size_t index)
+ TYPE& operator[] (size_t index)
{
#ifdef DEBUG
assert(index < length);
diff --git a/gcc/d/dmd/root/bitarray.h b/gcc/d/dmd/root/bitarray.h
index fa01dd9..195e3be 100644
--- a/gcc/d/dmd/root/bitarray.h
+++ b/gcc/d/dmd/root/bitarray.h
@@ -24,8 +24,8 @@ struct BitArray
mem.xfree(ptr);
}
- d_size_t len;
- d_size_t *ptr;
+ size_t len;
+ size_t *ptr;
private:
BitArray(const BitArray&);
diff --git a/gcc/d/dmd/root/dcompat.h b/gcc/d/dmd/root/dcompat.h
index 72326d5..5aec84e 100644
--- a/gcc/d/dmd/root/dcompat.h
+++ b/gcc/d/dmd/root/dcompat.h
@@ -34,15 +34,3 @@ struct DString : public DArray<const char>
DString(size_t length, const char *ptr)
: DArray<const char>(length, ptr) { }
};
-
-/// Corresponding C++ type that maps to D size_t
-#if __APPLE__ && __i386__
-// size_t is 'unsigned long', which makes it mangle differently than D's 'uint'
-typedef unsigned d_size_t;
-#elif MARS && DMD_VERSION >= 2079 && DMD_VERSION <= 2081 && \
- __APPLE__ && __SIZEOF_SIZE_T__ == 8
-// DMD versions between 2.079 and 2.081 mapped D ulong to uint64_t on OS X.
-typedef uint64_t d_size_t;
-#else
-typedef size_t d_size_t;
-#endif
diff --git a/gcc/d/dmd/root/outbuffer.h b/gcc/d/dmd/root/outbuffer.h
index 49b1c3e5..2ff5ee9 100644
--- a/gcc/d/dmd/root/outbuffer.h
+++ b/gcc/d/dmd/root/outbuffer.h
@@ -39,13 +39,13 @@ public:
mem.xfree(data.ptr);
}
const DArray<unsigned char> slice() const { return data; }
- d_size_t length() const { return offset; }
+ size_t length() const { return offset; }
char *extractData();
void reserve(size_t nbytes);
void setsize(size_t size);
void reset();
- void write(const void *data, d_size_t nbytes);
+ void write(const void *data, size_t nbytes);
void writestring(const char *string);
void prependstring(const char *string);
void writenl(); // write newline
diff --git a/gcc/d/dmd/root/rmem.h b/gcc/d/dmd/root/rmem.h
index 7f5e980..fdb8676 100644
--- a/gcc/d/dmd/root/rmem.h
+++ b/gcc/d/dmd/root/rmem.h
@@ -8,18 +8,18 @@
#pragma once
-#include "dcompat.h" // for d_size_t
+#include "dsystem.h" // for size_t
struct Mem
{
Mem() { }
static char *xstrdup(const char *s);
- static void *xmalloc(d_size_t size);
- static void *xcalloc(d_size_t size, d_size_t n);
- static void *xrealloc(void *p, d_size_t size);
+ static void *xmalloc(size_t size);
+ static void *xcalloc(size_t size, size_t n);
+ static void *xrealloc(void *p, size_t size);
static void xfree(void *p);
- static void *xmallocdup(void *o, d_size_t size);
+ static void *xmallocdup(void *o, size_t size);
static void error();
};
diff --git a/gcc/d/dmd/root/stringtable.h b/gcc/d/dmd/root/stringtable.h
index 7df5c87..8cbdbd8 100644
--- a/gcc/d/dmd/root/stringtable.h
+++ b/gcc/d/dmd/root/stringtable.h
@@ -9,7 +9,6 @@
#pragma once
#include "root.h"
-#include "dcompat.h" // for d_size_t
struct StringEntry;
@@ -40,13 +39,13 @@ private:
size_t count;
public:
- void _init(d_size_t size = 0);
- void reset(d_size_t size = 0);
+ void _init(size_t size = 0);
+ void reset(size_t size = 0);
~StringTable();
- StringValue *lookup(const char *s, d_size_t len);
+ StringValue *lookup(const char *s, size_t len);
StringValue *insert(const char *s, size_t len, void *ptrvalue);
- StringValue *update(const char *s, d_size_t len);
+ StringValue *update(const char *s, size_t len);
int apply(int (*fp)(StringValue *));
private:
diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c
index 42f885d..4ff07f6 100644
--- a/gcc/d/dmd/statementsem.c
+++ b/gcc/d/dmd/statementsem.c
@@ -3213,14 +3213,15 @@ public:
else
{
/* Generate our own critical section, then rewrite as:
- * __gshared byte[CriticalSection.sizeof] critsec;
- * _d_criticalenter(critsec.ptr);
- * try { body } finally { _d_criticalexit(critsec.ptr); }
+ * __gshared void* __critsec;
+ * _d_criticalenter2(&__critsec);
+ * try { body } finally { _d_criticalexit(__critsec); }
*/
Identifier *id = Identifier::generateId("__critsec");
- Type *t = Type::tint8->sarrayOf(target.ptrsize + target.critsecsize());
+ Type *t = Type::tvoidptr;
VarDeclaration *tmp = new VarDeclaration(ss->loc, t, id, NULL);
tmp->storage_class |= STCtemp | STCgshared | STCstatic;
+ Expression *tmpExp = new VarExp(ss->loc, tmp);
Statements *cs = new Statements();
cs->push(new ExpStatement(ss->loc, tmp));
@@ -3236,15 +3237,14 @@ public:
args->push(new Parameter(0, t->pointerTo(), NULL, NULL));
FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter, STCnothrow);
- Expression *e = new DotIdExp(ss->loc, new VarExp(ss->loc, tmp), Id::ptr);
+ Expression *e = new AddrExp(ss->loc, tmpExp);
e = semantic(e, sc);
e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), e);
e->type = Type::tvoid; // do not run semantic on e
cs->push(new ExpStatement(ss->loc, e));
FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit, STCnothrow);
- e = new DotIdExp(ss->loc, new VarExp(ss->loc, tmp), Id::ptr);
- e = semantic(e, sc);
+ e = semantic(tmpExp, sc);
e = new CallExp(ss->loc, new VarExp(ss->loc, fdexit, false), e);
e->type = Type::tvoid; // do not run semantic on e
Statement *s = new ExpStatement(ss->loc, e);
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index d76a9f8..f2a55d6 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -19,6 +19,7 @@
class ClassDeclaration;
class Dsymbol;
class Expression;
+class FuncDeclaration;
class Parameter;
class Type;
class TypeTuple;
@@ -28,7 +29,6 @@ struct TargetC
{
unsigned longsize; // size of a C 'long' or 'unsigned long' type
unsigned long_doublesize; // size of a C 'long double'
- unsigned criticalSectionSize; // size of os critical section
};
struct TargetCPP
@@ -39,6 +39,7 @@ struct TargetCPP
const char *toMangle(Dsymbol *s);
const char *typeInfoMangle(ClassDeclaration *cd);
+ const char *thunkMangle(FuncDeclaration *fd, int offset);
const char *typeMangle(Type *t);
Type *parameterType(Parameter *p);
bool fundamentalType(const Type *t, bool& isFundamental);
@@ -98,7 +99,6 @@ public:
// Type sizes and support.
unsigned alignsize(Type *type);
unsigned fieldalign(Type *type);
- unsigned critsecsize();
Type *va_listType(const Loc &loc, Scope *sc); // get type of va_list
int isVectorTypeSupported(int sz, Type *type);
bool isVectorOpSupported(Type *type, TOK op, Type *t2 = NULL);
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 79f212c..2a1818a 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -838,59 +838,81 @@ public:
Type *tb2 = e->e2->type->toBasetype ();
Type *etype = tb1->nextOf ()->toBasetype ();
+ /* Save the address of `e1', so it can be evaluated first.
+ As all D run-time library functions for concat assignments update `e1'
+ in-place and then return its value, the saved address can also be used as
+ the result of this expression as well. */
+ tree lhs = build_expr (e->e1);
+ tree lexpr = stabilize_expr (&lhs);
+ tree ptr = d_save_expr (build_address (lhs));
+ tree result = NULL_TREE;
+
if (tb1->ty == Tarray && tb2->ty == Tdchar
&& (etype->ty == Tchar || etype->ty == Twchar))
{
- /* Append a dchar to a char[] or wchar[] */
+ /* Append a dchar to a char[] or wchar[]:
+ The assignment is handled by the D run-time library, so only
+ need to call `_d_arrayappend[cw]d(&e1, e2)' */
libcall_fn libcall = (etype->ty == Tchar)
? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
- this->result_ = build_libcall (libcall, e->type, 2,
- build_address (build_expr (e->e1)),
- build_expr (e->e2));
+ result = build_libcall (libcall, e->type, 2,
+ ptr, build_expr (e->e2));
}
else
{
gcc_assert (tb1->ty == Tarray || tb2->ty == Tsarray);
- tree tinfo = build_typeinfo (e->loc, e->type);
- tree ptr = build_address (build_expr (e->e1));
-
if ((tb2->ty == Tarray || tb2->ty == Tsarray)
&& same_type_p (etype, tb2->nextOf ()->toBasetype ()))
{
- /* Append an array. */
- this->result_ = build_libcall (LIBCALL_ARRAYAPPENDT, e->type, 3,
- tinfo, ptr, d_array_convert (e->e2));
-
+ /* Append an array to another array:
+ The assignment is handled by the D run-time library, so only
+ need to call `_d_arrayappendT(ti, &e1, e2)' */
+ result = build_libcall (LIBCALL_ARRAYAPPENDT, e->type, 3,
+ build_typeinfo (e->loc, e->type),
+ ptr, d_array_convert (e->e2));
}
else if (same_type_p (etype, tb2))
{
- /* Append an element. */
- tree result = build_libcall (LIBCALL_ARRAYAPPENDCTX, e->type, 3,
- tinfo, ptr, size_one_node);
- result = d_save_expr (result);
+ /* Append an element to an array:
+ The assignment is generated inline, so need to handle temporaries
+ here, and ensure that they are evaluated in the correct order.
+
+ The generated code should end up being equivalent to:
+ _d_arrayappendcTX(ti, &e1, 1)[e1.length - 1] = e2
+ */
+ tree callexp = build_libcall (LIBCALL_ARRAYAPPENDCTX, e->type, 3,
+ build_typeinfo (e->loc, e->type),
+ ptr, size_one_node);
+ callexp = d_save_expr (callexp);
/* Assign e2 to last element. */
- tree offexp = d_array_length (result);
+ tree offexp = d_array_length (callexp);
offexp = build2 (MINUS_EXPR, TREE_TYPE (offexp),
offexp, size_one_node);
- tree ptrexp = d_array_ptr (result);
+ tree ptrexp = d_array_ptr (callexp);
ptrexp = void_okay_p (ptrexp);
ptrexp = build_array_index (ptrexp, offexp);
/* Evaluate expression before appending. */
- tree t2 = build_expr (e->e2);
- tree expr = stabilize_expr (&t2);
+ tree rhs = build_expr (e->e2);
+ tree rexpr = stabilize_expr (&rhs);
- result = modify_expr (build_deref (ptrexp), t2);
+ if (TREE_CODE (rhs) == CALL_EXPR)
+ rhs = force_target_expr (rhs);
- this->result_ = compound_expr (expr, result);
+ result = modify_expr (build_deref (ptrexp), rhs);
+ result = compound_expr (rexpr, result);
}
else
gcc_unreachable ();
}
+
+ /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
+ result = compound_expr (compound_expr (lexpr, ptr), result);
+ this->result_ = compound_expr (result, build_deref (ptr));
}
/* Build an assignment expression. The right operand is implicitly
diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index a629472..4196ed3 100644
--- a/gcc/d/intrinsics.cc
+++ b/gcc/d/intrinsics.cc
@@ -466,11 +466,14 @@ expand_intrinsic_copysign (tree callexp)
from = fold_convert (type, from);
/* Which variant of __builtin_copysign* should we call? */
- tree builtin = mathfn_built_in (type, BUILT_IN_COPYSIGN);
- gcc_assert (builtin != NULL_TREE);
+ built_in_function code = (type == float_type_node) ? BUILT_IN_COPYSIGNF
+ : (type == double_type_node) ? BUILT_IN_COPYSIGN
+ : (type == long_double_type_node) ? BUILT_IN_COPYSIGNL
+ : END_BUILTINS;
- return call_builtin_fn (callexp, DECL_FUNCTION_CODE (builtin), 2,
- to, from);
+ gcc_assert (code != END_BUILTINS);
+
+ return call_builtin_fn (callexp, code, 2, to, from);
}
/* Expand a front-end intrinsic call to pow(). This takes two arguments, the
@@ -811,10 +814,14 @@ maybe_expand_intrinsic (tree callexp)
case INTRINSIC_CEIL:
case INTRINSIC_CEILF:
case INTRINSIC_CEILL:
+ case INTRINSIC_COS:
+ case INTRINSIC_COSF:
case INTRINSIC_COSL:
case INTRINSIC_EXP:
case INTRINSIC_EXP2:
case INTRINSIC_EXPM1:
+ case INTRINSIC_FABS:
+ case INTRINSIC_FABSF:
case INTRINSIC_FABSL:
case INTRINSIC_FLOOR:
case INTRINSIC_FLOORF:
@@ -825,9 +832,15 @@ maybe_expand_intrinsic (tree callexp)
case INTRINSIC_LOG:
case INTRINSIC_LOG10:
case INTRINSIC_LOG2:
+ case INTRINSIC_RINT:
+ case INTRINSIC_RINTF:
case INTRINSIC_RINTL:
+ case INTRINSIC_RNDTOL:
+ case INTRINSIC_RNDTOLF:
case INTRINSIC_RNDTOLL:
case INTRINSIC_ROUND:
+ case INTRINSIC_SIN:
+ case INTRINSIC_SINF:
case INTRINSIC_SINL:
case INTRINSIC_SQRT:
case INTRINSIC_SQRTF:
@@ -841,6 +854,8 @@ maybe_expand_intrinsic (tree callexp)
case INTRINSIC_FMAX:
case INTRINSIC_FMIN:
+ case INTRINSIC_LDEXP:
+ case INTRINSIC_LDEXPF:
case INTRINSIC_LDEXPL:
code = intrinsic_decls[intrinsic].built_in;
gcc_assert (code != BUILT_IN_NONE);
diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def
index 5b8cb71..c05a666 100644
--- a/gcc/d/intrinsics.def
+++ b/gcc/d/intrinsics.def
@@ -93,22 +93,34 @@ DEF_D_BUILTIN (NEGSL, NONE, "negs", "core.checkedint", "FNaNbNiNflKbZl")
/* core.math intrinsics. */
+DEF_D_BUILTIN (COSF, COSF, "cos", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (COS, COS, "cos", "core.math", "FNaNbNiNfdZd")
DEF_D_BUILTIN (COSL, COSL, "cos", "core.math", "FNaNbNiNfeZe")
+DEF_D_BUILTIN (FABSF, FABSL, "fabs", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (FABS, FABS, "fabs", "core.math", "FNaNbNiNfdZd")
DEF_D_BUILTIN (FABSL, FABSL, "fabs", "core.math", "FNaNbNiNfeZe")
+DEF_D_BUILTIN (LDEXPF, LDEXPF, "ldexp", "core.math", "FNaNbNiNffiZf")
+DEF_D_BUILTIN (LDEXP, LDEXP, "ldexp", "core.math", "FNaNbNiNfdiZd")
DEF_D_BUILTIN (LDEXPL, LDEXPL, "ldexp", "core.math", "FNaNbNiNfeiZe")
+DEF_D_BUILTIN (RINTF, RINTF, "rint", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (RINT, RINT, "rint", "core.math", "FNaNbNiNfdZd")
DEF_D_BUILTIN (RINTL, RINTL, "rint", "core.math", "FNaNbNiNfeZe")
-/* Not sure if `llroundl' stands as a good replacement for the expected
+/* Not sure if `llround{f,l}' stands as a good replacement for the expected
behavior of `rndtol()'. */
+DEF_D_BUILTIN (RNDTOLF, LLROUNDF, "rndtol", "core.math", "FNaNbNiNffZl")
+DEF_D_BUILTIN (RNDTOL, LLROUND, "rndtol", "core.math", "FNaNbNiNfdZl")
DEF_D_BUILTIN (RNDTOLL, LLROUNDL, "rndtol", "core.math", "FNaNbNiNfeZl")
+DEF_D_BUILTIN (SINF, SINF, "sin", "core.math", "FNaNbNiNffZf")
+DEF_D_BUILTIN (SIN, SIN, "sin", "core.math", "FNaNbNiNfdZd")
DEF_D_BUILTIN (SINL, SINL, "sin", "core.math", "FNaNbNiNfeZe")
DEF_D_BUILTIN (SQRTF, SQRTF, "sqrt", "core.math", "FNaNbNiNffZf")
DEF_D_BUILTIN (SQRT, SQRT, "sqrt", "core.math", "FNaNbNiNfdZd")
DEF_D_BUILTIN (SQRTL, SQRTL, "sqrt", "core.math", "FNaNbNiNfeZe")
-DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FNaNbNffZI1T")
-DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FNaNbNfdZI1T")
-DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FNaNbNfeZI1T")
+DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FfZI1T")
+DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FdZI1T")
+DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FeZI1T")
/* std.math intrinsics. */
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index 4b48c19..742a24f 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "d-tree.h"
+#include "d-target.h"
/* D generates module information to inform the runtime library which modules
@@ -405,6 +406,10 @@ build_dso_registry_var (const char * name, tree type)
static void
register_moduleinfo (Module *decl, tree minfo)
{
+ /* No defined minfo section for target. */
+ if (targetdm.d_minfo_section == NULL)
+ return;
+
if (!targetm_common.have_named_sections)
sorry ("%<-fmoduleinfo%> is not supported on this target");
@@ -420,7 +425,8 @@ register_moduleinfo (Module *decl, tree minfo)
DECL_EXTERNAL (mref) = 0;
DECL_PRESERVE_P (mref) = 1;
- set_decl_section_name (mref, "minfo");
+ set_decl_section_name (mref, targetdm.d_minfo_section);
+ symtab_node::get (mref)->implicit_section = true;
d_pushdecl (mref);
rest_of_decl_compilation (mref, 1, 0);
@@ -431,10 +437,12 @@ register_moduleinfo (Module *decl, tree minfo)
if (!first_module)
return;
- start_minfo_node = build_dso_registry_var ("__start_minfo", ptr_type_node);
+ start_minfo_node = build_dso_registry_var (targetdm.d_minfo_start_name,
+ ptr_type_node);
rest_of_decl_compilation (start_minfo_node, 1, 0);
- stop_minfo_node = build_dso_registry_var ("__stop_minfo", ptr_type_node);
+ stop_minfo_node = build_dso_registry_var (targetdm.d_minfo_end_name,
+ ptr_type_node);
rest_of_decl_compilation (stop_minfo_node, 1, 0);
/* Declare dso_slot and dso_initialized. */
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 6df1e78..acb8c40 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -791,7 +791,6 @@ public:
/* Handle any special support for calling conventions. */
switch (t->linkage)
{
- case LINKpascal:
case LINKwindows:
/* [attribute/linkage]
@@ -965,7 +964,10 @@ public:
if (!t->sym->isPOD ())
{
for (tree tv = t->ctype; tv != NULL_TREE; tv = TYPE_NEXT_VARIANT (tv))
- TREE_ADDRESSABLE (tv) = 1;
+ {
+ TREE_ADDRESSABLE (tv) = 1;
+ SET_TYPE_MODE (tv, BLKmode);
+ }
}
}
@@ -1000,7 +1002,10 @@ public:
/* Classes only live in memory, so always set the TREE_ADDRESSABLE bit. */
for (tree tv = basetype; tv != NULL_TREE; tv = TYPE_NEXT_VARIANT (tv))
- TREE_ADDRESSABLE (tv) = 1;
+ {
+ TREE_ADDRESSABLE (tv) = 1;
+ SET_TYPE_MODE (tv, BLKmode);
+ }
/* Type is final, there are no derivations. */
if (t->sym->storage_class & STCfinal)
diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def
index 07946a8..c0744b2 100644
--- a/gcc/dbgcnt.def
+++ b/gcc/dbgcnt.def
@@ -170,7 +170,10 @@ DEBUG_COUNTER (if_after_combine)
DEBUG_COUNTER (if_after_reload)
DEBUG_COUNTER (if_conversion)
DEBUG_COUNTER (if_conversion_tree)
+DEBUG_COUNTER (if_to_switch)
DEBUG_COUNTER (ipa_cp_bits)
+DEBUG_COUNTER (ipa_cp_values)
+DEBUG_COUNTER (ipa_cp_vr)
DEBUG_COUNTER (ipa_mod_ref)
DEBUG_COUNTER (ipa_sra_params)
DEBUG_COUNTER (ipa_sra_retvalues)
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 5a20fde..eaee2f1 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -1963,6 +1963,7 @@ dbxout_type (tree type, int full)
case VOID_TYPE:
case NULLPTR_TYPE:
case LANG_TYPE:
+ case OPAQUE_TYPE:
/* For a void type, just define it as itself; i.e., "5=5".
This makes us consider it defined
without saying what it is. The debugger will make it
diff --git a/gcc/defaults.h b/gcc/defaults.h
index f1a3862..80a84dd 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -286,6 +286,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
#endif
+/* This determines whether or not we support marking sections with
+ SHF_GNU_RETAIN flag. Also require .init_array/.fini_array section
+ for constructors and destructors. */
+#ifndef SUPPORTS_SHF_GNU_RETAIN
+#if HAVE_GAS_SHF_GNU_RETAIN && HAVE_INITFINI_ARRAY_SUPPORT
+#define SUPPORTS_SHF_GNU_RETAIN 1
+#else
+#define SUPPORTS_SHF_GNU_RETAIN 0
+#endif
+#endif
+
/* This determines whether or not we support link-once semantics. */
#ifndef SUPPORTS_ONE_ONLY
#ifdef MAKE_DECL_ONE_ONLY
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 93b060f..9e75c13 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -3614,6 +3614,14 @@ df_update_entry_block_defs (void)
}
+/* Return true if REGNO is used by the epilogue. */
+bool
+df_epilogue_uses_p (unsigned int regno)
+{
+ return (EPILOGUE_USES (regno)
+ || TEST_HARD_REG_BIT (crtl->must_be_zero_on_return, regno));
+}
+
/* Set the bit for regs that are considered being used at the exit. */
static void
@@ -3661,7 +3669,7 @@ df_get_exit_block_use_set (bitmap exit_block_uses)
epilogue as being live at the end of the function since they
may be referenced by our caller. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i] || EPILOGUE_USES (i))
+ if (global_regs[i] || df_epilogue_uses_p (i))
bitmap_set_bit (exit_block_uses, i);
if (targetm.have_epilogue () && epilogue_completed)
@@ -3802,7 +3810,6 @@ df_hard_reg_init (void)
initialized = true;
}
-
/* Recompute the parts of scanning that are based on regs_ever_live
because something changed in that array. */
@@ -3862,7 +3869,6 @@ df_regs_ever_live_p (unsigned int regno)
return regs_ever_live[regno];
}
-
/* Set regs_ever_live[REGNO] to VALUE. If this cause regs_ever_live
to change, schedule that change for the next update. */
diff --git a/gcc/df.h b/gcc/df.h
index 8b6ca8c..0f098d7 100644
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -1085,6 +1085,7 @@ extern void df_update_entry_exit_and_calls (void);
extern bool df_hard_reg_used_p (unsigned int);
extern unsigned int df_hard_reg_used_count (unsigned int);
extern bool df_regs_ever_live_p (unsigned int);
+extern bool df_epilogue_uses_p (unsigned int);
extern void df_set_regs_ever_live (unsigned int, bool);
extern void df_compute_regs_ever_live (bool);
extern void df_scan_verify (void);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 1b6c984..da20cdb 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -689,12 +689,13 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
set_last_module (context, map);
if (! MAIN_FILE_P (map))
{
- bool first = true;
+ bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
expanded_location s = {};
do
{
where = linemap_included_from (map);
map = linemap_included_from_linemap (line_table, map);
+ bool is_module = MAP_MODULE_P (map);
s.file = LINEMAP_FILE (map);
s.line = SOURCE_LINE (map, where);
int col = -1;
@@ -706,14 +707,24 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
const char *line_col = maybe_line_and_column (s.line, col);
static const char *const msgs[] =
{
- N_("In file included from"),
+ NULL,
N_(" from"),
+ N_("In file included from"), /* 2 */
+ N_(" included from"),
+ N_("In module"), /* 4 */
+ N_("of module"),
+ N_("In module imported at"), /* 6 */
+ N_("imported at"),
};
- unsigned index = !first;
+
+ unsigned index = (was_module ? 6 : is_module ? 4
+ : need_inc ? 2 : 0) + !first;
+
pp_verbatim (context->printer, "%s%s %r%s%s%R",
- first ? "" : ",\n", _(msgs[index]),
+ first ? "" : was_module ? ", " : ",\n",
+ _(msgs[index]),
"locus", s.file, line_col);
- first = false;
+ first = false, need_inc = was_module, was_module = is_module;
}
while (! MAIN_FILE_P (map));
pp_verbatim (context->printer, ":");
@@ -1161,7 +1172,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
return false;
}
- if (diagnostic->kind != DK_NOTE)
+ if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
diagnostic_check_max_errors (context);
context->lock++;
diff --git a/gcc/digraph.cc b/gcc/digraph.cc
index 31b3e19..cd376ba 100644
--- a/gcc/digraph.cc
+++ b/gcc/digraph.cc
@@ -67,7 +67,7 @@ struct test_edge : public dedge<test_graph_traits>
void dump_dot (graphviz_out *gv, const dump_args_t &) const OVERRIDE
{
- gv->println ("%s -> %s;", m_src->m_name, m_dest->m_name);
+ gv->println ("%s %s %s%c", m_src->m_name, "->", m_dest->m_name, ';');
}
};
diff --git a/gcc/doc/analyzer.texi b/gcc/doc/analyzer.texi
index 96fe9bb..c9df556 100644
--- a/gcc/doc/analyzer.texi
+++ b/gcc/doc/analyzer.texi
@@ -245,7 +245,7 @@ Merging can be disabled via @option{-fno-analyzer-state-merge}.
Part of the state stored at a @code{exploded_node} is a @code{region_model}.
This is an implementation of the region-based ternary model described in
-@url{http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf,
+@url{http://lcs.ios.ac.cn/~xzx/memmodel.pdf,
"A Memory Model for Static Analysis of C Programs"}
(Zhongxing Xu, Ted Kremenek, and Jian Zhang).
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 33f876a..5dcd672 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2451,6 +2451,15 @@ features are supported by GCC.
@item __NO_MATH_ERRNO__
This macro is defined if @option{-fno-math-errno} is used, or enabled
by another option such as @option{-ffast-math} or by default.
+
+@item __GNUC_EXECUTION_CHARSET_NAME
+@itemx __GNUC_WIDE_EXECUTION_CHARSET_NAME
+These macros are defined to expand to a narrow string literal of
+the name of the narrow and wide compile-time execution character
+set used. It directly reflects the name passed to the options
+@option{-fexec-charset} and @option{-fwide-exec-charset}, or the defaults
+documented for those options (that is, it can expand to something like
+@code{"UTF-8"}). @xref{Invocation}.
@end table
@node System-specific Predefined Macros
@@ -3159,6 +3168,7 @@ directive}: @samp{#if}, @samp{#ifdef} or @samp{#ifndef}.
* Elif::
* @code{__has_attribute}::
* @code{__has_cpp_attribute}::
+* @code{__has_c_attribute}::
* @code{__has_builtin}::
* @code{__has_include}::
@end menu
@@ -3432,8 +3442,9 @@ condition succeeds after the original @samp{#if} and all previous
The special operator @code{__has_attribute (@var{operand})} may be used
in @samp{#if} and @samp{#elif} expressions to test whether the attribute
referenced by its @var{operand} is recognized by GCC. Using the operator
-in other contexts is not valid. In C code, @var{operand} must be
-a valid identifier. In C++ code, @var{operand} may be optionally
+in other contexts is not valid. In C code, if compiling for strict
+conformance to standards before C2x, @var{operand} must be
+a valid identifier. Otherwise, @var{operand} may be optionally
introduced by the @code{@var{attribute-scope}::} prefix.
The @var{attribute-scope} prefix identifies the ``namespace'' within
which the attribute is recognized. The scope of GCC attributes is
@@ -3479,6 +3490,21 @@ information including the dates of the introduction of current standard
attributes, see @w{@uref{https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations/,
SD-6: SG10 Feature Test Recommendations}}.
+@node @code{__has_c_attribute}
+@subsection @code{__has_c_attribute}
+@cindex @code{__has_c_attribute}
+
+The special operator @code{__has_c_attribute (@var{operand})} may be
+used in @samp{#if} and @samp{#elif} expressions in C code to test
+whether the attribute referenced by its @var{operand} is recognized by
+GCC in attributes using the @samp{[[]]} syntax. GNU attributes must
+be specified with the scope @samp{gnu} or @samp{__gnu__} with
+@code{__has_c_attribute}. When @var{operand} designates a supported
+standard attribute it evaluates to an integer constant of the form
+@code{YYYYMM} indicating the year and month when the attribute was
+first introduced into the C standard, or when the syntax of operands
+to the attribute was extended in the C standard.
+
@node @code{__has_builtin}
@subsection @code{__has_builtin}
@cindex @code{__has_builtin}
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 7f1849d..e5ece92 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -139,6 +139,10 @@ this useless.
This feature is used in automatic updating of makefiles.
+@item -Mno-modules
+@opindex Mno-modules
+Disable dependency generation for compiled module interfaces.
+
@item -MP
@opindex MP
This option instructs CPP to add a phony target for each dependency
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 5be1cbe..e73464a 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -55,7 +55,7 @@ extensions, accepted by GCC in C90 mode and in C++.
* Designated Inits:: Labeling elements of initializers.
* Case Ranges:: `case 1 ... 9' and such.
* Cast to Union:: Casting to union type from any member of the union.
-* Mixed Declarations:: Mixing declarations and code.
+* Mixed Labels and Declarations:: Mixing declarations, labels and code.
* Function Attributes:: Declaring that functions have no side effects,
or that they can never return.
* Variable Attributes:: Specifying attributes of variables.
@@ -2353,15 +2353,17 @@ void hack (union foo);
hack ((union foo) x);
@end smallexample
-@node Mixed Declarations
-@section Mixed Declarations and Code
+@node Mixed Labels and Declarations
+@section Mixed Declarations, Labels and Code
@cindex mixed declarations and code
@cindex declarations, mixed with code
@cindex code, mixed with declarations
ISO C99 and ISO C++ allow declarations and code to be freely mixed
-within compound statements. As an extension, GNU C also allows this in
-C90 mode. For example, you could do:
+within compound statements. ISO C2X allows labels to be
+placed before declarations and at the end of a compound statement.
+As an extension, GNU C also allows all this in C90 mode. For example,
+you could do:
@smallexample
int i;
@@ -3231,20 +3233,63 @@ this reason the attribute is not allowed on types to annotate indirect
calls.
@item malloc
+@item malloc (@var{deallocator})
+@item malloc (@var{deallocator}, @var{ptr-index})
@cindex @code{malloc} function attribute
@cindex functions that behave like malloc
-This tells the compiler that a function is @code{malloc}-like, i.e.,
-that the pointer @var{P} returned by the function cannot alias any
+Attribute @code{malloc} indicates that a function is @code{malloc}-like,
+i.e., that the pointer @var{P} returned by the function cannot alias any
other pointer valid when the function returns, and moreover no
pointers to valid objects occur in any storage addressed by @var{P}.
-Using this attribute can improve optimization. Compiler predicts
-that a function with the attribute returns non-null in most cases.
-Functions like
-@code{malloc} and @code{calloc} have this property because they return
-a pointer to uninitialized or zeroed-out storage. However, functions
-like @code{realloc} do not have this property, as they can return a
-pointer to storage containing pointers.
+Independently, the form of the attribute with one or two arguments
+associates @code{deallocator} as a suitable deallocation function for
+pointers returned from the @code{malloc}-like function. @var{ptr-index}
+denotes the positional argument to which when the pointer is passed in
+calls to @code{deallocator} has the effect of deallocating it.
+
+Using the attribute with no arguments is designed to improve optimization.
+The compiler predicts that a function with the attribute returns non-null
+in most cases. Functions like @code{malloc} and @code{calloc} have this
+property because they return a pointer to uninitialized or zeroed-out
+storage. However, functions like @code{realloc} do not have this property,
+as they may return pointers to storage containing pointers to existing
+objects.
+
+Associating a function with a @var{deallocator} helps detect calls to
+mismatched allocation and deallocation functions and diagnose them under
+the control of options such as @option{-Wmismatched-dealloc}. To indicate
+that an allocation function both satisifies the nonaliasing property and
+has a deallocator associated with it, both the plain form of the attribute
+and the one with the @var{deallocator} argument must be used. The same
+function can be both an allocator and a deallocator. Since inlining one
+of the associated functions but not the other could result in apparent
+mismatches, this form of attribute @code{malloc} is not accepted on inline
+functions. For the same reason, using the attribute prevents both
+the allocation and deallocation functions from being expanded inline.
+
+For example, besides stating that the functions return pointers that do
+not alias any others, the following declarations make @code{fclose}
+a suitable deallocator for pointers returned from all functions except
+@code{popen}, and @code{pclose} as the only suitable deallocator for
+pointers returned from @code{popen}. The deallocator functions must
+declared before they can be referenced in the attribute.
+
+@smallexample
+int fclose (FILE*);
+int pclose (FILE*);
+
+__attribute__ ((malloc, malloc (fclose (1))))
+ FILE* fdopen (int);
+__attribute__ ((malloc, malloc (fclose (1))))
+ FILE* fopen (const char*, const char*);
+__attribute__ ((malloc, malloc (fclose (1))))
+ FILE* fmemopen(void *, size_t, const char *);
+__attribute__ ((malloc, malloc (pclose (1))))
+ FILE* popen (const char*, const char*);
+__attribute__ ((malloc, malloc (fclose (1))))
+ FILE* tmpfile (void);
+@end smallexample
@item no_icf
@cindex @code{no_icf} function attribute
@@ -3814,6 +3859,14 @@ When applied to a member function of a C++ class template, the
attribute also means that the function is instantiated if the
class itself is instantiated.
+For ELF targets that support the GNU or FreeBSD OSABIs, this attribute
+will also save the function from linker garbage collection. To support
+this behavior, functions that have not been placed in specific sections
+(e.g. by the @code{section} attribute, or the @code{-ffunction-sections}
+option), will be placed in new, unique sections.
+
+This additional functionality requires Binutils version 2.36 or later.
+
@item visibility ("@var{visibility_type}")
@cindex @code{visibility} function attribute
This attribute affects the linkage of the declaration to which it is attached.
@@ -3996,6 +4049,92 @@ performing a link with relocatable output (i.e.@: @code{ld -r}) on them.
A declaration to which @code{weakref} is attached and that is associated
with a named @code{target} must be @code{static}.
+@item zero_call_used_regs ("@var{choice}")
+@cindex @code{zero_call_used_regs} function attribute
+
+The @code{zero_call_used_regs} attribute causes the compiler to zero
+a subset of all call-used registers@footnote{A ``call-used'' register
+is a register whose contents can be changed by a function call;
+therefore, a caller cannot assume that the register has the same contents
+on return from the function as it had before calling the function. Such
+registers are also called ``call-clobbered'', ``caller-saved'', or
+``volatile''.} at function return.
+This is used to increase program security by either mitigating
+Return-Oriented Programming (ROP) attacks or preventing information leakage
+through registers.
+
+In order to satisfy users with different security needs and control the
+run-time overhead at the same time, the @var{choice} parameter provides a
+flexible way to choose the subset of the call-used registers to be zeroed.
+The three basic values of @var{choice} are:
+
+@itemize @bullet
+@item
+@samp{skip} doesn't zero any call-used registers.
+
+@item
+@samp{used} only zeros call-used registers that are used in the function.
+A ``used'' register is one whose content has been set or referenced in
+the function.
+
+@item
+@samp{all} zeros all call-used registers.
+@end itemize
+
+In addition to these three basic choices, it is possible to modify
+@samp{used} or @samp{all} as follows:
+
+@itemize @bullet
+@item
+Adding @samp{-gpr} restricts the zeroing to general-purpose registers.
+
+@item
+Adding @samp{-arg} restricts the zeroing to registers that can sometimes
+be used to pass function arguments. This includes all argument registers
+defined by the platform's calling conversion, regardless of whether the
+function uses those registers for function arguments or not.
+@end itemize
+
+The modifiers can be used individually or together. If they are used
+together, they must appear in the order above.
+
+The full list of @var{choice}s is therefore:
+
+@table @code
+@item skip
+doesn't zero any call-used register.
+
+@item used
+only zeros call-used registers that are used in the function.
+
+@item used-gpr
+only zeros call-used general purpose registers that are used in the function.
+
+@item used-arg
+only zeros call-used registers that are used in the function and pass arguments.
+
+@item used-gpr-arg
+only zeros call-used general purpose registers that are used in the function
+and pass arguments.
+
+@item all
+zeros all call-used registers.
+
+@item all-gpr
+zeros all call-used general purpose registers.
+
+@item all-arg
+zeros all call-used registers that pass arguments.
+
+@item all-gpr-arg
+zeros all call-used general purpose registers that pass
+arguments.
+@end table
+
+Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
+and @samp{all-gpr-arg} are mainly used for ROP mitigation.
+
+The default for the attribute is controlled by @option{-fzero-call-used-regs}.
@end table
@c This is the end of the target-independent attribute table
@@ -6073,9 +6212,10 @@ and for static member methods.
On 32-bit and 64-bit x86 targets, you can use an ABI attribute
to indicate which calling convention should be used for a function. The
@code{ms_abi} attribute tells the compiler to use the Microsoft ABI,
-while the @code{sysv_abi} attribute tells the compiler to use the ABI
-used on GNU/Linux and other systems. The default is to use the Microsoft ABI
-when targeting Windows. On all other systems, the default is the x86/AMD ABI.
+while the @code{sysv_abi} attribute tells the compiler to use the System V
+ELF ABI, which is used on GNU/Linux and other systems. The default is to use
+the Microsoft ABI when targeting Windows. On all other systems, the default
+is the System V ELF ABI.
Note, the @code{ms_abi} attribute for Microsoft Windows 64-bit targets currently
requires the @option{-maccumulate-outgoing-args} option.
@@ -6652,6 +6792,21 @@ Enable/disable the generation of the UINTR instructions.
@cindex @code{target("hreset")} function attribute, x86
Enable/disable the generation of the HRESET instruction.
+@item kl
+@itemx no-kl
+@cindex @code{target("kl")} function attribute, x86
+Enable/disable the generation of the KEYLOCKER instructions.
+
+@item widekl
+@itemx no-widekl
+@cindex @code{target("widekl")} function attribute, x86
+Enable/disable the generation of the WIDEKL instructions.
+
+@item avxvnni
+@itemx no-avxvnni
+@cindex @code{target("avxvnni")} function attribute, x86
+Enable/disable the generation of the AVXVNNI instructions.
+
@item cld
@itemx no-cld
@cindex @code{target("cld")} function attribute, x86
@@ -7273,6 +7428,14 @@ When applied to a static data member of a C++ class template, the
attribute also means that the member is instantiated if the
class itself is instantiated.
+For ELF targets that support the GNU or FreeBSD OSABIs, this attribute
+will also save the variable from linker garbage collection. To support
+this behavior, variables that have not been placed in specific sections
+(e.g. by the @code{section} attribute, or the @code{-fdata-sections} option),
+will be placed in new, unique sections.
+
+This additional functionality requires Binutils version 2.36 or later.
+
@item vector_size (@var{bytes})
@cindex @code{vector_size} variable attribute
This attribute specifies the vector size for the type of the declared
@@ -7322,9 +7485,49 @@ The @code{weak} attribute is described in
@cindex @code{noinit} variable attribute
Any data with the @code{noinit} attribute will not be initialized by
the C runtime startup code, or the program loader. Not initializing
-data in this way can reduce program startup times. This attribute is
-specific to ELF targets and relies on the linker to place such data in
-the right location
+data in this way can reduce program startup times.
+
+This attribute is specific to ELF targets and relies on the linker
+script to place sections with the @code{.noinit} prefix in the right
+location.
+
+@item persistent
+@cindex @code{persistent} variable attribute
+Any data with the @code{persistent} attribute will not be initialized by
+the C runtime startup code, but will be initialized by the program
+loader. This enables the value of the variable to @samp{persist}
+between processor resets.
+
+This attribute is specific to ELF targets and relies on the linker
+script to place the sections with the @code{.persistent} prefix in the
+right location. Specifically, some type of non-volatile, writeable
+memory is required.
+
+@item objc_nullability (@var{nullability kind}) @r{(Objective-C and Objective-C++ only)}
+@cindex @code{objc_nullability} variable attribute
+This attribute applies to pointer variables only. It allows marking the
+pointer with one of four possible values describing the conditions under
+which the pointer might have a @code{nil} value. In most cases, the
+attribute is intended to be an internal representation for property and
+method nullability (specified by language keywords); it is not recommended
+to use it directly.
+
+When @var{nullability kind} is @code{"unspecified"} or @code{0}, nothing is
+known about the conditions in which the pointer might be @code{nil}. Making
+this state specific serves to avoid false positives in diagnostics.
+
+When @var{nullability kind} is @code{"nonnull"} or @code{1}, the pointer has
+no meaning if it is @code{nil} and thus the compiler is free to emit
+diagnostics if it can be determined that the value will be @code{nil}.
+
+When @var{nullability kind} is @code{"nullable"} or @code{2}, the pointer might
+be @code{nil} and carry meaning as such.
+
+When @var{nullability kind} is @code{"resettable"} or @code{3} (used only in
+the context of property attribute lists) this describes the case in which a
+property setter may take the value @code{nil} (which perhaps causes the
+property to be reset in some manner to a default) but for which the property
+getter will never validly return @code{nil}.
@end table
@@ -7719,23 +7922,6 @@ The @code{shared} attribute is only available on Microsoft Windows@.
@subsection MSP430 Variable Attributes
@table @code
-@item noinit
-@cindex @code{noinit} variable attribute, MSP430
-Any data with the @code{noinit} attribute will not be initialised by
-the C runtime startup code, or the program loader. Not initialising
-data in this way can reduce program startup times.
-
-@item persistent
-@cindex @code{persistent} variable attribute, MSP430
-Any variable with the @code{persistent} attribute will not be
-initialised by the C runtime startup code. Instead its value will be
-set once, when the application is loaded, and then never initialised
-again, even if the processor is reset or the program restarts.
-Persistent data is intended to be placed into FLASH RAM, where its
-value will be retained across resets. The linker script being used to
-create the application should ensure that persistent data is correctly
-placed.
-
@item upper
@itemx either
@cindex @code{upper} variable attribute, MSP430
@@ -8415,6 +8601,12 @@ and caught in another, the class must have default visibility.
Otherwise the two shared objects are unable to use the same
typeinfo node and exception handling will break.
+@item objc_root_class @r{(Objective-C and Objective-C++ only)}
+@cindex @code{objc_root_class} type attribute
+This attribute marks a class as being a root class, and thus allows
+the compiler to elide any warnings about a missing superclass and to
+make additional checks for mandatory methods as needed.
+
@end table
To specify multiple attributes, separate them by commas within the
@@ -8534,7 +8726,8 @@ details of the exact syntax for using attributes. Other attributes are
available for functions (@pxref{Function Attributes}), variables
(@pxref{Variable Attributes}), enumerators (@pxref{Enumerator Attributes}),
statements (@pxref{Statement Attributes}), and for types
-(@pxref{Type Attributes}).
+(@pxref{Type Attributes}). A label attribute followed
+by a declaration appertains to the label and not the declaration.
This example uses the @code{cold} label attribute to indicate the
@code{ErrorHandling} branch is unlikely to be taken and that the
@@ -9430,7 +9623,7 @@ asm @var{asm-qualifiers} ( @var{AssemblerTemplate}
@r{[} : @var{Clobbers} @r{]} @r{]})
asm @var{asm-qualifiers} ( @var{AssemblerTemplate}
- :
+ : @var{OutputOperands}
: @var{InputOperands}
: @var{Clobbers}
: @var{GotoLabels})
@@ -9537,7 +9730,7 @@ there is no need for the output variables. Also, the optimizers may move
code out of loops if they believe that the code will always return the same
result (i.e.@: none of its input values change between calls). Using the
@code{volatile} qualifier disables these optimizations. @code{asm} statements
-that have no output operands, including @code{asm goto} statements,
+that have no output operands and @code{asm goto} statements,
are implicitly volatile.
This i386 code demonstrates a case that does not use (or require) the
@@ -10396,9 +10589,6 @@ case, consider using the @code{__builtin_unreachable} intrinsic after the
using the @code{hot} and @code{cold} label attributes (@pxref{Label
Attributes}).
-An @code{asm goto} statement cannot have outputs.
-This is due to an internal restriction of
-the compiler: control transfer instructions cannot have outputs.
If the assembler code does modify anything, use the @code{"memory"} clobber
to force the
optimizers to flush all register values to memory and reload them if
@@ -10407,6 +10597,13 @@ necessary after the @code{asm} statement.
Also note that an @code{asm goto} statement is always implicitly
considered volatile.
+Be careful when you set output operands inside @code{asm goto} only on
+some possible control flow paths. If you don't set up the output on
+given path and never use it on this path, it is okay. Otherwise, you
+should use @samp{+} constraint modifier meaning that the operand is
+input and output one. With this modifier you will have the correct
+values on all possible paths from the @code{asm goto}.
+
To reference a label in the assembler template,
prefix it with @samp{%l} (lowercase @samp{L}) followed
by its (zero-based) position in @var{GotoLabels} plus the number of input
@@ -10452,6 +10649,41 @@ error:
@}
@end example
+The following example shows an @code{asm goto} that uses an output.
+
+@example
+int foo(int count)
+@{
+ asm goto ("dec %0; jb %l[stop]"
+ : "+r" (count)
+ :
+ :
+ : stop);
+ return count;
+stop:
+ return 0;
+@}
+@end example
+
+The following artificial example shows an @code{asm goto} that sets
+up an output only on one path inside the @code{asm goto}. Usage of
+constraint modifier @code{=} instead of @code{+} would be wrong as
+@code{factor} is used on all paths from the @code{asm goto}.
+
+@example
+int foo(int inp)
+@{
+ int factor = 0;
+ asm goto ("cmp %1, 10; jb %l[lab]; mov 2, %0"
+ : "+r" (factor)
+ : "r" (inp)
+ :
+ : lab);
+lab:
+ return inp * factor; /* return 2 * inp or 0 if inp < 10 */
+@}
+@end example
+
@anchor{x86Operandmodifiers}
@subsubsection x86 Operand Modifiers
@@ -13388,6 +13620,34 @@ initializers of variables usable in constant expressions. For more details
refer to the latest revision of the C++ standard.
@end deftypefn
+@deftypefn {Built-in Function} void __builtin_clear_padding (@var{ptr})
+The built-in function @code{__builtin_clear_padding} function clears
+padding bits inside of the object representation of object pointed by
+@var{ptr}, which has to be a pointer. The value representation of the
+object is not affected. The type of the object is assumed to be the type
+the pointer points to. Inside of a union, the only cleared bits are
+bits that are padding bits for all the union members.
+
+This built-in-function is useful if the padding bits of an object might
+have intederminate values and the object representation needs to be
+bitwise compared to some other object, for example for atomic operations.
+@end deftypefn
+
+@deftypefn {Built-in Function} @var{type} __builtin_bit_cast (@var{type}, @var{arg})
+The @code{__builtin_bit_cast} function is available only
+in C++. The built-in is intended to be used by implementations of
+the @code{std::bit_cast} C++ template function. Programs should make
+use of the latter function rather than invoking the built-in directly.
+
+This built-in function allows reinterpreting the bits of the @var{arg}
+argument as if it had type @var{type}. @var{type} and the type of the
+@var{arg} argument need to be trivially copyable types with the same size.
+When manifestly constant-evaluated, it performs extra diagnostics required
+for @code{std::bit_cast} and returns a constant expression if @var{arg}
+is a constant expression. For more details
+refer to the latest revision of the C++ standard.
+@end deftypefn
+
@deftypefn {Built-in Function} long __builtin_expect (long @var{exp}, long @var{c})
@opindex fprofile-arcs
You may use @code{__builtin_expect} to provide the compiler with
@@ -13769,6 +14029,18 @@ to be a signaling NaN@. The @code{nans} function is proposed by
@uref{http://www.open-std.org/jtc1/sc22/wg14/www/docs/n965.htm,,WG14 N965}.
@end deftypefn
+@deftypefn {Built-in Function} _Decimal32 __builtin_nansd32 (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{_Decimal32}.
+@end deftypefn
+
+@deftypefn {Built-in Function} _Decimal64 __builtin_nansd64 (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{_Decimal64}.
+@end deftypefn
+
+@deftypefn {Built-in Function} _Decimal128 __builtin_nansd128 (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{_Decimal128}.
+@end deftypefn
+
@deftypefn {Built-in Function} float __builtin_nansf (const char *str)
Similar to @code{__builtin_nans}, except the return type is @code{float}.
@end deftypefn
@@ -13966,6 +14238,7 @@ instructions, but allow the compiler to schedule those calls.
* PowerPC Hardware Transactional Memory Built-in Functions::
* PowerPC Atomic Memory Operation Functions::
* PowerPC Matrix-Multiply Assist Built-in Functions::
+* PRU Built-in Functions::
* RISC-V Built-in Functions::
* RX Built-in Functions::
* S/390 System z Built-in Functions::
@@ -20161,15 +20434,28 @@ __int128 vec_vsubuqm (__int128, __int128);
__uint128 vec_vsubuqm (__uint128, __uint128);
vector __int128 __builtin_bcdadd (vector __int128, vector __int128, const int);
+vector unsigned char __builtin_bcdadd (vector unsigned char, vector unsigned char,
+ const int);
int __builtin_bcdadd_lt (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_lt (vector unsigned char, vector unsigned char, const int);
int __builtin_bcdadd_eq (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_eq (vector unsigned char, vector unsigned char, const int);
int __builtin_bcdadd_gt (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_gt (vector unsigned char, vector unsigned char, const int);
int __builtin_bcdadd_ov (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_ov (vector unsigned char, vector unsigned char, const int);
+
vector __int128 __builtin_bcdsub (vector __int128, vector __int128, const int);
+vector unsigned char __builtin_bcdsub (vector unsigned char, vector unsigned char,
+ const int);
int __builtin_bcdsub_lt (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_lt (vector unsigned char, vector unsigned char, const int);
int __builtin_bcdsub_eq (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_eq (vector unsigned char, vector unsigned char, const int);
int __builtin_bcdsub_gt (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_gt (vector unsigned char, vector unsigned char, const int);
int __builtin_bcdsub_ov (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_ov (vector unsigned char, vector unsigned char, const int);
@end smallexample
@node PowerPC AltiVec Built-in Functions Available on ISA 3.0
@@ -21733,6 +22019,33 @@ vec_t __builtin_vsx_xvcvspbf16 (vec_t);
vec_t __builtin_vsx_xvcvbf16spn (vec_t);
@end smallexample
+@node PRU Built-in Functions
+@subsection PRU Built-in Functions
+
+GCC provides a couple of special builtin functions to aid in utilizing
+special PRU instructions.
+
+The built-in functions supported are:
+
+@table @code
+@item __delay_cycles (long long @var{cycles})
+This inserts an instruction sequence that takes exactly @var{cycles}
+cycles (between 0 and 0xffffffff) to complete. The inserted sequence
+may use jumps, loops, or no-ops, and does not interfere with any other
+instructions. Note that @var{cycles} must be a compile-time constant
+integer - that is, you must pass a number, not a variable that may be
+optimized to a constant later. The number of cycles delayed by this
+builtin is exact.
+
+@item __halt (void)
+This inserts a HALT instruction to stop processor execution.
+
+@item unsigned int __lmbd (unsigned int @var{wordval}, unsigned int @var{bitval})
+This inserts LMBD instruction to calculate the left-most bit with value
+@var{bitval} in value @var{wordval}. Only the least significant bit
+of @var{bitval} is taken into account.
+@end table
+
@node RISC-V Built-in Functions
@subsection RISC-V Built-in Functions
@@ -22585,6 +22898,12 @@ AMD Family 17h Zen version 1.
@item znver2
AMD Family 17h Zen version 2.
+
+@item amdfam19h
+AMD Family 19h CPU.
+
+@item znver3
+AMD Family 19h Zen version 3.
@end table
Here is an example:
@@ -23907,7 +24226,7 @@ void __builtin_ia32_wrpkru (unsigned int)
unsigned int __builtin_ia32_rdpkru ()
@end smallexample
-The following built-in functions are available when @option{-mcet} or
+The following built-in functions are available when
@option{-mshstk} option is used. They support shadow stack
machine instructions from Intel Control-flow Enforcement Technology (CET).
Each built-in function generates the machine instruction that is part
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index 7373266..9791f8b 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -302,6 +302,7 @@ The elements are indexed from zero.
@tindex ARRAY_TYPE
@tindex RECORD_TYPE
@tindex UNION_TYPE
+@tindex OPAQUE_TYPE
@tindex UNKNOWN_TYPE
@tindex OFFSET_TYPE
@findex TYPE_UNQUALIFIED
@@ -487,6 +488,13 @@ assigned to that constant. These constants will appear in the order in
which they were declared. The @code{TREE_TYPE} of each of these
constants will be the type of enumeration type itself.
+@item OPAQUE_TYPE
+Used for things that have a @code{MODE_OPAQUE} mode class in the
+backend. Opaque types have a size and precision, and can be held in
+memory or registers. They are used when we do not want the compiler to
+make assumptions about the availability of other operations as would
+happen with integer types.
+
@item BOOLEAN_TYPE
Used to represent the @code{bool} type.
@@ -1790,6 +1798,10 @@ a value from @code{enum annot_expr_kind}, the third is an @code{INTEGER_CST}.
@tindex VEC_RSHIFT_EXPR
@tindex VEC_WIDEN_MULT_HI_EXPR
@tindex VEC_WIDEN_MULT_LO_EXPR
+@tindex VEC_WIDEN_PLUS_HI_EXPR
+@tindex VEC_WIDEN_PLUS_LO_EXPR
+@tindex VEC_WIDEN_MINUS_HI_EXPR
+@tindex VEC_WIDEN_MINUS_LO_EXPR
@tindex VEC_UNPACK_HI_EXPR
@tindex VEC_UNPACK_LO_EXPR
@tindex VEC_UNPACK_FLOAT_HI_EXPR
@@ -1836,6 +1848,33 @@ vector of @code{N/2} products. In the case of @code{VEC_WIDEN_MULT_LO_EXPR} the
low @code{N/2} elements of the two vector are multiplied to produce the
vector of @code{N/2} products.
+@item VEC_WIDEN_PLUS_HI_EXPR
+@itemx VEC_WIDEN_PLUS_LO_EXPR
+These nodes represent widening vector addition of the high and low parts of
+the two input vectors, respectively. Their operands are vectors that contain
+the same number of elements (@code{N}) of the same integral type. The result
+is a vector that contains half as many elements, of an integral type whose size
+is twice as wide. In the case of @code{VEC_WIDEN_PLUS_HI_EXPR} the high
+@code{N/2} elements of the two vectors are added to produce the vector of
+@code{N/2} products. In the case of @code{VEC_WIDEN_PLUS_LO_EXPR} the low
+@code{N/2} elements of the two vectors are added to produce the vector of
+@code{N/2} products.
+
+@item VEC_WIDEN_MINUS_HI_EXPR
+@itemx VEC_WIDEN_MINUS_LO_EXPR
+These nodes represent widening vector subtraction of the high and low parts of
+the two input vectors, respectively. Their operands are vectors that contain
+the same number of elements (@code{N}) of the same integral type. The high/low
+elements of the second vector are subtracted from the high/low elements of the
+first. The result is a vector that contains half as many elements, of an
+integral type whose size is twice as wide. In the case of
+@code{VEC_WIDEN_MINUS_HI_EXPR} the high @code{N/2} elements of the second
+vector are subtracted from the high @code{N/2} of the first to produce the
+vector of @code{N/2} products. In the case of
+@code{VEC_WIDEN_MINUS_LO_EXPR} the low @code{N/2} elements of the second
+vector are subtracted from the low @code{N/2} of the first to produce the
+vector of @code{N/2} products.
+
@item VEC_UNPACK_HI_EXPR
@itemx VEC_UNPACK_LO_EXPR
These nodes represent unpacking of the high and low parts of the input vector,
diff --git a/gcc/doc/implement-c.texi b/gcc/doc/implement-c.texi
index 692297b..d7433ba 100644
--- a/gcc/doc/implement-c.texi
+++ b/gcc/doc/implement-c.texi
@@ -576,6 +576,11 @@ are of scalar types, the expression is interpreted by GCC as a read of
the volatile object; in the other cases, the expression is only evaluated
for its side effects.
+When an object of an aggregate type, with the same size and alignment as a
+scalar type @code{S}, is the subject of a volatile access by an assignment
+expression or an atomic function, the access to it is performed as if the
+object's declared type were @code{volatile S}.
+
@end itemize
@node Declarators implementation
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 5330bf3..e30d2fc 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -464,6 +464,9 @@ Necessary when modifying @command{gperf} input files, e.g.@:
@item DejaGnu 1.4.4
@itemx Expect
@itemx Tcl
+@c Once Tcl 8.5 or higher is required, remove any obsolete
+@c compatibility workarounds:
+@c git grep 'compatibility with earlier Tcl releases'
Necessary to run the GCC testsuite; see the section on testing for
details.
@@ -1252,6 +1255,37 @@ If @option{--with-multilib-list} is not given, then only 32-bit and
64-bit run-time libraries will be enabled.
@end table
+@item --with-multilib-generator=@var{config}
+Specify what multilibs to build. @var{config} is a semicolon separated list of
+values, possibly consisting of a single value. Currently only implemented
+for riscv*-*-elf*. The accepted values and meanings are given below.
+
+
+Every config is constructed with four components: architecture string, ABI,
+reuse rule with architecture string and reuse rule with sub-extension.
+
+Example 1: Add multi-lib suppport for rv32i with ilp32.
+@smallexample
+rv32i-ilp32--
+@end smallexample
+
+Example 2: Add multi-lib suppport for rv32i with ilp32 and rv32imafd with ilp32.
+@smallexample
+rv32i-ilp32--;rv32imafd-ilp32--
+@end smallexample
+
+Example 3: Add multi-lib suppport for rv32i with ilp32; rv32im with ilp32 and
+rv32ic with ilp32 will reuse this multi-lib set.
+@smallexample
+rv32i-ilp32-rv32im-c
+@end smallexample
+
+Example 4: Add multi-lib suppport for rv64ima with lp64; rv64imaf with lp64,
+rv64imac with lp64 and rv64imafc with lp64 will reuse this multi-lib set.
+@smallexample
+rv64ima-lp64--f,c,fc
+@end smallexample
+
@item --with-endian=@var{endians}
Specify what endians to use.
Currently only implemented for sh*-*-*.
@@ -1340,7 +1374,7 @@ Specify which cpu variant the compiler should generate code for by default.
This option is only supported on some targets, including ARC, ARM, i386, M68k,
PowerPC, and SPARC@. It is mandatory for ARC@. The @option{--with-cpu-32} and
@option{--with-cpu-64} options specify separate default CPUs for
-32-bit and 64-bit modes; these options are only supported for i386,
+32-bit and 64-bit modes; these options are only supported for aarch64, i386,
x86-64, PowerPC, and SPARC@.
@item --with-schedule=@var{cpu}
@@ -1533,6 +1567,14 @@ When building GCC, use a mutex to avoid linking the compilers for
multiple languages at the same time, to avoid thrashing on build
systems with limited free memory. The default is not to use such a mutex.
+@item --enable-link-serialization
+When building GCC, use make dependencies to serialize linking the compilers for
+multiple languages, to avoid thrashing on build
+systems with limited free memory. The default is not to add such
+dependencies and thus with parallel make potentially link different
+compilers concurrently. If the argument is a positive integer, allow
+that number of concurrent link processes for the large binaries.
+
@item --enable-maintainer-mode
The build rules that regenerate the Autoconf and Automake output files as
well as the GCC master message catalog @file{gcc.pot} are normally
@@ -2217,11 +2259,10 @@ instrumentation, see @option{-fcf-protection} option. When
to add @option{-fcf-protection} and, if needed, other target
specific options to a set of building options.
-The option is disabled by default. When @code{--enable-cet=auto}
-is used, it is enabled on Linux/x86 if target binutils
-supports @code{Intel CET} instructions and disabled otherwise.
-In this case the target libraries are configured to get additional
-@option{-fcf-protection} option.
+@code{--enable-cet=auto} is default. CET is enabled on Linux/x86 if
+target binutils supports @code{Intel CET} instructions and disabled
+otherwise. In this case, the target libraries are configured to get
+additional @option{-fcf-protection} option.
@item --with-riscv-attribute=@samp{yes}, @samp{no} or @samp{default}
Generate RISC-V attribute by default, in order to record extra build
@@ -2229,6 +2270,17 @@ information in object.
The option is disabled by default. It is enabled on RISC-V/ELF (bare-metal)
target if target binutils supported.
+
+@item --enable-s390-excess-float-precision
+@itemx --disable-s390-excess-float-precision
+On s390(x) targets, enable treatment of float expressions with double precision
+when in standards-compliant mode (e.g., when @code{--std=c99} or
+@code{-fexcess-precision=standard} are given).
+
+For a native build and cross compiles that have target headers, the option's
+default is derived from glibc's behavior. When glibc clamps float_t to double,
+GCC follows and enables the option. For other cross compiles, the default is
+disabled.
@end table
@subheading Cross-Compiler-Specific Options
@@ -2759,6 +2811,15 @@ Arranges for the run time of each program started by the GCC driver,
built in any stage, to be logged to @file{time.log}, in the top level of
the build tree.
+@item @samp{bootstrap-asan}
+Compiles GCC itself using Address Sanitization in order to catch invalid memory
+accesses within the GCC code.
+
+@item @samp{bootstrap-hwasan}
+Compiles GCC itself using HWAddress Sanitization in order to catch invalid
+memory accesses within the GCC code. This option is only available on AArch64
+systems that are running Linux kernel version 5.4 or later.
+
@end table
@section Building a cross compiler
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index edea7ee..dd08697 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -97,7 +97,7 @@ The usual way to run GCC is to run the executable called @command{gcc}, or
When you compile C++ programs, you should invoke GCC as @command{g++}
instead. @xref{Invoking G++,,Compiling C++ Programs},
for information about the differences in behavior between @command{gcc}
-and @code{g++} when compiling C++ programs.
+and @command{g++} when compiling C++ programs.
@cindex grouping options
@cindex options, grouping
@@ -172,6 +172,7 @@ listing and explanation of the binary and decimal byte size prefixes.
* Spec Files:: How to pass switches to sub-processes.
* Environment Variables:: Env vars that affect GCC.
* Precompiled Headers:: Compiling a header once, and using it many times.
+* C++ Modules:: Experimental C++20 module system.
@end menu
@c man begin OPTIONS
@@ -201,7 +202,7 @@ in the following sections.
-aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} -fgimple@gol
-fhosted -ffreestanding @gol
--fopenacc -fopenacc-dim=@var{geom} @gol
+-fopenacc -fopenacc-dim=@var{geom} -fopenacc-kernels=@var{mode} @gol
-fopenmp -fopenmp-simd @gol
-fms-extensions -fplan9-extensions -fsso-struct=@var{endianness} @gol
-fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol
@@ -219,7 +220,13 @@ in the following sections.
-fno-gnu-keywords @gol
-fno-implicit-templates @gol
-fno-implicit-inline-templates @gol
--fno-implement-inlines -fms-extensions @gol
+-fno-implement-inlines @gol
+-fmodule-header@r{[}=@var{kind}@r{]} -fmodule-only -fmodules-ts @gol
+-fmodule-implicit-inline @gol
+-fno-module-lazy @gol
+-fmodule-mapper=@var{specification} @gol
+-fmodule-version-ignore @gol
+-fms-extensions @gol
-fnew-inheriting-ctors @gol
-fnew-ttp-matching @gol
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
@@ -233,15 +240,21 @@ in the following sections.
-fvisibility-inlines-hidden @gol
-fvisibility-ms-compat @gol
-fext-numeric-literals @gol
+-flang-info-include-translate@r{[}=@var{name}@r{]} @gol
+-flang-info-include-translate-not @gol
+-stdlib=@var{libstdc++,libc++} @gol
-Wabi-tag -Wcatch-value -Wcatch-value=@var{n} @gol
-Wno-class-conversion -Wclass-memaccess @gol
-Wcomma-subscript -Wconditionally-supported @gol
-Wno-conversion-null -Wctad-maybe-unsupported @gol
-Wctor-dtor-privacy -Wno-delete-incomplete @gol
--Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
--Weffc++ -Wextra-semi -Wno-inaccessible-base @gol
+-Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
+-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
+-Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
--Wno-invalid-offsetof -Wno-literal-suffix -Wmismatched-tags @gol
+-Winvalid-imported-macros @gol
+-Wno-invalid-offsetof -Wno-literal-suffix @gol
+-Wno-mismatched-new-delete -Wmismatched-tags @gol
-Wmultiple-inheritance -Wnamespaces -Wnarrowing @gol
-Wnoexcept -Wnoexcept-type -Wnon-virtual-dtor @gol
-Wpessimizing-move -Wno-placement-new -Wplacement-new=@var{n} @gol
@@ -252,7 +265,8 @@ in the following sections.
-Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo @gol
-Wsized-deallocation -Wsuggest-final-methods @gol
-Wsuggest-final-types -Wsuggest-override @gol
--Wno-terminate -Wuseless-cast -Wvirtual-inheritance @gol
+-Wno-terminate -Wuseless-cast -Wno-vexing-parse @gol
+-Wvirtual-inheritance @gol
-Wno-virtual-move-assign -Wvolatile -Wzero-as-null-pointer-constant}
@item Objective-C and Objective-C++ Language Options
@@ -274,7 +288,7 @@ Objective-C and Objective-C++ Dialects}.
-fzero-link @gol
-gen-decls @gol
-Wassign-intercept -Wno-property-assign-default @gol
--Wno-protocol -Wselector @gol
+-Wno-protocol -Wobjc-root-class -Wselector @gol
-Wstrict-selector-match @gol
-Wundeclared-selector}
@@ -374,7 +388,7 @@ Objective-C and Objective-C++ Dialects}.
-Wswitch -Wno-switch-bool -Wswitch-default -Wswitch-enum @gol
-Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand @gol
-Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs @gol
--Wtype-limits -Wundef @gol
+-Wtsan -Wtype-limits -Wundef @gol
-Wuninitialized -Wunknown-pragmas @gol
-Wunsuffixed-float-constants -Wunused @gol
-Wunused-but-set-parameter -Wunused-but-set-variable @gol
@@ -423,6 +437,8 @@ Objective-C and Objective-C++ Dialects}.
-Wno-analyzer-null-dereference @gol
-Wno-analyzer-possible-null-argument @gol
-Wno-analyzer-possible-null-dereference @gol
+-Wno-analyzer-shift-count-negative @gol
+-Wno-analyzer-shift-count-overflow @gol
-Wno-analyzer-stale-setjmp-buffer @gol
-Wno-analyzer-tainted-array-index @gol
-Wanalyzer-too-complex @gol
@@ -448,7 +464,7 @@ Objective-C and Objective-C++ Dialects}.
-gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol
-gas-loc-support -gno-as-loc-support @gol
-gas-locview-support -gno-as-locview-support @gol
--gcolumn-info -gno-column-info @gol
+-gcolumn-info -gno-column-info -gdwarf32 -gdwarf64 @gol
-gstatement-frontiers -gno-statement-frontiers @gol
-gvariable-location-views -gno-variable-location-views @gol
-ginternal-reset-location-views -gno-internal-reset-location-views @gol
@@ -553,7 +569,7 @@ Objective-C and Objective-C++ Dialects}.
-funit-at-a-time -funroll-all-loops -funroll-loops @gol
-funsafe-math-optimizations -funswitch-loops @gol
-fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol
--fweb -fwhole-program -fwpa -fuse-linker-plugin @gol
+-fweb -fwhole-program -fwpa -fuse-linker-plugin -fzero-call-used-regs @gol
--param @var{name}=@var{value}
-O -O0 -O1 -O2 -O3 -Os -Ofast -Og}
@@ -562,6 +578,7 @@ Objective-C and Objective-C++ Dialects}.
@gccoptlist{-p -pg -fprofile-arcs --coverage -ftest-coverage @gol
-fprofile-abs-path @gol
-fprofile-dir=@var{path} -fprofile-generate -fprofile-generate=@var{path} @gol
+-fprofile-info-section -fprofile-info-section=@var{name} @gol
-fprofile-note=@var{path} -fprofile-prefix-path=@var{path} @gol
-fprofile-update=@var{method} -fprofile-filter-files=@var{regex} @gol
-fprofile-exclude-files=@var{regex} @gol
@@ -594,7 +611,7 @@ Objective-C and Objective-C++ Dialects}.
-fpreprocessed -ftabstop=@var{width} -ftrack-macro-expansion @gol
-fwide-exec-charset=@var{charset} -fworking-directory @gol
-H -imacros @var{file} -include @var{file} @gol
--M -MD -MF -MG -MM -MMD -MP -MQ -MT @gol
+-M -MD -MF -MG -MM -MMD -MP -MQ -MT -Mno-modules @gol
-no-integrated-cpp -P -pthread -remap @gol
-traditional -traditional-cpp -trigraphs @gol
-U@var{macro} -undef @gol
@@ -636,7 +653,7 @@ Objective-C and Objective-C++ Dialects}.
-fno-gnu-unique @gol
-finhibit-size-directive -fcommon -fno-ident @gol
-fpcc-struct-return -fpic -fPIC -fpie -fPIE -fno-plt @gol
--fno-jump-tables @gol
+-fno-jump-tables -fno-bit-tests @gol
-frecord-gcc-switches @gol
-freg-struct-return -fshort-enums -fshort-wchar @gol
-fverbose-asm -fpack-struct[=@var{n}] @gol
@@ -1365,9 +1382,10 @@ See RS/6000 and PowerPC Options.
-mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b -mavx512vpopcntdq @gol
-mavx5124fmaps -mavx512vnni -mavx5124vnniw -mprfchw -mrdpid @gol
-mrdseed -msgx -mavx512vp2intersect -mserialize -mtsxldtrk@gol
--mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset@gol
+-mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset -mavxvnni@gol
-mcldemote -mms-bitfields -mno-align-stringops -minline-all-stringops @gol
-minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
+-mkl -mwidekl @gol
-mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy} @gol
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
-m96bit-long-double -mlong-double-64 -mlong-double-80 -mlong-double-128 @gol
@@ -1386,7 +1404,7 @@ See RS/6000 and PowerPC Options.
-mstack-protector-guard-symbol=@var{symbol} @gol
-mgeneral-regs-only -mcall-ms2sysv-xlogues @gol
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
--mindirect-branch-register}
+-mindirect-branch-register -mneeded}
@emph{x86 Windows Options}
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
@@ -1565,7 +1583,7 @@ name suffix). This option applies to all following input files until
the next @option{-x} option. Possible values for @var{language} are:
@smallexample
c c-header cpp-output
-c++ c++-header c++-cpp-output
+c++ c++-header c++-system-header c++-user-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
@@ -2584,6 +2602,18 @@ not explicitly specify. The @var{geom} value is a triple of
':'-separated sizes, in order 'gang', 'worker' and, 'vector'. A size
can be omitted, to use a target-specific default value.
+@item -fopenacc-kernels=@var{mode}
+@opindex fopenacc-kernels
+@cindex OpenACC accelerator programming
+Specify mode of OpenACC `kernels' constructs handling.
+With @option{-fopenacc-kernels=decompose}, OpenACC `kernels'
+constructs are decomposed into parts, a sequence of compute
+constructs, each then handled individually.
+This is work in progress.
+With @option{-fopenacc-kernels=parloops}, OpenACC `kernels' constructs
+are handled by the @samp{parloops} pass, en bloc.
+This is the current default.
+
@item -fopenmp
@opindex fopenmp
@cindex OpenMP parallel
@@ -2804,6 +2834,9 @@ change in version 12.
Version 14, which first appeared in G++ 10, corrects the mangling of
the nullptr expression.
+Version 15, which first appeared in G++ 11, changes the mangling of
+@code{__alignof__} to be distinct from that of @code{alignof}.
+
See also @option{-Wabi}.
@item -fabi-compat-version=@var{n}
@@ -3035,6 +3068,52 @@ To save space, do not emit out-of-line copies of inline functions
controlled by @code{#pragma implementation}. This causes linker
errors if these functions are not inlined everywhere they are called.
+@item -fmodules-ts
+@itemx -fno-modules-ts
+@opindex fmodules-ts
+@opindex fno-modules-ts
+Enable support for C++20 modules (@xref{C++ Modules}). The
+@option{-fno-modules-ts} is usually not needed, as that is the
+default. Even though this is a C++20 feature, it is not currently
+implicitly enabled by selecting that standard version.
+
+@item -fmodule-header
+@itemx -fmodule-header=user
+@itemx -fmodule-header=system
+@opindex fmodule-header
+Compile a header file to create an importable header unit.
+
+@item -fmodule-implicit-inline
+@opindex fmodule-implicit-inline
+Member functions defined in their class definitions are not implicitly
+inline for modular code. This is different to traditional C++
+behavior, for good reasons. However, it may result in a difficulty
+during code porting. This option makes such function definitions
+implicitly inline. It does however generate an ABI incompatibility,
+so you must use it everywhere or nowhere. (Such definitions outside
+of a named module remain implicitly inline, regardless.)
+
+@item -fno-module-lazy
+@opindex fno-module-lazy
+@opindex fmodule-lazy
+Disable lazy module importing and module mapper creation.
+
+@item -fmodule-mapper=@r{[}@var{hostname}@r{]}:@var{port}@r{[}?@var{ident}@r{]}
+@itemx -fmodule-mapper=|@var{program}@r{[}?@var{ident}@r{]} @var{args...}
+@itemx -fmodule-mapper==@var{socket}@r{[}?@var{ident}@r{]}
+@itemx -fmodule-mapper=<>@r{[}@var{inout}@r{]}@r{[}?@var{ident}@r{]}
+@itemx -fmodule-mapper=<@var{in}>@var{out}@r{[}?@var{ident}@r{]}
+@itemx -fmodule-mapper=@var{file}@r{[}?@var{ident}@r{]}
+@vindex CXX_MODULE_MAPPER @r{environment variable}
+@opindex fmodule-mapper
+An oracle to query for module name to filename mappings. If
+unspecified the @env{CXX_MODULE_MAPPER} environment variable is used,
+and if that is unset, an in-process default is provided.
+
+@item -fmodule-only
+@opindex fmodule-only
+Only emit the Compiled Module Interface, inhibiting any object file.
+
@item -fms-extensions
@opindex fms-extensions
Disable Wpedantic warnings about constructs used in MFC, such as implicit
@@ -3282,6 +3361,23 @@ for ISO C++11 onwards (@option{-std=c++11}, ...).
Do not search for header files in the standard directories specific to
C++, but do still search the other standard directories. (This option
is used when building the C++ library.)
+
+@item -flang-info-include-translate
+@itemx -flang-info-include-translate-not
+@itemx -flang-info-include-translate=@var{header}
+@opindex flang-info-include-translate
+@opindex flang-info-include-translate-not
+Diagnose include translation events.
+
+@item -stdlib=@var{libstdc++,libc++}
+@opindex stdlib
+When G++ is configured to support this option, it allows specification of
+alternate C++ runtime libraries. Two options are available: @var{libstdc++}
+(the default, native C++ runtime for G++) and @var{libc++} which is the
+C++ runtime installed on some operating systems (e.g. Darwin versions from
+Darwin11 onwards). The option switches G++ to use the headers from the
+specified library and to emit @code{-lstdc++} or @code{-lc++} respectively,
+when a C++ runtime is required for linking.
@end table
In addition, these warning options have meanings only for C++ programs:
@@ -3358,6 +3454,42 @@ warning is enabled by @option{-Wextra}. With
@option{-Wdeprecated-copy-dtor}, also deprecate if the class has a
user-provided destructor.
+@item -Wno-deprecated-enum-enum-conversion @r{(C++ and Objective-C++ only)}
+@opindex Wdeprecated-enum-enum-conversion
+@opindex Wno-deprecated-enum-enum-conversion
+Disable the warning about the case when the usual arithmetic conversions
+are applied on operands where one is of enumeration type and the other is
+of a different enumeration type. This conversion was deprecated in C++20.
+For example:
+
+@smallexample
+enum E1 @{ e @};
+enum E2 @{ f @};
+int k = f - e;
+@end smallexample
+
+@option{-Wdeprecated-enum-enum-conversion} is enabled by default with
+@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
+by @option{-Wenum-conversion}.
+
+@item -Wno-deprecated-enum-float-conversion @r{(C++ and Objective-C++ only)}
+@opindex Wdeprecated-enum-float-conversion
+@opindex Wno-deprecated-enum-float-conversion
+Disable the warning about the case when the usual arithmetic conversions
+are applied on operands where one is of enumeration type and the other is
+of a floating-point type. This conversion was deprecated in C++20. For
+example:
+
+@smallexample
+enum E1 @{ e @};
+enum E2 @{ f @};
+bool b = e <= 3.7;
+@end smallexample
+
+@option{-Wdeprecated-enum-float-conversion} is enabled by default with
+@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
+by @option{-Wenum-conversion}.
+
@item -Wno-init-list-lifetime @r{(C++ and Objective-C++ only)}
@opindex Winit-list-lifetime
@opindex Wno-init-list-lifetime
@@ -3403,6 +3535,14 @@ the variable declaration statement.
@end itemize
+@item -Winvalid-imported-macros
+@opindex Winvalid-imported-macros
+@opindex Wno-invalid-imported-macros
+Verify all imported macro definitions are valid at the end of
+compilation. This is not enabled by default, as it requires
+additional processing to determine. It may be useful when preparing
+sets of header-units to ensure consistent macros.
+
@item -Wno-literal-suffix @r{(C++ and Objective-C++ only)}
@opindex Wliteral-suffix
@opindex Wno-literal-suffix
@@ -3624,7 +3764,23 @@ void fn () @{
@end smallexample
It does not warn when the type being copied is a trivially-copyable type whose
-size is less than 64 bytes. This warning is enabled by @option{-Wall}.
+size is less than 64 bytes.
+
+This warning also warns when a loop variable in a range-based for-loop is
+initialized with a value of a different type resulting in a copy. For example:
+
+@smallexample
+void fn() @{
+ int arr[10];
+ for (const double &x : arr) @{ @dots{} @}
+@}
+@end smallexample
+
+In the example above, in every iteration of the loop a temporary value of
+type @code{double} is created and destroyed, to which the reference
+@code{const double &} is bound.
+
+This warning is enabled by @option{-Wall}.
@item -Wredundant-tags @r{(C++ and Objective-C++ only)}
@opindex Wredundant-tags
@@ -3700,6 +3856,12 @@ When selecting this option, be aware that the standard library
headers do not obey all of these guidelines; use @samp{grep -v}
to filter out those warnings.
+@item -Wno-exceptions @r{(C++ and Objective-C++ only)}
+@opindex Wexceptions
+@opindex Wno-exceptions
+Disable the warning about the case when an exception handler is shadowed by
+another handler, which can point out a wrong ordering of exception handlers.
+
@item -Wstrict-null-sentinel @r{(C++ and Objective-C++ only)}
@opindex Wstrict-null-sentinel
@opindex Wno-strict-null-sentinel
@@ -3780,6 +3942,40 @@ The warning is inactive inside a system header file, such as the STL, so
one can still use the STL. One may also instantiate or specialize
templates.
+@item -Wno-mismatched-new-delete @r{(C++ and Objective-C++ only)}
+@opindex Wmismatched-new-delete
+@opindex Wno-mismatched-new-delete
+Warn for mismatches between calls to @code{operator new} or @code{operator
+delete} and the corresponding call to the allocation or deallocation function.
+This includes invocations of C++ @code{operator delete} with pointers
+returned from either mismatched forms of @code{operator new}, or from other
+functions that allocate objects for which the @code{operator delete} isn't
+a suitable deallocator, as well as calls to other deallocation functions
+with pointers returned from @code{operator new} for which the deallocation
+function isn't suitable.
+
+For example, the @code{delete} expression in the function below is diagnosed
+because it doesn't match the array form of the @code{new} expression
+the pointer argument was returned from. Similarly, the call to @code{free}
+is also diagnosed.
+
+@smallexample
+void f ()
+@{
+ int *a = new int[n];
+ delete a; // warning: mismatch in array forms of expressions
+
+ char *p = new char[n];
+ free (p); // warning: mismatch between new and free
+@}
+@end smallexample
+
+The related option @option{-Wmismatched-dealloc} diagnoses mismatches
+involving allocation and deallocation functions other than @code{operator
+new} and @code{operator delete}.
+
+@option{-Wmismatched-new-delete} is enabled by default.
+
@item -Wmismatched-tags @r{(C++ and Objective-C++ only)}
@opindex Wmismatched-tags
@opindex Wno-mismatched-tags
@@ -3848,6 +4044,37 @@ use the STL. One may also use using directives and qualified names.
Disable the warning about a throw-expression that will immediately
result in a call to @code{terminate}.
+@item -Wno-vexing-parse @r{(C++ and Objective-C++ only)}
+@opindex Wvexing-parse
+@opindex Wno-vexing-parse
+Warn about the most vexing parse syntactic ambiguity. This warns about
+the cases when a declaration looks like a variable definition, but the
+C++ language requires it to be interpreted as a function declaration.
+For instance:
+
+@smallexample
+void f(double a) @{
+ int i(); // extern int i (void);
+ int n(int(a)); // extern int n (int);
+@}
+@end smallexample
+
+Another example:
+
+@smallexample
+struct S @{ S(int); @};
+void f(double a) @{
+ S x(int(a)); // extern struct S x (int);
+ S y(int()); // extern struct S y (int (*) (void));
+ S z(); // extern struct S z (void);
+@}
+@end smallexample
+
+The warning will suggest options how to deal with such an ambiguity; e.g.,
+it can suggest removing the parentheses or using braces instead.
+
+This warning is enabled by default.
+
@item -Wno-class-conversion @r{(C++ and Objective-C++ only)}
@opindex Wno-class-conversion
@opindex Wclass-conversion
@@ -4267,6 +4494,13 @@ from the superclass. If you use the @option{-Wno-protocol} option, then
methods inherited from the superclass are considered to be implemented,
and no warning is issued for them.
+@item -Wobjc-root-class @r{(Objective-C and Objective-C++ only)}
+@opindex Wobjc-root-class
+Warn if a class interface lacks a superclass. Most classes will inherit
+from @code{NSObject} (or @code{Object}) for example. When declaring
+classes intended to be root classes, the warning can be suppressed by
+marking their interfaces with @code{__attribute__((objc_root_class))}.
+
@item -Wselector @r{(Objective-C and Objective-C++ only)}
@opindex Wselector
@opindex Wno-selector
@@ -5271,7 +5505,6 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Wcomment @gol
-Wduplicate-decl-specifier @r{(C and Objective-C only)} @gol
-Wenum-compare @r{(in C/ObjC; this is on by default in C++)} @gol
--Wenum-conversion @r{in C/ObjC;} @gol
-Wformat @gol
-Wformat-overflow @gol
-Wformat-truncation @gol
@@ -5340,6 +5573,7 @@ name is still supported, but the newer name is more descriptive.)
-Wcast-function-type @gol
-Wdeprecated-copy @r{(C++ only)} @gol
-Wempty-body @gol
+-Wenum-conversion @r{(C only)} @gol
-Wignored-qualifiers @gol
-Wimplicit-fallthrough=3 @gol
-Wmissing-field-initializers @gol
@@ -6170,6 +6404,41 @@ Ignoring the warning can result in poorly optimized code.
disable the warning, but this is not recommended and should be done only
when non-existent profile data is justified.
+@item -Wno-mismatched-dealloc
+@opindex Wmismatched-dealloc
+@opindex Wno-mismatched-dealloc
+
+Warn for calls to deallocation functions with pointer arguments returned
+from from allocations functions for which the former isn't a suitable
+deallocator. A pair of functions can be associated as matching allocators
+and deallocators by use of attribute @code{malloc}. Unless disabled by
+the @option{-fno-builtin} option the standard functions @code{calloc},
+@code{malloc}, @code{realloc}, and @code{free}, as well as the corresponding
+forms of C++ @code{operator new} and @code{operator delete} are implicitly
+associated as matching allocators and deallocators. In the following
+example @code{mydealloc} is the deallocator for pointers returned from
+@code{myalloc}.
+
+@smallexample
+void mydealloc (void*);
+
+__attribute__ ((malloc (mydealloc, 1))) void*
+myalloc (size_t);
+
+void f (void)
+@{
+ void *p = myalloc (32);
+ // @dots{}use p@dots{}
+ free (p); // warning: not a matching deallocator for myalloc
+ mydealloc (p); // ok
+@}
+@end smallexample
+
+In C++, the related option @option{-Wmismatched-new-delete} diagnoses
+mismatches involving either @code{operator new} or @code{operator delete}.
+
+Option @option{-Wmismatched-dealloc} is enabled by default.
+
@item -Wmultistatement-macros
@opindex Wmultistatement-macros
@opindex Wno-multistatement-macros
@@ -6861,37 +7130,28 @@ const char* f (enum Color clr)
Option @option{-Wstringop-overflow=2} is enabled by default.
-@item -Wno-stringop-overread
-@opindex Wstringop-overread
-@opindex Wno-stringop-overread
-Warn for calls to string manipulation functions such as @code{memchr},
-@code{strcpy} that are determined to read past the end of the source
-sequence.
-
-Option @option{-Wstringop-overread} is enabled by default.
-
@table @gcctabopt
@item -Wstringop-overflow
@itemx -Wstringop-overflow=1
@opindex Wstringop-overflow
@opindex Wno-stringop-overflow
The @option{-Wstringop-overflow=1} option uses type-zero Object Size Checking
-to determine the sizes of destination objects. This is the default setting
-of the option. At this setting the option does not warn for writes past
-the end of subobjects of larger objects accessed by pointers unless the
-size of the largest surrounding object is known. When the destination may
-be one of several objects it is assumed to be the largest one of them. On
-Linux systems, when optimization is enabled at this setting the option warns
-for the same code as when the @code{_FORTIFY_SOURCE} macro is defined to
-a non-zero value.
+to determine the sizes of destination objects. At this setting the option
+does not warn for writes past the end of subobjects of larger objects accessed
+by pointers unless the size of the largest surrounding object is known. When
+the destination may be one of several objects it is assumed to be the largest
+one of them. On Linux systems, when optimization is enabled at this setting
+the option warns for the same code as when the @code{_FORTIFY_SOURCE} macro
+is defined to a non-zero value.
@item -Wstringop-overflow=2
The @option{-Wstringop-overflow=2} option uses type-one Object Size Checking
to determine the sizes of destination objects. At this setting the option
-warna about overflows when writing to members of the largest complete
+warns about overflows when writing to members of the largest complete
objects whose exact size is known. However, it does not warn for excessive
writes to the same members of unknown objects referenced by pointers since
-they may point to arrays containing unknown numbers of elements.
+they may point to arrays containing unknown numbers of elements. This is
+the default setting of the option.
@item -Wstringop-overflow=3
The @option{-Wstringop-overflow=3} option uses type-two Object Size Checking
@@ -6909,6 +7169,15 @@ whether to issue a warning. Similarly to @option{-Wstringop-overflow=3} this
setting of the option may result in warnings for benign code.
@end table
+@item -Wno-stringop-overread
+@opindex Wstringop-overread
+@opindex Wno-stringop-overread
+Warn for calls to string manipulation functions such as @code{memchr}, or
+@code{strcpy} that are determined to read past the end of the source
+sequence.
+
+Option @option{-Wstringop-overread} is enabled by default.
+
@item -Wno-stringop-truncation
@opindex Wstringop-truncation
@opindex Wno-stringop-truncation
@@ -7554,7 +7823,7 @@ except when the same as the default promotion.
@opindex Wno-declaration-after-statement
Warn when a declaration is found after a statement in a block. This
construct, known from C++, was introduced with ISO C99 and is by default
-allowed in GCC@. It is not supported by ISO C90. @xref{Mixed Declarations}.
+allowed in GCC@. It is not supported by ISO C90. @xref{Mixed Labels and Declarations}.
@item -Wshadow
@opindex Wshadow
@@ -7661,8 +7930,23 @@ to @option{-Wframe-larger-than=}@samp{SIZE_MAX} or larger.
@item -Wno-free-nonheap-object
@opindex Wno-free-nonheap-object
@opindex Wfree-nonheap-object
-Do not warn when attempting to free an object that was not allocated
-on the heap.
+Warn when attempting to deallocate an object that was either not allocated
+on the heap, or by using a pointer that was not returned from a prior call
+to the corresponding allocation function. For example, because the call
+to @code{stpcpy} returns a pointer to the terminating nul character and
+not to the begginning of the object, the call to @code{free} below is
+diagnosed.
+
+@smallexample
+void f (char *p)
+@{
+ p = stpcpy (p, "abc");
+ // ...
+ free (p); // warning
+@}
+@end smallexample
+
+@option{-Wfree-nonheap-object} is enabled by default.
@item -Wstack-usage=@var{byte-size}
@opindex Wstack-usage
@@ -7749,6 +8033,16 @@ Note that the code above is invalid in C++11.
This warning is enabled by default.
+@item -Wtsan
+@opindex Wtsan
+@opindex Wno-tsan
+Warn about unsupported features in ThreadSanitizer.
+
+ThreadSanitizer does not support @code{std::atomic_thread_fence} and
+can report false positives.
+
+This warning is enabled by default.
+
@item -Wtype-limits
@opindex Wtype-limits
@opindex Wno-type-limits
@@ -8006,11 +8300,12 @@ In C++ enumerated type mismatches in conditional expressions are also
diagnosed and the warning is enabled by default. In C this warning is
enabled by @option{-Wall}.
-@item -Wenum-conversion @r{(C, Objective-C only)}
+@item -Wenum-conversion
@opindex Wenum-conversion
@opindex Wno-enum-conversion
Warn when a value of enumerated type is implicitly converted to a
-different enumerated type. This warning is enabled by @option{-Wextra}.
+different enumerated type. This warning is enabled by @option{-Wextra}
+in C@.
@item -Wjump-misses-init @r{(C, Objective-C only)}
@opindex Wjump-misses-init
@@ -8817,6 +9112,8 @@ Enabling this option effectively enables the following warnings:
-Wanalyzer-possible-null-dereference @gol
-Wanalyzer-null-argument @gol
-Wanalyzer-null-dereference @gol
+-Wanalyzer-shift-count-negative @gol
+-Wanalyzer-shift-count-overflow @gol
-Wanalyzer-stale-setjmp-buffer @gol
-Wanalyzer-tainted-array-index @gol
-Wanalyzer-unsafe-call-within-signal-handler @gol
@@ -8950,6 +9247,35 @@ This warning requires @option{-fanalyzer}, which enables it; use
This diagnostic warns for paths through the code in which a
value known to be NULL is dereferenced.
+@item -Wno-analyzer-shift-count-negative
+@opindex Wanalyzer-shift-count-negative
+@opindex Wno-analyzer-shift-count-negative
+This warning requires @option{-fanalyzer}, which enables it; use
+@option{-Wno-analyzer-shift-count-negative} to disable it.
+
+This diagnostic warns for paths through the code in which a
+shift is attempted with a negative count. It is analogous to
+the @option{-Wshift-count-negative} diagnostic implemented in
+the C/C++ front ends, but is implemented based on analyzing
+interprocedural paths, rather than merely parsing the syntax tree.
+However, the analyzer does not prioritize detection of such paths, so
+false negatives are more likely relative to other warnings.
+
+@item -Wno-analyzer-shift-count-overflow
+@opindex Wanalyzer-shift-count-overflow
+@opindex Wno-analyzer-shift-count-overflow
+This warning requires @option{-fanalyzer}, which enables it; use
+@option{-Wno-analyzer-shift-count-overflow} to disable it.
+
+This diagnostic warns for paths through the code in which a
+shift is attempted with a count greater than or equal to the
+precision of the operand's type. It is analogous to
+the @option{-Wshift-count-overflow} diagnostic implemented in
+the C/C++ front ends, but is implemented based on analyzing
+interprocedural paths, rather than merely parsing the syntax tree.
+However, the analyzer does not prioritize detection of such paths, so
+false negatives are more likely relative to other warnings.
+
@item -Wno-analyzer-stale-setjmp-buffer
@opindex Wanalyzer-stale-setjmp-buffer
@opindex Wno-analyzer-stale-setjmp-buffer
@@ -9420,6 +9746,18 @@ information as possible into a separate output file with the extension
debug information. To be useful, this option requires a debugger capable of
reading @file{.dwo} files.
+@item -gdwarf32
+@itemx -gdwarf64
+@opindex gdwarf32
+@opindex gdwarf64
+If DWARF debugging information is enabled, the @option{-gdwarf32} selects
+the 32-bit DWARF format and the @option{-gdwarf64} selects the 64-bit
+DWARF format. The default is target specific, on most targets it is
+@option{-gdwarf32} though. The 32-bit DWARF format is smaller, but
+can't support more than 2GiB of debug information in any of the DWARF
+debug information sections. The 64-bit DWARF format allows larger debug
+information and might not be well supported by all consumers yet.
+
@item -gdescribe-dies
@opindex gdescribe-dies
Add description attributes to some DWARF DIEs that have no name attribute,
@@ -11307,7 +11645,8 @@ and @option{-fauto-profile}.
@item -fvect-cost-model=@var{model}
@opindex fvect-cost-model
Alter the cost model used for vectorization. The @var{model} argument
-should be one of @samp{unlimited}, @samp{dynamic} or @samp{cheap}.
+should be one of @samp{unlimited}, @samp{dynamic}, @samp{cheap} or
+@samp{very-cheap}.
With the @samp{unlimited} model the vectorized code-path is assumed
to be profitable while with the @samp{dynamic} model a runtime check
guards the vectorized code-path to enable it only for iteration
@@ -11315,7 +11654,14 @@ counts that will likely execute faster than when executing the original
scalar loop. The @samp{cheap} model disables vectorization of
loops where doing so would be cost prohibitive for example due to
required runtime checks for data dependence or alignment but otherwise
-is equal to the @samp{dynamic} model.
+is equal to the @samp{dynamic} model. The @samp{very-cheap} model only
+allows vectorization if the vector code would entirely replace the
+scalar code that is being vectorized. For example, if each iteration
+of a vectorized loop would only be able to handle exactly four iterations
+of the scalar loop, the @samp{very-cheap} model would only allow
+vectorization if the scalar iteration count is known to be a multiple
+of four.
+
The default cost model depends on other optimization flags and is
either @samp{dynamic} or @samp{cheap}.
@@ -12609,6 +12955,19 @@ int foo (void)
Not all targets support this option.
+@item -fzero-call-used-regs=@var{choice}
+@opindex fzero-call-used-regs
+Zero call-used registers at function return to increase program
+security by either mitigating Return-Oriented Programming (ROP)
+attacks or preventing information leakage through registers.
+
+The possible values of @var{choice} are the same as for the
+@code{zero_call_used_regs} attribute (@pxref{Function Attributes}).
+The default is @samp{skip}.
+
+You can control this behavior for a specific function by using the function
+attribute @code{zero_call_used_regs} (@pxref{Function Attributes}).
+
@item --param @var{name}=@var{value}
@opindex param
In some places, GCC uses various constants to control the amount of
@@ -12786,6 +13145,9 @@ growth limit is needed to avoid exponential explosion of code size. Thus for
smaller units, the size is increased to @option{--param large-unit-insns}
before applying @option{--param inline-unit-growth}.
+@item lazy-modules
+Maximum number of concurrently open C++ module files when lazy loading.
+
@item inline-unit-growth
Specifies maximal overall growth of the compilation unit caused by inlining.
For example, parameter value 20 limits unit growth to 1.2 times the original
@@ -12797,6 +13159,9 @@ Specifies maximal overall growth of the compilation unit caused by
interprocedural constant propagation. For example, parameter value 10 limits
unit growth to 1.1 times the original size.
+@item ipa-cp-large-unit-insns
+The size of translation unit that IPA-CP pass considers large.
+
@item large-stack-frame
The limit specifying large stack frames. While inlining the algorithm is trying
to not grow past this limit too much.
@@ -12851,17 +13216,24 @@ Deeper chains are still handled by late inlining.
Probability (in percent) that C++ inline function with comdat visibility
are shared across multiple compilation units.
-@item ipa-modref-max-bases
-@item ipa-modref-max-refs
-@item ipa-modref-max-accesses
+@item modref-max-bases
+@item modref-max-refs
+@item modref-max-accesses
Specifies the maximal number of base pointers, referneces and accesses stored
for a single function by mod/ref analysis.
-@item ipa-modref-max-tests
+@item modref-max-tests
Specifies the maxmal number of tests alias oracle can perform to disambiguate
memory locations using the mod/ref information. This parameter ought to be
-bigger than @option{--param ipa-modref-max-bases} and @option{--param
-ipa-modref-max-refs}.
+bigger than @option{--param modref-max-bases} and @option{--param
+modref-max-refs}.
+
+@item modref-max-depth
+Specifies the maximum depth of DFS walk used by modref escape analysis.
+Setting to 0 disables the analysis completely.
+
+@item modref-max-escape-points
+Specifies the maximum number of escape points tracked by modref per SSA-name.
@item profile-func-internal-id
A parameter to control whether to use function internal id in profile
@@ -13652,11 +14024,64 @@ is greater or equal to this number, use callbacks instead of inline checks.
E.g. to disable inline code use
@option{--param asan-instrumentation-with-call-threshold=0}.
+@item hwasan-instrument-stack
+Enable hwasan instrumentation of statically sized stack-allocated variables.
+This kind of instrumentation is enabled by default when using
+@option{-fsanitize=hwaddress} and disabled by default when using
+@option{-fsanitize=kernel-hwaddress}.
+To disable stack instrumentation use
+@option{--param hwasan-instrument-stack=0}, and to enable it use
+@option{--param hwasan-instrument-stack=1}.
+
+@item hwasan-random-frame-tag
+When using stack instrumentation, decide tags for stack variables using a
+deterministic sequence beginning at a random tag for each frame. With this
+parameter unset tags are chosen using the same sequence but beginning from 1.
+This is enabled by default for @option{-fsanitize=hwaddress} and unavailable
+for @option{-fsanitize=kernel-hwaddress}.
+To disable it use @option{--param hwasan-random-frame-tag=0}.
+
+@item hwasan-instrument-allocas
+Enable hwasan instrumentation of dynamically sized stack-allocated variables.
+This kind of instrumentation is enabled by default when using
+@option{-fsanitize=hwaddress} and disabled by default when using
+@option{-fsanitize=kernel-hwaddress}.
+To disable instrumentation of such variables use
+@option{--param hwasan-instrument-allocas=0}, and to enable it use
+@option{--param hwasan-instrument-allocas=1}.
+
+@item hwasan-instrument-reads
+Enable hwasan checks on memory reads. Instrumentation of reads is enabled by
+default for both @option{-fsanitize=hwaddress} and
+@option{-fsanitize=kernel-hwaddress}.
+To disable checking memory reads use
+@option{--param hwasan-instrument-reads=0}.
+
+@item hwasan-instrument-writes
+Enable hwasan checks on memory writes. Instrumentation of writes is enabled by
+default for both @option{-fsanitize=hwaddress} and
+@option{-fsanitize=kernel-hwaddress}.
+To disable checking memory writes use
+@option{--param hwasan-instrument-writes=0}.
+
+@item hwasan-instrument-mem-intrinsics
+Enable hwasan instrumentation of builtin functions. Instrumentation of these
+builtin functions is enabled by default for both @option{-fsanitize=hwaddress}
+and @option{-fsanitize=kernel-hwaddress}.
+To disable instrumentation of builtin functions use
+@option{--param hwasan-instrument-mem-intrinsics=0}.
+
@item use-after-scope-direct-emission-threshold
If the size of a local variable in bytes is smaller or equal to this
number, directly poison (or unpoison) shadow memory instead of using
run-time callbacks.
+@item tsan-distinguish-volatile
+Emit special instrumentation for accesses to volatiles.
+
+@item tsan-instrument-func-entry-exit
+Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit().
+
@item max-fsm-thread-path-insns
Maximum number of instructions to copy when duplicating blocks on a
finite state automaton jump thread path.
@@ -13696,6 +14121,9 @@ we may be able to devirtualize speculatively.
The maximum number of assertions to add along the default edge of a switch
statement during VRP.
+@item evrp-mode
+Specifies the mode Early VRP should operate in.
+
@item unroll-jam-min-percent
The minimum percentage of memory references that must be optimized
away for the unroll-and-jam transformation to be considered profitable.
@@ -13749,10 +14177,6 @@ code to iterate. 2 allows partial vector loads and stores in all loops.
The parameter only has an effect on targets that support partial
vector loads and stores.
-@item slp-max-insns-in-bb
-Maximum number of instructions in basic block to be
-considered for SLP vectorization.
-
@item avoid-fma-max-bits
Maximum number of bits for which we avoid creating FMAs.
@@ -13864,15 +14288,26 @@ Maximum number of VALUEs handled during a single find_base_term call.
The maximum number of exploded nodes per program point within
the analyzer, before terminating analysis of that point.
+@item analyzer-max-constraints
+The maximum number of constraints per state.
+
@item analyzer-min-snodes-for-call-summary
The minimum number of supernodes within a function for the
analyzer to consider summarizing its effects at call sites.
+@item analyzer-max-enodes-for-full-dump
+The maximum depth of exploded nodes that should appear in a dot dump
+before switching to a less verbose format.
+
@item analyzer-max-recursion-depth
The maximum number of times a callsite can appear in a call stack
within the analyzer, before terminating analysis of a call that would
recurse deeper.
+@item analyzer-max-svalue-depth
+The maximum depth of a symbolic value, before approximating
+the value as unknown.
+
@item gimple-fe-computed-hot-bb-threshold
The number of executions of a basic block which is considered hot.
The parameter is used only in GIMPLE FE.
@@ -13905,6 +14340,24 @@ The number of Newton iterations for calculating the reciprocal for double type.
The precision of division is propotional to this param when division
approximation is enabled. The default value is 2.
+@item aarch64-autovec-preference
+Force an ISA selection strategy for auto-vectorization. Accepts values from
+0 to 4, inclusive.
+@table @samp
+@item 0
+Use the default heuristics.
+@item 1
+Use only Advanced SIMD for auto-vectorization.
+@item 2
+Use only SVE for auto-vectorization.
+@item 3
+Use both Advanced SIMD and SVE. Prefer Advanced SIMD when the costs are
+deemed equal.
+@item 4
+Use both Advanced SIMD and SVE. Prefer SVE when the costs are deemed equal.
+@end table
+The default value is 0.
+
@end table
@end table
@@ -14092,6 +14545,34 @@ the profile feedback data files. See @option{-fprofile-dir}.
To optimize the program based on the collected profile information, use
@option{-fprofile-use}. @xref{Optimize Options}, for more information.
+@item -fprofile-info-section
+@itemx -fprofile-info-section=@var{name}
+@opindex fprofile-info-section
+
+Register the profile information in the specified section instead of using a
+constructor/destructor. The section name is @var{name} if it is specified,
+otherwise the section name defaults to @code{.gcov_info}. A pointer to the
+profile information generated by @option{-fprofile-arcs} or
+@option{-ftest-coverage} is placed in the specified section for each
+translation unit. This option disables the profile information registration
+through a constructor and it disables the profile information processing
+through a destructor. This option is not intended to be used in hosted
+environments such as GNU/Linux. It targets systems with limited resources
+which do not support constructors and destructors. The linker could collect
+the input sections in a continuous memory block and define start and end
+symbols. The runtime support could dump the profiling information registered
+in this linker set during program termination to a serial line for example. A
+GNU linker script example which defines a linker output section follows:
+
+@smallexample
+ .gcov_info :
+ @{
+ PROVIDE (__gcov_info_start = .);
+ KEEP (*(.gcov_info))
+ PROVIDE (__gcov_info_end = .);
+ @}
+@end smallexample
+
@item -fprofile-note=@var{path}
@opindex fprofile-note
@@ -14167,7 +14648,7 @@ Note that it is quite common that execution counts of some part of
programs depends, for example, on length of temporary file names or
memory space randomization (that may affect hash-table collision rate).
Such non-reproducible part of programs may be annotated by
-@code{no_instrument_function} function attribute. @code{gcov-dump} with
+@code{no_instrument_function} function attribute. @command{gcov-dump} with
@option{-l} can be used to dump gathered data and verify that they are
indeed reproducible.
@@ -14190,12 +14671,46 @@ more details. The run-time behavior can be influenced using the
the available options are shown at startup of the instrumented program. See
@url{https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags}
for a list of supported options.
-The option cannot be combined with @option{-fsanitize=thread}.
+The option cannot be combined with @option{-fsanitize=thread} or
+@option{-fsanitize=hwaddress}. Note that the only target this option is
+currently supported on is AArch64.
@item -fsanitize=kernel-address
@opindex fsanitize=kernel-address
Enable AddressSanitizer for Linux kernel.
-See @uref{https://github.com/google/kasan/wiki} for more details.
+See @uref{https://github.com/google/kasan} for more details.
+
+@item -fsanitize=hwaddress
+@opindex fsanitize=hwaddress
+Enable Hardware-assisted AddressSanitizer, which uses a hardware ability to
+ignore the top byte of a pointer to allow the detection of memory errors with
+a low memory overhead.
+Memory access instructions are instrumented to detect out-of-bounds and
+use-after-free bugs.
+The option enables @option{-fsanitize-address-use-after-scope}.
+See
+@uref{https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html}
+for more details. The run-time behavior can be influenced using the
+@env{HWASAN_OPTIONS} environment variable. When set to @code{help=1},
+the available options are shown at startup of the instrumented program.
+The option cannot be combined with @option{-fsanitize=thread} or
+@option{-fsanitize=address}, and is currently only available on AArch64.
+
+@item -fsanitize=kernel-hwaddress
+@opindex fsanitize=kernel-hwaddress
+Enable Hardware-assisted AddressSanitizer for compilation of the Linux kernel.
+Similar to @option{-fsanitize=kernel-address} but using an alternate
+instrumentation method, and similar to @option{-fsanitize=hwaddress} but with
+instrumentation differences necessary for compiling the Linux kernel.
+These differences are to avoid hwasan library initialization calls and to
+account for the stack pointer having a different value in its top byte.
+
+@emph{Note:} This option has different defaults to the @option{-fsanitize=hwaddress}.
+Instrumenting the stack and alloca calls are not on by default but are still
+possible by specifying the command-line options
+@option{--param hwasan-instrument-stack=1} and
+@option{--param hwasan-instrument-allocas=1} respectively. Using a random frame
+tag is not implemented for kernel instrumentation.
@item -fsanitize=pointer-compare
@opindex fsanitize=pointer-compare
@@ -15898,6 +16413,12 @@ building code that forms part of a dynamic linker and cannot
reference the address of a jump table. On some targets, jump tables
do not require a GOT and this option is not needed.
+@item -fno-bit-tests
+@opindex fno-bit-tests
+@opindex fbit-tests
+Do not use bit tests for switch statements even where it would be
+more efficient than other code generation strategies.
+
@item -ffixed-@var{reg}
@opindex ffixed
Treat the register named @var{reg} as a fixed register; generated code
@@ -16537,6 +17058,11 @@ By default, the dump will contain messages about successful
optimizations (equivalent to @option{-optimized}) together with
low-level details about the analysis.
+@item -fdump-lang
+@opindex fdump-lang
+Dump language-specific information. The file name is made by appending
+@file{.lang} to the source file name.
+
@item -fdump-lang-all
@itemx -fdump-lang-@var{switch}
@itemx -fdump-lang-@var{switch}-@var{options}
@@ -16557,6 +17083,14 @@ Enable all language-specific dumps.
Dump class hierarchy information. Virtual table information is emitted
unless '@option{slim}' is specified. This option is applicable to C++ only.
+@item module
+Dump module information. Options @option{lineno} (locations),
+@option{graph} (reachability), @option{blocks} (clusters),
+@option{uid} (serialization), @option{alias} (mergeable),
+@option{asmname} (Elrond), @option{eh} (mapper) & @option{vops}
+(macros) may provide additional information. This option is
+applicable to C++ only.
+
@item raw
Dump the raw internal tree data. This option is applicable to C++ only.
@@ -17587,8 +18121,8 @@ and the features that they enable by default:
@item @samp{armv8-a} @tab Armv8-A @tab @samp{+fp}, @samp{+simd}
@item @samp{armv8.1-a} @tab Armv8.1-A @tab @samp{armv8-a}, @samp{+crc}, @samp{+lse}, @samp{+rdma}
@item @samp{armv8.2-a} @tab Armv8.2-A @tab @samp{armv8.1-a}
-@item @samp{armv8.3-a} @tab Armv8.3-A @tab @samp{armv8.2-a}
-@item @samp{armv8.4-a} @tab Armv8.4-A @tab @samp{armv8.3-a}, @samp{+fp16fml}, @samp{+dotprod}
+@item @samp{armv8.3-a} @tab Armv8.3-A @tab @samp{armv8.2-a}, @samp{+pauth}
+@item @samp{armv8.4-a} @tab Armv8.4-A @tab @samp{armv8.3-a}, @samp{+flagm}, @samp{+fp16fml}, @samp{+dotprod}
@item @samp{armv8.5-a} @tab Armv8.5-A @tab @samp{armv8.4-a}, @samp{+sb}, @samp{+ssbs}, @samp{+predres}
@item @samp{armv8.6-a} @tab Armv8.6-A @tab @samp{armv8.5-a}, @samp{+bf16}, @samp{+i8mm}
@item @samp{armv8-r} @tab Armv8-R @tab @samp{armv8-r}
@@ -17618,7 +18152,7 @@ performance of the code. Permissible values for this option are:
@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
@samp{cortex-a76}, @samp{cortex-a76ae}, @samp{cortex-a77},
@samp{cortex-a65}, @samp{cortex-a65ae}, @samp{cortex-a34},
-@samp{cortex-a78}, @samp{cortex-a78ae},
+@samp{cortex-a78}, @samp{cortex-a78ae}, @samp{cortex-a78c},
@samp{ares}, @samp{exynos-m1}, @samp{emag}, @samp{falkor},
@samp{neoverse-e1}, @samp{neoverse-n1}, @samp{neoverse-n2},
@samp{neoverse-v1}, @samp{qdf24xx}, @samp{saphira},
@@ -17858,6 +18392,10 @@ Enable brain half-precision floating-point instructions. This also enables
Advanced SIMD and floating-point instructions. This option is enabled by
default for @option{-march=armv8.6-a}. Use of this option with architectures
prior to Armv8.2-A is not supported.
+@item flagm
+Enable the Flag Manipulation instructions Extension.
+@item pauth
+Enable the Pointer Authentication Extension.
@end table
@@ -19461,7 +19999,7 @@ Permissible names are: @samp{arm7tdmi}, @samp{arm7tdmi-s}, @samp{arm710t},
@samp{cortex-a32}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55},
@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
@samp{cortex-a76}, @samp{cortex-a76ae}, @samp{cortex-a77},
-@samp{cortex-a78}, @samp{cortex-a78ae},
+@samp{cortex-a78}, @samp{cortex-a78ae}, @samp{cortex-a78c},
@samp{ares}, @samp{cortex-r4}, @samp{cortex-r4f},
@samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8}, @samp{cortex-r52},
@samp{cortex-m0}, @samp{cortex-m0plus}, @samp{cortex-m1}, @samp{cortex-m3},
@@ -27644,7 +28182,7 @@ the backchain is placed into the topmost word of the 96/160 byte register
save area.
In general, code compiled with @option{-mbackchain} is call-compatible with
-code compiled with @option{-mmo-backchain}; however, use of the backchain
+code compiled with @option{-mno-backchain}; however, use of the backchain
for debugging purposes usually requires that the whole binary is built with
@option{-mbackchain}. Note that the combination of @option{-mbackchain},
@option{-mpacked-stack} and @option{-mhard-float} is not supported. In order
@@ -29345,8 +29883,9 @@ A generic CPU with 64-bit extensions.
@itemx x86-64-v3
@itemx x86-64-v4
These choices for @var{cpu-type} select the corresponding
-micro-architecture level from the x86-64 psABI. They are only available
-when compiling for an x86-64 target that uses the System V psABI@.
+micro-architecture level from the x86-64 psABI. On ABIs other than
+the x86-64 psABI they select the same CPU features as the x86-64 psABI
+documents for the particular micro-architecture level.
Since these @var{cpu-type} values do not have a corresponding
@option{-mtune} setting, using @option{-march} with these values enables
@@ -29431,14 +29970,14 @@ BMI, BMI2 and F16C instruction set support.
@item broadwell
Intel Broadwell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
-SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA,
-BMI, BMI2, F16C, RDSEED, ADCX and PREFETCHW instruction set support.
+SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2,
+F16C, RDSEED ADCX and PREFETCHW instruction set support.
@item skylake
Intel Skylake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA,
-BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC and
-XSAVES instruction set support.
+BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC and XSAVES
+instruction set support.
@item bonnell
Intel Bonnell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3 and SSSE3
@@ -29446,34 +29985,36 @@ instruction set support.
@item silvermont
Intel Silvermont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
-SSE4.1, SSE4.2, POPCNT, AES, PCLMUL and RDRND instruction set support.
+SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL and RDRND instruction set support.
@item goldmont
Intel Goldmont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
-SSE4.1, SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT and FSGSBASE
-instruction set support.
+SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES,
+XSAVEOPT and FSGSBASE instruction set support.
@item goldmont-plus
Intel Goldmont Plus CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
-SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE,
-PTWRITE, RDPID, SGX and UMIP instruction set support.
+SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC,
+XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX and UMIP instruction set support.
@item tremont
Intel Tremont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
-SSE4.1, SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, PTWRITE,
-RDPID, SGX, UMIP, GFNI-SSE, CLWB and ENCLV instruction set support.
+SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES,
+XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, UMIP, GFNI-SSE, CLWB, MOVDIRI,
+MOVDIR64B, CLDEMOTE and WAITPKG instruction set support.
@item knl
Intel Knight's Landing CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA,
-BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, AVX512F, AVX512PF, AVX512ER and
-AVX512CD instruction set support.
+BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF,
+AVX512ER and AVX512CD instruction set support.
@item knm
Intel Knights Mill CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA,
-BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, AVX512F, AVX512PF, AVX512ER, AVX512CD,
-AVX5124VNNIW, AVX5124FMAPS and AVX512VPOPCNTDQ instruction set support.
+BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF,
+AVX512ER, AVX512CD, AVX5124VNNIW, AVX5124FMAPS and AVX512VPOPCNTDQ instruction
+set support.
@item skylake-avx512
Intel Skylake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
@@ -29524,8 +30065,8 @@ SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F,
AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP,
RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ,
-VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B and AVX512VP2INTERSECT instruction
-set support.
+VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT and KEYLOCKER
+instruction set support.
@item sapphirerapids
Intel sapphirerapids CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
@@ -29533,12 +30074,15 @@ SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES,
AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI, AVX512BF16,
MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
-SERIALIZE and TSXLDTRK instruction set support.
+SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8 and AVX-VNNI
+instruction set support.
@item alderlake
Intel Alderlake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
-SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, CLDEMOTE,
-PTWRITE, WAITPKG and SERIALIZE instruction set support.
+SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI,
+BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, CLDEMOTE,
+PTWRITE, WAITPKG, SERIALIZE, KEYLOCKER, HRESET and AVX-VNNI instruction set
+support.
@item k6
AMD K6 CPU with MMX instruction set support.
@@ -29615,6 +30159,13 @@ MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A,
SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID,
WBNOINVD, and 64-bit instruction set extensions.)
+@item znver3
+AMD Family 19h core based CPUs with x86-64 instruction set support. (This
+supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED,
+MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A,
+SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID,
+WBNOINVD, PKU, VPCLMULQDQ, VAES, and 64-bit instruction set extensions.)
+
@item btver1
CPUs based on AMD Family 14h cores with x86-64 instruction set support. (This
supersets MMX, SSE, SSE2, SSE3, SSSE3, SSE4A, CX16, ABM and 64-bit
@@ -30311,6 +30862,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mavx512vnni
@opindex mavx512vnni
@need 200
+@itemx -mavxvnni
+@opindex mavxvnni
+@need 200
@itemx -mavx5124vnniw
@opindex mavx5124vnniw
@need 200
@@ -30331,6 +30885,11 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@need 200
@itemx -mhreset
@opindex mhreset
+@itemx -mkl
+@opindex mkl
+@need 200
+@itemx -mwidekl
+@opindex mwidekl
These switches enable the use of instructions in the MMX, SSE,
SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF,
AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA,
@@ -30340,8 +30899,9 @@ WBNOINVD, FMA4, PREFETCHW, RDPID, PREFETCHWT1, RDSEED, SGX, XOP, LWP,
XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2,
GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16,
ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE,
-UINTR, HRESET or CLDEMOTE extended instruction sets. Each has a corresponding
-@option{-mno-} option to disable use of these instructions.
+UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI or CLDEMOTE
+extended instruction sets. Each has a corresponding @option{-mno-} option to
+disable use of these instructions.
These extensions are also available as built-in functions: see
@ref{x86 Built-in Functions}, for details of the functions enabled and
@@ -31057,6 +31617,12 @@ environments.
Generate code for short address mode. This is only supported for 32-bit
and x32 environments. It is the default address mode for 32-bit and
x32 environments.
+
+@item -mneeded
+@itemx -mno-needed
+@opindex mneeded
+Emit GNU_PROPERTY_X86_ISA_1_NEEDED GNU property for Linux target to
+indicate the micro-architecture ISA level required to execute the binary.
@end table
@node x86 Windows Options
@@ -31530,6 +32096,9 @@ Marks the argument containing or following the @samp{%w} as the
designated output file of this compilation. This puts the argument
into the sequence of arguments that @samp{%o} substitutes.
+@item %V
+Indicates that this compilation produces no output file.
+
@item %o
Substitutes the names of all the output files, with spaces
automatically placed around them. You should write spaces
@@ -31548,16 +32117,6 @@ been substituted, except that @samp{%g, %u, and %U} do not currently
support additional @var{suffix} characters following @samp{%O} as they do
following, for example, @samp{.o}.
-@item %p
-Substitutes the standard macro predefinitions for the
-current target machine. Use this when running @command{cpp}.
-
-@item %P
-Like @samp{%p}, but puts @samp{__} before and after the name of each
-predefined macro, except for macros that start with @samp{__} or with
-@samp{_@var{L}}, where @var{L} is an uppercase letter. This is for ISO
-C@.
-
@item %I
Substitute any of @option{-iprefix} (made from @env{GCC_EXEC_PREFIX}),
@option{-isysroot} (made from @env{TARGET_SYSTEM_ROOT}),
@@ -31582,6 +32141,9 @@ searched.
Print @var{str} as an error message. @var{str} is terminated by a newline.
Use this when inconsistent options are detected.
+@item %n@var{str}
+Print @var{str} as a notice. @var{str} is terminated by a newline.
+
@item %(@var{name})
Substitute the contents of spec string @var{name} at this point.
@@ -31598,6 +32160,12 @@ Output the accumulated assembler options specified by @option{-Wa}.
@item %Z
Output the accumulated preprocessor options specified by @option{-Wp}.
+@item %M
+Output @code{multilib_os_dir}.
+
+@item %R
+Output the concatenation of @code{target_system_root} and @code{target_sysroot_suffix}.
+
@item %a
Process the @code{asm} spec. This is used to compute the
switches to be passed to the assembler.
@@ -31657,6 +32225,12 @@ command is position dependent. @samp{%} commands in the spec string
before this one see @code{-S}, @samp{%} commands in the spec string
after this one do not.
+@item %<S*
+Similar to @samp{%<S}, but match all switches beginning with @code{-S}.
+
+@item %>S
+Similar to @samp{%<S}, but keep @code{-S} in the GCC command line.
+
@item %:@var{function}(@var{args})
Call the named function @var{function}, passing it @var{args}.
@var{args} is first processed as a nested spec string, then split
@@ -31717,6 +32291,14 @@ usage:
-l%:if-exists-then-else(%:getenv(VSB_DIR rtnet.h) rtnet net)
@end smallexample
+@item @code{sanitize}
+The @code{sanitize} spec function takes no arguments. It returns non-NULL if
+any address, thread or undefined behavior sanitizers are active.
+
+@smallexample
+%@{%:sanitize(address):-funwind-tables@}
+@end smallexample
+
@item @code{replace-outfile}
The @code{replace-outfile} spec function takes two arguments. It looks for the
first argument in the outfiles array and replaces it with the second argument. Here
@@ -31735,6 +32317,56 @@ its usage:
%:remove-outfile(-lm)
@end smallexample
+@item @code{version-compare}
+The @code{version-compare} spec function takes four or five arguments of the following
+form:
+
+@smallexample
+<comparison-op> <arg1> [<arg2>] <switch> <result>
+@end smallexample
+
+It returns @code{result} if the comparison evaluates to true, and NULL if it doesn't.
+The supported @code{comparison-op} values are:
+
+@table @code
+@item >=
+True if @code{switch} is a later (or same) version than @code{arg1}
+
+@item !>
+Opposite of @code{>=}
+
+@item <
+True if @code{switch} is an earlier version than @code{arg1}
+
+@item !<
+Opposite of @code{<}
+
+@item ><
+True if @code{switch} is @code{arg1} or later, and earlier than @code{arg2}
+
+@item <>
+True if @code{switch} is earlier than @code{arg1}, or is @code{arg2} or later
+@end table
+
+If the @code{switch} is not present at all, the condition is false unless the first character
+of the @code{comparison-op} is @code{!}.
+
+@smallexample
+%:version-compare(>= 10.3 mmacosx-version-min= -lmx)
+@end smallexample
+
+The above example would add @option{-lmx} if @option{-mmacosx-version-min=10.3.9} was
+passed.
+
+@item @code{include}
+The @code{include} spec function behaves much like @code{%include}, with the advantage
+that it can be nested inside a spec and thus be conditionalized. It takes one argument,
+the filename, and looks for it in the startfile path. It always returns NULL.
+
+@smallexample
+%@{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)@}
+@end smallexample
+
@item @code{pass-through-libs}
The @code{pass-through-libs} spec function takes any number of arguments. It
finds any @option{-l} options and any non-options ending in @file{.a} (which it
@@ -31760,6 +32392,25 @@ Use "-Wa,OPTION" to pass "OPTION" to the assembler.
It is used to separate compiler options from assembler options
in the @option{--target-help} output.
+
+@item @code{gt}
+The @code{gt} spec function takes two or more arguments. It returns @code{""} (the
+empty string) if the second-to-last argument is greater than the last argument, and NULL
+otherwise. The following example inserts the @code{link_gomp} spec if the last
+@option{-ftree-parallelize-loops=} option given on the command line is greater than 1:
+
+@smallexample
+%@{%:gt(%@{ftree-parallelize-loops=*:%*@} 1):%:include(libgomp.spec)%(link_gomp)@}
+@end smallexample
+
+@item @code{debug-level-gt}
+The @code{debug-level-gt} spec function takes one argument and returns @code{""} (the
+empty string) if @code{debug_info_level} is greater than the specified number, and NULL
+otherwise.
+
+@smallexample
+%@{%:debug-level-gt(0):%@{gdwarf*:--gdwarf2@}@}
+@end smallexample
@end table
@item %@{S@}
@@ -31774,6 +32425,10 @@ and outputs the command-line option @option{-foo}.
Like %@{@code{S}@} but mark last argument supplied within as a file to be
deleted on failure.
+@item %@@@{S@}
+Like %@{@code{S}@} but puts the result into a @code{FILE} and substitutes
+@code{@@FILE} if an @code{@@file} argument has been supplied.
+
@item %@{S*@}
Substitutes all the switches specified to GCC whose names start
with @code{-S}, but which also take an argument. This is used for
@@ -31856,6 +32511,12 @@ jim.d -bar -boggle
-d jim.d -bar -baz -boggle
@end smallexample
+@item %@{%:@var{function}(@var{args}):X@}
+
+Call function named @var{function} with args @var{args}. If the
+function returns non-NULL, then @code{X} is substituted, if it returns
+NULL, it isn't substituted.
+
@item %@{S:X; T:Y; :D@}
If @code{S} is given to GCC, substitutes @code{X}; else if @code{T} is
@@ -32192,3 +32853,350 @@ precompiled header, the actual behavior is a mixture of the
behavior for the options. For instance, if you use @option{-g} to
generate the precompiled header but not when using it, you may or may
not get debugging information for routines in the precompiled header.
+
+@node C++ Modules
+@section C++ Modules
+@cindex speed of compilation
+
+Modules are a C++ 20 language feature. As the name suggests, it
+provides a modular compilation system, intending to provide both
+faster builds and better library isolation. The ``Merging Modules''
+paper @uref{https://wg21.link/p1103}, provides the easiest to read set
+of changes to the standard, although it does not capture later
+changes. That specification is now part of C++20,
+@uref{git@@github.com:cplusplus/draft.git}, it is considered complete
+(there may be defect reports to come).
+
+@emph{G++'s modules support is not complete.} Other than bugs, the
+known missing pieces are:
+
+@table @emph
+
+@item Private Module Fragment
+The Private Module Fragment is recognized, but an error is emitted.
+
+@item Partition definition visibility rules
+Entities may be defined in implementation partitions, and those
+definitions are not available outside of the module. This is not
+implemented, and the definitions are available to extra-module use.
+
+@item Textual merging of reachable GM entities
+Entities may be multiply defined across different header-units.
+These must be de-duplicated, and this is implemented across imports,
+or when an import redefines a textually-defined entity. However the
+reverse is not implemented---textually redefining an entity that has
+been defined in an imported header-unit. A redefinition error is
+emitted.
+
+@item Translation-Unit local referencing rules
+Papers p1815 (@uref{https://wg21.link/p1815}) and p2003
+(@uref{https://wg21.link/p2003} add limitations on which entities an
+exported region may reference (for instance, the entities an exported
+template definition may reference). These are not fully implemented.
+
+@item Language-linkage module attachment
+Declarations with explicit language linkage (@code{extern "C"} or
+@code{extern "C++"}) are attached to the global module, even when in
+the purview of a named module. This is not implemented. Such
+declarations will be attached to the module, if any, in which they are
+declared.
+
+@item Standard Library Header Units
+The Standard Library is not provided as importable header units. If
+you want to import such units, you must explicitly build them first.
+If you do not do this with care, you may have multiple declarations,
+which the module machinery must merge---compiler resource usage can be
+affected by how you partition header files into header units.
+
+@end table
+
+Modular compilation is @emph{not} enabled with just the
+@option{-std=c++20} option. You must explicitly enable it with the
+@option{-fmodules-ts} option. It is independent of the language
+version selected, although in pre-C++20 versions, it is of course an
+extension.
+
+No new source file suffixes are required or supported. If you wish to
+use a non-standard suffix (@xref{Overall Options}), you also need
+to provide a @option{-x c++} option too.@footnote{Some users like to
+distinguish module interface files with a new suffix, such as naming
+the source @code{module.cppm}, which involves
+teaching all tools about the new suffix. A different scheme, such as
+naming @code{module-m.cpp} would be less invasive.}
+
+Compiling a module interface unit produces an additional output (to
+the assembly or object file), called a Compiled Module Interface
+(CMI). This encodes the exported declarations of the module.
+Importing a module reads in the CMI. The import graph is a Directed
+Acyclic Graph (DAG). You must build imports before the importer.
+
+Header files may themselves be compiled to header units, which are a
+transitional ability aiming at faster compilation. The
+@option{-fmodule-header} option is used to enable this, and implies
+the @option{-fmodules-ts} option. These CMIs are named by the fully
+resolved underlying header file, and thus may be a complete pathname
+containing subdirectories. If the header file is found at an absolute
+pathname, the CMI location is still relative to a CMI root directory.
+
+As header files often have no suffix, you commonly have to specify a
+@option{-x} option to tell the compiler the source is a header file.
+You may use @option{-x c++-header}, @option{-x c++-user-header} or
+@option{-x c++-system-header}. When used in conjunction with
+@option{-fmodules-ts}, these all imply an appropriate
+@option{-fmodule-header} option. The latter two variants use the
+user or system include path to search for the file specified. This
+allows you to, for instance, compile standard library header files as
+header units, without needing to know exactly where they are
+installed. Specifying the language as one of these variants also
+inhibits output of the object file, as header files have no associated
+object file.
+
+The @option{-fmodule-only} option disables generation of the
+associated object file for compiling a module interface. Only the CMI
+is generated. This option is implied when using the
+@option{-fmodule-header} option.
+
+The @option{-flang-info-include-translate} and
+@option{-flang-info-include-translate-not} options notes whether
+include translation occurs or not. With no argument, the first will
+note all include translation. The second will note all
+non-translations of include files not known to intentionally be
+textual. With an argument, queries about include translation of a
+header files with that particular trailing pathname are noted. You
+may repeat this form to cover several different header files. This
+option may be helpful in determining whether include translation is
+happening---if it is working correctly, it'll behave as if it wasn't
+there at all.
+
+The @option{-Winvalid-imported-macros} option causes all imported macros
+to be resolved at the end of compilation. Without this, imported
+macros are only resolved when expanded or (re)defined. This option
+detects conflicting import definitions for all macros.
+
+@xref{C++ Module Mapper} for details of the @option{-fmodule-mapper}
+family of options.
+
+@menu
+* C++ Module Mapper:: Module Mapper
+* C++ Module Preprocessing:: Module Preprocessing
+* C++ Compiled Module Interface:: Compiled Module Interface
+@end menu
+
+@node C++ Module Mapper
+@subsection Module Mapper
+@cindex C++ Module Mapper
+
+A module mapper provides a server or file that the compiler queries to
+determine the mapping between module names and CMI files. It is also
+used to build CMIs on demand. @emph{Mapper functionality is in its
+infancy and is intended for experimentation with build system
+interactions.}
+
+You can specify a mapper with the @option{-fmodule-mapper=@var{val}}
+option or @env{CXX_MODULE_MAPPER} environment variable. The value may
+have one of the following forms:
+
+@table @gcctabopt
+
+@item @r{[}@var{hostname}@r{]}:@var{port}@r{[}?@var{ident}@r{]}
+An optional hostname and a numeric port number to connect to. If the
+hostname is omitted, the loopback address is used. If the hostname
+corresponds to multiple IPV6 addresses, these are tried in turn, until
+one is successful. If your host lacks IPv6, this form is
+non-functional. If you must use IPv4 use
+@option{-fmodule-mapper='|ncat @var{ipv4host} @var{port}'}.
+
+@item =@var{socket}@r{[}?@var{ident}@r{]}
+A local domain socket. If your host lacks local domain sockets, this
+form is non-functional.
+
+@item |@var{program}@r{[}?@var{ident}@r{]} @r{[}@var{args...}@r{]}
+A program to spawn, and communicate with on its stdin/stdout streams.
+Your @var{PATH} environment variable is searched for the program.
+Arguments are separated by space characters, (it is not possible for
+one of the arguments delivered to the program to contain a space). An
+exception is if @var{program} begins with @@. In that case
+@var{program} (sans @@) is looked for in the compiler's internal
+binary directory. Thus the sample mapper-server can be specified
+with @code{@@g++-mapper-server}.
+
+@item <>@r{[}?@var{ident}@r{]}
+@item <>@var{inout}@r{[}?@var{ident}@r{]}
+@item <@var{in}>@var{out}@r{[}?@var{ident}@r{]}
+Named pipes or file descriptors to communicate over. The first form,
+@option{<>}, communicates over stdin and stdout. The other forms
+allow you to specify a file descriptor or name a pipe. A numeric value
+is interpreted as a file descriptor, otherwise named pipe is opened.
+The second form specifies a bidirectional pipe and the last form
+allows specifying two independent pipes. Using file descriptors
+directly in this manner is fragile in general, as it can require the
+cooperation of intermediate processes. In particular using stdin &
+stdout is fraught with danger as other compiler options might also
+cause the compiler to read stdin or write stdout, and it can have
+unfortunate interactions with signal delivery from the terminal.
+
+@item @var{file}@r{[}?@var{ident}@r{]}
+A mapping file consisting of space-separated module-name, filename
+pairs, one per line. Only the mappings for the direct imports and any
+module export name need be provided. If other mappings are provided,
+they override those stored in any imported CMI files. A repository
+root may be specified in the mapping file by using @samp{$root} as the
+module name in the first active line.
+
+@end table
+
+As shown, an optional @var{ident} may suffix the first word of the
+option, indicated by a @samp{?} prefix. The value is used in the
+initial handshake with the module server, or to specify a prefix on
+mapping file lines. In the server case, the main source file name is
+used if no @var{ident} is specified. In the file case, all non-blank
+lines are significant, unless a value is specified, in which case only
+lines beginning with @var{ident} are significant. The @var{ident}
+must be separated by whitespace from the module name. Be aware that
+@samp{<}, @samp{>}, @samp{?}, and @samp{|} characters are often
+significant to the shell, and therefore may need quoting.
+
+The mapper is connected to or loaded lazily, when the first module
+mapping is required. The networking protocols are only supported on
+hosts that provide networking. If no mapper is specified a default is
+provided.
+
+A project-specific mapper is expected to be provided by the build
+system that invokes the compiler. It is not expected that a
+general-purpose server is provided for all compilations. As such, the
+server will know the build configuration, the compiler it invoked, and
+the environment (such as working directory) in which that is
+operating. As it may parallelize builds, several compilations may
+connect to the same socket.
+
+The default mapper generates CMI files in a @samp{gcm.cache}
+directory. CMI files have a @samp{.gcm} suffix. The module unit name
+is used directly to provide the basename. Header units construct a
+relative path using the underlying header file name. If the path is
+already relative, a @samp{,} directory is prepended. Internal
+@samp{..} components are translated to @samp{,,}. No attempt is made
+to canonicalize these filenames beyond that done by the preprocessor's
+include search algorithm, as in general it is ambiguous when symbolic
+links are present.
+
+The mapper protocol was published as ``A Module Mapper''
+@uref{https://wg21.link/p1184}. The implementation is provided by
+@command{libcody}, @uref{https://github.com/urnathan/libcody},
+which specifies the canonical protocol definition. A proof of concept
+server implementation embedded in @command{make} was described in
+''Make Me A Module'', @uref{https://wg21.link/p1602}.
+
+@node C++ Module Preprocessing
+@subsection Module Preprocessing
+@cindex C++ Module Preprocessing
+
+Modules affect preprocessing because of header units and include
+translation. Some uses of the preprocessor as a separate step either
+do not produce a correct output, or require CMIs to be available.
+
+Header units import macros. These macros can affect later conditional
+inclusion, which therefore can cascade to differing import sets. When
+preprocessing, it is necessary to load the CMI. If a header unit is
+unavailable, the preprocessor issues a warning and continue (when
+not just preprocessing, an error is emitted). Detecting such imports
+requires preprocessor tokenization of the input stream to phase 4
+(macro expansion).
+
+Include translation converts @code{#include}, @code{#include_next} and
+@code{#import} directives to internal @code{import} declarations.
+Whether a particular directive is translated is controlled by the
+module mapper. Header unit names are canonicalized during
+preprocessing.
+
+Dependency information can be emitted for macro import, extending the
+functionality of @option{-MD} and @option{-MMD} options. Detection of
+import declarations also requires phase 4 preprocessing, and thus
+requires full preprocessing (or compilation).
+
+The @option{-M}, @option{-MM} and @option{-E -fdirectives-only} options halt
+preprocessing before phase 4.
+
+The @option{-save-temps} option uses @option{-fdirectives-only} for
+preprocessing, and preserve the macro definitions in the preprocessed
+output. Usually you also want to use this option when explicitly
+preprocessing a header-unit, or consuming such preprocessed output:
+
+@smallexample
+g++ -fmodules-ts -E -fdirectives-only my-header.hh -o my-header.ii
+g++ -x c++-header -fmodules-ts -fpreprocessed -fdirectives-only my-header.ii
+@end smallexample
+
+@node C++ Compiled Module Interface
+@subsection Compiled Module Interface
+@cindex C++ Compiled Module Interface
+
+CMIs are an additional artifact when compiling named module
+interfaces, partitions or header units. These are read when
+importing. CMI contents are implementation-specific, and in GCC's
+case tied to the compiler version. Consider them a rebuildable cache
+artifact, not a distributable object.
+
+When creating an output CMI, any missing directory components are
+created in a manner that is safe for concurrent builds creating
+multiple, different, CMIs within a common subdirectory tree.
+
+CMI contents are written to a temporary file, which is then atomically
+renamed. Observers either see old contents (if there is an
+existing file), or complete new contents. They do not observe the
+CMI during its creation. This is unlike object file writing, which
+may be observed by an external process.
+
+CMIs are read in lazily, if the host OS provides @code{mmap}
+functionality. Generally blocks are read when name lookup or template
+instantiation occurs. To inhibit this, the @option{-fno-module-lazy}
+option may be used.
+
+The @option{--param lazy-modules=@var{n}} parameter controls the limit
+on the number of concurrently open module files during lazy loading.
+Should more modules be imported, an LRU algorithm is used to determine
+which files to close---until that file is needed again. This limit
+may be exceeded with deep module dependency hierarchies. With large
+code bases there may be more imports than the process limit of file
+descriptors. By default, the limit is a few less than the per-process
+file descriptor hard limit, if that is determinable.@footnote{Where
+applicable the soft limit is incremented as needed towards the hard limit.}
+
+GCC CMIs use ELF32 as an architecture-neutral encapsulation mechanism.
+You may use @command{readelf} to inspect them, although section
+contents are largely undecipherable. There is a section named
+@code{.gnu.c++.README}, which contains human-readable text. Other
+than the first line, each line consists of @code{@var{tag}: @code{value}}
+tuples.
+
+@smallexample
+> @command{readelf -p.gnu.c++.README gcm.cache/foo.gcm}
+
+String dump of section '.gnu.c++.README':
+ [ 0] GNU C++ primary module interface
+ [ 21] compiler: 11.0.0 20201116 (experimental) [c++-modules revision 20201116-0454]
+ [ 6f] version: 2020/11/16-04:54
+ [ 89] module: foo
+ [ 95] source: c_b.ii
+ [ a4] dialect: C++20/coroutines
+ [ be] cwd: /data/users/nathans/modules/obj/x86_64/gcc
+ [ ee] repository: gcm.cache
+ [ 104] buildtime: 2020/11/16 15:03:21 UTC
+ [ 127] localtime: 2020/11/16 07:03:21 PST
+ [ 14a] export: foo:part1 foo-part1.gcm
+@end smallexample
+
+Amongst other things, this lists the source that was built, C++
+dialect used and imports of the module.@footnote{The precise contents
+of this output may change.} The timestamp is the same value as that
+provided by the @code{__DATE__} & @code{__TIME__} macros, and may be
+explicitly specified with the environment variable
+@code{SOURCE_DATE_EPOCH}. @xref{Environment Variables} for further
+details.
+
+A set of related CMIs may be copied, provided the relative pathnames
+are preserved.
+
+The @code{.gnu.c++.README} contents do not affect CMI integrity, and
+it may be removed or altered. The section numbering of the sections
+whose names do not begin with @code{.gnu.c++.}, or are not the string
+section is significant and must not be altered.
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 2b46286..ec6ec18 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1634,7 +1634,7 @@ constraints with multiple alternatives, sometimes one alternative
requires @samp{&} while others do not. See, for example, the
@samp{movdf} insn of the 68000.
-A operand which is read by the instruction can be tied to an earlyclobber
+An operand which is read by the instruction can be tied to an earlyclobber
operand if its only use as an input occurs before the early result is
written. Adding alternatives of this form often allows GCC to produce
better code when only some of the read operands can be affected by the
@@ -5626,6 +5626,28 @@ with N signed/unsigned elements of size S@. Operand 2 is a constant. Shift
the high/low elements of operand 1, and put the N/2 results of size 2*S in the
output vector (operand 0).
+@cindex @code{vec_widen_saddl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_saddl_lo_@var{m}} instruction pattern
+@cindex @code{vec_widen_uaddl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_uaddl_lo_@var{m}} instruction pattern
+@item @samp{vec_widen_uaddl_hi_@var{m}}, @samp{vec_widen_uaddl_lo_@var{m}}
+@itemx @samp{vec_widen_saddl_hi_@var{m}}, @samp{vec_widen_saddl_lo_@var{m}}
+Signed/Unsigned widening add long. Operands 1 and 2 are vectors with N
+signed/unsigned elements of size S@. Add the high/low elements of 1 and 2
+together, widen the resulting elements and put the N/2 results of size 2*S in
+the output vector (operand 0).
+
+@cindex @code{vec_widen_ssubl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_ssubl_lo_@var{m}} instruction pattern
+@cindex @code{vec_widen_usubl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_usubl_lo_@var{m}} instruction pattern
+@item @samp{vec_widen_usubl_hi_@var{m}}, @samp{vec_widen_usubl_lo_@var{m}}
+@itemx @samp{vec_widen_ssubl_hi_@var{m}}, @samp{vec_widen_ssubl_lo_@var{m}}
+Signed/Unsigned widening subtract long. Operands 1 and 2 are vectors with N
+signed/unsigned elements of size S@. Subtract the high/low elements of 2 from
+1 and widen the resulting elements. Put the N/2 results of size 2*S in the
+output vector (operand 0).
+
@cindex @code{mulhisi3} instruction pattern
@item @samp{mulhisi3}
Multiply operands 1 and 2, which have mode @code{HImode}, and store
@@ -6132,6 +6154,54 @@ floating-point mode.
This pattern is not allowed to @code{FAIL}.
+@cindex @code{cadd90@var{m}3} instruction pattern
+@item @samp{cadd90@var{m}3}
+Perform vector add and subtract on even/odd number pairs. The operation being
+matched is semantically described as
+
+@smallexample
+ for (int i = 0; i < N; i += 2)
+ @{
+ c[i] = a[i] - b[i+1];
+ c[i+1] = a[i+1] + b[i];
+ @}
+@end smallexample
+
+This operation is semantically equivalent to performing a vector addition of
+complex numbers in operand 1 with operand 2 rotated by 90 degrees around
+the argand plane and storing the result in operand 0.
+
+In GCC lane ordering the real part of the number must be in the even lanes with
+the imaginary part in the odd lanes.
+
+The operation is only supported for vector modes @var{m}.
+
+This pattern is not allowed to @code{FAIL}.
+
+@cindex @code{cadd270@var{m}3} instruction pattern
+@item @samp{cadd270@var{m}3}
+Perform vector add and subtract on even/odd number pairs. The operation being
+matched is semantically described as
+
+@smallexample
+ for (int i = 0; i < N; i += 2)
+ @{
+ c[i] = a[i] + b[i+1];
+ c[i+1] = a[i+1] - b[i];
+ @}
+@end smallexample
+
+This operation is semantically equivalent to performing a vector addition of
+complex numbers in operand 1 with operand 2 rotated by 270 degrees around
+the argand plane and storing the result in operand 0.
+
+In GCC lane ordering the real part of the number must be in the even lanes with
+the imaginary part in the odd lanes.
+
+The operation is only supported for vector modes @var{m}.
+
+This pattern is not allowed to @code{FAIL}.
+
@cindex @code{ffs@var{m}2} instruction pattern
@item @samp{ffs@var{m}2}
Store into operand 0 one plus the index of the least significant 1-bit
@@ -11201,11 +11271,11 @@ The construct:
@end smallexample
defines a pseudo integer constant @var{name} that can be instantiated as
-@var{inti} if condition @var{condi} is true. Each @var{int}
-must have the same rtx format. @xref{RTL Classes}. Int iterators can appear
-in only those rtx fields that have 'i' as the specifier. This means that
-each @var{int} has to be a constant defined using define_constant or
-define_c_enum.
+@var{inti} if condition @var{condi} is true. Each @var{int} must have the
+same rtx format. @xref{RTL Classes}. Int iterators can appear in only
+those rtx fields that have 'i', 'n', 'w', or 'p' as the specifier. This
+means that each @var{int} has to be a constant defined using define_constant
+or define_c_enum.
As with mode and code iterators, each pattern that uses @var{name} will be
expanded @var{n} times, once with all uses of @var{name} replaced by
diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi
index a8e83fc..aabfb82 100644
--- a/gcc/doc/options.texi
+++ b/gcc/doc/options.texi
@@ -454,9 +454,6 @@ operands, which is passed to the @samp{warning} function. If an alias
is marked @code{Warn}, the target of the alias must not also be marked
@code{Warn}.
-@item Report
-The state of the option should be printed by @option{-fverbose-asm}.
-
@item Warning
This is a warning option and should be shown as such in
@option{--help} output. This flag does not currently affect anything
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index a5ae414..c86df5c 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -709,7 +709,8 @@ loop.
The pass is implemented in @file{tree-vectorizer.c} (the main driver),
@file{tree-vect-loop.c} and @file{tree-vect-loop-manip.c} (loop specific parts
and general loop utilities), @file{tree-vect-slp} (loop-aware SLP
-functionality), @file{tree-vect-stmts.c} and @file{tree-vect-data-refs.c}.
+functionality), @file{tree-vect-stmts.c}, @file{tree-vect-data-refs.c} and
+@file{tree-vect-slp-patterns.c} containing the SLP pattern matcher.
Analysis of data references is in @file{tree-data-ref.c}.
SLP Vectorization. This pass performs vectorization of straight-line code. The
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 23a8b41..1c211bb 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -218,6 +218,10 @@ enum plugin_event
as a const char* pointer. */
PLUGIN_INCLUDE_FILE,
+ /* Called when -fanalyzer starts. The event data is an
+ ana::plugin_analyzer_init_iface *. */
+ PLUGIN_ANALYZER_INIT,
+
PLUGIN_EVENT_FIRST_DYNAMIC /* Dummy event used for indexing callback
array. */
@};
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index 22af573..86290de 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -39,6 +39,7 @@ form uses nested parentheses to indicate the pointers in the internal form.
* Debug Information:: Expressions representing debugging information.
* Insns:: Expression types for entire insns.
* Calls:: RTL representation of function call insns.
+* RTL SSA:: An on-the-side SSA form for RTL
* Sharing:: Some expressions are unique; others *must* be copied.
* Reading RTL:: Reading textual RTL from a file.
@end menu
@@ -1406,6 +1407,12 @@ Pointer bounds modes. Used to represent values of pointer bounds type.
Operations in these modes may be executed as NOPs depending on hardware
features and environment setup.
+@findex MODE_OPAQUE
+@item MODE_OPAQUE
+This is a mode class for modes that don't want to provide operations
+other than register moves, memory moves, loads, stores, and
+@code{unspec}s. They have a size and precision and that's all.
+
@findex MODE_RANDOM
@item MODE_RANDOM
This is a catchall mode class for modes which don't fit into the above
@@ -1705,6 +1712,24 @@ machine's or host machine's floating point format. To convert them to
the precise bit pattern used by the target machine, use the macro
@code{REAL_VALUE_TO_TARGET_DOUBLE} and friends (@pxref{Data Output}).
+@findex const_double_zero
+The host dependency for the number of integers used to store a double
+value makes it problematic for machine descriptions to use expressions
+of code @code{const_double} and therefore a syntactic alias has been
+provided:
+
+@smallexample
+(const_double_zero)
+@end smallexample
+
+standing for:
+
+@smallexample
+(const_double 0 0 @dots{})
+@end smallexample
+
+for matching the floating-point value zero, possibly the only useful one.
+
@findex CONST_WIDE_INT
@item (const_wide_int:@var{m} @var{nunits} @var{elt0} @dots{})
This contains an array of @code{HOST_WIDE_INT}s that is large enough
@@ -4420,6 +4445,792 @@ function. Similarly, if registers other than those in
containing a single @code{clobber} follow immediately after the call to
indicate which registers.
+@node RTL SSA
+@section On-the-Side SSA Form for RTL
+@cindex SSA, RTL form
+@cindex RTL SSA
+
+The patterns of an individual RTL instruction describe which registers
+are inputs to that instruction and which registers are outputs from
+that instruction. However, it is often useful to know where the
+definition of a register input comes from and where the result of
+a register output is used. One way of obtaining this information
+is to use the RTL SSA form, which provides a Static Single Assignment
+representation of the RTL instructions.
+
+The RTL SSA code is located in the @file{rtl-ssa} subdirectory of the GCC
+source tree. This section only gives a brief overview of it; please
+see the comments in the source code for more details.
+
+@menu
+* Using RTL SSA:: What a pass needs to do to use the RTL SSA form
+* RTL SSA Instructions:: How instructions are represented and organized
+* RTL SSA Basic Blocks:: How instructions are grouped into blocks
+* RTL SSA Resources:: How registers and memory are represented
+* RTL SSA Accesses:: How register and memory accesses are represented
+* RTL SSA Phi Nodes:: How multiple sources are combined into one
+* RTL SSA Access Lists:: How accesses are chained together
+* Changing RTL Instructions:: How to use the RTL SSA framework to change insns
+@end menu
+
+@node Using RTL SSA
+@subsection Using RTL SSA in a pass
+
+A pass that wants to use the RTL SSA form should start with the following:
+
+@smallexample
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+@end smallexample
+
+All the RTL SSA code is contained in the @code{rtl_ssa} namespace,
+so most passes will then want to do:
+
+@smallexample
+using namespace rtl_ssa;
+@end smallexample
+
+However, this is purely a matter of taste, and the examples in the rest of
+this section do not require it.
+
+The RTL SSA represention is an optional on-the-side feature that applies
+on top of the normal RTL instructions. It is currently local to individual
+RTL passes and is not maintained across passes.
+
+However, in order to allow the RTL SSA information to be preserved across
+passes in future, @samp{crtl->ssa} points to the current function's
+SSA form (if any). Passes that want to use the RTL SSA form should
+first do:
+
+@smallexample
+crtl->ssa = new rtl_ssa::function_info (@var{fn});
+@end smallexample
+
+where @var{fn} is the function that the pass is processing.
+(Passes that are @code{using namespace rtl_ssa} do not need
+the @samp{rtl_ssa::}.)
+
+Once the pass has finished with the SSA form, it should do the following:
+
+@smallexample
+free_dominance_info (CDI_DOMINATORS);
+if (crtl->ssa->perform_pending_updates ())
+ cleanup_cfg (0);
+
+delete crtl->ssa;
+crtl->ssa = nullptr;
+@end smallexample
+
+The @code{free_dominance_info} call is necessary because
+dominance information is not currently maintained between RTL passes.
+The next two lines commit any changes to the RTL instructions that
+were queued for later; see the comment above the declaration of
+@code{perform_pending_updates} for details. The final two lines
+discard the RTL SSA form and free the associated memory.
+
+@node RTL SSA Instructions
+@subsection RTL SSA Instructions
+
+@cindex RPO
+@cindex reverse postorder
+@cindex instructions, RTL SSA
+@findex rtl_ssa::insn_info
+RTL SSA instructions are represented by an @code{rtl_ssa::insn_info}.
+These instructions are chained together in a single list that follows
+a reverse postorder (RPO) traversal of the function. This means that
+if any path through the function can execute an instruction @var{I1}
+and then later execute an instruction @var{I2} for the first time,
+@var{I1} appears before @var{I2} in the list@footnote{Note that this
+order is different from the order of the underlying RTL instructions,
+which follow machine code order instead.}.
+
+Two RTL SSA instructions can be compared to find which instruction
+occurs earlier than the other in the RPO@. One way to do this is
+to use the C++ comparison operators, such as:
+
+@example
+*@var{insn1} < *@var{insn2}
+@end example
+
+Another way is to use the @code{compare_with} function:
+
+@example
+@var{insn1}->compare_with (@var{insn2})
+@end example
+
+This expression is greater than zero if @var{insn1} comes after @var{insn2}
+in the RPO, less than zero if @var{insn1} comes before @var{insn2} in the
+RPO, or zero if @var{insn1} and @var{insn2} are the same. This order is
+maintained even if instructions are added to the function or moved around.
+
+The main purpose of @code{rtl_ssa::insn_info} is to hold
+SSA information about an instruction. However, it also caches
+certain properties of the instruction, such as whether it is an
+inline assembly instruction, whether it has volatile accesses, and so on.
+
+@node RTL SSA Basic Blocks
+@subsection RTL SSA Basic Blocks
+
+@cindex basic blocks, RTL SSA
+@findex basic_block
+@findex rtl_ssa::bb_info
+RTL SSA instructions (@pxref{RTL SSA Instructions}) are organized into
+basic blocks, with each block being represented by an @code{rtl_ssa:bb_info}.
+There is a one-to-one mapping between these @code{rtl_ssa:bb_info}
+structures and the underlying CFG @code{basic_block} structures
+(@pxref{Basic Blocks}).
+
+@cindex ``real'' instructions, RTL SSA
+@anchor{real RTL SSA insns}
+If a CFG basic block @var{bb} contains an RTL instruction @var{insn},
+the RTL SSA represenation of @var{bb} also contains an RTL SSA representation
+of @var{insn}@footnote{Note that this excludes non-instruction things like
+@code{note}s and @code{barrier}s that also appear in the chain of RTL
+instructions.}. Within RTL SSA, these instructions are referred to as
+``real'' instructions. These real instructions fall into two groups:
+debug instructions and nondebug instructions. Only nondebug instructions
+should affect code generation decisions.
+
+In addition, each RTL SSA basic block has two ``artificial''
+instructions: a ``head'' instruction that comes before all the real
+instructions and an ``end'' instruction that comes after all real
+instructions. These instructions exist to represent things that
+are conceptually defined or used at the start and end of a basic block.
+The instructions always exist, even if they do not currently do anything.
+
+Like instructions, these blocks are chained together in a reverse
+postorder. This list includes the entry block (which always comes
+first) and the exit block (which always comes last).
+
+@cindex extended basic blocks, RTL SSA
+@findex rtl_ssa::ebb_info
+RTL SSA basic blocks are chained together into ``extended basic blocks''
+(EBBs), represented by an @code{rtl_ssa::ebb_info}. Extended basic
+blocks contain one or more basic blocks. They have the property
+that if a block @var{bby} comes immediately after a block @var{bbx}
+in an EBB, then @var{bby} can only be reached by @var{bbx}; in other words,
+@var{bbx} is the sole predecessor of @var{bby}.
+
+Each extended basic block starts with an artificial ``phi node''
+instruction. This instruction defines all phi nodes for the EBB
+(@pxref{RTL SSA Phi Nodes}). (Individual blocks in an EBB do not
+need phi nodes because their live values can only come from one source.)
+
+The contents of a function are therefore represented using a
+four-level hierarchy:
+
+@itemize @bullet
+@item
+functions (@code{rtl_ssa::function_info}), which contain @dots{}
+
+@item
+extended basic blocks (@code{rtl_ssa::ebb_info}), which contain @dots{}
+
+@item
+basic blocks (@code{rtl_ssa::bb_info}), which contain @dots{}
+
+@item
+instructions (@code{rtl_ssa::insn_info})
+@end itemize
+
+In dumps, a basic block is identified as @code{bb@var{n}}, where @var{n}
+is the index of the associated CFG @code{basic_block} structure.
+An EBB is in turn identified by the index of its first block.
+For example, an EBB that contains @samp{bb10}, @code{bb5}, @code{bb6}
+and @code{bb9} is identified as @var{ebb10}.
+
+@node RTL SSA Resources
+@subsection RTL SSA Resources
+
+The RTL SSA form tracks two types of ``resource'': registers and memory.
+Each hard and pseudo register is a separate resource. Memory is a
+single unified resource, like it is in GIMPLE (@pxref{GIMPLE}).
+
+Each resource has a unique identifier. The unique identifier for a
+register is simply its register number. The unique identifier for
+memory is a special register number called @code{MEM_REGNO}.
+
+Since resource numbers so closely match register numbers, it is sometimes
+convenient to refer to them simply as register numbers, or ``regnos''
+for short. However, the RTL SSA form also provides an abstraction
+of resources in the form of @code{rtl_ssa::resource_info}.
+This is a lightweight class that records both the regno of a resource
+and the @code{machine_mode} that the resource has (@pxref{Machine Modes}).
+It has functions for testing whether a resource is a register or memory.
+In principle it could be extended to other kinds of resource in future.
+
+@node RTL SSA Accesses
+@subsection RTL SSA Register and Memory Accesses
+
+In the RTL SSA form, most reads or writes of a resource are
+represented as a @code{rtl_ssa::access_info}@footnote{The exceptions
+are call clobbers, which are generally represented separately.
+See the comment above @code{rtl_ssa::insn_info} for details.}.
+These @code{rtl_ssa::access_info}s are organized into the following
+class hierarchy:
+
+@findex rtl_ssa::access_info
+@findex rtl_ssa::use_info
+@findex rtl_ssa::def_info
+@findex rtl_ssa::clobber_info
+@findex rtl_ssa::set_info
+@findex rtl_ssa::phi_info
+@smallexample
+rtl_ssa::access_info
+ |
+ +-- rtl_ssa::use_info
+ |
+ +-- rtl_ssa::def_info
+ |
+ +-- rtl_ssa::clobber_info
+ |
+ +-- rtl_ssa::set_info
+ |
+ +-- rtl_ssa::phi_info
+@end smallexample
+
+A @code{rtl_ssa::use_info} represents a read or use of a resource and
+a @code{rtl_ssa::def_info} represents a write or definition of a resource.
+As in the main RTL representation, there are two basic types of
+definition: clobbers and sets. The difference is that a clobber
+leaves the register with an unspecified value that cannot be used
+or relied on by later instructions, while a set leaves the register
+with a known value that later instructions could use if they wanted to.
+A @code{rtl_ssa::clobber_info} represents a clobber and
+a @code{rtl_ssa::set_info} represent a set.
+
+Each @code{rtl_ssa::use_info} records which single @code{rtl_ssa::set_info}
+provides the value of the resource; this is null if the resource is
+completely undefined at the point of use. Each @code{rtl_ssa::set_info}
+in turn records all the @code{rtl_ssa::use_info}s that use its value.
+
+If a value of a resource can come from multiple sources,
+a @code{rtl_ssa::phi_info} brings those multiple sources together
+into a single definition (@pxref{RTL SSA Phi Nodes}).
+
+@node RTL SSA Phi Nodes
+@subsection RTL SSA Phi Nodes
+
+@cindex phi nodes, RTL SSA
+@findex rtl_ssa::phi_info
+If a resource is live on entry to an extended basic block and if the
+resource's value can come from multiple sources, the extended basic block
+has a ``phi node'' that collects together these multiple sources.
+The phi node conceptually has one input for each incoming edge of
+the extended basic block, with the input specifying the value of
+the resource on that edge. For example, suppose a function contains
+the following RTL:
+
+@smallexample
+;; Basic block bb3
+@dots{}
+(set (reg:SI R1) (const_int 0)) ;; A
+(set (pc) (label_ref bb5))
+
+;; Basic block bb4
+@dots{}
+(set (reg:SI R1) (const_int 1)) ;; B
+;; Fall through
+
+;; Basic block bb5
+;; preds: bb3, bb4
+;; live in: R1 @dots{}
+(code_label bb5)
+@dots{}
+(set (reg:SI @var{R2})
+ (plus:SI (reg:SI R1) @dots{})) ;; C
+@end smallexample
+
+The value of R1 on entry to block 5 can come from either A or B@.
+The extended basic block that contains block 5 would therefore have a
+phi node with two inputs: the first input would have the value of
+R1 defined by A and the second input would have the value of
+R1 defined by B@. This phi node would then provide the value of
+R1 for C (assuming that R1 does not change again between
+the start of block 5 and C).
+
+Since RTL is not a ``native'' SSA representation, these phi nodes
+simply collect together definitions that already exist. Each input
+to a phi node for a resource @var{R} is itself a definition of
+resource @var{R} (or is null if the resource is completely
+undefined for a particular incoming edge). This is in contrast
+to a native SSA representation like GIMPLE, where the phi inputs
+can be arbitrary expressions. As a result, RTL SSA phi nodes
+never involve ``hidden'' moves: all moves are instead explicit.
+
+Phi nodes are represented as a @code{rtl_ssa::phi_node}.
+Each input to a phi node is represented as an @code{rtl_ssa::use_info}.
+
+@node RTL SSA Access Lists
+@subsection RTL SSA Access Lists
+
+All the definitions of a resource are chained together in reverse postorder.
+In general, this list can contain an arbitrary mix of both sets
+(@code{rtl_ssa::set_info}) and clobbers (@code{rtl_ssa::clobber_info}).
+However, it is often useful to skip over all intervening clobbers
+of a resource in order to find the next set. The list is constructed
+in such a way that this can be done in amortized constant time.
+
+All uses (@code{rtl_ssa::use_info}) of a given set are also chained
+together into a list. This list of uses is divided into three parts:
+
+@enumerate
+@item
+uses by ``real'' nondebug instructions (@pxref{real RTL SSA insns})
+
+@item
+uses by real debug instructions
+
+@item
+uses by phi nodes (@pxref{RTL SSA Phi Nodes})
+@end enumerate
+
+The first and second parts individually follow reverse postorder.
+The third part has no particular order.
+
+@cindex degenerate phi node, RTL SSA
+The last use by a real nondebug instruction always comes earlier in
+the reverse postorder than the next definition of the resource (if any).
+This means that the accesses follow a linear sequence of the form:
+
+@itemize @bullet
+@item
+first definition of resource R
+
+@itemize @bullet
+@item
+first use by a real nondebug instruction of the first definition of resource R
+
+@item
+@dots{}
+
+@item
+last use by a real nondebug instruction of the first definition of resource R
+@end itemize
+
+@item
+second definition of resource R
+
+@itemize @bullet
+@item
+first use by a real nondebug instruction of the second definition of resource R
+
+@item
+@dots{}
+
+@item
+last use by a real nondebug instruction of the second definition of resource R
+@end itemize
+
+@item
+@dots{}
+
+@item
+last definition of resource R
+
+@itemize @bullet
+@item
+first use by a real nondebug instruction of the last definition of resource R
+
+@item
+@dots{}
+
+@item
+last use by a real nondebug instruction of the last definition of resource R
+@end itemize
+@end itemize
+
+(Note that clobbers never have uses; only sets do.)
+
+This linear view is easy to achieve when there is only a single definition
+of a resource, which is commonly true for pseudo registers. However,
+things are more complex if code has a structure like the following:
+
+@smallexample
+// ebb2, bb2
+R = @var{va}; // A
+if (@dots{})
+ @{
+ // ebb2, bb3
+ use1 (R); // B
+ @dots{}
+ R = @var{vc}; // C
+ @}
+else
+ @{
+ // ebb4, bb4
+ use2 (R); // D
+ @}
+@end smallexample
+
+The list of accesses would begin as follows:
+
+@itemize @bullet
+@item
+definition of R by A
+
+@itemize @bullet
+@item
+use of A's definition of R by B
+@end itemize
+
+@item
+definition of R by C
+@end itemize
+
+The next access to R is in D, but the value of R that D uses comes from
+A rather than C@.
+
+This is resolved by adding a phi node for @code{ebb4}. All inputs to this
+phi node have the same value, which in the example above is A's definition
+of R@. In other circumstances, it would not be necessary to create a phi
+node when all inputs are equal, so these phi nodes are referred to as
+``degenerate'' phi nodes.
+
+The full list of accesses to R is therefore:
+
+@itemize @bullet
+@item
+definition of R by A
+
+@itemize @bullet
+@item
+use of A's definition of R by B
+@end itemize
+
+@item
+definition of R by C
+
+@item
+definition of R by ebb4's phi instruction, with the input coming from A
+
+@itemize @bullet
+@item
+use of the ebb4's R phi definition of R by B
+@end itemize
+@end itemize
+
+Note that A's definition is also used by ebb4's phi node, but this
+use belongs to the third part of the use list described above and
+so does not form part of the linear sequence.
+
+It is possible to ``look through'' any degenerate phi to the ultimate
+definition using the function @code{look_through_degenerate_phi}.
+Note that the input to a degenerate phi is never itself provided
+by a degenerate phi.
+
+At present, the SSA form takes this principle one step further
+and guarantees that, for any given resource @var{res}, one of the
+following is true:
+
+@itemize
+@item
+The resource has a single definition @var{def}, which is not a phi node.
+Excluding uses of undefined registers, all uses of @var{res} by real
+nondebug instructions use the value provided by @var{def}.
+
+@item
+Excluding uses of undefined registers, all uses of @var{res} use
+values provided by definitions that occur earlier in the same
+extended basic block. These definitions might come from phi nodes
+or from real instructions.
+@end itemize
+
+@node Changing RTL Instructions
+@subsection Using the RTL SSA framework to change instructions
+
+@findex rtl_ssa::insn_change
+There are various routines that help to change a single RTL instruction
+or a group of RTL instructions while keeping the RTL SSA form up-to-date.
+This section first describes the process for changing a single instruction,
+then goes on to describe the differences when changing multiple instructions.
+
+@menu
+* Changing One RTL SSA Instruction::
+* Changing Multiple RTL SSA Instructions::
+@end menu
+
+@node Changing One RTL SSA Instruction
+@subsubsection Changing One RTL SSA Instruction
+
+Before making a change, passes should first use a statement like the
+following:
+
+@smallexample
+auto attempt = crtl->ssa->new_change_attempt ();
+@end smallexample
+
+Here, @code{attempt} is an RAII object that should remain in scope
+for the entire change attempt. It automatically frees temporary
+memory related to the changes when it goes out of scope.
+
+Next, the pass should create an @code{rtl_ssa::insn_change} object
+for the instruction that it wants to change. This object specifies
+several things:
+
+@itemize @bullet
+@item
+what the instruction's new list of uses should be (@code{new_uses}).
+By default this is the same as the instruction's current list of uses.
+
+@item
+what the instruction's new list of definitions should be (@code{new_defs}).
+By default this is the same as the instruction's current list of
+definitions.
+
+@item
+where the instruction should be located (@code{move_range}).
+This is a range of instructions after which the instruction could
+be placed, represented as an @code{rtl_ssa::insn_range}.
+By default the instruction must remain at its current position.
+@end itemize
+
+If a pass was attempting to change all these properties of an instruction
+@code{insn}, it might do something like this:
+
+@smallexample
+rtl_ssa::insn_change change (insn);
+change.new_defs = @dots{};
+change.new_uses = @dots{};
+change.move_range = @dots{};
+@end smallexample
+
+This @code{rtl_ssa::insn_change} only describes something that the
+pass @emph{might} do; at this stage, nothing has actually changed.
+
+As noted above, the default @code{move_range} requires the instruction
+to remain where it is. At the other extreme, it is possible to allow
+the instruction to move anywhere within its extended basic block,
+provided that all the new uses and definitions can be performed
+at the new location. The way to do this is:
+
+@smallexample
+change.move_range = insn->ebb ()->insn_range ();
+@end smallexample
+
+In either case, the next step is to make sure that move range is
+consistent with the new uses and definitions. The way to do this is:
+
+@smallexample
+if (!rtl_ssa::restrict_movement (change))
+ return false;
+@end smallexample
+
+This function tries to limit @code{move_range} to a range of instructions
+at which @code{new_uses} and @code{new_defs} can be correctly performed.
+It returns true on success or false if no suitable location exists.
+
+The pass should also tentatively change the pattern of the instruction
+to whatever form the pass wants the instruction to have. This should use
+the facilities provided by @file{recog.c}. For example:
+
+@smallexample
+rtl_insn *rtl = insn->rtl ();
+insn_change_watermark watermark;
+validate_change (rtl, &PATTERN (rtl), new_pat, 1);
+@end smallexample
+
+will tentatively replace @code{insn}'s pattern with @code{new_pat}.
+
+These changes and the construction of the @code{rtl_ssa::insn_change}
+can happen in either order or be interleaved.
+
+After the tentative changes to the instruction are complete,
+the pass should check whether the new pattern matches a target
+instruction or satisfies the requirements of an inline asm:
+
+@smallexample
+if (!rtl_ssa::recog (change))
+ return false;
+@end smallexample
+
+This step might change the instruction pattern further in order to
+make it match. It might also add new definitions or restrict the range
+of the move. For example, if the new pattern did not match in its original
+form, but could be made to match by adding a clobber of the flags
+register, @code{rtl_ssa::recog} will check whether the flags register
+is free at an appropriate point. If so, it will add a clobber of the
+flags register to @code{new_defs} and restrict @code{move_range} to
+the locations at which the flags register can be safely clobbered.
+
+Even if the proposed new instruction is valid according to
+@code{rtl_ssa::recog}, the change might not be worthwhile.
+For example, when optimizing for speed, the new instruction might
+turn out to be slower than the original one. When optimizing for
+size, the new instruction might turn out to be bigger than the
+original one.
+
+Passes should check for this case using @code{change_is_worthwhile}.
+For example:
+
+@smallexample
+if (!rtl_ssa::change_is_worthwhile (change))
+ return false;
+@end smallexample
+
+If the change passes this test too then the pass can perform the change using:
+
+@smallexample
+confirm_change_group ();
+crtl->ssa->change_insn (change);
+@end smallexample
+
+Putting all this together, the change has the following form:
+
+@smallexample
+auto attempt = crtl->ssa->new_change_attempt ();
+
+rtl_ssa::insn_change change (insn);
+change.new_defs = @dots{};
+change.new_uses = @dots{};
+change.move_range = @dots{};
+
+if (!rtl_ssa::restrict_movement (change))
+ return false;
+
+insn_change_watermark watermark;
+// Use validate_change etc. to change INSN's pattern.
+@dots{}
+if (!rtl_ssa::recog (change)
+ || !rtl_ssa::change_is_worthwhile (change))
+ return false;
+
+confirm_change_group ();
+crtl->ssa->change_insn (change);
+@end smallexample
+
+@node Changing Multiple RTL SSA Instructions
+@subsubsection Changing Multiple RTL SSA Instructions
+
+The process for changing multiple instructions is similar
+to the process for changing single instructions
+(@pxref{Changing One RTL SSA Instruction}). The pass should
+again start the change attempt with:
+
+@smallexample
+auto attempt = crtl->ssa->new_change_attempt ();
+@end smallexample
+
+and keep @code{attempt} in scope for the duration of the change
+attempt. It should then construct an @code{rtl_ssa::insn_change}
+for each change that it wants to make.
+
+After this, it should combine the changes into a sequence of
+@code{rtl_ssa::insn_change} pointers. This sequence must be in
+reverse postorder; the instructions will remain strictly in the
+order that the sequence specifies.
+
+For example, if a pass is changing exactly two instructions,
+it might do:
+
+@smallexample
+rtl_ssa::insn_change *changes[] = @{ &change1, change2 @};
+@end smallexample
+
+where @code{change1}'s instruction must come before @code{change2}'s.
+Alternatively, if the pass is changing a variable number of
+instructions, it might build up the sequence in a
+@code{vec<rtl_ssa::insn_change *>}.
+
+By default, @code{rtl_ssa::restrict_movement} assumes that all
+instructions other than the one passed to it will remain in their
+current positions and will retain their current uses and definitions.
+When changing multiple instructions, it is usually more effective
+to ignore the other instructions that are changing. The sequencing
+described above ensures that the changing instructions remain
+in the correct order with respect to each other.
+The way to do this is:
+
+@smallexample
+if (!rtl_ssa::restrict_movement (change, insn_is_changing (changes)))
+ return false;
+@end smallexample
+
+Similarly, when @code{rtl_ssa::restrict_movement} is detecting
+whether a register can be clobbered, it by default assumes that
+all other instructions will remain in their current positions and
+retain their current form. It is again more effective to ignore
+changing instructions (which might, for example, no longer need
+to clobber the flags register). The way to do this is:
+
+@smallexample
+if (!rtl_ssa::recog (change, insn_is_changing (changes)))
+ return false;
+@end smallexample
+
+When changing multiple instructions, the important question is usually
+not whether each individual change is worthwhile, but whether the changes
+as a whole are worthwhile. The way to test this is:
+
+@smallexample
+if (!rtl_ssa::changes_are_worthwhile (changes))
+ return false;
+@end smallexample
+
+The process for changing single instructions makes sure that one
+@code{rtl_ssa::insn_change} in isolation is valid. But when changing
+multiple instructions, it is also necessary to test whether the
+sequence as a whole is valid. For example, it might be impossible
+to satisfy all of the @code{move_range}s at once.
+
+Therefore, once the pass has a sequence of changes that are
+individually correct, it should use:
+
+@smallexample
+if (!crtl->ssa->verify_insn_changes (changes))
+ return false;
+@end smallexample
+
+to check whether the sequence as a whole is valid. If all checks pass,
+the final step is:
+
+@smallexample
+confirm_change_group ();
+crtl->ssa->change_insns (changes);
+@end smallexample
+
+Putting all this together, the process for a two-instruction change is:
+
+@smallexample
+auto attempt = crtl->ssa->new_change_attempt ();
+
+rtl_ssa::insn_change change (insn1);
+change1.new_defs = @dots{};
+change1.new_uses = @dots{};
+change1.move_range = @dots{};
+
+rtl_ssa::insn_change change (insn2);
+change2.new_defs = @dots{};
+change2.new_uses = @dots{};
+change2.move_range = @dots{};
+
+rtl_ssa::insn_change *changes[] = @{ &change1, change2 @};
+
+auto is_changing = insn_is_changing (changes);
+if (!rtl_ssa::restrict_movement (change1, is_changing)
+ || !rtl_ssa::restrict_movement (change2, is_changing))
+ return false;
+
+insn_change_watermark watermark;
+// Use validate_change etc. to change INSN1's and INSN2's patterns.
+@dots{}
+if (!rtl_ssa::recog (change1, is_changing)
+ || !rtl_ssa::recog (change2, is_changing)
+ || !rtl_ssa::changes_are_worthwhile (changes)
+ || !crtl->ssa->verify_insn_changes (changes))
+ return false;
+
+confirm_change_group ();
+crtl->ssa->change_insns (changes);
+@end smallexample
+
@node Sharing
@section Structure Sharing Assumptions
@cindex sharing of RTL components
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 49316a5..4159ebb 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1141,7 +1141,7 @@ but not if @code{-fpic} is also present:
/* @{ dg-skip-if "" @{ *-*-* @} @{ "-O2 -g" "-O3 -g" @} @{ "-fpic" @} @} */
@end smallexample
-@item @{ dg-require-effective-target @var{keyword} [@{ @var{selector} @}] @}
+@item @{ dg-require-effective-target @var{keyword} [@{ target @var{selector} @}] @}
Skip the test if the test target, including current multilib flags,
is not covered by the effective-target keyword.
If the directive includes the optional @samp{@{ @var{selector} @}}
@@ -1443,6 +1443,10 @@ Target has runtime support for any options added with
@item inf
Target supports floating point infinite (@code{inf}) for type
@code{double}.
+
+@item inff
+Target supports floating point infinite (@code{inf}) for type
+@code{float}.
@end table
@subsubsection Fortran-specific attributes
@@ -1795,8 +1799,7 @@ variant of the ABI for the ARM Architecture (as selected with
@code{-mfloat-abi=hard}).
@item arm_softfloat
-ARM target uses the soft-float ABI with no floating-point instructions
-used whatsoever (as selected with @code{-mfloat-abi=soft}).
+ARM target uses emulated floating point operations.
@item arm_hard_vfp_ok
ARM target supports @code{-mfpu=vfp -mfloat-abi=hard}.
@@ -2243,6 +2246,9 @@ Target supports compiling @code{avx2} instructions.
@item avx2_runtime
Target supports the execution of @code{avx2} instructions.
+@item avxvnni
+Target supports the execution of @code{avxvnni} instructions.
+
@item avx512f
Target supports compiling @code{avx512f} instructions.
@@ -2356,6 +2362,11 @@ Target provides @file{fenv.h} include file.
Target supports @file{fenv.h} with all the standard IEEE exceptions
and floating-point exceptions are raised by arithmetic operations.
+@item fenv_exceptions_dfp
+Target supports @file{fenv.h} with all the standard IEEE exceptions
+and floating-point exceptions are raised by arithmetic operations for
+decimal floating point.
+
@item fileio
Target offers such file I/O library functions as @code{fopen},
@code{fclose}, @code{tmpnam}, and @code{remove}. This is a link-time
@@ -2450,6 +2461,9 @@ Target supports wide characters.
@subsubsection Other attributes
@table @code
+@item R_flag_in_section
+Target supports the 'R' flag in .section directive in assembly inputs.
+
@item automatic_stack_alignment
Target supports automatic stack alignment.
@@ -2533,9 +2547,15 @@ Target supports the @code{noinit} variable attribute.
@item nonpic
Target does not generate PIC by default.
+@item o_flag_in_section
+Target supports the 'o' flag in .section directive in assembly inputs.
+
@item offload_gcn
Target has been configured for OpenACC/OpenMP offloading on AMD GCN.
+@item persistent
+Target supports the @code{persistent} variable attribute.
+
@item pie_enabled
Target generates PIE by default.
@@ -2903,6 +2923,14 @@ Passes if @var{regex} matches text in the test's demangled assembler output.
Passes if @var{regex} does not match text in the test's demangled assembler
output.
+@item scan-assembler-symbol-section @var{functions} @var{section} [@{ target/xfail @var{selector} @}]
+Passes if @var{functions} are all in @var{section}. The caller needs to
+allow for @code{USER_LABEL_PREFIX} and different section name conventions.
+
+@item scan-symbol-section @var{filename} @var{functions} @var{section} [@{ target/xfail @var{selector} @}]
+Passes if @var{functions} are all in @var{section}in @var{filename}.
+The same caveats as for @code{scan-assembler-symbol-section} apply.
+
@item scan-hidden @var{symbol} [@{ target/xfail @var{selector} @}]
Passes if @var{symbol} is defined as a hidden symbol in the test's
assembly output.
diff --git a/gcc/doc/standards.texi b/gcc/doc/standards.texi
index fc50160..974f9b7 100644
--- a/gcc/doc/standards.texi
+++ b/gcc/doc/standards.texi
@@ -312,14 +312,6 @@ available online, see @uref{http://gcc.gnu.org/readings.html}
As of the GCC 4.7.1 release, GCC supports the Go 1 language standard,
described at @uref{https://golang.org/doc/go1}.
-@section HSA Intermediate Language (HSAIL)
-
-GCC can compile the binary representation (BRIG) of the HSAIL text format as
-described in HSA Programmer's Reference Manual version 1.0.1. This
-capability is typically utilized to implement the HSA runtime API's HSAIL
-finalization extension for a gcc supported processor. HSA standards are
-freely available at @uref{http://www.hsafoundation.com/standards/}.
-
@section D language
GCC supports the D 2.0 programming language. The D language itself is
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 97437e8..900d584 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5457,11 +5457,24 @@ Note that the block move need only cover the constant parts of the
trampoline. If the target isolates the variable parts of the trampoline
to the end, not all @code{TRAMPOLINE_SIZE} bytes need be copied.
-If the target requires any other actions, such as flushing caches or
+If the target requires any other actions, such as flushing caches
+(possibly calling function maybe_emit_call_builtin___clear_cache) or
enabling stack execution, these actions should be performed after
initializing the trampoline proper.
@end deftypefn
+@deftypefn {Target Hook} void TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE (rtx @var{begin}, rtx @var{end})
+On targets that do not define a @code{clear_cache} insn expander,
+but that define the @code{CLEAR_CACHE_INSN} macro,
+maybe_emit_call_builtin___clear_cache relies on this target hook
+to clear an address range in the instruction cache.
+
+The default implementation calls the @code{__clear_cache} builtin,
+taking the assembler name from the builtin declaration. Overriding
+definitions may call alternate functions, with alternate calling
+conventions, or emit alternate RTX to perform the job.
+@end deftypefn
+
@deftypefn {Target Hook} rtx TARGET_TRAMPOLINE_ADJUST_ADDRESS (rtx @var{addr})
This hook should perform any machine-specific adjustment in
the address of the trampoline. Its argument contains the address of the
@@ -5490,7 +5503,7 @@ the following macro.
If defined, expands to a C expression clearing the @emph{instruction
cache} in the specified interval. The definition of this macro would
typically be a series of @code{asm} statements. Both @var{beg} and
-@var{end} are both pointer expressions.
+@var{end} are pointer expressions.
@end defmac
To use a standard subroutine, define the following macro. In addition,
@@ -6992,9 +7005,12 @@ delay slot branches filled using the basic filler is often still desirable
as the delay slot can hide a pipeline bubble.
@end deftypefn
-@deftypefn {Target Hook} HOST_WIDE_INT TARGET_ESTIMATED_POLY_VALUE (poly_int64 @var{val})
+@deftypefn {Target Hook} HOST_WIDE_INT TARGET_ESTIMATED_POLY_VALUE (poly_int64 @var{val}, poly_value_estimate_kind @var{kind})
Return an estimate of the runtime value of @var{val}, for use in
-things like cost calculations or profiling frequencies. The default
+things like cost calculations or profiling frequencies. @var{kind} is used
+to ask for the minimum, maximum, and likely estimates of the value through
+the @code{POLY_VALUE_MIN}, @code{POLY_VALUE_MAX} and
+@code{POLY_VALUE_LIKELY} values. The default
implementation returns the lowest possible value of @var{val}.
@end deftypefn
@@ -7711,13 +7727,14 @@ example, the function @code{foo} would be placed in @code{.text.foo}.
Whatever the actual target object format, this is often good enough.
@end deftypefn
-@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_RODATA_SECTION (tree @var{decl})
-Return the readonly data section associated with
-@samp{DECL_SECTION_NAME (@var{decl})}.
+@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_RODATA_SECTION (tree @var{decl}, bool @var{relocatable})
+Return the readonly data or reloc readonly data section associated with
+@samp{DECL_SECTION_NAME (@var{decl})}. @var{relocatable} selects the latter
+over the former.
The default version of this function selects @code{.gnu.linkonce.r.name} if
the function's section is @code{.gnu.linkonce.t.name}, @code{.rodata.name}
-if function is in @code{.text.name}, and the normal readonly-data section
-otherwise.
+or @code{.data.rel.ro.name} if function is in @code{.text.name}, and
+the normal readonly-data or reloc readonly data section otherwise.
@end deftypefn
@deftypevr {Target Hook} {const char *} TARGET_ASM_MERGEABLE_RODATA_PREFIX
@@ -8076,43 +8093,9 @@ need to override this if your target has special flags that might be
set via @code{__attribute__}.
@end deftypefn
-@deftypefn {Target Hook} int TARGET_ASM_RECORD_GCC_SWITCHES (print_switch_type @var{type}, const char *@var{text})
+@deftypefn {Target Hook} void TARGET_ASM_RECORD_GCC_SWITCHES (const char *@var{})
Provides the target with the ability to record the gcc command line
-switches that have been passed to the compiler, and options that are
-enabled. The @var{type} argument specifies what is being recorded.
-It can take the following values:
-
-@table @gcctabopt
-@item SWITCH_TYPE_PASSED
-@var{text} is a command line switch that has been set by the user.
-
-@item SWITCH_TYPE_ENABLED
-@var{text} is an option which has been enabled. This might be as a
-direct result of a command line switch, or because it is enabled by
-default or because it has been enabled as a side effect of a different
-command line switch. For example, the @option{-O2} switch enables
-various different individual optimization passes.
-
-@item SWITCH_TYPE_DESCRIPTIVE
-@var{text} is either NULL or some descriptive text which should be
-ignored. If @var{text} is NULL then it is being used to warn the
-target hook that either recording is starting or ending. The first
-time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the
-warning is for start up and the second time the warning is for
-wind down. This feature is to allow the target hook to make any
-necessary preparations before it starts to record switches and to
-perform any necessary tidying up after it has finished recording
-switches.
-
-@item SWITCH_TYPE_LINE_START
-This option can be ignored by this target hook.
-
-@item SWITCH_TYPE_LINE_END
-This option can be ignored by this target hook.
-@end table
-
-The hook's return value must be zero. Other return values may be
-supported in the future.
+switches provided as argument.
By default this hook is set to NULL, but an example implementation is
provided for ELF based targets. Called @var{elf_record_gcc_switches},
@@ -9560,6 +9543,10 @@ given instruction. This is only used when @code{TARGET_EXCEPT_UNWIND_INFO}
returns @code{UI_TARGET}.
@end deftypefn
+@deftypefn {Target Hook} rtx TARGET_ASM_MAKE_EH_SYMBOL_INDIRECT (rtx @var{origsymbol}, bool @var{pubvis})
+If necessary, modify personality and LSDA references to handle indirection. The original symbol is in @code{origsymbol} and if @code{pubvis} is true the symbol is visible outside the TU.
+@end deftypefn
+
@deftypevr {Target Hook} bool TARGET_ASM_UNWIND_EMIT_BEFORE_INSN
True if the @code{TARGET_ASM_UNWIND_EMIT} hook should be called before the assembly for @var{insn} has been emitted, false if the hook should be called afterward.
@end deftypevr
@@ -10817,12 +10804,25 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
relating to the target operating system.
@end deftypefn
-@deftypefn {D Target Hook} unsigned TARGET_D_CRITSEC_SIZE (void)
-Returns the size of the data structure used by the target operating system
-for critical sections and monitors. For example, on Microsoft Windows this
-would return the @code{sizeof(CRITICAL_SECTION)}, while other platforms that
-implement pthreads would return @code{sizeof(pthread_mutex_t)}.
-@end deftypefn
+@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
+Contains the name of the section in which module info references should be
+placed. This section is expected to be bracketed by two symbols to indicate
+the start and end address of the section, so that the runtime library can
+collect all modules for each loaded shared library and executable. The
+default value of @code{NULL} disables the use of sections altogether.
+@end deftypevr
+
+@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_START_NAME
+If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined
+as the name of the symbol indicating the start address of the module info
+section
+@end deftypevr
+
+@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_END_NAME
+If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined
+as the name of the symbol indicating the end address of the module info
+section
+@end deftypevr
@node Named Address Spaces
@section Adding support for named address spaces
@@ -12053,6 +12053,18 @@ argument list due to stack realignment. Return @code{NULL} if no DRAP
is needed.
@end deftypefn
+@deftypefn {Target Hook} HARD_REG_SET TARGET_ZERO_CALL_USED_REGS (HARD_REG_SET @var{selected_regs})
+This target hook emits instructions to zero the subset of @var{selected_regs}
+that could conceivably contain values that are useful to an attacker.
+Return the set of registers that were actually cleared.
+
+The default implementation uses normal move instructions to zero
+all the registers in @var{selected_regs}. Define this hook if the
+target has more efficient ways of zeroing certain registers,
+or if you believe that certain registers would never contain
+values that are useful to an attacker.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS (void)
When optimization is disabled, this hook indicates whether or not
arguments should be allocated to stack slots. Normally, GCC allocates
@@ -12085,7 +12097,8 @@ is zero, which disables this optimization.
@deftypefn {Target Hook} {unsigned HOST_WIDE_INT} TARGET_ASAN_SHADOW_OFFSET (void)
Return the offset bitwise ored into shifted address to get corresponding
Address Sanitizer shadow memory address. NULL if Address Sanitizer is not
-supported by the target.
+supported by the target. May return 0 if Address Sanitizer is not supported
+by a subtarget.
@end deftypefn
@deftypefn {Target Hook} {unsigned HOST_WIDE_INT} TARGET_MEMMODEL_CHECK (unsigned HOST_WIDE_INT @var{val})
@@ -12211,3 +12224,69 @@ This target hook can be used to generate a target-specific code
@deftypefn {Target Hook} void TARGET_RUN_TARGET_SELFTESTS (void)
If selftests are enabled, run any selftests for this target.
@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_MEMTAG_CAN_TAG_ADDRESSES ()
+True if the backend architecture naturally supports ignoring some region
+of pointers. This feature means that @option{-fsanitize=hwaddress} can
+work.
+
+At preset, this feature does not support address spaces. It also requires
+@code{Pmode} to be the same as @code{ptr_mode}.
+@end deftypefn
+
+@deftypefn {Target Hook} uint8_t TARGET_MEMTAG_TAG_SIZE ()
+Return the size of a tag (in bits) for this platform.
+
+The default returns 8.
+@end deftypefn
+
+@deftypefn {Target Hook} uint8_t TARGET_MEMTAG_GRANULE_SIZE ()
+Return the size in real memory that each byte in shadow memory refers to.
+I.e. if a variable is @var{X} bytes long in memory, then this hook should
+return the value @var{Y} such that the tag in shadow memory spans
+@var{X}/@var{Y} bytes.
+
+Most variables will need to be aligned to this amount since two variables
+that are neighbors in memory and share a tag granule would need to share
+the same tag.
+
+The default returns 16.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_MEMTAG_INSERT_RANDOM_TAG (rtx @var{untagged}, rtx @var{target})
+Return an RTX representing the value of @var{untagged} but with a
+(possibly) random tag in it.
+Put that value into @var{target} if it is convenient to do so.
+This function is used to generate a tagged base for the current stack frame.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_MEMTAG_ADD_TAG (rtx @var{base}, poly_int64 @var{addr_offset}, uint8_t @var{tag_offset})
+Return an RTX that represents the result of adding @var{addr_offset} to
+the address in pointer @var{base} and @var{tag_offset} to the tag in pointer
+@var{base}.
+The resulting RTX must either be a valid memory address or be able to get
+put into an operand with @code{force_operand}.
+
+Unlike other memtag hooks, this must return an expression and not emit any
+RTL.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_MEMTAG_SET_TAG (rtx @var{untagged_base}, rtx @var{tag}, rtx @var{target})
+Return an RTX representing @var{untagged_base} but with the tag @var{tag}.
+Try and store this in @var{target} if convenient.
+@var{untagged_base} is required to have a zero tag when this hook is called.
+The default of this hook is to set the top byte of @var{untagged_base} to
+@var{tag}.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_MEMTAG_EXTRACT_TAG (rtx @var{tagged_pointer}, rtx @var{target})
+Return an RTX representing the tag stored in @var{tagged_pointer}.
+Store the result in @var{target} if it is convenient.
+The default represents the top byte of the original pointer.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_MEMTAG_UNTAGGED_POINTER (rtx @var{tagged_pointer}, rtx @var{target})
+Return an RTX representing @var{tagged_pointer} with its tag set to zero.
+Store the result in @var{target} if convenient.
+The default clears the top byte of the original pointer.
+@end deftypefn
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 412e22c..ad56858 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3877,6 +3877,8 @@ is used for aligning trampolines.
@hook TARGET_TRAMPOLINE_INIT
+@hook TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE
+
@hook TARGET_TRAMPOLINE_ADJUST_ADDRESS
Implementing trampolines is difficult on many machines because they have
@@ -3897,7 +3899,7 @@ the following macro.
If defined, expands to a C expression clearing the @emph{instruction
cache} in the specified interval. The definition of this macro would
typically be a series of @code{asm} statements. Both @var{beg} and
-@var{end} are both pointer expressions.
+@var{end} are pointer expressions.
@end defmac
To use a standard subroutine, define the following macro. In addition,
@@ -6456,6 +6458,8 @@ the jump-table.
@hook TARGET_ASM_UNWIND_EMIT
+@hook TARGET_ASM_MAKE_EH_SYMBOL_INDIRECT
+
@hook TARGET_ASM_UNWIND_EMIT_BEFORE_INSN
@node Exception Region Output
@@ -7351,7 +7355,11 @@ floating-point support; they are not included in this mechanism.
@hook TARGET_D_OS_VERSIONS
-@hook TARGET_D_CRITSEC_SIZE
+@hook TARGET_D_MINFO_SECTION
+
+@hook TARGET_D_MINFO_START_NAME
+
+@hook TARGET_D_MINFO_END_NAME
@node Named Address Spaces
@section Adding support for named address spaces
@@ -8111,6 +8119,8 @@ and the associated definitions of those functions.
@hook TARGET_GET_DRAP_RTX
+@hook TARGET_ZERO_CALL_USED_REGS
+
@hook TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
@hook TARGET_CONST_ANCHOR
@@ -8182,3 +8192,19 @@ maintainer is familiar with.
@hook TARGET_SPECULATION_SAFE_VALUE
@hook TARGET_RUN_TARGET_SELFTESTS
+
+@hook TARGET_MEMTAG_CAN_TAG_ADDRESSES
+
+@hook TARGET_MEMTAG_TAG_SIZE
+
+@hook TARGET_MEMTAG_GRANULE_SIZE
+
+@hook TARGET_MEMTAG_INSERT_RANDOM_TAG
+
+@hook TARGET_MEMTAG_ADD_TAG
+
+@hook TARGET_MEMTAG_SET_TAG
+
+@hook TARGET_MEMTAG_EXTRACT_TAG
+
+@hook TARGET_MEMTAG_UNTAGGED_POINTER
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 28b47b7..09c2b52 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -1114,7 +1114,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
/* ... or if there is no libcall for it. */
|| code_to_optab (code) == unknown_optab))
{
- enum rtx_code first_code;
+ enum rtx_code first_code, orig_code = code;
bool and_them = split_comparison (code, mode, &first_code, &code);
/* If there are no NaNs, the first comparison should always fall
@@ -1122,6 +1122,12 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
if (!HONOR_NANS (mode))
gcc_assert (first_code == (and_them ? ORDERED : UNORDERED));
+ else if ((orig_code == EQ || orig_code == NE)
+ && rtx_equal_p (op0, op1))
+ /* Self-comparisons x == x or x != x can be optimized into
+ just x ord x or x nord x. */
+ code = orig_code == EQ ? ORDERED : UNORDERED;
+
else
{
profile_probability cprob
@@ -1132,18 +1138,37 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
cprob = cprob.apply_scale (99, 100);
else
cprob = profile_probability::even ();
- /* We want to split:
+ /* For and_them we want to split:
if (x) goto t; // prob;
+ goto f;
into
- if (a) goto t; // first_prob;
- if (b) goto t; // prob;
+ if (a) ; else goto f; // first_prob for ;
+ // 1 - first_prob for goto f;
+ if (b) goto t; // adjusted prob;
+ goto f;
such that the overall probability of jumping to t
- remains the same and first_prob is prob * cprob. */
+ remains the same. The and_them case should be
+ probability-wise equivalent to the !and_them case with
+ f and t swapped and also the conditions inverted, i.e.
+ if (!a) goto f;
+ if (!b) goto f;
+ goto t;
+ where the overall probability of jumping to f is
+ 1 - prob (thus the first prob.invert () below).
+ cprob.invert () is because the a condition is inverted,
+ so if it was originally ORDERED, !a is UNORDERED and
+ thus should be relative 1% rather than 99%.
+ The invert () on assignment to first_prob is because
+ first_prob represents the probability of fallthru,
+ rather than goto f. And the last prob.invert () is
+ because the adjusted prob represents the probability of
+ jumping to t rather than to f. */
if (and_them)
{
rtx_code_label *dest_label;
prob = prob.invert ();
- profile_probability first_prob = prob.split (cprob).invert ();
+ profile_probability first_prob
+ = prob.split (cprob.invert ()).invert ();
prob = prob.invert ();
/* If we only jump if true, just bypass the second jump. */
if (! if_false_label)
@@ -1157,11 +1182,37 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
size, dest_label, NULL, first_prob);
}
+ /* For !and_them we want to split:
+ if (x) goto t; // prob;
+ goto f;
+ into
+ if (a) goto t; // first_prob;
+ if (b) goto t; // adjusted prob;
+ goto f;
+ such that the overall probability of jumping to t
+ remains the same and first_prob is prob * cprob. */
else
{
profile_probability first_prob = prob.split (cprob);
do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
size, NULL, if_true_label, first_prob);
+ if (orig_code == NE && can_compare_p (UNEQ, mode, ccp_jump))
+ {
+ /* x != y can be split into x unord y || x ltgt y
+ or x unord y || !(x uneq y). The latter has the
+ advantage that both comparisons are non-signalling and
+ so there is a higher chance that the RTL optimizations
+ merge the two comparisons into just one. */
+ code = UNEQ;
+ prob = prob.invert ();
+ if (! if_false_label)
+ {
+ if (! dummy_label)
+ dummy_label = gen_label_rtx ();
+ if_false_label = dummy_label;
+ }
+ std::swap (if_false_label, if_true_label);
+ }
}
}
}
diff --git a/gcc/dse.c b/gcc/dse.c
index d65266b..651e6e7 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1757,8 +1757,7 @@ find_shift_sequence (poly_int64 access_size,
the machine. */
opt_scalar_int_mode new_mode_iter;
- FOR_EACH_MODE_FROM (new_mode_iter,
- smallest_int_mode_for_size (GET_MODE_BITSIZE (read_mode)))
+ FOR_EACH_MODE_IN_CLASS (new_mode_iter, MODE_INT)
{
rtx target, new_reg, new_lhs;
rtx_insn *shift_seq, *insn;
@@ -1767,6 +1766,8 @@ find_shift_sequence (poly_int64 access_size,
new_mode = new_mode_iter.require ();
if (GET_MODE_BITSIZE (new_mode) > BITS_PER_WORD)
break;
+ if (maybe_lt (GET_MODE_SIZE (new_mode), GET_MODE_SIZE (read_mode)))
+ continue;
/* Try a wider mode if truncating the store mode to NEW_MODE
requires a real instruction. */
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 8e53aef..80a65fe 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -492,6 +492,14 @@ dump_loc (dump_flags_t dump_kind, FILE *dfile, location_t loc)
static void
dump_loc (dump_flags_t dump_kind, pretty_printer *pp, location_t loc)
{
+ /* Disable warnings about missing quoting in GCC diagnostics for
+ the pp_printf calls. Their format strings aren't used to format
+ diagnostics so don't need to follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
if (dump_kind)
{
if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
@@ -507,6 +515,10 @@ dump_loc (dump_flags_t dump_kind, pretty_printer *pp, location_t loc)
for (unsigned i = 0; i < get_dump_scope_depth (); i++)
pp_character (pp, ' ');
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
}
/* Implementation of dump_context member functions. */
@@ -1118,8 +1130,12 @@ dump_context::begin_scope (const char *name,
if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags))
::dump_loc (MSG_NOTE, m_test_pp, src_loc);
+ /* Format multiple consecutive punctuation characters via %s to
+ avoid -Wformat-diag in the pp_printf call below whose output
+ isn't used for diagnostic output. */
pretty_printer pp;
- pp_printf (&pp, "=== %s ===\n", name);
+ pp_printf (&pp, "%s %s %s", "===", name, "===");
+ pp_newline (&pp);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
xstrdup (pp_formatted_text (&pp)));
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 534877b..027f327 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -182,14 +182,14 @@ static GTY(()) section *debug_frame_section;
bytes.
However, the SGI/MIPS ABI uses an initial length which is equal to
- DWARF_OFFSET_SIZE. It is defined (elsewhere) accordingly. */
+ dwarf_offset_size. It is defined (elsewhere) accordingly. */
#ifndef DWARF_INITIAL_LENGTH_SIZE
-#define DWARF_INITIAL_LENGTH_SIZE (DWARF_OFFSET_SIZE == 4 ? 4 : 12)
+#define DWARF_INITIAL_LENGTH_SIZE (dwarf_offset_size == 4 ? 4 : 12)
#endif
#ifndef DWARF_INITIAL_LENGTH_SIZE_STR
-#define DWARF_INITIAL_LENGTH_SIZE_STR (DWARF_OFFSET_SIZE == 4 ? "-4" : "-12")
+#define DWARF_INITIAL_LENGTH_SIZE_STR (dwarf_offset_size == 4 ? "-4" : "-12")
#endif
/* Round SIZE up to the nearest BOUNDARY. */
@@ -199,7 +199,7 @@ static GTY(()) section *debug_frame_section;
/* CIE identifier. */
#if HOST_BITS_PER_WIDE_INT >= 64
#define DWARF_CIE_ID \
- (unsigned HOST_WIDE_INT) (DWARF_OFFSET_SIZE == 4 ? DW_CIE_ID : DW64_CIE_ID)
+ (unsigned HOST_WIDE_INT) (dwarf_offset_size == 4 ? DW_CIE_ID : DW64_CIE_ID)
#else
#define DWARF_CIE_ID DW_CIE_ID
#endif
@@ -287,8 +287,8 @@ static GTY(()) bool do_eh_frame = false;
static unsigned int rnglist_idx;
/* Data and reference forms for relocatable data. */
-#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
-#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
+#define DW_FORM_data (dwarf_offset_size == 8 ? DW_FORM_data8 : DW_FORM_data4)
+#define DW_FORM_ref (dwarf_offset_size == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
#ifndef DEBUG_FRAME_SECTION
#define DEBUG_FRAME_SECTION ".debug_frame"
@@ -602,10 +602,10 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
if (!XCOFF_DEBUGGING_INFO || for_eh)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
" indicating 64-bit DWARF extension");
- dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
"FDE Length");
}
ASM_OUTPUT_LABEL (asm_out_file, l1);
@@ -613,7 +613,7 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
if (for_eh)
dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset");
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label,
+ dw2_asm_output_offset (dwarf_offset_size, section_start_label,
debug_frame_section, "FDE CIE offset");
begin = second ? fde->dw_fde_second_begin : fde->dw_fde_begin;
@@ -806,17 +806,17 @@ output_call_frame_info (int for_eh)
ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
if (!XCOFF_DEBUGGING_INFO || for_eh)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
"Length of Common Information Entry");
}
ASM_OUTPUT_LABEL (asm_out_file, l1);
/* Now that the CIE pointer is PC-relative for EH,
use 0 to identify the CIE. */
- dw2_asm_output_data ((for_eh ? 4 : DWARF_OFFSET_SIZE),
+ dw2_asm_output_data ((for_eh ? 4 : dwarf_offset_size),
(for_eh ? 0 : DWARF_CIE_ID),
"CIE Identifier Tag");
@@ -991,7 +991,12 @@ dwarf2out_do_cfi_startproc (bool second)
in the assembler. Further, the assembler can't handle any
of the weirder relocation types. */
if (enc & DW_EH_PE_indirect)
- ref = dw2_force_const_mem (ref, true);
+ {
+ if (targetm.asm_out.make_eh_symbol_indirect != NULL)
+ ref = targetm.asm_out.make_eh_symbol_indirect (ref, true);
+ else
+ ref = dw2_force_const_mem (ref, true);
+ }
fprintf (asm_out_file, "\t.cfi_personality %#x,", enc);
output_addr_const (asm_out_file, ref);
@@ -1009,7 +1014,12 @@ dwarf2out_do_cfi_startproc (bool second)
SYMBOL_REF_FLAGS (ref) = SYMBOL_FLAG_LOCAL;
if (enc & DW_EH_PE_indirect)
- ref = dw2_force_const_mem (ref, true);
+ {
+ if (targetm.asm_out.make_eh_symbol_indirect != NULL)
+ ref = targetm.asm_out.make_eh_symbol_indirect (ref, true);
+ else
+ ref = dw2_force_const_mem (ref, true);
+ }
fprintf (asm_out_file, "\t.cfi_lsda %#x,", enc);
output_addr_const (asm_out_file, ref);
@@ -1613,7 +1623,7 @@ loc_list_plus_const (dw_loc_list_ref list_head, poly_int64 offset)
}
#define DWARF_REF_SIZE \
- (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
+ (dwarf_version == 2 ? DWARF2_ADDR_SIZE : dwarf_offset_size)
/* The number of bits that can be encoded by largest DW_FORM_dataN.
In DWARF4 and earlier it is DW_FORM_data8 with 64 bits, in DWARF5
@@ -3219,33 +3229,33 @@ skeleton_chain_node;
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE \
- (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE \
+ (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size \
+ (dwarf_version >= 5 ? 4 : 3))
/* Fixed size portion of the DWARF comdat type unit header. */
#define DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE \
(DWARF_COMPILE_UNIT_HEADER_SIZE \
- + DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE)
+ + DWARF_TYPE_SIGNATURE_SIZE + dwarf_offset_size)
/* Fixed size portion of the DWARF skeleton compilation unit header. */
#define DWARF_COMPILE_UNIT_SKELETON_HEADER_SIZE \
(DWARF_COMPILE_UNIT_HEADER_SIZE + (dwarf_version >= 5 ? 8 : 0))
/* Fixed size portion of public names info. */
-#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
+#define DWARF_PUBNAMES_HEADER_SIZE (2 * dwarf_offset_size + 2)
/* Fixed size portion of the address range info. */
#define DWARF_ARANGES_HEADER_SIZE \
- (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
+ (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size + 4, \
DWARF2_ADDR_SIZE * 2) \
- DWARF_INITIAL_LENGTH_SIZE)
/* Size of padding portion in the address range info. It must be
aligned to twice the pointer size. */
#define DWARF_ARANGES_PAD_SIZE \
- (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
+ (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size + 4, \
DWARF2_ADDR_SIZE * 2) \
- - (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4))
+ - (DWARF_INITIAL_LENGTH_SIZE + dwarf_offset_size + 4))
/* Use assembler line directives if available. */
#ifndef DWARF2_ASM_LINE_DEBUG_INFO
@@ -4777,7 +4787,7 @@ find_string_form (struct indirect_string_node *node)
/* If the string is shorter or equal to the size of the reference, it is
always better to put it inline. */
- if (len <= DWARF_OFFSET_SIZE || node->refcount == 0)
+ if (len <= (unsigned) dwarf_offset_size || node->refcount == 0)
return node->form = DW_FORM_string;
/* If we cannot expect the linker to merge strings in .debug_str
@@ -4785,7 +4795,7 @@ find_string_form (struct indirect_string_node *node)
single module. */
if (DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
|| ((debug_str_section->common.flags & SECTION_MERGE) == 0
- && (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
+ && (len - dwarf_offset_size) * node->refcount <= len))
return node->form = DW_FORM_string;
set_indirect_string (node);
@@ -5974,6 +5984,7 @@ maybe_create_die_with_external_ref (tree decl)
const char *sym = desc->sym;
unsigned HOST_WIDE_INT off = desc->off;
+ external_die_map->remove (decl);
in_lto_p = false;
dw_die_ref die = (TREE_CODE (decl) == BLOCK
@@ -8881,7 +8892,7 @@ output_loclists_offsets (dw_die_ref die)
dw_loc_list_ref l = AT_loc_list (a);
if (l->offset_emitted)
continue;
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l->ll_symbol,
+ dw2_asm_output_delta (dwarf_offset_size, l->ll_symbol,
loc_section_label, NULL);
gcc_assert (l->hash == loc_list_idx);
loc_list_idx++;
@@ -9389,7 +9400,7 @@ size_of_die (dw_die_ref die)
size += DWARF2_ADDR_SIZE;
break;
case dw_val_class_offset:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_loc:
{
@@ -9410,10 +9421,10 @@ size_of_die (dw_die_ref die)
size += size_of_uleb128 (AT_loc_list (a)->hash);
}
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_view_list:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_range_list:
if (value_format (a) == DW_FORM_rnglistx)
@@ -9423,7 +9434,7 @@ size_of_die (dw_die_ref die)
size += size_of_uleb128 (r->idx);
}
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_const:
size += size_of_sleb128 (AT_int (a));
@@ -9497,13 +9508,13 @@ size_of_die (dw_die_ref die)
else if (dwarf_version == 2)
size += DWARF2_ADDR_SIZE;
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
}
else
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_fde_ref:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_lbl_id:
if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
@@ -9517,12 +9528,12 @@ size_of_die (dw_die_ref die)
case dw_val_class_lineptr:
case dw_val_class_macptr:
case dw_val_class_loclistsptr:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_str:
form = AT_string_form (a);
if (form == DW_FORM_strp || form == DW_FORM_line_strp)
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
else if (form == dwarf_FORM (DW_FORM_strx))
size += size_of_uleb128 (AT_index (a));
else
@@ -9535,7 +9546,7 @@ size_of_die (dw_die_ref die)
size += 8;
break;
case dw_val_class_vms_delta:
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
break;
case dw_val_class_high_pc:
size += DWARF2_ADDR_SIZE;
@@ -9713,9 +9724,9 @@ size_of_pubnames (vec<pubname_entry, va_gc> *names)
size = DWARF_PUBNAMES_HEADER_SIZE;
FOR_EACH_VEC_ELT (*names, i, p)
if (include_pubname_in_output (names, p))
- size += strlen (p->name) + DWARF_OFFSET_SIZE + 1 + space_for_flags;
+ size += strlen (p->name) + dwarf_offset_size + 1 + space_for_flags;
- size += DWARF_OFFSET_SIZE;
+ size += dwarf_offset_size;
return size;
}
@@ -9812,7 +9823,7 @@ value_format (dw_attr_node *a)
/* FALLTHRU */
case dw_val_class_vms_delta:
case dw_val_class_offset:
- switch (DWARF_OFFSET_SIZE)
+ switch (dwarf_offset_size)
{
case 4:
return DW_FORM_data4;
@@ -10514,7 +10525,7 @@ output_range_list_offset (dw_attr_node *a)
if (dwarf_version >= 5)
{
dw_ranges *r = &(*ranges_table)[a->dw_attr_val.v.val_offset];
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, r->label,
+ dw2_asm_output_offset (dwarf_offset_size, r->label,
debug_ranges_section, "%s", name);
}
else
@@ -10522,7 +10533,7 @@ output_range_list_offset (dw_attr_node *a)
char *p = strchr (ranges_section_label, '\0');
sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX,
a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, ranges_section_label,
debug_ranges_section, "%s", name);
*p = '\0';
}
@@ -10534,7 +10545,7 @@ output_range_list_offset (dw_attr_node *a)
dw2_asm_output_data_uleb128 (r->idx, "%s", name);
}
else
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ dw2_asm_output_data (dwarf_offset_size,
a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE,
"%s (offset from %s)", name, ranges_section_label);
}
@@ -10548,7 +10559,7 @@ output_loc_list_offset (dw_attr_node *a)
gcc_assert (sym);
if (!dwarf_split_debug_info)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
+ dw2_asm_output_offset (dwarf_offset_size, sym, debug_loc_section,
"%s", dwarf_attr_name (a->dw_attr));
else if (dwarf_version >= 5)
{
@@ -10558,7 +10569,7 @@ output_loc_list_offset (dw_attr_node *a)
sym);
}
else
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
+ dw2_asm_output_delta (dwarf_offset_size, sym, loc_section_label,
"%s", dwarf_attr_name (a->dw_attr));
}
@@ -10571,10 +10582,10 @@ output_view_list_offset (dw_attr_node *a)
gcc_assert (sym);
if (dwarf_split_debug_info)
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
+ dw2_asm_output_delta (dwarf_offset_size, sym, loc_section_label,
"%s", dwarf_attr_name (a->dw_attr));
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
+ dw2_asm_output_offset (dwarf_offset_size, sym, debug_loc_section,
"%s", dwarf_attr_name (a->dw_attr));
}
@@ -10652,7 +10663,7 @@ output_die (dw_die_ref die)
break;
case dw_val_class_offset:
- dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+ dw2_asm_output_data (dwarf_offset_size, a->dw_attr_val.v.val_offset,
"%s", name);
break;
@@ -10846,7 +10857,7 @@ output_die (dw_die_ref die)
if (dwarf_version == 2)
size = DWARF2_ADDR_SIZE;
else
- size = DWARF_OFFSET_SIZE;
+ size = dwarf_offset_size;
/* ??? We cannot unconditionally output die_offset if
non-zero - others might create references to those
DIEs via symbols.
@@ -10866,7 +10877,7 @@ output_die (dw_die_ref die)
else
{
gcc_assert (AT_ref (a)->die_offset);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset,
+ dw2_asm_output_data (dwarf_offset_size, AT_ref (a)->die_offset,
"%s", name);
}
break;
@@ -10877,18 +10888,18 @@ output_die (dw_die_ref die)
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL,
a->dw_attr_val.v.val_fde_index * 2);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, l1, debug_frame_section,
+ dw2_asm_output_offset (dwarf_offset_size, l1, debug_frame_section,
"%s", name);
}
break;
case dw_val_class_vms_delta:
#ifdef ASM_OUTPUT_DWARF_VMS_DELTA
- dw2_asm_output_vms_delta (DWARF_OFFSET_SIZE,
+ dw2_asm_output_vms_delta (dwarf_offset_size,
AT_vms_delta2 (a), AT_vms_delta1 (a),
"%s", name);
#else
- dw2_asm_output_delta (DWARF_OFFSET_SIZE,
+ dw2_asm_output_delta (dwarf_offset_size,
AT_vms_delta2 (a), AT_vms_delta1 (a),
"%s", name);
#endif
@@ -10899,28 +10910,28 @@ output_die (dw_die_ref die)
break;
case dw_val_class_lineptr:
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a),
debug_line_section, "%s", name);
break;
case dw_val_class_macptr:
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a),
debug_macinfo_section, "%s", name);
break;
case dw_val_class_loclistsptr:
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a),
debug_loc_section, "%s", name);
break;
case dw_val_class_str:
if (a->dw_attr_val.v.val_str->form == DW_FORM_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+ dw2_asm_output_offset (dwarf_offset_size,
a->dw_attr_val.v.val_str->label,
debug_str_section,
"%s: \"%s\"", name, AT_string (a));
else if (a->dw_attr_val.v.val_str->form == DW_FORM_line_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+ dw2_asm_output_offset (dwarf_offset_size,
a->dw_attr_val.v.val_str->label,
debug_line_str_section,
"%s: \"%s\"", name, AT_string (a));
@@ -11037,10 +11048,10 @@ output_compilation_unit_header (enum dwarf_unit_type ut)
{
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ dw2_asm_output_data (dwarf_offset_size,
next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
"Length of Compilation Unit Info");
}
@@ -11060,7 +11071,7 @@ output_compilation_unit_header (enum dwarf_unit_type ut)
dw2_asm_output_data (1, ut, "%s", name);
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
}
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, abbrev_section_label,
debug_abbrev_section,
"Offset Into Abbrev. Section");
if (dwarf_version < 5)
@@ -11250,12 +11261,12 @@ output_skeleton_debug_sections (dw_die_ref comp_unit,
/* Produce the skeleton compilation-unit header. This one differs enough from
a normal CU header that it's better not to call output_compilation_unit
header. */
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit "
"DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ dw2_asm_output_data (dwarf_offset_size,
DWARF_COMPILE_UNIT_SKELETON_HEADER_SIZE
- DWARF_INITIAL_LENGTH_SIZE
+ size_of_die (comp_unit),
@@ -11266,7 +11277,7 @@ output_skeleton_debug_sections (dw_die_ref comp_unit,
dw2_asm_output_data (1, DW_UT_skeleton, "DW_UT_skeleton");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
}
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_abbrev_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_skeleton_abbrev_section_label,
debug_skeleton_abbrev_section,
"Offset Into Abbrev. Section");
if (dwarf_version < 5)
@@ -11351,7 +11362,7 @@ output_comdat_type_unit (comdat_type_node *node,
output_compilation_unit_header (dwarf_split_debug_info
? DW_UT_split_type : DW_UT_type);
output_signature (node->signature, "Type Signature");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, node->type_die->die_offset,
+ dw2_asm_output_data (dwarf_offset_size, node->type_die->die_offset,
"Offset to Type DIE");
output_die (node->root_die);
@@ -11480,7 +11491,7 @@ output_pubname (dw_offset die_offset, pubname_entry *entry)
dw_die_ref die = entry->die;
int is_static = get_AT_flag (die, DW_AT_external) ? 0 : 1;
- dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
+ dw2_asm_output_data (dwarf_offset_size, die_offset, "DIE offset");
if (debug_generate_pub_sections == 2)
{
@@ -11554,10 +11565,10 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+ dw2_asm_output_data (dwarf_offset_size, pubnames_length,
"Pub Info Length");
}
@@ -11565,14 +11576,14 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version");
if (dwarf_split_debug_info)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_skeleton_info_section_label,
debug_skeleton_info_section,
"Offset of Compilation Unit Info");
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_info_section_label,
debug_info_section,
"Offset of Compilation Unit Info");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
+ dw2_asm_output_data (dwarf_offset_size, next_die_offset,
"Compilation Unit Length");
FOR_EACH_VEC_ELT (*names, i, pub)
@@ -11603,7 +11614,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
}
}
- dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
+ dw2_asm_output_data (dwarf_offset_size, 0, NULL);
}
/* Output public names and types tables if necessary. */
@@ -11636,21 +11647,21 @@ output_aranges (void)
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
+ dw2_asm_output_data (dwarf_offset_size, aranges_length,
"Length of Address Ranges Info");
}
/* Version number for aranges is still 2, even up to DWARF5. */
dw2_asm_output_data (2, 2, "DWARF aranges version");
if (dwarf_split_debug_info)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_skeleton_info_section_label,
debug_skeleton_info_section,
"Offset of Compilation Unit Info");
else
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_info_section_label,
debug_info_section,
"Offset of Compilation Unit Info");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
@@ -11925,11 +11936,11 @@ output_rnglists (unsigned generation)
2 + generation * 4);
ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_RANGES_SECTION_LABEL,
3 + generation * 4);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating "
"64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (dwarf_offset_size, l2, l1,
"Length of Range Lists");
ASM_OUTPUT_LABEL (asm_out_file, l1);
output_dwarf_version ();
@@ -11948,7 +11959,7 @@ output_rnglists (unsigned generation)
ASM_OUTPUT_LABEL (asm_out_file, ranges_base_label);
FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
if (r->label)
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, r->label,
+ dw2_asm_output_delta (dwarf_offset_size, r->label,
ranges_base_label, NULL);
}
@@ -12208,7 +12219,7 @@ output_line_string (enum dwarf_form form, const char *str,
node = find_AT_string_in_table (str, debug_line_str_hash);
set_indirect_string (node);
node->form = form;
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+ dw2_asm_output_offset (dwarf_offset_size, node->label,
debug_line_str_section, "%s: %#x: \"%s\"",
entry_kind, 0, node->str);
break;
@@ -12717,10 +12728,10 @@ output_line_info (bool prologue_only)
if (!XCOFF_DEBUGGING_INFO)
{
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (dwarf_offset_size, l2, l1,
"Length of Source Line Info");
}
@@ -12732,7 +12743,7 @@ output_line_info (bool prologue_only)
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
dw2_asm_output_data (1, 0, "Segment Size");
}
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
+ dw2_asm_output_delta (dwarf_offset_size, p2, p1, "Prolog Length");
ASM_OUTPUT_LABEL (asm_out_file, p1);
/* Define the architecture-dependent minimum instruction length (in bytes).
@@ -12854,7 +12865,7 @@ base_type_die (tree type, bool reverse)
if ((dwarf_version >= 4 || !dwarf_strict)
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_IS_BUILTIN (TYPE_NAME (type))
+ && DECL_IS_UNDECLARED_BUILTIN (TYPE_NAME (type))
&& DECL_NAME (TYPE_NAME (type)))
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
@@ -12962,18 +12973,19 @@ base_type_die (tree type, bool reverse)
break;
case fixed_point_scale_factor_arbitrary:
- /* Arbitrary scale factors cannot be described in standard DWARF,
- yet. */
+ /* Arbitrary scale factors cannot be described in standard DWARF. */
if (!dwarf_strict)
{
/* Describe the scale factor as a rational constant. */
const dw_die_ref scale_factor
= new_die (DW_TAG_constant, comp_unit_die (), type);
- add_AT_unsigned (scale_factor, DW_AT_GNU_numerator,
- fpt_info.scale_factor.arbitrary.numerator);
- add_AT_int (scale_factor, DW_AT_GNU_denominator,
- fpt_info.scale_factor.arbitrary.denominator);
+ add_scalar_info (scale_factor, DW_AT_GNU_numerator,
+ fpt_info.scale_factor.arbitrary.numerator,
+ dw_scalar_form_constant, NULL);
+ add_scalar_info (scale_factor, DW_AT_GNU_denominator,
+ fpt_info.scale_factor.arbitrary.denominator,
+ dw_scalar_form_constant, NULL);
add_AT_die_ref (base_type_result, DW_AT_small, scale_factor);
}
@@ -13026,6 +13038,7 @@ is_base_type (tree type)
return 1;
case VOID_TYPE:
+ case OPAQUE_TYPE:
case ARRAY_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
@@ -18232,10 +18245,11 @@ loc_list_from_tree_1 (tree loc, int want_address,
case PLACEHOLDER_EXPR:
/* This case involves extracting fields from an object to determine the
position of other fields. It is supposed to appear only as the first
- operand of COMPONENT_REF nodes and to reference precisely the type
- that the context allows. */
+ operand of COMPONENT_REF nodes and to reference precisely the type
+ that the context allows or its enclosing type. */
if (context != NULL
- && TREE_TYPE (loc) == context->context_type
+ && (TREE_TYPE (loc) == context->context_type
+ || TREE_TYPE (loc) == TYPE_CONTEXT (context->context_type))
&& want_address >= 1)
{
if (dwarf_version >= 3 || !dwarf_strict)
@@ -20762,12 +20776,23 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
else
add_AT_int (die, attr, TREE_INT_CST_LOW (value));
}
- else
+ else if (dwarf_version >= 5
+ && TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (value))) == 128)
/* Otherwise represent the bound as an unsigned value with
the precision of its type. The precision and signedness
of the type will be necessary to re-interpret it
unambiguously. */
add_AT_wide (die, attr, wi::to_wide (value));
+ else
+ {
+ rtx v = immed_wide_int_const (wi::to_wide (value),
+ TYPE_MODE (TREE_TYPE (value)));
+ dw_loc_descr_ref loc
+ = loc_descriptor (v, TYPE_MODE (TREE_TYPE (value)),
+ VAR_INIT_STATUS_INITIALIZED);
+ if (loc)
+ add_AT_loc (die, attr, loc);
+ }
return;
}
@@ -21292,7 +21317,16 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
here. */
if (origin_die)
- add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ {
+ dw_attr_node *a;
+ /* Like above, if we already created a concrete instance DIE
+ do not use that for the abstract origin but the early DIE
+ if present. */
+ if (in_lto_p
+ && (a = get_AT (origin_die, DW_AT_abstract_origin)))
+ origin_die = AT_ref (a);
+ add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ }
}
/* We do not currently support the pure_virtual attribute. */
@@ -22173,6 +22207,9 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link);
tree value = TREE_VALUE (link);
+ if (DECL_P (value))
+ equate_decl_number_to_die (value, enum_die);
+
gcc_assert (!ENUM_IS_OPAQUE (type));
add_name_attribute (enum_die,
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
@@ -22756,6 +22793,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
tree origin = decl_ultimate_origin (decl);
dw_die_ref subr_die;
dw_die_ref old_die = lookup_decl_die (decl);
+ bool old_die_had_no_children = false;
/* This function gets called multiple times for different stages of
the debug process. For example, for func() in this code:
@@ -22839,6 +22877,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
available.
*/
int declaration = (current_function_decl != decl
+ || (!DECL_INITIAL (decl) && !origin)
|| class_or_namespace_scope_p (context_die));
/* A declaration that has been previously dumped needs no
@@ -22846,6 +22885,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
if (old_die && declaration)
return;
+ if (in_lto_p && old_die && old_die->die_child == NULL)
+ old_die_had_no_children = true;
+
/* Now that the C++ front end lazily declares artificial member fns, we
might need to retrofit the declaration into its class. */
if (!declaration && !origin && !old_die
@@ -23365,6 +23407,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
else if (DECL_INITIAL (decl) == NULL_TREE)
gen_unspecified_parameters_die (decl, subr_die);
}
+ else if ((subr_die != old_die || old_die_had_no_children)
+ && prototype_p (TREE_TYPE (decl))
+ && stdarg_p (TREE_TYPE (decl)))
+ gen_unspecified_parameters_die (decl, subr_die);
}
if (subr_die != old_die)
@@ -24393,115 +24439,6 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
static char *producer_string;
-/* Return a heap allocated producer string including command line options
- if -grecord-gcc-switches. */
-
-static char *
-gen_producer_string (void)
-{
- size_t j;
- auto_vec<const char *> switches;
- const char *language_string = lang_hooks.name;
- char *producer, *tail;
- const char *p;
- size_t len = dwarf_record_gcc_switches ? 0 : 3;
- size_t plen = strlen (language_string) + 1 + strlen (version_string);
-
- for (j = 1; dwarf_record_gcc_switches && j < save_decoded_options_count; j++)
- switch (save_decoded_options[j].opt_index)
- {
- case OPT_o:
- case OPT_d:
- case OPT_dumpbase:
- case OPT_dumpbase_ext:
- case OPT_dumpdir:
- case OPT_quiet:
- case OPT_version:
- case OPT_v:
- case OPT_w:
- case OPT_L:
- case OPT_D:
- case OPT_I:
- case OPT_U:
- case OPT_SPECIAL_unknown:
- case OPT_SPECIAL_ignore:
- case OPT_SPECIAL_warn_removed:
- case OPT_SPECIAL_program_name:
- case OPT_SPECIAL_input_file:
- case OPT_grecord_gcc_switches:
- case OPT__output_pch_:
- case OPT_fdiagnostics_show_location_:
- case OPT_fdiagnostics_show_option:
- case OPT_fdiagnostics_show_caret:
- case OPT_fdiagnostics_show_labels:
- case OPT_fdiagnostics_show_line_numbers:
- case OPT_fdiagnostics_color_:
- case OPT_fdiagnostics_format_:
- case OPT_fverbose_asm:
- case OPT____:
- case OPT__sysroot_:
- case OPT_nostdinc:
- case OPT_nostdinc__:
- case OPT_fpreprocessed:
- case OPT_fltrans_output_list_:
- case OPT_fresolution_:
- case OPT_fdebug_prefix_map_:
- case OPT_fmacro_prefix_map_:
- case OPT_ffile_prefix_map_:
- case OPT_fcompare_debug:
- case OPT_fchecking:
- case OPT_fchecking_:
- /* Ignore these. */
- continue;
- case OPT_flto_:
- {
- const char *lto_canonical = "-flto";
- switches.safe_push (lto_canonical);
- len += strlen (lto_canonical) + 1;
- break;
- }
- default:
- if (cl_options[save_decoded_options[j].opt_index].flags
- & CL_NO_DWARF_RECORD)
- continue;
- gcc_checking_assert (save_decoded_options[j].canonical_option[0][0]
- == '-');
- switch (save_decoded_options[j].canonical_option[0][1])
- {
- case 'M':
- case 'i':
- case 'W':
- continue;
- case 'f':
- if (strncmp (save_decoded_options[j].canonical_option[0] + 2,
- "dump", 4) == 0)
- continue;
- break;
- default:
- break;
- }
- switches.safe_push (save_decoded_options[j].orig_option_with_args_text);
- len += strlen (save_decoded_options[j].orig_option_with_args_text) + 1;
- break;
- }
-
- producer = XNEWVEC (char, plen + 1 + len + 1);
- tail = producer;
- sprintf (tail, "%s %s", language_string, version_string);
- tail += plen;
-
- FOR_EACH_VEC_ELT (switches, j, p)
- {
- len = strlen (p);
- *tail = ' ';
- memcpy (tail + 1, p, len);
- tail += len + 1;
- }
-
- *tail = '\0';
- return producer;
-}
-
/* Given a C and/or C++ language/version string return the "highest".
C++ is assumed to be "higher" than C in this case. Used for merging
LTO translation unit languages. */
@@ -24599,7 +24536,7 @@ gen_compile_unit_die (const char *filename)
if (dwarf_version >= 5 /* || !dwarf_strict */)
if (strcmp (language_string, "GNU C11") == 0
|| strcmp (language_string, "GNU C17") == 0
- || strcmp (language_string, "GNU C2X"))
+ || strcmp (language_string, "GNU C2X") == 0)
language = DW_LANG_C11;
}
}
@@ -24612,7 +24549,8 @@ gen_compile_unit_die (const char *filename)
language = DW_LANG_C_plus_plus_11;
else if (strcmp (language_string, "GNU C++14") == 0)
language = DW_LANG_C_plus_plus_14;
- else if (strcmp (language_string, "GNU C++17") == 0)
+ else if (strcmp (language_string, "GNU C++17") == 0
+ || strcmp (language_string, "GNU C++20") == 0)
/* For now. */
language = DW_LANG_C_plus_plus_14;
}
@@ -25226,6 +25164,10 @@ gen_member_die (tree type, dw_die_ref context_die)
splice = false;
}
}
+ else if (child->die_tag == DW_TAG_enumerator)
+ /* Enumerators remain under their enumeration even if
+ their names are introduced in the enclosing scope. */
+ splice = false;
if (splice)
splice_child_die (context_die, child);
@@ -25739,6 +25681,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
return;
case VOID_TYPE:
+ case OPAQUE_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case FIXED_POINT_TYPE:
@@ -26036,7 +25979,7 @@ is_naming_typedef_decl (const_tree decl)
|| TREE_CODE (decl) != TYPE_DECL
|| DECL_NAMELESS (decl)
|| !is_tagged_type (TREE_TYPE (decl))
- || DECL_IS_BUILTIN (decl)
+ || DECL_IS_UNDECLARED_BUILTIN (decl)
|| is_redundant_typedef (decl)
/* It looks like Ada produces TYPE_DECLs that are very similar
to C++ naming typedefs but that have different
@@ -26137,6 +26080,13 @@ force_decl_die (tree decl)
decl_die = comp_unit_die ();
break;
+ case CONST_DECL:
+ /* Enumerators shouldn't need force_decl_die. */
+ gcc_assert (DECL_CONTEXT (decl) == NULL_TREE
+ || TREE_CODE (DECL_CONTEXT (decl)) != ENUMERAL_TYPE);
+ gen_decl_die (decl, NULL, NULL, context_die);
+ break;
+
case TRANSLATION_UNIT_DECL:
decl_die = comp_unit_die ();
break;
@@ -26722,7 +26672,7 @@ dwarf2out_imported_module_or_decl_1 (tree decl,
else
xloc = expand_location (input_location);
- if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
+ if (TREE_CODE (decl) == TYPE_DECL)
{
at_import_die = force_type_die (TREE_TYPE (decl));
/* For namespace N { typedef void T; } using N::T; base_type_die
@@ -26755,6 +26705,13 @@ dwarf2out_imported_module_or_decl_1 (tree decl,
gen_type_die_for_member (type, decl,
get_context_die (TYPE_CONTEXT (type)));
}
+ if (TREE_CODE (decl) == CONST_DECL)
+ {
+ /* Individual enumerators of an enum type do not get output here
+ (see gen_decl_die), so we cannot call force_decl_die. */
+ if (!is_fortran () && !is_ada () && !is_dlang ())
+ return;
+ }
if (TREE_CODE (decl) == NAMELIST_DECL)
at_import_die = gen_namelist_decl (DECL_NAME (decl),
get_context_die (DECL_CONTEXT (decl)),
@@ -26948,7 +26905,7 @@ dwarf2out_decl (tree decl)
/* Don't bother trying to generate any DIEs to represent any of the
normal built-in types for the language we are compiling. */
- if (DECL_IS_BUILTIN (decl))
+ if (DECL_IS_UNDECLARED_BUILTIN (decl))
return;
/* If we are in terse mode, don't generate any DIEs for types. */
@@ -28259,7 +28216,7 @@ output_macinfo_op (macinfo_entry *ref)
case DW_MACINFO_undef:
len = strlen (ref->info) + 1;
if (!dwarf_strict
- && len > DWARF_OFFSET_SIZE
+ && len > (size_t) dwarf_offset_size
&& !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
{
@@ -28300,7 +28257,7 @@ output_macinfo_op (macinfo_entry *ref)
dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
(unsigned long) ref->lineno);
if (node->form == DW_FORM_strp)
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+ dw2_asm_output_offset (dwarf_offset_size, node->label,
debug_str_section, "The macro: \"%s\"",
ref->info);
else
@@ -28312,7 +28269,7 @@ output_macinfo_op (macinfo_entry *ref)
ASM_GENERATE_INTERNAL_LABEL (label,
DEBUG_MACRO_SECTION_LABEL,
ref->lineno + macinfo_label_base);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
+ dw2_asm_output_offset (dwarf_offset_size, label, NULL, NULL);
break;
default:
fprintf (asm_out_file, "%s unrecognized macinfo code %lu\n",
@@ -28396,7 +28353,7 @@ optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
/* The group name format is: wmN.[<encoded filename>.]<lineno>.<md5sum> */
grp_name = XALLOCAVEC (char, 4 + encoded_filename_len + linebuf_len + 1
+ 16 * 2 + 1);
- memcpy (grp_name, DWARF_OFFSET_SIZE == 4 ? "wm4." : "wm8.", 4);
+ memcpy (grp_name, dwarf_offset_size == 4 ? "wm4." : "wm8.", 4);
tail = grp_name + 4;
if (encoded_filename_len)
{
@@ -28467,7 +28424,7 @@ save_macinfo_strings (void)
case DW_MACINFO_undef:
len = strlen (ref->info) + 1;
if (!dwarf_strict
- && len > DWARF_OFFSET_SIZE
+ && len > (unsigned) dwarf_offset_size
&& !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
set_indirect_string (find_AT_string (ref->info));
@@ -28520,11 +28477,11 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug)
{
dw2_asm_output_data (2, dwarf_version >= 5 ? 5 : 4,
"DWARF macro version number");
- if (DWARF_OFFSET_SIZE == 8)
+ if (dwarf_offset_size == 8)
dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
else
dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
+ dw2_asm_output_offset (dwarf_offset_size, debug_line_label,
debug_line_section, NULL);
}
@@ -28613,7 +28570,7 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug)
ref->info = NULL;
dw2_asm_output_data (2, dwarf_version >= 5 ? 5 : 4,
"DWARF macro version number");
- if (DWARF_OFFSET_SIZE == 8)
+ if (dwarf_offset_size == 8)
dw2_asm_output_data (1, 1, "Flags: 64-bit");
else
dw2_asm_output_data (1, 0, "Flags: 32-bit");
@@ -28950,7 +28907,7 @@ output_index_string_offset (indirect_string_node **h, unsigned int *offset)
/* Assert that this node has been assigned an index. */
gcc_assert (node->index != NO_INDEX_ASSIGNED
&& node->index != NOT_INDEXED);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, *offset,
+ dw2_asm_output_data (dwarf_offset_size, *offset,
"indexed string 0x%x: %s", node->index, node->str);
*offset += strlen (node->str) + 1;
}
@@ -29044,11 +29001,11 @@ output_indirect_strings (void)
debug_str_hash->traverse_noresize
<unsigned int *, count_index_strings> (&last_idx);
- str_offsets_length = last_idx * DWARF_OFFSET_SIZE + 4;
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ str_offsets_length = last_idx * dwarf_offset_size + 4;
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Escape value for 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, str_offsets_length,
+ dw2_asm_output_data (dwarf_offset_size, str_offsets_length,
"Length of string offsets unit");
dw2_asm_output_data (2, 5, "DWARF string offsets version");
dw2_asm_output_data (2, 0, "Header zero padding");
@@ -29138,10 +29095,10 @@ output_addr_table (void)
<unsigned int *, count_index_addrs> (&last_idx);
addrs_length = last_idx * DWARF2_ADDR_SIZE + 4;
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Escape value for 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, addrs_length,
+ dw2_asm_output_data (dwarf_offset_size, addrs_length,
"Length of Address Unit");
dw2_asm_output_data (2, 5, "DWARF addr version");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
@@ -31700,11 +31657,11 @@ dwarf2out_finish (const char *filename)
{
ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_LOC_SECTION_LABEL, 2);
ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_LOC_SECTION_LABEL, 3);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating "
"64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ dw2_asm_output_delta (dwarf_offset_size, l2, l1,
"Length of Location Lists");
ASM_OUTPUT_LABEL (asm_out_file, l1);
output_dwarf_version ();
@@ -32099,7 +32056,14 @@ dwarf2out_early_finish (const char *filename)
header compilation, so always fill it with empty string initially
and overwrite only here. */
dw_attr_node *producer = get_AT (comp_unit_die (), DW_AT_producer);
- producer_string = gen_producer_string ();
+
+ if (dwarf_record_gcc_switches)
+ producer_string = gen_producer_string (lang_hooks.name,
+ save_decoded_options,
+ save_decoded_options_count);
+ else
+ producer_string = concat (lang_hooks.name, " ", version_string, NULL);
+
producer->dw_attr_val.v.val_str->refcount--;
producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
@@ -32125,13 +32089,13 @@ dwarf2out_early_finish (const char *filename)
emit full debugging info for them. */
retry_incomplete_types ();
+ gen_scheduled_generic_parms_dies ();
+ gen_remaining_tmpl_value_param_die_attribute ();
+
/* The point here is to flush out the limbo list so that it is empty
and we don't need to stream it for LTO. */
flush_limbo_die_list ();
- gen_scheduled_generic_parms_dies ();
- gen_remaining_tmpl_value_param_die_attribute ();
-
/* Add DW_AT_linkage_name for all deferred DIEs. */
for (limbo_die_node *node = deferred_asm_name; node; node = node->next)
{
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 9571f8b..0b06cff 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -362,23 +362,18 @@ enum fixed_point_scale_factor
struct fixed_point_type_info
{
- /* A scale factor is the value one has to multiply with physical data in
- order to get the fixed point logical data. The DWARF standard enables one
- to encode it in three ways. */
+ /* The scale factor is the value one has to multiply the actual data with
+ to get the fixed point value. We support three ways to encode it. */
enum fixed_point_scale_factor scale_factor_kind;
union
{
- /* For binary scale factor, the scale factor is: 2 ** binary. */
+ /* For a binary scale factor, the scale factor is 2 ** binary. */
int binary;
- /* For decimal scale factor, the scale factor is: 10 ** binary. */
+ /* For a decimal scale factor, the scale factor is 10 ** decimal. */
int decimal;
- /* For arbitrary scale factor, the scale factor is:
+ /* For an arbitrary scale factor, the scale factor is the ratio
numerator / denominator. */
- struct
- {
- unsigned HOST_WIDE_INT numerator;
- HOST_WIDE_INT denominator;
- } arbitrary;
+ struct { tree numerator; tree denominator; } arbitrary;
} scale_factor;
};
diff --git a/gcc/edit-context.c b/gcc/edit-context.c
index 97897d6..80641c2 100644
--- a/gcc/edit-context.c
+++ b/gcc/edit-context.c
@@ -447,8 +447,13 @@ edited_file::print_diff (pretty_printer *pp, bool show_filenames)
if (show_filenames)
{
pp_string (pp, colorize_start (pp_show_color (pp), "diff-filename"));
- pp_printf (pp, "--- %s\n", m_filename);
- pp_printf (pp, "+++ %s\n", m_filename);
+ /* Avoid -Wformat-diag in non-diagnostic output. */
+ pp_string (pp, "--- ");
+ pp_string (pp, m_filename);
+ pp_newline (pp);
+ pp_string (pp, "+++ ");
+ pp_string (pp, m_filename);
+ pp_newline (pp);
pp_string (pp, colorize_stop (pp_show_color (pp)));
}
@@ -519,8 +524,9 @@ edited_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
= get_effective_line_count (old_start_of_hunk, old_end_of_hunk);
pp_string (pp, colorize_start (pp_show_color (pp), "diff-hunk"));
- pp_printf (pp, "@@ -%i,%i +%i,%i @@\n", old_start_of_hunk, old_num_lines,
- new_start_of_hunk, new_num_lines);
+ pp_printf (pp, "%s -%i,%i +%i,%i %s",
+ "@@", old_start_of_hunk, old_num_lines,
+ new_start_of_hunk, new_num_lines, "@@\n");
pp_string (pp, colorize_stop (pp_show_color (pp)));
int line_num = old_start_of_hunk;
diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
index 92ad0dd6..b20cd76 100644
--- a/gcc/emit-rtl.h
+++ b/gcc/emit-rtl.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
class temp_slot;
typedef class temp_slot *temp_slot_p;
class predefined_function_abi;
+namespace rtl_ssa { class function_info; }
/* Information mainlined about RTL representation of incoming arguments. */
struct GTY(()) incoming_args {
@@ -73,6 +74,8 @@ struct GTY(()) rtl_data {
different ABIs. */
const predefined_function_abi *GTY((skip)) abi;
+ rtl_ssa::function_info *GTY((skip)) ssa;
+
/* For function.c */
/* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
@@ -310,6 +313,9 @@ struct GTY(()) rtl_data {
sets them. */
HARD_REG_SET asm_clobbers;
+ /* All hard registers that need to be zeroed at the return of the routine. */
+ HARD_REG_SET must_be_zero_on_return;
+
/* The highest address seen during shorten_branches. */
int max_insn_address;
};
diff --git a/gcc/explow.c b/gcc/explow.c
index 0fbc6d2..65f904a 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -27,9 +27,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "memmodel.h"
#include "tm_p.h"
+#include "optabs.h"
#include "expmed.h"
#include "profile-count.h"
-#include "optabs.h"
#include "emit-rtl.h"
#include "recog.h"
#include "diagnostic-core.h"
@@ -1583,10 +1583,14 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
OFFSET is the offset of the area into the virtual stack vars area.
REQUIRED_ALIGN is the alignment (in bits) required for the region
- of memory. */
+ of memory.
+
+ BASE is the rtx of the base of this virtual stack vars area.
+ The only time this is not `virtual_stack_vars_rtx` is when tagging pointers
+ on the stack. */
rtx
-get_dynamic_stack_base (poly_int64 offset, unsigned required_align)
+get_dynamic_stack_base (poly_int64 offset, unsigned required_align, rtx base)
{
rtx target;
@@ -1594,7 +1598,7 @@ get_dynamic_stack_base (poly_int64 offset, unsigned required_align)
crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
target = gen_reg_rtx (Pmode);
- emit_move_insn (target, virtual_stack_vars_rtx);
+ emit_move_insn (target, base);
target = expand_binop (Pmode, add_optab, target,
gen_int_mode (offset, Pmode),
NULL_RTX, 1, OPTAB_LIB_WIDEN);
diff --git a/gcc/explow.h b/gcc/explow.h
index 0df8c62..581831c 100644
--- a/gcc/explow.h
+++ b/gcc/explow.h
@@ -106,7 +106,7 @@ extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned,
extern void get_dynamic_stack_size (rtx *, unsigned, unsigned, HOST_WIDE_INT *);
/* Returns the address of the dynamic stack space without allocating it. */
-extern rtx get_dynamic_stack_base (poly_int64, unsigned);
+extern rtx get_dynamic_stack_base (poly_int64, unsigned, rtx);
/* Return an rtx doing runtime alignment to REQUIRED_ALIGN on TARGET. */
extern rtx align_dynamic_address (rtx, unsigned);
diff --git a/gcc/expmed.c b/gcc/expmed.c
index d34f0fb..0d600bd 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -31,8 +31,8 @@ along with GCC; see the file COPYING3. If not see
#include "predict.h"
#include "memmodel.h"
#include "tm_p.h"
-#include "expmed.h"
#include "optabs.h"
+#include "expmed.h"
#include "regs.h"
#include "emit-rtl.h"
#include "diagnostic-core.h"
@@ -412,7 +412,8 @@ flip_storage_order (machine_mode mode, rtx x)
&& __builtin_expect (reverse_float_storage_order_supported < 0, 0))
check_reverse_float_storage_order_support ();
- if (!int_mode_for_size (GET_MODE_PRECISION (mode), 0).exists (&int_mode))
+ if (!int_mode_for_size (GET_MODE_PRECISION (mode), 0).exists (&int_mode)
+ || !targetm.scalar_mode_supported_p (int_mode))
{
sorry ("reverse storage order for %smode", GET_MODE_NAME (mode));
return x;
@@ -4193,7 +4194,8 @@ expand_sdiv_pow2 (scalar_int_mode mode, rtx op0, HOST_WIDE_INT d)
rtx
expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
- rtx op0, rtx op1, rtx target, int unsignedp)
+ rtx op0, rtx op1, rtx target, int unsignedp,
+ enum optab_methods methods)
{
machine_mode compute_mode;
rtx tquotient;
@@ -4299,17 +4301,22 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
optab2 = (op1_is_pow2 ? optab1
: (unsignedp ? udivmod_optab : sdivmod_optab));
- FOR_EACH_MODE_FROM (compute_mode, mode)
- if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
- || optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
- break;
-
- if (compute_mode == VOIDmode)
- FOR_EACH_MODE_FROM (compute_mode, mode)
- if (optab_libfunc (optab1, compute_mode)
- || optab_libfunc (optab2, compute_mode))
+ if (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN)
+ {
+ FOR_EACH_MODE_FROM (compute_mode, mode)
+ if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
+ || optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
break;
+ if (compute_mode == VOIDmode && methods == OPTAB_LIB_WIDEN)
+ FOR_EACH_MODE_FROM (compute_mode, mode)
+ if (optab_libfunc (optab1, compute_mode)
+ || optab_libfunc (optab2, compute_mode))
+ break;
+ }
+ else
+ compute_mode = mode;
+
/* If we still couldn't find a mode, use MODE, but expand_binop will
probably die. */
if (compute_mode == VOIDmode)
@@ -4412,8 +4419,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
remainder
= expand_binop (int_mode, and_optab, op0,
gen_int_mode (mask, int_mode),
- remainder, 1,
- OPTAB_LIB_WIDEN);
+ remainder, 1, methods);
if (remainder)
return gen_lowpart (mode, remainder);
}
@@ -4721,7 +4727,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
remainder = expand_binop
(int_mode, and_optab, op0,
gen_int_mode (mask, int_mode),
- remainder, 0, OPTAB_LIB_WIDEN);
+ remainder, 0, methods);
if (remainder)
return gen_lowpart (mode, remainder);
}
@@ -4846,7 +4852,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
do_cmp_and_jump (adjusted_op0, const0_rtx, LT, compute_mode, label1);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -4858,7 +4864,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
emit_label (label2);
do_cmp_and_jump (adjusted_op0, const0_rtx, GT, compute_mode, label3);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -4867,7 +4873,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
expand_dec (adjusted_op0, const1_rtx);
emit_label (label4);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
expand_dec (quotient, const1_rtx);
@@ -4892,7 +4898,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
floor_log2 (d), tquotient, 1);
t2 = expand_binop (int_mode, and_optab, op0,
gen_int_mode (d - 1, int_mode),
- NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ NULL_RTX, 1, methods);
t3 = gen_reg_rtx (int_mode);
t3 = emit_store_flag (t3, NE, t2, const0_rtx, int_mode, 1, 1);
if (t3 == 0)
@@ -4963,7 +4969,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
emit_label (label1);
expand_dec (adjusted_op0, const1_rtx);
tem = expand_binop (compute_mode, udiv_optab, adjusted_op0, op1,
- quotient, 1, OPTAB_LIB_WIDEN);
+ quotient, 1, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
expand_inc (quotient, const1_rtx);
@@ -4987,7 +4993,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
floor_log2 (d), tquotient, 0);
t2 = expand_binop (compute_mode, and_optab, op0,
gen_int_mode (d - 1, compute_mode),
- NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ NULL_RTX, 1, methods);
t3 = gen_reg_rtx (compute_mode);
t3 = emit_store_flag (t3, NE, t2, const0_rtx,
compute_mode, 1, 1);
@@ -5063,7 +5069,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (adjusted_op0, const0_rtx, GT,
compute_mode, label1);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -5076,7 +5082,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (adjusted_op0, const0_rtx, LT,
compute_mode, label3);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
emit_jump_insn (targetm.gen_jump (label5));
@@ -5085,7 +5091,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
expand_inc (adjusted_op0, const1_rtx);
emit_label (label4);
tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
if (tem != quotient)
emit_move_insn (quotient, tem);
expand_inc (quotient, const1_rtx);
@@ -5133,10 +5139,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
{
rtx tem;
quotient = expand_binop (int_mode, udiv_optab, op0, op1,
- quotient, 1, OPTAB_LIB_WIDEN);
+ quotient, 1, methods);
tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 1);
remainder = expand_binop (int_mode, sub_optab, op0, tem,
- remainder, 1, OPTAB_LIB_WIDEN);
+ remainder, 1, methods);
}
tem = plus_constant (int_mode, op1, -1);
tem = expand_shift (RSHIFT_EXPR, int_mode, tem, 1, NULL_RTX, 1);
@@ -5158,10 +5164,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
{
rtx tem;
quotient = expand_binop (int_mode, sdiv_optab, op0, op1,
- quotient, 0, OPTAB_LIB_WIDEN);
+ quotient, 0, methods);
tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 0);
remainder = expand_binop (int_mode, sub_optab, op0, tem,
- remainder, 0, OPTAB_LIB_WIDEN);
+ remainder, 0, methods);
}
abs_rem = expand_abs (int_mode, remainder, NULL_RTX, 1, 0);
abs_op1 = expand_abs (int_mode, op1, NULL_RTX, 1, 0);
@@ -5258,7 +5264,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
quotient = sign_expand_binop (compute_mode,
udiv_optab, sdiv_optab,
op0, op1, target,
- unsignedp, OPTAB_LIB_WIDEN);
+ unsignedp, methods);
}
}
}
@@ -5273,10 +5279,11 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
/* No divide instruction either. Use library for remainder. */
remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
op0, op1, target,
- unsignedp, OPTAB_LIB_WIDEN);
+ unsignedp, methods);
/* No remainder function. Try a quotient-and-remainder
function, keeping the remainder. */
- if (!remainder)
+ if (!remainder
+ && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
{
remainder = gen_reg_rtx (compute_mode);
if (!expand_twoval_binop_libfunc
@@ -5294,10 +5301,14 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
NULL_RTX, unsignedp);
remainder = expand_binop (compute_mode, sub_optab, op0,
remainder, target, unsignedp,
- OPTAB_LIB_WIDEN);
+ methods);
}
}
+ if (methods != OPTAB_LIB_WIDEN
+ && (rem_flag ? remainder : quotient) == NULL_RTX)
+ return NULL_RTX;
+
return gen_lowpart (mode, rem_flag ? remainder : quotient);
}
diff --git a/gcc/expmed.h b/gcc/expmed.h
index b719b94..6a9bab7 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -716,8 +716,10 @@ extern rtx expand_variable_shift (enum tree_code, machine_mode,
rtx, tree, rtx, int);
extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
int);
+#ifdef GCC_OPTABS_H
extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
- rtx, int);
+ rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
+#endif
#endif
extern void store_bit_field (rtx, poly_uint64, poly_uint64,
diff --git a/gcc/expr.c b/gcc/expr.c
index 9d951e8..33934d6 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -29,8 +29,8 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "tm_p.h"
#include "ssa.h"
-#include "expmed.h"
#include "optabs.h"
+#include "expmed.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
@@ -96,7 +96,6 @@ static void emit_single_push_insn (machine_mode, rtx, tree);
static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx,
profile_probability);
static rtx const_vector_from_tree (tree);
-static rtx const_scalar_mask_from_tree (scalar_int_mode, tree);
static tree tree_expr_size (const_tree);
static HOST_WIDE_INT int_expr_size (tree);
static void convert_mode_scalar (rtx, rtx, int);
@@ -5452,6 +5451,30 @@ expand_assignment (tree to, tree from, bool nontemporal)
mode1, to_rtx, to, from,
reversep))
result = NULL;
+ else if (SUBREG_P (to_rtx)
+ && SUBREG_PROMOTED_VAR_P (to_rtx))
+ {
+ /* If to_rtx is a promoted subreg, we need to zero or sign
+ extend the value afterwards. */
+ if (TREE_CODE (to) == MEM_REF
+ && !REF_REVERSE_STORAGE_ORDER (to)
+ && known_eq (bitpos, 0)
+ && known_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (to_rtx))))
+ result = store_expr (from, to_rtx, 0, nontemporal, false);
+ else
+ {
+ rtx to_rtx1
+ = lowpart_subreg (subreg_unpromoted_mode (to_rtx),
+ SUBREG_REG (to_rtx),
+ subreg_promoted_mode (to_rtx));
+ result = store_field (to_rtx1, bitsize, bitpos,
+ bitregion_start, bitregion_end,
+ mode1, from, get_alias_set (to),
+ nontemporal, reversep);
+ convert_move (SUBREG_REG (to_rtx), to_rtx1,
+ SUBREG_PROMOTED_SIGN (to_rtx));
+ }
+ }
else
result = store_field (to_rtx, bitsize, bitpos,
bitregion_start, bitregion_end,
@@ -6172,6 +6195,7 @@ count_type_elements (const_tree type, bool for_ctor_p)
return 0;
case VOID_TYPE:
+ case OPAQUE_TYPE:
case METHOD_TYPE:
case FUNCTION_TYPE:
case LANG_TYPE:
@@ -9035,6 +9059,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
target, unsignedp);
return target;
+ case WIDEN_PLUS_EXPR:
+ case WIDEN_MINUS_EXPR:
case WIDEN_MULT_EXPR:
/* If first operand is constant, swap them.
Thus the following special case checks need only
@@ -9755,6 +9781,10 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
return temp;
}
+ case VEC_WIDEN_PLUS_HI_EXPR:
+ case VEC_WIDEN_PLUS_LO_EXPR:
+ case VEC_WIDEN_MINUS_HI_EXPR:
+ case VEC_WIDEN_MINUS_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
@@ -10356,16 +10386,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
scalar_int_mode int_mode;
if (is_int_mode (mode, &int_mode))
{
- if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
- return const_scalar_mask_from_tree (int_mode, exp);
- else
- {
- tree type_for_mode
- = lang_hooks.types.type_for_mode (int_mode, 1);
- if (type_for_mode)
- tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR,
- type_for_mode, exp);
- }
+ tree type_for_mode = lang_hooks.types.type_for_mode (int_mode, 1);
+ if (type_for_mode)
+ tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR,
+ type_for_mode, exp);
}
if (!tmp)
{
@@ -11607,111 +11631,6 @@ is_aligning_offset (const_tree offset, const_tree exp)
return TREE_CODE (offset) == ADDR_EXPR && TREE_OPERAND (offset, 0) == exp;
}
-/* If EXPR is a constant initializer (either an expression or CONSTRUCTOR),
- attempt to obtain its native representation as an array of nonzero BYTES.
- Return true on success and false on failure (the latter without modifying
- BYTES). */
-
-static bool
-convert_to_bytes (tree type, tree expr, vec<unsigned char> *bytes)
-{
- if (TREE_CODE (expr) == CONSTRUCTOR)
- {
- /* Set to the size of the CONSTRUCTOR elements. */
- unsigned HOST_WIDE_INT ctor_size = bytes->length ();
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree val, idx;
- tree eltype = TREE_TYPE (type);
- unsigned HOST_WIDE_INT elsize =
- tree_to_uhwi (TYPE_SIZE_UNIT (eltype));
-
- /* Jump through hoops to determine the lower bound for languages
- like Ada that can set it to an (almost) arbitrary value. */
- tree dom = TYPE_DOMAIN (type);
- if (!dom)
- return false;
- tree min = TYPE_MIN_VALUE (dom);
- if (!min || !tree_fits_uhwi_p (min))
- return false;
- unsigned HOST_WIDE_INT i, last_idx = tree_to_uhwi (min) - 1;
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (expr), i, idx, val)
- {
- /* Append zeros for elements with no initializers. */
- if (!tree_fits_uhwi_p (idx))
- return false;
- unsigned HOST_WIDE_INT cur_idx = tree_to_uhwi (idx);
- if (unsigned HOST_WIDE_INT size = cur_idx - (last_idx + 1))
- {
- size = size * elsize + bytes->length ();
- bytes->safe_grow_cleared (size, true);
- }
-
- if (!convert_to_bytes (eltype, val, bytes))
- return false;
-
- last_idx = cur_idx;
- }
- }
- else if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree val, fld;
- unsigned HOST_WIDE_INT i;
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (expr), i, fld, val)
- {
- /* Append zeros for members with no initializers and
- any padding. */
- unsigned HOST_WIDE_INT cur_off = int_byte_position (fld);
- if (bytes->length () < cur_off)
- bytes->safe_grow_cleared (cur_off, true);
-
- if (!convert_to_bytes (TREE_TYPE (val), val, bytes))
- return false;
- }
- }
- else
- return false;
-
- /* Compute the size of the COSNTRUCTOR elements. */
- ctor_size = bytes->length () - ctor_size;
-
- /* Append zeros to the byte vector to the full size of the type.
- The type size can be less than the size of the CONSTRUCTOR
- if the latter contains initializers for a flexible array
- member. */
- tree size = TYPE_SIZE_UNIT (type);
- unsigned HOST_WIDE_INT type_size = tree_to_uhwi (size);
- if (ctor_size < type_size)
- if (unsigned HOST_WIDE_INT size_grow = type_size - ctor_size)
- bytes->safe_grow_cleared (bytes->length () + size_grow, true);
-
- return true;
- }
-
- /* Except for RECORD_TYPE which may have an initialized flexible array
- member, the size of a type is the same as the size of the initializer
- (including any implicitly zeroed out members and padding). Allocate
- just enough for that many bytes. */
- tree expr_size = TYPE_SIZE_UNIT (TREE_TYPE (expr));
- if (!expr_size || !tree_fits_uhwi_p (expr_size))
- return false;
- const unsigned HOST_WIDE_INT expr_bytes = tree_to_uhwi (expr_size);
- const unsigned bytes_sofar = bytes->length ();
- /* native_encode_expr can convert at most INT_MAX bytes. vec is limited
- to at most UINT_MAX. */
- if (bytes_sofar + expr_bytes > INT_MAX)
- return false;
-
- /* Unlike for RECORD_TYPE, there is no need to clear the memory since
- it's completely overwritten by native_encode_expr. */
- bytes->safe_grow (bytes_sofar + expr_bytes, true);
- unsigned char *pnext = bytes->begin () + bytes_sofar;
- int nbytes = native_encode_expr (expr, pnext, expr_bytes, 0);
- /* NBYTES is zero on failure. Otherwise it should equal EXPR_BYTES. */
- return (unsigned HOST_WIDE_INT) nbytes == expr_bytes;
-}
-
/* Return a STRING_CST corresponding to ARG's constant initializer either
if it's a string constant, or, when VALREP is set, any other constant,
or null otherwise.
@@ -11724,7 +11643,7 @@ static tree
constant_byte_string (tree arg, tree *ptr_offset, tree *mem_size, tree *decl,
bool valrep = false)
{
- tree dummy = NULL_TREE;;
+ tree dummy = NULL_TREE;
if (!mem_size)
mem_size = &dummy;
@@ -11879,18 +11798,42 @@ constant_byte_string (tree arg, tree *ptr_offset, tree *mem_size, tree *decl,
if (!base_off.is_constant (&cstoff))
return NULL_TREE;
+ /* Check that the host and target are sane. */
+ if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
+ return NULL_TREE;
+
+ HOST_WIDE_INT typesz = int_size_in_bytes (TREE_TYPE (init));
+ if (typesz <= 0 || (int) typesz != typesz)
+ return NULL_TREE;
+
+ HOST_WIDE_INT size = typesz;
+ if (VAR_P (array)
+ && DECL_SIZE_UNIT (array)
+ && tree_fits_shwi_p (DECL_SIZE_UNIT (array)))
+ {
+ size = tree_to_shwi (DECL_SIZE_UNIT (array));
+ gcc_checking_assert (size >= typesz);
+ }
+
/* If value representation was requested convert the initializer
for the whole array or object into a string of bytes forming
its value representation and return it. */
- auto_vec<unsigned char> bytes;
- if (!convert_to_bytes (TREE_TYPE (init), init, &bytes))
- return NULL_TREE;
+ unsigned char *bytes = XNEWVEC (unsigned char, size);
+ int r = native_encode_initializer (init, bytes, size);
+ if (r < typesz)
+ {
+ XDELETEVEC (bytes);
+ return NULL_TREE;
+ }
+
+ if (r < size)
+ memset (bytes + r, '\0', size - r);
- unsigned n = bytes.length ();
- const char *p = reinterpret_cast<const char *>(bytes.address ());
- init = build_string_literal (n, p, char_type_node);
+ const char *p = reinterpret_cast<const char *>(bytes);
+ init = build_string_literal (size, p, char_type_node);
init = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 0);
+ XDELETE (bytes);
*mem_size = size_int (TREE_STRING_LENGTH (init));
*ptr_offset = wide_int_to_tree (ssizetype, base_off);
@@ -11941,6 +11884,10 @@ constant_byte_string (tree arg, tree *ptr_offset, tree *mem_size, tree *decl,
&& (TREE_CODE (TREE_TYPE (array)) == INTEGER_TYPE
|| TYPE_MAIN_VARIANT (inittype) == char_type_node))
{
+ /* Check that the host and target are sane. */
+ if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
+ return NULL_TREE;
+
/* For a reference to (address of) a single constant character,
store the native representation of the character in CHARBUF.
If the reference is to an element of an array or a member
@@ -11983,6 +11930,9 @@ constant_byte_string (tree arg, tree *ptr_offset, tree *mem_size, tree *decl,
initsize = integer_zero_node;
unsigned HOST_WIDE_INT size = tree_to_uhwi (initsize);
+ if (size > (unsigned HOST_WIDE_INT) INT_MAX)
+ return NULL_TREE;
+
init = build_string_literal (size, NULL, chartype, size);
init = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 0);
@@ -12739,30 +12689,6 @@ const_vector_mask_from_tree (tree exp)
return builder.build ();
}
-/* EXP is a VECTOR_CST in which each element is either all-zeros or all-ones.
- Return a constant scalar rtx of mode MODE in which bit X is set if element
- X of EXP is nonzero. */
-static rtx
-const_scalar_mask_from_tree (scalar_int_mode mode, tree exp)
-{
- wide_int res = wi::zero (GET_MODE_PRECISION (mode));
- tree elt;
-
- /* The result has a fixed number of bits so the input must too. */
- unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant ();
- for (unsigned int i = 0; i < nunits; ++i)
- {
- elt = VECTOR_CST_ELT (exp, i);
- gcc_assert (TREE_CODE (elt) == INTEGER_CST);
- if (integer_all_onesp (elt))
- res = wi::set_bit (res, i);
- else
- gcc_assert (integer_zerop (elt));
- }
-
- return immed_wide_int_const (res, mode);
-}
-
/* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
static rtx
const_vector_from_tree (tree exp)
diff --git a/gcc/final.c b/gcc/final.c
index 80423d1..fc9a05e 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-iter.h"
#include "print-rtl.h"
#include "function-abi.h"
+#include "common/common-target.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data declarations. */
@@ -2154,6 +2155,21 @@ asm_show_source (const char *filename, int linenum)
fputc ('\n', asm_out_file);
}
+/* Judge if an absolute jump table is relocatable. */
+
+bool
+jumptable_relocatable (void)
+{
+ bool relocatable = false;
+
+ if (!CASE_VECTOR_PC_RELATIVE
+ && !targetm.asm_out.generate_pic_addr_diff_vec ()
+ && targetm_common.have_named_sections)
+ relocatable = targetm.asm_out.reloc_rw_mask ();
+
+ return relocatable;
+}
+
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
@@ -2493,7 +2509,8 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
int log_align;
switch_to_section (targetm.asm_out.function_rodata_section
- (current_function_decl));
+ (current_function_decl,
+ jumptable_relocatable ()));
#ifdef ADDR_VEC_ALIGN
log_align = ADDR_VEC_ALIGN (table);
@@ -2572,7 +2589,8 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
if (! JUMP_TABLES_IN_TEXT_SECTION)
switch_to_section (targetm.asm_out.function_rodata_section
- (current_function_decl));
+ (current_function_decl,
+ jumptable_relocatable ()));
else
switch_to_section (current_function_section ());
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index e8ce051..da83793 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_FLAG_TYPES_H
#define GCC_FLAG_TYPES_H
+#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
+
enum debug_info_type
{
NO_DEBUG, /* Write no debug info. */
@@ -230,12 +232,14 @@ enum scalar_storage_order_kind {
SSO_LITTLE_ENDIAN
};
-/* Vectorizer cost-model. */
+/* Vectorizer cost-model. Except for DEFAULT, the values are ordered from
+ the most conservative to the least conservative. */
enum vect_cost_model {
+ VECT_COST_MODEL_VERY_CHEAP = -3,
+ VECT_COST_MODEL_CHEAP = -2,
+ VECT_COST_MODEL_DYNAMIC = -1,
VECT_COST_MODEL_UNLIMITED = 0,
- VECT_COST_MODEL_CHEAP = 1,
- VECT_COST_MODEL_DYNAMIC = 2,
- VECT_COST_MODEL_DEFAULT = 3
+ VECT_COST_MODEL_DEFAULT = 1
};
/* Different instrumentation modes. */
@@ -272,6 +276,9 @@ enum sanitize_code {
SANITIZE_BUILTIN = 1UL << 25,
SANITIZE_POINTER_COMPARE = 1UL << 26,
SANITIZE_POINTER_SUBTRACT = 1UL << 27,
+ SANITIZE_HWADDRESS = 1UL << 28,
+ SANITIZE_USER_HWADDRESS = 1UL << 29,
+ SANITIZE_KERNEL_HWADDRESS = 1UL << 30,
SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
| SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
@@ -285,6 +292,24 @@ enum sanitize_code {
| SANITIZE_BOUNDS_STRICT
};
+/* Different settings for zeroing subset of registers. */
+namespace zero_regs_flags {
+ const unsigned int UNSET = 0;
+ const unsigned int SKIP = 1UL << 0;
+ const unsigned int ONLY_USED = 1UL << 1;
+ const unsigned int ONLY_GPR = 1UL << 2;
+ const unsigned int ONLY_ARG = 1UL << 3;
+ const unsigned int ENABLED = 1UL << 4;
+ const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
+ const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
+ const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
+ const unsigned int USED = ENABLED | ONLY_USED;
+ const unsigned int ALL_GPR_ARG = ENABLED | ONLY_GPR | ONLY_ARG;
+ const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
+ const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
+ const unsigned int ALL = ENABLED;
+}
+
/* Settings of flag_incremental_link. */
enum incremental_link {
INCREMENTAL_LINK_NONE,
@@ -396,4 +421,13 @@ enum evrp_mode
EVRP_MODE_RVRP_DEBUG = EVRP_MODE_RVRP_ONLY | EVRP_MODE_DEBUG
};
+/* Modes of OpenACC 'kernels' constructs handling. */
+enum openacc_kernels
+{
+ OPENACC_KERNELS_DECOMPOSE,
+ OPENACC_KERNELS_PARLOOPS
+};
+
+#endif
+
#endif /* ! GCC_FLAG_TYPES_H */
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 11ed47d..3548fab 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -1300,6 +1300,9 @@ fold_const_call (combined_fn fn, tree type, tree arg)
CASE_CFN_NANS:
CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
+ case CFN_BUILT_IN_NANSD32:
+ case CFN_BUILT_IN_NANSD64:
+ case CFN_BUILT_IN_NANSD128:
return fold_const_builtin_nan (type, arg, false);
case CFN_REDUC_PLUS:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ebd32bb..0d7113a 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -82,6 +82,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "tree-vector-builder.h"
#include "vec-perm-indices.h"
+#include "asan.h"
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
@@ -992,26 +993,19 @@ wide_int_binop (wide_int &res,
res = wi::bit_and (arg1, arg2);
break;
- case RSHIFT_EXPR:
case LSHIFT_EXPR:
if (wi::neg_p (arg2))
- {
- tmp = -arg2;
- if (code == RSHIFT_EXPR)
- code = LSHIFT_EXPR;
- else
- code = RSHIFT_EXPR;
- }
- else
- tmp = arg2;
+ return false;
+ res = wi::lshift (arg1, arg2);
+ break;
- if (code == RSHIFT_EXPR)
- /* It's unclear from the C standard whether shifts can overflow.
- The following code ignores overflow; perhaps a C standard
- interpretation ruling is needed. */
- res = wi::rshift (arg1, tmp, sign);
- else
- res = wi::lshift (arg1, tmp);
+ case RSHIFT_EXPR:
+ if (wi::neg_p (arg2))
+ return false;
+ /* It's unclear from the C standard whether shifts can overflow.
+ The following code ignores overflow; perhaps a C standard
+ interpretation ruling is needed. */
+ res = wi::rshift (arg1, arg2, sign);
break;
case RROTATE_EXPR:
@@ -3312,10 +3306,36 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
case COMPONENT_REF:
/* Handle operand 2 the same as for ARRAY_REF. Operand 0
may be NULL when we're called to compare MEM_EXPRs. */
- if (!OP_SAME_WITH_NULL (0)
- || !OP_SAME (1))
+ if (!OP_SAME_WITH_NULL (0))
return false;
- flags &= ~OEP_ADDRESS_OF;
+ {
+ bool compare_address = flags & OEP_ADDRESS_OF;
+
+ /* Most of time we only need to compare FIELD_DECLs for equality.
+ However when determining address look into actual offsets.
+ These may match for unions and unshared record types. */
+ flags &= ~OEP_ADDRESS_OF;
+ if (!OP_SAME (1))
+ {
+ if (compare_address)
+ {
+ if (TREE_OPERAND (arg0, 2)
+ || TREE_OPERAND (arg1, 2))
+ return OP_SAME_WITH_NULL (2);
+ tree field0 = TREE_OPERAND (arg0, 1);
+ tree field1 = TREE_OPERAND (arg1, 1);
+
+ if (!operand_equal_p (DECL_FIELD_OFFSET (field0),
+ DECL_FIELD_OFFSET (field1), flags)
+ || !operand_equal_p (DECL_FIELD_BIT_OFFSET (field0),
+ DECL_FIELD_BIT_OFFSET (field1),
+ flags))
+ return false;
+ }
+ else
+ return false;
+ }
+ }
return OP_SAME_WITH_NULL (2);
case BIT_FIELD_REF:
@@ -3324,24 +3344,6 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
flags &= ~OEP_ADDRESS_OF;
return OP_SAME (1) && OP_SAME (2);
- /* Virtual table call. */
- case OBJ_TYPE_REF:
- {
- if (!operand_equal_p (OBJ_TYPE_REF_EXPR (arg0),
- OBJ_TYPE_REF_EXPR (arg1), flags))
- return false;
- if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg0))
- != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg1)))
- return false;
- if (!operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0),
- OBJ_TYPE_REF_OBJECT (arg1), flags))
- return false;
- if (!types_same_for_odr (obj_type_ref_class (arg0),
- obj_type_ref_class (arg1)))
- return false;
- return true;
- }
-
default:
return false;
}
@@ -3420,6 +3422,27 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
return OP_SAME (0);
return false;
+ case OBJ_TYPE_REF:
+ /* Virtual table reference. */
+ if (!operand_equal_p (OBJ_TYPE_REF_EXPR (arg0),
+ OBJ_TYPE_REF_EXPR (arg1), flags))
+ return false;
+ flags &= ~OEP_ADDRESS_OF;
+ if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg0))
+ != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg1)))
+ return false;
+ if (!operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0),
+ OBJ_TYPE_REF_OBJECT (arg1), flags))
+ return false;
+ if (virtual_method_call_p (arg0))
+ {
+ if (!virtual_method_call_p (arg1))
+ return false;
+ return types_same_for_odr (obj_type_ref_class (arg0),
+ obj_type_ref_class (arg1));
+ }
+ return false;
+
default:
return false;
}
@@ -3787,9 +3810,26 @@ operand_compare::hash_operand (const_tree t, inchash::hash &hstate,
sflags = flags;
break;
+ case COMPONENT_REF:
+ if (sflags & OEP_ADDRESS_OF)
+ {
+ hash_operand (TREE_OPERAND (t, 0), hstate, flags);
+ if (TREE_OPERAND (t, 2))
+ hash_operand (TREE_OPERAND (t, 2), hstate,
+ flags & ~OEP_ADDRESS_OF);
+ else
+ {
+ tree field = TREE_OPERAND (t, 1);
+ hash_operand (DECL_FIELD_OFFSET (field),
+ hstate, flags & ~OEP_ADDRESS_OF);
+ hash_operand (DECL_FIELD_BIT_OFFSET (field),
+ hstate, flags & ~OEP_ADDRESS_OF);
+ }
+ return;
+ }
+ break;
case ARRAY_REF:
case ARRAY_RANGE_REF:
- case COMPONENT_REF:
case BIT_FIELD_REF:
sflags &= ~OEP_ADDRESS_OF;
break;
@@ -3822,11 +3862,25 @@ operand_compare::hash_operand (const_tree t, inchash::hash &hstate,
hash_operand (TARGET_EXPR_SLOT (t), hstate, flags);
return;
- /* Virtual table call. */
case OBJ_TYPE_REF:
+ /* Virtual table reference. */
inchash::add_expr (OBJ_TYPE_REF_EXPR (t), hstate, flags);
+ flags &= ~OEP_ADDRESS_OF;
inchash::add_expr (OBJ_TYPE_REF_TOKEN (t), hstate, flags);
inchash::add_expr (OBJ_TYPE_REF_OBJECT (t), hstate, flags);
+ if (!virtual_method_call_p (t))
+ return;
+ if (tree c = obj_type_ref_class (t))
+ {
+ c = TYPE_NAME (TYPE_MAIN_VARIANT (c));
+ /* We compute mangled names only when free_lang_data is run.
+ In that case we can hash precisely. */
+ if (TREE_CODE (c) == TYPE_DECL
+ && DECL_ASSEMBLER_NAME_SET_P (c))
+ hstate.add_object
+ (IDENTIFIER_HASH_VALUE
+ (DECL_ASSEMBLER_NAME (c)));
+ }
return;
default:
break;
@@ -7915,25 +7969,78 @@ native_encode_expr (const_tree expr, unsigned char *ptr, int len, int off)
}
}
+/* Try to find a type whose byte size is smaller or equal to LEN bytes larger
+ or equal to FIELDSIZE bytes, with underlying mode precision/size multiple
+ of BITS_PER_UNIT. As native_{interpret,encode}_int works in term of
+ machine modes, we can't just use build_nonstandard_integer_type. */
+
+tree
+find_bitfield_repr_type (int fieldsize, int len)
+{
+ machine_mode mode;
+ for (int pass = 0; pass < 2; pass++)
+ {
+ enum mode_class mclass = pass ? MODE_PARTIAL_INT : MODE_INT;
+ FOR_EACH_MODE_IN_CLASS (mode, mclass)
+ if (known_ge (GET_MODE_SIZE (mode), fieldsize)
+ && known_eq (GET_MODE_PRECISION (mode),
+ GET_MODE_BITSIZE (mode))
+ && known_le (GET_MODE_SIZE (mode), len))
+ {
+ tree ret = lang_hooks.types.type_for_mode (mode, 1);
+ if (ret && TYPE_MODE (ret) == mode)
+ return ret;
+ }
+ }
+
+ for (int i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && int_n_data[i].bitsize >= (unsigned) (BITS_PER_UNIT * fieldsize)
+ && int_n_trees[i].unsigned_type)
+ {
+ tree ret = int_n_trees[i].unsigned_type;
+ mode = TYPE_MODE (ret);
+ if (known_ge (GET_MODE_SIZE (mode), fieldsize)
+ && known_eq (GET_MODE_PRECISION (mode),
+ GET_MODE_BITSIZE (mode))
+ && known_le (GET_MODE_SIZE (mode), len))
+ return ret;
+ }
+
+ return NULL_TREE;
+}
+
/* Similar to native_encode_expr, but also handle CONSTRUCTORs, VCEs,
- NON_LVALUE_EXPRs and nops. */
+ NON_LVALUE_EXPRs and nops. If MASK is non-NULL (then PTR has
+ to be non-NULL and OFF zero), then in addition to filling the
+ bytes pointed by PTR with the value also clear any bits pointed
+ by MASK that are known to be initialized, keep them as is for
+ e.g. uninitialized padding bits or uninitialized fields. */
int
native_encode_initializer (tree init, unsigned char *ptr, int len,
- int off)
+ int off, unsigned char *mask)
{
+ int r;
+
/* We don't support starting at negative offset and -1 is special. */
if (off < -1 || init == NULL_TREE)
return 0;
+ gcc_assert (mask == NULL || (off == 0 && ptr));
+
STRIP_NOPS (init);
switch (TREE_CODE (init))
{
case VIEW_CONVERT_EXPR:
case NON_LVALUE_EXPR:
- return native_encode_initializer (TREE_OPERAND (init, 0), ptr, len, off);
+ return native_encode_initializer (TREE_OPERAND (init, 0), ptr, len, off,
+ mask);
default:
- return native_encode_expr (init, ptr, len, off);
+ r = native_encode_expr (init, ptr, len, off);
+ if (mask)
+ memset (mask, 0, r);
+ return r;
case CONSTRUCTOR:
tree type = TREE_TYPE (init);
HOST_WIDE_INT total_bytes = int_size_in_bytes (type);
@@ -7946,7 +8053,7 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
{
HOST_WIDE_INT min_index;
unsigned HOST_WIDE_INT cnt;
- HOST_WIDE_INT curpos = 0, fieldsize;
+ HOST_WIDE_INT curpos = 0, fieldsize, valueinit = -1;
constructor_elt *ce;
if (TYPE_DOMAIN (type) == NULL_TREE
@@ -7961,12 +8068,22 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
if (ptr != NULL)
memset (ptr, '\0', MIN (total_bytes - off, len));
- FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
+ for (cnt = 0; ; cnt++)
{
- tree val = ce->value;
- tree index = ce->index;
+ tree val = NULL_TREE, index = NULL_TREE;
HOST_WIDE_INT pos = curpos, count = 0;
bool full = false;
+ if (vec_safe_iterate (CONSTRUCTOR_ELTS (init), cnt, &ce))
+ {
+ val = ce->value;
+ index = ce->index;
+ }
+ else if (mask == NULL
+ || CONSTRUCTOR_NO_CLEARING (init)
+ || curpos >= total_bytes)
+ break;
+ else
+ pos = total_bytes;
if (index && TREE_CODE (index) == RANGE_EXPR)
{
if (!tree_fits_shwi_p (TREE_OPERAND (index, 0))
@@ -7984,6 +8101,29 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
pos = (tree_to_shwi (index) - min_index) * fieldsize;
}
+ if (mask && !CONSTRUCTOR_NO_CLEARING (init) && curpos != pos)
+ {
+ if (valueinit == -1)
+ {
+ tree zero = build_zero_cst (TREE_TYPE (type));
+ r = native_encode_initializer (zero, ptr + curpos,
+ fieldsize, 0,
+ mask + curpos);
+ if (TREE_CODE (zero) == CONSTRUCTOR)
+ ggc_free (zero);
+ if (!r)
+ return 0;
+ valueinit = curpos;
+ curpos += fieldsize;
+ }
+ while (curpos != pos)
+ {
+ memcpy (ptr + curpos, ptr + valueinit, fieldsize);
+ memcpy (mask + curpos, mask + valueinit, fieldsize);
+ curpos += fieldsize;
+ }
+ }
+
curpos = pos;
if (val)
do
@@ -7998,6 +8138,8 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
if (ptr)
memcpy (ptr + (curpos - o), ptr + (pos - o),
fieldsize);
+ if (mask)
+ memcpy (mask + curpos, mask + pos, fieldsize);
}
else if (!native_encode_initializer (val,
ptr
@@ -8005,7 +8147,10 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
: NULL,
fieldsize,
off == -1 ? -1
- : 0))
+ : 0,
+ mask
+ ? mask + curpos
+ : NULL))
return 0;
else
{
@@ -8020,6 +8165,7 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
unsigned char *p = NULL;
int no = 0;
int l;
+ gcc_assert (mask == NULL);
if (curpos >= off)
{
if (ptr)
@@ -8033,7 +8179,7 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
no = off - curpos;
l = len;
}
- if (!native_encode_initializer (val, p, l, no))
+ if (!native_encode_initializer (val, p, l, no, NULL))
return 0;
}
curpos += fieldsize;
@@ -8047,31 +8193,107 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
{
unsigned HOST_WIDE_INT cnt;
constructor_elt *ce;
+ tree fld_base = TYPE_FIELDS (type);
+ tree to_free = NULL_TREE;
+ gcc_assert (TREE_CODE (type) == RECORD_TYPE || mask == NULL);
if (ptr != NULL)
- memset (ptr, '\0', MIN (total_bytes - off, len));
- FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
+ memset (ptr, '\0', MIN (total_bytes - o, len));
+ for (cnt = 0; ; cnt++)
{
- tree field = ce->index;
- tree val = ce->value;
- HOST_WIDE_INT pos, fieldsize;
+ tree val = NULL_TREE, field = NULL_TREE;
+ HOST_WIDE_INT pos = 0, fieldsize;
unsigned HOST_WIDE_INT bpos = 0, epos = 0;
- if (field == NULL_TREE)
- return 0;
+ if (to_free)
+ {
+ ggc_free (to_free);
+ to_free = NULL_TREE;
+ }
- pos = int_byte_position (field);
- if (off != -1 && (HOST_WIDE_INT) off + len <= pos)
- continue;
+ if (vec_safe_iterate (CONSTRUCTOR_ELTS (init), cnt, &ce))
+ {
+ val = ce->value;
+ field = ce->index;
+ if (field == NULL_TREE)
+ return 0;
+
+ pos = int_byte_position (field);
+ if (off != -1 && (HOST_WIDE_INT) off + len <= pos)
+ continue;
+ }
+ else if (mask == NULL
+ || CONSTRUCTOR_NO_CLEARING (init))
+ break;
+ else
+ pos = total_bytes;
+
+ if (mask && !CONSTRUCTOR_NO_CLEARING (init))
+ {
+ tree fld;
+ for (fld = fld_base; fld; fld = DECL_CHAIN (fld))
+ {
+ if (TREE_CODE (fld) != FIELD_DECL)
+ continue;
+ if (fld == field)
+ break;
+ if (DECL_PADDING_P (fld))
+ continue;
+ if (DECL_SIZE_UNIT (fld) == NULL_TREE
+ || !tree_fits_shwi_p (DECL_SIZE_UNIT (fld)))
+ return 0;
+ if (integer_zerop (DECL_SIZE_UNIT (fld)))
+ continue;
+ break;
+ }
+ if (fld == NULL_TREE)
+ {
+ if (ce == NULL)
+ break;
+ return 0;
+ }
+ fld_base = DECL_CHAIN (fld);
+ if (fld != field)
+ {
+ cnt--;
+ field = fld;
+ pos = int_byte_position (field);
+ val = build_zero_cst (TREE_TYPE (fld));
+ if (TREE_CODE (val) == CONSTRUCTOR)
+ to_free = val;
+ }
+ }
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
&& TYPE_DOMAIN (TREE_TYPE (field))
&& ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
- return 0;
- if (DECL_SIZE_UNIT (field) == NULL_TREE
- || !tree_fits_shwi_p (DECL_SIZE_UNIT (field)))
- return 0;
- fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
+ {
+ if (mask || off != -1)
+ return 0;
+ if (val == NULL_TREE)
+ continue;
+ if (TREE_CODE (TREE_TYPE (val)) != ARRAY_TYPE)
+ return 0;
+ fieldsize = int_size_in_bytes (TREE_TYPE (val));
+ if (fieldsize < 0
+ || (int) fieldsize != fieldsize
+ || (pos + fieldsize) > INT_MAX)
+ return 0;
+ if (pos + fieldsize > total_bytes)
+ {
+ if (ptr != NULL && total_bytes < len)
+ memset (ptr + total_bytes, '\0',
+ MIN (pos + fieldsize, len) - total_bytes);
+ total_bytes = pos + fieldsize;
+ }
+ }
+ else
+ {
+ if (DECL_SIZE_UNIT (field) == NULL_TREE
+ || !tree_fits_shwi_p (DECL_SIZE_UNIT (field)))
+ return 0;
+ fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
+ }
if (fieldsize == 0)
continue;
@@ -8103,30 +8325,49 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
return 0;
- tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
- if (repr == NULL_TREE
- || TREE_CODE (val) != INTEGER_CST
- || !INTEGRAL_TYPE_P (TREE_TYPE (repr)))
+ if (TREE_CODE (val) != INTEGER_CST)
return 0;
- HOST_WIDE_INT rpos = int_byte_position (repr);
+ tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
+ tree repr_type = NULL_TREE;
+ HOST_WIDE_INT rpos = 0;
+ if (repr && INTEGRAL_TYPE_P (TREE_TYPE (repr)))
+ {
+ rpos = int_byte_position (repr);
+ repr_type = TREE_TYPE (repr);
+ }
+ else
+ {
+ repr_type = find_bitfield_repr_type (fieldsize, len);
+ if (repr_type == NULL_TREE)
+ return 0;
+ HOST_WIDE_INT repr_size = int_size_in_bytes (repr_type);
+ gcc_assert (repr_size > 0 && repr_size <= len);
+ if (pos + repr_size <= o + len)
+ rpos = pos;
+ else
+ {
+ rpos = o + len - repr_size;
+ gcc_assert (rpos <= pos);
+ }
+ }
+
if (rpos > pos)
return 0;
- wide_int w = wi::to_wide (val,
- TYPE_PRECISION (TREE_TYPE (repr)));
- int diff = (TYPE_PRECISION (TREE_TYPE (repr))
+ wide_int w = wi::to_wide (val, TYPE_PRECISION (repr_type));
+ int diff = (TYPE_PRECISION (repr_type)
- TYPE_PRECISION (TREE_TYPE (field)));
HOST_WIDE_INT bitoff = (pos - rpos) * BITS_PER_UNIT + bpos;
if (!BYTES_BIG_ENDIAN)
w = wi::lshift (w, bitoff);
else
w = wi::lshift (w, diff - bitoff);
- val = wide_int_to_tree (TREE_TYPE (repr), w);
+ val = wide_int_to_tree (repr_type, w);
unsigned char buf[MAX_BITSIZE_MODE_ANY_INT
/ BITS_PER_UNIT + 1];
int l = native_encode_int (val, buf, sizeof buf, 0);
- if (l * BITS_PER_UNIT != TYPE_PRECISION (TREE_TYPE (repr)))
+ if (l * BITS_PER_UNIT != TYPE_PRECISION (repr_type))
return 0;
if (ptr == NULL)
@@ -8139,15 +8380,31 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
{
if (!BYTES_BIG_ENDIAN)
{
- int mask = (1 << bpos) - 1;
- buf[pos - rpos] &= ~mask;
- buf[pos - rpos] |= ptr[pos - o] & mask;
+ int msk = (1 << bpos) - 1;
+ buf[pos - rpos] &= ~msk;
+ buf[pos - rpos] |= ptr[pos - o] & msk;
+ if (mask)
+ {
+ if (fieldsize > 1 || epos == 0)
+ mask[pos] &= msk;
+ else
+ mask[pos] &= (msk | ~((1 << epos) - 1));
+ }
}
else
{
- int mask = (1 << (BITS_PER_UNIT - bpos)) - 1;
- buf[pos - rpos] &= mask;
- buf[pos - rpos] |= ptr[pos - o] & ~mask;
+ int msk = (1 << (BITS_PER_UNIT - bpos)) - 1;
+ buf[pos - rpos] &= msk;
+ buf[pos - rpos] |= ptr[pos - o] & ~msk;
+ if (mask)
+ {
+ if (fieldsize > 1 || epos == 0)
+ mask[pos] &= ~msk;
+ else
+ mask[pos] &= (~msk
+ | ((1 << (BITS_PER_UNIT - epos))
+ - 1));
+ }
}
}
/* If the bitfield does not end at byte boundary, handle
@@ -8158,27 +8415,37 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
{
if (!BYTES_BIG_ENDIAN)
{
- int mask = (1 << epos) - 1;
- buf[pos - rpos + fieldsize - 1] &= mask;
+ int msk = (1 << epos) - 1;
+ buf[pos - rpos + fieldsize - 1] &= msk;
buf[pos - rpos + fieldsize - 1]
- |= ptr[pos + fieldsize - 1 - o] & ~mask;
+ |= ptr[pos + fieldsize - 1 - o] & ~msk;
+ if (mask && (fieldsize > 1 || bpos == 0))
+ mask[pos + fieldsize - 1] &= ~msk;
}
else
{
- int mask = (1 << (BITS_PER_UNIT - epos)) - 1;
- buf[pos - rpos + fieldsize - 1] &= ~mask;
+ int msk = (1 << (BITS_PER_UNIT - epos)) - 1;
+ buf[pos - rpos + fieldsize - 1] &= ~msk;
buf[pos - rpos + fieldsize - 1]
- |= ptr[pos + fieldsize - 1 - o] & mask;
+ |= ptr[pos + fieldsize - 1 - o] & msk;
+ if (mask && (fieldsize > 1 || bpos == 0))
+ mask[pos + fieldsize - 1] &= msk;
}
}
if (off == -1
|| (pos >= off
&& (pos + fieldsize <= (HOST_WIDE_INT) off + len)))
- memcpy (ptr + pos - o, buf + (pos - rpos), fieldsize);
+ {
+ memcpy (ptr + pos - o, buf + (pos - rpos), fieldsize);
+ if (mask && (fieldsize > (bpos != 0) + (epos != 0)))
+ memset (mask + pos + (bpos != 0), 0,
+ fieldsize - (bpos != 0) - (epos != 0));
+ }
else
{
/* Partial overlap. */
HOST_WIDE_INT fsz = fieldsize;
+ gcc_assert (mask == NULL);
if (pos < off)
{
fsz -= (off - pos);
@@ -8195,11 +8462,31 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
|| (pos >= off
&& (pos + fieldsize <= (HOST_WIDE_INT) off + len)))
{
- if (!native_encode_initializer (val, ptr ? ptr + pos - o
- : NULL,
- fieldsize,
- off == -1 ? -1 : 0))
+ int fldsize = fieldsize;
+ if (off == -1)
+ {
+ tree fld = DECL_CHAIN (field);
+ while (fld)
+ {
+ if (TREE_CODE (fld) == FIELD_DECL)
+ break;
+ fld = DECL_CHAIN (fld);
+ }
+ if (fld == NULL_TREE)
+ fldsize = len - pos;
+ }
+ r = native_encode_initializer (val, ptr ? ptr + pos - o
+ : NULL,
+ fldsize,
+ off == -1 ? -1 : 0,
+ mask ? mask + pos : NULL);
+ if (!r)
return 0;
+ if (off == -1
+ && fldsize != fieldsize
+ && r > fieldsize
+ && pos + r > total_bytes)
+ total_bytes = pos + r;
}
else
{
@@ -8207,6 +8494,7 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
unsigned char *p = NULL;
int no = 0;
int l;
+ gcc_assert (mask == NULL);
if (pos >= off)
{
if (ptr)
@@ -8220,7 +8508,7 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
no = off - pos;
l = len;
}
- if (!native_encode_initializer (val, p, l, no))
+ if (!native_encode_initializer (val, p, l, no, NULL))
return 0;
}
}
@@ -8496,6 +8784,168 @@ can_native_interpret_type_p (tree type)
}
}
+/* Attempt to interpret aggregate of TYPE from bytes encoded in target
+ byte order at PTR + OFF with LEN bytes. Does not handle unions. */
+
+tree
+native_interpret_aggregate (tree type, const unsigned char *ptr, int off,
+ int len)
+{
+ vec<constructor_elt, va_gc> *elts = NULL;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ HOST_WIDE_INT eltsz = int_size_in_bytes (TREE_TYPE (type));
+ if (eltsz < 0 || eltsz > len || TYPE_DOMAIN (type) == NULL_TREE)
+ return NULL_TREE;
+
+ HOST_WIDE_INT cnt = 0;
+ if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ {
+ if (!tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+ return NULL_TREE;
+ cnt = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1;
+ }
+ if (eltsz == 0)
+ cnt = 0;
+ HOST_WIDE_INT pos = 0;
+ for (HOST_WIDE_INT i = 0; i < cnt; i++, pos += eltsz)
+ {
+ tree v = NULL_TREE;
+ if (pos >= len || pos + eltsz > len)
+ return NULL_TREE;
+ if (can_native_interpret_type_p (TREE_TYPE (type)))
+ {
+ v = native_interpret_expr (TREE_TYPE (type),
+ ptr + off + pos, eltsz);
+ if (v == NULL_TREE)
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
+ v = native_interpret_aggregate (TREE_TYPE (type), ptr, off + pos,
+ eltsz);
+ if (v == NULL_TREE)
+ return NULL_TREE;
+ CONSTRUCTOR_APPEND_ELT (elts, size_int (i), v);
+ }
+ return build_constructor (type, elts);
+ }
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return NULL_TREE;
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL || DECL_PADDING_P (field))
+ continue;
+ tree fld = field;
+ HOST_WIDE_INT bitoff = 0, pos = 0, sz = 0;
+ int diff = 0;
+ tree v = NULL_TREE;
+ if (DECL_BIT_FIELD (field))
+ {
+ fld = DECL_BIT_FIELD_REPRESENTATIVE (field);
+ if (fld && INTEGRAL_TYPE_P (TREE_TYPE (fld)))
+ {
+ poly_int64 bitoffset;
+ poly_uint64 field_offset, fld_offset;
+ if (poly_int_tree_p (DECL_FIELD_OFFSET (field), &field_offset)
+ && poly_int_tree_p (DECL_FIELD_OFFSET (fld), &fld_offset))
+ bitoffset = (field_offset - fld_offset) * BITS_PER_UNIT;
+ else
+ bitoffset = 0;
+ bitoffset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
+ - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (fld)));
+ diff = (TYPE_PRECISION (TREE_TYPE (fld))
+ - TYPE_PRECISION (TREE_TYPE (field)));
+ if (!bitoffset.is_constant (&bitoff)
+ || bitoff < 0
+ || bitoff > diff)
+ return NULL_TREE;
+ }
+ else
+ {
+ if (!tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (field)))
+ return NULL_TREE;
+ int fieldsize = TYPE_PRECISION (TREE_TYPE (field));
+ int bpos = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field));
+ bpos %= BITS_PER_UNIT;
+ fieldsize += bpos;
+ fieldsize += BITS_PER_UNIT - 1;
+ fieldsize /= BITS_PER_UNIT;
+ tree repr_type = find_bitfield_repr_type (fieldsize, len);
+ if (repr_type == NULL_TREE)
+ return NULL_TREE;
+ sz = int_size_in_bytes (repr_type);
+ if (sz < 0 || sz > len)
+ return NULL_TREE;
+ pos = int_byte_position (field);
+ if (pos < 0 || pos > len || pos + fieldsize > len)
+ return NULL_TREE;
+ HOST_WIDE_INT rpos;
+ if (pos + sz <= len)
+ rpos = pos;
+ else
+ {
+ rpos = len - sz;
+ gcc_assert (rpos <= pos);
+ }
+ bitoff = (HOST_WIDE_INT) (pos - rpos) * BITS_PER_UNIT + bpos;
+ pos = rpos;
+ diff = (TYPE_PRECISION (repr_type)
+ - TYPE_PRECISION (TREE_TYPE (field)));
+ v = native_interpret_expr (repr_type, ptr + off + pos, sz);
+ if (v == NULL_TREE)
+ return NULL_TREE;
+ fld = NULL_TREE;
+ }
+ }
+
+ if (fld)
+ {
+ sz = int_size_in_bytes (TREE_TYPE (fld));
+ if (sz < 0 || sz > len)
+ return NULL_TREE;
+ tree byte_pos = byte_position (fld);
+ if (!tree_fits_shwi_p (byte_pos))
+ return NULL_TREE;
+ pos = tree_to_shwi (byte_pos);
+ if (pos < 0 || pos > len || pos + sz > len)
+ return NULL_TREE;
+ }
+ if (fld == NULL_TREE)
+ /* Already handled above. */;
+ else if (can_native_interpret_type_p (TREE_TYPE (fld)))
+ {
+ v = native_interpret_expr (TREE_TYPE (fld),
+ ptr + off + pos, sz);
+ if (v == NULL_TREE)
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (fld)) == ARRAY_TYPE)
+ v = native_interpret_aggregate (TREE_TYPE (fld), ptr, off + pos, sz);
+ if (v == NULL_TREE)
+ return NULL_TREE;
+ if (fld != field)
+ {
+ if (TREE_CODE (v) != INTEGER_CST)
+ return NULL_TREE;
+
+ /* FIXME: Figure out how to handle PDP endian bitfields. */
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ return NULL_TREE;
+ if (!BYTES_BIG_ENDIAN)
+ v = wide_int_to_tree (TREE_TYPE (field),
+ wi::lrshift (wi::to_wide (v), bitoff));
+ else
+ v = wide_int_to_tree (TREE_TYPE (field),
+ wi::lrshift (wi::to_wide (v),
+ diff - bitoff));
+ }
+ CONSTRUCTOR_APPEND_ELT (elts, field, v);
+ }
+ return build_constructor (type, elts);
+}
+
/* Routines for manipulation of native_encode_expr encoded data if the encoded
or extracted constant positions and/or sizes aren't byte aligned. */
@@ -8943,8 +9393,17 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
- return fold_build_pointer_plus_loc
- (loc, fold_convert_loc (loc, type, arg00), arg01);
+ /* If -fsanitize=alignment, avoid this optimization in GENERIC
+ when the pointed type needs higher alignment than
+ the p+ first operand's pointed type. */
+ if (!in_gimple_form
+ && sanitize_flags_p (SANITIZE_ALIGNMENT)
+ && (min_align_of_type (TREE_TYPE (type))
+ > min_align_of_type (TREE_TYPE (TREE_TYPE (arg00)))))
+ return NULL_TREE;
+
+ arg00 = fold_convert_loc (loc, type, arg00);
+ return fold_build_pointer_plus_loc (loc, arg00, arg01);
}
/* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
@@ -13662,6 +14121,248 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
}
}
+/* Return true if expression X cannot be (or contain) a NaN or infinity.
+ This function returns true for integer expressions, and returns
+ false if uncertain. */
+
+bool
+tree_expr_finite_p (const_tree x)
+{
+ machine_mode mode = element_mode (x);
+ if (!HONOR_NANS (mode) && !HONOR_INFINITIES (mode))
+ return true;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isfinite (TREE_REAL_CST_PTR (x));
+ case COMPLEX_CST:
+ return tree_expr_finite_p (TREE_REALPART (x))
+ && tree_expr_finite_p (TREE_IMAGPART (x));
+ case FLOAT_EXPR:
+ return true;
+ case ABS_EXPR:
+ case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ case NEGATE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_finite_p (TREE_OPERAND (x, 0));
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return tree_expr_finite_p (TREE_OPERAND (x, 0))
+ && tree_expr_finite_p (TREE_OPERAND (x, 1));
+ case COND_EXPR:
+ return tree_expr_finite_p (TREE_OPERAND (x, 1))
+ && tree_expr_finite_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return tree_expr_finite_p (CALL_EXPR_ARG (x, 0));
+ CASE_CFN_FMAX:
+ CASE_CFN_FMIN:
+ return tree_expr_finite_p (CALL_EXPR_ARG (x, 0))
+ && tree_expr_finite_p (CALL_EXPR_ARG (x, 1));
+ default:
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X evaluates to an infinity.
+ This function returns false for integer expressions. */
+
+bool
+tree_expr_infinite_p (const_tree x)
+{
+ if (!HONOR_INFINITIES (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isinf (TREE_REAL_CST_PTR (x));
+ case ABS_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_infinite_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_infinite_p (TREE_OPERAND (x, 1))
+ && tree_expr_infinite_p (TREE_OPERAND (x, 2));
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X could evaluate to an infinity.
+ This function returns false for integer expressions, and returns
+ true if uncertain. */
+
+bool
+tree_expr_maybe_infinite_p (const_tree x)
+{
+ if (!HONOR_INFINITIES (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isinf (TREE_REAL_CST_PTR (x));
+ case FLOAT_EXPR:
+ return false;
+ case ABS_EXPR:
+ case NEGATE_EXPR:
+ return tree_expr_maybe_infinite_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_maybe_infinite_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_infinite_p (TREE_OPERAND (x, 2));
+ default:
+ return true;
+ }
+}
+
+/* Return true if expression X evaluates to a signaling NaN.
+ This function returns false for integer expressions. */
+
+bool
+tree_expr_signaling_nan_p (const_tree x)
+{
+ if (!HONOR_SNANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_issignaling_nan (TREE_REAL_CST_PTR (x));
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_signaling_nan_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_signaling_nan_p (TREE_OPERAND (x, 1))
+ && tree_expr_signaling_nan_p (TREE_OPERAND (x, 2));
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X could evaluate to a signaling NaN.
+ This function returns false for integer expressions, and returns
+ true if uncertain. */
+
+bool
+tree_expr_maybe_signaling_nan_p (const_tree x)
+{
+ if (!HONOR_SNANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_issignaling_nan (TREE_REAL_CST_PTR (x));
+ case FLOAT_EXPR:
+ return false;
+ case ABS_EXPR:
+ case CONVERT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 0));
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 0))
+ || tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 1));
+ case COND_EXPR:
+ return tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 0));
+ CASE_CFN_FMAX:
+ CASE_CFN_FMIN:
+ return tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 0))
+ || tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 1));
+ default:
+ return true;
+ }
+ default:
+ return true;
+ }
+}
+
+/* Return true if expression X evaluates to a NaN.
+ This function returns false for integer expressions. */
+
+bool
+tree_expr_nan_p (const_tree x)
+{
+ if (!HONOR_NANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isnan (TREE_REAL_CST_PTR (x));
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_nan_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_nan_p (TREE_OPERAND (x, 1))
+ && tree_expr_nan_p (TREE_OPERAND (x, 2));
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X could evaluate to a NaN.
+ This function returns false for integer expressions, and returns
+ true if uncertain. */
+
+bool
+tree_expr_maybe_nan_p (const_tree x)
+{
+ if (!HONOR_NANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isnan (TREE_REAL_CST_PTR (x));
+ case FLOAT_EXPR:
+ return false;
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ return !tree_expr_finite_p (TREE_OPERAND (x, 0))
+ || !tree_expr_finite_p (TREE_OPERAND (x, 1));
+ case ABS_EXPR:
+ case CONVERT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_maybe_nan_p (TREE_OPERAND (x, 0));
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return tree_expr_maybe_nan_p (TREE_OPERAND (x, 0))
+ || tree_expr_maybe_nan_p (TREE_OPERAND (x, 1));
+ case COND_EXPR:
+ return tree_expr_maybe_nan_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_nan_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 0));
+ CASE_CFN_FMAX:
+ CASE_CFN_FMIN:
+ return tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 0))
+ || tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 1));
+ default:
+ return true;
+ }
+ default:
+ return true;
+ }
+}
+
#define tree_expr_nonnegative_warnv_p(X, Y) \
_Pragma ("GCC error \"Use RECURSE for recursive calls\"") 0
@@ -13839,7 +14540,13 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
return false;
case BIT_AND_EXPR:
+ return RECURSE (op0) || RECURSE (op1);
+
case MAX_EXPR:
+ /* Usually RECURSE (op0) || RECURSE (op1) but NaNs complicate
+ things. */
+ if (tree_expr_maybe_nan_p (op0) || tree_expr_maybe_nan_p (op1))
+ return RECURSE (op0) && RECURSE (op1);
return RECURSE (op0) || RECURSE (op1);
case BIT_IOR_EXPR:
@@ -13999,8 +14706,18 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
CASE_CFN_FMAX:
CASE_CFN_FMAX_FN:
- /* True if the 1st OR 2nd arguments are nonnegative. */
- return RECURSE (arg0) || RECURSE (arg1);
+ /* Usually RECURSE (arg0) || RECURSE (arg1) but NaNs complicate
+ things. In the presence of sNaNs, we're only guaranteed to be
+ non-negative if both operands are non-negative. In the presence
+ of qNaNs, we're non-negative if either operand is non-negative
+ and can't be a qNaN, or if both operands are non-negative. */
+ if (tree_expr_maybe_signaling_nan_p (arg0) ||
+ tree_expr_maybe_signaling_nan_p (arg1))
+ return RECURSE (arg0) && RECURSE (arg1);
+ return RECURSE (arg0) ? (!tree_expr_maybe_nan_p (arg0)
+ || RECURSE (arg1))
+ : (RECURSE (arg1)
+ && !tree_expr_maybe_nan_p (arg1));
CASE_CFN_FMIN:
CASE_CFN_FMIN_FN:
@@ -15565,11 +16282,6 @@ getbyterep (tree src, unsigned HOST_WIDE_INT *strsize)
is equal to strlen (A) + 1. */
const unsigned HOST_WIDE_INT array_size = tree_to_uhwi (mem_size);
unsigned HOST_WIDE_INT init_bytes = TREE_STRING_LENGTH (src);
-
- /* Ideally this would turn into a gcc_checking_assert over time. */
- if (init_bytes > array_size)
- init_bytes = array_size;
-
const char *string = TREE_STRING_POINTER (src);
/* Ideally this would turn into a gcc_checking_assert over time. */
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 0c0f5fd..818c3d5 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -27,9 +27,11 @@ extern int folding_initializer;
/* Convert between trees and native memory representation. */
extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1);
extern int native_encode_initializer (tree, unsigned char *, int,
- int off = -1);
+ int off = -1, unsigned char * = nullptr);
extern tree native_interpret_expr (tree, const unsigned char *, int);
extern bool can_native_interpret_type_p (tree);
+extern tree native_interpret_aggregate (tree, const unsigned char *, int, int);
+extern tree find_bitfield_repr_type (int, int);
extern void shift_bytes_in_array_left (unsigned char *, unsigned int,
unsigned int);
extern void shift_bytes_in_array_right (unsigned char *, unsigned int,
@@ -186,6 +188,13 @@ extern tree non_lvalue_loc (location_t, tree);
extern bool tree_expr_nonzero_p (tree);
extern bool tree_expr_nonnegative_p (tree);
extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
+extern bool tree_expr_finite_p (const_tree);
+extern bool tree_expr_infinite_p (const_tree);
+extern bool tree_expr_maybe_infinite_p (const_tree);
+extern bool tree_expr_signaling_nan_p (const_tree);
+extern bool tree_expr_maybe_signaling_nan_p (const_tree);
+extern bool tree_expr_nan_p (const_tree);
+extern bool tree_expr_maybe_nan_p (const_tree);
extern tree make_range (tree, int *, tree *, tree *, bool *);
extern tree make_range_step (location_t, enum tree_code, tree, tree, tree,
tree *, tree *, int *, bool *);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 0dd7931..66e39f5 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,443 @@
+2020-12-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/97612
+ * primary.c (build_actual_constructor): Missing allocatable
+ components are set unallocated using EXPR_NULL. Then missing
+ components are tested for a default initializer.
+
+2020-12-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/93833
+ * trans-array.c (get_array_ctor_var_strlen): If the character
+ length backend_decl cannot be found, convert the expression and
+ use the string length. Clear up some minor white space issues
+ in the rest of the file.
+
+2020-12-27 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/97694
+ PR fortran/97723
+ * check.c (allocatable_check): Select rank temporaries are
+ permitted even though they are treated as associate variables.
+ * resolve.c (gfc_resolve_code): Break on select rank as well as
+ select type so that the block os resolved.
+ * trans-stmt.c (trans_associate_var): Class associate variables
+ that are optional dummies must use the backend_decl.
+
+2020-12-26 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/98022
+ * data.c (gfc_assign_data_value): Throw an error for inquiry
+ references. Follow with corrected code that would provide the
+ expected result and provides clean error recovery.
+
+2020-12-26 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/83118
+ * trans-array.c (gfc_alloc_allocatable_for_assignment): Make
+ sure that class expressions are captured for dummy arguments by
+ use of gfc_get_class_from_gfc_expr otherwise the wrong vptr is
+ used.
+ * trans-expr.c (gfc_get_class_from_gfc_expr): New function.
+ (gfc_get_class_from_expr): If a constant expression is
+ encountered, return NULL_TREE;
+ (gfc_trans_assignment_1): Deallocate rhs allocatable components
+ after passing derived type function results to class lhs.
+ * trans.h : Add prototype for gfc_get_class_from_gfc_expr.
+
+2020-12-25 Harald Anlauf <anlauf@gmx.de>
+
+ * data.c (gfc_assign_data_value): Restrict use of
+ create_character_initializer to constant initializers.
+ * trans-expr.c (gfc_conv_initializer): Ensure that character
+ initializer is constant, otherwise fall through to get the same
+ error handling as for non-character cases.
+
+2020-12-20 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * trans.c (create_var_debug_raw): Set DECL_ARTIFICIAL
+ on variables.
+
+2020-12-18 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/83118
+ PR fortran/96012
+ * resolve.c (resolve_ordinary_assign): Generate a vtable if
+ necessary for scalar non-polymorphic rhs's to unlimited lhs's.
+ * trans-array.c (get_class_info_from_ss): New function.
+ (gfc_trans_allocate_array_storage): Defer obtaining class
+ element type until all sources of class exprs are tried. Use
+ class API rather than TREE_OPERAND. Look for class expressions
+ in ss->info by calling get_class_info_from_ss. After, obtain
+ the element size for class descriptors. Where the element type
+ is unknown, cast the data as character(len=size) to overcome
+ unlimited polymorphic problems.
+ (gfc_conv_ss_descriptor): Do not fix class variable refs.
+ (build_class_array_ref, structure_alloc_comps): Replace code
+ replicating the new function gfc_resize_class_size_with_len.
+ (gfc_alloc_allocatable_for_assignment): Obtain element size
+ for lhs in cases of deferred characters and class enitities.
+ Move code for the element size of rhs to start of block. Clean
+ up extraction of class parameters throughout this function.
+ After the shape check test whether or not the lhs and rhs
+ element sizes are the same. Use earlier evaluation of
+ 'cond_null'. Reallocation of lhs only to happen if size changes
+ or element size changes.
+ * trans-expr.c (gfc_resize_class_size_with_len): New function.
+ (gfc_get_class_from_expr): If a constant expression is
+ encountered, return NULL_TREE;
+ (trans_scalar_class_assign): New function.
+ (gfc_conv_procedure_call): Ensure the vtable is present for
+ passing a non-class actual to an unlimited formal.
+ (trans_class_vptr_len_assignment): For expressions of type
+ BT_CLASS, extract the class expression if necessary. Use a
+ statement block outside the loop body. Ensure that 'rhs' is
+ of the correct type. Obtain rhs vptr in all circumstances.
+ (gfc_trans_scalar_assign): Call trans_scalar_class_assign to
+ make maximum use of the vptr copy in place of assignment.
+ (trans_class_assignment): Actually do reallocation if needed.
+ (gfc_trans_assignment_1): Simplify some of the logic with
+ 'realloc_flag'. Set 'vptr_copy' for all array assignments to
+ unlimited polymorphic lhs.
+ * trans.c (gfc_build_array_ref): Call gfc_resize_class_size_
+ with_len to correct span for unlimited polymorphic decls.
+ * trans.h : Add prototype for gfc_resize_class_size_with_len.
+
+2020-12-17 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/92587
+ * match.c (gfc_match_assignment): Move gfc_find_vtab call from here ...
+ * resolve.c (gfc_resolve_code): ... to here.
+
+2020-12-17 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/98307
+ * trans-stmt.c (check_forall_dependencies): Extend dependency
+ check to allocatable components of derived types.
+
+2020-12-16 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/98284
+ * resolve.c (check_data_variable): Reject DATA elements with the
+ ALLOCATABLE attribute.
+
+2020-12-15 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90207
+ * invoke.texi: Document -fdebug-aux-vars.
+ * lang.opt: Add -fdebug-aux-vars.
+ * trans.c (MAX_PREFIX_LEN): New macro.
+ (create_var_debug_raw): New function.
+ (gfc_create_var_np): Call create_var_debug_raw if
+ flag_debug_aux_vars is set.
+
+2020-12-13 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * dump-parse-tree.c (show_array_ref): Also show coarrays.
+ (debug): Implement for array reference.
+
+2020-12-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/98022
+ * data.c (gfc_assign_data_value): Handle inquiry references in
+ the data statement object list.
+
+2020-12-08 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses, show_omp_node,
+ show_code_node): Handle OMP SCAN.
+ * gfortran.h (enum gfc_statement): Add ST_OMP_SCAN.
+ (enum): Add OMP_LIST_SCAN_IN and OMP_LIST_SCAN_EX.
+ (enum gfc_exec_op): Add EXEC_OMP_SCAN.
+ * match.h (gfc_match_omp_scan): New prototype.
+ * openmp.c (gfc_match_omp_scan): New.
+ (gfc_match_omp_taskgroup): Cleanup.
+ (resolve_omp_clauses, gfc_resolve_omp_do_blocks,
+ omp_code_to_statement, gfc_resolve_omp_directive): Handle 'omp scan'.
+ * parse.c (decode_omp_directive, next_statement,
+ gfc_ascii_statement): Likewise.
+ * resolve.c (gfc_resolve_code): Handle EXEC_OMP_SCAN.
+ * st.c (gfc_free_statement): Likewise.
+ * trans-openmp.c (gfc_trans_omp_clauses, gfc_trans_omp_do,
+ gfc_split_omp_clauses): Handle 'omp scan'.
+
+2020-12-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/98016
+ * resolve.c (resolve_symbol): Set formal_arg_flag before
+ resolving an array spec and restore value afterwards.
+
+2020-12-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/95342
+ * decl.c (gfc_match_function_decl): Avoid NULL pointer dereference.
+ (gfc_match_subroutine): Likewise.
+
+2020-11-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/98011
+ * scanner.c (skip_free_comments, skip_fixed_comments): If only
+ -fopenacc but not -fopenmp is used, ignore OpenMP's conditional
+ compilation sentinels. Fix indentation, use 'else if' for readability.
+
+2020-11-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/98010
+ PR fortran/98013
+ * options.c (gfc_post_options): Also imply recursive with
+ -fopenacc.
+ * trans-decl.c (gfc_generate_function_code): Simplify condition.
+
+2020-11-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_expr): Use '==' not '=' for '.eq.'.
+
+2020-11-29 Harald Anlauf <anlauf@gmx.de>
+
+ * expr.c (simplify_parameter_variable): Fix up character length
+ after copying an array-valued expression.
+
+2020-11-28 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/97454
+ * trans-decl.c (gfc_get_extern_function_decl): Add argument
+ fnspec.
+ * trans-intrinsic.c (MAX_SPEC_ARG): Define.
+ (intrinsic_fnspec): New function.
+ (ADD_CHAR): Define.
+ (specific_intrinsic_symbol): Adjust comment. Pass
+ fn spec to gfc_get_extern_function_decl.
+ (gfc_conv_intrinsic_funcall): Add ANY, ALL, NORM2, PRODUCT
+ and SUM intrnisic. Add FIXME for cshift et al.
+ * trans-types.c (gfc_get_function_type): Add fnspec argument,
+ handle it.
+ * trans-types.h (gfc_get_function_type): Add optinal fnspec
+ argument.
+ * trans.h (gfc_get_extern_function_decl): Likewise.
+
+2020-11-25 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/85796
+ * resolve.c (traverse_data_list): Fix copy&paste errors; catch
+ step=0 in implied do loop.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (fortran.serial): Change from goal to a variable.
+ (.PHONY): Drop fortran.serial and fortran.prev.
+ (f951$(exeext)): Depend on $(fortran.serial) rather than
+ fortran.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (fortran.serial): New goal.
+ (.PHONY): Add fortran.serial fortran.prev.
+ (f951$(exeext)): Depend on fortran.prev. Call LINK_PROGRESS.
+
+2020-11-17 Harald Anlauf <anlauf@gmx.de>
+
+ * gfortran.texi: Fix description of GFC_RTCHECK_* to match actual
+ code.
+
+2020-11-16 Harald Anlauf <anlauf@gmx.de>
+
+ * trans-intrinsic.c (gfc_conv_intrinsic_size): Generate runtime
+ checking code for status of argument.
+
+2020-11-13 Gergö Barany <gergo@codesourcery.com>
+ Thomas Schwinge <thomas@codesourcery.com>
+
+ * lang.opt (fopenacc-kernels): Add.
+
+2020-11-12 Jakub Jelinek <jakub@redhat.com>
+
+ * f95-lang.c (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST):
+ Define.
+ (gfc_init_builtin_functions): Add alloc_size and warn_unused_result
+ attributes to __builtin_GOMP_alloc.
+ * types.def (BT_PTRMODE): New primitive type.
+ (BT_FN_VOID_PTR_PTRMODE, BT_FN_PTR_SIZE_SIZE_PTRMODE): New function
+ types.
+
+2020-11-12 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/97782
+ * trans-openmp.c (gfc_trans_oacc_construct, gfc_trans_omp_parallel_do,
+ gfc_trans_omp_parallel_do_simd, gfc_trans_omp_parallel_sections,
+ gfc_trans_omp_parallel_workshare, gfc_trans_omp_sections
+ gfc_trans_omp_single, gfc_trans_omp_task, gfc_trans_omp_teams
+ gfc_trans_omp_target, gfc_trans_omp_target_data,
+ gfc_trans_omp_workshare): Use code->loc instead of input_location
+ when building the OMP_/OACC_ construct.
+
+2020-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/97768
+ * misc.c (gfc_typename): Use ex->value.character.length only if
+ ex->expr_type == EXPR_CONSTANT. If ex->ts.deferred, print : instead
+ of length. If ex->ts.u.cl && ex->ts.u.cl->length == NULL, print *
+ instead of length. Otherwise if character length is non-constant,
+ print just CHARACTER or CHARACTER(KIND=N).
+
+2020-11-10 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses): Handle new reduction enums.
+ * gfortran.h (OMP_LIST_REDUCTION_INSCAN, OMP_LIST_REDUCTION_TASK,
+ OMP_LIST_IN_REDUCTION, OMP_LIST_TASK_REDUCTION): Add enums.
+ * openmp.c (enum omp_mask1): Add OMP_CLAUSE_IN_REDUCTION
+ and OMP_CLAUSE_TASK_REDUCTION.
+ (gfc_match_omp_clause_reduction): Extend reduction handling;
+ moved from ...
+ (gfc_match_omp_clauses): ... here. Add calls to it.
+ (OMP_TASK_CLAUSES, OMP_TARGET_CLAUSES, OMP_TASKLOOP_CLAUSES):
+ Add OMP_CLAUSE_IN_REDUCTION.
+ (gfc_match_omp_taskgroup): Add task_reduction matching.
+ (resolve_omp_clauses): Update for new reduction clause changes;
+ remove removed nonmonotonic-schedule restrictions.
+ (gfc_resolve_omp_parallel_blocks): Add new enums to switch.
+ * trans-openmp.c (gfc_omp_clause_default_ctor,
+ gfc_trans_omp_reduction_list, gfc_trans_omp_clauses,
+ gfc_split_omp_clauses): Handle updated reduction clause.
+
+2020-11-10 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/95847
+ * trans-decl.c (gfc_get_symbol_decl): Do not (re)set the location
+ of an external procedure.
+ (build_entry_thunks, generate_coarray_init, create_main_function,
+ gfc_generate_function_code): Use fndecl's location in BIND_EXPR.
+
+2020-11-09 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/90111
+ * parse.c (case_decl): Move ST_OACC_ROUTINE and ST_OACC_DECLARE to ...
+ (case_omp_decl): ... here.
+ (verify_st_order): Update comment.
+
+2020-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * openmp.c (oacc_is_parallel, resolve_oacc_params_in_parallel):
+ Remove.
+ (resolve_oacc_loop_blocks): Don't call the former.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * openmp.c (gfc_match_oacc_atomic): No longer accept 'update capture'.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/97652
+ * module.c (mio_symbol): Fix symbol name for pdt_type.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * cpp.c (gfc_cpp_add_dep): Only add dependency if we're recording
+ them.
+ (gfc_cpp_init): Likewise for target.
+
+2020-11-03 Tobias Burnus <tobias@codesourcery.com>
+
+ * decl.c (ext_attr_list): Add EXT_ATTR_DEPRECATED.
+ * gfortran.h (ext_attr_id_t): Ditto.
+ * gfortran.texi (GCC$ ATTRIBUTES): Document it.
+ * resolve.c (resolve_variable, resolve_function,
+ resolve_call, resolve_values): Show -Wdeprecated-declarations warning.
+ * trans-decl.c (add_attributes_to_decl): Skip those
+ with no middle_end_name.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/92793
+ * trans-openmp.c (gfc_trans_omp_clauses): More precise location
+ information for OpenACC 'gang', 'worker', 'vector' clauses with
+ argument.
+
+2020-11-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/92793
+ * trans.c (gfc_set_backend_locus): Use 'gfc_get_location'.
+ (gfc_restore_backend_locus): Adjust.
+
+2020-11-02 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/97655
+ * openmp.c (gfc_match_omp_atomic): Fix mem-order handling;
+ reject specifying update + capture together.
+
+2020-10-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses): Handle atomic clauses.
+ (show_omp_node): Call it for atomic.
+ * gfortran.h (enum gfc_omp_atomic_op): Add GFC_OMP_ATOMIC_UNSET,
+ remove GFC_OMP_ATOMIC_SEQ_CST and GFC_OMP_ATOMIC_ACQ_REL.
+ (enum gfc_omp_memorder): Replace OMP_MEMORDER_LAST by
+ OMP_MEMORDER_UNSET, add OMP_MEMORDER_SEQ_CST/OMP_MEMORDER_RELAXED.
+ (gfc_omp_clauses): Add capture and atomic_op.
+ (gfc_code): remove omp_atomic.
+ * openmp.c (enum omp_mask1): Add atomic, capture, memorder clauses.
+ (gfc_match_omp_clauses): Match them.
+ (OMP_ATOMIC_CLAUSES): Add.
+ (gfc_match_omp_flush): Update for 'last' to 'unset' change.
+ (gfc_match_omp_oacc_atomic): Removed and placed content ..
+ (gfc_match_omp_atomic): ... here. Update for OpenMP 5 clauses.
+ (gfc_match_oacc_atomic): Match directly here.
+ (resolve_omp_atomic, gfc_resolve_omp_directive): Update.
+ * parse.c (parse_omp_oacc_atomic): Update for struct gfc_code changes.
+ * resolve.c (gfc_resolve_blocks): Update assert.
+ * st.c (gfc_free_statement): Also call for EXEC_O{ACC,MP}_ATOMIC.
+ * trans-openmp.c (gfc_trans_omp_atomic): Update.
+ (gfc_trans_omp_flush): Update for 'last' to 'unset' change.
+
+2020-10-30 Jan Hubicka <jh@suse.cz>
+
+ * trans-types.c: Include alias.h
+ (gfc_get_array_type_bounds): Set typeless storage.
+
+2020-10-27 Harald Anlauf <anlauf@gmx.de>
+
+ * resolve.c (gfc_impure_variable): A dummy argument with the VALUE
+ attribute may be redefined without making a procedure impure.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * trans-array.c (gfc_get_descriptor_field): New helper.
+ (gfc_conv_descriptor_data_get): Use it - drop strange
+ REFERENCE_TYPE handling and make sure we don't trigger it.
+ (gfc_conv_descriptor_data_addr): Use gfc_get_descriptor_field.
+ (gfc_conv_descriptor_data_set): Likewise.
+ (gfc_conv_descriptor_offset): Likewise.
+ (gfc_conv_descriptor_dtype): Likewise.
+ (gfc_conv_descriptor_span): Likewise.
+ (gfc_get_descriptor_dimension): Likewise.
+ (gfc_conv_descriptor_token): Likewise.
+ (gfc_conv_descriptor_subfield): New helper.
+ (gfc_conv_descriptor_stride): Use it.
+ (gfc_conv_descriptor_lbound): Likewise.
+ (gfc_conv_descriptor_ubound): Likewise.
+
+2020-10-25 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/97454
+ * gfortran.h (gfc_symbol): Add pass_as_value flag.
+ (gfc_copy_formal_args_intr): Add optional argument
+ copy_type.
+ (gfc_get_intrinsic_function_symbol): Add prototype.
+ (gfc_find_intrinsic_symbol): Add prototype.
+ * intrinsic.c (gfc_get_intrinsic_function_symbol): New function.
+ (gfc_find_intrinsic_symbol): New function.
+ * symbol.c (gfc_copy_formal_args_intr): Add argument. Handle case
+ where the type needs to be copied from the actual argument.
+ * trans-intrinsic.c (remove_empty_actual_arguments): New function.
+ (specific_intrinsic_symbol): New function.
+ (gfc_conv_intrinsic_funcall): Use it.
+ (strip_kind_from_actual): Adjust so that the expression pointer
+ is set to NULL.
+ (gfc_conv_intrinsic_minmaxloc): Likewise.
+ (gfc_conv_intrinsic_minmaxval): Adjust removal of dim.
+ * trans-types.c (gfc_sym_type): If sym->pass_as_value is set, do
+ not pass by reference.
+
2020-10-22 Tobias Burnus <tobias@codesourcery.com>
* gfortran.h (enum gfc_omp_memorder): Add.
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index 977db60..4afd874 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -72,6 +72,7 @@ fortran_OBJS = $(F95_OBJS) fortran/gfortranspec.o
#
# Define the names for selecting gfortran in LANGUAGES.
fortran: f951$(exeext)
+fortran.serial = f951$(exeext)
# Tell GNU make to ignore files by these names if they exist.
.PHONY: fortran
@@ -92,11 +93,12 @@ gfortran-cross$(exeext): gfortran$(exeext)
cp gfortran$(exeext) gfortran-cross$(exeext)
# The compiler itself is called f951.
-f951$(exeext): $(F95_OBJS) \
- $(BACKEND) $(LIBDEPS) attribs.o
+f951$(exeext): $(F95_OBJS) $(BACKEND) $(LIBDEPS) attribs.o $(fortran.prev)
+ @$(call LINK_PROGRESS,$(INDEX.fortran),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(F95_OBJS) $(BACKEND) $(ZLIB) $(LIBS) attribs.o \
$(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.fortran),end)
gt-fortran-trans.h : s-gtype; @true
#
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 1e64fab..d8829e4 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -289,7 +289,7 @@ bin2real (gfc_expr *x, int kind)
}
-/* Fortran 2018 treats a BOZ as simply a string of bits. gfc_boz2real ()
+/* Fortran 2018 treats a BOZ as simply a string of bits. gfc_boz2real ()
converts the string into a REAL of the appropriate kind. The treatment
of the sign bit is processor dependent. */
@@ -377,12 +377,12 @@ gfc_boz2real (gfc_expr *x, int kind)
}
-/* Fortran 2018 treats a BOZ as simply a string of bits. gfc_boz2int ()
+/* Fortran 2018 treats a BOZ as simply a string of bits. gfc_boz2int ()
converts the string into an INTEGER of the appropriate kind. The
treatment of the sign bit is processor dependent. If the converted
value exceeds the range of the type, then wrap-around semantics are
applied. */
-
+
bool
gfc_boz2int (gfc_expr *x, int kind)
{
@@ -975,7 +975,8 @@ allocatable_check (gfc_expr *e, int n)
symbol_attribute attr;
attr = gfc_variable_attr (e, NULL);
- if (!attr.allocatable || attr.associate_var)
+ if (!attr.allocatable
+ || (attr.associate_var && !attr.select_rank_temporary))
{
gfc_error ("%qs argument of %qs intrinsic at %L must be ALLOCATABLE",
gfc_current_intrinsic_arg[n]->name, gfc_current_intrinsic,
@@ -3232,7 +3233,7 @@ gfc_check_intconv (gfc_expr *x)
|| strcmp (gfc_current_intrinsic, "long") == 0)
{
gfc_error ("%qs intrinsic subprogram at %L has been deprecated. "
- "Use INT intrinsic subprogram.", gfc_current_intrinsic,
+ "Use INT intrinsic subprogram.", gfc_current_intrinsic,
&x->where);
return false;
}
@@ -3965,7 +3966,7 @@ gfc_check_findloc (gfc_actual_arglist *ap)
/* Check the kind of the characters argument match. */
if (a1 && v1 && a->ts.kind != v->ts.kind)
goto incompat;
-
+
d = ap->next->next->expr;
m = ap->next->next->next->expr;
k = ap->next->next->next->next->expr;
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index dcde557..51baf141 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -222,13 +222,15 @@ void
gfc_cpp_add_dep (const char *name, bool system)
{
if (!gfc_cpp_option.deps_skip_system || !system)
- deps_add_dep (cpp_get_deps (cpp_in), name);
+ if (mkdeps *deps = cpp_get_deps (cpp_in))
+ deps_add_dep (deps, name);
}
void
gfc_cpp_add_target (const char *name)
{
- deps_add_target (cpp_get_deps (cpp_in), name, 0);
+ if (mkdeps *deps = cpp_get_deps (cpp_in))
+ deps_add_target (deps, name, 0);
}
@@ -605,8 +607,8 @@ gfc_cpp_init (void)
cpp_assert (cpp_in, opt->arg);
}
else if (opt->code == OPT_MT || opt->code == OPT_MQ)
- deps_add_target (cpp_get_deps (cpp_in),
- opt->arg, opt->code == OPT_MQ);
+ if (mkdeps *deps = cpp_get_deps (cpp_in))
+ deps_add_target (deps, opt->arg, opt->code == OPT_MQ);
}
/* Pre-defined macros for non-required INTEGER kind types. */
diff --git a/gcc/fortran/data.c b/gcc/fortran/data.c
index 5147515..07fa1c5 100644
--- a/gcc/fortran/data.c
+++ b/gcc/fortran/data.c
@@ -20,14 +20,14 @@ along with GCC; see the file COPYING3. If not see
/* Notes for DATA statement implementation:
-
+
We first assign initial value to each symbol by gfc_assign_data_value
during resolving DATA statement. Refer to check_data_variable and
traverse_data_list in resolve.c.
-
+
The complexity exists in the handling of array section, implied do
and array of struct appeared in DATA statement.
-
+
We call gfc_conv_structure, gfc_con_array_array_initializer,
etc., to convert the initial value. Refer to trans-expr.c and
trans-array.c. */
@@ -221,11 +221,14 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
gfc_ref *ref;
gfc_expr *init;
gfc_expr *expr = NULL;
+ gfc_expr *rexpr;
gfc_constructor *con;
gfc_constructor *last_con;
gfc_symbol *symbol;
gfc_typespec *last_ts;
mpz_t offset;
+ const char *msg = "F18(R841): data-implied-do object at %L is neither an "
+ "array-element nor a scalar-structure-component";
symbol = lvalue->symtree->n.sym;
init = symbol->value;
@@ -464,6 +467,74 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
}
break;
+ case REF_INQUIRY:
+
+ /* After some discussion on clf it was determined that the following
+ violates F18(R841). If the error is removed, the expected result
+ is obtained. Leaving the code in place ensures a clean error
+ recovery. */
+ gfc_error (msg, &lvalue->where);
+
+ /* This breaks with the other reference types in that the output
+ constructor has to be of type COMPLEX, whereas the lvalue is
+ of type REAL. The rvalue is copied to the real or imaginary
+ part as appropriate. In addition, for all except scalar
+ complex variables, a complex expression has to provided, where
+ the constructor does not have it, and the expression modified
+ with a new value for the real or imaginary part. */
+ gcc_assert (ref->next == NULL && last_ts->type == BT_COMPLEX);
+ rexpr = gfc_copy_expr (rvalue);
+ if (!gfc_compare_types (&lvalue->ts, &rexpr->ts))
+ gfc_convert_type (rexpr, &lvalue->ts, 0);
+
+ /* This is the scalar, complex case, where an initializer exists. */
+ if (init && ref == lvalue->ref)
+ expr = symbol->value;
+ /* Then all cases, where a complex expression does not exist. */
+ else if (!last_con || !last_con->expr)
+ {
+ expr = gfc_get_constant_expr (BT_COMPLEX, lvalue->ts.kind,
+ &lvalue->where);
+ if (last_con)
+ last_con->expr = expr;
+ }
+ else
+ /* Finally, and existing constructor expression to be modified. */
+ expr = last_con->expr;
+
+ /* Rejection of LEN and KIND inquiry references is handled
+ elsewhere. The error here is added as backup. The assertion
+ of F2008 for RE and IM is also done elsewhere. */
+ switch (ref->u.i)
+ {
+ case INQUIRY_LEN:
+ case INQUIRY_KIND:
+ gfc_error ("LEN or KIND inquiry ref in DATA statement at %L",
+ &lvalue->where);
+ goto abort;
+ case INQUIRY_RE:
+ mpfr_set (mpc_realref (expr->value.complex),
+ rexpr->value.real,
+ GFC_RND_MODE);
+ break;
+ case INQUIRY_IM:
+ mpfr_set (mpc_imagref (expr->value.complex),
+ rexpr->value.real,
+ GFC_RND_MODE);
+ break;
+ }
+
+ /* Only the scalar, complex expression needs to be saved as the
+ symbol value since the last constructor expression is already
+ provided as the initializer in the code after the reference
+ cases. */
+ if (ref == lvalue->ref)
+ symbol->value = expr;
+
+ gfc_free_expr (rexpr);
+ mpz_clear (offset);
+ return true;
+
default:
gcc_unreachable ();
}
@@ -498,12 +569,11 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
return false;
}
- if (ref || last_ts->type == BT_CHARACTER)
+ if (ref || (last_ts->type == BT_CHARACTER
+ && rvalue->expr_type == EXPR_CONSTANT))
{
/* An initializer has to be constant. */
- if (rvalue->expr_type != EXPR_CONSTANT
- || (lvalue->ts.u.cl->length == NULL
- && !(ref && ref->u.ss.length != NULL)))
+ if (lvalue->ts.u.cl->length == NULL && !(ref && ref->u.ss.length != NULL))
return false;
expr = create_character_initializer (init, last_ts, ref, rvalue);
}
@@ -513,7 +583,7 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
&& gfc_has_default_initializer (lvalue->ts.u.derived))
{
gfc_error ("Nonpointer object %qs with default initialization "
- "shall not appear in a DATA statement at %L",
+ "shall not appear in a DATA statement at %L",
symbol->name, &lvalue->where);
return false;
}
@@ -540,13 +610,13 @@ abort:
/* Modify the index of array section and re-calculate the array offset. */
-void
+void
gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
mpz_t *offset_ret)
{
int i;
mpz_t delta;
- mpz_t tmp;
+ mpz_t tmp;
bool forwards;
int cmp;
gfc_expr *start, *end, *stride;
@@ -567,21 +637,21 @@ gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
forwards = true;
else
forwards = false;
- gfc_free_expr(stride);
+ gfc_free_expr(stride);
}
else
{
mpz_add_ui (section_index[i], section_index[i], 1);
forwards = true;
}
-
+
if (ar->end[i])
{
end = gfc_copy_expr(ar->end[i]);
if(!gfc_simplify_expr(end, 1))
gfc_internal_error("Simplification error");
cmp = mpz_cmp (section_index[i], end->value.integer);
- gfc_free_expr(end);
+ gfc_free_expr(end);
}
else
cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
@@ -595,7 +665,7 @@ gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
if(!gfc_simplify_expr(start, 1))
gfc_internal_error("Simplification error");
mpz_set (section_index[i], start->value.integer);
- gfc_free_expr(start);
+ gfc_free_expr(start);
}
else
mpz_set (section_index[i], ar->as->lower[i]->value.integer);
@@ -613,7 +683,7 @@ gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
mpz_mul (tmp, tmp, delta);
mpz_add (*offset_ret, tmp, *offset_ret);
- mpz_sub (tmp, ar->as->upper[i]->value.integer,
+ mpz_sub (tmp, ar->as->upper[i]->value.integer,
ar->as->lower[i]->value.integer);
mpz_add_ui (tmp, tmp, 1);
mpz_mul (delta, tmp, delta);
@@ -699,7 +769,7 @@ gfc_formalize_init_value (gfc_symbol *sym)
/* Get the integer value into RET_AS and SECTION from AS and AR, and return
offset. */
-
+
void
gfc_get_section_index (gfc_array_ref *ar, mpz_t *section_index, mpz_t *offset)
{
@@ -741,7 +811,7 @@ gfc_get_section_index (gfc_array_ref *ar, mpz_t *section_index, mpz_t *offset)
gcc_unreachable ();
}
- mpz_sub (tmp, ar->as->upper[i]->value.integer,
+ mpz_sub (tmp, ar->as->upper[i]->value.integer,
ar->as->lower[i]->value.integer);
mpz_add_ui (tmp, tmp, 1);
mpz_mul (delta, tmp, delta);
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 6df3206..c85ae0d 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -7408,6 +7408,7 @@ gfc_match_function_decl (void)
procedure interface body. */
if (sym->attr.is_bind_c && sym->attr.module_procedure && sym->old_symbol
&& strcmp (sym->name, sym->old_symbol->name) == 0
+ && sym->binding_label && sym->old_symbol->binding_label
&& strcmp (sym->binding_label, sym->old_symbol->binding_label) != 0)
{
const char *null = "NULL", *s1, *s2;
@@ -7923,6 +7924,7 @@ gfc_match_subroutine (void)
procedure interface body. */
if (sym->attr.module_procedure && sym->old_symbol
&& strcmp (sym->name, sym->old_symbol->name) == 0
+ && sym->binding_label && sym->old_symbol->binding_label
&& strcmp (sym->binding_label, sym->old_symbol->binding_label) != 0)
{
const char *null = "NULL", *s1, *s2;
@@ -11585,6 +11587,7 @@ const ext_attr_t ext_attr_list[] = {
{ "stdcall", EXT_ATTR_STDCALL, "stdcall" },
{ "fastcall", EXT_ATTR_FASTCALL, "fastcall" },
{ "no_arg_check", EXT_ATTR_NO_ARG_CHECK, NULL },
+ { "deprecated", EXT_ATTR_DEPRECATED, NULL },
{ NULL, EXT_ATTR_LAST, NULL }
};
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index d1a3325..31de25c 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -673,7 +673,7 @@ show_expr (gfc_expr *p)
break;
case INTRINSIC_EQ:
case INTRINSIC_EQ_OS:
- fputs ("= ", dumpfile);
+ fputs ("== ", dumpfile);
break;
case INTRINSIC_NE:
case INTRINSIC_NE_OS:
@@ -1612,7 +1612,11 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
case OMP_LIST_MAP: type = "MAP"; break;
case OMP_LIST_TO: type = "TO"; break;
case OMP_LIST_FROM: type = "FROM"; break;
- case OMP_LIST_REDUCTION: type = "REDUCTION"; break;
+ case OMP_LIST_REDUCTION:
+ case OMP_LIST_REDUCTION_INSCAN:
+ case OMP_LIST_REDUCTION_TASK: type = "REDUCTION"; break;
+ case OMP_LIST_IN_REDUCTION: type = "IN_REDUCTION"; break;
+ case OMP_LIST_TASK_REDUCTION: type = "TASK_REDUCTION"; break;
case OMP_LIST_DEVICE_RESIDENT: type = "DEVICE_RESIDENT"; break;
case OMP_LIST_LINK: type = "LINK"; break;
case OMP_LIST_USE_DEVICE: type = "USE_DEVICE"; break;
@@ -1621,10 +1625,16 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
case OMP_LIST_USE_DEVICE_ADDR: type = "USE_DEVICE_ADDR"; break;
case OMP_LIST_NONTEMPORAL: type = "NONTEMPORAL"; break;
+ case OMP_LIST_SCAN_IN: type = "INCLUSIVE"; break;
+ case OMP_LIST_SCAN_EX: type = "EXCLUSIVE"; break;
default:
gcc_unreachable ();
}
fprintf (dumpfile, " %s(", type);
+ if (list_type == OMP_LIST_REDUCTION_INSCAN)
+ fputs ("inscan, ", dumpfile);
+ if (list_type == OMP_LIST_REDUCTION_TASK)
+ fputs ("task, ", dumpfile);
show_omp_namelist (list_type, omp_clauses->lists[list_type]);
fputc (')', dumpfile);
}
@@ -1740,6 +1750,36 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
}
if (omp_clauses->depend_source)
fputs (" DEPEND(source)", dumpfile);
+ if (omp_clauses->capture)
+ fputs (" CAPTURE", dumpfile);
+ if (omp_clauses->atomic_op != GFC_OMP_ATOMIC_UNSET)
+ {
+ const char *atomic_op;
+ switch (omp_clauses->atomic_op)
+ {
+ case GFC_OMP_ATOMIC_READ: atomic_op = "READ"; break;
+ case GFC_OMP_ATOMIC_WRITE: atomic_op = "WRITE"; break;
+ case GFC_OMP_ATOMIC_UPDATE: atomic_op = "UPDATE"; break;
+ default: gcc_unreachable ();
+ }
+ fputc (' ', dumpfile);
+ fputs (atomic_op, dumpfile);
+ }
+ if (omp_clauses->memorder != OMP_MEMORDER_UNSET)
+ {
+ const char *memorder;
+ switch (omp_clauses->memorder)
+ {
+ case OMP_MEMORDER_ACQ_REL: memorder = "ACQ_REL"; break;
+ case OMP_MEMORDER_ACQUIRE: memorder = "AQUIRE"; break;
+ case OMP_MEMORDER_RELAXED: memorder = "RELAXED"; break;
+ case OMP_MEMORDER_RELEASE: memorder = "RELEASE"; break;
+ case OMP_MEMORDER_SEQ_CST: memorder = "SEQ_CST"; break;
+ default: gcc_unreachable ();
+ }
+ fputc (' ', dumpfile);
+ fputs (memorder, dumpfile);
+ }
}
/* Show a single OpenMP or OpenACC directive node and everything underneath it
@@ -1790,6 +1830,7 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_PARALLEL_DO_SIMD: name = "PARALLEL DO SIMD"; break;
case EXEC_OMP_PARALLEL_SECTIONS: name = "PARALLEL SECTIONS"; break;
case EXEC_OMP_PARALLEL_WORKSHARE: name = "PARALLEL WORKSHARE"; break;
+ case EXEC_OMP_SCAN: name = "SCAN"; break;
case EXEC_OMP_SECTIONS: name = "SECTIONS"; break;
case EXEC_OMP_SIMD: name = "SIMD"; break;
case EXEC_OMP_SINGLE: name = "SINGLE"; break;
@@ -1860,6 +1901,7 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
+ case EXEC_OMP_SCAN:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
@@ -1905,6 +1947,10 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_TASKWAIT:
case EXEC_OMP_TASKYIELD:
return;
+ case EXEC_OACC_ATOMIC:
+ case EXEC_OMP_ATOMIC:
+ omp_clauses = c->block ? c->block->ext.omp_clauses : NULL;
+ break;
default:
break;
}
@@ -1916,7 +1962,7 @@ show_omp_node (int level, gfc_code *c)
if (c->op == EXEC_OACC_CACHE || c->op == EXEC_OACC_UPDATE
|| c->op == EXEC_OACC_ENTER_DATA || c->op == EXEC_OACC_EXIT_DATA
|| c->op == EXEC_OMP_TARGET_UPDATE || c->op == EXEC_OMP_TARGET_ENTER_DATA
- || c->op == EXEC_OMP_TARGET_EXIT_DATA
+ || c->op == EXEC_OMP_TARGET_EXIT_DATA || c->op == EXEC_OMP_SCAN
|| (c->op == EXEC_OMP_ORDERED && c->block == NULL))
return;
if (c->op == EXEC_OMP_SECTIONS || c->op == EXEC_OMP_PARALLEL_SECTIONS)
@@ -3056,6 +3102,7 @@ show_code_node (int level, gfc_code *c)
case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
+ case EXEC_OMP_SCAN:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 32d905a..ae9b0a7 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -2096,6 +2096,9 @@ simplify_parameter_variable (gfc_expr *p, int type)
return false;
e->rank = p->rank;
+
+ if (e->ts.type == BT_CHARACTER && p->ts.u.cl)
+ e->ts = p->ts;
}
if (e->ts.type == BT_CHARACTER && e->ts.u.cl == NULL)
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 526b721..1a05144 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -531,7 +531,7 @@ gfc_builtin_function (tree decl)
return decl;
}
-/* So far we need just these 7 attribute types. */
+/* So far we need just these 8 attribute types. */
#define ATTR_NULL 0
#define ATTR_LEAF_LIST (ECF_LEAF)
#define ATTR_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF)
@@ -540,6 +540,8 @@ gfc_builtin_function (tree decl)
#define ATTR_PURE_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF | ECF_PURE)
#define ATTR_NOTHROW_LIST (ECF_NOTHROW)
#define ATTR_CONST_NOTHROW_LIST (ECF_NOTHROW | ECF_CONST)
+#define ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST \
+ (ECF_NOTHROW)
static void
gfc_define_builtin (const char *name, tree type, enum built_in_function code,
@@ -1236,6 +1238,13 @@ gfc_init_builtin_functions (void)
#undef DEF_GOACC_BUILTIN
#undef DEF_GOACC_BUILTIN_COMPILER
#undef DEF_GOMP_BUILTIN
+ tree gomp_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
+ tree two = build_int_cst (integer_type_node, 2);
+ DECL_ATTRIBUTES (gomp_alloc)
+ = tree_cons (get_identifier ("warn_unused_result"), NULL_TREE,
+ tree_cons (get_identifier ("alloc_size"),
+ build_tree_list (NULL_TREE, two),
+ DECL_ATTRIBUTES (gomp_alloc)));
}
gfc_define_builtin ("__builtin_trap", builtin_types[BT_FN_VOID],
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 0bed2e1..db704d1 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -261,7 +261,7 @@ enum gfc_statement
ST_OMP_TARGET_PARALLEL_DO_SIMD, ST_OMP_END_TARGET_PARALLEL_DO_SIMD,
ST_OMP_TARGET_ENTER_DATA, ST_OMP_TARGET_EXIT_DATA,
ST_OMP_TARGET_SIMD, ST_OMP_END_TARGET_SIMD,
- ST_OMP_TASKLOOP, ST_OMP_END_TASKLOOP,
+ ST_OMP_TASKLOOP, ST_OMP_END_TASKLOOP, ST_OMP_SCAN,
ST_OMP_TASKLOOP_SIMD, ST_OMP_END_TASKLOOP_SIMD, ST_OMP_ORDERED_DEPEND,
ST_OMP_REQUIRES, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL,
ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_EVENT_POST,
@@ -770,6 +770,7 @@ typedef enum
EXT_ATTR_CDECL,
EXT_ATTR_FASTCALL,
EXT_ATTR_NO_ARG_CHECK,
+ EXT_ATTR_DEPRECATED,
EXT_ATTR_LAST, EXT_ATTR_NUM = EXT_ATTR_LAST
}
ext_attr_id_t;
@@ -1276,7 +1277,13 @@ enum
OMP_LIST_MAP,
OMP_LIST_TO,
OMP_LIST_FROM,
+ OMP_LIST_SCAN_IN,
+ OMP_LIST_SCAN_EX,
OMP_LIST_REDUCTION,
+ OMP_LIST_REDUCTION_INSCAN,
+ OMP_LIST_REDUCTION_TASK,
+ OMP_LIST_IN_REDUCTION,
+ OMP_LIST_TASK_REDUCTION,
OMP_LIST_DEVICE_RESIDENT,
OMP_LIST_LINK,
OMP_LIST_USE_DEVICE,
@@ -1343,6 +1350,16 @@ enum gfc_omp_if_kind
OMP_IF_LAST
};
+enum gfc_omp_atomic_op
+{
+ GFC_OMP_ATOMIC_UNSET = 0,
+ GFC_OMP_ATOMIC_UPDATE = 1,
+ GFC_OMP_ATOMIC_READ = 2,
+ GFC_OMP_ATOMIC_WRITE = 3,
+ GFC_OMP_ATOMIC_MASK = 3,
+ GFC_OMP_ATOMIC_SWAP = 16
+};
+
enum gfc_omp_requires_kind
{
/* Keep in sync with gfc_namespace, esp. with omp_req_mem_order. */
@@ -1363,10 +1380,12 @@ enum gfc_omp_requires_kind
enum gfc_omp_memorder
{
+ OMP_MEMORDER_UNSET,
+ OMP_MEMORDER_SEQ_CST,
OMP_MEMORDER_ACQ_REL,
OMP_MEMORDER_RELEASE,
OMP_MEMORDER_ACQUIRE,
- OMP_MEMORDER_LAST
+ OMP_MEMORDER_RELAXED
};
typedef struct gfc_omp_clauses
@@ -1383,7 +1402,8 @@ typedef struct gfc_omp_clauses
bool nowait, ordered, untied, mergeable;
bool inbranch, notinbranch, defaultmap, nogroup;
bool sched_simd, sched_monotonic, sched_nonmonotonic;
- bool simd, threads, depend_source, order_concurrent;
+ bool simd, threads, depend_source, order_concurrent, capture;
+ enum gfc_omp_atomic_op atomic_op;
enum gfc_omp_memorder memorder;
enum gfc_omp_cancel_kind cancel;
enum gfc_omp_proc_bind_kind proc_bind;
@@ -2680,19 +2700,7 @@ enum gfc_exec_op
EXEC_OMP_TARGET_ENTER_DATA, EXEC_OMP_TARGET_EXIT_DATA,
EXEC_OMP_TARGET_PARALLEL, EXEC_OMP_TARGET_PARALLEL_DO,
EXEC_OMP_TARGET_PARALLEL_DO_SIMD, EXEC_OMP_TARGET_SIMD,
- EXEC_OMP_TASKLOOP, EXEC_OMP_TASKLOOP_SIMD
-};
-
-enum gfc_omp_atomic_op
-{
- GFC_OMP_ATOMIC_UPDATE = 0,
- GFC_OMP_ATOMIC_READ = 1,
- GFC_OMP_ATOMIC_WRITE = 2,
- GFC_OMP_ATOMIC_CAPTURE = 3,
- GFC_OMP_ATOMIC_MASK = 3,
- GFC_OMP_ATOMIC_SEQ_CST = 4,
- GFC_OMP_ATOMIC_ACQ_REL = 8,
- GFC_OMP_ATOMIC_SWAP = 16
+ EXEC_OMP_TASKLOOP, EXEC_OMP_TASKLOOP_SIMD, EXEC_OMP_SCAN
};
typedef struct gfc_code
@@ -2749,7 +2757,6 @@ typedef struct gfc_code
const char *omp_name;
gfc_omp_namelist *omp_namelist;
bool omp_bool;
- gfc_omp_atomic_op omp_atomic;
}
ext; /* Points to additional structures required by statement */
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 151e3d7..3b27217 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -3639,6 +3639,9 @@ requires an explicit interface.
@itemize
@item @code{NO_ARG_CHECK} -- disable the type, kind and rank checking
+@item @code{DEPRECATED} -- print a warning when using a such-tagged
+deprecated procedure, variable or parameter; the warning can be suppressed
+with @option{-Wno-deprecated-declarations}.
@end itemize
@@ -3863,8 +3866,8 @@ initialization using @code{_gfortran_set_args}.
Default: enabled.
@item @var{option}[6] @tab Enables run-time checking. Possible values
are (bitwise or-ed): GFC_RTCHECK_BOUNDS (1), GFC_RTCHECK_ARRAY_TEMPS (2),
-GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32),
-GFC_RTCHECK_BITS (64).
+GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (8), GFC_RTCHECK_POINTER (16),
+GFC_RTCHECK_MEM (32), GFC_RTCHECK_BITS (64).
Default: disabled.
@item @var{option}[7] @tab Unused.
@item @var{option}[8] @tab Show a warning when invoking @code{STOP} and
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index b93da4e..99cc2bc 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -691,6 +691,10 @@ fopenacc-dim=
Fortran LTO Joined Var(flag_openacc_dims)
; Documented in C
+fopenacc-kernels=
+Fortran RejectNegative Joined Enum(openacc_kernels) Var(flag_openacc_kernels) Init(OPENACC_KERNELS_PARLOOPS)
+; Documented in C
+
fopenmp
Fortran LTO
; Documented in C
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index bee73e7..c13fe96 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -1389,9 +1389,6 @@ gfc_match_assignment (void)
gfc_check_do_variable (lvalue->symtree);
- if (lvalue->ts.type == BT_CLASS)
- gfc_find_vtab (&rvalue->ts);
-
return MATCH_YES;
}
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 4ccb596..c771448 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -176,6 +176,7 @@ match gfc_match_omp_parallel_do_simd (void);
match gfc_match_omp_parallel_sections (void);
match gfc_match_omp_parallel_workshare (void);
match gfc_match_omp_requires (void);
+match gfc_match_omp_scan (void);
match gfc_match_omp_sections (void);
match gfc_match_omp_simd (void);
match gfc_match_omp_single (void);
diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
index 65bcfa6..e9b87aa 100644
--- a/gcc/fortran/misc.c
+++ b/gcc/fortran/misc.c
@@ -224,10 +224,32 @@ gfc_typename (gfc_expr *ex)
if (ex->ts.type == BT_CHARACTER)
{
- if (ex->ts.u.cl && ex->ts.u.cl->length)
- length = gfc_mpz_get_hwi (ex->ts.u.cl->length->value.integer);
- else
+ if (ex->expr_type == EXPR_CONSTANT)
length = ex->value.character.length;
+ else if (ex->ts.deferred)
+ {
+ if (ex->ts.kind == gfc_default_character_kind)
+ return "CHARACTER(:)";
+ sprintf (buffer, "CHARACTER(:,%d)", ex->ts.kind);
+ return buffer;
+ }
+ else if (ex->ts.u.cl && ex->ts.u.cl->length == NULL)
+ {
+ if (ex->ts.kind == gfc_default_character_kind)
+ return "CHARACTER(*)";
+ sprintf (buffer, "CHARACTER(*,%d)", ex->ts.kind);
+ return buffer;
+ }
+ else if (ex->ts.u.cl == NULL
+ || ex->ts.u.cl->length->expr_type != EXPR_CONSTANT)
+ {
+ if (ex->ts.kind == gfc_default_character_kind)
+ return "CHARACTER";
+ sprintf (buffer, "CHARACTER(KIND=%d)", ex->ts.kind);
+ return buffer;
+ }
+ else
+ length = gfc_mpz_get_hwi (ex->ts.u.cl->length->value.integer);
if (ex->ts.kind == gfc_default_character_kind)
sprintf (buffer, "CHARACTER(" HOST_WIDE_INT_PRINT_DEC ")", length);
else
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 33e7df7..4c6ff22 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4549,6 +4549,9 @@ mio_symbol (gfc_symbol *sym)
mio_symbol_attribute (&sym->attr);
+ if (sym->attr.pdt_type)
+ sym->name = gfc_dt_upper_string (sym->name);
+
/* Note that components are always saved, even if they are supposed
to be private. Component access is checked during searching. */
mio_component_list (&sym->components, sym->attr.vtype);
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index b143ba7..b1f0097 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -762,6 +762,8 @@ enum omp_mask1
OMP_CLAUSE_SHARED,
OMP_CLAUSE_COPYIN,
OMP_CLAUSE_REDUCTION,
+ OMP_CLAUSE_IN_REDUCTION,
+ OMP_CLAUSE_TASK_REDUCTION,
OMP_CLAUSE_IF,
OMP_CLAUSE_NUM_THREADS,
OMP_CLAUSE_SCHEDULE,
@@ -802,6 +804,9 @@ enum omp_mask1
OMP_CLAUSE_USE_DEVICE_PTR,
OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */
OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */
+ OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */
+ OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */
+ OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */
OMP_CLAUSE_NOWAIT,
/* This must come last. */
OMP_MASK1_LAST
@@ -956,6 +961,163 @@ gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
return false;
}
+/* reduction ( reduction-modifier, reduction-operator : variable-list )
+ in_reduction ( reduction-operator : variable-list )
+ task_reduction ( reduction-operator : variable-list ) */
+
+static match
+gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
+ bool allow_derived)
+{
+ if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
+ return MATCH_NO;
+ else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
+ return MATCH_NO;
+ else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
+ return MATCH_NO;
+
+ locus old_loc = gfc_current_locus;
+ int list_idx = 0;
+
+ if (pc == 'r' && !openacc)
+ {
+ if (gfc_match ("inscan") == MATCH_YES)
+ list_idx = OMP_LIST_REDUCTION_INSCAN;
+ else if (gfc_match ("task") == MATCH_YES)
+ list_idx = OMP_LIST_REDUCTION_TASK;
+ else if (gfc_match ("default") == MATCH_YES)
+ list_idx = OMP_LIST_REDUCTION;
+ if (list_idx != 0 && gfc_match (", ") != MATCH_YES)
+ {
+ gfc_error ("Comma expected at %C");
+ gfc_current_locus = old_loc;
+ return MATCH_NO;
+ }
+ if (list_idx == 0)
+ list_idx = OMP_LIST_REDUCTION;
+ }
+ else if (pc == 'i')
+ list_idx = OMP_LIST_IN_REDUCTION;
+ else if (pc == 't')
+ list_idx = OMP_LIST_TASK_REDUCTION;
+ else
+ list_idx = OMP_LIST_REDUCTION;
+
+ gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
+ char buffer[GFC_MAX_SYMBOL_LEN + 3];
+ if (gfc_match_char ('+') == MATCH_YES)
+ rop = OMP_REDUCTION_PLUS;
+ else if (gfc_match_char ('*') == MATCH_YES)
+ rop = OMP_REDUCTION_TIMES;
+ else if (gfc_match_char ('-') == MATCH_YES)
+ rop = OMP_REDUCTION_MINUS;
+ else if (gfc_match (".and.") == MATCH_YES)
+ rop = OMP_REDUCTION_AND;
+ else if (gfc_match (".or.") == MATCH_YES)
+ rop = OMP_REDUCTION_OR;
+ else if (gfc_match (".eqv.") == MATCH_YES)
+ rop = OMP_REDUCTION_EQV;
+ else if (gfc_match (".neqv.") == MATCH_YES)
+ rop = OMP_REDUCTION_NEQV;
+ if (rop != OMP_REDUCTION_NONE)
+ snprintf (buffer, sizeof buffer, "operator %s",
+ gfc_op2string ((gfc_intrinsic_op) rop));
+ else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
+ {
+ buffer[0] = '.';
+ strcat (buffer, ".");
+ }
+ else if (gfc_match_name (buffer) == MATCH_YES)
+ {
+ gfc_symbol *sym;
+ const char *n = buffer;
+
+ gfc_find_symbol (buffer, NULL, 1, &sym);
+ if (sym != NULL)
+ {
+ if (sym->attr.intrinsic)
+ n = sym->name;
+ else if ((sym->attr.flavor != FL_UNKNOWN
+ && sym->attr.flavor != FL_PROCEDURE)
+ || sym->attr.external
+ || sym->attr.generic
+ || sym->attr.entry
+ || sym->attr.result
+ || sym->attr.dummy
+ || sym->attr.subroutine
+ || sym->attr.pointer
+ || sym->attr.target
+ || sym->attr.cray_pointer
+ || sym->attr.cray_pointee
+ || (sym->attr.proc != PROC_UNKNOWN
+ && sym->attr.proc != PROC_INTRINSIC)
+ || sym->attr.if_source != IFSRC_UNKNOWN
+ || sym == sym->ns->proc_name)
+ {
+ sym = NULL;
+ n = NULL;
+ }
+ else
+ n = sym->name;
+ }
+ if (n == NULL)
+ rop = OMP_REDUCTION_NONE;
+ else if (strcmp (n, "max") == 0)
+ rop = OMP_REDUCTION_MAX;
+ else if (strcmp (n, "min") == 0)
+ rop = OMP_REDUCTION_MIN;
+ else if (strcmp (n, "iand") == 0)
+ rop = OMP_REDUCTION_IAND;
+ else if (strcmp (n, "ior") == 0)
+ rop = OMP_REDUCTION_IOR;
+ else if (strcmp (n, "ieor") == 0)
+ rop = OMP_REDUCTION_IEOR;
+ if (rop != OMP_REDUCTION_NONE
+ && sym != NULL
+ && ! sym->attr.intrinsic
+ && ! sym->attr.use_assoc
+ && ((sym->attr.flavor == FL_UNKNOWN
+ && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
+ sym->name, NULL))
+ || !gfc_add_intrinsic (&sym->attr, NULL)))
+ rop = OMP_REDUCTION_NONE;
+ }
+ else
+ buffer[0] = '\0';
+ gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
+ : NULL);
+ gfc_omp_namelist **head = NULL;
+ if (rop == OMP_REDUCTION_NONE && udr)
+ rop = OMP_REDUCTION_USER;
+
+ if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
+ &head, openacc, allow_derived) != MATCH_YES)
+ {
+ gfc_current_locus = old_loc;
+ return MATCH_NO;
+ }
+ gfc_omp_namelist *n;
+ if (rop == OMP_REDUCTION_NONE)
+ {
+ n = *head;
+ *head = NULL;
+ gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
+ buffer, &old_loc);
+ gfc_free_omp_namelist (n);
+ }
+ else
+ for (n = *head; n; n = n->next)
+ {
+ n->u.reduction_op = rop;
+ if (udr)
+ {
+ n->udr = gfc_get_omp_namelist_udr ();
+ n->udr->udr = udr;
+ }
+ }
+ return MATCH_YES;
+}
+
/* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
clauses that are allowed for a particular directive. */
@@ -1017,6 +1179,22 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
n->expr = alignment;
continue;
}
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("acq_rel") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_ACQ_REL;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("acquire") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_ACQUIRE;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_ASYNC)
&& !c->async
&& gfc_match ("async") == MATCH_YES)
@@ -1055,6 +1233,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
continue;
break;
case 'c':
+ if ((mask & OMP_CLAUSE_CAPTURE)
+ && !c->capture
+ && gfc_match ("capture") == MATCH_YES)
+ {
+ c->capture = true;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_COLLAPSE)
&& !c->collapse)
{
@@ -1352,6 +1538,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_IN_REDUCTION)
+ && gfc_match_omp_clause_reduction (pc, c, openacc,
+ allow_derived) == MATCH_YES)
+ continue;
if ((mask & OMP_CLAUSE_INBRANCH)
&& !c->inbranch
&& !c->notinbranch
@@ -1681,125 +1871,49 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
}
break;
case 'r':
+ if ((mask & OMP_CLAUSE_ATOMIC)
+ && c->atomic_op == GFC_OMP_ATOMIC_UNSET
+ && gfc_match ("read") == MATCH_YES)
+ {
+ c->atomic_op = GFC_OMP_ATOMIC_READ;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_REDUCTION)
- && gfc_match ("reduction ( ") == MATCH_YES)
+ && gfc_match_omp_clause_reduction (pc, c, openacc,
+ allow_derived) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("relaxed") == MATCH_YES)
{
- gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
- char buffer[GFC_MAX_SYMBOL_LEN + 3];
- if (gfc_match_char ('+') == MATCH_YES)
- rop = OMP_REDUCTION_PLUS;
- else if (gfc_match_char ('*') == MATCH_YES)
- rop = OMP_REDUCTION_TIMES;
- else if (gfc_match_char ('-') == MATCH_YES)
- rop = OMP_REDUCTION_MINUS;
- else if (gfc_match (".and.") == MATCH_YES)
- rop = OMP_REDUCTION_AND;
- else if (gfc_match (".or.") == MATCH_YES)
- rop = OMP_REDUCTION_OR;
- else if (gfc_match (".eqv.") == MATCH_YES)
- rop = OMP_REDUCTION_EQV;
- else if (gfc_match (".neqv.") == MATCH_YES)
- rop = OMP_REDUCTION_NEQV;
- if (rop != OMP_REDUCTION_NONE)
- snprintf (buffer, sizeof buffer, "operator %s",
- gfc_op2string ((gfc_intrinsic_op) rop));
- else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
- {
- buffer[0] = '.';
- strcat (buffer, ".");
- }
- else if (gfc_match_name (buffer) == MATCH_YES)
- {
- gfc_symbol *sym;
- const char *n = buffer;
-
- gfc_find_symbol (buffer, NULL, 1, &sym);
- if (sym != NULL)
- {
- if (sym->attr.intrinsic)
- n = sym->name;
- else if ((sym->attr.flavor != FL_UNKNOWN
- && sym->attr.flavor != FL_PROCEDURE)
- || sym->attr.external
- || sym->attr.generic
- || sym->attr.entry
- || sym->attr.result
- || sym->attr.dummy
- || sym->attr.subroutine
- || sym->attr.pointer
- || sym->attr.target
- || sym->attr.cray_pointer
- || sym->attr.cray_pointee
- || (sym->attr.proc != PROC_UNKNOWN
- && sym->attr.proc != PROC_INTRINSIC)
- || sym->attr.if_source != IFSRC_UNKNOWN
- || sym == sym->ns->proc_name)
- {
- sym = NULL;
- n = NULL;
- }
- else
- n = sym->name;
- }
- if (n == NULL)
- rop = OMP_REDUCTION_NONE;
- else if (strcmp (n, "max") == 0)
- rop = OMP_REDUCTION_MAX;
- else if (strcmp (n, "min") == 0)
- rop = OMP_REDUCTION_MIN;
- else if (strcmp (n, "iand") == 0)
- rop = OMP_REDUCTION_IAND;
- else if (strcmp (n, "ior") == 0)
- rop = OMP_REDUCTION_IOR;
- else if (strcmp (n, "ieor") == 0)
- rop = OMP_REDUCTION_IEOR;
- if (rop != OMP_REDUCTION_NONE
- && sym != NULL
- && ! sym->attr.intrinsic
- && ! sym->attr.use_assoc
- && ((sym->attr.flavor == FL_UNKNOWN
- && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
- sym->name, NULL))
- || !gfc_add_intrinsic (&sym->attr, NULL)))
- rop = OMP_REDUCTION_NONE;
- }
- else
- buffer[0] = '\0';
- gfc_omp_udr *udr
- = (buffer[0]
- ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL) : NULL);
- gfc_omp_namelist **head = NULL;
- if (rop == OMP_REDUCTION_NONE && udr)
- rop = OMP_REDUCTION_USER;
-
- if (gfc_match_omp_variable_list (" :",
- &c->lists[OMP_LIST_REDUCTION],
- false, NULL, &head, openacc,
- allow_derived) == MATCH_YES)
- {
- gfc_omp_namelist *n;
- if (rop == OMP_REDUCTION_NONE)
- {
- n = *head;
- *head = NULL;
- gfc_error_now ("!$OMP DECLARE REDUCTION %s not found "
- "at %L", buffer, &old_loc);
- gfc_free_omp_namelist (n);
- }
- else
- for (n = *head; n; n = n->next)
- {
- n->u.reduction_op = rop;
- if (udr)
- {
- n->udr = gfc_get_omp_namelist_udr ();
- n->udr->udr = udr;
- }
- }
- continue;
- }
- else
- gfc_current_locus = old_loc;
+ c->memorder = OMP_MEMORDER_RELAXED;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("release") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_RELEASE;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("relaxed") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_RELAXED;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("release") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_RELEASE;
+ needs_space = true;
+ continue;
}
break;
case 's':
@@ -1885,6 +1999,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("seq_cst") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_SHARED)
&& gfc_match_omp_variable_list ("shared (",
&c->lists[OMP_LIST_SHARED],
@@ -1903,6 +2025,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
}
break;
case 't':
+ if ((mask & OMP_CLAUSE_TASK_REDUCTION)
+ && gfc_match_omp_clause_reduction (pc, c, openacc,
+ allow_derived) == MATCH_YES)
+ continue;
if ((mask & OMP_CLAUSE_THREAD_LIMIT)
&& c->thread_limit == NULL
&& gfc_match ("thread_limit ( %e )",
@@ -1945,6 +2071,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
c->untied = needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_ATOMIC)
+ && c->atomic_op == GFC_OMP_ATOMIC_UNSET
+ && gfc_match ("update") == MATCH_YES)
+ {
+ c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_USE_DEVICE)
&& gfc_match_omp_variable_list ("use_device (",
&c->lists[OMP_LIST_USE_DEVICE],
@@ -2026,6 +2160,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_ATOMIC)
+ && c->atomic_op == GFC_OMP_ATOMIC_UNSET
+ && gfc_match ("write") == MATCH_YES)
+ {
+ c->atomic_op = GFC_OMP_ATOMIC_WRITE;
+ needs_space = true;
+ continue;
+ }
break;
}
break;
@@ -2621,18 +2763,19 @@ cleanup:
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
| OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
- | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY)
+ | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION)
#define OMP_TASKLOOP_CLAUSES \
(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
| OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
| OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
- | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP)
+ | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \
+ | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION)
#define OMP_TARGET_CLAUSES \
(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
| OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
| OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
- | OMP_CLAUSE_IS_DEVICE_PTR)
+ | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION)
#define OMP_TARGET_DATA_CLAUSES \
(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
| OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
@@ -2658,6 +2801,9 @@ cleanup:
(omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
#define OMP_DECLARE_TARGET_CLAUSES \
(omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE)
+#define OMP_ATOMIC_CLAUSES \
+ (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
+ | OMP_CLAUSE_MEMORDER)
static match
@@ -2768,7 +2914,7 @@ gfc_match_omp_flush (void)
gfc_omp_namelist *list = NULL;
gfc_omp_clauses *c = NULL;
gfc_gobble_whitespace ();
- enum gfc_omp_memorder mo = OMP_MEMORDER_LAST;
+ enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
{
if (gfc_match ("acq_rel") == MATCH_YES)
@@ -2786,7 +2932,7 @@ gfc_match_omp_flush (void)
c->memorder = mo;
}
gfc_match_omp_variable_list (" (", &list, true);
- if (list && mo != OMP_MEMORDER_LAST)
+ if (list && mo != OMP_MEMORDER_UNSET)
{
gfc_error ("List specified together with memory order clause in FLUSH "
"directive at %C");
@@ -3737,6 +3883,42 @@ error:
match
+gfc_match_omp_scan (void)
+{
+ bool incl;
+ gfc_omp_clauses *c = gfc_get_omp_clauses ();
+ gfc_gobble_whitespace ();
+ if ((incl = (gfc_match ("inclusive") == MATCH_YES))
+ || gfc_match ("exclusive") == MATCH_YES)
+ {
+ if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
+ : OMP_LIST_SCAN_EX],
+ false) != MATCH_YES)
+ {
+ gfc_free_omp_clauses (c);
+ return MATCH_ERROR;
+ }
+ }
+ else
+ {
+ gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
+ gfc_free_omp_clauses (c);
+ return MATCH_ERROR;
+ }
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after !$OMP SCAN at %C");
+ gfc_free_omp_clauses (c);
+ return MATCH_ERROR;
+ }
+
+ new_st.op = EXEC_OMP_SCAN;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_sections (void)
{
return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
@@ -4014,49 +4196,29 @@ gfc_match_omp_ordered_depend (void)
}
-static match
-gfc_match_omp_oacc_atomic (bool omp_p)
+/* omp atomic [clause-list]
+ - atomic-clause: read | write | update
+ - capture
+ - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
+ - hint(hint-expr)
+*/
+
+match
+gfc_match_omp_atomic (void)
{
- gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
- int seq_cst = 0;
- if (gfc_match ("% seq_cst") == MATCH_YES)
- seq_cst = 1;
- locus old_loc = gfc_current_locus;
- if (seq_cst && gfc_match_char (',') == MATCH_YES)
- seq_cst = 2;
- if (seq_cst == 2
- || gfc_match_space () == MATCH_YES)
- {
- gfc_gobble_whitespace ();
- if (gfc_match ("update") == MATCH_YES)
- op = GFC_OMP_ATOMIC_UPDATE;
- else if (gfc_match ("read") == MATCH_YES)
- op = GFC_OMP_ATOMIC_READ;
- else if (gfc_match ("write") == MATCH_YES)
- op = GFC_OMP_ATOMIC_WRITE;
- else if (gfc_match ("capture") == MATCH_YES)
- op = GFC_OMP_ATOMIC_CAPTURE;
- else
- {
- if (seq_cst == 2)
- gfc_current_locus = old_loc;
- goto finish;
- }
- if (!seq_cst
- && (gfc_match (", seq_cst") == MATCH_YES
- || gfc_match ("% seq_cst") == MATCH_YES))
- seq_cst = 1;
- }
- finish:
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
- return MATCH_ERROR;
- }
- new_st.op = (omp_p ? EXEC_OMP_ATOMIC : EXEC_OACC_ATOMIC);
- if (seq_cst)
- op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
- else if (omp_p)
+ gfc_omp_clauses *c;
+ locus loc = gfc_current_locus;
+
+ if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
+ return MATCH_ERROR;
+
+ if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UNSET)
+ gfc_error ("OMP ATOMIC at %L with multiple atomic clauses", &loc);
+
+ if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
+ c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+
+ if (c->memorder == OMP_MEMORDER_UNSET)
{
gfc_namespace *prog_unit = gfc_current_ns;
while (prog_unit->parent)
@@ -4065,32 +4227,93 @@ gfc_match_omp_oacc_atomic (bool omp_p)
{
case 0:
case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
+ c->memorder = OMP_MEMORDER_RELAXED;
break;
case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
- op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
break;
case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
- op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_ACQ_REL);
+ if (c->capture)
+ c->memorder = OMP_MEMORDER_ACQ_REL;
+ else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
+ c->memorder = OMP_MEMORDER_ACQUIRE;
+ else
+ c->memorder = OMP_MEMORDER_RELEASE;
break;
default:
gcc_unreachable ();
}
}
- new_st.ext.omp_atomic = op;
+ else
+ switch (c->atomic_op)
+ {
+ case GFC_OMP_ATOMIC_READ:
+ if (c->memorder == OMP_MEMORDER_ACQ_REL
+ || c->memorder == OMP_MEMORDER_RELEASE)
+ {
+ gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
+ "ACQ_REL or RELEASE clauses", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ break;
+ case GFC_OMP_ATOMIC_WRITE:
+ if (c->memorder == OMP_MEMORDER_ACQ_REL
+ || c->memorder == OMP_MEMORDER_ACQUIRE)
+ {
+ gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
+ "ACQ_REL or ACQUIRE clauses", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ break;
+ case GFC_OMP_ATOMIC_UPDATE:
+ if ((c->memorder == OMP_MEMORDER_ACQ_REL
+ || c->memorder == OMP_MEMORDER_ACQUIRE)
+ && !c->capture)
+ {
+ gfc_error ("!$OMP ATOMIC UPDATE at %L incompatible with "
+ "ACQ_REL or ACQUIRE clauses", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ break;
+ default:
+ break;
+ }
+ gfc_error_check ();
+ new_st.ext.omp_clauses = c;
+ new_st.op = EXEC_OMP_ATOMIC;
return MATCH_YES;
}
+
+/* acc atomic [ read | write | update | capture] */
+
match
gfc_match_oacc_atomic (void)
{
- return gfc_match_omp_oacc_atomic (false);
+ gfc_omp_clauses *c = gfc_get_omp_clauses ();
+ c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+ c->memorder = OMP_MEMORDER_RELAXED;
+ gfc_gobble_whitespace ();
+ if (gfc_match ("update") == MATCH_YES)
+ ;
+ else if (gfc_match ("read") == MATCH_YES)
+ c->atomic_op = GFC_OMP_ATOMIC_READ;
+ else if (gfc_match ("write") == MATCH_YES)
+ c->atomic_op = GFC_OMP_ATOMIC_WRITE;
+ else if (gfc_match ("capture") == MATCH_YES)
+ c->capture = true;
+ gfc_gobble_whitespace ();
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
+ gfc_free_omp_clauses (c);
+ return MATCH_ERROR;
+ }
+ new_st.ext.omp_clauses = c;
+ new_st.op = EXEC_OACC_ATOMIC;
+ return MATCH_YES;
}
-match
-gfc_match_omp_atomic (void)
-{
- return gfc_match_omp_oacc_atomic (true);
-}
match
gfc_match_omp_barrier (void)
@@ -4109,13 +4332,7 @@ gfc_match_omp_barrier (void)
match
gfc_match_omp_taskgroup (void)
{
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after $OMP TASKGROUP statement at %C");
- return MATCH_ERROR;
- }
- new_st.op = EXEC_OMP_TASKGROUP;
- return MATCH_YES;
+ return match_omp (EXEC_OMP_TASKGROUP, OMP_CLAUSE_TASK_REDUCTION);
}
@@ -4441,7 +4658,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
static const char *clause_names[]
= { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
"COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "MAP",
- "TO", "FROM", "REDUCTION", "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
+ "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
+ "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
+ "IN_REDUCTION", "TASK_REDUCTION",
+ "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
"CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
"NONTEMPORAL" };
STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
@@ -4608,21 +4828,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
if (omp_clauses->sched_kind != OMP_SCHED_NONE
&& omp_clauses->sched_nonmonotonic)
{
- if (omp_clauses->sched_kind != OMP_SCHED_DYNAMIC
- && omp_clauses->sched_kind != OMP_SCHED_GUIDED)
- {
- const char *p;
- switch (omp_clauses->sched_kind)
- {
- case OMP_SCHED_STATIC: p = "STATIC"; break;
- case OMP_SCHED_RUNTIME: p = "RUNTIME"; break;
- case OMP_SCHED_AUTO: p = "AUTO"; break;
- default: gcc_unreachable ();
- }
- gfc_error ("NONMONOTONIC modifier specified for %s schedule kind "
- "at %L", p, &code->loc);
- }
- else if (omp_clauses->sched_monotonic)
+ if (omp_clauses->sched_monotonic)
gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
"specified at %L", &code->loc);
else if (omp_clauses->ordered)
@@ -4690,6 +4896,15 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
gfc_error ("Object %qs is not a variable at %L", n->sym->name,
&n->where);
}
+ if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]
+ && code->op != EXEC_OMP_DO
+ && code->op != EXEC_OMP_SIMD
+ && code->op != EXEC_OMP_DO_SIMD
+ && code->op != EXEC_OMP_PARALLEL_DO
+ && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
+ gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, SIMD, "
+ "DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
+ &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where);
for (list = 0; list < OMP_LIST_NUM; list++)
if (list != OMP_LIST_FIRSTPRIVATE
@@ -4699,7 +4914,11 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
&& (list != OMP_LIST_MAP || openacc)
&& list != OMP_LIST_FROM
&& list != OMP_LIST_TO
- && (list != OMP_LIST_REDUCTION || !openacc))
+ && (list != OMP_LIST_REDUCTION || !openacc)
+ && list != OMP_LIST_REDUCTION_INSCAN
+ && list != OMP_LIST_REDUCTION_TASK
+ && list != OMP_LIST_IN_REDUCTION
+ && list != OMP_LIST_TASK_REDUCTION)
for (n = omp_clauses->lists[list]; n; n = n->next)
{
bool component_ref_p = false;
@@ -4803,6 +5022,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
n->sym->mark = 1;
}
+ bool has_inscan = false, has_notinscan = false;
for (list = 0; list < OMP_LIST_NUM; list++)
if ((n = omp_clauses->lists[list]) != NULL)
{
@@ -5105,6 +5325,22 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
for (; n != NULL; n = n->next)
{
bool bad = false;
+ bool is_reduction = (list == OMP_LIST_REDUCTION
+ || list == OMP_LIST_REDUCTION_INSCAN
+ || list == OMP_LIST_REDUCTION_TASK
+ || list == OMP_LIST_IN_REDUCTION
+ || list == OMP_LIST_TASK_REDUCTION);
+ if (list == OMP_LIST_REDUCTION_INSCAN)
+ has_inscan = true;
+ else if (is_reduction)
+ has_notinscan = true;
+ if (has_inscan && has_notinscan && is_reduction)
+ {
+ gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
+ "clauses on the same construct %L",
+ &n->where);
+ break;
+ }
if (n->sym->attr.threadprivate)
gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
n->sym->name, name, &n->where);
@@ -5114,15 +5350,15 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
if (n->sym->attr.associate_var)
gfc_error ("ASSOCIATE name %qs in %s clause at %L",
n->sym->name, name, &n->where);
- if (list != OMP_LIST_PRIVATE)
+ if (list != OMP_LIST_PRIVATE && is_reduction)
{
- if (n->sym->attr.proc_pointer && list == OMP_LIST_REDUCTION)
+ if (n->sym->attr.proc_pointer)
gfc_error ("Procedure pointer %qs in %s clause at %L",
n->sym->name, name, &n->where);
- if (n->sym->attr.pointer && list == OMP_LIST_REDUCTION)
+ if (n->sym->attr.pointer)
gfc_error ("POINTER object %qs in %s clause at %L",
n->sym->name, name, &n->where);
- if (n->sym->attr.cray_pointer && list == OMP_LIST_REDUCTION)
+ if (n->sym->attr.cray_pointer)
gfc_error ("Cray pointer %qs in %s clause at %L",
n->sym->name, name, &n->where);
}
@@ -5134,7 +5370,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
else if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
gfc_error ("Assumed size array %qs in %s clause at %L",
n->sym->name, name, &n->where);
- if (n->sym->attr.in_namelist && list != OMP_LIST_REDUCTION)
+ if (n->sym->attr.in_namelist && !is_reduction)
gfc_error ("Variable %qs in %s clause is used in "
"NAMELIST statement at %L",
n->sym->name, name, &n->where);
@@ -5154,7 +5390,21 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
switch (list)
{
+ case OMP_LIST_REDUCTION_INSCAN:
+ case OMP_LIST_REDUCTION_TASK:
+ if (code && (code->op == EXEC_OMP_TASKLOOP
+ || code->op == EXEC_OMP_TEAMS
+ || code->op == EXEC_OMP_TEAMS_DISTRIBUTE))
+ {
+ gfc_error ("Only DEFAULT permitted as reduction-"
+ "modifier in REDUCTION clause at %L",
+ &n->where);
+ break;
+ }
+ gcc_fallthrough ();
case OMP_LIST_REDUCTION:
+ case OMP_LIST_IN_REDUCTION:
+ case OMP_LIST_TASK_REDUCTION:
switch (n->u.reduction_op)
{
case OMP_REDUCTION_PLUS:
@@ -5514,11 +5764,12 @@ is_conversion (gfc_expr *expr, bool widening)
static void
resolve_omp_atomic (gfc_code *code)
{
- gfc_code *atomic_code = code;
+ gfc_code *atomic_code = code->block;
gfc_symbol *var;
gfc_expr *expr2, *expr2_tmp;
gfc_omp_atomic_op aop
- = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
+ = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
+ & GFC_OMP_ATOMIC_MASK);
code = code->block->next;
/* resolve_blocks asserts this is initially EXEC_ASSIGN.
@@ -5531,7 +5782,7 @@ resolve_omp_atomic (gfc_code *code)
gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
return;
}
- if (aop != GFC_OMP_ATOMIC_CAPTURE)
+ if (!atomic_code->ext.omp_clauses->capture)
{
if (code->next != NULL)
goto unexpected;
@@ -5591,7 +5842,11 @@ resolve_omp_atomic (gfc_code *code)
"must be scalar and cannot reference var at %L",
&expr2->where);
return;
- case GFC_OMP_ATOMIC_CAPTURE:
+ default:
+ break;
+ }
+ if (atomic_code->ext.omp_clauses->capture)
+ {
expr2_tmp = expr2;
if (expr2 == code->expr2)
{
@@ -5640,9 +5895,6 @@ resolve_omp_atomic (gfc_code *code)
if (expr2 == NULL)
expr2 = code->expr2;
}
- break;
- default:
- break;
}
if (gfc_expr_attr (code->expr1).allocatable)
@@ -5652,12 +5904,12 @@ resolve_omp_atomic (gfc_code *code)
return;
}
- if (aop == GFC_OMP_ATOMIC_CAPTURE
+ if (atomic_code->ext.omp_clauses->capture
&& code->next == NULL
&& code->expr2->rank == 0
&& !expr_references_sym (code->expr2, var, NULL))
- atomic_code->ext.omp_atomic
- = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic
+ atomic_code->ext.omp_clauses->atomic_op
+ = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
| GFC_OMP_ATOMIC_SWAP);
else if (expr2->expr_type == EXPR_OP)
{
@@ -5867,7 +6119,7 @@ resolve_omp_atomic (gfc_code *code)
gfc_error ("!$OMP ATOMIC assignment must have an operator or "
"intrinsic on right hand side at %L", &expr2->where);
- if (aop == GFC_OMP_ATOMIC_CAPTURE && code->next)
+ if (atomic_code->ext.omp_clauses->capture && code->next)
{
code = code->next;
if (code->expr1->expr_type != EXPR_VARIABLE
@@ -5951,6 +6203,28 @@ gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
}
if (i < omp_current_do_collapse || omp_current_do_collapse <= 0)
omp_current_do_collapse = 1;
+ if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
+ {
+ locus *loc
+ = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
+ if (code->ext.omp_clauses->ordered)
+ gfc_error ("ORDERED clause specified together with %<inscan%> "
+ "REDUCTION clause at %L", loc);
+ if (code->ext.omp_clauses->sched_kind != OMP_SCHED_NONE)
+ gfc_error ("SCHEDULE clause specified together with %<inscan%> "
+ "REDUCTION clause at %L", loc);
+ if (!c->block
+ || !c->block->next
+ || !c->block->next->next
+ || c->block->next->next->op != EXEC_OMP_SCAN
+ || !c->block->next->next->next
+ || c->block->next->next->next->next)
+ gfc_error ("With INSCAN at %L, expected loop body with !$OMP SCAN "
+ "between two structured-block-sequences", loc);
+ else
+ /* Mark as checked; flag will be unset later. */
+ c->block->next->next->ext.omp_clauses->if_present = true;
+ }
}
gfc_resolve_blocks (code->block, ns);
omp_current_do_collapse = 0;
@@ -5981,6 +6255,10 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
case OMP_LIST_FIRSTPRIVATE:
case OMP_LIST_LASTPRIVATE:
case OMP_LIST_REDUCTION:
+ case OMP_LIST_REDUCTION_INSCAN:
+ case OMP_LIST_REDUCTION_TASK:
+ case OMP_LIST_IN_REDUCTION:
+ case OMP_LIST_TASK_REDUCTION:
case OMP_LIST_LINEAR:
for (n = omp_clauses->lists[list]; n; n = n->next)
ctx.sharing_clauses->add (n->sym);
@@ -6282,11 +6560,6 @@ resolve_omp_do (gfc_code *code)
}
}
-static bool
-oacc_is_parallel (gfc_code *code)
-{
- return code->op == EXEC_OACC_PARALLEL || code->op == EXEC_OACC_PARALLEL_LOOP;
-}
static gfc_statement
omp_code_to_statement (gfc_code *code)
@@ -6335,6 +6608,8 @@ omp_code_to_statement (gfc_code *code)
return ST_OMP_DISTRIBUTE_SIMD;
case EXEC_OMP_DO_SIMD:
return ST_OMP_DO_SIMD;
+ case EXEC_OMP_SCAN:
+ return ST_OMP_SCAN;
case EXEC_OMP_SIMD:
return ST_OMP_SIMD;
case EXEC_OMP_TARGET:
@@ -6546,26 +6821,6 @@ resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
static void
-resolve_oacc_params_in_parallel (gfc_code *code, const char *clause,
- const char *arg)
-{
- fortran_omp_context *c;
-
- if (oacc_is_parallel (code))
- gfc_error ("!$ACC LOOP %s in PARALLEL region doesn't allow "
- "%s arguments at %L", clause, arg, &code->loc);
- for (c = omp_current_ctx; c; c = c->previous)
- {
- if (oacc_is_loop (c->code))
- break;
- if (oacc_is_parallel (c->code))
- gfc_error ("!$ACC LOOP %s in PARALLEL region doesn't allow "
- "%s arguments at %L", clause, arg, &code->loc);
- }
-}
-
-
-static void
resolve_oacc_loop_blocks (gfc_code *code)
{
if (!oacc_is_loop (code))
@@ -6576,18 +6831,6 @@ resolve_oacc_loop_blocks (gfc_code *code)
gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
"vectors at the same time at %L", &code->loc);
- if (code->ext.omp_clauses->gang
- && code->ext.omp_clauses->gang_num_expr)
- resolve_oacc_params_in_parallel (code, "GANG", "num");
-
- if (code->ext.omp_clauses->worker
- && code->ext.omp_clauses->worker_expr)
- resolve_oacc_params_in_parallel (code, "WORKER", "num");
-
- if (code->ext.omp_clauses->vector
- && code->ext.omp_clauses->vector_expr)
- resolve_oacc_params_in_parallel (code, "VECTOR", "length");
-
if (code->ext.omp_clauses->tile_list)
{
gfc_expr_list *el;
@@ -6805,7 +7048,7 @@ gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
of each directive. */
void
-gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
+gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
{
resolve_omp_directive_inside_oacc_region (code);
@@ -6866,6 +7109,7 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
"FROM clause", &code->loc);
break;
case EXEC_OMP_ATOMIC:
+ resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
resolve_omp_atomic (code);
break;
case EXEC_OMP_CRITICAL:
@@ -6878,6 +7122,14 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
"except when omp_sync_hint_none is used", &code->loc);
break;
+ case EXEC_OMP_SCAN:
+ /* Flag is only used to checking, hence, it is unset afterwards. */
+ if (!code->ext.omp_clauses->if_present)
+ gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
+ "%<inscan%> REDUCTION clause", &code->loc);
+ code->ext.omp_clauses->if_present = false;
+ resolve_omp_clauses (code, code->ext.omp_clauses, ns);
+ break;
default:
break;
}
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 9e32ae6..f2ee40e 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -412,22 +412,24 @@ gfc_post_options (const char **pfilename)
else if (!flag_automatic && flag_recursive)
gfc_warning_now (OPT_Woverwrite_recursive, "Flag %<-fno-automatic%> "
"overwrites %<-frecursive%>");
- else if (!flag_automatic && flag_openmp)
- gfc_warning_now (0, "Flag %<-fno-automatic%> overwrites %<-frecursive%> implied by "
- "%<-fopenmp%>");
+ else if (!flag_automatic && (flag_openmp || flag_openacc))
+ gfc_warning_now (0, "Flag %<-fno-automatic%> overwrites %<-frecursive%> "
+ "implied by %qs", flag_openmp ? "-fopenmp" : "-fopenacc");
else if (flag_max_stack_var_size != -2 && flag_recursive)
gfc_warning_now (0, "Flag %<-frecursive%> overwrites %<-fmax-stack-var-size=%d%>",
flag_max_stack_var_size);
- else if (flag_max_stack_var_size != -2 && flag_openmp)
- gfc_warning_now (0, "Flag %<-fmax-stack-var-size=%d%> overwrites %<-frecursive%> "
- "implied by %<-fopenmp%>", flag_max_stack_var_size);
+ else if (flag_max_stack_var_size != -2 && (flag_openmp || flag_openacc))
+ gfc_warning_now (0, "Flag %<-fmax-stack-var-size=%d%> overwrites "
+ "%<-frecursive%> implied by %qs", flag_max_stack_var_size,
+ flag_openmp ? "-fopenmp" : "-fopenacc");
/* Implement -frecursive as -fmax-stack-var-size=-1. */
if (flag_recursive)
flag_max_stack_var_size = -1;
/* Implied -frecursive; implemented as -fmax-stack-var-size=-1. */
- if (flag_max_stack_var_size == -2 && flag_openmp && flag_automatic)
+ if (flag_max_stack_var_size == -2 && flag_automatic
+ && (flag_openmp || flag_openacc))
{
flag_recursive = 1;
flag_max_stack_var_size = -1;
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 6669621..fe0fffd 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -999,6 +999,7 @@ decode_omp_directive (void)
matcho ("requires", gfc_match_omp_requires, ST_OMP_REQUIRES);
break;
case 's':
+ matcho ("scan", gfc_match_omp_scan, ST_OMP_SCAN);
matcho ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS);
matcho ("section", gfc_match_omp_eos_error, ST_OMP_SECTION);
matcho ("single", gfc_match_omp_single, ST_OMP_SINGLE);
@@ -1590,7 +1591,7 @@ next_statement (void)
case ST_OMP_CANCEL: case ST_OMP_CANCELLATION_POINT: \
case ST_OMP_TARGET_UPDATE: case ST_OMP_TARGET_ENTER_DATA: \
case ST_OMP_TARGET_EXIT_DATA: case ST_OMP_ORDERED_DEPEND: \
- case ST_ERROR_STOP: case ST_SYNC_ALL: \
+ case ST_ERROR_STOP: case ST_OMP_SCAN: case ST_SYNC_ALL: \
case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK: \
case ST_FORM_TEAM: case ST_CHANGE_TEAM: \
case ST_END_TEAM: case ST_SYNC_TEAM: \
@@ -1633,14 +1634,15 @@ next_statement (void)
#define case_decl case ST_ATTR_DECL: case ST_COMMON: case ST_DATA_DECL: \
case ST_EQUIVALENCE: case ST_NAMELIST: case ST_STATEMENT_FUNCTION: \
- case ST_TYPE: case ST_INTERFACE: case ST_PROCEDURE: case ST_OACC_ROUTINE: \
- case ST_OACC_DECLARE
+ case ST_TYPE: case ST_INTERFACE: case ST_PROCEDURE
-/* OpenMP declaration statements. */
+/* OpenMP and OpenACC declaration statements, which may appear anywhere in
+ the specification part. */
#define case_omp_decl case ST_OMP_THREADPRIVATE: case ST_OMP_DECLARE_SIMD: \
case ST_OMP_DECLARE_TARGET: case ST_OMP_DECLARE_REDUCTION: \
- case ST_OMP_REQUIRES
+ case ST_OMP_REQUIRES: case ST_OACC_ROUTINE: case ST_OACC_DECLARE
+
/* Block end statements. Errors associated with interchanging these
are detected in gfc_match_end(). */
@@ -2446,6 +2448,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_REQUIRES:
p = "!$OMP REQUIRES";
break;
+ case ST_OMP_SCAN:
+ p = "!$OMP SCAN";
+ break;
case ST_OMP_SECTIONS:
p = "!$OMP SECTIONS";
break;
@@ -2813,7 +2818,7 @@ verify_st_order (st_state *p, gfc_statement st, bool silent)
break;
case_omp_decl:
- /* The OpenMP directives have to be somewhere in the specification
+ /* The OpenMP/OpenACC directives have to be somewhere in the specification
part, but there are no further requirements on their ordering.
Thus don't adjust p->state, just ignore them. */
if (p->state >= ORDER_EXEC)
@@ -5062,9 +5067,9 @@ parse_omp_oacc_atomic (bool omp_p)
np = new_level (cp);
np->op = cp->op;
np->block = NULL;
- np->ext.omp_atomic = cp->ext.omp_atomic;
- count = 1 + ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- == GFC_OMP_ATOMIC_CAPTURE);
+ np->ext.omp_clauses = cp->ext.omp_clauses;
+ cp->ext.omp_clauses = NULL;
+ count = 1 + np->ext.omp_clauses->capture;
while (count)
{
@@ -5090,8 +5095,7 @@ parse_omp_oacc_atomic (bool omp_p)
gfc_warning_check ();
st = next_statement ();
}
- else if ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- == GFC_OMP_ATOMIC_CAPTURE)
+ else if (np->ext.omp_clauses->capture)
gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
return st;
}
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index a58a259..93d7473 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -3003,26 +3003,36 @@ build_actual_constructor (gfc_structure_ctor_component **comp_head,
continue;
}
- /* If it was not found, try the default initializer if there's any;
+ /* If it was not found, apply NULL expression to set the component as
+ unallocated. Then try the default initializer if there's any;
otherwise, it's an error unless this is a deferred parameter. */
if (!comp_iter)
{
- if (comp->initializer)
- {
- if (!gfc_notify_std (GFC_STD_F2003, "Structure constructor "
- "with missing optional arguments at %C"))
- return false;
- value = gfc_copy_expr (comp->initializer);
- }
- else if (comp->attr.allocatable
- || (comp->ts.type == BT_CLASS
- && CLASS_DATA (comp)->attr.allocatable))
+ /* F2018 7.5.10: If an allocatable component has no corresponding
+ component-data-source, then that component has an allocation
+ status of unallocated.... */
+ if (comp->attr.allocatable
+ || (comp->ts.type == BT_CLASS
+ && CLASS_DATA (comp)->attr.allocatable))
{
if (!gfc_notify_std (GFC_STD_F2008, "No initializer for "
"allocatable component %qs given in the "
"structure constructor at %C", comp->name))
return false;
+ value = gfc_get_null_expr (&gfc_current_locus);
+ }
+ /* ....(Preceeding sentence) If a component with default
+ initialization has no corresponding component-data-source, then
+ the default initialization is applied to that component. */
+ else if (comp->initializer)
+ {
+ if (!gfc_notify_std (GFC_STD_F2003, "Structure constructor "
+ "with missing optional arguments at %C"))
+ return false;
+ value = gfc_copy_expr (comp->initializer);
}
+ /* Do not trap components such as the string length for deferred
+ length character components. */
else if (!comp->attr.artificial)
{
gfc_error ("No initializer for component %qs given in the"
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 106df27..a2898bf 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -3404,6 +3404,11 @@ resolve_function (gfc_expr *expr)
/* typebound procedure: Assume the worst. */
gfc_current_ns->proc_name->attr.array_outer_dependency = 1;
+ if (expr->value.function.esym
+ && expr->value.function.esym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED))
+ gfc_warning (OPT_Wdeprecated_declarations,
+ "Using function %qs at %L is deprecated",
+ sym->name, &expr->where);
return t;
}
@@ -3798,6 +3803,11 @@ resolve_call (gfc_code *c)
if (flag_coarray == GFC_FCOARRAY_SHARED)
fixup_shared_coarray_args (csym, c->ext.actual);
+ if (c->resolved_sym
+ && c->resolved_sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED))
+ gfc_warning (OPT_Wdeprecated_declarations,
+ "Using subroutine %qs at %L is deprecated",
+ c->resolved_sym->name, &c->loc);
return t;
}
@@ -5968,6 +5978,10 @@ resolve_procedure:
if (t && flag_coarray == GFC_FCOARRAY_LIB && gfc_is_coindexed (e))
add_caf_get_intrinsic (e);
+ if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED) && sym != sym->result)
+ gfc_warning (OPT_Wdeprecated_declarations,
+ "Using variable %qs at %L is deprecated",
+ sym->name, &e->where);
/* Simplify cases where access to a parameter array results in a
single constant. Suppress errors since those will have been
issued before, as warnings. */
@@ -10812,15 +10826,12 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_ATOMIC:
case EXEC_OACC_ATOMIC:
{
- gfc_omp_atomic_op aop
- = (gfc_omp_atomic_op) (b->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
-
/* Verify this before calling gfc_resolve_code, which might
change it. */
gcc_assert (b->next && b->next->op == EXEC_ASSIGN);
- gcc_assert (((aop != GFC_OMP_ATOMIC_CAPTURE)
+ gcc_assert ((!b->ext.omp_clauses->capture
&& b->next->next == NULL)
- || ((aop == GFC_OMP_ATOMIC_CAPTURE)
+ || (b->ext.omp_clauses->capture
&& b->next->next != NULL
&& b->next->next->op == EXEC_ASSIGN
&& b->next->next->next == NULL));
@@ -11123,7 +11134,7 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
/* Make sure there is a vtable and, in particular, a _copy for the
rhs type. */
- if (UNLIMITED_POLY (lhs) && lhs->rank && rhs->ts.type != BT_CLASS)
+ if (lhs->ts.type == BT_CLASS && rhs->ts.type != BT_CLASS)
gfc_find_vtab (&rhs->ts);
bool caf_convert_to_send = flag_coarray == GFC_FCOARRAY_LIB
@@ -11845,8 +11856,9 @@ gfc_resolve_code (gfc_code *code, gfc_namespace *ns)
gfc_resolve_omp_do_blocks (code, ns);
break;
case EXEC_SELECT_TYPE:
- /* Blocks are handled in resolve_select_type because we have
- to transform the SELECT TYPE into ASSOCIATE first. */
+ case EXEC_SELECT_RANK:
+ /* Blocks are handled in resolve_select_type/rank because we
+ have to transform the SELECT TYPE into ASSOCIATE first. */
break;
case EXEC_DO_CONCURRENT:
gfc_do_concurrent_flag = 1;
@@ -11965,6 +11977,9 @@ start:
if (!t)
break;
+ if (code->expr1->ts.type == BT_CLASS)
+ gfc_find_vtab (&code->expr2->ts);
+
/* Remove a GFC_ISYM_CAF_GET inserted for a coindexed variable on
the LHS. */
if (code->expr1->expr_type == EXPR_FUNCTION
@@ -12253,6 +12268,7 @@ start:
case EXEC_OMP_DO_SIMD:
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
+ case EXEC_OMP_SCAN:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
@@ -12316,6 +12332,11 @@ resolve_values (gfc_symbol *sym)
if (sym->value == NULL)
return;
+ if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED))
+ gfc_warning (OPT_Wdeprecated_declarations,
+ "Using parameter %qs declared at %L is deprecated",
+ sym->name, &sym->declared_at);
+
if (sym->value->expr_type == EXPR_STRUCTURE)
t= resolve_structure_cons (sym->value, 1);
else
@@ -15458,8 +15479,12 @@ resolve_symbol (gfc_symbol *sym)
else if (mp_flag && sym->attr.flavor == FL_PROCEDURE && sym->attr.function)
{
bool saved_specification_expr = specification_expr;
+ bool saved_formal_arg_flag = formal_arg_flag;
+
specification_expr = true;
+ formal_arg_flag = true;
gfc_resolve_array_spec (sym->result->as, false);
+ formal_arg_flag = saved_formal_arg_flag;
specification_expr = saved_specification_expr;
}
@@ -16228,6 +16253,13 @@ check_data_variable (gfc_data_variable *var, locus *where)
return false;
}
}
+
+ if (ref->type == REF_COMPONENT && ref->u.c.component->attr.allocatable)
+ {
+ gfc_error ("DATA element %qs at %L cannot have the ALLOCATABLE "
+ "attribute", ref->u.c.component->name, &e->where);
+ return false;
+ }
}
if (e->rank == 0 || has_pointer)
@@ -16391,7 +16423,7 @@ traverse_data_list (gfc_data_variable *var, locus *where)
|| end->expr_type != EXPR_CONSTANT)
{
gfc_error ("end of implied-do loop at %L could not be "
- "simplified to a constant value", &start->where);
+ "simplified to a constant value", &end->where);
retval = false;
goto cleanup;
}
@@ -16399,7 +16431,14 @@ traverse_data_list (gfc_data_variable *var, locus *where)
|| step->expr_type != EXPR_CONSTANT)
{
gfc_error ("step of implied-do loop at %L could not be "
- "simplified to a constant value", &start->where);
+ "simplified to a constant value", &step->where);
+ retval = false;
+ goto cleanup;
+ }
+ if (mpz_cmp_si (step->value.integer, 0) == 0)
+ {
+ gfc_error ("step of implied-do loop at %L shall not be zero",
+ &step->where);
retval = false;
goto cleanup;
}
@@ -16557,6 +16596,7 @@ gfc_impure_variable (gfc_symbol *sym)
proc = sym->ns->proc_name;
if (sym->attr.dummy
+ && !sym->attr.value
&& ((proc->attr.subroutine && sym->attr.intent == INTENT_IN)
|| proc->attr.function))
return 1;
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index fd11f5a..304ae2d 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -899,21 +899,14 @@ skip_free_comments (void)
if (next_char () == '$')
{
c = next_char ();
- if (c == 'a' || c == 'A')
- {
- if (skip_free_oacc_sentinel (start, old_loc))
- return false;
- gfc_current_locus = old_loc;
- next_char();
- c = next_char();
- }
- if (continue_flag || c == ' ' || c == '\t')
- {
- gfc_current_locus = old_loc;
- next_char();
- openacc_flag = 0;
- return true;
- }
+ if (c == 'a' || c == 'A')
+ {
+ if (skip_free_oacc_sentinel (start, old_loc))
+ return false;
+ gfc_current_locus = old_loc;
+ next_char();
+ c = next_char();
+ }
}
gfc_current_locus = old_loc;
}
@@ -1076,8 +1069,7 @@ skip_fixed_comments (void)
}
gfc_current_locus = start;
}
-
- if (flag_openacc && !(flag_openmp || flag_openmp_simd))
+ else if (flag_openacc && !(flag_openmp || flag_openmp_simd))
{
if (next_char () == '$')
{
@@ -1087,13 +1079,10 @@ skip_fixed_comments (void)
if (skip_fixed_oacc_sentinel (&start))
return;
}
- else
- goto check_for_digits;
}
gfc_current_locus = start;
}
-
- if (flag_openacc || flag_openmp || flag_openmp_simd)
+ else if (flag_openacc || flag_openmp || flag_openmp_simd)
{
if (next_char () == '$')
{
@@ -1120,6 +1109,7 @@ skip_fixed_comments (void)
gcc_unreachable ();
check_for_digits:
{
+ /* Required for OpenMP's conditional compilation sentinel. */
int digit_seen = 0;
for (col = 3; col < 6; col++, c = next_char ())
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index f6937b9..d5bccb8 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -198,6 +198,7 @@ gfc_free_statement (gfc_code *p)
gfc_free_oacc_declare_clauses (p->ext.oacc_declare);
break;
+ case EXEC_OACC_ATOMIC:
case EXEC_OACC_PARALLEL_LOOP:
case EXEC_OACC_PARALLEL:
case EXEC_OACC_KERNELS_LOOP:
@@ -213,6 +214,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OACC_ENTER_DATA:
case EXEC_OACC_EXIT_DATA:
case EXEC_OACC_ROUTINE:
+ case EXEC_OMP_ATOMIC:
case EXEC_OMP_CANCEL:
case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_CRITICAL:
@@ -229,6 +231,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
+ case EXEC_OMP_SCAN:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
@@ -266,8 +269,6 @@ gfc_free_statement (gfc_code *p)
gfc_free_omp_namelist (p->ext.omp_namelist);
break;
- case EXEC_OACC_ATOMIC:
- case EXEC_OMP_ATOMIC:
case EXEC_OMP_BARRIER:
case EXEC_OMP_MASTER:
case EXEC_OMP_END_NOWAIT:
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 998ec95..199bcae 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -133,28 +133,31 @@ gfc_array_dataptr_type (tree desc)
#define LBOUND_SUBFIELD 1
#define UBOUND_SUBFIELD 2
+static tree
+gfc_get_descriptor_field (tree desc, unsigned field_idx)
+{
+ tree type = TREE_TYPE (desc);
+ gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+
+ tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
+ gcc_assert (field != NULL_TREE);
+
+ return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
+ desc, field, NULL_TREE);
+}
+
/* This provides READ-ONLY access to the data field. The field itself
doesn't have the proper type. */
tree
gfc_conv_descriptor_data_get (tree desc)
{
- tree field, type, t;
-
- type = TREE_TYPE (desc);
+ tree type = TREE_TYPE (desc);
if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = TYPE_FIELDS (type);
- gcc_assert (DATA_FIELD == 0);
-
- t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
- field, NULL_TREE);
- t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
+ gcc_unreachable ();
- return t;
+ tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
+ return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field);
}
/* This provides WRITE access to the data field.
@@ -168,17 +171,8 @@ gfc_conv_descriptor_data_get (tree desc)
void
gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
{
- tree field, type, t;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = TYPE_FIELDS (type);
- gcc_assert (DATA_FIELD == 0);
-
- t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
- field, NULL_TREE);
- gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
+ tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
+ gfc_add_modify (block, field, fold_convert (TREE_TYPE (field), value));
}
@@ -188,33 +182,16 @@ gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
tree
gfc_conv_descriptor_data_addr (tree desc)
{
- tree field, type, t;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = TYPE_FIELDS (type);
- gcc_assert (DATA_FIELD == 0);
-
- t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
- field, NULL_TREE);
- return gfc_build_addr_expr (NULL_TREE, t);
+ tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
+ return gfc_build_addr_expr (NULL_TREE, field);
}
static tree
gfc_conv_descriptor_offset (tree desc)
{
- tree type;
- tree field;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
- gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
-
- return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- desc, field, NULL_TREE);
+ tree field = gfc_get_descriptor_field (desc, OFFSET_FIELD);
+ gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+ return field;
}
tree
@@ -235,34 +212,17 @@ gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
tree
gfc_conv_descriptor_dtype (tree desc)
{
- tree field;
- tree type;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
- gcc_assert (field != NULL_TREE
- && TREE_TYPE (field) == get_dtype_type_node ());
-
- return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- desc, field, NULL_TREE);
+ tree field = gfc_get_descriptor_field (desc, DTYPE_FIELD);
+ gcc_assert (TREE_TYPE (field) == get_dtype_type_node ());
+ return field;
}
static tree
gfc_conv_descriptor_span (tree desc)
{
- tree type;
- tree field;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
- gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
-
- return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- desc, field, NULL_TREE);
+ tree field = gfc_get_descriptor_field (desc, SPAN_FIELD);
+ gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+ return field;
}
tree
@@ -328,22 +288,13 @@ gfc_conv_descriptor_attribute (tree desc)
dtype, tmp, NULL_TREE);
}
-
tree
gfc_get_descriptor_dimension (tree desc)
{
- tree type, field;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
- field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
- gcc_assert (field != NULL_TREE
- && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
- && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
-
- return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- desc, field, NULL_TREE);
+ tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
+ gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
+ return field;
}
@@ -361,38 +312,31 @@ gfc_conv_descriptor_dimension (tree desc, tree dim)
tree
gfc_conv_descriptor_token (tree desc)
{
- tree type;
- tree field;
-
- type = TREE_TYPE (desc);
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
- field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
-
+ tree field = gfc_get_descriptor_field (desc, CAF_TOKEN_FIELD);
/* Should be a restricted pointer - except in the finalization wrapper. */
- gcc_assert (field != NULL_TREE
- && (TREE_TYPE (field) == prvoid_type_node
- || TREE_TYPE (field) == pvoid_type_node));
+ gcc_assert (TREE_TYPE (field) == prvoid_type_node
+ || TREE_TYPE (field) == pvoid_type_node);
+ return field;
+}
+
+static tree
+gfc_conv_descriptor_subfield (tree desc, tree dim, unsigned field_idx)
+{
+ tree tmp = gfc_conv_descriptor_dimension (desc, dim);
+ tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
+ gcc_assert (field != NULL_TREE);
return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- desc, field, NULL_TREE);
+ tmp, field, NULL_TREE);
}
-
static tree
gfc_conv_descriptor_stride (tree desc, tree dim)
{
- tree tmp;
- tree field;
-
- tmp = gfc_conv_descriptor_dimension (desc, dim);
- field = TYPE_FIELDS (TREE_TYPE (tmp));
- field = gfc_advance_chain (field, STRIDE_SUBFIELD);
- gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
-
- tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- tmp, field, NULL_TREE);
- return tmp;
+ tree field = gfc_conv_descriptor_subfield (desc, dim, STRIDE_SUBFIELD);
+ gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+ return field;
}
tree
@@ -421,17 +365,9 @@ gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
static tree
gfc_conv_descriptor_lbound (tree desc, tree dim)
{
- tree tmp;
- tree field;
-
- tmp = gfc_conv_descriptor_dimension (desc, dim);
- field = TYPE_FIELDS (TREE_TYPE (tmp));
- field = gfc_advance_chain (field, LBOUND_SUBFIELD);
- gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
-
- tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- tmp, field, NULL_TREE);
- return tmp;
+ tree field = gfc_conv_descriptor_subfield (desc, dim, LBOUND_SUBFIELD);
+ gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+ return field;
}
tree
@@ -451,17 +387,9 @@ gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
static tree
gfc_conv_descriptor_ubound (tree desc, tree dim)
{
- tree tmp;
- tree field;
-
- tmp = gfc_conv_descriptor_dimension (desc, dim);
- field = TYPE_FIELDS (TREE_TYPE (tmp));
- field = gfc_advance_chain (field, UBOUND_SUBFIELD);
- gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
-
- tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
- tmp, field, NULL_TREE);
- return tmp;
+ tree field = gfc_conv_descriptor_subfield (desc, dim, UBOUND_SUBFIELD);
+ gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+ return field;
}
tree
@@ -1102,7 +1030,6 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
tmp = TREE_TYPE (tmp); /* The descriptor itself. */
tmp = gfc_get_element_type (tmp);
- gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
packed = gfc_create_var (build_pointer_type (tmp), "data");
tmp = build_call_expr_loc (input_location,
@@ -1211,6 +1138,123 @@ get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
}
+/* Use the information in the ss to obtain the required information about
+ the type and size of an array temporary, when the lhs in an assignment
+ is a class expression. */
+
+static tree
+get_class_info_from_ss (stmtblock_t * pre, gfc_ss *ss, tree *eltype)
+{
+ gfc_ss *lhs_ss;
+ gfc_ss *rhs_ss;
+ tree tmp;
+ tree tmp2;
+ tree vptr;
+ tree rhs_class_expr = NULL_TREE;
+ tree lhs_class_expr = NULL_TREE;
+ bool unlimited_rhs = false;
+ bool unlimited_lhs = false;
+ bool rhs_function = false;
+ gfc_symbol *vtab;
+
+ /* The second element in the loop chain contains the source for the
+ temporary; ie. the rhs of the assignment. */
+ rhs_ss = ss->loop->ss->loop_chain;
+
+ if (rhs_ss != gfc_ss_terminator
+ && rhs_ss->info
+ && rhs_ss->info->expr
+ && rhs_ss->info->expr->ts.type == BT_CLASS
+ && rhs_ss->info->data.array.descriptor)
+ {
+ rhs_class_expr
+ = gfc_get_class_from_expr (rhs_ss->info->data.array.descriptor);
+ unlimited_rhs = UNLIMITED_POLY (rhs_ss->info->expr);
+ if (rhs_ss->info->expr->expr_type == EXPR_FUNCTION)
+ rhs_function = true;
+ }
+
+ /* For an assignment the lhs is the next element in the loop chain.
+ If we have a class rhs, this had better be a class variable
+ expression! */
+ lhs_ss = rhs_ss->loop_chain;
+ if (lhs_ss != gfc_ss_terminator
+ && lhs_ss->info
+ && lhs_ss->info->expr
+ && lhs_ss->info->expr->expr_type ==EXPR_VARIABLE
+ && lhs_ss->info->expr->ts.type == BT_CLASS)
+ {
+ tmp = lhs_ss->info->data.array.descriptor;
+ unlimited_lhs = UNLIMITED_POLY (rhs_ss->info->expr);
+ }
+ else
+ tmp = NULL_TREE;
+
+ /* Get the lhs class expression. */
+ if (tmp != NULL_TREE && lhs_ss->loop_chain == gfc_ss_terminator)
+ lhs_class_expr = gfc_get_class_from_expr (tmp);
+ else
+ return rhs_class_expr;
+
+ gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (lhs_class_expr)));
+
+ /* Set the lhs vptr and, if necessary, the _len field. */
+ if (rhs_class_expr)
+ {
+ /* Both lhs and rhs are class expressions. */
+ tmp = gfc_class_vptr_get (lhs_class_expr);
+ gfc_add_modify (pre, tmp,
+ fold_convert (TREE_TYPE (tmp),
+ gfc_class_vptr_get (rhs_class_expr)));
+ if (unlimited_lhs)
+ {
+ tmp = gfc_class_len_get (lhs_class_expr);
+ if (unlimited_rhs)
+ tmp2 = gfc_class_len_get (rhs_class_expr);
+ else
+ tmp2 = build_int_cst (TREE_TYPE (tmp), 0);
+ gfc_add_modify (pre, tmp, tmp2);
+ }
+
+ if (rhs_function)
+ {
+ tmp = gfc_class_data_get (rhs_class_expr);
+ gfc_conv_descriptor_offset_set (pre, tmp, gfc_index_zero_node);
+ }
+ }
+ else
+ {
+ /* lhs is class and rhs is intrinsic or derived type. */
+ *eltype = TREE_TYPE (rhs_ss->info->data.array.descriptor);
+ *eltype = gfc_get_element_type (*eltype);
+ vtab = gfc_find_vtab (&rhs_ss->info->expr->ts);
+ vptr = vtab->backend_decl;
+ if (vptr == NULL_TREE)
+ vptr = gfc_get_symbol_decl (vtab);
+ vptr = gfc_build_addr_expr (NULL_TREE, vptr);
+ tmp = gfc_class_vptr_get (lhs_class_expr);
+ gfc_add_modify (pre, tmp,
+ fold_convert (TREE_TYPE (tmp), vptr));
+
+ if (unlimited_lhs)
+ {
+ tmp = gfc_class_len_get (lhs_class_expr);
+ if (rhs_ss->info
+ && rhs_ss->info->expr
+ && rhs_ss->info->expr->ts.type == BT_CHARACTER)
+ tmp2 = build_int_cst (TREE_TYPE (tmp),
+ rhs_ss->info->expr->ts.kind);
+ else
+ tmp2 = build_int_cst (TREE_TYPE (tmp), 0);
+ gfc_add_modify (pre, tmp, tmp2);
+ }
+ }
+
+ return rhs_class_expr;
+}
+
+
+
/* Generate code to create and initialize the descriptor for a temporary
array. This is used for both temporaries needed by the scalarizer, and
functions returning arrays. Adjusts the loop variables to be
@@ -1256,13 +1300,46 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
{
gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
class_expr = build_fold_indirect_ref_loc (input_location, initial);
- eltype = TREE_TYPE (class_expr);
- eltype = gfc_get_element_type (eltype);
/* Obtain the structure (class) expression. */
- class_expr = TREE_OPERAND (class_expr, 0);
+ class_expr = gfc_get_class_from_expr (class_expr);
gcc_assert (class_expr);
}
+ /* Otherwise, some expressions, such as class functions, arising from
+ dependency checking in assignments come here with class element type.
+ The descriptor can be obtained from the ss->info and then converted
+ to the class object. */
+ if (class_expr == NULL_TREE && GFC_CLASS_TYPE_P (eltype))
+ class_expr = get_class_info_from_ss (pre, ss, &eltype);
+
+ /* If the dynamic type is not available, use the declared type. */
+ if (eltype && GFC_CLASS_TYPE_P (eltype))
+ eltype = gfc_get_element_type (TREE_TYPE (TYPE_FIELDS (eltype)));
+
+ if (class_expr == NULL_TREE)
+ elemsize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (eltype));
+ else
+ {
+ /* Unlimited polymorphic entities are initialised with NULL vptr. They
+ can be tested for by checking if the len field is present. If so
+ test the vptr before using the vtable size. */
+ tmp = gfc_class_vptr_get (class_expr);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ tmp, build_int_cst (TREE_TYPE (tmp), 0));
+ elemsize = fold_build3_loc (input_location, COND_EXPR,
+ gfc_array_index_type,
+ tmp,
+ gfc_class_vtab_size_get (class_expr),
+ gfc_index_zero_node);
+ elemsize = gfc_evaluate_now (elemsize, pre);
+ elemsize = gfc_resize_class_size_with_len (pre, class_expr, elemsize);
+ /* Casting the data as a character of the dynamic length ensures that
+ assignment of elements works when needed. */
+ eltype = gfc_get_character_type_len (1, elemsize);
+ }
+
memset (from, 0, sizeof (from));
memset (to, 0, sizeof (to));
@@ -1411,12 +1488,6 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
}
}
- if (class_expr == NULL_TREE)
- elemsize = fold_convert (gfc_array_index_type,
- TYPE_SIZE_UNIT (gfc_get_element_type (type)));
- else
- elemsize = gfc_class_vtab_size_get (class_expr);
-
/* Get the size of the array. */
if (size && !callee_alloc)
{
@@ -2128,6 +2199,7 @@ get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
gfc_ref *ref;
gfc_typespec *ts;
mpz_t char_len;
+ gfc_se se;
/* Don't bother if we already know the length is a constant. */
if (*len && INTEGER_CST_P (*len))
@@ -2173,6 +2245,19 @@ get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
}
}
+ /* A last ditch attempt that is sometimes needed for deferred characters. */
+ if (!ts->u.cl->backend_decl)
+ {
+ gfc_init_se (&se, NULL);
+ if (expr->rank)
+ gfc_conv_expr_descriptor (&se, expr);
+ else
+ gfc_conv_expr (&se, expr);
+ gcc_assert (se.string_length != NULL_TREE);
+ gfc_add_block_to_block (block, &se.pre);
+ ts->u.cl->backend_decl = se.string_length;
+ }
+
*len = ts->u.cl->backend_decl;
}
@@ -3067,17 +3152,17 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
}
/* Also the data pointer. */
tmp = gfc_conv_array_data (se.expr);
- /* If we have a native coarray with implied this_image (), add the
- appropriate offset to the data pointer. */
- ref = ss_info->expr->ref;
- /* If this is a variable or address of a variable we use it directly.
+ /* If this is a variable or address or a class array, use it directly.
Otherwise we must evaluate it now to avoid breaking dependency
analysis by pulling the expressions for elemental array indices
inside the loop. */
if (!(DECL_P (tmp)
|| (TREE_CODE (tmp) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (tmp, 0)))))
+ && DECL_P (TREE_OPERAND (tmp, 0)))
+ || (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
+ && TREE_CODE (se.expr) == COMPONENT_REF
+ && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (se.expr, 0))))))
tmp = gfc_evaluate_now (tmp, block);
info->data = tmp;
@@ -3544,18 +3629,10 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
size = gfc_class_vtab_size_get (decl);
/* For unlimited polymorphic entities then _len component needs to be
- multiplied with the size. If no _len component is present, then
- gfc_class_len_or_zero_get () return a zero_node. */
- tmp = gfc_class_len_or_zero_get (decl);
- if (!integer_zerop (tmp))
- size = fold_build2 (MULT_EXPR, TREE_TYPE (index),
- fold_convert (TREE_TYPE (index), size),
- fold_build2 (MAX_EXPR, TREE_TYPE (index),
- fold_convert (TREE_TYPE (index), tmp),
- fold_convert (TREE_TYPE (index),
- integer_one_node)));
- else
- size = fold_convert (TREE_TYPE (index), size);
+ multiplied with the size. */
+ size = gfc_resize_class_size_with_len (&se->pre, decl, size);
+
+ size = fold_convert (TREE_TYPE (index), size);
/* Build the address of the element. */
type = TREE_TYPE (TREE_TYPE (base));
@@ -9616,21 +9693,9 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
for the malloc call. */
if (UNLIMITED_POLY (c))
{
- tree ctmp;
gfc_add_modify (&tmpblock, gfc_class_len_get (dcmp),
gfc_class_len_get (comp));
-
- size = gfc_evaluate_now (size, &tmpblock);
- tmp = gfc_class_len_get (comp);
- ctmp = fold_build2_loc (input_location, MULT_EXPR,
- size_type_node, size,
- fold_convert (size_type_node, tmp));
- tmp = fold_build2_loc (input_location, GT_EXPR,
- logical_type_node, tmp,
- build_zero_cst (TREE_TYPE (tmp)));
- size = fold_build3_loc (input_location, COND_EXPR,
- size_type_node, tmp, ctmp, size);
- size = gfc_evaluate_now (size, &tmpblock);
+ size = gfc_resize_class_size_with_len (&tmpblock, comp, size);
}
/* Coarray component have to have the same allocation status and
@@ -10416,6 +10481,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
tree alloc_expr;
tree size1;
tree size2;
+ tree elemsize1;
+ tree elemsize2;
tree array1;
tree cond_null;
tree cond;
@@ -10431,6 +10498,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
tree jump_label2;
tree neq_size;
tree lbd;
+ tree class_expr2 = NULL_TREE;
int n;
int dim;
gfc_array_spec * as;
@@ -10495,6 +10563,114 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
array1 = gfc_conv_descriptor_data_get (desc);
+ if (expr2)
+ desc2 = rss->info->data.array.descriptor;
+ else
+ desc2 = NULL_TREE;
+
+ /* Get the old lhs element size for deferred character and class expr1. */
+ if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
+ {
+ if (expr1->ts.u.cl->backend_decl
+ && VAR_P (expr1->ts.u.cl->backend_decl))
+ elemsize1 = expr1->ts.u.cl->backend_decl;
+ else
+ elemsize1 = lss->info->string_length;
+ }
+ else if (expr1->ts.type == BT_CLASS)
+ {
+ tmp = expr1->rank ? gfc_get_class_from_expr (desc) : NULL_TREE;
+ if (tmp == NULL_TREE)
+ tmp = gfc_get_class_from_gfc_expr (expr1);
+
+ if (tmp != NULL_TREE)
+ {
+ tmp2 = gfc_class_vptr_get (tmp);
+ cond = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, tmp2,
+ build_int_cst (TREE_TYPE (tmp2), 0));
+ elemsize1 = gfc_class_vtab_size_get (tmp);
+ elemsize1 = fold_build3_loc (input_location, COND_EXPR,
+ gfc_array_index_type, cond,
+ elemsize1, gfc_index_zero_node);
+ }
+ else
+ elemsize1 = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&CLASS_DATA (expr1)->ts));
+ }
+ else
+ elemsize1 = NULL_TREE;
+ if (elemsize1 != NULL_TREE)
+ elemsize1 = gfc_evaluate_now (elemsize1, &fblock);
+
+ /* Get the new lhs size in bytes. */
+ if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
+ {
+ if (expr2->ts.deferred)
+ {
+ if (expr2->ts.u.cl->backend_decl
+ && VAR_P (expr2->ts.u.cl->backend_decl))
+ tmp = expr2->ts.u.cl->backend_decl;
+ else
+ tmp = rss->info->string_length;
+ }
+ else
+ {
+ tmp = expr2->ts.u.cl->backend_decl;
+ if (!tmp && expr2->expr_type == EXPR_OP
+ && expr2->value.op.op == INTRINSIC_CONCAT)
+ {
+ tmp = concat_str_length (expr2);
+ expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
+ }
+ else if (!tmp && expr2->ts.u.cl->length)
+ {
+ gfc_se tmpse;
+ gfc_init_se (&tmpse, NULL);
+ gfc_conv_expr_type (&tmpse, expr2->ts.u.cl->length,
+ gfc_charlen_type_node);
+ tmp = tmpse.expr;
+ expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
+ }
+ tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
+ }
+
+ if (expr1->ts.u.cl->backend_decl
+ && VAR_P (expr1->ts.u.cl->backend_decl))
+ gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
+ else
+ gfc_add_modify (&fblock, lss->info->string_length, tmp);
+
+ if (expr1->ts.kind > 1)
+ tmp = fold_build2_loc (input_location, MULT_EXPR,
+ TREE_TYPE (tmp),
+ tmp, build_int_cst (TREE_TYPE (tmp),
+ expr1->ts.kind));
+ }
+ else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
+ {
+ tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
+ tmp = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type, tmp,
+ expr1->ts.u.cl->backend_decl);
+ }
+ else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
+ else if (expr1->ts.type == BT_CLASS && expr2->ts.type == BT_CLASS)
+ {
+ tmp = expr2->rank ? gfc_get_class_from_expr (desc2) : NULL_TREE;
+ if (tmp == NULL_TREE && expr2->expr_type == EXPR_VARIABLE)
+ tmp = class_expr2 = gfc_get_class_from_gfc_expr (expr2);
+
+ if (tmp != NULL_TREE)
+ tmp = gfc_class_vtab_size_get (tmp);
+ else
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&CLASS_DATA (expr2)->ts));
+ }
+ else
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
+ elemsize2 = fold_convert (gfc_array_index_type, tmp);
+ elemsize2 = gfc_evaluate_now (elemsize2, &fblock);
+
/* 7.4.1.3 "If variable is an allocated allocatable variable, it is
deallocated if expr is an array of different shape or any of the
corresponding length type parameter values of variable and expr
@@ -10514,6 +10690,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
rss->info->string_length);
cond_null = fold_build2_loc (input_location, TRUTH_OR_EXPR,
logical_type_node, tmp, cond_null);
+ cond_null= gfc_evaluate_now (cond_null, &fblock);
}
else
cond_null= gfc_evaluate_now (cond_null, &fblock);
@@ -10562,6 +10739,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_expr_to_block (&fblock, tmp);
}
+ /* ...else if the element lengths are not the same also go to
+ setting the bounds and doing the reallocation.... */
+ if (elemsize1 != NULL_TREE)
+ {
+ cond = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ elemsize1, elemsize2);
+ tmp = build3_v (COND_EXPR, cond,
+ build1_v (GOTO_EXPR, jump_label1),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&fblock, tmp);
+ }
+
/* ....else jump past the (re)alloc code. */
tmp = build1_v (GOTO_EXPR, jump_label2);
gfc_add_expr_to_block (&fblock, tmp);
@@ -10584,11 +10774,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_expr_to_block (&fblock, tmp);
/* Get the rhs size and fix it. */
- if (expr2)
- desc2 = rss->info->data.array.descriptor;
- else
- desc2 = NULL_TREE;
-
size2 = gfc_index_one_node;
for (n = 0; n < expr2->rank; n++)
{
@@ -10703,69 +10888,12 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_modify (&fblock, linfo->delta[dim], tmp);
}
- /* Get the new lhs size in bytes. */
- if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
- {
- if (expr2->ts.deferred)
- {
- if (expr2->ts.u.cl->backend_decl
- && VAR_P (expr2->ts.u.cl->backend_decl))
- tmp = expr2->ts.u.cl->backend_decl;
- else
- tmp = rss->info->string_length;
- }
- else
- {
- tmp = expr2->ts.u.cl->backend_decl;
- if (!tmp && expr2->expr_type == EXPR_OP
- && expr2->value.op.op == INTRINSIC_CONCAT)
- {
- tmp = concat_str_length (expr2);
- expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
- }
- else if (!tmp && expr2->ts.u.cl->length)
- {
- gfc_se tmpse;
- gfc_init_se (&tmpse, NULL);
- gfc_conv_expr_type (&tmpse, expr2->ts.u.cl->length,
- gfc_charlen_type_node);
- tmp = tmpse.expr;
- expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
- }
- tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
- }
-
- if (expr1->ts.u.cl->backend_decl
- && VAR_P (expr1->ts.u.cl->backend_decl))
- gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
- else
- gfc_add_modify (&fblock, lss->info->string_length, tmp);
-
- if (expr1->ts.kind > 1)
- tmp = fold_build2_loc (input_location, MULT_EXPR,
- TREE_TYPE (tmp),
- tmp, build_int_cst (TREE_TYPE (tmp),
- expr1->ts.kind));
- }
- else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
- {
- tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
- tmp = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, tmp,
- expr1->ts.u.cl->backend_decl);
- }
- else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
- tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
- else
- tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
- tmp = fold_convert (gfc_array_index_type, tmp);
-
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
- gfc_conv_descriptor_span_set (&fblock, desc, tmp);
+ gfc_conv_descriptor_span_set (&fblock, desc, elemsize2);
size2 = fold_build2_loc (input_location, MULT_EXPR,
gfc_array_index_type,
- tmp, size2);
+ elemsize2, size2);
size2 = fold_convert (size_type_node, size2);
size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
size2, size_one_node);
@@ -10786,27 +10914,47 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_modify (&fblock, tmp,
gfc_get_dtype_rank_type (expr1->rank,type));
}
- else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
+ else if (expr1->ts.type == BT_CLASS)
{
tree type;
tmp = gfc_conv_descriptor_dtype (desc);
- type = gfc_typenode_for_spec (&expr2->ts);
+
+ if (expr2->ts.type != BT_CLASS)
+ type = gfc_typenode_for_spec (&expr2->ts);
+ else
+ type = gfc_get_character_type_len (1, elemsize2);
+
gfc_add_modify (&fblock, tmp,
gfc_get_dtype_rank_type (expr2->rank,type));
/* Set the _len field as well... */
- tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
- if (expr2->ts.type == BT_CHARACTER)
- gfc_add_modify (&fblock, tmp,
- fold_convert (TREE_TYPE (tmp),
- TYPE_SIZE_UNIT (type)));
- else
- gfc_add_modify (&fblock, tmp,
- build_int_cst (TREE_TYPE (tmp), 0));
+ if (UNLIMITED_POLY (expr1))
+ {
+ tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
+ if (expr2->ts.type == BT_CHARACTER)
+ gfc_add_modify (&fblock, tmp,
+ fold_convert (TREE_TYPE (tmp),
+ TYPE_SIZE_UNIT (type)));
+ else
+ gfc_add_modify (&fblock, tmp,
+ build_int_cst (TREE_TYPE (tmp), 0));
+ }
/* ...and the vptr. */
tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
- tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
- tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
- gfc_add_modify (&fblock, tmp, tmp2);
+ if (expr2->ts.type == BT_CLASS && !VAR_P (desc2)
+ && TREE_CODE (desc2) == COMPONENT_REF)
+ {
+ tmp2 = gfc_get_class_from_expr (desc2);
+ tmp2 = gfc_class_vptr_get (tmp2);
+ }
+ else if (expr2->ts.type == BT_CLASS && class_expr2 != NULL_TREE)
+ tmp2 = gfc_class_vptr_get (class_expr2);
+ else
+ {
+ tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
+ tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
+ }
+
+ gfc_add_modify (&fblock, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
}
else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
{
@@ -10882,11 +11030,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_block_to_block (&realloc_block, &caf_se.post);
realloc_expr = gfc_finish_block (&realloc_block);
- /* Only reallocate if sizes are different. */
+ /* Reallocate if sizes or dynamic types are different. */
+ if (elemsize1)
+ {
+ tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ elemsize1, elemsize2);
+ tmp = gfc_evaluate_now (tmp, &fblock);
+ neq_size = fold_build2_loc (input_location, TRUTH_OR_EXPR,
+ logical_type_node, neq_size, tmp);
+ }
tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
build_empty_stmt (input_location));
- realloc_expr = tmp;
+ realloc_expr = tmp;
/* Malloc expression. */
gfc_init_block (&alloc_block);
@@ -10933,11 +11089,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
alloc_expr = gfc_finish_block (&alloc_block);
/* Malloc if not allocated; realloc otherwise. */
- tmp = build_int_cst (TREE_TYPE (array1), 0);
- cond = fold_build2_loc (input_location, EQ_EXPR,
- logical_type_node,
- array1, tmp);
- tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
+ tmp = build3_v (COND_EXPR, cond_null, alloc_expr, realloc_expr);
gfc_add_expr_to_block (&fblock, tmp);
/* Make sure that the scalarizer data pointer is updated. */
@@ -10947,7 +11099,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_modify (&fblock, linfo->data, tmp);
}
- /* Add the exit label. */
+ /* Add the label for same shape lhs and rhs. */
tmp = build1_v (LABEL_EXPR, jump_label2);
gfc_add_expr_to_block (&fblock, tmp);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 61d5667..3ecd63d 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1464,7 +1464,7 @@ add_attributes_to_decl (symbol_attribute sym_attr, tree list)
tree attr;
for (id = 0; id < EXT_ATTR_NUM; id++)
- if (sym_attr.ext_attr & (1 << id))
+ if (sym_attr.ext_attr & (1 << id) && ext_attr_list[id].middle_end_name)
{
attr = build_tree_list (
get_identifier (ext_attr_list[id].middle_end_name),
@@ -1785,7 +1785,6 @@ gfc_get_symbol_decl (gfc_symbol * sym)
|| sym->attr.if_source != IFSRC_DECL)
{
decl = gfc_get_extern_function_decl (sym);
- gfc_set_decl_location (decl, &sym->declared_at);
}
else
{
@@ -2115,7 +2114,8 @@ get_proc_pointer_decl (gfc_symbol *sym)
/* Get a basic decl for an external function. */
tree
-gfc_get_extern_function_decl (gfc_symbol * sym, gfc_actual_arglist *actual_args)
+gfc_get_extern_function_decl (gfc_symbol * sym, gfc_actual_arglist *actual_args,
+ const char *fnspec)
{
tree type;
tree fndecl;
@@ -2327,7 +2327,8 @@ module_sym:
mangled_name = gfc_sym_mangled_function_id (sym);
}
- type = gfc_get_function_type (sym, actual_args);
+ type = gfc_get_function_type (sym, actual_args, fnspec);
+
fndecl = build_decl (input_location,
FUNCTION_DECL, name, type);
@@ -3060,8 +3061,9 @@ build_entry_thunks (gfc_namespace * ns, bool global)
poplevel (1, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (thunk_fndecl)) = thunk_fndecl;
DECL_SAVED_TREE (thunk_fndecl)
- = build3_v (BIND_EXPR, tmp, DECL_SAVED_TREE (thunk_fndecl),
- DECL_INITIAL (thunk_fndecl));
+ = fold_build3_loc (DECL_SOURCE_LOCATION (thunk_fndecl), BIND_EXPR,
+ void_type_node, tmp, DECL_SAVED_TREE (thunk_fndecl),
+ DECL_INITIAL (thunk_fndecl));
/* Output the GENERIC tree. */
dump_function (TDI_original, thunk_fndecl);
@@ -6751,8 +6753,9 @@ create_main_function (tree fndecl)
BLOCK_SUPERCONTEXT (DECL_INITIAL (ftn_main)) = ftn_main;
DECL_SAVED_TREE (ftn_main)
- = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (ftn_main),
- DECL_INITIAL (ftn_main));
+ = fold_build3_loc (DECL_SOURCE_LOCATION (ftn_main), BIND_EXPR,
+ void_type_node, decl, DECL_SAVED_TREE (ftn_main),
+ DECL_INITIAL (ftn_main));
/* Output the GENERIC tree. */
dump_function (TDI_original, ftn_main);
@@ -7203,8 +7206,7 @@ gfc_generate_function_code (gfc_namespace * ns)
gfc_init_block (&cleanup);
/* Reset recursion-check variable. */
- if ((gfc_option.rtcheck & GFC_RTCHECK_RECURSION)
- && !is_recursive && !flag_openmp && recurcheckvar != NULL_TREE)
+ if (recurcheckvar != NULL_TREE)
{
gfc_add_modify (&cleanup, recurcheckvar, logical_false_node);
recurcheckvar = NULL;
@@ -7243,8 +7245,8 @@ gfc_generate_function_code (gfc_namespace * ns)
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
DECL_SAVED_TREE (fndecl)
- = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl),
- DECL_INITIAL (fndecl));
+ = fold_build3_loc (DECL_SOURCE_LOCATION (fndecl), BIND_EXPR, void_type_node,
+ decl, DECL_SAVED_TREE (fndecl), DECL_INITIAL (fndecl));
/* Output the GENERIC tree. */
dump_function (TDI_original, fndecl);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 5a6e696..3a2f9d9 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -257,6 +257,42 @@ gfc_class_len_or_zero_get (tree decl)
}
+tree
+gfc_resize_class_size_with_len (stmtblock_t * block, tree class_expr, tree size)
+{
+ tree tmp;
+ tree tmp2;
+ tree type;
+
+ tmp = gfc_class_len_or_zero_get (class_expr);
+
+ /* Include the len value in the element size if present. */
+ if (!integer_zerop (tmp))
+ {
+ type = TREE_TYPE (size);
+ if (block)
+ {
+ size = gfc_evaluate_now (size, block);
+ tmp = gfc_evaluate_now (fold_convert (type , tmp), block);
+ }
+ tmp2 = fold_build2_loc (input_location, MULT_EXPR,
+ type, size, tmp);
+ tmp = fold_build2_loc (input_location, GT_EXPR,
+ logical_type_node, tmp,
+ build_zero_cst (type));
+ size = fold_build3_loc (input_location, COND_EXPR,
+ type, tmp, tmp2, size);
+ }
+ else
+ return size;
+
+ if (block)
+ size = gfc_evaluate_now (size, block);
+
+ return size;
+}
+
+
/* Get the specified FIELD from the VPTR. */
static tree
@@ -472,6 +508,25 @@ gfc_reset_len (stmtblock_t *block, gfc_expr *expr)
}
+/* Obtain the last class reference in a gfc_expr. Return NULL_TREE if no class
+ reference is found. Note that it is up to the caller to avoid using this
+ for expressions other than variables. */
+
+tree
+gfc_get_class_from_gfc_expr (gfc_expr *e)
+{
+ gfc_expr *class_expr;
+ gfc_se cse;
+ class_expr = gfc_find_and_cut_at_last_class_ref (e);
+ if (class_expr == NULL)
+ return NULL_TREE;
+ gfc_init_se (&cse, NULL);
+ gfc_conv_expr (&cse, class_expr);
+ gfc_free_expr (class_expr);
+ return cse.expr;
+}
+
+
/* Obtain the last class reference in an expression.
Return NULL_TREE if no class reference is found. */
@@ -483,6 +538,9 @@ gfc_get_class_from_expr (tree expr)
for (tmp = expr; tmp; tmp = TREE_OPERAND (tmp, 0))
{
+ if (CONSTANT_CLASS_P (tmp))
+ return NULL_TREE;
+
type = TREE_TYPE (tmp);
while (type)
{
@@ -1606,6 +1664,111 @@ gfc_trans_class_init_assign (gfc_code *code)
}
+/* Class valued elemental function calls or class array elements arriving
+ in gfc_trans_scalar_assign come here. Wherever possible the vptr copy
+ is used to ensure that the rhs dynamic type is assigned to the lhs. */
+
+static bool
+trans_scalar_class_assign (stmtblock_t *block, gfc_se *lse, gfc_se *rse)
+{
+ tree fcn;
+ tree rse_expr;
+ tree class_data;
+ tree tmp;
+ tree zero;
+ tree cond;
+ tree final_cond;
+ stmtblock_t inner_block;
+ bool is_descriptor;
+ bool not_call_expr = TREE_CODE (rse->expr) != CALL_EXPR;
+ bool not_lhs_array_type;
+
+ /* Temporaries arising from depencies in assignment get cast as a
+ character type of the dynamic size of the rhs. Use the vptr copy
+ for this case. */
+ tmp = TREE_TYPE (lse->expr);
+ not_lhs_array_type = !(tmp && TREE_CODE (tmp) == ARRAY_TYPE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (tmp)) != NULL_TREE);
+
+ /* Use ordinary assignment if the rhs is not a call expression or
+ the lhs is not a class entity or an array(ie. character) type. */
+ if ((not_call_expr && gfc_get_class_from_expr (lse->expr) == NULL_TREE)
+ && not_lhs_array_type)
+ return false;
+
+ /* Ordinary assignment can be used if both sides are class expressions
+ since the dynamic type is preserved by copying the vptr. This
+ should only occur, where temporaries are involved. */
+ if (GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
+ && GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
+ return false;
+
+ /* Fix the class expression and the class data of the rhs. */
+ if (!GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))
+ || not_call_expr)
+ {
+ tmp = gfc_get_class_from_expr (rse->expr);
+ if (tmp == NULL_TREE)
+ return false;
+ rse_expr = gfc_evaluate_now (tmp, block);
+ }
+ else
+ rse_expr = gfc_evaluate_now (rse->expr, block);
+
+ class_data = gfc_class_data_get (rse_expr);
+
+ /* Check that the rhs data is not null. */
+ is_descriptor = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (class_data));
+ if (is_descriptor)
+ class_data = gfc_conv_descriptor_data_get (class_data);
+ class_data = gfc_evaluate_now (class_data, block);
+
+ zero = build_int_cst (TREE_TYPE (class_data), 0);
+ cond = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ class_data, zero);
+
+ /* Copy the rhs to the lhs. */
+ fcn = gfc_vptr_copy_get (gfc_class_vptr_get (rse_expr));
+ fcn = build_fold_indirect_ref_loc (input_location, fcn);
+ tmp = gfc_evaluate_now (gfc_build_addr_expr (NULL, rse->expr), block);
+ tmp = is_descriptor ? tmp : class_data;
+ tmp = build_call_expr_loc (input_location, fcn, 2, tmp,
+ gfc_build_addr_expr (NULL, lse->expr));
+ gfc_add_expr_to_block (block, tmp);
+
+ /* Only elemental function results need to be finalised and freed. */
+ if (not_call_expr)
+ return true;
+
+ /* Finalize the class data if needed. */
+ gfc_init_block (&inner_block);
+ fcn = gfc_vptr_final_get (gfc_class_vptr_get (rse_expr));
+ zero = build_int_cst (TREE_TYPE (fcn), 0);
+ final_cond = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, fcn, zero);
+ fcn = build_fold_indirect_ref_loc (input_location, fcn);
+ tmp = build_call_expr_loc (input_location, fcn, 1, class_data);
+ tmp = build3_v (COND_EXPR, final_cond,
+ tmp, build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&inner_block, tmp);
+
+ /* Free the class data. */
+ tmp = gfc_call_free (class_data);
+ tmp = build3_v (COND_EXPR, cond, tmp,
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&inner_block, tmp);
+
+ /* Finish the inner block and subject it to the condition on the
+ class data being non-zero. */
+ tmp = gfc_finish_block (&inner_block);
+ tmp = build3_v (COND_EXPR, cond, tmp,
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (block, tmp);
+
+ return true;
+}
+
/* End of prototype trans-class.c */
@@ -5616,8 +5779,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
{
/* The intrinsic type needs to be converted to a temporary
CLASS object for the unlimited polymorphic formal. */
+ gfc_find_vtab (&e->ts);
gfc_init_se (&parmse, se);
gfc_conv_intrinsic_to_class (&parmse, e, fsym->ts);
+
}
else if (se->ss && se->ss->info->useflags)
{
@@ -7734,12 +7899,14 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
return se.expr;
case BT_CHARACTER:
- {
- tree ctor = gfc_conv_string_init (ts->u.cl->backend_decl,expr);
- TREE_STATIC (ctor) = 1;
- return ctor;
- }
+ if (expr->expr_type == EXPR_CONSTANT)
+ {
+ tree ctor = gfc_conv_string_init (ts->u.cl->backend_decl, expr);
+ TREE_STATIC (ctor) = 1;
+ return ctor;
+ }
+ /* Fallthrough. */
default:
gfc_init_se (&se, NULL);
gfc_conv_constant (&se, expr);
@@ -8929,14 +9096,32 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le,
tree tmp, to_len = NULL_TREE, from_len = NULL_TREE, lhs_vptr;
bool set_vptr = false, temp_rhs = false;
stmtblock_t *pre = block;
+ tree class_expr = NULL_TREE;
/* Create a temporary for complicated expressions. */
if (re->expr_type != EXPR_VARIABLE && re->expr_type != EXPR_NULL
&& rse->expr != NULL_TREE && !DECL_P (rse->expr))
{
- tmp = gfc_create_var (TREE_TYPE (rse->expr), "rhs");
- pre = &rse->pre;
- gfc_add_modify (&rse->pre, tmp, rse->expr);
+ if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
+ class_expr = gfc_get_class_from_expr (rse->expr);
+
+ if (rse->loop)
+ pre = &rse->loop->pre;
+ else
+ pre = &rse->pre;
+
+ if (class_expr != NULL_TREE && UNLIMITED_POLY (re))
+ {
+ tmp = TREE_OPERAND (rse->expr, 0);
+ tmp = gfc_create_var (TREE_TYPE (tmp), "rhs");
+ gfc_add_modify (&rse->pre, tmp, TREE_OPERAND (rse->expr, 0));
+ }
+ else
+ {
+ tmp = gfc_create_var (TREE_TYPE (rse->expr), "rhs");
+ gfc_add_modify (&rse->pre, tmp, rse->expr);
+ }
+
rse->expr = tmp;
temp_rhs = true;
}
@@ -9004,9 +9189,17 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le,
else if (temp_rhs && re->ts.type == BT_CLASS)
{
vptr_expr = NULL;
- se.expr = gfc_class_vptr_get (rse->expr);
+ if (class_expr)
+ tmp = class_expr;
+ else if (!GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
+ tmp = gfc_get_class_from_expr (rse->expr);
+ else
+ tmp = rse->expr;
+
+ se.expr = gfc_class_vptr_get (tmp);
if (UNLIMITED_POLY (re))
- from_len = gfc_class_len_get (rse->expr);
+ from_len = gfc_class_len_get (tmp);
+
}
else if (re->expr_type != EXPR_NULL)
/* Only when rhs is non-NULL use its declared type for vptr
@@ -9753,7 +9946,7 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
gfc_add_expr_to_block (&block, tmp);
}
}
- else if (gfc_bt_struct (ts.type) || ts.type == BT_CLASS)
+ else if (gfc_bt_struct (ts.type))
{
gfc_add_block_to_block (&block, &lse->pre);
gfc_add_block_to_block (&block, &rse->pre);
@@ -9761,7 +9954,20 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
TREE_TYPE (lse->expr), rse->expr);
gfc_add_modify (&block, lse->expr, tmp);
}
- else
+ /* If possible use the rhs vptr copy with trans_scalar_class_assign.... */
+ else if (ts.type == BT_CLASS
+ && !trans_scalar_class_assign (&block, lse, rse))
+ {
+ gfc_add_block_to_block (&block, &lse->pre);
+ gfc_add_block_to_block (&block, &rse->pre);
+ /* ...otherwise assignment suffices. Note the use of VIEW_CONVERT_EXPR
+ for the lhs which ensures that class data rhs cast as a string assigns
+ correctly. */
+ tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
+ TREE_TYPE (rse->expr), lse->expr);
+ gfc_add_modify (&block, tmp, rse->expr);
+ }
+ else if (ts.type != BT_CLASS)
{
gfc_add_block_to_block (&block, &lse->pre);
gfc_add_block_to_block (&block, &rse->pre);
@@ -10669,23 +10875,53 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
gfc_se *lse, gfc_se *rse, bool use_vptr_copy,
bool class_realloc)
{
- tree tmp, fcn, stdcopy, to_len, from_len, vptr;
+ tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr;
vec<tree, va_gc> *args = NULL;
+ /* Store the old vptr so that dynamic types can be compared for
+ reallocation to occur or not. */
+ if (class_realloc)
+ {
+ tmp = lse->expr;
+ if (!GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
+ tmp = gfc_get_class_from_expr (tmp);
+ }
+
vptr = trans_class_vptr_len_assignment (block, lhs, rhs, rse, &to_len,
&from_len);
- /* Generate allocation of the lhs. */
+ /* Generate (re)allocation of the lhs. */
if (class_realloc)
{
- stmtblock_t alloc;
- tree class_han;
+ stmtblock_t alloc, re_alloc;
+ tree class_han, re, size;
+
+ if (tmp && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
+ old_vptr = gfc_evaluate_now (gfc_class_vptr_get (tmp), block);
+ else
+ old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
- tmp = gfc_vptr_size_get (vptr);
+ size = gfc_vptr_size_get (vptr);
class_han = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
? gfc_class_data_get (lse->expr) : lse->expr;
+
+ /* Allocate block. */
gfc_init_block (&alloc);
- gfc_allocate_using_malloc (&alloc, class_han, tmp, NULL_TREE);
+ gfc_allocate_using_malloc (&alloc, class_han, size, NULL_TREE);
+
+ /* Reallocate if dynamic types are different. */
+ gfc_init_block (&re_alloc);
+ re = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_REALLOC), 2,
+ fold_convert (pvoid_type_node, class_han),
+ size);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, vptr, old_vptr);
+ re = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+ tmp, re, build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&re_alloc, re);
+
+ /* Allocate if _data is NULL, reallocate otherwise. */
tmp = fold_build2_loc (input_location, EQ_EXPR,
logical_type_node, class_han,
build_int_cst (prvoid_type_node, 0));
@@ -10693,7 +10929,7 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
gfc_unlikely (tmp,
PRED_FORTRAN_FAIL_ALLOC),
gfc_finish_block (&alloc),
- build_empty_stmt (input_location));
+ gfc_finish_block (&re_alloc));
gfc_add_expr_to_block (&lse->pre, tmp);
}
@@ -10796,6 +11032,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
bool maybe_workshare = false, lhs_refs_comp = false, rhs_refs_comp = false;
symbol_attribute lhs_caf_attr, rhs_caf_attr, lhs_attr;
bool is_poly_assign;
+ bool realloc_flag;
/* Assignment of the form lhs = rhs. */
gfc_start_block (&block);
@@ -10836,6 +11073,10 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
|| gfc_is_class_array_ref (expr2, NULL)
|| gfc_is_class_scalar_expr (expr2));
+ realloc_flag = flag_realloc_lhs
+ && gfc_is_reallocatable_lhs (expr1)
+ && expr2->rank
+ && !is_runtime_conformable (expr1, expr2);
/* Only analyze the expressions for coarray properties, when in coarray-lib
mode. */
@@ -11078,10 +11319,24 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
tmp = NULL_TREE;
if (is_poly_assign)
- tmp = trans_class_assignment (&body, expr1, expr2, &lse, &rse,
- use_vptr_copy || (lhs_attr.allocatable
- && !lhs_attr.dimension),
- flag_realloc_lhs && !lhs_attr.pointer);
+ {
+ tmp = trans_class_assignment (&body, expr1, expr2, &lse, &rse,
+ use_vptr_copy || (lhs_attr.allocatable
+ && !lhs_attr.dimension),
+ !realloc_flag && flag_realloc_lhs
+ && !lhs_attr.pointer);
+ if (expr2->expr_type == EXPR_FUNCTION
+ && expr2->ts.type == BT_DERIVED
+ && expr2->ts.u.derived->attr.alloc_comp)
+ {
+ tree tmp2 = gfc_deallocate_alloc_comp (expr2->ts.u.derived,
+ rse.expr, expr2->rank);
+ if (lss == gfc_ss_terminator)
+ gfc_add_expr_to_block (&rse.post, tmp2);
+ else
+ gfc_add_expr_to_block (&loop.post, tmp2);
+ }
+ }
else if (flag_coarray == GFC_FCOARRAY_LIB
&& lhs_caf_attr.codimension && rhs_caf_attr.codimension
&& ((lhs_caf_attr.allocatable && lhs_refs_comp)
@@ -11111,7 +11366,8 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
{
/* This case comes about when the scalarizer provides array element
references. Use the vptr copy function, since this does a deep
- copy of allocatable components, without which the finalizer call */
+ copy of allocatable components, without which the finalizer call
+ will deallocate the components. */
tmp = gfc_get_vptr_from_expr (rse.expr);
if (tmp != NULL_TREE)
{
@@ -11186,10 +11442,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
}
/* F2003: Allocate or reallocate lhs of allocatable array. */
- if (flag_realloc_lhs
- && gfc_is_reallocatable_lhs (expr1)
- && expr2->rank
- && !is_runtime_conformable (expr1, expr2))
+ if (realloc_flag)
{
realloc_lhs_warning (expr1->ts.type, true, &expr1->where);
ompws_flags &= ~OMPWS_SCALARIZER_WS;
@@ -11298,8 +11551,7 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
return tmp;
}
- if (UNLIMITED_POLY (expr1) && expr1->rank
- && expr2->ts.type != BT_CLASS)
+ if (UNLIMITED_POLY (expr1) && expr1->rank)
use_vptr_copy = true;
/* Fallback to the scalarizer to generate explicit loops. */
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 912c9b0..13c3295 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -40,6 +40,8 @@ along with GCC; see the file COPYING3. If not see
#include "trans-types.h"
#include "trans-array.h"
#include "dependency.h" /* For CAF array alias analysis. */
+#include "attribs.h"
+
/* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
#include "trans-stmt.h"
@@ -4277,10 +4279,69 @@ remove_empty_actual_arguments (gfc_actual_arglist **ap)
}
}
+#define MAX_SPEC_ARG 12
+
+/* Make up an fn spec that's right for intrinsic functions that we
+ want to call. */
+
+static char *
+intrinsic_fnspec (gfc_expr *expr)
+{
+ static char fnspec_buf[MAX_SPEC_ARG*2+1];
+ char *fp;
+ int i;
+ int num_char_args;
+
+#define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
+
+ /* Set the fndecl. */
+ fp = fnspec_buf;
+ /* Function return value. FIXME: Check if the second letter could
+ be something other than a space, for further optimization. */
+ ADD_CHAR ('.');
+ if (expr->rank == 0)
+ {
+ if (expr->ts.type == BT_CHARACTER)
+ {
+ ADD_CHAR ('w'); /* Address of character. */
+ ADD_CHAR ('.'); /* Length of character. */
+ }
+ }
+ else
+ ADD_CHAR ('w'); /* Return value is a descriptor. */
+
+ num_char_args = 0;
+ for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
+ {
+ if (a->expr == NULL)
+ continue;
+
+ if (a->name && strcmp (a->name,"%VAL") == 0)
+ ADD_CHAR ('.');
+ else
+ {
+ if (a->expr->rank > 0)
+ ADD_CHAR ('r');
+ else
+ ADD_CHAR ('R');
+ }
+ num_char_args += a->expr->ts.type == BT_CHARACTER;
+ gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2);
+ }
+
+ for (i = 0; i < num_char_args; i++)
+ ADD_CHAR ('.');
+
+ *fp = '\0';
+ return fnspec_buf;
+}
+
+#undef MAX_SPEC_ARG
+#undef ADD_CHAR
+
/* Generate the right symbol for the specific intrinsic function and
modify the expr accordingly. This assumes that absent optional
- arguments should be removed. FIXME: This should be extended for
- procedures which do not ignore optional arguments (PR 97454). */
+ arguments should be removed. */
gfc_symbol *
specific_intrinsic_symbol (gfc_expr *expr)
@@ -4298,14 +4359,19 @@ specific_intrinsic_symbol (gfc_expr *expr)
gfc_copy_formal_args_intr (sym, expr->value.function.isym,
expr->value.function.actual, true);
sym->backend_decl
- = gfc_get_extern_function_decl (sym, expr->value.function.actual);
+ = gfc_get_extern_function_decl (sym, expr->value.function.actual,
+ intrinsic_fnspec (expr));
}
+
remove_empty_actual_arguments (&(expr->value.function.actual));
return sym;
}
-/* Generate a call to an external intrinsic function. */
+/* Generate a call to an external intrinsic function. FIXME: So far,
+ this only works for functions which are called with well-defined
+ types; CSHIFT and friends will come later. */
+
static void
gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
{
@@ -4322,11 +4388,16 @@ gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
switch (expr->value.function.isym->id)
{
+ case GFC_ISYM_ANY:
+ case GFC_ISYM_ALL:
case GFC_ISYM_FINDLOC:
case GFC_ISYM_MAXLOC:
case GFC_ISYM_MINLOC:
case GFC_ISYM_MAXVAL:
case GFC_ISYM_MINVAL:
+ case GFC_ISYM_NORM2:
+ case GFC_ISYM_PRODUCT:
+ case GFC_ISYM_SUM:
specific_symbol = true;
break;
default:
@@ -7949,6 +8020,35 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
&& strcmp (e->ref->u.c.component->name, "_data") == 0)
sym = e->symtree->n.sym;
+ if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER)
+ && e
+ && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION))
+ {
+ symbol_attribute attr;
+ char *msg;
+
+ attr = gfc_expr_attr (e);
+ if (attr.allocatable)
+ msg = xasprintf ("Allocatable argument '%s' is not allocated",
+ e->symtree->n.sym->name);
+ else if (attr.pointer)
+ msg = xasprintf ("Pointer argument '%s' is not associated",
+ e->symtree->n.sym->name);
+ else
+ goto end_arg_check;
+
+ argse.descriptor_only = 1;
+ gfc_conv_expr_descriptor (&argse, actual->expr);
+ tree temp = gfc_conv_descriptor_data_get (argse.expr);
+ tree cond = fold_build2_loc (input_location, EQ_EXPR,
+ logical_type_node, temp,
+ fold_convert (TREE_TYPE (temp),
+ null_pointer_node));
+ gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg);
+ free (msg);
+ }
+ end_arg_check:
+
argse.data_not_needed = 1;
if (gfc_is_class_array_function (e))
{
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index bd7e13d..ae29064 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -626,6 +626,8 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_LINEAR:
case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
break;
default:
gcc_unreachable ();
@@ -699,7 +701,9 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
then_b = gfc_finish_block (&cond_block);
/* Reduction clause requires allocated ALLOCATABLE. */
- if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION)
+ if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION
+ && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION)
{
gfc_init_block (&cond_block);
if (GFC_DESCRIPTOR_TYPE_P (type))
@@ -2029,9 +2033,25 @@ gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
}
static tree
-gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
+gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
locus where, bool mark_addressable)
{
+ omp_clause_code clause = OMP_CLAUSE_REDUCTION;
+ switch (kind)
+ {
+ case OMP_LIST_REDUCTION:
+ case OMP_LIST_REDUCTION_INSCAN:
+ case OMP_LIST_REDUCTION_TASK:
+ break;
+ case OMP_LIST_IN_REDUCTION:
+ clause = OMP_CLAUSE_IN_REDUCTION;
+ break;
+ case OMP_LIST_TASK_REDUCTION:
+ clause = OMP_CLAUSE_TASK_REDUCTION;
+ break;
+ default:
+ gcc_unreachable ();
+ }
for (; namelist != NULL; namelist = namelist->next)
if (namelist->sym->attr.referenced)
{
@@ -2039,10 +2059,14 @@ gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
if (t != error_mark_node)
{
tree node = build_omp_clause (gfc_get_location (&namelist->where),
- OMP_CLAUSE_REDUCTION);
+ clause);
OMP_CLAUSE_DECL (node) = t;
if (mark_addressable)
TREE_ADDRESSABLE (t) = 1;
+ if (kind == OMP_LIST_REDUCTION_INSCAN)
+ OMP_CLAUSE_REDUCTION_INSCAN (node) = 1;
+ if (kind == OMP_LIST_REDUCTION_TASK)
+ OMP_CLAUSE_REDUCTION_TASK (node) = 1;
switch (namelist->u.reduction_op)
{
case OMP_REDUCTION_PLUS:
@@ -2267,10 +2291,14 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
switch (list)
{
case OMP_LIST_REDUCTION:
+ case OMP_LIST_REDUCTION_INSCAN:
+ case OMP_LIST_REDUCTION_TASK:
+ case OMP_LIST_IN_REDUCTION:
+ case OMP_LIST_TASK_REDUCTION:
/* An OpenACC async clause indicates the need to set reduction
arguments addressable, to allow asynchronous copy-out. */
- omp_clauses = gfc_trans_omp_reduction_list (n, omp_clauses, where,
- clauses->async);
+ omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
+ where, clauses->async);
break;
case OMP_LIST_PRIVATE:
clause_code = OMP_CLAUSE_PRIVATE;
@@ -2306,6 +2334,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_LIST_NONTEMPORAL:
clause_code = OMP_CLAUSE_NONTEMPORAL;
goto add_clause;
+ case OMP_LIST_SCAN_IN:
+ clause_code = OMP_CLAUSE_INCLUSIVE;
+ goto add_clause;
+ case OMP_LIST_SCAN_EX:
+ clause_code = OMP_CLAUSE_EXCLUSIVE;
+ goto add_clause;
add_clause:
omp_clauses
@@ -3771,34 +3805,38 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
}
if (clauses->vector)
{
+ c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+
if (clauses->vector_expr)
{
tree vector_var
= gfc_convert_expr_to_tree (block, clauses->vector_expr);
- c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- else
- {
- c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+
+ /* TODO: We're not capturing location information for individual
+ clauses. However, if we have an expression attached to the
+ clause, that one provides better location information. */
+ OMP_CLAUSE_LOCATION (c)
+ = gfc_get_location (&clauses->vector_expr->where);
}
}
if (clauses->worker)
{
+ c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+
if (clauses->worker_expr)
{
tree worker_var
= gfc_convert_expr_to_tree (block, clauses->worker_expr);
- c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- else
- {
- c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+
+ /* TODO: We're not capturing location information for individual
+ clauses. However, if we have an expression attached to the
+ clause, that one provides better location information. */
+ OMP_CLAUSE_LOCATION (c)
+ = gfc_get_location (&clauses->worker_expr->where);
}
}
if (clauses->gang)
@@ -3806,11 +3844,19 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
tree arg;
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+
if (clauses->gang_num_expr)
{
arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
OMP_CLAUSE_GANG_EXPR (c) = arg;
+
+ /* TODO: We're not capturing location information for individual
+ clauses. However, if we have an expression attached to the
+ clause, that one provides better location information. */
+ OMP_CLAUSE_LOCATION (c)
+ = gfc_get_location (&clauses->gang_num_expr->where);
}
+
if (clauses->gang_static)
{
arg = clauses->gang_static_expr
@@ -3882,8 +3928,8 @@ gfc_trans_oacc_construct (gfc_code *code)
oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
code->loc, false, true);
stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
- oacc_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
+ void_type_node, stmt, oacc_clauses);
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
}
@@ -3967,7 +4013,7 @@ static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
static tree
gfc_trans_omp_atomic (gfc_code *code)
{
- gfc_code *atomic_code = code;
+ gfc_code *atomic_code = code->block;
gfc_se lse;
gfc_se rse;
gfc_se vse;
@@ -3979,12 +4025,16 @@ gfc_trans_omp_atomic (gfc_code *code)
enum tree_code aop = OMP_ATOMIC;
bool var_on_left = false;
enum omp_memory_order mo;
- if (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST)
- mo = OMP_MEMORY_ORDER_SEQ_CST;
- else if (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_ACQ_REL)
- mo = OMP_MEMORY_ORDER_ACQ_REL;
- else
- mo = OMP_MEMORY_ORDER_RELAXED;
+ switch (atomic_code->ext.omp_clauses->memorder)
+ {
+ case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
+ case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break;
+ case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break;
+ case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break;
+ case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break;
+ case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
+ default: gcc_unreachable ();
+ }
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
@@ -3996,16 +4046,16 @@ gfc_trans_omp_atomic (gfc_code *code)
gfc_start_block (&block);
expr2 = code->expr2;
- if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
!= GFC_OMP_ATOMIC_WRITE)
&& expr2->expr_type == EXPR_FUNCTION
&& expr2->value.function.isym
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
- switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
+ == GFC_OMP_ATOMIC_READ)
{
- case GFC_OMP_ATOMIC_READ:
gfc_conv_expr (&vse, code->expr1);
gfc_add_block_to_block (&block, &vse.pre);
@@ -4023,7 +4073,9 @@ gfc_trans_omp_atomic (gfc_code *code)
gfc_add_block_to_block (&block, &rse.pre);
return gfc_finish_block (&block);
- case GFC_OMP_ATOMIC_CAPTURE:
+ }
+ if (atomic_code->ext.omp_clauses->capture)
+ {
aop = OMP_ATOMIC_CAPTURE_NEW;
if (expr2->expr_type == EXPR_VARIABLE)
{
@@ -4042,9 +4094,6 @@ gfc_trans_omp_atomic (gfc_code *code)
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
}
- break;
- default:
- break;
}
gfc_conv_expr (&lse, code->expr1);
@@ -4052,9 +4101,9 @@ gfc_trans_omp_atomic (gfc_code *code)
type = TREE_TYPE (lse.expr);
lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
- if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
== GFC_OMP_ATOMIC_WRITE)
- || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
+ || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP))
{
gfc_conv_expr (&rse, expr2);
gfc_add_block_to_block (&block, &rse.pre);
@@ -4190,9 +4239,9 @@ gfc_trans_omp_atomic (gfc_code *code)
rhs = gfc_evaluate_now (rse.expr, &block);
- if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
== GFC_OMP_ATOMIC_WRITE)
- || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
+ || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP))
x = rhs;
else
{
@@ -4664,7 +4713,31 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
code->exit_label = NULL_TREE;
/* Main loop body. */
- tmp = gfc_trans_omp_code (code->block->next, true);
+ if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
+ {
+ gcc_assert (code->block->next->next->op == EXEC_OMP_SCAN);
+ gcc_assert (code->block->next->next->next->next == NULL);
+ locus *cloc = &code->block->next->next->loc;
+ location_t loc = gfc_get_location (cloc);
+
+ gfc_code code2 = *code->block->next;
+ code2.next = NULL;
+ tmp = gfc_trans_code (&code2);
+ tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
+ SET_EXPR_LOCATION (tmp, loc);
+ gfc_add_expr_to_block (&body, tmp);
+ input_location = loc;
+ tree c = gfc_trans_omp_clauses (&body,
+ code->block->next->next->ext.omp_clauses,
+ *cloc);
+ code2 = *code->block->next->next->next;
+ code2.next = NULL;
+ tmp = gfc_trans_code (&code2);
+ tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
+ SET_EXPR_LOCATION (tmp, loc);
+ }
+ else
+ tmp = gfc_trans_omp_code (code->block->next, true);
gfc_add_expr_to_block (&body, tmp);
/* Label for cycle statements (if needed). */
@@ -4791,7 +4864,7 @@ gfc_trans_omp_flush (gfc_code *code)
{
tree call;
if (!code->ext.omp_clauses
- || code->ext.omp_clauses->memorder == OMP_MEMORDER_LAST)
+ || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET)
{
call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
call = build_call_expr_loc (input_location, call, 0);
@@ -5191,19 +5264,30 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
/* Reduction is allowed on simd, do, parallel and teams.
Duplicate it on all of them, but omit on do if
- parallel is present. */
- if (mask & GFC_OMP_MASK_TEAMS)
- clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- if (mask & GFC_OMP_MASK_PARALLEL)
- clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- else if (mask & GFC_OMP_MASK_DO)
- clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- if (mask & GFC_OMP_MASK_SIMD)
- clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
+ parallel is present; additionally, inscan applies to do/simd only. */
+ for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
+ {
+ if (mask & GFC_OMP_MASK_TEAMS
+ && i != OMP_LIST_REDUCTION_INSCAN)
+ clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ if (mask & GFC_OMP_MASK_PARALLEL
+ && i != OMP_LIST_REDUCTION_INSCAN)
+ clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ else if (mask & GFC_OMP_MASK_DO)
+ clausesa[GFC_OMP_SPLIT_DO].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ if (mask & GFC_OMP_MASK_SIMD)
+ clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ }
+ if (mask & GFC_OMP_MASK_TARGET)
+ clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
+ = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
+ if (mask & GFC_OMP_MASK_TASKLOOP)
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
+ = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
/* Linear clause is supported on do and simd,
put it on the innermost one. */
clausesa[innermost].lists[OMP_LIST_LINEAR]
@@ -5299,8 +5383,8 @@ gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
}
else if (TREE_CODE (stmt) != BIND_EXPR)
stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
+ void_type_node, stmt, omp_clauses);
OMP_PARALLEL_COMBINED (stmt) = 1;
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
@@ -5342,8 +5426,8 @@ gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
if (flag_openmp)
{
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
+ void_type_node, stmt, omp_clauses);
OMP_PARALLEL_COMBINED (stmt) = 1;
}
gfc_add_expr_to_block (&block, stmt);
@@ -5369,8 +5453,8 @@ gfc_trans_omp_parallel_sections (gfc_code *code)
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
else
poplevel (0, 0);
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
+ void_type_node, stmt, omp_clauses);
OMP_PARALLEL_COMBINED (stmt) = 1;
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
@@ -5392,8 +5476,8 @@ gfc_trans_omp_parallel_workshare (gfc_code *code)
pushlevel ();
stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
+ void_type_node, stmt, omp_clauses);
OMP_PARALLEL_COMBINED (stmt) = 1;
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
@@ -5405,6 +5489,7 @@ gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
stmtblock_t block, body;
tree omp_clauses, stmt;
bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
+ location_t loc = gfc_get_location (&code->loc);
gfc_start_block (&block);
@@ -5425,8 +5510,7 @@ gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
}
stmt = gfc_finish_block (&body);
- stmt = build2_loc (input_location, OMP_SECTIONS, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
@@ -5437,8 +5521,8 @@ gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
{
tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
tree stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, OMP_SINGLE, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
+ stmt, omp_clauses);
return stmt;
}
@@ -5454,8 +5538,8 @@ gfc_trans_omp_task (gfc_code *code)
pushlevel ();
stmt = gfc_trans_omp_code (code->block->next, true);
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- stmt = build2_loc (input_location, OMP_TASK, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
+ stmt, omp_clauses);
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
}
@@ -5597,8 +5681,8 @@ gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
if (flag_openmp)
{
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
+ void_type_node, stmt, omp_clauses);
if (combined)
OMP_TEAMS_COMBINED (stmt) = 1;
}
@@ -5701,8 +5785,8 @@ gfc_trans_omp_target (gfc_code *code)
}
if (flag_openmp)
{
- stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
+ void_type_node, stmt, omp_clauses);
if (code->op != EXEC_OMP_TARGET)
OMP_TARGET_COMBINED (stmt) = 1;
cfun->has_omp_target = true;
@@ -5763,8 +5847,8 @@ gfc_trans_omp_target_data (gfc_code *code)
omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
code->loc);
stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, OMP_TARGET_DATA, void_type_node, stmt,
- omp_clauses);
+ stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
+ void_type_node, stmt, omp_clauses);
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
}
@@ -5824,6 +5908,7 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
bool singleblock_in_progress = false;
/* True if previous gfc_code in workshare construct is not workshared. */
bool prev_singleunit;
+ location_t loc = gfc_get_location (&code->loc);
code = code->block->next;
@@ -5914,7 +5999,7 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
{
/* Finish single block and add it to pblock. */
tmp = gfc_finish_block (&singleblock);
- tmp = build2_loc (input_location, OMP_SINGLE,
+ tmp = build2_loc (loc, OMP_SINGLE,
void_type_node, tmp, NULL_TREE);
gfc_add_expr_to_block (pblock, tmp);
/* Add current gfc_code to pblock. */
@@ -5930,6 +6015,7 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
gfc_init_block (&singleblock);
gfc_add_expr_to_block (&singleblock, res);
singleblock_in_progress = true;
+ loc = gfc_get_location (&code->loc);
}
else
/* Add the new statement to the block. */
@@ -5944,7 +6030,7 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
{
/* Finish single block and add it to pblock. */
tmp = gfc_finish_block (&singleblock);
- tmp = build2_loc (input_location, OMP_SINGLE, void_type_node, tmp,
+ tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
clauses->nowait
? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
: NULL_TREE);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 09f6327..afbf786 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -1841,7 +1841,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
if (e->ts.type == BT_CLASS)
{
/* Go straight to the class data. */
- if (sym2->attr.dummy)
+ if (sym2->attr.dummy && !sym2->attr.optional)
{
class_decl = DECL_LANG_SPECIFIC (sym2->backend_decl) ?
GFC_DECL_SAVED_DESCRIPTOR (sym2->backend_decl) :
@@ -4006,9 +4006,10 @@ check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
point to the copy instead. Note that the shallow copy of
the variable will not suffice for derived types with
pointer components. We therefore leave these to their
- own devices. */
+ own devices. Likewise for allocatable components. */
if (lsym->ts.type == BT_DERIVED
- && lsym->ts.u.derived->attr.pointer_comp)
+ && (lsym->ts.u.derived->attr.pointer_comp
+ || lsym->ts.u.derived->attr.alloc_comp))
return need_temp;
new_symtree = NULL;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 4cd53ad..c5924a0 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "trans-array.h"
#include "dwarf2out.h" /* For struct array_descr_info. */
#include "attribs.h"
+#include "alias.h"
#if (GFC_MAX_DIMENSIONS < 10)
@@ -1914,6 +1915,10 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
base_type = gfc_get_array_descriptor_base (dimen, codimen, false);
TYPE_CANONICAL (fat_type) = base_type;
TYPE_STUB_DECL (fat_type) = TYPE_STUB_DECL (base_type);
+ /* Arrays of unknown type must alias with all array descriptors. */
+ TYPE_TYPELESS_STORAGE (base_type) = 1;
+ TYPE_TYPELESS_STORAGE (fat_type) = 1;
+ gcc_checking_assert (!get_alias_set (base_type) && !get_alias_set (fat_type));
tmp = TYPE_NAME (etype);
if (tmp && TREE_CODE (tmp) == TYPE_DECL)
@@ -3035,7 +3040,8 @@ create_fn_spec (gfc_symbol *sym, tree fntype)
}
tree
-gfc_get_function_type (gfc_symbol * sym, gfc_actual_arglist *actual_args)
+gfc_get_function_type (gfc_symbol * sym, gfc_actual_arglist *actual_args,
+ const char *fnspec)
{
tree type;
vec<tree, va_gc> *typelist = NULL;
@@ -3219,7 +3225,19 @@ arg_type_list_done:
type = build_varargs_function_type_vec (type, typelist);
else
type = build_function_type_vec (type, typelist);
- type = create_fn_spec (sym, type);
+
+ /* If we were passed an fn spec, add it here, otherwise determine it from
+ the formal arguments. */
+ if (fnspec)
+ {
+ tree tmp;
+ int spec_len = strlen (fnspec);
+ tmp = build_tree_list (NULL_TREE, build_string (spec_len, fnspec));
+ tmp = tree_cons (get_identifier ("fn spec"), tmp, TYPE_ATTRIBUTES (type));
+ type = build_type_attribute_variant (type, tmp);
+ }
+ else
+ type = create_fn_spec (sym, type);
return type;
}
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index 56074f1..1b59287 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -88,7 +88,8 @@ tree gfc_sym_type (gfc_symbol *);
tree gfc_typenode_for_spec (gfc_typespec *, int c = 0);
int gfc_copy_dt_decls_ifequal (gfc_symbol *, gfc_symbol *, bool);
-tree gfc_get_function_type (gfc_symbol *, gfc_actual_arglist *args = NULL);
+tree gfc_get_function_type (gfc_symbol *, gfc_actual_arglist *args = NULL,
+ const char *fnspec = NULL);
tree gfc_type_for_size (unsigned, int);
tree gfc_type_for_mode (machine_mode, int);
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 57a344a..5a0004e 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -512,21 +512,7 @@ gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
/* Check if this is an unlimited polymorphic object carrying a character
payload. In this case, the 'len' field is non-zero. */
if (decl && GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
- {
- tmp = gfc_class_len_or_zero_get (decl);
- if (!integer_zerop (tmp))
- {
- tree cond;
- tree stype = TREE_TYPE (span);
- tmp = fold_convert (stype, tmp);
- cond = fold_build2_loc (input_location, EQ_EXPR,
- logical_type_node, tmp,
- build_int_cst (stype, 0));
- tmp = fold_build2 (MULT_EXPR, stype, span, tmp);
- span = fold_build3_loc (input_location, COND_EXPR, stype,
- cond, span, tmp);
- }
- }
+ span = gfc_resize_class_size_with_len (NULL, decl, span);
}
else if (decl)
span = get_array_span (type, decl);
@@ -1925,7 +1911,7 @@ void
gfc_set_backend_locus (locus * loc)
{
gfc_current_backend_file = loc->lb->file;
- input_location = loc->lb->location;
+ input_location = gfc_get_location (loc);
}
@@ -1935,7 +1921,10 @@ gfc_set_backend_locus (locus * loc)
void
gfc_restore_backend_locus (locus * loc)
{
- gfc_set_backend_locus (loc);
+ /* This only restores the information captured by gfc_save_backend_locus,
+ intentionally does not use gfc_get_location. */
+ input_location = loc->lb->location;
+ gfc_current_backend_file = loc->lb->file;
free (loc->lb);
}
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 9a3a72c..306cf42 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -427,6 +427,7 @@ tree gfc_class_data_get (tree);
tree gfc_class_vptr_get (tree);
tree gfc_class_len_get (tree);
tree gfc_class_len_or_zero_get (tree);
+tree gfc_resize_class_size_with_len (stmtblock_t *, tree, tree);
gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *, bool is_mold = false);
/* Get an accessor to the class' vtab's * field, when a class handle is
available. */
@@ -446,6 +447,7 @@ tree gfc_vptr_final_get (tree);
tree gfc_vptr_deallocate_get (tree);
void gfc_reset_vptr (stmtblock_t *, gfc_expr *);
void gfc_reset_len (stmtblock_t *, gfc_expr *);
+tree gfc_get_class_from_gfc_expr (gfc_expr *);
tree gfc_get_class_from_expr (tree);
tree gfc_get_vptr_from_expr (tree);
tree gfc_get_class_array_ref (tree, tree, tree, bool);
@@ -616,7 +618,8 @@ tree gfc_get_label_decl (gfc_st_label *);
/* Return the decl for an external function. */
tree gfc_get_extern_function_decl (gfc_symbol *,
- gfc_actual_arglist *args = NULL);
+ gfc_actual_arglist *args = NULL,
+ const char *fnspec = NULL);
/* Return the decl for a function. */
tree gfc_get_function_decl (gfc_symbol *);
diff --git a/gcc/fortran/types.def b/gcc/fortran/types.def
index 7b4925c..5736bba 100644
--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def
@@ -70,6 +70,7 @@ DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PTR,
build_pointer_type
(build_qualified_type (void_type_node,
TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
+DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
DEF_POINTER_TYPE (BT_PTR_ULONGLONG, BT_ULONGLONG)
DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
@@ -117,6 +118,8 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
BT_CONST_VOLATILE_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE,
+ BT_VOID, BT_PTR, BT_PTRMODE)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
@@ -149,6 +152,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16,
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_SIZE_SIZE_PTR, BT_VOID, BT_SIZE, BT_SIZE,
BT_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_PTR_PTR, BT_UINT, BT_UINT, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_SIZE_PTRMODE,
+ BT_PTR, BT_SIZE, BT_SIZE, BT_PTRMODE)
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
diff --git a/gcc/function-tests.c b/gcc/function-tests.c
index 6536458..92f1acf 100644
--- a/gcc/function-tests.c
+++ b/gcc/function-tests.c
@@ -580,6 +580,7 @@ test_ranges ()
function *fun = DECL_STRUCT_FUNCTION (fndecl);
push_cfun (fun);
range_tests ();
+ range_op_tests ();
pop_cfun ();
}
diff --git a/gcc/function.c b/gcc/function.c
index f903a1e..af9618e 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -46,10 +46,12 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "expmed.h"
#include "optabs.h"
+#include "opts.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
#include "rtl-error.h"
+#include "hard-reg-set.h"
#include "alias.h"
#include "fold-const.h"
#include "stor-layout.h"
@@ -2204,13 +2206,15 @@ use_register_for_decl (const_tree decl)
/* Otherwise, if RESULT_DECL is DECL_BY_REFERENCE, it will take
the function_result_decl's assignment. Since it's a pointer,
we can short-circuit a number of the tests below, and we must
- duplicat e them because we don't have the
- function_result_decl to test. */
+ duplicate them because we don't have the function_result_decl
+ to test. */
if (!targetm.calls.allocate_stack_slots_for_args ())
return true;
/* We don't set DECL_IGNORED_P for the function_result_decl. */
if (optimize)
return true;
+ if (cfun->tail_call_marked)
+ return true;
/* We don't set DECL_REGISTER for the function_result_decl. */
return false;
}
@@ -5815,6 +5819,107 @@ make_prologue_seq (void)
return seq;
}
+/* Emit a sequence of insns to zero the call-used registers before RET
+ according to ZERO_REGS_TYPE. */
+
+static void
+gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
+{
+ bool only_gpr = true;
+ bool only_used = true;
+ bool only_arg = true;
+
+ /* No need to zero call-used-regs in main (). */
+ if (MAIN_NAME_P (DECL_NAME (current_function_decl)))
+ return;
+
+ /* No need to zero call-used-regs if __builtin_eh_return is called
+ since it isn't a normal function return. */
+ if (crtl->calls_eh_return)
+ return;
+
+ /* If only_gpr is true, only zero call-used registers that are
+ general-purpose registers; if only_used is true, only zero
+ call-used registers that are used in the current function;
+ if only_arg is true, only zero call-used registers that pass
+ parameters defined by the flatform's calling conversion. */
+
+ using namespace zero_regs_flags;
+
+ only_gpr = zero_regs_type & ONLY_GPR;
+ only_used = zero_regs_type & ONLY_USED;
+ only_arg = zero_regs_type & ONLY_ARG;
+
+ /* For each of the hard registers, we should zero it if:
+ 1. it is a call-used register;
+ and 2. it is not a fixed register;
+ and 3. it is not live at the return of the routine;
+ and 4. it is general registor if only_gpr is true;
+ and 5. it is used in the routine if only_used is true;
+ and 6. it is a register that passes parameter if only_arg is true. */
+
+ /* First, prepare the data flow information. */
+ basic_block bb = BLOCK_FOR_INSN (ret);
+ auto_bitmap live_out;
+ bitmap_copy (live_out, df_get_live_out (bb));
+ df_simulate_initialize_backwards (bb, live_out);
+ df_simulate_one_insn_backwards (bb, ret, live_out);
+
+ HARD_REG_SET selected_hardregs;
+ CLEAR_HARD_REG_SET (selected_hardregs);
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ if (!crtl->abi->clobbers_full_reg_p (regno))
+ continue;
+ if (fixed_regs[regno])
+ continue;
+ if (REGNO_REG_SET_P (live_out, regno))
+ continue;
+ if (only_gpr
+ && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], regno))
+ continue;
+ if (only_used && !df_regs_ever_live_p (regno))
+ continue;
+ if (only_arg && !FUNCTION_ARG_REGNO_P (regno))
+ continue;
+#ifdef LEAF_REG_REMAP
+ if (crtl->uses_only_leaf_regs && LEAF_REG_REMAP (regno) < 0)
+ continue;
+#endif
+
+ /* Now this is a register that we might want to zero. */
+ SET_HARD_REG_BIT (selected_hardregs, regno);
+ }
+
+ if (hard_reg_set_empty_p (selected_hardregs))
+ return;
+
+ /* Now that we have a hard register set that needs to be zeroed, pass it to
+ target to generate zeroing sequence. */
+ HARD_REG_SET zeroed_hardregs;
+ start_sequence ();
+ zeroed_hardregs = targetm.calls.zero_call_used_regs (selected_hardregs);
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ if (seq)
+ {
+ /* Emit the memory blockage and register clobber asm volatile before
+ the whole sequence. */
+ start_sequence ();
+ expand_asm_reg_clobber_mem_blockage (zeroed_hardregs);
+ rtx_insn *seq_barrier = get_insns ();
+ end_sequence ();
+
+ emit_insn_before (seq_barrier, ret);
+ emit_insn_before (seq, ret);
+
+ /* Update the data flow information. */
+ crtl->must_be_zero_on_return |= zeroed_hardregs;
+ df_set_bb_dirty (EXIT_BLOCK_PTR_FOR_FN (cfun));
+ }
+}
+
+
/* Return a sequence to be used as the epilogue for the current function,
or NULL. */
@@ -6486,7 +6591,96 @@ make_pass_thread_prologue_and_epilogue (gcc::context *ctxt)
{
return new pass_thread_prologue_and_epilogue (ctxt);
}
-
+
+namespace {
+
+const pass_data pass_data_zero_call_used_regs =
+{
+ RTL_PASS, /* type */
+ "zero_call_used_regs", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_zero_call_used_regs: public rtl_opt_pass
+{
+public:
+ pass_zero_call_used_regs (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_zero_call_used_regs, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *);
+
+}; // class pass_zero_call_used_regs
+
+unsigned int
+pass_zero_call_used_regs::execute (function *fun)
+{
+ using namespace zero_regs_flags;
+ unsigned int zero_regs_type = UNSET;
+
+ tree attr_zero_regs = lookup_attribute ("zero_call_used_regs",
+ DECL_ATTRIBUTES (fun->decl));
+
+ /* Get the type of zero_call_used_regs from function attribute.
+ We have filtered out invalid attribute values already at this point. */
+ if (attr_zero_regs)
+ {
+ /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE
+ is the attribute argument's value. */
+ attr_zero_regs = TREE_VALUE (attr_zero_regs);
+ gcc_assert (TREE_CODE (attr_zero_regs) == TREE_LIST);
+ attr_zero_regs = TREE_VALUE (attr_zero_regs);
+ gcc_assert (TREE_CODE (attr_zero_regs) == STRING_CST);
+
+ for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
+ if (strcmp (TREE_STRING_POINTER (attr_zero_regs),
+ zero_call_used_regs_opts[i].name) == 0)
+ {
+ zero_regs_type = zero_call_used_regs_opts[i].flag;
+ break;
+ }
+ }
+
+ if (!zero_regs_type)
+ zero_regs_type = flag_zero_call_used_regs;
+
+ /* No need to zero call-used-regs when no user request is present. */
+ if (!(zero_regs_type & ENABLED))
+ return 0;
+
+ edge_iterator ei;
+ edge e;
+
+ /* This pass needs data flow information. */
+ df_analyze ();
+
+ /* Iterate over the function's return instructions and insert any
+ register zeroing required by the -fzero-call-used-regs command-line
+ option or the "zero_call_used_regs" function attribute. */
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+ {
+ rtx_insn *insn = BB_END (e->src);
+ if (JUMP_P (insn) && ANY_RETURN_P (JUMP_LABEL (insn)))
+ gen_call_used_regs_seq (insn, zero_regs_type);
+ }
+
+ return 0;
+}
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_zero_call_used_regs (gcc::context *ctxt)
+{
+ return new pass_zero_call_used_regs (ctxt);
+}
/* If CONSTRAINT is a matching constraint, then return its number.
Otherwise, return -1. */
diff --git a/gcc/function.h b/gcc/function.h
index d55cbdd..dbe8a58 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -269,6 +269,13 @@ struct GTY(()) function {
/* Value histograms attached to particular statements. */
htab_t GTY((skip)) value_histograms;
+ /* Different from normal TODO_flags which are handled right at the
+ beginning or the end of one pass execution, the pending_TODOs
+ are passed down in the pipeline until one of its consumers can
+ perform the requested action. Consumers should then clear the
+ flags for the actions that they have taken. */
+ unsigned int pending_TODOs;
+
/* For function.c. */
/* Points to the FUNCTION_DECL of this function. */
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index 756c1d6..2d2d4b6 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -18,32 +18,28 @@ 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/>. */
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
-#include "target.h"
#include "rtl.h"
-#include "predict.h"
#include "df.h"
-#include "memmodel.h"
-#include "tm_p.h"
-#include "insn-config.h"
-#include "emit-rtl.h"
-#include "recog.h"
+#include "rtl-ssa.h"
#include "sparseset.h"
+#include "predict.h"
#include "cfgrtl.h"
#include "cfgcleanup.h"
#include "cfgloop.h"
#include "tree-pass.h"
-#include "domwalk.h"
#include "rtl-iter.h"
-
+#include "target.h"
/* This pass does simple forward propagation and simplification when an
operand of an insn can only come from a single def. This pass uses
- df.c, so it is global. However, we only do limited analysis of
+ RTL SSA, so it is global. However, we only do limited analysis of
available expressions.
1) The pass tries to propagate the source of the def into the use,
@@ -60,9 +56,9 @@ along with GCC; see the file COPYING3. If not see
(set (subreg:SI (reg:DI 120) 0) (const_int 0))
(set (subreg:SI (reg:DI 120) 4) (const_int -1))
(set (subreg:SI (reg:DI 122) 0)
- (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0)))
+ (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0)))
(set (subreg:SI (reg:DI 122) 4)
- (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4)))
+ (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4)))
can be simplified to the much simpler
@@ -89,7 +85,7 @@ along with GCC; see the file COPYING3. If not see
(set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
(set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
(set (reg:SI 122) (plus:SI (subreg:SI (reg:QI 120) 0)
- (subreg:SI (reg:QI 121) 0)))
+ (subreg:SI (reg:QI 121) 0)))
are very common on machines that can only do word-sized operations.
For each use of a paradoxical subreg (subreg:WIDER (reg:NARROW N) 0),
@@ -101,218 +97,12 @@ along with GCC; see the file COPYING3. If not see
(set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
(set (reg:SI 122) (plus:SI (reg:SI 118) (reg:SI 119)))
- where the first two insns are now dead.
-
- We used to use reaching definitions to find which uses have a
- single reaching definition (sounds obvious...), but this is too
- complex a problem in nasty testcases like PR33928. Now we use the
- multiple definitions problem in df-problems.c. The similarity
- between that problem and SSA form creation is taken further, in
- that fwprop does a dominator walk to create its chains; however,
- instead of creating a PHI function where multiple definitions meet
- I just punt and record only singleton use-def chains, which is
- all that is needed by fwprop. */
+ where the first two insns are now dead. */
+using namespace rtl_ssa;
static int num_changes;
-static vec<df_ref> use_def_ref;
-static vec<df_ref> reg_defs;
-static vec<df_ref> reg_defs_stack;
-
-/* The maximum number of propagations that are still allowed. If we do
- more propagations than originally we had uses, we must have ended up
- in a propagation loop, as in PR79405. Until the algorithm fwprop
- uses can obviously not get into such loops we need a workaround like
- this. */
-static int propagations_left;
-
-/* The MD bitmaps are trimmed to include only live registers to cut
- memory usage on testcases like insn-recog.c. Track live registers
- in the basic block and do not perform forward propagation if the
- destination is a dead pseudo occurring in a note. */
-static bitmap local_md;
-static bitmap local_lr;
-
-/* Return the only def in USE's use-def chain, or NULL if there is
- more than one def in the chain. */
-
-static inline df_ref
-get_def_for_use (df_ref use)
-{
- return use_def_ref[DF_REF_ID (use)];
-}
-
-
-/* Update the reg_defs vector with non-partial definitions in DEF_REC.
- TOP_FLAG says which artificials uses should be used, when DEF_REC
- is an artificial def vector. LOCAL_MD is modified as after a
- df_md_simulate_* function; we do more or less the same processing
- done there, so we do not use those functions. */
-
-#define DF_MD_GEN_FLAGS \
- (DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER)
-
-static void
-process_defs (df_ref def, int top_flag)
-{
- for (; def; def = DF_REF_NEXT_LOC (def))
- {
- df_ref curr_def = reg_defs[DF_REF_REGNO (def)];
- unsigned int dregno;
-
- if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) != top_flag)
- continue;
-
- dregno = DF_REF_REGNO (def);
- if (curr_def)
- reg_defs_stack.safe_push (curr_def);
- else
- {
- /* Do not store anything if "transitioning" from NULL to NULL. But
- otherwise, push a special entry on the stack to tell the
- leave_block callback that the entry in reg_defs was NULL. */
- if (DF_REF_FLAGS (def) & DF_MD_GEN_FLAGS)
- ;
- else
- reg_defs_stack.safe_push (def);
- }
-
- if (DF_REF_FLAGS (def) & DF_MD_GEN_FLAGS)
- {
- bitmap_set_bit (local_md, dregno);
- reg_defs[dregno] = NULL;
- }
- else
- {
- bitmap_clear_bit (local_md, dregno);
- reg_defs[dregno] = def;
- }
- }
-}
-
-
-/* Fill the use_def_ref vector with values for the uses in USE_REC,
- taking reaching definitions info from LOCAL_MD and REG_DEFS.
- TOP_FLAG says which artificials uses should be used, when USE_REC
- is an artificial use vector. */
-
-static void
-process_uses (df_ref use, int top_flag)
-{
- for (; use; use = DF_REF_NEXT_LOC (use))
- if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == top_flag)
- {
- unsigned int uregno = DF_REF_REGNO (use);
- if (reg_defs[uregno]
- && !bitmap_bit_p (local_md, uregno)
- && bitmap_bit_p (local_lr, uregno))
- use_def_ref[DF_REF_ID (use)] = reg_defs[uregno];
- }
-}
-
-class single_def_use_dom_walker : public dom_walker
-{
-public:
- single_def_use_dom_walker (cdi_direction direction)
- : dom_walker (direction) {}
- virtual edge before_dom_children (basic_block);
- virtual void after_dom_children (basic_block);
-};
-
-edge
-single_def_use_dom_walker::before_dom_children (basic_block bb)
-{
- int bb_index = bb->index;
- class df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index);
- class df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index);
- rtx_insn *insn;
-
- bitmap_copy (local_md, &md_bb_info->in);
- bitmap_copy (local_lr, &lr_bb_info->in);
-
- /* Push a marker for the leave_block callback. */
- reg_defs_stack.safe_push (NULL);
-
- process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP);
- process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP);
-
- /* We don't call df_simulate_initialize_forwards, as it may overestimate
- the live registers if there are unused artificial defs. We prefer
- liveness to be underestimated. */
-
- FOR_BB_INSNS (bb, insn)
- if (INSN_P (insn))
- {
- unsigned int uid = INSN_UID (insn);
- process_uses (DF_INSN_UID_USES (uid), 0);
- process_uses (DF_INSN_UID_EQ_USES (uid), 0);
- process_defs (DF_INSN_UID_DEFS (uid), 0);
- df_simulate_one_insn_forwards (bb, insn, local_lr);
- }
-
- process_uses (df_get_artificial_uses (bb_index), 0);
- process_defs (df_get_artificial_defs (bb_index), 0);
-
- return NULL;
-}
-
-/* Pop the definitions created in this basic block when leaving its
- dominated parts. */
-
-void
-single_def_use_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
-{
- df_ref saved_def;
- while ((saved_def = reg_defs_stack.pop ()) != NULL)
- {
- unsigned int dregno = DF_REF_REGNO (saved_def);
-
- /* See also process_defs. */
- if (saved_def == reg_defs[dregno])
- reg_defs[dregno] = NULL;
- else
- reg_defs[dregno] = saved_def;
- }
-}
-
-
-/* Build a vector holding the reaching definitions of uses reached by a
- single dominating definition. */
-
-static void
-build_single_def_use_links (void)
-{
- /* We use the multiple definitions problem to compute our restricted
- use-def chains. */
- df_set_flags (DF_EQ_NOTES);
- df_md_add_problem ();
- df_note_add_problem ();
- df_analyze ();
- df_maybe_reorganize_use_refs (DF_REF_ORDER_BY_INSN_WITH_NOTES);
-
- use_def_ref.create (DF_USES_TABLE_SIZE ());
- use_def_ref.safe_grow_cleared (DF_USES_TABLE_SIZE (), true);
-
- reg_defs.create (max_reg_num ());
- reg_defs.safe_grow_cleared (max_reg_num (), true);
-
- reg_defs_stack.create (n_basic_blocks_for_fn (cfun) * 10);
- local_md = BITMAP_ALLOC (NULL);
- local_lr = BITMAP_ALLOC (NULL);
-
- /* Walk the dominator tree looking for single reaching definitions
- dominating the uses. This is similar to how SSA form is built. */
- single_def_use_dom_walker (CDI_DOMINATORS)
- .walk (cfun->cfg->x_entry_block_ptr);
-
- BITMAP_FREE (local_lr);
- BITMAP_FREE (local_md);
- reg_defs.release ();
- reg_defs_stack.release ();
-}
-
-
/* Do not try to replace constant addresses or addresses of local and
argument slots. These MEM expressions are made only once and inserted
in many instructions, as well as being used to control symbol table
@@ -342,773 +132,477 @@ can_simplify_addr (rtx addr)
&& REGNO (reg) != ARG_POINTER_REGNUM));
}
-/* Returns a canonical version of X for the address, from the point of view,
- that all multiplications are represented as MULT instead of the multiply
- by a power of 2 being represented as ASHIFT.
-
- Every ASHIFT we find has been made by simplify_gen_binary and was not
- there before, so it is not shared. So we can do this in place. */
-
-static void
-canonicalize_address (rtx x)
-{
- for (;;)
- switch (GET_CODE (x))
- {
- case ASHIFT:
- if (CONST_INT_P (XEXP (x, 1))
- && INTVAL (XEXP (x, 1)) < GET_MODE_UNIT_BITSIZE (GET_MODE (x))
- && INTVAL (XEXP (x, 1)) >= 0)
- {
- HOST_WIDE_INT shift = INTVAL (XEXP (x, 1));
- PUT_CODE (x, MULT);
- XEXP (x, 1) = gen_int_mode (HOST_WIDE_INT_1 << shift,
- GET_MODE (x));
- }
-
- x = XEXP (x, 0);
- break;
-
- case PLUS:
- if (GET_CODE (XEXP (x, 0)) == PLUS
- || GET_CODE (XEXP (x, 0)) == ASHIFT
- || GET_CODE (XEXP (x, 0)) == CONST)
- canonicalize_address (XEXP (x, 0));
-
- x = XEXP (x, 1);
- break;
-
- case CONST:
- x = XEXP (x, 0);
- break;
-
- default:
- return;
- }
-}
-
-/* OLD is a memory address. Return whether it is good to use NEW instead,
- for a memory access in the given MODE. */
+/* MEM is the result of an address simplification, and temporarily
+ undoing changes OLD_NUM_CHANGES onwards restores the original address.
+ Return whether it is good to use the new address instead of the
+ old one. INSN is the containing instruction. */
static bool
-should_replace_address (rtx old_rtx, rtx new_rtx, machine_mode mode,
- addr_space_t as, bool speed)
+should_replace_address (int old_num_changes, rtx mem, rtx_insn *insn)
{
int gain;
- if (rtx_equal_p (old_rtx, new_rtx)
- || !memory_address_addr_space_p (mode, new_rtx, as))
- return false;
-
- /* Copy propagation is always ok. */
- if (REG_P (old_rtx) && REG_P (new_rtx))
- return true;
-
/* Prefer the new address if it is less expensive. */
- gain = (address_cost (old_rtx, mode, as, speed)
- - address_cost (new_rtx, mode, as, speed));
+ bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
+ temporarily_undo_changes (old_num_changes);
+ gain = address_cost (XEXP (mem, 0), GET_MODE (mem),
+ MEM_ADDR_SPACE (mem), speed);
+ redo_changes (old_num_changes);
+ gain -= address_cost (XEXP (mem, 0), GET_MODE (mem),
+ MEM_ADDR_SPACE (mem), speed);
/* If the addresses have equivalent cost, prefer the new address
if it has the highest `set_src_cost'. That has the potential of
eliminating the most insns without additional costs, and it
is the same that cse.c used to do. */
if (gain == 0)
- gain = (set_src_cost (new_rtx, VOIDmode, speed)
- - set_src_cost (old_rtx, VOIDmode, speed));
+ {
+ gain = set_src_cost (XEXP (mem, 0), VOIDmode, speed);
+ temporarily_undo_changes (old_num_changes);
+ gain -= set_src_cost (XEXP (mem, 0), VOIDmode, speed);
+ redo_changes (old_num_changes);
+ }
return (gain > 0);
}
-/* Flags for the last parameter of propagate_rtx_1. */
-
-enum {
- /* If PR_CAN_APPEAR is true, propagate_rtx_1 always returns true;
- if it is false, propagate_rtx_1 returns false if, for at least
- one occurrence OLD, it failed to collapse the result to a constant.
- For example, (mult:M (reg:M A) (minus:M (reg:M B) (reg:M A))) may
- collapse to zero if replacing (reg:M B) with (reg:M A).
-
- PR_CAN_APPEAR is disregarded inside MEMs: in that case,
- propagate_rtx_1 just tries to make cheaper and valid memory
- addresses. */
- PR_CAN_APPEAR = 1,
-
- /* If PR_HANDLE_MEM is not set, propagate_rtx_1 won't attempt any replacement
- outside memory addresses. This is needed because propagate_rtx_1 does
- not do any analysis on memory; thus it is very conservative and in general
- it will fail if non-read-only MEMs are found in the source expression.
-
- PR_HANDLE_MEM is set when the source of the propagation was not
- another MEM. Then, it is safe not to treat non-read-only MEMs as
- ``opaque'' objects. */
- PR_HANDLE_MEM = 2,
-
- /* Set when costs should be optimized for speed. */
- PR_OPTIMIZE_FOR_SPEED = 4
-};
+namespace
+{
+ class fwprop_propagation : public insn_propagation
+ {
+ public:
+ static const uint16_t CHANGED_MEM = FIRST_SPARE_RESULT;
+ static const uint16_t CONSTANT = FIRST_SPARE_RESULT << 1;
+ static const uint16_t PROFITABLE = FIRST_SPARE_RESULT << 2;
+
+ fwprop_propagation (rtx_insn *, rtx, rtx);
+
+ bool changed_mem_p () const { return result_flags & CHANGED_MEM; }
+ bool folded_to_constants_p () const;
+ bool profitable_p () const;
+
+ bool check_mem (int, rtx) final override;
+ void note_simplification (int, uint16_t, rtx, rtx) final override;
+ uint16_t classify_result (rtx, rtx);
+ };
+}
-/* Check that X has a single def. */
+/* Prepare to replace FROM with TO in INSN. */
-static bool
-reg_single_def_p (rtx x)
+fwprop_propagation::fwprop_propagation (rtx_insn *insn, rtx from, rtx to)
+ : insn_propagation (insn, from, to)
{
- if (!REG_P (x))
- return false;
-
- int regno = REGNO (x);
- return (DF_REG_DEF_COUNT (regno) == 1
- && !bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)), regno));
+ should_check_mems = true;
+ should_note_simplifications = true;
}
-/* Replace all occurrences of OLD in *PX with NEW and try to simplify the
- resulting expression. Replace *PX with a new RTL expression if an
- occurrence of OLD was found.
+/* MEM is the result of an address simplification, and temporarily
+ undoing changes OLD_NUM_CHANGES onwards restores the original address.
+ Return true if the propagation should continue, false if it has failed. */
- This is only a wrapper around simplify-rtx.c: do not add any pattern
- matching code here. (The sole exception is the handling of LO_SUM, but
- that is because there is no simplify_gen_* function for LO_SUM). */
-
-static bool
-propagate_rtx_1 (rtx *px, rtx old_rtx, rtx new_rtx, int flags)
+bool
+fwprop_propagation::check_mem (int old_num_changes, rtx mem)
{
- rtx x = *px, tem = NULL_RTX, op0, op1, op2;
- enum rtx_code code = GET_CODE (x);
- machine_mode mode = GET_MODE (x);
- machine_mode op_mode;
- bool can_appear = (flags & PR_CAN_APPEAR) != 0;
- bool valid_ops = true;
-
- if (!(flags & PR_HANDLE_MEM) && MEM_P (x) && !MEM_READONLY_P (x))
+ if (!memory_address_addr_space_p (GET_MODE (mem), XEXP (mem, 0),
+ MEM_ADDR_SPACE (mem)))
{
- /* If unsafe, change MEMs to CLOBBERs or SCRATCHes (to preserve whether
- they have side effects or not). */
- *px = (side_effects_p (x)
- ? gen_rtx_CLOBBER (GET_MODE (x), const0_rtx)
- : gen_rtx_SCRATCH (GET_MODE (x)));
+ failure_reason = "would create an invalid MEM";
return false;
}
- /* If X is OLD_RTX, return NEW_RTX. But not if replacing only within an
- address, and we are *not* inside one. */
- if (x == old_rtx)
+ temporarily_undo_changes (old_num_changes);
+ bool can_simplify = can_simplify_addr (XEXP (mem, 0));
+ redo_changes (old_num_changes);
+ if (!can_simplify)
{
- *px = new_rtx;
- return can_appear;
+ failure_reason = "would replace a frame address";
+ return false;
}
- /* If this is an expression, try recursive substitution. */
- switch (GET_RTX_CLASS (code))
+ /* Copy propagations are always ok. Otherwise check the costs. */
+ if (!(REG_P (from) && REG_P (to))
+ && !should_replace_address (old_num_changes, mem, insn))
{
- case RTX_UNARY:
- op0 = XEXP (x, 0);
- op_mode = GET_MODE (op0);
- valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
- if (op0 == XEXP (x, 0))
- return true;
- tem = simplify_gen_unary (code, mode, op0, op_mode);
- break;
-
- case RTX_BIN_ARITH:
- case RTX_COMM_ARITH:
- op0 = XEXP (x, 0);
- op1 = XEXP (x, 1);
- valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
- valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
- if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
- return true;
- tem = simplify_gen_binary (code, mode, op0, op1);
- break;
-
- case RTX_COMPARE:
- case RTX_COMM_COMPARE:
- op0 = XEXP (x, 0);
- op1 = XEXP (x, 1);
- op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
- valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
- valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
- if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
- return true;
- tem = simplify_gen_relational (code, mode, op_mode, op0, op1);
- break;
-
- case RTX_TERNARY:
- case RTX_BITFIELD_OPS:
- op0 = XEXP (x, 0);
- op1 = XEXP (x, 1);
- op2 = XEXP (x, 2);
- op_mode = GET_MODE (op0);
- valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
- valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
- valid_ops &= propagate_rtx_1 (&op2, old_rtx, new_rtx, flags);
- if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2))
- return true;
- if (op_mode == VOIDmode)
- op_mode = GET_MODE (op0);
- tem = simplify_gen_ternary (code, mode, op_mode, op0, op1, op2);
- break;
-
- case RTX_EXTRA:
- /* The only case we try to handle is a SUBREG. */
- if (code == SUBREG)
- {
- op0 = XEXP (x, 0);
- valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
- if (op0 == XEXP (x, 0))
- return true;
- tem = simplify_gen_subreg (mode, op0, GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x));
- }
-
- else
- {
- rtvec vec;
- rtvec newvec;
- const char *fmt = GET_RTX_FORMAT (code);
- rtx op;
-
- for (int i = 0; fmt[i]; i++)
- switch (fmt[i])
- {
- case 'E':
- vec = XVEC (x, i);
- newvec = vec;
- for (int j = 0; j < GET_NUM_ELEM (vec); j++)
- {
- op = RTVEC_ELT (vec, j);
- valid_ops &= propagate_rtx_1 (&op, old_rtx, new_rtx, flags);
- if (op != RTVEC_ELT (vec, j))
- {
- if (newvec == vec)
- {
- newvec = shallow_copy_rtvec (vec);
- if (!tem)
- tem = shallow_copy_rtx (x);
- XVEC (tem, i) = newvec;
- }
- RTVEC_ELT (newvec, j) = op;
- }
- }
- break;
-
- case 'e':
- if (XEXP (x, i))
- {
- op = XEXP (x, i);
- valid_ops &= propagate_rtx_1 (&op, old_rtx, new_rtx, flags);
- if (op != XEXP (x, i))
- {
- if (!tem)
- tem = shallow_copy_rtx (x);
- XEXP (tem, i) = op;
- }
- }
- break;
- }
- }
-
- break;
-
- case RTX_OBJ:
- if (code == MEM && x != new_rtx)
- {
- rtx new_op0;
- op0 = XEXP (x, 0);
-
- /* There are some addresses that we cannot work on. */
- if (!can_simplify_addr (op0))
- return true;
-
- op0 = new_op0 = targetm.delegitimize_address (op0);
- valid_ops &= propagate_rtx_1 (&new_op0, old_rtx, new_rtx,
- flags | PR_CAN_APPEAR);
-
- /* Dismiss transformation that we do not want to carry on. */
- if (!valid_ops
- || new_op0 == op0
- || !(GET_MODE (new_op0) == GET_MODE (op0)
- || GET_MODE (new_op0) == VOIDmode))
- return true;
-
- canonicalize_address (new_op0);
-
- /* Copy propagations are always ok. Otherwise check the costs. */
- if (!(REG_P (old_rtx) && REG_P (new_rtx))
- && !should_replace_address (op0, new_op0, GET_MODE (x),
- MEM_ADDR_SPACE (x),
- flags & PR_OPTIMIZE_FOR_SPEED))
- return true;
-
- tem = replace_equiv_address_nv (x, new_op0);
- }
-
- else if (code == LO_SUM)
- {
- op0 = XEXP (x, 0);
- op1 = XEXP (x, 1);
-
- /* The only simplification we do attempts to remove references to op0
- or make it constant -- in both cases, op0's invalidity will not
- make the result invalid. */
- propagate_rtx_1 (&op0, old_rtx, new_rtx, flags | PR_CAN_APPEAR);
- valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
- if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
- return true;
-
- /* (lo_sum (high x) x) -> x */
- if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
- tem = op1;
- else
- tem = gen_rtx_LO_SUM (mode, op0, op1);
+ failure_reason = "would increase the cost of a MEM";
+ return false;
+ }
- /* OP1 is likely not a legitimate address, otherwise there would have
- been no LO_SUM. We want it to disappear if it is invalid, return
- false in that case. */
- return memory_address_p (mode, tem);
- }
+ result_flags |= CHANGED_MEM;
+ return true;
+}
- else if (code == REG)
- {
- if (rtx_equal_p (x, old_rtx))
- {
- *px = new_rtx;
- return can_appear;
- }
- }
- break;
+/* OLDX has been simplified to NEWX. Describe the change in terms of
+ result_flags. */
- default:
- break;
+uint16_t
+fwprop_propagation::classify_result (rtx old_rtx, rtx new_rtx)
+{
+ if (CONSTANT_P (new_rtx))
+ {
+ /* If OLD_RTX is a LO_SUM, then it presumably exists for a reason,
+ and NEW_RTX is likely not a legitimate address. We want it to
+ disappear if it is invalid.
+
+ ??? Using the mode of the LO_SUM as the mode of the address
+ seems odd, but it was what the pre-SSA code did. */
+ if (GET_CODE (old_rtx) == LO_SUM
+ && !memory_address_p (GET_MODE (old_rtx), new_rtx))
+ return CONSTANT;
+ return CONSTANT | PROFITABLE;
}
- /* No change, no trouble. */
- if (tem == NULL_RTX)
- return true;
-
- *px = tem;
-
/* Allow replacements that simplify operations on a vector or complex
value to a component. The most prominent case is
(subreg ([vec_]concat ...)). */
- if (REG_P (tem) && !HARD_REGISTER_P (tem)
- && (VECTOR_MODE_P (GET_MODE (new_rtx))
- || COMPLEX_MODE_P (GET_MODE (new_rtx)))
- && GET_MODE (tem) == GET_MODE_INNER (GET_MODE (new_rtx)))
- return true;
+ if (REG_P (new_rtx)
+ && !HARD_REGISTER_P (new_rtx)
+ && (VECTOR_MODE_P (GET_MODE (from))
+ || COMPLEX_MODE_P (GET_MODE (from)))
+ && GET_MODE (new_rtx) == GET_MODE_INNER (GET_MODE (from)))
+ return PROFITABLE;
- /* The replacement we made so far is valid, if all of the recursive
- replacements were valid, or we could simplify everything to
- a constant. */
- return valid_ops || can_appear || CONSTANT_P (tem);
+ return 0;
}
+/* Record that OLD_RTX has been simplified to NEW_RTX. OLD_NUM_CHANGES
+ is the number of unrelated changes that had been made before processing
+ OLD_RTX and its subrtxes. OLD_RESULT_FLAGS is the value that result_flags
+ had at that point. */
-/* Return true if X constains a non-constant mem. */
-
-static bool
-varying_mem_p (const_rtx x)
+void
+fwprop_propagation::note_simplification (int old_num_changes,
+ uint16_t old_result_flags,
+ rtx old_rtx, rtx new_rtx)
{
- subrtx_iterator::array_type array;
- FOR_EACH_SUBRTX (iter, array, x, NONCONST)
- if (MEM_P (*iter) && !MEM_READONLY_P (*iter))
- return true;
- return false;
+ result_flags &= ~(CONSTANT | PROFITABLE);
+ uint16_t new_flags = classify_result (old_rtx, new_rtx);
+ if (old_num_changes)
+ new_flags &= old_result_flags;
+ result_flags |= new_flags;
}
+/* Return true if all substitutions eventually folded to constants. */
+
+bool
+fwprop_propagation::folded_to_constants_p () const
+{
+ /* If we're propagating a HIGH, require it to be folded with a
+ partnering LO_SUM. For example, a REG_EQUAL note with a register
+ replaced by an unfolded HIGH is not useful. */
+ if (CONSTANT_P (to) && GET_CODE (to) != HIGH)
+ return true;
+ return !(result_flags & UNSIMPLIFIED) && (result_flags & CONSTANT);
+}
-/* Replace all occurrences of OLD in X with NEW and try to simplify the
- resulting expression (in mode MODE). Return a new expression if it is
- a constant, otherwise X.
- Simplifications where occurrences of NEW collapse to a constant are always
- accepted. All simplifications are accepted if NEW is a pseudo too.
- Otherwise, we accept simplifications that have a lower or equal cost. */
+/* Return true if it is worth keeping the result of the propagation,
+ false if it would increase the complexity of the pattern too much. */
-static rtx
-propagate_rtx (rtx x, machine_mode mode, rtx old_rtx, rtx new_rtx,
- bool speed)
+bool
+fwprop_propagation::profitable_p () const
{
- rtx tem;
- bool collapsed;
- int flags;
+ if (changed_mem_p ())
+ return true;
- if (REG_P (new_rtx) && REGNO (new_rtx) < FIRST_PSEUDO_REGISTER)
- return NULL_RTX;
+ if (!(result_flags & UNSIMPLIFIED)
+ && (result_flags & PROFITABLE))
+ return true;
- flags = 0;
- if (REG_P (new_rtx)
- || CONSTANT_P (new_rtx)
- || (GET_CODE (new_rtx) == SUBREG
- && REG_P (SUBREG_REG (new_rtx))
- && !paradoxical_subreg_p (new_rtx)))
- flags |= PR_CAN_APPEAR;
- if (!varying_mem_p (new_rtx))
- flags |= PR_HANDLE_MEM;
-
- if (speed)
- flags |= PR_OPTIMIZE_FOR_SPEED;
-
- tem = x;
- collapsed = propagate_rtx_1 (&tem, old_rtx, copy_rtx (new_rtx), flags);
- if (tem == x || !collapsed)
- return NULL_RTX;
-
- /* gen_lowpart_common will not be able to process VOIDmode entities other
- than CONST_INTs. */
- if (GET_MODE (tem) == VOIDmode && !CONST_INT_P (tem))
- return NULL_RTX;
-
- if (GET_MODE (tem) == VOIDmode)
- tem = rtl_hooks.gen_lowpart_no_emit (mode, tem);
- else
- gcc_assert (GET_MODE (tem) == mode);
+ if (REG_P (to))
+ return true;
- return tem;
-}
+ if (GET_CODE (to) == SUBREG
+ && REG_P (SUBREG_REG (to))
+ && !paradoxical_subreg_p (to))
+ return true;
+ if (CONSTANT_P (to))
+ return true;
-
+ return false;
+}
-/* Return true if the register from reference REF is killed
- between FROM to (but not including) TO. */
+/* Check that X has a single def. */
static bool
-local_ref_killed_between_p (df_ref ref, rtx_insn *from, rtx_insn *to)
+reg_single_def_p (rtx x)
{
- rtx_insn *insn;
+ return REG_P (x) && crtl->ssa->single_dominating_def (REGNO (x));
+}
- for (insn = from; insn != to; insn = NEXT_INSN (insn))
- {
- df_ref def;
- if (!INSN_P (insn))
- continue;
+/* Return true if X contains a paradoxical subreg. */
- FOR_EACH_INSN_DEF (def, insn)
- if (DF_REF_REGNO (ref) == DF_REF_REGNO (def))
- return true;
+static bool
+contains_paradoxical_subreg_p (rtx x)
+{
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
+ {
+ x = *iter;
+ if (SUBREG_P (x) && paradoxical_subreg_p (x))
+ return true;
}
return false;
}
+/* Try to substitute (set DEST SRC) from DEF_INSN into note NOTE of USE_INSN.
+ Return the number of substitutions on success, otherwise return -1 and
+ leave USE_INSN unchanged.
-/* Check if USE is killed between DEF_INSN and TARGET_INSN. This would
- require full computation of available expressions; we check only a few
- restricted conditions:
- - if the reg in USE has only one definition, go ahead;
- - in the same basic block, we check for no definitions killing the use;
- - if TARGET_INSN's basic block has DEF_INSN's basic block as its sole
- predecessor, we check if the use is killed after DEF_INSN or before
- TARGET_INSN insn, in their respective basic blocks. */
+ If REQUIRE_CONSTANT is true, require all substituted occurences of SRC
+ to fold to a constant, so that the note does not use any more registers
+ than it did previously. If REQUIRE_CONSTANT is false, also allow the
+ substitution if it's something we'd normally allow for the main
+ instruction pattern. */
-static bool
-use_killed_between (df_ref use, rtx_insn *def_insn, rtx_insn *target_insn)
+static int
+try_fwprop_subst_note (insn_info *use_insn, insn_info *def_insn,
+ rtx note, rtx dest, rtx src, bool require_constant)
{
- basic_block def_bb = BLOCK_FOR_INSN (def_insn);
- basic_block target_bb = BLOCK_FOR_INSN (target_insn);
- int regno;
- df_ref def;
-
- /* We used to have a def reaching a use that is _before_ the def,
- with the def not dominating the use even though the use and def
- are in the same basic block, when a register may be used
- uninitialized in a loop. This should not happen anymore since
- we do not use reaching definitions, but still we test for such
- cases and assume that DEF is not available. */
- if (def_bb == target_bb
- ? DF_INSN_LUID (def_insn) >= DF_INSN_LUID (target_insn)
- : !dominated_by_p (CDI_DOMINATORS, target_bb, def_bb))
- return true;
+ rtx_insn *use_rtl = use_insn->rtl ();
- /* Check if the reg in USE has only one definition. We already
- know that this definition reaches use, or we wouldn't be here.
- However, this is invalid for hard registers because if they are
- live at the beginning of the function it does not mean that we
- have an uninitialized access. And we have to check for the case
- where a register may be used uninitialized in a loop as above. */
- regno = DF_REF_REGNO (use);
- def = DF_REG_DEF_CHAIN (regno);
- if (def
- && DF_REF_NEXT_REG (def) == NULL
- && regno >= FIRST_PSEUDO_REGISTER
- && (BLOCK_FOR_INSN (DF_REF_INSN (def)) == def_bb
- ? DF_INSN_LUID (DF_REF_INSN (def)) < DF_INSN_LUID (def_insn)
- : dominated_by_p (CDI_DOMINATORS,
- def_bb, BLOCK_FOR_INSN (DF_REF_INSN (def)))))
- return false;
-
- /* Check locally if we are in the same basic block. */
- if (def_bb == target_bb)
- return local_ref_killed_between_p (use, def_insn, target_insn);
-
- /* Finally, if DEF_BB is the sole predecessor of TARGET_BB. */
- if (single_pred_p (target_bb)
- && single_pred (target_bb) == def_bb)
+ insn_change_watermark watermark;
+ fwprop_propagation prop (use_rtl, dest, src);
+ if (!prop.apply_to_rvalue (&XEXP (note, 0)))
{
- df_ref x;
-
- /* See if USE is killed between DEF_INSN and the last insn in the
- basic block containing DEF_INSN. */
- x = df_bb_regno_last_def_find (def_bb, regno);
- if (x && DF_INSN_LUID (DF_REF_INSN (x)) >= DF_INSN_LUID (def_insn))
- return true;
-
- /* See if USE is killed between TARGET_INSN and the first insn in the
- basic block containing TARGET_INSN. */
- x = df_bb_regno_first_def_find (target_bb, regno);
- if (x && DF_INSN_LUID (DF_REF_INSN (x)) < DF_INSN_LUID (target_insn))
- return true;
-
- return false;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "cannot propagate from insn %d into"
+ " notes of insn %d: %s\n", def_insn->uid (),
+ use_insn->uid (), prop.failure_reason);
+ return -1;
}
- /* Otherwise assume the worst case. */
- return true;
-}
-
+ if (prop.num_replacements == 0)
+ return 0;
-/* Check if all uses in DEF_INSN can be used in TARGET_INSN. This
- would require full computation of available expressions;
- we check only restricted conditions, see use_killed_between. */
-static bool
-all_uses_available_at (rtx_insn *def_insn, rtx_insn *target_insn)
-{
- df_ref use;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn);
- rtx def_set = single_set (def_insn);
- rtx_insn *next;
-
- gcc_assert (def_set);
-
- /* If target_insn comes right after def_insn, which is very common
- for addresses, we can use a quicker test. Ignore debug insns
- other than target insns for this. */
- next = NEXT_INSN (def_insn);
- while (next && next != target_insn && DEBUG_INSN_P (next))
- next = NEXT_INSN (next);
- if (next == target_insn && REG_P (SET_DEST (def_set)))
+ if (require_constant)
{
- rtx def_reg = SET_DEST (def_set);
-
- /* If the insn uses the reg that it defines, the substitution is
- invalid. */
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- if (rtx_equal_p (DF_REF_REG (use), def_reg))
- return false;
- FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
- if (rtx_equal_p (DF_REF_REG (use), def_reg))
- return false;
+ if (!prop.folded_to_constants_p ())
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "cannot propagate from insn %d into"
+ " notes of insn %d: %s\n", def_insn->uid (),
+ use_insn->uid (), "wouldn't fold to constants");
+ return -1;
+ }
}
else
{
- rtx def_reg = REG_P (SET_DEST (def_set)) ? SET_DEST (def_set) : NULL_RTX;
-
- /* Look at all the uses of DEF_INSN, and see if they are not
- killed between DEF_INSN and TARGET_INSN. */
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
- return false;
- if (use_killed_between (use, def_insn, target_insn))
- return false;
- }
- FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+ if (!prop.folded_to_constants_p () && !prop.profitable_p ())
{
- if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
- return false;
- if (use_killed_between (use, def_insn, target_insn))
- return false;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "cannot propagate from insn %d into"
+ " notes of insn %d: %s\n", def_insn->uid (),
+ use_insn->uid (), "would increase complexity of node");
+ return -1;
}
}
- return true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\nin notes of insn %d, replacing:\n ",
+ INSN_UID (use_rtl));
+ temporarily_undo_changes (0);
+ print_inline_rtx (dump_file, note, 2);
+ redo_changes (0);
+ fprintf (dump_file, "\n with:\n ");
+ print_inline_rtx (dump_file, note, 2);
+ fprintf (dump_file, "\n");
+ }
+ watermark.keep ();
+ return prop.num_replacements;
}
-
-static df_ref *active_defs;
-static sparseset active_defs_check;
-
-/* Fill the ACTIVE_DEFS array with the use->def link for the registers
- mentioned in USE_REC. Register the valid entries in ACTIVE_DEFS_CHECK
- too, for checking purposes. */
+/* Try to substitute (set DEST SRC) from DEF_INSN into location LOC of
+ USE_INSN's pattern. Return true on success, otherwise leave USE_INSN
+ unchanged. */
-static void
-register_active_defs (df_ref use)
+static bool
+try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change,
+ insn_info *def_insn, rtx *loc, rtx dest, rtx src)
{
- for (; use; use = DF_REF_NEXT_LOC (use))
- {
- df_ref def = get_def_for_use (use);
- int regno = DF_REF_REGNO (use);
+ insn_info *use_insn = use_change.insn ();
+ rtx_insn *use_rtl = use_insn->rtl ();
- if (flag_checking)
- sparseset_set_bit (active_defs_check, regno);
- active_defs[regno] = def;
+ insn_change_watermark watermark;
+ fwprop_propagation prop (use_rtl, dest, src);
+ if (!prop.apply_to_pattern (loc))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "cannot propagate from insn %d into"
+ " insn %d: %s\n", def_insn->uid (), use_insn->uid (),
+ prop.failure_reason);
+ return false;
}
-}
+ if (prop.num_replacements == 0)
+ return false;
-/* Build the use->def links that we use to update the dataflow info
- for new uses. Note that building the links is very cheap and if
- it were done earlier, they could be used to rule out invalid
- propagations (in addition to what is done in all_uses_available_at).
- I'm not doing this yet, though. */
-
-static void
-update_df_init (rtx_insn *def_insn, rtx_insn *insn)
-{
- if (flag_checking)
- sparseset_clear (active_defs_check);
- register_active_defs (DF_INSN_USES (def_insn));
- register_active_defs (DF_INSN_USES (insn));
- register_active_defs (DF_INSN_EQ_USES (insn));
-}
+ if (!prop.profitable_p ())
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "cannot propagate from insn %d into"
+ " insn %d: %s\n", def_insn->uid (), use_insn->uid (),
+ "would increase complexity of pattern");
+ return false;
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\npropagating insn %d into insn %d, replacing:\n",
+ def_insn->uid (), use_insn->uid ());
+ temporarily_undo_changes (0);
+ print_rtl_single (dump_file, PATTERN (use_rtl));
+ redo_changes (0);
+ }
-/* Update the USE_DEF_REF array for the given use, using the active definitions
- in the ACTIVE_DEFS array to match pseudos to their def. */
+ /* ??? In theory, it should be better to use insn costs rather than
+ set_src_costs here. That would involve replacing this code with
+ change_is_worthwhile. */
+ bool ok = recog (attempt, use_change);
+ if (ok && !prop.changed_mem_p () && !use_insn->is_asm ())
+ if (rtx use_set = single_set (use_rtl))
+ {
+ bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_rtl));
+ temporarily_undo_changes (0);
+ auto old_cost = set_src_cost (SET_SRC (use_set),
+ GET_MODE (SET_DEST (use_set)), speed);
+ redo_changes (0);
+ auto new_cost = set_src_cost (SET_SRC (use_set),
+ GET_MODE (SET_DEST (use_set)), speed);
+ if (new_cost > old_cost)
+ {
+ if (dump_file)
+ fprintf (dump_file, "change not profitable"
+ " (cost %d -> cost %d)\n", old_cost, new_cost);
+ ok = false;
+ }
+ }
-static inline void
-update_uses (df_ref use)
-{
- for (; use; use = DF_REF_NEXT_LOC (use))
+ if (!ok)
{
- int regno = DF_REF_REGNO (use);
+ /* The pattern didn't match, but if all uses of SRC folded to
+ constants, we can add a REG_EQUAL note for the result, if there
+ isn't one already. */
+ if (!prop.folded_to_constants_p ())
+ return false;
- /* Set up the use-def chain. */
- if (DF_REF_ID (use) >= (int) use_def_ref.length ())
- use_def_ref.safe_grow_cleared (DF_REF_ID (use) + 1, true);
+ /* Test this first to avoid creating an unnecessary copy of SRC. */
+ if (find_reg_note (use_rtl, REG_EQUAL, NULL_RTX))
+ return false;
- if (flag_checking)
- gcc_assert (sparseset_bit_p (active_defs_check, regno));
- use_def_ref[DF_REF_ID (use)] = active_defs[regno];
- }
-}
+ rtx set = set_for_reg_notes (use_rtl);
+ if (!set || !REG_P (SET_DEST (set)))
+ return false;
+ rtx value = copy_rtx (SET_SRC (set));
+ cancel_changes (0);
-/* Update the USE_DEF_REF array for the uses in INSN. Only update note
- uses if NOTES_ONLY is true. */
+ /* If there are any paradoxical SUBREGs, drop the REG_EQUAL note,
+ because the bits in there can be anything and so might not
+ match the REG_EQUAL note content. See PR70574. */
+ if (contains_paradoxical_subreg_p (SET_SRC (set)))
+ return false;
-static void
-update_df (rtx_insn *insn, rtx note)
-{
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Setting REG_EQUAL note\n");
- if (note)
- {
- df_uses_create (&XEXP (note, 0), insn, DF_REF_IN_NOTE);
- df_notes_rescan (insn);
+ return set_unique_reg_note (use_rtl, REG_EQUAL, value);
}
- else
+
+ rtx *note_ptr = &REG_NOTES (use_rtl);
+ while (rtx note = *note_ptr)
{
- df_uses_create (&PATTERN (insn), insn, 0);
- df_insn_rescan (insn);
- update_uses (DF_INSN_INFO_USES (insn_info));
+ if ((REG_NOTE_KIND (note) == REG_EQUAL
+ || REG_NOTE_KIND (note) == REG_EQUIV)
+ && try_fwprop_subst_note (use_insn, def_insn, note,
+ dest, src, false) < 0)
+ {
+ *note_ptr = XEXP (note, 1);
+ free_EXPR_LIST_node (note);
+ }
+ else
+ note_ptr = &XEXP (note, 1);
}
- update_uses (DF_INSN_INFO_EQ_USES (insn_info));
+ confirm_change_group ();
+ crtl->ssa->change_insn (use_change);
+ num_changes++;
+ return true;
}
-
-/* Try substituting NEW into LOC, which originated from forward propagation
- of USE's value from DEF_INSN. SET_REG_EQUAL says whether we are
- substituting the whole SET_SRC, so we can set a REG_EQUAL note if the
- new insn is not recognized. Return whether the substitution was
- performed. */
+/* Try to substitute (set DEST SRC) from DEF_INSN into USE_INSN's notes,
+ given that it was not possible to do this for USE_INSN's main pattern.
+ Return true on success, otherwise leave USE_INSN unchanged. */
static bool
-try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx_insn *def_insn,
- bool set_reg_equal)
+try_fwprop_subst_notes (insn_info *use_insn, insn_info *def_insn,
+ rtx dest, rtx src)
{
- rtx_insn *insn = DF_REF_INSN (use);
- rtx set = single_set (insn);
- rtx note = NULL_RTX;
- bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
- int old_cost = 0;
- bool ok;
+ rtx_insn *use_rtl = use_insn->rtl ();
+ for (rtx note = REG_NOTES (use_rtl); note; note = XEXP (note, 1))
+ if ((REG_NOTE_KIND (note) == REG_EQUAL
+ || REG_NOTE_KIND (note) == REG_EQUIV)
+ && try_fwprop_subst_note (use_insn, def_insn, note,
+ dest, src, true) > 0)
+ {
+ confirm_change_group ();
+ return true;
+ }
- update_df_init (def_insn, insn);
+ return false;
+}
- /* forward_propagate_subreg may be operating on an instruction with
- multiple sets. If so, assume the cost of the new instruction is
- not greater than the old one. */
- if (set)
- old_cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed);
- if (dump_file)
- {
- fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn));
- print_inline_rtx (dump_file, *loc, 2);
- fprintf (dump_file, "\n with ");
- print_inline_rtx (dump_file, new_rtx, 2);
- fprintf (dump_file, "\n");
- }
+/* Check whether we could validly substitute (set DEST SRC) from DEF_INSN
+ into USE. If so, first try performing the substitution in location LOC
+ of USE->insn ()'s pattern. If that fails, try instead to substitute
+ into the notes.
- validate_unshare_change (insn, loc, new_rtx, true);
- if (!verify_changes (0))
- {
- if (dump_file)
- fprintf (dump_file, "Changes to insn %d not recognized\n",
- INSN_UID (insn));
- ok = false;
- }
+ Return true on success, otherwise leave USE_INSN unchanged. */
- else if (DF_REF_TYPE (use) == DF_REF_REG_USE
- && set
- && (set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed)
- > old_cost))
- {
- if (dump_file)
- fprintf (dump_file, "Changes to insn %d not profitable\n",
- INSN_UID (insn));
- ok = false;
- }
+static bool
+try_fwprop_subst (use_info *use, insn_info *def_insn,
+ rtx *loc, rtx dest, rtx src)
+{
+ insn_info *use_insn = use->insn ();
- else
- {
- if (dump_file)
- fprintf (dump_file, "Changed insn %d\n", INSN_UID (insn));
- ok = true;
- }
+ auto attempt = crtl->ssa->new_change_attempt ();
+ use_array src_uses = remove_note_accesses (attempt, def_insn->uses ());
- if (ok)
+ /* ??? Not really a meaningful test: it means we can propagate arithmetic
+ involving hard registers but not bare references to them. A better
+ test would be to iterate over src_uses looking for hard registers
+ that are not fixed. */
+ if (REG_P (src) && HARD_REGISTER_P (src))
+ return false;
+
+ /* ??? It would be better to make this EBB-based instead. That would
+ involve checking for equal EBBs rather than equal BBs and trying
+ to make the uses available at use_insn->ebb ()->first_bb (). */
+ if (def_insn->bb () != use_insn->bb ())
{
- confirm_change_group ();
- num_changes++;
+ src_uses = crtl->ssa->make_uses_available (attempt, src_uses,
+ use_insn->bb ());
+ if (!src_uses.is_valid ())
+ return false;
}
- else
- {
- cancel_changes (0);
-
- /* Can also record a simplified value in a REG_EQUAL note,
- making a new one if one does not already exist. */
- if (set_reg_equal)
- {
- /* If there are any paradoxical SUBREGs, don't add REG_EQUAL note,
- because the bits in there can be anything and so might not
- match the REG_EQUAL note content. See PR70574. */
- subrtx_var_iterator::array_type array;
- FOR_EACH_SUBRTX_VAR (iter, array, *loc, NONCONST)
- {
- rtx x = *iter;
- if (SUBREG_P (x) && paradoxical_subreg_p (x))
- {
- set_reg_equal = false;
- break;
- }
- }
- if (set_reg_equal)
- {
- if (dump_file)
- fprintf (dump_file, " Setting REG_EQUAL note\n");
+ insn_change use_change (use_insn);
+ use_change.new_uses = merge_access_arrays (attempt, use_change.new_uses,
+ src_uses);
+ if (!use_change.new_uses.is_valid ())
+ return false;
- note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx));
- }
- }
- }
+ /* ??? We could allow movement within the EBB by adding:
- if ((ok || note) && !CONSTANT_P (new_rtx))
- update_df (insn, note);
+ use_change.move_range = use_insn->ebb ()->insn_range (); */
+ if (!restrict_movement (use_change))
+ return false;
- return ok;
+ return (try_fwprop_subst_pattern (attempt, use_change, def_insn,
+ loc, dest, src)
+ || try_fwprop_subst_notes (use_insn, def_insn, dest, src));
}
/* For the given single_set INSN, containing SRC known to be a
@@ -1117,33 +611,31 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx_insn *def_insn,
load from memory. */
static bool
-free_load_extend (rtx src, rtx_insn *insn)
+free_load_extend (rtx src, insn_info *insn)
{
- rtx reg;
- df_ref def, use;
-
- reg = XEXP (src, 0);
+ rtx reg = XEXP (src, 0);
if (load_extend_op (GET_MODE (reg)) != GET_CODE (src))
return false;
- FOR_EACH_INSN_USE (use, insn)
- if (!DF_REF_IS_ARTIFICIAL (use)
- && DF_REF_TYPE (use) == DF_REF_REG_USE
- && DF_REF_REG (use) == reg)
- break;
- if (!use)
- return false;
+ def_info *def = nullptr;
+ for (use_info *use : insn->uses ())
+ if (use->regno () == REGNO (reg))
+ {
+ def = use->def ();
+ break;
+ }
- def = get_def_for_use (use);
if (!def)
return false;
- if (DF_REF_IS_ARTIFICIAL (def))
+ insn_info *def_insn = def->insn ();
+ if (def_insn->is_artificial ())
return false;
- if (NONJUMP_INSN_P (DF_REF_INSN (def)))
+ rtx_insn *def_rtl = def_insn->rtl ();
+ if (NONJUMP_INSN_P (def_rtl))
{
- rtx patt = PATTERN (DF_REF_INSN (def));
+ rtx patt = PATTERN (def_rtl);
if (GET_CODE (patt) == SET
&& GET_CODE (SET_SRC (patt)) == MEM
@@ -1153,22 +645,24 @@ free_load_extend (rtx src, rtx_insn *insn)
return false;
}
-/* If USE is a subreg, see if it can be replaced by a pseudo. */
+/* Subroutine of forward_propagate_subreg that handles a use of DEST
+ in REF. The other parameters are the same. */
static bool
-forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set)
+forward_propagate_subreg (use_info *use, insn_info *def_insn,
+ rtx dest, rtx src, df_ref ref)
{
- rtx use_reg = DF_REF_REG (use);
- rtx_insn *use_insn;
- rtx src;
scalar_int_mode int_use_mode, src_mode;
/* Only consider subregs... */
+ rtx use_reg = DF_REF_REG (ref);
machine_mode use_mode = GET_MODE (use_reg);
if (GET_CODE (use_reg) != SUBREG
- || !REG_P (SET_DEST (def_set)))
+ || GET_MODE (SUBREG_REG (use_reg)) != GET_MODE (dest))
return false;
+ /* ??? Replacing throughout the pattern would help for match_dups. */
+ rtx *loc = DF_REF_LOC (ref);
if (paradoxical_subreg_p (use_reg))
{
/* If this is a paradoxical SUBREG, we have no idea what value the
@@ -1176,16 +670,13 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set)
a SUBREG whose operand is the same as our mode, and all the modes
are within a word, we can just use the inner operand because
these SUBREGs just say how to treat the register. */
- use_insn = DF_REF_INSN (use);
- src = SET_SRC (def_set);
if (GET_CODE (src) == SUBREG
&& REG_P (SUBREG_REG (src))
&& REGNO (SUBREG_REG (src)) >= FIRST_PSEUDO_REGISTER
&& GET_MODE (SUBREG_REG (src)) == use_mode
- && subreg_lowpart_p (src)
- && all_uses_available_at (def_insn, use_insn))
- return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src),
- def_insn, false);
+ && subreg_lowpart_p (src))
+ return try_fwprop_subst (use, def_insn, loc,
+ use_reg, SUBREG_REG (src));
}
/* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG
@@ -1206,8 +697,6 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set)
else if (is_a <scalar_int_mode> (use_mode, &int_use_mode)
&& subreg_lowpart_p (use_reg))
{
- use_insn = DF_REF_INSN (use);
- src = SET_SRC (def_set);
if ((GET_CODE (src) == ZERO_EXTEND
|| GET_CODE (src) == SIGN_EXTEND)
&& is_a <scalar_int_mode> (GET_MODE (src), &src_mode)
@@ -1216,139 +705,73 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set)
&& GET_MODE (XEXP (src, 0)) == use_mode
&& !free_load_extend (src, def_insn)
&& (targetm.mode_rep_extended (int_use_mode, src_mode)
- != (int) GET_CODE (src))
- && all_uses_available_at (def_insn, use_insn))
- return try_fwprop_subst (use, DF_REF_LOC (use), XEXP (src, 0),
- def_insn, false);
+ != (int) GET_CODE (src)))
+ return try_fwprop_subst (use, def_insn, loc, use_reg, XEXP (src, 0));
}
return false;
}
-/* Try to replace USE with SRC (defined in DEF_INSN) in __asm. */
+/* Try to substitute (set DEST SRC) from DEF_INSN into USE and simplify
+ the result, handling cases where DEST is used in a subreg and where
+ applying that subreg to SRC results in a useful simplification. */
static bool
-forward_propagate_asm (df_ref use, rtx_insn *def_insn, rtx def_set, rtx reg)
+forward_propagate_subreg (use_info *use, insn_info *def_insn,
+ rtx dest, rtx src)
{
- rtx_insn *use_insn = DF_REF_INSN (use);
- rtx src, use_pat, asm_operands, new_rtx, *loc;
- int speed_p, i;
- df_ref uses;
-
- gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0);
-
- src = SET_SRC (def_set);
- use_pat = PATTERN (use_insn);
+ if (!use->includes_subregs () || !REG_P (dest))
+ return false;
- /* In __asm don't replace if src might need more registers than
- reg, as that could increase register pressure on the __asm. */
- uses = DF_INSN_USES (def_insn);
- if (uses && DF_REF_NEXT_LOC (uses))
+ if (GET_CODE (src) != SUBREG
+ && GET_CODE (src) != ZERO_EXTEND
+ && GET_CODE (src) != SIGN_EXTEND)
return false;
- update_df_init (def_insn, use_insn);
- speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
- asm_operands = NULL_RTX;
- switch (GET_CODE (use_pat))
- {
- case ASM_OPERANDS:
- asm_operands = use_pat;
- break;
- case SET:
- if (MEM_P (SET_DEST (use_pat)))
- {
- loc = &SET_DEST (use_pat);
- new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
- if (new_rtx)
- validate_unshare_change (use_insn, loc, new_rtx, true);
- }
- asm_operands = SET_SRC (use_pat);
- break;
- case PARALLEL:
- for (i = 0; i < XVECLEN (use_pat, 0); i++)
- if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET)
- {
- if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i))))
- {
- loc = &SET_DEST (XVECEXP (use_pat, 0, i));
- new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg,
- src, speed_p);
- if (new_rtx)
- validate_unshare_change (use_insn, loc, new_rtx, true);
- }
- asm_operands = SET_SRC (XVECEXP (use_pat, 0, i));
- }
- else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS)
- asm_operands = XVECEXP (use_pat, 0, i);
- break;
- default:
- gcc_unreachable ();
- }
+ rtx_insn *use_rtl = use->insn ()->rtl ();
+ df_ref ref;
- gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS);
- for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++)
- {
- loc = &ASM_OPERANDS_INPUT (asm_operands, i);
- new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
- if (new_rtx)
- validate_unshare_change (use_insn, loc, new_rtx, true);
- }
+ FOR_EACH_INSN_USE (ref, use_rtl)
+ if (DF_REF_REGNO (ref) == use->regno ()
+ && forward_propagate_subreg (use, def_insn, dest, src, ref))
+ return true;
- if (num_changes_pending () == 0 || !apply_change_group ())
- return false;
+ FOR_EACH_INSN_EQ_USE (ref, use_rtl)
+ if (DF_REF_REGNO (ref) == use->regno ()
+ && forward_propagate_subreg (use, def_insn, dest, src, ref))
+ return true;
- update_df (use_insn, NULL);
- num_changes++;
- return true;
+ return false;
}
-/* Try to replace USE with SRC (defined in DEF_INSN) and simplify the
- result. */
+/* Try to substitute (set DEST SRC) from DEF_INSN into USE and
+ simplify the result. */
static bool
-forward_propagate_and_simplify (df_ref use, rtx_insn *def_insn, rtx def_set)
+forward_propagate_and_simplify (use_info *use, insn_info *def_insn,
+ rtx dest, rtx src)
{
- rtx_insn *use_insn = DF_REF_INSN (use);
- rtx use_set = single_set (use_insn);
- rtx src, reg, new_rtx, *loc;
- bool set_reg_equal;
- machine_mode mode;
- int asm_use = -1;
-
- if (INSN_CODE (use_insn) < 0)
- asm_use = asm_noperands (PATTERN (use_insn));
-
- if (!use_set && asm_use < 0 && !DEBUG_INSN_P (use_insn))
+ insn_info *use_insn = use->insn ();
+ rtx_insn *use_rtl = use_insn->rtl ();
+
+ /* ??? This check seems unnecessary. We should be able to propagate
+ into any kind of instruction, regardless of whether it's a single set.
+ It seems odd to be more permissive with asms than normal instructions. */
+ bool need_single_set = (!use_insn->is_asm () && !use_insn->is_debug_insn ());
+ rtx use_set = single_set (use_rtl);
+ if (need_single_set && !use_set)
return false;
- /* Do not propagate into PC, CC0, etc. */
- if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode)
- return false;
+ /* Do not propagate into PC, CC0, etc.
- /* If def and use are subreg, check if they match. */
- reg = DF_REF_REG (use);
- if (GET_CODE (reg) == SUBREG && GET_CODE (SET_DEST (def_set)) == SUBREG)
- {
- if (maybe_ne (SUBREG_BYTE (SET_DEST (def_set)), SUBREG_BYTE (reg)))
- return false;
- }
- /* Check if the def had a subreg, but the use has the whole reg. */
- else if (REG_P (reg) && GET_CODE (SET_DEST (def_set)) == SUBREG)
- return false;
- /* Check if the use has a subreg, but the def had the whole reg. Unlike the
- previous case, the optimization is possible and often useful indeed. */
- else if (GET_CODE (reg) == SUBREG && REG_P (SET_DEST (def_set)))
- reg = SUBREG_REG (reg);
-
- /* Make sure that we can treat REG as having the same mode as the
- source of DEF_SET. */
- if (GET_MODE (SET_DEST (def_set)) != GET_MODE (reg))
+ ??? This too seems unnecessary. The current code should work correctly
+ without it, including cases where jumps become unconditional. */
+ if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode)
return false;
- /* Check if the substitution is valid (last, because it's the most
- expensive check!). */
- src = SET_SRC (def_set);
- if (!CONSTANT_P (src) && !all_uses_available_at (def_insn, use_insn))
+ /* In __asm don't replace if src might need more registers than
+ reg, as that could increase register pressure on the __asm. */
+ if (use_insn->is_asm () && def_insn->uses ().size () > 1)
return false;
/* Check if the def is loading something from the constant pool; in this
@@ -1357,149 +780,90 @@ forward_propagate_and_simplify (df_ref use, rtx_insn *def_insn, rtx def_set)
if (MEM_P (src) && MEM_READONLY_P (src))
{
rtx x = avoid_constant_pool_reference (src);
- if (x != src && use_set)
+ rtx note_set;
+ if (x != src
+ && (note_set = set_for_reg_notes (use_rtl))
+ && REG_P (SET_DEST (note_set))
+ && !contains_paradoxical_subreg_p (SET_SRC (note_set)))
{
- rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
- rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set);
+ rtx note = find_reg_note (use_rtl, REG_EQUAL, NULL_RTX);
+ rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (note_set);
rtx new_rtx = simplify_replace_rtx (old_rtx, src, x);
if (old_rtx != new_rtx)
- set_unique_reg_note (use_insn, REG_EQUAL, copy_rtx (new_rtx));
+ set_unique_reg_note (use_rtl, REG_EQUAL, copy_rtx (new_rtx));
}
return false;
}
- if (asm_use >= 0)
- return forward_propagate_asm (use, def_insn, def_set, reg);
-
- /* Else try simplifying. */
-
- if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE)
- {
- loc = &SET_DEST (use_set);
- set_reg_equal = false;
- }
- else if (!use_set)
- {
- loc = &INSN_VAR_LOCATION_LOC (use_insn);
- set_reg_equal = false;
- }
- else
- {
- rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
- if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
- loc = &XEXP (note, 0);
- else
- loc = &SET_SRC (use_set);
-
- /* Do not replace an existing REG_EQUAL note if the insn is not
- recognized. Either we're already replacing in the note, or we'll
- separately try plugging the definition in the note and simplifying.
- And only install a REQ_EQUAL note when the destination is a REG
- that isn't mentioned in USE_SET, as the note would be invalid
- otherwise. We also don't want to install a note if we are merely
- propagating a pseudo since verifying that this pseudo isn't dead
- is a pain; moreover such a note won't help anything.
- If the use is a paradoxical subreg, make sure we don't add a
- REG_EQUAL note for it, because it is not equivalent, it is one
- possible value for it, but we can't rely on it holding that value.
- See PR70574. */
- set_reg_equal = (note == NULL_RTX
- && REG_P (SET_DEST (use_set))
- && !REG_P (src)
- && !(GET_CODE (src) == SUBREG
- && REG_P (SUBREG_REG (src)))
- && !reg_mentioned_p (SET_DEST (use_set),
- SET_SRC (use_set))
- && !paradoxical_subreg_p (DF_REF_REG (use)));
- }
-
- if (GET_MODE (*loc) == VOIDmode)
- mode = GET_MODE (SET_DEST (use_set));
- else
- mode = GET_MODE (*loc);
-
- new_rtx = propagate_rtx (*loc, mode, reg, src,
- optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)));
-
- if (!new_rtx)
- return false;
-
- return try_fwprop_subst (use, loc, new_rtx, def_insn, set_reg_equal);
+ /* ??? Unconditionally propagating into PATTERN would work better
+ for instructions that have match_dups. */
+ rtx *loc = need_single_set ? &use_set : &PATTERN (use_rtl);
+ return try_fwprop_subst (use, def_insn, loc, dest, src);
}
-
/* Given a use USE of an insn, if it has a single reaching
definition, try to forward propagate it into that insn.
- Return true if cfg cleanup will be needed.
+ Return true if something changed.
+
REG_PROP_ONLY is true if we should only propagate register copies. */
static bool
-forward_propagate_into (df_ref use, bool reg_prop_only = false)
+forward_propagate_into (use_info *use, bool reg_prop_only = false)
{
- df_ref def;
- rtx_insn *def_insn, *use_insn;
- rtx def_set;
- rtx parent;
-
- if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
- return false;
- if (DF_REF_IS_ARTIFICIAL (use))
+ if (use->includes_read_writes ())
return false;
- /* Only consider uses that have a single definition. */
- def = get_def_for_use (use);
+ /* Disregard uninitialized uses. */
+ def_info *def = use->def ();
if (!def)
return false;
- if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
- return false;
- if (DF_REF_IS_ARTIFICIAL (def))
- return false;
- /* Check if the use is still present in the insn! */
- use_insn = DF_REF_INSN (use);
- if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
- parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
- else
- parent = PATTERN (use_insn);
+ /* Only consider single-register definitions. This could be relaxed,
+ but it should rarely be needed before RA. */
+ def = look_through_degenerate_phi (def);
+ if (def->includes_multiregs ())
+ return false;
- if (!reg_mentioned_p (DF_REF_REG (use), parent))
+ /* Only consider uses whose definition comes from a real instruction. */
+ insn_info *def_insn = def->insn ();
+ if (def_insn->is_artificial ())
return false;
- def_insn = DF_REF_INSN (def);
- if (multiple_sets (def_insn))
+ rtx_insn *def_rtl = def_insn->rtl ();
+ if (!NONJUMP_INSN_P (def_rtl))
+ return false;
+ /* ??? This seems an unnecessary restriction. We can easily tell
+ which set the definition comes from. */
+ if (multiple_sets (def_rtl))
return false;
- def_set = single_set (def_insn);
+ rtx def_set = simple_regno_set (PATTERN (def_rtl), def->regno ());
if (!def_set)
return false;
- if (reg_prop_only
- && (!reg_single_def_p (SET_SRC (def_set))
- || !reg_single_def_p (SET_DEST (def_set))))
- return false;
+ rtx dest = SET_DEST (def_set);
+ rtx src = SET_SRC (def_set);
/* Allow propagations into a loop only for reg-to-reg copies, since
replacing one register by another shouldn't increase the cost. */
+ struct loop *def_loop = def_insn->bb ()->cfg_bb ()->loop_father;
+ struct loop *use_loop = use->bb ()->cfg_bb ()->loop_father;
+ if ((reg_prop_only || def_loop != use_loop)
+ && (!reg_single_def_p (dest) || !reg_single_def_p (src)))
+ return false;
- if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father
- && (!reg_single_def_p (SET_SRC (def_set))
- || !reg_single_def_p (SET_DEST (def_set))))
+ /* Don't substitute into a non-local goto, this confuses CFG. */
+ insn_info *use_insn = use->insn ();
+ rtx_insn *use_rtl = use_insn->rtl ();
+ if (JUMP_P (use_rtl)
+ && find_reg_note (use_rtl, REG_NON_LOCAL_GOTO, NULL_RTX))
return false;
- /* Only try one kind of propagation. If two are possible, we'll
- do it on the following iterations. */
- if (forward_propagate_and_simplify (use, def_insn, def_set)
- || forward_propagate_subreg (use, def_insn, def_set))
- {
- propagations_left--;
+ if (forward_propagate_and_simplify (use, def_insn, dest, src)
+ || forward_propagate_subreg (use, def_insn, dest, src))
+ return true;
- if (cfun->can_throw_non_call_exceptions
- && find_reg_note (use_insn, REG_EH_REGION, NULL_RTX)
- && purge_dead_edges (DF_REF_BB (use)))
- return true;
- }
return false;
}
-
static void
fwprop_init (void)
@@ -1513,14 +877,8 @@ fwprop_init (void)
build_single_def_use_links. */
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
- build_single_def_use_links ();
- df_set_flags (DF_DEFER_INSN_RESCAN);
-
- active_defs = XNEWVEC (df_ref, max_reg_num ());
- if (flag_checking)
- active_defs_check = sparseset_alloc (max_reg_num ());
-
- propagations_left = DF_USES_TABLE_SIZE ();
+ df_analyze ();
+ crtl->ssa = new rtl_ssa::function_info (cfun);
}
static void
@@ -1528,13 +886,13 @@ fwprop_done (void)
{
loop_optimizer_finalize ();
- use_def_ref.release ();
- free (active_defs);
- if (flag_checking)
- sparseset_free (active_defs_check);
-
+ crtl->ssa->perform_pending_updates ();
free_dominance_info (CDI_DOMINATORS);
cleanup_cfg (0);
+
+ delete crtl->ssa;
+ crtl->ssa = nullptr;
+
delete_trivially_dead_insns (get_insns (), max_reg_num ());
if (dump_file)
@@ -1543,6 +901,41 @@ fwprop_done (void)
num_changes);
}
+/* Try to optimize INSN, returning true if something changes.
+ FWPROP_ADDR_P is true if we are running fwprop_addr rather than
+ the full fwprop. */
+
+static bool
+fwprop_insn (insn_info *insn, bool fwprop_addr_p)
+{
+ for (use_info *use : insn->uses ())
+ {
+ if (use->is_mem ())
+ continue;
+ /* ??? The choices here follow those in the pre-SSA code. */
+ if (!use->includes_address_uses ())
+ {
+ if (forward_propagate_into (use, fwprop_addr_p))
+ return true;
+ }
+ else
+ {
+ struct loop *loop = insn->bb ()->cfg_bb ()->loop_father;
+ /* The outermost loop is not really a loop. */
+ if (loop == NULL || loop_outer (loop) == NULL)
+ {
+ if (forward_propagate_into (use, fwprop_addr_p))
+ return true;
+ }
+ else if (fwprop_addr_p)
+ {
+ if (forward_propagate_into (use, false))
+ return true;
+ }
+ }
+ }
+ return false;
+}
/* Main entry point. */
@@ -1555,33 +948,33 @@ gate_fwprop (void)
static unsigned int
fwprop (bool fwprop_addr_p)
{
- unsigned i;
-
fwprop_init ();
- /* Go through all the uses. df_uses_create will create new ones at the
- end, and we'll go through them as well.
+ /* Go through all the instructions (including debug instructions) looking
+ for uses that we could propagate into.
Do not forward propagate addresses into loops until after unrolling.
CSE did so because it was able to fix its own mess, but we are not. */
- for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
- {
- if (!propagations_left)
- break;
-
- df_ref use = DF_USES_GET (i);
- if (use)
- {
- if (DF_REF_TYPE (use) == DF_REF_REG_USE
- || DF_REF_BB (use)->loop_father == NULL
- /* The outer most loop is not really a loop. */
- || loop_outer (DF_REF_BB (use)->loop_father) == NULL)
- forward_propagate_into (use, fwprop_addr_p);
+ insn_info *next;
- else if (fwprop_addr_p)
- forward_propagate_into (use, false);
- }
+ /* ??? This code uses a worklist in order to preserve the behavior
+ of the pre-SSA implementation. It would be better to instead
+ iterate on each instruction until no more propagations are
+ possible, then move on to the next. */
+ auto_vec<insn_info *> worklist;
+ for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next)
+ {
+ next = insn->next_any_insn ();
+ if (insn->can_be_optimized () || insn->is_debug_insn ())
+ if (fwprop_insn (insn, fwprop_addr_p))
+ worklist.safe_push (insn);
+ }
+ for (unsigned int i = 0; i < worklist.length (); ++i)
+ {
+ insn_info *insn = worklist[i];
+ if (fwprop_insn (insn, fwprop_addr_p))
+ worklist.safe_push (insn);
}
fwprop_done ();
diff --git a/gcc/gcc.c b/gcc/gcc.c
index cdf4d4f..d179de7 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -542,6 +542,12 @@ or with constant text in a single argument.
%s current argument is the name of a library or startup file of some sort.
Search for that file in a standard list of directories
and substitute the full name found.
+ %T current argument is the name of a linker script.
+ Search for that file in the current list of directories to scan for
+ libraries. If the file is located, insert a --script option into the
+ command line followed by the full path name found. If the file is
+ not found then generate an error message.
+ Note: the current working directory is not searched.
%eSTR Print STR as an error message. STR is terminated by a newline.
Use this when inconsistent options are detected.
%nSTR Print STR as a notice. STR is terminated by a newline.
@@ -743,6 +749,24 @@ proper position among the other output files. */
#define LIBASAN_EARLY_SPEC ""
#endif
+#ifndef LIBHWASAN_SPEC
+#define STATIC_LIBHWASAN_LIBS \
+ " %{static-libhwasan|static:%:include(libsanitizer.spec)%(link_libhwasan)}"
+#ifdef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_SPEC STATIC_LIBHWASAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBHWASAN_SPEC "%{static-libhwasan:" LD_STATIC_OPTION \
+ "} -lhwasan %{static-libhwasan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBHWASAN_LIBS
+#else
+#define LIBHWASAN_SPEC "-lhwasan" STATIC_LIBHWASAN_LIBS
+#endif
+#endif
+
+#ifndef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC ""
+#endif
+
#ifndef LIBTSAN_SPEC
#define STATIC_LIBTSAN_LIBS \
" %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}"
@@ -1065,6 +1089,7 @@ proper position among the other output files. */
#ifndef SANITIZER_EARLY_SPEC
#define SANITIZER_EARLY_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
+ %{%:sanitize(hwaddress):" LIBHWASAN_EARLY_SPEC "} \
%{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
%{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}"
#endif
@@ -1074,6 +1099,8 @@ proper position among the other output files. */
#define SANITIZER_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=address}}\
+ %{%:sanitize(hwaddress):" LIBHWASAN_SPEC "\
+ %{static:%ecannot specify -static with -fsanitize=hwaddress}}\
%{%:sanitize(thread):" LIBTSAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=thread}}\
%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
@@ -1205,8 +1232,9 @@ static const char *cpp_unique_options =
%{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
%{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
+ %{Mmodules} %{Mno-modules}\
%{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
- %{remap} %{g3|ggdb3|gstabs3|gxcoff3|gvms3:-dD}\
+ %{remap} %{%:debug-level-gt(2):-dD}\
%{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
%{H} %C %{D*&U*&A*} %{i*} %Z %i\
%{E|M|MM:%W{o*}}";
@@ -3653,7 +3681,7 @@ convert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
/* If there is no filetype, make it the executable suffix (which includes
the "."). But don't get confused if we have just "-o". */
- if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
+ if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || not_actual_file_p (name))
return name;
for (i = len - 1; i >= 0; i--)
@@ -9748,6 +9776,7 @@ print_multilib_info (void)
const char *p = multilib_select;
const char *last_path = 0, *this_path;
int skip;
+ int not_arg;
unsigned int last_path_len = 0;
while (*p != '\0')
@@ -9902,9 +9931,13 @@ print_multilib_info (void)
goto invalid_select;
if (*q == '!')
- arg = NULL;
+ {
+ not_arg = 1;
+ q++;
+ }
else
- arg = q;
+ not_arg = 0;
+ arg = q;
while (*q != ' ' && *q != ';')
{
@@ -9913,11 +9946,17 @@ print_multilib_info (void)
++q;
}
- if (arg != NULL
- && default_arg (arg, q - arg))
+ if (default_arg (arg, q - arg))
{
- skip = 1;
- break;
+ /* Stop checking if any default arguments appeared in not
+ list. */
+ if (not_arg)
+ {
+ skip = 0;
+ break;
+ }
+ else
+ skip = 1;
}
if (*q == ' ')
@@ -10125,8 +10164,12 @@ sanitize_spec_function (int argc, const char **argv)
if (strcmp (argv[0], "address") == 0)
return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "hwaddress") == 0)
+ return (flag_sanitize & SANITIZE_USER_HWADDRESS) ? "" : NULL;
if (strcmp (argv[0], "kernel-address") == 0)
return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "kernel-hwaddress") == 0)
+ return (flag_sanitize & SANITIZE_KERNEL_HWADDRESS) ? "" : NULL;
if (strcmp (argv[0], "thread") == 0)
return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
if (strcmp (argv[0], "undefined") == 0)
@@ -10544,7 +10587,7 @@ static bool
not_actual_file_p (const char *name)
{
return (strcmp (name, "-") == 0
- || strcmp (output_file, HOST_BIT_BUCKET) == 0);
+ || strcmp (name, HOST_BIT_BUCKET) == 0);
}
/* %:dumps spec function. Take an optional argument that overrides
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index 4dba01c..4e95c7c 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -293,7 +293,7 @@ GCOV_COUNTERS
#define GCOV_TOPN_MAXIMUM_TRACKED_VALUES 32
/* Number of pre-allocated gcov_kvp structures. */
-#define GCOV_PREALLOCATED_KVP 16
+#define GCOV_PREALLOCATED_KVP 64
/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 36938bd..8dcec94 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -293,7 +293,7 @@ public:
/* Index of source file where the function is defined. */
unsigned src;
- /* Vector of line information. */
+ /* Vector of line information (used only for group functions). */
vector<line_info> lines;
/* Next function. */
@@ -1165,21 +1165,22 @@ output_json_intermediate_file (json::array *json_files, source_info *src)
json::array *lineso = new json::array ();
root->set ("lines", lineso);
- function_info *last_non_group_fn = NULL;
+ vector<function_info *> last_non_group_fns;
for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
{
vector<function_info *> *fns = src->get_functions_at_location (line_num);
if (fns != NULL)
- /* Print first group functions that begin on the line. */
+ /* Print info for all group functions that begin on the line. */
for (vector<function_info *>::iterator it2 = fns->begin ();
it2 != fns->end (); it2++)
{
if (!(*it2)->is_group)
- last_non_group_fn = *it2;
+ last_non_group_fns.push_back (*it2);
vector<line_info> &lines = (*it2)->lines;
+ /* The LINES array is allocated only for group functions. */
for (unsigned i = 0; i < lines.size (); i++)
{
line_info *line = &lines[i];
@@ -1190,9 +1191,17 @@ output_json_intermediate_file (json::array *json_files, source_info *src)
/* Follow with lines associated with the source file. */
if (line_num < src->lines.size ())
- output_intermediate_json_line (lineso, &src->lines[line_num], line_num,
- (last_non_group_fn != NULL
- ? last_non_group_fn->m_name : NULL));
+ {
+ unsigned size = last_non_group_fns.size ();
+ function_info *last_fn = size > 0 ? last_non_group_fns[size - 1] : NULL;
+ const char *fname = last_fn ? last_fn->m_name : NULL;
+ output_intermediate_json_line (lineso, &src->lines[line_num], line_num,
+ fname);
+
+ /* Pop ending function from stack. */
+ if (last_fn != NULL && last_fn->end_line == line_num)
+ last_non_group_fns.pop_back ();
+ }
}
}
diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in
index e951c19..f2becb4 100644
--- a/gcc/gdbinit.in
+++ b/gcc/gdbinit.in
@@ -46,7 +46,7 @@ call debug ($debug_arg)
end
document pp
-GCC hook: pp [any]
+GCC hook: debug (<multiple overloads>)
Print a representation of any GCC data structure for which an instance of
overloaded function 'debug' is available.
See also 'help-gcc-hooks'.
@@ -58,7 +58,7 @@ call debug_rtx ($debug_arg)
end
document pr
-GCC hook: pr [rtx]
+GCC hook: debug_rtx (rtx)
Print the full structure of given rtx.
See also 'help-gcc-hooks'.
end
@@ -69,7 +69,7 @@ call debug_rtx_list ($debug_arg, debug_rtx_count)
end
document prl
-GCC hook: prl [rtx]
+GCC hook: debug_rtx_list (rtx)
Print the full structure of all rtx insns beginning at given rtx.
Uses variable debug_rtx_count to control number of insns printed:
debug_rtx_count > 0: print from given rtx on.
@@ -85,7 +85,7 @@ call debug_tree ($debug_arg)
end
document pt
-GCC hook: pt [tree]
+GCC hook: debug_tree (tree)
Print the full structure of given tree.
See also 'help-gcc-hooks'.
end
@@ -96,7 +96,7 @@ call debug_c_tree ($debug_arg)
end
document pct
-GCC hook: pct [tree]
+GCC hook: debug_c_tree (tree)
Print given tree in C syntax.
See also 'help-gcc-hooks'.
end
@@ -107,7 +107,7 @@ call debug_gimple_stmt ($debug_arg)
end
document pgg
-GCC hook: pgg [gimple]
+GCC hook: debug_gimple_stmt (gimple)
Print given GIMPLE statement in C syntax.
See also 'help-gcc-hooks'.
end
@@ -118,7 +118,7 @@ call debug_gimple_seq ($debug_arg)
end
document pgq
-GCC hook: pgq [gimple_seq]
+GCC hook: debug_gimple_seq (gimple_seq)
Print given GIMPLE sequence in C syntax.
See also 'help-gcc-hooks'.
end
@@ -129,7 +129,7 @@ call debug_generic_stmt ($debug_arg)
end
document pgs
-GCC hook: pgs [tree]
+GCC hook: debug_generic_stmt (tree)
Print given GENERIC statement in C syntax.
See also 'help-gcc-hooks'.
end
@@ -140,7 +140,7 @@ call debug_generic_expr ($debug_arg)
end
document pge
-GCC hook: pge [tree]
+GCC hook: debug_generic_expr (tree)
Print given GENERIC expression in C syntax.
See also 'help-gcc-hooks'.
end
@@ -151,7 +151,7 @@ call mpz_out_str(stderr, 10, $debug_arg)
end
document pmz
-GCC hook: pmz [mpz_t]
+GCC hook: mpz_out_str (mpz_t)
Print given mpz value.
See also 'help-gcc-hooks'.
end
@@ -163,7 +163,7 @@ echo \n
end
document ptc
-GCC hook: ptc [tree]
+GCC hook: TREE_CODE (tree)
Print the tree-code of given tree node.
See also 'help-gcc-hooks'.
end
@@ -175,7 +175,7 @@ echo \n
end
document pdn
-GCC hook: pdn [tree]
+GCC hook: IDENTIFIER_POINTER (DECL_NAME (tree))
Print the name of given decl-node.
See also 'help-gcc-hooks'.
end
@@ -187,7 +187,7 @@ echo \n
end
document ptn
-GCC hook: ptn [tree]
+GCC hook: IDENTIFIER_POINTER (DECL_NAME (TREE_TYPE (tree)))
Print the name of given type-node.
See also 'help-gcc-hooks'.
end
@@ -198,7 +198,7 @@ call debug_dwarf_die ($debug_arg)
end
document pdd
-GCC hook: pdd [dw_die_ref]
+GCC hook: debug_dwarf_die (dw_die_ref)
Print given dw_die_ref.
See also 'help-gcc-hooks'.
end
@@ -212,7 +212,7 @@ echo )\n
end
document prc
-GCC hook: prc [rtx]
+GCC hook: GET_CODE (rtx)
Print the rtx-code and machine mode of given rtx.
See also 'help-gcc-hooks'.
end
@@ -223,7 +223,7 @@ print $debug_arg.u.fld[0].rt_rtx@7
end
document pi
-GCC hook: pi [rtx_insn]
+GCC hook: X0EXP (rtx_insn)
Print the fields of given RTL instruction.
See also 'help-gcc-hooks'.
end
@@ -243,7 +243,7 @@ call bitmap_print (stderr, $debug_arg, "", "\n")
end
document pbm
-GCC hook: pbm [bitmap]
+GCC hook: bitmap_print (bitmap)
Dump given bitmap as a comma-separated list of numbers.
See also 'help-gcc-hooks'.
end
@@ -255,7 +255,7 @@ echo \n
end
document pel
-GCC hook: pel [location_t]
+GCC hook: expand_location (location_t)
Print given location.
See also 'help-gcc-hooks'.
end
@@ -275,7 +275,7 @@ print ($debug_arg.typed.type)
end
document trt
-GCC hook: trt [tree]
+GCC hook: TREE_TYPE (tree)
Print TREE_TYPE of given tree node.
See also 'help-gcc-hooks'.
end
diff --git a/gcc/genextract.c b/gcc/genextract.c
index 63911e7..359681e 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -365,6 +365,8 @@ print_header (void)
#define IN_TARGET_CODE 1\n\
#include \"config.h\"\n\
#include \"system.h\"\n\
+#undef ENABLE_RTL_CHECKING\n\
+#undef ENABLE_RTL_FLAG_CHECKING\n\
#include \"coretypes.h\"\n\
#include \"tm.h\"\n\
#include \"rtl.h\"\n\
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index dd21ade..b21eeac 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,6 +1727,7 @@ open_base_files (void)
"target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
"ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
"omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
+ "symtab-clones.h",
NULL
};
const char *const *ifp;
@@ -5199,6 +5200,7 @@ main (int argc, char **argv)
POS_HERE (do_scalar_typedef ("widest_int", &pos));
POS_HERE (do_scalar_typedef ("int64_t", &pos));
POS_HERE (do_scalar_typedef ("poly_int64", &pos));
+ POS_HERE (do_scalar_typedef ("poly_uint64", &pos));
POS_HERE (do_scalar_typedef ("uint64_t", &pos));
POS_HERE (do_scalar_typedef ("uint8", &pos));
POS_HERE (do_scalar_typedef ("uintptr_t", &pos));
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index bd78310..34b52fe 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -358,6 +358,14 @@ complete_mode (struct mode_data *m)
m->component = 0;
break;
+ case MODE_OPAQUE:
+ /* Opaque modes have size and precision. */
+ validate_mode (m, OPTIONAL, SET, UNSET, UNSET, UNSET);
+
+ m->ncomponents = 1;
+ m->component = 0;
+ break;
+
case MODE_PARTIAL_INT:
/* A partial integer mode uses ->component to say what the
corresponding full-size integer mode is, and may also
@@ -588,6 +596,20 @@ make_int_mode (const char *name,
m->precision = precision;
}
+#define OPAQUE_MODE(N, B) \
+ make_opaque_mode (#N, -1U, B, __FILE__, __LINE__)
+
+static void ATTRIBUTE_UNUSED
+make_opaque_mode (const char *name,
+ unsigned int precision,
+ unsigned int bytesize,
+ const char *file, unsigned int line)
+{
+ struct mode_data *m = new_mode (MODE_OPAQUE, name, file, line);
+ m->bytesize = bytesize;
+ m->precision = precision;
+}
+
#define FRACT_MODE(N, Y, F) \
make_fixed_point_mode (MODE_FRACT, #N, Y, 0, F, __FILE__, __LINE__)
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index c3fa4cb..3148c6b 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2689,7 +2689,7 @@ gimple_fold_builtin_memchr (gimple_stmt_iterator *gsi)
gimple_seq stmts = NULL;
if (lhs != NULL_TREE)
{
- tree offset_cst = build_int_cst (TREE_TYPE (len), offset);
+ tree offset_cst = build_int_cst (sizetype, offset);
gassign *stmt = gimple_build_assign (lhs, POINTER_PLUS_EXPR,
arg1, offset_cst);
gimple_seq_add_stmt_without_update (&stmts, stmt);
@@ -3948,6 +3948,858 @@ gimple_fold_builtin_realloc (gimple_stmt_iterator *gsi)
return false;
}
+/* Number of bytes into which any type but aggregate or vector types
+ should fit. */
+static constexpr size_t clear_padding_unit
+ = MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT;
+/* Buffer size on which __builtin_clear_padding folding code works. */
+static const size_t clear_padding_buf_size = 32 * clear_padding_unit;
+
+/* Data passed through __builtin_clear_padding folding. */
+struct clear_padding_struct {
+ location_t loc;
+ /* 0 during __builtin_clear_padding folding, nonzero during
+ clear_type_padding_in_mask. In that case, instead of clearing the
+ non-padding bits in union_ptr array clear the padding bits in there. */
+ bool clear_in_mask;
+ tree base;
+ tree alias_type;
+ gimple_stmt_iterator *gsi;
+ /* Alignment of buf->base + 0. */
+ unsigned align;
+ /* Offset from buf->base. Should be always a multiple of UNITS_PER_WORD. */
+ HOST_WIDE_INT off;
+ /* Number of padding bytes before buf->off that don't have padding clear
+ code emitted yet. */
+ HOST_WIDE_INT padding_bytes;
+ /* The size of the whole object. Never emit code to touch
+ buf->base + buf->sz or following bytes. */
+ HOST_WIDE_INT sz;
+ /* Number of bytes recorded in buf->buf. */
+ size_t size;
+ /* When inside union, instead of emitting code we and bits inside of
+ the union_ptr array. */
+ unsigned char *union_ptr;
+ /* Set bits mean padding bits that need to be cleared by the builtin. */
+ unsigned char buf[clear_padding_buf_size + clear_padding_unit];
+};
+
+/* Emit code to clear padding requested in BUF->buf - set bits
+ in there stand for padding that should be cleared. FULL is true
+ if everything from the buffer should be flushed, otherwise
+ it can leave up to 2 * clear_padding_unit bytes for further
+ processing. */
+
+static void
+clear_padding_flush (clear_padding_struct *buf, bool full)
+{
+ gcc_assert ((clear_padding_unit % UNITS_PER_WORD) == 0);
+ if (!full && buf->size < 2 * clear_padding_unit)
+ return;
+ gcc_assert ((buf->off % UNITS_PER_WORD) == 0);
+ size_t end = buf->size;
+ if (!full)
+ end = ((end - clear_padding_unit - 1) / clear_padding_unit
+ * clear_padding_unit);
+ size_t padding_bytes = buf->padding_bytes;
+ if (buf->union_ptr)
+ {
+ if (buf->clear_in_mask)
+ {
+ /* During clear_type_padding_in_mask, clear the padding
+ bits set in buf->buf in the buf->union_ptr mask. */
+ for (size_t i = 0; i < end; i++)
+ {
+ if (buf->buf[i] == (unsigned char) ~0)
+ padding_bytes++;
+ else
+ {
+ memset (&buf->union_ptr[buf->off + i - padding_bytes],
+ 0, padding_bytes);
+ padding_bytes = 0;
+ buf->union_ptr[buf->off + i] &= ~buf->buf[i];
+ }
+ }
+ if (full)
+ {
+ memset (&buf->union_ptr[buf->off + end - padding_bytes],
+ 0, padding_bytes);
+ buf->off = 0;
+ buf->size = 0;
+ buf->padding_bytes = 0;
+ }
+ else
+ {
+ memmove (buf->buf, buf->buf + end, buf->size - end);
+ buf->off += end;
+ buf->size -= end;
+ buf->padding_bytes = padding_bytes;
+ }
+ return;
+ }
+ /* Inside of a union, instead of emitting any code, instead
+ clear all bits in the union_ptr buffer that are clear
+ in buf. Whole padding bytes don't clear anything. */
+ for (size_t i = 0; i < end; i++)
+ {
+ if (buf->buf[i] == (unsigned char) ~0)
+ padding_bytes++;
+ else
+ {
+ padding_bytes = 0;
+ buf->union_ptr[buf->off + i] &= buf->buf[i];
+ }
+ }
+ if (full)
+ {
+ buf->off = 0;
+ buf->size = 0;
+ buf->padding_bytes = 0;
+ }
+ else
+ {
+ memmove (buf->buf, buf->buf + end, buf->size - end);
+ buf->off += end;
+ buf->size -= end;
+ buf->padding_bytes = padding_bytes;
+ }
+ return;
+ }
+ size_t wordsize = UNITS_PER_WORD;
+ for (size_t i = 0; i < end; i += wordsize)
+ {
+ size_t nonzero_first = wordsize;
+ size_t nonzero_last = 0;
+ size_t zero_first = wordsize;
+ size_t zero_last = 0;
+ bool all_ones = true, bytes_only = true;
+ if ((unsigned HOST_WIDE_INT) (buf->off + i + wordsize)
+ > (unsigned HOST_WIDE_INT) buf->sz)
+ {
+ gcc_assert (wordsize > 1);
+ wordsize /= 2;
+ i -= wordsize;
+ continue;
+ }
+ for (size_t j = i; j < i + wordsize && j < end; j++)
+ {
+ if (buf->buf[j])
+ {
+ if (nonzero_first == wordsize)
+ {
+ nonzero_first = j - i;
+ nonzero_last = j - i;
+ }
+ if (nonzero_last != j - i)
+ all_ones = false;
+ nonzero_last = j + 1 - i;
+ }
+ else
+ {
+ if (zero_first == wordsize)
+ zero_first = j - i;
+ zero_last = j + 1 - i;
+ }
+ if (buf->buf[j] != 0 && buf->buf[j] != (unsigned char) ~0)
+ {
+ all_ones = false;
+ bytes_only = false;
+ }
+ }
+ size_t padding_end = i;
+ if (padding_bytes)
+ {
+ if (nonzero_first == 0
+ && nonzero_last == wordsize
+ && all_ones)
+ {
+ /* All bits are padding and we had some padding
+ before too. Just extend it. */
+ padding_bytes += wordsize;
+ continue;
+ }
+ if (all_ones && nonzero_first == 0)
+ {
+ padding_bytes += nonzero_last;
+ padding_end += nonzero_last;
+ nonzero_first = wordsize;
+ nonzero_last = 0;
+ }
+ else if (bytes_only && nonzero_first == 0)
+ {
+ gcc_assert (zero_first && zero_first != wordsize);
+ padding_bytes += zero_first;
+ padding_end += zero_first;
+ }
+ tree atype, src;
+ if (padding_bytes == 1)
+ {
+ atype = char_type_node;
+ src = build_zero_cst (char_type_node);
+ }
+ else
+ {
+ atype = build_array_type_nelts (char_type_node, padding_bytes);
+ src = build_constructor (atype, NULL);
+ }
+ tree dst = build2_loc (buf->loc, MEM_REF, atype, buf->base,
+ build_int_cst (buf->alias_type,
+ buf->off + padding_end
+ - padding_bytes));
+ gimple *g = gimple_build_assign (dst, src);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ padding_bytes = 0;
+ buf->padding_bytes = 0;
+ }
+ if (nonzero_first == wordsize)
+ /* All bits in a word are 0, there are no padding bits. */
+ continue;
+ if (all_ones && nonzero_last == wordsize)
+ {
+ /* All bits between nonzero_first and end of word are padding
+ bits, start counting padding_bytes. */
+ padding_bytes = nonzero_last - nonzero_first;
+ continue;
+ }
+ if (bytes_only)
+ {
+ /* If bitfields aren't involved in this word, prefer storing
+ individual bytes or groups of them over performing a RMW
+ operation on the whole word. */
+ gcc_assert (i + zero_last <= end);
+ for (size_t j = padding_end; j < i + zero_last; j++)
+ {
+ if (buf->buf[j])
+ {
+ size_t k;
+ for (k = j; k < i + zero_last; k++)
+ if (buf->buf[k] == 0)
+ break;
+ HOST_WIDE_INT off = buf->off + j;
+ tree atype, src;
+ if (k - j == 1)
+ {
+ atype = char_type_node;
+ src = build_zero_cst (char_type_node);
+ }
+ else
+ {
+ atype = build_array_type_nelts (char_type_node, k - j);
+ src = build_constructor (atype, NULL);
+ }
+ tree dst = build2_loc (buf->loc, MEM_REF, atype,
+ buf->base,
+ build_int_cst (buf->alias_type, off));
+ gimple *g = gimple_build_assign (dst, src);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ j = k;
+ }
+ }
+ if (nonzero_last == wordsize)
+ padding_bytes = nonzero_last - zero_last;
+ continue;
+ }
+ for (size_t eltsz = 1; eltsz <= wordsize; eltsz <<= 1)
+ {
+ if (nonzero_last - nonzero_first <= eltsz
+ && ((nonzero_first & ~(eltsz - 1))
+ == ((nonzero_last - 1) & ~(eltsz - 1))))
+ {
+ tree type;
+ if (eltsz == 1)
+ type = char_type_node;
+ else
+ type = lang_hooks.types.type_for_size (eltsz * BITS_PER_UNIT,
+ 0);
+ size_t start = nonzero_first & ~(eltsz - 1);
+ HOST_WIDE_INT off = buf->off + i + start;
+ tree atype = type;
+ if (eltsz > 1 && buf->align < TYPE_ALIGN (type))
+ atype = build_aligned_type (type, buf->align);
+ tree dst = build2_loc (buf->loc, MEM_REF, atype, buf->base,
+ build_int_cst (buf->alias_type, off));
+ tree src;
+ gimple *g;
+ if (all_ones
+ && nonzero_first == start
+ && nonzero_last == start + eltsz)
+ src = build_zero_cst (type);
+ else
+ {
+ src = make_ssa_name (type);
+ g = gimple_build_assign (src, unshare_expr (dst));
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ tree mask = native_interpret_expr (type,
+ buf->buf + i + start,
+ eltsz);
+ gcc_assert (mask && TREE_CODE (mask) == INTEGER_CST);
+ mask = fold_build1 (BIT_NOT_EXPR, type, mask);
+ tree src_masked = make_ssa_name (type);
+ g = gimple_build_assign (src_masked, BIT_AND_EXPR,
+ src, mask);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ src = src_masked;
+ }
+ g = gimple_build_assign (dst, src);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ break;
+ }
+ }
+ }
+ if (full)
+ {
+ if (padding_bytes)
+ {
+ tree atype, src;
+ if (padding_bytes == 1)
+ {
+ atype = char_type_node;
+ src = build_zero_cst (char_type_node);
+ }
+ else
+ {
+ atype = build_array_type_nelts (char_type_node, padding_bytes);
+ src = build_constructor (atype, NULL);
+ }
+ tree dst = build2_loc (buf->loc, MEM_REF, atype, buf->base,
+ build_int_cst (buf->alias_type,
+ buf->off + end
+ - padding_bytes));
+ gimple *g = gimple_build_assign (dst, src);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ }
+ size_t end_rem = end % UNITS_PER_WORD;
+ buf->off += end - end_rem;
+ buf->size = end_rem;
+ memset (buf->buf, 0, buf->size);
+ buf->padding_bytes = 0;
+ }
+ else
+ {
+ memmove (buf->buf, buf->buf + end, buf->size - end);
+ buf->off += end;
+ buf->size -= end;
+ buf->padding_bytes = padding_bytes;
+ }
+}
+
+/* Append PADDING_BYTES padding bytes. */
+
+static void
+clear_padding_add_padding (clear_padding_struct *buf,
+ HOST_WIDE_INT padding_bytes)
+{
+ if (padding_bytes == 0)
+ return;
+ if ((unsigned HOST_WIDE_INT) padding_bytes + buf->size
+ > (unsigned HOST_WIDE_INT) clear_padding_buf_size)
+ clear_padding_flush (buf, false);
+ if ((unsigned HOST_WIDE_INT) padding_bytes + buf->size
+ > (unsigned HOST_WIDE_INT) clear_padding_buf_size)
+ {
+ memset (buf->buf + buf->size, ~0, clear_padding_buf_size - buf->size);
+ padding_bytes -= clear_padding_buf_size - buf->size;
+ buf->size = clear_padding_buf_size;
+ clear_padding_flush (buf, false);
+ gcc_assert (buf->padding_bytes);
+ /* At this point buf->buf[0] through buf->buf[buf->size - 1]
+ is guaranteed to be all ones. */
+ padding_bytes += buf->size;
+ buf->size = padding_bytes % UNITS_PER_WORD;
+ memset (buf->buf, ~0, buf->size);
+ buf->off += padding_bytes - buf->size;
+ buf->padding_bytes += padding_bytes - buf->size;
+ }
+ else
+ {
+ memset (buf->buf + buf->size, ~0, padding_bytes);
+ buf->size += padding_bytes;
+ }
+}
+
+static void clear_padding_type (clear_padding_struct *, tree, HOST_WIDE_INT);
+
+/* Clear padding bits of union type TYPE. */
+
+static void
+clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
+{
+ clear_padding_struct *union_buf;
+ HOST_WIDE_INT start_off = 0, next_off = 0;
+ size_t start_size = 0;
+ if (buf->union_ptr)
+ {
+ start_off = buf->off + buf->size;
+ next_off = start_off + sz;
+ start_size = start_off % UNITS_PER_WORD;
+ start_off -= start_size;
+ clear_padding_flush (buf, true);
+ union_buf = buf;
+ }
+ else
+ {
+ if (sz + buf->size > clear_padding_buf_size)
+ clear_padding_flush (buf, false);
+ union_buf = XALLOCA (clear_padding_struct);
+ union_buf->loc = buf->loc;
+ union_buf->clear_in_mask = buf->clear_in_mask;
+ union_buf->base = NULL_TREE;
+ union_buf->alias_type = NULL_TREE;
+ union_buf->gsi = NULL;
+ union_buf->align = 0;
+ union_buf->off = 0;
+ union_buf->padding_bytes = 0;
+ union_buf->sz = sz;
+ union_buf->size = 0;
+ if (sz + buf->size <= clear_padding_buf_size)
+ union_buf->union_ptr = buf->buf + buf->size;
+ else
+ union_buf->union_ptr = XNEWVEC (unsigned char, sz);
+ memset (union_buf->union_ptr, ~0, sz);
+ }
+
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL && !DECL_PADDING_P (field))
+ {
+ if (DECL_SIZE_UNIT (field) == NULL_TREE)
+ {
+ if (TREE_TYPE (field) == error_mark_node)
+ continue;
+ gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+ && !COMPLETE_TYPE_P (TREE_TYPE (field)));
+ if (!buf->clear_in_mask)
+ error_at (buf->loc, "flexible array member %qD does not have "
+ "well defined padding bits for %qs",
+ field, "__builtin_clear_padding");
+ continue;
+ }
+ HOST_WIDE_INT fldsz = tree_to_shwi (DECL_SIZE_UNIT (field));
+ gcc_assert (union_buf->size == 0);
+ union_buf->off = start_off;
+ union_buf->size = start_size;
+ memset (union_buf->buf, ~0, start_size);
+ clear_padding_type (union_buf, TREE_TYPE (field), fldsz);
+ clear_padding_add_padding (union_buf, sz - fldsz);
+ clear_padding_flush (union_buf, true);
+ }
+
+ if (buf == union_buf)
+ {
+ buf->off = next_off;
+ buf->size = next_off % UNITS_PER_WORD;
+ buf->off -= buf->size;
+ memset (buf->buf, ~0, buf->size);
+ }
+ else if (sz + buf->size <= clear_padding_buf_size)
+ buf->size += sz;
+ else
+ {
+ unsigned char *union_ptr = union_buf->union_ptr;
+ while (sz)
+ {
+ clear_padding_flush (buf, false);
+ HOST_WIDE_INT this_sz
+ = MIN ((unsigned HOST_WIDE_INT) sz,
+ clear_padding_buf_size - buf->size);
+ memcpy (buf->buf + buf->size, union_ptr, this_sz);
+ buf->size += this_sz;
+ union_ptr += this_sz;
+ sz -= this_sz;
+ }
+ XDELETE (union_buf->union_ptr);
+ }
+}
+
+/* The only known floating point formats with padding bits are the
+ IEEE extended ones. */
+
+static bool
+clear_padding_real_needs_padding_p (tree type)
+{
+ const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
+ return (fmt->b == 2
+ && fmt->signbit_ro == fmt->signbit_rw
+ && (fmt->signbit_ro == 79 || fmt->signbit_ro == 95));
+}
+
+/* Return true if TYPE might contain any padding bits. */
+
+static bool
+clear_padding_type_may_have_padding_p (tree type)
+{
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ return true;
+ case ARRAY_TYPE:
+ case COMPLEX_TYPE:
+ case VECTOR_TYPE:
+ return clear_padding_type_may_have_padding_p (TREE_TYPE (type));
+ case REAL_TYPE:
+ return clear_padding_real_needs_padding_p (type);
+ default:
+ return false;
+ }
+}
+
+/* Emit a runtime loop:
+ for (; buf.base != end; buf.base += sz)
+ __builtin_clear_padding (buf.base); */
+
+static void
+clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
+{
+ tree l1 = create_artificial_label (buf->loc);
+ tree l2 = create_artificial_label (buf->loc);
+ tree l3 = create_artificial_label (buf->loc);
+ gimple *g = gimple_build_goto (l2);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ g = gimple_build_label (l1);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ clear_padding_type (buf, type, buf->sz);
+ clear_padding_flush (buf, true);
+ g = gimple_build_assign (buf->base, POINTER_PLUS_EXPR, buf->base,
+ size_int (buf->sz));
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ g = gimple_build_label (l2);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ g = gimple_build_cond (NE_EXPR, buf->base, end, l1, l3);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ g = gimple_build_label (l3);
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+}
+
+/* Clear padding bits for TYPE. Called recursively from
+ gimple_fold_builtin_clear_padding. */
+
+static void
+clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
+{
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ HOST_WIDE_INT cur_pos;
+ cur_pos = 0;
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL && !DECL_PADDING_P (field))
+ {
+ tree ftype = TREE_TYPE (field);
+ if (DECL_BIT_FIELD (field))
+ {
+ HOST_WIDE_INT fldsz = TYPE_PRECISION (ftype);
+ if (fldsz == 0)
+ continue;
+ HOST_WIDE_INT pos = int_byte_position (field);
+ HOST_WIDE_INT bpos
+ = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field));
+ bpos %= BITS_PER_UNIT;
+ HOST_WIDE_INT end
+ = ROUND_UP (bpos + fldsz, BITS_PER_UNIT) / BITS_PER_UNIT;
+ if (pos + end > cur_pos)
+ {
+ clear_padding_add_padding (buf, pos + end - cur_pos);
+ cur_pos = pos + end;
+ }
+ gcc_assert (cur_pos > pos
+ && ((unsigned HOST_WIDE_INT) buf->size
+ >= (unsigned HOST_WIDE_INT) cur_pos - pos));
+ unsigned char *p = buf->buf + buf->size - (cur_pos - pos);
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ sorry_at (buf->loc, "PDP11 bit-field handling unsupported"
+ " in %qs", "__builtin_clear_padding");
+ else if (BYTES_BIG_ENDIAN)
+ {
+ /* Big endian. */
+ if (bpos + fldsz <= BITS_PER_UNIT)
+ *p &= ~(((1 << fldsz) - 1)
+ << (BITS_PER_UNIT - bpos - fldsz));
+ else
+ {
+ if (bpos)
+ {
+ *p &= ~(((1U << BITS_PER_UNIT) - 1) >> bpos);
+ p++;
+ fldsz -= BITS_PER_UNIT - bpos;
+ }
+ memset (p, 0, fldsz / BITS_PER_UNIT);
+ p += fldsz / BITS_PER_UNIT;
+ fldsz %= BITS_PER_UNIT;
+ if (fldsz)
+ *p &= ((1U << BITS_PER_UNIT) - 1) >> fldsz;
+ }
+ }
+ else
+ {
+ /* Little endian. */
+ if (bpos + fldsz <= BITS_PER_UNIT)
+ *p &= ~(((1 << fldsz) - 1) << bpos);
+ else
+ {
+ if (bpos)
+ {
+ *p &= ~(((1 << BITS_PER_UNIT) - 1) << bpos);
+ p++;
+ fldsz -= BITS_PER_UNIT - bpos;
+ }
+ memset (p, 0, fldsz / BITS_PER_UNIT);
+ p += fldsz / BITS_PER_UNIT;
+ fldsz %= BITS_PER_UNIT;
+ if (fldsz)
+ *p &= ~((1 << fldsz) - 1);
+ }
+ }
+ }
+ else if (DECL_SIZE_UNIT (field) == NULL_TREE)
+ {
+ if (ftype == error_mark_node)
+ continue;
+ gcc_assert (TREE_CODE (ftype) == ARRAY_TYPE
+ && !COMPLETE_TYPE_P (ftype));
+ if (!buf->clear_in_mask)
+ error_at (buf->loc, "flexible array member %qD does not "
+ "have well defined padding bits for %qs",
+ field, "__builtin_clear_padding");
+ }
+ else if (is_empty_type (TREE_TYPE (field)))
+ continue;
+ else
+ {
+ HOST_WIDE_INT pos = int_byte_position (field);
+ HOST_WIDE_INT fldsz = tree_to_shwi (DECL_SIZE_UNIT (field));
+ gcc_assert (pos >= 0 && fldsz >= 0 && pos >= cur_pos);
+ clear_padding_add_padding (buf, pos - cur_pos);
+ cur_pos = pos;
+ clear_padding_type (buf, TREE_TYPE (field), fldsz);
+ cur_pos += fldsz;
+ }
+ }
+ gcc_assert (sz >= cur_pos);
+ clear_padding_add_padding (buf, sz - cur_pos);
+ break;
+ case ARRAY_TYPE:
+ HOST_WIDE_INT nelts, fldsz;
+ fldsz = int_size_in_bytes (TREE_TYPE (type));
+ if (fldsz == 0)
+ break;
+ nelts = sz / fldsz;
+ if (nelts > 1
+ && sz > 8 * UNITS_PER_WORD
+ && buf->union_ptr == NULL
+ && clear_padding_type_may_have_padding_p (TREE_TYPE (type)))
+ {
+ /* For sufficiently large array of more than one elements,
+ emit a runtime loop to keep code size manageable. */
+ tree base = buf->base;
+ unsigned int prev_align = buf->align;
+ HOST_WIDE_INT off = buf->off + buf->size;
+ HOST_WIDE_INT prev_sz = buf->sz;
+ clear_padding_flush (buf, true);
+ tree elttype = TREE_TYPE (type);
+ buf->base = create_tmp_var (build_pointer_type (elttype));
+ tree end = make_ssa_name (TREE_TYPE (buf->base));
+ gimple *g = gimple_build_assign (buf->base, POINTER_PLUS_EXPR,
+ base, size_int (off));
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (end, POINTER_PLUS_EXPR, buf->base,
+ size_int (sz));
+ gimple_set_location (g, buf->loc);
+ gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
+ buf->sz = fldsz;
+ buf->align = TYPE_ALIGN (elttype);
+ buf->off = 0;
+ buf->size = 0;
+ clear_padding_emit_loop (buf, elttype, end);
+ buf->base = base;
+ buf->sz = prev_sz;
+ buf->align = prev_align;
+ buf->size = off % UNITS_PER_WORD;
+ buf->off = off - buf->size;
+ memset (buf->buf, 0, buf->size);
+ break;
+ }
+ for (HOST_WIDE_INT i = 0; i < nelts; i++)
+ clear_padding_type (buf, TREE_TYPE (type), fldsz);
+ break;
+ case UNION_TYPE:
+ clear_padding_union (buf, type, sz);
+ break;
+ case REAL_TYPE:
+ gcc_assert ((size_t) sz <= clear_padding_unit);
+ if ((unsigned HOST_WIDE_INT) sz + buf->size > clear_padding_buf_size)
+ clear_padding_flush (buf, false);
+ if (clear_padding_real_needs_padding_p (type))
+ {
+ /* Use native_interpret_expr + native_encode_expr to figure out
+ which bits are padding. */
+ memset (buf->buf + buf->size, ~0, sz);
+ tree cst = native_interpret_expr (type, buf->buf + buf->size, sz);
+ gcc_assert (cst && TREE_CODE (cst) == REAL_CST);
+ int len = native_encode_expr (cst, buf->buf + buf->size, sz);
+ gcc_assert (len > 0 && (size_t) len == (size_t) sz);
+ for (size_t i = 0; i < (size_t) sz; i++)
+ buf->buf[buf->size + i] ^= ~0;
+ }
+ else
+ memset (buf->buf + buf->size, 0, sz);
+ buf->size += sz;
+ break;
+ case COMPLEX_TYPE:
+ fldsz = int_size_in_bytes (TREE_TYPE (type));
+ clear_padding_type (buf, TREE_TYPE (type), fldsz);
+ clear_padding_type (buf, TREE_TYPE (type), fldsz);
+ break;
+ case VECTOR_TYPE:
+ nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
+ fldsz = int_size_in_bytes (TREE_TYPE (type));
+ for (HOST_WIDE_INT i = 0; i < nelts; i++)
+ clear_padding_type (buf, TREE_TYPE (type), fldsz);
+ break;
+ case NULLPTR_TYPE:
+ gcc_assert ((size_t) sz <= clear_padding_unit);
+ if ((unsigned HOST_WIDE_INT) sz + buf->size > clear_padding_buf_size)
+ clear_padding_flush (buf, false);
+ memset (buf->buf + buf->size, ~0, sz);
+ buf->size += sz;
+ break;
+ default:
+ gcc_assert ((size_t) sz <= clear_padding_unit);
+ if ((unsigned HOST_WIDE_INT) sz + buf->size > clear_padding_buf_size)
+ clear_padding_flush (buf, false);
+ memset (buf->buf + buf->size, 0, sz);
+ buf->size += sz;
+ break;
+ }
+}
+
+/* Clear padding bits of TYPE in MASK. */
+
+void
+clear_type_padding_in_mask (tree type, unsigned char *mask)
+{
+ clear_padding_struct buf;
+ buf.loc = UNKNOWN_LOCATION;
+ buf.clear_in_mask = true;
+ buf.base = NULL_TREE;
+ buf.alias_type = NULL_TREE;
+ buf.gsi = NULL;
+ buf.align = 0;
+ buf.off = 0;
+ buf.padding_bytes = 0;
+ buf.sz = int_size_in_bytes (type);
+ buf.size = 0;
+ buf.union_ptr = mask;
+ clear_padding_type (&buf, type, buf.sz);
+ clear_padding_flush (&buf, true);
+}
+
+/* Fold __builtin_clear_padding builtin. */
+
+static bool
+gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
+{
+ gimple *stmt = gsi_stmt (*gsi);
+ gcc_assert (gimple_call_num_args (stmt) == 2);
+ tree ptr = gimple_call_arg (stmt, 0);
+ tree typearg = gimple_call_arg (stmt, 1);
+ tree type = TREE_TYPE (TREE_TYPE (typearg));
+ location_t loc = gimple_location (stmt);
+ clear_padding_struct buf;
+ gimple_stmt_iterator gsiprev = *gsi;
+ /* This should be folded during the lower pass. */
+ gcc_assert (!gimple_in_ssa_p (cfun) && cfun->cfg == NULL);
+ gcc_assert (COMPLETE_TYPE_P (type));
+ gsi_prev (&gsiprev);
+
+ buf.loc = loc;
+ buf.clear_in_mask = false;
+ buf.base = ptr;
+ buf.alias_type = NULL_TREE;
+ buf.gsi = gsi;
+ buf.align = get_pointer_alignment (ptr);
+ unsigned int talign = min_align_of_type (type) * BITS_PER_UNIT;
+ buf.align = MAX (buf.align, talign);
+ buf.off = 0;
+ buf.padding_bytes = 0;
+ buf.size = 0;
+ buf.sz = int_size_in_bytes (type);
+ buf.union_ptr = NULL;
+ if (buf.sz < 0 && int_size_in_bytes (strip_array_types (type)) < 0)
+ sorry_at (loc, "%s not supported for variable length aggregates",
+ "__builtin_clear_padding");
+ /* The implementation currently assumes 8-bit host and target
+ chars which is the case for all currently supported targets
+ and hosts and is required e.g. for native_{encode,interpret}* APIs. */
+ else if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
+ sorry_at (loc, "%s not supported on this target",
+ "__builtin_clear_padding");
+ else if (!clear_padding_type_may_have_padding_p (type))
+ ;
+ else if (TREE_CODE (type) == ARRAY_TYPE && buf.sz < 0)
+ {
+ tree sz = TYPE_SIZE_UNIT (type);
+ tree elttype = type;
+ /* Only supports C/C++ VLAs and flattens all the VLA levels. */
+ while (TREE_CODE (elttype) == ARRAY_TYPE
+ && int_size_in_bytes (elttype) < 0)
+ elttype = TREE_TYPE (elttype);
+ HOST_WIDE_INT eltsz = int_size_in_bytes (elttype);
+ gcc_assert (eltsz >= 0);
+ if (eltsz)
+ {
+ buf.base = create_tmp_var (build_pointer_type (elttype));
+ tree end = make_ssa_name (TREE_TYPE (buf.base));
+ gimple *g = gimple_build_assign (buf.base, ptr);
+ gimple_set_location (g, loc);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (end, POINTER_PLUS_EXPR, buf.base, sz);
+ gimple_set_location (g, loc);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ buf.sz = eltsz;
+ buf.align = TYPE_ALIGN (elttype);
+ buf.alias_type = build_pointer_type (elttype);
+ clear_padding_emit_loop (&buf, elttype, end);
+ }
+ }
+ else
+ {
+ if (!is_gimple_mem_ref_addr (buf.base))
+ {
+ buf.base = make_ssa_name (TREE_TYPE (ptr));
+ gimple *g = gimple_build_assign (buf.base, ptr);
+ gimple_set_location (g, loc);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ }
+ buf.alias_type = build_pointer_type (type);
+ clear_padding_type (&buf, type, buf.sz);
+ clear_padding_flush (&buf, true);
+ }
+
+ gimple_stmt_iterator gsiprev2 = *gsi;
+ gsi_prev (&gsiprev2);
+ if (gsi_stmt (gsiprev) == gsi_stmt (gsiprev2))
+ gsi_replace (gsi, gimple_build_nop (), true);
+ else
+ {
+ gsi_remove (gsi, true);
+ *gsi = gsiprev2;
+ }
+ return true;
+}
+
/* Fold the non-target builtin at *GSI and return whether any simplification
was made. */
@@ -4105,6 +4957,9 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
case BUILT_IN_REALLOC:
return gimple_fold_builtin_realloc (gsi);
+ case BUILT_IN_CLEAR_PADDING:
+ return gimple_fold_builtin_clear_padding (gsi);
+
default:;
}
@@ -7688,6 +8543,32 @@ gimple_build (gimple_seq *seq, location_t loc,
return res;
}
+/* Build the call FN () with a result of type TYPE (or no result if TYPE is
+ void) with a location LOC. Returns the built expression value (or NULL_TREE
+ if TYPE is void) and appends statements possibly defining it to SEQ. */
+
+tree
+gimple_build (gimple_seq *seq, location_t loc, combined_fn fn, tree type)
+{
+ tree res = NULL_TREE;
+ gcall *stmt;
+ if (internal_fn_p (fn))
+ stmt = gimple_build_call_internal (as_internal_fn (fn), 0);
+ else
+ {
+ tree decl = builtin_decl_implicit (as_builtin_fn (fn));
+ stmt = gimple_build_call (decl, 0);
+ }
+ if (!VOID_TYPE_P (type))
+ {
+ res = create_tmp_reg_or_ssa_name (type);
+ gimple_call_set_lhs (stmt, res);
+ }
+ gimple_set_location (stmt, loc);
+ gimple_seq_add_stmt_without_update (seq, stmt);
+ return res;
+}
+
/* Build the call FN (ARG0) with a result of type TYPE
(or no result if TYPE is void) with location LOC,
simplifying it first if possible. Returns the built
@@ -7855,7 +8736,7 @@ gimple_build_vector (gimple_seq *seq, location_t loc,
gcc_assert (builder->nelts_per_pattern () <= 2);
unsigned int encoded_nelts = builder->encoded_nelts ();
for (unsigned int i = 0; i < encoded_nelts; ++i)
- if (!TREE_CONSTANT ((*builder)[i]))
+ if (!CONSTANT_CLASS_P ((*builder)[i]))
{
tree type = builder->type ();
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
@@ -7877,6 +8758,26 @@ gimple_build_vector (gimple_seq *seq, location_t loc,
return builder->build ();
}
+/* Emit gimple statements into &stmts that take a value given in OLD_SIZE
+ and generate a value guaranteed to be rounded upwards to ALIGN.
+
+ Return the tree node representing this size, it is of TREE_TYPE TYPE. */
+
+tree
+gimple_build_round_up (gimple_seq *seq, location_t loc, tree type,
+ tree old_size, unsigned HOST_WIDE_INT align)
+{
+ unsigned HOST_WIDE_INT tg_mask = align - 1;
+ /* tree new_size = (old_size + tg_mask) & ~tg_mask; */
+ gcc_assert (INTEGRAL_TYPE_P (type));
+ tree tree_mask = build_int_cst (type, tg_mask);
+ tree oversize = gimple_build (seq, loc, PLUS_EXPR, type, old_size,
+ tree_mask);
+
+ tree mask = build_int_cst (type, -align);
+ return gimple_build (seq, loc, BIT_AND_EXPR, type, oversize, mask);
+}
+
/* Return true if the result of assignment STMT is known to be non-negative.
If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index 0ed1d1f..f0f43f6 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -35,6 +35,7 @@ extern tree maybe_fold_and_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree);
extern tree maybe_fold_or_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree);
+extern void clear_type_padding_in_mask (tree, unsigned char *);
extern bool optimize_atomic_compare_exchange_p (gimple *);
extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *);
extern bool arith_overflowed_p (enum tree_code, const_tree, const_tree,
@@ -90,6 +91,12 @@ gimple_build (gimple_seq *seq,
{
return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1, op2);
}
+extern tree gimple_build (gimple_seq *, location_t, combined_fn, tree);
+inline tree
+gimple_build (gimple_seq *seq, combined_fn fn, tree type)
+{
+ return gimple_build (seq, UNKNOWN_LOCATION, fn, type);
+}
extern tree gimple_build (gimple_seq *, location_t, combined_fn, tree, tree);
inline tree
gimple_build (gimple_seq *seq, combined_fn fn, tree type, tree arg0)
@@ -144,6 +151,15 @@ gimple_build_vector (gimple_seq *seq, tree_vector_builder *builder)
return gimple_build_vector (seq, UNKNOWN_LOCATION, builder);
}
+extern tree gimple_build_round_up (gimple_seq *, location_t, tree, tree,
+ unsigned HOST_WIDE_INT);
+inline tree
+gimple_build_round_up (gimple_seq *seq, tree type, tree old_size,
+ unsigned HOST_WIDE_INT align)
+{
+ return gimple_build_round_up (seq, UNKNOWN_LOCATION, type, old_size, align);
+}
+
extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0);
extern bool gimple_stmt_integer_valued_real_p (gimple *, int = 0);
diff --git a/gcc/gimple-if-to-switch.cc b/gcc/gimple-if-to-switch.cc
new file mode 100644
index 0000000..311f6f6
--- /dev/null
+++ b/gcc/gimple-if-to-switch.cc
@@ -0,0 +1,575 @@
+/* If-elseif-else to switch conversion pass
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* Algorithm of the pass runs in the following steps:
+ a) We walk basic blocks in DOMINATOR order so that we first reach
+ a first condition of a future switch.
+ b) We follow false edges of a if-else-chain and we record chain
+ of GIMPLE conditions. These blocks are only used for comparison
+ of a common SSA_NAME and we do not allow any side effect.
+ c) We remove all basic blocks (except first) of such chain and
+ GIMPLE switch replaces the condition in the first basic block.
+ d) We move all GIMPLE statements in the removed blocks into the
+ first one. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "gimple-pretty-print.h"
+#include "fold-const.h"
+#include "gimple-iterator.h"
+#include "tree-cfg.h"
+#include "tree-dfa.h"
+#include "tree-cfgcleanup.h"
+#include "alias.h"
+#include "tree-ssa-loop.h"
+#include "diagnostic.h"
+#include "cfghooks.h"
+#include "tree-into-ssa.h"
+#include "cfganal.h"
+#include "dbgcnt.h"
+#include "target.h"
+#include "alloc-pool.h"
+#include "tree-switch-conversion.h"
+#include "tree-ssa-reassoc.h"
+
+using namespace tree_switch_conversion;
+
+struct condition_info
+{
+ typedef vec<std::pair<gphi *, tree>> mapping_vec;
+
+ condition_info (gcond *cond): m_cond (cond), m_bb (gimple_bb (cond)),
+ m_forwarder_bb (NULL), m_ranges (), m_true_edge (NULL), m_false_edge (NULL),
+ m_true_edge_phi_mapping (), m_false_edge_phi_mapping ()
+ {
+ m_ranges.create (0);
+ }
+
+ /* Recond PHI mapping for an original edge E and save these into
+ vector VEC. */
+ void record_phi_mapping (edge e, mapping_vec *vec);
+
+ gcond *m_cond;
+ basic_block m_bb;
+ basic_block m_forwarder_bb;
+ vec<range_entry> m_ranges;
+ edge m_true_edge;
+ edge m_false_edge;
+ mapping_vec m_true_edge_phi_mapping;
+ mapping_vec m_false_edge_phi_mapping;
+};
+
+/* Recond PHI mapping for an original edge E and save these into vector VEC. */
+
+void
+condition_info::record_phi_mapping (edge e, mapping_vec *vec)
+{
+ for (gphi_iterator gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ if (!virtual_operand_p (gimple_phi_result (phi)))
+ {
+ tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
+ vec->safe_push (std::make_pair (phi, arg));
+ }
+ }
+}
+
+/* Master structure for one if to switch conversion candidate. */
+
+struct if_chain
+{
+ /* Default constructor. */
+ if_chain (): m_entries ()
+ {
+ m_entries.create (2);
+ }
+
+ /* Default destructor. */
+ ~if_chain ()
+ {
+ m_entries.release ();
+ }
+
+ /* Verify that all case ranges do not overlap. */
+ bool check_non_overlapping_cases ();
+
+ /* Return true when the switch can be expanded with a jump table or
+ a bit test (at least partially). */
+ bool is_beneficial ();
+
+ /* If chain entries. */
+ vec<condition_info *> m_entries;
+};
+
+/* Compare two case ranges by minimum value. */
+
+static int
+range_cmp (const void *a, const void *b)
+{
+ const range_entry *re1 = *(const range_entry * const *) a;
+ const range_entry *re2 = *(const range_entry * const *) b;
+
+ return tree_int_cst_compare (re1->low, re2->low);
+}
+
+/* Verify that all case ranges do not overlap. */
+
+bool
+if_chain::check_non_overlapping_cases ()
+{
+ auto_vec<range_entry *> all_ranges;
+ for (unsigned i = 0; i < m_entries.length (); i++)
+ for (unsigned j = 0; j < m_entries[i]->m_ranges.length (); j++)
+ all_ranges.safe_push (&m_entries[i]->m_ranges[j]);
+
+ all_ranges.qsort (range_cmp);
+
+ for (unsigned i = 0; i < all_ranges.length () - 1; i++)
+ {
+ range_entry *left = all_ranges[i];
+ range_entry *right = all_ranges[i + 1];
+ if (tree_int_cst_le (left->low, right->low)
+ && tree_int_cst_le (right->low, left->high))
+ return false;
+ }
+
+ return true;
+}
+
+/* Compare clusters by minimum value. */
+
+static int
+cluster_cmp (const void *a, const void *b)
+{
+ simple_cluster *sc1 = *(simple_cluster * const *) a;
+ simple_cluster *sc2 = *(simple_cluster * const *) b;
+
+ return tree_int_cst_compare (sc1->get_low (), sc2->get_high ());
+}
+
+/* Dump constructed CLUSTERS with prefix MESSAGE. */
+
+static void
+dump_clusters (vec<cluster *> *clusters, const char *message)
+{
+ if (dump_file)
+ {
+ fprintf (dump_file, ";; %s: ", message);
+ for (unsigned i = 0; i < clusters->length (); i++)
+ (*clusters)[i]->dump (dump_file, dump_flags & TDF_DETAILS);
+ fprintf (dump_file, "\n");
+ }
+}
+
+/* Return true when the switch can be expanded with a jump table or
+ a bit test (at least partially). */
+
+bool
+if_chain::is_beneficial ()
+{
+ profile_probability prob = profile_probability::uninitialized ();
+
+ auto_vec<cluster *> clusters;
+ clusters.create (m_entries.length ());
+
+ for (unsigned i = 0; i < m_entries.length (); i++)
+ {
+ condition_info *info = m_entries[i];
+ for (unsigned j = 0; j < info->m_ranges.length (); j++)
+ {
+ range_entry *range = &info->m_ranges[j];
+ basic_block bb = info->m_true_edge->dest;
+ bool has_forwarder = !info->m_true_edge_phi_mapping.is_empty ();
+ clusters.safe_push (new simple_cluster (range->low, range->high,
+ NULL_TREE, bb, prob,
+ has_forwarder));
+ }
+ }
+
+ /* Sort clusters and merge them. */
+ auto_vec<cluster *> filtered_clusters;
+ filtered_clusters.create (16);
+ clusters.qsort (cluster_cmp);
+ simple_cluster *left = static_cast<simple_cluster *> (clusters[0]);
+ filtered_clusters.safe_push (left);
+
+ for (unsigned i = 1; i < clusters.length (); i++)
+ {
+ simple_cluster *right = static_cast<simple_cluster *> (clusters[i]);
+ tree type = TREE_TYPE (left->get_low ());
+ if (!left->m_has_forward_bb
+ && !right->m_has_forward_bb
+ && left->m_case_bb == right->m_case_bb)
+ {
+ if (wi::eq_p (wi::to_wide (right->get_low ()) - wi::to_wide
+ (left->get_high ()), wi::one (TYPE_PRECISION (type))))
+ {
+ left->set_high (right->get_high ());
+ continue;
+ }
+ }
+
+ left = static_cast<simple_cluster *> (clusters[i]);
+ filtered_clusters.safe_push (left);
+ }
+
+ dump_clusters (&filtered_clusters, "Canonical GIMPLE case clusters");
+
+ vec<cluster *> output
+ = jump_table_cluster::find_jump_tables (filtered_clusters);
+ bool r = output.length () < filtered_clusters.length ();
+ if (r)
+ dump_clusters (&output, "JT can be built");
+ output.release ();
+ if (r)
+ return true;
+
+ output = bit_test_cluster::find_bit_tests (filtered_clusters);
+ r = output.length () < filtered_clusters.length ();
+ if (r)
+ dump_clusters (&output, "BT can be built");
+ output.release ();
+ return r;
+}
+
+/* Build case label with MIN and MAX values of a given basic block DEST. */
+
+static tree
+build_case_label (tree index_type, tree min, tree max, basic_block dest)
+{
+ if (min != NULL_TREE && index_type != TREE_TYPE (min))
+ min = fold_convert (index_type, min);
+ if (max != NULL_TREE && index_type != TREE_TYPE (max))
+ max = fold_convert (index_type, max);
+
+ tree label = gimple_block_label (dest);
+ return build_case_label (min, min == max ? NULL_TREE : max, label);
+}
+
+/* Compare two integer constants. */
+
+static int
+label_cmp (const void *a, const void *b)
+{
+ const_tree l1 = *(const const_tree *) a;
+ const_tree l2 = *(const const_tree *) b;
+
+ return tree_int_cst_compare (CASE_LOW (l1), CASE_LOW (l2));
+}
+
+/* Convert a given if CHAIN into a switch GIMPLE statement. */
+
+static void
+convert_if_conditions_to_switch (if_chain *chain)
+{
+ if (!dbg_cnt (if_to_switch))
+ return;
+
+ auto_vec<tree> labels;
+ unsigned entries = chain->m_entries.length ();
+ condition_info *first_cond = chain->m_entries[0];
+ condition_info *last_cond = chain->m_entries[entries - 1];
+
+ edge default_edge = last_cond->m_false_edge;
+ basic_block default_bb = default_edge->dest;
+
+ gimple_stmt_iterator gsi = gsi_for_stmt (first_cond->m_cond);
+ tree index_type = TREE_TYPE (first_cond->m_ranges[0].exp);
+ for (unsigned i = 0; i < entries; i++)
+ {
+ condition_info *info = chain->m_entries[i];
+ basic_block case_bb = info->m_true_edge->dest;
+
+ /* Create a forwarder block if needed. */
+ if (!info->m_true_edge_phi_mapping.is_empty ())
+ {
+ info->m_forwarder_bb = split_edge (info->m_true_edge);
+ case_bb = info->m_forwarder_bb;
+ }
+
+ for (unsigned j = 0; j < info->m_ranges.length (); j++)
+ labels.safe_push (build_case_label (index_type,
+ info->m_ranges[j].low,
+ info->m_ranges[j].high,
+ case_bb));
+ default_bb = info->m_false_edge->dest;
+
+ if (i == 0)
+ {
+ remove_edge (first_cond->m_true_edge);
+ remove_edge (first_cond->m_false_edge);
+ }
+ else
+ delete_basic_block (info->m_bb);
+
+ make_edge (first_cond->m_bb, case_bb, 0);
+ }
+
+ labels.qsort (label_cmp);
+
+ edge e = find_edge (first_cond->m_bb, default_bb);
+ if (e == NULL)
+ e = make_edge (first_cond->m_bb, default_bb, 0);
+ gswitch *s
+ = gimple_build_switch (first_cond->m_ranges[0].exp,
+ build_case_label (index_type, NULL_TREE,
+ NULL_TREE, default_bb),
+ labels);
+
+ gsi_remove (&gsi, true);
+ gsi_insert_before (&gsi, s, GSI_NEW_STMT);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Expanded into a new gimple STMT: ");
+ print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
+ putc ('\n', dump_file);
+ }
+
+ /* Fill up missing PHI node arguments. */
+ for (unsigned i = 0; i < chain->m_entries.length (); ++i)
+ {
+ condition_info *info = chain->m_entries[i];
+ for (unsigned j = 0; j < info->m_true_edge_phi_mapping.length (); ++j)
+ {
+ std::pair<gphi *, tree> item = info->m_true_edge_phi_mapping[j];
+ add_phi_arg (item.first, item.second,
+ single_succ_edge (info->m_forwarder_bb),
+ UNKNOWN_LOCATION);
+ }
+ }
+
+ /* Fill up missing PHI nodes for the default BB. */
+ for (unsigned j = 0; j < last_cond->m_false_edge_phi_mapping.length (); ++j)
+ {
+ std::pair<gphi *, tree> item = last_cond->m_false_edge_phi_mapping[j];
+ add_phi_arg (item.first, item.second, e, UNKNOWN_LOCATION);
+ }
+}
+
+/* Identify an index variable used in BB in a GIMPLE condition.
+ Save information about the condition into CONDITIONS_IN_BBS. */
+
+static void
+find_conditions (basic_block bb,
+ hash_map<basic_block, condition_info> *conditions_in_bbs)
+{
+ gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
+ if (gsi_end_p (gsi))
+ return;
+
+ gcond *cond = dyn_cast<gcond *> (gsi_stmt (gsi));
+ if (cond == NULL)
+ return;
+
+ if (!no_side_effect_bb (bb))
+ return;
+
+ tree lhs = gimple_cond_lhs (cond);
+ tree rhs = gimple_cond_rhs (cond);
+ tree_code code = gimple_cond_code (cond);
+
+ condition_info info (cond);
+
+ gassign *def;
+ if (code == NE_EXPR
+ && TREE_CODE (lhs) == SSA_NAME
+ && (def = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (lhs))) != NULL
+ && integer_zerop (rhs))
+ {
+ enum tree_code rhs_code = gimple_assign_rhs_code (def);
+ if (rhs_code == BIT_IOR_EXPR)
+ {
+ info.m_ranges.safe_grow (2, true);
+ init_range_entry (&info.m_ranges[0], gimple_assign_rhs1 (def), NULL);
+ init_range_entry (&info.m_ranges[1], gimple_assign_rhs2 (def), NULL);
+ }
+ }
+ else
+ {
+ info.m_ranges.safe_grow (1, true);
+ init_range_entry (&info.m_ranges[0], NULL_TREE, cond);
+ }
+
+ /* All identified ranges must have equal expression and IN_P flag. */
+ if (!info.m_ranges.is_empty ())
+ {
+ edge true_edge, false_edge;
+ tree expr = info.m_ranges[0].exp;
+ bool in_p = info.m_ranges[0].in_p;
+
+ extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
+ info.m_true_edge = in_p ? true_edge : false_edge;
+ info.m_false_edge = in_p ? false_edge : true_edge;
+
+ for (unsigned i = 0; i < info.m_ranges.length (); ++i)
+ if (info.m_ranges[i].exp == NULL_TREE
+ || !INTEGRAL_TYPE_P (TREE_TYPE (info.m_ranges[i].exp))
+ || info.m_ranges[i].low == NULL_TREE
+ || info.m_ranges[i].high == NULL_TREE
+ || (TYPE_PRECISION (TREE_TYPE (info.m_ranges[i].low))
+ != TYPE_PRECISION (TREE_TYPE (info.m_ranges[i].high))))
+ return;
+
+ for (unsigned i = 1; i < info.m_ranges.length (); ++i)
+ if (info.m_ranges[i].exp != expr
+ || info.m_ranges[i].in_p != in_p)
+ return;
+
+ info.record_phi_mapping (info.m_true_edge,
+ &info.m_true_edge_phi_mapping);
+ info.record_phi_mapping (info.m_false_edge,
+ &info.m_false_edge_phi_mapping);
+ conditions_in_bbs->put (bb, info);
+ }
+
+}
+
+namespace {
+
+const pass_data pass_data_if_to_switch =
+{
+ GIMPLE_PASS, /* type */
+ "iftoswitch", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_TREE_IF_TO_SWITCH, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_cleanup_cfg | TODO_update_ssa /* todo_flags_finish */
+};
+
+class pass_if_to_switch : public gimple_opt_pass
+{
+public:
+ pass_if_to_switch (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_if_to_switch, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ return (jump_table_cluster::is_enabled ()
+ || bit_test_cluster::is_enabled ());
+ }
+
+ virtual unsigned int execute (function *);
+
+}; // class pass_if_to_switch
+
+unsigned int
+pass_if_to_switch::execute (function *fun)
+{
+ auto_vec<if_chain *> all_candidates;
+ hash_map<basic_block, condition_info> conditions_in_bbs;
+
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, fun)
+ find_conditions (bb, &conditions_in_bbs);
+
+ if (conditions_in_bbs.is_empty ())
+ return 0;
+
+ int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun));
+ unsigned n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, false);
+
+ auto_bitmap seen_bbs;
+ for (int i = n - 1; i >= 0; --i)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]);
+ if (bitmap_bit_p (seen_bbs, bb->index))
+ continue;
+
+ bitmap_set_bit (seen_bbs, bb->index);
+ condition_info *info = conditions_in_bbs.get (bb);
+ if (info)
+ {
+ if_chain *chain = new if_chain ();
+ chain->m_entries.safe_push (info);
+ /* Try to find a chain starting in this BB. */
+ while (true)
+ {
+ if (!single_pred_p (gimple_bb (info->m_cond)))
+ break;
+ edge e = single_pred_edge (gimple_bb (info->m_cond));
+ condition_info *info2 = conditions_in_bbs.get (e->src);
+ if (!info2 || info->m_ranges[0].exp != info2->m_ranges[0].exp)
+ break;
+
+ /* It is important that the blocks are linked through FALSE_EDGE.
+ For an expression of index != VALUE, true and false edges
+ are flipped. */
+ if (info2->m_false_edge != e)
+ break;
+
+ chain->m_entries.safe_push (info2);
+ bitmap_set_bit (seen_bbs, e->src->index);
+ info = info2;
+ }
+
+ chain->m_entries.reverse ();
+ if (chain->m_entries.length () >= 2
+ && chain->check_non_overlapping_cases ()
+ && chain->is_beneficial ())
+ {
+ gcond *cond = chain->m_entries[0]->m_cond;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, cond,
+ "Condition chain with %d BBs "
+ "transformed into a switch statement.\n",
+ chain->m_entries.length ());
+ all_candidates.safe_push (chain);
+ }
+ }
+ }
+
+ for (unsigned i = 0; i < all_candidates.length (); i++)
+ {
+ convert_if_conditions_to_switch (all_candidates[i]);
+ delete all_candidates[i];
+ }
+
+ free (rpo);
+
+ if (!all_candidates.is_empty ())
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ mark_virtual_operands_for_renaming (fun);
+ }
+
+ return 0;
+}
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_if_to_switch (gcc::context *ctxt)
+{
+ return new pass_if_to_switch (ctxt);
+}
diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index b64e31f..1ab75e7 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-dce.h"
#include "memmodel.h"
#include "optabs.h"
+#include "gimple-fold.h"
/* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to
internal function based on vector type of selected expansion.
@@ -134,6 +135,25 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
lhs = gimple_assign_lhs (stmt);
machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
+ /* Lower mask typed, non-vector mode VEC_COND_EXPRs to bitwise operations.
+ Those can end up generated by folding and at least for integer mode masks
+ we cannot expect vcond expanders to exist. We lower a ? b : c
+ to (b & a) | (c & ~a). */
+ if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (lhs))
+ && !VECTOR_MODE_P (mode))
+ {
+ gcc_assert (types_compatible_p (TREE_TYPE (op0), TREE_TYPE (op1)));
+ gimple_seq stmts = NULL;
+ tree type = TREE_TYPE (lhs);
+ location_t loc = gimple_location (stmt);
+ tree tem0 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op1, op0);
+ tree tem1 = gimple_build (&stmts, loc, BIT_NOT_EXPR, type, op0);
+ tree tem2 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op2, tem1);
+ tree tem3 = gimple_build (&stmts, loc, BIT_IOR_EXPR, type, tem0, tem2);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ return gimple_build_assign (lhs, tem3);
+ }
+
gcc_assert (!COMPARISON_CLASS_P (op0));
if (TREE_CODE (op0) == SSA_NAME)
{
@@ -162,11 +182,26 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
op0a = gimple_assign_rhs1 (def_stmt);
op0b = gimple_assign_rhs2 (def_stmt);
+ tree op0_type = TREE_TYPE (op0);
tree op0a_type = TREE_TYPE (op0a);
+
+ /* Try to fold x CMP y ? -1 : 0 to x CMP y. */
+
+ if (integer_minus_onep (op1)
+ && integer_zerop (op2)
+ && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (TREE_TYPE (op0))
+ && expand_vec_cmp_expr_p (op0a_type, op0_type, tcode))
+ {
+ tree conv_op = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), op0);
+ gassign *new_stmt = gimple_build_assign (lhs, conv_op);
+ gsi_replace (gsi, new_stmt, true);
+ return new_stmt;
+ }
+
if (used_vec_cond_exprs >= 2
- && (get_vcond_mask_icode (mode, TYPE_MODE (op0a_type))
+ && (get_vcond_mask_icode (mode, TYPE_MODE (op0_type))
!= CODE_FOR_nothing)
- && expand_vec_cmp_expr_p (op0a_type, TREE_TYPE (lhs), tcode))
+ && expand_vec_cmp_expr_p (op0a_type, op0_type, tcode))
{
/* Keep the SSA name and use vcond_mask. */
tcode = TREE_CODE (op0);
@@ -197,10 +232,8 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
-
- gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode))
- && known_eq (GET_MODE_NUNITS (mode),
- GET_MODE_NUNITS (cmp_op_mode)));
+ gcc_assert (known_eq (GET_MODE_NUNITS (mode),
+ GET_MODE_NUNITS (cmp_op_mode)));
icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
if (icode == CODE_FOR_nothing)
@@ -246,7 +279,6 @@ gimple_expand_vec_exprs (void)
{
gimple *g = gimple_expand_vec_cond_expr (&gsi,
&vec_cond_ssa_name_uses);
-
if (g != NULL)
{
tree lhs = gimple_assign_lhs (gsi_stmt (gsi));
@@ -255,6 +287,8 @@ gimple_expand_vec_exprs (void)
}
gimple_expand_vec_set_expr (&gsi);
+ if (gsi_end_p (gsi))
+ break;
}
}
diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc
index 1656004..a36dbb4 100644
--- a/gcc/gimple-loop-interchange.cc
+++ b/gcc/gimple-loop-interchange.cc
@@ -2085,8 +2085,13 @@ pass_linterchange::execute (function *fun)
}
if (changed_p)
- scev_reset ();
- return changed_p ? (TODO_update_ssa_only_virtuals) : 0;
+ {
+ unsigned todo = TODO_update_ssa_only_virtuals;
+ todo |= loop_invariant_motion_in_fun (cfun, false);
+ scev_reset ();
+ return todo;
+ }
+ return 0;
}
} // anon namespace
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index a01bf90..075d6e5 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -753,6 +753,7 @@ dump_gimple_call_args (pretty_printer *buffer, const gcall *gs,
limit = ARRAY_SIZE (reduction_args);
break;
+ case IFN_HWASAN_MARK:
case IFN_ASAN_MARK:
#define DEF(X) #X
static const char *const asan_mark_args[] = {IFN_ASAN_MARK_FLAGS};
@@ -1700,6 +1701,15 @@ dump_gimple_omp_target (pretty_printer *buffer, const gomp_target *gs,
case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
kind = " oacc_host_data";
break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ kind = " oacc_parallel_kernels_parallelized";
+ break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
+ kind = " oacc_parallel_kernels_gang_single";
+ break;
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
+ kind = " oacc_data_kernels";
+ break;
default:
gcc_unreachable ();
}
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 13b9933..edebad4 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -91,19 +91,15 @@ non_null_ref::process_name (tree name)
{
gimple *s = USE_STMT (use_p);
unsigned index = gimple_bb (s)->index;
- tree value;
- enum tree_code comp_code;
// If bit is already set for this block, dont bother looking again.
if (bitmap_bit_p (b, index))
continue;
- // If we can infer a != 0 range, then set the bit for this BB
- if (infer_value_range (s, name, &comp_code, &value))
- {
- if (comp_code == NE_EXPR && integer_zerop (value))
- bitmap_set_bit (b, index);
- }
+ // If we can infer a nonnull range, then set the bit for this BB
+ if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name)
+ && infer_nonnull_range (s, name))
+ bitmap_set_bit (b, index);
}
m_nn[v] = b;
@@ -169,6 +165,7 @@ ssa_block_ranges::~ssa_block_ranges ()
void
ssa_block_ranges::set_bb_range (const basic_block bb, const irange &r)
{
+ gcc_checking_assert ((unsigned) bb->index < m_tab.length ());
irange *m = m_irange_allocator->allocate (r);
m_tab[bb->index] = m;
}
@@ -178,6 +175,7 @@ ssa_block_ranges::set_bb_range (const basic_block bb, const irange &r)
void
ssa_block_ranges::set_bb_varying (const basic_block bb)
{
+ gcc_checking_assert ((unsigned) bb->index < m_tab.length ());
m_tab[bb->index] = m_type_range;
}
@@ -187,6 +185,7 @@ ssa_block_ranges::set_bb_varying (const basic_block bb)
bool
ssa_block_ranges::get_bb_range (irange &r, const basic_block bb)
{
+ gcc_checking_assert ((unsigned) bb->index < m_tab.length ());
irange *m = m_tab[bb->index];
if (m)
{
@@ -201,6 +200,7 @@ ssa_block_ranges::get_bb_range (irange &r, const basic_block bb)
bool
ssa_block_ranges::bb_range_p (const basic_block bb)
{
+ gcc_checking_assert ((unsigned) bb->index < m_tab.length ());
return m_tab[bb->index] != NULL;
}
@@ -248,8 +248,8 @@ block_range_cache::~block_range_cache ()
m_ssa_ranges.release ();
}
-// Return a reference to the m_block_cache for NAME. If it has not been
-// accessed yet, allocate it.
+// Return a reference to the ssa_block_cache for NAME. If it has not been
+// accessed yet, allocate it first.
ssa_block_ranges &
block_range_cache::get_block_ranges (tree name)
@@ -259,11 +259,24 @@ block_range_cache::get_block_ranges (tree name)
m_ssa_ranges.safe_grow_cleared (num_ssa_names + 1);
if (!m_ssa_ranges[v])
- m_ssa_ranges[v] = new ssa_block_ranges (TREE_TYPE (name), m_irange_allocator);
-
+ m_ssa_ranges[v] = new ssa_block_ranges (TREE_TYPE (name),
+ m_irange_allocator);
return *(m_ssa_ranges[v]);
}
+
+// Return a pointer to the ssa_block_cache for NAME. If it has not been
+// accessed yet, return NULL.
+
+ssa_block_ranges *
+block_range_cache::query_block_ranges (tree name)
+{
+ unsigned v = SSA_NAME_VERSION (name);
+ if (v >= m_ssa_ranges.length () || !m_ssa_ranges[v])
+ return NULL;
+ return m_ssa_ranges[v];
+}
+
// Set the range for NAME on entry to block BB to R.
void
@@ -287,7 +300,10 @@ block_range_cache::set_bb_varying (tree name, const basic_block bb)
bool
block_range_cache::get_bb_range (irange &r, tree name, const basic_block bb)
{
- return get_block_ranges (name).get_bb_range (r, bb);
+ ssa_block_ranges *ptr = query_block_ranges (name);
+ if (ptr)
+ return ptr->get_bb_range (r, bb);
+ return false;
}
// Return true if NAME has a range set in block BB.
@@ -295,7 +311,10 @@ block_range_cache::get_bb_range (irange &r, tree name, const basic_block bb)
bool
block_range_cache::bb_range_p (tree name, const basic_block bb)
{
- return get_block_ranges (name).bb_range_p (bb);
+ ssa_block_ranges *ptr = query_block_ranges (name);
+ if (ptr)
+ return ptr->bb_range_p (bb);
+ return false;
}
// Print all known block caches to file F.
@@ -400,8 +419,9 @@ ssa_global_cache::get_global_range (irange &r, tree name) const
}
// Set the range for NAME to R in the global cache.
+// Return TRUE if there was already a range set, otherwise false.
-void
+bool
ssa_global_cache::set_global_range (tree name, const irange &r)
{
unsigned v = SSA_NAME_VERSION (name);
@@ -413,6 +433,7 @@ ssa_global_cache::set_global_range (tree name, const irange &r)
*m = r;
else
m_tab[v] = m_irange_allocator->allocate (r);
+ return m != NULL;
}
// Set the range for NAME to R in the glonbal cache.
@@ -457,7 +478,141 @@ ssa_global_cache::dump (FILE *f)
// --------------------------------------------------------------------------
-ranger_cache::ranger_cache (range_query &q) : query (q)
+
+// This struct provides a timestamp for a global range calculation.
+// it contains the time counter, as well as a limited number of ssa-names
+// that it is dependent upon. If the timestamp for any of the dependent names
+// Are newer, then this range could need updating.
+
+struct range_timestamp
+{
+ unsigned time;
+ unsigned ssa1;
+ unsigned ssa2;
+};
+
+// This class will manage the timestamps for each ssa_name.
+// When a value is calcualted, its timestamp is set to the current time.
+// The ssanames it is dependent on have already been calculated, so they will
+// have older times. If one fo those values is ever calculated again, it
+// will get a newer timestamp, and the "current_p" check will fail.
+
+class temporal_cache
+{
+public:
+ temporal_cache ();
+ ~temporal_cache ();
+ bool current_p (tree name) const;
+ void set_timestamp (tree name);
+ void set_dependency (tree name, tree dep);
+ void set_always_current (tree name);
+private:
+ unsigned temporal_value (unsigned ssa) const;
+ const range_timestamp *get_timestamp (unsigned ssa) const;
+ range_timestamp *get_timestamp (unsigned ssa);
+
+ unsigned m_current_time;
+ vec <range_timestamp> m_timestamp;
+};
+
+
+inline
+temporal_cache::temporal_cache ()
+{
+ m_current_time = 1;
+ m_timestamp.create (0);
+ m_timestamp.safe_grow_cleared (num_ssa_names);
+}
+
+inline
+temporal_cache::~temporal_cache ()
+{
+ m_timestamp.release ();
+}
+
+// Return a pointer to the timetamp for ssa-name at index SSA, if there is
+// one, otherwise return NULL.
+
+inline const range_timestamp *
+temporal_cache::get_timestamp (unsigned ssa) const
+{
+ if (ssa >= m_timestamp.length ())
+ return NULL;
+ return &(m_timestamp[ssa]);
+}
+
+// Return a reference to the timetamp for ssa-name at index SSA. If the index
+// is past the end of the vector, extend the vector.
+
+inline range_timestamp *
+temporal_cache::get_timestamp (unsigned ssa)
+{
+ if (ssa >= m_timestamp.length ())
+ m_timestamp.safe_grow_cleared (num_ssa_names + 20);
+ return &(m_timestamp[ssa]);
+}
+
+// This routine will fill NAME's next operand slot with DEP if DEP is a valid
+// SSA_NAME and there is a free slot.
+
+inline void
+temporal_cache::set_dependency (tree name, tree dep)
+{
+ if (dep && TREE_CODE (dep) == SSA_NAME)
+ {
+ gcc_checking_assert (get_timestamp (SSA_NAME_VERSION (name)));
+ range_timestamp& ts = *(get_timestamp (SSA_NAME_VERSION (name)));
+ if (!ts.ssa1)
+ ts.ssa1 = SSA_NAME_VERSION (dep);
+ else if (!ts.ssa2 && ts.ssa1 != SSA_NAME_VERSION (name))
+ ts.ssa2 = SSA_NAME_VERSION (dep);
+ }
+}
+
+// Return the timestamp value for SSA, or 0 if there isnt one.
+inline unsigned
+temporal_cache::temporal_value (unsigned ssa) const
+{
+ const range_timestamp *ts = get_timestamp (ssa);
+ return ts ? ts->time : 0;
+}
+
+// Return TRUE if the timestampe for NAME is newer than any of its dependents.
+
+bool
+temporal_cache::current_p (tree name) const
+{
+ const range_timestamp *ts = get_timestamp (SSA_NAME_VERSION (name));
+ if (!ts || ts->time == 0)
+ return true;
+ // Any non-registered dependencies will have a value of 0 and thus be older.
+ // Return true if time is newer than either dependent.
+ return ts->time > temporal_value (ts->ssa1)
+ && ts->time > temporal_value (ts->ssa2);
+}
+
+// This increments the global timer and sets the timestamp for NAME.
+
+inline void
+temporal_cache::set_timestamp (tree name)
+{
+ gcc_checking_assert (get_timestamp (SSA_NAME_VERSION (name)));
+ get_timestamp (SSA_NAME_VERSION (name))->time = ++m_current_time;
+}
+
+// Set the timestamp to 0, marking it as "always up to date".
+
+inline void
+temporal_cache::set_always_current (tree name)
+{
+ gcc_checking_assert (get_timestamp (SSA_NAME_VERSION (name)));
+ get_timestamp (SSA_NAME_VERSION (name))->time = 0;
+}
+
+
+// --------------------------------------------------------------------------
+
+ranger_cache::ranger_cache (gimple_ranger &q) : query (q)
{
m_workback.create (0);
m_workback.safe_grow_cleared (last_basic_block_for_fn (cfun));
@@ -467,15 +622,106 @@ ranger_cache::ranger_cache (range_query &q) : query (q)
m_poor_value_list.create (0);
m_poor_value_list.safe_grow_cleared (20);
m_poor_value_list.truncate (0);
+ m_temporal = new temporal_cache;
}
ranger_cache::~ranger_cache ()
{
+ delete m_temporal;
m_poor_value_list.release ();
m_workback.release ();
m_update_list.release ();
}
+// Dump the global caches to file F. if GORI_DUMP is true, dump the
+// gori map as well.
+
+void
+ranger_cache::dump (FILE *f, bool gori_dump)
+{
+ m_globals.dump (f);
+ if (gori_dump)
+ {
+ fprintf (f, "\nDUMPING GORI MAP\n");
+ gori_compute::dump (f);
+ }
+ fprintf (f, "\n");
+}
+
+// Dump the caches for basic block BB to file F.
+
+void
+ranger_cache::dump (FILE *f, basic_block bb)
+{
+ m_on_entry.dump (f, bb);
+}
+
+// Get the global range for NAME, and return in R. Return false if the
+// global range is not set.
+
+bool
+ranger_cache::get_global_range (irange &r, tree name) const
+{
+ return m_globals.get_global_range (r, name);
+}
+
+// Get the global range for NAME, and return in R if the value is not stale.
+// If the range is set, but is stale, mark it current and return false.
+// If it is not set pick up the legacy global value, mark it current, and
+// return false.
+// Note there is always a value returned in R. The return value indicates
+// whether that value is an up-to-date calculated value or not..
+
+bool
+ranger_cache::get_non_stale_global_range (irange &r, tree name)
+{
+ if (m_globals.get_global_range (r, name))
+ {
+ if (m_temporal->current_p (name))
+ return true;
+ }
+ else
+ {
+ // Global has never been accessed, so pickup the legacy global value.
+ r = gimple_range_global (name);
+ m_globals.set_global_range (name, r);
+ }
+ // After a stale check failure, mark the value as always current until a
+ // new one is set.
+ m_temporal->set_always_current (name);
+ return false;
+}
+// Set the global range of NAME to R.
+
+void
+ranger_cache::set_global_range (tree name, const irange &r)
+{
+ if (m_globals.set_global_range (name, r))
+ {
+ // If there was already a range set, propagate the new value.
+ basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (name));
+ if (!bb)
+ bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+
+ if (DEBUG_RANGE_CACHE)
+ fprintf (dump_file, " GLOBAL :");
+
+ propagate_updated_value (name, bb);
+ }
+ // Mark the value as up-to-date.
+ m_temporal->set_timestamp (name);
+}
+
+// Register a dependency on DEP to name. If the timestamp for DEP is ever
+// greateer than the timestamp for NAME, then it is newer and NAMEs value
+// becomes stale.
+
+void
+ranger_cache::register_dependency (tree name, tree dep)
+{
+ m_temporal->set_dependency (name, dep);
+}
+
// Push a request for a new lookup in block BB of name. Return true if
// the request is actually made (ie, isn't a duplicate).
@@ -533,8 +779,10 @@ ranger_cache::ssa_range_in_bb (irange &r, tree name, basic_block bb)
// Look for the on-entry value of name in BB from the cache.
else if (!m_on_entry.get_bb_range (r, name, bb))
{
- // If it has no entry then mark this as a poor value.
- if (push_poor_value (bb, name))
+ // If it has no entry but should, then mark this as a poor value.
+ // Its not a poor value if it does not have *any* edge ranges,
+ // Then global range is as good as it gets.
+ if (has_edge_range_p (name) && push_poor_value (bb, name))
{
if (DEBUG_RANGE_CACHE)
{
@@ -566,6 +814,11 @@ ranger_cache::block_range (irange &r, basic_block bb, tree name, bool calc)
{
gcc_checking_assert (gimple_range_ssa_p (name));
+ // If there are no range calculations anywhere in the IL, global range
+ // applies everywhere, so don't bother caching it.
+ if (!has_edge_range_p (name))
+ return false;
+
if (calc)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
@@ -601,11 +854,11 @@ ranger_cache::add_to_update (basic_block bb)
m_update_list.quick_push (bb);
}
-// If there is anything in the iterative update_list, continue
+// If there is anything in the propagation update_list, continue
// processing NAME until the list of blocks is empty.
void
-ranger_cache::iterative_cache_update (tree name)
+ranger_cache::propagate_cache (tree name)
{
basic_block bb;
edge_iterator ei;
@@ -696,6 +949,50 @@ ranger_cache::iterative_cache_update (tree name)
}
}
+// Check to see if an update to the value for NAME in BB has any effect
+// on values already in the on-entry cache for successor blocks.
+// If it does, update them. Don't visit any blocks which dont have a cache
+// entry.
+
+void
+ranger_cache::propagate_updated_value (tree name, basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+
+ // The update work list should be empty at this point.
+ gcc_checking_assert (m_update_list.length () == 0);
+ gcc_checking_assert (bb);
+
+ if (DEBUG_RANGE_CACHE)
+ {
+ fprintf (dump_file, " UPDATE cache for ");
+ print_generic_expr (dump_file, name, TDF_SLIM);
+ fprintf (dump_file, " in BB %d : successors : ", bb->index);
+ }
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ // Only update active cache entries.
+ if (m_on_entry.bb_range_p (name, e->dest))
+ {
+ add_to_update (e->dest);
+ if (DEBUG_RANGE_CACHE)
+ fprintf (dump_file, " UPDATE: bb%d", e->dest->index);
+ }
+ }
+ if (m_update_list.length () != 0)
+ {
+ if (DEBUG_RANGE_CACHE)
+ fprintf (dump_file, "\n");
+ propagate_cache (name);
+ }
+ else
+ {
+ if (DEBUG_RANGE_CACHE)
+ fprintf (dump_file, " : No updates!\n");
+ }
+}
+
// Make sure that the range-on-entry cache for NAME is set for block BB.
// Work back through the CFG to DEF_BB ensuring the range is calculated
// on the block/edges leading back to that point.
@@ -782,7 +1079,7 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
{
if (DEBUG_RANGE_CACHE)
fprintf (dump_file, "has cache, ");
- if (!r.undefined_p () || has_edge_range_p (e, name))
+ if (!r.undefined_p () || has_edge_range_p (name, e))
{
add_to_update (node);
if (DEBUG_RANGE_CACHE)
@@ -805,13 +1102,13 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
fprintf (dump_file, "\n");
// Now fill in the marked blocks with values.
- iterative_cache_update (name);
+ propagate_cache (name);
if (DEBUG_RANGE_CACHE)
- fprintf (dump_file, " iterative update done.\n");
+ fprintf (dump_file, " Propagation update done.\n");
// Now that the cache has been updated, check to see if there were any
// SSA_NAMES used in filling the cache which were "poor values".
- // We can evaluate them, and inject any new values into the iteration
+ // Evaluate them, and inject any new values into the propagation
// list, and see if it improves any on-entry values.
if (poor_list_start != m_poor_value_list.length ())
{
@@ -827,51 +1124,25 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
basic_block calc_bb = rec.bb;
int_range_max tmp;
- // The update work list should be empty at this point.
- gcc_checking_assert (m_update_list.length () == 0);
-
if (DEBUG_RANGE_CACHE)
{
fprintf (dump_file, "(%d:%d)Calculating ",
m_poor_value_list.length () + 1, poor_list_start);
print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, " used poor value for ");
+ fprintf (dump_file, " used POOR VALUE for ");
print_generic_expr (dump_file, rec.calc, TDF_SLIM);
fprintf (dump_file, " in bb%d, trying to improve:\n",
calc_bb->index);
}
- // It must have at least one edge, pick edge 0. we just want to
- // calculate a range at the exit from the block so the caches feeding
- // this block will be filled up.
- gcc_checking_assert (EDGE_SUCC (calc_bb, 0));
- query.range_on_edge (tmp, EDGE_SUCC (calc_bb, 0), rec.calc);
+ // Calculate a range at the exit from the block so the caches feeding
+ // this block will be filled, and we'll get a "better" value.
+ query.range_on_exit (tmp, calc_bb, rec.calc);
- if (DEBUG_RANGE_CACHE)
- fprintf (dump_file, " Checking successors of bb%d :",
- calc_bb->index);
-
- // Try recalculating any successor blocks with the new value.
- // Note that even if this value is refined from the initial value,
- // it may not affect the calculation, but the iterative update
- // will resolve that efficently.
- FOR_EACH_EDGE (e, ei, calc_bb->succs)
- {
- if (DEBUG_RANGE_CACHE)
- fprintf (dump_file, "bb%d: ", e->dest->index);
- // Only update active cache entries.
- if (m_on_entry.bb_range_p (name, e->dest))
- {
- if (DEBUG_RANGE_CACHE)
- fprintf (dump_file, "update ");
- add_to_update (e->dest);
- }
- }
- if (DEBUG_RANGE_CACHE)
- fprintf (dump_file, "\n");
- // Now see if there is a new value.
- iterative_cache_update (name);
+ // Then ask for NAME to be re-evaluated on outgoing edges and
+ // use any new values.
+ propagate_updated_value (name, calc_bb);
}
}
-
}
+
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index 29ab01e..c5749fe 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -60,6 +60,7 @@ public:
private:
vec<class ssa_block_ranges *> m_ssa_ranges;
ssa_block_ranges &get_block_ranges (tree name);
+ ssa_block_ranges *query_block_ranges (tree name);
irange_allocator *m_irange_allocator;
};
@@ -73,7 +74,7 @@ public:
ssa_global_cache ();
~ssa_global_cache ();
bool get_global_range (irange &r, tree name) const;
- void set_global_range (tree name, const irange &r);
+ bool set_global_range (tree name, const irange &r);
void clear_global_range (tree name);
void clear ();
void dump (FILE *f = stderr);
@@ -89,19 +90,30 @@ private:
class ranger_cache : public gori_compute_cache
{
public:
- ranger_cache (class range_query &q);
+ ranger_cache (class gimple_ranger &q);
~ranger_cache ();
virtual void ssa_range_in_bb (irange &r, tree name, basic_block bb);
bool block_range (irange &r, basic_block bb, tree name, bool calc = true);
- ssa_global_cache m_globals;
- block_range_cache m_on_entry;
+ bool get_global_range (irange &r, tree name) const;
+ bool get_non_stale_global_range (irange &r, tree name);
+ void set_global_range (tree name, const irange &r);
+ void register_dependency (tree name, tree dep);
+
non_null_ref m_non_null;
+
+ void dump (FILE *f, bool dump_gori = true);
+ void dump (FILE *f, basic_block bb);
private:
+ ssa_global_cache m_globals;
+ block_range_cache m_on_entry;
+ class temporal_cache *m_temporal;
void add_to_update (basic_block bb);
void fill_block_cache (tree name, basic_block bb, basic_block def_bb);
- void iterative_cache_update (tree name);
+ void propagate_cache (tree name);
+
+ void propagate_updated_value (tree name, basic_block bb);
vec<basic_block> m_workback;
vec<basic_block> m_update_list;
@@ -114,7 +126,7 @@ private:
};
bool push_poor_value (basic_block bb, tree name);
vec<update_record> m_poor_value_list;
- class range_query &query;
+ class gimple_ranger &query;
};
#endif // GCC_SSA_RANGE_CACHE_H
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 5d50b11..ac13718 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -229,17 +229,18 @@ public:
gori_map ();
~gori_map ();
- bool is_export_p (tree name, basic_block bb);
+ bool is_export_p (tree name, basic_block bb = NULL);
bool def_chain_in_export_p (tree name, basic_block bb);
+ bitmap exports (basic_block bb);
void dump (FILE *f);
void dump (FILE *f, basic_block bb);
private:
bitmap_obstack m_bitmaps;
vec<bitmap> m_outgoing; // BB: Outgoing ranges calculatable on edges
+ bitmap all_outgoing; // All outgoing ranges combined.
void maybe_add_gori (tree name, basic_block bb);
void calculate_gori (basic_block bb);
- bitmap exports (basic_block bb);
};
@@ -250,6 +251,7 @@ gori_map::gori_map ()
m_outgoing.create (0);
m_outgoing.safe_grow_cleared (last_basic_block_for_fn (cfun));
bitmap_obstack_initialize (&m_bitmaps);
+ all_outgoing = BITMAP_ALLOC (&m_bitmaps);
}
// Free any memory the GORI map allocated.
@@ -276,6 +278,9 @@ gori_map::exports (basic_block bb)
bool
gori_map::is_export_p (tree name, basic_block bb)
{
+ // If no BB is specified, test if it is exported anywhere in the IL.
+ if (!bb)
+ return bitmap_bit_p (all_outgoing, SSA_NAME_VERSION (name));
return bitmap_bit_p (exports (bb), SSA_NAME_VERSION (name));
}
@@ -342,6 +347,8 @@ gori_map::calculate_gori (basic_block bb)
name = gimple_range_ssa_p (gimple_switch_index (gs));
maybe_add_gori (name, gimple_bb (stmt));
}
+ // Add this bitmap to the aggregate list of all outgoing names.
+ bitmap_ior_into (all_outgoing, m_outgoing[bb->index]);
}
// Dump the table information for BB to file F.
@@ -438,6 +445,16 @@ gori_compute::gori_compute ()
m_bool_zero = int_range<2> (boolean_false_node, boolean_false_node);
m_bool_one = int_range<2> (boolean_true_node, boolean_true_node);
m_gori_map = new gori_map;
+ unsigned x, lim = last_basic_block_for_fn (cfun);
+ // Calculate outgoing range info upfront. This will fully populate the
+ // all_outgoing bitmap which will help eliminate processing of names
+ // which never have their ranges adjusted.
+ for (x = 0; x < lim ; x++)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, x);
+ if (bb)
+ m_gori_map->exports (bb);
+ }
}
// Destruct a gori_compute_object.
@@ -730,8 +747,8 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
if (lhs.zero_p ())
{
// An OR operation will only take the FALSE path if both
- // operands are false, so [20, 255] intersect [0, 5] is the
- // union: [0,5][20,255].
+ // operands are false simlulateously, which means they should
+ // be intersected. !(x || y) == !x && !y
r = op1.false_range;
r.intersect (op2.false_range);
}
@@ -804,9 +821,12 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range,
tree name,
tree op, bool op_in_chain)
{
- if (!op_in_chain)
+ gimple *src_stmt = gimple_range_ssa_p (op) ? SSA_NAME_DEF_STMT (op) : NULL;
+ basic_block bb = gimple_bb (stmt);
+ if (!op_in_chain || (src_stmt != NULL && bb != gimple_bb (src_stmt)))
{
- // If op is not in chain, use its known value.
+ // If op is not in the def chain, or defined in this block,
+ // use its known value on entry to the block.
expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
range.false_range = range.true_range;
return;
@@ -814,14 +834,12 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range,
if (optimize_logical_operands (range, stmt, lhs, name, op))
return;
- // Calulate ranges for true and false on both sides, since the false
+ // Calculate ranges for true and false on both sides, since the false
// path is not always a simple inversion of the true side.
- if (!compute_operand_range (range.true_range, SSA_NAME_DEF_STMT (op),
- m_bool_one, name))
- expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
- if (!compute_operand_range (range.false_range, SSA_NAME_DEF_STMT (op),
- m_bool_zero, name))
- expr_range_in_bb (range.false_range, name, gimple_bb (stmt));
+ if (!compute_operand_range (range.true_range, src_stmt, m_bool_one, name))
+ expr_range_in_bb (range.true_range, name, bb);
+ if (!compute_operand_range (range.false_range, src_stmt, m_bool_zero, name))
+ expr_range_in_bb (range.false_range, name, bb);
}
// Given a logical STMT, calculate true and false for each potential
@@ -968,8 +986,12 @@ gori_compute::compute_operand1_and_operand2_range
// Return TRUE if a range can be calcalated for NAME on edge E.
bool
-gori_compute::has_edge_range_p (edge e, tree name)
+gori_compute::has_edge_range_p (tree name, edge e)
{
+ // If no edge is specified, check if NAME is an export on any edge.
+ if (!e)
+ return m_gori_map->is_export_p (name);
+
return (m_gori_map->is_export_p (name, e->src)
|| m_gori_map->def_chain_in_export_p (name, e->src));
}
@@ -1313,13 +1335,15 @@ gori_compute_cache::cache_stmt (gimple *stmt)
else if (tree cached_name = m_cache->same_cached_name (op1, op2))
{
tf_range op1_range, op2_range;
- gcc_assert (m_cache->get_range (op1_range, op1, cached_name));
- gcc_assert (m_cache->get_range (op2_range, op2, cached_name));
- gcc_assert (logical_combine (r_true_side, code, m_bool_one,
- op1_range, op2_range));
- gcc_assert (logical_combine (r_false_side, code, m_bool_zero,
- op1_range, op2_range));
- m_cache->set_range (lhs, cached_name,
- tf_range (r_true_side, r_false_side));
+ bool ok = m_cache->get_range (op1_range, op1, cached_name);
+ ok = ok && m_cache->get_range (op2_range, op2, cached_name);
+ ok = ok && logical_combine (r_true_side, code, m_bool_one,
+ op1_range, op2_range);
+ ok = ok && logical_combine (r_false_side, code, m_bool_zero,
+ op1_range, op2_range);
+ gcc_checking_assert (ok);
+ if (ok)
+ m_cache->set_range (lhs, cached_name,
+ tf_range (r_true_side, r_false_side));
}
}
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 8ef452b..6cbf532 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -29,10 +29,13 @@ along with GCC; see the file COPYING3. If not see
//
// There are 2 primary entry points:
//
-// has_edge_range_p (edge e, tree name)
+// has_edge_range_p (tree name, edge e)
// returns true if the outgoing edge *may* be able to produce range
// information for ssa_name NAME on edge E.
// FALSE is returned if this edge does not affect the range of NAME.
+// if no edge is specified, return TRUE if name may have a value calculated
+// on *ANY* edge that has been seen. FALSE indicates that the global value
+// is applicable everywhere that has been processed.
//
// outgoing_edge_range_p (irange &range, edge e, tree name)
// Actually does the calculation of RANGE for name on E
@@ -68,7 +71,7 @@ public:
gori_compute ();
~gori_compute ();
bool outgoing_edge_range_p (irange &r, edge e, tree name);
- bool has_edge_range_p (edge e, tree name);
+ bool has_edge_range_p (tree name, edge e = NULL);
void dump (FILE *f);
protected:
virtual void ssa_range_in_bb (irange &r, tree name, basic_block bb);
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 267ebad..4f5d502 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -144,7 +144,7 @@ gimple_range_adjustment (irange &res, const gimple *stmt)
}
// Return a range in R for the tree EXPR. Return true if a range is
-// representable.
+// representable, and UNDEFINED/false if not.
bool
get_tree_range (irange &r, tree expr)
@@ -157,11 +157,16 @@ get_tree_range (irange &r, tree expr)
// Return false if the type isn't suported.
if (!irange::supports_type_p (type))
- return false;
+ {
+ r.set_undefined ();
+ return false;
+ }
switch (TREE_CODE (expr))
{
case INTEGER_CST:
+ if (TREE_OVERFLOW_P (expr))
+ expr = drop_tree_overflow (expr);
r.set (expr, expr);
return true;
@@ -373,7 +378,8 @@ gimple_ranger::calc_stmt (irange &r, gimple *s, tree name)
res = range_of_call (r, as_a<gcall *> (s));
else if (is_a<gassign *> (s) && gimple_assign_rhs_code (s) == COND_EXPR)
res = range_of_cond_expr (r, as_a<gassign *> (s));
- else
+
+ if (!res)
{
// If no name is specified, try the expression kind.
if (!name)
@@ -384,25 +390,24 @@ gimple_ranger::calc_stmt (irange &r, gimple *s, tree name)
r.set_varying (t);
return true;
}
+ if (!gimple_range_ssa_p (name))
+ return false;
// We don't understand the stmt, so return the global range.
r = gimple_range_global (name);
return true;
}
- if (res)
+
+ if (r.undefined_p ())
+ return true;
+
+ // We sometimes get compatible types copied from operands, make sure
+ // the correct type is being returned.
+ if (name && TREE_TYPE (name) != r.type ())
{
- if (r.undefined_p ())
- return true;
- // We sometimes get compatible types copied from operands, make sure
- // the correct type is being returned.
- if (name && TREE_TYPE (name) != r.type ())
- {
- gcc_checking_assert (range_compatible_p (r.type (),
- TREE_TYPE (name)));
- range_cast (r, TREE_TYPE (name));
- }
- return true;
+ gcc_checking_assert (range_compatible_p (r.type (), TREE_TYPE (name)));
+ range_cast (r, TREE_TYPE (name));
}
- return false;
+ return true;
}
// Calculate a range for range_op statement S and return it in R. If any
@@ -412,14 +417,23 @@ bool
gimple_ranger::range_of_range_op (irange &r, gimple *s)
{
int_range_max range1, range2;
+ tree lhs = gimple_get_lhs (s);
tree type = gimple_expr_type (s);
gcc_checking_assert (irange::supports_type_p (type));
tree op1 = gimple_range_operand1 (s);
tree op2 = gimple_range_operand2 (s);
- if (range_of_non_trivial_assignment (r, s))
- return true;
+ if (lhs)
+ {
+ // Register potential dependencies for stale value tracking.
+ m_cache.register_dependency (lhs, op1);
+ m_cache.register_dependency (lhs, op2);
+ }
+
+ if (gimple_code (s) == GIMPLE_ASSIGN
+ && gimple_assign_rhs_code (s) == ADDR_EXPR)
+ return range_of_address (r, s);
if (range_of_expr (range1, op1, s))
{
@@ -433,48 +447,84 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s)
return true;
}
-// Calculate the range of a non-trivial assignment. That is, is one
-// inolving arithmetic on an SSA name (for example, an ADDR_EXPR).
+// Calculate the range of an assignment containing an ADDR_EXPR.
// Return the range in R.
-//
-// If a range cannot be calculated, return false.
+// If a range cannot be calculated, set it to VARYING and return true.
bool
-gimple_ranger::range_of_non_trivial_assignment (irange &r, gimple *stmt)
+gimple_ranger::range_of_address (irange &r, gimple *stmt)
{
- if (gimple_code (stmt) != GIMPLE_ASSIGN)
- return false;
+ gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
+ gcc_checking_assert (gimple_assign_rhs_code (stmt) == ADDR_EXPR);
- tree base = gimple_range_base_of_assignment (stmt);
- if (base)
+ bool strict_overflow_p;
+ tree expr = gimple_assign_rhs1 (stmt);
+ poly_int64 bitsize, bitpos;
+ tree offset;
+ machine_mode mode;
+ int unsignedp, reversep, volatilep;
+ tree base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
+ &bitpos, &offset, &mode, &unsignedp,
+ &reversep, &volatilep);
+
+
+ if (base != NULL_TREE
+ && TREE_CODE (base) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
{
- if (TREE_CODE (base) == MEM_REF)
+ tree ssa = TREE_OPERAND (base, 0);
+ gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa)));
+ range_of_expr (r, ssa, stmt);
+ range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt)));
+
+ poly_offset_int off = 0;
+ bool off_cst = false;
+ if (offset == NULL_TREE || TREE_CODE (offset) == INTEGER_CST)
{
- if (TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
- {
- int_range_max range1;
- tree ssa = TREE_OPERAND (base, 0);
- if (range_of_expr (range1, ssa, stmt))
- {
- tree type = TREE_TYPE (ssa);
- range_operator *op = range_op_handler (POINTER_PLUS_EXPR,
- type);
- int_range<2> offset (TREE_OPERAND (base, 1),
- TREE_OPERAND (base, 1));
- op->fold_range (r, type, range1, offset);
- return true;
- }
- }
- return false;
+ off = mem_ref_offset (base);
+ if (offset)
+ off += poly_offset_int::from (wi::to_poly_wide (offset),
+ SIGNED);
+ off <<= LOG2_BITS_PER_UNIT;
+ off += bitpos;
+ off_cst = true;
}
- if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+ /* If &X->a is equal to X, the range of X is the result. */
+ if (off_cst && known_eq (off, 0))
+ return true;
+ else if (flag_delete_null_pointer_checks
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)))
+ {
+ /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
+ allow going from non-NULL pointer to NULL. */
+ if(!range_includes_zero_p (&r))
+ return true;
+ }
+ /* If MEM_REF has a "positive" offset, consider it non-NULL
+ always, for -fdelete-null-pointer-checks also "negative"
+ ones. Punt for unknown offsets (e.g. variable ones). */
+ if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))
+ && off_cst
+ && known_ne (off, 0)
+ && (flag_delete_null_pointer_checks || known_gt (off, 0)))
{
- // Handle "= &a" and return non-zero.
r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
return true;
}
+ r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+ return true;
}
- return false;
+
+ // Handle "= &a".
+ if (tree_single_nonzero_warnv_p (expr, &strict_overflow_p))
+ {
+ r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+ return true;
+ }
+
+ // Otherwise return varying.
+ r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+ return true;
}
// Calculate a range for phi statement S and return it in R.
@@ -498,6 +548,9 @@ gimple_ranger::range_of_phi (irange &r, gphi *phi)
tree arg = gimple_phi_arg_def (phi, x);
edge e = gimple_phi_arg_edge (phi, x);
+ // Register potential dependencies for stale value tracking.
+ m_cache.register_dependency (phi_def, arg);
+
range_on_edge (arg_range, e, arg);
r.union_ (arg_range);
// Once the value reaches varying, stop looking.
@@ -582,8 +635,8 @@ range_of_builtin_ubsan_call (range_query &query, irange &r, gcall *call,
int_range_max ir0, ir1;
tree arg0 = gimple_call_arg (call, 0);
tree arg1 = gimple_call_arg (call, 1);
- gcc_assert (query.range_of_expr (ir0, arg0, call));
- gcc_assert (query.range_of_expr (ir1, arg1, call));
+ query.range_of_expr (ir0, arg0, call);
+ query.range_of_expr (ir1, arg1, call);
bool saved_flag_wrapv = flag_wrapv;
// Pretend the arithmetic is wrapping. If there is any overflow,
@@ -611,7 +664,7 @@ range_of_builtin_call (range_query &query, irange &r, gcall *call)
tree type = gimple_call_return_type (call);
tree arg;
- int mini, maxi, zerov, prec;
+ int mini, maxi, zerov = 0, prec;
scalar_int_mode mode;
switch (func)
@@ -638,7 +691,7 @@ range_of_builtin_call (range_query &query, irange &r, gcall *call)
prec = TYPE_PRECISION (TREE_TYPE (arg));
mini = 0;
maxi = prec;
- gcc_assert (query.range_of_expr (r, arg, call));
+ query.range_of_expr (r, arg, call);
// If arg is non-zero, then ffs or popcount are non-zero.
if (!range_includes_zero_p (&r))
mini = 1;
@@ -682,7 +735,7 @@ range_of_builtin_call (range_query &query, irange &r, gcall *call)
}
}
- gcc_assert (query.range_of_expr (r, arg, call));
+ query.range_of_expr (r, arg, call);
// From clz of minimum we can compute result maximum.
if (r.constant_p ())
{
@@ -747,7 +800,7 @@ range_of_builtin_call (range_query &query, irange &r, gcall *call)
mini = -2;
}
}
- gcc_assert (query.range_of_expr (r, arg, call));
+ query.range_of_expr (r, arg, call);
if (!r.undefined_p ())
{
if (r.lower_bound () != 0)
@@ -864,9 +917,9 @@ gimple_ranger::range_of_cond_expr (irange &r, gassign *s)
if (!irange::supports_type_p (TREE_TYPE (op1)))
return false;
- gcc_assert (range_of_expr (cond_range, cond, s));
- gcc_assert (range_of_expr (range1, op1, s));
- gcc_assert (range_of_expr (range2, op2, s));
+ range_of_expr (cond_range, cond, s);
+ range_of_expr (range1, op1, s);
+ range_of_expr (range2, op2, s);
// If the condition is known, choose the appropriate expression.
if (cond_range.singleton_p ())
@@ -894,7 +947,7 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
// If there is no statement, just get the global value.
if (!stmt)
{
- if (!m_cache.m_globals.get_global_range (r, expr))
+ if (!m_cache.get_global_range (r, expr))
r = gimple_range_global (expr);
return true;
}
@@ -904,7 +957,7 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
// If name is defined in this block, try to get an range from S.
if (def_stmt && gimple_bb (def_stmt) == bb)
- gcc_assert (range_of_stmt (r, def_stmt, expr));
+ range_of_stmt (r, def_stmt, expr);
else
// Otherwise OP comes from outside this block, use range on entry.
range_on_entry (r, bb, expr);
@@ -933,7 +986,7 @@ gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
gcc_checking_assert (gimple_range_ssa_p (name));
// Start with any known range
- gcc_assert (range_of_stmt (r, SSA_NAME_DEF_STMT (name), name));
+ range_of_stmt (r, SSA_NAME_DEF_STMT (name), name);
// Now see if there is any on_entry value which may refine it.
if (m_cache.block_range (entry_range, bb, name))
@@ -948,6 +1001,7 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
{
// on-exit from the exit block?
gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
+ gcc_checking_assert (gimple_range_ssa_p (name));
gimple *s = last_stmt (bb);
// If there is no statement in the block and this isn't the entry
@@ -956,7 +1010,7 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
if (!s && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
range_on_entry (r, bb, name);
else
- gcc_assert (range_of_expr (r, name, s));
+ range_of_expr (r, name, s);
gcc_checking_assert (r.undefined_p ()
|| range_compatible_p (r.type (), TREE_TYPE (name)));
}
@@ -971,10 +1025,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
// PHI arguments can be constants, catch these here.
if (!gimple_range_ssa_p (name))
- {
- gcc_assert (range_of_expr (r, name));
- return true;
- }
+ return range_of_expr (r, name);
range_on_exit (r, e->src, name);
gcc_checking_assert (r.undefined_p ()
@@ -991,33 +1042,36 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
// provided it represents the SSA_NAME on the LHS of the statement.
// It is only required if there is more than one lhs/output. Check
// the global cache for NAME first to see if the evaluation can be
-// avoided. If a range cannot be calculated, return false.
+// avoided. If a range cannot be calculated, return false and UNDEFINED.
bool
gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
{
- // If no name, simply call the base routine.
+ r.set_undefined ();
+
if (!name)
name = gimple_get_lhs (s);
+ // If no name, simply call the base routine.
if (!name)
return calc_stmt (r, s, NULL_TREE);
- gcc_checking_assert (TREE_CODE (name) == SSA_NAME &&
- irange::supports_type_p (TREE_TYPE (name)));
+ if (!gimple_range_ssa_p (name))
+ return false;
- // If this STMT has already been processed, return that value.
- if (m_cache.m_globals.get_global_range (r, name))
+ // Check if the stmt has already been processed, and is not stale.
+ if (m_cache.get_non_stale_global_range (r, name))
return true;
- // Avoid infinite recursion by initializing global cache
- int_range_max tmp = gimple_range_global (name);
- m_cache.m_globals.set_global_range (name, tmp);
- gcc_assert (calc_stmt (r, s, name));
+ // Otherwise calculate a new value.
+ int_range_max tmp;
+ calc_stmt (tmp, s, name);
- if (is_a<gphi *> (s))
- r.intersect (tmp);
- m_cache.m_globals.set_global_range (name, r);
+ // Combine the new value with the old value. This is required because
+ // the way value propagation works, when the IL changes on the fly we
+ // can sometimes get different results. See PR 97741.
+ r.intersect (tmp);
+ m_cache.set_global_range (name, r);
return true;
}
@@ -1040,7 +1094,7 @@ gimple_ranger::export_global_ranges ()
tree name = ssa_name (x);
if (name && !SSA_NAME_IN_FREE_LIST (name)
&& gimple_range_ssa_p (name)
- && m_cache.m_globals.get_global_range (r, name)
+ && m_cache.get_global_range (r, name)
&& !r.varying_p())
{
// Make sure the new range is a subset of the old range.
@@ -1084,7 +1138,7 @@ gimple_ranger::dump (FILE *f)
edge e;
int_range_max range;
fprintf (f, "\n=========== BB %d ============\n", bb->index);
- m_cache.m_on_entry.dump (f, bb);
+ m_cache.dump (f, bb);
dump_bb (f, bb, 4, TDF_NONE);
@@ -1094,7 +1148,7 @@ gimple_ranger::dump (FILE *f)
tree name = ssa_name (x);
if (gimple_range_ssa_p (name) && SSA_NAME_DEF_STMT (name) &&
gimple_bb (SSA_NAME_DEF_STMT (name)) == bb &&
- m_cache.m_globals.get_global_range (range, name))
+ m_cache.get_global_range (range, name))
{
if (!range.varying_p ())
{
@@ -1146,15 +1200,7 @@ gimple_ranger::dump (FILE *f)
}
}
- m_cache.m_globals.dump (dump_file);
- fprintf (f, "\n");
-
- if (dump_flags & TDF_DETAILS)
- {
- fprintf (f, "\nDUMPING GORI MAP\n");
- m_cache.dump (f);
- fprintf (f, "\n");
- }
+ m_cache.dump (dump_file, (dump_flags & TDF_DETAILS) != 0);
}
// If SCEV has any information about phi node NAME, return it as a range in R.
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index 0aa6d46..92bb530 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -62,7 +62,7 @@ protected:
ranger_cache m_cache;
private:
bool range_of_phi (irange &r, gphi *phi);
- bool range_of_non_trivial_assignment (irange &r, gimple *s);
+ bool range_of_address (irange &r, gimple *s);
bool range_of_builtin_call (irange &r, gcall *call);
bool range_with_loop_info (irange &r, tree name);
void range_of_ssa_name_with_loop_info (irange &, tree, class loop *,
@@ -97,8 +97,12 @@ extern bool gimple_range_calc_op2 (irange &r, const gimple *s,
static inline range_operator *
gimple_range_handler (const gimple *s)
{
- if ((gimple_code (s) == GIMPLE_ASSIGN) || (gimple_code (s) == GIMPLE_COND))
- return range_op_handler (gimple_expr_code (s), gimple_expr_type (s));
+ if (const gassign *ass = dyn_cast<const gassign *> (s))
+ return range_op_handler (gimple_assign_rhs_code (ass),
+ TREE_TYPE (gimple_assign_lhs (ass)));
+ if (const gcond *cond = dyn_cast<const gcond *> (s))
+ return range_op_handler (gimple_cond_code (cond),
+ TREE_TYPE (gimple_cond_lhs (cond)));
return NULL;
}
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 485774d..b998e0b 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -218,7 +218,11 @@ evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
push_value_range (vrs[i].first, vrs[i].second);
if (is_fallthru
&& m_update_global_ranges
- && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt))
+ && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)
+ /* The condition must post-dominate the definition point. */
+ && (SSA_NAME_IS_DEFAULT_DEF (vrs[i].first)
+ || (gimple_bb (SSA_NAME_DEF_STMT (vrs[i].first))
+ == pred_e->src)))
{
set_ssa_range_info (vrs[i].first, vrs[i].second);
maybe_set_nonzero_bits (pred_e, vrs[i].first);
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index fff034f..ca0572f 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -4032,26 +4032,22 @@ compute_format_length (call_info &info, format_result *res, range_query *query)
available, or the maximum possible size otherwise. */
static unsigned HOST_WIDE_INT
-get_destination_size (tree dest)
+get_destination_size (tree dest, pointer_query &ptr_qry)
{
/* When there is no destination return the maximum. */
if (!dest)
return HOST_WIDE_INT_MAX;
- /* Initialize object size info before trying to compute it. */
- init_object_sizes ();
+ /* Use compute_objsize to determine the size of the destination object. */
+ access_ref aref;
+ if (!ptr_qry.get_ref (dest, &aref))
+ return HOST_WIDE_INT_MAX;
- /* Use __builtin_object_size to determine the size of the destination
- object. When optimizing, determine the smallest object (such as
- a member array as opposed to the whole enclosing object), otherwise
- use type-zero object size to determine the size of the enclosing
- object (the function fails without optimization in this type). */
- int ost = optimize > 0;
- unsigned HOST_WIDE_INT size;
- if (compute_builtin_object_size (dest, ost, &size))
- return size;
+ offset_int remsize = aref.size_remaining ();
+ if (!wi::fits_uhwi_p (remsize))
+ return HOST_WIDE_INT_MAX;
- return HOST_WIDE_INT_MAX;
+ return remsize.to_uhwi ();
}
/* Return true if the call described by INFO with result RES safe to
@@ -4296,7 +4292,7 @@ get_user_idx_format (tree fndecl, unsigned *idx_args)
gsi_next should not be performed in the caller. */
bool
-handle_printf_call (gimple_stmt_iterator *gsi, range_query *query)
+handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
{
init_target_to_host_charmap ();
@@ -4519,7 +4515,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, range_query *query)
/* For non-bounded functions like sprintf, determine the size
of the destination from the object or pointer passed to it
as the first argument. */
- dstsize = get_destination_size (dstptr);
+ dstsize = get_destination_size (dstptr, ptr_qry);
}
else if (tree size = gimple_call_arg (info.callstmt, idx_dstsize))
{
@@ -4566,7 +4562,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, range_query *query)
and use the greater of the two at level 1 and the smaller
of them at level 2. */
value_range vr;
- query->range_of_expr (vr, size, info.callstmt);
+ ptr_qry.rvals->range_of_expr (vr, size, info.callstmt);
if (!vr.undefined_p ())
{
@@ -4683,7 +4679,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, range_query *query)
never set to true again). */
res.posunder4k = posunder4k && dstptr;
- bool success = compute_format_length (info, &res, query);
+ bool success = compute_format_length (info, &res, ptr_qry.rvals);
if (res.warned)
gimple_set_no_warning (info.callstmt, true);
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 28fc2e2..2ab51e2 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -851,17 +851,82 @@ find_bswap_or_nop_finalize (struct symbolic_number *n, uint64_t *cmpxchg,
gimple *
find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
{
+ tree type_size = TYPE_SIZE_UNIT (gimple_expr_type (stmt));
+ if (!tree_fits_uhwi_p (type_size))
+ return NULL;
+
/* The last parameter determines the depth search limit. It usually
correlates directly to the number n of bytes to be touched. We
increase that number by 2 * (log2(n) + 1) here in order to also
cover signed -> unsigned conversions of the src operand as can be seen
in libgcc, and for initial shift/and operation of the src operand. */
- int limit = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (gimple_expr_type (stmt)));
+ int limit = tree_to_uhwi (type_size);
limit += 2 * (1 + (int) ceil_log2 ((unsigned HOST_WIDE_INT) limit));
gimple *ins_stmt = find_bswap_or_nop_1 (stmt, n, limit);
if (!ins_stmt)
- return NULL;
+ {
+ if (gimple_assign_rhs_code (stmt) != CONSTRUCTOR
+ || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ return NULL;
+ unsigned HOST_WIDE_INT sz = tree_to_uhwi (type_size) * BITS_PER_UNIT;
+ if (sz != 16 && sz != 32 && sz != 64)
+ return NULL;
+ tree rhs = gimple_assign_rhs1 (stmt);
+ if (CONSTRUCTOR_NELTS (rhs) == 0)
+ return NULL;
+ tree eltype = TREE_TYPE (TREE_TYPE (rhs));
+ unsigned HOST_WIDE_INT eltsz
+ = int_size_in_bytes (eltype) * BITS_PER_UNIT;
+ if (TYPE_PRECISION (eltype) != eltsz)
+ return NULL;
+ constructor_elt *elt;
+ unsigned int i;
+ tree type = build_nonstandard_integer_type (sz, 1);
+ FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
+ {
+ if (TREE_CODE (elt->value) != SSA_NAME
+ || !INTEGRAL_TYPE_P (TREE_TYPE (elt->value)))
+ return NULL;
+ struct symbolic_number n1;
+ gimple *source_stmt
+ = find_bswap_or_nop_1 (SSA_NAME_DEF_STMT (elt->value), &n1,
+ limit - 1);
+
+ if (!source_stmt)
+ return NULL;
+
+ n1.type = type;
+ if (!n1.base_addr)
+ n1.range = sz / BITS_PER_UNIT;
+
+ if (i == 0)
+ {
+ ins_stmt = source_stmt;
+ *n = n1;
+ }
+ else
+ {
+ if (n->vuse != n1.vuse)
+ return NULL;
+
+ struct symbolic_number n0 = *n;
+
+ if (!BYTES_BIG_ENDIAN)
+ {
+ if (!do_shift_rotate (LSHIFT_EXPR, &n1, i * eltsz))
+ return NULL;
+ }
+ else if (!do_shift_rotate (LSHIFT_EXPR, &n0, eltsz))
+ return NULL;
+ ins_stmt
+ = perform_symbolic_merge (ins_stmt, &n0, source_stmt, &n1, n);
+
+ if (!ins_stmt)
+ return NULL;
+ }
+ }
+ }
uint64_t cmpxchg, cmpnop;
find_bswap_or_nop_finalize (n, &cmpxchg, &cmpnop);
@@ -935,11 +1000,18 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
{
tree src, tmp, tgt = NULL_TREE;
gimple *bswap_stmt;
+ tree_code conv_code = NOP_EXPR;
gimple *cur_stmt = gsi_stmt (gsi);
src = n->src;
if (cur_stmt)
- tgt = gimple_assign_lhs (cur_stmt);
+ {
+ tgt = gimple_assign_lhs (cur_stmt);
+ if (gimple_assign_rhs_code (cur_stmt) == CONSTRUCTOR
+ && tgt
+ && VECTOR_TYPE_P (TREE_TYPE (tgt)))
+ conv_code = VIEW_CONVERT_EXPR;
+ }
/* Need to load the value from memory first. */
if (n->base_addr)
@@ -1027,7 +1099,9 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
load_stmt = gimple_build_assign (val_tmp, val_expr);
gimple_set_vuse (load_stmt, n->vuse);
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
- gimple_assign_set_rhs_with_ops (&gsi, NOP_EXPR, val_tmp);
+ if (conv_code == VIEW_CONVERT_EXPR)
+ val_tmp = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (tgt), val_tmp);
+ gimple_assign_set_rhs_with_ops (&gsi, conv_code, val_tmp);
update_stmt (cur_stmt);
}
else if (cur_stmt)
@@ -1069,7 +1143,9 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
{
if (!is_gimple_val (src))
return NULL_TREE;
- g = gimple_build_assign (tgt, NOP_EXPR, src);
+ if (conv_code == VIEW_CONVERT_EXPR)
+ src = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (tgt), src);
+ g = gimple_build_assign (tgt, conv_code, src);
}
else if (cur_stmt)
g = gimple_build_assign (tgt, src);
@@ -1149,7 +1225,10 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
gimple *convert_stmt;
tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst");
- convert_stmt = gimple_build_assign (tgt, NOP_EXPR, tmp);
+ tree atmp = tmp;
+ if (conv_code == VIEW_CONVERT_EXPR)
+ atmp = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (tgt), tmp);
+ convert_stmt = gimple_build_assign (tgt, conv_code, atmp);
gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
}
@@ -1254,6 +1333,14 @@ pass_optimize_bswap::execute (function *fun)
/* Fall through. */
case BIT_IOR_EXPR:
break;
+ case CONSTRUCTOR:
+ {
+ tree rhs = gimple_assign_rhs1 (cur_stmt);
+ if (VECTOR_TYPE_P (TREE_TYPE (rhs))
+ && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (rhs))))
+ break;
+ }
+ continue;
default:
continue;
}
@@ -1446,6 +1533,7 @@ public:
bool bit_insertion;
bool string_concatenation;
bool only_constants;
+ bool consecutive;
unsigned int first_nonmergeable_order;
int lp_nr;
@@ -1818,6 +1906,7 @@ merged_store_group::merged_store_group (store_immediate_info *info)
bit_insertion = info->rhs_code == BIT_INSERT_EXPR;
string_concatenation = info->rhs_code == STRING_CST;
only_constants = info->rhs_code == INTEGER_CST;
+ consecutive = true;
first_nonmergeable_order = ~0U;
lp_nr = info->lp_nr;
unsigned HOST_WIDE_INT align_bitpos = 0;
@@ -1953,6 +2042,9 @@ merged_store_group::do_merge (store_immediate_info *info)
first_stmt = stmt;
}
+ if (info->bitpos != start + width)
+ consecutive = false;
+
/* We need to use extraction if there is any bit-field. */
if (info->rhs_code == BIT_INSERT_EXPR)
{
@@ -1960,13 +2052,17 @@ merged_store_group::do_merge (store_immediate_info *info)
gcc_assert (!string_concatenation);
}
- /* We need to use concatenation if there is any string. */
+ /* We want to use concatenation if there is any string. */
if (info->rhs_code == STRING_CST)
{
string_concatenation = true;
gcc_assert (!bit_insertion);
}
+ /* But we cannot use it if we don't have consecutive stores. */
+ if (!consecutive)
+ string_concatenation = false;
+
if (info->rhs_code != INTEGER_CST)
only_constants = false;
}
@@ -1978,12 +2074,13 @@ merged_store_group::do_merge (store_immediate_info *info)
void
merged_store_group::merge_into (store_immediate_info *info)
{
+ do_merge (info);
+
/* Make sure we're inserting in the position we think we're inserting. */
gcc_assert (info->bitpos >= start + width
&& info->bitregion_start <= bitregion_end);
width = info->bitpos + info->bitsize - start;
- do_merge (info);
}
/* Merge a store described by INFO into this merged store.
@@ -1993,11 +2090,11 @@ merged_store_group::merge_into (store_immediate_info *info)
void
merged_store_group::merge_overlapping (store_immediate_info *info)
{
+ do_merge (info);
+
/* If the store extends the size of the group, extend the width. */
if (info->bitpos + info->bitsize > start + width)
width = info->bitpos + info->bitsize - start;
-
- do_merge (info);
}
/* Go through all the recorded stores in this group in program order and
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f19e24d..bb13458 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "langhooks.h"
#include "attr-fnspec.h"
+#include "ipa-modref-tree.h"
+#include "ipa-modref.h"
/* All the tuples have their operand vector (if present) at the very bottom
@@ -611,10 +613,6 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
gasm *p;
int size = strlen (string);
- /* ASMs with labels cannot have outputs. This should have been
- enforced by the front end. */
- gcc_assert (nlabels == 0 || noutputs == 0);
-
p = as_a <gasm *> (
gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
ninputs + noutputs + nclobbers + nlabels));
@@ -1487,23 +1485,44 @@ gimple_call_flags (const gimple *stmt)
/* Return the "fn spec" string for call STMT. */
-static const_tree
+attr_fnspec
gimple_call_fnspec (const gcall *stmt)
{
tree type, attr;
if (gimple_call_internal_p (stmt))
- return internal_fn_fnspec (gimple_call_internal_fn (stmt));
+ {
+ const_tree spec = internal_fn_fnspec (gimple_call_internal_fn (stmt));
+ if (spec)
+ return spec;
+ else
+ return "";
+ }
type = gimple_call_fntype (stmt);
- if (!type)
- return NULL_TREE;
-
- attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
- if (!attr)
- return NULL_TREE;
-
- return TREE_VALUE (TREE_VALUE (attr));
+ if (type)
+ {
+ attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+ if (attr)
+ return TREE_VALUE (TREE_VALUE (attr));
+ }
+ if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+ return builtin_fnspec (gimple_call_fndecl (stmt));
+ tree fndecl = gimple_call_fndecl (stmt);
+ /* If the call is to a replaceable operator delete and results
+ from a delete expression as opposed to a direct call to
+ such operator, then we can treat it as free. */
+ if (fndecl
+ && DECL_IS_OPERATOR_DELETE_P (fndecl)
+ && DECL_IS_REPLACEABLE_OPERATOR (fndecl)
+ && gimple_call_from_new_or_delete (stmt))
+ return ".co ";
+ /* Similarly operator new can be treated as malloc. */
+ if (fndecl
+ && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
+ && gimple_call_from_new_or_delete (stmt))
+ return "mC";
+ return "";
}
/* Detects argument flags for argument number ARG on call STMT. */
@@ -1511,26 +1530,46 @@ gimple_call_fnspec (const gcall *stmt)
int
gimple_call_arg_flags (const gcall *stmt, unsigned arg)
{
- const_tree attr = gimple_call_fnspec (stmt);
-
- if (!attr)
- return 0;
-
+ attr_fnspec fnspec = gimple_call_fnspec (stmt);
int flags = 0;
- attr_fnspec fnspec (attr);
- if (!fnspec.arg_specified_p (arg))
- ;
- else if (!fnspec.arg_used_p (arg))
- flags = EAF_UNUSED;
- else
+ if (fnspec.known_p ())
{
- if (fnspec.arg_direct_p (arg))
- flags |= EAF_DIRECT;
- if (fnspec.arg_noescape_p (arg))
- flags |= EAF_NOESCAPE;
- if (fnspec.arg_readonly_p (arg))
- flags |= EAF_NOCLOBBER;
+ if (!fnspec.arg_specified_p (arg))
+ ;
+ else if (!fnspec.arg_used_p (arg))
+ flags = EAF_UNUSED;
+ else
+ {
+ if (fnspec.arg_direct_p (arg))
+ flags |= EAF_DIRECT;
+ if (fnspec.arg_noescape_p (arg))
+ flags |= EAF_NOESCAPE | EAF_NODIRECTESCAPE;
+ if (fnspec.arg_readonly_p (arg))
+ flags |= EAF_NOCLOBBER;
+ }
+ }
+ tree callee = gimple_call_fndecl (stmt);
+ if (callee)
+ {
+ cgraph_node *node = cgraph_node::get (callee);
+ modref_summary *summary = node ? get_modref_function_summary (node)
+ : NULL;
+
+ if (summary && summary->arg_flags.length () > arg)
+ {
+ int modref_flags = summary->arg_flags[arg];
+
+ /* We have possibly optimized out load. Be conservative here. */
+ if (!node->binds_to_current_def_p ())
+ {
+ if ((modref_flags & EAF_UNUSED) && !(flags & EAF_UNUSED))
+ modref_flags &= ~EAF_UNUSED;
+ if ((modref_flags & EAF_DIRECT) && !(flags & EAF_DIRECT))
+ modref_flags &= ~EAF_DIRECT;
+ }
+ flags |= modref_flags;
+ }
}
return flags;
}
@@ -1540,15 +1579,10 @@ gimple_call_arg_flags (const gcall *stmt, unsigned arg)
int
gimple_call_return_flags (const gcall *stmt)
{
- const_tree attr;
-
if (gimple_call_flags (stmt) & ECF_MALLOC)
return ERF_NOALIAS;
- attr = gimple_call_fnspec (stmt);
- if (!attr)
- return 0;
- attr_fnspec fnspec (attr);
+ attr_fnspec fnspec = gimple_call_fnspec (stmt);
unsigned int arg_no;
if (fnspec.returns_arg (&arg_no))
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 3c9b996..8a1db3c 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -175,6 +175,15 @@ enum gf_mask {
GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA = 10,
GF_OMP_TARGET_KIND_OACC_DECLARE = 11,
GF_OMP_TARGET_KIND_OACC_HOST_DATA = 12,
+ /* A 'GF_OMP_TARGET_KIND_OACC_PARALLEL' representing an OpenACC 'kernels'
+ decomposed part, parallelized. */
+ GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED = 13,
+ /* A 'GF_OMP_TARGET_KIND_OACC_PARALLEL' representing an OpenACC 'kernels'
+ decomposed part, "gang-single". */
+ GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE = 14,
+ /* A 'GF_OMP_TARGET_KIND_OACC_DATA' representing an OpenACC 'kernels'
+ decomposed parts' 'data' construct. */
+ GF_OMP_TARGET_KIND_OACC_DATA_KERNELS = 15,
GF_OMP_TEAMS_HOST = 1 << 0,
/* True on an GIMPLE_OMP_RETURN statement if the return does not require
@@ -2229,26 +2238,6 @@ gimple_set_modified (gimple *s, bool modifiedp)
}
-/* Return the tree code for the expression computed by STMT. This is
- only valid for GIMPLE_COND, GIMPLE_CALL and GIMPLE_ASSIGN. For
- GIMPLE_CALL, return CALL_EXPR as the expression code for
- consistency. This is useful when the caller needs to deal with the
- three kinds of computation that GIMPLE supports. */
-
-static inline enum tree_code
-gimple_expr_code (const gimple *stmt)
-{
- enum gimple_code code = gimple_code (stmt);
- if (code == GIMPLE_ASSIGN || code == GIMPLE_COND)
- return (enum tree_code) stmt->subcode;
- else
- {
- gcc_gimple_checking_assert (code == GIMPLE_CALL);
- return CALL_EXPR;
- }
-}
-
-
/* Return true if statement STMT contains volatile operands. */
static inline bool
@@ -3405,7 +3394,7 @@ gimple_call_set_from_new_or_delete (gcall *s, bool from_new_or_delete_p)
from a new or delete expression. */
static inline bool
-gimple_call_from_new_or_delete (gcall *s)
+gimple_call_from_new_or_delete (const gcall *s)
{
return (s->subcode & GF_CALL_FROM_NEW_OR_DELETE) != 0;
}
@@ -3793,6 +3782,28 @@ gimple_cond_set_condition (gcond *stmt, enum tree_code code, tree lhs,
gimple_cond_set_rhs (stmt, rhs);
}
+
+/* Return the tree code for the expression computed by STMT. This is
+ only valid for GIMPLE_COND, GIMPLE_CALL and GIMPLE_ASSIGN. For
+ GIMPLE_CALL, return CALL_EXPR as the expression code for
+ consistency. This is useful when the caller needs to deal with the
+ three kinds of computation that GIMPLE supports. */
+
+static inline enum tree_code
+gimple_expr_code (const gimple *stmt)
+{
+ if (const gassign *ass = dyn_cast<const gassign *> (stmt))
+ return gimple_assign_rhs_code (ass);
+ if (const gcond *cond = dyn_cast<const gcond *> (stmt))
+ return gimple_cond_code (cond);
+ else
+ {
+ gcc_gimple_checking_assert (gimple_code (stmt) == GIMPLE_CALL);
+ return CALL_EXPR;
+ }
+}
+
+
/* Return the LABEL_DECL node used by GIMPLE_LABEL statement GS. */
static inline tree
@@ -4025,7 +4036,7 @@ static inline tree
gimple_asm_label_op (const gasm *asm_stmt, unsigned index)
{
gcc_gimple_checking_assert (index < asm_stmt->nl);
- return asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc];
+ return asm_stmt->op[index + asm_stmt->no + asm_stmt->ni + asm_stmt->nc];
}
/* Set LABEL_OP to be label operand INDEX in GIMPLE_ASM ASM_STMT. */
@@ -4035,7 +4046,7 @@ gimple_asm_set_label_op (gasm *asm_stmt, unsigned index, tree label_op)
{
gcc_gimple_checking_assert (index < asm_stmt->nl
&& TREE_CODE (label_op) == TREE_LIST);
- asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc] = label_op;
+ asm_stmt->op[index + asm_stmt->no + asm_stmt->ni + asm_stmt->nc] = label_op;
}
/* Return the string representing the assembly instruction in
@@ -6509,6 +6520,9 @@ is_gimple_omp_oacc (const gimple *stmt)
case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
case GF_OMP_TARGET_KIND_OACC_DECLARE:
case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
return true;
default:
return false;
@@ -6534,6 +6548,8 @@ is_gimple_omp_offloaded (const gimple *stmt)
case GF_OMP_TARGET_KIND_OACC_PARALLEL:
case GF_OMP_TARGET_KIND_OACC_KERNELS:
case GF_OMP_TARGET_KIND_OACC_SERIAL:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
return true;
default:
return false;
@@ -6598,6 +6614,8 @@ gimple_expr_type (const gimple *stmt)
}
else if (code == GIMPLE_COND)
return boolean_type_node;
+ else if (code == GIMPLE_PHI)
+ return TREE_TYPE (gimple_phi_result (stmt));
else
return void_type_node;
}
diff --git a/gcc/gimplify-me.c b/gcc/gimplify-me.c
index 47148fb..ee84c8b 100644
--- a/gcc/gimplify-me.c
+++ b/gcc/gimplify-me.c
@@ -230,10 +230,8 @@ gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p)
if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
else if (i == 2
- && is_gimple_assign (stmt)
- && num_ops == 2
- && get_gimple_rhs_class (gimple_expr_code (stmt))
- == GIMPLE_SINGLE_RHS)
+ && gimple_assign_single_p (stmt)
+ && num_ops == 2)
gimplify_expr (&op, &pre, NULL,
rhs_predicate_for (gimple_assign_lhs (stmt)),
fb_rvalue);
@@ -255,10 +253,8 @@ gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p)
{
bool need_temp = false;
- if (is_gimple_assign (stmt)
- && num_ops == 2
- && get_gimple_rhs_class (gimple_expr_code (stmt))
- == GIMPLE_SINGLE_RHS)
+ if (gimple_assign_single_p (stmt)
+ && num_ops == 2)
gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
rhs_predicate_for (gimple_assign_lhs (stmt)),
fb_rvalue);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 29f385c..46f726a 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -231,6 +231,8 @@ struct gimplify_omp_ctx
bool target_firstprivatize_array_bases;
bool add_safelen1;
bool order_concurrent;
+ bool has_depend;
+ bool in_for_exprs;
int defaultmap[4];
};
@@ -780,7 +782,7 @@ gimple_add_tmp_var (tree tmp)
if (gimplify_omp_ctxp)
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
- int flag = GOVD_LOCAL;
+ int flag = GOVD_LOCAL | GOVD_SEEN;
while (ctx
&& (ctx->region_type == ORT_WORKSHARE
|| ctx->region_type == ORT_TASKGROUP
@@ -793,14 +795,16 @@ gimple_add_tmp_var (tree tmp)
{
if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
ctx->add_safelen1 = true;
- else
+ else if (ctx->in_for_exprs)
flag = GOVD_PRIVATE;
+ else
+ flag = GOVD_PRIVATE | GOVD_SEEN;
break;
}
ctx = ctx->outer_context;
}
if (ctx)
- omp_add_variable (ctx, tmp, flag | GOVD_SEEN);
+ omp_add_variable (ctx, tmp, flag);
}
}
else if (cfun)
@@ -1237,8 +1241,11 @@ asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
/* It's necessary to have all stack variables aligned to ASAN granularity
bytes. */
- if (DECL_ALIGN_UNIT (decl) <= ASAN_SHADOW_GRANULARITY)
- SET_DECL_ALIGN (decl, BITS_PER_UNIT * ASAN_SHADOW_GRANULARITY);
+ gcc_assert (!hwasan_sanitize_p () || hwasan_sanitize_stack_p ());
+ unsigned shadow_granularity
+ = hwasan_sanitize_p () ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY;
+ if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
+ SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
@@ -3384,6 +3391,20 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
cfun->calls_eh_return = true;
break;
+ case BUILT_IN_CLEAR_PADDING:
+ if (call_expr_nargs (*expr_p) == 1)
+ {
+ /* Remember the original type of the argument in an internal
+ dummy second argument, as in GIMPLE pointer conversions are
+ useless. */
+ p = CALL_EXPR_ARG (*expr_p, 0);
+ *expr_p
+ = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
+ build_zero_cst (TREE_TYPE (p)));
+ return GS_OK;
+ }
+ break;
+
default:
;
}
@@ -4586,7 +4607,11 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
pre_p, cleared);
else
- gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
+ {
+ if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
+ != GS_ERROR)
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
+ }
/* We exit the loop when the index var is equal to the upper bound. */
gimplify_seq_add_stmt (pre_p,
@@ -5518,6 +5543,19 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
return GS_OK;
}
+ case NOP_EXPR:
+ /* Pull out compound literal expressions from a NOP_EXPR.
+ Those are created in the C FE to drop qualifiers during
+ lvalue conversion. */
+ if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
+ && tree_ssa_useless_type_conversion (*from_p))
+ {
+ *from_p = TREE_OPERAND (*from_p, 0);
+ ret = GS_OK;
+ changed = true;
+ }
+ break;
+
case COMPOUND_LITERAL_EXPR:
{
tree complit = TREE_OPERAND (*expr_p, 1);
@@ -7586,6 +7624,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
goto do_outer;
}
+ /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
+ lb, b or incr expressions, those shouldn't be turned into simd arrays. */
+ if (ctx->region_type == ORT_SIMD
+ && ctx->in_for_exprs
+ && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
+ == GOVD_PRIVATE))
+ flags &= ~GOVD_SEEN;
+
if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
&& (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
&& DECL_SIZE (decl))
@@ -8364,6 +8410,113 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp,
return base;
}
+/* Returns true if EXPR is or contains (as a sub-component) BASE_PTR. */
+
+static bool
+is_or_contains_p (tree expr, tree base_ptr)
+{
+ while (expr != base_ptr)
+ if (TREE_CODE (base_ptr) == COMPONENT_REF)
+ base_ptr = TREE_OPERAND (base_ptr, 0);
+ else
+ break;
+ return expr == base_ptr;
+}
+
+/* Implement OpenMP 5.x map ordering rules for target directives. There are
+ several rules, and with some level of ambiguity, hopefully we can at least
+ collect the complexity here in one place. */
+
+static void
+omp_target_reorder_clauses (tree *list_p)
+{
+ /* Collect refs to alloc/release/delete maps. */
+ auto_vec<tree, 32> ard;
+ tree *cp = list_p;
+ while (*cp != NULL_TREE)
+ if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALLOC
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_RELEASE
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_DELETE))
+ {
+ /* Unlink cp and push to ard. */
+ tree c = *cp;
+ tree nc = OMP_CLAUSE_CHAIN (c);
+ *cp = nc;
+ ard.safe_push (c);
+
+ /* Any associated pointer type maps should also move along. */
+ while (*cp != NULL_TREE
+ && OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_POINTER
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ATTACH_DETACH
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_POINTER
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALWAYS_POINTER
+ || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_TO_PSET))
+ {
+ c = *cp;
+ nc = OMP_CLAUSE_CHAIN (c);
+ *cp = nc;
+ ard.safe_push (c);
+ }
+ }
+ else
+ cp = &OMP_CLAUSE_CHAIN (*cp);
+
+ /* Link alloc/release/delete maps to the end of list. */
+ for (unsigned int i = 0; i < ard.length (); i++)
+ {
+ *cp = ard[i];
+ cp = &OMP_CLAUSE_CHAIN (ard[i]);
+ }
+ *cp = NULL_TREE;
+
+ /* OpenMP 5.0 requires that pointer variables are mapped before
+ its use as a base-pointer. */
+ auto_vec<tree *, 32> atf;
+ for (tree *cp = list_p; *cp; cp = &OMP_CLAUSE_CHAIN (*cp))
+ if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP)
+ {
+ /* Collect alloc, to, from, to/from clause tree pointers. */
+ gomp_map_kind k = OMP_CLAUSE_MAP_KIND (*cp);
+ if (k == GOMP_MAP_ALLOC
+ || k == GOMP_MAP_TO
+ || k == GOMP_MAP_FROM
+ || k == GOMP_MAP_TOFROM
+ || k == GOMP_MAP_ALWAYS_TO
+ || k == GOMP_MAP_ALWAYS_FROM
+ || k == GOMP_MAP_ALWAYS_TOFROM)
+ atf.safe_push (cp);
+ }
+
+ for (unsigned int i = 0; i < atf.length (); i++)
+ if (atf[i])
+ {
+ tree *cp = atf[i];
+ tree decl = OMP_CLAUSE_DECL (*cp);
+ if (TREE_CODE (decl) == INDIRECT_REF || TREE_CODE (decl) == MEM_REF)
+ {
+ tree base_ptr = TREE_OPERAND (decl, 0);
+ STRIP_TYPE_NOPS (base_ptr);
+ for (unsigned int j = i + 1; j < atf.length (); j++)
+ {
+ tree *cp2 = atf[j];
+ tree decl2 = OMP_CLAUSE_DECL (*cp2);
+ if (is_or_contains_p (decl2, base_ptr))
+ {
+ /* Move *cp2 to before *cp. */
+ tree c = *cp2;
+ *cp2 = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = *cp;
+ *cp = c;
+ atf[j] = NULL;
+ }
+ }
+ }
+ }
+}
+
/* Scan the OMP clauses in *LIST_P, installing mappings into a new
and previous omp contexts. */
@@ -8405,6 +8558,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
break;
}
+ if (code == OMP_TARGET
+ || code == OMP_TARGET_DATA
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA)
+ omp_target_reorder_clauses (list_p);
+
while ((c = *list_p) != NULL)
{
bool remove = false;
@@ -8559,7 +8718,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
{
error_at (OMP_CLAUSE_LOCATION (c),
"invalid %<task%> reduction modifier on construct "
- "other than %<parallel%>, %<for%> or %<sections%>");
+ "other than %<parallel%>, %qs or %<sections%>",
+ lang_GNU_Fortran () ? "do" : "for");
OMP_CLAUSE_REDUCTION_TASK (c) = 0;
}
}
@@ -8845,15 +9005,18 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
|| (OMP_CLAUSE_MAP_KIND (c)
- == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
+ == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
&& TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
{
OMP_CLAUSE_SIZE (c)
= get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), pre_p, NULL,
false);
- omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
- GOVD_FIRSTPRIVATE | GOVD_SEEN);
+ if ((region_type & ORT_TARGET) != 0)
+ omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
+ GOVD_FIRSTPRIVATE | GOVD_SEEN);
}
+
if (!DECL_P (decl))
{
tree d = decl, *pd;
@@ -8878,7 +9041,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
bool indir_p = false;
tree orig_decl = decl;
tree decl_ref = NULL_TREE;
- if ((region_type & ORT_ACC) != 0
+ if ((region_type & (ORT_ACC | ORT_TARGET | ORT_TARGET_DATA)) != 0
&& TREE_CODE (*pd) == COMPONENT_REF
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH
&& code != OACC_UPDATE)
@@ -8886,9 +9049,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
while (TREE_CODE (decl) == COMPONENT_REF)
{
decl = TREE_OPERAND (decl, 0);
- if ((TREE_CODE (decl) == MEM_REF
- && integer_zerop (TREE_OPERAND (decl, 1)))
- || INDIRECT_REF_P (decl))
+ if (((TREE_CODE (decl) == MEM_REF
+ && integer_zerop (TREE_OPERAND (decl, 1)))
+ || INDIRECT_REF_P (decl))
+ && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
+ == POINTER_TYPE))
{
indir_p = true;
decl = TREE_OPERAND (decl, 0);
@@ -8915,8 +9080,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
if (decl != orig_decl && DECL_P (decl) && indir_p)
{
- gomp_map_kind k = (code == OACC_EXIT_DATA) ? GOMP_MAP_DETACH
- : GOMP_MAP_ATTACH;
+ gomp_map_kind k
+ = ((code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
+ ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH);
/* We have a dereference of a struct member. Make this an
attach/detach operation, and ensure the base pointer is
mapped as a FIRSTPRIVATE_POINTER. */
@@ -8925,6 +9091,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
tree next_clause = OMP_CLAUSE_CHAIN (c);
if (k == GOMP_MAP_ATTACH
&& code != OACC_ENTER_DATA
+ && code != OMP_TARGET_ENTER_DATA
&& (!next_clause
|| (OMP_CLAUSE_CODE (next_clause) != OMP_CLAUSE_MAP)
|| (OMP_CLAUSE_MAP_KIND (next_clause)
@@ -8972,17 +9139,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (code == OACC_UPDATE
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
- if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, fb_lvalue)
- == GS_ERROR)
- {
- remove = true;
- break;
- }
if (DECL_P (decl)
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
- && code != OACC_UPDATE)
+ && code != OACC_UPDATE
+ && code != OMP_TARGET_UPDATE)
{
if (error_operand_p (decl))
{
@@ -9044,15 +9206,19 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
bool has_attachments = false;
/* For OpenACC, pointers in structs should trigger an
attach action. */
- if (attach_detach && (region_type & ORT_ACC) != 0)
+ if (attach_detach
+ && ((region_type & (ORT_ACC | ORT_TARGET | ORT_TARGET_DATA))
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA))
+
{
/* Turn a GOMP_MAP_ATTACH_DETACH clause into a
GOMP_MAP_ATTACH or GOMP_MAP_DETACH clause after we
have detected a case that needs a GOMP_MAP_STRUCT
mapping added. */
gomp_map_kind k
- = (code == OACC_EXIT_DATA) ? GOMP_MAP_DETACH
- : GOMP_MAP_ATTACH;
+ = ((code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
+ ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH);
OMP_CLAUSE_SET_MAP_KIND (c, k);
has_attachments = true;
}
@@ -9148,33 +9314,38 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
break;
if (scp)
continue;
- tree d1 = OMP_CLAUSE_DECL (*sc);
- tree d2 = OMP_CLAUSE_DECL (c);
- while (TREE_CODE (d1) == ARRAY_REF)
- d1 = TREE_OPERAND (d1, 0);
- while (TREE_CODE (d2) == ARRAY_REF)
- d2 = TREE_OPERAND (d2, 0);
- if (TREE_CODE (d1) == INDIRECT_REF)
- d1 = TREE_OPERAND (d1, 0);
- if (TREE_CODE (d2) == INDIRECT_REF)
- d2 = TREE_OPERAND (d2, 0);
- while (TREE_CODE (d1) == COMPONENT_REF)
- if (TREE_CODE (d2) == COMPONENT_REF
- && TREE_OPERAND (d1, 1)
- == TREE_OPERAND (d2, 1))
- {
+ if ((region_type & ORT_ACC) != 0)
+ {
+ /* This duplicate checking code is currently only
+ enabled for OpenACC. */
+ tree d1 = OMP_CLAUSE_DECL (*sc);
+ tree d2 = OMP_CLAUSE_DECL (c);
+ while (TREE_CODE (d1) == ARRAY_REF)
d1 = TREE_OPERAND (d1, 0);
+ while (TREE_CODE (d2) == ARRAY_REF)
d2 = TREE_OPERAND (d2, 0);
- }
- else
- break;
- if (d1 == d2)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%qE appears more than once in map "
- "clauses", OMP_CLAUSE_DECL (c));
- remove = true;
- break;
+ if (TREE_CODE (d1) == INDIRECT_REF)
+ d1 = TREE_OPERAND (d1, 0);
+ if (TREE_CODE (d2) == INDIRECT_REF)
+ d2 = TREE_OPERAND (d2, 0);
+ while (TREE_CODE (d1) == COMPONENT_REF)
+ if (TREE_CODE (d2) == COMPONENT_REF
+ && TREE_OPERAND (d1, 1)
+ == TREE_OPERAND (d2, 1))
+ {
+ d1 = TREE_OPERAND (d1, 0);
+ d2 = TREE_OPERAND (d2, 0);
+ }
+ else
+ break;
+ if (d1 == d2)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE appears more than once in map "
+ "clauses", OMP_CLAUSE_DECL (c));
+ remove = true;
+ break;
+ }
}
if (maybe_lt (offset1, offsetn)
|| (known_eq (offset1, offsetn)
@@ -9220,6 +9391,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
}
}
+
+ if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, fb_lvalue)
+ == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+
if (!remove
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_POINTER
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
@@ -9236,10 +9415,60 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
break;
}
+ else
+ {
+ /* DECL_P (decl) == true */
+ tree *sc;
+ if (struct_map_to_clause
+ && (sc = struct_map_to_clause->get (decl)) != NULL
+ && OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_STRUCT
+ && decl == OMP_CLAUSE_DECL (*sc))
+ {
+ /* We have found a map of the whole structure after a
+ leading GOMP_MAP_STRUCT has been created, so refill the
+ leading clause into a map of the whole structure
+ variable, and remove the current one.
+ TODO: we should be able to remove some maps of the
+ following structure element maps if they are of
+ compatible TO/FROM/ALLOC type. */
+ OMP_CLAUSE_SET_MAP_KIND (*sc, OMP_CLAUSE_MAP_KIND (c));
+ OMP_CLAUSE_SIZE (*sc) = unshare_expr (OMP_CLAUSE_SIZE (c));
+ remove = true;
+ break;
+ }
+ }
flags = GOVD_MAP | GOVD_EXPLICIT;
if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
|| OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
flags |= GOVD_MAP_ALWAYS_TO;
+
+ if ((code == OMP_TARGET
+ || code == OMP_TARGET_DATA
+ || code == OMP_TARGET_ENTER_DATA
+ || code == OMP_TARGET_EXIT_DATA)
+ && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
+ {
+ for (struct gimplify_omp_ctx *octx = outer_ctx; octx;
+ octx = octx->outer_context)
+ {
+ splay_tree_node n
+ = splay_tree_lookup (octx->variables,
+ (splay_tree_key) OMP_CLAUSE_DECL (c));
+ /* If this is contained in an outer OpenMP region as a
+ firstprivate value, remove the attach/detach. */
+ if (n && (n->value & GOVD_FIRSTPRIVATE))
+ {
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FIRSTPRIVATE_POINTER);
+ goto do_add;
+ }
+ }
+
+ enum gomp_map_kind map_kind = (code == OMP_TARGET_EXIT_DATA
+ ? GOMP_MAP_DETACH
+ : GOMP_MAP_ATTACH);
+ OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
+ }
+
goto do_add;
case OMP_CLAUSE_DEPEND:
@@ -9284,6 +9513,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
remove = true;
break;
}
+ if (code == OMP_TASK)
+ ctx->has_depend = true;
break;
case OMP_CLAUSE_TO:
@@ -9708,6 +9939,30 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
break;
+ case OMP_CLAUSE_ALLOCATE:
+ decl = OMP_CLAUSE_DECL (c);
+ if (error_operand_p (decl))
+ {
+ remove = true;
+ break;
+ }
+ if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
+ || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ == INTEGER_CST))
+ ;
+ else if (code == OMP_TASKLOOP
+ || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+ = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
+ pre_p, NULL, false);
+ break;
+
case OMP_CLAUSE_DEFAULT:
ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
break;
@@ -9970,6 +10225,11 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
return 0;
}
code = OMP_CLAUSE_SHARED;
+ /* Don't optimize shared into firstprivate for read-only vars
+ on tasks with depend clause, we shouldn't try to copy them
+ until the dependencies are satisfied. */
+ if (gimplify_omp_ctxp->has_depend)
+ flags |= GOVD_WRITTEN;
}
else if (flags & GOVD_PRIVATE)
code = OMP_CLAUSE_PRIVATE;
@@ -10257,6 +10517,10 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+ && ctx->has_depend
+ && DECL_P (decl))
+ n->value |= GOVD_WRITTEN;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
&& (n->value & GOVD_WRITTEN) == 0
&& DECL_P (decl)
@@ -10270,6 +10534,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
}
+ else
+ n->value &= ~GOVD_EXPLICIT;
break;
case OMP_CLAUSE_LASTPRIVATE:
@@ -10569,6 +10835,41 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
break;
+
+ case OMP_CLAUSE_ALLOCATE:
+ decl = OMP_CLAUSE_DECL (c);
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if (n != NULL && !(n->value & GOVD_SEEN))
+ {
+ if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
+ != 0
+ && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
+ remove = true;
+ }
+ if (!remove
+ && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+ && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
+ && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
+ || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
+ || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
+ {
+ tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
+ if (n == NULL)
+ {
+ enum omp_clause_default_kind default_kind
+ = ctx->default_kind;
+ ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
+ omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
+ true);
+ ctx->default_kind = default_kind;
+ }
+ else
+ omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
+ true);
+ }
+ break;
+
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
@@ -11417,6 +11718,15 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
if (c)
tile = list_length (OMP_CLAUSE_TILE_LIST (c));
+ c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
+ hash_set<tree> *allocate_uids = NULL;
+ if (c)
+ {
+ allocate_uids = new hash_set<tree>;
+ for (; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
+ allocate_uids->add (OMP_CLAUSE_DECL (c));
+ }
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
{
t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
@@ -11743,12 +12053,13 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
as an iteration counter. This is valid, since DECL cannot be
modified in the body of the loop. Similarly for any iteration vars
in simd with collapse > 1 where the iterator vars must be
- lastprivate. */
+ lastprivate. And similarly for vars mentioned in allocate clauses. */
if (orig_for_stmt != for_stmt)
var = decl;
else if (!is_gimple_reg (decl)
|| (ort == ORT_SIMD
- && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1))
+ && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
+ || (allocate_uids && allocate_uids->contains (decl)))
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
/* Make sure omp_add_variable is not called on it prematurely.
@@ -11784,6 +12095,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
else
var = decl;
+ gimplify_omp_ctxp->in_for_exprs = true;
if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
{
tree lb = TREE_OPERAND (t, 1);
@@ -11796,6 +12108,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
else
tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
is_gimple_val, fb_rvalue, false);
+ gimplify_omp_ctxp->in_for_exprs = false;
ret = MIN (ret, tret);
if (ret == GS_ERROR)
return ret;
@@ -11805,6 +12118,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gcc_assert (COMPARISON_CLASS_P (t));
gcc_assert (TREE_OPERAND (t, 0) == decl);
+ gimplify_omp_ctxp->in_for_exprs = true;
if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
{
tree ub = TREE_OPERAND (t, 1);
@@ -11817,6 +12131,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
else
tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
is_gimple_val, fb_rvalue, false);
+ gimplify_omp_ctxp->in_for_exprs = false;
ret = MIN (ret, tret);
/* Handle OMP_FOR_INCR. */
@@ -11882,6 +12197,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gcc_unreachable ();
}
+ gimplify_omp_ctxp->in_for_exprs = true;
tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
is_gimple_val, fb_rvalue, false);
ret = MIN (ret, tret);
@@ -11903,6 +12219,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
ret = MIN (ret, tret);
}
}
+ gimplify_omp_ctxp->in_for_exprs = false;
break;
default:
@@ -11975,6 +12292,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
}
BITMAP_FREE (has_decl_expr);
+ delete allocate_uids;
if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
|| (loop_p && orig_for_stmt == for_stmt))
@@ -12104,6 +12422,20 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
tree *gtask_clauses_ptr = &task_clauses;
tree outer_for_clauses = NULL_TREE;
tree *gforo_clauses_ptr = &outer_for_clauses;
+ bitmap lastprivate_uids = NULL;
+ if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
+ {
+ c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
+ if (c)
+ {
+ lastprivate_uids = BITMAP_ALLOC (NULL);
+ for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+ OMP_CLAUSE_LASTPRIVATE))
+ bitmap_set_bit (lastprivate_uids,
+ DECL_UID (OMP_CLAUSE_DECL (c)));
+ }
+ c = *gfor_clauses_ptr;
+ }
for (; c; c = OMP_CLAUSE_CHAIN (c))
switch (OMP_CLAUSE_CODE (c))
{
@@ -12149,7 +12481,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
*gforo_clauses_ptr = c;
gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
break;
- /* Taskloop clause we duplicate on both taskloops. */
+ /* Collapse clause we duplicate on both taskloops. */
case OMP_CLAUSE_COLLAPSE:
*gfor_clauses_ptr = c;
gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
@@ -12191,12 +12523,43 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gtask_clauses_ptr
= &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
break;
+ /* Allocate clause we duplicate on task and inner taskloop
+ if the decl is lastprivate, otherwise just put on task. */
+ case OMP_CLAUSE_ALLOCATE:
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+ && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
+ {
+ /* Additionally, put firstprivate clause on task
+ for the allocator if it is not constant. */
+ *gtask_clauses_ptr
+ = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (*gtask_clauses_ptr)
+ = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+ }
+ if (lastprivate_uids
+ && bitmap_bit_p (lastprivate_uids,
+ DECL_UID (OMP_CLAUSE_DECL (c))))
+ {
+ *gfor_clauses_ptr = c;
+ gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+ *gtask_clauses_ptr = copy_node (c);
+ gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+ }
+ else
+ {
+ *gtask_clauses_ptr = c;
+ gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+ }
+ break;
default:
gcc_unreachable ();
}
*gfor_clauses_ptr = NULL_TREE;
*gtask_clauses_ptr = NULL_TREE;
*gforo_clauses_ptr = NULL_TREE;
+ BITMAP_FREE (lastprivate_uids);
g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE, NULL_TREE);
@@ -12453,7 +12816,8 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
{
error_at (OMP_CLAUSE_LOCATION (*pc),
"invalid %<task%> reduction modifier on construct "
- "other than %<parallel%>, %<for%> or %<sections%>");
+ "other than %<parallel%>, %qs or %<sections%>",
+ lang_GNU_Fortran () ? "do" : "for");
OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
}
pc = &OMP_CLAUSE_CHAIN (*pc);
@@ -15064,7 +15428,7 @@ gimplify_function_tree (tree fndecl)
if necessary. */
cfun->curr_properties |= PROP_gimple_lva;
- if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS))
+ if (asan_sanitize_use_after_scope ())
asan_poisoned_variables = new hash_set<tree> ();
bind = gimplify_body (fndecl, true);
if (asan_poisoned_variables)
diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h
index 9c4b038..39139ee 100644
--- a/gcc/ginclude/float.h
+++ b/gcc/ginclude/float.h
@@ -248,9 +248,45 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define DBL_NORM_MAX __DBL_NORM_MAX__
#define LDBL_NORM_MAX __LDBL_NORM_MAX__
+/* Whether each type matches an IEC 60559 format (1 for format, 2 for
+ format and operations). */
+#undef FLT_IS_IEC_60559
+#undef DBL_IS_IEC_60559
+#undef LDBL_IS_IEC_60559
+#define FLT_IS_IEC_60559 __FLT_IS_IEC_60559__
+#define DBL_IS_IEC_60559 __DBL_IS_IEC_60559__
+#define LDBL_IS_IEC_60559 __LDBL_IS_IEC_60559__
+
+/* Infinity in type float, or overflow if infinity not supported. */
+#undef INFINITY
+#define INFINITY (__builtin_inff ())
+
+/* Quiet NaN, if supported for float. */
+#if __FLT_HAS_QUIET_NAN__
+#undef NAN
+#define NAN (__builtin_nanf (""))
+#endif
+
+/* Signaling NaN, if supported for each type. All formats supported
+ by GCC support either both quiet and signaling NaNs, or neither
+ kind of NaN. */
+#if __FLT_HAS_QUIET_NAN__
+#undef FLT_SNAN
+#define FLT_SNAN (__builtin_nansf (""))
+#endif
+#if __DBL_HAS_QUIET_NAN__
+#undef DBL_SNAN
+#define DBL_SNAN (__builtin_nans (""))
+#endif
+#if __LDBL_HAS_QUIET_NAN__
+#undef LDBL_SNAN
+#define LDBL_SNAN (__builtin_nansl (""))
+#endif
+
#endif /* C2X */
-#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
+#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ \
+ || defined __STDC_WANT_IEC_60559_EXT__)
/* Number of decimal digits for which conversions between decimal
character strings and binary formats, in both directions, are
correctly rounded. */
@@ -284,6 +320,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__
#undef FLT16_TRUE_MIN
#define FLT16_TRUE_MIN __FLT16_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT16_SNAN
+#define FLT16_SNAN (__builtin_nansf16 (""))
+#endif /* C2X */
#endif /* __FLT16_MANT_DIG__. */
#ifdef __FLT32_MANT_DIG__
@@ -309,6 +349,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT32_DECIMAL_DIG __FLT32_DECIMAL_DIG__
#undef FLT32_TRUE_MIN
#define FLT32_TRUE_MIN __FLT32_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT32_SNAN
+#define FLT32_SNAN (__builtin_nansf32 (""))
+#endif /* C2X */
#endif /* __FLT32_MANT_DIG__. */
#ifdef __FLT64_MANT_DIG__
@@ -334,6 +378,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT64_DECIMAL_DIG __FLT64_DECIMAL_DIG__
#undef FLT64_TRUE_MIN
#define FLT64_TRUE_MIN __FLT64_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT64_SNAN
+#define FLT64_SNAN (__builtin_nansf64 (""))
+#endif /* C2X */
#endif /* __FLT64_MANT_DIG__. */
#ifdef __FLT128_MANT_DIG__
@@ -359,6 +407,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT128_DECIMAL_DIG __FLT128_DECIMAL_DIG__
#undef FLT128_TRUE_MIN
#define FLT128_TRUE_MIN __FLT128_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT128_SNAN
+#define FLT128_SNAN (__builtin_nansf128 (""))
+#endif /* C2X */
#endif /* __FLT128_MANT_DIG__. */
#ifdef __FLT32X_MANT_DIG__
@@ -384,6 +436,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT32X_DECIMAL_DIG __FLT32X_DECIMAL_DIG__
#undef FLT32X_TRUE_MIN
#define FLT32X_TRUE_MIN __FLT32X_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT32X_SNAN
+#define FLT32X_SNAN (__builtin_nansf32x (""))
+#endif /* C2X */
#endif /* __FLT32X_MANT_DIG__. */
#ifdef __FLT64X_MANT_DIG__
@@ -409,6 +465,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT64X_DECIMAL_DIG __FLT64X_DECIMAL_DIG__
#undef FLT64X_TRUE_MIN
#define FLT64X_TRUE_MIN __FLT64X_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT64X_SNAN
+#define FLT64X_SNAN (__builtin_nansf64x (""))
+#endif /* C2X */
#endif /* __FLT64X_MANT_DIG__. */
#ifdef __FLT128X_MANT_DIG__
@@ -434,6 +494,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define FLT128X_DECIMAL_DIG __FLT128X_DECIMAL_DIG__
#undef FLT128X_TRUE_MIN
#define FLT128X_TRUE_MIN __FLT128X_DENORM_MIN__
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#undef FLT128X_SNAN
+#define FLT128X_SNAN (__builtin_nansf128x (""))
+#endif /* C2X */
#endif /* __FLT128X_MANT_DIG__. */
#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__. */
@@ -537,6 +601,26 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif /* __STDC_WANT_IEC_60559_DFP_EXT__ || C2X. */
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+
+/* Infinity in type _Decimal32. */
+#undef DEC_INFINITY
+#define DEC_INFINITY (__builtin_infd32 ())
+
+/* Quiet NaN in type _Decimal32. */
+#undef DEC_NAN
+#define DEC_NAN (__builtin_nand32 (""))
+
+/* Signaling NaN in each decimal floating-point type. */
+#undef DEC32_SNAN
+#define DEC32_SNAN (__builtin_nansd32 (""))
+#undef DEC64_SNAN
+#define DEC64_SNAN (__builtin_nansd64 (""))
+#undef DEC128_SNAN
+#define DEC128_SNAN (__builtin_nansd128 (""))
+
+#endif /* C2X */
+
#endif /* __DEC32_MANT_DIG__ */
#endif /* _FLOAT_H___ */
diff --git a/gcc/ginclude/stdatomic.h b/gcc/ginclude/stdatomic.h
index b968164..7c2e08a 100644
--- a/gcc/ginclude/stdatomic.h
+++ b/gcc/ginclude/stdatomic.h
@@ -107,7 +107,7 @@ extern void atomic_signal_fence (memory_order);
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
-/* Note that these macros require __typeof__ and __auto_type to remove
+/* Note that these macros require __auto_type to remove
_Atomic qualifiers (and const qualifiers, if those are valid on
macro operands).
@@ -122,7 +122,7 @@ extern void atomic_signal_fence (memory_order);
__extension__ \
({ \
__auto_type __atomic_store_ptr = (PTR); \
- __typeof__ (*__atomic_store_ptr) __atomic_store_tmp = (VAL); \
+ __typeof__ ((void)0, *__atomic_store_ptr) __atomic_store_tmp = (VAL); \
__atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO)); \
})
@@ -134,7 +134,7 @@ extern void atomic_signal_fence (memory_order);
__extension__ \
({ \
__auto_type __atomic_load_ptr = (PTR); \
- __typeof__ (*__atomic_load_ptr) __atomic_load_tmp; \
+ __typeof__ ((void)0, *__atomic_load_ptr) __atomic_load_tmp; \
__atomic_load (__atomic_load_ptr, &__atomic_load_tmp, (MO)); \
__atomic_load_tmp; \
})
@@ -146,8 +146,8 @@ extern void atomic_signal_fence (memory_order);
__extension__ \
({ \
__auto_type __atomic_exchange_ptr = (PTR); \
- __typeof__ (*__atomic_exchange_ptr) __atomic_exchange_val = (VAL); \
- __typeof__ (*__atomic_exchange_ptr) __atomic_exchange_tmp; \
+ __typeof__ ((void)0, *__atomic_exchange_ptr) __atomic_exchange_val = (VAL); \
+ __typeof__ ((void)0, *__atomic_exchange_ptr) __atomic_exchange_tmp; \
__atomic_exchange (__atomic_exchange_ptr, &__atomic_exchange_val, \
&__atomic_exchange_tmp, (MO)); \
__atomic_exchange_tmp; \
@@ -161,7 +161,7 @@ extern void atomic_signal_fence (memory_order);
__extension__ \
({ \
__auto_type __atomic_compare_exchange_ptr = (PTR); \
- __typeof__ (*__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
+ __typeof__ ((void)0, *__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
= (DES); \
__atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \
&__atomic_compare_exchange_tmp, 0, \
@@ -176,7 +176,7 @@ extern void atomic_signal_fence (memory_order);
__extension__ \
({ \
__auto_type __atomic_compare_exchange_ptr = (PTR); \
- __typeof__ (*__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
+ __typeof__ ((void)0, *__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
= (DES); \
__atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \
&__atomic_compare_exchange_tmp, 1, \
diff --git a/gcc/ginclude/stdbool.h b/gcc/ginclude/stdbool.h
index 1b56498..2355422 100644
--- a/gcc/ginclude/stdbool.h
+++ b/gcc/ginclude/stdbool.h
@@ -31,8 +31,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef __cplusplus
#define bool _Bool
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#define true ((_Bool)+1u)
+#define false ((_Bool)+0u)
+#else
#define true 1
#define false 0
+#endif
#else /* __cplusplus */
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index b25aa0c..4d611a1 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,37 @@
+2020-12-22 Ian Lance Taylor <iant@golang.org>
+
+ PR go/98402
+ * go-lang.c (go_langhook_init): Force MPFR exponent range to be
+ large enough to support Go constants.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (go.serial): Change from goal to a variable.
+ (.PHONY): Drop go.serial and go.prev.
+ (go1$(exeext)): Depend on $(go.serial) rather than go.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (go.serial): New goal.
+ (.PHONY): Add go.serial go.prev.
+ (go1$(exeext)): Depend on go.prev. Call LINK_PROGRESS.
+
+2020-11-11 Alan Modra <amodra@gmail.com>
+
+ * go-gcc.cc (Gcc_backend::global_variable_set_init): Cast NULL to
+ avoid ambiguous overloaded call.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * go-gcc.cc (Gcc_backend::call_expression): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+
+2020-11-04 Ian Lance Taylor <iant@golang.org>
+
+ * go-lang.c (go_langhook_post_options): Disable
+ -fipa-icf-functions if it was not explicitly enabled.
+
2020-09-14 Jakub Jelinek <jakub@redhat.com>
* go-gcc.cc (Gcc_backend::function): Adjust
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
index ce711b2..a987127 100644
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -27,6 +27,7 @@ GCCGO_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccgo|sed '$(pr
# The name for selecting go in LANGUAGES.
go: go1$(exeext)
+go.serial = go1$(exeext)
.PHONY: go
@@ -78,9 +79,11 @@ GO_OBJS = \
go_OBJS = $(GO_OBJS) go/gospec.o
-go1$(exeext): $(GO_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+go1$(exeext): $(GO_OBJS) attribs.o $(BACKEND) $(LIBDEPS) $(go.prev)
+ @$(call LINK_PROGRESS,$(INDEX.go),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GO_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.go),end)
# Documentation.
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 505fb15..d8d9c3f 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -2110,7 +2110,7 @@ Gcc_backend::call_expression(Bfunction*, // containing fcn for call
if (optimize
&& TREE_CODE(fndecl) == FUNCTION_DECL
&& fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
- && DECL_IS_BUILTIN (fndecl)
+ && DECL_IS_UNDECLARED_BUILTIN (fndecl)
&& nargs > 0
&& ((SCALAR_FLOAT_TYPE_P(rettype)
&& SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[0])))
@@ -2756,7 +2756,7 @@ Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr)
if (symtab_node::get(var_decl)
&& symtab_node::get(var_decl)->implicit_section)
{
- set_decl_section_name (var_decl, NULL);
+ set_decl_section_name (var_decl, (const char *) NULL);
resolve_unique_section (var_decl,
compute_reloc_for_constant (expr_tree),
1);
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 2cfb410..9c0e7af 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -131,6 +131,16 @@ go_langhook_init (void)
eventually be controllable by a command line option. */
mpfr_set_default_prec (256);
+ /* If necessary, override GCC's choice of minimum and maximum
+ exponents. This should only affect GCC middle-end
+ compilation-time, not correctness. */
+ mpfr_exp_t exp = mpfr_get_emax ();
+ if (exp < (1 << 16) - 1)
+ mpfr_set_emax ((1 << 16) - 1);
+ exp = mpfr_get_emin ();
+ if (exp > - ((1 << 16) - 1))
+ mpfr_set_emin (- ((1 << 16) - 1));
+
/* Go uses exceptions. */
using_eh_for_cleanups ();
@@ -306,6 +316,12 @@ go_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
flag_partial_inlining, 0);
+ /* Go programs expect runtime.Callers to give the right answers,
+ which means that we can't combine functions even if they look the
+ same. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ flag_ipa_icf_functions, 0);
+
/* If the debug info level is still 1, as set in init_options, make
sure that some debugging type is selected. */
if (global_options.x_debug_info_level == DINFO_LEVEL_TERSE
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 3ad6c96..fc5ef44 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-28f3df468666787f83f94220312383a7c267a8ce
+47bdc8bb36f16f9d1dec72df5dd6b45d7b0b0725
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc
index a3cbda9..eca0bf1 100644
--- a/gcc/go/gofrontend/ast-dump.cc
+++ b/gcc/go/gofrontend/ast-dump.cc
@@ -226,7 +226,11 @@ Ast_dump_context::dump_type(const Type* t)
// FIXME: write a type pretty printer instead of
// using mangled names.
if (this->gogo_ != NULL)
- this->ostream() << "(" << t->mangled_name(this->gogo_) << ")";
+ {
+ Backend_name bname;
+ t->backend_name(this->gogo_, &bname);
+ this->ostream() << "(" << bname.name() << ")";
+ }
}
// Dump a textual representation of a block to the
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index 8962f3f..cf68874 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -363,8 +363,6 @@ Node::op_format() const
op << "append";
break;
- case Runtime::SLICECOPY:
- case Runtime::SLICESTRINGCOPY:
case Runtime::TYPEDSLICECOPY:
op << "copy";
break;
diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc
index 277aa74..e99c680 100644
--- a/gcc/go/gofrontend/export.cc
+++ b/gcc/go/gofrontend/export.cc
@@ -461,7 +461,7 @@ should_export(Named_object* no)
return false;
// We don't export various special functions.
- if (Gogo::is_special_name(no->name()))
+ if (Gogo::special_name_pos(no->name()) != std::string::npos)
return false;
// Methods are exported with the type, not here.
@@ -524,7 +524,11 @@ struct Sort_types
if (t1->classification() != t2->classification())
return t1->classification() < t2->classification();
Gogo* gogo = go_get_gogo();
- return gogo->type_descriptor_name(t1, NULL).compare(gogo->type_descriptor_name(t2, NULL)) < 0;
+ Backend_name b1;
+ gogo->type_descriptor_backend_name(t1, NULL, &b1);
+ Backend_name b2;
+ gogo->type_descriptor_backend_name(t2, NULL, &b2);
+ return b1.name() < b2.name();
}
};
@@ -1211,6 +1215,9 @@ Export::write_type_definition(const Type* type, int index)
this->write_string(nt->named_object()->name());
this->write_c_string("\" ");
+ if (!nt->in_heap())
+ this->write_c_string("notinheap ");
+
if (nt->is_alias())
this->write_c_string("= ");
}
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index e76bc69..17b4cfd 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -59,6 +59,67 @@ Expression::traverse_subexpressions(Traverse* traverse)
return this->do_traverse(traverse);
}
+// A traversal used to set the location of subexpressions.
+
+class Set_location : public Traverse
+{
+ public:
+ Set_location(Location loc)
+ : Traverse(traverse_expressions),
+ loc_(loc)
+ { }
+
+ int
+ expression(Expression** pexpr);
+
+ private:
+ Location loc_;
+};
+
+// Set the location of an expression.
+
+int
+Set_location::expression(Expression** pexpr)
+{
+ // Some expressions are shared or don't have an independent
+ // location, so we shouldn't change their location. This is the set
+ // of expressions for which do_copy is just "return this" or
+ // otherwise does not pass down the location.
+ switch ((*pexpr)->classification())
+ {
+ case Expression::EXPRESSION_ERROR:
+ case Expression::EXPRESSION_VAR_REFERENCE:
+ case Expression::EXPRESSION_ENCLOSED_VAR_REFERENCE:
+ case Expression::EXPRESSION_STRING:
+ case Expression::EXPRESSION_FUNC_DESCRIPTOR:
+ case Expression::EXPRESSION_TYPE:
+ case Expression::EXPRESSION_BOOLEAN:
+ case Expression::EXPRESSION_CONST_REFERENCE:
+ case Expression::EXPRESSION_NIL:
+ case Expression::EXPRESSION_TYPE_DESCRIPTOR:
+ case Expression::EXPRESSION_GC_SYMBOL:
+ case Expression::EXPRESSION_PTRMASK_SYMBOL:
+ case Expression::EXPRESSION_TYPE_INFO:
+ case Expression::EXPRESSION_STRUCT_FIELD_OFFSET:
+ return TRAVERSE_CONTINUE;
+ default:
+ break;
+ }
+
+ (*pexpr)->location_ = this->loc_;
+ return TRAVERSE_CONTINUE;
+}
+
+// Set the location of an expression and its subexpressions.
+
+void
+Expression::set_location(Location loc)
+{
+ this->location_ = loc;
+ Set_location sl(loc);
+ this->traverse_subexpressions(&sl);
+}
+
// Default implementation for do_traverse for child classes.
int
@@ -113,7 +174,13 @@ Expression::export_name(Export_function_body* efb, const Named_object* no)
void
Expression::unused_value_error()
{
- this->report_error(_("value computed is not used"));
+ if (this->type()->is_error())
+ {
+ go_assert(saw_errors());
+ this->set_is_error();
+ }
+ else
+ this->report_error(_("value computed is not used"));
}
// Note that this expression is an error. This is called by children
@@ -827,8 +894,7 @@ Type_expression : public Expression
{ }
void
- do_check_types(Gogo*)
- { this->report_error(_("invalid use of type")); }
+ do_check_types(Gogo*);
Expression*
do_copy()
@@ -846,6 +912,18 @@ Type_expression : public Expression
};
void
+Type_expression::do_check_types(Gogo*)
+{
+ if (this->type_->is_error())
+ {
+ go_assert(saw_errors());
+ this->set_is_error();
+ }
+ else
+ this->report_error(_("invalid use of type"));
+}
+
+void
Type_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
ast_dump_context->dump_type(this->type_);
@@ -1596,7 +1674,8 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
return context->backend()->var_expression(this->dvar_, loc);
Gogo* gogo = context->gogo();
- std::string var_name(gogo->function_descriptor_name(no));
+ Backend_name bname;
+ gogo->function_descriptor_backend_name(no, &bname);
bool is_descriptor = false;
if (no->is_function_declaration()
&& !no->func_declaration_value()->asm_name().empty()
@@ -1616,10 +1695,11 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
Btype* btype = this->type()->get_backend(gogo);
Bvariable* bvar;
- std::string asm_name(go_selectively_encode_id(var_name));
if (no->package() != NULL || is_descriptor)
- bvar = context->backend()->immutable_struct_reference(var_name, asm_name,
- btype, loc);
+ bvar =
+ context->backend()->immutable_struct_reference(bname.name(),
+ bname.optional_asm_name(),
+ btype, loc);
else
{
Location bloc = Linemap::predeclared_location();
@@ -1644,7 +1724,8 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
if (no->is_function() && no->func_value()->is_referenced_by_inline())
is_hidden = false;
- bvar = context->backend()->immutable_struct(var_name, asm_name,
+ bvar = context->backend()->immutable_struct(bname.name(),
+ bname.optional_asm_name(),
is_hidden, false,
btype, bloc);
Expression_list* vals = new Expression_list();
@@ -1654,8 +1735,9 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
Translate_context bcontext(gogo, NULL, NULL, NULL);
bcontext.set_is_const();
Bexpression* binit = init->get_backend(&bcontext);
- context->backend()->immutable_struct_set_init(bvar, var_name, is_hidden,
- false, btype, bloc, binit);
+ context->backend()->immutable_struct_set_init(bvar, bname.name(),
+ is_hidden, false, btype,
+ bloc, binit);
}
this->dvar_ = bvar;
@@ -4020,8 +4102,16 @@ Type_conversion_expression::do_string_constant_value(std::string* val) const
unsigned long ival;
if (nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID)
{
+ unsigned int cval = static_cast<unsigned int>(ival);
+ if (static_cast<unsigned long>(cval) != ival)
+ {
+ go_warning_at(this->location(), 0,
+ "unicode code point 0x%lx out of range",
+ ival);
+ cval = 0xfffd; // Unicode "replacement character."
+ }
val->clear();
- Lex::append_char(ival, true, val, this->location());
+ Lex::append_char(cval, true, val, this->location());
return true;
}
}
@@ -5190,11 +5280,9 @@ Unary_expression::do_get_backend(Translate_context* context)
copy_to_heap = (context->function() != NULL
|| context->is_const());
}
- std::string asm_name(go_selectively_encode_id(var_name));
Bvariable* implicit =
- gogo->backend()->implicit_variable(var_name, asm_name,
- btype, true, copy_to_heap,
- false, 0);
+ gogo->backend()->implicit_variable(var_name, "", btype, true,
+ copy_to_heap, false, 0);
gogo->backend()->implicit_variable_set_init(implicit, var_name, btype,
true, copy_to_heap, false,
bexpr);
@@ -5219,10 +5307,9 @@ Unary_expression::do_get_backend(Translate_context* context)
&& this->expr_->is_static_initializer())
{
std::string var_name(gogo->initializer_name());
- std::string asm_name(go_selectively_encode_id(var_name));
Bvariable* decl =
- gogo->backend()->immutable_struct(var_name, asm_name,
- true, false, btype, loc);
+ gogo->backend()->immutable_struct(var_name, "", true, false,
+ btype, loc);
gogo->backend()->immutable_struct_set_init(decl, var_name, true,
false, btype, loc, bexpr);
bexpr = gogo->backend()->var_expression(decl, loc);
@@ -5230,9 +5317,8 @@ Unary_expression::do_get_backend(Translate_context* context)
else if (this->expr_->is_constant())
{
std::string var_name(gogo->initializer_name());
- std::string asm_name(go_selectively_encode_id(var_name));
Bvariable* decl =
- gogo->backend()->implicit_variable(var_name, asm_name, btype,
+ gogo->backend()->implicit_variable(var_name, "", btype,
true, true, false, 0);
gogo->backend()->implicit_variable_set_init(decl, var_name, btype,
true, true, false,
@@ -5248,7 +5334,6 @@ Unary_expression::do_get_backend(Translate_context* context)
{
go_assert(this->expr_->type()->points_to() != NULL);
- bool known_valid = false;
Type* ptype = this->expr_->type()->points_to();
Btype* pbtype = ptype->get_backend(gogo);
switch (this->requires_nil_check(gogo))
@@ -5289,14 +5374,12 @@ Unary_expression::do_get_backend(Translate_context* context)
compare,
bcrash, ubexpr,
loc);
- known_valid = true;
break;
}
case NIL_CHECK_DEFAULT:
go_unreachable();
}
- ret = gogo->backend()->indirect_expression(pbtype, bexpr,
- known_valid, loc);
+ ret = gogo->backend()->indirect_expression(pbtype, bexpr, false, loc);
}
break;
@@ -6279,8 +6362,21 @@ Binary_expression::lower_array_comparison(Gogo* gogo,
args->push_back(this->operand_address(inserter, this->left_));
args->push_back(this->operand_address(inserter, this->right_));
- Expression* ret = Expression::make_call(func, args, false, loc);
-
+ Call_expression* ce = Expression::make_call(func, args, false, loc);
+
+ // Record that this is a call to a generated equality function. We
+ // need to do this because a comparison returns an abstract boolean
+ // type, but the function necessarily returns "bool". The
+ // difference shows up in code like
+ // type mybool bool
+ // var b mybool = [10]string{} == [10]string{}
+ // The comparison function returns "bool", but since a comparison
+ // has an abstract boolean type we need an implicit conversion to
+ // "mybool". The implicit conversion is inserted in
+ // Call_expression::do_flatten.
+ ce->set_is_equal_function();
+
+ Expression* ret = ce;
if (this->op_ == OPERATOR_NOTEQ)
ret = Expression::make_unary(OPERATOR_NOT, ret, loc);
@@ -6971,27 +7067,6 @@ Binary_expression::do_get_backend(Translate_context* context)
// been converted to a String_concat_expression in do_lower.
go_assert(!left_type->is_string_type());
- // For complex division Go might want slightly different results than the
- // backend implementation provides, so we have our own runtime routine.
- if (this->op_ == OPERATOR_DIV && this->left_->type()->complex_type() != NULL)
- {
- Runtime::Function complex_code;
- switch (this->left_->type()->complex_type()->bits())
- {
- case 64:
- complex_code = Runtime::COMPLEX64_DIV;
- break;
- case 128:
- complex_code = Runtime::COMPLEX128_DIV;
- break;
- default:
- go_unreachable();
- }
- Expression* complex_div =
- Runtime::make_call(complex_code, loc, 2, this->left_, this->right_);
- return complex_div->get_backend(context);
- }
-
Bexpression* left = this->left_->get_backend(context);
Bexpression* right = this->right_->get_backend(context);
@@ -8885,8 +8960,8 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
// We will optimize this to directly zeroing the tail,
// instead of allocating a new slice then copy.
- // Retrieve the length. Cannot reference s2 as we will remove
- // the makeslice call.
+ // Retrieve the length and capacity. Cannot reference s2 as
+ // we will remove the makeslice call.
Expression* len_arg = makecall->args()->at(1);
len_arg = Expression::make_cast(int_type, len_arg, loc);
l2tmp = Statement::make_temporary(int_type, len_arg, loc);
@@ -8899,28 +8974,19 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
inserter->insert(c2tmp);
// Check bad len/cap here.
- // if len2 < 0 { panicmakeslicelen(); }
+ // checkmakeslice(type, len, cap)
+ // (Note that if len and cap are constants, we won't see a
+ // makeslice call here, as it will be rewritten to a stack
+ // allocated array by Mark_address_taken::expression.)
+ Expression* elem = Expression::make_type_descriptor(element_type,
+ loc);
len2 = Expression::make_temporary_reference(l2tmp, loc);
- Expression* zero = Expression::make_integer_ul(0, int_type, loc);
- Expression* cond = Expression::make_binary(OPERATOR_LT, len2,
- zero, loc);
- Expression* call = Runtime::make_call(Runtime::PANIC_MAKE_SLICE_LEN,
- loc, 0);
- cond = Expression::make_conditional(cond, call, zero->copy(), loc);
- gogo->lower_expression(function, inserter, &cond);
- gogo->flatten_expression(function, inserter, &cond);
- Statement* s = Statement::make_statement(cond, false);
- inserter->insert(s);
-
- // if cap2 < 0 { panicmakeslicecap(); }
Expression* cap2 = Expression::make_temporary_reference(c2tmp, loc);
- cond = Expression::make_binary(OPERATOR_LT, cap2,
- zero->copy(), loc);
- call = Runtime::make_call(Runtime::PANIC_MAKE_SLICE_CAP, loc, 0);
- cond = Expression::make_conditional(cond, call, zero->copy(), loc);
- gogo->lower_expression(function, inserter, &cond);
- gogo->flatten_expression(function, inserter, &cond);
- s = Statement::make_statement(cond, false);
+ Expression* check = Runtime::make_call(Runtime::CHECK_MAKE_SLICE,
+ loc, 3, elem, len2, cap2);
+ gogo->lower_expression(function, inserter, &check);
+ gogo->flatten_expression(function, inserter, &check);
+ Statement* s = Statement::make_statement(check, false);
inserter->insert(s);
// Remove the original makeslice call.
@@ -9398,6 +9464,8 @@ Builtin_call_expression::do_is_constant() const
if (arg == NULL)
return false;
Type* arg_type = arg->type();
+ if (arg_type->is_error())
+ return true;
if (arg_type->points_to() != NULL
&& arg_type->points_to()->array_type() != NULL
@@ -9469,6 +9537,8 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
if (arg == NULL)
return false;
Type* arg_type = arg->type();
+ if (arg_type->is_error())
+ return false;
if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
{
@@ -9491,17 +9561,25 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
{
if (this->seen_)
return false;
- Expression* e = arg_type->array_type()->length();
- this->seen_ = true;
- bool r = e->numeric_constant_value(nc);
- this->seen_ = false;
- if (r)
+
+ // We may be replacing this expression with a constant
+ // during lowering, so verify the type to report any errors.
+ // It's OK to verify an array type more than once.
+ arg_type->verify();
+ if (!arg_type->is_error())
{
- if (!nc->set_type(Type::lookup_integer_type("int"), false,
- this->location()))
- r = false;
+ Expression* e = arg_type->array_type()->length();
+ this->seen_ = true;
+ bool r = e->numeric_constant_value(nc);
+ this->seen_ = false;
+ if (r)
+ {
+ if (!nc->set_type(Type::lookup_integer_type("int"), false,
+ this->location()))
+ r = false;
+ }
+ return r;
}
- return r;
}
}
else if (this->code_ == BUILTIN_SIZEOF
@@ -11185,6 +11263,13 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
return ret;
}
+ // Add an implicit conversion to a boolean type, if needed. See the
+ // comment in Binary_expression::lower_array_comparison.
+ if (this->is_equal_function_
+ && this->type_ != NULL
+ && this->type_ != Type::lookup_bool_type())
+ return Expression::make_cast(this->type_, this, this->location());
+
return this;
}
@@ -11960,7 +12045,7 @@ Call_expression::do_type()
// parameter types to set the types of the arguments.
void
-Call_expression::do_determine_type(const Type_context*)
+Call_expression::do_determine_type(const Type_context* context)
{
if (!this->determining_types())
return;
@@ -12007,6 +12092,22 @@ Call_expression::do_determine_type(const Type_context*)
(*pa)->determine_type_no_context();
}
}
+
+ // If this is a call to a generated equality function, we determine
+ // the type based on the context. See the comment in
+ // Binary_expression::lower_array_comparison.
+ if (this->is_equal_function_
+ && !context->may_be_abstract
+ && context->type != NULL
+ && context->type->is_boolean_type()
+ && context->type != Type::lookup_bool_type())
+ {
+ go_assert(this->type_ == NULL
+ || this->type_ == Type::lookup_bool_type()
+ || this->type_ == context->type
+ || this->type_->is_error());
+ this->type_ = context->type;
+ }
}
// Called when determining types for a Call_expression. Return true
@@ -12794,24 +12895,11 @@ Array_index_expression::do_determine_type(const Type_context*)
this->array_->determine_type_no_context();
Type_context index_context(Type::lookup_integer_type("int"), false);
- if (this->start_->is_constant())
- this->start_->determine_type(&index_context);
- else
- this->start_->determine_type_no_context();
+ this->start_->determine_type(&index_context);
if (this->end_ != NULL)
- {
- if (this->end_->is_constant())
- this->end_->determine_type(&index_context);
- else
- this->end_->determine_type_no_context();
- }
+ this->end_->determine_type(&index_context);
if (this->cap_ != NULL)
- {
- if (this->cap_->is_constant())
- this->cap_->determine_type(&index_context);
- else
- this->cap_->determine_type_no_context();
- }
+ this->cap_->determine_type(&index_context);
}
// Check types of an array index.
@@ -13248,7 +13336,8 @@ Array_index_expression::do_get_backend(Translate_context* context)
Type* ele_type = this->array_->type()->array_type()->element_type();
Btype* ele_btype = ele_type->get_backend(gogo);
- ret = gogo->backend()->indirect_expression(ele_btype, ptr, true, loc);
+ ret = gogo->backend()->indirect_expression(ele_btype, ptr, false,
+ loc);
}
return ret;
}
@@ -13467,7 +13556,7 @@ Type*
String_index_expression::do_type()
{
if (this->end_ == NULL)
- return Type::lookup_integer_type("uint8");
+ return Type::lookup_integer_type("byte");
else
return this->string_->type();
}
@@ -13480,17 +13569,9 @@ String_index_expression::do_determine_type(const Type_context*)
this->string_->determine_type_no_context();
Type_context index_context(Type::lookup_integer_type("int"), false);
- if (this->start_->is_constant())
- this->start_->determine_type(&index_context);
- else
- this->start_->determine_type_no_context();
+ this->start_->determine_type(&index_context);
if (this->end_ != NULL)
- {
- if (this->end_->is_constant())
- this->end_->determine_type(&index_context);
- else
- this->end_->determine_type_no_context();
- }
+ this->end_->determine_type(&index_context);
}
// Check types of a string index.
@@ -13596,7 +13677,7 @@ String_index_expression::do_get_backend(Translate_context* context)
{
ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc);
Btype* ubtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
- return gogo->backend()->indirect_expression(ubtype, ptr, true, loc);
+ return gogo->backend()->indirect_expression(ubtype, ptr, false, loc);
}
Expression* end = NULL;
@@ -14028,7 +14109,7 @@ Field_reference_expression::do_lower(Gogo* gogo, Named_object* function,
Expression* length_expr = Expression::make_integer_ul(s.length(), NULL, loc);
- Type* byte_type = gogo->lookup_global("byte")->type_value();
+ Type* byte_type = Type::lookup_integer_type("byte");
Array_type* array_type = Type::make_array_type(byte_type, length_expr);
array_type->set_is_array_incomparable();
@@ -15295,9 +15376,22 @@ Array_construction_expression::do_is_static_initializer() const
void
Array_construction_expression::do_determine_type(const Type_context*)
{
+ if (this->is_error_expression())
+ {
+ go_assert(saw_errors());
+ return;
+ }
+
if (this->vals() == NULL)
return;
- Type_context subcontext(this->type_->array_type()->element_type(), false);
+ Array_type* at = this->type_->array_type();
+ if (at == NULL || at->is_error() || at->element_type()->is_error())
+ {
+ go_assert(saw_errors());
+ this->set_is_error();
+ return;
+ }
+ Type_context subcontext(at->element_type(), false);
for (Expression_list::const_iterator pv = this->vals()->begin();
pv != this->vals()->end();
++pv)
@@ -15312,10 +15406,22 @@ Array_construction_expression::do_determine_type(const Type_context*)
void
Array_construction_expression::do_check_types(Gogo*)
{
+ if (this->is_error_expression())
+ {
+ go_assert(saw_errors());
+ return;
+ }
+
if (this->vals() == NULL)
return;
Array_type* at = this->type_->array_type();
+ if (at == NULL || at->is_error() || at->element_type()->is_error())
+ {
+ go_assert(saw_errors());
+ this->set_is_error();
+ return;
+ }
int i = 0;
Type* element_type = at->element_type();
for (Expression_list::const_iterator pv = this->vals()->begin();
@@ -15340,6 +15446,12 @@ Expression*
Array_construction_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter)
{
+ if (this->is_error_expression())
+ {
+ go_assert(saw_errors());
+ return this;
+ }
+
if (this->vals() == NULL)
return this;
@@ -15376,6 +15488,12 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*,
void
Array_construction_expression::do_add_conversions()
{
+ if (this->is_error_expression())
+ {
+ go_assert(saw_errors());
+ return;
+ }
+
if (this->vals() == NULL)
return;
@@ -18251,9 +18369,8 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
{
// The interface conversion table is defined elsewhere.
Btype* btype = this->type()->get_backend(gogo);
- std::string asm_name(go_selectively_encode_id(mangled_name));
this->bvar_ =
- gogo->backend()->immutable_struct_reference(mangled_name, asm_name,
+ gogo->backend()->immutable_struct_reference(mangled_name, "",
btype, loc);
return gogo->backend()->var_expression(this->bvar_, this->location());
}
@@ -18323,8 +18440,7 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
Bexpression* ctor =
gogo->backend()->constructor_expression(btype, ctor_bexprs, loc);
- std::string asm_name(go_selectively_encode_id(mangled_name));
- this->bvar_ = gogo->backend()->immutable_struct(mangled_name, asm_name, false,
+ this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", false,
!is_public, btype, loc);
gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false,
!is_public, btype, loc, ctor);
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index d297523..712f687 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -549,6 +549,16 @@ class Expression
location() const
{ return this->location_; }
+ // Set the location of an expression and all its subexpressions.
+ // This is used for const declarations where the expression is
+ // copied from an earlier declaration.
+ void
+ set_location(Location loc);
+
+ // For set_location. This should really be a local class in
+ // Expression, but it needs types defined in gogo.h.
+ friend class Set_location;
+
// Return whether this is a constant expression.
bool
is_constant() const
@@ -2326,8 +2336,8 @@ class Call_expression : public Expression
fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL)
, expected_result_count_(0), is_varargs_(is_varargs),
varargs_are_lowered_(false), types_are_determined_(false),
- is_deferred_(false), is_concurrent_(false), issued_error_(false),
- is_multi_value_arg_(false), is_flattened_(false)
+ is_deferred_(false), is_concurrent_(false), is_equal_function_(false),
+ issued_error_(false), is_multi_value_arg_(false), is_flattened_(false)
{ }
// The function to call.
@@ -2408,6 +2418,11 @@ class Call_expression : public Expression
set_is_concurrent()
{ this->is_concurrent_ = true; }
+ // Note that this is a call to a generated equality function.
+ void
+ set_is_equal_function()
+ { this->is_equal_function_ = true; }
+
// We have found an error with this call expression; return true if
// we should report it.
bool
@@ -2545,6 +2560,8 @@ class Call_expression : public Expression
bool is_deferred_;
// True if the call is an argument to a go statement.
bool is_concurrent_;
+ // True if this is a call to a generated equality function.
+ bool is_equal_function_;
// True if we reported an error about a mismatch between call
// results and uses. This is to avoid producing multiple errors
// when there are multiple Call_result_expressions.
diff --git a/gcc/go/gofrontend/go-encode-id.cc b/gcc/go/gofrontend/go-encode-id.cc
index 550da97..7ab65f5 100644
--- a/gcc/go/gofrontend/go-encode-id.cc
+++ b/gcc/go/gofrontend/go-encode-id.cc
@@ -12,8 +12,8 @@
#include "go-encode-id.h"
#include "lex.h"
-// Return whether the character c is OK to use in the assembler. We
-// only permit ASCII alphanumeric characters, underscore, and dot.
+// Return whether the character c can appear in a name that we are
+// encoding. We only permit ASCII alphanumeric characters.
static bool
char_needs_encoding(char c)
@@ -32,7 +32,6 @@ char_needs_encoding(char c)
case 'y': case 'z':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- case '_': case '.':
return false;
default:
return true;
@@ -53,6 +52,52 @@ go_id_needs_encoding(const std::string& str)
return false;
}
+// Map from characters to the underscore encoding for them.
+
+class Special_char_code
+{
+ public:
+ Special_char_code();
+
+ // Return the simple underscore encoding for C, or 0 if none.
+ char
+ code_for(unsigned int c) const
+ {
+ if (c <= 127)
+ return this->codes_[c];
+ return 0;
+ }
+
+ private:
+ // Encodings for characters.
+ char codes_[128];
+};
+
+// Construct the underscore encoding map.
+
+Special_char_code::Special_char_code()
+{
+ memset(this->codes_, 0, sizeof this->codes_);
+ this->codes_['_'] = '_';
+ this->codes_['.'] = '0';
+ this->codes_['/'] = '1';
+ this->codes_['*'] = '2';
+ this->codes_[','] = '3';
+ this->codes_['{'] = '4';
+ this->codes_['}'] = '5';
+ this->codes_['['] = '6';
+ this->codes_[']'] = '7';
+ this->codes_['('] = '8';
+ this->codes_[')'] = '9';
+ this->codes_['"'] = 'a';
+ this->codes_[' '] = 'b';
+ this->codes_[';'] = 'c';
+}
+
+// The singleton Special_char_code.
+
+static const Special_char_code special_char_code;
+
// Pull the next UTF-8 character out of P and store it in *PC. Return
// the number of bytes read.
@@ -82,10 +127,9 @@ fetch_utf8_char(const char* p, unsigned int* pc)
return len;
}
-// Encode an identifier using assembler-friendly characters. The encoding is
-// described in detail near the end of the long comment at the start of
-// names.cc. Short version: translate all non-ASCII-alphanumeric characters into
-// ..uXXXX or ..UXXXXXXXX, translate ASCII non-alphanumerics into ".zXX".
+// Encode an identifier using assembler-friendly characters. The
+// encoding is described in detail near the end of the long comment at
+// the start of names.cc.
std::string
go_encode_id(const std::string &id)
@@ -96,50 +140,57 @@ go_encode_id(const std::string &id)
return id;
}
- // The encoding is only unambiguous if the input string does not
- // contain ..z, ..u or ..U.
- go_assert(id.find("..z") == std::string::npos);
- go_assert(id.find("..u") == std::string::npos);
- go_assert(id.find("..U") == std::string::npos);
-
std::string ret;
const char* p = id.c_str();
const char* pend = p + id.length();
- // A leading ".0" is a space introduced before a mangled type name
- // that starts with a 'u' or 'U', to avoid confusion with the
- // mangling used here. We don't need a leading ".0", and we don't
- // want symbols that start with '.', so remove it.
- if (p[0] == '.' && p[1] == '0')
- p += 2;
+ // We encode a leading digit, to ensure that no identifier starts
+ // with a digit.
+ if (pend > p && p[0] >= '0' && p[0] <= '9')
+ {
+ char buf[8];
+ snprintf(buf, sizeof buf, "_x%02x", p[0]);
+ ret.append(buf);
+ ++p;
+ }
while (p < pend)
{
unsigned int c;
size_t len = fetch_utf8_char(p, &c);
- if (len == 1 && !char_needs_encoding(c))
+ if (len == 1)
{
- ret += c;
+ if (!char_needs_encoding(c))
+ ret.push_back(c);
+ else
+ {
+ char code = special_char_code.code_for(c);
+ if (code != 0)
+ {
+ ret.push_back('_');
+ ret.push_back(code);
+ }
+ else
+ {
+ char buf[8];
+ snprintf(buf, sizeof buf, "_x%02x", c);
+ ret.append(buf);
+ }
+ }
}
else
{
char buf[16];
- if (len == 1)
- snprintf(buf, sizeof buf, "..z%02x", c);
- else if (c < 0x10000)
- snprintf(buf, sizeof buf, "..u%04x", c);
+ if (c < 0x10000)
+ snprintf(buf, sizeof buf, "_u%04x", c);
else
- snprintf(buf, sizeof buf, "..U%08x", c);
-
- // We don't want a symbol to start with '.', so add a prefix
- // if needed.
- if (ret.empty())
- ret += '_';
-
- ret += buf;
+ snprintf(buf, sizeof buf, "_U%08x", c);
+ ret.append(buf);
}
+
p += len;
}
+
return ret;
}
@@ -170,64 +221,116 @@ go_decode_id(const std::string &encoded)
const char* pend = p + encoded.length();
const Location loc = Linemap::predeclared_location();
- // Special case for initial "_", in case it was introduced
- // as a way to prevent encoded symbol starting with ".".
- if (*p == '_' && (strncmp(p+1, "..u", 3) == 0 || strncmp(p+1, "..U", 3) == 0))
- p++;
-
while (p < pend)
{
- if (strncmp(p, "..z", 3) == 0)
- {
- const char* digits = p+3;
- if (strlen(digits) < 2)
- return "";
- unsigned rune = hex_digits_to_unicode_codepoint(digits, 2);
- Lex::append_char(rune, true, &ret, loc);
- p += 5;
- }
- else if (strncmp(p, "..u", 3) == 0)
- {
- const char* digits = p+3;
- if (strlen(digits) < 4)
- return "";
- unsigned rune = hex_digits_to_unicode_codepoint(digits, 4);
- Lex::append_char(rune, true, &ret, loc);
- p += 7;
- }
- else if (strncmp(p, "..U", 3) == 0)
- {
- const char* digits = p+3;
- if (strlen(digits) < 8)
- return "";
- unsigned rune = hex_digits_to_unicode_codepoint(digits, 8);
- Lex::append_char(rune, true, &ret, loc);
- p += 11;
- }
- else
- {
- ret += *p;
- p += 1;
- }
+ if (*p != '_' || p + 1 == pend)
+ {
+ ret.push_back(*p);
+ p++;
+ continue;
+ }
+
+ switch (p[1])
+ {
+ case '_':
+ ret.push_back('_');
+ p += 2;
+ break;
+ case '0':
+ ret.push_back('.');
+ p += 2;
+ break;
+ case '1':
+ ret.push_back('/');
+ p += 2;
+ break;
+ case '2':
+ ret.push_back('*');
+ p += 2;
+ break;
+ case '3':
+ ret.push_back(',');
+ p += 2;
+ break;
+ case '4':
+ ret.push_back('{');
+ p += 2;
+ break;
+ case '5':
+ ret.push_back('}');
+ p += 2;
+ break;
+ case '6':
+ ret.push_back('[');
+ p += 2;
+ break;
+ case '7':
+ ret.push_back(']');
+ p += 2;
+ break;
+ case '8':
+ ret.push_back('(');
+ p += 2;
+ break;
+ case '9':
+ ret.push_back(')');
+ p += 2;
+ break;
+ case 'a':
+ ret.push_back('"');
+ p += 2;
+ break;
+ case 'b':
+ ret.push_back(' ');
+ p += 2;
+ break;
+ case 'c':
+ ret.push_back(';');
+ p += 2;
+ break;
+ case 'x':
+ {
+ const char* digits = p + 2;
+ if (strlen(digits) < 2)
+ return "";
+ unsigned int rune = hex_digits_to_unicode_codepoint(digits, 2);
+ Lex::append_char(rune, true, &ret, loc);
+ p += 4;
+ }
+ break;
+ case 'u':
+ {
+ const char* digits = p + 2;
+ if (strlen(digits) < 4)
+ return "";
+ unsigned int rune = hex_digits_to_unicode_codepoint(digits, 4);
+ Lex::append_char(rune, true, &ret, loc);
+ p += 6;
+ }
+ break;
+ case 'U':
+ {
+ const char* digits = p + 2;
+ if (strlen(digits) < 8)
+ return "";
+ unsigned int rune = hex_digits_to_unicode_codepoint(digits, 8);
+ Lex::append_char(rune, true, &ret, loc);
+ p += 10;
+ }
+ break;
+ default:
+ return "";
+ }
}
return ret;
}
-std::string
-go_selectively_encode_id(const std::string &id)
-{
- if (go_id_needs_encoding(id))
- return go_encode_id(id);
- return std::string();
-}
-
// Encode a struct field tag. This is only used when we need to
// create a type descriptor for an anonymous struct type with field
-// tags. This mangling is applied before go_encode_id. We skip
-// alphanumerics and underscore, replace every other single byte
-// character with .xNN, and leave larger UTF-8 characters for
-// go_encode_id.
+// tags. Underscore encoding will be applied to the returned string.
+// The tag will appear between curly braces, so that is all we have to
+// avoid.
std::string
go_mangle_struct_tag(const std::string& tag)
@@ -241,28 +344,14 @@ go_mangle_struct_tag(const std::string& tag)
size_t len = fetch_utf8_char(p, &c);
if (len > 1)
ret.append(p, len);
- else if (!char_needs_encoding(c) && c != '.')
- ret += c;
+ else if (c != '{' && c != '}' && c != '\\')
+ ret.push_back(c);
else
{
- char buf[16];
- snprintf(buf, sizeof buf, ".x%02x", c);
- ret += buf;
+ ret.push_back('\\');
+ ret.push_back(c);
}
p += len;
}
return ret;
}
-
-// Encode a package path.
-
-std::string
-go_mangle_pkgpath(const std::string& pkgpath)
-{
- std::string s = pkgpath;
- for (size_t i = s.find('.');
- i != std::string::npos;
- i = s.find('.', i + 1))
- s.replace(i, 1, ".x2e"); // 0x2e is the ASCII encoding for '.'
- return s;
-}
diff --git a/gcc/go/gofrontend/go-encode-id.h b/gcc/go/gofrontend/go-encode-id.h
index 2d09b0c..cbafd54 100644
--- a/gcc/go/gofrontend/go-encode-id.h
+++ b/gcc/go/gofrontend/go-encode-id.h
@@ -25,21 +25,8 @@ go_encode_id(const std::string &id);
extern std::string
go_decode_id(const std::string &id);
-// Returns the empty string if the specified name needs encoding,
-// otherwise invokes go_encode_id on the name and returns the result.
-extern std::string
-go_selectively_encode_id(const std::string &id);
-
// Encodes a struct tag that appears in a type literal encoding.
extern std::string
go_mangle_struct_tag(const std::string& tag);
-// Encode a package path. A package path can contain any arbitrary
-// character, including '.'. go_encode_id expects that any '.' will
-// be inserted by name mangling in a controlled manner. So first
-// translate any '.' using the same .x encoding as used by
-// go_mangle_struct_tag.
-extern std::string
-go_mangle_pkgpath(const std::string& pkgpath);
-
#endif // !defined(GO_ENCODE_ID_H)
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index f40f131..fbf8935 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -117,17 +117,11 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
// "byte" is an alias for "uint8".
uint8_type->integer_type()->set_is_byte();
- Named_object* byte_type = Named_object::make_type("byte", NULL, uint8_type,
- loc);
- byte_type->type_value()->set_is_alias();
- this->add_named_type(byte_type->type_value());
+ this->add_named_type(Type::make_integer_type_alias("byte", uint8_type));
// "rune" is an alias for "int32".
int32_type->integer_type()->set_is_rune();
- Named_object* rune_type = Named_object::make_type("rune", NULL, int32_type,
- loc);
- rune_type->type_value()->set_is_alias();
- this->add_named_type(rune_type->type_value());
+ this->add_named_type(Type::make_integer_type_alias("rune", int32_type));
this->add_named_type(Type::make_named_bool_type());
@@ -299,7 +293,7 @@ void
Gogo::set_pkgpath(const std::string& arg)
{
go_assert(!this->pkgpath_set_);
- this->pkgpath_ = go_mangle_pkgpath(arg);
+ this->pkgpath_ = arg;
this->pkgpath_set_ = true;
this->pkgpath_from_option_ = true;
}
@@ -324,32 +318,6 @@ Gogo::set_prefix(const std::string& arg)
this->prefix_from_option_ = true;
}
-// Given a name which may or may not have been hidden, append the
-// appropriate version of the name to the result string. Take care
-// to avoid creating a sequence that will be rejected by go_encode_id
-// (avoid ..u, ..U, ..z).
-void
-Gogo::append_possibly_hidden_name(std::string *result, const std::string& name)
-{
- // FIXME: This adds in pkgpath twice for hidden symbols, which is
- // less than ideal.
- if (!Gogo::is_hidden_name(name))
- (*result) += name;
- else
- {
- std::string n = ".";
- std::string pkgpath = Gogo::hidden_name_pkgpath(name);
- char lastR = result->at(result->length() - 1);
- char firstP = pkgpath.at(0);
- if (lastR == '.' && (firstP == 'u' || firstP == 'U' || firstP == 'z'))
- n = "_.";
- n.append(pkgpath);
- n.append(1, '.');
- n.append(Gogo::unpack_hidden_name(name));
- (*result) += n;
- }
-}
-
// Munge name for use in an error message.
std::string
@@ -397,8 +365,7 @@ Gogo::set_package_name(const std::string& package_name,
{
if (!this->prefix_from_option_)
this->prefix_ = "go";
- this->pkgpath_ = (go_mangle_pkgpath(this->prefix_) + '.'
- + package_name);
+ this->pkgpath_ = this->prefix_ + '.' + package_name;
this->pkgpath_symbol_ = (Gogo::pkgpath_for_symbol(this->prefix_) + '.'
+ Gogo::pkgpath_for_symbol(package_name));
}
@@ -792,7 +759,7 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
Type* pvt = Type::make_pointer_type(Type::make_void_type());
Type* uintptr_type = Type::lookup_integer_type("uintptr");
- Type* byte_type = this->lookup_global("byte")->type_value();
+ Type* byte_type = Type::lookup_integer_type("byte");
Type* pointer_byte_type = Type::make_pointer_type(byte_type);
Struct_type* root_type =
Type::make_builtin_struct_type(4,
@@ -997,9 +964,9 @@ Gogo::register_type_descriptors(std::vector<Bstatement*>& init_stmts,
it != this->imported_init_fns_.end();
++it)
{
- std::string pkgpath =
- this->pkgpath_from_init_fn_name((*it)->init_name());
- list_names.push_back(this->type_descriptor_list_symbol(pkgpath));
+ std::string pkgpath_symbol =
+ this->pkgpath_symbol_from_init_fn_name((*it)->init_name());
+ list_names.push_back(this->type_descriptor_list_symbol(pkgpath_symbol));
}
// Add the main package itself.
list_names.push_back(this->type_descriptor_list_symbol("main"));
@@ -1591,6 +1558,17 @@ Gogo::write_globals()
|| (no->is_const() && no->const_value()->is_sink()))
continue;
+ // Skip global sink variables with static initializers. With
+ // non-static initializers we have to evaluate for side effects,
+ // and we wind up initializing a dummy variable. That is not
+ // ideal but it works and it's a rare case.
+ if (no->is_variable()
+ && no->var_value()->is_global_sink()
+ && !no->var_value()->has_pre_init()
+ && (no->var_value()->init() == NULL
+ || no->var_value()->init()->is_static_initializer()))
+ continue;
+
// There is nothing useful we can output for constants which
// have ideal or non-integral type.
if (no->is_const())
@@ -2746,8 +2724,7 @@ Gogo::clear_file_scope()
// parse tree is lowered.
void
-Gogo::queue_hash_function(Type* type, int64_t size,
- const std::string& hash_name,
+Gogo::queue_hash_function(Type* type, int64_t size, Backend_name* bname,
Function_type* hash_fntype)
{
go_assert(!this->specific_type_functions_are_written_);
@@ -2755,7 +2732,7 @@ Gogo::queue_hash_function(Type* type, int64_t size,
Specific_type_function::Specific_type_function_kind kind =
Specific_type_function::SPECIFIC_HASH;
Specific_type_function* tsf = new Specific_type_function(type, NULL, size,
- kind, hash_name,
+ kind, bname,
hash_fntype);
this->specific_type_functions_.push_back(tsf);
}
@@ -2766,15 +2743,14 @@ Gogo::queue_hash_function(Type* type, int64_t size,
void
Gogo::queue_equal_function(Type* type, Named_type* name, int64_t size,
- const std::string& equal_name,
- Function_type* equal_fntype)
+ Backend_name* bname, Function_type* equal_fntype)
{
go_assert(!this->specific_type_functions_are_written_);
go_assert(!this->in_global_scope());
Specific_type_function::Specific_type_function_kind kind =
Specific_type_function::SPECIFIC_EQUAL;
Specific_type_function* tsf = new Specific_type_function(type, name, size,
- kind, equal_name,
+ kind, bname,
equal_fntype);
this->specific_type_functions_.push_back(tsf);
}
@@ -2872,11 +2848,11 @@ Gogo::write_specific_type_functions()
Specific_type_function* tsf = this->specific_type_functions_.back();
this->specific_type_functions_.pop_back();
if (tsf->kind == Specific_type_function::SPECIFIC_HASH)
- tsf->type->write_hash_function(this, tsf->size, tsf->fnname,
+ tsf->type->write_hash_function(this, tsf->size, &tsf->bname,
tsf->fntype);
else
tsf->type->write_equal_function(this, tsf->name, tsf->size,
- tsf->fnname, tsf->fntype);
+ &tsf->bname, tsf->fntype);
delete tsf;
}
this->specific_type_functions_are_written_ = true;
@@ -3773,7 +3749,7 @@ Check_types_traverse::variable(Named_object* named_object)
&& !var->type()->is_error()
&& (init == NULL || !init->is_error_expression())
&& !Lex::is_invalid_identifier(named_object->name()))
- go_error_at(var->location(), "%qs declared and not used",
+ go_error_at(var->location(), "%qs declared but not used",
named_object->message_name().c_str());
}
return TRAVERSE_CONTINUE;
@@ -6218,6 +6194,56 @@ Function::import_func(Import* imp, std::string* pname,
return true;
}
+// Get the backend name.
+
+void
+Function::backend_name(Gogo* gogo, Named_object* no, Backend_name *bname)
+{
+ if (!this->asm_name_.empty())
+ bname->set_asm_name(this->asm_name_);
+ else if (no->package() == NULL && no->name() == gogo->get_init_fn_name())
+ {
+ // These names appear in the export data and are used
+ // directly in the assembler code. If we change this here
+ // we need to change Gogo::init_imports.
+ bname->set_asm_name(no->name());
+ }
+ else if (this->enclosing_ != NULL)
+ {
+ // Rewrite the nested name to use the enclosing function name.
+ // We don't do this earlier because we just store simple names
+ // in a Named_object, not Backend_names.
+
+ // The name was set by nested_function_name, which always
+ // appends ..funcNNN. We want that to be our suffix.
+ size_t pos = no->name().find("..func");
+ go_assert(pos != std::string::npos);
+
+ Named_object* enclosing = this->enclosing_;
+ while (true)
+ {
+ Named_object* parent = enclosing->func_value()->enclosing();
+ if (parent == NULL)
+ break;
+ enclosing = parent;
+ }
+
+ Type* rtype = NULL;
+ if (enclosing->func_value()->type()->is_method())
+ rtype = enclosing->func_value()->type()->receiver()->type();
+ gogo->function_backend_name(enclosing->name(), enclosing->package(),
+ rtype, bname);
+ bname->append_suffix(no->name().substr(pos));
+ }
+ else
+ {
+ Type* rtype = NULL;
+ if (this->type_->is_method())
+ rtype = this->type_->receiver()->type();
+ gogo->function_backend_name(no->name(), no->package(), rtype, bname);
+ }
+}
+
// Get the backend representation.
Bfunction*
@@ -6226,7 +6252,6 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
if (this->fndecl_ == NULL)
{
unsigned int flags = 0;
- bool is_init_fn = false;
if (no->package() != NULL)
{
// Functions defined in other packages must be visible.
@@ -6238,10 +6263,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
&& !this->type_->is_method())
;
else if (no->name() == gogo->get_init_fn_name())
- {
- flags |= Backend::function_is_visible;
- is_init_fn = true;
- }
+ flags |= Backend::function_is_visible;
else if (Gogo::unpack_hidden_name(no->name()) == "main"
&& gogo->is_main_package())
flags |= Backend::function_is_visible;
@@ -6255,29 +6277,13 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
flags |= Backend::function_is_visible;
}
- Type* rtype = NULL;
- if (this->type_->is_method())
- rtype = this->type_->receiver()->type();
-
- std::string asm_name;
if (!this->asm_name_.empty())
{
- asm_name = this->asm_name_;
-
// If an assembler name is explicitly specified, there must
// be some reason to refer to the symbol from a different
// object file.
flags |= Backend::function_is_visible;
}
- else if (is_init_fn)
- {
- // These names appear in the export data and are used
- // directly in the assembler code. If we change this here
- // we need to change Gogo::init_imports.
- asm_name = no->name();
- }
- else
- asm_name = gogo->function_asm_name(no->name(), no->package(), rtype);
// If an inline body refers to this function, then it
// needs to be visible in the symbol table.
@@ -6337,13 +6343,36 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
flags |= Backend::function_only_inline;
Btype* functype = this->type_->get_backend_fntype(gogo);
- this->fndecl_ =
- gogo->backend()->function(functype, no->get_id(gogo), asm_name,
- flags, this->location());
+
+ Backend_name bname;
+ this->backend_name(gogo, no, &bname);
+
+ this->fndecl_ = gogo->backend()->function(functype,
+ bname.name(),
+ bname.optional_asm_name(),
+ flags,
+ this->location());
}
return this->fndecl_;
}
+// Get the backend name.
+
+void
+Function_declaration::backend_name(Gogo* gogo, Named_object* no,
+ Backend_name* bname)
+{
+ if (!this->asm_name_.empty())
+ bname->set_asm_name(this->asm_name_);
+ else
+ {
+ Type* rtype = NULL;
+ if (this->fntype_->is_method())
+ rtype = this->fntype_->receiver()->type();
+ gogo->function_backend_name(no->name(), no->package(), rtype, bname);
+ }
+}
+
// Get the backend representation.
Bfunction*
@@ -6375,21 +6404,16 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
flags |= Backend::function_does_not_return;
}
- std::string asm_name;
- if (this->asm_name_.empty())
- {
- Type* rtype = NULL;
- if (this->fntype_->is_method())
- rtype = this->fntype_->receiver()->type();
- asm_name = gogo->function_asm_name(no->name(), no->package(), rtype);
- }
- else if (go_id_needs_encoding(no->get_id(gogo)))
- asm_name = go_encode_id(no->get_id(gogo));
-
Btype* functype = this->fntype_->get_backend_fntype(gogo);
- this->fndecl_ =
- gogo->backend()->function(functype, no->get_id(gogo), asm_name,
- flags, this->location());
+
+ Backend_name bname;
+ this->backend_name(gogo, no, &bname);
+
+ this->fndecl_ = gogo->backend()->function(functype,
+ bname.name(),
+ bname.optional_asm_name(),
+ flags,
+ this->location());
}
return this->fndecl_;
@@ -7434,7 +7458,7 @@ Variable::Variable(Type* type, Expression* init, bool is_global,
: type_(type), init_(init), preinit_(NULL), location_(location),
backend_(NULL), is_global_(is_global), is_parameter_(is_parameter),
is_closure_(false), is_receiver_(is_receiver),
- is_varargs_parameter_(false), is_used_(false),
+ is_varargs_parameter_(false), is_global_sink_(false), is_used_(false),
is_address_taken_(false), is_non_escaping_address_taken_(false),
seen_(false), init_is_lowered_(false), init_is_flattened_(false),
type_from_init_tuple_(false), type_from_range_index_(false),
@@ -7993,7 +8017,6 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
type = Type::make_pointer_type(type);
}
- const std::string n = Gogo::unpack_hidden_name(name);
Btype* btype = type->get_backend(gogo);
Bvariable* bvar;
@@ -8001,19 +8024,14 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
bvar = Map_type::backend_zero_value(gogo);
else if (this->is_global_)
{
- std::string var_name(package != NULL
- ? package->package_name()
- : gogo->package_name());
- var_name.push_back('.');
- var_name.append(n);
-
- std::string asm_name(gogo->global_var_asm_name(name, package));
+ Backend_name bname;
+ gogo->global_var_backend_name(name, package, &bname);
bool is_hidden = Gogo::is_hidden_name(name);
// Hack to export runtime.writeBarrier. FIXME.
// This is because go:linkname doesn't work on variables.
if (gogo->compiling_runtime()
- && var_name == "runtime.writeBarrier")
+ && bname.name() == "runtime.writeBarrier")
is_hidden = false;
// If an inline body refers to this variable, then it
@@ -8028,8 +8046,12 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
if (package != NULL)
is_hidden = false;
- bvar = backend->global_variable(var_name,
- asm_name,
+ // For some reason asm_name can't be the empty string
+ // for global_variable, so we call asm_name rather than
+ // optional_asm_name here. FIXME.
+
+ bvar = backend->global_variable(bname.name(),
+ bname.asm_name(),
btype,
package != NULL,
is_hidden,
@@ -8043,6 +8065,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
}
else
{
+ const std::string n = Gogo::unpack_hidden_name(name);
Bfunction* bfunction = function->func_value()->get_decl();
bool is_address_taken = (this->is_non_escaping_address_taken_
&& !this->is_in_heap());
@@ -8216,7 +8239,13 @@ Named_constant::get_backend(Gogo* gogo, Named_object* const_no)
if (type != NULL && type->is_numeric_type())
{
Btype* btype = type->get_backend(gogo);
- std::string name = const_no->get_id(gogo);
+ std::string name;
+ if (const_no->package() == NULL)
+ name = gogo->pkgpath();
+ else
+ name = const_no->package()->pkgpath();
+ name.push_back('.');
+ name.append(Gogo::unpack_hidden_name(const_no->name()));
const_decl =
gogo->backend()->named_constant_expression(btype, name,
const_decl, loc);
@@ -8637,54 +8666,6 @@ Named_object::get_backend_variable(Gogo* gogo, Named_object* function)
go_unreachable();
}
-// Return the external identifier for this object.
-
-std::string
-Named_object::get_id(Gogo* gogo)
-{
- go_assert(!this->is_variable()
- && !this->is_result_variable()
- && !this->is_type());
- std::string decl_name;
- if (this->is_function_declaration()
- && !this->func_declaration_value()->asm_name().empty())
- decl_name = this->func_declaration_value()->asm_name();
- else
- {
- std::string package_name;
- if (this->package_ == NULL)
- package_name = gogo->package_name();
- else
- package_name = this->package_->package_name();
-
- // Note that this will be misleading if this is an unexported
- // method generated for an embedded imported type. In that case
- // the unexported method should have the package name of the
- // package from which it is imported, but we are going to give
- // it our package name. Fixing this would require knowing the
- // package name, but we only know the package path. It might be
- // better to use package paths here anyhow. This doesn't affect
- // the assembler code, because we always set that name in
- // Function::get_or_make_decl anyhow. FIXME.
-
- decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
-
- Function_type* fntype;
- if (this->is_function())
- fntype = this->func_value()->type();
- else if (this->is_function_declaration())
- fntype = this->func_declaration_value()->type();
- else
- fntype = NULL;
- if (fntype != NULL && fntype->is_method())
- {
- decl_name.push_back('.');
- decl_name.append(fntype->receiver()->type()->mangled_name(gogo));
- }
- }
- return decl_name;
-}
-
void
debug_go_named_object(Named_object* no)
{
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 45be173..bdb3166 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -57,6 +57,116 @@ class Node;
// This file declares the basic classes used to hold the internal
// representation of Go which is built by the parser.
+// The name of some backend object. Backend objects have a
+// user-visible name and an assembler name. The user visible name
+// might include arbitrary Unicode characters. The assembler name
+// will not.
+
+class Backend_name
+{
+ public:
+ Backend_name()
+ : prefix_(NULL), components_(), count_(0), suffix_(),
+ is_asm_name_(false), is_non_identifier_(false)
+ {}
+
+ // Set the prefix. Prefixes are always constant strings.
+ void
+ set_prefix(const char* p)
+ {
+ go_assert(this->prefix_ == NULL && !this->is_asm_name_);
+ this->prefix_ = p;
+ }
+
+ // Set the suffix.
+ void
+ set_suffix(const std::string& s)
+ {
+ go_assert(this->suffix_.empty() && !this->is_asm_name_);
+ this->suffix_ = s;
+ }
+
+ // Append to the suffix.
+ void
+ append_suffix(const std::string& s)
+ {
+ if (this->is_asm_name_)
+ this->components_[0].append(s);
+ else
+ this->suffix_.append(s);
+ }
+
+ // Add a component.
+ void
+ add(const std::string& c)
+ {
+ go_assert(this->count_ < Backend_name::max_components
+ && !this->is_asm_name_);
+ this->components_[this->count_] = c;
+ ++this->count_;
+ }
+
+ // Set an assembler name specified by the user. This overrides both
+ // the user-visible name and the assembler name. No further
+ // encoding is applied.
+ void
+ set_asm_name(const std::string& n)
+ {
+ go_assert(this->prefix_ == NULL
+ && this->count_ == 0
+ && this->suffix_.empty()
+ && !this->is_asm_name_);
+ this->components_[0] = n;
+ this->is_asm_name_ = true;
+ }
+
+ // Whether some component includes some characters that can't appear
+ // in an identifier.
+ bool
+ is_non_identifier() const
+ { return this->is_non_identifier_; }
+
+ // Record that some component includes some character that can't
+ // appear in an identifier.
+ void
+ set_is_non_identifier()
+ { this->is_non_identifier_ = true; }
+
+ // Get the user visible name.
+ std::string
+ name() const;
+
+ // Get the assembler name. This may be the same as the user visible
+ // name.
+ std::string
+ asm_name() const;
+
+ // Get an optional assembler name: if it would be the same as the
+ // user visible name, this returns the empty string.
+ std::string
+ optional_asm_name() const;
+
+ private:
+ // The maximum number of components.
+ static const int max_components = 4;
+
+ // An optional prefix that does not require encoding.
+ const char *prefix_;
+ // Up to four components. The name will include these components
+ // separated by dots. Each component will be underscore-encoded
+ // (see the long comment near the top of names.cc).
+ std::string components_[Backend_name::max_components];
+ // Number of components.
+ int count_;
+ // An optional suffix that does not require encoding.
+ std::string suffix_;
+ // True if components_[0] is an assembler name specified by the user.
+ bool is_asm_name_;
+ // True if some component includes some character that can't
+ // normally appear in an identifier.
+ bool is_non_identifier_;
+};
+
// An initialization function for an imported package. This is a
// magic function which initializes variables and runs the "init"
// function.
@@ -613,7 +723,7 @@ class Gogo
// is used when a type-specific hash function is needed when not at
// top level.
void
- queue_hash_function(Type* type, int64_t size, const std::string& hash_name,
+ queue_hash_function(Type* type, int64_t size, Backend_name*,
Function_type* hash_fntype);
// Queue up a type-specific equal function to be written out. This
@@ -621,8 +731,7 @@ class Gogo
// top level.
void
queue_equal_function(Type* type, Named_type* name, int64_t size,
- const std::string& equal_name,
- Function_type* equal_fntype);
+ Backend_name*, Function_type* equal_fntype);
// Write out queued specific type functions.
void
@@ -869,31 +978,32 @@ class Gogo
Expression*
allocate_memory(Type *type, Location);
- // Return the assembler name to use for an exported function, a
- // method, or a function/method declaration.
- std::string
- function_asm_name(const std::string& go_name, const Package*,
- const Type* receiver);
+ // Get the backend name to use for an exported function, a method,
+ // or a function/method declaration.
+ void
+ function_backend_name(const std::string& go_name, const Package*,
+ const Type* receiver, Backend_name*);
// Return the name to use for a function descriptor.
- std::string
- function_descriptor_name(Named_object*);
+ void
+ function_descriptor_backend_name(Named_object*, Backend_name*);
// Return the name to use for a generated stub method.
std::string
stub_method_name(const Package*, const std::string& method_name);
- // Return the name of the hash function for TYPE.
- std::string
- hash_function_name(const Type*);
+ // Get the backend name of the hash function for TYPE.
+ void
+ hash_function_name(const Type*, Backend_name*);
- // Return the name of the equal function for TYPE.
- std::string
- equal_function_name(const Type*, const Named_type*);
+ // Get the backend name of the equal function for TYPE.
+ void
+ equal_function_name(const Type*, const Named_type*, Backend_name*);
- // Return the assembler name to use for a global variable.
- std::string
- global_var_asm_name(const std::string& go_name, const Package*);
+ // Get the backend name to use for a global variable.
+ void
+ global_var_backend_name(const std::string& go_name, const Package*,
+ Backend_name*);
// Return a name to use for an error case. This should only be used
// after reporting an error, and is used to avoid useless knockon
@@ -961,13 +1071,14 @@ class Gogo
// Return the package path symbol from an init function name, which
// can be a real init function or a dummy one.
std::string
- pkgpath_from_init_fn_name(std::string);
+ pkgpath_symbol_from_init_fn_name(std::string);
- // Return the name for a type descriptor symbol.
- std::string
- type_descriptor_name(const Type*, Named_type*);
+ // Get the backend name for a type descriptor symbol.
+ void
+ type_descriptor_backend_name(const Type*, Named_type*, Backend_name*);
// Return the name of the type descriptor list symbol of a package.
+ // The argument is an encoded pkgpath, as with pkgpath_symbol.
std::string
type_descriptor_list_symbol(const std::string&);
@@ -987,11 +1098,11 @@ class Gogo
std::string
interface_method_table_name(Interface_type*, Type*, bool is_pointer);
- // Return whether NAME is a special name that can not be passed to
- // unpack_hidden_name. This is needed because various special names
- // use "..SUFFIX", but unpack_hidden_name just looks for '.'.
- static bool
- is_special_name(const std::string& name);
+ // If NAME is a special name used as a Go identifier, return the
+ // position within the string where the special part of the name
+ // occurs.
+ static size_t
+ special_name_pos(const std::string& name);
private:
// During parsing, we keep a stack of functions. Each function on
@@ -1056,6 +1167,9 @@ class Gogo
Named_object*
write_barrier_variable();
+ static bool
+ is_digits(const std::string&);
+
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
@@ -1079,15 +1193,15 @@ class Gogo
Named_type* name;
int64_t size;
Specific_type_function_kind kind;
- std::string fnname;
+ Backend_name bname;
Function_type* fntype;
Specific_type_function(Type* atype, Named_type* aname, int64_t asize,
Specific_type_function_kind akind,
- const std::string& afnname,
+ Backend_name* abname,
Function_type* afntype)
: type(atype), name(aname), size(asize), kind(akind),
- fnname(afnname), fntype(afntype)
+ bname(*abname), fntype(afntype)
{ }
};
@@ -1631,6 +1745,10 @@ class Function
Bstatement*
return_value(Gogo*, Named_object*, Location) const;
+ // Get the backend name of this function.
+ void
+ backend_name(Gogo*, Named_object*, Backend_name*);
+
// Get an expression for the variable holding the defer stack.
Expression*
defer_stack(Location);
@@ -1872,6 +1990,10 @@ class Function_declaration
void
build_backend_descriptor(Gogo*);
+ // Get the backend name of this function declaration.
+ void
+ backend_name(Gogo*, Named_object*, Backend_name*);
+
// Export a function declaration.
void
export_func(Export* exp, const Named_object* no) const
@@ -1991,6 +2113,20 @@ class Variable
is_varargs_parameter() const
{ return this->is_varargs_parameter_; }
+ // Return whether this is a global sink variable, created only to
+ // run an initializer.
+ bool
+ is_global_sink() const
+ { return this->is_global_sink_; }
+
+ // Record that this is a global sink variable.
+ void
+ set_is_global_sink()
+ {
+ go_assert(this->is_global_);
+ this->is_global_sink_ = true;
+ }
+
// Whether this variable's address is taken.
bool
is_address_taken() const
@@ -2218,6 +2354,9 @@ class Variable
bool is_receiver_ : 1;
// Whether this is the varargs parameter of a function.
bool is_varargs_parameter_ : 1;
+ // Whether this is a global sink variable created to run an
+ // initializer.
+ bool is_global_sink_ : 1;
// Whether this variable is ever referenced.
bool is_used_ : 1;
// Whether something takes the address of this variable. For a
@@ -2863,10 +3002,6 @@ class Named_object
Bvariable*
get_backend_variable(Gogo*, Named_object* function);
- // Return the external identifier for this object.
- std::string
- get_id(Gogo*);
-
// Get the backend representation of this object.
void
get_backend(Gogo*, std::vector<Bexpression*>&, std::vector<Btype*>&,
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index c6c1178..f671416 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -1049,6 +1049,13 @@ Import::read_named_type(int index)
this->require_c_string(" ");
}
+ bool in_heap = true;
+ if (this->match_c_string("notinheap"))
+ {
+ this->require_c_string("notinheap ");
+ in_heap = false;
+ }
+
bool is_alias = false;
if (this->match_c_string("= "))
{
@@ -1102,7 +1109,14 @@ Import::read_named_type(int index)
// declaration of a type defined in some other file.
Type* type;
if (this->match_c_string(">") || this->match_c_string("\n"))
- type = this->types_[index];
+ {
+ type = this->types_[index];
+ if (!in_heap)
+ go_error_at(this->location_,
+ ("import error at %d for type index %d: "
+ "forward declaration marked notinheap"),
+ this->pos(), index);
+ }
else
{
if (no->is_type_declaration())
@@ -1117,6 +1131,8 @@ Import::read_named_type(int index)
// This type has not yet been imported.
ntype->clear_is_visible();
+ if (!in_heap)
+ ntype->set_not_in_heap();
if (is_alias)
ntype->set_is_alias();
diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc
index 156a90c..0baf4e4 100644
--- a/gcc/go/gofrontend/lex.cc
+++ b/gcc/go/gofrontend/lex.cc
@@ -743,6 +743,13 @@ Lex::next_token()
if (Lex::is_unicode_letter(ci))
return this->gather_identifier();
+ if (!issued_error && Lex::is_unicode_digit(ci))
+ {
+ go_error_at(this->location(),
+ "identifier cannot begin with digit");
+ issued_error = true;
+ }
+
if (!issued_error)
go_error_at(this->location(),
"invalid character 0x%x in input file",
@@ -1309,9 +1316,13 @@ Lex::gather_number()
}
}
+ mpfr_clear_overflow();
mpfr_t val;
int r = mpfr_init_set_str(val, num.c_str(), base, MPFR_RNDN);
go_assert(r == 0);
+ if (mpfr_overflow_p())
+ go_error_at(this->location(),
+ "floating-point exponent too large to represent");
bool is_imaginary = *p == 'i';
if (is_imaginary)
diff --git a/gcc/go/gofrontend/names.cc b/gcc/go/gofrontend/names.cc
index 1f0a545..f85d84c 100644
--- a/gcc/go/gofrontend/names.cc
+++ b/gcc/go/gofrontend/names.cc
@@ -15,53 +15,68 @@
// assembly code. This is not used for names that appear only in the
// debug info.
-// Our external names contain only ASCII alphanumeric characters,
+// Our external names may contain only ASCII alphanumeric characters,
// underscore, and dot. (According to the GCC sources, dot is not
// permitted in assembler symbols on VxWorks and MMIX. We will not
-// support those systems.) Go names can not contain dot, so we rely
-// on using dot to encode Unicode characters, and to separate Go
-// symbols by package, and so forth. We assume that none of the
-// non-Go symbols in the final link will contain a dot, so we don't
-// worry about conflicts.
+// support those systems.) Go identifiers cannot contain dot, but Go
+// package paths can. Both Go identifiers and package paths can, of
+// course, contain all sorts of Unicode characters.
+//
+// The gc compiler uses names like "pkg.F", and it seems convenient to
+// emulate that. Therefore, we will use dot to separate different
+// components of names.
+//
+// Since package paths can contain dot, to avoid ambiguity we must
+// encode package paths such that they do not contain any dot. The
+// natural way to do this is to encode forbidden characters, including
+// dot, using a notation based on underscore. We will, of course,
+// have to encode underscore itself.
+//
+// Since we will be using an underscore encoding for the package path,
+// it seems reasonable to use the same encoding for Go identifiers.
+// This has the disadvantage that encoded Go identifiers will appear
+// to be valid Go identifiers with funny spellings, but it seems like
+// the best available approach.
+//
+// Therefore, in the following discussion we may assume that none of
+// the names under discussion contain a dot. All of the names we
+// generate for Go identifiers (that don't use //export or
+// //go:linkname) will contain at least one dot, as discussed below.
+// We assume that none of the non-Go symbols in the final link will
+// contain a dot, so we don't worry about conflicts.
//
// We first describe the basic symbol names, used to represent Go
-// functions and variables. These never start with a dot, never end
-// with a dot, never contain two consecutive dots, and never contain a
-// dot followed by a digit.
+// functions and variables.
//
// The external name for a normal Go symbol NAME, a function or
// variable, is simply "PKGPATH.NAME". Note that NAME is not the
// packed form used for the "hidden" name internally in the compiler;
-// it is the name that appears in the source code. PKGPATH is the
-// -fgo-pkgpath option as adjusted by Gogo::pkgpath_for_symbol. Note
-// that PKGPATH can not contain a dot and neither can NAME. Also,
-// NAME may not begin with a digit. NAME may require further encoding
-// for non-ASCII characters as described below, but until that
-// encoding these symbols contain exactly one dot, and they do not
-// start with a dot.
+// it is the name that appears in the source code. Both PKGPATH and
+// NAME will be encoded as described below. The encoding process
+// ensures that neither encoded string can contain a dot, and neither
+// will start with a digit (NAME is a Go identifier that can't contain
+// a dot or start with a digit anyhow). The encoding process means
+// that these external names contain exactly one dot and do not start
+// with a dot.
//
// The external name for a method NAME for a named type TYPE is
-// "PKGPATH.TYPE.NAME". Unlike the gc compiler, the external name
-// does not indicate whether this is a pointer method or a value
-// method; a named type can not have both a pointer and value method
-// with the same name, so there is no ambiguity. PKGPATH is the
-// package path of the package in which TYPE is defined. Here none of
-// PKGPATH, TYPE, or NAME can be empty or contain a dot, and neither
-// TYPE nor NAME may begin with a digit. Before encoding these names
-// contain exactly two dots, not consecutive, and they do not start
-// with a dot.
+// "PKGPATH.TYPE.NAME". Both NAME and TYPE are simple Go identifiers.
+// Unlike the gc compiler, the external name does not indicate whether
+// this is a pointer method or a value method; a named type can not
+// have both a pointer and value method with the same name, so there
+// is no ambiguity. PKGPATH is the package path of the package in
+// which TYPE is defined. PKGPATH, TYPE, and NAME are encoded, and
+// cannot be empty or contain a dot or start with a digit. These
+// external names contain exactly two dots, not consecutive, and they
+// do not start with a dot.
//
// It's uncommon, but the use of type literals with embedded fields
// can cause us to have methods on unnamed types. The external names
-// for these are also PKGPATH.TYPE.NAME, where TYPE is an
+// for these are also PKGPATH.TYPELIT.NAME, where TYPELIT is an
// approximately readable version of the type literal, described
-// below. As the type literal encoding always contains multiple dots,
-// these names always contain more than two dots. Although the type
-// literal encoding contains dots, neither PKGPATH nor NAME can
-// contain a dot, and neither TYPE nor NAME can begin with a digit.
-// The effect is that PKGPATH is always the portion of the name before
-// the first dot and NAME is always the portion after the last dot.
-// There is no ambiguity as long as encoded type literals are
+// below. A TYPELIT will always contain characters that cannot appear
+// in a Go identifier, so TYPELIT can never be confused with a TYPE
+// name. There is no ambiguity as long as encoded type literals are
// unambiguous.
//
// Also uncommon is an external name that must refer to a named type
@@ -91,46 +106,51 @@
// the function with an added suffix "..f".
//
// A thunk for a go or defer statement is treated as a function whose
-// name is ".thunkNN" where NN is a sequence of digits (these
-// functions are never globally visible). Thus the final name of a
-// thunk will be PKGPATH..thunkNN.
+// name is ".thunkNN", unencoded, where NN is a sequence of digits
+// (these functions are never globally visible). Thus the final name
+// of a thunk will be PKGPATH..thunkNN (PKGPATH is encoded).
//
-// An init function is treated as a function whose name is ".initNN"
-// where NN is a sequence of digits (these functions are never
-// globally visible). Thus the final name of an init function will be
-// PKGPATH..initNN.
+// An init function is treated as a function whose name is ".initNN",
+// unencoded, where NN is a sequence of digits (these functions are
+// never globally visible). Thus the final name of an init function
+// will be PKGPATH..initNN (PKGPATH is encoded).
//
// A nested function is given the name of outermost enclosing function
-// or method with an added suffix "..funcNN" where NN is a sequence of
-// digits. Note that the function descriptor of a nested function, if
-// needed, will end with "..funcNN..f".
+// or method with an added suffix "..funcNN", unencoded, where NN is a
+// sequence of digits. Note that the function descriptor of a nested
+// function, if needed, will end with "..funcNN..f".
//
// A recover thunk is the same as the name of the function with an
// added suffix "..r".
//
-// The name of a type descriptor for a named type is PKGPATH.TYPE..d.
+// The name of a type descriptor for a named type is
+// PKGPATH.TYPENAME..d (PKGPATH and TYPENAME are encoded).
//
-// The name of a type descriptor for an unnamed type is type..TYPE.
-// That is, the string "type.." followed by the type literal encoding.
+// The name of a type descriptor for a pointer to a named type is
+// PKGPATH.TYPENAME..p (PKGPATH and TYPENAME are encoded).
+//
+// The name of a type descriptor for an unnamed type is type..TYPELIT.
+// That is, the string "type.." followed by the encoded type literal.
// These names are common symbols, in the linker's sense of the word
// common: in the final executable there is only one instance of the
-// type descriptor for a given unnamed type. The type literal
-// encoding can never start with a digit or with 'u' or 'U'.
+// type descriptor for a given unnamed type.
//
-// The name of the GC symbol for a named type is PKGPATH.TYPE..g.
+// The name of the GC symbol for a named type is PKGPATH.TYPE..g
+// (PKGPATH and TYPE are encoded).
//
-// The name of the GC symbol for an unnamed type is typeg..TYPE.
+// The name of the GC symbol for an unnamed type is type..TYPELIT..g.
// These are common symbols.
//
// The name of a ptrmask symbol is gcbits..B32 where B32 is an
-// encoding of the ptrmask bits using only ASCII letters without 'u'
-// or 'U'. These are common symbols.
+// encoding of the ptrmask bits using only ASCII letters. These are
+// common symbols.
//
// An interface method table for assigning the non-interface type TYPE
// to the interface type ITYPE is named imt..ITYPE..TYPE. If ITYPE or
-// TYPE is a named type, they are written as PKGPATH.TYPE. Otherwise
-// they are written as a type literal. An interface method table for
-// a pointer method set uses pimt instead of imt.
+// TYPE is a named type, they are written as PKGPATH.TYPE (where both
+// PKGPATH and TYPE are encoded). Otherwise they are written as a
+// type literal. An interface method table for a pointer method set
+// uses pimt instead of imt.
//
// The names of composite literal initializers, including the GC root
// variable, are not referenced. They must not conflict with any C
@@ -147,7 +167,7 @@
// PKGPATH..import. If a package doesn't need an init function, it
// will have a dummy one, named ~PKGPATH.
//
-// In each pacakge there is a list of all the type descriptors defined
+// In each package there is a list of all the type descriptors defined
// in this package. The name of the list is PKGPATH..types.
//
// In the main package it gathers all the type descriptor lists in a
@@ -161,109 +181,123 @@
// The type literal encoding is not quite valid Go, as some aspects of
// compiler generated types can not be represented. For example,
// incomparable struct types have an extra field "{x}". Struct tags
-// are quoted inside curly braces, rather than introduce an encoding
-// for quotes. Struct tags can contain any character, so any single
-// byte Unicode character that is not alphanumeric or underscore is
-// replaced with .xNN where NN is the hex encoding.
+// can contain any character, which will be underscore encoded as
+// usual. In the unusual case of a curly brace or a backslash in a
+// struct tag, the brace or backslash will be backslash quoted, before
+// underscore encoding.
+//
+// Many of these names will be visible in the debugger. The debugger
+// will be given these names before applying any underscore encoding.
+// These user names do not have to be unique--they are only used by
+// the debugger, not the linker--so this is OK. However, there is an
+// exception: if the name would otherwise include characters that
+// can't normally appear in an identifier, then the user name will
+// also be underscore encoded. This avoids problems with
+// communicating the debug info to the assembler and with handling the
+// debug info in the debugger. A Go-aware debugger will need to know
+// whether to apply underscore decoding to a name before showing it to
+// the user. We indicate this by adding a prefix of "g.", and
+// assuming that cases of a package path of "g" are unusual. This
+// prefix will only appear in the user name, not the assembler name.
//
-// There is a simple encoding for glue characters in type literals:
-// .0 - ' '
-// .1 - '*'
-// .2 - ';'
-// .3 - ','
-// .4 - '{'
-// .5 - '}'
-// .6 - '['
-// .7 - ']'
-// .8 - '('
-// .9 - ')'
-// This is unambiguous as, although the type literal can contain a dot
-// as shown above, those dots are always followed by a name and names
-// can not begin with a digit. A dot is always followed by a name or
-// a digit, and a type literal can neither start nor end with a dot,
-// so this never introduces consecutive dots.
+// The underscore encoding is, naturally, an underscore followed by
+// other characters. As there are various characters that commonly
+// appear in type literals and in package paths, we have a set of
+// short encodings. Then we have general encodings for other
+// characters.
//
-// Struct tags can contain any character, so they need special
-// treatment. Alphanumerics, underscores, and Unicode characters that
-// require more than a single byte are left alone (Unicode characters
-// will be encoded later, as described below). Other single bytes
-// characters are replace with .xNN where NN is the hex encoding.
+// __ - '_'
+// _0 - '.'
+// _1 - '/'
+// _2 - '*'
+// _3 - ','
+// _4 - '{'
+// _5 - '}'
+// _6 - '['
+// _7 - ']'
+// _8 - '('
+// _9 - ')'
+// _a - '"'
+// _b - ' '
+// _c - ';'
//
-// Since Go identifiers can contain Unicode characters, we must encode
-// them into ASCII. We do this last, after the name is generated as
-// described above and after type literals are encoded. To make the
-// encoding unambiguous, we introduce it with two consecutive dots.
-// This is followed by the letter u and four hex digits or the letter
-// U and eight digits, just as in the language only using ..u and ..U
-// instead of \u and \U. The compiler also produces identifiers that
-// are qualified by package path, which means that there may also be ASCII
-// characters that are not assembler-friendly (ex: '=', '/'). The encoding
-// scheme translates such characters into the "..zNN" where NN is the
-// hex value for the character. Since before this encoding names can never
-// contain consecutive dots followed by 'z', 'u' or 'U', and after this
-// encoding "..z", "..u" and "..U" are followed by a known number of
-// characters, this is unambiguous.
+// Other non-alphanumeric ASCII characters are encoded as _xNN, where
+// NN is the hex value for the character. If an encoded name would
+// otherwise start with a digit, this encoding is also used for the
+// leading digit.
+//
+// Non-ASCII Unicode characters are encoded as _u and four hex digits
+// or _U and eight digits, just as in the language only using _u and
+// _U instead of \u and \U.
//
// Demangling these names is straightforward:
-// - replace ..zXX with an ASCII character
-// - replace ..uXXXX with a unicode character
-// - replace ..UXXXXXXXX with a unicode character
-// - replace .D, where D is a digit, with the character from the above
+// - replace _xXX with an ASCII character
+// - replace _uXXXX with a unicode character
+// - replace _UXXXXXXXX with a unicode character
+// - replace _C per the table above
// That will get you as close as possible to a readable name.
-// Return the assembler name to use for an exported function, a
-// method, or a function/method declaration. This is not called if
-// the function has been given an explicit name via a magic //extern
-// or //go:linkname comment. GO_NAME is the name that appears in the
-// Go code. PACKAGE is the package where the function is defined, and
-// is NULL for the package being compiled. For a method, RTYPE is
+// Set BNAME to the name to use for an exported function, a method, or
+// a function/method declaration. GO_NAME is the name that appears in
+// the Go code. PACKAGE is the package where the function is defined,
+// and is NULL for the package being compiled. For a method, RTYPE is
// the method's receiver type; for a function, RTYPE is NULL.
-std::string
-Gogo::function_asm_name(const std::string& go_name, const Package* package,
- const Type* rtype)
+void
+Gogo::function_backend_name(const std::string& go_name,
+ const Package* package, const Type* rtype,
+ Backend_name* bname)
{
- std::string ret;
if (rtype != NULL)
- ret = rtype->deref()->mangled_name(this);
+ rtype->deref()->backend_name(this, bname);
else if (package == NULL)
- ret = this->pkgpath();
+ bname->add(this->pkgpath());
else
- ret = package->pkgpath();
- ret.push_back('.');
- // Check for special names that will break if we use
- // Gogo::unpack_hidden_name.
- if (Gogo::is_special_name(go_name))
- ret.append(go_name);
+ bname->add(package->pkgpath());
+
+ size_t pos = Gogo::special_name_pos(go_name);
+ if (pos == std::string::npos)
+ bname->add(Gogo::unpack_hidden_name(go_name));
else
- ret.append(Gogo::unpack_hidden_name(go_name));
- return go_encode_id(ret);
+ {
+ if (pos > 0)
+ bname->add(go_name.substr(0, pos));
+ bname->set_suffix(go_name.substr(pos));
+ }
}
-// Return the name to use for a function descriptor. These symbols
-// are globally visible.
+// Set BNAME to the name to use for a function descriptor. These
+// symbols are globally visible.
-std::string
-Gogo::function_descriptor_name(Named_object* no)
+void
+Gogo::function_descriptor_backend_name(Named_object* no,
+ Backend_name* bname)
{
- if (no->is_function() && !no->func_value()->asm_name().empty())
- return no->func_value()->asm_name() + "..f";
- else if (no->is_function_declaration()
- && !no->func_declaration_value()->asm_name().empty())
- return no->func_declaration_value()->asm_name() + "..f";
- std::string ret = this->function_asm_name(no->name(), no->package(), NULL);
- ret.append("..f");
- return ret;
+ if (no->is_function())
+ no->func_value()->backend_name(this, no, bname);
+ else if (no->is_function_declaration())
+ no->func_declaration_value()->backend_name(this, no, bname);
+ else
+ go_unreachable();
+ bname->append_suffix("..f");
}
-// Return the name to use for a generated stub method. MNAME is the
-// method name. PACKAGE is the package where the type that needs this
-// stub method is defined. These functions are globally visible.
-// Note that this is the function name that corresponds to the name
-// used for the method in Go source code, if this stub method were
-// written in Go. The assembler name will be generated by
-// Gogo::function_asm_name, and because this is a method that name
-// will include the receiver type.
+// Return the name to use for a generated stub method. A stub method
+// is used as the method table entry for a promoted method of an
+// embedded type. MNAME is the method name. PACKAGE is the package
+// where the type that needs this stub method is defined. These
+// functions are globally visible.
+//
+// This returns a name that acts like a Go identifier, as though the
+// stub method were written in Go as an explicitly defined method that
+// simply calls the promoted method. The name we return here will
+// eventually be passed to function_backend_name, which will return a
+// name that includes the receiver type.
+//
+// We construct a unique method name and append "..stub".
+// function_backend_name will look for the "..stub" and turn that into
+// an unencoded suffix. The rest of the name will be encoded as
+// usual.
std::string
Gogo::stub_method_name(const Package* package, const std::string& mname)
@@ -279,56 +313,70 @@ Gogo::stub_method_name(const Package* package, const std::string& mname)
return Gogo::unpack_hidden_name(mname) + "..stub";
// We are creating a stub method for an unexported method of an
- // imported embedded type. We need to disambiguate the method name.
- std::string ret = mpkgpath;
+ // imported embedded type. A single type can have multiple promoted
+ // methods with the same unexported name, if it embeds types from
+ // different packages. We need to disambiguate the method name.
+ // This produces an unambiguous name because even though MPKGPATH
+ // can be anything, we know that MNAME does not contain a dot. The
+ // dot we return here, between MPKGPATH and MNAME, will wind up
+ // being underscore encoded.
+ std::string ret(mpkgpath);
ret.push_back('.');
ret.append(Gogo::unpack_hidden_name(mname));
ret.append("..stub");
return ret;
}
-// Return the name of the hash function for TYPE.
+// Set BNAME to the name of the hash function for TYPE.
-std::string
-Gogo::hash_function_name(const Type* type)
+void
+Gogo::hash_function_name(const Type* type, Backend_name* bname)
{
- std::string tname = type->mangled_name(this);
- return tname + "..hash";
+ if (type->named_type() != NULL)
+ type->backend_name(this, bname);
+ else
+ {
+ bname->add(this->pkgpath());
+ type->backend_name(this, bname);
+ }
+ bname->set_suffix("..hash");
}
-// Return the name of the equal function for TYPE. If NAME is not
-// NULL it is the name of the type.
+// Set BNAME to the name of the equal function for TYPE. If NAME is
+// not NULL it is the name of the type.
-std::string
-Gogo::equal_function_name(const Type* type, const Named_type* name)
+void
+Gogo::equal_function_name(const Type* type, const Named_type* name,
+ Backend_name* bname)
{
- const Type* rtype = type;
if (name != NULL)
- rtype = name;
- std::string tname = rtype->mangled_name(this);
- return tname + "..eq";
+ name->backend_name(this, bname);
+ else
+ {
+ bname->add(this->pkgpath());
+ type->backend_name(this, bname);
+ }
+ bname->set_suffix("..eq");
}
-// Return the assembler name to use for a global variable. GO_NAME is
-// the name that appears in the Go code. PACKAGE is the package where
-// the variable is defined, and is NULL for the package being
-// compiled.
+// Set BNAME to the name to use for a global variable. GO_NAME is the
+// name that appears in the Go code. PACKAGE is the package where the
+// variable is defined, and is NULL for the package being compiled.
-std::string
-Gogo::global_var_asm_name(const std::string& go_name, const Package* package)
+void
+Gogo::global_var_backend_name(const std::string& go_name,
+ const Package* package,
+ Backend_name* bname)
{
- std::string ret;
if (package == NULL)
- ret = this->pkgpath();
+ bname->add(this->pkgpath());
else
- ret = package->pkgpath();
- ret.append(1, '.');
- ret.append(Gogo::unpack_hidden_name(go_name));
- return go_encode_id(ret);
+ bname->add(package->pkgpath());
+ bname->add(Gogo::unpack_hidden_name(go_name));
}
// Return an erroneous name that indicates that an error has already
-// been reported.
+// been reported. This name will act like a Go identifier.
std::string
Gogo::erroneous_name()
@@ -349,7 +397,10 @@ Gogo::is_erroneous_name(const std::string& name)
return name.compare(0, 10, ".erroneous") == 0;
}
-// Return a name for a thunk object.
+// Return a name for a thunk object. This name will act like a Go
+// identifier. The name returned here will eventually be passed to
+// function_backend_name, which will pull off the ..thunk as an
+// unencoded suffix.
std::string
Gogo::thunk_name()
@@ -358,7 +409,12 @@ Gogo::thunk_name()
char thunk_name[50];
snprintf(thunk_name, sizeof thunk_name, "..thunk%d", thunk_count);
++thunk_count;
- std::string ret = this->pkgpath();
+ // We don't want to return a name that starts with a dot, as that
+ // will confuse Gogo::is_hidden_name. And we don't want to change
+ // ..thunk, which fits our general theme and is used by code like
+ // runtime.Callers. But the prefix doesn't matter, as the actual
+ // name will include the package path.
+ std::string ret = "go";
return ret + thunk_name;
}
@@ -368,13 +424,10 @@ bool
Gogo::is_thunk(const Named_object* no)
{
const std::string& name(no->name());
- size_t i = name.find("..thunk");
+ size_t i = name.rfind("..thunk");
if (i == std::string::npos)
return false;
- for (i += 7; i < name.size(); ++i)
- if (name[i] < '0' || name[i] > '9')
- return false;
- return true;
+ return Gogo::is_digits(name.substr(i + 7));
}
// Return the name to use for an init function. There can be multiple
@@ -387,11 +440,12 @@ Gogo::init_function_name()
char buf[30];
snprintf(buf, sizeof buf, "..init%d", init_count);
++init_count;
- std::string ret = this->pkgpath();
- return ret + buf;
+ return this->pkgpath() + buf;
}
-// Return the name to use for a nested function.
+// Return the name to use for a nested function. This name acts like
+// a Go identifier. This name will be rewritten by
+// Function::backend_name.
std::string
Gogo::nested_function_name(Named_object* enclosing)
@@ -420,7 +474,9 @@ Gogo::nested_function_name(Named_object* enclosing)
enclosing->func_value()->type()->receiver();
if (rcvr != NULL)
{
- prefix = rcvr->type()->mangled_name(this);
+ Backend_name bname;
+ rcvr->type()->backend_name(this, &bname);
+ prefix = bname.name();
prefix.push_back('.');
}
prefix.append(Gogo::unpack_hidden_name(enclosing->name()));
@@ -460,7 +516,8 @@ Gogo::redefined_function_name()
}
// Return the name to use for a recover thunk for the function NAME.
-// If the function is a method, RTYPE is the receiver type.
+// If the function is a method, RTYPE is the receiver type. This is a
+// name that acts like a Go identifier.
std::string
Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
@@ -468,10 +525,12 @@ Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
std::string ret;
if (rtype != NULL)
{
- ret = rtype->mangled_name(this);
+ Backend_name bname;
+ rtype->deref()->backend_name(this, &bname);
+ ret = bname.name();
ret.append(1, '.');
}
- if (Gogo::is_special_name(name))
+ if (Gogo::special_name_pos(name) != std::string::npos)
ret.append(name);
else
ret.append(Gogo::unpack_hidden_name(name));
@@ -504,8 +563,8 @@ Gogo::initializer_name()
return buf;
}
-// Return the name of the variable used to represent the zero value of
-// a map. This is a globally visible common symbol.
+// Return the assembler name of the variable used to represent the
+// zero value of a map. This is a globally visible common symbol.
std::string
Gogo::map_zero_value_name()
@@ -513,7 +572,9 @@ Gogo::map_zero_value_name()
return "go..zerovalue";
}
-// Return the name to use for the import control function.
+// Return the name to use for the import control function. This name
+// is handled specially by Function::backend_name. It is not encoded
+// further.
const std::string&
Gogo::get_init_fn_name()
@@ -550,7 +611,7 @@ Gogo::dummy_init_fn_name()
// can be a real init function or a dummy one.
std::string
-Gogo::pkgpath_from_init_fn_name(std::string name)
+Gogo::pkgpath_symbol_from_init_fn_name(std::string name)
{
go_assert(!name.empty());
if (name[0] == '~')
@@ -561,85 +622,71 @@ Gogo::pkgpath_from_init_fn_name(std::string name)
go_unreachable();
}
-// Return a mangled name for a type. These names appear in symbol
-// names in the assembler file for things like type descriptors and
-// methods.
+// Set BNAME to a name for a type to use in a symbol. Return a name
+// for a type to use in a symbol. These names appear in symbol names
+// in the assembler file for things like type descriptors and methods.
-std::string
-Type::mangled_name(Gogo* gogo) const
+void
+Type::backend_name(Gogo* gogo, Backend_name* bname) const
{
- std::string ret;
-
- // The do_mangled_name virtual function will set RET to the mangled
- // name before glue character mapping.
- this->do_mangled_name(gogo, &ret);
-
- // Type descriptor names and interface method table names use a ".."
- // before the mangled name of a type, so to avoid ambiguity the
- // mangled name must not start with 'u' or 'U' or a digit.
- go_assert((ret[0] < '0' || ret[0] > '9') && ret[0] != ' ');
- if (ret[0] == 'u' || ret[0] == 'U')
- ret = " " + ret;
-
- // Map glue characters as described above.
-
- // The mapping is only unambiguous if there is no .DIGIT in the
- // string, so check that.
- for (size_t i = ret.find('.');
- i != std::string::npos;
- i = ret.find('.', i + 1))
+ // Special case top level named types to get nicer name encodings
+ // for this common case.
+ const Named_type* nt = this->unalias()->named_type();
+ if (nt != NULL && !nt->is_builtin())
{
- if (i + 1 < ret.size())
+ unsigned int index;
+ if (nt->in_function(&index) == NULL)
{
- char c = ret[i + 1];
- go_assert(c < '0' || c > '9');
+ const Named_object* no = nt->named_object();
+ if (no->package() == NULL)
+ bname->add(gogo->pkgpath());
+ else
+ bname->add(no->package()->pkgpath());
+ bname->add(Gogo::unpack_hidden_name(no->name()));
+ return;
}
}
- // The order of these characters is the replacement code.
- const char * const replace = " *;,{}[]()";
+ std::string name;
+ bool is_non_identifier = false;
- const size_t rlen = strlen(replace);
- char buf[2];
- buf[0] = '.';
- for (size_t ri = 0; ri < rlen; ++ri)
- {
- buf[1] = '0' + ri;
- while (true)
- {
- size_t i = ret.find(replace[ri]);
- if (i == std::string::npos)
- break;
- ret.replace(i, 1, buf, 2);
- }
- }
+ // The do_symbol_name virtual function will set RET to the mangled
+ // name before encoding.
+ this->do_mangled_name(gogo, &name, &is_non_identifier);
- return ret;
+ bname->add(name);
+ if (is_non_identifier)
+ bname->set_is_non_identifier();
}
// The mangled name is implemented as a method on each instance of
// Type.
void
-Error_type::do_mangled_name(Gogo*, std::string* ret) const
+Error_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("{error}");
+ *is_non_identifier = true;
}
void
-Void_type::do_mangled_name(Gogo*, std::string* ret) const
+Void_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("{void}");
+ *is_non_identifier = true;
}
void
-Boolean_type::do_mangled_name(Gogo*, std::string* ret) const
+Boolean_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
{
ret->append("bool");
}
void
-Integer_type::do_mangled_name(Gogo*, std::string* ret) const
+Integer_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%s%si%d",
@@ -647,43 +694,53 @@ Integer_type::do_mangled_name(Gogo*, std::string* ret) const
this->is_unsigned_ ? "u" : "",
this->bits_);
ret->append(buf);
+ if (this->is_abstract_)
+ *is_non_identifier = true;
}
void
-Float_type::do_mangled_name(Gogo*, std::string* ret) const
+Float_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%sfloat%d",
this->is_abstract_ ? "{abstract}" : "",
this->bits_);
ret->append(buf);
+ if (this->is_abstract_)
+ *is_non_identifier = true;
}
void
-Complex_type::do_mangled_name(Gogo*, std::string* ret) const
+Complex_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%sc%d",
this->is_abstract_ ? "{abstract}" : "",
this->bits_);
ret->append(buf);
+ if (this->is_abstract_)
+ *is_non_identifier = true;
}
void
-String_type::do_mangled_name(Gogo*, std::string* ret) const
+String_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
{
ret->append("string");
}
void
-Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Function_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("func");
if (this->receiver_ != NULL)
{
ret->push_back('(');
- this->append_mangled_name(this->receiver_->type(), gogo, ret);
+ this->append_mangled_name(this->receiver_->type(), gogo, ret,
+ is_non_identifier);
ret->append(")");
}
@@ -701,13 +758,9 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
else
ret->push_back(',');
if (this->is_varargs_ && p + 1 == params->end())
- {
- // We can't use "..." here because the mangled name
- // might start with 'u' or 'U', which would be ambiguous
- // with the encoding of Unicode characters.
- ret->append(",,,");
- }
- this->append_mangled_name(p->type(), gogo, ret);
+ ret->append("...");
+ this->append_mangled_name(p->type(), gogo, ret,
+ is_non_identifier);
}
}
ret->push_back(')');
@@ -725,27 +778,34 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
first = false;
else
ret->append(",");
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
}
}
ret->push_back(')');
+
+ *is_non_identifier = true;
}
void
-Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->push_back('*');
- this->append_mangled_name(this->to_type_, gogo, ret);
+ this->append_mangled_name(this->to_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Nil_type::do_mangled_name(Gogo*, std::string* ret) const
+Nil_type::do_mangled_name(Gogo*, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("{nil}");
+ *is_non_identifier = true;
}
void
-Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Struct_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("struct{");
@@ -776,15 +836,16 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
if (p->is_anonymous()
&& p->type()->named_type() != NULL
&& p->type()->named_type()->is_alias())
- p->type()->named_type()->append_mangled_type_name(gogo, true, ret);
+ p->type()->named_type()->append_symbol_type_name(gogo, true, ret,
+ is_non_identifier);
else
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
if (p->has_tag())
{
// Use curly braces around a struct tag, since they are
- // unambiguous here and we have no encoding for
- // quotation marks.
+ // unambiguous here and struct tags rarely contain curly
+ // braces.
ret->push_back('{');
ret->append(go_mangle_struct_tag(p->tag()));
ret->push_back('}');
@@ -793,10 +854,13 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
}
ret->push_back('}');
+
+ *is_non_identifier = true;
}
void
-Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Array_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->push_back('[');
if (this->length_ != NULL)
@@ -821,32 +885,38 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
ret->append("x");
}
ret->push_back(']');
- this->append_mangled_name(this->element_type_, gogo, ret);
+ this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Map_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Map_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
ret->append("map[");
- this->append_mangled_name(this->key_type_, gogo, ret);
+ this->append_mangled_name(this->key_type_, gogo, ret, is_non_identifier);
ret->push_back(']');
- this->append_mangled_name(this->val_type_, gogo, ret);
+ this->append_mangled_name(this->val_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Channel_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
if (!this->may_send_)
- ret->append("{}");
+ ret->append("<-");
ret->append("chan");
if (!this->may_receive_)
- ret->append("{}");
+ ret->append("<-");
ret->push_back(' ');
- this->append_mangled_name(this->element_type_, gogo, ret);
+ this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
+ *is_non_identifier = true;
}
void
-Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Interface_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
go_assert(this->methods_are_finalized_);
@@ -872,25 +942,29 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
ret->push_back(' ');
}
- this->append_mangled_name(p->type(), gogo, ret);
+ this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
}
this->seen_ = false;
}
ret->push_back('}');
+
+ *is_non_identifier = true;
}
void
-Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Named_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool* is_non_identifier) const
{
- this->append_mangled_type_name(gogo, false, ret);
+ this->append_symbol_type_name(gogo, false, ret, is_non_identifier);
}
void
-Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret,
+ bool *is_non_identifier) const
{
if (this->is_defined())
- this->append_mangled_name(this->real_type(), gogo, ret);
+ this->append_mangled_name(this->real_type(), gogo, ret, is_non_identifier);
else
{
const Named_object* no = this->named_object();
@@ -903,13 +977,14 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
}
}
-// Append the mangled name for a named type to RET. For an alias we
+// Append the symbol name for a named type to RET. For an alias we
// normally use the real name, but if USE_ALIAS is true we use the
// alias name itself.
void
-Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
- std::string* ret) const
+Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
+ std::string* ret,
+ bool* is_non_identifier) const
{
if (this->is_error_)
return;
@@ -918,7 +993,7 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
if (this->seen_alias_)
return;
this->seen_alias_ = true;
- this->append_mangled_name(this->type_, gogo, ret);
+ this->append_mangled_name(this->type_, gogo, ret, is_non_identifier);
this->seen_alias_ = false;
return;
}
@@ -933,7 +1008,13 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
const Typed_identifier* rcvr =
this->in_function_->func_value()->type()->receiver();
if (rcvr != NULL)
- ret->append(rcvr->type()->deref()->mangled_name(gogo));
+ {
+ Backend_name bname;
+ rcvr->type()->deref()->backend_name(gogo, &bname);
+ ret->append(bname.name());
+ if (bname.is_non_identifier())
+ *is_non_identifier = true;
+ }
else if (this->in_function_->package() == NULL)
ret->append(gogo->pkgpath());
else
@@ -956,23 +1037,46 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
if (this->in_function_ != NULL && this->in_function_index_ > 0)
{
char buf[30];
- snprintf(buf, sizeof buf, "..i%u", this->in_function_index_);
+ snprintf(buf, sizeof buf, ".i%u", this->in_function_index_);
ret->append(buf);
}
}
-// Return the name for the type descriptor symbol for TYPE. This can
-// be a global, common, or local symbol, depending. NT is not NULL if
-// it is the name to use.
+// Given a name which may or may not have been hidden, append the
+// appropriate version of the name to the result string.
-std::string
-Gogo::type_descriptor_name(const Type* type, Named_type* nt)
+void
+Gogo::append_possibly_hidden_name(std::string *result, const std::string& name)
+{
+ if (!Gogo::is_hidden_name(name))
+ *result += name;
+ else
+ *result += name.substr(1);
+}
+
+// Set BNAME to the name for the type descriptor symbol for TYPE.
+// This can be a global, common, or local symbol, depending. NT is
+// not NULL if it is the name to use.
+
+void
+Gogo::type_descriptor_backend_name(const Type* type, Named_type* nt,
+ Backend_name* bname)
{
// The type descriptor symbol for the unsafe.Pointer type is defined
// in libgo/runtime/go-unsafe-pointer.c, so just use a reference to
// that symbol for all unsafe pointer types.
if (type->is_unsafe_pointer_type())
- return "unsafe.Pointer..d";
+ {
+ bname->set_asm_name("unsafe.Pointer..d");
+ return;
+ }
+
+ bool is_pointer = false;
+ if (nt == NULL && type->points_to() != NULL)
+ {
+ nt = type->points_to()->unalias()->named_type();
+ is_pointer = true;
+ }
if (nt == NULL)
{
@@ -981,63 +1085,28 @@ Gogo::type_descriptor_name(const Type* type, Named_type* nt)
// using a named type, like "int".
go_assert(!type->is_basic_type());
- return "type.." + type->mangled_name(this);
+ type->backend_name(this, bname);
+ bname->set_prefix("type..");
}
-
- std::string ret;
- Named_object* no = nt->named_object();
- unsigned int index;
- const Named_object* in_function = nt->in_function(&index);
- if (nt->is_builtin())
- go_assert(in_function == NULL);
else
{
- if (in_function != NULL)
- {
- const Typed_identifier* rcvr =
- in_function->func_value()->type()->receiver();
- if (rcvr != NULL)
- ret.append(rcvr->type()->deref()->mangled_name(this));
- else if (in_function->package() == NULL)
- ret.append(this->pkgpath());
- else
- ret.append(in_function->package()->pkgpath());
- ret.push_back('.');
- ret.append(Gogo::unpack_hidden_name(in_function->name()));
- ret.push_back('.');
- }
-
- if (no->package() == NULL)
- ret.append(this->pkgpath());
- else
- ret.append(no->package()->pkgpath());
- ret.push_back('.');
- }
-
- Gogo::append_possibly_hidden_name(&ret, no->name());
-
- if (in_function != NULL && index > 0)
- {
- char buf[30];
- snprintf(buf, sizeof buf, "..i%u", index);
- ret.append(buf);
+ nt->backend_name(this, bname);
+ bname->set_suffix(is_pointer ? "..p" : "..d");
}
-
- ret.append("..d");
-
- return ret;
}
// Return the name of the type descriptor list symbol of a package.
+// This is passed directly to the backend without further encoding.
std::string
-Gogo::type_descriptor_list_symbol(const std::string& pkgpath)
+Gogo::type_descriptor_list_symbol(const std::string& pkgpath_symbol)
{
- return pkgpath + "..types";
+ return pkgpath_symbol + "..types";
}
// Return the name of the list of all type descriptor lists. This is
-// only used in the main package.
+// only used in the main package. This is passed directly to the
+// backend without further encoding.
std::string
Gogo::typelists_symbol()
@@ -1045,24 +1114,30 @@ Gogo::typelists_symbol()
return "go..typelists";
}
-// Return the name for the GC symbol for a type. This is used to
-// initialize the gcdata field of a type descriptor. This is a local
-// name never referenced outside of this assembly file. (Note that
-// some type descriptors will initialize the gcdata field with a name
-// generated by ptrmask_symbol_name rather than this method.)
+// Return the assembler name for the GC symbol for a type. This is
+// used to initialize the gcdata field of a type descriptor. This is
+// a local name never referenced outside of this assembly file. (Note
+// that some type descriptors will initialize the gcdata field with a
+// name generated by ptrmask_symbol_name rather than this method.)
+// This is passed directly to the backend without further encoding.
std::string
Gogo::gc_symbol_name(Type* type)
{
- return this->type_descriptor_name(type, type->named_type()) + "..g";
+ Backend_name bname;
+ this->type_descriptor_backend_name(type, type->named_type(), &bname);
+ bname.append_suffix("..g");
+ return bname.asm_name();
}
-// Return the name for a ptrmask variable. PTRMASK_SYM_NAME is a
-// base32 string encoding the ptrmask (as returned by Ptrmask::symname
-// in types.cc). This name is used to intialize the gcdata field of a
-// type descriptor. These names are globally visible. (Note that
-// some type descriptors will initialize the gcdata field with a name
-// generated by gc_symbol_name rather than this method.)
+// Return the assembler name for a ptrmask variable. PTRMASK_SYM_NAME
+// is a base32 string encoding the ptrmask (as returned by
+// Ptrmask::symname in types.cc). This name is used to intialize the
+// gcdata field of a type descriptor. These names are globally
+// visible. (Note that some type descriptors will initialize the
+// gcdata field with a name generated by gc_symbol_name rather than
+// this method.) This is passed directly to the backend without
+// further encoding.
std::string
Gogo::ptrmask_symbol_name(const std::string& ptrmask_sym_name)
@@ -1070,34 +1145,134 @@ Gogo::ptrmask_symbol_name(const std::string& ptrmask_sym_name)
return "gcbits.." + ptrmask_sym_name;
}
-// Return the name to use for an interface method table used for the
-// ordinary type TYPE converted to the interface type ITYPE.
+// Return the assembler name to use for an interface method table used
+// for the ordinary type TYPE converted to the interface type ITYPE.
// IS_POINTER is true if this is for the method set for a pointer
-// receiver.
+// receiver. This is passed directly to the backend without further
+// encoding.
std::string
Gogo::interface_method_table_name(Interface_type* itype, Type* type,
bool is_pointer)
{
+ Backend_name iname;
+ itype->backend_name(this, &iname);
+ Backend_name tname;
+ type->backend_name(this, &tname);
return ((is_pointer ? "pimt.." : "imt..")
- + itype->mangled_name(this)
+ + iname.asm_name()
+ ".."
- + type->mangled_name(this));
+ + tname.asm_name());
+}
+
+// If NAME is a special name with a ".." suffix, return the position
+// of that suffix. This is needed because various special names use
+// "..SUFFIX", but unpack_hidden_name just looks for '.', and because
+// we don't want to encode the suffix.
+
+size_t
+Gogo::special_name_pos(const std::string& name)
+{
+ size_t pos = name.rfind("..");
+ if (pos == std::string::npos)
+ return pos;
+ std::string suffix(name.substr(pos));
+ if (suffix == "..hash"
+ || suffix == "..eq"
+ || suffix == "..stub"
+ || suffix == "..d"
+ || suffix == "..f"
+ || suffix == "..r"
+ || suffix == "..import")
+ return pos;
+ if ((suffix.compare(2, 4, "func") == 0
+ || suffix.compare(2, 4, "init") == 0)
+ && Gogo::is_digits(suffix.substr(6)))
+ return pos;
+ if (suffix.compare(2, 5, "thunk") == 0
+ && Gogo::is_digits(suffix.substr(7)))
+ return pos;
+ return std::string::npos;
}
-// Return whether NAME is a special name that can not be passed to
-// unpack_hidden_name. This is needed because various special names
-// use "..SUFFIX", but unpack_hidden_name just looks for '.'.
+// Return whether the string is non-empty and contains only digits.
bool
-Gogo::is_special_name(const std::string& name)
+Gogo::is_digits(const std::string& s)
+{
+ if (s.empty())
+ return false;
+ for (size_t i = 0; i < s.size(); ++i)
+ if (s[i] < '0' || s[i] > '9')
+ return false;
+ return true;
+}
+
+// Class Backend_name.
+
+// Get the user visible name.
+
+std::string
+Backend_name::name() const
+{
+ if (this->is_asm_name_)
+ return this->components_[0];
+
+ // If there is some character in the name that can't appear in an
+ // identifier, use the assembler name as the user name. This avoids
+ // possible problems in the assembler or debugger. The usual
+ // demangling scheme will still work. We use a prefix of "g." to
+ // tell the debugger about this.
+ if (this->is_non_identifier_)
+ return "g." + this->asm_name();
+
+ std::string ret;
+ if (this->prefix_ != NULL)
+ ret.append(this->prefix_);
+ for (int i = 0; i < this->count_; i++)
+ {
+ if (i > 0)
+ ret.push_back('.');
+ ret.append(this->components_[i]);
+ }
+ if (!this->suffix_.empty())
+ ret.append(this->suffix_);
+ return ret;
+}
+
+// Get the assembler name.
+
+std::string
+Backend_name::asm_name() const
+{
+ if (this->is_asm_name_)
+ return this->components_[0];
+ std::string ret;
+ if (this->prefix_ != NULL)
+ ret.append(this->prefix_);
+ for (int i = 0; i < this->count_; i++)
+ {
+ if (i > 0)
+ ret.push_back('.');
+ ret.append(go_encode_id(this->components_[i]));
+ }
+ if (!this->suffix_.empty())
+ ret.append(this->suffix_);
+ return ret;
+}
+
+// Get the assembler name, or the empty string if it is the same as
+// the user visible name.
+
+std::string
+Backend_name::optional_asm_name() const
{
- return (name.find("..hash") != std::string::npos
- || name.find("..eq") != std::string::npos
- || name.find("..stub") != std::string::npos
- || name.find("..func") != std::string::npos
- || name.find("..r") != std::string::npos
- || name.find("..init") != std::string::npos
- || name.find("..thunk") != std::string::npos
- || name.find("..import") != std::string::npos);
+ if (this->is_asm_name_)
+ return "";
+ if (this->is_non_identifier_)
+ return this->asm_name();
+ for (int i = 0; i < this->count_; i++)
+ if (go_id_needs_encoding(this->components_[i]))
+ return this->asm_name();
+ return "";
}
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index ef59415..1664fe3 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -995,7 +995,7 @@ Parse::parameter_list(bool* is_varargs)
}
if (mix_error)
{
- go_error_at(location, "invalid named/anonymous mix");
+ go_error_at(location, "mixed named and unnamed function parameters");
saw_error = true;
}
if (saw_error)
@@ -1442,6 +1442,7 @@ Parse::const_decl()
void
Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
{
+ Location loc = this->location();
Typed_identifier_list til;
this->identifier_list(&til);
@@ -1466,7 +1467,11 @@ Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
for (Expression_list::const_iterator p = (*last_expr_list)->begin();
p != (*last_expr_list)->end();
++p)
- expr_list->push_back((*p)->copy());
+ {
+ Expression* copy = (*p)->copy();
+ copy->set_location(loc);
+ expr_list->push_back(copy);
+ }
}
else
{
@@ -1567,7 +1572,6 @@ Parse::type_spec(void*, unsigned int pragmas)
go_error_at(this->location(),
"unexpected semicolon or newline in type declaration");
type = Type::make_error_type();
- this->advance_token();
}
if (type->is_error_type())
@@ -2071,6 +2075,7 @@ Parse::create_dummy_global(Type* type, Expression* init,
if (type == NULL && init == NULL)
type = Type::lookup_bool_type();
Variable* var = new Variable(type, init, true, false, false, location);
+ var->set_is_global_sink();
static int count;
char buf[30];
snprintf(buf, sizeof buf, "_.%d", count);
@@ -2165,8 +2170,12 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
id = this->gogo_->pack_hidden_name(id, is_id_exported);
ins = uniq_idents.insert(id);
if (!ins.second && !Gogo::is_sink_name(id))
- go_error_at(id_location, "multiple assignments to %s",
- Gogo::message_name(id).c_str());
+ {
+ // Use %s to print := to avoid -Wformat-diag warning.
+ go_error_at(id_location,
+ "%qs repeated on left side of %s",
+ Gogo::message_name(id).c_str(), ":=");
+ }
til.push_back(Typed_identifier(id, NULL, location));
}
else
@@ -2219,7 +2228,11 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
const Token* token = this->advance_token();
if (!dup_name.empty())
- go_error_at(dup_loc, "multiple assignments to %s", dup_name.c_str());
+ {
+ // Use %s to print := to avoid -Wformat-diag warning.
+ go_error_at(dup_loc, "%qs repeated on left side of %s",
+ dup_name.c_str(), ":=");
+ }
if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
{
@@ -4414,7 +4427,7 @@ Parse::if_stat()
{
Location semi_loc = this->location();
if (this->advance_token()->is_op(OPERATOR_LCURLY))
- go_error_at(semi_loc, "missing %<{%> after if clause");
+ go_error_at(semi_loc, "unexpected semicolon or newline, expecting %<{%> after if clause");
// Otherwise we will get an error when we call this->block
// below.
}
@@ -4478,7 +4491,7 @@ Parse::switch_stat(Label* label)
bool saw_simple_stat = false;
Expression* switch_val = NULL;
- bool saw_send_stmt;
+ bool saw_send_stmt = false;
Type_switch type_switch;
bool have_type_switch_block = false;
if (this->simple_stat_may_start_here())
@@ -4810,7 +4823,7 @@ Parse::type_switch_body(Label* label, const Type_switch& type_switch,
}
}
if (!used)
- go_error_at(type_switch.location, "%qs declared and not used",
+ go_error_at(type_switch.location, "%qs declared but not used",
Gogo::message_name(var_name).c_str());
}
return statement;
@@ -5313,7 +5326,7 @@ Parse::for_stat(Label* label)
{
// We might be looking at a Condition, an InitStat, or a
// RangeClause.
- bool saw_send_stmt;
+ bool saw_send_stmt = false;
cond = this->simple_stat(false, &saw_send_stmt, &range_clause, NULL);
if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
{
@@ -5351,7 +5364,7 @@ Parse::for_stat(Label* label)
{
Location semi_loc = this->location();
if (this->advance_token()->is_op(OPERATOR_LCURLY))
- go_error_at(semi_loc, "missing %<{%> after for clause");
+ go_error_at(semi_loc, "unexpected semicolon or newline, expecting %<{%> after for clause");
// Otherwise we will get an error when we call this->block
// below.
}
@@ -5422,7 +5435,7 @@ Parse::for_clause(Expression** cond, Block** post)
*cond = NULL;
else if (this->peek_token()->is_op(OPERATOR_LCURLY))
{
- go_error_at(this->location(), "missing %<{%> after for clause");
+ go_error_at(this->location(), "unexpected semicolon or newline, expecting %<{%> after for clause");
*cond = NULL;
*post = NULL;
return;
@@ -5780,7 +5793,7 @@ Parse::import_spec(void*, unsigned int pragmas)
if (!token->is_string())
{
- go_error_at(this->location(), "import statement not a string");
+ go_error_at(this->location(), "import path must be a string");
this->advance_token();
return;
}
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 0796cba..ec01be0 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -62,12 +62,6 @@ DEF_GO_RUNTIME(STRINGTOSLICERUNE, "runtime.stringtoslicerune",
P2(POINTER, STRING), R1(SLICE))
-// Complex division.
-DEF_GO_RUNTIME(COMPLEX64_DIV, "__go_complex64_div",
- P2(COMPLEX64, COMPLEX64), R1(COMPLEX64))
-DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
- P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
-
// Make a slice.
DEF_GO_RUNTIME(MAKESLICE, "runtime.makeslice", P3(TYPE, INT, INT),
R1(POINTER))
@@ -83,7 +77,7 @@ DEF_GO_RUNTIME(MAKEMAP64, "runtime.makemap64", P3(TYPE, INT64, POINTER),
R1(MAP))
// Make a map with no hint, or a small constant hint.
-DEF_GO_RUNTIME(MAKEMAP_SMALL, "runtime.makemap_small", P0(), R1(MAP))
+DEF_GO_RUNTIME(MAKEMAP_SMALL, "runtime.makemap__small", P0(), R1(MAP))
// Build a map from a composite literal.
DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
@@ -95,19 +89,19 @@ DEF_GO_RUNTIME(MAPACCESS1, "runtime.mapaccess1", P3(TYPE, MAP, POINTER),
R1(POINTER))
// Look up a uint32 key in a map.
-DEF_GO_RUNTIME(MAPACCESS1_FAST32, "runtime.mapaccess1_fast32",
+DEF_GO_RUNTIME(MAPACCESS1_FAST32, "runtime.mapaccess1__fast32",
P3(TYPE, MAP, UINT32), R1(POINTER))
// Look up a uint64 key in a map.
-DEF_GO_RUNTIME(MAPACCESS1_FAST64, "runtime.mapaccess1_fast64",
+DEF_GO_RUNTIME(MAPACCESS1_FAST64, "runtime.mapaccess1__fast64",
P3(TYPE, MAP, UINT64), R1(POINTER))
// Look up a string key in a map.
-DEF_GO_RUNTIME(MAPACCESS1_FASTSTR, "runtime.mapaccess1_faststr",
+DEF_GO_RUNTIME(MAPACCESS1_FASTSTR, "runtime.mapaccess1__faststr",
P3(TYPE, MAP, STRING), R1(POINTER))
// Look up a key in a map when the value is large.
-DEF_GO_RUNTIME(MAPACCESS1_FAT, "runtime.mapaccess1_fat",
+DEF_GO_RUNTIME(MAPACCESS1_FAT, "runtime.mapaccess1__fat",
P4(TYPE, MAP, POINTER, POINTER), R1(POINTER))
// Look up a key in a map returning the value and whether it is
@@ -117,22 +111,22 @@ DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2", P3(TYPE, MAP, POINTER),
// Look up a uint32 key in a map returning the value and whether
// it is present.
-DEF_GO_RUNTIME(MAPACCESS2_FAST32, "runtime.mapaccess2_fast32",
+DEF_GO_RUNTIME(MAPACCESS2_FAST32, "runtime.mapaccess2__fast32",
P3(TYPE, MAP, UINT32), R2(POINTER, BOOL))
// Look up a uint64 key in a map returning the value and whether
// it is present.
-DEF_GO_RUNTIME(MAPACCESS2_FAST64, "runtime.mapaccess2_fast64",
+DEF_GO_RUNTIME(MAPACCESS2_FAST64, "runtime.mapaccess2__fast64",
P3(TYPE, MAP, UINT64), R2(POINTER, BOOL))
// Look up a string key in a map returning the value and whether
// it is present.
-DEF_GO_RUNTIME(MAPACCESS2_FASTSTR, "runtime.mapaccess2_faststr",
+DEF_GO_RUNTIME(MAPACCESS2_FASTSTR, "runtime.mapaccess2__faststr",
P3(TYPE, MAP, STRING), R2(POINTER, BOOL))
// Look up a key in a map, returning the value and whether it is
// present, when the value is large.
-DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2_fat",
+DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2__fat",
P4(TYPE, MAP, POINTER, POINTER), R2(POINTER, BOOL))
// Assignment to a key in a map.
@@ -140,38 +134,38 @@ DEF_GO_RUNTIME(MAPASSIGN, "runtime.mapassign", P3(TYPE, MAP, POINTER),
R1(POINTER))
// Assignment to a uint32 key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST32, "runtime.mapassign_fast32",
+DEF_GO_RUNTIME(MAPASSIGN_FAST32, "runtime.mapassign__fast32",
P3(TYPE, MAP, UINT32), R1(POINTER))
// Assignment to a uint64 key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST64, "runtime.mapassign_fast64",
+DEF_GO_RUNTIME(MAPASSIGN_FAST64, "runtime.mapassign__fast64",
P3(TYPE, MAP, UINT64), R1(POINTER))
// Assignment to a 32-bit pointer key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST32PTR, "runtime.mapassign_fast32ptr",
+DEF_GO_RUNTIME(MAPASSIGN_FAST32PTR, "runtime.mapassign__fast32ptr",
P3(TYPE, MAP, POINTER), R1(POINTER))
// Assignment to a 64-bit pointer key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FAST64PTR, "runtime.mapassign_fast64ptr",
+DEF_GO_RUNTIME(MAPASSIGN_FAST64PTR, "runtime.mapassign__fast64ptr",
P3(TYPE, MAP, POINTER), R1(POINTER))
// Assignment to a string key in a map.
-DEF_GO_RUNTIME(MAPASSIGN_FASTSTR, "runtime.mapassign_faststr",
+DEF_GO_RUNTIME(MAPASSIGN_FASTSTR, "runtime.mapassign__faststr",
P3(TYPE, MAP, STRING), R1(POINTER))
// Delete a key from a map.
DEF_GO_RUNTIME(MAPDELETE, "runtime.mapdelete", P3(TYPE, MAP, POINTER), R0())
// Delete a uint32 key from a map.
-DEF_GO_RUNTIME(MAPDELETE_FAST32, "runtime.mapdelete_fast32",
+DEF_GO_RUNTIME(MAPDELETE_FAST32, "runtime.mapdelete__fast32",
P3(TYPE, MAP, UINT32), R0())
// Delete a uint64 key from a map.
-DEF_GO_RUNTIME(MAPDELETE_FAST64, "runtime.mapdelete_fast64",
+DEF_GO_RUNTIME(MAPDELETE_FAST64, "runtime.mapdelete__fast64",
P3(TYPE, MAP, UINT64), R0())
// Delete a string key from a map.
-DEF_GO_RUNTIME(MAPDELETE_FASTSTR, "runtime.mapdelete_faststr",
+DEF_GO_RUNTIME(MAPDELETE_FASTSTR, "runtime.mapdelete__faststr",
P3(TYPE, MAP, STRING), R0())
// Begin a range over a map.
@@ -201,8 +195,8 @@ DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P2(CHAN, POINTER), R1(BOOL))
// Run a select, returning the index of the selected clause and
// whether that channel received a value.
-DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P3(POINTER, POINTER, INT),
- R2(INT, BOOL))
+DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo",
+ P5(POINTER, POINTER, INT, INT, BOOL), R2(INT, BOOL))
// Non-blocking send a value on a channel, used for two-case select
// statement with a default case.
@@ -248,14 +242,6 @@ DEF_GO_RUNTIME(DEFERRETURN, "runtime.deferreturn", P1(BOOLPTR), R0())
DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0())
-// Copy.
-DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy",
- P5(POINTER, INT, POINTER, INT, UINTPTR), R1(INT))
-
-// Copy from string.
-DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy",
- P3(POINTER, INT, STRING), R1(INT))
-
// Copy of value containing pointers.
DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
P5(TYPE, POINTER, INT, POINTER, INT), R1(INT))
@@ -265,6 +251,11 @@ DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice",
P5(TYPE, POINTER, INT, INT, INT), R1(SLICE))
+// Check the length and cap passed to make, without making a slice.
+// This is used for apend(s, make([]T, len)...).
+DEF_GO_RUNTIME(CHECK_MAKE_SLICE, "runtime.checkMakeSlice", P3(TYPE, INT, INT),
+ R1(UINTPTR))
+
// Register roots (global variables) for the garbage collector.
DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "runtime.registerGCRoots", P1(POINTER), R0())
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index ad89807..da0e084 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -1985,18 +1985,42 @@ Tuple_type_guard_assignment_statement::lower_to_object_type(
NULL, loc);
b->add_statement(val_temp);
- // ok = CODE(type_descriptor, expr, &val_temp)
+ // var ok_temp bool
+ Temporary_statement* ok_temp = NULL;
+ if (!this->ok_->is_sink_expression())
+ {
+ ok_temp = Statement::make_temporary(this->ok_->type(),
+ NULL, loc);
+ b->add_statement(ok_temp);
+ }
+
+ // ok_temp = CODE(type_descriptor, expr, &val_temp)
Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
Expression* ref = Expression::make_temporary_reference(val_temp, loc);
Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
Expression* call = Runtime::make_call(code, loc, 3, p1, this->expr_, p3);
- Statement* s = Statement::make_assignment(this->ok_, call, loc);
+ Statement* s;
+ if (ok_temp == NULL)
+ s = Statement::make_statement(call, true);
+ else
+ {
+ Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc);
+ s = Statement::make_assignment(ok_ref, call, loc);
+ }
b->add_statement(s);
// val = val_temp
ref = Expression::make_temporary_reference(val_temp, loc);
s = Statement::make_assignment(this->val_, ref, loc);
b->add_statement(s);
+
+ // ok = ok_temp
+ if (ok_temp != NULL)
+ {
+ ref = Expression::make_temporary_reference(ok_temp, loc);
+ s = Statement::make_assignment(this->ok_, ref, loc);
+ b->add_statement(s);
+ }
}
// Dump the AST representation for a tuple type guard statement.
@@ -4514,7 +4538,7 @@ Switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
Type::make_nil_type(), NULL))
{
go_error_at(this->val_->location(),
- "cannot switch on value whose type that may not be compared");
+ "cannot switch on value whose type may not be compared");
return Statement::make_error_statement(loc);
}
@@ -5267,22 +5291,23 @@ Select_clauses::Select_clause::traverse(Traverse* traverse)
void
Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
Block* b, Temporary_statement* scases,
- size_t index, Temporary_statement* recvok)
+ int index, Temporary_statement* recvok)
{
Location loc = this->location_;
- Expression* scase = Expression::make_temporary_reference(scases, loc);
- Expression* index_expr = Expression::make_integer_ul(index, NULL, loc);
- scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
+ this->set_case_index(index);
if (this->is_default_)
{
go_assert(this->channel_ == NULL && this->val_ == NULL);
- this->lower_default(b, scase);
this->is_lowered_ = true;
return;
}
+ Expression* scase = Expression::make_temporary_reference(scases, loc);
+ Expression* index_expr = Expression::make_integer_sl(index, NULL, loc);
+ scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
+
// Evaluate the channel before the select statement.
Temporary_statement* channel_temp = Statement::make_temporary(NULL,
this->channel_,
@@ -5302,15 +5327,6 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
this->val_ = NULL;
}
-// Lower a default clause in a select statement.
-
-void
-Select_clauses::Select_clause::lower_default(Block* b, Expression* scase)
-{
- Location loc = this->location_;
- this->set_case(b, scase, Expression::make_nil(loc), NULL, caseDefault);
-}
-
// Lower a send clause in a select statement.
void
@@ -5342,7 +5358,7 @@ Select_clauses::Select_clause::lower_send(Block* b, Expression* scase,
Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
- this->set_case(b, scase, chanref, valaddr, caseSend);
+ this->set_case(b, scase, chanref, valaddr);
}
// Lower a receive clause in a select statement.
@@ -5368,7 +5384,7 @@ Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
- this->set_case(b, scase, chanref, valaddr, caseRecv);
+ this->set_case(b, scase, chanref, valaddr);
// If the block of statements is executed, arrange for the received
// value to move from VAL to the place where the statements expect
@@ -5423,8 +5439,7 @@ void
Select_clauses::Select_clause::set_case(Block* b,
Expression* scase,
Expression* chanref,
- Expression* elem,
- int kind)
+ Expression* elem)
{
Location loc = this->location_;
Struct_type* scase_type = scase->type()->struct_type();
@@ -5445,14 +5460,6 @@ Select_clauses::Select_clause::set_case(Block* b,
s = Statement::make_assignment(ref, elem, loc);
b->add_statement(s);
}
-
- field_index = 2;
- go_assert(scase_type->field(field_index)->is_field_name("kind"));
- Type* uint16_type = Type::lookup_integer_type("uint16");
- Expression* k = Expression::make_integer_ul(kind, uint16_type, loc);
- ref = Expression::make_field_reference(scase->copy(), field_index, loc);
- s = Statement::make_assignment(ref, k, loc);
- b->add_statement(s);
}
// Determine types.
@@ -5553,6 +5560,19 @@ Select_clauses::Select_clause::dump_clause(
// Class Select_clauses.
+// Whether there is a default case.
+
+bool
+Select_clauses::has_default() const
+{
+ for (Clauses::const_iterator p = this->clauses_.begin();
+ p != this->clauses_.end();
+ ++p)
+ if (p->is_default())
+ return true;
+ return false;
+}
+
// Traversal.
int
@@ -5570,17 +5590,60 @@ Select_clauses::traverse(Traverse* traverse)
// Lowering. Here we pull out the channel and the send values, to
// enforce the order of evaluation. We also add explicit send and
-// receive statements to the clauses.
+// receive statements to the clauses. This builds the entries in the
+// local array of scase values. It sets *P_SEND_COUNT and
+// *P_RECV_COUNT.
void
Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
- Temporary_statement* scases, Temporary_statement* recvok)
+ Temporary_statement* scases, Temporary_statement* recvok,
+ int *p_send_count, int *p_recv_count)
{
- size_t i = 0;
+ int send_count = 0;
+ int recv_count = 0;
+ bool has_default = false;
for (Clauses::iterator p = this->clauses_.begin();
p != this->clauses_.end();
- ++p, ++i)
- p->lower(gogo, function, b, scases, i, recvok);
+ ++p)
+ {
+ if (p->is_default())
+ has_default = true;
+ else if (p->is_send())
+ ++send_count;
+ else
+ ++recv_count;
+ }
+
+ *p_send_count = send_count;
+ *p_recv_count = recv_count;
+
+ int send_index = 0;
+ int recv_index = send_count;
+ for (Clauses::iterator p = this->clauses_.begin();
+ p != this->clauses_.end();
+ ++p)
+ {
+ int index;
+ if (p->is_default())
+ index = -1;
+ else if (p->is_send())
+ {
+ index = send_index;
+ ++send_index;
+ }
+ else
+ {
+ index = recv_index;
+ ++recv_index;
+ }
+
+ p->lower(gogo, function, b, scases, index, recvok);
+ }
+
+ go_assert(send_index == send_count);
+ go_assert(recv_index == send_count + recv_count);
+ go_assert(static_cast<size_t>(recv_index + (has_default ? 1 : 0))
+ == this->size());
}
// Determine types.
@@ -5640,7 +5703,8 @@ Select_clauses::get_backend(Translate_context* context,
p != this->clauses_.end();
++p, ++i)
{
- Expression* index_expr = Expression::make_integer_ul(i, int_type,
+ Expression* index_expr = Expression::make_integer_sl(p->case_index(),
+ int_type,
location);
cases[i].push_back(index_expr->get_backend(context));
@@ -5725,6 +5789,7 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
Block* b = new Block(enclosing, loc);
int ncases = this->clauses_->size();
+ bool has_default = this->clauses_->has_default();
// Zero-case select. Just block the execution.
if (ncases == 0)
@@ -5742,11 +5807,13 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
// Two-case select with one default case. It is a non-blocking
// send/receive.
- if (ncases == 2
- && (this->clauses_->at(0).is_default()
- || this->clauses_->at(1).is_default()))
+ if (ncases == 2 && has_default)
return this->lower_two_case(b);
+ // We don't allocate an entry in scases for the default case.
+ if (has_default)
+ --ncases;
+
Type* scase_type = Channel_type::select_case_type();
Expression* ncases_expr =
Expression::make_integer_ul(ncases, NULL,
@@ -5779,7 +5846,10 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
b->add_statement(recvok);
// Initialize the scases array.
- this->clauses_->lower(gogo, function, b, scases, recvok);
+ int send_count;
+ int recv_count;
+ this->clauses_->lower(gogo, function, b, scases, recvok, &send_count,
+ &recv_count);
// Build the call to selectgo. Later, in do_get_backend, we will
// build a switch on the result that branches to the various cases.
@@ -5793,11 +5863,18 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);
- Expression* count_expr = Expression::make_integer_ul(ncases, int_type, loc);
+ Expression* send_count_expr = Expression::make_integer_sl(send_count,
+ int_type,
+ loc);
+ Expression* recv_count_expr = Expression::make_integer_sl(recv_count,
+ int_type,
+ loc);
+ Expression* block_expr = Expression::make_boolean(!has_default, loc);
- Call_expression* call = Runtime::make_call(Runtime::SELECTGO, loc, 3,
+ Call_expression* call = Runtime::make_call(Runtime::SELECTGO, loc, 5,
scases_ref, order_ref,
- count_expr);
+ send_count_expr, recv_count_expr,
+ block_expr);
Expression* result = Expression::make_call_result(call, 0);
Expression* ref = Expression::make_temporary_reference(this->index_, loc);
@@ -6317,7 +6394,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
else if (range_type->is_string_type())
{
index_type = Type::lookup_integer_type("int");
- value_type = gogo->lookup_global("rune")->type_value();
+ value_type = Type::lookup_integer_type("rune");
}
else if (range_type->map_type() != NULL)
{
@@ -6788,7 +6865,7 @@ For_range_statement::lower_range_string(Gogo* gogo,
rune_type = value_temp->type();
else
{
- rune_type = gogo->lookup_global("rune")->type_value();
+ rune_type = Type::lookup_integer_type("rune");
value_temp = Statement::make_temporary(rune_type, NULL, loc);
init->add_statement(value_temp);
}
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index 47092b4..c08b493 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -1092,6 +1092,9 @@ class Select_clauses
size() const
{ return this->clauses_.size(); }
+ bool
+ has_default() const;
+
// Traverse the select clauses.
int
traverse(Traverse*);
@@ -1099,7 +1102,7 @@ class Select_clauses
// Lower statements.
void
lower(Gogo*, Named_object*, Block*, Temporary_statement*,
- Temporary_statement*);
+ Temporary_statement*, int* send_count, int* recv_count);
// Determine types.
void
@@ -1138,8 +1141,9 @@ class Select_clauses
Named_object* closedvar, bool is_default, Block* statements,
Location location)
: channel_(channel), val_(val), closed_(closed), var_(var),
- closedvar_(closedvar), statements_(statements), location_(location),
- is_send_(is_send), is_default_(is_default), is_lowered_(false)
+ closedvar_(closedvar), statements_(statements), case_index_(0),
+ location_(location), is_send_(is_send), is_default_(is_default),
+ is_lowered_(false), is_case_index_set_(false)
{ go_assert(is_default ? channel == NULL : channel != NULL); }
// Traverse the select clause.
@@ -1148,7 +1152,7 @@ class Select_clauses
// Lower statements.
void
- lower(Gogo*, Named_object*, Block*, Temporary_statement*, size_t,
+ lower(Gogo*, Named_object*, Block*, Temporary_statement*, int,
Temporary_statement*);
// Determine types.
@@ -1210,6 +1214,23 @@ class Select_clauses
location() const
{ return this->location_; }
+ // Return the case index for this clause.
+ int
+ case_index() const
+ {
+ go_assert(this->is_case_index_set_);
+ return this->case_index_;
+ }
+
+ // Set the case index.
+ void
+ set_case_index(int i)
+ {
+ go_assert(!this->is_case_index_set_);
+ this->case_index_ = i;
+ this->is_case_index_set_ = true;
+ }
+
// Whether this clause may fall through to the statement which
// follows the overall select statement.
bool
@@ -1224,17 +1245,6 @@ class Select_clauses
dump_clause(Ast_dump_context*) const;
private:
- // These values must match the values in libgo/go/runtime/select.go.
- enum
- {
- caseRecv = 1,
- caseSend = 2,
- caseDefault = 3,
- };
-
- void
- lower_default(Block*, Expression*);
-
void
lower_send(Block*, Expression*, Expression*);
@@ -1243,7 +1253,7 @@ class Select_clauses
Temporary_statement*);
void
- set_case(Block*, Expression*, Expression*, Expression*, int);
+ set_case(Block*, Expression*, Expression*, Expression*);
// The channel.
Expression* channel_;
@@ -1259,6 +1269,10 @@ class Select_clauses
Named_object* closedvar_;
// The statements to execute.
Block* statements_;
+ // The index of this clause in the switch statement. If
+ // runtime.selectgo returns this index, this clause has been
+ // chosen.
+ int case_index_;
// The location of this clause.
Location location_;
// Whether this is a send or a receive.
@@ -1267,6 +1281,8 @@ class Select_clauses
bool is_default_;
// Whether this has been lowered.
bool is_lowered_;
+ // Whether the case index has been set.
+ bool is_case_index_set_;
};
Select_clause&
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index eb9c766..7d4c47f 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -261,6 +261,15 @@ Type::is_error_type() const
}
}
+// Note that this type is an error. This is called by children when
+// they discover an error during the verify_types pass.
+
+void
+Type::set_is_error()
+{
+ this->classification_ = TYPE_ERROR;
+}
+
// If this is a pointer type, return the type to which it points.
// Otherwise, return NULL.
@@ -1342,19 +1351,21 @@ Type::make_type_descriptor_var(Gogo* gogo)
Type* td_type = Type::make_type_descriptor_type();
Btype* td_btype = td_type->get_backend(gogo);
- std::string name = gogo->type_descriptor_name(this, nt);
- std::string asm_name(go_selectively_encode_id(name));
+ Backend_name bname;
+ gogo->type_descriptor_backend_name(this, nt, &bname);
this->type_descriptor_var_ =
- gogo->backend()->immutable_struct_reference(name, asm_name,
- td_btype,
- bloc);
+ gogo->backend()->immutable_struct_reference(bname.name(),
+ bname.optional_asm_name(),
+ td_btype,
+ bloc);
if (phash != NULL)
*phash = this->type_descriptor_var_;
return;
}
- std::string var_name = gogo->type_descriptor_name(this, nt);
+ Backend_name bname;
+ gogo->type_descriptor_backend_name(this, nt, &bname);
// Build the contents of the type descriptor.
Expression* initializer = this->do_type_descriptor(gogo, NULL);
@@ -1366,11 +1377,11 @@ Type::make_type_descriptor_var(Gogo* gogo)
const Package* dummy;
if (this->type_descriptor_defined_elsewhere(nt, &dummy))
{
- std::string asm_name(go_selectively_encode_id(var_name));
this->type_descriptor_var_ =
- gogo->backend()->immutable_struct_reference(var_name, asm_name,
- initializer_btype,
- loc);
+ gogo->backend()->immutable_struct_reference(bname.name(),
+ bname.optional_asm_name(),
+ initializer_btype,
+ loc);
if (phash != NULL)
*phash = this->type_descriptor_var_;
return;
@@ -1399,10 +1410,10 @@ Type::make_type_descriptor_var(Gogo* gogo)
// ensure that type_descriptor_pointer will work if called while
// converting INITIALIZER.
- std::string asm_name(go_selectively_encode_id(var_name));
this->type_descriptor_var_ =
- gogo->backend()->immutable_struct(var_name, asm_name, false, is_common,
- initializer_btype, loc);
+ gogo->backend()->immutable_struct(bname.name(), bname.optional_asm_name(),
+ false, is_common, initializer_btype,
+ loc);
if (phash != NULL)
*phash = this->type_descriptor_var_;
@@ -1411,7 +1422,7 @@ Type::make_type_descriptor_var(Gogo* gogo)
Bexpression* binitializer = initializer->get_backend(&context);
gogo->backend()->immutable_struct_set_init(this->type_descriptor_var_,
- var_name, false, is_common,
+ bname.name(), false, is_common,
initializer_btype, loc,
binitializer);
@@ -1924,19 +1935,20 @@ Type::build_hash_function(Gogo* gogo, int64_t size, Function_type* hash_fntype)
return ins.first->second;
}
- std::string hash_name = gogo->hash_function_name(type);
+ Backend_name bname;
+ gogo->hash_function_name(type, &bname);
Location bloc = Linemap::predeclared_location();
- Named_object* hash_fn = gogo->declare_package_function(hash_name,
+ Named_object* hash_fn = gogo->declare_package_function(bname.name(),
hash_fntype, bloc);
ins.first->second = hash_fn;
if (gogo->in_global_scope())
- type->write_hash_function(gogo, size, hash_name, hash_fntype);
+ type->write_hash_function(gogo, size, &bname, hash_fntype);
else
- gogo->queue_hash_function(type, size, hash_name, hash_fntype);
+ gogo->queue_hash_function(type, size, &bname, hash_fntype);
return hash_fn;
}
@@ -1944,8 +1956,7 @@ Type::build_hash_function(Gogo* gogo, int64_t size, Function_type* hash_fntype)
// Write the hash function for a type that needs it written specially.
void
-Type::write_hash_function(Gogo* gogo, int64_t size,
- const std::string& hash_name,
+Type::write_hash_function(Gogo* gogo, int64_t size, const Backend_name* bname,
Function_type* hash_fntype)
{
Location bloc = Linemap::predeclared_location();
@@ -1958,8 +1969,9 @@ Type::write_hash_function(Gogo* gogo, int64_t size,
go_assert(this->is_comparable());
- Named_object* hash_fn = gogo->start_function(hash_name, hash_fntype, false,
- bloc);
+ Named_object* hash_fn = gogo->start_function(bname->name(), hash_fntype,
+ false, bloc);
+ hash_fn->func_value()->set_asm_name(bname->asm_name());
hash_fn->func_value()->set_is_type_specific_function();
gogo->start_block(bloc);
@@ -2245,7 +2257,8 @@ Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
return ins.first->second;
}
- std::string equal_name = gogo->equal_function_name(this, name);
+ Backend_name bname;
+ gogo->equal_function_name(this, name, &bname);
Location bloc = Linemap::predeclared_location();
@@ -2255,19 +2268,21 @@ Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
Named_object* equal_fn;
if (is_defined_elsewhere)
- equal_fn = Named_object::make_function_declaration(equal_name, package,
+ equal_fn = Named_object::make_function_declaration(bname.name(), package,
equal_fntype, bloc);
else
- equal_fn = gogo->declare_package_function(equal_name, equal_fntype, bloc);
+ equal_fn = gogo->declare_package_function(bname.name(), equal_fntype, bloc);
ins.first->second = equal_fn;
- if (!is_defined_elsewhere)
+ if (is_defined_elsewhere)
+ equal_fn->func_declaration_value()->set_asm_name(bname.asm_name());
+ else
{
if (gogo->in_global_scope())
- this->write_equal_function(gogo, name, size, equal_name, equal_fntype);
+ this->write_equal_function(gogo, name, size, &bname, equal_fntype);
else
- gogo->queue_equal_function(this, name, size, equal_name, equal_fntype);
+ gogo->queue_equal_function(this, name, size, &bname, equal_fntype);
}
return equal_fn;
@@ -2278,7 +2293,7 @@ Type::build_equal_function(Gogo* gogo, Named_type* name, int64_t size,
void
Type::write_equal_function(Gogo* gogo, Named_type* name, int64_t size,
- const std::string& equal_name,
+ const Backend_name* bname,
Function_type* equal_fntype)
{
Location bloc = Linemap::predeclared_location();
@@ -2291,8 +2306,9 @@ Type::write_equal_function(Gogo* gogo, Named_type* name, int64_t size,
go_assert(this->is_comparable());
- Named_object* equal_fn = gogo->start_function(equal_name, equal_fntype,
+ Named_object* equal_fn = gogo->start_function(bname->name(), equal_fntype,
false, bloc);
+ equal_fn->func_value()->set_asm_name(bname->asm_name());
equal_fn->func_value()->set_is_type_specific_function();
gogo->start_block(bloc);
@@ -2671,9 +2687,8 @@ Type::make_gc_symbol_var(Gogo* gogo)
const Package* dummy;
if (this->type_descriptor_defined_elsewhere(nt, &dummy))
{
- std::string asm_name(go_selectively_encode_id(sym_name));
this->gc_symbol_var_ =
- gogo->backend()->implicit_variable_reference(sym_name, asm_name,
+ gogo->backend()->implicit_variable_reference(sym_name, "",
sym_btype);
if (phash != NULL)
*phash = this->gc_symbol_var_;
@@ -2699,10 +2714,9 @@ Type::make_gc_symbol_var(Gogo* gogo)
// Since we are building the GC symbol in this package, we must create the
// variable before converting the initializer to its backend representation
// because the initializer may refer to the GC symbol for this type.
- std::string asm_name(go_selectively_encode_id(sym_name));
this->gc_symbol_var_ =
- gogo->backend()->implicit_variable(sym_name, asm_name,
- sym_btype, false, true, is_common, 0);
+ gogo->backend()->implicit_variable(sym_name, "", sym_btype, false, true,
+ is_common, 0);
if (phash != NULL)
*phash = this->gc_symbol_var_;
@@ -2750,7 +2764,7 @@ class Ptrmask
symname() const;
Expression*
- constructor(Gogo* gogo) const;
+ constructor() const;
private:
void
@@ -2876,14 +2890,17 @@ Ptrmask::set_from(Gogo* gogo, Type* type, int64_t ptrsize, int64_t offset)
}
}
-// Return a symbol name for this ptrmask. This is used to coalesce identical
-// ptrmasks, which are common. The symbol name must use only characters that are
-// valid in symbols. It's nice if it's short. For smaller ptrmasks, we convert
-// it to a string that uses only 32 characters, avoiding digits and u and U. For
-// longer pointer masks, apply the same process to the SHA1 digest of the bits,
-// so as to avoid pathologically long symbol names (see related Go issues #32083
-// and #11583 for more on this). To avoid collisions between the two encoding
-// schemes, use a prefix ("X") for the SHA form to disambiguate.
+// Return a symbol name for this ptrmask. This is used to coalesce
+// identical ptrmasks, which are common. The symbol name must use
+// only characters that are valid in symbols. It's nice if it's
+// short. For smaller ptrmasks, we convert it to a string that uses
+// only 32 characters. For longer pointer masks, apply the same
+// process to the SHA1 digest of the bits, so as to avoid
+// pathologically long symbol names (see related Go issues #32083 and
+// #11583 for more on this). To avoid collisions between the two
+// encoding schemes, use a prefix ("X") for the SHA form to
+// disambiguate.
+
std::string
Ptrmask::symname() const
{
@@ -2911,7 +2928,7 @@ Ptrmask::symname() const
bits = &shabits;
}
- const char chars[33] = "abcdefghijklmnopqrstvwxyzABCDEFG";
+ const char chars[33] = "abcdefghijklmnopqrstuvwxyzABCDEF";
go_assert(chars[32] == '\0');
std::string ret(prefix);
unsigned int b = 0;
@@ -2942,10 +2959,10 @@ Ptrmask::symname() const
// initialize the runtime ptrmask value.
Expression*
-Ptrmask::constructor(Gogo* gogo) const
+Ptrmask::constructor() const
{
Location bloc = Linemap::predeclared_location();
- Type* byte_type = gogo->lookup_global("byte")->type_value();
+ Type* byte_type = Type::lookup_integer_type("byte");
Expression* len = Expression::make_integer_ul(this->bits_.size(), NULL,
bloc);
Array_type* at = Type::make_array_type(byte_type, len);
@@ -2990,14 +3007,13 @@ Type::gc_ptrmask_var(Gogo* gogo, int64_t ptrsize, int64_t ptrdata)
return ins.first->second;
}
- Expression* val = ptrmask.constructor(gogo);
+ Expression* val = ptrmask.constructor();
Translate_context context(gogo, NULL, NULL, NULL);
context.set_is_const();
Bexpression* bval = val->get_backend(&context);
- std::string asm_name(go_selectively_encode_id(sym_name));
Btype *btype = val->type()->get_backend(gogo);
- Bvariable* ret = gogo->backend()->implicit_variable(sym_name, asm_name,
+ Bvariable* ret = gogo->backend()->implicit_variable(sym_name, "",
btype, false, true,
true, 0);
gogo->backend()->implicit_variable_set_init(ret, sym_name, btype, false,
@@ -3030,7 +3046,7 @@ class GCProg
end();
Expression*
- constructor(Gogo* gogo) const;
+ constructor() const;
private:
void
@@ -3341,7 +3357,7 @@ GCProg::end()
// Return an Expression for the bytes in a GC program.
Expression*
-GCProg::constructor(Gogo* gogo) const
+GCProg::constructor() const
{
Location bloc = Linemap::predeclared_location();
@@ -3351,7 +3367,7 @@ GCProg::constructor(Gogo* gogo) const
Type* uint32_type = Type::lookup_integer_type("uint32");
- Type* byte_type = gogo->lookup_global("byte")->type_value();
+ Type* byte_type = Type::lookup_integer_type("byte");
Expression* len = Expression::make_integer_ul(this->bytes_.size(), NULL,
bloc);
Array_type* at = Type::make_array_type(byte_type, len);
@@ -3398,7 +3414,7 @@ Type::gcprog_constructor(Gogo* gogo, int64_t ptrsize, int64_t ptrdata)
go_assert(offset >= ptrdata && offset <= type_size);
- return prog.constructor(gogo);
+ return prog.constructor();
}
// Return a composite literal for the uncommon type information for
@@ -4125,6 +4141,23 @@ Integer_type::create_abstract_character_type()
return abstract_type;
}
+// Create an alias to an integer type. This is used for byte and rune.
+
+Named_type*
+Integer_type::create_integer_type_alias(const char* name,
+ Named_type* real_type)
+{
+ std::string sname(name);
+ Named_object* no = Named_object::make_type(sname, NULL, real_type,
+ Linemap::predeclared_location());
+ Named_type* nt = no->type_value();
+ nt->set_is_alias();
+ std::pair<Named_integer_types::iterator, bool> ins =
+ Integer_type::named_integer_types.insert(std::make_pair(sname, nt));
+ go_assert(ins.second);
+ return nt;
+}
+
// Integer type compatibility.
bool
@@ -4202,6 +4235,14 @@ Type::make_abstract_character_type()
return Integer_type::create_abstract_character_type();
}
+// Make an integer type alias.
+
+Named_type*
+Type::make_integer_type_alias(const char* name, Named_type* real_type)
+{
+ return Integer_type::create_integer_type_alias(name, real_type);
+}
+
// Look up an integer type.
Named_type*
@@ -4450,7 +4491,7 @@ String_type::do_get_backend(Gogo* gogo)
{
std::vector<Backend::Btyped_identifier> fields(2);
- Type* b = gogo->lookup_global("byte")->type_value();
+ Type* b = Type::lookup_integer_type("byte");
Type* pb = Type::make_pointer_type(b);
// We aren't going to get back to this field to finish the
@@ -4561,7 +4602,7 @@ class Sink_type : public Type
{ go_unreachable(); }
void
- do_mangled_name(Gogo*, std::string*) const
+ do_mangled_name(Gogo*, std::string*, bool*) const
{ go_unreachable(); }
};
@@ -5671,7 +5712,7 @@ class Call_multiple_result_type : public Type
{ go_assert(saw_errors()); }
void
- do_mangled_name(Gogo*, std::string*) const
+ do_mangled_name(Gogo*, std::string*, bool*) const
{ go_assert(saw_errors()); }
private:
@@ -5864,6 +5905,7 @@ Struct_type::do_verify()
{
go_error_at(p->location(), "embedded type may not be a pointer");
p->set_type(Type::make_error_type());
+ this->set_is_error();
}
else if (t->points_to() != NULL
&& t->points_to()->interface_type() != NULL)
@@ -5871,6 +5913,7 @@ Struct_type::do_verify()
go_error_at(p->location(),
"embedded type may not be pointer to interface");
p->set_type(Type::make_error_type());
+ this->set_is_error();
}
}
}
@@ -6048,7 +6091,7 @@ Struct_type::do_hash_might_panic()
// Return whether this struct type is permitted to be in the heap.
bool
-Struct_type::do_in_heap()
+Struct_type::do_in_heap() const
{
const Struct_field_list* fields = this->fields_;
if (fields == NULL)
@@ -7229,6 +7272,13 @@ Array_type::verify_length()
Type_context context(Type::lookup_integer_type("int"), false);
this->length_->determine_type(&context);
+ if (this->length_->is_error_expression()
+ || this->length_->type()->is_error())
+ {
+ go_assert(saw_errors());
+ return false;
+ }
+
if (!this->length_->is_constant())
{
go_error_at(this->length_->location(), "array bound is not constant");
@@ -7303,7 +7353,10 @@ Array_type::do_verify()
if (this->element_type()->is_error_type())
return false;
if (!this->verify_length())
- this->length_ = Expression::make_error(this->length_->location());
+ {
+ this->length_ = Expression::make_error(this->length_->location());
+ this->set_is_error();
+ }
return true;
}
@@ -8092,11 +8145,9 @@ Map_type::backend_zero_value(Gogo* gogo)
Btype* barray_type = gogo->backend()->array_type(buint8_type, blength);
std::string zname = Map_type::zero_value->name();
- std::string asm_name(go_selectively_encode_id(zname));
Bvariable* zvar =
- gogo->backend()->implicit_variable(zname, asm_name,
- barray_type, false, false, true,
- Map_type::zero_value_align);
+ gogo->backend()->implicit_variable(zname, "", barray_type, false, false,
+ true, Map_type::zero_value_align);
gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type,
false, false, true, NULL);
return zvar;
@@ -8120,11 +8171,20 @@ Map_type::do_verify()
{
// The runtime support uses "map[void]void".
if (!this->key_type_->is_comparable() && !this->key_type_->is_void_type())
- go_error_at(this->location_, "invalid map key type");
+ {
+ go_error_at(this->location_, "invalid map key type");
+ this->set_is_error();
+ }
if (!this->key_type_->in_heap())
- go_error_at(this->location_, "go:notinheap map key not allowed");
+ {
+ go_error_at(this->location_, "go:notinheap map key not allowed");
+ this->set_is_error();
+ }
if (!this->val_type_->in_heap())
- go_error_at(this->location_, "go:notinheap map value not allowed");
+ {
+ go_error_at(this->location_, "go:notinheap map value not allowed");
+ this->set_is_error();
+ }
return true;
}
@@ -8655,8 +8715,11 @@ Channel_type::do_verify()
// We have no location for this error, but this is not something the
// ordinary user will see.
if (!this->element_type_->in_heap())
- go_error_at(Linemap::unknown_location(),
- "chan of go:notinheap type not allowed");
+ {
+ go_error_at(Linemap::unknown_location(),
+ "chan of go:notinheap type not allowed");
+ this->set_is_error();
+ }
return true;
}
@@ -8782,7 +8845,22 @@ Channel_type::do_reflection(Gogo* gogo, std::string* ret) const
if (!this->may_receive_)
ret->append("<-");
ret->push_back(' ');
+
+ bool need_paren = false;
+ if (this->may_send_
+ && this->may_receive_
+ && this->element_type_->channel_type() != NULL
+ && this->element_type_->unalias()->named_type() == NULL
+ && !this->element_type_->channel_type()->may_send())
+ {
+ ret->push_back('(');
+ need_paren = true;
+ }
+
this->append_reflection(this->element_type_, gogo, ret);
+
+ if (need_paren)
+ ret->push_back(')');
}
// Export.
@@ -8842,14 +8920,10 @@ Channel_type::select_case_type()
{
Type* unsafe_pointer_type =
Type::make_pointer_type(Type::make_void_type());
- Type* uint16_type = Type::lookup_integer_type("uint16");
- Type* int64_type = Type::lookup_integer_type("int64");
scase_type =
- Type::make_builtin_struct_type(4,
+ Type::make_builtin_struct_type(2,
"c", unsafe_pointer_type,
- "elem", unsafe_pointer_type,
- "kind", uint16_type,
- "releasetime", int64_type);
+ "elem", unsafe_pointer_type);
scase_type->set_is_struct_incomparable();
}
return scase_type;
@@ -8921,8 +8995,11 @@ Interface_type::finalize_methods()
else if (this->find_method(p->name()) == NULL)
this->all_methods_->push_back(*p);
else
- go_error_at(p->location(), "duplicate method %qs",
- Gogo::message_name(p->name()).c_str());
+ {
+ go_error_at(p->location(), "duplicate method %qs",
+ Gogo::message_name(p->name()).c_str());
+ this->set_is_error();
+ }
}
std::vector<Named_type*> seen;
@@ -8938,7 +9015,10 @@ Interface_type::finalize_methods()
if (it == NULL)
{
if (!t->is_error())
- go_error_at(tl, "interface contains embedded non-interface");
+ {
+ go_error_at(tl, "interface contains embedded non-interface");
+ this->set_is_error();
+ }
continue;
}
if (it == this)
@@ -8946,6 +9026,7 @@ Interface_type::finalize_methods()
if (!issued_recursive_error)
{
go_error_at(tl, "invalid recursive interface");
+ this->set_is_error();
issued_recursive_error = true;
}
continue;
@@ -8964,6 +9045,7 @@ Interface_type::finalize_methods()
if (*q == nt)
{
go_error_at(tl, "inherited interface loop");
+ this->set_is_error();
break;
}
}
@@ -8986,8 +9068,11 @@ Interface_type::finalize_methods()
q->type(), tl));
else if (!Type::are_identical(q->type(), oldm->type(),
Type::COMPARE_TAGS, NULL))
- go_error_at(tl, "duplicate method %qs",
- Gogo::message_name(q->name()).c_str());
+ {
+ go_error_at(tl, "duplicate method %qs",
+ Gogo::message_name(q->name()).c_str());
+ this->set_is_error();
+ }
}
}
@@ -12014,6 +12099,15 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
ambig2.c_str());
else if (found_pointer_method)
go_error_at(location, "method requires a pointer receiver");
+ else if (it != NULL && it->is_empty())
+ go_error_at(location,
+ "reference to method %qs in interface with no methods",
+ Gogo::message_name(name).c_str());
+ else if (it == NULL && type->deref()->interface_type() != NULL)
+ go_error_at(location,
+ ("reference to method %qs in type that is "
+ "pointer to interface, not interface"),
+ Gogo::message_name(name).c_str());
else if (nt == NULL && st == NULL && it == NULL)
go_error_at(location,
("reference to field %qs in object which "
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index ef81589..f2880f9 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -49,6 +49,7 @@ class Function;
class Translate_context;
class Export;
class Import;
+class Backend_name;
class Btype;
class Bexpression;
class Bvariable;
@@ -461,6 +462,10 @@ class Type
make_integer_type(const char* name, bool is_unsigned, int bits,
int runtime_type_kind);
+ // Make a named integer type alias. This is used for byte and rune.
+ static Named_type*
+ make_integer_type_alias(const char* name, Named_type* real_type);
+
// Look up a named integer type.
static Named_type*
lookup_integer_type(const char* name);
@@ -667,7 +672,7 @@ class Type
// Whether the type is permitted in the heap.
bool
- in_heap()
+ in_heap() const
{ return this->do_in_heap(); }
// Return a hash code for this type for the method hash table.
@@ -1008,11 +1013,11 @@ class Type
std::string
reflection(Gogo*) const;
- // Return a mangled name for the type. This is a name which can be
- // used in assembler code. Identical types should have the same
- // manged name.
- std::string
- mangled_name(Gogo*) const;
+ // Add the backend name for the type to BNAME. This will add one or
+ // two name components. Identical types should have the same
+ // backend name.
+ void
+ backend_name(Gogo*, Backend_name* bname) const;
// If the size of the type can be determined, set *PSIZE to the size
// in bytes and return true. Otherwise, return false. This queries
@@ -1066,12 +1071,11 @@ class Type
// Write the equal function for a type.
void
write_equal_function(Gogo*, Named_type*, int64_t size,
- const std::string& equal_name,
- Function_type* equal_fntype);
+ const Backend_name*, Function_type* equal_fntype);
// Write the hash function for a type.
void
- write_hash_function(Gogo*, int64_t size, const std::string& hash_name,
+ write_hash_function(Gogo*, int64_t size, const Backend_name*,
Function_type* hash_fntype);
// Return the alignment required by the memequalN function.
@@ -1120,7 +1124,7 @@ class Type
{ return false; }
virtual bool
- do_in_heap()
+ do_in_heap() const
{ return true; }
virtual unsigned int
@@ -1136,11 +1140,15 @@ class Type
do_reflection(Gogo*, std::string*) const = 0;
virtual void
- do_mangled_name(Gogo*, std::string*) const = 0;
+ do_mangled_name(Gogo*, std::string*, bool*) const = 0;
virtual void
do_export(Export*) const;
+ // For children to call when they detect that they are in error.
+ void
+ set_is_error();
+
// Return whether a method expects a pointer as the receiver.
static bool
method_expects_pointer(const Named_object*);
@@ -1194,8 +1202,9 @@ class Type
// For the benefit of child class mangling.
void
- append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const
- { type->do_mangled_name(gogo, ret); }
+ append_mangled_name(const Type* type, Gogo* gogo, std::string* ret,
+ bool *is_non_identifier) const
+ { type->do_mangled_name(gogo, ret, is_non_identifier); }
// Return the backend representation for the underlying type of a
// named type.
@@ -1426,8 +1435,6 @@ class Type
// The GC symbol for this type. This starts out as NULL and
// is filled in as needed.
Bvariable* gc_symbol_var_;
- // Whether this type can appear in the heap.
- bool in_heap_;
};
// Type hash table operations, treating aliases as identical to the
@@ -1658,7 +1665,7 @@ class Error_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The void type.
@@ -1687,7 +1694,7 @@ class Void_type : public Type
{ }
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The boolean type.
@@ -1716,7 +1723,7 @@ class Boolean_type : public Type
{ ret->append("bool"); }
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The type of an integer.
@@ -1741,6 +1748,10 @@ class Integer_type : public Type
static Integer_type*
create_abstract_character_type();
+ // Create an alias to an integer type.
+ static Named_type*
+ create_integer_type_alias(const char* name, Named_type* real_type);
+
// Whether this is an abstract integer type.
bool
is_abstract() const
@@ -1798,7 +1809,7 @@ protected:
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Integer_type(bool is_abstract, bool is_unsigned, int bits,
@@ -1884,7 +1895,7 @@ class Float_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Float_type(bool is_abstract, int bits, int runtime_type_kind)
@@ -1962,7 +1973,7 @@ class Complex_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Complex_type(bool is_abstract, int bits, int runtime_type_kind)
@@ -2016,7 +2027,7 @@ class String_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
private:
// The named string type.
@@ -2176,7 +2187,7 @@ class Function_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -2305,7 +2316,7 @@ class Pointer_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -2343,7 +2354,7 @@ class Nil_type : public Type
{ go_unreachable(); }
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The type of a field in a struct.
@@ -2662,7 +2673,7 @@ class Struct_type : public Type
do_hash_might_panic();
bool
- do_in_heap();
+ do_in_heap() const;
unsigned int
do_hash_for_method(Gogo*, int) const;
@@ -2677,7 +2688,7 @@ class Struct_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -2844,7 +2855,7 @@ class Array_type : public Type
{ return this->length_ != NULL && this->element_type_->hash_might_panic(); }
bool
- do_in_heap()
+ do_in_heap() const
{ return this->length_ == NULL || this->element_type_->in_heap(); }
unsigned int
@@ -2860,7 +2871,7 @@ class Array_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -2998,7 +3009,7 @@ class Map_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -3112,7 +3123,7 @@ class Channel_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -3288,7 +3299,7 @@ class Interface_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string*) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -3559,10 +3570,11 @@ class Named_type : public Type
void
append_reflection_type_name(Gogo*, bool use_alias, std::string*) const;
- // Append the mangled type name as for Type::append_mangled_name,
+ // Append the symbol type name as for Type::append_mangled_name,
// but if USE_ALIAS use the alias name rather than the alias target.
void
- append_mangled_type_name(Gogo*, bool use_alias, std::string*) const;
+ append_symbol_type_name(Gogo*, bool use_alias, std::string*,
+ bool* is_non_identifier) const;
// Import a named type.
static void
@@ -3593,7 +3605,7 @@ class Named_type : public Type
do_needs_key_update();
bool
- do_in_heap()
+ do_in_heap() const
{ return this->in_heap_ && this->type_->in_heap(); }
unsigned int
@@ -3609,7 +3621,7 @@ class Named_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@@ -3756,7 +3768,7 @@ class Forward_declaration_type : public Type
{ return this->real_type()->needs_key_update(); }
bool
- do_in_heap()
+ do_in_heap() const
{ return this->real_type()->in_heap(); }
unsigned int
@@ -3773,7 +3785,7 @@ class Forward_declaration_type : public Type
do_reflection(Gogo*, std::string*) const;
void
- do_mangled_name(Gogo*, std::string* ret) const;
+ do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc
index 1eadb3e..ac1f0a1 100644
--- a/gcc/go/gofrontend/wb.cc
+++ b/gcc/go/gofrontend/wb.cc
@@ -683,8 +683,9 @@ Gogo::write_barrier_variable()
Location bloc = Linemap::predeclared_location();
Type* bool_type = Type::lookup_bool_type();
- Array_type* pad_type = Type::make_array_type(this->lookup_global("byte")->type_value(),
- Expression::make_integer_ul(3, NULL, bloc));
+ Array_type* pad_type =
+ Type::make_array_type(Type::lookup_integer_type("byte"),
+ Expression::make_integer_ul(3, NULL, bloc));
Type* uint64_type = Type::lookup_integer_type("uint64");
Type* wb_type = Type::make_builtin_struct_type(5,
"enabled", bool_type,
diff --git a/gcc/godump.c b/gcc/godump.c
index a7cd7ed..a59f9a0 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -484,7 +484,7 @@ static void
go_decl (tree decl)
{
if (!TREE_PUBLIC (decl)
- || DECL_IS_BUILTIN (decl)
+ || DECL_IS_UNDECLARED_BUILTIN (decl)
|| DECL_NAME (decl) == NULL_TREE)
return;
vec_safe_push (queue, decl);
@@ -522,7 +522,7 @@ go_type_decl (tree decl, int local)
{
real_debug_hooks->type_decl (decl, local);
- if (local || DECL_IS_BUILTIN (decl))
+ if (local || DECL_IS_UNDECLARED_BUILTIN (decl))
return;
if (DECL_NAME (decl) == NULL_TREE
&& (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
@@ -697,9 +697,8 @@ go_format_type (class godump_container *container, tree type,
ret = true;
ob = &container->type_obstack;
- if (TYPE_NAME (type) != NULL_TREE
- && (container->decls_seen.contains (type)
- || container->decls_seen.contains (TYPE_NAME (type)))
+ if (use_type_name
+ && TYPE_NAME (type) != NULL_TREE
&& (AGGREGATE_TYPE_P (type)
|| POINTER_TYPE_P (type)
|| TREE_CODE (type) == FUNCTION_TYPE))
@@ -707,6 +706,12 @@ go_format_type (class godump_container *container, tree type,
tree name;
void **slot;
+ /* References to complex builtin types cannot be translated to
+ Go. */
+ if (DECL_P (TYPE_NAME (type))
+ && DECL_IS_UNDECLARED_BUILTIN (TYPE_NAME (type)))
+ ret = false;
+
name = TYPE_IDENTIFIER (type);
slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
@@ -714,13 +719,17 @@ go_format_type (class godump_container *container, tree type,
if (slot != NULL)
ret = false;
+ /* References to incomplete structs are permitted in many
+ contexts, like behind a pointer or inside of a typedef. So
+ consider any referenced struct a potential dummy type. */
+ if (RECORD_OR_UNION_TYPE_P (type))
+ container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
+
obstack_1grow (ob, '_');
go_append_string (ob, name);
return ret;
}
- container->decls_seen.add (type);
-
switch (TREE_CODE (type))
{
case TYPE_DECL:
@@ -821,34 +830,6 @@ go_format_type (class godump_container *container, tree type,
break;
case POINTER_TYPE:
- if (use_type_name
- && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
- && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
- || (POINTER_TYPE_P (TREE_TYPE (type))
- && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
- == FUNCTION_TYPE))))
- {
- tree name;
- void **slot;
-
- name = TYPE_IDENTIFIER (TREE_TYPE (type));
-
- slot = htab_find_slot (container->invalid_hash,
- IDENTIFIER_POINTER (name), NO_INSERT);
- if (slot != NULL)
- ret = false;
-
- obstack_grow (ob, "*_", 2);
- go_append_string (ob, name);
-
- /* The pointer here can be used without the struct or union
- definition. So this struct or union is a potential dummy
- type. */
- if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
- container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
-
- return ret;
- }
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
obstack_grow (ob, "func", 4);
else
@@ -1107,7 +1088,7 @@ go_output_type (class godump_container *container)
static void
go_output_fndecl (class godump_container *container, tree decl)
{
- if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
+ if (!go_format_type (container, TREE_TYPE (decl), true, true, NULL, false))
fprintf (go_dump_file, "// ");
fprintf (go_dump_file, "func _%s ",
IDENTIFIER_POINTER (DECL_NAME (decl)));
@@ -1174,16 +1155,28 @@ go_output_typedef (class godump_container *container, tree decl)
{
void **slot;
const char *type;
+ tree original_type;
type = IDENTIFIER_POINTER (DECL_NAME (decl));
+ original_type = DECL_ORIGINAL_TYPE (decl);
+ if (original_type == NULL_TREE)
+ original_type = TREE_TYPE (decl);
+
+ /* Suppress typedefs where the type name matches the underlying
+ struct/union/enum tag. This way we'll emit the struct definition
+ instead of an invalid recursive type. */
+ if (TYPE_IDENTIFIER (original_type) != NULL
+ && IDENTIFIER_POINTER (TYPE_IDENTIFIER (original_type)) == type)
+ return;
+
/* If type defined already, skip. */
slot = htab_find_slot (container->type_hash, type, INSERT);
if (*slot != NULL)
return;
*slot = CONST_CAST (void *, (const void *) type);
- if (!go_format_type (container, TREE_TYPE (decl), true, false, NULL,
- false))
+ if (!go_format_type (container, original_type, true, false,
+ NULL, false))
{
fprintf (go_dump_file, "// ");
slot = htab_find_slot (container->invalid_hash, type, INSERT);
@@ -1206,7 +1199,9 @@ go_output_typedef (class godump_container *container, tree decl)
container->decls_seen.add (decl);
}
- else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
+ else if ((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && TYPE_NAME (TREE_TYPE (decl)) != NULL)
{
void **slot;
const char *type;
diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h
index 1ec1b4e..787da3a 100644
--- a/gcc/hard-reg-set.h
+++ b/gcc/hard-reg-set.h
@@ -359,6 +359,8 @@ hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
extern char global_regs[FIRST_PSEUDO_REGISTER];
+extern HARD_REG_SET global_reg_set;
+
class simplifiable_subreg;
class subreg_shape;
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index a9ea7b1..0bd05dc 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -5127,6 +5127,11 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
rtx cond;
+ /* If the conditional jump is more than just a conditional jump,
+ then we cannot do conditional execution conversion on this block. */
+ if (!onlyjump_p (jump))
+ goto nce;
+
cond = cond_exec_get_condition (jump);
if (! cond)
return FALSE;
@@ -5154,6 +5159,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
earliest = jump;
}
+ nce:
#endif
/* If we allocated new pseudos (e.g. in the conditional move
diff --git a/gcc/incpath.c b/gcc/incpath.c
index 8437939..14593a1 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -137,7 +137,8 @@ add_standard_paths (const char *sysroot, const char *iprefix,
IPREFIX and search them first. */
for (p = cpp_include_defaults; p->fname; p++)
{
- if (!p->cplusplus || cxx_stdinc)
+ if (p->cplusplus == 0
+ || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))
{
/* Should we be translating sysrooted dirs too? Assume
that iprefix and sysroot are mutually exclusive, for
@@ -168,7 +169,8 @@ add_standard_paths (const char *sysroot, const char *iprefix,
for (p = cpp_include_defaults; p->fname; p++)
{
- if (!p->cplusplus || cxx_stdinc)
+ if (p->cplusplus == 0
+ || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))
{
char *str;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 792d2ca..41223ff 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -469,6 +469,111 @@ expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
/* This should get expanded in the sanopt pass. */
static void
+expand_HWASAN_CHECK (internal_fn, gcall *)
+{
+ gcc_unreachable ();
+}
+
+/* For hwasan stack tagging:
+ Clear tags on the dynamically allocated space.
+ For use after an object dynamically allocated on the stack goes out of
+ scope. */
+static void
+expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
+{
+ gcc_assert (Pmode == ptr_mode);
+ tree restored_position = gimple_call_arg (gc, 0);
+ rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
+ EXPAND_NORMAL);
+ rtx func = init_one_libfunc ("__hwasan_tag_memory");
+ rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
+ stack_pointer_rtx, NULL_RTX, 0,
+ OPTAB_WIDEN);
+ emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
+ virtual_stack_dynamic_rtx, Pmode,
+ HWASAN_STACK_BACKGROUND, QImode,
+ off, Pmode);
+}
+
+/* For hwasan stack tagging:
+ Return a tag to be used for a dynamic allocation. */
+static void
+expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
+{
+ tree tag = gimple_call_lhs (gc);
+ rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ machine_mode mode = GET_MODE (target);
+ gcc_assert (mode == QImode);
+
+ rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
+ gcc_assert (base_tag);
+ rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
+ rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
+ target, /* unsignedp = */1,
+ OPTAB_WIDEN);
+ chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
+
+ /* Really need to put the tag into the `target` RTX. */
+ if (chosen_tag != target)
+ {
+ rtx temp = chosen_tag;
+ gcc_assert (GET_MODE (chosen_tag) == mode);
+ emit_move_insn (target, temp);
+ }
+
+ hwasan_increment_frame_tag ();
+}
+
+/* For hwasan stack tagging:
+ Tag a region of space in the shadow stack according to the base pointer of
+ an object on the stack. N.b. the length provided in the internal call is
+ required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
+static void
+expand_HWASAN_MARK (internal_fn, gcall *gc)
+{
+ gcc_assert (ptr_mode == Pmode);
+ HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
+ bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
+
+ tree base = gimple_call_arg (gc, 1);
+ gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
+ rtx base_rtx = expand_normal (base);
+
+ rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
+ : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
+ rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
+
+ tree len = gimple_call_arg (gc, 2);
+ rtx r_len = expand_normal (len);
+
+ rtx func = init_one_libfunc ("__hwasan_tag_memory");
+ emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
+ tag, QImode, r_len, Pmode);
+}
+
+/* For hwasan stack tagging:
+ Store a tag into a pointer. */
+static void
+expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
+{
+ gcc_assert (ptr_mode == Pmode);
+ tree g_target = gimple_call_lhs (gc);
+ tree g_ptr = gimple_call_arg (gc, 0);
+ tree g_tag = gimple_call_arg (gc, 1);
+
+ rtx ptr = expand_normal (g_ptr);
+ rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
+ rtx target = expand_normal (g_target);
+
+ rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
+ rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
+ if (tagged_value != target)
+ emit_move_insn (target, tagged_value);
+}
+
+/* This should get expanded in the sanopt pass. */
+
+static void
expand_ASAN_CHECK (internal_fn, gcall *)
{
gcc_unreachable ();
@@ -553,6 +658,16 @@ get_min_precision (tree arg, signop sign)
if (++cnt > 30)
return prec + (orig_sign != sign);
}
+ if (CONVERT_EXPR_P (arg)
+ && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
+ && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
+ {
+ /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
+ If y_2's min precision is smaller than prec, return that. */
+ int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
+ if (oprec < prec)
+ return oprec + (orig_sign != sign);
+ }
if (TREE_CODE (arg) != SSA_NAME)
return prec + (orig_sign != sign);
wide_int arg_min, arg_max;
@@ -683,7 +798,7 @@ expand_ubsan_result_store (rtx target, rtx res)
/* Add sub/add overflow checking to the statement STMT.
CODE says whether the operation is +, or -. */
-static void
+void
expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
tree arg0, tree arg1, bool unsr_p, bool uns0_p,
bool uns1_p, bool is_ubsan, tree *datap)
@@ -1357,6 +1472,37 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
case 3:
+ if (get_min_precision (arg1, UNSIGNED)
+ + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
+ {
+ /* If the first operand is sign extended from narrower type, the
+ second operand is zero extended from narrower type and
+ the sum of the two precisions is smaller or equal to the
+ result precision: if the first argument is at runtime
+ non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
+ and there will be no overflow, if the first argument is
+ negative and the second argument zero, the result will be
+ 0 and there will be no overflow, if the first argument is
+ negative and the second argument positive, the result when
+ treated as signed will be negative (minimum -0x7f80 or
+ -0x7f..f80..0) there there will be always overflow. So, do
+ res = (U) (s1 * u2)
+ ovf = (S) res < 0 */
+ struct separate_ops ops;
+ ops.code = MULT_EXPR;
+ ops.type
+ = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
+ 1);
+ ops.op0 = make_tree (ops.type, op0);
+ ops.op1 = make_tree (ops.type, op1);
+ ops.op2 = NULL_TREE;
+ ops.location = loc;
+ res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
+ do_compare_rtx_and_jump (res, const0_rtx, GE, false,
+ mode, NULL_RTX, NULL, done_label,
+ profile_probability::very_likely ());
+ goto do_error_label;
+ }
rtx_code_label *do_main_label;
do_main_label = gen_label_rtx ();
do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
@@ -1374,7 +1520,16 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
/* u1 * u2 -> sr */
if (uns0_p && uns1_p && !unsr_p)
{
- uns = true;
+ if ((pos_neg0 | pos_neg1) == 1)
+ {
+ /* If both arguments are zero extended from narrower types,
+ the MSB will be clear on both and so we can pretend it is
+ a normal s1 * s2 -> sr multiplication. */
+ uns0_p = false;
+ uns1_p = false;
+ }
+ else
+ uns = true;
/* Rest of handling of this case after res is computed. */
goto do_main;
}
@@ -1455,6 +1610,37 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
profile_probability::very_likely ());
goto do_error_label;
}
+ if (get_min_precision (arg0, SIGNED)
+ + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
+ {
+ /* If both operands are sign extended from narrower types and
+ the sum of the two precisions is smaller or equal to the
+ result precision: if both arguments are at runtime
+ non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
+ and there will be no overflow, if both arguments are negative,
+ maximum result will be 0x40..00 and there will be no overflow
+ either, if one argument is positive and the other argument
+ negative, the result when treated as signed will be negative
+ and there will be always overflow, and if one argument is
+ zero and the other negative the result will be zero and no
+ overflow. So, do
+ res = (U) (s1 * s2)
+ ovf = (S) res < 0 */
+ struct separate_ops ops;
+ ops.code = MULT_EXPR;
+ ops.type
+ = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
+ 1);
+ ops.op0 = make_tree (ops.type, op0);
+ ops.op1 = make_tree (ops.type, op1);
+ ops.op2 = NULL_TREE;
+ ops.location = loc;
+ res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
+ do_compare_rtx_and_jump (res, const0_rtx, GE, false,
+ mode, NULL_RTX, NULL, done_label,
+ profile_probability::very_likely ());
+ goto do_error_label;
+ }
/* The general case, do all the needed comparisons at runtime. */
rtx_code_label *do_main_label, *after_negate_label;
rtx rop0, rop1;
@@ -3044,27 +3230,68 @@ expand_DIVMOD (internal_fn, gcall *call_stmt)
the division and modulo and if it emits any library calls or any
{,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
divmod libcall. */
- struct separate_ops ops;
- ops.code = TRUNC_DIV_EXPR;
- ops.type = type;
- ops.op0 = make_tree (ops.type, op0);
- ops.op1 = arg1;
- ops.op2 = NULL_TREE;
- ops.location = gimple_location (call_stmt);
- start_sequence ();
- quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
- if (contains_call_div_mod (get_insns ()))
- quotient = NULL_RTX;
- else
+ scalar_int_mode int_mode;
+ if (remainder == NULL_RTX
+ && optimize
+ && CONST_INT_P (op1)
+ && !pow2p_hwi (INTVAL (op1))
+ && is_int_mode (TYPE_MODE (type), &int_mode)
+ && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+ && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
+ && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
+ && optimize_insn_for_speed_p ())
{
- ops.code = TRUNC_MOD_EXPR;
- remainder = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
+ rtx_insn *last = get_last_insn ();
+ remainder = NULL_RTX;
+ quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
+ TYPE_UNSIGNED (type));
+ if (quotient != NULL_RTX)
+ {
+ if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
+ {
+ rtx_insn *move = emit_move_insn (quotient, quotient);
+ set_dst_reg_note (move, REG_EQUAL,
+ gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
+ ? UDIV : DIV, int_mode,
+ copy_rtx (op0), op1),
+ quotient);
+ move = emit_move_insn (remainder, remainder);
+ set_dst_reg_note (move, REG_EQUAL,
+ gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
+ ? UMOD : MOD, int_mode,
+ copy_rtx (op0), op1),
+ quotient);
+ }
+ }
+ else
+ delete_insns_since (last);
+ }
+
+ if (remainder == NULL_RTX)
+ {
+ struct separate_ops ops;
+ ops.code = TRUNC_DIV_EXPR;
+ ops.type = type;
+ ops.op0 = make_tree (ops.type, op0);
+ ops.op1 = arg1;
+ ops.op2 = NULL_TREE;
+ ops.location = gimple_location (call_stmt);
+ start_sequence ();
+ quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
if (contains_call_div_mod (get_insns ()))
- remainder = NULL_RTX;
+ quotient = NULL_RTX;
+ else
+ {
+ ops.code = TRUNC_MOD_EXPR;
+ remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
+ EXPAND_NORMAL);
+ if (contains_call_div_mod (get_insns ()))
+ remainder = NULL_RTX;
+ }
+ if (remainder)
+ insns = get_insns ();
+ end_sequence ();
}
- if (remainder)
- insns = get_insns ();
- end_sequence ();
}
if (remainder)
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 310d37a..511fe70 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -277,6 +277,9 @@ DEF_INTERNAL_FLT_FN (SCALB, ECF_CONST, scalb, binary)
DEF_INTERNAL_FLT_FLOATN_FN (FMIN, ECF_CONST, fmin, binary)
DEF_INTERNAL_FLT_FLOATN_FN (FMAX, ECF_CONST, fmax, binary)
DEF_INTERNAL_OPTAB_FN (XORSIGN, ECF_CONST, xorsign, binary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_ADD_ROT90, ECF_CONST, cadd90, binary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_ADD_ROT270, ECF_CONST, cadd270, binary)
+
/* FP scales. */
DEF_INTERNAL_FLT_FN (LDEXP, ECF_CONST, ldexp, binary)
@@ -321,6 +324,13 @@ DEF_INTERNAL_FN (UBSAN_PTR, ECF_LEAF | ECF_NOTHROW, ". R . ")
DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (HWASAN_ALLOCA_UNPOISON, ECF_LEAF | ECF_NOTHROW, ". R ")
+DEF_INTERNAL_FN (HWASAN_CHOOSE_TAG, ECF_LEAF | ECF_NOTHROW, ". ")
+DEF_INTERNAL_FN (HWASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW,
+ ". . R . . ")
+DEF_INTERNAL_FN (HWASAN_MARK, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (HWASAN_SET_TAG,
+ ECF_TM_PURE | ECF_PURE | ECF_LEAF | ECF_NOTHROW, ". R R ")
DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW,
". . R . . ")
DEF_INTERNAL_FN (ASAN_MARK, ECF_LEAF | ECF_NOTHROW, NULL)
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index ac970e9..2a96b2b 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -224,6 +224,8 @@ extern bool internal_gather_scatter_fn_supported_p (internal_fn, tree,
extern bool internal_check_ptrs_fn_supported_p (internal_fn, tree,
poly_uint64, unsigned int);
+extern void expand_addsub_overflow (location_t, tree_code, tree, tree, tree,
+ bool, bool, bool, bool, tree *);
extern void expand_internal_call (gcall *);
extern void expand_internal_call (internal_fn, gcall *);
extern void expand_PHI (internal_fn, gcall *);
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index f981366..ac9bc23 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -124,6 +124,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "dbgcnt.h"
+#include "symtab-clones.h"
template <typename valtype> class ipcp_value;
@@ -155,16 +156,22 @@ public:
class ipcp_value_base
{
public:
- /* Time benefit and size cost that specializing the function for this value
- would bring about in this function alone. */
- int local_time_benefit, local_size_cost;
- /* Time benefit and size cost that specializing the function for this value
- can bring about in it's callees (transitively). */
- int prop_time_benefit, prop_size_cost;
+ /* Time benefit and that specializing the function for this value would bring
+ about in this function alone. */
+ sreal local_time_benefit;
+ /* Time benefit that specializing the function for this value can bring about
+ in it's callees. */
+ sreal prop_time_benefit;
+ /* Size cost that specializing the function for this value would bring about
+ in this function alone. */
+ int local_size_cost;
+ /* Size cost that specializing the function for this value can bring about in
+ it's callees. */
+ int prop_size_cost;
ipcp_value_base ()
- : local_time_benefit (0), local_size_cost (0),
- prop_time_benefit (0), prop_size_cost (0) {}
+ : local_time_benefit (0), prop_time_benefit (0),
+ local_size_cost (0), prop_size_cost (0) {}
};
/* Describes one particular value stored in struct ipcp_lattice. */
@@ -498,10 +505,10 @@ ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
}
if (dump_benefits)
- fprintf (f, " [loc_time: %i, loc_size: %i, "
- "prop_time: %i, prop_size: %i]\n",
- val->local_time_benefit, val->local_size_cost,
- val->prop_time_benefit, val->prop_size_cost);
+ fprintf (f, " [loc_time: %g, loc_size: %i, "
+ "prop_time: %g, prop_size: %i]\n",
+ val->local_time_benefit.to_double (), val->local_size_cost,
+ val->prop_time_benefit.to_double (), val->prop_size_cost);
}
if (!dump_benefits)
fprintf (f, "\n");
@@ -667,7 +674,8 @@ ipcp_versionable_function_p (struct cgraph_node *node)
struct caller_statistics
{
profile_count count_sum;
- int n_calls, n_hot_calls, freq_sum;
+ sreal freq_sum;
+ int n_calls, n_hot_calls;
};
/* Initialize fields of STAT to zeroes. */
@@ -695,7 +703,7 @@ gather_caller_stats (struct cgraph_node *node, void *data)
{
if (cs->count.ipa ().initialized_p ())
stats->count_sum += cs->count.ipa ();
- stats->freq_sum += cs->frequency ();
+ stats->freq_sum += cs->sreal_frequency ();
stats->n_calls++;
if (cs->maybe_hot_p ())
stats->n_hot_calls ++;
@@ -1226,18 +1234,21 @@ initialize_node_lattices (struct cgraph_node *node)
auto_vec<bool, 16> surviving_params;
bool pre_modified = false;
- if (!disable && node->clone.param_adjustments)
+
+ clone_info *cinfo = clone_info::get (node);
+
+ if (!disable && cinfo && cinfo->param_adjustments)
{
/* At the moment all IPA optimizations should use the number of
parameters of the prevailing decl as the m_always_copy_start.
Handling any other value would complicate the code below, so for the
time bing let's only assert it is so. */
- gcc_assert ((node->clone.param_adjustments->m_always_copy_start
+ gcc_assert ((cinfo->param_adjustments->m_always_copy_start
== ipa_get_param_count (info))
- || node->clone.param_adjustments->m_always_copy_start < 0);
+ || cinfo->param_adjustments->m_always_copy_start < 0);
pre_modified = true;
- node->clone.param_adjustments->get_surviving_params (&surviving_params);
+ cinfo->param_adjustments->get_surviving_params (&surviving_params);
if (dump_file && (dump_flags & TDF_DETAILS)
&& !node->alias && !node->thunk)
@@ -1293,6 +1304,26 @@ initialize_node_lattices (struct cgraph_node *node)
}
}
+/* Return true iff X and Y should be considered equal values by IPA-CP. */
+
+static bool
+values_equal_for_ipcp_p (tree x, tree y)
+{
+ gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
+
+ if (x == y)
+ return true;
+
+ if (TREE_CODE (x) == ADDR_EXPR
+ && TREE_CODE (y) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
+ && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
+ return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
+ DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
+ else
+ return operand_equal_p (x, y, 0);
+}
+
/* Return the result of a (possibly arithmetic) operation on the constant
value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is
the type of the parameter to which the result is passed. Return
@@ -1310,6 +1341,14 @@ ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand,
if (!is_gimple_ip_invariant (input))
return NULL_TREE;
+ if (opcode == ASSERT_EXPR)
+ {
+ if (values_equal_for_ipcp_p (input, operand))
+ return input;
+ else
+ return NULL_TREE;
+ }
+
if (!res_type)
{
if (TREE_CODE_CLASS (opcode) == tcc_comparison)
@@ -1742,26 +1781,6 @@ ipcp_verify_propagated_values (void)
}
}
-/* Return true iff X and Y should be considered equal values by IPA-CP. */
-
-static bool
-values_equal_for_ipcp_p (tree x, tree y)
-{
- gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
-
- if (x == y)
- return true;
-
- if (TREE_CODE (x) == ADDR_EXPR
- && TREE_CODE (y) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
- && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
- return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
- DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
- else
- return operand_equal_p (x, y, 0);
-}
-
/* Return true iff X and Y should be considered equal contexts by IPA-CP. */
static bool
@@ -3220,9 +3239,9 @@ hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates)
/* If there is a reason to penalize the function described by INFO in the
cloning goodness evaluation, do so. */
-static inline int64_t
+static inline sreal
incorporate_penalties (cgraph_node *node, ipa_node_params *info,
- int64_t evaluation)
+ sreal evaluation)
{
if (info->node_within_scc && !info->node_is_self_scc)
evaluation = (evaluation
@@ -3243,8 +3262,9 @@ incorporate_penalties (cgraph_node *node, ipa_node_params *info,
potential new clone in FREQUENCIES. */
static bool
-good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
- int freq_sum, profile_count count_sum, int size_cost)
+good_cloning_opportunity_p (struct cgraph_node *node, sreal time_benefit,
+ sreal freq_sum, profile_count count_sum,
+ int size_cost)
{
if (time_benefit == 0
|| !opt_for_fn (node->decl, flag_ipa_cp_clone)
@@ -3257,45 +3277,44 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
int eval_threshold = opt_for_fn (node->decl, param_ipa_cp_eval_threshold);
if (max_count > profile_count::zero ())
{
- int factor = RDIV (count_sum.probability_in
- (max_count).to_reg_br_prob_base ()
- * 1000, REG_BR_PROB_BASE);
- int64_t evaluation = (((int64_t) time_benefit * factor)
- / size_cost);
+
+ sreal factor = count_sum.probability_in (max_count).to_sreal ();
+ sreal evaluation = (time_benefit * factor) / size_cost;
evaluation = incorporate_penalties (node, info, evaluation);
+ evaluation *= 1000;
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
- "size: %i, count_sum: ", time_benefit, size_cost);
+ fprintf (dump_file, " good_cloning_opportunity_p (time: %g, "
+ "size: %i, count_sum: ", time_benefit.to_double (),
+ size_cost);
count_sum.dump (dump_file);
- fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
- ", threshold: %i\n",
+ fprintf (dump_file, "%s%s) -> evaluation: %.2f, threshold: %i\n",
info->node_within_scc
? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
info->node_calling_single_call ? ", single_call" : "",
- evaluation, eval_threshold);
+ evaluation.to_double (), eval_threshold);
}
- return evaluation >= eval_threshold;
+ return evaluation.to_int () >= eval_threshold;
}
else
{
- int64_t evaluation = (((int64_t) time_benefit * freq_sum)
- / size_cost);
+ sreal evaluation = (time_benefit * freq_sum) / size_cost;
evaluation = incorporate_penalties (node, info, evaluation);
+ evaluation *= 1000;
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
- "size: %i, freq_sum: %i%s%s) -> evaluation: "
- "%" PRId64 ", threshold: %i\n",
- time_benefit, size_cost, freq_sum,
+ fprintf (dump_file, " good_cloning_opportunity_p (time: %g, "
+ "size: %i, freq_sum: %g%s%s) -> evaluation: %.2f, "
+ "threshold: %i\n",
+ time_benefit.to_double (), size_cost, freq_sum.to_double (),
info->node_within_scc
? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
info->node_calling_single_call ? ", single_call" : "",
- evaluation, eval_threshold);
+ evaluation.to_double (), eval_threshold);
- return evaluation >= eval_threshold;
+ return evaluation.to_int () >= eval_threshold;
}
}
@@ -3407,13 +3426,10 @@ perform_estimation_of_a_value (cgraph_node *node,
int removable_params_cost, int est_move_cost,
ipcp_value_base *val)
{
- int time_benefit;
+ sreal time_benefit;
ipa_call_estimates estimates;
estimate_ipcp_clone_size_and_time (node, avals, &estimates);
- sreal time_delta = estimates.nonspecialized_time - estimates.time;
- if (time_delta > 65535)
- time_delta = 65535;
/* Extern inline functions have no cloning local time benefits because they
will be inlined anyway. The only reason to clone them is if it enables
@@ -3421,10 +3437,10 @@ perform_estimation_of_a_value (cgraph_node *node,
if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
time_benefit = 0;
else
- time_benefit = time_delta.to_int ()
- + devirtualization_time_bonus (node, avals)
- + hint_time_bonus (node, estimates)
- + removable_params_cost + est_move_cost;
+ time_benefit = (estimates.nonspecialized_time - estimates.time)
+ + (devirtualization_time_bonus (node, avals)
+ + hint_time_bonus (node, estimates)
+ + removable_params_cost + est_move_cost);
int size = estimates.size;
gcc_checking_assert (size >=0);
@@ -3505,10 +3521,8 @@ estimate_local_effects (struct cgraph_node *node)
fprintf (dump_file, " Decided to specialize for all "
"known contexts, code not going to grow.\n");
}
- else if (good_cloning_opportunity_p (node,
- MIN ((time).to_int (), 65536),
- stats.freq_sum, stats.count_sum,
- size))
+ else if (good_cloning_opportunity_p (node, time, stats.freq_sum,
+ stats.count_sum, size))
{
if (size + overall_size <= get_max_overall_size (node))
{
@@ -3557,8 +3571,9 @@ estimate_local_effects (struct cgraph_node *node)
print_ipcp_constant_value (dump_file, val->value);
fprintf (dump_file, " for ");
ipa_dump_param (dump_file, info, i);
- fprintf (dump_file, ": time_benefit: %i, size: %i\n",
- val->local_time_benefit, val->local_size_cost);
+ fprintf (dump_file, ": time_benefit: %g, size: %i\n",
+ val->local_time_benefit.to_double (),
+ val->local_size_cost);
}
}
avals.m_known_vals[i] = NULL_TREE;
@@ -3591,8 +3606,9 @@ estimate_local_effects (struct cgraph_node *node)
print_ipcp_constant_value (dump_file, val->value);
fprintf (dump_file, " for ");
ipa_dump_param (dump_file, info, i);
- fprintf (dump_file, ": time_benefit: %i, size: %i\n",
- val->local_time_benefit, val->local_size_cost);
+ fprintf (dump_file, ": time_benefit: %g, size: %i\n",
+ val->local_time_benefit.to_double (),
+ val->local_size_cost);
}
}
avals.m_known_contexts[i] = ipa_polymorphic_call_context ();
@@ -3633,10 +3649,11 @@ estimate_local_effects (struct cgraph_node *node)
fprintf (dump_file, " for ");
ipa_dump_param (dump_file, info, i);
fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
- "]: time_benefit: %i, size: %i\n",
+ "]: time_benefit: %g, size: %i\n",
plats->aggs_by_ref ? "ref " : "",
aglat->offset,
- val->local_time_benefit, val->local_size_cost);
+ val->local_time_benefit.to_double (),
+ val->local_size_cost);
}
agg->items.pop ();
@@ -3824,20 +3841,6 @@ propagate_constants_topo (class ipa_topo_info *topo)
}
}
-
-/* Return the sum of A and B if none of them is bigger than INT_MAX/2, return
- the bigger one if otherwise. */
-
-static int
-safe_add (int a, int b)
-{
- if (a > INT_MAX/2 || b > INT_MAX/2)
- return a > b ? a : b;
- else
- return a + b;
-}
-
-
/* Propagate the estimated effects of individual values along the topological
from the dependent values to those they depend on. */
@@ -3846,30 +3849,51 @@ void
value_topo_info<valtype>::propagate_effects ()
{
ipcp_value<valtype> *base;
+ hash_set<ipcp_value<valtype> *> processed_srcvals;
for (base = values_topo; base; base = base->topo_next)
{
ipcp_value_source<valtype> *src;
ipcp_value<valtype> *val;
- int time = 0, size = 0;
+ sreal time = 0;
+ HOST_WIDE_INT size = 0;
for (val = base; val; val = val->scc_next)
{
- time = safe_add (time,
- val->local_time_benefit + val->prop_time_benefit);
- size = safe_add (size, val->local_size_cost + val->prop_size_cost);
+ time = time + val->local_time_benefit + val->prop_time_benefit;
+ size = size + val->local_size_cost + val->prop_size_cost;
}
for (val = base; val; val = val->scc_next)
- for (src = val->sources; src; src = src->next)
- if (src->val
- && src->cs->maybe_hot_p ())
+ {
+ processed_srcvals.empty ();
+ for (src = val->sources; src; src = src->next)
+ if (src->val
+ && src->cs->maybe_hot_p ())
+ {
+ if (!processed_srcvals.add (src->val))
+ {
+ HOST_WIDE_INT prop_size = size + src->val->prop_size_cost;
+ if (prop_size < INT_MAX)
+ src->val->prop_size_cost = prop_size;
+ else
+ continue;
+ }
+ src->val->prop_time_benefit
+ += time * src->cs->sreal_frequency ();
+ }
+
+ if (size < INT_MAX)
{
- src->val->prop_time_benefit = safe_add (time,
- src->val->prop_time_benefit);
- src->val->prop_size_cost = safe_add (size,
- src->val->prop_size_cost);
+ val->prop_time_benefit = time;
+ val->prop_size_cost = size;
}
+ else
+ {
+ val->prop_time_benefit = 0;
+ val->prop_size_cost = 0;
+ }
+ }
}
}
@@ -4158,11 +4182,12 @@ get_next_cgraph_edge_clone (struct cgraph_edge *cs)
template <typename valtype>
static bool
get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
- int *freq_sum,
- profile_count *count_sum, int *caller_count)
+ sreal *freq_sum, profile_count *count_sum,
+ int *caller_count)
{
ipcp_value_source<valtype> *src;
- int freq = 0, count = 0;
+ sreal freq = 0;
+ int count = 0;
profile_count cnt = profile_count::zero ();
bool hot = false;
bool non_self_recursive = false;
@@ -4175,7 +4200,7 @@ get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
if (cgraph_edge_brings_value_p (cs, src, dest, val))
{
count++;
- freq += cs->frequency ();
+ freq += cs->sreal_frequency ();
if (cs->count.ipa ().initialized_p ())
cnt += cs->count.ipa ();
hot |= cs->maybe_hot_p ();
@@ -4456,9 +4481,10 @@ want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts)
if (!filled_vec)
{
- if (!node->clone.param_adjustments)
+ clone_info *info = clone_info::get (node);
+ if (!info || !info->param_adjustments)
return true;
- node->clone.param_adjustments->get_surviving_params (&surviving);
+ info->param_adjustments->get_surviving_params (&surviving);
filled_vec = true;
}
if (surviving.length() < (unsigned) i && surviving[i])
@@ -4484,7 +4510,9 @@ create_specialized_node (struct cgraph_node *node,
struct ipa_agg_replacement_value *av;
struct cgraph_node *new_node;
int i, count = ipa_get_param_count (info);
- ipa_param_adjustments *old_adjustments = node->clone.param_adjustments;
+ clone_info *cinfo = clone_info::get (node);
+ ipa_param_adjustments *old_adjustments = cinfo
+ ? cinfo->param_adjustments : NULL;
ipa_param_adjustments *new_adjustments;
gcc_assert (!info->ipcp_orig_node);
gcc_assert (node->can_change_signature
@@ -4538,7 +4566,7 @@ create_specialized_node (struct cgraph_node *node,
else
new_adjustments = NULL;
- replace_trees = vec_safe_copy (node->clone.tree_map);
+ replace_trees = cinfo ? vec_safe_copy (cinfo->tree_map) : NULL;
for (i = 0; i < count; i++)
{
tree t = known_csts[i];
@@ -5441,7 +5469,8 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
ipcp_value<valtype> *val, ipa_auto_call_arg_values *avals)
{
struct ipa_agg_replacement_value *aggvals;
- int freq_sum, caller_count;
+ int caller_count;
+ sreal freq_sum;
profile_count count_sum;
vec<cgraph_edge *> callers;
@@ -5462,6 +5491,9 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
&caller_count))
return false;
+ if (!dbg_cnt (ipa_cp_values))
+ return false;
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " - considering value ");
@@ -5476,12 +5508,8 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
if (!good_cloning_opportunity_p (node, val->local_time_benefit,
freq_sum, count_sum,
val->local_size_cost)
- && !good_cloning_opportunity_p (node,
- safe_add (val->local_time_benefit,
- val->prop_time_benefit),
- freq_sum, count_sum,
- safe_add (val->local_size_cost,
- val->prop_size_cost)))
+ && !good_cloning_opportunity_p (node, val->prop_time_benefit,
+ freq_sum, count_sum, val->prop_size_cost))
return false;
if (dump_file)
@@ -5577,6 +5605,12 @@ decide_whether_version_node (struct cgraph_node *node)
if (info->do_clone_for_all_contexts)
{
+ if (!dbg_cnt (ipa_cp_values))
+ {
+ info->do_clone_for_all_contexts = false;
+ return ret;
+ }
+
struct cgraph_node *clone;
vec<cgraph_edge *> callers = node->collect_callers ();
@@ -5864,7 +5898,8 @@ ipcp_store_vr_results (void)
ipa_vr vr;
if (!plats->m_value_range.bottom_p ()
- && !plats->m_value_range.top_p ())
+ && !plats->m_value_range.top_p ()
+ && dbg_cnt (ipa_cp_vr))
{
vr.known = true;
vr.type = plats->m_value_range.m_vr.kind ();
@@ -5943,22 +5978,6 @@ ipcp_generate_summary (void)
ipa_analyze_node (node);
}
-/* Write ipcp summary for nodes in SET. */
-
-static void
-ipcp_write_summary (void)
-{
- ipa_prop_write_jump_functions ();
-}
-
-/* Read ipcp summary. */
-
-static void
-ipcp_read_summary (void)
-{
- ipa_prop_read_jump_functions ();
-}
-
namespace {
const pass_data pass_data_ipa_cp =
@@ -5980,8 +5999,8 @@ public:
pass_ipa_cp (gcc::context *ctxt)
: ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
ipcp_generate_summary, /* generate_summary */
- ipcp_write_summary, /* write_summary */
- ipcp_read_summary, /* read_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
ipcp_write_transformation_summaries, /*
write_optimization_summary */
ipcp_read_transformation_summaries, /*
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 067ed5b..0f2b814 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -1521,6 +1521,7 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
break;
}
case VOID_TYPE:
+ case OPAQUE_TYPE:
case NULLPTR_TYPE:
break;
@@ -2032,6 +2033,8 @@ odr_based_tbaa_p (const_tree type)
{
if (!RECORD_OR_UNION_TYPE_P (type))
return false;
+ if (!odr_hash)
+ return false;
odr_type t = get_odr_type (const_cast <tree> (type), false);
if (!t || !t->tbaa_enabled)
return false;
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index f27c5f0..b8f4a0a9 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "tree-into-ssa.h"
+#include "symtab-clones.h"
/* Summaries. */
fast_function_summary <ipa_fn_summary *, va_gc> *ipa_fn_summaries;
@@ -167,8 +168,7 @@ ipa_fn_summary::account_size_time (int size, sreal time,
bool found = false;
int i;
predicate nonconst_pred;
- vec<size_time_entry, va_gc> *table = call
- ? call_size_time_table : size_time_table;
+ vec<size_time_entry> *table = call ? &call_size_time_table : &size_time_table;
if (exec_pred == false)
return;
@@ -180,13 +180,13 @@ ipa_fn_summary::account_size_time (int size, sreal time,
/* We need to create initial empty unconditional clause, but otherwise
we don't need to account empty times and sizes. */
- if (!size && time == 0 && table)
+ if (!size && time == 0 && table->length ())
return;
/* Only for calls we are unaccounting what we previously recorded. */
gcc_checking_assert (time >= 0 || call);
- for (i = 0; vec_safe_iterate (table, i, &e); i++)
+ for (i = 0; table->iterate (i, &e); i++)
if (e->exec_predicate == exec_pred
&& e->nonconst_predicate == nonconst_pred)
{
@@ -226,9 +226,9 @@ ipa_fn_summary::account_size_time (int size, sreal time,
new_entry.exec_predicate = exec_pred;
new_entry.nonconst_predicate = nonconst_pred;
if (call)
- vec_safe_push (call_size_time_table, new_entry);
+ call_size_time_table.safe_push (new_entry);
else
- vec_safe_push (size_time_table, new_entry);
+ size_time_table.safe_push (new_entry);
}
else
{
@@ -752,8 +752,7 @@ ipa_fn_summary::~ipa_fn_summary ()
for (unsigned i = 0; i < len; i++)
edge_predicate_pool.remove ((*loop_strides)[i].predicate);
vec_free (conds);
- vec_free (size_time_table);
- vec_free (call_size_time_table);
+ call_size_time_table.release ();
vec_free (loop_iterations);
vec_free (loop_strides);
builtin_constant_p_parms.release ();
@@ -803,19 +802,19 @@ remap_freqcounting_preds_after_dup (vec<ipa_freqcounting_predicate, va_gc> *v,
void
ipa_fn_summary_t::duplicate (cgraph_node *src,
cgraph_node *dst,
- ipa_fn_summary *,
+ ipa_fn_summary *src_info,
ipa_fn_summary *info)
{
- new (info) ipa_fn_summary (*ipa_fn_summaries->get (src));
+ new (info) ipa_fn_summary (*src_info);
/* TODO: as an optimization, we may avoid copying conditions
that are known to be false or true. */
info->conds = vec_safe_copy (info->conds);
+ clone_info *cinfo = clone_info::get (dst);
/* When there are any replacements in the function body, see if we can figure
out that something was optimized out. */
- if (ipa_node_params_sum && dst->clone.tree_map)
+ if (ipa_node_params_sum && cinfo && cinfo->tree_map)
{
- vec<size_time_entry, va_gc> *entry = info->size_time_table;
/* Use SRC parm info since it may not be copied yet. */
class ipa_node_params *parms_info = IPA_NODE_REF (src);
ipa_auto_call_arg_values avals;
@@ -828,13 +827,13 @@ ipa_fn_summary_t::duplicate (cgraph_node *src,
bool inlined_to_p = false;
struct cgraph_edge *edge, *next;
- info->size_time_table = 0;
+ info->size_time_table.release ();
avals.m_known_vals.safe_grow_cleared (count, true);
for (i = 0; i < count; i++)
{
struct ipa_replace_map *r;
- for (j = 0; vec_safe_iterate (dst->clone.tree_map, j, &r); j++)
+ for (j = 0; vec_safe_iterate (cinfo->tree_map, j, &r); j++)
{
if (r->parm_num == i)
{
@@ -857,7 +856,7 @@ ipa_fn_summary_t::duplicate (cgraph_node *src,
to be false.
TODO: as on optimization, we can also eliminate conditions known
to be true. */
- for (i = 0; vec_safe_iterate (entry, i, &e); i++)
+ for (i = 0; src_info->size_time_table.iterate (i, &e); i++)
{
predicate new_exec_pred;
predicate new_nonconst_pred;
@@ -933,8 +932,8 @@ ipa_fn_summary_t::duplicate (cgraph_node *src,
}
else
{
- info->size_time_table = vec_safe_copy (info->size_time_table);
- info->loop_iterations = vec_safe_copy (info->loop_iterations);
+ info->size_time_table = src_info->size_time_table.copy ();
+ info->loop_iterations = vec_safe_copy (src_info->loop_iterations);
info->loop_strides = vec_safe_copy (info->loop_strides);
info->builtin_constant_p_parms
@@ -1103,7 +1102,7 @@ ipa_dump_fn_summary (FILE *f, struct cgraph_node *node)
fprintf (f, " estimated growth:%i\n", (int) s->growth);
if (s->scc_no)
fprintf (f, " In SCC: %i\n", (int) s->scc_no);
- for (i = 0; vec_safe_iterate (s->size_time_table, i, &e); i++)
+ for (i = 0; s->size_time_table.iterate (i, &e); i++)
{
fprintf (f, " size:%f, time:%f",
(double) e->size / ipa_fn_summary::size_scale,
@@ -1842,7 +1841,7 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
}
p_seg = add_condition (summary, params_summary, index,
- param_type, &aggpos, GT_EXPR,
+ param_type, &aggpos, GT_EXPR,
max, param_ops);
}
}
@@ -2593,8 +2592,8 @@ analyze_function_body (struct cgraph_node *node, bool early)
memset(&fbi, 0, sizeof(fbi));
vec_free (info->conds);
info->conds = NULL;
- vec_free (info->size_time_table);
- info->size_time_table = NULL;
+ info->size_time_table.release ();
+ info->call_size_time_table.release ();
/* When optimizing and analyzing for IPA inliner, initialize loop optimizer
so we can produce proper inline hints.
@@ -3372,7 +3371,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
if (use_table)
{
/* Build summary if it is absent. */
- if (!sum->call_size_time_table)
+ if (!sum->call_size_time_table.length ())
{
predicate true_pred = true;
sum->account_size_time (0, 0, true_pred, true_pred, true);
@@ -3383,13 +3382,13 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
sreal old_time = time ? *time : 0;
if (min_size)
- *min_size += (*sum->call_size_time_table)[0].size;
+ *min_size += sum->call_size_time_table[0].size;
unsigned int i;
size_time_entry *e;
/* Walk the table and account sizes and times. */
- for (i = 0; vec_safe_iterate (sum->call_size_time_table, i, &e);
+ for (i = 0; sum->call_size_time_table.iterate (i, &e);
i++)
if (e->exec_predicate.evaluate (possible_truths))
{
@@ -3402,7 +3401,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
if ((flag_checking || dump_file)
/* Do not try to sanity check when we know we lost some
precision. */
- && sum->call_size_time_table->length ()
+ && sum->call_size_time_table.length ()
< ipa_fn_summary::max_size_time_table_size)
{
estimate_calls_size_and_time_1 (node, &old_size, NULL, &old_time, NULL,
@@ -3692,8 +3691,8 @@ ipa_call_context::estimate_size_and_time (ipa_call_estimates *estimates,
sreal nonspecialized_time = time;
- min_size += (*info->size_time_table)[0].size;
- for (i = 0; vec_safe_iterate (info->size_time_table, i, &e); i++)
+ min_size += info->size_time_table[0].size;
+ for (i = 0; info->size_time_table.iterate (i, &e); i++)
{
bool exec = e->exec_predicate.evaluate (m_nonspec_possible_truths);
@@ -3739,8 +3738,8 @@ ipa_call_context::estimate_size_and_time (ipa_call_estimates *estimates,
gcc_checking_assert (time >= 0);
}
}
- gcc_checking_assert ((*info->size_time_table)[0].exec_predicate == true);
- gcc_checking_assert ((*info->size_time_table)[0].nonconst_predicate == true);
+ gcc_checking_assert (info->size_time_table[0].exec_predicate == true);
+ gcc_checking_assert (info->size_time_table[0].nonconst_predicate == true);
gcc_checking_assert (min_size >= 0);
gcc_checking_assert (size >= 0);
gcc_checking_assert (time >= 0);
@@ -4097,7 +4096,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
add_builtin_constant_p_parm (info, operand_map[ip]);
}
sreal freq = edge->sreal_frequency ();
- for (i = 0; vec_safe_iterate (callee_info->size_time_table, i, &e); i++)
+ for (i = 0; callee_info->size_time_table.iterate (i, &e); i++)
{
predicate p;
p = e->exec_predicate.remap_after_inlining
@@ -4144,7 +4143,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
info->estimated_stack_size = peak;
inline_update_callee_summaries (edge->callee, es->loop_depth);
- if (info->call_size_time_table)
+ if (info->call_size_time_table.length ())
{
int edge_size = 0;
sreal edge_time = 0;
@@ -4179,14 +4178,14 @@ ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset)
size_info->size = 0;
info->time = 0;
- for (i = 0; vec_safe_iterate (info->size_time_table, i, &e); i++)
+ for (i = 0; info->size_time_table.iterate (i, &e); i++)
{
size_info->size += e->size;
info->time += e->time;
}
- info->min_size = (*info->size_time_table)[0].size;
+ info->min_size = info->size_time_table[0].size;
if (reset)
- vec_free (info->call_size_time_table);
+ info->call_size_time_table.release ();
if (node->callees || node->indirect_calls)
estimate_calls_size_and_time (node, &size_info->size, &info->min_size,
&info->time, NULL,
@@ -4302,7 +4301,11 @@ read_ipa_call_summary (class lto_input_block *ib, struct cgraph_edge *e,
if (es)
edge_set_predicate (e, &p);
length = streamer_read_uhwi (ib);
- if (length && es && e->possibly_call_in_translation_unit_p ())
+ if (length && es
+ && (e->possibly_call_in_translation_unit_p ()
+ /* Also stream in jump functions to builtins in hope that they
+ will get fnspecs. */
+ || fndecl_built_in_p (e->callee->decl, BUILT_IN_NORMAL)))
{
es->param.safe_grow_cleared (length, true);
for (i = 0; i < length; i++)
@@ -4450,9 +4453,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
info->conds->quick_push (c);
}
count2 = streamer_read_uhwi (&ib);
- gcc_assert (!info || !info->size_time_table);
+ gcc_assert (!info || !info->size_time_table.length ());
if (info && count2)
- vec_safe_reserve_exact (info->size_time_table, count2);
+ info->size_time_table.reserve_exact (count2);
for (j = 0; j < count2; j++)
{
class size_time_entry e;
@@ -4463,7 +4466,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
e.nonconst_predicate.stream_in (&ib);
if (info)
- info->size_time_table->quick_push (e);
+ info->size_time_table.quick_push (e);
}
count2 = streamer_read_uhwi (&ib);
@@ -4526,6 +4529,7 @@ ipa_fn_summary_read (void)
struct lto_file_decl_data *file_data;
unsigned int j = 0;
+ ipa_prop_read_jump_functions ();
ipa_fn_summary_alloc ();
while ((file_data = file_data_vec[j++]))
@@ -4544,8 +4548,6 @@ ipa_fn_summary_read (void)
"ipa inline summary is missing in input file");
}
ipa_register_cgraph_hooks ();
- if (!flag_ipa_cp)
- ipa_prop_read_jump_functions ();
gcc_assert (ipa_fn_summaries);
ipa_fn_summaries->enable_insertion_hook ();
@@ -4657,8 +4659,8 @@ ipa_fn_summary_write (void)
}
}
}
- streamer_write_uhwi (ob, vec_safe_length (info->size_time_table));
- for (i = 0; vec_safe_iterate (info->size_time_table, i, &e); i++)
+ streamer_write_uhwi (ob, info->size_time_table.length ());
+ for (i = 0; info->size_time_table.iterate (i, &e); i++)
{
streamer_write_uhwi (ob, e->size);
e->time.stream_out (ob);
@@ -4693,8 +4695,7 @@ ipa_fn_summary_write (void)
produce_asm (ob, NULL);
destroy_output_block (ob);
- if (!flag_ipa_cp)
- ipa_prop_write_jump_functions ();
+ ipa_prop_write_jump_functions ();
}
diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h
index 3ecedb5..66984a9 100644
--- a/gcc/ipa-fnsummary.h
+++ b/gcc/ipa-fnsummary.h
@@ -72,7 +72,7 @@ struct agg_position_info
/* Representation of function body size and time depending on the call
context. We keep simple array of record, every containing of predicate
and time/size to account. */
-class GTY(()) size_time_entry
+class size_time_entry
{
public:
/* Predicate for code to be executed. */
@@ -82,7 +82,7 @@ public:
the executed code paths will simplify. */
predicate nonconst_predicate;
int size;
- sreal GTY((skip)) time;
+ sreal time;
};
/* Summary about function and stack frame sizes. We keep this info
@@ -129,7 +129,7 @@ public:
fp_expressions (false),
estimated_stack_size (false),
time (0), conds (NULL),
- size_time_table (NULL), call_size_time_table (NULL),
+ size_time_table (), call_size_time_table (vNULL),
loop_iterations (NULL), loop_strides (NULL),
builtin_constant_p_parms (vNULL),
growth (0), scc_no (0)
@@ -142,8 +142,8 @@ public:
inlinable (s.inlinable), single_caller (s.single_caller),
fp_expressions (s.fp_expressions),
estimated_stack_size (s.estimated_stack_size),
- time (s.time), conds (s.conds), size_time_table (s.size_time_table),
- call_size_time_table (NULL),
+ time (s.time), conds (s.conds), size_time_table (),
+ call_size_time_table (vNULL),
loop_iterations (s.loop_iterations), loop_strides (s.loop_strides),
builtin_constant_p_parms (s.builtin_constant_p_parms),
growth (s.growth), scc_no (s.scc_no)
@@ -181,8 +181,11 @@ public:
accounted in call_size_time_table. This is because calls
are often adjusted by IPA optimizations and thus this summary
is generated from call summary information when needed. */
- vec<size_time_entry, va_gc> *size_time_table;
- vec<size_time_entry, va_gc> *call_size_time_table;
+ auto_vec<size_time_entry> GTY((skip)) size_time_table;
+ /* Unlike size_time_table that is initialized for all summaries
+ call_size_time_table is allocated only for functions with
+ many calls. Use effecient vl_ptr storage. */
+ vec<size_time_entry, va_heap, vl_ptr> GTY((skip)) call_size_time_table;
/* Predicates on when some loops in the function can have known bounds. */
vec<ipa_freqcounting_predicate, va_gc> *loop_iterations;
diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c
index d5423a7..7e2b3c4 100644
--- a/gcc/ipa-icf-gimple.c
+++ b/gcc/ipa-icf-gimple.c
@@ -38,7 +38,9 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "cfgloop.h"
#include "attribs.h"
+#include "gimple-walk.h"
+#include "tree-ssa-alias-compare.h"
#include "ipa-icf-gimple.h"
namespace ipa_icf_gimple {
@@ -51,13 +53,13 @@ namespace ipa_icf_gimple {
of declarations that can be skipped. */
func_checker::func_checker (tree source_func_decl, tree target_func_decl,
- bool ignore_labels,
+ bool ignore_labels, bool tbaa,
hash_set<symtab_node *> *ignored_source_nodes,
hash_set<symtab_node *> *ignored_target_nodes)
: m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
m_ignored_source_nodes (ignored_source_nodes),
m_ignored_target_nodes (ignored_target_nodes),
- m_ignore_labels (ignore_labels)
+ m_ignore_labels (ignore_labels), m_tbaa (tbaa)
{
function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
@@ -109,7 +111,7 @@ func_checker::compare_ssa_name (const_tree t1, const_tree t2)
tree b1 = SSA_NAME_VAR (t1);
tree b2 = SSA_NAME_VAR (t2);
- return compare_operand (b1, b2);
+ return compare_operand (b1, b2, OP_NORMAL);
}
return true;
@@ -151,8 +153,21 @@ func_checker::compare_decl (const_tree t1, const_tree t2)
&& DECL_BY_REFERENCE (t1) != DECL_BY_REFERENCE (t2))
return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
- if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
- return return_false ();
+ /* We do not really need to check types of variables, since they are just
+ blocks of memory and we verify types of the accesses to them.
+ However do compare types of other kinds of decls
+ (parm decls and result decl types may affect ABI convetions). */
+ if (t != VAR_DECL)
+ {
+ if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ return return_false ();
+ }
+ else
+ {
+ if (!operand_equal_p (DECL_SIZE (t1), DECL_SIZE (t2),
+ OEP_MATCH_SIDE_EFFECTS))
+ return return_false_with_msg ("DECL_SIZEs are different");
+ }
bool existed_p;
const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
@@ -212,8 +227,8 @@ func_checker::compatible_types_p (tree t1, tree t2)
return true;
}
-/* Function compare for equality given trees T1 and T2 which
- can be either a constant or a declaration type. */
+/* Add hash of ARG to HSTATE. FLAGS have same meaning
+ as for operand_equal_p. Works only if operand acces type is OP_NORMAL. */
void
func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
@@ -227,13 +242,29 @@ func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
switch (TREE_CODE (arg))
{
+ case PARM_DECL:
+ {
+ unsigned int index = 0;
+ if (DECL_CONTEXT (arg))
+ for (tree p = DECL_ARGUMENTS (DECL_CONTEXT (arg));
+ p && index < 32; p = DECL_CHAIN (p), index++)
+ if (p == arg)
+ break;
+ hstate.add_int (PARM_DECL);
+ hstate.add_int (index);
+ }
+ return;
case FUNCTION_DECL:
case VAR_DECL:
case LABEL_DECL:
- case PARM_DECL:
case RESULT_DECL:
case CONST_DECL:
+ hstate.add_int (TREE_CODE (arg));
+ return;
case SSA_NAME:
+ hstate.add_int (SSA_NAME);
+ if (SSA_NAME_IS_DEFAULT_DEF (arg))
+ hash_operand (SSA_NAME_VAR (arg), hstate, flags);
return;
case FIELD_DECL:
inchash::add_expr (DECL_FIELD_OFFSET (arg), hstate, flags);
@@ -243,9 +274,36 @@ func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
break;
}
+ /* In gimple all clobbers can be considered equal: while comparaing two
+ gimple clobbers we match the left hand memory accesses. */
+ if (TREE_CLOBBER_P (arg))
+ {
+ hstate.add_int (0xc10bbe5);
+ return;
+ }
+ gcc_assert (!DECL_P (arg));
+ gcc_assert (!TYPE_P (arg));
+
return operand_compare::hash_operand (arg, hstate, flags);
}
+/* Add hash of ARG accesses according to ACCESS to HSTATE.
+ FLAGS have same meaning as for operand_equal_p. */
+
+void
+func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
+ unsigned int flags, operand_access_type access)
+{
+ if (access == OP_MEMORY)
+ {
+ ao_ref ref;
+ ao_ref_init (&ref, const_cast <tree> (arg));
+ return hash_ao_ref (&ref, lto_streaming_expected_p (), m_tbaa, hstate);
+ }
+ else
+ return hash_operand (arg, hstate, flags);
+}
+
bool
func_checker::operand_equal_p (const_tree t1, const_tree t2,
unsigned int flags)
@@ -287,28 +345,65 @@ func_checker::operand_equal_p (const_tree t1, const_tree t2,
default:
break;
}
+ /* In gimple all clobbers can be considered equal. We match the left hand
+ memory accesses. */
+ if (TREE_CLOBBER_P (t1) || TREE_CLOBBER_P (t2))
+ return TREE_CLOBBER_P (t1) == TREE_CLOBBER_P (t2);
return operand_compare::operand_equal_p (t1, t2, flags);
}
-/* Function responsible for comparison of various operands T1 and T2.
+/* Function responsible for comparison of various operands T1 and T2
+ which are accessed as ACCESS.
If these components, from functions FUNC1 and FUNC2, are equal, true
is returned. */
bool
-func_checker::compare_operand (tree t1, tree t2)
+func_checker::compare_operand (tree t1, tree t2, operand_access_type access)
{
if (!t1 && !t2)
return true;
else if (!t1 || !t2)
return false;
- if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
- return true;
- return return_false_with_msg ("operand_equal_p failed");
+ if (access == OP_MEMORY)
+ {
+ ao_ref ref1, ref2;
+ ao_ref_init (&ref1, const_cast <tree> (t1));
+ ao_ref_init (&ref2, const_cast <tree> (t2));
+ int flags = compare_ao_refs (&ref1, &ref2,
+ lto_streaming_expected_p (), m_tbaa);
+
+ if (!flags)
+ return true;
+ if (flags & SEMANTICS)
+ return return_false_with_msg
+ ("compare_ao_refs failed (semantic difference)");
+ if (flags & BASE_ALIAS_SET)
+ return return_false_with_msg
+ ("compare_ao_refs failed (base alias set difference)");
+ if (flags & REF_ALIAS_SET)
+ return return_false_with_msg
+ ("compare_ao_refs failed (ref alias set difference)");
+ if (flags & ACCESS_PATH)
+ return return_false_with_msg
+ ("compare_ao_refs failed (access path difference)");
+ if (flags & DEPENDENCE_CLIQUE)
+ return return_false_with_msg
+ ("compare_ao_refs failed (dependence clique difference)");
+ gcc_unreachable ();
+ }
+ else
+ {
+ if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
+ return true;
+ return return_false_with_msg
+ ("operand_equal_p failed");
+ }
}
bool
-func_checker::compare_asm_inputs_outputs (tree t1, tree t2)
+func_checker::compare_asm_inputs_outputs (tree t1, tree t2,
+ operand_access_type_map *map)
{
gcc_assert (TREE_CODE (t1) == TREE_LIST);
gcc_assert (TREE_CODE (t2) == TREE_LIST);
@@ -318,7 +413,8 @@ func_checker::compare_asm_inputs_outputs (tree t1, tree t2)
if (!t2)
return false;
- if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2)))
+ if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2),
+ get_operand_access_type (map, t1)))
return return_false ();
tree p1 = TREE_PURPOSE (t1);
@@ -545,9 +641,12 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
return false;
+ operand_access_type_map map (5);
+ classify_operands (s1, &map);
+
t1 = gimple_call_fn (s1);
t2 = gimple_call_fn (s2);
- if (!compare_operand (t1, t2))
+ if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
return return_false ();
/* Compare flags. */
@@ -567,10 +666,17 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
tree fntype1 = gimple_call_fntype (s1);
tree fntype2 = gimple_call_fntype (s2);
- if ((fntype1 && !fntype2)
- || (!fntype1 && fntype2)
- || (fntype1 && !types_compatible_p (fntype1, fntype2)))
- return return_false_with_msg ("call function types are not compatible");
+
+ /* For direct calls we verify that types are comopatible so if we matced
+ callees, callers must match, too. For indirect calls however verify
+ function type. */
+ if (!gimple_call_fndecl (s1))
+ {
+ if ((fntype1 && !fntype2)
+ || (!fntype1 && fntype2)
+ || (fntype1 && !types_compatible_p (fntype1, fntype2)))
+ return return_false_with_msg ("call function types are not compatible");
+ }
if (fntype1 && fntype2 && comp_type_attributes (fntype1, fntype2) != 1)
return return_false_with_msg ("different fntype attributes");
@@ -579,7 +685,8 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
tree chain2 = gimple_call_chain (s2);
if ((chain1 && !chain2)
|| (!chain1 && chain2)
- || !compare_operand (chain1, chain2))
+ || !compare_operand (chain1, chain2,
+ get_operand_access_type (&map, chain1)))
return return_false_with_msg ("static call chains are different");
/* Checking of argument. */
@@ -588,7 +695,7 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
t1 = gimple_call_arg (s1, i);
t2 = gimple_call_arg (s2, i);
- if (!compare_operand (t1, t2))
+ if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
return return_false_with_msg ("GIMPLE call operands are different");
}
@@ -596,7 +703,7 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
t1 = gimple_get_lhs (s1);
t2 = gimple_get_lhs (s2);
- return compare_operand (t1, t2);
+ return compare_operand (t1, t2, get_operand_access_type (&map, t1));
}
@@ -610,31 +717,28 @@ func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
tree_code code1, code2;
unsigned i;
- code1 = gimple_expr_code (s1);
- code2 = gimple_expr_code (s2);
-
- if (code1 != code2)
- return false;
-
code1 = gimple_assign_rhs_code (s1);
code2 = gimple_assign_rhs_code (s2);
if (code1 != code2)
return false;
+ operand_access_type_map map (5);
+ classify_operands (s1, &map);
+
for (i = 0; i < gimple_num_ops (s1); i++)
{
arg1 = gimple_op (s1, i);
arg2 = gimple_op (s2, i);
/* Compare types for LHS. */
- if (i == 0)
+ if (i == 0 && !gimple_store_p (s1))
{
if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
- return return_false_with_msg ("GIMPLE NOP LHS type mismatch");
+ return return_false_with_msg ("GIMPLE LHS type mismatch");
}
- if (!compare_operand (arg1, arg2))
+ if (!compare_operand (arg1, arg2, get_operand_access_type (&map, arg1)))
return return_false_with_msg ("GIMPLE assignment operands "
"are different");
}
@@ -652,8 +756,8 @@ func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
tree t1, t2;
tree_code code1, code2;
- code1 = gimple_expr_code (s1);
- code2 = gimple_expr_code (s2);
+ code1 = gimple_cond_code (s1);
+ code2 = gimple_cond_code (s2);
if (code1 != code2)
return false;
@@ -661,13 +765,13 @@ func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
t1 = gimple_cond_lhs (s1);
t2 = gimple_cond_lhs (s2);
- if (!compare_operand (t1, t2))
+ if (!compare_operand (t1, t2, OP_NORMAL))
return false;
t1 = gimple_cond_rhs (s1);
t2 = gimple_cond_rhs (s2);
- return compare_operand (t1, t2);
+ return compare_operand (t1, t2, OP_NORMAL);
}
/* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
@@ -706,7 +810,7 @@ func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
tree t1 = gimple_switch_index (g1);
tree t2 = gimple_switch_index (g2);
- if (!compare_operand (t1, t2))
+ if (!compare_operand (t1, t2, OP_NORMAL))
return false;
for (i = 0; i < lsize1; i++)
@@ -733,7 +837,7 @@ func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
label1 = CASE_LABEL (label1);
label2 = CASE_LABEL (label2);
- if (!compare_operand (label1, label2))
+ if (!compare_operand (label1, label2, OP_NORMAL))
return return_false_with_msg ("switch label_exprs are different");
}
else if (!tree_int_cst_equal (label1, label2))
@@ -758,7 +862,10 @@ func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
if (t1 == NULL && t2 == NULL)
return true;
else
- return compare_operand (t1, t2);
+ {
+ operand_access_type_map map (3);
+ return compare_operand (t1, t2, get_operand_access_type (&map, t1));
+ }
}
/* Verifies for given GIMPLEs S1 and S2 that
@@ -775,7 +882,7 @@ func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
return false;
- return compare_operand (dest1, dest2);
+ return compare_operand (dest1, dest2, OP_NORMAL);
}
/* Verifies for given GIMPLE_RESX stmts S1 and S2 that
@@ -819,12 +926,15 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
return return_false_with_msg ("ASM strings are different");
+ operand_access_type_map map (5);
+ classify_operands (g1, &map);
+
for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
{
tree input1 = gimple_asm_input_op (g1, i);
tree input2 = gimple_asm_input_op (g2, i);
- if (!compare_asm_inputs_outputs (input1, input2))
+ if (!compare_asm_inputs_outputs (input1, input2, &map))
return return_false_with_msg ("ASM input is different");
}
@@ -833,7 +943,7 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
tree output1 = gimple_asm_output_op (g1, i);
tree output2 = gimple_asm_output_op (g2, i);
- if (!compare_asm_inputs_outputs (output1, output2))
+ if (!compare_asm_inputs_outputs (output1, output2, &map))
return return_false_with_msg ("ASM output is different");
}
@@ -850,4 +960,35 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
return true;
}
+/* Helper for func_checker::classify_operands. Record that T is a load. */
+
+static bool
+visit_load_store (gimple *, tree, tree t, void *data)
+{
+ func_checker::operand_access_type_map *map =
+ (func_checker::operand_access_type_map *) data;
+ map->add (t);
+ return false;
+}
+
+/* Compute hash map determining access types of operands. */
+
+void
+func_checker::classify_operands (const gimple *stmt,
+ operand_access_type_map *map)
+{
+ walk_stmt_load_store_ops (const_cast <gimple *> (stmt),
+ (void *)map, visit_load_store, visit_load_store);
+}
+
+/* Return access type of a given operand. */
+
+func_checker::operand_access_type
+func_checker::get_operand_access_type (operand_access_type_map *map, tree t)
+{
+ if (map->contains (t))
+ return OP_MEMORY;
+ return OP_NORMAL;
+}
+
} // ipa_icf_gimple namespace
diff --git a/gcc/ipa-icf-gimple.h b/gcc/ipa-icf-gimple.h
index 28459d2..40f7474 100644
--- a/gcc/ipa-icf-gimple.h
+++ b/gcc/ipa-icf-gimple.h
@@ -118,14 +118,14 @@ public:
/* A class aggregating all connections and semantic equivalents
for a given pair of semantic function candidates. */
-class func_checker : operand_compare
+class func_checker : ao_compare
{
public:
/* Default constructor. */
func_checker ():
m_source_func_decl (NULL_TREE), m_target_func_decl (NULL_TREE),
m_ignored_source_nodes (NULL), m_ignored_target_nodes (NULL),
- m_ignore_labels (false)
+ m_ignore_labels (false), m_tbaa (true)
{
m_source_ssa_names.create (0);
m_target_ssa_names.create (0);
@@ -139,6 +139,7 @@ public:
of declarations that can be skipped. */
func_checker (tree source_func_decl, tree target_func_decl,
bool ignore_labels = false,
+ bool tbaa = true,
hash_set<symtab_node *> *ignored_source_nodes = NULL,
hash_set<symtab_node *> *ignored_target_nodes = NULL);
@@ -200,14 +201,19 @@ public:
/* Verification function for declaration trees T1 and T2. */
bool compare_decl (const_tree t1, const_tree t2);
+ /* Compute hash map MAP that determines loads and stores of STMT. */
+ enum operand_access_type {OP_MEMORY, OP_NORMAL};
+ typedef hash_set<tree> operand_access_type_map;
+
/* Function responsible for comparison of various operands T1 and T2.
If these components, from functions FUNC1 and FUNC2, are equal, true
is returned. */
- bool compare_operand (tree t1, tree t2);
+ bool compare_operand (tree t1, tree t2, operand_access_type type);
/* Compares GIMPLE ASM inputs (or outputs) where we iterate tree chain
and compare both TREE_PURPOSEs and TREE_VALUEs. */
- bool compare_asm_inputs_outputs (tree t1, tree t2);
+ bool compare_asm_inputs_outputs (tree t1, tree t2,
+ operand_access_type_map *map);
/* Verifies that trees T1 and T2, representing function declarations
are equivalent from perspective of ICF. */
@@ -230,7 +236,13 @@ public:
first parameter of a function. */
static bool compatible_types_p (tree t1, tree t2);
+ /* Compute hash map determining access types of operands. */
+ static void classify_operands (const gimple *stmt,
+ operand_access_type_map *map);
+ /* Return access type of a given operand. */
+ static operand_access_type get_operand_access_type
+ (operand_access_type_map *map, tree);
private:
/* Vector mapping source SSA names to target ones. */
vec <int> m_source_ssa_names;
@@ -264,6 +276,9 @@ private:
/* Flag if ignore labels in comparison. */
bool m_ignore_labels;
+ /* Flag if we should compare type based alias analysis info. */
+ bool m_tbaa;
+
public:
/* Return true if two operands are equal. The flags fields can be used
to specify OEP flags described above. */
@@ -272,6 +287,8 @@ public:
/* Generate a hash value for an expression. This can be used iteratively
by passing a previous result as the HSTATE argument. */
virtual void hash_operand (const_tree, inchash::hash &, unsigned flags);
+ void hash_operand (const_tree, inchash::hash &, unsigned flags,
+ operand_access_type access);
};
} // ipa_icf_gimple namespace
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 8cae076..5bbbec6 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
#include "coverage.h"
#include "gimple-pretty-print.h"
#include "data-streamer.h"
+#include "tree-streamer.h"
#include "fold-const.h"
#include "calls.h"
#include "varasm.h"
@@ -78,6 +79,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "print-tree.h"
#include "ipa-utils.h"
+#include "tree-ssa-alias-compare.h"
#include "ipa-icf-gimple.h"
#include "fibonacci_heap.h"
#include "ipa-icf.h"
@@ -85,6 +87,7 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "tree-vector-builder.h"
#include "symtab-thunks.h"
+#include "alias.h"
using namespace ipa_icf_gimple;
@@ -226,14 +229,16 @@ hash_map<const_tree, hashval_t> sem_item::m_type_hash_cache;
/* Semantic function constructor that uses STACK as bitmap memory stack. */
sem_function::sem_function (bitmap_obstack *stack)
-: sem_item (FUNC, stack), m_checker (NULL), m_compared_func (NULL)
+ : sem_item (FUNC, stack), memory_access_types (), m_alias_sets_hash (0),
+ m_checker (NULL), m_compared_func (NULL)
{
bb_sizes.create (0);
bb_sorted.create (0);
}
sem_function::sem_function (cgraph_node *node, bitmap_obstack *stack)
-: sem_item (FUNC, node, stack), m_checker (NULL), m_compared_func (NULL)
+ : sem_item (FUNC, node, stack), memory_access_types (),
+ m_alias_sets_hash (0), m_checker (NULL), m_compared_func (NULL)
{
bb_sizes.create (0);
bb_sorted.create (0);
@@ -570,6 +575,7 @@ sem_function::equals_wpa (sem_item *item,
type memory location for ipa-polymorphic-call and we do not want
it to get confused by wrong type. */
if (DECL_CXX_CONSTRUCTOR_P (decl)
+ && opt_for_fn (decl, flag_devirtualize)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{
if (TREE_CODE (TREE_TYPE (item->decl)) != METHOD_TYPE)
@@ -843,6 +849,8 @@ sem_function::equals_private (sem_item *item)
m_checker = new func_checker (decl, m_compared_func->decl,
false,
+ opt_for_fn (m_compared_func->decl,
+ flag_strict_aliasing),
&refs_set,
&m_compared_func->refs_set);
arg1 = DECL_ARGUMENTS (decl);
@@ -1419,33 +1427,53 @@ sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
{
case GIMPLE_SWITCH:
m_checker->hash_operand (gimple_switch_index (as_a <gswitch *> (stmt)),
- hstate, 0);
+ hstate, 0, func_checker::OP_NORMAL);
break;
case GIMPLE_ASSIGN:
hstate.add_int (gimple_assign_rhs_code (stmt));
- if (commutative_tree_code (gimple_assign_rhs_code (stmt))
- || commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
- {
- m_checker->hash_operand (gimple_assign_rhs1 (stmt), hstate, 0);
- m_checker->hash_operand (gimple_assign_rhs2 (stmt), hstate, 0);
- if (commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
- m_checker->hash_operand (gimple_assign_rhs3 (stmt), hstate, 0);
- m_checker->hash_operand (gimple_assign_lhs (stmt), hstate, 0);
- }
/* fall through */
case GIMPLE_CALL:
case GIMPLE_ASM:
case GIMPLE_COND:
case GIMPLE_GOTO:
case GIMPLE_RETURN:
- /* All these statements are equivalent if their operands are. */
- for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
- m_checker->hash_operand (gimple_op (stmt, i), hstate, 0);
- /* Consider nocf_check attribute in hash as it affects code
- generation. */
- if (code == GIMPLE_CALL
- && flag_cf_protection & CF_BRANCH)
- hstate.add_flag (gimple_call_nocf_check_p (as_a <gcall *> (stmt)));
+ {
+ func_checker::operand_access_type_map map (5);
+ func_checker::classify_operands (stmt, &map);
+
+ /* All these statements are equivalent if their operands are. */
+ for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
+ {
+ func_checker::operand_access_type
+ access_type = func_checker::get_operand_access_type
+ (&map, gimple_op (stmt, i));
+ m_checker->hash_operand (gimple_op (stmt, i), hstate, 0,
+ access_type);
+ /* For memory accesses when hasing for LTO stremaing record
+ base and ref alias ptr types so we can compare them at WPA
+ time without having to read actual function body. */
+ if (access_type == func_checker::OP_MEMORY
+ && lto_streaming_expected_p ()
+ && flag_strict_aliasing)
+ {
+ ao_ref ref;
+
+ ao_ref_init (&ref, gimple_op (stmt, i));
+ tree t = ao_ref_alias_ptr_type (&ref);
+ if (!variably_modified_type_p (t, NULL_TREE))
+ memory_access_types.safe_push (t);
+ t = ao_ref_base_alias_ptr_type (&ref);
+ if (!variably_modified_type_p (t, NULL_TREE))
+ memory_access_types.safe_push (t);
+ }
+ }
+ /* Consider nocf_check attribute in hash as it affects code
+ generation. */
+ if (code == GIMPLE_CALL
+ && flag_cf_protection & CF_BRANCH)
+ hstate.add_flag (gimple_call_nocf_check_p (as_a <gcall *> (stmt)));
+ }
+ break;
default:
break;
}
@@ -1534,7 +1562,8 @@ sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
tree phi_result1 = gimple_phi_result (phi1);
tree phi_result2 = gimple_phi_result (phi2);
- if (!m_checker->compare_operand (phi_result1, phi_result2))
+ if (!m_checker->compare_operand (phi_result1, phi_result2,
+ func_checker::OP_NORMAL))
return return_false_with_msg ("PHI results are different");
size1 = gimple_phi_num_args (phi1);
@@ -1548,7 +1577,7 @@ sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
t1 = gimple_phi_arg (phi1, i)->def;
t2 = gimple_phi_arg (phi2, i)->def;
- if (!m_checker->compare_operand (t1, t2))
+ if (!m_checker->compare_operand (t1, t2, func_checker::OP_NORMAL))
return return_false ();
e1 = gimple_phi_arg_edge (phi1, i);
@@ -2126,6 +2155,14 @@ sem_item_optimizer::write_summary (void)
streamer_write_uhwi_stream (ob->main_stream, node_ref);
streamer_write_uhwi (ob, (*item)->get_hash ());
+
+ if ((*item)->type == FUNC)
+ {
+ sem_function *fn = static_cast<sem_function *> (*item);
+ streamer_write_uhwi (ob, fn->memory_access_types.length ());
+ for (unsigned i = 0; i < fn->memory_access_types.length (); i++)
+ stream_write_tree (ob, fn->memory_access_types[i], true);
+ }
}
}
@@ -2177,6 +2214,18 @@ sem_item_optimizer::read_section (lto_file_decl_data *file_data,
cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
sem_function *fn = new sem_function (cnode, &m_bmstack);
+ unsigned count = streamer_read_uhwi (&ib_main);
+ inchash::hash hstate (0);
+ if (flag_incremental_link == INCREMENTAL_LINK_LTO)
+ fn->memory_access_types.reserve_exact (count);
+ for (unsigned i = 0; i < count; i++)
+ {
+ tree type = stream_read_tree (&ib_main, data_in);
+ hstate.add_int (get_deref_alias_set (type));
+ if (flag_incremental_link == INCREMENTAL_LINK_LTO)
+ fn->memory_access_types.quick_push (type);
+ }
+ fn->m_alias_sets_hash = hstate.end ();
fn->set_hash (hash);
m_items.safe_push (fn);
}
@@ -2373,6 +2422,7 @@ sem_item_optimizer::execute (void)
build_graph ();
update_hash_by_addr_refs ();
+ update_hash_by_memory_access_type ();
build_hash_based_classes ();
if (dump_file)
@@ -2487,11 +2537,24 @@ sem_item_optimizer::update_hash_by_addr_refs ()
= TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl));
inchash::hash hstate (m_items[i]->get_hash ());
+ /* Hash ODR types by mangled name if it is defined.
+ If not we know that type is anonymous of free_lang_data
+ was not run and in that case type main variants are
+ unique. */
if (TYPE_NAME (class_type)
- && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (class_type)))
+ && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (class_type))
+ && !type_in_anonymous_namespace_p
+ (class_type))
hstate.add_hwi
(IDENTIFIER_HASH_VALUE
(DECL_ASSEMBLER_NAME (TYPE_NAME (class_type))));
+ else
+ {
+ gcc_checking_assert
+ (!in_lto_p
+ || type_in_anonymous_namespace_p (class_type));
+ hstate.add_hwi (TYPE_UID (TYPE_MAIN_VARIANT (class_type)));
+ }
m_items[i]->set_hash (hstate.end ());
}
@@ -2510,6 +2573,21 @@ sem_item_optimizer::update_hash_by_addr_refs ()
m_items[i]->set_hash (m_items[i]->global_hash);
}
+void
+sem_item_optimizer::update_hash_by_memory_access_type ()
+{
+ for (unsigned i = 0; i < m_items.length (); i++)
+ {
+ if (m_items[i]->type == FUNC)
+ {
+ sem_function *fn = static_cast<sem_function *> (m_items[i]);
+ inchash::hash hstate (fn->get_hash ());
+ hstate.add_int (fn->m_alias_sets_hash);
+ fn->set_hash (hstate.end ());
+ }
+ }
+}
+
/* Congruence classes are built by hash value. */
void
diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h
index 6dc1a13..3e0e724 100644
--- a/gcc/ipa-icf.h
+++ b/gcc/ipa-icf.h
@@ -371,12 +371,19 @@ public:
/* GIMPLE codes hash value. */
hashval_t gcode_hash;
+ /* Vector of subpart of memory access types. */
+ vec<tree> memory_access_types;
+
/* Total number of SSA names used in the function. */
unsigned ssa_names_size;
/* Array of structures for all basic blocks. */
vec <ipa_icf_gimple::sem_bb *> bb_sorted;
+ /* Hash of canonical types used for memory references in the
+ function. */
+ hashval_t m_alias_sets_hash;
+
/* Return true if parameter I may be used. */
bool param_used_p (unsigned int i);
@@ -541,6 +548,9 @@ private:
/* For each semantic item, append hash values of references. */
void update_hash_by_addr_refs ();
+ /* Update hash by canonical types of memory accesses. */
+ void update_hash_by_memory_access_type ();
+
/* Congruence classes are built by hash value. */
void build_hash_based_classes (void);
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index acbf82e..bd0e322 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -127,6 +127,9 @@ initialize_growth_caches ()
= new fast_call_summary<edge_growth_cache_entry *, va_heap> (symtab);
node_context_cache
= new fast_function_summary<node_context_summary *, va_heap> (symtab);
+ edge_growth_cache->disable_duplication_hook ();
+ node_context_cache->disable_insertion_hook ();
+ node_context_cache->disable_duplication_hook ();
}
/* Free growth caches. */
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 3782cce..907a95c 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-modref-tree.h"
#include "ipa-modref.h"
#include "symtab-thunks.h"
+#include "symtab-clones.h"
int ncalls_inlined;
int nfunctions_inlined;
@@ -231,6 +232,11 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
e->callee->remove_from_same_comdat_group ();
e->callee->inlined_to = inlining_into;
+ if (e->callee->ipa_transforms_to_apply.length ())
+ {
+ e->callee->ipa_transforms_to_apply.release ();
+ e->callee->ipa_transforms_to_apply = vNULL;
+ }
/* Recursively clone all bodies. */
for (e = e->callee->callees; e; e = next)
@@ -606,7 +612,10 @@ save_inline_function_body (struct cgraph_node *node)
tree prev_body_holder = node->decl;
if (!ipa_saved_clone_sources)
- ipa_saved_clone_sources = new function_summary <tree *> (symtab);
+ {
+ ipa_saved_clone_sources = new function_summary <tree *> (symtab);
+ ipa_saved_clone_sources->disable_insertion_hook ();
+ }
else
{
tree *p = ipa_saved_clone_sources->get (node);
@@ -687,6 +696,31 @@ preserve_function_body_p (struct cgraph_node *node)
return false;
}
+/* tree-inline can not recurse; materialize all function bodie we will need
+ during inlining. This includes inlined functions, but also called functions
+ with param manipulation because IPA param manipulation attaches debug
+ statements to PARM_DECLs of called clone. Materialize them if needed.
+
+ FIXME: This is somehwat broken by design because it does not play well
+ with partitioning. */
+
+static void
+maybe_materialize_called_clones (cgraph_node *node)
+{
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ clone_info *info;
+
+ if (!e->inline_failed)
+ maybe_materialize_called_clones (e->callee);
+
+ cgraph_node *callee = cgraph_node::get (e->callee->decl);
+ if (callee->clone_of
+ && (info = clone_info::get (callee)) && info->param_adjustments)
+ callee->get_untransformed_body ();
+ }
+}
+
/* Apply inline plan to function. */
unsigned int
@@ -708,6 +742,7 @@ inline_transform (struct cgraph_node *node)
if (n->decl != node->decl)
n->materialize_clone ();
}
+ node->clear_stmts_in_references ();
/* We might need the body of this function so that we can expand
it inline somewhere else. */
@@ -739,6 +774,7 @@ inline_transform (struct cgraph_node *node)
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count;
}
+ maybe_materialize_called_clones (node);
for (e = node->callees; e; e = next)
{
if (!e->inline_failed)
diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h
index b37280d..7d5acb1 100644
--- a/gcc/ipa-modref-tree.h
+++ b/gcc/ipa-modref-tree.h
@@ -23,17 +23,17 @@ along with GCC; see the file COPYING3. If not see
call. For every function we collect two trees, one for loads and other
for stores. Tree consist of following levels:
- 1) Base: this level represent base alias set of the acecess and refers
+ 1) Base: this level represent base alias set of the access and refers
to sons (ref nodes). Flag all_refs means that all possible references
are aliasing.
- Because for LTO streaming we need to stream types rahter than alias sets
+ Because for LTO streaming we need to stream types rather than alias sets
modref_base_node is implemented as a template.
- 2) Ref: this level represent ref alias set and links to acesses unless
- all_refs flag is et.
+ 2) Ref: this level represent ref alias set and links to accesses unless
+ all_refs flag is set.
Again ref is an template to allow LTO streaming.
3) Access: this level represent info about individual accesses. Presently
- we record whether access is trhough a dereference of a function parameter
+ we record whether access is through a dereference of a function parameter
*/
#ifndef GCC_MODREF_TREE_H
@@ -50,7 +50,7 @@ struct GTY(()) modref_access_node
poly_int64 size;
poly_int64 max_size;
- /* Offset from parmeter pointer to the base of the access (in bytes). */
+ /* Offset from parameter pointer to the base of the access (in bytes). */
poly_int64 parm_offset;
/* Index of parameter which specifies the base of access. -1 if base is not
@@ -240,7 +240,7 @@ struct modref_parm_map
{
/* Index of parameter we translate to.
-1 indicates that parameter is unknown
- -2 indicates that parmaeter points to local memory and access can be
+ -2 indicates that parameter points to local memory and access can be
discarded. */
int parm_index;
bool parm_offset_known;
@@ -333,7 +333,7 @@ struct GTY((user)) modref_tree
/* If we failed to insert ref, just see if there is a cleanup possible. */
if (!ref_node)
{
- /* No useful ref information and no useful base; collapse everyting. */
+ /* No useful ref information and no useful base; collapse everything. */
if (!base && base_node->every_ref)
{
collapse ();
@@ -367,7 +367,7 @@ struct GTY((user)) modref_tree
return changed;
}
- /* Remove tree branches that are not useful (i.e. they will allways pass). */
+ /* Remove tree branches that are not useful (i.e. they will always pass). */
void cleanup ()
{
@@ -544,6 +544,32 @@ struct GTY((user)) modref_tree
{
collapse ();
}
+
+ /* Update parameter indexes in TT according to MAP. */
+ void
+ remap_params (vec <int> *map)
+ {
+ size_t i;
+ modref_base_node <T> *base_node;
+ FOR_EACH_VEC_SAFE_ELT (bases, i, base_node)
+ {
+ size_t j;
+ modref_ref_node <T> *ref_node;
+ FOR_EACH_VEC_SAFE_ELT (base_node->refs, j, ref_node)
+ {
+ size_t k;
+ modref_access_node *access_node;
+ FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node)
+ if (access_node->parm_index > 0)
+ {
+ if (access_node->parm_index < (int)map->length ())
+ access_node->parm_index = (*map)[access_node->parm_index];
+ else
+ access_node->parm_index = -1;
+ }
+ }
+ }
+ }
};
void modref_c_tests ();
diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index 3a70965..388b229 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -20,11 +20,10 @@ along with GCC; see the file COPYING3. If not see
/* Mod/ref pass records summary about loads and stores performed by the
function. This is later used by alias analysis to disambiguate memory
- accesses across function calls. The summary has a form of decision tree
- described in ipa-modref-tree.h.
+ accesses across function calls.
This file contains a tree pass and an IPA pass. Both performs the same
- analys however tree pass is executed during early and late optimization
+ analysis however tree pass is executed during early and late optimization
passes to propagate info downwards in the compilation order. IPA pass
propagates across the callgraph and is able to handle recursion and works on
whole program during link-time analysis.
@@ -32,8 +31,27 @@ along with GCC; see the file COPYING3. If not see
LTO mode differs from the local mode by not recording alias sets but types
that are translated to alias sets later. This is necessary in order stream
the information because the alias sets are rebuild at stream-in time and may
- not correspond to ones seen during analysis. For this reason part of analysis
- is duplicated. */
+ not correspond to ones seen during analysis. For this reason part of
+ analysis is duplicated.
+
+ The following information is computed
+ 1) load/store access tree described in ipa-modref-tree.h
+ This is used by tree-ssa-alias to disambiguate load/dtores
+ 2) EAF flags used by points-to analysis (in tree-ssa-structlias).
+ and defined in tree-core.h.
+ and stored to optimization_summaries.
+
+ There are multiple summaries computed and used during the propagation:
+ - summaries holds summaries from analysis to IPA propagation
+ time.
+ - summaries_lto is same as summaries but holds them in a format
+ that can be streamed (as described above).
+ - fnspec_summary holds fnspec strings for call. This is
+ necessary because gimple_call_fnspec performs additional
+ analysis except for looking callee fndecl.
+ - escape_summary holds escape points for given call edge.
+ That is a vector recording what function parmaeters
+ may escape to a function call (and with what parameter index). */
#include "config.h"
#include "system.h"
@@ -59,9 +77,128 @@ along with GCC; see the file COPYING3. If not see
#include "value-range.h"
#include "ipa-prop.h"
#include "ipa-fnsummary.h"
+#include "attr-fnspec.h"
+#include "symtab-clones.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "tree-ssa-operands.h"
+#include "ssa-iterators.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
+
+namespace {
+
+/* We record fnspec specifiers for call edges since they depends on actual
+ gimple statements. */
+
+class fnspec_summary
+{
+public:
+ char *fnspec;
+
+ fnspec_summary ()
+ : fnspec (NULL)
+ {
+ }
+
+ ~fnspec_summary ()
+ {
+ free (fnspec);
+ }
+};
+
+/* Summary holding fnspec string for a given call. */
+
+class fnspec_summaries_t : public call_summary <fnspec_summary *>
+{
+public:
+ fnspec_summaries_t (symbol_table *symtab)
+ : call_summary <fnspec_summary *> (symtab) {}
+ /* Hook that is called by summary when an edge is duplicated. */
+ virtual void duplicate (cgraph_edge *,
+ cgraph_edge *,
+ fnspec_summary *src,
+ fnspec_summary *dst)
+ {
+ dst->fnspec = xstrdup (src->fnspec);
+ }
+};
+
+static fnspec_summaries_t *fnspec_summaries = NULL;
+
+/* Escape summary holds a vector of param indexes that escape to
+ a given call. */
+struct escape_entry
+{
+ /* Parameter that escapes at a given call. */
+ unsigned int parm_index;
+ /* Argument it escapes to. */
+ unsigned int arg;
+ /* Minimal flags known about the argument. */
+ char min_flags;
+ /* Does it escape directly or indirectly? */
+ bool direct;
+};
+
+/* Dump EAF flags. */
+
+static void
+dump_eaf_flags (FILE *out, int flags, bool newline = true)
+{
+ if (flags & EAF_DIRECT)
+ fprintf (out, " direct");
+ if (flags & EAF_NOCLOBBER)
+ fprintf (out, " noclobber");
+ if (flags & EAF_NOESCAPE)
+ fprintf (out, " noescape");
+ if (flags & EAF_NODIRECTESCAPE)
+ fprintf (out, " nodirectescape");
+ if (flags & EAF_UNUSED)
+ fprintf (out, " unused");
+ if (newline)
+ fprintf (out, "\n");
+}
+
+struct escape_summary
+{
+ auto_vec <escape_entry> esc;
+ void dump (FILE *out)
+ {
+ for (unsigned int i = 0; i < esc.length (); i++)
+ {
+ fprintf (out, " parm %i arg %i %s min:",
+ esc[i].parm_index,
+ esc[i].arg,
+ esc[i].direct ? "(direct)" : "(indirect)");
+ dump_eaf_flags (out, esc[i].min_flags, false);
+ }
+ fprintf (out, "\n");
+ }
+};
+
+class escape_summaries_t : public call_summary <escape_summary *>
+{
+public:
+ escape_summaries_t (symbol_table *symtab)
+ : call_summary <escape_summary *> (symtab) {}
+ /* Hook that is called by summary when an edge is duplicated. */
+ virtual void duplicate (cgraph_edge *,
+ cgraph_edge *,
+ escape_summary *src,
+ escape_summary *dst)
+ {
+ dst->esc = src->esc.copy ();
+ }
+};
+
+static escape_summaries_t *escape_summaries = NULL;
+
+} /* ANON namespace: GTY annotated summaries can not be anonymous. */
+
/* Class (from which there is one global instance) that holds modref summaries
for all analyzed functions. */
+
class GTY((user)) modref_summaries
: public fast_function_summary <modref_summary *, va_gc>
{
@@ -84,6 +221,7 @@ class modref_summary_lto;
/* Class (from which there is one global instance) that holds modref summaries
for all analyzed functions. */
+
class GTY((user)) modref_summaries_lto
: public fast_function_summary <modref_summary_lto *, va_gc>
{
@@ -106,23 +244,26 @@ public:
/* Global variable holding all modref summaries
(from analysis to IPA propagation time). */
+
static GTY(()) fast_function_summary <modref_summary *, va_gc>
*summaries;
-/* Global variable holding all modref optimizaiton summaries
+/* Global variable holding all modref optimization summaries
(from IPA propagation time or used by local optimization pass). */
+
static GTY(()) fast_function_summary <modref_summary *, va_gc>
*optimization_summaries;
/* LTO summaries hold info from analysis to LTO streaming or from LTO
stream-in through propagation to LTO stream-out. */
+
static GTY(()) fast_function_summary <modref_summary_lto *, va_gc>
*summaries_lto;
/* Summary for a single function which this pass produces. */
modref_summary::modref_summary ()
- : loads (NULL), stores (NULL)
+ : loads (NULL), stores (NULL), writes_errno (NULL)
{
}
@@ -134,13 +275,38 @@ modref_summary::~modref_summary ()
ggc_delete (stores);
}
-/* Return true if summary is potentially useful for optimization. */
+/* Return true if FLAGS holds some useful information. */
+
+static bool
+eaf_flags_useful_p (vec <unsigned char> &flags, int ecf_flags)
+{
+ for (unsigned i = 0; i < flags.length (); i++)
+ if (ecf_flags & ECF_PURE)
+ {
+ if (flags[i] & (EAF_UNUSED | EAF_DIRECT))
+ return true;
+ }
+ else
+ {
+ if (flags[i])
+ return true;
+ }
+ return false;
+}
+
+/* Return true if summary is potentially useful for optimization.
+ If CHECK_FLAGS is false assume that arg_flags are useful. */
bool
-modref_summary::useful_p (int ecf_flags)
+modref_summary::useful_p (int ecf_flags, bool check_flags)
{
if (ecf_flags & (ECF_CONST | ECF_NOVOPS))
return false;
+ if (arg_flags.length () && !check_flags)
+ return true;
+ if (check_flags && eaf_flags_useful_p (arg_flags, ecf_flags))
+ return true;
+ arg_flags.release ();
if (loads && !loads->every_base)
return true;
if (ecf_flags & ECF_PURE)
@@ -159,17 +325,19 @@ struct GTY(()) modref_summary_lto
more verbose and thus more likely to hit the limits. */
modref_records_lto *loads;
modref_records_lto *stores;
+ auto_vec<unsigned char> GTY((skip)) arg_flags;
+ bool writes_errno;
modref_summary_lto ();
~modref_summary_lto ();
void dump (FILE *);
- bool useful_p (int ecf_flags);
+ bool useful_p (int ecf_flags, bool check_flags = true);
};
/* Summary for a single function which this pass produces. */
modref_summary_lto::modref_summary_lto ()
- : loads (NULL), stores (NULL)
+ : loads (NULL), stores (NULL), writes_errno (NULL)
{
}
@@ -182,13 +350,19 @@ modref_summary_lto::~modref_summary_lto ()
}
-/* Return true if lto summary is potentially useful for optimization. */
+/* Return true if lto summary is potentially useful for optimization.
+ If CHECK_FLAGS is false assume that arg_flags are useful. */
bool
-modref_summary_lto::useful_p (int ecf_flags)
+modref_summary_lto::useful_p (int ecf_flags, bool check_flags)
{
if (ecf_flags & (ECF_CONST | ECF_NOVOPS))
return false;
+ if (arg_flags.length () && !check_flags)
+ return true;
+ if (check_flags && eaf_flags_useful_p (arg_flags, ecf_flags))
+ return true;
+ arg_flags.release ();
if (loads && !loads->every_base)
return true;
if (ecf_flags & ECF_PURE)
@@ -309,15 +483,90 @@ dump_lto_records (modref_records_lto *tt, FILE *out)
}
}
+/* Dump all escape points of NODE to OUT. */
+
+static void
+dump_modref_edge_summaries (FILE *out, cgraph_node *node, int depth)
+{
+ int i = 0;
+ if (!escape_summaries)
+ return;
+ for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
+ {
+ class escape_summary *sum = escape_summaries->get (e);
+ if (sum)
+ {
+ fprintf (out, "%*sIndirect call %i in %s escapes:",
+ depth, "", i, node->dump_name ());
+ sum->dump (out);
+ }
+ i++;
+ }
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ if (!e->inline_failed)
+ dump_modref_edge_summaries (out, e->callee, depth + 1);
+ class escape_summary *sum = escape_summaries->get (e);
+ if (sum)
+ {
+ fprintf (out, "%*sCall %s->%s escapes:", depth, "",
+ node->dump_name (), e->callee->dump_name ());
+ sum->dump (out);
+ }
+ class fnspec_summary *fsum = fnspec_summaries->get (e);
+ if (fsum)
+ {
+ fprintf (out, "%*sCall %s->%s fnspec: %s\n", depth, "",
+ node->dump_name (), e->callee->dump_name (),
+ fsum->fnspec);
+ }
+ }
+}
+
+/* Remove all call edge summaries associated with NODE. */
+
+static void
+remove_modref_edge_summaries (cgraph_node *node)
+{
+ if (!escape_summaries)
+ return;
+ for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
+ escape_summaries->remove (e);
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ if (!e->inline_failed)
+ remove_modref_edge_summaries (e->callee);
+ escape_summaries->remove (e);
+ fnspec_summaries->remove (e);
+ }
+}
+
/* Dump summary. */
void
modref_summary::dump (FILE *out)
{
- fprintf (out, " loads:\n");
- dump_records (loads, out);
- fprintf (out, " stores:\n");
- dump_records (stores, out);
+ if (loads)
+ {
+ fprintf (out, " loads:\n");
+ dump_records (loads, out);
+ }
+ if (stores)
+ {
+ fprintf (out, " stores:\n");
+ dump_records (stores, out);
+ }
+ if (writes_errno)
+ fprintf (out, " Writes errno\n");
+ if (arg_flags.length ())
+ {
+ for (unsigned int i = 0; i < arg_flags.length (); i++)
+ if (arg_flags[i])
+ {
+ fprintf (out, " parm %i flags:", i);
+ dump_eaf_flags (out, arg_flags[i]);
+ }
+ }
}
/* Dump summary. */
@@ -329,6 +578,17 @@ modref_summary_lto::dump (FILE *out)
dump_lto_records (loads, out);
fprintf (out, " stores:\n");
dump_lto_records (stores, out);
+ if (writes_errno)
+ fprintf (out, " Writes errno\n");
+ if (arg_flags.length ())
+ {
+ for (unsigned int i = 0; i < arg_flags.length (); i++)
+ if (arg_flags[i])
+ {
+ fprintf (out, " parm %i flags:", i);
+ dump_eaf_flags (out, arg_flags[i]);
+ }
+ }
}
/* Get function summary for FUNC if it exists, return NULL otherwise. */
@@ -346,7 +606,8 @@ get_modref_function_summary (cgraph_node *func)
function. */
enum availability avail;
func = func->function_or_virtual_thunk_symbol
- (&avail, cgraph_node::get (current_function_decl));
+ (&avail, current_function_decl ?
+ cgraph_node::get (current_function_decl) : NULL);
if (avail <= AVAIL_INTERPOSABLE)
return NULL;
@@ -498,12 +759,23 @@ record_access_p (tree expr)
return true;
}
+/* Return true if ECF flags says that return value can be ignored. */
+
+static bool
+ignore_retval_p (tree caller, int flags)
+{
+ if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
+ || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
+ return true;
+ return false;
+}
+
/* Return true if ECF flags says that stores can be ignored. */
static bool
ignore_stores_p (tree caller, int flags)
{
- if (flags & ECF_PURE)
+ if (flags & (ECF_PURE | ECF_CONST | ECF_NOVOPS))
return true;
if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
|| (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
@@ -511,6 +783,46 @@ ignore_stores_p (tree caller, int flags)
return false;
}
+/* Determine parm_map for argument I of STMT. */
+
+modref_parm_map
+parm_map_for_arg (gimple *stmt, int i)
+{
+ tree op = gimple_call_arg (stmt, i);
+ bool offset_known;
+ poly_int64 offset;
+ struct modref_parm_map parm_map;
+
+ parm_map.parm_offset_known = false;
+ parm_map.parm_offset = 0;
+
+ offset_known = unadjusted_ptr_and_unit_offset (op, &op, &offset);
+ if (TREE_CODE (op) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (op)
+ && TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
+ {
+ int index = 0;
+ for (tree t = DECL_ARGUMENTS (current_function_decl);
+ t != SSA_NAME_VAR (op); t = DECL_CHAIN (t))
+ {
+ if (!t)
+ {
+ index = -1;
+ break;
+ }
+ index++;
+ }
+ parm_map.parm_index = index;
+ parm_map.parm_offset_known = offset_known;
+ parm_map.parm_offset = offset;
+ }
+ else if (points_to_local_or_readonly_memory_p (op))
+ parm_map.parm_index = -2;
+ else
+ parm_map.parm_index = -1;
+ return parm_map;
+}
+
/* Merge side effects of call STMT to function with CALLEE_SUMMARY
int CUR_SUMMARY. Return true if something changed.
If IGNORE_STORES is true, do not merge stores. */
@@ -527,37 +839,21 @@ merge_call_side_effects (modref_summary *cur_summary,
fprintf (dump_file, " - Merging side effects of %s with parm map:",
callee_node->dump_name ());
- parm_map.safe_grow_cleared (gimple_call_num_args (stmt));
- for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
+ /* We can not safely optimize based on summary of callee if it does
+ not always bind to current def: it is possible that memory load
+ was optimized out earlier which may not happen in the interposed
+ variant. */
+ if (!callee_node->binds_to_current_def_p ())
{
- tree op = gimple_call_arg (stmt, i);
- bool offset_known;
- poly_int64 offset;
+ if (dump_file)
+ fprintf (dump_file, " - May be interposed: collapsing loads.\n");
+ cur_summary->loads->collapse ();
+ }
- offset_known = unadjusted_ptr_and_unit_offset (op, &op, &offset);
- if (TREE_CODE (op) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (op)
- && TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
- {
- int index = 0;
- for (tree t = DECL_ARGUMENTS (current_function_decl);
- t != SSA_NAME_VAR (op); t = DECL_CHAIN (t))
- {
- if (!t)
- {
- index = -1;
- break;
- }
- index++;
- }
- parm_map[i].parm_index = index;
- parm_map[i].parm_offset_known = offset_known;
- parm_map[i].parm_offset = offset;
- }
- else if (points_to_local_or_readonly_memory_p (op))
- parm_map[i].parm_index = -2;
- else
- parm_map[i].parm_index = -1;
+ parm_map.safe_grow_cleared (gimple_call_num_args (stmt), true);
+ for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ parm_map[i] = parm_map_for_arg (stmt, i);
if (dump_file)
{
fprintf (dump_file, " %i", parm_map[i].parm_index);
@@ -575,17 +871,203 @@ merge_call_side_effects (modref_summary *cur_summary,
/* Merge with callee's summary. */
changed |= cur_summary->loads->merge (callee_summary->loads, &parm_map);
if (!ignore_stores)
- changed |= cur_summary->stores->merge (callee_summary->stores,
- &parm_map);
+ {
+ changed |= cur_summary->stores->merge (callee_summary->stores,
+ &parm_map);
+ if (!cur_summary->writes_errno
+ && callee_summary->writes_errno)
+ {
+ cur_summary->writes_errno = true;
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+/* Return access mode for argument I of call STMT with FNSPEC. */
+
+static modref_access_node
+get_access_for_fnspec (gcall *call, attr_fnspec &fnspec,
+ unsigned int i, modref_parm_map &map)
+{
+ tree size = NULL_TREE;
+ unsigned int size_arg;
+
+ if (!fnspec.arg_specified_p (i))
+ ;
+ else if (fnspec.arg_max_access_size_given_by_arg_p (i, &size_arg))
+ size = gimple_call_arg (call, size_arg);
+ else if (fnspec.arg_access_size_given_by_type_p (i))
+ {
+ tree callee = gimple_call_fndecl (call);
+ tree t = TYPE_ARG_TYPES (TREE_TYPE (callee));
+
+ for (unsigned int p = 0; p < i; p++)
+ t = TREE_CHAIN (t);
+ size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_VALUE (t)));
+ }
+ modref_access_node a = {0, -1, -1,
+ map.parm_offset, map.parm_index,
+ map.parm_offset_known};
+ poly_int64 size_hwi;
+ if (size
+ && poly_int_tree_p (size, &size_hwi)
+ && coeffs_in_range_p (size_hwi, 0,
+ HOST_WIDE_INT_MAX / BITS_PER_UNIT))
+ {
+ a.size = -1;
+ a.max_size = size_hwi << LOG2_BITS_PER_UNIT;
+ }
+ return a;
+}
+
+/* Collapse loads and return true if something changed. */
+
+static bool
+collapse_loads (modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto)
+{
+ bool changed = false;
+
+ if (cur_summary && !cur_summary->loads->every_base)
+ {
+ cur_summary->loads->collapse ();
+ changed = true;
+ }
+ if (cur_summary_lto
+ && !cur_summary_lto->loads->every_base)
+ {
+ cur_summary_lto->loads->collapse ();
+ changed = true;
+ }
return changed;
}
+/* Collapse loads and return true if something changed. */
+
+static bool
+collapse_stores (modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto)
+{
+ bool changed = false;
+
+ if (cur_summary && !cur_summary->stores->every_base)
+ {
+ cur_summary->stores->collapse ();
+ changed = true;
+ }
+ if (cur_summary_lto
+ && !cur_summary_lto->stores->every_base)
+ {
+ cur_summary_lto->stores->collapse ();
+ changed = true;
+ }
+ return changed;
+}
+
+
+/* Apply side effects of call STMT to CUR_SUMMARY using FNSPEC.
+ If IGNORE_STORES is true ignore them.
+ Return false if no useful summary can be produced. */
+
+static bool
+process_fnspec (modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto,
+ gcall *call, bool ignore_stores)
+{
+ attr_fnspec fnspec = gimple_call_fnspec (call);
+ if (!fnspec.known_p ())
+ {
+ if (dump_file && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
+ fprintf (dump_file, " Builtin with no fnspec: %s\n",
+ IDENTIFIER_POINTER (DECL_NAME (gimple_call_fndecl (call))));
+ if (ignore_stores)
+ {
+ collapse_loads (cur_summary, cur_summary_lto);
+ return true;
+ }
+ return false;
+ }
+ if (fnspec.global_memory_read_p ())
+ collapse_loads (cur_summary, cur_summary_lto);
+ else
+ {
+ for (unsigned int i = 0; i < gimple_call_num_args (call); i++)
+ if (!POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, i))))
+ ;
+ else if (!fnspec.arg_specified_p (i)
+ || fnspec.arg_maybe_read_p (i))
+ {
+ modref_parm_map map = parm_map_for_arg (call, i);
+
+ if (map.parm_index == -2)
+ continue;
+ if (map.parm_index == -1)
+ {
+ collapse_loads (cur_summary, cur_summary_lto);
+ break;
+ }
+ if (cur_summary)
+ cur_summary->loads->insert (0, 0,
+ get_access_for_fnspec (call,
+ fnspec, i,
+ map));
+ if (cur_summary_lto)
+ cur_summary_lto->loads->insert (0, 0,
+ get_access_for_fnspec (call,
+ fnspec, i,
+ map));
+ }
+ }
+ if (ignore_stores)
+ return true;
+ if (fnspec.global_memory_written_p ())
+ collapse_stores (cur_summary, cur_summary_lto);
+ else
+ {
+ for (unsigned int i = 0; i < gimple_call_num_args (call); i++)
+ if (!POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, i))))
+ ;
+ else if (!fnspec.arg_specified_p (i)
+ || fnspec.arg_maybe_written_p (i))
+ {
+ modref_parm_map map = parm_map_for_arg (call, i);
+
+ if (map.parm_index == -2)
+ continue;
+ if (map.parm_index == -1)
+ {
+ collapse_stores (cur_summary, cur_summary_lto);
+ break;
+ }
+ if (cur_summary)
+ cur_summary->stores->insert (0, 0,
+ get_access_for_fnspec (call,
+ fnspec, i,
+ map));
+ if (cur_summary_lto)
+ cur_summary_lto->stores->insert (0, 0,
+ get_access_for_fnspec (call,
+ fnspec, i,
+ map));
+ }
+ if (fnspec.errno_maybe_written_p () && flag_errno_math)
+ {
+ if (cur_summary)
+ cur_summary->writes_errno = true;
+ if (cur_summary_lto)
+ cur_summary_lto->writes_errno = true;
+ }
+ }
+ return true;
+}
+
/* Analyze function call STMT in function F.
Remember recursive calls in RECURSIVE_CALLS. */
static bool
-analyze_call (modref_summary *cur_summary,
- gimple *stmt, vec <gimple *> *recursive_calls)
+analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
+ gcall *stmt, vec <gimple *> *recursive_calls)
{
/* Check flags on the function call. In certain cases, analysis can be
simplified. */
@@ -610,35 +1092,16 @@ analyze_call (modref_summary *cur_summary,
/* Check if this is an indirect call. */
if (!callee)
{
- /* If the indirect call does not write memory, our store summary is
- unaffected, but we have to discard our loads summary (we don't know
- anything about the loads that the called function performs). */
- if (ignore_stores)
- {
- if (dump_file)
- fprintf (dump_file, " - Indirect call which does not write memory, "
- "discarding loads.\n");
- cur_summary->loads->collapse ();
- return true;
- }
if (dump_file)
- fprintf (dump_file, " - Indirect call.\n");
- return false;
+ fprintf (dump_file, gimple_call_internal_p (stmt)
+ ? " - Internal call" : " - Indirect call.\n");
+ return process_fnspec (cur_summary, cur_summary_lto, stmt, ignore_stores);
}
+ /* We only need to handle internal calls in IPA mode. */
+ gcc_checking_assert (!cur_summary_lto);
struct cgraph_node *callee_node = cgraph_node::get_create (callee);
- /* We can not safely optimize based on summary of callee if it does
- not always bind to current def: it is possible that memory load
- was optimized out earlier which may not happen in the interposed
- variant. */
- if (!callee_node->binds_to_current_def_p ())
- {
- if (dump_file)
- fprintf (dump_file, " - May be interposed: collapsing loads.\n");
- cur_summary->loads->collapse ();
- }
-
/* If this is a recursive call, the target summary is the same as ours, so
there's nothing to do. */
if (recursive_call_p (current_function_decl, callee))
@@ -656,16 +1119,9 @@ analyze_call (modref_summary *cur_summary,
callee_node = callee_node->function_symbol (&avail);
if (avail <= AVAIL_INTERPOSABLE)
{
- /* Keep stores summary, but discard all loads for interposable function
- symbols. */
- if (ignore_stores)
- {
- cur_summary->loads->collapse ();
- return true;
- }
if (dump_file)
fprintf (dump_file, " - Function availability <= AVAIL_INTERPOSABLE.\n");
- return false;
+ return process_fnspec (cur_summary, cur_summary_lto, stmt, ignore_stores);
}
/* Get callee's modref summary. As above, if there's no summary, we either
@@ -673,14 +1129,9 @@ analyze_call (modref_summary *cur_summary,
modref_summary *callee_summary = optimization_summaries->get (callee_node);
if (!callee_summary)
{
- if (ignore_stores)
- {
- cur_summary->loads->collapse ();
- return true;
- }
if (dump_file)
fprintf (dump_file, " - No modref summary available for callee.\n");
- return false;
+ return process_fnspec (cur_summary, cur_summary_lto, stmt, ignore_stores);
}
merge_call_side_effects (cur_summary, stmt, callee_summary, ignore_stores,
@@ -689,7 +1140,7 @@ analyze_call (modref_summary *cur_summary,
return true;
}
-/* Support analyzis in non-lto and lto mode in parallel. */
+/* Support analysis in non-lto and lto mode in parallel. */
struct summary_ptrs
{
@@ -760,10 +1211,10 @@ static bool
analyze_stmt (modref_summary *summary, modref_summary_lto *summary_lto,
gimple *stmt, bool ipa, vec <gimple *> *recursive_calls)
{
- /* In general we can not ignore clobbers because they are barries for code
- motion, however after inlining it is safe to do becuase local optimization
+ /* In general we can not ignore clobbers because they are barriers for code
+ motion, however after inlining it is safe to do because local optimization
passes do not consider clobbers from other functions.
- Similar logic is in ipa-pure-consts. */
+ Similar logic is in ipa-pure-const.c. */
if ((ipa || cfun->after_inlining) && gimple_clobber_p (stmt))
return true;
@@ -785,8 +1236,24 @@ analyze_stmt (modref_summary *summary, modref_summary_lto *summary_lto,
"which clobbers memory.\n");
return false;
case GIMPLE_CALL:
- if (!ipa)
- return analyze_call (summary, stmt, recursive_calls);
+ if (!ipa || gimple_call_internal_p (stmt))
+ return analyze_call (summary, summary_lto,
+ as_a <gcall *> (stmt), recursive_calls);
+ else
+ {
+ attr_fnspec fnspec = gimple_call_fnspec (as_a <gcall *>(stmt));
+
+ if (fnspec.known_p ()
+ && (!fnspec.global_memory_read_p ()
+ || !fnspec.global_memory_written_p ()))
+ {
+ fnspec_summaries->get_create
+ (cgraph_node::get (current_function_decl)->get_edge (stmt))
+ ->fnspec = xstrdup (fnspec.get_str ());
+ if (dump_file)
+ fprintf (dump_file, " Recorded fnspec %s\n", fnspec.get_str ());
+ }
+ }
return true;
default:
/* Nothing to do for other types of statements. */
@@ -810,12 +1277,623 @@ remove_summary (bool lto, bool nolto, bool ipa)
summaries->remove (fnode);
if (lto)
summaries_lto->remove (fnode);
+ remove_modref_edge_summaries (fnode);
}
if (dump_file)
fprintf (dump_file,
" - modref done with result: not tracked.\n");
}
+/* Return true if OP accesses memory pointed to by SSA_NAME. */
+
+bool
+memory_access_to (tree op, tree ssa_name)
+{
+ tree base = get_base_address (op);
+ if (!base)
+ return false;
+ if (TREE_CODE (base) != MEM_REF && TREE_CODE (base) != TARGET_MEM_REF)
+ return false;
+ return TREE_OPERAND (base, 0) == ssa_name;
+}
+
+/* Consider statement val = *arg.
+ return EAF flags of ARG that can be determined from EAF flags of VAL
+ (which are known to be FLAGS). If IGNORE_STORES is true we can ignore
+ all stores to VAL, i.e. when handling noreturn function. */
+
+static int
+deref_flags (int flags, bool ignore_stores)
+{
+ int ret = EAF_NODIRECTESCAPE;
+ if (flags & EAF_UNUSED)
+ ret |= EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE;
+ else
+ {
+ if ((flags & EAF_NOCLOBBER) || ignore_stores)
+ ret |= EAF_NOCLOBBER;
+ if ((flags & EAF_NOESCAPE) || ignore_stores)
+ ret |= EAF_NOESCAPE;
+ }
+ return ret;
+}
+
+namespace {
+
+/* Description of an escape point. */
+
+struct escape_point
+{
+ /* Value escapes to this call. */
+ gcall *call;
+ /* Argument it escapes to. */
+ int arg;
+ /* Flags already known about the argument (this can save us from recording
+ esape points if local analysis did good job already). */
+ char min_flags;
+ /* Does value escape directly or indiretly? */
+ bool direct;
+};
+
+class modref_lattice
+{
+public:
+ /* EAF flags of the SSA name. */
+ int flags;
+ /* DFS bookkkeeping: we don't do real dataflow yet. */
+ bool known;
+ bool open;
+
+ /* When doing IPA analysis we can not merge in callee escape points;
+ Only remember them and do the merging at IPA propagation time. */
+ vec <escape_point, va_heap, vl_ptr> escape_points;
+
+ void init ();
+ void release ();
+ bool merge (const modref_lattice &with);
+ bool merge (int flags);
+ bool merge_deref (const modref_lattice &with, bool ignore_stores);
+ bool merge_direct_load ();
+ bool merge_direct_store ();
+ bool add_escape_point (gcall *call, int arg, int min_flags, bool diret);
+ void dump (FILE *out, int indent = 0) const;
+};
+
+/* Lattices are saved to vectors, so keep them PODs. */
+void
+modref_lattice::init ()
+{
+ flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED
+ | EAF_NODIRECTESCAPE;
+ open = true;
+ known = false;
+}
+
+/* Release memory. */
+void
+modref_lattice::release ()
+{
+ escape_points.release ();
+}
+
+/* Dump lattice to OUT; indent with INDENT spaces. */
+
+void
+modref_lattice::dump (FILE *out, int indent) const
+{
+ dump_eaf_flags (out, flags);
+ if (escape_points.length ())
+ {
+ fprintf (out, "%*sEscapes:\n", indent, "");
+ for (unsigned int i = 0; i < escape_points.length (); i++)
+ {
+ fprintf (out, "%*s Arg %i (%s) min flags", indent, "",
+ escape_points[i].arg,
+ escape_points[i].direct ? "direct" : "indirect");
+ dump_eaf_flags (out, flags, false);
+ fprintf (out, " in call ");
+ print_gimple_stmt (out, escape_points[i].call, 0);
+ }
+ }
+}
+
+/* Add escape point CALL, ARG, MIN_FLAGS, DIRECT. Return false if such escape
+ point exists. */
+
+bool
+modref_lattice::add_escape_point (gcall *call, int arg, int min_flags,
+ bool direct)
+{
+ escape_point *ep;
+ unsigned int i;
+
+ /* If we already determined flags to be bad enough,
+ * we do not need to record. */
+ if ((flags & min_flags) == flags)
+ return false;
+
+ FOR_EACH_VEC_ELT (escape_points, i, ep)
+ if (ep->call == call && ep->arg == arg && ep->direct == direct)
+ {
+ if ((ep->min_flags & min_flags) == min_flags)
+ return false;
+ ep->min_flags &= min_flags;
+ return true;
+ }
+ /* Give up if max escape points is met. */
+ if ((int)escape_points.length () > param_modref_max_escape_points)
+ {
+ if (dump_file)
+ fprintf (dump_file, "--param modref-max-escape-points limit reached\n");
+ merge (0);
+ return true;
+ }
+ escape_point new_ep = {call, arg, min_flags, direct};
+ escape_points.safe_push (new_ep);
+ return true;
+}
+
+/* Merge in flags from F. */
+bool
+modref_lattice::merge (int f)
+{
+ if (f & EAF_UNUSED)
+ return false;
+ if ((flags & f) != flags)
+ {
+ flags &= f;
+ /* Only NOCLOBBER or DIRECT flags alone are not useful (see comments
+ in tree-ssa-alias.c). Give up earlier. */
+ if ((flags & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
+ flags = 0;
+ if (!flags)
+ escape_points.release ();
+ return true;
+ }
+ return false;
+}
+
+/* Merge in WITH. Return true if anyting changed. */
+
+bool
+modref_lattice::merge (const modref_lattice &with)
+{
+ if (!with.known)
+ return merge (0);
+
+ bool changed = merge (with.flags);
+
+ if (!flags)
+ return changed;
+ for (unsigned int i = 0; i < with.escape_points.length (); i++)
+ changed |= add_escape_point (with.escape_points[i].call,
+ with.escape_points[i].arg,
+ with.escape_points[i].min_flags,
+ with.escape_points[i].direct);
+ return changed;
+}
+
+/* Merge in deref of WITH. If IGNORE_STORES is true do not consider
+ stores. Return true if anyting changed. */
+
+bool
+modref_lattice::merge_deref (const modref_lattice &with, bool ignore_stores)
+{
+ if (!with.known)
+ return merge (0);
+
+ bool changed = merge (deref_flags (with.flags, ignore_stores));
+
+ if (!flags)
+ return changed;
+ for (unsigned int i = 0; i < with.escape_points.length (); i++)
+ changed |= add_escape_point (with.escape_points[i].call,
+ with.escape_points[i].arg,
+ with.escape_points[i].min_flags,
+ false);
+ return changed;
+}
+
+/* Merge in flags for direct load. */
+
+bool
+modref_lattice::merge_direct_load ()
+{
+ return merge (~EAF_UNUSED);
+}
+
+/* Merge in flags for direct store. */
+
+bool
+modref_lattice::merge_direct_store ()
+{
+ return merge (~(EAF_UNUSED | EAF_NOCLOBBER));
+}
+
+} /* ANON namespace. */
+
+static void analyze_ssa_name_flags (tree name,
+ vec<modref_lattice> &lattice,
+ int depth, bool ipa);
+
+/* Call statements may return their parameters. Consider argument number
+ ARG of USE_STMT and determine flags that can needs to be cleared
+ in case pointer possibly indirectly references from ARG I is returned.
+ LATTICE, DEPTH and ipa are same as in analyze_ssa_name_flags. */
+
+static void
+merge_call_lhs_flags (gcall *call, int arg, int index, bool deref,
+ vec<modref_lattice> &lattice,
+ int depth, bool ipa)
+{
+ /* If there is no return value, no flags are affected. */
+ if (!gimple_call_lhs (call))
+ return;
+
+ /* If we know that function returns given argument and it is not ARG
+ we can still be happy. */
+ int flags = gimple_call_return_flags (call);
+ if ((flags & ERF_RETURNS_ARG)
+ && (flags & ERF_RETURN_ARG_MASK) != arg)
+ return;
+
+ /* If return value is SSA name determine its flags. */
+ if (TREE_CODE (gimple_call_lhs (call)) == SSA_NAME)
+ {
+ tree lhs = gimple_call_lhs (call);
+ analyze_ssa_name_flags (lhs, lattice, depth + 1, ipa);
+ if (deref)
+ lattice[index].merge (lattice[SSA_NAME_VERSION (lhs)]);
+ else
+ lattice[index].merge_deref (lattice[SSA_NAME_VERSION (lhs)], false);
+ }
+ /* In the case of memory store we can do nothing. */
+ else
+ lattice[index].merge (0);
+}
+
+/* Analyze EAF flags for SSA name NAME and store result to LATTICE.
+ LATTICE is an array of modref_lattices.
+ DEPTH is a recursion depth used to make debug output prettier.
+ If IPA is true we analyze for IPA propagation (and thus call escape points
+ are processed later) */
+
+static void
+analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth,
+ bool ipa)
+{
+ imm_use_iterator ui;
+ gimple *use_stmt;
+ int index = SSA_NAME_VERSION (name);
+
+ /* See if value is already computed. */
+ if (lattice[index].known)
+ return;
+ if (lattice[index].open)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "%*sGiving up on a cycle in SSA graph\n", depth * 4, "");
+ return;
+ }
+ if (depth == param_modref_max_depth)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "%*sGiving up on max depth\n", depth * 4, "");
+ return;
+ }
+ /* Recursion guard. */
+ lattice[index].init ();
+
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "%*sAnalyzing flags of ssa name: ", depth * 4, "");
+ print_generic_expr (dump_file, name);
+ fprintf (dump_file, "\n");
+ }
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, name)
+ {
+ if (lattice[index].flags == 0)
+ {
+ BREAK_FROM_IMM_USE_STMT (ui);
+ }
+ if (is_gimple_debug (use_stmt))
+ continue;
+ if (dump_file)
+ {
+ fprintf (dump_file, "%*s Analyzing stmt:", depth * 4, "");
+ print_gimple_stmt (dump_file, use_stmt, 0);
+ }
+
+ /* Gimple return may load the return value.
+ Returning name counts as an use by tree-ssa-structalias.c */
+ if (greturn *ret = dyn_cast <greturn *> (use_stmt))
+ {
+ if (gimple_return_retval (ret) == name)
+ lattice[index].merge (~EAF_UNUSED);
+ else if (memory_access_to (gimple_return_retval (ret), name))
+ lattice[index].merge_direct_load ();
+ }
+ /* Account for LHS store, arg loads and flags from callee function. */
+ else if (gcall *call = dyn_cast <gcall *> (use_stmt))
+ {
+ tree callee = gimple_call_fndecl (call);
+
+ /* Recursion would require bit of propagation; give up for now. */
+ if (callee && !ipa && recursive_call_p (current_function_decl,
+ callee))
+ lattice[index].merge (0);
+ else
+ {
+ int ecf_flags = gimple_call_flags (call);
+ bool ignore_stores = ignore_stores_p (current_function_decl,
+ ecf_flags);
+ bool ignore_retval = ignore_retval_p (current_function_decl,
+ ecf_flags);
+
+ /* Handle *name = func (...). */
+ if (gimple_call_lhs (call)
+ && memory_access_to (gimple_call_lhs (call), name))
+ lattice[index].merge_direct_store ();
+
+ /* We do not track accesses to the static chain (we could)
+ so give up. */
+ if (gimple_call_chain (call)
+ && (gimple_call_chain (call) == name))
+ lattice[index].merge (0);
+
+ /* Process internal functions and right away. */
+ bool record_ipa = ipa && !gimple_call_internal_p (call);
+
+ /* Handle all function parameters. */
+ for (unsigned i = 0;
+ i < gimple_call_num_args (call) && lattice[index].flags; i++)
+ /* Name is directly passed to the callee. */
+ if (gimple_call_arg (call, i) == name)
+ {
+ if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS)))
+ {
+ int call_flags = gimple_call_arg_flags (call, i);
+ if (ignore_stores)
+ call_flags |= EAF_NOCLOBBER | EAF_NOESCAPE
+ | EAF_NODIRECTESCAPE;
+
+ if (!record_ipa)
+ lattice[index].merge (call_flags);
+ if (record_ipa)
+ lattice[index].add_escape_point (call, i,
+ call_flags, true);
+ }
+ if (!ignore_retval)
+ merge_call_lhs_flags (call, i, index, false,
+ lattice, depth, ipa);
+ }
+ /* Name is dereferenced and passed to a callee. */
+ else if (memory_access_to (gimple_call_arg (call, i), name))
+ {
+ if (ecf_flags & (ECF_CONST | ECF_NOVOPS))
+ lattice[index].merge_direct_load ();
+ else
+ {
+ int call_flags = deref_flags
+ (gimple_call_arg_flags (call, i), ignore_stores);
+ if (!record_ipa)
+ lattice[index].merge (call_flags);
+ if (record_ipa)
+ lattice[index].add_escape_point (call, i,
+ call_flags, false);
+ }
+ if (!ignore_retval)
+ merge_call_lhs_flags (call, i, index, true,
+ lattice, depth, ipa);
+ }
+ }
+ }
+ else if (gimple_assign_load_p (use_stmt))
+ {
+ gassign *assign = as_a <gassign *> (use_stmt);
+ /* Memory to memory copy. */
+ if (gimple_store_p (assign))
+ {
+ /* Handle *lhs = *name.
+
+ We do not track memory locations, so assume that value
+ is used arbitrarily. */
+ if (memory_access_to (gimple_assign_rhs1 (assign), name))
+ lattice[index].merge (0);
+ /* Handle *name = *exp. */
+ else if (memory_access_to (gimple_assign_lhs (assign), name))
+ lattice[index].merge_direct_store ();
+ }
+ /* Handle lhs = *name. */
+ else if (memory_access_to (gimple_assign_rhs1 (assign), name))
+ {
+ tree lhs = gimple_assign_lhs (assign);
+ analyze_ssa_name_flags (lhs, lattice, depth + 1, ipa);
+ lattice[index].merge_deref (lattice[SSA_NAME_VERSION (lhs)],
+ false);
+ }
+ }
+ else if (gimple_store_p (use_stmt))
+ {
+ gassign *assign = dyn_cast <gassign *> (use_stmt);
+
+ /* Handle *lhs = name. */
+ if (assign && gimple_assign_rhs1 (assign) == name)
+ {
+ if (dump_file)
+ fprintf (dump_file, "%*s ssa name saved to memory\n",
+ depth * 4, "");
+ lattice[index].merge (0);
+ }
+ /* Handle *name = exp. */
+ else if (assign
+ && memory_access_to (gimple_assign_lhs (assign), name))
+ {
+ /* In general we can not ignore clobbers because they are
+ barriers for code motion, however after inlining it is safe to
+ do because local optimization passes do not consider clobbers
+ from other functions. Similar logic is in ipa-pure-const.c. */
+ if (!cfun->after_inlining || !gimple_clobber_p (assign))
+ lattice[index].merge_direct_store ();
+ }
+ /* ASM statements etc. */
+ else if (!assign)
+ {
+ if (dump_file)
+ fprintf (dump_file, "%*s Unhandled store\n",
+ depth * 4, "");
+ lattice[index].merge (0);
+ }
+ }
+ else if (gassign *assign = dyn_cast <gassign *> (use_stmt))
+ {
+ enum tree_code code = gimple_assign_rhs_code (assign);
+
+ /* See if operation is a merge as considered by
+ tree-ssa-structalias.c:find_func_aliases. */
+ if (!truth_value_p (code)
+ && code != POINTER_DIFF_EXPR
+ && (code != POINTER_PLUS_EXPR
+ || gimple_assign_rhs1 (assign) == name))
+ {
+ tree lhs = gimple_assign_lhs (assign);
+ analyze_ssa_name_flags (lhs, lattice, depth + 1, ipa);
+ lattice[index].merge (lattice[SSA_NAME_VERSION (lhs)]);
+ }
+ }
+ else if (gphi *phi = dyn_cast <gphi *> (use_stmt))
+ {
+ tree result = gimple_phi_result (phi);
+ analyze_ssa_name_flags (result, lattice, depth + 1, ipa);
+ lattice[index].merge (lattice[SSA_NAME_VERSION (result)]);
+ }
+ /* Conditions are not considered escape points
+ by tree-ssa-structalias. */
+ else if (gimple_code (use_stmt) == GIMPLE_COND)
+ ;
+ else
+ {
+ if (dump_file)
+ fprintf (dump_file, "%*s Unhandled stmt\n", depth * 4, "");
+ lattice[index].merge (0);
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "%*s current flags of ", depth * 4, "");
+ print_generic_expr (dump_file, name);
+ lattice[index].dump (dump_file, depth * 4 + 4);
+ }
+ }
+ if (dump_file)
+ {
+ fprintf (dump_file, "%*sflags of ssa name ", depth * 4, "");
+ print_generic_expr (dump_file, name);
+ lattice[index].dump (dump_file, depth * 4 + 2);
+ }
+ lattice[index].open = false;
+ lattice[index].known = true;
+}
+
+/* Determine EAF flags for function parameters. */
+
+static void
+analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto,
+ bool ipa)
+{
+ unsigned int parm_index = 0;
+ unsigned int count = 0;
+ int ecf_flags = flags_from_decl_or_type (current_function_decl);
+
+ /* For const functions we have nothing to gain by EAF flags. */
+ if (ecf_flags & (ECF_CONST | ECF_NOVOPS))
+ return;
+
+ for (tree parm = DECL_ARGUMENTS (current_function_decl); parm;
+ parm = TREE_CHAIN (parm))
+ count++;
+
+ if (!count)
+ return;
+
+ auto_vec<modref_lattice> lattice;
+ lattice.safe_grow_cleared (num_ssa_names, true);
+
+ for (tree parm = DECL_ARGUMENTS (current_function_decl); parm; parm_index++,
+ parm = TREE_CHAIN (parm))
+ {
+ tree name = ssa_default_def (cfun, parm);
+ if (!name || has_zero_uses (name))
+ {
+ /* We do not track non-SSA parameters,
+ but we want to track unused gimple_regs. */
+ if (!is_gimple_reg (parm))
+ continue;
+ if (summary)
+ {
+ if (parm_index >= summary->arg_flags.length ())
+ summary->arg_flags.safe_grow_cleared (count, true);
+ summary->arg_flags[parm_index] = EAF_UNUSED;
+ }
+ else if (summary_lto)
+ {
+ if (parm_index >= summary_lto->arg_flags.length ())
+ summary_lto->arg_flags.safe_grow_cleared (count, true);
+ summary_lto->arg_flags[parm_index] = EAF_UNUSED;
+ }
+ continue;
+ }
+ analyze_ssa_name_flags (name, lattice, 0, ipa);
+ int flags = lattice[SSA_NAME_VERSION (name)].flags;
+
+ /* For pure functions we have implicit NOCLOBBER
+ and NOESCAPE. */
+ if (ecf_flags & ECF_PURE)
+ flags &= ~(EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE);
+
+ if (flags)
+ {
+ if (summary)
+ {
+ if (parm_index >= summary->arg_flags.length ())
+ summary->arg_flags.safe_grow_cleared (count, true);
+ summary->arg_flags[parm_index] = flags;
+ }
+ else if (summary_lto)
+ {
+ if (parm_index >= summary_lto->arg_flags.length ())
+ summary_lto->arg_flags.safe_grow_cleared (count, true);
+ summary_lto->arg_flags[parm_index] = flags;
+ }
+ if (lattice[SSA_NAME_VERSION (name)].escape_points.length ())
+ {
+ escape_point *ep;
+ unsigned int ip;
+ cgraph_node *node = cgraph_node::get (current_function_decl);
+
+ gcc_checking_assert (ipa);
+ FOR_EACH_VEC_ELT
+ (lattice[SSA_NAME_VERSION (name)].escape_points, ip, ep)
+ if ((ep->min_flags & flags) != flags)
+ {
+ cgraph_edge *e = node->get_edge (ep->call);
+ struct escape_entry ee = {parm_index, ep->arg,
+ ep->min_flags, ep->direct};
+
+ escape_summaries->get_create (e)->esc.safe_push (ee);
+ }
+ }
+ }
+ }
+ if (ipa)
+ for (unsigned int i = 0; i < num_ssa_names; i++)
+ lattice[i].release ();
+}
+
/* Analyze function F. IPA indicates whether we're running in local mode
(false) or the IPA mode (true). */
@@ -870,7 +1948,7 @@ analyze_function (function *f, bool ipa)
summary = optimization_summaries->get_create (cgraph_node::get (f->decl));
gcc_checking_assert (nolto && !lto);
}
- /* In IPA mode we analyze every function precisely once. Asser that. */
+ /* In IPA mode we analyze every function precisely once. Assert that. */
else
{
if (nolto)
@@ -889,6 +1967,10 @@ analyze_function (function *f, bool ipa)
summaries_lto->remove (cgraph_node::get (f->decl));
summary_lto = summaries_lto->get_create (cgraph_node::get (f->decl));
}
+ if (!fnspec_summaries)
+ fnspec_summaries = new fnspec_summaries_t (symtab);
+ if (!escape_summaries)
+ escape_summaries = new escape_summaries_t (symtab);
}
@@ -905,6 +1987,7 @@ analyze_function (function *f, bool ipa)
summary->stores = modref_records::create_ggc (param_modref_max_bases,
param_modref_max_refs,
param_modref_max_accesses);
+ summary->writes_errno = false;
}
if (lto)
{
@@ -918,7 +2001,11 @@ analyze_function (function *f, bool ipa)
(param_modref_max_bases,
param_modref_max_refs,
param_modref_max_accesses);
+ summary_lto->writes_errno = false;
}
+
+ analyze_parms (summary, summary_lto, ipa);
+
int ecf_flags = flags_from_decl_or_type (current_function_decl);
auto_vec <gimple *, 32> recursive_calls;
@@ -933,11 +2020,13 @@ analyze_function (function *f, bool ipa)
{
if (!analyze_stmt (summary, summary_lto,
gsi_stmt (si), ipa, &recursive_calls)
- || ((!summary || !summary->useful_p (ecf_flags))
- && (!summary_lto || !summary_lto->useful_p (ecf_flags))))
+ || ((!summary || !summary->useful_p (ecf_flags, false))
+ && (!summary_lto
+ || !summary_lto->useful_p (ecf_flags, false))))
{
- remove_summary (lto, nolto, ipa);
- return;
+ collapse_loads (summary, summary_lto);
+ collapse_stores (summary, summary_lto);
+ break;
}
}
}
@@ -958,7 +2047,7 @@ analyze_function (function *f, bool ipa)
gimple_call_flags
(recursive_calls[i])),
fnode);
- if (!summary->useful_p (ecf_flags))
+ if (!summary->useful_p (ecf_flags, false))
{
remove_summary (lto, nolto, ipa);
return;
@@ -979,6 +2068,8 @@ analyze_function (function *f, bool ipa)
summaries_lto->remove (fnode);
summary_lto = NULL;
}
+ if (ipa && !summary && !summary_lto)
+ remove_modref_edge_summaries (fnode);
if (dump_file)
{
@@ -987,6 +2078,7 @@ analyze_function (function *f, bool ipa)
summary->dump (dump_file);
if (summary_lto)
summary_lto->dump (dump_file);
+ dump_modref_edge_summaries (dump_file, fnode, 2);
}
}
@@ -1018,7 +2110,8 @@ modref_summaries::insert (struct cgraph_node *node, modref_summary *)
optimization_summaries->remove (node);
return;
}
- if (!DECL_STRUCT_FUNCTION (node->decl))
+ if (!DECL_STRUCT_FUNCTION (node->decl)
+ || !opt_for_fn (node->decl, flag_ipa_modref))
{
summaries->remove (node);
return;
@@ -1037,6 +2130,7 @@ modref_summaries_lto::insert (struct cgraph_node *node, modref_summary_lto *)
propagated. This is done only by SIMD cloning that is not very
critical. */
if (!DECL_STRUCT_FUNCTION (node->decl)
+ || !opt_for_fn (node->decl, flag_ipa_modref)
|| propagated)
{
summaries_lto->remove (node);
@@ -1054,7 +2148,7 @@ modref_summaries::duplicate (cgraph_node *, cgraph_node *dst,
modref_summary *src_data,
modref_summary *dst_data)
{
- /* Do not duplicte optimization summaries; we do not handle parameter
+ /* Do not duplicate optimization summaries; we do not handle parameter
transforms on them. */
if (this == optimization_summaries)
{
@@ -1071,6 +2165,9 @@ modref_summaries::duplicate (cgraph_node *, cgraph_node *dst,
src_data->loads->max_refs,
src_data->loads->max_accesses);
dst_data->loads->copy_from (src_data->loads);
+ dst_data->writes_errno = src_data->writes_errno;
+ if (src_data->arg_flags.length ())
+ dst_data->arg_flags = src_data->arg_flags.copy ();
}
/* Called when new clone is inserted to callgraph late. */
@@ -1080,6 +2177,9 @@ modref_summaries_lto::duplicate (cgraph_node *, cgraph_node *,
modref_summary_lto *src_data,
modref_summary_lto *dst_data)
{
+ /* Be sure that no further cloning happens after ipa-modref. If it does
+ we will need to update signatures for possible param changes. */
+ gcc_checking_assert (!((modref_summaries_lto *)summaries_lto)->propagated);
dst_data->stores = modref_records_lto::create_ggc
(src_data->stores->max_bases,
src_data->stores->max_refs,
@@ -1090,6 +2190,9 @@ modref_summaries_lto::duplicate (cgraph_node *, cgraph_node *,
src_data->loads->max_refs,
src_data->loads->max_accesses);
dst_data->loads->copy_from (src_data->loads);
+ dst_data->writes_errno = src_data->writes_errno;
+ if (src_data->arg_flags.length ())
+ dst_data->arg_flags = src_data->arg_flags.copy ();
}
namespace
@@ -1314,6 +2417,49 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in,
(*nolto_ret)->cleanup ();
}
+/* Write ESUM to BP. */
+
+static void
+modref_write_escape_summary (struct bitpack_d *bp, escape_summary *esum)
+{
+ if (!esum)
+ {
+ bp_pack_var_len_unsigned (bp, 0);
+ return;
+ }
+ bp_pack_var_len_unsigned (bp, esum->esc.length ());
+ unsigned int i;
+ escape_entry *ee;
+ FOR_EACH_VEC_ELT (esum->esc, i, ee)
+ {
+ bp_pack_var_len_unsigned (bp, ee->parm_index);
+ bp_pack_var_len_unsigned (bp, ee->arg);
+ bp_pack_var_len_unsigned (bp, ee->min_flags);
+ bp_pack_value (bp, ee->direct, 1);
+ }
+}
+
+/* Read escape summary for E from BP. */
+
+static void
+modref_read_escape_summary (struct bitpack_d *bp, cgraph_edge *e)
+{
+ unsigned int n = bp_unpack_var_len_unsigned (bp);
+ if (!n)
+ return;
+ escape_summary *esum = escape_summaries->get_create (e);
+ esum->esc.reserve_exact (n);
+ for (unsigned int i = 0; i < n; i++)
+ {
+ escape_entry ee;
+ ee.parm_index = bp_unpack_var_len_unsigned (bp);
+ ee.arg = bp_unpack_var_len_unsigned (bp);
+ ee.min_flags = bp_unpack_var_len_unsigned (bp);
+ ee.direct = bp_unpack_value (bp, 1);
+ esum->esc.quick_push (ee);
+ }
+}
+
/* Callback for write_summary. */
static void
@@ -1353,7 +2499,6 @@ modref_write ()
if (cnode && cnode->definition && !cnode->alias)
{
-
modref_summary_lto *r = summaries_lto->get (cnode);
if (!r || !r->useful_p (flags_from_decl_or_type (cnode->decl)))
@@ -1361,8 +2506,38 @@ modref_write ()
streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder, cnode));
+ streamer_write_uhwi (ob, r->arg_flags.length ());
+ for (unsigned int i = 0; i < r->arg_flags.length (); i++)
+ streamer_write_char_stream (ob->main_stream, r->arg_flags[i]);
+
write_modref_records (r->loads, ob);
write_modref_records (r->stores, ob);
+
+ struct bitpack_d bp = bitpack_create (ob->main_stream);
+ bp_pack_value (&bp, r->writes_errno, 1);
+ if (!flag_wpa)
+ {
+ for (cgraph_edge *e = cnode->indirect_calls;
+ e; e = e->next_callee)
+ {
+ class fnspec_summary *sum = fnspec_summaries->get (e);
+ bp_pack_value (&bp, sum != NULL, 1);
+ if (sum)
+ bp_pack_string (ob, &bp, sum->fnspec, true);
+ class escape_summary *esum = escape_summaries->get (e);
+ modref_write_escape_summary (&bp,esum);
+ }
+ for (cgraph_edge *e = cnode->callees; e; e = e->next_callee)
+ {
+ class fnspec_summary *sum = fnspec_summaries->get (e);
+ bp_pack_value (&bp, sum != NULL, 1);
+ if (sum)
+ bp_pack_string (ob, &bp, sum->fnspec, true);
+ class escape_summary *esum = escape_summaries->get (e);
+ modref_write_escape_summary (&bp,esum);
+ }
+ }
+ streamer_write_bitpack (&bp);
}
}
streamer_write_char_stream (ob->main_stream, 0);
@@ -1405,20 +2580,66 @@ read_section (struct lto_file_decl_data *file_data, const char *data,
modref_summary_lto *modref_sum_lto = summaries_lto
? summaries_lto->get_create (node)
: NULL;
-
if (optimization_summaries)
modref_sum = optimization_summaries->get_create (node);
+ if (modref_sum)
+ modref_sum->writes_errno = false;
+ if (modref_sum_lto)
+ modref_sum_lto->writes_errno = false;
+
gcc_assert (!modref_sum || (!modref_sum->loads
&& !modref_sum->stores));
gcc_assert (!modref_sum_lto || (!modref_sum_lto->loads
&& !modref_sum_lto->stores));
+ unsigned int args = streamer_read_uhwi (&ib);
+ if (args && modref_sum)
+ modref_sum->arg_flags.reserve_exact (args);
+ if (args && modref_sum_lto)
+ modref_sum_lto->arg_flags.reserve_exact (args);
+ for (unsigned int i = 0; i < args; i++)
+ {
+ unsigned char flags = streamer_read_uchar (&ib);
+ if (modref_sum)
+ modref_sum->arg_flags.quick_push (flags);
+ if (modref_sum_lto)
+ modref_sum_lto->arg_flags.quick_push (flags);
+ }
read_modref_records (&ib, data_in,
modref_sum ? &modref_sum->loads : NULL,
modref_sum_lto ? &modref_sum_lto->loads : NULL);
read_modref_records (&ib, data_in,
modref_sum ? &modref_sum->stores : NULL,
modref_sum_lto ? &modref_sum_lto->stores : NULL);
+ struct bitpack_d bp = streamer_read_bitpack (&ib);
+ if (bp_unpack_value (&bp, 1))
+ {
+ if (modref_sum)
+ modref_sum->writes_errno = true;
+ if (modref_sum_lto)
+ modref_sum_lto->writes_errno = true;
+ }
+ if (!flag_ltrans)
+ {
+ for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
+ {
+ if (bp_unpack_value (&bp, 1))
+ {
+ class fnspec_summary *sum = fnspec_summaries->get_create (e);
+ sum->fnspec = xstrdup (bp_unpack_string (data_in, &bp));
+ }
+ modref_read_escape_summary (&bp, e);
+ }
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ if (bp_unpack_value (&bp, 1))
+ {
+ class fnspec_summary *sum = fnspec_summaries->get_create (e);
+ sum->fnspec = xstrdup (bp_unpack_string (data_in, &bp));
+ }
+ modref_read_escape_summary (&bp, e);
+ }
+ }
if (dump_file)
{
fprintf (dump_file, "Read modref for %s\n",
@@ -1427,6 +2648,7 @@ read_section (struct lto_file_decl_data *file_data, const char *data,
modref_sum->dump (dump_file);
if (modref_sum_lto)
modref_sum_lto->dump (dump_file);
+ dump_modref_edge_summaries (dump_file, node, 4);
}
}
@@ -1455,6 +2677,10 @@ modref_read (void)
|| (flag_incremental_link == INCREMENTAL_LINK_LTO
&& flag_fat_lto_objects))
summaries = modref_summaries::create_ggc (symtab);
+ if (!fnspec_summaries)
+ fnspec_summaries = new fnspec_summaries_t (symtab);
+ if (!escape_summaries)
+ escape_summaries = new escape_summaries_t (symtab);
}
while ((file_data = file_data_vec[j++]))
@@ -1474,56 +2700,65 @@ modref_read (void)
}
}
-/* Update parameter indexes in TT according to MAP. */
+/* Recompute arg_flags for param adjustments in INFO. */
-void
-remap_arguments (vec <int> *map, modref_records *tt)
+static void
+remap_arg_flags (auto_vec <unsigned char> &arg_flags, clone_info *info)
{
+ auto_vec<unsigned char> old = arg_flags.copy ();
+ int max = -1;
size_t i;
- modref_base_node <alias_set_type> *base_node;
- FOR_EACH_VEC_SAFE_ELT (tt->bases, i, base_node)
+ ipa_adjusted_param *p;
+
+ arg_flags.release ();
+
+ FOR_EACH_VEC_SAFE_ELT (info->param_adjustments->m_adj_params, i, p)
{
- size_t j;
- modref_ref_node <alias_set_type> *ref_node;
- FOR_EACH_VEC_SAFE_ELT (base_node->refs, j, ref_node)
- {
- size_t k;
- modref_access_node *access_node;
- FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node)
- if (access_node->parm_index > 0)
- {
- if (access_node->parm_index < (int)map->length ())
- access_node->parm_index = (*map)[access_node->parm_index];
- else
- access_node->parm_index = -1;
- }
- }
+ int o = info->param_adjustments->get_original_index (i);
+ if (o >= 0 && (int)old.length () > o && old[o])
+ max = i;
+ }
+ if (max >= 0)
+ arg_flags.safe_grow_cleared (max + 1, true);
+ FOR_EACH_VEC_SAFE_ELT (info->param_adjustments->m_adj_params, i, p)
+ {
+ int o = info->param_adjustments->get_original_index (i);
+ if (o >= 0 && (int)old.length () > o && old[o])
+ arg_flags[i] = old[o];
}
}
/* If signature changed, update the summary. */
-static unsigned int
-modref_transform (struct cgraph_node *node)
+static void
+update_signature (struct cgraph_node *node)
{
- if (!node->clone.param_adjustments || !optimization_summaries)
- return 0;
- modref_summary *r = optimization_summaries->get (node);
- if (!r)
- return 0;
+ clone_info *info = clone_info::get (node);
+ if (!info || !info->param_adjustments)
+ return;
+
+ modref_summary *r = optimization_summaries
+ ? optimization_summaries->get (node) : NULL;
+ modref_summary_lto *r_lto = summaries_lto
+ ? summaries_lto->get (node) : NULL;
+ if (!r && !r_lto)
+ return;
if (dump_file)
{
fprintf (dump_file, "Updating summary for %s from:\n",
node->dump_name ());
- r->dump (dump_file);
+ if (r)
+ r->dump (dump_file);
+ if (r_lto)
+ r_lto->dump (dump_file);
}
size_t i, max = 0;
ipa_adjusted_param *p;
- FOR_EACH_VEC_SAFE_ELT (node->clone.param_adjustments->m_adj_params, i, p)
+ FOR_EACH_VEC_SAFE_ELT (info->param_adjustments->m_adj_params, i, p)
{
- int idx = node->clone.param_adjustments->get_original_index (i);
+ int idx = info->param_adjustments->get_original_index (i);
if (idx > (int)max)
max = idx;
}
@@ -1533,20 +2768,35 @@ modref_transform (struct cgraph_node *node)
map.reserve (max + 1);
for (i = 0; i <= max; i++)
map.quick_push (-1);
- FOR_EACH_VEC_SAFE_ELT (node->clone.param_adjustments->m_adj_params, i, p)
+ FOR_EACH_VEC_SAFE_ELT (info->param_adjustments->m_adj_params, i, p)
{
- int idx = node->clone.param_adjustments->get_original_index (i);
+ int idx = info->param_adjustments->get_original_index (i);
if (idx >= 0)
map[idx] = i;
}
- remap_arguments (&map, r->loads);
- remap_arguments (&map, r->stores);
+ if (r)
+ {
+ r->loads->remap_params (&map);
+ r->stores->remap_params (&map);
+ if (r->arg_flags.length ())
+ remap_arg_flags (r->arg_flags, info);
+ }
+ if (r_lto)
+ {
+ r_lto->loads->remap_params (&map);
+ r_lto->stores->remap_params (&map);
+ if (r_lto->arg_flags.length ())
+ remap_arg_flags (r_lto->arg_flags, info);
+ }
if (dump_file)
{
fprintf (dump_file, "to:\n");
- r->dump (dump_file);
+ if (r)
+ r->dump (dump_file);
+ if (r_lto)
+ r_lto->dump (dump_file);
}
- return 0;
+ return;
}
/* Definition of the modref IPA pass. */
@@ -1575,7 +2825,7 @@ public:
modref_read, /* read_optimization_summary */
NULL, /* stmt_fixup */
0, /* function_transform_todo_flags_start */
- modref_transform,/* function_transform */
+ NULL, /* function_transform */
NULL) /* variable_transform */
{}
@@ -1631,9 +2881,9 @@ ignore_edge (struct cgraph_edge *e)
& (ECF_CONST | ECF_NOVOPS));
}
-/* Compute parm_map for CALLE_EDGE. */
+/* Compute parm_map for CALLEE_EDGE. */
-static void
+static bool
compute_parm_map (cgraph_edge *callee_edge, vec<modref_parm_map> *parm_map)
{
class ipa_edge_args *args;
@@ -1654,7 +2904,7 @@ compute_parm_map (cgraph_edge *callee_edge, vec<modref_parm_map> *parm_map)
: callee_edge->caller);
callee_pi = IPA_NODE_REF (callee);
- (*parm_map).safe_grow_cleared (count);
+ (*parm_map).safe_grow_cleared (count, true);
for (i = 0; i < count; i++)
{
@@ -1704,7 +2954,7 @@ compute_parm_map (cgraph_edge *callee_edge, vec<modref_parm_map> *parm_map)
(!(ipa_get_jf_ancestor_offset (jf) & (BITS_PER_UNIT - 1)));
(*parm_map)[i].parm_offset
= ipa_get_jf_ancestor_offset (jf) >> LOG2_BITS_PER_UNIT;
- }
+ }
else
(*parm_map)[i].parm_index = -1;
}
@@ -1715,6 +2965,67 @@ compute_parm_map (cgraph_edge *callee_edge, vec<modref_parm_map> *parm_map)
fprintf (dump_file, " %i", (*parm_map)[i].parm_index);
fprintf (dump_file, "\n");
}
+ return true;
+ }
+ return false;
+}
+
+/* Map used to translate escape infos. */
+
+struct escape_map
+{
+ int parm_index;
+ bool direct;
+};
+
+/* Update escape map fo E. */
+
+static void
+update_escape_summary_1 (cgraph_edge *e,
+ vec <vec <escape_map>> &map)
+{
+ escape_summary *sum = escape_summaries->get (e);
+ if (!sum)
+ return;
+ auto_vec <escape_entry> old = sum->esc.copy ();
+ sum->esc.release ();
+
+ unsigned int i;
+ escape_entry *ee;
+ FOR_EACH_VEC_ELT (old, i, ee)
+ {
+ unsigned int j;
+ struct escape_map *em;
+ if (ee->parm_index >= map.length ())
+ continue;
+ FOR_EACH_VEC_ELT (map[ee->parm_index], j, em)
+ {
+ struct escape_entry entry = {em->parm_index, ee->arg,
+ ee->min_flags,
+ ee->direct & em->direct};
+ sum->esc.safe_push (entry);
+ }
+ }
+ if (!sum->esc.length ())
+ escape_summaries->remove (e);
+}
+
+/* Update escape map fo NODE. */
+
+static void
+update_escape_summary (cgraph_node *node,
+ vec <vec <escape_map>> &map)
+{
+ if (!escape_summaries)
+ return;
+ for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
+ update_escape_summary_1 (e, map);
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ if (!e->inline_failed)
+ update_escape_summary (e->callee, map);
+ else
+ update_escape_summary_1 (e, map);
}
}
@@ -1738,6 +3049,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
summaries->remove (edge->callee);
if (summaries_lto)
summaries_lto->remove (edge->callee);
+ remove_modref_edge_summaries (edge->callee);
return;
}
@@ -1746,26 +3058,21 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
class modref_summary_lto *callee_info_lto
= summaries_lto ? summaries_lto->get (edge->callee) : NULL;
int flags = flags_from_decl_or_type (edge->callee->decl);
+ bool ignore_stores = ignore_stores_p (edge->caller->decl, flags);
if (!callee_info && to_info)
{
- if (ignore_stores_p (edge->caller->decl, flags))
+ if (!(flags & (ECF_CONST | ECF_NOVOPS)))
to_info->loads->collapse ();
- else
- {
- summaries->remove (to);
- to_info = NULL;
- }
+ if (!ignore_stores)
+ to_info->stores->collapse ();
}
if (!callee_info_lto && to_info_lto)
{
- if (ignore_stores_p (edge->caller->decl, flags))
+ if (!(flags & (ECF_CONST | ECF_NOVOPS)))
to_info_lto->loads->collapse ();
- else
- {
- summaries_lto->remove (to);
- to_info_lto = NULL;
- }
+ if (!ignore_stores)
+ to_info_lto->stores->collapse ();
}
if (callee_info || callee_info_lto)
{
@@ -1773,18 +3080,82 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
compute_parm_map (edge, &parm_map);
- if (!ignore_stores_p (edge->caller->decl, flags))
+ if (!ignore_stores)
{
if (to_info && callee_info)
to_info->stores->merge (callee_info->stores, &parm_map);
if (to_info_lto && callee_info_lto)
to_info_lto->stores->merge (callee_info_lto->stores, &parm_map);
}
- if (to_info && callee_info)
- to_info->loads->merge (callee_info->loads, &parm_map);
- if (to_info_lto && callee_info_lto)
- to_info_lto->loads->merge (callee_info_lto->loads, &parm_map);
+ if (!(flags & (ECF_CONST | ECF_NOVOPS)))
+ {
+ if (to_info && callee_info)
+ to_info->loads->merge (callee_info->loads, &parm_map);
+ if (to_info_lto && callee_info_lto)
+ to_info_lto->loads->merge (callee_info_lto->loads, &parm_map);
+ }
}
+
+ /* Now merge escape summaries.
+ For every escape to the callee we need to merge calle flags
+ and remap calees escapes. */
+ class escape_summary *sum = escape_summaries->get (edge);
+ int max_escape = -1;
+ escape_entry *ee;
+ unsigned int i;
+
+ if (sum && !(flags & (ECF_CONST | ECF_NOVOPS)))
+ FOR_EACH_VEC_ELT (sum->esc, i, ee)
+ if ((int)ee->arg > max_escape)
+ max_escape = ee->arg;
+
+ auto_vec <vec <struct escape_map>, 32> emap (max_escape + 1);
+ emap.safe_grow (max_escape + 1, true);
+ for (i = 0; (int)i < max_escape + 1; i++)
+ emap[i] = vNULL;
+
+ if (sum && !(flags & (ECF_CONST | ECF_NOVOPS)))
+ FOR_EACH_VEC_ELT (sum->esc, i, ee)
+ {
+ bool needed = false;
+ if (to_info && to_info->arg_flags.length () > ee->parm_index)
+ {
+ int flags = callee_info
+ && callee_info->arg_flags.length () > ee->arg
+ ? callee_info->arg_flags[ee->arg] : 0;
+ if (!ee->direct)
+ flags = deref_flags (flags, ignore_stores);
+ else if (ignore_stores)
+ flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE;
+ flags |= ee->min_flags;
+ to_info->arg_flags[ee->parm_index] &= flags;
+ if (to_info->arg_flags[ee->parm_index])
+ needed = true;
+ }
+ if (to_info_lto && to_info_lto->arg_flags.length () > ee->parm_index)
+ {
+ int flags = callee_info_lto
+ && callee_info_lto->arg_flags.length () > ee->arg
+ ? callee_info_lto->arg_flags[ee->arg] : 0;
+ if (!ee->direct)
+ flags = deref_flags (flags, ignore_stores);
+ else if (ignore_stores)
+ flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE;
+ flags |= ee->min_flags;
+ to_info_lto->arg_flags[ee->parm_index] &= flags;
+ if (to_info_lto->arg_flags[ee->parm_index])
+ needed = true;
+ }
+ struct escape_map entry = {ee->parm_index, ee->direct};
+ if (needed)
+ emap[ee->arg].safe_push (entry);
+ }
+ update_escape_summary (edge->callee, emap);
+ for (i = 0; (int)i < max_escape + 1; i++)
+ emap[i].release ();
+ if (sum)
+ escape_summaries->remove (edge);
+
if (summaries)
{
if (to_info && !to_info->useful_p (flags))
@@ -1793,6 +3164,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
fprintf (dump_file, "Removed mod-ref summary for %s\n",
to->dump_name ());
summaries->remove (to);
+ to_info = NULL;
}
else if (to_info && dump_file)
{
@@ -1819,36 +3191,197 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
fprintf (dump_file, "Updated mod-ref summary for %s\n",
to->dump_name ());
to_info_lto->dump (dump_file);
+ to_info_lto = NULL;
}
if (callee_info_lto)
summaries_lto->remove (edge->callee);
}
+ if (!to_info && !to_info_lto)
+ remove_modref_edge_summaries (to);
return;
}
-/* Collapse loads and return true if something changed. */
+/* Get parameter type from DECL. This is only safe for special cases
+ like builtins we create fnspec for because the type match is checked
+ at fnspec creation time. */
-bool
-collapse_loads (modref_summary *cur_summary,
- modref_summary_lto *cur_summary_lto)
+static tree
+get_parm_type (tree decl, unsigned int i)
{
- bool changed = false;
+ tree t = TYPE_ARG_TYPES (TREE_TYPE (decl));
- if (cur_summary && !cur_summary->loads->every_base)
+ for (unsigned int p = 0; p < i; p++)
+ t = TREE_CHAIN (t);
+ return TREE_VALUE (t);
+}
+
+/* Return access mode for argument I of call E with FNSPEC. */
+
+static modref_access_node
+get_access_for_fnspec (cgraph_edge *e, attr_fnspec &fnspec,
+ unsigned int i, modref_parm_map &map)
+{
+ tree size = NULL_TREE;
+ unsigned int size_arg;
+
+ if (!fnspec.arg_specified_p (i))
+ ;
+ else if (fnspec.arg_max_access_size_given_by_arg_p (i, &size_arg))
+ {
+ cgraph_node *node = e->caller->inlined_to
+ ? e->caller->inlined_to : e->caller;
+ class ipa_node_params *caller_parms_info = IPA_NODE_REF (node);
+ class ipa_edge_args *args = IPA_EDGE_REF (e);
+ struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, size_arg);
+
+ if (jf)
+ size = ipa_value_from_jfunc (caller_parms_info, jf,
+ get_parm_type (e->callee->decl, size_arg));
+ }
+ else if (fnspec.arg_access_size_given_by_type_p (i))
+ size = TYPE_SIZE_UNIT (get_parm_type (e->callee->decl, i));
+ modref_access_node a = {0, -1, -1,
+ map.parm_offset, map.parm_index,
+ map.parm_offset_known};
+ poly_int64 size_hwi;
+ if (size
+ && poly_int_tree_p (size, &size_hwi)
+ && coeffs_in_range_p (size_hwi, 0,
+ HOST_WIDE_INT_MAX / BITS_PER_UNIT))
+ {
+ a.size = -1;
+ a.max_size = size_hwi << LOG2_BITS_PER_UNIT;
+ }
+ return a;
+}
+
+/* Call E in NODE with ECF_FLAGS has no summary; update MODREF_SUMMARY and
+ CUR_SUMMARY_LTO accordingly. Return true if something changed. */
+
+static bool
+propagate_unknown_call (cgraph_node *node,
+ cgraph_edge *e, int ecf_flags,
+ modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto)
+{
+ bool changed = false;
+ class fnspec_summary *fnspec_sum = fnspec_summaries->get (e);
+ auto_vec <modref_parm_map, 32> parm_map;
+ if (fnspec_sum
+ && compute_parm_map (e, &parm_map))
{
- cur_summary->loads->collapse ();
- changed = true;
+ attr_fnspec fnspec (fnspec_sum->fnspec);
+
+ gcc_checking_assert (fnspec.known_p ());
+ if (fnspec.global_memory_read_p ())
+ collapse_loads (cur_summary, cur_summary_lto);
+ else
+ {
+ tree t = TYPE_ARG_TYPES (TREE_TYPE (e->callee->decl));
+ for (unsigned i = 0; i < parm_map.length () && t;
+ i++, t = TREE_CHAIN (t))
+ if (!POINTER_TYPE_P (TREE_VALUE (t)))
+ ;
+ else if (!fnspec.arg_specified_p (i)
+ || fnspec.arg_maybe_read_p (i))
+ {
+ modref_parm_map map = parm_map[i];
+ if (map.parm_index == -2)
+ continue;
+ if (map.parm_index == -1)
+ {
+ collapse_loads (cur_summary, cur_summary_lto);
+ break;
+ }
+ if (cur_summary)
+ changed |= cur_summary->loads->insert
+ (0, 0, get_access_for_fnspec (e, fnspec, i, map));
+ if (cur_summary_lto)
+ changed |= cur_summary_lto->loads->insert
+ (0, 0, get_access_for_fnspec (e, fnspec, i, map));
+ }
+ }
+ if (ignore_stores_p (node->decl, ecf_flags))
+ ;
+ else if (fnspec.global_memory_written_p ())
+ collapse_stores (cur_summary, cur_summary_lto);
+ else
+ {
+ tree t = TYPE_ARG_TYPES (TREE_TYPE (e->callee->decl));
+ for (unsigned i = 0; i < parm_map.length () && t;
+ i++, t = TREE_CHAIN (t))
+ if (!POINTER_TYPE_P (TREE_VALUE (t)))
+ ;
+ else if (!fnspec.arg_specified_p (i)
+ || fnspec.arg_maybe_written_p (i))
+ {
+ modref_parm_map map = parm_map[i];
+ if (map.parm_index == -2)
+ continue;
+ if (map.parm_index == -1)
+ {
+ collapse_stores (cur_summary, cur_summary_lto);
+ break;
+ }
+ if (cur_summary)
+ changed |= cur_summary->stores->insert
+ (0, 0, get_access_for_fnspec (e, fnspec, i, map));
+ if (cur_summary_lto)
+ changed |= cur_summary_lto->stores->insert
+ (0, 0, get_access_for_fnspec (e, fnspec, i, map));
+ }
+ }
+ if (fnspec.errno_maybe_written_p () && flag_errno_math)
+ {
+ if (cur_summary && !cur_summary->writes_errno)
+ {
+ cur_summary->writes_errno = true;
+ changed = true;
+ }
+ if (cur_summary_lto && !cur_summary_lto->writes_errno)
+ {
+ cur_summary_lto->writes_errno = true;
+ changed = true;
+ }
+ }
+ return changed;
}
- if (cur_summary_lto
- && !cur_summary_lto->loads->every_base)
+ if (dump_file)
+ fprintf (dump_file, " collapsing loads\n");
+ changed |= collapse_loads (cur_summary, cur_summary_lto);
+ if (!ignore_stores_p (node->decl, ecf_flags))
{
- cur_summary_lto->loads->collapse ();
- changed = true;
+ if (dump_file)
+ fprintf (dump_file, " collapsing stores\n");
+ changed |= collapse_stores (cur_summary, cur_summary_lto);
}
return changed;
}
-/* Perform iterative dataflow on SCC component starting in COMPONENT_NODE. */
+/* Maybe remove summaies of NODE pointed to by CUR_SUMMARY_PTR
+ and CUR_SUMMARY_LTO_PTR if they are useless according to ECF_FLAGS. */
+
+static void
+remove_useless_summaries (cgraph_node *node,
+ modref_summary **cur_summary_ptr,
+ modref_summary_lto **cur_summary_lto_ptr,
+ int ecf_flags)
+{
+ if (*cur_summary_ptr && !(*cur_summary_ptr)->useful_p (ecf_flags, false))
+ {
+ optimization_summaries->remove (node);
+ *cur_summary_ptr = NULL;
+ }
+ if (*cur_summary_lto_ptr
+ && !(*cur_summary_lto_ptr)->useful_p (ecf_flags, false))
+ {
+ summaries_lto->remove (node);
+ *cur_summary_lto_ptr = NULL;
+ }
+}
+
+/* Perform iterative dataflow on SCC component starting in COMPONENT_NODE
+ and propagate loads/stores. */
static void
modref_propagate_in_scc (cgraph_node *component_node)
@@ -1873,6 +3406,8 @@ modref_propagate_in_scc (cgraph_node *component_node)
if (!cur_summary && !cur_summary_lto)
continue;
+ int cur_ecf_flags = flags_from_decl_or_type (node->decl);
+
if (dump_file)
fprintf (dump_file, " Processing %s%s%s\n",
cur->dump_name (),
@@ -1883,25 +3418,19 @@ modref_propagate_in_scc (cgraph_node *component_node)
{
if (e->indirect_info->ecf_flags & (ECF_CONST | ECF_NOVOPS))
continue;
- if (ignore_stores_p (cur->decl, e->indirect_info->ecf_flags))
- {
- if (dump_file)
- fprintf (dump_file, " Indirect call: "
- "collapsing loads\n");
- changed |= collapse_loads (cur_summary, cur_summary_lto);
- }
- else
+ if (dump_file)
+ fprintf (dump_file, " Indirect call"
+ "collapsing loads\n");
+ if (propagate_unknown_call
+ (node, e, e->indirect_info->ecf_flags,
+ cur_summary, cur_summary_lto))
{
- if (dump_file)
- fprintf (dump_file, " Indirect call: giving up\n");
- if (optimization_summaries)
- optimization_summaries->remove (node);
- if (summaries_lto)
- summaries_lto->remove (node);
changed = true;
- cur_summary = NULL;
- cur_summary_lto = NULL;
- break;
+ remove_useless_summaries (node, &cur_summary,
+ &cur_summary_lto,
+ cur_ecf_flags);
+ if (!cur_summary && !cur_summary_lto)
+ break;
}
}
@@ -1941,30 +3470,15 @@ modref_propagate_in_scc (cgraph_node *component_node)
if (avail <= AVAIL_INTERPOSABLE)
{
- if (!ignore_stores)
- {
- if (dump_file)
- fprintf (dump_file, " Call target interposable"
- " or not available\n");
-
- if (optimization_summaries)
- optimization_summaries->remove (node);
- if (summaries_lto)
- summaries_lto->remove (node);
- cur_summary = NULL;
- cur_summary_lto = NULL;
- changed = true;
- break;
- }
- else
- {
- if (dump_file)
- fprintf (dump_file, " Call target interposable"
- " or not available; collapsing loads\n");
-
- changed |= collapse_loads (cur_summary, cur_summary_lto);
- continue;
- }
+ if (dump_file)
+ fprintf (dump_file, " Call target interposable"
+ " or not available\n");
+ changed |= propagate_unknown_call
+ (node, callee_edge, flags,
+ cur_summary, cur_summary_lto);
+ if (!cur_summary && !cur_summary_lto)
+ break;
+ continue;
}
/* We don't know anything about CALLEE, hence we cannot tell
@@ -1973,52 +3487,20 @@ modref_propagate_in_scc (cgraph_node *component_node)
if (cur_summary
&& !(callee_summary = optimization_summaries->get (callee)))
{
- if (!ignore_stores)
- {
- if (dump_file)
- fprintf (dump_file, " No call target summary\n");
-
- optimization_summaries->remove (node);
- cur_summary = NULL;
- changed = true;
- }
- else
- {
- if (dump_file)
- fprintf (dump_file, " No call target summary;"
- " collapsing loads\n");
-
- if (!cur_summary->loads->every_base)
- {
- cur_summary->loads->collapse ();
- changed = true;
- }
- }
+ if (dump_file)
+ fprintf (dump_file, " No call target summary\n");
+ changed |= propagate_unknown_call
+ (node, callee_edge, flags,
+ cur_summary, NULL);
}
if (cur_summary_lto
&& !(callee_summary_lto = summaries_lto->get (callee)))
{
- if (!ignore_stores)
- {
- if (dump_file)
- fprintf (dump_file, " No call target summary\n");
-
- summaries_lto->remove (node);
- cur_summary_lto = NULL;
- changed = true;
- }
- else
- {
- if (dump_file)
- fprintf (dump_file, " No call target summary;"
- " collapsing loads\n");
-
- if (!cur_summary_lto->loads->every_base)
- {
- cur_summary_lto->loads->collapse ();
- changed = true;
- }
- }
+ if (dump_file)
+ fprintf (dump_file, " No call target summary\n");
+ changed |= propagate_unknown_call
+ (node, callee_edge, flags,
+ NULL, cur_summary_lto);
}
/* We can not safely optimize based on summary of callee if it
@@ -2044,63 +3526,276 @@ modref_propagate_in_scc (cgraph_node *component_node)
changed |= cur_summary->loads->merge
(callee_summary->loads, &parm_map);
if (!ignore_stores)
- changed |= cur_summary->stores->merge
- (callee_summary->stores, &parm_map);
+ {
+ changed |= cur_summary->stores->merge
+ (callee_summary->stores, &parm_map);
+ if (!cur_summary->writes_errno
+ && callee_summary->writes_errno)
+ {
+ cur_summary->writes_errno = true;
+ changed = true;
+ }
+ }
}
if (callee_summary_lto)
{
changed |= cur_summary_lto->loads->merge
(callee_summary_lto->loads, &parm_map);
if (!ignore_stores)
- changed |= cur_summary_lto->stores->merge
- (callee_summary_lto->stores, &parm_map);
+ {
+ changed |= cur_summary_lto->stores->merge
+ (callee_summary_lto->stores, &parm_map);
+ if (!cur_summary_lto->writes_errno
+ && callee_summary_lto->writes_errno)
+ {
+ cur_summary_lto->writes_errno = true;
+ changed = true;
+ }
+ }
}
+ if (changed)
+ remove_useless_summaries (node, &cur_summary,
+ &cur_summary_lto,
+ cur_ecf_flags);
+ if (!cur_summary && !cur_summary_lto)
+ break;
if (dump_file && changed)
{
if (cur_summary)
cur_summary->dump (dump_file);
if (cur_summary_lto)
cur_summary_lto->dump (dump_file);
+ dump_modref_edge_summaries (dump_file, node, 4);
}
}
}
iteration++;
}
if (dump_file)
+ fprintf (dump_file,
+ "Propagation finished in %i iterations\n", iteration);
+}
+
+/* Dump results of propagation in SCC rooted in COMPONENT_NODE. */
+
+static void
+modref_propagate_dump_scc (cgraph_node *component_node)
+{
+ for (struct cgraph_node *cur = component_node; cur;
+ cur = ((struct ipa_dfs_info *) cur->aux)->next_cycle)
+ if (!cur->inlined_to)
+ {
+ modref_summary *cur_summary = optimization_summaries
+ ? optimization_summaries->get (cur)
+ : NULL;
+ modref_summary_lto *cur_summary_lto = summaries_lto
+ ? summaries_lto->get (cur)
+ : NULL;
+
+ fprintf (dump_file, "Propagated modref for %s%s%s\n",
+ cur->dump_name (),
+ TREE_READONLY (cur->decl) ? " (const)" : "",
+ DECL_PURE_P (cur->decl) ? " (pure)" : "");
+ if (optimization_summaries)
+ {
+ if (cur_summary)
+ cur_summary->dump (dump_file);
+ else
+ fprintf (dump_file, " Not tracked\n");
+ }
+ if (summaries_lto)
+ {
+ if (cur_summary_lto)
+ cur_summary_lto->dump (dump_file);
+ else
+ fprintf (dump_file, " Not tracked (lto)\n");
+ }
+ }
+}
+
+/* Process escapes in SUM and merge SUMMARY to CUR_SUMMARY
+ and SUMMARY_LTO to CUR_SUMMARY_LTO.
+ Return true if something changed. */
+
+static bool
+modref_merge_call_site_flags (escape_summary *sum,
+ modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto,
+ modref_summary *summary,
+ modref_summary_lto *summary_lto,
+ bool ignore_stores)
+{
+ escape_entry *ee;
+ unsigned int i;
+ bool changed = false;
+
+ /* If we have no useful info to propagate. */
+ if ((!cur_summary || !cur_summary->arg_flags.length ())
+ && (!cur_summary_lto || !cur_summary_lto->arg_flags.length ()))
+ return false;
+
+ FOR_EACH_VEC_ELT (sum->esc, i, ee)
{
- fprintf (dump_file,
- "Propagation finished in %i iterations\n", iteration);
+ int flags = 0;
+ int flags_lto = 0;
+
+ if (summary && ee->arg < summary->arg_flags.length ())
+ flags = summary->arg_flags[ee->arg];
+ if (summary_lto
+ && ee->arg < summary_lto->arg_flags.length ())
+ flags_lto = summary_lto->arg_flags[ee->arg];
+ if (!ee->direct)
+ {
+ flags = deref_flags (flags, ignore_stores);
+ flags_lto = deref_flags (flags_lto, ignore_stores);
+ }
+ else if (ignore_stores)
+ {
+ flags |= EAF_NOESCAPE | EAF_NOCLOBBER | EAF_NODIRECTESCAPE;
+ flags_lto |= EAF_NOESCAPE | EAF_NOCLOBBER | EAF_NODIRECTESCAPE;
+ }
+ flags |= ee->min_flags;
+ flags_lto |= ee->min_flags;
+ if (!(flags & EAF_UNUSED)
+ && cur_summary && ee->parm_index < cur_summary->arg_flags.length ())
+ {
+ int f = cur_summary->arg_flags[ee->parm_index];
+ if ((f & flags) != f)
+ {
+ f = f & flags;
+ if ((f & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
+ f = 0;
+ cur_summary->arg_flags[ee->parm_index] = f;
+ changed = true;
+ }
+ }
+ if (!(flags_lto & EAF_UNUSED)
+ && cur_summary_lto
+ && ee->parm_index < cur_summary_lto->arg_flags.length ())
+ {
+ int f = cur_summary_lto->arg_flags[ee->parm_index];
+ if ((f & flags_lto) != f)
+ {
+ f = f & flags;
+ if ((f & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
+ f = 0;
+ cur_summary_lto->arg_flags[ee->parm_index] = f;
+ changed = true;
+ }
+ }
+ }
+ return changed;
+}
+
+/* Perform iterative dataflow on SCC component starting in COMPONENT_NODE
+ and propagate arg flags. */
+
+static void
+modref_propagate_flags_in_scc (cgraph_node *component_node)
+{
+ bool changed = true;
+ int iteration = 0;
+
+ while (changed)
+ {
+ changed = false;
for (struct cgraph_node *cur = component_node; cur;
cur = ((struct ipa_dfs_info *) cur->aux)->next_cycle)
- if (!cur->inlined_to)
- {
- modref_summary *cur_summary = optimization_summaries
- ? optimization_summaries->get (cur)
- : NULL;
- modref_summary_lto *cur_summary_lto = summaries_lto
- ? summaries_lto->get (cur)
- : NULL;
-
- fprintf (dump_file, "Propagated modref for %s%s%s\n",
+ {
+ cgraph_node *node = cur->inlined_to ? cur->inlined_to : cur;
+ modref_summary *cur_summary = optimization_summaries
+ ? optimization_summaries->get (node)
+ : NULL;
+ modref_summary_lto *cur_summary_lto = summaries_lto
+ ? summaries_lto->get (node)
+ : NULL;
+
+ if (!cur_summary && !cur_summary_lto)
+ continue;
+
+ if (dump_file)
+ fprintf (dump_file, " Processing %s%s%s\n",
cur->dump_name (),
TREE_READONLY (cur->decl) ? " (const)" : "",
DECL_PURE_P (cur->decl) ? " (pure)" : "");
- if (optimization_summaries)
- {
- if (cur_summary)
- cur_summary->dump (dump_file);
- else
- fprintf (dump_file, " Not tracked\n");
- }
- if (summaries_lto)
- {
- if (cur_summary_lto)
- cur_summary_lto->dump (dump_file);
- else
- fprintf (dump_file, " Not tracked (lto)\n");
- }
- }
- }
+
+ for (cgraph_edge *e = cur->indirect_calls; e; e = e->next_callee)
+ {
+ escape_summary *sum = escape_summaries->get (e);
+
+ if (!sum || (e->indirect_info->ecf_flags
+ & (ECF_CONST | ECF_NOVOPS)))
+ continue;
+
+ changed |= modref_merge_call_site_flags
+ (sum, cur_summary, cur_summary_lto,
+ NULL, NULL, ignore_stores_p (node->decl,
+ e->indirect_info->ecf_flags));
+ }
+
+ if (!cur_summary && !cur_summary_lto)
+ continue;
+
+ for (cgraph_edge *callee_edge = cur->callees; callee_edge;
+ callee_edge = callee_edge->next_callee)
+ {
+ int flags = flags_from_decl_or_type (callee_edge->callee->decl);
+ modref_summary *callee_summary = NULL;
+ modref_summary_lto *callee_summary_lto = NULL;
+ struct cgraph_node *callee;
+
+ if (flags & (ECF_CONST | ECF_NOVOPS)
+ || !callee_edge->inline_failed)
+ continue;
+ /* Get the callee and its summary. */
+ enum availability avail;
+ callee = callee_edge->callee->function_or_virtual_thunk_symbol
+ (&avail, cur);
+
+ /* It is not necessary to re-process calls outside of the
+ SCC component. */
+ if (iteration > 0
+ && (!callee->aux
+ || ((struct ipa_dfs_info *)cur->aux)->scc_no
+ != ((struct ipa_dfs_info *)callee->aux)->scc_no))
+ continue;
+
+ escape_summary *sum = escape_summaries->get (callee_edge);
+ if (!sum)
+ continue;
+
+ if (dump_file)
+ fprintf (dump_file, " Call to %s\n",
+ callee_edge->callee->dump_name ());
+
+ if (avail <= AVAIL_INTERPOSABLE
+ || callee_edge->call_stmt_cannot_inline_p)
+ ;
+ else
+ {
+ if (cur_summary)
+ callee_summary = optimization_summaries->get (callee);
+ if (cur_summary_lto)
+ callee_summary_lto = summaries_lto->get (callee);
+ }
+ changed |= modref_merge_call_site_flags
+ (sum, cur_summary, cur_summary_lto,
+ callee_summary, callee_summary_lto,
+ ignore_stores_p (node->decl, flags));
+ if (dump_file && changed)
+ {
+ if (cur_summary)
+ cur_summary->dump (dump_file);
+ if (cur_summary_lto)
+ cur_summary_lto->dump (dump_file);
+ }
+ }
+ }
+ iteration++;
+ }
+ if (dump_file)
+ fprintf (dump_file,
+ "Propagation of flags finished in %i iterations\n", iteration);
}
/* Run the IPA pass. This will take a function's summaries and calls and
@@ -2136,11 +3831,21 @@ pass_ipa_modref::execute (function *)
fprintf (dump_file, "\n\nStart of SCC component\n");
modref_propagate_in_scc (component_node);
+ modref_propagate_flags_in_scc (component_node);
+ if (dump_file)
+ modref_propagate_dump_scc (component_node);
}
+ cgraph_node *node;
+ FOR_EACH_FUNCTION (node)
+ update_signature (node);
if (summaries_lto)
((modref_summaries_lto *)summaries_lto)->propagated = true;
ipa_free_postorder_info ();
free (order);
+ delete fnspec_summaries;
+ fnspec_summaries = NULL;
+ delete escape_summaries;
+ escape_summaries = NULL;
return 0;
}
@@ -2154,10 +3859,14 @@ ipa_modref_c_finalize ()
optimization_summaries = NULL;
gcc_checking_assert (!summaries);
if (summaries_lto)
- {
- ggc_delete (summaries_lto);
- summaries_lto = NULL;
- }
+ ggc_delete (summaries_lto);
+ summaries_lto = NULL;
+ if (fnspec_summaries)
+ delete fnspec_summaries;
+ fnspec_summaries = NULL;
+ if (escape_summaries)
+ delete escape_summaries;
+ escape_summaries = NULL;
}
#include "gt-ipa-modref.h"
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index 8828104..7decabd 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -29,11 +29,13 @@ struct GTY(()) modref_summary
/* Load and stores in function (transitively closed to all callees) */
modref_records *loads;
modref_records *stores;
+ auto_vec<unsigned char> GTY((skip)) arg_flags;
+ bool writes_errno;
modref_summary ();
~modref_summary ();
void dump (FILE *);
- bool useful_p (int ecf_flags);
+ bool useful_p (int ecf_flags, bool check_flags = true);
};
modref_summary *get_modref_function_summary (cgraph_node *func);
diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
index 438f4bd..9ab4a10 100644
--- a/gcc/ipa-param-manipulation.c
+++ b/gcc/ipa-param-manipulation.c
@@ -40,6 +40,9 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "tree-ssa.h"
#include "tree-inline.h"
+#include "alloc-pool.h"
+#include "symbol-summary.h"
+#include "symtab-clones.h"
/* Actual prefixes of different newly synthetized parameters. Keep in sync
@@ -1072,7 +1075,8 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
ipa_param_performed_split ps;
ps.dummy_decl = dummy_decl;
ps.unit_offset = apm->unit_offset;
- vec_safe_push (m_id->dst_node->clone.performed_splits, ps);
+ vec_safe_push (clone_info::get_create
+ (m_id->dst_node)->performed_splits, ps);
}
else
register_replacement (apm, new_parm);
@@ -1131,11 +1135,11 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
when they were in fact replaced by a constant. */
auto_vec <int, 16> index_mapping;
bool need_remap = false;
+ clone_info *info = clone_info::get (m_id->src_node);
- if (m_id && m_id->src_node->clone.param_adjustments)
+ if (m_id && info && info->param_adjustments)
{
- ipa_param_adjustments *prev_adjustments
- = m_id->src_node->clone.param_adjustments;
+ ipa_param_adjustments *prev_adjustments = info->param_adjustments;
prev_adjustments->get_updated_indices (&index_mapping);
need_remap = true;
}
@@ -1677,6 +1681,8 @@ ipa_param_body_adjustments::modify_call_stmt (gcall **stmt_p)
}
}
gcall *new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
+ if (gimple_has_location (stmt))
+ gimple_set_location (new_stmt, gimple_location (stmt));
gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
gimple_call_copy_flags (new_stmt, stmt);
if (tree lhs = gimple_call_lhs (stmt))
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index a848f1d..130b2f8 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -53,6 +53,8 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "tree-cfgcleanup.h"
#include "options.h"
+#include "symtab-clones.h"
+#include "attr-fnspec.h"
/* Function summary where the parameter infos are actually stored. */
ipa_node_params_t *ipa_node_params_sum = NULL;
@@ -1680,7 +1682,7 @@ build_agg_jump_func_from_list (struct ipa_known_agg_contents_list *list,
int value_count, HOST_WIDE_INT arg_offset,
struct ipa_jump_func *jfunc)
{
- vec_alloc (jfunc->agg.items, value_count);
+ vec_safe_reserve (jfunc->agg.items, value_count, true);
for (; list; list = list->next)
{
struct ipa_agg_jf_item item;
@@ -1773,75 +1775,123 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi,
stmt = SSA_NAME_DEF_STMT (rhs1);
if (!is_gimple_assign (stmt))
- return;
+ break;
rhs1 = gimple_assign_rhs1 (stmt);
}
- code = gimple_assign_rhs_code (stmt);
- switch (gimple_assign_rhs_class (stmt))
+ if (gphi *phi = dyn_cast<gphi *> (stmt))
{
- case GIMPLE_SINGLE_RHS:
- if (is_gimple_ip_invariant (rhs1))
- {
- agg_value->pass_through.operand = rhs1;
- return;
- }
- code = NOP_EXPR;
- break;
+ /* Also special case like the following (a is a formal parameter):
- case GIMPLE_UNARY_RHS:
- /* NOTE: A GIMPLE_UNARY_RHS operation might not be tcc_unary
- (truth_not_expr is example), GIMPLE_BINARY_RHS does not imply
- tcc_binary, this subtleness is somewhat misleading.
+ _12 = *a_11(D).dim[0].stride;
+ ...
+ # iftmp.22_9 = PHI <_12(2), 1(3)>
+ ...
+ parm.6.dim[0].stride = iftmp.22_9;
+ ...
+ __x_MOD_foo (&parm.6, b_31(D));
- Since tcc_unary is widely used in IPA-CP code to check an operation
- with one operand, here we only allow tc_unary operation to avoid
- possible problem. Then we can use (opclass == tc_unary) or not to
- distinguish unary and binary. */
- if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code))
+ The aggregate function describing parm.6.dim[0].stride is encoded as a
+ PASS-THROUGH jump function with ASSERT_EXPR operation whith operand 1
+ (the constant from the PHI node). */
+
+ if (gimple_phi_num_args (phi) != 2)
+ return;
+ tree arg0 = gimple_phi_arg_def (phi, 0);
+ tree arg1 = gimple_phi_arg_def (phi, 1);
+ tree operand;
+
+ if (is_gimple_ip_invariant (arg1))
+ {
+ operand = arg1;
+ rhs1 = arg0;
+ }
+ else if (is_gimple_ip_invariant (arg0))
+ {
+ operand = arg0;
+ rhs1 = arg1;
+ }
+ else
return;
rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt);
- break;
+ if (!is_gimple_assign (stmt))
+ return;
- case GIMPLE_BINARY_RHS:
- {
- gimple *rhs1_stmt = stmt;
- gimple *rhs2_stmt = stmt;
- tree rhs2 = gimple_assign_rhs2 (stmt);
+ code = ASSERT_EXPR;
+ agg_value->pass_through.operand = operand;
+ }
+ else if (is_gimple_assign (stmt))
+ {
+ code = gimple_assign_rhs_code (stmt);
+ switch (gimple_assign_rhs_class (stmt))
+ {
+ case GIMPLE_SINGLE_RHS:
+ if (is_gimple_ip_invariant (rhs1))
+ {
+ agg_value->pass_through.operand = rhs1;
+ return;
+ }
+ code = NOP_EXPR;
+ break;
- rhs1 = get_ssa_def_if_simple_copy (rhs1, &rhs1_stmt);
- rhs2 = get_ssa_def_if_simple_copy (rhs2, &rhs2_stmt);
+ case GIMPLE_UNARY_RHS:
+ /* NOTE: A GIMPLE_UNARY_RHS operation might not be tcc_unary
+ (truth_not_expr is example), GIMPLE_BINARY_RHS does not imply
+ tcc_binary, this subtleness is somewhat misleading.
+
+ Since tcc_unary is widely used in IPA-CP code to check an operation
+ with one operand, here we only allow tc_unary operation to avoid
+ possible problem. Then we can use (opclass == tc_unary) or not to
+ distinguish unary and binary. */
+ if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code))
+ return;
- if (is_gimple_ip_invariant (rhs2))
- {
- agg_value->pass_through.operand = rhs2;
- stmt = rhs1_stmt;
- }
- else if (is_gimple_ip_invariant (rhs1))
+ rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt);
+ break;
+
+ case GIMPLE_BINARY_RHS:
{
- if (TREE_CODE_CLASS (code) == tcc_comparison)
- code = swap_tree_comparison (code);
- else if (!commutative_tree_code (code))
+ gimple *rhs1_stmt = stmt;
+ gimple *rhs2_stmt = stmt;
+ tree rhs2 = gimple_assign_rhs2 (stmt);
+
+ rhs1 = get_ssa_def_if_simple_copy (rhs1, &rhs1_stmt);
+ rhs2 = get_ssa_def_if_simple_copy (rhs2, &rhs2_stmt);
+
+ if (is_gimple_ip_invariant (rhs2))
+ {
+ agg_value->pass_through.operand = rhs2;
+ stmt = rhs1_stmt;
+ }
+ else if (is_gimple_ip_invariant (rhs1))
+ {
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ code = swap_tree_comparison (code);
+ else if (!commutative_tree_code (code))
+ return;
+
+ agg_value->pass_through.operand = rhs1;
+ stmt = rhs2_stmt;
+ rhs1 = rhs2;
+ }
+ else
return;
- agg_value->pass_through.operand = rhs1;
- stmt = rhs2_stmt;
- rhs1 = rhs2;
+ if (TREE_CODE_CLASS (code) != tcc_comparison
+ && !useless_type_conversion_p (TREE_TYPE (lhs),
+ TREE_TYPE (rhs1)))
+ return;
}
- else
- return;
+ break;
- if (TREE_CODE_CLASS (code) != tcc_comparison
- && !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs1)))
+ default:
return;
- }
- break;
-
- default:
- return;
- }
+ }
+ }
+ else
+ return;
if (TREE_CODE (rhs1) != SSA_NAME)
index = load_from_unmodified_param_or_agg (fbi, fbi->info, stmt,
@@ -2363,7 +2413,8 @@ ipa_compute_jump_functions_for_bb (struct ipa_func_body_info *fbi, basic_block b
callee = callee->ultimate_alias_target ();
/* We do not need to bother analyzing calls to unknown functions
unless they may become known during lto/whopr. */
- if (!callee->definition && !flag_lto)
+ if (!callee->definition && !flag_lto
+ && !gimple_call_fnspec (cs->call_stmt).known_p ())
continue;
}
ipa_compute_jump_functions_for_edge (fbi, cs);
@@ -4211,7 +4262,10 @@ ipcp_transformation_initialize (void)
if (!ipa_vr_hash_table)
ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
if (ipcp_transformation_sum == NULL)
- ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
+ {
+ ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
+ ipcp_transformation_sum->disable_insertion_hook ();
+ }
}
/* Release the IPA CP transformation summary. */
@@ -4739,7 +4793,10 @@ ipa_read_jump_function (class lto_input_block *ib,
count = streamer_read_uhwi (ib);
if (prevails)
- vec_alloc (jump_func->agg.items, count);
+ {
+ jump_func->agg.items = NULL;
+ vec_safe_reserve (jump_func->agg.items, count, true);
+ }
if (count)
{
struct bitpack_d bp = streamer_read_bitpack (ib);
@@ -4970,7 +5027,11 @@ ipa_read_edge_info (class lto_input_block *ib,
count /= 2;
if (!count)
return;
- if (prevails && e->possibly_call_in_translation_unit_p ())
+ if (prevails
+ && (e->possibly_call_in_translation_unit_p ()
+ /* Also stream in jump functions to builtins in hope that they
+ will get fnspecs. */
+ || fndecl_built_in_p (e->callee->decl, BUILT_IN_NORMAL)))
{
class ipa_edge_args *args = IPA_EDGE_REF_GET_CREATE (e);
vec_safe_grow_cleared (args->jump_functions, count, true);
@@ -5416,12 +5477,13 @@ adjust_agg_replacement_values (struct cgraph_node *node,
struct ipa_agg_replacement_value *aggval)
{
struct ipa_agg_replacement_value *v;
+ clone_info *cinfo = clone_info::get (node);
- if (!node->clone.param_adjustments)
+ if (!cinfo || !cinfo->param_adjustments)
return;
auto_vec<int, 16> new_indices;
- node->clone.param_adjustments->get_updated_indices (&new_indices);
+ cinfo->param_adjustments->get_updated_indices (&new_indices);
for (v = aggval; v; v = v->next)
{
gcc_checking_assert (v->index >= 0);
@@ -5574,9 +5636,10 @@ ipcp_get_parm_bits (tree parm, tree *value, widest_int *mask)
return false;
}
- if (cnode->clone.param_adjustments)
+ clone_info *cinfo = clone_info::get (cnode);
+ if (cinfo && cinfo->param_adjustments)
{
- i = cnode->clone.param_adjustments->get_original_index (i);
+ i = cinfo->param_adjustments->get_original_index (i);
if (i < 0)
return false;
}
@@ -5607,9 +5670,10 @@ ipcp_update_bits (struct cgraph_node *node)
auto_vec<int, 16> new_indices;
bool need_remapping = false;
- if (node->clone.param_adjustments)
+ clone_info *cinfo = clone_info::get (node);
+ if (cinfo && cinfo->param_adjustments)
{
- node->clone.param_adjustments->get_updated_indices (&new_indices);
+ cinfo->param_adjustments->get_updated_indices (&new_indices);
need_remapping = true;
}
auto_vec <tree, 16> parm_decls;
@@ -5728,9 +5792,10 @@ ipcp_update_vr (struct cgraph_node *node)
auto_vec<int, 16> new_indices;
bool need_remapping = false;
- if (node->clone.param_adjustments)
+ clone_info *cinfo = clone_info::get (node);
+ if (cinfo && cinfo->param_adjustments)
{
- node->clone.param_adjustments->get_updated_indices (&new_indices);
+ cinfo->param_adjustments->get_updated_indices (&new_indices);
need_remapping = true;
}
auto_vec <tree, 16> parm_decls;
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 0bbbbf9..112a1ba 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -94,9 +94,14 @@ struct GTY(()) ipa_pass_through_data
/* Number of the caller's formal parameter being passed. */
int formal_id;
/* Operation that is performed on the argument before it is passed on.
- NOP_EXPR means no operation. Otherwise oper must be a simple binary
- arithmetic operation where the caller's parameter is the first operand and
- operand field from this structure is the second one. */
+ Special values which have other meaning than in normal contexts:
+ - NOP_EXPR means no operation, not even type conversion.
+ - ASSERT_EXPR means that only the value in operand is allowed to pass
+ through (without any change), for all other values the result is
+ unknown.
+ Otherwise operation must be a simple binary or unary arithmetic operation
+ where the caller's parameter is the first operand and (for binary
+ operations) the operand field from this structure is the second one. */
enum tree_code operation;
/* When the passed value is a pointer, it is set to true only when we are
certain that no write to the object it points to has occurred since the
@@ -620,6 +625,7 @@ inline
ipa_node_params::~ipa_node_params ()
{
free (lattices);
+ vec_free (descriptors);
known_csts.release ();
known_contexts.release ();
}
@@ -895,6 +901,10 @@ class GTY((for_user)) ipa_edge_args
/* Destructor. */
~ipa_edge_args ()
{
+ unsigned int i;
+ ipa_jump_func *jf;
+ FOR_EACH_VEC_SAFE_ELT (jump_functions, i, jf)
+ vec_free (jf->agg.items);
vec_free (jump_functions);
vec_free (polymorphic_call_contexts);
}
@@ -941,7 +951,10 @@ class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *>
{
public:
ipa_node_params_t (symbol_table *table, bool ggc):
- function_summary<ipa_node_params *> (table, ggc) { }
+ function_summary<ipa_node_params *> (table, ggc)
+ {
+ disable_insertion_hook ();
+ }
/* Hook that is called by summary when a node is duplicated. */
virtual void duplicate (cgraph_node *node,
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 054f359..4c47eec 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1973,7 +1973,8 @@ propagate_malloc (void)
funct_state l = funct_state_summaries->get (node);
if (!node->alias
&& l->malloc_state == STATE_MALLOC
- && !node->inlined_to)
+ && !node->inlined_to
+ && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (node->decl))))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Function %s found to be malloc\n",
diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c
index 241828e..b7217c4 100644
--- a/gcc/ipa-ref.c
+++ b/gcc/ipa-ref.c
@@ -32,7 +32,6 @@ ipa_ref::remove_reference ()
{
struct ipa_ref_list *list = referred_ref_list ();
struct ipa_ref_list *list2 = referring_ref_list ();
- vec<ipa_ref_t, va_gc> *old_references = list2->references;
struct ipa_ref *last;
gcc_assert (list->referring[referred_index] == this);
@@ -66,7 +65,7 @@ ipa_ref::remove_reference ()
}
list->referring.pop ();
- last = &list2->references->last ();
+ last = &list2->references.last ();
struct ipa_ref *ref = this;
@@ -75,8 +74,7 @@ ipa_ref::remove_reference ()
*ref = *last;
ref->referred_ref_list ()->referring[referred_index] = ref;
}
- list2->references->pop ();
- gcc_assert (list2->references == old_references);
+ list2->references.pop ();
}
/* Return true when execution of reference can lead to return from
diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
index 1de5bd3..3ea3f66 100644
--- a/gcc/ipa-ref.h
+++ b/gcc/ipa-ref.h
@@ -27,7 +27,7 @@ struct symtab_node;
/* How the reference is done. */
-enum GTY(()) ipa_ref_use
+enum ipa_ref_use
{
IPA_REF_LOAD,
IPA_REF_STORE,
@@ -36,7 +36,7 @@ enum GTY(()) ipa_ref_use
};
/* Record of reference in callgraph or varpool. */
-struct GTY(()) ipa_ref
+struct ipa_ref
{
public:
/* Remove reference. */
@@ -59,28 +59,27 @@ public:
symtab_node *referred;
gimple *stmt;
unsigned int lto_stmt_uid;
+ unsigned int referred_index;
/* speculative id is used to link direct calls with their corresponding
IPA_REF_ADDR references when representing speculative calls. */
unsigned int speculative_id : 16;
- unsigned int referred_index;
ENUM_BITFIELD (ipa_ref_use) use:3;
unsigned int speculative:1;
};
typedef struct ipa_ref ipa_ref_t;
-typedef struct ipa_ref *ipa_ref_ptr;
/* List of references. This is stored in both callgraph and varpool nodes. */
-struct GTY(()) ipa_ref_list
+struct ipa_ref_list
{
public:
/* Return first reference in list or NULL if empty. */
struct ipa_ref *first_reference (void)
{
- if (!vec_safe_length (references))
+ if (!references.length ())
return NULL;
- return &(*references)[0];
+ return &references[0];
}
/* Return first referring ref in list or NULL if empty. */
@@ -121,20 +120,20 @@ public:
void clear (void)
{
referring.create (0);
- references = NULL;
+ references.create (0);
}
/* Return number of references. */
unsigned int nreferences (void)
{
- return vec_safe_length (references);
+ return references.length ();
}
/* Store actual references in references vector. */
- vec<ipa_ref_t, va_gc> *references;
+ vec<ipa_ref_t, va_heap, vl_ptr> references;
/* Referring is vector of pointers to references. It must not live in GGC space
or GGC will try to mark middle of references vectors. */
- vec<ipa_ref_ptr> GTY((skip)) referring;
+ vec<ipa_ref_t *, va_heap, vl_ptr> referring;
};
#endif /* GCC_IPA_REF_H */
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 4a6c011..871c997 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -894,7 +894,10 @@ propagate (void)
}
if (ipa_ref_opt_sum_summaries == NULL)
- ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+ {
+ ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+ ipa_ref_opt_sum_summaries->disable_insertion_hook ();
+ }
/* Cleanup. */
FOR_EACH_DEFINED_FUNCTION (node)
@@ -1130,6 +1133,7 @@ ipa_reference_read_optimization_summary (void)
gcc_checking_assert (ipa_ref_opt_sum_summaries == NULL);
ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
+ ipa_ref_opt_sum_summaries->disable_insertion_hook ();
ipa_reference_vars_map = new reference_vars_map_t(257);
varpool_node_hooks
= symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c
index 8d4f580..7adc4b6 100644
--- a/gcc/ipa-sra.c
+++ b/gcc/ipa-sra.c
@@ -84,6 +84,9 @@ along with GCC; see the file COPYING3. If not see
#include "cfganal.h"
#include "tree-streamer.h"
#include "internal-fn.h"
+#include "symtab-clones.h"
+
+static void ipa_sra_summarize_function (cgraph_node *);
/* Bits used to track size of an aggregate in bytes interprocedurally. */
#define ISRA_ARG_SIZE_LIMIT_BITS 16
@@ -373,6 +376,7 @@ public:
virtual void duplicate (cgraph_node *, cgraph_node *,
isra_func_summary *old_sum,
isra_func_summary *new_sum);
+ virtual void insert (cgraph_node *, isra_func_summary *);
};
/* Hook that is called by summary when a node is duplicated. */
@@ -426,6 +430,21 @@ ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *,
static GTY(()) ipa_sra_function_summaries *func_sums;
+/* Hook that is called by summary when new node appears. */
+
+void
+ipa_sra_function_summaries::insert (cgraph_node *node, isra_func_summary *)
+{
+ if (opt_for_fn (node->decl, flag_ipa_sra))
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ ipa_sra_summarize_function (node);
+ pop_cfun ();
+ }
+ else
+ func_sums->remove (node);
+}
+
/* Class to manage call summaries. */
class ipa_sra_call_summaries: public call_summary <isra_call_summary *>
@@ -1461,7 +1480,7 @@ verify_access_tree_1 (gensum_param_access *access, HOST_WIDE_INT parent_offset,
{
while (access)
{
- gcc_assert (access->offset >= 0 && access->size > 0);
+ gcc_assert (access->offset >= 0 && access->size >= 0);
if (parent_size != 0)
{
@@ -2478,79 +2497,6 @@ verify_splitting_accesses (cgraph_node *node, bool certain_must_exist)
}
}
-/* Intraprocedural part of IPA-SRA analysis. Scan function body of NODE and
- create a summary structure describing IPA-SRA opportunities and constraints
- in it. */
-
-static void
-ipa_sra_summarize_function (cgraph_node *node)
-{
- if (dump_file)
- fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
- node->order);
- if (!ipa_sra_preliminary_function_checks (node))
- return;
- gcc_obstack_init (&gensum_obstack);
- isra_func_summary *ifs = func_sums->get_create (node);
- ifs->m_candidate = true;
- tree ret = TREE_TYPE (TREE_TYPE (node->decl));
- ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
-
- decl2desc = new hash_map<tree, gensum_param_desc *>;
- unsigned count = 0;
- for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
- count++;
-
- if (count > 0)
- {
- auto_vec<gensum_param_desc, 16> param_descriptions (count);
- param_descriptions.reserve_exact (count);
- param_descriptions.quick_grow_cleared (count);
-
- bool cfun_pushed = false;
- struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
- if (create_parameter_descriptors (node, &param_descriptions))
- {
- push_cfun (fun);
- cfun_pushed = true;
- final_bbs = BITMAP_ALLOC (NULL);
- bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
- by_ref_count
- * last_basic_block_for_fn (fun));
- aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
- scan_function (node, fun);
-
- if (dump_file)
- {
- dump_gensum_param_descriptors (dump_file, node->decl,
- &param_descriptions);
- fprintf (dump_file, "----------------------------------------\n");
- }
- }
- process_scan_results (node, fun, ifs, &param_descriptions);
-
- if (cfun_pushed)
- pop_cfun ();
- if (bb_dereferences)
- {
- free (bb_dereferences);
- bb_dereferences = NULL;
- BITMAP_FREE (final_bbs);
- final_bbs = NULL;
- }
- }
- isra_analyze_all_outgoing_calls (node);
-
- delete decl2desc;
- decl2desc = NULL;
- obstack_free (&gensum_obstack, NULL);
- if (dump_file)
- fprintf (dump_file, "\n\n");
- if (flag_checking)
- verify_splitting_accesses (node, false);
- return;
-}
-
/* Intraprocedural part of IPA-SRA analysis. Scan bodies of all functions in
this compilation unit and create summary structures describing IPA-SRA
opportunities and constraints in them. */
@@ -3741,10 +3687,11 @@ process_isra_node_results (cgraph_node *node,
auto_vec<bool, 16> surviving_params;
bool check_surviving = false;
- if (node->clone.param_adjustments)
+ clone_info *cinfo = clone_info::get (node);
+ if (cinfo && cinfo->param_adjustments)
{
check_surviving = true;
- node->clone.param_adjustments->get_surviving_params (&surviving_params);
+ cinfo->param_adjustments->get_surviving_params (&surviving_params);
}
unsigned param_count = vec_safe_length (ifs->m_parameters);
@@ -3778,7 +3725,8 @@ process_isra_node_results (cgraph_node *node,
}
vec<ipa_adjusted_param, va_gc> *new_params = NULL;
- if (ipa_param_adjustments *old_adjustments = node->clone.param_adjustments)
+ if (ipa_param_adjustments *old_adjustments
+ = cinfo ? cinfo->param_adjustments : NULL)
{
unsigned old_adj_len = vec_safe_length (old_adjustments->m_adj_params);
for (unsigned i = 0; i < old_adj_len; i++)
@@ -3839,10 +3787,11 @@ disable_unavailable_parameters (cgraph_node *node, isra_func_summary *ifs)
auto_vec<bool, 16> surviving_params;
bool check_surviving = false;
- if (node->clone.param_adjustments)
+ clone_info *cinfo = clone_info::get (node);
+ if (cinfo && cinfo->param_adjustments)
{
check_surviving = true;
- node->clone.param_adjustments->get_surviving_params (&surviving_params);
+ cinfo->param_adjustments->get_surviving_params (&surviving_params);
}
bool dumped_first = false;
for (unsigned i = 0; i < len; i++)
@@ -4102,6 +4051,79 @@ public:
} // anon namespace
+/* Intraprocedural part of IPA-SRA analysis. Scan function body of NODE and
+ create a summary structure describing IPA-SRA opportunities and constraints
+ in it. */
+
+static void
+ipa_sra_summarize_function (cgraph_node *node)
+{
+ if (dump_file)
+ fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (),
+ node->order);
+ if (!ipa_sra_preliminary_function_checks (node))
+ return;
+ gcc_obstack_init (&gensum_obstack);
+ isra_func_summary *ifs = func_sums->get_create (node);
+ ifs->m_candidate = true;
+ tree ret = TREE_TYPE (TREE_TYPE (node->decl));
+ ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE);
+
+ decl2desc = new hash_map<tree, gensum_param_desc *>;
+ unsigned count = 0;
+ for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm))
+ count++;
+
+ if (count > 0)
+ {
+ auto_vec<gensum_param_desc, 16> param_descriptions (count);
+ param_descriptions.reserve_exact (count);
+ param_descriptions.quick_grow_cleared (count);
+
+ bool cfun_pushed = false;
+ struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
+ if (create_parameter_descriptors (node, &param_descriptions))
+ {
+ push_cfun (fun);
+ cfun_pushed = true;
+ final_bbs = BITMAP_ALLOC (NULL);
+ bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
+ by_ref_count
+ * last_basic_block_for_fn (fun));
+ aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps);
+ scan_function (node, fun);
+
+ if (dump_file)
+ {
+ dump_gensum_param_descriptors (dump_file, node->decl,
+ &param_descriptions);
+ fprintf (dump_file, "----------------------------------------\n");
+ }
+ }
+ process_scan_results (node, fun, ifs, &param_descriptions);
+
+ if (cfun_pushed)
+ pop_cfun ();
+ if (bb_dereferences)
+ {
+ free (bb_dereferences);
+ bb_dereferences = NULL;
+ BITMAP_FREE (final_bbs);
+ final_bbs = NULL;
+ }
+ }
+ isra_analyze_all_outgoing_calls (node);
+
+ delete decl2desc;
+ decl2desc = NULL;
+ obstack_free (&gensum_obstack, NULL);
+ if (dump_file)
+ fprintf (dump_file, "\n\n");
+ if (flag_checking)
+ verify_splitting_accesses (node, false);
+ return;
+}
+
ipa_opt_pass_d *
make_pass_ipa_sra (gcc::context *ctxt)
{
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 178c2cb..91571d8 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -211,8 +211,6 @@ type_with_linkage_p (const_tree t)
if (!TYPE_CONTEXT (t))
return false;
- gcc_checking_assert (TREE_CODE (t) == ENUMERAL_TYPE || TYPE_CXX_ODR_P (t));
-
return true;
}
@@ -265,4 +263,16 @@ get_odr_name_for_type (tree type)
return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (type_name));
}
+/* Return true if we are going to do LTO streaming. */
+
+inline bool
+lto_streaming_expected_p ()
+{
+ /* Compilation before LTO stremaing. */
+ if (flag_lto && !in_lto_p && symtab->state < IPA_SSA_AFTER_INLINING)
+ return true;
+ /* WPA or incremental link. */
+ return (flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO);
+}
+
#endif /* GCC_IPA_UTILS_H */
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index d3f8e23..eb52539 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -1407,9 +1407,11 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
register classes bigger modes might be invalid,
e.g. DImode for AREG on x86. For such cases the
register move cost will be maximal. */
- mode = narrower_subreg_mode (mode, ALLOCNO_MODE (cp->second));
+ mode = narrower_subreg_mode (ALLOCNO_MODE (cp->first),
+ ALLOCNO_MODE (cp->second));
+
ira_init_register_move_cost_if_necessary (mode);
-
+
cost = (cp->second == allocno
? ira_register_move_cost[mode][rclass][aclass]
: ira_register_move_cost[mode][aclass][rclass]);
diff --git a/gcc/ira.c b/gcc/ira.c
index a61138c..89b5df4 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1845,6 +1845,7 @@ ira_setup_alts (rtx_insn *insn)
default:
{
enum constraint_num cn = lookup_constraint (p);
+ rtx mem = NULL;
switch (get_constraint_type (cn))
{
case CT_REGISTER:
@@ -1867,8 +1868,12 @@ ira_setup_alts (rtx_insn *insn)
goto op_success;
case CT_MEMORY:
+ mem = op;
+ /* Fall through. */
case CT_SPECIAL_MEMORY:
- if (MEM_P (extract_mem_from_operand (op)))
+ if (!mem)
+ mem = extract_mem_from_operand (op);
+ if (MEM_P (mem))
goto op_success;
win_p = true;
break;
@@ -4661,7 +4666,9 @@ find_moveable_pseudos (void)
|| !DF_REF_INSN_INFO (def)
|| HARD_REGISTER_NUM_P (regno)
|| DF_REG_EQ_USE_COUNT (regno) > 0
- || (!INTEGRAL_MODE_P (mode) && !FLOAT_MODE_P (mode)))
+ || (!INTEGRAL_MODE_P (mode)
+ && !FLOAT_MODE_P (mode)
+ && !OPAQUE_MODE_P (mode)))
continue;
def_insn = DF_REF_INSN (def);
@@ -5133,7 +5140,198 @@ move_unallocated_pseudos (void)
first_moveable_pseudo = last_moveable_pseudo = 0;
}
+
+
+/* Code dealing with scratches (changing them onto
+ pseudos and restoring them from the pseudos).
+
+ We change scratches into pseudos at the beginning of IRA to
+ simplify dealing with them (conflicts, hard register assignments).
+
+ If the pseudo denoting scratch was spilled it means that we do not
+ need a hard register for it. Such pseudos are transformed back to
+ scratches at the end of LRA. */
+
+/* Description of location of a former scratch operand. */
+struct sloc
+{
+ rtx_insn *insn; /* Insn where the scratch was. */
+ int nop; /* Number of the operand which was a scratch. */
+ unsigned regno; /* regno gnerated instead of scratch */
+ int icode; /* Original icode from which scratch was removed. */
+};
+
+typedef struct sloc *sloc_t;
+
+/* Locations of the former scratches. */
+static vec<sloc_t> scratches;
+
+/* Bitmap of scratch regnos. */
+static bitmap_head scratch_bitmap;
+
+/* Bitmap of scratch operands. */
+static bitmap_head scratch_operand_bitmap;
+
+/* Return true if pseudo REGNO is made of SCRATCH. */
+bool
+ira_former_scratch_p (int regno)
+{
+ return bitmap_bit_p (&scratch_bitmap, regno);
+}
+
+/* Return true if the operand NOP of INSN is a former scratch. */
+bool
+ira_former_scratch_operand_p (rtx_insn *insn, int nop)
+{
+ return bitmap_bit_p (&scratch_operand_bitmap,
+ INSN_UID (insn) * MAX_RECOG_OPERANDS + nop) != 0;
+}
+
+/* Register operand NOP in INSN as a former scratch. It will be
+ changed to scratch back, if it is necessary, at the LRA end. */
+void
+ira_register_new_scratch_op (rtx_insn *insn, int nop, int icode)
+{
+ rtx op = *recog_data.operand_loc[nop];
+ sloc_t loc = XNEW (struct sloc);
+ ira_assert (REG_P (op));
+ loc->insn = insn;
+ loc->nop = nop;
+ loc->regno = REGNO (op);
+ loc->icode = icode;
+ scratches.safe_push (loc);
+ bitmap_set_bit (&scratch_bitmap, REGNO (op));
+ bitmap_set_bit (&scratch_operand_bitmap,
+ INSN_UID (insn) * MAX_RECOG_OPERANDS + nop);
+ add_reg_note (insn, REG_UNUSED, op);
+}
+
+/* Return true if string STR contains constraint 'X'. */
+static bool
+contains_X_constraint_p (const char *str)
+{
+ int c;
+
+ while ((c = *str))
+ {
+ str += CONSTRAINT_LEN (c, str);
+ if (c == 'X') return true;
+ }
+ return false;
+}
+
+/* Change INSN's scratches into pseudos and save their location.
+ Return true if we changed any scratch. */
+bool
+ira_remove_insn_scratches (rtx_insn *insn, bool all_p, FILE *dump_file,
+ rtx (*get_reg) (rtx original))
+{
+ int i;
+ bool insn_changed_p;
+ rtx reg, *loc;
+
+ extract_insn (insn);
+ insn_changed_p = false;
+ for (i = 0; i < recog_data.n_operands; i++)
+ {
+ loc = recog_data.operand_loc[i];
+ if (GET_CODE (*loc) == SCRATCH && GET_MODE (*loc) != VOIDmode)
+ {
+ if (! all_p && contains_X_constraint_p (recog_data.constraints[i]))
+ continue;
+ insn_changed_p = true;
+ *loc = reg = get_reg (*loc);
+ ira_register_new_scratch_op (insn, i, INSN_CODE (insn));
+ if (ira_dump_file != NULL)
+ fprintf (dump_file,
+ "Removing SCRATCH to p%u in insn #%u (nop %d)\n",
+ REGNO (reg), INSN_UID (insn), i);
+ }
+ }
+ return insn_changed_p;
+}
+
+/* Return new register of the same mode as ORIGINAL. Used in
+ remove_scratches. */
+static rtx
+get_scratch_reg (rtx original)
+{
+ return gen_reg_rtx (GET_MODE (original));
+}
+
+/* Change scratches into pseudos and save their location. Return true
+ if we changed any scratch. */
+static bool
+remove_scratches (void)
+{
+ bool change_p = false;
+ basic_block bb;
+ rtx_insn *insn;
+
+ scratches.create (get_max_uid ());
+ bitmap_initialize (&scratch_bitmap, &reg_obstack);
+ bitmap_initialize (&scratch_operand_bitmap, &reg_obstack);
+ FOR_EACH_BB_FN (bb, cfun)
+ FOR_BB_INSNS (bb, insn)
+ if (INSN_P (insn)
+ && ira_remove_insn_scratches (insn, false, ira_dump_file, get_scratch_reg))
+ {
+ /* Because we might use DF, we need to keep DF info up to date. */
+ df_insn_rescan (insn);
+ change_p = true;
+ }
+ return change_p;
+}
+
+/* Changes pseudos created by function remove_scratches onto scratches. */
+void
+ira_restore_scratches (FILE *dump_file)
+{
+ int regno, n;
+ unsigned i;
+ rtx *op_loc;
+ sloc_t loc;
+
+ for (i = 0; scratches.iterate (i, &loc); i++)
+ {
+ /* Ignore already deleted insns. */
+ if (NOTE_P (loc->insn)
+ && NOTE_KIND (loc->insn) == NOTE_INSN_DELETED)
+ continue;
+ extract_insn (loc->insn);
+ if (loc->icode != INSN_CODE (loc->insn))
+ {
+ /* The icode doesn't match, which means the insn has been modified
+ (e.g. register elimination). The scratch cannot be restored. */
+ continue;
+ }
+ op_loc = recog_data.operand_loc[loc->nop];
+ if (REG_P (*op_loc)
+ && ((regno = REGNO (*op_loc)) >= FIRST_PSEUDO_REGISTER)
+ && reg_renumber[regno] < 0)
+ {
+ /* It should be only case when scratch register with chosen
+ constraint 'X' did not get memory or hard register. */
+ ira_assert (ira_former_scratch_p (regno));
+ *op_loc = gen_rtx_SCRATCH (GET_MODE (*op_loc));
+ for (n = 0; n < recog_data.n_dups; n++)
+ *recog_data.dup_loc[n]
+ = *recog_data.operand_loc[(int) recog_data.dup_num[n]];
+ if (dump_file != NULL)
+ fprintf (dump_file, "Restoring SCRATCH in insn #%u(nop %d)\n",
+ INSN_UID (loc->insn), loc->nop);
+ }
+ }
+ for (i = 0; scratches.iterate (i, &loc); i++)
+ free (loc);
+ scratches.release ();
+ bitmap_clear (&scratch_bitmap);
+ bitmap_clear (&scratch_operand_bitmap);
+}
+
+
+
/* If the backend knows where to allocate pseudos for hard
register initial values, register these allocations now. */
static void
@@ -5182,8 +5380,10 @@ allocate_initial_values (void)
&hreg, &preg));
}
}
+
+
/* True when we use LRA instead of reload pass for the current
function. */
bool ira_use_lra_p;
@@ -5203,6 +5403,59 @@ ira (FILE *f)
int ira_max_point_before_emit;
bool saved_flag_caller_saves = flag_caller_saves;
enum ira_region saved_flag_ira_region = flag_ira_region;
+ basic_block bb;
+ edge_iterator ei;
+ edge e;
+ bool output_jump_reload_p = false;
+
+ if (ira_use_lra_p)
+ {
+ /* First put potential jump output reloads on the output edges
+ as USE which will be removed at the end of LRA. The major
+ goal is actually to create BBs for critical edges for LRA and
+ populate them later by live info. In LRA it will be
+ difficult to do this. */
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ rtx_insn *end = BB_END (bb);
+ if (!JUMP_P (end))
+ continue;
+ extract_insn (end);
+ for (int i = 0; i < recog_data.n_operands; i++)
+ if (recog_data.operand_type[i] != OP_IN)
+ {
+ output_jump_reload_p = true;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (EDGE_CRITICAL_P (e)
+ && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
+ {
+ ira_assert (!(e->flags & EDGE_ABNORMAL));
+ start_sequence ();
+ /* We need to put some no-op insn here. We can
+ not put a note as commit_edges insertion will
+ fail. */
+ emit_insn (gen_rtx_USE (VOIDmode, const1_rtx));
+ rtx_insn *insns = get_insns ();
+ end_sequence ();
+ insert_insn_on_edge (insns, e);
+ }
+ break;
+ }
+ }
+ if (output_jump_reload_p)
+ commit_edge_insertions ();
+ }
+
+ if (flag_ira_verbose < 10)
+ {
+ internal_flag_ira_verbose = flag_ira_verbose;
+ ira_dump_file = f;
+ }
+ else
+ {
+ internal_flag_ira_verbose = flag_ira_verbose - 10;
+ ira_dump_file = stderr;
+ }
clear_bb_flags ();
@@ -5250,17 +5503,6 @@ ira (FILE *f)
if (flag_caller_saves && !ira_use_lra_p)
init_caller_save ();
- if (flag_ira_verbose < 10)
- {
- internal_flag_ira_verbose = flag_ira_verbose;
- ira_dump_file = f;
- }
- else
- {
- internal_flag_ira_verbose = flag_ira_verbose - 10;
- ira_dump_file = stderr;
- }
-
setup_prohibited_mode_move_regs ();
decrease_live_ranges_number ();
df_note_add_problem ();
@@ -5305,9 +5547,6 @@ ira (FILE *f)
if (warn_clobbered)
generate_setjmp_warnings ();
- if (resize_reg_info () && flag_ira_loop_pressure)
- ira_set_pseudo_classes (true, ira_dump_file);
-
init_alias_analysis ();
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
reg_equiv = XCNEWVEC (struct equivalence, max_reg_num ());
@@ -5331,6 +5570,30 @@ ira (FILE *f)
end_alias_analysis ();
free (reg_equiv);
+ /* Once max_regno changes, we need to free and re-init/re-compute
+ some data structures like regstat_n_sets_and_refs and reg_info_p. */
+ auto regstat_recompute_for_max_regno = []() {
+ regstat_free_n_sets_and_refs ();
+ regstat_free_ri ();
+ regstat_init_n_sets_and_refs ();
+ regstat_compute_ri ();
+ };
+
+ int max_regno_before_rm = max_reg_num ();
+ if (ira_use_lra_p && remove_scratches ())
+ {
+ ira_expand_reg_equiv ();
+ /* For now remove_scatches is supposed to create pseudos when it
+ succeeds, assert this happens all the time. Once it doesn't
+ hold, we should guard the regstat recompute for the case
+ max_regno changes. */
+ gcc_assert (max_regno_before_rm != max_reg_num ());
+ regstat_recompute_for_max_regno ();
+ }
+
+ if (resize_reg_info () && flag_ira_loop_pressure)
+ ira_set_pseudo_classes (true, ira_dump_file);
+
setup_reg_equiv ();
grow_reg_equivs ();
setup_reg_equiv_init ();
@@ -5453,12 +5716,7 @@ ira (FILE *f)
#endif
if (max_regno != max_regno_before_ira)
- {
- regstat_free_n_sets_and_refs ();
- regstat_free_ri ();
- regstat_init_n_sets_and_refs ();
- regstat_compute_ri ();
- }
+ regstat_recompute_for_max_regno ();
overall_cost_before = ira_overall_cost;
if (! ira_conflicts_p)
@@ -5495,6 +5753,21 @@ ira (FILE *f)
}
}
+/* Modify asm goto to avoid further trouble with this insn. We can
+ not replace the insn by USE as in other asm insns as we still
+ need to keep CFG consistency. */
+void
+ira_nullify_asm_goto (rtx_insn *insn)
+{
+ ira_assert (JUMP_P (insn) && INSN_CODE (insn) < 0);
+ rtx tmp = extract_asm_operands (PATTERN (insn));
+ PATTERN (insn) = gen_rtx_ASM_OPERANDS (VOIDmode, ggc_strdup (""), "", 0,
+ rtvec_alloc (0),
+ rtvec_alloc (0),
+ ASM_OPERANDS_LABEL_VEC (tmp),
+ ASM_OPERANDS_SOURCE_LOCATION(tmp));
+}
+
static void
do_reload (void)
{
diff --git a/gcc/ira.h b/gcc/ira.h
index 09f40ef..0da06ee 100644
--- a/gcc/ira.h
+++ b/gcc/ira.h
@@ -207,6 +207,14 @@ extern bool ira_bad_reload_regno (int, rtx, rtx);
extern void ira_adjust_equiv_reg_cost (unsigned, int);
+extern bool ira_former_scratch_p (int regno);
+extern bool ira_former_scratch_operand_p (rtx_insn *insn, int nop);
+extern void ira_register_new_scratch_op (rtx_insn *insn, int nop, int icode);
+extern bool ira_remove_insn_scratches (rtx_insn *insn, bool all_p, FILE *dump_file,
+ rtx (*get_reg) (rtx original));
+extern void ira_restore_scratches (FILE *dump_file);
+extern void ira_nullify_asm_goto (rtx_insn *insn);
+
/* ira-costs.c */
extern void ira_costs_c_finalize (void);
diff --git a/gcc/is-a.h b/gcc/is-a.h
index e84c3e4..26f53a5 100644
--- a/gcc/is-a.h
+++ b/gcc/is-a.h
@@ -116,9 +116,30 @@ the connection between the types has not been made. See below.
EXTENDING THE GENERIC TYPE FACILITY
-Each connection between types must be made by defining a specialization of the
-template member function 'test' of the template class 'is_a_helper'. For
-example,
+Method 1
+--------
+
+If DERIVED is derived from BASE, and if BASE contains enough information
+to determine whether an object is actually an instance of DERIVED,
+then you can make the above routines work for DERIVED by defining
+a specialization of is_a_helper such as:
+
+ template<>
+ struct is_a_helper<DERIVED *> : static_is_a_helper<DERIVED *>
+ {
+ static inline bool test (const BASE *p) { return ...; }
+ };
+
+This test function should return true if P is an instanced of DERIVED.
+This on its own is enough; the comments below for method 2 do not apply.
+
+Method 2
+--------
+
+Alternatively, if two types are connected in ways other than C++
+inheritance, each connection between them must be made by defining a
+specialization of the template member function 'test' of the template
+class 'is_a_helper'. For example,
template <>
template <>
@@ -145,15 +166,52 @@ when needed may result in a crash. For example,
#ifndef GCC_IS_A_H
#define GCC_IS_A_H
+/* A base class that specializations of is_a_helper can use if casting
+ U * to T is simply a reinterpret_cast. */
+
+template <typename T>
+struct reinterpret_is_a_helper
+{
+ template <typename U>
+ static inline T cast (U *p) { return reinterpret_cast <T> (p); }
+};
+
+/* A base class that specializations of is_a_helper can use if casting
+ U * to T is simply a static_cast. This is more type-safe than
+ reinterpret_is_a_helper. */
+
+template <typename T>
+struct static_is_a_helper
+{
+ template <typename U>
+ static inline T cast (U *p) { return static_cast <T> (p); }
+};
+
/* A generic type conversion internal helper class. */
template <typename T>
-struct is_a_helper
+struct is_a_helper : reinterpret_is_a_helper<T>
{
template <typename U>
static inline bool test (U *p);
+};
+
+/* Reuse the definition of is_a_helper<T *> to implement
+ is_a_helper<const T *>. */
+
+template <typename T>
+struct is_a_helper<const T *>
+{
template <typename U>
- static inline T cast (U *p);
+ static inline const T *cast (const U *p)
+ {
+ return is_a_helper<T *>::cast (const_cast <U *> (p));
+ }
+ template <typename U>
+ static inline bool test (const U *p)
+ {
+ return is_a_helper<T *>::test (p);
+ }
};
/* Note that we deliberately do not define the 'test' member template. Not
@@ -161,19 +219,6 @@ struct is_a_helper
not been defined, rather than a run-time error. See the discussion above
for when to define this member. */
-/* This is the generic implementation for casting from one type to another.
- Do not use this routine directly; it is an internal function. See the
- discussion above for when to define this member. */
-
-template <typename T>
-template <typename U>
-inline T
-is_a_helper <T>::cast (U *p)
-{
- return reinterpret_cast <T> (p);
-}
-
-
/* The public interface. */
/* A generic test for a type relationship. See the discussion above for when
diff --git a/gcc/iterator-utils.h b/gcc/iterator-utils.h
new file mode 100644
index 0000000..22cc1a5
--- /dev/null
+++ b/gcc/iterator-utils.h
@@ -0,0 +1,203 @@
+// Iterator-related utilities.
+// Copyright (C) 2002-2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_ITERATOR_UTILS_H
+#define GCC_ITERATOR_UTILS_H 1
+
+// A half-open [begin, end) range of iterators.
+template<typename T>
+struct iterator_range
+{
+public:
+ using const_iterator = T;
+
+ iterator_range () = default;
+ iterator_range (const T &begin, const T &end)
+ : m_begin (begin), m_end (end) {}
+
+ T begin () const { return m_begin; }
+ T end () const { return m_end; }
+
+ explicit operator bool () const { return m_begin != m_end; }
+
+private:
+ T m_begin;
+ T m_end;
+};
+
+// Provide an iterator like BaseIT, except that it yields values of type T,
+// which is derived from the type that BaseIT normally yields.
+//
+// The class doesn't inherit from BaseIT for two reasons:
+// - using inheritance would stop the class working with plain pointers
+// - not using inheritance increases type-safety for writable iterators
+//
+// Constructing this class from a BaseIT involves an assertion that all
+// contents really do have type T. The constructor is therefore explicit.
+template<typename T, typename BaseIT>
+class derived_iterator
+{
+public:
+ using value_type = T;
+
+ derived_iterator () = default;
+
+ template<typename... Ts>
+ explicit derived_iterator (Ts... args)
+ : m_base (std::forward<Ts> (args)...) {}
+
+ derived_iterator &operator++ () { ++m_base; return *this; }
+ derived_iterator operator++ (int);
+
+ T operator* () const { return static_cast<T> (*m_base); }
+ T *operator-> () const { return static_cast<T *> (m_base.operator-> ()); }
+
+ bool operator== (const derived_iterator &other) const;
+ bool operator!= (const derived_iterator &other) const;
+
+protected:
+ BaseIT m_base;
+};
+
+template<typename T, typename BaseIT>
+inline derived_iterator<T, BaseIT>
+derived_iterator<T, BaseIT>::operator++ (int)
+{
+ derived_iterator ret = *this;
+ ++m_base;
+ return ret;
+}
+
+template<typename T, typename BaseIT>
+inline bool
+derived_iterator<T, BaseIT>::operator== (const derived_iterator &other) const
+{
+ return m_base == other.m_base;
+}
+
+template<typename T, typename BaseIT>
+inline bool
+derived_iterator<T, BaseIT>::operator!= (const derived_iterator &other) const
+{
+ return m_base != other.m_base;
+}
+
+// Provide a constant view of a BaseCT in which every value is known to
+// have type T, which is derived from the type that BaseCT normally presents.
+//
+// Constructing this class from a BaseCT involves an assertion that all
+// contents really do have type T. The constructor is therefore explicit.
+template<typename T, typename BaseCT>
+class const_derived_container : public BaseCT
+{
+ using base_const_iterator = typename BaseCT::const_iterator;
+
+public:
+ using value_type = T;
+ using const_iterator = derived_iterator<T, base_const_iterator>;
+
+ const_derived_container () = default;
+
+ template<typename... Ts>
+ explicit const_derived_container (Ts... args)
+ : BaseCT (std::forward<Ts> (args)...) {}
+
+ const_iterator begin () const { return const_iterator (BaseCT::begin ()); }
+ const_iterator end () const { return const_iterator (BaseCT::end ()); }
+
+ T front () const { return static_cast<T> (BaseCT::front ()); }
+ T back () const { return static_cast<T> (BaseCT::back ()); }
+ T operator[] (unsigned int i) const;
+};
+
+template<typename T, typename BaseCT>
+inline T
+const_derived_container<T, BaseCT>::operator[] (unsigned int i) const
+{
+ return static_cast<T> (BaseCT::operator[] (i));
+}
+
+// A base class for iterators whose contents consist of a StoredT and that
+// when dereferenced yield those StoredT contents as a T. Derived classes
+// should implement at least operator++ or operator--.
+template<typename T, typename StoredT = T>
+class wrapper_iterator
+{
+public:
+ using value_type = T;
+
+ wrapper_iterator () = default;
+
+ template<typename... Ts>
+ wrapper_iterator (Ts... args) : m_contents (std::forward<Ts> (args)...) {}
+
+ T operator* () const { return static_cast<T> (m_contents); }
+ bool operator== (const wrapper_iterator &) const;
+ bool operator!= (const wrapper_iterator &) const;
+
+protected:
+ StoredT m_contents;
+};
+
+template<typename T, typename StoredT>
+inline bool
+wrapper_iterator<T, StoredT>::operator== (const wrapper_iterator &other) const
+{
+ return m_contents == other.m_contents;
+}
+
+template<typename T, typename StoredT>
+inline bool
+wrapper_iterator<T, StoredT>::operator!= (const wrapper_iterator &other) const
+{
+ return m_contents != other.m_contents;
+}
+
+// A forward iterator for a linked list whose nodes are referenced using
+// type T. Given a node "T N", the next element is given by (N->*Next) ().
+template<typename T, T *(T::*Next) () const>
+class list_iterator : public wrapper_iterator<T *>
+{
+private:
+ using parent = wrapper_iterator<T *>;
+
+public:
+ using parent::parent;
+ list_iterator &operator++ ();
+ list_iterator operator++ (int);
+};
+
+template<typename T, T *(T::*Next) () const>
+inline list_iterator<T, Next> &
+list_iterator<T, Next>::operator++ ()
+{
+ this->m_contents = (this->m_contents->*Next) ();
+ return *this;
+}
+
+template<typename T, T *(T::*Next) () const>
+inline list_iterator<T, Next>
+list_iterator<T, Next>::operator++ (int)
+{
+ list_iterator ret = *this;
+ this->m_contents = (this->m_contents->*Next) ();
+ return ret;
+}
+
+#endif
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index 48bd54d..dafb480 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,157 @@
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR bootstrap/94982
+ * jit-recording.c (recording::function::dump_to_dot): Avoid
+ -Wformat-diag.
+ (recording::block::dump_to_dot): Same.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (jit.serial): Change from goal to a
+ variable.
+ (.PHONY): Drop jit.serial and jit.prev.
+ ($(LIBGCCJIT_FILENAME)): Depend on $(jit.serial) rather than
+ jit.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (jit.serial): New goal.
+ (.PHONY): Add jit.serial jit.prev.
+ ($(LIBGCCJIT_FILENAME)): Depend on jit.prev. Call LINK_PROGRESS.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/87291
+ * docs/cp/topics/asm.rst: New file.
+ * docs/cp/topics/index.rst (Topic Reference): Add it.
+ * docs/topics/asm.rst: New file.
+ * docs/topics/compatibility.rst (LIBGCCJIT_ABI_15): New.
+ * docs/topics/functions.rst (Statements): Add link to extended
+ asm.
+ * docs/topics/index.rst (Topic Reference): Add asm.rst.
+ * docs/topics/objects.rst: Add gcc_jit_extended_asm to ASCII art.
+ * docs/_build/texinfo/Makefile: Regenerate.
+ * docs/_build/texinfo/libgccjit.texi: Regenerate.
+ * jit-common.h (gcc::jit::recording::extended_asm): New forward
+ decl.
+ (gcc::jit::recording::top_level_asm): Likewise.
+ * jit-playback.c: Include "stmt.h".
+ (build_string): New.
+ (gcc::jit::playback::context::new_string_literal): Disambiguate
+ build_string call.
+ (gcc::jit::playback::context::add_top_level_asm): New.
+ (build_operand_chain): New.
+ (build_clobbers): New.
+ (build_goto_operands): New.
+ (gcc::jit::playback::block::add_extended_asm): New.
+ * jit-playback.h (gcc::jit::playback::context::add_top_level_asm):
+ New decl.
+ (struct gcc::jit::playback::asm_operand): New struct.
+ (gcc::jit::playback::block::add_extended_asm): New decl.
+ * jit-recording.c (gcc::jit::recording::context::dump_to_file):
+ Dump top-level asms.
+ (gcc::jit::recording::context::add_top_level_asm): New.
+ (gcc::jit::recording::block::add_extended_asm): New.
+ (gcc::jit::recording::block::end_with_extended_asm_goto): New.
+ (gcc::jit::recording::asm_operand::asm_operand): New.
+ (gcc::jit::recording::asm_operand::print): New.
+ (gcc::jit::recording::asm_operand::make_debug_string): New.
+ (gcc::jit::recording::output_asm_operand::write_reproducer): New.
+ (gcc::jit::recording::output_asm_operand::print): New.
+ (gcc::jit::recording::input_asm_operand::write_reproducer): New.
+ (gcc::jit::recording::input_asm_operand::print): New.
+ (gcc::jit::recording::extended_asm::add_output_operand): New.
+ (gcc::jit::recording::extended_asm::add_input_operand): New.
+ (gcc::jit::recording::extended_asm::add_clobber): New.
+ (gcc::jit::recording::extended_asm::replay_into): New.
+ (gcc::jit::recording::extended_asm::make_debug_string): New.
+ (gcc::jit::recording::extended_asm::write_flags): New.
+ (gcc::jit::recording::extended_asm::write_clobbers): New.
+ (gcc::jit::recording::extended_asm_simple::write_reproducer): New.
+ (gcc::jit::recording::extended_asm::maybe_populate_playback_blocks):
+ New.
+ (gcc::jit::recording::extended_asm_goto::extended_asm_goto): New.
+ (gcc::jit::recording::extended_asm_goto::replay_into): New.
+ (gcc::jit::recording::extended_asm_goto::write_reproducer): New.
+ (gcc::jit::recording::extended_asm_goto::get_successor_blocks):
+ New.
+ (gcc::jit::recording::extended_asm_goto::maybe_print_gotos): New.
+ (gcc::jit::recording::extended_asm_goto::maybe_populate_playback_blocks):
+ New.
+ (gcc::jit::recording::top_level_asm::top_level_asm): New.
+ (gcc::jit::recording::top_level_asm::replay_into): New.
+ (gcc::jit::recording::top_level_asm::make_debug_string): New.
+ (gcc::jit::recording::top_level_asm::write_to_dump): New.
+ (gcc::jit::recording::top_level_asm::write_reproducer): New.
+ * jit-recording.h
+ (gcc::jit::recording::context::add_top_level_asm): New decl.
+ (gcc::jit::recording::context::m_top_level_asms): New field.
+ (gcc::jit::recording::block::add_extended_asm): New decl.
+ (gcc::jit::recording::block::end_with_extended_asm_goto): New
+ decl.
+ (gcc::jit::recording::asm_operand): New class.
+ (gcc::jit::recording::output_asm_operand): New class.
+ (gcc::jit::recording::input_asm_operand): New class.
+ (gcc::jit::recording::extended_asm): New class.
+ (gcc::jit::recording::extended_asm_simple): New class.
+ (gcc::jit::recording::extended_asm_goto): New class.
+ (gcc::jit::recording::top_level_asm): New class.
+ * libgccjit++.h (gccjit::extended_asm): New forward decl.
+ (gccjit::context::add_top_level_asm): New.
+ (gccjit::block::add_extended_asm): New.
+ (gccjit::block::end_with_extended_asm_goto): New.
+ (gccjit::extended_asm): New class.
+ (gccjit::extended_asm::extended_asm): New ctors.
+ (gccjit::extended_asm::set_volatile_flag): New.
+ (gccjit::extended_asm::set_inline_flag): New.
+ (gccjit::extended_asm::add_output_operand): New.
+ (gccjit::extended_asm::add_input_operand): New.
+ (gccjit::extended_asm::add_clobber): New.
+ (gccjit::extended_asm::get_inner_extended_asm): New.
+ * libgccjit.c (struct gcc_jit_extended_asm): New.
+ (jit_error): Make "loc" param take a gcc::jit::recording::location *
+ rather than a gcc_jit_location *.
+ (gcc_jit_block_add_extended_asm): New entrypoint.
+ (gcc_jit_block_end_with_extended_asm_goto): New entrypoint.
+ (gcc_jit_extended_asm_as_object): New entrypoint.
+ (gcc_jit_extended_asm_set_volatile_flag): New entrypoint.
+ (gcc_jit_extended_asm_set_inline_flag): New entrypoint.
+ (gcc_jit_extended_asm_add_output_operand): New entrypoint.
+ (gcc_jit_extended_asm_add_clobber): New entrypoint.
+ (gcc_jit_context_add_top_level_asm): New entrypoint.
+ * libgccjit.h: Add gcc_jit_extended_asm to ASCII art.
+ (gcc_jit_extended_asm): New typedef.
+ (LIBGCCJIT_HAVE_ASM_STATEMENTS): New define.
+ (gcc_jit_block_add_extended_asm): New entrypoint.
+ (gcc_jit_block_end_with_extended_asm_goto): New entrypoint.
+ (gcc_jit_extended_asm_as_object): New entrypoint.
+ (gcc_jit_extended_asm_set_volatile_flag): New entrypoint.
+ (gcc_jit_extended_asm_set_inline_flag): New entrypoint.
+ (gcc_jit_extended_asm_add_output_operand): New entrypoint.
+ (gcc_jit_extended_asm_add_input_operand): New entrypoint.
+ (gcc_jit_extended_asm_add_clobber): New entrypoint.
+ (gcc_jit_context_add_top_level_asm): New entrypoint.
+ * libgccjit.map (LIBGCCJIT_ABI_15): New.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ * jit-recording.c (recording::context::new_string): Add "escaped"
+ param and use it when creating the new recording::string instance.
+ (recording::string::string): Add "escaped" param and use it to
+ initialize m_escaped.
+ (recording::string::make_debug_string): Replace check that first
+ char is double-quote with use of m_escaped. Fix escaping of
+ '\t' and '\n'. Set "escaped" on the result.
+ * jit-recording.h (recording::context::new_string): Add "escaped"
+ param.
+ (recording::string::string): Add "escaped" param.
+ (recording::string::m_escaped): New field.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ * libgccjit.h: Fix typo in comment.
+
2020-09-14 Andrea Corallo <andrea.corallo@arm.com>
* docs/_build/texinfo/libgccjit.texi: Regenerate.
diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
index 3b54392..1d34d2a0 100644
--- a/gcc/jit/Make-lang.in
+++ b/gcc/jit/Make-lang.in
@@ -81,6 +81,8 @@ jit: $(LIBGCCJIT_FILENAME) \
$(FULL_DRIVER_NAME)
endif
+jit.serial = $(LIBGCCJIT_FILENAME)
+
# Tell GNU make to ignore these if they exist.
.PHONY: jit
@@ -117,12 +119,14 @@ $(LIBGCCJIT_FILENAME): $(jit_OBJS) \
libbackend.a libcommon-target.a libcommon.a \
$(CPPLIB) $(LIBDECNUMBER) \
$(LIBDEPS) $(srcdir)/jit/libgccjit.map \
- $(EXTRA_GCC_OBJS)
+ $(EXTRA_GCC_OBJS) $(jit.prev)
+ @$(call LINK_PROGRESS,$(INDEX.jit),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ -shared \
$(jit_OBJS) libbackend.a libcommon-target.a libcommon.a \
$(CPPLIB) $(LIBDECNUMBER) $(EXTRA_GCC_LIBS) $(LIBS) $(BACKENDLIBS) \
$(EXTRA_GCC_OBJS) \
$(LIBGCCJIT_EXTRA_OPTS)
+ @$(call LINK_PROGRESS,$(INDEX.jit),end)
# Create symlinks when not building for Windows
ifeq (,$(findstring mingw,$(target)))
diff --git a/gcc/jit/docs/_build/texinfo/Makefile b/gcc/jit/docs/_build/texinfo/Makefile
index 81c60f5..e3b732c 100644
--- a/gcc/jit/docs/_build/texinfo/Makefile
+++ b/gcc/jit/docs/_build/texinfo/Makefile
@@ -18,13 +18,20 @@ pdf: $(addsuffix .pdf,$(ALLDOCS))
install-info: info
for f in *.info; do \
- cp -t $(infodir) "$$f" && \
- $(INSTALL_INFO) --info-dir=$(infodir) "$$f" ; \
+ mkdir -p $(infodir) && \
+ cp "$$f" $(infodir) && \
+ $(INSTALL_INFO) --info-dir=$(infodir) "$$f" && \
+ \
+ FIGURE_DIR="`basename \"$$f\" .info`-figures" && \
+ if [ -e "$$FIGURE_DIR" ]; then \
+ cp -r "$$FIGURE_DIR" $(infodir) ; \
+ fi; \
done
uninstall-info: info
for f in *.info; do \
rm -f "$(infodir)/$$f" ; \
+ rm -rf "$(infodir)/`basename '$$f' .info`-figures" && \
$(INSTALL_INFO) --delete --info-dir=$(infodir) "$$f" ; \
done
diff --git a/gcc/jit/docs/_build/texinfo/libgccjit.texi b/gcc/jit/docs/_build/texinfo/libgccjit.texi
index 57aca7a..7b957b7 100644
--- a/gcc/jit/docs/_build/texinfo/libgccjit.texi
+++ b/gcc/jit/docs/_build/texinfo/libgccjit.texi
@@ -3,7 +3,7 @@
@setfilename libgccjit.info
@documentencoding UTF-8
@ifinfo
-@*Generated by Sphinx 1.6.7.@*
+@*Generated by Sphinx 2.2.2.@*
@end ifinfo
@settitle libgccjit Documentation
@defindex ge
@@ -21,7 +21,7 @@
@copying
@quotation
-libgccjit 11.0.0 (experimental 20200914), Sep 14, 2020
+libgccjit 11.0.0 (experimental 20201112), Nov 12, 2020
David Malcolm
@@ -173,6 +173,7 @@ Topic Reference
* Compiling a context::
* ABI and API compatibility::
* Performance::
+* Using Assembly Language with libgccjit::
Compilation contexts
@@ -256,11 +257,17 @@ ABI symbol tags
* LIBGCCJIT_ABI_12::
* LIBGCCJIT_ABI_13::
* LIBGCCJIT_ABI_14::
+* LIBGCCJIT_ABI_15::
Performance
* The timing API::
+Using Assembly Language with libgccjit
+
+* Adding assembler instructions within a function::
+* Adding top-level assembler statements::
+
C++ bindings for libgccjit
* Tutorial: Tutorial<2>.
@@ -312,6 +319,7 @@ Topic Reference
* Creating and using functions: Creating and using functions<2>.
* Source Locations: Source Locations<2>.
* Compiling a context: Compiling a context<2>.
+* Using Assembly Language with libgccjit++::
Compilation contexts
@@ -372,6 +380,11 @@ Compiling a context
* In-memory compilation: In-memory compilation<2>.
* Ahead-of-time compilation: Ahead-of-time compilation<2>.
+Using Assembly Language with libgccjit++
+
+* Adding assembler instructions within a function: Adding assembler instructions within a function<2>.
+* Adding top-level assembler statements: Adding top-level assembler statements<2>.
+
Internals
* Working on the JIT library::
@@ -390,7 +403,7 @@ Running the test suite
@end menu
@node Tutorial,Topic Reference,Top,Top
-@anchor{intro/index libgccjit}@anchor{1}@anchor{intro/index doc}@anchor{2}@anchor{intro/index tutorial}@anchor{3}
+@anchor{intro/index doc}@anchor{1}@anchor{intro/index libgccjit}@anchor{2}@anchor{intro/index tutorial}@anchor{3}
@chapter Tutorial
@@ -1122,7 +1135,7 @@ result: 25
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 3 Loops and variables,Tutorial part 4 Adding JIT-compilation to a toy interpreter,Tutorial part 2 Creating a trivial machine code function,Tutorial
-@anchor{intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{21}@anchor{intro/tutorial03 doc}@anchor{22}
+@anchor{intro/tutorial03 doc}@anchor{21}@anchor{intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{22}
@section Tutorial part 3: Loops and variables
@@ -1171,7 +1184,7 @@ Here’s what the final control flow graph will look like:
@float Figure
-@image{sum-of-squares1,,,image of a control flow graph,png}
+@image{libgccjit-figures/sum-of-squares1,,,image of a control flow graph,png}
@end float
@@ -1520,7 +1533,7 @@ install it with @cite{yum install python-xdot}):
@float Figure
-@image{sum-of-squares1,,,image of a control flow graph,png}
+@image{libgccjit-figures/sum-of-squares1,,,image of a control flow graph,png}
@end float
@@ -1740,7 +1753,7 @@ loop_test returned: 285
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 4 Adding JIT-compilation to a toy interpreter,Tutorial part 5 Implementing an Ahead-of-Time compiler,Tutorial part 3 Loops and variables,Tutorial
-@anchor{intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{35}@anchor{intro/tutorial04 doc}@anchor{36}
+@anchor{intro/tutorial04 doc}@anchor{35}@anchor{intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{36}
@section Tutorial part 4: Adding JIT-compilation to a toy interpreter
@@ -2716,7 +2729,7 @@ errors in our compiler.
@float Figure
-@image{factorial1,,,image of a control flow graph,png}
+@image{libgccjit-figures/factorial1,,,image of a control flow graph,png}
@end float
@@ -4435,11 +4448,12 @@ and to a dynamic library. See the documentation of
* Compiling a context::
* ABI and API compatibility::
* Performance::
+* Using Assembly Language with libgccjit::
@end menu
@node Compilation contexts,Objects,,Topic Reference
-@anchor{topics/contexts compilation-contexts}@anchor{51}@anchor{topics/contexts doc}@anchor{52}
+@anchor{topics/contexts doc}@anchor{51}@anchor{topics/contexts compilation-contexts}@anchor{52}
@section Compilation contexts
@@ -5130,7 +5144,7 @@ its presence using
@c <http://www.gnu.org/licenses/>.
@node Objects,Types,Compilation contexts,Topic Reference
-@anchor{topics/objects objects}@anchor{76}@anchor{topics/objects doc}@anchor{77}
+@anchor{topics/objects doc}@anchor{76}@anchor{topics/objects objects}@anchor{77}
@section Objects
@@ -5175,6 +5189,7 @@ looks like this:
+- gcc_jit_lvalue
+- gcc_jit_param
+- gcc_jit_case
+ +- gcc_jit_extended_asm
@end example
There are casting methods for upcasting from subclasses to parent classes.
@@ -5875,7 +5890,7 @@ Function pointer types can be created using
@c <http://www.gnu.org/licenses/>.
@node Expressions,Creating and using functions,Types,Topic Reference
-@anchor{topics/expressions expressions}@anchor{96}@anchor{topics/expressions doc}@anchor{97}
+@anchor{topics/expressions doc}@anchor{96}@anchor{topics/expressions expressions}@anchor{97}
@section Expressions
@@ -7520,6 +7535,9 @@ create_code (gcc_jit_context *ctxt, void *user_data)
@end quotation
@end deffn
+See also @ref{f1,,gcc_jit_extended_asm} for entrypoints for adding inline
+assembler statements to a function.
+
@c Copyright (C) 2017-2020 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -7538,7 +7556,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
@c <http://www.gnu.org/licenses/>.
@node Function pointers<2>,Source Locations,Creating and using functions,Topic Reference
-@anchor{topics/function-pointers doc}@anchor{f1}@anchor{topics/function-pointers function-pointers}@anchor{f2}
+@anchor{topics/function-pointers doc}@anchor{f2}@anchor{topics/function-pointers function-pointers}@anchor{f3}
@section Function pointers
@@ -7557,7 +7575,7 @@ via @ref{c0,,gcc_jit_function_get_address()}.
Get the address of a function as an rvalue, of function pointer
type.
-This entrypoint was added in @ref{f3,,LIBGCCJIT_ABI_9}; you can test
+This entrypoint was added in @ref{f4,,LIBGCCJIT_ABI_9}; you can test
for its presence using
@example
@@ -7619,7 +7637,7 @@ Each of @cite{param_types} must be non-@cite{void}; @cite{return_type} may be @c
@c <http://www.gnu.org/licenses/>.
@node Source Locations,Compiling a context,Function pointers<2>,Topic Reference
-@anchor{topics/locations source-locations}@anchor{f4}@anchor{topics/locations doc}@anchor{f5}
+@anchor{topics/locations doc}@anchor{f5}@anchor{topics/locations source-locations}@anchor{f6}
@section Source Locations
@@ -7667,7 +7685,7 @@ on-stack buffer.
@end menu
@node Faking it,,,Source Locations
-@anchor{topics/locations faking-it}@anchor{f6}
+@anchor{topics/locations faking-it}@anchor{f7}
@subsection Faking it
@@ -7703,7 +7721,7 @@ file, giving you @emph{something} you can step through in the debugger.
@c <http://www.gnu.org/licenses/>.
@node Compiling a context,ABI and API compatibility,Source Locations,Topic Reference
-@anchor{topics/compilation compiling-a-context}@anchor{f7}@anchor{topics/compilation doc}@anchor{f8}
+@anchor{topics/compilation doc}@anchor{f8}@anchor{topics/compilation compiling-a-context}@anchor{f9}
@section Compiling a context
@@ -7722,7 +7740,7 @@ prevent any future compilation of that context.
@end menu
@node In-memory compilation,Ahead-of-time compilation,,Compiling a context
-@anchor{topics/compilation in-memory-compilation}@anchor{f9}
+@anchor{topics/compilation in-memory-compilation}@anchor{fa}
@subsection In-memory compilation
@@ -7842,7 +7860,7 @@ by calling @ref{17,,gcc_jit_result_get_code()} or
@end deffn
@node Ahead-of-time compilation,,In-memory compilation,Compiling a context
-@anchor{topics/compilation ahead-of-time-compilation}@anchor{fa}
+@anchor{topics/compilation ahead-of-time-compilation}@anchor{fb}
@subsection Ahead-of-time compilation
@@ -7871,7 +7889,7 @@ suffix of the output file when determining what to do.
@end cartouche
@geindex gcc_jit_output_kind (C type)
-@anchor{topics/compilation c gcc_jit_output_kind}@anchor{fb}
+@anchor{topics/compilation c gcc_jit_output_kind}@anchor{fc}
@deffn {C Type} enum gcc_jit_output_kind
@end deffn
@@ -7889,7 +7907,7 @@ Typical suffix
@item
-@ref{fc,,GCC_JIT_OUTPUT_KIND_ASSEMBLER}
+@ref{fd,,GCC_JIT_OUTPUT_KIND_ASSEMBLER}
@tab
@@ -7897,7 +7915,7 @@ Typical suffix
@item
-@ref{fd,,GCC_JIT_OUTPUT_KIND_OBJECT_FILE}
+@ref{fe,,GCC_JIT_OUTPUT_KIND_OBJECT_FILE}
@tab
@@ -7905,7 +7923,7 @@ Typical suffix
@item
-@ref{fe,,GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}
+@ref{ff,,GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}
@tab
@@ -7913,7 +7931,7 @@ Typical suffix
@item
-@ref{ff,,GCC_JIT_OUTPUT_KIND_EXECUTABLE}
+@ref{100,,GCC_JIT_OUTPUT_KIND_EXECUTABLE}
@tab
@@ -7923,21 +7941,21 @@ None, or .exe
@geindex GCC_JIT_OUTPUT_KIND_ASSEMBLER (C macro)
-@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_ASSEMBLER}@anchor{fc}
+@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_ASSEMBLER}@anchor{fd}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_ASSEMBLER
Compile the context to an assembler file.
@end deffn
@geindex GCC_JIT_OUTPUT_KIND_OBJECT_FILE (C macro)
-@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_OBJECT_FILE}@anchor{fd}
+@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_OBJECT_FILE}@anchor{fe}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_OBJECT_FILE
Compile the context to an object file.
@end deffn
@geindex GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY (C macro)
-@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}@anchor{fe}
+@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}@anchor{ff}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY
Compile the context to a dynamic library.
@@ -7947,7 +7965,7 @@ against.
@end deffn
@geindex GCC_JIT_OUTPUT_KIND_EXECUTABLE (C macro)
-@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_EXECUTABLE}@anchor{ff}
+@anchor{topics/compilation c GCC_JIT_OUTPUT_KIND_EXECUTABLE}@anchor{100}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_EXECUTABLE
Compile the context to an executable.
@@ -7974,7 +7992,7 @@ against.
@c <http://www.gnu.org/licenses/>.
@node ABI and API compatibility,Performance,Compiling a context,Topic Reference
-@anchor{topics/compatibility abi-and-api-compatibility}@anchor{100}@anchor{topics/compatibility doc}@anchor{101}
+@anchor{topics/compatibility doc}@anchor{101}@anchor{topics/compatibility abi-and-api-compatibility}@anchor{102}
@section ABI and API compatibility
@@ -8030,21 +8048,21 @@ Version definitions:
@end menu
@node Programmatically checking version,ABI symbol tags,,ABI and API compatibility
-@anchor{topics/compatibility programmatically-checking-version}@anchor{102}
+@anchor{topics/compatibility programmatically-checking-version}@anchor{103}
@subsection Programmatically checking version
Client code can programmatically check libgccjit version using:
@geindex gcc_jit_version_major (C function)
-@anchor{topics/compatibility c gcc_jit_version_major}@anchor{103}
+@anchor{topics/compatibility c gcc_jit_version_major}@anchor{104}
@deffn {C Function} int gcc_jit_version_major (void)
Return libgccjit major version. This is analogous to __GNUC__ in C code.
@end deffn
@geindex gcc_jit_version_minor (C function)
-@anchor{topics/compatibility c gcc_jit_version_minor}@anchor{104}
+@anchor{topics/compatibility c gcc_jit_version_minor}@anchor{105}
@deffn {C Function} int gcc_jit_version_minor (void)
Return libgccjit minor version. This is analogous to
@@ -8052,7 +8070,7 @@ __GNUC_MINOR__ in C code.
@end deffn
@geindex gcc_jit_version_patchlevel (C function)
-@anchor{topics/compatibility c gcc_jit_version_patchlevel}@anchor{105}
+@anchor{topics/compatibility c gcc_jit_version_patchlevel}@anchor{106}
@deffn {C Function} int gcc_jit_version_patchlevel (void)
Return libgccjit patchlevel version. This is analogous to
@@ -8067,7 +8085,7 @@ These entry points has been added with @code{LIBGCCJIT_ABI_13}
@end cartouche
@node ABI symbol tags,,Programmatically checking version,ABI and API compatibility
-@anchor{topics/compatibility abi-symbol-tags}@anchor{106}
+@anchor{topics/compatibility abi-symbol-tags}@anchor{107}
@subsection ABI symbol tags
@@ -8091,11 +8109,12 @@ Newer releases use the following tags.
* LIBGCCJIT_ABI_12::
* LIBGCCJIT_ABI_13::
* LIBGCCJIT_ABI_14::
+* LIBGCCJIT_ABI_15::
@end menu
@node LIBGCCJIT_ABI_0,LIBGCCJIT_ABI_1,,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-0}@anchor{107}@anchor{topics/compatibility id1}@anchor{108}
+@anchor{topics/compatibility id1}@anchor{108}@anchor{topics/compatibility libgccjit-abi-0}@anchor{109}
@subsubsection @code{LIBGCCJIT_ABI_0}
@@ -8107,7 +8126,7 @@ continue to work, with this being handled transparently by the linker
(see this post@footnote{https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html})
@node LIBGCCJIT_ABI_1,LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_0,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-1}@anchor{73}@anchor{topics/compatibility id2}@anchor{109}
+@anchor{topics/compatibility id2}@anchor{10a}@anchor{topics/compatibility libgccjit-abi-1}@anchor{73}
@subsubsection @code{LIBGCCJIT_ABI_1}
@@ -8115,7 +8134,7 @@ continue to work, with this being handled transparently by the linker
@ref{72,,gcc_jit_context_add_command_line_option()}
@node LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_1,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-2}@anchor{6c}@anchor{topics/compatibility id3}@anchor{10a}
+@anchor{topics/compatibility id3}@anchor{10b}@anchor{topics/compatibility libgccjit-abi-2}@anchor{6c}
@subsubsection @code{LIBGCCJIT_ABI_2}
@@ -8123,7 +8142,7 @@ continue to work, with this being handled transparently by the linker
@ref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()}
@node LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_4,LIBGCCJIT_ABI_2,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-3}@anchor{ef}@anchor{topics/compatibility id4}@anchor{10b}
+@anchor{topics/compatibility id4}@anchor{10c}@anchor{topics/compatibility libgccjit-abi-3}@anchor{ef}
@subsubsection @code{LIBGCCJIT_ABI_3}
@@ -8147,7 +8166,7 @@ entrypoints:
@end quotation
@node LIBGCCJIT_ABI_4,LIBGCCJIT_ABI_5,LIBGCCJIT_ABI_3,ABI symbol tags
-@anchor{topics/compatibility id5}@anchor{10c}@anchor{topics/compatibility libgccjit-abi-4}@anchor{10d}
+@anchor{topics/compatibility id5}@anchor{10d}@anchor{topics/compatibility libgccjit-abi-4}@anchor{10e}
@subsubsection @code{LIBGCCJIT_ABI_4}
@@ -8160,30 +8179,30 @@ entrypoints:
@itemize *
@item
-@ref{10e,,gcc_jit_context_get_timer()}
+@ref{10f,,gcc_jit_context_get_timer()}
@item
-@ref{10f,,gcc_jit_context_set_timer()}
+@ref{110,,gcc_jit_context_set_timer()}
@item
-@ref{110,,gcc_jit_timer_new()}
+@ref{111,,gcc_jit_timer_new()}
@item
-@ref{111,,gcc_jit_timer_release()}
+@ref{112,,gcc_jit_timer_release()}
@item
-@ref{112,,gcc_jit_timer_push()}
+@ref{113,,gcc_jit_timer_push()}
@item
-@ref{113,,gcc_jit_timer_pop()}
+@ref{114,,gcc_jit_timer_pop()}
@item
-@ref{114,,gcc_jit_timer_print()}
+@ref{115,,gcc_jit_timer_print()}
@end itemize
@end quotation
@node LIBGCCJIT_ABI_5,LIBGCCJIT_ABI_6,LIBGCCJIT_ABI_4,ABI symbol tags
-@anchor{topics/compatibility id6}@anchor{115}@anchor{topics/compatibility libgccjit-abi-5}@anchor{6e}
+@anchor{topics/compatibility id6}@anchor{116}@anchor{topics/compatibility libgccjit-abi-5}@anchor{6e}
@subsubsection @code{LIBGCCJIT_ABI_5}
@@ -8191,7 +8210,7 @@ entrypoints:
@ref{6d,,gcc_jit_context_set_bool_use_external_driver()}
@node LIBGCCJIT_ABI_6,LIBGCCJIT_ABI_7,LIBGCCJIT_ABI_5,ABI symbol tags
-@anchor{topics/compatibility id7}@anchor{116}@anchor{topics/compatibility libgccjit-abi-6}@anchor{be}
+@anchor{topics/compatibility id7}@anchor{117}@anchor{topics/compatibility libgccjit-abi-6}@anchor{be}
@subsubsection @code{LIBGCCJIT_ABI_6}
@@ -8199,7 +8218,7 @@ entrypoints:
@ref{bd,,gcc_jit_rvalue_set_bool_require_tail_call()}
@node LIBGCCJIT_ABI_7,LIBGCCJIT_ABI_8,LIBGCCJIT_ABI_6,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-7}@anchor{83}@anchor{topics/compatibility id8}@anchor{117}
+@anchor{topics/compatibility id8}@anchor{118}@anchor{topics/compatibility libgccjit-abi-7}@anchor{83}
@subsubsection @code{LIBGCCJIT_ABI_7}
@@ -8207,7 +8226,7 @@ entrypoints:
@ref{82,,gcc_jit_type_get_aligned()}
@node LIBGCCJIT_ABI_8,LIBGCCJIT_ABI_9,LIBGCCJIT_ABI_7,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-8}@anchor{86}@anchor{topics/compatibility id9}@anchor{118}
+@anchor{topics/compatibility id9}@anchor{119}@anchor{topics/compatibility libgccjit-abi-8}@anchor{86}
@subsubsection @code{LIBGCCJIT_ABI_8}
@@ -8215,7 +8234,7 @@ entrypoints:
@ref{85,,gcc_jit_type_get_vector()}
@node LIBGCCJIT_ABI_9,LIBGCCJIT_ABI_10,LIBGCCJIT_ABI_8,ABI symbol tags
-@anchor{topics/compatibility id10}@anchor{119}@anchor{topics/compatibility libgccjit-abi-9}@anchor{f3}
+@anchor{topics/compatibility id10}@anchor{11a}@anchor{topics/compatibility libgccjit-abi-9}@anchor{f4}
@subsubsection @code{LIBGCCJIT_ABI_9}
@@ -8223,7 +8242,7 @@ entrypoints:
@ref{c0,,gcc_jit_function_get_address()}
@node LIBGCCJIT_ABI_10,LIBGCCJIT_ABI_11,LIBGCCJIT_ABI_9,ABI symbol tags
-@anchor{topics/compatibility id11}@anchor{11a}@anchor{topics/compatibility libgccjit-abi-10}@anchor{a0}
+@anchor{topics/compatibility id11}@anchor{11b}@anchor{topics/compatibility libgccjit-abi-10}@anchor{a0}
@subsubsection @code{LIBGCCJIT_ABI_10}
@@ -8231,7 +8250,7 @@ entrypoints:
@ref{87,,gcc_jit_context_new_rvalue_from_vector()}
@node LIBGCCJIT_ABI_11,LIBGCCJIT_ABI_12,LIBGCCJIT_ABI_10,ABI symbol tags
-@anchor{topics/compatibility id12}@anchor{11b}@anchor{topics/compatibility libgccjit-abi-11}@anchor{75}
+@anchor{topics/compatibility id12}@anchor{11c}@anchor{topics/compatibility libgccjit-abi-11}@anchor{75}
@subsubsection @code{LIBGCCJIT_ABI_11}
@@ -8239,7 +8258,7 @@ entrypoints:
@ref{74,,gcc_jit_context_add_driver_option()}
@node LIBGCCJIT_ABI_12,LIBGCCJIT_ABI_13,LIBGCCJIT_ABI_11,ABI symbol tags
-@anchor{topics/compatibility id13}@anchor{11c}@anchor{topics/compatibility libgccjit-abi-12}@anchor{8d}
+@anchor{topics/compatibility id13}@anchor{11d}@anchor{topics/compatibility libgccjit-abi-12}@anchor{8d}
@subsubsection @code{LIBGCCJIT_ABI_12}
@@ -8247,7 +8266,7 @@ entrypoints:
@ref{8c,,gcc_jit_context_new_bitfield()}
@node LIBGCCJIT_ABI_13,LIBGCCJIT_ABI_14,LIBGCCJIT_ABI_12,ABI symbol tags
-@anchor{topics/compatibility id14}@anchor{11d}@anchor{topics/compatibility libgccjit-abi-13}@anchor{11e}
+@anchor{topics/compatibility id14}@anchor{11e}@anchor{topics/compatibility libgccjit-abi-13}@anchor{11f}
@subsubsection @code{LIBGCCJIT_ABI_13}
@@ -8260,24 +8279,66 @@ entrypoints:
@itemize *
@item
-@ref{103,,gcc_jit_version_major()}
+@ref{104,,gcc_jit_version_major()}
@item
-@ref{104,,gcc_jit_version_minor()}
+@ref{105,,gcc_jit_version_minor()}
@item
-@ref{105,,gcc_jit_version_patchlevel()}
+@ref{106,,gcc_jit_version_patchlevel()}
@end itemize
@end quotation
-@node LIBGCCJIT_ABI_14,,LIBGCCJIT_ABI_13,ABI symbol tags
-@anchor{topics/compatibility libgccjit-abi-14}@anchor{cf}@anchor{topics/compatibility id15}@anchor{11f}
+@node LIBGCCJIT_ABI_14,LIBGCCJIT_ABI_15,LIBGCCJIT_ABI_13,ABI symbol tags
+@anchor{topics/compatibility id15}@anchor{120}@anchor{topics/compatibility libgccjit-abi-14}@anchor{cf}
@subsubsection @code{LIBGCCJIT_ABI_14}
@code{LIBGCCJIT_ABI_14} covers the addition of
@ref{ce,,gcc_jit_global_set_initializer()}
+@node LIBGCCJIT_ABI_15,,LIBGCCJIT_ABI_14,ABI symbol tags
+@anchor{topics/compatibility id16}@anchor{121}@anchor{topics/compatibility libgccjit-abi-15}@anchor{122}
+@subsubsection @code{LIBGCCJIT_ABI_15}
+
+
+@code{LIBGCCJIT_ABI_15} covers the addition of API entrypoints for directly
+embedding assembler instructions:
+
+@quotation
+
+
+@itemize *
+
+@item
+@ref{123,,gcc_jit_block_add_extended_asm()}
+
+@item
+@ref{124,,gcc_jit_block_end_with_extended_asm_goto()}
+
+@item
+@ref{125,,gcc_jit_extended_asm_as_object()}
+
+@item
+@ref{126,,gcc_jit_extended_asm_set_volatile_flag()}
+
+@item
+@ref{127,,gcc_jit_extended_asm_set_inline_flag()}
+
+@item
+@ref{128,,gcc_jit_extended_asm_add_output_operand()}
+
+@item
+@ref{129,,gcc_jit_extended_asm_add_input_operand()}
+
+@item
+@ref{12a,,gcc_jit_extended_asm_add_clobber()}
+
+@item
+@ref{12b,,gcc_jit_context_add_top_level_asm()}
+@end itemize
+@end quotation
+
@c Copyright (C) 2015-2020 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -8295,8 +8356,8 @@ entrypoints:
@c along with this program. If not, see
@c <http://www.gnu.org/licenses/>.
-@node Performance,,ABI and API compatibility,Topic Reference
-@anchor{topics/performance performance}@anchor{120}@anchor{topics/performance doc}@anchor{121}
+@node Performance,Using Assembly Language with libgccjit,ABI and API compatibility,Topic Reference
+@anchor{topics/performance doc}@anchor{12c}@anchor{topics/performance performance}@anchor{12d}
@section Performance
@@ -8306,14 +8367,14 @@ entrypoints:
@end menu
@node The timing API,,,Performance
-@anchor{topics/performance the-timing-api}@anchor{122}
+@anchor{topics/performance the-timing-api}@anchor{12e}
@subsection The timing API
As of GCC 6, libgccjit exposes a timing API, for printing reports on
how long was spent in different parts of code.
-You can create a @ref{123,,gcc_jit_timer} instance, which will
+You can create a @ref{12f,,gcc_jit_timer} instance, which will
measure time spent since its creation. The timer maintains a stack
of “timer items”: as control flow moves through your code, you can push
and pop named items relating to your code onto the stack, and the timer
@@ -8411,7 +8472,7 @@ Client items:
The exact format is intended to be human-readable, and is subject to change.
@geindex LIBGCCJIT_HAVE_TIMING_API (C macro)
-@anchor{topics/performance c LIBGCCJIT_HAVE_TIMING_API}@anchor{124}
+@anchor{topics/performance c LIBGCCJIT_HAVE_TIMING_API}@anchor{130}
@deffn {C Macro} LIBGCCJIT_HAVE_TIMING_API
The timer API was added to libgccjit in GCC 6.
@@ -8428,21 +8489,21 @@ gcc_jit_context_set_timer (ctxt, t);
@end deffn
@geindex gcc_jit_timer (C type)
-@anchor{topics/performance c gcc_jit_timer}@anchor{123}
+@anchor{topics/performance c gcc_jit_timer}@anchor{12f}
@deffn {C Type} gcc_jit_timer
@end deffn
@geindex gcc_jit_timer_new (C function)
-@anchor{topics/performance c gcc_jit_timer_new}@anchor{110}
+@anchor{topics/performance c gcc_jit_timer_new}@anchor{111}
@deffn {C Function} gcc_jit_timer * gcc_jit_timer_new (void)
-Create a @ref{123,,gcc_jit_timer} instance, and start timing:
+Create a @ref{12f,,gcc_jit_timer} instance, and start timing:
@example
gcc_jit_timer *t = gcc_jit_timer_new ();
@end example
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8451,10 +8512,10 @@ for its presence using
@end deffn
@geindex gcc_jit_timer_release (C function)
-@anchor{topics/performance c gcc_jit_timer_release}@anchor{111}
+@anchor{topics/performance c gcc_jit_timer_release}@anchor{112}
@deffn {C Function} void gcc_jit_timer_release (gcc_jit_timer@w{ }*timer)
-Release a @ref{123,,gcc_jit_timer} instance:
+Release a @ref{12f,,gcc_jit_timer} instance:
@example
gcc_jit_timer_release (t);
@@ -8462,7 +8523,7 @@ gcc_jit_timer_release (t);
This should be called exactly once on a timer.
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8471,10 +8532,10 @@ for its presence using
@end deffn
@geindex gcc_jit_context_set_timer (C function)
-@anchor{topics/performance c gcc_jit_context_set_timer}@anchor{10f}
+@anchor{topics/performance c gcc_jit_context_set_timer}@anchor{110}
@deffn {C Function} void gcc_jit_context_set_timer (gcc_jit_context@w{ }*ctxt, gcc_jit_timer@w{ }*timer)
-Associate a @ref{123,,gcc_jit_timer} instance with a context:
+Associate a @ref{12f,,gcc_jit_timer} instance with a context:
@example
gcc_jit_context_set_timer (ctxt, t);
@@ -8487,7 +8548,7 @@ Timers have no locking, so if you have a multithreaded program, you
must provide your own locks if more than one thread could be working
with the same timer via timer-associated contexts.
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8496,12 +8557,12 @@ for its presence using
@end deffn
@geindex gcc_jit_context_get_timer (C function)
-@anchor{topics/performance c gcc_jit_context_get_timer}@anchor{10e}
+@anchor{topics/performance c gcc_jit_context_get_timer}@anchor{10f}
@deffn {C Function} gcc_jit_timer *gcc_jit_context_get_timer (gcc_jit_context@w{ }*ctxt)
Get the timer associated with a context (if any).
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8510,7 +8571,7 @@ for its presence using
@end deffn
@geindex gcc_jit_timer_push (C function)
-@anchor{topics/performance c gcc_jit_timer_push}@anchor{112}
+@anchor{topics/performance c gcc_jit_timer_push}@anchor{113}
@deffn {C Function} void gcc_jit_timer_push (gcc_jit_timer@w{ }*timer, const char@w{ }*item_name)
Push the given item onto the timer’s stack:
@@ -8521,7 +8582,7 @@ run_the_code (ctxt, result);
gcc_jit_timer_pop (t, "running code");
@end example
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8530,7 +8591,7 @@ for its presence using
@end deffn
@geindex gcc_jit_timer_pop (C function)
-@anchor{topics/performance c gcc_jit_timer_pop}@anchor{113}
+@anchor{topics/performance c gcc_jit_timer_pop}@anchor{114}
@deffn {C Function} void gcc_jit_timer_pop (gcc_jit_timer@w{ }*timer, const char@w{ }*item_name)
Pop the top item from the timer’s stack.
@@ -8538,7 +8599,7 @@ Pop the top item from the timer’s stack.
If “item_name” is provided, it must match that of the top item.
Alternatively, @code{NULL} can be passed in, to suppress checking.
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8547,13 +8608,13 @@ for its presence using
@end deffn
@geindex gcc_jit_timer_print (C function)
-@anchor{topics/performance c gcc_jit_timer_print}@anchor{114}
+@anchor{topics/performance c gcc_jit_timer_print}@anchor{115}
@deffn {C Function} void gcc_jit_timer_print (gcc_jit_timer@w{ }*timer, FILE@w{ }*f_out)
Print timing information to the given stream about activity since
the timer was started.
-This API entrypoint was added in @ref{10d,,LIBGCCJIT_ABI_4}; you can test
+This API entrypoint was added in @ref{10e,,LIBGCCJIT_ABI_4}; you can test
for its presence using
@example
@@ -8561,6 +8622,403 @@ for its presence using
@end example
@end deffn
+@c Copyright (C) 2020 Free Software Foundation, Inc.
+@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
+@c
+@c This is free software: you can redistribute it and/or modify it
+@c under the terms of the GNU General Public License as published by
+@c the Free Software Foundation, either version 3 of the License, or
+@c (at your option) any later version.
+@c
+@c This program is distributed in the hope that it will be useful, but
+@c WITHOUT ANY WARRANTY; without even the implied warranty of
+@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+@c General Public License for more details.
+@c
+@c You should have received a copy of the GNU General Public License
+@c along with this program. If not, see
+@c <http://www.gnu.org/licenses/>.
+
+@node Using Assembly Language with libgccjit,,Performance,Topic Reference
+@anchor{topics/asm doc}@anchor{131}@anchor{topics/asm using-assembly-language-with-libgccjit}@anchor{132}
+@section Using Assembly Language with libgccjit
+
+
+libgccjit has some support for directly embedding assembler instructions.
+This is based on GCC’s support for inline @code{asm} in C code, and the
+following assumes a familiarity with that functionality. See
+How to Use Inline Assembly Language in C Code@footnote{https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html}
+in GCC’s documentation, the “Extended Asm” section in particular.
+
+These entrypoints were added in @ref{122,,LIBGCCJIT_ABI_15}; you can test
+for their presence using
+
+@quotation
+
+@example
+#ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
+@end example
+@end quotation
+
+@menu
+* Adding assembler instructions within a function::
+* Adding top-level assembler statements::
+
+@end menu
+
+@node Adding assembler instructions within a function,Adding top-level assembler statements,,Using Assembly Language with libgccjit
+@anchor{topics/asm adding-assembler-instructions-within-a-function}@anchor{133}
+@subsection Adding assembler instructions within a function
+
+
+@geindex gcc_jit_extended_asm (C type)
+@anchor{topics/asm c gcc_jit_extended_asm}@anchor{f1}
+@deffn {C Type} gcc_jit_extended_asm
+
+A @cite{gcc_jit_extended_asm} represents an extended @code{asm} statement: a
+series of low-level instructions inside a function that convert inputs
+to outputs.
+
+To avoid having an API entrypoint with a very large number of
+parameters, an extended @code{asm} statement is made in stages:
+an initial call to create the @ref{f1,,gcc_jit_extended_asm},
+followed by calls to add operands and set other properties of the
+statement.
+
+There are two API entrypoints for creating a @ref{f1,,gcc_jit_extended_asm}:
+
+
+@itemize *
+
+@item
+@ref{123,,gcc_jit_block_add_extended_asm()} for an @code{asm} statement with
+no control flow, and
+
+@item
+@ref{124,,gcc_jit_block_end_with_extended_asm_goto()} for an @code{asm goto}.
+@end itemize
+
+For example, to create the equivalent of:
+
+@example
+ asm ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
+@end example
+
+the following API calls could be used:
+
+@example
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_add_extended_asm (block, NULL,
+ "mov %1, %0\n\t"
+ "add $1, %0");
+ gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst);
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_lvalue_as_rvalue (src));
+@end example
+
+@cartouche
+@quotation Warning
+When considering the numbering of operands within an
+extended @code{asm} statement (e.g. the @code{%0} and @code{%1}
+above), the equivalent to the C syntax is followed i.e. all
+output operands, then all input operands, regardless of
+what order the calls to
+@ref{128,,gcc_jit_extended_asm_add_output_operand()} and
+@ref{129,,gcc_jit_extended_asm_add_input_operand()} were made in.
+@end quotation
+@end cartouche
+
+As in the C syntax, operands can be given symbolic names to avoid having
+to number them. For example, to create the equivalent of:
+
+@example
+ asm ("bsfl %[aMask], %[aIndex]"
+ : [aIndex] "=r" (Index)
+ : [aMask] "r" (Mask)
+ : "cc");
+@end example
+
+the following API calls could be used:
+
+@example
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_add_extended_asm (block, NULL,
+ "bsfl %[aMask], %[aIndex]");
+ gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index);
+ gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r",
+ gcc_jit_param_as_rvalue (mask));
+ gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
+@end example
+@end deffn
+
+@geindex gcc_jit_block_add_extended_asm (C function)
+@anchor{topics/asm c gcc_jit_block_add_extended_asm}@anchor{123}
+@deffn {C Function} gcc_jit_extended_asm * gcc_jit_block_add_extended_asm (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, const char@w{ }*asm_template)
+
+Create a @ref{f1,,gcc_jit_extended_asm} for an extended @code{asm} statement
+with no control flow (i.e. without the @code{goto} qualifier).
+
+The parameter @code{asm_template} corresponds to the @cite{AssemblerTemplate}
+within C’s extended @code{asm} syntax. It must be non-NULL. The call takes
+a copy of the underlying string, so it is valid to pass in a pointer to
+an on-stack buffer.
+@end deffn
+
+@geindex gcc_jit_block_end_with_extended_asm_goto (C function)
+@anchor{topics/asm c gcc_jit_block_end_with_extended_asm_goto}@anchor{124}
+@deffn {C Function} gcc_jit_extended_asm * gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, const char@w{ }*asm_template, int@w{ }num_goto_blocks, gcc_jit_block@w{ }**goto_blocks, gcc_jit_block@w{ }*fallthrough_block)
+
+Create a @ref{f1,,gcc_jit_extended_asm} for an extended @code{asm} statement
+that may perform jumps, and use it to terminate the given block.
+This is equivalent to the @code{goto} qualifier in C’s extended @code{asm}
+syntax.
+
+For example, to create the equivalent of:
+
+@example
+ asm goto ("btl %1, %0\n\t"
+ "jc %l[carry]"
+ : // No outputs
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+@end example
+
+the following API calls could be used:
+
+@example
+ const char *asm_template =
+ (use_name
+ ? /* Label referred to by name: "%l[carry]". */
+ ("btl %1, %0\n\t"
+ "jc %l[carry]")
+ : /* Label referred to numerically: "%l2". */
+ ("btl %1, %0\n\t"
+ "jc %l2"));
+
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_end_with_extended_asm_goto (b_start, NULL,
+ asm_template,
+ 1, &b_carry,
+ b_fallthru);
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_param_as_rvalue (p1));
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_param_as_rvalue (p2));
+ gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
+@end example
+
+here referencing a @ref{28,,gcc_jit_block} named “carry”.
+
+@code{num_goto_blocks} must be >= 0.
+
+@code{goto_blocks} must be non-NULL. This corresponds to the @code{GotoLabels}
+parameter within C’s extended @code{asm} syntax. The block names can be
+referenced within the assembler template.
+
+@code{fallthrough_block} can be NULL. If non-NULL, it specifies the block
+to fall through to after the statement.
+
+@cartouche
+@quotation Note
+This is needed since each @ref{28,,gcc_jit_block} must have a
+single exit point, as a basic block: you can’t jump from the
+middle of a block. A “goto” is implicitly added after the
+asm to handle the fallthrough case, which is equivalent to what
+would have happened in the C case.
+@end quotation
+@end cartouche
+@end deffn
+
+@geindex gcc_jit_extended_asm_set_volatile_flag (C function)
+@anchor{topics/asm c gcc_jit_extended_asm_set_volatile_flag}@anchor{126}
+@deffn {C Function} void gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm@w{ }*ext_asm, int@w{ }flag)
+
+Set whether the @ref{f1,,gcc_jit_extended_asm} has side-effects, equivalent to the
+volatile@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile}
+qualifier in C’s extended asm syntax.
+
+For example, to create the equivalent of:
+
+@example
+asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (msr)
+ :
+ : "rdx");
+@end example
+
+the following API calls could be used:
+
+@example
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_add_extended_asm
+ (block, NULL,
+ "rdtsc\n\t" /* Returns the time in EDX:EAX. */
+ "shl $32, %%rdx\n\t" /* Shift the upper bits left. */
+ "or %%rdx, %0"); /* 'Or' in the lower bits. */
+ gcc_jit_extended_asm_set_volatile_flag (ext_asm, 1);
+ gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=a", msr);
+ gcc_jit_extended_asm_add_clobber (ext_asm, "rdx");
+@end example
+
+where the @ref{f1,,gcc_jit_extended_asm} is flagged as volatile.
+@end deffn
+
+@geindex gcc_jit_extended_asm_set_inline_flag (C function)
+@anchor{topics/asm c gcc_jit_extended_asm_set_inline_flag}@anchor{127}
+@deffn {C Function} void gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm@w{ }*ext_asm, int@w{ }flag)
+
+Set the equivalent of the
+inline@footnote{https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm}
+qualifier in C’s extended @code{asm} syntax.
+@end deffn
+
+@geindex gcc_jit_extended_asm_add_output_operand (C function)
+@anchor{topics/asm c gcc_jit_extended_asm_add_output_operand}@anchor{128}
+@deffn {C Function} void gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*asm_symbolic_name, const char@w{ }*constraint, gcc_jit_lvalue@w{ }*dest)
+
+Add an output operand to the extended @code{asm} statement. See the
+Output Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands}
+section of the documentation of the C syntax.
+
+@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of C’s
+extended @code{asm} syntax. It can be NULL. If non-NULL it specifies the
+symbolic name for the operand.
+
+@code{constraint} corresponds to the @code{constraint} component of C’s extended
+@code{asm} syntax. It must be non-NULL.
+
+@code{dest} corresponds to the @code{cvariablename} component of C’s extended
+@code{asm} syntax. It must be non-NULL.
+
+@example
+// Example with a NULL symbolic name, the equivalent of:
+// : "=r" (dst)
+gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst);
+
+// Example with a symbolic name ("aIndex"), the equivalent of:
+// : [aIndex] "=r" (index)
+gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index);
+@end example
+
+This function can’t be called on an @code{asm goto} as such instructions can’t
+have outputs; see the
+Goto Labels@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels}
+section of GCC’s “Extended Asm” documentation.
+@end deffn
+
+@geindex gcc_jit_extended_asm_add_input_operand (C function)
+@anchor{topics/asm c gcc_jit_extended_asm_add_input_operand}@anchor{129}
+@deffn {C Function} void gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*asm_symbolic_name, const char@w{ }*constraint, gcc_jit_rvalue@w{ }*src)
+
+Add an input operand to the extended @code{asm} statement. See the
+Input Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands}
+section of the documentation of the C syntax.
+
+@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of C’s
+extended @code{asm} syntax. It can be NULL. If non-NULL it specifies the
+symbolic name for the operand.
+
+@code{constraint} corresponds to the @code{constraint} component of C’s extended
+@code{asm} syntax. It must be non-NULL.
+
+@code{src} corresponds to the @code{cexpression} component of C’s extended
+@code{asm} syntax. It must be non-NULL.
+
+@example
+// Example with a NULL symbolic name, the equivalent of:
+// : "r" (src)
+gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_lvalue_as_rvalue (src));
+
+// Example with a symbolic name ("aMask"), the equivalent of:
+// : [aMask] "r" (Mask)
+gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r",
+ gcc_jit_lvalue_as_rvalue (mask));
+@end example
+@end deffn
+
+@geindex gcc_jit_extended_asm_add_clobber (C function)
+@anchor{topics/asm c gcc_jit_extended_asm_add_clobber}@anchor{12a}
+@deffn {C Function} void gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm@w{ }*ext_asm, const char@w{ }*victim)
+
+Add @cite{victim} to the list of registers clobbered by the extended @code{asm}
+statement. It must be non-NULL. See the
+Clobbers and Scratch Registers@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#}
+section of the documentation of the C syntax.
+
+Statements with multiple clobbers will require multiple calls, one per
+clobber.
+
+For example:
+
+@example
+gcc_jit_extended_asm_add_clobber (ext_asm, "r0");
+gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
+gcc_jit_extended_asm_add_clobber (ext_asm, "memory");
+@end example
+@end deffn
+
+A @ref{f1,,gcc_jit_extended_asm} is a @ref{e,,gcc_jit_object} “owned” by
+the block’s context. The following upcast is available:
+
+@geindex gcc_jit_extended_asm_as_object (C function)
+@anchor{topics/asm c gcc_jit_extended_asm_as_object}@anchor{125}
+@deffn {C Function} gcc_jit_object * gcc_jit_extended_asm_as_object (gcc_jit_extended_asm@w{ }*ext_asm)
+
+Upcast from extended @code{asm} to object.
+@end deffn
+
+@node Adding top-level assembler statements,,Adding assembler instructions within a function,Using Assembly Language with libgccjit
+@anchor{topics/asm adding-top-level-assembler-statements}@anchor{134}
+@subsection Adding top-level assembler statements
+
+
+In addition to creating extended @code{asm} instructions within a function,
+there is support for creating “top-level” assembler statements, outside
+of any function.
+
+@geindex gcc_jit_context_add_top_level_asm (C function)
+@anchor{topics/asm c gcc_jit_context_add_top_level_asm}@anchor{12b}
+@deffn {C Function} void gcc_jit_context_add_top_level_asm (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*asm_stmts)
+
+Create a set of top-level asm statements, analogous to those created
+by GCC’s “basic” @code{asm} syntax in C at file scope.
+
+For example, to create the equivalent of:
+
+@example
+ asm ("\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @@function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t.popsection\n");
+@end example
+
+the following API calls could be used:
+
+@example
+ gcc_jit_context_add_top_level_asm (ctxt, NULL,
+ "\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @@function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t# some asm here\n"
+ "\t.popsection\n");
+@end example
+@end deffn
+
@c Copyright (C) 2014-2020 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -8579,7 +9037,7 @@ for its presence using
@c <http://www.gnu.org/licenses/>.
@node C++ bindings for libgccjit,Internals,Topic Reference,Top
-@anchor{cp/index c-bindings-for-libgccjit}@anchor{125}@anchor{cp/index doc}@anchor{126}
+@anchor{cp/index doc}@anchor{135}@anchor{cp/index c-bindings-for-libgccjit}@anchor{136}
@chapter C++ bindings for libgccjit
@@ -8623,7 +9081,7 @@ Contents:
@end menu
@node Tutorial<2>,Topic Reference<2>,,C++ bindings for libgccjit
-@anchor{cp/intro/index doc}@anchor{127}@anchor{cp/intro/index tutorial}@anchor{128}
+@anchor{cp/intro/index doc}@anchor{137}@anchor{cp/intro/index tutorial}@anchor{138}
@section Tutorial
@@ -8653,7 +9111,7 @@ Contents:
@end menu
@node Tutorial part 1 “Hello world”<2>,Tutorial part 2 Creating a trivial machine code function<2>,,Tutorial<2>
-@anchor{cp/intro/tutorial01 doc}@anchor{129}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{12a}
+@anchor{cp/intro/tutorial01 doc}@anchor{139}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{13a}
@subsection Tutorial part 1: “Hello world”
@@ -8816,7 +9274,7 @@ hello world
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 2 Creating a trivial machine code function<2>,Tutorial part 3 Loops and variables<2>,Tutorial part 1 “Hello world”<2>,Tutorial<2>
-@anchor{cp/intro/tutorial02 doc}@anchor{12b}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{12c}
+@anchor{cp/intro/tutorial02 doc}@anchor{13b}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{13c}
@subsection Tutorial part 2: Creating a trivial machine code function
@@ -8838,10 +9296,10 @@ First we need to include the relevant header:
@end example
All state associated with compilation is associated with a
-@ref{12d,,gccjit;;context}, which is a thin C++ wrapper around the C API’s
+@ref{13d,,gccjit;;context}, which is a thin C++ wrapper around the C API’s
@ref{8,,gcc_jit_context *}.
-Create one using @ref{12e,,gccjit;;context;;acquire()}:
+Create one using @ref{13e,,gccjit;;context;;acquire()}:
@example
gccjit::context ctxt;
@@ -8851,19 +9309,19 @@ ctxt = gccjit::context::acquire ();
The JIT library has a system of types. It is statically-typed: every
expression is of a specific type, fixed at compile-time. In our example,
all of the expressions are of the C @cite{int} type, so let’s obtain this from
-the context, as a @ref{12f,,gccjit;;type}, using
-@ref{130,,gccjit;;context;;get_type()}:
+the context, as a @ref{13f,,gccjit;;type}, using
+@ref{140,,gccjit;;context;;get_type()}:
@example
gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
@end example
-@ref{12f,,gccjit;;type} is an example of a “contextual” object: every
-entity in the API is associated with a @ref{12d,,gccjit;;context}.
+@ref{13f,,gccjit;;type} is an example of a “contextual” object: every
+entity in the API is associated with a @ref{13d,,gccjit;;context}.
Memory management is easy: all such “contextual” objects are automatically
cleaned up for you when the context is released, using
-@ref{131,,gccjit;;context;;release()}:
+@ref{141,,gccjit;;context;;release()}:
@example
ctxt.release ();
@@ -8890,9 +9348,9 @@ The C++ class hierarchy within the @code{gccjit} namespace looks like this:
+- param
@end example
-One thing you can do with a @ref{132,,gccjit;;object} is
+One thing you can do with a @ref{142,,gccjit;;object} is
to ask it for a human-readable description as a @code{std::string}, using
-@ref{133,,gccjit;;object;;get_debug_string()}:
+@ref{143,,gccjit;;object;;get_debug_string()}:
@example
printf ("obj: %s\n", obj.get_debug_string ().c_str ());
@@ -8908,7 +9366,7 @@ This is invaluable when debugging.
Let’s create the function. To do so, we first need to construct
its single parameter, specifying its type and giving it a name,
-using @ref{134,,gccjit;;context;;new_param()}:
+using @ref{144,,gccjit;;context;;new_param()}:
@example
gccjit::param param_i = ctxt.new_param (int_type, "i");
@@ -8949,7 +9407,7 @@ gccjit::block block = func.new_block ();
Our basic block is relatively simple: it immediately terminates by
returning the value of an expression.
-We can build the expression using @ref{135,,gccjit;;context;;new_binary_op()}:
+We can build the expression using @ref{145,,gccjit;;context;;new_binary_op()}:
@example
gccjit::rvalue expr =
@@ -8958,9 +9416,9 @@ gccjit::rvalue expr =
param_i, param_i);
@end example
-A @ref{136,,gccjit;;rvalue} is another example of a
-@ref{132,,gccjit;;object} subclass. As before, we can print it with
-@ref{133,,gccjit;;object;;get_debug_string()}.
+A @ref{146,,gccjit;;rvalue} is another example of a
+@ref{142,,gccjit;;object} subclass. As before, we can print it with
+@ref{143,,gccjit;;object;;get_debug_string()}.
@example
printf ("expr: %s\n", expr.get_debug_string ().c_str ());
@@ -8972,7 +9430,7 @@ giving this output:
expr: i * i
@end example
-Note that @ref{136,,gccjit;;rvalue} provides numerous overloaded operators
+Note that @ref{146,,gccjit;;rvalue} provides numerous overloaded operators
which can be used to dramatically reduce the amount of typing needed.
We can build the above binary operation more directly with this one-liner:
@@ -8989,7 +9447,7 @@ block.end_with_return (expr);
@end example
OK, we’ve populated the context. We can now compile it using
-@ref{137,,gccjit;;context;;compile()}:
+@ref{147,,gccjit;;context;;compile()}:
@example
gcc_jit_result *result;
@@ -9031,12 +9489,12 @@ result: 25
@end menu
@node Options<3>,Full example<3>,,Tutorial part 2 Creating a trivial machine code function<2>
-@anchor{cp/intro/tutorial02 options}@anchor{138}
+@anchor{cp/intro/tutorial02 options}@anchor{148}
@subsubsection Options
To get more information on what’s going on, you can set debugging flags
-on the context using @ref{139,,gccjit;;context;;set_bool_option()}.
+on the context using @ref{149,,gccjit;;context;;set_bool_option()}.
@c (I'm deliberately not mentioning
@c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think
@@ -9100,7 +9558,7 @@ square:
By default, no optimizations are performed, the equivalent of GCC’s
@cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling
-@ref{13a,,gccjit;;context;;set_int_option()} with
+@ref{14a,,gccjit;;context;;set_int_option()} with
@ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}:
@example
@@ -9130,7 +9588,7 @@ square:
Naturally this has only a small effect on such a trivial function.
@node Full example<3>,,Options<3>,Tutorial part 2 Creating a trivial machine code function<2>
-@anchor{cp/intro/tutorial02 full-example}@anchor{13b}
+@anchor{cp/intro/tutorial02 full-example}@anchor{14b}
@subsubsection Full example
@@ -9268,7 +9726,7 @@ result: 25
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 3 Loops and variables<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,Tutorial part 2 Creating a trivial machine code function<2>,Tutorial<2>
-@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{13c}@anchor{cp/intro/tutorial03 doc}@anchor{13d}
+@anchor{cp/intro/tutorial03 doc}@anchor{14c}@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{14d}
@subsection Tutorial part 3: Loops and variables
@@ -9317,14 +9775,14 @@ Here’s what the final control flow graph will look like:
@float Figure
-@image{sum-of-squares,,,image of a control flow graph,png}
+@image{libgccjit-figures/sum-of-squares,,,image of a control flow graph,png}
@end float
@end quotation
As before, we include the libgccjit++ header and make a
-@ref{12d,,gccjit;;context}.
+@ref{13d,,gccjit;;context}.
@example
#include <libgccjit++.h>
@@ -9378,18 +9836,18 @@ gccjit::function func =
@end menu
@node Expressions lvalues and rvalues<2>,Control flow<2>,,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{13e}
+@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{14e}
@subsubsection Expressions: lvalues and rvalues
-The base class of expression is the @ref{136,,gccjit;;rvalue},
+The base class of expression is the @ref{146,,gccjit;;rvalue},
representing an expression that can be on the @emph{right}-hand side of
an assignment: a value that can be computed somehow, and assigned
@emph{to} a storage area (such as a variable). It has a specific
-@ref{12f,,gccjit;;type}.
+@ref{13f,,gccjit;;type}.
-Anothe important class is @ref{13f,,gccjit;;lvalue}.
-A @ref{13f,,gccjit;;lvalue}. is something that can of the @emph{left}-hand
+Anothe important class is @ref{14f,,gccjit;;lvalue}.
+A @ref{14f,,gccjit;;lvalue}. is something that can of the @emph{left}-hand
side of an assignment: a storage area (such as a variable).
In other words, every assignment can be thought of as:
@@ -9398,8 +9856,8 @@ In other words, every assignment can be thought of as:
LVALUE = RVALUE;
@end example
-Note that @ref{13f,,gccjit;;lvalue} is a subclass of
-@ref{136,,gccjit;;rvalue}, where in an assignment of the form:
+Note that @ref{14f,,gccjit;;lvalue} is a subclass of
+@ref{146,,gccjit;;rvalue}, where in an assignment of the form:
@example
LVALUE_A = LVALUE_B;
@@ -9429,7 +9887,7 @@ gccjit::rvalue expr =
gccjit::rvalue expr = param_i * param_i;
@end example
-which is a @ref{136,,gccjit;;rvalue}, and
+which is a @ref{146,,gccjit;;rvalue}, and
@end quotation
@@ -9437,15 +9895,15 @@ which is a @ref{136,,gccjit;;rvalue}, and
@item
the various function parameters: @cite{param_i} and @cite{param_n}, instances of
-@ref{140,,gccjit;;param}, which is a subclass of @ref{13f,,gccjit;;lvalue}
-(and, in turn, of @ref{136,,gccjit;;rvalue}):
+@ref{150,,gccjit;;param}, which is a subclass of @ref{14f,,gccjit;;lvalue}
+(and, in turn, of @ref{146,,gccjit;;rvalue}):
we can both read from and write to function parameters within the
body of a function.
@end enumerate
Our new example has a new kind of expression: we have two local
variables. We create them by calling
-@ref{141,,gccjit;;function;;new_local()}, supplying a type and a name:
+@ref{151,,gccjit;;function;;new_local()}, supplying a type and a name:
@example
/* Build locals: */
@@ -9453,7 +9911,7 @@ gccjit::lvalue i = func.new_local (the_type, "i");
gccjit::lvalue sum = func.new_local (the_type, "sum");
@end example
-These are instances of @ref{13f,,gccjit;;lvalue} - they can be read from
+These are instances of @ref{14f,,gccjit;;lvalue} - they can be read from
and written to.
Note that there is no precanned way to create @emph{and} initialize a variable
@@ -9467,7 +9925,7 @@ Instead, having added the local to the function, we have to separately add
an assignment of @cite{0} to @cite{local_i} at the beginning of the function.
@node Control flow<2>,Visualizing the control flow graph<2>,Expressions lvalues and rvalues<2>,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 control-flow}@anchor{142}
+@anchor{cp/intro/tutorial03 control-flow}@anchor{152}
@subsubsection Control flow
@@ -9490,8 +9948,8 @@ the body of the loop
after the loop terminates (@cite{return sum})
@end enumerate
-so we create these as @ref{143,,gccjit;;block} instances within the
-@ref{144,,gccjit;;function}:
+so we create these as @ref{153,,gccjit;;block} instances within the
+@ref{154,,gccjit;;function}:
@example
gccjit::block b_initial = func.new_block ("initial");
@@ -9504,8 +9962,8 @@ We now populate each block with statements.
The entry block @cite{b_initial} consists of initializations followed by a jump
to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using
-@ref{145,,gccjit;;block;;add_assignment()} to add
-an assignment statement, and using @ref{146,,gccjit;;context;;zero()} to get
+@ref{155,,gccjit;;block;;add_assignment()} to add
+an assignment statement, and using @ref{156,,gccjit;;context;;zero()} to get
the constant value @cite{0} for the relevant type for the right-hand side of
the assignment:
@@ -9526,9 +9984,9 @@ b_initial.end_with_jump (b_loop_cond);
The conditional block is equivalent to the line @cite{while (i < n)} from our
C example. It contains a single statement: a conditional, which jumps to
one of two destination blocks depending on a boolean
-@ref{136,,gccjit;;rvalue}, in this case the comparison of @cite{i} and @cite{n}.
+@ref{146,,gccjit;;rvalue}, in this case the comparison of @cite{i} and @cite{n}.
-We could build the comparison using @ref{147,,gccjit;;context;;new_comparison()}:
+We could build the comparison using @ref{157,,gccjit;;context;;new_comparison()}:
@example
gccjit::rvalue guard =
@@ -9537,7 +9995,7 @@ gccjit::rvalue guard =
@end example
and can then use this to add @cite{b_loop_cond}’s sole statement, via
-@ref{148,,gccjit;;block;;end_with_conditional()}:
+@ref{158,,gccjit;;block;;end_with_conditional()}:
@example
b_loop_cond.end_with_conditional (guard,
@@ -9545,7 +10003,7 @@ b_loop_cond.end_with_conditional (guard,
b_loop_body); // on_false
@end example
-However @ref{136,,gccjit;;rvalue} has overloaded operators for this, so we
+However @ref{146,,gccjit;;rvalue} has overloaded operators for this, so we
express the conditional as
@example
@@ -9565,7 +10023,7 @@ Next, we populate the body of the loop.
The C statement @cite{sum += i * i;} is an assignment operation, where an
lvalue is modified “in-place”. We use
-@ref{149,,gccjit;;block;;add_assignment_op()} to handle these operations:
+@ref{159,,gccjit;;block;;add_assignment_op()} to handle these operations:
@example
/* sum += i * i */
@@ -9589,7 +10047,7 @@ b_loop_body.add_assignment_op (i,
@cartouche
@quotation Note
For numeric constants other than 0 or 1, we could use
-@ref{14a,,gccjit;;context;;new_rvalue()}, which has overloads
+@ref{15a,,gccjit;;context;;new_rvalue()}, which has overloads
for both @code{int} and @code{double}.
@end quotation
@end cartouche
@@ -9655,12 +10113,12 @@ result: 285
@end example
@node Visualizing the control flow graph<2>,Full example<4>,Control flow<2>,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{14b}
+@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{15b}
@subsubsection Visualizing the control flow graph
You can see the control flow graph of a function using
-@ref{14c,,gccjit;;function;;dump_to_dot()}:
+@ref{15c,,gccjit;;function;;dump_to_dot()}:
@example
func.dump_to_dot ("/tmp/sum-of-squares.dot");
@@ -9683,14 +10141,14 @@ install it with @cite{yum install python-xdot}):
@float Figure
-@image{sum-of-squares,,,image of a control flow graph,png}
+@image{libgccjit-figures/sum-of-squares,,,image of a control flow graph,png}
@end float
@end quotation
@node Full example<4>,,Visualizing the control flow graph<2>,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 full-example}@anchor{14d}
+@anchor{cp/intro/tutorial03 full-example}@anchor{15d}
@subsubsection Full example
@@ -9868,7 +10326,7 @@ loop_test returned: 285
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,,Tutorial part 3 Loops and variables<2>,Tutorial<2>
-@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{14e}@anchor{cp/intro/tutorial04 doc}@anchor{14f}
+@anchor{cp/intro/tutorial04 doc}@anchor{15e}@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{15f}
@subsection Tutorial part 4: Adding JIT-compilation to a toy interpreter
@@ -9890,7 +10348,7 @@ to it.
@end menu
@node Our toy interpreter<2>,Compiling to machine code<2>,,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{150}
+@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{160}
@subsubsection Our toy interpreter
@@ -10292,7 +10750,7 @@ toyvm_function::interpret (int arg, FILE *trace)
@end quotation
@node Compiling to machine code<2>,Setting things up<2>,Our toy interpreter<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{151}
+@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{161}
@subsubsection Compiling to machine code
@@ -10362,7 +10820,7 @@ This means our compiler has the following state:
@end quotation
@node Setting things up<2>,Populating the function<2>,Compiling to machine code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 setting-things-up}@anchor{152}
+@anchor{cp/intro/tutorial04 setting-things-up}@anchor{162}
@subsubsection Setting things up
@@ -10452,7 +10910,7 @@ compilation_state::add_pop (gccjit::block block,
@end quotation
We will support single-stepping through the generated code in the
-debugger, so we need to create @ref{153,,gccjit;;location} instances, one
+debugger, so we need to create @ref{163,,gccjit;;location} instances, one
per operation in the source code. These will reference the lines of
e.g. @code{factorial.toy}.
@@ -10512,7 +10970,7 @@ We create the locals within the function.
@end quotation
@node Populating the function<2>,Verifying the control flow graph<2>,Setting things up<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 populating-the-function}@anchor{154}
+@anchor{cp/intro/tutorial04 populating-the-function}@anchor{164}
@subsubsection Populating the function
@@ -10625,7 +11083,7 @@ stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y
uninitialized.
To track this kind of thing down, we can use
-@ref{155,,gccjit;;block;;add_comment()} to add descriptive comments
+@ref{165,,gccjit;;block;;add_comment()} to add descriptive comments
to the internal representation. This is invaluable when looking through
the generated IR for, say @code{factorial}:
@@ -10765,14 +11223,14 @@ to the next block.
This is analogous to simply incrementing the program counter.
@node Verifying the control flow graph<2>,Compiling the context<2>,Populating the function<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{156}
+@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{166}
@subsubsection Verifying the control flow graph
Having finished looping over the blocks, the context is complete.
As before, we can verify that the control flow and statements are sane by
-using @ref{14c,,gccjit;;function;;dump_to_dot()}:
+using @ref{15c,,gccjit;;function;;dump_to_dot()}:
@example
fn.dump_to_dot ("/tmp/factorial.dot");
@@ -10787,14 +11245,14 @@ errors in our compiler.
@float Figure
-@image{factorial,,,image of a control flow graph,png}
+@image{libgccjit-figures/factorial,,,image of a control flow graph,png}
@end float
@end quotation
@node Compiling the context<2>,Single-stepping through the generated code<2>,Verifying the control flow graph<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{157}
+@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{167}
@subsubsection Compiling the context
@@ -10845,7 +11303,7 @@ private:
@end quotation
@node Single-stepping through the generated code<2>,Examining the generated code<2>,Compiling the context<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{158}
+@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{168}
@subsubsection Single-stepping through the generated code
@@ -10859,14 +11317,14 @@ It’s possible to debug the generated code. To do this we need to both:
@item
Set up source code locations for our statements, so that we can
meaningfully step through the code. We did this above by
-calling @ref{159,,gccjit;;context;;new_location()} and using the
+calling @ref{169,,gccjit;;context;;new_location()} and using the
results.
@item
Enable the generation of debugging information, by setting
@ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the
-@ref{12d,,gccjit;;context} via
-@ref{139,,gccjit;;context;;set_bool_option()}:
+@ref{13d,,gccjit;;context} via
+@ref{149,,gccjit;;context;;set_bool_option()}:
@example
ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
@@ -10930,14 +11388,14 @@ optimization level in a regular compiler.
@end cartouche
@node Examining the generated code<2>,Putting it all together<2>,Single-stepping through the generated code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{15a}
+@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{16a}
@subsubsection Examining the generated code
How good is the optimized code?
We can turn up optimizations, by calling
-@ref{13a,,gccjit;;context;;set_int_option()} with
+@ref{14a,,gccjit;;context;;set_int_option()} with
@ref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}:
@example
@@ -11105,7 +11563,7 @@ Note that the stack pushing and popping have been eliminated, as has the
recursive call (in favor of an iteration).
@node Putting it all together<2>,Behind the curtain How does our code get optimized?<2>,Examining the generated code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{15b}
+@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{16b}
@subsubsection Putting it all together
@@ -11136,7 +11594,7 @@ compiler result: 55
@end example
@node Behind the curtain How does our code get optimized?<2>,,Putting it all together<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{15c}
+@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{16c}
@subsubsection Behind the curtain: How does our code get optimized?
@@ -11314,7 +11772,7 @@ instr9:
@}
@end example
-Note in the above how all the @ref{143,,gccjit;;block} instances we
+Note in the above how all the @ref{153,,gccjit;;block} instances we
created have been consolidated into just 3 blocks in GCC’s internal
representation: @code{initial}, @code{instr4} and @code{instr9}.
@@ -11325,7 +11783,7 @@ representation: @code{initial}, @code{instr4} and @code{instr9}.
@end menu
@node Optimizing away stack manipulation<2>,Elimination of tail recursion<2>,,Behind the curtain How does our code get optimized?<2>
-@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{15d}
+@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{16d}
@subsubsection Optimizing away stack manipulation
@@ -11589,7 +12047,7 @@ instr9:
@end example
@node Elimination of tail recursion<2>,,Optimizing away stack manipulation<2>,Behind the curtain How does our code get optimized?<2>
-@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{15e}
+@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{16e}
@subsubsection Elimination of tail recursion
@@ -11672,7 +12130,7 @@ instr9:
@c <http://www.gnu.org/licenses/>.
@node Topic Reference<2>,,Tutorial<2>,C++ bindings for libgccjit
-@anchor{cp/topics/index doc}@anchor{15f}@anchor{cp/topics/index topic-reference}@anchor{160}
+@anchor{cp/topics/index doc}@anchor{16f}@anchor{cp/topics/index topic-reference}@anchor{170}
@section Topic Reference
@@ -11701,26 +12159,27 @@ instr9:
* Creating and using functions: Creating and using functions<2>.
* Source Locations: Source Locations<2>.
* Compiling a context: Compiling a context<2>.
+* Using Assembly Language with libgccjit++::
@end menu
@node Compilation contexts<2>,Objects<2>,,Topic Reference<2>
-@anchor{cp/topics/contexts compilation-contexts}@anchor{161}@anchor{cp/topics/contexts doc}@anchor{162}
+@anchor{cp/topics/contexts doc}@anchor{171}@anchor{cp/topics/contexts compilation-contexts}@anchor{172}
@subsection Compilation contexts
@geindex gccjit;;context (C++ class)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7contextE}@anchor{12d}@anchor{cp/topics/contexts gccjit context}@anchor{163}
+@anchor{cp/topics/contexts _CPPv4N6gccjit7contextE}@anchor{13d}@anchor{cp/topics/contexts _CPPv3N6gccjit7contextE}@anchor{173}@anchor{cp/topics/contexts _CPPv2N6gccjit7contextE}@anchor{174}@anchor{cp/topics/contexts gccjit context}@anchor{175}
@deffn {C++ Class} gccjit::context
@end deffn
-The top-level of the C++ API is the @ref{12d,,gccjit;;context} type.
+The top-level of the C++ API is the @ref{13d,,gccjit;;context} type.
-A @ref{12d,,gccjit;;context} instance encapsulates the state of a
+A @ref{13d,,gccjit;;context} instance encapsulates the state of a
compilation.
You can set up options on it, and add types, functions and code.
-Invoking @ref{137,,gccjit;;context;;compile()} on it gives you a
+Invoking @ref{147,,gccjit;;context;;compile()} on it gives you a
@ref{16,,gcc_jit_result *}.
It is a thin wrapper around the C API’s @ref{8,,gcc_jit_context *}.
@@ -11735,7 +12194,7 @@ It is a thin wrapper around the C API’s @ref{8,,gcc_jit_context *}.
@end menu
@node Lifetime-management<2>,Thread-safety<2>,,Compilation contexts<2>
-@anchor{cp/topics/contexts lifetime-management}@anchor{164}
+@anchor{cp/topics/contexts lifetime-management}@anchor{176}
@subsubsection Lifetime-management
@@ -11744,17 +12203,17 @@ have their lifetime bounded by the context they are created within, and
cleanup of such objects is done for you when the context is released.
@geindex gccjit;;context;;acquire (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context7acquireEv}@anchor{12e}@anchor{cp/topics/contexts gccjit context acquire}@anchor{165}
-@deffn {C++ Function} gccjit::@ref{12d,,context} gccjit::context::acquire ()
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context7acquireEv}@anchor{13e}@anchor{cp/topics/contexts _CPPv3N6gccjit7context7acquireEv}@anchor{177}@anchor{cp/topics/contexts _CPPv2N6gccjit7context7acquireEv}@anchor{178}@anchor{cp/topics/contexts gccjit context acquire}@anchor{179}
+@deffn {C++ Function} gccjit::@ref{13d,,context} gccjit::@ref{13d,,context}::acquire ()
-This function acquires a new @ref{12d,,gccjit;;context} instance,
+This function acquires a new @ref{13d,,gccjit;;context} instance,
which is independent of any others that may be present within this
process.
@end deffn
@geindex gccjit;;context;;release (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context7releaseEv}@anchor{131}@anchor{cp/topics/contexts gccjit context release}@anchor{166}
-@deffn {C++ Function} void gccjit::context::release ()
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context7releaseEv}@anchor{141}@anchor{cp/topics/contexts _CPPv3N6gccjit7context7releaseEv}@anchor{17a}@anchor{cp/topics/contexts _CPPv2N6gccjit7context7releaseEv}@anchor{17b}@anchor{cp/topics/contexts gccjit context release}@anchor{17c}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::release ()
This function releases all resources associated with the given context.
Both the context itself and all of its @code{gccjit::object *}
@@ -11770,8 +12229,8 @@ ctxt.release ();
@end deffn
@geindex gccjit;;context;;new_child_context (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context17new_child_contextEv}@anchor{167}@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{168}
-@deffn {C++ Function} gccjit::@ref{12d,,context} gccjit::context::new_child_context ()
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context17new_child_contextEv}@anchor{17d}@anchor{cp/topics/contexts _CPPv3N6gccjit7context17new_child_contextEv}@anchor{17e}@anchor{cp/topics/contexts _CPPv2N6gccjit7context17new_child_contextEv}@anchor{17f}@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{180}
+@deffn {C++ Function} gccjit::@ref{13d,,context} gccjit::@ref{13d,,context}::new_child_context ()
Given an existing JIT context, create a child context.
@@ -11802,16 +12261,16 @@ there will likely be a performance hit for such nesting.
@end deffn
@node Thread-safety<2>,Error-handling<3>,Lifetime-management<2>,Compilation contexts<2>
-@anchor{cp/topics/contexts thread-safety}@anchor{169}
+@anchor{cp/topics/contexts thread-safety}@anchor{181}
@subsubsection Thread-safety
-Instances of @ref{12d,,gccjit;;context} created via
-@ref{12e,,gccjit;;context;;acquire()} are independent from each other:
+Instances of @ref{13d,,gccjit;;context} created via
+@ref{13e,,gccjit;;context;;acquire()} are independent from each other:
only one thread may use a given context at once, but multiple threads
could each have their own contexts without needing locks.
-Contexts created via @ref{167,,gccjit;;context;;new_child_context()} are
+Contexts created via @ref{17d,,gccjit;;context;;new_child_context()} are
related to their parent context. They can be partitioned by their
ultimate ancestor into independent “family trees”. Only one thread
within a process may use a given “family tree” of such contexts at once,
@@ -11819,7 +12278,7 @@ and if you’re using multiple threads you should provide your own locking
around entire such context partitions.
@node Error-handling<3>,Debugging<2>,Thread-safety<2>,Compilation contexts<2>
-@anchor{cp/topics/contexts error-handling}@anchor{16a}
+@anchor{cp/topics/contexts error-handling}@anchor{182}
@subsubsection Error-handling
@@ -11832,11 +12291,11 @@ NULL. You don’t have to check everywhere for NULL results, since the
API gracefully handles a NULL being passed in for any argument.
Errors are printed on stderr and can be queried using
-@ref{16b,,gccjit;;context;;get_first_error()}.
+@ref{183,,gccjit;;context;;get_first_error()}.
@geindex gccjit;;context;;get_first_error (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{16b}@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{16c}
-@deffn {C++ Function} const char *gccjit::context::get_first_error (gccjit::context *ctxt)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{183}@anchor{cp/topics/contexts _CPPv3N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{184}@anchor{cp/topics/contexts _CPPv2N6gccjit7context15get_first_errorEPN6gccjit7contextE}@anchor{185}@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{186}
+@deffn {C++ Function} const char *gccjit::@ref{13d,,context}::get_first_error (gccjit::context *ctxt)
Returns the first error message that occurred on the context.
@@ -11847,18 +12306,18 @@ If no errors occurred, this will be NULL.
@end deffn
@node Debugging<2>,Options<4>,Error-handling<3>,Compilation contexts<2>
-@anchor{cp/topics/contexts debugging}@anchor{16d}
+@anchor{cp/topics/contexts debugging}@anchor{187}
@subsubsection Debugging
@geindex gccjit;;context;;dump_to_file (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{16e}@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{16f}
-@deffn {C++ Function} void gccjit::context::dump_to_file (const std::string &path, int update_locations)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{188}@anchor{cp/topics/contexts _CPPv3N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{189}@anchor{cp/topics/contexts _CPPv2N6gccjit7context12dump_to_fileERKNSt6stringEi}@anchor{18a}@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{18b}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::dump_to_file (const std::string &path, int update_locations)
To help with debugging: dump a C-like representation to the given path,
describing what’s been set up on the context.
-If “update_locations” is true, then also set up @ref{153,,gccjit;;location}
+If “update_locations” is true, then also set up @ref{163,,gccjit;;location}
information throughout the context, pointing at the dump file as if it
were a source file. This may be of use in conjunction with
@code{GCCJIT::BOOL_OPTION_DEBUGINFO} to allow stepping through the
@@ -11866,8 +12325,8 @@ code in a debugger.
@end deffn
@geindex gccjit;;context;;dump_reproducer_to_file (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{170}@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{171}
-@deffn {C++ Function} void gccjit::context::dump_reproducer_to_file (gcc_jit_context *ctxt, const char *path)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{18c}@anchor{cp/topics/contexts _CPPv3N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{18d}@anchor{cp/topics/contexts _CPPv2N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc}@anchor{18e}@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{18f}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::dump_reproducer_to_file (gcc_jit_context *ctxt, const char *path)
This is a thin wrapper around the C API
@ref{5d,,gcc_jit_context_dump_reproducer_to_file()}, and hence works the
@@ -11878,7 +12337,7 @@ for seeing what the C++ bindings are doing at the C level.
@end deffn
@node Options<4>,,Debugging<2>,Compilation contexts<2>
-@anchor{cp/topics/contexts options}@anchor{172}
+@anchor{cp/topics/contexts options}@anchor{190}
@subsubsection Options
@@ -11891,13 +12350,13 @@ for seeing what the C++ bindings are doing at the C level.
@end menu
@node String Options<2>,Boolean options<2>,,Options<4>
-@anchor{cp/topics/contexts string-options}@anchor{173}
+@anchor{cp/topics/contexts string-options}@anchor{191}
@subsubsection String Options
@geindex gccjit;;context;;set_str_option (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{174}@anchor{cp/topics/contexts gccjit context set_str_option__gcc_jit_str_option cCP}@anchor{175}
-@deffn {C++ Function} void gccjit::context::set_str_option (enum gcc_jit_str_option, const char *value)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{192}@anchor{cp/topics/contexts _CPPv3N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{193}@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc}@anchor{194}@anchor{cp/topics/contexts gccjit context set_str_option__gcc_jit_str_option cCP}@anchor{195}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_str_option (enum gcc_jit_str_option, const char *value)
Set a string option of the context.
@@ -11907,13 +12366,13 @@ meaning.
@end deffn
@node Boolean options<2>,Integer options<2>,String Options<2>,Options<4>
-@anchor{cp/topics/contexts boolean-options}@anchor{176}
+@anchor{cp/topics/contexts boolean-options}@anchor{196}
@subsubsection Boolean options
@geindex gccjit;;context;;set_bool_option (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{139}@anchor{cp/topics/contexts gccjit context set_bool_option__gcc_jit_bool_option i}@anchor{177}
-@deffn {C++ Function} void gccjit::context::set_bool_option (enum gcc_jit_bool_option, int value)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{149}@anchor{cp/topics/contexts _CPPv3N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{197}@anchor{cp/topics/contexts _CPPv2N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni}@anchor{198}@anchor{cp/topics/contexts gccjit context set_bool_option__gcc_jit_bool_option i}@anchor{199}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_bool_option (enum gcc_jit_bool_option, int value)
Set a boolean option of the context.
@@ -11923,8 +12382,8 @@ meaning.
@end deffn
@geindex gccjit;;context;;set_bool_allow_unreachable_blocks (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{178}@anchor{cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i}@anchor{179}
-@deffn {C++ Function} void gccjit::context::set_bool_allow_unreachable_blocks (int bool_value)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{19a}@anchor{cp/topics/contexts _CPPv3N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{19b}@anchor{cp/topics/contexts _CPPv2N6gccjit7context33set_bool_allow_unreachable_blocksEi}@anchor{19c}@anchor{cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i}@anchor{19d}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_bool_allow_unreachable_blocks (int bool_value)
By default, libgccjit will issue an error about unreachable blocks
within a function.
@@ -11942,8 +12401,8 @@ its presence using
@end deffn
@geindex gccjit;;context;;set_bool_use_external_driver (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context28set_bool_use_external_driverEi}@anchor{17a}@anchor{cp/topics/contexts gccjit context set_bool_use_external_driver__i}@anchor{17b}
-@deffn {C++ Function} void gccjit::context::set_bool_use_external_driver (int bool_value)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context28set_bool_use_external_driverEi}@anchor{19e}@anchor{cp/topics/contexts _CPPv3N6gccjit7context28set_bool_use_external_driverEi}@anchor{19f}@anchor{cp/topics/contexts _CPPv2N6gccjit7context28set_bool_use_external_driverEi}@anchor{1a0}@anchor{cp/topics/contexts gccjit context set_bool_use_external_driver__i}@anchor{1a1}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_bool_use_external_driver (int bool_value)
libgccjit internally generates assembler, and uses “driver” code
for converting it to other formats (e.g. shared libraries).
@@ -11964,13 +12423,13 @@ its presence using
@end deffn
@node Integer options<2>,Additional command-line options<2>,Boolean options<2>,Options<4>
-@anchor{cp/topics/contexts integer-options}@anchor{17c}
+@anchor{cp/topics/contexts integer-options}@anchor{1a2}
@subsubsection Integer options
@geindex gccjit;;context;;set_int_option (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{13a}@anchor{cp/topics/contexts gccjit context set_int_option__gcc_jit_int_option i}@anchor{17d}
-@deffn {C++ Function} void gccjit::context::set_int_option (enum gcc_jit_int_option, int value)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{14a}@anchor{cp/topics/contexts _CPPv3N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{1a3}@anchor{cp/topics/contexts _CPPv2N6gccjit7context14set_int_optionE18gcc_jit_int_optioni}@anchor{1a4}@anchor{cp/topics/contexts gccjit context set_int_option__gcc_jit_int_option i}@anchor{1a5}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::set_int_option (enum gcc_jit_int_option, int value)
Set an integer option of the context.
@@ -11980,13 +12439,13 @@ meaning.
@end deffn
@node Additional command-line options<2>,,Integer options<2>,Options<4>
-@anchor{cp/topics/contexts additional-command-line-options}@anchor{17e}
+@anchor{cp/topics/contexts additional-command-line-options}@anchor{1a6}
@subsubsection Additional command-line options
@geindex gccjit;;context;;add_command_line_option (C++ function)
-@anchor{cp/topics/contexts _CPPv2N6gccjit7context23add_command_line_optionEPKc}@anchor{17f}@anchor{cp/topics/contexts gccjit context add_command_line_option__cCP}@anchor{180}
-@deffn {C++ Function} void gccjit::context::add_command_line_option (const char *optname)
+@anchor{cp/topics/contexts _CPPv4N6gccjit7context23add_command_line_optionEPKc}@anchor{1a7}@anchor{cp/topics/contexts _CPPv3N6gccjit7context23add_command_line_optionEPKc}@anchor{1a8}@anchor{cp/topics/contexts _CPPv2N6gccjit7context23add_command_line_optionEPKc}@anchor{1a9}@anchor{cp/topics/contexts gccjit context add_command_line_option__cCP}@anchor{1aa}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::add_command_line_option (const char *optname)
Add an arbitrary gcc command-line option to the context for use
when compiling.
@@ -12020,18 +12479,18 @@ its presence using
@c <http://www.gnu.org/licenses/>.
@node Objects<2>,Types<2>,Compilation contexts<2>,Topic Reference<2>
-@anchor{cp/topics/objects objects}@anchor{181}@anchor{cp/topics/objects doc}@anchor{182}
+@anchor{cp/topics/objects doc}@anchor{1ab}@anchor{cp/topics/objects objects}@anchor{1ac}
@subsection Objects
@geindex gccjit;;object (C++ class)
-@anchor{cp/topics/objects _CPPv2N6gccjit6objectE}@anchor{132}@anchor{cp/topics/objects gccjit object}@anchor{183}
+@anchor{cp/topics/objects _CPPv4N6gccjit6objectE}@anchor{142}@anchor{cp/topics/objects _CPPv3N6gccjit6objectE}@anchor{1ad}@anchor{cp/topics/objects _CPPv2N6gccjit6objectE}@anchor{1ae}@anchor{cp/topics/objects gccjit object}@anchor{1af}
@deffn {C++ Class} gccjit::object
@end deffn
Almost every entity in the API (with the exception of
-@ref{12d,,gccjit;;context} and @ref{16,,gcc_jit_result *}) is a
-“contextual” object, a @ref{132,,gccjit;;object}.
+@ref{13d,,gccjit;;context} and @ref{16,,gcc_jit_result *}) is a
+“contextual” object, a @ref{142,,gccjit;;object}.
A JIT object:
@@ -12041,7 +12500,7 @@ A JIT object:
@itemize *
@item
-is associated with a @ref{12d,,gccjit;;context}.
+is associated with a @ref{13d,,gccjit;;context}.
@item
is automatically cleaned up for you when its context is released so
@@ -12066,18 +12525,18 @@ The C++ class hierarchy within the @code{gccjit} namespace looks like this:
+- case_
@end example
-The @ref{132,,gccjit;;object} base class has the following operations:
+The @ref{142,,gccjit;;object} base class has the following operations:
@geindex gccjit;;object;;get_context (C++ function)
-@anchor{cp/topics/objects _CPPv2NK6gccjit6object11get_contextEv}@anchor{184}@anchor{cp/topics/objects gccjit object get_contextC}@anchor{185}
-@deffn {C++ Function} gccjit::@ref{12d,,context} gccjit::object::get_context () const
+@anchor{cp/topics/objects _CPPv4NK6gccjit6object11get_contextEv}@anchor{1b0}@anchor{cp/topics/objects _CPPv3NK6gccjit6object11get_contextEv}@anchor{1b1}@anchor{cp/topics/objects _CPPv2NK6gccjit6object11get_contextEv}@anchor{1b2}@anchor{cp/topics/objects gccjit object get_contextC}@anchor{1b3}
+@deffn {C++ Function} gccjit::@ref{13d,,context} gccjit::@ref{142,,object}::get_context () const
Which context is the obj within?
@end deffn
@geindex gccjit;;object;;get_debug_string (C++ function)
-@anchor{cp/topics/objects _CPPv2NK6gccjit6object16get_debug_stringEv}@anchor{133}@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{186}
-@deffn {C++ Function} std::string gccjit::object::get_debug_string () const
+@anchor{cp/topics/objects _CPPv4NK6gccjit6object16get_debug_stringEv}@anchor{143}@anchor{cp/topics/objects _CPPv3NK6gccjit6object16get_debug_stringEv}@anchor{1b4}@anchor{cp/topics/objects _CPPv2NK6gccjit6object16get_debug_stringEv}@anchor{1b5}@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{1b6}
+@deffn {C++ Function} std::string gccjit::@ref{142,,object}::get_debug_string () const
Generate a human-readable description for the given object.
@@ -12112,16 +12571,16 @@ obj: 4.0 * (float)i
@c <http://www.gnu.org/licenses/>.
@node Types<2>,Expressions<2>,Objects<2>,Topic Reference<2>
-@anchor{cp/topics/types doc}@anchor{187}@anchor{cp/topics/types types}@anchor{188}
+@anchor{cp/topics/types doc}@anchor{1b7}@anchor{cp/topics/types types}@anchor{1b8}
@subsection Types
@geindex gccjit;;type (C++ class)
-@anchor{cp/topics/types _CPPv2N6gccjit4typeE}@anchor{12f}@anchor{cp/topics/types gccjit type}@anchor{189}
+@anchor{cp/topics/types _CPPv4N6gccjit4typeE}@anchor{13f}@anchor{cp/topics/types _CPPv3N6gccjit4typeE}@anchor{1b9}@anchor{cp/topics/types _CPPv2N6gccjit4typeE}@anchor{1ba}@anchor{cp/topics/types gccjit type}@anchor{1bb}
@deffn {C++ Class} gccjit::type
gccjit::type represents a type within the library. It is a subclass
-of @ref{132,,gccjit;;object}.
+of @ref{142,,gccjit;;object}.
@end deffn
Types can be created in several ways:
@@ -12131,7 +12590,7 @@ Types can be created in several ways:
@item
fundamental types can be accessed using
-@ref{130,,gccjit;;context;;get_type()}:
+@ref{140,,gccjit;;context;;get_type()}:
@example
gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
@@ -12147,7 +12606,7 @@ See @ref{b,,gcc_jit_context_get_type()} for the available types.
@item
derived types can be accessed by using functions such as
-@ref{18a,,gccjit;;type;;get_pointer()} and @ref{18b,,gccjit;;type;;get_const()}:
+@ref{1bc,,gccjit;;type;;get_pointer()} and @ref{1bd,,gccjit;;type;;get_const()}:
@example
gccjit::type const_int_star = int_type.get_const ().get_pointer ();
@@ -12167,28 +12626,28 @@ by creating structures (see below).
@end menu
@node Standard types<2>,Pointers const and volatile<2>,,Types<2>
-@anchor{cp/topics/types standard-types}@anchor{18c}
+@anchor{cp/topics/types standard-types}@anchor{1be}
@subsubsection Standard types
@geindex gccjit;;context;;get_type (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit7context8get_typeE13gcc_jit_types}@anchor{130}@anchor{cp/topics/types gccjit context get_type__gcc_jit_types}@anchor{18d}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::context::get_type (enum gcc_jit_types)
+@anchor{cp/topics/types _CPPv4N6gccjit7context8get_typeE13gcc_jit_types}@anchor{140}@anchor{cp/topics/types _CPPv3N6gccjit7context8get_typeE13gcc_jit_types}@anchor{1bf}@anchor{cp/topics/types _CPPv2N6gccjit7context8get_typeE13gcc_jit_types}@anchor{1c0}@anchor{cp/topics/types gccjit context get_type__gcc_jit_types}@anchor{1c1}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::get_type (enum gcc_jit_types)
Access a specific type. This is a thin wrapper around
@ref{b,,gcc_jit_context_get_type()}; the parameter has the same meaning.
@end deffn
@geindex gccjit;;context;;get_int_type (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit7context12get_int_typeE6size_ti}@anchor{18e}@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{18f}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::context::get_int_type (size_t num_bytes, int is_signed)
+@anchor{cp/topics/types _CPPv4N6gccjit7context12get_int_typeE6size_ti}@anchor{1c2}@anchor{cp/topics/types _CPPv3N6gccjit7context12get_int_typeE6size_ti}@anchor{1c3}@anchor{cp/topics/types _CPPv2N6gccjit7context12get_int_typeE6size_ti}@anchor{1c4}@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{1c5}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::get_int_type (size_t num_bytes, int is_signed)
Access the integer type of the given size.
@end deffn
@geindex gccjit;;context;;get_int_type<T> (C++ function)
-@anchor{cp/topics/types _CPPv2IEN6gccjit7context12get_int_typeI1TEEv}@anchor{190}
-@deffn {C++ Function} template<>gccjit::@ref{12f,,type} gccjit::context::get_int_type<T> ()
+@anchor{cp/topics/types _CPPv4IEN6gccjit7context12get_int_typeI1TEEN6gccjit4typeEv}@anchor{1c6}@anchor{cp/topics/types _CPPv3IEN6gccjit7context12get_int_typeI1TEEv}@anchor{1c7}@anchor{cp/topics/types _CPPv2IEN6gccjit7context12get_int_typeI1TEEv}@anchor{1c8}
+@deffn {C++ Function} template<>gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::get_int_type<T> ()
Access the given integer type. For example, you could map the
@code{unsigned short} type into a gccjit::type via:
@@ -12199,34 +12658,34 @@ gccjit::type t = ctxt.get_int_type <unsigned short> ();
@end deffn
@node Pointers const and volatile<2>,Vector types<2>,Standard types<2>,Types<2>
-@anchor{cp/topics/types pointers-const-and-volatile}@anchor{191}
+@anchor{cp/topics/types pointers-const-and-volatile}@anchor{1c9}
@subsubsection Pointers, @cite{const}, and @cite{volatile}
@geindex gccjit;;type;;get_pointer (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit4type11get_pointerEv}@anchor{18a}@anchor{cp/topics/types gccjit type get_pointer}@anchor{192}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::type::get_pointer ()
+@anchor{cp/topics/types _CPPv4N6gccjit4type11get_pointerEv}@anchor{1bc}@anchor{cp/topics/types _CPPv3N6gccjit4type11get_pointerEv}@anchor{1ca}@anchor{cp/topics/types _CPPv2N6gccjit4type11get_pointerEv}@anchor{1cb}@anchor{cp/topics/types gccjit type get_pointer}@anchor{1cc}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_pointer ()
Given type “T”, get type “T*”.
@end deffn
@geindex gccjit;;type;;get_const (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit4type9get_constEv}@anchor{18b}@anchor{cp/topics/types gccjit type get_const}@anchor{193}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::type::get_const ()
+@anchor{cp/topics/types _CPPv4N6gccjit4type9get_constEv}@anchor{1bd}@anchor{cp/topics/types _CPPv3N6gccjit4type9get_constEv}@anchor{1cd}@anchor{cp/topics/types _CPPv2N6gccjit4type9get_constEv}@anchor{1ce}@anchor{cp/topics/types gccjit type get_const}@anchor{1cf}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_const ()
Given type “T”, get type “const T”.
@end deffn
@geindex gccjit;;type;;get_volatile (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit4type12get_volatileEv}@anchor{194}@anchor{cp/topics/types gccjit type get_volatile}@anchor{195}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::type::get_volatile ()
+@anchor{cp/topics/types _CPPv4N6gccjit4type12get_volatileEv}@anchor{1d0}@anchor{cp/topics/types _CPPv3N6gccjit4type12get_volatileEv}@anchor{1d1}@anchor{cp/topics/types _CPPv2N6gccjit4type12get_volatileEv}@anchor{1d2}@anchor{cp/topics/types gccjit type get_volatile}@anchor{1d3}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_volatile ()
Given type “T”, get type “volatile T”.
@end deffn
@geindex gccjit;;type;;get_aligned (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit4type11get_alignedE6size_t}@anchor{196}@anchor{cp/topics/types gccjit type get_aligned__s}@anchor{197}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::type::get_aligned (size_t alignment_in_bytes)
+@anchor{cp/topics/types _CPPv4N6gccjit4type11get_alignedE6size_t}@anchor{1d4}@anchor{cp/topics/types _CPPv3N6gccjit4type11get_alignedE6size_t}@anchor{1d5}@anchor{cp/topics/types _CPPv2N6gccjit4type11get_alignedE6size_t}@anchor{1d6}@anchor{cp/topics/types gccjit type get_aligned__s}@anchor{1d7}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_aligned (size_t alignment_in_bytes)
Given type “T”, get type:
@@ -12238,21 +12697,21 @@ The alignment must be a power of two.
@end deffn
@geindex gccjit;;context;;new_array_type (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{198}@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{199}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::context::new_array_type (gccjit::type element_type, int num_elements, gccjit::location loc)
+@anchor{cp/topics/types _CPPv4N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{1d8}@anchor{cp/topics/types _CPPv3N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{1d9}@anchor{cp/topics/types _CPPv2N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE}@anchor{1da}@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{1db}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13d,,context}::new_array_type (gccjit::type element_type, int num_elements, gccjit::location loc)
Given type “T”, get type “T[N]” (for a constant N).
Param “loc” is optional.
@end deffn
@node Vector types<2>,Structures and unions<2>,Pointers const and volatile<2>,Types<2>
-@anchor{cp/topics/types vector-types}@anchor{19a}
+@anchor{cp/topics/types vector-types}@anchor{1dc}
@subsubsection Vector types
@geindex gccjit;;type;;get_vector (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit4type10get_vectorE6size_t}@anchor{19b}@anchor{cp/topics/types gccjit type get_vector__s}@anchor{19c}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::type::get_vector (size_t num_units)
+@anchor{cp/topics/types _CPPv4N6gccjit4type10get_vectorE6size_t}@anchor{1dd}@anchor{cp/topics/types _CPPv3N6gccjit4type10get_vectorE6size_t}@anchor{1de}@anchor{cp/topics/types _CPPv2N6gccjit4type10get_vectorE6size_t}@anchor{1df}@anchor{cp/topics/types gccjit type get_vector__s}@anchor{1e0}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{13f,,type}::get_vector (size_t num_units)
Given type “T”, get type:
@@ -12264,31 +12723,31 @@ T must be integral or floating point; num_units must be a power of two.
@end deffn
@node Structures and unions<2>,,Vector types<2>,Types<2>
-@anchor{cp/topics/types structures-and-unions}@anchor{19d}
+@anchor{cp/topics/types structures-and-unions}@anchor{1e1}
@subsubsection Structures and unions
@geindex gccjit;;struct_ (C++ class)
-@anchor{cp/topics/types _CPPv2N6gccjit7struct_E}@anchor{19e}@anchor{cp/topics/types gccjit struct_}@anchor{19f}
+@anchor{cp/topics/types _CPPv4N6gccjit7struct_E}@anchor{1e2}@anchor{cp/topics/types _CPPv3N6gccjit7struct_E}@anchor{1e3}@anchor{cp/topics/types _CPPv2N6gccjit7struct_E}@anchor{1e4}@anchor{cp/topics/types gccjit struct_}@anchor{1e5}
@deffn {C++ Class} gccjit::struct_
@end deffn
A compound type analagous to a C @cite{struct}.
-@ref{19e,,gccjit;;struct_} is a subclass of @ref{12f,,gccjit;;type} (and thus
-of @ref{132,,gccjit;;object} in turn).
+@ref{1e2,,gccjit;;struct_} is a subclass of @ref{13f,,gccjit;;type} (and thus
+of @ref{142,,gccjit;;object} in turn).
@geindex gccjit;;field (C++ class)
-@anchor{cp/topics/types _CPPv2N6gccjit5fieldE}@anchor{1a0}@anchor{cp/topics/types gccjit field}@anchor{1a1}
+@anchor{cp/topics/types _CPPv4N6gccjit5fieldE}@anchor{1e6}@anchor{cp/topics/types _CPPv3N6gccjit5fieldE}@anchor{1e7}@anchor{cp/topics/types _CPPv2N6gccjit5fieldE}@anchor{1e8}@anchor{cp/topics/types gccjit field}@anchor{1e9}
@deffn {C++ Class} gccjit::field
@end deffn
-A field within a @ref{19e,,gccjit;;struct_}.
+A field within a @ref{1e2,,gccjit;;struct_}.
-@ref{1a0,,gccjit;;field} is a subclass of @ref{132,,gccjit;;object}.
+@ref{1e6,,gccjit;;field} is a subclass of @ref{142,,gccjit;;object}.
-You can model C @cite{struct} types by creating @ref{19e,,gccjit;;struct_} and
-@ref{1a0,,gccjit;;field} instances, in either order:
+You can model C @cite{struct} types by creating @ref{1e2,,gccjit;;struct_} and
+@ref{1e6,,gccjit;;field} instances, in either order:
@itemize *
@@ -12336,15 +12795,15 @@ node.set_fields (fields);
@c FIXME: the above API doesn't seem to exist yet
@geindex gccjit;;context;;new_field (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1a2}@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{1a3}
-@deffn {C++ Function} gccjit::@ref{1a0,,field} gccjit::context::new_field (gccjit::type type, const char *name, gccjit::location loc)
+@anchor{cp/topics/types _CPPv4N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1ea}@anchor{cp/topics/types _CPPv3N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1eb}@anchor{cp/topics/types _CPPv2N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{1ec}@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{1ed}
+@deffn {C++ Function} gccjit::@ref{1e6,,field} gccjit::@ref{13d,,context}::new_field (gccjit::type type, const char *name, gccjit::location loc)
Construct a new field, with the given type and name.
@end deffn
@geindex gccjit;;context;;new_struct_type (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1a4}@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{1a5}
-@deffn {C++ Function} gccjit::@ref{19e,,struct_} gccjit::context::new_struct_type (const std::string &name, std::vector<field> &fields, gccjit::location loc)
+@anchor{cp/topics/types _CPPv4N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1ee}@anchor{cp/topics/types _CPPv3N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1ef}@anchor{cp/topics/types _CPPv2N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE}@anchor{1f0}@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{1f1}
+@deffn {C++ Function} gccjit::@ref{1e2,,struct_} gccjit::@ref{13d,,context}::new_struct_type (const std::string &name, std::vector<field> &fields, gccjit::location loc)
@quotation
@@ -12353,8 +12812,8 @@ Construct a new struct type, with the given name and fields.
@end deffn
@geindex gccjit;;context;;new_opaque_struct (C++ function)
-@anchor{cp/topics/types _CPPv2N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1a6}@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{1a7}
-@deffn {C++ Function} gccjit::@ref{19e,,struct_} gccjit::context::new_opaque_struct (const std::string &name, gccjit::location loc)
+@anchor{cp/topics/types _CPPv4N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1f2}@anchor{cp/topics/types _CPPv3N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1f3}@anchor{cp/topics/types _CPPv2N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE}@anchor{1f4}@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{1f5}
+@deffn {C++ Function} gccjit::@ref{1e2,,struct_} gccjit::@ref{13d,,context}::new_opaque_struct (const std::string &name, gccjit::location loc)
Construct a new struct type, with the given name, but without
specifying the fields. The fields can be omitted (in which case the
@@ -12380,7 +12839,7 @@ size of the struct is not known), or later specified using
@c <http://www.gnu.org/licenses/>.
@node Expressions<2>,Creating and using functions<2>,Types<2>,Topic Reference<2>
-@anchor{cp/topics/expressions expressions}@anchor{1a8}@anchor{cp/topics/expressions doc}@anchor{1a9}
+@anchor{cp/topics/expressions doc}@anchor{1f6}@anchor{cp/topics/expressions expressions}@anchor{1f7}
@subsection Expressions
@@ -12392,17 +12851,17 @@ size of the struct is not known), or later specified using
@end menu
@node Rvalues<2>,Lvalues<2>,,Expressions<2>
-@anchor{cp/topics/expressions rvalues}@anchor{1aa}
+@anchor{cp/topics/expressions rvalues}@anchor{1f8}
@subsubsection Rvalues
@geindex gccjit;;rvalue (C++ class)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalueE}@anchor{136}@anchor{cp/topics/expressions gccjit rvalue}@anchor{1ab}
+@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalueE}@anchor{146}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalueE}@anchor{1f9}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalueE}@anchor{1fa}@anchor{cp/topics/expressions gccjit rvalue}@anchor{1fb}
@deffn {C++ Class} gccjit::rvalue
@end deffn
-A @ref{136,,gccjit;;rvalue} is an expression that can be computed. It is a
-subclass of @ref{132,,gccjit;;object}, and is a thin wrapper around
+A @ref{146,,gccjit;;rvalue} is an expression that can be computed. It is a
+subclass of @ref{142,,gccjit;;object}, and is a thin wrapper around
@ref{13,,gcc_jit_rvalue *} from the C API.
It can be simple, e.g.:
@@ -12448,8 +12907,8 @@ Every rvalue has an associated type, and the API will check to ensure
that types match up correctly (otherwise the context will emit an error).
@geindex gccjit;;rvalue;;get_type (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue8get_typeEv}@anchor{1ac}@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{1ad}
-@deffn {C++ Function} gccjit::@ref{12f,,type} gccjit::rvalue::get_type ()
+@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue8get_typeEv}@anchor{1fc}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue8get_typeEv}@anchor{1fd}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue8get_typeEv}@anchor{1fe}@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{1ff}
+@deffn {C++ Function} gccjit::@ref{13f,,type} gccjit::@ref{146,,rvalue}::get_type ()
Get the type of this rvalue.
@end deffn
@@ -12467,29 +12926,29 @@ Get the type of this rvalue.
@end menu
@node Simple expressions<2>,Vector expressions<2>,,Rvalues<2>
-@anchor{cp/topics/expressions simple-expressions}@anchor{1ae}
+@anchor{cp/topics/expressions simple-expressions}@anchor{200}
@subsubsection Simple expressions
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{14a}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{1af}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_rvalue (gccjit::type numeric_type, int value) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{15a}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{201}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEi}@anchor{202}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{203}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type numeric_type, int value) const
Given a numeric type (integer or floating point), build an rvalue for
the given constant @code{int} value.
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{1b0}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{1b1}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_rvalue (gccjit::type numeric_type, long value) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{204}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{205}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEl}@anchor{206}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{207}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type numeric_type, long value) const
Given a numeric type (integer or floating point), build an rvalue for
the given constant @code{long} value.
@end deffn
@geindex gccjit;;context;;zero (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{146}@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{1b2}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::zero (gccjit::type numeric_type) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{156}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{208}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context4zeroEN6gccjit4typeE}@anchor{209}@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{20a}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::zero (gccjit::type numeric_type) const
Given a numeric type (integer or floating point), get the rvalue for
zero. Essentially this is just a shortcut for:
@@ -12500,8 +12959,8 @@ ctxt.new_rvalue (numeric_type, 0)
@end deffn
@geindex gccjit;;context;;one (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context3oneEN6gccjit4typeE}@anchor{1b3}@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{1b4}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::one (gccjit::type numeric_type) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context3oneEN6gccjit4typeE}@anchor{20b}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context3oneEN6gccjit4typeE}@anchor{20c}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context3oneEN6gccjit4typeE}@anchor{20d}@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{20e}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::one (gccjit::type numeric_type) const
Given a numeric type (integer or floating point), get the rvalue for
one. Essentially this is just a shortcut for:
@@ -12512,36 +12971,36 @@ ctxt.new_rvalue (numeric_type, 1)
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{1b5}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{1b6}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_rvalue (gccjit::type numeric_type, double value) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{20f}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{210}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEd}@anchor{211}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{212}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type numeric_type, double value) const
Given a numeric type (integer or floating point), build an rvalue for
the given constant @code{double} value.
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{1b7}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{1b8}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_rvalue (gccjit::type pointer_type, void *value) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{213}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{214}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEPv}@anchor{215}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{216}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type pointer_type, void *value) const
Given a pointer type, build an rvalue for the given address.
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{1b9}@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{1ba}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_rvalue (const std::string &value) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{217}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{218}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueERKNSt6stringE}@anchor{219}@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{21a}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (const std::string &value) const
Generate an rvalue of type @code{GCC_JIT_TYPE_CONST_CHAR_PTR} for
the given string. This is akin to a string literal.
@end deffn
@node Vector expressions<2>,Unary Operations<2>,Simple expressions<2>,Rvalues<2>
-@anchor{cp/topics/expressions vector-expressions}@anchor{1bb}
+@anchor{cp/topics/expressions vector-expressions}@anchor{21b}
@subsubsection Vector expressions
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{1bc}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type std vector gccjit rvalue C}@anchor{1bd}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_rvalue (gccjit::type vector_type, std::vector<gccjit::rvalue> elements) const
+@anchor{cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{21c}@anchor{cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{21d}@anchor{cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE}@anchor{21e}@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type std vector gccjit rvalue C}@anchor{21f}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_rvalue (gccjit::type vector_type, std::vector<gccjit::rvalue> elements) const
Given a vector type, and a vector of scalar rvalue elements, generate a
vector rvalue.
@@ -12550,13 +13009,13 @@ The number of elements needs to match that of the vector type.
@end deffn
@node Unary Operations<2>,Binary Operations<2>,Vector expressions<2>,Rvalues<2>
-@anchor{cp/topics/expressions unary-operations}@anchor{1be}
+@anchor{cp/topics/expressions unary-operations}@anchor{220}
@subsubsection Unary Operations
@geindex gccjit;;context;;new_unary_op (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1bf}@anchor{cp/topics/expressions gccjit context new_unary_op__gcc_jit_unary_op gccjit type gccjit rvalue gccjit location}@anchor{1c0}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_unary_op (enum gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue rvalue, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{221}@anchor{cp/topics/expressions _CPPv3N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{222}@anchor{cp/topics/expressions _CPPv2N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{223}@anchor{cp/topics/expressions gccjit context new_unary_op__gcc_jit_unary_op gccjit type gccjit rvalue gccjit location}@anchor{224}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_unary_op (enum gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue rvalue, gccjit::location loc)
Build a unary operation out of an input rvalue.
@@ -12571,8 +13030,8 @@ There are shorter ways to spell the various specific kinds of unary
operation:
@geindex gccjit;;context;;new_minus (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1c1}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{1c2}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{225}@anchor{cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{226}@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{227}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{228}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
Negate an arithmetic value; for example:
@@ -12588,8 +13047,8 @@ builds the equivalent of this C expression:
@end deffn
@geindex new_bitwise_negate (C++ function)
-@anchor{cp/topics/expressions _CPPv218new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1c3}@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{1c4}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} new_bitwise_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv418new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{229}@anchor{cp/topics/expressions _CPPv318new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22a}@anchor{cp/topics/expressions _CPPv218new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22b}@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{22c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} new_bitwise_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
Bitwise negation of an integer value (one’s complement); for example:
@@ -12605,8 +13064,8 @@ builds the equivalent of this C expression:
@end deffn
@geindex new_logical_negate (C++ function)
-@anchor{cp/topics/expressions _CPPv218new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1c5}@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{1c6}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} new_logical_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv418new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22d}@anchor{cp/topics/expressions _CPPv318new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22e}@anchor{cp/topics/expressions _CPPv218new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22f}@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{230}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} new_logical_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
Logical negation of an arithmetic or pointer value; for example:
@@ -12624,8 +13083,8 @@ builds the equivalent of this C expression:
The most concise way to spell them is with overloaded operators:
@geindex operator- (C++ function)
-@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueE}@anchor{1c7}@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{1c8}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator@w{-} (gccjit::rvalue a)
+@anchor{cp/topics/expressions _CPPv4miN6gccjit6rvalueE}@anchor{231}@anchor{cp/topics/expressions _CPPv3miN6gccjit6rvalueE}@anchor{232}@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueE}@anchor{233}@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{234}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator@w{-} (gccjit::rvalue a)
@example
gccjit::rvalue negpi = -pi;
@@ -12633,8 +13092,8 @@ gccjit::rvalue negpi = -pi;
@end deffn
@geindex operator~ (C++ function)
-@anchor{cp/topics/expressions _CPPv2coN6gccjit6rvalueE}@anchor{1c9}@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{1ca}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator~ (gccjit::rvalue a)
+@anchor{cp/topics/expressions _CPPv4coN6gccjit6rvalueE}@anchor{235}@anchor{cp/topics/expressions _CPPv3coN6gccjit6rvalueE}@anchor{236}@anchor{cp/topics/expressions _CPPv2coN6gccjit6rvalueE}@anchor{237}@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{238}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator~ (gccjit::rvalue a)
@example
gccjit::rvalue mask = ~a;
@@ -12642,8 +13101,8 @@ gccjit::rvalue mask = ~a;
@end deffn
@geindex operator! (C++ function)
-@anchor{cp/topics/expressions _CPPv2ntN6gccjit6rvalueE}@anchor{1cb}@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{1cc}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator! (gccjit::rvalue a)
+@anchor{cp/topics/expressions _CPPv4ntN6gccjit6rvalueE}@anchor{239}@anchor{cp/topics/expressions _CPPv3ntN6gccjit6rvalueE}@anchor{23a}@anchor{cp/topics/expressions _CPPv2ntN6gccjit6rvalueE}@anchor{23b}@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{23c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator! (gccjit::rvalue a)
@example
gccjit::rvalue guard = !cond;
@@ -12651,13 +13110,13 @@ gccjit::rvalue guard = !cond;
@end deffn
@node Binary Operations<2>,Comparisons<2>,Unary Operations<2>,Rvalues<2>
-@anchor{cp/topics/expressions binary-operations}@anchor{1cd}
+@anchor{cp/topics/expressions binary-operations}@anchor{23d}
@subsubsection Binary Operations
@geindex gccjit;;context;;new_binary_op (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{135}@anchor{cp/topics/expressions gccjit context new_binary_op__gcc_jit_binary_op gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1ce}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_binary_op (enum gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{145}@anchor{cp/topics/expressions _CPPv3N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{23e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{23f}@anchor{cp/topics/expressions gccjit context new_binary_op__gcc_jit_binary_op gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{240}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_binary_op (enum gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
Build a binary operation out of two constituent rvalues.
@@ -12672,60 +13131,60 @@ There are shorter ways to spell the various specific kinds of binary
operation:
@geindex gccjit;;context;;new_plus (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1cf}@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1d0}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_plus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{241}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{242}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{243}@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{244}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_plus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_minus (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1d1}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1d2}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{245}@anchor{cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{246}@anchor{cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{247}@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{248}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_mult (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1d3}@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1d4}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_mult (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{249}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24b}@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{24c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_mult (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_divide (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1d5}@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1d6}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_divide (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24f}@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{250}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_divide (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_modulo (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1d7}@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1d8}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_modulo (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{251}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{252}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{253}@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{254}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_modulo (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_bitwise_and (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1d9}@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1da}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_bitwise_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{255}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{256}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{257}@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{258}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_bitwise_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_bitwise_xor (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1db}@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1dc}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_bitwise_xor (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{259}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25b}@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{25c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_bitwise_xor (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_bitwise_or (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1dd}@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1de}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_bitwise_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{25f}@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{260}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_bitwise_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_logical_and (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1df}@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1e0}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_logical_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{261}@anchor{cp/topics/expressions _CPPv3N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{262}@anchor{cp/topics/expressions _CPPv2N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{263}@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{264}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_logical_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_logical_or (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1e1}@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{1e2}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_logical_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{265}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{266}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{267}@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{268}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_logical_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
The most concise way to spell them is with overloaded operators:
@geindex operator+ (C++ function)
-@anchor{cp/topics/expressions _CPPv2plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1e3}@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{1e4}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator+ (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{269}@anchor{cp/topics/expressions _CPPv3plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26a}@anchor{cp/topics/expressions _CPPv2plN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26b}@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{26c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator+ (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue sum = a + b;
@@ -12733,8 +13192,8 @@ gccjit::rvalue sum = a + b;
@end deffn
@geindex operator- (C++ function)
-@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1e5}@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{1e6}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator@w{-} (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26d}@anchor{cp/topics/expressions _CPPv3miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26e}@anchor{cp/topics/expressions _CPPv2miN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{26f}@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{270}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator@w{-} (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue diff = a - b;
@@ -12742,8 +13201,8 @@ gccjit::rvalue diff = a - b;
@end deffn
@geindex operator* (C++ function)
-@anchor{cp/topics/expressions _CPPv2mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1e7}@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{1e8}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator* (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{271}@anchor{cp/topics/expressions _CPPv3mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{272}@anchor{cp/topics/expressions _CPPv2mlN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{273}@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{274}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator* (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue prod = a * b;
@@ -12751,8 +13210,8 @@ gccjit::rvalue prod = a * b;
@end deffn
@geindex operator/ (C++ function)
-@anchor{cp/topics/expressions _CPPv2dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1e9}@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{1ea}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator/ (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{275}@anchor{cp/topics/expressions _CPPv3dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{276}@anchor{cp/topics/expressions _CPPv2dvN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{277}@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{278}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator/ (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue result = a / b;
@@ -12760,8 +13219,8 @@ gccjit::rvalue result = a / b;
@end deffn
@geindex operator% (C++ function)
-@anchor{cp/topics/expressions _CPPv2rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1eb}@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{1ec}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator% (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{279}@anchor{cp/topics/expressions _CPPv3rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27a}@anchor{cp/topics/expressions _CPPv2rmN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27b}@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{27c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator% (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue mod = a % b;
@@ -12769,8 +13228,8 @@ gccjit::rvalue mod = a % b;
@end deffn
@geindex operator& (C++ function)
-@anchor{cp/topics/expressions _CPPv2anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1ed}@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{1ee}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator& (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27d}@anchor{cp/topics/expressions _CPPv3anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27e}@anchor{cp/topics/expressions _CPPv2anN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{27f}@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{280}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator& (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue x = a & b;
@@ -12778,8 +13237,8 @@ gccjit::rvalue x = a & b;
@end deffn
@geindex operator^ (C++ function)
-@anchor{cp/topics/expressions _CPPv2eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1ef}@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{1f0}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator^ (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{281}@anchor{cp/topics/expressions _CPPv3eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{282}@anchor{cp/topics/expressions _CPPv2eoN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{283}@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{284}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator^ (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue x = a ^ b;
@@ -12787,8 +13246,8 @@ gccjit::rvalue x = a ^ b;
@end deffn
@geindex operator| (C++ function)
-@anchor{cp/topics/expressions _CPPv2orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1f1}@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{1f2}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator| (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{285}@anchor{cp/topics/expressions _CPPv3orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{286}@anchor{cp/topics/expressions _CPPv2orN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{287}@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{288}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator| (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue x = a | b;
@@ -12796,8 +13255,8 @@ gccjit::rvalue x = a | b;
@end deffn
@geindex operator&& (C++ function)
-@anchor{cp/topics/expressions _CPPv2aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1f3}@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{1f4}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator&& (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{289}@anchor{cp/topics/expressions _CPPv3aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28a}@anchor{cp/topics/expressions _CPPv2aaN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28b}@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{28c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator&& (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = a && b;
@@ -12805,8 +13264,8 @@ gccjit::rvalue cond = a && b;
@end deffn
@geindex operator|| (C++ function)
-@anchor{cp/topics/expressions _CPPv2ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{1f5}@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{1f6}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator|| (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28d}@anchor{cp/topics/expressions _CPPv3ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28e}@anchor{cp/topics/expressions _CPPv2ooN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{28f}@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{290}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator|| (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = a || b;
@@ -12824,13 +13283,13 @@ gccjit::rvalue discriminant = (b * b) - (four * a * c);
@end quotation
@node Comparisons<2>,Function calls<2>,Binary Operations<2>,Rvalues<2>
-@anchor{cp/topics/expressions comparisons}@anchor{1f7}
+@anchor{cp/topics/expressions comparisons}@anchor{291}
@subsubsection Comparisons
@geindex gccjit;;context;;new_comparison (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{147}@anchor{cp/topics/expressions gccjit context new_comparison__gcc_jit_comparison gccjit rvalue gccjit rvalue gccjit location}@anchor{1f8}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_comparison (enum gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{157}@anchor{cp/topics/expressions _CPPv3N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{292}@anchor{cp/topics/expressions _CPPv2N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{293}@anchor{cp/topics/expressions gccjit context new_comparison__gcc_jit_comparison gccjit rvalue gccjit rvalue gccjit location}@anchor{294}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_comparison (enum gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
Build a boolean rvalue out of the comparison of two other rvalues.
@@ -12845,40 +13304,40 @@ There are shorter ways to spell the various specific kinds of binary
operation:
@geindex gccjit;;context;;new_eq (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1f9}@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{1fa}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_eq (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{295}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{296}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{297}@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{298}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_eq (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_ne (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1fb}@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{1fc}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_ne (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{299}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29a}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29b}@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{29c}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_ne (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_lt (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1fd}@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{1fe}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_lt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29d}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29e}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{29f}@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{2a0}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_lt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_le (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{1ff}@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{200}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_le (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a1}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a2}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a3}@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{2a4}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_le (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_gt (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{201}@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{202}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_gt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a5}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a6}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a7}@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{2a8}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_gt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_ge (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{203}@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{204}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_ge (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2a9}@anchor{cp/topics/expressions _CPPv3N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2aa}@anchor{cp/topics/expressions _CPPv2N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2ab}@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{2ac}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_ge (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
The most concise way to spell them is with overloaded operators:
@geindex operator== (C++ function)
-@anchor{cp/topics/expressions _CPPv2eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{205}@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{206}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator== (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ad}@anchor{cp/topics/expressions _CPPv3eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ae}@anchor{cp/topics/expressions _CPPv2eqN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2af}@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{2b0}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator== (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = (a == ctxt.zero (t_int));
@@ -12886,8 +13345,8 @@ gccjit::rvalue cond = (a == ctxt.zero (t_int));
@end deffn
@geindex operator!= (C++ function)
-@anchor{cp/topics/expressions _CPPv2neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{207}@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{208}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator!= (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b1}@anchor{cp/topics/expressions _CPPv3neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b2}@anchor{cp/topics/expressions _CPPv2neN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b3}@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{2b4}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator!= (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = (i != j);
@@ -12895,8 +13354,8 @@ gccjit::rvalue cond = (i != j);
@end deffn
@geindex operator< (C++ function)
-@anchor{cp/topics/expressions _CPPv2ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{209}@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{20a}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator< (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b5}@anchor{cp/topics/expressions _CPPv3ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b6}@anchor{cp/topics/expressions _CPPv2ltN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b7}@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{2b8}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator< (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = i < n;
@@ -12904,8 +13363,8 @@ gccjit::rvalue cond = i < n;
@end deffn
@geindex operator<= (C++ function)
-@anchor{cp/topics/expressions _CPPv2leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{20b}@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{20c}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator<= (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2b9}@anchor{cp/topics/expressions _CPPv3leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2ba}@anchor{cp/topics/expressions _CPPv2leN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bb}@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{2bc}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator<= (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = i <= n;
@@ -12913,8 +13372,8 @@ gccjit::rvalue cond = i <= n;
@end deffn
@geindex operator> (C++ function)
-@anchor{cp/topics/expressions _CPPv2gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{20d}@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{20e}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator> (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bd}@anchor{cp/topics/expressions _CPPv3gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2be}@anchor{cp/topics/expressions _CPPv2gtN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2bf}@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{2c0}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator> (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = (ch > limit);
@@ -12922,8 +13381,8 @@ gccjit::rvalue cond = (ch > limit);
@end deffn
@geindex operator>= (C++ function)
-@anchor{cp/topics/expressions _CPPv2geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{20f}@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{210}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} operator>= (gccjit::rvalue a, gccjit::rvalue b)
+@anchor{cp/topics/expressions _CPPv4geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c1}@anchor{cp/topics/expressions _CPPv3geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c2}@anchor{cp/topics/expressions _CPPv2geN6gccjit6rvalueEN6gccjit6rvalueE}@anchor{2c3}@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{2c4}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} operator>= (gccjit::rvalue a, gccjit::rvalue b)
@example
gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100));
@@ -12933,12 +13392,12 @@ gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100));
@c TODO: beyond this point
@node Function calls<2>,Function pointers<3>,Comparisons<2>,Rvalues<2>
-@anchor{cp/topics/expressions function-calls}@anchor{211}
+@anchor{cp/topics/expressions function-calls}@anchor{2c5}
@subsubsection Function calls
@geindex gcc_jit_context_new_call (C++ function)
-@anchor{cp/topics/expressions _CPPv224gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{212}@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{213}
+@anchor{cp/topics/expressions _CPPv424gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2c6}@anchor{cp/topics/expressions _CPPv324gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2c7}@anchor{cp/topics/expressions _CPPv224gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue}@anchor{2c8}@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{2c9}
@deffn {C++ Function} gcc_jit_rvalue *gcc_jit_context_new_call (gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_function *func, int numargs, gcc_jit_rvalue **args)
Given a function and the given table of argument rvalues, construct a
@@ -12947,14 +13406,14 @@ call to the function, with the result as an rvalue.
@cartouche
@quotation Note
@code{gccjit::context::new_call()} merely builds a
-@ref{136,,gccjit;;rvalue} i.e. an expression that can be evaluated,
+@ref{146,,gccjit;;rvalue} i.e. an expression that can be evaluated,
perhaps as part of a more complicated expression.
The call @emph{won’t} happen unless you add a statement to a function
that evaluates the expression.
For example, if you want to call a function and discard the result
(or to call a function with @code{void} return type), use
-@ref{214,,gccjit;;block;;add_eval()}:
+@ref{2ca,,gccjit;;block;;add_eval()}:
@example
/* Add "(void)printf (arg0, arg1);". */
@@ -12965,26 +13424,26 @@ block.add_eval (ctxt.new_call (printf_func, arg0, arg1));
@end deffn
@node Function pointers<3>,Type-coercion<2>,Function calls<2>,Rvalues<2>
-@anchor{cp/topics/expressions function-pointers}@anchor{215}
+@anchor{cp/topics/expressions function-pointers}@anchor{2cb}
@subsubsection Function pointers
@geindex gccjit;;function;;get_address (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{216}@anchor{cp/topics/expressions gccjit function get_address__gccjit location}@anchor{217}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::function::get_address (gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{2cc}@anchor{cp/topics/expressions _CPPv3N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{2cd}@anchor{cp/topics/expressions _CPPv2N6gccjit8function11get_addressEN6gccjit8locationE}@anchor{2ce}@anchor{cp/topics/expressions gccjit function get_address__gccjit location}@anchor{2cf}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{154,,function}::get_address (gccjit::location loc)
Get the address of a function as an rvalue, of function pointer
type.
@end deffn
@node Type-coercion<2>,,Function pointers<3>,Rvalues<2>
-@anchor{cp/topics/expressions type-coercion}@anchor{218}
+@anchor{cp/topics/expressions type-coercion}@anchor{2d0}
@subsubsection Type-coercion
@geindex gccjit;;context;;new_cast (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{219}@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{21a}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::context::new_cast (gccjit::rvalue rvalue, gccjit::type type, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{2d1}@anchor{cp/topics/expressions _CPPv3N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{2d2}@anchor{cp/topics/expressions _CPPv2N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE}@anchor{2d3}@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{2d4}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{13d,,context}::new_cast (gccjit::rvalue rvalue, gccjit::type type, gccjit::location loc)
Given an rvalue of T, construct another rvalue of another type.
@@ -13008,25 +13467,25 @@ P* <-> Q*, for pointer types P and Q
@end deffn
@node Lvalues<2>,Working with pointers structs and unions<2>,Rvalues<2>,Expressions<2>
-@anchor{cp/topics/expressions lvalues}@anchor{21b}
+@anchor{cp/topics/expressions lvalues}@anchor{2d5}
@subsubsection Lvalues
@geindex gccjit;;lvalue (C++ class)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalueE}@anchor{13f}@anchor{cp/topics/expressions gccjit lvalue}@anchor{21c}
+@anchor{cp/topics/expressions _CPPv4N6gccjit6lvalueE}@anchor{14f}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalueE}@anchor{2d6}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalueE}@anchor{2d7}@anchor{cp/topics/expressions gccjit lvalue}@anchor{2d8}
@deffn {C++ Class} gccjit::lvalue
@end deffn
An lvalue is something that can of the @emph{left}-hand side of an assignment:
a storage area (such as a variable). It is a subclass of
-@ref{136,,gccjit;;rvalue}, where the rvalue is computed by reading from the
+@ref{146,,gccjit;;rvalue}, where the rvalue is computed by reading from the
storage area.
It iss a thin wrapper around @ref{24,,gcc_jit_lvalue *} from the C API.
@geindex gccjit;;lvalue;;get_address (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{21d}@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{21e}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::lvalue::get_address (gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{2d9}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{2da}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue11get_addressEN6gccjit8locationE}@anchor{2db}@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{2dc}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{14f,,lvalue}::get_address (gccjit::location loc)
Take the address of an lvalue; analogous to:
@@ -13045,13 +13504,13 @@ Parameter “loc” is optional.
@end menu
@node Global variables<2>,,,Lvalues<2>
-@anchor{cp/topics/expressions global-variables}@anchor{21f}
+@anchor{cp/topics/expressions global-variables}@anchor{2dd}
@subsubsection Global variables
@geindex gccjit;;context;;new_global (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{220}@anchor{cp/topics/expressions gccjit context new_global__gcc_jit_global_kind gccjit type cCP gccjit location}@anchor{221}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::context::new_global (enum gcc_jit_global_kind, gccjit::type type, const char *name, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{2de}@anchor{cp/topics/expressions _CPPv3N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{2df}@anchor{cp/topics/expressions _CPPv2N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE}@anchor{2e0}@anchor{cp/topics/expressions gccjit context new_global__gcc_jit_global_kind gccjit type cCP gccjit location}@anchor{2e1}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{13d,,context}::new_global (enum gcc_jit_global_kind, gccjit::type type, const char *name, gccjit::location loc)
Add a new global variable of the given type and name to the context.
@@ -13060,13 +13519,13 @@ the C API; the “kind” parameter has the same meaning as there.
@end deffn
@node Working with pointers structs and unions<2>,,Lvalues<2>,Expressions<2>
-@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{222}
+@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{2e2}
@subsubsection Working with pointers, structs and unions
@geindex gccjit;;rvalue;;dereference (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{223}@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{224}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::rvalue::dereference (gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{2e3}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{2e4}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue11dereferenceEN6gccjit8locationE}@anchor{2e5}@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{2e6}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{146,,rvalue}::dereference (gccjit::location loc)
Given an rvalue of pointer type @code{T *}, dereferencing the pointer,
getting an lvalue of type @code{T}. Analogous to:
@@ -13084,8 +13543,8 @@ If you don’t need to specify the location, this can also be expressed using
an overloaded operator:
@geindex gccjit;;rvalue;;operator* (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6rvaluemlEv}@anchor{225}@anchor{cp/topics/expressions gccjit rvalue mul-operator}@anchor{226}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::rvalue::operator* ()
+@anchor{cp/topics/expressions _CPPv4N6gccjit6rvaluemlEv}@anchor{2e7}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvaluemlEv}@anchor{2e8}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvaluemlEv}@anchor{2e9}@anchor{cp/topics/expressions gccjit rvalue mul-operator}@anchor{2ea}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{146,,rvalue}::operator* ()
@example
gccjit::lvalue content = *ptr;
@@ -13095,8 +13554,8 @@ gccjit::lvalue content = *ptr;
Field access is provided separately for both lvalues and rvalues:
@geindex gccjit;;lvalue;;access_field (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{227}@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{228}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::lvalue::access_field (gccjit::field field, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2eb}@anchor{cp/topics/expressions _CPPv3N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2ec}@anchor{cp/topics/expressions _CPPv2N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2ed}@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{2ee}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{14f,,lvalue}::access_field (gccjit::field field, gccjit::location loc)
Given an lvalue of struct or union type, access the given field,
getting an lvalue of the field’s type. Analogous to:
@@ -13109,8 +13568,8 @@ in C.
@end deffn
@geindex gccjit;;rvalue;;access_field (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{229}@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{22a}
-@deffn {C++ Function} gccjit::@ref{136,,rvalue} gccjit::rvalue::access_field (gccjit::field field, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2ef}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f0}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f1}@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{2f2}
+@deffn {C++ Function} gccjit::@ref{146,,rvalue} gccjit::@ref{146,,rvalue}::access_field (gccjit::field field, gccjit::location loc)
Given an rvalue of struct or union type, access the given field
as an rvalue. Analogous to:
@@ -13123,8 +13582,8 @@ in C.
@end deffn
@geindex gccjit;;rvalue;;dereference_field (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{22b}@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{22c}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::rvalue::dereference_field (gccjit::field field, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f3}@anchor{cp/topics/expressions _CPPv3N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f4}@anchor{cp/topics/expressions _CPPv2N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE}@anchor{2f5}@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{2f6}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{146,,rvalue}::dereference_field (gccjit::field field, gccjit::location loc)
Given an rvalue of pointer type @code{T *} where T is of struct or union
type, access the given field as an lvalue. Analogous to:
@@ -13137,8 +13596,8 @@ in C, itself equivalent to @code{(*EXPR).FIELD}.
@end deffn
@geindex gccjit;;context;;new_array_access (C++ function)
-@anchor{cp/topics/expressions _CPPv2N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{22d}@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{22e}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::context::new_array_access (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location loc)
+@anchor{cp/topics/expressions _CPPv4N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2f7}@anchor{cp/topics/expressions _CPPv3N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2f8}@anchor{cp/topics/expressions _CPPv2N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2f9}@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{2fa}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{13d,,context}::new_array_access (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location loc)
Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at
the given index, using standard C array indexing rules i.e. each
@@ -13154,7 +13613,7 @@ in C (or, indeed, to @code{PTR + INDEX}).
Parameter “loc” is optional.
@end deffn
-For array accesses where you don’t need to specify a @ref{153,,gccjit;;location},
+For array accesses where you don’t need to specify a @ref{163,,gccjit;;location},
two overloaded operators are available:
@quotation
@@ -13190,7 +13649,7 @@ gccjit::lvalue element = array[0];
@c <http://www.gnu.org/licenses/>.
@node Creating and using functions<2>,Source Locations<2>,Expressions<2>,Topic Reference<2>
-@anchor{cp/topics/functions doc}@anchor{22f}@anchor{cp/topics/functions creating-and-using-functions}@anchor{230}
+@anchor{cp/topics/functions doc}@anchor{2fb}@anchor{cp/topics/functions creating-and-using-functions}@anchor{2fc}
@subsection Creating and using functions
@@ -13203,36 +13662,36 @@ gccjit::lvalue element = array[0];
@end menu
@node Params<2>,Functions<2>,,Creating and using functions<2>
-@anchor{cp/topics/functions params}@anchor{231}
+@anchor{cp/topics/functions params}@anchor{2fd}
@subsubsection Params
@geindex gccjit;;param (C++ class)
-@anchor{cp/topics/functions _CPPv2N6gccjit5paramE}@anchor{140}@anchor{cp/topics/functions gccjit param}@anchor{232}
+@anchor{cp/topics/functions _CPPv4N6gccjit5paramE}@anchor{150}@anchor{cp/topics/functions _CPPv3N6gccjit5paramE}@anchor{2fe}@anchor{cp/topics/functions _CPPv2N6gccjit5paramE}@anchor{2ff}@anchor{cp/topics/functions gccjit param}@anchor{300}
@deffn {C++ Class} gccjit::param
A @cite{gccjit::param} represents a parameter to a function.
@end deffn
@geindex gccjit;;context;;new_param (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{134}@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{233}
-@deffn {C++ Function} gccjit::@ref{140,,param} gccjit::context::new_param (gccjit::type type, const char *name, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{144}@anchor{cp/topics/functions _CPPv3N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{301}@anchor{cp/topics/functions _CPPv2N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{302}@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{303}
+@deffn {C++ Function} gccjit::@ref{150,,param} gccjit::@ref{13d,,context}::new_param (gccjit::type type, const char *name, gccjit::location loc)
In preparation for creating a function, create a new parameter of the
given type and name.
@end deffn
-@ref{140,,gccjit;;param} is a subclass of @ref{13f,,gccjit;;lvalue} (and thus
-of @ref{136,,gccjit;;rvalue} and @ref{132,,gccjit;;object}). It is a thin
+@ref{150,,gccjit;;param} is a subclass of @ref{14f,,gccjit;;lvalue} (and thus
+of @ref{146,,gccjit;;rvalue} and @ref{142,,gccjit;;object}). It is a thin
wrapper around the C API’s @ref{25,,gcc_jit_param *}.
@node Functions<2>,Blocks<2>,Params<2>,Creating and using functions<2>
-@anchor{cp/topics/functions functions}@anchor{234}
+@anchor{cp/topics/functions functions}@anchor{304}
@subsubsection Functions
@geindex gccjit;;function (C++ class)
-@anchor{cp/topics/functions _CPPv2N6gccjit8functionE}@anchor{144}@anchor{cp/topics/functions gccjit function}@anchor{235}
+@anchor{cp/topics/functions _CPPv4N6gccjit8functionE}@anchor{154}@anchor{cp/topics/functions _CPPv3N6gccjit8functionE}@anchor{305}@anchor{cp/topics/functions _CPPv2N6gccjit8functionE}@anchor{306}@anchor{cp/topics/functions gccjit function}@anchor{307}
@deffn {C++ Class} gccjit::function
A @cite{gccjit::function} represents a function - either one that we’re
@@ -13240,8 +13699,8 @@ creating ourselves, or one that we’re referencing.
@end deffn
@geindex gccjit;;context;;new_function (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{236}@anchor{cp/topics/functions gccjit context new_function__gcc_jit_function_kind gccjit type cCP std vector param R i gccjit location}@anchor{237}
-@deffn {C++ Function} gccjit::@ref{144,,function} gccjit::context::new_function (enum gcc_jit_function_kind, gccjit::type return_type, const char *name, std::vector<param> &params, int is_variadic, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{308}@anchor{cp/topics/functions _CPPv3N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{309}@anchor{cp/topics/functions _CPPv2N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE}@anchor{30a}@anchor{cp/topics/functions gccjit context new_function__gcc_jit_function_kind gccjit type cCP std vector param R i gccjit location}@anchor{30b}
+@deffn {C++ Function} gccjit::@ref{154,,function} gccjit::@ref{13d,,context}::new_function (enum gcc_jit_function_kind, gccjit::type return_type, const char *name, std::vector<param> &params, int is_variadic, gccjit::location loc)
Create a gcc_jit_function with the given name and parameters.
@@ -13251,49 +13710,49 @@ This is a wrapper around the C API’s @ref{11,,gcc_jit_context_new_function()}.
@end deffn
@geindex gccjit;;context;;get_builtin_function (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit7context20get_builtin_functionEPKc}@anchor{238}@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{239}
-@deffn {C++ Function} gccjit::@ref{144,,function} gccjit::context::get_builtin_function (const char *name)
+@anchor{cp/topics/functions _CPPv4N6gccjit7context20get_builtin_functionEPKc}@anchor{30c}@anchor{cp/topics/functions _CPPv3N6gccjit7context20get_builtin_functionEPKc}@anchor{30d}@anchor{cp/topics/functions _CPPv2N6gccjit7context20get_builtin_functionEPKc}@anchor{30e}@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{30f}
+@deffn {C++ Function} gccjit::@ref{154,,function} gccjit::@ref{13d,,context}::get_builtin_function (const char *name)
This is a wrapper around the C API’s
@ref{e1,,gcc_jit_context_get_builtin_function()}.
@end deffn
@geindex gccjit;;function;;get_param (C++ function)
-@anchor{cp/topics/functions _CPPv2NK6gccjit8function9get_paramEi}@anchor{23a}@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{23b}
-@deffn {C++ Function} gccjit::@ref{140,,param} gccjit::function::get_param (int index) const
+@anchor{cp/topics/functions _CPPv4NK6gccjit8function9get_paramEi}@anchor{310}@anchor{cp/topics/functions _CPPv3NK6gccjit8function9get_paramEi}@anchor{311}@anchor{cp/topics/functions _CPPv2NK6gccjit8function9get_paramEi}@anchor{312}@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{313}
+@deffn {C++ Function} gccjit::@ref{150,,param} gccjit::@ref{154,,function}::get_param (int index) const
Get the param of the given index (0-based).
@end deffn
@geindex gccjit;;function;;dump_to_dot (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit8function11dump_to_dotEPKc}@anchor{14c}@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{23c}
-@deffn {C++ Function} void gccjit::function::dump_to_dot (const char *path)
+@anchor{cp/topics/functions _CPPv4N6gccjit8function11dump_to_dotEPKc}@anchor{15c}@anchor{cp/topics/functions _CPPv3N6gccjit8function11dump_to_dotEPKc}@anchor{314}@anchor{cp/topics/functions _CPPv2N6gccjit8function11dump_to_dotEPKc}@anchor{315}@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{316}
+@deffn {C++ Function} void gccjit::@ref{154,,function}::dump_to_dot (const char *path)
Emit the function in graphviz format to the given path.
@end deffn
@geindex gccjit;;function;;new_local (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{141}@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{23d}
-@deffn {C++ Function} gccjit::@ref{13f,,lvalue} gccjit::function::new_local (gccjit::type type, const char *name, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{151}@anchor{cp/topics/functions _CPPv3N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{317}@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE}@anchor{318}@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{319}
+@deffn {C++ Function} gccjit::@ref{14f,,lvalue} gccjit::@ref{154,,function}::new_local (gccjit::type type, const char *name, gccjit::location loc)
Create a new local variable within the function, of the given type and
name.
@end deffn
@node Blocks<2>,Statements<2>,Functions<2>,Creating and using functions<2>
-@anchor{cp/topics/functions blocks}@anchor{23e}
+@anchor{cp/topics/functions blocks}@anchor{31a}
@subsubsection Blocks
@geindex gccjit;;block (C++ class)
-@anchor{cp/topics/functions _CPPv2N6gccjit5blockE}@anchor{143}@anchor{cp/topics/functions gccjit block}@anchor{23f}
+@anchor{cp/topics/functions _CPPv4N6gccjit5blockE}@anchor{153}@anchor{cp/topics/functions _CPPv3N6gccjit5blockE}@anchor{31b}@anchor{cp/topics/functions _CPPv2N6gccjit5blockE}@anchor{31c}@anchor{cp/topics/functions gccjit block}@anchor{31d}
@deffn {C++ Class} gccjit::block
A @cite{gccjit::block} represents a basic block within a function i.e. a
sequence of statements with a single entry point and a single exit
point.
-@ref{143,,gccjit;;block} is a subclass of @ref{132,,gccjit;;object}.
+@ref{153,,gccjit;;block} is a subclass of @ref{142,,gccjit;;object}.
The first basic block that you create within a function will
be the entrypoint.
@@ -13307,8 +13766,8 @@ one function.
@end deffn
@geindex gccjit;;function;;new_block (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_blockEPKc}@anchor{240}@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{241}
-@deffn {C++ Function} gccjit::@ref{143,,block} gccjit::function::new_block (const char *name)
+@anchor{cp/topics/functions _CPPv4N6gccjit8function9new_blockEPKc}@anchor{31e}@anchor{cp/topics/functions _CPPv3N6gccjit8function9new_blockEPKc}@anchor{31f}@anchor{cp/topics/functions _CPPv2N6gccjit8function9new_blockEPKc}@anchor{320}@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{321}
+@deffn {C++ Function} gccjit::@ref{153,,block} gccjit::@ref{154,,function}::new_block (const char *name)
Create a basic block of the given name. The name may be NULL, but
providing meaningful names is often helpful when debugging: it may
@@ -13317,13 +13776,13 @@ messages.
@end deffn
@node Statements<2>,,Blocks<2>,Creating and using functions<2>
-@anchor{cp/topics/functions statements}@anchor{242}
+@anchor{cp/topics/functions statements}@anchor{322}
@subsubsection Statements
@geindex gccjit;;block;;add_eval (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{214}@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{243}
-@deffn {C++ Function} void gccjit::block::add_eval (gccjit::rvalue rvalue, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{2ca}@anchor{cp/topics/functions _CPPv3N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{323}@anchor{cp/topics/functions _CPPv2N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE}@anchor{324}@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{325}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::add_eval (gccjit::rvalue rvalue, gccjit::location loc)
Add evaluation of an rvalue, discarding the result
(e.g. a function call that “returns” void).
@@ -13336,8 +13795,8 @@ This is equivalent to this C code:
@end deffn
@geindex gccjit;;block;;add_assignment (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{145}@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{244}
-@deffn {C++ Function} void gccjit::block::add_assignment (gccjit::lvalue lvalue, gccjit::rvalue rvalue, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{155}@anchor{cp/topics/functions _CPPv3N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{326}@anchor{cp/topics/functions _CPPv2N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE}@anchor{327}@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{328}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::add_assignment (gccjit::lvalue lvalue, gccjit::rvalue rvalue, gccjit::location loc)
Add evaluation of an rvalue, assigning the result to the given
lvalue.
@@ -13350,8 +13809,8 @@ lvalue = rvalue;
@end deffn
@geindex gccjit;;block;;add_assignment_op (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{149}@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue gcc_jit_binary_op gccjit rvalue gccjit location}@anchor{245}
-@deffn {C++ Function} void gccjit::block::add_assignment_op (gccjit::lvalue lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{159}@anchor{cp/topics/functions _CPPv3N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{329}@anchor{cp/topics/functions _CPPv2N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE}@anchor{32a}@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue gcc_jit_binary_op gccjit rvalue gccjit location}@anchor{32b}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::add_assignment_op (gccjit::lvalue lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue, gccjit::location loc)
Add evaluation of an rvalue, using the result to modify an
lvalue.
@@ -13376,8 +13835,8 @@ loop_body.add_assignment_op (
@end deffn
@geindex gccjit;;block;;add_comment (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{155}@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{246}
-@deffn {C++ Function} void gccjit::block::add_comment (const char *text, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{165}@anchor{cp/topics/functions _CPPv3N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{32c}@anchor{cp/topics/functions _CPPv2N6gccjit5block11add_commentEPKcN6gccjit8locationE}@anchor{32d}@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{32e}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::add_comment (const char *text, gccjit::location loc)
Add a no-op textual comment to the internal representation of the
code. It will be optimized away, but will be visible in the dumps
@@ -13390,8 +13849,8 @@ Parameter “loc” is optional.
@end deffn
@geindex gccjit;;block;;end_with_conditional (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{148}@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{247}
-@deffn {C++ Function} void gccjit::block::end_with_conditional (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block on_false, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{158}@anchor{cp/topics/functions _CPPv3N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{32f}@anchor{cp/topics/functions _CPPv2N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE}@anchor{330}@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{331}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_conditional (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block on_false, gccjit::location loc)
Terminate a block by adding evaluation of an rvalue, branching on the
result to the appropriate successor block.
@@ -13409,8 +13868,8 @@ block, boolval, on_true, and on_false must be non-NULL.
@end deffn
@geindex gccjit;;block;;end_with_jump (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{248}@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{249}
-@deffn {C++ Function} void gccjit::block::end_with_jump (gccjit::block target, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{332}@anchor{cp/topics/functions _CPPv3N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{333}@anchor{cp/topics/functions _CPPv2N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE}@anchor{334}@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{335}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_jump (gccjit::block target, gccjit::location loc)
Terminate a block by adding a jump to the given target block.
@@ -13422,8 +13881,8 @@ goto target;
@end deffn
@geindex gccjit;;block;;end_with_return (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{24a}@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{24b}
-@deffn {C++ Function} void gccjit::block::end_with_return (gccjit::rvalue rvalue, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{336}@anchor{cp/topics/functions _CPPv3N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{337}@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE}@anchor{338}@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{339}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_return (gccjit::rvalue rvalue, gccjit::location loc)
Terminate a block.
@@ -13452,8 +13911,8 @@ return;
@end deffn
@geindex gccjit;;block;;end_with_switch (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{24c}@anchor{cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location}@anchor{24d}
-@deffn {C++ Function} void gccjit::block::end_with_switch (gccjit::rvalue expr, gccjit::block default_block, std::vector<gccjit::case_> cases, gccjit::location loc)
+@anchor{cp/topics/functions _CPPv4N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{33a}@anchor{cp/topics/functions _CPPv3N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{33b}@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE}@anchor{33c}@anchor{cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location}@anchor{33d}
+@deffn {C++ Function} void gccjit::@ref{153,,block}::end_with_switch (gccjit::rvalue expr, gccjit::block default_block, std::vector<gccjit::case_> cases, gccjit::location loc)
Terminate a block by adding evalation of an rvalue, then performing
a multiway branch.
@@ -13493,10 +13952,10 @@ The API entrypoints relating to switch statements and cases:
@itemize *
@item
-@code{gccjit::block::end_with_switch()}
+@ref{33a,,gccjit;;block;;end_with_switch()}
@item
-@ref{24e,,gccjit;;context;;new_case()}
+@code{gccjit::context::new_case()}
@end itemize
@end quotation
@@ -13507,32 +13966,15 @@ using
#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
@end example
-@geindex gccjit;;block;;end_with_switch;;gccjit;;case_ (C++ class)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_switch6gccjit5case_E}@anchor{24f}@anchor{cp/topics/functions gccjit block end_with_switch gccjit case_}@anchor{250}
-@deffn {C++ Class} gccjit::case_
-@end deffn
-
A @cite{gccjit::case_} represents a case within a switch statement, and
-is created within a particular @code{gccjit::context} using
-@ref{24e,,gccjit;;context;;new_case()}. It is a subclass of
-@code{gccjit::object}.
+is created within a particular @ref{13d,,gccjit;;context} using
+@code{gccjit::context::new_case()}. It is a subclass of
+@ref{142,,gccjit;;object}.
Each case expresses a multivalued range of integer values. You
can express single-valued cases by passing in the same value for
both @cite{min_value} and @cite{max_value}.
-@geindex gccjit;;block;;end_with_switch;;gccjit;;context;;new_case (C++ function)
-@anchor{cp/topics/functions _CPPv2N6gccjit5block15end_with_switch6gccjit7context8new_caseEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit5blockE}@anchor{24e}@anchor{cp/topics/functions gccjit block end_with_switch gccjit context new_case__gccjit rvalue gccjit rvalue gccjit block}@anchor{251}
-@deffn {C++ Function} gccjit::@ref{24f,,case_} *gccjit::context::new_case (gccjit::rvalue min_value, gccjit::rvalue max_value, gccjit::block dest_block)
-
-Create a new gccjit::case for use in a switch statement.
-@cite{min_value} and @cite{max_value} must be constants of an integer type,
-which must match that of the expression of the switch statement.
-
-@cite{dest_block} must be within the same function as the switch
-statement.
-@end deffn
-
Here’s an example of creating a switch statement:
@quotation
@@ -13630,12 +14072,12 @@ create_code (gcc_jit_context *c_ctxt, void *user_data)
@c <http://www.gnu.org/licenses/>.
@node Source Locations<2>,Compiling a context<2>,Creating and using functions<2>,Topic Reference<2>
-@anchor{cp/topics/locations source-locations}@anchor{252}@anchor{cp/topics/locations doc}@anchor{253}
+@anchor{cp/topics/locations doc}@anchor{33e}@anchor{cp/topics/locations source-locations}@anchor{33f}
@subsection Source Locations
@geindex gccjit;;location (C++ class)
-@anchor{cp/topics/locations _CPPv2N6gccjit8locationE}@anchor{153}@anchor{cp/topics/locations gccjit location}@anchor{254}
+@anchor{cp/topics/locations _CPPv4N6gccjit8locationE}@anchor{163}@anchor{cp/topics/locations _CPPv3N6gccjit8locationE}@anchor{340}@anchor{cp/topics/locations _CPPv2N6gccjit8locationE}@anchor{341}@anchor{cp/topics/locations gccjit location}@anchor{342}
@deffn {C++ Class} gccjit::location
A @cite{gccjit::location} encapsulates a source code location, so that
@@ -13646,10 +14088,10 @@ single-step through your language.
@cite{gccjit::location} instances are optional: you can always omit them
from any C++ API entrypoint accepting one.
-You can construct them using @ref{159,,gccjit;;context;;new_location()}.
+You can construct them using @ref{169,,gccjit;;context;;new_location()}.
You need to enable @ref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the
-@ref{12d,,gccjit;;context} for these locations to actually be usable by
+@ref{13d,,gccjit;;context} for these locations to actually be usable by
the debugger:
@example
@@ -13658,8 +14100,8 @@ ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
@end deffn
@geindex gccjit;;context;;new_location (C++ function)
-@anchor{cp/topics/locations _CPPv2N6gccjit7context12new_locationEPKcii}@anchor{159}@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{255}
-@deffn {C++ Function} gccjit::@ref{153,,location} gccjit::context::new_location (const char *filename, int line, int column)
+@anchor{cp/topics/locations _CPPv4N6gccjit7context12new_locationEPKcii}@anchor{169}@anchor{cp/topics/locations _CPPv3N6gccjit7context12new_locationEPKcii}@anchor{343}@anchor{cp/topics/locations _CPPv2N6gccjit7context12new_locationEPKcii}@anchor{344}@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{345}
+@deffn {C++ Function} gccjit::@ref{163,,location} gccjit::@ref{13d,,context}::new_location (const char *filename, int line, int column)
Create a @cite{gccjit::location} instance representing the given source
location.
@@ -13671,13 +14113,13 @@ location.
@end menu
@node Faking it<2>,,,Source Locations<2>
-@anchor{cp/topics/locations faking-it}@anchor{256}
+@anchor{cp/topics/locations faking-it}@anchor{346}
@subsubsection Faking it
If you don’t have source code for your internal representation, but need
to debug, you can generate a C-like representation of the functions in
-your context using @ref{16e,,gccjit;;context;;dump_to_file()}:
+your context using @ref{188,,gccjit;;context;;dump_to_file()}:
@example
ctxt.dump_to_file ("/tmp/something.c",
@@ -13706,14 +14148,14 @@ file, giving you @emph{something} you can step through in the debugger.
@c along with this program. If not, see
@c <http://www.gnu.org/licenses/>.
-@node Compiling a context<2>,,Source Locations<2>,Topic Reference<2>
-@anchor{cp/topics/compilation compiling-a-context}@anchor{257}@anchor{cp/topics/compilation doc}@anchor{258}
+@node Compiling a context<2>,Using Assembly Language with libgccjit++,Source Locations<2>,Topic Reference<2>
+@anchor{cp/topics/compilation doc}@anchor{347}@anchor{cp/topics/compilation compiling-a-context}@anchor{348}
@subsection Compiling a context
-Once populated, a @ref{12d,,gccjit;;context} can be compiled to
-machine code, either in-memory via @ref{137,,gccjit;;context;;compile()} or
-to disk via @ref{259,,gccjit;;context;;compile_to_file()}.
+Once populated, a @ref{13d,,gccjit;;context} can be compiled to
+machine code, either in-memory via @ref{147,,gccjit;;context;;compile()} or
+to disk via @ref{349,,gccjit;;context;;compile_to_file()}.
You can compile a context multiple times (using either form of
compilation), although any errors that occur on the context will
@@ -13726,13 +14168,13 @@ prevent any future compilation of that context.
@end menu
@node In-memory compilation<2>,Ahead-of-time compilation<2>,,Compiling a context<2>
-@anchor{cp/topics/compilation in-memory-compilation}@anchor{25a}
+@anchor{cp/topics/compilation in-memory-compilation}@anchor{34a}
@subsubsection In-memory compilation
@geindex gccjit;;context;;compile (C++ function)
-@anchor{cp/topics/compilation _CPPv2N6gccjit7context7compileEv}@anchor{137}@anchor{cp/topics/compilation gccjit context compile}@anchor{25b}
-@deffn {C++ Function} gcc_jit_result *gccjit::context::compile ()
+@anchor{cp/topics/compilation _CPPv4N6gccjit7context7compileEv}@anchor{147}@anchor{cp/topics/compilation _CPPv3N6gccjit7context7compileEv}@anchor{34b}@anchor{cp/topics/compilation _CPPv2N6gccjit7context7compileEv}@anchor{34c}@anchor{cp/topics/compilation gccjit context compile}@anchor{34d}
+@deffn {C++ Function} gcc_jit_result *gccjit::@ref{13d,,context}::compile ()
This calls into GCC and builds the code, returning a
@cite{gcc_jit_result *}.
@@ -13742,25 +14184,418 @@ This is a thin wrapper around the
@end deffn
@node Ahead-of-time compilation<2>,,In-memory compilation<2>,Compiling a context<2>
-@anchor{cp/topics/compilation ahead-of-time-compilation}@anchor{25c}
+@anchor{cp/topics/compilation ahead-of-time-compilation}@anchor{34e}
@subsubsection Ahead-of-time compilation
Although libgccjit is primarily aimed at just-in-time compilation, it
can also be used for implementing more traditional ahead-of-time
-compilers, via the @ref{259,,gccjit;;context;;compile_to_file()} method.
+compilers, via the @ref{349,,gccjit;;context;;compile_to_file()} method.
@geindex gccjit;;context;;compile_to_file (C++ function)
-@anchor{cp/topics/compilation _CPPv2N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{259}@anchor{cp/topics/compilation gccjit context compile_to_file__gcc_jit_output_kind cCP}@anchor{25d}
-@deffn {C++ Function} void gccjit::context::compile_to_file (enum gcc_jit_output_kind, const char *output_path)
+@anchor{cp/topics/compilation _CPPv4N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{349}@anchor{cp/topics/compilation _CPPv3N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{34f}@anchor{cp/topics/compilation _CPPv2N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc}@anchor{350}@anchor{cp/topics/compilation gccjit context compile_to_file__gcc_jit_output_kind cCP}@anchor{351}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::compile_to_file (enum gcc_jit_output_kind, const char *output_path)
-Compile the @ref{12d,,gccjit;;context} to a file of the given
+Compile the @ref{13d,,gccjit;;context} to a file of the given
kind.
This is a thin wrapper around the
@ref{4a,,gcc_jit_context_compile_to_file()} API entrypoint.
@end deffn
+@c Copyright (C) 2020 Free Software Foundation, Inc.
+@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
+@c
+@c This is free software: you can redistribute it and/or modify it
+@c under the terms of the GNU General Public License as published by
+@c the Free Software Foundation, either version 3 of the License, or
+@c (at your option) any later version.
+@c
+@c This program is distributed in the hope that it will be useful, but
+@c WITHOUT ANY WARRANTY; without even the implied warranty of
+@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+@c General Public License for more details.
+@c
+@c You should have received a copy of the GNU General Public License
+@c along with this program. If not, see
+@c <http://www.gnu.org/licenses/>.
+
+@node Using Assembly Language with libgccjit++,,Compiling a context<2>,Topic Reference<2>
+@anchor{cp/topics/asm doc}@anchor{352}@anchor{cp/topics/asm using-assembly-language-with-libgccjit}@anchor{353}
+@subsection Using Assembly Language with libgccjit++
+
+
+libgccjit has some support for directly embedding assembler instructions.
+This is based on GCC’s support for inline @code{asm} in C code, and the
+following assumes a familiarity with that functionality. See
+How to Use Inline Assembly Language in C Code@footnote{https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html}
+in GCC’s documentation, the “Extended Asm” section in particular.
+
+These entrypoints were added in @ref{122,,LIBGCCJIT_ABI_15}; you can test
+for their presence using
+
+@quotation
+
+@example
+#ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
+@end example
+@end quotation
+
+@menu
+* Adding assembler instructions within a function: Adding assembler instructions within a function<2>.
+* Adding top-level assembler statements: Adding top-level assembler statements<2>.
+
+@end menu
+
+@node Adding assembler instructions within a function<2>,Adding top-level assembler statements<2>,,Using Assembly Language with libgccjit++
+@anchor{cp/topics/asm adding-assembler-instructions-within-a-function}@anchor{354}
+@subsubsection Adding assembler instructions within a function
+
+
+@geindex gccjit;;extended_asm (C++ class)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asmE}@anchor{355}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asmE}@anchor{356}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asmE}@anchor{357}@anchor{cp/topics/asm gccjit extended_asm}@anchor{358}
+@deffn {C++ Class} gccjit::extended_asm
+
+A @cite{gccjit::extended_asm} represents an extended @code{asm} statement: a
+series of low-level instructions inside a function that convert inputs
+to outputs.
+
+@ref{355,,gccjit;;extended_asm} is a subclass of @ref{142,,gccjit;;object}.
+It is a thin wrapper around the C API’s @ref{f1,,gcc_jit_extended_asm *}.
+
+To avoid having an API entrypoint with a very large number of
+parameters, an extended @code{asm} statement is made in stages:
+an initial call to create the @ref{355,,gccjit;;extended_asm},
+followed by calls to add operands and set other properties of the
+statement.
+
+There are two API entrypoints for creating a @ref{355,,gccjit;;extended_asm}:
+
+
+@itemize *
+
+@item
+@ref{359,,gccjit;;block;;add_extended_asm()} for an @code{asm} statement with
+no control flow, and
+
+@item
+@ref{35a,,gccjit;;block;;end_with_extended_asm_goto()} for an @code{asm goto}.
+@end itemize
+
+For example, to create the equivalent of:
+
+@example
+ asm ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
+@end example
+
+the following API calls could be used:
+
+@example
+ block.add_extended_asm ("mov %1, %0\n\t"
+ "add $1, %0")
+ .add_output_operand ("=r", dst)
+ .add_input_operand ("r", src);
+@end example
+
+@cartouche
+@quotation Warning
+When considering the numbering of operands within an
+extended @code{asm} statement (e.g. the @code{%0} and @code{%1}
+above), the equivalent to the C syntax is followed i.e. all
+output operands, then all input operands, regardless of
+what order the calls to
+@ref{35b,,gccjit;;extended_asm;;add_output_operand()} and
+@ref{35c,,gccjit;;extended_asm;;add_input_operand()} were made in.
+@end quotation
+@end cartouche
+
+As in the C syntax, operands can be given symbolic names to avoid having
+to number them. For example, to create the equivalent of:
+
+@example
+ asm ("bsfl %[aMask], %[aIndex]"
+ : [aIndex] "=r" (Index)
+ : [aMask] "r" (Mask)
+ : "cc");
+@end example
+
+the following API calls could be used:
+
+@example
+ block.add_extended_asm ("bsfl %[aMask], %[aIndex]")
+ .add_output_operand ("aIndex", "=r", index)
+ .add_input_operand ("aMask", "r", mask)
+ .add_clobber ("cc");
+@end example
+@end deffn
+
+@geindex gccjit;;block;;add_extended_asm (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{359}@anchor{cp/topics/asm _CPPv3N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{35d}@anchor{cp/topics/asm _CPPv2N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE}@anchor{35e}@anchor{cp/topics/asm gccjit block add_extended_asm__ssCR gccjit location}@anchor{35f}
+@deffn {C++ Function} @ref{355,,extended_asm} gccjit::@ref{153,,block}::add_extended_asm (const std::string &asm_template, gccjit::location loc = location())
+
+Create a @ref{355,,gccjit;;extended_asm} for an extended @code{asm} statement
+with no control flow (i.e. without the @code{goto} qualifier).
+
+The parameter @code{asm_template} corresponds to the @cite{AssemblerTemplate}
+within C’s extended @code{asm} syntax. It must be non-NULL. The call takes
+a copy of the underlying string, so it is valid to pass in a pointer to
+an on-stack buffer.
+@end deffn
+
+@geindex gccjit;;block;;end_with_extended_asm_goto (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{35a}@anchor{cp/topics/asm _CPPv3N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{360}@anchor{cp/topics/asm _CPPv2N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location}@anchor{361}@anchor{cp/topics/asm gccjit block end_with_extended_asm_goto__ssCR std vector block blockP location}@anchor{362}
+@deffn {C++ Function} @ref{355,,extended_asm} gccjit::@ref{153,,block}::end_with_extended_asm_goto (const std::string &asm_template, std::vector<block> goto_blocks, block *fallthrough_block, location loc = location())
+
+Create a @ref{355,,gccjit;;extended_asm} for an extended @code{asm} statement
+that may perform jumps, and use it to terminate the given block.
+This is equivalent to the @code{goto} qualifier in C’s extended @code{asm}
+syntax.
+
+For example, to create the equivalent of:
+
+@example
+ asm goto ("btl %1, %0\n\t"
+ "jc %l[carry]"
+ : // No outputs
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+@end example
+
+the following API calls could be used:
+
+@example
+ const char *asm_template =
+ (use_name
+ ? /* Label referred to by name: "%l[carry]". */
+ ("btl %1, %0\n\t"
+ "jc %l[carry]")
+ : /* Label referred to numerically: "%l2". */
+ ("btl %1, %0\n\t"
+ "jc %l2"));
+
+ std::vector<gccjit::block> goto_blocks (@{b_carry@});
+ gccjit::extended_asm ext_asm
+ = (b_start.end_with_extended_asm_goto (asm_template,
+ goto_blocks,
+ &b_fallthru)
+ .add_input_operand ("r", p1)
+ .add_input_operand ("r", p2)
+ .add_clobber ("cc"));
+@end example
+
+here referencing a @code{gcc_jit_block} named “carry”.
+
+@code{num_goto_blocks} corresponds to the @code{GotoLabels} parameter within C’s
+extended @code{asm} syntax. The block names can be referenced within the
+assembler template.
+
+@code{fallthrough_block} can be NULL. If non-NULL, it specifies the block
+to fall through to after the statement.
+
+@cartouche
+@quotation Note
+This is needed since each @ref{153,,gccjit;;block} must have a
+single exit point, as a basic block: you can’t jump from the
+middle of a block. A “goto” is implicitly added after the
+asm to handle the fallthrough case, which is equivalent to what
+would have happened in the C case.
+@end quotation
+@end cartouche
+@end deffn
+
+@geindex gccjit;;extended_asm;;set_volatile_flag (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17set_volatile_flagEb}@anchor{363}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17set_volatile_flagEb}@anchor{364}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17set_volatile_flagEb}@anchor{365}@anchor{cp/topics/asm gccjit extended_asm set_volatile_flag__b}@anchor{366}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::set_volatile_flag (bool flag)
+
+Set whether the @ref{355,,gccjit;;extended_asm} has side-effects, equivalent to the
+volatile@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile}
+qualifier in C’s extended asm syntax.
+
+For example, to create the equivalent of:
+
+@example
+asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (msr)
+ :
+ : "rdx");
+@end example
+
+the following API calls could be used:
+
+@example
+ gccjit::extended_asm ext_asm
+ = block.add_extended_asm
+ ("rdtsc\n\t" /* Returns the time in EDX:EAX. */
+ "shl $32, %%rdx\n\t" /* Shift the upper bits left. */
+ "or %%rdx, %0") /* 'Or' in the lower bits. */
+ .set_volatile_flag (true)
+ .add_output_operand ("=a", msr)
+ .add_clobber ("rdx");
+@end example
+
+where the @ref{355,,gccjit;;extended_asm} is flagged as volatile.
+@end deffn
+
+@geindex gccjit;;extended_asm;;set_inline_flag (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm15set_inline_flagEb}@anchor{367}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm15set_inline_flagEb}@anchor{368}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm15set_inline_flagEb}@anchor{369}@anchor{cp/topics/asm gccjit extended_asm set_inline_flag__b}@anchor{36a}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::set_inline_flag (bool flag)
+
+Set the equivalent of the
+inline@footnote{https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm}
+qualifier in C’s extended @code{asm} syntax.
+@end deffn
+
+@geindex gccjit;;extended_asm;;add_output_operand (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{35b}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{36b}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE}@anchor{36c}@anchor{cp/topics/asm gccjit extended_asm add_output_operand__ssCR ssCR gccjit lvalue}@anchor{36d}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_output_operand (const std::string &asm_symbolic_name, const std::string &constraint, gccjit::lvalue dest)
+
+Add an output operand to the extended @code{asm} statement. See the
+Output Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands}
+section of the documentation of the C syntax.
+
+@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component of
+C’s extended @code{asm} syntax, and specifies the symbolic name for the operand.
+See the overload below for an alternative that does not supply a symbolic
+name.
+
+@code{constraint} corresponds to the @code{constraint} component of C’s extended
+@code{asm} syntax.
+
+@code{dest} corresponds to the @code{cvariablename} component of C’s extended
+@code{asm} syntax.
+
+@example
+// Example with a symbolic name ("aIndex"), the equivalent of:
+// : [aIndex] "=r" (index)
+ext_asm.add_output_operand ("aIndex", "=r", index);
+@end example
+
+This function can’t be called on an @code{asm goto} as such instructions can’t
+have outputs; see the
+Goto Labels@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels}
+section of GCC’s “Extended Asm” documentation.
+@end deffn
+
+@geindex gccjit;;extended_asm;;add_output_operand (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{36e}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{36f}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE}@anchor{370}@anchor{cp/topics/asm gccjit extended_asm add_output_operand__ssCR gccjit lvalue}@anchor{371}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_output_operand (const std::string &constraint, gccjit::lvalue dest)
+
+As above, but don’t supply a symbolic name for the operand.
+
+@example
+// Example without a symbolic name, the equivalent of:
+// : "=r" (dst)
+ext_asm.add_output_operand ("=r", dst);
+@end example
+@end deffn
+
+@geindex gccjit;;extended_asm;;add_input_operand (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{35c}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{372}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE}@anchor{373}@anchor{cp/topics/asm gccjit extended_asm add_input_operand__ssCR ssCR gccjit rvalue}@anchor{374}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_input_operand (const std::string &asm_symbolic_name, const std::string &constraint, gccjit::rvalue src)
+
+Add an input operand to the extended @code{asm} statement. See the
+Input Operands@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands}
+section of the documentation of the C syntax.
+
+@code{asm_symbolic_name} corresponds to the @code{asmSymbolicName} component
+of C’s extended @code{asm} syntax. See the overload below for an alternative
+that does not supply a symbolic name.
+
+@code{constraint} corresponds to the @code{constraint} component of C’s extended
+@code{asm} syntax.
+
+@code{src} corresponds to the @code{cexpression} component of C’s extended
+@code{asm} syntax.
+
+@example
+// Example with a symbolic name ("aMask"), the equivalent of:
+// : [aMask] "r" (Mask)
+ext_asm.add_input_operand ("aMask", "r", mask);
+@end example
+@end deffn
+
+@geindex gccjit;;extended_asm;;add_input_operand (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{375}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{376}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE}@anchor{377}@anchor{cp/topics/asm gccjit extended_asm add_input_operand__ssCR gccjit rvalue}@anchor{378}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_input_operand (const std::string &constraint, gccjit::rvalue src)
+
+As above, but don’t supply a symbolic name for the operand.
+
+@example
+// Example without a symbolic name, the equivalent of:
+// : "r" (src)
+ext_asm.add_input_operand ("r", src);
+@end example
+@end deffn
+
+@geindex gccjit;;extended_asm;;add_clobber (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{379}@anchor{cp/topics/asm _CPPv3N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{37a}@anchor{cp/topics/asm _CPPv2N6gccjit12extended_asm11add_clobberERKNSt6stringE}@anchor{37b}@anchor{cp/topics/asm gccjit extended_asm add_clobber__ssCR}@anchor{37c}
+@deffn {C++ Function} gccjit::@ref{355,,extended_asm} &gccjit::@ref{355,,extended_asm}::add_clobber (const std::string &victim)
+
+Add @cite{victim} to the list of registers clobbered by the extended @code{asm}
+statement. See the
+Clobbers and Scratch Registers@footnote{https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#}
+section of the documentation of the C syntax.
+
+Statements with multiple clobbers will require multiple calls, one per
+clobber.
+
+For example:
+
+@example
+ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory");
+@end example
+@end deffn
+
+@node Adding top-level assembler statements<2>,,Adding assembler instructions within a function<2>,Using Assembly Language with libgccjit++
+@anchor{cp/topics/asm adding-top-level-assembler-statements}@anchor{37d}
+@subsubsection Adding top-level assembler statements
+
+
+In addition to creating extended @code{asm} instructions within a function,
+there is support for creating “top-level” assembler statements, outside
+of any function.
+
+@geindex gccjit;;context;;add_top_level_asm (C++ function)
+@anchor{cp/topics/asm _CPPv4N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{37e}@anchor{cp/topics/asm _CPPv3N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{37f}@anchor{cp/topics/asm _CPPv2N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE}@anchor{380}@anchor{cp/topics/asm gccjit context add_top_level_asm__cCP gccjit location}@anchor{381}
+@deffn {C++ Function} void gccjit::@ref{13d,,context}::add_top_level_asm (const char *asm_stmts, gccjit::location loc = location())
+
+Create a set of top-level asm statements, analogous to those created
+by GCC’s “basic” @code{asm} syntax in C at file scope.
+
+For example, to create the equivalent of:
+
+@example
+ asm ("\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @@function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t.popsection\n");
+@end example
+
+the following API calls could be used:
+
+@example
+ ctxt.add_top_level_asm ("\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @@function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t# some asm here\n"
+ "\t.popsection\n");
+@end example
+@end deffn
+
@c Copyright (C) 2014-2020 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -13779,7 +14614,7 @@ This is a thin wrapper around the
@c <http://www.gnu.org/licenses/>.
@node Internals,Indices and tables,C++ bindings for libgccjit,Top
-@anchor{internals/index internals}@anchor{25e}@anchor{internals/index doc}@anchor{25f}
+@anchor{internals/index doc}@anchor{382}@anchor{internals/index internals}@anchor{383}
@chapter Internals
@@ -13795,7 +14630,7 @@ This is a thin wrapper around the
@end menu
@node Working on the JIT library,Running the test suite,,Internals
-@anchor{internals/index working-on-the-jit-library}@anchor{260}
+@anchor{internals/index working-on-the-jit-library}@anchor{384}
@section Working on the JIT library
@@ -13828,7 +14663,7 @@ gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
Here’s what those configuration options mean:
@geindex command line option; --enable-host-shared
-@anchor{internals/index cmdoption-enable-host-shared}@anchor{261}
+@anchor{internals/index cmdoption-enable-host-shared}@anchor{385}
@deffn {Option} @w{-}@w{-}enable@w{-}host@w{-}shared
Configuring with this option means that the compiler is built as
@@ -13837,7 +14672,7 @@ but it necessary for a shared library.
@end deffn
@geindex command line option; --enable-languages=jit@comma{}c++
-@anchor{internals/index cmdoption-enable-languages}@anchor{262}
+@anchor{internals/index cmdoption-enable-languages}@anchor{386}
@deffn {Option} @w{-}@w{-}enable@w{-}languages=jit,c++
This specifies which frontends to build. The JIT library looks like
@@ -13854,7 +14689,7 @@ c++: error trying to exec 'cc1plus': execvp: No such file or directory
@end deffn
@geindex command line option; --disable-bootstrap
-@anchor{internals/index cmdoption-disable-bootstrap}@anchor{263}
+@anchor{internals/index cmdoption-disable-bootstrap}@anchor{387}
@deffn {Option} @w{-}@w{-}disable@w{-}bootstrap
For hacking on the “jit” subdirectory, performing a full
@@ -13864,7 +14699,7 @@ the compiler can still bootstrap itself.
@end deffn
@geindex command line option; --enable-checking=release
-@anchor{internals/index cmdoption-enable-checking}@anchor{264}
+@anchor{internals/index cmdoption-enable-checking}@anchor{388}
@deffn {Option} @w{-}@w{-}enable@w{-}checking=release
The compile can perform extensive self-checking as it runs, useful when
@@ -13875,7 +14710,7 @@ disable this self-checking.
@end deffn
@node Running the test suite,Environment variables,Working on the JIT library,Internals
-@anchor{internals/index running-the-test-suite}@anchor{265}
+@anchor{internals/index running-the-test-suite}@anchor{389}
@section Running the test suite
@@ -13933,7 +14768,7 @@ and once a test has been compiled, you can debug it directly:
@end menu
@node Running under valgrind,,,Running the test suite
-@anchor{internals/index running-under-valgrind}@anchor{266}
+@anchor{internals/index running-under-valgrind}@anchor{38a}
@subsection Running under valgrind
@@ -13982,7 +14817,7 @@ When running under valgrind, it’s best to have configured gcc with
various known false positives.
@node Environment variables,Packaging notes,Running the test suite,Internals
-@anchor{internals/index environment-variables}@anchor{267}
+@anchor{internals/index environment-variables}@anchor{38b}
@section Environment variables
@@ -13990,7 +14825,7 @@ When running client code against a locally-built libgccjit, three
environment variables need to be set up:
@geindex environment variable; LD_LIBRARY_PATH
-@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{268}
+@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{38c}
@deffn {Environment Variable} LD_LIBRARY_PATH
@quotation
@@ -14010,7 +14845,7 @@ libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux),
@end deffn
@geindex environment variable; PATH
-@anchor{internals/index envvar-PATH}@anchor{269}
+@anchor{internals/index envvar-PATH}@anchor{38d}
@deffn {Environment Variable} PATH
The library uses a driver executable for converting from .s assembler
@@ -14029,7 +14864,7 @@ of development.
@end deffn
@geindex environment variable; LIBRARY_PATH
-@anchor{internals/index envvar-LIBRARY_PATH}@anchor{26a}
+@anchor{internals/index envvar-LIBRARY_PATH}@anchor{38e}
@deffn {Environment Variable} LIBRARY_PATH
The driver executable invokes the linker, and the latter needs to locate
@@ -14061,11 +14896,11 @@ hello world
@end example
@node Packaging notes,Overview of code structure,Environment variables,Internals
-@anchor{internals/index packaging-notes}@anchor{26b}
+@anchor{internals/index packaging-notes}@anchor{38f}
@section Packaging notes
-The configure-time option @ref{261,,--enable-host-shared} is needed when
+The configure-time option @ref{385,,--enable-host-shared} is needed when
building the jit in order to get position-independent code. This will
slow down the regular compiler by a few percent. Hence when packaging gcc
with libgccjit, please configure and build twice:
@@ -14076,10 +14911,10 @@ with libgccjit, please configure and build twice:
@itemize *
@item
-once without @ref{261,,--enable-host-shared} for most languages, and
+once without @ref{385,,--enable-host-shared} for most languages, and
@item
-once with @ref{261,,--enable-host-shared} for the jit
+once with @ref{385,,--enable-host-shared} for the jit
@end itemize
@end quotation
@@ -14121,7 +14956,7 @@ popd
@end example
@node Overview of code structure,Design notes,Packaging notes,Internals
-@anchor{internals/index overview-of-code-structure}@anchor{26c}
+@anchor{internals/index overview-of-code-structure}@anchor{390}
@section Overview of code structure
@@ -14168,7 +15003,9 @@ The gcc::jit::recording classes (within @code{jit-recording.c} and
class base_call;
class function_pointer;
class statement;
+ class extended_asm;
class case_;
+ class top_level_asm;
@end example
@end quotation
@@ -14588,7 +15425,7 @@ JIT: gcc::jit::logger::~logger()
@end example
@node Design notes,Submitting patches,Overview of code structure,Internals
-@anchor{internals/index design-notes}@anchor{26d}
+@anchor{internals/index design-notes}@anchor{391}
@section Design notes
@@ -14601,7 +15438,7 @@ close as possible to the error; failing that, a good place is within
@code{recording::context::validate ()} in jit-recording.c.
@node Submitting patches,,Design notes,Internals
-@anchor{internals/index submitting-patches}@anchor{26e}
+@anchor{internals/index submitting-patches}@anchor{392}
@section Submitting patches
@@ -14735,7 +15572,7 @@ large and inconsequential (e.g. anchor renumbering), rather like generated
committing to svn.
@node Indices and tables,Index,Internals,Top
-@anchor{index indices-and-tables}@anchor{26f}
+@anchor{index indices-and-tables}@anchor{393}
@unnumbered Indices and tables
diff --git a/gcc/jit/docs/cp/topics/asm.rst b/gcc/jit/docs/cp/topics/asm.rst
new file mode 100644
index 0000000..69e2d1e
--- /dev/null
+++ b/gcc/jit/docs/cp/topics/asm.rst
@@ -0,0 +1,308 @@
+.. Copyright (C) 2020 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <dmalcolm@redhat.com>
+
+ This 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see
+ <http://www.gnu.org/licenses/>.
+
+.. default-domain:: cpp
+
+Using Assembly Language with libgccjit++
+========================================
+
+libgccjit has some support for directly embedding assembler instructions.
+This is based on GCC's support for inline ``asm`` in C code, and the
+following assumes a familiarity with that functionality. See
+`How to Use Inline Assembly Language in C Code <https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html>`_
+in GCC's documentation, the "Extended Asm" section in particular.
+
+These entrypoints were added in :ref:`LIBGCCJIT_ABI_15`; you can test
+for their presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
+
+Adding assembler instructions within a function
+***********************************************
+
+.. class:: gccjit::extended_asm
+
+ A `gccjit::extended_asm` represents an extended ``asm`` statement: a
+ series of low-level instructions inside a function that convert inputs
+ to outputs.
+
+ :class:`gccjit::extended_asm` is a subclass of :class:`gccjit::object`.
+ It is a thin wrapper around the C API's :c:type:`gcc_jit_extended_asm *`.
+
+ To avoid having an API entrypoint with a very large number of
+ parameters, an extended ``asm`` statement is made in stages:
+ an initial call to create the :type:`gccjit::extended_asm`,
+ followed by calls to add operands and set other properties of the
+ statement.
+
+ There are two API entrypoints for creating a :type:`gccjit::extended_asm`:
+
+ * :func:`gccjit::block::add_extended_asm` for an ``asm`` statement with
+ no control flow, and
+
+ * :func:`gccjit::block::end_with_extended_asm_goto` for an ``asm goto``.
+
+ For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: // Quote from here in docs/cp/topics/asm.rst: example 1: C
+ :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 1: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 1: jit. */
+ :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 1: jit. */
+ :language: c
+
+ .. warning:: When considering the numbering of operands within an
+ extended ``asm`` statement (e.g. the ``%0`` and ``%1``
+ above), the equivalent to the C syntax is followed i.e. all
+ output operands, then all input operands, regardless of
+ what order the calls to
+ :func:`gccjit::extended_asm::add_output_operand` and
+ :func:`gccjit::extended_asm::add_input_operand` were made in.
+
+ As in the C syntax, operands can be given symbolic names to avoid having
+ to number them. For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: // Quote from here in docs/cp/topics/asm.rst: example 2: C
+ :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 2: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 2: jit. */
+ :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 2: jit. */
+ :language: c
+
+.. function:: extended_asm \
+ gccjit::block::add_extended_asm (const std::string &asm_template,\
+ gccjit::location loc = location ())
+
+ Create a :type:`gccjit::extended_asm` for an extended ``asm`` statement
+ with no control flow (i.e. without the ``goto`` qualifier).
+
+ The parameter ``asm_template`` corresponds to the `AssemblerTemplate`
+ within C's extended ``asm`` syntax. It must be non-NULL. The call takes
+ a copy of the underlying string, so it is valid to pass in a pointer to
+ an on-stack buffer.
+
+.. function:: extended_asm\
+ gccjit::block::end_with_extended_asm_goto (const std::string &asm_template,\
+ std::vector<block> goto_blocks,\
+ block *fallthrough_block,\
+ location loc = location ())
+
+ Create a :type:`gccjit::extended_asm` for an extended ``asm`` statement
+ that may perform jumps, and use it to terminate the given block.
+ This is equivalent to the ``goto`` qualifier in C's extended ``asm``
+ syntax.
+
+ For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: // Quote from here in docs/cp/topics/asm.rst: example 3b: C
+ :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 3b: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 3: jit. */
+ :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 3: jit. */
+ :language: c
+
+ here referencing a :type:`gcc_jit_block` named "carry".
+
+ ``num_goto_blocks`` corresponds to the ``GotoLabels`` parameter within C's
+ extended ``asm`` syntax. The block names can be referenced within the
+ assembler template.
+
+ ``fallthrough_block`` can be NULL. If non-NULL, it specifies the block
+ to fall through to after the statement.
+
+ .. note:: This is needed since each :type:`gccjit::block` must have a
+ single exit point, as a basic block: you can't jump from the
+ middle of a block. A "goto" is implicitly added after the
+ asm to handle the fallthrough case, which is equivalent to what
+ would have happened in the C case.
+
+.. function:: gccjit::extended_asm &\
+ gccjit::extended_asm::set_volatile_flag (bool flag)
+
+ Set whether the :type:`gccjit::extended_asm` has side-effects, equivalent to the
+ `volatile <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile>`_
+ qualifier in C's extended asm syntax.
+
+ For example, to create the equivalent of:
+
+ .. code-block:: c
+
+ asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (msr)
+ :
+ : "rdx");
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 4: jit. */
+ :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 4: jit. */
+ :language: c
+
+ where the :type:`gccjit::extended_asm` is flagged as volatile.
+
+.. function:: gccjit::extended_asm &\
+ gccjit::extended_asm::set_inline_flag (bool flag)
+
+ Set the equivalent of the
+ `inline <https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm>`_
+ qualifier in C's extended ``asm`` syntax.
+
+.. function:: gccjit::extended_asm&\
+ gccjit::extended_asm::add_output_operand (const std::string &asm_symbolic_name,\
+ const std::string &constraint,\
+ gccjit::lvalue dest)
+
+ Add an output operand to the extended ``asm`` statement. See the
+ `Output Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands>`_
+ section of the documentation of the C syntax.
+
+ ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component of
+ C's extended ``asm`` syntax, and specifies the symbolic name for the operand.
+ See the overload below for an alternative that does not supply a symbolic
+ name.
+
+ ``constraint`` corresponds to the ``constraint`` component of C's extended
+ ``asm`` syntax.
+
+ ``dest`` corresponds to the ``cvariablename`` component of C's extended
+ ``asm`` syntax.
+
+ .. code-block:: c++
+
+ // Example with a symbolic name ("aIndex"), the equivalent of:
+ // : [aIndex] "=r" (index)
+ ext_asm.add_output_operand ("aIndex", "=r", index);
+
+ This function can't be called on an ``asm goto`` as such instructions can't
+ have outputs; see the
+ `Goto Labels <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels>`_
+ section of GCC's "Extended Asm" documentation.
+
+.. function:: gccjit::extended_asm&\
+ gccjit::extended_asm::add_output_operand (const std::string &constraint,\
+ gccjit::lvalue dest)
+
+ As above, but don't supply a symbolic name for the operand.
+
+ .. code-block:: c++
+
+ // Example without a symbolic name, the equivalent of:
+ // : "=r" (dst)
+ ext_asm.add_output_operand ("=r", dst);
+
+.. function:: gccjit::extended_asm&\
+ gccjit::extended_asm::add_input_operand (const std::string &asm_symbolic_name, \
+ const std::string &constraint, \
+ gccjit::rvalue src)
+
+ Add an input operand to the extended ``asm`` statement. See the
+ `Input Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands>`_
+ section of the documentation of the C syntax.
+
+ ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component
+ of C's extended ``asm`` syntax. See the overload below for an alternative
+ that does not supply a symbolic name.
+
+ ``constraint`` corresponds to the ``constraint`` component of C's extended
+ ``asm`` syntax.
+
+ ``src`` corresponds to the ``cexpression`` component of C's extended
+ ``asm`` syntax.
+
+ .. code-block:: c++
+
+ // Example with a symbolic name ("aMask"), the equivalent of:
+ // : [aMask] "r" (Mask)
+ ext_asm.add_input_operand ("aMask", "r", mask);
+
+.. function:: gccjit::extended_asm&\
+ gccjit::extended_asm::add_input_operand (const std::string &constraint,\
+ gccjit::rvalue src)
+
+ As above, but don't supply a symbolic name for the operand.
+
+ .. code-block:: c++
+
+ // Example without a symbolic name, the equivalent of:
+ // : "r" (src)
+ ext_asm.add_input_operand ("r", src);
+
+.. function:: gccjit::extended_asm&\
+ gccjit::extended_asm::add_clobber (const std::string &victim)
+
+ Add `victim` to the list of registers clobbered by the extended ``asm``
+ statement. See the
+ `Clobbers and Scratch Registers <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#>`_
+ section of the documentation of the C syntax.
+
+ Statements with multiple clobbers will require multiple calls, one per
+ clobber.
+
+ For example:
+
+ .. code-block:: c++
+
+ ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory");
+
+
+Adding top-level assembler statements
+*************************************
+
+In addition to creating extended ``asm`` instructions within a function,
+there is support for creating "top-level" assembler statements, outside
+of any function.
+
+.. function:: void\
+ gccjit::context::add_top_level_asm (const char *asm_stmts,\
+ gccjit::location loc = location ())
+
+ Create a set of top-level asm statements, analogous to those created
+ by GCC's "basic" ``asm`` syntax in C at file scope.
+
+ For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: // Quote from here in docs/cp/topics/asm.rst: example 5: C
+ :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 5: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
+ :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 5: jit. */
+ :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 5: jit. */
+ :language: c
diff --git a/gcc/jit/docs/cp/topics/index.rst b/gcc/jit/docs/cp/topics/index.rst
index 187a20d..721e70c 100644
--- a/gcc/jit/docs/cp/topics/index.rst
+++ b/gcc/jit/docs/cp/topics/index.rst
@@ -28,3 +28,4 @@ Topic Reference
functions.rst
locations.rst
compilation.rst
+ asm.rst
diff --git a/gcc/jit/docs/topics/asm.rst b/gcc/jit/docs/topics/asm.rst
new file mode 100644
index 0000000..b91514d
--- /dev/null
+++ b/gcc/jit/docs/topics/asm.rst
@@ -0,0 +1,311 @@
+.. Copyright (C) 2020 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <dmalcolm@redhat.com>
+
+ This 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see
+ <http://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Using Assembly Language with libgccjit
+======================================
+
+libgccjit has some support for directly embedding assembler instructions.
+This is based on GCC's support for inline ``asm`` in C code, and the
+following assumes a familiarity with that functionality. See
+`How to Use Inline Assembly Language in C Code <https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html>`_
+in GCC's documentation, the "Extended Asm" section in particular.
+
+These entrypoints were added in :ref:`LIBGCCJIT_ABI_15`; you can test
+for their presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
+
+Adding assembler instructions within a function
+***********************************************
+
+.. type:: gcc_jit_extended_asm
+
+ A `gcc_jit_extended_asm` represents an extended ``asm`` statement: a
+ series of low-level instructions inside a function that convert inputs
+ to outputs.
+
+ To avoid having an API entrypoint with a very large number of
+ parameters, an extended ``asm`` statement is made in stages:
+ an initial call to create the :type:`gcc_jit_extended_asm`,
+ followed by calls to add operands and set other properties of the
+ statement.
+
+ There are two API entrypoints for creating a :type:`gcc_jit_extended_asm`:
+
+ * :func:`gcc_jit_block_add_extended_asm` for an ``asm`` statement with
+ no control flow, and
+
+ * :func:`gcc_jit_block_end_with_extended_asm_goto` for an ``asm goto``.
+
+ For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: // Quote from here in docs/topics/asm.rst: example 1: C
+ :end-before: // Quote up to here in docs/topics/asm.rst: example 1: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: /* Quote from here in docs/topics/asm.rst: example 1: jit. */
+ :end-before: /* Quote up to here in docs/topics/asm.rst: example 1: jit. */
+ :language: c
+
+ .. warning:: When considering the numbering of operands within an
+ extended ``asm`` statement (e.g. the ``%0`` and ``%1``
+ above), the equivalent to the C syntax is followed i.e. all
+ output operands, then all input operands, regardless of
+ what order the calls to
+ :func:`gcc_jit_extended_asm_add_output_operand` and
+ :func:`gcc_jit_extended_asm_add_input_operand` were made in.
+
+ As in the C syntax, operands can be given symbolic names to avoid having
+ to number them. For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: // Quote from here in docs/topics/asm.rst: example 2: C
+ :end-before: // Quote up to here in docs/topics/asm.rst: example 2: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: /* Quote from here in docs/topics/asm.rst: example 2: jit. */
+ :end-before: /* Quote up to here in docs/topics/asm.rst: example 2: jit. */
+ :language: c
+
+.. function:: gcc_jit_extended_asm *\
+ gcc_jit_block_add_extended_asm (gcc_jit_block *block,\
+ gcc_jit_location *loc,\
+ const char *asm_template)
+
+ Create a :type:`gcc_jit_extended_asm` for an extended ``asm`` statement
+ with no control flow (i.e. without the ``goto`` qualifier).
+
+ The parameter ``asm_template`` corresponds to the `AssemblerTemplate`
+ within C's extended ``asm`` syntax. It must be non-NULL. The call takes
+ a copy of the underlying string, so it is valid to pass in a pointer to
+ an on-stack buffer.
+
+.. function:: gcc_jit_extended_asm *\
+ gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block *block,\
+ gcc_jit_location *loc,\
+ const char *asm_template,\
+ int num_goto_blocks,\
+ gcc_jit_block **goto_blocks,\
+ gcc_jit_block *fallthrough_block)
+
+ Create a :type:`gcc_jit_extended_asm` for an extended ``asm`` statement
+ that may perform jumps, and use it to terminate the given block.
+ This is equivalent to the ``goto`` qualifier in C's extended ``asm``
+ syntax.
+
+ For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: // Quote from here in docs/topics/asm.rst: example 3b: C
+ :end-before: // Quote up to here in docs/topics/asm.rst: example 3b: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: /* Quote from here in docs/topics/asm.rst: example 3: jit. */
+ :end-before: /* Quote up to here in docs/topics/asm.rst: example 3: jit. */
+ :language: c
+
+ here referencing a :type:`gcc_jit_block` named "carry".
+
+ ``num_goto_blocks`` must be >= 0.
+
+ ``goto_blocks`` must be non-NULL. This corresponds to the ``GotoLabels``
+ parameter within C's extended ``asm`` syntax. The block names can be
+ referenced within the assembler template.
+
+ ``fallthrough_block`` can be NULL. If non-NULL, it specifies the block
+ to fall through to after the statement.
+
+ .. note:: This is needed since each :type:`gcc_jit_block` must have a
+ single exit point, as a basic block: you can't jump from the
+ middle of a block. A "goto" is implicitly added after the
+ asm to handle the fallthrough case, which is equivalent to what
+ would have happened in the C case.
+
+.. function:: void\
+ gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm *ext_asm,\
+ int flag)
+
+ Set whether the :type:`gcc_jit_extended_asm` has side-effects, equivalent to the
+ `volatile <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile>`_
+ qualifier in C's extended asm syntax.
+
+ For example, to create the equivalent of:
+
+ .. code-block:: c
+
+ asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (msr)
+ :
+ : "rdx");
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: /* Quote from here in docs/topics/asm.rst: example 4: jit. */
+ :end-before: /* Quote up to here in docs/topics/asm.rst: example 4: jit. */
+ :language: c
+
+ where the :type:`gcc_jit_extended_asm` is flagged as volatile.
+
+.. function:: void\
+ gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm *ext_asm,\
+ int flag)
+
+ Set the equivalent of the
+ `inline <https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm>`_
+ qualifier in C's extended ``asm`` syntax.
+
+.. function:: void\
+ gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm *ext_asm,\
+ const char *asm_symbolic_name,\
+ const char *constraint,\
+ gcc_jit_lvalue *dest)
+
+ Add an output operand to the extended ``asm`` statement. See the
+ `Output Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands>`_
+ section of the documentation of the C syntax.
+
+ ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component of C's
+ extended ``asm`` syntax. It can be NULL. If non-NULL it specifies the
+ symbolic name for the operand.
+
+ ``constraint`` corresponds to the ``constraint`` component of C's extended
+ ``asm`` syntax. It must be non-NULL.
+
+ ``dest`` corresponds to the ``cvariablename`` component of C's extended
+ ``asm`` syntax. It must be non-NULL.
+
+ .. code-block:: c
+
+ // Example with a NULL symbolic name, the equivalent of:
+ // : "=r" (dst)
+ gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst);
+
+ // Example with a symbolic name ("aIndex"), the equivalent of:
+ // : [aIndex] "=r" (index)
+ gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index);
+
+ This function can't be called on an ``asm goto`` as such instructions can't
+ have outputs; see the
+ `Goto Labels <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels>`_
+ section of GCC's "Extended Asm" documentation.
+
+.. function:: void\
+ gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm *ext_asm,\
+ const char *asm_symbolic_name,\
+ const char *constraint,\
+ gcc_jit_rvalue *src)
+
+ Add an input operand to the extended ``asm`` statement. See the
+ `Input Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands>`_
+ section of the documentation of the C syntax.
+
+ ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component of C's
+ extended ``asm`` syntax. It can be NULL. If non-NULL it specifies the
+ symbolic name for the operand.
+
+ ``constraint`` corresponds to the ``constraint`` component of C's extended
+ ``asm`` syntax. It must be non-NULL.
+
+ ``src`` corresponds to the ``cexpression`` component of C's extended
+ ``asm`` syntax. It must be non-NULL.
+
+ .. code-block:: c
+
+ // Example with a NULL symbolic name, the equivalent of:
+ // : "r" (src)
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_lvalue_as_rvalue (src));
+
+ // Example with a symbolic name ("aMask"), the equivalent of:
+ // : [aMask] "r" (Mask)
+ gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r",
+ gcc_jit_lvalue_as_rvalue (mask));
+
+.. function:: void\
+ gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm *ext_asm,\
+ const char *victim)
+
+ Add `victim` to the list of registers clobbered by the extended ``asm``
+ statement. It must be non-NULL. See the
+ `Clobbers and Scratch Registers <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#>`_
+ section of the documentation of the C syntax.
+
+ Statements with multiple clobbers will require multiple calls, one per
+ clobber.
+
+ For example:
+
+ .. code-block:: c
+
+ gcc_jit_extended_asm_add_clobber (ext_asm, "r0");
+ gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
+ gcc_jit_extended_asm_add_clobber (ext_asm, "memory");
+
+A :type:`gcc_jit_extended_asm` is a :type:`gcc_jit_object` "owned" by
+the block's context. The following upcast is available:
+
+.. function:: gcc_jit_object *\
+ gcc_jit_extended_asm_as_object (gcc_jit_extended_asm *ext_asm)
+
+ Upcast from extended ``asm`` to object.
+
+
+Adding top-level assembler statements
+*************************************
+
+In addition to creating extended ``asm`` instructions within a function,
+there is support for creating "top-level" assembler statements, outside
+of any function.
+
+.. function:: void \
+ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ const char *asm_stmts)
+
+ Create a set of top-level asm statements, analogous to those created
+ by GCC's "basic" ``asm`` syntax in C at file scope.
+
+ For example, to create the equivalent of:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: // Quote from here in docs/topics/asm.rst: example 5: C
+ :end-before: // Quote up to here in docs/topics/asm.rst: example 5: C
+ :language: c
+
+ the following API calls could be used:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c
+ :start-after: /* Quote from here in docs/topics/asm.rst: example 5: jit. */
+ :end-before: /* Quote up to here in docs/topics/asm.rst: example 5: jit. */
+ :language: c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 6bfa101..b953da5 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -226,3 +226,20 @@ entrypoints:
--------------------
``LIBGCCJIT_ABI_14`` covers the addition of
:func:`gcc_jit_global_set_initializer`
+
+.. _LIBGCCJIT_ABI_15:
+
+``LIBGCCJIT_ABI_15``
+-----------------------
+``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
+embedding assembler instructions:
+
+ * :func:`gcc_jit_block_add_extended_asm`
+ * :func:`gcc_jit_block_end_with_extended_asm_goto`
+ * :func:`gcc_jit_extended_asm_as_object`
+ * :func:`gcc_jit_extended_asm_set_volatile_flag`
+ * :func:`gcc_jit_extended_asm_set_inline_flag`
+ * :func:`gcc_jit_extended_asm_add_output_operand`
+ * :func:`gcc_jit_extended_asm_add_input_operand`
+ * :func:`gcc_jit_extended_asm_add_clobber`
+ * :func:`gcc_jit_context_add_top_level_asm`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index eb40d64..b869256 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -458,3 +458,6 @@ Statements
:start-after: /* Quote from here in docs/topics/functions.rst. */
:end-before: /* Quote up to here in docs/topics/functions.rst. */
:language: c
+
+See also :type:`gcc_jit_extended_asm` for entrypoints for adding inline
+assembler statements to a function.
diff --git a/gcc/jit/docs/topics/index.rst b/gcc/jit/docs/topics/index.rst
index 8352ca2..d7cb86a 100644
--- a/gcc/jit/docs/topics/index.rst
+++ b/gcc/jit/docs/topics/index.rst
@@ -31,3 +31,4 @@ Topic Reference
compilation.rst
compatibility.rst
performance.rst
+ asm.rst
diff --git a/gcc/jit/docs/topics/objects.rst b/gcc/jit/docs/topics/objects.rst
index 12d3c9f..cdee2c0 100644
--- a/gcc/jit/docs/topics/objects.rst
+++ b/gcc/jit/docs/topics/objects.rst
@@ -48,6 +48,7 @@ looks like this::
+- gcc_jit_lvalue
+- gcc_jit_param
+- gcc_jit_case
+ +- gcc_jit_extended_asm
There are casting methods for upcasting from subclasses to parent classes.
For example, :c:func:`gcc_jit_type_as_object`:
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index 4570bd2..b8c3685 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -131,7 +131,9 @@ namespace recording {
class base_call;
class function_pointer;
class statement;
+ class extended_asm;
class case_;
+ class top_level_asm;
/* End of recording types. */
}
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 4fac64d..5bccf59 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "opt-suggestions.h"
#include "gcc.h"
#include "diagnostic.h"
+#include "stmt.h"
#include <pthread.h>
@@ -86,6 +87,18 @@ namespace jit {
Playback.
**********************************************************************/
+/* Build a STRING_CST tree for STR, or return NULL if it is NULL.
+ The TREE_TYPE is not initialized. */
+
+static tree
+build_string (const char *str)
+{
+ if (str)
+ return ::build_string (strlen (str), str);
+ else
+ return NULL_TREE;
+}
+
/* The constructor for gcc::jit::playback::context. */
playback::context::context (recording::context *ctxt)
@@ -774,7 +787,7 @@ new_string_literal (const char *value)
tree a_type = build_array_type (char_type_node, i_type);
/* build_string len parameter must include NUL terminator when
building C strings. */
- tree t_str = build_string (len + 1, value);
+ tree t_str = ::build_string (len + 1, value);
TREE_TYPE (t_str) = a_type;
/* Convert to (const char*), loosely based on
@@ -821,6 +834,18 @@ as_truth_value (tree expr, location *loc)
return expr;
}
+/* Add a "top-level" basic asm statement (i.e. one outside of any functions)
+ containing ASM_STMTS.
+
+ Compare with c_parser_asm_definition. */
+
+void
+playback::context::add_top_level_asm (const char *asm_stmts)
+{
+ tree asm_str = build_string (asm_stmts);
+ symtab->finalize_toplevel_asm (asm_str);
+}
+
/* Construct a playback::rvalue instance (wrapping a tree) for a
unary op. */
@@ -1897,6 +1922,104 @@ add_switch (location *loc,
add_stmt (switch_stmt);
}
+/* Convert OPERANDS to a tree-based chain suitable for creating an
+ extended asm stmt.
+ Compare with c_parser_asm_operands. */
+
+static tree
+build_operand_chain (const auto_vec <playback::asm_operand> *operands)
+{
+ tree result = NULL_TREE;
+ unsigned i;
+ playback::asm_operand *asm_op;
+ FOR_EACH_VEC_ELT (*operands, i, asm_op)
+ {
+ tree name = build_string (asm_op->m_asm_symbolic_name);
+ tree str = build_string (asm_op->m_constraint);
+ tree value = asm_op->m_expr;
+ result = chainon (result,
+ build_tree_list (build_tree_list (name, str),
+ value));
+ }
+ return result;
+}
+
+/* Convert CLOBBERS to a tree-based list suitable for creating an
+ extended asm stmt.
+ Compare with c_parser_asm_clobbers. */
+
+static tree
+build_clobbers (const auto_vec <const char *> *clobbers)
+{
+ tree list = NULL_TREE;
+ unsigned i;
+ const char *clobber;
+ FOR_EACH_VEC_ELT (*clobbers, i, clobber)
+ {
+ tree str = build_string (clobber);
+ list = tree_cons (NULL_TREE, str, list);
+ }
+ return list;
+}
+
+/* Convert BLOCKS to a tree-based list suitable for creating an
+ extended asm stmt.
+ Compare with c_parser_asm_goto_operands. */
+
+static tree
+build_goto_operands (const auto_vec <playback::block *> *blocks)
+{
+ tree list = NULL_TREE;
+ unsigned i;
+ playback::block *b;
+ FOR_EACH_VEC_ELT (*blocks, i, b)
+ {
+ tree label = b->as_label_decl ();
+ tree name = build_string (IDENTIFIER_POINTER (DECL_NAME (label)));
+ TREE_USED (label) = 1;
+ list = tree_cons (name, label, list);
+ }
+ return nreverse (list);
+}
+
+/* Add an extended asm statement to this block.
+
+ Compare with c_parser_asm_statement (in c/c-parser.c)
+ and build_asm_expr (in c/c-typeck.c). */
+
+void
+playback::block::add_extended_asm (location *loc,
+ const char *asm_template,
+ bool is_volatile,
+ bool is_inline,
+ const auto_vec <asm_operand> *outputs,
+ const auto_vec <asm_operand> *inputs,
+ const auto_vec <const char *> *clobbers,
+ const auto_vec <block *> *goto_blocks)
+{
+ tree t_string = build_string (asm_template);
+ tree t_outputs = build_operand_chain (outputs);
+ tree t_inputs = build_operand_chain (inputs);
+ tree t_clobbers = build_clobbers (clobbers);
+ tree t_labels = build_goto_operands (goto_blocks);
+ t_string
+ = resolve_asm_operand_names (t_string, t_outputs, t_inputs, t_labels);
+ tree asm_stmt
+ = build5 (ASM_EXPR, void_type_node,
+ t_string, t_outputs, t_inputs, t_clobbers, t_labels);
+
+ /* asm statements without outputs, including simple ones, are treated
+ as volatile. */
+ ASM_VOLATILE_P (asm_stmt) = (outputs->length () == 0);
+ ASM_INPUT_P (asm_stmt) = 0; /* extended asm stmts are not "simple". */
+ ASM_INLINE_P (asm_stmt) = is_inline;
+ if (is_volatile)
+ ASM_VOLATILE_P (asm_stmt) = 1;
+ if (loc)
+ set_tree_location (asm_stmt, loc);
+ add_stmt (asm_stmt);
+}
+
/* Constructor for gcc::jit::playback::block. */
playback::block::
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 50b6975..ff1f778 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -252,6 +252,8 @@ public:
timer *get_timer () const { return m_recording_ctxt->get_timer (); }
+ void add_top_level_asm (const char *asm_stmts);
+
private:
void dump_generated_code ();
@@ -514,6 +516,21 @@ struct case_
block *m_dest_block;
};
+struct asm_operand
+{
+ asm_operand (const char *asm_symbolic_name,
+ const char *constraint,
+ tree expr)
+ : m_asm_symbolic_name (asm_symbolic_name),
+ m_constraint (constraint),
+ m_expr (expr)
+ {}
+
+ const char *m_asm_symbolic_name;
+ const char *m_constraint;
+ tree m_expr;
+};
+
class block : public wrapper
{
public:
@@ -563,6 +580,16 @@ public:
block *default_block,
const auto_vec <case_> *cases);
+ void
+ add_extended_asm (location *loc,
+ const char *asm_template,
+ bool is_volatile,
+ bool is_inline,
+ const auto_vec <asm_operand> *outputs,
+ const auto_vec <asm_operand> *inputs,
+ const auto_vec <const char *> *clobbers,
+ const auto_vec <block *> *goto_blocks);
+
private:
void
set_tree_location (tree t, location *loc)
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 3cbeba0..a237d57 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -724,12 +724,12 @@ recording::context::disassociate_from_playback ()
This creates a fresh copy of the given 0-terminated buffer. */
recording::string *
-recording::context::new_string (const char *text)
+recording::context::new_string (const char *text, bool escaped)
{
if (!text)
return NULL;
- recording::string *result = new string (this, text);
+ recording::string *result = new string (this, text, escaped);
record (result);
return result;
}
@@ -1578,6 +1578,10 @@ recording::context::dump_to_file (const char *path, bool update_locations)
{
fn->write_to_dump (d);
}
+
+ top_level_asm *tla;
+ FOR_EACH_VEC_ELT (m_top_level_asms, i, tla)
+ tla->write_to_dump (d);
}
static const char * const
@@ -1904,6 +1908,22 @@ recording::context::get_all_requested_dumps (vec <recording::requested_dump> *ou
out->splice (m_requested_dumps);
}
+/* Create a recording::top_level_asm instance and add it to this
+ context's list of mementos and to m_top_level_asms.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_add_top_level_asm. */
+
+void
+recording::context::add_top_level_asm (recording::location *loc,
+ const char *asm_stmts)
+{
+ recording::top_level_asm *asm_obj
+ = new recording::top_level_asm (this, loc, new_string (asm_stmts));
+ record (asm_obj);
+ m_top_level_asms.safe_push (asm_obj);
+}
+
/* This is a pre-compilation check for the context (and any parents).
Detect errors within the context, adding errors if any are found. */
@@ -1954,8 +1974,9 @@ recording::memento::write_to_dump (dump &d)
/* Constructor for gcc::jit::recording::string::string, allocating a
copy of the given text using new char[]. */
-recording::string::string (context *ctxt, const char *text)
- : memento (ctxt)
+recording::string::string (context *ctxt, const char *text, bool escaped)
+: memento (ctxt),
+ m_escaped (escaped)
{
m_len = strlen (text);
m_buffer = new char[m_len + 1];
@@ -2005,9 +2026,9 @@ recording::string::from_printf (context *ctxt, const char *fmt, ...)
recording::string *
recording::string::make_debug_string ()
{
- /* Hack to avoid infinite recursion into strings when logging all
- mementos: don't re-escape strings: */
- if (m_buffer[0] == '"')
+ /* Avoid infinite recursion into strings when logging all mementos:
+ don't re-escape strings: */
+ if (m_escaped)
return this;
/* Wrap in quotes and do escaping etc */
@@ -2024,15 +2045,31 @@ recording::string::make_debug_string ()
for (size_t i = 0; i < m_len ; i++)
{
char ch = m_buffer[i];
- if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
- APPEND('\\');
- APPEND(ch);
+ switch (ch)
+ {
+ default:
+ APPEND(ch);
+ break;
+ case '\t':
+ APPEND('\\');
+ APPEND('t');
+ break;
+ case '\n':
+ APPEND('\\');
+ APPEND('n');
+ break;
+ case '\\':
+ case '"':
+ APPEND('\\');
+ APPEND(ch);
+ break;
+ }
}
APPEND('"'); /* closing quote */
#undef APPEND
tmp[len] = '\0'; /* nil termintator */
- string *result = m_ctxt->new_string (tmp);
+ string *result = m_ctxt->new_string (tmp, true);
delete[] tmp;
return result;
@@ -4001,8 +4038,8 @@ recording::function::dump_to_dot (const char *path)
pretty_printer *pp = &the_pp;
- pp_printf (pp,
- "digraph %s {\n", get_debug_string ());
+ pp_printf (pp, "digraph %s", get_debug_string ());
+ pp_string (pp, " {\n");
/* Blocks: */
{
@@ -4020,7 +4057,7 @@ recording::function::dump_to_dot (const char *path)
b->dump_edges_to_dot (pp);
}
- pp_printf (pp, "}\n");
+ pp_string (pp, "}\n");
pp_flush (pp);
fclose (fp);
}
@@ -4189,6 +4226,23 @@ recording::block::add_comment (recording::location *loc,
return result;
}
+/* Create a recording::extended_asm_simple instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the heart of gcc_jit_block_add_extended_asm. */
+
+recording::extended_asm *
+recording::block::add_extended_asm (location *loc,
+ const char *asm_template)
+{
+ extended_asm *result
+ = new extended_asm_simple (this, loc, new_string (asm_template));
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ return result;
+}
+
/* Create a recording::end_with_conditional instance and add it to
the block's context's list of mementos, and to the block's
list of statements.
@@ -4271,6 +4325,30 @@ recording::block::end_with_switch (recording::location *loc,
return result;
}
+/* Create a recording::extended_asm_goto instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the heart of gcc_jit_block_end_with_extended_asm_goto. */
+
+
+recording::extended_asm *
+recording::block::end_with_extended_asm_goto (location *loc,
+ const char *asm_template,
+ int num_goto_blocks,
+ block **goto_blocks,
+ block *fallthrough_block)
+{
+ extended_asm *result
+ = new extended_asm_goto (this, loc, new_string (asm_template),
+ num_goto_blocks, goto_blocks,
+ fallthrough_block);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ m_has_been_terminated = true;
+ return result;
+}
+
/* Override the default implementation of
recording::memento::write_to_dump for blocks by writing
an unindented block name as a label, followed by the indented
@@ -4401,6 +4479,14 @@ recording::block::write_reproducer (reproducer &r)
m_name ? m_name->get_debug_string () : "NULL");
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the pp_printf calls. Their format strings deliberately don't
+ follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Dump a block in graphviz form into PP, capturing the block name (if
any) and the statements. */
@@ -4429,7 +4515,7 @@ recording::block::dump_to_dot (pretty_printer *pp)
pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
}
- pp_printf (pp,
+ pp_string (pp,
"}\"];\n\n");
pp_flush (pp);
}
@@ -4449,6 +4535,10 @@ recording::block::dump_edges_to_dot (pretty_printer *pp)
successors.release ();
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
+
/* The implementation of class gcc::jit::recording::global. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -6491,6 +6581,459 @@ recording::switch_::write_reproducer (reproducer &r)
cases_id);
}
+/* class asm_operand : public memento. */
+
+recording::asm_operand::asm_operand (extended_asm *ext_asm,
+ string *asm_symbolic_name,
+ string *constraint)
+: memento (ext_asm->get_context ()),
+ m_ext_asm (ext_asm),
+ m_asm_symbolic_name (asm_symbolic_name),
+ m_constraint (constraint)
+{
+}
+
+void
+recording::asm_operand::print (pretty_printer *pp) const
+{
+ if (m_asm_symbolic_name)
+ {
+ pp_character (pp, '[');
+ pp_string (pp, m_asm_symbolic_name->c_str ());
+ pp_character (pp, ']');
+ pp_space (pp);
+ }
+ pp_string (pp, m_constraint->get_debug_string ());
+ /* Subclass will add lvalue/rvalue. */
+}
+
+recording::string *
+recording::asm_operand::make_debug_string ()
+{
+ pretty_printer pp;
+ print (&pp);
+ return m_ctxt->new_string (pp_formatted_text (&pp), false);
+}
+
+/* class output_asm_operand : public asm_operand. */
+
+void
+recording::output_asm_operand::write_reproducer (reproducer &r)
+{
+ const char *fmt =
+ " gcc_jit_extended_asm_add_output_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
+ " %s, /* const char *asm_symbolic_name */\n"
+ " %s, /* const char *constraint */\n"
+ " %s); /* gcc_jit_lvalue *dest */\n";
+ r.write (fmt,
+ r.get_identifier (m_ext_asm),
+ (m_asm_symbolic_name
+ ? m_asm_symbolic_name->get_debug_string () : "NULL"),
+ m_constraint->get_debug_string (),
+ r.get_identifier (m_dest));
+}
+
+void
+recording::output_asm_operand::print (pretty_printer *pp) const
+{
+ asm_operand::print (pp);
+ pp_string (pp, " (");
+ pp_string (pp, m_dest->get_debug_string ());
+ pp_string (pp, ")");
+}
+
+/* class input_asm_operand : public asm_operand. */
+
+void
+recording::input_asm_operand::write_reproducer (reproducer &r)
+{
+ const char *fmt =
+ " gcc_jit_extended_asm_add_input_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
+ " %s, /* const char *asm_symbolic_name */\n"
+ " %s, /* const char *constraint */\n"
+ " %s); /* gcc_jit_rvalue *src */\n";
+ r.write (fmt,
+ r.get_identifier (m_ext_asm),
+ (m_asm_symbolic_name
+ ? m_asm_symbolic_name->get_debug_string () : "NULL"),
+ m_constraint->get_debug_string (),
+ r.get_identifier_as_rvalue (m_src));
+}
+
+void
+recording::input_asm_operand::print (pretty_printer *pp) const
+{
+ asm_operand::print (pp);
+ pp_string (pp, " (");
+ pp_string (pp, m_src->get_debug_string ());
+ pp_string (pp, ")");
+}
+
+/* The implementation of class gcc::jit::recording::extended_asm. */
+
+void
+recording::extended_asm::add_output_operand (const char *asm_symbolic_name,
+ const char *constraint,
+ lvalue *dest)
+{
+ output_asm_operand *op
+ = new output_asm_operand (this,
+ new_string (asm_symbolic_name),
+ new_string (constraint),
+ dest);
+ m_ctxt->record (op);
+ m_output_ops.safe_push (op);
+}
+
+void
+recording::extended_asm::add_input_operand (const char *asm_symbolic_name,
+ const char *constraint,
+ rvalue *src)
+{
+ input_asm_operand *op
+ = new input_asm_operand (this,
+ new_string (asm_symbolic_name),
+ new_string (constraint),
+ src);
+ m_ctxt->record (op);
+ m_input_ops.safe_push (op);
+}
+
+void
+recording::extended_asm::add_clobber (const char *victim)
+{
+ m_clobbers.safe_push (new_string (victim));
+}
+
+/* Implementation of recording::memento::replay_into
+ for recording::extended_asm. */
+
+void
+recording::extended_asm::replay_into (replayer *r)
+{
+ auto_vec<playback::asm_operand> playback_output_ops;
+ auto_vec<playback::asm_operand> playback_input_ops;
+ auto_vec<const char *> playback_clobbers;
+ auto_vec<playback::block *> playback_goto_blocks;
+
+ /* Populate outputs. */
+ {
+ output_asm_operand *rec_asm_op;
+ unsigned i;
+ FOR_EACH_VEC_ELT (m_output_ops, i, rec_asm_op)
+ {
+ playback::asm_operand playback_asm_op
+ (rec_asm_op->get_symbolic_name (),
+ rec_asm_op->get_constraint (),
+ rec_asm_op->get_lvalue ()->playback_lvalue ()->as_tree ());
+ playback_output_ops.safe_push (playback_asm_op);
+ }
+ }
+
+ /* Populate inputs. */
+ {
+ input_asm_operand *rec_asm_op;
+ unsigned i;
+ FOR_EACH_VEC_ELT (m_input_ops, i, rec_asm_op)
+ {
+ playback::asm_operand playback_asm_op
+ (rec_asm_op->get_symbolic_name (),
+ rec_asm_op->get_constraint (),
+ rec_asm_op->get_rvalue ()->playback_rvalue ()->as_tree ());
+ playback_input_ops.safe_push (playback_asm_op);
+ }
+ }
+
+ /* Populate clobbers. */
+ {
+ string *rec_clobber;
+ unsigned i;
+ FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
+ playback_clobbers.safe_push (rec_clobber->c_str ());
+ }
+
+ /* Populate playback blocks if an "asm goto". */
+ maybe_populate_playback_blocks (&playback_goto_blocks);
+
+ playback_block (get_block ())
+ ->add_extended_asm (playback_location (r),
+ m_asm_template->c_str (),
+ m_is_volatile, m_is_inline,
+ &playback_output_ops,
+ &playback_input_ops,
+ &playback_clobbers,
+ &playback_goto_blocks);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ an extended_asm "statement". */
+
+recording::string *
+recording::extended_asm::make_debug_string ()
+{
+ pretty_printer pp;
+ pp_string (&pp, "asm ");
+ if (m_is_volatile)
+ pp_string (&pp, "volatile ");
+ if (m_is_inline)
+ pp_string (&pp, "inline ");
+ if (is_goto ())
+ pp_string (&pp, "goto ");
+ pp_character (&pp, '(');
+ pp_string (&pp, m_asm_template->get_debug_string ());
+ pp_string (&pp, " : ");
+ unsigned i;
+ {
+ output_asm_operand *asm_op;
+ FOR_EACH_VEC_ELT (m_output_ops, i, asm_op)
+ {
+ if (i > 0)
+ pp_string (&pp, ", ");
+ asm_op->print (&pp);
+ }
+ }
+ pp_string (&pp, " : ");
+ {
+ input_asm_operand *asm_op;
+ FOR_EACH_VEC_ELT (m_input_ops, i, asm_op)
+ {
+ if (i > 0)
+ pp_string (&pp, ", ");
+ asm_op->print (&pp);
+ }
+ }
+ pp_string (&pp, " : ");
+ string *rec_clobber;
+ FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
+ {
+ if (i > 0)
+ pp_string (&pp, ", ");
+ pp_string (&pp, rec_clobber->get_debug_string ());
+ }
+ maybe_print_gotos (&pp);
+ pp_character (&pp, ')');
+ return new_string (pp_formatted_text (&pp));
+}
+
+void
+recording::extended_asm::write_flags (reproducer &r)
+{
+ if (m_is_volatile)
+ r.write (" gcc_jit_extended_asm_set_volatile_flag (%s, 1);\n",
+ r.get_identifier (this));
+ if (m_is_inline)
+ r.write (" gcc_jit_extended_asm_set_inline_flag (%s, 1);\n",
+ r.get_identifier (this));
+}
+
+void
+recording::extended_asm::write_clobbers (reproducer &r)
+{
+ string *clobber;
+ unsigned i;
+ FOR_EACH_VEC_ELT (m_clobbers, i, clobber)
+ r.write (" gcc_jit_extended_asm_add_clobber (%s, %s);\n",
+ r.get_identifier (this),
+ clobber->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ extended_asm_simple. */
+
+void
+recording::extended_asm_simple::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "extended_asm");
+ r.write (" gcc_jit_extended_asm *%s =\n"
+ " gcc_jit_block_add_extended_asm (%s, /*gcc_jit_block *block */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s); /* const char *asm_template */\n",
+ id,
+ r.get_identifier (get_block ()),
+ r.get_identifier (get_loc ()),
+ m_asm_template->get_debug_string ());
+ write_flags (r);
+ write_clobbers (r);
+}
+
+void
+recording::extended_asm::
+maybe_populate_playback_blocks (auto_vec <playback::block *> *)
+{
+ /* Do nothing; not an "asm goto". */
+}
+
+/* The implementation of class gcc::jit::recording::extended_asm_goto. */
+
+/* recording::extended_asm_goto's ctor. */
+
+recording::extended_asm_goto::extended_asm_goto (block *b,
+ location *loc,
+ string *asm_template,
+ int num_goto_blocks,
+ block **goto_blocks,
+ block *fallthrough_block)
+: extended_asm (b, loc, asm_template),
+ m_goto_blocks (num_goto_blocks),
+ m_fallthrough_block (fallthrough_block)
+{
+ for (int i = 0; i < num_goto_blocks; i++)
+ m_goto_blocks.quick_push (goto_blocks[i]);
+}
+
+/* Implementation of recording::memento::replay_into
+ for recording::extended_asm_goto. */
+
+void
+recording::extended_asm_goto::replay_into (replayer *r)
+{
+ /* Chain up to base class impl. */
+ recording::extended_asm::replay_into (r);
+
+ /* ...and potentially add a goto for the fallthrough. */
+ if (m_fallthrough_block)
+ playback_block (get_block ())
+ ->add_jump (playback_location (r),
+ m_fallthrough_block->playback_block ());
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ extended_asm_goto. */
+
+void
+recording::extended_asm_goto::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "extended_asm");
+ const char *blocks_id = r.make_tmp_identifier ("blocks_for", this);
+ r.write (" gcc_jit_block *%s[%i] = {\n",
+ blocks_id,
+ m_goto_blocks.length ());
+ int i;
+ block *b;
+ FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
+ r.write (" %s,\n", r.get_identifier (b));
+ r.write (" };\n");
+ r.write (" gcc_jit_extended_asm *%s =\n"
+ " gcc_jit_block_end_with_extended_asm_goto (%s, /*gcc_jit_block *block */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* const char *asm_template */\n"
+ " %i, /* int num_goto_blocks */\n"
+ " %s, /* gcc_jit_block **goto_blocks */\n"
+ " %s); /* gcc_jit_block *fallthrough_block */\n",
+ id,
+ r.get_identifier (get_block ()),
+ r.get_identifier (get_loc ()),
+ m_asm_template->get_debug_string (),
+ m_goto_blocks.length (),
+ blocks_id,
+ (m_fallthrough_block
+ ? r.get_identifier (m_fallthrough_block)
+ : "NULL"));
+ write_flags (r);
+ write_clobbers (r);
+}
+
+/* Override the poisoned default implementation of
+ gcc::jit::recording::statement::get_successor_blocks
+
+ An extended_asm_goto can jump to the m_goto_blocks, and to
+ the (optional) m_fallthrough_block. */
+
+vec <recording::block *>
+recording::extended_asm_goto::get_successor_blocks () const
+{
+ vec <block *> result;
+ result.create (m_goto_blocks.length () + 1);
+ if (m_fallthrough_block)
+ result.quick_push (m_fallthrough_block);
+ result.splice (m_goto_blocks);
+ return result;
+}
+
+/* Vfunc for use by recording::extended_asm::make_debug_string. */
+
+void
+recording::extended_asm_goto::maybe_print_gotos (pretty_printer *pp) const
+{
+ pp_string (pp, " : ");
+ unsigned i;
+ block *b;
+ FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
+ {
+ if (i > 0)
+ pp_string (pp, ", ");
+ pp_string (pp, b->get_debug_string ());
+ }
+ /* Non-C syntax here. */
+ if (m_fallthrough_block)
+ pp_printf (pp, " [fallthrough: %s]",
+ m_fallthrough_block->get_debug_string ());
+}
+
+/* Vfunc for use by recording::extended_asm::replay_into. */
+
+void
+recording::extended_asm_goto::
+maybe_populate_playback_blocks (auto_vec <playback::block *> *out)
+{
+ unsigned i;
+ block *b;
+ FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
+ out->safe_push (b->playback_block ());
+}
+
+/* class top_level_asm : public memento. */
+
+recording::top_level_asm::top_level_asm (context *ctxt,
+ location *loc,
+ string *asm_stmts)
+: memento (ctxt),
+ m_loc (loc),
+ m_asm_stmts (asm_stmts)
+{
+}
+
+/* Implementation of recording::memento::replay_into for top-level asm. */
+
+void
+recording::top_level_asm::replay_into (replayer *r)
+{
+ r->add_top_level_asm (m_asm_stmts->c_str ());
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ top-level asm. */
+
+recording::string *
+recording::top_level_asm::make_debug_string ()
+{
+ return string::from_printf (m_ctxt, "asm (%s)",
+ m_asm_stmts->get_debug_string ());
+}
+
+/* Override the default implementation of
+ recording::memento::write_to_dump.
+ Don't indent the string. */
+
+void
+recording::top_level_asm::write_to_dump (dump &d)
+{
+ d.write ("%s;\n", get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for top-level asm. */
+
+void
+recording::top_level_asm::write_reproducer (reproducer &r)
+{
+ r.write (" gcc_jit_context_add_top_level_asm (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s); /* const char *asm_stmts */\n",
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ m_asm_stmts->get_debug_string ());
+}
+
} // namespace gcc::jit
} // namespace gcc
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 30e37af..e694882 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -74,7 +74,7 @@ public:
void disassociate_from_playback ();
string *
- new_string (const char *text);
+ new_string (const char *text, bool escaped = false);
location *
new_location (const char *filename,
@@ -301,6 +301,8 @@ public:
void set_timer (timer *t) { m_timer = t; }
timer *get_timer () const { return m_timer; }
+ void add_top_level_asm (location *loc, const char *asm_stmts);
+
private:
void log_all_options () const;
void log_str_option (enum gcc_jit_str_option opt) const;
@@ -344,6 +346,7 @@ private:
auto_vec<compound_type *> m_compound_types;
auto_vec<global *> m_globals;
auto_vec<function *> m_functions;
+ auto_vec<top_level_asm *> m_top_level_asms;
type *m_basic_types[NUM_GCC_JIT_TYPES];
type *m_FILE_type;
@@ -414,7 +417,7 @@ private:
class string : public memento
{
public:
- string (context *ctxt, const char *text);
+ string (context *ctxt, const char *text, bool escaped);
~string ();
const char *c_str () { return m_buffer; }
@@ -431,6 +434,11 @@ private:
private:
size_t m_len;
char *m_buffer;
+
+ /* Flag to track if this string is the result of string::make_debug_string,
+ to avoid infinite recursion when logging all mementos: don't re-escape
+ such strings. */
+ bool m_escaped;
};
class location : public memento
@@ -1270,6 +1278,10 @@ public:
add_comment (location *loc,
const char *text);
+ extended_asm *
+ add_extended_asm (location *loc,
+ const char *asm_template);
+
statement *
end_with_conditional (location *loc,
rvalue *boolval,
@@ -1291,6 +1303,13 @@ public:
int num_cases,
case_ **cases);
+ extended_asm *
+ end_with_extended_asm_goto (location *loc,
+ const char *asm_template,
+ int num_goto_blocks,
+ block **goto_blocks,
+ block *fallthrough_block);
+
playback::block *
playback_block () const
{
@@ -2107,6 +2126,207 @@ private:
auto_vec <case_ *> m_cases;
};
+class asm_operand : public memento
+{
+public:
+ asm_operand (extended_asm *ext_asm,
+ string *asm_symbolic_name,
+ string *constraint);
+
+ const char *get_symbolic_name () const
+ {
+ if (m_asm_symbolic_name)
+ return m_asm_symbolic_name->c_str ();
+ else
+ return NULL;
+ }
+
+ const char *get_constraint () const
+ {
+ return m_constraint->c_str ();
+ }
+
+ virtual void print (pretty_printer *pp) const;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+
+protected:
+ extended_asm *m_ext_asm;
+ string *m_asm_symbolic_name;
+ string *m_constraint;
+};
+
+class output_asm_operand : public asm_operand
+{
+public:
+ output_asm_operand (extended_asm *ext_asm,
+ string *asm_symbolic_name,
+ string *constraint,
+ lvalue *dest)
+ : asm_operand (ext_asm, asm_symbolic_name, constraint),
+ m_dest (dest)
+ {}
+
+ lvalue *get_lvalue () const { return m_dest; }
+
+ void replay_into (replayer *) FINAL OVERRIDE {}
+
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+private:
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+ lvalue *m_dest;
+};
+
+class input_asm_operand : public asm_operand
+{
+public:
+ input_asm_operand (extended_asm *ext_asm,
+ string *asm_symbolic_name,
+ string *constraint,
+ rvalue *src)
+ : asm_operand (ext_asm, asm_symbolic_name, constraint),
+ m_src (src)
+ {}
+
+ rvalue *get_rvalue () const { return m_src; }
+
+ void replay_into (replayer *) FINAL OVERRIDE {}
+
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+private:
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+ rvalue *m_src;
+};
+
+/* Abstract base class for extended_asm statements. */
+
+class extended_asm : public statement
+{
+public:
+ extended_asm (block *b,
+ location *loc,
+ string *asm_template)
+ : statement (b, loc),
+ m_asm_template (asm_template),
+ m_is_volatile (false),
+ m_is_inline (false)
+ {}
+
+ void set_volatile_flag (bool flag) { m_is_volatile = flag; }
+ void set_inline_flag (bool flag) { m_is_inline = flag; }
+
+ void add_output_operand (const char *asm_symbolic_name,
+ const char *constraint,
+ lvalue *dest);
+ void add_input_operand (const char *asm_symbolic_name,
+ const char *constraint,
+ rvalue *src);
+ void add_clobber (const char *victim);
+
+ void replay_into (replayer *r) OVERRIDE;
+
+ string *get_asm_template () const { return m_asm_template; }
+
+ virtual bool is_goto () const = 0;
+ virtual void maybe_print_gotos (pretty_printer *) const = 0;
+
+protected:
+ void write_flags (reproducer &r);
+ void write_clobbers (reproducer &r);
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ virtual void maybe_populate_playback_blocks
+ (auto_vec <playback::block *> *out) = 0;
+
+protected:
+ string *m_asm_template;
+ bool m_is_volatile;
+ bool m_is_inline;
+ auto_vec<output_asm_operand *> m_output_ops;
+ auto_vec<input_asm_operand *> m_input_ops;
+ auto_vec<string *> m_clobbers;
+};
+
+/* An extended_asm that's not a goto, as created by
+ gcc_jit_block_add_extended_asm. */
+
+class extended_asm_simple : public extended_asm
+{
+public:
+ extended_asm_simple (block *b,
+ location *loc,
+ string *asm_template)
+ : extended_asm (b, loc, asm_template)
+ {}
+
+ void write_reproducer (reproducer &r) OVERRIDE;
+ bool is_goto () const FINAL OVERRIDE { return false; }
+ void maybe_print_gotos (pretty_printer *) const FINAL OVERRIDE {}
+
+private:
+ void maybe_populate_playback_blocks
+ (auto_vec <playback::block *> *) FINAL OVERRIDE
+ {}
+};
+
+/* An extended_asm that's a asm goto, as created by
+ gcc_jit_block_end_with_extended_asm_goto. */
+
+class extended_asm_goto : public extended_asm
+{
+public:
+ extended_asm_goto (block *b,
+ location *loc,
+ string *asm_template,
+ int num_goto_blocks,
+ block **goto_blocks,
+ block *fallthrough_block);
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) OVERRIDE;
+
+ vec <block *> get_successor_blocks () const FINAL OVERRIDE;
+
+ bool is_goto () const FINAL OVERRIDE { return true; }
+ void maybe_print_gotos (pretty_printer *) const FINAL OVERRIDE;
+
+private:
+ void maybe_populate_playback_blocks
+ (auto_vec <playback::block *> *out) FINAL OVERRIDE;
+
+private:
+ auto_vec <block *> m_goto_blocks;
+ block *m_fallthrough_block;
+};
+
+/* A group of top-level asm statements, as created by
+ gcc_jit_context_add_top_level_asm. */
+
+class top_level_asm : public memento
+{
+public:
+ top_level_asm (context *ctxt, location *loc, string *asm_stmts);
+
+ void write_to_dump (dump &d) FINAL OVERRIDE;
+
+private:
+ void replay_into (replayer *r) FINAL OVERRIDE;
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+ location *m_loc;
+ string *m_asm_stmts;
+};
+
} // namespace gcc::jit::recording
/* Create a recording::memento_of_new_rvalue_from_const instance and add
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 1b9ef1a..b4901ce 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -46,6 +46,7 @@ namespace gccjit
class lvalue;
class param;
class case_;
+ class extended_asm;
class timer;
class auto_time;
@@ -316,6 +317,9 @@ namespace gccjit
rvalue max_value,
block dest_block);
+ void add_top_level_asm (const char *asm_stmts,
+ location loc = location ());
+
private:
gcc_jit_context *m_inner_ctxt;
};
@@ -449,6 +453,13 @@ namespace gccjit
block default_block,
std::vector <case_> cases,
location loc = location ());
+
+ extended_asm add_extended_asm (const std::string &asm_template,
+ location loc = location ());
+ extended_asm end_with_extended_asm_goto (const std::string &asm_template,
+ std::vector<block> goto_blocks,
+ block *fallthrough_block,
+ location loc = location ());
};
class rvalue : public object
@@ -509,6 +520,40 @@ namespace gccjit
gcc_jit_case *get_inner_case () const;
};
+ class extended_asm : public object
+ {
+ public:
+ extended_asm ();
+ extended_asm (gcc_jit_extended_asm *inner);
+
+ extended_asm &
+ set_volatile_flag (bool flag);
+
+ extended_asm &
+ set_inline_flag (bool flag);
+
+ extended_asm&
+ add_output_operand (const std::string &asm_symbolic_name,
+ const std::string &constraint,
+ gccjit::lvalue dest);
+ extended_asm&
+ add_output_operand (const std::string &constraint,
+ gccjit::lvalue dest);
+
+ extended_asm&
+ add_input_operand (const std::string &asm_symbolic_name,
+ const std::string &constraint,
+ gccjit::rvalue src);
+ extended_asm&
+ add_input_operand (const std::string &constraint,
+ gccjit::rvalue src);
+
+ extended_asm&
+ add_clobber (const std::string &victim);
+
+ gcc_jit_extended_asm *get_inner_extended_asm () const;
+ };
+
/* Overloaded operators, for those who want the most terse API
(at the possible risk of being a little too magical).
@@ -1259,6 +1304,14 @@ context::new_case (rvalue min_value,
dest_block.get_inner_block ()));
}
+inline void
+context::add_top_level_asm (const char *asm_stmts, location loc)
+{
+ gcc_jit_context_add_top_level_asm (m_inner_ctxt,
+ loc.get_inner_location (),
+ asm_stmts);
+}
+
// class object
inline context
object::get_context () const
@@ -1554,6 +1607,37 @@ block::end_with_switch (rvalue expr,
as_array_of_ptrs);
}
+inline extended_asm
+block::add_extended_asm (const std::string &asm_template,
+ location loc)
+{
+ return gcc_jit_block_add_extended_asm (get_inner_block (),
+ loc.get_inner_location (),
+ asm_template.c_str ());
+}
+
+inline extended_asm
+block::end_with_extended_asm_goto (const std::string &asm_template,
+ std::vector<block> goto_blocks,
+ block *fallthrough_block,
+ location loc)
+{
+ /* Treat std::vector as an array, relying on it not being resized: */
+ block *as_array_of_wrappers = &goto_blocks[0];
+
+ /* Treat the array as being of the underlying pointers, relying on
+ the wrapper type being such a pointer internally. */
+ gcc_jit_block **as_array_of_ptrs =
+ reinterpret_cast<gcc_jit_block **> (as_array_of_wrappers);
+ return gcc_jit_block_end_with_extended_asm_goto
+ (get_inner_block (),
+ loc.get_inner_location (),
+ asm_template.c_str (),
+ goto_blocks.size (),
+ as_array_of_ptrs,
+ fallthrough_block ? fallthrough_block->get_inner_block () : NULL);
+}
+
inline rvalue
block::add_call (function other,
location loc)
@@ -1767,6 +1851,92 @@ case_::get_inner_case () const
return reinterpret_cast<gcc_jit_case *> (get_inner_object ());
}
+// class extended_asm : public object
+inline extended_asm::extended_asm () : object () {}
+inline extended_asm::extended_asm (gcc_jit_extended_asm *inner)
+ : object (gcc_jit_extended_asm_as_object (inner))
+{
+}
+
+inline extended_asm&
+extended_asm::set_volatile_flag (bool flag)
+{
+ gcc_jit_extended_asm_set_volatile_flag (get_inner_extended_asm (), flag);
+ return *this;
+}
+
+inline extended_asm&
+extended_asm::set_inline_flag (bool flag)
+{
+ gcc_jit_extended_asm_set_inline_flag (get_inner_extended_asm (), flag);
+ return *this;
+}
+
+inline extended_asm&
+extended_asm::add_output_operand (const std::string &asm_symbolic_name,
+ const std::string &constraint,
+ gccjit::lvalue dest)
+{
+ gcc_jit_extended_asm_add_output_operand
+ (get_inner_extended_asm (),
+ asm_symbolic_name.c_str (),
+ constraint.c_str (),
+ dest.get_inner_lvalue ());
+ return *this;
+}
+
+inline extended_asm&
+extended_asm::add_output_operand (const std::string &constraint,
+ gccjit::lvalue dest)
+{
+ gcc_jit_extended_asm_add_output_operand
+ (get_inner_extended_asm (),
+ NULL, /* asm_symbolic_name */
+ constraint.c_str (),
+ dest.get_inner_lvalue ());
+ return *this;
+}
+
+inline extended_asm&
+extended_asm::add_input_operand (const std::string &asm_symbolic_name,
+ const std::string &constraint,
+ gccjit::rvalue src)
+{
+ gcc_jit_extended_asm_add_input_operand
+ (get_inner_extended_asm (),
+ asm_symbolic_name.c_str (),
+ constraint.c_str (),
+ src.get_inner_rvalue ());
+ return *this;
+}
+
+inline extended_asm&
+extended_asm::add_input_operand (const std::string &constraint,
+ gccjit::rvalue src)
+{
+ gcc_jit_extended_asm_add_input_operand
+ (get_inner_extended_asm (),
+ NULL, /* asm_symbolic_name */
+ constraint.c_str (),
+ src.get_inner_rvalue ());
+ return *this;
+}
+
+inline extended_asm&
+extended_asm::add_clobber (const std::string &victim)
+{
+ gcc_jit_extended_asm_add_clobber (get_inner_extended_asm (),
+ victim.c_str ());
+ return *this;
+}
+
+inline gcc_jit_extended_asm *
+extended_asm::get_inner_extended_asm () const
+{
+ /* Manual downcast: */
+ return reinterpret_cast<gcc_jit_extended_asm *> (get_inner_object ());
+}
+
/* Overloaded operators. */
// Unary operators
inline rvalue operator- (rvalue a)
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index a00aefc..f9c33c6 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -96,6 +96,11 @@ struct gcc_jit_timer : public timer
{
};
+struct gcc_jit_extended_asm : public gcc::jit::recording::extended_asm
+{
+};
+
+
/**********************************************************************
Error-handling.
@@ -300,13 +305,13 @@ struct gcc_jit_timer : public timer
static void
jit_error (gcc::jit::recording::context *ctxt,
- gcc_jit_location *loc,
+ gcc::jit::recording::location *loc,
const char *fmt, ...)
GNU_PRINTF(3, 4);
static void
jit_error (gcc::jit::recording::context *ctxt,
- gcc_jit_location *loc,
+ gcc::jit::recording::location *loc,
const char *fmt, ...)
{
va_list ap;
@@ -3290,3 +3295,182 @@ gcc_jit_version_patchlevel (void)
version_info vi;
return vi.patchlevel;
}
+
+/**********************************************************************
+ Asm support.
+ **********************************************************************/
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::block::add_extended_asm, in
+ jit-recording.c. */
+
+gcc_jit_extended_asm *
+gcc_jit_block_add_extended_asm (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ const char *asm_template)
+{
+ RETURN_NULL_IF_NOT_VALID_BLOCK (block, loc);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (asm_template, ctxt, loc, "NULL asm_template");
+
+ return (gcc_jit_extended_asm *)block->add_extended_asm (loc, asm_template);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::block::end_with_extended_asm_goto, in
+ jit-recording.c. */
+
+gcc_jit_extended_asm *
+gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ const char *asm_template,
+ int num_goto_blocks,
+ gcc_jit_block **goto_blocks,
+ gcc_jit_block *fallthrough_block)
+{
+ RETURN_NULL_IF_NOT_VALID_BLOCK (block, loc);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (asm_template, ctxt, loc, "NULL asm_template");
+ RETURN_NULL_IF_FAIL (num_goto_blocks >= 0, ctxt, loc, "num_goto_blocks < 0");
+ for (int i = 0; i < num_goto_blocks; i++)
+ RETURN_NULL_IF_FAIL_PRINTF1 (goto_blocks[i],
+ ctxt, loc,
+ "NULL goto_blocks[%i]", i);
+ /* fallthrough_block can be NULL. */
+ return (gcc_jit_extended_asm *)block->end_with_extended_asm_goto
+ (loc, asm_template,
+ num_goto_blocks, (gcc::jit::recording::block **)goto_blocks,
+ fallthrough_block);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, this calls the trivial
+ gcc::jit::recording::memento::as_object method (an extended_asm is a
+ memento), in jit-recording.h. */
+
+gcc_jit_object *
+gcc_jit_extended_asm_as_object (gcc_jit_extended_asm *ext_asm)
+{
+ RETURN_NULL_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm");
+
+ return static_cast <gcc_jit_object *> (ext_asm->as_object ());
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::extended_asm::set_volatile_flag, in
+ jit-recording.c. */
+
+void
+gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm *ext_asm,
+ int flag)
+{
+ RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm");
+ ext_asm->set_volatile_flag (flag);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::extended_asm::set_inline_flag, in
+ jit-recording.c. */
+
+void
+gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm *ext_asm,
+ int flag)
+{
+ RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm");
+ ext_asm->set_inline_flag (flag);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::extended_asm::add_output_operand, in
+ jit-recording.c. */
+
+void
+gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm *ext_asm,
+ const char *asm_symbolic_name,
+ const char *constraint,
+ gcc_jit_lvalue *dest)
+{
+ RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm");
+ gcc::jit::recording::context *ctxt = ext_asm->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ gcc::jit::recording::location *loc = ext_asm->get_loc ();
+ /* asm_symbolic_name can be NULL. */
+ RETURN_IF_FAIL (constraint, ctxt, loc, "NULL constraint");
+ RETURN_IF_FAIL (dest, ctxt, loc, "NULL dest");
+ RETURN_IF_FAIL (!ext_asm->is_goto (), ctxt, loc,
+ "cannot add output operand to asm goto");
+ ext_asm->add_output_operand (asm_symbolic_name, constraint, dest);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::extended_asm::add_input_operand, in
+ jit-recording.c. */
+
+extern void
+gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm *ext_asm,
+ const char *asm_symbolic_name,
+ const char *constraint,
+ gcc_jit_rvalue *src)
+{
+ RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm");
+ gcc::jit::recording::context *ctxt = ext_asm->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ gcc::jit::recording::location *loc = ext_asm->get_loc ();
+ /* asm_symbolic_name can be NULL. */
+ RETURN_IF_FAIL (constraint, ctxt, loc, "NULL constraint");
+ RETURN_IF_FAIL (src, ctxt, loc, "NULL src");
+ ext_asm->add_input_operand (asm_symbolic_name, constraint, src);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::extended_asm::add_clobber, in
+ jit-recording.c. */
+
+void
+gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm *ext_asm,
+ const char *victim)
+{
+ RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm");
+ gcc::jit::recording::context *ctxt = ext_asm->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ gcc::jit::recording::location *loc = ext_asm->get_loc ();
+ RETURN_IF_FAIL (victim, ctxt, loc, "NULL victim");
+ ext_asm->add_clobber (victim);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::add_top_level_asm, in
+ jit-recording.c. */
+
+void
+gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ const char *asm_stmts)
+{
+ RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_IF_FAIL (asm_stmts, ctxt, NULL, "NULL asm_stmts");
+ ctxt->add_top_level_asm (loc, asm_stmts);
+}
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 7134841..c523f93 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -68,6 +68,7 @@ typedef struct gcc_jit_result gcc_jit_result;
+- gcc_jit_lvalue
+- gcc_jit_param
+- gcc_jit_case
+ +- gcc_jit_extended_asm
*/
typedef struct gcc_jit_object gcc_jit_object;
@@ -138,6 +139,12 @@ typedef struct gcc_jit_param gcc_jit_param;
destination block. */
typedef struct gcc_jit_case gcc_jit_case;
+/* A gcc_jit_extended_asm represents an assembly language statement,
+ analogous to an extended "asm" statement in GCC's C front-end: a series
+ of low-level instructions inside a function that convert inputs to
+ outputs. */
+typedef struct gcc_jit_extended_asm gcc_jit_extended_asm;
+
/* Acquire a JIT-compilation context. */
extern gcc_jit_context *
gcc_jit_context_acquire (void);
@@ -1504,7 +1511,7 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
#define LIBGCCJIT_HAVE_gcc_jit_version
-/* Functions to retrive libgccjit version.
+/* Functions to retrieve libgccjit version.
Analogous to __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ in C code.
These API entrypoints were added in LIBGCCJIT_ABI_13; you can test for their
@@ -1518,6 +1525,102 @@ gcc_jit_version_minor (void);
extern int
gcc_jit_version_patchlevel (void);
+/**********************************************************************
+ Asm support.
+ **********************************************************************/
+
+/* Functions for adding inline assembler code, analogous to GCC's
+ "extended asm" syntax.
+
+ See https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html
+
+ These API entrypoints were added in LIBGCCJIT_ABI_15; you can test for their
+ presence using
+ #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
+*/
+
+#define LIBGCCJIT_HAVE_ASM_STATEMENTS
+
+/* Create a gcc_jit_extended_asm for an extended asm statement
+ with no control flow (i.e. without the goto qualifier).
+
+ The asm_template parameter corresponds to the AssemblerTemplate
+ within C's extended asm syntax. It must be non-NULL. */
+
+extern gcc_jit_extended_asm *
+gcc_jit_block_add_extended_asm (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ const char *asm_template);
+
+/* Create a gcc_jit_extended_asm for an extended asm statement
+ that may perform jumps, and use it to terminate the given block.
+ This is equivalent to the "goto" qualifier in C's extended asm
+ syntax. */
+
+extern gcc_jit_extended_asm *
+gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ const char *asm_template,
+ int num_goto_blocks,
+ gcc_jit_block **goto_blocks,
+ gcc_jit_block *fallthrough_block);
+
+/* Upcasting from extended asm to object. */
+
+extern gcc_jit_object *
+gcc_jit_extended_asm_as_object (gcc_jit_extended_asm *ext_asm);
+
+/* Set whether the gcc_jit_extended_asm has side-effects, equivalent to
+ the "volatile" qualifier in C's extended asm syntax. */
+
+extern void
+gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm *ext_asm,
+ int flag);
+
+/* Set the equivalent of the "inline" qualifier in C's extended asm
+ syntax. */
+
+extern void
+gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm *ext_asm,
+ int flag);
+
+/* Add an output operand to the extended asm statement.
+ "asm_symbolic_name" can be NULL.
+ "constraint" and "dest" must be non-NULL.
+ This function can't be called on an "asm goto" as such instructions
+ can't have outputs */
+
+extern void
+gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm *ext_asm,
+ const char *asm_symbolic_name,
+ const char *constraint,
+ gcc_jit_lvalue *dest);
+
+/* Add an input operand to the extended asm statement.
+ "asm_symbolic_name" can be NULL.
+ "constraint" and "src" must be non-NULL. */
+
+extern void
+gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm *ext_asm,
+ const char *asm_symbolic_name,
+ const char *constraint,
+ gcc_jit_rvalue *src);
+
+/* Add "victim" to the list of registers clobbered by the extended
+ asm statement. It must be non-NULL. */
+
+extern void
+gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm *ext_asm,
+ const char *victim);
+
+/* Add "asm_stmts", a set of top-level asm statements, analogous to
+ those created by GCC's "basic" asm syntax in C at file scope. */
+
+extern void
+gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ const char *asm_stmts);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index a6e67e78..bcabe16 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -192,3 +192,16 @@ LIBGCCJIT_ABI_14 {
global:
gcc_jit_global_set_initializer;
} LIBGCCJIT_ABI_13;
+
+LIBGCCJIT_ABI_15 {
+ global:
+ gcc_jit_block_add_extended_asm;
+ gcc_jit_block_end_with_extended_asm_goto;
+ gcc_jit_extended_asm_as_object;
+ gcc_jit_extended_asm_set_volatile_flag;
+ gcc_jit_extended_asm_set_inline_flag;
+ gcc_jit_extended_asm_add_output_operand;
+ gcc_jit_extended_asm_add_input_operand;
+ gcc_jit_extended_asm_add_clobber;
+ gcc_jit_context_add_top_level_asm;
+} LIBGCCJIT_ABI_14;
diff --git a/gcc/json.cc b/gcc/json.cc
index 627741d..70775d1 100644
--- a/gcc/json.cc
+++ b/gcc/json.cc
@@ -70,7 +70,10 @@ object::print (pretty_printer *pp) const
pp_string (pp, ", ");
const char *key = const_cast <char *>((*it).first);
value *value = (*it).second;
- pp_printf (pp, "\"%s\": ", key); // FIXME: escaping?
+ pp_doublequote (pp);
+ pp_string (pp, key); // FIXME: escaping?
+ pp_doublequote (pp);
+ pp_string (pp, ": ");
value->print (pp);
}
pp_character (pp, '}');
diff --git a/gcc/jump.c b/gcc/jump.c
index 34a8f20..c508467 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -850,9 +850,17 @@ pc_set (const rtx_insn *insn)
pat = PATTERN (insn);
/* The set is allowed to appear either as the insn pattern or
- the first set in a PARALLEL. */
- if (GET_CODE (pat) == PARALLEL)
- pat = XVECEXP (pat, 0, 0);
+ the first set in a PARALLEL, UNSPEC or UNSPEC_VOLATILE. */
+ switch (GET_CODE (pat))
+ {
+ case PARALLEL:
+ case UNSPEC:
+ case UNSPEC_VOLATILE:
+ pat = XVECEXP (pat, 0, 0);
+ break;
+ default:
+ break;
+ }
if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
return pat;
@@ -860,7 +868,9 @@ pc_set (const rtx_insn *insn)
}
/* Return true when insn is an unconditional direct jump,
- possibly bundled inside a PARALLEL. */
+ possibly bundled inside a PARALLEL, UNSPEC or UNSPEC_VOLATILE.
+ The instruction may have various other effects so before removing the jump
+ you must verify onlyjump_p. */
int
any_uncondjump_p (const rtx_insn *insn)
@@ -876,9 +886,9 @@ any_uncondjump_p (const rtx_insn *insn)
}
/* Return true when insn is a conditional jump. This function works for
- instructions containing PC sets in PARALLELs. The instruction may have
- various other effects so before removing the jump you must verify
- onlyjump_p.
+ instructions containing PC sets in PARALLELs, UNSPECs or UNSPEC_VOLATILEs.
+ The instruction may have various other effects so before removing the jump
+ you must verify onlyjump_p.
Note that unlike condjump_p it returns false for unconditional jumps. */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index a909915..c670b77 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -87,6 +87,8 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
tree);
extern bool lhd_omp_mappable_type (tree);
extern bool lhd_omp_scalar_p (tree);
+extern tree *lhd_omp_get_decl_init (tree);
+extern void lhd_omp_finish_decl_inits ();
extern const char *lhd_get_substring_location (const substring_loc &,
location_t *out_loc);
@@ -103,6 +105,10 @@ extern void lhd_finalize_early_debug (void);
#define LANG_HOOKS_INIT_OPTIONS_STRUCT hook_void_gcc_optionsp
#define LANG_HOOKS_INIT_OPTIONS lhd_init_options
#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
+#define LANG_HOOKS_PREPROCESS_MAIN_FILE NULL
+#define LANG_HOOKS_PREPROCESS_OPTIONS NULL
+#define LANG_HOOKS_PREPROCESS_UNDEF NULL
+#define LANG_HOOKS_PREPROCESS_TOKEN NULL
#define LANG_HOOKS_REGISTER_DUMPS lhd_register_dumps
#define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
#define LANG_HOOKS_HANDLE_OPTION lhd_handle_option
@@ -261,6 +267,8 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
#define LANG_HOOKS_OMP_FINISH_CLAUSE lhd_omp_finish_clause
#define LANG_HOOKS_OMP_SCALAR_P lhd_omp_scalar_p
+#define LANG_HOOKS_OMP_GET_DECL_INIT lhd_omp_get_decl_init
+#define LANG_HOOKS_OMP_FINISH_DECL_INITS lhd_omp_finish_decl_inits
#define LANG_HOOKS_DECLS { \
LANG_HOOKS_GLOBAL_BINDINGS_P, \
@@ -289,7 +297,9 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR, \
LANG_HOOKS_OMP_CLAUSE_DTOR, \
LANG_HOOKS_OMP_FINISH_CLAUSE, \
- LANG_HOOKS_OMP_SCALAR_P \
+ LANG_HOOKS_OMP_SCALAR_P, \
+ LANG_HOOKS_OMP_GET_DECL_INIT, \
+ LANG_HOOKS_OMP_FINISH_DECL_INITS \
}
/* LTO hooks. */
@@ -317,6 +327,10 @@ extern void lhd_end_section (void);
LANG_HOOKS_INIT_OPTIONS_STRUCT, \
LANG_HOOKS_INIT_OPTIONS, \
LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
+ LANG_HOOKS_PREPROCESS_MAIN_FILE, \
+ LANG_HOOKS_PREPROCESS_OPTIONS, \
+ LANG_HOOKS_PREPROCESS_UNDEF, \
+ LANG_HOOKS_PREPROCESS_TOKEN, \
LANG_HOOKS_REGISTER_DUMPS, \
LANG_HOOKS_COMPLAIN_WRONG_LANG_P, \
LANG_HOOKS_HANDLE_OPTION, \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 8819a88..23cbf06 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -632,6 +632,22 @@ lhd_omp_scalar_p (tree decl)
return false;
}
+/* Return static initializer for DECL. */
+
+tree *
+lhd_omp_get_decl_init (tree decl)
+{
+ return &DECL_INITIAL (decl);
+}
+
+/* Free any extra memory used to hold initializer information for
+ variable declarations. */
+
+void
+lhd_omp_finish_decl_inits (void)
+{
+}
+
/* Register language specific type size variables as potentially OpenMP
firstprivate variables. */
@@ -790,7 +806,7 @@ lhd_begin_section (const char *name)
saved_section = text_section;
/* Create a new section and switch to it. */
- section = get_section (name, SECTION_DEBUG | SECTION_EXCLUDE, NULL);
+ section = get_section (name, SECTION_DEBUG | SECTION_EXCLUDE, NULL, true);
switch_to_section (section);
}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index a35cf21..235ce99 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -299,6 +299,16 @@ struct lang_hooks_for_decls
/* Return true if DECL is a scalar variable (for the purpose of
implicit firstprivatization). */
bool (*omp_scalar_p) (tree decl);
+
+ /* Return a pointer to the tree representing the initializer
+ expression for the non-local variable DECL. Return NULL if
+ DECL is not initialized. */
+ tree *(*omp_get_decl_init) (tree decl);
+
+ /* Free any extra memory used to hold initializer information for
+ variable declarations. omp_get_decl_init must not be called
+ after calling this. */
+ void (*omp_finish_decl_inits) (void);
};
/* Language hooks related to LTO serialization. */
@@ -356,6 +366,24 @@ struct lang_hooks
global diagnostic context structure. */
void (*initialize_diagnostics) (diagnostic_context *);
+ /* Beginning the main source file. */
+ void (*preprocess_main_file) (cpp_reader *, line_maps *,
+ const line_map_ordinary *);
+
+ /* Adjust libcpp options and callbacks. */
+ void (*preprocess_options) (cpp_reader *);
+
+ /* Undefining a macro. */
+ void (*preprocess_undef) (cpp_reader *, location_t, cpp_hashnode *);
+
+ /* Observer for preprocessing stream. */
+ uintptr_t (*preprocess_token) (cpp_reader *, const cpp_token *, uintptr_t);
+ /* Various flags it can return about the token. */
+ enum PT_flags
+ {
+ PT_begin_pragma = 1 << 0
+ };
+
/* Register language-specific dumps. */
void (*register_dumps) (gcc::dump_manager *);
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index 02282d4..661e502 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -378,7 +378,7 @@ add_test (rtx cond, edge *e, basic_block dest)
bb = split_edge_and_insert (*e, seq);
*e = single_succ_edge (bb);
- if (any_uncondjump_p (jump))
+ if (any_uncondjump_p (jump) && onlyjump_p (jump))
{
/* The condition is always true. */
delete_insn (jump);
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index 401e528..ac87daf 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-loop-niter.h"
#include "loop-unroll.h"
#include "tree-scalar-evolution.h"
+#include "tree-cfgcleanup.h"
/* Apply FLAGS to the loop state. */
@@ -133,13 +134,19 @@ loop_optimizer_init (unsigned flags)
/* Finalize loop structures. */
void
-loop_optimizer_finalize (struct function *fn)
+loop_optimizer_finalize (struct function *fn, bool clean_loop_closed_phi)
{
class loop *loop;
basic_block bb;
timevar_push (TV_LOOP_FINI);
+ if (clean_loop_closed_phi && loops_state_satisfies_p (fn, LOOP_CLOSED_SSA))
+ {
+ clean_up_loop_closed_phi (fn);
+ loops_state_clear (fn, LOOP_CLOSED_SSA);
+ }
+
if (loops_state_satisfies_p (fn, LOOPS_HAVE_RECORDED_EXITS))
release_recorded_exits (fn);
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 37ae654..653e303 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -1099,6 +1099,10 @@ find_invariant_insn (rtx_insn *insn, bool always_reached, bool always_executed)
if (HAVE_cc0 && sets_cc0_p (insn))
return;
+ /* Jumps have control flow side-effects. */
+ if (JUMP_P (insn))
+ return;
+
set = single_set (insn);
if (!set)
return;
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index d7b3d90..9d401d2 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -44,7 +44,7 @@ along with GCC; see the file COPYING3. If not see
iv_analyze_result (insn, def, iv): Stores to IV the description of the iv
corresponding to DEF, which is a register defined in INSN.
iv_analyze_expr (insn, mode, expr, iv): Stores to IV the description of iv
- corresponding to expression EXPR evaluated at INSN. All registers used bu
+ corresponding to expression EXPR evaluated at INSN. All registers used by
EXPR must also be used in INSN. MODE is the mode of EXPR.
*/
@@ -1936,7 +1936,7 @@ simplify_using_initial_values (class loop *loop, enum rtx_code op, rtx *expr)
while (1)
{
insn = BB_END (e->src);
- if (any_condjump_p (insn))
+ if (any_condjump_p (insn) && onlyjump_p (insn))
{
rtx cond = get_condition (BB_END (e->src), NULL, false, true);
@@ -2887,7 +2887,7 @@ check_simple_exit (class loop *loop, edge e, class niter_desc *desc)
return;
/* It must end in a simple conditional jump. */
- if (!any_condjump_p (BB_END (exit_bb)))
+ if (!any_condjump_p (BB_END (exit_bb)) || !onlyjump_p (BB_END (exit_bb)))
return;
ein = EDGE_SUCC (exit_bb, 0);
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index 40e323c..b040f7f 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -1715,8 +1715,8 @@ find_reload_regno_insns (int regno, rtx_insn * &start, rtx_insn * &finish)
start_insn = lra_insn_recog_data[uid]->insn;
n++;
}
- /* For reload pseudo we should have at most 3 insns referring for it:
- input/output reload insns and the original insn. */
+ /* For reload pseudo we should have at most 3 insns referring for
+ it: input/output reload insns and the original insn. */
if (n > 3)
return false;
if (n > 1)
@@ -1792,7 +1792,8 @@ lra_split_hard_reg_for (void)
{
if (! find_reload_regno_insns (i, first, last))
continue;
- if (spill_hard_reg_in_range (i, rclass, first, last))
+ if (BLOCK_FOR_INSN (first) == BLOCK_FOR_INSN (last)
+ && spill_hard_reg_in_range (i, rclass, first, last))
{
bitmap_clear (&failed_reload_pseudos);
return true;
@@ -1817,16 +1818,10 @@ lra_split_hard_reg_for (void)
lra_asm_error_p = asm_p = true;
error_for_asm (insn,
"%<asm%> operand has impossible constraints");
- /* Avoid further trouble with this insn.
- For asm goto, instead of fixing up all the edges
- just clear the template and clear input operands
- (asm goto doesn't have any output operands). */
+ /* Avoid further trouble with this insn. */
if (JUMP_P (insn))
{
- rtx asm_op = extract_asm_operands (PATTERN (insn));
- ASM_OPERANDS_TEMPLATE (asm_op) = ggc_strdup ("");
- ASM_OPERANDS_INPUT_VEC (asm_op) = rtvec_alloc (0);
- ASM_OPERANDS_INPUT_CONSTRAINT_VEC (asm_op) = rtvec_alloc (0);
+ ira_nullify_asm_goto (insn);
lra_update_insn_regno_info (insn);
}
else
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index b5c010d..80ca1e0 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -406,8 +406,10 @@ valid_address_p (rtx op, struct address_info *ad,
address_eliminator eliminator (ad);
/* Allow a memory OP if it matches CONSTRAINT, even if CONSTRAINT is more
- forgiving than "m". */
- if (MEM_P (op)
+ forgiving than "m".
+ Need to extract memory from op for special memory constraint,
+ i.e. bcst_mem_operand in i386 backend. */
+ if (MEM_P (extract_mem_from_operand (op))
&& (insn_extra_memory_constraint (constraint)
|| insn_extra_special_memory_constraint (constraint))
&& constraint_satisfied_p (op, constraint))
@@ -2426,7 +2428,8 @@ process_alt_operands (int only_alternative)
break;
case CT_MEMORY:
- if (satisfies_memory_constraint_p (op, cn))
+ if (MEM_P (op)
+ && satisfies_memory_constraint_p (op, cn))
win = true;
else if (spilled_pseudo_p (op))
win = true;
@@ -2505,7 +2508,7 @@ process_alt_operands (int only_alternative)
while ((p += len), c);
scratch_p = (operand_reg[nop] != NULL_RTX
- && lra_former_scratch_p (REGNO (operand_reg[nop])));
+ && ira_former_scratch_p (REGNO (operand_reg[nop])));
/* Record which operands fit this alternative. */
if (win)
{
@@ -3427,13 +3430,14 @@ process_address_1 (int nop, bool check_only_p,
rtx new_reg;
HOST_WIDE_INT scale;
rtx op = *curr_id->operand_loc[nop];
+ rtx mem = extract_mem_from_operand (op);
const char *constraint = curr_static_id->operand[nop].constraint;
enum constraint_num cn = lookup_constraint (constraint);
bool change_p = false;
- if (MEM_P (op)
- && GET_MODE (op) == BLKmode
- && GET_CODE (XEXP (op, 0)) == SCRATCH)
+ if (MEM_P (mem)
+ && GET_MODE (mem) == BLKmode
+ && GET_CODE (XEXP (mem, 0)) == SCRATCH)
return false;
if (insn_extra_address_constraint (cn)
@@ -3446,12 +3450,14 @@ process_address_1 (int nop, bool check_only_p,
&& curr_static_id->operand[nop].is_address)
decompose_lea_address (&ad, curr_id->operand_loc[nop]);
/* Do not attempt to decompose arbitrary addresses generated by combine
- for asm operands with loose constraints, e.g 'X'. */
- else if (MEM_P (op)
+ for asm operands with loose constraints, e.g 'X'.
+ Need to extract memory from op for special memory constraint,
+ i.e. bcst_mem_operand in i386 backend. */
+ else if (MEM_P (mem)
&& !(INSN_CODE (curr_insn) < 0
&& get_constraint_type (cn) == CT_FIXED_FORM
&& constraint_satisfied_p (op, cn)))
- decompose_mem_address (&ad, op);
+ decompose_mem_address (&ad, mem);
else if (GET_CODE (op) == SUBREG
&& MEM_P (SUBREG_REG (op)))
decompose_mem_address (&ad, SUBREG_REG (op));
@@ -3948,10 +3954,10 @@ curr_insn_transform (bool check_only_p)
no_input_reloads_p = no_output_reloads_p = false;
goal_alt_number = -1;
change_p = sec_mem_p = false;
- /* JUMP_INSNs and CALL_INSNs are not allowed to have any output
- reloads; neither are insns that SET cc0. Insns that use CC0 are
- not allowed to have any input reloads. */
- if (JUMP_P (curr_insn) || CALL_P (curr_insn))
+ /* CALL_INSNs are not allowed to have any output reloads; neither
+ are insns that SET cc0. Insns that use CC0 are not allowed to
+ have any input reloads. */
+ if (CALL_P (curr_insn))
no_output_reloads_p = true;
if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (curr_insn)))
@@ -4098,9 +4104,18 @@ curr_insn_transform (bool check_only_p)
error_for_asm (curr_insn,
"inconsistent operand constraints in an %<asm%>");
lra_asm_error_p = true;
- /* Avoid further trouble with this insn. Don't generate use
- pattern here as we could use the insn SP offset. */
- lra_set_insn_deleted (curr_insn);
+ if (! JUMP_P (curr_insn))
+ {
+ /* Avoid further trouble with this insn. Don't generate use
+ pattern here as we could use the insn SP offset. */
+ lra_set_insn_deleted (curr_insn);
+ }
+ else
+ {
+ lra_invalidate_insn_data (curr_insn);
+ ira_nullify_asm_goto (curr_insn);
+ lra_update_insn_regno_info (curr_insn);
+ }
return true;
}
@@ -4354,8 +4369,8 @@ curr_insn_transform (bool check_only_p)
assigment pass and the scratch pseudo will be
spilled. Spilled scratch pseudos are transformed
back to scratches at the LRA end. */
- && lra_former_scratch_operand_p (curr_insn, i)
- && lra_former_scratch_p (REGNO (op)))
+ && ira_former_scratch_operand_p (curr_insn, i)
+ && ira_former_scratch_p (REGNO (op)))
{
int regno = REGNO (op);
lra_change_class (regno, NO_REGS, " Change to", true);
@@ -4376,7 +4391,7 @@ curr_insn_transform (bool check_only_p)
&& goal_alt[i] != NO_REGS && REG_P (op)
&& (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER
&& regno < new_regno_start
- && ! lra_former_scratch_p (regno)
+ && ! ira_former_scratch_p (regno)
&& reg_renumber[regno] < 0
/* Check that the optional reload pseudo will be able to
hold given mode value. */
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 01fcbfa..f9e99a2 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -319,9 +319,6 @@ extern struct lra_insn_reg *lra_get_insn_regs (int);
extern void lra_free_copies (void);
extern void lra_create_copy (int, int, int);
extern lra_copy_t lra_get_copy (int);
-extern bool lra_former_scratch_p (int);
-extern bool lra_former_scratch_operand_p (rtx_insn *, int);
-extern void lra_register_new_scratch_op (rtx_insn *, int, int);
extern int lra_new_regno_start;
extern int lra_constraint_new_regno_start;
diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c
index 72309e5..7a62c8f 100644
--- a/gcc/lra-remat.c
+++ b/gcc/lra-remat.c
@@ -1031,12 +1031,12 @@ update_scratch_ops (rtx_insn *remat_insn)
if (! REG_P (*loc))
continue;
int regno = REGNO (*loc);
- if (! lra_former_scratch_p (regno))
+ if (! ira_former_scratch_p (regno))
continue;
*loc = lra_create_new_reg (GET_MODE (*loc), *loc,
lra_get_allocno_class (regno),
"scratch pseudo copy");
- lra_register_new_scratch_op (remat_insn, i, id->icode);
+ ira_register_new_scratch_op (remat_insn, i, id->icode);
}
}
diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c
index 0caa4ac..85c3664 100644
--- a/gcc/lra-spills.c
+++ b/gcc/lra-spills.c
@@ -446,7 +446,7 @@ remove_pseudos (rtx *loc, rtx_insn *insn)
it might result in an address reload for some targets. In
any case we transform such pseudos not getting hard registers
into scratches back. */
- && ! lra_former_scratch_p (i))
+ && ! ira_former_scratch_p (i))
{
if (lra_reg_info[i].nrefs == 0
&& pseudo_slots[i].mem == NULL && spill_hard_reg[i] == NULL)
@@ -494,7 +494,7 @@ spill_pseudos (void)
for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
{
if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
- && ! lra_former_scratch_p (i))
+ && ! ira_former_scratch_p (i))
{
bitmap_set_bit (spilled_pseudos, i);
bitmap_ior_into (changed_insns, &lra_reg_info[i].insn_bitmap);
@@ -578,7 +578,7 @@ lra_need_for_scratch_reg_p (void)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
- && lra_former_scratch_p (i))
+ && ira_former_scratch_p (i))
return true;
return false;
}
@@ -591,7 +591,7 @@ lra_need_for_spills_p (void)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
- && ! lra_former_scratch_p (i))
+ && ! ira_former_scratch_p (i))
return true;
return false;
}
@@ -612,7 +612,7 @@ lra_spill (void)
for (n = 0, i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
/* We do not want to assign memory for former scratches. */
- && ! lra_former_scratch_p (i))
+ && ! ira_former_scratch_p (i))
pseudo_regnos[n++] = i;
lra_assert (n > 0);
pseudo_slots = XNEWVEC (struct pseudo_slot, regs_num);
@@ -788,6 +788,14 @@ lra_final_code_change (void)
{
rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == USE && XEXP (pat, 0) == const1_rtx)
+ {
+ /* Remove markers to eliminate critical edges for jump insn
+ output reloads (see code in ira.c::ira). */
+ lra_invalidate_insn_data (insn);
+ delete_insn (insn);
+ continue;
+ }
if (GET_CODE (pat) == CLOBBER && LRA_TEMP_CLOBBER_P (pat))
{
/* Remove clobbers temporarily created in LRA. We don't
diff --git a/gcc/lra.c b/gcc/lra.c
index caa09d8..a79213e 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -160,8 +160,6 @@ static void invalidate_insn_recog_data (int);
static int get_insn_freq (rtx_insn *);
static void invalidate_insn_data_regno_info (lra_insn_recog_data_t,
rtx_insn *, int);
-static void remove_scratches_1 (rtx_insn *);
-
/* Expand all regno related info needed for LRA. */
static void
expand_reg_data (int old)
@@ -482,6 +480,8 @@ lra_emit_add (rtx x, rtx y, rtx z)
/* The number of emitted reload insns so far. */
int lra_curr_reload_num;
+static void remove_insn_scratches (rtx_insn *insn);
+
/* Emit x := y, processing special case when y = u + v or y = u + v *
scale + w through emit_add (Y can be an address which is base +
index reg * scale + displacement in general case). X may be used
@@ -503,7 +503,7 @@ lra_emit_move (rtx x, rtx y)
/* The move pattern may require scratch registers, so convert them
into real registers now. */
if (insn != NULL_RTX)
- remove_scratches_1 (insn);
+ remove_insn_scratches (insn);
if (REG_P (x))
lra_reg_info[ORIGINAL_REGNO (x)].last_reload = ++lra_curr_reload_num;
/* Function emit_move can create pseudos -- so expand the pseudo
@@ -1852,8 +1852,6 @@ void
lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
const char *title)
{
- rtx_insn *last;
-
if (before == NULL_RTX && after == NULL_RTX)
return;
if (lra_dump_file != NULL)
@@ -1864,12 +1862,6 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
fprintf (lra_dump_file," %s before:\n", title);
dump_rtl_slim (lra_dump_file, before, NULL, -1, 0);
}
- if (after != NULL_RTX)
- {
- fprintf (lra_dump_file, " %s after:\n", title);
- dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
- }
- fprintf (lra_dump_file, "\n");
}
if (before != NULL_RTX)
{
@@ -1883,12 +1875,69 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
{
if (cfun->can_throw_non_call_exceptions)
copy_reg_eh_region_note_forward (insn, after, NULL);
- for (last = after; NEXT_INSN (last) != NULL_RTX; last = NEXT_INSN (last))
- ;
- emit_insn_after (after, insn);
- push_insns (last, insn);
- setup_sp_offset (after, last);
+ if (! JUMP_P (insn))
+ {
+ rtx_insn *last;
+
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " %s after:\n", title);
+ dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
+ }
+ for (last = after;
+ NEXT_INSN (last) != NULL_RTX;
+ last = NEXT_INSN (last))
+ ;
+ emit_insn_after (after, insn);
+ push_insns (last, insn);
+ setup_sp_offset (after, last);
+ }
+ else
+ {
+ /* Put output reload insns on successor BBs: */
+ edge_iterator ei;
+ edge e;
+
+ FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs)
+ if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
+ {
+ /* We already made the edge no-critical in ira.c::ira */
+ lra_assert (!EDGE_CRITICAL_P (e));
+ rtx_insn *curr, *tmp = BB_HEAD (e->dest);
+ if (LABEL_P (tmp))
+ tmp = NEXT_INSN (tmp);
+ if (NOTE_INSN_BASIC_BLOCK_P (tmp))
+ tmp = NEXT_INSN (tmp);
+ /* Do not put reload insns if it is the last BB
+ without actual insns. */
+ if (tmp == NULL)
+ continue;
+ start_sequence ();
+ for (curr = after; curr != NULL_RTX; curr = NEXT_INSN (curr))
+ emit_insn (copy_insn (PATTERN (curr)));
+ rtx_insn *copy = get_insns (), *last = get_last_insn ();
+ end_sequence ();
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " %s after in bb%d:\n", title,
+ e->dest->index);
+ dump_rtl_slim (lra_dump_file, copy, NULL, -1, 0);
+ }
+ /* Use the right emit func for setting up BB_END/BB_HEAD: */
+ if (BB_END (e->dest) == PREV_INSN (tmp))
+ emit_insn_after_noloc (copy, PREV_INSN (tmp), e->dest);
+ else
+ emit_insn_before_noloc (copy, tmp, e->dest);
+ push_insns (last, PREV_INSN (copy));
+ setup_sp_offset (copy, last);
+ /* We can ignore BB live info here as it and reg notes
+ will be updated before the next assignment
+ sub-pass. */
+ }
+ }
}
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file, "\n");
if (cfun->can_throw_non_call_exceptions)
{
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
@@ -1988,170 +2037,35 @@ lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno,
-/* This page contains code dealing with scratches (changing them onto
- pseudos and restoring them from the pseudos).
-
- We change scratches into pseudos at the beginning of LRA to
- simplify dealing with them (conflicts, hard register assignments).
-
- If the pseudo denoting scratch was spilled it means that we do need
- a hard register for it. Such pseudos are transformed back to
- scratches at the end of LRA. */
-
-/* Description of location of a former scratch operand. */
-struct sloc
+/* Return new register of the same mode as ORIGINAL of class ALL_REGS.
+ Used in ira_remove_scratches. */
+static rtx
+get_scratch_reg (rtx original)
{
- rtx_insn *insn; /* Insn where the scratch was. */
- int nop; /* Number of the operand which was a scratch. */
- int icode; /* Original icode from which scratch was removed. */
-};
-
-typedef struct sloc *sloc_t;
-
-/* Locations of the former scratches. */
-static vec<sloc_t> scratches;
-
-/* Bitmap of scratch regnos. */
-static bitmap_head scratch_bitmap;
-
-/* Bitmap of scratch operands. */
-static bitmap_head scratch_operand_bitmap;
-
-/* Return true if pseudo REGNO is made of SCRATCH. */
-bool
-lra_former_scratch_p (int regno)
-{
- return bitmap_bit_p (&scratch_bitmap, regno);
+ return lra_create_new_reg (GET_MODE (original), original, ALL_REGS, NULL);
}
-/* Return true if the operand NOP of INSN is a former scratch. */
-bool
-lra_former_scratch_operand_p (rtx_insn *insn, int nop)
-{
- return bitmap_bit_p (&scratch_operand_bitmap,
- INSN_UID (insn) * MAX_RECOG_OPERANDS + nop) != 0;
-}
-
-/* Register operand NOP in INSN as a former scratch. It will be
- changed to scratch back, if it is necessary, at the LRA end. */
-void
-lra_register_new_scratch_op (rtx_insn *insn, int nop, int icode)
-{
- lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
- rtx op = *id->operand_loc[nop];
- sloc_t loc = XNEW (struct sloc);
- lra_assert (REG_P (op));
- loc->insn = insn;
- loc->nop = nop;
- loc->icode = icode;
- scratches.safe_push (loc);
- bitmap_set_bit (&scratch_bitmap, REGNO (op));
- bitmap_set_bit (&scratch_operand_bitmap,
- INSN_UID (insn) * MAX_RECOG_OPERANDS + nop);
- add_reg_note (insn, REG_UNUSED, op);
-}
-
-/* Change INSN's scratches into pseudos and save their location. */
+/* Remove all insn scratches in INSN. */
static void
-remove_scratches_1 (rtx_insn *insn)
+remove_insn_scratches (rtx_insn *insn)
{
- int i;
- bool insn_changed_p;
- rtx reg;
- lra_insn_recog_data_t id;
- struct lra_static_insn_data *static_id;
-
- id = lra_get_insn_recog_data (insn);
- static_id = id->insn_static_data;
- insn_changed_p = false;
- for (i = 0; i < static_id->n_operands; i++)
- if (GET_CODE (*id->operand_loc[i]) == SCRATCH
- && GET_MODE (*id->operand_loc[i]) != VOIDmode)
- {
- insn_changed_p = true;
- *id->operand_loc[i] = reg
- = lra_create_new_reg (static_id->operand[i].mode,
- *id->operand_loc[i], ALL_REGS, NULL);
- lra_register_new_scratch_op (insn, i, id->icode);
- if (lra_dump_file != NULL)
- fprintf (lra_dump_file,
- "Removing SCRATCH in insn #%u (nop %d)\n",
- INSN_UID (insn), i);
- }
- if (insn_changed_p)
- /* Because we might use DF right after caller-saves sub-pass
- we need to keep DF info up to date. */
+ if (ira_remove_insn_scratches (insn, true, lra_dump_file, get_scratch_reg))
df_insn_rescan (insn);
}
-/* Change scratches into pseudos and save their location. */
+/* Remove all insn scratches in the current function. */
static void
remove_scratches (void)
{
basic_block bb;
rtx_insn *insn;
- scratches.create (get_max_uid ());
- bitmap_initialize (&scratch_bitmap, &reg_obstack);
- bitmap_initialize (&scratch_operand_bitmap, &reg_obstack);
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
- if (INSN_P (insn))
- remove_scratches_1 (insn);
-}
-
-/* Changes pseudos created by function remove_scratches onto scratches. */
-static void
-restore_scratches (void)
-{
- int regno;
- unsigned i;
- sloc_t loc;
- rtx_insn *last = NULL;
- lra_insn_recog_data_t id = NULL;
-
- for (i = 0; scratches.iterate (i, &loc); i++)
- {
- /* Ignore already deleted insns. */
- if (NOTE_P (loc->insn)
- && NOTE_KIND (loc->insn) == NOTE_INSN_DELETED)
- continue;
- if (last != loc->insn)
- {
- last = loc->insn;
- id = lra_get_insn_recog_data (last);
- }
- if (loc->icode != id->icode)
- {
- /* The icode doesn't match, which means the insn has been modified
- (e.g. register elimination). The scratch cannot be restored. */
- continue;
- }
- if (REG_P (*id->operand_loc[loc->nop])
- && ((regno = REGNO (*id->operand_loc[loc->nop]))
- >= FIRST_PSEUDO_REGISTER)
- && lra_get_regno_hard_regno (regno) < 0)
- {
- /* It should be only case when scratch register with chosen
- constraint 'X' did not get memory or hard register. */
- lra_assert (lra_former_scratch_p (regno));
- *id->operand_loc[loc->nop]
- = gen_rtx_SCRATCH (GET_MODE (*id->operand_loc[loc->nop]));
- lra_update_dup (id, loc->nop);
- if (lra_dump_file != NULL)
- fprintf (lra_dump_file, "Restoring SCRATCH in insn #%u(nop %d)\n",
- INSN_UID (loc->insn), loc->nop);
- }
- }
- for (i = 0; scratches.iterate (i, &loc); i++)
- free (loc);
- scratches.release ();
- bitmap_clear (&scratch_bitmap);
- bitmap_clear (&scratch_operand_bitmap);
+ if (INSN_P (insn))
+ remove_insn_scratches (insn);
}
-
-
/* Function checks RTL for correctness. If FINAL_P is true, it is
done at the end of LRA and the check is more rigorous. */
static void
@@ -2543,7 +2457,7 @@ lra (FILE *f)
lra_bad_spill_regno_start = lra_constraint_new_regno_start;
lra_assignment_iter_after_spill = 0;
}
- restore_scratches ();
+ ira_restore_scratches (lra_dump_file);
lra_eliminate (true, false);
lra_final_code_change ();
lra_in_progress = 0;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 19d4ca5..8718678 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "symbol-summary.h"
#include "symtab-thunks.h"
+#include "symtab-clones.h"
/* True when asm nodes has been output. */
bool asm_nodes_output = false;
@@ -767,6 +768,9 @@ output_refs (lto_symtab_encoder_t encoder)
for (int i = 0; node->iterate_reference (i, ref); i++)
lto_output_ref (ob, ref, encoder);
}
+ if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
+ if (cnode->declare_variant_alt)
+ omp_lto_output_declare_variant_alt (ob, cnode, encoder);
}
streamer_write_uhwi_stream (ob->main_stream, 0);
@@ -1608,6 +1612,9 @@ input_refs (class lto_input_block *ib,
input_ref (ib, node, nodes);
count--;
}
+ if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
+ if (cnode->declare_variant_alt)
+ omp_lto_input_declare_variant_alt (ib, cnode, nodes);
}
}
@@ -1817,9 +1824,10 @@ input_offload_tables (bool do_force_output)
static int
output_cgraph_opt_summary_p (struct cgraph_node *node)
{
- return ((node->clone_of || node->former_clone_of)
- && (node->clone.tree_map
- || node->clone.param_adjustments));
+ if (node->clone_of || node->former_clone_of)
+ return true;
+ clone_info *info = clone_info::get (node);
+ return info && (info->tree_map || info->param_adjustments);
}
/* Output optimization summary for EDGE to OB. */
@@ -1843,9 +1851,12 @@ output_node_opt_summary (struct output_block *ob,
/* TODO: Should this code be moved to ipa-param-manipulation? */
struct bitpack_d bp;
bp = bitpack_create (ob->main_stream);
- bp_pack_value (&bp, (node->clone.param_adjustments != NULL), 1);
+ clone_info *info = clone_info::get (node);
+
+ bp_pack_value (&bp, (info && info->param_adjustments != NULL), 1);
streamer_write_bitpack (&bp);
- if (ipa_param_adjustments *adjustments = node->clone.param_adjustments)
+ if (ipa_param_adjustments *adjustments
+ = info ? info->param_adjustments : NULL)
{
streamer_write_uhwi (ob, vec_safe_length (adjustments->m_adj_params));
ipa_adjusted_param *adj;
@@ -1873,17 +1884,18 @@ output_node_opt_summary (struct output_block *ob,
}
streamer_write_hwi (ob, adjustments->m_always_copy_start);
bp = bitpack_create (ob->main_stream);
- bp_pack_value (&bp, node->clone.param_adjustments->m_skip_return, 1);
+ bp_pack_value (&bp, info->param_adjustments->m_skip_return, 1);
streamer_write_bitpack (&bp);
}
- streamer_write_uhwi (ob, vec_safe_length (node->clone.tree_map));
- FOR_EACH_VEC_SAFE_ELT (node->clone.tree_map, i, map)
- {
- streamer_write_uhwi (ob, map->parm_num);
- gcc_assert (EXPR_LOCATION (map->new_tree) == UNKNOWN_LOCATION);
- stream_write_tree (ob, map->new_tree, true);
- }
+ streamer_write_uhwi (ob, info ? vec_safe_length (info->tree_map) : 0);
+ if (info)
+ FOR_EACH_VEC_SAFE_ELT (info->tree_map, i, map)
+ {
+ streamer_write_uhwi (ob, map->parm_num);
+ gcc_assert (EXPR_LOCATION (map->new_tree) == UNKNOWN_LOCATION);
+ stream_write_tree (ob, map->new_tree, true);
+ }
if (lto_symtab_encoder_in_partition_p (encoder, node))
{
@@ -1953,6 +1965,8 @@ input_node_opt_summary (struct cgraph_node *node,
struct bitpack_d bp;
bp = streamer_read_bitpack (ib_main);
bool have_adjustments = bp_unpack_value (&bp, 1);
+ clone_info *info = clone_info::get_create (node);
+
if (have_adjustments)
{
count = streamer_read_uhwi (ib_main);
@@ -1985,7 +1999,7 @@ input_node_opt_summary (struct cgraph_node *node,
int always_copy_start = streamer_read_hwi (ib_main);
bp = streamer_read_bitpack (ib_main);
bool skip_return = bp_unpack_value (&bp, 1);
- node->clone.param_adjustments
+ info->param_adjustments
= (new (ggc_alloc <ipa_param_adjustments> ())
ipa_param_adjustments (new_params, always_copy_start, skip_return));
}
@@ -1995,7 +2009,7 @@ input_node_opt_summary (struct cgraph_node *node,
{
struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
- vec_safe_push (node->clone.tree_map, map);
+ vec_safe_push (info->tree_map, map);
map->parm_num = streamer_read_uhwi (ib_main);
map->new_tree = stream_read_tree (ib_main, data_in);
}
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 64037f7..a20d64b 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1017,7 +1017,6 @@ input_cfg (class lto_input_block *ib, class data_in *data_in,
int index;
init_empty_tree_cfg_for_function (fn);
- init_ssa_operands (fn);
profile_status_for_fn (fn) = streamer_read_enum (ib, profile_status_d,
PROFILE_LAST);
@@ -1144,7 +1143,9 @@ input_ssa_names (class lto_input_block *ib, class data_in *data_in,
unsigned int i, size;
size = streamer_read_uhwi (ib);
- init_ssanames (fn, size);
+ init_tree_ssa (fn, size);
+ cfun->gimple_df->in_ssa_p = true;
+ init_ssa_operands (fn);
i = streamer_read_uhwi (ib);
while (i)
@@ -1384,9 +1385,6 @@ input_function (tree fn_decl, class data_in *data_in,
push_struct_function (fn_decl);
fn = DECL_STRUCT_FUNCTION (fn_decl);
- init_tree_ssa (fn);
- /* We input IL in SSA form. */
- cfun->gimple_df->in_ssa_p = true;
gimple_register_cfg_hooks ();
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 7882c89..0ca2796 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2424,7 +2424,7 @@ output_function (struct cgraph_node *node)
/* As we do not recurse into BLOCK_SUBBLOCKS but only BLOCK_SUPERCONTEXT
collect block tree leafs and stream those. */
auto_vec<tree> block_tree_leafs;
- if (DECL_INITIAL (function))
+ if (DECL_INITIAL (function) && DECL_INITIAL (function) != error_mark_node)
collect_block_tree_leafs (DECL_INITIAL (function), block_tree_leafs);
streamer_write_uhwi (ob, block_tree_leafs.length ());
for (unsigned i = 0; i < block_tree_leafs.length (); ++i)
@@ -2788,7 +2788,8 @@ lto_output (void)
&& flag_incremental_link != INCREMENTAL_LINK_LTO)
/* Thunks have no body but they may be synthetized
at WPA time. */
- || DECL_ARGUMENTS (cnode->decl)))
+ || DECL_ARGUMENTS (cnode->decl)
+ || cnode->declare_variant_alt))
output_function (cnode);
else if ((vnode = dyn_cast <varpool_node *> (snode))
&& (DECL_INITIAL (vnode->decl) != error_mark_node
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index b465a5e..c75a8b2 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -927,6 +927,12 @@ bool reachable_from_this_partition_p (struct cgraph_node *,
lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
void select_what_to_stream (void);
+/* In omp-general.c. */
+void omp_lto_output_declare_variant_alt (lto_simple_output_block *,
+ cgraph_node *, lto_symtab_encoder_t);
+void omp_lto_input_declare_variant_alt (lto_input_block *, cgraph_node *,
+ vec<symtab_node *>);
+
/* In options-save.c. */
void cl_target_option_stream_out (struct output_block *, struct bitpack_d *,
struct cl_target_option *);
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index b2af3ca..da1305c 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -323,8 +323,9 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
if (cf_protection_option
&& cf_protection_option->value == CF_CHECK)
fatal_error (input_location,
- "option -fcf-protection with mismatching values"
+ "option %qs with mismatching values"
" (%s, %s)",
+ "-fcf-protection",
(*decoded_options)[j].arg, foption->arg);
else
{
@@ -1582,7 +1583,11 @@ run_gcc (unsigned argc, char *argv[])
{
const char *jobserver_error = jobserver_active_p ();
if (jobserver && jobserver_error != NULL)
- warning (0, jobserver_error);
+ {
+ warning (0, jobserver_error);
+ parallel = 0;
+ jobserver = 0;
+ }
else if (!jobserver && jobserver_error == NULL)
{
parallel = 1;
@@ -1775,6 +1780,8 @@ cont1:
{
char buf[256];
init_num_threads ();
+ if (nthreads_var == 0)
+ nthreads_var = 1;
if (verbose)
fprintf (stderr, "LTO parallelism level set to %ld\n",
nthreads_var);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 5fbbce8..ac16f0f 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,48 @@
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ * lang.opt: Remove usage of Report.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (lto1.serial, lto2.serial): Change from goals to
+ variables.
+ (.PHONY): Drop lto1.serial, lto2.serial, lto1.prev and lto2.prev.
+ ($(LTO_EXE)): Depend on $(lto1.serial) rather than lto1.serial.
+ ($(LTO_DUMP_EXE)): Depend on $(lto2.serial) rather than lto2.serial.
+
+2020-11-18 Jerry Clcanny <a837940593@gmail.com>
+
+ * lto-symtab.c (lto_symtab_merge_symbols): Fix typos in comment.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (lto, lto1.serial, lto2.serial): New goals.
+ (.PHONY): Add lto lto1.serial lto1.prev lto2.serial lto2.prev.
+ (lto.all.cross, lto.start.encap): Remove dependencies.
+ ($(LTO_EXE)): Depend on lto1.prev. Call LINK_PROGRESS.
+ ($(LTO_DUMP_EXE)): Depend on lto2.prev. Call LINK_PROGRESS.
+
+2020-11-17 Jan Hubicka <jh@suse.cz>
+
+ PR bootstrap/97857
+ * lto-common.c (gimple_register_canonical_type_1): Only
+ register types with TYPE_CXX_ODR_P flag; sanity check that no
+ conflict happens at ltrans time.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * lto-symtab.c (lto_symtab_merge_decls_1): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR lto/96680
+ * lto-common.c (lto_fixup_prevailing_decls): Don't use
+ LTO_NO_PREVAIL on TREE_LIST's TREE_PURPOSE.
+ * lto-partition.c (lto_balanced_map): Treat declare_variant_alt
+ nodes like definitions.
+
2020-10-23 Jan Hubicka <hubicka@ucw.cz>
* lto-partition.c (add_symbol_to_partition_1): Update for new thunk
diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in
index 0b73f9e..6e5fbac 100644
--- a/gcc/lto/Make-lang.in
+++ b/gcc/lto/Make-lang.in
@@ -41,10 +41,16 @@ lto_dump_OBJS = $(LTO_DUMP_OBJS)
# Rules
+lto: $(LTO_EXE) $(LTO_DUMP_EXE)
+lto1.serial = $(LTO_EXE)
+lto2.serial = $(LTO_DUMP_EXE)
+
+.PHONY: lto
+
# These hooks are used by the main GCC Makefile. Consult that
# Makefile for documentation.
-lto.all.cross: $(LTO_EXE) $(LTO_DUMP_EXE)
-lto.start.encap: $(LTO_EXE) $(LTO_DUMP_EXE)
+lto.all.cross:
+lto.start.encap:
lto.rest.encap:
lto.tags:
lto.install-common: installdirs
@@ -84,13 +90,17 @@ lto.stagefeedback:
# Use strict warnings for this front end.
lto-warn = $(STRICT_WARN)
-$(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS)
+$(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS) $(lto1.prev)
+ @$(call LINK_PROGRESS,$(INDEX.lto1),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
+ @$(call LINK_PROGRESS,$(INDEX.lto1),end)
-$(LTO_DUMP_EXE): $(LTO_DUMP_OBJS) $(BACKEND) $(LIBDEPS)
+$(LTO_DUMP_EXE): $(LTO_DUMP_OBJS) $(BACKEND) $(LIBDEPS) $(lto2.prev)
+ @$(call LINK_PROGRESS,$(INDEX.lto2),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(LTO_DUMP_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
+ @$(call LINK_PROGRESS,$(INDEX.lto2),end)
lto/lto-dump.o: $(LTO_OBJS)
diff --git a/gcc/lto/lang.opt b/gcc/lto/lang.opt
index 0d2fbb9..2ef76f1 100644
--- a/gcc/lto/lang.opt
+++ b/gcc/lto/lang.opt
@@ -49,12 +49,12 @@ EnumValue
Enum(lto_linker_output) String(exec) Value(LTO_LINKER_OUTPUT_EXEC)
flinker-output=
-LTO Report Driver Joined RejectNegative Enum(lto_linker_output) Var(flag_lto_linker_output) Init(LTO_LINKER_OUTPUT_UNKNOWN)
+LTO Driver Joined RejectNegative Enum(lto_linker_output) Var(flag_lto_linker_output) Init(LTO_LINKER_OUTPUT_UNKNOWN)
Set linker output type (used internally during LTO optimization).
fltrans
-LTO Report Var(flag_ltrans)
+LTO Var(flag_ltrans)
Run the link-time optimizer in local transformation (LTRANS) mode.
fltrans-output-list=
@@ -62,7 +62,7 @@ LTO Joined Var(ltrans_output_list)
Specify a file to which a list of files output by LTRANS is written.
fwpa
-LTO Driver Report
+LTO Driver
Run the link-time optimizer in whole program analysis (WPA) mode.
fwpa=
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index 3ca0fd8..0a3033c 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -415,8 +415,8 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
that we can use to lookup structurally equivalent non-ODR type.
In case we decide to treat type as unique ODR type we recompute hash based
on name and let TBAA machinery know about our decision. */
- if (RECORD_OR_UNION_TYPE_P (t)
- && odr_type_p (t) && !odr_type_violation_reported_p (t))
+ if (RECORD_OR_UNION_TYPE_P (t) && odr_type_p (t)
+ && TYPE_CXX_ODR_P (t) && !odr_type_violation_reported_p (t))
{
/* Anonymous namespace types never conflict with non-C++ types. */
if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
@@ -434,6 +434,7 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
if (slot && !TYPE_CXX_ODR_P (*(tree *)slot))
{
tree nonodr = *(tree *)slot;
+ gcc_checking_assert (!flag_ltrans);
if (symtab->dump_file)
{
fprintf (symtab->dump_file,
@@ -2592,7 +2593,6 @@ lto_fixup_prevailing_decls (tree t)
case TREE_LIST:
LTO_SET_PREVAIL (TREE_VALUE (t));
LTO_SET_PREVAIL (TREE_PURPOSE (t));
- LTO_NO_PREVAIL (TREE_PURPOSE (t));
break;
default:
gcc_unreachable ();
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 7c15181..cc721f9 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -593,7 +593,8 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
last_visited_node++;
- gcc_assert (node->definition || node->weakref);
+ gcc_assert (node->definition || node->weakref
+ || node->declare_variant_alt);
/* Compute boundary cost of callgraph edges. */
for (edge = node->callees; edge; edge = edge->next_callee)
@@ -704,7 +705,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
int index;
node = dyn_cast <cgraph_node *> (ref->referring);
- gcc_assert (node->definition);
+ gcc_assert (node->definition || node->declare_variant_alt);
index = lto_symtab_encoder_lookup (partition->encoder,
node);
if (index != LCC_NOT_FOUND
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index d5e38be..80457c3 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -694,8 +694,8 @@ lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p)
location in that case. It also happens for AVR if two built-ins
use the same asm name because their libgcc assembler code is the
same, see PR78562. */
- if (DECL_IS_BUILTIN (prevailing->decl)
- && DECL_IS_BUILTIN (decl))
+ if (DECL_IS_UNDECLARED_BUILTIN (prevailing->decl)
+ && DECL_IS_UNDECLARED_BUILTIN (decl))
continue;
int level = warn_type_compatibility_p (TREE_TYPE (prevailing->decl),
@@ -985,7 +985,7 @@ lto_symtab_merge_symbols (void)
/* Do the actual merging.
At this point we invalidate hash translating decls into symtab nodes
because after removing one of duplicate decls the hash is not correcly
- updated to the ohter dupliate. */
+ updated to the other duplicate. */
FOR_EACH_SYMBOL (node)
if (lto_symtab_symbol_p (node)
&& node->next_sharing_asm_name
diff --git a/gcc/machmode.def b/gcc/machmode.def
index e4c9b4b..6f8c685 100644
--- a/gcc/machmode.def
+++ b/gcc/machmode.def
@@ -153,6 +153,9 @@ along with GCC; see the file COPYING3. If not see
the element at index 0 occupying the lsb of the first byte in
memory. Only the lowest bit of each element is significant.
+ OPAQUE_MODE (NAME, BYTESIZE)
+ Create an opaque mode called NAME that is BYTESIZE bytes wide.
+
COMPLEX_MODES (CLASS);
For all modes presently declared in class CLASS, construct
corresponding complex modes. Modes smaller than one byte
diff --git a/gcc/machmode.h b/gcc/machmode.h
index fbeefc2..bb3a5c6 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -225,6 +225,10 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
(SIGNED_FIXED_POINT_MODE_P (MODE) \
|| UNSIGNED_FIXED_POINT_MODE_P (MODE))
+/* Nonzero if MODE is opaque. */
+#define OPAQUE_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_OPAQUE)
+
/* Nonzero if CLASS modes can be widened. */
#define CLASS_HAS_WIDER_MODES_P(CLASS) \
(CLASS == MODE_INT \
diff --git a/gcc/match.pd b/gcc/match.pd
index 17ba041..529933f 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -348,11 +348,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* But not for 0 / 0 so that we can get the proper warnings and errors. */
(if (!integer_zerop (@1))
@0))
- /* X / -1 is -X. */
+ /* X / -1 is -X. */
(simplify
- (div @0 integer_minus_onep@1)
- (if (!TYPE_UNSIGNED (type))
- (negate @0)))
+ (div @0 integer_minus_onep@1)
+ (if (!TYPE_UNSIGNED (type))
+ (negate @0)))
+ /* X / bool_range_Y is X. */
+ (simplify
+ (div @0 SSA_NAME@1)
+ (if (INTEGRAL_TYPE_P (type) && ssa_name_has_boolean_range (@1))
+ @0))
/* X / X is one. */
(simplify
(div @0 @0)
@@ -650,9 +655,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(for div (trunc_div ceil_div floor_div round_div exact_div)
(simplify
(div (mult:c @0 @1) @1)
- (if (ANY_INTEGRAL_TYPE_P (type)
- && TYPE_OVERFLOW_UNDEFINED (type))
- @0)))
+ (if (ANY_INTEGRAL_TYPE_P (type))
+ (if (TYPE_OVERFLOW_UNDEFINED (type))
+ @0
+#if GIMPLE
+ (with
+ {
+ bool overflowed = true;
+ wide_int wmin0, wmax0, wmin1, wmax1;
+ if (INTEGRAL_TYPE_P (type)
+ && get_range_info (@0, &wmin0, &wmax0) == VR_RANGE
+ && get_range_info (@1, &wmin1, &wmax1) == VR_RANGE)
+ {
+ /* If the multiplication can't overflow/wrap around, then
+ it can be optimized too. */
+ wi::overflow_type min_ovf, max_ovf;
+ wi::mul (wmin0, wmin1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmax1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ {
+ wi::mul (wmin0, wmax1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmin1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ overflowed = false;
+ }
+ }
+ }
+ (if (!overflowed)
+ @0))
+#endif
+ ))))
(for op (negate abs)
/* Simplify cos(-x) and cos(|x|) -> cos(x). Similarly for cosh. */
@@ -901,6 +933,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_not (bit_ior:cs (bit_not @0) @1))
(bit_and @0 (bit_not @1)))
+/* (a ^ b) & ((b ^ c) ^ a) --> (a ^ b) & ~c */
+(simplify
+ (bit_and:c (bit_xor:c@3 @0 @1) (bit_xor:cs (bit_xor:cs @1 @2) @0))
+ (bit_and @3 (bit_not @2)))
+
+/* (a ^ b) | ((b ^ c) ^ a) --> (a ^ b) | c */
+(simplify
+ (bit_ior:c (bit_xor:c@3 @0 @1) (bit_xor:c (bit_xor:c @1 @2) @0))
+ (bit_ior @3 @2))
+
/* Simplify (~X & Y) to X ^ Y if we know that (X & ~Y) is 0. */
#if GIMPLE
(simplify
@@ -1037,6 +1079,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_not (plus:c (bit_not @0) @1))
(minus @0 @1))
+/* ~(X - Y) -> ~X + Y. */
+(simplify
+ (bit_not (minus:s @0 @1))
+ (plus (bit_not @0) @1))
+(simplify
+ (bit_not (plus:s @0 INTEGER_CST@1))
+ (if ((INTEGRAL_TYPE_P (type)
+ && TYPE_UNSIGNED (type))
+ || (!TYPE_OVERFLOW_SANITIZED (type)
+ && may_negate_without_overflow_p (@1)))
+ (plus (bit_not @0) { const_unop (NEGATE_EXPR, type, @1); })))
+
+#if GIMPLE
+/* ~X + Y -> (Y - X) - 1. */
+(simplify
+ (plus:c (bit_not @0) @1)
+ (if (ANY_INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type)
+ /* -1 - X is folded to ~X, so we'd recurse endlessly. */
+ && !integer_all_onesp (@1))
+ (plus (minus @1 @0) { build_minus_one_cst (type); })
+ (if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (@1) == INTEGER_CST
+ && wi::to_wide (@1) != wi::min_value (TYPE_PRECISION (type),
+ SIGNED))
+ (minus (plus @1 { build_minus_one_cst (type); }) @0))))
+#endif
+
/* x + (x & 1) -> (x + 1) & ~1 */
(simplify
(plus:c @0 (bit_and:s @0 integer_onep@1))
@@ -1304,6 +1374,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(absu tree_expr_nonnegative_p@0)
(convert @0))
+/* Simplify (-(X < 0) | 1) * X into abs (X). */
+(simplify
+ (mult:c (bit_ior (negate (convert? (lt @0 integer_zerop))) integer_onep) @0)
+ (if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type))
+ (abs @0)))
+
+/* Similarly (-(X < 0) | 1U) * X into absu (X). */
+(simplify
+ (mult:c (bit_ior (nop_convert (negate (convert? (lt @0 integer_zerop))))
+ integer_onep) (nop_convert @0))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_UNSIGNED (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (absu @0)))
+
/* A few cases of fold-const.c negate_expr_p predicate. */
(match negate_expr_p
INTEGER_CST
@@ -1423,6 +1509,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bitop:c (rbitop:c (bit_not @0) @1) @0)
(bitop @0 @1)))
+/* ((x | y) & z) | x -> (z & y) | x */
+(simplify
+ (bit_ior:c (bit_and:cs (bit_ior:cs @0 @1) @2) @0)
+ (bit_ior (bit_and @2 @1) @0))
+
/* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
(simplify
(bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
@@ -2841,6 +2932,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(cmp (minmax @0 INTEGER_CST@1) INTEGER_CST@2)
(comb (cmp @0 @2) (cmp @1 @2))))
+/* X <= MAX(X, Y) -> true
+ X > MAX(X, Y) -> false
+ X >= MIN(X, Y) -> true
+ X < MIN(X, Y) -> false */
+(for minmax (min min max max )
+ cmp (ge lt le gt )
+ (simplify
+ (cmp @0 (minmax:c @0 @1))
+ { constant_boolean_node (cmp == GE_EXPR || cmp == LE_EXPR, type); } ))
+
/* Undo fancy way of writing max/min or other ?: expressions,
like a - ((a - b) & -(a < b)), in this case into (a < b) ? b : a.
People normally use ?: and that is what we actually try to optimize. */
@@ -2890,8 +2991,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Optimize -1 >> x for arithmetic right shifts. */
(simplify
(rshift integer_all_onesp@0 @1)
- (if (!TYPE_UNSIGNED (type)
- && tree_expr_nonnegative_p (@1))
+ (if (!TYPE_UNSIGNED (type))
@0))
/* Optimize (x >> c) << c into x & (-1<<c). */
@@ -2925,6 +3025,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& (wi::ltu_p (wi::to_wide (@1), element_precision (type))))
(bit_and @0 (rshift { build_minus_one_cst (type); } @1))))
+/* Optimize x >> x into 0 */
+(simplify
+ (rshift @0 @0)
+ { build_zero_cst (type); })
+
(for shiftrotate (lrotate rrotate lshift rshift)
(simplify
(shiftrotate @0 integer_zerop)
@@ -3105,7 +3210,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(shift (convert?:s (bit_op:s @0 INTEGER_CST@2)) INTEGER_CST@1)
(if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
(with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); }
- (bit_op (shift (convert @0) @1) { mask; }))))))
+ (if (mask)
+ (bit_op (shift (convert @0) @1) { mask; })))))))
/* ~(~X >> Y) -> X >> Y (for arithmetic shift). */
(simplify
@@ -3755,6 +3861,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(cnd (logical_inverted_value truth_valued_p@0) @1 @2)
(cnd @0 @2 @1)))
+/* -(type)!A -> (type)A - 1. */
+(simplify
+ (negate (convert?:s (logical_inverted_value:s @0)))
+ (if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (type) != BOOLEAN_TYPE
+ && TYPE_PRECISION (type) > 1
+ && TREE_CODE (@0) == SSA_NAME
+ && ssa_name_has_boolean_range (@0))
+ (plus (convert:type @0) { build_all_ones_cst (type); })))
+
/* A + (B vcmp C ? 1 : 0) -> A - (B vcmp C ? -1 : 0), since vector comparisons
return all -1 or all 0 results. */
/* ??? We could instead convert all instances of the vec_cond to negate,
@@ -4917,6 +5033,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ constant_boolean_node (cmp == ORDERED_EXPR || cmp == LTGT_EXPR
? false : true, type); })))
+/* Fold UNORDERED if either operand must be NaN, or neither can be. */
+(simplify
+ (unordered @0 @1)
+ (switch
+ (if (tree_expr_nan_p (@0) || tree_expr_nan_p (@1))
+ { constant_boolean_node (true, type); })
+ (if (!tree_expr_maybe_nan_p (@0) && !tree_expr_maybe_nan_p (@1))
+ { constant_boolean_node (false, type); })))
+
+/* Fold ORDERED if either operand must be NaN, or neither can be. */
+(simplify
+ (ordered @0 @1)
+ (switch
+ (if (tree_expr_nan_p (@0) || tree_expr_nan_p (@1))
+ { constant_boolean_node (false, type); })
+ (if (!tree_expr_maybe_nan_p (@0) && !tree_expr_maybe_nan_p (@1))
+ { constant_boolean_node (true, type); })))
+
/* bool_var != 0 becomes bool_var. */
(simplify
(ne @0 integer_zerop)
@@ -4940,18 +5074,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* When one argument is a constant, overflow detection can be simplified.
Currently restricted to single use so as not to interfere too much with
ADD_OVERFLOW detection in tree-ssa-math-opts.c.
- A + CST CMP A -> A CMP' CST' */
+ CONVERT?(CONVERT?(A) + CST) CMP A -> A CMP' CST' */
(for cmp (lt le ge gt)
out (gt gt le le)
(simplify
- (cmp:c (plus@2 @0 INTEGER_CST@1) @0)
- (if (TYPE_UNSIGNED (TREE_TYPE (@0))
- && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
+ (cmp:c (convert?@3 (plus@2 (convert?@4 @0) INTEGER_CST@1)) @0)
+ (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@2))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@3))
+ && tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@0))
&& wi::to_wide (@1) != 0
&& single_use (@2))
- (with { unsigned int prec = TYPE_PRECISION (TREE_TYPE (@0)); }
+ (with {
+ unsigned int prec = TYPE_PRECISION (TREE_TYPE (@0));
+ signop sign = TYPE_SIGN (TREE_TYPE (@0));
+ }
(out @0 { wide_int_to_tree (TREE_TYPE (@0),
- wi::max_value (prec, UNSIGNED)
+ wi::max_value (prec, sign)
- wi::to_wide (@1)); })))))
/* To detect overflow in unsigned A - B, A < B is simpler than A - B > A.
@@ -5044,7 +5182,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Simplify sqrt(x) * sqrt(x) -> x. */
(simplify
(mult (SQRT_ALL@1 @0) @1)
- (if (!HONOR_SNANS (type))
+ (if (!tree_expr_maybe_signaling_nan_p (@0))
@0))
(for op (plus minus)
@@ -6088,6 +6226,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (single_use (@3))
(IFN_FMA @0 @1 @2))))
+/* CLZ simplifications. */
+(for clz (CLZ)
+ (for op (eq ne)
+ cmp (lt ge)
+ (simplify
+ (op (clz:s @0) INTEGER_CST@1)
+ (if (integer_zerop (@1))
+ /* clz(X) == 0 is (int)X < 0 and clz(X) != 0 is (int)X >= 0. */
+ (with { tree stype = signed_type_for (TREE_TYPE (@0));
+ HOST_WIDE_INT val = 0;
+#ifdef CLZ_DEFINED_VALUE_AT_ZERO
+ /* Punt on hypothetical weird targets. */
+ if (CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (@0)),
+ val) == 2
+ && val == 0)
+ stype = NULL_TREE;
+#endif
+ }
+ (if (stype)
+ (cmp (convert:stype @0) { build_zero_cst (stype); })))
+ /* clz(X) == (prec-1) is X == 1 and clz(X) != (prec-1) is X != 1. */
+ (with { bool ok = true;
+#ifdef CLZ_DEFINED_VALUE_AT_ZERO
+ /* Punt on hypothetical weird targets. */
+ if (CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (@0)),
+ val) == 2
+ && val == TYPE_PRECISION (TREE_TYPE (@0)) - 1)
+ ok = false;
+#endif
+ }
+ (if (ok && wi::to_wide (@1) == (TYPE_PRECISION (TREE_TYPE (@0)) - 1))
+ (op @0 { build_one_cst (TREE_TYPE (@0)); })))))))
+
/* POPCOUNT simplifications. */
/* popcount(X) + popcount(Y) is popcount(X|Y) when X&Y must be zero. */
(simplify
diff --git a/gcc/mode-classes.def b/gcc/mode-classes.def
index f181def0..b78a715 100644
--- a/gcc/mode-classes.def
+++ b/gcc/mode-classes.def
@@ -36,4 +36,5 @@ along with GCC; see the file COPYING3. If not see
DEF_MODE_CLASS (MODE_VECTOR_UFRACT), /* SIMD vectors */ \
DEF_MODE_CLASS (MODE_VECTOR_ACCUM), /* SIMD vectors */ \
DEF_MODE_CLASS (MODE_VECTOR_UACCUM), /* SIMD vectors */ \
- DEF_MODE_CLASS (MODE_VECTOR_FLOAT)
+ DEF_MODE_CLASS (MODE_VECTOR_FLOAT), \
+ DEF_MODE_CLASS (MODE_OPAQUE) /* opaque modes */
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index 6f699a8..4568674 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -210,8 +210,6 @@ static int sms_order_nodes (ddg_ptr, int, int *, int *);
static void set_node_sched_params (ddg_ptr);
static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
static void permute_partial_schedule (partial_schedule_ptr, rtx_insn *);
-static void generate_prolog_epilog (partial_schedule_ptr, class loop *,
- rtx, rtx);
static int calculate_stage_count (partial_schedule_ptr, int);
static void calculate_must_precede_follow (ddg_node_ptr, int, int,
int, int, sbitmap, sbitmap, sbitmap);
@@ -391,30 +389,40 @@ doloop_register_get (rtx_insn *head, rtx_insn *tail)
this constant. Otherwise return 0. */
static rtx_insn *
const_iteration_count (rtx count_reg, basic_block pre_header,
- int64_t * count)
+ int64_t *count, bool* adjust_inplace)
{
rtx_insn *insn;
rtx_insn *head, *tail;
+ *adjust_inplace = false;
+ bool read_after = false;
+
if (! pre_header)
return NULL;
get_ebb_head_tail (pre_header, pre_header, &head, &tail);
for (insn = tail; insn != PREV_INSN (head); insn = PREV_INSN (insn))
- if (NONDEBUG_INSN_P (insn) && single_set (insn) &&
- rtx_equal_p (count_reg, SET_DEST (single_set (insn))))
+ if (single_set (insn) && rtx_equal_p (count_reg,
+ SET_DEST (single_set (insn))))
{
rtx pat = single_set (insn);
if (CONST_INT_P (SET_SRC (pat)))
{
*count = INTVAL (SET_SRC (pat));
+ *adjust_inplace = !read_after;
return insn;
}
return NULL;
}
+ else if (NONDEBUG_INSN_P (insn) && reg_mentioned_p (count_reg, insn))
+ {
+ read_after = true;
+ if (reg_set_p (count_reg, insn))
+ break;
+ }
return NULL;
}
@@ -1126,7 +1134,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
/* Generate the instructions (including reg_moves) for prolog & epilog. */
static void
generate_prolog_epilog (partial_schedule_ptr ps, class loop *loop,
- rtx count_reg, rtx count_init)
+ rtx count_reg, bool adjust_init)
{
int i;
int last_stage = PS_STAGE_COUNT (ps) - 1;
@@ -1135,12 +1143,12 @@ generate_prolog_epilog (partial_schedule_ptr ps, class loop *loop,
/* Generate the prolog, inserting its insns on the loop-entry edge. */
start_sequence ();
- if (!count_init)
+ if (adjust_init)
{
/* Generate instructions at the beginning of the prolog to
- adjust the loop count by STAGE_COUNT. If loop count is constant
- (count_init), this constant is adjusted by STAGE_COUNT in
- generate_prolog_epilog function. */
+ adjust the loop count by STAGE_COUNT. If loop count is constant
+ and it not used anywhere in prologue, this constant is adjusted by
+ STAGE_COUNT outside of generate_prolog_epilog function. */
rtx sub_reg = NULL_RTX;
sub_reg = expand_simple_binop (GET_MODE (count_reg), MINUS, count_reg,
@@ -1528,7 +1536,8 @@ sms_schedule (void)
rtx_insn *count_init;
int mii, rec_mii, stage_count, min_cycle;
int64_t loop_count = 0;
- bool opt_sc_p;
+ bool opt_sc_p, adjust_inplace = false;
+ basic_block pre_header;
if (! (g = g_arr[loop->num]))
continue;
@@ -1569,19 +1578,13 @@ sms_schedule (void)
}
- /* In case of th loop have doloop register it gets special
- handling. */
- count_init = NULL;
- if ((count_reg = doloop_register_get (head, tail)))
- {
- basic_block pre_header;
-
- pre_header = loop_preheader_edge (loop)->src;
- count_init = const_iteration_count (count_reg, pre_header,
- &loop_count);
- }
+ count_reg = doloop_register_get (head, tail);
gcc_assert (count_reg);
+ pre_header = loop_preheader_edge (loop)->src;
+ count_init = const_iteration_count (count_reg, pre_header, &loop_count,
+ &adjust_inplace);
+
if (dump_file && count_init)
{
fprintf (dump_file, "SMS const-doloop ");
@@ -1701,9 +1704,20 @@ sms_schedule (void)
print_partial_schedule (ps, dump_file);
}
- /* case the BCT count is not known , Do loop-versioning */
- if (count_reg && ! count_init)
+ if (count_init)
+ {
+ if (adjust_inplace)
+ {
+ /* When possible, set new iteration count of loop kernel in
+ place. Otherwise, generate_prolog_epilog creates an insn
+ to adjust. */
+ SET_SRC (single_set (count_init)) = GEN_INT (loop_count
+ - stage_count + 1);
+ }
+ }
+ else
{
+ /* case the BCT count is not known , Do loop-versioning */
rtx comp_rtx = gen_rtx_GT (VOIDmode, count_reg,
gen_int_mode (stage_count,
GET_MODE (count_reg)));
@@ -1713,12 +1727,7 @@ sms_schedule (void)
loop_version (loop, comp_rtx, &condition_bb,
prob, prob.invert (),
prob, prob.invert (), true);
- }
-
- /* Set new iteration count of loop kernel. */
- if (count_reg && count_init)
- SET_SRC (single_set (count_init)) = GEN_INT (loop_count
- - stage_count + 1);
+ }
/* Now apply the scheduled kernel to the RTL of the loop. */
permute_partial_schedule (ps, g->closing_branch->first_note);
@@ -1735,7 +1744,7 @@ sms_schedule (void)
if (dump_file)
print_node_sched_params (dump_file, g->num_nodes, ps);
/* Generate prolog and epilog. */
- generate_prolog_epilog (ps, loop, count_reg, count_init);
+ generate_prolog_epilog (ps, loop, count_reg, !adjust_inplace);
break;
}
diff --git a/gcc/mux-utils.h b/gcc/mux-utils.h
new file mode 100644
index 0000000..b026a9f
--- /dev/null
+++ b/gcc/mux-utils.h
@@ -0,0 +1,251 @@
+// Multiplexer utilities
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_MUX_UTILS_H
+#define GCC_MUX_UTILS_H 1
+
+// A class that stores a choice "A or B", where A has type T1 * and B has
+// type T2 *. Both T1 and T2 must have an alignment greater than 1, since
+// the low bit is used to identify B over A. T1 and T2 can be the same.
+//
+// A can be a null pointer but B cannot.
+//
+// Barring the requirement that B must be nonnull, using the class is
+// equivalent to using:
+//
+// union { T1 *A; T2 *B; };
+//
+// and having a separate tag bit to indicate which alternative is active.
+// However, using this class can have two advantages over a union:
+//
+// - It avoides the need to find somewhere to store the tag bit.
+//
+// - The compiler is aware that B cannot be null, which can make checks
+// of the form:
+//
+// if (auto *B = mux.dyn_cast<T2 *> ())
+//
+// more efficient. With a union-based representation, the dyn_cast
+// check could fail either because MUX is an A or because MUX is a
+// null B, both of which require a run-time test. With a pointer_mux,
+// only a check for MUX being A is needed.
+template<typename T1, typename T2 = T1>
+class pointer_mux
+{
+public:
+ // Return an A pointer with the given value.
+ static pointer_mux first (T1 *);
+
+ // Return a B pointer with the given (nonnull) value.
+ static pointer_mux second (T2 *);
+
+ pointer_mux () = default;
+
+ // Create a null A pointer.
+ pointer_mux (std::nullptr_t) : m_ptr (nullptr) {}
+
+ // Create an A or B pointer with the given value. This is only valid
+ // if T1 and T2 are distinct and if T can be resolved to exactly one
+ // of them.
+ template<typename T,
+ typename Enable = typename
+ std::enable_if<std::is_convertible<T *, T1 *>::value
+ != std::is_convertible<T *, T2 *>::value>::type>
+ pointer_mux (T *ptr);
+
+ // Return true unless the pointer is a null A pointer.
+ explicit operator bool () const { return m_ptr; }
+
+ // Assign A and B pointers respectively.
+ void set_first (T1 *ptr) { *this = first (ptr); }
+ void set_second (T2 *ptr) { *this = second (ptr); }
+
+ // Return true if the pointer is an A pointer.
+ bool is_first () const { return !(uintptr_t (m_ptr) & 1); }
+
+ // Return true if the pointer is a B pointer.
+ bool is_second () const { return uintptr_t (m_ptr) & 1; }
+
+ // Return the contents of the pointer, given that it is known to be
+ // an A pointer.
+ T1 *known_first () const { return reinterpret_cast<T1 *> (m_ptr); }
+
+ // Return the contents of the pointer, given that it is known to be
+ // a B pointer.
+ T2 *known_second () const { return reinterpret_cast<T2 *> (m_ptr - 1); }
+
+ // If the pointer is an A pointer, return its contents, otherwise
+ // return null. Thus a null return can mean that the pointer is
+ // either a null A pointer or a B pointer.
+ //
+ // If all A pointers are nonnull, it is more efficient to use:
+ //
+ // if (ptr.is_first ())
+ // ...use ptr.known_first ()...
+ //
+ // over:
+ //
+ // if (T1 *a = ptr.first_or_null ())
+ // ...use a...
+ T1 *first_or_null () const;
+
+ // If the pointer is a B pointer, return its contents, otherwise
+ // return null. Using:
+ //
+ // if (T1 *b = ptr.second_or_null ())
+ // ...use b...
+ //
+ // should be at least as efficient as:
+ //
+ // if (ptr.is_second ())
+ // ...use ptr.known_second ()...
+ T2 *second_or_null () const;
+
+ // Return true if the pointer is a T.
+ //
+ // This is only valid if T1 and T2 are distinct and if T can be
+ // resolved to exactly one of them. The condition is checked using
+ // a static assertion rather than SFINAE because it gives a clearer
+ // error message.
+ template<typename T>
+ bool is_a () const;
+
+ // Assert that the pointer is a T and return it as such. See is_a
+ // for the restrictions on T.
+ template<typename T>
+ T as_a () const;
+
+ // If the pointer is a T, return it as such, otherwise return null.
+ // See is_a for the restrictions on T.
+ template<typename T>
+ T dyn_cast () const;
+
+private:
+ pointer_mux (char *ptr) : m_ptr (ptr) {}
+
+ // The pointer value for A pointers, or the pointer value + 1 for B pointers.
+ // Using a pointer rather than a uintptr_t tells the compiler that second ()
+ // can never return null, and that second_or_null () is only null if
+ // is_first ().
+ char *m_ptr;
+};
+
+template<typename T1, typename T2>
+inline pointer_mux<T1, T2>
+pointer_mux<T1, T2>::first (T1 *ptr)
+{
+ gcc_checking_assert (!(uintptr_t (ptr) & 1));
+ return reinterpret_cast<char *> (ptr);
+}
+
+template<typename T1, typename T2>
+inline pointer_mux<T1, T2>
+pointer_mux<T1, T2>::second (T2 *ptr)
+{
+ gcc_checking_assert (ptr && !(uintptr_t (ptr) & 1));
+ return reinterpret_cast<char *> (ptr) + 1;
+}
+
+template<typename T1, typename T2>
+template<typename T, typename Enable>
+inline pointer_mux<T1, T2>::pointer_mux (T *ptr)
+ : m_ptr (reinterpret_cast<char *> (ptr))
+{
+ if (std::is_convertible<T *, T2 *>::value)
+ {
+ gcc_checking_assert (m_ptr);
+ m_ptr += 1;
+ }
+}
+
+template<typename T1, typename T2>
+inline T1 *
+pointer_mux<T1, T2>::first_or_null () const
+{
+ return is_first () ? known_first () : nullptr;
+}
+
+template<typename T1, typename T2>
+inline T2 *
+pointer_mux<T1, T2>::second_or_null () const
+{
+ // Micro optimization that's effective as of GCC 11: compute the value
+ // of the second pointer as an integer and test that, so that the integer
+ // result can be reused as the pointer and so that all computation can
+ // happen before a branch on null. This reduces the number of branches
+ // needed for loops.
+ return (uintptr_t (m_ptr) - 1) & 1 ? nullptr : known_second ();
+}
+
+template<typename T1, typename T2>
+template<typename T>
+inline bool
+pointer_mux<T1, T2>::is_a () const
+{
+ static_assert (std::is_convertible<T1 *, T>::value
+ != std::is_convertible<T2 *, T>::value,
+ "Ambiguous pointer type");
+ if (std::is_convertible<T2 *, T>::value)
+ return is_second ();
+ else
+ return is_first ();
+}
+
+template<typename T1, typename T2>
+template<typename T>
+inline T
+pointer_mux<T1, T2>::as_a () const
+{
+ static_assert (std::is_convertible<T1 *, T>::value
+ != std::is_convertible<T2 *, T>::value,
+ "Ambiguous pointer type");
+ if (std::is_convertible<T2 *, T>::value)
+ {
+ gcc_checking_assert (is_second ());
+ return reinterpret_cast<T> (m_ptr - 1);
+ }
+ else
+ {
+ gcc_checking_assert (is_first ());
+ return reinterpret_cast<T> (m_ptr);
+ }
+}
+
+template<typename T1, typename T2>
+template<typename T>
+inline T
+pointer_mux<T1, T2>::dyn_cast () const
+{
+ static_assert (std::is_convertible<T1 *, T>::value
+ != std::is_convertible<T2 *, T>::value,
+ "Ambiguous pointer type");
+ if (std::is_convertible<T2 *, T>::value)
+ {
+ if (is_second ())
+ return reinterpret_cast<T> (m_ptr - 1);
+ }
+ else
+ {
+ if (is_first ())
+ return reinterpret_cast<T> (m_ptr);
+ }
+ return nullptr;
+}
+
+#endif
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index f69d2d7..3e83a4f 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,79 @@
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (objc.serial): Change from goal to a variable.
+ (.PHONY): Drop objc.serial and objc.prev.
+ (cc1obj$(exeext)): Depend on $(objc.serial) rather than objc.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (objc.serial): New goal.
+ (.PHONY): Add objc.serial objc.prev.
+ (cc1obj$(exeext)): Depend on objc.prev. Call LINK_PROGRESS.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90707
+ * objc-act.c (objc_prop_attr_kind_for_rid): Handle nullability.
+ (objc_add_property_declaration): Handle nullability attributes.
+ Check that these are applicable to the property type.
+ * objc-act.h (enum objc_property_nullability): New.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * objc-act.c (objc_start_class_interface): Accept the location
+ of the class name, use it in existing diagnostic.
+ (start_class): Accept obj_root_class type attributes. Warn when
+ the interface for an implementation does not contain a super
+ class (unless the diagnostic is suppressed by the the command
+ line flag or the objc_root_class type attribute).
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_prop_attr_kind_for_rid): Handle class
+ attribute.
+ (objc_add_property_declaration): Likewise.
+ * objc-act.h (PROPERTY_CLASS): Record class attribute state.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_prop_attr_kind_for_rid): Handle
+ RID_PROPATOMIC.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_compare_types): Handle NSObject type
+ attributes.
+ (objc_type_valid_for_messaging): Likewise.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (start_class): Accept visibility attributes
+ without warning.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_prop_attr_kind_for_rid): New.
+ (objc_add_property_declaration): Adjust to consume the
+ parser output using a vector of parsed attributes.
+
+2020-11-04 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (objc_non_constant_expr_p): New.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc-act.c (synth_module_prologue): Get the SEL identifier.
+ * objc-act.h (enum objc_tree_index): Add OCTI_SEL_NAME.
+ (objc_selector_name): New.
+ (SEL_TYPEDEF_NAME): New.
+ * objc-gnu-runtime-abi-01.c
+ (gnu_runtime_01_initialize): Initialize SEL typedef.
+ * objc-next-runtime-abi-01.c
+ (next_runtime_01_initialize): Likewise.
+ * objc-next-runtime-abi-02.c
+
2020-10-11 Iain Sandoe <iain@sandoe.co.uk>
* objc-next-runtime-abi-02.c
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index add1355..2edf0a9 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -38,6 +38,7 @@
#
# Define the names for selecting Objective-C in LANGUAGES.
objc: cc1obj$(exeext)
+objc.serial = cc1obj$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: objc
@@ -62,10 +63,13 @@ cc1obj-checksum.c : build/genchecksum$(build_exeext) checksum-options \
$(BACKEND) $(LIBDEPS) checksum-options > cc1obj-checksum.c.tmp && \
$(srcdir)/../move-if-change cc1obj-checksum.c.tmp cc1obj-checksum.c
-cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(LIBDEPS)
+cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) \
+ $(LIBDEPS) $(objc.prev)
+ @$(call LINK_PROGRESS,$(INDEX.objc),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o \
$(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.objc),end)
objc.srcextra:
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 31a2cf3..2700bbe 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -571,11 +571,11 @@ lookup_protocol_in_reflist (tree rproto_list, tree lproto)
}
void
-objc_start_class_interface (tree klass, tree super_class,
+objc_start_class_interface (tree klass, location_t name_loc, tree super_class,
tree protos, tree attributes)
{
if (flag_objc1_only && attributes)
- error_at (input_location, "class attributes are not available in Objective-C 1.0");
+ error_at (name_loc, "class attributes are not available in Objective-C 1.0");
objc_interface_context
= objc_ivar_context
@@ -804,119 +804,81 @@ lookup_property (tree interface_type, tree property)
return inter;
}
+/* This routine returns a PROPERTY_KIND for the front end RID code supplied. */
+
+enum objc_property_attribute_kind
+objc_prop_attr_kind_for_rid (enum rid prop_rid)
+{
+ switch (prop_rid)
+ {
+ default: return OBJC_PROPERTY_ATTR_UNKNOWN;
+ case RID_GETTER: return OBJC_PROPERTY_ATTR_GETTER;
+ case RID_SETTER: return OBJC_PROPERTY_ATTR_SETTER;
+
+ case RID_READONLY: return OBJC_PROPERTY_ATTR_READONLY;
+ case RID_READWRITE: return OBJC_PROPERTY_ATTR_READWRITE;
+
+ case RID_ASSIGN: return OBJC_PROPERTY_ATTR_ASSIGN;
+ case RID_RETAIN: return OBJC_PROPERTY_ATTR_RETAIN;
+ case RID_COPY: return OBJC_PROPERTY_ATTR_COPY;
+
+ case RID_PROPATOMIC: return OBJC_PROPERTY_ATTR_ATOMIC;
+ case RID_NONATOMIC: return OBJC_PROPERTY_ATTR_NONATOMIC;
+
+ case RID_NULL_UNSPECIFIED:return OBJC_PROPERTY_ATTR_NULL_UNSPECIFIED;
+ case RID_NULLABLE: return OBJC_PROPERTY_ATTR_NULLABLE;
+ case RID_NONNULL: return OBJC_PROPERTY_ATTR_NONNULL;
+ case RID_NULL_RESETTABLE: return OBJC_PROPERTY_ATTR_NULL_RESETTABLE;
+
+ case RID_CLASS: return OBJC_PROPERTY_ATTR_CLASS;
+ }
+}
+
/* This routine is called by the parser when a
@property... declaration is found. 'decl' is the declaration of
the property (type/identifier), and the other arguments represent
property attributes that may have been specified in the Objective-C
declaration. 'parsed_property_readonly' is 'true' if the attribute
'readonly' was specified, and 'false' if not; similarly for the
- other bool parameters. 'parsed_property_getter_ident' is NULL_TREE
+ other bool parameters. 'property_getter_ident' is NULL_TREE
if the attribute 'getter' was not specified, and is the identifier
corresponding to the specified getter if it was; similarly for
- 'parsed_property_setter_ident'. */
+ 'property_setter_ident'. */
void
objc_add_property_declaration (location_t location, tree decl,
- bool parsed_property_readonly, bool parsed_property_readwrite,
- bool parsed_property_assign, bool parsed_property_retain,
- bool parsed_property_copy, bool parsed_property_nonatomic,
- tree parsed_property_getter_ident, tree parsed_property_setter_ident)
+ vec<property_attribute_info *>& prop_attr_list)
{
- tree property_decl;
- tree x;
- /* 'property_readonly' and 'property_assign_semantics' are the final
- attributes of the property after all parsed attributes have been
- considered (eg, if we parsed no 'readonly' and no 'readwrite', ie
- parsed_property_readonly = false and parsed_property_readwrite =
- false, then property_readonly will be false because the default
- is readwrite). */
- bool property_readonly = false;
- objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
- bool property_extension_in_class_extension = false;
-
if (flag_objc1_only)
- error_at (input_location, "%<@property%> is not available in Objective-C 1.0");
-
- if (parsed_property_readonly && parsed_property_readwrite)
- {
- error_at (location, "%<readonly%> attribute conflicts with %<readwrite%> attribute");
- /* In case of conflicting attributes (here and below), after
- producing an error, we pick one of the attributes and keep
- going. */
- property_readonly = false;
- }
- else
- {
- if (parsed_property_readonly)
- property_readonly = true;
-
- if (parsed_property_readwrite)
- property_readonly = false;
- }
-
- if (parsed_property_readonly && parsed_property_setter_ident)
- {
- error_at (location, "%<readonly%> attribute conflicts with %<setter%> attribute");
- property_readonly = false;
- }
-
- if (parsed_property_assign && parsed_property_retain)
- {
- error_at (location, "%<assign%> attribute conflicts with %<retain%> attribute");
- property_assign_semantics = OBJC_PROPERTY_RETAIN;
- }
- else if (parsed_property_assign && parsed_property_copy)
- {
- error_at (location, "%<assign%> attribute conflicts with %<copy%> attribute");
- property_assign_semantics = OBJC_PROPERTY_COPY;
- }
- else if (parsed_property_retain && parsed_property_copy)
- {
- error_at (location, "%<retain%> attribute conflicts with %<copy%> attribute");
- property_assign_semantics = OBJC_PROPERTY_COPY;
- }
- else
- {
- if (parsed_property_assign)
- property_assign_semantics = OBJC_PROPERTY_ASSIGN;
-
- if (parsed_property_retain)
- property_assign_semantics = OBJC_PROPERTY_RETAIN;
-
- if (parsed_property_copy)
- property_assign_semantics = OBJC_PROPERTY_COPY;
- }
+ /* FIXME: we probably ought to bail out at this point. */
+ error_at (location, "%<@property%> is not available in Objective-C 1.0");
+ /* We must be in an interface, category, or protocol. */
if (!objc_interface_context)
{
- error_at (location, "property declaration not in @interface or @protocol context");
+ error_at (location, "property declaration not in %<@interface%>,"
+ " %<@protocol%> or %<category%> context");
return;
}
- /* At this point we know that we are either in an interface, a
- category, or a protocol. */
+ /* Do some spot-checks for the most obvious invalid cases. */
+
+ gcc_checking_assert (decl && TREE_CODE (decl) == FIELD_DECL);
- /* We expect a FIELD_DECL from the parser. Make sure we didn't get
- something else, as that would confuse the checks below. */
- if (TREE_CODE (decl) != FIELD_DECL)
+ if (decl && !DECL_NAME (decl))
{
- error_at (location, "invalid property declaration");
+ error_at (location, "properties must be named");
return;
}
- /* Do some spot-checks for the most obvious invalid types. */
-
+ location_t decl_loc = DECL_SOURCE_LOCATION (decl);
+ decl_loc = make_location (decl_loc, location, decl_loc);
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
- error_at (location, "property cannot be an array");
+ error_at (decl_loc, "property cannot be an array");
return;
}
- /* The C++/ObjC++ parser seems to reject the ':' for a bitfield when
- parsing, while the C/ObjC parser accepts it and gives us a
- FIELD_DECL with a DECL_INITIAL set. So we use the DECL_INITIAL
- to check for a bitfield when doing ObjC. */
-#ifndef OBJCPLUS
- if (DECL_INITIAL (decl))
+ if (DECL_C_BIT_FIELD (decl))
{
/* A @property is not an actual variable, but it is a way to
describe a pair of accessor methods, so its type (which is
@@ -925,10 +887,139 @@ objc_add_property_declaration (location_t location, tree decl,
and arguments of functions cannot be bitfields). The
underlying instance variable could be a bitfield, but that is
a different matter. */
- error_at (location, "property cannot be a bit-field");
+ error_at (decl_loc, "property cannot be a bit-field");
return;
}
-#endif
+
+ /* The final results of parsing the (growing number) of property
+ attributes. */
+ property_attribute_info *attrs[OBJC_PROPATTR_GROUP_MAX] = { nullptr };
+
+ tree property_getter_ident = NULL_TREE;
+ tree property_setter_ident = NULL_TREE;
+ for (unsigned pn = 0; pn < prop_attr_list.length (); ++pn)
+ {
+ if (prop_attr_list[pn]->parse_error)
+ continue; /* Ignore attributes known to be wrongly parsed. */
+
+ switch (int g = (int) prop_attr_list[pn]->group())
+ {
+ case OBJC_PROPATTR_GROUP_UNKNOWN:
+ continue;
+ case OBJC_PROPATTR_GROUP_SETTER:
+ case OBJC_PROPATTR_GROUP_GETTER:
+ if (attrs[g])
+ {
+ warning_at (prop_attr_list[pn]->prop_loc, OPT_Wattributes,
+ "multiple property %qE methods specified, the latest"
+ " one will be used", attrs[g]->name);
+ inform (attrs[g]->prop_loc, "previous specification");
+ }
+ attrs[g] = prop_attr_list[pn];
+ if (g == OBJC_PROPATTR_GROUP_SETTER)
+ property_setter_ident = attrs[g]->ident;
+ else
+ property_getter_ident = attrs[g]->ident;
+ continue;
+ default:
+ {
+ if (!attrs[g])
+ ;
+ else if (attrs[g]->prop_kind != prop_attr_list[pn]->prop_kind)
+ {
+ error_at (prop_attr_list[pn]->prop_loc,
+ "%qE attribute conflicts with %qE attribute",
+ prop_attr_list[pn]->name, attrs[g]->name);
+ inform (attrs[g]->prop_loc, "%qE specified here",
+ attrs[g]->name );
+ }
+ else
+ {
+ warning_at (prop_attr_list[pn]->prop_loc, OPT_Wattributes,
+ "duplicate %qE attribute", attrs[g]->name);
+ inform (attrs[g]->prop_loc, "first specified here");
+ }
+ attrs[g] = prop_attr_list[pn];
+ }
+ continue;
+ }
+ }
+
+ /* The defaults for atomicity (atomic) and write-ability (readwrite) apply
+ even if the user provides no specified attributes. */
+ bool property_nonatomic = false;
+ bool property_readonly = false;
+
+ /* Set the values from any specified by the user; these are easy, only two
+ states. */
+ if (attrs[OBJC_PROPATTR_GROUP_ATOMIC])
+ property_nonatomic = attrs[OBJC_PROPATTR_GROUP_ATOMIC]->prop_kind
+ == OBJC_PROPERTY_ATTR_NONATOMIC;
+
+ if (attrs[OBJC_PROPATTR_GROUP_READWRITE])
+ property_readonly = attrs[OBJC_PROPATTR_GROUP_READWRITE]->prop_kind
+ == OBJC_PROPERTY_ATTR_READONLY;
+
+ /* One can't set a readonly value; we issue an error, but force the property
+ to readwrite as well. */
+ if (property_readonly && property_setter_ident)
+ {
+ error_at (attrs[OBJC_PROPATTR_GROUP_READWRITE]->prop_loc, "%<readonly%>"
+ " attribute conflicts with %<setter%> attribute");
+ gcc_checking_assert (attrs[OBJC_PROPATTR_GROUP_SETTER]);
+ inform (attrs[OBJC_PROPATTR_GROUP_SETTER]->prop_loc, "%<setter%>"
+ " specified here");
+ property_readonly = false;
+ }
+
+ /* Assign semantics is a tri-state property, and also needs some further
+ checking against the object type. */
+ objc_property_assign_semantics property_assign_semantics
+ = OBJC_PROPERTY_ASSIGN;
+
+ if (attrs[OBJC_PROPATTR_GROUP_ASSIGN])
+ {
+ if (attrs[OBJC_PROPATTR_GROUP_ASSIGN]->prop_kind
+ == OBJC_PROPERTY_ATTR_ASSIGN)
+ property_assign_semantics = OBJC_PROPERTY_ASSIGN;
+ else if (attrs[OBJC_PROPATTR_GROUP_ASSIGN]->prop_kind
+ == OBJC_PROPERTY_ATTR_RETAIN)
+ property_assign_semantics = OBJC_PROPERTY_RETAIN;
+ else if (attrs[OBJC_PROPATTR_GROUP_ASSIGN]->prop_kind
+ == OBJC_PROPERTY_ATTR_COPY)
+ property_assign_semantics = OBJC_PROPERTY_COPY;
+ else
+ gcc_unreachable ();
+ }
+
+ /* An attribute that indicates this property manipulates a class variable.
+ In this case, both the variable and the getter/setter must be provided
+ by the user. */
+ bool property_class = false;
+ if (attrs[OBJC_PROPATTR_GROUP_CLASS])
+ property_nonatomic = attrs[OBJC_PROPATTR_GROUP_CLASS]->prop_kind
+ == OBJC_PROPERTY_ATTR_CLASS;
+
+ /* Nullability specifications for the property. */
+ enum objc_property_nullability property_nullability
+ = OBJC_PROPERTY_NULL_UNSET;
+ if (attrs[OBJC_PROPATTR_GROUP_NULLABLE])
+ {
+ if (attrs[OBJC_PROPATTR_GROUP_NULLABLE]->prop_kind
+ == OBJC_PROPERTY_ATTR_NULL_UNSPECIFIED)
+ property_nullability = OBJC_PROPERTY_NULL_UNSPECIFIED;
+ else if (attrs[OBJC_PROPATTR_GROUP_NULLABLE]->prop_kind
+ == OBJC_PROPERTY_ATTR_NULLABLE)
+ property_nullability = OBJC_PROPERTY_NULLABLE;
+ else if (attrs[OBJC_PROPATTR_GROUP_NULLABLE]->prop_kind
+ == OBJC_PROPERTY_ATTR_NONNULL)
+ property_nullability = OBJC_PROPERTY_NONNULL;
+ else if (attrs[OBJC_PROPATTR_GROUP_NULLABLE]->prop_kind
+ == OBJC_PROPERTY_ATTR_NULL_RESETTABLE)
+ property_nullability = OBJC_PROPERTY_NULL_RESETTABLE;
+ else
+ gcc_unreachable ();
+ }
/* TODO: Check that the property type is an Objective-C object or a
"POD". */
@@ -950,69 +1041,77 @@ objc_add_property_declaration (location_t location, tree decl,
for non-{Objective-C objects}, and to 'retain' for
Objective-C objects. But that would break compatibility with
other compilers. */
- if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy)
+ if (!attrs[OBJC_PROPATTR_GROUP_ASSIGN])
{
/* Use 'false' so we do not warn for Class objects. */
if (objc_type_valid_for_messaging (TREE_TYPE (decl), false))
{
- warning_at (location,
- 0,
- "object property %qD has no %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>",
- decl);
- inform (location,
- "%<assign%> can be unsafe for Objective-C objects; please state explicitly if you need it");
+ warning_at (decl_loc, 0, "object property %qD has no %<assign%>,"
+ " %<retain%> or %<copy%> attribute; assuming"
+ " %<assign%>", decl);
+ inform (decl_loc, "%<assign%> can be unsafe for Objective-C"
+ " objects; please state explicitly if you need it");
}
}
}
- if (property_assign_semantics == OBJC_PROPERTY_RETAIN
- && !objc_type_valid_for_messaging (TREE_TYPE (decl), true))
- error_at (location, "%<retain%> attribute is only valid for Objective-C objects");
+ /* Some attributes make no sense unless applied to an Objective-C object. */
+ bool prop_objc_object_p
+ = objc_type_valid_for_messaging (TREE_TYPE (decl), true);
+ if (!prop_objc_object_p)
+ {
+ tree p_name = NULL_TREE;
+ if (property_assign_semantics == OBJC_PROPERTY_RETAIN
+ || property_assign_semantics == OBJC_PROPERTY_COPY)
+ p_name = attrs[OBJC_PROPATTR_GROUP_ASSIGN]->name;
- if (property_assign_semantics == OBJC_PROPERTY_COPY
- && !objc_type_valid_for_messaging (TREE_TYPE (decl), true))
- error_at (location, "%<copy%> attribute is only valid for Objective-C objects");
+ if (p_name)
+ error_at (decl_loc, "%qE attribute is only valid for Objective-C"
+ " objects", p_name);
+ }
/* Now determine the final property getter and setter names. They
will be stored in the PROPERTY_DECL, from which they'll always be
extracted and used. */
/* Adjust, or fill in, setter and getter names. We overwrite the
- parsed_property_setter_ident and parsed_property_getter_ident
+ property_setter_ident and property_getter_ident
with the final setter and getter identifiers that will be
used. */
- if (parsed_property_setter_ident)
+ if (property_setter_ident)
{
/* The setter should be terminated by ':', but the parser only
gives us an identifier without ':'. So, we need to add ':'
at the end. */
- const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
+ const char *parsed_setter = IDENTIFIER_POINTER (property_setter_ident);
size_t length = strlen (parsed_setter);
char *final_setter = (char *)alloca (length + 2);
sprintf (final_setter, "%s:", parsed_setter);
- parsed_property_setter_ident = get_identifier (final_setter);
+ property_setter_ident = get_identifier (final_setter);
}
else
{
if (!property_readonly)
- parsed_property_setter_ident = get_identifier (objc_build_property_setter_name
+ property_setter_ident = get_identifier (objc_build_property_setter_name
(DECL_NAME (decl)));
}
- if (!parsed_property_getter_ident)
- parsed_property_getter_ident = DECL_NAME (decl);
+ if (!property_getter_ident)
+ property_getter_ident = DECL_NAME (decl);
/* Check for duplicate property declarations. We first check the
immediate context for a property with the same name. Any such
declarations are an error, unless this is a class extension and
we are extending a property from readonly to readwrite. */
+ bool property_extension_in_class_extension = false;
+ tree x = NULL_TREE;
for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
{
if (PROPERTY_NAME (x) == DECL_NAME (decl))
{
if (objc_in_class_extension
- && property_readonly == 0
+ && !property_readonly
&& PROPERTY_READONLY (x) == 1)
{
/* This is a class extension, and we are extending an
@@ -1087,7 +1186,7 @@ objc_add_property_declaration (location_t location, tree decl,
types, or it is compatible. */
location_t original_location = DECL_SOURCE_LOCATION (x);
- if (PROPERTY_NONATOMIC (x) != parsed_property_nonatomic)
+ if (PROPERTY_NONATOMIC (x) != property_nonatomic)
{
warning_at (location, 0,
"%<nonatomic%> attribute of property %qD conflicts with "
@@ -1098,7 +1197,7 @@ objc_add_property_declaration (location_t location, tree decl,
return;
}
- if (PROPERTY_GETTER_NAME (x) != parsed_property_getter_ident)
+ if (PROPERTY_GETTER_NAME (x) != property_getter_ident)
{
warning_at (location, 0,
"%<getter%> attribute of property %qD conflicts with "
@@ -1112,7 +1211,7 @@ objc_add_property_declaration (location_t location, tree decl,
/* We can only compare the setter names if both the old and new property have a setter. */
if (!property_readonly && !PROPERTY_READONLY(x))
{
- if (PROPERTY_SETTER_NAME (x) != parsed_property_setter_ident)
+ if (PROPERTY_SETTER_NAME (x) != property_setter_ident)
{
warning_at (location, 0,
"%<setter%> attribute of property %qD conflicts with "
@@ -1190,29 +1289,53 @@ objc_add_property_declaration (location_t location, tree decl,
if (property_extension_in_class_extension)
{
PROPERTY_READONLY (x) = 0;
- PROPERTY_SETTER_NAME (x) = parsed_property_setter_ident;
+ PROPERTY_SETTER_NAME (x) = property_setter_ident;
return;
}
}
/* Create a PROPERTY_DECL node. */
- property_decl = make_node (PROPERTY_DECL);
+ tree property_decl = make_node (PROPERTY_DECL);
/* Copy the basic information from the original decl. */
- TREE_TYPE (property_decl) = TREE_TYPE (decl);
+ tree p_type = TREE_TYPE (decl);
+ TREE_TYPE (property_decl) = p_type;
DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
/* Add property-specific information. */
PROPERTY_NAME (property_decl) = DECL_NAME (decl);
- PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
- PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
+ PROPERTY_GETTER_NAME (property_decl) = property_getter_ident;
+ PROPERTY_SETTER_NAME (property_decl) = property_setter_ident;
PROPERTY_READONLY (property_decl) = property_readonly;
- PROPERTY_NONATOMIC (property_decl) = parsed_property_nonatomic;
+ PROPERTY_NONATOMIC (property_decl) = property_nonatomic;
+ PROPERTY_CLASS (property_decl) = property_class;
PROPERTY_ASSIGN_SEMANTICS (property_decl) = property_assign_semantics;
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
PROPERTY_DYNAMIC (property_decl) = 0;
+ /* FIXME: We seem to drop any existing DECL_ATTRIBUTES on the floor. */
+ if (property_nullability != OBJC_PROPERTY_NULL_UNSET)
+ {
+ if (p_type && !POINTER_TYPE_P (p_type))
+ error_at (decl_loc, "nullability specifier %qE cannot be applied to"
+ " non-pointer type %qT",
+ attrs[OBJC_PROPATTR_GROUP_NULLABLE]->name, p_type);
+ else if (p_type && POINTER_TYPE_P (p_type) && TREE_TYPE (p_type)
+ && POINTER_TYPE_P (TREE_TYPE (p_type)))
+ error_at (decl_loc, "nullability specifier %qE cannot be applied to"
+ " multi-level pointer type %qT",
+ attrs[OBJC_PROPATTR_GROUP_NULLABLE]->name, p_type);
+ else
+ {
+ tree attr_name = get_identifier ("objc_nullability");
+ tree attr_value = build_int_cst (unsigned_type_node,
+ (unsigned)property_nullability);
+ tree nulla = build_tree_list (attr_name, attr_value);
+ DECL_ATTRIBUTES (property_decl) = nulla;
+ }
+ }
+
/* Remember the fact that the property was found in the @optional
section in a @protocol, or not. */
if (objc_method_optional_flag)
@@ -1720,7 +1843,6 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
}
-
/* This is used because we don't want to expose PROPERTY_REF to the
C/C++ frontends. Maybe we should! */
bool
@@ -1732,6 +1854,21 @@ objc_is_property_ref (tree node)
return false;
}
+/* We use this to report tree codes that are known to be invalid in const-
+ expression contexts. */
+bool
+objc_non_constant_expr_p (tree node)
+{
+ switch (TREE_CODE (node))
+ {
+ default:
+ return false;
+ case MESSAGE_SEND_EXPR:
+ case PROPERTY_REF:
+ return true;
+ }
+}
+
/* This function builds a setter call for a PROPERTY_REF (real, for a
declared property, or artificial, for a dot-syntax accessor which
is not corresponding to a property). 'lhs' must be a PROPERTY_REF
@@ -2399,9 +2536,14 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
if (!POINTER_TYPE_P (ltyp) || !POINTER_TYPE_P (rtyp))
return false;
+ tree ltyp_attr, rtyp_attr;
do
{
- ltyp = TREE_TYPE (ltyp); /* Remove indirections. */
+ /* Remove indirections, but keep the type attributes from the innermost
+ pointer type, to check for NSObject. */
+ ltyp_attr = TYPE_ATTRIBUTES (ltyp);
+ ltyp = TREE_TYPE (ltyp);
+ rtyp_attr = TYPE_ATTRIBUTES (rtyp);
rtyp = TREE_TYPE (rtyp);
}
while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
@@ -2446,17 +2588,23 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
return true;
}
+ /* We might have void * with NSObject type attr. */
+ bool l_NSObject_p = ltyp_attr && lookup_attribute ("NSObject", ltyp_attr);
+ bool r_NSObject_p = rtyp_attr && lookup_attribute ("NSObject", rtyp_attr);
+
/* Past this point, we are only interested in ObjC class instances,
- or 'id' or 'Class'. */
- if (TREE_CODE (ltyp) != RECORD_TYPE || TREE_CODE (rtyp) != RECORD_TYPE)
+ or 'id' or 'Class' (except if the user applied the NSObject type
+ attribute). */
+ if ((TREE_CODE (ltyp) != RECORD_TYPE && !l_NSObject_p)
+ || (TREE_CODE (rtyp) != RECORD_TYPE && !r_NSObject_p))
return false;
if (!objc_is_object_id (ltyp) && !objc_is_class_id (ltyp)
- && !TYPE_HAS_OBJC_INFO (ltyp))
+ && !TYPE_HAS_OBJC_INFO (ltyp) && !l_NSObject_p)
return false;
if (!objc_is_object_id (rtyp) && !objc_is_class_id (rtyp)
- && !TYPE_HAS_OBJC_INFO (rtyp))
+ && !TYPE_HAS_OBJC_INFO (rtyp) && !r_NSObject_p)
return false;
/* Past this point, we are committed to returning 'true' to the caller
@@ -2490,12 +2638,15 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
rcls = NULL_TREE;
/* If either type is an unqualified 'id', we're done. This is because
- an 'id' can be assigned to or from any type with no warnings. */
+ an 'id' can be assigned to or from any type with no warnings. When
+ the pointer has NSObject attribute, consider that to be equivalent. */
if (argno != -5)
{
if ((!lproto && objc_is_object_id (ltyp))
|| (!rproto && objc_is_object_id (rtyp)))
return true;
+ if (l_NSObject_p || r_NSObject_p)
+ return true;
}
else
{
@@ -2503,7 +2654,7 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
general type of object, hence if you try to specialize an
'NSArray *' (ltyp) property with an 'id' (rtyp) one, we need
to warn. */
- if (!lproto && objc_is_object_id (ltyp))
+ if (!lproto && (objc_is_object_id (ltyp) || l_NSObject_p))
return true;
}
@@ -2954,6 +3105,7 @@ synth_module_prologue (void)
objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
objc_instancetype_name = get_identifier (INSTANCE_TYPEDEF_NAME);
objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
+ objc_selector_name = get_identifier (SEL_TYPEDEF_NAME);
/* Declare the 'id', 'instancetype' and 'Class' typedefs. */
type = lang_hooks.decls.pushdecl (build_decl (input_location,
@@ -6911,6 +7063,12 @@ start_class (enum tree_code code, tree class_name, tree super_name,
CLASS_SUPER_NAME (objc_implementation_context)
= CLASS_SUPER_NAME (implementation_template);
}
+
+ if (!CLASS_SUPER_NAME (objc_implementation_context)
+ && !lookup_attribute ("objc_root_class",
+ TYPE_ATTRIBUTES (implementation_template)))
+ warning (OPT_Wobjc_root_class, "class %qE defined without"
+ " specifying a base class", class_name);
break;
case CLASS_INTERFACE_TYPE:
@@ -6935,12 +7093,16 @@ start_class (enum tree_code code, tree class_name, tree super_name,
tree name = TREE_PURPOSE (attribute);
/* TODO: Document what the objc_exception attribute is/does. */
- /* We handle the 'deprecated' and (undocumented) 'objc_exception'
- attributes. */
+ /* We handle the 'deprecated', 'visibility' and (undocumented)
+ 'objc_exception' attributes. */
if (is_attribute_p ("deprecated", name))
TREE_DEPRECATED (klass) = 1;
else if (is_attribute_p ("objc_exception", name))
CLASS_HAS_EXCEPTION_ATTR (klass) = 1;
+ else if (is_attribute_p ("objc_root_class", name))
+ ;
+ else if (is_attribute_p ("visibility", name))
+ ;
else
/* Warn about and ignore all others for now, but store them. */
warning (OPT_Wattributes, "%qE attribute directive ignored", name);
@@ -8579,11 +8741,19 @@ objc_type_valid_for_messaging (tree type, bool accept_classes)
if (!POINTER_TYPE_P (type))
return false;
+ /* We will check for an NSObject type attribute on the pointer if other
+ tests fail. */
+ tree type_attr = TYPE_ATTRIBUTES (type);
+
/* Remove the pointer indirection; don't remove more than one
otherwise we'd consider "NSObject **" a valid type for messaging,
which it isn't. */
type = TREE_TYPE (type);
+ /* We allow void * to have an NSObject type attr. */
+ if (VOID_TYPE_P (type) && type_attr)
+ return lookup_attribute ("NSObject", type_attr) != NULL_TREE;
+
if (TREE_CODE (type) != RECORD_TYPE)
return false;
@@ -8596,6 +8766,9 @@ objc_type_valid_for_messaging (tree type, bool accept_classes)
if (TYPE_HAS_OBJC_INFO (type))
return true;
+ if (type_attr)
+ return lookup_attribute ("NSObject", type_attr) != NULL_TREE;
+
return false;
}
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 913e152..2fe409db 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -137,6 +137,20 @@ enum objc_property_assign_semantics {
#define PROPERTY_OPTIONAL(DECL) \
DECL_LANG_FLAG_5 (PROPERTY_DECL_CHECK (DECL))
+/* PROPERTY_CLASS can be 0 or 1. */
+#define PROPERTY_CLASS(DECL) \
+ DECL_LANG_FLAG_6 (PROPERTY_DECL_CHECK (DECL))
+
+/* PROPERTY_NULLABILITY attributes added to the decl attributes.
+ effectively, __attribute__((objc_nullability(kind))), */
+enum objc_property_nullability {
+ OBJC_PROPERTY_NULL_UNSPECIFIED = 0,
+ OBJC_PROPERTY_NULLABLE,
+ OBJC_PROPERTY_NONNULL,
+ OBJC_PROPERTY_NULL_RESETTABLE,
+ OBJC_PROPERTY_NULL_UNSET
+};
+
/* PROPERTY_REF. A PROPERTY_REF represents an 'object.property'
expression. It is normally used for property access, but when
the Objective-C 2.0 "dot-syntax" (object.component) is used
@@ -371,6 +385,7 @@ enum objc_tree_index
OCTI_ID_NAME,
OCTI_INSTANCETYPE_NAME,
OCTI_CLASS_NAME,
+ OCTI_SEL_NAME,
OCTI_CNST_STR_ID,
OCTI_CNST_STR_TYPE,
OCTI_CNST_STR_GLOB_ID,
@@ -576,6 +591,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_object_name objc_global_trees[OCTI_ID_NAME]
#define objc_instancetype_name objc_global_trees[OCTI_INSTANCETYPE_NAME]
#define objc_class_name objc_global_trees[OCTI_CLASS_NAME]
+#define objc_selector_name objc_global_trees[OCTI_SEL_NAME]
/* Constant string classes. */
#define constant_string_id objc_global_trees[OCTI_CNST_STR_ID]
@@ -614,6 +630,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define OBJECT_TYPEDEF_NAME "id"
#define INSTANCE_TYPEDEF_NAME "instancetype"
#define CLASS_TYPEDEF_NAME "Class"
+#define SEL_TYPEDEF_NAME "SEL"
#define TAG_OBJECT "objc_object"
#define TAG_CLASS "objc_class"
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index 25c0e01..ac9a862 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -208,6 +208,13 @@ static void gnu_runtime_01_initialize (void)
type = build_qualified_type (type, TYPE_QUAL_CONST);
objc_selector_type = build_pointer_type (type);
+ /* SEL typedef. */
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
+ objc_selector_name,
+ objc_selector_type));
+ TREE_NO_WARNING (type) = 1;
+
/* typedef id (*IMP)(id, SEL, ...); */
ftype = build_varargs_function_type_list (objc_object_type,
objc_object_type,
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 233d89e..7fc449b 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -277,6 +277,13 @@ static void next_runtime_01_initialize (void)
objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
get_identifier (TAG_SELECTOR)));
+ /* SEL typedef. */
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
+ objc_selector_name,
+ objc_selector_type));
+ TREE_NO_WARNING (type) = 1;
+
build_v1_class_template ();
build_super_template ();
build_v1_protocol_template ();
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index d7812ff..f3c285a 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -374,6 +374,13 @@ static void next_runtime_02_initialize (void)
objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
get_identifier (TAG_SELECTOR)));
+ /* SEL typedef. */
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
+ objc_selector_name,
+ objc_selector_type));
+ TREE_NO_WARNING (type) = 1;
+
/* IMP : id (*) (id, _message_ref_t*, ...)
SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
objc_v2_selector_type. */
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 64a0deb..0b257a9 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,17 @@
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (obj-c++.serial): Change from goal to a variable.
+ (.PHONY): Drop obj-c++.serial and obj-c++.prev.
+ (cc1objplus$(exeext)): Depend on $(obj-c++.serial) rather than
+ obj-c++.serial.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (obj-c++.serial): New goal.
+ (.PHONY): Add obj-c++.serial obj-c++.prev.
+ (cc1objplus$(exeext)): Depend on obj-c++.prev. Call LINK_PROGRESS.
+
2020-09-25 Nathan Sidwell <nathan@acm.org>
* objcp-decl.c (objcp_start_struct): Use TAG_how not tag_scope.
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 5bfef24..2e3e37e 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -39,6 +39,7 @@
#
# Define the names for selecting Objective-C++ in LANGUAGES.
obj-c++: cc1objplus$(exeext)
+obj-c++.serial = cc1objplus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: obj-c++
@@ -66,9 +67,12 @@ cc1objplus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
$(srcdir)/../move-if-change cc1objplus-checksum.c.tmp \
cc1objplus-checksum.c
-cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
+cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) \
+ $(LIBDEPS) $(obj-c++.prev)
+ @$(call LINK_PROGRESS,$(INDEX.obj-c++),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.obj-c++),end)
# Objective C++ language specific files.
diff --git a/gcc/obstack-utils.h b/gcc/obstack-utils.h
new file mode 100644
index 0000000..ee389f8
--- /dev/null
+++ b/gcc/obstack-utils.h
@@ -0,0 +1,86 @@
+// Obstack-related utilities.
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_OBSTACK_UTILS_H
+#define GCC_OBSTACK_UTILS_H
+
+// This RAII class automatically frees memory allocated on an obstack,
+// unless told not to via keep (). It automatically converts to an
+// obstack, so it can (optionally) be used in place of the obstack
+// to make the scoping clearer. For example:
+//
+// obstack_watermark watermark (ob);
+// auto *ptr1 = XOBNEW (watermark, struct1);
+// if (...)
+// // Frees ptr1.
+// return false;
+//
+// auto *ptr2 = XOBNEW (watermark, struct2);
+// if (...)
+// // Frees ptr1 and ptr2.
+// return false;
+//
+// // Retains ptr1 and ptr2.
+// watermark.keep ();
+//
+// auto *ptr3 = XOBNEW (watermark, struct3);
+// if (...)
+// // Frees ptr3.
+// return false;
+//
+// // Retains ptr3 (in addition to ptr1 and ptr2 above).
+// watermark.keep ();
+// return true;
+//
+// The move constructor makes it possible to transfer ownership to a caller:
+//
+// obstack_watermark
+// foo ()
+// {
+// obstack_watermark watermark (ob);
+// ...
+// return watermark;
+// }
+//
+// void
+// bar ()
+// {
+// // Inherit ownership of everything that foo allocated.
+// obstack_watermark watermark = foo ();
+// ...
+// }
+class obstack_watermark
+{
+public:
+ obstack_watermark (obstack *ob) : m_obstack (ob) { keep (); }
+ constexpr obstack_watermark (obstack_watermark &&) = default;
+ ~obstack_watermark () { obstack_free (m_obstack, m_start); }
+
+ operator obstack *() const { return m_obstack; }
+ void keep () { m_start = XOBNEWVAR (m_obstack, char, 0); }
+
+private:
+ DISABLE_COPY_AND_ASSIGN (obstack_watermark);
+
+protected:
+ obstack *m_obstack;
+ char *m_start;
+};
+
+#endif
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index f461d60..f9b78ed 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -47,6 +47,8 @@ DEF_GOACC_BUILTIN (BUILT_IN_GOACC_UPDATE, "GOACC_update",
DEF_GOACC_BUILTIN (BUILT_IN_GOACC_WAIT, "GOACC_wait",
BT_FN_VOID_INT_INT_VAR,
ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DECLARE, "GOACC_declare",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
DEF_GOACC_BUILTIN_COMPILER (BUILT_IN_ACC_ON_DEVICE, "acc_on_device",
BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -444,5 +446,8 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK_REDUCTION_REMAP,
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER,
"GOMP_workshare_task_reduction_unregister",
BT_FN_VOID_BOOL, ATTR_NOTHROW_LEAF_LIST)
-DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DECLARE, "GOACC_declare",
- BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC,
+ "GOMP_alloc", BT_FN_PTR_SIZE_SIZE_PTRMODE,
+ ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE,
+ "GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 6583c88..4baec32 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -1510,8 +1510,8 @@ struct oacc_collapse
static tree
expand_oacc_collapse_init (const struct omp_for_data *fd,
gimple_stmt_iterator *gsi,
- oacc_collapse *counts, tree bound_type,
- location_t loc)
+ oacc_collapse *counts, tree diff_type,
+ tree bound_type, location_t loc)
{
tree tiling = fd->tiling;
tree total = build_int_cst (bound_type, 1);
@@ -1528,17 +1528,12 @@ expand_oacc_collapse_init (const struct omp_for_data *fd,
const omp_for_data_loop *loop = &fd->loops[ix];
tree iter_type = TREE_TYPE (loop->v);
- tree diff_type = iter_type;
tree plus_type = iter_type;
gcc_assert (loop->cond_code == fd->loop.cond_code);
if (POINTER_TYPE_P (iter_type))
plus_type = sizetype;
- if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
- diff_type = signed_type_for (diff_type);
- if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (integer_type_node))
- diff_type = integer_type_node;
if (tiling)
{
@@ -1626,7 +1621,8 @@ expand_oacc_collapse_init (const struct omp_for_data *fd,
static void
expand_oacc_collapse_vars (const struct omp_for_data *fd, bool inner,
gimple_stmt_iterator *gsi,
- const oacc_collapse *counts, tree ivar)
+ const oacc_collapse *counts, tree ivar,
+ tree diff_type)
{
tree ivar_type = TREE_TYPE (ivar);
@@ -1638,7 +1634,6 @@ expand_oacc_collapse_vars (const struct omp_for_data *fd, bool inner,
const oacc_collapse *collapse = &counts[ix];
tree v = inner ? loop->v : collapse->outer;
tree iter_type = TREE_TYPE (v);
- tree diff_type = TREE_TYPE (collapse->step);
tree plus_type = iter_type;
enum tree_code plus_code = PLUS_EXPR;
tree expr;
@@ -1660,7 +1655,7 @@ expand_oacc_collapse_vars (const struct omp_for_data *fd, bool inner,
}
expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
- collapse->step);
+ fold_convert (diff_type, collapse->step));
expr = fold_build2 (plus_code, iter_type,
inner ? collapse->outer : collapse->base,
fold_convert (plus_type, expr));
@@ -2514,7 +2509,8 @@ expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
&& (TREE_CODE (fd->loop.n2) == INTEGER_CST
|| fd->first_inner_iterations)
&& (optab_handler (sqrt_optab, TYPE_MODE (double_type_node))
- != CODE_FOR_nothing))
+ != CODE_FOR_nothing)
+ && !integer_zerop (fd->loop.n2))
{
tree outer_n1 = fd->adjn1 ? fd->adjn1 : fd->loops[i - 1].n1;
tree itype = TREE_TYPE (fd->loops[i].v);
@@ -4255,8 +4251,7 @@ expand_omp_for_generic (struct omp_region *region,
: POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
- assign_stmt = gimple_build_assign (dest, t);
- gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ expand_omp_build_assign (&gsi, dest, t, true);
}
if (fd->collapse > 1)
expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
@@ -4309,13 +4304,18 @@ expand_omp_for_generic (struct omp_region *region,
gsi = gsi_last_bb (l0_bb);
expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
istart0, true);
- gsi = gsi_last_bb (cont_bb);
- t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
- build_int_cst (fd->iter_type, 1));
- expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
- tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
- size_zero_node, NULL_TREE, NULL_TREE);
- expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
+ if (cont_bb)
+ {
+ gsi = gsi_last_bb (cont_bb);
+ t = fold_build2 (PLUS_EXPR, fd->iter_type,
+ counts[fd->collapse - 1],
+ build_int_cst (fd->iter_type, 1));
+ expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
+ tree aref = build4 (ARRAY_REF, fd->iter_type,
+ counts[fd->ordered], size_zero_node,
+ NULL_TREE, NULL_TREE);
+ expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
+ }
t = counts[fd->collapse - 1];
}
else if (fd->collapse > 1)
@@ -5250,8 +5250,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
: POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
- assign_stmt = gimple_build_assign (dest, t);
- gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ expand_omp_build_assign (&gsi, dest, t, true);
}
if (fd->collapse > 1)
{
@@ -5974,8 +5973,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
: POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
- assign_stmt = gimple_build_assign (dest, t);
- gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ expand_omp_build_assign (&gsi, dest, t, true);
}
if (fd->collapse > 1)
expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
@@ -7415,6 +7413,21 @@ expand_omp_taskloop_for_inner (struct omp_region *region,
static void
expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
{
+ bool is_oacc_kernels_parallelized
+ = (lookup_attribute ("oacc kernels parallelized",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ {
+ bool is_oacc_kernels
+ = (lookup_attribute ("oacc kernels",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ if (is_oacc_kernels_parallelized)
+ gcc_checking_assert (is_oacc_kernels);
+ }
+ gcc_assert (gimple_in_ssa_p (cfun) == is_oacc_kernels_parallelized);
+ /* In the following, some of the 'gimple_in_ssa_p (cfun)' conditionals are
+ for SSA specifics, and some are for 'parloops' OpenACC
+ 'kernels'-parallelized specifics. */
+
tree v = fd->loop.v;
enum tree_code cond_code = fd->loop.cond_code;
enum tree_code plus_code = PLUS_EXPR;
@@ -7436,6 +7449,12 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
plus_code = POINTER_PLUS_EXPR;
plus_type = sizetype;
}
+ for (int ix = fd->collapse; ix--;)
+ {
+ tree diff_type2 = TREE_TYPE (fd->loops[ix].step);
+ if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (diff_type2))
+ diff_type = diff_type2;
+ }
if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
diff_type = signed_type_for (diff_type);
if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (integer_type_node))
@@ -7519,7 +7538,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
{
gcc_assert (!gimple_in_ssa_p (cfun) && up);
counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
- tree total = expand_oacc_collapse_init (fd, &gsi, counts,
+ tree total = expand_oacc_collapse_init (fd, &gsi, counts, diff_type,
TREE_TYPE (fd->loop.n2), loc);
if (SSA_VAR_P (fd->loop.n2))
@@ -7681,7 +7700,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
if (fd->collapse > 1 || fd->tiling)
- expand_oacc_collapse_vars (fd, false, &gsi, counts, v);
+ expand_oacc_collapse_vars (fd, false, &gsi, counts, v, diff_type);
if (fd->tiling)
{
@@ -7751,7 +7770,8 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
/* Initialize the user's loop vars. */
gsi = gsi_start_bb (elem_body_bb);
- expand_oacc_collapse_vars (fd, true, &gsi, counts, e_offset);
+ expand_oacc_collapse_vars (fd, true, &gsi, counts, e_offset,
+ diff_type);
}
}
@@ -9240,7 +9260,7 @@ expand_omp_target (struct omp_region *region)
gomp_target *entry_stmt;
gimple *stmt;
edge e;
- bool offloaded, data_region;
+ bool offloaded;
int target_kind;
entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
@@ -9260,12 +9280,12 @@ expand_omp_target (struct omp_region *region)
case GF_OMP_TARGET_KIND_OACC_UPDATE:
case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
case GF_OMP_TARGET_KIND_OACC_DECLARE:
- data_region = false;
- break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
case GF_OMP_TARGET_KIND_DATA:
case GF_OMP_TARGET_KIND_OACC_DATA:
case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
- data_region = true;
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
break;
default:
gcc_unreachable ();
@@ -9287,27 +9307,43 @@ expand_omp_target (struct omp_region *region)
entry_bb = region->entry;
exit_bb = region->exit;
+ if (target_kind == GF_OMP_TARGET_KIND_OACC_KERNELS)
+ mark_loops_in_oacc_kernels_region (region->entry, region->exit);
+
+ /* Going on, all OpenACC compute constructs are mapped to
+ 'BUILT_IN_GOACC_PARALLEL', and get their compute regions outlined.
+ To distinguish between them, we attach attributes. */
switch (target_kind)
{
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL:
+ DECL_ATTRIBUTES (child_fn)
+ = tree_cons (get_identifier ("oacc parallel"),
+ NULL_TREE, DECL_ATTRIBUTES (child_fn));
+ break;
case GF_OMP_TARGET_KIND_OACC_KERNELS:
- mark_loops_in_oacc_kernels_region (region->entry, region->exit);
-
- /* Further down, all OpenACC compute constructs will be mapped to
- BUILT_IN_GOACC_PARALLEL, and to distinguish between them, there
- is an "oacc kernels" attribute set for OpenACC kernels. */
DECL_ATTRIBUTES (child_fn)
= tree_cons (get_identifier ("oacc kernels"),
NULL_TREE, DECL_ATTRIBUTES (child_fn));
break;
case GF_OMP_TARGET_KIND_OACC_SERIAL:
- /* Further down, all OpenACC compute constructs will be mapped to
- BUILT_IN_GOACC_PARALLEL, and to distinguish between them, there
- is an "oacc serial" attribute set for OpenACC serial. */
DECL_ATTRIBUTES (child_fn)
= tree_cons (get_identifier ("oacc serial"),
NULL_TREE, DECL_ATTRIBUTES (child_fn));
break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ DECL_ATTRIBUTES (child_fn)
+ = tree_cons (get_identifier ("oacc parallel_kernels_parallelized"),
+ NULL_TREE, DECL_ATTRIBUTES (child_fn));
+ break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
+ DECL_ATTRIBUTES (child_fn)
+ = tree_cons (get_identifier ("oacc parallel_kernels_gang_single"),
+ NULL_TREE, DECL_ATTRIBUTES (child_fn));
+ break;
default:
+ /* Make sure we don't miss any. */
+ gcc_checking_assert (!(is_gimple_omp_oacc (entry_stmt)
+ && is_gimple_omp_offloaded (entry_stmt)));
break;
}
@@ -9514,10 +9550,13 @@ expand_omp_target (struct omp_region *region)
case GF_OMP_TARGET_KIND_OACC_PARALLEL:
case GF_OMP_TARGET_KIND_OACC_KERNELS:
case GF_OMP_TARGET_KIND_OACC_SERIAL:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
start_ix = BUILT_IN_GOACC_PARALLEL;
break;
case GF_OMP_TARGET_KIND_OACC_DATA:
case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
start_ix = BUILT_IN_GOACC_DATA_START;
break;
case GF_OMP_TARGET_KIND_OACC_UPDATE:
@@ -9813,13 +9852,6 @@ expand_omp_target (struct omp_region *region)
gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
gsi_remove (&gsi, true);
}
- if (data_region && region->exit)
- {
- gsi = gsi_last_nondebug_bb (region->exit);
- g = gsi_stmt (gsi);
- gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
- gsi_remove (&gsi, true);
- }
}
/* Expand the parallel region tree rooted at REGION. Expansion
@@ -9984,16 +10016,19 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
switch (gimple_omp_target_kind (stmt))
{
case GF_OMP_TARGET_KIND_REGION:
- case GF_OMP_TARGET_KIND_DATA:
case GF_OMP_TARGET_KIND_OACC_PARALLEL:
case GF_OMP_TARGET_KIND_OACC_KERNELS:
case GF_OMP_TARGET_KIND_OACC_SERIAL:
- case GF_OMP_TARGET_KIND_OACC_DATA:
- case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
break;
case GF_OMP_TARGET_KIND_UPDATE:
case GF_OMP_TARGET_KIND_ENTER_DATA:
case GF_OMP_TARGET_KIND_EXIT_DATA:
+ case GF_OMP_TARGET_KIND_DATA:
+ case GF_OMP_TARGET_KIND_OACC_DATA:
+ case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
case GF_OMP_TARGET_KIND_OACC_UPDATE:
case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
case GF_OMP_TARGET_KIND_OACC_DECLARE:
@@ -10238,16 +10273,19 @@ omp_make_gimple_edges (basic_block bb, struct omp_region **region,
switch (gimple_omp_target_kind (last))
{
case GF_OMP_TARGET_KIND_REGION:
- case GF_OMP_TARGET_KIND_DATA:
case GF_OMP_TARGET_KIND_OACC_PARALLEL:
case GF_OMP_TARGET_KIND_OACC_KERNELS:
case GF_OMP_TARGET_KIND_OACC_SERIAL:
- case GF_OMP_TARGET_KIND_OACC_DATA:
- case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
break;
case GF_OMP_TARGET_KIND_UPDATE:
case GF_OMP_TARGET_KIND_ENTER_DATA:
case GF_OMP_TARGET_KIND_EXIT_DATA:
+ case GF_OMP_TARGET_KIND_DATA:
+ case GF_OMP_TARGET_KIND_OACC_DATA:
+ case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
case GF_OMP_TARGET_KIND_OACC_UPDATE:
case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
case GF_OMP_TARGET_KIND_OACC_DECLARE:
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index b70e3e3..b66dfb5 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "omp-device-properties.h"
#include "tree-iterator.h"
+#include "data-streamer.h"
+#include "streamer-hooks.h"
enum omp_requires omp_requires_mask;
@@ -2337,6 +2339,125 @@ omp_resolve_declare_variant (tree base)
? TREE_PURPOSE (TREE_VALUE (variant1)) : base);
}
+void
+omp_lto_output_declare_variant_alt (lto_simple_output_block *ob,
+ cgraph_node *node,
+ lto_symtab_encoder_t encoder)
+{
+ gcc_assert (node->declare_variant_alt);
+
+ omp_declare_variant_base_entry entry;
+ entry.base = NULL;
+ entry.node = node;
+ entry.variants = NULL;
+ omp_declare_variant_base_entry *entryp
+ = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (node->decl));
+ gcc_assert (entryp);
+
+ int nbase = lto_symtab_encoder_lookup (encoder, entryp->base);
+ gcc_assert (nbase != LCC_NOT_FOUND);
+ streamer_write_hwi_stream (ob->main_stream, nbase);
+
+ streamer_write_hwi_stream (ob->main_stream, entryp->variants->length ());
+
+ unsigned int i;
+ omp_declare_variant_entry *varentry;
+ FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry)
+ {
+ int nvar = lto_symtab_encoder_lookup (encoder, varentry->variant);
+ gcc_assert (nvar != LCC_NOT_FOUND);
+ streamer_write_hwi_stream (ob->main_stream, nvar);
+
+ for (widest_int *w = &varentry->score; ;
+ w = &varentry->score_in_declare_simd_clone)
+ {
+ unsigned len = w->get_len ();
+ streamer_write_hwi_stream (ob->main_stream, len);
+ const HOST_WIDE_INT *val = w->get_val ();
+ for (unsigned j = 0; j < len; j++)
+ streamer_write_hwi_stream (ob->main_stream, val[j]);
+ if (w == &varentry->score_in_declare_simd_clone)
+ break;
+ }
+
+ HOST_WIDE_INT cnt = -1;
+ HOST_WIDE_INT i = varentry->matches ? 1 : 0;
+ for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
+ attr; attr = TREE_CHAIN (attr), i += 2)
+ {
+ attr = lookup_attribute ("omp declare variant base", attr);
+ if (attr == NULL_TREE)
+ break;
+
+ if (varentry->ctx == TREE_VALUE (TREE_VALUE (attr)))
+ {
+ cnt = i;
+ break;
+ }
+ }
+
+ gcc_assert (cnt != -1);
+ streamer_write_hwi_stream (ob->main_stream, cnt);
+ }
+}
+
+void
+omp_lto_input_declare_variant_alt (lto_input_block *ib, cgraph_node *node,
+ vec<symtab_node *> nodes)
+{
+ gcc_assert (node->declare_variant_alt);
+ omp_declare_variant_base_entry *entryp
+ = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
+ entryp->base = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
+ entryp->node = node;
+ unsigned int len = streamer_read_hwi (ib);
+ vec_alloc (entryp->variants, len);
+
+ for (unsigned int i = 0; i < len; i++)
+ {
+ omp_declare_variant_entry varentry;
+ varentry.variant
+ = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
+ for (widest_int *w = &varentry.score; ;
+ w = &varentry.score_in_declare_simd_clone)
+ {
+ unsigned len2 = streamer_read_hwi (ib);
+ HOST_WIDE_INT arr[WIDE_INT_MAX_ELTS];
+ gcc_assert (len2 <= WIDE_INT_MAX_ELTS);
+ for (unsigned int j = 0; j < len2; j++)
+ arr[j] = streamer_read_hwi (ib);
+ *w = widest_int::from_array (arr, len2, true);
+ if (w == &varentry.score_in_declare_simd_clone)
+ break;
+ }
+
+ HOST_WIDE_INT cnt = streamer_read_hwi (ib);
+ HOST_WIDE_INT j = 0;
+ varentry.ctx = NULL_TREE;
+ varentry.matches = (cnt & 1) ? true : false;
+ cnt &= ~HOST_WIDE_INT_1;
+ for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
+ attr; attr = TREE_CHAIN (attr), j += 2)
+ {
+ attr = lookup_attribute ("omp declare variant base", attr);
+ if (attr == NULL_TREE)
+ break;
+
+ if (cnt == j)
+ {
+ varentry.ctx = TREE_VALUE (TREE_VALUE (attr));
+ break;
+ }
+ }
+ gcc_assert (varentry.ctx != NULL_TREE);
+ entryp->variants->quick_push (varentry);
+ }
+ if (omp_declare_variant_alt == NULL)
+ omp_declare_variant_alt
+ = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
+ *omp_declare_variant_alt->find_slot_with_hash (entryp, DECL_UID (node->decl),
+ INSERT) = entryp;
+}
/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
macro on gomp-constants.h. We do not check for overflow. */
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 6d0aa8d..91a5e3d 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -126,6 +126,10 @@ struct omp_context
corresponding tracking loop iteration variables. */
hash_map<tree, tree> *lastprivate_conditional_map;
+ /* And a hash map from the allocate variables to their corresponding
+ allocators. */
+ hash_map<tree, tree> *allocate_map;
+
/* A tree_list of the reduction clauses in this context. This is
only used for checking the consistency of OpenACC reduction
clauses in scan_omp_for and is not guaranteed to contain a valid
@@ -189,8 +193,8 @@ static tree scan_omp_1_op (tree *, int *, void *);
*handled_ops_p = false; \
break;
-/* Return true if CTX corresponds to an OpenACC 'parallel' or 'serial'
- region. */
+/* Return whether CTX represents an OpenACC 'parallel' or 'serial' construct.
+ (This doesn't include OpenACC 'kernels' decomposed parts.) */
static bool
is_oacc_parallel_or_serial (omp_context *ctx)
@@ -203,7 +207,8 @@ is_oacc_parallel_or_serial (omp_context *ctx)
== GF_OMP_TARGET_KIND_OACC_SERIAL)));
}
-/* Return true if CTX corresponds to an oacc kernels region. */
+/* Return whether CTX represents an OpenACC 'kernels' construct.
+ (This doesn't include OpenACC 'kernels' decomposed parts.) */
static bool
is_oacc_kernels (omp_context *ctx)
@@ -214,6 +219,36 @@ is_oacc_kernels (omp_context *ctx)
== GF_OMP_TARGET_KIND_OACC_KERNELS));
}
+/* Return whether CTX represents an OpenACC 'kernels' decomposed part. */
+
+static bool
+is_oacc_kernels_decomposed_part (omp_context *ctx)
+{
+ enum gimple_code outer_type = gimple_code (ctx->stmt);
+ return ((outer_type == GIMPLE_OMP_TARGET)
+ && ((gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED)
+ || (gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE)
+ || (gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_OACC_DATA_KERNELS)));
+}
+
+/* Return true if STMT corresponds to an OpenMP target region. */
+static bool
+is_omp_target (gimple *stmt)
+{
+ if (gimple_code (stmt) == GIMPLE_OMP_TARGET)
+ {
+ int kind = gimple_omp_target_kind (stmt);
+ return (kind == GF_OMP_TARGET_KIND_REGION
+ || kind == GF_OMP_TARGET_KIND_DATA
+ || kind == GF_OMP_TARGET_KIND_ENTER_DATA
+ || kind == GF_OMP_TARGET_KIND_EXIT_DATA);
+ }
+ return false;
+}
+
/* If DECL is the artificial dummy VAR_DECL created for non-static
data member privatization, return the underlying "this" parameter,
otherwise return NULL. */
@@ -768,7 +803,7 @@ install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
}
else if (by_ref)
type = build_pointer_type (type);
- else if ((mask & 3) == 1 && omp_is_reference (var))
+ else if ((mask & (32 | 3)) == 1 && omp_is_reference (var))
type = TREE_TYPE (type);
field = build_decl (DECL_SOURCE_LOCATION (var),
@@ -1028,6 +1063,7 @@ delete_omp_context (splay_tree_value value)
}
delete ctx->lastprivate_conditional_map;
+ delete ctx->allocate_map;
XDELETE (ctx);
}
@@ -1100,6 +1136,20 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
bool scan_array_reductions = false;
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
+ /* omp_default_mem_alloc is 1 */
+ || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))))
+ {
+ if (ctx->allocate_map == NULL)
+ ctx->allocate_map = new hash_map<tree, tree>;
+ ctx->allocate_map->put (OMP_CLAUSE_DECL (c),
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+ ? OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
+ : integer_zero_node);
+ }
+
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
{
bool by_ref;
@@ -1115,6 +1165,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE_SHARED:
decl = OMP_CLAUSE_DECL (c);
+ if (ctx->allocate_map && ctx->allocate_map->get (decl))
+ ctx->allocate_map->remove (decl);
/* Ignore shared directives in teams construct inside of
target construct. */
if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
@@ -1156,13 +1208,32 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
goto do_private;
case OMP_CLAUSE_REDUCTION:
- if (is_oacc_parallel_or_serial (ctx) || is_oacc_kernels (ctx))
- ctx->local_reduction_clauses
- = tree_cons (NULL, c, ctx->local_reduction_clauses);
+ /* Collect 'reduction' clauses on OpenACC compute construct. */
+ if (is_gimple_omp_oacc (ctx->stmt)
+ && is_gimple_omp_offloaded (ctx->stmt))
+ {
+ /* No 'reduction' clauses on OpenACC 'kernels'. */
+ gcc_checking_assert (!is_oacc_kernels (ctx));
+ /* Likewise, on OpenACC 'kernels' decomposed parts. */
+ gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
+
+ ctx->local_reduction_clauses
+ = tree_cons (NULL, c, ctx->local_reduction_clauses);
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
decl = OMP_CLAUSE_DECL (c);
+ if (ctx->allocate_map
+ && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && (OMP_CLAUSE_REDUCTION_INSCAN (c)
+ || OMP_CLAUSE_REDUCTION_TASK (c)))
+ || is_task_ctx (ctx)))
+ {
+ /* For now. */
+ if (ctx->allocate_map->get (decl))
+ ctx->allocate_map->remove (decl);
+ }
if (TREE_CODE (decl) == MEM_REF)
{
tree t = TREE_OPERAND (decl, 0);
@@ -1246,7 +1317,16 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (is_variable_sized (decl))
{
if (is_task_ctx (ctx))
- install_var_field (decl, false, 1, ctx);
+ {
+ if (ctx->allocate_map
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+ {
+ /* For now. */
+ if (ctx->allocate_map->get (decl))
+ ctx->allocate_map->remove (decl);
+ }
+ install_var_field (decl, false, 1, ctx);
+ }
break;
}
else if (is_taskreg_ctx (ctx))
@@ -1258,7 +1338,11 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (is_task_ctx (ctx)
&& (global || by_ref || omp_is_reference (decl)))
{
- install_var_field (decl, false, 1, ctx);
+ if (ctx->allocate_map
+ && ctx->allocate_map->get (decl))
+ install_var_field (decl, by_ref, 32 | 1, ctx);
+ else
+ install_var_field (decl, false, 1, ctx);
if (!global)
install_var_field (decl, by_ref, 2, ctx);
}
@@ -1346,7 +1430,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
&& DECL_P (decl)
&& ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
&& (OMP_CLAUSE_MAP_KIND (c)
- != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
+ != GOMP_MAP_FIRSTPRIVATE_REFERENCE)
+ && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
+ && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH)
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO
&& OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM
@@ -1368,6 +1454,40 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
break;
}
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && DECL_P (decl)
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+ && is_omp_target (ctx->stmt))
+ {
+ /* If this is an offloaded region, an attach operation should
+ only exist when the pointer variable is mapped in a prior
+ clause. */
+ if (is_gimple_omp_offloaded (ctx->stmt))
+ gcc_assert
+ (maybe_lookup_decl (decl, ctx)
+ || (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
+ && lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (decl))));
+
+ /* By itself, attach/detach is generated as part of pointer
+ variable mapping and should not create new variables in the
+ offloaded region, however sender refs for it must be created
+ for its address to be passed to the runtime. */
+ tree field
+ = build_decl (OMP_CLAUSE_LOCATION (c),
+ FIELD_DECL, NULL_TREE, ptr_type_node);
+ SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
+ insert_field_into_struct (ctx->record_type, field);
+ /* To not clash with a map of the pointer variable itself,
+ attach/detach maps have their field looked up by the *clause*
+ tree expression, not the decl. */
+ gcc_assert (!splay_tree_lookup (ctx->field_map,
+ (splay_tree_key) c));
+ splay_tree_insert (ctx->field_map, (splay_tree_key) c,
+ (splay_tree_value) field);
+ break;
+ }
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
|| (OMP_CLAUSE_MAP_KIND (c)
== GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
@@ -1486,6 +1606,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
case OMP_CLAUSE_TASK_REDUCTION:
+ case OMP_CLAUSE_ALLOCATE:
break;
case OMP_CLAUSE_ALIGNED:
@@ -1606,6 +1727,11 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
&& is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
&& varpool_node::get_create (decl)->offloadable)
break;
+ if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+ && is_omp_target (ctx->stmt)
+ && !is_gimple_omp_offloaded (ctx->stmt))
+ break;
if (DECL_P (decl))
{
if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
@@ -1653,6 +1779,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE_SIMDLEN:
case OMP_CLAUSE_ALIGNED:
case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_ALLOCATE:
case OMP_CLAUSE__LOOPTEMP_:
case OMP_CLAUSE__REDUCTEMP_:
case OMP_CLAUSE_TO:
@@ -2319,7 +2446,9 @@ enclosing_target_ctx (omp_context *ctx)
return ctx;
}
-/* Return true if ctx is part of an oacc kernels region. */
+/* Return whether CTX's parent compute construct is an OpenACC 'kernels'
+ construct.
+ (This doesn't include OpenACC 'kernels' decomposed parts.) */
static bool
ctx_in_oacc_kernels_region (omp_context *ctx)
@@ -2335,7 +2464,8 @@ ctx_in_oacc_kernels_region (omp_context *ctx)
return false;
}
-/* Check the parallelism clauses inside a kernels regions.
+/* Check the parallelism clauses inside a OpenACC 'kernels' region.
+ (This doesn't include OpenACC 'kernels' decomposed parts.)
Until kernels handling moves to use the same loop indirection
scheme as parallel, we need to do this checking early. */
@@ -2413,53 +2543,50 @@ scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
{
omp_context *tgt = enclosing_target_ctx (outer_ctx);
- if (!tgt || is_oacc_parallel_or_serial (tgt))
+ if (!(tgt && is_oacc_kernels (tgt)))
for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
{
- char const *check = NULL;
-
+ tree c_op0;
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_GANG:
- check = "gang";
+ c_op0 = OMP_CLAUSE_GANG_EXPR (c);
break;
case OMP_CLAUSE_WORKER:
- check = "worker";
+ c_op0 = OMP_CLAUSE_WORKER_EXPR (c);
break;
case OMP_CLAUSE_VECTOR:
- check = "vector";
+ c_op0 = OMP_CLAUSE_VECTOR_EXPR (c);
break;
default:
- break;
+ continue;
}
- if (check && OMP_CLAUSE_OPERAND (c, 0))
- error_at (gimple_location (stmt),
- "argument not permitted on %qs clause in"
- " OpenACC %<parallel%> or %<serial%>", check);
+ if (c_op0)
+ {
+ /* By construction, this is impossible for OpenACC 'kernels'
+ decomposed parts. */
+ gcc_assert (!(tgt && is_oacc_kernels_decomposed_part (tgt)));
+
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "argument not permitted on %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ if (tgt)
+ inform (gimple_location (tgt->stmt),
+ "enclosing parent compute construct");
+ else if (oacc_get_fn_attrib (current_function_decl))
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "enclosing routine");
+ else
+ gcc_unreachable ();
+ }
}
if (tgt && is_oacc_kernels (tgt))
- {
- /* Strip out reductions, as they are not handled yet. */
- tree *prev_ptr = &clauses;
-
- while (tree probe = *prev_ptr)
- {
- tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
-
- if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
- *prev_ptr = *next_ptr;
- else
- prev_ptr = next_ptr;
- }
-
- gimple_omp_for_set_clauses (stmt, clauses);
- check_oacc_kernel_gwv (stmt, ctx);
- }
+ check_oacc_kernel_gwv (stmt, ctx);
/* Collect all variables named in reductions on this loop. Ensure
that, if this loop has a reduction on some variable v, and there is
@@ -2542,6 +2669,24 @@ scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
ctx->outer_reduction_clauses
= chainon (unshare_expr (ctx->local_reduction_clauses),
ctx->outer_reduction_clauses);
+
+ if (tgt && is_oacc_kernels (tgt))
+ {
+ /* Strip out reductions, as they are not handled yet. */
+ tree *prev_ptr = &clauses;
+
+ while (tree probe = *prev_ptr)
+ {
+ tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
+
+ if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
+ *prev_ptr = *next_ptr;
+ else
+ prev_ptr = next_ptr;
+ }
+
+ gimple_omp_for_set_clauses (stmt, clauses);
+ }
}
scan_sharing_clauses (clauses, ctx);
@@ -2868,7 +3013,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
{
error_at (gimple_location (stmt),
"%<ordered simd threads%> must be closely "
- "nested inside of %<for simd%> region");
+ "nested inside of %<%s simd%> region",
+ lang_GNU_Fortran () ? "do" : "for");
return false;
}
return true;
@@ -2962,6 +3108,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
case GF_OMP_TARGET_KIND_OACC_PARALLEL:
case GF_OMP_TARGET_KIND_OACC_KERNELS:
case GF_OMP_TARGET_KIND_OACC_SERIAL:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
ok = true;
break;
@@ -3418,6 +3566,11 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
case GF_OMP_TARGET_KIND_OACC_DECLARE: stmt_name = "declare"; break;
case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
+ /* OpenACC 'kernels' decomposed parts. */
+ stmt_name = "kernels"; break;
default: gcc_unreachable ();
}
switch (gimple_omp_target_kind (ctx->stmt))
@@ -3433,6 +3586,11 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ctx_stmt_name = "host_data"; break;
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
+ /* OpenACC 'kernels' decomposed parts. */
+ ctx_stmt_name = "kernels"; break;
default: gcc_unreachable ();
}
@@ -4288,6 +4446,79 @@ task_reduction_read (gimple_seq *ilist, tree tskred_temp, tree type,
return v;
}
+/* Lower early initialization of privatized variable NEW_VAR
+ if it needs an allocator (has allocate clause). */
+
+static bool
+lower_private_allocate (tree var, tree new_var, tree &allocator,
+ tree &allocate_ptr, gimple_seq *ilist,
+ omp_context *ctx, bool is_ref, tree size)
+{
+ if (allocator)
+ return false;
+ gcc_assert (allocate_ptr == NULL_TREE);
+ if (ctx->allocate_map
+ && (DECL_P (new_var) || (TYPE_P (new_var) && size)))
+ if (tree *allocatorp = ctx->allocate_map->get (var))
+ allocator = *allocatorp;
+ if (allocator == NULL_TREE)
+ return false;
+ if (!is_ref && omp_is_reference (var))
+ {
+ allocator = NULL_TREE;
+ return false;
+ }
+
+ if (TREE_CODE (allocator) != INTEGER_CST)
+ allocator = build_outer_var_ref (allocator, ctx);
+ allocator = fold_convert (pointer_sized_int_node, allocator);
+ if (TREE_CODE (allocator) != INTEGER_CST)
+ {
+ tree var = create_tmp_var (TREE_TYPE (allocator));
+ gimplify_assign (var, allocator, ilist);
+ allocator = var;
+ }
+
+ tree ptr_type, align, sz = size;
+ if (TYPE_P (new_var))
+ {
+ ptr_type = build_pointer_type (new_var);
+ align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (new_var));
+ }
+ else if (is_ref)
+ {
+ ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
+ align = build_int_cst (size_type_node,
+ TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
+ }
+ else
+ {
+ ptr_type = build_pointer_type (TREE_TYPE (new_var));
+ align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (new_var));
+ if (sz == NULL_TREE)
+ sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
+ }
+ if (TREE_CODE (sz) != INTEGER_CST)
+ {
+ tree szvar = create_tmp_var (size_type_node);
+ gimplify_assign (szvar, sz, ilist);
+ sz = szvar;
+ }
+ allocate_ptr = create_tmp_var (ptr_type);
+ tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
+ gimple *g = gimple_build_call (a, 3, align, sz, allocator);
+ gimple_call_set_lhs (g, allocate_ptr);
+ gimple_seq_add_stmt (ilist, g);
+ if (!is_ref)
+ {
+ tree x = build_simple_mem_ref (allocate_ptr);
+ TREE_THIS_NOTRAP (x) = 1;
+ SET_DECL_VALUE_EXPR (new_var, x);
+ DECL_HAS_VALUE_EXPR_P (new_var) = 1;
+ }
+ return true;
+}
+
/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
from the receiver (aka child) side and initializers for REFERENCE_TYPE
private variables. Initialization statements go in ILIST, while calls
@@ -4453,6 +4684,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bool task_reduction_p = false;
bool task_reduction_needs_orig_p = false;
tree cond = NULL_TREE;
+ tree allocator, allocate_ptr;
switch (c_kind)
{
@@ -4589,6 +4821,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (task_reduction_p != (pass >= 2))
continue;
+ allocator = NULL_TREE;
+ allocate_ptr = NULL_TREE;
new_var = var = OMP_CLAUSE_DECL (c);
if ((c_kind == OMP_CLAUSE_REDUCTION
|| c_kind == OMP_CLAUSE_IN_REDUCTION)
@@ -4697,7 +4931,23 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
tree type = TREE_TYPE (d);
gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
+ tree sz = v;
const char *name = get_name (orig_var);
+ if (pass != 3 && !TREE_CONSTANT (v))
+ {
+ tree t = maybe_lookup_decl (v, ctx);
+ if (t)
+ v = t;
+ else
+ v = maybe_lookup_decl_in_outer_ctx (v, ctx);
+ gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
+ t = fold_build2_loc (clause_loc, PLUS_EXPR,
+ TREE_TYPE (v), v,
+ build_int_cst (TREE_TYPE (v), 1));
+ sz = fold_build2_loc (clause_loc, MULT_EXPR,
+ TREE_TYPE (v), t,
+ TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ }
if (pass == 3)
{
tree xv = create_tmp_var (ptr_type_node);
@@ -4755,6 +5005,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gimplify_assign (cond, x, ilist);
x = xv;
}
+ else if (lower_private_allocate (var, type, allocator,
+ allocate_ptr, ilist, ctx,
+ true,
+ TREE_CONSTANT (v)
+ ? TYPE_SIZE_UNIT (type)
+ : sz))
+ x = allocate_ptr;
else if (TREE_CONSTANT (v))
{
x = create_tmp_var_raw (type, name);
@@ -4766,20 +5023,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
{
tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
- tree t = maybe_lookup_decl (v, ctx);
- if (t)
- v = t;
- else
- v = maybe_lookup_decl_in_outer_ctx (v, ctx);
- gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
- t = fold_build2_loc (clause_loc, PLUS_EXPR,
- TREE_TYPE (v), v,
- build_int_cst (TREE_TYPE (v), 1));
- t = fold_build2_loc (clause_loc, MULT_EXPR,
- TREE_TYPE (v), t,
- TYPE_SIZE_UNIT (TREE_TYPE (type)));
tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
- x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
+ x = build_call_expr_loc (clause_loc, atmp, 2, sz, al);
}
tree ptype = build_pointer_type (TREE_TYPE (type));
@@ -5041,6 +5286,12 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gimple_seq_add_stmt (dlist, g);
gimple_seq_add_stmt (dlist, gimple_build_label (end2));
}
+ if (allocator)
+ {
+ tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+ g = gimple_build_call (f, 2, allocate_ptr, allocator);
+ gimple_seq_add_stmt (dlist, g);
+ }
continue;
}
else if (pass == 2)
@@ -5125,8 +5376,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
{
- gcall *stmt;
- tree tmp, atmp;
+ tree tmp;
ptr = DECL_VALUE_EXPR (new_var);
gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
@@ -5134,16 +5384,25 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gcc_assert (DECL_P (ptr));
x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
- /* void *tmp = __builtin_alloca */
- atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
- stmt = gimple_build_call (atmp, 2, x,
- size_int (DECL_ALIGN (var)));
- cfun->calls_alloca = 1;
- tmp = create_tmp_var_raw (ptr_type_node);
- gimple_add_tmp_var (tmp);
- gimple_call_set_lhs (stmt, tmp);
-
- gimple_seq_add_stmt (ilist, stmt);
+ if (lower_private_allocate (var, new_var, allocator,
+ allocate_ptr, ilist, ctx,
+ false, x))
+ tmp = allocate_ptr;
+ else
+ {
+ /* void *tmp = __builtin_alloca */
+ tree atmp
+ = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ gcall *stmt
+ = gimple_build_call (atmp, 2, x,
+ size_int (DECL_ALIGN (var)));
+ cfun->calls_alloca = 1;
+ tmp = create_tmp_var_raw (ptr_type_node);
+ gimple_add_tmp_var (tmp);
+ gimple_call_set_lhs (stmt, tmp);
+
+ gimple_seq_add_stmt (ilist, stmt);
+ }
x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
gimplify_assign (ptr, x, ilist);
@@ -5165,8 +5424,23 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
{
x = build_receiver_ref (var, false, ctx);
- x = build_fold_addr_expr_loc (clause_loc, x);
+ if (ctx->allocate_map)
+ if (tree *allocatep = ctx->allocate_map->get (var))
+ {
+ allocator = *allocatep;
+ if (TREE_CODE (allocator) != INTEGER_CST)
+ allocator = build_outer_var_ref (allocator, ctx);
+ allocator = fold_convert (pointer_sized_int_node,
+ allocator);
+ allocate_ptr = unshare_expr (x);
+ }
+ if (allocator == NULL_TREE)
+ x = build_fold_addr_expr_loc (clause_loc, x);
}
+ else if (lower_private_allocate (var, new_var, allocator,
+ allocate_ptr,
+ ilist, ctx, true, x))
+ x = allocate_ptr;
else if (TREE_CONSTANT (x))
{
/* For reduction in SIMD loop, defer adding the
@@ -5279,6 +5553,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
tree nx;
bool copy_ctor;
copy_ctor = false;
+ lower_private_allocate (var, new_var, allocator, allocate_ptr,
+ ilist, ctx, false, NULL_TREE);
nx = unshare_expr (new_var);
if (is_simd
&& OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
@@ -5424,6 +5700,25 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = lang_hooks.decls.omp_clause_dtor (c, new_var);
if (x)
gimplify_and_add (x, dlist);
+ if (allocator)
+ {
+ if (!is_gimple_val (allocator))
+ {
+ tree avar = create_tmp_var (TREE_TYPE (allocator));
+ gimplify_assign (avar, allocator, dlist);
+ allocator = avar;
+ }
+ if (!is_gimple_val (allocate_ptr))
+ {
+ tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
+ gimplify_assign (apvar, allocate_ptr, dlist);
+ allocate_ptr = apvar;
+ }
+ tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+ gimple *g
+ = gimple_build_call (f, 2, allocate_ptr, allocator);
+ gimple_seq_add_stmt (dlist, g);
+ }
break;
case OMP_CLAUSE_LINEAR:
@@ -5447,6 +5742,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|| use_pointer_for_field (var, NULL))
{
x = build_receiver_ref (var, false, ctx);
+ if (ctx->allocate_map)
+ if (tree *allocatep = ctx->allocate_map->get (var))
+ {
+ allocator = *allocatep;
+ if (TREE_CODE (allocator) != INTEGER_CST)
+ allocator = build_outer_var_ref (allocator, ctx);
+ allocator = fold_convert (pointer_sized_int_node,
+ allocator);
+ allocate_ptr = unshare_expr (x);
+ x = build_simple_mem_ref (x);
+ TREE_THIS_NOTRAP (x) = 1;
+ }
SET_DECL_VALUE_EXPR (new_var, x);
DECL_HAS_VALUE_EXPR_P (new_var) = 1;
goto do_dtor;
@@ -5465,6 +5772,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
goto do_dtor;
}
do_firstprivate:
+ lower_private_allocate (var, new_var, allocator, allocate_ptr,
+ ilist, ctx, false, NULL_TREE);
x = build_outer_var_ref (var, ctx);
if (is_simd)
{
@@ -5652,6 +5961,9 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
else
{
+ lower_private_allocate (var, new_var, allocator,
+ allocate_ptr, ilist, ctx, false,
+ NULL_TREE);
x = build_outer_var_ref (var, ctx);
if (omp_is_reference (var)
@@ -6048,6 +6360,9 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
else
{
+ lower_private_allocate (var, new_var, allocator,
+ allocate_ptr, ilist, ctx,
+ false, NULL_TREE);
if (omp_is_reference (var) && is_simd)
handle_simd_reference (clause_loc, new_vard, ilist);
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
@@ -6062,6 +6377,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
ref = build_outer_var_ref (var, ctx);
gimplify_assign (ref, x, dlist);
}
+ if (allocator)
+ goto do_dtor;
}
}
break;
@@ -6698,6 +7015,11 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
{
+ /* No 'reduction' clauses on OpenACC 'kernels'. */
+ gcc_checking_assert (!is_oacc_kernels (ctx));
+ /* Likewise, on OpenACC 'kernels' decomposed parts. */
+ gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
+
tree orig = OMP_CLAUSE_DECL (c);
tree var = maybe_lookup_decl (orig, ctx);
tree ref_to_res = NULL_TREE;
@@ -6735,10 +7057,11 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
break;
case GIMPLE_OMP_TARGET:
- if ((gimple_omp_target_kind (probe->stmt)
- != GF_OMP_TARGET_KIND_OACC_PARALLEL)
- && (gimple_omp_target_kind (probe->stmt)
- != GF_OMP_TARGET_KIND_OACC_SERIAL))
+ /* No 'reduction' clauses inside OpenACC 'kernels'
+ regions. */
+ gcc_checking_assert (!is_oacc_kernels (probe));
+
+ if (!is_gimple_omp_offloaded (probe->stmt))
goto do_lookup;
cls = gimple_omp_target_clauses (probe->stmt);
@@ -7418,7 +7741,10 @@ lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
continue;
nvar = maybe_lookup_decl (ovar, ctx);
- if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
+ if (!nvar
+ || !DECL_HAS_VALUE_EXPR_P (nvar)
+ || (ctx->allocate_map
+ && ctx->allocate_map->get (ovar)))
continue;
/* If CTX is a nested parallel directive. Find the immediately
@@ -7542,11 +7868,29 @@ lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
tag |= OLF_GANG_STATIC;
}
- /* In a parallel region, loops are implicitly INDEPENDENT. */
omp_context *tgt = enclosing_target_ctx (ctx);
if (!tgt || is_oacc_parallel_or_serial (tgt))
+ ;
+ else if (is_oacc_kernels (tgt))
+ /* Not using this loops handling inside OpenACC 'kernels' regions. */
+ gcc_unreachable ();
+ else if (is_oacc_kernels_decomposed_part (tgt))
+ ;
+ else
+ gcc_unreachable ();
+
+ /* In a parallel region, loops are implicitly INDEPENDENT. */
+ if (!tgt || is_oacc_parallel_or_serial (tgt))
tag |= OLF_INDEPENDENT;
+ /* Loops inside OpenACC 'kernels' decomposed parts' regions are expected to
+ have an explicit 'seq' or 'independent' clause, and no 'auto' clause. */
+ if (tgt && is_oacc_kernels_decomposed_part (tgt))
+ {
+ gcc_assert (tag & (OLF_SEQ | OLF_INDEPENDENT));
+ gcc_assert (!(tag & OLF_AUTO));
+ }
+
if (tag & OLF_TILE)
/* Tiling could use all 3 levels. */
levels = 3;
@@ -10996,7 +11340,35 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
else
- t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
+ {
+ if (ctx->allocate_map)
+ if (tree *allocatorp = ctx->allocate_map->get (decl))
+ {
+ tree allocator = *allocatorp;
+ if (TREE_CODE (allocator) != INTEGER_CST)
+ {
+ n = splay_tree_lookup (ctx->sfield_map,
+ (splay_tree_key) allocator);
+ allocator = (tree) n->value;
+ if (tcctx.cb.decl_map)
+ allocator = *tcctx.cb.decl_map->get (allocator);
+ tree a = build_simple_mem_ref_loc (loc, sarg);
+ allocator = omp_build_component_ref (a, allocator);
+ }
+ allocator = fold_convert (pointer_sized_int_node, allocator);
+ tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
+ tree align = build_int_cst (size_type_node,
+ DECL_ALIGN_UNIT (decl));
+ tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst)));
+ tree ptr = build_call_expr_loc (loc, a, 3, align, sz,
+ allocator);
+ ptr = fold_convert (TREE_TYPE (dst), ptr);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, ptr);
+ append_to_statement_list (t, &list);
+ dst = build_simple_mem_ref_loc (loc, dst);
+ }
+ t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
+ }
append_to_statement_list (t, &list);
break;
case OMP_CLAUSE_PRIVATE:
@@ -11394,11 +11766,14 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
case GF_OMP_TARGET_KIND_OACC_UPDATE:
case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
case GF_OMP_TARGET_KIND_OACC_DECLARE:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
+ case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
data_region = false;
break;
case GF_OMP_TARGET_KIND_DATA:
case GF_OMP_TARGET_KIND_OACC_DATA:
case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
+ case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
data_region = true;
break;
default:
@@ -11458,6 +11833,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_STRUCT:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH:
+ case GOMP_MAP_DETACH:
break;
case GOMP_MAP_IF_PRESENT:
case GOMP_MAP_FORCE_ALLOC:
@@ -11468,8 +11845,6 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
case GOMP_MAP_FORCE_DEVICEPTR:
case GOMP_MAP_DEVICE_RESIDENT:
case GOMP_MAP_LINK:
- case GOMP_MAP_ATTACH:
- case GOMP_MAP_DETACH:
case GOMP_MAP_FORCE_DETACH:
gcc_assert (is_gimple_omp_oacc (stmt));
break;
@@ -11524,6 +11899,16 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
continue;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+ && is_omp_target (stmt))
+ {
+ gcc_assert (maybe_lookup_field (c, ctx));
+ map_cnt++;
+ continue;
+ }
+
if (!maybe_lookup_field (var, ctx))
continue;
@@ -11569,8 +11954,16 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- if (is_oacc_parallel_or_serial (ctx))
- goto oacc_firstprivate;
+ gcc_checking_assert (offloaded);
+ if (is_gimple_omp_oacc (ctx->stmt))
+ {
+ /* No 'firstprivate' clauses on OpenACC 'kernels'. */
+ gcc_checking_assert (!is_oacc_kernels (ctx));
+ /* Likewise, on OpenACC 'kernels' decomposed parts. */
+ gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
+
+ goto oacc_firstprivate;
+ }
map_cnt++;
var = OMP_CLAUSE_DECL (c);
if (!omp_is_reference (var)
@@ -11595,8 +11988,16 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
break;
case OMP_CLAUSE_PRIVATE:
+ gcc_checking_assert (offloaded);
if (is_gimple_omp_oacc (ctx->stmt))
- break;
+ {
+ /* No 'private' clauses on OpenACC 'kernels'. */
+ gcc_checking_assert (!is_oacc_kernels (ctx));
+ /* Likewise, on OpenACC 'kernels' decomposed parts. */
+ gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
+
+ break;
+ }
var = OMP_CLAUSE_DECL (c);
if (is_variable_sized (var))
{
@@ -11756,14 +12157,28 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gcc_assert (DECL_P (ovar2));
ovar = ovar2;
}
- if (!maybe_lookup_field (ovar, ctx))
+ if (!maybe_lookup_field (ovar, ctx)
+ && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)))
continue;
}
talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
talign = DECL_ALIGN_UNIT (ovar);
- if (nc)
+
+ if (nc
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+ && is_omp_target (stmt))
+ {
+ var = lookup_decl_in_outer_ctx (ovar, ctx);
+ x = build_sender_ref (c, ctx);
+ gimplify_assign (x, build_fold_addr_expr (var), &ilist);
+ }
+ else if (nc)
{
var = lookup_decl_in_outer_ctx (ovar, ctx);
x = build_sender_ref (ovar, ctx);
@@ -11945,7 +12360,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- if (is_oacc_parallel_or_serial (ctx))
+ if (is_gimple_omp_oacc (ctx->stmt))
goto oacc_firstprivate_map;
ovar = OMP_CLAUSE_DECL (c);
if (omp_is_reference (ovar))
@@ -12549,7 +12964,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq fork_seq = NULL;
gimple_seq join_seq = NULL;
- if (is_oacc_parallel_or_serial (ctx))
+ if (offloaded && is_gimple_omp_oacc (ctx->stmt))
{
/* If there are reductions on the offloaded region itself, treat
them as a dummy GANG loop. */
@@ -12564,9 +12979,10 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_seq (&new_body, join_seq);
if (offloaded)
- new_body = maybe_catch_exception (new_body);
-
- gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
+ {
+ new_body = maybe_catch_exception (new_body);
+ gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
+ }
gimple_omp_set_body (stmt, new_body);
}
diff --git a/gcc/omp-oacc-kernels-decompose.cc b/gcc/omp-oacc-kernels-decompose.cc
new file mode 100644
index 0000000..c46168e
--- /dev/null
+++ b/gcc/omp-oacc-kernels-decompose.cc
@@ -0,0 +1,1545 @@
+/* Decompose OpenACC 'kernels' constructs into parts, a sequence of compute
+ constructs
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+#include "fold-const.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "gomp-constants.h"
+#include "omp-general.h"
+#include "diagnostic-core.h"
+
+
+/* This preprocessing pass is run immediately before lower_omp. It decomposes
+ OpenACC 'kernels' constructs into parts, a sequence of compute constructs.
+
+ The translation is as follows:
+ - The entire 'kernels' region is turned into a 'data' region with clauses
+ taken from the 'kernels' region. New 'create' clauses are added for all
+ variables declared at the top level in the kernels region.
+ - Any loop nests annotated with an OpenACC 'loop' directive are wrapped in
+ a new compute construct.
+ - 'loop' directives without an explicit 'independent' or 'seq' clause
+ get an 'auto' clause added; other clauses are preserved on the loop
+ or moved to the new surrounding compute construct, as applicable.
+ - Any sequences of other code (non-loops, non-OpenACC 'loop's) are wrapped
+ in new "gang-single" compute construct: 'worker'/'vector' parallelism is
+ preserved, but 'num_gangs (1)' is enforced.
+ - Both points above only apply at the topmost level in the region, that
+ is, the transformation does not introduce new compute constructs inside
+ nested statement bodies. In particular, this means that a
+ gang-parallelizable loop inside an 'if' statement is made "gang-single".
+ - In order to make the host wait only once for the whole region instead
+ of once per device kernel launch, the new compute constructs are
+ annotated 'async'. Unless the original 'kernels' construct already was
+ marked 'async', the entire region ends with a 'wait' directive. If the
+ original 'kernels' construct was marked 'async', the synthesized 'async'
+ clauses use the original 'kernels' construct's 'async' argument
+ (possibly implicit).
+*/
+
+
+/*TODO Things are conceptually wrong here: 'loop' clauses may be hidden behind
+ 'device_type', so we have to defer a lot of processing until we're in the
+ offloading compilation. "Fortunately", GCC doesn't support the OpenACC
+ 'device_type' clause yet, so we get away that. */
+
+
+/* Helper function for decompose_kernels_region_body. If STMT contains a
+ "top-level" OMP_FOR statement, returns a pointer to that statement;
+ returns NULL otherwise.
+
+ A "top-level" OMP_FOR statement is one that is possibly accompanied by
+ small snippets of setup code. Specifically, this function accepts an
+ OMP_FOR possibly wrapped in a singleton bind and a singleton try
+ statement to allow for a local loop variable, but not an OMP_FOR
+ statement nested in any other constructs. Alternatively, it accepts a
+ non-singleton bind containing only assignments and then an OMP_FOR
+ statement at the very end. The former style can be generated by the C
+ frontend, the latter by the Fortran frontend. */
+
+static gimple *
+top_level_omp_for_in_stmt (gimple *stmt)
+{
+ if (gimple_code (stmt) == GIMPLE_OMP_FOR)
+ return stmt;
+
+ if (gimple_code (stmt) == GIMPLE_BIND)
+ {
+ gimple_seq body = gimple_bind_body (as_a <gbind *> (stmt));
+ if (gimple_seq_singleton_p (body))
+ {
+ /* Accept an OMP_FOR statement, or a try statement containing only
+ a single OMP_FOR. */
+ gimple *maybe_for_or_try = gimple_seq_first_stmt (body);
+ if (gimple_code (maybe_for_or_try) == GIMPLE_OMP_FOR)
+ return maybe_for_or_try;
+ else if (gimple_code (maybe_for_or_try) == GIMPLE_TRY)
+ {
+ gimple_seq try_body = gimple_try_eval (maybe_for_or_try);
+ if (!gimple_seq_singleton_p (try_body))
+ return NULL;
+ gimple *maybe_omp_for_stmt = gimple_seq_first_stmt (try_body);
+ if (gimple_code (maybe_omp_for_stmt) == GIMPLE_OMP_FOR)
+ return maybe_omp_for_stmt;
+ }
+ }
+ else
+ {
+ gimple_stmt_iterator gsi;
+ /* Accept only a block of optional assignments followed by an
+ OMP_FOR at the end. No other kinds of statements allowed. */
+ for (gsi = gsi_start (body); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *body_stmt = gsi_stmt (gsi);
+ if (gimple_code (body_stmt) == GIMPLE_ASSIGN)
+ continue;
+ else if (gimple_code (body_stmt) == GIMPLE_OMP_FOR
+ && gsi_one_before_end_p (gsi))
+ return body_stmt;
+ else
+ return NULL;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* Helper for adjust_region_code: evaluate the statement at GSI_P. */
+
+static tree
+adjust_region_code_walk_stmt_fn (gimple_stmt_iterator *gsi_p,
+ bool *handled_ops_p,
+ struct walk_stmt_info *wi)
+{
+ int *region_code = (int *) wi->info;
+
+ gimple *stmt = gsi_stmt (*gsi_p);
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_OMP_FOR:
+ {
+ tree clauses = gimple_omp_for_clauses (stmt);
+ if (omp_find_clause (clauses, OMP_CLAUSE_INDEPENDENT))
+ {
+ /* Explicit 'independent' clause. */
+ /* Keep going; recurse into loop body. */
+ break;
+ }
+ else if (omp_find_clause (clauses, OMP_CLAUSE_SEQ))
+ {
+ /* Explicit 'seq' clause. */
+ /* We'll "parallelize" if at some level a loop construct has been
+ marked up by the user as unparallelizable ('seq' clause; we'll
+ respect that in the later processing). Given that the user has
+ explicitly marked it up, this loop construct cannot be
+ performance-critical, and in this case it's also fine to
+ "parallelize" instead of "gang-single", because any outer or
+ inner loops may still exploit the available parallelism. */
+ /* Keep going; recurse into loop body. */
+ break;
+ }
+ else
+ {
+ /* Explicit or implicit 'auto' clause. */
+ /* The user would like this loop analyzed ('auto' clause) and
+ typically parallelized, but we don't have available yet the
+ compiler logic to analyze this, so can't parallelize it here, so
+ we'd very likely be running into a performance problem if we
+ were to execute this unparallelized, thus forward the whole loop
+ nest to 'parloops'. */
+ *region_code = GF_OMP_TARGET_KIND_OACC_KERNELS;
+ /* Terminate: final decision for this region. */
+ *handled_ops_p = true;
+ return integer_zero_node;
+ }
+ gcc_unreachable ();
+ }
+
+ case GIMPLE_COND:
+ case GIMPLE_GOTO:
+ case GIMPLE_SWITCH:
+ case GIMPLE_ASM:
+ case GIMPLE_TRANSACTION:
+ case GIMPLE_RETURN:
+ /* Statement that might constitute some looping/control flow pattern. */
+ /* The user would like this code analyzed (implicit inside a 'kernels'
+ region) and typically parallelized, but we don't have available yet
+ the compiler logic to analyze this, so can't parallelize it here, so
+ we'd very likely be running into a performance problem if we were to
+ execute this unparallelized, thus forward the whole thing to
+ 'parloops'. */
+ *region_code = GF_OMP_TARGET_KIND_OACC_KERNELS;
+ /* Terminate: final decision for this region. */
+ *handled_ops_p = true;
+ return integer_zero_node;
+
+ default:
+ /* Keep going. */
+ break;
+ }
+
+ return NULL;
+}
+
+/* Adjust the REGION_CODE for the region in GS. */
+
+static void
+adjust_region_code (gimple_seq gs, int *region_code)
+{
+ struct walk_stmt_info wi;
+ memset (&wi, 0, sizeof (wi));
+ wi.info = region_code;
+ walk_gimple_seq (gs, adjust_region_code_walk_stmt_fn, NULL, &wi);
+}
+
+/* Helper function for make_loops_gang_single for walking the tree. If the
+ statement indicated by GSI_P is an OpenACC for loop with a gang clause,
+ issue a warning and remove the clause. */
+
+static tree
+visit_loops_in_gang_single_region (gimple_stmt_iterator *gsi_p,
+ bool *handled_ops_p,
+ struct walk_stmt_info *)
+{
+ *handled_ops_p = false;
+
+ gimple *stmt = gsi_stmt (*gsi_p);
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_OMP_FOR:
+ /*TODO Given the current 'adjust_region_code' algorithm, this is
+ actually... */
+ gcc_unreachable ();
+
+ {
+ tree clauses = gimple_omp_for_clauses (stmt);
+ tree prev_clause = NULL;
+ for (tree clause = clauses; clause; clause = OMP_CLAUSE_CHAIN (clause))
+ {
+ if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_GANG)
+ {
+ /* It makes no sense to have a 'gang' clause in a "gang-single"
+ region, so warn and remove it. */
+ warning_at (gimple_location (stmt), 0,
+ "conditionally executed loop in %<kernels%> region"
+ " will be executed by a single gang;"
+ " ignoring %<gang%> clause");
+ if (prev_clause != NULL)
+ OMP_CLAUSE_CHAIN (prev_clause) = OMP_CLAUSE_CHAIN (clause);
+ else
+ clauses = OMP_CLAUSE_CHAIN (clause);
+
+ break;
+ }
+ prev_clause = clause;
+ }
+ gimple_omp_for_set_clauses (stmt, clauses);
+ }
+ /* No need to recurse into nested statements; no loop nested inside
+ this loop can be gang-partitioned. */
+ sorry ("%<gang%> loop in %<gang-single%> region");
+ *handled_ops_p = true;
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+/* Visit all nested OpenACC loops in the sequence indicated by GS. This
+ statement is expected to be inside a gang-single region. Issue a warning
+ for any loops inside it that have gang clauses and remove the clauses. */
+
+static void
+make_loops_gang_single (gimple_seq gs)
+{
+ struct walk_stmt_info wi;
+ memset (&wi, 0, sizeof (wi));
+ walk_gimple_seq (gs, visit_loops_in_gang_single_region, NULL, &wi);
+}
+
+/* Construct a "gang-single" compute construct at LOC containing the STMTS.
+ Annotate with CLAUSES, which must not contain a 'num_gangs' clause, and an
+ additional 'num_gangs (1)' clause to force "gang-single" execution. */
+
+static gimple *
+make_region_seq (location_t loc, gimple_seq stmts,
+ tree num_gangs_clause,
+ tree num_workers_clause,
+ tree vector_length_clause,
+ tree clauses)
+{
+ /* This correctly unshares the entire clause chain rooted here. */
+ clauses = unshare_expr (clauses);
+
+ dump_user_location_t loc_stmts_first = gimple_seq_first (stmts);
+
+ /* Figure out the region code for this region. */
+ /* Optimistic default: assume "setup code", no looping; thus not
+ performance-critical. */
+ int region_code = GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE;
+ adjust_region_code (stmts, &region_code);
+
+ if (region_code == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE)
+ {
+ if (dump_enabled_p ())
+ /*TODO MSG_MISSED_OPTIMIZATION? */
+ dump_printf_loc (MSG_NOTE, loc_stmts_first,
+ "beginning %<gang-single%> part"
+ " in OpenACC %<kernels%> region\n");
+
+ /* Synthesize a 'num_gangs (1)' clause. */
+ tree gang_single_clause = build_omp_clause (loc, OMP_CLAUSE_NUM_GANGS);
+ OMP_CLAUSE_OPERAND (gang_single_clause, 0) = integer_one_node;
+ OMP_CLAUSE_CHAIN (gang_single_clause) = clauses;
+ clauses = gang_single_clause;
+
+ /* Remove and issue warnings about gang clauses on any OpenACC
+ loops nested inside this sequentially executed statement. */
+ make_loops_gang_single (stmts);
+ }
+ else if (region_code == GF_OMP_TARGET_KIND_OACC_KERNELS)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc_stmts_first,
+ "beginning %<parloops%> part"
+ " in OpenACC %<kernels%> region\n");
+
+ /* As we're transforming a 'GF_OMP_TARGET_KIND_OACC_KERNELS' into another
+ 'GF_OMP_TARGET_KIND_OACC_KERNELS', this isn't doing any of the clauses
+ mangling that 'make_region_loop_nest' is doing. */
+ /* Re-assemble the clauses stripped off earlier. */
+ if (num_gangs_clause != NULL)
+ {
+ tree c = unshare_expr (num_gangs_clause);
+ OMP_CLAUSE_CHAIN (c) = clauses;
+ clauses = c;
+ }
+ if (num_workers_clause != NULL)
+ {
+ tree c = unshare_expr (num_workers_clause);
+ OMP_CLAUSE_CHAIN (c) = clauses;
+ clauses = c;
+ }
+ if (vector_length_clause != NULL)
+ {
+ tree c = unshare_expr (vector_length_clause);
+ OMP_CLAUSE_CHAIN (c) = clauses;
+ clauses = c;
+ }
+ }
+ else
+ gcc_unreachable ();
+
+ /* Build the gang-single region. */
+ gimple *single_region = gimple_build_omp_target (NULL, region_code, clauses);
+ gimple_set_location (single_region, loc);
+ gbind *single_body = gimple_build_bind (NULL, stmts, make_node (BLOCK));
+ gimple_omp_set_body (single_region, single_body);
+
+ return single_region;
+}
+
+/* Helper function for make_region_loop_nest. Adds a 'num_gangs'
+ ('num_workers', 'vector_length') clause to the given CLAUSES, either the one
+ from the parent compute construct (PARENT_CLAUSE) or a new one based on the
+ loop's own LOOP_CLAUSE ('gang (num: N)' or similar for 'worker' or 'vector'
+ clauses) with the given CLAUSE_CODE. Does nothing if neither PARENT_CLAUSE
+ nor LOOP_CLAUSE exist. Returns the new clauses. */
+
+static tree
+add_parent_or_loop_num_clause (tree parent_clause, tree loop_clause,
+ omp_clause_code clause_code, tree clauses)
+{
+ if (parent_clause != NULL)
+ {
+ tree num_clause = unshare_expr (parent_clause);
+ OMP_CLAUSE_CHAIN (num_clause) = clauses;
+ clauses = num_clause;
+ }
+ else if (loop_clause != NULL)
+ {
+ /* The kernels region does not have a 'num_gangs' clause, but the loop
+ itself had a 'gang (num: N)' clause. Honor it by adding a
+ 'num_gangs (N)' clause on the compute construct. */
+ tree num = OMP_CLAUSE_OPERAND (loop_clause, 0);
+ tree new_num_clause
+ = build_omp_clause (OMP_CLAUSE_LOCATION (loop_clause), clause_code);
+ OMP_CLAUSE_OPERAND (new_num_clause, 0) = num;
+ OMP_CLAUSE_CHAIN (new_num_clause) = clauses;
+ clauses = new_num_clause;
+ }
+ return clauses;
+}
+
+/* Helper for make_region_loop_nest, looking for 'worker (num: N)' or 'vector
+ (length: N)' clauses in nested loops. Removes the argument, transferring it
+ to the enclosing compute construct (via WI->INFO). If arguments within the
+ same loop nest conflict, emits a warning.
+
+ This function also decides whether to add an 'auto' clause on each of these
+ nested loops. */
+
+struct adjust_nested_loop_clauses_wi_info
+{
+ tree *loop_gang_clause_ptr;
+ tree *loop_worker_clause_ptr;
+ tree *loop_vector_clause_ptr;
+};
+
+static tree
+adjust_nested_loop_clauses (gimple_stmt_iterator *gsi_p, bool *,
+ struct walk_stmt_info *wi)
+{
+ struct adjust_nested_loop_clauses_wi_info *wi_info
+ = (struct adjust_nested_loop_clauses_wi_info *) wi->info;
+ gimple *stmt = gsi_stmt (*gsi_p);
+
+ if (gimple_code (stmt) == GIMPLE_OMP_FOR)
+ {
+ bool add_auto_clause = true;
+ tree loop_clauses = gimple_omp_for_clauses (stmt);
+ tree loop_clause = loop_clauses;
+ for (; loop_clause; loop_clause = OMP_CLAUSE_CHAIN (loop_clause))
+ {
+ tree *outer_clause_ptr = NULL;
+ switch (OMP_CLAUSE_CODE (loop_clause))
+ {
+ case OMP_CLAUSE_GANG:
+ outer_clause_ptr = wi_info->loop_gang_clause_ptr;
+ break;
+ case OMP_CLAUSE_WORKER:
+ outer_clause_ptr = wi_info->loop_worker_clause_ptr;
+ break;
+ case OMP_CLAUSE_VECTOR:
+ outer_clause_ptr = wi_info->loop_vector_clause_ptr;
+ break;
+ case OMP_CLAUSE_SEQ:
+ case OMP_CLAUSE_INDEPENDENT:
+ case OMP_CLAUSE_AUTO:
+ add_auto_clause = false;
+ default:
+ break;
+ }
+ if (outer_clause_ptr != NULL)
+ {
+ if (OMP_CLAUSE_OPERAND (loop_clause, 0) != NULL
+ && *outer_clause_ptr == NULL)
+ {
+ /* Transfer the clause to the enclosing compute construct and
+ remove the numerical argument from the 'loop'. */
+ *outer_clause_ptr = unshare_expr (loop_clause);
+ OMP_CLAUSE_OPERAND (loop_clause, 0) = NULL;
+ }
+ else if (OMP_CLAUSE_OPERAND (loop_clause, 0) != NULL &&
+ OMP_CLAUSE_OPERAND (*outer_clause_ptr, 0) != NULL)
+ {
+ /* See if both of these are the same constant. If they
+ aren't, emit a warning. */
+ tree old_op = OMP_CLAUSE_OPERAND (*outer_clause_ptr, 0);
+ tree new_op = OMP_CLAUSE_OPERAND (loop_clause, 0);
+ if (!(cst_and_fits_in_hwi (old_op) &&
+ cst_and_fits_in_hwi (new_op) &&
+ int_cst_value (old_op) == int_cst_value (new_op)))
+ {
+ const char *clause_name
+ = omp_clause_code_name[OMP_CLAUSE_CODE (loop_clause)];
+ error_at (gimple_location (stmt),
+ "cannot honor conflicting %qs clause",
+ clause_name);
+ inform (OMP_CLAUSE_LOCATION (*outer_clause_ptr),
+ "location of the previous clause"
+ " in the same loop nest");
+ }
+ OMP_CLAUSE_OPERAND (loop_clause, 0) = NULL;
+ }
+ }
+ }
+ if (add_auto_clause)
+ {
+ tree auto_clause
+ = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_AUTO);
+ OMP_CLAUSE_CHAIN (auto_clause) = loop_clauses;
+ gimple_omp_for_set_clauses (stmt, auto_clause);
+ }
+ }
+
+ return NULL;
+}
+
+/* Helper for make_region_loop_nest. Transform OpenACC 'kernels'/'loop'
+ construct clauses into OpenACC 'parallel'/'loop' construct ones. */
+
+static tree
+transform_kernels_loop_clauses (gimple *omp_for,
+ tree num_gangs_clause,
+ tree num_workers_clause,
+ tree vector_length_clause,
+ tree clauses)
+{
+ /* If this loop in a kernels region does not have an explicit 'seq',
+ 'independent', or 'auto' clause, we must give it an explicit 'auto'
+ clause.
+ We also check for 'gang (num: N)' clauses. These must not appear in
+ kernels regions that have their own 'num_gangs' clause. Otherwise, they
+ must be converted and put on the region; similarly for 'worker' and
+ 'vector' clauses. */
+ bool add_auto_clause = true;
+ tree loop_gang_clause = NULL, loop_worker_clause = NULL,
+ loop_vector_clause = NULL;
+ tree loop_clauses = gimple_omp_for_clauses (omp_for);
+ for (tree loop_clause = loop_clauses;
+ loop_clause;
+ loop_clause = OMP_CLAUSE_CHAIN (loop_clause))
+ {
+ bool found_num_clause = false;
+ tree *clause_ptr, clause_to_check;
+ switch (OMP_CLAUSE_CODE (loop_clause))
+ {
+ case OMP_CLAUSE_GANG:
+ found_num_clause = true;
+ clause_ptr = &loop_gang_clause;
+ clause_to_check = num_gangs_clause;
+ break;
+ case OMP_CLAUSE_WORKER:
+ found_num_clause = true;
+ clause_ptr = &loop_worker_clause;
+ clause_to_check = num_workers_clause;
+ break;
+ case OMP_CLAUSE_VECTOR:
+ found_num_clause = true;
+ clause_ptr = &loop_vector_clause;
+ clause_to_check = vector_length_clause;
+ break;
+ case OMP_CLAUSE_INDEPENDENT:
+ case OMP_CLAUSE_SEQ:
+ case OMP_CLAUSE_AUTO:
+ add_auto_clause = false;
+ default:
+ break;
+ }
+ if (found_num_clause && OMP_CLAUSE_OPERAND (loop_clause, 0) != NULL)
+ {
+ if (clause_to_check)
+ {
+ const char *clause_name
+ = omp_clause_code_name[OMP_CLAUSE_CODE (loop_clause)];
+ const char *parent_clause_name
+ = omp_clause_code_name[OMP_CLAUSE_CODE (clause_to_check)];
+ error_at (OMP_CLAUSE_LOCATION (loop_clause),
+ "argument not permitted on %qs clause"
+ " in OpenACC %<kernels%> region with a %qs clause",
+ clause_name, parent_clause_name);
+ inform (OMP_CLAUSE_LOCATION (clause_to_check),
+ "location of OpenACC %<kernels%>");
+ }
+ /* Copy the 'gang (N)'/'worker (N)'/'vector (N)' clause to the
+ enclosing compute construct. */
+ *clause_ptr = unshare_expr (loop_clause);
+ OMP_CLAUSE_CHAIN (*clause_ptr) = NULL;
+ /* Leave a 'gang'/'worker'/'vector' clause on the 'loop', but without
+ argument. */
+ OMP_CLAUSE_OPERAND (loop_clause, 0) = NULL;
+ }
+ }
+ if (add_auto_clause)
+ {
+ tree auto_clause = build_omp_clause (gimple_location (omp_for),
+ OMP_CLAUSE_AUTO);
+ OMP_CLAUSE_CHAIN (auto_clause) = loop_clauses;
+ loop_clauses = auto_clause;
+ }
+ gimple_omp_for_set_clauses (omp_for, loop_clauses);
+ /* We must also recurse into the loop; it might contain nested loops having
+ their own 'worker (num: W)' or 'vector (length: V)' clauses. Turn these
+ into 'worker'/'vector' clauses on the compute construct. */
+ struct walk_stmt_info wi;
+ memset (&wi, 0, sizeof (wi));
+ struct adjust_nested_loop_clauses_wi_info wi_info;
+ wi_info.loop_gang_clause_ptr = &loop_gang_clause;
+ wi_info.loop_worker_clause_ptr = &loop_worker_clause;
+ wi_info.loop_vector_clause_ptr = &loop_vector_clause;
+ wi.info = &wi_info;
+ gimple *body = gimple_omp_body (omp_for);
+ walk_gimple_seq (body, adjust_nested_loop_clauses, NULL, &wi);
+ /* Check if there were conflicting numbers of workers or vector length. */
+ if (loop_gang_clause != NULL &&
+ OMP_CLAUSE_OPERAND (loop_gang_clause, 0) == NULL)
+ loop_gang_clause = NULL;
+ if (loop_worker_clause != NULL &&
+ OMP_CLAUSE_OPERAND (loop_worker_clause, 0) == NULL)
+ loop_worker_clause = NULL;
+ if (loop_vector_clause != NULL &&
+ OMP_CLAUSE_OPERAND (loop_vector_clause, 0) == NULL)
+ vector_length_clause = NULL;
+
+ /* If the kernels region had 'num_gangs', 'num_worker', 'vector_length'
+ clauses, add these to this new compute construct. */
+ clauses
+ = add_parent_or_loop_num_clause (num_gangs_clause, loop_gang_clause,
+ OMP_CLAUSE_NUM_GANGS, clauses);
+ clauses
+ = add_parent_or_loop_num_clause (num_workers_clause, loop_worker_clause,
+ OMP_CLAUSE_NUM_WORKERS, clauses);
+ clauses
+ = add_parent_or_loop_num_clause (vector_length_clause, loop_vector_clause,
+ OMP_CLAUSE_VECTOR_LENGTH, clauses);
+
+ return clauses;
+}
+
+/* Construct a possibly gang-parallel compute construct containing the STMT,
+ which must be identical to, or a bind containing, the loop OMP_FOR.
+
+ The NUM_GANGS_CLAUSE, NUM_WORKERS_CLAUSE, and VECTOR_LENGTH_CLAUSE are
+ optional clauses from the original kernels region and must not be contained
+ in the other CLAUSES. The newly created compute construct is annotated with
+ the optional NUM_GANGS_CLAUSE as well as the other CLAUSES. If there is no
+ NUM_GANGS_CLAUSE but the loop has a 'gang (num: N)' clause, that is
+ converted to a 'num_gangs (N)' clause on the new compute construct, and
+ similarly for 'worker' and 'vector' clauses.
+
+ The outermost loop gets an 'auto' clause unless there already is an
+ 'seq'/'independent'/'auto' clause. Nested loops inside OMP_FOR are treated
+ similarly by the adjust_nested_loop_clauses function. */
+
+static gimple *
+make_region_loop_nest (gimple *omp_for, gimple_seq stmts,
+ tree num_gangs_clause,
+ tree num_workers_clause,
+ tree vector_length_clause,
+ tree clauses)
+{
+ /* This correctly unshares the entire clause chain rooted here. */
+ clauses = unshare_expr (clauses);
+
+ /* Figure out the region code for this region. */
+ /* Optimistic default: assume that the loop nest is parallelizable
+ (essentially, no GIMPLE_OMP_FOR with (explicit or implicit) 'auto' clause,
+ and no un-annotated loops). */
+ int region_code = GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED;
+ adjust_region_code (stmts, &region_code);
+
+ if (region_code == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED)
+ {
+ if (dump_enabled_p ())
+ /* This is not MSG_OPTIMIZED_LOCATIONS, as we're just doing what the
+ user asked us to. */
+ dump_printf_loc (MSG_NOTE, omp_for,
+ "parallelized loop nest"
+ " in OpenACC %<kernels%> region\n");
+
+ clauses = transform_kernels_loop_clauses (omp_for,
+ num_gangs_clause,
+ num_workers_clause,
+ vector_length_clause,
+ clauses);
+ }
+ else if (region_code == GF_OMP_TARGET_KIND_OACC_KERNELS)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, omp_for,
+ "forwarded loop nest"
+ " in OpenACC %<kernels%> region"
+ " to %<parloops%> for analysis\n");
+
+ /* We're transforming one 'GF_OMP_TARGET_KIND_OACC_KERNELS' into another
+ 'GF_OMP_TARGET_KIND_OACC_KERNELS', so don't have to
+ 'transform_kernels_loop_clauses'. */
+ /* Re-assemble the clauses stripped off earlier. */
+ clauses
+ = add_parent_or_loop_num_clause (num_gangs_clause, NULL,
+ OMP_CLAUSE_NUM_GANGS, clauses);
+ clauses
+ = add_parent_or_loop_num_clause (num_workers_clause, NULL,
+ OMP_CLAUSE_NUM_WORKERS, clauses);
+ clauses
+ = add_parent_or_loop_num_clause (vector_length_clause, NULL,
+ OMP_CLAUSE_VECTOR_LENGTH, clauses);
+ }
+ else
+ gcc_unreachable ();
+
+ gimple *parallel_body_bind
+ = gimple_build_bind (NULL, stmts, make_node (BLOCK));
+ gimple *parallel_region
+ = gimple_build_omp_target (parallel_body_bind, region_code, clauses);
+ gimple_set_location (parallel_region, gimple_location (omp_for));
+
+ return parallel_region;
+}
+
+/* Eliminate any binds directly inside BIND by adding their statements to
+ BIND (i.e., modifying it in place), excluding binds that hold only an
+ OMP_FOR loop and associated setup/cleanup code. Recurse into binds but
+ not other statements. Return a chain of the local variables of eliminated
+ binds, i.e., the local variables found in nested binds. If
+ INCLUDE_TOPLEVEL_VARS is true, this also includes the variables belonging
+ to BIND itself. */
+
+static tree
+flatten_binds (gbind *bind, bool include_toplevel_vars = false)
+{
+ tree vars = NULL, last_var = NULL;
+
+ if (include_toplevel_vars)
+ {
+ vars = gimple_bind_vars (bind);
+ last_var = vars;
+ }
+
+ gimple_seq new_body = NULL;
+ gimple_seq body_sequence = gimple_bind_body (bind);
+ gimple_stmt_iterator gsi, gsi_n;
+ for (gsi = gsi_start (body_sequence); !gsi_end_p (gsi); gsi = gsi_n)
+ {
+ /* Advance the iterator here because otherwise it would be invalidated
+ by moving statements below. */
+ gsi_n = gsi;
+ gsi_next (&gsi_n);
+
+ gimple *stmt = gsi_stmt (gsi);
+ /* Flatten bind statements, except the ones that contain only an
+ OpenACC for loop. */
+ if (gimple_code (stmt) == GIMPLE_BIND
+ && !top_level_omp_for_in_stmt (stmt))
+ {
+ gbind *inner_bind = as_a <gbind *> (stmt);
+ /* Flatten recursively, and collect all variables. */
+ tree inner_vars = flatten_binds (inner_bind, true);
+ gimple_seq inner_sequence = gimple_bind_body (inner_bind);
+ if (flag_checking)
+ {
+ for (gimple_stmt_iterator inner_gsi = gsi_start (inner_sequence);
+ !gsi_end_p (inner_gsi);
+ gsi_next (&inner_gsi))
+ {
+ gimple *inner_stmt = gsi_stmt (inner_gsi);
+ gcc_assert (gimple_code (inner_stmt) != GIMPLE_BIND
+ || top_level_omp_for_in_stmt (inner_stmt));
+ }
+ }
+ gimple_seq_add_seq (&new_body, inner_sequence);
+ /* Find the last variable; we will append others to it. */
+ while (last_var != NULL && TREE_CHAIN (last_var) != NULL)
+ last_var = TREE_CHAIN (last_var);
+ if (last_var != NULL)
+ {
+ TREE_CHAIN (last_var) = inner_vars;
+ last_var = inner_vars;
+ }
+ else
+ {
+ vars = inner_vars;
+ last_var = vars;
+ }
+ }
+ else
+ gimple_seq_add_stmt (&new_body, stmt);
+ }
+
+ /* Put the possibly transformed body back into the bind. */
+ gimple_bind_set_body (bind, new_body);
+ return vars;
+}
+
+/* Helper function for places where we construct data regions. Wraps the BODY
+ inside a try-finally construct at LOC that calls __builtin_GOACC_data_end
+ in its cleanup block. Returns this try statement. */
+
+static gimple *
+make_data_region_try_statement (location_t loc, gimple *body)
+{
+ tree data_end_fn = builtin_decl_explicit (BUILT_IN_GOACC_DATA_END);
+ gimple *call = gimple_build_call (data_end_fn, 0);
+ gimple_seq cleanup = NULL;
+ gimple_seq_add_stmt (&cleanup, call);
+ gimple *try_stmt = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
+ gimple_set_location (body, loc);
+ return try_stmt;
+}
+
+/* If INNER_BIND_VARS holds variables, build an OpenACC data region with
+ location LOC containing BODY and having 'create (var)' clauses for each
+ variable. If INNER_CLEANUP is present, add a try-finally statement with
+ this cleanup code in the finally block. Return the new data region, or
+ the original BODY if no data region was needed. */
+
+static gimple *
+maybe_build_inner_data_region (location_t loc, gimple *body,
+ tree inner_bind_vars, gimple *inner_cleanup)
+{
+ /* Is this an instantiation of a template? (In this case, we don't care what
+ the generic decl is - just whether the function decl has one.) */
+ bool generic_inst_p
+ = (lang_hooks.decls.get_generic_function_decl (current_function_decl)
+ != NULL);
+
+ /* Build data 'create (var)' clauses for these local variables.
+ Below we will add these to a data region enclosing the entire body
+ of the decomposed kernels region. */
+ tree prev_mapped_var = NULL, next = NULL, artificial_vars = NULL,
+ inner_data_clauses = NULL;
+ for (tree v = inner_bind_vars; v; v = next)
+ {
+ next = TREE_CHAIN (v);
+ if (DECL_ARTIFICIAL (v)
+ || TREE_CODE (v) == CONST_DECL
+ || generic_inst_p)
+ {
+ /* If this is an artificial temporary, it need not be mapped. We
+ move its declaration into the bind inside the data region.
+ Also avoid mapping variables if we are inside a template
+ instantiation; the code does not contain all the copies to
+ temporaries that would make this legal. */
+ TREE_CHAIN (v) = artificial_vars;
+ artificial_vars = v;
+ if (prev_mapped_var != NULL)
+ TREE_CHAIN (prev_mapped_var) = next;
+ else
+ inner_bind_vars = next;
+ }
+ else
+ {
+ /* Otherwise, build the map clause. */
+ tree new_clause = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (new_clause, GOMP_MAP_ALLOC);
+ OMP_CLAUSE_DECL (new_clause) = v;
+ OMP_CLAUSE_SIZE (new_clause) = DECL_SIZE_UNIT (v);
+ OMP_CLAUSE_CHAIN (new_clause) = inner_data_clauses;
+ inner_data_clauses = new_clause;
+
+ prev_mapped_var = v;
+ }
+ }
+
+ if (artificial_vars)
+ body = gimple_build_bind (artificial_vars, body, make_node (BLOCK));
+
+ /* If we determined above that there are variables that need to be created
+ on the device, construct a data region for them and wrap the body
+ inside that. */
+ if (inner_data_clauses != NULL)
+ {
+ gcc_assert (inner_bind_vars != NULL);
+ gimple *inner_data_region
+ = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DATA_KERNELS,
+ inner_data_clauses);
+ gimple_set_location (inner_data_region, loc);
+ /* Make sure __builtin_GOACC_data_end is called at the end. */
+ gimple *try_stmt = make_data_region_try_statement (loc, body);
+ gimple_omp_set_body (inner_data_region, try_stmt);
+ gimple *bind_body;
+ if (inner_cleanup != NULL)
+ /* Clobber all the inner variables that need to be clobbered. */
+ bind_body = gimple_build_try (inner_data_region, inner_cleanup,
+ GIMPLE_TRY_FINALLY);
+ else
+ bind_body = inner_data_region;
+ body = gimple_build_bind (inner_bind_vars, bind_body, make_node (BLOCK));
+ }
+
+ return body;
+}
+
+/* Helper function of decompose_kernels_region_body. The statements in
+ REGION_BODY are expected to be decomposed parts; add an 'async' clause to
+ each. Also add a 'wait' directive at the end of the sequence. */
+
+static void
+add_async_clauses_and_wait (location_t loc, gimple_seq *region_body)
+{
+ tree default_async_queue
+ = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
+ for (gimple_stmt_iterator gsi = gsi_start (*region_body);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ tree target_clauses = gimple_omp_target_clauses (stmt);
+ tree new_async_clause = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
+ OMP_CLAUSE_OPERAND (new_async_clause, 0) = default_async_queue;
+ OMP_CLAUSE_CHAIN (new_async_clause) = target_clauses;
+ target_clauses = new_async_clause;
+ gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt),
+ target_clauses);
+ }
+ /* A '#pragma acc wait' is just a call 'GOACC_wait (acc_async_sync, 0)'. */
+ tree wait_fn = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
+ tree sync_arg = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC);
+ gimple *wait_call = gimple_build_call (wait_fn, 2,
+ sync_arg, integer_zero_node);
+ gimple_set_location (wait_call, loc);
+ gimple_seq_add_stmt (region_body, wait_call);
+}
+
+/* Auxiliary analysis of the body of a kernels region, to determine for each
+ OpenACC loop whether it is control-dependent (i.e., not necessarily
+ executed every time the kernels region is entered) or not.
+ We say that a loop is control-dependent if there is some cond, switch, or
+ goto statement that jumps over it, forwards or backwards. For example,
+ if the loop is controlled by an if statement, then a jump to the true
+ block, the false block, or from one of those blocks to the control flow
+ join point will necessarily jump over the loop.
+ This analysis implements an ad-hoc union-find data structure classifying
+ statements into "control-flow regions" as follows: Most statements are in
+ the same region as their predecessor, except that each OpenACC loop is in
+ a region of its own, and each OpenACC loop's successor starts a new
+ region. We then unite the regions of any statements linked by jumps,
+ placing any cond, switch, or goto statement in the same region as its
+ target label(s).
+ In the end, control dependence of OpenACC loops can be determined by
+ comparing their immediate predecessor and successor statements' regions.
+ A jump crosses the loop if and only if the predecessor and successor are
+ in the same region. (If there is no predecessor or successor, the loop
+ is executed unconditionally.)
+ The methods in this class identify statements by their index in the
+ kernels region's body. */
+
+class control_flow_regions
+{
+ public:
+ /* Initialize an instance and pre-compute the control-flow region
+ information for the statement sequence SEQ. */
+ control_flow_regions (gimple_seq seq);
+
+ /* Return true if the statement with the given index IDX in the analyzed
+ statement sequence is an unconditionally executed OpenACC loop. */
+ bool is_unconditional_oacc_for_loop (size_t idx);
+
+ private:
+ /* Find the region representative for the statement identified by index
+ STMT_IDX. */
+ size_t find_rep (size_t stmt_idx);
+
+ /* Union the regions containing the statements represented by
+ representatives A and B. */
+ void union_reps (size_t a, size_t b);
+
+ /* Helper for the constructor. Performs the actual computation of the
+ control-flow regions in the statement sequence SEQ. */
+ void compute_regions (gimple_seq seq);
+
+ /* The mapping from statement indices to region representatives. */
+ vec <size_t> representatives;
+
+ /* A cache mapping statement indices to a flag indicating whether the
+ statement is a top level OpenACC for loop. */
+ vec <bool> omp_for_loops;
+};
+
+control_flow_regions::control_flow_regions (gimple_seq seq)
+{
+ representatives.create (1);
+ omp_for_loops.create (1);
+ compute_regions (seq);
+}
+
+bool
+control_flow_regions::is_unconditional_oacc_for_loop (size_t idx)
+{
+ if (idx == 0 || idx == representatives.length () - 1)
+ /* The first or last statement in the kernels region. This means that
+ there is no room before or after it for a jump or a label. Thus
+ there cannot be a jump across it, so it is unconditional. */
+ return true;
+ /* Otherwise, the loop is unconditional if the statements before and after
+ it are in different control flow regions. Scan forward and backward,
+ skipping over neighboring OpenACC for loops, to find these preceding
+ statements. */
+ size_t prev_index = idx - 1;
+ while (prev_index > 0 && omp_for_loops [prev_index] == true)
+ prev_index--;
+ /* If all preceding statements are also OpenACC loops, all of these are
+ unconditional. */
+ if (prev_index == 0)
+ return true;
+ size_t succ_index = idx + 1;
+ while (succ_index < omp_for_loops.length ()
+ && omp_for_loops [succ_index] == true)
+ succ_index++;
+ /* If all following statements are also OpenACC loops, all of these are
+ unconditional. */
+ if (succ_index == omp_for_loops.length ())
+ return true;
+ return (find_rep (prev_index) != find_rep (succ_index));
+}
+
+size_t
+control_flow_regions::find_rep (size_t stmt_idx)
+{
+ size_t rep = stmt_idx, aux = stmt_idx;
+ /* Find the root representative of this statement. */
+ while (representatives[rep] != rep)
+ rep = representatives[rep];
+ /* Compress the path from the original statement to the representative. */
+ while (representatives[aux] != rep)
+ {
+ size_t tmp = representatives[aux];
+ representatives[aux] = rep;
+ aux = tmp;
+ }
+ return rep;
+}
+
+void
+control_flow_regions::union_reps (size_t a, size_t b)
+{
+ a = find_rep (a);
+ b = find_rep (b);
+ representatives[b] = a;
+}
+
+void
+control_flow_regions::compute_regions (gimple_seq seq)
+{
+ hash_map <gimple *, size_t> control_flow_reps;
+ hash_map <tree, size_t> label_reps;
+ size_t current_region = 0, idx = 0;
+
+ /* In a first pass, assign an initial region to each statement. Except in
+ the case of OpenACC loops, each statement simply gets the same region
+ representative as its predecessor. */
+ for (gimple_stmt_iterator gsi = gsi_start (seq);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ gimple *omp_for = top_level_omp_for_in_stmt (stmt);
+ omp_for_loops.safe_push (omp_for != NULL);
+ if (omp_for != NULL)
+ {
+ /* Assign a new region to this loop and to its successor. */
+ current_region = idx;
+ representatives.safe_push (current_region);
+ current_region++;
+ }
+ else
+ {
+ representatives.safe_push (current_region);
+ /* Remember any jumps and labels for the second pass below. */
+ if (gimple_code (stmt) == GIMPLE_COND
+ || gimple_code (stmt) == GIMPLE_SWITCH
+ || gimple_code (stmt) == GIMPLE_GOTO)
+ control_flow_reps.put (stmt, current_region);
+ else if (gimple_code (stmt) == GIMPLE_LABEL)
+ label_reps.put (gimple_label_label (as_a <glabel *> (stmt)),
+ current_region);
+ }
+ idx++;
+ }
+ gcc_assert (representatives.length () == omp_for_loops.length ());
+
+ /* Revisit all the control flow statements and union the region of each
+ cond, switch, or goto statement with the target labels' regions. */
+ for (hash_map <gimple *, size_t>::iterator it = control_flow_reps.begin ();
+ it != control_flow_reps.end ();
+ ++it)
+ {
+ gimple *stmt = (*it).first;
+ size_t stmt_rep = (*it).second;
+ switch (gimple_code (stmt))
+ {
+ tree label;
+ unsigned int n;
+
+ case GIMPLE_COND:
+ label = gimple_cond_true_label (as_a <gcond *> (stmt));
+ union_reps (stmt_rep, *label_reps.get (label));
+ label = gimple_cond_false_label (as_a <gcond *> (stmt));
+ union_reps (stmt_rep, *label_reps.get (label));
+ break;
+
+ case GIMPLE_SWITCH:
+ n = gimple_switch_num_labels (as_a <gswitch *> (stmt));
+ for (unsigned int i = 0; i < n; i++)
+ {
+ tree switch_case
+ = gimple_switch_label (as_a <gswitch *> (stmt), i);
+ label = CASE_LABEL (switch_case);
+ union_reps (stmt_rep, *label_reps.get (label));
+ }
+ break;
+
+ case GIMPLE_GOTO:
+ label = gimple_goto_dest (stmt);
+ union_reps (stmt_rep, *label_reps.get (label));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+}
+
+/* Decompose the body of the KERNELS_REGION, which was originally annotated
+ with the KERNELS_CLAUSES, into a series of compute constructs. */
+
+static gimple *
+decompose_kernels_region_body (gimple *kernels_region, tree kernels_clauses)
+{
+ location_t loc = gimple_location (kernels_region);
+
+ /* The kernels clauses will be propagated to the child clauses unmodified,
+ except that the 'num_gangs', 'num_workers', and 'vector_length' clauses
+ will only be added to loop regions. The other regions are "gang-single"
+ and get an explicit 'num_gangs (1)' clause. So separate out the
+ 'num_gangs', 'num_workers', and 'vector_length' clauses here.
+ Also check for the presence of an 'async' clause but do not remove it from
+ the 'kernels' clauses. */
+ tree num_gangs_clause = NULL, num_workers_clause = NULL,
+ vector_length_clause = NULL;
+ tree async_clause = NULL;
+ tree prev_clause = NULL, next_clause = NULL;
+ tree parallel_clauses = kernels_clauses;
+ for (tree c = parallel_clauses; c; c = next_clause)
+ {
+ /* Preserve this here, as we might NULL it later. */
+ next_clause = OMP_CLAUSE_CHAIN (c);
+
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
+ {
+ /* Cut this clause out of the chain. */
+ if (prev_clause != NULL)
+ OMP_CLAUSE_CHAIN (prev_clause) = OMP_CLAUSE_CHAIN (c);
+ else
+ kernels_clauses = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = NULL;
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_NUM_GANGS:
+ num_gangs_clause = c;
+ break;
+ case OMP_CLAUSE_NUM_WORKERS:
+ num_workers_clause = c;
+ break;
+ case OMP_CLAUSE_VECTOR_LENGTH:
+ vector_length_clause = c;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ prev_clause = c;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ASYNC)
+ async_clause = c;
+ }
+
+ gimple *kernels_body = gimple_omp_body (kernels_region);
+ gbind *kernels_bind = as_a <gbind *> (kernels_body);
+
+ /* The body of the region may contain other nested binds declaring inner
+ local variables. Collapse all these binds into one to ensure that we
+ have a single sequence of statements to iterate over; also, collect all
+ inner variables. */
+ tree inner_bind_vars = flatten_binds (kernels_bind);
+ gimple_seq body_sequence = gimple_bind_body (kernels_bind);
+
+ /* All these inner variables will get allocated on the device (below, by
+ calling maybe_build_inner_data_region). Here we create 'present'
+ clauses for them and add these clauses to the list of clauses to be
+ attached to each inner compute construct. */
+ tree present_clauses = kernels_clauses;
+ for (tree var = inner_bind_vars; var; var = TREE_CHAIN (var))
+ {
+ if (!DECL_ARTIFICIAL (var) && TREE_CODE (var) != CONST_DECL)
+ {
+ tree present_clause = build_omp_clause (loc, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (present_clause, GOMP_MAP_FORCE_PRESENT);
+ OMP_CLAUSE_DECL (present_clause) = var;
+ OMP_CLAUSE_SIZE (present_clause) = DECL_SIZE_UNIT (var);
+ OMP_CLAUSE_CHAIN (present_clause) = present_clauses;
+ present_clauses = present_clause;
+ }
+ }
+ kernels_clauses = present_clauses;
+
+ /* In addition to nested binds, the "real" body of the region may be
+ nested inside a try-finally block. Find its cleanup block, which
+ contains code to clobber the local variables that must be clobbered. */
+ gimple *inner_cleanup = NULL;
+ if (body_sequence != NULL && gimple_code (body_sequence) == GIMPLE_TRY)
+ {
+ if (gimple_seq_singleton_p (body_sequence))
+ {
+ /* The try statement is the only thing inside the bind. */
+ inner_cleanup = gimple_try_cleanup (body_sequence);
+ body_sequence = gimple_try_eval (body_sequence);
+ }
+ else
+ {
+ /* The bind's body starts with a try statement, but it is followed
+ by other things. */
+ gimple_stmt_iterator gsi = gsi_start (body_sequence);
+ gimple *try_stmt = gsi_stmt (gsi);
+ inner_cleanup = gimple_try_cleanup (try_stmt);
+ gimple *try_body = gimple_try_eval (try_stmt);
+
+ gsi_remove (&gsi, false);
+ /* Now gsi indicates the sequence of statements after the try
+ statement in the bind. Append the statement in the try body and
+ the trailing statements from gsi. */
+ gsi_insert_seq_before (&gsi, try_body, GSI_CONTINUE_LINKING);
+ body_sequence = gsi_stmt (gsi);
+ }
+ }
+
+ /* This sequence will collect all the top-level statements in the body of
+ the data region we are about to construct. */
+ gimple_seq region_body = NULL;
+ /* This sequence will collect consecutive statements to be put into a
+ gang-single region. */
+ gimple_seq gang_single_seq = NULL;
+ /* Flag recording whether the gang_single_seq only contains copies to
+ local variables. These may be loop setup code that should not be
+ separated from the loop. */
+ bool only_simple_assignments = true;
+
+ /* Precompute the control flow region information to determine whether an
+ OpenACC loop is executed conditionally or unconditionally. */
+ control_flow_regions cf_regions (body_sequence);
+
+ /* Iterate over the statements in the kernels region's body. */
+ size_t idx = 0;
+ gimple_stmt_iterator gsi, gsi_n;
+ for (gsi = gsi_start (body_sequence); !gsi_end_p (gsi); gsi = gsi_n, idx++)
+ {
+ /* Advance the iterator here because otherwise it would be invalidated
+ by moving statements below. */
+ gsi_n = gsi;
+ gsi_next (&gsi_n);
+
+ gimple *stmt = gsi_stmt (gsi);
+ gimple *omp_for = top_level_omp_for_in_stmt (stmt);
+ bool is_unconditional_oacc_for_loop = false;
+ if (omp_for != NULL)
+ is_unconditional_oacc_for_loop
+ = cf_regions.is_unconditional_oacc_for_loop (idx);
+ if (omp_for != NULL
+ && is_unconditional_oacc_for_loop)
+ {
+ /* This is an OMP for statement, put it into a separate region.
+ But first, construct a gang-single region containing any
+ complex sequential statements we may have seen. */
+ if (gang_single_seq != NULL && !only_simple_assignments)
+ {
+ gimple *single_region
+ = make_region_seq (loc, gang_single_seq,
+ num_gangs_clause,
+ num_workers_clause,
+ vector_length_clause,
+ kernels_clauses);
+ gimple_seq_add_stmt (&region_body, single_region);
+ }
+ else if (gang_single_seq != NULL && only_simple_assignments)
+ {
+ /* There is a sequence of sequential statements preceding this
+ loop, but they are all simple assignments. This is
+ probably setup code for the loop; in particular, Fortran DO
+ loops are preceded by code to copy the loop limit variable
+ to a temporary. Group this code together with the loop
+ itself. */
+ gimple_seq_add_stmt (&gang_single_seq, stmt);
+ stmt = gimple_build_bind (NULL, gang_single_seq,
+ make_node (BLOCK));
+ }
+ gang_single_seq = NULL;
+ only_simple_assignments = true;
+
+ gimple_seq parallel_seq = NULL;
+ gimple_seq_add_stmt (&parallel_seq, stmt);
+ gimple *parallel_region
+ = make_region_loop_nest (omp_for, parallel_seq,
+ num_gangs_clause,
+ num_workers_clause,
+ vector_length_clause,
+ kernels_clauses);
+ gimple_seq_add_stmt (&region_body, parallel_region);
+ }
+ else
+ {
+ if (omp_for != NULL)
+ {
+ gcc_checking_assert (!is_unconditional_oacc_for_loop);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, omp_for,
+ "unparallelized loop nest"
+ " in OpenACC %<kernels%> region:"
+ " it's executed conditionally\n");
+ }
+
+ /* This is not an unconditional OMP for statement, so it will be
+ put into a gang-single region. */
+ gimple_seq_add_stmt (&gang_single_seq, stmt);
+ /* Is this a simple assignment? We call it simple if it is an
+ assignment to an artificial local variable. This captures
+ Fortran loop setup code computing loop bounds and offsets. */
+ bool is_simple_assignment
+ = (gimple_code (stmt) == GIMPLE_ASSIGN
+ && TREE_CODE (gimple_assign_lhs (stmt)) == VAR_DECL
+ && DECL_ARTIFICIAL (gimple_assign_lhs (stmt)));
+ if (!is_simple_assignment)
+ only_simple_assignments = false;
+ }
+ }
+
+ /* If we did not emit a new region, and are not going to emit one now
+ (that is, the original region was empty), prepare to emit a dummy so as
+ to preserve the original construct, which other processing (at least
+ test cases) depend on. */
+ if (region_body == NULL && gang_single_seq == NULL)
+ {
+ gimple *stmt = gimple_build_nop ();
+ gimple_set_location (stmt, loc);
+ gimple_seq_add_stmt (&gang_single_seq, stmt);
+ }
+
+ /* Gather up any remaining gang-single statements. */
+ if (gang_single_seq != NULL)
+ {
+ gimple *single_region
+ = make_region_seq (loc, gang_single_seq,
+ num_gangs_clause,
+ num_workers_clause,
+ vector_length_clause,
+ kernels_clauses);
+ gimple_seq_add_stmt (&region_body, single_region);
+ }
+
+ /* We want to launch these kernels asynchronously. If the original
+ kernels region had an async clause, this is done automatically because
+ that async clause was copied to the individual regions we created.
+ Otherwise, add an async clause to each newly created region, as well as
+ a wait directive at the end. */
+ if (async_clause == NULL)
+ add_async_clauses_and_wait (loc, &region_body);
+
+ tree kernels_locals = gimple_bind_vars (as_a <gbind *> (kernels_body));
+ gimple *body = gimple_build_bind (kernels_locals, region_body,
+ make_node (BLOCK));
+
+ /* If we found variables declared in nested scopes, build a data region to
+ map them to the device. */
+ body = maybe_build_inner_data_region (loc, body, inner_bind_vars,
+ inner_cleanup);
+
+ return body;
+}
+
+/* Decompose one OpenACC 'kernels' construct into an OpenACC 'data' construct
+ containing the original OpenACC 'kernels' construct's region cut up into a
+ sequence of compute constructs. */
+
+static gimple *
+omp_oacc_kernels_decompose_1 (gimple *kernels_stmt)
+{
+ gcc_checking_assert (gimple_omp_target_kind (kernels_stmt)
+ == GF_OMP_TARGET_KIND_OACC_KERNELS);
+ location_t loc = gimple_location (kernels_stmt);
+
+ /* Collect the data clauses of the OpenACC 'kernels' directive and create a
+ new OpenACC 'data' construct with those clauses. */
+ tree kernels_clauses = gimple_omp_target_clauses (kernels_stmt);
+ tree data_clauses = NULL;
+ for (tree c = kernels_clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ /* Certain clauses are copied to the enclosing OpenACC 'data'. Other
+ clauses remain on the OpenACC 'kernels'. */
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
+ {
+ tree decl = OMP_CLAUSE_DECL (c);
+ HOST_WIDE_INT map_kind = OMP_CLAUSE_MAP_KIND (c);
+ switch (map_kind)
+ {
+ default:
+ if (map_kind == GOMP_MAP_ALLOC
+ && integer_zerop (OMP_CLAUSE_SIZE (c)))
+ /* ??? This is an alloc clause for mapping a pointer whose
+ target is already mapped. We leave these on the inner
+ compute constructs because moving them to the outer data
+ region causes runtime errors. */
+ break;
+
+ /* For non-artificial variables, and for non-declaration
+ expressions like A[0:n], copy the clause to the data
+ region. */
+ if ((DECL_P (decl) && !DECL_ARTIFICIAL (decl))
+ || !DECL_P (decl))
+ {
+ tree new_clause = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (new_clause, map_kind);
+ /* This must be unshared here to avoid "incorrect sharing
+ of tree nodes" errors from verify_gimple. */
+ OMP_CLAUSE_DECL (new_clause) = unshare_expr (decl);
+ OMP_CLAUSE_SIZE (new_clause) = OMP_CLAUSE_SIZE (c);
+ OMP_CLAUSE_CHAIN (new_clause) = data_clauses;
+ data_clauses = new_clause;
+
+ /* Now that this data is mapped, turn the data clause on the
+ inner OpenACC 'kernels' into a 'present' clause. */
+ OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
+ }
+ break;
+
+ case GOMP_MAP_POINTER:
+ case GOMP_MAP_TO_PSET:
+ case GOMP_MAP_FORCE_TOFROM:
+ case GOMP_MAP_FIRSTPRIVATE_POINTER:
+ case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
+ /* ??? Copying these map kinds leads to internal compiler
+ errors in later passes. */
+ break;
+ }
+ }
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
+ {
+ /* If there is an 'if' clause, it must be duplicated to the
+ enclosing data region. Temporarily remove the if clause's
+ chain to avoid copying it. */
+ tree saved_chain = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = NULL;
+ tree new_if_clause = unshare_expr (c);
+ OMP_CLAUSE_CHAIN (c) = saved_chain;
+ OMP_CLAUSE_CHAIN (new_if_clause) = data_clauses;
+ data_clauses = new_if_clause;
+ }
+ }
+ /* Restore the original order of the clauses. */
+ data_clauses = nreverse (data_clauses);
+
+ gimple *data_region
+ = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DATA_KERNELS,
+ data_clauses);
+ gimple_set_location (data_region, loc);
+
+ /* Transform the body of the kernels region into a sequence of compute
+ constructs. */
+ gimple *body = decompose_kernels_region_body (kernels_stmt,
+ kernels_clauses);
+
+ /* Put the transformed pieces together. The entire body of the region is
+ wrapped in a try-finally statement that calls __builtin_GOACC_data_end
+ for cleanup. */
+ gimple *try_stmt = make_data_region_try_statement (loc, body);
+ gimple_omp_set_body (data_region, try_stmt);
+
+ return data_region;
+}
+
+
+/* Decompose OpenACC 'kernels' constructs in the current function. */
+
+static tree
+omp_oacc_kernels_decompose_callback_stmt (gimple_stmt_iterator *gsi_p,
+ bool *handled_ops_p,
+ struct walk_stmt_info *)
+{
+ gimple *stmt = gsi_stmt (*gsi_p);
+
+ if ((gimple_code (stmt) == GIMPLE_OMP_TARGET)
+ && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
+ {
+ gimple *stmt_new = omp_oacc_kernels_decompose_1 (stmt);
+ gsi_replace (gsi_p, stmt_new, false);
+ *handled_ops_p = true;
+ }
+ else
+ *handled_ops_p = false;
+
+ return NULL;
+}
+
+static unsigned int
+omp_oacc_kernels_decompose (void)
+{
+ gimple_seq body = gimple_body (current_function_decl);
+
+ struct walk_stmt_info wi;
+ memset (&wi, 0, sizeof (wi));
+ walk_gimple_seq_mod (&body, omp_oacc_kernels_decompose_callback_stmt, NULL,
+ &wi);
+
+ gimple_set_body (current_function_decl, body);
+
+ return 0;
+}
+
+
+namespace {
+
+const pass_data pass_data_omp_oacc_kernels_decompose =
+{
+ GIMPLE_PASS, /* type */
+ "omp_oacc_kernels_decompose", /* name */
+ OPTGROUP_OMP, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_gimple_any, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_omp_oacc_kernels_decompose : public gimple_opt_pass
+{
+public:
+ pass_omp_oacc_kernels_decompose (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_omp_oacc_kernels_decompose, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ return (flag_openacc
+ && flag_openacc_kernels == OPENACC_KERNELS_DECOMPOSE);
+ }
+ virtual unsigned int execute (function *)
+ {
+ return omp_oacc_kernels_decompose ();
+ }
+
+}; // class pass_omp_oacc_kernels_decompose
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_omp_oacc_kernels_decompose (gcc::context *ctxt)
+{
+ return new pass_omp_oacc_kernels_decompose (ctxt);
+}
diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c
index 3e9c31d..15b735b 100644
--- a/gcc/omp-offload.c
+++ b/gcc/omp-offload.c
@@ -196,7 +196,26 @@ omp_declare_target_var_p (tree decl)
static tree
omp_discover_declare_target_tgt_fn_r (tree *tp, int *walk_subtrees, void *data)
{
- if (TREE_CODE (*tp) == FUNCTION_DECL)
+ if (TREE_CODE (*tp) == CALL_EXPR
+ && CALL_EXPR_FN (*tp)
+ && TREE_CODE (CALL_EXPR_FN (*tp)) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (*tp), 0)) == FUNCTION_DECL
+ && lookup_attribute ("omp declare variant base",
+ DECL_ATTRIBUTES (TREE_OPERAND (CALL_EXPR_FN (*tp),
+ 0))))
+ {
+ tree fn = TREE_OPERAND (CALL_EXPR_FN (*tp), 0);
+ for (tree attr = DECL_ATTRIBUTES (fn); attr; attr = TREE_CHAIN (attr))
+ {
+ attr = lookup_attribute ("omp declare variant base", attr);
+ if (attr == NULL_TREE)
+ break;
+ tree purpose = TREE_PURPOSE (TREE_VALUE (attr));
+ if (TREE_CODE (purpose) == FUNCTION_DECL)
+ omp_discover_declare_target_tgt_fn_r (&purpose, walk_subtrees, data);
+ }
+ }
+ else if (TREE_CODE (*tp) == FUNCTION_DECL)
{
tree decl = *tp;
tree id = get_identifier ("omp declare target");
@@ -237,7 +256,7 @@ omp_discover_declare_target_tgt_fn_r (tree *tp, int *walk_subtrees, void *data)
}
if (omp_declare_target_fn_p (decl)
|| lookup_attribute ("omp declare target host",
- DECL_ATTRIBUTES (decl)))
+ DECL_ATTRIBUTES (decl)))
return NULL_TREE;
if (!DECL_EXTERNAL (decl) && DECL_SAVED_TREE (decl))
@@ -296,7 +315,7 @@ omp_discover_declare_target_var_r (tree *tp, int *walk_subtrees, void *data)
DECL_ATTRIBUTES (*tp)
= remove_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp));
}
- if (TREE_STATIC (*tp) && DECL_INITIAL (*tp))
+ if (TREE_STATIC (*tp) && lang_hooks.decls.omp_get_decl_init (*tp))
((vec<tree> *) data)->safe_push (*tp);
DECL_ATTRIBUTES (*tp) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (*tp));
symtab_node *node = symtab_node::get (*tp);
@@ -342,14 +361,15 @@ omp_discover_implicit_declare_target (void)
&& DECL_STRUCT_FUNCTION (cgn->decl)->has_omp_target)
worklist.safe_push (cgn->decl);
}
- FOR_EACH_STATIC_INITIALIZER (vnode)
- if (omp_declare_target_var_p (vnode->decl))
+ FOR_EACH_VARIABLE (vnode)
+ if (lang_hooks.decls.omp_get_decl_init (vnode->decl)
+ && omp_declare_target_var_p (vnode->decl))
worklist.safe_push (vnode->decl);
while (!worklist.is_empty ())
{
tree decl = worklist.pop ();
if (VAR_P (decl))
- walk_tree_without_duplicates (&DECL_INITIAL (decl),
+ walk_tree_without_duplicates (lang_hooks.decls.omp_get_decl_init (decl),
omp_discover_declare_target_var_r,
&worklist);
else if (omp_declare_target_fn_p (decl))
@@ -361,6 +381,8 @@ omp_discover_implicit_declare_target (void)
omp_discover_declare_target_fn_r,
&worklist);
}
+
+ lang_hooks.decls.omp_finish_decl_inits ();
}
@@ -1743,12 +1765,59 @@ execute_oacc_device_lower ()
flag_openacc_dims = (char *)&flag_openacc_dims;
}
+ bool is_oacc_parallel
+ = (lookup_attribute ("oacc parallel",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL);
bool is_oacc_kernels
= (lookup_attribute ("oacc kernels",
DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ bool is_oacc_serial
+ = (lookup_attribute ("oacc serial",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ bool is_oacc_parallel_kernels_parallelized
+ = (lookup_attribute ("oacc parallel_kernels_parallelized",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ bool is_oacc_parallel_kernels_gang_single
+ = (lookup_attribute ("oacc parallel_kernels_gang_single",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ int fn_level = oacc_fn_attrib_level (attrs);
+ bool is_oacc_routine = (fn_level >= 0);
+ gcc_checking_assert (is_oacc_parallel
+ + is_oacc_kernels
+ + is_oacc_serial
+ + is_oacc_parallel_kernels_parallelized
+ + is_oacc_parallel_kernels_gang_single
+ + is_oacc_routine
+ == 1);
+
bool is_oacc_kernels_parallelized
= (lookup_attribute ("oacc kernels parallelized",
DECL_ATTRIBUTES (current_function_decl)) != NULL);
+ if (is_oacc_kernels_parallelized)
+ gcc_checking_assert (is_oacc_kernels);
+
+ if (dump_file)
+ {
+ if (is_oacc_parallel)
+ fprintf (dump_file, "Function is OpenACC parallel offload\n");
+ else if (is_oacc_kernels)
+ fprintf (dump_file, "Function is %s OpenACC kernels offload\n",
+ (is_oacc_kernels_parallelized
+ ? "parallelized" : "unparallelized"));
+ else if (is_oacc_serial)
+ fprintf (dump_file, "Function is OpenACC serial offload\n");
+ else if (is_oacc_parallel_kernels_parallelized)
+ fprintf (dump_file, "Function is %s OpenACC kernels offload\n",
+ "parallel_kernels_parallelized");
+ else if (is_oacc_parallel_kernels_gang_single)
+ fprintf (dump_file, "Function is %s OpenACC kernels offload\n",
+ "parallel_kernels_gang_single");
+ else if (is_oacc_routine)
+ fprintf (dump_file, "Function is OpenACC routine level %d\n",
+ fn_level);
+ else
+ gcc_unreachable ();
+ }
/* Unparallelized OpenACC kernels constructs must get launched as 1 x 1 x 1
kernels, so remove the parallelism dimensions function attributes
@@ -1761,22 +1830,10 @@ execute_oacc_device_lower ()
/* Discover, partition and process the loops. */
oacc_loop *loops = oacc_loop_discovery ();
- int fn_level = oacc_fn_attrib_level (attrs);
-
- if (dump_file)
- {
- if (fn_level >= 0)
- fprintf (dump_file, "Function is OpenACC routine level %d\n",
- fn_level);
- else if (is_oacc_kernels)
- fprintf (dump_file, "Function is %s OpenACC kernels offload\n",
- (is_oacc_kernels_parallelized
- ? "parallelized" : "unparallelized"));
- else
- fprintf (dump_file, "Function is OpenACC parallel offload\n");
- }
- unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
+ unsigned outer_mask = 0;
+ if (is_oacc_routine)
+ outer_mask = GOMP_DIM_MASK (fn_level) - 1;
unsigned used_mask = oacc_loop_partition (loops, outer_mask);
/* OpenACC kernels constructs are special: they currently don't use the
generic oacc_loop infrastructure and attribute/dimension processing. */
@@ -1798,6 +1855,11 @@ execute_oacc_device_lower ()
fprintf (dump_file, "]\n");
}
+ /* Verify that for OpenACC 'kernels' decomposed "gang-single" parts we launch
+ a single gang only. */
+ if (is_oacc_parallel_kernels_gang_single)
+ gcc_checking_assert (dims[GOMP_DIM_GANG] == 1);
+
oacc_loop_process (loops);
if (dump_file)
{
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index 942fb97..cbd58c8 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -338,16 +338,18 @@ simd_clone_mangle (struct cgraph_node *node,
{
char vecsize_mangle = clone_info->vecsize_mangle;
char mask = clone_info->inbranch ? 'M' : 'N';
- unsigned int simdlen = clone_info->simdlen;
+ poly_uint64 simdlen = clone_info->simdlen;
unsigned int n;
pretty_printer pp;
- gcc_assert (vecsize_mangle && simdlen);
+ gcc_assert (vecsize_mangle && maybe_ne (simdlen, 0U));
pp_string (&pp, "_ZGV");
pp_character (&pp, vecsize_mangle);
pp_character (&pp, mask);
- pp_decimal_int (&pp, simdlen);
+ /* For now, simdlen is always constant, while variable simdlen pp 'n'. */
+ unsigned int len = simdlen.to_constant ();
+ pp_decimal_int (&pp, (len));
for (n = 0; n < clone_info->nargs; ++n)
{
@@ -491,7 +493,7 @@ simd_clone_adjust_return_type (struct cgraph_node *node)
{
tree fndecl = node->decl;
tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
- unsigned int veclen;
+ poly_uint64 veclen;
tree t;
/* Adjust the function return type. */
@@ -502,17 +504,18 @@ simd_clone_adjust_return_type (struct cgraph_node *node)
veclen = node->simdclone->vecsize_int;
else
veclen = node->simdclone->vecsize_float;
- veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (t));
- if (veclen > node->simdclone->simdlen)
+ veclen = exact_div (veclen, GET_MODE_BITSIZE (SCALAR_TYPE_MODE (t)));
+ if (multiple_p (veclen, node->simdclone->simdlen))
veclen = node->simdclone->simdlen;
if (POINTER_TYPE_P (t))
t = pointer_sized_int_node;
- if (veclen == node->simdclone->simdlen)
+ if (known_eq (veclen, node->simdclone->simdlen))
t = build_vector_type (t, node->simdclone->simdlen);
else
{
t = build_vector_type (t, veclen);
- t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
+ t = build_array_type_nelts (t, exact_div (node->simdclone->simdlen,
+ veclen));
}
TREE_TYPE (TREE_TYPE (fndecl)) = t;
if (!node->definition)
@@ -526,7 +529,7 @@ simd_clone_adjust_return_type (struct cgraph_node *node)
tree atype = build_array_type_nelts (orig_rettype,
node->simdclone->simdlen);
- if (veclen != node->simdclone->simdlen)
+ if (maybe_ne (veclen, node->simdclone->simdlen))
return build1 (VIEW_CONVERT_EXPR, atype, t);
/* Set up a SIMD array to use as the return value. */
@@ -546,7 +549,7 @@ simd_clone_adjust_return_type (struct cgraph_node *node)
SIMDLEN is the number of elements. */
static tree
-create_tmp_simd_array (const char *prefix, tree type, int simdlen)
+create_tmp_simd_array (const char *prefix, tree type, poly_uint64 simdlen)
{
tree atype = build_array_type_nelts (type, simdlen);
tree avar = create_tmp_var_raw (atype, prefix);
@@ -578,7 +581,8 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
struct cgraph_simd_clone *sc = node->simdclone;
vec<ipa_adjusted_param, va_gc> *new_params = NULL;
vec_safe_reserve (new_params, sc->nargs);
- unsigned i, j, veclen;
+ unsigned i, j, k;
+ poly_uint64 veclen;
for (i = 0; i < sc->nargs; ++i)
{
@@ -614,8 +618,9 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
veclen = sc->vecsize_int;
else
veclen = sc->vecsize_float;
- veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (parm_type));
- if (veclen > sc->simdlen)
+ veclen = exact_div (veclen,
+ GET_MODE_BITSIZE (SCALAR_TYPE_MODE (parm_type)));
+ if (multiple_p (veclen, sc->simdlen))
veclen = sc->simdlen;
adj.op = IPA_PARAM_OP_NEW;
adj.param_prefix_index = IPA_PARAM_PREFIX_SIMD;
@@ -624,10 +629,11 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
else
adj.type = build_vector_type (parm_type, veclen);
sc->args[i].vector_type = adj.type;
- for (j = veclen; j < sc->simdlen; j += veclen)
+ k = vector_unroll_factor (sc->simdlen, veclen);
+ for (j = 1; j < k; j++)
{
vec_safe_push (new_params, adj);
- if (j == veclen)
+ if (j == 1)
{
memset (&adj, 0, sizeof (adj));
adj.op = IPA_PARAM_OP_NEW;
@@ -663,8 +669,9 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
veclen = sc->vecsize_int;
else
veclen = sc->vecsize_float;
- veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type));
- if (veclen > sc->simdlen)
+ veclen = exact_div (veclen,
+ GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type)));
+ if (multiple_p (veclen, sc->simdlen))
veclen = sc->simdlen;
if (sc->mask_mode != VOIDmode)
adj.type
@@ -675,7 +682,8 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
adj.type = build_vector_type (base_type, veclen);
vec_safe_push (new_params, adj);
- for (j = veclen; j < sc->simdlen; j += veclen)
+ k = vector_unroll_factor (sc->simdlen, veclen);
+ for (j = 1; j < k; j++)
vec_safe_push (new_params, adj);
/* We have previously allocated one extra entry for the mask. Use
@@ -690,9 +698,9 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
if (sc->mask_mode == VOIDmode)
sc->args[i].simd_array
= create_tmp_simd_array ("mask", base_type, sc->simdlen);
- else if (veclen < sc->simdlen)
+ else if (k > 1)
sc->args[i].simd_array
- = create_tmp_simd_array ("mask", adj.type, sc->simdlen / veclen);
+ = create_tmp_simd_array ("mask", adj.type, k);
else
sc->args[i].simd_array = NULL_TREE;
}
@@ -783,7 +791,8 @@ simd_clone_init_simd_arrays (struct cgraph_node *node,
}
continue;
}
- if (simd_clone_subparts (TREE_TYPE (arg)) == node->simdclone->simdlen)
+ if (known_eq (simd_clone_subparts (TREE_TYPE (arg)),
+ node->simdclone->simdlen))
{
tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
tree ptr = build_fold_addr_expr (array);
@@ -795,8 +804,10 @@ simd_clone_init_simd_arrays (struct cgraph_node *node,
else
{
unsigned int simdlen = simd_clone_subparts (TREE_TYPE (arg));
+ unsigned int times = vector_unroll_factor (node->simdclone->simdlen,
+ simdlen);
tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
- for (k = 0; k < node->simdclone->simdlen; k += simdlen)
+ for (k = 0; k < times; k++)
{
tree ptr = build_fold_addr_expr (array);
int elemsize;
@@ -808,7 +819,7 @@ simd_clone_init_simd_arrays (struct cgraph_node *node,
tree elemtype = TREE_TYPE (TREE_TYPE (arg));
elemsize = GET_MODE_SIZE (SCALAR_TYPE_MODE (elemtype));
tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
- build_int_cst (ptype, k * elemsize));
+ build_int_cst (ptype, k * elemsize * simdlen));
t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
gimplify_and_add (t, &seq);
}
@@ -981,8 +992,9 @@ ipa_simd_modify_function_body (struct cgraph_node *node,
iter, NULL_TREE, NULL_TREE);
adjustments->register_replacement (&(*adjustments->m_adj_params)[j], r);
- if (simd_clone_subparts (vectype) < node->simdclone->simdlen)
- j += node->simdclone->simdlen / simd_clone_subparts (vectype) - 1;
+ if (multiple_p (node->simdclone->simdlen, simd_clone_subparts (vectype)))
+ j += vector_unroll_factor (node->simdclone->simdlen,
+ simd_clone_subparts (vectype)) - 1;
}
tree name;
@@ -1249,7 +1261,8 @@ simd_clone_adjust (struct cgraph_node *node)
below). */
loop = alloc_loop ();
cfun->has_force_vectorize_loops = true;
- loop->safelen = node->simdclone->simdlen;
+ /* For now, simlen is always constant. */
+ loop->safelen = node->simdclone->simdlen.to_constant ();
loop->force_vectorize = true;
loop->header = body_bb;
}
@@ -1275,7 +1288,8 @@ simd_clone_adjust (struct cgraph_node *node)
{
tree maskt = TREE_TYPE (mask_array);
int c = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (maskt)));
- c = node->simdclone->simdlen / (c + 1);
+ /* For now, c must be constant here. */
+ c = exact_div (node->simdclone->simdlen, c + 1).to_constant ();
int s = exact_log2 (c);
gcc_assert (s > 0);
c--;
@@ -1683,7 +1697,7 @@ expand_simd_clones (struct cgraph_node *node)
if (clone_info == NULL)
continue;
- int orig_simdlen = clone_info->simdlen;
+ poly_uint64 orig_simdlen = clone_info->simdlen;
tree base_type = simd_clone_compute_base_data_type (node, clone_info);
/* The target can return 0 (no simd clones should be created),
1 (just one ISA of simd clones should be created) or higher
diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
index b4952b8..0c489e0 100644
--- a/gcc/opt-functions.awk
+++ b/gcc/opt-functions.awk
@@ -166,9 +166,11 @@ function switch_bit_fields (flags)
uinteger_flag \
hwi_flag \
flag_init("ToLower", flags) \
- flag_init("Report", flags) \
byte_size_flag
+ if (flag_set_p("Report", flags))
+ print "#error Report option property is dropped"
+
sub(", $", "", result)
return result
}
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index badd30b..a8968f3 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -170,6 +170,22 @@ optab_for_tree_code (enum tree_code code, const_tree type,
return (TYPE_UNSIGNED (type)
? vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab);
+ case VEC_WIDEN_PLUS_LO_EXPR:
+ return (TYPE_UNSIGNED (type)
+ ? vec_widen_uaddl_lo_optab : vec_widen_saddl_lo_optab);
+
+ case VEC_WIDEN_PLUS_HI_EXPR:
+ return (TYPE_UNSIGNED (type)
+ ? vec_widen_uaddl_hi_optab : vec_widen_saddl_hi_optab);
+
+ case VEC_WIDEN_MINUS_LO_EXPR:
+ return (TYPE_UNSIGNED (type)
+ ? vec_widen_usubl_lo_optab : vec_widen_ssubl_lo_optab);
+
+ case VEC_WIDEN_MINUS_HI_EXPR:
+ return (TYPE_UNSIGNED (type)
+ ? vec_widen_usubl_hi_optab : vec_widen_ssubl_hi_optab);
+
case VEC_UNPACK_HI_EXPR:
return (TYPE_UNSIGNED (type)
? vec_unpacku_hi_optab : vec_unpacks_hi_optab);
@@ -321,6 +337,35 @@ supportable_convert_operation (enum tree_code code,
return false;
}
+/* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector comparison
+ for code CODE, comparing operands of type VALUE_TYPE and producing a result
+ of type MASK_TYPE. */
+
+static bool
+vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
+{
+ enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
+ if (rcode == UNKNOWN)
+ return false;
+
+ return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
+ TYPE_MODE (mask_type));
+}
+
+/* Return true iff vec_cmpeq_optab can handle a vector comparison for code
+ CODE, comparing operands of type VALUE_TYPE and producing a result of type
+ MASK_TYPE. */
+
+static bool
+vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
+{
+ if (code != EQ_EXPR && code != NE_EXPR)
+ return false;
+
+ return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
+ != CODE_FOR_nothing;
+}
+
/* Return TRUE if appropriate vector insn is available
for vector comparison expr with vector type VALUE_TYPE
and resulting mask with MASK_TYPE. */
@@ -328,14 +373,8 @@ supportable_convert_operation (enum tree_code code,
bool
expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
{
- if (get_vec_cmp_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type),
- TYPE_UNSIGNED (value_type)) != CODE_FOR_nothing)
- return true;
- if ((code == EQ_EXPR || code == NE_EXPR)
- && (get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
- != CODE_FOR_nothing))
- return true;
- return false;
+ return vec_cmp_icode_p (value_type, mask_type, code)
+ || vec_cmp_eq_icode_p (value_type, mask_type, code);
}
/* Return true iff vcond_optab/vcondu_optab can handle a vector
@@ -345,8 +384,12 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
static bool
vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
{
- return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
- TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
+ enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (cmp_op_type));
+ if (rcode == UNKNOWN)
+ return false;
+
+ return can_vcond_compare_p (rcode, TYPE_MODE (value_type),
+ TYPE_MODE (cmp_op_type));
}
/* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
@@ -377,8 +420,7 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
TYPE_MODE (cmp_op_type)) != CODE_FOR_nothing)
return true;
- if (maybe_ne (GET_MODE_SIZE (value_mode), GET_MODE_SIZE (cmp_op_mode))
- || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
+ if (maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
return false;
if (TREE_CODE_CLASS (code) != tcc_comparison)
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 8ad7f4b..0427063 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -28,8 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "predict.h"
#include "tm_p.h"
-#include "expmed.h"
#include "optabs.h"
+#include "expmed.h"
#include "emit-rtl.h"
#include "recog.h"
#include "diagnostic-core.h"
@@ -44,6 +44,8 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h"
#include "optabs-tree.h"
#include "libfuncs.h"
+#include "internal-fn.h"
+#include "langhooks.h"
static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
machine_mode *);
@@ -926,6 +928,291 @@ expand_doubleword_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
emit_move_insn (product_high, adjust);
return product;
}
+
+/* Subroutine of expand_binop. Optimize unsigned double-word OP0 % OP1 for
+ constant OP1. If for some bit in [BITS_PER_WORD / 2, BITS_PER_WORD] range
+ (prefer higher bits) ((1w << bit) % OP1) == 1, then the modulo can be
+ computed in word-mode as ((OP0 & (bit - 1)) + ((OP0 >> bit) & (bit - 1))
+ + (OP0 >> (2 * bit))) % OP1. Whether we need to sum 2, 3 or 4 values
+ depends on the bit value, if 2, then carry from the addition needs to be
+ added too, i.e. like:
+ sum += __builtin_add_overflow (low, high, &sum)
+
+ Optimize signed double-word OP0 % OP1 similarly, just apply some correction
+ factor to the sum before doing unsigned remainder, in the form of
+ sum += (((signed) OP0 >> (2 * BITS_PER_WORD - 1)) & const);
+ then perform unsigned
+ remainder = sum % OP1;
+ and finally
+ remainder += ((signed) OP0 >> (2 * BITS_PER_WORD - 1)) & (1 - OP1); */
+
+static rtx
+expand_doubleword_mod (machine_mode mode, rtx op0, rtx op1, bool unsignedp)
+{
+ if (INTVAL (op1) <= 1 || (INTVAL (op1) & 1) == 0)
+ return NULL_RTX;
+
+ rtx_insn *last = get_last_insn ();
+ for (int bit = BITS_PER_WORD; bit >= BITS_PER_WORD / 2; bit--)
+ {
+ wide_int w = wi::shifted_mask (bit, 1, false, 2 * BITS_PER_WORD);
+ if (wi::ne_p (wi::umod_trunc (w, INTVAL (op1)), 1))
+ continue;
+ rtx sum = NULL_RTX, mask = NULL_RTX;
+ if (bit == BITS_PER_WORD)
+ {
+ /* For signed modulo we need to add correction to the sum
+ and that might again overflow. */
+ if (!unsignedp)
+ continue;
+ if (optab_handler (uaddv4_optab, word_mode) == CODE_FOR_nothing)
+ continue;
+ tree wtype = lang_hooks.types.type_for_mode (word_mode, 1);
+ if (wtype == NULL_TREE)
+ continue;
+ tree ctype = build_complex_type (wtype);
+ if (TYPE_MODE (ctype) != GET_MODE_COMPLEX_MODE (word_mode))
+ continue;
+ machine_mode cmode = TYPE_MODE (ctype);
+ rtx op00 = operand_subword_force (op0, 0, mode);
+ rtx op01 = operand_subword_force (op0, 1, mode);
+ rtx cres = gen_rtx_CONCAT (cmode, gen_reg_rtx (word_mode),
+ gen_reg_rtx (word_mode));
+ tree lhs = make_tree (ctype, cres);
+ tree arg0 = make_tree (wtype, op00);
+ tree arg1 = make_tree (wtype, op01);
+ expand_addsub_overflow (UNKNOWN_LOCATION, PLUS_EXPR, lhs, arg0,
+ arg1, true, true, true, false, NULL);
+ sum = expand_simple_binop (word_mode, PLUS, XEXP (cres, 0),
+ XEXP (cres, 1), NULL_RTX, 1,
+ OPTAB_DIRECT);
+ if (sum == NULL_RTX)
+ return NULL_RTX;
+ }
+ else
+ {
+ /* Code below uses GEN_INT, so we need the masks to be representable
+ in HOST_WIDE_INTs. */
+ if (bit >= HOST_BITS_PER_WIDE_INT)
+ continue;
+ /* If op0 is e.g. -1 or -2 unsigned, then the 2 additions might
+ overflow. Consider 64-bit -1ULL for word size 32, if we add
+ 0x7fffffffU + 0x7fffffffU + 3U, it wraps around to 1. */
+ if (bit == BITS_PER_WORD - 1)
+ continue;
+
+ int count = (2 * BITS_PER_WORD + bit - 1) / bit;
+ rtx sum_corr = NULL_RTX;
+
+ if (!unsignedp)
+ {
+ /* For signed modulo, compute it as unsigned modulo of
+ sum with a correction added to it if OP0 is negative,
+ such that the result can be computed as unsigned
+ remainder + ((OP1 >> (2 * BITS_PER_WORD - 1)) & (1 - OP1). */
+ w = wi::min_value (2 * BITS_PER_WORD, SIGNED);
+ wide_int wmod1 = wi::umod_trunc (w, INTVAL (op1));
+ wide_int wmod2 = wi::smod_trunc (w, INTVAL (op1));
+ /* wmod2 == -wmod1. */
+ wmod2 = wmod2 + (INTVAL (op1) - 1);
+ if (wi::ne_p (wmod1, wmod2))
+ {
+ wide_int wcorr = wmod2 - wmod1;
+ if (wi::neg_p (w))
+ wcorr = wcorr + INTVAL (op1);
+ /* Now verify if the count sums can't overflow, and punt
+ if they could. */
+ w = wi::mask (bit, false, 2 * BITS_PER_WORD);
+ w = w * (count - 1);
+ w = w + wi::mask (2 * BITS_PER_WORD - (count - 1) * bit,
+ false, 2 * BITS_PER_WORD);
+ w = w + wcorr;
+ w = wi::lrshift (w, BITS_PER_WORD);
+ if (wi::ne_p (w, 0))
+ continue;
+
+ mask = operand_subword_force (op0, WORDS_BIG_ENDIAN ? 0 : 1,
+ mode);
+ mask = expand_simple_binop (word_mode, ASHIFTRT, mask,
+ GEN_INT (BITS_PER_WORD - 1),
+ NULL_RTX, 0, OPTAB_DIRECT);
+ if (mask == NULL_RTX)
+ return NULL_RTX;
+ sum_corr = immed_wide_int_const (wcorr, word_mode);
+ sum_corr = expand_simple_binop (word_mode, AND, mask,
+ sum_corr, NULL_RTX, 1,
+ OPTAB_DIRECT);
+ if (sum_corr == NULL_RTX)
+ return NULL_RTX;
+ }
+ }
+
+ for (int i = 0; i < count; i++)
+ {
+ rtx v = op0;
+ if (i)
+ v = expand_simple_binop (mode, LSHIFTRT, v, GEN_INT (i * bit),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (v == NULL_RTX)
+ return NULL_RTX;
+ v = lowpart_subreg (word_mode, v, mode);
+ if (v == NULL_RTX)
+ return NULL_RTX;
+ if (i != count - 1)
+ v = expand_simple_binop (word_mode, AND, v,
+ GEN_INT ((HOST_WIDE_INT_1U << bit)
+ - 1), NULL_RTX, 1,
+ OPTAB_DIRECT);
+ if (v == NULL_RTX)
+ return NULL_RTX;
+ if (sum == NULL_RTX)
+ sum = v;
+ else
+ sum = expand_simple_binop (word_mode, PLUS, sum, v, NULL_RTX,
+ 1, OPTAB_DIRECT);
+ if (sum == NULL_RTX)
+ return NULL_RTX;
+ }
+ if (sum_corr)
+ {
+ sum = expand_simple_binop (word_mode, PLUS, sum, sum_corr,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (sum == NULL_RTX)
+ return NULL_RTX;
+ }
+ }
+ rtx remainder = expand_divmod (1, TRUNC_MOD_EXPR, word_mode, sum,
+ gen_int_mode (INTVAL (op1), word_mode),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (remainder == NULL_RTX)
+ return NULL_RTX;
+
+ if (!unsignedp)
+ {
+ if (mask == NULL_RTX)
+ {
+ mask = operand_subword_force (op0, WORDS_BIG_ENDIAN ? 0 : 1,
+ mode);
+ mask = expand_simple_binop (word_mode, ASHIFTRT, mask,
+ GEN_INT (BITS_PER_WORD - 1),
+ NULL_RTX, 0, OPTAB_DIRECT);
+ if (mask == NULL_RTX)
+ return NULL_RTX;
+ }
+ mask = expand_simple_binop (word_mode, AND, mask,
+ gen_int_mode (1 - INTVAL (op1),
+ word_mode),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (mask == NULL_RTX)
+ return NULL_RTX;
+ remainder = expand_simple_binop (word_mode, PLUS, remainder,
+ mask, NULL_RTX, 1, OPTAB_DIRECT);
+ if (remainder == NULL_RTX)
+ return NULL_RTX;
+ }
+
+ remainder = convert_modes (mode, word_mode, remainder, unsignedp);
+ /* Punt if we need any library calls. */
+ for (; last; last = NEXT_INSN (last))
+ if (CALL_P (last))
+ return NULL_RTX;
+ return remainder;
+ }
+ return NULL_RTX;
+}
+
+/* Similarly to the above function, but compute both quotient and remainder.
+ Quotient can be computed from the remainder as:
+ rem = op0 % op1; // Handled using expand_doubleword_mod
+ quot = (op0 - rem) * inv; // inv is multiplicative inverse of op1 modulo
+ // 2 * BITS_PER_WORD
+
+ We can also handle cases where op1 is a multiple of power of two constant
+ and constant handled by expand_doubleword_mod.
+ op11 = 1 << __builtin_ctz (op1);
+ op12 = op1 / op11;
+ rem1 = op0 % op12; // Handled using expand_doubleword_mod
+ quot1 = (op0 - rem1) * inv; // inv is multiplicative inverse of op12 modulo
+ // 2 * BITS_PER_WORD
+ rem = (quot1 % op11) * op12 + rem1;
+ quot = quot1 / op11; */
+
+rtx
+expand_doubleword_divmod (machine_mode mode, rtx op0, rtx op1, rtx *rem,
+ bool unsignedp)
+{
+ *rem = NULL_RTX;
+
+ /* Negative dividend should have been optimized into positive,
+ similarly modulo by 1 and modulo by power of two is optimized
+ differently too. */
+ if (INTVAL (op1) <= 1 || pow2p_hwi (INTVAL (op1)))
+ return NULL_RTX;
+
+ rtx op11 = const1_rtx;
+ rtx op12 = op1;
+ if ((INTVAL (op1) & 1) == 0)
+ {
+ int bit = ctz_hwi (INTVAL (op1));
+ op11 = GEN_INT (HOST_WIDE_INT_1 << bit);
+ op12 = GEN_INT (INTVAL (op1) >> bit);
+ }
+
+ rtx rem1 = expand_doubleword_mod (mode, op0, op12, unsignedp);
+ if (rem1 == NULL_RTX)
+ return NULL_RTX;
+
+ int prec = 2 * BITS_PER_WORD;
+ wide_int a = wide_int::from (INTVAL (op12), prec + 1, UNSIGNED);
+ wide_int b = wi::shifted_mask (prec, 1, false, prec + 1);
+ wide_int m = wide_int::from (wi::mod_inv (a, b), prec, UNSIGNED);
+ rtx inv = immed_wide_int_const (m, mode);
+
+ rtx_insn *last = get_last_insn ();
+ rtx quot1 = expand_simple_binop (mode, MINUS, op0, rem1,
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
+ if (quot1 == NULL_RTX)
+ return NULL_RTX;
+
+ quot1 = expand_simple_binop (mode, MULT, quot1, inv,
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
+ if (quot1 == NULL_RTX)
+ return NULL_RTX;
+
+ if (op11 != const1_rtx)
+ {
+ rtx rem2 = expand_divmod (1, TRUNC_MOD_EXPR, mode, quot1, op11,
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
+ if (rem2 == NULL_RTX)
+ return NULL_RTX;
+
+ rem2 = expand_simple_binop (mode, MULT, rem2, op12, NULL_RTX,
+ unsignedp, OPTAB_DIRECT);
+ if (rem2 == NULL_RTX)
+ return NULL_RTX;
+
+ rem2 = expand_simple_binop (mode, PLUS, rem2, rem1, NULL_RTX,
+ unsignedp, OPTAB_DIRECT);
+ if (rem2 == NULL_RTX)
+ return NULL_RTX;
+
+ rtx quot2 = expand_divmod (0, TRUNC_DIV_EXPR, mode, quot1, op11,
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
+ if (quot2 == NULL_RTX)
+ return NULL_RTX;
+
+ rem1 = rem2;
+ quot1 = quot2;
+ }
+
+ /* Punt if we need any library calls. */
+ for (; last; last = NEXT_INSN (last))
+ if (CALL_P (last))
+ return NULL_RTX;
+
+ *rem = rem1;
+ return quot1;
+}
/* Wrapper around expand_binop which takes an rtx code to specify
the operation to perform, not an optab pointer. All other
@@ -1806,6 +2093,54 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
}
}
+ /* Attempt to synthetize double word modulo by constant divisor. */
+ if ((binoptab == umod_optab
+ || binoptab == smod_optab
+ || binoptab == udiv_optab
+ || binoptab == sdiv_optab)
+ && optimize
+ && CONST_INT_P (op1)
+ && is_int_mode (mode, &int_mode)
+ && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+ && optab_handler ((binoptab == umod_optab || binoptab == udiv_optab)
+ ? udivmod_optab : sdivmod_optab,
+ int_mode) == CODE_FOR_nothing
+ && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
+ && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
+ && optimize_insn_for_speed_p ())
+ {
+ rtx res = NULL_RTX;
+ if ((binoptab == umod_optab || binoptab == smod_optab)
+ && (INTVAL (op1) & 1) == 0)
+ res = expand_doubleword_mod (int_mode, op0, op1,
+ binoptab == umod_optab);
+ else
+ {
+ rtx quot = expand_doubleword_divmod (int_mode, op0, op1, &res,
+ binoptab == umod_optab
+ || binoptab == udiv_optab);
+ if (quot == NULL_RTX)
+ res = NULL_RTX;
+ else if (binoptab == udiv_optab || binoptab == sdiv_optab)
+ res = quot;
+ }
+ if (res != NULL_RTX)
+ {
+ if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
+ {
+ rtx_insn *move = emit_move_insn (target ? target : res,
+ res);
+ set_dst_reg_note (move, REG_EQUAL,
+ gen_rtx_fmt_ee (optab_to_code (binoptab),
+ int_mode, copy_rtx (op0), op1),
+ target ? target : res);
+ }
+ return res;
+ }
+ else
+ delete_insns_since (last);
+ }
+
/* It can't be open-coded in this mode.
Use a library call if one is available and caller says that's ok. */
@@ -3834,23 +4169,59 @@ can_compare_p (enum rtx_code code, machine_mode mode,
return 0;
}
-/* Return whether the backend can emit a vector comparison for code CODE,
- comparing operands of mode CMP_OP_MODE and producing a result with
- VALUE_MODE. */
+/* Return whether RTL code CODE corresponds to an unsigned optab. */
+
+static bool
+unsigned_optab_p (enum rtx_code code)
+{
+ return code == LTU || code == LEU || code == GTU || code == GEU;
+}
+
+/* Return whether the backend-emitted comparison for code CODE, comparing
+ operands of mode VALUE_MODE and producing a result with MASK_MODE, matches
+ operand OPNO of pattern ICODE. */
+
+static bool
+insn_predicate_matches_p (enum insn_code icode, unsigned int opno,
+ enum rtx_code code, machine_mode mask_mode,
+ machine_mode value_mode)
+{
+ rtx reg1 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 1);
+ rtx reg2 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 2);
+ rtx test = alloca_rtx_fmt_ee (code, mask_mode, reg1, reg2);
+ return insn_operand_matches (icode, opno, test);
+}
+
+/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
+ for code CODE, comparing operands of mode VALUE_MODE and producing a result
+ with MASK_MODE. */
+
+bool
+can_vec_cmp_compare_p (enum rtx_code code, machine_mode value_mode,
+ machine_mode mask_mode)
+{
+ enum insn_code icode
+ = get_vec_cmp_icode (value_mode, mask_mode, unsigned_optab_p (code));
+ if (icode == CODE_FOR_nothing)
+ return false;
+
+ return insn_predicate_matches_p (icode, 1, code, mask_mode, value_mode);
+}
+
+/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
+ code CODE, comparing operands of mode CMP_OP_MODE and producing a result
+ with VALUE_MODE. */
bool
can_vcond_compare_p (enum rtx_code code, machine_mode value_mode,
machine_mode cmp_op_mode)
{
- enum insn_code icode;
- bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
- rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
- rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
- rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
-
- return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
- != CODE_FOR_nothing
- && insn_operand_matches (icode, 3, test);
+ enum insn_code icode
+ = get_vcond_icode (value_mode, cmp_op_mode, unsigned_optab_p (code));
+ if (icode == CODE_FOR_nothing)
+ return false;
+
+ return insn_predicate_matches_p (icode, 3, code, value_mode, cmp_op_mode);
}
/* Return whether the backend can emit vector set instructions for inserting
@@ -5403,11 +5774,11 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
return insn;
}
-/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
+/* Return rtx code for TCODE or UNKNOWN. Use UNSIGNEDP to select signed
or unsigned operation code. */
enum rtx_code
-get_rtx_code (enum tree_code tcode, bool unsignedp)
+get_rtx_code_1 (enum tree_code tcode, bool unsignedp)
{
enum rtx_code code;
switch (tcode)
@@ -5465,11 +5836,23 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
break;
default:
- gcc_unreachable ();
+ code = UNKNOWN;
+ break;
}
return code;
}
+/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
+ or unsigned operation code. */
+
+enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+ enum rtx_code code = get_rtx_code_1 (tcode, unsignedp);
+ gcc_assert (code != UNKNOWN);
+ return code;
+}
+
/* Return a comparison rtx of mode CMP_MODE for COND. Use UNSIGNEDP to
select signed or unsigned operators. OPNO holds the index of the
first comparison operand for insn ICODE. Do not generate the
@@ -6484,6 +6867,48 @@ expand_memory_blockage (void)
expand_asm_memory_blockage ();
}
+/* Generate asm volatile("" : : : "memory") as a memory blockage, at the
+ same time clobbering the register set specified by REGS. */
+
+void
+expand_asm_reg_clobber_mem_blockage (HARD_REG_SET regs)
+{
+ rtx asm_op, clob_mem;
+
+ unsigned int num_of_regs = 0;
+ for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (regs, i))
+ num_of_regs++;
+
+ asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
+ rtvec_alloc (0), rtvec_alloc (0),
+ rtvec_alloc (0), UNKNOWN_LOCATION);
+ MEM_VOLATILE_P (asm_op) = 1;
+
+ rtvec v = rtvec_alloc (num_of_regs + 2);
+
+ clob_mem = gen_rtx_SCRATCH (VOIDmode);
+ clob_mem = gen_rtx_MEM (BLKmode, clob_mem);
+ clob_mem = gen_rtx_CLOBBER (VOIDmode, clob_mem);
+
+ RTVEC_ELT (v, 0) = asm_op;
+ RTVEC_ELT (v, 1) = clob_mem;
+
+ if (num_of_regs > 0)
+ {
+ unsigned int j = 2;
+ for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (regs, i))
+ {
+ RTVEC_ELT (v, j) = gen_rtx_CLOBBER (VOIDmode, regno_reg_rtx[i]);
+ j++;
+ }
+ gcc_assert (j == (num_of_regs + 2));
+ }
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, v));
+}
+
/* This routine will either emit the mem_thread_fence pattern or issue a
sync_synchronize to generate a fence for memory model MEMMODEL. */
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 78409aa..e9727de 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -290,6 +290,8 @@ OPTAB_D (atan_optab, "atan$a2")
OPTAB_D (atanh_optab, "atanh$a2")
OPTAB_D (copysign_optab, "copysign$F$a3")
OPTAB_D (xorsign_optab, "xorsign$F$a3")
+OPTAB_D (cadd90_optab, "cadd90$a3")
+OPTAB_D (cadd270_optab, "cadd270$a3")
OPTAB_D (cos_optab, "cos$a2")
OPTAB_D (cosh_optab, "cosh$a2")
OPTAB_D (exp10_optab, "exp10$a2")
@@ -383,6 +385,10 @@ OPTAB_D (vec_widen_smult_even_optab, "vec_widen_smult_even_$a")
OPTAB_D (vec_widen_smult_hi_optab, "vec_widen_smult_hi_$a")
OPTAB_D (vec_widen_smult_lo_optab, "vec_widen_smult_lo_$a")
OPTAB_D (vec_widen_smult_odd_optab, "vec_widen_smult_odd_$a")
+OPTAB_D (vec_widen_ssubl_hi_optab, "vec_widen_ssubl_hi_$a")
+OPTAB_D (vec_widen_ssubl_lo_optab, "vec_widen_ssubl_lo_$a")
+OPTAB_D (vec_widen_saddl_hi_optab, "vec_widen_saddl_hi_$a")
+OPTAB_D (vec_widen_saddl_lo_optab, "vec_widen_saddl_lo_$a")
OPTAB_D (vec_widen_sshiftl_hi_optab, "vec_widen_sshiftl_hi_$a")
OPTAB_D (vec_widen_sshiftl_lo_optab, "vec_widen_sshiftl_lo_$a")
OPTAB_D (vec_widen_umult_even_optab, "vec_widen_umult_even_$a")
@@ -391,6 +397,10 @@ OPTAB_D (vec_widen_umult_lo_optab, "vec_widen_umult_lo_$a")
OPTAB_D (vec_widen_umult_odd_optab, "vec_widen_umult_odd_$a")
OPTAB_D (vec_widen_ushiftl_hi_optab, "vec_widen_ushiftl_hi_$a")
OPTAB_D (vec_widen_ushiftl_lo_optab, "vec_widen_ushiftl_lo_$a")
+OPTAB_D (vec_widen_usubl_hi_optab, "vec_widen_usubl_hi_$a")
+OPTAB_D (vec_widen_usubl_lo_optab, "vec_widen_usubl_lo_$a")
+OPTAB_D (vec_widen_uaddl_hi_optab, "vec_widen_uaddl_hi_$a")
+OPTAB_D (vec_widen_uaddl_lo_optab, "vec_widen_uaddl_lo_$a")
OPTAB_D (sync_add_optab, "sync_add$I$a")
OPTAB_D (sync_and_optab, "sync_and$I$a")
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 0b14700..87fed90 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -183,6 +183,8 @@ extern bool force_expand_binop (machine_mode, optab, rtx, rtx, rtx, int,
enum optab_methods);
extern rtx expand_vector_broadcast (machine_mode, rtx);
+extern rtx expand_doubleword_divmod (machine_mode, rtx, rtx, rtx *, bool);
+
/* Generate code for a simple binary or unary operation. "Simple" in
this case means "can be unambiguously described by a (mode, code)
pair and mapped to a single optab." */
@@ -244,9 +246,14 @@ enum can_compare_purpose
extern int can_compare_p (enum rtx_code, machine_mode,
enum can_compare_purpose);
-/* Return whether the backend can emit a vector comparison for code CODE,
- comparing operands of mode CMP_OP_MODE and producing a result with
- VALUE_MODE. */
+/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
+ for code CODE, comparing operands of mode VALUE_MODE and producing a result
+ with MASK_MODE. */
+extern bool can_vec_cmp_compare_p (enum rtx_code, machine_mode, machine_mode);
+
+/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
+ code CODE, comparing operands of mode CMP_OP_MODE and producing a result
+ with VALUE_MODE. */
extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
/* Return whether the backend can emit vector set instructions for inserting
@@ -345,6 +352,8 @@ rtx expand_atomic_store (rtx, rtx, enum memmodel, bool);
rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel,
bool);
+extern void expand_asm_reg_clobber_mem_blockage (HARD_REG_SET);
+
extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
rtx operand);
extern bool valid_multiword_target_p (rtx);
@@ -364,6 +373,7 @@ extern void expand_insn (enum insn_code icode, unsigned int nops,
extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
class expand_operand *ops);
+extern enum rtx_code get_rtx_code_1 (enum tree_code tcode, bool unsignedp);
extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
tree t_op0, tree t_op1, bool unsignedp,
diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk
index 73a96ba..0c9fa16 100644
--- a/gcc/optc-gen.awk
+++ b/gcc/optc-gen.awk
@@ -104,6 +104,9 @@ for (i = 0; i < n_opts; i++) {
enabledby_negarg = nth_arg(3, enabledby_arg);
lang_enabled_by(enabledby_langs, enabledby_name, enabledby_posarg, enabledby_negarg);
}
+
+ if (flag_set_p("Param", flags[i]) && !(opts[i] ~ "^-param="))
+ print "#error Parameter option name '" opts[i] "' must start with '-param='"
}
@@ -329,8 +332,6 @@ for (i = 0; i < n_opts; i++) {
print "#error Ignored option with Warn"
if (var_name(flags[i]) != "")
print "#error Ignored option with Var"
- if (flag_set_p("Report", flags[i]))
- print "#error Ignored option with Report"
}
else if (flag_set_p("Deprecated", flags[i]))
print "#error Deprecated was replaced with WarnRemoved"
@@ -338,8 +339,6 @@ for (i = 0; i < n_opts; i++) {
alias_data = "NULL, NULL, OPT_SPECIAL_warn_removed"
if (warn_message != "NULL")
print "#error WarnRemoved option with Warn"
- if (flag_set_p("Report", flags[i]))
- print "#error WarnRemoved option with Report"
}
else
alias_data = "NULL, NULL, N_OPTS"
@@ -592,5 +591,29 @@ for (i = 0; i < n_opts; i++) {
}
print "} "
+split("", var_seen, ":")
+print "\n#if !defined(GENERATOR_FILE) && defined(ENABLE_PLUGIN)"
+print "DEBUG_VARIABLE const struct cl_var cl_vars[] =\n{"
+
+for (i = 0; i < n_opts; i++) {
+ name = var_name(flags[i]);
+ if (name == "")
+ continue;
+ var_seen[name] = 1;
+}
+
+for (i = 0; i < n_extra_vars; i++) {
+ var = extra_vars[i]
+ sub(" *=.*", "", var)
+ name = var
+ sub("^.*[ *]", "", name)
+ sub("\\[.*\\]$", "", name)
+ if (name in var_seen)
+ continue;
+ print " { " quote name quote ", offsetof (struct gcc_options, x_" name ") },"
+ var_seen[name] = 1
}
+print " { NULL, (unsigned short) -1 }\n};\n#endif"
+
+}
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
index a756835..0a1be8c 100644
--- a/gcc/optc-save-gen.awk
+++ b/gcc/optc-save-gen.awk
@@ -1290,6 +1290,7 @@ for (i = 0; i < n_opts; i++) {
var_opt_val_type[n_opt_val] = otype;
var_opt_val[n_opt_val] = "x_" name;
var_opt_hash[n_opt_val] = flag_set_p("Optimization", flags[i]);
+ var_opt_init[n_opt_val] = opt_args("Init", flags[i]);
n_opt_val++;
}
}
@@ -1361,10 +1362,21 @@ for (i = 0; i < n_opt_val; i++) {
otype = var_opt_val_type[i];
if (otype ~ "^const char \\**$")
print " bp_pack_string (ob, bp, ptr->" name", true);";
- else if (otype ~ "^unsigned")
- print " bp_pack_var_len_unsigned (bp, ptr->" name");";
- else
- print " bp_pack_var_len_int (bp, ptr->" name");";
+ else {
+ if (otype ~ "^unsigned") {
+ sgn = "unsigned";
+ } else {
+ sgn = "int";
+ }
+ if (name ~ "^x_param" && !(otype ~ "^enum ") && var_opt_init[i]) {
+ print " if (" var_opt_init[i] " > (" var_opt_val_type[i] ") 10)";
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name" ^ " var_opt_init[i] ");";
+ print " else";
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name");";
+ } else {
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name");";
+ }
+ }
}
print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
print " bp_pack_value (bp, ptr->explicit_mask[i], 64);";
@@ -1385,10 +1397,18 @@ for (i = 0; i < n_opt_val; i++) {
print " if (ptr->" name")";
print " ptr->" name" = xstrdup (ptr->" name");";
}
- else if (otype ~ "^unsigned")
- print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_var_len_unsigned (bp);";
- else
- print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_var_len_int (bp);";
+ else {
+ if (otype ~ "^unsigned") {
+ sgn = "unsigned";
+ } else {
+ sgn = "int";
+ }
+ print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_var_len_" sgn " (bp);";
+ if (name ~ "^x_param" && !(otype ~ "^enum ") && var_opt_init[i]) {
+ print " if (" var_opt_init[i] " > (" var_opt_val_type[i] ") 10)";
+ print " ptr->" name" ^= " var_opt_init[i] ";";
+ }
+ }
}
print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
print " ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 8ec8c1e..30be7d5 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -1466,9 +1466,15 @@ set_option (struct gcc_options *opts, struct gcc_options *opts_set,
}
else
{
- *(int *) flag_var = value;
- if (set_flag_var)
- *(int *) set_flag_var = 1;
+ if (value > INT_MAX)
+ error_at (loc, "argument to %qs is bigger than %d",
+ option->opt_text, INT_MAX);
+ else
+ {
+ *(int *) flag_var = value;
+ if (set_flag_var)
+ *(int *) set_flag_var = 1;
+ }
}
break;
diff --git a/gcc/opts.c b/gcc/opts.c
index da503c3..3db08b3 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "spellcheck.h"
#include "opt-suggestions.h"
#include "diagnostic-color.h"
+#include "version.h"
#include "selftest.h"
static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
@@ -688,30 +689,26 @@ control_options_for_live_patching (struct gcc_options *opts,
{
case LIVE_PATCHING_INLINE_ONLY_STATIC:
if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone)
- error_at (loc,
- "%<-fipa-cp-clone%> is incompatible with "
- "%<-flive-patching=inline-only-static%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-cp-clone", "-flive-patching=inline-only-static");
else
opts->x_flag_ipa_cp_clone = 0;
if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra)
- error_at (loc,
- "%<-fipa-sra%> is incompatible with "
- "%<-flive-patching=inline-only-static%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-sra", "-flive-patching=inline-only-static");
else
opts->x_flag_ipa_sra = 0;
if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining)
- error_at (loc,
- "%<-fpartial-inlining%> is incompatible with "
- "%<-flive-patching=inline-only-static%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fpartial-inlining", "-flive-patching=inline-only-static");
else
opts->x_flag_partial_inlining = 0;
if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp)
- error_at (loc,
- "%<-fipa-cp%> is incompatible with "
- "%<-flive-patching=inline-only-static%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-cp", "-flive-patching=inline-only-static");
else
opts->x_flag_ipa_cp = 0;
@@ -719,9 +716,9 @@ control_options_for_live_patching (struct gcc_options *opts,
case LIVE_PATCHING_INLINE_CLONE:
/* live patching should disable whole-program optimization. */
if (opts_set->x_flag_whole_program && opts->x_flag_whole_program)
- error_at (loc,
- "%<-fwhole-program%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fwhole-program",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_whole_program = 0;
@@ -730,65 +727,65 @@ control_options_for_live_patching (struct gcc_options *opts,
&& !flag_partial_inlining. */
if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta)
- error_at (loc,
- "%<-fipa-pta%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-pta",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_pta = 0;
if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference)
- error_at (loc,
- "%<-fipa-reference%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-reference",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_reference = 0;
if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra)
- error_at (loc,
- "%<-fipa-ra%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-ra",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_ra = 0;
if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf)
- error_at (loc,
- "%<-fipa-icf%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-icf",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_icf = 0;
if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions)
- error_at (loc,
- "%<-fipa-icf-functions%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-icf-functions",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_icf_functions = 0;
if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables)
- error_at (loc,
- "%<-fipa-icf-variables%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-icf-variables",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_icf_variables = 0;
if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp)
- error_at (loc,
- "%<-fipa-bit-cp%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-bit-cp",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_bit_cp = 0;
if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp)
- error_at (loc,
- "%<-fipa-vrp%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-vrp",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_vrp = 0;
if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const)
- error_at (loc,
- "%<-fipa-pure-const%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-pure-const",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_pure_const = 0;
@@ -804,18 +801,18 @@ control_options_for_live_patching (struct gcc_options *opts,
/* discovery of functions/variables with no address taken. */
if (opts_set->x_flag_ipa_reference_addressable
&& opts->x_flag_ipa_reference_addressable)
- error_at (loc,
- "%<-fipa-reference-addressable%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-reference-addressable",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_reference_addressable = 0;
/* ipa stack alignment propagation. */
if (opts_set->x_flag_ipa_stack_alignment
&& opts->x_flag_ipa_stack_alignment)
- error_at (loc,
- "%<-fipa-stack-alignment%> is incompatible with "
- "%<-flive-patching=inline-only-static|inline-clone%>");
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-stack-alignment",
+ "-flive-patching=inline-only-static|inline-clone");
else
opts->x_flag_ipa_stack_alignment = 0;
break;
@@ -827,6 +824,57 @@ control_options_for_live_patching (struct gcc_options *opts,
/* --help option argument if set. */
vec<const char *> help_option_arguments;
+/* Return the string name describing a sanitizer argument which has been
+ provided on the command line and has set this particular flag. */
+const char *
+find_sanitizer_argument (struct gcc_options *opts, unsigned int flags)
+{
+ for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
+ {
+ /* Need to find the sanitizer_opts element which:
+ a) Could have set the flags requested.
+ b) Has been set on the command line.
+
+ Can have (a) without (b) if the flag requested is e.g.
+ SANITIZE_ADDRESS, since both -fsanitize=address and
+ -fsanitize=kernel-address set this flag.
+
+ Can have (b) without (a) by requesting more than one sanitizer on the
+ command line. */
+ if ((sanitizer_opts[i].flag & opts->x_flag_sanitize)
+ != sanitizer_opts[i].flag)
+ continue;
+ if ((sanitizer_opts[i].flag & flags) != flags)
+ continue;
+ return sanitizer_opts[i].name;
+ }
+ return NULL;
+}
+
+
+/* Report an error to the user about sanitizer options they have requested
+ which have set conflicting flags.
+
+ LEFT and RIGHT indicate sanitizer flags which conflict with each other, this
+ function reports an error if both have been set in OPTS->x_flag_sanitize and
+ ensures the error identifies the requested command line options that have
+ set these flags. */
+static void
+report_conflicting_sanitizer_options (struct gcc_options *opts, location_t loc,
+ unsigned int left, unsigned int right)
+{
+ unsigned int left_seen = (opts->x_flag_sanitize & left);
+ unsigned int right_seen = (opts->x_flag_sanitize & right);
+ if (left_seen && right_seen)
+ {
+ const char* left_arg = find_sanitizer_argument (opts, left_seen);
+ const char* right_arg = find_sanitizer_argument (opts, right_seen);
+ gcc_assert (left_arg && right_arg);
+ error_at (loc,
+ "%<-fsanitize=%s%> is incompatible with %<-fsanitize=%s%>",
+ left_arg, right_arg);
+ }
+}
/* After all options at LOC have been read into OPTS and OPTS_SET,
finalize settings of those options and diagnose incompatible
@@ -1078,24 +1126,22 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
"%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
}
- /* Userspace and kernel ASan conflict with each other. */
- if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
- && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
- error_at (loc,
- "%<-fsanitize=address%> is incompatible with "
- "%<-fsanitize=kernel-address%>");
+ /* Address sanitizers conflict with the thread sanitizer. */
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_THREAD,
+ SANITIZE_ADDRESS | SANITIZE_HWADDRESS);
+ /* The leak sanitizer conflicts with the thread sanitizer. */
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_LEAK,
+ SANITIZE_THREAD);
- /* And with TSan. */
- if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
- && (opts->x_flag_sanitize & SANITIZE_THREAD))
- error_at (loc,
- "%<-fsanitize=address%> and %<-fsanitize=kernel-address%> "
- "are incompatible with %<-fsanitize=thread%>");
+ /* No combination of HWASAN and ASAN work together. */
+ report_conflicting_sanitizer_options (opts, loc,
+ SANITIZE_HWADDRESS, SANITIZE_ADDRESS);
- if ((opts->x_flag_sanitize & SANITIZE_LEAK)
- && (opts->x_flag_sanitize & SANITIZE_THREAD))
- error_at (loc,
- "%<-fsanitize=leak%> is incompatible with %<-fsanitize=thread%>");
+ /* The userspace and kernel address sanitizers conflict with each other. */
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_USER_HWADDRESS,
+ SANITIZE_KERNEL_HWADDRESS);
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_USER_ADDRESS,
+ SANITIZE_KERNEL_ADDRESS);
/* Check error recovery for -fsanitize-recover option. */
for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
@@ -1114,9 +1160,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
if (opts->x_flag_sanitize & ~(SANITIZE_LEAK | SANITIZE_UNREACHABLE))
opts->x_flag_aggressive_loop_optimizations = 0;
- /* Enable -fsanitize-address-use-after-scope if address sanitizer is
+ /* Enable -fsanitize-address-use-after-scope if either address sanitizer is
enabled. */
- if (opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+ if (opts->x_flag_sanitize
+ & (SANITIZE_USER_ADDRESS | SANITIZE_USER_HWADDRESS))
SET_OPTION_IF_UNSET (opts, opts_set, flag_sanitize_address_use_after_scope,
true);
@@ -1730,8 +1777,13 @@ const struct sanitizer_opts_s sanitizer_opts[] =
#define SANITIZER_OPT(name, flags, recover) \
{ #name, flags, sizeof #name - 1, recover }
SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true),
+ SANITIZER_OPT (hwaddress, (SANITIZE_HWADDRESS | SANITIZE_USER_HWADDRESS),
+ true),
SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
true),
+ SANITIZER_OPT (kernel-hwaddress,
+ (SANITIZE_HWADDRESS | SANITIZE_KERNEL_HWADDRESS),
+ true),
SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true),
SANITIZER_OPT (pointer-subtract, SANITIZE_POINTER_SUBTRACT, true),
SANITIZER_OPT (thread, SANITIZE_THREAD, false),
@@ -1776,6 +1828,24 @@ const struct sanitizer_opts_s coverage_sanitizer_opts[] =
{ NULL, 0U, 0UL, false }
};
+/* -fzero-call-used-regs= suboptions. */
+const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
+{
+#define ZERO_CALL_USED_REGS_OPT(name, flags) \
+ { #name, flags }
+ ZERO_CALL_USED_REGS_OPT (skip, zero_regs_flags::SKIP),
+ ZERO_CALL_USED_REGS_OPT (used-gpr-arg, zero_regs_flags::USED_GPR_ARG),
+ ZERO_CALL_USED_REGS_OPT (used-gpr, zero_regs_flags::USED_GPR),
+ ZERO_CALL_USED_REGS_OPT (used-arg, zero_regs_flags::USED_ARG),
+ ZERO_CALL_USED_REGS_OPT (used, zero_regs_flags::USED),
+ ZERO_CALL_USED_REGS_OPT (all-gpr-arg, zero_regs_flags::ALL_GPR_ARG),
+ ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
+ ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
+ ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
+#undef ZERO_CALL_USED_REGS_OPT
+ {NULL, 0U}
+};
+
/* A struct for describing a run of chars within a string. */
class string_fragment
@@ -1970,6 +2040,27 @@ parse_no_sanitize_attribute (char *value)
return flags;
}
+/* Parse -fzero-call-used-regs suboptions from ARG, return the FLAGS. */
+
+unsigned int
+parse_zero_call_used_regs_options (const char *arg)
+{
+ unsigned int flags = 0;
+
+ /* Check to see if the string matches a sub-option name. */
+ for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
+ if (strcmp (arg, zero_call_used_regs_opts[i].name) == 0)
+ {
+ flags = zero_call_used_regs_opts[i].flag;
+ break;
+ }
+
+ if (!flags)
+ error ("unrecognized argument to %<-fzero-call-used-regs=%>: %qs", arg);
+
+ return flags;
+}
+
/* Parse -falign-NAME format for a FLAG value. Return individual
parsed integer values into RESULT_VALUES array. If REPORT_ERROR is
set, print error message at LOC location. */
@@ -2271,6 +2362,15 @@ common_handle_option (struct gcc_options *opts,
SET_OPTION_IF_UNSET (opts, opts_set, param_asan_protect_allocas, 0);
SET_OPTION_IF_UNSET (opts, opts_set, param_asan_use_after_return, 0);
}
+ if (opts->x_flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
+ {
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_hwasan_instrument_stack, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_hwasan_random_frame_tag, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_hwasan_instrument_allocas, 0);
+ }
break;
case OPT_fsanitize_recover_:
@@ -2563,6 +2663,10 @@ common_handle_option (struct gcc_options *opts,
SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
break;
+ case OPT_fprofile_info_section:
+ opts->x_profile_info_section = ".gcov_info";
+ break;
+
case OPT_fpatchable_function_entry_:
{
char *patch_area_arg = xstrdup (arg);
@@ -2596,6 +2700,11 @@ common_handle_option (struct gcc_options *opts,
/* Automatically sets -ftree-loop-vectorize and
-ftree-slp-vectorize. Nothing more to do here. */
break;
+ case OPT_fzero_call_used_regs_:
+ opts->x_flag_zero_call_used_regs
+ = parse_zero_call_used_regs_options (arg);
+ break;
+
case OPT_fshow_column:
dc->show_column = value;
break;
@@ -3158,6 +3267,124 @@ get_option_url (diagnostic_context *, int option_index)
return NULL;
}
+/* Return a heap allocated producer with command line options. */
+
+char *
+gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count)
+{
+ auto_vec<const char *> switches;
+ char *options_string, *tail;
+ const char *p;
+ size_t len = 0;
+
+ for (unsigned i = 0; i < options_count; i++)
+ switch (options[i].opt_index)
+ {
+ case OPT_o:
+ case OPT_d:
+ case OPT_dumpbase:
+ case OPT_dumpdir:
+ case OPT_quiet:
+ case OPT_version:
+ case OPT_v:
+ case OPT_w:
+ case OPT_L:
+ case OPT_D:
+ case OPT_I:
+ case OPT_U:
+ case OPT_SPECIAL_unknown:
+ case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_warn_removed:
+ case OPT_SPECIAL_program_name:
+ case OPT_SPECIAL_input_file:
+ case OPT_grecord_gcc_switches:
+ case OPT_frecord_gcc_switches:
+ case OPT__output_pch_:
+ case OPT_fdiagnostics_show_location_:
+ case OPT_fdiagnostics_show_option:
+ case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
+ case OPT_fdiagnostics_color_:
+ case OPT_fdiagnostics_format_:
+ case OPT_fverbose_asm:
+ case OPT____:
+ case OPT__sysroot_:
+ case OPT_nostdinc:
+ case OPT_nostdinc__:
+ case OPT_fpreprocessed:
+ case OPT_fltrans_output_list_:
+ case OPT_fresolution_:
+ case OPT_fdebug_prefix_map_:
+ case OPT_fmacro_prefix_map_:
+ case OPT_ffile_prefix_map_:
+ case OPT_fcompare_debug:
+ case OPT_fchecking:
+ case OPT_fchecking_:
+ /* Ignore these. */
+ continue;
+ case OPT_flto_:
+ {
+ const char *lto_canonical = "-flto";
+ switches.safe_push (lto_canonical);
+ len += strlen (lto_canonical) + 1;
+ break;
+ }
+ default:
+ if (cl_options[options[i].opt_index].flags
+ & CL_NO_DWARF_RECORD)
+ continue;
+ gcc_checking_assert (options[i].canonical_option[0][0] == '-');
+ switch (options[i].canonical_option[0][1])
+ {
+ case 'M':
+ case 'i':
+ case 'W':
+ continue;
+ case 'f':
+ if (strncmp (options[i].canonical_option[0] + 2,
+ "dump", 4) == 0)
+ continue;
+ break;
+ default:
+ break;
+ }
+ switches.safe_push (options[i].orig_option_with_args_text);
+ len += strlen (options[i].orig_option_with_args_text) + 1;
+ break;
+ }
+
+ options_string = XNEWVEC (char, len + 1);
+ tail = options_string;
+
+ unsigned i;
+ FOR_EACH_VEC_ELT (switches, i, p)
+ {
+ len = strlen (p);
+ memcpy (tail, p, len);
+ tail += len;
+ if (i != switches.length () - 1)
+ {
+ *tail = ' ';
+ ++tail;
+ }
+ }
+
+ *tail = '\0';
+ return options_string;
+}
+
+/* Return a heap allocated producer string including command line options. */
+
+char *
+gen_producer_string (const char *language_string, cl_decoded_option *options,
+ unsigned int options_count)
+{
+ return concat (language_string, " ", version_string, " ",
+ gen_command_line_string (options, options_count), NULL);
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/opts.h b/gcc/opts.h
index 8f594b4..2cf24d1 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -104,8 +104,6 @@ struct cl_option
BOOL_BITFIELD cl_host_wide_int : 1;
/* Argument should be converted to lowercase. */
BOOL_BITFIELD cl_tolower : 1;
- /* Report argument with -fverbose-asm */
- BOOL_BITFIELD cl_report : 1;
/* Argument is an unsigned integer with an optional byte suffix. */
BOOL_BITFIELD cl_byte_size: 1;
/* Offset of field for this option in struct gcc_options, or
@@ -124,6 +122,14 @@ struct cl_option
int range_max;
};
+struct cl_var
+{
+ /* Name of the variable. */
+ const char *var_name;
+ /* Offset of field for this var in struct gcc_options. */
+ unsigned short var_offset;
+};
+
/* Records that the state of an option consists of SIZE bytes starting
at DATA. DATA might point to CH in some cases. */
struct cl_option_state {
@@ -134,6 +140,9 @@ struct cl_option_state {
extern const struct cl_option cl_options[];
extern const unsigned int cl_options_count;
+#ifdef ENABLE_PLUGIN
+extern const struct cl_var cl_vars[];
+#endif
extern const char *const lang_names[];
extern const unsigned int cl_lang_count;
@@ -444,6 +453,12 @@ extern const struct sanitizer_opts_s
bool can_recover;
} sanitizer_opts[];
+extern const struct zero_call_used_regs_opts_s
+{
+ const char *const name;
+ unsigned int flag;
+} zero_call_used_regs_opts[];
+
extern vec<const char *> help_option_arguments;
extern void add_misspelling_candidates (auto_vec<char *> *candidates,
@@ -465,6 +480,12 @@ extern void parse_options_from_collect_gcc_options (const char *, obstack *,
extern void prepend_xassembler_to_collect_as_options (const char *, obstack *);
+extern char *gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count);
+extern char *gen_producer_string (const char *language_string,
+ cl_decoded_option *options,
+ unsigned int options_count);
+
/* Set OPTION in OPTS to VALUE if the option is not set in OPTS_SET. */
#define SET_OPTION_IF_UNSET(OPTS, OPTS_SET, OPTION, VALUE) \
diff --git a/gcc/output.h b/gcc/output.h
index eb253c5..1f9af46 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,12 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_COMMON 0x800000 /* contains common data */
#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000 /* subsequent bits reserved for target */
+#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
+#define SECTION_LINK_ORDER 0x8000000 /* section needs link-order. */
+
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+#define SECTION_MACH_DEP 0x10000000 /* subsequent bits reserved for target */
/* This SECTION_STYLE is used for unnamed sections that we can switch
to using a special assembler directive. */
@@ -523,7 +528,8 @@ extern GTY(()) bool in_cold_section_p;
extern section *get_unnamed_section (unsigned int, void (*) (const void *),
const void *);
-extern section *get_section (const char *, unsigned int, tree);
+extern section *get_section (const char *, unsigned int, tree,
+ bool not_existing = false);
extern section *get_named_section (tree, const char *, int);
extern section *get_variable_section (tree, bool);
extern void place_block_symbol (rtx);
@@ -542,7 +548,7 @@ extern void switch_to_other_text_partition (void);
extern section *get_cdtor_priority_section (int, bool);
extern bool unlikely_text_section_p (section *);
-extern void switch_to_section (section *);
+extern void switch_to_section (section *, tree = nullptr);
extern void output_section_asm_op (const void *);
extern void record_tm_clone_pair (tree, tree);
@@ -571,8 +577,8 @@ extern void default_ctor_section_asm_out_constructor (rtx, int);
extern section *default_select_section (tree, int, unsigned HOST_WIDE_INT);
extern section *default_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
extern void default_unique_section (tree, int);
-extern section *default_function_rodata_section (tree);
-extern section *default_no_function_rodata_section (tree);
+extern section *default_function_rodata_section (tree, bool);
+extern section *default_no_function_rodata_section (tree, bool);
extern section *default_clone_table_section (void);
extern section *default_select_rtx_section (machine_mode, rtx,
unsigned HOST_WIDE_INT);
diff --git a/gcc/params.opt b/gcc/params.opt
index e05f7ff..54951f2 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -62,6 +62,30 @@ Enable asan stack protection.
Common Joined UInteger Var(param_asan_use_after_return) Init(1) IntegerRange(0, 1) Param Optimization
Enable asan detection of use-after-return bugs.
+-param=hwasan-instrument-stack=
+Common Joined UInteger Var(param_hwasan_instrument_stack) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of statically sized stack-allocated variables.
+
+-param=hwasan-random-frame-tag=
+Common Joined UInteger Var(param_hwasan_random_frame_tag) Init(1) IntegerRange(0, 1) Param Optimization
+Use random base tag for each frame, as opposed to base always zero.
+
+-param=hwasan-instrument-allocas=
+Common Joined UInteger Var(param_hwasan_instrument_allocas) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of allocas/VLAs.
+
+-param=hwasan-instrument-reads=
+Common Joined UInteger Var(param_hwasan_instrument_reads) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of load operations.
+
+-param=hwasan-instrument-writes=
+Common Joined UInteger Var(param_hwasan_instrument_writes) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of store operations.
+
+-param=hwasan-instrument-mem-intrinsics=
+Common Joined UInteger Var(param_hwasan_instrument_mem_intrinsics) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of builtin functions.
+
-param=avg-loop-niter=
Common Joined UInteger Var(param_avg_loop_niter) Init(10) IntegerRange(1, 65536) Param Optimization
Average number of iterations of a loop.
@@ -253,7 +277,7 @@ The size of translation unit that IPA-CP pass considers large.
Common Joined UInteger Var(param_ipa_cp_value_list_size) Init(8) Param Optimization
Maximum size of a list of values associated with each parameter for interprocedural constant propagation.
--param-ipa-jump-function-lookups=
+-param=ipa-jump-function-lookups=
Common Joined UInteger Var(param_ipa_jump_function_lookups) Init(8) Param Optimization
Maximum number of statements visited during jump function offset discovery.
@@ -349,6 +373,10 @@ Maximal stack frame growth due to inlining (in percent).
Common Joined UInteger Var(param_large_unit_insns) Optimization Init(10000) Param
The size of translation unit to be considered large.
+-param=lazy-modules=
+C++ Joined UInteger Var(param_lazy_modules) Init(32768) Param
+Maximum number of concurrently open C++ module files when lazy loading.
+
-param=lim-expensive=
Common Joined UInteger Var(param_lim_expensive) Init(20) Param Optimization
The minimum cost of an expensive expression in the loop invariant motion.
@@ -855,10 +883,6 @@ The number of prefetches that can run at the same time.
Common Joined UInteger Var(param_sink_frequency_threshold) Init(75) IntegerRange(0, 100) Param Optimization
Target block's relative execution frequency (as a percentage) required to sink a statement.
--param=slp-max-insns-in-bb=
-Common Joined UInteger Var(param_slp_max_insns_in_bb) Init(1000) Param Optimization
-Maximum number of instructions in basic block to be considered for SLP vectorization.
-
-param=sms-dfa-history=
Common Joined UInteger Var(param_sms_dfa_history) IntegerRange(0, 16) Param Optimization
The number of cycles the swing modulo scheduler considers when checking conflicts using DFA.
@@ -916,21 +940,29 @@ Common Joined UInteger Var(param_switch_conversion_branch_ratio) Init(8) Integer
The maximum ratio between array size and switch branches for a switch conversion to take place.
-param=modref-max-bases=
-Common Joined UInteger Var(param_modref_max_bases) Init(32)
+Common Joined UInteger Var(param_modref_max_bases) Init(32) Param Optimization
Maximum number of bases stored in each modref tree.
-param=modref-max-refs=
-Common Joined UInteger Var(param_modref_max_refs) Init(16)
+Common Joined UInteger Var(param_modref_max_refs) Init(16) Param Optimization
Maximum number of references stored in each modref base.
-param=modref-max-accesses=
-Common Joined UInteger Var(param_modref_max_accesses) Init(16)
+Common Joined UInteger Var(param_modref_max_accesses) Init(16) Param Optimization
Maximum number of accesse stored in each modref reference.
-param=modref-max-tests=
-Common Joined UInteger Var(param_modref_max_tests) Init(64)
+Common Joined UInteger Var(param_modref_max_tests) Init(64) Param Optimization
Maximum number of tests performed by modref query.
+-param=modref-max-depth=
+Common Joined UInteger Var(param_modref_max_depth) Init(256) Param Optimization
+Maximum depth of DFS walk used by modref escape analysis.
+
+-param=modref-max-escape-points=
+Common Joined UInteger Var(param_modref_max_escape_points) Init(256) Param Optimization
+Maximum number of escape points tracked by modref per SSA-name.
+
-param=tm-max-aggregate-size=
Common Joined UInteger Var(param_tm_max_aggregate_size) Init(9) Param Optimization
Size in bytes after which thread-local aggregates should be instrumented with the logging functions instead of save/restore pairs.
diff --git a/gcc/passes.c b/gcc/passes.c
index 1942b7c..973c958 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -731,7 +731,54 @@ make_pass_late_compilation (gcc::context *ctxt)
return new pass_late_compilation (ctxt);
}
+/* Pre-SLP scalar cleanup, it has several cleanup passes like FRE, DSE. */
+namespace {
+
+const pass_data pass_data_pre_slp_scalar_cleanup =
+{
+ GIMPLE_PASS, /* type */
+ "*pre_slp_scalar_cleanup", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ TV_SCALAR_CLEANUP, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_pre_slp_scalar_cleanup : public gimple_opt_pass
+{
+public:
+ pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_pre_slp_scalar_cleanup, ctxt)
+ {
+ }
+
+ virtual bool
+ gate (function *fun)
+ {
+ return flag_tree_slp_vectorize
+ && (fun->pending_TODOs & PENDING_TODO_force_next_scalar_cleanup);
+ }
+
+ virtual unsigned int
+ execute (function *fun)
+ {
+ fun->pending_TODOs &= ~PENDING_TODO_force_next_scalar_cleanup;
+ return 0;
+ }
+
+}; // class pass_pre_slp_scalar_cleanup
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt)
+{
+ return new pass_pre_slp_scalar_cleanup (ctxt);
+}
/* Set the static pass number of pass PASS to ID and record that
in the mapping from static pass number to pass. */
@@ -1790,6 +1837,9 @@ emergency_dump_function ()
fnotice (stderr, "dump file: %s\n", dump_file_name);
fprintf (dump_file, "\n\n\nEMERGENCY DUMP:\n\n");
execute_function_dump (cfun, current_pass);
+
+ if (symtab && current_pass->type == IPA_PASS)
+ symtab->dump (dump_file);
}
static struct profile_record *profile_record;
@@ -2566,7 +2616,8 @@ execute_one_pass (opt_pass *pass)
{
struct cgraph_node *node;
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
- node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
+ if (!node->inlined_to)
+ node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *)pass);
}
else if (dump_file)
do_per_function (execute_function_dump, pass);
@@ -2730,7 +2781,8 @@ ipa_write_summaries (void)
{
struct cgraph_node *node = order[i];
- if (node->definition && node->need_lto_streaming)
+ if ((node->definition || node->declare_variant_alt)
+ && node->need_lto_streaming)
{
if (gimple_has_body_p (node->decl))
lto_prepare_function_for_streaming (node);
diff --git a/gcc/passes.def b/gcc/passes.def
index cf15d8e..21b2e2a 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_warn_unused_result);
NEXT_PASS (pass_diagnose_omp_blocks);
NEXT_PASS (pass_diagnose_tm_blocks);
+ NEXT_PASS (pass_omp_oacc_kernels_decompose);
NEXT_PASS (pass_lower_omp);
NEXT_PASS (pass_lower_cf);
NEXT_PASS (pass_lower_tm);
@@ -93,6 +94,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_phiopt, true /* early_p */);
NEXT_PASS (pass_modref);
NEXT_PASS (pass_tail_recursion);
+ NEXT_PASS (pass_if_to_switch);
NEXT_PASS (pass_convert_switch);
NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_profile);
@@ -289,11 +291,16 @@ along with GCC; see the file COPYING3. If not see
/* pass_vectorize must immediately follow pass_if_conversion.
Please do not add any other passes in between. */
NEXT_PASS (pass_vectorize);
- PUSH_INSERT_PASSES_WITHIN (pass_vectorize)
+ PUSH_INSERT_PASSES_WITHIN (pass_vectorize)
NEXT_PASS (pass_dce);
- POP_INSERT_PASSES ()
- NEXT_PASS (pass_predcom);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_predcom);
NEXT_PASS (pass_complete_unroll);
+ NEXT_PASS (pass_pre_slp_scalar_cleanup);
+ PUSH_INSERT_PASSES_WITHIN (pass_pre_slp_scalar_cleanup)
+ NEXT_PASS (pass_fre, false /* may_iterate */);
+ NEXT_PASS (pass_dse);
+ POP_INSERT_PASSES ()
NEXT_PASS (pass_slp_vectorize);
NEXT_PASS (pass_loop_prefetch);
/* Run IVOPTs after the last pass that uses data-reference analysis
@@ -491,6 +498,7 @@ along with GCC; see the file COPYING3. If not see
POP_INSERT_PASSES ()
NEXT_PASS (pass_late_compilation);
PUSH_INSERT_PASSES_WITHIN (pass_late_compilation)
+ NEXT_PASS (pass_zero_call_used_regs);
NEXT_PASS (pass_compute_alignments);
NEXT_PASS (pass_variable_tracking);
NEXT_PASS (pass_free_cfg);
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 69b6f5b..76069e6 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -497,6 +497,7 @@ register_callback (const char *plugin_name,
case PLUGIN_EARLY_GIMPLE_PASSES_END:
case PLUGIN_NEW_PASS:
case PLUGIN_INCLUDE_FILE:
+ case PLUGIN_ANALYZER_INIT:
{
struct callback_info *new_callback;
if (!callback)
@@ -577,6 +578,7 @@ invoke_plugin_callbacks_full (int event, void *gcc_data)
case PLUGIN_EARLY_GIMPLE_PASSES_END:
case PLUGIN_NEW_PASS:
case PLUGIN_INCLUDE_FILE:
+ case PLUGIN_ANALYZER_INIT:
{
/* Iterate over every callback registered with this event and
call it. */
diff --git a/gcc/plugin.def b/gcc/plugin.def
index 3482ed7..b811019 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -99,6 +99,10 @@ DEFEVENT (PLUGIN_NEW_PASS)
as a const char* pointer. */
DEFEVENT (PLUGIN_INCLUDE_FILE)
+/* Called when -fanalyzer starts. The event data is an
+ ana::plugin_analyzer_init_iface *. */
+DEFEVENT (PLUGIN_ANALYZER_INIT)
+
/* When adding a new hard-coded plugin event, don't forget to edit in
file plugin.c the functions register_callback and
invoke_plugin_callbacks_full accordingly! */
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 0cd3014f..e29c057 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2020-11-18 Joseph Myers <joseph@codesourcery.com>
+
+ * zh_TW.po: Update.
+
2020-07-29 Joseph Myers <joseph@codesourcery.com>
* ja.po, sv.po: Update.
diff --git a/gcc/po/zh_TW.po b/gcc/po/zh_TW.po
index 69cd0be..bf76882 100644
--- a/gcc/po/zh_TW.po
+++ b/gcc/po/zh_TW.po
@@ -7,10 +7,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: gcc 10.1.0\n"
+"Project-Id-Version: gcc 10.2.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2020-07-20 18:08+0000\n"
-"PO-Revision-Date: 2020-05-08 22:14+0800\n"
+"PO-Revision-Date: 2020-11-19 00:56+0800\n"
"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
"Language-Team: Chinese (traditional) <zh-l10n@lists.linux.org.tw>\n"
"Language: zh_TW\n"
@@ -19,7 +19,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Bugs: Report translation errors to the Language-Team address.\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 2.3\n"
+"X-Generator: Poedit 2.4.1\n"
#: cfgrtl.c:2748
msgid "flow control insn inside a basic block"
@@ -134,7 +134,7 @@ msgstr "請參閱 %s 取得指引。\n"
#: diagnostic.c:602
#, c-format
msgid "compilation terminated.\n"
-msgstr "編譯插斷。\n"
+msgstr "編譯終止。\n"
#: diagnostic.c:663
msgid "In file included from"
diff --git a/gcc/poly-int-types.h b/gcc/poly-int-types.h
index 5e04e63..302e5bf 100644
--- a/gcc/poly-int-types.h
+++ b/gcc/poly-int-types.h
@@ -81,6 +81,14 @@ typedef poly_int<NUM_POLY_INT_COEFFS, widest_int> poly_widest_int;
#define vector_element_size(SIZE, NELTS) \
(exact_div (SIZE, NELTS).to_constant ())
+/* Return the number of unroll times when a vector that has NELTS1 elements
+ is unrolled to vectors that have NELTS2 elements.
+
+ to_constant () is safe in this situation because the multiples of the
+ NELTS of two vectors are always constant-size scalars. */
+#define vector_unroll_factor(NELTS1, NELTS2) \
+ (exact_div (NELTS1, NELTS2).to_constant ())
+
/* Wrapper for poly_int arguments to target macros, so that if a target
doesn't need polynomial-sized modes, its header file can continue to
treat the argument as a normal constant. This should go away once
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index b953ffa..96a763d 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -2044,6 +2044,63 @@ constant_multiple_p (const poly_int_pod<N, Ca> &a,
return true;
}
+/* Return true if A is a constant multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+constant_multiple_p (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a.coeffs[0]) % NCb (b) != 0 || !a.is_constant ())
+ return false;
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+constant_multiple_p (Ca a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) int_type;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a) % NCb (b.coeffs[0]) != 0
+ || (a != int_type (0) && !b.is_constant ()))
+ return false;
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+constant_multiple_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) ICa;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+
+ if (NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0)
+ return false;
+
+ C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+ for (unsigned int i = 1; i < N; ++i)
+ if (b.coeffs[i] == ICb (0)
+ ? a.coeffs[i] != ICa (0)
+ : (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0
+ || NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != r))
+ return false;
+ return true;
+}
+
+
/* Return true if A is a multiple of B. */
template<typename Ca, typename Cb>
diff --git a/gcc/predict.c b/gcc/predict.c
index 5983889..3acbb86 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -243,7 +243,7 @@ probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
static bool
unlikely_executed_edge_p (edge e)
{
- return (e->count () == profile_count::zero ()
+ return (e->src->count == profile_count::zero ()
|| e->probability == profile_probability::never ())
|| (e->flags & (EDGE_EH | EDGE_FAKE));
}
@@ -260,13 +260,15 @@ probably_never_executed_edge_p (struct function *fun, edge e)
/* Return true if function FUN should always be optimized for size. */
-bool
+optimize_size_level
optimize_function_for_size_p (struct function *fun)
{
if (!fun || !fun->decl)
- return optimize_size;
+ return optimize_size ? OPTIMIZE_SIZE_MAX : OPTIMIZE_SIZE_NO;
cgraph_node *n = cgraph_node::get (fun->decl);
- return n && n->optimize_for_size_p ();
+ if (n)
+ return n->optimize_for_size_p ();
+ return OPTIMIZE_SIZE_NO;
}
/* Return true if function FUN should always be optimized for speed. */
@@ -289,11 +291,16 @@ function_optimization_type (struct function *fun)
/* Return TRUE if basic block BB should be optimized for size. */
-bool
+optimize_size_level
optimize_bb_for_size_p (const_basic_block bb)
{
- return (optimize_function_for_size_p (cfun)
- || (bb && !maybe_hot_bb_p (cfun, bb)));
+ enum optimize_size_level ret = optimize_function_for_size_p (cfun);
+
+ if (bb && ret < OPTIMIZE_SIZE_MAX && bb->count == profile_count::zero ())
+ ret = OPTIMIZE_SIZE_MAX;
+ if (bb && ret < OPTIMIZE_SIZE_BALANCED && !maybe_hot_bb_p (cfun, bb))
+ ret = OPTIMIZE_SIZE_BALANCED;
+ return ret;
}
/* Return TRUE if basic block BB should be optimized for speed. */
@@ -316,10 +323,16 @@ bb_optimization_type (const_basic_block bb)
/* Return TRUE if edge E should be optimized for size. */
-bool
+optimize_size_level
optimize_edge_for_size_p (edge e)
{
- return optimize_function_for_size_p (cfun) || !maybe_hot_edge_p (e);
+ enum optimize_size_level ret = optimize_function_for_size_p (cfun);
+
+ if (ret < OPTIMIZE_SIZE_MAX && unlikely_executed_edge_p (e))
+ ret = OPTIMIZE_SIZE_MAX;
+ if (ret < OPTIMIZE_SIZE_BALANCED && !maybe_hot_edge_p (e))
+ ret = OPTIMIZE_SIZE_BALANCED;
+ return ret;
}
/* Return TRUE if edge E should be optimized for speed. */
@@ -332,10 +345,13 @@ optimize_edge_for_speed_p (edge e)
/* Return TRUE if the current function is optimized for size. */
-bool
+optimize_size_level
optimize_insn_for_size_p (void)
{
- return optimize_function_for_size_p (cfun) || !crtl->maybe_hot_insn_p;
+ enum optimize_size_level ret = optimize_function_for_size_p (cfun);
+ if (ret < OPTIMIZE_SIZE_BALANCED && !crtl->maybe_hot_insn_p)
+ ret = OPTIMIZE_SIZE_BALANCED;
+ return ret;
}
/* Return TRUE if the current function is optimized for speed. */
@@ -348,7 +364,7 @@ optimize_insn_for_speed_p (void)
/* Return TRUE if LOOP should be optimized for size. */
-bool
+optimize_size_level
optimize_loop_for_size_p (class loop *loop)
{
return optimize_bb_for_size_p (loop->header);
@@ -392,10 +408,31 @@ optimize_loop_nest_for_speed_p (class loop *loop)
/* Return TRUE if nest rooted at LOOP should be optimized for size. */
-bool
+optimize_size_level
optimize_loop_nest_for_size_p (class loop *loop)
{
- return !optimize_loop_nest_for_speed_p (loop);
+ enum optimize_size_level ret = optimize_loop_for_size_p (loop);
+ class loop *l = loop;
+
+ l = loop->inner;
+ while (l && l != loop)
+ {
+ if (ret == OPTIMIZE_SIZE_NO)
+ break;
+ ret = MIN (optimize_loop_for_size_p (l), ret);
+ if (l->inner)
+ l = l->inner;
+ else if (l->next)
+ l = l->next;
+ else
+ {
+ while (l != loop && !l->next)
+ l = loop_outer (l);
+ if (l != loop)
+ l = l->next;
+ }
+ }
+ return ret;
}
/* Return true if edge E is likely to be well predictable by branch
@@ -2167,7 +2204,7 @@ predict_loops (void)
{
gimple *call_stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
if (gimple_code (call_stmt) == GIMPLE_ASSIGN
- && gimple_expr_code (call_stmt) == NOP_EXPR
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (call_stmt))
&& TREE_CODE (gimple_assign_rhs1 (call_stmt)) == SSA_NAME)
call_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (call_stmt));
if (gimple_call_internal_p (call_stmt, IFN_BUILTIN_EXPECT)
diff --git a/gcc/predict.h b/gcc/predict.h
index 274597e..b64d209 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -58,20 +58,20 @@ extern bool maybe_hot_bb_p (struct function *, const_basic_block);
extern bool maybe_hot_edge_p (edge);
extern bool probably_never_executed_bb_p (struct function *, const_basic_block);
extern bool probably_never_executed_edge_p (struct function *, edge);
-extern bool optimize_function_for_size_p (struct function *);
+extern enum optimize_size_level optimize_function_for_size_p (struct function *);
extern bool optimize_function_for_speed_p (struct function *);
extern optimization_type function_optimization_type (struct function *);
-extern bool optimize_bb_for_size_p (const_basic_block);
+extern enum optimize_size_level optimize_bb_for_size_p (const_basic_block);
extern bool optimize_bb_for_speed_p (const_basic_block);
extern optimization_type bb_optimization_type (const_basic_block);
-extern bool optimize_edge_for_size_p (edge);
+extern enum optimize_size_level optimize_edge_for_size_p (edge);
extern bool optimize_edge_for_speed_p (edge);
-extern bool optimize_insn_for_size_p (void);
+extern enum optimize_size_level optimize_insn_for_size_p (void);
extern bool optimize_insn_for_speed_p (void);
-extern bool optimize_loop_for_size_p (class loop *);
+extern enum optimize_size_level optimize_loop_for_size_p (class loop *);
extern bool optimize_loop_for_speed_p (class loop *);
extern bool optimize_loop_nest_for_speed_p (class loop *);
-extern bool optimize_loop_nest_for_size_p (class loop *);
+extern enum optimize_size_level optimize_loop_nest_for_size_p (class loop *);
extern bool predictable_edge_p (edge);
extern void rtl_profile_for_bb (basic_block);
extern void rtl_profile_for_edge (edge);
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 25265ef..c1d3c17 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -1260,9 +1260,6 @@ print_rtx_insn_vec (FILE *file, const vec<rtx_insn *> &vec)
It is also possible to obtain a string for a single pattern as a string
pointer, via str_pattern_slim, but this usage is discouraged. */
-/* For insns we print patterns, and for some patterns we print insns... */
-static void print_insn_with_notes (pretty_printer *, const rtx_insn *);
-
/* This recognizes rtx'en classified as expressions. These are always
represent some action on values or results of other expression, that
may be stored in objects representing values. */
@@ -2011,7 +2008,7 @@ print_insn (pretty_printer *pp, const rtx_insn *x, int verbose)
/* Pretty-print a slim dump of X (an insn) to PP, including any register
note attached to the instruction. */
-static void
+void
print_insn_with_notes (pretty_printer *pp, const rtx_insn *x)
{
pp_string (pp, print_rtx_head);
@@ -2139,7 +2136,7 @@ extern void debug_bb_slim (basic_block);
DEBUG_FUNCTION void
debug_bb_slim (basic_block bb)
{
- dump_bb (stderr, bb, 0, TDF_SLIM | TDF_BLOCKS);
+ debug_bb (bb, TDF_SLIM | TDF_BLOCKS);
}
extern void debug_bb_n_slim (int);
diff --git a/gcc/print-rtl.h b/gcc/print-rtl.h
index 09e5a51..cf801e8 100644
--- a/gcc/print-rtl.h
+++ b/gcc/print-rtl.h
@@ -84,6 +84,7 @@ extern void dump_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *,
extern void print_value (pretty_printer *, const_rtx, int);
extern void print_pattern (pretty_printer *, const_rtx, int);
extern void print_insn (pretty_printer *pp, const rtx_insn *x, int verbose);
+extern void print_insn_with_notes (pretty_printer *, const rtx_insn *);
extern void rtl_dump_bb_for_graph (pretty_printer *, basic_block);
extern const char *str_pattern_slim (const_rtx);
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index d1150e4..17c88f8 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -742,20 +742,26 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
}
if (code == CALL_EXPR)
{
- call_expr_arg_iterator iter;
- tree arg;
print_node (file, "fn", CALL_EXPR_FN (node), indent + 4);
print_node (file, "static_chain", CALL_EXPR_STATIC_CHAIN (node),
indent + 4);
- i = 0;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
+
+ call_expr_arg_iterator iter;
+ init_call_expr_arg_iterator (node, &iter);
+ while (more_call_expr_args_p (&iter))
{
/* Buffer big enough to format a 32-bit UINT_MAX into, plus
the text. */
char temp[15];
- sprintf (temp, "arg:%u", i);
- print_node (file, temp, arg, indent + 4);
- i++;
+ sprintf (temp, "arg:%u", iter.i);
+ tree arg = next_call_expr_arg (&iter);
+ if (arg)
+ print_node (file, temp, arg, indent + 4);
+ else
+ {
+ indent_to (file, indent + 4);
+ fprintf (file, "%s NULL", temp);
+ }
}
}
else
@@ -1046,7 +1052,7 @@ print_decl_identifier (FILE *file, tree decl, int flags)
if (flags & PRINT_DECL_ORIGIN)
{
- if (DECL_IS_BUILTIN (decl))
+ if (DECL_IS_UNDECLARED_BUILTIN (decl))
fputs ("<built-in>", file);
else
{
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index ee62f10..a473f33 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -80,30 +80,25 @@ empty_range_varying (irange &r, tree type,
return false;
}
-// Return TRUE if shifting by OP is undefined behavior, and set R to
-// the appropriate range.
+// Return false if shifting by OP is undefined behavior. Otherwise, return
+// true and the range it is to be shifted by. This allows trimming out of
+// undefined ranges, leaving only valid ranges if there are any.
static inline bool
-undefined_shift_range_check (irange &r, tree type, const irange &op)
+get_shift_range (irange &r, tree type, const irange &op)
{
if (op.undefined_p ())
- {
- r.set_undefined ();
- return true;
- }
+ return false;
- // Shifting by any values outside [0..prec-1], gets undefined
- // behavior from the shift operation. We cannot even trust
- // SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
- // shifts, and the operation at the tree level may be widened.
- if (wi::lt_p (op.lower_bound (), 0, TYPE_SIGN (op.type ()))
- || wi::ge_p (op.upper_bound (),
- TYPE_PRECISION (type), TYPE_SIGN (op.type ())))
- {
- r.set_varying (type);
- return true;
- }
- return false;
+ // Build valid range and intersect it with the shift range.
+ r = value_range (build_int_cst_type (op.type (), 0),
+ build_int_cst_type (op.type (), TYPE_PRECISION (type) - 1));
+ r.intersect (op);
+
+ // If there are no valid ranges in the shift range, returned false.
+ if (r.undefined_p ())
+ return false;
+ return true;
}
// Return TRUE if 0 is within [WMIN, WMAX].
@@ -428,9 +423,9 @@ operator_equal::fold_range (irange &r, tree type,
{
// If ranges do not intersect, we know the range is not equal,
// otherwise we don't know anything for sure.
- r = op1;
- r.intersect (op2);
- if (r.undefined_p ())
+ int_range_max tmp = op1;
+ tmp.intersect (op2);
+ if (tmp.undefined_p ())
r = range_false (type);
else
r = range_true_and_false (type);
@@ -513,9 +508,9 @@ operator_not_equal::fold_range (irange &r, tree type,
{
// If ranges do not intersect, we know the range is not equal,
// otherwise we don't know anything for sure.
- r = op1;
- r.intersect (op2);
- if (r.undefined_p ())
+ int_range_max tmp = op1;
+ tmp.intersect (op2);
+ if (tmp.undefined_p ())
r = range_true (type);
else
r = range_true_and_false (type);
@@ -1465,13 +1460,20 @@ operator_lshift::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2) const
{
- if (undefined_shift_range_check (r, type, op2))
- return true;
+ int_range_max shift_range;
+ if (!get_shift_range (shift_range, type, op2))
+ {
+ if (op2.undefined_p ())
+ r.set_undefined ();
+ else
+ r.set_varying (type);
+ return true;
+ }
// Transform left shifts by constants into multiplies.
- if (op2.singleton_p ())
+ if (shift_range.singleton_p ())
{
- unsigned shift = op2.lower_bound ().to_uhwi ();
+ unsigned shift = shift_range.lower_bound ().to_uhwi ();
wide_int tmp = wi::set_bit_in_zero (shift, TYPE_PRECISION (type));
int_range<1> mult (type, tmp, tmp);
@@ -1487,7 +1489,7 @@ operator_lshift::fold_range (irange &r, tree type,
}
else
// Otherwise, invoke the generic fold routine.
- return range_operator::fold_range (r, type, op1, op2);
+ return range_operator::fold_range (r, type, op1, shift_range);
}
void
@@ -1709,11 +1711,17 @@ operator_rshift::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2) const
{
- // Invoke the generic fold routine if not undefined..
- if (undefined_shift_range_check (r, type, op2))
- return true;
+ int_range_max shift;
+ if (!get_shift_range (shift, type, op2))
+ {
+ if (op2.undefined_p ())
+ r.set_undefined ();
+ else
+ r.set_varying (type);
+ return true;
+ }
- return range_operator::fold_range (r, type, op1, op2);
+ return range_operator::fold_range (r, type, op1, shift);
}
void
@@ -1842,6 +1850,31 @@ operator_cast::op1_range (irange &r, tree type,
tree lhs_type = lhs.type ();
gcc_checking_assert (types_compatible_p (op2.type(), type));
+ // If we are calculating a pointer, shortcut to what we really care about.
+ if (POINTER_TYPE_P (type))
+ {
+ // Conversion from other pointers or a constant (including 0/NULL)
+ // are straightforward.
+ if (POINTER_TYPE_P (lhs.type ())
+ || (lhs.singleton_p ()
+ && TYPE_PRECISION (lhs.type ()) >= TYPE_PRECISION (type)))
+ {
+ r = lhs;
+ range_cast (r, type);
+ }
+ else
+ {
+ // If the LHS is not a pointer nor a singleton, then it is
+ // either VARYING or non-zero.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ r.set_nonzero (type);
+ else
+ r.set_varying (type);
+ }
+ r.intersect (op2);
+ return true;
+ }
+
if (truncating_cast_p (op2, lhs))
{
if (lhs.varying_p ())
@@ -2163,6 +2196,14 @@ wi_optimize_and_or (irange &r,
else
gcc_unreachable ();
value_range_with_overflow (r, type, res_lb, res_ub);
+
+ // Furthermore, if the mask is non-zero, an IOR cannot contain zero.
+ if (code == BIT_IOR_EXPR && wi::ne_p (mask, 0))
+ {
+ int_range<2> tmp;
+ tmp.set_nonzero (type);
+ r.intersect (tmp);
+ }
return true;
}
@@ -2626,6 +2667,12 @@ public:
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const;
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs,
+ const irange &op2) const;
+ virtual bool op2_range (irange &r, tree type,
+ const irange &lhs,
+ const irange &op1) const;
} op_trunc_mod;
void
@@ -2672,6 +2719,65 @@ operator_trunc_mod::wi_fold (irange &r, tree type,
value_range_with_overflow (r, type, new_lb, new_ub);
}
+bool
+operator_trunc_mod::op1_range (irange &r, tree type,
+ const irange &lhs,
+ const irange &) const
+{
+ // PR 91029.
+ signop sign = TYPE_SIGN (type);
+ unsigned prec = TYPE_PRECISION (type);
+ // (a % b) >= x && x > 0 , then a >= x.
+ if (wi::gt_p (lhs.lower_bound (), 0, sign))
+ {
+ r = value_range (type, lhs.lower_bound (), wi::max_value (prec, sign));
+ return true;
+ }
+ // (a % b) <= x && x < 0 , then a <= x.
+ if (wi::lt_p (lhs.upper_bound (), 0, sign))
+ {
+ r = value_range (type, wi::min_value (prec, sign), lhs.upper_bound ());
+ return true;
+ }
+ return false;
+}
+
+bool
+operator_trunc_mod::op2_range (irange &r, tree type,
+ const irange &lhs,
+ const irange &) const
+{
+ // PR 91029.
+ signop sign = TYPE_SIGN (type);
+ unsigned prec = TYPE_PRECISION (type);
+ // (a % b) >= x && x > 0 , then b is in ~[-x, x] for signed
+ // or b > x for unsigned.
+ if (wi::gt_p (lhs.lower_bound (), 0, sign))
+ {
+ if (sign == SIGNED)
+ r = value_range (type, wi::neg (lhs.lower_bound ()),
+ lhs.lower_bound (), VR_ANTI_RANGE);
+ else if (wi::lt_p (lhs.lower_bound (), wi::max_value (prec, sign),
+ sign))
+ r = value_range (type, lhs.lower_bound () + 1,
+ wi::max_value (prec, sign));
+ else
+ return false;
+ return true;
+ }
+ // (a % b) <= x && x < 0 , then b is in ~[x, -x].
+ if (wi::lt_p (lhs.upper_bound (), 0, sign))
+ {
+ if (wi::gt_p (lhs.upper_bound (), wi::min_value (prec, sign), sign))
+ r = value_range (type, lhs.upper_bound (),
+ wi::neg (lhs.upper_bound ()), VR_ANTI_RANGE);
+ else
+ return false;
+ return true;
+ }
+ return false;
+}
+
class operator_logical_not : public range_operator
{
@@ -2706,27 +2812,21 @@ operator_logical_not::fold_range (irange &r, tree type,
if (empty_range_varying (r, type, lh, rh))
return true;
- if (lh.varying_p () || lh.undefined_p ())
- r = lh;
- else
- {
- r = lh;
- r.invert ();
- }
- gcc_checking_assert (lh.type() == type);
+ r = lh;
+ if (!lh.varying_p () && !lh.undefined_p ())
+ r.invert ();
+
return true;
}
bool
operator_logical_not::op1_range (irange &r,
- tree type ATTRIBUTE_UNUSED,
+ tree type,
const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2) const
{
- r = lhs;
- if (!lhs.varying_p () && !lhs.undefined_p ())
- r.invert ();
- return true;
+ // Logical NOT is involutary...do it again.
+ return fold_range (r, type, lhs, op2);
}
@@ -2749,6 +2849,9 @@ operator_bitwise_not::fold_range (irange &r, tree type,
if (empty_range_varying (r, type, lh, rh))
return true;
+ if (types_compatible_p (type, boolean_type_node))
+ return op_logical_not.fold_range (r, type, lh, rh);
+
// ~X is simply -1 - X.
int_range<1> minusone (type, wi::minus_one (TYPE_PRECISION (type)),
wi::minus_one (TYPE_PRECISION (type)));
@@ -2761,6 +2864,9 @@ operator_bitwise_not::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2) const
{
+ if (types_compatible_p (type, boolean_type_node))
+ return op_logical_not.op1_range (r, type, lhs, op2);
+
// ~X is -1 - X and since bitwise NOT is involutary...do it again.
return fold_range (r, type, lhs, op2);
}
@@ -3328,6 +3434,7 @@ pointer_table::pointer_table ()
set (GT_EXPR, op_gt);
set (GE_EXPR, op_ge);
set (SSA_NAME, op_identity);
+ set (INTEGER_CST, op_integer_cst);
set (ADDR_EXPR, op_addr);
set (NOP_EXPR, op_convert);
set (CONVERT_EXPR, op_convert);
@@ -3341,10 +3448,12 @@ pointer_table::pointer_table ()
range_operator *
range_op_handler (enum tree_code code, tree type)
{
- // First check if there is apointer specialization.
+ // First check if there is a pointer specialization.
if (POINTER_TYPE_P (type))
return pointer_tree_table[code];
- return integral_tree_table[code];
+ if (INTEGRAL_TYPE_P (type))
+ return integral_tree_table[code];
+ return NULL;
}
// Cast the range in R to TYPE.
@@ -3361,7 +3470,6 @@ range_cast (irange &r, tree type)
#if CHECKING_P
#include "selftest.h"
-#include "stor-layout.h"
namespace selftest
{
@@ -3369,400 +3477,21 @@ namespace selftest
#define UINT(N) build_int_cstu (unsigned_type_node, (N))
#define INT16(N) build_int_cst (short_integer_type_node, (N))
#define UINT16(N) build_int_cstu (short_unsigned_type_node, (N))
-#define INT64(N) build_int_cstu (long_long_integer_type_node, (N))
-#define UINT64(N) build_int_cstu (long_long_unsigned_type_node, (N))
-#define UINT128(N) build_int_cstu (u128_type, (N))
-#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N))
#define SCHAR(N) build_int_cst (signed_char_type_node, (N))
-
-static int_range<3>
-build_range3 (int a, int b, int c, int d, int e, int f)
-{
- int_range<3> i1 (INT (a), INT (b));
- int_range<3> i2 (INT (c), INT (d));
- int_range<3> i3 (INT (e), INT (f));
- i1.union_ (i2);
- i1.union_ (i3);
- return i1;
-}
-
-static void
-range3_tests ()
-{
- typedef int_range<3> int_range3;
- int_range3 r0, r1, r2;
- int_range3 i1, i2, i3;
-
- // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
- r0 = int_range3 (INT (10), INT (20));
- r1 = int_range3 (INT (5), INT (8));
- r0.union_ (r1);
- r1 = int_range3 (INT (1), INT (3));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20));
-
- // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
- r1 = int_range3 (INT (-5), INT (0));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20));
-
- // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
- r1 = int_range3 (INT (50), INT (60));
- r0 = int_range3 (INT (10), INT (20));
- r0.union_ (int_range3 (INT (30), INT (40)));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
- // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80].
- r1 = int_range3 (INT (70), INT (80));
- r0.union_ (r1);
-
- r2 = build_range3 (10, 20, 30, 40, 50, 60);
- r2.union_ (int_range3 (INT (70), INT (80)));
- ASSERT_TRUE (r0 == r2);
-
- // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
- r0 = build_range3 (10, 20, 30, 40, 50, 60);
- r1 = int_range3 (INT (6), INT (35));
- r0.union_ (r1);
- r1 = int_range3 (INT (6), INT (40));
- r1.union_ (int_range3 (INT (50), INT (60)));
- ASSERT_TRUE (r0 == r1);
-
- // [10,20][30,40][50,60] U [6,60] => [6,60].
- r0 = build_range3 (10, 20, 30, 40, 50, 60);
- r1 = int_range3 (INT (6), INT (60));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == int_range3 (INT (6), INT (60)));
-
- // [10,20][30,40][50,60] U [6,70] => [6,70].
- r0 = build_range3 (10, 20, 30, 40, 50, 60);
- r1 = int_range3 (INT (6), INT (70));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == int_range3 (INT (6), INT (70)));
-
- // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
- r0 = build_range3 (10, 20, 30, 40, 50, 60);
- r1 = int_range3 (INT (35), INT (70));
- r0.union_ (r1);
- r1 = int_range3 (INT (10), INT (20));
- r1.union_ (int_range3 (INT (30), INT (70)));
- ASSERT_TRUE (r0 == r1);
-
- // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
- r0 = build_range3 (10, 20, 30, 40, 50, 60);
- r1 = int_range3 (INT (15), INT (35));
- r0.union_ (r1);
- r1 = int_range3 (INT (10), INT (40));
- r1.union_ (int_range3 (INT (50), INT (60)));
- ASSERT_TRUE (r0 == r1);
-
- // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
- r0 = build_range3 (10, 20, 30, 40, 50, 60);
- r1 = int_range3 (INT (35), INT (35));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
-}
-
-static void
-int_range_max_tests ()
-{
- int_range_max big;
- unsigned int nrange;
-
- // Build a huge multi-range range.
- for (nrange = 0; nrange < 50; ++nrange)
- {
- int_range<1> tmp (INT (nrange*10), INT (nrange*10 + 5));
- big.union_ (tmp);
- }
- ASSERT_TRUE (big.num_pairs () == nrange);
-
- // Verify that we can copy it without loosing precision.
- int_range_max copy (big);
- ASSERT_TRUE (copy.num_pairs () == nrange);
-
- // Inverting it should produce one more sub-range.
- big.invert ();
- ASSERT_TRUE (big.num_pairs () == nrange + 1);
-
- int_range<1> tmp (INT (5), INT (37));
- big.intersect (tmp);
- ASSERT_TRUE (big.num_pairs () == 4);
-
- // Test that [10,10][20,20] does NOT contain 15.
- {
- int_range_max i1 (build_int_cst (integer_type_node, 10),
- build_int_cst (integer_type_node, 10));
- int_range_max i2 (build_int_cst (integer_type_node, 20),
- build_int_cst (integer_type_node, 20));
- i1.union_ (i2);
- ASSERT_FALSE (i1.contains_p (build_int_cst (integer_type_node, 15)));
- }
-
-}
-
-static void
-multi_precision_range_tests ()
-{
- // Test truncating copy to int_range<1>.
- int_range<3> big = build_range3 (10, 20, 30, 40, 50, 60);
- int_range<1> small = big;
- ASSERT_TRUE (small == int_range<1> (INT (10), INT (60)));
-
- // Test truncating copy to int_range<2>.
- int_range<2> medium = big;
- ASSERT_TRUE (!medium.undefined_p ());
-
- // Test that a truncating copy of [MIN,20][22,40][80,MAX]
- // ends up as a conservative anti-range of ~[21,21].
- big = int_range<3> (vrp_val_min (integer_type_node), INT (20));
- big.union_ (int_range<1> (INT (22), INT (40)));
- big.union_ (int_range<1> (INT (80), vrp_val_max (integer_type_node)));
- small = big;
- ASSERT_TRUE (small == int_range<1> (INT (21), INT (21), VR_ANTI_RANGE));
-
- // Copying a legacy symbolic to an int_range should normalize the
- // symbolic at copy time.
- {
- tree ssa = make_ssa_name (integer_type_node);
- value_range legacy_range (ssa, INT (25));
- int_range<2> copy = legacy_range;
- ASSERT_TRUE (copy == int_range<2> (vrp_val_min (integer_type_node),
- INT (25)));
-
- // Test that copying ~[abc_23, abc_23] to a multi-range yields varying.
- legacy_range = value_range (ssa, ssa, VR_ANTI_RANGE);
- copy = legacy_range;
- ASSERT_TRUE (copy.varying_p ());
- }
-
- range3_tests ();
-}
+#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N))
static void
-operator_tests ()
+range_op_cast_tests ()
{
- tree min = vrp_val_min (integer_type_node);
- tree max = vrp_val_max (integer_type_node);
- tree tiny = fold_build2 (PLUS_EXPR, integer_type_node, min,
- build_one_cst (integer_type_node));
- int_range_max res;
- int_range_max i1 (tiny, max);
- int_range_max i2 (build_int_cst (integer_type_node, 255),
- build_int_cst (integer_type_node, 255));
-
- // [MIN+1, MAX] = OP1 & 255: OP1 is VARYING
- op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
- ASSERT_TRUE (res == int_range<1> (integer_type_node));
-
- // VARYING = OP1 & 255: OP1 is VARYING
- i1 = int_range<1> (integer_type_node);
- op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
- ASSERT_TRUE (res == int_range<1> (integer_type_node));
-
- // Test that 0x808.... & 0x8.... still contains 0x8....
- // for a large set of numbers.
- {
- tree big_type = long_long_unsigned_type_node;
- // big_num = 0x808,0000,0000,0000
- tree big_num = fold_build2 (LSHIFT_EXPR, big_type,
- build_int_cst (big_type, 0x808),
- build_int_cst (big_type, 48));
- op_bitwise_and.fold_range (res, big_type,
- int_range <1> (big_type),
- int_range <1> (big_num, big_num));
- // val = 0x8,0000,0000,0000
- tree val = fold_build2 (LSHIFT_EXPR, big_type,
- build_int_cst (big_type, 0x8),
- build_int_cst (big_type, 48));
- ASSERT_TRUE (res.contains_p (val));
- }
-
- // unsigned: [3, MAX] = OP1 >> 1
- {
- int_range_max lhs (build_int_cst (unsigned_type_node, 3),
- TYPE_MAX_VALUE (unsigned_type_node));
- int_range_max one (build_one_cst (unsigned_type_node),
- build_one_cst (unsigned_type_node));
- int_range_max op1;
- op_rshift.op1_range (op1, unsigned_type_node, lhs, one);
- ASSERT_FALSE (op1.contains_p (UINT (3)));
- }
-
- // signed: [3, MAX] = OP1 >> 1
- {
- int_range_max lhs (INT (3), TYPE_MAX_VALUE (integer_type_node));
- int_range_max one (INT (1), INT (1));
- int_range_max op1;
- op_rshift.op1_range (op1, integer_type_node, lhs, one);
- ASSERT_FALSE (op1.contains_p (INT (-2)));
- }
-
- // This is impossible, so OP1 should be [].
- // signed: [MIN, MIN] = OP1 >> 1
- {
- int_range_max lhs (TYPE_MIN_VALUE (integer_type_node),
- TYPE_MIN_VALUE (integer_type_node));
- int_range_max one (INT (1), INT (1));
- int_range_max op1;
- op_rshift.op1_range (op1, integer_type_node, lhs, one);
- ASSERT_TRUE (op1.undefined_p ());
- }
-
- // signed: ~[-1] = OP1 >> 31
- if (TYPE_PRECISION (integer_type_node) > 31)
- {
- int_range_max lhs (INT (-1), INT (-1), VR_ANTI_RANGE);
- int_range_max shift (INT (31), INT (31));
- int_range_max op1;
- op_rshift.op1_range (op1, integer_type_node, lhs, shift);
- int_range_max negatives = range_negatives (integer_type_node);
- negatives.intersect (op1);
- ASSERT_TRUE (negatives.undefined_p ());
- }
-
- if (TYPE_PRECISION (unsigned_type_node) > 31)
- {
- // unsigned VARYING = op1 << 1 should be VARYING.
- int_range<2> lhs (unsigned_type_node);
- int_range<2> shift (INT (1), INT (1));
- int_range_max op1;
- op_lshift.op1_range (op1, unsigned_type_node, lhs, shift);
- ASSERT_TRUE (op1.varying_p ());
-
- // 0 = op1 << 1 should be [0,0], [0x8000000, 0x8000000].
- int_range<2> zero (UINT (0), UINT (0));
- op_lshift.op1_range (op1, unsigned_type_node, zero, shift);
- ASSERT_TRUE (op1.num_pairs () == 2);
- // Remove the [0,0] range.
- op1.intersect (zero);
- ASSERT_TRUE (op1.num_pairs () == 1);
- // op1 << 1 should be [0x8000,0x8000] << 1,
- // which should result in [0,0].
- int_range_max result;
- op_lshift.fold_range (result, unsigned_type_node, op1, shift);
- ASSERT_TRUE (result == zero);
- }
- // signed VARYING = op1 << 1 should be VARYING.
- if (TYPE_PRECISION (integer_type_node) > 31)
- {
- // unsigned VARYING = op1 << 1 hould be VARYING.
- int_range<2> lhs (integer_type_node);
- int_range<2> shift (INT (1), INT (1));
- int_range_max op1;
- op_lshift.op1_range (op1, integer_type_node, lhs, shift);
- ASSERT_TRUE (op1.varying_p ());
-
- // 0 = op1 << 1 should be [0,0], [0x8000000, 0x8000000].
- int_range<2> zero (INT (0), INT (0));
- op_lshift.op1_range (op1, integer_type_node, zero, shift);
- ASSERT_TRUE (op1.num_pairs () == 2);
- // Remove the [0,0] range.
- op1.intersect (zero);
- ASSERT_TRUE (op1.num_pairs () == 1);
- // op1 << 1 shuould be [0x8000,0x8000] << 1,
- // which should result in [0,0].
- int_range_max result;
- op_lshift.fold_range (result, unsigned_type_node, op1, shift);
- ASSERT_TRUE (result == zero);
- }
-}
-
-// Run all of the selftests within this file.
-
-void
-range_tests ()
-{
- tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
- int_range<1> i1, i2, i3;
- int_range<1> r0, r1, rold;
-
- // Test 1-bit signed integer union.
- // [-1,-1] U [0,0] = VARYING.
- tree one_bit_type = build_nonstandard_integer_type (1, 0);
- {
- tree one_bit_min = vrp_val_min (one_bit_type);
- tree one_bit_max = vrp_val_max (one_bit_type);
- int_range<2> min (one_bit_min, one_bit_min);
- int_range<2> max (one_bit_max, one_bit_max);
- max.union_ (min);
- ASSERT_TRUE (max.varying_p ());
- }
-
- // Test that NOT(255) is [0..254] in 8-bit land.
- int_range<1> not_255 (UCHAR (255), UCHAR (255), VR_ANTI_RANGE);
- ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254)));
-
- // Test that NOT(0) is [1..255] in 8-bit land.
- int_range<1> not_zero = range_nonzero (unsigned_char_type_node);
- ASSERT_TRUE (not_zero == int_range<1> (UCHAR (1), UCHAR (255)));
-
- // Check that [0,127][0x..ffffff80,0x..ffffff]
- // => ~[128, 0x..ffffff7f].
- r0 = int_range<1> (UINT128 (0), UINT128 (127));
- tree high = build_minus_one_cst (u128_type);
- // low = -1 - 127 => 0x..ffffff80.
- tree low = fold_build2 (MINUS_EXPR, u128_type, high, UINT128(127));
- r1 = int_range<1> (low, high); // [0x..ffffff80, 0x..ffffffff]
- // r0 = [0,127][0x..ffffff80,0x..fffffff].
- r0.union_ (r1);
- // r1 = [128, 0x..ffffff7f].
- r1 = int_range<1> (UINT128(128),
- fold_build2 (MINUS_EXPR, u128_type,
- build_minus_one_cst (u128_type),
- UINT128(128)));
- r0.invert ();
- ASSERT_TRUE (r0 == r1);
-
+ int_range<1> r0, r1, r2, rold;
r0.set_varying (integer_type_node);
- tree minint = wide_int_to_tree (integer_type_node, r0.lower_bound ());
tree maxint = wide_int_to_tree (integer_type_node, r0.upper_bound ());
+ // If a range is in any way outside of the range for the converted
+ // to range, default to the range for the new type.
r0.set_varying (short_integer_type_node);
tree minshort = wide_int_to_tree (short_integer_type_node, r0.lower_bound ());
tree maxshort = wide_int_to_tree (short_integer_type_node, r0.upper_bound ());
-
- r0.set_varying (unsigned_type_node);
- tree maxuint = wide_int_to_tree (unsigned_type_node, r0.upper_bound ());
-
- // Check that ~[0,5] => [6,MAX] for unsigned int.
- r0 = int_range<1> (UINT (0), UINT (5));
- r0.invert ();
- ASSERT_TRUE (r0 == int_range<1> (UINT(6), maxuint));
-
- // Check that ~[10,MAX] => [0,9] for unsigned int.
- r0 = int_range<1> (UINT(10), maxuint);
- r0.invert ();
- ASSERT_TRUE (r0 == int_range<1> (UINT (0), UINT (9)));
-
- // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
- r0 = int_range<1> (UINT128 (0), UINT128 (5), VR_ANTI_RANGE);
- r1 = int_range<1> (UINT128(6), build_minus_one_cst (u128_type));
- ASSERT_TRUE (r0 == r1);
-
- // Check that [~5] is really [-MIN,4][6,MAX].
- r0 = int_range<1> (INT (5), INT (5), VR_ANTI_RANGE);
- r1 = int_range<1> (minint, INT (4));
- r1.union_ (int_range<1> (INT (6), maxint));
- ASSERT_FALSE (r1.undefined_p ());
- ASSERT_TRUE (r0 == r1);
-
- r1 = int_range<1> (INT (5), INT (5));
- int_range<1> r2 (r1);
- ASSERT_TRUE (r1 == r2);
-
- r1 = int_range<1> (INT (5), INT (10));
-
- r1 = int_range<1> (integer_type_node,
- wi::to_wide (INT (5)), wi::to_wide (INT (10)));
- ASSERT_TRUE (r1.contains_p (INT (7)));
-
- r1 = int_range<1> (SCHAR (0), SCHAR (20));
- ASSERT_TRUE (r1.contains_p (SCHAR(15)));
- ASSERT_FALSE (r1.contains_p (SCHAR(300)));
-
- // If a range is in any way outside of the range for the converted
- // to range, default to the range for the new type.
if (TYPE_PRECISION (TREE_TYPE (maxint))
> TYPE_PRECISION (short_integer_type_node))
{
@@ -3852,25 +3581,6 @@ range_tests ()
TYPE_MAX_VALUE (short_unsigned_type_node));
ASSERT_TRUE (r0 == r1);
- // NOT([10,20]) ==> [-MIN,9][21,MAX].
- r0 = r1 = int_range<1> (INT (10), INT (20));
- r2 = int_range<1> (minint, INT(9));
- r2.union_ (int_range<1> (INT(21), maxint));
- ASSERT_FALSE (r2.undefined_p ());
- r1.invert ();
- ASSERT_TRUE (r1 == r2);
- // Test that NOT(NOT(x)) == x.
- r2.invert ();
- ASSERT_TRUE (r0 == r2);
-
- // Test that booleans and their inverse work as expected.
- r0 = range_zero (boolean_type_node);
- ASSERT_TRUE (r0 == int_range<1> (build_zero_cst (boolean_type_node),
- build_zero_cst (boolean_type_node)));
- r0.invert ();
- ASSERT_TRUE (r0 == int_range<1> (build_one_cst (boolean_type_node),
- build_one_cst (boolean_type_node)));
-
// Casting NONZERO to a narrower type will wrap/overflow so
// it's just the entire range for the narrower type.
//
@@ -3897,84 +3607,153 @@ range_tests ()
r2 = int_range<1> (INT (1), INT (32767));
r1.union_ (r2);
ASSERT_TRUE (r0 == r1);
+}
- // Make sure NULL and non-NULL of pointer types work, and that
- // inverses of them are consistent.
- tree voidp = build_pointer_type (void_type_node);
- r0 = range_zero (voidp);
- r1 = r0;
- r0.invert ();
- r0.invert ();
- ASSERT_TRUE (r0 == r1);
+static void
+range_op_lshift_tests ()
+{
+ // Test that 0x808.... & 0x8.... still contains 0x8....
+ // for a large set of numbers.
+ {
+ int_range_max res;
+ tree big_type = long_long_unsigned_type_node;
+ // big_num = 0x808,0000,0000,0000
+ tree big_num = fold_build2 (LSHIFT_EXPR, big_type,
+ build_int_cst (big_type, 0x808),
+ build_int_cst (big_type, 48));
+ op_bitwise_and.fold_range (res, big_type,
+ int_range <1> (big_type),
+ int_range <1> (big_num, big_num));
+ // val = 0x8,0000,0000,0000
+ tree val = fold_build2 (LSHIFT_EXPR, big_type,
+ build_int_cst (big_type, 0x8),
+ build_int_cst (big_type, 48));
+ ASSERT_TRUE (res.contains_p (val));
+ }
- // [10,20] U [15, 30] => [10, 30].
- r0 = int_range<1> (INT (10), INT (20));
- r1 = int_range<1> (INT (15), INT (30));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (30)));
-
- // [15,40] U [] => [15,40].
- r0 = int_range<1> (INT (15), INT (40));
- r1.set_undefined ();
- r0.union_ (r1);
- ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (40)));
-
- // [10,20] U [10,10] => [10,20].
- r0 = int_range<1> (INT (10), INT (20));
- r1 = int_range<1> (INT (10), INT (10));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (20)));
-
- // [10,20] U [9,9] => [9,20].
- r0 = int_range<1> (INT (10), INT (20));
- r1 = int_range<1> (INT (9), INT (9));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == int_range<1> (INT (9), INT (20)));
-
- // [10,20] ^ [15,30] => [15,20].
- r0 = int_range<1> (INT (10), INT (20));
- r1 = int_range<1> (INT (15), INT (30));
- r0.intersect (r1);
- ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (20)));
-
- // Test the internal sanity of wide_int's wrt HWIs.
- ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node),
- TYPE_SIGN (boolean_type_node))
- == wi::uhwi (1, TYPE_PRECISION (boolean_type_node)));
-
- // Test zero_p().
- r0 = int_range<1> (INT (0), INT (0));
- ASSERT_TRUE (r0.zero_p ());
-
- // Test nonzero_p().
- r0 = int_range<1> (INT (0), INT (0));
- r0.invert ();
- ASSERT_TRUE (r0.nonzero_p ());
-
- // test legacy interaction
- // r0 = ~[1,1]
- r0 = int_range<1> (UINT (1), UINT (1), VR_ANTI_RANGE);
- // r1 = ~[3,3]
- r1 = int_range<1> (UINT (3), UINT (3), VR_ANTI_RANGE);
-
- // vv = [0,0][2,2][4, MAX]
- int_range<3> vv = r0;
- vv.intersect (r1);
-
- ASSERT_TRUE (vv.contains_p (UINT (2)));
- ASSERT_TRUE (vv.num_pairs () == 3);
-
- // create r0 as legacy [1,1]
- r0 = int_range<1> (UINT (1), UINT (1));
- // And union it with [0,0][2,2][4,MAX] multi range
- r0.union_ (vv);
- // The result should be [0,2][4,MAX], or ~[3,3] but it must contain 2
- ASSERT_TRUE (r0.contains_p (UINT (2)));
-
-
- multi_precision_range_tests ();
- int_range_max_tests ();
- operator_tests ();
+ if (TYPE_PRECISION (unsigned_type_node) > 31)
+ {
+ // unsigned VARYING = op1 << 1 should be VARYING.
+ int_range<2> lhs (unsigned_type_node);
+ int_range<2> shift (INT (1), INT (1));
+ int_range_max op1;
+ op_lshift.op1_range (op1, unsigned_type_node, lhs, shift);
+ ASSERT_TRUE (op1.varying_p ());
+
+ // 0 = op1 << 1 should be [0,0], [0x8000000, 0x8000000].
+ int_range<2> zero (UINT (0), UINT (0));
+ op_lshift.op1_range (op1, unsigned_type_node, zero, shift);
+ ASSERT_TRUE (op1.num_pairs () == 2);
+ // Remove the [0,0] range.
+ op1.intersect (zero);
+ ASSERT_TRUE (op1.num_pairs () == 1);
+ // op1 << 1 should be [0x8000,0x8000] << 1,
+ // which should result in [0,0].
+ int_range_max result;
+ op_lshift.fold_range (result, unsigned_type_node, op1, shift);
+ ASSERT_TRUE (result == zero);
+ }
+ // signed VARYING = op1 << 1 should be VARYING.
+ if (TYPE_PRECISION (integer_type_node) > 31)
+ {
+ // unsigned VARYING = op1 << 1 hould be VARYING.
+ int_range<2> lhs (integer_type_node);
+ int_range<2> shift (INT (1), INT (1));
+ int_range_max op1;
+ op_lshift.op1_range (op1, integer_type_node, lhs, shift);
+ ASSERT_TRUE (op1.varying_p ());
+
+ // 0 = op1 << 1 should be [0,0], [0x8000000, 0x8000000].
+ int_range<2> zero (INT (0), INT (0));
+ op_lshift.op1_range (op1, integer_type_node, zero, shift);
+ ASSERT_TRUE (op1.num_pairs () == 2);
+ // Remove the [0,0] range.
+ op1.intersect (zero);
+ ASSERT_TRUE (op1.num_pairs () == 1);
+ // op1 << 1 shuould be [0x8000,0x8000] << 1,
+ // which should result in [0,0].
+ int_range_max result;
+ op_lshift.fold_range (result, unsigned_type_node, op1, shift);
+ ASSERT_TRUE (result == zero);
+ }
+}
+
+static void
+range_op_rshift_tests ()
+{
+ // unsigned: [3, MAX] = OP1 >> 1
+ {
+ int_range_max lhs (build_int_cst (unsigned_type_node, 3),
+ TYPE_MAX_VALUE (unsigned_type_node));
+ int_range_max one (build_one_cst (unsigned_type_node),
+ build_one_cst (unsigned_type_node));
+ int_range_max op1;
+ op_rshift.op1_range (op1, unsigned_type_node, lhs, one);
+ ASSERT_FALSE (op1.contains_p (UINT (3)));
+ }
+
+ // signed: [3, MAX] = OP1 >> 1
+ {
+ int_range_max lhs (INT (3), TYPE_MAX_VALUE (integer_type_node));
+ int_range_max one (INT (1), INT (1));
+ int_range_max op1;
+ op_rshift.op1_range (op1, integer_type_node, lhs, one);
+ ASSERT_FALSE (op1.contains_p (INT (-2)));
+ }
+
+ // This is impossible, so OP1 should be [].
+ // signed: [MIN, MIN] = OP1 >> 1
+ {
+ int_range_max lhs (TYPE_MIN_VALUE (integer_type_node),
+ TYPE_MIN_VALUE (integer_type_node));
+ int_range_max one (INT (1), INT (1));
+ int_range_max op1;
+ op_rshift.op1_range (op1, integer_type_node, lhs, one);
+ ASSERT_TRUE (op1.undefined_p ());
+ }
+
+ // signed: ~[-1] = OP1 >> 31
+ if (TYPE_PRECISION (integer_type_node) > 31)
+ {
+ int_range_max lhs (INT (-1), INT (-1), VR_ANTI_RANGE);
+ int_range_max shift (INT (31), INT (31));
+ int_range_max op1;
+ op_rshift.op1_range (op1, integer_type_node, lhs, shift);
+ int_range_max negatives = range_negatives (integer_type_node);
+ negatives.intersect (op1);
+ ASSERT_TRUE (negatives.undefined_p ());
+ }
+}
+
+static void
+range_op_bitwise_and_tests ()
+{
+ int_range_max res;
+ tree min = vrp_val_min (integer_type_node);
+ tree max = vrp_val_max (integer_type_node);
+ tree tiny = fold_build2 (PLUS_EXPR, integer_type_node, min,
+ build_one_cst (integer_type_node));
+ int_range_max i1 (tiny, max);
+ int_range_max i2 (build_int_cst (integer_type_node, 255),
+ build_int_cst (integer_type_node, 255));
+
+ // [MIN+1, MAX] = OP1 & 255: OP1 is VARYING
+ op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
+ ASSERT_TRUE (res == int_range<1> (integer_type_node));
+
+ // VARYING = OP1 & 255: OP1 is VARYING
+ i1 = int_range<1> (integer_type_node);
+ op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
+ ASSERT_TRUE (res == int_range<1> (integer_type_node));
+}
+
+void
+range_op_tests ()
+{
+ range_op_rshift_tests ();
+ range_op_lshift_tests ();
+ range_op_bitwise_and_tests ();
+ range_op_cast_tests ();
}
} // namespace selftest
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index 3ec83a60..2922af5 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -77,12 +77,12 @@ struct iterator_group {
/* Treat the given string as the name of a standard mode, etc., and
return its integer value. */
- int (*find_builtin) (const char *);
+ HOST_WIDE_INT (*find_builtin) (const char *);
/* Make the given rtx use the iterator value given by the third argument.
If the iterator applies to operands, the second argument gives the
operand index, otherwise it is ignored. */
- void (*apply_iterator) (rtx, unsigned int, int);
+ void (*apply_iterator) (rtx, unsigned int, HOST_WIDE_INT);
/* Return the C token for the given standard mode, code, etc. */
const char *(*get_c_token) (int);
@@ -139,7 +139,7 @@ static void one_time_initialization (void);
/* Global singleton. */
rtx_reader *rtx_reader_ptr = NULL;
-
+
/* The mode and code iterator structures. */
static struct iterator_group modes, codes, ints, substs;
@@ -152,9 +152,49 @@ static vec<iterator_use> iterator_uses;
/* The list of all attribute uses in the current rtx. */
static vec<attribute_use> attribute_uses;
+/* Provide a version of a function to read a long long if the system does
+ not provide one. */
+#if (HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG \
+ && !HAVE_DECL_ATOLL \
+ && !defined (HAVE_ATOQ))
+HOST_WIDE_INT atoll (const char *);
+
+HOST_WIDE_INT
+atoll (const char *p)
+{
+ int neg = 0;
+ HOST_WIDE_INT tmp_wide;
+
+ while (ISSPACE (*p))
+ p++;
+ if (*p == '-')
+ neg = 1, p++;
+ else if (*p == '+')
+ p++;
+
+ tmp_wide = 0;
+ while (ISDIGIT (*p))
+ {
+ HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
+ if (new_wide < tmp_wide)
+ {
+ /* Return INT_MAX equiv on overflow. */
+ tmp_wide = HOST_WIDE_INT_M1U >> 1;
+ break;
+ }
+ tmp_wide = new_wide;
+ p++;
+ }
+
+ if (neg)
+ tmp_wide = -tmp_wide;
+ return tmp_wide;
+}
+#endif
+
/* Implementations of the iterator_group callbacks for modes. */
-static int
+static HOST_WIDE_INT
find_mode (const char *name)
{
int i;
@@ -167,7 +207,7 @@ find_mode (const char *name)
}
static void
-apply_mode_iterator (rtx x, unsigned int, int mode)
+apply_mode_iterator (rtx x, unsigned int, HOST_WIDE_INT mode)
{
PUT_MODE (x, (machine_mode) mode);
}
@@ -215,7 +255,7 @@ maybe_find_code (const char *name)
/* Implementations of the iterator_group callbacks for codes. */
-static int
+static HOST_WIDE_INT
find_code (const char *name)
{
rtx_code code = maybe_find_code (name);
@@ -225,7 +265,7 @@ find_code (const char *name)
}
static void
-apply_code_iterator (rtx x, unsigned int, int code)
+apply_code_iterator (rtx x, unsigned int, HOST_WIDE_INT code)
{
PUT_CODE (x, (enum rtx_code) code);
}
@@ -245,20 +285,52 @@ get_code_token (int code)
we have to accept any int as valid. No cross-checking can
be done. */
-static int
+static HOST_WIDE_INT
find_int (const char *name)
{
+ HOST_WIDE_INT tmp;
+
validate_const_int (name);
- return atoi (name);
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+ tmp = atoi (name);
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ tmp = atol (name);
+#else
+ /* Prefer atoll over atoq, since the former is in the ISO C99 standard.
+ But prefer not to use our hand-rolled function above either. */
+#if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ)
+ tmp = atoll (name);
+#else
+ tmp = atoq (name);
+#endif
+#endif
+#endif
+ return tmp;
}
static void
-apply_int_iterator (rtx x, unsigned int index, int value)
+apply_int_iterator (rtx x, unsigned int index, HOST_WIDE_INT value)
{
- if (GET_CODE (x) == SUBREG)
- SUBREG_BYTE (x) = value;
- else
- XINT (x, index) = value;
+ RTX_CODE code = GET_CODE (x);
+ const char *format_ptr = GET_RTX_FORMAT (code);
+
+ switch (format_ptr[index])
+ {
+ case 'i':
+ case 'n':
+ XINT (x, index) = value;
+ break;
+ case 'w':
+ XWINT (x, index) = value;
+ break;
+ case 'p':
+ gcc_assert (code == SUBREG);
+ SUBREG_BYTE (x) = value;
+ break;
+ default:
+ gcc_unreachable ();
+ }
}
static const char *
@@ -279,7 +351,7 @@ get_int_token (int value)
applied. If such attribute has already been added, then no the
routine has no effect. */
static void
-apply_subst_iterator (rtx rt, unsigned int, int value)
+apply_subst_iterator (rtx rt, unsigned int, HOST_WIDE_INT value)
{
rtx new_attr;
rtvec attrs_vec, new_attrs_vec;
@@ -1003,44 +1075,6 @@ initialize_iterators (void)
}
}
-/* Provide a version of a function to read a long long if the system does
- not provide one. */
-#if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !HAVE_DECL_ATOLL && !defined(HAVE_ATOQ)
-HOST_WIDE_INT atoll (const char *);
-
-HOST_WIDE_INT
-atoll (const char *p)
-{
- int neg = 0;
- HOST_WIDE_INT tmp_wide;
-
- while (ISSPACE (*p))
- p++;
- if (*p == '-')
- neg = 1, p++;
- else if (*p == '+')
- p++;
-
- tmp_wide = 0;
- while (ISDIGIT (*p))
- {
- HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
- if (new_wide < tmp_wide)
- {
- /* Return INT_MAX equiv on overflow. */
- tmp_wide = HOST_WIDE_INT_M1U >> 1;
- break;
- }
- tmp_wide = new_wide;
- p++;
- }
-
- if (neg)
- tmp_wide = -tmp_wide;
- return tmp_wide;
-}
-#endif
-
#ifdef GENERATOR_FILE
/* Process a define_conditions directive, starting with the optional
@@ -1617,6 +1651,16 @@ rtx_reader::read_rtx_code (const char *code_name)
return return_rtx;
}
+ /* Handle "const_double_zero". */
+ if (strcmp (code_name, "const_double_zero") == 0)
+ {
+ code = CONST_DOUBLE;
+ return_rtx = rtx_alloc (code);
+ memset (return_rtx, 0, RTX_CODE_SIZE (code));
+ PUT_CODE (return_rtx, code);
+ return return_rtx;
+ }
+
/* If we end up with an insn expression then we free this space below. */
return_rtx = rtx_alloc_for_name (code_name);
code = GET_CODE (return_rtx);
@@ -1939,32 +1983,9 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
}
break;
- case 'w':
- {
- HOST_WIDE_INT tmp_wide;
- read_name (&name);
- validate_const_int (name.string);
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- tmp_wide = atoi (name.string);
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
- tmp_wide = atol (name.string);
-#else
- /* Prefer atoll over atoq, since the former is in the ISO C99 standard.
- But prefer not to use our hand-rolled function above either. */
-#if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ)
- tmp_wide = atoll (name.string);
-#else
- tmp_wide = atoq (name.string);
-#endif
-#endif
-#endif
- XWINT (return_rtx, idx) = tmp_wide;
- }
- break;
-
case 'i':
case 'n':
+ case 'w':
case 'p':
{
/* Can be an iterator or an integer constant. */
diff --git a/gcc/recog.c b/gcc/recog.c
index d3552ec..e9aa1ba 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -183,6 +183,7 @@ struct change_t
{
rtx object;
int old_code;
+ int old_len;
bool unshare;
rtx *loc;
rtx old;
@@ -192,10 +193,13 @@ static change_t *changes;
static int changes_allocated;
static int num_changes = 0;
+static int temporarily_undone_changes = 0;
/* Validate a proposed change to OBJECT. LOC is the location in the rtl
- at which NEW_RTX will be placed. If OBJECT is zero, no validation is done,
- the change is simply made.
+ at which NEW_RTX will be placed. If NEW_LEN is >= 0, XVECLEN (NEW_RTX, 0)
+ will also be changed to NEW_LEN, which is no greater than the current
+ XVECLEN. If OBJECT is zero, no validation is done, the change is
+ simply made.
Two types of objects are supported: If OBJECT is a MEM, memory_address_p
will be called with the address and mode as parameters. If OBJECT is
@@ -212,14 +216,26 @@ static int num_changes = 0;
Otherwise, perform the change and return 1. */
static bool
-validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group, bool unshare)
+validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group,
+ bool unshare, int new_len = -1)
{
+ gcc_assert (temporarily_undone_changes == 0);
rtx old = *loc;
- if (old == new_rtx || rtx_equal_p (old, new_rtx))
+ /* Single-element parallels aren't valid and won't match anything.
+ Replace them with the single element. */
+ if (new_len == 1 && GET_CODE (new_rtx) == PARALLEL)
+ {
+ new_rtx = XVECEXP (new_rtx, 0, 0);
+ new_len = -1;
+ }
+
+ if ((old == new_rtx || rtx_equal_p (old, new_rtx))
+ && (new_len < 0 || XVECLEN (new_rtx, 0) == new_len))
return 1;
- gcc_assert (in_group != 0 || num_changes == 0);
+ gcc_assert ((in_group != 0 || num_changes == 0)
+ && (new_len < 0 || new_rtx == *loc));
*loc = new_rtx;
@@ -239,8 +255,12 @@ validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group, bool unshar
changes[num_changes].object = object;
changes[num_changes].loc = loc;
changes[num_changes].old = old;
+ changes[num_changes].old_len = (new_len >= 0 ? XVECLEN (new_rtx, 0) : -1);
changes[num_changes].unshare = unshare;
+ if (new_len >= 0)
+ XVECLEN (new_rtx, 0) = new_len;
+
if (object && !MEM_P (object))
{
/* Set INSN_CODE to force rerecognition of insn. Save old code in
@@ -278,6 +298,14 @@ validate_unshare_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
return validate_change_1 (object, loc, new_rtx, in_group, true);
}
+/* Change XVECLEN (*LOC, 0) to NEW_LEN. OBJECT, IN_GROUP and the return
+ value are as for validate_change_1. */
+
+bool
+validate_change_xveclen (rtx object, rtx *loc, int new_len, bool in_group)
+{
+ return validate_change_1 (object, loc, *loc, in_group, false, new_len);
+}
/* Keep X canonicalized if some changes have made it non-canonical; only
modifies the operands of X, not (for example) its code. Simplifications
@@ -408,10 +436,7 @@ verify_changes (int num)
changes[i].old
&& REG_P (changes[i].old)
&& asm_noperands (PATTERN (object)) > 0
- && REG_EXPR (changes[i].old) != NULL_TREE
- && HAS_DECL_ASSEMBLER_NAME_P (REG_EXPR (changes[i].old))
- && DECL_ASSEMBLER_NAME_SET_P (REG_EXPR (changes[i].old))
- && DECL_REGISTER (REG_EXPR (changes[i].old)))
+ && register_asm_p (changes[i].old))
{
/* Don't allow changes of hard register operands to inline
assemblies if they have been defined as register asm ("x"). */
@@ -483,6 +508,7 @@ confirm_change_group (void)
int i;
rtx last_object = NULL;
+ gcc_assert (temporarily_undone_changes == 0);
for (i = 0; i < num_changes; i++)
{
rtx object = changes[i].object;
@@ -538,19 +564,67 @@ num_validated_changes (void)
void
cancel_changes (int num)
{
+ gcc_assert (temporarily_undone_changes == 0);
int i;
/* Back out all the changes. Do this in the opposite order in which
they were made. */
for (i = num_changes - 1; i >= num; i--)
{
- *changes[i].loc = changes[i].old;
+ if (changes[i].old_len >= 0)
+ XVECLEN (*changes[i].loc, 0) = changes[i].old_len;
+ else
+ *changes[i].loc = changes[i].old;
if (changes[i].object && !MEM_P (changes[i].object))
INSN_CODE (changes[i].object) = changes[i].old_code;
}
num_changes = num;
}
+/* Swap the status of change NUM from being applied to not being applied,
+ or vice versa. */
+
+static void
+swap_change (int num)
+{
+ if (changes[num].old_len >= 0)
+ std::swap (XVECLEN (*changes[num].loc, 0), changes[num].old_len);
+ else
+ std::swap (*changes[num].loc, changes[num].old);
+ if (changes[num].object && !MEM_P (changes[num].object))
+ std::swap (INSN_CODE (changes[num].object), changes[num].old_code);
+}
+
+/* Temporarily undo all the changes numbered NUM and up, with a view
+ to reapplying them later. The next call to the changes machinery
+ must be:
+
+ redo_changes (NUM)
+
+ otherwise things will end up in an invalid state. */
+
+void
+temporarily_undo_changes (int num)
+{
+ gcc_assert (temporarily_undone_changes == 0 && num <= num_changes);
+ for (int i = num_changes - 1; i >= num; i--)
+ swap_change (i);
+ temporarily_undone_changes = num_changes - num;
+}
+
+/* Redo the changes that were temporarily undone by:
+
+ temporarily_undo_changes (NUM). */
+
+void
+redo_changes (int num)
+{
+ gcc_assert (temporarily_undone_changes == num_changes - num);
+ for (int i = num; i < num_changes; ++i)
+ swap_change (i);
+ temporarily_undone_changes = 0;
+}
+
/* Reduce conditional compilation elsewhere. */
/* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
rtx. */
@@ -922,7 +996,403 @@ validate_simplify_insn (rtx_insn *insn)
}
return ((num_changes_pending () > 0) && (apply_change_group () > 0));
}
-
+
+/* Try to process the address of memory expression MEM. Return true on
+ success; leave the caller to clean up on failure. */
+
+bool
+insn_propagation::apply_to_mem_1 (rtx mem)
+{
+ auto old_num_changes = num_validated_changes ();
+ mem_depth += 1;
+ bool res = apply_to_rvalue_1 (&XEXP (mem, 0));
+ mem_depth -= 1;
+ if (!res)
+ return false;
+
+ if (old_num_changes != num_validated_changes ()
+ && should_check_mems
+ && !check_mem (old_num_changes, mem))
+ return false;
+
+ return true;
+}
+
+/* Try to process the rvalue expression at *LOC. Return true on success;
+ leave the caller to clean up on failure. */
+
+bool
+insn_propagation::apply_to_rvalue_1 (rtx *loc)
+{
+ rtx x = *loc;
+ enum rtx_code code = GET_CODE (x);
+ machine_mode mode = GET_MODE (x);
+
+ auto old_num_changes = num_validated_changes ();
+ if (from && GET_CODE (x) == GET_CODE (from) && rtx_equal_p (x, from))
+ {
+ /* Don't replace register asms in asm statements; we mustn't
+ change the user's register allocation. */
+ if (REG_P (x)
+ && HARD_REGISTER_P (x)
+ && register_asm_p (x)
+ && asm_noperands (PATTERN (insn)) > 0)
+ return false;
+
+ if (should_unshare)
+ validate_unshare_change (insn, loc, to, 1);
+ else
+ validate_change (insn, loc, to, 1);
+ if (mem_depth && !REG_P (to) && !CONSTANT_P (to))
+ {
+ /* We're substituting into an address, but TO will have the
+ form expected outside an address. Canonicalize it if
+ necessary. */
+ insn_propagation subprop (insn);
+ subprop.mem_depth += 1;
+ if (!subprop.apply_to_rvalue (loc))
+ gcc_unreachable ();
+ if (should_unshare
+ && num_validated_changes () != old_num_changes + 1)
+ {
+ /* TO is owned by someone else, so create a copy and
+ return TO to its original form. */
+ rtx to = copy_rtx (*loc);
+ cancel_changes (old_num_changes);
+ validate_change (insn, loc, to, 1);
+ }
+ }
+ num_replacements += 1;
+ should_unshare = true;
+ result_flags |= UNSIMPLIFIED;
+ return true;
+ }
+
+ /* Recursively apply the substitution and see if we can simplify
+ the result. This specifically shouldn't use simplify_gen_* for
+ speculative simplifications, since we want to avoid generating new
+ expressions where possible. */
+ auto old_result_flags = result_flags;
+ rtx newx = NULL_RTX;
+ bool recurse_p = false;
+ switch (GET_RTX_CLASS (code))
+ {
+ case RTX_UNARY:
+ {
+ machine_mode op0_mode = GET_MODE (XEXP (x, 0));
+ if (!apply_to_rvalue_1 (&XEXP (x, 0)))
+ return false;
+ if (from && old_num_changes == num_validated_changes ())
+ return true;
+
+ newx = simplify_unary_operation (code, mode, XEXP (x, 0), op0_mode);
+ break;
+ }
+
+ case RTX_BIN_ARITH:
+ case RTX_COMM_ARITH:
+ {
+ if (!apply_to_rvalue_1 (&XEXP (x, 0))
+ || !apply_to_rvalue_1 (&XEXP (x, 1)))
+ return false;
+ if (from && old_num_changes == num_validated_changes ())
+ return true;
+
+ if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
+ && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
+ newx = simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0));
+ else
+ newx = simplify_binary_operation (code, mode,
+ XEXP (x, 0), XEXP (x, 1));
+ break;
+ }
+
+ case RTX_COMPARE:
+ case RTX_COMM_COMPARE:
+ {
+ machine_mode op_mode = (GET_MODE (XEXP (x, 0)) != VOIDmode
+ ? GET_MODE (XEXP (x, 0))
+ : GET_MODE (XEXP (x, 1)));
+ if (!apply_to_rvalue_1 (&XEXP (x, 0))
+ || !apply_to_rvalue_1 (&XEXP (x, 1)))
+ return false;
+ if (from && old_num_changes == num_validated_changes ())
+ return true;
+
+ newx = simplify_relational_operation (code, mode, op_mode,
+ XEXP (x, 0), XEXP (x, 1));
+ break;
+ }
+
+ case RTX_TERNARY:
+ case RTX_BITFIELD_OPS:
+ {
+ machine_mode op0_mode = GET_MODE (XEXP (x, 0));
+ if (!apply_to_rvalue_1 (&XEXP (x, 0))
+ || !apply_to_rvalue_1 (&XEXP (x, 1))
+ || !apply_to_rvalue_1 (&XEXP (x, 2)))
+ return false;
+ if (from && old_num_changes == num_validated_changes ())
+ return true;
+
+ newx = simplify_ternary_operation (code, mode, op0_mode,
+ XEXP (x, 0), XEXP (x, 1),
+ XEXP (x, 2));
+ break;
+ }
+
+ case RTX_EXTRA:
+ if (code == SUBREG)
+ {
+ machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+ if (!apply_to_rvalue_1 (&SUBREG_REG (x)))
+ return false;
+ if (from && old_num_changes == num_validated_changes ())
+ return true;
+
+ rtx inner = SUBREG_REG (x);
+ newx = simplify_subreg (mode, inner, inner_mode, SUBREG_BYTE (x));
+ /* Reject the same cases that simplify_gen_subreg would. */
+ if (!newx
+ && (GET_CODE (inner) == SUBREG
+ || GET_CODE (inner) == CONCAT
+ || GET_MODE (inner) == VOIDmode
+ || !validate_subreg (mode, inner_mode,
+ inner, SUBREG_BYTE (x))))
+ {
+ failure_reason = "would create an invalid subreg";
+ return false;
+ }
+ break;
+ }
+ else
+ recurse_p = true;
+ break;
+
+ case RTX_OBJ:
+ if (code == LO_SUM)
+ {
+ if (!apply_to_rvalue_1 (&XEXP (x, 0))
+ || !apply_to_rvalue_1 (&XEXP (x, 1)))
+ return false;
+ if (from && old_num_changes == num_validated_changes ())
+ return true;
+
+ /* (lo_sum (high x) y) -> y where x and y have the same base. */
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+ if (GET_CODE (op0) == HIGH)
+ {
+ rtx base0, base1, offset0, offset1;
+ split_const (XEXP (op0, 0), &base0, &offset0);
+ split_const (op1, &base1, &offset1);
+ if (rtx_equal_p (base0, base1))
+ newx = op1;
+ }
+ }
+ else if (code == REG)
+ {
+ if (from && REG_P (from) && reg_overlap_mentioned_p (x, from))
+ {
+ failure_reason = "inexact register overlap";
+ return false;
+ }
+ }
+ else if (code == MEM)
+ return apply_to_mem_1 (x);
+ else
+ recurse_p = true;
+ break;
+
+ case RTX_CONST_OBJ:
+ break;
+
+ case RTX_AUTOINC:
+ if (from && reg_overlap_mentioned_p (XEXP (x, 0), from))
+ {
+ failure_reason = "is subject to autoinc";
+ return false;
+ }
+ recurse_p = true;
+ break;
+
+ case RTX_MATCH:
+ case RTX_INSN:
+ gcc_unreachable ();
+ }
+
+ if (recurse_p)
+ {
+ const char *fmt = GET_RTX_FORMAT (code);
+ for (int i = 0; fmt[i]; i++)
+ switch (fmt[i])
+ {
+ case 'E':
+ for (int j = 0; j < XVECLEN (x, i); j++)
+ if (!apply_to_rvalue_1 (&XVECEXP (x, i, j)))
+ return false;
+ break;
+
+ case 'e':
+ if (XEXP (x, i) && !apply_to_rvalue_1 (&XEXP (x, i)))
+ return false;
+ break;
+ }
+ }
+ else if (newx && !rtx_equal_p (x, newx))
+ {
+ /* All substitutions made by OLD_NUM_CHANGES onwards have been
+ simplified. */
+ result_flags = ((result_flags & ~UNSIMPLIFIED)
+ | (old_result_flags & UNSIMPLIFIED));
+
+ if (should_note_simplifications)
+ note_simplification (old_num_changes, old_result_flags, x, newx);
+
+ /* There's no longer any point unsharing the substitutions made
+ for subexpressions, since we'll just copy this one instead. */
+ bool unshare = false;
+ for (int i = old_num_changes; i < num_changes; ++i)
+ {
+ unshare |= changes[i].unshare;
+ changes[i].unshare = false;
+ }
+ if (unshare)
+ validate_unshare_change (insn, loc, newx, 1);
+ else
+ validate_change (insn, loc, newx, 1);
+ }
+
+ return true;
+}
+
+/* Try to process the lvalue expression at *LOC. Return true on success;
+ leave the caller to clean up on failure. */
+
+bool
+insn_propagation::apply_to_lvalue_1 (rtx dest)
+{
+ rtx old_dest = dest;
+ while (GET_CODE (dest) == SUBREG
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == STRICT_LOW_PART)
+ {
+ if (GET_CODE (dest) == ZERO_EXTRACT
+ && (!apply_to_rvalue_1 (&XEXP (dest, 1))
+ || !apply_to_rvalue_1 (&XEXP (dest, 2))))
+ return false;
+ dest = XEXP (dest, 0);
+ }
+
+ if (MEM_P (dest))
+ return apply_to_mem_1 (dest);
+
+ /* Check whether the substitution is safe in the presence of this lvalue. */
+ if (!from
+ || dest == old_dest
+ || !REG_P (dest)
+ || !reg_overlap_mentioned_p (dest, from))
+ return true;
+
+ if (SUBREG_P (old_dest)
+ && SUBREG_REG (old_dest) == dest
+ && !read_modify_subreg_p (old_dest))
+ return true;
+
+ failure_reason = "is part of a read-write destination";
+ return false;
+}
+
+/* Try to process the instruction pattern at *LOC. Return true on success;
+ leave the caller to clean up on failure. */
+
+bool
+insn_propagation::apply_to_pattern_1 (rtx *loc)
+{
+ rtx body = *loc;
+ switch (GET_CODE (body))
+ {
+ case COND_EXEC:
+ return (apply_to_rvalue_1 (&COND_EXEC_TEST (body))
+ && apply_to_pattern_1 (&COND_EXEC_CODE (body)));
+
+ case PARALLEL:
+ {
+ int last = XVECLEN (body, 0) - 1;
+ for (int i = 0; i < last; ++i)
+ if (!apply_to_pattern_1 (&XVECEXP (body, 0, i)))
+ return false;
+ return apply_to_pattern_1 (&XVECEXP (body, 0, last));
+ }
+
+ case ASM_OPERANDS:
+ for (int i = 0, len = ASM_OPERANDS_INPUT_LENGTH (body); i < len; ++i)
+ if (!apply_to_rvalue_1 (&ASM_OPERANDS_INPUT (body, i)))
+ return false;
+ return true;
+
+ case CLOBBER:
+ return apply_to_lvalue_1 (XEXP (body, 0));
+
+ case SET:
+ return (apply_to_lvalue_1 (SET_DEST (body))
+ && apply_to_rvalue_1 (&SET_SRC (body)));
+
+ default:
+ /* All the other possibilities never store and can use a normal
+ rtx walk. This includes:
+
+ - USE
+ - TRAP_IF
+ - PREFETCH
+ - UNSPEC
+ - UNSPEC_VOLATILE. */
+ return apply_to_rvalue_1 (loc);
+ }
+}
+
+/* Apply this insn_propagation object's simplification or substitution
+ to the instruction pattern at LOC. */
+
+bool
+insn_propagation::apply_to_pattern (rtx *loc)
+{
+ unsigned int num_changes = num_validated_changes ();
+ bool res = apply_to_pattern_1 (loc);
+ if (!res)
+ cancel_changes (num_changes);
+ return res;
+}
+
+/* Apply this insn_propagation object's simplification or substitution
+ to the rvalue expression at LOC. */
+
+bool
+insn_propagation::apply_to_rvalue (rtx *loc)
+{
+ unsigned int num_changes = num_validated_changes ();
+ bool res = apply_to_rvalue_1 (loc);
+ if (!res)
+ cancel_changes (num_changes);
+ return res;
+}
+
+/* Check whether INSN matches a specific alternative of an .md pattern. */
+
+bool
+valid_insn_p (rtx_insn *insn)
+{
+ recog_memoized (insn);
+ if (INSN_CODE (insn) < 0)
+ return false;
+ extract_insn (insn);
+ /* We don't know whether the insn will be in code that is optimized
+ for size or speed, so consider all enabled alternatives. */
+ if (!constrain_operands (1, get_enabled_alternatives (insn)))
+ return false;
+ return true;
+}
+
/* Return 1 if OP is a valid general operand for machine mode MODE.
This is either a register reference, a memory reference,
or a constant. In the case of a memory reference, the address
@@ -1778,6 +2248,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
/* FALLTHRU */
default:
cn = lookup_constraint (constraint);
+ rtx mem = NULL;
switch (get_constraint_type (cn))
{
case CT_REGISTER:
@@ -1796,10 +2267,13 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
break;
case CT_MEMORY:
+ mem = op;
+ /* Fall through. */
case CT_SPECIAL_MEMORY:
/* Every memory operand can be reloaded to fit. */
- result = result || memory_operand (extract_mem_from_operand (op),
- VOIDmode);
+ if (!mem)
+ mem = extract_mem_from_operand (op);
+ result = result || memory_operand (mem, VOIDmode);
break;
case CT_ADDRESS:
diff --git a/gcc/recog.h b/gcc/recog.h
index ae3675f..b8de43b 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -82,12 +82,113 @@ alternative_class (const operand_alternative *alt, int i)
return alt[i].matches >= 0 ? alt[alt[i].matches].cl : alt[i].cl;
}
+/* A class for substituting one rtx for another within an instruction,
+ or for recursively simplifying the instruction as-is. Derived classes
+ can record or filter certain decisions. */
+
+class insn_propagation : public simplify_context
+{
+public:
+ /* Assignments for RESULT_FLAGS.
+
+ UNSIMPLIFIED is true if a substitution has been made inside an rtx
+ X and if neither X nor its parent expressions could be simplified.
+
+ FIRST_SPARE_RESULT is the first flag available for derived classes. */
+ static const uint16_t UNSIMPLIFIED = 1U << 0;
+ static const uint16_t FIRST_SPARE_RESULT = 1U << 1;
+
+ insn_propagation (rtx_insn *);
+ insn_propagation (rtx_insn *, rtx, rtx, bool = true);
+ bool apply_to_pattern (rtx *);
+ bool apply_to_rvalue (rtx *);
+
+ /* Return true if we should accept a substitution into the address of
+ memory expression MEM. Undoing changes OLD_NUM_CHANGES and up restores
+ MEM's original address. */
+ virtual bool check_mem (int /*old_num_changes*/,
+ rtx /*mem*/) { return true; }
+
+ /* Note that we've simplified OLD_RTX into NEW_RTX. When substituting,
+ this only happens if a substitution occured within OLD_RTX.
+ Undoing OLD_NUM_CHANGES and up will restore the old form of OLD_RTX.
+ OLD_RESULT_FLAGS is the value that RESULT_FLAGS had before processing
+ OLD_RTX. */
+ virtual void note_simplification (int /*old_num_changes*/,
+ uint16_t /*old_result_flags*/,
+ rtx /*old_rtx*/, rtx /*new_rtx*/) {}
+
+private:
+ bool apply_to_mem_1 (rtx);
+ bool apply_to_lvalue_1 (rtx);
+ bool apply_to_rvalue_1 (rtx *);
+ bool apply_to_pattern_1 (rtx *);
+
+public:
+ /* The instruction that we are simplifying or propagating into. */
+ rtx_insn *insn;
+
+ /* If FROM is nonnull, we're replacing FROM with TO, otherwise we're
+ just doing a recursive simplification. */
+ rtx from;
+ rtx to;
+
+ /* The number of times that we have replaced FROM with TO. */
+ unsigned int num_replacements;
+
+ /* A bitmask of flags that describe the result of the simplificiation;
+ see above for details. */
+ uint16_t result_flags : 16;
+
+ /* True if we should unshare TO when making the next substitution,
+ false if we can use TO itself. */
+ uint16_t should_unshare : 1;
+
+ /* True if we should call check_mem after substituting into a memory. */
+ uint16_t should_check_mems : 1;
+
+ /* True if we should call note_simplification after each simplification. */
+ uint16_t should_note_simplifications : 1;
+
+ /* For future expansion. */
+ uint16_t spare : 13;
+
+ /* Gives the reason that a substitution failed, for debug purposes. */
+ const char *failure_reason;
+};
+
+/* Try to replace FROM with TO in INSN. SHARED_P is true if TO is shared
+ with other instructions, false if INSN can use TO directly. */
+
+inline insn_propagation::insn_propagation (rtx_insn *insn, rtx from, rtx to,
+ bool shared_p)
+ : insn (insn),
+ from (from),
+ to (to),
+ num_replacements (0),
+ result_flags (0),
+ should_unshare (shared_p),
+ should_check_mems (false),
+ should_note_simplifications (false),
+ spare (0),
+ failure_reason (nullptr)
+{
+}
+
+/* Try to simplify INSN without performing a substitution. */
+
+inline insn_propagation::insn_propagation (rtx_insn *insn)
+ : insn_propagation (insn, NULL_RTX, NULL_RTX)
+{
+}
+
extern void init_recog (void);
extern void init_recog_no_volatile (void);
extern int check_asm_operands (rtx);
extern int asm_operand_ok (rtx, const char *, const char **);
extern bool validate_change (rtx, rtx *, rtx, bool);
extern bool validate_unshare_change (rtx, rtx *, rtx, bool);
+extern bool validate_change_xveclen (rtx, rtx *, int, bool);
extern bool canonicalize_change_group (rtx_insn *insn, rtx x);
extern int insn_invalid_p (rtx_insn *, bool);
extern int verify_changes (int);
@@ -95,6 +196,8 @@ extern void confirm_change_group (void);
extern int apply_change_group (void);
extern int num_validated_changes (void);
extern void cancel_changes (int);
+extern void temporarily_undo_changes (int);
+extern void redo_changes (int);
extern int constrain_operands (int, alternative_mask);
extern int constrain_operands_cached (rtx_insn *, int);
extern int memory_address_addr_space_p (machine_mode, rtx, addr_space_t);
@@ -113,6 +216,7 @@ extern void validate_replace_src_group (rtx, rtx, rtx_insn *);
extern bool validate_simplify_insn (rtx_insn *insn);
extern int num_changes_pending (void);
extern bool reg_fits_class_p (const_rtx, reg_class_t, int, machine_mode);
+extern bool valid_insn_p (rtx_insn *);
extern int offsettable_memref_p (rtx);
extern int offsettable_nonstrict_memref_p (rtx);
@@ -399,6 +503,57 @@ alternative_mask get_preferred_alternatives (rtx_insn *, basic_block);
bool check_bool_attrs (rtx_insn *);
void recog_init ();
+
+/* This RAII class can help to undo tentative insn changes on failure.
+ When an object of the class goes out of scope, it undoes all group
+ changes that have been made via the validate_change machinery and
+ not yet confirmed via confirm_change_group.
+
+ For example:
+
+ insn_change_watermark watermark;
+ validate_change (..., true); // A
+ ...
+ if (test)
+ // Undoes change A.
+ return false;
+ ...
+ validate_change (..., true); // B
+ ...
+ if (test)
+ // Undoes changes A and B.
+ return false;
+ ...
+ confirm_change_group ();
+
+ Code that wants to avoid this behavior can use keep ():
+
+ insn_change_watermark watermark;
+ validate_change (..., true); // A
+ ...
+ if (test)
+ // Undoes change A.
+ return false;
+ ...
+ watermark.keep ();
+ validate_change (..., true); // B
+ ...
+ if (test)
+ // Undoes change B, but not A.
+ return false;
+ ...
+ confirm_change_group (); */
+class insn_change_watermark
+{
+public:
+ insn_change_watermark () : m_old_num_changes (num_validated_changes ()) {}
+ ~insn_change_watermark () { cancel_changes (m_old_num_changes); }
+ void keep () { m_old_num_changes = num_validated_changes (); }
+
+private:
+ int m_old_num_changes;
+};
+
#endif
#endif /* GCC_RECOG_H */
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 8f98bd8..3dab843 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -3426,7 +3426,8 @@ static unsigned int
rest_of_handle_stack_regs (void)
{
#ifdef STACK_REGS
- reg_to_stack ();
+ if (reg_to_stack ())
+ df_insn_rescan_all ();
regstack_completed = 1;
#endif
return 0;
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index e34b74a..cc7d174 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -91,6 +91,9 @@ static const char initial_call_used_regs[] = CALL_USED_REGISTERS;
and are also considered fixed. */
char global_regs[FIRST_PSEUDO_REGISTER];
+/* The set of global registers. */
+HARD_REG_SET global_reg_set;
+
/* Declaration for the global register. */
tree global_regs_decl[FIRST_PSEUDO_REGISTER];
@@ -390,6 +393,7 @@ init_reg_sets_1 (void)
{
fixed_regs[i] = call_used_regs[i] = 1;
SET_HARD_REG_BIT (fixed_reg_set, i);
+ SET_HARD_REG_BIT (global_reg_set, i);
}
}
@@ -724,6 +728,7 @@ globalize_reg (tree decl, int i)
global_regs[i] = 1;
global_regs_decl[i] = decl;
+ SET_HARD_REG_BIT (global_reg_set, i);
/* If we're globalizing the frame pointer, we need to set the
appropriate regs_invalidated_by_call bit, even if it's already
diff --git a/gcc/reload.c b/gcc/reload.c
index 78b4049..b99b72c 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -1043,53 +1043,72 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
Also reload the inner expression if it does not require a secondary
reload but the SUBREG does.
- Finally, reload the inner expression if it is a register that is in
+ Also reload the inner expression if it is a register that is in
the class whose registers cannot be referenced in a different size
and M1 is not the same size as M2. If subreg_lowpart_p is false, we
cannot reload just the inside since we might end up with the wrong
register class. But if it is inside a STRICT_LOW_PART, we have
- no choice, so we hope we do get the right register class there. */
+ no choice, so we hope we do get the right register class there.
+
+ Finally, reload the inner expression if it is a pseudo that will
+ become a MEM and the MEM has a mode-dependent address, as in that
+ case we obviously cannot change the mode of the MEM to that of the
+ containing SUBREG as that would change the interpretation of the
+ address. */
scalar_int_mode inner_mode;
if (in != 0 && GET_CODE (in) == SUBREG
- && (subreg_lowpart_p (in) || strict_low)
&& targetm.can_change_mode_class (GET_MODE (SUBREG_REG (in)),
inmode, rclass)
&& contains_allocatable_reg_of_mode[rclass][GET_MODE (SUBREG_REG (in))]
- && (CONSTANT_P (SUBREG_REG (in))
- || GET_CODE (SUBREG_REG (in)) == PLUS
- || strict_low
- || (((REG_P (SUBREG_REG (in))
- && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
- || MEM_P (SUBREG_REG (in)))
- && (paradoxical_subreg_p (inmode, GET_MODE (SUBREG_REG (in)))
- || (known_le (GET_MODE_SIZE (inmode), UNITS_PER_WORD)
- && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (in)),
- &inner_mode)
- && GET_MODE_SIZE (inner_mode) <= UNITS_PER_WORD
- && paradoxical_subreg_p (inmode, inner_mode)
- && LOAD_EXTEND_OP (inner_mode) != UNKNOWN)
- || (WORD_REGISTER_OPERATIONS
- && partial_subreg_p (inmode, GET_MODE (SUBREG_REG (in)))
- && (known_equal_after_align_down
- (GET_MODE_SIZE (inmode) - 1,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1,
- UNITS_PER_WORD)))))
- || (REG_P (SUBREG_REG (in))
- && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
- /* The case where out is nonzero
- is handled differently in the following statement. */
- && (out == 0 || subreg_lowpart_p (in))
- && (complex_word_subreg_p (inmode, SUBREG_REG (in))
- || !targetm.hard_regno_mode_ok (subreg_regno (in), inmode)))
- || (secondary_reload_class (1, rclass, inmode, in) != NO_REGS
- && (secondary_reload_class (1, rclass, GET_MODE (SUBREG_REG (in)),
- SUBREG_REG (in))
- == NO_REGS))
+ && (strict_low
+ || (subreg_lowpart_p (in)
+ && (CONSTANT_P (SUBREG_REG (in))
+ || GET_CODE (SUBREG_REG (in)) == PLUS
+ || (((REG_P (SUBREG_REG (in))
+ && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
+ || MEM_P (SUBREG_REG (in)))
+ && (paradoxical_subreg_p (inmode,
+ GET_MODE (SUBREG_REG (in)))
+ || (known_le (GET_MODE_SIZE (inmode), UNITS_PER_WORD)
+ && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG
+ (in)),
+ &inner_mode)
+ && GET_MODE_SIZE (inner_mode) <= UNITS_PER_WORD
+ && paradoxical_subreg_p (inmode, inner_mode)
+ && LOAD_EXTEND_OP (inner_mode) != UNKNOWN)
+ || (WORD_REGISTER_OPERATIONS
+ && partial_subreg_p (inmode,
+ GET_MODE (SUBREG_REG (in)))
+ && (known_equal_after_align_down
+ (GET_MODE_SIZE (inmode) - 1,
+ GET_MODE_SIZE (GET_MODE (SUBREG_REG
+ (in))) - 1,
+ UNITS_PER_WORD)))))
+ || (REG_P (SUBREG_REG (in))
+ && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ /* The case where out is nonzero
+ is handled differently in the following statement. */
+ && (out == 0 || subreg_lowpart_p (in))
+ && (complex_word_subreg_p (inmode, SUBREG_REG (in))
+ || !targetm.hard_regno_mode_ok (subreg_regno (in),
+ inmode)))
+ || (secondary_reload_class (1, rclass, inmode, in) != NO_REGS
+ && (secondary_reload_class (1, rclass,
+ GET_MODE (SUBREG_REG (in)),
+ SUBREG_REG (in))
+ == NO_REGS))
+ || (REG_P (SUBREG_REG (in))
+ && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ && !REG_CAN_CHANGE_MODE_P (REGNO (SUBREG_REG (in)),
+ GET_MODE (SUBREG_REG (in)),
+ inmode))))
|| (REG_P (SUBREG_REG (in))
- && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
- && !REG_CAN_CHANGE_MODE_P (REGNO (SUBREG_REG (in)),
- GET_MODE (SUBREG_REG (in)), inmode))))
+ && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER
+ && reg_equiv_mem (REGNO (SUBREG_REG (in)))
+ && (mode_dependent_address_p
+ (XEXP (reg_equiv_mem (REGNO (SUBREG_REG (in))), 0),
+ MEM_ADDR_SPACE (reg_equiv_mem (REGNO (SUBREG_REG (in)))))))))
{
#ifdef LIMIT_RELOAD_CLASS
in_subreg_loc = inloc;
@@ -2656,6 +2675,22 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
hard_regs_live_known = live_known;
static_reload_reg_p = reload_reg_p;
+ if (JUMP_P (insn) && INSN_CODE (insn) < 0)
+ {
+ extract_insn (insn);
+ for (i = 0; i < recog_data.n_operands; i++)
+ if (recog_data.operand_type[i] != OP_IN)
+ break;
+ if (i < recog_data.n_operands)
+ {
+ error_for_asm (insn,
+ "the target does not support %<asm goto%> "
+ "with outputs in %<asm%>");
+ ira_nullify_asm_goto (insn);
+ return 0;
+ }
+ }
+
/* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads;
neither are insns that SET cc0. Insns that use CC0 are not allowed
to have any input reloads. */
@@ -3141,6 +3176,19 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
&& paradoxical_subreg_p (operand_mode[i],
inner_mode)
&& LOAD_EXTEND_OP (inner_mode) != UNKNOWN)))
+ /* We must force a reload of a SUBREG's inner expression
+ if it is a pseudo that will become a MEM and the MEM
+ has a mode-dependent address, as in that case we
+ obviously cannot change the mode of the MEM to that
+ of the containing SUBREG as that would change the
+ interpretation of the address. */
+ || (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_equiv_mem (REGNO (operand))
+ && (mode_dependent_address_p
+ (XEXP (reg_equiv_mem (REGNO (operand)), 0),
+ (MEM_ADDR_SPACE
+ (reg_equiv_mem (REGNO (operand)))))))
)
force_reload = 1;
}
diff --git a/gcc/resource.c b/gcc/resource.c
index 0a9d594..90cf091 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -1186,7 +1186,7 @@ init_resource_info (rtx_insn *epilogue_insn)
&end_of_function_needs, true);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i] || EPILOGUE_USES (i))
+ if (global_regs[i] || df_epilogue_uses_p (i))
SET_HARD_REG_BIT (end_of_function_needs.regs, i);
/* The registers required to be live at the end of the function are
diff --git a/gcc/rtl-ssa.h b/gcc/rtl-ssa.h
new file mode 100644
index 0000000..edb09a7
--- /dev/null
+++ b/gcc/rtl-ssa.h
@@ -0,0 +1,71 @@
+// On-the-side RTL SSA representation -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_RTL_SSA_H
+#define GCC_RTL_SSA_H 1
+
+// This is an aggregation header file. This means it should contain only
+// other include files.
+
+#if 0
+// Files that use this one should first have:
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#endif
+
+// Needed by splay-tree-utils.h and directly by rtl-ssa.
+#include "pretty-print.h"
+
+// Needed directly by recog.h.
+#include "insn-config.h"
+
+// Needed directly by rtl-ssa.
+#include "splay-tree-utils.h"
+#include "recog.h"
+#include "regs.h"
+#include "function-abi.h"
+#include "obstack-utils.h"
+#include "mux-utils.h"
+#include "rtlanal.h"
+
+// Provides the global crtl->ssa.
+#include "memmodel.h"
+#include "tm_p.h"
+#include "emit-rtl.h"
+
+// The rtl-ssa files themselves.
+#include "rtl-ssa/accesses.h"
+#include "rtl-ssa/insns.h"
+#include "rtl-ssa/blocks.h"
+#include "rtl-ssa/changes.h"
+#include "rtl-ssa/functions.h"
+#include "rtl-ssa/is-a.inl"
+#include "rtl-ssa/access-utils.h"
+#include "rtl-ssa/insn-utils.h"
+#include "rtl-ssa/movement.h"
+#include "rtl-ssa/change-utils.h"
+#include "rtl-ssa/member-fns.inl"
+
+#endif
diff --git a/gcc/rtl-ssa/access-utils.h b/gcc/rtl-ssa/access-utils.h
new file mode 100644
index 0000000..634f99b
--- /dev/null
+++ b/gcc/rtl-ssa/access-utils.h
@@ -0,0 +1,553 @@
+// Access-related utilities for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// Return a referene to the whole of register REGNO.
+inline resource_info
+full_register (unsigned int regno)
+{
+ return { GET_MODE (regno_reg_rtx[regno]), regno };
+}
+
+// Return true if sorted array ACCESSES includes an access to hard registers.
+inline bool
+accesses_include_hard_registers (const access_array &accesses)
+{
+ return accesses.size () && HARD_REGISTER_NUM_P (accesses.front ()->regno ());
+}
+
+// Return true if sorted array ACCESSES includes an access to memory.
+inline bool
+accesses_include_memory (const access_array &accesses)
+{
+ return accesses.size () && accesses.back ()->is_mem ();
+}
+
+// If sorted array ACCESSES includes an access to memory, return the access,
+// otherwise return null.
+template<typename T>
+inline auto
+memory_access (T accesses) -> decltype (accesses[0])
+{
+ if (accesses.size () && accesses.back ()->is_mem ())
+ return accesses.back ();
+ return nullptr;
+}
+
+// If sorted array ACCESSES includes a reference to REGNO, return the
+// access, otherwise return null.
+template<typename T>
+inline auto
+find_access (T accesses, unsigned int regno) -> decltype (accesses[0])
+{
+ unsigned int start = 0;
+ unsigned int end = accesses.size ();
+ while (start < end)
+ {
+ unsigned int mid = (start + end) / 2;
+ unsigned int found = accesses[mid]->regno ();
+ if (found == regno)
+ return accesses[mid];
+ if (found < regno)
+ start = mid + 1;
+ else
+ end = mid;
+ }
+ return nullptr;
+}
+
+// If sorted array ACCESSES includes a reference to REGNO, return the
+// index of the access, otherwise return -1.
+inline int
+find_access_index (access_array accesses, unsigned int regno)
+{
+ unsigned int start = 0;
+ unsigned int end = accesses.size ();
+ while (start < end)
+ {
+ unsigned int mid = (start + end) / 2;
+ unsigned int found = accesses[mid]->regno ();
+ if (found == regno)
+ return mid;
+ if (found < regno)
+ start = mid + 1;
+ else
+ end = mid;
+ }
+ return -1;
+}
+
+// If ACCESS is a set whose result is used by at least one instruction,
+// return the access as a set_info, otherwise return null.
+inline const set_info *
+set_with_nondebug_insn_uses (const access_info *access)
+{
+ if (access->is_set_with_nondebug_insn_uses ())
+ // No need for as_a; this test is just as definitive.
+ return static_cast<const set_info *> (access);
+ return nullptr;
+}
+
+// A non-const version of the above.
+inline set_info *
+set_with_nondebug_insn_uses (access_info *access)
+{
+ if (access->is_set_with_nondebug_insn_uses ())
+ return static_cast<set_info *> (access);
+ return nullptr;
+}
+
+// Return true if SET is the only set of SET->resource () and if it
+// dominates all uses (excluding uses of SET->resource () at points
+// where SET->resource () is always undefined).
+inline bool
+is_single_dominating_def (const set_info *set)
+{
+ return set->is_first_def () && set->is_last_def ();
+}
+
+// SET is known to be available on entry to BB. Return true if it is
+// also available on exit from BB. (The value might or might not be live.)
+inline bool
+remains_available_on_exit (const set_info *set, bb_info *bb)
+{
+ return (set->is_last_def ()
+ || *set->next_def ()->insn () > *bb->end_insn ());
+}
+
+// ACCESS is known to be associated with an instruction rather than
+// a phi node. Return which instruction that is.
+inline insn_info *
+access_insn (const access_info *access)
+{
+ // In release builds this function reduces to a single pointer reference.
+ if (auto *def = dyn_cast<const def_info *> (access))
+ return def->insn ();
+ return as_a<const use_info *> (access)->insn ();
+}
+
+// If ACCESS records a use, return the value that it uses. If ACCESS records
+// a set, return that set. If ACCESS records a clobber, return null.
+inline const set_info *
+access_value (const access_info *access)
+{
+ if (!access)
+ return nullptr;
+
+ if (auto *use = dyn_cast<const use_info *> (access))
+ return use->def ();
+
+ return dyn_cast<const set_info *> (access);
+}
+
+// A non-const version of the above.
+inline set_info *
+access_value (access_info *access)
+{
+ auto *const_access = const_cast<const access_info *> (access);
+ return const_cast<set_info *> (access_value (const_access));
+}
+
+// If ACCESS is a degenerate phi, return the set_info that defines its input,
+// otherwise return ACCESS itself.
+template<typename T>
+inline const T *
+look_through_degenerate_phi (const T *access)
+{
+ if (auto *phi = dyn_cast<const phi_info *> (access))
+ if (phi->is_degenerate ())
+ return phi->input_value (0);
+ return access;
+}
+
+// A non-const version of the above.
+template<typename T>
+inline T *
+look_through_degenerate_phi (T *access)
+{
+ auto *const_access = const_cast<const T *> (access);
+ return const_cast<T *> (look_through_degenerate_phi (const_access));
+}
+
+// If CLOBBER is in a group, return the first clobber in the group,
+// otherwise return CLOBBER itself.
+inline clobber_info *
+first_clobber_in_group (clobber_info *clobber)
+{
+ if (clobber->is_in_group ())
+ return clobber->group ()->first_clobber ();
+ return clobber;
+}
+
+// If CLOBBER is in a group, return the last clobber in the group,
+// otherwise return CLOBBER itself.
+inline clobber_info *
+last_clobber_in_group (clobber_info *clobber)
+{
+ if (clobber->is_in_group ())
+ return clobber->group ()->last_clobber ();
+ return clobber;
+}
+
+// If DEF is a clobber in a group, return the containing group,
+// otherwise return DEF.
+inline def_mux
+clobber_group_or_single_def (def_info *def)
+{
+ if (auto *clobber = dyn_cast<clobber_info *> (def))
+ if (clobber->is_in_group ())
+ return clobber->group ();
+ return def;
+}
+
+// Return the first definition associated with NODE. If NODE holds
+// a single set, the result is that set. If NODE holds a clobber_group,
+// the result is the first clobber in the group.
+inline def_info *
+first_def (def_node *node)
+{
+ return node->first_def ();
+}
+
+// Likewise for something that is either a node or a single definition.
+inline def_info *
+first_def (def_mux mux)
+{
+ return mux.first_def ();
+}
+
+// Return the last definition associated with NODE. If NODE holds
+// a single set, the result is that set. If NODE holds a clobber_group,
+// the result is the last clobber in the group.
+inline def_info *
+last_def (def_node *node)
+{
+ if (auto *group = dyn_cast<clobber_group *> (node))
+ return group->last_clobber ();
+ return node->first_def ();
+}
+
+// Likewise for something that is either a node or a single definition.
+inline def_info *
+last_def (def_mux mux)
+{
+ return mux.last_def ();
+}
+
+int lookup_use (splay_tree<use_info *> &, insn_info *);
+int lookup_def (def_splay_tree &, insn_info *);
+int lookup_clobber (clobber_tree &, insn_info *);
+int lookup_call_clobbers (insn_call_clobbers_tree &, insn_info *);
+
+// Search backwards from immediately before INSN for the first instruction
+// recorded in TREE, ignoring any instruction I for which IGNORE (I) is true.
+// Return null if no such instruction exists.
+template<typename IgnorePredicate>
+insn_info *
+prev_call_clobbers_ignoring (insn_call_clobbers_tree &tree, insn_info *insn,
+ IgnorePredicate ignore)
+{
+ if (!tree)
+ return nullptr;
+
+ int comparison = lookup_call_clobbers (tree, insn);
+ while (comparison <= 0 || ignore (tree->insn ()))
+ {
+ if (!tree.splay_prev_node ())
+ return nullptr;
+
+ comparison = 1;
+ }
+ return tree->insn ();
+}
+
+// Search forwards from immediately after INSN for the first instruction
+// recorded in TREE, ignoring any instruction I for which IGNORE (I) is true.
+// Return null if no such instruction exists.
+template<typename IgnorePredicate>
+insn_info *
+next_call_clobbers_ignoring (insn_call_clobbers_tree &tree, insn_info *insn,
+ IgnorePredicate ignore)
+{
+ if (!tree)
+ return nullptr;
+
+ int comparison = lookup_call_clobbers (tree, insn);
+ while (comparison >= 0 || ignore (tree->insn ()))
+ {
+ if (!tree.splay_next_node ())
+ return nullptr;
+
+ comparison = -1;
+ }
+ return tree->insn ();
+}
+
+// If ACCESS is a set, return the first use of ACCESS by a nondebug insn I
+// for which IGNORE (I) is false. Return null if ACCESS is not a set or if
+// no such use exists.
+template<typename IgnorePredicate>
+inline use_info *
+first_nondebug_insn_use_ignoring (const access_info *access,
+ IgnorePredicate ignore)
+{
+ if (const set_info *set = set_with_nondebug_insn_uses (access))
+ {
+ // Written this way to emphasize to the compiler that first_use
+ // must be nonnull in this situation.
+ use_info *use = set->first_use ();
+ do
+ {
+ if (!ignore (use->insn ()))
+ return use;
+ use = use->next_nondebug_insn_use ();
+ }
+ while (use);
+ }
+ return nullptr;
+}
+
+// If ACCESS is a set, return the last use of ACCESS by a nondebug insn I for
+// which IGNORE (I) is false. Return null if ACCESS is not a set or if no
+// such use exists.
+template<typename IgnorePredicate>
+inline use_info *
+last_nondebug_insn_use_ignoring (const access_info *access,
+ IgnorePredicate ignore)
+{
+ if (const set_info *set = set_with_nondebug_insn_uses (access))
+ {
+ // Written this way to emphasize to the compiler that
+ // last_nondebug_insn_use must be nonnull in this situation.
+ use_info *use = set->last_nondebug_insn_use ();
+ do
+ {
+ if (!ignore (use->insn ()))
+ return use;
+ use = use->prev_use ();
+ }
+ while (use);
+ }
+ return nullptr;
+}
+
+// If DEF is null, return null.
+//
+// Otherwise, search backwards for an access to DEF->resource (), starting at
+// the end of DEF's live range. Ignore clobbers if IGNORE_CLOBBERS_SETTING
+// is YES, otherwise treat them like any other access. Also ignore any
+// access A for which IGNORE (access_insn (A)) is true.
+//
+// Thus if DEF is a set that is used by nondebug insns, the first access
+// that the function considers is the last such use of the set. Otherwise,
+// the first access that the function considers is DEF itself.
+//
+// Return the access found, or null if there is no access that meets
+// the criteria.
+//
+// Note that this function does not consider separately-recorded call clobbers,
+// although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
+template<typename IgnorePredicate>
+access_info *
+last_access_ignoring (def_info *def, ignore_clobbers ignore_clobbers_setting,
+ IgnorePredicate ignore)
+{
+ while (def)
+ {
+ auto *clobber = dyn_cast<clobber_info *> (def);
+ if (clobber && ignore_clobbers_setting == ignore_clobbers::YES)
+ def = first_clobber_in_group (clobber);
+ else
+ {
+ if (use_info *use = last_nondebug_insn_use_ignoring (def, ignore))
+ return use;
+
+ insn_info *insn = def->insn ();
+ if (!ignore (insn))
+ return def;
+ }
+ def = def->prev_def ();
+ }
+ return nullptr;
+}
+
+// Search backwards for an access to DEF->resource (), starting
+// immediately before the point at which DEF occurs. Ignore clobbers
+// if IGNORE_CLOBBERS_SETTING is YES, otherwise treat them like any other
+// access. Also ignore any access A for which IGNORE (access_insn (A))
+// is true.
+//
+// Thus if DEF->insn () uses DEF->resource (), that use is the first access
+// that the function considers, since an instruction's uses occur strictly
+// before its definitions.
+//
+// Note that this function does not consider separately-recorded call clobbers,
+// although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
+template<typename IgnorePredicate>
+inline access_info *
+prev_access_ignoring (def_info *def, ignore_clobbers ignore_clobbers_setting,
+ IgnorePredicate ignore)
+{
+ return last_access_ignoring (def->prev_def (), ignore_clobbers_setting,
+ ignore);
+}
+
+// If DEF is null, return null.
+//
+// Otherwise, search forwards for a definition of DEF->resource (),
+// starting at DEF itself. Ignore clobbers if IGNORE_CLOBBERS_SETTING
+// is YES, otherwise treat them like any other access. Also ignore any
+// definition D for which IGNORE (D->insn ()) is true.
+//
+// Return the definition found, or null if there is no access that meets
+// the criteria.
+//
+// Note that this function does not consider separately-recorded call clobbers,
+// although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
+template<typename IgnorePredicate>
+def_info *
+first_def_ignoring (def_info *def, ignore_clobbers ignore_clobbers_setting,
+ IgnorePredicate ignore)
+{
+ while (def)
+ {
+ auto *clobber = dyn_cast<clobber_info *> (def);
+ if (clobber && ignore_clobbers_setting == ignore_clobbers::YES)
+ def = last_clobber_in_group (clobber);
+ else if (!ignore (def->insn ()))
+ return def;
+
+ def = def->next_def ();
+ }
+ return nullptr;
+}
+
+// Search forwards for the next access to DEF->resource (),
+// starting immediately after DEF's instruction. Ignore clobbers if
+// IGNORE_CLOBBERS_SETTING is YES, otherwise treat them like any other access.
+// Also ignore any access A for which IGNORE (access_insn (A)) is true;
+// in this context, ignoring a set includes ignoring all uses of the set.
+//
+// Thus if DEF is a set with uses by nondebug insns, the first access that the
+// function considers is the first such use of the set.
+//
+// Return the access found, or null if there is no access that meets the
+// criteria.
+//
+// Note that this function does not consider separately-recorded call clobbers,
+// although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
+template<typename IgnorePredicate>
+access_info *
+next_access_ignoring (def_info *def, ignore_clobbers ignore_clobbers_setting,
+ IgnorePredicate ignore)
+{
+ if (use_info *use = first_nondebug_insn_use_ignoring (def, ignore))
+ return use;
+
+ return first_def_ignoring (def->next_def (), ignore_clobbers_setting,
+ ignore);
+}
+
+// Return true if ACCESS1 should before ACCESS2 in an access_array.
+inline bool
+compare_access_infos (const access_info *access1, const access_info *access2)
+{
+ gcc_checking_assert (access1 == access2
+ || access1->regno () != access2->regno ());
+ return access1->regno () < access2->regno ();
+}
+
+// Sort [BEGIN, END) into ascending regno order. The sequence must have
+// at most one access to a given a regno.
+inline void
+sort_accesses (access_info **begin, access_info **end)
+{
+ auto count = end - begin;
+ if (count <= 1)
+ return;
+
+ if (count == 2)
+ {
+ gcc_checking_assert (begin[0]->regno () != begin[1]->regno ());
+ if (begin[0]->regno () > begin[1]->regno ())
+ std::swap (begin[0], begin[1]);
+ return;
+ }
+
+ std::sort (begin, end, compare_access_infos);
+}
+
+// Sort the accesses in CONTAINER, which contains pointers to access_infos.
+template<typename T>
+inline void
+sort_accesses (T &container)
+{
+ return sort_accesses (container.begin (), container.end ());
+}
+
+// The underlying non-template implementation of merge_access_arrays.
+access_array merge_access_arrays_base (obstack_watermark &, access_array,
+ access_array);
+// Merge access arrays ACCESSES1 and ACCESSES2, including the allocation
+// in the area governed by WATERMARK. Return an invalid access_array if
+// ACCESSES1 and ACCESSES2 contain conflicting accesses to the same resource.
+//
+// T can be an access_array, a def_array or a use_array.
+template<typename T>
+inline T
+merge_access_arrays (obstack_watermark &watermark, T accesses1, T accesses2)
+{
+ return T (merge_access_arrays_base (watermark, accesses1, accesses2));
+}
+
+// The underlying non-template implementation of insert_access.
+access_array insert_access_base (obstack_watermark &, access_info *,
+ access_array);
+
+// Return a new access_array that contains the result of inserting ACCESS1
+// into sorted access array ACCESSES2. Allocate the returned array in the
+// area governed by WATERMARK. Return an invalid access_array if ACCESSES2
+// contains a conflicting access to the same resource as ACCESS1.
+//
+// T can be an access_array, a def_array or a use_array.
+template<typename T>
+inline T
+insert_access (obstack_watermark &watermark,
+ typename T::value_type access1, T accesses2)
+{
+ return T (insert_access_base (watermark, access1, accesses2));
+}
+
+// The underlying non-template implementation of remove_note_accesses.
+access_array remove_note_accesses_base (obstack_watermark &, access_array);
+
+// If ACCESSES contains accesses that only occur in notes, return a new
+// array without such accesses, allocating it in the area governed by
+// WATERMARK. Return ACCESSES itself otherwise.
+//
+// T can be an access_array, a def_array or a use_array.
+template<typename T>
+inline T
+remove_note_accesses (obstack_watermark &watermark, T accesses)
+{
+ return T (remove_note_accesses_base (watermark, accesses));
+}
+
+}
diff --git a/gcc/rtl-ssa/accesses.cc b/gcc/rtl-ssa/accesses.cc
new file mode 100644
index 0000000..6a28007
--- /dev/null
+++ b/gcc/rtl-ssa/accesses.cc
@@ -0,0 +1,1594 @@
+// Implementation of access-related functions for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+#include "rtl-ssa/internals.inl"
+
+using namespace rtl_ssa;
+
+// This clobber belongs to a clobber_group but m_group appears to be
+// out of date. Update it and return the new (correct) value.
+clobber_group *
+clobber_info::recompute_group ()
+{
+ using splay_tree = clobber_info::splay_tree;
+
+ // Splay this clobber to the root of the tree while searching for a node
+ // that has the correct group. The root always has the correct group,
+ // so the search always breaks early and does not install this clobber
+ // as the root.
+ clobber_info *cursor = m_parent;
+ auto find_group = [](clobber_info *node, unsigned int)
+ {
+ return node->m_group->has_been_superceded () ? nullptr : node->m_group;
+ };
+ clobber_group *group = splay_tree::splay_and_search (this, nullptr,
+ find_group);
+ gcc_checking_assert (m_parent);
+
+ // If the previous splay operation did anything, this clobber is now an
+ // ancestor of CURSOR, and all the nodes inbetween have a stale group.
+ // Since we have visited the nodes, we might as well update them too.
+ //
+ // If the previous splay operation did nothing, start the update from
+ // this clobber instead. In that case we change at most two clobbers:
+ // this clobber and possibly its parent.
+ if (cursor == m_parent)
+ cursor = this;
+
+ // Walk up the tree from CURSOR updating clobbers that need it.
+ // This walk always includes this clobber.
+ while (cursor->m_group != group)
+ {
+ cursor->m_group = group;
+ cursor = cursor->m_parent;
+ }
+
+ gcc_checking_assert (m_group == group);
+ return group;
+}
+
+// See the comment above the declaration.
+void
+resource_info::print_identifier (pretty_printer *pp) const
+{
+ if (is_mem ())
+ pp_string (pp, "mem");
+ else
+ {
+ char tmp[3 * sizeof (regno) + 2];
+ snprintf (tmp, sizeof (tmp), "r%d", regno);
+ pp_string (pp, tmp);
+ }
+}
+
+// See the comment above the declaration.
+void
+resource_info::print_context (pretty_printer *pp) const
+{
+ if (HARD_REGISTER_NUM_P (regno))
+ {
+ if (const char *name = reg_names[regno])
+ {
+ pp_space (pp);
+ pp_left_paren (pp);
+ pp_string (pp, name);
+ if (mode != E_BLKmode)
+ {
+ pp_colon (pp);
+ pp_string (pp, GET_MODE_NAME (mode));
+ }
+ pp_right_paren (pp);
+ }
+ }
+ else if (is_reg ())
+ {
+ pp_space (pp);
+ pp_left_paren (pp);
+ if (mode != E_BLKmode)
+ {
+ pp_string (pp, GET_MODE_NAME (mode));
+ pp_space (pp);
+ }
+ pp_string (pp, "pseudo");
+ pp_right_paren (pp);
+ }
+}
+
+// See the comment above the declaration.
+void
+resource_info::print (pretty_printer *pp) const
+{
+ print_identifier (pp);
+ print_context (pp);
+}
+
+// Some properties can naturally be described using adjectives that attach
+// to nouns like "use" or "definition". Print such adjectives to PP.
+void
+access_info::print_prefix_flags (pretty_printer *pp) const
+{
+ if (m_is_temp)
+ pp_string (pp, "temporary ");
+ if (m_has_been_superceded)
+ pp_string (pp, "superceded ");
+}
+
+// Print properties not handled by print_prefix_flags to PP, putting
+// each property on a new line indented by two extra spaces.
+void
+access_info::print_properties_on_new_lines (pretty_printer *pp) const
+{
+ if (m_is_pre_post_modify)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "set by a pre/post-modify");
+ pp_indentation (pp) -= 2;
+ }
+ if (m_includes_address_uses)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "appears inside an address");
+ pp_indentation (pp) -= 2;
+ }
+ if (m_includes_read_writes)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "appears in a read/write context");
+ pp_indentation (pp) -= 2;
+ }
+ if (m_includes_subregs)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "appears inside a subreg");
+ pp_indentation (pp) -= 2;
+ }
+}
+
+// Return true if there are no known issues with the integrity of the
+// link information.
+inline bool
+use_info::check_integrity ()
+{
+ auto subsequence_id = [](use_info *use)
+ {
+ if (use->is_in_nondebug_insn ())
+ return 1;
+ if (use->is_in_debug_insn ())
+ return 2;
+ return 3;
+ };
+
+ use_info *prev = prev_use ();
+ use_info *next = next_use ();
+
+ if (prev && subsequence_id (prev) > subsequence_id (this))
+ return false;
+ if (next && subsequence_id (next) < subsequence_id (this))
+ return false;
+ if (m_is_last_nondebug_insn_use != calculate_is_last_nondebug_insn_use ())
+ return false;
+
+ if (!prev && last_use ()->next_use ())
+ return false;
+ if (!next)
+ if (use_info *use = last_nondebug_insn_use ())
+ if (!use->m_is_last_nondebug_insn_use)
+ return false;
+
+ return true;
+}
+
+// See the comment above the declaration.
+void
+use_info::print_location (pretty_printer *pp) const
+{
+ if (is_in_phi ())
+ pp_access (pp, phi (), PP_ACCESS_INCLUDE_LOCATION);
+ else
+ insn ()->print_identifier_and_location (pp);
+}
+
+// See the comment above the declaration.
+void
+use_info::print_def (pretty_printer *pp) const
+{
+ if (const set_info *set = def ())
+ pp_access (pp, set, 0);
+ else
+ {
+ pp_string (pp, "undefined ");
+ resource ().print (pp);
+ }
+}
+
+// See the comment above the declaration.
+void
+use_info::print (pretty_printer *pp, unsigned int flags) const
+{
+ print_prefix_flags (pp);
+
+ const set_info *set = def ();
+ if (set && set->mode () != mode ())
+ {
+ pp_string (pp, GET_MODE_NAME (mode ()));
+ pp_space (pp);
+ }
+
+ pp_string (pp, "use of ");
+ print_def (pp);
+ if (flags & PP_ACCESS_INCLUDE_LOCATION)
+ {
+ pp_string (pp, " by ");
+ print_location (pp);
+ }
+ if (set && (flags & PP_ACCESS_INCLUDE_LINKS))
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "defined in ");
+ set->insn ()->print_location (pp);
+ pp_indentation (pp) -= 2;
+ }
+ if (flags & PP_ACCESS_INCLUDE_PROPERTIES)
+ print_properties_on_new_lines (pp);
+}
+
+// See the comment above the declaration.
+void
+def_info::print_identifier (pretty_printer *pp) const
+{
+ resource ().print_identifier (pp);
+ pp_colon (pp);
+ insn ()->print_identifier (pp);
+ resource ().print_context (pp);
+}
+
+// See the comment above the declaration.
+void
+def_info::print_location (pretty_printer *pp) const
+{
+ insn ()->print_identifier_and_location (pp);
+}
+
+// See the comment above the declaration.
+void
+clobber_info::print (pretty_printer *pp, unsigned int flags) const
+{
+ print_prefix_flags (pp);
+ if (is_call_clobber ())
+ pp_string (pp, "call ");
+ pp_string (pp, "clobber ");
+ print_identifier (pp);
+ if (flags & PP_ACCESS_INCLUDE_LOCATION)
+ {
+ pp_string (pp, " in ");
+ insn ()->print_location (pp);
+ }
+ if (flags & PP_ACCESS_INCLUDE_PROPERTIES)
+ print_properties_on_new_lines (pp);
+}
+
+// See the comment above the declaration.
+void
+set_info::print_uses_on_new_lines (pretty_printer *pp) const
+{
+ for (const use_info *use : all_uses ())
+ {
+ pp_newline_and_indent (pp, 2);
+ if (use->is_live_out_use ())
+ {
+ pp_string (pp, "live out from ");
+ use->insn ()->print_location (pp);
+ }
+ else
+ {
+ pp_string (pp, "used by ");
+ use->print_location (pp);
+ }
+ pp_indentation (pp) -= 2;
+ }
+ if (m_use_tree)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "splay tree:");
+ pp_newline_and_indent (pp, 2);
+ auto print_use = [](pretty_printer *pp,
+ splay_tree_node<use_info *> *node)
+ {
+ pp_string (pp, "use by ");
+ node->value ()->print_location (pp);
+ };
+ m_use_tree.print (pp, m_use_tree.root (), print_use);
+ pp_indentation (pp) -= 4;
+ }
+}
+
+// See the comment above the declaration.
+void
+set_info::print (pretty_printer *pp, unsigned int flags) const
+{
+ print_prefix_flags (pp);
+ pp_string (pp, "set ");
+ print_identifier (pp);
+ if (flags & PP_ACCESS_INCLUDE_LOCATION)
+ {
+ pp_string (pp, " in ");
+ insn ()->print_location (pp);
+ }
+ if (flags & PP_ACCESS_INCLUDE_PROPERTIES)
+ print_properties_on_new_lines (pp);
+ if (flags & PP_ACCESS_INCLUDE_LINKS)
+ print_uses_on_new_lines (pp);
+}
+
+// See the comment above the declaration.
+void
+phi_info::print (pretty_printer *pp, unsigned int flags) const
+{
+ print_prefix_flags (pp);
+ pp_string (pp, "phi node ");
+ print_identifier (pp);
+ if (flags & PP_ACCESS_INCLUDE_LOCATION)
+ {
+ pp_string (pp, " in ");
+ insn ()->print_location (pp);
+ }
+
+ if (flags & PP_ACCESS_INCLUDE_PROPERTIES)
+ print_properties_on_new_lines (pp);
+
+ if (flags & PP_ACCESS_INCLUDE_LINKS)
+ {
+ basic_block cfg_bb = bb ()->cfg_bb ();
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "inputs:");
+ unsigned int i = 0;
+ for (const use_info *input : inputs ())
+ {
+ basic_block pred_cfg_bb = EDGE_PRED (cfg_bb, i)->src;
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "bb");
+ pp_decimal_int (pp, pred_cfg_bb->index);
+ pp_colon (pp);
+ pp_space (pp);
+ input->print_def (pp);
+ pp_indentation (pp) -= 2;
+ i += 1;
+ }
+ pp_indentation (pp) -= 2;
+
+ print_uses_on_new_lines (pp);
+ }
+}
+
+// See the comment above the declaration.
+void
+set_node::print (pretty_printer *pp) const
+{
+ pp_access (pp, first_def ());
+}
+
+// See the comment above the declaration.
+void
+clobber_group::print (pretty_printer *pp) const
+{
+ auto print_clobber = [](pretty_printer *pp, const def_info *clobber)
+ {
+ pp_access (pp, clobber);
+ };
+ pp_string (pp, "grouped clobber");
+ for (const def_info *clobber : clobbers ())
+ {
+ pp_newline_and_indent (pp, 2);
+ print_clobber (pp, clobber);
+ pp_indentation (pp) -= 2;
+ }
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "splay tree");
+ pp_newline_and_indent (pp, 2);
+ m_clobber_tree.print (pp, print_clobber);
+ pp_indentation (pp) -= 4;
+}
+
+// Return a clobber_group for CLOBBER, creating one if CLOBBER doesn't
+// already belong to a group.
+clobber_group *
+function_info::need_clobber_group (clobber_info *clobber)
+{
+ if (clobber->is_in_group ())
+ return clobber->group ();
+ return allocate<clobber_group> (clobber);
+}
+
+// Return a def_node for inserting DEF into the associated resource's
+// splay tree. Use a clobber_group if DEF is a clobber and a set_node
+// otherwise.
+def_node *
+function_info::need_def_node (def_info *def)
+{
+ if (auto *clobber = dyn_cast<clobber_info *> (def))
+ return need_clobber_group (clobber);
+ return allocate<set_node> (as_a<set_info *> (def));
+}
+
+// LAST is the last thing to define LAST->resource (), and is where any
+// splay tree root for LAST->resource () is stored. Require such a splay tree
+// to exist, creating a new one if necessary. Return the root of the tree.
+//
+// The caller must call LAST->set_splay_root after it has finished with
+// the splay tree.
+def_splay_tree
+function_info::need_def_splay_tree (def_info *last)
+{
+ if (def_node *root = last->splay_root ())
+ return root;
+
+ // Use a left-spine rooted at the last node.
+ def_node *root = need_def_node (last);
+ def_node *parent = root;
+ while (def_info *prev = first_def (parent)->prev_def ())
+ {
+ def_node *node = need_def_node (prev);
+ def_splay_tree::insert_child (parent, 0, node);
+ parent = node;
+ }
+ return root;
+}
+
+// Search TREE for either:
+//
+// - a set_info at INSN or
+// - a clobber_group whose range includes INSN
+//
+// If such a node exists, install it as the root of TREE and return 0.
+// Otherwise arbitrarily choose between:
+//
+// (1) Installing the closest preceding node as the root and returning 1.
+// (2) Installing the closest following node as the root and returning -1.
+//
+// Note that this routine should not be used to check whether INSN
+// itself defines a resource; that can be checked more cheaply using
+// find_access_index.
+int
+rtl_ssa::lookup_def (def_splay_tree &tree, insn_info *insn)
+{
+ auto go_left = [&](def_node *node)
+ {
+ return *insn < *first_def (node)->insn ();
+ };
+ auto go_right = [&](def_node *node)
+ {
+ return *insn > *last_def (node)->insn ();
+ };
+ return tree.lookup (go_left, go_right);
+}
+
+// Search TREE for a clobber in INSN. If such a clobber exists, install
+// it as the root of TREE and return 0. Otherwise arbitrarily choose between:
+//
+// (1) Installing the closest preceding clobber as the root and returning 1.
+// (2) Installing the closest following clobber as the root and returning -1.
+int
+rtl_ssa::lookup_clobber (clobber_tree &tree, insn_info *insn)
+{
+ auto compare = [&](clobber_info *clobber)
+ {
+ return insn->compare_with (clobber->insn ());
+ };
+ return tree.lookup (compare);
+}
+
+// Search for a definition of RESOURCE at INSN and return the result of
+// the search as a def_lookup. See the comment above the class for more
+// details.
+def_lookup
+function_info::find_def (resource_info resource, insn_info *insn)
+{
+ def_info *first = m_defs[resource.regno + 1];
+ if (!first)
+ // There are no nodes. The comparison result is pretty meaningless
+ // in this case.
+ return { nullptr, -1 };
+
+ // See whether the first node matches.
+ auto first_result = clobber_group_or_single_def (first);
+ if (*insn <= *last_def (first_result)->insn ())
+ {
+ int comparison = (*insn >= *first->insn () ? 0 : -1);
+ return { first_result, comparison };
+ }
+
+ // See whether the last node matches.
+ def_info *last = first->last_def ();
+ auto last_result = clobber_group_or_single_def (last);
+ if (*insn >= *first_def (last_result)->insn ())
+ {
+ int comparison = (*insn <= *last->insn () ? 0 : 1);
+ return { last_result, comparison };
+ }
+
+ // Resort to using a splay tree to search for the result.
+ def_splay_tree tree = need_def_splay_tree (last);
+ int comparison = lookup_def (tree, insn);
+ last->set_splay_root (tree.root ());
+ return { tree.root (), comparison };
+}
+
+// Add DEF to the function's list of definitions of DEF->resource (),
+// inserting DEF immediately before BEFORE. DEF is not currently in the list.
+void
+function_info::insert_def_before (def_info *def, def_info *before)
+{
+ gcc_checking_assert (!def->has_def_links ()
+ && *before->insn () > *def->insn ());
+
+ def->copy_prev_from (before);
+ if (def_info *prev = def->prev_def ())
+ {
+ gcc_checking_assert (*prev->insn () < *def->insn ());
+ prev->set_next_def (def);
+ }
+ else
+ m_defs[def->regno () + 1] = def;
+
+ def->set_next_def (before);
+ before->set_prev_def (def);
+}
+
+// Add DEF to the function's list of definitions of DEF->resource (),
+// inserting DEF immediately after AFTER. DEF is not currently in the list.
+void
+function_info::insert_def_after (def_info *def, def_info *after)
+{
+ gcc_checking_assert (!def->has_def_links ()
+ && *after->insn () < *def->insn ());
+
+ def->copy_next_from (after);
+ if (def_info *next = def->next_def ())
+ {
+ gcc_checking_assert (*next->insn () > *def->insn ());
+ next->set_prev_def (def);
+ }
+ else
+ m_defs[def->regno () + 1]->set_last_def (def);
+
+ def->set_prev_def (after);
+ after->set_next_def (def);
+}
+
+// Remove DEF from the function's list of definitions of DEF->resource ().
+void
+function_info::remove_def_from_list (def_info *def)
+{
+ def_info *prev = def->prev_def ();
+ def_info *next = def->next_def ();
+
+ if (next)
+ next->copy_prev_from (def);
+ else
+ m_defs[def->regno () + 1]->set_last_def (prev);
+
+ if (prev)
+ prev->copy_next_from (def);
+ else
+ m_defs[def->regno () + 1] = next;
+
+ def->clear_def_links ();
+}
+
+// Add CLOBBER to GROUP and insert it into the function's list of
+// accesses to CLOBBER->resource (). CLOBBER is not currently part
+// of an active group and is not currently in the list.
+void
+function_info::add_clobber (clobber_info *clobber, clobber_group *group)
+{
+ // Search for either the previous or next clobber in the group.
+ // The result is less than zero if CLOBBER should come before NEIGHBOR
+ // or greater than zero if CLOBBER should come after NEIGHBOR.
+ int comparison = lookup_clobber (group->m_clobber_tree, clobber->insn ());
+ gcc_checking_assert (comparison != 0);
+ clobber_info *neighbor = group->m_clobber_tree.root ();
+
+ // Since HEIGHBOR is now the root of the splay tree, its group needs
+ // to be up-to-date.
+ neighbor->update_group (group);
+
+ // If CLOBBER comes before NEIGHBOR, insert CLOBBER to NEIGHBOR's left,
+ // otherwise insert CLOBBER to NEIGHBOR's right.
+ clobber_info::splay_tree::insert_child (neighbor, comparison > 0, clobber);
+ clobber->set_group (group);
+
+ // Insert the clobber into the function-wide list and update the
+ // bounds of the group.
+ if (comparison > 0)
+ {
+ insert_def_after (clobber, neighbor);
+ if (neighbor == group->last_clobber ())
+ group->set_last_clobber (clobber);
+ }
+ else
+ {
+ insert_def_before (clobber, neighbor);
+ if (neighbor == group->first_clobber ())
+ group->set_first_clobber (clobber);
+ }
+}
+
+// Remove CLOBBER from GROUP, given that GROUP contains other clobbers too.
+// Also remove CLOBBER from the function's list of accesses to
+// CLOBBER->resource ().
+void
+function_info::remove_clobber (clobber_info *clobber, clobber_group *group)
+{
+ if (clobber == group->first_clobber ())
+ {
+ auto *new_first = as_a<clobber_info *> (clobber->next_def ());
+ group->set_first_clobber (new_first);
+ new_first->update_group (group);
+ }
+ else if (clobber == group->last_clobber ())
+ {
+ auto *new_last = as_a<clobber_info *> (clobber->prev_def ());
+ group->set_last_clobber (new_last);
+ new_last->update_group (group);
+ }
+
+ clobber_info *replacement = clobber_info::splay_tree::remove_node (clobber);
+ if (clobber == group->m_clobber_tree.root ())
+ {
+ group->m_clobber_tree = replacement;
+ replacement->update_group (group);
+ }
+ clobber->set_group (nullptr);
+
+ remove_def_from_list (clobber);
+}
+
+// Add CLOBBER immediately before the first clobber in GROUP, given that
+// CLOBBER is not currently part of any group.
+void
+function_info::prepend_clobber_to_group (clobber_info *clobber,
+ clobber_group *group)
+{
+ clobber_info *next = group->first_clobber ();
+ clobber_info::splay_tree::insert_child (next, 0, clobber);
+ group->set_first_clobber (clobber);
+ clobber->set_group (group);
+}
+
+// Add CLOBBER immediately after the last clobber in GROUP, given that
+// CLOBBER is not currently part of any group.
+void
+function_info::append_clobber_to_group (clobber_info *clobber,
+ clobber_group *group)
+{
+ clobber_info *prev = group->last_clobber ();
+ clobber_info::splay_tree::insert_child (prev, 1, clobber);
+ group->set_last_clobber (clobber);
+ clobber->set_group (group);
+}
+
+// Put CLOBBER1 and CLOBBER2 into the same clobber_group, given that
+// CLOBBER1 occurs immediately before CLOBBER2 and that the two clobbers
+// are not currently in the same group. LAST is the last definition of
+// the associated resource, and is where any splay tree is stored.
+void
+function_info::merge_clobber_groups (clobber_info *clobber1,
+ clobber_info *clobber2,
+ def_info *last)
+{
+ if (clobber1->is_in_group () && clobber2->is_in_group ())
+ {
+ clobber_group *group1 = clobber1->group ();
+ clobber_group *group2 = clobber2->group ();
+ gcc_checking_assert (clobber1 == group1->last_clobber ()
+ && clobber2 == group2->first_clobber ());
+
+ if (def_splay_tree tree = last->splay_root ())
+ {
+ // Remove GROUP2 from the splay tree.
+ int comparison = lookup_def (tree, clobber2->insn ());
+ gcc_checking_assert (comparison == 0);
+ tree.remove_root ();
+ last->set_splay_root (tree.root ());
+ }
+
+ // Splice the trees together.
+ group1->m_clobber_tree.splice_next_tree (group2->m_clobber_tree);
+
+ // Bring the two extremes of GROUP2 under GROUP1. Any other
+ // clobbers in the group are updated lazily on demand.
+ clobber2->set_group (group1);
+ group2->last_clobber ()->set_group (group1);
+ group1->set_last_clobber (group2->last_clobber ());
+
+ // Record that GROUP2 is no more.
+ group2->set_first_clobber (nullptr);
+ group2->set_last_clobber (nullptr);
+ group2->m_clobber_tree = nullptr;
+ }
+ else
+ {
+ // In this case there can be no active splay tree.
+ gcc_assert (!last->splay_root ());
+ if (clobber2->is_in_group ())
+ prepend_clobber_to_group (clobber1, clobber2->group ());
+ else
+ append_clobber_to_group (clobber2, need_clobber_group (clobber1));
+ }
+}
+
+// GROUP spans INSN, and INSN now sets the resource that GROUP clobbers.
+// Split GROUP around INSN and return the clobber that comes immediately
+// before INSN.
+clobber_info *
+function_info::split_clobber_group (clobber_group *group, insn_info *insn)
+{
+ // Search for either the previous or next clobber in the group.
+ // The result is less than zero if CLOBBER should come before NEIGHBOR
+ // or greater than zero if CLOBBER should come after NEIGHBOR.
+ int comparison = lookup_clobber (group->m_clobber_tree, insn);
+ gcc_checking_assert (comparison != 0);
+ clobber_info *neighbor = group->m_clobber_tree.root ();
+
+ clobber_tree tree1, tree2;
+ clobber_info *prev;
+ clobber_info *next;
+ if (comparison > 0)
+ {
+ // NEIGHBOR is the last clobber in what will become the first group.
+ tree1 = neighbor;
+ tree2 = tree1.split_after_root ();
+ prev = neighbor;
+ next = as_a<clobber_info *> (prev->next_def ());
+ }
+ else
+ {
+ // NEIGHBOR is the first clobber in what will become the second group.
+ tree2 = neighbor;
+ tree1 = tree2.split_before_root ();
+ next = neighbor;
+ prev = as_a<clobber_info *> (next->prev_def ());
+ }
+
+ // Use GROUP to hold PREV and earlier clobbers. Create a new group for
+ // NEXT onwards.
+ clobber_info *last_clobber = group->last_clobber ();
+ clobber_group *group1 = group;
+ clobber_group *group2 = allocate<clobber_group> (next);
+
+ // Finish setting up GROUP1, making sure that the roots and extremities
+ // have a correct group pointer. Leave the rest to be updated lazily.
+ group1->set_last_clobber (prev);
+ tree1->set_group (group1);
+ prev->set_group (group1);
+
+ // Finish setting up GROUP2, with the same approach as for GROUP1.
+ group2->set_first_clobber (next);
+ group2->set_last_clobber (last_clobber);
+ next->set_group (group2);
+ tree2->set_group (group2);
+ last_clobber->set_group (group2);
+
+ return prev;
+}
+
+// Add DEF to the end of the function's list of definitions of
+// DEF->resource (). There is known to be no associated splay tree yet.
+void
+function_info::append_def (def_info *def)
+{
+ gcc_checking_assert (!def->has_def_links ());
+ def_info **head = &m_defs[def->regno () + 1];
+ def_info *first = *head;
+ if (!first)
+ {
+ // This is the only definition of the resource.
+ def->set_last_def (def);
+ *head = def;
+ return;
+ }
+
+ def_info *prev = first->last_def ();
+ gcc_checking_assert (!prev->splay_root ());
+
+ // Maintain the invariant that two clobbers must not appear in
+ // neighboring nodes of the splay tree.
+ auto *clobber = dyn_cast<clobber_info *> (def);
+ auto *prev_clobber = dyn_cast<clobber_info *> (prev);
+ if (clobber && prev_clobber)
+ append_clobber_to_group (clobber, need_clobber_group (prev_clobber));
+
+ prev->set_next_def (def);
+ def->set_prev_def (prev);
+ first->set_last_def (def);
+}
+
+// Add DEF to the function's list of definitions of DEF->resource ().
+// Also insert it into the associated splay tree, if there is one.
+// DEF is not currently part of the list and is not in the splay tree.
+void
+function_info::add_def (def_info *def)
+{
+ gcc_checking_assert (!def->has_def_links ()
+ && !def->m_is_temp
+ && !def->m_has_been_superceded);
+ def_info **head = &m_defs[def->regno () + 1];
+ def_info *first = *head;
+ if (!first)
+ {
+ // This is the only definition of the resource.
+ def->set_last_def (def);
+ *head = def;
+ return;
+ }
+
+ def_info *last = first->last_def ();
+ insn_info *insn = def->insn ();
+
+ int comparison;
+ def_node *root = nullptr;
+ def_info *prev = nullptr;
+ def_info *next = nullptr;
+ if (*insn > *last->insn ())
+ {
+ // This definition comes after all other definitions.
+ comparison = 1;
+ if (def_splay_tree tree = last->splay_root ())
+ {
+ tree.splay_max_node ();
+ root = tree.root ();
+ last->set_splay_root (root);
+ }
+ prev = last;
+ }
+ else if (*insn < *first->insn ())
+ {
+ // This definition comes before all other definitions.
+ comparison = -1;
+ if (def_splay_tree tree = last->splay_root ())
+ {
+ tree.splay_min_node ();
+ root = tree.root ();
+ last->set_splay_root (root);
+ }
+ next = first;
+ }
+ else
+ {
+ // Search the splay tree for an insertion point.
+ def_splay_tree tree = need_def_splay_tree (last);
+ comparison = lookup_def (tree, insn);
+ root = tree.root ();
+ last->set_splay_root (root);
+
+ // Deal with cases in which we found an overlapping live range.
+ if (comparison == 0)
+ {
+ auto *group = as_a<clobber_group *> (tree.root ());
+ if (auto *clobber = dyn_cast<clobber_info *> (def))
+ {
+ add_clobber (clobber, group);
+ return;
+ }
+ prev = split_clobber_group (group, insn);
+ next = prev->next_def ();
+ }
+ // COMPARISON is < 0 if DEF comes before ROOT or > 0 if DEF comes
+ // after ROOT.
+ else if (comparison < 0)
+ {
+ next = first_def (root);
+ prev = next->prev_def ();
+ }
+ else
+ {
+ prev = last_def (root);
+ next = prev->next_def ();
+ }
+ }
+
+ // See if we should merge CLOBBER with a neighboring clobber.
+ auto *clobber = dyn_cast<clobber_info *> (def);
+ auto *prev_clobber = safe_dyn_cast<clobber_info *> (prev);
+ auto *next_clobber = safe_dyn_cast<clobber_info *> (next);
+ // We shouldn't have consecutive clobber_groups.
+ gcc_checking_assert (!(clobber && prev_clobber && next_clobber));
+ if (clobber && prev_clobber)
+ append_clobber_to_group (clobber, need_clobber_group (prev_clobber));
+ else if (clobber && next_clobber)
+ prepend_clobber_to_group (clobber, need_clobber_group (next_clobber));
+ else if (root)
+ {
+ // If DEF comes before ROOT, insert DEF to ROOT's left,
+ // otherwise insert DEF to ROOT's right.
+ def_node *node = need_def_node (def);
+ def_splay_tree::insert_child (root, comparison >= 0, node);
+ }
+ if (prev)
+ insert_def_after (def, prev);
+ else
+ insert_def_before (def, next);
+}
+
+// Remove DEF from the function's list of definitions of DEF->resource ().
+// Also remove DEF from the associated splay tree, if there is one.
+void
+function_info::remove_def (def_info *def)
+{
+ def_info **head = &m_defs[def->regno () + 1];
+ def_info *first = *head;
+ gcc_checking_assert (first);
+ if (first->is_last_def ())
+ {
+ // DEF is the only definition of the resource.
+ gcc_checking_assert (first == def);
+ *head = nullptr;
+ def->clear_def_links ();
+ return;
+ }
+
+ // If CLOBBER belongs to a clobber_group that contains other clobbers
+ // too, then we need to update the clobber_group and the list, but any
+ // splay tree that contains the clobber_group is unaffected.
+ if (auto *clobber = dyn_cast<clobber_info *> (def))
+ if (clobber->is_in_group ())
+ {
+ clobber_group *group = clobber->group ();
+ if (group->first_clobber () != group->last_clobber ())
+ {
+ remove_clobber (clobber, group);
+ return;
+ }
+ }
+
+ // If we've created a splay tree for this resource, remove the entry
+ // for DEF.
+ def_info *last = first->last_def ();
+ if (def_splay_tree tree = last->splay_root ())
+ {
+ int comparison = lookup_def (tree, def->insn ());
+ gcc_checking_assert (comparison == 0);
+ tree.remove_root ();
+ last->set_splay_root (tree.root ());
+ }
+
+ // If the definition came between two clobbers, merge them into a single
+ // group.
+ auto *prev_clobber = safe_dyn_cast<clobber_info *> (def->prev_def ());
+ auto *next_clobber = safe_dyn_cast<clobber_info *> (def->next_def ());
+ if (prev_clobber && next_clobber)
+ merge_clobber_groups (prev_clobber, next_clobber, last);
+
+ remove_def_from_list (def);
+}
+
+// Require DEF to have a splay tree that contains all non-phi uses.
+void
+function_info::need_use_splay_tree (set_info *def)
+{
+ if (!def->m_use_tree)
+ for (use_info *use : def->all_insn_uses ())
+ {
+ auto *use_node = allocate<splay_tree_node<use_info *>> (use);
+ def->m_use_tree.insert_max_node (use_node);
+ }
+}
+
+// Compare two instructions by their position in a use splay tree. Return >0
+// if INSN1 comes after INSN2, <0 if INSN1 comes before INSN2, or 0 if they are
+// the same instruction.
+static inline int
+compare_use_insns (insn_info *insn1, insn_info *insn2)
+{
+ // Debug instructions go after nondebug instructions.
+ int diff = insn1->is_debug_insn () - insn2->is_debug_insn ();
+ if (diff != 0)
+ return diff;
+ return insn1->compare_with (insn2);
+}
+
+// Search TREE for a use in INSN. If such a use exists, install it as
+// the root of TREE and return 0. Otherwise arbitrarily choose between:
+//
+// (1) Installing the closest preceding use as the root and returning 1.
+// (2) Installing the closest following use as the root and returning -1.
+int
+rtl_ssa::lookup_use (splay_tree<use_info *> &tree, insn_info *insn)
+{
+ auto compare = [&](splay_tree_node<use_info *> *node)
+ {
+ return compare_use_insns (insn, node->value ()->insn ());
+ };
+ return tree.lookup (compare);
+}
+
+// Add USE to USE->def ()'s list of uses. inserting USE immediately before
+// BEFORE. USE is not currently in the list.
+//
+// This routine should not be used for inserting phi uses.
+void
+function_info::insert_use_before (use_info *use, use_info *before)
+{
+ gcc_checking_assert (!use->has_use_links () && use->is_in_any_insn ());
+
+ set_info *def = use->def ();
+
+ use->copy_prev_from (before);
+ use->set_next_use (before);
+
+ if (use_info *prev = use->prev_use ())
+ prev->set_next_use (use);
+ else
+ use->def ()->set_first_use (use);
+
+ before->set_prev_use (use);
+ if (use->is_in_nondebug_insn () && before->is_in_debug_insn_or_phi ())
+ def->last_use ()->set_last_nondebug_insn_use (use);
+
+ gcc_checking_assert (use->check_integrity () && before->check_integrity ());
+}
+
+// Add USE to USE->def ()'s list of uses. inserting USE immediately after
+// AFTER. USE is not currently in the list.
+//
+// This routine should not be used for inserting phi uses.
+void
+function_info::insert_use_after (use_info *use, use_info *after)
+{
+ set_info *def = use->def ();
+ gcc_checking_assert (after->is_in_any_insn ()
+ && !use->has_use_links ()
+ && use->is_in_any_insn ());
+
+ use->set_prev_use (after);
+ use->copy_next_from (after);
+
+ after->set_next_use (use);
+
+ if (use_info *next = use->next_use ())
+ {
+ // The last node doesn't change, but we might need to update its
+ // last_nondebug_insn_use record.
+ if (use->is_in_nondebug_insn () && next->is_in_debug_insn_or_phi ())
+ def->last_use ()->set_last_nondebug_insn_use (use);
+ next->set_prev_use (use);
+ }
+ else
+ {
+ // USE is now the last node.
+ if (use->is_in_nondebug_insn ())
+ use->set_last_nondebug_insn_use (use);
+ def->first_use ()->set_last_use (use);
+ }
+
+ gcc_checking_assert (use->check_integrity () && after->check_integrity ());
+}
+
+// If USE has a known definition, add USE to that definition's list of uses.
+// Also update the associated splay tree, if any.
+void
+function_info::add_use (use_info *use)
+{
+ gcc_checking_assert (!use->has_use_links ()
+ && !use->m_is_temp
+ && !use->m_has_been_superceded);
+
+ set_info *def = use->def ();
+ if (!def)
+ return;
+
+ use_info *first = def->first_use ();
+ if (!first)
+ {
+ // This is the only use of the definition.
+ use->set_last_use (use);
+ if (use->is_in_nondebug_insn ())
+ use->set_last_nondebug_insn_use (use);
+
+ def->set_first_use (use);
+
+ gcc_checking_assert (use->check_integrity ());
+ return;
+ }
+
+ if (use->is_in_phi ())
+ {
+ // Add USE at the end of the list, as the new first phi.
+ use_info *last = first->last_use ();
+
+ use->set_prev_use (last);
+ use->copy_next_from (last);
+
+ last->set_next_use (use);
+ first->set_last_use (use);
+
+ gcc_checking_assert (use->check_integrity ());
+ return;
+ }
+
+ // If there is currently no splay tree for this definition, see if can
+ // get away with a pure list-based update.
+ insn_info *insn = use->insn ();
+ auto quick_path = [&]()
+ {
+ // Check if USE should come before all current uses.
+ if (first->is_in_phi () || compare_use_insns (insn, first->insn ()) < 0)
+ {
+ insert_use_before (use, first);
+ return true;
+ }
+
+ // Check if USE should come after all current uses in the same
+ // subsequence (i.e. the list of nondebug insn uses or the list
+ // of debug insn uses).
+ use_info *last = first->last_use ();
+ if (use->is_in_debug_insn ())
+ {
+ if (last->is_in_phi ())
+ return false;
+ }
+ else
+ last = last->last_nondebug_insn_use ();
+
+ if (compare_use_insns (insn, last->insn ()) > 0)
+ {
+ insert_use_after (use, last);
+ return true;
+ }
+
+ return false;
+ };
+ if (!def->m_use_tree && quick_path ())
+ return;
+
+ // Search the splay tree for an insertion point. COMPARISON is less
+ // than zero if USE should come before NEIGHBOR, or greater than zero
+ // if USE should come after NEIGHBOR.
+ need_use_splay_tree (def);
+ int comparison = lookup_use (def->m_use_tree, insn);
+ gcc_checking_assert (comparison != 0);
+ splay_tree_node<use_info *> *neighbor = def->m_use_tree.root ();
+
+ // If USE comes before NEIGHBOR, insert USE to NEIGHBOR's left,
+ // otherwise insert USE to NEIGHBOR's right.
+ auto *use_node = allocate<splay_tree_node<use_info *>> (use);
+ def->m_use_tree.insert_child (neighbor, comparison > 0, use_node);
+ if (comparison > 0)
+ insert_use_after (use, neighbor->value ());
+ else
+ insert_use_before (use, neighbor->value ());
+}
+
+// If USE has a known definition, remove USE from that definition's list
+// of uses. Also remove if it from the associated splay tree, if any.
+void
+function_info::remove_use (use_info *use)
+{
+ set_info *def = use->def ();
+ if (!def)
+ return;
+
+ // Remove USE from the splay tree.
+ if (def->m_use_tree && use->is_in_any_insn ())
+ {
+ int comparison = lookup_use (def->m_use_tree, use->insn ());
+ gcc_checking_assert (comparison == 0);
+ def->m_use_tree.remove_root ();
+ }
+
+ use_info *prev = use->prev_use ();
+ use_info *next = use->next_use ();
+
+ use_info *first = def->first_use ();
+ use_info *last = first->last_use ();
+ if (last->last_nondebug_insn_use () == use)
+ last->set_last_nondebug_insn_use (prev);
+
+ if (next)
+ next->copy_prev_from (use);
+ else
+ first->set_last_use (prev);
+
+ if (prev)
+ prev->copy_next_from (use);
+ else
+ def->set_first_use (next);
+
+ use->clear_use_links ();
+ gcc_checking_assert ((!prev || prev->check_integrity ())
+ && (!next || next->check_integrity ()));
+}
+
+// Allocate a temporary clobber_info for register REGNO in insn INSN,
+// including it in the region of the obstack governed by WATERMARK.
+// Return a new def_array that contains OLD_DEFS and the new clobber.
+//
+// OLD_DEFS is known not to define REGNO.
+def_array
+function_info::insert_temp_clobber (obstack_watermark &watermark,
+ insn_info *insn, unsigned int regno,
+ def_array old_defs)
+{
+ gcc_checking_assert (watermark == &m_temp_obstack);
+ auto *clobber = allocate_temp<clobber_info> (insn, regno);
+ clobber->m_is_temp = true;
+ return insert_access (watermark, clobber, old_defs);
+}
+
+// A subroutine of make_uses_available. Try to make USE's definition
+// available at the head of BB. On success:
+//
+// - If the use would have the same def () as USE, return USE.
+//
+// - If BB already has a degenerate phi for the same definition,
+// return a temporary use of that phi.
+//
+// - Otherwise, the use would need a new degenerate phi. Allocate a
+// temporary phi and return a temporary use of it.
+//
+// Return null on failure.
+use_info *
+function_info::make_use_available (use_info *use, bb_info *bb)
+{
+ set_info *def = use->def ();
+ if (!def)
+ return use;
+
+ if (is_single_dominating_def (def))
+ return use;
+
+ // FIXME: Deliberately limited for fwprop compatibility testing.
+ basic_block cfg_bb = bb->cfg_bb ();
+ bb_info *use_bb = use->bb ();
+ if (single_pred_p (cfg_bb)
+ && single_pred (cfg_bb) == use_bb->cfg_bb ()
+ && remains_available_on_exit (def, use_bb))
+ {
+ if (def->ebb () == bb->ebb ())
+ return use;
+
+ resource_info resource = use->resource ();
+ set_info *ultimate_def = look_through_degenerate_phi (def);
+
+ // See if there is already a (degenerate) phi for DEF.
+ insn_info *phi_insn = bb->ebb ()->phi_insn ();
+ phi_info *phi;
+ def_lookup dl = find_def (resource, phi_insn);
+ if (set_info *set = dl.matching_set ())
+ {
+ // There is an existing phi.
+ phi = as_a<phi_info *> (set);
+ gcc_checking_assert (phi->input_value (0) == ultimate_def);
+ }
+ else
+ {
+ // Create a temporary placeholder phi. This will become
+ // permanent if the change is later committed.
+ phi = allocate_temp<phi_info> (phi_insn, resource, 0);
+ auto *input = allocate<use_info> (phi, resource, ultimate_def);
+ input->m_is_temp = true;
+ phi->m_is_temp = true;
+ phi->make_degenerate (input);
+ if (def_info *prev = dl.prev_def ())
+ phi->set_prev_def (prev);
+ if (def_info *next = dl.next_def ())
+ phi->set_next_def (next);
+ }
+
+ // Create a temporary use of the phi at the head of the first
+ // block, since we know for sure that it's available there.
+ insn_info *use_insn = bb->ebb ()->first_bb ()->head_insn ();
+ auto *new_use = allocate_temp<use_info> (use_insn, resource, phi);
+ new_use->m_is_temp = true;
+ return new_use;
+ }
+ return nullptr;
+}
+
+// See the comment above the declaration.
+use_array
+function_info::make_uses_available (obstack_watermark &watermark,
+ use_array uses, bb_info *bb)
+{
+ unsigned int num_uses = uses.size ();
+ if (num_uses == 0)
+ return uses;
+
+ auto **new_uses = XOBNEWVEC (watermark, access_info *, num_uses);
+ for (unsigned int i = 0; i < num_uses; ++i)
+ {
+ use_info *use = make_use_available (uses[i], bb);
+ if (!use)
+ return use_array (access_array::invalid ());
+ new_uses[i] = use;
+ }
+ return use_array (new_uses, num_uses);
+}
+
+// Return true if ACCESS1 can represent ACCESS2 and if ACCESS2 can
+// represent ACCESS1.
+static bool
+can_merge_accesses (access_info *access1, access_info *access2)
+{
+ if (access1 == access2)
+ return true;
+
+ auto *use1 = dyn_cast<use_info *> (access1);
+ auto *use2 = dyn_cast<use_info *> (access2);
+ return use1 && use2 && use1->def () == use2->def ();
+}
+
+// See the comment above the declaration.
+access_array
+rtl_ssa::merge_access_arrays_base (obstack_watermark &watermark,
+ access_array accesses1,
+ access_array accesses2)
+{
+ if (accesses1.empty ())
+ return accesses2;
+ if (accesses2.empty ())
+ return accesses1;
+
+ auto i1 = accesses1.begin ();
+ auto end1 = accesses1.end ();
+ auto i2 = accesses2.begin ();
+ auto end2 = accesses2.end ();
+
+ access_array_builder builder (watermark);
+ builder.reserve (accesses1.size () + accesses2.size ());
+
+ while (i1 != end1 && i2 != end2)
+ {
+ access_info *access1 = *i1;
+ access_info *access2 = *i2;
+
+ unsigned int regno1 = access1->regno ();
+ unsigned int regno2 = access2->regno ();
+ if (regno1 == regno2)
+ {
+ if (!can_merge_accesses (access1, access2))
+ return access_array::invalid ();
+
+ builder.quick_push (access1);
+ ++i1;
+ ++i2;
+ }
+ else if (regno1 < regno2)
+ {
+ builder.quick_push (access1);
+ ++i1;
+ }
+ else
+ {
+ builder.quick_push (access2);
+ ++i2;
+ }
+ }
+ for (; i1 != end1; ++i1)
+ builder.quick_push (*i1);
+ for (; i2 != end2; ++i2)
+ builder.quick_push (*i2);
+
+ return builder.finish ();
+}
+
+// See the comment above the declaration.
+access_array
+rtl_ssa::insert_access_base (obstack_watermark &watermark,
+ access_info *access1, access_array accesses2)
+{
+ access_array_builder builder (watermark);
+ builder.reserve (1 + accesses2.size ());
+
+ unsigned int regno1 = access1->regno ();
+ auto i2 = accesses2.begin ();
+ auto end2 = accesses2.end ();
+ while (i2 != end2)
+ {
+ access_info *access2 = *i2;
+
+ unsigned int regno2 = access2->regno ();
+ if (regno1 == regno2)
+ {
+ if (!can_merge_accesses (access1, access2))
+ return access_array::invalid ();
+
+ builder.quick_push (access1);
+ access1 = nullptr;
+ ++i2;
+ break;
+ }
+ else if (regno1 < regno2)
+ {
+ builder.quick_push (access1);
+ access1 = nullptr;
+ break;
+ }
+ else
+ {
+ builder.quick_push (access2);
+ ++i2;
+ }
+ }
+ if (access1)
+ builder.quick_push (access1);
+ for (; i2 != end2; ++i2)
+ builder.quick_push (*i2);
+
+ return builder.finish ();
+}
+
+// See the comment above the declaration.
+access_array
+rtl_ssa::remove_note_accesses_base (obstack_watermark &watermark,
+ access_array accesses)
+{
+ for (access_info *access : accesses)
+ if (access->only_occurs_in_notes ())
+ {
+ access_array_builder builder (watermark);
+ builder.reserve (accesses.size ());
+ for (access_info *access2 : accesses)
+ if (!access2->only_occurs_in_notes ())
+ builder.quick_push (access2);
+ return builder.finish ();
+ }
+ return accesses;
+}
+
+// Print RESOURCE to PP.
+void
+rtl_ssa::pp_resource (pretty_printer *pp, resource_info resource)
+{
+ resource.print (pp);
+}
+
+// Print ACCESS to PP. FLAGS is a bitmask of PP_ACCESS_* flags.
+void
+rtl_ssa::pp_access (pretty_printer *pp, const access_info *access,
+ unsigned int flags)
+{
+ if (!access)
+ pp_string (pp, "<null>");
+ else if (auto *phi = dyn_cast<const phi_info *> (access))
+ phi->print (pp, flags);
+ else if (auto *set = dyn_cast<const set_info *> (access))
+ set->print (pp, flags);
+ else if (auto *clobber = dyn_cast<const clobber_info *> (access))
+ clobber->print (pp, flags);
+ else if (auto *use = dyn_cast<const use_info *> (access))
+ use->print (pp, flags);
+ else
+ pp_string (pp, "??? Unknown access");
+}
+
+// Print ACCESSES to PP. FLAGS is a bitmask of PP_ACCESS_* flags.
+void
+rtl_ssa::pp_accesses (pretty_printer *pp, access_array accesses,
+ unsigned int flags)
+{
+ if (accesses.empty ())
+ pp_string (pp, "none");
+ else
+ {
+ bool is_first = true;
+ for (access_info *access : accesses)
+ {
+ if (is_first)
+ is_first = false;
+ else
+ pp_newline_and_indent (pp, 0);
+ pp_access (pp, access, flags);
+ }
+ }
+}
+
+// Print NODE to PP.
+void
+rtl_ssa::pp_def_node (pretty_printer *pp, const def_node *node)
+{
+ if (!node)
+ pp_string (pp, "<null>");
+ else if (auto *group = dyn_cast<const clobber_group *> (node))
+ group->print (pp);
+ else if (auto *set = dyn_cast<const set_node *> (node))
+ set->print (pp);
+ else
+ pp_string (pp, "??? Unknown def node");
+}
+
+// Print MUX to PP.
+void
+rtl_ssa::pp_def_mux (pretty_printer *pp, def_mux mux)
+{
+ if (auto *node = mux.dyn_cast<def_node *> ())
+ pp_def_node (pp, node);
+ else
+ pp_access (pp, mux.as_a<def_info *> ());
+}
+
+// Print DL to PP.
+void
+rtl_ssa::pp_def_lookup (pretty_printer *pp, def_lookup dl)
+{
+ pp_string (pp, "comparison result of ");
+ pp_decimal_int (pp, dl.comparison);
+ pp_string (pp, " for ");
+ pp_newline_and_indent (pp, 0);
+ pp_def_mux (pp, dl.mux);
+}
+
+// Dump RESOURCE to FILE.
+void
+dump (FILE *file, resource_info resource)
+{
+ dump_using (file, pp_resource, resource);
+}
+
+// Dump ACCESS to FILE. FLAGS is a bitmask of PP_ACCESS_* flags.
+void
+dump (FILE *file, const access_info *access, unsigned int flags)
+{
+ dump_using (file, pp_access, access, flags);
+}
+
+// Dump ACCESSES to FILE. FLAGS is a bitmask of PP_ACCESS_* flags.
+void
+dump (FILE *file, access_array accesses, unsigned int flags)
+{
+ dump_using (file, pp_accesses, accesses, flags);
+}
+
+// Print NODE to FILE.
+void
+dump (FILE *file, const def_node *node)
+{
+ dump_using (file, pp_def_node, node);
+}
+
+// Print MUX to FILE.
+void
+dump (FILE *file, def_mux mux)
+{
+ dump_using (file, pp_def_mux, mux);
+}
+
+// Print RESULT to FILE.
+void
+dump (FILE *file, def_lookup result)
+{
+ dump_using (file, pp_def_lookup, result);
+}
+
+// Debug interfaces to the dump routines above.
+void debug (const resource_info &x) { dump (stderr, x); }
+void debug (const access_info *x) { dump (stderr, x); }
+void debug (const access_array &x) { dump (stderr, x); }
+void debug (const def_node *x) { dump (stderr, x); }
+void debug (const def_mux &x) { dump (stderr, x); }
+void debug (const def_lookup &x) { dump (stderr, x); }
diff --git a/gcc/rtl-ssa/accesses.h b/gcc/rtl-ssa/accesses.h
new file mode 100644
index 0000000..fdb4a64
--- /dev/null
+++ b/gcc/rtl-ssa/accesses.h
@@ -0,0 +1,1032 @@
+// Access-related classes for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// Forward declarations.
+class bb_info;
+class clobber_group;
+class def_node;
+class ebb_info;
+class insn_info;
+class phi_info;
+class set_info;
+
+// Used as a boolean argunent to certain routines.
+enum class ignore_clobbers { NO, YES };
+
+// Represents something that the SSA form tracks: either a register
+// or memory.
+class resource_info
+{
+public:
+ // Return true if this resource represents memory.
+ bool is_mem () const { return regno == MEM_REGNO; }
+
+ // Return true if this resource represents a register.
+ bool is_reg () const { return regno != MEM_REGNO; }
+
+ // Print the name of the resource to PP.
+ void print_identifier (pretty_printer *pp) const;
+
+ // Possibly print additional information about the resource to PP.
+ void print_context (pretty_printer *pp) const;
+
+ // A combination of print_identifier and print_context.
+ void print (pretty_printer *pp) const;
+
+ // The mode with which the resource is being defined or used. This is
+ // always BLKmode for memory. It can also be BLKmode for registers if
+ // we don't yet know the real mode, or if the mode is not relevant for
+ // some reason.
+ machine_mode mode;
+
+ // The pseudo register or single hard register that the resource represents,
+ // or MEM_REGNO for memory.
+ unsigned int regno;
+};
+
+// For simplicity, we treat memory as a single unified entity.
+const resource_info memory = { E_BLKmode, MEM_REGNO };
+
+// Flags used when printing access_infos.
+//
+// Print the location at which the access occurs. This is redundant
+// when the access is being printed as part of the instruction or phi node
+// that contains the access.
+const unsigned int PP_ACCESS_INCLUDE_LOCATION = 1U << 0;
+//
+// Print links to other accesses: the definition that defines a use,
+// the uses of a definition, and the inputs of a phi node.
+const unsigned int PP_ACCESS_INCLUDE_LINKS = 1U << 1;
+//
+// Print additional properties about the access.
+const unsigned int PP_ACCESS_INCLUDE_PROPERTIES = 1U << 2;
+//
+// The usual flags when printing an access in isolation.
+const unsigned int PP_ACCESS_DEFAULT = (PP_ACCESS_INCLUDE_LOCATION
+ | PP_ACCESS_INCLUDE_LINKS
+ | PP_ACCESS_INCLUDE_PROPERTIES);
+//
+// The usual flags when printing a def_info from its defining instruction.
+const unsigned int PP_ACCESS_SETTER = (PP_ACCESS_INCLUDE_LINKS
+ | PP_ACCESS_INCLUDE_PROPERTIES);
+//
+// The usual flags when printing a use_info from its user.
+const unsigned int PP_ACCESS_USER = PP_ACCESS_INCLUDE_PROPERTIES;
+
+// The various ways of accessing a resource. The two range checks that
+// we need to perform are [SET, PHI] (for set_info) and [SET, CLOBBER]
+// (for def_info), so the ordering tries to make those tests as
+// efficient as possible.
+enum class access_kind : uint8_t
+{
+ // Set the resource to a useful value.
+ SET,
+
+ // A form of SET that collects the possible incoming values of the
+ // resource using a phi node; the resource does not actually change value.
+ PHI,
+
+ // Set the resource to a value that is both unknown and not useful.
+ CLOBBER,
+
+ // Use the current value of the resource.
+ USE
+};
+
+// A base class that represents an access to a resource.
+class access_info
+{
+ // Size: 1 LP64 word
+ friend class function_info;
+
+public:
+ // Return the resource that is being accessed.
+ resource_info resource () const { return { m_mode, m_regno }; }
+
+ // Return true if the access is to memory.
+ bool is_mem () const { return m_regno == MEM_REGNO; }
+
+ // Return true if the access is to a register.
+ bool is_reg () const { return m_regno != MEM_REGNO; }
+
+ // If the access is to a register, return the register number,
+ // otherwise return MEM_REGNO.
+ unsigned int regno () const { return m_regno; }
+
+ // For sets, return the mode of the value to which the resource is being set.
+ // For uses, return the mode in which the resource is being used (which for
+ // hard registers might be different from the mode in which the resource
+ // was set).
+ //
+ // When accessing memory, the mode is always BLKmode. When accessing
+ // pseudo registers, the mode is always the mode of the pseudo register
+ // (and so doesn't, for example, take subregs into account).
+ machine_mode mode () const { return m_mode; }
+
+ // Return the kind of access that this is.
+ access_kind kind () const { return m_kind; }
+
+ // Return true if the access occurs in a phi node or an "artificial"
+ // instruction (see insn_info), false if it occurs in a real instruction.
+ bool is_artificial () const { return m_is_artificial; }
+
+ // Return the opposite of is_artificial.
+ bool is_real () const { return !m_is_artificial; }
+
+ // Return true if this access is a set_info whose result is used by at least
+ // one nondebug instruction.
+ bool is_set_with_nondebug_insn_uses () const;
+
+ // Return true if the access describes a set_info and if the value
+ // is defined by an RTX_AUTOINC rtx.
+ bool is_pre_post_modify () const { return m_is_pre_post_modify; }
+
+ // Return true if the access is a clobber_info that describes the effect
+ // of a called function. This kind of clobber is added for -fipa-ra
+ // functions that clobber only a strict subset of the normal ABI set.
+ bool is_call_clobber () const { return m_is_call_clobber; }
+
+ // Return true if the access is a use_info that simply marks a point in
+ // the live range of a set_info at which the value is live out from
+ // the containing EBB.
+ bool is_live_out_use () const { return m_is_live_out_use; }
+
+ // Return true if the access is a use_info for an instruction and if
+ // at least some of the uses occur within a MEM address.
+ //
+ // There shouldn't be a need to check whether *all* uses occur within
+ // a MEM address, since in principle:
+ //
+ // A: (set (reg:SI R1) (mem:SI (post_inc:SI (reg:SI R2))))
+ //
+ // should be semantically equivalent to:
+ //
+ // B: (parallel [(set (reg:SI R1) (mem:SI (reg:SI R2)))
+ // (set (reg:SI R2) (plus:SI (reg:SI R2) (const_int 4)))])
+ //
+ // even though R2 occurs only in MEMs for A but occurs outside MEMs for B.
+ bool includes_address_uses () const { return m_includes_address_uses; }
+
+ // Return true if the access occurs in an instruction and if at least
+ // some accesses to resource () occur in a read-modify-write context.
+ // This is equivalent to the DF_REF_READ_WRITE flag.
+ bool includes_read_writes () const { return m_includes_read_writes; }
+
+ // Return true if the access occurs in an instruction and if at least
+ // some accesses to resource () occur in a subreg context.
+ bool includes_subregs () const { return m_includes_subregs; }
+
+ // Return true if the access occurs in an instruction and if at least
+ // some accesses to resource () occur in a multi-register REG.
+ // This implies that resource () is a hard register.
+ bool includes_multiregs () const { return m_includes_multiregs; }
+
+ // Return true if the access occurs in a real nondebug instruction
+ // and if all accesses to resource () occur in notes, rather than
+ // in the main instruction pattern.
+ bool only_occurs_in_notes () const { return m_only_occurs_in_notes; }
+
+protected:
+ access_info (resource_info, access_kind);
+
+ void print_prefix_flags (pretty_printer *) const;
+ void print_properties_on_new_lines (pretty_printer *) const;
+
+private:
+ void set_mode (machine_mode mode) { m_mode = mode; }
+
+ // The values returned by the accessors above.
+ unsigned int m_regno;
+ access_kind m_kind : 8;
+
+protected:
+ // The value returned by the accessors above.
+ unsigned int m_is_artificial : 1;
+ unsigned int m_is_set_with_nondebug_insn_uses : 1;
+ unsigned int m_is_pre_post_modify : 1;
+ unsigned int m_is_call_clobber : 1;
+ unsigned int m_is_live_out_use : 1;
+ unsigned int m_includes_address_uses : 1;
+ unsigned int m_includes_read_writes : 1;
+ unsigned int m_includes_subregs : 1;
+ unsigned int m_includes_multiregs : 1;
+ unsigned int m_only_occurs_in_notes : 1;
+
+ // True if this access is a use_insn that occurs in a nondebug instruction,
+ // and if there are no following uses by nondebug instructions. The next use
+ // is null, a use_info for a debug instruction, or a use_info for a phi node.
+ //
+ // Providing this helps to optimize use_info::next_nondebug_insn_use.
+ unsigned int m_is_last_nondebug_insn_use : 1;
+
+ // True if this access is a use_info for a debug instruction or
+ // a phi node.
+ unsigned int m_is_in_debug_insn_or_phi : 1;
+
+private:
+ // Used as a flag during various update routines; has no long-lasting
+ // meaning.
+ unsigned int m_has_been_superceded : 1;
+
+ // Indicates that this access has been allocated on the function_info's
+ // temporary obstack and so is not (yet) part of the proper SSA form.
+ unsigned int m_is_temp : 1;
+
+ // Bits for future expansion.
+ unsigned int m_spare : 2;
+
+ // The value returned by the accessor above.
+ machine_mode m_mode : 8;
+};
+
+// A contiguous array of access_info pointers. Used to represent a
+// (mostly small) number of definitions and/or uses.
+using access_array = array_slice<access_info *const>;
+
+// A class for building an access_array on an obstack. It automatically
+// frees any in-progress array if the build attempt fails before finish ()
+// has been called.
+class access_array_builder : public obstack_watermark
+{
+public:
+ using obstack_watermark::obstack_watermark;
+
+ // Make sure that the array has enough for NUM_ACCESSES accesses.
+ void reserve (unsigned int num_accesses);
+
+ // Add ACCESS to the end of the array that we're building, given that
+ // reserve () has already made room.
+ void quick_push (access_info *access);
+
+ // Finish and return the new array. The array survives the destruction
+ // of the builder.
+ array_slice<access_info *> finish ();
+};
+
+// An access_info that represents the use of a resource in either a phi node
+// or an instruction. It records which set_info (if any) provides the
+// resource's value.
+class use_info : public access_info
+{
+ // Overall size: 5 LP64 words.
+ friend class set_info;
+ friend class function_info;
+
+public:
+ // Return true if the access occurs in an instruction rather than a phi node.
+ // The instruction might be a debug instruction or a nondebug instruction.
+ bool is_in_any_insn () const { return m_insn_or_phi.is_first (); }
+
+ // Return true if the access occurs in a nondebug instruction,
+ // false if it occurs in a debug instruction or a phi node.
+ bool is_in_nondebug_insn () const { return !m_is_in_debug_insn_or_phi; }
+
+ // Return true if the instruction occurs in a debug instruction.
+ bool is_in_debug_insn () const;
+
+ // Return true if the access occurs in a phi node rather than in an
+ // instruction.
+ bool is_in_phi () const { return m_insn_or_phi.is_second (); }
+
+ // Return true if the access occurs in a debug instruction or a phi node,
+ // false if it occurs in a nondebug instruction.
+ bool is_in_debug_insn_or_phi () const { return m_is_in_debug_insn_or_phi; }
+
+ // Return the instruction that uses the resource. Only valid is
+ // is_in_any_insn ().
+ insn_info *insn () const { return m_insn_or_phi.known_first (); }
+
+ // Return the phi node that uses the resource. Only valid if is_in_phi ().
+ phi_info *phi () const { return m_insn_or_phi.known_second (); }
+
+ // Return the basic block that contains the access.
+ bb_info *bb () const;
+
+ // Return the extended basic block that contains the access.
+ ebb_info *ebb () const;
+
+ // Return the set_info whose result the access uses, or null if the
+ // value of the resource is completely undefined.
+ //
+ // The value is undefined if the use is completely upwards exposed
+ // (i.e. has no preceding definition) or if the preceding definition
+ // is a clobber rather than a set.
+ //
+ // The mode of the definition can be different from the mode of the use;
+ // for example, a hard register might be set in DImode and used in SImode.
+ set_info *def () const { return m_def; }
+
+ // Return the previous and next uses of the definition. See set_info
+ // for details about the ordering.
+ //
+ // These routines are only meaningful when def () is nonnull.
+ use_info *prev_use () const;
+ use_info *next_use () const;
+
+ // Return the next use by a nondebug instruction, or null if none.
+ //
+ // This is only valid if is_in_nondebug_insn (). It is equivalent to,
+ // but more efficient than:
+ //
+ // next_use () && next_use ()->is_in_nondebug_insn ()
+ // ? next_use () : nullptr
+ use_info *next_nondebug_insn_use () const;
+
+ // Return the next use by an instruction, or null if none. The use might
+ // be by a debug instruction or a nondebug instruction.
+ //
+ // This is only valid if is_in_any_insn (). It is equivalent to:
+ //
+ // next_use () && next_use ()->is_in_any_insn () ? next_use () : nullptr
+ use_info *next_any_insn_use () const;
+
+ // Return the previous use by a phi node in the list, or null if none.
+ //
+ // This is only valid if is_in_phi (). It is equivalent to:
+ //
+ // prev_use () && prev_use ()->is_in_phi () ? prev_use () : nullptr
+ use_info *prev_phi_use () const;
+
+ // Return true if this is the first use of the definition. See set_info
+ // for details about the ordering.
+ //
+ // This routine is only meaningful when def () is nonnull.
+ bool is_first_use () const;
+
+ // Return true if this is the last use of the definition. See set_info
+ // for details about the ordering.
+ //
+ // This routine is only meaningful when def () is nonnull.
+ bool is_last_use () const;
+
+ // Print a description of def () to PP.
+ void print_def (pretty_printer *pp) const;
+
+ // Print a description of the location of the use to PP.
+ void print_location (pretty_printer *pp) const;
+
+ // Print a description of the use to PP under the control of
+ // PP_ACCESS_* flags FLAGS.
+ void print (pretty_printer *pp,
+ unsigned int flags = PP_ACCESS_DEFAULT) const;
+
+private:
+ // If we only create a set_info splay tree for sets that are used by
+ // three instructions or more, then only about 16% of uses need to be in
+ // a splay tree. It is therefore more memory-efficient to use separate
+ // nodes for the splay tree, instead of storing the child nodes
+ // directly in the use_info.
+
+ // Make insn_info the first (and thus directly-encoded) choice since
+ // insn () is read much more often than phi ().
+ using insn_or_phi = pointer_mux<insn_info, phi_info>;
+
+ // The use belongs to a list that is partitioned into three sections:
+ //
+ // (1) all uses in nondebug instructions, in reverse postorder
+ //
+ // (2) all uses in debug instructions, in reverse postorder
+ //
+ // (3) all phi nodes, in no particular order.
+ //
+ // In order to preserve memory:
+ //
+ // - The set_info just has a pointer to the first use.
+ //
+ // - The first use's "prev" pointer points to the last use.
+ //
+ // - The last use's "next" pointer points to the last use in a nondebug
+ // instruction, or null if there are no such uses.
+ using last_use_or_prev_use = pointer_mux<use_info>;
+ using last_nondebug_insn_use_or_next_use = pointer_mux<use_info>;
+
+ use_info (insn_or_phi, resource_info, set_info *);
+
+ use_info *last_use () const;
+ use_info *last_nondebug_insn_use () const;
+ bool calculate_is_last_nondebug_insn_use () const;
+
+ void record_reference (rtx_obj_reference, bool);
+ void set_insn (insn_info *);
+ void set_def (set_info *set) { m_def = set; }
+ void set_is_live_out_use (bool value) { m_is_live_out_use = value; }
+ void copy_prev_from (use_info *);
+ void copy_next_from (use_info *);
+ void set_last_use (use_info *);
+ void set_prev_use (use_info *);
+ void set_last_nondebug_insn_use (use_info *);
+ void set_next_use (use_info *);
+ void clear_use_links ();
+ bool has_use_links ();
+ bool check_integrity ();
+
+ // The location of the use.
+ insn_or_phi m_insn_or_phi;
+
+ // The overloaded "prev" and "next" pointers, as described above.
+ last_use_or_prev_use m_last_use_or_prev_use;
+ last_nondebug_insn_use_or_next_use m_last_nondebug_insn_use_or_next_use;
+
+ // The value of def ().
+ set_info *m_def;
+};
+
+// Iterators for lists of uses.
+using use_iterator = list_iterator<use_info, &use_info::next_use>;
+using reverse_use_iterator = list_iterator<use_info, &use_info::prev_use>;
+
+// Like use_iterator, but specifically for uses by nondebug instructions,
+// uses by any kind of instruction, and uses by phi nodes respectively.
+// These iterators allow a nullptr end point even if there are other types
+// of use in the same definition.
+using nondebug_insn_use_iterator
+ = list_iterator<use_info, &use_info::next_nondebug_insn_use>;
+using any_insn_use_iterator
+ = list_iterator<use_info, &use_info::next_any_insn_use>;
+using phi_use_iterator = list_iterator<use_info, &use_info::prev_phi_use>;
+
+// A view of an access_array in which every entry is known to be a use_info.
+using use_array = const_derived_container<use_info *, access_array>;
+
+// An access_info that describes a definition of a resource. The definition
+// can be a set or a clobber; the difference is that a set provides a known
+// and potentially useful value, while a clobber provides an unknown and
+// unusable value.
+//
+// Every definition is associated with an insn_info. All definitions of
+// a given resource are stored in a linked list, maintained in reverse
+// postorder.
+class def_info : public access_info
+{
+ // Overall size: 4 LP64 words
+ friend class function_info;
+ friend class clobber_group;
+
+public:
+ // Return the instruction that contains the definition.
+ insn_info *insn () const { return m_insn; }
+
+ // Return the basic block that contains the definition.
+ bb_info *bb () const;
+
+ // Return the extended basic block that contains the access.
+ ebb_info *ebb () const;
+
+ // Return the previous and next definitions of the same resource,
+ // in reverse postorder, or null if no such definition exists.
+ def_info *prev_def () const;
+ def_info *next_def () const;
+
+ // Return true if this is the first definition in the list.
+ bool is_first_def () const;
+
+ // Return true if this is the last definition in the list.
+ bool is_last_def () const;
+
+ // Print the location of the definition to PP.
+ void print_location (pretty_printer *pp) const;
+
+ // Print a unique identifier for this definition to PP. The identifier has
+ // the form <resource>:<insn uid>.
+ void print_identifier (pretty_printer *pp) const;
+
+protected:
+ def_info (insn_info *insn, resource_info resource, access_kind kind);
+
+private:
+ // In order to preserve memory, the list head only points to the first
+ // definition in the list. The "prev" entry of the first definition
+ // then points to the last definition.
+ using last_def_or_prev_def = pointer_mux<def_info>;
+
+ // For similar memory-saving reasons, if we want to create a splay tree
+ // of accesses to a resource, we hang the root off the "next" entry of
+ // the last definition in the list.
+ using splay_root_or_next_def = pointer_mux<def_node, def_info>;
+
+ void set_insn (insn_info *insn) { m_insn = insn; }
+
+ def_info *last_def () const;
+ def_node *splay_root () const;
+
+ void record_reference (rtx_obj_reference, bool);
+ void copy_prev_from (def_info *);
+ void copy_next_from (def_info *);
+ void set_last_def (def_info *);
+ void set_prev_def (def_info *);
+ void set_splay_root (def_node *);
+ void set_next_def (def_info *);
+ void clear_def_links ();
+ bool has_def_links ();
+
+ // The location of the definition.
+ insn_info *m_insn;
+
+ // The overloaded "prev" and "next" pointers, as described above.
+ last_def_or_prev_def m_last_def_or_prev_def;
+ splay_root_or_next_def m_splay_root_or_next_def;
+};
+
+// Iterators for lists of definitions.
+using def_iterator = list_iterator<def_info, &def_info::next_def>;
+using reverse_def_iterator = list_iterator<def_info, &def_info::prev_def>;
+
+// A view of an access_array in which every entry is known to be a
+// def_info.
+using def_array = const_derived_container<def_info *, access_array>;
+
+// A def_info that sets the resource to a value that is both
+// unknown and not useful. This is only ever used for registers,
+// since memory always has some useful contents.
+//
+// Neighboring clobbers are grouped into clobber_groups, so that it's
+// possibly to skip over all neighboring clobbers in a single step.
+class clobber_info : public def_info
+{
+ // Overall size: 8 LP64 words
+ friend class default_splay_tree_accessors<clobber_info *>;
+ friend class default_splay_tree_accessors_with_parent<clobber_info *>;
+ friend class function_info;
+ friend class clobber_group;
+
+public:
+ using splay_tree = default_rootless_splay_tree<clobber_info *>;
+
+ // Return true if the clobber belongs to a clobber_group, false if it
+ // is standalone.
+ bool is_in_group () const { return m_group; }
+
+ // Return the group that the clobber is in, or null if none.
+ //
+ // Complexity: amortized O(1), worst case O(N), where N is the number
+ // of clobbers in the containing clobber_group.
+ clobber_group *group () const;
+
+ // Print a description of the clobber to PP under the control of
+ // PP_ACCESS_* flags FLAGS.
+ void print (pretty_printer *pp,
+ unsigned int flags = PP_ACCESS_DEFAULT) const;
+
+private:
+ // Once normal call clobbers are taken out of the equation by
+ // insn_call_clobbers_notes, clobber_infos account for roughly 6% of all
+ // def_infos, with the rest being set_infos. clobber_infos are
+ // therefore much less size-sensitive than set_infos are.
+ //
+ // As noted above, we want to group neighboring clobbers together so that
+ // we can quickly step over them to find the previous or next "real" set.
+ // We also want to be able to split the group in sublinear time,
+ // for example when inserting a set/use pair between two clobbers
+ // in a group.
+ //
+ // So:
+ //
+ // - Clobbers need to have ready access to their group, so that we
+ // can cheaply skip over the whole group. This means that they
+ // need a group pointer.
+ //
+ // - We need to be able to update the group pointer lazily, so that
+ // the cost of updating it is counted against accesses to the clobbers
+ // that need updating.
+ //
+ // We also want to be able to insert clobbers into a group in
+ // amortized logarithmic time.
+ //
+ // We therefore use a splay tree to represent the clobbers in a group,
+ // with the nodes storing their parent node. It is then possible to
+ // perform splay operations without first getting hold of the root.
+ // The root of the splay tree always has a valid, up-to-date group,
+ // so lazy group updates can get the new group from there.
+ //
+ // Roughly 90% of clobbers have a neighboring definition in the same
+ // block, which means that most need to be stored in a splay tree.
+ // We therefore store the splay tree fields directly in the clobber_info
+ // rather than using a separate node object.
+
+ clobber_info (insn_info *, unsigned int);
+
+ void set_group (clobber_group *group) { m_group = group; }
+ void update_group (clobber_group *);
+ clobber_group *recompute_group ();
+
+ // The child and parent nodes in the splay tree.
+ clobber_info *m_children[2];
+ clobber_info *m_parent;
+
+ // The last known value of group (), which might now be out of date.
+ clobber_group *m_group;
+};
+
+using clobber_tree = clobber_info::splay_tree::rooted;
+
+// A def_info that sets the resource to a useful value. It records
+// all uses of the value in a linked list. The list is partitioned
+// into three sections:
+//
+// (1) all uses by nondebug instructions, in reverse postorder, followed by
+// (2) all uses by debug instructions, in reverse postorder, followed by
+// (3) all uses by phi nodes, in no particular order.
+//
+// There are two cases:
+//
+// - If we know in advance that there is a single definition of a resource R
+// and therefore decide not to use phi nodes for R, (1) and (2) contain
+// all uses of R, regardless of which blocks contain the uses. (3) is
+// then empty.
+//
+// - Otherwise, (1) only contains uses in the same extended basic block
+// as the definition, and it is terminated by a use that marks the end
+// of the live range for the EBB. In other words, if the resource dies
+// in the EBB, the last use by a nondebug instruction marks the point at
+// which it dies, otherwise there is a fake live-out use at the end of
+// the EBB.
+//
+// Since debug instructions should not affect codegen, they opportunisticly
+// attach to the same set_info as nondebug instructions where possible.
+// If a nondebug instruction would attach to a degenerate phi and if no
+// such phi exists, debug instructions instead attach to whichever set_info
+// provides the value, regardless of where that set_info is.
+class set_info : public def_info
+{
+ // Overall size: 6 LP64 words.
+ friend class function_info;
+ using use_splay_tree = splay_tree<use_info *>;
+
+public:
+ // Return the first and last uses of the set, or null if the list is empty.
+ // See the comment above for details about the order.
+ use_info *first_use () const { return m_first_use; }
+ use_info *last_use () const;
+
+ // Return the first and last uses of the set by nondebug instructions,
+ // or null if there are no such uses. The uses are in reverse postorder.
+ use_info *first_nondebug_insn_use () const;
+ use_info *last_nondebug_insn_use () const;
+
+ // Return the first use of the set by any kind of instruction, or null
+ // if there are no such uses. The uses are in the order described above.
+ use_info *first_any_insn_use () const;
+
+ // Return the last use of the set by phi inputs, or null if there are no
+ // such uses. The phi input uses are in no particular order.
+ use_info *last_phi_use () const;
+
+ // Return true if at least one nondebug instruction or phi node uses
+ // the set's result. This is equivalent to testing whether the set is
+ // ever live.
+ bool has_nondebug_uses () const;
+
+ // Return true if anything uses the set's result. Note that this includes
+ // uses by debug instructions, so it should not be used for optimization
+ // decisions.
+ bool has_any_uses () const { return m_first_use; }
+
+ // Return true if at least one nondebug instruction uses the set's result.
+ bool has_nondebug_insn_uses () const;
+
+ // Return true if at least one phi node uses the set's result.
+ bool has_phi_uses () const;
+
+ // Return true if the set and its uses are contained within a single
+ // extended basic block, with the set coming first. This implies
+ // that all uses are by instructions rather than phi nodes.
+ bool is_local_to_ebb () const;
+
+ // List all the uses of the set, in the order described above.
+ iterator_range<use_iterator> all_uses () const;
+
+ // Return uses () in reverse order.
+ iterator_range<reverse_use_iterator> reverse_all_uses () const;
+
+ // List the uses of the set by nondebug instructions, in reverse postorder.
+ iterator_range<nondebug_insn_use_iterator> nondebug_insn_uses () const;
+
+ // Return nondebug_insn_uses () in reverse order.
+ iterator_range<reverse_use_iterator> reverse_nondebug_insn_uses () const;
+
+ // List the uses of the set by any kind of instruction. The list follows
+ // the order described above.
+ iterator_range<any_insn_use_iterator> all_insn_uses () const;
+
+ // List the uses of the set by phi nodes, in no particular order.
+ // There is therefore no reversed equivalent of this list.
+ iterator_range<phi_use_iterator> phi_uses () const;
+
+ // Print a description of the set to PP under the control of
+ // PP_ACCESS_* flags FLAGS.
+ void print (pretty_printer *pp,
+ unsigned int flags = PP_ACCESS_DEFAULT) const;
+
+protected:
+ set_info (insn_info *, resource_info, access_kind);
+
+ // Print information about uses () to PP, continuing information printed
+ // about the set itself.
+ void print_uses_on_new_lines (pretty_printer *pp) const;
+
+private:
+ // Sets (including phis) account for about 94% of all definitions
+
+ set_info (insn_info *, resource_info);
+
+ void set_first_use (use_info *);
+
+ // The first use in the list.
+ use_info *m_first_use;
+
+ // The root of a splay tree of all uses, built lazily when we first
+ // think it's needed.
+ use_splay_tree m_use_tree;
+};
+
+// A set_info for an on-the-side phi node. The phi node is attached
+// to an extended basic block EBB and has one input for each incoming edge.
+// The inputs are represented as an array of use_infos, with input I
+// corresponding to EDGE_PRED (EBB->first_bb ()->cfg_bb (), I).
+//
+// Each phi node has a densely-allocated unique identifier, which is intended
+// to be suitable for bitmaps or sbitmaps.
+//
+// All the phi nodes in an extended basic block are chained together
+// into a linked list. The list has no particular order.
+class phi_info : public set_info
+{
+ // Overall size: 8 LP64 words
+ friend class function_info;
+
+public:
+ // Return the previous and next phi nodes in the extended basic block's list,
+ // or null if none.
+ phi_info *prev_phi () const { return m_prev_phi; }
+ phi_info *next_phi () const { return m_next_phi; }
+
+ // Return the number of phi inputs. This is 1 for degenerate phis,
+ // otherwise it is equal to the number of incoming edges.
+ unsigned int num_inputs () const { return m_num_inputs; }
+
+ // Return true if the phi node is degenerate, i.e. if it has only a
+ // single input.
+ bool is_degenerate () const { return m_num_inputs == 1; }
+
+ // Return the phi node's unique identifier.
+ unsigned int uid () const { return m_uid; }
+
+ // Return the array of inputs. For degenerate phi nodes, this array contains
+ // a single element, otherwise it has one input per incoming edge,
+ // with element E corresponding to incoming edge E.
+ use_array inputs () const;
+
+ // Return the use_info that describes the phi input for incoming edge E.
+ use_info *input_use (unsigned int e) const;
+
+ // Return the value of resource () on incoming edge E, or null if the
+ // value is completely undefined for that edge.
+ set_info *input_value (unsigned int e) const;
+
+ // Print a description of the phi node to PP under the control of
+ // PP_ACCESS_* flags FLAGS.
+ void print (pretty_printer *pp,
+ unsigned int flags = PP_ACCESS_DEFAULT) const;
+
+private:
+ phi_info (insn_info *insn, resource_info resource, unsigned int uid);
+
+ void make_degenerate (use_info *);
+ void set_inputs (use_array inputs);
+ void set_prev_phi (phi_info *prev_phi) { m_prev_phi = prev_phi; }
+ void set_next_phi (phi_info *next_phi) { m_next_phi = next_phi; }
+ void clear_phi_links () { m_prev_phi = m_next_phi = nullptr; }
+ bool has_phi_links () { return m_prev_phi || m_next_phi; }
+
+ // The values returned by the accessors above.
+ unsigned int m_uid;
+ unsigned int m_num_inputs;
+ union
+ {
+ access_info *const *m_inputs;
+ access_info *m_single_input;
+ };
+ phi_info *m_prev_phi;
+ phi_info *m_next_phi;
+};
+
+// An iterator for lists of phi nodes.
+using phi_iterator = list_iterator<phi_info, &phi_info::next_phi>;
+
+// One node in a splay tree of definitions. This base class represents
+// a single def_info, but it is structured to allow derived classes
+// to add a range.
+class def_node
+{
+ // Size: 3 LP64 words.
+ friend class function_info;
+ friend class default_splay_tree_accessors<def_node *>;
+
+public:
+ // Return the first definition that the node represents.
+ def_info *first_def () const;
+
+ // Return which type of access first_def () is.
+ bool contains_clobber () const { return m_clobber_or_set.is_first (); }
+ bool contains_set () const { return m_clobber_or_set.is_second (); }
+
+protected:
+ // More nodes are clobbers rather than sets, so put clobbers first.
+ // Neither choice can be null.
+ using clobber_or_set = pointer_mux<clobber_info, set_info>;
+
+ // Construct a node that represents FIRST_DEF (and possibly later
+ // definitions too, if called from a derived class).
+ def_node (clobber_or_set first_def);
+
+ // The first definition in the node.
+ clobber_or_set m_clobber_or_set;
+
+private:
+ // The splay tree child nodes.
+ def_node *m_children[2];
+};
+
+// One node in a splay tree of def_infos, representing a single set_info.
+class set_node : public def_node
+{
+ // Overall size: 3 LP64 words.
+ friend class function_info;
+
+public:
+ // Return the set that the node contains.
+ set_info *set () const { return m_clobber_or_set.known_second (); }
+
+ // Print a description of the node to PP.
+ void print (pretty_printer *pp) const;
+
+private:
+ // Construct a node for SET.
+ set_node (set_info *set) : def_node (set) {}
+};
+
+// One node in a splay tree of def_infos. This class represents
+// a list of contiguous clobber_infos, in execution order.
+class clobber_group : public def_node
+{
+ // Overall size: 5 LP64 words.
+ friend class function_info;
+
+public:
+ // Return the first and last clobbers in the group. The results are
+ // always nonnull.
+ clobber_info *first_clobber () const;
+ clobber_info *last_clobber () const { return m_last_clobber; }
+
+ // Return true if this group has been replaced by new clobber_groups.
+ bool has_been_superceded () const { return !m_last_clobber; }
+
+ // Return a list of the clobbers in the group, in execution order.
+ iterator_range<def_iterator> clobbers () const;
+
+ // Print a description of the group to PP.
+ void print (pretty_printer *pp) const;
+
+private:
+ clobber_group (clobber_info *clobber);
+
+ // Set the values of first_clobber () and last_clobber ().
+ void set_first_clobber (clobber_info *c) { m_clobber_or_set = c; }
+ void set_last_clobber (clobber_info *c) { m_last_clobber = c; }
+
+ // The value returned by last_clobber ().
+ clobber_info *m_last_clobber;
+
+ // A splay tree that contains all the clobbers in the group.
+ // The root of the splay tree always has an up-to-date group
+ // pointer, but the other clobbers in the tree might not.
+ clobber_tree m_clobber_tree;
+};
+
+// A splay tree in which one node represents a standalone set_info or a
+// range of consecutive clobber_infos. The nodes follow execution order
+// and maintain the invariant that no two groups of clobber_infos appear
+// next to each other (instead, the groups are merged).
+using def_splay_tree = default_splay_tree<def_node *>;
+
+// This type represents a choice between:
+//
+// (1) a single definition of a resource
+// (2) a node in a def_splay_tree that represents either a single
+// set or a group of clobbers.
+class def_mux : public pointer_mux<def_info, def_node>
+{
+ using parent = pointer_mux<def_info, def_node>;
+
+ // Provide the same constructors as the pointer_mux.
+ using parent::parent;
+
+public:
+ // Return the first definition associated with this mux. If the mux holds
+ // a single definition, the result is that definition. If the mux holds
+ // a clobber_group, the result is the first clobber in the group.
+ def_info *first_def () const;
+
+ // Return the last definition associated with this mux. If the mux holds
+ // a single definition, the result is that definition. If the mux holds
+ // a clobber_group, the result is the last clobber in the group.
+ def_info *last_def () const;
+
+ // If the pointer represents a set_info, return that set_info,
+ // otherwise return null.
+ set_info *set () const;
+};
+
+// This class represents the result of looking up the definition of a
+// resource at a particular point, here referred to as point P.
+// There are four states:
+//
+// - MUX is null if there were no definitions to search.
+//
+// - Otherwise, COMPARISON is 0 if we found a definition at P or a
+// clobber_group that spans P. MUX then contains this definition
+// or clobber_group.
+//
+// - Otherwise, COMPARISON is less than 0 if we found the definition
+// that precedes P or the group of clobbers that precedes P. MUX then
+// contains this definition or clobber_group.
+//
+// - Otherwise, COMPARISON is greater than zero and we found the
+// definition that follows P, or the group of clobbers that follows P.
+// MUX then contains this definition or clobber_group.
+class def_lookup
+{
+public:
+ // If we found a clobber_group that spans P, return the definition
+ // that precedes the start of the group, or null if none.
+ //
+ // Otherwise, return the last definition that occurs before P,
+ // or null if none.
+ def_info *prev_def () const;
+
+ // If we found a clobber_group that spans P, return the definition
+ // that follows the end of the group, or null if none.
+ //
+ // Otherwise, return the first definition that occurs after P,
+ // or null if none.
+ def_info *next_def () const;
+
+ // If we found a set_info at P, return that set_info, otherwise return null.
+ set_info *matching_set () const;
+
+ // If we found a set_info at P, return that set_info, otherwise return
+ // prev_def ().
+ def_info *matching_or_prev_def () const;
+
+ // If we found a set_info at P, return that set_info, otherwise return
+ // next_def ().
+ def_info *matching_or_next_def () const;
+
+ def_mux mux;
+ int comparison;
+};
+
+void pp_resource (pretty_printer *, resource_info);
+void pp_access (pretty_printer *, const access_info *,
+ unsigned int flags = PP_ACCESS_DEFAULT);
+void pp_accesses (pretty_printer *, access_array,
+ unsigned int flags = PP_ACCESS_DEFAULT);
+void pp_def_node (pretty_printer *, const def_node *);
+void pp_def_mux (pretty_printer *, def_mux);
+void pp_def_lookup (pretty_printer *, def_lookup);
+
+}
+
+void dump (FILE *, rtl_ssa::resource_info);
+void dump (FILE *, const rtl_ssa::access_info *,
+ unsigned int flags = rtl_ssa::PP_ACCESS_DEFAULT);
+void dump (FILE *, rtl_ssa::access_array,
+ unsigned int flags = rtl_ssa::PP_ACCESS_DEFAULT);
+void dump (FILE *, const rtl_ssa::def_node *);
+void dump (FILE *, rtl_ssa::def_mux);
+void dump (FILE *, rtl_ssa::def_lookup);
+
+void DEBUG_FUNCTION debug (const rtl_ssa::resource_info *);
+void DEBUG_FUNCTION debug (const rtl_ssa::access_info *);
+void DEBUG_FUNCTION debug (const rtl_ssa::access_array);
+void DEBUG_FUNCTION debug (const rtl_ssa::def_node *);
+void DEBUG_FUNCTION debug (const rtl_ssa::def_mux &);
+void DEBUG_FUNCTION debug (const rtl_ssa::def_lookup &);
diff --git a/gcc/rtl-ssa/blocks.cc b/gcc/rtl-ssa/blocks.cc
new file mode 100644
index 0000000..5436305
--- /dev/null
+++ b/gcc/rtl-ssa/blocks.cc
@@ -0,0 +1,1146 @@
+// Implementation of basic-block-related functions for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+#include "rtl-ssa/internals.inl"
+#include "cfganal.h"
+#include "cfgrtl.h"
+#include "predict.h"
+
+using namespace rtl_ssa;
+
+// See the comment above the declaration.
+void
+bb_info::print_identifier (pretty_printer *pp) const
+{
+ char tmp[3 * sizeof (index ()) + 3];
+ snprintf (tmp, sizeof (tmp), "bb%d", index ());
+ pp_string (pp, tmp);
+ if (ebb_info *ebb = this->ebb ())
+ {
+ pp_space (pp);
+ pp_left_bracket (pp);
+ ebb->print_identifier (pp);
+ pp_right_bracket (pp);
+ }
+}
+
+// See the comment above the declaration.
+void
+bb_info::print_full (pretty_printer *pp) const
+{
+ pp_string (pp, "basic block ");
+ print_identifier (pp);
+ pp_colon (pp);
+
+ auto print_insn = [pp](const char *header, const insn_info *insn)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, header);
+ pp_newline_and_indent (pp, 2);
+ if (insn)
+ pp_insn (pp, insn);
+ else
+ pp_string (pp, "<uninitialized>");
+ pp_indentation (pp) -= 4;
+ };
+
+ print_insn ("head:", head_insn ());
+
+ pp_newline (pp);
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "contents:");
+ if (!head_insn ())
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "<uninitialized>");
+ pp_indentation (pp) -= 2;
+ }
+ else if (auto insns = real_insns ())
+ {
+ bool is_first = true;
+ for (const insn_info *insn : insns)
+ {
+ if (is_first)
+ is_first = false;
+ else
+ pp_newline (pp);
+ pp_newline_and_indent (pp, 2);
+ pp_insn (pp, insn);
+ pp_indentation (pp) -= 2;
+ }
+ }
+ else
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "none");
+ pp_indentation (pp) -= 2;
+ }
+ pp_indentation (pp) -= 2;
+
+ pp_newline (pp);
+ print_insn ("end:", end_insn ());
+}
+
+// See the comment above the declaration.
+void
+ebb_call_clobbers_info::print_summary (pretty_printer *pp) const
+{
+ pp_string (pp, "call clobbers for ABI ");
+ if (m_abi)
+ pp_decimal_int (pp, m_abi->id ());
+ else
+ pp_string (pp, "<null>");
+}
+
+// See the comment above the declaration.
+void
+ebb_call_clobbers_info::print_full (pretty_printer *pp) const
+{
+ print_summary (pp);
+ pp_colon (pp);
+ pp_newline_and_indent (pp, 2);
+ auto print_node = [](pretty_printer *pp,
+ const insn_call_clobbers_note *note)
+ {
+ if (insn_info *insn = note->insn ())
+ insn->print_identifier_and_location (pp);
+ else
+ pp_string (pp, "<null>");
+ };
+ print (pp, root (), print_node);
+ pp_indentation (pp) -= 2;
+}
+
+// See the comment above the declaration.
+void
+ebb_info::print_identifier (pretty_printer *pp) const
+{
+ // first_bb is populated by the constructor and so should always
+ // be nonnull.
+ auto index = first_bb ()->index ();
+ char tmp[3 * sizeof (index) + 4];
+ snprintf (tmp, sizeof (tmp), "ebb%d", index);
+ pp_string (pp, tmp);
+}
+
+// See the comment above the declaration.
+void
+ebb_info::print_full (pretty_printer *pp) const
+{
+ pp_string (pp, "extended basic block ");
+ print_identifier (pp);
+ pp_colon (pp);
+
+ pp_newline_and_indent (pp, 2);
+ if (insn_info *phi_insn = this->phi_insn ())
+ {
+ phi_insn->print_identifier_and_location (pp);
+ pp_colon (pp);
+ if (auto phis = this->phis ())
+ {
+ bool is_first = true;
+ for (const phi_info *phi : phis)
+ {
+ if (is_first)
+ is_first = false;
+ else
+ pp_newline (pp);
+ pp_newline_and_indent (pp, 2);
+ pp_access (pp, phi, PP_ACCESS_SETTER);
+ pp_indentation (pp) -= 2;
+ }
+ }
+ else
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "no phi nodes");
+ pp_indentation (pp) -= 2;
+ }
+ }
+ else
+ pp_string (pp, "no phi insn");
+ pp_indentation (pp) -= 2;
+
+ for (const bb_info *bb : bbs ())
+ {
+ pp_newline (pp);
+ pp_newline_and_indent (pp, 2);
+ pp_bb (pp, bb);
+ pp_indentation (pp) -= 2;
+ }
+
+ for (ebb_call_clobbers_info *ecc : call_clobbers ())
+ {
+ pp_newline (pp);
+ pp_newline_and_indent (pp, 2);
+ pp_ebb_call_clobbers (pp, ecc);
+ pp_indentation (pp) -= 2;
+ }
+}
+
+// Add a dummy use to mark that DEF is live out of BB's EBB at the end of BB.
+void
+function_info::add_live_out_use (bb_info *bb, set_info *def)
+{
+ // There is nothing to do if DEF is an artificial definition at the end
+ // of BB. In that case the definitino is rooted at the end of the block
+ // and we wouldn't gain anything by inserting a use immediately after it.
+ // If we did want to insert a use, we'd need to associate it with a new
+ // instruction that comes after bb->end_insn ().
+ if (def->insn () == bb->end_insn ())
+ return;
+
+ // If the end of the block already has an artificial use, that use
+ // acts to make DEF live at the appropriate point.
+ unsigned int regno = def->regno ();
+ if (find_access (bb->end_insn ()->uses (), regno))
+ return;
+
+ // Currently there is no need to maintain a backward link from the end
+ // instruction to the list of live-out uses. Such a list would be
+ // expensive to update if it was represented using the usual insn_info
+ // access arrays.
+ use_info *use = allocate<use_info> (bb->end_insn (), def->resource (), def);
+ use->set_is_live_out_use (true);
+ add_use (use);
+}
+
+// Return true if all nondebug uses of DEF are live-out uses.
+static bool
+all_uses_are_live_out_uses (set_info *def)
+{
+ for (use_info *use : def->all_uses ())
+ if (!use->is_in_debug_insn () && !use->is_live_out_use ())
+ return false;
+ return true;
+}
+
+// SET, if nonnull, is a definition of something that is live out from BB.
+// Return the live-out value itself.
+set_info *
+function_info::live_out_value (bb_info *bb, set_info *set)
+{
+ // Degenerate phis only exist to provide a definition for uses in the
+ // same EBB. The live-out value is the same as the live-in value.
+ if (auto *phi = safe_dyn_cast<phi_info *> (set))
+ if (phi->is_degenerate ())
+ {
+ set = phi->input_value (0);
+
+ // Remove the phi if it turned out to be useless. This is
+ // mainly useful for memory, because we don't know ahead of time
+ // whether a block will use memory or not.
+ if (bb == bb->ebb ()->last_bb () && all_uses_are_live_out_uses (phi))
+ replace_phi (phi, set);
+ }
+
+ return set;
+}
+
+// Add PHI to EBB and enter it into the function's hash table.
+void
+function_info::append_phi (ebb_info *ebb, phi_info *phi)
+{
+ phi_info *first_phi = ebb->first_phi ();
+ if (first_phi)
+ first_phi->set_prev_phi (phi);
+ phi->set_next_phi (first_phi);
+ ebb->set_first_phi (phi);
+ add_def (phi);
+}
+
+// Remove PHI from its current position in the SSA graph.
+void
+function_info::remove_phi (phi_info *phi)
+{
+ phi_info *next = phi->next_phi ();
+ phi_info *prev = phi->prev_phi ();
+
+ if (next)
+ next->set_prev_phi (prev);
+
+ if (prev)
+ prev->set_next_phi (next);
+ else
+ phi->ebb ()->set_first_phi (next);
+
+ remove_def (phi);
+ phi->clear_phi_links ();
+}
+
+// Remove PHI from the SSA graph and free its memory.
+void
+function_info::delete_phi (phi_info *phi)
+{
+ gcc_assert (!phi->has_any_uses ());
+
+ // Remove the inputs to the phi.
+ for (use_info *input : phi->inputs ())
+ remove_use (input);
+
+ remove_phi (phi);
+
+ phi->set_next_phi (m_free_phis);
+ m_free_phis = phi;
+}
+
+// If possible, remove PHI and replace all uses with NEW_VALUE.
+void
+function_info::replace_phi (phi_info *phi, set_info *new_value)
+{
+ auto update_use = [&](use_info *use)
+ {
+ remove_use (use);
+ use->set_def (new_value);
+ add_use (use);
+ };
+
+ if (new_value)
+ for (use_info *use : phi->nondebug_insn_uses ())
+ if (!use->is_live_out_use ())
+ {
+ // We need to keep the phi around for its local uses.
+ // Turn it into a degenerate phi, if it isn't already.
+ use_info *use = phi->input_use (0);
+ if (use->def () != new_value)
+ update_use (use);
+
+ if (phi->is_degenerate ())
+ return;
+
+ phi->make_degenerate (use);
+
+ // Redirect all phi users to NEW_VALUE.
+ while (use_info *phi_use = phi->last_phi_use ())
+ update_use (phi_use);
+
+ return;
+ }
+
+ // Replace the uses. We can discard uses that only existed for the
+ // sake of marking live-out values, since the resource is now transparent
+ // in the phi's EBB.
+ while (use_info *use = phi->last_use ())
+ if (use->is_live_out_use ())
+ remove_use (use);
+ else
+ update_use (use);
+
+ delete_phi (phi);
+}
+
+// Create and return a phi node for EBB. RESOURCE is the resource that
+// the phi node sets (and thus that all the inputs set too). NUM_INPUTS
+// is the number of inputs, which is 1 for a degenerate phi. INPUTS[I]
+// is a set_info that gives the value of input I, or null if the value
+// is either unknown or uninitialized. If NUM_INPUTS > 1, this array
+// is allocated on the main obstack and can be reused for the use array.
+//
+// Add the created phi node to its basic block and enter it into the
+// function's hash table.
+phi_info *
+function_info::create_phi (ebb_info *ebb, resource_info resource,
+ access_info **inputs, unsigned int num_inputs)
+{
+ phi_info *phi = m_free_phis;
+ if (phi)
+ {
+ m_free_phis = phi->next_phi ();
+ *phi = phi_info (ebb->phi_insn (), resource, phi->uid ());
+ }
+ else
+ {
+ phi = allocate<phi_info> (ebb->phi_insn (), resource, m_next_phi_uid);
+ m_next_phi_uid += 1;
+ }
+
+ // Convert the array of set_infos into an array of use_infos. Also work
+ // out what mode the phi should have.
+ machine_mode new_mode = resource.mode;
+ for (unsigned int i = 0; i < num_inputs; ++i)
+ {
+ auto *input = safe_as_a<set_info *> (inputs[i]);
+ auto *use = allocate<use_info> (phi, resource, input);
+ add_use (use);
+ inputs[i] = use;
+ if (input)
+ new_mode = combine_modes (new_mode, input->mode ());
+ }
+
+ phi->set_inputs (use_array (inputs, num_inputs));
+ phi->set_mode (new_mode);
+
+ append_phi (ebb, phi);
+
+ return phi;
+}
+
+// Create and return a degenerate phi for EBB whose input comes from DEF.
+// This is used in cases where DEF is known to be available on entry to
+// EBB but was not previously used within it. If DEF is for a register,
+// there are two cases:
+//
+// (1) DEF was already live on entry to EBB but was previously transparent
+// within it.
+//
+// (2) DEF was not previously live on entry to EBB and is being made live
+// by this update.
+//
+// At the moment, this function only handles the case in which EBB has a
+// single predecessor block and DEF is defined in that block's EBB.
+phi_info *
+function_info::create_degenerate_phi (ebb_info *ebb, set_info *def)
+{
+ access_info *input = def;
+ phi_info *phi = create_phi (ebb, def->resource (), &input, 1);
+ if (def->is_reg ())
+ {
+ unsigned int regno = def->regno ();
+
+ // Find the single predecessor mentioned above.
+ basic_block pred_cfg_bb = single_pred (ebb->first_bb ()->cfg_bb ());
+ bb_info *pred_bb = this->bb (pred_cfg_bb);
+
+ if (!bitmap_set_bit (DF_LR_IN (ebb->first_bb ()->cfg_bb ()), regno))
+ {
+ // The register was not previously live on entry to EBB and
+ // might not have been live on exit from PRED_BB either.
+ if (bitmap_set_bit (DF_LR_OUT (pred_cfg_bb), regno))
+ add_live_out_use (pred_bb, def);
+ }
+ else
+ {
+ // The register was previously live in to EBB. Add live-out uses
+ // at the appropriate points.
+ insn_info *next_insn = nullptr;
+ if (def_info *next_def = phi->next_def ())
+ next_insn = next_def->insn ();
+ for (bb_info *bb : ebb->bbs ())
+ {
+ if ((next_insn && *next_insn <= *bb->end_insn ())
+ || !bitmap_bit_p (DF_LR_OUT (bb->cfg_bb ()), regno))
+ break;
+ add_live_out_use (bb, def);
+ }
+ }
+ }
+ return phi;
+}
+
+// Create a bb_info for CFG_BB, given that no such structure currently exists.
+bb_info *
+function_info::create_bb_info (basic_block cfg_bb)
+{
+ bb_info *bb = allocate<bb_info> (cfg_bb);
+ gcc_checking_assert (!m_bbs[cfg_bb->index]);
+ m_bbs[cfg_bb->index] = bb;
+ return bb;
+}
+
+// Add BB to the end of the list of blocks.
+void
+function_info::append_bb (bb_info *bb)
+{
+ if (m_last_bb)
+ m_last_bb->set_next_bb (bb);
+ else
+ m_first_bb = bb;
+ bb->set_prev_bb (m_last_bb);
+ m_last_bb = bb;
+}
+
+// Called while building SSA form using BI, with BI.current_bb being
+// the entry block.
+//
+// Create the entry block instructions and their definitions. The only
+// useful instruction is the end instruction, which carries definitions
+// for the values that are live on entry to the function. However, it
+// seems simpler to create a head instruction too, rather than force all
+// users of the block information to treat the entry block as a special case.
+void
+function_info::add_entry_block_defs (build_info &bi)
+{
+ bb_info *bb = bi.current_bb;
+ basic_block cfg_bb = bi.current_bb->cfg_bb ();
+ auto *lr_info = DF_LR_BB_INFO (cfg_bb);
+
+ bb->set_head_insn (append_artificial_insn (bb));
+ insn_info *insn = append_artificial_insn (bb);
+ bb->set_end_insn (insn);
+
+ start_insn_accesses ();
+
+ // Using LR to derive the liveness information means that we create an
+ // entry block definition for upwards exposed registers. These registers
+ // are sometimes genuinely uninitialized. However, some targets also
+ // create a pseudo PIC base register and only initialize it later.
+ // Handling that case correctly seems more important than optimizing
+ // uninitialized uses.
+ unsigned int regno;
+ bitmap_iterator in_bi;
+ EXECUTE_IF_SET_IN_BITMAP (&lr_info->out, 0, regno, in_bi)
+ {
+ auto *set = allocate<set_info> (insn, full_register (regno));
+ append_def (set);
+ m_temp_defs.safe_push (set);
+ bi.record_reg_def (regno, set);
+ }
+
+ // Create a definition that reflects the state of memory on entry to
+ // the function.
+ auto *set = allocate<set_info> (insn, memory);
+ append_def (set);
+ m_temp_defs.safe_push (set);
+ bi.record_mem_def (set);
+
+ finish_insn_accesses (insn);
+}
+
+// Called while building SSA form using BI. Create phi nodes for the
+// current EBB, leaving backedge inputs to be filled in later. Set
+// bi.last_access to the values that are live on entry to the EBB,
+// regardless of whether or not they are phi nodes.
+void
+function_info::add_phi_nodes (build_info &bi)
+{
+ ebb_info *ebb = bi.current_ebb;
+ basic_block cfg_bb = ebb->first_bb ()->cfg_bb ();
+ auto *lr_info = DF_LR_BB_INFO (cfg_bb);
+
+ // Get a local cache of the predecessor blocks' live out values.
+ unsigned int num_preds = EDGE_COUNT (cfg_bb->preds);
+ auto_vec<const bb_live_out_info *, 16> pred_live_outs (num_preds);
+ bool has_backedge = false;
+ bool has_eh_edge = false;
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, cfg_bb->preds)
+ {
+ bb_info *pred_bb = this->bb (e->src);
+ const bb_live_out_info *live_out = &bi.bb_live_out[e->src->index];
+
+ // In LR (but not LIVE), the registers live on entry to a block must
+ // normally be a subset of the registers live on exit from any
+ // given predecessor block. The exceptions are EH edges, which
+ // implicitly clobber all registers in eh_edge_abi.full_reg_clobbers ().
+ // Thus if a register is upwards exposed in an EH handler, it won't
+ // be propagated across the EH edge.
+ //
+ // Excluding that special case, all registers live on entry to
+ // EBB are also live on exit from PRED_BB and were (or will be)
+ // considered when creating LIVE_OUT.
+ gcc_checking_assert ((e->flags & EDGE_EH)
+ || !bitmap_intersect_compl_p (&lr_info->in,
+ DF_LR_OUT (e->src)));
+ if (!pred_bb || !pred_bb->head_insn ())
+ {
+ has_backedge = true;
+ live_out = nullptr;
+ }
+ has_eh_edge |= (e->flags & EDGE_EH);
+ pred_live_outs.quick_push (live_out);
+ }
+
+ // PRED_REG_INDICES[I] tracks the index into PRED_LIVE_OUTS[I]->reg_values
+ // of the first unused entry.
+ auto_vec<unsigned int, 16> pred_reg_indices (num_preds);
+ pred_reg_indices.quick_grow_cleared (num_preds);
+
+ // Use this array to build up the list of inputs to each phi.
+ m_temp_defs.safe_grow (num_preds);
+
+ // Return true if the current phi is degenerate, i.e. if all its inputs
+ // are the same.
+ auto is_degenerate_phi = [&]()
+ {
+ if (has_backedge)
+ return false;
+
+ for (unsigned int i = 1; i < num_preds; ++i)
+ if (m_temp_defs[i] != m_temp_defs[0])
+ return false;
+
+ return true;
+ };
+
+ // Finish calculating the live-in value for RESOURCE. Decide how to
+ // represent the value of RESOURCE on entry to EBB and return its definition.
+ auto finish_phi = [&](resource_info resource) -> set_info *
+ {
+ access_info **inputs;
+ unsigned int num_inputs;
+ if (is_degenerate_phi ())
+ {
+ auto *input = safe_as_a<set_info *> (m_temp_defs[0]);
+ if (!input)
+ // The live-in value is completely uninitialized.
+ return nullptr;
+
+ unsigned int regno = input->regno ();
+ if (input->is_reg () && !bitmap_bit_p (bi.ebb_use, regno))
+ // The live-in value comes from a single source and there
+ // are no uses of it within the EBB itself. We therefore
+ // don't need a phi node.
+ return input;
+
+ // The live-in value comes from a single source and might be
+ // used by the EBB itself. Create a degenerate phi for it.
+ inputs = m_temp_defs.begin ();
+ num_inputs = 1;
+ }
+ else
+ {
+ obstack_grow (&m_obstack, m_temp_defs.address (),
+ num_preds * sizeof (access_info *));
+ inputs = static_cast<access_info **> (obstack_finish (&m_obstack));
+ num_inputs = num_preds;
+ }
+ return create_phi (ebb, resource, inputs, num_inputs);
+ };
+
+ if (bi.ebb_live_in_for_debug)
+ bitmap_clear (bi.ebb_live_in_for_debug);
+
+ // Get the definition of each live input register, excluding registers
+ // that are known to have a single definition that dominates all uses.
+ unsigned int regno;
+ bitmap_iterator in_bi;
+ EXECUTE_IF_AND_IN_BITMAP (&lr_info->in, m_potential_phi_regs,
+ 0, regno, in_bi)
+ {
+ for (unsigned int pred_i = 0; pred_i < num_preds; ++pred_i)
+ {
+ set_info *input = nullptr;
+ if (const bb_live_out_info *pred_live_out = pred_live_outs[pred_i])
+ {
+ // Skip over registers that aren't live on entry to this block.
+ unsigned int reg_i = pred_reg_indices[pred_i];
+ while (reg_i < pred_live_out->num_reg_values
+ && pred_live_out->reg_values[reg_i]->regno () < regno)
+ reg_i += 1;
+
+ // As we asserted above, REGNO is live out from the predecessor
+ // block, at least by the LR reckoning. But there are three
+ // cases:
+ //
+ // (1) The live-out value is well-defined (the normal case),
+ // with the definition coming either from the block itself
+ // or from a predecessor block. In this case reg_values
+ // has a set_info entry for the register.
+ //
+ // (2) The live-out value was not modified by the predecessor
+ // EBB and did not have a defined value on input to that
+ // EBB either. In this case reg_values has no entry for
+ // the register.
+ //
+ // (3) The live-out value was modified by the predecessor EBB,
+ // but the final modification was a clobber rather than
+ // a set. In this case reg_values again has no entry for
+ // the register.
+ //
+ // The phi input for (2) and (3) is undefined, which we
+ // represent as a null set_info.
+ if (reg_i < pred_live_out->num_reg_values)
+ {
+ set_info *set = pred_live_out->reg_values[reg_i];
+ if (set->regno () == regno)
+ {
+ input = set;
+ reg_i += 1;
+ }
+ }
+
+ // Fully call-clobbered values do not survive across EH edges.
+ // In particular, if a call that normally sets a result register
+ // throws an exception, the set of the result register should
+ // not be treated as live on entry to the EH handler.
+ if (has_eh_edge
+ && HARD_REGISTER_NUM_P (regno)
+ && eh_edge_abi.clobbers_full_reg_p (regno)
+ && (EDGE_PRED (cfg_bb, pred_i)->flags & EDGE_EH))
+ input = nullptr;
+
+ pred_reg_indices[pred_i] = reg_i;
+ }
+ m_temp_defs[pred_i] = input;
+ }
+ // Later code works out the correct mode of the phi. Use BLKmode
+ // as a placeholder for now.
+ bi.record_reg_def (regno, finish_phi ({ E_BLKmode, regno }));
+ if (bi.ebb_live_in_for_debug)
+ bitmap_set_bit (bi.ebb_live_in_for_debug, regno);
+ }
+
+ // Repeat the process above for memory.
+ for (unsigned int pred_i = 0; pred_i < num_preds; ++pred_i)
+ {
+ set_info *input = nullptr;
+ if (const bb_live_out_info *pred_live_out = pred_live_outs[pred_i])
+ input = pred_live_out->mem_value;
+ m_temp_defs[pred_i] = input;
+ }
+ bi.record_mem_def (finish_phi (memory));
+
+ m_temp_defs.truncate (0);
+}
+
+// Called while building SSA form using BI.
+//
+// If FLAGS is DF_REF_AT_TOP, create the head insn for BI.current_bb
+// and populate its uses and definitions. If FLAGS is 0, do the same
+// for the end insn.
+void
+function_info::add_artificial_accesses (build_info &bi, df_ref_flags flags)
+{
+ bb_info *bb = bi.current_bb;
+ basic_block cfg_bb = bb->cfg_bb ();
+ auto *lr_info = DF_LR_BB_INFO (cfg_bb);
+ df_ref ref;
+
+ insn_info *insn;
+ if (flags == DF_REF_AT_TOP)
+ {
+ if (cfg_bb->index == EXIT_BLOCK)
+ insn = append_artificial_insn (bb);
+ else
+ insn = append_artificial_insn (bb, bb_note (cfg_bb));
+ bb->set_head_insn (insn);
+ }
+ else
+ {
+ insn = append_artificial_insn (bb);
+ bb->set_end_insn (insn);
+ }
+
+ start_insn_accesses ();
+
+ FOR_EACH_ARTIFICIAL_USE (ref, cfg_bb->index)
+ if ((DF_REF_FLAGS (ref) & DF_REF_AT_TOP) == flags)
+ {
+ unsigned int regno = DF_REF_REGNO (ref);
+ machine_mode mode = GET_MODE (DF_REF_REAL_REG (ref));
+ resource_info resource { mode, regno };
+
+ // A definition must be available.
+ gcc_checking_assert (bitmap_bit_p (&lr_info->in, regno)
+ || (flags != DF_REF_AT_TOP
+ && bitmap_bit_p (&lr_info->def, regno)));
+ set_info *def = bi.current_reg_value (regno);
+ auto *use = allocate<use_info> (insn, resource, def);
+ add_use (use);
+ m_temp_uses.safe_push (use);
+ }
+
+ // Track the return value of memory by adding an artificial use of
+ // memory at the end of the exit block.
+ if (flags == 0 && cfg_bb->index == EXIT_BLOCK)
+ {
+ auto *use = allocate<use_info> (insn, memory, bi.current_mem_value ());
+ add_use (use);
+ m_temp_uses.safe_push (use);
+ }
+
+ FOR_EACH_ARTIFICIAL_DEF (ref, cfg_bb->index)
+ if ((DF_REF_FLAGS (ref) & DF_REF_AT_TOP) == flags)
+ {
+ unsigned int regno = DF_REF_REGNO (ref);
+ machine_mode mode = GET_MODE (DF_REF_REAL_REG (ref));
+ resource_info resource { mode, regno };
+
+ // If the value isn't used later in the block and isn't live
+ // on exit, we could instead represent the definition as a
+ // clobber_info. However, that case should be relatively
+ // rare and set_info is any case more compact than clobber_info.
+ set_info *def = allocate<set_info> (insn, resource);
+ append_def (def);
+ m_temp_defs.safe_push (def);
+ bi.record_reg_def (regno, def);
+ }
+
+ // Model the effect of a memory clobber on an incoming edge by adding
+ // a fake definition of memory at the start of the block. We don't need
+ // to add a use of the phi node because memory is implicitly always live.
+ if (flags == DF_REF_AT_TOP && has_abnormal_call_or_eh_pred_edge_p (cfg_bb))
+ {
+ set_info *def = allocate<set_info> (insn, memory);
+ append_def (def);
+ m_temp_defs.safe_push (def);
+ bi.record_mem_def (def);
+ }
+
+ finish_insn_accesses (insn);
+}
+
+// Called while building SSA form using BI. Create insn_infos for all
+// relevant instructions in BI.current_bb.
+void
+function_info::add_block_contents (build_info &bi)
+{
+ basic_block cfg_bb = bi.current_bb->cfg_bb ();
+ rtx_insn *insn;
+ FOR_BB_INSNS (cfg_bb, insn)
+ if (INSN_P (insn))
+ add_insn_to_block (bi, insn);
+}
+
+// Called while building SSA form using BI. Use BI.bb_live_out to record
+// the values that are live out from BI.current_bb.
+void
+function_info::record_block_live_out (build_info &bi)
+{
+ bb_info *bb = bi.current_bb;
+ ebb_info *ebb = bi.current_ebb;
+ basic_block cfg_bb = bb->cfg_bb ();
+ bb_live_out_info *live_out = &bi.bb_live_out[bb->index ()];
+ auto *lr_info = DF_LR_BB_INFO (bb->cfg_bb ());
+
+ // Calculate which subset of m_potential_phi_regs is live out from EBB
+ // at the end of BB.
+ auto_bitmap live_out_from_ebb;
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, cfg_bb->succs)
+ {
+ bb_info *dest_bb = this->bb (e->dest);
+ if (!dest_bb || dest_bb->ebb () != ebb)
+ bitmap_ior_and_into (live_out_from_ebb, DF_LR_IN (e->dest),
+ m_potential_phi_regs);
+ }
+
+ // Record the live-out register values.
+ unsigned int regno;
+ bitmap_iterator out_bi;
+ EXECUTE_IF_AND_IN_BITMAP (&lr_info->out, m_potential_phi_regs,
+ 0, regno, out_bi)
+ if (set_info *value = live_out_value (bb, bi.current_reg_value (regno)))
+ {
+ if (value->ebb () == ebb && bitmap_bit_p (live_out_from_ebb, regno))
+ add_live_out_use (bb, value);
+ obstack_ptr_grow (&m_temp_obstack, value);
+ }
+
+ live_out->num_reg_values = (obstack_object_size (&m_temp_obstack)
+ / sizeof (set_info *));
+ auto *data = obstack_finish (&m_temp_obstack);
+ live_out->reg_values = static_cast<set_info **> (data);
+
+ live_out->mem_value = live_out_value (bb, bi.current_mem_value ());
+}
+
+// Called while building SSA form using BI. Check if BI.current_bb has
+// any outgoing backedges. If so, use the up-to-date contents of
+// BI.bb_live_out to populate the associated inputs of any phi nodes.
+void
+function_info::populate_backedge_phis (build_info &bi)
+{
+ bb_info *bb = bi.current_bb;
+ basic_block cfg_bb = bb->cfg_bb ();
+ const bb_live_out_info *live_out = &bi.bb_live_out[bb->index ()];
+
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, cfg_bb->succs)
+ {
+ // Check if this edge counts as a backedge in the current traversal.
+ bb_info *succ_bb = this->bb (e->dest);
+ if (!succ_bb || !succ_bb->head_insn ())
+ continue;
+
+ // Although the phis do not keep a defined order long-term, they are
+ // still in reverse regno order at this point. We can therefore use
+ // a merge operation on the phis and the live-out values.
+ unsigned int input_i = e->dest_idx;
+ int reg_i = live_out->num_reg_values - 1;
+ for (phi_info *phi : succ_bb->ebb ()->phis ())
+ {
+ set_info *input = nullptr;
+ if (phi->is_mem ())
+ input = live_out->mem_value;
+ else
+ {
+ // Skip over any intervening live-out values.
+ unsigned int regno = phi->regno ();
+ while (reg_i >= 0)
+ {
+ set_info *reg_value = live_out->reg_values[reg_i];
+ if (reg_value->regno () < regno)
+ break;
+ reg_i -= 1;
+ if (reg_value->regno () == regno)
+ {
+ input = reg_value;
+ break;
+ }
+ }
+ }
+ if (input)
+ {
+ use_info *use = phi->input_use (input_i);
+ gcc_assert (!use->def ());
+ use->set_def (input);
+ add_use (use);
+ }
+ }
+ }
+}
+
+// Return true if it would be better to continue an EBB across NEW_EDGE
+// rather than across OLD_EDGE, given that both edges are viable candidates.
+// This is not a total ordering.
+static bool
+better_ebb_edge_p (edge new_edge, edge old_edge)
+{
+ // Prefer the likeliest edge.
+ if (new_edge->probability.initialized_p ()
+ && old_edge->probability.initialized_p ()
+ && !(old_edge->probability == new_edge->probability))
+ return old_edge->probability < new_edge->probability;
+
+ // If both edges are equally likely, prefer a fallthru edge.
+ if (new_edge->flags & EDGE_FALLTHRU)
+ return true;
+ if (old_edge->flags & EDGE_FALLTHRU)
+ return false;
+
+ // Otherwise just stick with OLD_EDGE.
+ return false;
+}
+
+// Pick and return the next basic block in an EBB that currently ends with BB.
+// Return null if the EBB must end with BB.
+static basic_block
+choose_next_block_in_ebb (basic_block bb)
+{
+ // Although there's nothing in principle wrong with having an EBB that
+ // starts with the entry block and includes later blocks, there's not
+ // really much point either. Keeping the entry block separate means
+ // that uses of arguments consistently occur through phi nodes, rather
+ // than the arguments sometimes appearing to come from an EBB-local
+ // definition instead.
+ if (bb->index == ENTRY_BLOCK)
+ return nullptr;
+
+ bool optimize_for_speed_p = optimize_bb_for_speed_p (bb);
+ edge best_edge = nullptr;
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (!(e->flags & EDGE_COMPLEX)
+ && e->dest->index != EXIT_BLOCK
+ && single_pred_p (e->dest)
+ && optimize_for_speed_p == optimize_bb_for_speed_p (e->dest)
+ && (!best_edge || better_ebb_edge_p (e, best_edge)))
+ best_edge = e;
+
+ return best_edge ? best_edge->dest : nullptr;
+}
+
+// Partition the function's blocks into EBBs and build SSA form for all
+// EBBs in the function.
+void
+function_info::process_all_blocks ()
+{
+ auto temps = temp_watermark ();
+ unsigned int num_bb_indices = last_basic_block_for_fn (m_fn);
+
+ // Compute the starting reverse postorder. We tweak this later to try
+ // to get better EBB assignments.
+ auto *postorder = new int[n_basic_blocks_for_fn (m_fn)];
+ unsigned int postorder_num
+ = pre_and_rev_post_order_compute (nullptr, postorder, true);
+ gcc_assert (int (postorder_num) <= n_basic_blocks_for_fn (m_fn));
+
+ // Construct the working state for this function and its subroutines.
+ build_info bi;
+ bi.last_access = XOBNEWVEC (&m_temp_obstack, access_info *, m_num_regs + 1);
+ memset (bi.last_access, 0, (m_num_regs + 1) * sizeof (set_info *));
+
+ // The bb_live_out array shouldn't need to be initialized, since we'll
+ // always write to an entry before reading from it. But poison the
+ // contents when checking, just to make sure we don't accidentally use
+ // an uninitialized value.
+ bi.bb_live_out = XOBNEWVEC (&m_temp_obstack, bb_live_out_info,
+ num_bb_indices);
+ if (flag_checking)
+ memset (bi.bb_live_out, 0xaf,
+ num_bb_indices * sizeof (bb_live_out_info));
+
+ // Only pay the overhead of recording a separate live-in bitmap if
+ // there are debug instructions that might need it.
+ auto_bitmap ebb_live_in;
+ if (MAY_HAVE_DEBUG_INSNS)
+ {
+ bi.ebb_live_in_for_debug = ebb_live_in;
+ // The bitmap is tested using individual bit operations, so optimize
+ // for that case.
+ bitmap_tree_view (ebb_live_in);
+ }
+ else
+ bi.ebb_live_in_for_debug = nullptr;
+
+ // Iterate over the blocks in reverse postorder. In cases where
+ // multiple possible orders exist, prefer orders that chain blocks
+ // together into EBBs. If multiple possible EBBs exist, try to pick
+ // the ones that are most likely to be profitable.
+ auto_vec<bb_info *, 16> ebb;
+ auto_bitmap ebb_use_tmp;
+ auto_bitmap ebb_def_tmp;
+ for (unsigned int i = 0; i < postorder_num; ++i)
+ if (!m_bbs[postorder[i]])
+ {
+ // Choose and create the blocks that should form the next EBB,
+ // and calculate the set of registers that the EBB uses and defines
+ // Only do actual bitmap operations if the EBB contains multiple
+ // blocks.
+ basic_block cfg_bb = BASIC_BLOCK_FOR_FN (m_fn, postorder[i]);
+ bi.ebb_use = &DF_LR_BB_INFO (cfg_bb)->use;
+ bi.ebb_def = &DF_LR_BB_INFO (cfg_bb)->def;
+ ebb.safe_push (create_bb_info (cfg_bb));
+ cfg_bb = choose_next_block_in_ebb (cfg_bb);
+ if (cfg_bb)
+ {
+ // An EBB with two blocks.
+ bitmap_ior (ebb_use_tmp, bi.ebb_use, &DF_LR_BB_INFO (cfg_bb)->use);
+ bitmap_ior (ebb_def_tmp, bi.ebb_def, &DF_LR_BB_INFO (cfg_bb)->def);
+ bi.ebb_use = ebb_use_tmp;
+ bi.ebb_def = ebb_def_tmp;
+ ebb.safe_push (create_bb_info (cfg_bb));
+ cfg_bb = choose_next_block_in_ebb (cfg_bb);
+ while (cfg_bb)
+ {
+ // An EBB with three or more blocks.
+ bitmap_ior_into (bi.ebb_use, &DF_LR_BB_INFO (cfg_bb)->use);
+ bitmap_ior_into (bi.ebb_def, &DF_LR_BB_INFO (cfg_bb)->def);
+ ebb.safe_push (create_bb_info (cfg_bb));
+ cfg_bb = choose_next_block_in_ebb (cfg_bb);
+ }
+ }
+
+ // Create the EBB itself.
+ bi.current_ebb = allocate<ebb_info> (ebb[0], ebb.last ());
+ for (bb_info *bb : ebb)
+ {
+ bb->set_ebb (bi.current_ebb);
+ append_bb (bb);
+ }
+
+ // Populate the contents of the EBB.
+ bi.current_ebb->set_phi_insn (append_artificial_insn (ebb[0]));
+ if (ebb[0]->index () == ENTRY_BLOCK)
+ {
+ gcc_assert (ebb.length () == 1);
+ bi.current_bb = ebb[0];
+ add_entry_block_defs (bi);
+ record_block_live_out (bi);
+ }
+ else if (EDGE_COUNT (ebb[0]->cfg_bb ()->preds) == 0)
+ // Leave unreachable blocks empty, since there is no useful
+ // liveness information for them, and anything they do will
+ // be wasted work. In a cleaned-up cfg, the only unreachable
+ // block we should see is the exit block of a noreturn function.
+ for (bb_info *bb : ebb)
+ {
+ bb->set_head_insn (append_artificial_insn (bb));
+ bb->set_end_insn (append_artificial_insn (bb));
+ }
+ else
+ {
+ add_phi_nodes (bi);
+ for (bb_info *bb : ebb)
+ {
+ bi.current_bb = bb;
+ add_artificial_accesses (bi, DF_REF_AT_TOP);
+ if (bb->index () != EXIT_BLOCK)
+ add_block_contents (bi);
+ add_artificial_accesses (bi, df_ref_flags ());
+ record_block_live_out (bi);
+ populate_backedge_phis (bi);
+ }
+ }
+ ebb.truncate (0);
+ }
+
+ delete[] postorder;
+}
+
+// Print a description of CALL_CLOBBERS to PP.
+void
+rtl_ssa::pp_ebb_call_clobbers (pretty_printer *pp,
+ const ebb_call_clobbers_info *call_clobbers)
+{
+ if (!call_clobbers)
+ pp_string (pp, "<null>");
+ else
+ call_clobbers->print_full (pp);
+}
+
+// Print a description of BB to PP.
+void
+rtl_ssa::pp_bb (pretty_printer *pp, const bb_info *bb)
+{
+ if (!bb)
+ pp_string (pp, "<null>");
+ else
+ bb->print_full (pp);
+}
+
+// Print a description of EBB to PP
+void
+rtl_ssa::pp_ebb (pretty_printer *pp, const ebb_info *ebb)
+{
+ if (!ebb)
+ pp_string (pp, "<null>");
+ else
+ ebb->print_full (pp);
+}
+
+// Print a description of CALL_CLOBBERS to FILE.
+void
+dump (FILE *file, const ebb_call_clobbers_info *call_clobbers)
+{
+ dump_using (file, pp_ebb_call_clobbers, call_clobbers);
+}
+
+// Print a description of BB to FILE.
+void
+dump (FILE *file, const bb_info *bb)
+{
+ dump_using (file, pp_bb, bb);
+}
+
+// Print a description of EBB to FILE.
+void
+dump (FILE *file, const ebb_info *ebb)
+{
+ dump_using (file, pp_ebb, ebb);
+}
+
+// Debug interfaces to the dump routines above.
+void debug (const ebb_call_clobbers_info *x) { dump (stderr, x); }
+void debug (const bb_info *x) { dump (stderr, x); }
+void debug (const ebb_info *x) { dump (stderr, x); }
diff --git a/gcc/rtl-ssa/blocks.h b/gcc/rtl-ssa/blocks.h
new file mode 100644
index 0000000..f173e6f
--- /dev/null
+++ b/gcc/rtl-ssa/blocks.h
@@ -0,0 +1,301 @@
+// Basic-block-related classes for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// SSA-related information about a basic block. Each block contains
+// the following, which are conceptually executed in order:
+//
+// - an artificial "head" insn_info that holds artificial uses and definitions
+// for the start of the block.
+//
+// - one insn_info for each "real" instruction in the block
+// (i.e. those that have an RTL pattern).
+//
+// - an artificial "end" insn_info that holds artificial uses and definitions
+// for the end of the block.
+//
+// Blocks are grouped together into extended basic blocks. In cases where
+// multiple EBBs exist (such as in a full diamond), we try to pick the one
+// that's most frequently executed.
+//
+// Blocks are chained together in reverse postorder. (Rather than use a
+// list, we could instead have stored the index of the block in the overall
+// postorder. However, using lists should make it cheaper to update the
+// information after trivial CFG manipulations.)
+class bb_info
+{
+ // Size: 6 LP64 words.
+ friend class function_info;
+
+public:
+ // Return the previous basic block in reverse postorder, or null if this
+ // is the entry block.
+ bb_info *prev_bb () const { return m_prev_bb; }
+
+ // Return the next basic block in reverse postorder, or null if this
+ // is the exit block.
+ bb_info *next_bb () const { return m_next_bb; }
+
+ // Return true if this block is the function's entry block.
+ bool is_entry_block () const { return !m_prev_bb; }
+
+ // Return true if this block is the function's exit block.
+ bool is_exit_block () const { return !m_next_bb; }
+
+ // Return the underlying basic_block structure.
+ basic_block cfg_bb () const { return m_cfg_bb; }
+
+ // Return the unique identifier of the underlying basic_block. These uids
+ // do not follow any particular order.
+ unsigned int index () const { return m_cfg_bb->index; }
+
+ // Return the EBB that contains this block.
+ ebb_info *ebb () const { return m_ebb; }
+
+ // Return a list of all the instructions in the block, in execution order.
+ // The list includes the head and end instructions described above.
+ //
+ // Iterations over the list will pick up any new instructions that are
+ // inserted after the iterator's current instruction.
+ iterator_range<any_insn_iterator> all_insns () const;
+
+ // Like all_insns (), except that the instructions are in reverse order.
+ //
+ // Iterations over the list will pick up any new instructions that are
+ // inserted before the iterator's current instruction.
+ iterator_range<reverse_any_insn_iterator> reverse_all_insns () const;
+
+ // Like all_insns (), but without the debug instructions.
+ iterator_range<nondebug_insn_iterator> nondebug_insns () const;
+
+ // Like reverse_all_insns (), but without the debug instructions.
+ iterator_range<reverse_nondebug_insn_iterator>
+ reverse_nondebug_insns () const;
+
+ // Like all_insns (), but without the artificial instructions.
+ iterator_range<any_insn_iterator> real_insns () const;
+
+ // Like reverse_all_insns (), but without the artificial instructions.
+ iterator_range<reverse_any_insn_iterator> reverse_real_insns () const;
+
+ // Like real_insns (), but without the debug instructions.
+ iterator_range<nondebug_insn_iterator> real_nondebug_insns () const;
+
+ // Like reverse_real_insns (), but without the debug instructions.
+ iterator_range<reverse_nondebug_insn_iterator>
+ reverse_real_nondebug_insns () const;
+
+ // Return the instruction that holds the artificial uses and
+ // definitions at the head of the block. The associated RTL insn
+ // is the block head note.
+ //
+ // This instruction always exists, even if it has no uses and definitions.
+ insn_info *head_insn () const { return m_head_insn; }
+
+ // Return the instruction that holds the artificial uses and definitions
+ // at the end of the block. There is no associated RTL insn.
+ //
+ // This instruction always exists, even if it has no uses and definitions.
+ insn_info *end_insn () const { return m_end_insn; }
+
+ // Print "bb" + index () to PP.
+ void print_identifier (pretty_printer *pp) const;
+
+ // Print a full description of the block to PP.
+ void print_full (pretty_printer *) const;
+
+private:
+ bb_info (basic_block);
+
+ void set_prev_bb (bb_info *bb) { m_prev_bb = bb; }
+ void set_next_bb (bb_info *bb) { m_next_bb = bb; }
+ void set_cfg_bb (basic_block cfg_bb) { m_cfg_bb = cfg_bb; }
+ void set_ebb (ebb_info *ebb) { m_ebb = ebb; }
+ void set_head_insn (insn_info *insn) { m_head_insn = insn; }
+ void set_end_insn (insn_info *insn) { m_end_insn = insn; }
+
+ // The values returned by the functions above.
+ bb_info *m_prev_bb;
+ bb_info *m_next_bb;
+ basic_block m_cfg_bb;
+ ebb_info *m_ebb;
+ insn_info *m_head_insn;
+ insn_info *m_end_insn;
+};
+
+// Iterators for lists of basic blocks.
+using bb_iterator = list_iterator<bb_info, &bb_info::next_bb>;
+using reverse_bb_iterator = list_iterator<bb_info, &bb_info::prev_bb>;
+
+// This class collects together instructions for which has_call_clobbers ()
+// is true, storing them in a splay tree that follows reverse postorder.
+// Instances of the class form a singly-linked list, with one instance
+// per predefined_function_abi.
+class ebb_call_clobbers_info : public insn_call_clobbers_tree
+{
+ // Size 3 LP64 words.
+ friend class function_info;
+
+public:
+ // Return the next group in the list.
+ ebb_call_clobbers_info *next () const { return m_next; }
+
+ // Return the function abi used by all the calls in the group.
+ const predefined_function_abi *abi () const { return m_abi; }
+
+ // Return true if at least one call in the group should conservatively
+ // be assumed to clobber RESOURCE.
+ bool clobbers (resource_info) const;
+
+ // Print a summary of what the class describes to PP, without printing
+ // the actual instructions.
+ void print_summary (pretty_printer *pp) const;
+
+ // Print a full description of the object to PP, including the
+ // instructions it contains.
+ void print_full (pretty_printer *) const;
+
+private:
+ ebb_call_clobbers_info (const predefined_function_abi *);
+
+ // The values returned by the accessors above.
+ ebb_call_clobbers_info *m_next;
+ const predefined_function_abi *m_abi;
+};
+
+// A list of ebb_call_clobbers_infos.
+using ebb_call_clobbers_iterator
+ = list_iterator<ebb_call_clobbers_info, &ebb_call_clobbers_info::next>;
+
+// Information about an extended basic block.
+//
+// Each EBB has a list of phi nodes and starts with an artificial phi
+// instruction that conceptually "executes" the phi nodes. The phi
+// nodes are independent of one another and so can be executed in any
+// order. The order of the phi nodes in the list is not significant.
+//
+// Each EBB also maintains a list of ebb_call_clobbers_info structures
+// that describe all instructions for which has_call_clobbers () is true.
+// See the comment above that class for details.
+class ebb_info
+{
+ // Size: 5 LP64 words.
+ friend class function_info;
+
+public:
+ // Return the previous EBB in reverse postorder, or null if this EBB
+ // contains the entry block.
+ ebb_info *prev_ebb () const;
+
+ // Return the next EBB in reverse postorder, or null if this EBB contains
+ // the exit block.
+ ebb_info *next_ebb () const;
+
+ // Return the instruction that holds the EBB's phi nodes (and does
+ // nothing else). There is no associated RTL insn.
+ //
+ // This instruction always exists, even if the EBB does not currently
+ // need any phi nodes.
+ insn_info *phi_insn () const { return m_phi_insn; }
+
+ // Return the first and last blocks in the EBB.
+ bb_info *first_bb () const { return m_first_bb; }
+ bb_info *last_bb () const { return m_last_bb; }
+
+ // Return the first of the EBB's phi nodes.
+ phi_info *first_phi () const { return m_first_phi; }
+
+ // Return the head of the list of ebb_call_clobbers_infos.
+ ebb_call_clobbers_info *first_call_clobbers () const;
+
+ // Return the list of ebb_call_clobbers_infos.
+ iterator_range<ebb_call_clobbers_iterator> call_clobbers () const;
+
+ // Return a list of the EBB's phi nodes, in arbitrary order.
+ iterator_range<phi_iterator> phis () const;
+
+ // Return a list of the blocks in the EBB, in execution order.
+ iterator_range<bb_iterator> bbs () const;
+
+ // Return a list of the blocks in the EBB, in reverse execution order.
+ iterator_range<reverse_bb_iterator> reverse_bbs () const;
+
+ // Return a list of all the instructions in the EBB, in execution order.
+ // The list includes phi_insn (), the head and end of each block,
+ // and the real instructions in each block.
+ //
+ // Iterations over the list will pick up any new instructions that are
+ // inserted after the iterator's current instruction.
+ iterator_range<any_insn_iterator> all_insns () const;
+
+ // Like all_insns (), except that the instructions are in reverse order.
+ //
+ // Iterations over the list will pick up any new instructions that are
+ // inserted before the iterator's current instruction.
+ iterator_range<reverse_any_insn_iterator> reverse_all_insns () const;
+
+ // Like all_insns (), but without the debug instructions.
+ iterator_range<nondebug_insn_iterator> nondebug_insns () const;
+
+ // Like reverse_all_insns (), but without the debug instructions.
+ iterator_range<reverse_nondebug_insn_iterator>
+ reverse_nondebug_insns () const;
+
+ // Return an insn_range that covers the same instructions as all_insns ().
+ insn_range_info insn_range () const;
+
+ // Print "ebb" + first_bb ()->index () to PP.
+ void print_identifier (pretty_printer *pp) const;
+
+ // Print a full description of the EBB to PP.
+ void print_full (pretty_printer *pp) const;
+
+private:
+ ebb_info (bb_info *, bb_info *);
+
+ void set_first_phi (phi_info *phi) { m_first_phi = phi; }
+ void set_phi_insn (insn_info *insn) { m_phi_insn = insn; }
+ void set_first_call_clobbers (ebb_call_clobbers_info *);
+
+ // The values returned by the functions above.
+ phi_info *m_first_phi;
+ insn_info *m_phi_insn;
+ bb_info *m_first_bb;
+ bb_info *m_last_bb;
+ ebb_call_clobbers_info *m_first_call_clobbers;
+};
+
+// Iterators for lists of extended basic blocks.
+using ebb_iterator = list_iterator<ebb_info, &ebb_info::next_ebb>;
+using reverse_ebb_iterator = list_iterator<ebb_info, &ebb_info::prev_ebb>;
+
+void pp_bb (pretty_printer *, const bb_info *);
+void pp_ebb_call_clobbers (pretty_printer *, const ebb_call_clobbers_info *);
+void pp_ebb (pretty_printer *, const ebb_info *);
+
+}
+
+void dump (FILE *, const rtl_ssa::bb_info *);
+void dump (FILE *, const rtl_ssa::ebb_call_clobbers_info *);
+void dump (FILE *, const rtl_ssa::ebb_info *);
+
+void DEBUG_FUNCTION debug (const rtl_ssa::bb_info *);
+void DEBUG_FUNCTION debug (const rtl_ssa::ebb_call_clobbers_info *);
+void DEBUG_FUNCTION debug (const rtl_ssa::ebb_info *);
diff --git a/gcc/rtl-ssa/change-utils.h b/gcc/rtl-ssa/change-utils.h
new file mode 100644
index 0000000..8245330
--- /dev/null
+++ b/gcc/rtl-ssa/change-utils.h
@@ -0,0 +1,137 @@
+// RTL SSA utility functions for changing instructions -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// Return true if INSN is one of the instructions being changed by CHANGES.
+inline bool
+insn_is_changing (array_slice<insn_change *const> changes,
+ const insn_info *insn)
+{
+ for (const insn_change *change : changes)
+ if (change->insn () == insn)
+ return true;
+ return false;
+}
+
+// Return a closure of insn_is_changing, for use as a predicate.
+// This could be done using local lambdas instead, but the predicate is
+// used often enough that having a class should be more convenient and allow
+// reuse of template instantiations.
+//
+// We don't use std::bind because it would involve an indirect function call,
+// whereas this function is used in relatively performance-critical code.
+inline insn_is_changing_closure
+insn_is_changing (array_slice<insn_change *const> changes)
+{
+ return insn_is_changing_closure (changes);
+}
+
+// Restrict CHANGE.move_range so that the changed instruction can perform
+// all its definitions and uses. Assume that if:
+//
+// - CHANGE contains an access A1 of resource R;
+// - an instruction I2 contains another access A2 to R; and
+// - IGNORE (I2) is true
+//
+// then either:
+//
+// - A2 will be removed; or
+// - something will ensure that A1 and A2 maintain their current order,
+// without this having to be enforced by CHANGE's move range.
+//
+// IGNORE should return true for CHANGE.insn ().
+//
+// Return true on success, otherwise leave CHANGE.move_range in an invalid
+// state.
+//
+// This function only works correctly for instructions that remain within
+// the same extended basic block.
+template<typename IgnorePredicate>
+bool
+restrict_movement_ignoring (insn_change &change, IgnorePredicate ignore)
+{
+ // Uses generally lead to failure quicker, so test those first.
+ return (restrict_movement_for_uses_ignoring (change.move_range,
+ change.new_uses, ignore)
+ && restrict_movement_for_defs_ignoring (change.move_range,
+ change.new_defs, ignore)
+ && canonicalize_move_range (change.move_range, change.insn ()));
+}
+
+// Like restrict_movement_ignoring, but ignore only the instruction
+// that is being changed.
+inline bool
+restrict_movement (insn_change &change)
+{
+ return restrict_movement_ignoring (change, insn_is (change.insn ()));
+}
+
+using add_regno_clobber_fn = std::function<bool (insn_change &,
+ unsigned int)>;
+bool recog_internal (insn_change &, add_regno_clobber_fn);
+
+// Try to recognize the new instruction pattern for CHANGE, potentially
+// tweaking the pattern or adding extra clobbers in order to make it match.
+//
+// When adding an extra clobber for register R, restrict CHANGE.move_range
+// to a range of instructions for which R is not live. When determining
+// whether R is live, ignore accesses made by an instruction I if
+// IGNORE (I) is true. The caller then assumes the responsibility
+// of ensuring that CHANGE and I are placed in a valid order.
+//
+// IGNORE should return true for CHANGE.insn ().
+//
+// Return true on success. Leave CHANGE unmodified on failure.
+template<typename IgnorePredicate>
+inline bool
+recog_ignoring (obstack_watermark &watermark, insn_change &change,
+ IgnorePredicate ignore)
+{
+ auto add_regno_clobber = [&](insn_change &change, unsigned int regno)
+ {
+ return crtl->ssa->add_regno_clobber (watermark, change, regno, ignore);
+ };
+ return recog_internal (change, add_regno_clobber);
+}
+
+// As for recog_ignoring, but ignore only the instruction that is being
+// changed.
+inline bool
+recog (obstack_watermark &watermark, insn_change &change)
+{
+ return recog_ignoring (watermark, change, insn_is (change.insn ()));
+}
+
+// Check whether insn costs indicate that the net effect of the changes
+// in CHANGES is worthwhile. Require a strict improvement if STRICT_P,
+// otherwise allow the new instructions to be the same cost as the old
+// instructions.
+bool changes_are_worthwhile (array_slice<insn_change *const> changes,
+ bool strict_p = false);
+
+// Like changes_are_worthwhile, but for a single change.
+inline bool
+change_is_worthwhile (insn_change &change, bool strict_p = false)
+{
+ insn_change *changes[] = { &change };
+ return changes_are_worthwhile (changes, strict_p);
+}
+
+}
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
new file mode 100644
index 0000000..1885a80
--- /dev/null
+++ b/gcc/rtl-ssa/changes.cc
@@ -0,0 +1,1025 @@
+// RTL SSA routines for changing instructions -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+#include "rtl-ssa/internals.inl"
+#include "target.h"
+#include "predict.h"
+#include "memmodel.h" // Needed by emit-rtl.h
+#include "emit-rtl.h"
+#include "cfghooks.h"
+#include "cfgrtl.h"
+
+using namespace rtl_ssa;
+
+// See the comment above the declaration.
+void
+insn_change::print (pretty_printer *pp) const
+{
+ if (m_is_deletion)
+ {
+ pp_string (pp, "deletion of ");
+ pp_insn (pp, m_insn);
+ }
+ else
+ {
+ pp_string (pp, "change to ");
+ pp_insn (pp, m_insn);
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "~~~~~~~");
+
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "new cost: ");
+ pp_decimal_int (pp, new_cost);
+
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "new uses:");
+ pp_newline_and_indent (pp, 2);
+ pp_accesses (pp, new_uses);
+ pp_indentation (pp) -= 2;
+
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "new defs:");
+ pp_newline_and_indent (pp, 2);
+ pp_accesses (pp, new_defs);
+ pp_indentation (pp) -= 2;
+
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "first insert-after candidate: ");
+ move_range.first->print_identifier_and_location (pp);
+
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "last insert-after candidate: ");
+ move_range.last->print_identifier_and_location (pp);
+ }
+}
+
+// Return a copy of access_array ACCESSES, allocating it on the
+// temporary obstack.
+access_array
+function_info::temp_access_array (access_array accesses)
+{
+ if (accesses.empty ())
+ return accesses;
+
+ gcc_assert (obstack_object_size (&m_temp_obstack) == 0);
+ obstack_grow (&m_temp_obstack, accesses.begin (), accesses.size_bytes ());
+ return { static_cast<access_info **> (obstack_finish (&m_temp_obstack)),
+ accesses.size () };
+}
+
+// See the comment above the declaration.
+bool
+function_info::verify_insn_changes (array_slice<insn_change *const> changes)
+{
+ HARD_REG_SET defined_hard_regs, clobbered_hard_regs;
+ CLEAR_HARD_REG_SET (defined_hard_regs);
+ CLEAR_HARD_REG_SET (clobbered_hard_regs);
+
+ insn_info *min_insn = m_first_insn;
+ for (insn_change *change : changes)
+ if (!change->is_deletion ())
+ {
+ // Make sure that the changes can be kept in their current order
+ // while honoring all of the move ranges.
+ min_insn = later_insn (min_insn, change->move_range.first);
+ while (min_insn != change->insn () && !can_insert_after (min_insn))
+ min_insn = min_insn->next_nondebug_insn ();
+ if (*min_insn > *change->move_range.last)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "no viable insn position assignment\n");
+ return false;
+ }
+
+ // If recog introduced new clobbers of a register as part of
+ // the matching process, make sure that they don't conflict
+ // with any other new definitions or uses of the register.
+ // (We have already checked that they don't conflict with
+ // unchanging definitions and uses.)
+ for (use_info *use : change->new_uses)
+ {
+ unsigned int regno = use->regno ();
+ if (HARD_REGISTER_NUM_P (regno)
+ && TEST_HARD_REG_BIT (clobbered_hard_regs, regno))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "register %d would be clobbered"
+ " while it is still live\n", regno);
+ return false;
+ }
+ }
+ for (def_info *def : change->new_defs)
+ {
+ unsigned int regno = def->regno ();
+ if (HARD_REGISTER_NUM_P (regno))
+ {
+ if (def->m_is_temp)
+ {
+ // This is a clobber introduced by recog.
+ gcc_checking_assert (is_a<clobber_info *> (def));
+ if (TEST_HARD_REG_BIT (defined_hard_regs, regno))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "conflicting definitions of"
+ " register %d\n", regno);
+ return false;
+ }
+ SET_HARD_REG_BIT (clobbered_hard_regs, regno);
+ }
+ else if (is_a<set_info *> (def))
+ {
+ // REGNO now has a defined value.
+ SET_HARD_REG_BIT (defined_hard_regs, regno);
+ CLEAR_HARD_REG_BIT (clobbered_hard_regs, regno);
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// See the comment above the declaration.
+bool
+rtl_ssa::changes_are_worthwhile (array_slice<insn_change *const> changes,
+ bool strict_p)
+{
+ unsigned int old_cost = 0;
+ unsigned int new_cost = 0;
+ for (insn_change *change : changes)
+ {
+ old_cost += change->old_cost ();
+ if (!change->is_deletion ())
+ {
+ basic_block cfg_bb = change->bb ()->cfg_bb ();
+ change->new_cost = insn_cost (change->rtl (),
+ optimize_bb_for_speed_p (cfg_bb));
+ new_cost += change->new_cost;
+ }
+ }
+ bool ok_p = (strict_p ? new_cost < old_cost : new_cost <= old_cost);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "original cost");
+ char sep = '=';
+ for (const insn_change *change : changes)
+ {
+ fprintf (dump_file, " %c %d", sep, change->old_cost ());
+ sep = '+';
+ }
+ fprintf (dump_file, ", replacement cost");
+ sep = '=';
+ for (const insn_change *change : changes)
+ if (!change->is_deletion ())
+ {
+ fprintf (dump_file, " %c %d", sep, change->new_cost);
+ sep = '+';
+ }
+ fprintf (dump_file, "; %s\n",
+ ok_p ? "keeping replacement" : "rejecting replacement");
+ }
+ if (!ok_p)
+ return false;
+
+ return true;
+}
+
+// Update the REG_NOTES of INSN, whose pattern has just been changed.
+static void
+update_notes (rtx_insn *insn)
+{
+ for (rtx *note_ptr = &REG_NOTES (insn); *note_ptr; )
+ {
+ rtx note = *note_ptr;
+ bool keep_p = true;
+ switch (REG_NOTE_KIND (note))
+ {
+ case REG_EQUAL:
+ case REG_EQUIV:
+ case REG_NOALIAS:
+ keep_p = (single_set (insn) != nullptr);
+ break;
+
+ case REG_UNUSED:
+ case REG_DEAD:
+ // These notes are stale. We'll recompute REG_UNUSED notes
+ // after the update.
+ keep_p = false;
+ break;
+
+ default:
+ break;
+ }
+ if (keep_p)
+ note_ptr = &XEXP (*note_ptr, 1);
+ else
+ {
+ *note_ptr = XEXP (*note_ptr, 1);
+ free_EXPR_LIST_node (note);
+ }
+ }
+}
+
+// Pick a location for CHANGE's instruction and return the instruction
+// after which it should be placed.
+static insn_info *
+choose_insn_placement (insn_change &change)
+{
+ gcc_checking_assert (change.move_range);
+
+ insn_info *insn = change.insn ();
+ insn_info *first = change.move_range.first;
+ insn_info *last = change.move_range.last;
+
+ // Quick(ish) exit if there is only one possible choice.
+ if (first == last)
+ return first;
+ if (first == insn->prev_nondebug_insn () && last == insn)
+ return insn;
+
+ // For now just use the closest valid choice to the original instruction.
+ // If the register usage has changed significantly, it might instead be
+ // better to try to take register pressure into account.
+ insn_info *closest = change.move_range.clamp_insn_to_range (insn);
+ while (closest != insn && !can_insert_after (closest))
+ closest = closest->next_nondebug_insn ();
+ return closest;
+}
+
+// Record any changes related to CHANGE that need to be queued for later.
+void
+function_info::possibly_queue_changes (insn_change &change)
+{
+ insn_info *insn = change.insn ();
+ rtx_insn *rtl = insn->rtl ();
+
+ // If the instruction could previously throw, we eventually need to call
+ // purge_dead_edges to check whether things have changed.
+ if (find_reg_note (rtl, REG_EH_REGION, nullptr))
+ bitmap_set_bit (m_need_to_purge_dead_edges, insn->bb ()->index ());
+
+ auto needs_pending_update = [&]()
+ {
+ // If an instruction became a no-op without the pass explicitly
+ // deleting it, queue the deletion for later. Removing the
+ // instruction on the fly would require an update to all instructions
+ // that use the result of the move, which would be a potential source
+ // of quadraticness. Also, definitions shouldn't disappear under
+ // the pass's feet.
+ if (INSN_CODE (rtl) == NOOP_MOVE_INSN_CODE)
+ return true;
+
+ // If any jumps got turned into unconditional jumps or nops, we need
+ // to update the CFG accordingly.
+ if (JUMP_P (rtl)
+ && (returnjump_p (rtl) || any_uncondjump_p (rtl))
+ && !single_succ_p (insn->bb ()->cfg_bb ()))
+ return true;
+
+ // If a previously conditional trap now always fires, execution
+ // terminates at that point.
+ rtx pattern = PATTERN (rtl);
+ if (GET_CODE (pattern) == TRAP_IF
+ && XEXP (pattern, 0) == const1_rtx)
+ return true;
+
+ return false;
+ };
+
+ if (needs_pending_update ()
+ && bitmap_set_bit (m_queued_insn_update_uids, insn->uid ()))
+ {
+ gcc_assert (!change.is_deletion ());
+ m_queued_insn_updates.safe_push (insn);
+ }
+}
+
+// Remove the instruction described by CHANGE from the underlying RTL
+// and from the insn_info list.
+static void
+delete_insn (insn_change &change)
+{
+ insn_info *insn = change.insn ();
+ rtx_insn *rtl = change.rtl ();
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "deleting insn %d\n", insn->uid ());
+ set_insn_deleted (rtl);
+}
+
+// Move the RTL instruction associated with CHANGE so that it comes
+// immediately after AFTER.
+static void
+move_insn (insn_change &change, insn_info *after)
+{
+ rtx_insn *rtl = change.rtl ();
+ rtx_insn *after_rtl = after->rtl ();
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "moving insn %d after insn %d\n",
+ INSN_UID (rtl), INSN_UID (after_rtl));
+
+ // At the moment we don't support moving instructions between EBBs,
+ // but this would be worth adding if it's useful.
+ insn_info *insn = change.insn ();
+ gcc_assert (after->ebb () == insn->ebb ());
+ bb_info *bb = after->bb ();
+ basic_block cfg_bb = bb->cfg_bb ();
+
+ if (insn->bb () != bb)
+ // Force DF to mark the old block as dirty.
+ df_insn_delete (rtl);
+ ::remove_insn (rtl);
+ ::add_insn_after (rtl, after_rtl, cfg_bb);
+}
+
+// The instruction associated with CHANGE is being changed in-place.
+// Update the DF information for its new pattern.
+static void
+update_insn_in_place (insn_change &change)
+{
+ insn_info *insn = change.insn ();
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "updating insn %d in-place\n", insn->uid ());
+ df_insn_rescan (change.rtl ());
+}
+
+// Finalize the new list of definitions and uses in CHANGE, removing
+// any uses and definitions that are no longer needed, and converting
+// pending clobbers into actual definitions.
+void
+function_info::finalize_new_accesses (insn_change &change)
+{
+ insn_info *insn = change.insn ();
+
+ // Get a list of all the things that the instruction now references.
+ vec_rtx_properties properties;
+ properties.add_insn (insn->rtl (), true);
+
+ // Build up the new list of definitions.
+ for (rtx_obj_reference ref : properties.refs ())
+ if (ref.is_write ())
+ {
+ def_info *def = find_access (change.new_defs, ref.regno);
+ gcc_assert (def);
+ if (def->m_is_temp)
+ {
+ // At present, the only temporary instruction definitions we
+ // create are clobbers, such as those added during recog.
+ gcc_assert (is_a<clobber_info *> (def));
+ def = allocate<clobber_info> (change.insn (), ref.regno);
+ }
+ else if (!def->m_has_been_superceded)
+ {
+ // This is a second or subsequent definition.
+ // See function_info::record_def for a discussion of when
+ // this can happen.
+ def->record_reference (ref, false);
+ continue;
+ }
+ else
+ {
+ def->m_has_been_superceded = false;
+
+ // Clobbers can move around, so remove them from their current
+ // position and them back in their final position.
+ //
+ // At the moment, we don't allow sets to move relative to other
+ // definitions of the same resource, so we can leave those where
+ // they are. It might be useful to relax this in future.
+ // The main complication is that removing a set would potentially
+ // fuse two adjoining clobber_groups, and adding the set back
+ // would require the group to be split again.
+ if (is_a<clobber_info *> (def))
+ remove_def (def);
+ else if (ref.is_reg ())
+ def->set_mode (ref.mode);
+ def->set_insn (insn);
+ }
+ def->record_reference (ref, true);
+ m_temp_defs.safe_push (def);
+ }
+
+ // Also keep any explicitly-recorded call clobbers, which are deliberately
+ // excluded from the vec_rtx_properties.
+ for (def_info *def : change.new_defs)
+ if (def->m_has_been_superceded && def->is_call_clobber ())
+ {
+ def->m_has_been_superceded = false;
+ def->set_insn (insn);
+ m_temp_defs.safe_push (def);
+ }
+
+ // Install the new list of definitions in CHANGE.
+ sort_accesses (m_temp_defs);
+ access_array accesses = temp_access_array (m_temp_defs);
+ change.new_defs = def_array (accesses);
+ m_temp_defs.truncate (0);
+
+ // Create temporary copies of use_infos that are already attached to
+ // other insns, which could happen if the uses come from unchanging
+ // insns or if they have been used by earlier changes. Doing this
+ // makes it easier to detect multiple reads below.
+ auto *unshared_uses_base = XOBNEWVEC (&m_temp_obstack, access_info *,
+ change.new_uses.size ());
+ unsigned int i = 0;
+ for (use_info *use : change.new_uses)
+ {
+ if (!use->m_has_been_superceded)
+ {
+ use = allocate_temp<use_info> (insn, use->resource (), use->def ());
+ use->m_has_been_superceded = true;
+ use->m_is_temp = true;
+ }
+ unshared_uses_base[i++] = use;
+ }
+ auto unshared_uses = use_array (unshared_uses_base, change.new_uses.size ());
+
+ // Add (possibly temporary) uses to m_temp_uses for each resource.
+ // If there are multiple references to the same resource, aggregate
+ // information in the modes and flags.
+ for (rtx_obj_reference ref : properties.refs ())
+ if (ref.is_read ())
+ {
+ unsigned int regno = ref.regno;
+ machine_mode mode = ref.is_reg () ? ref.mode : BLKmode;
+ use_info *use = find_access (unshared_uses, ref.regno);
+ gcc_assert (use);
+ if (use->m_has_been_superceded)
+ {
+ // This is the first reference to the resource.
+ bool is_temp = use->m_is_temp;
+ *use = use_info (insn, resource_info { mode, regno }, use->def ());
+ use->m_is_temp = is_temp;
+ use->record_reference (ref, true);
+ m_temp_uses.safe_push (use);
+ }
+ else
+ {
+ // Record the mode of the largest use. The choice is arbitrary if
+ // the instruction (unusually) references the same register in two
+ // different but equal-sized modes.
+ if (HARD_REGISTER_NUM_P (regno)
+ && partial_subreg_p (use->mode (), mode))
+ use->set_mode (mode);
+ use->record_reference (ref, false);
+ }
+ }
+
+ // Replace any temporary uses and definitions with real ones.
+ for (unsigned int i = 0; i < m_temp_uses.length (); ++i)
+ {
+ auto *use = as_a<use_info *> (m_temp_uses[i]);
+ if (use->m_is_temp)
+ {
+ m_temp_uses[i] = use = allocate<use_info> (*use);
+ use->m_is_temp = false;
+ set_info *def = use->def ();
+ // Handle cases in which the value was previously not used
+ // within the block.
+ if (def && def->m_is_temp)
+ {
+ phi_info *phi = as_a<phi_info *> (def);
+ gcc_assert (phi->is_degenerate ());
+ phi = create_degenerate_phi (phi->ebb (), phi->input_value (0));
+ use->set_def (phi);
+ }
+ }
+ }
+
+ // Install the new list of definitions in CHANGE.
+ sort_accesses (m_temp_uses);
+ change.new_uses = use_array (temp_access_array (m_temp_uses));
+ m_temp_uses.truncate (0);
+
+ // Record the new instruction-wide properties.
+ insn->set_properties (properties);
+}
+
+// Copy information from CHANGE to its underlying insn_info, given that
+// the insn_info has already been placed appropriately.
+void
+function_info::apply_changes_to_insn (insn_change &change)
+{
+ insn_info *insn = change.insn ();
+ if (change.is_deletion ())
+ {
+ insn->set_accesses (nullptr, 0, 0);
+ return;
+ }
+
+ // Copy the cost.
+ insn->set_cost (change.new_cost);
+
+ // Add all clobbers. Sets never moved relative to other definitions,
+ // so are OK as-is.
+ for (def_info *def : change.new_defs)
+ if (is_a<clobber_info *> (def))
+ add_def (def);
+
+ // Add all uses, now that their position is final.
+ for (use_info *use : change.new_uses)
+ add_use (use);
+
+ // Copy the uses and definitions.
+ unsigned int num_defs = change.new_defs.size ();
+ unsigned int num_uses = change.new_uses.size ();
+ if (num_defs + num_uses <= insn->num_defs () + insn->num_uses ())
+ insn->copy_accesses (change.new_defs, change.new_uses);
+ else
+ {
+ access_array_builder builder (&m_obstack);
+ builder.reserve (num_defs + num_uses);
+
+ for (def_info *def : change.new_defs)
+ builder.quick_push (def);
+ for (use_info *use : change.new_uses)
+ builder.quick_push (use);
+
+ insn->set_accesses (builder.finish ().begin (), num_defs, num_uses);
+ }
+
+ add_reg_unused_notes (insn);
+}
+
+// Add a temporary placeholder instruction after AFTER.
+insn_info *
+function_info::add_placeholder_after (insn_info *after)
+{
+ insn_info *insn = allocate_temp<insn_info> (after->bb (), nullptr, -1);
+ add_insn_after (insn, after);
+ return insn;
+}
+
+// See the comment above the declaration.
+void
+function_info::change_insns (array_slice<insn_change *> changes)
+{
+ auto watermark = temp_watermark ();
+
+ insn_info *min_insn = m_first_insn;
+ for (insn_change *change : changes)
+ {
+ // Tentatively mark all the old uses and definitions for deletion.
+ for (use_info *use : change->old_uses ())
+ {
+ use->m_has_been_superceded = true;
+ remove_use (use);
+ }
+ for (def_info *def : change->old_defs ())
+ def->m_has_been_superceded = true;
+
+ if (!change->is_deletion ())
+ {
+ // Remove any notes that are no longer relevant.
+ update_notes (change->rtl ());
+
+ // Make sure that the placement of this instruction would still
+ // leave room for previous instructions.
+ change->move_range = move_later_than (change->move_range, min_insn);
+ if (!canonicalize_move_range (change->move_range, change->insn ()))
+ // verify_insn_changes is supposed to make sure that this holds.
+ gcc_unreachable ();
+ min_insn = later_insn (min_insn, change->move_range.first);
+ }
+ }
+
+ // Walk backwards through the changes, allocating specific positions
+ // to each one. Update the underlying RTL and its associated DF
+ // information.
+ insn_info *following_insn = nullptr;
+ auto_vec<insn_info *, 16> placeholders;
+ placeholders.safe_grow_cleared (changes.size ());
+ for (unsigned int i = changes.size (); i-- > 0;)
+ {
+ insn_change &change = *changes[i];
+ insn_info *placeholder = nullptr;
+ possibly_queue_changes (change);
+ if (change.is_deletion ())
+ delete_insn (change);
+ else
+ {
+ // Make sure that this instruction comes before later ones.
+ if (following_insn)
+ {
+ change.move_range = move_earlier_than (change.move_range,
+ following_insn);
+ if (!canonicalize_move_range (change.move_range,
+ change.insn ()))
+ // verify_insn_changes is supposed to make sure that this
+ // holds.
+ gcc_unreachable ();
+ }
+
+ // Decide which instruction INSN should go after.
+ insn_info *after = choose_insn_placement (change);
+
+ // If INSN is moving, insert a placeholder insn_info at the
+ // new location. We can't move INSN itself yet because it
+ // might still be referenced by earlier move ranges.
+ insn_info *insn = change.insn ();
+ if (after == insn || after == insn->prev_nondebug_insn ())
+ {
+ update_insn_in_place (change);
+ following_insn = insn;
+ }
+ else
+ {
+ move_insn (change, after);
+ placeholder = add_placeholder_after (after);
+ following_insn = placeholder;
+ }
+
+ // Finalize the new list of accesses for the change. Don't install
+ // them yet, so that we still have access to the old lists below.
+ finalize_new_accesses (change);
+ }
+ placeholders[i] = placeholder;
+ }
+
+ // Remove all definitions that are no longer needed. After the above,
+ // such definitions should no longer have any registered users.
+ //
+ // In particular, this means that consumers must handle debug
+ // instructions before removing a set.
+ for (insn_change *change : changes)
+ for (def_info *def : change->old_defs ())
+ if (def->m_has_been_superceded)
+ {
+ auto *set = dyn_cast<set_info *> (def);
+ gcc_assert (!set || !set->has_any_uses ());
+ remove_def (def);
+ }
+
+ // Move the insn_infos to their new locations.
+ for (unsigned int i = 0; i < changes.size (); ++i)
+ {
+ insn_change &change = *changes[i];
+ insn_info *insn = change.insn ();
+ if (change.is_deletion ())
+ remove_insn (insn);
+ else if (insn_info *placeholder = placeholders[i])
+ {
+ // Check if earlier movements turned a move into a no-op.
+ if (placeholder->prev_nondebug_insn () == insn
+ || placeholder->next_nondebug_insn () == insn)
+ {
+ remove_insn (placeholder);
+ placeholders[i] = nullptr;
+ }
+ else
+ {
+ // Remove the placeholder first so that we have a wider range of
+ // program points when inserting INSN.
+ insn_info *after = placeholder->prev_any_insn ();
+ remove_insn (insn);
+ remove_insn (placeholder);
+ insn->set_bb (after->bb ());
+ add_insn_after (insn, after);
+ }
+ }
+ }
+
+ // Finally apply the changes to the underlying insn_infos.
+ for (insn_change *change : changes)
+ apply_changes_to_insn (*change);
+}
+
+// See the comment above the declaration.
+void
+function_info::change_insn (insn_change &change)
+{
+ insn_change *changes[] = { &change };
+ return change_insns (changes);
+}
+
+// Try to adjust CHANGE so that its pattern can include clobber rtx CLOBBER.
+// Return true on success.
+//
+// ADD_REGNO_CLOBBER is a specialization of function_info::add_regno_clobber
+// for a specific caller-provided predicate.
+static bool
+add_clobber (insn_change &change, add_regno_clobber_fn add_regno_clobber,
+ rtx clobber)
+{
+ rtx pat = PATTERN (change.rtl ());
+ gcc_assert (GET_CODE (clobber) == CLOBBER);
+ rtx dest = XEXP (clobber, 0);
+ if (GET_CODE (dest) == SCRATCH)
+ {
+ if (reload_completed)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ // ??? Maybe we could try to do some RA here?
+ fprintf (dump_file, "instruction requires a scratch"
+ " after reload:\n");
+ print_rtl_single (dump_file, pat);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ gcc_assert (REG_P (dest));
+ for (unsigned int regno = REGNO (dest); regno != END_REGNO (dest); ++regno)
+ if (!add_regno_clobber (change, regno))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "cannot clobber live register %d in:\n",
+ regno);
+ print_rtl_single (dump_file, pat);
+ }
+ return false;
+ }
+ return true;
+}
+
+// Try to recognize the new form of the insn associated with CHANGE,
+// adding any clobbers that are necessary to make the instruction match
+// an .md pattern. Return true on success.
+//
+// ADD_REGNO_CLOBBER is a specialization of function_info::add_regno_clobber
+// for a specific caller-provided predicate.
+static bool
+recog_level2 (insn_change &change, add_regno_clobber_fn add_regno_clobber)
+{
+ insn_change_watermark insn_watermark;
+ rtx_insn *rtl = change.rtl ();
+ rtx pat = PATTERN (rtl);
+ int num_clobbers = 0;
+ int icode = -1;
+ bool asm_p = asm_noperands (pat) >= 0;
+ if (asm_p)
+ {
+ if (!check_asm_operands (pat))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "failed to match this asm instruction:\n");
+ print_rtl_single (dump_file, pat);
+ }
+ return false;
+ }
+ }
+ else if (noop_move_p (rtl))
+ {
+ INSN_CODE (rtl) = NOOP_MOVE_INSN_CODE;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "instruction becomes a no-op:\n");
+ print_rtl_single (dump_file, pat);
+ }
+ insn_watermark.keep ();
+ return true;
+ }
+ else
+ {
+ icode = ::recog (pat, rtl, &num_clobbers);
+ if (icode < 0)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "failed to match this instruction:\n");
+ print_rtl_single (dump_file, pat);
+ }
+ return false;
+ }
+ }
+
+ auto prev_new_defs = change.new_defs;
+ auto prev_move_range = change.move_range;
+ if (num_clobbers > 0)
+ {
+ // ??? It would be good to have a way of recycling the rtxes on failure,
+ // but any attempt to cache old PARALLELs would at best be a half
+ // measure, since add_clobbers would still generate fresh clobbers
+ // each time. It would be better to have a more general recycling
+ // mechanism that all rtx passes can use.
+ rtvec newvec;
+ int oldlen;
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ oldlen = XVECLEN (pat, 0);
+ newvec = rtvec_alloc (num_clobbers + oldlen);
+ for (int i = 0; i < oldlen; ++i)
+ RTVEC_ELT (newvec, i) = XVECEXP (pat, 0, i);
+ }
+ else
+ {
+ oldlen = 1;
+ newvec = rtvec_alloc (num_clobbers + oldlen);
+ RTVEC_ELT (newvec, 0) = pat;
+ }
+ rtx newpat = gen_rtx_PARALLEL (VOIDmode, newvec);
+ add_clobbers (newpat, icode);
+ validate_change (rtl, &PATTERN (rtl), newpat, true);
+ for (int i = 0; i < num_clobbers; ++i)
+ if (!add_clobber (change, add_regno_clobber,
+ XVECEXP (newpat, 0, oldlen + i)))
+ {
+ change.new_defs = prev_new_defs;
+ change.move_range = prev_move_range;
+ return false;
+ }
+
+ pat = newpat;
+ }
+
+ INSN_CODE (rtl) = icode;
+ if (reload_completed)
+ {
+ extract_insn (rtl);
+ if (!constrain_operands (1, get_preferred_alternatives (rtl)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ if (asm_p)
+ fprintf (dump_file, "asm does not match its constraints:\n");
+ else if (const char *name = get_insn_name (icode))
+ fprintf (dump_file, "instruction does not match the"
+ " constraints for %s:\n", name);
+ else
+ fprintf (dump_file, "instruction does not match its"
+ " constraints:\n");
+ print_rtl_single (dump_file, pat);
+ }
+ change.new_defs = prev_new_defs;
+ change.move_range = prev_move_range;
+ return false;
+ }
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ const char *name;
+ if (!asm_p && (name = get_insn_name (icode)))
+ fprintf (dump_file, "successfully matched this instruction "
+ "to %s:\n", name);
+ else
+ fprintf (dump_file, "successfully matched this instruction:\n");
+ print_rtl_single (dump_file, pat);
+ }
+
+ insn_watermark.keep ();
+ return true;
+}
+
+// Try to recognize the new form of the insn associated with CHANGE,
+// adding and removing clobbers as necessary to make the instruction
+// match an .md pattern. Return true on success, otherwise leave
+// CHANGE as it was on entry.
+//
+// ADD_REGNO_CLOBBER is a specialization of function_info::add_regno_clobber
+// for a specific caller-provided predicate.
+bool
+rtl_ssa::recog_internal (insn_change &change,
+ add_regno_clobber_fn add_regno_clobber)
+{
+ // Accept all changes to debug instructions.
+ insn_info *insn = change.insn ();
+ if (insn->is_debug_insn ())
+ return true;
+
+ rtx_insn *rtl = insn->rtl ();
+ rtx pat = PATTERN (rtl);
+ if (GET_CODE (pat) == PARALLEL && asm_noperands (pat) < 0)
+ {
+ // Try to remove trailing (clobber (scratch)) rtxes, since the new form
+ // of the instruction might not need those scratches. recog will add
+ // back any that are needed.
+ int len = XVECLEN (pat, 0);
+ int new_len = len;
+ while (new_len > 0
+ && GET_CODE (XVECEXP (pat, 0, new_len - 1)) == CLOBBER
+ && GET_CODE (XEXP (XVECEXP (pat, 0, new_len - 1), 0)) == SCRATCH)
+ new_len -= 1;
+
+ int old_num_changes = num_validated_changes ();
+ validate_change_xveclen (rtl, &PATTERN (rtl), new_len, true);
+ if (recog_level2 (change, add_regno_clobber))
+ return true;
+ cancel_changes (old_num_changes);
+
+ // Try to remove all trailing clobbers. For example, a pattern that
+ // used to clobber the flags might no longer need to do so.
+ int prev_len = new_len;
+ while (new_len > 0
+ && GET_CODE (XVECEXP (pat, 0, new_len - 1)) == CLOBBER)
+ new_len -= 1;
+ if (new_len != prev_len)
+ {
+ validate_change_xveclen (rtl, &PATTERN (rtl), new_len, true);
+ if (recog_level2 (change, add_regno_clobber))
+ return true;
+ cancel_changes (old_num_changes);
+ }
+ return false;
+ }
+
+ return recog_level2 (change, add_regno_clobber);
+}
+
+// See the comment above the declaration.
+bool
+function_info::perform_pending_updates ()
+{
+ bool changed_cfg = false;
+ bool changed_jumps = false;
+ for (insn_info *insn : m_queued_insn_updates)
+ {
+ rtx_insn *rtl = insn->rtl ();
+ if (JUMP_P (rtl))
+ {
+ if (INSN_CODE (rtl) == NOOP_MOVE_INSN_CODE)
+ {
+ ::delete_insn (rtl);
+ bitmap_set_bit (m_need_to_purge_dead_edges,
+ insn->bb ()->index ());
+ }
+ else if (returnjump_p (rtl) || any_uncondjump_p (rtl))
+ {
+ mark_jump_label (PATTERN (rtl), rtl, 0);
+ update_cfg_for_uncondjump (rtl);
+ changed_cfg = true;
+ changed_jumps = true;
+ }
+ }
+ else if (INSN_CODE (rtl) == NOOP_MOVE_INSN_CODE)
+ ::delete_insn (rtl);
+ else
+ {
+ rtx pattern = PATTERN (rtl);
+ if (GET_CODE (pattern) == TRAP_IF
+ && XEXP (pattern, 0) == const1_rtx)
+ {
+ remove_edge (split_block (BLOCK_FOR_INSN (rtl), rtl));
+ emit_barrier_after_bb (BLOCK_FOR_INSN (rtl));
+ changed_cfg = true;
+ }
+ }
+ }
+
+ unsigned int index;
+ bitmap_iterator bi;
+ EXECUTE_IF_SET_IN_BITMAP (m_need_to_purge_dead_edges, 0, index, bi)
+ if (purge_dead_edges (BASIC_BLOCK_FOR_FN (m_fn, index)))
+ changed_cfg = true;
+
+ if (changed_jumps)
+ // This uses its own timevar internally, so we don't need to push
+ // one ourselves.
+ rebuild_jump_labels (get_insns ());
+
+ bitmap_clear (m_need_to_purge_dead_edges);
+ bitmap_clear (m_queued_insn_update_uids);
+ m_queued_insn_updates.truncate (0);
+
+ if (changed_cfg)
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ }
+
+ return changed_cfg;
+}
+
+// Print a description of CHANGE to PP.
+void
+rtl_ssa::pp_insn_change (pretty_printer *pp, const insn_change &change)
+{
+ change.print (pp);
+}
+
+// Print a description of CHANGE to FILE.
+void
+dump (FILE *file, const insn_change &change)
+{
+ dump_using (file, pp_insn_change, change);
+}
+
+// Debug interface to the dump routine above.
+void debug (const insn_change &x) { dump (stderr, x); }
diff --git a/gcc/rtl-ssa/changes.h b/gcc/rtl-ssa/changes.h
new file mode 100644
index 0000000..308c5ed
--- /dev/null
+++ b/gcc/rtl-ssa/changes.h
@@ -0,0 +1,118 @@
+// RTL SSA classes related to changing instructions -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// A class that describes a change that we're considering making to an
+// instruction. There are three choices:
+//
+// (1) delete the instruction
+// (2) replace the instruction with a new instruction in-place
+// (3) replace the instruction with a new instruction at a different location
+//
+// Anything related to the "new instruction" is irrelevant for (1).
+//
+// The class doesn't actually change anything itself, it simply records
+// something that we might do.
+class insn_change
+{
+public:
+ enum delete_action { DELETE };
+
+ // Construct a possible change to INSN.
+ insn_change (insn_info *insn);
+
+ // Construct a possible deletion of INSN.
+ insn_change (insn_info *insn, delete_action);
+
+ // The instruction that we would change.
+ insn_info *insn () const { return m_insn; }
+
+ // The rtx_insn of the instruction that we would change.
+ rtx_insn *rtl () const { return m_insn->rtl (); }
+
+ // The basic block that contains insn ().
+ bb_info *bb () const { return m_insn->bb (); }
+
+ // The extended basic block that contains insn ().
+ ebb_info *ebb () const { return m_insn->ebb (); }
+
+ // The uid of the instruction that we would change.
+ unsigned int insn_uid () const { return m_insn->uid (); }
+
+ // The list of things that the original instruction defined and used.
+ def_array old_defs () const { return m_insn->defs (); }
+ use_array old_uses () const { return m_insn->uses (); }
+
+ // The cost of the original instruction, as calculated by the target.
+ unsigned int old_cost () const { return m_insn->cost (); }
+
+ // Return true if the original instruction would simply be deleted,
+ // rather than being replaced by a new instruction.
+ bool is_deletion () const { return m_is_deletion; }
+
+ // Print a description of the change to PP.
+ void print (pretty_printer *pp) const;
+
+ // Return an insn_change for deleting INSN.
+ static insn_change delete_insn (insn_info *insn) { return { insn, DELETE }; }
+
+private:
+ // The value returned by insn ().
+ insn_info *m_insn;
+
+public:
+ // The list of things that the new instruction would define and use.
+ def_array new_defs;
+ use_array new_uses;
+
+ // The range of instructions after which the instruction could be placed.
+ // The range can include INSN itself: placing the instruction after either
+ // INSN or INSN->prev_nondebug_insn () is equivalent to not moving the
+ // instruction.
+ insn_range_info move_range;
+
+ // The cost that the new instruction would have, as calculated by the target.
+ unsigned int new_cost;
+
+private:
+ // The value returned by is_deletion ().
+ bool m_is_deletion;
+};
+
+// A class that represents a closure of the two-argument form of
+// insn_is_changing. See the comment above the one-argument form
+// for details.
+class insn_is_changing_closure
+{
+public:
+ insn_is_changing_closure (array_slice<insn_change *const> changes);
+ bool operator() (const insn_info *) const;
+
+private:
+ array_slice<insn_change *const> m_changes;
+};
+
+void pp_insn_change (pretty_printer *, const insn_change &);
+
+}
+
+void dump (FILE *, const rtl_ssa::insn_change &);
+
+void DEBUG_FUNCTION debug (const rtl_ssa::insn_change &);
diff --git a/gcc/rtl-ssa/functions.cc b/gcc/rtl-ssa/functions.cc
new file mode 100644
index 0000000..50595ac
--- /dev/null
+++ b/gcc/rtl-ssa/functions.cc
@@ -0,0 +1,325 @@
+// Implementation of function-related RTL SSA functions -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+#include "rtl-ssa/internals.inl"
+
+using namespace rtl_ssa;
+
+function_info::function_info (function *fn)
+ : m_fn (fn)
+{
+ // Force the alignment to be obstack_alignment. Everything else is normal.
+ obstack_specify_allocation (&m_obstack, OBSTACK_CHUNK_SIZE,
+ obstack_alignment, obstack_chunk_alloc,
+ obstack_chunk_free);
+ obstack_specify_allocation (&m_temp_obstack, OBSTACK_CHUNK_SIZE,
+ obstack_alignment, obstack_chunk_alloc,
+ obstack_chunk_free);
+
+ // Record the start of the obstacks.
+ m_obstack_start = XOBNEWVAR (&m_obstack, char, 0);
+ m_temp_obstack_start = XOBNEWVAR (&m_temp_obstack, char, 0);
+
+ init_function_data ();
+ process_all_blocks ();
+ simplify_phis ();
+}
+
+function_info::~function_info ()
+{
+ // Anything using the temporary obstack should free it afterwards,
+ // preferably via temp_watermark ().
+ gcc_assert (XOBNEWVAR (&m_temp_obstack, char, 0) == m_temp_obstack_start);
+
+ obstack_free (&m_temp_obstack, nullptr);
+ obstack_free (&m_obstack, nullptr);
+}
+
+// See the comment above the declaration.
+void
+function_info::print (pretty_printer *pp) const
+{
+ pp_string (pp, "Function: ");
+ pp_string (pp, function_name (m_fn));
+ for (ebb_info *ebb : ebbs ())
+ {
+ pp_newline (pp);
+ pp_newline_and_indent (pp, 0);
+ pp_ebb (pp, ebb);
+ }
+}
+
+// Calculate m_potential_phi_regs.
+void
+function_info::calculate_potential_phi_regs ()
+{
+ auto *lr_info = DF_LR_BB_INFO (ENTRY_BLOCK_PTR_FOR_FN (m_fn));
+ for (unsigned int regno = 0; regno < m_num_regs; ++regno)
+ if (regno >= DF_REG_SIZE (DF)
+ // Exclude registers that have a single definition that dominates
+ // all uses. If the definition does not dominate all uses,
+ // the register will be exposed upwards to the entry block but
+ // will not be defined by the entry block.
+ || DF_REG_DEF_COUNT (regno) > 1
+ || (!bitmap_bit_p (&lr_info->def, regno)
+ && bitmap_bit_p (&lr_info->out, regno)))
+ bitmap_set_bit (m_potential_phi_regs, regno);
+}
+
+// Initialize all member variables in preparation for (re)building
+// SSA form from scratch.
+void
+function_info::init_function_data ()
+{
+ m_next_artificial_uid = -1;
+ m_next_phi_uid = 0;
+ m_num_regs = max_reg_num ();
+ m_defs.safe_grow_cleared (m_num_regs + 1);
+ m_bbs.safe_grow_cleared (last_basic_block_for_fn (m_fn));
+ m_first_bb = nullptr;
+ m_last_bb = nullptr;
+ m_first_insn = nullptr;
+ m_last_insn = nullptr;
+ m_last_nondebug_insn = nullptr;
+ m_free_phis = nullptr;
+
+ calculate_potential_phi_regs ();
+}
+
+// The initial phase of the phi simplification process. The cumulative
+// effect of the initial phase is to set up ASSUMED_VALUES such that,
+// for a phi P with uid ID:
+//
+// - if we think all inputs to P have the same value, ASSUMED_VALUES[ID]
+// is that value
+//
+// - otherwise, ASSUMED_VALUES[ID] is P.
+//
+// This has already been done for phis with a lower uid than PHI,
+// initially making optimistic assumptions about backedge inputs.
+// Now do the same for PHI. If this might invalidate any assumptions
+// made for earlier phis, add the uids of those phis to WORKLIST.
+void
+function_info::simplify_phi_setup (phi_info *phi, set_info **assumed_values,
+ bitmap worklist)
+{
+ // If all non-backedge inputs have the same value, set NEW_VALUE
+ // to that value. Otherwise set NEW_VALUE to PHI, to indicate
+ // that PHI cannot be simplified.
+ unsigned int phi_uid = phi->uid ();
+ bool is_first_input = true;
+ set_info *new_value = nullptr;
+ machine_mode phi_mode = phi->mode ();
+ for (use_info *input : phi->inputs ())
+ {
+ set_info *def = input->def ();
+
+ if (auto *input_phi = safe_dyn_cast<phi_info *> (def))
+ {
+ // Ignore backedges for now.
+ unsigned int input_phi_uid = input_phi->uid ();
+ if (phi_uid <= input_phi_uid)
+ continue;
+
+ def = assumed_values[input_phi_uid];
+ }
+
+ // Compare this definition with previous ones.
+ if (is_first_input)
+ {
+ new_value = def;
+ is_first_input = false;
+ }
+ else if (new_value != def)
+ new_value = phi;
+
+ // If the input has a known mode (i.e. not BLKmode), make sure
+ // that the phi's mode is at least as large.
+ if (def)
+ phi_mode = combine_modes (phi_mode, def->mode ());
+ }
+ if (phi->mode () != phi_mode)
+ phi->set_mode (phi_mode);
+
+ // Since we use a reverse postorder traversal, no phi can consist
+ // entirely of backedges.
+ gcc_checking_assert (!is_first_input);
+ assumed_values[phi_uid] = new_value;
+
+ // See whether any assumptions for earlier phis are now invalid.
+ simplify_phi_propagate (phi, assumed_values, nullptr, worklist);
+}
+
+// The propagation phase of the phi simplification process, with
+// ASSUMED_VALUES as described above simplify_phi_setup. Iteratively
+// update the phis that use PHI based on PHI's entry in ASSUMED_VALUES.
+// If CURR_WORKLIST is null, consider only phi uses with a lower uid
+// than PHI, otherwise consider all phi uses.
+//
+// If a phi with a higher uid than PHI needs updating, add its uid to
+// CURR_WORKLIST; if a phi with a lower uid than PHI needs updating,
+// add its uid to NEXT_WORKLIST.
+void
+function_info::simplify_phi_propagate (phi_info *phi,
+ set_info **assumed_values,
+ bitmap curr_worklist,
+ bitmap next_worklist)
+{
+ // Go through each phi user of PHI to see whether it needs updating.
+ unsigned int phi_uid = phi->uid ();
+ machine_mode phi_mode = phi->mode ();
+ set_info *phi_value = assumed_values[phi_uid];
+ for (use_info *use : phi->phi_uses ())
+ {
+ phi_info *user_phi = use->phi ();
+
+ // Propagate the phi's new mode to all phi users. Insn uses should
+ // not be updated, since their modes reflect a property of the insns
+ // rather than the phi.
+ if (use->mode () != phi_mode)
+ use->set_mode (phi_mode);
+
+ if (user_phi == phi)
+ continue;
+
+ // If this is a phi we should be looking at, see whether it needs
+ // an update.
+ unsigned int user_phi_uid = user_phi->uid ();
+ if (user_phi_uid < phi_uid || curr_worklist)
+ {
+ bool needs_update = false;
+
+ // Make sure that USER_PHI's mode is at least as big as PHI_MODE.
+ machine_mode user_phi_mode = user_phi->mode ();
+ machine_mode new_mode = combine_modes (user_phi_mode, phi_mode);
+ if (user_phi_mode != new_mode)
+ {
+ user_phi->set_mode (new_mode);
+ needs_update = true;
+ }
+
+ // If USER_PHI optimistically assumed an incorrect value,
+ // adjust it now.
+ if (assumed_values[user_phi_uid] != user_phi
+ && assumed_values[user_phi_uid] != phi_value)
+ {
+ assumed_values[user_phi_uid] = user_phi;
+ needs_update = true;
+ }
+
+ if (needs_update)
+ {
+ if (user_phi_uid < phi_uid)
+ bitmap_set_bit (next_worklist, user_phi_uid);
+ else
+ bitmap_set_bit (curr_worklist, user_phi_uid);
+ }
+ }
+ }
+}
+
+// Update the modes of all phis so that they are at least as big as
+// all inputs. Remove any non-degenerate phis whose inputs are all equal.
+void
+function_info::simplify_phis ()
+{
+ auto temps = temp_watermark ();
+
+ // See the comment above simplify_phi_setup for details about this array.
+ auto *assumed_values = XOBNEWVEC (&m_temp_obstack, set_info *,
+ m_next_phi_uid);
+
+ // An array of all phis, indexed by uid.
+ auto *phis = XOBNEWVEC (&m_temp_obstack, phi_info *, m_next_phi_uid);
+
+ // Which phi uids are actually in use.
+ auto_sbitmap valid_phi_uids (m_next_phi_uid);
+ bitmap_clear (valid_phi_uids);
+
+ // Bitmaps used for the main double-queue propagation phase.
+ auto_bitmap worklist1;
+ auto_bitmap worklist2;
+ bitmap curr_worklist = worklist1;
+ bitmap next_worklist = worklist2;
+
+ // Perform the set-up phase; see simplify_phi_setup for details.
+ for (ebb_info *ebb : ebbs ())
+ for (phi_info *phi : ebb->phis ())
+ {
+ bitmap_set_bit (valid_phi_uids, phi->uid ());
+ phis[phi->uid ()] = phi;
+ simplify_phi_setup (phi, assumed_values, curr_worklist);
+ }
+
+ // Iteratively process any phis that need updating; see
+ // simplify_phi_propagate for details. Using a double queue
+ // should reduce the number of times that any given phi node
+ // needs to be revisited.
+ while (!bitmap_empty_p (curr_worklist))
+ {
+ do
+ {
+ unsigned int uid = bitmap_first_set_bit (curr_worklist);
+ bitmap_clear_bit (curr_worklist, uid);
+ simplify_phi_propagate (phis[uid], assumed_values,
+ curr_worklist, next_worklist);
+ }
+ while (!bitmap_empty_p (curr_worklist));
+ std::swap (next_worklist, curr_worklist);
+ }
+
+ // Make sure that assumed_values is a transitive closure. This ensures
+ // that each use_info is only updated once.
+ if (flag_checking)
+ for (unsigned int i = 0; i < m_next_phi_uid; ++i)
+ if (bitmap_bit_p (valid_phi_uids, i))
+ if (auto *new_phi = safe_dyn_cast<phi_info *> (assumed_values[i]))
+ gcc_assert (assumed_values[new_phi->uid ()] == new_phi);
+
+ // Update any phis that turned out to be equivalent to a single input.
+ for (unsigned int i = 0; i < m_next_phi_uid; ++i)
+ if (bitmap_bit_p (valid_phi_uids, i) && phis[i] != assumed_values[i])
+ replace_phi (phis[i], assumed_values[i]);
+}
+
+// Print a description of FUNCTION to PP.
+void
+rtl_ssa::pp_function (pretty_printer *pp, const function_info *function)
+{
+ function->print (pp);
+}
+
+// Print a description of FUNCTION to FILE.
+void
+dump (FILE *file, const function_info *function)
+{
+ dump_using (file, pp_function, function);
+}
+
+// Debug interface to the dump routine above.
+void debug (const function_info *x) { dump (stderr, x); }
diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h
new file mode 100644
index 0000000..b09d50e
--- /dev/null
+++ b/gcc/rtl-ssa/functions.h
@@ -0,0 +1,433 @@
+// Function-related RTL SSA classes -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// SSA-related information about a function. It contains three levels
+// of information, each in reverse postorder:
+//
+// - a list of extended basic blocks
+// - a list of basic blocks
+// - a list of instructions
+//
+// It also maintains a list of definitions of memory, and a list of
+// definitions of each register.
+//
+// See doc/rtl.texi for more details about the way this information
+// is organized and how changes to it are made.
+class function_info
+{
+ // The default obstack alignment takes long double into account.
+ // Since we have no use for that here, and since we allocate many
+ // relatively small objects, it's better to specify an alignment
+ // explicitly. The allocation routines assert that the alignment
+ // is enough for the objects being allocated.
+ //
+ // Because various structures use pointer_mux, we need at least 2 bytes
+ // of alignment.
+ static const size_t obstack_alignment = sizeof (void *);
+
+public:
+ // Construct SSA form for function FN.
+ function_info (function *fn);
+ ~function_info ();
+
+ // Return a list of all the extended basic blocks in the function, in reverse
+ // postorder. The list includes the entry and exit blocks.
+ iterator_range<ebb_iterator> ebbs () const;
+
+ // Like ebbs (), but in the reverse order.
+ iterator_range<reverse_ebb_iterator> reverse_ebbs () const;
+
+ // Return a list of all the basic blocks in the function, in reverse
+ // postorder. The list includes the entry and exit blocks.
+ iterator_range<bb_iterator> bbs () const;
+
+ // Like bbs (), but in the reverse order.
+ iterator_range<reverse_bb_iterator> reverse_bbs () const;
+
+ // Return the SSA information for the basic block with index INDEX.
+ bb_info *bb (unsigned int index) const { return m_bbs[index]; }
+
+ // Return the SSA information for CFG_BB.
+ bb_info *bb (basic_block cfg_bb) const { return m_bbs[cfg_bb->index]; }
+
+ // Return a list of all the instructions in the function, in reverse
+ // postorder. The list includes both real and artificial instructions.
+ //
+ // Iterations over the list will pick up any new instructions that are
+ // inserted after the iterator's current instruction.
+ iterator_range<any_insn_iterator> all_insns () const;
+
+ // Like all_insns (), but in the reverse order.
+ //
+ // Iterations over the list will pick up any new instructions that are
+ // inserted before the iterator's current instruction.
+ iterator_range<reverse_any_insn_iterator> reverse_all_insns () const;
+
+ // Like all_insns (), but without the debug instructions.
+ iterator_range<nondebug_insn_iterator> nondebug_insns () const;
+
+ // Like reverse_all_insns (), but without the debug instructions.
+ iterator_range<reverse_nondebug_insn_iterator>
+ reverse_nondebug_insns () const;
+
+ // Return the first and last instructions in insns ().
+ insn_info *first_insn () const { return m_first_insn; }
+ insn_info *last_insn () const { return m_last_insn; }
+
+ // Return a list of all definitions of memory, in reverse postorder.
+ // This includes both real stores by instructions and artificial
+ // definitions by things like phi nodes.
+ iterator_range<def_iterator> mem_defs () const;
+
+ // Return a list of all definitions of register REGNO, in reverse postorder.
+ // This includes both real stores by instructions and artificial
+ // definitions by things like phi nodes.
+ iterator_range<def_iterator> ref_defs (unsigned int regno) const;
+
+ // Check if all uses of register REGNO are either unconditionally undefined
+ // or use the same single dominating definition. Return the definition
+ // if so, otherwise return null.
+ set_info *single_dominating_def (unsigned int regno) const;
+
+ // Look for a definition of RESOURCE at INSN. Return the result of the
+ // search as a def_lookup; see the comments there for more details.
+ def_lookup find_def (resource_info resource, insn_info *insn);
+
+ // Return an RAII object that owns all temporary RTL SSA memory
+ // allocated during a change attempt. The object should remain in
+ // scope until the change has been aborted or successfully completed.
+ obstack_watermark new_change_attempt () { return &m_temp_obstack; }
+
+ // Make a best attempt to check whether the values used by USES are
+ // available on entry to BB, without solving a full dataflow problem.
+ // If all the values are already live on entry to BB or can be made
+ // available there, return a use_array that describes the uses as
+ // if they occured at the start of BB. These uses are purely temporary,
+ // and will not become permanent unless applied using change_insns.
+ //
+ // If the operation fails, return an invalid use_array.
+ //
+ // WATERMARK is a watermark returned by new_change_attempt ().
+ use_array make_uses_available (obstack_watermark &watermark,
+ use_array uses, bb_info *bb);
+
+ // If CHANGE doesn't already clobber REGNO, try to add such a clobber,
+ // limiting the movement range in order to make the clobber valid.
+ // When determining whether REGNO is live, ignore accesses made by an
+ // instruction I if IGNORE (I) is true. The caller then assumes the
+ // responsibility of ensuring that CHANGE and I are placed in a valid order.
+ //
+ // Return true on success. Leave CHANGE unmodified when returning false.
+ //
+ // WATERMARK is a watermark returned by new_change_attempt ().
+ template<typename IgnorePredicate>
+ bool add_regno_clobber (obstack_watermark &watermark, insn_change &change,
+ unsigned int regno, IgnorePredicate ignore);
+
+ // Return true if change_insns will be able to perform the changes
+ // described by CHANGES.
+ bool verify_insn_changes (array_slice<insn_change *const> changes);
+
+ // Perform all the changes in CHANGES, keeping the instructions in the
+ // order specified by the CHANGES array. On return, the SSA information
+ // remains up-to-date. The same is true for instruction-level DF
+ // information, although the block-level DF information might be
+ // marked dirty.
+ void change_insns (array_slice<insn_change *> changes);
+
+ // Like change_insns, but for a single change CHANGE.
+ void change_insn (insn_change &change);
+
+ // If the changes that have been made to instructions require updates
+ // to the CFG, perform those updates now. Return true if something changed.
+ // If it did:
+ //
+ // - The SSA information is now invalid and needs to be recomputed.
+ //
+ // - Dominance information is no longer available (in either direction).
+ //
+ // - The caller will need to call cleanup_cfg at some point.
+ //
+ // ??? We could probably update the SSA information for simple updates,
+ // but currently nothing would benefit. These late CFG changes are
+ // relatively rare anyway, since gimple optimisers should remove most
+ // unnecessary control flow.
+ bool perform_pending_updates ();
+
+ // Print the contents of the function to PP.
+ void print (pretty_printer *pp) const;
+
+private:
+ // Information about the values that are live on exit from a basic block.
+ // This class is only used when constructing the SSA form, it isn't
+ // designed for being kept up-to-date.
+ class bb_live_out_info
+ {
+ public:
+ // REG_VALUES contains all the registers that live out from the block,
+ // in order of increasing register number. There are NUM_REG_VALUES
+ // in total. Registers do not appear here if their values are known
+ // to be completely undefined; in that sense, the information is
+ // closer to DF_LIVE than to DF_LR.
+ unsigned int num_reg_values;
+ set_info **reg_values;
+
+ // The memory value that is live on exit from the block.
+ set_info *mem_value;
+ };
+
+ // Information used while constructing the SSA form and discarded
+ // afterwards.
+ class build_info
+ {
+ public:
+ set_info *current_reg_value (unsigned int) const;
+ set_info *current_mem_value () const;
+
+ void record_reg_def (unsigned int, def_info *);
+ void record_mem_def (def_info *);
+
+ // The block that we're currently processing.
+ bb_info *current_bb;
+
+ // The EBB that contains CURRENT_BB.
+ ebb_info *current_ebb;
+
+ // Except for the local exception noted below:
+ //
+ // - If register R has been defined in the current EBB, LAST_ACCESS[R + 1]
+ // is the last definition of R in the EBB.
+ //
+ // - If register R is currently live but has not yet been defined
+ // in the EBB, LAST_ACCESS[R + 1] is the current value of R,
+ // or null if the register's value is completely undefined.
+ //
+ // - The contents are not meaningful for other registers.
+ //
+ // Similarly:
+ //
+ // - If the current EBB has defined memory, LAST_ACCESS[0] is the last
+ // definition of memory in the EBB.
+ //
+ // - Otherwise LAST_ACCESS[0] is the value of memory that is live on
+ // - entry to the EBB.
+ //
+ // The exception is that while building instructions, LAST_ACCESS[I]
+ // can temporarily be the use of regno I - 1 by that instruction.
+ access_info **last_access;
+
+ // A bitmap of registers that are live on entry to this EBB, with a tree
+ // view for quick lookup. Only used if MAY_HAVE_DEBUG_INSNS.
+ bitmap ebb_live_in_for_debug;
+
+ // A conservative superset of the registers that are used by
+ // instructions in CURRENT_EBB. That is, all used registers
+ // are in the set, but some unused registers might be too.
+ bitmap ebb_use;
+
+ // A similarly conservative superset of the registers that are defined
+ // by instructions in CURRENT_EBB.
+ bitmap ebb_def;
+
+ // BB_LIVE_OUT[BI] gives the live-out values for the basic block
+ // with index BI.
+ bb_live_out_info *bb_live_out;
+ };
+
+ // Return an RAII object that owns all objects allocated by
+ // allocate_temp during its lifetime.
+ obstack_watermark temp_watermark () { return &m_temp_obstack; }
+
+ template<typename T, typename... Ts>
+ T *allocate (Ts... args);
+
+ template<typename T, typename... Ts>
+ T *allocate_temp (Ts... args);
+
+ access_array temp_access_array (access_array accesses);
+
+ clobber_group *need_clobber_group (clobber_info *);
+ def_node *need_def_node (def_info *);
+ def_splay_tree need_def_splay_tree (def_info *);
+
+ use_info *make_use_available (use_info *, bb_info *);
+ def_array insert_temp_clobber (obstack_watermark &, insn_info *,
+ unsigned int, def_array);
+
+ void insert_def_before (def_info *, def_info *);
+ void insert_def_after (def_info *, def_info *);
+ void remove_def_from_list (def_info *);
+
+ void add_clobber (clobber_info *, clobber_group *);
+ void remove_clobber (clobber_info *, clobber_group *);
+ void prepend_clobber_to_group (clobber_info *, clobber_group *);
+ void append_clobber_to_group (clobber_info *, clobber_group *);
+ void merge_clobber_groups (clobber_info *, clobber_info *,
+ def_info *);
+ clobber_info *split_clobber_group (clobber_group *, insn_info *);
+
+ void append_def (def_info *);
+ void add_def (def_info *);
+ void remove_def (def_info *);
+
+ void need_use_splay_tree (set_info *);
+
+ static void insert_use_before (use_info *, use_info *);
+ static void insert_use_after (use_info *, use_info *);
+
+ void add_use (use_info *);
+ void remove_use (use_info *);
+
+ insn_info::order_node *need_order_node (insn_info *);
+
+ void add_insn_after (insn_info *, insn_info *);
+ void append_insn (insn_info *);
+ void remove_insn (insn_info *);
+
+ insn_info *append_artificial_insn (bb_info *, rtx_insn * = nullptr);
+
+ void start_insn_accesses ();
+ void finish_insn_accesses (insn_info *);
+
+ void record_use (build_info &, insn_info *, rtx_obj_reference);
+ void record_call_clobbers (build_info &, insn_info *, rtx_call_insn *);
+ void record_def (build_info &, insn_info *, rtx_obj_reference);
+ void add_insn_to_block (build_info &, rtx_insn *);
+
+ void add_reg_unused_notes (insn_info *);
+
+ void add_live_out_use (bb_info *, set_info *);
+ set_info *live_out_value (bb_info *, set_info *);
+
+ void append_phi (ebb_info *, phi_info *);
+ void remove_phi (phi_info *);
+ void delete_phi (phi_info *);
+ void replace_phi (phi_info *, set_info *);
+ phi_info *create_phi (ebb_info *, resource_info, access_info **,
+ unsigned int);
+ phi_info *create_degenerate_phi (ebb_info *, set_info *);
+
+ bb_info *create_bb_info (basic_block);
+ void append_bb (bb_info *);
+ void calculate_potential_phi_regs ();
+
+ insn_info *add_placeholder_after (insn_info *);
+ void possibly_queue_changes (insn_change &);
+ void finalize_new_accesses (insn_change &);
+ void apply_changes_to_insn (insn_change &);
+
+ void init_function_data ();
+ void add_entry_block_defs (build_info &);
+ void add_phi_nodes (build_info &);
+ void add_artificial_accesses (build_info &, df_ref_flags);
+ void add_block_contents (build_info &);
+ void record_block_live_out (build_info &);
+ void populate_backedge_phis (build_info &);
+ void process_all_blocks ();
+
+ void simplify_phi_setup (phi_info *, set_info **, bitmap);
+ void simplify_phi_propagate (phi_info *, set_info **, bitmap, bitmap);
+ void simplify_phis ();
+
+ // The function that this object describes.
+ function *m_fn;
+
+ // The lowest (negative) in-use artificial insn uid minus one.
+ int m_next_artificial_uid;
+
+ // The highest in-use phi uid plus one.
+ unsigned int m_next_phi_uid;
+
+ // The highest in-use register number plus one.
+ unsigned int m_num_regs;
+
+ // M_DEFS[R] is the first definition of register R - 1 in a reverse
+ // postorder traversal of the function, or null if the function has
+ // no definition of R. Applying last () gives the last definition of R.
+ //
+ // M_DEFS[0] is for memory; MEM_REGNO + 1 == 0.
+ auto_vec<def_info *> m_defs;
+
+ // M_BBS[BI] gives the SSA information about the block with index BI.
+ auto_vec<bb_info *> m_bbs;
+
+ // An obstack used to allocate the main RTL SSA information.
+ obstack m_obstack;
+
+ // An obstack used for temporary work, such as while building up a list
+ // of possible instruction changes.
+ obstack m_temp_obstack;
+
+ // The start of each obstack, so that all memory in them can be freed.
+ char *m_obstack_start;
+ char *m_temp_obstack_start;
+
+ // The entry and exit blocks.
+ bb_info *m_first_bb;
+ bb_info *m_last_bb;
+
+ // The first and last instructions in a reverse postorder traversal
+ // of the function.
+ insn_info *m_first_insn;
+ insn_info *m_last_insn;
+
+ // The last nondebug instruction in the list of instructions.
+ // This is only different from m_last_insn when building the initial
+ // SSA information; after that, the last instruction is always a
+ // BB end instruction.
+ insn_info *m_last_nondebug_insn;
+
+ // Temporary working state when building up lists of definitions and uses.
+ // Keeping them around should reduce the number of unnecessary reallocations.
+ auto_vec<access_info *> m_temp_defs;
+ auto_vec<access_info *> m_temp_uses;
+
+ // The set of registers that might need to have phis associated with them.
+ // Registers outside this set are known to have a single definition that
+ // dominates all uses.
+ //
+ // Before RA, about 5% of registers are typically in the set.
+ auto_bitmap m_potential_phi_regs;
+
+ // A list of phis that are no longer in use. Their uids are still unique
+ // and so can be recycled.
+ phi_info *m_free_phis;
+
+ // A list of instructions that have been changed in ways that need
+ // further processing later, such as removing dead instructions or
+ // altering the CFG.
+ auto_vec<insn_info *> m_queued_insn_updates;
+
+ // The INSN_UIDs of all instructions in M_QUEUED_INSN_UPDATES.
+ auto_bitmap m_queued_insn_update_uids;
+
+ // A basic_block is in this bitmap if we need to call purge_dead_edges
+ // on it. As with M_QUEUED_INSN_UPDATES, these updates are queued until
+ // a convenient point.
+ auto_bitmap m_need_to_purge_dead_edges;
+};
+
+void pp_function (pretty_printer *, const function_info *);
+}
+
+void dump (FILE *, const rtl_ssa::function_info *);
+
+void DEBUG_FUNCTION debug (const rtl_ssa::function_info *);
diff --git a/gcc/rtl-ssa/insn-utils.h b/gcc/rtl-ssa/insn-utils.h
new file mode 100644
index 0000000..d7705e9
--- /dev/null
+++ b/gcc/rtl-ssa/insn-utils.h
@@ -0,0 +1,46 @@
+// Instruction-related utilities for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// Return whichever of INSN1 and INSN2 occurs earlier in the function's
+// reverse postorder.
+inline insn_info *
+earlier_insn (insn_info *insn1, insn_info *insn2)
+{
+ return *insn1 < *insn2 ? insn1 : insn2;
+}
+
+// Return whichever of INSN1 and INSN2 occurs later in the function's
+// reverse postorder.
+inline insn_info *
+later_insn (insn_info *insn1, insn_info *insn2)
+{
+ return *insn1 < *insn2 ? insn2 : insn1;
+}
+
+// Return a closure of operator== for INSN. See insn_is_changing for
+// the rationale for defining the function this way.
+inline insn_is_closure
+insn_is (const insn_info *insn)
+{
+ return insn_is_closure (insn);
+}
+
+}
diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc
new file mode 100644
index 0000000..b8e08ff
--- /dev/null
+++ b/gcc/rtl-ssa/insns.cc
@@ -0,0 +1,718 @@
+// Implementation of instruction-related RTL SSA functions -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+#include "rtl-ssa/internals.inl"
+#include "predict.h"
+#include "print-rtl.h"
+#include "rtl-iter.h"
+
+using namespace rtl_ssa;
+
+// The gap to leave between program points when building up the list
+// of instructions for the first time. Using 2 allows an instruction
+// to be inserted between two others without resorting to splay tree
+// ordering. Using 0 is useful as a debugging aid to stress the
+// splay tree code.
+static const unsigned int POINT_INCREASE = 2;
+
+// Calculate and record the cost of the instruction, based on the
+// form it had before any in-progress changes were made.
+void
+insn_info::calculate_cost () const
+{
+ basic_block cfg_bb = BLOCK_FOR_INSN (m_rtl);
+ temporarily_undo_changes (0);
+ m_cost_or_uid = insn_cost (m_rtl, optimize_bb_for_speed_p (cfg_bb));
+ redo_changes (0);
+}
+
+// Add NOTE to the instruction's notes.
+void
+insn_info::add_note (insn_note *note)
+{
+ insn_note **ptr = &m_first_note;
+ // Always put the order node first, since it's the one that's likely
+ // to be used most often.
+ if (*ptr && (*ptr)->kind () == insn_note_kind::ORDER_NODE)
+ ptr = &(*ptr)->m_next_note;
+ note->m_next_note = *ptr;
+ *ptr = note;
+}
+
+// Implement compare_with for the case in which this insn and OTHER
+// have the same program point.
+int
+insn_info::slow_compare_with (const insn_info &other) const
+{
+ return order_splay_tree::compare_nodes (get_known_order_node (),
+ other.get_known_order_node ());
+}
+
+// Print insn uid UID to PP, where UID has the same form as insn_info::uid.
+void
+insn_info::print_uid (pretty_printer *pp, int uid)
+{
+ char tmp[3 * sizeof (uid) + 2];
+ if (uid < 0)
+ // An artificial instruction.
+ snprintf (tmp, sizeof (tmp), "a%d", -uid);
+ else
+ // A real RTL instruction.
+ snprintf (tmp, sizeof (tmp), "i%d", uid);
+ pp_string (pp, tmp);
+}
+
+// See comment above declaration.
+void
+insn_info::print_identifier (pretty_printer *pp) const
+{
+ print_uid (pp, uid ());
+}
+
+// See comment above declaration.
+void
+insn_info::print_location (pretty_printer *pp) const
+{
+ if (bb_info *bb = this->bb ())
+ {
+ ebb_info *ebb = bb->ebb ();
+ if (ebb && is_phi ())
+ ebb->print_identifier (pp);
+ else
+ bb->print_identifier (pp);
+ pp_string (pp, " at point ");
+ pp_decimal_int (pp, m_point);
+ }
+ else
+ pp_string (pp, "<unknown location>");
+}
+
+// See comment above declaration.
+void
+insn_info::print_identifier_and_location (pretty_printer *pp) const
+{
+ if (m_is_asm)
+ pp_string (pp, "asm ");
+ if (m_is_debug_insn)
+ pp_string (pp, "debug ");
+ pp_string (pp, "insn ");
+ print_identifier (pp);
+ pp_string (pp, " in ");
+ print_location (pp);
+}
+
+// See comment above declaration.
+void
+insn_info::print_full (pretty_printer *pp) const
+{
+ print_identifier_and_location (pp);
+ pp_colon (pp);
+ if (is_real ())
+ {
+ pp_newline_and_indent (pp, 2);
+ if (has_been_deleted ())
+ pp_string (pp, "deleted");
+ else
+ {
+ // Print the insn pattern to a temporary printer.
+ pretty_printer sub_pp;
+ print_insn_with_notes (&sub_pp, rtl ());
+ const char *text = pp_formatted_text (&sub_pp);
+
+ // Calculate the length of the maximum line in the pattern.
+ unsigned int max_len = 0;
+ const char *start = text;
+ while (const char *end = strchr (start, '\n'))
+ {
+ max_len = MAX (max_len, (unsigned int) (end - start));
+ start = end + 1;
+ }
+
+ // Print a separator before or after the pattern.
+ auto print_top_bottom = [&]()
+ {
+ pp_character (pp, '+');
+ for (unsigned int i = 0; i < max_len + 2; ++i)
+ pp_character (pp, '-');
+ };
+
+ print_top_bottom ();
+ start = text;
+ while (const char *end = strchr (start, '\n'))
+ {
+ pp_newline_and_indent (pp, 0);
+ pp_character (pp, '|');
+ // Each line of the pattern already starts with a space.
+ // so we don't need to add another one here.
+ pp_append_text (pp, start, end);
+ start = end + 1;
+ }
+ pp_newline_and_indent (pp, 0);
+ print_top_bottom ();
+
+ if (m_cost_or_uid != UNKNOWN_COST)
+ {
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "cost: ");
+ pp_decimal_int (pp, m_cost_or_uid);
+ }
+ if (m_has_pre_post_modify)
+ {
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "has pre/post-modify operations");
+ }
+ if (m_has_volatile_refs)
+ {
+ pp_newline_and_indent (pp, 0);
+ pp_string (pp, "has volatile refs");
+ }
+ }
+ pp_indentation (pp) -= 2;
+ }
+
+ auto print_accesses = [&](const char *heading, access_array accesses,
+ unsigned int flags)
+ {
+ if (!accesses.empty ())
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, heading);
+ pp_newline_and_indent (pp, 2);
+ pp_accesses (pp, accesses, flags);
+ pp_indentation (pp) -= 4;
+ }
+ };
+
+ print_accesses ("uses:", uses (), PP_ACCESS_USER);
+ auto *call_clobbers_note = find_note<insn_call_clobbers_note> ();
+ if (call_clobbers_note)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "has call clobbers for ABI ");
+ pp_decimal_int (pp, call_clobbers_note->abi_id ());
+ pp_indentation (pp) -= 2;
+ }
+ print_accesses ("defines:", defs (), PP_ACCESS_SETTER);
+ if (num_uses () == 0 && !call_clobbers_note && num_defs () == 0)
+ {
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "has no uses or defs");
+ pp_indentation (pp) -= 2;
+ }
+
+ if (order_node *node = get_order_node ())
+ {
+ while (node->m_parent)
+ node = node->m_parent;
+
+ pp_newline_and_indent (pp, 2);
+ pp_string (pp, "insn order: ");
+ pp_newline_and_indent (pp, 2);
+ auto print_order = [](pretty_printer *pp, order_node *node)
+ {
+ print_uid (pp, node->uid ());
+ };
+ order_splay_tree::print (pp, node, print_order);
+ pp_indentation (pp) -= 4;
+ }
+}
+
+// Return an insn_info::order_node for INSN, creating one if necessary.
+insn_info::order_node *
+function_info::need_order_node (insn_info *insn)
+{
+ insn_info::order_node *order = insn->get_order_node ();
+ if (!order)
+ {
+ order = allocate<insn_info::order_node> (insn->uid ());
+ insn->add_note (order);
+ }
+ return order;
+}
+
+// Add instruction INSN immediately after AFTER in the reverse postorder list.
+// INSN is not currently in the list.
+void
+function_info::add_insn_after (insn_info *insn, insn_info *after)
+{
+ gcc_checking_assert (!insn->has_insn_links ());
+
+ insn->copy_next_from (after);
+ after->set_next_any_insn (insn);
+
+ // The prev link is easy if AFTER and INSN are the same type.
+ // Handle the other cases below.
+ if (after->is_debug_insn () == insn->is_debug_insn ())
+ insn->set_prev_sametype_insn (after);
+
+ if (insn_info *next = insn->next_any_insn ())
+ {
+ if (insn->is_debug_insn () == next->is_debug_insn ())
+ {
+ // INSN might now be the start of the subsequence of debug insns,
+ // and so its prev pointer might point to the end of the subsequence
+ // instead of AFTER.
+ insn->copy_prev_from (next);
+ next->set_prev_sametype_insn (insn);
+ }
+ else if (insn->is_debug_insn ()) // && !next->is_debug_insn ()
+ {
+ // INSN ends a subsequence of debug instructions. Find the
+ // first debug instruction in the subsequence, which might
+ // be INSN itself. (If it isn't, then AFTER is also a debug
+ // instruction and we updated INSN's prev link above.)
+ insn_info *first = next->prev_nondebug_insn ()->next_any_insn ();
+ first->set_last_debug_insn (insn);
+ }
+ else // !insn->is_debug_insn () && next->is_debug_insn ()
+ // At present we don't (need to) support inserting a nondebug
+ // instruction between two existing debug instructions.
+ gcc_assert (!after->is_debug_insn ());
+
+ // If AFTER and NEXT are separated by at least two points, we can
+ // use a unique point number for INSN. Otherwise INSN will have
+ // the same point number as AFTER.
+ insn->set_point ((next->point () + after->point ()) / 2);
+ }
+ else
+ {
+ if (!insn->is_debug_insn ())
+ {
+ insn->set_prev_sametype_insn (m_last_nondebug_insn);
+ m_last_nondebug_insn = insn;
+ }
+ else
+ // There is now at least one debug instruction after
+ // m_last_nondebug_insn: either INSN itself, or the start of
+ // a longer subsequence of debug insns that now ends with AFTER
+ // followed by INSN.
+ m_last_nondebug_insn->next_any_insn ()->set_last_debug_insn (insn);
+ m_last_insn = insn;
+
+ insn->set_point (after->point () + POINT_INCREASE);
+ }
+
+ // If INSN's program point is the same as AFTER's, we need to use the
+ // splay tree to record their relative order.
+ if (insn->point () == after->point ())
+ {
+ insn_info::order_node *after_node = need_order_node (after);
+ insn_info::order_node *insn_node = need_order_node (insn);
+ insn_info::order_splay_tree::insert_child (after_node, 1, insn_node);
+ }
+}
+
+// Remove INSN from the function's list of instructions.
+void
+function_info::remove_insn (insn_info *insn)
+{
+ if (insn_info::order_node *order = insn->get_order_node ())
+ insn_info::order_splay_tree::remove_node (order);
+
+ if (auto *note = insn->find_note<insn_call_clobbers_note> ())
+ {
+ ebb_call_clobbers_info *ecc = insn->ebb ()->first_call_clobbers ();
+ while (ecc->abi ()->id () != note->abi_id ())
+ ecc = ecc->next ();
+ int comparison = lookup_call_clobbers (*ecc, insn);
+ gcc_assert (comparison == 0);
+ ecc->remove_root ();
+ }
+
+ insn_info *prev = insn->prev_any_insn ();
+ insn_info *next = insn->next_any_insn ();
+ insn_info *prev_nondebug = insn->prev_nondebug_insn ();
+ insn_info *next_nondebug = insn->next_nondebug_insn ();
+
+ // We should never remove the entry or exit block's instructions.
+ // At present we also don't remove entire blocks, so should never
+ // remove debug instructions.
+ gcc_checking_assert (prev_nondebug
+ && next_nondebug
+ && !insn->is_debug_insn ());
+
+ if (prev->is_debug_insn () && next->is_debug_insn ())
+ {
+ // We need to stitch together two subsequences of debug insns.
+ insn_info *last = next->last_debug_insn ();
+ next->set_prev_sametype_insn (prev);
+ prev_nondebug->next_any_insn ()->set_last_debug_insn (last);
+ }
+ prev->set_next_any_insn (next);
+ next_nondebug->set_prev_sametype_insn (prev_nondebug);
+
+ insn->clear_insn_links ();
+}
+
+// Create an artificial instruction for BB, associating it with RTL (which can
+// be null). Add the new instruction to the end of the function's list and
+// return the new instruction.
+insn_info *
+function_info::append_artificial_insn (bb_info *bb, rtx_insn *rtl)
+{
+ insn_info *insn = allocate<insn_info> (bb, rtl, m_next_artificial_uid);
+ m_next_artificial_uid -= 1;
+ append_insn (insn);
+ return insn;
+}
+
+// Finish building a new list of uses and definitions for instruction INSN.
+void
+function_info::finish_insn_accesses (insn_info *insn)
+{
+ unsigned int num_defs = m_temp_defs.length ();
+ unsigned int num_uses = m_temp_uses.length ();
+ obstack_make_room (&m_obstack, num_defs + num_uses);
+ if (num_defs)
+ {
+ sort_accesses (m_temp_defs);
+ obstack_grow (&m_obstack, m_temp_defs.address (),
+ num_defs * sizeof (access_info *));
+ m_temp_defs.truncate (0);
+ }
+ if (num_uses)
+ {
+ sort_accesses (m_temp_uses);
+ obstack_grow (&m_obstack, m_temp_uses.address (),
+ num_uses * sizeof (access_info *));
+ m_temp_uses.truncate (0);
+ }
+ void *addr = obstack_finish (&m_obstack);
+ insn->set_accesses (static_cast<access_info **> (addr), num_defs, num_uses);
+}
+
+// Called while building SSA form using BI. Record that INSN contains
+// read reference REF. If this requires new entries to be added to
+// INSN->uses (), add those entries to the list we're building in
+// m_temp_uses.
+void
+function_info::record_use (build_info &bi, insn_info *insn,
+ rtx_obj_reference ref)
+{
+ unsigned int regno = ref.regno;
+ machine_mode mode = ref.is_reg () ? ref.mode : BLKmode;
+ access_info *access = bi.last_access[ref.regno + 1];
+ use_info *use = safe_dyn_cast<use_info *> (access);
+ if (!use)
+ {
+ set_info *value = safe_dyn_cast<set_info *> (access);
+ // In order to ensure that -g doesn't affect codegen, uses in debug
+ // instructions do not affect liveness, either in DF or here.
+ // This means that there might be no correct definition of the resource
+ // available (e.g. if it would require a phi node that the nondebug
+ // code doesn't need). Perhaps we could have "debug phi nodes" as
+ // well as "debug instructions", but that would require a method
+ // of building phi nodes that didn't depend on DF liveness information,
+ // and so might be significantly more expensive.
+ //
+ // Therefore, the only value we try to attach to a use by a debug
+ // instruction is VALUE itself (as we would for nondebug instructions).
+ // We then need to make a conservative check for whether VALUE is
+ // actually correct.
+ auto value_is_valid = [&]()
+ {
+ // Memmory always has a valid definition.
+ if (ref.is_mem ())
+ return true;
+
+ // If VALUE would lead to an uninitialized use anyway, there's
+ // nothing to check.
+ if (!value)
+ return false;
+
+ // If the previous definition occurs in the same EBB then it
+ // is certainly correct.
+ if (value->ebb () == bi.current_ebb)
+ return true;
+
+ // If the register is live on entry to the EBB but not used
+ // within it, VALUE is the correct live-in value.
+ if (bitmap_bit_p (bi.ebb_live_in_for_debug, regno))
+ return true;
+
+ // Check if VALUE is the function's only definition of REGNO
+ // and if it dominates the use.
+ if (regno != MEM_REGNO
+ && regno < DF_REG_SIZE (DF)
+ && DF_REG_DEF_COUNT (regno) == 1
+ && dominated_by_p (CDI_DOMINATORS, insn->bb ()->cfg_bb (),
+ value->bb ()->cfg_bb ()))
+ return true;
+
+ // Punt for other cases.
+ return false;
+ };
+ if (insn->is_debug_insn () && !value_is_valid ())
+ value = nullptr;
+
+ use = allocate<use_info> (insn, resource_info { mode, regno }, value);
+ add_use (use);
+ m_temp_uses.safe_push (use);
+ bi.last_access[ref.regno + 1] = use;
+ use->record_reference (ref, true);
+ }
+ else
+ {
+ // Record the mode of the largest use. The choice is arbitrary if
+ // the instruction (unusually) references the same register in two
+ // different but equal-sized modes.
+ gcc_checking_assert (use->insn () == insn);
+ if (HARD_REGISTER_NUM_P (regno)
+ && partial_subreg_p (use->mode (), mode))
+ use->set_mode (mode);
+ use->record_reference (ref, false);
+ }
+}
+
+// Called while building SSA form for INSN using BI. Record the effect
+// of call clobbers in RTL. We have already added the explicit sets and
+// clobbers for RTL, which have priority over any call clobbers.
+void
+function_info::record_call_clobbers (build_info &bi, insn_info *insn,
+ rtx_call_insn *rtl)
+{
+ // See whether we should record this call in the EBB's list of
+ // call clobbers. Three things affect this choice:
+ //
+ // (1) The list is the only way we have of recording partial clobbers.
+ // All calls that only partially clobber registers must therefore
+ // be in the list.
+ //
+ // (2) Adding calls to the list is much more memory-efficient than
+ // creating a long list of clobber_infos.
+ //
+ // (3) Adding calls to the list limits the ability to move definitions
+ // of registers that are normally fully or partially clobbered
+ // by the associated predefined ABI. So adding calls to the list
+ // can hamper optimization if (thanks to -fipa-ra) the number of
+ // clobbers is much smaller than the usual set.
+ //
+ // The trade-off that we currently take is to use the list if there
+ // are some registers that the call only partially clobbers or if
+ // the set of clobbers is the standard set.
+ function_abi abi = insn_callee_abi (rtl);
+ if (abi.base_abi ().full_reg_clobbers () == abi.full_reg_clobbers ()
+ || abi.full_and_partial_reg_clobbers () != abi.full_reg_clobbers ())
+ {
+ // Find an entry for this predefined ABI, creating one if necessary.
+ ebb_call_clobbers_info *ecc = bi.current_ebb->first_call_clobbers ();
+ while (ecc && ecc->abi () != &abi.base_abi ())
+ ecc = ecc->next ();
+ if (!ecc)
+ {
+ ecc = allocate<ebb_call_clobbers_info> (&abi.base_abi ());
+ ecc->m_next = bi.current_ebb->first_call_clobbers ();
+ bi.current_ebb->set_first_call_clobbers (ecc);
+ }
+
+ auto abi_id = abi.base_abi ().id ();
+ auto *insn_clobbers = allocate<insn_call_clobbers_note> (abi_id, insn);
+ insn->add_note (insn_clobbers);
+
+ ecc->insert_max_node (insn_clobbers);
+ }
+ else
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ if (TEST_HARD_REG_BIT (abi.full_reg_clobbers (), regno))
+ {
+ def_info *def = m_defs[regno + 1];
+ if (!def || def->last_def ()->insn () != insn)
+ {
+ def = allocate<clobber_info> (insn, regno);
+ def->m_is_call_clobber = true;
+ append_def (def);
+ m_temp_defs.safe_push (def);
+ bi.last_access[regno + 1] = def;
+ }
+ }
+}
+
+// Called while building SSA form using BI. Record that INSN contains
+// write reference REF. Add associated def_infos to the list of accesses
+// that we're building in m_temp_defs. Record the register's new live
+// value in BI.
+void
+function_info::record_def (build_info &bi, insn_info *insn,
+ rtx_obj_reference ref)
+{
+ // Punt if we see multiple definitions of the same resource.
+ // This can happen for several reasons:
+ //
+ // - An instruction might store two values to memory at once, giving two
+ // distinct memory references.
+ //
+ // - An instruction might assign to multiple pieces of a wide pseudo
+ // register. For example, on 32-bit targets, an instruction might
+ // assign to both the upper and lower halves of a 64-bit pseudo register.
+ //
+ // - It's possible for the same register to be clobbered by the
+ // CALL_INSN_FUNCTION_USAGE and to be set by the main instruction
+ // pattern as well. In that case, the clobber conceptually happens
+ // before the set and can essentially be ignored.
+ //
+ // - Similarly, global registers are implicitly set by a call but can
+ // be explicitly set or clobbered as well. In that situation, the sets
+ // are listed first and should win over a clobber.
+ unsigned int regno = ref.regno;
+ machine_mode mode = ref.is_reg () ? ref.mode : BLKmode;
+ def_info *def = safe_dyn_cast<def_info *> (bi.last_access[ref.regno + 1]);
+ if (def && def->insn () == insn)
+ {
+ if (!ref.is_clobber ())
+ {
+ gcc_checking_assert (!is_a<clobber_info *> (def));
+ def->record_reference (ref, false);
+ }
+ return;
+ }
+
+ // Memory is always well-defined, so only use clobber_infos for registers.
+ if (ref.is_reg () && ref.is_clobber ())
+ def = allocate<clobber_info> (insn, regno);
+ else
+ def = allocate<set_info> (insn, resource_info { mode, regno });
+ def->record_reference (ref, true);
+ append_def (def);
+ m_temp_defs.safe_push (def);
+ bi.last_access[ref.regno + 1] = def;
+}
+
+// Called while building SSA form using BI. Add an insn_info for RTL
+// to the block that we're current building.
+void
+function_info::add_insn_to_block (build_info &bi, rtx_insn *rtl)
+{
+ insn_info *insn = allocate<insn_info> (bi.current_bb, rtl, UNKNOWN_COST);
+ append_insn (insn);
+
+ vec_rtx_properties properties;
+ properties.add_insn (rtl, true);
+ insn->set_properties (properties);
+
+ start_insn_accesses ();
+
+ // Record the uses.
+ for (rtx_obj_reference ref : properties.refs ())
+ if (ref.is_read ())
+ record_use (bi, insn, ref);
+
+ // Restore the contents of bi.last_access, which we used as a cache
+ // when assembling the uses.
+ for (access_info *access : m_temp_uses)
+ {
+ unsigned int regno = access->regno ();
+ gcc_checking_assert (bi.last_access[regno + 1] == access);
+ bi.last_access[regno + 1] = as_a<use_info *> (access)->def ();
+ }
+
+ // Record the definitions.
+ for (rtx_obj_reference ref : properties.refs ())
+ if (ref.is_write ())
+ record_def (bi, insn, ref);
+
+ // Logically these happen before the explicit definitions, but if the
+ // explicit definitions and call clobbers reference the same register,
+ // the explicit definition should win.
+ if (auto *call_rtl = dyn_cast<rtx_call_insn *> (rtl))
+ record_call_clobbers (bi, insn, call_rtl);
+
+ finish_insn_accesses (insn);
+}
+
+// Check whether INSN sets any registers that are never subsequently used.
+// If so, add REG_UNUSED notes for them. The caller has already removed
+// any previous REG_UNUSED notes.
+void
+function_info::add_reg_unused_notes (insn_info *insn)
+{
+ rtx_insn *rtl = insn->rtl ();
+
+ auto handle_potential_set = [&](rtx pattern)
+ {
+ if (GET_CODE (pattern) != SET)
+ return;
+
+ rtx dest = SET_DEST (pattern);
+ if (!REG_P (dest))
+ return;
+
+ def_array defs = insn->defs ();
+ unsigned int index = find_access_index (defs, REGNO (dest));
+ for (unsigned int i = 0; i < REG_NREGS (dest); ++i)
+ {
+ def_info *def = defs[index + i];
+ gcc_checking_assert (def->regno () == REGNO (dest) + i);
+ set_info *set = dyn_cast<set_info *> (def);
+ if (set && set->has_nondebug_uses ())
+ return;
+ }
+ add_reg_note (rtl, REG_UNUSED, dest);
+ };
+
+ rtx pattern = PATTERN (rtl);
+ if (GET_CODE (pattern) == PARALLEL)
+ for (int i = 0; i < XVECLEN (pattern, 0); ++i)
+ handle_potential_set (XVECEXP (pattern, 0, i));
+ else
+ handle_potential_set (pattern);
+}
+
+// Search TREE for call clobbers at INSN. Return:
+//
+// - less than zero if INSN occurs before the root of TREE
+// - 0 if INSN is the root of TREE
+// - greater than zero if INSN occurs after the root of TREE
+int
+rtl_ssa::lookup_call_clobbers (insn_call_clobbers_tree &tree, insn_info *insn)
+{
+ auto compare = [&](insn_call_clobbers_note *clobbers)
+ {
+ return insn->compare_with (clobbers->insn ());
+ };
+ return tree.lookup (compare);
+}
+
+// Print a description of INSN to PP.
+void
+rtl_ssa::pp_insn (pretty_printer *pp, const insn_info *insn)
+{
+ if (!insn)
+ pp_string (pp, "<null>");
+ else
+ insn->print_full (pp);
+}
+
+// Print a description of INSN to FILE.
+void
+dump (FILE *file, const insn_info *insn)
+{
+ dump_using (file, pp_insn, insn);
+}
+
+// Debug interface to the dump routine above.
+void debug (const insn_info *x) { dump (stderr, x); }
diff --git a/gcc/rtl-ssa/insns.h b/gcc/rtl-ssa/insns.h
new file mode 100644
index 0000000..a663103
--- /dev/null
+++ b/gcc/rtl-ssa/insns.h
@@ -0,0 +1,505 @@
+// Instruction-related RTL SSA classes -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// A fake cost for instructions that we haven't costed yet.
+const int UNKNOWN_COST = INT_MAX;
+
+// Enumerates the kinds of note that can be added to an instruction.
+// See the comment above insn_info for details.
+enum class insn_note_kind : uint8_t
+{
+ ORDER_NODE,
+ CALL_CLOBBERS
+};
+
+// The base class for notes that can be added to an instruction.
+// See the comment above insn_info for details.
+class insn_note
+{
+ // Size: 2 LP64 words.
+ friend class insn_info;
+ friend class function_info;
+
+public:
+ // Return what kind of note this is.
+ insn_note_kind kind () const { return m_kind; }
+
+ // Return the next note in the list, or null if none.
+ insn_note *next_note () const { return m_next_note; }
+
+ // Used with T = Derived *, where Derived is derived from insn_note.
+ // Convert the note to Derived, asserting that it has the right kind.
+ template<typename T>
+ T as_a ();
+
+ // Used with T = Derived *, where Derived is derived from insn_note.
+ // If the note is a Derived note, return it in that form, otherwise
+ // return null.
+ template<typename T>
+ T dyn_cast ();
+
+protected:
+ // Construct a note with the given kind.
+ insn_note (insn_note_kind);
+
+private:
+ // The next note in the list, or null if none.
+ insn_note *m_next_note;
+
+ // The kind of note this is.
+ insn_note_kind m_kind : 8;
+
+protected:
+ // Fill in the remaining LP64 word with data that derived classes can use.
+ unsigned int m_data8 : 8;
+ unsigned int m_data16 : 16;
+ unsigned int m_data32 : 32;
+};
+
+// Instructions have one of these notes if insn_info::has_call_clobbers ()
+// is true. All such instructions in an EBB are first grouped together
+// by the predefined_function_abis of the functions that they call.
+// Then, for each such predefined ABI, the call_clobbers notes are put
+// into a splay tree whose nodes follow execution order.
+class insn_call_clobbers_note : public insn_note
+{
+ friend class function_info;
+ friend class default_splay_tree_accessors<insn_call_clobbers_note *>;
+
+public:
+ static const insn_note_kind kind = insn_note_kind::CALL_CLOBBERS;
+
+ // Return the identifier of the predefined_function_abi.
+ unsigned int abi_id () const { return m_data32; }
+
+ // Return the instruction to which the note is attached.
+ insn_info *insn () const { return m_insn; }
+
+protected:
+ insn_call_clobbers_note (unsigned int abi_id, insn_info *insn);
+
+ // The splay tree pointers.
+ insn_call_clobbers_note *m_children[2];
+
+ // The value returned by insn ().
+ insn_info *m_insn;
+};
+
+// A splay tree of insn_call_clobbers_notes.
+using insn_call_clobbers_tree = default_splay_tree<insn_call_clobbers_note *>;
+
+// SSA-related information about an instruction. It also represents
+// artificial instructions that are added to make the dataflow correct;
+// these artificial instructions fall into three categories:
+//
+// - Instructions that hold the phi nodes for an extended basic block (is_phi).
+//
+// - Instructions that represent the head of a basic block and that hold
+// all the associated artificial uses and definitions.
+//
+// - Instructions that represent the end of a basic block and that again
+// hold all the associated artificial uses and definitions.
+//
+// Dataflow-wise, each instruction goes through three stages:
+//
+// (1) Use all the values in uses ().
+//
+// (2) If has_call_clobbers (), clobber the registers indicated by
+// insn_callee_abi.
+//
+// (3) Define all the values in defs ().
+//
+// Having stage (2) is a trade-off: it makes processing the instructions
+// more complicated, but it saves having to allocate memory for every
+// individual call clobber. Without it, clobbers for calls would often
+// make up a large proportion of the total definitions in a function.
+//
+// All the instructions in a function are chained together in a list
+// that follows a reverse postorder traversal of the CFG. The list
+// contains both debug and nondebug instructions, but it is possible
+// to hop from one nondebug instruction to the next with constant complexity.
+//
+// Instructions can have supplemental information attached in the form
+// of "notes", a bit like REG_NOTES for the underlying RTL insns.
+class insn_info
+{
+ // Size: 8 LP64 words.
+ friend class ebb_info;
+ friend class function_info;
+
+public:
+ // Compare instructions by their positions in the function list described
+ // above. Thus for two instructions in the same basic block, I1 < I2 if
+ // I1 comes before I2 in the block.
+ bool operator< (const insn_info &) const;
+ bool operator<= (const insn_info &) const;
+ bool operator>= (const insn_info &) const;
+ bool operator> (const insn_info &) const;
+
+ // Return -1 if this instruction comes before INSN in the reverse
+ // postorder, 0 if this instruction is INSN, or 1 if this instruction
+ // comes after INSN in the reverse postorder.
+ int compare_with (const insn_info *insn) const;
+
+ // Return the previous and next instructions in the list described above,
+ // or null if there are no such instructions.
+ insn_info *prev_any_insn () const;
+ insn_info *next_any_insn () const;
+
+ // Only valid if !is_debug_insn (). Return the previous and next
+ // nondebug instructions in the list described above, skipping over
+ // any intervening debug instructions. These are constant-time operations.
+ insn_info *prev_nondebug_insn () const;
+ insn_info *next_nondebug_insn () const;
+
+ // Return the underlying RTL insn. This instruction is null if is_phi ()
+ // or is_bb_end () are true. The instruction is a basic block note if
+ // is_bb_head () is true.
+ rtx_insn *rtl () const { return m_rtl; }
+
+ // Return true if the instruction is a real insn with an rtl pattern.
+ // Return false if it is an artificial instruction that represents the
+ // phi nodes in an extended basic block or the head or end of a basic block.
+ bool is_real () const { return m_cost_or_uid >= 0; }
+
+ // Return the opposite of is_real ().
+ bool is_artificial () const { return m_cost_or_uid < 0; }
+
+ // Return true if the instruction was a real instruction but has now
+ // been deleted. In this case the instruction is no longer part of
+ // the SSA information.
+ bool has_been_deleted () const { return m_rtl && !INSN_P (m_rtl); }
+
+ // Return true if the instruction is a debug instruction (and thus
+ // also a real instruction).
+ bool is_debug_insn () const { return m_is_debug_insn; }
+
+ // Return true if the instruction is something that we can optimize.
+ // This implies that it is a real instruction that contains an asm
+ // or that contains something that matches an .md define_insn pattern.
+ bool can_be_optimized () const { return m_can_be_optimized; }
+
+ // Return true if the instruction is a call instruction.
+ //
+ // ??? We could cache this information, but since most callers would
+ // go on to access PATTERN (rtl ()), a cache might not be helpful and
+ // could even be counterproductive.
+ bool is_call () const { return CALL_P (m_rtl); }
+
+ // Return true if the instruction is a jump instruction.
+ //
+ // ??? See is_call for the reason we don't cache this.
+ bool is_jump () const { return JUMP_P (m_rtl); }
+
+ // Return true if the instruction is real and contains an inline asm.
+ bool is_asm () const { return m_is_asm; }
+
+ // Return true if the instruction is real and includes an RTX_AUTOINC
+ // operation.
+ bool has_pre_post_modify () const { return m_has_pre_post_modify; }
+
+ // Return true if the instruction is real and has volatile references,
+ // in the sense of volatile_refs_p. This includes volatile memory,
+ // volatile asms and UNSPEC_VOLATILEs.
+ bool has_volatile_refs () const { return m_has_volatile_refs; }
+
+ // Return true if the instruction is aritificial and if its (sole)
+ // purpose is to hold the phi nodes in an extended basic block.
+ bool is_phi () const;
+
+ // Return true if the instruction is artificial and if it represents
+ // the head of a basic block. If so, the instruction conceptually
+ // executes before the real instructions in the block. The uses
+ // and definitions represent the df_get_artificial_uses and
+ // df_get_artificial_defs entries for the head of the block.
+ bool is_bb_head () const;
+
+ // Return true if the instruction is artificial and if it represents
+ // the end of a basic block. The uses and definitions represent the
+ // the df_get_artificial_uses and df_get_artificial_defs entries for
+ // the end of the block.
+ bool is_bb_end () const;
+
+ // Return the basic block that the instruction is in.
+ bb_info *bb () const { return m_bb; }
+
+ // Return the extended basic block that the instruction is in;
+ // see bb_info for details.
+ ebb_info *ebb () const;
+
+ // If the instruction is real, return the unique identifier of the
+ // underlying RTL insn. If the instruction is artificial, return
+ // a unique negative identifier for the instructions.
+ //
+ // Note that the identifiers are not linear: it can be the case that
+ // an instruction with a higher uid comes earlier in a block than an
+ // instruction with a lower uid. The identifiers are however persistent;
+ // the identifier remains the same after the instruction has been moved
+ // or changed.
+ int uid () const;
+
+ // Return the list of things that this instruction uses. Registers
+ // come first, in register number order, followed by memory.
+ use_array uses () const;
+
+ // Return true if the instruction is a call and if the clobbers
+ // described by insn_callee_abi have been omitted from the list
+ // of definitions.
+ bool has_call_clobbers () const;
+
+ // Return the list of things that this instruction sets or clobbers.
+ // Registers come first, in register number order, followed by memory.
+ //
+ // If has_call_clobbers () is true, the list omits both the full and
+ // partial register clobbers described by insn_callee_abi.
+ def_array defs () const;
+
+ // The number of entries in uses ().
+ unsigned int num_uses () const { return m_num_uses; }
+
+ // The number of entries in defs ().
+ unsigned int num_defs () const { return m_num_defs; }
+
+ // Return the cost of the instruction, as calculated by the target.
+ // For performance reasons, the cost is evaluated lazily on first use.
+ //
+ // Artificial instructions have a cost of 0.
+ unsigned int cost () const;
+
+ // Return the first insn_note attached to the instruction, or null
+ // if none.
+ insn_note *first_note () const { return m_first_note; }
+
+ // See if a note of type T is attached to the instruction. Return it
+ // if so, otherwise return null.
+ template<typename T>
+ const T *find_note () const;
+
+ // Print "i" + uid () for real instructions and "a" + -uid () for
+ // artificial instructions.
+ void print_identifier (pretty_printer *) const;
+
+ // Print a short(ish) description of where the instruction is.
+ void print_location (pretty_printer *) const;
+
+ // Combine print_identifier and print_location.
+ void print_identifier_and_location (pretty_printer *) const;
+
+ // Print a full description of the instruction.
+ void print_full (pretty_printer *) const;
+
+private:
+ // The first-order way of representing the order between instructions
+ // is to assign "program points", with higher point numbers coming
+ // later in the reverse postorder than lower point numbers. However,
+ // after a sequence of instruction movements, we may end up in a situation
+ // that adjacent instructions have the same program point.
+ //
+ // When that happens, we put the instructions into a splay tree that
+ // records their relative order. Each node of the splay tree is an
+ // order_node note that is attached to its respective instruction.
+ // The root of the splay tree is not stored, since the only thing
+ // we need the tree for is to compare two nodes.
+ class order_node : public insn_note
+ {
+ public:
+ static const insn_note_kind kind = insn_note_kind::ORDER_NODE;
+
+ order_node (int uid);
+
+ // Return the uid of the instruction that this node describes.
+ int uid () const { return m_data32; }
+
+ // The splay tree pointers.
+ order_node *m_children[2];
+ order_node *m_parent;
+ };
+ using order_splay_tree = default_rootless_splay_tree<order_node *>;
+
+ // prev_insn_or_last_debug_insn represents a choice between two things:
+ //
+ // (1) A pointer to the previous instruction in the list that has the
+ // same is_debug_insn () value, or null if no such instruction exists.
+ //
+ // (2) A pointer to the end of a sublist of debug instructions.
+ //
+ // (2) is used if this instruction is a debug instruction and the
+ // previous instruction is not. (1) is used otherwise.
+ //
+ // next_nondebug_or_debug_insn points to the next instruction but also
+ // records whether that next instruction is a debug instruction or a
+ // nondebug instruction.
+ //
+ // Thus the list is chained as follows:
+ //
+ // ----> ----> ----> ----> ---->
+ // NONDEBUG NONDEBUG DEBUG DEBUG DEBUG NONDEBUG ...
+ // <---- ^ +-- <---- <---- ^ +--
+ // | | | |
+ // | +------------------------+ |
+ // | |
+ // +-----------------------------------+
+ using prev_insn_or_last_debug_insn = pointer_mux<insn_info>;
+ using next_nondebug_or_debug_insn = pointer_mux<insn_info>;
+
+ insn_info (bb_info *bb, rtx_insn *rtl, int cost_or_uid);
+
+ static void print_uid (pretty_printer *, int);
+
+ void calculate_cost () const;
+ void set_properties (const rtx_properties &);
+ void set_accesses (access_info **, unsigned int, unsigned int);
+ void copy_accesses (access_array, access_array);
+ void set_cost (unsigned int cost) { m_cost_or_uid = cost; }
+ void set_bb (bb_info *bb) { m_bb = bb; }
+
+ void add_note (insn_note *note);
+
+ order_node *get_order_node () const;
+ order_node *get_known_order_node () const;
+ int slow_compare_with (const insn_info &) const;
+
+ insn_info *last_debug_insn () const;
+
+ unsigned int point () const { return m_point; }
+ void copy_prev_from (insn_info *);
+ void copy_next_from (insn_info *);
+ void set_prev_sametype_insn (insn_info *);
+ void set_last_debug_insn (insn_info *);
+ void set_next_any_insn (insn_info *);
+ void set_point (unsigned int point) { m_point = point; }
+ void clear_insn_links ();
+ bool has_insn_links ();
+
+ // The values returned by the accessors above.
+ prev_insn_or_last_debug_insn m_prev_insn_or_last_debug_insn;
+ next_nondebug_or_debug_insn m_next_nondebug_or_debug_insn;
+ bb_info *m_bb;
+ rtx_insn *m_rtl;
+
+ // The list of definitions followed by the list of uses.
+ access_info **m_accesses;
+
+ // The number of definitions and the number uses. FIRST_PSEUDO_REGISTER + 1
+ // is the maximum number of accesses to hard registers and memory, and
+ // MAX_RECOG_OPERANDS is the maximum number of pseudos that can be
+ // defined by an instruction, so the number of definitions should fit
+ // easily in 16 bits.
+ unsigned int m_num_uses;
+ unsigned int m_num_defs : 16;
+
+ // Flags returned by the accessors above.
+ unsigned int m_is_debug_insn : 1;
+ unsigned int m_can_be_optimized : 1;
+ unsigned int m_is_asm : 1;
+ unsigned int m_has_pre_post_modify : 1;
+ unsigned int m_has_volatile_refs : 1;
+
+ // For future expansion.
+ unsigned int m_spare : 11;
+
+ // The program point at which the instruction occurs.
+ //
+ // Note that the values of the program points are influenced by -g
+ // and so should not used to make codegen decisions.
+ unsigned int m_point;
+
+ // Negative if the instruction is artificial, nonnegative if it is real.
+ //
+ // For real instructions: the cost of the instruction, or UNKNOWN_COST
+ // if we haven't measured it yet.
+ //
+ // For artificial instructions: the (negative) unique identifier of the
+ // instruction.
+ mutable int m_cost_or_uid;
+
+ // The list of notes that have been attached to the instruction.
+ insn_note *m_first_note;
+};
+
+// Iterators for unfiltered lists of instructions.
+using any_insn_iterator = list_iterator<insn_info, &insn_info::next_any_insn>;
+using reverse_any_insn_iterator
+ = list_iterator<insn_info, &insn_info::prev_any_insn>;
+
+// Iterators for nondebug instructions only.
+using nondebug_insn_iterator
+ = list_iterator<insn_info, &insn_info::next_nondebug_insn>;
+using reverse_nondebug_insn_iterator
+ = list_iterator<insn_info, &insn_info::prev_nondebug_insn>;
+
+// A class that describes an inclusive range of instructions.
+class insn_range_info
+{
+public:
+ insn_range_info () = default;
+
+ // Create a range that contains a singleton instruction.
+ insn_range_info (insn_info *insn) : first (insn), last (insn) {}
+
+ // Create a range [FIRST, LAST], given that *FIRST <= *LAST.
+ insn_range_info (insn_info *first, insn_info *last);
+
+ // Return true if the range contains at least one instruction.
+ explicit operator bool () const { return *first <= *last; }
+
+ bool operator== (const insn_range_info &) const;
+ bool operator!= (const insn_range_info &) const;
+
+ // If the range contains a single instruction, return that instruction,
+ // otherwise return null.
+ insn_info *singleton () const;
+
+ // Return true if the range includes INSN.
+ bool includes (insn_info *insn) const;
+
+ // If INSN is inside the range, return INSN, otherwise return the
+ // nearest in-range instruction.
+ insn_info *clamp_insn_to_range (insn_info *insn) const;
+
+ // Return true if this range is a subrange of OTHER, i.e. if OTHER
+ // includes every instruction that this range does.
+ bool is_subrange_of (const insn_range_info &other) const;
+
+ // The lower and upper bounds of the range.
+ insn_info *first;
+ insn_info *last;
+};
+
+// A class that represents a closure of operator== for instructions.
+// This is used by insn_is; see there for details.
+class insn_is_closure
+{
+public:
+ insn_is_closure (const insn_info *insn) : m_insn (insn) {}
+ bool operator() (const insn_info *other) const { return m_insn == other; }
+
+private:
+ const insn_info *m_insn;
+};
+
+void pp_insn (pretty_printer *, const insn_info *);
+
+}
+
+void dump (FILE *, const rtl_ssa::insn_info *);
+
+void DEBUG_FUNCTION debug (const rtl_ssa::insn_info *);
diff --git a/gcc/rtl-ssa/internals.inl b/gcc/rtl-ssa/internals.inl
new file mode 100644
index 0000000..00ad642
--- /dev/null
+++ b/gcc/rtl-ssa/internals.inl
@@ -0,0 +1,682 @@
+// Implementation of private inline member functions for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// Construct a new access with the given resource () and kind () values.
+inline access_info::access_info (resource_info resource, access_kind kind)
+ : m_regno (resource.regno),
+ m_kind (kind),
+ m_is_artificial (false),
+ m_is_set_with_nondebug_insn_uses (false),
+ m_is_pre_post_modify (false),
+ m_is_call_clobber (false),
+ m_is_live_out_use (false),
+ m_includes_address_uses (false),
+ m_includes_read_writes (false),
+ m_includes_subregs (false),
+ m_includes_multiregs (false),
+ m_only_occurs_in_notes (false),
+ m_is_last_nondebug_insn_use (false),
+ m_is_in_debug_insn_or_phi (false),
+ m_has_been_superceded (false),
+ m_is_temp (false),
+ m_spare (0),
+ m_mode (resource.mode)
+{
+}
+
+// Construct a use of RESOURCE in LOCATION. The resource's value is provided
+// by DEF, or is completely undefined if DEF is null.
+inline use_info::use_info (insn_or_phi location, resource_info resource,
+ set_info *definition)
+ : access_info (resource, access_kind::USE),
+ m_insn_or_phi (location),
+ m_last_use_or_prev_use (nullptr),
+ m_last_nondebug_insn_use_or_next_use (nullptr),
+ m_def (definition)
+{
+ if (m_insn_or_phi.is_second ())
+ {
+ m_is_in_debug_insn_or_phi = true;
+ m_is_artificial = true;
+ }
+ else
+ {
+ insn_info *insn = m_insn_or_phi.known_first ();
+ m_is_in_debug_insn_or_phi = insn->is_debug_insn ();
+ m_is_artificial = insn->is_artificial ();
+ }
+}
+
+// Return the correct (uncached) value of m_is_last_nondebug_insn_use.
+inline bool
+use_info::calculate_is_last_nondebug_insn_use () const
+{
+ use_info *next = next_use ();
+ return is_in_nondebug_insn () && (!next || next->is_in_debug_insn_or_phi ());
+}
+
+// Accumulate any properties about REF that are also stored in use_infos.
+// IS_FIRST is true if REF is the first access to resource () that we have
+// recorded in this way, false if we have already recorded previous
+// references.
+inline void
+use_info::record_reference (rtx_obj_reference ref, bool is_first)
+{
+ if (is_first)
+ {
+ m_includes_address_uses = ref.in_address ();
+ m_includes_read_writes = ref.is_write ();
+ m_includes_subregs = ref.in_subreg ();
+ m_includes_multiregs = ref.is_multireg ();
+ m_only_occurs_in_notes = ref.in_note ();
+ }
+ else
+ {
+ m_includes_address_uses |= ref.in_address ();
+ m_includes_read_writes |= ref.is_write ();
+ m_includes_subregs |= ref.in_subreg ();
+ m_includes_multiregs |= ref.is_multireg ();
+ m_only_occurs_in_notes &= ref.in_note ();
+ }
+}
+
+// Change the value of insn () to INSN.
+inline void
+use_info::set_insn (insn_info *insn)
+{
+ m_insn_or_phi = insn;
+ m_is_artificial = insn->is_artificial ();
+}
+
+// Copy the overloaded prev link from OTHER.
+inline void
+use_info::copy_prev_from (use_info *other)
+{
+ m_last_use_or_prev_use = other->m_last_use_or_prev_use;
+}
+
+// Copy the overloaded next link from OTHER.
+inline void
+use_info::copy_next_from (use_info *other)
+{
+ m_last_nondebug_insn_use_or_next_use
+ = other->m_last_nondebug_insn_use_or_next_use;
+ m_is_last_nondebug_insn_use = calculate_is_last_nondebug_insn_use ();
+}
+
+// Record that this use is the first in the list and that the last use is LAST.
+inline void
+use_info::set_last_use (use_info *last_use)
+{
+ m_last_use_or_prev_use.set_first (last_use);
+}
+
+// Record that this use is not the first in the list and that the previous
+// use is PREV.
+inline void
+use_info::set_prev_use (use_info *prev_use)
+{
+ m_last_use_or_prev_use.set_second (prev_use);
+}
+
+// Record that this use is the last use in the list. If USE is nonnull,
+// record that USE is the last use in the list by a nondebug instruction,
+// otherwise record that there are no uses by nondebug instructions
+// in the list.
+inline void
+use_info::set_last_nondebug_insn_use (use_info *use)
+{
+ m_last_nondebug_insn_use_or_next_use.set_first (use);
+ m_is_last_nondebug_insn_use = (use == this);
+}
+
+// Record that this use is not the last in the list and that the next
+// use is NEXT_USE.
+inline void
+use_info::set_next_use (use_info *next_use)
+{
+ m_last_nondebug_insn_use_or_next_use.set_second (next_use);
+ m_is_last_nondebug_insn_use = calculate_is_last_nondebug_insn_use ();
+}
+
+// Clear any information relating to the position of the use in its
+// definition's list.
+inline void
+use_info::clear_use_links ()
+{
+ m_last_use_or_prev_use = nullptr;
+ m_last_nondebug_insn_use_or_next_use = nullptr;
+ m_is_last_nondebug_insn_use = false;
+}
+
+// Return true if the use has any links to other uses. This is mostly
+// for assert checking.
+inline bool
+use_info::has_use_links ()
+{
+ return (m_last_use_or_prev_use
+ || m_last_nondebug_insn_use_or_next_use
+ || m_is_last_nondebug_insn_use);
+}
+
+// Construct a definition of RESOURCE in INSN, giving it kind KIND.
+inline def_info::def_info (insn_info *insn, resource_info resource,
+ access_kind kind)
+ : access_info (resource, kind),
+ m_insn (insn),
+ m_last_def_or_prev_def (nullptr),
+ m_splay_root_or_next_def (nullptr)
+{
+ m_is_artificial = insn->is_artificial ();
+}
+
+// Record any properties about REF that are also stored in def_infos.
+// IS_FIRST is true if REF is the first access to resource () that we have
+// recorded in this way, false if we have already recorded previous
+// references.
+inline void
+def_info::record_reference (rtx_obj_reference ref, bool is_first)
+{
+ if (is_first)
+ {
+ m_is_pre_post_modify = ref.is_pre_post_modify ();
+ m_includes_read_writes = ref.is_read ();
+ m_includes_subregs = ref.in_subreg ();
+ m_includes_multiregs = ref.is_multireg ();
+ }
+ else
+ {
+ m_is_pre_post_modify |= ref.is_pre_post_modify ();
+ m_includes_read_writes |= ref.is_read ();
+ m_includes_subregs |= ref.in_subreg ();
+ m_includes_multiregs |= ref.is_multireg ();
+ }
+}
+
+// Return the last definition in the list. Only valid when is_first ()
+// is true.
+inline def_info *
+def_info::last_def () const
+{
+ return m_last_def_or_prev_def.known_first ();
+}
+
+// Return the root of the splay tree of definitions of resource (),
+// or null if no splay tree has been created for this resource.
+// Only valid when is_last () is true.
+inline def_node *
+def_info::splay_root () const
+{
+ return m_splay_root_or_next_def.known_first ();
+}
+
+// Copy the overloaded prev link from OTHER.
+inline void
+def_info::copy_prev_from (def_info *other)
+{
+ m_last_def_or_prev_def
+ = other->m_last_def_or_prev_def;
+}
+
+// Copy the overloaded next link from OTHER.
+inline void
+def_info::copy_next_from (def_info *other)
+{
+ m_splay_root_or_next_def = other->m_splay_root_or_next_def;
+}
+
+// Record that this definition is the first in the list and that the last
+// definition is LAST.
+inline void
+def_info::set_last_def (def_info *last_def)
+{
+ m_last_def_or_prev_def.set_first (last_def);
+}
+
+// Record that this definition is not the first in the list and that the
+// previous definition is PREV.
+inline void
+def_info::set_prev_def (def_info *prev_def)
+{
+ m_last_def_or_prev_def.set_second (prev_def);
+}
+
+// Record that this definition is the last in the list and that the root
+// of the splay tree associated with resource () is ROOT.
+inline void
+def_info::set_splay_root (def_node *root)
+{
+ m_splay_root_or_next_def = root;
+}
+
+// Record that this definition is not the last in the list and that the
+// next definition is NEXT.
+inline void
+def_info::set_next_def (def_info *next_def)
+{
+ m_splay_root_or_next_def = next_def;
+}
+
+// Clear the prev and next links
+inline void
+def_info::clear_def_links ()
+{
+ m_last_def_or_prev_def = nullptr;
+ m_splay_root_or_next_def = nullptr;
+}
+
+// Return true if the definition has any links to other definitions.
+// This is mostly for assert checking.
+inline bool
+def_info::has_def_links ()
+{
+ return m_last_def_or_prev_def || m_splay_root_or_next_def;
+}
+
+// Construct a clobber of register REGNO in insn INSN.
+inline clobber_info::clobber_info (insn_info *insn, unsigned int regno)
+ : def_info (insn, { E_BLKmode, regno }, access_kind::CLOBBER),
+ m_children (),
+ m_parent (nullptr),
+ m_group (nullptr)
+{
+}
+
+// Set the containing group to GROUP, if it isn't already. The main
+// use of this function is to update the new root of GROUP's splay tree.
+inline void
+clobber_info::update_group (clobber_group *group)
+{
+ if (__builtin_expect (m_group != group, 0))
+ m_group = group;
+}
+
+// Cconstruct a set_info for a store to RESOURCE in INSN, giving it
+// kind KIND.
+inline set_info::set_info (insn_info *insn, resource_info resource,
+ access_kind kind)
+ : def_info (insn, resource, kind),
+ m_first_use (nullptr)
+{
+}
+
+// Cconstruct a set_info for a store to RESOURCE in INSN.
+inline set_info::set_info (insn_info *insn, resource_info resource)
+ : set_info (insn, resource, access_kind::SET)
+{
+}
+
+// Record that USE is the first use of this definition.
+inline void
+set_info::set_first_use (use_info *first_use)
+{
+ m_first_use = first_use;
+ m_is_set_with_nondebug_insn_uses
+ = (first_use && first_use->is_in_nondebug_insn ());
+}
+
+// Construct a phi for RESOURCE in INSN, giving it identifier UID.
+inline phi_info::phi_info (insn_info *insn, resource_info resource,
+ unsigned int uid)
+ : set_info (insn, resource, access_kind::PHI),
+ m_uid (uid),
+ m_num_inputs (0),
+ m_prev_phi (nullptr),
+ m_next_phi (nullptr)
+{
+}
+
+// Turn the phi into a degenerate phi, with INPUT representing the
+// value of the resource on all incoming edges.
+inline void
+phi_info::make_degenerate (use_info *input)
+{
+ m_num_inputs = 1;
+ m_single_input = input;
+}
+
+// Set the inputs of the phi to INPUTS.
+inline void
+phi_info::set_inputs (use_array inputs)
+{
+ m_num_inputs = inputs.size ();
+ if (inputs.size () == 1)
+ m_single_input = inputs[0];
+ else
+ m_inputs = access_array (inputs).begin ();
+}
+
+// Construct a definition splay tree node for FIRST_DEF, which is either
+// the first clobber_info in a group or a standalone set_info.
+inline def_node::def_node (clobber_or_set first_def)
+ : m_clobber_or_set (first_def),
+ m_children ()
+{
+}
+
+// Construct a new group of clobber_infos that initially contains just CLOBBER.
+inline clobber_group::clobber_group (clobber_info *clobber)
+ : def_node (clobber),
+ m_last_clobber (clobber),
+ m_clobber_tree (clobber)
+{
+ clobber->m_group = this;
+}
+
+// Construct a node for the instruction with uid UID.
+inline insn_info::order_node::order_node (int uid)
+ : insn_note (kind),
+ m_children (),
+ m_parent (nullptr)
+{
+ m_data32 = uid;
+}
+
+// Construct a note for instruction INSN, giving it abi_id () value ABI_ID.
+inline insn_call_clobbers_note::insn_call_clobbers_note (unsigned int abi_id,
+ insn_info *insn)
+ : insn_note (kind),
+ m_children (),
+ m_insn (insn)
+{
+ m_data32 = abi_id;
+}
+
+// Construct an instruction with the given bb () and rtl () values.
+// If the instruction is real, COST_OR_UID is the value of cost (),
+// otherwise it is the value of uid ().
+inline insn_info::insn_info (bb_info *bb, rtx_insn *rtl, int cost_or_uid)
+ : m_prev_insn_or_last_debug_insn (nullptr),
+ m_next_nondebug_or_debug_insn (nullptr),
+ m_bb (bb),
+ m_rtl (rtl),
+ m_accesses (nullptr),
+ m_num_uses (0),
+ m_num_defs (0),
+ m_is_debug_insn (rtl && DEBUG_INSN_P (rtl)),
+ m_can_be_optimized (false),
+ m_is_asm (false),
+ m_has_pre_post_modify (false),
+ m_has_volatile_refs (false),
+ m_spare (0),
+ m_point (0),
+ m_cost_or_uid (cost_or_uid),
+ m_first_note (nullptr)
+{
+}
+
+// Copy any insn properties from PROPERTIES that are also stored in an
+// insn_info.
+inline void
+insn_info::set_properties (const rtx_properties &properties)
+{
+ m_is_asm = properties.has_asm;
+ m_has_pre_post_modify = properties.has_pre_post_modify;
+ m_has_volatile_refs = properties.has_volatile_refs;
+ // Not strictly related to the properties we've been given, but it's
+ // a convenient location to do this.
+ m_can_be_optimized = (NONDEBUG_INSN_P (m_rtl)
+ & (GET_CODE (PATTERN (m_rtl)) != USE)
+ & (GET_CODE (PATTERN (m_rtl)) != CLOBBER));
+}
+
+// Change the list of instruction accesses to ACCESSES, which contains
+// NUM_DEFS definitions followed by NUM_USES uses.
+inline void
+insn_info::set_accesses (access_info **accesses,
+ unsigned int num_defs, unsigned int num_uses)
+{
+ m_accesses = accesses;
+ m_num_defs = num_defs;
+ gcc_assert (num_defs == m_num_defs);
+ m_num_uses = num_uses;
+}
+
+// Change defs () and uses () to DEFS and USES respectively, given that
+// the existing m_accesses array has enough room for them.
+inline void
+insn_info::copy_accesses (access_array defs, access_array uses)
+{
+ gcc_assert (defs.size () + uses.size () <= m_num_defs + m_num_uses);
+ memcpy (m_accesses, defs.begin (), defs.size_bytes ());
+ memcpy (m_accesses + defs.size (), uses.begin (), uses.size_bytes ());
+ m_num_defs = defs.size ();
+ gcc_assert (m_num_defs == defs.size ());
+ m_num_uses = uses.size ();
+}
+
+// If the instruction has an insn_info::order_node, return the node,
+// otherwise return null.
+inline insn_info::order_node *
+insn_info::get_order_node () const
+{
+ // The order_node always comes first.
+ if (insn_note *note = first_note ())
+ return note->dyn_cast<insn_info::order_node *> ();
+ return nullptr;
+}
+
+// Like get_order_node (), but the node is known to exist.
+inline insn_info::order_node *
+insn_info::get_known_order_node () const
+{
+ // The order_node always comes first.
+ return first_note ()->as_a<insn_info::order_node *> ();
+}
+
+// Copy the overloaded prev link from OTHER.
+inline void
+insn_info::copy_prev_from (insn_info *other)
+{
+ m_prev_insn_or_last_debug_insn = other->m_prev_insn_or_last_debug_insn;
+}
+
+// Copy the overloaded next link from OTHER.
+inline void
+insn_info::copy_next_from (insn_info *other)
+{
+ m_next_nondebug_or_debug_insn = other->m_next_nondebug_or_debug_insn;
+}
+
+// If this is a nondebug instruction, record that the previous nondebug
+// instruction is PREV. (There might be intervening debug instructions.)
+//
+// If this is a debug instruction, record that the previous instruction
+// is debug instruction PREV.
+inline void
+insn_info::set_prev_sametype_insn (insn_info *prev)
+{
+ m_prev_insn_or_last_debug_insn.set_first (prev);
+}
+
+// Only valid for debug instructions. Record that this instruction starts
+// a subsequence of debug instructions that ends with LAST.
+inline void
+insn_info::set_last_debug_insn (insn_info *last)
+{
+ m_prev_insn_or_last_debug_insn.set_second (last);
+}
+
+// Record that the next instruction of any kind is NEXT.
+inline void
+insn_info::set_next_any_insn (insn_info *next)
+{
+ if (next && next->is_debug_insn ())
+ m_next_nondebug_or_debug_insn.set_second (next);
+ else
+ m_next_nondebug_or_debug_insn.set_first (next);
+}
+
+// Clear the list links and point number for this instruction.
+inline void
+insn_info::clear_insn_links ()
+{
+ m_prev_insn_or_last_debug_insn = nullptr;
+ m_next_nondebug_or_debug_insn = nullptr;
+ m_point = 0;
+}
+
+// Return true if the instruction contains any list information.
+// This is used by assert checking.
+inline bool
+insn_info::has_insn_links ()
+{
+ return (m_prev_insn_or_last_debug_insn
+ || m_next_nondebug_or_debug_insn
+ || m_point);
+}
+
+// Construct a representation of basic block CFG_BB.
+inline bb_info::bb_info (basic_block cfg_bb)
+ : m_prev_bb (nullptr),
+ m_next_bb (nullptr),
+ m_cfg_bb (cfg_bb),
+ m_ebb (nullptr),
+ m_head_insn (nullptr),
+ m_end_insn (nullptr)
+{
+}
+
+// Construct a tree of call clobbers for the given ABI.
+inline ebb_call_clobbers_info::
+ebb_call_clobbers_info (const predefined_function_abi *abi)
+ : m_next (nullptr),
+ m_abi (abi)
+{
+}
+
+// Construct an EBB whose first block is FIRST_BB and whose last block
+// is LAST_BB.
+inline ebb_info::ebb_info (bb_info *first_bb, bb_info *last_bb)
+ : m_first_phi (nullptr),
+ m_phi_insn (nullptr),
+ m_first_bb (first_bb),
+ m_last_bb (last_bb),
+ m_first_call_clobbers (nullptr)
+{
+}
+
+// Set the contents of last_access for register REGNO to DEF.
+inline void
+function_info::build_info::record_reg_def (unsigned int regno, def_info *def)
+{
+ last_access[regno + 1] = def;
+}
+
+// Set the contents of last_access for memory to DEF.
+inline void
+function_info::build_info::record_mem_def (def_info *def)
+{
+ last_access[0] = def;
+}
+
+// Return the current value of live register REGNO, or null if the register's
+// value is completedly undefined.
+inline set_info *
+function_info::build_info::current_reg_value (unsigned int regno) const
+{
+ return safe_dyn_cast<set_info *> (last_access[regno + 1]);
+}
+
+// Return the current value of memory.
+inline set_info *
+function_info::build_info::current_mem_value () const
+{
+ return as_a<set_info *> (last_access[0]);
+}
+
+// Allocate a T on the function's main obstack, passing ARGS
+// to its constructor.
+template<typename T, typename... Ts>
+inline T *
+function_info::allocate (Ts... args)
+{
+ static_assert (std::is_trivially_destructible<T>::value,
+ "destructor won't be called");
+ static_assert (alignof (T) <= obstack_alignment,
+ "too much alignment required");
+ void *addr = obstack_alloc (&m_obstack, sizeof (T));
+ return new (addr) T (std::forward<Ts> (args)...);
+}
+
+// Allocate a T on the function's temporary obstack, passing ARGS
+// to its constructor.
+template<typename T, typename... Ts>
+inline T *
+function_info::allocate_temp (Ts... args)
+{
+ static_assert (std::is_trivially_destructible<T>::value,
+ "destructor won't be called");
+ static_assert (alignof (T) <= obstack_alignment,
+ "too much alignment required");
+ void *addr = obstack_alloc (&m_temp_obstack, sizeof (T));
+ return new (addr) T (std::forward<Ts> (args)...);
+}
+
+// Add INSN to the end of the function's list of instructions.
+inline void
+function_info::append_insn (insn_info *insn)
+{
+ gcc_checking_assert (!insn->has_insn_links ());
+ if (insn_info *after = m_last_insn)
+ add_insn_after (insn, after);
+ else
+ // The first instruction is for the entry block and is always a nondebug
+ // insn
+ m_first_insn = m_last_insn = m_last_nondebug_insn = insn;
+}
+
+// Start building a new list of uses and definitions for an instruction.
+inline void
+function_info::start_insn_accesses ()
+{
+ gcc_checking_assert (m_temp_defs.is_empty ()
+ && m_temp_uses.is_empty ());
+}
+
+// Return a mode that encapsulates two distinct references to a register,
+// one with mode MODE1 and one with mode MODE2. Treat BLKmode as a
+// "don't know" wildcard.
+inline machine_mode
+combine_modes (machine_mode mode1, machine_mode mode2)
+{
+ if (mode1 == E_BLKmode)
+ return mode2;
+
+ if (mode2 == E_BLKmode)
+ return mode1;
+
+ return wider_subreg_mode (mode1, mode2);
+}
+
+// PRINTER (PP, ARGS...) prints ARGS... to a pretty_printer PP. Use it
+// to print ARGS... to FILE.
+template<typename Printer, typename... Args>
+inline void
+dump_using (FILE *file, Printer printer, Args... args)
+{
+ pretty_printer pp;
+ printer (&pp, args...);
+ pp_newline (&pp);
+ fprintf (file, "%s", pp_formatted_text (&pp));
+}
+
+}
diff --git a/gcc/rtl-ssa/is-a.inl b/gcc/rtl-ssa/is-a.inl
new file mode 100644
index 0000000..14e1316
--- /dev/null
+++ b/gcc/rtl-ssa/is-a.inl
@@ -0,0 +1,98 @@
+// is_a<> support for RTL SSA classes -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+template<>
+struct is_a_helper<rtl_ssa::def_info *>
+ : static_is_a_helper<rtl_ssa::def_info *>
+{
+ static inline bool
+ test (const rtl_ssa::access_info *ref)
+ {
+ return (ref->kind () == rtl_ssa::access_kind::SET
+ || ref->kind () == rtl_ssa::access_kind::PHI
+ || ref->kind () == rtl_ssa::access_kind::CLOBBER);
+ }
+};
+
+template<>
+struct is_a_helper<rtl_ssa::clobber_info *>
+ : static_is_a_helper<rtl_ssa::clobber_info *>
+{
+ static inline bool
+ test (const rtl_ssa::access_info *ref)
+ {
+ return ref->kind () == rtl_ssa::access_kind::CLOBBER;
+ }
+};
+
+template<>
+struct is_a_helper<rtl_ssa::use_info *>
+ : static_is_a_helper<rtl_ssa::use_info *>
+{
+ static inline bool
+ test (const rtl_ssa::access_info *ref)
+ {
+ return ref->kind () == rtl_ssa::access_kind::USE;
+ }
+};
+
+template<>
+struct is_a_helper<rtl_ssa::set_info *>
+ : static_is_a_helper<rtl_ssa::set_info *>
+{
+ static inline bool
+ test (const rtl_ssa::access_info *ref)
+ {
+ return (ref->kind () == rtl_ssa::access_kind::SET
+ || ref->kind () == rtl_ssa::access_kind::PHI);
+ }
+};
+
+template<>
+struct is_a_helper<rtl_ssa::phi_info *>
+ : static_is_a_helper<rtl_ssa::phi_info *>
+{
+ static inline bool
+ test (const rtl_ssa::access_info *ref)
+ {
+ return ref->kind () == rtl_ssa::access_kind::PHI;
+ }
+};
+
+template<>
+struct is_a_helper<rtl_ssa::set_node *>
+ : static_is_a_helper<rtl_ssa::set_node *>
+{
+ static inline bool
+ test (const rtl_ssa::def_node *node)
+ {
+ return node->contains_set ();
+ }
+};
+
+template<>
+struct is_a_helper<rtl_ssa::clobber_group *>
+ : static_is_a_helper<rtl_ssa::clobber_group *>
+{
+ static inline bool
+ test (const rtl_ssa::def_node *node)
+ {
+ return node->contains_clobber ();
+ }
+};
diff --git a/gcc/rtl-ssa/member-fns.inl b/gcc/rtl-ssa/member-fns.inl
new file mode 100644
index 0000000..4f3bb2e
--- /dev/null
+++ b/gcc/rtl-ssa/member-fns.inl
@@ -0,0 +1,928 @@
+// Implementation of public inline member functions for RTL SSA -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// This file contains inline implementations of public member functions that
+// are too large to be written in the class definition. It also contains
+// some non-inline template definitions of public member functions.
+// See the comments above the function declarations for details.
+//
+// The file also contains the bare minimum of private and protected inline
+// member functions that are needed to make the public functions compile.
+namespace rtl_ssa {
+
+inline void
+access_array_builder::reserve (unsigned int num_accesses)
+{
+ obstack_make_room (m_obstack, num_accesses * sizeof (access_info *));
+}
+
+inline void
+access_array_builder::quick_push (access_info *access)
+{
+ obstack_ptr_grow_fast (m_obstack, access);
+}
+
+inline array_slice<access_info *>
+access_array_builder::finish ()
+{
+ auto num_accesses = obstack_object_size (m_obstack) / sizeof (access_info *);
+ if (num_accesses == 0)
+ return {};
+
+ auto **base = static_cast<access_info **> (obstack_finish (m_obstack));
+ keep ();
+ return { base, num_accesses };
+}
+
+inline bool
+access_info::is_set_with_nondebug_insn_uses () const
+{
+ return m_is_set_with_nondebug_insn_uses;
+}
+
+inline bool
+use_info::is_in_debug_insn () const
+{
+ return m_insn_or_phi.is_first () && m_is_in_debug_insn_or_phi;
+}
+
+inline bb_info *
+use_info::bb () const
+{
+ if (m_insn_or_phi.is_first ())
+ return m_insn_or_phi.known_first ()->bb ();
+ return m_insn_or_phi.known_second ()->bb ();
+}
+
+inline ebb_info *
+use_info::ebb () const
+{
+ return bb ()->ebb ();
+}
+
+inline use_info *
+use_info::prev_use () const
+{
+ return m_last_use_or_prev_use.second_or_null ();
+}
+
+inline use_info *
+use_info::next_use () const
+{
+ return m_last_nondebug_insn_use_or_next_use.second_or_null ();
+}
+
+inline bool
+use_info::is_first_use () const
+{
+ return m_last_use_or_prev_use.is_first ();
+}
+
+inline bool
+use_info::is_last_use () const
+{
+ return m_last_nondebug_insn_use_or_next_use.is_first ();
+}
+
+inline use_info *
+use_info::next_nondebug_insn_use () const
+{
+ if (m_is_last_nondebug_insn_use)
+ return nullptr;
+ return m_last_nondebug_insn_use_or_next_use.known_second ();
+}
+
+inline use_info *
+use_info::next_any_insn_use () const
+{
+ // This is used less often than next_nondebug_insn_use, so it doesn't
+ // seem worth having an m_is_last_nondebug_insn_use-style end marker.
+ if (use_info *use = next_use ())
+ if (use->is_in_any_insn ())
+ return use;
+ return nullptr;
+}
+
+inline use_info *
+use_info::prev_phi_use () const
+{
+ // This is used less often than next_nondebug_insn_use, so it doesn't
+ // seem worth having an m_is_last_nondebug_insn_use-style end marker.
+ if (use_info *use = prev_use ())
+ if (use->is_in_phi ())
+ return use;
+ return nullptr;
+}
+
+// Return the last use of any kind in the list. Only valid when is_first ()
+// is true.
+inline use_info *
+use_info::last_use () const
+{
+ return m_last_use_or_prev_use.known_first ();
+}
+
+// Return the last nondebug insn use in the list, or null if none. Only valid
+// when is_last_use () is true.
+inline use_info *
+use_info::last_nondebug_insn_use () const
+{
+ return m_last_nondebug_insn_use_or_next_use.known_first ();
+}
+
+inline def_info *
+def_info::prev_def () const
+{
+ return m_last_def_or_prev_def.second_or_null ();
+}
+
+inline def_info *
+def_info::next_def () const
+{
+ return m_splay_root_or_next_def.second_or_null ();
+}
+
+inline bool
+def_info::is_first_def () const
+{
+ return m_last_def_or_prev_def.is_first ();
+}
+
+inline bool
+def_info::is_last_def () const
+{
+ return m_splay_root_or_next_def.is_first ();
+}
+
+inline bb_info *
+def_info::bb () const
+{
+ return m_insn->bb ();
+}
+
+inline ebb_info *
+def_info::ebb () const
+{
+ return m_insn->ebb ();
+}
+
+inline clobber_group *
+clobber_info::group () const
+{
+ if (!m_group || !m_group->has_been_superceded ())
+ return m_group;
+ return const_cast<clobber_info *> (this)->recompute_group ();
+}
+
+inline use_info *
+set_info::last_use () const
+{
+ return m_first_use ? m_first_use->last_use () : nullptr;
+}
+
+inline use_info *
+set_info::first_nondebug_insn_use () const
+{
+ if (m_is_set_with_nondebug_insn_uses)
+ return m_first_use;
+ return nullptr;
+}
+
+inline use_info *
+set_info::last_nondebug_insn_use () const
+{
+ if (m_is_set_with_nondebug_insn_uses)
+ return m_first_use->last_use ()->last_nondebug_insn_use ();
+ return nullptr;
+}
+
+inline use_info *
+set_info::first_any_insn_use () const
+{
+ if (m_first_use->is_in_any_insn ())
+ return m_first_use;
+ return nullptr;
+}
+
+inline use_info *
+set_info::last_phi_use () const
+{
+ if (m_first_use)
+ {
+ use_info *last = m_first_use->last_use ();
+ if (last->is_in_phi ())
+ return last;
+ }
+ return nullptr;
+}
+
+inline bool
+set_info::has_nondebug_uses () const
+{
+ return has_nondebug_insn_uses () || has_phi_uses ();
+}
+
+inline bool
+set_info::has_nondebug_insn_uses () const
+{
+ return m_is_set_with_nondebug_insn_uses;
+}
+
+inline bool
+set_info::has_phi_uses () const
+{
+ return m_first_use && m_first_use->last_use ()->is_in_phi ();
+}
+
+inline bool
+set_info::is_local_to_ebb () const
+{
+ if (!m_first_use)
+ return true;
+
+ use_info *last = m_first_use->last_use ();
+ if (last->is_in_phi ())
+ return false;
+
+ last = last->last_nondebug_insn_use ();
+ return !last || last->ebb () == ebb ();
+}
+
+inline iterator_range<use_iterator>
+set_info::all_uses () const
+{
+ return { m_first_use, nullptr };
+}
+
+inline iterator_range<reverse_use_iterator>
+set_info::reverse_all_uses () const
+{
+ return { last_use (), nullptr };
+}
+
+inline iterator_range<nondebug_insn_use_iterator>
+set_info::nondebug_insn_uses () const
+{
+ return { first_nondebug_insn_use (), nullptr };
+}
+
+inline iterator_range<reverse_use_iterator>
+set_info::reverse_nondebug_insn_uses () const
+{
+ return { last_nondebug_insn_use (), nullptr };
+}
+
+inline iterator_range<any_insn_use_iterator>
+set_info::all_insn_uses () const
+{
+ return { first_any_insn_use (), nullptr };
+}
+
+inline iterator_range<phi_use_iterator>
+set_info::phi_uses () const
+{
+ return { last_phi_use (), nullptr };
+}
+
+inline use_array
+phi_info::inputs () const
+{
+ if (m_num_inputs == 1)
+ return use_array (&m_single_input, 1);
+ return use_array (m_inputs, m_num_inputs);
+}
+
+inline use_info *
+phi_info::input_use (unsigned int i) const
+{
+ if (m_num_inputs == 1)
+ return as_a<use_info *> (m_single_input);
+ return as_a<use_info *> (m_inputs[i]);
+}
+
+inline set_info *
+phi_info::input_value (unsigned int i) const
+{
+ return input_use (i)->def ();
+}
+
+inline def_info *
+def_node::first_def () const
+{
+ // This should get optimized into an AND with -2.
+ if (m_clobber_or_set.is_first ())
+ return m_clobber_or_set.known_first ();
+ return m_clobber_or_set.known_second ();
+}
+
+inline clobber_info *
+clobber_group::first_clobber () const
+{
+ return m_clobber_or_set.known_first ();
+}
+
+inline iterator_range<def_iterator>
+clobber_group::clobbers () const
+{
+ return { first_clobber (), m_last_clobber->next_def () };
+}
+
+inline def_info *
+def_mux::first_def () const
+{
+ if (is_first ())
+ return known_first ();
+ return known_second ()->first_def ();
+}
+
+inline def_info *
+def_mux::last_def () const
+{
+ if (is_first ())
+ return known_first ();
+
+ def_node *node = known_second ();
+ if (auto *clobber = ::dyn_cast<clobber_group *> (node))
+ return clobber->last_clobber ();
+
+ return node->first_def ();
+}
+
+inline set_info *
+def_mux::set () const
+{
+ if (is_first ())
+ return ::safe_dyn_cast<set_info *> (known_first ());
+ return ::dyn_cast<set_info *> (known_second ()->first_def ());
+}
+
+inline def_info *
+def_lookup::prev_def () const
+{
+ if (!mux)
+ return nullptr;
+
+ if (comparison > 0)
+ return mux.last_def ();
+
+ return mux.first_def ()->prev_def ();
+}
+
+inline def_info *
+def_lookup::next_def () const
+{
+ if (!mux)
+ return nullptr;
+
+ if (comparison < 0)
+ return mux.first_def ();
+
+ return mux.last_def ()->next_def ();
+}
+
+inline set_info *
+def_lookup::matching_set () const
+{
+ if (comparison == 0)
+ return mux.set ();
+ return nullptr;
+}
+
+inline def_info *
+def_lookup::matching_or_prev_def () const
+{
+ if (set_info *set = matching_set ())
+ return set;
+ return prev_def ();
+}
+
+inline def_info *
+def_lookup::matching_or_next_def () const
+{
+ if (set_info *set = matching_set ())
+ return set;
+ return next_def ();
+}
+
+inline insn_note::insn_note (insn_note_kind kind)
+ : m_next_note (nullptr),
+ m_kind (kind),
+ m_data8 (0),
+ m_data16 (0),
+ m_data32 (0)
+{
+}
+
+template<typename T>
+inline T
+insn_note::as_a ()
+{
+ using deref_type = decltype (*std::declval<T> ());
+ using derived = typename std::remove_reference<deref_type>::type;
+ gcc_checking_assert (m_kind == derived::kind);
+ return static_cast<T> (this);
+}
+
+template<typename T>
+inline T
+insn_note::dyn_cast ()
+{
+ using deref_type = decltype (*std::declval<T> ());
+ using derived = typename std::remove_reference<deref_type>::type;
+ if (m_kind == derived::kind)
+ return static_cast<T> (this);
+ return nullptr;
+}
+
+inline bool
+insn_info::operator< (const insn_info &other) const
+{
+ if (this == &other)
+ return false;
+
+ if (__builtin_expect (m_point != other.m_point, 1))
+ return m_point < other.m_point;
+
+ return slow_compare_with (other) < 0;
+}
+
+inline bool
+insn_info::operator> (const insn_info &other) const
+{
+ return other < *this;
+}
+
+inline bool
+insn_info::operator<= (const insn_info &other) const
+{
+ return !(other < *this);
+}
+
+inline bool
+insn_info::operator>= (const insn_info &other) const
+{
+ return !(*this < other);
+}
+
+inline int
+insn_info::compare_with (const insn_info *other) const
+{
+ if (this == other)
+ return 0;
+
+ if (__builtin_expect (m_point != other->m_point, 1))
+ // Assume that points remain in [0, INT_MAX].
+ return m_point - other->m_point;
+
+ return slow_compare_with (*other);
+}
+
+inline insn_info *
+insn_info::prev_nondebug_insn () const
+{
+ gcc_checking_assert (!is_debug_insn ());
+ return m_prev_insn_or_last_debug_insn.known_first ();
+}
+
+inline insn_info *
+insn_info::next_nondebug_insn () const
+{
+ gcc_checking_assert (!is_debug_insn ());
+ const insn_info *from = this;
+ if (insn_info *first_debug = m_next_nondebug_or_debug_insn.second_or_null ())
+ from = first_debug->last_debug_insn ();
+ return from->m_next_nondebug_or_debug_insn.known_first ();
+}
+
+inline insn_info *
+insn_info::prev_any_insn () const
+{
+ const insn_info *from = this;
+ if (insn_info *last_debug = m_prev_insn_or_last_debug_insn.second_or_null ())
+ // This instruction is the first in a subsequence of debug instructions.
+ // Move to the following nondebug instruction.
+ from = last_debug->m_next_nondebug_or_debug_insn.known_first ();
+ return from->m_prev_insn_or_last_debug_insn.known_first ();
+}
+
+inline insn_info *
+insn_info::next_any_insn () const
+{
+ // This should get optimized into an AND with -2.
+ if (m_next_nondebug_or_debug_insn.is_first ())
+ return m_next_nondebug_or_debug_insn.known_first ();
+ return m_next_nondebug_or_debug_insn.known_second ();
+}
+
+inline bool
+insn_info::is_phi () const
+{
+ return this == ebb ()->phi_insn ();
+}
+
+inline bool
+insn_info::is_bb_head () const
+{
+ return this == m_bb->head_insn ();
+}
+
+inline bool
+insn_info::is_bb_end () const
+{
+ return this == m_bb->end_insn ();
+}
+
+inline ebb_info *
+insn_info::ebb () const
+{
+ return m_bb->ebb ();
+}
+
+inline int
+insn_info::uid () const
+{
+ return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (m_rtl);
+}
+
+inline use_array
+insn_info::uses () const
+{
+ return use_array (m_accesses + m_num_defs, m_num_uses);
+}
+
+inline bool
+insn_info::has_call_clobbers () const
+{
+ return find_note<insn_call_clobbers_note> ();
+}
+
+inline def_array
+insn_info::defs () const
+{
+ return def_array (m_accesses, m_num_defs);
+}
+
+inline unsigned int
+insn_info::cost () const
+{
+ if (m_cost_or_uid < 0)
+ return 0;
+ if (m_cost_or_uid == UNKNOWN_COST)
+ calculate_cost ();
+ return m_cost_or_uid;
+}
+
+template<typename T>
+inline const T *
+insn_info::find_note () const
+{
+ // We could break if the note kind is > T::kind, but since the number
+ // of notes should be very small, the check is unlikely to pay for itself.
+ for (const insn_note *note = first_note (); note; note = note->next_note ())
+ if (note->kind () == T::kind)
+ return static_cast<const T *> (note);
+ return nullptr;
+}
+
+// Only valid for debug instructions that come after a nondebug instruction,
+// and so start a subsequence of debug instructions. Return the last debug
+// instruction in the subsequence.
+inline insn_info *
+insn_info::last_debug_insn () const
+{
+ return m_prev_insn_or_last_debug_insn.known_second ();
+}
+
+inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
+ : first (first), last (last)
+{
+}
+
+inline bool
+insn_range_info::operator== (const insn_range_info &other) const
+{
+ return first == other.first && last == other.last;
+}
+
+inline bool
+insn_range_info::operator!= (const insn_range_info &other) const
+{
+ return first != other.first || last != other.last;
+}
+
+inline insn_info *
+insn_range_info::singleton () const
+{
+ return first == last ? last : nullptr;
+}
+
+inline bool
+insn_range_info::includes (insn_info *insn) const
+{
+ return *insn >= *first && *insn <= *last;
+}
+
+inline insn_info *
+insn_range_info::clamp_insn_to_range (insn_info *insn) const
+{
+ if (*first > *insn)
+ return first;
+ if (*last < *insn)
+ return last;
+ return insn;
+}
+
+inline bool
+insn_range_info::is_subrange_of (const insn_range_info &other) const
+{
+ return *first >= *other.first && *last <= *other.last;
+}
+
+inline iterator_range<any_insn_iterator>
+bb_info::all_insns () const
+{
+ return { m_head_insn, m_end_insn->next_any_insn () };
+}
+
+inline iterator_range<reverse_any_insn_iterator>
+bb_info::reverse_all_insns () const
+{
+ return { m_end_insn, m_head_insn->prev_any_insn () };
+}
+
+inline iterator_range<nondebug_insn_iterator>
+bb_info::nondebug_insns () const
+{
+ return { m_head_insn, m_end_insn->next_nondebug_insn () };
+}
+
+inline iterator_range<reverse_nondebug_insn_iterator>
+bb_info::reverse_nondebug_insns () const
+{
+ return { m_end_insn, m_head_insn->prev_nondebug_insn () };
+}
+
+inline iterator_range<any_insn_iterator>
+bb_info::real_insns () const
+{
+ return { m_head_insn->next_any_insn (), m_end_insn };
+}
+
+inline iterator_range<reverse_any_insn_iterator>
+bb_info::reverse_real_insns () const
+{
+ return { m_end_insn->prev_any_insn (), m_head_insn };
+}
+
+inline iterator_range<nondebug_insn_iterator>
+bb_info::real_nondebug_insns () const
+{
+ return { m_head_insn->next_nondebug_insn (), m_end_insn };
+}
+
+inline iterator_range<reverse_nondebug_insn_iterator>
+bb_info::reverse_real_nondebug_insns () const
+{
+ return { m_end_insn->prev_nondebug_insn (), m_head_insn };
+}
+
+inline bool
+ebb_call_clobbers_info::clobbers (resource_info resource) const
+{
+ // Only register clobbers are tracked this way. Other clobbers are
+ // recorded explicitly.
+ return (resource.is_reg ()
+ && m_abi->clobbers_reg_p (resource.mode, resource.regno));
+}
+
+inline ebb_info *
+ebb_info::prev_ebb () const
+{
+ if (bb_info *prev_bb = m_first_bb->prev_bb ())
+ return prev_bb->ebb ();
+ return nullptr;
+}
+
+inline ebb_info *
+ebb_info::next_ebb () const
+{
+ if (bb_info *next_bb = m_last_bb->next_bb ())
+ return next_bb->ebb ();
+ return nullptr;
+}
+
+inline iterator_range<phi_iterator>
+ebb_info::phis () const
+{
+ return { m_first_phi, nullptr };
+}
+
+inline iterator_range<bb_iterator>
+ebb_info::bbs () const
+{
+ return { m_first_bb, m_last_bb->next_bb () };
+}
+
+inline iterator_range<reverse_bb_iterator>
+ebb_info::reverse_bbs () const
+{
+ return { m_last_bb, m_first_bb->prev_bb () };
+}
+
+inline iterator_range<any_insn_iterator>
+ebb_info::all_insns () const
+{
+ return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
+}
+
+inline iterator_range<reverse_any_insn_iterator>
+ebb_info::reverse_all_insns () const
+{
+ return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
+}
+
+inline iterator_range<nondebug_insn_iterator>
+ebb_info::nondebug_insns () const
+{
+ return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
+}
+
+inline iterator_range<reverse_nondebug_insn_iterator>
+ebb_info::reverse_nondebug_insns () const
+{
+ return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
+}
+
+inline insn_range_info
+ebb_info::insn_range () const
+{
+ return { m_phi_insn, m_last_bb->end_insn () };
+}
+
+inline void
+ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
+{
+ m_first_call_clobbers = call_clobbers;
+}
+
+inline ebb_call_clobbers_info *
+ebb_info::first_call_clobbers () const
+{
+ return m_first_call_clobbers;
+}
+
+inline iterator_range<ebb_call_clobbers_iterator>
+ebb_info::call_clobbers () const
+{
+ return { m_first_call_clobbers, nullptr };
+}
+
+inline insn_change::insn_change (insn_info *insn)
+ : m_insn (insn),
+ new_defs (insn->defs ()),
+ new_uses (insn->uses ()),
+ move_range (insn),
+ new_cost (UNKNOWN_COST),
+ m_is_deletion (false)
+{
+}
+
+inline insn_change::insn_change (insn_info *insn, delete_action)
+ : m_insn (insn),
+ new_defs (),
+ new_uses (),
+ move_range (insn),
+ new_cost (0),
+ m_is_deletion (true)
+{
+}
+
+inline insn_is_changing_closure::
+insn_is_changing_closure (array_slice<insn_change *const> changes)
+ : m_changes (changes)
+{
+}
+
+inline bool
+insn_is_changing_closure::operator() (const insn_info *insn) const
+{
+ for (const insn_change *change : m_changes)
+ if (change->insn () == insn)
+ return true;
+ return false;
+}
+
+inline iterator_range<bb_iterator>
+function_info::bbs () const
+{
+ return { m_first_bb, nullptr };
+}
+
+inline iterator_range<reverse_bb_iterator>
+function_info::reverse_bbs () const
+{
+ return { m_last_bb, nullptr };
+}
+
+inline iterator_range<ebb_iterator>
+function_info::ebbs () const
+{
+ return { m_first_bb->ebb (), nullptr };
+}
+
+inline iterator_range<reverse_ebb_iterator>
+function_info::reverse_ebbs () const
+{
+ return { m_last_bb->ebb (), nullptr };
+}
+
+inline iterator_range<any_insn_iterator>
+function_info::all_insns () const
+{
+ return { m_first_insn, nullptr };
+}
+
+inline iterator_range<reverse_any_insn_iterator>
+function_info::reverse_all_insns () const
+{
+ return { m_last_insn, nullptr };
+}
+
+inline iterator_range<nondebug_insn_iterator>
+function_info::nondebug_insns () const
+{
+ return { m_first_insn, nullptr };
+}
+
+inline iterator_range<reverse_nondebug_insn_iterator>
+function_info::reverse_nondebug_insns () const
+{
+ return { m_last_insn, nullptr };
+}
+
+inline iterator_range<def_iterator>
+function_info::mem_defs () const
+{
+ return { m_defs[0], nullptr };
+}
+
+inline iterator_range<def_iterator>
+function_info::ref_defs (unsigned int regno) const
+{
+ return { m_defs[regno + 1], nullptr };
+}
+
+inline set_info *
+function_info::single_dominating_def (unsigned int regno) const
+{
+ if (set_info *set = safe_dyn_cast<set_info *> (m_defs[regno + 1]))
+ if (is_single_dominating_def (set))
+ return set;
+ return nullptr;
+}
+
+template<typename IgnorePredicate>
+bool
+function_info::add_regno_clobber (obstack_watermark &watermark,
+ insn_change &change, unsigned int regno,
+ IgnorePredicate ignore)
+{
+ // Check whether CHANGE already clobbers REGNO.
+ if (find_access (change.new_defs, regno))
+ return true;
+
+ // Get the closest position to INSN at which the new instruction
+ // could be placed.
+ insn_info *insn = change.move_range.clamp_insn_to_range (change.insn ());
+ def_array new_defs = insert_temp_clobber (watermark, insn, regno,
+ change.new_defs);
+ if (!new_defs.is_valid ())
+ return false;
+
+ // Find a definition at or neighboring INSN.
+ insn_range_info move_range = change.move_range;
+ if (!restrict_movement_for_dead_range (move_range, regno, insn, ignore))
+ return false;
+
+ change.new_defs = new_defs;
+ change.move_range = move_range;
+ return true;
+}
+
+}
diff --git a/gcc/rtl-ssa/movement.h b/gcc/rtl-ssa/movement.h
new file mode 100644
index 0000000..3b0cbf9
--- /dev/null
+++ b/gcc/rtl-ssa/movement.h
@@ -0,0 +1,335 @@
+// RTL SSA utilities relating to instruction movement -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+namespace rtl_ssa {
+
+// Restrict movement range RANGE so that the instruction is placed later
+// than INSN. (The movement range is the range of instructions after which
+// an instruction can be placed.)
+inline insn_range_info
+move_later_than (insn_range_info range, insn_info *insn)
+{
+ return { later_insn (range.first, insn), range.last };
+}
+
+// Restrict movement range RANGE so that the instruction is placed no earlier
+// than INSN. (The movement range is the range of instructions after which
+// an instruction can be placed.)
+inline insn_range_info
+move_no_earlier_than (insn_range_info range, insn_info *insn)
+{
+ insn_info *first = later_insn (range.first, insn->prev_nondebug_insn ());
+ return { first, range.last };
+}
+
+// Restrict movement range RANGE so that the instruction is placed no later
+// than INSN. (The movement range is the range of instructions after which
+// an instruction can be placed.)
+inline insn_range_info
+move_no_later_than (insn_range_info range, insn_info *insn)
+{
+ return { range.first, earlier_insn (range.last, insn) };
+}
+
+// Restrict movement range RANGE so that the instruction is placed earlier
+// than INSN. (The movement range is the range of instructions after which
+// an instruction can be placed.)
+inline insn_range_info
+move_earlier_than (insn_range_info range, insn_info *insn)
+{
+ insn_info *last = earlier_insn (range.last, insn->prev_nondebug_insn ());
+ return { range.first, last };
+}
+
+// Return true if it is possible to insert a new instruction after INSN.
+inline bool
+can_insert_after (insn_info *insn)
+{
+ return insn->is_bb_head () || (insn->is_real () && !insn->is_jump ());
+}
+
+// Try to restrict move range MOVE_RANGE so that it is possible to
+// insert INSN after both of the end points. Return true on success,
+// otherwise leave MOVE_RANGE in an invalid state.
+inline bool
+canonicalize_move_range (insn_range_info &move_range, insn_info *insn)
+{
+ while (move_range.first != insn && !can_insert_after (move_range.first))
+ move_range.first = move_range.first->next_nondebug_insn ();
+ while (move_range.last != insn && !can_insert_after (move_range.last))
+ move_range.last = move_range.last->prev_nondebug_insn ();
+ return bool (move_range);
+}
+
+// Try to restrict movement range MOVE_RANGE of INSN so that it can set
+// or clobber REGNO. Assume that if:
+//
+// - an instruction I2 contains another access A to REGNO; and
+// - IGNORE (I2) is true
+//
+// then either:
+//
+// - A will be removed; or
+// - something will ensure that the new definition of REGNO does not
+// interfere with A, without this having to be enforced by I1's move range.
+//
+// Return true on success, otherwise leave MOVE_RANGE in an invalid state.
+//
+// This function only works correctly for instructions that remain within
+// the same extended basic block.
+template<typename IgnorePredicate>
+bool
+restrict_movement_for_dead_range (insn_range_info &move_range,
+ unsigned int regno, insn_info *insn,
+ IgnorePredicate ignore)
+{
+ // Find a definition at or neighboring INSN.
+ resource_info resource = full_register (regno);
+ def_lookup dl = crtl->ssa->find_def (resource, insn);
+
+ def_info *prev = dl.prev_def ();
+ ebb_info *ebb = insn->ebb ();
+ if (!prev || prev->ebb () != ebb)
+ {
+ // REGNO is not defined or used in EBB before INSN, but it
+ // might be live on entry. To keep complexity under control,
+ // handle only these cases:
+ //
+ // - If the register is not live on entry to EBB, the register is
+ // free from the start of EBB to the first definition in EBB.
+ //
+ // - Otherwise, if the register is live on entry to BB, refuse
+ // to allocate the register. We could in principle try to move
+ // the instruction to later blocks in the EBB, but it's rarely
+ // worth the effort, and could lead to linear complexity.
+ //
+ // - Otherwise, don't allow INSN to move earlier than its current
+ // block. Again, we could in principle look backwards to find where
+ // REGNO dies, but it's rarely worth the effort.
+ bb_info *bb = insn->bb ();
+ insn_info *limit;
+ if (!bitmap_bit_p (DF_LR_IN (ebb->first_bb ()->cfg_bb ()), regno))
+ limit = ebb->phi_insn ();
+ else if (bitmap_bit_p (DF_LR_IN (bb->cfg_bb ()), regno))
+ return false;
+ else
+ limit = bb->head_insn ();
+ move_range = move_later_than (move_range, limit);
+ }
+ else
+ {
+ // Stop the instruction moving beyond the previous relevant access
+ // to REGNO.
+ access_info *prev_access
+ = last_access_ignoring (prev, ignore_clobbers::YES, ignore);
+ if (prev_access)
+ move_range = move_later_than (move_range, access_insn (prev_access));
+ }
+
+ // Stop the instruction moving beyond the next relevant definition of REGNO.
+ def_info *next = first_def_ignoring (dl.matching_or_next_def (),
+ ignore_clobbers::YES, ignore);
+ if (next)
+ move_range = move_earlier_than (move_range, next->insn ());
+
+ return canonicalize_move_range (move_range, insn);
+}
+
+// Try to restrict movement range MOVE_RANGE so that it is possible for the
+// instruction being moved ("instruction I1") to perform all the definitions
+// in DEFS while still preserving dependencies between those definitions
+// and surrounding instructions. Assume that if:
+//
+// - DEFS contains a definition D of resource R;
+// - an instruction I2 contains another access A to R; and
+// - IGNORE (I2) is true
+//
+// then either:
+//
+// - A will be removed; or
+// - something will ensure that D and A maintain their current order,
+// without this having to be enforced by I1's move range.
+//
+// Return true on success, otherwise leave MOVE_RANGE in an invalid state.
+//
+// This function only works correctly for instructions that remain within
+// the same extended basic block.
+template<typename IgnorePredicate>
+bool
+restrict_movement_for_defs_ignoring (insn_range_info &move_range,
+ def_array defs, IgnorePredicate ignore)
+{
+ for (def_info *def : defs)
+ {
+ // If the definition is a clobber, we can move it with respect
+ // to other clobbers.
+ //
+ // ??? We could also do this if a definition and all its uses
+ // are being moved at once.
+ bool is_clobber = is_a<clobber_info *> (def);
+
+ // Search back for the first unfiltered use or definition of the
+ // same resource.
+ access_info *access;
+ access = prev_access_ignoring (def, ignore_clobbers (is_clobber),
+ ignore);
+ if (access)
+ move_range = move_later_than (move_range, access_insn (access));
+
+ // Search forward for the first unfiltered use of DEF,
+ // or the first unfiltered definition that follows DEF.
+ //
+ // We don't need to consider uses of following definitions, since
+ // if IGNORE (D->insn ()) is true for some definition D, the caller
+ // is guarantees that either
+ //
+ // - D will be removed, and thus its uses will be removed; or
+ // - D will occur after DEF, and thus D's uses will also occur
+ // after DEF.
+ //
+ // This is purely a simplification: we could also process D's uses,
+ // but we don't need to.
+ access = next_access_ignoring (def, ignore_clobbers (is_clobber),
+ ignore);
+ if (access)
+ move_range = move_earlier_than (move_range, access_insn (access));
+
+ // If DEF sets a hard register, take any call clobbers
+ // into account.
+ unsigned int regno = def->regno ();
+ if (!HARD_REGISTER_NUM_P (regno) || is_clobber)
+ continue;
+
+ ebb_info *ebb = def->ebb ();
+ for (ebb_call_clobbers_info *call_group : ebb->call_clobbers ())
+ {
+ if (!call_group->clobbers (def->resource ()))
+ continue;
+
+ // Exit now if we've already failed, and if the splay accesses
+ // below would be wasted work.
+ if (!move_range)
+ return false;
+
+ insn_info *insn;
+ insn = prev_call_clobbers_ignoring (*call_group, def->insn (),
+ ignore);
+ if (insn)
+ move_range = move_later_than (move_range, insn);
+
+ insn = next_call_clobbers_ignoring (*call_group, def->insn (),
+ ignore);
+ if (insn)
+ move_range = move_earlier_than (move_range, insn);
+ }
+ }
+
+ // Make sure that we don't move stores between basic blocks, since we
+ // don't have enough information to tell whether it's safe.
+ if (def_info *def = memory_access (defs))
+ {
+ move_range = move_later_than (move_range, def->bb ()->head_insn ());
+ move_range = move_earlier_than (move_range, def->bb ()->end_insn ());
+ }
+
+ return bool (move_range);
+}
+
+// Like restrict_movement_for_defs_ignoring, but for the uses in USES.
+template<typename IgnorePredicate>
+bool
+restrict_movement_for_uses_ignoring (insn_range_info &move_range,
+ use_array uses, IgnorePredicate ignore)
+{
+ for (const use_info *use : uses)
+ {
+ // Ignore uses of undefined values.
+ set_info *set = use->def ();
+ if (!set)
+ continue;
+
+ // Ignore uses by debug instructions. Debug instructions are
+ // never supposed to move, and uses by debug instructions are
+ // never supposed to be transferred elsewhere, so we know that
+ // the caller must be changing the uses on the debug instruction
+ // and checking whether all new uses are available at the debug
+ // instruction's original location.
+ if (use->is_in_debug_insn ())
+ continue;
+
+ // If the used value is defined by an instruction I2 for which
+ // IGNORE (I2) is true, the caller guarantees that I2 will occur
+ // before change.insn (). Otherwise, make sure that the use occurs
+ // after the definition.
+ insn_info *insn = set->insn ();
+ if (!ignore (insn))
+ move_range = move_later_than (move_range, insn);
+
+ // Search forward for the first unfiltered definition that follows SET.
+ //
+ // We don't need to consider the uses of these definitions, since
+ // if IGNORE (D->insn ()) is true for some definition D, the caller
+ // is guarantees that either
+ //
+ // - D will be removed, and thus its uses will be removed; or
+ // - D will occur after USE, and thus D's uses will also occur
+ // after USE.
+ //
+ // This is purely a simplification: we could also process D's uses,
+ // but we don't need to.
+ def_info *def;
+ def = first_def_ignoring (set->next_def (), ignore_clobbers::NO,
+ ignore);
+ if (def)
+ move_range = move_earlier_than (move_range, def->insn ());
+
+ // If USE uses a hard register, take any call clobbers into account too.
+ // SET will necessarily occur after any previous call clobber, so we
+ // only need to check for later clobbers.
+ unsigned int regno = use->regno ();
+ if (!HARD_REGISTER_NUM_P (regno))
+ continue;
+
+ ebb_info *ebb = use->ebb ();
+ for (ebb_call_clobbers_info *call_group : ebb->call_clobbers ())
+ {
+ if (!call_group->clobbers (use->resource ()))
+ continue;
+
+ if (!move_range)
+ return false;
+
+ insn_info *insn = next_call_clobbers_ignoring (*call_group,
+ use->insn (), ignore);
+ if (insn)
+ move_range = move_earlier_than (move_range, insn);
+ }
+ }
+
+ // Make sure that we don't move loads into an earlier basic block.
+ //
+ // ??? It would be good to relax this for loads that can be safely
+ // speculated.
+ if (use_info *use = memory_access (uses))
+ move_range = move_later_than (move_range, use->bb ()->head_insn ());
+
+ return bool (move_range);
+}
+
+}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index fcec9dc..3915fae 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3375,30 +3375,143 @@ extern rtx_insn *try_split (rtx, rtx_insn *, int);
extern rtx_insn *split_insns (rtx, rtx_insn *);
/* In simplify-rtx.c */
+
+/* A class that records the context in which a simplification
+ is being mode. */
+class simplify_context
+{
+public:
+ rtx simplify_unary_operation (rtx_code, machine_mode, rtx, machine_mode);
+ rtx simplify_binary_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_ternary_operation (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_relational_operation (rtx_code, machine_mode, machine_mode,
+ rtx, rtx);
+ rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+
+ rtx lowpart_subreg (machine_mode, rtx, machine_mode);
+
+ rtx simplify_merge_mask (rtx, rtx, int);
+
+ rtx simplify_gen_unary (rtx_code, machine_mode, rtx, machine_mode);
+ rtx simplify_gen_binary (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_gen_ternary (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_gen_relational (rtx_code, machine_mode, machine_mode, rtx, rtx);
+ rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+
+ /* Tracks the level of MEM nesting for the value being simplified:
+ 0 means the value is not in a MEM, >0 means it is. This is needed
+ because the canonical representation of multiplication is different
+ inside a MEM than outside. */
+ unsigned int mem_depth = 0;
+
+private:
+ rtx simplify_truncation (machine_mode, rtx, machine_mode);
+ rtx simplify_byte_swapping_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_associative_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_distributive_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_logical_relational_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_binary_operation_series (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_distribute_over_subregs (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_shift_const_int (rtx_code, machine_mode, rtx, unsigned int);
+ rtx simplify_plus_minus (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_cond_clz_ctz (rtx, rtx_code, rtx, rtx);
+
+ rtx simplify_unary_operation_1 (rtx_code, machine_mode, rtx);
+ rtx simplify_binary_operation_1 (rtx_code, machine_mode, rtx, rtx, rtx, rtx);
+ rtx simplify_ternary_operation_1 (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_relational_operation_1 (rtx_code, machine_mode, machine_mode,
+ rtx, rtx);
+};
+
+inline rtx
+simplify_unary_operation (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
+{
+ return simplify_context ().simplify_unary_operation (code, mode, op,
+ op_mode);
+}
+
+inline rtx
+simplify_binary_operation (rtx_code code, machine_mode mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_binary_operation (code, mode, op0, op1);
+}
+
+inline rtx
+simplify_ternary_operation (rtx_code code, machine_mode mode,
+ machine_mode op0_mode, rtx op0, rtx op1, rtx op2)
+{
+ return simplify_context ().simplify_ternary_operation (code, mode, op0_mode,
+ op0, op1, op2);
+}
+
+inline rtx
+simplify_relational_operation (rtx_code code, machine_mode mode,
+ machine_mode op_mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_relational_operation (code, mode,
+ op_mode, op0, op1);
+}
+
+inline rtx
+simplify_subreg (machine_mode outermode, rtx op, machine_mode innermode,
+ poly_uint64 byte)
+{
+ return simplify_context ().simplify_subreg (outermode, op, innermode, byte);
+}
+
+inline rtx
+simplify_gen_unary (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
+{
+ return simplify_context ().simplify_gen_unary (code, mode, op, op_mode);
+}
+
+inline rtx
+simplify_gen_binary (rtx_code code, machine_mode mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_gen_binary (code, mode, op0, op1);
+}
+
+inline rtx
+simplify_gen_ternary (rtx_code code, machine_mode mode, machine_mode op0_mode,
+ rtx op0, rtx op1, rtx op2)
+{
+ return simplify_context ().simplify_gen_ternary (code, mode, op0_mode,
+ op0, op1, op2);
+}
+
+inline rtx
+simplify_gen_relational (rtx_code code, machine_mode mode,
+ machine_mode op_mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_gen_relational (code, mode, op_mode,
+ op0, op1);
+}
+
+inline rtx
+simplify_gen_subreg (machine_mode outermode, rtx op, machine_mode innermode,
+ poly_uint64 byte)
+{
+ return simplify_context ().simplify_gen_subreg (outermode, op,
+ innermode, byte);
+}
+
+inline rtx
+lowpart_subreg (machine_mode outermode, rtx op, machine_mode innermode)
+{
+ return simplify_context ().lowpart_subreg (outermode, op, innermode);
+}
+
extern rtx simplify_const_unary_operation (enum rtx_code, machine_mode,
rtx, machine_mode);
-extern rtx simplify_unary_operation (enum rtx_code, machine_mode, rtx,
- machine_mode);
extern rtx simplify_const_binary_operation (enum rtx_code, machine_mode,
rtx, rtx);
-extern rtx simplify_binary_operation (enum rtx_code, machine_mode, rtx,
- rtx);
-extern rtx simplify_ternary_operation (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx, rtx);
extern rtx simplify_const_relational_operation (enum rtx_code,
machine_mode, rtx, rtx);
-extern rtx simplify_relational_operation (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx);
-extern rtx simplify_gen_binary (enum rtx_code, machine_mode, rtx, rtx);
-extern rtx simplify_gen_unary (enum rtx_code, machine_mode, rtx,
- machine_mode);
-extern rtx simplify_gen_ternary (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx, rtx);
-extern rtx simplify_gen_relational (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx);
-extern rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64);
-extern rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64);
-extern rtx lowpart_subreg (machine_mode, rtx, machine_mode);
extern rtx simplify_replace_fn_rtx (rtx, const_rtx,
rtx (*fn) (rtx, const_rtx, void *), void *);
extern rtx simplify_replace_rtx (rtx, const_rtx, rtx);
@@ -3426,6 +3539,7 @@ extern void set_insn_deleted (rtx_insn *);
/* Functions in rtlanal.c */
extern rtx single_set_2 (const rtx_insn *, const_rtx);
+extern rtx simple_regno_set (rtx, unsigned int);
extern bool contains_symbol_ref_p (const_rtx);
extern bool contains_symbolic_reference_p (const_rtx);
extern bool contains_constant_pool_address_p (const_rtx);
@@ -3525,6 +3639,7 @@ extern rtx tablejump_casesi_pattern (const rtx_insn *insn);
extern int computed_jump_p (const rtx_insn *);
extern bool tls_referenced_p (const_rtx);
extern bool contains_mem_rtx_p (rtx x);
+extern bool register_asm_p (const_rtx);
/* Overload for refers_to_regno_p for checking a single register. */
inline bool
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 01130a1..80e72d6 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "backend.h"
#include "target.h"
#include "rtl.h"
+#include "rtlanal.h"
#include "tree.h"
#include "predict.h"
#include "df.h"
@@ -1454,6 +1455,39 @@ set_of (const_rtx pat, const_rtx insn)
return data.found;
}
+/* Check whether instruction pattern PAT contains a SET with the following
+ properties:
+
+ - the SET is executed unconditionally;
+ - the destination of the SET is write-only rather than read-write; and
+ - either:
+ - the destination of the SET is a REG that contains REGNO; or
+ - the destination of the SET is a SUBREG of such a REG.
+
+ If PAT does have a SET like that, return the set, otherwise return null.
+
+ This is intended to be an alternative to single_set for passes that
+ can handle patterns with multiple_sets. */
+rtx
+simple_regno_set (rtx pat, unsigned int regno)
+{
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ int last = XVECLEN (pat, 0) - 1;
+ for (int i = 0; i < last; ++i)
+ if (rtx set = simple_regno_set (XVECEXP (pat, 0, i), regno))
+ return set;
+
+ pat = XVECEXP (pat, 0, last);
+ }
+
+ if (GET_CODE (pat) == SET
+ && covers_regno_no_parallel_p (SET_DEST (pat), regno))
+ return pat;
+
+ return nullptr;
+}
+
/* Add all hard register in X to *PSET. */
void
find_all_hard_regs (const_rtx x, HARD_REG_SET *pset)
@@ -1668,10 +1702,6 @@ noop_move_p (const rtx_insn *insn)
if (INSN_CODE (insn) == NOOP_MOVE_INSN_CODE)
return 1;
- /* Insns carrying these notes are useful later on. */
- if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
- return 0;
-
/* Check the code to be executed for COND_EXEC. */
if (GET_CODE (pat) == COND_EXEC)
pat = COND_EXEC_CODE (pat);
@@ -2053,6 +2083,287 @@ note_uses (rtx *pbody, void (*fun) (rtx *, void *), void *data)
return;
}
}
+
+/* Try to add a description of REG X to this object, stopping once
+ the REF_END limit has been reached. FLAGS is a bitmask of
+ rtx_obj_reference flags that describe the context. */
+
+void
+rtx_properties::try_to_add_reg (const_rtx x, unsigned int flags)
+{
+ if (REG_NREGS (x) != 1)
+ flags |= rtx_obj_flags::IS_MULTIREG;
+ machine_mode mode = GET_MODE (x);
+ unsigned int start_regno = REGNO (x);
+ unsigned int end_regno = END_REGNO (x);
+ for (unsigned int regno = start_regno; regno < end_regno; ++regno)
+ if (ref_iter != ref_end)
+ *ref_iter++ = rtx_obj_reference (regno, flags, mode,
+ regno - start_regno);
+}
+
+/* Add a description of destination X to this object. FLAGS is a bitmask
+ of rtx_obj_reference flags that describe the context.
+
+ This routine accepts all rtxes that can legitimately appear in a
+ SET_DEST. */
+
+void
+rtx_properties::try_to_add_dest (const_rtx x, unsigned int flags)
+{
+ /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
+ each of whose first operand is a register. */
+ if (__builtin_expect (GET_CODE (x) == PARALLEL, 0))
+ {
+ for (int i = XVECLEN (x, 0) - 1; i >= 0; --i)
+ if (rtx dest = XEXP (XVECEXP (x, 0, i), 0))
+ try_to_add_dest (dest, flags);
+ return;
+ }
+
+ unsigned int base_flags = flags & rtx_obj_flags::STICKY_FLAGS;
+ flags |= rtx_obj_flags::IS_WRITE;
+ for (;;)
+ if (GET_CODE (x) == ZERO_EXTRACT)
+ {
+ try_to_add_src (XEXP (x, 1), base_flags);
+ try_to_add_src (XEXP (x, 2), base_flags);
+ flags |= rtx_obj_flags::IS_READ;
+ x = XEXP (x, 0);
+ }
+ else if (GET_CODE (x) == STRICT_LOW_PART)
+ {
+ flags |= rtx_obj_flags::IS_READ;
+ x = XEXP (x, 0);
+ }
+ else if (GET_CODE (x) == SUBREG)
+ {
+ flags |= rtx_obj_flags::IN_SUBREG;
+ if (read_modify_subreg_p (x))
+ flags |= rtx_obj_flags::IS_READ;
+ x = SUBREG_REG (x);
+ }
+ else
+ break;
+
+ if (MEM_P (x))
+ {
+ if (ref_iter != ref_end)
+ *ref_iter++ = rtx_obj_reference (MEM_REGNO, flags, GET_MODE (x));
+
+ unsigned int addr_flags = base_flags | rtx_obj_flags::IN_MEM_STORE;
+ if (flags & rtx_obj_flags::IS_READ)
+ addr_flags |= rtx_obj_flags::IN_MEM_LOAD;
+ try_to_add_src (XEXP (x, 0), addr_flags);
+ return;
+ }
+
+ if (__builtin_expect (REG_P (x), 1))
+ {
+ /* We want to keep sp alive everywhere - by making all
+ writes to sp also use sp. */
+ if (REGNO (x) == STACK_POINTER_REGNUM)
+ flags |= rtx_obj_flags::IS_READ;
+ try_to_add_reg (x, flags);
+ return;
+ }
+}
+
+/* Try to add a description of source X to this object, stopping once
+ the REF_END limit has been reached. FLAGS is a bitmask of
+ rtx_obj_reference flags that describe the context.
+
+ This routine accepts all rtxes that can legitimately appear in a SET_SRC. */
+
+void
+rtx_properties::try_to_add_src (const_rtx x, unsigned int flags)
+{
+ unsigned int base_flags = flags & rtx_obj_flags::STICKY_FLAGS;
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, NONCONST)
+ {
+ const_rtx x = *iter;
+ rtx_code code = GET_CODE (x);
+ if (code == REG)
+ try_to_add_reg (x, flags | rtx_obj_flags::IS_READ);
+ else if (code == MEM)
+ {
+ if (MEM_VOLATILE_P (x))
+ has_volatile_refs = true;
+
+ if (!MEM_READONLY_P (x) && ref_iter != ref_end)
+ {
+ auto mem_flags = flags | rtx_obj_flags::IS_READ;
+ *ref_iter++ = rtx_obj_reference (MEM_REGNO, mem_flags,
+ GET_MODE (x));
+ }
+
+ try_to_add_src (XEXP (x, 0),
+ base_flags | rtx_obj_flags::IN_MEM_LOAD);
+ iter.skip_subrtxes ();
+ }
+ else if (code == SUBREG)
+ {
+ try_to_add_src (SUBREG_REG (x), flags | rtx_obj_flags::IN_SUBREG);
+ iter.skip_subrtxes ();
+ }
+ else if (code == UNSPEC_VOLATILE)
+ has_volatile_refs = true;
+ else if (code == ASM_INPUT || code == ASM_OPERANDS)
+ {
+ has_asm = true;
+ if (MEM_VOLATILE_P (x))
+ has_volatile_refs = true;
+ }
+ else if (code == PRE_INC
+ || code == PRE_DEC
+ || code == POST_INC
+ || code == POST_DEC
+ || code == PRE_MODIFY
+ || code == POST_MODIFY)
+ {
+ has_pre_post_modify = true;
+
+ unsigned int addr_flags = (base_flags
+ | rtx_obj_flags::IS_PRE_POST_MODIFY
+ | rtx_obj_flags::IS_READ);
+ try_to_add_dest (XEXP (x, 0), addr_flags);
+ if (code == PRE_MODIFY || code == POST_MODIFY)
+ iter.substitute (XEXP (XEXP (x, 1), 1));
+ else
+ iter.skip_subrtxes ();
+ }
+ else if (code == CALL)
+ has_call = true;
+ }
+}
+
+/* Try to add a description of instruction pattern PAT to this object,
+ stopping once the REF_END limit has been reached. */
+
+void
+rtx_properties::try_to_add_pattern (const_rtx pat)
+{
+ switch (GET_CODE (pat))
+ {
+ case COND_EXEC:
+ try_to_add_src (COND_EXEC_TEST (pat));
+ try_to_add_pattern (COND_EXEC_CODE (pat));
+ break;
+
+ case PARALLEL:
+ {
+ int last = XVECLEN (pat, 0) - 1;
+ for (int i = 0; i < last; ++i)
+ try_to_add_pattern (XVECEXP (pat, 0, i));
+ try_to_add_pattern (XVECEXP (pat, 0, last));
+ break;
+ }
+
+ case ASM_OPERANDS:
+ for (int i = 0, len = ASM_OPERANDS_INPUT_LENGTH (pat); i < len; ++i)
+ try_to_add_src (ASM_OPERANDS_INPUT (pat, i));
+ break;
+
+ case CLOBBER:
+ try_to_add_dest (XEXP (pat, 0), rtx_obj_flags::IS_CLOBBER);
+ break;
+
+ case SET:
+ try_to_add_dest (SET_DEST (pat));
+ try_to_add_src (SET_SRC (pat));
+ break;
+
+ default:
+ /* All the other possibilities never store and can use a normal
+ rtx walk. This includes:
+
+ - USE
+ - TRAP_IF
+ - PREFETCH
+ - UNSPEC
+ - UNSPEC_VOLATILE. */
+ try_to_add_src (pat);
+ break;
+ }
+}
+
+/* Try to add a description of INSN to this object, stopping once
+ the REF_END limit has been reached. INCLUDE_NOTES is true if the
+ description should include REG_EQUAL and REG_EQUIV notes; all such
+ references will then be marked with rtx_obj_flags::IN_NOTE.
+
+ For calls, this description includes all accesses in
+ CALL_INSN_FUNCTION_USAGE. It also include all implicit accesses
+ to global registers by the target function. However, it does not
+ include clobbers performed by the target function; callers that want
+ this information should instead use the function_abi interface. */
+
+void
+rtx_properties::try_to_add_insn (const rtx_insn *insn, bool include_notes)
+{
+ if (CALL_P (insn))
+ {
+ /* Adding the global registers first removes a situation in which
+ a fixed-form clobber of register R could come before a real set
+ of register R. */
+ if (!hard_reg_set_empty_p (global_reg_set))
+ {
+ unsigned int flags = (rtx_obj_flags::IS_READ
+ | rtx_obj_flags::IS_WRITE);
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ if (global_regs[regno] && ref_iter != ref_end)
+ *ref_iter++ = rtx_obj_reference (regno, flags,
+ reg_raw_mode[regno], 0);
+ }
+ if (ref_iter != ref_end && !RTL_CONST_CALL_P (insn))
+ {
+ auto mem_flags = rtx_obj_flags::IS_READ;
+ if (!RTL_PURE_CALL_P (insn))
+ mem_flags |= rtx_obj_flags::IS_WRITE;
+ *ref_iter++ = rtx_obj_reference (MEM_REGNO, mem_flags, BLKmode);
+ }
+ try_to_add_pattern (PATTERN (insn));
+ for (rtx link = CALL_INSN_FUNCTION_USAGE (insn); link;
+ link = XEXP (link, 1))
+ {
+ rtx x = XEXP (link, 0);
+ if (GET_CODE (x) == CLOBBER)
+ try_to_add_dest (XEXP (x, 0), rtx_obj_flags::IS_CLOBBER);
+ else if (GET_CODE (x) == USE)
+ try_to_add_src (XEXP (x, 0));
+ }
+ }
+ else
+ try_to_add_pattern (PATTERN (insn));
+
+ if (include_notes)
+ for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_EQUAL
+ || REG_NOTE_KIND (note) == REG_EQUIV)
+ try_to_add_note (XEXP (note, 0));
+}
+
+/* Grow the storage by a bit while keeping the contents of the first
+ START elements. */
+
+void
+vec_rtx_properties_base::grow (ptrdiff_t start)
+{
+ /* The same heuristic that vec uses. */
+ ptrdiff_t new_elems = (ref_end - ref_begin) * 3 / 2;
+ if (ref_begin == m_storage)
+ {
+ ref_begin = XNEWVEC (rtx_obj_reference, new_elems);
+ if (start)
+ memcpy (ref_begin, m_storage, start * sizeof (rtx_obj_reference));
+ }
+ else
+ ref_begin = reinterpret_cast<rtx_obj_reference *>
+ (xrealloc (ref_begin, new_elems * sizeof (rtx_obj_reference)));
+ ref_iter = ref_begin + start;
+ ref_end = ref_begin + new_elems;
+}
/* Return nonzero if X's old contents don't survive after INSN.
This will be true if X is (cc0) or if X is a register and
@@ -6621,3 +6932,15 @@ add_auto_inc_notes (rtx_insn *insn, rtx x)
add_auto_inc_notes (insn, XVECEXP (x, i, j));
}
}
+
+/* Return true if X is register asm. */
+
+bool
+register_asm_p (const_rtx x)
+{
+ return (REG_P (x)
+ && REG_EXPR (x) != NULL_TREE
+ && HAS_DECL_ASSEMBLER_NAME_P (REG_EXPR (x))
+ && DECL_ASSEMBLER_NAME_SET_P (REG_EXPR (x))
+ && DECL_REGISTER (REG_EXPR (x)));
+}
diff --git a/gcc/rtlanal.h b/gcc/rtlanal.h
new file mode 100644
index 0000000..322761b
--- /dev/null
+++ b/gcc/rtlanal.h
@@ -0,0 +1,334 @@
+/* Analyze RTL for GNU compiler.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* Note that for historical reasons, many rtlanal.c functions are
+ declared in rtl.h rather than here. */
+
+#ifndef GCC_RTLANAL_H
+#define GCC_RTLANAL_H
+
+/* A dummy register value that represents the whole of variable memory.
+ Using ~0U means that arrays that track both registers and memory can
+ be indexed by regno + 1. */
+const unsigned int MEM_REGNO = ~0U;
+
+/* Bitmasks of flags describing an rtx_obj_reference. See the accessors
+ in the class for details. */
+namespace rtx_obj_flags
+{
+ const uint16_t IS_READ = 1U << 0;
+ const uint16_t IS_WRITE = 1U << 1;
+ const uint16_t IS_CLOBBER = 1U << 2;
+ const uint16_t IS_PRE_POST_MODIFY = 1U << 3;
+ const uint16_t IS_MULTIREG = 1U << 4;
+ const uint16_t IN_MEM_LOAD = 1U << 5;
+ const uint16_t IN_MEM_STORE = 1U << 6;
+ const uint16_t IN_SUBREG = 1U << 7;
+ const uint16_t IN_NOTE = 1U << 8;
+
+ /* Flags that apply to all subrtxes of the rtx they were originally
+ added for. */
+ static const uint16_t STICKY_FLAGS = IN_NOTE;
+}
+
+/* Contains information about a reference to a register or variable memory. */
+class rtx_obj_reference
+{
+public:
+ rtx_obj_reference () = default;
+ rtx_obj_reference (unsigned int regno, uint16_t flags,
+ machine_mode mode, unsigned int multireg_offset = 0);
+
+ bool is_reg () const { return regno != MEM_REGNO; }
+ bool is_mem () const { return regno == MEM_REGNO; }
+
+ /* True if the reference is a read or a write respectively.
+ Both flags are set in a read-modify-write context, such as
+ for read_modify_subreg_p. */
+ bool is_read () const { return flags & rtx_obj_flags::IS_READ; }
+ bool is_write () const { return flags & rtx_obj_flags::IS_WRITE; }
+
+ /* True if IS_WRITE and if the write is a clobber rather than a set. */
+ bool is_clobber () const { return flags & rtx_obj_flags::IS_CLOBBER; }
+
+ /* True if the reference is updated by an RTX_AUTOINC. Both IS_READ
+ and IS_WRITE are also true if so. */
+ bool is_pre_post_modify () const
+ {
+ return flags & rtx_obj_flags::IS_PRE_POST_MODIFY;
+ }
+
+ /* True if the register is part of a multi-register hard REG. */
+ bool is_multireg () const { return flags & rtx_obj_flags::IS_MULTIREG; }
+
+ /* True if the reference occurs in the address of a load MEM. */
+ bool in_mem_load () const { return flags & rtx_obj_flags::IN_MEM_LOAD; }
+
+ /* True if the reference occurs in the address of a store MEM. */
+ bool in_mem_store () const { return flags & rtx_obj_flags::IN_MEM_STORE; }
+
+ /* True if the reference occurs in any kind of MEM address. */
+ bool in_address () const { return in_mem_load () || in_mem_store (); }
+
+ /* True if the reference occurs in a SUBREG. */
+ bool in_subreg () const { return flags & rtx_obj_flags::IN_SUBREG; }
+
+ /* True if the reference occurs in a REG_EQUAL or REG_EQUIV note. */
+ bool in_note () const { return flags & rtx_obj_flags::IN_NOTE; }
+
+ /* The referenced register, or MEM_REGNO for variable memory. */
+ unsigned int regno;
+
+ /* A bitmask of rtx_obj_flags. */
+ unsigned int flags : 16;
+
+ /* The mode of the reference. If IS_MULTIREG, this is the mode of
+ REGNO - MULTIREG_OFFSET. */
+ machine_mode mode : 8;
+
+ /* If IS_MULTIREG, the offset of REGNO from the start of the register. */
+ unsigned int multireg_offset : 8;
+};
+
+/* Construct a reference with the given fields. */
+
+inline rtx_obj_reference::rtx_obj_reference (unsigned int regno, uint16_t flags,
+ machine_mode mode,
+ unsigned int multireg_offset)
+ : regno (regno),
+ flags (flags),
+ mode (mode),
+ multireg_offset (multireg_offset)
+{
+}
+
+/* Contains information about an rtx or an instruction, including a
+ list of rtx_obj_references. The storage backing the list needs
+ to be filled in by assigning to REF_BEGIN and REF_END. */
+
+class rtx_properties
+{
+public:
+ rtx_properties ();
+
+ void try_to_add_reg (const_rtx x, unsigned int flags = 0);
+ void try_to_add_dest (const_rtx x, unsigned int flags = 0);
+ void try_to_add_src (const_rtx x, unsigned int flags = 0);
+ void try_to_add_pattern (const_rtx pat);
+ void try_to_add_note (const_rtx x);
+ void try_to_add_insn (const rtx_insn *insn, bool include_notes);
+
+ iterator_range<rtx_obj_reference *> refs () const;
+
+ /* Return the number of rtx_obj_references that have been recorded. */
+ size_t num_refs () const { return ref_iter - ref_begin; }
+
+ bool has_side_effects () const;
+
+ /* [REF_BEGIN, REF_END) is the maximum extent of the memory available
+ for recording references. REG_ITER is the first unused entry. */
+ rtx_obj_reference *ref_begin;
+ rtx_obj_reference *ref_iter;
+ rtx_obj_reference *ref_end;
+
+ /* True if the rtx includes an asm. */
+ unsigned int has_asm : 1;
+
+ /* True if the rtx includes a call. */
+ unsigned int has_call : 1;
+
+ /* True if the rtx includes an RTX_AUTOINC expression. */
+ unsigned int has_pre_post_modify : 1;
+
+ /* True if the rtx contains volatile references, in the sense of
+ volatile_refs_p. */
+ unsigned int has_volatile_refs : 1;
+
+ /* For future expansion. */
+ unsigned int spare : 28;
+};
+
+inline rtx_properties::rtx_properties ()
+ : ref_begin (nullptr),
+ ref_iter (nullptr),
+ ref_end (nullptr),
+ has_asm (false),
+ has_call (false),
+ has_pre_post_modify (false),
+ has_volatile_refs (false),
+ spare (0)
+{
+}
+
+/* Like add_src, but treat X has being part of a REG_EQUAL or
+ REG_EQUIV note. */
+
+inline void
+rtx_properties::try_to_add_note (const_rtx x)
+{
+ try_to_add_src (x, rtx_obj_flags::IN_NOTE);
+}
+
+/* Return true if the rtx has side effects, in the sense of
+ side_effects_p (except for side_effects_p's special handling
+ of combine.c clobbers). */
+
+inline bool
+rtx_properties::has_side_effects () const
+{
+ return has_volatile_refs || has_pre_post_modify || has_call;
+}
+
+/* Return an iterator range for all the references, suitable for
+ range-based for loops. */
+
+inline iterator_range<rtx_obj_reference *>
+rtx_properties::refs () const
+{
+ return { ref_begin, ref_iter };
+}
+
+/* BASE is derived from rtx_properties and provides backing storage
+ for REF_BEGIN. It has a grow () method that increases the amount
+ of memory available if the initial allocation was too small. */
+
+template<typename Base>
+class growing_rtx_properties : public Base
+{
+public:
+ template<typename... Args>
+ growing_rtx_properties (Args...);
+
+ template<typename AddFn>
+ void repeat (AddFn add);
+
+ /* Wrappers around the try_to_* functions that always succeed. */
+ void add_dest (const_rtx x, unsigned int flags = 0);
+ void add_src (const_rtx x, unsigned int flags = 0);
+ void add_pattern (const_rtx pat);
+ void add_note (const_rtx x);
+ void add_insn (const rtx_insn *insn, bool include_notes);
+};
+
+template<typename Base>
+template<typename... Args>
+growing_rtx_properties<Base>::growing_rtx_properties (Args... args)
+ : Base (std::forward<Args> (args)...)
+{
+}
+
+/* Perform ADD until there is enough room to hold the result. */
+
+template<typename Base>
+template<typename AddFn>
+inline void
+growing_rtx_properties<Base>::repeat (AddFn add)
+{
+ ptrdiff_t count = this->num_refs ();
+ for (;;)
+ {
+ add ();
+ /* This retries if the storage happened to be exactly the right size,
+ but that's expected to be a rare case and so isn't worth
+ optimizing for. */
+ if (__builtin_expect (this->ref_iter != this->ref_end, 1))
+ break;
+ this->grow (count);
+ }
+}
+
+template<typename Base>
+inline void
+growing_rtx_properties<Base>::add_dest (const_rtx x, unsigned int flags)
+{
+ repeat ([&]() { this->try_to_add_dest (x, flags); });
+}
+
+template<typename Base>
+inline void
+growing_rtx_properties<Base>::add_src (const_rtx x, unsigned int flags)
+{
+ repeat ([&]() { this->try_to_add_src (x, flags); });
+}
+
+template<typename Base>
+inline void
+growing_rtx_properties<Base>::add_pattern (const_rtx pat)
+{
+ repeat ([&]() { this->try_to_add_pattern (pat); });
+}
+
+template<typename Base>
+inline void
+growing_rtx_properties<Base>::add_note (const_rtx x)
+{
+ repeat ([&]() { this->try_to_add_note (x); });
+}
+
+template<typename Base>
+inline void
+growing_rtx_properties<Base>::add_insn (const rtx_insn *insn, bool include_notes)
+{
+ repeat ([&]() { this->try_to_add_insn (insn, include_notes); });
+}
+
+/* A base class for vec_rtx_properties; see there for details. */
+
+class vec_rtx_properties_base : public rtx_properties
+{
+ static const size_t SIZE = 32;
+
+public:
+ vec_rtx_properties_base ();
+ ~vec_rtx_properties_base ();
+
+protected:
+ void grow (ptrdiff_t);
+
+private:
+ rtx_obj_reference m_storage[SIZE];
+};
+
+inline vec_rtx_properties_base::vec_rtx_properties_base ()
+{
+ ref_begin = ref_iter = m_storage;
+ ref_end = m_storage + SIZE;
+}
+
+inline vec_rtx_properties_base::~vec_rtx_properties_base ()
+{
+ if (__builtin_expect (ref_begin != m_storage, 0))
+ free (ref_begin);
+}
+
+/* A rtx_properties that stores its references in a temporary array.
+ Like auto_vec, the array is initially on the stack, but can switch
+ to the heap if necessary.
+
+ The reason for implementing this as a derived class is that the
+ default on-stack size should be enough for the vast majority of
+ expressions and instructions. It's therefore not worth paying
+ the cost of conditionally calling grow code at every site that
+ records a new reference. Instead, the rtx_properties code can use
+ trivial iterator updates for the common case, and in the rare case
+ that the vector needs to be resized, we can pay the cost of
+ collecting the references a second time. */
+using vec_rtx_properties = growing_rtx_properties<vec_rtx_properties_base>;
+
+#endif
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index a32715d..f02731e 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -180,6 +180,67 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_POINTER_COMPARE, "__sanitizer_ptr_cmp",
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_POINTER_SUBTRACT, "__sanitizer_ptr_sub",
BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+/* Hardware Address Sanitizer. */
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_INIT, "__hwasan_init",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD1, "__hwasan_load1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD2, "__hwasan_load2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD4, "__hwasan_load4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD8, "__hwasan_load8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD16, "__hwasan_load16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOADN, "__hwasan_loadN",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE1, "__hwasan_store1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE2, "__hwasan_store2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE4, "__hwasan_store4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE8, "__hwasan_store8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE16, "__hwasan_store16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STOREN, "__hwasan_storeN",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD1_NOABORT, "__hwasan_load1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD2_NOABORT, "__hwasan_load2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD4_NOABORT, "__hwasan_load4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD8_NOABORT, "__hwasan_load8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD16_NOABORT, "__hwasan_load16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOADN_NOABORT, "__hwasan_loadN_noabort",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE1_NOABORT, "__hwasan_store1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE2_NOABORT, "__hwasan_store2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE4_NOABORT, "__hwasan_store4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE8_NOABORT, "__hwasan_store8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE16_NOABORT,
+ "__hwasan_store16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STOREN_NOABORT, "__hwasan_storeN_noabort",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_TAG_MISMATCH4, "__hwasan_tag_mismatch4",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_HANDLE_LONGJMP, "__hwasan_handle_longjmp",
+ BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_TAG_PTR, "__hwasan_tag_pointer",
+ BT_FN_PTR_CONST_PTR_UINT8, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_TAG_MEM, "__hwasan_tag_memory",
+ BT_FN_VOID_PTR_UINT8_PTRMODE, ATTR_NOTHROW_LIST)
+
/* Thread Sanitizer */
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 6c3bce9..965ab36 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -776,7 +776,8 @@ sanopt_optimize_walker (basic_block bb, class sanopt_ctx *ctx)
basic_block son;
gimple_stmt_iterator gsi;
sanopt_info *info = (sanopt_info *) bb->aux;
- bool asan_check_optimize = (flag_sanitize & SANITIZE_ADDRESS) != 0;
+ bool asan_check_optimize
+ = ((flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_HWADDRESS)) != 0);
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
{
@@ -806,6 +807,7 @@ sanopt_optimize_walker (basic_block bb, class sanopt_ctx *ctx)
if (asan_check_optimize
&& gimple_call_builtin_p (stmt, BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT))
{
+ gcc_assert (!hwasan_sanitize_p ());
use_operand_p use;
gimple *use_stmt;
if (single_imm_use (gimple_vdef (stmt), &use, &use_stmt))
@@ -834,6 +836,7 @@ sanopt_optimize_walker (basic_block bb, class sanopt_ctx *ctx)
case IFN_UBSAN_PTR:
remove = maybe_optimize_ubsan_ptr_ifn (ctx, stmt);
break;
+ case IFN_HWASAN_CHECK:
case IFN_ASAN_CHECK:
if (asan_check_optimize)
remove = maybe_optimize_asan_check_ifn (ctx, stmt);
@@ -1262,6 +1265,10 @@ sanitize_rewrite_addressable_params (function *fun)
unsigned int
pass_sanopt::execute (function *fun)
{
+ /* n.b. ASAN_MARK is used for both HWASAN and ASAN.
+ asan_num_accesses is hence used to count either HWASAN_CHECK or ASAN_CHECK
+ stuff. This is fine because you can only have one of these active at a
+ time. */
basic_block bb;
int asan_num_accesses = 0;
bool contains_asan_mark = false;
@@ -1269,10 +1276,10 @@ pass_sanopt::execute (function *fun)
/* Try to remove redundant checks. */
if (optimize
&& (flag_sanitize
- & (SANITIZE_NULL | SANITIZE_ALIGNMENT
+ & (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_HWADDRESS
| SANITIZE_ADDRESS | SANITIZE_VPTR | SANITIZE_POINTER_OVERFLOW)))
asan_num_accesses = sanopt_optimize (fun, &contains_asan_mark);
- else if (flag_sanitize & SANITIZE_ADDRESS)
+ else if (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_HWADDRESS))
{
gimple_stmt_iterator gsi;
FOR_EACH_BB_FN (bb, fun)
@@ -1292,7 +1299,7 @@ pass_sanopt::execute (function *fun)
sanitize_asan_mark_poison ();
}
- if (asan_sanitize_stack_p ())
+ if (asan_sanitize_stack_p () || hwasan_sanitize_stack_p ())
sanitize_rewrite_addressable_params (fun);
bool use_calls = param_asan_instrumentation_with_call_threshold < INT_MAX
@@ -1334,6 +1341,9 @@ pass_sanopt::execute (function *fun)
case IFN_UBSAN_VPTR:
no_next = ubsan_expand_vptr_ifn (&gsi);
break;
+ case IFN_HWASAN_CHECK:
+ no_next = hwasan_expand_check_ifn (&gsi, use_calls);
+ break;
case IFN_ASAN_CHECK:
no_next = asan_expand_check_ifn (&gsi, use_calls);
break;
@@ -1345,6 +1355,9 @@ pass_sanopt::execute (function *fun)
&need_commit_edge_insert,
shadow_vars_mapping);
break;
+ case IFN_HWASAN_MARK:
+ no_next = hwasan_expand_mark_ifn (&gsi);
+ break;
default:
break;
}
diff --git a/gcc/sbitmap.c b/gcc/sbitmap.c
index 292e7ee..3a43fe35 100644
--- a/gcc/sbitmap.c
+++ b/gcc/sbitmap.c
@@ -139,7 +139,8 @@ sbitmap_realloc (sbitmap src, unsigned int n_elms)
sbitmap *
sbitmap_vector_alloc (unsigned int n_vecs, unsigned int n_elms)
{
- unsigned int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
+ unsigned int i, size;
+ size_t amt, bytes, vector_bytes, elm_bytes, offset;
sbitmap *bitmap_vector;
size = SBITMAP_SET_SIZE (n_elms);
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index c8e086e..2bcd398 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -3793,7 +3793,8 @@ maybe_tidy_empty_bb (basic_block bb)
else if (single_succ_p (pred_bb) && any_condjump_p (BB_END (pred_bb)))
{
/* If possible, try to remove the unneeded conditional jump. */
- if (INSN_SCHED_TIMES (BB_END (pred_bb)) == 0
+ if (onlyjump_p (BB_END (pred_bb))
+ && INSN_SCHED_TIMES (BB_END (pred_bb)) == 0
&& !IN_CURRENT_FENCE_P (BB_END (pred_bb)))
{
if (!sel_remove_insn (BB_END (pred_bb), false, false))
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 7a89b2d..c0c18ad 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -79,6 +79,7 @@ selftest::run_tests ()
optinfo_emit_json_cc_tests ();
opt_problem_cc_tests ();
ordered_hash_map_tests_cc_tests ();
+ splay_tree_cc_tests ();
/* Mid-level data structures. */
input_c_tests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 6c6c7f2..b6e4345 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -248,6 +248,7 @@ extern void ordered_hash_map_tests_cc_tests ();
extern void predict_c_tests ();
extern void pretty_print_c_tests ();
extern void range_tests ();
+extern void range_op_tests ();
extern void read_rtl_function_c_tests ();
extern void rtl_tests_c_tests ();
extern void sbitmap_c_tests ();
@@ -255,6 +256,7 @@ extern void selftest_c_tests ();
extern void simplify_rtx_c_tests ();
extern void spellcheck_c_tests ();
extern void spellcheck_tree_c_tests ();
+extern void splay_tree_cc_tests ();
extern void sreal_c_tests ();
extern void store_merging_c_tests ();
extern void tree_c_tests ();
diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
index d70635e..4bb63e9 100644
--- a/gcc/shrink-wrap.c
+++ b/gcc/shrink-wrap.c
@@ -494,7 +494,7 @@ can_get_prologue (basic_block pro, HARD_REG_SET prologue_clobbered)
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, pro->preds)
- if (e->flags & (EDGE_COMPLEX | EDGE_CROSSING)
+ if (e->flags & EDGE_COMPLEX
&& !dominated_by_p (CDI_DOMINATORS, e->src, pro))
return false;
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 47e7aeb..ff331e1 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -47,14 +47,6 @@ along with GCC; see the file COPYING3. If not see
((((HOST_WIDE_INT) low) < 0) ? HOST_WIDE_INT_M1 : HOST_WIDE_INT_0)
static bool plus_minus_operand_p (const_rtx);
-static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx);
-static rtx simplify_associative_operation (enum rtx_code, machine_mode,
- rtx, rtx);
-static rtx simplify_relational_operation_1 (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx);
-static rtx simplify_unary_operation_1 (enum rtx_code, machine_mode, rtx);
-static rtx simplify_binary_operation_1 (enum rtx_code, machine_mode,
- rtx, rtx, rtx, rtx);
/* Negate I, which satisfies poly_int_rtx_p. MODE is the mode of I. */
@@ -180,8 +172,8 @@ val_signbit_known_clear_p (machine_mode mode, unsigned HOST_WIDE_INT val)
seeing if the expression folds. */
rtx
-simplify_gen_binary (enum rtx_code code, machine_mode mode, rtx op0,
- rtx op1)
+simplify_context::simplify_gen_binary (rtx_code code, machine_mode mode,
+ rtx op0, rtx op1)
{
rtx tem;
@@ -358,8 +350,8 @@ delegitimize_mem_from_attrs (rtx x)
the specified operation. */
rtx
-simplify_gen_unary (enum rtx_code code, machine_mode mode, rtx op,
- machine_mode op_mode)
+simplify_context::simplify_gen_unary (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
{
rtx tem;
@@ -373,8 +365,9 @@ simplify_gen_unary (enum rtx_code code, machine_mode mode, rtx op,
/* Likewise for ternary operations. */
rtx
-simplify_gen_ternary (enum rtx_code code, machine_mode mode,
- machine_mode op0_mode, rtx op0, rtx op1, rtx op2)
+simplify_context::simplify_gen_ternary (rtx_code code, machine_mode mode,
+ machine_mode op0_mode,
+ rtx op0, rtx op1, rtx op2)
{
rtx tem;
@@ -390,8 +383,9 @@ simplify_gen_ternary (enum rtx_code code, machine_mode mode,
CMP_MODE specifies mode comparison is done in. */
rtx
-simplify_gen_relational (enum rtx_code code, machine_mode mode,
- machine_mode cmp_mode, rtx op0, rtx op1)
+simplify_context::simplify_gen_relational (rtx_code code, machine_mode mode,
+ machine_mode cmp_mode,
+ rtx op0, rtx op1)
{
rtx tem;
@@ -614,9 +608,9 @@ simplify_replace_rtx (rtx x, const_rtx old_rtx, rtx new_rtx)
However, X is still an arbitrary 64-bit number and so we cannot
assume that truncating it too is a no-op. */
-static rtx
-simplify_truncation (machine_mode mode, rtx op,
- machine_mode op_mode)
+rtx
+simplify_context::simplify_truncation (machine_mode mode, rtx op,
+ machine_mode op_mode)
{
unsigned int precision = GET_MODE_UNIT_PRECISION (mode);
unsigned int op_precision = GET_MODE_UNIT_PRECISION (op_mode);
@@ -858,8 +852,8 @@ simplify_truncation (machine_mode mode, rtx op,
MODE with input operand OP whose mode was originally OP_MODE.
Return zero if no simplification can be made. */
rtx
-simplify_unary_operation (enum rtx_code code, machine_mode mode,
- rtx op, machine_mode op_mode)
+simplify_context::simplify_unary_operation (rtx_code code, machine_mode mode,
+ rtx op, machine_mode op_mode)
{
rtx trueop, tem;
@@ -900,8 +894,9 @@ exact_int_to_float_conversion_p (const_rtx op)
/* Perform some simplifications we can do even if the operands
aren't constant. */
-static rtx
-simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
+rtx
+simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
+ rtx op)
{
enum rtx_code reversed;
rtx temp, elt, base, step;
@@ -2091,9 +2086,10 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
operating on OP0 and OP1. CODE is currently one of AND, IOR or XOR.
Return zero if no simplification or canonicalization is possible. */
-static rtx
-simplify_byte_swapping_operation (enum rtx_code code, machine_mode mode,
- rtx op0, rtx op1)
+rtx
+simplify_context::simplify_byte_swapping_operation (rtx_code code,
+ machine_mode mode,
+ rtx op0, rtx op1)
{
rtx tem;
@@ -2121,9 +2117,10 @@ simplify_byte_swapping_operation (enum rtx_code code, machine_mode mode,
SMIN, SMAX, UMIN or UMAX. Return zero if no simplification or
canonicalization is possible. */
-static rtx
-simplify_associative_operation (enum rtx_code code, machine_mode mode,
- rtx op0, rtx op1)
+rtx
+simplify_context::simplify_associative_operation (rtx_code code,
+ machine_mode mode,
+ rtx op0, rtx op1)
{
rtx tem;
@@ -2302,8 +2299,9 @@ comparison_code_valid_for_mode (enum rtx_code code, enum machine_mode mode)
and OP1, which should be both relational operations. Return 0 if no such
simplification is possible. */
rtx
-simplify_logical_relational_operation (enum rtx_code code, machine_mode mode,
- rtx op0, rtx op1)
+simplify_context::simplify_logical_relational_operation (rtx_code code,
+ machine_mode mode,
+ rtx op0, rtx op1)
{
/* We only handle IOR of two relational operations. */
if (code != IOR)
@@ -2351,8 +2349,8 @@ simplify_logical_relational_operation (enum rtx_code code, machine_mode mode,
Don't use this for relational operations such as EQ or LT.
Use simplify_relational_operation instead. */
rtx
-simplify_binary_operation (enum rtx_code code, machine_mode mode,
- rtx op0, rtx op1)
+simplify_context::simplify_binary_operation (rtx_code code, machine_mode mode,
+ rtx op0, rtx op1)
{
rtx trueop0, trueop1;
rtx tem;
@@ -2397,9 +2395,10 @@ simplify_binary_operation (enum rtx_code code, machine_mode mode,
MODE is the mode of the operation and is known to be a vector
integer mode. */
-static rtx
-simplify_binary_operation_series (rtx_code code, machine_mode mode,
- rtx op0, rtx op1)
+rtx
+simplify_context::simplify_binary_operation_series (rtx_code code,
+ machine_mode mode,
+ rtx op0, rtx op1)
{
rtx base0, step0;
if (vec_duplicate_p (op0, &base0))
@@ -2433,9 +2432,10 @@ simplify_binary_operation_series (rtx_code code, machine_mode mode,
e.g. simplify (xor (and A C) (and (B C)) to (and (xor (A B) C).
Returns NULL_RTX if no simplification is possible. */
-static rtx
-simplify_distributive_operation (enum rtx_code code, machine_mode mode,
- rtx op0, rtx op1)
+rtx
+simplify_context::simplify_distributive_operation (rtx_code code,
+ machine_mode mode,
+ rtx op0, rtx op1)
{
enum rtx_code op = GET_CODE (op0);
gcc_assert (GET_CODE (op1) == op);
@@ -2481,9 +2481,11 @@ simplify_distributive_operation (enum rtx_code code, machine_mode mode,
OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the
actual constants. */
-static rtx
-simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
- rtx op0, rtx op1, rtx trueop0, rtx trueop1)
+rtx
+simplify_context::simplify_binary_operation_1 (rtx_code code,
+ machine_mode mode,
+ rtx op0, rtx op1,
+ rtx trueop0, rtx trueop1)
{
rtx tem, reversed, opleft, opright, elt0, elt1;
HOST_WIDE_INT val;
@@ -2948,7 +2950,7 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
return op0;
/* Convert multiply by constant power of two into shift. */
- if (CONST_SCALAR_INT_P (trueop1))
+ if (mem_depth == 0 && CONST_SCALAR_INT_P (trueop1))
{
val = wi::exact_log2 (rtx_mode_t (trueop1, mode));
if (val >= 0)
@@ -3863,6 +3865,18 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
return op0;
if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
return op0;
+ if (mem_depth
+ && code == ASHIFT
+ && CONST_INT_P (trueop1)
+ && is_a <scalar_int_mode> (mode, &int_mode)
+ && IN_RANGE (UINTVAL (trueop1),
+ 1, GET_MODE_PRECISION (int_mode) - 1))
+ {
+ auto c = (wi::one (GET_MODE_PRECISION (int_mode))
+ << UINTVAL (trueop1));
+ rtx new_op1 = immed_wide_int_const (c, int_mode);
+ return simplify_gen_binary (MULT, int_mode, op0, new_op1);
+ }
goto canonicalize_shift;
case LSHIFTRT:
@@ -4887,9 +4901,9 @@ simplify_plus_minus_op_data_cmp (rtx x, rtx y)
May return NULL_RTX when no changes were made. */
-static rtx
-simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
- rtx op1)
+rtx
+simplify_context::simplify_plus_minus (rtx_code code, machine_mode mode,
+ rtx op0, rtx op1)
{
struct simplify_plus_minus_op_data
{
@@ -5234,8 +5248,10 @@ plus_minus_operand_p (const_rtx x)
the operands or, if both are VOIDmode, the operands are compared in
"infinite precision". */
rtx
-simplify_relational_operation (enum rtx_code code, machine_mode mode,
- machine_mode cmp_mode, rtx op0, rtx op1)
+simplify_context::simplify_relational_operation (rtx_code code,
+ machine_mode mode,
+ machine_mode cmp_mode,
+ rtx op0, rtx op1)
{
rtx tem, trueop0, trueop1;
@@ -5318,9 +5334,11 @@ simplify_relational_operation (enum rtx_code code, machine_mode mode,
MODE is the mode of the result, while CMP_MODE specifies in which
mode the comparison is done in, so it is the mode of the operands. */
-static rtx
-simplify_relational_operation_1 (enum rtx_code code, machine_mode mode,
- machine_mode cmp_mode, rtx op0, rtx op1)
+rtx
+simplify_context::simplify_relational_operation_1 (rtx_code code,
+ machine_mode mode,
+ machine_mode cmp_mode,
+ rtx op0, rtx op1)
{
enum rtx_code op0code = GET_CODE (op0);
@@ -5988,8 +6006,9 @@ simplify_const_relational_operation (enum rtx_code code,
Assume X is compared against zero with CMP_CODE and the true
arm is TRUE_VAL and the false arm is FALSE_VAL. */
-static rtx
-simplify_cond_clz_ctz (rtx x, rtx_code cmp_code, rtx true_val, rtx false_val)
+rtx
+simplify_context::simplify_cond_clz_ctz (rtx x, rtx_code cmp_code,
+ rtx true_val, rtx false_val)
{
if (cmp_code != EQ && cmp_code != NE)
return NULL_RTX;
@@ -6032,7 +6051,7 @@ simplify_cond_clz_ctz (rtx x, rtx_code cmp_code, rtx true_val, rtx false_val)
Return the simplified X on success, otherwise return NULL_RTX. */
rtx
-simplify_merge_mask (rtx x, rtx mask, int op)
+simplify_context::simplify_merge_mask (rtx x, rtx mask, int op)
{
gcc_assert (VECTOR_MODE_P (GET_MODE (x)));
poly_uint64 nunits = GET_MODE_NUNITS (GET_MODE (x));
@@ -6102,9 +6121,9 @@ simplify_merge_mask (rtx x, rtx mask, int op)
a constant. Return 0 if no simplifications is possible. */
rtx
-simplify_ternary_operation (enum rtx_code code, machine_mode mode,
- machine_mode op0_mode, rtx op0, rtx op1,
- rtx op2)
+simplify_context::simplify_ternary_operation (rtx_code code, machine_mode mode,
+ machine_mode op0_mode,
+ rtx op0, rtx op1, rtx op2)
{
bool any_change = false;
rtx tem, trueop2;
@@ -6971,8 +6990,8 @@ simplify_immed_subreg (fixed_size_mode outermode, rtx x,
/* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE)
Return 0 if no simplifications are possible. */
rtx
-simplify_subreg (machine_mode outermode, rtx op,
- machine_mode innermode, poly_uint64 byte)
+simplify_context::simplify_subreg (machine_mode outermode, rtx op,
+ machine_mode innermode, poly_uint64 byte)
{
/* Little bit of sanity checking. */
gcc_assert (innermode != VOIDmode);
@@ -7246,8 +7265,9 @@ simplify_subreg (machine_mode outermode, rtx op,
/* Make a SUBREG operation or equivalent if it folds. */
rtx
-simplify_gen_subreg (machine_mode outermode, rtx op,
- machine_mode innermode, poly_uint64 byte)
+simplify_context::simplify_gen_subreg (machine_mode outermode, rtx op,
+ machine_mode innermode,
+ poly_uint64 byte)
{
rtx newx;
@@ -7270,8 +7290,8 @@ simplify_gen_subreg (machine_mode outermode, rtx op,
INNER_MODE) to OUTER_MODE. */
rtx
-lowpart_subreg (machine_mode outer_mode, rtx expr,
- machine_mode inner_mode)
+simplify_context::lowpart_subreg (machine_mode outer_mode, rtx expr,
+ machine_mode inner_mode)
{
return simplify_gen_subreg (outer_mode, expr, inner_mode,
subreg_lowpart_offset (outer_mode, inner_mode));
@@ -7685,6 +7705,12 @@ test_vector_ops_series (machine_mode mode, rtx scalar_reg)
series_0_1));
}
+static rtx
+simplify_merge_mask (rtx x, rtx mask, int op)
+{
+ return simplify_context ().simplify_merge_mask (x, mask, op);
+}
+
/* Verify simplify_merge_mask works correctly. */
static void
diff --git a/gcc/splay-tree-utils.cc b/gcc/splay-tree-utils.cc
new file mode 100644
index 0000000..4b2007b
--- /dev/null
+++ b/gcc/splay-tree-utils.cc
@@ -0,0 +1,264 @@
+// Splay tree utilities -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_ARRAY
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "pretty-print.h"
+#include "splay-tree-utils.h"
+#include "selftest.h"
+
+#if CHECKING_P
+namespace {
+// A simple test node for rootless_splay_tree.
+struct rootless_test_node
+{
+ int data;
+ rootless_test_node *m_parent;
+ rootless_test_node *m_children[2];
+};
+}
+
+namespace selftest {
+
+// Random input data.
+static const size_t MAX_DATA = 32768;
+static const int data[] = {
+ 1379, 14643, 30579, 28160, 31750, 22280, 5502, 4720, 30075, 27595,
+ 8395, 19410, 518, 19709, 29694, 19865, 25372, 11752, 15485, 21547,
+ 25153, 25072, 10146, 3341, 15625, 3038, 10189, 19943, 1322, 11762,
+ 807, 430, 11284, 11841, 23965, 32008, 4547, 8087, 13225, 23054,
+ 22284, 13756, 2182, 26450, 30482, 32502, 23348, 20265, 29509, 3290,
+ 10807, 1242, 3212, 32178, 25354, 22032, 30509, 16157, 22432, 1295,
+ 8348, 23342, 24678, 193, 31016, 10316, 3872, 13521, 19211, 30594,
+ 12229, 4794, 25083, 16098, 28144, 27896, 4801, 20689, 31450, 15614,
+ 19597, 13731, 30309, 24846, 11042, 31929, 18306, 28520, 16907, 12488,
+ 15001, 18487, 3438, 1706, 4829, 20892, 6226, 18204, 15776, 30717,
+ 19398, 2480, 19434, 2838, 2605, 3994, 22538, 12269, 6486, 1314,
+ 30301, 9919, 31405, 30847, 25000, 24013, 22196, 30220, 31415, 14630,
+ 26319, 4880, 21292, 20217, 20078, 14679, 25686, 28675, 13883, 14853,
+ 2872, 2428, 3636, 14131, 2952, 2133, 4470, 25808, 12576, 31395,
+ 5938, 28393, 14553, 4494, 14928, 24310, 17394, 17436, 23385, 22792,
+ 9785, 13118, 22338, 23320, 27059, 17663, 16434, 14954, 16962, 31088,
+ 22247, 22600, 7980, 1344, 15635, 13611, 32739, 3283, 12924, 17904,
+ 28216, 7542, 9212, 28308, 18873, 3912, 5473, 4666, 11900, 21420,
+ 20072, 27662, 16445, 29848, 24444, 31668, 30664, 14287, 13754, 29276,
+ 21462, 25517, 17632, 8105, 32510, 16677, 11162, 20734, 26873, 5097
+};
+
+// Look up VALUE in TREE using the single-comparator lookup function.
+static int
+lookup1 (splay_tree<int> &tree, int value)
+{
+ auto compare = [&](splay_tree_node<int> *node)
+ {
+ return value - node->value ();
+ };
+ return tree.lookup (compare);
+}
+
+// Look up VALUE in TREE using the double-comparator lookup function.
+static int
+lookup2 (splay_tree<int> &tree, int value)
+{
+ auto want_something_smaller = [&](splay_tree_node<int> *node)
+ {
+ return value < node->value ();
+ };
+ auto want_something_bigger = [&](splay_tree_node<int> *node)
+ {
+ return value > node->value ();
+ };
+ return tree.lookup (want_something_smaller, want_something_bigger);
+}
+
+// Test printing TREE to a pretty printer. Don't check the output against
+// anything; just make sure that it doesn't crash.
+static void
+test_print (splay_tree<int> &tree)
+{
+ auto print_node = [](pretty_printer *pp, splay_tree_node<int> *node)
+ {
+ pp_decimal_int (pp, node->value ());
+ };
+ pretty_printer pp;
+ tree.print (&pp, print_node);
+}
+
+// Test various lookups on TREE using LOOKUP, where lookup returns the
+// same kind of value as the rooted_splay_tree lookup functions.
+static void
+test_lookup (splay_tree<int> &tree, int (*lookup) (splay_tree<int> &, int))
+{
+ // Look up values that are known to exist.
+ for (int value : data)
+ ASSERT_EQ (lookup (tree, value), 0);
+
+ // Look up values that are 1 less than values that are known to exist.
+ for (int value : data)
+ {
+ int result = lookup (tree, value - 1);
+ if (result == 0)
+ ASSERT_EQ (tree->value (), value - 1);
+ else if (result < 0)
+ // VALUE - 1 is less than the root.
+ ASSERT_EQ (tree->value (), value);
+ else if (result > 0)
+ {
+ // VALUE - 1 is greater than the root.
+ ASSERT_TRUE (tree->value () < value - 1);
+ if (tree.splay_next_node ())
+ ASSERT_EQ (tree->value (), value);
+ }
+ }
+
+ // Look up values that are 1 greater than values that are known to exist.
+ for (int value : data)
+ {
+ int result = lookup (tree, value + 1);
+ if (result == 0)
+ ASSERT_EQ (tree->value (), value + 1);
+ else if (result < 0)
+ {
+ // VALUE + 1 is less than the root.
+ ASSERT_TRUE (tree->value () > value + 1);
+ if (tree.splay_prev_node ())
+ ASSERT_EQ (tree->value (), value);
+ }
+ else if (result > 0)
+ // VALUE + 1 is greater than the root.
+ ASSERT_EQ (tree->value (), value);
+ }
+}
+
+// Run all tests for this module.
+void
+splay_tree_cc_tests ()
+{
+ obstack ob;
+ gcc_obstack_init (&ob);
+
+ // Build up the splay tree.
+ splay_tree<int> tree;
+ for (int value : data)
+ {
+ auto *node = XOBNEW (&ob, splay_tree_node<int>);
+ new (node) splay_tree_node<int> (value);
+ auto compare = [&](splay_tree_node<int> *other_node)
+ {
+ return value - other_node->value ();
+ };
+ bool inserted = tree.insert (node, compare);
+ ASSERT_TRUE (inserted);
+ }
+
+ // Test the single-comparator lookup function.
+ test_lookup (tree, lookup1);
+
+ // Sort the input data.
+ std::array<int, ARRAY_SIZE (data)> sorted;
+ std::copy (data, data + ARRAY_SIZE (data), sorted.begin ());
+ std::sort (sorted.begin (), sorted.end ());
+
+ // Iterate over the tree in ascending order.
+ tree.splay_min_node ();
+ bool result = true;
+ for (int value : sorted)
+ {
+ ASSERT_TRUE (result);
+ ASSERT_EQ (tree->value (), value);
+ result = tree.splay_next_node ();
+ }
+ ASSERT_FALSE (result);
+ ASSERT_EQ (tree.min_node ()->value (), sorted.front ());
+
+ // Test the double-comparator lookup function.
+ test_lookup (tree, lookup2);
+
+ // Test printing the tree now, while it's still bushy.
+ test_print (tree);
+
+ // Iterate over the tree in descending order.
+ tree.splay_max_node ();
+ result = true;
+ for (auto it = sorted.rbegin (); it != sorted.rend (); ++it)
+ {
+ ASSERT_TRUE (result);
+ ASSERT_EQ (tree->value (), *it);
+ result = tree.splay_prev_node ();
+ }
+ ASSERT_FALSE (result);
+ ASSERT_EQ (tree.max_node ()->value (), sorted.back ());
+
+ // Try splitting the tree into three.
+ int mid_min = sorted[sorted.size () / 3];
+ int mid_max = sorted[sorted.size () * 2 / 3];
+ ASSERT_EQ (lookup1 (tree, mid_min), 0);
+ splay_tree<int> left = tree.split_before_root ();
+ ASSERT_EQ (lookup1 (tree, mid_max), 0);
+ splay_tree<int> right = tree.split_after_root ();
+
+ // Test removing all the nodes from their respective trees.
+ for (int value : data)
+ {
+ splay_tree<int> &t = (value < mid_min ? left
+ : value > mid_max ? right : tree);
+ ASSERT_EQ (lookup1 (t, value), 0);
+ t.remove_root ();
+ }
+ ASSERT_EQ (left.root (), nullptr);
+ ASSERT_EQ (tree.root (), nullptr);
+ ASSERT_EQ (right.root (), nullptr);
+
+ using rootless = default_rootless_splay_tree<rootless_test_node *>;
+
+ // Build a tree in ascending order with the lowest element as the root.
+ auto *nodes = XOBNEWVEC (&ob, rootless_test_node *, MAX_DATA);
+ rootless_test_node *parent = nullptr;
+ for (int data : sorted)
+ {
+ auto *node = XOBNEW (&ob, rootless_test_node);
+ new (node) rootless_test_node ();
+ node->data = data;
+ nodes[data] = node;
+ if (parent)
+ rootless::insert_child (parent, 1, node);
+ parent = node;
+ }
+
+ // Try comparing nodes to make sure that their order matches the data.
+ for (size_t i = 1; i < ARRAY_SIZE (data); ++i)
+ {
+ int data1 = data[i - 1];
+ int data2 = data[i];
+ int comparison = rootless::compare_nodes (nodes[data1], nodes[data2]);
+ if (data1 < data2)
+ ASSERT_TRUE (comparison < 0);
+ else if (data1 > data2)
+ ASSERT_TRUE (comparison > 0);
+ else
+ ASSERT_EQ (comparison, 0);
+ }
+
+ obstack_free (&ob, nullptr);
+}
+}
+#endif // CHECKING_P
diff --git a/gcc/splay-tree-utils.h b/gcc/splay-tree-utils.h
new file mode 100644
index 0000000..dfb2a4a
--- /dev/null
+++ b/gcc/splay-tree-utils.h
@@ -0,0 +1,491 @@
+// Splay tree utilities -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Implement splay tree node accessors for a class that stores its
+// two child nodes in a member variable of the form:
+//
+// Node m_children[2];
+template<typename Node>
+class default_splay_tree_accessors
+{
+public:
+ using node_type = Node;
+
+ static auto
+ child (node_type node, unsigned int index)
+ -> decltype (node->m_children[index]) &
+ {
+ return node->m_children[index];
+ }
+};
+
+// Implement splay tree node accessors for a class that stores its
+// two child nodes in a member variable of the form:
+//
+// Node m_children[2];
+//
+// and also stores its parent node in a member variable of the form:
+//
+// Node m_parent;
+template<typename Node>
+class default_splay_tree_accessors_with_parent
+ : public default_splay_tree_accessors<Node>
+{
+public:
+ using node_type = Node;
+
+ static auto
+ parent (node_type node) -> decltype (node->m_parent) &
+ {
+ return node->m_parent;
+ }
+};
+
+// Base is a splay tree accessor class for nodes that have no parent field.
+// Base therefore provides a Base::child method but does not provide a
+// Base::parent method. Extend Base with dummy routines for setting the
+// parent, which is a no-op when the parent is not stored.
+template<typename Base>
+class splay_tree_accessors_without_parent : public Base
+{
+public:
+ using typename Base::node_type;
+
+ static void set_parent (node_type, node_type) {}
+};
+
+// Base is splay tree accessor class for nodes that have a parent field.
+// Base therefore provides both Base::child and Base::parent methods.
+// Extend Base with routines for setting the parent.
+template<typename Base>
+class splay_tree_accessors_with_parent : public Base
+{
+public:
+ using typename Base::node_type;
+
+ // Record that NODE's parent is now NEW_PARENT.
+ static void
+ set_parent (node_type node, node_type new_parent)
+ {
+ Base::parent (node) = new_parent;
+ }
+};
+
+// A base class that provides some splay tree operations that are common
+// to both rooted_splay_tree and rootless_splay_tree.
+//
+// Nodes in the splay tree have type Accessors::node_type; this is
+// usually a pointer type. The Accessors class provides the following
+// static member functions for accessing nodes:
+//
+// - Accessors::child (NODE, INDEX)
+// INDEX is guaranteed to be 0 or 1. If INDEX is 0, return a reference
+// to where NODE's left child is stored, otherwise return a reference
+// to where NODE's right child is stored.
+//
+// - Accessors::set_parent (NODE, PARENT)
+// Record that NODE's parent node is now PARENT.
+template<typename Accessors>
+class base_splay_tree : protected Accessors
+{
+public:
+ using typename Accessors::node_type;
+
+ // INDEX is either 0 or 1. If INDEX is 0, insert CHILD immediately
+ // before NODE, otherwise insert CHILD immediately after NODE.
+ //
+ // Complexity: O(1).
+ static void insert_child (node_type node, unsigned int index,
+ node_type child);
+
+ // Print NODE and its child nodes to PP for debugging purposes,
+ // using PRINTER (PP, N) to print the data for node N.
+ template<typename Printer>
+ static void print (pretty_printer *pp, node_type node, Printer printer);
+
+protected:
+ using Accessors::set_parent;
+
+ static node_type get_child (node_type, unsigned int);
+ static void set_child (node_type, unsigned int, node_type);
+ static node_type promote_child (node_type, unsigned int);
+ static void promote_child (node_type, unsigned int, node_type);
+
+ template<unsigned int N>
+ static node_type splay_limit (node_type);
+
+ static node_type remove_node_internal (node_type);
+
+ template<typename Printer>
+ static void print (pretty_printer *pp, node_type node, Printer printer,
+ char, vec<char> &);
+};
+
+// This class provides splay tree routines for cases in which the root
+// of the splay tree is known. It works with both nodes that store
+// their parent node and nodes that don't.
+//
+// The class is lightweight: it only contains a single root node.
+template<typename Accessors>
+class rooted_splay_tree : public base_splay_tree<Accessors>
+{
+ using parent = base_splay_tree<Accessors>;
+
+public:
+ using typename Accessors::node_type;
+
+protected:
+ // The root of the splay tree, or node_type () if the tree is empty.
+ node_type m_root;
+
+public:
+ rooted_splay_tree () : m_root () {}
+
+ // Construct a tree with the specified root node.
+ rooted_splay_tree (node_type root) : m_root (root) {}
+
+ // Return the root of the tree.
+ node_type root () const { return m_root; }
+
+ // Return true if the tree contains any nodes.
+ explicit operator bool () const { return m_root; }
+
+ // Dereference the root node.
+ node_type operator-> () { return m_root; }
+
+ // Insert NEW_NODE into the splay tree, if no equivalent node already
+ // exists. For a given node N, COMPARE (N) should return:
+ //
+ // - a negative value if NEW_NODE should come before N
+ // - zero if NEW_NODE and N are the same
+ // - a positive value if NEW_NODE should come after N
+ //
+ // Return true if NEW_NODE was inserted.
+ //
+ // On return, NEW_NODE or its equivalent is the root of the tree.
+ //
+ // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+ // the complexity of the comparison.
+ template<typename Comparator>
+ bool insert (node_type new_node, Comparator compare);
+
+ // Insert NEW_NODE into the splay tree, given that NEW_NODE is the
+ // maximum node of the new tree. On return, NEW_NODE is also the
+ // root of the tree.
+ //
+ // Complexity: O(1).
+ void insert_max_node (node_type new_node);
+
+ // Splice NEXT_TREE onto this one, given that all nodes in NEXT_TREE
+ // are greater than the maximum node in this tree. NEXT_TREE should
+ // not be used afterwards.
+ //
+ // Complexity: O(1) if the root of the splay tree is already the maximum
+ // node. Otherwise amortized O(log N), worst-cast O(N).
+ void splice_next_tree (rooted_splay_tree next_tree);
+
+ // The root of the tree is currently the maximum node. Replace it
+ // with NEW_NODE.
+ //
+ // Complexity: O(1).
+ void replace_max_node_at_root (node_type new_node);
+
+ // Remove the root node of the splay tree.
+ //
+ // Complexity: O(1) if removing the maximum or minimum node.
+ // Otherwise amortized O(log N), worst-cast O(N).
+ void remove_root ();
+
+ // Split the left child of the current root out into a separate tree
+ // and return the new tree.
+ rooted_splay_tree split_before_root ();
+
+ // Split the right child of the current root out into a separate tree
+ // and return the new tree.
+ rooted_splay_tree split_after_root ();
+
+ // If the root is not the minimum node of the splay tree, bring the previous
+ // node to the root and return true, otherwise return false.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ bool splay_prev_node ();
+
+ // If the root is not the maximum node of the splay tree, bring the next
+ // node to the root and return true, otherwise return false.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ bool splay_next_node ();
+
+ // Bring the minimum node of the splay tree to the root.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ void splay_min_node ();
+
+ // Bring the maximum node of the splay tree to the root.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ void splay_max_node ();
+
+ // Return the minimum node of the splay tree, or node_type () if the
+ // tree is empty. On return, the minimum node (if any) is also the
+ // root of the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ node_type min_node ();
+
+ // Return the maximum node of the splay tree, or node_type () if the
+ // tree is empty. On return, the maximum node (if any) is also the
+ // root of the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ node_type max_node ();
+
+ // Search the splay tree. For a given node N, COMPARE (N) should return:
+ //
+ // - a negative value if N is bigger than the node being searched for
+ // - zero if N is the node being searched for
+ // - a positive value if N is smaller than the node being searched for
+ //
+ // If the node that COMPARE is looking for exists, install it as the root
+ // node of the splay tree. Otherwise, arbitrarily pick either:
+ //
+ // - the maximum node that is smaller than the node being searched for or
+ // - the minimum node that is bigger than the node being searched for
+ //
+ // and install that node as the root instead.
+ //
+ // Return the result of COMPARE for the new root.
+ //
+ // This form of lookup is intended for cases in which both the following
+ // are true:
+ //
+ // (a) The work that COMPARE needs to do to detect if a node is too big
+ // is the same as the work that COMPARE needs to do to detect if a
+ // node is too small. (This is not true of range comparisons,
+ // for example.)
+ //
+ // (b) COMPARE is (or might be) relatively complex.
+ //
+ // This form of lookup is also useful if the items being compared naturally
+ // provide a <=>-style comparison result, without the result having to be
+ // forced by the equivalent of a ?: expression.
+ //
+ // The implementation only invokes COMPARE once per node.
+ //
+ // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+ // the complexity of the comparison.
+ template<typename Comparator>
+ auto lookup (Comparator compare) -> decltype (compare (m_root));
+
+ // Search the splay tree. For a given node N, WANT_SOMETHING_SMALLER (N)
+ // is true if N is too big and WANT_SOMETHING_BIGGER (N) is true if N
+ // is too small. Both functions return false if N is the node being
+ // searched for.
+ //
+ // If the node that is being searched for exists, install it as the root
+ // node of the splay tree and return 0. Otherwise, arbitrarily choose
+ // between these two options:
+ //
+ // - Install the maximum node that is smaller than the node being
+ // searched for as the root of the splay tree and return 1.
+ //
+ // - Install the minimum node that is bigger than the node being
+ // searched for and return -1.
+ //
+ // This form of lookup is intended for cases in which either of the
+ // following are true:
+ //
+ // (a) WANT_SOMETHING_SMALLER and WANT_SOMETHING_BIGGER test different
+ // parts of the node's data. For example, when comparing ranges,
+ // WANT_SOMETHING_SMALLER would test the lower limit of the given
+ // node's range while WANT_SOMETHING_BIGGER would test the upper
+ // limit of the given node's range.
+ //
+ // (b) There is no significant overhead to calling both
+ // WANT_SOMETHING_SMALLER and WANT_SOMETHING_BIGGER for the same node.
+ //
+ // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+ // the complexity of the comparisons.
+ template<typename LeftPredicate, typename RightPredicate>
+ int lookup (LeftPredicate want_something_smaller,
+ RightPredicate want_something_bigger);
+
+ // Keep the ability to print subtrees.
+ using parent::print;
+
+ // Print the tree to PP for debugging purposes, using PRINTER (PP, N)
+ // to print the data for node N.
+ template<typename Printer>
+ void print (pretty_printer *pp, Printer printer) const;
+
+protected:
+ using parent::get_child;
+ using parent::set_child;
+ using parent::promote_child;
+
+ using parent::set_parent;
+
+ template<unsigned int N>
+ bool splay_neighbor ();
+};
+
+// Provide splay tree routines for nodes of type Accessors::node_type,
+// which doesn't have a parent field. Use Accessors::child to access
+// the children of a node.
+template<typename Accessors>
+using splay_tree_without_parent
+ = rooted_splay_tree<splay_tree_accessors_without_parent<Accessors>>;
+
+// A splay tree for nodes of type Node, which is usually a pointer type.
+// The child nodes are stored in a member variable:
+//
+// Node m_children[2];
+//
+// Node does not have a parent field.
+template<typename Node>
+using default_splay_tree
+ = splay_tree_without_parent<default_splay_tree_accessors<Node>>;
+
+// A simple splay tree node that stores a value of type T.
+template<typename T>
+class splay_tree_node
+{
+ friend class default_splay_tree_accessors<splay_tree_node *>;
+
+public:
+ splay_tree_node () = default;
+ splay_tree_node (T value) : m_value (value), m_children () {}
+
+ T &value () { return m_value; }
+ const T &value () const { return m_value; }
+
+private:
+ T m_value;
+ splay_tree_node *m_children[2];
+};
+
+// A splay tree whose nodes hold values of type T.
+template<typename T>
+using splay_tree = default_splay_tree<splay_tree_node<T> *>;
+
+// Provide splay tree routines for cases in which the root of the tree
+// is not explicitly stored.
+//
+// The nodes of the tree have type Accessors::node_type, which is usually
+// a pointer type. The nodes have a link back to their parent.
+//
+// The Accessors class provides the following static member functions:
+//
+// - Accessors::child (NODE, INDEX)
+// INDEX is guaranteed to be 0 or 1. If INDEX is 0, return a reference
+// to where NODE's left child is stored, otherwise return a reference
+// to where NODE's right child is stored.
+//
+// - Accessors::parent (NODE)
+// Return a reference to where NODE's parent is stored.
+template<typename Accessors>
+class rootless_splay_tree
+ : public base_splay_tree<splay_tree_accessors_with_parent<Accessors>>
+{
+ using full_accessors = splay_tree_accessors_with_parent<Accessors>;
+ using parent = base_splay_tree<full_accessors>;
+
+public:
+ using rooted = rooted_splay_tree<full_accessors>;
+
+ using typename Accessors::node_type;
+
+ // Remove NODE from the splay tree. Return the node that replaces it,
+ // or null if NODE had no children.
+ //
+ // Complexity: O(1) if removing the maximum or minimum node.
+ // Otherwise amortized O(log N), worst-cast O(N).
+ static node_type remove_node (node_type node);
+
+ // Splay NODE so that it becomes the root of the splay tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static void splay (node_type node);
+
+ // Like splay, but take advantage of the fact that NODE is known to be
+ // the minimum node in the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static void splay_known_min_node (node_type node);
+
+ // Like splay, but take advantage of the fact that NODE is known to be
+ // the maximum node in the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static void splay_known_max_node (node_type node);
+
+ // Splay NODE while looking for an ancestor node N for which PREDICATE (N)
+ // is true. If such an ancestor node exists, stop the splay operation
+ // early and return PREDICATE (N). Otherwise, complete the splay operation
+ // and return DEFAULT_RESULT. In the latter case, NODE is now the root of
+ // the splay tree.
+ //
+ // Note that this routine only examines nodes that happen to be ancestors
+ // of NODE. It does not search the full tree.
+ //
+ // Complexity: amortized O(P log N), worst-cast O(P N), where P is the
+ // complexity of the predicate.
+ template<typename DefaultResult, typename Predicate>
+ static auto splay_and_search (node_type node, DefaultResult default_result,
+ Predicate predicate)
+ -> decltype (predicate (node, 0));
+
+ // NODE1 and NODE2 are known to belong to the same splay tree. Return:
+ //
+ // -1 if NODE1 < NODE2
+ // 0 if NODE1 == NODE2
+ // 1 if NODE1 > NODE2
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static int compare_nodes (node_type node1, node_type node2);
+
+protected:
+ using parent::get_child;
+ using parent::set_child;
+ using parent::promote_child;
+
+ static node_type get_parent (node_type);
+ using parent::set_parent;
+
+ static unsigned int child_index (node_type, node_type);
+
+ static int compare_nodes_one_way (node_type, node_type);
+
+ template<unsigned int N>
+ static void splay_known_limit (node_type);
+};
+
+// Provide rootless splay tree routines for nodes of type Node.
+// The child nodes are stored in a member variable:
+//
+// Node m_children[2];
+//
+// and the parent node is stored in a member variable:
+//
+// Node m_parent;
+template<typename Node>
+using default_rootless_splay_tree
+ = rootless_splay_tree<default_splay_tree_accessors_with_parent<Node>>;
+
+#include "splay-tree-utils.tcc"
diff --git a/gcc/splay-tree-utils.tcc b/gcc/splay-tree-utils.tcc
new file mode 100644
index 0000000..5c9c859
--- /dev/null
+++ b/gcc/splay-tree-utils.tcc
@@ -0,0 +1,960 @@
+// Splay tree utilities -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// INDEX is either 0 or 1. If it is 0, return NODE's left child,
+// otherwise return NODE's right child.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::get_child (node_type node, unsigned int index)
+{
+ return Accessors::child (node, index);
+}
+
+// INDEX is either 0 or 1. If it is 0, change NODE's left child to CHILD,
+// otherwise change NODE's right child to CHILD. If CHILD has a parent
+// field, record that its parent is now NODE.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::set_child (node_type node, unsigned int index,
+ node_type child)
+{
+ Accessors::child (node, index) = child;
+ if (child)
+ set_parent (child, node);
+}
+
+// Rotate the tree to promote child number INDEX of NODE, so that that
+// child becomes a parent of NODE. Return the promoted node.
+//
+// The caller has the responsibility of assigning a correct parent
+// to the returned node.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index)
+{
+ node_type promoted = get_child (node, index);
+ set_child (node, index, get_child (promoted, 1 - index));
+ set_child (promoted, 1 - index, node);
+ return promoted;
+}
+
+// Treat child number INDEX of NODE as being CHILD and rotate the tree
+// so that CHILD becomes a parent of NODE.
+//
+// The caller has the responsibility of assigning a correct parent to CHILD.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index,
+ node_type child)
+{
+ set_child (node, index, get_child (child, 1 - index));
+ set_child (child, 1 - index, node);
+}
+
+// Print NODE to PP, using PRINTER (PP, N) to print the contents of node N.
+// Prefix each new line with INDENT_STRING. CODE is 'T' if NODE is the root
+// node, 'L' if NODE is the left child of its parent, or 'R' if NODE is the
+// right child of its parent.
+template<typename Accessors>
+template<typename Printer>
+void
+base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
+ Printer printer, char code,
+ vec<char> &indent_string)
+{
+ // In the comments below, PREFIX refers to the incoming contents
+ // of INDENT_STRING.
+ node_type left = get_child (node, 0);
+ node_type right = get_child (node, 1);
+
+ auto orig_indent_len = indent_string.length ();
+ indent_string.safe_grow (orig_indent_len + 3);
+ char *extra_indent = indent_string.address () + orig_indent_len;
+
+ // Print [T], [L], or [R].
+ extra_indent[0] = '[';
+ extra_indent[1] = code;
+ extra_indent[2] = ']';
+ pp_append_text (pp, extra_indent, indent_string.end ());
+ pp_space (pp);
+
+ // Print the node itself, using PREFIX + " | " or PREFIX + " " to indent
+ // new lines under the "[_]" that we just printed.
+ extra_indent[0] = ' ';
+ extra_indent[1] = (left || right ? '|' : ' ');
+ extra_indent[2] = ' ';
+ {
+ pretty_printer sub_pp;
+ printer (&sub_pp, node);
+ const char *text = pp_formatted_text (&sub_pp);
+ while (const char *end = strchr (text, '\n'))
+ {
+ pp_append_text (pp, text, end);
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), indent_string.end ());
+ text = end + 1;
+ }
+ pp_string (pp, text);
+ }
+
+ if (left)
+ {
+ // Print PREFIX + " +-" for the first line of the left subtree,
+ // to be followed by "[L]".
+ extra_indent[1] = '+';
+ extra_indent[2] = '-';
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), indent_string.end ());
+
+ // Print the left subtree, using PREFIX + " | " or PREFIX + " "
+ // to indent under the PREFIX + " +-" that we just printed.
+ extra_indent[1] = right ? '|' : ' ';
+ extra_indent[2] = ' ';
+ print (pp, left, printer, 'L', indent_string);
+ extra_indent = indent_string.address () + orig_indent_len;
+
+ // If LEFT is not a leaf and we also have a right subtree, use a
+ // PREFIX + " |" line to separate them.
+ if (right && (get_child (left, 0) || get_child (left, 1)))
+ {
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), &extra_indent[2]);
+ }
+ }
+ if (right)
+ {
+ // Print PREFIX + " +-" for the first line of the right subtree,
+ // to be followed by "[R]".
+ extra_indent[1] = '+';
+ extra_indent[2] = '-';
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), indent_string.end ());
+
+ // Print the right subtree, using PREFIX + " " to indent under the
+ // PREFIX + " +-" that we just printed.
+ extra_indent[1] = ' ';
+ extra_indent[2] = ' ';
+ print (pp, right, printer, 'R', indent_string);
+ }
+ indent_string.truncate (orig_indent_len);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Printer>
+void
+base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
+ Printer printer)
+{
+ if (!node)
+ {
+ pp_string (pp, "null");
+ return;
+ }
+ auto_vec<char, 64> indent_string;
+ print (pp, node, printer, 'T', indent_string);
+}
+
+// If N is 1, splay the last (rightmost) node reachable from START
+// to the position that START current holds and return the splayed node.
+// START is not itself the last node.
+//
+// If N is 0, splay the first (leftmost) node reachable from START
+// to the position that START current holds and return the splayed node.
+// START is not itself the first node.
+//
+// The caller has the responsibility of updating the parent of the
+// returned node.
+template<typename Accessors>
+template<unsigned int N>
+typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::splay_limit (node_type start)
+{
+ // This essentially follows the simpilfied top-down method described
+ // in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
+ // specialized for the case in which the comparison result is fixed.
+ // The first iteration is peeled to avoid the need for stack temporaries.
+ //
+ // The comments and names reflect the behavior for N == 1, but the
+ // N == 0 case behaves analogously.
+
+ // Rotate the tree to promote the right child of START to the root.
+ node_type node = promote_child (start, N);
+ if (node_type right = get_child (node, N))
+ {
+ // Perform the link left step, which for this first iteration
+ // means making NODE the root of the left tree.
+ //
+ // NODE will become left child of the final node. For a right
+ // spine starting at NODE of the form:
+ //
+ // 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> ... -> N
+ // | | | | | | | |
+ // V V V V V V V V
+ // A B C D E F G NL
+ //
+ // the next step is to create a subtree of N whose right spine contains
+ // the odd-numbered nodes, as follows:
+ //
+ // N
+ // |
+ // V
+ // 1 ------> 3 ------> 5 ------> 7 -> .... -> NL
+ // | | | |
+ // V V V V
+ // A 2 -> C 4 -> E 6 -> G
+ // | | |
+ // V V V
+ // B D F
+ //
+ // First record 1 as the left child of the final root (N) and move
+ // on to node 2.
+ node_type final_child = node;
+ node_type new_spine_end = node;
+ node = right;
+ while (node_type right = get_child (node, N))
+ {
+ // Perform another rotate left step.
+ //
+ // We've built the tree rooted at 1 in the diagram above up to,
+ // but not including, an even-numbered node NODE on the original
+ // right spine. Rotate the tree at NODE to promote the following
+ // odd-numbered node.
+ promote_child (node, N, right);
+ node = right;
+ if (node_type right = get_child (node, N))
+ {
+ // Perform another link left step.
+ //
+ // Add the promoted odd-numbered node to the right spine of the
+ // tree rooted at 1 and move on to the next even-numbered node.
+ set_child (new_spine_end, N, node);
+ new_spine_end = node;
+ node = right;
+ }
+ }
+ // Perform the assembly step.
+ //
+ // Add NL to the new spine and make N the new root.
+ set_child (new_spine_end, N, get_child (node, 1 - N));
+ set_child (node, 1 - N, final_child);
+ }
+ return node;
+}
+
+// Remove NODE from its position in the splay tree. If NODE has at least
+// one child node, return the node that should now hold NODE's position in
+// the splay tree. If NODE has no children, return null.
+//
+// The caller has the responsibility of updating the parent of the
+// returned node.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::remove_node_internal (node_type node)
+{
+ node_type left = get_child (node, 0);
+ node_type right = get_child (node, 1);
+ if (!left)
+ return right;
+
+ if (!right)
+ return left;
+
+ if (get_child (left, 1))
+ {
+ left = splay_limit<1> (left);
+ gcc_checking_assert (!get_child (left, 1));
+ }
+ set_child (left, 1, right);
+ return left;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::insert_child (node_type node, unsigned int index,
+ node_type child)
+{
+ gcc_checking_assert (!get_child (child, 0) && !get_child (child, 1));
+ set_child (child, index, get_child (node, index));
+ set_child (node, index, child);
+}
+
+// Implement splay_next_node if N == 1 and splay_prev_node if N == 0.
+template<typename Accessors>
+template<unsigned int N>
+bool
+rooted_splay_tree<Accessors>::splay_neighbor ()
+{
+ node_type node = m_root;
+ node_type new_root = get_child (node, N);
+ if (!new_root)
+ return false;
+
+ if (get_child (new_root, 1 - N))
+ {
+ // NEW_ROOT is not itself the required node, so splay the required
+ // node into its place.
+ new_root = parent::template splay_limit<1 - N> (new_root);
+ gcc_checking_assert (!get_child (new_root, 1 - N));
+ set_child (node, N, node_type ());
+ set_child (new_root, 1 - N, node);
+ }
+ else
+ promote_child (node, N, new_root);
+ set_parent (new_root, node_type ());
+ m_root = new_root;
+ return true;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Comparator>
+bool
+rooted_splay_tree<Accessors>::insert (node_type new_node, Comparator compare)
+{
+ gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
+ if (!m_root)
+ {
+ m_root = new_node;
+ return true;
+ }
+
+ int comparison = lookup (compare);
+ if (comparison == 0)
+ return false;
+
+ // Insert NEW_NODE before M_ROOT if COMPARISON < 0 and after M_ROOT
+ // otherwise.
+ set_child (new_node, comparison < 0, m_root);
+ set_child (new_node, comparison > 0, get_child (m_root, comparison > 0));
+ set_child (m_root, comparison > 0, nullptr);
+ m_root = new_node;
+ return true;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::insert_max_node (node_type new_node)
+{
+ gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
+ set_child (new_node, 0, m_root);
+ m_root = new_node;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splice_next_tree (rooted_splay_tree next_tree)
+{
+ splay_max_node ();
+ set_child (m_root, 1, next_tree.m_root);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::replace_max_node_at_root (node_type new_node)
+{
+ node_type old_node = m_root;
+ gcc_checking_assert (!get_child (new_node, 0)
+ && !get_child (new_node, 1)
+ && !get_child (old_node, 1));
+ set_child (new_node, 0, get_child (old_node, 0));
+ // Clear the links from OLD_NODE. Its parent and right child are
+ // already node_type ().
+ set_child (old_node, 0, node_type ());
+ m_root = new_node;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::remove_root ()
+{
+ node_type node = m_root;
+ m_root = parent::remove_node_internal (node);
+ if (m_root)
+ set_parent (m_root, node_type ());
+ // Clear the links from NODE. Its parent is already node_type ().
+ set_child (node, 0, node_type ());
+ set_child (node, 1, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline rooted_splay_tree<Accessors>
+rooted_splay_tree<Accessors>::split_before_root ()
+{
+ node_type new_root = get_child (m_root, 0);
+ set_child (m_root, 0, node_type ());
+ set_parent (new_root, node_type ());
+ return new_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline rooted_splay_tree<Accessors>
+rooted_splay_tree<Accessors>::split_after_root ()
+{
+ node_type new_root = get_child (m_root, 1);
+ set_child (m_root, 1, node_type ());
+ set_parent (new_root, node_type ());
+ return new_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline bool
+rooted_splay_tree<Accessors>::splay_prev_node ()
+{
+ return splay_neighbor<0> ();
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline bool
+rooted_splay_tree<Accessors>::splay_next_node ()
+{
+ return splay_neighbor<1> ();
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splay_min_node ()
+{
+ if (m_root && get_child (m_root, 0))
+ {
+ m_root = parent::template splay_limit<0> (m_root);
+ set_parent (m_root, node_type ());
+ }
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splay_max_node ()
+{
+ if (m_root && get_child (m_root, 1))
+ {
+ m_root = parent::template splay_limit<1> (m_root);
+ set_parent (m_root, node_type ());
+ }
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline typename rooted_splay_tree<Accessors>::node_type
+rooted_splay_tree<Accessors>::min_node ()
+{
+ splay_min_node ();
+ return m_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline typename rooted_splay_tree<Accessors>::node_type
+rooted_splay_tree<Accessors>::max_node ()
+{
+ splay_max_node ();
+ return m_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Comparator>
+auto
+rooted_splay_tree<Accessors>::lookup (Comparator compare)
+ -> decltype (compare (m_root))
+{
+ // This essentially follows the simpilfied top-down method described
+ // in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
+ // with the complication that the comparisons are done only once.
+ using result_type = decltype (compare (m_root));
+
+ // The roots of the left and right trees.
+ node_type link_left_root = node_type ();
+ node_type link_right_root = node_type ();
+
+ // Where to add new nodes to the left and right trees.
+ node_type *link_left_ptr = &link_left_root;
+ node_type *link_right_ptr = &link_right_root;
+
+ // The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
+ // once they no longer point to the roots above.
+ node_type link_left_parent = node_type ();
+ node_type link_right_parent = node_type ();
+
+ auto link_left = [&](node_type node)
+ {
+ *link_left_ptr = node;
+ link_left_ptr = &Accessors::child (node, 1);
+ set_parent (node, link_left_parent);
+ link_left_parent = node;
+ };
+
+ auto link_right = [&](node_type node)
+ {
+ *link_right_ptr = node;
+ link_right_ptr = &Accessors::child (node, 0);
+ set_parent (node, link_right_parent);
+ link_right_parent = node;
+ };
+
+ node_type node = m_root;
+ node_type parent = node_type ();
+ result_type result;
+ result_type old_result = 0;
+ while (1)
+ {
+ // OLD_RESULT is 0 if NODE is the root of the middle tree.
+ // Otherwise, PARENT is the root of the middle tree and OLD_RESULT
+ // is how it compared.
+ //
+ // Results are:
+ // < 0 if we want something smaller.
+ // = 0 if we found the right node.
+ // > 0 if we want something bigger.
+ result = compare (node);
+ if (old_result < 0)
+ {
+ if (result < 0)
+ {
+ // SEARCH < NODE < PARENT
+ //
+ // Promote NODE (rotate right).
+ promote_child (parent, 0, node);
+ node_type next = get_child (node, 0);
+ if (!next)
+ break;
+
+ link_right (node);
+
+ // NEXT is now the root of the middle tree.
+ node = next;
+ old_result = 0;
+ continue;
+ }
+
+ // SEARCH >= NODE, NODE < PARENT
+ link_right (parent);
+ }
+ else if (old_result > 0)
+ {
+ if (result > 0)
+ {
+ // SEARCH > NODE > PARENT
+ //
+ // Promote NODE (rotate left).
+ promote_child (parent, 1, node);
+ node_type next = get_child (node, 1);
+ if (!next)
+ break;
+
+ link_left (node);
+
+ // NEXT is now the root of the middle tree.
+ node = next;
+ old_result = 0;
+ continue;
+ }
+
+ // SEARCH <= NODE, NODE > PARENT
+ link_left (parent);
+ }
+
+ // Microoptimization to allow NODE to be read even if RESULT == 0.
+ node_type next = get_child (node, result >= 0);
+ if (result == 0 || !next)
+ break;
+
+ // NODE is now the root of the tree.
+ parent = node;
+ node = next;
+ old_result = result;
+ }
+
+ node_type new_left = link_left_root;
+ node_type new_right = link_right_root;
+
+ if (new_left)
+ {
+ node_type old_left = get_child (node, 0);
+ *link_left_ptr = old_left;
+ if (old_left)
+ set_parent (old_left, link_left_parent);
+ set_child (node, 0, new_left);
+ }
+
+ if (new_right)
+ {
+ node_type old_right = get_child (node, 1);
+ *link_right_ptr = old_right;
+ if (old_right)
+ set_parent (old_right, link_right_parent);
+ set_child (node, 1, new_right);
+ }
+
+ set_parent (node, node_type ());
+ m_root = node;
+ return result;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename LeftPredicate, typename RightPredicate>
+int
+rooted_splay_tree<Accessors>::lookup (LeftPredicate want_something_smaller,
+ RightPredicate want_something_bigger)
+{
+ // This essentially follows the simpilfied top-down method described
+ // in Sleator and Tarjan's "Self-adjusting Binary Search Trees"
+ // (and follows it more closely than the single-comparator version above).
+
+ // The roots of the left and right trees.
+ node_type link_left_root = node_type ();
+ node_type link_right_root = node_type ();
+
+ // Where to add new nodes to the left and right trees.
+ node_type *link_left_ptr = &link_left_root;
+ node_type *link_right_ptr = &link_right_root;
+
+ // The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
+ // once they no longer point to the roots above.
+ node_type link_left_parent = node_type ();
+ node_type link_right_parent = node_type ();
+
+ node_type node = m_root;
+ int result;
+ for (;;)
+ {
+ // NODE is the root of the middle tree.
+ if (want_something_smaller (node))
+ {
+ result = -1;
+ node_type next = get_child (node, 0);
+ if (!next)
+ break;
+
+ if (want_something_smaller (next))
+ {
+ // Promote NODE (rotate right).
+ promote_child (node, 0, next);
+ node = next;
+ next = get_child (node, 0);
+ if (!next)
+ break;
+ }
+
+ // Add NODE to the right tree (link right).
+ *link_right_ptr = node;
+ link_right_ptr = &Accessors::child (node, 0);
+ set_parent (node, link_right_parent);
+ link_right_parent = node;
+
+ node = next;
+ }
+ else if (want_something_bigger (node))
+ {
+ result = 1;
+ node_type next = get_child (node, 1);
+ if (!next)
+ break;
+
+ if (want_something_bigger (next))
+ {
+ // Promote NODE (rotate left).
+ promote_child (node, 1, next);
+ node = next;
+ next = get_child (node, 1);
+ if (!next)
+ break;
+ }
+
+ // Add NODE to the left tree (link left).
+ *link_left_ptr = node;
+ link_left_ptr = &Accessors::child (node, 1);
+ set_parent (node, link_left_parent);
+ link_left_parent = node;
+
+ node = next;
+ }
+ else
+ {
+ result = 0;
+ break;
+ }
+ }
+
+ node_type new_left = link_left_root;
+ node_type new_right = link_right_root;
+
+ if (new_left)
+ {
+ node_type old_left = get_child (node, 0);
+ *link_left_ptr = old_left;
+ if (old_left)
+ set_parent (old_left, link_left_parent);
+ set_child (node, 0, new_left);
+ }
+
+ if (new_right)
+ {
+ node_type old_right = get_child (node, 1);
+ *link_right_ptr = old_right;
+ if (old_right)
+ set_parent (old_right, link_right_parent);
+ set_child (node, 1, new_right);
+ }
+
+ set_parent (node, node_type ());
+ m_root = node;
+ return result;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Printer>
+inline void
+rooted_splay_tree<Accessors>::print (pretty_printer *pp, Printer printer) const
+{
+ print (pp, m_root, printer);
+}
+
+// Return NODE's current parent.
+template<typename Accessors>
+inline typename rootless_splay_tree<Accessors>::node_type
+rootless_splay_tree<Accessors>::get_parent (node_type node)
+{
+ return Accessors::parent (node);
+}
+
+// CHILD is known to be a child of PARENT. Return which index it has.
+template<typename Accessors>
+inline unsigned int
+rootless_splay_tree<Accessors>::child_index (node_type parent, node_type child)
+{
+ return get_child (parent, 1) == child;
+}
+
+// If N == 1, implement splay_known_max_node, otherwise implement
+// splay_known_min_node.
+template<typename Accessors>
+template<unsigned int N>
+inline void
+rootless_splay_tree<Accessors>::splay_known_limit (node_type node)
+{
+ node_type child = node;
+ node_type parent = get_parent (child);
+ if (!parent)
+ return;
+
+ do
+ // At this point, NODE conceptually replaces CHILD as a child of
+ // PARENT, but we haven't yet updated PARENT accordingly.
+ if (node_type grandparent = get_parent (parent))
+ {
+ node_type greatgrandparent = get_parent (grandparent);
+ promote_child (grandparent, N, parent);
+ promote_child (parent, N, node);
+ child = grandparent;
+ parent = greatgrandparent;
+ }
+ else
+ {
+ promote_child (parent, N, node);
+ break;
+ }
+ while (parent);
+ set_parent (node, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+typename rootless_splay_tree<Accessors>::node_type
+rootless_splay_tree<Accessors>::remove_node (node_type node)
+{
+ node_type replacement = parent::remove_node_internal (node);
+ if (node_type parent = get_parent (node))
+ set_child (parent, child_index (parent, node), replacement);
+ else if (replacement)
+ set_parent (replacement, node_type ());
+ // Clear the links from NODE.
+ set_parent (node, node_type ());
+ set_child (node, 0, node_type ());
+ set_child (node, 1, node_type ());
+ return replacement;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+void
+rootless_splay_tree<Accessors>::splay (node_type node)
+{
+ node_type child = node;
+ node_type parent = get_parent (child);
+ if (!parent)
+ return;
+
+ do
+ {
+ // At this point, NODE conceptually replaces CHILD as a child of
+ // PARENT, but we haven't yet updated PARENT accordingly.
+ unsigned int index = child_index (parent, child);
+ if (node_type grandparent = get_parent (parent))
+ {
+ node_type greatgrandparent = get_parent (grandparent);
+ unsigned int parent_index = child_index (grandparent, parent);
+ if (index == parent_index)
+ {
+ promote_child (grandparent, parent_index, parent);
+ promote_child (parent, index, node);
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ promote_child (grandparent, parent_index, node);
+ }
+ child = grandparent;
+ parent = greatgrandparent;
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ break;
+ }
+ }
+ while (parent);
+ set_parent (node, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rootless_splay_tree<Accessors>::splay_known_min_node (node_type node)
+{
+ splay_known_limit<0> (node);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rootless_splay_tree<Accessors>::splay_known_max_node (node_type node)
+{
+ splay_known_limit<1> (node);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename DefaultResult, typename Predicate>
+auto
+rootless_splay_tree<Accessors>::
+splay_and_search (node_type node, DefaultResult default_result,
+ Predicate predicate)
+ -> decltype (predicate (node, 0))
+{
+ using Result = decltype (predicate (node, 0));
+
+ node_type child = node;
+ node_type parent = get_parent (child);
+ if (!parent)
+ return default_result;
+
+ do
+ {
+ // At this point, NODE conceptually replaces CHILD as a child of
+ // PARENT, but we haven't yet updated PARENT accordingly.
+ unsigned int index = child_index (parent, child);
+ if (Result result = predicate (parent, index))
+ {
+ set_child (parent, index, node);
+ return result;
+ }
+ if (node_type grandparent = get_parent (parent))
+ {
+ node_type greatgrandparent = get_parent (grandparent);
+ unsigned int parent_index = child_index (grandparent, parent);
+ if (Result result = predicate (grandparent, parent_index))
+ {
+ set_child (parent, index, node);
+ return result;
+ }
+ if (index == parent_index)
+ {
+ promote_child (grandparent, parent_index, parent);
+ promote_child (parent, index, node);
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ promote_child (grandparent, parent_index, node);
+ }
+ child = grandparent;
+ parent = greatgrandparent;
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ break;
+ }
+ }
+ while (parent);
+ set_parent (node, node_type ());
+ return default_result;
+}
+
+// Splay NODE1 looking to see if one of its ancestors is NODE2. If it is,
+// return -1 if NODE1 comes before NODE2 or 1 if NODE1 comes after NODE2.
+// Return 0 if NODE2 is not an ancestor of NODE1.
+template<typename Accessors>
+int
+rootless_splay_tree<Accessors>::compare_nodes_one_way (node_type node1,
+ node_type node2)
+{
+ auto compare = [&](node_type parent, unsigned int index) -> int
+ {
+ if (parent == node2)
+ return index ? 1 : -1;
+ return 0;
+ };
+ return splay_and_search (node1, 0, compare);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+int
+rootless_splay_tree<Accessors>::compare_nodes (node_type node1,
+ node_type node2)
+{
+ if (node1 == node2)
+ return 0;
+
+ // Splay NODE1 looking for NODE2.
+ int cmp = compare_nodes_one_way (node1, node2);
+ if (cmp)
+ return cmp;
+
+ // That failed, but NODE1 is now the root of the tree. Splay NODE2
+ // to see on which side of NODE1 it falls.
+ cmp = compare_nodes_one_way (node2, node1);
+ gcc_checking_assert (cmp);
+ return -cmp;
+}
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index dff81d1..ee1cf55 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -393,6 +393,9 @@ int_mode_for_mode (machine_mode mode)
case MODE_VECTOR_UACCUM:
return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
+ case MODE_OPAQUE:
+ return opt_scalar_int_mode ();
+
case MODE_RANDOM:
if (mode == BLKmode)
return opt_scalar_int_mode ();
diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index a38eb1d..3944f11 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -28,31 +28,75 @@ class function_summary_base
{
public:
/* Default construction takes SYMTAB as an argument. */
- function_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
- m_symtab (symtab),
- m_insertion_enabled (true),
+ function_summary_base (symbol_table *symtab,
+ cgraph_node_hook symtab_insertion,
+ cgraph_node_hook symtab_removal,
+ cgraph_2node_hook symtab_duplication
+ CXX_MEM_STAT_INFO):
+ m_symtab (symtab), m_symtab_insertion (symtab_insertion),
+ m_symtab_removal (symtab_removal),
+ m_symtab_duplication (symtab_duplication),
+ m_symtab_insertion_hook (NULL), m_symtab_duplication_hook (NULL),
m_allocator ("function summary" PASS_MEM_STAT)
- {}
+ {
+ enable_insertion_hook ();
+ m_symtab_removal_hook
+ = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this);
+ enable_duplication_hook ();
+ }
/* Basic implementation of insert operation. */
- virtual void insert (cgraph_node *, T *) {}
+ virtual void insert (cgraph_node *, T *)
+ {
+ /* In most cases, it makes no sense to create summaries without
+ initializing them. */
+ gcc_unreachable ();
+ }
/* Basic implementation of removal operation. */
virtual void remove (cgraph_node *, T *) {}
/* Basic implementation of duplication operation. */
- virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
+ virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
+ {
+ /* It makes no sense to not copy anything during duplication. */
+ gcc_unreachable ();
+ }
/* Enable insertion hook invocation. */
void enable_insertion_hook ()
{
- m_insertion_enabled = true;
+ if (m_symtab_insertion_hook == NULL)
+ m_symtab_insertion_hook
+ = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
}
/* Enable insertion hook invocation. */
void disable_insertion_hook ()
{
- m_insertion_enabled = false;
+ if (m_symtab_insertion_hook != NULL)
+ {
+ m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
+ m_symtab_insertion_hook = NULL;
+ }
+ }
+
+ /* Enable duplication hook invocation. */
+ void enable_duplication_hook ()
+ {
+ if (m_symtab_duplication_hook == NULL)
+ m_symtab_duplication_hook
+ = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this);
+ }
+
+ /* Enable duplication hook invocation. */
+ void disable_duplication_hook ()
+ {
+ if (m_symtab_duplication_hook != NULL)
+ {
+ m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
+ m_symtab_duplication_hook = NULL;
+ }
}
protected:
@@ -77,17 +121,22 @@ protected:
/* Unregister all call-graph hooks. */
void unregister_hooks ();
+ /* Symbol table the summary is registered to. */
+ symbol_table *m_symtab;
+
+ /* Insertion function defined by a summary. */
+ cgraph_node_hook m_symtab_insertion;
+ /* Removal function defined by a summary. */
+ cgraph_node_hook m_symtab_removal;
+ /* Duplication function defined by a summary. */
+ cgraph_2node_hook m_symtab_duplication;
+
/* Internal summary insertion hook pointer. */
cgraph_node_hook_list *m_symtab_insertion_hook;
/* Internal summary removal hook pointer. */
cgraph_node_hook_list *m_symtab_removal_hook;
/* Internal summary duplication hook pointer. */
cgraph_2node_hook_list *m_symtab_duplication_hook;
- /* Symbol table the summary is registered to. */
- symbol_table *m_symtab;
-
- /* Indicates if insertion hook is enabled. */
- bool m_insertion_enabled;
private:
/* Return true when the summary uses GGC memory for allocation. */
@@ -101,9 +150,9 @@ template <typename T>
void
function_summary_base<T>::unregister_hooks ()
{
- m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
+ disable_insertion_hook ();
m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
- m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
+ disable_duplication_hook ();
}
/* We want to pass just pointer types as argument for function_summary
@@ -218,19 +267,11 @@ private:
template <typename T>
function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
MEM_STAT_DECL):
- function_summary_base<T> (symtab PASS_MEM_STAT), m_ggc (ggc),
- m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT)
-{
- this->m_symtab_insertion_hook
- = this->m_symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
- this);
- this->m_symtab_removal_hook
- = this->m_symtab->add_cgraph_removal_hook (function_summary::symtab_removal,
- this);
- this->m_symtab_duplication_hook
- = this->m_symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication,
- this);
-}
+ function_summary_base<T> (symtab, function_summary::symtab_insertion,
+ function_summary::symtab_removal,
+ function_summary::symtab_duplication
+ PASS_MEM_STAT),
+ m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
template <typename T>
function_summary<T *>::~function_summary ()
@@ -249,9 +290,7 @@ function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
{
gcc_checking_assert (node->get_uid ());
function_summary *summary = (function_summary <T *> *) (data);
-
- if (summary->m_insertion_enabled)
- summary->insert (node, summary->get_create (node));
+ summary->insert (node, summary->get_create (node));
}
template <typename T>
@@ -412,19 +451,15 @@ private:
};
template <typename T, typename V>
-fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab MEM_STAT_DECL):
- function_summary_base<T> (symtab PASS_MEM_STAT), m_vector (NULL)
+fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab
+ MEM_STAT_DECL):
+ function_summary_base<T> (symtab,
+ fast_function_summary::symtab_insertion,
+ fast_function_summary::symtab_removal,
+ fast_function_summary::symtab_duplication
+ PASS_MEM_STAT), m_vector (NULL)
{
vec_alloc (m_vector, 13 PASS_MEM_STAT);
- this->m_symtab_insertion_hook
- = this->m_symtab->add_cgraph_insertion_hook (fast_function_summary::symtab_insertion,
- this);
- this->m_symtab_removal_hook
- = this->m_symtab->add_cgraph_removal_hook (fast_function_summary::symtab_removal,
- this);
- this->m_symtab_duplication_hook
- = this->m_symtab->add_cgraph_duplication_hook (fast_function_summary::symtab_duplication,
- this);
}
template <typename T, typename V>
@@ -445,9 +480,7 @@ fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
{
gcc_checking_assert (node->get_uid ());
fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
-
- if (summary->m_insertion_enabled)
- summary->insert (node, summary->get_create (node));
+ summary->insert (node, summary->get_create (node));
}
template <typename T, typename V>
@@ -533,17 +566,45 @@ class call_summary_base
{
public:
/* Default construction takes SYMTAB as an argument. */
- call_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
- m_symtab (symtab),
+ call_summary_base (symbol_table *symtab, cgraph_edge_hook symtab_removal,
+ cgraph_2edge_hook symtab_duplication CXX_MEM_STAT_INFO):
+ m_symtab (symtab), m_symtab_removal (symtab_removal),
+ m_symtab_duplication (symtab_duplication), m_symtab_duplication_hook (NULL),
m_initialize_when_cloning (false),
m_allocator ("call summary" PASS_MEM_STAT)
- {}
+ {
+ m_symtab_removal_hook
+ = m_symtab->add_edge_removal_hook (m_symtab_removal, this);
+ enable_duplication_hook ();
+ }
/* Basic implementation of removal operation. */
virtual void remove (cgraph_edge *, T *) {}
/* Basic implementation of duplication operation. */
- virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
+ virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
+ {
+ gcc_unreachable ();
+ }
+
+ /* Enable duplication hook invocation. */
+ void enable_duplication_hook ()
+ {
+ if (m_symtab_duplication_hook == NULL)
+ m_symtab_duplication_hook
+ = m_symtab->add_edge_duplication_hook (m_symtab_duplication,
+ this);
+ }
+
+ /* Enable duplication hook invocation. */
+ void disable_duplication_hook ()
+ {
+ if (m_symtab_duplication_hook != NULL)
+ {
+ m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
+ m_symtab_duplication_hook = NULL;
+ }
+ }
protected:
/* Allocates new data that are stored within map. */
@@ -570,6 +631,11 @@ protected:
/* Symbol table the summary is registered to. */
symbol_table *m_symtab;
+ /* Removal function defined by a summary. */
+ cgraph_edge_hook m_symtab_removal;
+ /* Duplication function defined by a summary. */
+ cgraph_2edge_hook m_symtab_duplication;
+
/* Internal summary removal hook pointer. */
cgraph_edge_hook_list *m_symtab_removal_hook;
/* Internal summary duplication hook pointer. */
@@ -590,7 +656,7 @@ void
call_summary_base<T>::unregister_hooks ()
{
m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
- m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
+ disable_duplication_hook ();
}
/* An impossible class templated by non-pointers so, which makes sure that only
@@ -612,16 +678,9 @@ public:
/* Default construction takes SYMTAB as an argument. */
call_summary (symbol_table *symtab, bool ggc = false
CXX_MEM_STAT_INFO)
- : call_summary_base<T> (symtab PASS_MEM_STAT), m_ggc (ggc),
- m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT)
- {
- this->m_symtab_removal_hook
- = this->m_symtab->add_edge_removal_hook (call_summary::symtab_removal,
- this);
- this->m_symtab_duplication_hook
- = this->m_symtab->add_edge_duplication_hook (call_summary::symtab_duplication,
- this);
- }
+ : call_summary_base<T> (symtab, call_summary::symtab_removal,
+ call_summary::symtab_duplication PASS_MEM_STAT),
+ m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
/* Destructor. */
virtual ~call_summary ();
@@ -779,15 +838,11 @@ class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
public:
/* Default construction takes SYMTAB as an argument. */
fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
- : call_summary_base<T> (symtab PASS_MEM_STAT), m_vector (NULL)
+ : call_summary_base<T> (symtab, fast_call_summary::symtab_removal,
+ fast_call_summary::symtab_duplication PASS_MEM_STAT),
+ m_vector (NULL)
{
vec_alloc (m_vector, 13 PASS_MEM_STAT);
- this->m_symtab_removal_hook
- = this->m_symtab->add_edge_removal_hook (fast_call_summary::symtab_removal,
- this);
- this->m_symtab_duplication_hook
- = this->m_symtab->add_edge_duplication_hook (fast_call_summary::symtab_duplication,
- this);
}
/* Destructor. */
diff --git a/gcc/symtab-clones.cc b/gcc/symtab-clones.cc
new file mode 100644
index 0000000..ad154f6
--- /dev/null
+++ b/gcc/symtab-clones.cc
@@ -0,0 +1,62 @@
+/* Support for virtual clones in symbol table.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple.h"
+#include "predict.h"
+#include "target.h"
+#include "rtl.h"
+#include "alloc-pool.h"
+#include "cgraph.h"
+#include "symbol-summary.h"
+#include "symtab-clones.h"
+#include "lto-streamer.h"
+#include "data-streamer.h"
+
+namespace {
+
+/* Function summary for clone_infos. */
+class GTY((user)) clone_infos_t: public function_summary <clone_info *>
+{
+public:
+ clone_infos_t (symbol_table *table, bool ggc):
+ function_summary<clone_info *> (table, ggc) { }
+};
+
+} /* anon namespace */
+
+/* Return thunk_info possibly creating new one. */
+clone_info *
+clone_info::get_create (cgraph_node *node)
+{
+ if (!symtab->m_clones)
+ {
+ symtab->m_clones
+ = new (ggc_alloc_no_dtor <function_summary <clone_info *>> ())
+ function_summary <clone_info *> (symtab, true);
+ symtab->m_clones->disable_insertion_hook ();
+ symtab->m_clones->disable_duplication_hook ();
+ }
+ return symtab->m_clones->get_create (node);
+}
diff --git a/gcc/symtab-clones.h b/gcc/symtab-clones.h
new file mode 100644
index 0000000..a34fe21
--- /dev/null
+++ b/gcc/symtab-clones.h
@@ -0,0 +1,90 @@
+/* Representation of adjustment made to virtual clones in the symbol table.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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/>. */
+
+#ifndef GCC_SYMTAB_CLONES_H
+#define GCC_SYMTAB_CLONES_H
+
+struct GTY(()) clone_info
+{
+ /* Constructor. */
+ clone_info ()
+ : tree_map (NULL),
+ param_adjustments (NULL),
+ performed_splits (NULL)
+ {
+ }
+ /* Constants discovered by IPA-CP, i.e. which parameter should be replaced
+ with what. */
+ vec<ipa_replace_map *, va_gc> *tree_map;
+ /* Parameter modification that IPA-SRA decided to perform. */
+ ipa_param_adjustments *param_adjustments;
+ /* Lists of dummy-decl and offset pairs representing split formal parameters
+ in the caller. Offsets of all new replacements are enumerated, those
+ coming from the same original parameter have the same dummy decl stored
+ along with them.
+
+ Dummy decls sit in call statement arguments followed by new parameter
+ decls (or their SSA names) in between (caller) clone materialization and
+ call redirection. Redirection then recognizes the dummy variable and
+ together with the stored offsets can reconstruct what exactly the new
+ parameter decls represent and can leave in place only those that the
+ callee expects. */
+ vec<ipa_param_performed_split, va_gc> *performed_splits;
+
+ /* Return clone_info, if available. */
+ static clone_info *get (cgraph_node *node);
+
+ /* Return clone_info possibly creating new one. */
+ static clone_info *get_create (cgraph_node *node);
+
+ /* Remove clone_info. */
+ static void remove (cgraph_node *node);
+
+ /* Release all clone_infos. */
+ static void release (void);
+};
+
+/* Return clone_info, if available. */
+inline clone_info *
+clone_info::get (cgraph_node *node)
+{
+ if (!symtab->m_clones)
+ return NULL;
+ return symtab->m_clones->get (node);
+}
+
+
+/* Remove clone_info association for NODE. */
+inline void
+clone_info::remove (cgraph_node *node)
+{
+ symtab->m_clones->remove (node);
+}
+
+/* Free clone info summaries. */
+inline void
+clone_info::release ()
+{
+ if (symtab->m_clones)
+ delete (symtab->m_clones);
+ symtab->m_clones = NULL;
+}
+
+#endif /* GCC_SYMTAB_CLONES_H */
diff --git a/gcc/symtab-thunks.cc b/gcc/symtab-thunks.cc
index 1a4aaa2..2199f4e 100644
--- a/gcc/symtab-thunks.cc
+++ b/gcc/symtab-thunks.cc
@@ -52,6 +52,14 @@ along with GCC; see the file COPYING3. If not see
/* Used for vtable lookup in thunk adjusting. */
static GTY (()) tree vtable_entry_type;
+struct GTY (()) unprocessed_thunk
+{
+ cgraph_node *node;
+ thunk_info *info;
+};
+/* To be PCH safe we store thunks into a vector before end of compilation
+ unit. */
+static GTY (()) vec<unprocessed_thunk, va_gc> *thunks;
namespace {
@@ -147,6 +155,33 @@ thunk_info::hash ()
return hstate.end ();
}
+/* Add unprocessed thunk. */
+void
+thunk_info::register_early (cgraph_node *node)
+{
+ unprocessed_thunk entry = {node, new (ggc_alloc <thunk_info> ()) thunk_info};
+ *entry.info = *this;
+ vec_safe_push (thunks, entry);
+}
+
+/* Attach recorded thunks to cgraph_nodes.
+ All this is done only to avoid need to stream summaries to PCH. */
+void
+thunk_info::process_early_thunks ()
+{
+ unprocessed_thunk *e;
+ unsigned int i;
+ if (!thunks)
+ return;
+
+ FOR_EACH_VEC_ELT (*thunks, i, e)
+ {
+ *thunk_info::get_create (e->node) = *e->info;
+ }
+ vec_free (thunks);
+ thunks = NULL;
+}
+
/* Adjust PTR by the constant FIXED_OFFSET, by the vtable offset indicated by
VIRTUAL_OFFSET, and by the indirect offset indicated by INDIRECT_OFFSET, if
it is non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and zero
diff --git a/gcc/symtab-thunks.h b/gcc/symtab-thunks.h
index a23fc55..0dba221 100644
--- a/gcc/symtab-thunks.h
+++ b/gcc/symtab-thunks.h
@@ -77,6 +77,7 @@ struct GTY(()) thunk_info {
fixed_offset = other.fixed_offset;
virtual_value = other.virtual_value;
indirect_offset = other.indirect_offset;
+ alias = other.alias;
this_adjusting = other.this_adjusting;
virtual_offset_p = other.virtual_offset_p;
return *this;
@@ -133,6 +134,12 @@ struct GTY(()) thunk_info {
/* Remove thunk_info. */
static void remove (cgraph_node *node);
+ /* Add unprocessed thunk. */
+ void register_early (cgraph_node *node);
+
+ /* Attach recorded thunks to cgraph_nodes. */
+ static void process_early_thunks ();
+
/* Release all thunk_infos. */
static void release (void);
};
@@ -160,7 +167,7 @@ inline void
thunk_info::release ()
{
if (symtab->m_thunks)
- delete (symtab->m_thunks);
+ ggc_delete (symtab->m_thunks);
symtab->m_thunks = NULL;
}
#endif /* GCC_SYMTAB_THUNKS_H */
diff --git a/gcc/symtab.c b/gcc/symtab.c
index bc2865f..6ceec55 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -368,6 +368,36 @@ section_name_hasher::equal (section_hash_entry *n1, const char *name)
return n1->name == name || !strcmp (n1->name, name);
}
+/* Bump the reference count on ENTRY so that it is retained. */
+
+static section_hash_entry *
+retain_section_hash_entry (section_hash_entry *entry)
+{
+ entry->ref_count++;
+ return entry;
+}
+
+/* Drop the reference count on ENTRY and remove it if the reference
+ count drops to zero. */
+
+static void
+release_section_hash_entry (section_hash_entry *entry)
+{
+ if (entry)
+ {
+ entry->ref_count--;
+ if (!entry->ref_count)
+ {
+ hashval_t hash = htab_hash_string (entry->name);
+ section_hash_entry **slot
+ = symtab->section_hash->find_slot_with_hash (entry->name,
+ hash, INSERT);
+ ggc_free (entry);
+ symtab->section_hash->clear_slot (slot);
+ }
+ }
+}
+
/* Add node into symbol table. This function is not used directly, but via
cgraph/varpool node creation routines. */
@@ -408,10 +438,11 @@ symtab_node::remove_from_same_comdat_group (void)
}
/* Remove node from symbol table. This function is not used directly, but via
- cgraph/varpool node removal routines. */
+ cgraph/varpool node removal routines.
+ INFO is a clone info to attach to new root of clone tree (if any). */
void
-symtab_node::unregister (void)
+symtab_node::unregister (clone_info *info)
{
remove_all_references ();
remove_all_referring ();
@@ -430,7 +461,7 @@ symtab_node::unregister (void)
{
symtab_node *replacement_node = NULL;
if (cgraph_node *cnode = dyn_cast <cgraph_node *> (this))
- replacement_node = cnode->find_replacement ();
+ replacement_node = cnode->find_replacement (info);
decl->decl_with_vis.symtab_node = replacement_node;
}
if (!is_a <varpool_node *> (this) || !DECL_HARD_REGISTER (decl))
@@ -591,10 +622,9 @@ symtab_node::create_reference (symtab_node *referred_node,
gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
list = &ref_list;
- old_references = vec_safe_address (list->references);
- vec_safe_grow (list->references, vec_safe_length (list->references) + 1,
- true);
- ref = &list->references->last ();
+ old_references = list->references.address ();
+ list->references.safe_grow (list->references.length () + 1, false);
+ ref = &list->references.last ();
list2 = &referred_node->ref_list;
@@ -622,7 +652,7 @@ symtab_node::create_reference (symtab_node *referred_node,
ref->speculative = 0;
/* If vector was moved in memory, update pointers. */
- if (old_references != list->references->address ())
+ if (old_references != list->references.address ())
{
int i;
for (i = 0; iterate_reference(i, ref2); i++)
@@ -752,7 +782,8 @@ symtab_node::remove_stmt_references (gimple *stmt)
i++;
}
-/* Remove all stmt references in non-speculative references.
+/* Remove all stmt references in non-speculative references in THIS
+ and all clones.
Those are not maintained during inlining & cloning.
The exception are speculative references that are updated along
with callgraph edges associated with them. */
@@ -770,6 +801,13 @@ symtab_node::clear_stmts_in_references (void)
r->lto_stmt_uid = 0;
r->speculative_id = 0;
}
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
+ if (cnode)
+ {
+ if (cnode->clones)
+ for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone)
+ cnode->clear_stmts_in_references ();
+ }
}
/* Remove all references in ref list. */
@@ -777,9 +815,9 @@ symtab_node::clear_stmts_in_references (void)
void
symtab_node::remove_all_references (void)
{
- while (vec_safe_length (ref_list.references))
- ref_list.references->last ().remove_reference ();
- vec_free (ref_list.references);
+ while (ref_list.references.length ())
+ ref_list.references.last ().remove_reference ();
+ ref_list.references.release ();
}
/* Remove all referring items in ref list. */
@@ -1476,8 +1514,7 @@ symtab_node::copy_visibility_from (symtab_node *n)
DECL_DLLIMPORT_P (decl) = DECL_DLLIMPORT_P (n->decl);
resolution = n->resolution;
set_comdat_group (n->get_comdat_group ());
- call_for_symbol_and_aliases (symtab_node::set_section,
- const_cast<char *>(n->get_section ()), true);
+ set_section (*n);
externally_visible = n->externally_visible;
if (!DECL_RTL_SET_P (decl))
return;
@@ -1602,57 +1639,76 @@ void
symtab_node::set_section_for_node (const char *section)
{
const char *current = get_section ();
- section_hash_entry **slot;
if (current == section
|| (current && section
&& !strcmp (current, section)))
return;
- if (current)
- {
- x_section->ref_count--;
- if (!x_section->ref_count)
- {
- hashval_t hash = htab_hash_string (x_section->name);
- slot = symtab->section_hash->find_slot_with_hash (x_section->name,
- hash, INSERT);
- ggc_free (x_section);
- symtab->section_hash->clear_slot (slot);
- }
- x_section = NULL;
- }
+ release_section_hash_entry (x_section);
if (!section)
{
+ x_section = NULL;
implicit_section = false;
return;
}
if (!symtab->section_hash)
symtab->section_hash = hash_table<section_name_hasher>::create_ggc (10);
- slot = symtab->section_hash->find_slot_with_hash (section,
- htab_hash_string (section),
- INSERT);
+ section_hash_entry **slot = symtab->section_hash->find_slot_with_hash
+ (section, htab_hash_string (section), INSERT);
if (*slot)
- x_section = (section_hash_entry *)*slot;
+ x_section = retain_section_hash_entry (*slot);
else
{
int len = strlen (section);
*slot = x_section = ggc_cleared_alloc<section_hash_entry> ();
+ x_section->ref_count = 1;
x_section->name = ggc_vec_alloc<char> (len + 1);
memcpy (x_section->name, section, len + 1);
}
- x_section->ref_count++;
}
-/* Worker for set_section. */
+/* Set the section of node THIS to be the same as the section
+ of node OTHER. Keep reference counts of the sections
+ up-to-date as needed. */
+
+void
+symtab_node::set_section_for_node (const symtab_node &other)
+{
+ if (x_section == other.x_section)
+ return;
+ if (get_section () && other.get_section ())
+ gcc_checking_assert (strcmp (get_section (), other.get_section ()) != 0);
+ release_section_hash_entry (x_section);
+ if (other.x_section)
+ x_section = retain_section_hash_entry (other.x_section);
+ else
+ {
+ x_section = NULL;
+ implicit_section = false;
+ }
+}
+
+/* Workers for set_section. */
bool
-symtab_node::set_section (symtab_node *n, void *s)
+symtab_node::set_section_from_string (symtab_node *n, void *s)
{
n->set_section_for_node ((char *)s);
return false;
}
+/* Set the section of node N to be the same as the section
+ of node O. */
+
+bool
+symtab_node::set_section_from_node (symtab_node *n, void *o)
+{
+ const symtab_node &other = *static_cast<const symtab_node *> (o);
+ n->set_section_for_node (other);
+ return false;
+}
+
/* Set section of symbol and its aliases. */
void
@@ -1660,7 +1716,14 @@ symtab_node::set_section (const char *section)
{
gcc_assert (!this->alias || !this->analyzed);
call_for_symbol_and_aliases
- (symtab_node::set_section, const_cast<char *>(section), true);
+ (symtab_node::set_section_from_string, const_cast<char *>(section), true);
+}
+
+void
+symtab_node::set_section (const symtab_node &other)
+{
+ call_for_symbol_and_aliases
+ (symtab_node::set_section_from_node, const_cast<symtab_node *>(&other), true);
}
/* Return the initialization priority. */
@@ -1765,7 +1828,7 @@ symtab_node::resolve_alias (symtab_node *target, bool transparent)
{
symtab_node *n;
- gcc_assert (!analyzed && !vec_safe_length (ref_list.references));
+ gcc_assert (!analyzed && !ref_list.references.length ());
/* Never let cycles to creep into the symbol table alias references;
those will make alias walkers to be infinite. */
@@ -1806,8 +1869,7 @@ symtab_node::resolve_alias (symtab_node *target, bool transparent)
{
error ("section of alias %q+D must match section of its target", decl);
}
- call_for_symbol_and_aliases (symtab_node::set_section,
- const_cast<char *>(target->get_section ()), true);
+ set_section (*target);
if (target->implicit_section)
call_for_symbol_and_aliases (set_implicit_section, NULL, true);
@@ -1998,7 +2060,7 @@ symtab_node::get_partitioning_class (void)
if (DECL_ABSTRACT_P (decl))
return SYMBOL_EXTERNAL;
- if (cnode && cnode->inlined_to)
+ if (cnode && (cnode->inlined_to || cnode->declare_variant_alt))
return SYMBOL_DUPLICATE;
/* Transparent aliases are always duplicated. */
diff --git a/gcc/system.h b/gcc/system.h
index b0f3f1d..5b42825 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -232,6 +232,12 @@ extern int errno;
#ifdef INCLUDE_VECTOR
# include <vector>
#endif
+#ifdef INCLUDE_ARRAY
+# include <array>
+#endif
+#ifdef INCLUDE_FUNCTIONAL
+# include <functional>
+#endif
# include <cstring>
# include <new>
# include <utility>
@@ -789,6 +795,12 @@ extern void fancy_abort (const char *, int, const char *)
#define ALWAYS_INLINE inline
#endif
+#if GCC_VERSION >= 3004
+#define WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
+#else
+#define WARN_UNUSED_RESULT
+#endif
+
/* Use gcc_unreachable() to mark unreachable locations (like an
unreachable default case of a switch. Do not use gcc_assert(0). */
#if (GCC_VERSION >= 4005) && !ENABLE_ASSERT_CHECKING
diff --git a/gcc/target.def b/gcc/target.def
index ed2da15..d5ed0df 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -185,6 +185,16 @@ DEFHOOK
void, (rtx personality),
NULL)
+/* If necessary, modify personality and LSDA references to handle
+ indirection. This is used when the assembler supports CFI directives. */
+DEFHOOK
+(make_eh_symbol_indirect,
+ "If necessary, modify personality and LSDA references to handle indirection.\
+ The original symbol is in @code{origsymbol} and if @code{pubvis} is true\
+ the symbol is visible outside the TU.",
+ rtx, (rtx origsymbol, bool pubvis),
+ NULL)
+
/* Emit any directives required to unwind this instruction. */
DEFHOOK
(unwind_emit,
@@ -549,16 +559,18 @@ Whatever the actual target object format, this is often good enough.",
void, (tree decl, int reloc),
default_unique_section)
-/* Return the readonly data section associated with function DECL. */
+/* Return the readonly data or relocated readonly data section
+ associated with function DECL. */
DEFHOOK
(function_rodata_section,
- "Return the readonly data section associated with\n\
-@samp{DECL_SECTION_NAME (@var{decl})}.\n\
+ "Return the readonly data or reloc readonly data section associated with\n\
+@samp{DECL_SECTION_NAME (@var{decl})}. @var{relocatable} selects the latter\n\
+over the former.\n\
The default version of this function selects @code{.gnu.linkonce.r.name} if\n\
the function's section is @code{.gnu.linkonce.t.name}, @code{.rodata.name}\n\
-if function is in @code{.text.name}, and the normal readonly-data section\n\
-otherwise.",
- section *, (tree decl),
+or @code{.data.rel.ro.name} if function is in @code{.text.name}, and\n\
+the normal readonly-data or reloc readonly data section otherwise.",
+ section *, (tree decl, bool relocatable),
default_function_rodata_section)
/* Nonnull if the target wants to override the default ".rodata" prefix
@@ -745,41 +757,7 @@ directive to annotate @var{symbol} as used. The Darwin target uses the\n\
DEFHOOK
(record_gcc_switches,
"Provides the target with the ability to record the gcc command line\n\
-switches that have been passed to the compiler, and options that are\n\
-enabled. The @var{type} argument specifies what is being recorded.\n\
-It can take the following values:\n\
-\n\
-@table @gcctabopt\n\
-@item SWITCH_TYPE_PASSED\n\
-@var{text} is a command line switch that has been set by the user.\n\
-\n\
-@item SWITCH_TYPE_ENABLED\n\
-@var{text} is an option which has been enabled. This might be as a\n\
-direct result of a command line switch, or because it is enabled by\n\
-default or because it has been enabled as a side effect of a different\n\
-command line switch. For example, the @option{-O2} switch enables\n\
-various different individual optimization passes.\n\
-\n\
-@item SWITCH_TYPE_DESCRIPTIVE\n\
-@var{text} is either NULL or some descriptive text which should be\n\
-ignored. If @var{text} is NULL then it is being used to warn the\n\
-target hook that either recording is starting or ending. The first\n\
-time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the\n\
-warning is for start up and the second time the warning is for\n\
-wind down. This feature is to allow the target hook to make any\n\
-necessary preparations before it starts to record switches and to\n\
-perform any necessary tidying up after it has finished recording\n\
-switches.\n\
-\n\
-@item SWITCH_TYPE_LINE_START\n\
-This option can be ignored by this target hook.\n\
-\n\
-@item SWITCH_TYPE_LINE_END\n\
-This option can be ignored by this target hook.\n\
-@end table\n\
-\n\
-The hook's return value must be zero. Other return values may be\n\
-supported in the future.\n\
+switches provided as argument.\n\
\n\
By default this hook is set to NULL, but an example implementation is\n\
provided for ELF based targets. Called @var{elf_record_gcc_switches},\n\
@@ -787,7 +765,7 @@ it records the switches as ASCII text inside a new, string mergeable\n\
section in the assembler output file. The name of the new section is\n\
provided by the @code{TARGET_ASM_RECORD_GCC_SWITCHES_SECTION} target\n\
hook.",
- int, (print_switch_type type, const char *text),
+ void, (const char *),
NULL)
/* The name of the section that the example ELF implementation of
@@ -3873,9 +3851,12 @@ default_new_address_profitable_p)
DEFHOOK
(estimated_poly_value,
"Return an estimate of the runtime value of @var{val}, for use in\n\
-things like cost calculations or profiling frequencies. The default\n\
+things like cost calculations or profiling frequencies. @var{kind} is used\n\
+to ask for the minimum, maximum, and likely estimates of the value through\n\
+the @code{POLY_VALUE_MIN}, @code{POLY_VALUE_MAX} and\n\
+@code{POLY_VALUE_LIKELY} values. The default\n\
implementation returns the lowest possible value of @var{val}.",
- HOST_WIDE_INT, (poly_int64 val),
+ HOST_WIDE_INT, (poly_int64 val, poly_value_estimate_kind kind),
default_estimated_poly_value)
/* Permit speculative instructions in delay slots during delayed-branch
@@ -4452,7 +4433,8 @@ DEFHOOK
(asan_shadow_offset,
"Return the offset bitwise ored into shifted address to get corresponding\n\
Address Sanitizer shadow memory address. NULL if Address Sanitizer is not\n\
-supported by the target.",
+supported by the target. May return 0 if Address Sanitizer is not supported\n\
+by a subtarget.",
unsigned HOST_WIDE_INT, (void),
NULL)
@@ -5080,6 +5062,21 @@ argument list due to stack realignment. Return @code{NULL} if no DRAP\n\
is needed.",
rtx, (void), NULL)
+/* Generate instruction sequence to zero call used registers. */
+DEFHOOK
+(zero_call_used_regs,
+ "This target hook emits instructions to zero the subset of @var{selected_regs}\n\
+that could conceivably contain values that are useful to an attacker.\n\
+Return the set of registers that were actually cleared.\n\
+\n\
+The default implementation uses normal move instructions to zero\n\
+all the registers in @var{selected_regs}. Define this hook if the\n\
+target has more efficient ways of zeroing certain registers,\n\
+or if you believe that certain registers would never contain\n\
+values that are useful to an attacker.",
+ HARD_REG_SET, (HARD_REG_SET selected_regs),
+default_zero_call_used_regs)
+
/* Return true if all function parameters should be spilled to the
stack. */
DEFHOOK
@@ -5138,12 +5135,28 @@ Note that the block move need only cover the constant parts of the\n\
trampoline. If the target isolates the variable parts of the trampoline\n\
to the end, not all @code{TRAMPOLINE_SIZE} bytes need be copied.\n\
\n\
-If the target requires any other actions, such as flushing caches or\n\
+If the target requires any other actions, such as flushing caches\n\
+(possibly calling function maybe_emit_call_builtin___clear_cache) or\n\
enabling stack execution, these actions should be performed after\n\
initializing the trampoline proper.",
void, (rtx m_tramp, tree fndecl, rtx static_chain),
default_trampoline_init)
+/* Emit a call to a function to clear the instruction cache. */
+DEFHOOK
+(emit_call_builtin___clear_cache,
+ "On targets that do not define a @code{clear_cache} insn expander,\n\
+but that define the @code{CLEAR_CACHE_INSN} macro,\n\
+maybe_emit_call_builtin___clear_cache relies on this target hook\n\
+to clear an address range in the instruction cache.\n\
+\n\
+The default implementation calls the @code{__clear_cache} builtin,\n\
+taking the assembler name from the builtin declaration. Overriding\n\
+definitions may call alternate functions, with alternate calling\n\
+conventions, or emit alternate RTX to perform the job.",
+ void, (rtx begin, rtx end),
+ default_emit_call_builtin___clear_cache)
+
/* Adjust the address of the trampoline in a target-specific way. */
DEFHOOK
(trampoline_adjust_address,
@@ -6835,6 +6848,86 @@ DEFHOOK
HOOK_VECTOR_END (mode_switching)
#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_MEMTAG_"
+HOOK_VECTOR (TARGET_MEMTAG_, memtag)
+
+DEFHOOK
+(can_tag_addresses,
+ "True if the backend architecture naturally supports ignoring some region\n\
+of pointers. This feature means that @option{-fsanitize=hwaddress} can\n\
+work.\n\
+\n\
+At preset, this feature does not support address spaces. It also requires\n\
+@code{Pmode} to be the same as @code{ptr_mode}.",
+ bool, (), default_memtag_can_tag_addresses)
+
+DEFHOOK
+(tag_size,
+ "Return the size of a tag (in bits) for this platform.\n\
+\n\
+The default returns 8.",
+ uint8_t, (), default_memtag_tag_size)
+
+DEFHOOK
+(granule_size,
+ "Return the size in real memory that each byte in shadow memory refers to.\n\
+I.e. if a variable is @var{X} bytes long in memory, then this hook should\n\
+return the value @var{Y} such that the tag in shadow memory spans\n\
+@var{X}/@var{Y} bytes.\n\
+\n\
+Most variables will need to be aligned to this amount since two variables\n\
+that are neighbors in memory and share a tag granule would need to share\n\
+the same tag.\n\
+\n\
+The default returns 16.",
+ uint8_t, (), default_memtag_granule_size)
+
+DEFHOOK
+(insert_random_tag,
+ "Return an RTX representing the value of @var{untagged} but with a\n\
+(possibly) random tag in it.\n\
+Put that value into @var{target} if it is convenient to do so.\n\
+This function is used to generate a tagged base for the current stack frame.",
+ rtx, (rtx untagged, rtx target), default_memtag_insert_random_tag)
+
+DEFHOOK
+(add_tag,
+ "Return an RTX that represents the result of adding @var{addr_offset} to\n\
+the address in pointer @var{base} and @var{tag_offset} to the tag in pointer\n\
+@var{base}.\n\
+The resulting RTX must either be a valid memory address or be able to get\n\
+put into an operand with @code{force_operand}.\n\
+\n\
+Unlike other memtag hooks, this must return an expression and not emit any\n\
+RTL.",
+ rtx, (rtx base, poly_int64 addr_offset, uint8_t tag_offset),
+ default_memtag_add_tag)
+
+DEFHOOK
+(set_tag,
+ "Return an RTX representing @var{untagged_base} but with the tag @var{tag}.\n\
+Try and store this in @var{target} if convenient.\n\
+@var{untagged_base} is required to have a zero tag when this hook is called.\n\
+The default of this hook is to set the top byte of @var{untagged_base} to\n\
+@var{tag}.",
+ rtx, (rtx untagged_base, rtx tag, rtx target), default_memtag_set_tag)
+
+DEFHOOK
+(extract_tag,
+ "Return an RTX representing the tag stored in @var{tagged_pointer}.\n\
+Store the result in @var{target} if it is convenient.\n\
+The default represents the top byte of the original pointer.",
+ rtx, (rtx tagged_pointer, rtx target), default_memtag_extract_tag)
+
+DEFHOOK
+(untagged_pointer,
+ "Return an RTX representing @var{tagged_pointer} with its tag set to zero.\n\
+Store the result in @var{target} if convenient.\n\
+The default clears the top byte of the original pointer.",
+ rtx, (rtx tagged_pointer, rtx target), default_memtag_untagged_pointer)
+
+HOOK_VECTOR_END (memtag)
+#undef HOOK_PREFIX
#define HOOK_PREFIX "TARGET_"
#define DEF_TARGET_INSN(NAME, PROTO) \
diff --git a/gcc/target.h b/gcc/target.h
index 440cd25..68ef519 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -68,16 +68,6 @@ union cumulative_args_t { void *p; };
#endif /* !CHECKING_P */
-/* Types used by the record_gcc_switches() target function. */
-enum print_switch_type
-{
- SWITCH_TYPE_PASSED, /* A switch passed on the command line. */
- SWITCH_TYPE_ENABLED, /* An option that is currently enabled. */
- SWITCH_TYPE_DESCRIPTIVE, /* Descriptive text, not a switch or option. */
- SWITCH_TYPE_LINE_START, /* Please emit any necessary text at the start of a line. */
- SWITCH_TYPE_LINE_END /* Please emit a line terminator. */
-};
-
/* Types of memory operation understood by the "by_pieces" infrastructure.
Used by the TARGET_USE_BY_PIECES_INFRASTRUCTURE_P target hook and
internally by the functions in expr.c. */
@@ -96,10 +86,8 @@ extern unsigned HOST_WIDE_INT by_pieces_ninsns (unsigned HOST_WIDE_INT,
unsigned int,
by_pieces_operation);
-typedef int (* print_switch_fn_type) (print_switch_type, const char *);
-
/* An example implementation for ELF targets. Defined in varasm.c */
-extern int elf_record_gcc_switches (print_switch_type type, const char *);
+extern void elf_record_gcc_switches (const char *);
/* Some places still assume that all pointer or address modes are the
standard Pmode and ptr_mode. These optimizations become invalid if
@@ -264,6 +252,13 @@ enum type_context_kind {
TCTX_CAPTURE_BY_COPY
};
+enum poly_value_estimate_kind
+{
+ POLY_VALUE_MIN,
+ POLY_VALUE_MAX,
+ POLY_VALUE_LIKELY
+};
+
extern bool verify_type_context (location_t, type_context_kind, const_tree,
bool = false);
@@ -284,12 +279,13 @@ extern struct gcc_target targetm;
provides a rough guess. */
static inline HOST_WIDE_INT
-estimated_poly_value (poly_int64 x)
+estimated_poly_value (poly_int64 x,
+ poly_value_estimate_kind kind = POLY_VALUE_LIKELY)
{
if (NUM_POLY_INT_COEFFS == 1)
return x.coeffs[0];
else
- return targetm.estimated_poly_value (x);
+ return targetm.estimated_poly_value (x, kind);
}
#ifdef GCC_TM_H
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 5d94fce..d616fb7 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -56,6 +56,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-alias.h"
#include "gimple-expr.h"
#include "memmodel.h"
+#include "backend.h"
+#include "emit-rtl.h"
+#include "df.h"
#include "tm_p.h"
#include "stringpool.h"
#include "tree-vrp.h"
@@ -70,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
#include "varasm.h"
#include "flags.h"
#include "explow.h"
+#include "expmed.h"
#include "calls.h"
#include "expr.h"
#include "output.h"
@@ -83,6 +87,9 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "sbitmap.h"
#include "function-abi.h"
+#include "attribs.h"
+#include "asan.h"
+#include "emit-rtl.h"
bool
default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
@@ -987,6 +994,35 @@ default_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED)
#endif
}
+/* The default hook for TARGET_ZERO_CALL_USED_REGS. */
+
+HARD_REG_SET
+default_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+ gcc_assert (!hard_reg_set_empty_p (need_zeroed_hardregs));
+
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+ {
+ rtx_insn *last_insn = get_last_insn ();
+ machine_mode mode = GET_MODE (regno_reg_rtx[regno]);
+ rtx zero = CONST0_RTX (mode);
+ rtx_insn *insn = emit_move_insn (regno_reg_rtx[regno], zero);
+ if (!valid_insn_p (insn))
+ {
+ static bool issued_error;
+ if (!issued_error)
+ {
+ issued_error = true;
+ sorry ("%qs not supported on this target",
+ "-fzero-call-used-regs");
+ }
+ delete_insns_since (last_insn);
+ }
+ }
+ return need_zeroed_hardregs;
+}
+
rtx
default_internal_arg_pointer (void)
{
@@ -1721,7 +1757,7 @@ default_slow_unaligned_access (machine_mode, unsigned int)
/* The default implementation of TARGET_ESTIMATED_POLY_VALUE. */
HOST_WIDE_INT
-default_estimated_poly_value (poly_int64 x)
+default_estimated_poly_value (poly_int64 x, poly_value_estimate_kind)
{
return x.coeffs[0];
}
@@ -1828,8 +1864,11 @@ default_print_patchable_function_entry (FILE *file,
patch_area_number++;
ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number);
+ unsigned int flags = SECTION_WRITE | SECTION_RELRO;
+ if (HAVE_GAS_SECTION_LINK_ORDER)
+ flags |= SECTION_LINK_ORDER;
switch_to_section (get_section ("__patchable_function_entries",
- SECTION_WRITE | SECTION_RELRO, NULL));
+ flags, current_function_decl));
assemble_align (POINTER_SIZE);
fputs (asm_op, file);
assemble_name_raw (file, buf);
@@ -2383,4 +2422,115 @@ default_speculation_safe_value (machine_mode mode ATTRIBUTE_UNUSED,
return result;
}
+/* How many bits to shift in order to access the tag bits.
+ The default is to store the tag in the top 8 bits of a 64 bit pointer, hence
+ shifting 56 bits will leave just the tag. */
+#define HWASAN_SHIFT (GET_MODE_PRECISION (Pmode) - 8)
+#define HWASAN_SHIFT_RTX GEN_INT (HWASAN_SHIFT)
+
+bool
+default_memtag_can_tag_addresses ()
+{
+ return false;
+}
+
+uint8_t
+default_memtag_tag_size ()
+{
+ return 8;
+}
+
+uint8_t
+default_memtag_granule_size ()
+{
+ return 16;
+}
+
+/* The default implementation of TARGET_MEMTAG_INSERT_RANDOM_TAG. */
+rtx
+default_memtag_insert_random_tag (rtx untagged, rtx target)
+{
+ gcc_assert (param_hwasan_instrument_stack);
+ if (param_hwasan_random_frame_tag)
+ {
+ rtx fn = init_one_libfunc ("__hwasan_generate_tag");
+ rtx new_tag = emit_library_call_value (fn, NULL_RTX, LCT_NORMAL, QImode);
+ return targetm.memtag.set_tag (untagged, new_tag, target);
+ }
+ else
+ {
+ /* NOTE: The kernel API does not have __hwasan_generate_tag exposed.
+ In the future we may add the option emit random tags with inline
+ instrumentation instead of function calls. This would be the same
+ between the kernel and userland. */
+ return untagged;
+ }
+}
+
+/* The default implementation of TARGET_MEMTAG_ADD_TAG. */
+rtx
+default_memtag_add_tag (rtx base, poly_int64 offset, uint8_t tag_offset)
+{
+ /* Need to look into what the most efficient code sequence is.
+ This is a code sequence that would be emitted *many* times, so we
+ want it as small as possible.
+
+ There are two places where tag overflow is a question:
+ - Tagging the shadow stack.
+ (both tagging and untagging).
+ - Tagging addressable pointers.
+
+ We need to ensure both behaviors are the same (i.e. that the tag that
+ ends up in a pointer after "overflowing" the tag bits with a tag addition
+ is the same that ends up in the shadow space).
+
+ The aim is that the behavior of tag addition should follow modulo
+ wrapping in both instances.
+
+ The libhwasan code doesn't have any path that increments a pointer's tag,
+ which means it has no opinion on what happens when a tag increment
+ overflows (and hence we can choose our own behavior). */
+
+ offset += ((uint64_t)tag_offset << HWASAN_SHIFT);
+ return plus_constant (Pmode, base, offset);
+}
+
+/* The default implementation of TARGET_MEMTAG_SET_TAG. */
+rtx
+default_memtag_set_tag (rtx untagged, rtx tag, rtx target)
+{
+ gcc_assert (GET_MODE (untagged) == Pmode && GET_MODE (tag) == QImode);
+ tag = expand_simple_binop (Pmode, ASHIFT, tag, HWASAN_SHIFT_RTX, NULL_RTX,
+ /* unsignedp = */1, OPTAB_WIDEN);
+ rtx ret = expand_simple_binop (Pmode, IOR, untagged, tag, target,
+ /* unsignedp = */1, OPTAB_DIRECT);
+ gcc_assert (ret);
+ return ret;
+}
+
+/* The default implementation of TARGET_MEMTAG_EXTRACT_TAG. */
+rtx
+default_memtag_extract_tag (rtx tagged_pointer, rtx target)
+{
+ rtx tag = expand_simple_binop (Pmode, LSHIFTRT, tagged_pointer,
+ HWASAN_SHIFT_RTX, target,
+ /* unsignedp = */0,
+ OPTAB_DIRECT);
+ rtx ret = gen_lowpart (QImode, tag);
+ gcc_assert (ret);
+ return ret;
+}
+
+/* The default implementation of TARGET_MEMTAG_UNTAGGED_POINTER. */
+rtx
+default_memtag_untagged_pointer (rtx tagged_pointer, rtx target)
+{
+ rtx tag_mask = gen_int_mode ((HOST_WIDE_INT_1U << HWASAN_SHIFT) - 1, Pmode);
+ rtx untagged_base = expand_simple_binop (Pmode, AND, tagged_pointer,
+ tag_mask, target, true,
+ OPTAB_DIRECT);
+ gcc_assert (untagged_base);
+ return untagged_base;
+}
+
#include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 44ab926..4340a3b 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -160,11 +160,13 @@ extern unsigned int default_function_arg_round_boundary (machine_mode,
const_tree);
extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
extern rtx default_function_value (const_tree, const_tree, bool);
+extern HARD_REG_SET default_zero_call_used_regs (HARD_REG_SET);
extern rtx default_libcall_value (machine_mode, const_rtx);
extern bool default_function_value_regno_p (const unsigned int);
extern rtx default_internal_arg_pointer (void);
extern rtx default_static_chain (const_tree, bool);
extern void default_trampoline_init (rtx, tree, rtx);
+extern void default_emit_call_builtin___clear_cache (rtx, rtx);
extern poly_int64 default_return_pops_args (tree, tree, poly_int64);
extern reg_class_t default_ira_change_pseudo_allocno_class (int, reg_class_t,
reg_class_t);
@@ -219,7 +221,8 @@ extern int default_memory_move_cost (machine_mode, reg_class_t, bool);
extern int default_register_move_cost (machine_mode, reg_class_t,
reg_class_t);
extern bool default_slow_unaligned_access (machine_mode, unsigned int);
-extern HOST_WIDE_INT default_estimated_poly_value (poly_int64);
+extern HOST_WIDE_INT default_estimated_poly_value (poly_int64,
+ poly_value_estimate_kind);
extern bool default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT,
unsigned int,
@@ -285,4 +288,13 @@ extern bool default_have_speculation_safe_value (bool);
extern bool speculation_safe_value_not_needed (bool);
extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx);
+extern bool default_memtag_can_tag_addresses ();
+extern uint8_t default_memtag_tag_size ();
+extern uint8_t default_memtag_granule_size ();
+extern rtx default_memtag_insert_random_tag (rtx, rtx);
+extern rtx default_memtag_add_tag (rtx, poly_int64, uint8_t);
+extern rtx default_memtag_set_tag (rtx, rtx, rtx);
+extern rtx default_memtag_extract_tag (rtx, rtx);
+extern rtx default_memtag_untagged_pointer (rtx, rtx);
+
#endif /* GCC_TARGHOOKS_H */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cc13418..89fddd6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,6322 @@
+2020-12-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98461
+ * gcc.target/i386/sse2-pr98461.c: New test.
+ * gcc.target/i386/avx2-pr98461.c: New test.
+
+2020-12-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/97612
+ * gfortran.dg/structure_constructor_17.f90: New test.
+
+2020-12-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/93833
+ * gfortran.dg/deferred_character_36.f90 : New test.
+
+2020-12-29 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/loop-3.c: Update test pattern.
+
+2020-12-29 Vladimir Isaev <isaev@synopsys.com>
+
+ * gcc.target/arc/uncached-9.c: New test.
+
+2020-12-28 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/96793
+ * gcc.target/i386/pr96793-2.c: New test.
+
+2020-12-28 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/pr92658-avx2-2.c: New test.
+ * gcc.target/i386/pr92658-avx512bw-2.c: Likewise.
+ * gcc.target/i386/pr92658-sse4-2.c: Likewise.
+
+2020-12-27 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/asm-2.c: Use different register for iq2000.
+ * gcc.dg/tree-ssa/asm-3.c: Likewise.
+
+2020-12-27 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/97694
+ PR fortran/97723
+ * gfortran.dg/select_rank_5.f90: New test.
+
+2020-12-26 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/96045
+ * obj-c++.dg/property/property-neg-6.mm: Adjust EOF
+ diagnostic location.
+ * obj-c++.dg/syntax-error-10.mm: Likewise.
+ * obj-c++.dg/syntax-error-8.mm: Likewise.
+ * obj-c++.dg/syntax-error-9.mm: Likewise.
+
+2020-12-26 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/98022
+ * gfortran.dg/data_inquiry_ref.f90: Change to dg-compile and
+ add errors for inquiry references.
+
+2020-12-25 Harald Anlauf <anlauf@gmx.de>
+
+ * gfortran.dg/pr93685_1.f90: New test.
+ * gfortran.dg/pr93685_2.f90: New test.
+
+2020-12-23 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/98160
+ * g++.dg/warn/pr98160.C: New test.
+
+2020-12-23 Martin Sebor <msebor@redhat.com>
+
+ PR c++/98413
+ * g++.dg/warn/pr98413.C: New test.
+
+2020-12-23 Joel Brobecker <brobecker@adacore.com>
+
+ * gcc.target/arm/data-rel-1.c: Require "fpic" support.
+ * gcc.target/arm/data-rel-2.c: Likewise.
+ * gcc.target/arm/data-rel-3.c: Ditto.
+ * gcc.target/arm/pr44788.c: Ditto.
+ * gcc.target/arm/pr52006.c: Ditto.
+ * gcc.target/arm/pr59858.c: Ditto.
+ * gcc.target/arm/tlscall.c: Ditto.
+ * gcc.target/arm/require-pic-register-loc.c: Ditto.
+ Adjust line numbers.
+
+2020-12-23 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/96045
+ * g++.dg/diagnostic/pr96045-1.C: New.
+ * g++.dg/diagnostic/pr96045-2.C: New.
+ * g++.dg/diagnostic/pr96045-3.C: New.
+ * c-c++-common/goacc/pr79428-1.c: Adjust EOF diagnostic location.
+ * c-c++-common/gomp/pr79428-2.c: Likewise
+ * c-c++-common/raw-string-6.c: Likewise
+ * g++.dg/cpp0x/decltype63.C: Likewise
+ * g++.dg/cpp0x/gen-attrs-64.C: Likewise
+ * g++.dg/cpp0x/pr68726.C: Likewise
+ * g++.dg/cpp0x/pr78341.C: Likewise
+ * g++.dg/cpp1y/pr65202.C: Likewise
+ * g++.dg/cpp1y/pr65340.C: Likewise
+ * g++.dg/cpp1y/pr68578.C: Likewise
+ * g++.dg/cpp1z/class-deduction44.C: Likewise
+ * g++.dg/diagnostic/unclosed-extern-c.C: Likewise
+ * g++.dg/diagnostic/unclosed-function.C: Likewise
+ * g++.dg/diagnostic/unclosed-namespace.C: Likewise
+ * g++.dg/diagnostic/unclosed-struct.C: Likewise
+ * g++.dg/ext/pr84598.C: Likewise
+ * g++.dg/other/switch4.C: Likewise
+ * g++.dg/parse/attr4.C: Likewise
+ * g++.dg/parse/cond4.C: Likewise
+ * g++.dg/parse/crash10.C: Likewise
+ * g++.dg/parse/crash18.C: Likewise
+ * g++.dg/parse/crash27.C: Likewise
+ * g++.dg/parse/crash34.C: Likewise
+ * g++.dg/parse/crash35.C: Likewise
+ * g++.dg/parse/crash52.C: Likewise
+ * g++.dg/parse/crash59.C: Likewise
+ * g++.dg/parse/crash61.C: Likewise
+ * g++.dg/parse/crash67.C: Likewise
+ * g++.dg/parse/error14.C: Likewise
+ * g++.dg/parse/error56.C: Likewise
+ * g++.dg/parse/invalid1.C: Likewise
+ * g++.dg/parse/parameter-declaration-1.C: Likewise
+ * g++.dg/parse/parser-pr28152-2.C: Likewise
+ * g++.dg/parse/parser-pr28152.C: Likewise
+ * g++.dg/parse/pr68722.C: Likewise
+ * g++.dg/parse/pr96258.C: Likewise
+ * g++.dg/pr46852.C: Likewise
+ * g++.dg/pr46868.C: Likewise
+ * g++.dg/template/crash115.C: Likewise
+ * g++.dg/template/crash43.C: Likewise
+ * g++.dg/template/crash90.C: Likewise
+ * g++.dg/template/error-recovery1.C: Likewise
+ * g++.dg/template/error57.C: Likewise
+ * g++.old-deja/g++.other/crash31.C: Likewise
+
+2020-12-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/97597
+ * g++.dg/init/empty3.C: New test.
+
+2020-12-23 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/constexpr-overflow3.C: Use INT_MAX.
+
+2020-12-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/98332
+ * g++.dg/cpp0x/constexpr-overflow3.C: New test.
+
+2020-12-23 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/98427
+ * gdc.dg/pr98427.d: New test.
+
+2020-12-23 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/96793
+ * gcc.target/i386/pr96793-1.c: New test.
+
+2020-12-22 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/modules/access-1_a.C: New.: New.
+ * g++.dg/modules/access-1_b.C: New.
+ * g++.dg/modules/access-1_c.C: New.
+ * g++.dg/modules/adhoc-1_a.C: New.
+ * g++.dg/modules/adhoc-1_b.C: New.
+ * g++.dg/modules/adl-1_a.C: New.
+ * g++.dg/modules/adl-1_b.C: New.
+ * g++.dg/modules/adl-1_c.C: New.
+ * g++.dg/modules/adl-2_a.C: New.
+ * g++.dg/modules/adl-2_b.C: New.
+ * g++.dg/modules/adl-2_c.C: New.
+ * g++.dg/modules/adl-3_a.C: New.
+ * g++.dg/modules/adl-3_b.C: New.
+ * g++.dg/modules/adl-3_c.C: New.
+ * g++.dg/modules/adl-4_a.C: New.
+ * g++.dg/modules/adl-4_b.C: New.
+ * g++.dg/modules/adl-5_a.c: New.
+ * g++.dg/modules/adl-5_b.C: New.
+ * g++.dg/modules/adl-5_c.C: New.
+ * g++.dg/modules/adl-5_d.C: New.
+ * g++.dg/modules/alias-1_a.H: New.
+ * g++.dg/modules/alias-1_b.C: New.
+ * g++.dg/modules/alias-1_c.C: New.
+ * g++.dg/modules/alias-1_d.C: New.
+ * g++.dg/modules/alias-1_e.C: New.
+ * g++.dg/modules/alias-1_f.C: New.
+ * g++.dg/modules/alias-2_a.H: New.
+ * g++.dg/modules/alias-2_b.C: New.
+ * g++.dg/modules/align-type-1_a.C: New.
+ * g++.dg/modules/align-type-1_b.C: New.
+ * g++.dg/modules/ambig-1_a.C: New.
+ * g++.dg/modules/ambig-1_b.C: New.
+ * g++.dg/modules/anon-1_a.C: New.
+ * g++.dg/modules/anon-1_b.C: New.
+ * g++.dg/modules/anon-1_c.C: New.
+ * g++.dg/modules/anon-2.h: New.
+ * g++.dg/modules/anon-2_a.H: New.
+ * g++.dg/modules/anon-2_b.C: New.
+ * g++.dg/modules/atom-decl-0_a.C: New.
+ * g++.dg/modules/atom-decl-0_b.C: New.
+ * g++.dg/modules/atom-decl-0_c.C: New.
+ * g++.dg/modules/atom-decl-2.C: New.
+ * g++.dg/modules/atom-decl-3.C: New.
+ * g++.dg/modules/atom-pragma-1.C: New.
+ * g++.dg/modules/atom-pragma-3.C: New.
+ * g++.dg/modules/atom-preamble-1.C: New.
+ * g++.dg/modules/atom-preamble-2_a.C: New.
+ * g++.dg/modules/atom-preamble-2_b.C: New.
+ * g++.dg/modules/atom-preamble-2_c.C: New.
+ * g++.dg/modules/atom-preamble-2_d.C: New.
+ * g++.dg/modules/atom-preamble-2_e.C: New.
+ * g++.dg/modules/atom-preamble-2_f.C: New.
+ * g++.dg/modules/atom-preamble-3.C: New.
+ * g++.dg/modules/atom-preamble-4.C: New.
+ * g++.dg/modules/auto-1.h: New.
+ * g++.dg/modules/auto-1_a.H: New.
+ * g++.dg/modules/auto-1_b.C: New.
+ * g++.dg/modules/auto-2.h: New.
+ * g++.dg/modules/auto-2_a.H: New.
+ * g++.dg/modules/auto-2_b.C: New.
+ * g++.dg/modules/bad-mapper-1.C: New.
+ * g++.dg/modules/bad-mapper-2.C: New.
+ * g++.dg/modules/bad-mapper-3.C: New.
+ * g++.dg/modules/ben-1.map: New.
+ * g++.dg/modules/ben-1_a.C: New.
+ * g++.dg/modules/ben-1_b.C: New.
+ * g++.dg/modules/bfield-1_a.C: New.
+ * g++.dg/modules/bfield-1_b.C: New.
+ * g++.dg/modules/bfield-2_a.C: New.
+ * g++.dg/modules/bfield-2_b.C: New.
+ * g++.dg/modules/bool-1.h: New.
+ * g++.dg/modules/bool-1_a.H: New.
+ * g++.dg/modules/bool-1_b.H: New.
+ * g++.dg/modules/bool-1_c.C: New.
+ * g++.dg/modules/bug-1_a.C: New.
+ * g++.dg/modules/bug-1_b.C: New.
+ * g++.dg/modules/builtin-1_a.C: New.
+ * g++.dg/modules/builtin-1_b.C: New.
+ * g++.dg/modules/builtin-2.C: New.
+ * g++.dg/modules/builtin-3_b.C: New.
+ * g++.dg/modules/builtin-4_a.H: New.
+ * g++.dg/modules/builtin-4_b.C: New.
+ * g++.dg/modules/builtin-5_a.H: New.
+ * g++.dg/modules/builtin-5_b.C: New.
+ * g++.dg/modules/builtin-6_a.H: New.
+ * g++.dg/modules/builtin-6_b.C: New.
+ * g++.dg/modules/builtin-7_a.H: New.
+ * g++.dg/modules/builtin-7_b.C: New.
+ * g++.dg/modules/by-name-1.C: New.
+ * g++.dg/modules/cexpr-1_a.C: New.
+ * g++.dg/modules/cexpr-1_b.C: New.
+ * g++.dg/modules/cexpr-2_a.C: New.
+ * g++.dg/modules/cexpr-2_b.C: New.
+ * g++.dg/modules/circ-1_a.C: New.
+ * g++.dg/modules/circ-1_b.C: New.
+ * g++.dg/modules/circ-1_c.C: New.
+ * g++.dg/modules/circ-1_d.C: New.
+ * g++.dg/modules/class-1_a.C: New.
+ * g++.dg/modules/class-1_b.C: New.
+ * g++.dg/modules/class-1_c.C: New.
+ * g++.dg/modules/class-2_a.C: New.
+ * g++.dg/modules/class-2_b.C: New.
+ * g++.dg/modules/class-3_a.C: New.
+ * g++.dg/modules/class-3_b.C: New.
+ * g++.dg/modules/class-3_c.C: New.
+ * g++.dg/modules/class-3_d.C: New.
+ * g++.dg/modules/class-4_a.C: New.
+ * g++.dg/modules/class-4_b.C: New.
+ * g++.dg/modules/class-5_a.C: New.
+ * g++.dg/modules/class-5_b.C: New.
+ * g++.dg/modules/class-5_c.C: New.
+ * g++.dg/modules/class-6_a.C: New.
+ * g++.dg/modules/class-6_b.C: New.
+ * g++.dg/modules/class-6_c.C: New.
+ * g++.dg/modules/class-7_a.C: New.
+ * g++.dg/modules/class-7_b.C: New.
+ * g++.dg/modules/class-7_c.C: New.
+ * g++.dg/modules/class-8_a.C: New.
+ * g++.dg/modules/class-8_b.C: New.
+ * g++.dg/modules/clone-1_a.C: New.
+ * g++.dg/modules/clone-1_b.C: New.
+ * g++.dg/modules/concept-1_a.C: New.
+ * g++.dg/modules/concept-1_b.C: New.
+ * g++.dg/modules/concept-2_a.C: New.
+ * g++.dg/modules/concept-2_b.C: New.
+ * g++.dg/modules/concept-3_a.C: New.
+ * g++.dg/modules/concept-3_b.C: New.
+ * g++.dg/modules/concept-4.H: New.
+ * g++.dg/modules/concept-5.h: New.
+ * g++.dg/modules/concept-5_a.H: New.
+ * g++.dg/modules/concept-5_b.C: New.
+ * g++.dg/modules/concept-6.h: New.
+ * g++.dg/modules/concept-6_a.H: New.
+ * g++.dg/modules/concept-6_b.C: New.
+ * g++.dg/modules/constrained-partial-1_a.C: New.
+ * g++.dg/modules/constrained-partial-1_b.C: New.
+ * g++.dg/modules/convop-1_a.C: New.
+ * g++.dg/modules/convop-1_b.C: New.
+ * g++.dg/modules/cpp-1.C: New.
+ * g++.dg/modules/cpp-2_a.H: New.
+ * g++.dg/modules/cpp-2_b.H: New.
+ * g++.dg/modules/cpp-2_c.C: New.
+ * g++.dg/modules/cpp-3.C: New.
+ * g++.dg/modules/cpp-4.C: New.
+ * g++.dg/modules/cpp-4.h: New.
+ * g++.dg/modules/cpp-5_a.H: New.
+ * g++.dg/modules/cpp-5_b.C: New.
+ * g++.dg/modules/cpp-5_c.C: New.
+ * g++.dg/modules/cpp-6_a.H: New.
+ * g++.dg/modules/cpp-6_b.H: New.
+ * g++.dg/modules/cpp-6_c.C: New.
+ * g++.dg/modules/debug-1_a.C: New.
+ * g++.dg/modules/debug-1_b.C: New.
+ * g++.dg/modules/decomp-1_a.C: New.
+ * g++.dg/modules/decomp-1_b.C: New.
+ * g++.dg/modules/deferred-1.h: New.
+ * g++.dg/modules/deferred-1_a.H: New.
+ * g++.dg/modules/deferred-1_b.C: New.
+ * g++.dg/modules/dep-1_a.C: New.
+ * g++.dg/modules/dep-1_b.C: New.
+ * g++.dg/modules/dep-2.C: New.
+ * g++.dg/modules/dep-3.C: New.
+ * g++.dg/modules/dir-only-1.C: New.
+ * g++.dg/modules/dir-only-2_a.H: New.
+ * g++.dg/modules/dir-only-2_b.C: New.
+ * g++.dg/modules/dir-only-3.C: New.
+ * g++.dg/modules/dir-only-4.C: New.
+ * g++.dg/modules/dir-recovery.C: New.
+ * g++.dg/modules/enum-1_a.C: New.
+ * g++.dg/modules/enum-1_b.C: New.
+ * g++.dg/modules/enum-2_a.C: New.
+ * g++.dg/modules/enum-2_b.C: New.
+ * g++.dg/modules/enum-3_a.C: New.
+ * g++.dg/modules/enum-3_b.C: New.
+ * g++.dg/modules/enum-4_a.C: New.
+ * g++.dg/modules/enum-4_b.C: New.
+ * g++.dg/modules/enum-5_a.H: New.
+ * g++.dg/modules/enum-5_b.C: New.
+ * g++.dg/modules/enum-6_a.H: New.
+ * g++.dg/modules/enum-6_b.C: New.
+ * g++.dg/modules/enum-7.C: New.
+ * g++.dg/modules/enum-8_a.H: New.
+ * g++.dg/modules/enum-8_b.H: New.
+ * g++.dg/modules/enum-8_c.C: New.
+ * g++.dg/modules/enum-8_d.C: New.
+ * g++.dg/modules/enum-bad-1_a.H: New.
+ * g++.dg/modules/enum-bad-1_b.C: New.
+ * g++.dg/modules/err-1_a.C: New.
+ * g++.dg/modules/err-1_b.C: New.
+ * g++.dg/modules/err-1_c.C: New.
+ * g++.dg/modules/err-1_d.C: New.
+ * g++.dg/modules/except-1.C: New.
+ * g++.dg/modules/except-2.h: New.
+ * g++.dg/modules/except-2_a.H: New.
+ * g++.dg/modules/except-2_b.C: New.
+ * g++.dg/modules/except-3.h: New.
+ * g++.dg/modules/except-3_a.H: New.
+ * g++.dg/modules/except-3_b.C: New.
+ * g++.dg/modules/exp-xlate-1_a.H: New.
+ * g++.dg/modules/exp-xlate-1_b.C: New.
+ * g++.dg/modules/export-1.C: New.
+ * g++.dg/modules/extern-tpl-1_a.H: New.
+ * g++.dg/modules/extern-tpl-1_b.C: New.
+ * g++.dg/modules/extern-tpl-1_c.C: New.
+ * g++.dg/modules/extern-tpl-2_a.H: New.
+ * g++.dg/modules/extern-tpl-2_b.H: New.
+ * g++.dg/modules/extern-tpl-2_c.C: New.
+ * g++.dg/modules/extern-tpl-2_d.C: New.
+ * g++.dg/modules/flag-1_a.C: New.
+ * g++.dg/modules/flag-1_b.C: New.
+ * g++.dg/modules/fn-inline-1_a.C: New.
+ * g++.dg/modules/fn-inline-1_b.C: New.
+ * g++.dg/modules/fn-inline-1_c.C: New.
+ * g++.dg/modules/freeze-1_a.C: New.
+ * g++.dg/modules/freeze-1_b.C: New.
+ * g++.dg/modules/freeze-1_c.C: New.
+ * g++.dg/modules/freeze-1_d.C: New.
+ * g++.dg/modules/friend-1_a.C: New.
+ * g++.dg/modules/friend-1_b.C: New.
+ * g++.dg/modules/friend-1_c.C: New.
+ * g++.dg/modules/friend-2_a.C: New.
+ * g++.dg/modules/friend-2_b.C: New.
+ * g++.dg/modules/friend-3.C: New.
+ * g++.dg/modules/friend-4_a.C: New.
+ * g++.dg/modules/friend-4_b.C: New.
+ * g++.dg/modules/friend-5_a.C: New.
+ * g++.dg/modules/friend-5_b.C: New.
+ * g++.dg/modules/gc-1_a.C: New.
+ * g++.dg/modules/gc-1_b.C: New.
+ * g++.dg/modules/gc-1_c.C: New.
+ * g++.dg/modules/gc-1_d.C: New.
+ * g++.dg/modules/gc-2.map: New.
+ * g++.dg/modules/gc-2_a.C: New.
+ * g++.dg/modules/global-1_a.C: New.
+ * g++.dg/modules/global-1_b.C: New.
+ * g++.dg/modules/gmf-1_a.C: New.
+ * g++.dg/modules/gmf-1_b.C: New.
+ * g++.dg/modules/gmf-2_a.H: New.
+ * g++.dg/modules/gmf-2_b.C: New.
+ * g++.dg/modules/gmf-2_c.C: New.
+ * g++.dg/modules/gmf-2_d.C: New.
+ * g++.dg/modules/gvar_a.C: New.
+ * g++.dg/modules/gvar_b.C: New.
+ * g++.dg/modules/hdr-1_a.H: New.
+ * g++.dg/modules/hdr-1_b.H: New.
+ * g++.dg/modules/hdr-1_c.C: New.
+ * g++.dg/modules/hdr-init-1_a.H: New.
+ * g++.dg/modules/hdr-init-1_b.H: New.
+ * g++.dg/modules/hdr-init-1_c.C: New.
+ * g++.dg/modules/horcrux-1_a.C: New.
+ * g++.dg/modules/horcrux-1_b.C: New.
+ * g++.dg/modules/ice-1.C: New.
+ * g++.dg/modules/imp-inline-1_a.C: New.
+ * g++.dg/modules/imp-inline-1_b.C: New.
+ * g++.dg/modules/imp-member-1_a.C: New.
+ * g++.dg/modules/imp-member-1_b.C: New.
+ * g++.dg/modules/imp-member-1_c.C: New.
+ * g++.dg/modules/imp-member-1_d.C: New.
+ * g++.dg/modules/imp-member-1_e.C: New.
+ * g++.dg/modules/imp-member-2_a.C: New.
+ * g++.dg/modules/imp-member-2_b.C: New.
+ * g++.dg/modules/imp-member-2_c.C: New.
+ * g++.dg/modules/imp-member-3.H: New.
+ * g++.dg/modules/import-1_a.C: New.
+ * g++.dg/modules/import-1_b.C: New.
+ * g++.dg/modules/import-1_c.C: New.
+ * g++.dg/modules/import-1_d.C: New.
+ * g++.dg/modules/import-1_e.C: New.
+ * g++.dg/modules/import-1_f.C: New.
+ * g++.dg/modules/import-1_g.C: New.
+ * g++.dg/modules/import-2.C: New.
+ * g++.dg/modules/inc-xlate-1.map: New.
+ * g++.dg/modules/inc-xlate-1_a.H: New.
+ * g++.dg/modules/inc-xlate-1_b.H: New.
+ * g++.dg/modules/inc-xlate-1_c.C: New.
+ * g++.dg/modules/inc-xlate-1_e.C: New.
+ * g++.dg/modules/indirect-1_a.C: New.
+ * g++.dg/modules/indirect-1_b.C: New.
+ * g++.dg/modules/indirect-1_c.C: New.
+ * g++.dg/modules/indirect-2_a.C: New.
+ * g++.dg/modules/indirect-2_b.C: New.
+ * g++.dg/modules/indirect-2_c.C: New.
+ * g++.dg/modules/indirect-3_a.C: New.
+ * g++.dg/modules/indirect-3_b.C: New.
+ * g++.dg/modules/indirect-3_c.C: New.
+ * g++.dg/modules/indirect-4_a.C: New.
+ * g++.dg/modules/indirect-4_b.C: New.
+ * g++.dg/modules/indirect-4_c.C: New.
+ * g++.dg/modules/inext-1.H: New.
+ * g++.dg/modules/inh-tmpl-ctor-1.h: New.
+ * g++.dg/modules/inh-tmpl-ctor-1_a.H: New.
+ * g++.dg/modules/inh-tmpl-ctor-1_b.C: New.
+ * g++.dg/modules/init-1_a.C: New.
+ * g++.dg/modules/init-1_b.C: New.
+ * g++.dg/modules/init-2_a.C: New.
+ * g++.dg/modules/init-2_b.C: New.
+ * g++.dg/modules/init-2_c.C: New.
+ * g++.dg/modules/inst-1_a.C: New.
+ * g++.dg/modules/inst-1_b.C: New.
+ * g++.dg/modules/inst-2_a.C: New.
+ * g++.dg/modules/inst-2_b.C: New.
+ * g++.dg/modules/inst-3_a.C: New.
+ * g++.dg/modules/inst-3_b.C: New.
+ * g++.dg/modules/inst-4_a.C: New.
+ * g++.dg/modules/inst-4_b.C: New.
+ * g++.dg/modules/inst-5_a.H: New.
+ * g++.dg/modules/inst-5_b.C: New.
+ * g++.dg/modules/internal-1.C: New.
+ * g++.dg/modules/internal-2_a.H: New.
+ * g++.dg/modules/internal-2_b.H: New.
+ * g++.dg/modules/internal-2_c.C: New.
+ * g++.dg/modules/isalnum.H: New.
+ * g++.dg/modules/keyword-1_a.C: New.
+ * g++.dg/modules/keyword-1_b.C: New.
+ * g++.dg/modules/lambda-1_a.C: New.
+ * g++.dg/modules/lambda-1_b.C: New.
+ * g++.dg/modules/lambda-2.h: New.
+ * g++.dg/modules/lambda-2_a.H: New.
+ * g++.dg/modules/lambda-2_b.C: New.
+ * g++.dg/modules/lambda-2_c.C: New.
+ * g++.dg/modules/lambda-3.h: New.
+ * g++.dg/modules/lambda-3_a.H: New.
+ * g++.dg/modules/lambda-3_b.C: New.
+ * g++.dg/modules/lambda-3_c.C: New.
+ * g++.dg/modules/lambda-4.h: New.
+ * g++.dg/modules/lambda-4_a.H: New.
+ * g++.dg/modules/lambda-4_b.C: New.
+ * g++.dg/modules/lang-1_a.H: New.
+ * g++.dg/modules/lang-1_b.C: New.
+ * g++.dg/modules/lang-1_c.C: New.
+ * g++.dg/modules/lang-2_a.C: New.
+ * g++.dg/modules/lang-2_b.C: New.
+ * g++.dg/modules/late-ret-1.H: New.
+ * g++.dg/modules/late-ret-2_a.H: New.
+ * g++.dg/modules/late-ret-2_b.H: New.
+ * g++.dg/modules/late-ret-2_c.C: New.
+ * g++.dg/modules/late-ret-3_a.H: New.
+ * g++.dg/modules/late-ret-3_b.H: New.
+ * g++.dg/modules/late-ret-3_c.C: New.
+ * g++.dg/modules/lazy-1_a.C: New.
+ * g++.dg/modules/lazy-1_b.C: New.
+ * g++.dg/modules/leg-merge-1_a.H: New.
+ * g++.dg/modules/leg-merge-1_b.H: New.
+ * g++.dg/modules/leg-merge-1_c.C: New.
+ * g++.dg/modules/leg-merge-1_d.C: New.
+ * g++.dg/modules/leg-merge-2_a.H: New.
+ * g++.dg/modules/leg-merge-2_b.H: New.
+ * g++.dg/modules/leg-merge-2_c.C: New.
+ * g++.dg/modules/leg-merge-3_a.H: New.
+ * g++.dg/modules/leg-merge-3_b.H: New.
+ * g++.dg/modules/leg-merge-3_c.C: New.
+ * g++.dg/modules/leg-merge-3_d.C: New.
+ * g++.dg/modules/leg-merge-4_a.H: New.
+ * g++.dg/modules/leg-merge-4_b.H: New.
+ * g++.dg/modules/leg-merge-4_c.C: New.
+ * g++.dg/modules/leg-merge-5_a.H: New.
+ * g++.dg/modules/leg-merge-5_b.H: New.
+ * g++.dg/modules/leg-merge-5_c.C: New.
+ * g++.dg/modules/leg-merge-6_a.H: New.
+ * g++.dg/modules/leg-merge-6_b.H: New.
+ * g++.dg/modules/leg-merge-6_c.C: New.
+ * g++.dg/modules/leg-merge-7_a.H: New.
+ * g++.dg/modules/leg-merge-7_b.H: New.
+ * g++.dg/modules/leg-merge-7_c.C: New.
+ * g++.dg/modules/leg-merge-8_a.H: New.
+ * g++.dg/modules/leg-merge-8_b.H: New.
+ * g++.dg/modules/leg-merge-8_c.C: New.
+ * g++.dg/modules/leg-merge-9_a.H: New.
+ * g++.dg/modules/leg-merge-9_b.H: New.
+ * g++.dg/modules/leg-merge-9_c.C: New.
+ * g++.dg/modules/legacy-1_a.H: New.
+ * g++.dg/modules/legacy-1_b.C: New.
+ * g++.dg/modules/legacy-1_c.C: New.
+ * g++.dg/modules/legacy-2.h: New.
+ * g++.dg/modules/legacy-2.map: New.
+ * g++.dg/modules/legacy-2_a.H: New.
+ * g++.dg/modules/legacy-2_b.H: New.
+ * g++.dg/modules/legacy-2_c.C: New.
+ * g++.dg/modules/legacy-2_d.C: New.
+ * g++.dg/modules/legacy-3.h: New.
+ * g++.dg/modules/legacy-3_a.H: New.
+ * g++.dg/modules/legacy-3_b.H: New.
+ * g++.dg/modules/legacy-3_c.H: New.
+ * g++.dg/modules/legacy-6.map: New.
+ * g++.dg/modules/legacy-6_a.H: New.
+ * g++.dg/modules/legacy-6_b.H: New.
+ * g++.dg/modules/legacy-6_c.C: New.
+ * g++.dg/modules/legacy-6_d.C: New.
+ * g++.dg/modules/legacy-6_e.C: New.
+ * g++.dg/modules/legacy-6_f.C: New.
+ * g++.dg/modules/legacy-7_a.H: New.
+ * g++.dg/modules/legacy-7_b.C: New.
+ * g++.dg/modules/legacy-8_a.H: New.
+ * g++.dg/modules/legacy-8_b.H: New.
+ * g++.dg/modules/legacy-8_c.C: New.
+ * g++.dg/modules/legacy-8_d.C: New.
+ * g++.dg/modules/legacy-8_e.C: New.
+ * g++.dg/modules/libfn-1_a.C: New.
+ * g++.dg/modules/libfn-1_b.C: New.
+ * g++.dg/modules/literals-1_a.C: New.
+ * g++.dg/modules/literals-1_b.C: New.
+ * g++.dg/modules/loc-1_a.C: New.
+ * g++.dg/modules/loc-1_b.C: New.
+ * g++.dg/modules/loc-1_c.C: New.
+ * g++.dg/modules/loc-2_a.C: New.
+ * g++.dg/modules/loc-2_b.C: New.
+ * g++.dg/modules/loc-2_c.C: New.
+ * g++.dg/modules/loc-2_d.C: New.
+ * g++.dg/modules/loc-2_e.C: New.
+ * g++.dg/modules/loc-2_f.C: New.
+ * g++.dg/modules/loc-wrapper-1.h: New.
+ * g++.dg/modules/loc-wrapper-1_a.H: New.
+ * g++.dg/modules/loc-wrapper-1_b.C: New.
+ * g++.dg/modules/local-1_a.C: New.
+ * g++.dg/modules/local-1_b.C: New.
+ * g++.dg/modules/local-extern-1.C: New.
+ * g++.dg/modules/local-extern-2.H: New.
+ * g++.dg/modules/local-struct-1_a.C: New.
+ * g++.dg/modules/local-struct-1_b.C: New.
+ * g++.dg/modules/macloc-1_a.C: New.
+ * g++.dg/modules/macloc-1_b.C: New.
+ * g++.dg/modules/macloc-1_c.C: New.
+ * g++.dg/modules/macloc-1_d.C: New.
+ * g++.dg/modules/macloc-2_a.H: New.
+ * g++.dg/modules/macloc-2_b.C: New.
+ * g++.dg/modules/macro-1_a.H: New.
+ * g++.dg/modules/macro-1_b.C: New.
+ * g++.dg/modules/macro-2_a.H: New.
+ * g++.dg/modules/macro-2_b.H: New.
+ * g++.dg/modules/macro-2_c.H: New.
+ * g++.dg/modules/macro-2_d.C: New.
+ * g++.dg/modules/macro-3_a.H: New.
+ * g++.dg/modules/macro-3_b.H: New.
+ * g++.dg/modules/macro-3_c.C: New.
+ * g++.dg/modules/macro-4_a.H: New.
+ * g++.dg/modules/macro-4_b.H: New.
+ * g++.dg/modules/macro-4_c.H: New.
+ * g++.dg/modules/macro-4_d.C: New.
+ * g++.dg/modules/macro-4_e.C: New.
+ * g++.dg/modules/macro-4_f.C: New.
+ * g++.dg/modules/macro-4_g.C: New.
+ * g++.dg/modules/macro-5_a.H: New.
+ * g++.dg/modules/macro-5_b.H: New.
+ * g++.dg/modules/macro-5_c.C: New.
+ * g++.dg/modules/macro-6_a.H: New.
+ * g++.dg/modules/macro-6_b.C: New.
+ * g++.dg/modules/macro-6_c.C: New.
+ * g++.dg/modules/macro-7_a.C: New.
+ * g++.dg/modules/macro-7_b.C: New.
+ * g++.dg/modules/macro-7_c.C: New.
+ * g++.dg/modules/map-1.map: New.
+ * g++.dg/modules/map-1_a.C: New.
+ * g++.dg/modules/map-1_b.C: New.
+ * g++.dg/modules/map-1_b.map: New.
+ * g++.dg/modules/map-2.C: New.
+ * g++.dg/modules/map-2.map: New.
+ * g++.dg/modules/member-def-1_a.C: New.
+ * g++.dg/modules/member-def-1_b.C: New.
+ * g++.dg/modules/member-def-1_c.C: New.
+ * g++.dg/modules/member-def-1_d.C: New.
+ * g++.dg/modules/member-def-2_a.C: New.
+ * g++.dg/modules/member-def-2_b.C: New.
+ * g++.dg/modules/member-def-2_c.C: New.
+ * g++.dg/modules/member-def-2_d.C: New.
+ * g++.dg/modules/memref-1_a.C: New.
+ * g++.dg/modules/memref-1_b.C: New.
+ * g++.dg/modules/merge-10.h: New.
+ * g++.dg/modules/merge-10_a.H: New.
+ * g++.dg/modules/merge-10_b.C: New.
+ * g++.dg/modules/merge-11.h: New.
+ * g++.dg/modules/merge-11_a.H: New.
+ * g++.dg/modules/merge-11_b.C: New.
+ * g++.dg/modules/merge-12.h: New.
+ * g++.dg/modules/merge-12_a.H: New.
+ * g++.dg/modules/merge-12_b.C: New.
+ * g++.dg/modules/merge-13.h: New.
+ * g++.dg/modules/merge-13_a.H: New.
+ * g++.dg/modules/merge-13_b.C: New.
+ * g++.dg/modules/merge-14.h: New.
+ * g++.dg/modules/merge-14_a.H: New.
+ * g++.dg/modules/merge-14_b.C: New.
+ * g++.dg/modules/merge-15.h: New.
+ * g++.dg/modules/merge-15_a.H: New.
+ * g++.dg/modules/merge-15_b.C: New.
+ * g++.dg/modules/merge-1_a.C: New.
+ * g++.dg/modules/merge-1_b.C: New.
+ * g++.dg/modules/merge-2_a.H: New.
+ * g++.dg/modules/merge-2_b.C: New.
+ * g++.dg/modules/merge-3_a.H: New.
+ * g++.dg/modules/merge-3_b.C: New.
+ * g++.dg/modules/merge-4.h: New.
+ * g++.dg/modules/merge-4_a.H: New.
+ * g++.dg/modules/merge-4_b.C: New.
+ * g++.dg/modules/merge-5.h: New.
+ * g++.dg/modules/merge-5_a.H: New.
+ * g++.dg/modules/merge-5_b.C: New.
+ * g++.dg/modules/merge-6.h: New.
+ * g++.dg/modules/merge-6_a.H: New.
+ * g++.dg/modules/merge-6_b.C: New.
+ * g++.dg/modules/merge-7.h: New.
+ * g++.dg/modules/merge-7_a.H: New.
+ * g++.dg/modules/merge-7_b.C: New.
+ * g++.dg/modules/merge-8.h: New.
+ * g++.dg/modules/merge-8_a.H: New.
+ * g++.dg/modules/merge-8_b.C: New.
+ * g++.dg/modules/merge-9.h: New.
+ * g++.dg/modules/merge-9_a.H: New.
+ * g++.dg/modules/merge-9_b.C: New.
+ * g++.dg/modules/mod-exp-1_a.C: New.
+ * g++.dg/modules/mod-exp-1_b.C: New.
+ * g++.dg/modules/mod-imp-1_a.C: New.
+ * g++.dg/modules/mod-imp-1_b.C: New.
+ * g++.dg/modules/mod-imp-1_c.C: New.
+ * g++.dg/modules/mod-imp-1_d.C: New.
+ * g++.dg/modules/mod-impl-1_a.C: New.
+ * g++.dg/modules/mod-impl-1_b.C: New.
+ * g++.dg/modules/mod-impl-1_c.C: New.
+ * g++.dg/modules/mod-impl-1_d.C: New.
+ * g++.dg/modules/mod-indirect-1_a.C: New.
+ * g++.dg/modules/mod-indirect-1_b.C: New.
+ * g++.dg/modules/mod-indirect-1_c.C: New.
+ * g++.dg/modules/mod-indirect-1_d.C: New.
+ * g++.dg/modules/mod-indirect-1_e.C: New.
+ * g++.dg/modules/mod-stamp-1_a.C: New.
+ * g++.dg/modules/mod-stamp-1_b.C: New.
+ * g++.dg/modules/mod-stamp-1_c.C: New.
+ * g++.dg/modules/mod-stamp-1_d.C: New.
+ * g++.dg/modules/mod-sym-1.C: New.
+ * g++.dg/modules/mod-sym-2.C: New.
+ * g++.dg/modules/mod-sym-3.C: New.
+ * g++.dg/modules/mod-tpl-1_a.C: New.
+ * g++.dg/modules/mod-tpl-1_b.C: New.
+ * g++.dg/modules/mod-tpl-2_a.C: New.
+ * g++.dg/modules/mod-tpl-2_b.C: New.
+ * g++.dg/modules/mutual-friend.ii: New.
+ * g++.dg/modules/namespace-1_a.C: New.
+ * g++.dg/modules/namespace-1_b.C: New.
+ * g++.dg/modules/namespace-1_c.C: New.
+ * g++.dg/modules/namespace-2_a.C: New.
+ * g++.dg/modules/namespace-2_b.C: New.
+ * g++.dg/modules/namespace-3_a.C: New.
+ * g++.dg/modules/namespace-3_b.C: New.
+ * g++.dg/modules/namespace-4_a.C: New.
+ * g++.dg/modules/namespace-4_b.C: New.
+ * g++.dg/modules/namespace-4_c.C: New.
+ * g++.dg/modules/nest-1_a.C: New.
+ * g++.dg/modules/nest-1_b.C: New.
+ * g++.dg/modules/nest-1_c.C: New.
+ * g++.dg/modules/nested-1_a.C: New.
+ * g++.dg/modules/nested-1_b.C: New.
+ * g++.dg/modules/nested-1_c.C: New.
+ * g++.dg/modules/nested-2_a.C: New.
+ * g++.dg/modules/nested-2_b.C: New.
+ * g++.dg/modules/nested-constr-1.h: New.
+ * g++.dg/modules/nested-constr-1_a.H: New.
+ * g++.dg/modules/nested-constr-1_b.C: New.
+ * g++.dg/modules/nested-constr-2_a.C: New.
+ * g++.dg/modules/nested-constr-2_b.C: New.
+ * g++.dg/modules/nested-constr-2_c.C: New.
+ * g++.dg/modules/nodes-1_a.C: New.
+ * g++.dg/modules/nodes-1_b.C: New.
+ * g++.dg/modules/noexcept-1.h: New.
+ * g++.dg/modules/noexcept-1_a.H: New.
+ * g++.dg/modules/noexcept-1_b.C: New.
+ * g++.dg/modules/ns-alias-1_a.C: New.
+ * g++.dg/modules/ns-alias-1_b.C: New.
+ * g++.dg/modules/ns-alias-1_c.C: New.
+ * g++.dg/modules/ns-dir-1_a.C: New.
+ * g++.dg/modules/ns-dir-1_b.C: New.
+ * g++.dg/modules/ns-dup-1_a.C: New.
+ * g++.dg/modules/ns-dup-1_b.C: New.
+ * g++.dg/modules/ns-imp-1_a.C: New.
+ * g++.dg/modules/ns-imp-1_b.C: New.
+ * g++.dg/modules/ns-imp-1_c.C: New.
+ * g++.dg/modules/ns-part-1_a.C: New.
+ * g++.dg/modules/ns-part-1_b.C: New.
+ * g++.dg/modules/ns-part-1_c.C: New.
+ * g++.dg/modules/nsdmi-1_a.C: New.
+ * g++.dg/modules/nsdmi-1_b.C: New.
+ * g++.dg/modules/nsdmi-2.C: New.
+ * g++.dg/modules/omp-1_a.C: New.
+ * g++.dg/modules/omp-1_b.C: New.
+ * g++.dg/modules/omp-1_c.C: New.
+ * g++.dg/modules/omp-2_a.C: New.
+ * g++.dg/modules/omp-2_b.C: New.
+ * g++.dg/modules/only-1.C: New.
+ * g++.dg/modules/only-2.C: New.
+ * g++.dg/modules/only-3.C: New.
+ * g++.dg/modules/operator-1_a.C: New.
+ * g++.dg/modules/operator-1_b.C: New.
+ * g++.dg/modules/p0713-1.C: New.
+ * g++.dg/modules/p0713-2.C: New.
+ * g++.dg/modules/p0713-3.C: New.
+ * g++.dg/modules/part-1_a.C: New.
+ * g++.dg/modules/part-1_b.C: New.
+ * g++.dg/modules/part-1_c.C: New.
+ * g++.dg/modules/part-2_a.C: New.
+ * g++.dg/modules/part-2_b.C: New.
+ * g++.dg/modules/part-2_c.C: New.
+ * g++.dg/modules/part-2_d.C: New.
+ * g++.dg/modules/part-2_e.C: New.
+ * g++.dg/modules/part-3_a.C: New.
+ * g++.dg/modules/part-3_b.C: New.
+ * g++.dg/modules/part-3_c.C: New.
+ * g++.dg/modules/part-3_d.C: New.
+ * g++.dg/modules/part-4_a.C: New.
+ * g++.dg/modules/part-4_b.C: New.
+ * g++.dg/modules/part-4_c.C: New.
+ * g++.dg/modules/part-6_a.C: New.
+ * g++.dg/modules/part-6_b.C: New.
+ * g++.dg/modules/part-6_c.C: New.
+ * g++.dg/modules/part-6_d.C: New.
+ * g++.dg/modules/part-6_e.C: New.
+ * g++.dg/modules/part-7_a.C: New.
+ * g++.dg/modules/part-7_b.C: New.
+ * g++.dg/modules/part-7_c.C: New.
+ * g++.dg/modules/part-hdr-1_a.H: New.
+ * g++.dg/modules/part-hdr-1_b.C: New.
+ * g++.dg/modules/part-hdr-1_c.C: New.
+ * g++.dg/modules/part-mac-1_a.H: New.
+ * g++.dg/modules/part-mac-1_b.C: New.
+ * g++.dg/modules/part-mac-1_c.C: New.
+ * g++.dg/modules/partial-1.h: New.
+ * g++.dg/modules/partial-1_a.H: New.
+ * g++.dg/modules/partial-1_b.C: New.
+ * g++.dg/modules/pmf-1.h: New.
+ * g++.dg/modules/pmf-1_a.H: New.
+ * g++.dg/modules/pmf-1_b.C: New.
+ * g++.dg/modules/pmf-2.h: New.
+ * g++.dg/modules/pmf-2_a.H: New.
+ * g++.dg/modules/pmf-2_b.C: New.
+ * g++.dg/modules/pmp-1_a.C: New.
+ * g++.dg/modules/pmp-1_b.C: New.
+ * g++.dg/modules/pmp-2.C: New.
+ * g++.dg/modules/pmp-3.C: New.
+ * g++.dg/modules/pragma-1_a.H: New.
+ * g++.dg/modules/pragma-1_b.C: New.
+ * g++.dg/modules/predef-1.C: New.
+ * g++.dg/modules/predef-1.h: New.
+ * g++.dg/modules/predef-2.h: New.
+ * g++.dg/modules/predef-2_a.C: New.
+ * g++.dg/modules/predef-2_b.C: New.
+ * g++.dg/modules/preproc-1.C: New.
+ * g++.dg/modules/preproc-2_a.H: New.
+ * g++.dg/modules/preproc-2_b.C: New.
+ * g++.dg/modules/printf-1_a.H: New.
+ * g++.dg/modules/printf-1_b.C: New.
+ * g++.dg/modules/reparent-1_a.C: New.
+ * g++.dg/modules/reparent-1_b.C: New.
+ * g++.dg/modules/reparent-1_c.C: New.
+ * g++.dg/modules/scc-1.C: New.
+ * g++.dg/modules/scc-2.C: New.
+ * g++.dg/modules/shadow-1_a.C: New.
+ * g++.dg/modules/shadow-1_b.C: New.
+ * g++.dg/modules/stat-tpl-1_a.H: New.
+ * g++.dg/modules/static-1_a.C: New.
+ * g++.dg/modules/static-1_b.C: New.
+ * g++.dg/modules/static-1_c.C: New.
+ * g++.dg/modules/std-1_a.C: New.
+ * g++.dg/modules/std-1_b.C: New.
+ * g++.dg/modules/stdns_a.C: New.
+ * g++.dg/modules/stdns_b.C: New.
+ * g++.dg/modules/sv-1.h: New.
+ * g++.dg/modules/sv-1_a.C: New.
+ * g++.dg/modules/sv-1_b.C: New.
+ * g++.dg/modules/sym-subst-1.C: New.
+ * g++.dg/modules/sym-subst-2_a.C: New.
+ * g++.dg/modules/sym-subst-2_b.C: New.
+ * g++.dg/modules/sym-subst-3_a.C: New.
+ * g++.dg/modules/sym-subst-3_b.C: New.
+ * g++.dg/modules/sym-subst-4.C: New.
+ * g++.dg/modules/sym-subst-5.C: New.
+ * g++.dg/modules/sym-subst-6.C: New.
+ * g++.dg/modules/sys/alias-2_a.H: New.
+ * g++.dg/modules/sys/inext-1.H: New.
+ * g++.dg/modules/tdef-1_a.C: New.
+ * g++.dg/modules/tdef-1_b.C: New.
+ * g++.dg/modules/tdef-2_a.C: New.
+ * g++.dg/modules/tdef-2_b.C: New.
+ * g++.dg/modules/tdef-2_c.C: New.
+ * g++.dg/modules/tdef-3_a.C: New.
+ * g++.dg/modules/tdef-3_b.C: New.
+ * g++.dg/modules/tdef-3_c.C: New.
+ * g++.dg/modules/tdef-4_a.C: New.
+ * g++.dg/modules/tdef-4_b.C: New.
+ * g++.dg/modules/tdef-4_c.C: New.
+ * g++.dg/modules/tdef-5_a.C: New.
+ * g++.dg/modules/tdef-5_b.C: New.
+ * g++.dg/modules/tdef-6_a.H: New.
+ * g++.dg/modules/tdef-6_b.C: New.
+ * g++.dg/modules/tdef-7.h: New.
+ * g++.dg/modules/tdef-7_a.H: New.
+ * g++.dg/modules/tdef-7_b.C: New.
+ * g++.dg/modules/tdef-8_a.C: New.
+ * g++.dg/modules/tdef-8_b.C: New.
+ * g++.dg/modules/tdef-inst-1.h: New.
+ * g++.dg/modules/tdef-inst-1_a.C: New.
+ * g++.dg/modules/tdef-inst-1_b.C: New.
+ * g++.dg/modules/thunk-1_a.C: New.
+ * g++.dg/modules/thunk-1_b.C: New.
+ * g++.dg/modules/tmpl-part-req-1.h: New.
+ * g++.dg/modules/tmpl-part-req-1_a.H: New.
+ * g++.dg/modules/tmpl-part-req-1_b.C: New.
+ * g++.dg/modules/tmpl-part-req-2.h: New.
+ * g++.dg/modules/tmpl-part-req-2_a.H: New.
+ * g++.dg/modules/tmpl-part-req-2_b.C: New.
+ * g++.dg/modules/token-1.C: New.
+ * g++.dg/modules/token-2_a.C: New.
+ * g++.dg/modules/token-2_b.C: New.
+ * g++.dg/modules/token-3.C: New.
+ * g++.dg/modules/token-4.C: New.
+ * g++.dg/modules/token-5.C: New.
+ * g++.dg/modules/tpl-alias-1.h: New.
+ * g++.dg/modules/tpl-alias-1_a.H: New.
+ * g++.dg/modules/tpl-alias-1_b.C: New.
+ * g++.dg/modules/tpl-ary-1.h: New.
+ * g++.dg/modules/tpl-ary-1_a.H: New.
+ * g++.dg/modules/tpl-ary-1_b.C: New.
+ * g++.dg/modules/tpl-extern-fn-1_a.H: New.
+ * g++.dg/modules/tpl-extern-fn-1_b.C: New.
+ * g++.dg/modules/tpl-extern-var-1_a.H: New.
+ * g++.dg/modules/tpl-extern-var-1_b.C: New.
+ * g++.dg/modules/tpl-friend-1_a.C: New.
+ * g++.dg/modules/tpl-friend-1_b.C: New.
+ * g++.dg/modules/tpl-friend-2_a.C: New.
+ * g++.dg/modules/tpl-friend-2_b.C: New.
+ * g++.dg/modules/tpl-friend-3_a.C: New.
+ * g++.dg/modules/tpl-friend-3_b.C: New.
+ * g++.dg/modules/tpl-friend-4_a.C: New.
+ * g++.dg/modules/tpl-friend-4_b.C: New.
+ * g++.dg/modules/tpl-friend-5_a.C: New.
+ * g++.dg/modules/tpl-friend-5_b.C: New.
+ * g++.dg/modules/tpl-friend-6_a.C: New.
+ * g++.dg/modules/tpl-friend-6_b.C: New.
+ * g++.dg/modules/tpl-friend-7_a.C: New.
+ * g++.dg/modules/tpl-friend-7_b.C: New.
+ * g++.dg/modules/tpl-friend-merge-1.cc: New.
+ * g++.dg/modules/tpl-friend-merge-1.h: New.
+ * g++.dg/modules/tpl-friend-merge-1_a.H: New.
+ * g++.dg/modules/tpl-friend-merge-1_b.H: New.
+ * g++.dg/modules/tpl-friend-merge-1_c.H: New.
+ * g++.dg/modules/tpl-friend-merge-1_d.C: New.
+ * g++.dg/modules/tpl-friend-merge-1_e.C: New.
+ * g++.dg/modules/tpl-friend-merge-1_f.C: New.
+ * g++.dg/modules/tpl-spec-1_a.C: New.
+ * g++.dg/modules/tpl-spec-1_b.C: New.
+ * g++.dg/modules/tpl-spec-2_a.C: New.
+ * g++.dg/modules/tpl-spec-2_b.C: New.
+ * g++.dg/modules/tpl-spec-2_c.C: New.
+ * g++.dg/modules/tpl-spec-2_d.C: New.
+ * g++.dg/modules/tpl-spec-3_a.C: New.
+ * g++.dg/modules/tpl-spec-3_b.C: New.
+ * g++.dg/modules/tpl-spec-4_a.C: New.
+ * g++.dg/modules/tpl-spec-4_b.C: New.
+ * g++.dg/modules/tpl-spec-5_a.C: New.
+ * g++.dg/modules/tpl-spec-5_b.C: New.
+ * g++.dg/modules/tpl-spec-6_a.C: New.
+ * g++.dg/modules/tpl-spec-6_b.C: New.
+ * g++.dg/modules/tpl-spec-7.C: New.
+ * g++.dg/modules/tpl-tpl-friend-1_a.C: New.
+ * g++.dg/modules/tpl-tpl-friend-1_b.C: New.
+ * g++.dg/modules/tpl-tpl-mem-1_a.C: New.
+ * g++.dg/modules/tpl-tpl-mem-1_b.C: New.
+ * g++.dg/modules/tpl-tpl-merge-1.h: New.
+ * g++.dg/modules/tpl-tpl-merge-1_a.H: New.
+ * g++.dg/modules/tpl-tpl-merge-1_b.C: New.
+ * g++.dg/modules/tpl-tpl-merge-2.h: New.
+ * g++.dg/modules/tpl-tpl-merge-2_a.H: New.
+ * g++.dg/modules/tpl-tpl-merge-2_b.C: New.
+ * g++.dg/modules/tpl-tpl-parm-1_a.H: New.
+ * g++.dg/modules/tpl-tpl-parm-1_b.C: New.
+ * g++.dg/modules/tpl-tpl-parm-2.h: New.
+ * g++.dg/modules/tpl-tpl-parm-2_a.H: New.
+ * g++.dg/modules/tpl-tpl-parm-2_b.C: New.
+ * g++.dg/modules/tplmem-1_a.C: New.
+ * g++.dg/modules/tplmem-1_b.C: New.
+ * g++.dg/modules/tplmem-3_a.C: New.
+ * g++.dg/modules/tplmem-3_b.C: New.
+ * g++.dg/modules/ttp-1_a.C: New.
+ * g++.dg/modules/ttp-1_b.C: New.
+ * g++.dg/modules/ttp-2_a.C: New.
+ * g++.dg/modules/ttp-2_b.C: New.
+ * g++.dg/modules/ttp-3_a.C: New.
+ * g++.dg/modules/ttp-3_b.C: New.
+ * g++.dg/modules/typename-1_a.C: New.
+ * g++.dg/modules/typename-1_b.C: New.
+ * g++.dg/modules/unnamed-1_a.C: New.
+ * g++.dg/modules/unnamed-1_b.C: New.
+ * g++.dg/modules/unnamed-2.C: New.
+ * g++.dg/modules/used-1_a.H: New.
+ * g++.dg/modules/used-1_b.H: New.
+ * g++.dg/modules/used-1_c.C: New.
+ * g++.dg/modules/using-1_a.C: New.
+ * g++.dg/modules/using-1_b.C: New.
+ * g++.dg/modules/using-1_c.C: New.
+ * g++.dg/modules/using-2_a.C: New.
+ * g++.dg/modules/using-2_b.C: New.
+ * g++.dg/modules/using-2_c.C: New.
+ * g++.dg/modules/using-3.C: New.
+ * g++.dg/modules/using-4_a.C: New.
+ * g++.dg/modules/using-4_b.C: New.
+ * g++.dg/modules/using-5_a.C: New.
+ * g++.dg/modules/using-5_b.C: New.
+ * g++.dg/modules/using-6_a.C: New.
+ * g++.dg/modules/using-6_b.C: New.
+ * g++.dg/modules/using-7.C: New.
+ * g++.dg/modules/using-8_a.C: New.
+ * g++.dg/modules/using-8_b.C: New.
+ * g++.dg/modules/using-enum-1_a.H: New.
+ * g++.dg/modules/using-enum-1_b.C: New.
+ * g++.dg/modules/var-1_a.C: New.
+ * g++.dg/modules/var-1_b.C: New.
+ * g++.dg/modules/var-tpl-1_a.C: New.
+ * g++.dg/modules/var-tpl-1_b.C: New.
+ * g++.dg/modules/var-tpl-concept-1.h: New.
+ * g++.dg/modules/var-tpl-concept-1_a.C: New.
+ * g++.dg/modules/var-tpl-concept-1_b.C: New.
+ * g++.dg/modules/virt-1_a.C: New.
+ * g++.dg/modules/virt-1_b.C: New.
+ * g++.dg/modules/virt-2_a.C: New.
+ * g++.dg/modules/virt-2_b.C: New.
+ * g++.dg/modules/virt-2_c.C: New.
+ * g++.dg/modules/vmort-1_a.C: New.
+ * g++.dg/modules/vmort-1_b.C: New.
+ * g++.dg/modules/vmort-2_a.C: New.
+ * g++.dg/modules/vmort-2_b.C: New.
+ * g++.dg/modules/vmort-2_c.C: New.
+ * g++.dg/modules/vtt-1_a.C: New.
+ * g++.dg/modules/vtt-1_b.C: New.
+ * g++.dg/modules/vtt-1_c.C: New.
+ * g++.dg/modules/vtt-2.h: New.
+ * g++.dg/modules/vtt-2_a.H: New.
+ * g++.dg/modules/vtt-2_b.C: New.
+
+2020-12-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/93480
+ * g++.dg/cpp2a/spaceship-synth10.C: New test.
+ * g++.dg/cpp2a/spaceship-synth-neg5.C: New test.
+
+2020-12-22 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/96793
+ * gcc.target/i386/pr96793.c: New test.
+
+2020-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98353
+ * g++.dg/opt/pr98353.C: New test.
+
+2020-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98407
+ * gcc.c-torture/compile/pr98407.c: New test.
+
+2020-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98383
+ * g++.dg/gomp/pr98383.C: New test.
+
+2020-12-20 Max Filippov <jcmvbkbc@gmail.com>
+
+ * gcc.target/xtensa/bswap.c: New test.
+
+2020-12-20 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran.dg/coarray/send_char_array_1.f90: Correct coarray
+ indces.
+
+2020-12-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98366
+ * gcc.c-torture/execute/pr98366.c: New test.
+
+2020-12-19 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/98067
+ * gdc.dg/debug/debug.exp: New test.
+ * gdc.dg/debug/dwarf2/dwarf2.exp: New test.
+ * gdc.dg/debug/dwarf2/imports/pr98067.d: New test.
+ * gdc.dg/debug/dwarf2/langdw2.d: New test.
+ * gdc.dg/debug/dwarf2/langdw3.d: New test.
+ * gdc.dg/debug/dwarf2/pr98067.d: New test.
+ * gdc.dg/debug/trivial.d: New test.
+
+2020-12-18 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97750.c: Remove check for warning.
+
+2020-12-18 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * g++.dg/gomp/declare-target-3.C: Only check .offload_var_table
+ entries if offloading is enabled.
+
+2020-12-18 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ PR target/98177
+ * g++.target/aarch64/sve/pr98177-1.C: New test.
+ * g++.target/aarch64/sve/pr98177-2.C: New test.
+ * gcc.target/aarch64/sve/pr98177-1.c: New test.
+ * gcc.target/aarch64/sve/pr98177-2.c: New test.
+
+2020-12-18 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * g++.dg/gomp/declare-target-3.C: New.
+
+2020-12-18 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/83118
+ PR fortran/96012
+ * gfortran.dg/dependency_60.f90: New test.
+ * gfortran.dg/class_allocate_25.f90: New test.
+ * gfortran.dg/class_assign_4.f90: New test.
+ * gfortran.dg/unlimited_polymorphic_32.f03: New test.
+
+2020-12-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98343
+ * g++.dg/pch/pr98343.C: New test.
+ * g++.dg/pch/pr98343.Hs: New file.
+
+2020-12-18 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (go-set-goos): New procedure.
+ (go-gc-match): New procedure.
+ (go-gc-tests): Call go-set-goos. Use go-gc-match to handle +build
+ lines. Look for +build lines beyond first line of file.
+
+2020-12-18 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/96840
+ * g++.dg/cpp2a/concepts-pr88395.C: Adjust to expect the
+ self-recursive satisfaction to get directly diagnosed.
+ * g++.dg/cpp2a/concepts-recursive-sat2.C: Likewise.
+ * g++.dg/cpp2a/concepts-recursive-sat4.C: New test.
+
+2020-12-18 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/cpp2a/concepts-complete1.C: New test.
+ * g++.dg/cpp2a/concepts-complete2.C: New test.
+ * g++.dg/cpp2a/concepts-complete3.C: New test.
+
+2020-12-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97750.c: New.
+
+2020-12-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98289
+ * gcc.target/i386/pr98289.c: New test.
+ * gcc.dg/torture/pr98289.c: New test.
+
+2020-12-17 Arnaud Charlet <charlet@adacore.com>
+
+ * gnat.dg/debug15.adb: Remove fragile testcase.
+
+2020-12-17 Yannick Moy <moy@adacore.com>
+
+ * gnat.dg/interface6.adb, gnat.dg/not_null.adb,
+ gnat.dg/protected_func.adb: Adjust error messages.
+
+2020-12-17 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/92587
+ * gfortran.dg/finalize_37.f90: New test.
+
+2020-12-17 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/98307
+ * gfortran.dg/forall_19.f90: New test.
+
+2020-12-17 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * gcc.target/xtensa/shifts.c: New test.
+
+2020-12-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c: Don't
+ expect insn updates to be deferred.
+ * gcc.target/aarch64/sve/acle/asm/st4_s8.c: Expect the addition
+ to be folded into the address.
+ * gcc.target/aarch64/sve/acle/asm/st4_u8.c: Likewise.
+
+2020-12-16 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98047
+ * gcc.dg/qual-assign-7.c: New test.
+
+2020-12-16 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98260
+ * gcc.dg/unused-9.c: New test.
+
+2020-12-16 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/98280
+ * gcc.target/powerpc/fold-vec-logical-ors-char.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-ors-int.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-ors-longlong.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-ors-short.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-other-char.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-other-int.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-other-longlong.c: Adjust count.
+ * gcc.target/powerpc/fold-vec-logical-other-short.c: Adjust count.
+
+2020-12-16 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/template/pr98297.C: New.
+
+2020-12-16 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/98284
+ * gfortran.dg/pr98284.f90: New test.
+
+2020-12-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98146
+ * lib/target-supports.exp
+ (check_effective_target_R_flag_in_section): Also check
+ HAVE_INITFINI_ARRAY_SUPPORT != 0.
+
+2020-12-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98146
+ * c-c++-common/attr-used-5.c: Updated.
+ * c-c++-common/attr-used-6.c: Likewise.
+ * c-c++-common/attr-used-7.c: Likewise.
+ * c-c++-common/attr-used-8.c: Likewise.
+
+2020-12-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98146
+ * c-c++-common/attr-used-5.c: New test.
+ * c-c++-common/attr-used-6.c: Likewise.
+ * c-c++-common/attr-used-7.c: Likewise.
+ * c-c++-common/attr-used-8.c: Likewise.
+ * c-c++-common/attr-used-9.c: Likewise.
+
+2020-12-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96239
+ * gcc.dg/pr96239.c: New test.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/97868
+ * gcc.dg/tsan/atomic-fence.c: New test.
+
+2020-12-16 Martin Liska <mliska@suse.cz>
+
+ PR rtl-optimization/98271
+ PR rtl-optimization/98276
+ PR tree-optimization/98279
+ * gcc.dg/pr98271.c: New test.
+
+2020-12-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/pr98272.c: New test.
+
+2020-12-16 Kewen Lin <linkw@linux.ibm.com>
+
+ * gcc.target/powerpc/pr96933-1.c: Adjusted to check no rlwinm.
+ * gcc.target/powerpc/pr96933-2.c: Likewise.
+
+2020-12-15 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp0x/constexpr-52830.C: Remove dg-ice.
+
+2020-12-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96094
+ * gcc.dg/tree-ssa/pr96094.c: New test.
+
+2020-12-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/98277
+ * gdc.dg/pr98277.d: New test.
+
+2020-12-15 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/cpp2a/concepts-requires23.C: New test.
+
+2020-12-15 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/modules/mod-decl-0-2a.C: New.
+ * g++.dg/modules/mod-decl-0.C: New.
+ * g++.dg/modules/mod-decl-1.C: New.
+ * g++.dg/modules/mod-decl-2_a.C: New.
+ * g++.dg/modules/mod-decl-2_b.C: New.
+ * g++.dg/modules/mod-decl-2_c.C: New.
+ * g++.dg/modules/mod-decl-3.C: New.
+ * g++.dg/modules/mod-decl-5_a.C: New.
+ * g++.dg/modules/mod-decl-5_b.C: New.
+
+2020-12-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98274
+ * gcc.target/i386/pr98274.c: New test.
+
+2020-12-15 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/x86-64-v2.c: Don't expect
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 to be defined with -m32.
+ * gcc.target/i386/x86-64-v2-other.c: New test.
+ * gcc.target/i386/x86-64-v2-msabi.c: New test.
+ * gcc.target/i386/x86-64-v3.c: Fix a comment pasto. Don't expect
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 to be defined with -m32.
+ * gcc.target/i386/x86-64-v3-other.c: New test.
+ * gcc.target/i386/x86-64-v3-msabi.c: New test.
+ * gcc.target/i386/x86-64-v4.c:Don't expect
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 to be defined with -m32.
+ * gcc.target/i386/x86-64-v4-other.c: New test.
+ * gcc.target/i386/x86-64-v4-msabi.c: New test.
+
+2020-12-15 Max Filippov <jcmvbkbc@gmail.com>
+
+ * gcc.target/xtensa/pr98285.c: New test.
+
+2020-12-15 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (errchk): Retain any characters at the end
+ of the comment.
+
+2020-12-15 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr78102.c: Adjust testcase.
+
+2020-12-14 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/98166
+ PR c++/57111
+ PR middle-end/98160
+ * g++.dg/warn/Wmismatched-dealloc-2.C: Adjust test of expected warning.
+ * g++.dg/warn/Wmismatched-new-delete.C: Same.
+ * gcc.dg/Wmismatched-dealloc.c: Same.
+ * c-c++-common/Wfree-nonheap-object-2.c: New test.
+ * c-c++-common/Wfree-nonheap-object-3.c: New test.
+ * c-c++-common/Wfree-nonheap-object.c: New test.
+ * c-c++-common/Wmismatched-dealloc.c: New test.
+ * g++.dg/warn/Wfree-nonheap-object-3.C: New test.
+ * g++.dg/warn/Wfree-nonheap-object-4.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc-2.C: New test.
+ * g++.dg/warn/Wmismatched-new-delete-2.C: New test.
+ * g++.dg/warn/Wmismatched-new-delete.C: New test.
+ * gcc.dg/Wmismatched-dealloc-2.c: New test.
+ * gcc.dg/Wmismatched-dealloc-3.c: New test.
+ * gcc.dg/Wmismatched-dealloc.c: New test.
+
+2020-12-14 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * lib/target-supports.exp (check_effective_target_tune_cortex_a76): New
+ effective target test.
+ * gcc.target/aarch64/with-tune-config.c: New test.
+ * gcc.target/aarch64/with-tune-march.c: Likewise.
+ * gcc.target/aarch64/with-tune-mcpu.c: Likewise.
+ * gcc.target/aarch64/with-tune-mtune.c: Likewise.
+
+2020-12-14 Tamar Christina <tamar.christina@arm.com>
+
+ PR middle-end/98264
+ * gcc.target/i386/pr98264.c: New test.
+
+2020-12-14 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * lib/target-supports.exp(check_profiling_available): Limit
+ perf data buffer.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-vneg.c: Add tests for vneg.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-vmvn.c: Add tests for vmvn.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-vbic.c: Add tests for vbic.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-veor.c: Add tests for veor.
+
+2020-12-14 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/vect-half-floats.c: Fix typos.
+
+2020-12-14 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/98204
+ * c-c++-common/asan/pr98204.c: New test.
+
+2020-12-14 Nikhil Benesch <nikhil.benesch@gmail.com>
+
+ * gcc.misc-tests/godump-1.c: Add test cases.
+
+2020-12-13 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/push.c: New test.
+
+2020-12-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98256
+ * gcc.c-torture/compile/pr98256.c: New test.
+
+2020-12-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/92469
+ * gcc.target/i386/pr92469.c: New test.
+ * gcc.target/i386/pr79804.c: Adjust expected diagnostics.
+ * gcc.target/i386/pr88178.c: Expect an error.
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/arm/vect-half-floats.c: New test.
+
+2020-12-13 Tamar Christina <tamar.christina@arm.com>
+
+ * lib/target-supports.exp
+ (check_effective_target_arm_v8_3a_complex_neon_ok_nocache): Fix it.
+ (check_effective_target_vect_complex_add_byte
+ ,check_effective_target_vect_complex_add_int
+ ,check_effective_target_vect_complex_add_short
+ ,check_effective_target_vect_complex_add_long
+ ,check_effective_target_vect_complex_add_half
+ ,check_effective_target_vect_complex_add_float
+ ,check_effective_target_vect_complex_add_double): New.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-byte.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-int.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-long.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-short.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-byte.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-int.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-long.c: New test.
+ * gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-short.c: New test.
+ * gcc.dg/vect/complex/complex-add-pattern-template.c: New test.
+ * gcc.dg/vect/complex/complex-add-template.c: New test.
+ * gcc.dg/vect/complex/complex-operations-run.c: New test.
+ * gcc.dg/vect/complex/complex-operations.c: New test.
+ * gcc.dg/vect/complex/complex.exp: New test.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-add-double.c: New test.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-add-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-add-half-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-double.c: New test.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-half-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-complex-add-double.c: New test.
+ * gcc.dg/vect/complex/fast-math-complex-add-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-complex-add-half-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-complex-add-pattern-double.c: New test.
+ * gcc.dg/vect/complex/fast-math-complex-add-pattern-float.c: New test.
+ * gcc.dg/vect/complex/fast-math-complex-add-pattern-half-float.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-byte.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-int.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-long.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-short.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-byte.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-int.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-long.c: New test.
+ * gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-short.c: New test.
+
+2020-12-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/scanasm.exp (scan-symbol-section): Pass args to
+ dg-scan-symbol-section.
+ (scan-assembler-symbol-section): Likewise.
+ (dg-scan-symbol-section): Handle selector from orig_args.
+ Get patterns from orig_args.
+ (parse_section_of_symbols): Fix section_pattern.
+ Strip double quotes from section name.
+ * g++.dg/gomp/tls-5.C: Restrict ir, _ZGR2ir_ scans to tls_native.
+ * gcc.dg/20021029-1.c: Anchor ar symbol.
+ * gcc.dg/darwin-sections.c: Remove obsolete scans for _a, _b in
+ .data.
+
+2020-12-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/98022
+ * gfortran.dg/data_inquiry_ref.f90: New test.
+
+2020-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96685
+ * gcc.dg/tree-ssa/pr96685-1.c: New test.
+ * gcc.dg/tree-ssa/pr96685-2.c: New test.
+ * gcc.dg/tree-ssa/pr96685-3.c: New test.
+
+2020-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96272
+ * gcc.dg/tree-ssa/pr96272.c: New test.
+
+2020-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98183
+ * gcc.dg/gomp/pr98183.c: New test.
+ * gcc.dg/goacc/pr98183.c: New test.
+
+2020-12-11 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/concepts-conv3.C: New test.
+ * g++.dg/cpp2a/concepts-conv3a.C: New file.
+
+2020-12-11 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/modules/modules.exp: New.
+
+2020-12-11 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-vorr.c: Add vorr tests.
+
+2020-12-11 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/pmpyd.c: New test.
+ * gcc.target/arc/tmac-1.c: Update.
+
+2020-12-11 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/98219
+ * gcc.dg/guality/pr98219-1.c: New test.
+ * gcc.dg/guality/pr98219-2.c: Likewise.
+ * gcc.dg/torture/pr98219-1.c: Likewise.
+ * gcc.dg/torture/pr98219-2.c: Likewise.
+ * gcc.target/i386/uintr-2.c: Scan "add[lq] $8, %[er]sp".
+ (uword_t): New.
+ (foo): Add a uword_t argument.
+ (UINTR_hanlder): Likewise.
+ * gcc.target/i386/uintr-3.c: Scan "add[lq] $8, %[er]sp".
+ (uword_t): New.
+ (UINTR_hanlder): Add a uword_t argument.
+ * gcc.target/i386/uintr-4.c (uword_t): New.
+ (UINTR_hanlder): Add a uword_t argument.
+ * gcc.target/i386/uintr-5.c (uword_t): New.
+ (UINTR_hanlder): Add a uword_t argument.
+
+2020-12-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/78173
+ * g++.dg/cpp2a/concepts-pr78173.C: New test.
+
+2020-12-11 Andrea Corallo <andrea.corallo@arm.com>
+
+ * lib/target-supports.exp (check_effective_target_arm_softfloat):
+ Improve documentation.
+
+2020-12-11 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/lob2.c: Use '-march=armv8.1-m.main+fp'.
+ * gcc.target/arm/lob3.c: Skip with '-mfloat-abi=hard'.
+ * gcc.target/arm/lob4.c: Likewise.
+ * gcc.target/arm/lob5.c: Use '-march=armv8.1-m.main+fp'.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/98244
+ * gcc.dg/vect/vect-live-6.c: Require vect_condition.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/98242
+ * gcc.dg/vect/bb-slp-subgroups-3.c: Require vect_int_mult.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/98240
+ * gcc.dg/vect/pr97678.c: Require vect_int_mult and
+ vect_pack_trunc.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/98239
+ * gcc.dg/vect/bb-slp-69.c: Require vect_condition.
+
+2020-12-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98229
+ * gcc.c-torture/compile/pr98229.c: New test.
+
+2020-12-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98235
+ * gcc.dg/torture/pr98235.c: New testcase.
+
+2020-12-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98190
+ * gcc.dg/pr98190.c: New test.
+
+2020-12-11 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/aarch64/sve/pr97092.c: New test.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98212
+ * gcc.dg/predict-8.c: Adjust expected probability.
+
+2020-12-10 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/modular6.adb: New test.
+
+2020-12-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/91506
+ * g++.dg/init/array60.C: New test.
+
+2020-12-10 Dennis Zhang <denzha01@e124712.cambridge.arm.com>
+
+ * gcc.target/arm/simd/mve-vsub_1.c: Fix typo.
+ Remove needless dg-additional-options.
+
+2020-12-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/68451
+ * g++.dg/cpp0x/friend6.C: New test.
+
+2020-12-10 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-vand.c: New test.
+
+2020-12-10 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/98069
+ * gcc.dg/vect/pr98069.c: New file.
+
+2020-12-10 Joel Hutton <joel.hutton@arm.com>
+
+ * gcc.dg/vect/pr97929.c: New test.
+
+2020-12-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98211
+ * gcc.dg/pr98211.c: New testcase.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/98212
+ * gcc.target/i386/pr98212.c: New test.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98169
+ * gcc.target/i386/pr98169.c: New test.
+
+2020-12-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/98205
+ * c-c++-common/gomp/doacross-4.c: New test.
+
+2020-12-10 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-div-1.c: Expect the load to be
+ vectorized.
+
+2020-12-10 Nikhil Benesch <nikhil.benesch@gmail.com>
+
+ * gcc.misc-tests/godump-1.c: Add test case.
+
+2020-12-10 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (go-gc-tests): Recognize errorcheckdir -n,
+ for bug345.go.
+
+2020-12-09 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (errchk): Rewrite regexp quoting to use
+ curly braces, making it much simpler.
+
+2020-12-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98213
+ * g++.dg/pr98213.C: New testcase.
+
+2020-12-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97517
+ * g++.dg/diagnostic/nullptr.C: New test.
+
+2020-12-09 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98182
+ * gcc.dg/tree-ssa/if-to-switch-1.c: Add case-values-threshold in
+ order to fix them for aarch64.
+ * gcc.dg/tree-ssa/if-to-switch-10.c: Likewise.
+
+2020-12-09 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/zvector/autovec-double-signaling-eq.c: Build
+ with exceptions.
+ * gcc.target/s390/zvector/autovec-float-signaling-eq.c:
+ Likewise.
+
+2020-12-09 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-c++-common/gomp/allocate-5.c: New test.
+
+2020-12-09 Richard Biener <rguenther@suse.de>
+
+ PR c/98200
+ * gcc.dg/gimplefe-error-8.c: New testcase.
+
+2020-12-09 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/reduction4.f90: Update scan-trees, add
+ lost testcase; move test with FE error to ...
+ * gfortran.dg/gomp/reduction5.f90: ... here.
+
+2020-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98199
+ * gcc.c-torture/compile/pr98199.c: New test.
+
+2020-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98193
+ * g++.dg/cpp2a/bit-cast7.C: New test.
+
+2020-12-09 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/concepts-nodiscard1.C: Remove xfail.
+
+2020-12-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/59238
+ * g++.dg/cpp0x/new4.C: New test.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/98191
+ * gcc.dg/torture/pr98191.c: Add dg-additional-options with
+ -w -Wno-psabi.
+
+2020-12-08 Marek Polacek <polacek@redhat.com>
+
+ PR c++/98103
+ * g++.dg/ubsan/vptr-18.C: New test.
+
+2020-12-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/96299
+ * g++.dg/cpp2a/spaceship-synth-neg2.C: Move error.
+ * g++.dg/cpp2a/spaceship-p1186.C: New test.
+
+2020-12-08 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98182
+ * gcc.dg/tree-ssa/if-to-switch-10.c: New test.
+ * gcc.dg/tree-ssa/pr98182.c: New test.
+
+2020-12-08 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/reduction4.f90: Update; move FE some tests to ...
+ * gfortran.dg/gomp/reduction6.f90: ... this new test and ...
+ * gfortran.dg/gomp/reduction7.f90: ... this new test.
+ * gfortran.dg/gomp/reduction5.f90: Add dg-error.
+ * gfortran.dg/gomp/scan-1.f90: New test.
+ * gfortran.dg/gomp/scan-2.f90: New test.
+ * gfortran.dg/gomp/scan-3.f90: New test.
+ * gfortran.dg/gomp/scan-4.f90: New test.
+ * gfortran.dg/gomp/scan-5.f90: New test.
+ * gfortran.dg/gomp/scan-6.f90: New test.
+ * gfortran.dg/gomp/scan-7.f90: New test.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/94440
+ * gcc.target/i386/pr94440-1.c: New file.
+ * gcc.target/i386/pr94440-2.c: New file.
+
+2020-12-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.target/i386/avx512vpopcntdq-pr97770-2.c: Require
+ avx512vpopcntdq support.
+ * gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c: Require
+ avx512vpopcntdq, avx512vl support.
+
+2020-12-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.target/i386/pr98100.c: Require ifunc support.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/95900
+ * gcc.dg/vect/bb-slp-pr95866.c: Require sse2 for the
+ BIT_FIELD_REF match.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/avx512dq-vandnpd-2.c (CALC): Use union
+ to avoid aliasing violations.
+ * gcc.target/i386/avx512dq-vandnps-2.c (CALC): Likewise.
+ * gcc.target/i386/avx512dq-vandpd-2.c (CALC): Likewise.
+ * gcc.target/i386/avx512dq-vandps-2.c (CALC): Likewise.
+ * gcc.target/i386/avx512dq-vorpd-2.c (CALC): Likewise.
+ * gcc.target/i386/avx512dq-vorps-2.c (CALC): Likewise.
+ * gcc.target/i386/avx512dq-vxorpd-2.c (CALC): Likewise.
+ * gcc.target/i386/avx512dq-vxorps-2.c (CALC): Likewise.
+
+2020-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98187
+ * c-c++-common/gomp/pr98187.c: New test.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98191
+ * gcc.dg/torture/pr98191.c: New testcase.
+
+2020-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97559
+ * gcc.dg/torture/pr97559-1.c: New testcase.
+ * gcc.dg/torture/pr97559-2.c: Likewise.
+
+2020-12-08 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/97872
+ * gcc.target/arm/pr97872.c: New test.
+
+2020-12-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/96470
+ * gnat.dg/opt39.adb: Add dg-additional-options for PowerPC.
+
+2020-12-07 Martin Uecker <muecker@gwdg.de>
+
+ PR c/97981
+ * gcc.dg/pr97981.c: New test.
+ * gcc.dg/pr60195.c: Adapt test.
+
+2020-12-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98147
+ * gcc.dg/pr98147.c: New test.
+
+2020-12-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/98043
+ * g++.dg/cpp0x/enum41.C: New test.
+
+2020-12-07 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (errchk): Don't backslash quote parentheses
+ that are already backslash quoted.
+
+2020-12-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/98126
+ * g++.dg/warn/Wsequence-point-4.C: New test.
+
+2020-12-07 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98116
+ * g++.dg/template/pr98116.C: Remove dg-ice.
+ * g++.dg/template/pr98116-2.C: New.
+
+2020-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98113
+ * gcc.dg/vect/bb-slp-70.c: New testcase.
+
+2020-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98117
+ * gcc.dg/torture/pr98117.c: New testcase.
+
+2020-12-07 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/s390.exp: New target check s390_zarch.
+ * gcc.target/s390/stack-clash-1.c: Use s390_zarch instead of lp64.
+ * gcc.target/s390/stack-clash-2.c: Likewise.
+ * gcc.target/s390/stack-clash-3.c: Likewise.
+ * gcc.target/s390/stack-clash-5.c: New test.
+
+2020-12-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98137
+ * gcc.dg/vect/bb-slp-pr98137.c: New testcase.
+
+2020-12-06 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/pr98161.c: New test.
+
+2020-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96232
+ * gcc.dg/tree-ssa/pr96232-2.c: New test.
+ * gcc.dg/tree-ssa/pr88676-2.c: Check phiopt2 dump rather than phiopt1.
+
+2020-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96232
+ * gcc.dg/tree-ssa/pr96232-1.c: New test.
+
+2020-12-06 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR testsuite/98156
+ * gfortran.dg/coarray/alloc_comp_1.f90: Upper cobound is
+ determined by num_images(), not this_image().
+
+2020-12-06 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/signbit-1.c: Reinstate lp64 condition.
+ * gcc.target/powerpc/signbit-2.c: Match 32-bit output too.
+
+2020-12-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97093
+ * g++.dg/cpp2a/concepts-requires22.C: New test.
+
+2020-12-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97093
+ * g++.dg/concepts/pr94252.C: Verify we no longer issue a
+ spurious unsatisfaction note when diagnosing ill-formed
+ satisfaction.
+ * g++.dg/cpp2a/concepts-requires18.C: No longer expect a
+ spurious unsatisfaction diagnostic when evaluating the
+ nested-requirement subst<void&> of a requires-expression that
+ appears outside of a template.
+ * g++.dg/cpp2a/concepts-requires21.C: Verify we no longer issue
+ a spurious unsatisfaction note when evaluating a
+ nested-requirement of a requires-expression that appears outside
+ of a template.
+ * g++.dg/cpp2a/concepts-nonbool3.C: New test.
+ * g++.dg/cpp2a/concepts-pr97093.C: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ PR target/95294
+ * gcc.target/vax/cmpelim-eq-adddf.c: New test.
+ * gcc.target/vax/cmpelim-eq-addhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-addqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-addsf.c: New test.
+ * gcc.target/vax/cmpelim-eq-addsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-andhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-andqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-andsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-ashlsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-ashrsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-divdf.c: New test.
+ * gcc.target/vax/cmpelim-eq-divhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-divqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-divsf.c: New test.
+ * gcc.target/vax/cmpelim-eq-divsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-extendhisi.c: New test.
+ * gcc.target/vax/cmpelim-eq-extendqisi.c: New test.
+ * gcc.target/vax/cmpelim-eq-extvsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-extzvsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-fixdfhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-fixdfqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-fixdfsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-fixsfhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-fixsfqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-fixsfsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-floatsisf.c: New test.
+ * gcc.target/vax/cmpelim-eq-insvsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-iorhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-iorqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-iorsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-mova.c: New test.
+ * gcc.target/vax/cmpelim-eq-movdf.c: New test.
+ * gcc.target/vax/cmpelim-eq-movhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-movqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-movsf.c: New test.
+ * gcc.target/vax/cmpelim-eq-movsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-muldf.c: New test.
+ * gcc.target/vax/cmpelim-eq-mulhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-mulqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-mulsf.c: New test.
+ * gcc.target/vax/cmpelim-eq-mulsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-nothi.c: New test.
+ * gcc.target/vax/cmpelim-eq-notqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-notsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-rotlsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-rotrsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-subdf.c: New test.
+ * gcc.target/vax/cmpelim-eq-subhi.c: New test.
+ * gcc.target/vax/cmpelim-eq-subqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-subsf.c: New test.
+ * gcc.target/vax/cmpelim-eq-subsi.c: New test.
+ * gcc.target/vax/cmpelim-eq-truncdfsf.c: New test.
+ * gcc.target/vax/cmpelim-eq-trunchiqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-truncsihi.c: New test.
+ * gcc.target/vax/cmpelim-eq-truncsiqi.c: New test.
+ * gcc.target/vax/cmpelim-eq-zextendhisi.c: New test.
+ * gcc.target/vax/cmpelim-eq-zextendqihi.c: New test.
+ * gcc.target/vax/cmpelim-eq-zextendqisi.c: New test.
+ * gcc.target/vax/cmpelim-le-adddf.c: New test.
+ * gcc.target/vax/cmpelim-le-addhi.c: New test.
+ * gcc.target/vax/cmpelim-le-addqi.c: New test.
+ * gcc.target/vax/cmpelim-le-addsf.c: New test.
+ * gcc.target/vax/cmpelim-le-addsi.c: New test.
+ * gcc.target/vax/cmpelim-le-andhi.c: New test.
+ * gcc.target/vax/cmpelim-le-andqi.c: New test.
+ * gcc.target/vax/cmpelim-le-andsi.c: New test.
+ * gcc.target/vax/cmpelim-le-ashlsi.c: New test.
+ * gcc.target/vax/cmpelim-le-ashrsi.c: New test.
+ * gcc.target/vax/cmpelim-le-divdf.c: New test.
+ * gcc.target/vax/cmpelim-le-divhi.c: New test.
+ * gcc.target/vax/cmpelim-le-divqi.c: New test.
+ * gcc.target/vax/cmpelim-le-divsf.c: New test.
+ * gcc.target/vax/cmpelim-le-divsi.c: New test.
+ * gcc.target/vax/cmpelim-le-extendhisi.c: New test.
+ * gcc.target/vax/cmpelim-le-extendqisi.c: New test.
+ * gcc.target/vax/cmpelim-le-extvsi.c: New test.
+ * gcc.target/vax/cmpelim-le-extzvsi.c: New test.
+ * gcc.target/vax/cmpelim-le-fixdfhi.c: New test.
+ * gcc.target/vax/cmpelim-le-fixdfqi.c: New test.
+ * gcc.target/vax/cmpelim-le-fixdfsi.c: New test.
+ * gcc.target/vax/cmpelim-le-fixsfhi.c: New test.
+ * gcc.target/vax/cmpelim-le-fixsfqi.c: New test.
+ * gcc.target/vax/cmpelim-le-fixsfsi.c: New test.
+ * gcc.target/vax/cmpelim-le-floatsisf.c: New test.
+ * gcc.target/vax/cmpelim-le-insvsi.c: New test.
+ * gcc.target/vax/cmpelim-le-iorhi.c: New test.
+ * gcc.target/vax/cmpelim-le-iorqi.c: New test.
+ * gcc.target/vax/cmpelim-le-iorsi.c: New test.
+ * gcc.target/vax/cmpelim-le-movdf.c: New test.
+ * gcc.target/vax/cmpelim-le-movhi.c: New test.
+ * gcc.target/vax/cmpelim-le-movqi.c: New test.
+ * gcc.target/vax/cmpelim-le-movsf.c: New test.
+ * gcc.target/vax/cmpelim-le-movsi.c: New test.
+ * gcc.target/vax/cmpelim-le-muldf.c: New test.
+ * gcc.target/vax/cmpelim-le-mulhi.c: New test.
+ * gcc.target/vax/cmpelim-le-mulqi.c: New test.
+ * gcc.target/vax/cmpelim-le-mulsf.c: New test.
+ * gcc.target/vax/cmpelim-le-mulsi.c: New test.
+ * gcc.target/vax/cmpelim-le-nothi.c: New test.
+ * gcc.target/vax/cmpelim-le-notqi.c: New test.
+ * gcc.target/vax/cmpelim-le-notsi.c: New test.
+ * gcc.target/vax/cmpelim-le-rotlsi.c: New test.
+ * gcc.target/vax/cmpelim-le-rotrsi.c: New test.
+ * gcc.target/vax/cmpelim-le-subdf.c: New test.
+ * gcc.target/vax/cmpelim-le-subhi.c: New test.
+ * gcc.target/vax/cmpelim-le-subqi.c: New test.
+ * gcc.target/vax/cmpelim-le-subsf.c: New test.
+ * gcc.target/vax/cmpelim-le-subsi.c: New test.
+ * gcc.target/vax/cmpelim-le-truncdfsf.c: New test.
+ * gcc.target/vax/cmpelim-le-xorhi.c: New test.
+ * gcc.target/vax/cmpelim-le-xorqi.c: New test.
+ * gcc.target/vax/cmpelim-le-xorsi.c: New test.
+ * gcc.target/vax/cmpelim-leu-subhi.c: New test.
+ * gcc.target/vax/cmpelim-leu-subqi.c: New test.
+ * gcc.target/vax/cmpelim-leu-subsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-adddf.c: New test.
+ * gcc.target/vax/cmpelim-lt-addhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-addqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-addsf.c: New test.
+ * gcc.target/vax/cmpelim-lt-addsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-andhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-andqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-andsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-ashlsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-ashrsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-divdf.c: New test.
+ * gcc.target/vax/cmpelim-lt-divhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-divqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-divsf.c: New test.
+ * gcc.target/vax/cmpelim-lt-divsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-extendhisi.c: New test.
+ * gcc.target/vax/cmpelim-lt-extendqisi.c: New test.
+ * gcc.target/vax/cmpelim-lt-extvsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-extzvsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-fixdfhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-fixdfqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-fixdfsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-fixsfhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-fixsfqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-fixsfsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-floatsisf.c: New test.
+ * gcc.target/vax/cmpelim-lt-insvsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-iorhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-iorqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-iorsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-movdf.c: New test.
+ * gcc.target/vax/cmpelim-lt-movhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-movqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-movsf.c: New test.
+ * gcc.target/vax/cmpelim-lt-movsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-muldf.c: New test.
+ * gcc.target/vax/cmpelim-lt-mulhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-mulqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-mulsf.c: New test.
+ * gcc.target/vax/cmpelim-lt-mulsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-nothi.c: New test.
+ * gcc.target/vax/cmpelim-lt-notqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-notsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-rotlsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-rotrsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-subdf.c: New test.
+ * gcc.target/vax/cmpelim-lt-subhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-subqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-subsf.c: New test.
+ * gcc.target/vax/cmpelim-lt-subsi.c: New test.
+ * gcc.target/vax/cmpelim-lt-truncdfsf.c: New test.
+ * gcc.target/vax/cmpelim-lt-xorhi.c: New test.
+ * gcc.target/vax/cmpelim-lt-xorqi.c: New test.
+ * gcc.target/vax/cmpelim-lt-xorsi.c: New test.
+ * gcc.target/vax/cmpelim-ltu-subhi.c: New test.
+ * gcc.target/vax/cmpelim-ltu-subqi.c: New test.
+ * gcc.target/vax/cmpelim-ltu-subsi.c: New test.
+ * gcc.target/vax/cmpelim-xx-addsi.c: New test.
+ * gcc.target/vax/cmpelim-xx-insvsi.c: New test.
+ * gcc.target/vax/cmpelim-xxu-subsi.c: New test.
+ * gcc.target/vax/peephole2-eq-andhi.c: New test.
+ * gcc.target/vax/peephole2-eq-andqi.c: New test.
+ * gcc.target/vax/peephole2-eq-andsi.c: New test.
+ * gcc.target/vax/peephole2-eq-cmpvsi.c: New test.
+ * gcc.target/vax/peephole2-eq-cmpzvsi.c: New test.
+ * gcc.target/vax/peephole2-eq-ctzhi-0.c: New test.
+ * gcc.target/vax/peephole2-eq-ctzhi-1.c: New test.
+ * gcc.target/vax/peephole2-eq-ctzqi-0.c: New test.
+ * gcc.target/vax/peephole2-eq-ctzqi-1.c: New test.
+ * gcc.target/vax/peephole2-eq-ctzsi-0.c: New test.
+ * gcc.target/vax/peephole2-eq-ctzsi-1.c: New test.
+ * gcc.target/vax/peephole2-eq-ffshi.c: New test.
+ * gcc.target/vax/peephole2-eq-ffsqi.c: New test.
+ * gcc.target/vax/peephole2-eq-ffssi.c: New test.
+ * gcc.target/vax/peephole2-le-andhi.c: New test.
+ * gcc.target/vax/peephole2-le-andqi.c: New test.
+ * gcc.target/vax/peephole2-le-andsi.c: New test.
+ * gcc.target/vax/peephole2-le-cmpvsi.c: New test.
+ * gcc.target/vax/peephole2-le-cmpzvsi.c: New test.
+ * gcc.target/vax/peephole2-leu-cmpvsi.c: New test.
+ * gcc.target/vax/peephole2-leu-cmpzvsi.c: New test.
+ * gcc.target/vax/peephole2-lt-andhi.c: New test.
+ * gcc.target/vax/peephole2-lt-andqi.c: New test.
+ * gcc.target/vax/peephole2-lt-andsi.c: New test.
+ * gcc.target/vax/peephole2-lt-cmpvsi.c: New test.
+ * gcc.target/vax/peephole2-lt-cmpzvsi.c: New test.
+ * gcc.target/vax/peephole2-ltu-cmpvsi.c: New test.
+ * gcc.target/vax/peephole2-ltu-cmpzvsi.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/movmem.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/cpymem.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/ctzhi.c: New test.
+ * gcc.target/vax/ctzqi.c: New test.
+ * gcc.target/vax/ffshi.c: New test.
+ * gcc.target/vax/ffsqi.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/ctzsi.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/bbcci.c: New test.
+ * gcc.target/vax/bbssi.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/ffssi.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.dg/loop-8.c: Exclude for `vax-*-*'.
+ * gcc.target/vax/compare-add-zero.c: New test.
+ * gcc.target/vax/compare-mov-zero.c: New test.
+
+2020-12-05 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/vax.exp: Use `gcc-dg-runtest' rather than
+ `dg-runtest'.
+ * gcc.target/vax/pr56875.c (dg-options): Make empty.
+ (a): Rewrite for calculations to make effect. Reformat.
+
+2020-12-05 Matt Thomas <matt@3am-software.com>
+ Maciej W. Rozycki <macro@linux-mips.org>
+
+ PR target/58901
+ * gcc.c-torture/compile/pr58901-0.c: New test.
+ * gcc.c-torture/compile/pr58901-1.c: New test.
+
+2020-12-05 Roman Zhuykov <zhroma@ispras.ru>
+
+ PR rtl-optimization/97421
+ * gcc.c-torture/execute/pr97421-1.c: New test.
+ * gcc.c-torture/execute/pr97421-2.c: New test.
+ * gcc.c-torture/execute/pr97421-3.c: New test.
+
+2020-12-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/98016
+ * gfortran.dg/pr98016.f90: New test.
+
+2020-12-05 Venkataramanan Kumar <Venkataramanan.Kumar@amd.com>
+ Sharavan Kumar <Shravan.Kumar@amd.com>
+
+ * gcc.target/i386/funcspec-56.inc: Handle new march.
+ * g++.target/i386/mv29.C: New file.
+
+2020-12-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98122
+ * g++.dg/cpp1y/constexpr-98122.C: New test.
+ * g++.dg/cpp2a/constexpr-98122.C: New test.
+
+2020-12-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/93083
+ * g++.dg/cpp2a/nontype-class40.C: New test.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98130
+ * g++.dg/opt/pr98130.C: New test.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/96226
+ * gcc.target/i386/pr96226.c: New test.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * g++.dg/cpp2a/bit-cast6.C: New test.
+
+2020-12-04 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98116
+ * g++.dg/template/pr98116.C: Enable robust checking.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98100
+ * gcc.target/i386/pr98100.c: New test.
+
+2020-12-04 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/98123
+ * gcc.dg/tree-ssa/if-to-switch-4.c: Add param to make the test
+ stable on all architectures.
+ * gcc.dg/tree-ssa/if-to-switch-6.c: Likewise.
+ * gcc.dg/tree-ssa/if-to-switch-8.c: Likewise.
+
+2020-12-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/pr98099.c: Compile only for dfp targets.
+
+2020-12-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt91.ads, gnat.dg/opt91.adb: New test.
+ * gnat.dg/opt91_pkg.ads, gnat.dg/opt91_pkg.adb: New helper.
+
+2020-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/80780
+ * g++.dg/cpp2a/srcloc1.C (quux): Use __PRETTY_FUNCTION__ instead of
+ function.
+ * g++.dg/cpp2a/srcloc2.C (quux): Likewise.
+ * g++.dg/cpp2a/srcloc15.C (S::S): Likewise.
+ (bar): Likewise. Adjust expected column.
+ * g++.dg/cpp2a/srcloc17.C (S::S): Likewise.
+ (bar): Likewise. Adjust expected column.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/concepts-nodiscard1.C: XFAIL.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * g++.dg/asan/asan_test.cc: Fix a bug.
+ * g++.dg/warn/delete-array-1.C: Add expected warning.
+ * g++.old-deja/g++.other/delete2.C: Add expected warning.
+ * g++.dg/warn/Wfree-nonheap-object-2.C: New test.
+ * g++.dg/warn/Wfree-nonheap-object.C: New test.
+ * g++.dg/warn/Wmismatched-new-delete.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc-2.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc.C: New test.
+ * gcc.dg/Wmismatched-dealloc.c: New test.
+ * gcc.dg/analyzer/malloc-1.c: Prune out expected warning.
+ * gcc.dg/attr-malloc.c: New test.
+ * gcc.dg/free-1.c: Adjust text of expected warning.
+ * gcc.dg/free-2.c: Same.
+ * gcc.dg/torture/pr71816.c: Prune out expected warning.
+ * gcc.dg/tree-ssa/pr19831-2.c: Add an expected warning.
+ * gcc.dg/Wfree-nonheap-object-2.c: New test.
+ * gcc.dg/Wfree-nonheap-object-3.c: New test.
+ * gcc.dg/Wfree-nonheap-object.c: New test.
+ * g++.dg/warn/Wfree-nonheap-object.s: New file.
+
+2020-12-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/95342
+ * gfortran.dg/pr95342.f90: New test.
+
+2020-12-03 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (go-gc-tests): Add -I. when building all
+ sources in a directory (errorcheckdir, compiledir, rundir,
+ rundircmpout).
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/98019
+ * g++.dg/cpp2a/concepts-nodiscard1.C: New test.
+
+2020-12-03 Uroš Bizjak <ubizjak@gmail.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98086
+ * gcc.target/i386/pr98086.c: New test.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98115
+ PR c++/98116
+ * g++.dg/template/pr98115.C: New.
+ * g++.dg/template/pr98116.C: New.
+
+2020-12-03 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/stack-clash-4.c: New test.
+
+2020-12-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/undef_1.c: New test.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/pr98099.c: New test.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/cpp2a/pr98082.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * g++.dg/cpp2a/bit-cast1.C: New test.
+ * g++.dg/cpp2a/bit-cast2.C: New test.
+ * g++.dg/cpp2a/bit-cast3.C: New test.
+ * g++.dg/cpp2a/bit-cast4.C: New test.
+ * g++.dg/cpp2a/bit-cast5.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp2a/consteval-defarg2.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98104
+ * g++.dg/warn/pr98104.C: New test.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-pr96906-1.c: New test.
+ * gcc.target/i386/pr96906-1.c: Add -mno-avx512f.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-vmovdqu16-1.c: Adjust testcase to
+ make sure only masked load instruction is generated.
+ * gcc.target/i386/avx512bw-vmovdqu8-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovapd-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovaps-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovdqa32-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovdqa64-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovapd-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovaps-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovdqa32-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovdqa64-1.c: Ditto.
+ * gcc.target/i386/pr97642-1.c: New test.
+ * gcc.target/i386/pr97642-2.c: New test.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/parse/defarg17.C: New test.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/consteval-defarg1.C: New test.
+
+2020-12-03 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/97770
+ * gcc.target/i386/avx512bitalg-pr97770-1.c: New test.
+ * gcc.target/i386/avx512vpopcntdq-pr97770-1.c: Likewise.
+ * gcc.target/i386/avx512vpopcntdq-pr97770-2.c: Likewise.
+ * gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c: Likewise.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * lib/options.exp (check_for_options_with_filter): Detect
+ unavailable compiler for the selected language, and bail out
+ as unsupported.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust expected warnings
+ to correctly reflect the maximum object size.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-11.c: Same.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-18.c: Same.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/builtin-constant-p-threading.c: New test.
+
+2020-12-03 Peter Bergner <bergner@linux.ibm.com>
+
+ PR c++/97947
+ * g++.target/powerpc/pr97947.C: New test.
+
+2020-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/80780
+ PR c++/93093
+ * g++.dg/cpp2a/srcloc15.C: New test.
+ * g++.dg/cpp2a/srcloc16.C: New test.
+ * g++.dg/cpp2a/srcloc17.C: New test.
+ * g++.dg/cpp2a/srcloc18.C: New test.
+
+2020-12-02 qing zhao <qinzhao@gcc.gnu.org>
+
+ PR rtl-optimization/97777
+ PR rtl-optimization/97777
+ * gcc.target/i386/pr97777.c: New test.
+
+2020-12-02 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/other/pr88187.C: Adjust expected error.
+ * g++.dg/cpp2a/class-deduction-abbrev1.C: New test.
+
+2020-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97975
+ * g++.dg/cpp1z/inline-var8.C: New test.
+
+2020-12-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97187
+ PR c++/97993
+ * g++.dg/eh/crash2.C: New test.
+ * g++.dg/template/crash132.C: New test.
+
+2020-12-02 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust expected warnings
+ to correctly reflect the maximum object size.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-11.c: Same.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-18.c: Same.
+
+2020-12-02 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/load-imm64-1.c: New test.
+ * gcc.target/s390/load-imm64-2.c: New test.
+
+2020-12-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * ada/acats/support/acats25.lst: Delete.
+ * ada/acats/support/acats26.lst: New file.
+ * ada/acats/support/fcndecl.ada: Minor tweak.
+ * ada/acats/support/impdef.a: Add commentary.
+ * ada/acats/support/impdefg.a (Negative_Zero return): Simplify.
+ * ada/acats/support/macro.dfs (TASK_STORAGE_SIZE): Bump.
+ * ada/acats/support/repbody.ada: Upgrade to ACATS 2.6.
+ * ada/acats/support/tctouch.ada: Likewise.
+ * ada/acats/tests/c3/c352001.a: New file.
+ * ada/acats/tests/c4/c433001.a: Correct error messages.
+ * ada/acats/tests/c4/c453001.a: New file.
+ * ada/acats/tests/c4/c45622a.ada: Delete.
+ * ada/acats/tests/c4/c45624a.ada: Likewise.
+ * ada/acats/tests/c4/c45624b.ada: Likewise.
+ * ada/acats/tests/c4/c460013.a: New file.
+ * ada/acats/tests/c4/c460014.a: Likewise.
+ * ada/acats/tests/c6/c620001.a: Likewise.
+ * ada/acats/tests/c6/c620002.a: Likewise.
+ * ada/acats/tests/c7/c761006.a: Redo Unchecked_Deallocation case.
+ * ada/acats/tests/c9/c96004a.ada: Adjust for Ada 2005.
+ * ada/acats/tests/c9/c96007a.ada: Likewise.
+ * ada/acats/tests/cb/cb41004.a: Adjust for AI95-0044.
+ * ada/acats/tests/cc/cc3016f.ada: Minor tweak.
+ * ada/acats/tests/cd/cd30011.a: New file.
+ * ada/acats/tests/cd/cd30012.a: Likewise.
+ * ada/acats/tests/cd/cd90001.a: Fix comparison.
+ * ada/acats/tests/cxa/cxa3004.a: New file.
+ * ada/acats/tests/cxa/cxa5013.a: Likewise.
+ * ada/acats/tests/cxa/cxac005.a: Adjust for return-by-reference.
+ * ada/acats/tests/cxb/cxb30061.am: New file.
+ * ada/acats/tests/cxf/cxf2001.a: Fix failure message.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR ipa/98075
+ * g++.dg/ipa/pr98075.C: New test.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+
+ PR middle-end/93195
+ * g++.dg/pr93195a.C: New test.
+ * g++.dg/pr93195b.C: Likewise.
+ * lib/target-supports.exp
+ (check_effective_target_o_flag_in_section): New proc.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98084
+ * gcc.dg/tree-ssa/pr98094.c: New test.
+
+2020-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97459
+ * gcc.target/i386/pr97282.c (foo): Use 123456 divisor instead of
+ 10.
+ * gcc.dg/pr97459-1.c (TESTS): Add tests for 10, 12 and
+ 6144.
+ * gcc.dg/pr97459-2.c (TESTS): Likewise.
+ * gcc.dg/pr97459-3.c: New test.
+ * gcc.dg/pr97459-4.c: New test.
+ * gcc.dg/pr97459-5.c: New test.
+ * gcc.dg/pr97459-6.c: New test.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR c/98087
+ * gcc.c-torture/compile/pr98087.c: New test.
+
+2020-12-02 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/98079
+ * gcc.target/i386/pr98079.c: New test.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/88702
+ * gcc.dg/tree-ssa/if-to-switch-9.c: New test.
+
+2020-12-02 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/98084
+ * gcc.dg/tree-ssa/pr98084.c: New test.
+
+2020-12-02 Jeff Law <law@redhat.com>
+
+ * gcc.target/h8300/add.c: New test.
+ * gcc.target/h8300/add-2.c: New test.
+ * gcc.target/h8300/add-3.c: New test.
+ * gcc.target/h8300/sub.c: New test.
+ * gcc.target/h8300/sub-2.c: New test.
+ * gcc.target/h8300/sub-3.c: New test.
+
+2020-12-02 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (errchk): Permit trailing */ on ERROR line.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+ Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * c-c++-common/attr-used.c: Check the 'R' flag.
+ * c-c++-common/attr-used-2.c: Likewise.
+ * c-c++-common/attr-used-3.c: New test.
+ * c-c++-common/attr-used-4.c: Likewise.
+ * gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
+ * gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
+ * lib/target-supports.exp
+ (check_effective_target_R_flag_in_section): New proc.
+
+2020-12-02 H.J. Lu <hjl.tools@gmail.com>
+
+ * gcc.target/i386/x86-needed-1.c: New test.
+ * gcc.target/i386/x86-needed-2.c: Likewise.
+ * gcc.target/i386/x86-needed-3.c: Likewise.
+
+2020-12-01 Eugene Rozenfeld <Eugene.Rozenfeld@microsoft.com>
+
+ * gcc.dg/pr96708-negative.c: New test.
+ * gcc.dg/pr96708-positive.c: New test.
+
+2020-12-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97595
+ * g++.dg/warn/Warray-bounds-14.C: New test.
+ * g++.dg/warn/Wstringop-overflow-6.C: New test.
+
+2020-12-01 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/pr96480.c: Disable jump table optimization
+
+2020-12-01 JeanHeyd Meneide <phdofthehouse@gmail.com>
+
+ * c-c++-common/cpp/wide-narrow-predef-macros.c: New test.
+
+2020-12-01 Jeff Law <law@redhat.com>
+
+ * gcc.dg/pr46309-2.c: Add -fno-bit-tests and -fno-jump-tables
+ to avoid compromising the test.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98072
+ * c-c++-common/gomp/depobj-2.c: New test.
+
+2020-12-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97373
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-25.c: New test.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ * g++.dg/tree-ssa/if-to-switch-1.C: Do not allow newlines
+ in .* pattern.
+ * gcc.dg/tree-ssa/if-to-switch-1.c: Likewise.
+ * gcc.dg/tree-ssa/if-to-switch-2.c: Likewise.
+ * gcc.dg/tree-ssa/if-to-switch-3.c: Likewise.
+ * gcc.dg/tree-ssa/if-to-switch-5.c: Likewise.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/98085
+ * g++.dg/tree-ssa/if-to-switch-1.C: Do not expect precise number
+ of BBs.
+ * gcc.dg/tree-ssa/if-to-switch-1.c: Likewise.
+ * gcc.dg/tree-ssa/if-to-switch-2.c: Likewise. Find better name
+ for the function.
+ * gcc.dg/tree-ssa/if-to-switch-3.c: Likewise. Find better name
+ for the function.
+ * gcc.dg/tree-ssa/if-to-switch-5.c: Likewise.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97954
+ * gcc.dg/pr97954.c: New test.
+
+2020-12-01 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * lib/hwasan-dg.exp (check_effective_target_hwaddress_exec): Fix
+ check for correct kernel version.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/14799
+ PR ipa/88702
+ * gcc.dg/tree-ssa/pr96480.c: Disable if-to-switch conversion.
+ * gcc.dg/tree-ssa/reassoc-32.c: Likewise.
+ * g++.dg/tree-ssa/if-to-switch-1.C: New test.
+ * gcc.dg/tree-ssa/if-to-switch-1.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-2.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-3.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-4.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-5.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-6.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-7.c: New test.
+ * gcc.dg/tree-ssa/if-to-switch-8.c: New test.
+
+2020-12-01 Marius Hillenbrand <mhillen@linux.ibm.com>
+
+ * gcc.target/s390/float_t-1.c: New test.
+ * gcc.target/s390/float_t-2.c: New test.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ * g++.dg/torture/pr93347.C: Reduce and remove LIT keywords.
+
+2020-12-01 Martin Liska <mliska@suse.cz>
+
+ PR ipa/98057
+ * g++.dg/ipa/pr98057.C: New test.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98063
+ * gcc.target/i386/pr98063.c: New test.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/debug/dwarf2/lang-cpp17.C: New test.
+ * g++.dg/debug/dwarf2/lang-cpp20.C: New test.
+
+2020-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/97989
+ * gcc.dg/cpp/pr97989-1.c: New test.
+ * gcc.dg/cpp/pr97989-2.c: New test.
+
+2020-11-30 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/plugin/analyzer_gil_plugin.c: New test.
+ * gcc.dg/plugin/gil-1.c: New test.
+ * gcc.dg/plugin/gil.h: New header.
+ * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new plugin
+ and test.
+
+2020-11-30 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * lib/profopt.exp: Unset testname_with_flags if create_gcov
+ fails.
+
+2020-11-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR rtl-optimization/98037
+ * gcc.target/aarch64/sve/acle/general/pr98037.c: New test.
+
+2020-11-30 Jeff Law <law@redhat.com>
+
+ * g++.dg/warn/Wnonnull5.C: Fix non-unique testnames.
+ * g++.dg/warn/Wplacement-new-size-8.C: Likewise.
+
+2020-11-30 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/98011
+ * gfortran.dg/goacc/sentinel-free-form.f95:
+ * gfortran.dg/goacc-gomp/fixed-1.f: New test.
+ * gfortran.dg/goacc-gomp/free-1.f90: New test.
+ * gfortran.dg/goacc/fixed-5.f: New test.
+
+2020-11-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98064
+ * g++.dg/vect/pr98064.cc: New testcase.
+
+2020-11-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/98048
+ * gcc.dg/vect/pr98048.c: New testcase.
+
+2020-11-30 Stam Markianos-Wright <stam.markianos-wright@arm.com>
+
+ * gcc.target/arm/pr91816.c: New test.
+
+2020-11-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/97459
+ * gcc.dg/pr97459-1.c: New test.
+ * gcc.dg/pr97459-2.c: New test.
+
+2020-11-29 Harald Anlauf <anlauf@gmx.de>
+
+ * gfortran.dg/pr98017.f90: New test.
+
+2020-11-29 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/92936
+ PR middle-end/92940
+ PR middle-end/89428
+ * c-c++-common/Wstringop-overflow-2.c: Adjust text of expected
+ informational notes.
+ * g++.dg/warn/Wstringop-overflow-3.C: Same.
+ * g++.dg/warn/Wplacement-new-size.C: Remove a test for a no longer
+ issued warning.
+ * gcc.dg/Warray-bounds-43.c: Removed unused declarations.
+ * gcc.dg/Wstringop-overflow-11.c: Remove xfails.
+ * gcc.dg/Wstringop-overflow-12.c: Same.
+ * gcc.dg/Wstringop-overflow-17.c: Adjust text of expected messages.
+ * gcc.dg/Wstringop-overflow-27.c: Same. Remove xfails.
+ * gcc.dg/Wstringop-overflow-28.c: Adjust text of expected messages.
+ * gcc.dg/Wstringop-overflow-29.c: Same.
+ * gcc.dg/Wstringop-overflow-37.c: Same.
+ * gcc.dg/Wstringop-overflow-46.c: Same.
+ * gcc.dg/Wstringop-overflow-47.c: Same.
+ * gcc.dg/Wstringop-overflow-54.c: Same.
+ * gcc.dg/warn-strnlen-no-nul.c: Add expected warning.
+ * gcc.dg/Wstringop-overflow-7.c: New test.
+ * gcc.dg/Wstringop-overflow-58.c: New test.
+ * gcc.dg/Wstringop-overflow-59.c: New test.
+ * gcc.dg/Wstringop-overflow-60.c: New test.
+ * gcc.dg/Wstringop-overflow-61.c: New test.
+ * gcc.dg/Wstringop-overflow-62.c: New test.
+ * gcc.dg/Wstringop-overflow-63.c: New test.
+ * gcc.dg/Wstringop-overflow-64.c: New test.
+
+2020-11-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/overflow-6.c: New test.
+
+2020-11-27 Joseph Myers <joseph@codesourcery.com>
+
+ PR preprocessor/97602
+ * gcc.dg/cpp/line9.c, gcc.dg/cpp/line10.c: New tests.
+
+2020-11-27 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * gdc.dg/intrinsics.d: Adjust patterns in scan-tree-dump.
+
+2020-11-27 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/98036
+ * gcc.target/i386/fma4-256-maccXX.c (check_maccps):
+ Remove unnecessary postfix increment on a returned variable.
+ (check_maccpd): Ditto.
+ * gcc.target/i386/fma4-256-msubXX.c (check_msubps): Ditto.
+ (check_msubpd): Ditto.
+ * gcc.target/i386/fma4-256-nmaccXX.c (check_nmaccps): Ditto.
+ (check_nmaccpd): Ditto.
+ * gcc.target/i386/fma4-256-nmsubXX.c (check_nmsubps): Ditto.
+ (check_nmsubpd): Ditto.
+ * gcc.target/i386/fma4-maccXX.c (check_maccps): Ditto.
+ (check_maccpd): Ditto.
+ (check_maccss): Ditto.
+ (check_maccsd): Ditto.
+ * gcc.target/i386/fma4-msubXX.c (check_msubps): Ditto.
+ (check_msubpd): Ditto.
+ (check_msubss): Ditto.
+ (check_msubsd): Ditto.
+ * gcc.target/i386/fma4-nmaccXX.c (check_nmaccps): Ditto.
+ (check_nmaccpd): Ditto.
+ (check_nmaccss): Ditto.
+ (check_nmaccsd): Ditto.
+ * gcc.target/i386/fma4-nmsubXX.c (check_nmsubps): Ditto.
+ (check_nmsubpd): Ditto.
+ (check_nmsubss): Ditto.
+ (check_nmsubsd): Ditto.
+ * gcc.target/i386/xop-haddX.c (check_sbyte2word): Add missing return.
+ (check_sbyte2dword):
+ Remove unnecessary postfix increment on a returned value.
+ (check_sbyte2qword): Ditto.
+ (check_sword2dword): Add missing return.
+ (check_sword2qword):
+ Remove unnecessary postfix increment on a returned value.
+ (check_dword2qword): Add missing return.
+ * gcc.target/i386/xop-hadduX.c (check_byte2word): Add missing return.
+ (check_byte2dword):
+ Remove unnecessary postfix increment on a returned value.
+ (check_byte2qword): Ditto.
+ (check_word2dword): Add missing return.
+ (check_word2qword):
+ Remove unnecessary postfix increment on a returned value.
+ (check_word2qword): Add missing return.
+ * gcc.target/i386/xop-hsubX.c (check_sbyte2word): Add missing return.
+ (check_sword2dword): Ditto.
+ (check_sword2qword): Ditto.
+
+2020-11-27 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/kernels-decompose-ice-1.c: Adjust.
+ * c-c++-common/goacc/kernels-decompose-ice-2.c: Likewise.
+
+2020-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/requires-4.f90: Fix typo in '!$omp' clause.
+
+2020-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/requires-4.f90: Fix '!$omp' syntax.
+
+2020-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/88101
+ * g++.dg/torture/builtin-clear-padding-3.C: New test.
+
+2020-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR c/97880
+ * gcc.dg/goacc/tile-1.c: New test.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97997
+ * gcc.dg/tree-ssa/pr97997-1.c: New test.
+ * gcc.dg/tree-ssa/pr97997-2.c: New test.
+
+2020-11-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97953
+ * gcc.dg/pr97953.c: New testcase.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97979
+ * gcc.dg/pr97979.c: New test.
+ * gcc.c-torture/compile/pr97979.c: New test.
+
+2020-11-26 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/98002
+ * gcc.dg/strncmp-2.c: Call mprotect again before free.
+
+2020-11-26 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/cache-3-1.c: New.
+ * c-c++-common/goacc/cache-3-2.c: Likewise.
+ * c-c++-common/goacc/data-clause-1.c: Likewise.
+ * c-c++-common/goacc/data-clause-2.c: Likewise.
+ * c-c++-common/gomp/map-1.c: Adjust.
+ * c-c++-common/gomp/map-2.c: Likewise.
+ * g++.dg/goacc/cache-3-1.C: New.
+ * g++.dg/goacc/cache-3-2.C: Likewise.
+ * g++.dg/goacc/data-clause-1.C: Likewise.
+ * g++.dg/goacc/data-clause-2.C: Likewise.
+ * g++.dg/gomp/map-1.C: Adjust.
+ * g++.dg/gomp/map-2.C: Likewise.
+
+2020-11-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/97873
+ * gcc.target/i386/pr97873-3.c: New test.
+
+2020-11-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/multfixed.adb: Robustify.
+
+2020-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/96906
+ * gcc.target/i386/pr96906-1.c: New test.
+
+2020-11-26 Martin Uecker <muecker@gwdg.de>
+
+ PR c/65455
+ PR c/92935
+ * gcc.dg/typeof-2.c: Adapt test.
+
+2020-11-26 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/nextafter-1.c: Omit prototypes if _NEXT_AFTER_2 defined.
+ * gcc.dg/nextafter-2.c: Define _NEXT_AFTER_2.
+ * gcc.dg/profile-info-section.c: Skip on AIX.
+
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR bootstrap/94982
+ * c-c++-common/patchable_function_entry-error-3.c: Adjust text
+ of expected warning.
+
+2020-11-25 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/lto/modref-3_0.c: New test.
+ * gcc.dg/lto/modref-3_1.c: New test.
+ * gcc.dg/lto/modref-4_0.c: New test.
+ * gcc.dg/lto/modref-4_1.c: New test.
+ * gcc.dg/tree-ssa/modref-5.c: New test.
+
+2020-11-25 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/85796
+ * gfortran.dg/pr85796.f90: New test.
+
+2020-11-25 Thomas Schwinge <thomas@codesourcery.com>
+
+ * g++.dg/gomp/map-1.C: New.
+ * g++.dg/gomp/map-2.C: Likewise.
+ * c-c++-common/gomp/map-1.c: Adjust.
+ * c-c++-common/gomp/map-2.c: Likewise.
+
+2020-11-25 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/cache-1.c: Update.
+ * c-c++-common/goacc/cache-2.c: Likewise.
+ * g++.dg/goacc/cache-1.C: New.
+ * g++.dg/goacc/cache-2.C: Likewise.
+
+2020-11-25 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97956
+ * gcc.dg/memchr-3.c: New test.
+
+2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * c-c++-common/ubsan/sanitize-recover-7.c: Update error message format.
+ * lib/asan-dg.exp (asan_link_flags): Implement as a helper
+ function asan_link_flags_1 which asan_link_flags and
+ hwasan_link_flags use.
+ (asan_link_flags_1): Parametrised version of asan_link_flags.
+ * c-c++-common/hwasan/aligned-alloc.c: New test.
+ * c-c++-common/hwasan/alloca-array-accessible.c: New test.
+ * c-c++-common/hwasan/alloca-base-init.c: New test.
+ * c-c++-common/hwasan/alloca-gets-different-tag.c: New test.
+ * c-c++-common/hwasan/alloca-outside-caught.c: New test.
+ * c-c++-common/hwasan/arguments-1.c: New test.
+ * c-c++-common/hwasan/arguments-2.c: New test.
+ * c-c++-common/hwasan/arguments-3.c: New test.
+ * c-c++-common/hwasan/arguments.c: New test.
+ * c-c++-common/hwasan/asan-pr63316.c: New test.
+ * c-c++-common/hwasan/asan-pr70541.c: New test.
+ * c-c++-common/hwasan/asan-pr78106.c: New test.
+ * c-c++-common/hwasan/asan-pr79944.c: New test.
+ * c-c++-common/hwasan/asan-rlimit-mmap-test-1.c: New test.
+ * c-c++-common/hwasan/bitfield-1.c: New test.
+ * c-c++-common/hwasan/bitfield-2.c: New test.
+ * c-c++-common/hwasan/builtin-special-handling.c: New test.
+ * c-c++-common/hwasan/check-interface.c: New test.
+ * c-c++-common/hwasan/halt_on_error-1.c: New test.
+ * c-c++-common/hwasan/handles-poly_int-marked-vars.c: New test.
+ * c-c++-common/hwasan/heap-overflow.c: New test.
+ * c-c++-common/hwasan/hwasan-poison-optimisation.c: New test.
+ * c-c++-common/hwasan/hwasan-thread-access-parent.c: New test.
+ * c-c++-common/hwasan/hwasan-thread-basic-failure.c: New test.
+ * c-c++-common/hwasan/hwasan-thread-clears-stack.c: New test.
+ * c-c++-common/hwasan/hwasan-thread-success.c: New test.
+ * c-c++-common/hwasan/kernel-defaults.c: New test.
+ * c-c++-common/hwasan/large-aligned-0.c: New test.
+ * c-c++-common/hwasan/large-aligned-1.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-0.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-1.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-2.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-3.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-4.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-5.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-6.c: New test.
+ * c-c++-common/hwasan/large-aligned-untagging-7.c: New test.
+ * c-c++-common/hwasan/macro-definition.c: New test.
+ * c-c++-common/hwasan/no-sanitize-attribute.c: New test.
+ * c-c++-common/hwasan/param-instrument-mem-intrinsics.c: New test.
+ * c-c++-common/hwasan/param-instrument-reads-and-writes.c: New test.
+ * c-c++-common/hwasan/param-instrument-reads.c: New test.
+ * c-c++-common/hwasan/param-instrument-writes.c: New test.
+ * c-c++-common/hwasan/random-frame-tag.c: New test.
+ * c-c++-common/hwasan/sanity-check-pure-c.c: New test.
+ * c-c++-common/hwasan/setjmp-longjmp-0.c: New test.
+ * c-c++-common/hwasan/setjmp-longjmp-1.c: New test.
+ * c-c++-common/hwasan/stack-tagging-basic-0.c: New test.
+ * c-c++-common/hwasan/stack-tagging-basic-1.c: New test.
+ * c-c++-common/hwasan/stack-tagging-disable.c: New test.
+ * c-c++-common/hwasan/unprotected-allocas-0.c: New test.
+ * c-c++-common/hwasan/unprotected-allocas-1.c: New test.
+ * c-c++-common/hwasan/use-after-free.c: New test.
+ * c-c++-common/hwasan/vararray-outside-caught.c: New test.
+ * c-c++-common/hwasan/vararray-stack-restore-correct.c: New test.
+ * c-c++-common/hwasan/very-large-objects.c: New test.
+ * g++.dg/hwasan/hwasan.exp: New test.
+ * g++.dg/hwasan/rvo-handled.C: New test.
+ * gcc.dg/hwasan/hwasan.exp: New test.
+ * gcc.dg/hwasan/nested-functions-0.c: New test.
+ * gcc.dg/hwasan/nested-functions-1.c: New test.
+ * gcc.dg/hwasan/nested-functions-2.c: New test.
+ * lib/hwasan-dg.exp: New file.
+
+2020-11-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/95862
+ * gcc.dg/builtin-artih-overflow-5.c: Renamed to ...
+ * gcc.dg/builtin-arith-overflow-5.c: ... this.
+
+2020-11-25 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/asm/abs_f16.c (abs_f16_x_untied): Expect
+ a MOVPRFX instruction.
+ * gcc.target/aarch64/sve/acle/asm/abs_f32.c (abs_f32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/abs_f64.c (abs_f64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/abs_s16.c (abs_s16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/abs_s32.c (abs_s32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/abs_s64.c (abs_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/abs_s8.c (abs_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cls_s16.c (cls_s16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cls_s32.c (cls_s32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cls_s64.c (cls_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cls_s8.c (cls_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_s16.c (clz_s16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_s32.c (clz_s32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_s64.c (clz_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_s8.c (clz_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_u16.c (clz_u16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_u32.c (clz_u32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_u64.c (clz_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/clz_u8.c (clz_u8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_s16.c (cnot_s16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_s32.c (cnot_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_s64.c (cnot_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_s8.c (cnot_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_u16.c (cnot_u16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_u32.c (cnot_u32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_u64.c (cnot_u64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnot_u8.c (cnot_u8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_bf16.c (cnt_bf16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_f16.c (cnt_f16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_f32.c (cnt_f32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_f64.c (cnt_f64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_s16.c (cnt_s16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_s32.c (cnt_s32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_s64.c (cnt_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_s8.c (cnt_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_u16.c (cnt_u16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_u32.c (cnt_u32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_u64.c (cnt_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cnt_u8.c (cnt_u8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_bf16.c (cvt_bf16_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_f16.c (cvt_f16_f32_x_untied)
+ (cvt_f16_f64_x_untied, cvt_f16_s16_x_untied, cvt_f16_s32_x_untied)
+ (cvt_f16_s64_x_untied, cvt_f16_u16_x_untied, cvt_f16_u32_x_untied)
+ (cvt_f16_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_f32.c (cvt_f32_f16_x_untied)
+ (cvt_f32_f64_x_untied, cvt_f32_s16_x_untied, cvt_f32_s32_x_untied)
+ (cvt_f32_s64_x_untied, cvt_f32_u16_x_untied, cvt_f32_u32_x_untied)
+ (cvt_f32_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_f64.c (cvt_f64_f16_x_untied)
+ (cvt_f64_f32_x_untied, cvt_f64_s16_x_untied, cvt_f64_s32_x_untied)
+ (cvt_f64_s64_x_untied, cvt_f64_u16_x_untied, cvt_f64_u32_x_untied)
+ (cvt_f64_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_s16.c (cvt_s16_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_s32.c (cvt_s32_f16_x_untied)
+ (cvt_s32_f32_x_untied, cvt_s32_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_s64.c (cvt_s64_f16_x_untied)
+ (cvt_s64_f32_x_untied, cvt_s64_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_u16.c (cvt_u16_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_u32.c (cvt_u32_f16_x_untied)
+ (cvt_u32_f32_x_untied, cvt_u32_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/cvt_u64.c (cvt_u64_f16_x_untied)
+ (cvt_u64_f32_x_untied, cvt_u64_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/extb_s16.c (extb_s16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/extb_s32.c (extb_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/extb_s64.c (extb_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/exth_s32.c (exth_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/exth_s64.c (exth_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/extw_s64.c (extw_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_f16.c (neg_f16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_f32.c (neg_f32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_f64.c (neg_f64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_s16.c (neg_s16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_s32.c (neg_s32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_s64.c (neg_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/neg_s8.c (neg_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_s16.c (not_s16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_s32.c (not_s32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_s64.c (not_s64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_s8.c (not_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_u16.c (not_u16_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_u32.c (not_u32_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_u64.c (not_u64_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/not_u8.c (not_u8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_s16.c (rbit_s16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_s32.c (rbit_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_s64.c (rbit_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_s8.c (rbit_s8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_u16.c (rbit_u16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_u32.c (rbit_u32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_u64.c (rbit_u64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rbit_u8.c (rbit_u8_x_untied): Ditto.
+ * gcc.target/aarch64/sve/acle/asm/recpx_f16.c (recpx_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/recpx_f32.c (recpx_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/recpx_f64.c (recpx_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revb_s16.c (revb_s16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revb_s32.c (revb_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revb_s64.c (revb_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revb_u16.c (revb_u16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revb_u32.c (revb_u32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revb_u64.c (revb_u64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revh_s32.c (revh_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revh_s64.c (revh_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revh_u32.c (revh_u32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revh_u64.c (revh_u64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revw_s64.c (revw_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/revw_u64.c (revw_u64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rinta_f16.c (rinta_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rinta_f32.c (rinta_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rinta_f64.c (rinta_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rinti_f16.c (rinti_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rinti_f32.c (rinti_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rinti_f64.c (rinti_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintm_f16.c (rintm_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintm_f32.c (rintm_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintm_f64.c (rintm_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintn_f16.c (rintn_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintn_f32.c (rintn_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintn_f64.c (rintn_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintp_f16.c (rintp_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintp_f32.c (rintp_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintp_f64.c (rintp_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintx_f16.c (rintx_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintx_f32.c (rintx_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintx_f64.c (rintx_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintz_f16.c (rintz_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintz_f32.c (rintz_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/rintz_f64.c (rintz_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/sqrt_f16.c (sqrt_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/sqrt_f32.c (sqrt_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve/acle/asm/sqrt_f64.c (sqrt_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/cvtx_f32.c (cvtx_f32_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/logb_f16.c (logb_f16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/logb_f32.c (logb_f32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/logb_f64.c (logb_f64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qabs_s16.c (qabs_s16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qabs_s32.c (qabs_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qabs_s64.c (qabs_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qabs_s8.c (qabs_s8_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qneg_s16.c (qneg_s16_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qneg_s32.c (qneg_s32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qneg_s64.c (qneg_s64_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/qneg_s8.c (qneg_s8_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/recpe_u32.c (recpe_u32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/rsqrte_u32.c (rsqrte_u32_x_untied):
+ Ditto.
+ * gcc.target/aarch64/sve2/acle/asm/cvtlt_f32.c
+ (cvtlt_f32_f16_x_untied): Expect a MOV instruction.
+ * gcc.target/aarch64/sve2/acle/asm/cvtlt_f64.c
+ (cvtlt_f64_f32_x_untied): Likewise.
+
+2020-11-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/95862
+ * gcc.dg/builtin-artih-overflow-5.c: New test.
+
+2020-11-25 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/97579
+ * gcc.dg/pr97579.c: New testcase.
+
+2020-11-25 Stam Markianos-Wright <stam.markianos-wright@arm.com>
+
+ PR target/91816
+ * gcc.target/arm/pr91816.c: New test.
+
+2020-11-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/97943
+ * c-c++-common/builtin-clear-padding-2.c: New test.
+ * c-c++-common/builtin-clear-padding-3.c: New test.
+ * g++.dg/ext/builtin-clear-padding-1.C: New test.
+ * gcc.dg/builtin-clear-padding-2.c: New test.
+
+2020-11-24 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/pr97955.c: New test.
+
+2020-11-24 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/Wstringop-overflow-47.c: Add a note.
+
+2020-11-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/97899
+ * g++.dg/cpp0x/initlist-template3.C: New test.
+
+2020-11-24 Martin Sebor <msebor@redhat.com>
+
+ * gfortran.dg/gomp/declare-target-4.f90: Adjust pattern to expect
+ an additional attribute and function return type.
+
+2020-11-24 Richard Earnshaw <rearnsha@arm.com>
+
+ * gcc.dg/pr97534.c: New test.
+
+2020-11-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/aapcs64/abitest.h (FUNC_VAL_CHECK): Use
+ noipa rather than noinline.
+ * gcc.target/aarch64/aapcs64/abitest-2.h (FUNC_VAL_CHECK): Likewise.
+
+2020-11-24 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/zvector/autovec-double-quiet-uneq.c: Expect
+ that "vx" is not emitted.
+ * gcc.target/s390/zvector/autovec-float-quiet-uneq.c: Likewise.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/97950
+ * gcc.target/i386/pr97950.c: New test.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97964
+ * gcc.dg/tree-ssa/pr97964.c: New test.
+
+2020-11-24 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/kernels-decompose-1.c: Avoid Tcl 8.5-specific
+ behavior.
+ * c-c++-common/goacc/kernels-decompose-2.c: Likewise.
+ * gfortran.dg/goacc/kernels-decompose-1.f95: Likewise.
+ * gfortran.dg/goacc/kernels-decompose-2.f95: Likewise.
+
+2020-11-24 Thomas Schwinge <thomas@codesourcery.com>
+
+ * lib/gcc-dg.exp (dg-optimized, dg-missed): Use 'saved-dg-warning'
+ instead of 'saved-dg-error'.
+
+2020-11-24 Thomas Schwinge <thomas@codesourcery.com>
+
+ * lib/gcc-dg.exp (dg-optimized, dg-missed): Fix 'process-message'
+ call.
+ * gcc.dg/vect/nodump-vect-opt-info-1.c: Demonstrate.
+ * gcc.dg/vect/nodump-vect-opt-info-2.c: Likewise.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97958
+ * c-c++-common/gomp/pr97958.c: New test.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/96929
+ * gcc.dg/tree-ssa/pr96929.c: New test.
+
+2020-11-24 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/pr23401.c: Update expected output.
+ * gcc.dg/tree-ssa/pr27810.c: Update expected output.
+ * gcc.dg/tree-ssa/slsr-8.c: Update expected output.
+
+2020-11-24 Kewen Lin <linkw@linux.ibm.com>
+
+ * gcc.dg/vect/slp-perm-1.c: Adjust for partial vectors.
+ * gcc.dg/vect/slp-perm-5.c: Likewise.
+ * gcc.dg/vect/slp-perm-6.c: Likewise.
+ * gcc.dg/vect/slp-perm-7.c: Likewise.
+
+2020-11-24 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR tree-optimization/97849
+ * gcc.dg/tree-ssa/pr97849.c: New test.
+
+2020-11-24 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/attr-access-5.c: New test.
+
+2020-11-23 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/95630
+ * gcc.dg/c11-compare-incomplete-1.c,
+ gcc.dg/c11-compare-incomplete-2.c,
+ gcc.dg/c99-compare-incomplete-1.c,
+ gcc.dg/c99-compare-incomplete-2.c: New tests.
+
+2020-11-23 Martin Jambor <mjambor@suse.cz>
+
+ * gfortran.dg/ipcp-array-2.f90: New test.
+
+2020-11-23 Nathan Sidwell <nathan@acm.org>
+
+ * lib/prune.exp (prune_gcc_output): Adjust include stack pruning
+ for modules.
+ (print_ices): Relax regexp.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * g++.target/msp430/data-attributes.C: Remove expected warnings for
+ "lower" attribute conflicts.
+ Adjust expected wording for "persistent" attribute misuse.
+ * gcc.target/msp430/data-attributes-2.c: Likewise.
+ * gcc.target/msp430/pr78818-auto-warn.c: Likewise.
+
+2020-11-23 Richard Biener <rguenther@suse.de>
+
+ * g++.dg/vect/simd-12.cc: New testcase.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.c-torture/execute/noinit-attribute.c: Moved to...
+ * c-c++-common/torture/attr-noinit-main.inc: ...here.
+ * lib/target-supports.exp (check_effective_target_persistent): New.
+ * c-c++-common/torture/attr-noinit-1.c: New test.
+ * c-c++-common/torture/attr-noinit-2.c: New test.
+ * c-c++-common/torture/attr-noinit-3.c: New test.
+ * c-c++-common/torture/attr-noinit-invalid.c: New test.
+ * c-c++-common/torture/attr-persistent-1.c: New test.
+ * c-c++-common/torture/attr-persistent-2.c: New test.
+ * c-c++-common/torture/attr-persistent-3.c: New test.
+ * c-c++-common/torture/attr-persistent-invalid.c: New test.
+ * c-c++-common/torture/attr-persistent-main.inc: New test.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/data-attributes-2.c: Adjust test.
+ * g++.target/msp430/data-attributes.C: New test.
+ * g++.target/msp430/msp430.exp: New test.
+
+2020-11-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.c-torture/execute/noinit-attribute.c: Don't override
+ optimization options set by torture test harness.
+ * lib/target-supports.exp (check_effective_target_noinit): Adjust
+ comment formatting.
+
+2020-11-23 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/cortex-m55-nodsp-flag-hard.c: Add -mthumb.
+ * gcc.target/arm/cortex-m55-nodsp-flag-softfp.c: Likewise.
+ * gcc.target/arm/cortex-m55-nodsp-nofp-flag-softfp.c: Likewise.
+ * gcc.target/arm/cortex-m55-nofp-flag-hard.c: Likewise.
+ * gcc.target/arm/cortex-m55-nofp-flag-softfp.c: Likewise.
+ * gcc.target/arm/cortex-m55-nofp-nomve-flag-softfp.c: Likewise.
+ * gcc.target/arm/cortex-m55-nomve-flag-hard.c: Likewise.
+ * gcc.target/arm/cortex-m55-nomve-flag-softfp.c: Likewise.
+ * gcc.target/arm/cortex-m55-nomve.fp-flag-hard.c: Likewise.
+ * gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c: Likewise.
+ * gcc.target/arm/mve/intrinsics/pr97327.c: Likewise.
+
+2020-11-23 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR c++/97904
+ * g++.dg/ext/sve-sizeless-1.C: Add more template tests.
+ * g++.dg/ext/sve-sizeless-2.C: Likewise.
+
+2020-11-22 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/97873
+ * gcc.target/i386/pr97873-2.c: New test.
+
+2020-11-22 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/97889
+ * gdc.dg/torture/pr97889.d: New test.
+
+2020-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/95853
+ * gcc.dg/pr95853.c: New test.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94695
+ * g++.dg/warn/Wrange-loop-construct2.C: New test.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97846
+ * g++.dg/cpp1y/constexpr-label.C: New test.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97881
+ * g++.dg/warn/Wvexing-parse9.C: New test.
+
+2020-11-21 David Edelsohn <dje.gcc@gmail.com>
+
+ * g++.dg/debug/localclass2.C: Require LTO.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97839
+ * g++.dg/cpp2a/lambda-generic8.C: New test.
+
+2020-11-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97427
+ * g++.dg/cpp2a/constexpr-dtor10.C: New test.
+
+2020-11-21 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/vect/vect-35-big-array.c: Excpect 2 loops to be vectorized.
+ * gcc.dg/vect/vect-35.c: Excpect 2 loops to be vectorized.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * gcc.target/powerpc/mma-double-test.c (main): Call abort for failure.
+ * gcc.target/powerpc/mma-single-test.c (main): Call abort for failure.
+ * gcc.target/powerpc/pr96506.c: Rename to pr96506-1.c.
+ * gcc.target/powerpc/pr96506-2.c: New test.
+ * gcc.target/powerpc/pr96506-1.c: New file.
+
+2020-11-20 Michael Meissner <meissner@linux.ibm.com>
+
+ * gcc.dg/nextafter-2.c: Include math.h.
+
+2020-11-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/97918
+ * g++.dg/debug/localclass2.C: New test.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/attr-access-4.c: New test.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97879
+ * gcc.dg/attr-access-3.c: New test.
+
+2020-11-20 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97515.c: Check in ccp2, not evrp.
+
+2020-11-20 Andrea Corallo <andrea.corallo@arm.com>
+
+ PR target/97727
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_2.c: Relax
+ regexps.
+
+2020-11-20 Andrea Corallo <andrea.corallo@arm.com>
+
+ PR target/97726
+ * gcc.target/arm/simd/bf16_vldn_1.c: Relax regexps not to fail on
+ big endian.
+ * gcc.target/arm/simd/vldn_lane_bf16_1.c: Likewise
+ * gcc.target/arm/simd/vmmla_1.c: Add -mfloat-abi=hard flag.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/88101
+ * c-c++-common/builtin-clear-padding-1.c: New test.
+ * c-c++-common/torture/builtin-clear-padding-1.c: New test.
+ * c-c++-common/torture/builtin-clear-padding-2.c: New test.
+ * c-c++-common/torture/builtin-clear-padding-3.c: New test.
+ * c-c++-common/torture/builtin-clear-padding-4.c: New test.
+ * c-c++-common/torture/builtin-clear-padding-5.c: New test.
+ * g++.dg/torture/builtin-clear-padding-1.C: New test.
+ * g++.dg/torture/builtin-clear-padding-2.C: New test.
+ * gcc.dg/builtin-clear-padding-1.c: New test.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/97528
+ * gcc.target/arm/pr97528.c: New test.
+
+2020-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt90a.adb: New test.
+ * gnat.dg/opt90b.adb: Likewise.
+ * gnat.dg/opt90c.adb: Likewise.
+ * gnat.dg/opt90d.adb: Likewise.
+ * gnat.dg/opt90e.adb: Likewise.
+ * gnat.dg/opt90a_pkg.ads: New helper.
+ * gnat.dg/opt90b_pkg.ads: Likewise.
+ * gnat.dg/opt90c_pkg.ads: Likewise.
+ * gnat.dg/opt90d_pkg.ads: Likewise.
+ * gnat.dg/opt90e_pkg.ads: Likewise.
+
+2020-11-20 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/97873
+ * gcc.target/i386/pr97873.c: New test.
+ * gcc.target/i386/pr97873-1.c: New test.
+
+2020-11-20 Martin Uecker <muecker@gwdg.de>
+
+ * gcc.dg/cond-constqual-1.c: Adapt test.
+ * gcc.dg/lvalue-11.c: New test.
+ * gcc.dg/pr60195.c: Add warning.
+
+2020-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91029
+ * gcc.dg/tree-ssa/pr91029-1.c: New test.
+ * gcc.dg/tree-ssa/pr91029-2.c: New test.
+
+2020-11-19 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/tree-ssa/pr93781-1.c: New.
+ * gcc.dg/tree-ssa/pr93781-2.c: New.
+ * gcc.dg/tree-ssa/pr93781-3.c: New.
+
+2020-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97860
+ * gcc.dg/pr97860.c: New test.
+
+2020-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97523
+ * g++.dg/expr/anew5.C: New test.
+ * g++.dg/expr/anew6.C: New test.
+
+2020-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97895
+ * g++.dg/cpp0x/auto54.C: New test.
+
+2020-11-19 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97905
+ * g++.dg/lookup/pr97905.C: New.
+
+2020-11-19 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.target/pru/halt.c: New test.
+ * gcc.target/pru/lmbd.c: New test.
+
+2020-11-19 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/vect-cost-model-1.c: New test.
+ * gcc.dg/vect/vect-cost-model-2.c: Likewise.
+ * gcc.dg/vect/vect-cost-model-3.c: Likewise.
+ * gcc.dg/vect/vect-cost-model-4.c: Likewise.
+ * gcc.dg/vect/vect-cost-model-5.c: Likewise.
+ * gcc.dg/vect/vect-cost-model-6.c: Likewise.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/pr97897.c: Add dg-options.
+
+2020-11-19 Joel Hutton <joel.hutton@arm.com>
+
+ * gcc.target/aarch64/vect-widen-lshift.c: New test.
+
+2020-11-19 Joel Hutton <joel.hutton@arm.com>
+
+ * gcc.target/aarch64/vect-widen-add.c: New test.
+ * gcc.target/aarch64/vect-widen-sub.c: New test.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97901
+ * gcc.dg/torture/pr97901.c: New testcase.
+
+2020-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97897
+ * gcc.dg/pr97897.c: New testcase.
+
+2020-11-19 Uroš Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/pr97887.c: New test.
+
+2020-11-18 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR middle-end/85811
+ * gcc.dg/pr85811.c: New test.
+ * gcc.dg/fold-isfinite-1.c: New test.
+ * gcc.dg/fold-isfinite-2.c: New test.
+ * gcc.dg/fold-isinf-1.c: New test.
+ * gcc.dg/fold-isinf-2.c: New test.
+ * gcc.dg/fold-isnan-1.c: New test.
+ * gcc.dg/fold-isnan-2.c: New test.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91029
+ PR tree-optimization/97888
+ * gcc.dg/pr91029.c: Add comment with PR number.
+ (f2): Use > 0 rather than >= 0.
+ * gcc.c-torture/execute/pr97888-1.c: New test.
+ * gcc.c-torture/execute/pr97888-2.c: New test.
+
+2020-11-18 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97893
+ * gcc.dg/analyzer/malloc-1.c: Add CWE-690 and CWE-476 codes to
+ expected output.
+
+2020-11-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/bb-slp-pr68892.c: Don't XFAIL the profitability
+ test for aarch64*-*-*. Allow the "BB vectorization with gaps"
+ message to be printed more than once.
+
+2020-11-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/slp-21.c: Expect 4 SLP instances to be vectorized
+ on arm* and aarch64* targets.
+
+2020-11-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/fast-math-vect-call-1.c: Only expect SLP to be used
+ on vect_perm3_int targets.
+ * gcc.dg/vect/slp-perm-6.c: Likewise. Only XFAIL the LOAD/STORE_LANES
+ tests on vect_perm3_int targets.
+
+2020-11-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/vect-epilogues.c: XFAIL test for epilogue loop
+ vectorization if vect_partial_vectors_usage_2.
+
+2020-11-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/vect-sdiv-pow2-1.c (main): Add an asm to the
+ set-up loop.
+
+2020-11-18 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/97843
+ * gdc.dg/torture/pr97843.d: New test.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/97862
+ * c-c++-common/gomp/pr97862.c: New test.
+
+2020-11-18 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.target/riscv/arch-9.c: New.
+ * gcc.target/riscv/arch-10.c: Ditto.
+ * gcc.target/riscv/arch-11.c: Ditto.
+ * gcc.target/riscv/attribute-6.c: Remove, we don't support G
+ with version anymore.
+ * gcc.target/riscv/attribute-8.c: Reorder arch string to fit canonical
+ ordering.
+ * gcc.target/riscv/attribute-9.c: We don't emit version for
+ unknown extensions now.
+ * gcc.target/riscv/attribute-11.c: Add -misa-spec=2.2 flags.
+ * gcc.target/riscv/attribute-12.c: Ditto.
+ * gcc.target/riscv/attribute-13.c: Ditto.
+ * gcc.target/riscv/attribute-14.c: Ditto.
+ * gcc.target/riscv/attribute-15.c: New.
+ * gcc.target/riscv/attribute-16.c: Ditto.
+ * gcc.target/riscv/attribute-17.c: Ditto.
+
+2020-11-18 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.target/riscv/arch-8.c: New.
+ * gcc.target/riscv/attribute-14.c: Ditto.
+
+2020-11-18 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ * gcc.dg/tree-ssa/loopclosedphi.c: New test.
+
+2020-11-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr91029.c: New.
+
+2020-11-17 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97877
+ * g++.dg/lookup/pr97877.C: New.
+
+2020-11-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr83072.c: New.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/cr-decimal-dig-3.c: New test.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c11-float-6.c, gcc.dg/c2x-float-10.c: New tests.
+
+2020-11-17 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/pr25376.c: Allow .opd section.
+
+2020-11-17 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/31799
+ * gcc.target/i386/pr31799.c: New test.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/cond_cnot_1.c: Remove XFAIL.
+ * gcc.target/aarch64/sve/cond_unary_1.c: Likewise.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/97693
+ * gcc.dg/vect/pr97693.c: New test.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/slp-46.c: XFAIL test for SLP on vect_load_lanes targets.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/aligned-section-anchors-nest-1.c: XFAIL alignment
+ test if vect_element_align_preferred.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/bb-slp-subgroups-3.c: XFAIL for variable-length vectors.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/pr65947-8.c: Expect the loop to be vectorized for SVE.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/pr97678.c: XFAIL test for SLP vectorization
+ for variable-length vectors.
+ * gcc.dg/vect/pr97835.c: Likewise.
+ * gcc.dg/vect/slp-49.c: Likewise.
+ * gcc.dg/vect/vect-outer-slp-1.c: Likewise.
+ * gcc.dg/vect/vect-outer-slp-2.c: Likewise.
+ * gcc.dg/vect/vect-outer-slp-3.c: Likewise.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/slp-reduc-4.c: XFAIL test for SLP vectorization
+ for variable-length SVE.
+ * gcc.dg/vect/slp-reduc-7.c: Likewise.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/bb-slp-43.c: Remove XFAIL for vect_variable_length.
+
+2020-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/pr91750.c: Allow "[]," inside a vector(...) lane count.
+
+2020-11-17 Liu Hao <lh_mouse@126.com>
+
+ * gcc.dg/format/ms_c99-printf-3.c: Update tests.
+
+2020-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/90628
+ * gcc.dg/builtin-arith-overflow-4.c: New test.
+
+2020-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/guality/pr59776.c (foo): Use noipa attribute instead of
+ noinline, noclone.
+
+2020-11-17 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx2-vec-set-1.c: New test.
+ * gcc.target/i386/avx2-vec-set-2.c: New test.
+ * gcc.target/i386/avx512bw-vec-set-1.c: New test.
+ * gcc.target/i386/avx512bw-vec-set-2.c: New test.
+ * gcc.target/i386/avx512f-vec-set-2.c: New test.
+ * gcc.target/i386/avx512vl-vec-set-2.c: New test.
+
+2020-11-17 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/95673
+ * gcc.dg/Wstring-compare-3.c: New test.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/dfp/c2x-float-dfp-7.c, gcc.dg/dfp/c2x-float-dfp-8.c: New
+ tests.
+ * gcc.dg/c2x-float-no-dfp-3.c: Also check that DEC32_SNAN,
+ DEC64_SNAN and DEC128_SNAN are not defined.
+
+2020-11-17 Joseph Myers <joseph@codesourcery.com>
+
+ * lib/target-supports.exp (check_effective_target_inff): New.
+ * gcc.dg/c11-float-4.c, gcc.dg/c11-float-5.c,
+ gcc.dg/c11-float-dfp-2.c, gcc.dg/c2x-float-2.c,
+ gcc.dg/c2x-float-3.c, gcc.dg/c2x-float-4.c, gcc.dg/c2x-float-5.c,
+ gcc.dg/c2x-float-6.c, gcc.dg/c2x-float-7.c, gcc.dg/c2x-float-8.c,
+ gcc.dg/c2x-float-9.c, gcc.dg/c2x-float-no-dfp-3.c,
+ gcc.dg/c2x-float-no-dfp-4.c, gcc.dg/dfp/c2x-float-dfp-4.c,
+ gcc.dg/dfp/c2x-float-dfp-5.c, gcc.dg/dfp/c2x-float-dfp-6.c,
+ gcc.dg/torture/float128-nan-floath.c,
+ gcc.dg/torture/float128x-nan-floath.c,
+ gcc.dg/torture/float16-nan-floath.c,
+ gcc.dg/torture/float32-nan-floath.c,
+ gcc.dg/torture/float32x-nan-floath.c,
+ gcc.dg/torture/float64-nan-floath.c,
+ gcc.dg/torture/float64x-nan-floath.c,
+ gcc.dg/torture/floatn-nan-floath.h: New tests.
+
+2020-11-16 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR rtl-optimization/92180
+ * gcc.target/i386/pr92180.c: New test.
+
+2020-11-16 Harald Anlauf <anlauf@gmx.de>
+
+ * gfortran.dg/pr48958.f90: New test.
+
+2020-11-16 Jan Hubicka <jh@suse.cz>
+
+ * g++.dg/warn/uninit-1.C: New test.
+
+2020-11-16 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/s390.exp (check_effective_target_s390_z14_hw):
+ New predicate.
+ * gcc.target/s390/vector/long-double-caller-abi-run.c: Use the
+ new predicate.
+ * gcc.target/s390/vector/long-double-copysign.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-double.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-float.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-i16.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-i32.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-i64.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-i8.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-u16.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-u32.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-u64.c: Likewise.
+ * gcc.target/s390/vector/long-double-from-u8.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-double.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-float.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-i16.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-i32.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-i64.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-i8.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-u16.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-u32.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-u64.c: Likewise.
+ * gcc.target/s390/vector/long-double-to-u8.c: Likewise.
+ * gcc.target/s390/vector/long-double-wfaxb.c: Likewise.
+ * gcc.target/s390/vector/long-double-wfdxb.c: Likewise.
+ * gcc.target/s390/vector/long-double-wfsxb-1.c: Likewise.
+
+2020-11-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR testsuite/97803
+ * c-c++-common/asan/pointer-compare-1.c (global1): Add
+ __attribute__((used))
+ (global2): Likewise.
+ (small_global): Likewise.
+ (large_global): Likewise.
+
+2020-11-16 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * gcc.dg/profile-info-section.c: New test.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97838
+ * gcc.dg/vect/pr97838.c: New testcase.
+
+2020-11-16 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/97736
+ * gcc.dg/tree-ssa/switch-1.c: Prefer bit tests.
+ * g++.dg/tree-ssa/pr97736.C: New test.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97835
+ * gcc.dg/vect/pr97835.c: New testcase.
+
+2020-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97830
+ * gcc.dg/pr97830.c: New testcase.
+
+2020-11-15 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/rtx-cost-Os-f5series.c: Adjust test to use new
+ hwmult library function name.
+
+2020-11-15 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/ipa/modref-2.c: Add ilp32 expected result.
+
+2020-11-15 David Edelsohn <dje.gcc@gmail.com>
+
+ * lib/scanasm.exp (parse_section_of_symbols): Also look for AIX
+ XCOFF CSECT notation.
+ * g++.dg/opt/const4.C: Also look for AIX XCOFF "[RO]".
+ * gcc.dg/20021029-1.c: Likewise.
+ * gcc.dg/array-quals-1.c: Likewise and "[RW]".
+ * g++.dg/gomp/tls-5.C: Also look for AIX XCOFF "[TL]".
+ * gcc.dg/pr25376.c: Accept AIX decoration around named section
+ and function descriptor.
+
+2020-11-15 Maciej W. Rozycki <macro@linux-mips.org>
+
+ * gcc.target/vax/bswapdi-1.c (dg-options): New setting.
+
+2020-11-15 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/other/abstract1.C: Adjust.
+ * g++.dg/other/abstract2.C: Adjust.
+ * g++.dg/other/abstract4.C: Adjust.
+ * g++.dg/other/abstract5.C: Adjust.
+ * g++.dg/other/abstract8.C: New test.
+ * g++.dg/template/sfinae-dr657.C: Adjust.
+ * g++.old-deja/g++.other/decl3.C: Adjust.
+
+2020-11-15 Jan Hubicka <jh@suse.cz>
+
+ * gcc.c-torture/execute/pr97836.c: New test.
+
+2020-11-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc.dg/pr23214.m: Use Object as the root object before
+ Darwin12 (and NSObject after).
+
+2020-11-14 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/torture/pta-ptrarith-1.c: Escape parameters.
+
+2020-11-14 Matthew Glazar <strager.nds@gmail.com>
+
+ * lib/scanasm.exp (dg-scan): Extract file globbing code ...
+ (dg_glob_remote): ... into this new procedure.
+ (scan-assembler-symbol-section): Define.
+ (scan-symbol-section): Define.
+ * g++.dg/gomp/tls-5.C: Add symbol section test.
+ * g++.dg/opt/const4.C: Likewise.
+ * gcc.dg/20021029-1.c: Likewise.
+ * gcc.dg/array-quals-1.c: Likewise.
+ * gcc.dg/darwin-sections.c: Likewise.
+ * gcc.dg/pr25376.c: Likewise.
+ * gcc.test-framework/test-framework.exp: Load scanasm and test .S files.
+ * gcc.test-framework/dg-scan-symbol-section-1-exp-F.S: New test.
+ * gcc.test-framework/dg-scan-symbol-section-2-exp-F.S: New test.
+ * gcc.test-framework/dg-scan-symbol-section-3-exp-F.S: New test.
+ * gcc.test-framework/dg-scan-symbol-section-exp-P.S: New test.
+
+2020-11-14 Monk Chiang <monk.chiang@sifive.com>
+
+ PR target/97682
+ * g++.target/riscv/pr97682.C: New test.
+ * gcc.target/riscv/interrupt-3.c: Check register for t0.
+ * gcc.target/riscv/interrupt-4.c: Likewise.
+
+2020-11-13 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/binary-constants-2.c, gcc.dg/binary-constants-3.c,
+ gcc.dg/system-binary-constants-1.c: Update expected diagnostics.
+ * gcc.dg/c11-binary-constants-1.c,
+ gcc.dg/c11-binary-constants-2.c, gcc.dg/c2x-binary-constants-1.c,
+ gcc.dg/c2x-binary-constants-2.c, gcc.dg/c2x-binary-constants-3.c:
+ New tests.
+
+2020-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/guality/redeclaration1.C (p): New variable.
+ (S::f): Increment what p points to before storing S::i into l. Adjust
+ gdb-test line numbers.
+ (main): Initialize p to address of an automatic variable.
+
+2020-11-13 Gergö Barany <gergo@codesourcery.com>
+ Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/kernels-decompose-1.c: New.
+ * c-c++-common/goacc/kernels-decompose-2.c: New.
+ * c-c++-common/goacc/kernels-decompose-ice-1.c: New.
+ * c-c++-common/goacc/kernels-decompose-ice-2.c: New.
+ * gfortran.dg/goacc/kernels-decompose-1.f95: New.
+ * gfortran.dg/goacc/kernels-decompose-2.f95: New.
+ * c-c++-common/goacc/if-clause-2.c: Adjust.
+ * gfortran.dg/goacc/kernels-tree.f95: Likewise.
+
+2020-11-13 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/classify-parallel.c: Adjust.
+ * gfortran.dg/goacc/classify-parallel.f95: Likewise.
+ * c-c++-common/goacc/classify-serial.c: New.
+ * gfortran.dg/goacc/classify-serial.f95: Likewise.
+
+2020-11-13 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/feat-cxx2a.C: Check it.
+
+2020-11-13 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/inh-ctor28.C: Adjust expected diagnostic.
+ * g++.dg/cpp0x/inh-ctor33.C: Likewise.
+ * g++.dg/cpp0x/using-enum-1.C: Add comment.
+ * g++.dg/cpp0x/using-enum-2.C: Allowed in C++20.
+ * g++.dg/cpp0x/using-enum-3.C: Likewise.
+ * g++.dg/cpp1z/class-deduction69.C: Adjust diagnostic.
+ * g++.dg/inherit/using5.C: Likewise.
+ * g++.dg/cpp2a/using-enum-1.C: New test.
+ * g++.dg/cpp2a/using-enum-2.C: New test.
+ * g++.dg/cpp2a/using-enum-3.C: New test.
+ * g++.dg/cpp2a/using-enum-4.C: New test.
+ * g++.dg/cpp2a/using-enum-5.C: New test.
+ * g++.dg/cpp2a/using-enum-6.C: New test.
+ * g++.dg/debug/dwarf2/using-enum.C: New test.
+
+2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * c-c++-common/asmgoto-2.c: Permit output in asm goto.
+ * gcc.c-torture/compile/asmgoto-2.c: New.
+ * gcc.c-torture/compile/asmgoto-3.c: New.
+ * gcc.c-torture/compile/asmgoto-4.c: New.
+ * gcc.c-torture/compile/asmgoto-5.c: New.
+
+2020-11-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/tree-ssa/evrp20.c
+ * gcc.dg/tree-ssa/evrp21.c
+ * gcc.dg/tree-ssa/evrp22.c
+
+2020-11-13 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/97788
+ * g++.dg/ubsan/pr61272.C: Move expected error location.
+
+2020-11-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.c-torture/execute/index-1.c: Skip for the default MSP430 430X ISA.
+
+2020-11-13 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/rtx-cost-O3-default.c: New test.
+ * gcc.target/msp430/rtx-cost-O3-f5series.c: New test.
+ * gcc.target/msp430/rtx-cost-Os-default.c: New test.
+ * gcc.target/msp430/rtx-cost-Os-f5series.c: New test.
+
+2020-11-13 Jan Hubicka <jh@suse.cz>
+
+ * c-c++-common/Wstringop-overflow-2.c: Disable ICF.
+ * g++.dg/warn/Warray-bounds-8.C: Disable ICF.
+
+2020-11-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/tree-ssa/pr78655.c: New.
+
+2020-11-13 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * gdc.dg/pr92216.d: Update scan-assember.
+
+2020-11-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97812
+ * gcc.dg/torture/pr97812.c: New testcase.
+
+2020-11-13 Sudakshina Das <sudi.das@arm.com>
+
+ * g++.dg/tree-ssa/pr90883.C: Remove xfail for aarch64.
+ * gcc.dg/tree-prof/stringop-2.c: Add xfail for aarch64.
+ * gcc.target/aarch64/memset-corner-cases.c: New test.
+ * gcc.target/aarch64/memset-q-reg.c: New test.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90707
+ * obj-c++.dg/property/at-property-4.mm: Add basic nullability
+ tests.
+ * objc.dg/property/at-property-4.m: Likewise.
+ * obj-c++.dg/attributes/nullability-00.mm: New test.
+ * obj-c++.dg/property/nullability-00.mm: New test.
+ * objc.dg/attributes/nullability-00.m: New test.
+ * objc.dg/property/nullability-00.m: New test.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * obj-c++.dg/attributes/class-attribute-1.mm:
+ Add Wno-objc-root-class.
+ * obj-c++.dg/attributes/class-attribute-2.mm: Likewise.
+ * obj-c++.dg/attributes/class-attribute-3.mm: Likewise.
+ * obj-c++.dg/attributes/method-deprecated-1.mm: Likewise.
+ * obj-c++.dg/attributes/method-deprecated-2.mm: Likewise.
+ * obj-c++.dg/attributes/method-deprecated-3.mm: Likewise.
+ * obj-c++.dg/attributes/method-format-1.mm: Likewise.
+ * obj-c++.dg/attributes/method-nonnull-1.mm: Likewise.
+ * obj-c++.dg/attributes/method-noreturn-1.mm: Likewise.
+ * obj-c++.dg/attributes/method-sentinel-1.mm: Likewise.
+ * obj-c++.dg/attributes/nsobject-01.mm: Likewise.
+ * obj-c++.dg/attributes/parameter-attribute-1.mm: Likewise.
+ * obj-c++.dg/attributes/parameter-attribute-2.mm: Likewise.
+ * obj-c++.dg/attributes/proto-attribute-1.mm: Likewise.
+ * obj-c++.dg/attributes/proto-attribute-3.mm: Likewise.
+ * obj-c++.dg/attributes/proto-attribute-4.mm: Likewise.
+ * obj-c++.dg/attributes/unused-parameter-1.mm: Likewise.
+ * obj-c++.dg/bad-receiver-type.mm: Likewise.
+ * obj-c++.dg/bitfield-3.mm: Likewise.
+ * obj-c++.dg/bitfield-5.mm: Likewise.
+ * obj-c++.dg/class-extension-1.mm: Likewise.
+ * obj-c++.dg/class-extension-2.mm: Likewise.
+ * obj-c++.dg/class-extension-3.mm: Likewise.
+ * obj-c++.dg/class-extension-4.mm: Likewise.
+ * obj-c++.dg/class-protocol-1.mm: Likewise.
+ * obj-c++.dg/comp-types-1.mm: Likewise.
+ * obj-c++.dg/comp-types-10.mm: Likewise.
+ * obj-c++.dg/comp-types-2.mm: Likewise.
+ * obj-c++.dg/comp-types-3.mm: Likewise.
+ * obj-c++.dg/comp-types-5.mm: Likewise.
+ * obj-c++.dg/comp-types-6.mm: Likewise.
+ * obj-c++.dg/comp-types-7.mm: Likewise.
+ * obj-c++.dg/comp-types-8.mm: Likewise.
+ * obj-c++.dg/demangle-2.mm: Likewise.
+ * obj-c++.dg/demangle-3.mm: Likewise.
+ * obj-c++.dg/duplicate-class-1.mm: Likewise.
+ * obj-c++.dg/encode-1-next.mm: Likewise.
+ * obj-c++.dg/encode-1.mm: Likewise.
+ * obj-c++.dg/enhanced-proto-2.mm: Likewise.
+ * obj-c++.dg/exceptions-1.mm: Likewise.
+ * obj-c++.dg/exceptions-3.mm: Likewise.
+ * obj-c++.dg/exceptions-4.mm: Likewise.
+ * obj-c++.dg/exceptions-5.mm: Likewise.
+ * obj-c++.dg/extern-c-1.mm: Likewise.
+ * obj-c++.dg/fobjc-std-1.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-class-meta.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-class.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-ivar.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-method.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-objc.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-objc_msg_lookup.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-object.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-property.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-protocol.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-resolve-method.mm: Likewise.
+ * obj-c++.dg/gnu-api-2-sel.mm: Likewise.
+ * obj-c++.dg/invalid-method-2.mm: Likewise.
+ * obj-c++.dg/ivar-invalid-type-1.mm: Likewise.
+ * obj-c++.dg/ivar-problem-1.mm: Likewise.
+ * obj-c++.dg/lto/lto.exp: Likewise.
+ * obj-c++.dg/lto/trivial-1_0.mm: Likewise.
+ * obj-c++.dg/method-1.mm: Likewise.
+ * obj-c++.dg/method-12.mm: Likewise.
+ * obj-c++.dg/method-18.mm: Likewise.
+ * obj-c++.dg/method-19.mm: Likewise.
+ * obj-c++.dg/method-20.mm: Likewise.
+ * obj-c++.dg/method-3.mm: Likewise.
+ * obj-c++.dg/method-4.mm: Likewise.
+ * obj-c++.dg/method-5.mm: Likewise.
+ * obj-c++.dg/method-8.mm: Likewise.
+ * obj-c++.dg/method-9.mm: Likewise.
+ * obj-c++.dg/method-namespace-1.mm: Likewise.
+ * obj-c++.dg/plugin/diagnostic-test-expressions-1.mm:
+ Likewise.
+ * obj-c++.dg/pr23709.mm: Likewise.
+ * obj-c++.dg/pragma-2.mm: Likewise.
+ * obj-c++.dg/private-1.mm: Likewise.
+ * obj-c++.dg/private-2.mm: Likewise.
+ * obj-c++.dg/property/property.exp: Likewise.
+ * obj-c++.dg/proto-lossage-1.mm: Likewise.
+ * obj-c++.dg/proto-lossage-5.mm: Likewise.
+ * obj-c++.dg/proto-qual-1.mm: Likewise.
+ * obj-c++.dg/protocol-inheritance-1.mm: Likewise.
+ * obj-c++.dg/protocol-inheritance-2.mm: Likewise.
+ * obj-c++.dg/protocol-optional-1.mm: Likewise.
+ * obj-c++.dg/selector-1.mm: Likewise.
+ * obj-c++.dg/selector-2.mm: Likewise.
+ * obj-c++.dg/selector-3.mm: Likewise.
+ * obj-c++.dg/selector-4.mm: Likewise.
+ * obj-c++.dg/strings/strings.exp: Likewise.
+ * obj-c++.dg/stubify-1.mm: Likewise.
+ * obj-c++.dg/stubify-2.mm: Likewise.
+ * obj-c++.dg/super-dealloc-1.mm: Likewise.
+ * obj-c++.dg/super-dealloc-2.mm: Likewise.
+ * obj-c++.dg/sync-3.mm: Likewise.
+ * obj-c++.dg/syntax-error-2.mm: Likewise.
+ * obj-c++.dg/syntax-error-4.mm: Likewise.
+ * obj-c++.dg/syntax-error-7.mm: Likewise.
+ * obj-c++.dg/syntax-error-9.mm: Likewise.
+ * obj-c++.dg/template-4.mm: Likewise.
+ * obj-c++.dg/template-7.mm: Likewise.
+ * obj-c++.dg/template-8.mm: Likewise.
+ * obj-c++.dg/threedotthree-abi-1.mm: Likewise.
+ * obj-c++.dg/torture/dg-torture.exp: Likewise.
+ * obj-c++.dg/torture/strings/strings.exp: Likewise.
+ * obj-c++.dg/try-catch-12.mm: Likewise.
+ * obj-c++.dg/try-catch-13.mm: Likewise.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * objc.dg/anon-1.m: Add Wno-objc-root-class.
+ * objc.dg/attributes/class-attribute-1.m: Likewise.
+ * objc.dg/attributes/class-attribute-2.m: Likewise.
+ * objc.dg/attributes/class-attribute-3.m: Likewise.
+ * objc.dg/attributes/method-deprecated-1.m: Likewise.
+ * objc.dg/attributes/method-deprecated-2.m: Likewise.
+ * objc.dg/attributes/method-deprecated-3.m: Likewise.
+ * objc.dg/attributes/method-format-1.m: Likewise.
+ * objc.dg/attributes/method-nonnull-1.m: Likewise.
+ * objc.dg/attributes/method-noreturn-1.m: Likewise.
+ * objc.dg/attributes/method-sentinel-1.m: Likewise.
+ * objc.dg/attributes/nsobject-01.m: Likewise.
+ * objc.dg/attributes/objc-exception-1.m: Likewise.
+ * objc.dg/attributes/parameter-attribute-1.m: Likewise.
+ * objc.dg/attributes/parameter-attribute-2.m: Likewise.
+ * objc.dg/attributes/proto-attribute-1.m: Likewise.
+ * objc.dg/attributes/proto-attribute-2.m: Likewise.
+ * objc.dg/attributes/proto-attribute-3.m: Likewise.
+ * objc.dg/attributes/proto-attribute-4.m: Likewise.
+ * objc.dg/bitfield-2.m: Likewise.
+ * objc.dg/break-in-ifstmt.m: Likewise.
+ * objc.dg/class-1.m: Likewise.
+ * objc.dg/class-extension-1.m: Likewise.
+ * objc.dg/class-extension-2.m: Likewise.
+ * objc.dg/class-extension-3.m: Likewise.
+ * objc.dg/class-extension-4.m: Likewise.
+ * objc.dg/class-protocol-1.m: Likewise.
+ * objc.dg/comp-types-7.m: Likewise.
+ * objc.dg/demangle-1.m: Likewise.
+ * objc.dg/duplicate-class-1.m: Likewise.
+ * objc.dg/encode-6-next.m: Likewise.
+ * objc.dg/encode-6.m: Likewise.
+ * objc.dg/enhanced-proto-2.m: Likewise.
+ * objc.dg/exceptions-1.m: Likewise.
+ * objc.dg/exceptions-3.m: Likewise.
+ * objc.dg/exceptions-4.m: Likewise.
+ * objc.dg/exceptions-5.m: Likewise.
+ * objc.dg/fobjc-std-1.m: Likewise.
+ * objc.dg/foreach-2.m: Likewise.
+ * objc.dg/foreach-4.m: Likewise.
+ * objc.dg/foreach-5.m: Likewise.
+ * objc.dg/fsyntax-only.m: Likewise.
+ * objc.dg/gnu-api-2-class-meta.m: Likewise.
+ * objc.dg/gnu-api-2-class.m: Likewise.
+ * objc.dg/gnu-api-2-ivar.m: Likewise.
+ * objc.dg/gnu-api-2-method.m: Likewise.
+ * objc.dg/gnu-api-2-objc.m: Likewise.
+ * objc.dg/gnu-api-2-objc_msg_lookup.m: Likewise.
+ * objc.dg/gnu-api-2-object.m: Likewise.
+ * objc.dg/gnu-api-2-property.m: Likewise.
+ * objc.dg/gnu-api-2-protocol.m: Likewise.
+ * objc.dg/gnu-api-2-resolve-method.m: Likewise.
+ * objc.dg/gnu-api-2-sel.m: Likewise.
+ * objc.dg/incomplete-type-1.m: Likewise.
+ * objc.dg/instancetype-0.m: Likewise.
+ * objc.dg/invalid-method-2.m: Likewise.
+ * objc.dg/ivar-invalid-type-1.m: Likewise.
+ * objc.dg/ivar-problem-1.m: Likewise.
+ * objc.dg/ivar-scope-1.m: Likewise.
+ * objc.dg/ivar-scope-2.m: Likewise.
+ * objc.dg/ivar-scope-4.m: Likewise.
+ * objc.dg/ivar-visibility-1.m: Likewise.
+ * objc.dg/ivar-visibility-2.m: Likewise.
+ * objc.dg/ivar-visibility-3.m: Likewise.
+ * objc.dg/ivar-visibility-4.m: Likewise.
+ * objc.dg/local-decl-1.m: Likewise.
+ * objc.dg/lto/lto.exp: Likewise.
+ * objc.dg/lto/trivial-1_0.m: Likewise.
+ * objc.dg/method-1.m: Likewise.
+ * objc.dg/method-12.m: Likewise.
+ * objc.dg/method-13.m: Likewise.
+ * objc.dg/method-14.m: Likewise.
+ * objc.dg/missing-proto-3.m: Likewise.
+ * objc.dg/next-runtime-1.m: Likewise.
+ * objc.dg/objc-foreach-1.m: Likewise.
+ * objc.dg/objc-foreach-2.m: Likewise.
+ * objc.dg/objc-foreach-3.m: Likewise.
+ * objc.dg/objc-nofilename-1.m: Likewise.
+ * objc.dg/param-1.m: Likewise.
+ * objc.dg/pch/pch.exp: Likewise.
+ * objc.dg/plugin/diagnostic-test-expressions-1.m: Likewise.
+ * objc.dg/pr23709.m: Likewise.
+ * objc.dg/private-1.m: Likewise.
+ * objc.dg/private-2.m: Likewise.
+ * objc.dg/property/property.exp: Likewise.
+ * objc.dg/proto-hier-1.m: Likewise.
+ * objc.dg/proto-hier-2.m: Likewise.
+ * objc.dg/proto-lossage-1.m: Likewise.
+ * objc.dg/proto-lossage-5.m: Likewise.
+ * objc.dg/proto-qual-1.m: Likewise.
+ * objc.dg/protocol-inheritance-1.m: Likewise.
+ * objc.dg/protocol-inheritance-2.m: Likewise.
+ * objc.dg/protocol-optional-1.m: Likewise.
+ * objc.dg/selector-1.m: Likewise.
+ * objc.dg/selector-2.m: Likewise.
+ * objc.dg/selector-3.m: Likewise.
+ * objc.dg/selector-4.m: Likewise.
+ * objc.dg/shadow-1.m: Likewise.
+ * objc.dg/shadow-2.m: Likewise.
+ * objc.dg/special/load-category-1.m: Likewise.
+ * objc.dg/special/load-category-2.m: Likewise.
+ * objc.dg/special/load-category-3.m: Likewise.
+ * objc.dg/special/special.exp: Likewise.
+ * objc.dg/special/unclaimed-category-1.h: Likewise.
+ * objc.dg/special/unclaimed-category-1.m: Likewise.
+ * objc.dg/stabs-1.m: Likewise.
+ * objc.dg/strings/strings.exp: Likewise.
+ * objc.dg/stubify-1.m: Likewise.
+ * objc.dg/stubify-2.m: Likewise.
+ * objc.dg/super-class-2.m: Likewise.
+ * objc.dg/super-dealloc-1.m: Likewise.
+ * objc.dg/super-dealloc-2.m: Likewise.
+ * objc.dg/sync-3.m: Likewise.
+ * objc.dg/threedotthree-abi-1.m: Likewise.
+ * objc.dg/torture/dg-torture.exp: Likewise.
+ * objc.dg/torture/strings/strings.exp: Likewise.
+ * objc.dg/try-catch-11.m: Likewise.
+ * objc.dg/try-catch-12.m: Likewise.
+ * objc.dg/type-size-2.m: Likewise.
+ * objc.dg/type-size-3.m: Likewise.
+ * objc.dg/type-size-4.m: Likewise.
+ * objc.dg/type-size-5.m: Likewise.
+ * objc.dg/undeclared-selector.m: Likewise.
+ * objc.dg/volatile-1.m: Likewise.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * objc.dg/attributes/root-class-01.m: New test.
+ * objc.dg/root-class-00.m: New test.
+ * obj-c++.dg/attributes/root-class-01.mm: New test.
+ * obj-c++.dg/root-class-00.mm: New test.
+
+2020-11-13 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/cpp2a/concepts-decltype3.C: New test.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/87291
+ * jit.dg/jit.exp: Load target-supports-dg.exp.
+ Set dg-do-what-default.
+ (jit-dg-test): Set dg-do-what and call dg-get-options, skipping
+ the test if it's not supported on the given target.
+ * jit.dg/test-asm.c: New test.
+ * jit.dg/test-asm.cc: New test.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/test-debug-strings.c (create_code): Add tests of
+ string literal escaping.
+
+2020-11-12 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c2x-has-c-attribute-1.c, gcc.dg/c2x-has-c-attribute-2.c,
+ gcc.dg/c2x-has-c-attribute-3.c, gcc.dg/c2x-has-c-attribute-4.c:
+ New tests.
+
+2020-11-12 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/97782
+ * gfortran.dg/goacc/classify-kernels-unparallelized.f95: Move dg-message
+ one line up.
+ * gfortran.dg/goacc/classify-kernels.f95: Likewise.
+
+2020-11-12 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran.dg/entry_23.f: New test.
+
+2020-11-12 Alex Coplan <alex.coplan@arm.com>
+
+ PR target/97730
+ * gcc.target/aarch64/sve2/bcax_1.c (OP): Add missing bitwise not
+ to match correct bcax semantics.
+ * gcc.dg/vect/pr97730.c: New test.
+
+2020-11-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97806
+ * gcc.dg/pr97806.c: New testcase.
+
+2020-11-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97790
+ * g++.dg/cpp2a/constexpr-dtor9.C: New test.
+
+2020-11-12 Jason Merrill <jason@redhat.com>
+
+ PR debug/97060
+ * gcc.dg/debug/dwarf2/pr97060.c: New test.
+
+2020-11-12 Kewen Lin <linkw@linux.ibm.com>
+
+ * gcc.dg/tree-ssa/pr96789.c: Adjusted by disabling loop
+ vectorization.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/analyzer/setjmp-5.c: Update expected path output to show
+ an event where the pertinent stack frame is popped. Update
+ expected message from final event to reference this event.
+
+2020-11-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/97424
+ * gcc.dg/analyzer/invalid-shift-1.c: New test.
+
+2020-11-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ * g++.dg/abi/macro0.C: Adjust.
+ * g++.dg/cpp0x/alignof7.C: New test.
+ * g++.dg/cpp0x/alignof8.C: New test.
+
+2020-11-11 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ * g++.dg/cpp0x/alignof6.C: New test.
+
+2020-11-11 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97518
+ * g++.dg/diagnostic/static_assert3.C: New test.
+
+2020-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.dg/gomp/workshare-reduction-3.f90: Use (?:_ull)? instead
+ of (?:_ull) in the scan-tree-dump-times directives.
+ * gfortran.dg/gomp/workshare-reduction-26.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-27.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-28.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-36.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-37.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-38.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-39.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-40.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-41.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-42.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-43.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-44.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-45.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-46.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-47.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-56.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-57.f90: Likewise.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/bias2.adb: New test.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt89.adb: New test.
+
+2020-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/shift1.adb: New test.
+
+2020-11-11 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/97797
+ * gcc.dg/torture/ssa-fre-5.c: Use __SIZETYPE__ where
+ appropriate.
+ * gcc.dg/torture/ssa-fre-6.c: Likewise.
+
+2020-11-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97623
+ * gcc.dg/tree-ssa/ssa-hoist-3.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-hoist-7.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-pre-30.c: Likewise.
+
+2020-11-11 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/cmp_1.c: New test.
+ * gcc.target/aarch64/sve/cmp_2.c: Likewise.
+ * gcc.target/aarch64/sve/cond_arith_1.c: Add --param
+ aarch64-sve-compare-costs=0
+ * gcc.target/aarch64/sve/cond_arith_1_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_arith_3.c: Likewise.
+ * gcc.target/aarch64/sve/cond_arith_3_run.c: Likewise.
+ * gcc.target/aarch64/sve/mask_gather_load_7.c: Likewise.
+ * gcc.target/aarch64/sve/mask_load_slp_1.c: Likewise.
+ * gcc.target/aarch64/sve/vcond_11.c: Likewise.
+ * gcc.target/aarch64/sve/vcond_11_run.c: Likewise.
+
+2020-11-11 Hongtao Liu <hongtao.liu@intel.com>
+ Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/avx512vl-vnni-1.c: Rename..
+ * gcc.target/i386/avx512vl-vnni-1a.c: To This.
+ * gcc.target/i386/avx512vl-vnni-1b.c: New test.
+ * gcc.target/i386/avx512vl-vnni-2.c: Ditto.
+ * gcc.target/i386/avx512vl-vnni-3.c: Ditto.
+ * gcc.target/i386/avx-vnni-1.c: Ditto.
+ * gcc.target/i386/avx-vnni-2.c: Ditto.
+ * gcc.target/i386/avx-vnni-3.c: Ditto.
+ * gcc.target/i386/avx-vnni-4.c: Ditto.
+ * gcc.target/i386/avx-vnni-5.c: Ditto.
+ * gcc.target/i386/avx-vnni-6.c: Ditto.
+ * gcc.target/i386/avx-vpdpbusd-2.c: Ditto.
+ * gcc.target/i386/avx-vpdpbusds-2.c: Ditto.
+ * gcc.target/i386/avx-vpdpwssd-2.c: Ditto.
+ * gcc.target/i386/avx-vpdpwssds-2.c: Ditto.
+ * gcc.target/i386/vnni_inline_error.c: Ditto.
+ * gcc.target/i386/avx512vnnivl-builtin.c: Ditto.
+ * gcc.target/i386/avxvnni-builtin.c: Ditto.
+ * gcc.target/i386/funcspec-56.inc: Add new target attribute.
+ * gcc.target/i386/sse-12.c: Add -mavxvnni.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-14.c: Ditto.
+ * gcc.target/i386/sse-22.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * g++.dg/other/i386-2.C: Ditto.
+ * g++.dg/other/i386-3.C: Ditto.
+ * lib/target-supports.exp (check_effective_target_avxvnni):
+ New proc.
+
+2020-11-11 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/workshare-reduction-26.f90: Add (?:_ull) to
+ scan-tree-dump-times regex for -m32.
+ * gfortran.dg/gomp/workshare-reduction-27.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-28.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-3.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-36.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-37.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-38.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-39.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-40.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-41.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-42.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-43.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-44.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-45.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-46.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-47.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-56.f90: Likewise.
+ * gfortran.dg/gomp/workshare-reduction-57.f90: Likewise.
+
+2020-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/97768
+ * gfortran.dg/pr97768_1.f90: New test.
+ * gfortran.dg/pr97768_2.f90: New test.
+
+2020-11-11 Nagaraju Mekala <nmekala@xilinx.com>
+
+ * gcc.target/microblaze/others/strings1.c: Update
+ to include $LC label.
+
+2020-11-11 David Edelsohn <dje.gcc@gmail.com>
+
+ * c-c++-common/zero-scratch-regs-10.c: Skip on powerpc*-*-*.
+ * c-c++-common/zero-scratch-regs-11.c: Skip on powerpc*-*-*.
+ * c-c++-common/zero-scratch-regs-5.c: Skip on powerpc*-*-aix*.
+ * c-c++-common/zero-scratch-regs-8.c: Skip on powerpc*-*-*.
+ * c-c++-common/zero-scratch-regs-9.c: Skip on powerpc*-*-*.
+
+2020-11-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97518
+ * g++.dg/diagnostic/pr87386.C: Adjust expected output.
+ * g++.dg/diagnostic/static_assert1.C: New test.
+ * g++.dg/diagnostic/static_assert2.C: New test.
+
+2020-11-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/52830
+ PR c++/88982
+ PR c++/90799
+ PR c++/87765
+ PR c++/89565
+ * g++.dg/cpp0x/constexpr-52830.C: New test.
+ * g++.dg/cpp0x/vt-88982.C: New test.
+ * g++.dg/cpp1z/class-deduction76.C: New test.
+ * g++.dg/cpp1z/constexpr-lambda26.C: New test.
+ * g++.dg/cpp2a/nontype-class39.C: New test.
+
+2020-11-10 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/schedule-modifiers-2.f90: Remove some dg-error.
+ * gfortran.dg/gomp/reduction4.f90: New test.
+ * gfortran.dg/gomp/reduction5.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-1.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-2.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-3.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-4.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-5.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-6.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-7.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-8.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-9.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-10.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-11.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-12.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-13.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-14.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-15.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-16.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-17.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-18.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-19.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-20.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-21.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-22.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-23.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-24.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-25.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-26.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-27.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-28.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-29.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-30.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-31.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-32.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-33.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-34.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-35.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-36.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-37.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-38.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-39.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-40.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-41.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-42.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-43.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-44.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-45.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-46.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-47.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-48.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-49.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-50.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-51.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-52.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-53.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-54.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-55.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-56.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-57.f90: New test.
+ * gfortran.dg/gomp/workshare-reduction-58.f90: New test.
+
+2020-11-10 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * c-c++-common/ubsan/sanitize-recover-7.c: Update testcase.
+
+2020-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97748
+ * c-c++-common/Wunused-value-1.c: New test.
+
+2020-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97769
+ * gcc.dg/vect/pr97769.c: New testcase.
+
+2020-11-10 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-c++-common/gomp/clauses-2.c: Remove dg-error cases now valid.
+ * gfortran.dg/gomp/map-2.f90: Likewise.
+ * c-c++-common/gomp/map-5.c: New testcase.
+
+2020-11-10 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/vector/long-double-callee-abi-scan.c: New test.
+ * gcc.target/s390/vector/long-double-caller-abi-run.c: New test.
+ * gcc.target/s390/vector/long-double-caller-abi-scan.c: New test.
+ * gcc.target/s390/vector/long-double-copysign.c: New test.
+ * gcc.target/s390/vector/long-double-fprx2-constant.c: New test.
+ * gcc.target/s390/vector/long-double-from-double.c: New test.
+ * gcc.target/s390/vector/long-double-from-float.c: New test.
+ * gcc.target/s390/vector/long-double-from-i16.c: New test.
+ * gcc.target/s390/vector/long-double-from-i32.c: New test.
+ * gcc.target/s390/vector/long-double-from-i64.c: New test.
+ * gcc.target/s390/vector/long-double-from-i8.c: New test.
+ * gcc.target/s390/vector/long-double-from-u16.c: New test.
+ * gcc.target/s390/vector/long-double-from-u32.c: New test.
+ * gcc.target/s390/vector/long-double-from-u64.c: New test.
+ * gcc.target/s390/vector/long-double-from-u8.c: New test.
+ * gcc.target/s390/vector/long-double-to-double.c: New test.
+ * gcc.target/s390/vector/long-double-to-float.c: New test.
+ * gcc.target/s390/vector/long-double-to-i16.c: New test.
+ * gcc.target/s390/vector/long-double-to-i32.c: New test.
+ * gcc.target/s390/vector/long-double-to-i64.c: New test.
+ * gcc.target/s390/vector/long-double-to-i8.c: New test.
+ * gcc.target/s390/vector/long-double-to-u16.c: New test.
+ * gcc.target/s390/vector/long-double-to-u32.c: New test.
+ * gcc.target/s390/vector/long-double-to-u64.c: New test.
+ * gcc.target/s390/vector/long-double-to-u8.c: New test.
+ * gcc.target/s390/vector/long-double-vec-duplicate.c: New test.
+ * gcc.target/s390/vector/long-double-wf.h: New test.
+ * gcc.target/s390/vector/long-double-wfaxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfcxb-0001.c: New test.
+ * gcc.target/s390/vector/long-double-wfcxb-0111.c: New test.
+ * gcc.target/s390/vector/long-double-wfcxb-1011.c: New test.
+ * gcc.target/s390/vector/long-double-wfcxb-1101.c: New test.
+ * gcc.target/s390/vector/long-double-wfdxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfixb.c: New test.
+ * gcc.target/s390/vector/long-double-wfkxb-0111.c: New test.
+ * gcc.target/s390/vector/long-double-wfkxb-1011.c: New test.
+ * gcc.target/s390/vector/long-double-wfkxb-1101.c: New test.
+ * gcc.target/s390/vector/long-double-wflcxb.c: New test.
+ * gcc.target/s390/vector/long-double-wflpxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfmaxb-2.c: New test.
+ * gcc.target/s390/vector/long-double-wfmaxb-3.c: New test.
+ * gcc.target/s390/vector/long-double-wfmaxb-disabled.c: New test.
+ * gcc.target/s390/vector/long-double-wfmaxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfmsxb-disabled.c: New test.
+ * gcc.target/s390/vector/long-double-wfmsxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfmxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfnmaxb-disabled.c: New test.
+ * gcc.target/s390/vector/long-double-wfnmaxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfnmsxb-disabled.c: New test.
+ * gcc.target/s390/vector/long-double-wfnmsxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfsqxb.c: New test.
+ * gcc.target/s390/vector/long-double-wfsxb-1.c: New test.
+ * gcc.target/s390/vector/long-double-wfsxb.c: New test.
+ * gcc.target/s390/vector/long-double-wftcixb-1.c: New test.
+ * gcc.target/s390/vector/long-double-wftcixb.c: New test.
+
+2020-11-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt88.adb: New test.
+
+2020-11-10 David Candler <david.candler@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vqrshrn_high_n.c: Added skip
+ directive.
+ * gcc.target/aarch64/advsimd-intrinsics/vqrshrun_high_n.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vqshrn_high_n.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vqshrun_high_n.c: Likewise.
+
+2020-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97764
+ * gcc.c-torture/execute/pr97764.c: New test.
+
+2020-11-10 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/95847
+ * gfortran.dg/coverage.f90: New test.
+
+2020-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97760
+ * gcc.dg/vect/pr97760.c: New testcase.
+
+2020-11-10 Aldy Hernandez <aldyh@redhat.com>
+
+ * g++.dg/opt/pr97767.C: New test.
+
+2020-11-10 hongyuw1 <hongyuw1@intel.com>
+
+ * gcc.target/i386/keylocker-aesdec128kl.c: Adjust regex patterns.
+ * gcc.target/i386/keylocker-aesdec256kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesdecwide128kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesdecwide256kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesenc128kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesencwide128kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesencwide256kl.c: Likewise.
+ * gcc.target/i386/keylocker-encodekey128.c: Likewise.
+ * gcc.target/i386/keylocker-encodekey256.c: Likewise.
+ * gcc.target/i386/keylocker-aesenc256kl.c: New test.
+
+2020-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97567-2.c: New.
+
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ DR 1914
+ * c-c++-common/attr-fallthrough-2.c: Adjust dg-warning.
+ * g++.dg/cpp0x/fallthrough2.C: Likewise.
+ * g++.dg/cpp0x/gen-attrs-60.C: Turn dg-error into dg-warning.
+ * g++.dg/cpp1y/attr-deprecated-2.C: Likewise.
+ * g++.dg/cpp2a/attr-likely2.C: Adjust dg-warning.
+ * g++.dg/cpp2a/nodiscard-once.C: Turn dg-error into dg-warning.
+ * g++.dg/cpp0x/gen-attrs-72.C: New test.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/cpp2a/concepts-decltype2.C: New file.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/93907
+ * g++.dg/cpp2a/concepts-using3.C: New test, based off of
+ concepts-using2.C.
+
+2020-11-09 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/lookup/using26.C: Adjust location.
+ * g++.old-deja/g++.other/using1.C: Adjust location.
+
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97762
+ * g++.dg/warn/Wvexing-parse8.C: New test.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * gcc.dg/pragma-diag-6.c: Adjust expected diagnostics
+ accordingly.
+
+2020-11-09 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/90111
+ * gfortran.dg/goacc/specification-part.f90: New test.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97761
+ * gfortran.dg/vect/pr97761.f90: New testcase.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97753
+ * gcc.dg/vect/pr97753.c: New testcase.
+
+2020-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97746
+ * gcc.dg/vect/bb-slp-pr97746.c: New testcase.
+
+2020-11-09 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/simd/vld1_lane_bf16_1.c: Require target to
+ support and add -mfloat-abi=hard flag.
+ * gcc.target/arm/simd/vld1_lane_bf16_indices_1.c: Likewise.
+ * gcc.target/arm/simd/vld1q_lane_bf16_indices_1.c: Likewise.
+ * gcc.target/arm/simd/vst1_lane_bf16_1.c: Likewise.
+ * gcc.target/arm/simd/vst1_lane_bf16_indices_1.c: Likewise.
+ * gcc.target/arm/simd/vstq1_lane_bf16_indices_1.c: Likewise.
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/property/at-property-4.mm: Test handling class
+ attributes.
+ * objc.dg/property/at-property-4.m: Likewise.
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-c++-common/zero-scratch-regs-10.c: Skip for powerpc
+ Darwin.
+ * c-c++-common/zero-scratch-regs-11.c: Likewise.
+ * c-c++-common/zero-scratch-regs-8.c: Likewise.
+ * c-c++-common/zero-scratch-regs-9.c: Likewise.
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/builtin_thread_pointer.c: Require native TLS.
+
+2020-11-07 Marek Polacek <polacek@redhat.com>
+
+ * c-c++-common/Wimplicit-fallthrough-20.c: Adjust dg-warning.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/property/at-property-4.mm: Test atomic property
+ attribute.
+ * objc.dg/property/at-property-4.m: Likewise.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/attributes/nsobject-01.mm: New test.
+ * objc.dg/attributes/nsobject-01.m: New test.
+
+2020-11-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-c++-common/zero-scratch-regs-10.c: XFAIL for
+ powerpc-darwin.
+ * c-c++-common/zero-scratch-regs-11.c: Likewise.
+ * c-c++-common/zero-scratch-regs-8.c: Likewise.
+ * c-c++-common/zero-scratch-regs-9.c: Likewise.
+
+2020-11-07 Martin Uecker <muecker@gwdg.de>
+
+ * c-c++-common/attr-fallthrough-2.c: Update compiler flags.
+ * c-c++-common/Wimplicit-fallthrough-20.c: Adapt test.
+ * gcc.dg/20031223-1.c: Update compiler flags and adapt test.
+ * gcc.dg/c11-labels-1.c: New test.
+ * gcc.dg/c11-labels-2.c: New test.
+ * gcc.dg/c11-labels-3.c: New test.
+ * gcc.dg/c2x-attr-syntax-3.c: Adapt test.
+ * gcc.dg/c2x-labels-1.c: New test.
+ * gcc.dg/c2x-labels-2.c: New test.
+ * gcc.dg/c2x-labels-3.c: New test.
+ * gcc.dg/decl-9.c: Update compiler flags and add error.
+ * gcc.dg/gomp/barrier-2.c: Update compiler flags and add warning.
+ * gcc.dg/gomp/declare-simd-5.c: Update compiler flags and adapt test.
+ * gcc.dg/gomp/declare-variant-2.c: Update compiler flags and add error.
+ * gcc.dg/label-compound-stmt-1.c: Update compiler flags.
+ * gcc.dg/parse-decl-after-label.c: Update compiler flags.
+
+2020-11-06 Peter Bergner <bergner@linux.ibm.com>
+
+ * gcc.target/powerpc/pr64505.c: Run everywhere. Use correct minimized
+ test case.
+
+2020-11-06 Peter Bergner <bergner@linux.ibm.com>
+
+ * gcc.target/powerpc/mma-alignment.c: New test.
+
+2020-11-06 Jeff Law <law@torsion.usersys.redhat.com>
+
+ PR target/91489
+ * gcc.target/i386/ms_hook_prologue.c: Expand testcase
+ to reproduce PR target/91489 issue.
+
+2020-11-06 Joseph Myers <joseph@codesourcery.com>
+
+ * lib/target-supports.exp
+ (check_effective_target_fenv_exceptions_dfp): New.
+ * gcc.dg/dfp/builtin-snan-1.c, gcc.dg/dfp/builtin-snan-2.c: New
+ tests.
+
+2020-11-06 Marek Polacek <polacek@redhat.com>
+
+ PR c++/81660
+ * g++.dg/warn/Wexceptions3.C: New test.
+ * g++.dg/eh/pr42859.C: Add dg-warning.
+ * g++.dg/torture/pr81659.C: Likewise.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/property/at-property-1.mm: Adjust expected
+ diagnostics.
+ * obj-c++.dg/property/at-property-29.mm: Likewise.
+ * obj-c++.dg/property/at-property-4.mm: Likewise.
+ * obj-c++.dg/property/property-neg-2.mm: Likewise.
+ * objc.dg/property/at-property-1.m: Likewise.
+ * objc.dg/property/at-property-29.m: Likewise.
+ * objc.dg/property/at-property-4.m: Likewise.
+ * objc.dg/property/at-property-5.m: Likewise.
+ * objc.dg/property/property-neg-2.m: Likewise.
+
+2020-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/67453
+ * g++.dg/ext/attr-used-2.C: New test.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/darwin-minversion-link.c: Allow for Darwin19 (macOS 10.15)
+ and Darwin20 (macOS 11.0).
+
+2020-11-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97737.c: New.
+ * gcc.dg/pr97741.c: New.
+
+2020-11-06 David Candler <david.candler@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vqrshrn_high_n.c: New testcase.
+ * gcc.target/aarch64/advsimd-intrinsics/vqrshrun_high_n.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vqshrn_high_n.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vqshrun_high_n.c: Likewise.
+ * gcc.target/aarch64/narrow_high-intrinsics.c: Update expected assembler
+ for sqshrun2, sqrshrun2, sqshrn2, uqshrn2, sqrshrn2 and uqrshrn2.
+
+2020-11-06 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/dup_lane_2.c: New test.
+ * gcc.target/aarch64/sve/dup_lane_3.c: Likewise.
+ * gcc.target/aarch64/sve/ext_4.c: Likewise.
+ * gcc.target/aarch64/sve/rev_2.c: Likewise.
+ * gcc.target/aarch64/sve/revhw_1.c: Likewise.
+ * gcc.target/aarch64/sve/revhw_2.c: Likewise.
+ * gcc.target/aarch64/sve/slp_perm_8.c: Likewise.
+ * gcc.target/aarch64/sve/trn1_2.c: Likewise.
+ * gcc.target/aarch64/sve/trn2_2.c: Likewise.
+ * gcc.target/aarch64/sve/uzp1_2.c: Likewise.
+ * gcc.target/aarch64/sve/uzp2_2.c: Likewise.
+ * gcc.target/aarch64/sve/zip1_2.c: Likewise.
+ * gcc.target/aarch64/sve/zip2_2.c: Likewise.
+
+2020-11-06 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/tree-ssa/switch-4.c: New test.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97706
+ * gcc.dg/vect/bb-slp-pr97706.c: New testcase.
+
+2020-11-06 Kewen Lin <linkw@linux.ibm.com>
+
+ PR gcov-profile/97461
+ * gcc.dg/tree-prof/pr97461.c: Return aligned memory.
+
+2020-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/goacc/loop-2-parallel-3.f95: Adjust.
+
+2020-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/goacc/loop-6.f95: Remove.
+
+2020-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/goacc/loop-5.f95: Remove.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/goacc-gomp/goacc-gomp.exp: New.
+ * gfortran.dg/goacc-gomp/atomic.f90: New test.
+ * gfortran.dg/goacc/atomic.f90: New test.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-c++-common/goacc-gomp/atomic.c: New test.
+ * c-c++-common/goacc/atomic.c: New test.
+
+2020-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97732
+ * gcc.dg/vect/bb-slp-pr97732.c: New testcase.
+
+2020-11-06 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.target/i386/fentryname1.c: Add dg-require-profiling.
+ * gcc.target/i386/fentryname2.c: Likewise.
+ * gcc.target/i386/fentryname3.c: Likewise.
+ * gcc.target/i386/returninst1.c: Likewise.
+ * gcc.target/i386/returninst2.c: Likewise.
+ * gcc.target/i386/returninst3.c: Likewise.
+
+2020-11-06 Olivier Hainque <hainque@adacore.com>
+
+ * g++.dg/pr57878.C: Add dg-require-effective-target fpic.
+ * g++.dg/pr65032.C: Likewise.
+ * g++.dg/pr84279.C: Likewise.
+ * g++.dg/inherit/thunk8.C: Likewise.
+ * g++.dg/opt/pr64411.C: Likewise.
+
+2020-11-06 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/ipa/modref-2.c: New test.
+ * gcc.dg/lto/modref-2_0.c: New test.
+
+2020-11-06 Jeff Law <law@redhat.com>
+
+ * gcc.dg/no-strict-overflow-4.c: Adjust expected output.
+
+2020-11-06 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * gcc.dg/self-right-shift.c: New test.
+
+2020-11-06 Kito Cheng <kito.cheng@sifive.com>
+
+ PR target/96307
+ * gcc.dg/pr96307.c: New.
+ * gcc.target/riscv/pr96260.c: Move this test case from here to ...
+ * gcc.dg/pr96260.c: ... here.
+ * gcc.target/riscv/pr91441.c: Move this test case from here to ...
+ * gcc.dg/pr91441.c: ... here.
+ * lib/target-supports.exp (check_effective_target_no_fsanitize_address):
+ New proc.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/78209
+ * g++.dg/cpp1y/decltype-auto1.C: New test.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97675
+ * g++.old-deja/g++.eh/catch10.C: Adjust dg-warning.
+ * g++.dg/warn/Wexceptions1.C: New test.
+ * g++.dg/warn/Wexceptions2.C: New test.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/25814
+ * g++.dg/cpp2a/fn-template16.C: Add a dg-warning.
+ * g++.dg/cpp2a/fn-template7.C: Likewise.
+ * g++.dg/lookup/pr80891-5.C: Likewise.
+ * g++.dg/lto/pr79050_0.C: Add extern.
+ * g++.dg/lto/pr84805_0.C: Likewise.
+ * g++.dg/parse/pr58898.C: Add a dg-warning.
+ * g++.dg/template/scope5.C: Likewise.
+ * g++.old-deja/g++.brendan/recurse.C: Likewise.
+ * g++.old-deja/g++.jason/template4.C: Likewise.
+ * g++.old-deja/g++.law/arm4.C: Likewise.
+ * g++.old-deja/g++.mike/for2.C: Likewise.
+ * g++.old-deja/g++.other/local4.C: Likewise.
+ * g++.old-deja/g++.pt/crash3.C: Likewise.
+ * g++.dg/warn/Wvexing-parse.C: New test.
+ * g++.dg/warn/Wvexing-parse2.C: New test.
+ * g++.dg/warn/Wvexing-parse3.C: New test.
+ * g++.dg/warn/Wvexing-parse4.C: New test.
+ * g++.dg/warn/Wvexing-parse5.C: New test.
+ * g++.dg/warn/Wvexing-parse6.C: New test.
+ * g++.dg/warn/Wvexing-parse7.C: New test.
+
+2020-11-05 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97725.c: New.
+
+2020-11-05 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.dg/sms-12.c: Add dg-require-effective-target fpic.
+
+2020-11-05 Jan Hubicka <jh@suse.cz>
+
+ * g++.dg/ipa/devirt-24.C: Update template.
+
+2020-11-05 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/vect/slp-11b.c: Guard statements.
+
+2020-11-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/pr97721.c: New test.
+
+2020-11-05 qing zhao <qinzhao@gcc.gnu.org>
+
+ PR target/97715
+ * gcc.target/i386/zero-scratch-regs-32.c: New test.
+
+2020-11-05 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97668
+ * gcc.dg/analyzer/pr97668.c: New test.
+ * gfortran.dg/analyzer/pr97668.f: New test.
+
+2020-11-05 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-69.c: New testcase.
+
+2020-11-05 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/vect/slp-11b.c: Update testcase.
+ * gcc.dg/vect/slp-perm-6.c: Update target selector.
+
+2020-11-05 Kewen Lin <linkw@linux.ibm.com>
+
+ PR target/96933
+ * gcc.target/powerpc/pr96933-1.c: New test.
+ * gcc.target/powerpc/pr96933-2.c: New test.
+ * gcc.target/powerpc/pr96933-3.c: New test.
+ * gcc.target/powerpc/pr96933-4.c: New test.
+ * gcc.target/powerpc/pr96933.h: New test.
+ * gcc.target/powerpc/pr96933-run.h: New test.
+
+2020-11-04 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/vect/slp-11b.c: Update output scan.
+ * gcc.dg/vect/slp-perm-6.c: Likewise.
+
+2020-11-04 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97515.c: Check listing for folding of entire function.
+
+2020-11-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97709
+ * gcc.dg/vect/bb-slp-pr97709.c: New testcase.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97690
+ * gcc.dg/tree-ssa/phi-opt-22.c: New test.
+ * gcc.dg/tree-ssa/ssa-ccp-11.c: Use -O2 instead of -O1.
+ * gcc.dg/vect/bb-slp-pattern-2.c (foo): Use ? 2 : 7, ? 4 : 7 and
+ ? 8 : 7 instead of ? 2 : 0, ? 4 : 0, ? 8 : 0.
+
+2020-11-04 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/pure-code/no-literal-pool-m0.c: Add dg-skip-if
+ and -mfloat-abi=soft option.
+ * gcc.target/arm/pure-code/no-literal-pool-m23.c: Likewise.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97670
+ * c-c++-common/gomp/allocate-4.c: New test.
+ * g++.dg/gomp/allocate-2.C: New test.
+ * g++.dg/gomp/allocate-3.C: New test.
+
+2020-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c2x-attr-nodiscard-1.c, gcc.dg/c2x-attr-nodiscard-2.c,
+ gcc.dg/c2x-attr-nodiscard-3.c, gcc.dg/c2x-attr-nodiscard-4.c: New
+ tests.
+ * gcc.dg/c2x-attr-syntax-5.c: Remove nodiscard test.
+
+2020-11-04 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr97540.c: New test.
+
+2020-11-03 Jan Hubicka <jh@suse.cz>
+
+ * gcc.c-torture/execute/pr97695.c: New test.
+
+2020-11-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/Wclass-memaccess.C: Check that signed char and
+ char16_t aren't treated as byte-access types.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/pr92793-1.c: Extend.
+ * gfortran.dg/goacc/pr92793-1.f90: Likewise.
+
+2020-11-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97663
+ * g++.dg/cpp1z/class-deduction75.C: New test.
+
+2020-11-03 Kamlesh Kumar <kamleshbhalui@gmail.com>
+
+ * g++.dg/DRs/dr2303.C: New test.
+
+2020-11-03 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.target/powerpc/pr67789.c: Add
+ dg-require-effective-target fpic.
+ * gcc.target/powerpc/pr83629.c: Likewise.
+ * gcc.target/powerpc/pr84112.c: Likewise. Remove
+ a superflous target test in the dg-do compile
+ directive while at it.
+
+2020-11-03 Dennis Zhang <dennis.zhang@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_get.c: New test.
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_get-be.c: New test.
+
+2020-11-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97632
+ * g++.dg/warn/Winit-list4.C: New test.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vst2_lane_bf16_indices_1.c:
+ Run it also for arm-*-*.
+ * gcc.target/aarch64/advsimd-intrinsics/vst2q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst3_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst3q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst4_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst4q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/arm/simd/vstn_lane_bf16_1.c: New test.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vld2_lane_bf16_indices_1.c:
+ Run it also for the arm backend.
+ * gcc.target/aarch64/advsimd-intrinsics/vld2q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld3_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld3q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld4_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld4q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/arm/simd/vldn_lane_bf16_1.c: New test.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/simd/vst1_bf16_1.c: New test.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/simd/vld1_bf16_1.c: New test.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/simd/vst1_lane_bf16_1.c: New testcase.
+ * gcc.target/arm/simd/vstq1_lane_bf16_indices_1.c: Likewise.
+ * gcc.target/arm/simd/vst1_lane_bf16_indices_1.c: Likewise.
+
+2020-11-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/arm/simd/vld1_lane_bf16_1.c: New testcase.
+ * gcc.target/arm/simd/vld1_lane_bf16_indices_1.c: Likewise.
+ * gcc.target/arm/simd/vld1q_lane_bf16_indices_1.c: Likewise.
+
+2020-11-03 Dennis Zhang <dennis.zhang@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/bfcvt-compile.c
+ (test_vcvt_f32_bf16, test_vcvtq_low_f32_bf16): New tests.
+ (test_vcvtq_high_f32_bf16, test_vcvth_f32_bf16): Likewise.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/80928
+ * gcc.dg/vect/vect-outer-slp-2.c: New testcase.
+ * gcc.dg/vect/vect-outer-slp-3.c: Likewise.
+
+2020-11-03 Uroš Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/zero-scratch-regs-1.c: Add ia32 target
+ selector where appropriate. Improve scan-assembler regexp.
+ * gcc.target/i386/zero-scratch-regs-2.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-3.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-4.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-5.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-6.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-7.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-8.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-9.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-10.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-13.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-14.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-15.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-16.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-17.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-18.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-19.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-20.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-21.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-22.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-23.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-24.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-25.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-26.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-27.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-28.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-29.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-30.c: Ditto.
+ * gcc.target/i386/zero-scratch-regs-31.c: Ditto.
+
+2020-11-03 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.dg/tree-ssa/pr71077.c: Add
+ dg-require-effective-target lto.
+
+2020-11-03 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.target/i386/pr45352-1.c: Add dg-require-effective-target fpic.
+ * gcc.target/i386/pr47602.c: Likewise.
+ * gcc.target/i386/pr55151.c: Likewise.
+ * gcc.target/i386/pr55458.c: Likewise.
+ * gcc.target/i386/pr56348.c: Likewise.
+ * gcc.target/i386/pr57097.c: Likewise.
+ * gcc.target/i386/pr65753.c: Likewise.
+ * gcc.target/i386/pr65915.c: Likewise.
+ * gcc.target/i386/pr66232-5.c: Likewise.
+ * gcc.target/i386/pr66334.c: Likewise.
+ * gcc.target/i386/pr66819-2.c: Likewise.
+ * gcc.target/i386/pr67265.c: Likewise.
+ * gcc.target/i386/pr81481.c: Likewise.
+ * gcc.target/i386/pr83994.c: Likewise.
+
+2020-11-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.c-torture/compile/pr97578.c: New test.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/97688
+ * gcc.dg/vect/tree-vect.h (check_vect): Fix the x86 cpuid
+ check to always specify subleaf zero.
+
+2020-11-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97678
+ * gcc.dg/vect/pr97678.c: New testcase.
+
+2020-11-03 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/attr_deprecated.f90: New test.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/nested-reductions-1-kernels.c: Extend.
+ * c-c++-common/goacc/nested-reductions-2-kernels.c: Likewise.
+ * gfortran.dg/goacc/nested-reductions-1-kernels.f90: Likewise.
+ * gfortran.dg/goacc/nested-reductions-2-kernels.f90: Likewise.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/nested-reductions.c: Split file into...
+ * c-c++-common/goacc/nested-reductions-1-kernels.c: ... this...
+ * c-c++-common/goacc/nested-reductions-1-parallel.c: ..., this...
+ * c-c++-common/goacc/nested-reductions-1-routine.c: ..., and this.
+ * c-c++-common/goacc/nested-reductions-warn.c: Split file into...
+ * c-c++-common/goacc/nested-reductions-2-kernels.c: ... this...
+ * c-c++-common/goacc/nested-reductions-2-parallel.c: ..., this...
+ * c-c++-common/goacc/nested-reductions-2-routine.c: ..., and this.
+ * gfortran.dg/goacc/nested-reductions.f90: Split file into...
+ * gfortran.dg/goacc/nested-reductions-1-kernels.f90: ... this...
+ * gfortran.dg/goacc/nested-reductions-1-parallel.f90: ..., this...
+ * gfortran.dg/goacc/nested-reductions-1-routine.f90: ..., and
+ this.
+ * gfortran.dg/goacc/nested-reductions-warn.f90: Split file into...
+ * gfortran.dg/goacc/nested-reductions-2-kernels.f90: ... this...
+ * gfortran.dg/goacc/nested-reductions-2-parallel.f90: ..., this...
+ * gfortran.dg/goacc/nested-reductions-2-routine.f90: ..., and
+ this.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/92793
+ * gfortran.dg/goacc/pr92793-1.f90: Adjust.
+
+2020-11-03 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/goacc/pr92793-1.c: Extend.
+ * gfortran.dg/goacc/pr92793-1.f90: Likewise.
+
+2020-11-03 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR tree-optimization/96789
+ * gcc.dg/tree-ssa/ssa-dse-28.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-dse-29.c: Likewise.
+ * gcc.dg/vect/bb-slp-41.c: Likewise.
+ * gcc.dg/tree-ssa/pr96789.c: New test.
+
+2020-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR target/97205
+ * gcc.c-torture/compile/pr97205.c: New test.
+
+2020-11-02 Alan Modra <amodra@gmail.com>
+
+ PR middle-end/97267
+ * gcc.target/powerpc/pr97267.c: New test.
+
+2020-11-02 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/97140
+ * gcc.target/i386/pr97140.c: New test.
+
+2020-11-02 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/cpp2a/concepts-complete1.C: Delete test that became
+ ill-formed after P2104.
+
+2020-11-02 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/bcd-2.c: Add include altivec.h.
+ * gcc.target/powerpc/bcd-3.c: Add include altivec.h.
+ * gcc.target/powerpc/bcd-4.c: New test.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/concepts/pack-1.C: New.
+ * g++.dg/lookup/using53.C: Add an enum.
+ * g++.dg/template/error25.C: Relax 'export' error check.
+
+2020-11-02 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/97638
+ * gcc.target/aarch64/pr97638.c: New test.a
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/slp-49.c: New testcase.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/pure-code/no-literal-pool-m23.c: New.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/pure-code/no-literal-pool-m0.c: New.
+
+2020-11-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/92793
+ * gfortran.dg/goacc/pr92793-1.f90: Adjust.
+
+2020-11-02 Tobias Burnus <tobias@codesourcery.com>
+
+ PR fortran/97655
+ * gfortran.dg/gomp/atomic.f90: Update tree-dump counts; move
+ invalid OMP 5.0 code to ...
+ * gfortran.dg/gomp/atomic-2.f90: ... here; update dg-error.
+ * gfortran.dg/gomp/requires-9.f90: Update tree dump scan.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97558
+ * gcc.dg/vect/pr97558-2.c: New testcase.
+
+2020-11-02 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/97505
+ * gcc.dg/pr97505.c: New test.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97558
+ * gcc.dg/vect/pr97558.c: New testcase.
+
+2020-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97650
+ * gcc.dg/vect/bb-slp-pr97650.c: New testcase.
+
+2020-11-02 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.target/riscv/arch-7.c: New.
+ * gcc.target/riscv/attribute-10.c: Update test arch string.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR target/96770
+ * gcc.target/arm/pure-code/pr96770.c: New test.
+
+2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR target/96967
+ * gcc.target/arm/pure-code/pr96767.c: New test.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/SEL-typedef.mm: New test.
+ * objc.dg/SEL-typedef.m: New test.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/property/at-property-1.mm: Adjust test after
+ fixing spurious error output.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/amxbf16-asmintel-1.c: Require masm_intel.
+ * gcc.target/i386/amxint8-asmintel-1.c: Likewise.
+ * gcc.target/i386/amxtile-asmintel-1.c: Likewise.
+
+2020-10-30 Qing Zhao <qing.zhao@oracle.com>
+ H.J.Lu <hjl.tools@gmail.com>
+
+ * c-c++-common/zero-scratch-regs-1.c: New test.
+ * c-c++-common/zero-scratch-regs-10.c: New test.
+ * c-c++-common/zero-scratch-regs-11.c: New test.
+ * c-c++-common/zero-scratch-regs-2.c: New test.
+ * c-c++-common/zero-scratch-regs-3.c: New test.
+ * c-c++-common/zero-scratch-regs-4.c: New test.
+ * c-c++-common/zero-scratch-regs-5.c: New test.
+ * c-c++-common/zero-scratch-regs-6.c: New test.
+ * c-c++-common/zero-scratch-regs-7.c: New test.
+ * c-c++-common/zero-scratch-regs-8.c: New test.
+ * c-c++-common/zero-scratch-regs-9.c: New test.
+ * c-c++-common/zero-scratch-regs-attr-usages.c: New test.
+ * gcc.target/i386/zero-scratch-regs-1.c: New test.
+ * gcc.target/i386/zero-scratch-regs-10.c: New test.
+ * gcc.target/i386/zero-scratch-regs-11.c: New test.
+ * gcc.target/i386/zero-scratch-regs-12.c: New test.
+ * gcc.target/i386/zero-scratch-regs-13.c: New test.
+ * gcc.target/i386/zero-scratch-regs-14.c: New test.
+ * gcc.target/i386/zero-scratch-regs-15.c: New test.
+ * gcc.target/i386/zero-scratch-regs-16.c: New test.
+ * gcc.target/i386/zero-scratch-regs-17.c: New test.
+ * gcc.target/i386/zero-scratch-regs-18.c: New test.
+ * gcc.target/i386/zero-scratch-regs-19.c: New test.
+ * gcc.target/i386/zero-scratch-regs-2.c: New test.
+ * gcc.target/i386/zero-scratch-regs-20.c: New test.
+ * gcc.target/i386/zero-scratch-regs-21.c: New test.
+ * gcc.target/i386/zero-scratch-regs-22.c: New test.
+ * gcc.target/i386/zero-scratch-regs-23.c: New test.
+ * gcc.target/i386/zero-scratch-regs-24.c: New test.
+ * gcc.target/i386/zero-scratch-regs-25.c: New test.
+ * gcc.target/i386/zero-scratch-regs-26.c: New test.
+ * gcc.target/i386/zero-scratch-regs-27.c: New test.
+ * gcc.target/i386/zero-scratch-regs-28.c: New test.
+ * gcc.target/i386/zero-scratch-regs-29.c: New test.
+ * gcc.target/i386/zero-scratch-regs-30.c: New test.
+ * gcc.target/i386/zero-scratch-regs-31.c: New test.
+ * gcc.target/i386/zero-scratch-regs-3.c: New test.
+ * gcc.target/i386/zero-scratch-regs-4.c: New test.
+ * gcc.target/i386/zero-scratch-regs-5.c: New test.
+ * gcc.target/i386/zero-scratch-regs-6.c: New test.
+ * gcc.target/i386/zero-scratch-regs-7.c: New test.
+ * gcc.target/i386/zero-scratch-regs-8.c: New test.
+ * gcc.target/i386/zero-scratch-regs-9.c: New test.
+
+2020-10-30 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97556
+ * gcc.dg/Warray-bounds-70.c: New test.
+
+2020-10-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * g++.dg/guality/guality.exp: Skip $rootme-based check if unset.
+ * gcc.dg/guality/guality.exp: Likewise.
+ * gfortran.dg/guality/guality.exp: Likewise.
+ * lib/asan-dg.exp: Don't use $asan_saved_library_path if not set.
+ * lib/tsan-dg.exp: Don't use $tsan_saved_library_path if not set.
+ * lib/ubsan-dg.exp: Don't use $ubsan_saved_library_path if not set.
+
+2020-10-30 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/atomic-2.f90: New test.
+ * gfortran.dg/gomp/atomic.f90: New test.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97623
+ * gcc.dg/tree-ssa/ssa-hoist-7.c: New testcase.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97626
+ * gcc.dg/vect/bb-slp-pr97626.c: New testcase.
+
+2020-10-30 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/92793
+ * c-c++-common/goacc/clause-locations.c: Rewrite into...
+ * c-c++-common/goacc/pr92793-1.c: ... this.
+ * gfortran.dg/goacc/clause-locations.f90: Rewrite into...
+ * gfortran.dg/goacc/pr92793-1.f90: ... this.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97633
+ * g++.dg/vect/slp-pr97636.cc: New testcase.
+ * gcc.dg/vect/bb-slp-pr97633.c: Likewise.
+
+2020-10-30 Alex Coplan <alex.coplan@arm.com>
+
+ PR target/96998
+ * gcc.c-torture/compile/pr96998.c: New test.
+
+2020-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/allocate-3.c: New test.
+
+2020-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/allocate-1.c (qux): Add another test.
+ * g++.dg/gomp/allocate-1.C: New test.
+
+2020-10-30 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-pr65935.c: Adjust.
+
+2020-10-30 Michael Meissner <meissner@linux.ibm.com>
+
+ * gcc.target/powerpc/float128-mix-2.c: New test.
+ * gcc.target/powerpc/float128-mix-3.c: New test.
+ * gcc.target/powerpc/float128-mix.c: Update failure messages.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ DR 625
+ PR c++/97479
+ * g++.dg/cpp0x/auto3.C: Update dg-error.
+ * g++.dg/cpp0x/auto9.C: Likewise.
+ * g++.dg/cpp2a/concepts-pr84979-2.C: Likewise.
+ * g++.dg/cpp2a/concepts-pr84979-3.C: Likewise.
+ * g++.dg/cpp2a/concepts-pr84979.C: Likewise.
+ * g++.dg/DRs/dr625.C: New test.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ PR c++/93107
+ * g++.dg/cpp0x/initlist-deduce3.C: New test.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp2a/enum-conv1.C: Remove unused code.
+ * g++.dg/cpp2a/spaceship-err5.C: New test.
+
+2020-10-29 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97412
+ * g++.dg/cpp2a/concepts-variadic2.C: New test.
+
+2020-10-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/97388
+ * g++.dg/cpp2a/constexpr-dtor8.C: New test.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/97388
+ * g++.dg/cpp2a/constexpr-dtor5.C: New test.
+ * g++.dg/cpp2a/constexpr-dtor6.C: New test.
+ * g++.dg/cpp2a/constexpr-dtor7.C: New test.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/95808
+ * g++.dg/cpp2a/constexpr-new15.C: New test.
+
+2020-10-29 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c11-bool-1.c, gcc.dg/c2x-bool-1.c, gcc.dg/c99-bool-4.c:
+ New tests.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/pr97596.c: Require int128 effective target.
+
+2020-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97596.c: New.
+
+2020-10-29 Alexandre Oliva <oliva@adacore.com>
+
+ * gnat.dg/sin_cos.ads: New.
+ * gnat.dg/sin_cos.adb: New.
+ * gcc.dg/sin_cos.c: New.
+
+2020-10-29 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/keylocker-aesdec128kl.c: New test.
+ * gcc.target/i386/keylocker-aesdec256kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesdecwide128kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesdecwide256kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesenc128kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesencwide128kl.c: Likewise.
+ * gcc.target/i386/keylocker-aesencwide256kl.c: Likewise.
+ * gcc.target/i386/keylocker-encodekey128.c: Likewise.
+ * gcc.target/i386/keylocker-encodekey256.c: Likewise.
+ * gcc.target/i386/keylocker-loadiwkey.c: Likewise.
+ * g++.dg/other/i386-2.C: Add -mkl and -mwidekl.
+ * g++.dg/other/i386-3.C: Likewise.
+ * gcc.target/i386/sse-12.c: Likewise.
+ * gcc.target/i386/sse-13.c: Likewise.
+ * gcc.target/i386/sse-14.c: Likewise.
+ * gcc.target/i386/sse-22.c: Add kl and widekl.
+ * gcc.target/i386/sse-23.c: Likewise.
+ * gcc.target/i386/funcspec-56.inc: Add new target attribute test.
+
+2020-10-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-pr65935.c: Adjust.
+
+2020-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ * g++.dg/pr97609.C: New.
+
+2020-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97608
+ * gcc.dg/analyzer/malloc-1.c (test_42d): New.
+ * gcc.dg/analyzer/pr97608.c: New test.
+
+2020-10-28 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/vsx-load-element-extend-char.c: Put "dg-do run"
+ before "dg-do compile", and make them mutually exclusive.
+ * gcc.target/powerpc/vsx-load-element-extend-int.c: Likewise.
+ * gcc.target/powerpc/vsx-load-element-extend-longlong.c: Likewise.
+ * gcc.target/powerpc/vsx-load-element-extend-short.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-char.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-int.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-longlong.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-short.c: Likewise.
+ * gcc.target/powerpc/altivec-consts.c: Likewise, add -save-temps.
+ * gcc.target/powerpc/le-altivec-consts.c: Likewise.
+
+2020-10-28 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/float128-type-1.c: Simplify target test.
+ * gcc.target/powerpc/float128-type-2.c: Likewise.
+
+2020-10-28 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/fold-vec-extract-char.p9.c: Don't check addi
+ count for ilp32.
+ * gcc.target/powerpc/fold-vec-extract-int.p9.c: Likewise.
+ * gcc.target/powerpc/fold-vec-extract-longlong.p7.c: Likewise.
+ * gcc.target/powerpc/fold-vec-extract-longlong.p8.c: Likewise.
+ * gcc.target/powerpc/fold-vec-insert-int-p9.c: Likewise.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/warn/mvp3.C: New test.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * g++.dg/cpp0x/linkage2.C: Add dg-warning.
+ * g++.dg/parse/attr3.C: Likewise.
+ * g++.dg/cpp2a/enum-conv1.C: New test.
+ * g++.dg/cpp2a/enum-conv2.C: New test.
+ * g++.dg/cpp2a/enum-conv3.C: New test.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/96675
+ PR c++/96742
+ * g++.dg/warn/Wdiv-by-zero-3.C: Turn dg-warning into dg-bogus.
+ * g++.dg/warn/Wtautological-compare3.C: New test.
+ * g++.dg/warn/Wtype-limits5.C: New test.
+ * g++.old-deja/g++.pt/crash10.C: Remove dg-warning.
+
+2020-10-28 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.target/powerpc/sad-vectorize-1.c: Remove AIX skip.
+ * gcc.target/powerpc/sad-vectorize-2.c: Remove AIX skip.
+ * gcc.target/powerpc/sad-vectorize-3.c: Remove target.
+ Require p9vector_hw.
+ * gcc.target/powerpc/sad-vectorize-4.c: Remove target.
+ Require p9vector_hw.
+ * gcc.target/powerpc/signbit-1.c: Remove target.
+ Require ppc_float128_sw.
+ * gcc.target/powerpc/signbit-2.c: Remove target.
+ Require ppc_float128_sw.
+ * gcc.target/powerpc/signbit-3.c: Remove target.
+ Require ppc_float128_sw.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94799
+ * g++.dg/template/lookup16.C: New test.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86773
+ * g++.dg/cpp1z/fold12.C: New test.
+
+2020-10-28 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/97535
+ * gcc.target/aarch64/pr97535.c: Exclude ILP32.
+
+2020-10-28 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/97457
+ * gcc.dg/vect/pr97457.c: New test.
+
+2020-10-28 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c11-parm-omit-1.c, gcc.dg/c11-parm-omit-2.c,
+ gcc.dg/c11-parm-omit-3.c, gcc.dg/c11-parm-omit-4.c,
+ gcc.dg/c2x-parm-omit-1.c, gcc.dg/c2x-parm-omit-2.c,
+ gcc.dg/c2x-parm-omit-3.c, gcc.dg/c2x-parm-omit-4.c: New tests.
+ * gcc.dg/noncompile/pr79758.c: Do not expect error for omitted
+ parameter name.
+
+2020-10-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95132
+ * g++.dg/cpp2a/concepts-fn7.C: New test.
+
+2020-10-28 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.target/powerpc/vadsdu-0.c: Remove target.
+ * gcc.target/powerpc/vadsdu-1.c: Remove target.
+ * gcc.target/powerpc/vadsdu-2.c: Remove target.
+ * gcc.target/powerpc/vadsdu-3.c: Remove target.
+ * gcc.target/powerpc/vadsdu-4.c: Remove target.
+ * gcc.target/powerpc/vadsdu-5.c: Remove target.
+ * gcc.target/powerpc/vadsdub-1.c: Remove target.
+ * gcc.target/powerpc/vadsdub-2.c: Remove target.
+ * gcc.target/powerpc/vadsduh-1.c: Remove target.
+ * gcc.target/powerpc/vadsduh-2.c: Remove target.
+ * gcc.target/powerpc/vadsduw-1.c: Remove target.
+ * gcc.target/powerpc/vadsduw-2.c: Remove target.
+ * gcc.target/powerpc/vslv-0.c: Remove target.
+ * gcc.target/powerpc/vslv-1.c: Remove target.
+ * gcc.target/powerpc/vsrv-0.c: Remove target.
+ * gcc.target/powerpc/vsrv-1.c: Remove target.
+
+2020-10-28 David Edelsohn <dje.gcc@gmail.com>
+ Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/byte-in-either-range-0.c: Remove target.
+ * gcc.target/powerpc/byte-in-either-range-1.c: Remove target.
+ * gcc.target/powerpc/byte-in-range-0.c: Remove target.
+ * gcc.target/powerpc/byte-in-range-1.c: Remove target.
+ * gcc.target/powerpc/byte-in-set-0.c: Remove target.
+ * gcc.target/powerpc/byte-in-set-1.c: Remove target.
+ * gcc.target/powerpc/byte-in-set-2.c: Remove target. Expect
+ implicit declaration warning.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-58.c: Require vect_double.
+ * gcc.dg/vect/bb-slp-59.c: Likewise.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97615
+ * gcc.dg/vect/bb-slp-pr97615.c: New testcase.
+
+2020-10-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-68.c: New testcase.
+
+2020-10-28 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/arm-neon-ref.h
+ (hbfloat16_t): Define type.
+ (CHECK_FP): Make it working for bfloat types.
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_1.c: New file.
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_2.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst2_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst2q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst3_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst3q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst4_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst4q_lane_bf16_indices_1.c:
+ Likewise.
+
+2020-10-28 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_1.c: New
+ testcase.
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_2.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld2_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld2q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld3_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld3q_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld4_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld4q_lane_bf16_indices_1.c:
+ Likewise.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/allocate-1.c: New test.
+ * c-c++-common/gomp/allocate-2.c: New test.
+ * c-c++-common/gomp/clauses-1.c (omp_allocator_handle_t): New typedef.
+ (foo, bar, baz): Add allocate clauses where allowed.
+
+2020-10-28 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/vsx-load-element-extend-char.c: Add -save-temps.
+ * gcc.target/powerpc/vsx-load-element-extend-int.c: Likewise.
+ * gcc.target/powerpc/vsx-load-element-extend-longlong.c: Likewise.
+ * gcc.target/powerpc/vsx-load-element-extend-short.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-char.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-int.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-longlong.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-short.c: Likewise.
+
+2020-10-28 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/vec-blend-runnable.c: Add save-temps.
+ * gcc.target/powerpc/vec-insert-word-runnable.c: Likewise.
+ * gcc.target/powerpc/vec-permute-ext-runnable.c: Likewise.
+ * gcc.target/powerpc/vec-replace-word-runnable.c: Likewise.
+ * gcc.target/powerpc/vec-splati-runnable.c: Likewise.
+ * gcc.target/powerpc/vec-ternarylogic-3.c: Likewise.
+ * gcc.target/powerpc/vec-ternarylogic-9.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-count-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-expand-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-extract-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-move-runnable.c: Likewise.
+ * gcc.target/powerpc/vec-shift-double-runnable.c: Likewise,
+ and correct assembly match.
+
+2020-10-27 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c2x-attr-deprecated-4.c, gcc.dg/c2x-attr-fallthrough-4.c,
+ gcc.dg/c2x-attr-maybe_unused-4.c: Allow duplicate attributes.
+
+2020-10-27 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/pr97497.c: New test.
+
+2020-10-27 Harald Anlauf <anlauf@gmx.de>
+
+ * gfortran.dg/value_8.f90: New test.
+
+2020-10-27 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/vec-blend-runnable.c: Change #ifdef
+ DEBUG to #if DEBUG.
+ Fix printf line so it is less then 80 characters long.
+ * gcc.target/powerpc/vec-insert-word-runnable.c: Change
+ #ifdef DEBUG to #if DEBUG.
+ * gcc.target/powerpc/vec-permute-ext-runnable.c: Change
+ #ifdef DEBUG to #if DEBUG.
+ * gcc.target/powerpc/vec-replace-word-runnable.c: Change
+ #ifdef DEBUG to #if DEBUG.
+ Fix printf lines so they are less then 80 characters long.
+ * gcc.target/powerpc/vec-shift-double-runnable.c: Change
+ #ifdef DEBUG to #if DEBUG.
+
+2020-10-27 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/97535
+ * gcc.target/aarch64/pr97535.c: New test.
+
+2020-10-27 Andrea Corallo <andrea.corallo@arm.com>
+
+ * gcc.target/aarch64/advsimd-intrinsics/bf16_vect_copy_lane_1.c:
+ New test.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_2.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_2.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_2.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_1.c:
+ Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_2.c:
+ Likewise.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-67.c: New testcase.
+
+2020-10-27 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/92942
+ * gcc.dg/Wstringop-overflow-56.c: New test.
+ * gcc.dg/Wstringop-overflow-57.c: Same.
+
+2020-10-27 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/Wstringop-overflow-44.s: Remove.
+
+2020-10-27 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97567.c: Update to work with 32 bit targets.
+
+2020-10-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/97568
+ * gcc.dg/analyzer/pr97568.c: New test.
+
+2020-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/97560
+ PR testsuite/97590
+ * g++.dg/pr97560.C: Require c++11 effective target and add comment
+ with PR number.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-54.c: New test.
+ * gcc.dg/vect/bb-slp-55.c: Likewise.
+ * gcc.dg/vect/bb-slp-56.c: Likewise.
+ * gcc.dg/vect/bb-slp-57.c: Likewise.
+ * gcc.dg/vect/bb-slp-58.c: Likewise.
+ * gcc.dg/vect/bb-slp-59.c: Likewise.
+ * gcc.dg/vect/bb-slp-60.c: Likewise.
+ * gcc.dg/vect/bb-slp-61.c: Likewise.
+ * gcc.dg/vect/bb-slp-62.c: Likewise.
+ * gcc.dg/vect/bb-slp-63.c: Likewise.
+ * gcc.dg/vect/bb-slp-64.c: Likewise.
+ * gcc.dg/vect/bb-slp-65.c: Likewise.
+ * gcc.dg/vect/bb-slp-66.c: Likewise.
+ * gcc.dg/vect/vect-outer-slp-1.c: Likewise.
+ * gfortran.dg/vect/O3-bb-slp-1.f: Likewise.
+ * gfortran.dg/vect/O3-bb-slp-2.f: Likewise.
+ * g++.dg/vect/simd-11.cc: Likewise.
+
+2020-10-27 Richard Biener <rguenther@suse.de>
+
+ * gcc.target/i386/pr95866-1.c: Adjust.
+
+2020-10-27 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/swaps-p8-22.c: Enable only for aix and
+ -m64 linux.
+
+2020-10-27 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/97461
+ * gcc.dg/tree-prof/pr97461.c: New test.
+
+2020-10-27 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/97560
+ * g++.dg/pr97560.C: New test.
+
+2020-10-27 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/vsx_mask-count-runnable.c: Separate options
+ passed to dg-require-effective-target.
+ * gcc.target/powerpc/vsx_mask-expand-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-extract-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-move-runnable.c: Likewise.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/localentry-1.c: Remove -mpcrel from options.
+ * gcc.target/powerpc/notoc-direct-1.c: Likewise.
+ * gcc.target/powerpc/pr94740.c: Likewise.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/bswap64-4.c: Comment.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/pr93122.c: Replace -mcpu with -mdejagnu-cpu.
+ * gcc.target/powerpc/vsx_mask-count-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-expand-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-extract-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-move-runnable.c: Likewise.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/vsx-load-element-extend-char.c: Require int128.
+ * gcc.target/powerpc/vsx-load-element-extend-int.c: Likewise.
+ * gcc.target/powerpc/vsx-load-element-extend-longlong.c: Likewise.
+ * gcc.target/powerpc/vsx-load-element-extend-short.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-char.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-int.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-longlong.c: Likewise.
+ * gcc.target/powerpc/vsx-store-element-truncate-short.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-count-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-expand-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-extract-runnable.c: Likewise.
+ * gcc.target/powerpc/vsx_mask-move-runnable.c: Likewise.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/cfuged-1.c,
+ gcc.target/powerpc/cntlzdm-1.c,
+ gcc.target/powerpc/cnttzdm-1.c,
+ gcc.target/powerpc/dg-future-1.c,
+ gcc.target/powerpc/lsbb-runnable.c,
+ gcc.target/powerpc/mma-double-test.c,
+ gcc.target/powerpc/mma-single-test.c,
+ gcc.target/powerpc/p10-arch31.c,
+ gcc.target/powerpc/p10-identify.c,
+ gcc.target/powerpc/pdep-1.c,
+ gcc.target/powerpc/pextd-1.c,
+ gcc.target/powerpc/pr96787-2.c,
+ gcc.target/powerpc/vec-blend-runnable.c,
+ gcc.target/powerpc/vec-cfuged-1.c,
+ gcc.target/powerpc/vec-clrl-1.c,
+ gcc.target/powerpc/vec-clrl-3.c,
+ gcc.target/powerpc/vec-clrr-1.c,
+ gcc.target/powerpc/vec-clrr-3.c,
+ gcc.target/powerpc/vec-cntlzm-1.c,
+ gcc.target/powerpc/vec-cnttzm-1.c,
+ gcc.target/powerpc/vec-extracth-1.c,
+ gcc.target/powerpc/vec-extracth-3.c,
+ gcc.target/powerpc/vec-extracth-5.c,
+ gcc.target/powerpc/vec-extracth-7.c,
+ gcc.target/powerpc/vec-extractl-1.c,
+ gcc.target/powerpc/vec-extractl-3.c,
+ gcc.target/powerpc/vec-extractl-5.c,
+ gcc.target/powerpc/vec-extractl-7.c,
+ gcc.target/powerpc/vec-gnb-1.c,
+ gcc.target/powerpc/vec-insert-word-runnable.c,
+ gcc.target/powerpc/vec-pdep-1.c,
+ gcc.target/powerpc/vec-permute-ext-runnable.c,
+ gcc.target/powerpc/vec-pext-1.c,
+ gcc.target/powerpc/vec-replace-word-runnable.c,
+ gcc.target/powerpc/vec-shift-double-runnable.c,
+ gcc.target/powerpc/vec-splati-runnable.c,
+ gcc.target/powerpc/vec-stril-1.c,
+ gcc.target/powerpc/vec-stril-16.c,
+ gcc.target/powerpc/vec-stril-17.c,
+ gcc.target/powerpc/vec-stril-18.c,
+ gcc.target/powerpc/vec-stril-19.c,
+ gcc.target/powerpc/vec-stril-20.c,
+ gcc.target/powerpc/vec-stril-21.c,
+ gcc.target/powerpc/vec-stril-22.c,
+ gcc.target/powerpc/vec-stril-23.c,
+ gcc.target/powerpc/vec-stril-3.c,
+ gcc.target/powerpc/vec-stril-5.c,
+ gcc.target/powerpc/vec-stril-7.c,
+ gcc.target/powerpc/vec-stril_p-1.c,
+ gcc.target/powerpc/vec-stril_p-3.c,
+ gcc.target/powerpc/vec-stril_p-5.c,
+ gcc.target/powerpc/vec-stril_p-7.c,
+ gcc.target/powerpc/vec-strir-1.c,
+ gcc.target/powerpc/vec-strir-16.c,
+ gcc.target/powerpc/vec-strir-17.c,
+ gcc.target/powerpc/vec-strir-18.c,
+ gcc.target/powerpc/vec-strir-19.c,
+ gcc.target/powerpc/vec-strir-20.c,
+ gcc.target/powerpc/vec-strir-21.c,
+ gcc.target/powerpc/vec-strir-22.c,
+ gcc.target/powerpc/vec-strir-23.c,
+ gcc.target/powerpc/vec-strir-3.c,
+ gcc.target/powerpc/vec-strir-5.c,
+ gcc.target/powerpc/vec-strir-7.c,
+ gcc.target/powerpc/vec-strir_p-1.c,
+ gcc.target/powerpc/vec-strir_p-3.c,
+ gcc.target/powerpc/vec-strir_p-5.c,
+ gcc.target/powerpc/vec-strir_p-7.c,
+ gcc.target/powerpc/vec-ternarylogic-1.c,
+ gcc.target/powerpc/vec-ternarylogic-3.c,
+ gcc.target/powerpc/vec-ternarylogic-5.c,
+ gcc.target/powerpc/vec-ternarylogic-7.c,
+ gcc.target/powerpc/vec-ternarylogic-9.c,
+ gcc.target/powerpc/vsx_mask-count-runnable.c,
+ gcc.target/powerpc/vsx_mask-expand-runnable.c,
+ gcc.target/powerpc/vsx_mask-extract-runnable.c,
+ gcc.target/powerpc/vsx_mask-move-runnable.c,
+ gcc.target/powerpc/xxgenpc-runnable.c: Link testcase when it
+ can't be run.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/dimode_off.c: Add -mno-prefixed to options.
+
+2020-10-26 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/cprophard.c: Add -mno-pcrel to options.
+ * gcc.target/powerpc/float128-hw3.c: Likewise.
+ * gcc.target/powerpc/pr79439-1.c: Likewise.
+ * gcc.target/powerpc/pr79439-2.c: Likewise.
+ * gcc.target/powerpc/r2_shrink-wrap.c: Likewise.
+
+2020-10-26 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr97567.c: New.
+
+2020-10-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/pr97555.c: New test.
+
+2020-10-26 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ * g++.dg/ext/is_nothrow_constructible1.C: New file.
+ * g++.dg/ext/is_nothrow_constructible2.C: New file.
+ * g++.dg/ext/is_nothrow_constructible3.C: New file.
+ * g++.dg/ext/is_nothrow_constructible4.C: New file.
+ * g++.dg/ext/is_nothrow_constructible5.C: New file.
+ * g++.dg/ext/is_nothrow_constructible6.C: New file.
+
+2020-10-26 Jan Hubicka <jh@suse.cz>
+
+ PR ipa/97576
+ * gcc.c-torture/compile/pr97576.c: New test.
+
+2020-10-26 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/97546
+ * gcc.target/aarch64/sve/acle/general/pr97546.c: New test.
+
+2020-10-26 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/97521
+ * gcc.target/i386/pr97521.c: New testcase.
+
+2020-10-26 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/95458
+ * gcc.target/i386/pr95458-1.c: New test.
+ * gcc.target/i386/pr95458-2.c: Likewise.
+
+2020-10-26 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/95151
+ * gcc.target/i386/pr95151-1.c: New test.
+ * gcc.target/i386/pr95151-2.c: Likewise.
+ * gcc.target/i386/pr95151-3.c: Likewise.
+ * gcc.target/i386/pr95151-4.c: Likewise.
+
+2020-10-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/97539
+ * gcc.dg/pr97539.c: New testcase.
+
+2020-10-26 Arnaud Charlet <charlet@adacore.com>
+
+ * gnat.dg/warn14.adb: Update expectations.
+
2020-10-24 Marek Polacek <polacek@redhat.com>
PR c++/96241
@@ -53,7 +6372,7 @@
* gcc.dg/pr43783.c: ... here. Add dg-do compile, dg-options and
dg-error directives.
-2020-10-23 Dennis Zhang <dennis.zh@live.com>
+2020-10-23 Dennis Zhang <dennis.zhang@arm.com>
* gcc.target/arm/simd/mve-vsub_1.c: New test.
@@ -65,10 +6384,6 @@
PR middle-end/97521
* gcc.target/i386/pr97521.c: New testcase.
-2020-10-23 Dennis Zhang <dennis.zhang@arm.com>
-
- * gcc.target/arm/simd/mve-vsub_1.c: New test.
-
2020-10-22 Alan Modra <amodra@gmail.com>
* gcc.target/powerpc/vec-splati-runnable.c: Don't abort on
@@ -161,15 +6476,11 @@
* gcc.target/i386/pr97249-1.c: New test.
-2020-10-22 Dennis Zhang <dennis.zh@live.com>
-
- * gcc.target/arm/simd/mve-vminmax_1.c: New test.
-
2020-10-22 Andrew MacLeod <amacleod@redhat.com>
* gcc.dg/pr97520.c: New.
-2020-10-22 Dennis Zhang <dennis.zh@live.com>
+2020-10-22 Dennis Zhang <dennis.zhang@arm.com>
* gcc.target/arm/simd/mve-vmul_1.c: New test.
@@ -302,10 +6613,6 @@
* gcc.target/arm/simd/mve-vminmax_1.c: New test.
-2020-10-22 Dennis Zhang <dennis.zhang@arm.com>
-
- * gcc.target/arm/simd/mve-vmul_1.c: New test.
-
2020-10-20 Jeff Law <law@redhat.com>
* gcc.dg/Wbuiltin-declaration-mismatch-9.c: Improve pruning of
@@ -1392,20 +7699,6 @@
* gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c: New test.
* gcc.target/arm/multilib.exp: Add tests for -mcpu=cortex-m55.
-2020-10-05 Dennis Zhang <dennis.zhang@arm.com>
-
- * gcc.target/arm/mve/intrinsics/vreinterpretq_f16.c: Use additional
- option -fno-ipa-icf and change the instruction count from 8 to 16.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_f32.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_s16.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_s32.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_s64.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_s8.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_u16.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_u32.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_u64.c: Likewise.
- * gcc.target/arm/mve/intrinsics/vreinterpretq_u8.c: Likewise.
-
2020-10-05 Nathan Sidwell <nathan@acm.org>
* c-c++-common/spellcheck-reserved.c: Restore diagnostic.
diff --git a/gcc/testsuite/ada/acats/support/acats25.lst b/gcc/testsuite/ada/acats/support/acats25.lst
deleted file mode 100644
index 0133ed3..0000000
--- a/gcc/testsuite/ada/acats/support/acats25.lst
+++ /dev/null
@@ -1,4308 +0,0 @@
-a22006b.ada
-a22006c.ada
-a22006d.ada
-a26007a.tst
-a27003a.ada
-a29003a.ada
-a2a031a.ada
-a33003a.ada
-a34017c.ada
-a35101b.ada
-a35402a.ada
-a35801f.ada
-a35902c.ada
-a38106d.ada
-a38106e.ada
-a49027a.ada
-a49027b.ada
-a49027c.ada
-a54b01a.ada
-a54b02a.ada
-a55b12a.ada
-a55b13a.ada
-a55b14a.ada
-a71004a.ada
-a73001i.ada
-a73001j.ada
-a74105b.ada
-a74106a.ada
-a74106b.ada
-a74106c.ada
-a74205e.ada
-a74205f.ada
-a83009a.ada
-a83009b.ada
-a83a02a.ada
-a83a02b.ada
-a83a06a.ada
-a83a08a.ada
-a83c01c.ada
-a83c01h.ada
-a83c01i.ada
-a85007d.ada
-a85013b.ada
-a87b59a.ada
-a95001c.ada
-a95074d.ada
-a97106a.ada
-a99006a.ada
-aa2010a.ada
-aa2012a.ada
-acats25.lst
-ac1015b.ada
-ac3106a.ada
-ac3206a.ada
-ac3207a.ada
-ad7001b.ada
-ad7001c0.ada
-ad7001c1.ada
-ad7001d0.ada
-ad7001d1.ada
-ad7006a.ada
-ad7101a.ada
-ad7101c.ada
-ad7102a.ada
-ad7103a.ada
-ad7103c.ada
-ad7104a.ada
-ad7201a.ada
-ad7203b.ada
-ad7205b.ada
-ad8011a.tst
-ada101a.ada
-ae2113a.ada
-ae2113b.ada
-ae3002g.ada
-ae3101a.ada
-ae3702a.ada
-ae3709a.ada
-b22001a.tst
-b22001b.tst
-b22001c.tst
-b22001d.tst
-b22001e.tst
-b22001f.tst
-b22001g.tst
-b22001h.ada
-b22001i.tst
-b22001j.tst
-b22001k.tst
-b22001l.tst
-b22001m.tst
-b22001n.tst
-b23002a.ada
-b23004a.ada
-b23004b.ada
-b24001a.ada
-b24001b.ada
-b24001c.ada
-b24005a.ada
-b24005b.ada
-b24007a.ada
-b24009a.ada
-b24009b.ada
-b24104a.ada
-b24204a.ada
-b24204b.ada
-b24204c.ada
-b24204d.ada
-b24204e.ada
-b24204f.ada
-b24205a.ada
-b24206a.ada
-b24206b.ada
-b24211b.ada
-b25002a.ada
-b25002b.ada
-b26001a.ada
-b26002a.ada
-b26005a.ada
-b28001a.ada
-b28001b.ada
-b28001c.ada
-b28001d.ada
-b28001e.ada
-b28001f.ada
-b28001g.ada
-b28001h.ada
-b28001i.ada
-b28001j.ada
-b28001k.ada
-b28001l.ada
-b28001m.ada
-b28001n.ada
-b28001o.ada
-b28001p.ada
-b28001q.ada
-b28001r.ada
-b28001s.ada
-b28001t.ada
-b28001u.ada
-b28001v.ada
-b28001w.ada
-b29001a.ada
-b2a003a.ada
-b2a003b.ada
-b2a003c.ada
-b2a003d.ada
-b2a003e.ada
-b2a003f.ada
-b2a005a.ada
-b2a005b.ada
-b2a007a.ada
-b2a010a.ada
-b2a021a.ada
-b32101a.ada
-b32103a.ada
-b32104a.ada
-b32106a.ada
-b32201a.ada
-b32202a.ada
-b32202b.ada
-b32202c.ada
-b330001.a
-b33001a.ada
-b33101a.ada
-b33102a.ada
-b33102b.ada
-b33102c.ada
-b33102d.ada
-b33102e.ada
-b33201a.ada
-b33201b.ada
-b33201c.ada
-b33201d.ada
-b33201e.ada
-b33204a.ada
-b33205a.ada
-b33302a.ada
-b34001b.ada
-b34001e.ada
-b34002b.ada
-b34003b.ada
-b34004b.ada
-b34005b.ada
-b34005e.ada
-b34005h.ada
-b34005k.ada
-b34005n.ada
-b34005q.ada
-b34005t.ada
-b34006b.ada
-b34006e.ada
-b34006h.ada
-b34006k.ada
-b34007b.ada
-b34007e.ada
-b34007h.ada
-b34007k.ada
-b34007n.ada
-b34007q.ada
-b34007t.ada
-b34008b.ada
-b34009b.ada
-b34009e.ada
-b34009h.ada
-b34009k.ada
-b34011a.ada
-b34014b.ada
-b34014d.ada
-b34014f.ada
-b34014i.ada
-b34014m.ada
-b34014o.ada
-b34014q.ada
-b34014s.ada
-b34014v.ada
-b34014z.ada
-b35004a.ada
-b35101a.ada
-b35103a.ada
-b35103b.ada
-b35302a.ada
-b354001.a
-b35401a.ada
-b35401b.ada
-b35403a.ada
-b35501a.ada
-b35501b.ada
-b35506a.ada
-b35506b.ada
-b35506c.ada
-b35506d.ada
-b35701a.ada
-b35709a.ada
-b35901a.ada
-b35901c.ada
-b35901d.ada
-b35a01a.ada
-b35a08a.ada
-b360001.a
-b36001a.ada
-b36002a.ada
-b36101a.ada
-b36102a.ada
-b36103a.ada
-b36105c.dep
-b36171a.ada
-b36171b.ada
-b36171c.ada
-b36171d.ada
-b36171e.ada
-b36171f.ada
-b36171g.ada
-b36171h.ada
-b36171i.ada
-b36201a.ada
-b36307a.ada
-b370001.a
-b370002.a
-b37004a.ada
-b37004b.ada
-b37004c.ada
-b37004d.ada
-b37004e.ada
-b37004f.ada
-b37004g.ada
-b3710010.a
-b3710011.a
-b3710012.a
-b3710013.a
-b3710014.am
-b37101a.ada
-b37102a.ada
-b37104a.ada
-b37106a.ada
-b37201a.ada
-b37201b.ada
-b37203a.ada
-b37301i.ada
-b37301j.ada
-b37302a.ada
-b37303a.ada
-b37309b.ada
-b37310b.ada
-b37311a.ada
-b37401a.ada
-b37409b.ada
-b380001.a
-b38003a.ada
-b38003b.ada
-b38003c.ada
-b38003d.ada
-b38008a.ada
-b38008b.ada
-b38009a.ada
-b38009d.ada
-b38101a.ada
-b38101b.ada
-b38101c.ada
-b38103a.ada
-b38103b.ada
-b38103c0.ada
-b38103c1.ada
-b38103c2.ada
-b38103c3.ada
-b38103d.ada
-b38103e0.ada
-b38103e1.ada
-b38105a.ada
-b38105b.ada
-b38203a.ada
-b390001.a
-b391001.a
-b391002.a
-b391003.a
-b391004.a
-b392001.a
-b392002.a
-b392003.a
-b392004.a
-b392005.a
-b392006.a
-b392007.a
-b392008.a
-b392009.a
-b392010.a
-b392011.a
-b393001.a
-b393002.a
-b393003.a
-b393004.a
-b393005.a
-b393006.a
-b393007.a
-b3a0001.a
-b3a0002.a
-b3a0003.a
-b3a0004.a
-b3a2002.a
-b3a2003.a
-b3a2004.a
-b3a2005.a
-b3a2006.a
-b3a2007.a
-b3a2008.a
-b3a2009.a
-b3a2010.a
-b3a2011.a
-b3a2012.a
-b3a2013.a
-b3a2014.a
-b3a2015.a
-b3a2016.a
-b41101a.ada
-b41101c.ada
-b41201a.ada
-b41201c.ada
-b41202c.ada
-b41202d.ada
-b41324b.ada
-b41325b.ada
-b41327b.ada
-b420001.a
-b430001.a
-b43001m.ada
-b43002d.ada
-b43002e.ada
-b43002f.ada
-b43002g.ada
-b43002h.ada
-b43002i.ada
-b43002j.ada
-b43002k.ada
-b43005a.ada
-b43005b.ada
-b43005f.ada
-b43101a.ada
-b43102a.ada
-b43102b.ada
-b43105c.ada
-b43201a.ada
-b43201c.ada
-b43201d.ada
-b43202a.ada
-b43202c.ada
-b43209b.ada
-b43221a.ada
-b43221b.ada
-b43223a.ada
-b44001a.ada
-b44001b.ada
-b44002b.ada
-b44002c.ada
-b44004a.ada
-b44004b.ada
-b44004c.ada
-b44004d.ada
-b44004e.ada
-b45102a.ada
-b45116a.ada
-b45121a.ada
-b45204a.ada
-b45205a.ada
-b45206c.ada
-b45207a.ada
-b45207b.ada
-b45207c.ada
-b45207d.ada
-b45207g.ada
-b45207h.ada
-b45207i.ada
-b45207j.ada
-b45207m.ada
-b45207n.ada
-b45207o.ada
-b45207p.ada
-b45207s.ada
-b45207t.ada
-b45207u.ada
-b45207v.ada
-b45208a.ada
-b45208b.ada
-b45208c.ada
-b45208g.ada
-b45208h.ada
-b45208i.ada
-b45208m.ada
-b45208n.ada
-b45208s.ada
-b45208t.ada
-b45209a.ada
-b45209b.ada
-b45209c.ada
-b45209d.ada
-b45209e.ada
-b45209f.ada
-b45209g.ada
-b45209h.ada
-b45209i.ada
-b45209j.ada
-b45209k.ada
-b45221a.ada
-b45261a.ada
-b45261b.ada
-b45261c.ada
-b45261d.ada
-b45301a.ada
-b45301b.ada
-b45301c.ada
-b45302a.ada
-b45341a.ada
-b455002.a
-b45501a.ada
-b45501b.ada
-b45501c.ada
-b45522a.ada
-b45537a.ada
-b45601a.ada
-b45625a.ada
-b45661a.ada
-b460001.a
-b460002.a
-b460004.a
-b460005.a
-b46002a.ada
-b46003a.ada
-b46004a.ada
-b46004b.ada
-b46004c.ada
-b46004d.ada
-b46004e.ada
-b46005a.ada
-b47001a.ada
-b480001.a
-b48001a.ada
-b48001b.ada
-b48002a.ada
-b48002b.ada
-b48002c.ada
-b48002d.ada
-b48002e.ada
-b48002g.ada
-b48003a.ada
-b48003b.ada
-b48003c.ada
-b48003d.ada
-b48003e.ada
-b490001.a
-b490002.a
-b49002a.ada
-b49004a.ada
-b49005a.ada
-b49007a.ada
-b49007b.ada
-b49008a.ada
-b49008c.ada
-b49009b.ada
-b49009c.ada
-b49010a.ada
-b49011a.ada
-b4a010c.ada
-b4a016a.ada
-b51001a.ada
-b51004b.ada
-b51004c.ada
-b52002a.ada
-b52002b.ada
-b52002c.ada
-b52002d.ada
-b52002e.ada
-b52002f.ada
-b52002g.ada
-b52004a.ada
-b52004b.ada
-b52004c.ada
-b52004d.dep
-b52004e.dep
-b53001a.ada
-b53001b.ada
-b53002a.ada
-b53002b.ada
-b53009a.ada
-b53009b.ada
-b53009c.ada
-b54a01b.ada
-b54a01f.ada
-b54a01g.ada
-b54a01l.ada
-b54a05a.ada
-b54a05b.ada
-b54a10a.ada
-b54a12a.ada
-b54a20a.ada
-b54a21a.ada
-b54a25a.ada
-b54a60a.ada
-b54a60b.ada
-b54b01b.tst
-b54b01c.ada
-b54b02b.ada
-b54b02c.ada
-b54b02d.ada
-b54b04a.ada
-b54b04b.ada
-b54b05a.ada
-b54b06a.ada
-b55a01a.ada
-b55a01d.ada
-b55a01e.ada
-b55a01j.ada
-b55a01k.ada
-b55a01l.ada
-b55a01n.ada
-b55a01o.ada
-b55a01t.ada
-b55a01u.ada
-b55a01v.ada
-b55b01a.ada
-b55b01b.ada
-b55b09b.ada
-b55b09c.dep
-b55b09d.dep
-b55b12b.ada
-b55b12c.ada
-b55b17a.ada
-b55b17b.ada
-b55b17c.ada
-b55b18a.ada
-b56001a.ada
-b56001d.ada
-b56001e.ada
-b56001f.ada
-b56001g.ada
-b56001h.ada
-b57001a.ada
-b57001b.ada
-b57001c.ada
-b57001d.ada
-b58001a.ada
-b58002a.ada
-b58002b.ada
-b58002c.ada
-b58003a.ada
-b58003b.ada
-b59001a.ada
-b59001c.ada
-b59001d.ada
-b59001e.ada
-b59001f.ada
-b59001g.ada
-b59001h.ada
-b59001i.ada
-b610001.a
-b61001f.ada
-b61005a.ada
-b61006a.ada
-b61011a.ada
-b62001a.ada
-b62001b.ada
-b62001c.ada
-b62001d.ada
-b63001a.ada
-b63001b.ada
-b63005a.ada
-b63005b.ada
-b63006a.ada
-b63009a.ada
-b63009b.ada
-b63009c0.ada
-b63009c1.ada
-b63009c2.ada
-b63009c3.ada
-b63103a.ada
-b64002a.ada
-b64002c.ada
-b64003a.ada
-b64004a.ada
-b64004b.ada
-b64004c.ada
-b64004d.ada
-b64004e.ada
-b64004f.ada
-b641001.a
-b64101a.ada
-b64201a.ada
-b65001a.ada
-b65002a.ada
-b65002b.ada
-b660001.a
-b660002.a
-b66001a.ada
-b66001b.ada
-b66001c.ada
-b66001d.ada
-b67001a.ada
-b67001b.ada
-b67001c.ada
-b67001d.ada
-b67001h.ada
-b67001i.ada
-b67001j.ada
-b67001k.ada
-b67004a.ada
-b71001a.ada
-b71001b.ada
-b71001c.ada
-b71001d.ada
-b71001f.ada
-b71001g.ada
-b71001h.ada
-b71001i.ada
-b71001j.ada
-b71001l.ada
-b71001m.ada
-b71001n.ada
-b71001o.ada
-b71001p.ada
-b71001r.ada
-b71001t.ada
-b71001u.ada
-b71001v.ada
-b7200010.a
-b7200011.a
-b7200012.a
-b7200013.a
-b7200014.a
-b7200015.a
-b7200016.a
-b730001.a
-b730002.a
-b730003.a
-b730004.a
-b730005.a
-b7300060.a
-b7300061.a
-b7300062.a
-b7300063.am
-b73001a.ada
-b73001b.ada
-b73001c.ada
-b73001d.ada
-b73001e.ada
-b73001f.ada
-b73001g.ada
-b73001h.ada
-b73004a.ada
-b73004b0.ada
-b73004b1.ada
-b73004b2.ada
-b7310010.a
-b7310011.a
-b7310012.a
-b7310013.a
-b7310014.a
-b7310015.a
-b7310016.am
-b731a01.a
-b731a02.a
-b740001.a
-b74001a.ada
-b74001b.ada
-b74101a.ada
-b74101b.ada
-b74103a.ada
-b74103d.ada
-b74103e.ada
-b74103g.ada
-b74103i.ada
-b74104a.ada
-b74105a.ada
-b74105c.ada
-b74201a.ada
-b74202a.ada
-b74202b.ada
-b74202c.ada
-b74202d.ada
-b74203b.ada
-b74203c.ada
-b74203d.ada
-b74203e.ada
-b74205a.ada
-b74207a.ada
-b74304a.ada
-b74304b.ada
-b74304c.ada
-b74404a.ada
-b74404b.ada
-b74409a.ada
-b810001.a
-b830001.a
-b8300020.a
-b8300021.a
-b8300022.a
-b8300023.a
-b8300024.a
-b8300025.am
-b83001a.ada
-b83003a.ada
-b83003b0.ada
-b83003b1.ada
-b83003b2.ada
-b83003b3.ada
-b83003b4.ada
-b83003c.ada
-b83004a.ada
-b83004b0.ada
-b83004b1.ada
-b83004b2.ada
-b83004b3.ada
-b83004c0.ada
-b83004c1.ada
-b83004c2.ada
-b83004d0.ada
-b83004d1.ada
-b83004d2.ada
-b83004d3.ada
-b83006a.ada
-b83006b.ada
-b83008a.ada
-b83008b.ada
-b83011a.ada
-b83023b.ada
-b83024b.ada
-b83024f0.ada
-b83024f1.ada
-b83024f2.ada
-b83024f3.ada
-b83026b.ada
-b83027b.ada
-b83027d.ada
-b83028b.ada
-b83029b.ada
-b83030b.ada
-b83030d.ada
-b83031b.ada
-b83031d.ada
-b83031f.ada
-b83032b.ada
-b83033b.ada
-b83041e.ada
-b83a01a.ada
-b83a01b.ada
-b83a01c.ada
-b83a05a.ada
-b83a06b.ada
-b83a06h.ada
-b83a07a.ada
-b83a07b.ada
-b83a07c.ada
-b83a08b.ada
-b83a09a.ada
-b83b01a.ada
-b83b02c.ada
-b83e01a.ada
-b83e01b.ada
-b83e01c.ada
-b83e01d.ada
-b83e01e0.ada
-b83e01e1.ada
-b83e01e2.ada
-b83e01e3.ada
-b83e01f0.ada
-b83e01f1.ada
-b83e01f2.ada
-b83e01f3.ada
-b83e01f4.ada
-b83e01f5.ada
-b83e01f6.ada
-b83e11a.ada
-b83f02a.ada
-b83f02b.ada
-b83f02c.ada
-b840001.a
-b84001a.ada
-b84002b.ada
-b84004a.ada
-b84005b.ada
-b84006a.ada
-b84007a.ada
-b84008b.ada
-b85001a.ada
-b85001b.ada
-b85001c.ada
-b85001d.ada
-b85001e.ada
-b85001f.ada
-b85001g.ada
-b85001h.ada
-b85001i.ada
-b85001j.ada
-b85001k.ada
-b85001l.ada
-b85002a.ada
-b85003a.ada
-b85003b.ada
-b85004a.ada
-b85008f.ada
-b85008g.ada
-b85008h.ada
-b85010a.ada
-b85010b.ada
-b85012a.ada
-b85013c.ada
-b85013d.ada
-b85015a.ada
-b8510010.a
-b8510011.a
-b8510012.am
-b86001a0.ada
-b86001a1.ada
-b87b23b.ada
-b87b26a.ada
-b87b48c.ada
-b91001b.ada
-b91001c.ada
-b91001d.ada
-b91001e.ada
-b91001f.ada
-b91001g.ada
-b91002a.ada
-b91002b.ada
-b91002c.ada
-b91002d.ada
-b91002e.ada
-b91002f.ada
-b91002g.ada
-b91002h.ada
-b91002i.ada
-b91002j.ada
-b91002k.ada
-b91002l.ada
-b91003a.ada
-b91003b.ada
-b91003c.ada
-b91003d.ada
-b91003e.ada
-b91004a.ada
-b91005a.ada
-b92001a.ada
-b92001b.ada
-b940001.a
-b940002.a
-b940003.a
-b940004.a
-b940005.a
-b940006.a
-b940007.a
-b95001a.ada
-b95001b.ada
-b95001d.ada
-b95002a.ada
-b95003a.ada
-b95004a.ada
-b95004b.ada
-b95006a.ada
-b95006b.ada
-b95006c.ada
-b95006d.ada
-b95007a.ada
-b95007b.ada
-b95020a.ada
-b95020b0.ada
-b95020b1.ada
-b95020b2.ada
-b95030a.ada
-b95031a.ada
-b95032a.ada
-b95061a.ada
-b95061b.ada
-b95061c.ada
-b95061d.ada
-b95061e.ada
-b95061f.ada
-b95061g.ada
-b95062a.ada
-b95063a.ada
-b95064a.ada
-b95068a.ada
-b95070a.ada
-b95080a.ada
-b95080c.ada
-b95081a.ada
-b95082a.ada
-b95082b.ada
-b95082c.ada
-b95082d.ada
-b95082e.ada
-b95082f.ada
-b95083a.ada
-b95094a.ada
-b95094b.ada
-b95094c.ada
-b951001.a
-b952001.a
-b952002.a
-b952003.a
-b952004.a
-b954001.a
-b954003.a
-b954004.a
-b960001.a
-b96002a.ada
-b97102b.ada
-b97102c.ada
-b97102d.ada
-b97102f.ada
-b97102g.ada
-b97102h.ada
-b97102i.ada
-b97103a.ada
-b97103b.ada
-b97103d.ada
-b97103e.ada
-b97103f.ada
-b97103g.ada
-b97104a.ada
-b97104b.ada
-b97104c.ada
-b97104d.ada
-b97104e.ada
-b97104f.ada
-b97104g.ada
-b97107a.ada
-b97108a.ada
-b97108b.ada
-b97109a.ada
-b97110a.ada
-b97110b.ada
-b97111a.ada
-b97206a.ada
-b97306a.ada
-b99001a.ada
-b99001b.ada
-b99002a.ada
-b99002b.ada
-b99002c.ada
-b99003a.ada
-b9a001a.ada
-b9a001b.ada
-ba1001a0.ada
-ba1001a1.ada
-ba1001a4.ada
-ba1001ac.ada
-ba1001d.ada
-ba1010a0.ada
-ba1010a1.ada
-ba1010a2.ada
-ba1010a3.ada
-ba1010b0.ada
-ba1010b1.ada
-ba1010b2.ada
-ba1010b4.ada
-ba1010b5.ada
-ba1010b6.ada
-ba1010b7.ada
-ba1010b8.ada
-ba1010c0.ada
-ba1010c1.ada
-ba1010c2.ada
-ba1010c3.ada
-ba1010c4.ada
-ba1010c5.ada
-ba1010c6.ada
-ba1010d0.ada
-ba1010d1.ada
-ba1010d2.ada
-ba1010d3.ada
-ba1010e0.ada
-ba1010e1.ada
-ba1010e2.ada
-ba1010e3.ada
-ba1010e4.ada
-ba1010e5.ada
-ba1010e6.ada
-ba1010f0.ada
-ba1010f1.ada
-ba1010f3.ada
-ba1010f4.ada
-ba1010f5.ada
-ba1010f6.ada
-ba1010f7.ada
-ba1010f8.ada
-ba1010g0.ada
-ba1010g2.ada
-ba1010g3.ada
-ba1010g4.ada
-ba1010g5.ada
-ba1010h0.ada
-ba1010h2.ada
-ba1010i0.ada
-ba1010i1.ada
-ba1010i3.ada
-ba1010i4.ada
-ba1010j0.ada
-ba1010j1.ada
-ba1010j2.ada
-ba1010j4.ada
-ba1010j5.ada
-ba1010j6.ada
-ba1010j7.ada
-ba1010j8.ada
-ba1010k0.ada
-ba1010k1.ada
-ba1010k2.ada
-ba1010k3.ada
-ba1010k4.ada
-ba1010k5.ada
-ba1010k6.ada
-ba1010l0.ada
-ba1010l1.ada
-ba1010l2.ada
-ba1010l3.ada
-ba1010l4.ada
-ba1010l5.ada
-ba1010l6.ada
-ba1010m0.ada
-ba1010m1.ada
-ba1010m3.ada
-ba1010m4.ada
-ba1010m5.ada
-ba1010m6.ada
-ba1010m7.ada
-ba1010m8.ada
-ba1010n0.ada
-ba1010n2.ada
-ba1010n3.ada
-ba1010n4.ada
-ba1010n5.ada
-ba1010p0.ada
-ba1010p2.ada
-ba1010q0.ada
-ba1010q1.ada
-ba1010q3.ada
-ba1010q4.ada
-ba1011b0.ada
-ba1011b1.ada
-ba1011b2.ada
-ba1011b3.ada
-ba1011b4.ada
-ba1011b5.ada
-ba1011b6.ada
-ba1011b7.ada
-ba1011b8.ada
-ba1011c0.ada
-ba1011c1.ada
-ba1011c2.ada
-ba1011c3.ada
-ba1011c4.ada
-ba1011c5.ada
-ba1011c6.ada
-ba1011c7.ada
-ba1011c8.ada
-ba1020a0.ada
-ba1020a1.ada
-ba1020a2.ada
-ba1020a3.ada
-ba1020a4.ada
-ba1020a5.ada
-ba1020a6.ada
-ba1020a7.ada
-ba1020a8.ada
-ba1020b0.ada
-ba1020b1.ada
-ba1020b2.ada
-ba1020b3.ada
-ba1020b4.ada
-ba1020b5.ada
-ba1020b6.ada
-ba1020c0.ada
-ba1020c1.ada
-ba1020c2.ada
-ba1020c3.ada
-ba1020c4.ada
-ba1020c5.ada
-ba1020f0.ada
-ba1020f1.ada
-ba1020f2.ada
-ba11001.a
-ba11002.a
-ba11003.a
-ba11004.a
-ba11005.a
-ba11007.a
-ba11008.a
-ba11009.a
-ba11010.a
-ba11011.a
-ba11012.a
-ba1101a.ada
-ba1101b0.ada
-ba1101b1.ada
-ba1101b2.ada
-ba1101b3.ada
-ba1101b4.ada
-ba1101c0.ada
-ba1101c1.ada
-ba1101c2.ada
-ba1101c3.ada
-ba1101c4.ada
-ba1101c5.ada
-ba1101c6.ada
-ba1101e0.ada
-ba1101e1.ada
-ba1101f.ada
-ba1101g.ada
-ba1109a0.ada
-ba1109a1.ada
-ba1109a2.ada
-ba1110a0.ada
-ba1110a1.ada
-ba1110a2.ada
-ba1110a3.ada
-ba1110a4.ada
-ba1110a5.ada
-ba12001.a
-ba12002.a
-ba12003.a
-ba12004.a
-ba12005.a
-ba12007.a
-ba12008.a
-ba13b01.a
-ba13b02.a
-ba15001.a
-ba150020.a
-ba150021.a
-ba150022.a
-ba150023.a
-ba150024.a
-ba150025.a
-ba150026.a
-ba150027.a
-ba150028.a
-ba150029.am
-ba2001a.ada
-ba2001b.ada
-ba2001c.ada
-ba2001d.ada
-ba2001f0.ada
-ba2001f1.ada
-ba2001f2.ada
-ba2003b0.ada
-ba2003b1.ada
-ba2011a0.ada
-ba2011a1.ada
-ba2011a2.ada
-ba2011a3.ada
-ba2011a4.ada
-ba2011a5.ada
-ba2011a6.ada
-ba2011a7.ada
-ba2011a8.ada
-ba2011a9.ada
-ba2013a.ada
-ba2013b.ada
-ba21001.a
-ba21002.a
-ba210030.a
-ba210031.a
-ba210032.a
-ba210033.a
-ba210034.a
-ba210035.a
-ba210040.a
-ba210041.a
-ba210042.a
-ba210043.a
-ba210044.a
-ba210045.am
-ba21a01.a
-ba21a02.a
-ba3001a0.ada
-ba3001a1.ada
-ba3001a2.ada
-ba3001a3.ada
-ba3001b0.ada
-ba3001b1.ada
-ba3001c0.ada
-ba3001c1.ada
-ba3001e0.ada
-ba3001e1.ada
-ba3001e2.ada
-ba3001e3.ada
-ba3001f0.ada
-ba3001f1.ada
-ba3001f2.ada
-ba3001f3.ada
-ba3006a0.ada
-ba3006a1.ada
-ba3006a2.ada
-ba3006a3.ada
-ba3006a4.ada
-ba3006a5.ada
-ba3006a6.ada
-ba3006b0.ada
-ba3006b1.ada
-ba3006b2.ada
-ba3006b3.ada
-ba3006b4.ada
-bb10001.a
-bb20001.a
-bb2001a.ada
-bb2002a.ada
-bb2003a.ada
-bb2003b.ada
-bb2003c.ada
-bb3001a.ada
-bb3002a.ada
-bc1001a.ada
-bc1002a.ada
-bc1005a.ada
-bc1008a.ada
-bc1008b.ada
-bc1008c.ada
-bc1009a.ada
-bc1011a.ada
-bc1011b.ada
-bc1011c.ada
-bc1012a.ada
-bc1013a.ada
-bc1014a.ada
-bc1014b.ada
-bc1016a.ada
-bc1016b.ada
-bc1101a.ada
-bc1102a.ada
-bc1103a.ada
-bc1106a.ada
-bc1107a.ada
-bc1109a.ada
-bc1109b.ada
-bc1109c.ada
-bc1109d.ada
-bc1110a.ada
-bc1201a.ada
-bc1201b.ada
-bc1201c.ada
-bc1201d.ada
-bc1201e.ada
-bc1201f.ada
-bc1201g.ada
-bc1201h.ada
-bc1201i.ada
-bc1201j.ada
-bc1201k.ada
-bc1201l.ada
-bc1202a.ada
-bc1202c.ada
-bc1202e.ada
-bc1202f.ada
-bc1202g.ada
-bc1203a.ada
-bc1205a.ada
-bc1206a.ada
-bc1207a.ada
-bc1208a.ada
-bc1226a.ada
-bc1230a.ada
-bc1303a.ada
-bc1303b.ada
-bc1303c.ada
-bc1303d.ada
-bc1303e.ada
-bc1303f.ada
-bc1303g.ada
-bc1306a.ada
-bc2001b.ada
-bc2001c.ada
-bc2001d.ada
-bc2001e.ada
-bc2004a.ada
-bc2004b.ada
-bc30001.a
-bc3001a.ada
-bc3002a.ada
-bc3002b.ada
-bc3002c.ada
-bc3002d.ada
-bc3002e.ada
-bc3005a.ada
-bc3005b.ada
-bc3005c.ada
-bc3006a.ada
-bc3009c.ada
-bc3011b.ada
-bc3013a.ada
-bc3016g.ada
-bc3018a.ada
-bc3101a.ada
-bc3101b.ada
-bc3102a.ada
-bc3102b.ada
-bc3103b.ada
-bc3123c.ada
-bc3201a.ada
-bc3201b.ada
-bc3201c.ada
-bc3202a.ada
-bc3202b.ada
-bc3202c.ada
-bc3202d.ada
-bc3205c.ada
-bc3301a.ada
-bc3301b.ada
-bc3302a.ada
-bc3302b.ada
-bc3303a.ada
-bc3304a.ada
-bc3401a.ada
-bc3401b.ada
-bc3402a.ada
-bc3402b.ada
-bc3403a.ada
-bc3403b.ada
-bc3403c.ada
-bc3404a.ada
-bc3404b.ada
-bc3404c.ada
-bc3404d.ada
-bc3404e.ada
-bc3404f.ada
-bc3405a.ada
-bc3405b.ada
-bc3405d.ada
-bc3405e.ada
-bc3405f.ada
-bc3501a.ada
-bc3501b.ada
-bc3501c.ada
-bc3501d.ada
-bc3501e.ada
-bc3501f.ada
-bc3501g.ada
-bc3501h.ada
-bc3501i.ada
-bc3501j.ada
-bc3501k.ada
-bc3502a.ada
-bc3502b.ada
-bc3502c.ada
-bc3502d.ada
-bc3502e.ada
-bc3502f.ada
-bc3502g.ada
-bc3502h.ada
-bc3502i.ada
-bc3502j.ada
-bc3502k.ada
-bc3502l.ada
-bc3502m.ada
-bc3502n.ada
-bc3502o.ada
-bc3503a.ada
-bc3503c.ada
-bc3503d.ada
-bc3503e.ada
-bc3503f.ada
-bc3604a.ada
-bc3604b.ada
-bc3607a.ada
-bc40001.a
-bc40002.a
-bc50001.a
-bc50002.a
-bc50003.a
-bc50004.a
-bc51002.a
-bc51003.a
-bc51004.a
-bc51005.a
-bc51006.a
-bc51007.a
-bc51011.a
-bc51012.a
-bc51013.a
-bc51015.a
-bc51016.a
-bc51017.a
-bc51018.a
-bc51019.a
-bc51020.a
-bc51b01.a
-bc51b02.a
-bc51c01.a
-bc51c02.a
-bc53001.a
-bc53002.a
-bc54001.a
-bc54002.a
-bc54003.a
-bc54a01.a
-bc54a02.a
-bc54a03.a
-bc54a04.a
-bc54a05.a
-bc54a06.a
-bc70001.a
-bc70002.a
-bc70003.a
-bc70004.a
-bc70005.a
-bc70006.a
-bc70007.a
-bc70008.a
-bc70009.a
-bc70010.a
-bd1b01a.ada
-bd1b02b.ada
-bd1b03c.ada
-bd1b05e.ada
-bd1b06j.ada
-bd2001b.ada
-bd2a01h.ada
-bd2a02a.tst
-bd2a03a.ada
-bd2a03b.ada
-bd2a06a.ada
-bd2a25a.ada
-bd2a35a.ada
-bd2a45a.ada
-bd2a55a.ada
-bd2a55b.ada
-bd2a67a.ada
-bd2a77a.ada
-bd2a85a.ada
-bd2a85b.ada
-bd2b01c.ada
-bd2b02a.ada
-bd2b03a.ada
-bd2b03b.ada
-bd2b03c.ada
-bd2c01d.tst
-bd2c02a.tst
-bd2c03a.tst
-bd2d01c.ada
-bd2d01d.ada
-bd2d02a.ada
-bd2d03a.ada
-bd2d03b.ada
-bd3001a.ada
-bd3001b.ada
-bd3001c.ada
-bd3002a.ada
-bd3003a.ada
-bd3003b.ada
-bd3012a.ada
-bd3013a.ada
-bd4001a.ada
-bd4002a.ada
-bd4003a.ada
-bd4003b.ada
-bd4003c.ada
-bd4006a.tst
-bd4007a.ada
-bd4009a.ada
-bd4011a.ada
-bd5001a.ada
-bd5005a.ada
-bd5005d.ada
-bd5102a.ada
-bd5102b.ada
-bd5103a.ada
-bd5104a.ada
-bd7001a.ada
-bd7101h.ada
-bd7201c.ada
-bd7203a.ada
-bd7204a.ada
-bd7205a.ada
-bd7301a.ada
-bd7302a.ada
-bd8001a.tst
-bd8002a.tst
-bd8003a.tst
-bd8004a.tst
-bd8004b.tst
-bd8004c.tst
-bdb0a01.a
-bdd2001.a
-bde0001.a
-bde0002.a
-bde0003.a
-bde0004.a
-bde0005.a
-bde0006.a
-bde0007.a
-bde0008.a
-be2101e.ada
-be2101j.ada
-be2114a.ada
-be2116a.ada
-be2208a.ada
-be3002a.ada
-be3002e.ada
-be3205a.ada
-be3301c.ada
-be3606c.ada
-be3703a.ada
-be3802a.ada
-be3803a.ada
-be3902a.ada
-be3903a.ada
-bxa8001.a
-bxac001.a
-bxac002.a
-bxac003.a
-bxac004.a
-bxac005.a
-bxc3001.a
-bxc3002.a
-bxc5001.a
-bxc6001.a
-bxc6002.a
-bxc6003.a
-bxc6a01.a
-bxc6a02.a
-bxc6a03.a
-bxc6a04.a
-bxd1001.a
-bxd1002.a
-bxe2007.a
-bxe2008.a
-bxe2009.a
-bxe2010.a
-bxe2011.a
-bxe2012.a
-bxe2013.a
-bxe2a01.a
-bxe2a02.a
-bxe2a03.a
-bxe2a04.a
-bxe2a05.a
-bxe2a06.a
-bxe4001.a
-bxf1001.a
-bxh4001.a
-bxh4002.a
-bxh4003.a
-bxh4004.a
-bxh4005.a
-bxh4006.a
-bxh4007.a
-bxh4008.a
-bxh4009.a
-bxh4010.a
-bxh4011.a
-bxh4012.a
-bxh4013.a
-c23001a.ada
-c23003a.tst
-c23003b.tst
-c23003g.tst
-c23003i.tst
-c23006a.ada
-c23006b.ada
-c23006c.ada
-c23006d.ada
-c23006e.ada
-c23006f.ada
-c23006g.ada
-c24002d.ada
-c24003a.ada
-c24003b.ada
-c24003c.ada
-c24106a.ada
-c24202d.ada
-c24203a.ada
-c24203b.ada
-c24207a.ada
-c24211a.ada
-c250001.aw
-c250002.aw
-c25001a.ada
-c25001b.ada
-c26006a.ada
-c26008a.ada
-c2a001a.ada
-c2a001b.ada
-c2a001c.ada
-c2a002a.ada
-c2a008a.ada
-c2a021b.ada
-c32001a.ada
-c32001b.ada
-c32001c.ada
-c32001d.ada
-c32001e.ada
-c32107a.ada
-c32107c.ada
-c32108a.ada
-c32108b.ada
-c32111a.ada
-c32111b.ada
-c32112b.ada
-c32113a.ada
-c32115a.ada
-c32115b.ada
-c330001.a
-c330002.a
-c332001.a
-c340001.a
-c34001a.ada
-c34001c.ada
-c34001d.ada
-c34001f.ada
-c34002a.ada
-c34002c.ada
-c34003a.ada
-c34003c.ada
-c34004a.ada
-c34004c.ada
-c34005a.ada
-c34005c.ada
-c34005d.ada
-c34005f.ada
-c34005g.ada
-c34005i.ada
-c34005j.ada
-c34005l.ada
-c34005m.ada
-c34005o.ada
-c34005p.ada
-c34005r.ada
-c34005s.ada
-c34005u.ada
-c34005v.ada
-c34006a.ada
-c34006d.ada
-c34006f.ada
-c34006g.ada
-c34006j.ada
-c34006l.ada
-c34007a.ada
-c34007d.ada
-c34007f.ada
-c34007g.ada
-c34007i.ada
-c34007j.ada
-c34007m.ada
-c34007p.ada
-c34007r.ada
-c34007s.ada
-c34007u.ada
-c34007v.ada
-c34008a.ada
-c34009a.ada
-c34009d.ada
-c34009f.ada
-c34009g.ada
-c34009j.ada
-c34009l.ada
-c34011b.ada
-c34012a.ada
-c34014a.ada
-c34014c.ada
-c34014e.ada
-c34014g.ada
-c34014h.ada
-c34014n.ada
-c34014p.ada
-c34014r.ada
-c34014t.ada
-c34014u.ada
-c34018a.ada
-c340a01.a
-c340a02.a
-c341a01.a
-c341a02.a
-c341a03.a
-c341a04.a
-c35003a.ada
-c35003b.ada
-c35003d.ada
-c35102a.ada
-c352001.a
-c354002.a
-c354003.a
-c35502a.ada
-c35502b.ada
-c35502c.ada
-c35502d.tst
-c35502e.ada
-c35502f.tst
-c35502g.ada
-c35502h.ada
-c35502i.ada
-c35502j.ada
-c35502k.ada
-c35502l.ada
-c35502m.ada
-c35502n.ada
-c35502o.ada
-c35502p.ada
-c35503a.ada
-c35503b.ada
-c35503c.ada
-c35503d.tst
-c35503e.ada
-c35503f.tst
-c35503g.ada
-c35503h.ada
-c35503k.ada
-c35503l.ada
-c35503o.ada
-c35503p.ada
-c35504a.ada
-c35504b.ada
-c35505c.ada
-c35505e.ada
-c35505f.ada
-c35507a.ada
-c35507b.ada
-c35507c.ada
-c35507e.ada
-c35507g.ada
-c35507h.ada
-c35507i.ada
-c35507j.ada
-c35507k.ada
-c35507l.ada
-c35507m.ada
-c35507n.ada
-c35507o.ada
-c35507p.ada
-c35508a.ada
-c35508b.ada
-c35508c.ada
-c35508e.ada
-c35508g.ada
-c35508h.ada
-c35508k.ada
-c35508l.ada
-c35508o.ada
-c35508p.ada
-c35703a.ada
-c35704a.ada
-c35704b.ada
-c35704c.ada
-c35704d.ada
-c35801d.ada
-c35902d.ada
-c35904a.ada
-c35904b.ada
-c35a02a.ada
-c35a05a.ada
-c35a05d.ada
-c35a05n.ada
-c35a05q.ada
-c35a07a.ada
-c35a07d.ada
-c35a08b.ada
-c360002.a
-c36104a.ada
-c36104b.ada
-c36172a.ada
-c36172b.ada
-c36172c.ada
-c36174a.ada
-c36180a.ada
-c36202c.ada
-c36203a.ada
-c36204a.ada
-c36204b.ada
-c36204c.ada
-c36204d.ada
-c36205a.ada
-c36205b.ada
-c36205c.ada
-c36205d.ada
-c36205e.ada
-c36205f.ada
-c36205g.ada
-c36205h.ada
-c36205i.ada
-c36205j.ada
-c36205k.ada
-c36205l.ada
-c36301a.ada
-c36301b.ada
-c36302a.ada
-c36304a.ada
-c36305a.ada
-c37002a.ada
-c37003a.ada
-c37003b.ada
-c37005a.ada
-c37006a.ada
-c37008a.ada
-c37008b.ada
-c37009a.ada
-c37010a.ada
-c37010b.ada
-c371001.a
-c371002.a
-c371003.a
-c37102b.ada
-c37103a.ada
-c37105a.ada
-c37107a.ada
-c37108b.ada
-c37206a.ada
-c37207a.ada
-c37208a.ada
-c37208b.ada
-c37209a.ada
-c37209b.ada
-c37210a.ada
-c37211a.ada
-c37211b.ada
-c37211c.ada
-c37211d.ada
-c37211e.ada
-c37213b.ada
-c37213d.ada
-c37213f.ada
-c37213h.ada
-c37213j.ada
-c37213k.ada
-c37213l.ada
-c37215b.ada
-c37215d.ada
-c37215f.ada
-c37215h.ada
-c37217a.ada
-c37217b.ada
-c37217c.ada
-c37304a.ada
-c37305a.ada
-c37306a.ada
-c37309a.ada
-c37310a.ada
-c37312a.ada
-c37402a.ada
-c37403a.ada
-c37404a.ada
-c37404b.ada
-c37405a.ada
-c37411a.ada
-c38002a.ada
-c38002b.ada
-c38005a.ada
-c38005b.ada
-c38005c.ada
-c38006a.ada
-c38102a.ada
-c38102b.ada
-c38102c.ada
-c38102d.ada
-c38102e.ada
-c38104a.ada
-c38107a.ada
-c38107b.ada
-c38108a.ada
-c38108b.ada
-c38108c0.ada
-c38108c1.ada
-c38108c2.ada
-c38108d0.ada
-c38108d1.ada
-c38202a.ada
-c3900010.a
-c3900011.am
-c390002.a
-c390003.a
-c390004.a
-c3900050.a
-c3900051.a
-c3900052.a
-c3900053.am
-c3900060.a
-c3900061.a
-c3900062.a
-c3900063.am
-c390007.a
-c390010.a
-c390011.a
-c39006a.ada
-c39006b.ada
-c39006c0.ada
-c39006c1.ada
-c39006d.ada
-c39006e.ada
-c39006f0.ada
-c39006f1.ada
-c39006f2.ada
-c39006f3.ada
-c39006g.ada
-c39007a.ada
-c39007b.ada
-c39008a.ada
-c39008b.ada
-c39008c.ada
-c390a010.a
-c390a011.am
-c390a020.a
-c390a021.a
-c390a022.am
-c390a030.a
-c390a031.am
-c391001.a
-c391002.a
-c392002.a
-c392003.a
-c392004.a
-c392005.a
-c392008.a
-c392010.a
-c392011.a
-c392013.a
-c392014.a
-c392a01.a
-c392c05.a
-c392c07.a
-c392d01.a
-c392d02.a
-c392d03.a
-c393001.a
-c393007.a
-c393008.a
-c393009.a
-c393010.a
-c393011.a
-c393012.a
-c393a02.a
-c393a03.a
-c393a05.a
-c393a06.a
-c393b12.a
-c393b13.a
-c393b14.a
-c3a0001.a
-c3a0002.a
-c3a0003.a
-c3a0004.a
-c3a0005.a
-c3a0006.a
-c3a0007.a
-c3a0008.a
-c3a0009.a
-c3a0010.a
-c3a0011.a
-c3a00120.a
-c3a00121.a
-c3a00122.am
-c3a0013.a
-c3a0014.a
-c3a0015.a
-c3a1001.a
-c3a1002.a
-c3a2001.a
-c3a2002.a
-c3a2003.a
-c3a2a01.a
-c3a2a02.a
-c410001.a
-c41101d.ada
-c41103a.ada
-c41103b.ada
-c41104a.ada
-c41105a.ada
-c41107a.ada
-c41201d.ada
-c41203a.ada
-c41203b.ada
-c41204a.ada
-c41205a.ada
-c41206a.ada
-c41207a.ada
-c41301a.ada
-c41303a.ada
-c41303b.ada
-c41303c.ada
-c41303e.ada
-c41303f.ada
-c41303g.ada
-c41303i.ada
-c41303j.ada
-c41303k.ada
-c41303m.ada
-c41303n.ada
-c41303o.ada
-c41303q.ada
-c41303r.ada
-c41303s.ada
-c41303u.ada
-c41303v.ada
-c41303w.ada
-c41304a.ada
-c41304b.ada
-c41306a.ada
-c41306b.ada
-c41306c.ada
-c41307d.ada
-c41309a.ada
-c41320a.ada
-c41321a.ada
-c41322a.ada
-c41323a.ada
-c41324a.ada
-c41325a.ada
-c41326a.ada
-c41327a.ada
-c41328a.ada
-c41401a.ada
-c41402a.ada
-c41404a.ada
-c420001.a
-c42006a.ada
-c42007e.ada
-c43003a.ada
-c43004a.ada
-c43004c.ada
-c431001.a
-c43103a.ada
-c43103b.ada
-c43104a.ada
-c43105a.ada
-c43105b.ada
-c43106a.ada
-c43107a.ada
-c43108a.ada
-c432001.a
-c432002.a
-c432003.a
-c432004.a
-c43204a.ada
-c43204c.ada
-c43204e.ada
-c43204f.ada
-c43204g.ada
-c43204h.ada
-c43204i.ada
-c43205a.ada
-c43205b.ada
-c43205c.ada
-c43205d.ada
-c43205e.ada
-c43205g.ada
-c43205h.ada
-c43205i.ada
-c43205j.ada
-c43205k.ada
-c43206a.ada
-c43207b.ada
-c43207d.ada
-c43208a.ada
-c43208b.ada
-c43209a.ada
-c43210a.ada
-c43211a.ada
-c43212a.ada
-c43212c.ada
-c43214a.ada
-c43214b.ada
-c43214c.ada
-c43214d.ada
-c43214e.ada
-c43214f.ada
-c43215a.ada
-c43215b.ada
-c43222a.ada
-c43224a.ada
-c433001.a
-c44003d.ada
-c44003f.ada
-c44003g.ada
-c450001.a
-c45112a.ada
-c45112b.ada
-c45113a.ada
-c45114b.ada
-c452001.a
-c45201a.ada
-c45201b.ada
-c45202b.ada
-c45210a.ada
-c45211a.ada
-c45220a.ada
-c45220b.ada
-c45220c.ada
-c45220d.ada
-c45220e.ada
-c45220f.ada
-c45231a.ada
-c45231b.dep
-c45231c.dep
-c45231d.tst
-c45232b.ada
-c45242b.ada
-c45251a.ada
-c45252a.ada
-c45252b.ada
-c45253a.ada
-c45262a.ada
-c45262b.ada
-c45262c.ada
-c45262d.ada
-c45264a.ada
-c45264b.ada
-c45264c.ada
-c45265a.ada
-c45271a.ada
-c45272a.ada
-c45273a.ada
-c45274a.ada
-c45274b.ada
-c45274c.ada
-c45281a.ada
-c45282a.ada
-c45282b.ada
-c45291a.ada
-c45303a.ada
-c45304a.ada
-c45304b.dep
-c45304c.dep
-c45322a.ada
-c45323a.ada
-c45331a.ada
-c45342a.ada
-c45343a.ada
-c45344a.ada
-c45345b.ada
-c45347a.ada
-c45347b.ada
-c45347c.ada
-c45347d.ada
-c45411a.ada
-c45411b.dep
-c45411c.dep
-c45411d.ada
-c45413a.ada
-c45431a.ada
-c455001.a
-c45502b.dep
-c45502c.dep
-c45503a.ada
-c45503b.dep
-c45503c.dep
-c45504a.ada
-c45504b.dep
-c45504c.dep
-c45504d.ada
-c45504e.dep
-c45504f.dep
-c45505a.ada
-c45523a.ada
-c45531a.ada
-c45531b.ada
-c45531c.ada
-c45531d.ada
-c45531e.ada
-c45531f.ada
-c45531g.ada
-c45531h.ada
-c45531i.ada
-c45531j.ada
-c45531k.ada
-c45531l.ada
-c45531m.dep
-c45531n.dep
-c45531o.dep
-c45531p.dep
-c45532a.ada
-c45532b.ada
-c45532c.ada
-c45532d.ada
-c45532e.ada
-c45532f.ada
-c45532g.ada
-c45532h.ada
-c45532i.ada
-c45532j.ada
-c45532k.ada
-c45532l.ada
-c45532m.dep
-c45532n.dep
-c45532o.dep
-c45532p.dep
-c45534b.ada
-c45536a.dep
-c45611a.ada
-c45611b.dep
-c45611c.dep
-c45613a.ada
-c45613b.dep
-c45613c.dep
-c45614a.ada
-c45614b.dep
-c45614c.dep
-c45622a.ada
-c45624a.ada
-c45624b.ada
-c45631a.ada
-c45631b.dep
-c45631c.dep
-c45632a.ada
-c45632b.dep
-c45632c.dep
-c45651a.ada
-c45662a.ada
-c45662b.ada
-c45672a.ada
-c460001.a
-c460002.a
-c460004.a
-c460005.a
-c460006.a
-c460007.a
-c460008.a
-c460009.a
-c460010.a
-c460011.a
-c460012.a
-c46011a.ada
-c46013a.ada
-c46014a.ada
-c46021a.ada
-c46024a.ada
-c46031a.ada
-c46032a.ada
-c46033a.ada
-c46041a.ada
-c46042a.ada
-c46043b.ada
-c46044b.ada
-c46051a.ada
-c46051b.ada
-c46051c.ada
-c46052a.ada
-c46053a.ada
-c46054a.ada
-c460a01.a
-c460a02.a
-c47002a.ada
-c47002b.ada
-c47002c.ada
-c47002d.ada
-c47003a.ada
-c47004a.ada
-c47005a.ada
-c47006a.ada
-c47007a.ada
-c47008a.ada
-c47009a.ada
-c47009b.ada
-c48004a.ada
-c48004b.ada
-c48004c.ada
-c48004d.ada
-c48004e.ada
-c48004f.ada
-c48005a.ada
-c48005b.ada
-c48006a.ada
-c48006b.ada
-c48007a.ada
-c48007b.ada
-c48007c.ada
-c48008a.ada
-c48008c.ada
-c48009a.ada
-c48009b.ada
-c48009c.ada
-c48009d.ada
-c48009e.ada
-c48009f.ada
-c48009g.ada
-c48009h.ada
-c48009i.ada
-c48009j.ada
-c48010a.ada
-c48011a.ada
-c48012a.ada
-c490001.a
-c490002.a
-c490003.a
-c49020a.ada
-c49021a.ada
-c49022a.ada
-c49022b.ada
-c49022c.ada
-c49023a.ada
-c49024a.ada
-c49025a.ada
-c49026a.ada
-c4a005b.ada
-c4a006a.ada
-c4a007a.tst
-c4a010a.ada
-c4a010b.ada
-c4a011a.ada
-c4a012b.ada
-c4a013a.ada
-c4a014a.ada
-c51004a.ada
-c52005a.ada
-c52005b.ada
-c52005c.ada
-c52005d.ada
-c52005e.ada
-c52005f.ada
-c52008a.ada
-c52008b.ada
-c52009a.ada
-c52009b.ada
-c52010a.ada
-c52011a.ada
-c52011b.ada
-c52101a.ada
-c52102a.ada
-c52102b.ada
-c52102c.ada
-c52102d.ada
-c52103a.ada
-c52103b.ada
-c52103c.ada
-c52103f.ada
-c52103g.ada
-c52103h.ada
-c52103k.ada
-c52103l.ada
-c52103m.ada
-c52103p.ada
-c52103q.ada
-c52103r.ada
-c52103x.ada
-c52104a.ada
-c52104b.ada
-c52104c.ada
-c52104f.ada
-c52104g.ada
-c52104h.ada
-c52104k.ada
-c52104l.ada
-c52104m.ada
-c52104p.ada
-c52104q.ada
-c52104r.ada
-c52104x.ada
-c52104y.ada
-c53007a.ada
-c540001.a
-c54a03a.ada
-c54a04a.ada
-c54a07a.ada
-c54a13a.ada
-c54a13b.ada
-c54a13c.ada
-c54a13d.ada
-c54a22a.ada
-c54a23a.ada
-c54a24a.ada
-c54a24b.ada
-c54a42a.ada
-c54a42b.ada
-c54a42c.ada
-c54a42d.ada
-c54a42e.ada
-c54a42f.ada
-c54a42g.ada
-c55b03a.ada
-c55b04a.ada
-c55b05a.ada
-c55b06a.ada
-c55b06b.ada
-c55b07a.dep
-c55b07b.dep
-c55b10a.ada
-c55b11a.ada
-c55b11b.ada
-c55b15a.ada
-c55b16a.ada
-c55c02a.ada
-c55c02b.ada
-c56002a.ada
-c57003a.ada
-c57004a.ada
-c57004b.ada
-c58004c.ada
-c58004d.ada
-c58004g.ada
-c58005a.ada
-c58005b.ada
-c58005h.ada
-c58006a.ada
-c58006b.ada
-c59002a.ada
-c59002b.ada
-c59002c.ada
-c61008a.ada
-c61009a.ada
-c61010a.ada
-c62002a.ada
-c62003a.ada
-c62003b.ada
-c62004a.ada
-c62006a.ada
-c631001.a
-c640001.a
-c64002b.ada
-c64004g.ada
-c64005a.ada
-c64005b.ada
-c64005c.ada
-c64005d0.ada
-c64005da.ada
-c64005db.ada
-c64005dc.ada
-c641001.a
-c64103b.ada
-c64103c.ada
-c64103d.ada
-c64103e.ada
-c64103f.ada
-c64104a.ada
-c64104b.ada
-c64104c.ada
-c64104d.ada
-c64104e.ada
-c64104f.ada
-c64104g.ada
-c64104h.ada
-c64104i.ada
-c64104j.ada
-c64104k.ada
-c64104l.ada
-c64104m.ada
-c64104n.ada
-c64104o.ada
-c64105a.ada
-c64105b.ada
-c64105c.ada
-c64105d.ada
-c64106a.ada
-c64106b.ada
-c64106c.ada
-c64106d.ada
-c64107a.ada
-c64108a.ada
-c64109a.ada
-c64109b.ada
-c64109c.ada
-c64109d.ada
-c64109e.ada
-c64109f.ada
-c64109g.ada
-c64109h.ada
-c64109i.ada
-c64109j.ada
-c64109k.ada
-c64109l.ada
-c64201b.ada
-c64201c.ada
-c64202a.ada
-c650001.a
-c65003a.ada
-c65003b.ada
-c66002a.ada
-c66002c.ada
-c66002d.ada
-c66002e.ada
-c66002f.ada
-c66002g.ada
-c67002a.ada
-c67002b.ada
-c67002c.ada
-c67002d.ada
-c67002e.ada
-c67003f.ada
-c67005a.ada
-c67005b.ada
-c67005c.ada
-c67005d.ada
-c72001b.ada
-c72002a.ada
-c730001.a
-c730002.a
-c730003.a
-c730004.a
-c73002a.ada
-c730a01.a
-c730a02.a
-c731001.a
-c74004a.ada
-c74203a.ada
-c74206a.ada
-c74207b.ada
-c74208a.ada
-c74208b.ada
-c74209a.ada
-c74210a.ada
-c74211a.ada
-c74211b.ada
-c74302a.ada
-c74302b.ada
-c74305a.ada
-c74305b.ada
-c74306a.ada
-c74307a.ada
-c74401d.ada
-c74401e.ada
-c74401k.ada
-c74401q.ada
-c74402a.ada
-c74402b.ada
-c74406a.ada
-c74407b.ada
-c74409b.ada
-c760001.a
-c760002.a
-c760007.a
-c760009.a
-c760010.a
-c760011.a
-c760012.a
-c760013.a
-c761001.a
-c761002.a
-c761003.a
-c761004.a
-c761005.a
-c761006.a
-c761007.a
-c761010.a
-c761011.a
-c83007a.ada
-c83012d.ada
-c83022a.ada
-c83022g0.ada
-c83022g1.ada
-c83023a.ada
-c83024a.ada
-c83024e0.ada
-c83024e1.ada
-c83025a.ada
-c83025c.ada
-c83027a.ada
-c83027c.ada
-c83028a.ada
-c83029a.ada
-c83030a.ada
-c83030c.ada
-c83031a.ada
-c83031c.ada
-c83031e.ada
-c83032a.ada
-c83033a.ada
-c83051a.ada
-c83b02a.ada
-c83b02b.ada
-c83e02a.ada
-c83e02b.ada
-c83e03a.ada
-c83f01a.ada
-c83f01b.ada
-c83f01c0.ada
-c83f01c1.ada
-c83f01c2.ada
-c83f01d0.ada
-c83f01d1.ada
-c83f03a.ada
-c83f03b.ada
-c83f03c0.ada
-c83f03c1.ada
-c83f03c2.ada
-c83f03d0.ada
-c83f03d1.ada
-c840001.a
-c84002a.ada
-c84005a.ada
-c84008a.ada
-c84009a.ada
-c85004b.ada
-c85005a.ada
-c85005b.ada
-c85005c.ada
-c85005d.ada
-c85005e.ada
-c85005f.ada
-c85005g.ada
-c85006a.ada
-c85006b.ada
-c85006c.ada
-c85006d.ada
-c85006e.ada
-c85006f.ada
-c85006g.ada
-c85007a.ada
-c85007e.ada
-c85009a.ada
-c85011a.ada
-c85013a.ada
-c85014a.ada
-c85014b.ada
-c85014c.ada
-c85017a.ada
-c85018a.ada
-c85018b.ada
-c85019a.ada
-c854001.a
-c854002.a
-c86003a.ada
-c86004a.ada
-c86004b0.ada
-c86004b1.ada
-c86004b2.ada
-c86004c0.ada
-c86004c1.ada
-c86004c2.ada
-c86006i.ada
-c86007a.ada
-c87a05a.ada
-c87a05b.ada
-c87b02a.ada
-c87b02b.ada
-c87b03a.ada
-c87b04a.ada
-c87b04b.ada
-c87b04c.ada
-c87b05a.ada
-c87b06a.ada
-c87b07a.ada
-c87b07b.ada
-c87b07c.ada
-c87b07d.ada
-c87b07e.ada
-c87b08a.ada
-c87b09a.ada
-c87b09c.ada
-c87b10a.ada
-c87b11a.ada
-c87b11b.ada
-c87b13a.ada
-c87b14a.ada
-c87b14b.ada
-c87b14c.ada
-c87b14d.ada
-c87b15a.ada
-c87b16a.ada
-c87b17a.ada
-c87b18a.ada
-c87b18b.ada
-c87b19a.ada
-c87b23a.ada
-c87b24a.ada
-c87b24b.ada
-c87b26b.ada
-c87b27a.ada
-c87b28a.ada
-c87b29a.ada
-c87b30a.ada
-c87b31a.ada
-c87b32a.ada
-c87b33a.ada
-c87b34a.ada
-c87b34b.ada
-c87b34c.ada
-c87b35c.ada
-c87b38a.ada
-c87b39a.ada
-c87b40a.ada
-c87b41a.ada
-c87b42a.ada
-c87b43a.ada
-c87b44a.ada
-c87b45a.ada
-c87b45c.ada
-c87b47a.ada
-c87b48a.ada
-c87b48b.ada
-c87b50a.ada
-c87b54a.ada
-c87b57a.ada
-c87b62a.ada
-c87b62b.ada
-c87b62c.ada
-c87b62d.tst
-c910001.a
-c910002.a
-c910003.a
-c91004b.ada
-c91004c.ada
-c91006a.ada
-c91007a.ada
-c92002a.ada
-c92003a.ada
-c92005a.ada
-c92005b.ada
-c92006a.ada
-c930001.a
-c93001a.ada
-c93002a.ada
-c93003a.ada
-c93004a.ada
-c93004b.ada
-c93004c.ada
-c93004d.ada
-c93004f.ada
-c93005a.ada
-c93005b.ada
-c93005c.ada
-c93005d.ada
-c93005e.ada
-c93005f.ada
-c93005g.ada
-c93005h.ada
-c93006a.ada
-c93007a.ada
-c93008a.ada
-c93008b.ada
-c940001.a
-c940002.a
-c940004.a
-c940005.a
-c940006.a
-c940007.a
-c940010.a
-c940011.a
-c940012.a
-c940013.a
-c940014.a
-c940015.a
-c940016.a
-c94001a.ada
-c94001b.ada
-c94001c.ada
-c94001e.ada
-c94001f.ada
-c94001g.ada
-c94002a.ada
-c94002b.ada
-c94002d.ada
-c94002e.ada
-c94002f.ada
-c94002g.ada
-c94004a.ada
-c94004b.ada
-c94004c.ada
-c94005a.ada
-c94005b.ada
-c94006a.ada
-c94007a.ada
-c94007b.ada
-c94008a.ada
-c94008b.ada
-c94008c.ada
-c94008d.ada
-c94010a.ada
-c94011a.ada
-c94020a.ada
-c940a03.a
-c95008a.ada
-c95009a.ada
-c95010a.ada
-c95011a.ada
-c95012a.ada
-c95021a.ada
-c95022a.ada
-c95022b.ada
-c95033a.ada
-c95033b.ada
-c95034a.ada
-c95034b.ada
-c95035a.ada
-c95040a.ada
-c95040b.ada
-c95040c.ada
-c95040d.ada
-c95041a.ada
-c95065a.ada
-c95065b.ada
-c95065c.ada
-c95065d.ada
-c95065e.ada
-c95065f.ada
-c95066a.ada
-c95067a.ada
-c95071a.ada
-c95072a.ada
-c95072b.ada
-c95073a.ada
-c95074c.ada
-c95076a.ada
-c95078a.ada
-c95080b.ada
-c95082g.ada
-c95085a.ada
-c95085b.ada
-c95085c.ada
-c95085d.ada
-c95085e.ada
-c95085f.ada
-c95085g.ada
-c95085h.ada
-c95085i.ada
-c95085j.ada
-c95085k.ada
-c95085l.ada
-c95085m.ada
-c95085n.ada
-c95085o.ada
-c95086a.ada
-c95086b.ada
-c95086c.ada
-c95086d.ada
-c95086e.ada
-c95086f.ada
-c95087a.ada
-c95087b.ada
-c95087c.ada
-c95087d.ada
-c95088a.ada
-c95089a.ada
-c95090a.ada
-c95092a.ada
-c95093a.ada
-c95095a.ada
-c95095b.ada
-c95095c.ada
-c95095d.ada
-c95095e.ada
-c951001.a
-c951002.a
-c953001.a
-c953002.a
-c953003.a
-c954001.a
-c954010.a
-c954011.a
-c954012.a
-c954013.a
-c954014.a
-c954015.a
-c954016.a
-c954017.a
-c954018.a
-c954019.a
-c954020.a
-c954021.a
-c954022.a
-c954023.a
-c954024.a
-c954025.a
-c954026.a
-c954a01.a
-c954a02.a
-c954a03.a
-c960001.a
-c960002.a
-c960004.a
-c96001a.ada
-c96004a.ada
-c96005a.ada
-c96005b.tst
-c96005d.ada
-c96005f.ada
-c96006a.ada
-c96007a.ada
-c96008a.ada
-c96008b.ada
-c97112a.ada
-c97113a.ada
-c97114a.ada
-c97115a.ada
-c97116a.ada
-c97117a.ada
-c97117b.ada
-c97117c.ada
-c97118a.ada
-c97120a.ada
-c97120b.ada
-c97201a.ada
-c97201b.ada
-c97201c.ada
-c97201d.ada
-c97201e.ada
-c97201g.ada
-c97201h.ada
-c97201x.ada
-c97202a.ada
-c97203a.ada
-c97203b.ada
-c97203c.ada
-c97204a.ada
-c97204b.ada
-c97205a.ada
-c97205b.ada
-c97301a.ada
-c97301b.ada
-c97301c.ada
-c97301d.ada
-c97301e.ada
-c97302a.ada
-c97303a.ada
-c97303b.ada
-c97303c.ada
-c97304a.ada
-c97304b.ada
-c97305a.ada
-c97305b.ada
-c97305c.ada
-c97305d.ada
-c97307a.ada
-c974001.a
-c974002.a
-c974003.a
-c974004.a
-c974005.a
-c974006.a
-c974007.a
-c974008.a
-c974009.a
-c974010.a
-c974011.a
-c974012.a
-c974013.a
-c974014.a
-c980001.a
-c980002.a
-c980003.a
-c99004a.ada
-c99005a.ada
-c9a003a.ada
-c9a004a.ada
-c9a007a.ada
-c9a009a.ada
-c9a009c.ada
-c9a009f.ada
-c9a009g.ada
-c9a009h.ada
-c9a010a.ada
-c9a011a.ada
-c9a011b.ada
-ca1003a.ada
-ca1004a.ada
-ca1005a.ada
-ca1006a.ada
-ca1011a0.ada
-ca1011a1.ada
-ca1011a2.ada
-ca1011a3.ada
-ca1011a4.ada
-ca1011a5.ada
-ca1011a6.ada
-ca1012a0.ada
-ca1012a1.ada
-ca1012a2.ada
-ca1012a3.ada
-ca1012a4.ada
-ca1012b0.ada
-ca1012b2.ada
-ca1012b4.ada
-ca1013a0.ada
-ca1013a1.ada
-ca1013a2.ada
-ca1013a3.ada
-ca1013a4.ada
-ca1013a5.ada
-ca1013a6.ada
-ca1014a0.ada
-ca1014a1.ada
-ca1014a2.ada
-ca1014a3.ada
-ca1020e0.ada
-ca1020e1.ada
-ca1020e2.ada
-ca1020e3.ada
-ca1022a0.ada
-ca1022a1.ada
-ca1022a2.ada
-ca1022a3.ada
-ca1022a4.ada
-ca1022a5.ada
-ca1022a6.ada
-ca11001.a
-ca11002.a
-ca11003.a
-ca110040.a
-ca110041.a
-ca110042.am
-ca110050.a
-ca110051.am
-ca11006.a
-ca11007.a
-ca11008.a
-ca11009.a
-ca11010.a
-ca11011.a
-ca11012.a
-ca11013.a
-ca11014.a
-ca11015.a
-ca11016.a
-ca11017.a
-ca11018.a
-ca11019.a
-ca11020.a
-ca11021.a
-ca11022.a
-ca1102a0.ada
-ca1102a1.ada
-ca1102a2.ada
-ca1106a.ada
-ca1108a.ada
-ca1108b.ada
-ca11a01.a
-ca11a02.a
-ca11b01.a
-ca11b02.a
-ca11c01.a
-ca11c02.a
-ca11c03.a
-ca11d010.a
-ca11d011.a
-ca11d012.a
-ca11d013.am
-ca11d02.a
-ca11d03.a
-ca13001.a
-ca13002.a
-ca13003.a
-ca13a01.a
-ca13a02.a
-ca140230.a
-ca140231.a
-ca140232.am
-ca140233.a
-ca140280.a
-ca140281.a
-ca140282.a
-ca140283.am
-ca15003.a
-ca200020.a
-ca200021.a
-ca200022.am
-ca2001h0.ada
-ca2001h1.ada
-ca2001h2.ada
-ca2001h3.ada
-ca2002a0.ada
-ca2002a1.ada
-ca2002a2.ada
-ca2003a0.ada
-ca2003a1.ada
-ca2004a0.ada
-ca2004a1.ada
-ca2004a2.ada
-ca2004a3.ada
-ca2004a4.ada
-ca2007a0.ada
-ca2007a1.ada
-ca2007a2.ada
-ca2007a3.ada
-ca2008a0.ada
-ca2008a1.ada
-ca2008a2.ada
-ca2009a.ada
-ca2009c0.ada
-ca2009c1.ada
-ca2009d.ada
-ca2009f0.ada
-ca2009f1.ada
-ca2009f2.ada
-ca2011b.ada
-ca21001.a
-ca3011a0.ada
-ca3011a1.ada
-ca3011a2.ada
-ca3011a3.ada
-ca3011a4.ada
-ca5003a0.ada
-ca5003a1.ada
-ca5003a2.ada
-ca5003a3.ada
-ca5003a4.ada
-ca5003a5.ada
-ca5003a6.ada
-ca5003b0.ada
-ca5003b1.ada
-ca5003b2.ada
-ca5003b3.ada
-ca5003b4.ada
-ca5003b5.ada
-ca5004a.ada
-ca5004b0.ada
-ca5004b1.ada
-ca5004b2.ada
-ca5006a.ada
-cb10002.a
-cb1001a.ada
-cb1004a.ada
-cb1005a.ada
-cb1010a.ada
-cb1010c.ada
-cb1010d.ada
-cb20001.a
-cb20003.a
-cb20004.a
-cb20005.a
-cb20006.a
-cb20007.a
-cb2004a.ada
-cb2005a.ada
-cb2006a.ada
-cb2007a.ada
-cb20a02.a
-cb3003a.ada
-cb3003b.ada
-cb3004a.ada
-cb40005.a
-cb4001a.ada
-cb4002a.ada
-cb4003a.ada
-cb4004a.ada
-cb4005a.ada
-cb4006a.ada
-cb4007a.ada
-cb4008a.ada
-cb4009a.ada
-cb4013a.ada
-cb40a01.a
-cb40a020.a
-cb40a021.am
-cb40a030.a
-cb40a031.am
-cb40a04.a
-cb41001.a
-cb41002.a
-cb41003.a
-cb41004.a
-cb5001a.ada
-cb5001b.ada
-cb5002a.ada
-cc1004a.ada
-cc1005b.ada
-cc1010a.ada
-cc1010b.ada
-cc1018a.ada
-cc1104c.ada
-cc1107b.ada
-cc1111a.ada
-cc1204a.ada
-cc1207b.ada
-cc1220a.ada
-cc1221a.ada
-cc1221b.ada
-cc1221c.ada
-cc1221d.ada
-cc1222a.ada
-cc1223a.ada
-cc1224a.ada
-cc1225a.tst
-cc1226b.ada
-cc1227a.ada
-cc1301a.ada
-cc1302a.ada
-cc1304a.ada
-cc1304b.ada
-cc1307a.ada
-cc1307b.ada
-cc1308a.ada
-cc1310a.ada
-cc1311a.ada
-cc1311b.ada
-cc2002a.ada
-cc30001.a
-cc30002.a
-cc3004a.ada
-cc3007a.ada
-cc3007b.ada
-cc3011a.ada
-cc3011d.ada
-cc3012a.ada
-cc3015a.ada
-cc3016b.ada
-cc3016c.ada
-cc3016f.ada
-cc3016i.ada
-cc3017b.ada
-cc3017c.ada
-cc3019a.ada
-cc3019b0.ada
-cc3019b1.ada
-cc3019b2.ada
-cc3019c0.ada
-cc3019c1.ada
-cc3019c2.ada
-cc3106b.ada
-cc3120a.ada
-cc3120b.ada
-cc3121a.ada
-cc3123a.ada
-cc3125a.ada
-cc3125b.ada
-cc3125c.ada
-cc3125d.ada
-cc3126a.ada
-cc3127a.ada
-cc3128a.ada
-cc3203a.ada
-cc3207b.ada
-cc3220a.ada
-cc3221a.ada
-cc3222a.ada
-cc3223a.ada
-cc3224a.ada
-cc3225a.ada
-cc3230a.ada
-cc3231a.ada
-cc3232a.ada
-cc3233a.ada
-cc3234a.ada
-cc3235a.ada
-cc3236a.ada
-cc3240a.ada
-cc3305a.ada
-cc3305b.ada
-cc3305c.ada
-cc3305d.ada
-cc3601a.ada
-cc3601c.ada
-cc3602a.ada
-cc3603a.ada
-cc3605a.ada
-cc3606a.ada
-cc3606b.ada
-cc3607b.ada
-cc40001.a
-cc50001.a
-cc50a01.a
-cc50a02.a
-cc51001.a
-cc51002.a
-cc51003.a
-cc51004.a
-cc51006.a
-cc51007.a
-cc51a01.a
-cc51b03.a
-cc51d01.a
-cc51d02.a
-cc54001.a
-cc54002.a
-cc54003.a
-cc54004.a
-cc70001.a
-cc70002.a
-cc70003.a
-cc70a01.a
-cc70a02.a
-cc70b01.a
-cc70b02.a
-cc70c01.a
-cc70c02.a
-cd10001.a
-cd1009a.ada
-cd1009b.ada
-cd1009d.ada
-cd1009e.ada
-cd1009f.ada
-cd1009g.ada
-cd1009h.ada
-cd1009i.ada
-cd1009j.ada
-cd1009k.tst
-cd1009l.ada
-cd1009m.ada
-cd1009n.ada
-cd1009o.ada
-cd1009p.ada
-cd1009q.ada
-cd1009r.ada
-cd1009s.ada
-cd1009t.tst
-cd1009u.tst
-cd1009v.ada
-cd1009w.ada
-cd1009x.ada
-cd1009y.ada
-cd1009z.ada
-cd1c03a.ada
-cd1c03b.ada
-cd1c03c.ada
-cd1c03e.tst
-cd1c03f.ada
-cd1c03g.ada
-cd1c03h.ada
-cd1c03i.ada
-cd1c04a.ada
-cd1c04d.ada
-cd1c04e.ada
-cd1c06a.tst
-cd20001.a
-cd2a21a.ada
-cd2a21c.ada
-cd2a21e.ada
-cd2a22a.ada
-cd2a22e.ada
-cd2a22i.ada
-cd2a22j.ada
-cd2a23a.ada
-cd2a23e.ada
-cd2a24a.ada
-cd2a24e.ada
-cd2a24i.ada
-cd2a24j.ada
-cd2a31a.ada
-cd2a31c.ada
-cd2a31e.ada
-cd2a32a.ada
-cd2a32c.ada
-cd2a32e.ada
-cd2a32g.ada
-cd2a32i.ada
-cd2a32j.ada
-cd2a51a.ada
-cd2a53a.ada
-cd2a53e.ada
-cd2a83c.tst
-cd2a91c.tst
-cd2b11a.ada
-cd2b11b.ada
-cd2b11d.ada
-cd2b11e.ada
-cd2b11f.ada
-cd2b15c.ada
-cd2b16a.ada
-cd2c11a.tst
-cd2c11d.tst
-cd2d11a.ada
-cd2d13a.ada
-cd30001.a
-cd30002.a
-cd30003.a
-cd30004.a
-cd300050.am
-cd300051.c
-cd3014a.ada
-cd3014c.ada
-cd3014d.ada
-cd3014f.ada
-cd3015a.ada
-cd3015c.ada
-cd3015e.ada
-cd3015f.ada
-cd3015g.ada
-cd3015h.ada
-cd3015i.ada
-cd3015k.ada
-cd3021a.ada
-cd33001.a
-cd33002.a
-cd40001.a
-cd4031a.ada
-cd4041a.tst
-cd4051a.ada
-cd4051b.ada
-cd4051c.ada
-cd4051d.ada
-cd5003a.ada
-cd5003b.ada
-cd5003c.ada
-cd5003d.ada
-cd5003e.ada
-cd5003f.ada
-cd5003g.ada
-cd5003h.ada
-cd5003i.ada
-cd5011a.ada
-cd5011c.ada
-cd5011e.ada
-cd5011g.ada
-cd5011i.ada
-cd5011k.ada
-cd5011m.ada
-cd5011q.ada
-cd5011s.ada
-cd5012a.ada
-cd5012b.ada
-cd5012e.ada
-cd5012f.ada
-cd5012i.ada
-cd5012m.ada
-cd5013a.ada
-cd5013c.ada
-cd5013e.ada
-cd5013g.ada
-cd5013i.ada
-cd5013k.ada
-cd5013m.ada
-cd5013o.ada
-cd5014a.ada
-cd5014c.ada
-cd5014e.ada
-cd5014g.ada
-cd5014i.ada
-cd5014k.ada
-cd5014m.ada
-cd5014o.ada
-cd5014t.ada
-cd5014v.ada
-cd5014x.ada
-cd5014y.ada
-cd5014z.ada
-cd70001.a
-cd7002a.ada
-cd7007b.ada
-cd7101d.ada
-cd7101e.dep
-cd7101f.dep
-cd7101g.tst
-cd7103d.ada
-cd7202a.ada
-cd7204b.ada
-cd7204c.ada
-cd72a01.a
-cd72a02.a
-cd7305a.ada
-cd90001.a
-cd92001.a
-cda201a.ada
-cda201b.ada
-cda201c.ada
-cda201e.ada
-cdb0a01.a
-cdb0a02.a
-cdd1001.a
-cdd2001.a
-cde0001.a
-ce2102a.ada
-ce2102b.ada
-ce2102c.tst
-ce2102d.ada
-ce2102e.ada
-ce2102f.ada
-ce2102g.ada
-ce2102h.tst
-ce2102i.ada
-ce2102j.ada
-ce2102k.ada
-ce2102l.ada
-ce2102m.ada
-ce2102n.ada
-ce2102o.ada
-ce2102p.ada
-ce2102q.ada
-ce2102r.ada
-ce2102s.ada
-ce2102t.ada
-ce2102u.ada
-ce2102v.ada
-ce2102w.ada
-ce2102x.ada
-ce2102y.ada
-ce2103a.tst
-ce2103b.tst
-ce2103c.ada
-ce2103d.ada
-ce2104a.ada
-ce2104b.ada
-ce2104c.ada
-ce2104d.ada
-ce2106a.ada
-ce2106b.ada
-ce2108e.ada
-ce2108f.ada
-ce2108g.ada
-ce2108h.ada
-ce2109a.ada
-ce2109b.ada
-ce2109c.ada
-ce2110a.ada
-ce2110c.ada
-ce2111a.ada
-ce2111b.ada
-ce2111c.ada
-ce2111e.ada
-ce2111f.ada
-ce2111g.ada
-ce2111i.ada
-ce2201a.ada
-ce2201b.ada
-ce2201c.ada
-ce2201d.dep
-ce2201e.dep
-ce2201f.ada
-ce2201g.ada
-ce2201h.ada
-ce2201i.ada
-ce2201j.ada
-ce2201k.ada
-ce2201l.ada
-ce2201m.ada
-ce2201n.ada
-ce2202a.ada
-ce2203a.tst
-ce2204a.ada
-ce2204b.ada
-ce2204c.ada
-ce2204d.ada
-ce2205a.ada
-ce2206a.ada
-ce2208b.ada
-ce2401a.ada
-ce2401b.ada
-ce2401c.ada
-ce2401e.ada
-ce2401f.ada
-ce2401h.ada
-ce2401i.ada
-ce2401j.ada
-ce2401k.ada
-ce2401l.ada
-ce2402a.ada
-ce2403a.tst
-ce2404a.ada
-ce2404b.ada
-ce2405b.ada
-ce2406a.ada
-ce2407a.ada
-ce2407b.ada
-ce2408a.ada
-ce2408b.ada
-ce2409a.ada
-ce2409b.ada
-ce2410a.ada
-ce2410b.ada
-ce2411a.ada
-ce3002b.tst
-ce3002c.tst
-ce3002d.ada
-ce3002f.ada
-ce3102a.ada
-ce3102b.tst
-ce3102d.ada
-ce3102e.ada
-ce3102f.ada
-ce3102g.ada
-ce3102h.ada
-ce3102i.ada
-ce3102j.ada
-ce3102k.ada
-ce3103a.ada
-ce3104a.ada
-ce3104b.ada
-ce3104c.ada
-ce3106a.ada
-ce3106b.ada
-ce3107a.tst
-ce3107b.ada
-ce3108a.ada
-ce3108b.ada
-ce3110a.ada
-ce3112c.ada
-ce3112d.ada
-ce3114a.ada
-ce3115a.ada
-ce3201a.ada
-ce3202a.ada
-ce3206a.ada
-ce3207a.ada
-ce3301a.ada
-ce3302a.ada
-ce3303a.ada
-ce3304a.tst
-ce3305a.ada
-ce3306a.ada
-ce3401a.ada
-ce3402a.ada
-ce3402c.ada
-ce3402d.ada
-ce3402e.ada
-ce3403a.ada
-ce3403b.ada
-ce3403c.ada
-ce3403d.ada
-ce3403e.ada
-ce3403f.ada
-ce3404a.ada
-ce3404b.ada
-ce3404c.ada
-ce3404d.ada
-ce3405a.ada
-ce3405c.ada
-ce3405d.ada
-ce3406a.ada
-ce3406b.ada
-ce3406c.ada
-ce3406d.ada
-ce3407a.ada
-ce3407b.ada
-ce3407c.ada
-ce3408a.ada
-ce3408b.ada
-ce3408c.ada
-ce3409a.ada
-ce3409b.ada
-ce3409c.ada
-ce3409d.ada
-ce3409e.ada
-ce3410a.ada
-ce3410b.ada
-ce3410c.ada
-ce3410d.ada
-ce3410e.ada
-ce3411a.ada
-ce3411c.ada
-ce3412a.ada
-ce3413a.ada
-ce3413b.ada
-ce3413c.ada
-ce3414a.ada
-ce3601a.ada
-ce3602a.ada
-ce3602b.ada
-ce3602c.ada
-ce3602d.ada
-ce3603a.ada
-ce3604a.ada
-ce3604b.ada
-ce3605a.ada
-ce3605b.ada
-ce3605c.ada
-ce3605d.ada
-ce3605e.ada
-ce3606a.ada
-ce3606b.ada
-ce3701a.ada
-ce3704a.ada
-ce3704b.ada
-ce3704c.ada
-ce3704d.ada
-ce3704e.ada
-ce3704f.ada
-ce3704m.ada
-ce3704n.ada
-ce3704o.ada
-ce3705a.ada
-ce3705b.ada
-ce3705c.ada
-ce3705d.ada
-ce3705e.ada
-ce3706c.ada
-ce3706d.ada
-ce3706f.ada
-ce3706g.ada
-ce3707a.ada
-ce3708a.ada
-ce3801a.ada
-ce3801b.ada
-ce3804a.ada
-ce3804b.ada
-ce3804c.ada
-ce3804d.ada
-ce3804e.ada
-ce3804f.ada
-ce3804g.ada
-ce3804h.ada
-ce3804i.ada
-ce3804j.ada
-ce3804m.ada
-ce3804o.ada
-ce3804p.ada
-ce3805a.ada
-ce3805b.ada
-ce3806a.ada
-ce3806b.ada
-ce3806c.ada
-ce3806d.ada
-ce3806e.ada
-ce3806f.ada
-ce3806g.ada
-ce3806h.ada
-ce3809a.ada
-ce3809b.ada
-ce3810a.ada
-ce3810b.ada
-ce3815a.ada
-ce3901a.ada
-ce3902b.ada
-ce3904a.ada
-ce3904b.ada
-ce3905a.ada
-ce3905b.ada
-ce3905c.ada
-ce3905l.ada
-ce3906a.ada
-ce3906b.ada
-ce3906c.ada
-ce3906d.ada
-ce3906e.ada
-ce3906f.ada
-ce3907a.ada
-ce3908a.ada
-checkfil.ada
-coverage.txt
-cxa3001.a
-cxa3002.a
-cxa3003.a
-cxa3004.a
-cxa4001.a
-cxa4002.a
-cxa4003.a
-cxa4004.a
-cxa4005.a
-cxa4006.a
-cxa4007.a
-cxa4008.a
-cxa4009.a
-cxa4010.a
-cxa4011.a
-cxa4012.a
-cxa4013.a
-cxa4014.a
-cxa4015.a
-cxa4016.a
-cxa4017.a
-cxa4018.a
-cxa4019.a
-cxa4020.a
-cxa4021.a
-cxa4022.a
-cxa4023.a
-cxa4024.a
-cxa4025.a
-cxa4026.a
-cxa4027.a
-cxa4028.a
-cxa4029.a
-cxa4030.a
-cxa4031.a
-cxa4032.a
-cxa4033.a
-cxa4034.a
-cxa5011.a
-cxa5012.a
-cxa5013.a
-cxa5015.a
-cxa5a01.a
-cxa5a02.a
-cxa5a03.a
-cxa5a04.a
-cxa5a05.a
-cxa5a06.a
-cxa5a07.a
-cxa5a08.a
-cxa5a09.a
-cxa5a10.a
-cxa8001.a
-cxa8002.a
-cxa8003.a
-cxa9001.a
-cxa9002.a
-cxaa001.a
-cxaa002.a
-cxaa003.a
-cxaa004.a
-cxaa005.a
-cxaa006.a
-cxaa007.a
-cxaa008.a
-cxaa009.a
-cxaa010.a
-cxaa011.a
-cxaa012.a
-cxaa013.a
-cxaa014.a
-cxaa015.a
-cxaa016.a
-cxaa017.a
-cxaa018.a
-cxaa019.a
-cxab001.a
-cxac001.a
-cxac002.a
-cxac003.a
-cxac004.a
-cxac005.a
-cxaca01.a
-cxaca02.a
-cxacb01.a
-cxacb02.a
-cxacc01.a
-cxaf001.a
-cxb2001.a
-cxb2002.a
-cxb2003.a
-cxb3001.a
-cxb3002.a
-cxb3003.a
-cxb30040.c
-cxb30041.am
-cxb3005.a
-cxb30060.c
-cxb30061.am
-cxb3007.a
-cxb3008.a
-cxb3009.a
-cxb3010.a
-cxb3011.a
-cxb3012.a
-cxb30130.c
-cxb30131.c
-cxb30132.am
-cxb3014.a
-cxb3015.a
-cxb3016.a
-cxb4001.a
-cxb4002.a
-cxb4003.a
-cxb4004.a
-cxb4005.a
-cxb4006.a
-cxb4007.a
-cxb4008.a
-cxb40090.cbl
-cxb40091.cbl
-cxb40092.cbl
-cxb40093.am
-cxb5001.a
-cxb5002.a
-cxb5003.a
-cxb50040.ftn
-cxb50041.ftn
-cxb50042.am
-cxb50050.ftn
-cxb50051.ftn
-cxb50052.am
-cxc3001.a
-cxc3002.a
-cxc3003.a
-cxc3004.a
-cxc3005.a
-cxc3006.a
-cxc3007.a
-cxc3008.a
-cxc3009.a
-cxc6001.a
-cxc6002.a
-cxc6003.a
-cxc7001.a
-cxc7002.a
-cxc7003.a
-cxc7004.a
-cxd1001.a
-cxd1002.a
-cxd1003.a
-cxd1004.a
-cxd1005.a
-cxd1006.a
-cxd1007.a
-cxd1008.a
-cxd2001.a
-cxd2002.a
-cxd2003.a
-cxd2004.a
-cxd2006.a
-cxd2007.a
-cxd2008.a
-cxd3001.a
-cxd3002.a
-cxd3003.a
-cxd4001.a
-cxd4002.a
-cxd4003.a
-cxd4004.a
-cxd4005.a
-cxd4006.a
-cxd4007.a
-cxd4008.a
-cxd4009.a
-cxd4010.a
-cxd5001.a
-cxd6001.a
-cxd6002.a
-cxd6003.a
-cxd8001.a
-cxd8002.a
-cxd8003.a
-cxd9001.a
-cxda001.a
-cxda002.a
-cxda003.a
-cxda004.a
-cxdb001.a
-cxdb002.a
-cxdb003.a
-cxdb004.a
-cxe1001.a
-cxe2001.a
-cxe2002.a
-cxe4001.a
-cxe4002.a
-cxe4003.a
-cxe4004.a
-cxe4005.a
-cxe4006.a
-cxe5001.a
-cxe5002.a
-cxe5003.a
-cxf1001.a
-cxf2001.a
-cxf2002.a
-cxf2003.a
-cxf2004.a
-cxf2005.a
-cxf2a01.a
-cxf2a02.a
-cxf3001.a
-cxf3002.a
-cxf3003.a
-cxf3004.a
-cxf3a01.a
-cxf3a02.a
-cxf3a03.a
-cxf3a04.a
-cxf3a05.a
-cxf3a06.a
-cxf3a07.a
-cxf3a08.a
-cxg1001.a
-cxg1002.a
-cxg1003.a
-cxg1004.a
-cxg1005.a
-cxg2001.a
-cxg2002.a
-cxg2003.a
-cxg2004.a
-cxg2005.a
-cxg2006.a
-cxg2007.a
-cxg2008.a
-cxg2009.a
-cxg2010.a
-cxg2011.a
-cxg2012.a
-cxg2013.a
-cxg2014.a
-cxg2015.a
-cxg2016.a
-cxg2017.a
-cxg2018.a
-cxg2019.a
-cxg2020.a
-cxg2021.a
-cxg2022.a
-cxg2023.a
-cxg2024.a
-cxh1001.a
-cxh3001.a
-cxh3002.a
-cxh30030.a
-cxh30031.am
-cz00004.a
-cz1101a.ada
-cz1102a.ada
-cz1103a.ada
-d4a002a.ada
-d4a002b.ada
-d4a004a.ada
-d4a004b.ada
-e28002b.ada
-e28005d.ada
-e52103y.ada
-eb4011a.ada
-eb4012a.ada
-eb4014a.ada
-ee3203a.ada
-ee3204a.ada
-ee3402b.ada
-ee3409f.ada
-ee3412c.ada
-enumchek.ada
-f340a000.a
-f340a001.a
-f341a00.a
-f390a00.a
-f392a00.a
-f392c00.a
-f392d00.a
-f393a00.a
-f393b00.a
-f3a2a00.a
-f460a00.a
-f730a000.a
-f730a001.a
-f731a00.a
-f940a00.a
-f954a00.a
-fa11a00.a
-fa11b00.a
-fa11c00.a
-fa11d00.a
-fa13a00.a
-fa13b00.a
-fa21a00.a
-fb20a00.a
-fb40a00.a
-fc50a00.a
-fc51a00.a
-fc51b00.a
-fc51c00.a
-fc51d00.a
-fc54a00.a
-fc70a00.a
-fc70b00.a
-fc70c00.a
-fcndecl.ada
-fd72a00.a
-fdb0a00.a
-fxa5a00.a
-fxaca00.a
-fxacb00.a
-fxacc00.a
-fxc6a00.a
-fxe2a00.a
-fxf2a00.a
-fxf3a00.a
-impdef.a
-impdefc.a
-impdefd.a
-impdefe.a
-impdefg.a
-impdefh.a
-la140010.a
-la140011.am
-la140012.a
-la140020.a
-la140021.am
-la140022.a
-la140030.a
-la140031.a
-la140032.am
-la140033.a
-la140040.a
-la140041.am
-la140042.a
-la140050.a
-la140051.a
-la140052.am
-la140053.a
-la140060.a
-la140061.a
-la140062.am
-la140063.a
-la140070.a
-la140071.a
-la140072.am
-la140073.a
-la140080.a
-la140081.a
-la140082.am
-la140083.a
-la140090.a
-la140091.a
-la140092.am
-la140093.a
-la140100.a
-la140101.a
-la140102.am
-la140103.a
-la140110.a
-la140111.a
-la140112.am
-la140113.a
-la140120.a
-la140121.a
-la140122.am
-la140123.a
-la140130.a
-la140131.a
-la140132.am
-la140133.a
-la140140.a
-la140141.a
-la140142.am
-la140143.a
-la140150.a
-la140151.a
-la140152.am
-la140153.a
-la140160.a
-la140161.a
-la140162.am
-la140163.a
-la140170.a
-la140171.a
-la140172.am
-la140173.a
-la140180.a
-la140181.a
-la140182.am
-la140183.a
-la140190.a
-la140191.a
-la140192.am
-la140193.a
-la140200.a
-la140201.a
-la140202.am
-la140203.a
-la140210.a
-la140211.am
-la140212.a
-la140220.a
-la140221.am
-la140222.a
-la140240.a
-la140241.a
-la140242.am
-la140243.a
-la140250.a
-la140251.am
-la140252.a
-la140260.a
-la140261.a
-la140262.am
-la140263.a
-la140270.a
-la140271.a
-la140272.am
-la140273.a
-la200010.a
-la200011.a
-la200012.am
-la5001a0.ada
-la5001a1.ada
-la5001a2.ada
-la5001a3.ada
-la5001a4.ada
-la5001a5.ada
-la5001a6.ada
-la5001a7.ada
-la5007a0.ada
-la5007a1.ada
-la5007b0.ada
-la5007b1.ada
-la5007c0.ada
-la5007c1.ada
-la5007d0.ada
-la5007d1.ada
-la5007e0.ada
-la5007e1.ada
-la5007f0.ada
-la5007f1.ada
-la5007g0.ada
-la5007g1.ada
-la5008a0.ada
-la5008a1.ada
-la5008b0.ada
-la5008b1.ada
-la5008c0.ada
-la5008c1.ada
-la5008d0.ada
-la5008d1.ada
-la5008e0.ada
-la5008e1.ada
-la5008f0.ada
-la5008f1.ada
-la5008g0.ada
-la5008g1.ada
-lencheck.ada
-lxd70010.a
-lxd70011.a
-lxd70012.am
-lxd70030.a
-lxd70031.a
-lxd70032.am
-lxd70040.a
-lxd70041.a
-lxd70042.am
-lxd70050.a
-lxd70051.a
-lxd70052.am
-lxd70060.a
-lxd70061.a
-lxd70062.am
-lxd70070.a
-lxd70071.a
-lxd70072.am
-lxd70080.a
-lxd70081.a
-lxd70082.am
-lxd70090.a
-lxd70091.a
-lxd70092.am
-lxe30010.am
-lxe30011.am
-lxe30020.am
-lxe30021.am
-lxh40010.a
-lxh40011.a
-lxh40012.am
-lxh40020.a
-lxh40021.a
-lxh40022.am
-lxh40030.a
-lxh40031.a
-lxh40032.a
-lxh40033.am
-lxh40040.a
-lxh40041.a
-lxh40042.a
-lxh40043.am
-lxh40050.a
-lxh40051.a
-lxh40052.a
-lxh40053.am
-lxh40060.a
-lxh40061.a
-lxh40062.a
-lxh40063.am
-lxh40070.a
-lxh40071.a
-lxh40072.a
-lxh40073.am
-lxh40080.a
-lxh40081.a
-lxh40082.a
-lxh40083.a
-lxh40084.am
-lxh40090.a
-lxh40091.a
-lxh40092.a
-lxh40093.am
-lxh40100.a
-lxh40101.a
-lxh40102.a
-lxh40103.am
-lxh40110.a
-lxh40111.a
-lxh40112.am
-lxh40120.a
-lxh40121.a
-lxh40122.a
-lxh40123.am
-lxh40130.a
-lxh40131.a
-lxh40132.a
-lxh40133.am
-lxh40140.a
-lxh40141.a
-lxh40142.am
-macro.dfs
-macrosub.ada
-repbody.ada
-repspec.ada
-spprt13s.tst
-tctouch.ada
-testobj.txt
-tsttests.dat
-ug-apxa.doc
-ug-apxa.pdf
-ug-apxa.txt
-ug-apxb.doc
-ug-apxb.pdf
-ug-apxb.txt
-ug-apxc.doc
-ug-apxc.pdf
-ug-apxc.txt
-ug-apxd.doc
-ug-apxd.pdf
-ug-apxd.txt
-ug-body.doc
-ug-body.pdf
-ug-body.txt
-widechr.a
diff --git a/gcc/testsuite/ada/acats/support/acats26.lst b/gcc/testsuite/ada/acats/support/acats26.lst
new file mode 100644
index 0000000..d99145e
--- /dev/null
+++ b/gcc/testsuite/ada/acats/support/acats26.lst
@@ -0,0 +1,4332 @@
+a22006b.ada
+a22006c.ada
+a22006d.ada
+a26007a.tst
+a27003a.ada
+a29003a.ada
+a2a031a.ada
+a33003a.ada
+a34017c.ada
+a35101b.ada
+a35402a.ada
+a35801f.ada
+a35902c.ada
+a38106d.ada
+a38106e.ada
+a49027a.ada
+a49027b.ada
+a49027c.ada
+a54b01a.ada
+a54b02a.ada
+a55b12a.ada
+a55b13a.ada
+a55b14a.ada
+a71004a.ada
+a73001i.ada
+a73001j.ada
+a74105b.ada
+a74106a.ada
+a74106b.ada
+a74106c.ada
+a74205e.ada
+a74205f.ada
+a83009a.ada
+a83009b.ada
+a83a02a.ada
+a83a02b.ada
+a83a06a.ada
+a83a08a.ada
+a83c01c.ada
+a83c01h.ada
+a83c01i.ada
+a85007d.ada
+a85013b.ada
+a87b59a.ada
+a95001c.ada
+a95074d.ada
+a97106a.ada
+a99006a.ada
+aa2010a.ada
+aa2012a.ada
+acats25.lst
+ac1015b.ada
+ac3106a.ada
+ac3206a.ada
+ac3207a.ada
+ad7001b.ada
+ad7001c0.ada
+ad7001c1.ada
+ad7001d0.ada
+ad7001d1.ada
+ad7006a.ada
+ad7101a.ada
+ad7101c.ada
+ad7102a.ada
+ad7103a.ada
+ad7103c.ada
+ad7104a.ada
+ad7201a.ada
+ad7203b.ada
+ad7205b.ada
+ad8011a.tst
+ada101a.ada
+ae2113a.ada
+ae2113b.ada
+ae3002g.ada
+ae3101a.ada
+ae3702a.ada
+ae3709a.ada
+b22001a.tst
+b22001b.tst
+b22001c.tst
+b22001d.tst
+b22001e.tst
+b22001f.tst
+b22001g.tst
+b22001h.ada
+b22001i.tst
+b22001j.tst
+b22001k.tst
+b22001l.tst
+b22001m.tst
+b22001n.tst
+b23002a.ada
+b23004a.ada
+b23004b.ada
+b24001a.ada
+b24001b.ada
+b24001c.ada
+b24005a.ada
+b24005b.ada
+b24007a.ada
+b24009a.ada
+b24009b.ada
+b24104a.ada
+b24204a.ada
+b24204b.ada
+b24204c.ada
+b24204d.ada
+b24204e.ada
+b24204f.ada
+b24205a.ada
+b24206a.ada
+b24206b.ada
+b24211b.ada
+b25002a.ada
+b25002b.ada
+b26001a.ada
+b26002a.ada
+b26005a.ada
+b28001a.ada
+b28001b.ada
+b28001c.ada
+b28001d.ada
+b28001e.ada
+b28001f.ada
+b28001g.ada
+b28001h.ada
+b28001i.ada
+b28001j.ada
+b28001k.ada
+b28001l.ada
+b28001m.ada
+b28001n.ada
+b28001o.ada
+b28001p.ada
+b28001q.ada
+b28001r.ada
+b28001s.ada
+b28001t.ada
+b28001u.ada
+b28001v.ada
+b28001w.ada
+b29001a.ada
+b2a003a.ada
+b2a003b.ada
+b2a003c.ada
+b2a003d.ada
+b2a003e.ada
+b2a003f.ada
+b2a005a.ada
+b2a005b.ada
+b2a007a.ada
+b2a010a.ada
+b2a021a.ada
+b32101a.ada
+b32103a.ada
+b32104a.ada
+b32106a.ada
+b32201a.ada
+b32202a.ada
+b32202b.ada
+b32202c.ada
+b330001.a
+b33001a.ada
+b33101a.ada
+b33102a.ada
+b33102b.ada
+b33102c.ada
+b33102d.ada
+b33102e.ada
+b33201a.ada
+b33201b.ada
+b33201c.ada
+b33201d.ada
+b33201e.ada
+b33204a.ada
+b33205a.ada
+b33302a.ada
+b34001b.ada
+b34001e.ada
+b34002b.ada
+b34003b.ada
+b34004b.ada
+b34005b.ada
+b34005e.ada
+b34005h.ada
+b34005k.ada
+b34005n.ada
+b34005q.ada
+b34005t.ada
+b34006b.ada
+b34006e.ada
+b34006h.ada
+b34006k.ada
+b34007b.ada
+b34007e.ada
+b34007h.ada
+b34007k.ada
+b34007n.ada
+b34007q.ada
+b34007t.ada
+b34008b.ada
+b34009b.ada
+b34009e.ada
+b34009h.ada
+b34009k.ada
+b34011a.ada
+b34014b.ada
+b34014d.ada
+b34014f.ada
+b34014i.ada
+b34014m.ada
+b34014o.ada
+b34014q.ada
+b34014s.ada
+b34014v.ada
+b34014z.ada
+b35004a.ada
+b35101a.ada
+b35103a.ada
+b35103b.ada
+b35302a.ada
+b354001.a
+b35401a.ada
+b35401b.ada
+b35403a.ada
+b35501a.ada
+b35501b.ada
+b35506a.ada
+b35506b.ada
+b35506c.ada
+b35506d.ada
+b35701a.ada
+b35709a.ada
+b35901a.ada
+b35901c.ada
+b35901d.ada
+b35a01a.ada
+b35a08a.ada
+b360001.a
+b36001a.ada
+b36002a.ada
+b36101a.ada
+b36102a.ada
+b36103a.ada
+b36105c.dep
+b36171a.ada
+b36171b.ada
+b36171c.ada
+b36171d.ada
+b36171e.ada
+b36171f.ada
+b36171g.ada
+b36171h.ada
+b36171i.ada
+b36201a.ada
+b36307a.ada
+b370001.a
+b370002.a
+b37004a.ada
+b37004b.ada
+b37004c.ada
+b37004d.ada
+b37004e.ada
+b37004f.ada
+b37004g.ada
+b3710010.a
+b3710011.a
+b3710012.a
+b3710013.a
+b3710014.am
+b37101a.ada
+b37102a.ada
+b37104a.ada
+b37106a.ada
+b37201a.ada
+b37201b.ada
+b37203a.ada
+b37301i.ada
+b37301j.ada
+b37302a.ada
+b37303a.ada
+b37309b.ada
+b37310b.ada
+b37311a.ada
+b37401a.ada
+b37409b.ada
+b380001.a
+b38003a.ada
+b38003b.ada
+b38003c.ada
+b38003d.ada
+b38008a.ada
+b38008b.ada
+b38009a.ada
+b38009d.ada
+b38101a.ada
+b38101b.ada
+b38101c.ada
+b38103a.ada
+b38103b.ada
+b38103c0.ada
+b38103c1.ada
+b38103c2.ada
+b38103c3.ada
+b38103d.ada
+b38103e0.ada
+b38103e1.ada
+b38105a.ada
+b38105b.ada
+b38203a.ada
+b390001.a
+b391001.a
+b391002.a
+b391003.a
+b391004.a
+b392001.a
+b392002.a
+b392003.a
+b392004.a
+b392005.a
+b392006.a
+b392007.a
+b392008.a
+b392009.a
+b392010.a
+b392011.a
+b393001.a
+b393002.a
+b393003.a
+b393004.a
+b393005.a
+b393006.a
+b393007.a
+b3a0001.a
+b3a0002.a
+b3a0003.a
+b3a0004.a
+b3a2002.a
+b3a2003.a
+b3a2004.a
+b3a2005.a
+b3a2006.a
+b3a2007.a
+b3a2008.a
+b3a2009.a
+b3a2010.a
+b3a2011.a
+b3a2012.a
+b3a2013.a
+b3a2014.a
+b3a2015.a
+b3a2016.a
+b41101a.ada
+b41101c.ada
+b41201a.ada
+b41201c.ada
+b41202c.ada
+b41202d.ada
+b41324b.ada
+b41325b.ada
+b41327b.ada
+b420001.a
+b430001.a
+b43001m.ada
+b43002d.ada
+b43002e.ada
+b43002f.ada
+b43002g.ada
+b43002h.ada
+b43002i.ada
+b43002j.ada
+b43002k.ada
+b43005a.ada
+b43005b.ada
+b43005f.ada
+b43101a.ada
+b43102a.ada
+b43102b.ada
+b43105c.ada
+b43201a.ada
+b43201c.ada
+b43201d.ada
+b43202a.ada
+b43202c.ada
+b43209b.ada
+b43221a.ada
+b43221b.ada
+b43223a.ada
+b44001a.ada
+b44001b.ada
+b44002b.ada
+b44002c.ada
+b44004a.ada
+b44004b.ada
+b44004c.ada
+b44004d.ada
+b44004e.ada
+b45102a.ada
+b45116a.ada
+b45121a.ada
+b45204a.ada
+b45205a.ada
+b45206c.ada
+b45207a.ada
+b45207b.ada
+b45207c.ada
+b45207d.ada
+b45207g.ada
+b45207h.ada
+b45207i.ada
+b45207j.ada
+b45207m.ada
+b45207n.ada
+b45207o.ada
+b45207p.ada
+b45207s.ada
+b45207t.ada
+b45207u.ada
+b45207v.ada
+b45208a.ada
+b45208b.ada
+b45208c.ada
+b45208g.ada
+b45208h.ada
+b45208i.ada
+b45208m.ada
+b45208n.ada
+b45208s.ada
+b45208t.ada
+b45209a.ada
+b45209b.ada
+b45209c.ada
+b45209d.ada
+b45209e.ada
+b45209f.ada
+b45209g.ada
+b45209h.ada
+b45209i.ada
+b45209j.ada
+b45209k.ada
+b45221a.ada
+b45261a.ada
+b45261b.ada
+b45261c.ada
+b45261d.ada
+b45301a.ada
+b45301b.ada
+b45301c.ada
+b45302a.ada
+b45341a.ada
+b455002.a
+b45501a.ada
+b45501b.ada
+b45501c.ada
+b45522a.ada
+b45537a.ada
+b45601a.ada
+b45625a.ada
+b45661a.ada
+b460001.a
+b460002.a
+b460004.a
+b460005.a
+b460006.a
+b46002a.ada
+b46003a.ada
+b46004a.ada
+b46004b.ada
+b46004c.ada
+b46004d.ada
+b46004e.ada
+b46005a.ada
+b47001a.ada
+b480001.a
+b48001a.ada
+b48001b.ada
+b48002a.ada
+b48002b.ada
+b48002c.ada
+b48002d.ada
+b48002e.ada
+b48002g.ada
+b48003a.ada
+b48003b.ada
+b48003c.ada
+b48003d.ada
+b48003e.ada
+b490001.a
+b490002.a
+b49002a.ada
+b49004a.ada
+b49005a.ada
+b49007a.ada
+b49007b.ada
+b49008a.ada
+b49008c.ada
+b49009b.ada
+b49009c.ada
+b49010a.ada
+b49011a.ada
+b4a010c.ada
+b4a016a.ada
+b51001a.ada
+b51004b.ada
+b51004c.ada
+b52002a.ada
+b52002b.ada
+b52002c.ada
+b52002d.ada
+b52002e.ada
+b52002f.ada
+b52002g.ada
+b52004a.ada
+b52004b.ada
+b52004c.ada
+b52004d.dep
+b52004e.dep
+b53001a.ada
+b53001b.ada
+b53002a.ada
+b53002b.ada
+b53009a.ada
+b53009b.ada
+b53009c.ada
+b54a01b.ada
+b54a01f.ada
+b54a01g.ada
+b54a01l.ada
+b54a05a.ada
+b54a05b.ada
+b54a10a.ada
+b54a12a.ada
+b54a20a.ada
+b54a21a.ada
+b54a25a.ada
+b54a60a.ada
+b54a60b.ada
+b54b01b.tst
+b54b01c.ada
+b54b02b.ada
+b54b02c.ada
+b54b02d.ada
+b54b04a.ada
+b54b04b.ada
+b54b05a.ada
+b54b06a.ada
+b55a01a.ada
+b55a01d.ada
+b55a01e.ada
+b55a01j.ada
+b55a01k.ada
+b55a01l.ada
+b55a01n.ada
+b55a01o.ada
+b55a01t.ada
+b55a01u.ada
+b55a01v.ada
+b55b01a.ada
+b55b01b.ada
+b55b09b.ada
+b55b09c.dep
+b55b09d.dep
+b55b12b.ada
+b55b12c.ada
+b55b17a.ada
+b55b17b.ada
+b55b17c.ada
+b55b18a.ada
+b56001a.ada
+b56001d.ada
+b56001e.ada
+b56001f.ada
+b56001g.ada
+b56001h.ada
+b57001a.ada
+b57001b.ada
+b57001c.ada
+b57001d.ada
+b58001a.ada
+b58002a.ada
+b58002b.ada
+b58002c.ada
+b58003a.ada
+b58003b.ada
+b59001a.ada
+b59001c.ada
+b59001d.ada
+b59001e.ada
+b59001f.ada
+b59001g.ada
+b59001h.ada
+b59001i.ada
+b610001.a
+b61001f.ada
+b61005a.ada
+b61006a.ada
+b61011a.ada
+b62001a.ada
+b62001b.ada
+b62001c.ada
+b62001d.ada
+b63001a.ada
+b63001b.ada
+b63005a.ada
+b63005b.ada
+b63006a.ada
+b63009a.ada
+b63009b.ada
+b63009c0.ada
+b63009c1.ada
+b63009c2.ada
+b63009c3.ada
+b63103a.ada
+b64002a.ada
+b64002c.ada
+b64003a.ada
+b64004a.ada
+b64004b.ada
+b64004c.ada
+b64004d.ada
+b64004e.ada
+b64004f.ada
+b641001.a
+b64101a.ada
+b64201a.ada
+b65001a.ada
+b65002a.ada
+b65002b.ada
+b660001.a
+b660002.a
+b66001a.ada
+b66001b.ada
+b66001c.ada
+b66001d.ada
+b67001a.ada
+b67001b.ada
+b67001c.ada
+b67001d.ada
+b67001h.ada
+b67001i.ada
+b67001j.ada
+b67001k.ada
+b67004a.ada
+b71001a.ada
+b71001b.ada
+b71001c.ada
+b71001d.ada
+b71001f.ada
+b71001g.ada
+b71001h.ada
+b71001i.ada
+b71001j.ada
+b71001l.ada
+b71001m.ada
+b71001n.ada
+b71001o.ada
+b71001p.ada
+b71001r.ada
+b71001t.ada
+b71001u.ada
+b71001v.ada
+b7200010.a
+b7200011.a
+b7200012.a
+b7200013.a
+b7200014.a
+b7200015.a
+b7200016.a
+b730001.a
+b730002.a
+b730003.a
+b730004.a
+b730005.a
+b7300060.a
+b7300061.a
+b7300062.a
+b7300063.am
+b73001a.ada
+b73001b.ada
+b73001c.ada
+b73001d.ada
+b73001e.ada
+b73001f.ada
+b73001g.ada
+b73001h.ada
+b73004a.ada
+b73004b0.ada
+b73004b1.ada
+b73004b2.ada
+b7310010.a
+b7310011.a
+b7310012.a
+b7310013.a
+b7310014.a
+b7310015.a
+b7310016.am
+b731a01.a
+b731a02.a
+b740001.a
+b74001a.ada
+b74001b.ada
+b74101a.ada
+b74101b.ada
+b74103a.ada
+b74103d.ada
+b74103e.ada
+b74103g.ada
+b74103i.ada
+b74104a.ada
+b74105a.ada
+b74105c.ada
+b74201a.ada
+b74202a.ada
+b74202b.ada
+b74202c.ada
+b74202d.ada
+b74203b.ada
+b74203c.ada
+b74203d.ada
+b74203e.ada
+b74205a.ada
+b74207a.ada
+b74304a.ada
+b74304b.ada
+b74304c.ada
+b74404a.ada
+b74404b.ada
+b74409a.ada
+b810001.a
+b830001.a
+b8300020.a
+b8300021.a
+b8300022.a
+b8300023.a
+b8300024.a
+b8300025.am
+b83001a.ada
+b83003a.ada
+b83003b0.ada
+b83003b1.ada
+b83003b2.ada
+b83003b3.ada
+b83003b4.ada
+b83003c.ada
+b83004a.ada
+b83004b0.ada
+b83004b1.ada
+b83004b2.ada
+b83004b3.ada
+b83004c0.ada
+b83004c1.ada
+b83004c2.ada
+b83004d0.ada
+b83004d1.ada
+b83004d2.ada
+b83004d3.ada
+b83006a.ada
+b83006b.ada
+b83008a.ada
+b83008b.ada
+b83011a.ada
+b83023b.ada
+b83024b.ada
+b83024f0.ada
+b83024f1.ada
+b83024f2.ada
+b83024f3.ada
+b83026b.ada
+b83027b.ada
+b83027d.ada
+b83028b.ada
+b83029b.ada
+b83030b.ada
+b83030d.ada
+b83031b.ada
+b83031d.ada
+b83031f.ada
+b83032b.ada
+b83033b.ada
+b83041e.ada
+b83a01a.ada
+b83a01b.ada
+b83a01c.ada
+b83a05a.ada
+b83a06b.ada
+b83a06h.ada
+b83a07a.ada
+b83a07b.ada
+b83a07c.ada
+b83a08b.ada
+b83a09a.ada
+b83b01a.ada
+b83b02c.ada
+b83e01a.ada
+b83e01b.ada
+b83e01c.ada
+b83e01d.ada
+b83e01e0.ada
+b83e01e1.ada
+b83e01e2.ada
+b83e01e3.ada
+b83e01f0.ada
+b83e01f1.ada
+b83e01f2.ada
+b83e01f3.ada
+b83e01f4.ada
+b83e01f5.ada
+b83e01f6.ada
+b83e11a.ada
+b83f02a.ada
+b83f02b.ada
+b83f02c.ada
+b840001.a
+b84001a.ada
+b84002b.ada
+b84004a.ada
+b84005b.ada
+b84006a.ada
+b84007a.ada
+b84008b.ada
+b85001a.ada
+b85001b.ada
+b85001c.ada
+b85001d.ada
+b85001e.ada
+b85001f.ada
+b85001g.ada
+b85001h.ada
+b85001i.ada
+b85001j.ada
+b85001k.ada
+b85001l.ada
+b85002a.ada
+b85003a.ada
+b85003b.ada
+b85004a.ada
+b85008f.ada
+b85008g.ada
+b85008h.ada
+b85010a.ada
+b85010b.ada
+b85012a.ada
+b85013c.ada
+b85013d.ada
+b85015a.ada
+b8510010.a
+b8510011.a
+b8510012.am
+b854001.a
+b86001a0.ada
+b86001a1.ada
+b87b23b.ada
+b87b26a.ada
+b87b48c.ada
+b91001b.ada
+b91001c.ada
+b91001d.ada
+b91001e.ada
+b91001f.ada
+b91001g.ada
+b91002a.ada
+b91002b.ada
+b91002c.ada
+b91002d.ada
+b91002e.ada
+b91002f.ada
+b91002g.ada
+b91002h.ada
+b91002i.ada
+b91002j.ada
+b91002k.ada
+b91002l.ada
+b91003a.ada
+b91003b.ada
+b91003c.ada
+b91003d.ada
+b91003e.ada
+b91004a.ada
+b91005a.ada
+b92001a.ada
+b92001b.ada
+b940001.a
+b940002.a
+b940003.a
+b940004.a
+b940005.a
+b940006.a
+b940007.a
+b95001a.ada
+b95001b.ada
+b95001d.ada
+b95002a.ada
+b95003a.ada
+b95004a.ada
+b95004b.ada
+b95006a.ada
+b95006b.ada
+b95006c.ada
+b95006d.ada
+b95007a.ada
+b95007b.ada
+b95020a.ada
+b95020b0.ada
+b95020b1.ada
+b95020b2.ada
+b95030a.ada
+b95031a.ada
+b95032a.ada
+b95061a.ada
+b95061b.ada
+b95061c.ada
+b95061d.ada
+b95061e.ada
+b95061f.ada
+b95061g.ada
+b95062a.ada
+b95063a.ada
+b95064a.ada
+b95068a.ada
+b95070a.ada
+b95080a.ada
+b95080c.ada
+b95081a.ada
+b95082a.ada
+b95082b.ada
+b95082c.ada
+b95082d.ada
+b95082e.ada
+b95082f.ada
+b95083a.ada
+b95094a.ada
+b95094b.ada
+b95094c.ada
+b951001.a
+b952001.a
+b952002.a
+b952003.a
+b952004.a
+b954001.a
+b954003.a
+b954004.a
+b960001.a
+b96002a.ada
+b97102b.ada
+b97102c.ada
+b97102d.ada
+b97102f.ada
+b97102g.ada
+b97102h.ada
+b97102i.ada
+b97103a.ada
+b97103b.ada
+b97103d.ada
+b97103e.ada
+b97103f.ada
+b97103g.ada
+b97104a.ada
+b97104b.ada
+b97104c.ada
+b97104d.ada
+b97104e.ada
+b97104f.ada
+b97104g.ada
+b97107a.ada
+b97108a.ada
+b97108b.ada
+b97109a.ada
+b97110a.ada
+b97110b.ada
+b97111a.ada
+b97206a.ada
+b97306a.ada
+b99001a.ada
+b99001b.ada
+b99002a.ada
+b99002b.ada
+b99002c.ada
+b99003a.ada
+b9a001a.ada
+b9a001b.ada
+ba1001a0.ada
+ba1001a1.ada
+ba1001a4.ada
+ba1001ac.ada
+ba1001d.ada
+ba1010a0.ada
+ba1010a1.ada
+ba1010a2.ada
+ba1010a3.ada
+ba1010b0.ada
+ba1010b1.ada
+ba1010b2.ada
+ba1010b4.ada
+ba1010b5.ada
+ba1010b6.ada
+ba1010b7.ada
+ba1010b8.ada
+ba1010c0.ada
+ba1010c1.ada
+ba1010c2.ada
+ba1010c3.ada
+ba1010c4.ada
+ba1010c5.ada
+ba1010c6.ada
+ba1010d0.ada
+ba1010d1.ada
+ba1010d2.ada
+ba1010d3.ada
+ba1010e0.ada
+ba1010e1.ada
+ba1010e2.ada
+ba1010e3.ada
+ba1010e4.ada
+ba1010e5.ada
+ba1010e6.ada
+ba1010f0.ada
+ba1010f1.ada
+ba1010f3.ada
+ba1010f4.ada
+ba1010f5.ada
+ba1010f6.ada
+ba1010f7.ada
+ba1010f8.ada
+ba1010g0.ada
+ba1010g2.ada
+ba1010g3.ada
+ba1010g4.ada
+ba1010g5.ada
+ba1010h0.ada
+ba1010h2.ada
+ba1010i0.ada
+ba1010i1.ada
+ba1010i3.ada
+ba1010i4.ada
+ba1010j0.ada
+ba1010j1.ada
+ba1010j2.ada
+ba1010j4.ada
+ba1010j5.ada
+ba1010j6.ada
+ba1010j7.ada
+ba1010j8.ada
+ba1010k0.ada
+ba1010k1.ada
+ba1010k2.ada
+ba1010k3.ada
+ba1010k4.ada
+ba1010k5.ada
+ba1010k6.ada
+ba1010l0.ada
+ba1010l1.ada
+ba1010l2.ada
+ba1010l3.ada
+ba1010l4.ada
+ba1010l5.ada
+ba1010l6.ada
+ba1010m0.ada
+ba1010m1.ada
+ba1010m3.ada
+ba1010m4.ada
+ba1010m5.ada
+ba1010m6.ada
+ba1010m7.ada
+ba1010m8.ada
+ba1010n0.ada
+ba1010n2.ada
+ba1010n3.ada
+ba1010n4.ada
+ba1010n5.ada
+ba1010p0.ada
+ba1010p2.ada
+ba1010q0.ada
+ba1010q1.ada
+ba1010q3.ada
+ba1010q4.ada
+ba1011b0.ada
+ba1011b1.ada
+ba1011b2.ada
+ba1011b3.ada
+ba1011b4.ada
+ba1011b5.ada
+ba1011b6.ada
+ba1011b7.ada
+ba1011b8.ada
+ba1011c0.ada
+ba1011c1.ada
+ba1011c2.ada
+ba1011c3.ada
+ba1011c4.ada
+ba1011c5.ada
+ba1011c6.ada
+ba1011c7.ada
+ba1011c8.ada
+ba1020a0.ada
+ba1020a1.ada
+ba1020a2.ada
+ba1020a3.ada
+ba1020a4.ada
+ba1020a5.ada
+ba1020a6.ada
+ba1020a7.ada
+ba1020a8.ada
+ba1020b0.ada
+ba1020b1.ada
+ba1020b2.ada
+ba1020b3.ada
+ba1020b4.ada
+ba1020b5.ada
+ba1020b6.ada
+ba1020c0.ada
+ba1020c1.ada
+ba1020c2.ada
+ba1020c3.ada
+ba1020c4.ada
+ba1020c5.ada
+ba1020f0.ada
+ba1020f1.ada
+ba1020f2.ada
+ba11001.a
+ba11002.a
+ba11003.a
+ba11004.a
+ba11005.a
+ba11007.a
+ba11008.a
+ba11009.a
+ba11010.a
+ba11011.a
+ba11012.a
+ba1101a.ada
+ba1101b0.ada
+ba1101b1.ada
+ba1101b2.ada
+ba1101b3.ada
+ba1101b4.ada
+ba1101c0.ada
+ba1101c1.ada
+ba1101c2.ada
+ba1101c3.ada
+ba1101c4.ada
+ba1101c5.ada
+ba1101c6.ada
+ba1101e0.ada
+ba1101e1.ada
+ba1101f.ada
+ba1101g.ada
+ba1109a0.ada
+ba1109a1.ada
+ba1109a2.ada
+ba1110a0.ada
+ba1110a1.ada
+ba1110a2.ada
+ba1110a3.ada
+ba1110a4.ada
+ba1110a5.ada
+ba12001.a
+ba12002.a
+ba12003.a
+ba12004.a
+ba12005.a
+ba12007.a
+ba12008.a
+ba13b01.a
+ba13b02.a
+ba15001.a
+ba150020.a
+ba150021.a
+ba150022.a
+ba150023.a
+ba150024.a
+ba150025.a
+ba150026.a
+ba150027.a
+ba150028.a
+ba150029.am
+ba2001a.ada
+ba2001b.ada
+ba2001c.ada
+ba2001d.ada
+ba2001f0.ada
+ba2001f1.ada
+ba2001f2.ada
+ba2003b0.ada
+ba2003b1.ada
+ba2011a0.ada
+ba2011a1.ada
+ba2011a2.ada
+ba2011a3.ada
+ba2011a4.ada
+ba2011a5.ada
+ba2011a6.ada
+ba2011a7.ada
+ba2011a8.ada
+ba2011a9.ada
+ba2013a.ada
+ba2013b.ada
+ba21001.a
+ba21002.a
+ba210030.a
+ba210031.a
+ba210032.a
+ba210033.a
+ba210034.a
+ba210035.a
+ba210040.a
+ba210041.a
+ba210042.a
+ba210043.a
+ba210044.a
+ba210045.am
+ba21a01.a
+ba21a02.a
+ba3001a0.ada
+ba3001a1.ada
+ba3001a2.ada
+ba3001a3.ada
+ba3001b0.ada
+ba3001b1.ada
+ba3001c0.ada
+ba3001c1.ada
+ba3001e0.ada
+ba3001e1.ada
+ba3001e2.ada
+ba3001e3.ada
+ba3001f0.ada
+ba3001f1.ada
+ba3001f2.ada
+ba3001f3.ada
+ba3006a0.ada
+ba3006a1.ada
+ba3006a2.ada
+ba3006a3.ada
+ba3006a4.ada
+ba3006a5.ada
+ba3006a6.ada
+ba3006b0.ada
+ba3006b1.ada
+ba3006b2.ada
+ba3006b3.ada
+ba3006b4.ada
+bb10001.a
+bb20001.a
+bb2001a.ada
+bb2002a.ada
+bb2003a.ada
+bb2003b.ada
+bb2003c.ada
+bb3001a.ada
+bb3002a.ada
+bc1001a.ada
+bc1002a.ada
+bc1005a.ada
+bc1008a.ada
+bc1008b.ada
+bc1008c.ada
+bc1009a.ada
+bc1011a.ada
+bc1011b.ada
+bc1011c.ada
+bc1012a.ada
+bc1013a.ada
+bc1014a.ada
+bc1014b.ada
+bc1016a.ada
+bc1016b.ada
+bc1101a.ada
+bc1102a.ada
+bc1103a.ada
+bc1106a.ada
+bc1107a.ada
+bc1109a.ada
+bc1109b.ada
+bc1109c.ada
+bc1109d.ada
+bc1110a.ada
+bc1201a.ada
+bc1201b.ada
+bc1201c.ada
+bc1201d.ada
+bc1201e.ada
+bc1201f.ada
+bc1201g.ada
+bc1201h.ada
+bc1201i.ada
+bc1201j.ada
+bc1201k.ada
+bc1201l.ada
+bc1202a.ada
+bc1202c.ada
+bc1202e.ada
+bc1202f.ada
+bc1202g.ada
+bc1203a.ada
+bc1205a.ada
+bc1206a.ada
+bc1207a.ada
+bc1208a.ada
+bc1226a.ada
+bc1230a.ada
+bc1303a.ada
+bc1303b.ada
+bc1303c.ada
+bc1303d.ada
+bc1303e.ada
+bc1303f.ada
+bc1303g.ada
+bc1306a.ada
+bc2001b.ada
+bc2001c.ada
+bc2001d.ada
+bc2001e.ada
+bc2004a.ada
+bc2004b.ada
+bc30001.a
+bc3001a.ada
+bc3002a.ada
+bc3002b.ada
+bc3002c.ada
+bc3002d.ada
+bc3002e.ada
+bc3005a.ada
+bc3005b.ada
+bc3005c.ada
+bc3006a.ada
+bc3009c.ada
+bc3011b.ada
+bc3013a.ada
+bc3016g.ada
+bc3018a.ada
+bc3101a.ada
+bc3101b.ada
+bc3102a.ada
+bc3102b.ada
+bc3103b.ada
+bc3123c.ada
+bc3201a.ada
+bc3201b.ada
+bc3201c.ada
+bc3202a.ada
+bc3202b.ada
+bc3202c.ada
+bc3202d.ada
+bc3205c.ada
+bc3301a.ada
+bc3301b.ada
+bc3302a.ada
+bc3302b.ada
+bc3303a.ada
+bc3304a.ada
+bc3401a.ada
+bc3401b.ada
+bc3402a.ada
+bc3402b.ada
+bc3403a.ada
+bc3403b.ada
+bc3403c.ada
+bc3404a.ada
+bc3404b.ada
+bc3404c.ada
+bc3404d.ada
+bc3404e.ada
+bc3404f.ada
+bc3405a.ada
+bc3405b.ada
+bc3405d.ada
+bc3405e.ada
+bc3405f.ada
+bc3501a.ada
+bc3501b.ada
+bc3501c.ada
+bc3501d.ada
+bc3501e.ada
+bc3501f.ada
+bc3501g.ada
+bc3501h.ada
+bc3501i.ada
+bc3501j.ada
+bc3501k.ada
+bc3502a.ada
+bc3502b.ada
+bc3502c.ada
+bc3502d.ada
+bc3502e.ada
+bc3502f.ada
+bc3502g.ada
+bc3502h.ada
+bc3502i.ada
+bc3502j.ada
+bc3502k.ada
+bc3502l.ada
+bc3502m.ada
+bc3502n.ada
+bc3502o.ada
+bc3503a.ada
+bc3503c.ada
+bc3503d.ada
+bc3503e.ada
+bc3503f.ada
+bc3604a.ada
+bc3604b.ada
+bc3607a.ada
+bc40001.a
+bc40002.a
+bc50001.a
+bc50002.a
+bc50003.a
+bc50004.a
+bc51002.a
+bc51003.a
+bc51004.a
+bc51005.a
+bc51006.a
+bc51007.a
+bc51011.a
+bc51012.a
+bc51013.a
+bc51015.a
+bc51016.a
+bc51017.a
+bc51018.a
+bc51019.a
+bc51020.a
+bc51b01.a
+bc51b02.a
+bc51c01.a
+bc51c02.a
+bc53001.a
+bc53002.a
+bc54001.a
+bc54002.a
+bc54003.a
+bc54a01.a
+bc54a02.a
+bc54a03.a
+bc54a04.a
+bc54a05.a
+bc54a06.a
+bc70001.a
+bc70002.a
+bc70003.a
+bc70004.a
+bc70005.a
+bc70006.a
+bc70007.a
+bc70008.a
+bc70009.a
+bc70010.a
+bd1b01a.ada
+bd1b02b.ada
+bd1b03c.ada
+bd1b05e.ada
+bd1b06j.ada
+bd2001b.ada
+bd2a01h.ada
+bd2a02a.tst
+bd2a03a.ada
+bd2a03b.ada
+bd2a06a.ada
+bd2a25a.ada
+bd2a35a.ada
+bd2a45a.ada
+bd2a55a.ada
+bd2a55b.ada
+bd2a67a.ada
+bd2a77a.ada
+bd2a85a.ada
+bd2a85b.ada
+bd2b01c.ada
+bd2b02a.ada
+bd2b03a.ada
+bd2b03b.ada
+bd2b03c.ada
+bd2c01d.tst
+bd2c02a.tst
+bd2c03a.tst
+bd2d01c.ada
+bd2d01d.ada
+bd2d02a.ada
+bd2d03a.ada
+bd2d03b.ada
+bd3001a.ada
+bd3001b.ada
+bd3001c.ada
+bd3002a.ada
+bd3003a.ada
+bd3003b.ada
+bd3012a.ada
+bd3013a.ada
+bd4001a.ada
+bd4002a.ada
+bd4003a.ada
+bd4003b.ada
+bd4003c.ada
+bd4006a.tst
+bd4007a.ada
+bd4009a.ada
+bd4011a.ada
+bd5001a.ada
+bd5005a.ada
+bd5005d.ada
+bd5102a.ada
+bd5102b.ada
+bd5103a.ada
+bd5104a.ada
+bd7001a.ada
+bd7101h.ada
+bd7201c.ada
+bd7203a.ada
+bd7204a.ada
+bd7205a.ada
+bd7301a.ada
+bd7302a.ada
+bd8001a.tst
+bd8002a.tst
+bd8003a.tst
+bd8004a.tst
+bd8004b.tst
+bd8004c.tst
+bdb0a01.a
+bdd2001.a
+bdd2002.a
+bde0001.a
+bde0002.a
+bde0003.a
+bde0004.a
+bde0005.a
+bde0006.a
+bde0007.a
+bde0008.a
+bde0009.a
+bde0010.a
+be2101e.ada
+be2101j.ada
+be2114a.ada
+be2116a.ada
+be2208a.ada
+be3002a.ada
+be3002e.ada
+be3205a.ada
+be3301c.ada
+be3606c.ada
+be3703a.ada
+be3802a.ada
+be3803a.ada
+be3902a.ada
+be3903a.ada
+bxa8001.a
+bxac001.a
+bxac002.a
+bxac003.a
+bxac004.a
+bxac005.a
+bxc3001.a
+bxc3002.a
+bxc5001.a
+bxc6001.a
+bxc6002.a
+bxc6003.a
+bxc6a01.a
+bxc6a02.a
+bxc6a03.a
+bxc6a04.a
+bxd1001.a
+bxd1002.a
+bxe2007.a
+bxe2008.a
+bxe2009.a
+bxe2010.a
+bxe2011.a
+bxe2012.a
+bxe2013.a
+bxe2a01.a
+bxe2a02.a
+bxe2a03.a
+bxe2a04.a
+bxe2a05.a
+bxe2a06.a
+bxe4001.a
+bxf1001.a
+bxh4001.a
+bxh4002.a
+bxh4003.a
+bxh4004.a
+bxh4005.a
+bxh4006.a
+bxh4007.a
+bxh4008.a
+bxh4009.a
+bxh4010.a
+bxh4011.a
+bxh4012.a
+bxh4013.a
+c23001a.ada
+c23003a.tst
+c23003b.tst
+c23003g.tst
+c23003i.tst
+c23006a.ada
+c23006b.ada
+c23006c.ada
+c23006d.ada
+c23006e.ada
+c23006f.ada
+c23006g.ada
+c24002d.ada
+c24003a.ada
+c24003b.ada
+c24003c.ada
+c24106a.ada
+c24202d.ada
+c24203a.ada
+c24203b.ada
+c24207a.ada
+c24211a.ada
+c250001.aw
+c250002.aw
+c25001a.ada
+c25001b.ada
+c26006a.ada
+c26008a.ada
+c2a001a.ada
+c2a001b.ada
+c2a001c.ada
+c2a002a.ada
+c2a008a.ada
+c2a021b.ada
+c32001a.ada
+c32001b.ada
+c32001c.ada
+c32001d.ada
+c32001e.ada
+c32107a.ada
+c32107c.ada
+c32108a.ada
+c32108b.ada
+c32111a.ada
+c32111b.ada
+c32112b.ada
+c32113a.ada
+c32115a.ada
+c32115b.ada
+c330001.a
+c330002.a
+c332001.a
+c340001.a
+c34001a.ada
+c34001c.ada
+c34001d.ada
+c34001f.ada
+c34002a.ada
+c34002c.ada
+c34003a.ada
+c34003c.ada
+c34004a.ada
+c34004c.ada
+c34005a.ada
+c34005c.ada
+c34005d.ada
+c34005f.ada
+c34005g.ada
+c34005i.ada
+c34005j.ada
+c34005l.ada
+c34005m.ada
+c34005o.ada
+c34005p.ada
+c34005r.ada
+c34005s.ada
+c34005u.ada
+c34005v.ada
+c34006a.ada
+c34006d.ada
+c34006f.ada
+c34006g.ada
+c34006j.ada
+c34006l.ada
+c34007a.ada
+c34007d.ada
+c34007f.ada
+c34007g.ada
+c34007i.ada
+c34007j.ada
+c34007m.ada
+c34007p.ada
+c34007r.ada
+c34007s.ada
+c34007u.ada
+c34007v.ada
+c34008a.ada
+c34009a.ada
+c34009d.ada
+c34009f.ada
+c34009g.ada
+c34009j.ada
+c34009l.ada
+c34011b.ada
+c34012a.ada
+c34014a.ada
+c34014c.ada
+c34014e.ada
+c34014g.ada
+c34014h.ada
+c34014n.ada
+c34014p.ada
+c34014r.ada
+c34014t.ada
+c34014u.ada
+c34018a.ada
+c340a01.a
+c340a02.a
+c341a01.a
+c341a02.a
+c341a03.a
+c341a04.a
+c35003a.ada
+c35003b.ada
+c35003d.ada
+c35102a.ada
+c352001.a
+c354002.a
+c354003.a
+c35502a.ada
+c35502b.ada
+c35502c.ada
+c35502d.tst
+c35502e.ada
+c35502f.tst
+c35502g.ada
+c35502h.ada
+c35502i.ada
+c35502j.ada
+c35502k.ada
+c35502l.ada
+c35502m.ada
+c35502n.ada
+c35502o.ada
+c35502p.ada
+c35503a.ada
+c35503b.ada
+c35503c.ada
+c35503d.tst
+c35503e.ada
+c35503f.tst
+c35503g.ada
+c35503h.ada
+c35503k.ada
+c35503l.ada
+c35503o.ada
+c35503p.ada
+c35504a.ada
+c35504b.ada
+c35505c.ada
+c35505e.ada
+c35505f.ada
+c35507a.ada
+c35507b.ada
+c35507c.ada
+c35507e.ada
+c35507g.ada
+c35507h.ada
+c35507i.ada
+c35507j.ada
+c35507k.ada
+c35507l.ada
+c35507m.ada
+c35507n.ada
+c35507o.ada
+c35507p.ada
+c35508a.ada
+c35508b.ada
+c35508c.ada
+c35508e.ada
+c35508g.ada
+c35508h.ada
+c35508k.ada
+c35508l.ada
+c35508o.ada
+c35508p.ada
+c35703a.ada
+c35704a.ada
+c35704b.ada
+c35704c.ada
+c35704d.ada
+c35801d.ada
+c35902d.ada
+c35904a.ada
+c35904b.ada
+c35a02a.ada
+c35a05a.ada
+c35a05d.ada
+c35a05n.ada
+c35a05q.ada
+c35a07a.ada
+c35a07d.ada
+c35a08b.ada
+c360002.a
+c36104a.ada
+c36104b.ada
+c36172a.ada
+c36172b.ada
+c36172c.ada
+c36174a.ada
+c36180a.ada
+c36202c.ada
+c36203a.ada
+c36204a.ada
+c36204b.ada
+c36204c.ada
+c36204d.ada
+c36205a.ada
+c36205b.ada
+c36205c.ada
+c36205d.ada
+c36205e.ada
+c36205f.ada
+c36205g.ada
+c36205h.ada
+c36205i.ada
+c36205j.ada
+c36205k.ada
+c36205l.ada
+c36301a.ada
+c36301b.ada
+c36302a.ada
+c36304a.ada
+c36305a.ada
+c37002a.ada
+c37003a.ada
+c37003b.ada
+c37005a.ada
+c37006a.ada
+c37008a.ada
+c37008b.ada
+c37009a.ada
+c37010a.ada
+c37010b.ada
+c371001.a
+c371002.a
+c371003.a
+c37102b.ada
+c37103a.ada
+c37105a.ada
+c37107a.ada
+c37108b.ada
+c37206a.ada
+c37207a.ada
+c37208a.ada
+c37208b.ada
+c37209a.ada
+c37209b.ada
+c37210a.ada
+c37211a.ada
+c37211b.ada
+c37211c.ada
+c37211d.ada
+c37211e.ada
+c37213b.ada
+c37213d.ada
+c37213f.ada
+c37213h.ada
+c37213j.ada
+c37213k.ada
+c37213l.ada
+c37215b.ada
+c37215d.ada
+c37215f.ada
+c37215h.ada
+c37217a.ada
+c37217b.ada
+c37217c.ada
+c37304a.ada
+c37305a.ada
+c37306a.ada
+c37309a.ada
+c37310a.ada
+c37312a.ada
+c37402a.ada
+c37403a.ada
+c37404a.ada
+c37404b.ada
+c37405a.ada
+c37411a.ada
+c380001.a
+c380002.a
+c380003.a
+c380004.a
+c38002a.ada
+c38002b.ada
+c38005a.ada
+c38005b.ada
+c38005c.ada
+c38006a.ada
+c38102a.ada
+c38102b.ada
+c38102c.ada
+c38102d.ada
+c38102e.ada
+c38104a.ada
+c38107a.ada
+c38107b.ada
+c38108a.ada
+c38108b.ada
+c38108c0.ada
+c38108c1.ada
+c38108c2.ada
+c38108d0.ada
+c38108d1.ada
+c38202a.ada
+c3900010.a
+c3900011.am
+c390002.a
+c390003.a
+c390004.a
+c3900050.a
+c3900051.a
+c3900052.a
+c3900053.am
+c3900060.a
+c3900061.a
+c3900062.a
+c3900063.am
+c390007.a
+c390010.a
+c390011.a
+c39006a.ada
+c39006b.ada
+c39006c0.ada
+c39006c1.ada
+c39006d.ada
+c39006e.ada
+c39006f0.ada
+c39006f1.ada
+c39006f2.ada
+c39006f3.ada
+c39006g.ada
+c39007a.ada
+c39007b.ada
+c39008a.ada
+c39008b.ada
+c39008c.ada
+c390a010.a
+c390a011.am
+c390a020.a
+c390a021.a
+c390a022.am
+c390a030.a
+c390a031.am
+c391001.a
+c391002.a
+c392002.a
+c392003.a
+c392004.a
+c392005.a
+c392008.a
+c392010.a
+c392011.a
+c392013.a
+c392014.a
+c392a01.a
+c392c05.a
+c392c07.a
+c392d01.a
+c392d02.a
+c392d03.a
+c393001.a
+c393007.a
+c393008.a
+c393009.a
+c393010.a
+c393011.a
+c393012.a
+c393a02.a
+c393a03.a
+c393a05.a
+c393a06.a
+c393b12.a
+c393b13.a
+c393b14.a
+c3a0001.a
+c3a0002.a
+c3a0003.a
+c3a0004.a
+c3a0005.a
+c3a0006.a
+c3a0007.a
+c3a0008.a
+c3a0009.a
+c3a0010.a
+c3a0011.a
+c3a00120.a
+c3a00121.a
+c3a00122.am
+c3a0013.a
+c3a0014.a
+c3a0015.a
+c3a1001.a
+c3a1002.a
+c3a2001.a
+c3a2002.a
+c3a2003.a
+c3a2a01.a
+c3a2a02.a
+c410001.a
+c41101d.ada
+c41103a.ada
+c41103b.ada
+c41104a.ada
+c41105a.ada
+c41107a.ada
+c41201d.ada
+c41203a.ada
+c41203b.ada
+c41204a.ada
+c41205a.ada
+c41206a.ada
+c41207a.ada
+c41301a.ada
+c41303a.ada
+c41303b.ada
+c41303c.ada
+c41303e.ada
+c41303f.ada
+c41303g.ada
+c41303i.ada
+c41303j.ada
+c41303k.ada
+c41303m.ada
+c41303n.ada
+c41303o.ada
+c41303q.ada
+c41303r.ada
+c41303s.ada
+c41303u.ada
+c41303v.ada
+c41303w.ada
+c41304a.ada
+c41304b.ada
+c41306a.ada
+c41306b.ada
+c41306c.ada
+c41307d.ada
+c41309a.ada
+c41320a.ada
+c41321a.ada
+c41322a.ada
+c41323a.ada
+c41324a.ada
+c41325a.ada
+c41326a.ada
+c41327a.ada
+c41328a.ada
+c41401a.ada
+c41402a.ada
+c41404a.ada
+c420001.a
+c42006a.ada
+c42007e.ada
+c43003a.ada
+c43004a.ada
+c43004c.ada
+c431001.a
+c43103a.ada
+c43103b.ada
+c43104a.ada
+c43105a.ada
+c43105b.ada
+c43106a.ada
+c43107a.ada
+c43108a.ada
+c432001.a
+c432002.a
+c432003.a
+c432004.a
+c43204a.ada
+c43204c.ada
+c43204e.ada
+c43204f.ada
+c43204g.ada
+c43204h.ada
+c43204i.ada
+c43205a.ada
+c43205b.ada
+c43205c.ada
+c43205d.ada
+c43205e.ada
+c43205g.ada
+c43205h.ada
+c43205i.ada
+c43205j.ada
+c43205k.ada
+c43206a.ada
+c43207b.ada
+c43207d.ada
+c43208a.ada
+c43208b.ada
+c43209a.ada
+c43210a.ada
+c43211a.ada
+c43212a.ada
+c43212c.ada
+c43214a.ada
+c43214b.ada
+c43214c.ada
+c43214d.ada
+c43214e.ada
+c43214f.ada
+c43215a.ada
+c43215b.ada
+c43222a.ada
+c43224a.ada
+c433001.a
+c44003d.ada
+c44003f.ada
+c44003g.ada
+c450001.a
+c45112a.ada
+c45112b.ada
+c45113a.ada
+c45114b.ada
+c452001.a
+c45201a.ada
+c45201b.ada
+c45202b.ada
+c45210a.ada
+c45211a.ada
+c45220a.ada
+c45220b.ada
+c45220c.ada
+c45220d.ada
+c45220e.ada
+c45220f.ada
+c45231a.ada
+c45231b.dep
+c45231c.dep
+c45231d.tst
+c45232b.ada
+c45242b.ada
+c45251a.ada
+c45252a.ada
+c45252b.ada
+c45253a.ada
+c45262a.ada
+c45262b.ada
+c45262c.ada
+c45262d.ada
+c45264a.ada
+c45264b.ada
+c45264c.ada
+c45265a.ada
+c45271a.ada
+c45272a.ada
+c45273a.ada
+c45274a.ada
+c45274b.ada
+c45274c.ada
+c45281a.ada
+c45282a.ada
+c45282b.ada
+c45291a.ada
+c45303a.ada
+c45304a.ada
+c45304b.dep
+c45304c.dep
+c45322a.ada
+c45323a.ada
+c45331a.ada
+c45342a.ada
+c45343a.ada
+c45344a.ada
+c45345b.ada
+c45347a.ada
+c45347b.ada
+c45347c.ada
+c45347d.ada
+c45411a.ada
+c45411b.dep
+c45411c.dep
+c45411d.ada
+c45413a.ada
+c45431a.ada
+c455001.a
+c45502b.dep
+c45502c.dep
+c45503a.ada
+c45503b.dep
+c45503c.dep
+c45504a.ada
+c45504b.dep
+c45504c.dep
+c45504d.ada
+c45504e.dep
+c45504f.dep
+c45505a.ada
+c45523a.ada
+c45531a.ada
+c45531b.ada
+c45531c.ada
+c45531d.ada
+c45531e.ada
+c45531f.ada
+c45531g.ada
+c45531h.ada
+c45531i.ada
+c45531j.ada
+c45531k.ada
+c45531l.ada
+c45531m.dep
+c45531n.dep
+c45531o.dep
+c45531p.dep
+c45532a.ada
+c45532b.ada
+c45532c.ada
+c45532d.ada
+c45532e.ada
+c45532f.ada
+c45532g.ada
+c45532h.ada
+c45532i.ada
+c45532j.ada
+c45532k.ada
+c45532l.ada
+c45532m.dep
+c45532n.dep
+c45532o.dep
+c45532p.dep
+c45534b.ada
+c45536a.dep
+c456001.a
+c45611a.ada
+c45611b.dep
+c45611c.dep
+c45613a.ada
+c45613b.dep
+c45613c.dep
+c45614a.ada
+c45614b.dep
+c45614c.dep
+c45631a.ada
+c45631b.dep
+c45631c.dep
+c45632a.ada
+c45632b.dep
+c45632c.dep
+c45651a.ada
+c45662a.ada
+c45662b.ada
+c45672a.ada
+c460001.a
+c460002.a
+c460004.a
+c460005.a
+c460006.a
+c460007.a
+c460008.a
+c460009.a
+c460010.a
+c460011.a
+c460012.a
+c46011a.ada
+c46013a.ada
+c46014a.ada
+c46021a.ada
+c46024a.ada
+c46031a.ada
+c46032a.ada
+c46033a.ada
+c46041a.ada
+c46042a.ada
+c46043b.ada
+c46044b.ada
+c46051a.ada
+c46051b.ada
+c46051c.ada
+c46052a.ada
+c46053a.ada
+c46054a.ada
+c460a01.a
+c460a02.a
+c47002a.ada
+c47002b.ada
+c47002c.ada
+c47002d.ada
+c47003a.ada
+c47004a.ada
+c47005a.ada
+c47006a.ada
+c47007a.ada
+c47008a.ada
+c47009a.ada
+c47009b.ada
+c48004a.ada
+c48004b.ada
+c48004c.ada
+c48004d.ada
+c48004e.ada
+c48004f.ada
+c48005a.ada
+c48005b.ada
+c48006a.ada
+c48006b.ada
+c48007a.ada
+c48007b.ada
+c48007c.ada
+c48008a.ada
+c48008c.ada
+c48009a.ada
+c48009b.ada
+c48009c.ada
+c48009d.ada
+c48009e.ada
+c48009f.ada
+c48009g.ada
+c48009h.ada
+c48009i.ada
+c48009j.ada
+c48010a.ada
+c48011a.ada
+c48012a.ada
+c490001.a
+c490002.a
+c490003.a
+c49020a.ada
+c49021a.ada
+c49022a.ada
+c49022b.ada
+c49022c.ada
+c49023a.ada
+c49024a.ada
+c49025a.ada
+c49026a.ada
+c4a005b.ada
+c4a006a.ada
+c4a007a.tst
+c4a010a.ada
+c4a010b.ada
+c4a011a.ada
+c4a012b.ada
+c4a013a.ada
+c4a014a.ada
+c51004a.ada
+c52005a.ada
+c52005b.ada
+c52005c.ada
+c52005d.ada
+c52005e.ada
+c52005f.ada
+c52008a.ada
+c52008b.ada
+c52009a.ada
+c52009b.ada
+c52010a.ada
+c52011a.ada
+c52011b.ada
+c52101a.ada
+c52102a.ada
+c52102b.ada
+c52102c.ada
+c52102d.ada
+c52103a.ada
+c52103b.ada
+c52103c.ada
+c52103f.ada
+c52103g.ada
+c52103h.ada
+c52103k.ada
+c52103l.ada
+c52103m.ada
+c52103p.ada
+c52103q.ada
+c52103r.ada
+c52103x.ada
+c52104a.ada
+c52104b.ada
+c52104c.ada
+c52104f.ada
+c52104g.ada
+c52104h.ada
+c52104k.ada
+c52104l.ada
+c52104m.ada
+c52104p.ada
+c52104q.ada
+c52104r.ada
+c52104x.ada
+c52104y.ada
+c53007a.ada
+c540001.a
+c54a03a.ada
+c54a04a.ada
+c54a07a.ada
+c54a13a.ada
+c54a13b.ada
+c54a13c.ada
+c54a13d.ada
+c54a22a.ada
+c54a23a.ada
+c54a24a.ada
+c54a24b.ada
+c54a42a.ada
+c54a42b.ada
+c54a42c.ada
+c54a42d.ada
+c54a42e.ada
+c54a42f.ada
+c54a42g.ada
+c55b03a.ada
+c55b04a.ada
+c55b05a.ada
+c55b06a.ada
+c55b06b.ada
+c55b07a.dep
+c55b07b.dep
+c55b10a.ada
+c55b11a.ada
+c55b11b.ada
+c55b15a.ada
+c55b16a.ada
+c55c02a.ada
+c55c02b.ada
+c56002a.ada
+c57003a.ada
+c57004a.ada
+c57004b.ada
+c58004c.ada
+c58004d.ada
+c58004g.ada
+c58005a.ada
+c58005b.ada
+c58005h.ada
+c58006a.ada
+c58006b.ada
+c59002a.ada
+c59002b.ada
+c59002c.ada
+c61008a.ada
+c61009a.ada
+c61010a.ada
+c62002a.ada
+c62003a.ada
+c62003b.ada
+c62004a.ada
+c62006a.ada
+c631001.a
+c640001.a
+c64002b.ada
+c64004g.ada
+c64005a.ada
+c64005b.ada
+c64005c.ada
+c64005d0.ada
+c64005da.ada
+c64005db.ada
+c64005dc.ada
+c641001.a
+c64103b.ada
+c64103c.ada
+c64103d.ada
+c64103e.ada
+c64103f.ada
+c64104a.ada
+c64104b.ada
+c64104c.ada
+c64104d.ada
+c64104e.ada
+c64104f.ada
+c64104g.ada
+c64104h.ada
+c64104i.ada
+c64104j.ada
+c64104k.ada
+c64104l.ada
+c64104m.ada
+c64104n.ada
+c64104o.ada
+c64105a.ada
+c64105b.ada
+c64105c.ada
+c64105d.ada
+c64106a.ada
+c64106b.ada
+c64106c.ada
+c64106d.ada
+c64107a.ada
+c64108a.ada
+c64109a.ada
+c64109b.ada
+c64109c.ada
+c64109d.ada
+c64109e.ada
+c64109f.ada
+c64109g.ada
+c64109h.ada
+c64109i.ada
+c64109j.ada
+c64109k.ada
+c64109l.ada
+c64201b.ada
+c64201c.ada
+c64202a.ada
+c650001.a
+c65003a.ada
+c65003b.ada
+c66002a.ada
+c66002c.ada
+c66002d.ada
+c66002e.ada
+c66002f.ada
+c66002g.ada
+c67002a.ada
+c67002b.ada
+c67002c.ada
+c67002d.ada
+c67002e.ada
+c67003f.ada
+c67005a.ada
+c67005b.ada
+c67005c.ada
+c67005d.ada
+c72001b.ada
+c72002a.ada
+c730001.a
+c730002.a
+c730003.a
+c730004.a
+c73002a.ada
+c730a01.a
+c730a02.a
+c731001.a
+c74004a.ada
+c74203a.ada
+c74206a.ada
+c74207b.ada
+c74208a.ada
+c74208b.ada
+c74209a.ada
+c74210a.ada
+c74211a.ada
+c74211b.ada
+c74302a.ada
+c74302b.ada
+c74305a.ada
+c74305b.ada
+c74306a.ada
+c74307a.ada
+c74401d.ada
+c74401e.ada
+c74401k.ada
+c74401q.ada
+c74402a.ada
+c74402b.ada
+c74406a.ada
+c74407b.ada
+c74409b.ada
+c760001.a
+c760002.a
+c760007.a
+c760009.a
+c760010.a
+c760011.a
+c760012.a
+c760013.a
+c761001.a
+c761002.a
+c761003.a
+c761004.a
+c761005.a
+c761006.a
+c761007.a
+c761010.a
+c761011.a
+c761012.a
+c83007a.ada
+c83012d.ada
+c83022a.ada
+c83022g0.ada
+c83022g1.ada
+c83023a.ada
+c83024a.ada
+c83024e0.ada
+c83024e1.ada
+c83025a.ada
+c83025c.ada
+c83027a.ada
+c83027c.ada
+c83028a.ada
+c83029a.ada
+c83030a.ada
+c83030c.ada
+c83031a.ada
+c83031c.ada
+c83031e.ada
+c83032a.ada
+c83033a.ada
+c83051a.ada
+c83b02a.ada
+c83b02b.ada
+c83e02a.ada
+c83e02b.ada
+c83e03a.ada
+c83f01a.ada
+c83f01b.ada
+c83f01c0.ada
+c83f01c1.ada
+c83f01c2.ada
+c83f01d0.ada
+c83f01d1.ada
+c83f03a.ada
+c83f03b.ada
+c83f03c0.ada
+c83f03c1.ada
+c83f03c2.ada
+c83f03d0.ada
+c83f03d1.ada
+c840001.a
+c84002a.ada
+c84005a.ada
+c84008a.ada
+c84009a.ada
+c85004b.ada
+c85005a.ada
+c85005b.ada
+c85005c.ada
+c85005d.ada
+c85005e.ada
+c85005f.ada
+c85005g.ada
+c85006a.ada
+c85006b.ada
+c85006c.ada
+c85006d.ada
+c85006e.ada
+c85006f.ada
+c85006g.ada
+c85007a.ada
+c85007e.ada
+c85009a.ada
+c85011a.ada
+c85013a.ada
+c85014a.ada
+c85014b.ada
+c85014c.ada
+c85017a.ada
+c85018a.ada
+c85018b.ada
+c85019a.ada
+c854001.a
+c854002.a
+c854003.a
+c86003a.ada
+c86004a.ada
+c86004b0.ada
+c86004b1.ada
+c86004b2.ada
+c86004c0.ada
+c86004c1.ada
+c86004c2.ada
+c86006i.ada
+c86007a.ada
+c87a05a.ada
+c87a05b.ada
+c87b02a.ada
+c87b02b.ada
+c87b03a.ada
+c87b04a.ada
+c87b04b.ada
+c87b04c.ada
+c87b05a.ada
+c87b06a.ada
+c87b07a.ada
+c87b07b.ada
+c87b07c.ada
+c87b07d.ada
+c87b07e.ada
+c87b08a.ada
+c87b09a.ada
+c87b09c.ada
+c87b10a.ada
+c87b11a.ada
+c87b11b.ada
+c87b13a.ada
+c87b14a.ada
+c87b14b.ada
+c87b14c.ada
+c87b14d.ada
+c87b15a.ada
+c87b16a.ada
+c87b17a.ada
+c87b18a.ada
+c87b18b.ada
+c87b19a.ada
+c87b23a.ada
+c87b24a.ada
+c87b24b.ada
+c87b26b.ada
+c87b27a.ada
+c87b28a.ada
+c87b29a.ada
+c87b30a.ada
+c87b31a.ada
+c87b32a.ada
+c87b33a.ada
+c87b34a.ada
+c87b34b.ada
+c87b34c.ada
+c87b35c.ada
+c87b38a.ada
+c87b39a.ada
+c87b40a.ada
+c87b41a.ada
+c87b42a.ada
+c87b43a.ada
+c87b44a.ada
+c87b45a.ada
+c87b45c.ada
+c87b47a.ada
+c87b48a.ada
+c87b48b.ada
+c87b50a.ada
+c87b54a.ada
+c87b57a.ada
+c87b62a.ada
+c87b62b.ada
+c87b62c.ada
+c87b62d.tst
+c910001.a
+c910002.a
+c910003.a
+c91004b.ada
+c91004c.ada
+c91006a.ada
+c91007a.ada
+c92002a.ada
+c92003a.ada
+c92005a.ada
+c92005b.ada
+c92006a.ada
+c930001.a
+c93001a.ada
+c93002a.ada
+c93003a.ada
+c93004a.ada
+c93004b.ada
+c93004c.ada
+c93004d.ada
+c93004f.ada
+c93005a.ada
+c93005b.ada
+c93005c.ada
+c93005d.ada
+c93005e.ada
+c93005f.ada
+c93005g.ada
+c93005h.ada
+c93006a.ada
+c93007a.ada
+c93008a.ada
+c93008b.ada
+c940001.a
+c940002.a
+c940004.a
+c940005.a
+c940006.a
+c940007.a
+c940010.a
+c940011.a
+c940012.a
+c940013.a
+c940014.a
+c940015.a
+c940016.a
+c94001a.ada
+c94001b.ada
+c94001c.ada
+c94001e.ada
+c94001f.ada
+c94001g.ada
+c94002a.ada
+c94002b.ada
+c94002d.ada
+c94002e.ada
+c94002f.ada
+c94002g.ada
+c94004a.ada
+c94004b.ada
+c94004c.ada
+c94005a.ada
+c94005b.ada
+c94006a.ada
+c94007a.ada
+c94007b.ada
+c94008a.ada
+c94008b.ada
+c94008c.ada
+c94008d.ada
+c94010a.ada
+c94011a.ada
+c94020a.ada
+c940a03.a
+c95008a.ada
+c95009a.ada
+c95010a.ada
+c95011a.ada
+c95012a.ada
+c95021a.ada
+c95022a.ada
+c95022b.ada
+c95033a.ada
+c95033b.ada
+c95034a.ada
+c95034b.ada
+c95035a.ada
+c95040a.ada
+c95040b.ada
+c95040c.ada
+c95040d.ada
+c95041a.ada
+c95065a.ada
+c95065b.ada
+c95065c.ada
+c95065d.ada
+c95065e.ada
+c95065f.ada
+c95066a.ada
+c95067a.ada
+c95071a.ada
+c95072a.ada
+c95072b.ada
+c95073a.ada
+c95074c.ada
+c95076a.ada
+c95078a.ada
+c95080b.ada
+c95082g.ada
+c95085a.ada
+c95085b.ada
+c95085c.ada
+c95085d.ada
+c95085e.ada
+c95085f.ada
+c95085g.ada
+c95085h.ada
+c95085i.ada
+c95085j.ada
+c95085k.ada
+c95085l.ada
+c95085m.ada
+c95085n.ada
+c95085o.ada
+c95086a.ada
+c95086b.ada
+c95086c.ada
+c95086d.ada
+c95086e.ada
+c95086f.ada
+c95087a.ada
+c95087b.ada
+c95087c.ada
+c95087d.ada
+c95088a.ada
+c95089a.ada
+c95090a.ada
+c95092a.ada
+c95093a.ada
+c95095a.ada
+c95095b.ada
+c95095c.ada
+c95095d.ada
+c95095e.ada
+c951001.a
+c951002.a
+c953001.a
+c953002.a
+c953003.a
+c954001.a
+c954010.a
+c954011.a
+c954012.a
+c954013.a
+c954014.a
+c954015.a
+c954016.a
+c954017.a
+c954018.a
+c954019.a
+c954020.a
+c954021.a
+c954022.a
+c954023.a
+c954024.a
+c954025.a
+c954026.a
+c954a01.a
+c954a02.a
+c954a03.a
+c960001.a
+c960002.a
+c960004.a
+c96001a.ada
+c96004a.ada
+c96005a.ada
+c96005b.tst
+c96005d.ada
+c96005f.ada
+c96006a.ada
+c96007a.ada
+c96008a.ada
+c96008b.ada
+c97112a.ada
+c97113a.ada
+c97114a.ada
+c97115a.ada
+c97116a.ada
+c97117a.ada
+c97117b.ada
+c97117c.ada
+c97118a.ada
+c97120a.ada
+c97120b.ada
+c97201a.ada
+c97201b.ada
+c97201c.ada
+c97201d.ada
+c97201e.ada
+c97201g.ada
+c97201h.ada
+c97201x.ada
+c97202a.ada
+c97203a.ada
+c97203b.ada
+c97203c.ada
+c97204a.ada
+c97204b.ada
+c97205a.ada
+c97205b.ada
+c97301a.ada
+c97301b.ada
+c97301c.ada
+c97301d.ada
+c97301e.ada
+c97302a.ada
+c97303a.ada
+c97303b.ada
+c97303c.ada
+c97304a.ada
+c97304b.ada
+c97305a.ada
+c97305b.ada
+c97305c.ada
+c97305d.ada
+c97307a.ada
+c974001.a
+c974002.a
+c974003.a
+c974004.a
+c974005.a
+c974006.a
+c974007.a
+c974008.a
+c974009.a
+c974010.a
+c974011.a
+c974012.a
+c974013.a
+c974014.a
+c980001.a
+c980002.a
+c980003.a
+c99004a.ada
+c99005a.ada
+c9a003a.ada
+c9a004a.ada
+c9a007a.ada
+c9a009a.ada
+c9a009c.ada
+c9a009f.ada
+c9a009g.ada
+c9a009h.ada
+c9a010a.ada
+c9a011a.ada
+c9a011b.ada
+ca1003a.ada
+ca1004a.ada
+ca1005a.ada
+ca1006a.ada
+ca1011a0.ada
+ca1011a1.ada
+ca1011a2.ada
+ca1011a3.ada
+ca1011a4.ada
+ca1011a5.ada
+ca1011a6.ada
+ca1012a0.ada
+ca1012a1.ada
+ca1012a2.ada
+ca1012a3.ada
+ca1012a4.ada
+ca1012b0.ada
+ca1012b2.ada
+ca1012b4.ada
+ca1013a0.ada
+ca1013a1.ada
+ca1013a2.ada
+ca1013a3.ada
+ca1013a4.ada
+ca1013a5.ada
+ca1013a6.ada
+ca1014a0.ada
+ca1014a1.ada
+ca1014a2.ada
+ca1014a3.ada
+ca1020e0.ada
+ca1020e1.ada
+ca1020e2.ada
+ca1020e3.ada
+ca1022a0.ada
+ca1022a1.ada
+ca1022a2.ada
+ca1022a3.ada
+ca1022a4.ada
+ca1022a5.ada
+ca1022a6.ada
+ca11001.a
+ca11002.a
+ca11003.a
+ca110040.a
+ca110041.a
+ca110042.am
+ca110050.a
+ca110051.am
+ca11006.a
+ca11007.a
+ca11008.a
+ca11009.a
+ca11010.a
+ca11011.a
+ca11012.a
+ca11013.a
+ca11014.a
+ca11015.a
+ca11016.a
+ca11017.a
+ca11018.a
+ca11019.a
+ca11020.a
+ca11021.a
+ca11022.a
+ca1102a0.ada
+ca1102a1.ada
+ca1102a2.ada
+ca1106a.ada
+ca1108a.ada
+ca1108b.ada
+ca11a01.a
+ca11a02.a
+ca11b01.a
+ca11b02.a
+ca11c01.a
+ca11c02.a
+ca11c03.a
+ca11d010.a
+ca11d011.a
+ca11d012.a
+ca11d013.am
+ca11d02.a
+ca11d03.a
+ca13001.a
+ca13002.a
+ca13003.a
+ca13a01.a
+ca13a02.a
+ca140230.a
+ca140231.a
+ca140232.am
+ca140233.a
+ca140280.a
+ca140281.a
+ca140282.a
+ca140283.am
+ca15003.a
+ca200020.a
+ca200021.a
+ca200022.am
+ca2001h0.ada
+ca2001h1.ada
+ca2001h2.ada
+ca2001h3.ada
+ca2002a0.ada
+ca2002a1.ada
+ca2002a2.ada
+ca2003a0.ada
+ca2003a1.ada
+ca2004a0.ada
+ca2004a1.ada
+ca2004a2.ada
+ca2004a3.ada
+ca2004a4.ada
+ca2007a0.ada
+ca2007a1.ada
+ca2007a2.ada
+ca2007a3.ada
+ca2008a0.ada
+ca2008a1.ada
+ca2008a2.ada
+ca2009a.ada
+ca2009c0.ada
+ca2009c1.ada
+ca2009d.ada
+ca2009f0.ada
+ca2009f1.ada
+ca2009f2.ada
+ca2011b.ada
+ca21001.a
+ca3011a0.ada
+ca3011a1.ada
+ca3011a2.ada
+ca3011a3.ada
+ca3011a4.ada
+ca5003a0.ada
+ca5003a1.ada
+ca5003a2.ada
+ca5003a3.ada
+ca5003a4.ada
+ca5003a5.ada
+ca5003a6.ada
+ca5003b0.ada
+ca5003b1.ada
+ca5003b2.ada
+ca5003b3.ada
+ca5003b4.ada
+ca5003b5.ada
+ca5004a.ada
+ca5004b0.ada
+ca5004b1.ada
+ca5004b2.ada
+ca5006a.ada
+cb10002.a
+cb1001a.ada
+cb1004a.ada
+cb1005a.ada
+cb1010a.ada
+cb1010c.ada
+cb1010d.ada
+cb20001.a
+cb20003.a
+cb20004.a
+cb20005.a
+cb20006.a
+cb20007.a
+cb2004a.ada
+cb2005a.ada
+cb2006a.ada
+cb2007a.ada
+cb20a02.a
+cb3003a.ada
+cb3003b.ada
+cb3004a.ada
+cb40005.a
+cb4001a.ada
+cb4002a.ada
+cb4003a.ada
+cb4004a.ada
+cb4005a.ada
+cb4006a.ada
+cb4007a.ada
+cb4008a.ada
+cb4009a.ada
+cb4013a.ada
+cb40a01.a
+cb40a020.a
+cb40a021.am
+cb40a030.a
+cb40a031.am
+cb40a04.a
+cb41001.a
+cb41002.a
+cb41003.a
+cb41004.a
+cb5001a.ada
+cb5001b.ada
+cb5002a.ada
+cc1004a.ada
+cc1005b.ada
+cc1010a.ada
+cc1010b.ada
+cc1018a.ada
+cc1104c.ada
+cc1107b.ada
+cc1111a.ada
+cc1204a.ada
+cc1207b.ada
+cc1220a.ada
+cc1221a.ada
+cc1221b.ada
+cc1221c.ada
+cc1221d.ada
+cc1222a.ada
+cc1223a.ada
+cc1224a.ada
+cc1225a.tst
+cc1226b.ada
+cc1227a.ada
+cc1301a.ada
+cc1302a.ada
+cc1304a.ada
+cc1304b.ada
+cc1307a.ada
+cc1307b.ada
+cc1308a.ada
+cc1310a.ada
+cc1311a.ada
+cc1311b.ada
+cc2002a.ada
+cc30001.a
+cc30002.a
+cc3004a.ada
+cc3007a.ada
+cc3007b.ada
+cc3011a.ada
+cc3011d.ada
+cc3012a.ada
+cc3015a.ada
+cc3016b.ada
+cc3016c.ada
+cc3016f.ada
+cc3016i.ada
+cc3017b.ada
+cc3017c.ada
+cc3019a.ada
+cc3019b0.ada
+cc3019b1.ada
+cc3019b2.ada
+cc3019c0.ada
+cc3019c1.ada
+cc3019c2.ada
+cc3106b.ada
+cc3120a.ada
+cc3120b.ada
+cc3121a.ada
+cc3123a.ada
+cc3125a.ada
+cc3125b.ada
+cc3125c.ada
+cc3125d.ada
+cc3126a.ada
+cc3127a.ada
+cc3128a.ada
+cc3203a.ada
+cc3207b.ada
+cc3220a.ada
+cc3221a.ada
+cc3222a.ada
+cc3223a.ada
+cc3224a.ada
+cc3225a.ada
+cc3230a.ada
+cc3231a.ada
+cc3232a.ada
+cc3233a.ada
+cc3234a.ada
+cc3235a.ada
+cc3236a.ada
+cc3240a.ada
+cc3305a.ada
+cc3305b.ada
+cc3305c.ada
+cc3305d.ada
+cc3601a.ada
+cc3601c.ada
+cc3602a.ada
+cc3603a.ada
+cc3605a.ada
+cc3606a.ada
+cc3606b.ada
+cc3607b.ada
+cc40001.a
+cc50001.a
+cc50a01.a
+cc50a02.a
+cc51001.a
+cc51002.a
+cc51003.a
+cc51004.a
+cc51006.a
+cc51007.a
+cc51008.a
+cc51a01.a
+cc51b03.a
+cc51d01.a
+cc51d02.a
+cc54001.a
+cc54002.a
+cc54003.a
+cc54004.a
+cc70001.a
+cc70002.a
+cc70003.a
+cc70a01.a
+cc70a02.a
+cc70b01.a
+cc70b02.a
+cc70c01.a
+cc70c02.a
+cd10001.a
+cd10002.a
+cd1009a.ada
+cd1009b.ada
+cd1009d.ada
+cd1009e.ada
+cd1009f.ada
+cd1009g.ada
+cd1009h.ada
+cd1009i.ada
+cd1009j.ada
+cd1009k.tst
+cd1009l.ada
+cd1009m.ada
+cd1009n.ada
+cd1009o.ada
+cd1009p.ada
+cd1009q.ada
+cd1009r.ada
+cd1009s.ada
+cd1009t.tst
+cd1009u.tst
+cd1009v.ada
+cd1009w.ada
+cd1009x.ada
+cd1009y.ada
+cd1009z.ada
+cd1c03a.ada
+cd1c03b.ada
+cd1c03c.ada
+cd1c03e.tst
+cd1c03f.ada
+cd1c03g.ada
+cd1c03h.ada
+cd1c03i.ada
+cd1c04a.ada
+cd1c04d.ada
+cd1c04e.ada
+cd1c06a.tst
+cd20001.a
+cd2a21a.ada
+cd2a21c.ada
+cd2a21e.ada
+cd2a22a.ada
+cd2a22e.ada
+cd2a22i.ada
+cd2a22j.ada
+cd2a23a.ada
+cd2a23e.ada
+cd2a24a.ada
+cd2a24e.ada
+cd2a24i.ada
+cd2a24j.ada
+cd2a31a.ada
+cd2a31c.ada
+cd2a31e.ada
+cd2a32a.ada
+cd2a32c.ada
+cd2a32e.ada
+cd2a32g.ada
+cd2a32i.ada
+cd2a32j.ada
+cd2a51a.ada
+cd2a53a.ada
+cd2a53e.ada
+cd2a83c.tst
+cd2a91c.tst
+cd2b11a.ada
+cd2b11b.ada
+cd2b11d.ada
+cd2b11e.ada
+cd2b11f.ada
+cd2b15c.ada
+cd2b16a.ada
+cd2c11a.tst
+cd2c11d.tst
+cd2d11a.ada
+cd2d13a.ada
+cd30001.a
+cd30002.a
+cd30003.a
+cd30004.a
+cd300050.am
+cd300051.c
+cd3014a.ada
+cd3014c.ada
+cd3014d.ada
+cd3014f.ada
+cd3015a.ada
+cd3015c.ada
+cd3015e.ada
+cd3015f.ada
+cd3015g.ada
+cd3015h.ada
+cd3015i.ada
+cd3015k.ada
+cd3021a.ada
+cd33001.a
+cd33002.a
+cd40001.a
+cd4031a.ada
+cd4041a.tst
+cd4051a.ada
+cd4051b.ada
+cd4051c.ada
+cd4051d.ada
+cd5003a.ada
+cd5003b.ada
+cd5003c.ada
+cd5003d.ada
+cd5003e.ada
+cd5003f.ada
+cd5003g.ada
+cd5003h.ada
+cd5003i.ada
+cd5011a.ada
+cd5011c.ada
+cd5011e.ada
+cd5011g.ada
+cd5011i.ada
+cd5011k.ada
+cd5011m.ada
+cd5011q.ada
+cd5011s.ada
+cd5012a.ada
+cd5012b.ada
+cd5012e.ada
+cd5012f.ada
+cd5012i.ada
+cd5012m.ada
+cd5013a.ada
+cd5013c.ada
+cd5013e.ada
+cd5013g.ada
+cd5013i.ada
+cd5013k.ada
+cd5013m.ada
+cd5013o.ada
+cd5014a.ada
+cd5014c.ada
+cd5014e.ada
+cd5014g.ada
+cd5014i.ada
+cd5014k.ada
+cd5014m.ada
+cd5014o.ada
+cd5014t.ada
+cd5014v.ada
+cd5014x.ada
+cd5014y.ada
+cd5014z.ada
+cd70001.a
+cd7002a.ada
+cd7007b.ada
+cd7101d.ada
+cd7101e.dep
+cd7101f.dep
+cd7101g.tst
+cd7103d.ada
+cd7202a.ada
+cd7204b.ada
+cd7204c.ada
+cd72a01.a
+cd72a02.a
+cd7305a.ada
+cd90001.a
+cd92001.a
+cda201a.ada
+cda201b.ada
+cda201c.ada
+cda201e.ada
+cdb0a01.a
+cdb0a02.a
+cdd1001.a
+cdd2001.a
+cdd2a01.a
+cdd2a02.a
+cdd2a03.a
+cde0001.a
+ce2102a.ada
+ce2102b.ada
+ce2102c.tst
+ce2102d.ada
+ce2102e.ada
+ce2102f.ada
+ce2102g.ada
+ce2102h.tst
+ce2102i.ada
+ce2102j.ada
+ce2102k.ada
+ce2102l.ada
+ce2102m.ada
+ce2102n.ada
+ce2102o.ada
+ce2102p.ada
+ce2102q.ada
+ce2102r.ada
+ce2102s.ada
+ce2102t.ada
+ce2102u.ada
+ce2102v.ada
+ce2102w.ada
+ce2102x.ada
+ce2102y.ada
+ce2103a.tst
+ce2103b.tst
+ce2103c.ada
+ce2103d.ada
+ce2104a.ada
+ce2104b.ada
+ce2104c.ada
+ce2104d.ada
+ce2106a.ada
+ce2106b.ada
+ce2108e.ada
+ce2108f.ada
+ce2108g.ada
+ce2108h.ada
+ce2109a.ada
+ce2109b.ada
+ce2109c.ada
+ce2110a.ada
+ce2110c.ada
+ce2111a.ada
+ce2111b.ada
+ce2111c.ada
+ce2111e.ada
+ce2111f.ada
+ce2111g.ada
+ce2111i.ada
+ce2201a.ada
+ce2201b.ada
+ce2201c.ada
+ce2201d.dep
+ce2201e.dep
+ce2201f.ada
+ce2201g.ada
+ce2201h.ada
+ce2201i.ada
+ce2201j.ada
+ce2201k.ada
+ce2201l.ada
+ce2201m.ada
+ce2201n.ada
+ce2202a.ada
+ce2203a.tst
+ce2204a.ada
+ce2204b.ada
+ce2204c.ada
+ce2204d.ada
+ce2205a.ada
+ce2206a.ada
+ce2208b.ada
+ce2401a.ada
+ce2401b.ada
+ce2401c.ada
+ce2401e.ada
+ce2401f.ada
+ce2401h.ada
+ce2401i.ada
+ce2401j.ada
+ce2401k.ada
+ce2401l.ada
+ce2402a.ada
+ce2403a.tst
+ce2404a.ada
+ce2404b.ada
+ce2405b.ada
+ce2406a.ada
+ce2407a.ada
+ce2407b.ada
+ce2408a.ada
+ce2408b.ada
+ce2409a.ada
+ce2409b.ada
+ce2410a.ada
+ce2410b.ada
+ce2411a.ada
+ce3002b.tst
+ce3002c.tst
+ce3002d.ada
+ce3002f.ada
+ce3102a.ada
+ce3102b.tst
+ce3102d.ada
+ce3102e.ada
+ce3102f.ada
+ce3102g.ada
+ce3102h.ada
+ce3102i.ada
+ce3102j.ada
+ce3102k.ada
+ce3103a.ada
+ce3104a.ada
+ce3104b.ada
+ce3104c.ada
+ce3106a.ada
+ce3106b.ada
+ce3107a.tst
+ce3107b.ada
+ce3108a.ada
+ce3108b.ada
+ce3110a.ada
+ce3112c.ada
+ce3112d.ada
+ce3114a.ada
+ce3115a.ada
+ce3201a.ada
+ce3202a.ada
+ce3206a.ada
+ce3207a.ada
+ce3301a.ada
+ce3302a.ada
+ce3303a.ada
+ce3304a.tst
+ce3305a.ada
+ce3306a.ada
+ce3401a.ada
+ce3402a.ada
+ce3402c.ada
+ce3402d.ada
+ce3402e.ada
+ce3403a.ada
+ce3403b.ada
+ce3403c.ada
+ce3403d.ada
+ce3403e.ada
+ce3403f.ada
+ce3404a.ada
+ce3404b.ada
+ce3404c.ada
+ce3404d.ada
+ce3405a.ada
+ce3405c.ada
+ce3405d.ada
+ce3406a.ada
+ce3406b.ada
+ce3406c.ada
+ce3406d.ada
+ce3407a.ada
+ce3407b.ada
+ce3407c.ada
+ce3408a.ada
+ce3408b.ada
+ce3408c.ada
+ce3409a.ada
+ce3409b.ada
+ce3409c.ada
+ce3409d.ada
+ce3409e.ada
+ce3410a.ada
+ce3410b.ada
+ce3410c.ada
+ce3410d.ada
+ce3410e.ada
+ce3411a.ada
+ce3411c.ada
+ce3412a.ada
+ce3413a.ada
+ce3413b.ada
+ce3413c.ada
+ce3414a.ada
+ce3601a.ada
+ce3602a.ada
+ce3602b.ada
+ce3602c.ada
+ce3602d.ada
+ce3603a.ada
+ce3604a.ada
+ce3604b.ada
+ce3605a.ada
+ce3605b.ada
+ce3605c.ada
+ce3605d.ada
+ce3605e.ada
+ce3606a.ada
+ce3606b.ada
+ce3701a.ada
+ce3704a.ada
+ce3704b.ada
+ce3704c.ada
+ce3704d.ada
+ce3704e.ada
+ce3704f.ada
+ce3704m.ada
+ce3704n.ada
+ce3704o.ada
+ce3705a.ada
+ce3705b.ada
+ce3705c.ada
+ce3705d.ada
+ce3705e.ada
+ce3706c.ada
+ce3706d.ada
+ce3706f.ada
+ce3706g.ada
+ce3707a.ada
+ce3708a.ada
+ce3801a.ada
+ce3801b.ada
+ce3804a.ada
+ce3804b.ada
+ce3804c.ada
+ce3804d.ada
+ce3804e.ada
+ce3804f.ada
+ce3804g.ada
+ce3804h.ada
+ce3804i.ada
+ce3804j.ada
+ce3804m.ada
+ce3804o.ada
+ce3804p.ada
+ce3805a.ada
+ce3805b.ada
+ce3806a.ada
+ce3806b.ada
+ce3806c.ada
+ce3806d.ada
+ce3806e.ada
+ce3806f.ada
+ce3806g.ada
+ce3806h.ada
+ce3809a.ada
+ce3809b.ada
+ce3810a.ada
+ce3810b.ada
+ce3815a.ada
+ce3901a.ada
+ce3902b.ada
+ce3904a.ada
+ce3904b.ada
+ce3905a.ada
+ce3905b.ada
+ce3905c.ada
+ce3905l.ada
+ce3906a.ada
+ce3906b.ada
+ce3906c.ada
+ce3906d.ada
+ce3906e.ada
+ce3906f.ada
+ce3907a.ada
+ce3908a.ada
+checkfil.ada
+coverage.txt
+cxa3001.a
+cxa3002.a
+cxa3003.a
+cxa3004.a
+cxa4001.a
+cxa4002.a
+cxa4003.a
+cxa4004.a
+cxa4005.a
+cxa4006.a
+cxa4007.a
+cxa4008.a
+cxa4009.a
+cxa4010.a
+cxa4011.a
+cxa4012.a
+cxa4013.a
+cxa4014.a
+cxa4015.a
+cxa4016.a
+cxa4017.a
+cxa4018.a
+cxa4019.a
+cxa4020.a
+cxa4021.a
+cxa4022.a
+cxa4023.a
+cxa4024.a
+cxa4025.a
+cxa4026.a
+cxa4027.a
+cxa4028.a
+cxa4029.a
+cxa4030.a
+cxa4031.a
+cxa4032.a
+cxa4033.a
+cxa4034.a
+cxa5011.a
+cxa5012.a
+cxa5013.a
+cxa5015.a
+cxa5a01.a
+cxa5a02.a
+cxa5a03.a
+cxa5a04.a
+cxa5a05.a
+cxa5a06.a
+cxa5a07.a
+cxa5a08.a
+cxa5a09.a
+cxa5a10.a
+cxa8001.a
+cxa8002.a
+cxa8003.a
+cxa9001.a
+cxa9002.a
+cxaa001.a
+cxaa002.a
+cxaa003.a
+cxaa004.a
+cxaa005.a
+cxaa006.a
+cxaa007.a
+cxaa008.a
+cxaa009.a
+cxaa010.a
+cxaa011.a
+cxaa012.a
+cxaa013.a
+cxaa014.a
+cxaa015.a
+cxaa016.a
+cxaa017.a
+cxaa018.a
+cxaa019.a
+cxab001.a
+cxac001.a
+cxac002.a
+cxac003.a
+cxac004.a
+cxac005.a
+cxaca01.a
+cxaca02.a
+cxacb01.a
+cxacb02.a
+cxacc01.a
+cxaf001.a
+cxb2001.a
+cxb2002.a
+cxb2003.a
+cxb3001.a
+cxb3002.a
+cxb3003.a
+cxb30040.c
+cxb30041.am
+cxb3005.a
+cxb30060.c
+cxb30061.am
+cxb3007.a
+cxb3008.a
+cxb3009.a
+cxb3010.a
+cxb3011.a
+cxb3012.a
+cxb30130.c
+cxb30131.c
+cxb30132.am
+cxb3014.a
+cxb3015.a
+cxb3016.a
+cxb4001.a
+cxb4002.a
+cxb4003.a
+cxb4004.a
+cxb4005.a
+cxb4006.a
+cxb4007.a
+cxb4008.a
+cxb40090.cbl
+cxb40091.cbl
+cxb40092.cbl
+cxb40093.am
+cxb5001.a
+cxb5002.a
+cxb5003.a
+cxb50040.ftn
+cxb50041.ftn
+cxb50042.am
+cxb50050.ftn
+cxb50051.ftn
+cxb50052.am
+cxc3001.a
+cxc3002.a
+cxc3003.a
+cxc3004.a
+cxc3005.a
+cxc3006.a
+cxc3007.a
+cxc3008.a
+cxc3009.a
+cxc6001.a
+cxc6002.a
+cxc6003.a
+cxc7001.a
+cxc7002.a
+cxc7003.a
+cxc7004.a
+cxd1001.a
+cxd1002.a
+cxd1003.a
+cxd1004.a
+cxd1005.a
+cxd1006.a
+cxd1007.a
+cxd1008.a
+cxd2001.a
+cxd2002.a
+cxd2003.a
+cxd2004.a
+cxd2006.a
+cxd2007.a
+cxd2008.a
+cxd3001.a
+cxd3002.a
+cxd3003.a
+cxd4001.a
+cxd4002.a
+cxd4003.a
+cxd4004.a
+cxd4005.a
+cxd4006.a
+cxd4007.a
+cxd4008.a
+cxd4009.a
+cxd4010.a
+cxd5001.a
+cxd6001.a
+cxd6002.a
+cxd6003.a
+cxd8001.a
+cxd8002.a
+cxd8003.a
+cxd9001.a
+cxda001.a
+cxda002.a
+cxda003.a
+cxda004.a
+cxdb001.a
+cxdb002.a
+cxdb003.a
+cxdb004.a
+cxe1001.a
+cxe2001.a
+cxe2002.a
+cxe4001.a
+cxe4002.a
+cxe4003.a
+cxe4004.a
+cxe4005.a
+cxe4006.a
+cxe5001.a
+cxe5002.a
+cxe5003.a
+cxf1001.a
+cxf2001.a
+cxf2002.a
+cxf2003.a
+cxf2004.a
+cxf2005.a
+cxf2a01.a
+cxf2a02.a
+cxf3001.a
+cxf3002.a
+cxf3003.a
+cxf3004.a
+cxf3a01.a
+cxf3a02.a
+cxf3a03.a
+cxf3a04.a
+cxf3a05.a
+cxf3a06.a
+cxf3a07.a
+cxf3a08.a
+cxg1001.a
+cxg1002.a
+cxg1003.a
+cxg1004.a
+cxg1005.a
+cxg2001.a
+cxg2002.a
+cxg2003.a
+cxg2004.a
+cxg2005.a
+cxg2006.a
+cxg2007.a
+cxg2008.a
+cxg2009.a
+cxg2010.a
+cxg2011.a
+cxg2012.a
+cxg2013.a
+cxg2014.a
+cxg2015.a
+cxg2016.a
+cxg2017.a
+cxg2018.a
+cxg2019.a
+cxg2020.a
+cxg2021.a
+cxg2022.a
+cxg2023.a
+cxg2024.a
+cxh1001.a
+cxh3001.a
+cxh3002.a
+cxh30030.a
+cxh30031.am
+cz00004.a
+cz1101a.ada
+cz1102a.ada
+cz1103a.ada
+d4a002a.ada
+d4a002b.ada
+d4a004a.ada
+d4a004b.ada
+e28002b.ada
+e28005d.ada
+e52103y.ada
+eb4011a.ada
+eb4012a.ada
+eb4014a.ada
+ee3203a.ada
+ee3204a.ada
+ee3402b.ada
+ee3409f.ada
+ee3412c.ada
+enumchek.ada
+f340a000.a
+f340a001.a
+f341a00.a
+f390a00.a
+f392a00.a
+f392c00.a
+f392d00.a
+f393a00.a
+f393b00.a
+f3a2a00.a
+f460a00.a
+f730a000.a
+f730a001.a
+f731a00.a
+f940a00.a
+f954a00.a
+fa11a00.a
+fa11b00.a
+fa11c00.a
+fa11d00.a
+fa13a00.a
+fa13b00.a
+fa21a00.a
+fb20a00.a
+fb40a00.a
+fc50a00.a
+fc51a00.a
+fc51b00.a
+fc51c00.a
+fc51d00.a
+fc54a00.a
+fc70a00.a
+fc70b00.a
+fc70c00.a
+fcndecl.ada
+fd72a00.a
+fdb0a00.a
+fdd2a00.a
+fxa5a00.a
+fxaca00.a
+fxacb00.a
+fxacc00.a
+fxc6a00.a
+fxe2a00.a
+fxf2a00.a
+fxf3a00.a
+impdef.a
+impdefc.a
+impdefd.a
+impdefe.a
+impdefg.a
+impdefh.a
+la140010.a
+la140011.am
+la140012.a
+la140020.a
+la140021.am
+la140022.a
+la140030.a
+la140031.a
+la140032.am
+la140033.a
+la140040.a
+la140041.am
+la140042.a
+la140050.a
+la140051.a
+la140052.am
+la140053.a
+la140060.a
+la140061.a
+la140062.am
+la140063.a
+la140070.a
+la140071.a
+la140072.am
+la140073.a
+la140080.a
+la140081.a
+la140082.am
+la140083.a
+la140090.a
+la140091.a
+la140092.am
+la140093.a
+la140100.a
+la140101.a
+la140102.am
+la140103.a
+la140110.a
+la140111.a
+la140112.am
+la140113.a
+la140120.a
+la140121.a
+la140122.am
+la140123.a
+la140130.a
+la140131.a
+la140132.am
+la140133.a
+la140140.a
+la140141.a
+la140142.am
+la140143.a
+la140150.a
+la140151.a
+la140152.am
+la140153.a
+la140160.a
+la140161.a
+la140162.am
+la140163.a
+la140170.a
+la140171.a
+la140172.am
+la140173.a
+la140180.a
+la140181.a
+la140182.am
+la140183.a
+la140190.a
+la140191.a
+la140192.am
+la140193.a
+la140200.a
+la140201.a
+la140202.am
+la140203.a
+la140210.a
+la140211.am
+la140212.a
+la140220.a
+la140221.am
+la140222.a
+la140240.a
+la140241.a
+la140242.am
+la140243.a
+la140250.a
+la140251.am
+la140252.a
+la140260.a
+la140261.a
+la140262.am
+la140263.a
+la140270.a
+la140271.a
+la140272.am
+la140273.a
+la200010.a
+la200011.a
+la200012.am
+la5001a0.ada
+la5001a1.ada
+la5001a2.ada
+la5001a3.ada
+la5001a4.ada
+la5001a5.ada
+la5001a6.ada
+la5001a7.ada
+la5007a0.ada
+la5007a1.ada
+la5007b0.ada
+la5007b1.ada
+la5007c0.ada
+la5007c1.ada
+la5007d0.ada
+la5007d1.ada
+la5007e0.ada
+la5007e1.ada
+la5007f0.ada
+la5007f1.ada
+la5007g0.ada
+la5007g1.ada
+la5008a0.ada
+la5008a1.ada
+la5008b0.ada
+la5008b1.ada
+la5008c0.ada
+la5008c1.ada
+la5008d0.ada
+la5008d1.ada
+la5008e0.ada
+la5008e1.ada
+la5008f0.ada
+la5008f1.ada
+la5008g0.ada
+la5008g1.ada
+lc300010.a
+lc300011.a
+lc300012.am
+lc300020.a
+lc300021.a
+lc300022.am
+lc300030.a
+lc300031.a
+lc300032.am
+lencheck.ada
+lxd70010.a
+lxd70011.a
+lxd70012.am
+lxd70030.a
+lxd70031.a
+lxd70032.am
+lxd70040.a
+lxd70041.a
+lxd70042.am
+lxd70050.a
+lxd70051.a
+lxd70052.am
+lxd70060.a
+lxd70061.a
+lxd70062.am
+lxd70070.a
+lxd70071.a
+lxd70072.am
+lxd70080.a
+lxd70081.a
+lxd70082.am
+lxd70090.a
+lxd70091.a
+lxd70092.am
+lxe30010.am
+lxe30011.am
+lxe30020.am
+lxe30021.am
+lxh40010.a
+lxh40011.a
+lxh40012.am
+lxh40020.a
+lxh40021.a
+lxh40022.am
+lxh40030.a
+lxh40031.a
+lxh40032.a
+lxh40033.am
+lxh40040.a
+lxh40041.a
+lxh40042.a
+lxh40043.am
+lxh40050.a
+lxh40051.a
+lxh40052.a
+lxh40053.am
+lxh40060.a
+lxh40061.a
+lxh40062.a
+lxh40063.am
+lxh40070.a
+lxh40071.a
+lxh40072.a
+lxh40073.am
+lxh40080.a
+lxh40081.a
+lxh40082.a
+lxh40083.a
+lxh40084.am
+lxh40090.a
+lxh40091.a
+lxh40092.a
+lxh40093.am
+lxh40100.a
+lxh40101.a
+lxh40102.a
+lxh40103.am
+lxh40110.a
+lxh40111.a
+lxh40112.am
+lxh40120.a
+lxh40121.a
+lxh40122.a
+lxh40123.am
+lxh40130.a
+lxh40131.a
+lxh40132.a
+lxh40133.am
+lxh40140.a
+lxh40141.a
+lxh40142.am
+macro.dfs
+macrosub.ada
+repbody.ada
+repspec.ada
+spprt13s.tst
+tctouch.ada
+testobj.txt
+tsttests.dat
+ug-apxa.doc
+ug-apxa.pdf
+ug-apxa.txt
+ug-apxb.doc
+ug-apxb.pdf
+ug-apxb.txt
+ug-apxc.doc
+ug-apxc.pdf
+ug-apxc.txt
+ug-apxd.doc
+ug-apxd.pdf
+ug-apxd.txt
+ug-body.doc
+ug-body.pdf
+ug-body.txt
+widechr.a
diff --git a/gcc/testsuite/ada/acats/support/fcndecl.ada b/gcc/testsuite/ada/acats/support/fcndecl.ada
index 53347a4..eddc137 100644
--- a/gcc/testsuite/ada/acats/support/fcndecl.ada
+++ b/gcc/testsuite/ada/acats/support/fcndecl.ada
@@ -3,22 +3,22 @@
-- Grant of Unlimited Rights
--
-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
-- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
-- to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--*
diff --git a/gcc/testsuite/ada/acats/support/impdef.a b/gcc/testsuite/ada/acats/support/impdef.a
index 9c23d0b..ca02a7a 100644
--- a/gcc/testsuite/ada/acats/support/impdef.a
+++ b/gcc/testsuite/ada/acats/support/impdef.a
@@ -105,6 +105,9 @@ package ImpDef is
Minimum_Task_Switch : constant Duration := 0.001;
-- ^^^ --- MODIFY HERE AS NEEDED
+ -- The above constant has been chosen for use with delay statements in the
+ -- GCC testsuite so that they do not take too long, but may be too small.
+
Long_Minimum_Task_Switch : constant Duration := 0.1;
--=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====--
@@ -119,6 +122,9 @@ package ImpDef is
Switch_To_New_Task : constant Duration := 0.001;
-- ^^^ -- MODIFY HERE AS NEEDED
+ -- The above constant has been chosen for use with delay statements in the
+ -- GCC testsuite so that they do not take too long, but may be too small.
+
Long_Switch_To_New_Task : constant Duration := 0.1;
--=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====--
@@ -208,7 +214,7 @@ package ImpDef is
-- CD30005_1_Foreign_Address : constant System.Address:=
-- System.Storage_Elements.To_Address ( 16#0000_0000# )
- -- --MODIFY HERE AS REQUIRED --- ^^^^^^^^^^^^^
+ -- MODIFY HERE AS REQUIRED --- ^^^^^^^^^^^^^
--=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====--
@@ -337,11 +343,14 @@ package ImpDef is
-- package Address_Value_IO is
-- new Ada.Text_IO.Integer_IO(System.Storage_Elements.Integer_Address);
- package Address_Value_IO is
- new Ada.Text_IO.Modular_IO(System.Storage_Elements.Integer_Address);
+ package Address_Value_IO is
+ new Ada.Text_IO.Modular_IO(System.Storage_Elements.Integer_Address);
--=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====--
+ -- The following constants have been defined for use with various delay
+ -- statements in the GCC testsuite so that they do not take too long.
+
One_Second : constant Duration := 0.001;
One_Long_Second : constant Duration := 0.1;
diff --git a/gcc/testsuite/ada/acats/support/impdefg.a b/gcc/testsuite/ada/acats/support/impdefg.a
index 459ba9c..6afc7cd 100644
--- a/gcc/testsuite/ada/acats/support/impdefg.a
+++ b/gcc/testsuite/ada/acats/support/impdefg.a
@@ -60,24 +60,31 @@ end ImpDef.Annex_G;
package body ImpDef.Annex_G is
+ -- NOTE: These are example bodies. It is expected that implementors
+ -- will write their own versions of these routines.
--=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====--
- -- This function must return a negative zero value for implementations
- -- for which Float'Signed_Zeros is True.
- -- We generate the smallest normalized negative number, and divide by a
- -- few powers of two to obtain a number whose absolute value equals zero
- -- but whose sign is negative.
+ -- This function must return a negative zero value for implementations
+ -- for which Float'Signed_Zeros is True.
+ --
+ -- The default body simply returns a negated literal 0.0. If the
+ -- default body does not return the value corresponding to a negatively
+ -- signed zero for the implementation under test, it must be replaced
+ -- by one which does. See RM A.5.3(13).
function Negative_Zero return Float is
- negz : float := -1.0 *
- float (float'Machine_Radix)
- ** ( Float'Machine_Emin - Float'Machine_Mantissa);
begin
- return negz / 8.0;
+ return -0.0; -- Note: If this value is not negative zero for the
+ -- implementation, use of this "default" value
+ -- could result in false failures in
+ -- implementations where Float'Signed_Zeros
+ -- is True.
+
+ -- ^^^^^^^^^^^^^^^^^^^^ MODIFY THIS BODY AS NEEDED ^^^^^^^^^^^^^^^^^^^^
+
end Negative_Zero;
--=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====-=====--
end ImpDef.Annex_G;
-
diff --git a/gcc/testsuite/ada/acats/support/macro.dfs b/gcc/testsuite/ada/acats/support/macro.dfs
index e3c5559..c0acaf1 100644
--- a/gcc/testsuite/ada/acats/support/macro.dfs
+++ b/gcc/testsuite/ada/acats/support/macro.dfs
@@ -244,7 +244,7 @@ MIN_INT ACATS4GNATMININT
-- IDENTIFIER SUCH AS NO_SUCH_TYPE_AVAILABLE.)
-- USED IN: C45231D CD7101G
NAME LONG_LONG_INTEGER
-
+
-- $OPTIONAL_DISC
-- A DISCRIMINANT USED AS THE DISCRIMINANT PART OF $RECORD_NAME.
-- IF MACHINE CODE INSERTIONS ARE NOT SUPPORTED THEN SUBSTITUTE
@@ -277,7 +277,7 @@ TASK_SIZE ACATS4GNATBIT
-- THE NUMBER OF STORAGE UNITS REQUIRED FOR A TASK ACTIVATION.
-- USED IN: BD2C01D BD2C02A BD2C03A C87B62D CD1009K CD1009T
-- CD1009U CD1C03E CD1C06A CD2C11A CC1225A CD2C11D
-TASK_STORAGE_SIZE 1024
+TASK_STORAGE_SIZE 32768
-- $VARIABLE_ADDRESS
-- AN EXPRESSION YIELDING A LEGAL ADDRESS FOR A VARIABLE FOR THIS
@@ -298,4 +298,3 @@ VARIABLE_ADDRESS1 VAR_ADDR1
-- THE MACROS $VARIABLE_ADDRESS AND $VARIABLE_ADDRESS1.
-- USED IN: SPPRT13SP
VARIABLE_ADDRESS2 VAR_ADDR2
-
diff --git a/gcc/testsuite/ada/acats/support/repbody.ada b/gcc/testsuite/ada/acats/support/repbody.ada
index dd5c53b..d7b9fe0 100644
--- a/gcc/testsuite/ada/acats/support/repbody.ada
+++ b/gcc/testsuite/ada/acats/support/repbody.ada
@@ -57,7 +57,8 @@
-- RLB 3/16/00 UPDATED ACATS VERSION STRING TO "2.3".
-- CHANGED VARIOUS STRINGS TO READ "ACATS".
-- RLB 3/22/01 UPDATED ACATS VERSION STRING TO "2.4".
--- RLB 3/29/01 UPDATED ACATS VERSION STRING TO "2.5".
+-- RLB 3/29/02 UPDATED ACATS VERSION STRING TO "2.5".
+-- RLB 3/06/07 UPDATED ACATS VERSION STRING TO "2.6".
WITH TEXT_IO, CALENDAR;
USE TEXT_IO, CALENDAR;
@@ -80,7 +81,7 @@ PACKAGE BODY REPORT IS
- ACATS_VERSION : CONSTANT STRING := "2.5";
+ ACATS_VERSION : CONSTANT STRING := "2.6";
-- VERSION OF ACATS BEING RUN (X.XX).
PROCEDURE PUT_MSG (MSG : STRING) IS
diff --git a/gcc/testsuite/ada/acats/support/tctouch.ada b/gcc/testsuite/ada/acats/support/tctouch.ada
index 8fd4f00..83f1254 100644
--- a/gcc/testsuite/ada/acats/support/tctouch.ada
+++ b/gcc/testsuite/ada/acats/support/tctouch.ada
@@ -93,11 +93,12 @@
-- 16 MAR 00 RLB Changed foundation id to reflect test suite version.
-- 22 MAR 01 RLB Changed foundation id to reflect test suite version.
-- 29 MAR 02 RLB Changed foundation id to reflect test suite version.
+-- 06 MAR 07 RLB Changed foundation id to reflect test suite version.
--
--!
package TCTouch is
- Foundation_ID : constant String := "TCTouch ACATS 2.5";
+ Foundation_ID : constant String := "TCTouch ACATS 2.6";
Max_Touch_Count : constant := 80;
procedure Assert ( SB_True : Boolean; Message : String );
diff --git a/gcc/testsuite/ada/acats/tests/c3/c352001.a b/gcc/testsuite/ada/acats/tests/c3/c352001.a
new file mode 100644
index 0000000..04b094f
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/c3/c352001.a
@@ -0,0 +1,270 @@
+--
+-- C352001.A
+--
+-- Grant of Unlimited Rights
+--
+-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- unlimited rights in the software and documentation contained herein.
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
+-- to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+--
+-- OBJECTIVE:
+-- Check that the predefined Character type comprises 256 positions.
+-- Check that the names of the non-graphic characters are usable with
+-- the attributes (Wide_)Image and (Wide_)Value, and that these
+-- attributes produce the correct result.
+--
+-- TEST DESCRIPTION:
+-- Build two tables of nongraphic characters from positions of Row 00
+-- (0000-001F and 007F-009F) of the ISO 10646 Basic Multilingual Plane.
+-- Fill the first table with compiler created strings. Fill the second
+-- table with strings defined by the language. Compare the two tables.
+-- Check 256 positions of the predefined character type. Use attributes
+-- (Wide_)Image and (Wide_)Value to check the values of the non-graphic
+-- characters and the last 2 characters.
+--
+--
+-- CHANGE HISTORY:
+-- 20 Jun 95 SAIC Initial prerelease version.
+-- 27 Jan 96 SAIC Revised for 2.1. Hid values, added "del" case.
+--
+--!
+
+with Ada.Characters.Handling;
+with Report;
+procedure C352001 is
+
+ Lower_Bound : Integer := 0;
+ Middle_Bound : Integer := 31;
+ Upper_Bound : Integer := 159;
+ Half_Bound : Integer := 127;
+ Max_Bound : Integer := 255;
+
+ type Dyn_String is access String;
+ type Value_Result is array (Character) of Dyn_String;
+
+ Table_Of_Character : Value_Result;
+ TC_Table : Value_Result;
+
+ function CVII(K : Natural) return Character is
+ begin
+ return Character'Val( Report.Ident_Int(K) );
+ end CVII;
+
+ function "=" (L, R : String) return Boolean is
+ UCL : String (L'First .. L'Last);
+ UCR : String (R'First .. R'last);
+ begin
+ UCL := Ada.Characters.Handling.To_Upper (L);
+ UCR := Ada.Characters.Handling.To_Upper (R);
+ if UCL'Last /= UCR'Last then
+ return False;
+ else
+ for I in UCL'First .. UCR'Last loop
+ if UCL (I) /= UCR (I) then
+ return False;
+ end if;
+ end loop;
+ return True;
+ end if;
+ end "=";
+
+begin
+
+ Report.Test ("C352001", "Check that, the predefined Character type " &
+ "comprises 256 positions. Check that the names of the " &
+ "non-graphic characters are usable with the attributes " &
+ "(Wide_)Image and (Wide_)Value, and that these attributes " &
+ "produce the correct result");
+
+ -- Fill table with strings (positions of Row 00 (0000-001F) of the ISO
+ -- 10646 Basic Multilingual Plane created by the compiler.
+
+ for I in CVII(Lower_Bound) .. CVII(Middle_Bound) loop
+ Table_Of_Character (I) := new String'(Character'Image(I));
+ end loop;
+
+ -- Fill table with strings (positions of Row 00 (007F-009F) of the ISO
+ -- 10646 Basic Multilingual Plane created by the compiler.
+
+ for I in CVII(Half_Bound) .. CVII(Upper_Bound) loop
+ Table_Of_Character (I) := new String'(Character'Image(I));
+ end loop;
+
+ -- Fill table with strings (positions of Row 00 (0000-001F) of the ISO
+ -- 10646 Basic Multilingual Plane defined by the language.
+
+ TC_Table (CVII(0)) := new String'("nul");
+ TC_Table (CVII(1)) := new String'("soh");
+ TC_Table (CVII(2)) := new String'("stx");
+ TC_Table (CVII(3)) := new String'("etx");
+ TC_Table (CVII(4)) := new String'("eot");
+ TC_Table (CVII(5)) := new String'("enq");
+ TC_Table (CVII(6)) := new String'("ack");
+ TC_Table (CVII(7)) := new String'("bel");
+ TC_Table (CVII(8)) := new String'("bs");
+ TC_Table (CVII(9)) := new String'("ht");
+ TC_Table (CVII(10)) := new String'("lf");
+ TC_Table (CVII(11)) := new String'("vt");
+ TC_Table (CVII(12)) := new String'("ff");
+ TC_Table (CVII(13)) := new String'("cr");
+ TC_Table (CVII(14)) := new String'("so");
+ TC_Table (CVII(15)) := new String'("si");
+ TC_Table (CVII(16)) := new String'("dle");
+ TC_Table (CVII(17)) := new String'("dc1");
+ TC_Table (CVII(18)) := new String'("dc2");
+ TC_Table (CVII(19)) := new String'("dc3");
+ TC_Table (CVII(20)) := new String'("dc4");
+ TC_Table (CVII(21)) := new String'("nak");
+ TC_Table (CVII(22)) := new String'("syn");
+ TC_Table (CVII(23)) := new String'("etb");
+ TC_Table (CVII(24)) := new String'("can");
+ TC_Table (CVII(25)) := new String'("em");
+ TC_Table (CVII(26)) := new String'("sub");
+ TC_Table (CVII(27)) := new String'("esc");
+ TC_Table (CVII(28)) := new String'("fs");
+ TC_Table (CVII(29)) := new String'("gs");
+ TC_Table (CVII(30)) := new String'("rs");
+ TC_Table (CVII(31)) := new String'("us");
+ TC_Table (CVII(127)) := new String'("del");
+
+ -- Fill table with strings (positions of Row 00 (007F-009F) of the ISO
+ -- 10646 Basic Multilingual Plane defined by the language.
+
+ TC_Table (CVII(128)) := new String'("reserved_128");
+ TC_Table (CVII(129)) := new String'("reserved_129");
+ TC_Table (CVII(130)) := new String'("bph");
+ TC_Table (CVII(131)) := new String'("nbh");
+ TC_Table (CVII(132)) := new String'("reserved_132");
+ TC_Table (CVII(133)) := new String'("nel");
+ TC_Table (CVII(134)) := new String'("ssa");
+ TC_Table (CVII(135)) := new String'("esa");
+ TC_Table (CVII(136)) := new String'("hts");
+ TC_Table (CVII(137)) := new String'("htj");
+ TC_Table (CVII(138)) := new String'("vts");
+ TC_Table (CVII(139)) := new String'("pld");
+ TC_Table (CVII(140)) := new String'("plu");
+ TC_Table (CVII(141)) := new String'("ri");
+ TC_Table (CVII(142)) := new String'("ss2");
+ TC_Table (CVII(143)) := new String'("ss3");
+ TC_Table (CVII(144)) := new String'("dcs");
+ TC_Table (CVII(145)) := new String'("pu1");
+ TC_Table (CVII(146)) := new String'("pu2");
+ TC_Table (CVII(147)) := new String'("sts");
+ TC_Table (CVII(148)) := new String'("cch");
+ TC_Table (CVII(149)) := new String'("mw");
+ TC_Table (CVII(150)) := new String'("spa");
+ TC_Table (CVII(151)) := new String'("epa");
+ TC_Table (CVII(152)) := new String'("sos");
+ TC_Table (CVII(153)) := new String'("reserved_153");
+ TC_Table (CVII(154)) := new String'("sci");
+ TC_Table (CVII(155)) := new String'("csi");
+ TC_Table (CVII(156)) := new String'("st");
+ TC_Table (CVII(157)) := new String'("osc");
+ TC_Table (CVII(158)) := new String'("pm");
+ TC_Table (CVII(159)) := new String'("apc");
+
+
+ -- Compare the first half of two tables.
+ for I in CVII(Lower_Bound) .. CVII(Middle_Bound) loop
+ if TC_Table(I).all /= Table_Of_Character(I).all then
+ Report.Failed("Value of character#" & Integer'Image(Character'Pos(I)) &
+ " is not the same in the first half of the table");
+ end if;
+ end loop;
+
+
+ -- Compare the second half of two tables.
+ for I in CVII(Half_Bound) .. CVII(Upper_Bound) loop
+ if TC_Table(I).all /= Table_Of_Character(I).all then
+ Report.Failed("Value of character#" & Integer'Image(Character'Pos(I)) &
+ " is not the same in the second half of the table");
+ end if;
+ end loop;
+
+
+ -- Check the first character.
+ if Character'Image( Character'First ) /= "NUL" then
+ Report.Failed("Value of character#" &
+ Integer'Image(Character'Pos (Character'First)) &
+ " is not NUL");
+ end if;
+
+
+ -- Check that the names of the non-graphic characters are usable with
+ -- Image and Value attributes.
+ if Character'Value( Character'Image( CVII(153) )) /=
+ CVII( 153 ) then
+ Report.Failed ("Value of character#" &
+ Integer'Image( Character'Pos(CVII(153)) ) &
+ " is not reserved_153");
+ end if;
+
+
+ for I in CVII(Lower_Bound) .. CVII(Max_Bound) loop
+ if Character'Value(
+ Report.Ident_Str(
+ Character'Image(CVII(Character'Pos(I)))))
+ /= CVII( Character'Pos(I)) then
+ Report.Failed ("Value of character#" &
+ Integer'Image( Character'Pos(I) ) &
+ " is not the same as the predefined character type");
+ end if;
+ end loop;
+
+
+ -- Check Wide_Character attributes.
+ for I in Wide_Character'Val(Lower_Bound) .. Wide_Character'Val(Max_Bound)
+ loop
+ if Wide_Character'Wide_Value(
+ Report.Ident_Wide_Str(
+ Wide_Character'Wide_Image(
+ Wide_Character'Val(Wide_Character'Pos(I)))))
+ /= Wide_Character'Val(Wide_Character'Pos(I))
+ then
+ Report.Failed ("Value of the predefined Wide_Character type " &
+ "is not correct");
+ end if;
+ end loop;
+
+
+ if Wide_Character'Value( Wide_Character'Image(Wide_Character'Val(132)) )
+ /= Wide_Character'Val( Report.Ident_Int(132) ) then
+ Report.Failed ("Wide_Character at 132 is not reserved_132");
+ end if;
+
+
+ if Wide_Character'Image( Wide_Character'First ) /= "NUL" then
+ Report.Failed ("Wide_Character'First is not NUL");
+ end if;
+
+
+ if Wide_Character'Image
+ (Wide_Character'Pred (Wide_Character'Last) ) /= "FFFE" then
+ Report.Failed ("Wide_Character at 65534 is not FFFE");
+ end if;
+
+
+ if Wide_Character'Image(Wide_Character'Last) /= "FFFF" then
+ Report.Failed ("Wide_Character'Last is not FFFF");
+ end if;
+
+ Report.Result;
+
+end C352001;
diff --git a/gcc/testsuite/ada/acats/tests/c4/c433001.a b/gcc/testsuite/ada/acats/tests/c4/c433001.a
index 613b688..305e010 100644
--- a/gcc/testsuite/ada/acats/tests/c4/c433001.a
+++ b/gcc/testsuite/ada/acats/tests/c4/c433001.a
@@ -36,6 +36,7 @@
--
-- HISTORY:
-- 16 DEC 1999 RLB Initial Version.
+-- 20 JAN 2009 RLB Corrected error messages.
with Report;
procedure C433001 is
@@ -82,10 +83,10 @@ procedure C433001 is
Report.Failed ("First Component incorrect (" & Test_Case & ")");
end if;
if Obj(Low+1) /= Second_Component then
- Report.Failed ("First Component incorrect (" & Test_Case & ")");
+ Report.Failed ("Second Component incorrect (" & Test_Case & ")");
end if;
if Obj(High) /= Last_Component then
- Report.Failed ("First Component incorrect (" & Test_Case & ")");
+ Report.Failed ("Last Component incorrect (" & Test_Case & ")");
end if;
end Check_1;
@@ -104,10 +105,10 @@ procedure C433001 is
Report.Failed ("First Component incorrect (" & Test_Case & ")");
end if;
if Obj(Color_Type'Succ(Low)) /= Second_Component then
- Report.Failed ("First Component incorrect (" & Test_Case & ")");
+ Report.Failed ("Second Component incorrect (" & Test_Case & ")");
end if;
if Obj(High) /= Last_Component then
- Report.Failed ("First Component incorrect (" & Test_Case & ")");
+ Report.Failed ("Last Component incorrect (" & Test_Case & ")");
end if;
end Check_2;
diff --git a/gcc/testsuite/ada/acats/tests/c4/c453001.a b/gcc/testsuite/ada/acats/tests/c4/c453001.a
new file mode 100644
index 0000000..53f4584
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/c4/c453001.a
@@ -0,0 +1,236 @@
+-- C453001.A
+--
+-- Grant of Unlimited Rights
+--
+-- The Ada Conformity Assessment Authority (ACAA) holds unlimited
+-- rights in the software and documentation contained herein. Unlimited
+-- rights are the same as those granted by the U.S. Government for older
+-- parts of the Ada Conformity Assessment Test Suite, and are defined
+-- in DFAR 252.227-7013(a)(19). By making this public release, the ACAA
+-- intends to confer upon all recipients unlimited rights equal to those
+-- held by the ACAA. These rights include rights to use, duplicate,
+-- release or disclose the released technical data and computer software
+-- in whole or in part, in any manner and for any purpose whatsoever, and
+-- to have or permit others to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE ACAA MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--
+-- Notice
+--
+-- The ACAA has created and maintains the Ada Conformity Assessment Test
+-- Suite for the purpose of conformity assessments conducted in accordance
+-- with the International Standard ISO/IEC 18009 - Ada: Conformity
+-- assessment of a language processor. This test suite should not be used
+-- to make claims of conformance unless used in accordance with
+-- ISO/IEC 18009 and any applicable ACAA procedures.
+--*
+-- OBJECTIVES:
+-- Check that overflow checking is not performed for adding operators of
+-- modular types.
+--
+-- TEST DESCRIPTION:
+-- Check that Constraint_Error is not raised by + or - when the result
+-- is out of the range of the base type.
+-- Also check that assignment to values in the upper half of the range
+-- does not raise Constraint_Error.
+--
+-- We define modular types of various common sizes. We cannot
+-- assume a binary modulus greater than 2**16 is supported by 3.5.4(23),
+-- so the DWord type might be smaller on some targets. We also try
+-- a small prime number as a modulus (these are often used for hashing).
+-- We also the language-defined types
+-- System.Storage_Elements.Storage_Element, Ada.Streams.Stream_Element,
+-- and Ada.Containers.Hash_Type.
+--
+-- CHANGE HISTORY:
+-- 11 Feb 17 JAC Initial pre-release version.
+-- 30 Mar 17 RLB Renamed, removed non-modular test cases, removed
+-- types that aren't required to be supported, added
+-- other language-defined types, added key to locate
+-- failures, added additional test cases.
+-- 03 Apr 17 RLB Removed Ada.Containers from the Ada 95 version of
+-- this test.
+--
+--!
+with Report;
+with System.Storage_Elements;
+with Ada.Streams;
+
+procedure C453001 is
+ type Unsigned_Byte_Type is mod 16#100#; -- 256;
+
+ type Unsigned_Word_Type is mod 16#1_0000#; -- 65536;
+
+ type Unsigned_DWord_Type is mod
+ Natural'Min (2**32, System.Max_Binary_Modulus);
+
+ type Unsigned_NBM_Type is mod System.Max_Nonbinary_Modulus;
+
+ type Biggest_Unsigned_Type is mod System.Max_Binary_Modulus;
+
+ type Prime_Type is mod 23; -- Prime number for hashing.
+
+ generic
+ type Mod_Type is mod <>; -- Assume this is a base type.
+ Key : in String;
+ procedure Test_Operators;
+
+ procedure Test_Operators is
+
+ function Ident_Mod (Val : in Mod_Type) return Mod_Type is
+ -- Optimization breaker.
+ begin
+ if Report.Equal (4, 12) then -- Always False (but complex).
+ return 1;
+ else
+ return Val;
+ end if;
+ end Ident_Mod;
+
+ begin
+ if Mod_Type'First /= 0 then -- The First of a base type is always 0.
+ Report.Failed ("Not base type first - " & Key);
+ end if;
+ if Mod_Type'Last /= Mod_Type'Base'Last then
+ Report.Failed ("Not base type last - " & Key);
+ end if;
+
+ -- Note: Mod_Type'First always is 0.
+
+ -- Check addition
+ declare
+ M : constant Mod_Type := Mod_Type'Last;
+ V : Mod_Type;
+ begin
+ V := M + 1; -- Should wrap around
+ if Ident_Mod (V) /= 0 then
+ Report.Failed ("Addition didn't wrap round - " & Key);
+ end if;
+ V := Ident_Mod (M - 2) + 5; -- Should wrap around
+ if Ident_Mod (V) /= 2 then
+ Report.Failed ("Addition didn't wrap round again - " & Key);
+ end if;
+ exception
+ when Constraint_Error =>
+ Report.Failed ("Constraint_Error raised for addition - " & Key);
+ when others =>
+ Report.Failed
+ ("Some even more unexpected exception raised for addition - " &
+ Key);
+ end;
+
+ -- Check subtraction
+ declare
+ M : constant Mod_Type := 0;
+ V : Mod_Type;
+ begin
+ V := M - 1; -- Should wrap around
+ if Ident_Mod (V) /= Mod_Type'Last then
+ Report.Failed ("Subtraction didn't wrap round - " & Key);
+ end if;
+ V := Ident_Mod (3) - 7; -- Should wrap around
+ if Ident_Mod (V) /= Mod_Type'Last-3 then
+ Report.Failed ("Subtraction didn't wrap round again - " & Key);
+ end if;
+ exception
+ when Constraint_Error =>
+ Report.Failed ("Constraint_Error raised for subtraction - " & Key);
+ when others =>
+ Report.Failed
+ ("Some even more unexpected exception raised for subtraction - " &
+ Key);
+ end;
+
+ end Test_Operators;
+
+ procedure Test_Unsigned_Byte_Operators is new Test_Operators
+ (Unsigned_Byte_Type, "Byte");
+
+ procedure Test_Unsigned_Word_Operators is new Test_Operators
+ (Unsigned_Word_Type, "Word");
+
+ procedure Test_Unsigned_DWord_Operators is new Test_Operators
+ (Unsigned_DWord_Type, "DWord");
+
+ procedure Test_Unsigned_NBM_Operators is new Test_Operators
+ (Unsigned_NBM_Type, "NBM");
+
+ procedure Test_Biggest_Unsigned_Operators is new Test_Operators
+ (Biggest_Unsigned_Type, "Big");
+
+ procedure Test_Prime_Operators is new Test_Operators (Prime_Type, "Prime");
+
+ procedure Test_Storage_Element_Operators is new Test_Operators
+ (System.Storage_Elements.Storage_Element, "Storage");
+
+ procedure Test_Stream_Element_Operators is new Test_Operators
+ (Ada.Streams.Stream_Element, "Stream");
+
+begin
+
+ Report.Test
+ ("C453001",
+ "Check that overflow checking is not performed for adding operators " &
+ "of modular types");
+
+ -- Check assignment
+ declare
+ -- Define subtypes
+ subtype My_Unsigned_Byte_Type is Unsigned_Byte_Type;
+ subtype My_Unsigned_Word_Type is Unsigned_Word_Type;
+ subtype My_Unsigned_DWord_Type is Unsigned_DWord_Type;
+
+ -- Define constants in upper half of range
+ C1 : constant Unsigned_Byte_Type := Unsigned_Byte_Type'Last;
+ C2 : constant My_Unsigned_Byte_Type := 16#FE#;
+ C3 : constant Unsigned_Word_Type := 16#FACE#;
+ C4 : constant My_Unsigned_Word_Type := My_Unsigned_Word_Type'Last;
+ C5 : constant Unsigned_DWord_Type := My_Unsigned_DWord_Type'Last;
+
+ -- Define variables
+ V1 : Unsigned_Byte_Type;
+ V2 : My_Unsigned_Byte_Type;
+ V3 : Unsigned_Word_Type;
+ V4 : My_Unsigned_Word_Type;
+ V5 : Unsigned_DWord_Type;
+ begin
+ V1 := C1;
+ V1 := C2;
+ V2 := C1;
+ V2 := C2;
+ V3 := C3;
+ V3 := C4;
+ V4 := C3;
+ V4 := C4;
+ V5 := C5;
+ if V1 /= C2 or V2 /= C2 or V3 /= C4 or V4 /= C4 or V5 /= C5 then
+ Report.Comment ("Don't optimize assignment!"); -- Optimization breaker
+ end if;
+ exception
+ when Constraint_Error =>
+ Report.Failed ("Constraint_Error raised for assignment");
+ when others =>
+ Report.Failed ("Some even more unexpected exception raised " &
+ "for assignment");
+ end;
+
+ Test_Unsigned_Byte_Operators;
+ Test_Unsigned_Word_Operators;
+ Test_Unsigned_DWord_Operators;
+ Test_Unsigned_NBM_Operators;
+ Test_Biggest_Unsigned_Operators;
+ Test_Prime_Operators;
+ Test_Storage_Element_Operators;
+ Test_Stream_Element_Operators;
+
+ Report.Result;
+
+end C453001;
+
diff --git a/gcc/testsuite/ada/acats/tests/c4/c45622a.ada b/gcc/testsuite/ada/acats/tests/c4/c45622a.ada
deleted file mode 100644
index 42f0204..0000000
--- a/gcc/testsuite/ada/acats/tests/c4/c45622a.ada
+++ /dev/null
@@ -1,83 +0,0 @@
--- C45622A.ADA
-
--- Grant of Unlimited Rights
---
--- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
--- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
--- to do so.
---
--- DISCLAIMER
---
--- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
--- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
--- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--- PARTICULAR PURPOSE OF SAID MATERIAL.
---*
--- OBJECTIVE:
--- FOR EXPONENTIATION OF FLOATING POINT TYPES, CHECK THAT
--- CONSTRAINT_ERROR IS RAISED IF
--- MACHINE_OVERFLOWS IS TRUE AND THE RESULT IS OUTSIDE THE RANGE OF
--- THE BASE TYPE. THIS TESTS DIGITS 5.
-
--- *** NOTE: This test has been modified since ACVC version 1.11 to -- 9X
--- *** remove incompatibilities associated with the transition -- 9X
--- *** to Ada 9X. -- 9X
--- *** -- 9X
-
--- HISTORY:
--- BCB 02/09/88 CREATED ORIGINAL TEST.
--- MRM 03/30/93 REMOVED NUMERIC_ERROR FOR 9X COMPATIBILITY
-
-WITH REPORT; USE REPORT;
-
-PROCEDURE C45622A IS
-
- TYPE FLT IS DIGITS 5;
-
- F : FLT;
-
- FUNCTION EQUAL_FLT (ONE, TWO : FLT) RETURN BOOLEAN IS
- BEGIN
- RETURN ONE = TWO * FLT (IDENT_INT(1));
- END EQUAL_FLT;
-
-BEGIN
- TEST ("C45622A", "FOR EXPONENTIATION OF FLOATING POINT TYPES, " &
- "CHECK THAT CONSTRAINT_ERROR " &
- "IS RAISED IF MACHINE_OVERFLOWS IS TRUE AND " &
- "THE RESULT IS OUTSIDE THE RANGE OF THE BASE " &
- "TYPE. THIS TESTS DIGITS 5");
-
- IF FLT'MACHINE_OVERFLOWS THEN
- BEGIN
- F := (FLT'BASE'LAST)**IDENT_INT (2);
- FAILED ("CONSTRAINT_ERROR WAS NOT RAISED FOR " &
- "EXPONENTIATION");
-
- IF NOT EQUAL_FLT(F,F) THEN
- COMMENT ("DON'T OPTIMIZE F");
- END IF;
- EXCEPTION
- WHEN CONSTRAINT_ERROR =>
- COMMENT ("CONSTRAINT_ERROR WAS RAISED FOR " &
- "EXPONENTIATION");
- WHEN OTHERS =>
- FAILED ("AN EXCEPTION OTHER THAN CONSTRAINT_ERROR " &
- "WAS RAISED FOR EXPONENTIATION");
- END;
- ELSE
- NOT_APPLICABLE ("THIS TEST IS NOT APPLICABLE DUE TO " &
- "MACHINE_OVERFLOWS BEING FALSE");
- END IF;
-
- RESULT;
-END C45622A;
diff --git a/gcc/testsuite/ada/acats/tests/c4/c45624a.ada b/gcc/testsuite/ada/acats/tests/c4/c45624a.ada
deleted file mode 100644
index 32ba4c0..0000000
--- a/gcc/testsuite/ada/acats/tests/c4/c45624a.ada
+++ /dev/null
@@ -1,86 +0,0 @@
--- C45624A.ADA
-
--- Grant of Unlimited Rights
---
--- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
--- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
--- to do so.
---
--- DISCLAIMER
---
--- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
--- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
--- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--- PARTICULAR PURPOSE OF SAID MATERIAL.
---*
--- OBJECTIVE:
--- FOR FLOATING POINT TYPES, CHECK THAT CONSTRAINT_ERROR
--- IS RAISED IF THE RESULT OF A FLOATING POINT
--- EXPONENTIATION IS OUTSIDE THE RANGE OF THE BASE TYPE AND
--- MACHINE_OVERFLOWS IS FALSE. THIS TESTS DIGITS 5.
-
--- *** NOTE: This test has been modified since ACVC version 1.11 to -- 9X
--- *** remove incompatibilities associated with the transition -- 9X
--- *** to Ada 9X. -- 9X
--- *** -- 9X
-
--- HISTORY:
--- BCB 02/09/88 CREATED ORIGINAL TEST.
--- MRM 03/30/93 REMOVED NUMERIC_ERROR FOR 9X COMPATIBILITY
-
-WITH REPORT; USE REPORT;
-
-PROCEDURE C45624A IS
-
- TYPE FLT IS DIGITS 5;
-
- F : FLT;
-
- FUNCTION EQUAL_FLT (ONE, TWO : FLT) RETURN BOOLEAN IS
- BEGIN
- IF EQUAL(3,3) THEN
- RETURN ONE = TWO;
- ELSE
- RETURN ONE /= TWO;
- END IF;
- END EQUAL_FLT;
-
-BEGIN
- TEST ("C45624A", "FOR FLOATING POINT TYPES, CHECK THAT " &
- "CONSTRAINT_ERROR IS RAISED " &
- "IF MACHINE_OVERFLOWS IS FALSE. THIS TESTS " &
- "DIGITS 5");
-
- IF FLT'MACHINE_OVERFLOWS THEN
- NOT_APPLICABLE ("THIS TEST IS NOT APPLICABLE DUE TO " &
- "MACHINE_OVERFLOWS BEING TRUE");
- ELSE
- BEGIN
- F := FLT'BASE'FIRST**IDENT_INT (2);
- COMMENT ("CONSTRAINT_ERROR WAS NOT RAISED WHEN " &
- "MACHINE_OVERFLOWS WAS FALSE");
-
- IF EQUAL_FLT(F,F**IDENT_INT(1)) THEN
- COMMENT ("DON'T OPTIMIZE F");
- END IF;
- EXCEPTION
- WHEN CONSTRAINT_ERROR =>
- COMMENT ("CONSTRAINT_ERROR WAS RAISED WHEN " &
- "MACHINE_OVERFLOWS WAS FALSE");
- WHEN OTHERS =>
- FAILED ("AN EXCEPTION OTHER THAN CONSTRAINT_ERROR " &
- "WAS RAISED");
- END;
- END IF;
-
- RESULT;
-END C45624A;
diff --git a/gcc/testsuite/ada/acats/tests/c4/c45624b.ada b/gcc/testsuite/ada/acats/tests/c4/c45624b.ada
deleted file mode 100644
index c7bd592..0000000
--- a/gcc/testsuite/ada/acats/tests/c4/c45624b.ada
+++ /dev/null
@@ -1,81 +0,0 @@
--- C45624B.ADA
-
--- Grant of Unlimited Rights
---
--- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
--- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
--- to do so.
---
--- DISCLAIMER
---
--- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
--- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
--- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--- PARTICULAR PURPOSE OF SAID MATERIAL.
---*
--- OBJECTIVE:
--- FOR FLOATING POINT TYPES, CHECK THAT
--- CONSTRAINT_ERROR IS RAISED IF THE RESULT OF A FLOATING POINT
--- EXPONENTIATION IS OUTSIDE THE RANGE OF THE BASE TYPE AND
--- MACHINE_OVERFLOWS IS FALSE. THIS TESTS DIGITS 6.
-
--- *** NOTE: This test has been modified since ACVC version 1.11 to -- 9X
--- *** remove incompatibilities associated with the transition -- 9X
--- *** to Ada 9X. -- 9X
--- *** -- 9X
-
--- HISTORY:
--- BCB 07/14/88 CREATED ORIGINAL TEST.
--- MRM 03/30/93 REMOVED NUMERIC_ERROR FOR 9X COMPATIBILITY
-
-WITH REPORT; USE REPORT;
-
-PROCEDURE C45624B IS
-
- TYPE FLT IS DIGITS 6;
-
- F : FLT;
-
- FUNCTION EQUAL_FLT (ONE, TWO : FLT) RETURN BOOLEAN IS
- BEGIN
- RETURN ONE = TWO * FLT (IDENT_INT(1));
- END EQUAL_FLT;
-
-BEGIN
- TEST ("C45624B", "FOR FLOATING POINT TYPES, CHECK THAT " &
- "CONSTRAINT_ERROR IS RAISED " &
- "IF MACHINE_OVERFLOWS IS FALSE. THIS TESTS " &
- "DIGITS 6");
-
- IF FLT'MACHINE_OVERFLOWS THEN
- NOT_APPLICABLE ("THIS TEST IS NOT APPLICABLE DUE TO " &
- "MACHINE_OVERFLOWS BEING TRUE");
- ELSE
- BEGIN
- F := FLT'BASE'LAST**IDENT_INT (2);
- COMMENT ("CONSTRAINT_ERROR WAS NOT RAISED WHEN " &
- "MACHINE_OVERFLOWS WAS FALSE");
- IF NOT EQUAL_FLT(F,F**IDENT_INT(1)) THEN
- COMMENT ("DON'T OPTIMIZE F");
- END IF;
- EXCEPTION
- WHEN CONSTRAINT_ERROR =>
- COMMENT ("CONSTRAINT_ERROR WAS RAISED WHEN " &
- "MACHINE_OVERFLOWS WAS FALSE");
- WHEN OTHERS =>
- FAILED ("AN EXCEPTION OTHER THAN CONSTRAINT_ERROR " &
- "WAS RAISED");
- END;
- END IF;
-
- RESULT;
-END C45624B;
diff --git a/gcc/testsuite/ada/acats/tests/c4/c460013.a b/gcc/testsuite/ada/acats/tests/c4/c460013.a
new file mode 100644
index 0000000..7644f88
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/c4/c460013.a
@@ -0,0 +1,188 @@
+-- C460013.A
+--
+-- Grant of Unlimited Rights
+--
+-- The Ada Conformity Assessment Authority (ACAA) holds unlimited
+-- rights in the software and documentation contained herein. Unlimited
+-- rights are the same as those granted by the U.S. Government for older
+-- parts of the Ada Conformity Assessment Test Suite, and are defined
+-- in DFAR 252.227-7013(a)(19). By making this public release, the ACAA
+-- intends to confer upon all recipients unlimited rights equal to those
+-- held by the ACAA. These rights include rights to use, duplicate,
+-- release or disclose the released technical data and computer software
+-- in whole or in part, in any manner and for any purpose whatsoever, and
+-- to have or permit others to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+--
+-- OBJECTIVE:
+-- Check that if the target subtype excludes null, the value is not
+-- null. Check access parameters, which null-excluding if:
+-- (1) not null is given in their definition;
+-- (2) the access parameter is controlling;
+-- (3) an Ada 95 compiler is in use.
+--
+-- Note that the not null syntax is required even for Ada 95 compilers
+-- (see AI95-00447).
+--
+-- CHANGE HISTORY:
+-- 18 DEC 2006 RLB Initial version.
+-- 05 JAN 2007 RLB Corrected syntax error.
+--
+--!
+with Ada.Exceptions;
+use Ada.Exceptions;
+with Report;
+use Report;
+procedure C460013 is
+
+
+ package Nest1 is
+ type Doggie is tagged record
+ Cnt : Natural;
+ end record;
+ type Doggie_Access is access all Doggie;
+
+ procedure Controlled (P : access Doggie); -- Always null-excluding.
+ end Nest1;
+
+ package Nest2 is
+ type Kitty is record
+ Cnt : Natural;
+ end record;
+ type Kitty_Access is access all Kitty;
+
+ procedure Include (P : access Kitty); -- Null-excluding only in Ada 95.
+ procedure Exclude (P : not null access Kitty); -- Always null-excluding.
+ end Nest2;
+
+
+ package body Nest1 is
+ procedure Controlled (P : access Doggie) is
+ begin
+ if P.Cnt /= Ident_Int(4) then
+ Failed ("Bad value in null-excluding controlling parameter");
+ -- else OK
+ end if;
+ exception
+ when Constraint_Error => -- Dereference of null
+ Failed ("Null allowed in null-excluding controlling parameter");
+ end Controlled;
+ end Nest1;
+
+ package body Nest2 is
+ procedure Include (P : access Kitty) is
+ begin
+ if P.Cnt /= Ident_Int(31) then
+ Failed ("Bad value in access parameter");
+ -- else OK
+ end if;
+ exception
+ when Constraint_Error => -- Dereference of null
+ null;
+ --Comment ("Null allowed in access parameter - Ada 2005 semantics");
+ end Include;
+
+ procedure Exclude (P : not null access Kitty) is
+ begin
+ if P.Cnt /= Ident_Int(80) then
+ Failed ("Bad value in explicit null-excluding parameter");
+ -- else OK
+ end if;
+ exception
+ when Constraint_Error => -- Dereference of null
+ Failed ("Null allowed in explicit null-excluding parameter");
+ end Exclude;
+ end Nest2;
+
+ Shep : aliased Nest1.Doggie := (Cnt => 4);
+ Frisky : aliased Nest2.Kitty := (Cnt => 80);
+ Snuggles : aliased Nest2.Kitty := (Cnt => 31);
+
+begin
+ Test ("C460013",
+ "Check that if the target subtype excludes null, the value is not" &
+ " null - access parameter cases");
+
+ declare
+ Ptr : Nest1.Doggie_Access := Shep'Access;
+ begin
+ begin
+ Nest1.Controlled (Ptr); -- OK.
+ exception
+ when A: others =>
+ Failed ("Unexpected exception " & Exception_Name (A) &
+ " raised (1A) - " & Exception_Message (A));
+ end;
+ Ptr := null;
+ begin
+ Nest1.Controlled (Ptr);
+ Failed ("Null allowed for null-excluding controlling access parameter (1)");
+ exception
+ when Constraint_Error =>
+ null;
+ when B: others =>
+ Failed ("Unexpected exception " & Exception_Name (B) &
+ " raised (1B) - " & Exception_Message (B));
+ end;
+ end;
+
+ declare
+ Ptr : Nest2.Kitty_Access := Frisky'Access;
+ begin
+ begin
+ Nest2.Exclude (Ptr); -- OK.
+ exception
+ when C: others =>
+ Failed ("Unexpected exception " & Exception_Name (C) &
+ " raised (2A) - " & Exception_Message (C));
+ end;
+ Ptr := null;
+ begin
+ Nest2.Exclude (Ptr);
+ Failed ("Null allowed for null-excluding access parameter (2)");
+ exception
+ when Constraint_Error =>
+ null;
+ when D: others =>
+ Failed ("Unexpected exception " & Exception_Name (D) &
+ " raised (2B) - " & Exception_Message (D));
+ end;
+ end;
+
+ declare
+ Ptr : Nest2.Kitty_Access := Snuggles'Access;
+ begin
+ begin
+ Nest2.Include (Ptr); -- OK.
+ exception
+ when E: others =>
+ Failed ("Unexpected exception " & Exception_Name (E) &
+ " raised (3A) - " & Exception_Message (E));
+ end;
+ Ptr := null;
+ begin
+ Nest2.Include (Ptr);
+ Comment ("Null allowed for normal access parameter - " &
+ "Ada 2005 semantics");
+ exception
+ when Constraint_Error =>
+ Comment ("Null not allowed for normal access parameter - " &
+ "Ada 95 semantics");
+ when F: others =>
+ Failed ("Unexpected exception " & Exception_Name (F) &
+ " raised (3B) - " & Exception_Message (F));
+ end;
+ end;
+
+ Result;
+end C460013;
+
diff --git a/gcc/testsuite/ada/acats/tests/c4/c460014.a b/gcc/testsuite/ada/acats/tests/c4/c460014.a
new file mode 100644
index 0000000..59a95d9
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/c4/c460014.a
@@ -0,0 +1,289 @@
+-- C460014.A
+--
+-- Grant of Unlimited Rights
+--
+-- The Ada Conformity Assessment Authority (ACAA) holds unlimited
+-- rights in the software and documentation contained herein. Unlimited
+-- rights are the same as those granted by the U.S. Government for older
+-- parts of the Ada Conformity Assessment Test Suite, and are defined
+-- in DFAR 252.227-7013(a)(19). By making this public release, the ACAA
+-- intends to confer upon all recipients unlimited rights equal to those
+-- held by the ACAA. These rights include rights to use, duplicate,
+-- release or disclose the released technical data and computer software
+-- in whole or in part, in any manner and for any purpose whatsoever, and
+-- to have or permit others to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE ACAA MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--
+-- Notice
+--
+-- The ACAA has created and maintains the Ada Conformity Assessment Test
+-- Suite for the purpose of conformity assessments conducted in accordance
+-- with the International Standard ISO/IEC 18009 - Ada: Conformity
+-- assessment of a language processor. This test suite should not be used
+-- to make claims of conformance unless used in accordance with
+-- ISO/IEC 18009 and any applicable ACAA procedures.
+--*
+-- OBJECTIVES:
+-- Check that if the operand type of a type conversion is
+-- access-to-class-wide, Constraint_Error is raised if the tag of the
+-- object designated by the operand does not identify a specific type
+-- that is covered by or descended from the target type.
+--
+-- TEST DESCRIPTION:
+-- Attempt to convert a parameter of a type that designates a class-wide
+-- type to an object of a type that designates a specific member of that
+-- class, for both an actual with a different tag and an actual with a
+-- matching tag.
+--
+-- This test checks 4.6(42) as required by 4.6(50).
+--
+-- CHANGE HISTORY:
+-- 19 Aug 16 JAC Initial pre-release version.
+-- 19 Jan 17 RLB Readied for release: replaced objective, renamed
+-- to appropriate number, added class-wide cases,
+-- eliminated 11.6 problems, added third level of
+-- types, and checks on null.
+--
+--!
+package C460014_1 is
+ type Root_Facade_Type is tagged record
+ Error_Code : Integer;
+ end record;
+
+ type Root_Facade_Ptr_Type is access all Root_Facade_Type;
+
+ type Facade_Class_Ptr_Type is access all Root_Facade_Type'Class;
+
+ type Data_A_Type is
+ record
+ A : Boolean;
+ end record;
+
+ type Facade_A_Type is new Root_Facade_Type with
+ record
+ Data_A : Data_A_Type;
+ end record;
+
+ type Facade_A_Ptr_Type is access all Facade_A_Type;
+
+ type Facade_A_Class_Ptr_Type is access all Facade_A_Type'Class;
+
+ type Facade_B_Type is new Facade_A_Type with
+ record
+ B : Character;
+ end record;
+
+ type Facade_B_Ptr_Type is access all Facade_B_Type;
+
+ type Facade_B_Class_Ptr_Type is access all Facade_B_Type'Class;
+
+ procedure Define_Construct
+ (Facade_Class_Ptr : in Facade_Class_Ptr_Type);
+
+ procedure Define_Class_Construct
+ (Facade_Class_Ptr : in Facade_Class_Ptr_Type);
+
+ function Init_Root_Facade_Ptr return Root_Facade_Ptr_Type;
+
+ function Init_Facade_A_Ptr return Facade_A_Ptr_Type;
+
+ function Init_Facade_B_Ptr return Facade_B_Ptr_Type;
+
+ function Init_Facade_Class_Ptr_with_Root return Facade_Class_Ptr_Type;
+
+ function Init_Facade_Class_Ptr_with_A return Facade_Class_Ptr_Type;
+
+ function Init_Facade_Class_Ptr_with_B return Facade_Class_Ptr_Type;
+
+end C460014_1;
+
+with Report;
+package body C460014_1 is
+
+ procedure Define_Construct
+ (Facade_Class_Ptr : in Facade_Class_Ptr_Type) is
+
+ Facade_A_Ptr : constant Facade_A_Ptr_Type :=
+ Facade_A_Ptr_Type (Facade_Class_Ptr);
+
+ My_A : Data_A_Type renames Facade_A_Ptr.Data_A;
+ begin
+ if not My_A.A then
+ Report.Comment ("Wrong value"); -- So My_A is not dead by 11.6(5).
+ end if;
+ end Define_Construct;
+
+ procedure Define_Class_Construct
+ (Facade_Class_Ptr : in Facade_Class_Ptr_Type) is
+
+ Facade_Class_A_Ptr : constant Facade_A_Class_Ptr_Type :=
+ Facade_A_Class_Ptr_Type (Facade_Class_Ptr);
+
+ begin
+ if Facade_Class_A_Ptr /= null and then
+ (not Facade_Class_A_Ptr.Data_A.A) then
+ Report.Comment ("Wrong value"); -- So the ptr is not dead by 11.6(5).
+ end if;
+ end Define_Class_Construct;
+
+ Dummy_Root_Facade : aliased Root_Facade_Type := (Error_Code => 123);
+
+ function Init_Root_Facade_Ptr return Root_Facade_Ptr_Type is
+ begin
+ return Dummy_Root_Facade'Access;
+ end Init_Root_Facade_Ptr;
+
+ Dummy_Facade_A : aliased Facade_A_Type := (Error_Code => 123,
+ Data_A => (A => True));
+
+ function Init_Facade_A_Ptr return Facade_A_Ptr_Type is
+ begin
+ return Dummy_Facade_A'Access;
+ end Init_Facade_A_Ptr;
+
+ Dummy_Facade_B : aliased Facade_B_Type := (Error_Code => 234,
+ Data_A => (A => True),
+ B => 'P');
+
+ function Init_Facade_B_Ptr return Facade_B_Ptr_Type is
+ begin
+ return Dummy_Facade_B'Access;
+ end Init_Facade_B_Ptr;
+
+ function Init_Facade_Class_Ptr_with_Root return Facade_Class_Ptr_Type is
+ begin
+ return Dummy_Root_Facade'Access;
+ end Init_Facade_Class_Ptr_with_Root;
+
+ function Init_Facade_Class_Ptr_with_A return Facade_Class_Ptr_Type is
+ begin
+ return Dummy_Facade_A'Access;
+ end Init_Facade_Class_Ptr_with_A;
+
+ function Init_Facade_Class_Ptr_with_B return Facade_Class_Ptr_Type is
+ begin
+ return Dummy_Facade_B'Access;
+ end Init_Facade_Class_Ptr_with_B;
+
+end C460014_1;
+
+
+with C460014_1;
+with Report;
+
+procedure C460014 is
+
+ My_Root_Facade_Ptr : constant C460014_1.Facade_Class_Ptr_Type :=
+ C460014_1.Init_Facade_Class_Ptr_with_Root;
+
+ My_Facade_A_Ptr : constant C460014_1.Facade_Class_Ptr_Type :=
+ C460014_1.Init_Facade_Class_Ptr_with_A;
+
+ My_Facade_B_Ptr : constant C460014_1.Facade_Class_Ptr_Type :=
+ C460014_1.Init_Facade_Class_Ptr_with_B;
+
+ My_Null_Facade_B_Ptr : constant C460014_1.Facade_B_Ptr_Type := null;
+
+ Constraint_Error_Raised : Boolean;
+
+ procedure Test_Define_Construct
+ (Facade_Class_Ptr : in C460014_1.Facade_Class_Ptr_Type) is
+ begin
+ Constraint_Error_Raised := False;
+ -- Should fail Tag_Check and therefore raise Constraint_Error if
+ -- parameter doesn't designate an object of Facade_A_Type
+ -- or Facade_B_Type.
+ C460014_1.Define_Construct (Facade_Class_Ptr => Facade_Class_Ptr);
+ exception
+ when Constraint_Error =>
+ Constraint_Error_Raised := True;
+ end Test_Define_Construct;
+
+
+ procedure Test_Define_Class_Construct
+ (Facade_Class_Ptr : in C460014_1.Facade_Class_Ptr_Type) is
+ begin
+ Constraint_Error_Raised := False;
+ -- Should fail Tag_Check and therefore raise Constraint_Error if
+ -- parameter doesn't designate an object of Facade_A_Type
+ -- or Facade_B_Type.
+ C460014_1.Define_Class_Construct (Facade_Class_Ptr => Facade_Class_Ptr);
+ exception
+ when Constraint_Error =>
+ Constraint_Error_Raised := True;
+ end Test_Define_Class_Construct;
+
+begin
+
+ Report.Test
+ ("C460014",
+ "Check that if the operand type of a type conversion is " &
+ "access-to-class-wide, Constraint_Error is raised if the tag of the " &
+ "object designated by the operand does not identify a specific type " &
+ "that is covered by or descended from the target type");
+
+ Test_Define_Construct (Facade_Class_Ptr => My_Root_Facade_Ptr);
+
+ if not Constraint_Error_Raised then
+ Report.Failed ("Didn't get expected Constraint_Error (1)");
+ end if;
+
+ Test_Define_Construct
+ (Facade_Class_Ptr => My_Facade_A_Ptr);
+
+ if Constraint_Error_Raised then
+ Report.Failed ("Unexpected Constraint_Error (2)");
+ end if;
+
+ Test_Define_Construct
+ (Facade_Class_Ptr => My_Facade_B_Ptr);
+
+ if Constraint_Error_Raised then
+ Report.Failed ("Unexpected Constraint_Error (3)");
+ end if;
+
+ Test_Define_Class_Construct (Facade_Class_Ptr => My_Root_Facade_Ptr);
+
+ if not Constraint_Error_Raised then
+ Report.Failed ("Didn't get expected Constraint_Error (4)");
+ end if;
+
+ Test_Define_Class_Construct
+ (Facade_Class_Ptr => My_Facade_A_Ptr);
+
+ if Constraint_Error_Raised then
+ Report.Failed ("Unexpected Constraint_Error (5)");
+ end if;
+
+ Test_Define_Class_Construct
+ (Facade_Class_Ptr => My_Facade_B_Ptr);
+
+ if Constraint_Error_Raised then
+ Report.Failed ("Unexpected Constraint_Error (6)");
+ end if;
+
+ -- Check that it is OK to pass null and that does not cause some failure.
+ Test_Define_Class_Construct (Facade_Class_Ptr => null);
+
+ if Constraint_Error_Raised then
+ Report.Failed ("Unexpected Constraint_Error (7)");
+ end if;
+
+ Test_Define_Class_Construct (Facade_Class_Ptr =>
+ C460014_1.Facade_Class_Ptr_Type (My_Null_Facade_B_Ptr));
+
+ if Constraint_Error_Raised then
+ Report.Failed ("Unexpected Constraint_Error (8)");
+ end if;
+
+ Report.Result;
+
+end C460014;
diff --git a/gcc/testsuite/ada/acats/tests/c6/c620001.a b/gcc/testsuite/ada/acats/tests/c6/c620001.a
new file mode 100644
index 0000000..0f854d1
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/c6/c620001.a
@@ -0,0 +1,340 @@
+-- C620001.A
+
+-- Grant of Unlimited Rights
+--
+-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- unlimited rights in the software and documentation contained herein.
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
+-- to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+-- OBJECTIVE:
+-- Check that elementary parameters are passed by copy.
+--
+-- Part 1: Integer, float, and access types, procedures and functions.
+--
+-- TEST DESCRIPTION:
+-- Subtests are:
+-- (A) Scalar parameters to procedures.
+-- (B) Scalar parameters to functions.
+-- (C) Access parameters to procedures.
+-- (D) Access parameters to functions.
+--
+-- For the procedure examples, we pass array elements indexed by dynamically
+-- determined indexes. Doing this side-steps the check of 6.4.1(6.15/3) and
+-- makes the test more realistic.
+--
+-- To completely test this objective, we should also try in out and out
+-- parameters for functions (Ada 2012), in/in out/out parameters for
+-- task and protected entries, and a variety of different scalar types
+-- (enumeration, modular, fixed, decimal).
+--
+-- CHANGE HISTORY:
+-- 14 Jan 1980 DAS Created test.
+-- 26 Oct 1982 SPS
+-- 25 May 1984 CPP
+-- 29 Oct 1985 EG Eliminate the use of Numeric_Error in the test.
+-- 14 Mar 2014 RLB Revised so test cases are legal for Ada 2012, modernized
+-- objective, converted to modern format, added float cases.
+
+with Report;
+procedure C620001 is
+
+ use Report;
+
+begin
+ Test ("C620001", "Check that elementary parameters are passed by copy");
+
+ --------------------------------------------------
+
+ declare -- (A)
+
+ I,J,K : Natural := Report.Ident_Int(1); -- Index values.
+ Arr : array (1 .. 4) of Integer;
+ E : exception;
+
+ procedure P (PI : in Integer;
+ PO : out Integer;
+ PIO : in out Integer) is
+
+ Tmp : Integer;
+
+ begin
+
+ Tmp := PI; -- Save value of PI at procedure entry.
+
+ PO := 10;
+ if (PI /= Tmp) then
+ Failed ("Assignement to scalar out " &
+ "parameter changes the value of " &
+ "input parameter");
+ Tmp := PI; -- Reset Tmp for next case.
+ end if;
+
+ PIO := PIO + 100;
+ if (PI /= Tmp) then
+ Failed ("Assignment to scalar in out " &
+ "parameter changes the value of " &
+ "inputparameter");
+ Tmp := PI; -- Reset Tmp for next case.
+ end if;
+
+ Arr(I) := Arr(I) + 1;
+ if (PI /= Tmp) then
+ Failed ("Assignment to scalar actual " &
+ "parameter changes the value of " &
+ "input parameter");
+ end if;
+
+ raise E; -- Check exception handling.
+ end P;
+
+ begin -- (A)
+ Arr := (others => 0);
+ P (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - A");
+ exception
+ when E =>
+ if (Arr(I) /= 1) then
+ case Arr(I) is
+ when 11 =>
+ Failed ("Out actual scalar parameter " &
+ "changed global value");
+ when 101 =>
+ Failed ("In out actual scalar " &
+ "parameter changed global value");
+ when 111 =>
+ Failed ("Out and in out actual scalar " &
+ "parameters changed global " &
+ "value");
+ when others =>
+ Failed ("Uundetermined change to global " &
+ "value");
+ end case;
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - A");
+ end; -- (A)
+
+ --------------------------------------------------
+
+ declare -- (B)
+
+ I,J : Integer;
+
+ function F (FI : in Integer) return Integer is
+
+ Tmp : Integer := FI;
+
+ begin
+
+ I := I + 1;
+ if (FI /= Tmp) then
+ Failed ("Assignment to scalar actual function " &
+ "parameter changes the value of " &
+ "input parameter");
+ end if;
+
+ return (100);
+ end F;
+
+ begin -- (B)
+ I := 100;
+ J := F (I);
+ end; -- (B)
+
+ --------------------------------------------------
+
+ declare -- (C)
+
+ type Acctype is access Integer;
+
+ I,J,K : Natural := Report.Ident_Int(2); -- Index values.
+ Arr : array (1 .. 5) of Acctype;
+ E : exception;
+
+ procedure P (PI : in Acctype;
+ PO : out Acctype;
+ PIO : in out Acctype) is
+
+ Tmp : Acctype;
+
+ begin
+
+ Tmp := PI; -- Save value of PI at procedure entry.
+
+ Arr(I) := new Integer'(101);
+ if (PI /= Tmp) then
+ Failed ("Assignment to access actual " &
+ "parameter changes the value of " &
+ "input parameter");
+ Tmp := PI; -- Reset Tmp for next case.
+ end if;
+
+ PO := new Integer'(1);
+ if (PI /= Tmp) then
+ Failed ("Assignment to access out " &
+ "parameter changes the value of " &
+ "input parameter");
+ Tmp := PI; -- Reset Tmp for next case.
+ end if;
+
+ PIO := new Integer'(10);
+ if (PI /= Tmp) then
+ Failed ("Assignment to access in out " &
+ "parameter changes the value of " &
+ "input parameter");
+ end if;
+
+ raise E; -- Check exception handling.
+ end P;
+
+ begin -- (C)
+ Arr(I) := new Integer'(100);
+ P (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - C");
+ exception
+ when E =>
+ if (Arr(I).all /= 101) then
+ Failed ("Out or in out actual procedure " &
+ "parameter value changed despite " &
+ "raised exception");
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - C");
+ end; -- (C)
+
+ --------------------------------------------------
+
+ declare -- (D)
+
+ Type Acctype is access Integer;
+
+ I,J : Acctype;
+
+ function F (FI : in Acctype) return Acctype is
+
+ Tmp : Acctype := FI;
+
+ begin
+
+ I := new Integer;
+ if (FI /= Tmp) then
+ Failed ("Assignment to access actual function " &
+ "parameter changes the value of " &
+ "Input parameter");
+ end if;
+
+ return null;
+ end F;
+
+ begin -- (D)
+ I := null;
+ J := F(I);
+ end; -- (D)
+
+ --------------------------------------------------
+
+ declare -- (E)
+
+ I,J,K : Natural := Report.Ident_Int(3); -- Index values.
+ Arr : array (1 .. 3) of Float;
+ E : exception;
+
+ procedure P (PI : in Float;
+ PO : out Float;
+ PIO : in out Float) is
+
+ Tmp : Float;
+
+ begin
+
+ Tmp := PI; -- Save value of PI at procedure entry.
+
+ PO := 0.5;
+ if (PI /= Tmp) then
+ Failed ("Assignement to float out " &
+ "parameter changes the value of " &
+ "input parameter");
+ Tmp := PI; -- Reset Tmp for next case.
+ end if;
+
+ PIO := PIO + 0.25;
+ if (PI /= Tmp) then
+ Failed ("Assignment to float in out " &
+ "parameter changes the value of " &
+ "inputparameter");
+ Tmp := PI; -- Reset Tmp for next case.
+ end if;
+
+ Arr(I) := Arr(I) + 1.0;
+ if (PI /= Tmp) then
+ Failed ("Assignment to float actual " &
+ "parameter changes the value of " &
+ "input parameter");
+ end if;
+
+ raise E; -- Check exception handling.
+ end P;
+
+ begin -- (E)
+ Arr := (others => 0.0);
+ P (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - E");
+ exception
+ when E =>
+ if (Arr(I) /= 1.0) then
+ Failed ("Out or in out actual procedure " &
+ "parameter value changed despite " &
+ "raised exception");
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - E");
+ end; -- (E)
+
+ --------------------------------------------------
+
+ declare -- (F)
+
+ I,J : Float;
+
+ function F (FI : in Float) return Float is
+
+ Tmp : Float := FI;
+
+ begin
+
+ I := I + 1.0;
+ if (FI /= Tmp) then
+ Failed ("Assignment to float actual function " &
+ "parameter changes the value of " &
+ "input parameter");
+ end if;
+
+ return 100.0;
+ end F;
+
+ begin -- (F)
+ I := 100.0;
+ J := F (I);
+ end; -- (F)
+
+ --------------------------------------------------
+
+ Result;
+
+end C620001;
diff --git a/gcc/testsuite/ada/acats/tests/c6/c620002.a b/gcc/testsuite/ada/acats/tests/c6/c620002.a
new file mode 100644
index 0000000..b46a04e
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/c6/c620002.a
@@ -0,0 +1,509 @@
+-- C620001.A
+
+-- Grant of Unlimited Rights
+--
+-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- unlimited rights in the software and documentation contained herein.
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
+-- to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+-- OBJECTIVE:
+-- Check that elementary parameters are passed by copy.
+--
+-- Part 2: Integer, float, and access types, task and protected entries.
+--
+-- TEST DESCRIPTION:
+-- Subtests are:
+-- (A) Scalar parameters to task entries.
+-- (B) Scalar parameters to protected entries.
+-- (C) Access parameters to task entries.
+-- (D) Access parameters to protected entries.
+--
+-- For all of these examples, we pass array elements indexed by dynamically
+-- determined indexes. Doing this side-steps the check of 6.4.1(6.15/3) and
+-- makes the test more realistic.
+--
+-- Note: This is based on legacy test C95072A.ADA (which was withdrawn).
+--
+-- CHANGE HISTORY:
+-- 22 Jul 1985 DAS Created test.
+-- 12 May 2020 RLB Revised so test cases are legal for Ada 2012, modernized
+-- objective, converted to modern format, added float
+-- and protected cases.
+
+with Report;
+procedure C620002 is
+
+ use Report;
+
+begin
+ Test ("C620002", "Check that elementary parameters are passed by copy," &
+ " part 2 - task and protected entries");
+
+ --------------------------------------------------
+
+ declare -- (A)
+
+ I,J,K : Natural := Report.Ident_Int (1); -- Index values.
+ Arr : array (1 .. 4) of Integer;
+ E : exception;
+
+ task TA is
+ entry EA (EI : in Integer;
+ EO : out Integer;
+ EIO : in out Integer);
+ end TA;
+
+ task body TA is
+
+ Tmp : Integer;
+
+ begin
+
+ accept EA (EI : in Integer;
+ EO : out Integer;
+ EIO : in out Integer) do
+
+ Tmp := EI; -- Save value of EI at accept.
+
+ EO := 10;
+ if EI /= Tmp then
+ Failed ("Assignement to scalar out " &
+ "parameter changes the value of " &
+ "input parameter - A");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EIO := EIO + 100;
+ if EI /= Tmp then
+ Failed ("Assignment to scalar in out " &
+ "parameter changes the value of " &
+ "input parameter - A");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ Arr(I) := Arr(I) + 1;
+ if EI /= Tmp then
+ Failed ("Assignment to scalar actual " &
+ "parameter changes the value of " &
+ "input parameter - A");
+ end if;
+
+ raise E; -- Check exception handling.
+ end EA;
+
+ exception
+ when others => null;
+ end TA;
+
+ begin -- (A)
+ Arr := (others => 0);
+ TA.EA (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - A");
+ exception
+ when E =>
+ if Arr(I) /= 1 then
+ case Arr(I) is
+ when 11 =>
+ Failed ("Out actual scalar parameter " &
+ "changed global value - A");
+ when 101 =>
+ Failed ("In out actual scalar " &
+ "parameter changed global value - A");
+ when 111 =>
+ Failed ("Out and in out actual scalar " &
+ "parameters changed global " &
+ "value - A");
+ when others =>
+ Failed ("Undetermined change to global " &
+ "value - A");
+ end case;
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - A");
+ end; -- (A)
+
+ --------------------------------------------------
+
+ declare -- (B)
+
+ I,J,K : Natural := Report.Ident_Int (3); -- Index values.
+ Arr : array (1 .. 5) of Integer;
+ E : exception;
+
+ protected PA is
+ entry EA (EI : in Integer;
+ EO : out Integer;
+ EIO : in out Integer);
+ end PA;
+
+ protected body PA is
+
+ entry EA (EI : in Integer;
+ EO : out Integer;
+ EIO : in out Integer) when True is
+
+ Tmp : Integer;
+
+ begin
+
+ Tmp := EI; -- Save value of EI at entry.
+
+ EO := 10;
+ if EI /= Tmp then
+ Failed ("Assignement to scalar out " &
+ "parameter changes the value of " &
+ "input parameter - B");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EIO := EIO + 100;
+ if EI /= Tmp then
+ Failed ("Assignment to scalar in out " &
+ "parameter changes the value of " &
+ "input parameter - B");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ Arr(I) := Arr(I) + 1;
+ if EI /= Tmp then
+ Failed ("Assignment to scalar actual " &
+ "parameter changes the value of " &
+ "input parameter - B");
+ end if;
+
+ raise E; -- Check exception handling.
+ end EA;
+
+ end PA;
+
+ begin -- (B)
+ Arr := (others => 0);
+ PA.EA (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - B");
+ exception
+ when E =>
+ if Arr(I) /= 1 then
+ case Arr(I) is
+ when 11 =>
+ Failed ("Out actual scalar parameter " &
+ "changed global value - B");
+ when 101 =>
+ Failed ("In out actual scalar " &
+ "parameter changed global value - B");
+ when 111 =>
+ Failed ("Out and in out actual scalar " &
+ "parameters changed global " &
+ "value - B");
+ when others =>
+ Failed ("Undetermined change to global " &
+ "value - B");
+ end case;
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - B");
+ end; -- (B)
+
+ --------------------------------------------------
+
+ declare -- (C)
+
+ type Acctype is access Integer;
+
+ I,J,K : Natural := Report.Ident_Int (2); -- Index values.
+ Arr : array (1 .. 5) of Acctype;
+ E : exception;
+
+ task TB is
+ entry EB (EI : in Acctype;
+ EO : out Acctype;
+ EIO : in out Acctype);
+ end TB;
+
+ task body TB is
+
+ Tmp : Acctype;
+
+ begin
+
+ accept EB (EI : in Acctype;
+ EO : out Acctype;
+ EIO : in out Acctype) do
+
+ Tmp := EI; -- Save value of EI at accept.
+
+ Arr(I) := new Integer'(101);
+ if EI /= Tmp then
+ Failed ("Assignment to access actual " &
+ "parameter changes the value of " &
+ "input parameter - C");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EO := new Integer'(1);
+ if EI /= Tmp then
+ Failed ("Assignment to access out " &
+ "parameter changes the value of " &
+ "input parameter - C");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EIO := new Integer'(10);
+ if EI /= Tmp then
+ Failed ("Assignment to access in out " &
+ "parameter changes the value of " &
+ "input parameter - C");
+ end if;
+
+ raise E; -- Check exception handling.
+ end EB;
+
+ exception
+ when others => null;
+ end TB;
+
+ begin -- (C)
+ Arr(I) := new Integer'(100);
+ TB.EB (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - C");
+ exception
+ when E =>
+ if (Arr(I).all /= 101) then
+ Failed ("Out or in out actual " &
+ "parameter value changed despite " &
+ "raised exception - C");
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - C");
+ end; -- (C)
+
+ --------------------------------------------------
+
+ declare -- (D)
+
+ type Acctype is access Integer;
+
+ I,J,K : Natural := Report.Ident_Int (4); -- Index values.
+ Arr : array (1 .. 6) of Acctype;
+ E : exception;
+
+ protected PB is
+ entry EB (EI : in Acctype;
+ EO : out Acctype;
+ EIO : in out Acctype);
+ end PB;
+
+ protected body PB is
+
+ entry EB (EI : in Acctype;
+ EO : out Acctype;
+ EIO : in out Acctype) when True is
+
+ Tmp : Acctype;
+
+ begin
+ Tmp := EI; -- Save value of EI at entry.
+
+ Arr(I) := new Integer'(101);
+ if EI /= Tmp then
+ Failed ("Assignment to access actual " &
+ "parameter changes the value of " &
+ "input parameter - D");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EO := new Integer'(1);
+ if EI /= Tmp then
+ Failed ("Assignment to access out " &
+ "parameter changes the value of " &
+ "input parameter - D");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EIO := new Integer'(10);
+ if EI /= Tmp then
+ Failed ("Assignment to access in out " &
+ "parameter changes the value of " &
+ "input parameter - D");
+ end if;
+
+ raise E; -- Check exception handling.
+ end EB;
+
+ end PB;
+
+ begin -- (D)
+ Arr(I) := new Integer'(100);
+ PB.EB (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - D");
+ exception
+ when E =>
+ if (Arr(I).all /= 101) then
+ Failed ("Out or in out actual " &
+ "parameter value changed despite " &
+ "raised exception - D");
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - D");
+ end; -- (D)
+
+ --------------------------------------------------
+
+ declare -- (E)
+
+ I,J,K : Natural := Report.Ident_Int (3); -- Index values.
+ Arr : array (1 .. 3) of Float;
+ E : exception;
+
+ task TC is
+ entry EC (EI : in Float;
+ EO : out Float;
+ EIO : in out Float);
+ end TC;
+
+ task body TC is
+
+ Tmp : Float;
+
+ begin
+
+ accept EC (EI : in Float;
+ EO : out Float;
+ EIO : in out Float) do
+
+ Tmp := EI; -- Save value of EI at accept.
+
+ EO := 0.5;
+ if EI /= Tmp then
+ Failed ("Assignement to float out " &
+ "parameter changes the value of " &
+ "input parameter - E");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EIO := EIO + 0.25;
+ if EI /= Tmp then
+ Failed ("Assignment to float in out " &
+ "parameter changes the value of " &
+ "input parameter - E");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ Arr(I) := Arr(I) + 1.0;
+ if EI /= Tmp then
+ Failed ("Assignment to float actual " &
+ "parameter changes the value of " &
+ "input parameter - E");
+ end if;
+
+ raise E; -- Check exception handling.
+ end EC;
+
+ exception
+ when others => null;
+ end TC;
+
+ begin -- (E)
+ Arr := (others => 0.0);
+ TC.EC (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - E");
+ exception
+ when E =>
+ if (Arr(I) /= 1.0) then
+ Failed ("Out or in out actual procedure " &
+ "parameter value changed despite " &
+ "raised exception - E");
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - E");
+ end; -- (E)
+
+ --------------------------------------------------
+
+ declare -- (F)
+
+ I,J,K : Natural := Report.Ident_Int (6); -- Index values.
+ Arr : array (1 .. 7) of Float;
+ E : exception;
+
+ protected PC is
+ entry EC (EI : in Float;
+ EO : out Float;
+ EIO : in out Float);
+ end PC;
+
+ protected body PC is
+
+ entry EC (EI : in Float;
+ EO : out Float;
+ EIO : in out Float) when True is
+
+ Tmp : Float;
+
+ begin
+
+ Tmp := EI; -- Save value of EI at entry.
+
+ EO := 0.5;
+ if EI /= Tmp then
+ Failed ("Assignement to float out " &
+ "parameter changes the value of " &
+ "input parameter - F");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ EIO := EIO + 0.25;
+ if EI /= Tmp then
+ Failed ("Assignment to float in out " &
+ "parameter changes the value of " &
+ "input parameter - F");
+ Tmp := EI; -- Reset Tmp for next case.
+ end if;
+
+ Arr(I) := Arr(I) + 1.0;
+ if EI /= Tmp then
+ Failed ("Assignment to float actual " &
+ "parameter changes the value of " &
+ "input parameter - F");
+ end if;
+
+ raise E; -- Check exception handling.
+ end EC;
+
+ end PC;
+
+ begin -- (F)
+ Arr := (others => 0.0);
+ PC.EC (Arr(I), Arr(J), Arr(K));
+ Failed ("Exception not raised - F");
+ exception
+ when E =>
+ if (Arr(I) /= 1.0) then
+ Failed ("Out or in out actual procedure " &
+ "parameter value changed despite " &
+ "raised exception - F");
+ end if;
+ when others =>
+ Failed ("Wrong exception raised - F");
+ end; -- (F)
+
+ --------------------------------------------------
+
+ Result;
+
+end C620002;
diff --git a/gcc/testsuite/ada/acats/tests/c7/c761006.a b/gcc/testsuite/ada/acats/tests/c7/c761006.a
index 771e625..5cf4d89 100644
--- a/gcc/testsuite/ada/acats/tests/c7/c761006.a
+++ b/gcc/testsuite/ada/acats/tests/c7/c761006.a
@@ -55,6 +55,9 @@
-- 01 DEC 97 EDS Made correction wrt RM 7.6(21)
-- 16 MAR 01 RLB Corrected Adjust cases to avoid problems with
-- RM 7.6.1(16/1) from Technical Corrigendum 1.
+-- 05 JUL 12 RLB Redid Unchecked_Deallocation case to handle
+-- the fact that the behavior is unspecified (see
+-- AI95-0179-1). Also fixed indentation.
--
--!
@@ -346,23 +349,39 @@ procedure C761006 is
-- finalization of Item/Target should cause PE
end Finalize_15;
- -- check failure in finalize due to Unchecked_Deallocation
+ -- check failure in finalize due to Unchecked_Deallocation
- type Shark is access C761006_2.Fin_Check;
+ procedure Finalize_17_Outer is
+ -- This procedure exists to make Shark local, so everything allocated
+ -- on it will be finalized when this routine exits.
- procedure Catch is
- new Unchecked_Deallocation( C761006_2.Fin_Check, Shark );
+ type Shark is access C761006_2.Fin_Check;
- procedure Finalize_17 is
- White : Shark := new C761006_2.Fin_Check;
- begin
- Catch( White );
- exception
- when Program_Error =>
+ procedure Catch is
+ new Unchecked_Deallocation( C761006_2.Fin_Check, Shark );
+
+ procedure Finalize_17_Inner is
+ White : Shark := new C761006_2.Fin_Check;
+ begin
+ Catch (White);
+ -- Note: It is unspecified if Catch deallocates the memory
+ -- of the allocated object, and if it ceases to exist.
+ -- As such, it is possible that it will be finalized when
+ -- the scope of the access type is exited. We check for this
+ -- case below.
+ exception
+ when Program_Error =>
if not Sup.Events_Occurring(Sup.Good_Finalize) then
Report.Failed("Unchecked_Deallocation: " & Fin_Not_Perf);
end if;
- end Finalize_17;
+ end Finalize_17_Inner;
+
+ begin
+ Finalize_17_Inner;
+ exception
+ when others =>
+ Report.Failed("Unchecked_Deallocation check, unwanted exception in Outer");
+ end Finalize_17_Outer;
begin
@@ -373,10 +392,12 @@ procedure C761006 is
end Exception_In_Finalization;
Use_Of_Unchecked_Deallocation: begin
- Finalize_17;
+ Finalize_17_Outer;
exception
+ when Program_Error =>
+ Report.Comment("Unchecked_Deallocation check, double finalization occurred");
when others =>
- Report.Failed("Unchecked_Deallocation check, unwanted exception");
+ Report.Failed("Unchecked_Deallocation check, unwanted exception in caller");
end Use_Of_Unchecked_Deallocation;
end Finalize_Test;
diff --git a/gcc/testsuite/ada/acats/tests/c9/c96004a.ada b/gcc/testsuite/ada/acats/tests/c9/c96004a.ada
index f5357fc..b1f769b 100644
--- a/gcc/testsuite/ada/acats/tests/c9/c96004a.ada
+++ b/gcc/testsuite/ada/acats/tests/c9/c96004a.ada
@@ -3,22 +3,22 @@
-- Grant of Unlimited Rights
--
-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
-- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
-- to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--*
@@ -35,6 +35,8 @@
-- CPP 08/15/84 CREATED ORIGINAL TEST.
-- JET 01/06/88 UPDATED HEADER FORMAT AND ADDED CODE TO PREVENT
-- OPTIMIZATION.
+-- RLB 12/18/06 Changed so that the test will work for Ada 2005
+-- implementations.
WITH CALENDAR; USE CALENDAR;
WITH REPORT; USE REPORT;
@@ -92,15 +94,35 @@ BEGIN
END;
BEGIN
- YR := IDENT_INT(YEAR_NUMBER'LAST + 1);
- FAILED ("EXCEPTION NOT RAISED - (A)3");
+ YR := IDENT_INT(2100);
IF NOT EQUAL (YR, YR) THEN
COMMENT ("NO EXCEPTION RAISED");
END IF;
-
+ BEGIN
+ YR := 2399;
+ IF NOT EQUAL (YR, YR) THEN
+ COMMENT ("NO EXCEPTION RAISED");
+ END IF;
+
+ EXCEPTION
+ WHEN OTHERS =>
+ FAILED ("ADA 2005 CASE RAISED EXCEPTION ON 2399 - (A)");
+ END;
+ BEGIN
+ YR := IDENT_INT(2400);
+ IF NOT EQUAL (YR, YR) THEN
+ COMMENT ("NO EXCEPTION RAISED");
+ END IF;
+ FAILED ("EXCEPTION NOT RAISED - (A)3");
+ EXCEPTION
+ WHEN CONSTRAINT_ERROR =>
+ Comment ("Upper bound of Year_Number is appropriate" &
+ " for Ada 2005");
+ END;
EXCEPTION
WHEN CONSTRAINT_ERROR =>
- NULL;
+ Comment ("Upper bound of Year_Number is appropriate" &
+ " for Ada 95");
WHEN OTHERS =>
FAILED ("WRONG EXCEPTION RAISED - (A)3");
END;
diff --git a/gcc/testsuite/ada/acats/tests/c9/c96007a.ada b/gcc/testsuite/ada/acats/tests/c9/c96007a.ada
index beda25f..15ac5e9 100644
--- a/gcc/testsuite/ada/acats/tests/c9/c96007a.ada
+++ b/gcc/testsuite/ada/acats/tests/c9/c96007a.ada
@@ -3,22 +3,22 @@
-- Grant of Unlimited Rights
--
-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
-- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
-- to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--*
@@ -27,7 +27,9 @@
-- (A) TIME_ERROR IS RAISED ON INVALID DATES.
-- (B) CONSTRAINT_ERROR IS RAISED FOR OUT-OF-RANGE PARAMETERS.
--- CPP 8/16/84
+-- CPP 8/16/84
+-- RLB 12/18/06 - Changed so that the test will work for Ada 2005
+-- implementations.
WITH CALENDAR; USE CALENDAR;
WITH REPORT; USE REPORT;
@@ -136,13 +138,13 @@ BEGIN
END;
BEGIN
- BAD_TIME := TIME_OF (YEAR_NUMBER'LAST + 1, 8, 13);
- FAILED ("EXCEPTION NOT RAISED - 2100 (B)");
+ BAD_TIME := TIME_OF (YEAR_NUMBER'LAST+1, 8, 13);
+ FAILED ("EXCEPTION NOT RAISED - YEAR_NUM'LAST+1 (B)");
EXCEPTION
WHEN CONSTRAINT_ERROR =>
NULL;
WHEN OTHERS =>
- FAILED ("WRONG EXCEPTION RAISED - 2100 (B)");
+ FAILED ("WRONG EXCEPTION RAISED - YEAR_NUM'LAST+1 (B)");
END;
BEGIN
diff --git a/gcc/testsuite/ada/acats/tests/cb/cb41004.a b/gcc/testsuite/ada/acats/tests/cb/cb41004.a
index 5a7b704..b73ed8f 100644
--- a/gcc/testsuite/ada/acats/tests/cb/cb41004.a
+++ b/gcc/testsuite/ada/acats/tests/cb/cb41004.a
@@ -56,10 +56,8 @@
-- 06 Dec 94 SAIC ACVC 2.0
-- 08 Dec 00 RLB Removed Exception_Identity subtest, pending
-- resolution of AI95-00241.
--- Notes for future: Replace Exception_Identity
--- subtest with whatever the resolution is.
--- Add a subtest for Exception_Name(Null_Id), which
--- is missing from this test.
+-- 29 Mar 07 RLB Replaced Exception_Identity subtest, repaired
+-- Raise_Exception subtest for AI95-00446.
--!
with Report;
@@ -96,6 +94,29 @@ begin
end if;
+ -- Verify that Raise_Exception has no effect in the case of Null_Id.
+ -- Modified by AI-446.
+ begin
+ Ada.Exceptions.Raise_Exception(A_Null_Exception_Id);
+ Report.Comment(
+ "No exception raised by procedure Raise_Exception " &
+ "when called with a Null_Id input parameter - compatible with " &
+ "original Ada95");
+ exception
+ when Constraint_Error => null; -- OK, expected exception.
+ Report.Comment(
+ "Constraint_Error exception raised by procedure Raise_Exception " &
+ "when called with a Null_Id input parameter - compatible with " &
+ "AI95-00446");
+ when others =>
+ Report.Failed(
+ "Unexpected exception raised by procedure Raise_Exception " &
+ "when called with a Null_Id input parameter");
+ end;
+
+ TC_Flag := False;
+
+
-- Verify that Reraise_Occurrence has no effect in the case of
-- Null_Occurrence.
begin
@@ -135,26 +156,30 @@ begin
end;
--- -- Verify that function Exception_Identity raises Constraint_Error for
--- -- a Null_Occurrence input parameter.
--- -- Note: (RLB, 2000/12/08) This behavior may be modified by AI-00241.
--- -- As such, this test case has been removed pending a resolution.
--- begin
--- declare
--- Id : Ada.Exceptions.Exception_Id :=
--- Ada.Exceptions.Exception_Identity(A_Null_Exception_Occurrence);
--- begin
--- Report.Failed
--- ("Constraint_Error not raised by Function Exception_Identity " &
--- "when called with a Null_Occurrence input parameter");
--- end;
--- exception
--- when Constraint_Error => null; -- OK, expected exception.
--- when others =>
--- Report.Failed
--- ("Unexpected exception raised by Function Exception_Identity " &
--- "when called with a Null_Occurrence input parameter");
--- end;
+ -- Verify that function Exception_Identity raises Constraint_Error for
+ -- a Null_Occurrence input parameter.
+ -- Modified by AI-241.
+ begin
+ declare
+ Id : Ada.Exceptions.Exception_Id :=
+ Ada.Exceptions.Exception_Identity(A_Null_Exception_Occurrence);
+ begin
+ Report.Comment
+ ("No exception raised by Function Exception_Identity " &
+ "when called with a Null_Occurrence input parameter - " &
+ "compatible with AI95-00241.");
+ end;
+ exception
+ when Constraint_Error =>
+ Report.Comment
+ ("Constraint_Error raised by Function Exception_Identity " &
+ "when called with a Null_Occurrence input parameter - " &
+ "compatible with original Ada95.");
+ when others =>
+ Report.Failed
+ ("Unexpected exception raised by Function Exception_Identity " &
+ "when called with a Null_Occurrence input parameter");
+ end;
-- Verify that function Exception_Name raises Constraint_Error for
diff --git a/gcc/testsuite/ada/acats/tests/cc/cc3016f.ada b/gcc/testsuite/ada/acats/tests/cc/cc3016f.ada
index 9a1f099..ef94672 100644
--- a/gcc/testsuite/ada/acats/tests/cc/cc3016f.ada
+++ b/gcc/testsuite/ada/acats/tests/cc/cc3016f.ada
@@ -3,26 +3,25 @@
-- Grant of Unlimited Rights
--
-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
-- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
-- to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--*
--- OFFICE, 3E 114, THE PENTAGON, WASHINGTON DC 20301-3081.
-- OBJECTIVE:
-- CHECK THAT AN INSTANTIATED PACKAGE HAS THE PROPERTIES REQUIRED
diff --git a/gcc/testsuite/ada/acats/tests/cd/cd30011.a b/gcc/testsuite/ada/acats/tests/cd/cd30011.a
new file mode 100644
index 0000000..2cd96a4
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/cd/cd30011.a
@@ -0,0 +1,155 @@
+-- CD30011.A
+
+-- Grant of Unlimited Rights
+--
+-- The Ada Conformity Assessment Authority (ACAA) holds unlimited
+-- rights in the software and documentation contained herein. Unlimited
+-- rights are the same as those granted by the U.S. Government for older
+-- parts of the Ada Conformity Assessment Test Suite, and are defined
+-- in DFAR 252.227-7013(a)(19). By making this public release, the ACAA
+-- intends to confer upon all recipients unlimited rights equal to those
+-- held by the ACAA. These rights include rights to use, duplicate,
+-- release or disclose the released technical data and computer software
+-- in whole or in part, in any manner and for any purpose whatsoever, and
+-- to have or permit others to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--
+-- Notice
+--
+-- The ACAA has created and maintains the Ada Conformity Assessment Test
+-- Suite for the purpose of conformity assessments conducted in accordance
+-- with the International Standard ISO/IEC 18009 - Ada: Conformity
+-- assessment of a language processor. This test suite should not be used
+-- to make claims of conformance unless used in accordance with
+-- ISO/IEC 18009 and any applicable ACAA procedures.
+--
+--*
+-- OBJECTIVE:
+-- Check that a size specification can be given by an attribute definition
+-- clause for an enumeration type:
+-- * in the visible or private part of a package for a type declared
+-- in the visible part;
+-- * for a derived enumeration type;
+-- * for a derived private type whose full declaration is an
+-- enumeration type.
+--
+-- TEST DESCRIPTION:
+-- This test was created from legacy tests CD1009B and CD2A31C. The
+-- objective of CD1009B was also an objective of CD2A31C; the tests
+-- were merged to eliminate duplication and add appropriate applicability
+-- criteria.
+--
+-- APPLICABILITY CRITERIA:
+-- All implementations must attempt to compile this test.
+--
+-- For implementations validating against Systems Programming Annex (C):
+-- this test must execute and report PASSED.
+--
+-- or implementations not validating against Annex C:
+-- this test may report compile time errors at one or more points
+-- indicated by "-- ANX-C RQMT", in which case it may be graded as
+-- inapplicable. Otherwise, the test must execute and report PASSED.
+--
+-- CHANGE HISTORY:
+-- 17 Jun 87 PWB Created original test CD2A21C.
+-- 07 Oct 87 VCL Created original test CD1009B.
+-- 17 Apr 89 DHH Changed extension from '.DEP' TO '.ADA', changed
+-- operators on 'Size tests, and added check on
+-- representation clause.
+-- 26 Mar 92 JRL Removed testing of nonobjective types.
+-- 29 Mar 17 RLB Created test from CD2A21C and CD1009B; reformatted
+-- to "modern" standards, added applicability criteria.
+
+with Report; use Report;
+with Length_Check; -- CONTAINS A CALL TO 'Failed'.
+procedure CD30011 is
+
+ type Basic_Enum is (A, B, C, D, E);
+ Specified_Size : constant := Basic_Enum'Size;
+
+ Minimum_Size : Integer := Report.Ident_Int (Specified_Size);
+
+ type Derived_Enum is new Basic_Enum;
+ for Derived_Enum'Size use Specified_Size; -- ANX-C RQMT.
+
+ package P is
+ type Enum_in_P is (A1, B1, C1, D1, E1, F1, G1);
+ for Enum_in_P'Size use Specified_Size; -- ANX-C RQMT.
+ type private_Enum is private;
+ type Alt_Enum_in_P is (A2, B2, C2, D2, E2, F2, G2);
+ private
+ type private_Enum is (A3, B3, C3, D3, E3, F3, G3);
+ for Alt_Enum_in_P'Size use Specified_Size; -- ANX-C RQMT.
+ end P;
+
+ type Derived_Private_Enum is new P.Private_Enum;
+ for Derived_Private_Enum'Size use Specified_Size; -- ANX-C RQMT.
+
+ use P;
+
+ procedure Check_1 is new Length_Check (Derived_Enum);
+ procedure Check_2 is new Length_Check (Enum_in_P);
+ procedure Check_3 is new Length_Check (Alt_Enum_in_P);
+
+ X : Enum_in_P := A1;
+ Y : Alt_Enum_in_P := A2;
+
+begin
+
+ Report.Test ("CD30011", "Check that 'Size attribute definition clauses " &
+ "can be given in the visible or private part " &
+ "of a package for enumeration types declared " &
+ "declared in the visible part, and for derived " &
+ "enumeration types and derived private types " &
+ "whose full declarations are as enumeration types");
+
+ Check_1 (C, Specified_Size, "Derived_Enum");
+ Check_2 (C1, Specified_Size, "Enum_in_P");
+ Check_3 (C2, Specified_Size, "Alt_Enum_in_P");
+
+ if Derived_Enum'Size /= Minimum_Size then
+ Failed ("Derived_Enum'Size should not be greater than" &
+ Integer'Image (Minimum_Size) & ". Actual Size is" &
+ Integer'Image (Derived_Enum'Size));
+ end if;
+
+ if Enum_in_P'Size /= Minimum_Size then
+ Failed ("Enum_in_P'Size should not be greater than" &
+ Integer'Image (Minimum_Size) & ". Actual Size is" &
+ Integer'Image (Enum_in_P'Size));
+ end if;
+
+ if Alt_Enum_in_P'Size /= Minimum_Size then
+ Failed ("Alt_Enum_in_P'Size should not be greater than" &
+ Integer'Image (Minimum_Size) & ". Actual Size is" &
+ Integer'Image (Alt_Enum_in_P'Size));
+ end if;
+
+ if Derived_Private_Enum'Size /= Minimum_Size then
+
+ Failed ("Derived_Private_Enum'Size should not be greater " &
+ "than " & Integer'Image (Minimum_Size) & ". Actual Size is" &
+ Integer'Image (Derived_Private_Enum'Size));
+ end if;
+
+ if X'Size < Specified_Size then
+ Failed ("Object'Size is too small --" &
+ Enum_in_P'Image (X));
+ end if;
+
+ if Y'Size < Specified_Size then
+ Failed ("Object'Size is too small --" &
+ Alt_Enum_in_P'Image (Y));
+ end if;
+
+ Report.Result;
+
+end CD30011;
diff --git a/gcc/testsuite/ada/acats/tests/cd/cd30012.a b/gcc/testsuite/ada/acats/tests/cd/cd30012.a
new file mode 100644
index 0000000..a55dfbd
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/cd/cd30012.a
@@ -0,0 +1,173 @@
+-- CD30012.A
+
+-- Grant of Unlimited Rights
+--
+-- The Ada Conformity Assessment Authority (ACAA) holds unlimited
+-- rights in the software and documentation contained herein. Unlimited
+-- rights are the same as those granted by the U.S. Government for older
+-- parts of the Ada Conformity Assessment Test Suite, and are defined
+-- in DFAR 252.227-7013(a)(19). By making this public release, the ACAA
+-- intends to confer upon all recipients unlimited rights equal to those
+-- held by the ACAA. These rights include rights to use, duplicate,
+-- release or disclose the released technical data and computer software
+-- in whole or in part, in any manner and for any purpose whatsoever, and
+-- to have or permit others to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--
+-- Notice
+--
+-- The ACAA has created and maintains the Ada Conformity Assessment Test
+-- Suite for the purpose of conformity assessments conducted in accordance
+-- with the International Standard ISO/IEC 18009 - Ada: Conformity
+-- assessment of a language processor. This test suite should not be used
+-- to make claims of conformance unless used in accordance with
+-- ISO/IEC 18009 and any applicable ACAA procedures.
+--
+--*
+-- OBJECTIVE:
+-- Check that a size specification can be given by an attribute definition
+-- clause for an integer type:
+-- * in the visible or private part of a package for a type declared
+-- in the visible part;
+-- * for a derived integer type;
+-- * for a derived private type whose full declaration is an
+-- integer type.
+--
+-- TEST DESCRIPTION:
+-- This test was created from legacy tests CD1009B and CD2A31C. The
+-- objective of CD1009B was also an objective of CD30012; the tests
+-- were merged to eliminate duplication and add appropriate applicability
+-- criteria.
+--
+-- APPLICABILITY CRITERIA:
+-- All implementations must attempt to compile this test.
+--
+-- For implementations validating against Systems Programming Annex (C):
+-- this test must execute and report PASSED.
+--
+-- or implementations not validating against Annex C:
+-- this test may report compile time errors at one or more points
+-- indicated by "-- ANX-C RQMT", in which case it may be graded as
+-- inapplicable. Otherwise, the test must execute and report PASSED.
+--
+-- CHANGE HISTORY:
+-- 17 Jun 87 PWB Created original test CD2A31C.
+-- 09 Sep 87 VCL Created original test CD1009A.
+-- 06 Apr 89 DHH Changed extension from '.DEP' TO '.ADA', changed
+-- size clause value to 9, and added representation
+-- clause check and included test for for integer in a
+-- generic unit.
+-- 27 Mar 92 JRL Removed testing of nonobjective types.
+-- 17 Jun 92 DTN Removed the length clause for type Private_Int.
+-- 29 Mar 17 RLB Created test from CD2A31C and CD1009A; reformatted
+-- to "modern" standards, added applicability criteria,
+-- removed nonobjective packed array.
+
+with Report; use Report;
+with Length_Check; -- Contains a call to 'Failed'.
+procedure CD30012 is
+
+ type Basic_Int is range -60 .. 80;
+ Specified_Size : constant := 9;
+
+ type Derived_Int is new Basic_Int;
+ for Derived_Int'Size use Specified_Size; -- ANX-C RQMT.
+
+ package P is
+ type Int_in_P is range -125 .. 125;
+ for Int_in_P'Size use Specified_Size; -- ANX-C RQMT.
+ type Private_Int is private;
+ type Alt_Int_in_P is range -125 .. 125;
+ private
+ type Private_Int is range -125 .. 125;
+ for Alt_Int_in_P'Size use Specified_Size; -- ANX-C RQMT.
+ end P;
+
+ use P;
+ type Derived_Private_Int is new Private_Int;
+ for Derived_Private_Int'Size use Specified_Size; -- ANX-C RQMT.
+ Minimum_Size : Integer := Report.Ident_Int (Specified_Size);
+
+ -- Size specification given in a generic procedure:
+
+ generic
+ procedure Genproc;
+
+ procedure Genproc is
+ type Check_Int is range -125 .. 125;
+ for Check_Int'Size use Specified_Size; -- ANX-C RQMT.
+
+ procedure Check_4 is new Length_Check (Check_Int);
+
+ begin
+
+ if Check_Int'Size /= Minimum_Size then
+ Failed ("Generic Check_Int'Size is incorrect");
+ end if;
+ Check_4 (-60, 9, "generic Check_Int");
+
+ end Genproc;
+
+ procedure Newproc is new Genproc;
+
+ procedure Check_1 is new Length_Check (Derived_Int);
+ procedure Check_2 is new Length_Check (Int_in_P);
+ procedure Check_3 is new Length_Check (Alt_Int_in_P);
+
+ Obj1 : Int_in_P := 92;
+ Obj2 : Alt_Int_in_P := 52;
+
+begin
+
+ Report.Test ("CD30012", "Check that 'Size attribute definition clauses " &
+ "can be given in the visible or private part " &
+ "of a package for integer types declared " &
+ "declared in the visible part, and for derived " &
+ "integer types and derived private types " &
+ "whose full declarations are as integer types");
+
+ Check_1 (-60, 9, "Derived_Int");
+ Check_2 (-60, 9, "Int_in_P");
+ Check_3 (-60, 9, "Alt_Int_in_P");
+ Check_2 (Obj1, 9, "Int_in_P");
+ Check_3 (Obj2, 9, "Alt_Int_in_P");
+
+ Newproc;
+
+ if Derived_Int'Size /= Minimum_Size then
+ Failed ("Derived_Int'Size incorrect");
+ end if;
+
+ if Int_in_P'Size /= Minimum_Size then
+ Failed ("Int_in_P'Size incorrect");
+ end if;
+
+ if Alt_Int_in_P'Size /= Minimum_Size then
+ Failed ("Alt_Int_in_P'Size incorrect");
+ end if;
+
+ if Derived_Private_Int'Size /= Minimum_Size then
+ Failed ("Derived_Private_Int'Size incorrect");
+ end if;
+
+ if Obj1'Size < Specified_Size then
+ Failed ("Object'Size is too small --" &
+ Int_in_P'Image (Obj1));
+ end if;
+
+ if Obj2'Size < Specified_Size then
+ Failed ("Object'Size is too small --" &
+ Alt_Int_in_P'Image (Obj2));
+ end if;
+
+ Report.Result;
+
+end CD30012;
diff --git a/gcc/testsuite/ada/acats/tests/cd/cd90001.a b/gcc/testsuite/ada/acats/tests/cd/cd90001.a
index bd5c070..3f3bd89 100644
--- a/gcc/testsuite/ada/acats/tests/cd/cd90001.a
+++ b/gcc/testsuite/ada/acats/tests/cd/cd90001.a
@@ -3,22 +3,22 @@
-- Grant of Unlimited Rights
--
-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
-- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
-- to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--*
@@ -26,11 +26,11 @@
-- OBJECTIVE:
-- Check that Unchecked_Conversion is supported and is reversible in
-- the cases where:
--- Source'Size = Target'Size
--- Source'Alignment = Target'Alignment
--- Source and Target are both represented contiguously
+-- Source'Size = Target'Size
+-- Source'Alignment = Target'Alignment
+-- Source and Target are both represented contiguously
-- Bit pattern in Source is a meaningful value of Target type
---
+--
-- TEST DESCRIPTION:
-- This test declares an enumeration type with a representation
-- specification that should fit neatly into an 8 bit object; and a
@@ -61,6 +61,7 @@
-- 27 JUL 96 SAIC Allowed for partial N/A to be PASS
-- 14 FEB 97 PWB.CTA Corrected "=" to "/=" in alignment check.
-- 16 FEB 98 EDS Modified documentation.
+-- 21 DEC 05 RLB Corrected "=" to "/=" in other alignment check.
--!
----------------------------------------------------------------- CD90001_0
@@ -136,7 +137,7 @@ package body CD90001_0 is
Report.Failed ("EU => EB conversion failed");
end if;
- end loop;
+ end loop;
end TC_Check_Case_1;
procedure TC_Check_Case_2 is
@@ -209,7 +210,7 @@ begin -- Main test procedure.
Report.Comment("The sizes of the 16 bit types used in this test "
& "do not match" );
Sixteen_NA := True;
- elsif CD90001_0.Signed_16'Alignment = CD90001_0.Bits_16'Alignment then
+ elsif CD90001_0.Signed_16'Alignment /= CD90001_0.Bits_16'Alignment then
Report.Comment("The alignments of the 16 bit types used in this "
& "test do not match" );
Sixteen_NA := True;
diff --git a/gcc/testsuite/ada/acats/tests/cxa/cxa3004.a b/gcc/testsuite/ada/acats/tests/cxa/cxa3004.a
new file mode 100644
index 0000000..ed2023e
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/cxa/cxa3004.a
@@ -0,0 +1,235 @@
+-- CXA3004.A
+--
+-- Grant of Unlimited Rights
+--
+-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- unlimited rights in the software and documentation contained herein.
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
+-- to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+--
+-- OBJECTIVE:
+-- Check that the functions defined in package Ada.Characters.Handling
+-- for classification of and conversion between Wide_Character and
+-- Character values produce correct results when given the appropriate
+-- Character and String inputs.
+--
+-- TEST DESCRIPTION:
+-- This test demonstrates the functions defined in package
+-- Ada.Characters.Handling which provide for the classification of and
+-- conversion between Wide_Characters and Characters, in character
+-- variables and strings.
+-- Each of the functions is provided with input values that are of the
+-- appropriate range. The results of the function processing are
+-- subsequently evaluated.
+--
+-- APPLICABILITY CRITERIA:
+-- Applicable to all implementations using the Latin_1 set as the
+-- definition of Character.
+--
+--
+-- CHANGE HISTORY:
+-- 06 Dec 94 SAIC ACVC 2.0
+-- 27 Dec 94 SAIC Corrected variable names.
+--
+--!
+
+with Report;
+with Ada.Characters.Handling;
+
+procedure CXA3004 is
+begin
+
+ Report.Test ("CXA3004", "Check that the functions defined in package " &
+ "Ada.Characters.Handling for classification " &
+ "of and conversion between Wide_Character and " &
+ "Character values produce correct results " &
+ "when given the appropriate Character " &
+ "and String inputs");
+
+ Test_Block:
+ declare
+
+ package ACH renames Ada.Characters.Handling;
+
+ Char_End : Integer := 255;
+ WC_Start : Integer := 256;
+ Sub_Char : Character := '*';
+
+ Blank : Character := ' ';
+ First_Char : Character := Character'First;
+ Last_Char : Character := Character'Last;
+ F_Char : Character := 'F';
+
+
+ First_Wide_Char : Wide_Character := Wide_Character'First;
+ Last_Non_Wide_Char : Wide_Character := Wide_Character'Val(Char_End);
+ First_Unique_Wide_Char : Wide_Character := Wide_Character'Val(WC_Start);
+ Last_Wide_Char : Wide_Character := Wide_Character'Last;
+
+ A_String : String (1..3) := First_Char & 'X' & Last_Char;
+ A_Wide_String : Wide_String (1..3) := First_Wide_Char &
+ ACH.To_Wide_Character('X') &
+ ACH.To_Wide_Character(Last_Char);
+
+ Unique_Wide_String : Wide_String (1..2) := First_Unique_Wide_Char &
+ Last_Wide_Char;
+
+ Mixed_Wide_String : Wide_String (1..6) := ACH.To_Wide_Character('A') &
+ First_Wide_Char &
+ Last_Non_Wide_Char &
+ First_Unique_Wide_Char &
+ Last_Wide_Char &
+ ACH.To_Wide_Character('Z');
+
+
+ Basic_Char : Character := 'A';
+ Basic_Wide_Char : Wide_Character := 'A';
+ Basic_String : String (1..6) := "ABCXYZ";
+ Basic_Wide_String : Wide_String (1..6) := "ABCXYZ";
+
+ begin
+
+
+ -- Function Is_Character
+
+
+ if not ACH.Is_Character(First_Wide_Char) then
+ Report.Failed ("Incorrect result from Is_Character - 1");
+ end if;
+
+
+ if ACH.Is_Character(First_Unique_Wide_Char) or
+ ACH.Is_Character(Last_Wide_Char)
+ then
+ Report.Failed ("Incorrect result from Is_Character - 2");
+ end if;
+
+
+ -- Function Is_String
+
+
+ if not ACH.Is_String(A_Wide_String) then
+ Report.Failed ("Incorrect result from Is_String - 1");
+ end if;
+
+
+ if ACH.Is_String(Unique_Wide_String) or
+ ACH.Is_String(Mixed_Wide_String)
+ then
+ Report.Failed ("Incorrect result from Is_String - 2");
+ end if;
+
+
+ -- Function To_Character
+
+
+ -- Use default substitution character in call of To_Character.
+
+ if ACH.To_Character(First_Wide_Char) /= First_Char or
+ ACH.To_Character(Last_Non_Wide_Char) /= Last_Char
+ then
+ Report.Failed ("Incorrect result from To_Character - 1");
+ end if;
+
+
+ -- Provide a substitution character for use with To_Character.
+
+ if ACH.To_Character(First_Unique_Wide_Char, Blank) /= Blank or
+ ACH.To_Character(First_Unique_Wide_Char, Sub_Char) /= Sub_Char or
+ ACH.To_Character(Last_Wide_Char) /= ' ' -- default
+ then
+ Report.Failed ("Incorrect result from To_Character - 2");
+ end if;
+
+
+ -- Function To_String
+
+
+ if ACH.To_String(A_Wide_String) /= A_String then
+ Report.Failed ("Incorrect result from To_String - 1");
+ end if;
+
+
+ if ACH.To_String(Unique_Wide_String, Sub_Char) /= "**" then
+ Report.Failed ("Incorrect result from To_String - 2");
+ end if;
+
+
+
+ if ACH.To_String(Mixed_Wide_String, Sub_Char) /=
+ ('A' & First_Char & Last_Char & "**" & 'Z') or
+ ACH.To_String(Mixed_Wide_String, Sub_Char) /=
+ (ACH.To_Character(Mixed_Wide_String(1), Sub_Char) &
+ ACH.To_Character(Mixed_Wide_String(2), Sub_Char) &
+ ACH.To_Character(Mixed_Wide_String(3), Sub_Char) &
+ ACH.To_Character(Mixed_Wide_String(4), Sub_Char) &
+ ACH.To_Character(Mixed_Wide_String(5), Sub_Char) &
+ ACH.To_Character(Mixed_Wide_String(6), Sub_Char))
+ then
+ Report.Failed ("Incorrect result from To_String - 3");
+ end if;
+
+
+ -- Function To_Wide_Character
+
+
+ if ACH.To_Wide_Character(Basic_Char) /= Basic_Wide_Char then
+ Report.Failed ("Incorrect result from To_Wide_Character");
+ end if;
+
+
+ -- Function To_Wide_String
+
+
+ if not (ACH.To_Wide_String(Basic_String) = Basic_Wide_String) then
+ Report.Failed ("Incorrect result from To_Wide_String");
+ end if;
+
+
+ -- Functions Used In Combination
+
+ if not ACH.Is_Character (ACH.To_Wide_Character (
+ ACH.To_Character(First_Wide_Char)))
+ then
+ Report.Failed ("Incorrect result from functions in combination - 1");
+ end if;
+
+
+ if not ACH.Is_String(ACH.To_Wide_String(ACH.To_String(A_Wide_String)))
+ then
+ Report.Failed ("Incorrect result from functions in combination - 2");
+ end if;
+
+
+ if ACH.To_String(ACH.To_Wide_Character('A') &
+ ACH.To_Wide_Character(F_Char) &
+ ACH.To_Wide_Character('Z')) /= "AFZ"
+ then
+ Report.Failed ("Incorrect result from functions in combination - 3");
+ end if;
+
+
+ exception
+ when others => Report.Failed ("Exception raised in Test_Block");
+ end Test_Block;
+
+
+ Report.Result;
+
+end CXA3004;
diff --git a/gcc/testsuite/ada/acats/tests/cxa/cxa5013.a b/gcc/testsuite/ada/acats/tests/cxa/cxa5013.a
new file mode 100644
index 0000000..fe5b6e2
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/cxa/cxa5013.a
@@ -0,0 +1,326 @@
+-- CXA5013.A
+--
+-- Grant of Unlimited Rights
+--
+-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- unlimited rights in the software and documentation contained herein.
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
+-- to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+--
+-- OBJECTIVE:
+-- Check that a discrete random number generator will yield each value
+-- in its result subtype in a finite number of calls, provided that
+-- the number of such values does not exceed 2**15.
+--
+-- TEST DESCRIPTION:
+-- This test demonstrates certain capabilities of the random number
+-- generator packages in Ada.Numerics. A generic subprogram is
+-- defined that will be instantiated to produce a total of two test
+-- subprograms.
+-- The area examined by this test is the production of random values
+-- over a discrete range. A generic procedure is instantiated with
+-- an instance of the Discrete_Random package, once for an integer type,
+-- and once for an enumeration type. The test procedure performs a
+-- test run, generating a specific number of random numbers over the
+-- range of the type. If this run did not generate each of the values
+-- in the type range, an asynchronous select statement is invoked. This
+-- select statement has a trigger statement delay for a specific
+-- (implementation defined) amount of time during which additional test
+-- runs will be performed.
+-- At the end of each run in this test, an evaluation is made to
+-- determine if each value in the range of possible values have been
+-- generated. At the conclusion of the runs, or if the specified test
+-- delay time expires, the test is concluded with a status value
+-- returned from the test procedure. An implementation is given three
+-- completely separate opportunities to run the test successfully, and
+-- if at the conclusion of all of these tests no successful result has
+-- been returned, the test is considered failed.
+--
+--
+-- CHANGE HISTORY:
+-- 27 Apr 95 SAIC Initial prerelease version.
+--
+--!
+
+with Ada.Numerics.Discrete_Random;
+with ImpDef;
+with Report;
+
+procedure CXA5013 is
+
+begin
+
+ Report.Test ("CXA5013", "Check that a discrete random number generator " &
+ "will yield each value in its result subtype " &
+ "in a finite number of calls");
+
+ Test_Block:
+ declare
+
+ use Ada.Numerics;
+
+ -- The following constant designed into the test creates a high
+ -- probability that a random series of numbers will satisfy the
+ -- requirements. Occasionally, even a random series of numbers
+ -- will fail. In such a case, the test will reset the random
+ -- number generator and rerun the test conditions. This constant
+ -- determines how many times the random number generator will be
+ -- reset before any individual test run is failed.
+
+ TC_Max_Random_Test_Runs : constant := 3;
+
+ -- The following constant will ensure that multiple attempts of the
+ -- complete set of tests are performed in the event of a failure of
+ -- a set of test runs.
+
+ TC_Finite_Number_Of_Tests : constant := 3;
+
+
+ TC_Test_Run : Integer := 0;
+ TC_Success : Boolean := False;
+ TC_Trials_Per_Test : Integer := 1500;
+
+ type Enum_Type is (One, Two, Three, Four, Five, Six, Seven);
+ type Discrete_Type is range 1..100;
+
+
+ package Enum_Pack is new Discrete_Random(Enum_Type);
+ package Discrete_Pack is
+ new Discrete_Random(Result_Subtype => Discrete_Type);
+
+
+
+ --
+ -- Definition of generic Random_Test procedure, which will be
+ -- instantiated for both an integer type and an enumeration type.
+ --
+
+ generic
+ with package Gen_Pack is new Ada.Numerics.Discrete_Random (<>);
+ procedure Random_Test (Trials_Per_Test : in Integer;
+ Success : out Boolean);
+
+
+ procedure Random_Test (Trials_Per_Test : in Integer;
+ Success : out Boolean) is
+ Total_Runs : Integer := 0;
+ Total_Trials : Integer := 0;
+ Total_Attempts_This_Test : Integer := 0;
+ Random_Array : array (Gen_Pack.Result_Subtype)
+ of Boolean := (others => False);
+ Gen : Gen_Pack.Generator;
+
+ function All_Values_Present return Boolean is
+ Result : Boolean := True;
+ begin
+ for i in Gen_Pack.Result_Subtype'Range loop
+ if not Random_Array(i) then
+ Result := False;
+ exit;
+ end if;
+ end loop;
+ return Result;
+ end All_Values_Present;
+
+ begin
+
+ Success := False; -- Initialized to failure prior to test.
+ Gen_Pack.Reset(Gen); -- Perform a time-dependent reset.
+
+ -- Guarantee that a specific minimum number of trials are performed
+ -- prior to the timer being set.
+
+ for i in 1..Trials_Per_Test loop
+ -- Set array element to True when a particular array
+ -- index is generated by the random number generator.
+ Random_Array(Gen_Pack.Random(Gen)) := True;
+ end loop;
+
+ if All_Values_Present then
+
+ Success := True; -- Test was successful, exit procedure with no
+ -- further testing performed.
+ else
+
+ -- Initial test above was unsuccessful, so set a timer and perform
+ -- additional trials to determine if all values in the discrete
+ -- range will be produced.
+
+ select
+
+ -- This asynchronous select has a triggering statement which
+ -- is a delay statement, set to an implementation defined
+ -- number of seconds for any particular test to execute.
+ -- The point here is to allow the implementation to decide
+ -- how long to run this test in order to generate an
+ -- appropriate (i.e., correct) sample from the Random Number
+ -- Generator.
+
+ delay ImpDef.Delay_Per_Random_Test; -- Delay per test.
+
+ -- If, after expiration of delay, the random number generator
+ -- has generated all values within the range at least once,
+ -- then the result is success; otherwise, a comment is output
+ -- to indicate that the random number generator was
+ -- unsuccessful in this series of test runs.
+
+ if All_Values_Present then
+ Success := True;
+ else
+ Total_Attempts_This_Test :=
+ Total_Runs * Trials_Per_Test + Total_Trials;
+ Report.Comment
+ ("Not all numbers within the Range were produced in " &
+ Integer'Image(
+ Integer(ImpDef.Delay_Per_Random_Test*1000.0)) &
+ " milliseconds or in " &
+ Integer'Image(Total_Attempts_This_Test) &
+ " trials during this test");
+ end if;
+
+ then abort
+
+ -- After setting the triggering statement above, the execution
+ -- of this abortable part is begun.
+ -- This loop continues until either a) every value has been
+ -- produced or b) the triggering statement times out.
+
+ Total_Runs := 1;
+
+ Test_Loop: -- This loop continues until a test run is
+ loop -- successful, the test run limit has been reached,
+ -- or the triggering statement times-out above.
+
+ Total_Trials := 0;
+
+ for i in 1..Trials_Per_Test loop
+ Total_Trials := i; -- Used above if triggering statement
+ -- completes prior to test completion.
+
+ -- Set array element to True when a particular array
+ -- index is generated by the random number generator.
+
+ Random_Array(Gen_Pack.Random(Gen)) := True;
+
+ end loop;
+
+ -- At the conclusion of a complete series of trials, the
+ -- following evaluation is performed to determine whether
+ -- the test run was successful, or whether an additional
+ -- test run should be re-attempted.
+
+ if All_Values_Present then
+ Success := True;
+ exit Test_Loop;
+ elsif Total_Runs = TC_Max_Random_Test_Runs then
+ Report.Comment
+ ("Not all numbers in the Range were produced in " &
+ Integer'Image(Total_Runs*Trials_Per_Test) &
+ " individual trials during this test");
+ exit Test_Loop;
+ else
+ Total_Runs := Total_Runs + 1;
+ end if;
+
+ end loop Test_Loop;
+ end select;
+ end if;
+ end Random_Test;
+
+
+
+ -- Instantiation of test procedures.
+
+ procedure Discrete_Random_Test is new Random_Test(Discrete_Pack);
+ procedure Enumeration_Random_Test is new Random_Test(Enum_Pack);
+
+
+ begin
+
+ -- Make a series of test runs, checking to ensure that discrete
+ -- random number generators produce each value in their result subtype
+ -- within a finite number of calls. In each case, if the first test
+ -- is not successful, another attempt is made, after a time-dependent
+ -- reset, up to a total of 3 runs. This allows an implementation
+ -- multiple opportunities to pass the test successfully.
+ -- Note: The odds of getting all 100 integer values in 1500 trials are
+ -- greater than 99.997 percent, confirmed by Monte Carlo
+ -- simulation.
+
+
+
+ -- Run the Random_Test for an integer discrete random number generator.
+
+ TC_Test_Run := 0;
+ TC_Success := False;
+ while TC_Test_Run < TC_Finite_Number_Of_Tests and
+ not TC_Success
+ loop
+ TC_Test_Run := TC_Test_Run + 1; -- Increment test counter.
+ Discrete_Random_Test (TC_Trials_Per_Test, -- Perform test.
+ TC_Success);
+ -- Increment the number of trials that will be performed
+ -- in the next test by 50%.
+ TC_Trials_Per_Test := TC_Trials_Per_Test + TC_Trials_Per_Test/2 ;
+ end loop;
+
+ if not TC_Success then
+ Report.Failed("Random_Test was run " & Integer'Image(TC_Test_Run) &
+ " times, but a successful result was not recorded " &
+ "from any run using the integer discrete random " &
+ "number generator");
+ end if;
+
+
+
+ -- Run the Random_Test for an enumeration type random number generator.
+
+ -- Note: The odds of getting all seven enumeration values in 100
+ -- trials are greater than 99.997 percent, confirmed by Monte
+ -- Carlo simulation.
+
+ TC_Test_Run := 0;
+ TC_Trials_Per_Test := 100;
+ TC_Success := False;
+ while TC_Test_Run < TC_Finite_Number_Of_Tests and
+ not TC_Success
+ loop
+ TC_Test_Run := TC_Test_Run + 1;
+ Enumeration_Random_Test (TC_Trials_Per_Test,
+ TC_Success);
+ -- Increment the number of trials that will be performed
+ -- in the next test by 50%.
+ TC_Trials_Per_Test := TC_Trials_Per_Test + TC_Trials_Per_Test/2 ;
+ end loop;
+
+ if not TC_Success then
+ Report.Failed("Random_Test was run " & Integer'Image(TC_Test_Run) &
+ " times, but a successful result was not recorded " &
+ "from any run using the enumeration random number " &
+ "generator");
+ end if;
+
+
+ exception
+ when others => Report.Failed ("Exception raised in Test_Block");
+ end Test_Block;
+
+ Report.Result;
+
+end CXA5013;
diff --git a/gcc/testsuite/ada/acats/tests/cxa/cxac005.a b/gcc/testsuite/ada/acats/tests/cxa/cxac005.a
index 34a971f..5032357 100644
--- a/gcc/testsuite/ada/acats/tests/cxa/cxac005.a
+++ b/gcc/testsuite/ada/acats/tests/cxa/cxac005.a
@@ -31,6 +31,7 @@
-- 12 FEB 2001 PHL Initial version.
-- 14 MAR 2001 RLB Readied for release; fixed Not_Applicable check
-- to terminate test gracefully.
+-- 05 MAR 2007 RLB Updated to avoid problems with return-by-reference.
--
--!
with Ada.Streams.Stream_Io;
@@ -53,7 +54,6 @@ procedure CXAC005 is
package Checked_Stream_Io is
type File_Type (Max_Size : Stream_Element_Count) is limited private;
- function Stream_Io_File (File : File_Type) return Stream_Io.File_Type;
procedure Create (File : in out File_Type;
Mode : in Stream_Io.File_Mode := Stream_Io.Out_File;
@@ -93,6 +93,8 @@ procedure CXAC005 is
function Index (File : in File_Type) return Stream_Io.Positive_Count;
+ function Size (File : in File_Type) return Stream_Io.Count;
+
procedure Set_Mode (File : in out File_Type;
Mode : in Stream_Io.File_Mode);
@@ -111,11 +113,6 @@ procedure CXAC005 is
use Stream_Io;
- function Stream_Io_File (File : File_Type) return Stream_Io.File_Type is
- begin
- return File.File;
- end Stream_Io_File;
-
procedure Create (File : in out File_Type;
Mode : in Stream_Io.File_Mode := Stream_Io.Out_File;
Name : in String := "";
@@ -244,6 +241,13 @@ procedure CXAC005 is
return New_Index;
end Index;
+ function Size (File : in File_Type) return Stream_Io.Count is
+ New_Size : constant Count := Stream_Io.Size (File.File);
+ begin
+ TC_Assert (New_Size <= Count(File.Max_Size), "File too large");
+ return New_Size;
+ end Size;
+
procedure Set_Mode (File : in out File_Type;
Mode : in Stream_Io.File_Mode) is
Old_Index : constant Count := File.Index;
@@ -268,7 +272,8 @@ procedure CXAC005 is
begin
- Test ("CXAC005", "Check that stream file positioning work as specified");
+ Report.Test ("CXAC005",
+ "Check that stream file positioning work as specified");
declare
Name : constant String := Legal_File_Name;
@@ -320,8 +325,7 @@ begin
-- Check the contents of the entire file.
declare
S : Stream_Element_Array
- (1 .. Stream_Element_Offset
- (Stream_Io.Size (Csio.Stream_Io_File (F))));
+ (1 .. Stream_Element_Offset (Csio.Size (F)));
begin
Csio.Reset (F, Stream_Io.In_File);
Csio.Read (F, S, Last);
@@ -330,7 +334,7 @@ begin
Csio.Delete (F);
end;
- Result;
+ Report.Result;
exception
when Incomplete =>
Report.Result;
diff --git a/gcc/testsuite/ada/acats/tests/cxb/cxb30061.am b/gcc/testsuite/ada/acats/tests/cxb/cxb30061.am
new file mode 100644
index 0000000..d31345a
--- /dev/null
+++ b/gcc/testsuite/ada/acats/tests/cxb/cxb30061.am
@@ -0,0 +1,404 @@
+-- CXB30061.AM
+--
+-- Grant of Unlimited Rights
+--
+-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- unlimited rights in the software and documentation contained herein.
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
+-- to do so.
+--
+-- DISCLAIMER
+--
+-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
+-- PARTICULAR PURPOSE OF SAID MATERIAL.
+--*
+--
+-- OBJECTIVE:
+-- Check that the function To_C maps between the Ada type Wide_Character
+-- and the C type wchar_t.
+--
+-- Check that the function To_Ada maps between the C type wchar_t and
+-- the Ada type Wide_Character.
+--
+-- Check that the function Is_Nul_Terminated returns True if the
+-- wchar_array parameter contains wide_nul, and otherwise False.
+--
+-- Check that the function To_C produces a correct wchar_array result,
+-- with lower bound of 0, and length dependent upon the Item and
+-- Append_Nul parameters.
+--
+-- Check that the function To_Ada produces a correct wide_string result,
+-- with lower bound of 1, and length dependent upon the Item and
+-- Trim_Nul parameters.
+--
+-- Check that the function To_Ada raises Terminator_Error if the
+-- parameter Trim_Nul is set to True, but the actual Item parameter
+-- does not contain the wide_nul wchar_t.
+--
+-- TEST DESCRIPTION:
+-- This test uses a variety of Wide_Character, wchar_t, Wide_String, and
+-- wchar_array objects to test versions of the To_C, To_Ada, and
+-- Is_Nul_Terminated functions.
+--
+-- This test assumes that the following characters are all included
+-- in the implementation defined type Interfaces.C.wchar_t:
+-- ' ', ',', '.', '0'..'9', 'a'..'z' and 'A'..'Z'.
+--
+-- APPLICABILITY CRITERIA:
+-- This test is applicable to all implementations that provide
+-- package Interfaces.C. If an implementation provides
+-- package Interfaces.C, this test must compile, execute, and
+-- report "PASSED".
+--
+-- SPECIAL REQUIREMENTS:
+-- The file CXB30060.C must be compiled with a C compiler.
+-- Implementation dialects of C may require alteration of
+-- the C program syntax (see individual C files).
+--
+-- Note that the compiled C code must be bound with the compiled Ada
+-- code to create an executable image. An implementation must provide
+-- the necessary commands to accomplish this.
+--
+-- Note that the C code included in CXB30060.C conforms
+-- to ANSI-C. Modifications to these files may be required for other
+-- C compilers. An implementation must provide the necessary
+-- modifications to satisfy the function requirements.
+--
+-- TEST FILES:
+-- The following files comprise this test:
+--
+-- CXB30060.C
+-- CXB30061.AM
+--
+-- CHANGE HISTORY:
+-- 07 Sep 95 SAIC Initial prerelease version.
+-- 09 May 96 SAIC Incorporated reviewer comments for ACVC 2.1.
+-- 13 Sep 99 RLB Replaced (bogus) Unchecked_Conversions with a
+-- C function character generator.
+--
+--!
+
+with Report;
+with Interfaces.C; -- N/A => ERROR
+with Ada.Characters.Latin_1;
+with Ada.Characters.Handling;
+with Ada.Exceptions;
+with Ada.Strings.Wide_Fixed;
+with Impdef;
+
+procedure CXB30061 is
+begin
+
+ Report.Test ("CXB3006", "Check that the functions To_C and To_Ada " &
+ "produce correct results");
+
+ Test_Block:
+ declare
+
+ use Interfaces, Interfaces.C;
+ use Ada.Characters, Ada.Characters.Latin_1, Ada.Characters.Handling;
+ use Ada.Strings.Wide_Fixed;
+
+ First_Character,
+ Last_Character : Character;
+ TC_wchar_t,
+ TC_Low_wchar_t,
+ TC_High_wchar_t : wchar_t := wchar_t'First;
+ TC_Wide_String : Wide_String(1..8) := (others => Wide_Character'First);
+ TC_wchar_array : wchar_array(0..7) := (others => C.wide_nul);
+
+ -- The function Char_Gen returns a character corresponding to its
+ -- argument.
+ -- Value 0 .. 9 ==> '0' .. '9'
+ -- Value 10 .. 19 ==> 'A' .. 'J'
+ -- Value 20 .. 29 ==> 'k' .. 't'
+ -- Value 30 ==> ' '
+ -- Value 31 ==> '.'
+ -- Value 32 ==> ','
+
+ function Char_Gen (Value : in int) return wchar_t;
+
+ -- Use the user-defined C function char_gen as a completion to the
+ -- function specification above.
+
+ pragma Import (Convention => C,
+ Entity => Char_Gen,
+ External_Name => Impdef.CXB30060_External_Name);
+
+ begin
+
+ -- Check that the functions To_C and To_Ada map between the Ada type
+ -- Wide_Character and the C type wchar_t.
+
+ if To_C(To_Wide_Character(Ada.Characters.Latin_1.NUL)) /=
+ Interfaces.C.wide_nul
+ then
+ Report.Failed("Incorrect result from To_C with NUL character input");
+ end if;
+
+ First_Character := Report.Ident_Char('k');
+ Last_Character := Report.Ident_Char('t');
+ for i in First_Character..Last_Character loop
+ if To_C(Item => To_Wide_Character(i)) /=
+ Char_Gen(Character'Pos(i) - Character'Pos('k') + 20)
+ then
+ Report.Failed("Incorrect result from To_C with lower case " &
+ "alphabetic wide character input");
+ end if;
+ end loop;
+
+ First_Character := Report.Ident_Char('A');
+ Last_Character := Report.Ident_Char('J');
+ for i in First_Character..Last_Character loop
+ if To_C(Item => To_Wide_Character(i)) /=
+ Char_Gen(Character'Pos(i) - Character'Pos('A') + 10)
+ then
+ Report.Failed("Incorrect result from To_C with upper case " &
+ "alphabetic wide character input");
+ end if;
+ end loop;
+
+ First_Character := Report.Ident_Char('0');
+ Last_Character := Report.Ident_Char('9');
+ for i in First_Character..Last_Character loop
+ if To_C(Item => To_Wide_Character(i)) /=
+ Char_Gen(Character'Pos(i) - Character'Pos('0'))
+ then
+ Report.Failed("Incorrect result from To_C with digit " &
+ "wide character input");
+ end if;
+ end loop;
+
+ if To_C(Item => To_Wide_Character(' ')) /= Char_Gen(30)
+ then
+ Report.Failed("Incorrect result from To_C with space " &
+ "wide character input");
+ end if;
+
+ if To_C(Item => To_Wide_Character('.')) /= Char_Gen(31)
+ then
+ Report.Failed("Incorrect result from To_C with dot " &
+ "wide character input");
+ end if;
+
+ if To_C(Item => To_Wide_Character(',')) /= Char_Gen(32)
+ then
+ Report.Failed("Incorrect result from To_C with comma " &
+ "wide character input");
+ end if;
+
+ if To_Ada(Interfaces.C.wide_nul) /=
+ To_Wide_Character(Ada.Characters.Latin_1.NUL)
+ then
+ Report.Failed("Incorrect result from To_Ada with wide_nul " &
+ "wchar_t input");
+ end if;
+
+ for Code in int range
+ int(Report.Ident_Int(20)) .. int(Report.Ident_Int(29)) loop
+ -- 'k' .. 't'
+ if To_Ada(Item => Char_Gen(Code)) /=
+ To_Wide_Character(Character'Val (Character'Pos('k') + (Code - 20)))
+ then
+ Report.Failed("Incorrect result from To_Ada with lower case " &
+ "alphabetic wchar_t input");
+ end if;
+ end loop;
+
+ for Code in int range
+ int(Report.Ident_Int(10)) .. int(Report.Ident_Int(19)) loop
+ -- 'A' .. 'J'
+ if To_Ada(Item => Char_Gen(Code)) /=
+ To_Wide_Character(Character'Val (Character'Pos('A') + (Code - 10)))
+ then
+ Report.Failed("Incorrect result from To_Ada with upper case " &
+ "alphabetic wchar_t input");
+ end if;
+ end loop;
+
+ for Code in int range
+ int(Report.Ident_Int(0)) .. int(Report.Ident_Int(9)) loop
+ -- '0' .. '9'
+ if To_Ada(Item => Char_Gen(Code)) /=
+ To_Wide_Character(Character'Val (Character'Pos('0') + (Code)))
+ then
+ Report.Failed("Incorrect result from To_Ada with digit " &
+ "wchar_t input");
+ end if;
+ end loop;
+
+ if To_Ada(Item => Char_Gen(30)) /= ' ' then
+ Report.Failed("Incorrect result from To_Ada with space " &
+ "char input");
+ end if;
+ if To_Ada(Item => Char_Gen(31)) /= '.' then
+ Report.Failed("Incorrect result from To_Ada with dot " &
+ "char input");
+ end if;
+ if To_Ada(Item => Char_Gen(32)) /= ',' then
+ Report.Failed("Incorrect result from To_Ada with comma " &
+ "char input");
+ end if;
+
+ -- Check that the function Is_Nul_Terminated produces correct results
+ -- whether or not the wchar_array argument contains the
+ -- Ada.Interfaces.C.wide_nul character.
+
+ TC_Wide_String := "abcdefgh";
+ if Is_Nul_Terminated(Item => To_C(TC_Wide_String, Append_Nul => False))
+ then
+ Report.Failed("Incorrect result from Is_Nul_Terminated when no " &
+ "wide_nul wchar_t is present");
+ end if;
+
+ if not Is_Nul_Terminated(To_C(TC_Wide_String, Append_Nul => True)) then
+ Report.Failed("Incorrect result from Is_Nul_Terminated when the " &
+ "wide_nul wchar_t is present");
+ end if;
+
+
+
+ -- Now that we've tested the character/char versions of To_Ada and To_C,
+ -- use them to test the string versions.
+
+ declare
+ i : size_t := 0;
+ j : integer := 1;
+ Incorrect_Conversion : Boolean := False;
+
+ TC_No_wide_nul : constant wchar_array := To_C(TC_Wide_String,
+ False);
+ TC_wide_nul_Appended : constant wchar_array := To_C(TC_Wide_String,
+ True);
+ begin
+
+ -- Check that the function To_C produces a wchar_array result with
+ -- lower bound of 0, and length dependent upon the Item and
+ -- Append_Nul parameters (if Append_Nul is True, length is
+ -- Item'Length + 1; if False, length is Item'Length).
+
+ if TC_No_wide_nul'First /= 0 or TC_wide_nul_Appended'First /= 0 then
+ Report.Failed("Incorrect lower bound from Function To_C");
+ end if;
+
+ if TC_No_wide_nul'Length /= TC_Wide_String'Length then
+ Report.Failed("Incorrect length returned from Function To_C " &
+ "when Append_Nul => False");
+ end if;
+
+ if TC_wide_nul_Appended'Length /= TC_Wide_String'Length + 1 then
+ Report.Failed("Incorrect length returned from Function To_C " &
+ "when Append_Nul => True");
+ end if;
+
+ if not Is_Nul_Terminated(TC_wide_nul_Appended) then
+ Report.Failed("No wide_nul appended to the wide_string " &
+ "parameter during conversion to wchar_array " &
+ "by function To_C");
+ end if;
+
+ for TC_char in Report.Ident_Char('a')..Report.Ident_Char('h') loop
+ if TC_No_wide_nul(i) /= To_C(To_Wide_Character(TC_char)) or
+ TC_wide_nul_Appended(i) /= To_C(To_Wide_Character(TC_char)) then
+ -- Use single character To_C.
+ Incorrect_Conversion := True;
+ end if;
+ i := i + 1;
+ end loop;
+
+ if Incorrect_Conversion then
+ Report.Failed("Incorrect result from To_C with wide_string input " &
+ "and wchar_array result");
+ end if;
+
+
+ -- Check that the function To_Ada produces a wide_string result with
+ -- lower bound of 1, and length dependent upon the Item and
+ -- Trim_Nul parameters (if Trim_Nul is False, length is Item'Length;
+ -- if False, length will be the length of the slice of Item prior to
+ -- the first wide_nul).
+
+ declare
+ TC_No_NUL_Wide_String : constant Wide_String :=
+ To_Ada(Item => TC_wide_nul_Appended, Trim_Nul => True);
+
+ TC_NUL_Appended_Wide_String : constant Wide_String :=
+ To_Ada(TC_wide_nul_Appended, False);
+
+ begin
+
+ if TC_No_NUL_Wide_String'First /= 1 or
+ TC_NUL_Appended_Wide_String'First /= 1
+ then
+ Report.Failed("Incorrect lower bound from Function To_Ada");
+ end if;
+
+ if TC_No_NUL_Wide_String'Length /= TC_Wide_String'Length then
+ Report.Failed("Incorrect length returned from Function " &
+ "To_Ada when Trim_Nul => True");
+ end if;
+
+ if TC_NUL_Appended_Wide_String'Length /=
+ TC_Wide_String'Length + 1
+ then
+ Report.Failed("Incorrect length returned from Function " &
+ "To_Ada when Trim_Nul => False");
+ end if;
+
+ for TC_Character in Wide_Character'('a') .. Wide_Character'('h') loop
+ if TC_No_NUL_Wide_String(j) /= TC_Character or
+ TC_NUL_Appended_Wide_String(j) /= TC_Character
+ then
+ Report.Failed("Incorrect result from To_Ada with " &
+ "char_array input, index = " &
+ Integer'Image(j));
+ end if;
+ j := j + 1;
+ end loop;
+
+ end;
+
+
+ -- Check that the function To_Ada raises Terminator_Error if the
+ -- parameter Trim_Nul is set to True, but the actual Item parameter
+ -- does not contain the wide_nul wchar_t.
+
+ begin
+ TC_Wide_String := To_Ada(TC_No_wide_nul, Trim_Nul => True);
+ Report.Failed("Terminator_Error not raised when Item " &
+ "parameter of To_Ada does not contain the " &
+ "wide_nul wchar_t, but parameter Trim_Nul " &
+ "=> True");
+ Report.Comment
+ (To_String(TC_Wide_String) & " printed to defeat optimization");
+ exception
+ when Terminator_Error => null; -- OK, expected exception.
+ when others =>
+ Report.Failed("Incorrect exception raised by function " &
+ "To_Ada when the Item parameter does not " &
+ "contain the wide_nul wchar_t, but " &
+ "parameter Trim_Nul => True");
+ end;
+
+ end;
+
+ exception
+ when The_Error : others =>
+ Report.Failed
+ ("The following exception was raised in the Test_Block: " &
+ Ada.Exceptions.Exception_Name(The_Error));
+ end Test_Block;
+
+ Report.Result;
+
+end CXB30061;
diff --git a/gcc/testsuite/ada/acats/tests/cxf/cxf2001.a b/gcc/testsuite/ada/acats/tests/cxf/cxf2001.a
index 96d0a0a..a9f4bb2 100644
--- a/gcc/testsuite/ada/acats/tests/cxf/cxf2001.a
+++ b/gcc/testsuite/ada/acats/tests/cxf/cxf2001.a
@@ -3,22 +3,22 @@
-- Grant of Unlimited Rights
--
-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
+-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
-- unlimited rights in the software and documentation contained herein.
--- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
--- this public release, the Government intends to confer upon all
--- recipients unlimited rights equal to those held by the Government.
--- These rights include rights to use, duplicate, release or disclose the
--- released technical data and computer software in whole or in part, in
--- any manner and for any purpose whatsoever, and to have or permit others
+-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
+-- this public release, the Government intends to confer upon all
+-- recipients unlimited rights equal to those held by the Government.
+-- These rights include rights to use, duplicate, release or disclose the
+-- released technical data and computer software in whole or in part, in
+-- any manner and for any purpose whatsoever, and to have or permit others
-- to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
+-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
+-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--*
@@ -31,33 +31,33 @@
--
-- TEST DESCRIPTION:
-- This test is designed to test the generic procedure Divide found in
--- package Ada.Decimal.
+-- package Ada.Decimal.
--
--- The table below attempts to portray the design approach used in this
+-- The table below attempts to portray the design approach used in this
-- test. There are three "dimensions" of concern:
-- 1) the delta value of the Quotient and Remainder types, shown as
-- column headers,
-- 2) specific choices for the Dividend and Divisor numerical values
-- (i.e., whether they yielded a repeating/non-terminating result,
--- or a terminating result ["exact"]), displayed on the left side
+-- or a terminating result ["exact"]), displayed on the left side
-- of the tables, and
-- 3) the delta for the Dividend and Divisor.
---
+--
-- Each row in the tables indicates a specific test case, showing the
-- specific quotient and remainder (under the appropriate Delta column)
-- for each combination of dividend and divisor values. Test cases
-- follow the top-to-bottom sequence shown in the tables.
---
+--
-- Most of the test case sets (same dividend/divisor combinations -
--- indicated by dashed horizontal lines in the tables) vary the
--- delta of the quotient and remainder types between test cases. This
+-- indicated by dashed horizontal lines in the tables) vary the
+-- delta of the quotient and remainder types between test cases. This
-- allows for an examination of how different deltas for a quotient
-- and/or remainder type can influence the results of a division with
-- identical dividend and divisor.
---
+--
-- Note: Test cases are performed for both Radix 10 and Radix 2 types.
---
---
+--
+--
-- Divid Divis Delta Delta Delta Delta Delta
-- (Delta)(Delta)| .1 | .01 | .001 | .0001 | .00001 |Test
-- |---|---|-----|-----|-----|-----|-----|-----|-----|-----|Case
@@ -88,14 +88,14 @@
-- ---------------------------------------------------------------------------
-- Divide by Zero| Raise Constraint_Error 41
-- ---------------------------------------------------------------------------
---
---
+--
+--
-- CHANGE HISTORY:
-- 06 Dec 94 SAIC ACVC 2.0
-- 29 Dec 94 SAIC Modified Radix 2 cases to match Radix 10 cases.
--- 03 Oct 95 RBKD Modified to fix incorrect remainder results
+-- 03 Oct 95 RBKD Modified to fix incorrect remainder results.
-- 15 Nov 95 SAIC Incorporated reviewer fixes for ACVC 2.0.1.
---
+-- 18 Dec 06 RLB Fixed failure message to have correct block name.
--!
with Report;
@@ -117,12 +117,12 @@ begin
-- Declare all types and variables used in the various blocks below
-- for all Radix 10 evaluations.
- type DT_1 is delta 1.0 digits 5;
- type DT_0_1 is delta 0.1 digits 10;
- type DT_0_01 is delta 0.01 digits 10;
- type DT_0_001 is delta 0.001 digits 10;
- type DT_0_0001 is delta 0.0001 digits 10;
- type DT_0_00001 is delta 0.00001 digits 10;
+ type DT_1 is delta 1.0 digits 5;
+ type DT_0_1 is delta 0.1 digits 10;
+ type DT_0_01 is delta 0.01 digits 10;
+ type DT_0_001 is delta 0.001 digits 10;
+ type DT_0_0001 is delta 0.0001 digits 10;
+ type DT_0_00001 is delta 0.00001 digits 10;
for DT_1'Machine_Radix use 10;
for DT_0_1'Machine_Radix use 10;
@@ -138,11 +138,11 @@ begin
Dd_0_0001, Dv_0_0001, Quot_0_0001, Rem_0_0001 : DT_0_0001 := 0.0;
Dd_0_00001, Dv_0_00001, Quot_0_00001, Rem_0_00001 : DT_0_00001 := 0.0;
- begin
+ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(Dividend_Type => DT_0_01,
Divisor_Type => DT_0_1,
Quotient_Type => DT_0_1,
@@ -158,7 +158,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_1, DT_0_1);
begin
if TC_Verbose then Report.Comment("Case 2"); end if;
@@ -171,7 +171,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_01, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 3"); end if;
@@ -184,7 +184,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_01, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 4"); end if;
@@ -197,14 +197,14 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 5"); end if;
Dd_0_01 := DT_0_01(0.05); Dv_0_1 := DT_0_1(0.3);
Div(Dd_0_01, Dv_0_1, Quot_0_001, Rem_0_0001);
- if Quot_0_001 /= DT_0_001(0.166) or
- Rem_0_0001 /= DT_0_0001(0.0002)
+ if Quot_0_001 /= DT_0_001(0.166) or
+ Rem_0_0001 /= DT_0_0001(0.0002)
then
Report.Failed("Incorrect values returned, Case 5");
end if;
@@ -212,7 +212,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_01, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 6"); end if;
@@ -225,7 +225,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_01, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 7"); end if;
@@ -238,7 +238,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_01, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 8"); end if;
@@ -251,7 +251,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_001, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 9"); end if;
@@ -264,7 +264,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_001, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 10"); end if;
@@ -277,14 +277,14 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_0001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 11"); end if;
Dd_0_01 := DT_0_01(0.15); Dv_1 := DT_1(20);
Div(Dd_0_01, Dv_1, Quot_0_0001, Rem_0_0001);
- if Quot_0_0001 /= DT_0_0001(0.0075) or
- Rem_0_0001 /= DT_0_0001(0.0)
+ if Quot_0_0001 /= DT_0_0001(0.0075) or
+ Rem_0_0001 /= DT_0_0001(0.0)
then
Report.Failed("Incorrect values returned, Case 11");
end if;
@@ -292,14 +292,14 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_0001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 12"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_0001, Rem_0_0001);
- if Quot_0_0001 /= DT_0_0001(0.0625) or
- Rem_0_0001 /= DT_0_0001(0.0)
+ if Quot_0_0001 /= DT_0_0001(0.0625) or
+ Rem_0_0001 /= DT_0_0001(0.0)
then
Report.Failed("Incorrect values returned, Case 12");
end if;
@@ -307,13 +307,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_00001);
begin
if TC_Verbose then Report.Comment("Case 13"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_001, Rem_0_00001);
- if Quot_0_001 /= DT_0_001(0.062) or
+ if Quot_0_001 /= DT_0_001(0.062) or
Rem_0_00001 /= DT_0_00001(0.00025)
then
Report.Failed("Incorrect values returned, Case 13");
@@ -322,13 +322,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 14"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_001, Rem_0_0001);
- if Quot_0_001 /= DT_0_001(0.062) or
+ if Quot_0_001 /= DT_0_001(0.062) or
Rem_0_0001 /= DT_0_0001(0.0002)
then
Report.Failed("Incorrect values returned, Case 14");
@@ -337,7 +337,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 15"); end if;
@@ -351,7 +351,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 16"); end if;
@@ -364,13 +364,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_00001);
begin
if TC_Verbose then Report.Comment("Case 17"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_01, Rem_0_00001);
- if Quot_0_01 /= DT_0_01(0.06) or Rem_0_00001 /= DT_0_00001(0.00125)
+ if Quot_0_01 /= DT_0_01(0.06) or Rem_0_00001 /= DT_0_00001(0.00125)
then
Report.Failed("Incorrect values returned, Case 17");
end if;
@@ -378,13 +378,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 18"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_01, Rem_0_0001);
- if Quot_0_01 /= DT_0_01(0.06) or Rem_0_0001 /= DT_0_0001(0.0012)
+ if Quot_0_01 /= DT_0_01(0.06) or Rem_0_0001 /= DT_0_0001(0.0012)
then
Report.Failed("Incorrect values returned, Case 18");
end if;
@@ -392,7 +392,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 19"); end if;
@@ -405,7 +405,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 20"); end if;
@@ -429,12 +429,12 @@ begin
-- Declare all types and variables used in the various blocks below
-- for all Radix 2 evaluations.
- type DT_1 is delta 1.0 digits 5;
- type DT_0_1 is delta 0.1 digits 10;
- type DT_0_01 is delta 0.01 digits 10;
- type DT_0_001 is delta 0.001 digits 10;
- type DT_0_0001 is delta 0.0001 digits 10;
- type DT_0_00001 is delta 0.00001 digits 10;
+ type DT_1 is delta 1.0 digits 5;
+ type DT_0_1 is delta 0.1 digits 10;
+ type DT_0_01 is delta 0.01 digits 10;
+ type DT_0_001 is delta 0.001 digits 10;
+ type DT_0_0001 is delta 0.0001 digits 10;
+ type DT_0_00001 is delta 0.00001 digits 10;
for DT_1'Machine_Radix use 2;
for DT_0_1'Machine_Radix use 2;
@@ -450,11 +450,11 @@ begin
Dd_0_0001, Dv_0_0001, Quot_0_0001, Rem_0_0001 : DT_0_0001 := 0.0;
Dd_0_00001, Dv_0_00001, Quot_0_00001, Rem_0_00001 : DT_0_00001 := 0.0;
- begin
+ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(Dividend_Type => DT_0_01,
Divisor_Type => DT_0_1,
Quotient_Type => DT_0_1,
@@ -470,7 +470,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_1, DT_0_1);
begin
if TC_Verbose then Report.Comment("Case 22"); end if;
@@ -483,7 +483,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_01, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 23"); end if;
@@ -496,7 +496,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_01, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 24"); end if;
@@ -509,14 +509,14 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_0_1, DT_0_001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 25"); end if;
Dd_0_01 := DT_0_01(0.05); Dv_0_1 := DT_0_1(0.3);
Div(Dd_0_01, Dv_0_1, Quot_0_001, Rem_0_0001);
- if Quot_0_001 /= DT_0_001(0.166) or
- Rem_0_0001 /= DT_0_0001(0.0002)
+ if Quot_0_001 /= DT_0_001(0.166) or
+ Rem_0_0001 /= DT_0_0001(0.0002)
then
Report.Failed("Incorrect values returned, Case 25");
end if;
@@ -524,7 +524,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_01, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 26"); end if;
@@ -537,7 +537,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_01, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 27"); end if;
@@ -550,7 +550,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_01, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 28"); end if;
@@ -563,7 +563,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_001, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 29"); end if;
@@ -576,7 +576,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_001, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 30"); end if;
@@ -589,14 +589,14 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_01, DT_1, DT_0_0001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 31"); end if;
Dd_0_01 := DT_0_01(0.15); Dv_1 := DT_1(20);
Div(Dd_0_01, Dv_1, Quot_0_0001, Rem_0_0001);
- if Quot_0_0001 /= DT_0_0001(0.0075) or
- Rem_0_0001 /= DT_0_0001(0.0)
+ if Quot_0_0001 /= DT_0_0001(0.0075) or
+ Rem_0_0001 /= DT_0_0001(0.0)
then
Report.Failed("Incorrect values returned, Case 31");
end if;
@@ -604,14 +604,14 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_0001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 32"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_0001, Rem_0_0001);
- if Quot_0_0001 /= DT_0_0001(0.0625) or
- Rem_0_0001 /= DT_0_0001(0.0)
+ if Quot_0_0001 /= DT_0_0001(0.0625) or
+ Rem_0_0001 /= DT_0_0001(0.0)
then
Report.Failed("Incorrect values returned, Case 32");
end if;
@@ -619,13 +619,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_00001);
begin
if TC_Verbose then Report.Comment("Case 33"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_001, Rem_0_00001);
- if Quot_0_001 /= DT_0_001(0.062) or
+ if Quot_0_001 /= DT_0_001(0.062) or
Rem_0_00001 /= DT_0_00001(0.00025)
then
Report.Failed("Incorrect values returned, Case 33");
@@ -634,13 +634,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 34"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_001, Rem_0_0001);
- if Quot_0_001 /= DT_0_001(0.062) or
+ if Quot_0_001 /= DT_0_001(0.062) or
Rem_0_0001 /= DT_0_0001(0.0002)
then
Report.Failed("Incorrect values returned, Case 34");
@@ -649,7 +649,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 35"); end if;
@@ -663,7 +663,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_001, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 36"); end if;
@@ -676,13 +676,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_00001);
begin
if TC_Verbose then Report.Comment("Case 37"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_01, Rem_0_00001);
- if Quot_0_01 /= DT_0_01(0.06) or Rem_0_00001 /= DT_0_00001(0.00125)
+ if Quot_0_01 /= DT_0_01(0.06) or Rem_0_00001 /= DT_0_00001(0.00125)
then
Report.Failed("Incorrect values returned, Case 37");
end if;
@@ -690,13 +690,13 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 38"); end if;
Dd_0_00001 := DT_0_00001(0.03125); Dv_0_1 := DT_0_1(0.5);
Div(Dd_0_00001, Dv_0_1, Quot_0_01, Rem_0_0001);
- if Quot_0_01 /= DT_0_01(0.06) or Rem_0_0001 /= DT_0_0001(0.0012)
+ if Quot_0_01 /= DT_0_01(0.06) or Rem_0_0001 /= DT_0_0001(0.0012)
then
Report.Failed("Incorrect values returned, Case 38");
end if;
@@ -704,7 +704,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_001);
begin
if TC_Verbose then Report.Comment("Case 39"); end if;
@@ -717,7 +717,7 @@ begin
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_00001, DT_0_1, DT_0_01, DT_0_01);
begin
if TC_Verbose then Report.Comment("Case 40"); end if;
@@ -729,24 +729,24 @@ begin
end;
declare
- procedure Div is
+ procedure Div is
new Ada.Decimal.Divide(DT_0_0001, DT_1, DT_0_0001, DT_0_0001);
begin
if TC_Verbose then Report.Comment("Case 41"); end if;
- Dd_0_0001 := (DT_0_0001(6062.0) / DT_0_0001(16384.0));
+ Dd_0_0001 := (DT_0_0001(6062.0) / DT_0_0001(16384.0));
Dv_1 := DT_1(0.0);
Div(Dd_0_0001, Dv_1, Quot_0_0001, Rem_0_0001);
Report.Failed("Divide by Zero didn't raise Constraint_Error, " &
"Case 41");
exception
when Constraint_Error => null; -- OK, expected exception.
- when others =>
+ when others =>
Report.Failed("Unexpected exception raised by Divide by Zero," &
"Case 41");
end;
exception
- when others => Report.Failed("Exception raised in Radix_10_Block");
+ when others => Report.Failed("Exception raised in Radix_2_Block");
end Radix_2_Block;
diff --git a/gcc/testsuite/c-c++-common/Wfree-nonheap-object-2.c b/gcc/testsuite/c-c++-common/Wfree-nonheap-object-2.c
new file mode 100644
index 0000000..0aedf1b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wfree-nonheap-object-2.c
@@ -0,0 +1,52 @@
+/* PR middle-end/98166: bogus -Wmismatched-dealloc on user-defined allocator
+ and inlining
+ Verify that the allocator can be declared inline without a warning when
+ it's associated with a standard deallocator. Associating an inline
+ deallocator with an allocator would cause false positives when the former
+ calls a deallocation function the allocator isn't associated with, so
+ that triggers a warning on declaration.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+__attribute__ ((malloc (__builtin_free)))
+inline int*
+alloc_int (int n)
+{
+ return (int*)__builtin_malloc (n + sizeof (int));
+}
+
+void test_nowarn_int (int n)
+{
+ {
+ int *p = alloc_int (n);
+ __builtin_free (p);
+ }
+
+ {
+ int *p = alloc_int (n);
+ __builtin_free (p + 1); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+inline void
+dealloc_long (long *p)
+{
+ __builtin_free (p); // { dg-warning "'__builtin_free|void __builtin_free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+}
+
+__attribute__ ((malloc (dealloc_long)))
+long* alloc_long (int); // { dg-warning "'malloc \\\(dealloc_long\\\)' attribute ignored with deallocation functions declared 'inline'" }
+
+void test_nowarn_long (int n)
+{
+ {
+ long *p = alloc_long (n);
+ dealloc_long (p);
+ }
+
+ {
+ long *p = alloc_long (n);
+ dealloc_long (p + 1);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/Wfree-nonheap-object-3.c b/gcc/testsuite/c-c++-common/Wfree-nonheap-object-3.c
new file mode 100644
index 0000000..41a5b50
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wfree-nonheap-object-3.c
@@ -0,0 +1,70 @@
+/* PR middle-end/98166: bogus -Wmismatched-dealloc on user-defined allocator
+ and inlining
+ Verify that without inlining, both the allocator and the deallocator
+ can be declared inline without a warning and that mismatched calls are
+ detected, but that declaring them always_inline does trigger a warning.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+__attribute__ ((malloc (__builtin_free)))
+inline int*
+alloc_int (int n)
+{
+ return (int*)__builtin_malloc (n + sizeof (int));
+}
+
+void test_nowarn_int (int n)
+{
+ {
+ int *p = alloc_int (n);
+ __builtin_free (p);
+ }
+
+ {
+ int *p = alloc_int (n);
+ __builtin_free (p + 1); // { dg-warning "'__builtin_free|void __builtin_free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+ }
+}
+
+
+inline void
+dealloc_long (long *p) { __builtin_free (p); }
+
+__attribute__ ((malloc (dealloc_long)))
+long* alloc_long (int);
+
+void test_nowarn_long (int n)
+{
+ {
+ long *p = alloc_long (n);
+ dealloc_long (p);
+ }
+
+ {
+ long *p = alloc_long (n);
+ dealloc_long (p + 1); // { dg-warning "'dealloc_long' called on pointer 'p|<unknown>' with nonzero offset" }
+ }
+}
+
+
+inline __attribute__ ((always_inline)) void
+dealloc_float (float *p) // { dg-message "deallocation function declared here" }
+{
+ __builtin_free (p); // { dg-warning "'__builtin_free|void __builtin_free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+}
+
+__attribute__ ((malloc (dealloc_float)))
+float* alloc_float (int); // { dg-warning "'malloc \\(dealloc_float\\)' attribute ignored with deallocation functions declared 'inline'" }
+
+void test_nowarn_float (int n)
+{
+ {
+ float *p = alloc_float (n);
+ dealloc_float (p);
+ }
+
+ {
+ float *p = alloc_float (n);
+ dealloc_float (p + 2);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/Wfree-nonheap-object.c b/gcc/testsuite/c-c++-common/Wfree-nonheap-object.c
new file mode 100644
index 0000000..dfbb296
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wfree-nonheap-object.c
@@ -0,0 +1,50 @@
+/* Verify that built-in forms of functions can be used interchangeably
+ with their ordinary (library) forms in attribute malloc.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+char* f (void) __attribute__ ((malloc (__builtin_free)));
+
+#if __cplusplus
+extern "C" {
+#endif
+
+void free (void*);
+
+#if __cplusplus
+}
+#endif
+
+char* g (void) __attribute__ ((malloc (free)));
+
+
+void test_nowarm (void)
+{
+ char *p = f ();
+ free (p);
+
+ p = g ();
+ free (p);
+
+ p = f ();
+ __builtin_free (p);
+
+ p = g ();
+ __builtin_free (p);
+}
+
+
+void test_warn (void)
+{
+ char *p = f ();
+ free (p + 1); // { dg-warning "'free|void free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+
+ p = g ();
+ free (p + 2); // { dg-warning "'free|void free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+
+ p = f ();
+ __builtin_free (p + 3); // { dg-warning "'__builtin_free|void __builtin_free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+
+ p = g ();
+ __builtin_free (p + 4); // { dg-warning "'__builtin_free|void __builtin_free\\(void\\*\\)' called on pointer 'p|<unknown>' with nonzero offset" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c
index d37a840..bc0cd0f 100644
--- a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c
+++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-20.c
@@ -27,13 +27,13 @@ g (int i)
switch (i)
{
case -1:
- __attribute__((used)); /* { dg-warning "ignored|only attribute" } */
+ __attribute__((used)); /* { dg-warning "empty declaration|ignored" } */
default:
- __attribute__((used)); /* { dg-warning "ignored|only attribute" } */
+ __attribute__((used)); /* { dg-warning "empty declaration|ignored" } */
case 1:
return 6;
case 2 ... 4:
- __attribute__((used)); /* { dg-warning "ignored|only attribute" } */
+ __attribute__((used)); /* { dg-warning "empty declaration|ignored" } */
case 5:
return 7;
}
diff --git a/gcc/testsuite/c-c++-common/Wmismatched-dealloc.c b/gcc/testsuite/c-c++-common/Wmismatched-dealloc.c
new file mode 100644
index 0000000..27af2c2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmismatched-dealloc.c
@@ -0,0 +1,67 @@
+/* PR middle-end/98166: bogus -Wmismatched-dealloc on user-defined allocator
+ and inlining
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+
+void dealloc_shrt (short *p)
+{
+ /* A positive offset would be diagnosed but a negative one must
+ not be. */
+ __builtin_free (p - 1); // { dg-bogus "-Wmismatched-dealloc" }
+}
+
+__attribute__ ((malloc (dealloc_shrt)))
+short* alloc_shrt (int n) /* { return malloc (n) + 1; } */;
+
+void test_nowarn_shrt (int n)
+{
+ short *p = alloc_shrt (n);
+ dealloc_shrt (p);
+}
+
+
+void dealloc_int (int *p) /* { free (p - 1); } */;
+
+__attribute__ ((malloc (dealloc_int, 1)))
+int* alloc_int (int n)
+{
+ return (int*)__builtin_malloc (n) + 1;
+}
+
+void test_nowarn_int (int n)
+{
+ int *p = alloc_int (n);
+ dealloc_int (p); // { dg-bogus "-Wmismatched-dealloc" }
+}
+
+
+void dealloc_long (int, long *p) /* { free (p - 2); } */;
+
+__attribute__ ((malloc (dealloc_long, 2)))
+inline long*
+alloc_long (int n) { // { dg-warning "'malloc \\(\[^\n\r\]*dealloc_long\[^\n\r\]*\\)' attribute ignored on functions declared 'inline'" }
+ return (long*)__builtin_malloc (n) + 2;
+}
+
+void test_nowarn_long (int n)
+{
+ long *p = alloc_long (n);
+ dealloc_long (0, p); // { dg-bogus "\\\[-Wmismatched-dealloc" }
+}
+
+
+inline void
+dealloc_float (int, int, float *p) // { dg-message "deallocation function declared here" }
+{
+ __builtin_free (p - 3);
+}
+
+__attribute__ ((malloc (dealloc_float, 3)))
+float* alloc_float (int n); // { dg-warning "'malloc \\(\[^\n\r\]*dealloc_float\[^\n\r\]*\\)' attribute ignored with deallocation functions declared 'inline'" }
+
+void test_nowarn_float (int n)
+{
+ float *p = alloc_float (n);
+ dealloc_float (0, 1, p); // { dg-bogus "\\\[-Wmismatched-dealloc" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
index 7c7932e..1d79930 100644
--- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
+++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
@@ -1,7 +1,7 @@
/* PR middle-end/91458 - inconsistent warning for writing past the end
of an array member
{ dg-do compile }
- { dg-options "-O2 -Wall -Wno-array-bounds" } */
+ { dg-options "-O2 -Wall -Wno-array-bounds -fno-ipa-icf" } */
void sink (void*);
@@ -10,7 +10,7 @@ void sink (void*);
struct Ax
{
char n;
- char a[]; // { dg-message "declared here" }
+ char a[]; // { dg-message "destination object" "note" }
};
// Verify warning for a definition with no initializer.
@@ -91,7 +91,7 @@ void gaxx (void)
struct A0
{
char n;
- char a[0]; // { dg-message "declared here" }
+ char a[0]; // { dg-message "destination object" "note" }
};
// Verify warning for a definition with no initializer.
@@ -158,7 +158,7 @@ void ga0x (void)
struct A1
{
char n;
- char a[1]; // { dg-message "declared here" }
+ char a[1]; // { dg-message "destination object" "note" }
};
// Verify warning for a definition with no initializer.
@@ -256,7 +256,7 @@ void ga1x (void)
struct A1i
{
char n;
- char a[1]; // { dg-message "declared here" }
+ char a[1]; // { dg-message "destination object" }
char x;
};
diff --git a/gcc/testsuite/c-c++-common/Wunused-value-1.c b/gcc/testsuite/c-c++-common/Wunused-value-1.c
new file mode 100644
index 0000000..90c9d93
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wunused-value-1.c
@@ -0,0 +1,33 @@
+/* PR c/97748 */
+/* { dg-do compile } */
+/* { dg-options "-Wunused-value" } */
+
+double _Complex f ();
+double _Complex *p;
+
+double _Complex
+foo (double _Complex x)
+{
+ ++x; /* { dg-bogus "value computed is not used" } */
+ --x; /* { dg-bogus "value computed is not used" } */
+ x += 1; /* { dg-bogus "value computed is not used" } */
+ x += 1.0iF; /* { dg-bogus "value computed is not used" } */
+ x++; /* { dg-bogus "value computed is not used" } */
+ x--; /* { dg-bogus "value computed is not used" } */
+ x + 1; /* { dg-warning "value computed is not used" } */
+ (void) (x + 1); /* { dg-bogus "value computed is not used" } */
+ 1 + f (); /* { dg-warning "value computed is not used" } */
+ f () + f (); /* { dg-warning "value computed is not used" } */
+ f () + f (), f (); /* { dg-warning "value computed is not used" } */
+ f ();
+ (void) f ();
+ *p++; /* { dg-warning "value computed is not used" } */
+ ++*p; /* { dg-bogus "value computed is not used" } */
+ (*p ? f () : 0);
+ ({ f (); });
+ ({ f () + 1; });
+ ({ f (); 0; });
+ ({ f () + 1; 0; }); /* { dg-warning "value computed is not used" } */
+ 1 + ({ f (); }); /* { dg-warning "value computed is not used" } */
+ return x;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/pointer-compare-1.c b/gcc/testsuite/c-c++-common/asan/pointer-compare-1.c
index 1ce349e..4b558bf 100644
--- a/gcc/testsuite/c-c++-common/asan/pointer-compare-1.c
+++ b/gcc/testsuite/c-c++-common/asan/pointer-compare-1.c
@@ -14,12 +14,13 @@ foo (char *p, char *q)
v = p > q;
}
-char global1[100] = {}, global2[100] = {};
+char __attribute__((used)) global1[100] = {};
+char __attribute__((used)) global2[100] = {};
char __attribute__((used)) smallest_global[5] = {};
-char small_global[7] = {};
+char __attribute__((used)) small_global[7] = {};
char __attribute__((used)) little_global[10] = {};
char __attribute__((used)) medium_global[4000] = {};
-char large_global[5000] = {};
+char __attribute__((used)) large_global[5000] = {};
char __attribute__((used)) largest_global[6000] = {};
int
diff --git a/gcc/testsuite/c-c++-common/asan/pr98204.c b/gcc/testsuite/c-c++-common/asan/pr98204.c
new file mode 100644
index 0000000..7532646
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr98204.c
@@ -0,0 +1,6 @@
+/* PR sanitizer/98204 */
+/* { dg-options "-fsanitize=address,pointer-subtract,pointer-compare" } */
+
+struct{int c;}v;
+static long i=((char*)&(v.c)-(char*)&v);
+static long i2=((char*)&(v.c)<(char*)&v);
diff --git a/gcc/testsuite/c-c++-common/asmgoto-2.c b/gcc/testsuite/c-c++-common/asmgoto-2.c
index 5bf4572..fb81cde 100644
--- a/gcc/testsuite/c-c++-common/asmgoto-2.c
+++ b/gcc/testsuite/c-c++-common/asmgoto-2.c
@@ -7,7 +7,7 @@ foo (void)
__label__ lab;
int i = 0;
asm goto ("" : : : : lab);
- asm goto ("" : "=r" (i) : : : lab); /* { dg-error "expected" } */
+ asm goto ("" : "=r" (i) : : : lab);
asm goto ("" : : : : ); /* { dg-error "expected" } */
asm goto ("" : : : "memory"); /* { dg-error "expected" } */
asm goto ("" : : : ); /* { dg-error "expected" } */
diff --git a/gcc/testsuite/c-c++-common/attr-fallthrough-2.c b/gcc/testsuite/c-c++-common/attr-fallthrough-2.c
index e8659e5..156b413 100644
--- a/gcc/testsuite/c-c++-common/attr-fallthrough-2.c
+++ b/gcc/testsuite/c-c++-common/attr-fallthrough-2.c
@@ -1,6 +1,6 @@
/* PR c/7652 */
/* { dg-do compile } */
-/* { dg-options "-Wall -Wextra -Wpedantic -Wno-unused -Wno-implicit-fallthrough" } */
+/* { dg-options "-Wall -Wextra -Wno-unused -Wno-implicit-fallthrough" } */
extern void bar (int);
void
@@ -34,7 +34,7 @@ fn (int i)
__attribute__((fallthrough ("x"))); /* { dg-warning "specified with a parameter" } */
case 7:
bar (1);
- __attribute__((fallthrough, fallthrough)); /* { dg-warning "attribute specified multiple times" } */
+ __attribute__((fallthrough, fallthrough)); /* { dg-warning "specified multiple times" } */
case 8:
bar (1);
__attribute__((fallthrough));
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b..eef2519 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@ void foo()
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 0000000..ca64197
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+static int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 0000000..1cbc4c7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-5.c b/gcc/testsuite/c-c++-common/attr-used-5.c
new file mode 100644
index 0000000..ba59326
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-5.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2" } */
+
+struct dtv_slotinfo_list
+{
+ struct dtv_slotinfo_list *next;
+};
+
+extern struct dtv_slotinfo_list *list;
+
+static int __attribute__ ((section ("__libc_freeres_fn")))
+free_slotinfo (struct dtv_slotinfo_list **elemp)
+/* { dg-warning "'.*' without 'used' attribute and '.*' with 'used' attribute are placed in a section with the same name" "" { target R_flag_in_section } .-1 } */
+{
+ if (!free_slotinfo (&(*elemp)->next))
+ return 0;
+ return 1;
+}
+
+__attribute__ ((used, section ("__libc_freeres_fn")))
+static void free_mem (void)
+{
+ free_slotinfo (&list);
+}
+
+/* { dg-final { scan-assembler "__libc_freeres_fn,\"ax\"" { target R_flag_in_section } } } */
+/* { dg-final { scan-assembler "__libc_freeres_fn,\"axR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-6.c b/gcc/testsuite/c-c++-common/attr-used-6.c
new file mode 100644
index 0000000..5d20f87
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-6.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2" } */
+
+struct dtv_slotinfo_list
+{
+ struct dtv_slotinfo_list *next;
+};
+
+extern struct dtv_slotinfo_list *list;
+
+static int __attribute__ ((used, section ("__libc_freeres_fn")))
+free_slotinfo (struct dtv_slotinfo_list **elemp)
+{
+ if (!free_slotinfo (&(*elemp)->next))
+ return 0;
+ return 1;
+}
+
+__attribute__ ((section ("__libc_freeres_fn")))
+void free_mem (void)
+/* { dg-warning "'.*' without 'used' attribute and '.*' with 'used' attribute are placed in a section with the same name" "" { target R_flag_in_section } .-1 } */
+{
+ free_slotinfo (&list);
+}
+
+/* { dg-final { scan-assembler "__libc_freeres_fn,\"ax\"" { target R_flag_in_section } } } */
+/* { dg-final { scan-assembler "__libc_freeres_fn,\"axR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-7.c b/gcc/testsuite/c-c++-common/attr-used-7.c
new file mode 100644
index 0000000..75576bc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-7.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2" } */
+
+int __attribute__((used,section(".data.foo"))) foo2 = 2;
+int __attribute__((section(".data.foo"))) foo1 = 1;
+/* { dg-warning "'.*' without 'used' attribute and '.*' with 'used' attribute are placed in a section with the same name" "" { target R_flag_in_section } .-1 } */
+
+/* { dg-final { scan-assembler ".data.foo,\"aw\"" { target R_flag_in_section } } } */
+/* { dg-final { scan-assembler ".data.foo,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-8.c b/gcc/testsuite/c-c++-common/attr-used-8.c
new file mode 100644
index 0000000..e4982db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-8.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2" } */
+
+int __attribute__((section(".data.foo"))) foo1 = 1;
+/* { dg-warning "'.*' without 'used' attribute and '.*' with 'used' attribute are placed in a section with the same name" "" { target R_flag_in_section } .-1 } */
+int __attribute__((used,section(".data.foo"))) foo2 = 2;
+
+/* { dg-final { scan-assembler ".data.foo,\"aw\"" { target R_flag_in_section } } } */
+/* { dg-final { scan-assembler ".data.foo,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-9.c b/gcc/testsuite/c-c++-common/attr-used-9.c
new file mode 100644
index 0000000..cf3bde6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-9.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2" } */
+
+struct dtv_slotinfo_list
+{
+ struct dtv_slotinfo_list *next;
+};
+
+extern struct dtv_slotinfo_list *list;
+
+static int __attribute__ ((used, section ("__libc_freeres_fn")))
+free_slotinfo (struct dtv_slotinfo_list **elemp)
+{
+ if (!free_slotinfo (&(*elemp)->next))
+ return 0;
+ return 1;
+}
+
+__attribute__ ((section ("__libc_freeres_fn")))
+static void free_mem (void)
+/* { dg-warning "defined but not used" "" { target *-*-* } .-1 } */
+{
+ free_slotinfo (&list);
+}
+
+/* { dg-final { scan-assembler-not "__libc_freeres_fn\n" } } */
+/* { dg-final { scan-assembler-not "__libc_freeres_fn,\"ax\"" { target R_flag_in_section } } } */
+/* { dg-final { scan-assembler "__libc_freeres_fn,\"axR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705a..2036533 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,4 @@ static void function_declaration_after(void) __attribute__((__used__));
/* { dg-final { scan-assembler "function_declaration_before" } } */
/* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\.text.*,\"axR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/builtin-clear-padding-1.c b/gcc/testsuite/c-c++-common/builtin-clear-padding-1.c
new file mode 100644
index 0000000..8b036bf
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-clear-padding-1.c
@@ -0,0 +1,19 @@
+/* PR libstdc++/88101 */
+/* { dg-do compile } */
+
+struct S;
+struct T { char a; long long b; };
+
+void
+foo (struct S *p, void *q, char *r, const struct T *s)
+{
+ __builtin_clear_padding (); /* { dg-error "too few arguments to function '__builtin_clear_padding'" } */
+ __builtin_clear_padding (1); /* { dg-error "argument 1 in call to function '__builtin_clear_padding' does not have pointer type" } */
+ __builtin_clear_padding (&p);
+ __builtin_clear_padding (&p, 1); /* { dg-error "too many arguments to function '__builtin_clear_padding'" } */
+ __builtin_clear_padding (&p, &p); /* { dg-error "too many arguments to function '__builtin_clear_padding'" } */
+ __builtin_clear_padding (p); /* { dg-error "argument 1 in call to function '__builtin_clear_padding' points to incomplete type" } */
+ __builtin_clear_padding (q); /* { dg-error "argument 1 in call to function '__builtin_clear_padding' points to incomplete type" } */
+ __builtin_clear_padding (r);
+ __builtin_clear_padding (s); /* { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to 'const' type" } */
+}
diff --git a/gcc/testsuite/c-c++-common/builtin-clear-padding-2.c b/gcc/testsuite/c-c++-common/builtin-clear-padding-2.c
new file mode 100644
index 0000000..67c03c8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-clear-padding-2.c
@@ -0,0 +1,17 @@
+/* PR middle-end/97943 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); };
+struct T { int a; struct S b; };
+union U { int a; struct S b; };
+struct V { int a; union U b; };
+
+void
+foo (struct S *s, struct T *t, union U *u, struct V *v)
+{
+ __builtin_clear_padding (s); /* { dg-error "flexible array member '(S::)?b' does not have well defined padding bits for '__builtin_clear_padding'" } */
+ __builtin_clear_padding (t); /* { dg-error "flexible array member '(S::)?b' does not have well defined padding bits for '__builtin_clear_padding'" } */
+ __builtin_clear_padding (u); /* { dg-error "flexible array member '(S::)?b' does not have well defined padding bits for '__builtin_clear_padding'" } */
+ __builtin_clear_padding (v); /* { dg-error "flexible array member '(S::)?b' does not have well defined padding bits for '__builtin_clear_padding'" } */
+}
diff --git a/gcc/testsuite/c-c++-common/builtin-clear-padding-3.c b/gcc/testsuite/c-c++-common/builtin-clear-padding-3.c
new file mode 100644
index 0000000..d16cc6a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-clear-padding-3.c
@@ -0,0 +1,15 @@
+/* PR middle-end/97943 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+union U { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); }; /* { dg-error "flexible array member in union" } */
+struct V { int a; union U b; };
+struct W { int a; union U b; int c; };
+
+void
+foo (union U *u, struct V *v, struct W *w)
+{
+ __builtin_clear_padding (u);
+ __builtin_clear_padding (v);
+ __builtin_clear_padding (w);
+}
diff --git a/gcc/testsuite/c-c++-common/cpp/wide-narrow-predef-macros.c b/gcc/testsuite/c-c++-common/cpp/wide-narrow-predef-macros.c
new file mode 100644
index 0000000..d5440f8a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/wide-narrow-predef-macros.c
@@ -0,0 +1,13 @@
+/*
+ { dg-do compile }
+ */
+
+#if !defined(__GNUC_EXECUTION_CHARSET_NAME)
+#error "Required implementation macro for comple-time charset name is not present"
+#endif
+#if !defined(__GNUC_WIDE_EXECUTION_CHARSET_NAME)
+#error "Required implementation macro for wide comple-time charset name is not present"
+#endif
+
+const char narrow_name[] = __GNUC_EXECUTION_CHARSET_NAME;
+const char wide_name[] = __GNUC_WIDE_EXECUTION_CHARSET_NAME;
diff --git a/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c b/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c
new file mode 100644
index 0000000..4d18f23
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc-gomp/atomic.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+#pragma omp requires atomic_default_mem_order(acq_rel)
+
+void
+foo ()
+{
+ int i, v;
+
+#pragma omp atomic read
+ i = v;
+
+#pragma acc atomic read
+ i = v;
+
+#pragma omp atomic write
+ i = v;
+
+#pragma acc atomic write
+ i = v;
+
+#pragma omp atomic update
+ i += 1;
+
+#pragma acc atomic update
+ i += 1;
+
+#pragma omp atomic capture
+ v = i += 1;
+
+#pragma acc atomic capture
+ v = i += 1;
+#pragma acc atomic update capture
+ v = i += 1;
+}
+
+/* { dg-final { scan-tree-dump-times "i = #pragma omp atomic read acquire" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "i = #pragma omp atomic read relaxed" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp atomic release" 2 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp atomic relaxed" 2 "original" } } */
+/* { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture acq_rel" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture relaxed" 2 "original" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/atomic.c b/gcc/testsuite/c-c++-common/goacc/atomic.c
new file mode 100644
index 0000000..ff3b25e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/atomic.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+
+void
+foo ()
+{
+ int i, v;
+#pragma acc atomic read bar /* { dg-error "expected 'read', 'write', 'update', or 'capture' clause" } */
+ i = v; /* { dg-error "expected end of line before 'bar'" "" { target *-*-* } .-1 } */
+
+#pragma acc atomic read write /* { dg-error "too many atomic clauses" } */
+ i = v;
+
+#pragma acc atomic read seq_cst /* { dg-error "expected 'read', 'write', 'update', or 'capture' clause" } */
+ i = v; /* { dg-error "expected end of line before 'seq_cst'" "" { target *-*-* } .-1 } */
+
+#pragma acc atomic read relaxed /* { dg-error "expected 'read', 'write', 'update', or 'capture' clause" } */
+ i = v; /* { dg-error "expected end of line before 'relaxed'" "" { target *-*-* } .-1 } */
+
+#pragma acc atomic update hint(1) /* { dg-error "expected 'read', 'write', 'update', or 'capture' clause" } */
+ i += 1; /* { dg-error "expected end of line before 'hint'" "" { target *-*-* } .-1 } */
+
+#pragma acc atomic update update capture /* { dg-error "too many atomic clauses" } */
+ v = i += 1;
+
+#pragma acc atomic update capture capture /* { dg-error "too many atomic clauses" } */
+ v = i += 1;
+
+#pragma acc atomic write capture /* { dg-error "too many atomic clauses" } */
+ i = 1;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/cache-1.c b/gcc/testsuite/c-c++-common/goacc/cache-1.c
index 1d4759e..242f3c6 100644
--- a/gcc/testsuite/c-c++-common/goacc/cache-1.c
+++ b/gcc/testsuite/c-c++-common/goacc/cache-1.c
@@ -1,9 +1,15 @@
-/* OpenACC cache directive: valid usage. */
-/* For execution testing, this file is "#include"d from
- libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c. */
+/* OpenACC 'cache' directive: valid usage. */
-int
-main (int argc, char **argv)
+/* See also corresponding C++ variant: '../../g++.dg/goacc/cache-1.C'. */
+
+/* For execution testing, this file is '#include'd from
+ '../../../../libgomp/testsuite/libgomp.oacc-c-c++-common/cache-1.c'. */
+
+#ifdef TEMPLATIZE
+template <int N>
+#endif
+static void
+test ()
{
#define N 2
int a[N], b[N];
@@ -61,6 +67,4 @@ main (int argc, char **argv)
if (a[i] != b[i])
__builtin_abort ();
}
-
- return 0;
}
diff --git a/gcc/testsuite/c-c++-common/goacc/cache-2.c b/gcc/testsuite/c-c++-common/goacc/cache-2.c
index d1181d1..80b925e 100644
--- a/gcc/testsuite/c-c++-common/goacc/cache-2.c
+++ b/gcc/testsuite/c-c++-common/goacc/cache-2.c
@@ -1,7 +1,9 @@
-/* OpenACC cache directive: invalid usage. */
+/* OpenACC 'cache' directive: invalid usage. */
-int
-main (int argc, char **argv)
+/* See also corresponding C++ variant: '../../g++.dg/goacc/cache-2.C'. */
+
+static void
+test ()
{
#define N 2
int a[N], b[N];
@@ -52,6 +54,4 @@ main (int argc, char **argv)
if (a[i] != b[i])
__builtin_abort ();
}
-
- return 0;
}
diff --git a/gcc/testsuite/c-c++-common/goacc/cache-3-1.c b/gcc/testsuite/c-c++-common/goacc/cache-3-1.c
new file mode 100644
index 0000000..5318a57
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/cache-3-1.c
@@ -0,0 +1,116 @@
+/* Test 'cache' directive diagnostics. */
+
+/* See also corresponding C++ variant: '../../g++.dg/goacc/cache-3-1.C'. */
+
+/* See also corresponding C/C++ data clause variant: 'data-clause-1.c'. */
+
+/* { dg-additional-options "-fopenmp" } for '#pragma omp threadprivate'. */
+
+/* The current implementation doesn't restrict where a 'cache' directive may
+ appear, so we don't make any special arrangements. */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+int **q;
+int r[4][4][4][4][4];
+extern struct s s1;
+extern struct s s2[1]; /* { dg-error "array type has incomplete element type" "" { target c } } */
+int t[10];
+#pragma omp threadprivate (t)
+#pragma acc routine
+void bar (int *);
+
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma acc cache(bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma acc cache(t[2:5]) /* { dg-error "is threadprivate variable" } */
+ ;
+ #pragma acc cache(k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma acc cache(s1) /* { dg-error "expected '\\\['" } */
+ ;
+ #pragma acc cache(s2) /* { dg-error "expected '\\\['" } */
+ ;
+ #pragma acc cache(a[:][:]) /* { dg-error "array type length expression must be specified" } */
+ bar (&a[0][0]); /* { dg-bogus "referenced in target region does not have a mappable type" } */
+ #pragma acc cache(b[-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (b);
+ #pragma acc cache(c[:-3][:]) /* { dg-error "negative length in array section" } */
+ bar (&c[0][0]);
+ #pragma acc cache(d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (d);
+ #pragma acc cache(e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (e);
+ #pragma acc cache(f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (f);
+ #pragma acc cache(g[:][0:10]) /* { dg-error "for array function parameter length expression must be specified" } */
+ bar (&g[0][0]);
+ #pragma acc cache(h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (&h[0][0]);
+ #pragma acc cache(h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ bar (&h[0][0]);
+ #pragma acc cache(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (&i[0][0]);
+ #pragma acc cache(j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc cache(j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc cache(a2[:1][2:4])
+ bar (&a2[0][0]);
+ #pragma acc cache(a2[3:5][:])
+ bar (&a2[0][0]);
+ #pragma acc cache(a2[3:5][:10])
+ bar (&a2[0][0]);
+ #pragma acc cache(b2[0:])
+ bar (b2);
+ #pragma acc cache(c2[:3][:])
+ bar (&c2[0][0]);
+ #pragma acc cache(d2[9:])
+ bar (d2);
+ #pragma acc cache(e2[:10])
+ bar (e2);
+ #pragma acc cache(f2[1:9])
+ bar (f2);
+ #pragma acc cache(g2[:1][2:4])
+ bar (&g2[0][0]);
+ #pragma acc cache(h2[2:2][0:])
+ bar (&h2[0][0]);
+ #pragma acc cache(h2[:1][:3])
+ bar (&h2[0][0]);
+ #pragma acc cache(i2[:1][9:])
+ bar (&i2[0][0]);
+ #pragma acc cache(j2[3:4][:9])
+ bar (&j2[0][0]);
+ #pragma acc cache(j2[30:1][5:4])
+ bar (&j2[0][0]);
+ #pragma acc cache(q[1:2])
+ ;
+ #pragma acc cache(q[3:5][:10]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2])
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:][0:4])
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/cache-3-2.c b/gcc/testsuite/c-c++-common/goacc/cache-3-2.c
new file mode 100644
index 0000000..ea5222e7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/cache-3-2.c
@@ -0,0 +1,50 @@
+/* Test 'cache' directive diagnostics. */
+
+/* See also corresponding C++ variant: '../../g++.dg/goacc/cache-3-2.C'. */
+
+/* See also corresponding C/C++ data clause variant: 'data-clause-2.c'. */
+
+/* The current implementation doesn't restrict where a 'cache' directive may
+ appear, so we don't make any special arrangements. */
+
+void
+foo (int *p, int (*q)[10], int r[10], int s[10][10])
+{
+ int a[10], b[10][10];
+ #pragma acc cache (p[-1:2])
+ ;
+ #pragma acc cache (q[-1:2][0:10])
+ ;
+ #pragma acc cache (q[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (r[-1:2])
+ ;
+ #pragma acc cache (s[-1:2][:])
+ ;
+ #pragma acc cache (s[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (a[-1:2]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (b[-1:2][0:]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (b[1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (p[2:-3]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (q[2:-3][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (q[2:3][0:-1]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (r[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (s[2:-5][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (s[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (a[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (b[2:-5][0:10]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (b[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/classify-parallel.c b/gcc/testsuite/c-c++-common/goacc/classify-parallel.c
index 66a6d13..933d766 100644
--- a/gcc/testsuite/c-c++-common/goacc/classify-parallel.c
+++ b/gcc/testsuite/c-c++-common/goacc/classify-parallel.c
@@ -20,10 +20,10 @@ void PARALLEL ()
}
/* Check the offloaded function's attributes.
- { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp target entrypoint\\)\\)" 1 "ompexp" } } */
+ { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc parallel, omp target entrypoint\\)\\)" 1 "ompexp" } } */
/* Check the offloaded function's classification and compute dimensions (will
always be 1 x 1 x 1 for non-offloading compilation).
{ dg-final { scan-tree-dump-times "(?n)Function is OpenACC parallel offload" 1 "oaccdevlow" } }
{ dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
- { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), omp target entrypoint\\)\\)" 1 "oaccdevlow" } } */
+ { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc parallel, omp target entrypoint\\)\\)" 1 "oaccdevlow" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/classify-serial.c b/gcc/testsuite/c-c++-common/goacc/classify-serial.c
new file mode 100644
index 0000000..94ace1b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/classify-serial.c
@@ -0,0 +1,29 @@
+/* Check offloaded function's attributes and classification for OpenACC
+ serial. */
+
+/* { dg-additional-options "-O2" }
+ { dg-additional-options "-fopt-info-optimized-omp" }
+ { dg-additional-options "-fdump-tree-ompexp" }
+ { dg-additional-options "-fdump-tree-oaccdevlow" } */
+
+#define N 1024
+
+extern unsigned int *__restrict a;
+extern unsigned int *__restrict b;
+extern unsigned int *__restrict c;
+
+void SERIAL ()
+{
+#pragma acc serial loop copyin (a[0:N], b[0:N]) copyout (c[0:N]) /* { dg-message "optimized: assigned OpenACC gang vector loop parallelism" } */
+ for (unsigned int i = 0; i < N; i++)
+ c[i] = a[i] + b[i];
+}
+
+/* Check the offloaded function's attributes.
+ { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc serial, omp target entrypoint\\)\\)" 1 "ompexp" } } */
+
+/* Check the offloaded function's classification and compute dimensions (will
+ always be 1 x 1 x 1 for non-offloading compilation).
+ { dg-final { scan-tree-dump-times "(?n)Function is OpenACC serial offload" 1 "oaccdevlow" } }
+ { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
+ { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc serial, omp target entrypoint\\)\\)" 1 "oaccdevlow" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/clause-locations.c b/gcc/testsuite/c-c++-common/goacc/clause-locations.c
deleted file mode 100644
index 913988d..0000000
--- a/gcc/testsuite/c-c++-common/goacc/clause-locations.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Verify that the location information for clauses is correct. */
-
-void
-check_clause_columns() {
- int i, j, sum, diff;
-
- #pragma acc parallel
- {
- #pragma acc loop reduction(+:sum)
- for (i = 1; i <= 10; i++)
- {
- #pragma acc loop reduction(-:diff) reduction(-:sum)
- /* { dg-warning "53: conflicting reduction operations for .sum." "" { target c } .-1 } */
- /* { dg-warning "56: conflicting reduction operations for .sum." "" { target c++ } .-2 } */
- for (j = 1; j <= 10; j++)
- sum = 1;
- }
- }
-}
diff --git a/gcc/testsuite/c-c++-common/goacc/data-clause-1.c b/gcc/testsuite/c-c++-common/goacc/data-clause-1.c
new file mode 100644
index 0000000..9952ac4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/data-clause-1.c
@@ -0,0 +1,115 @@
+/* Test data clause diagnostics. */
+
+/* See also corresponding OpenACC C++ variant: '../../g++.dg/goacc/data-clause-1.C'. */
+
+/* See also corresponding OpenACC 'cache' directive variant: 'cache-3-1.c'. */
+
+/* See also corresponding OpenMP variant: '../gomp/map-1.c'. */
+
+/* { dg-additional-options "-fopenmp" } for '#pragma omp threadprivate'. */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+int **q;
+int r[4][4][4][4][4];
+extern struct s s1;
+extern struct s s2[1]; /* { dg-error "array type has incomplete element type" "" { target c } } */
+int t[10];
+#pragma omp threadprivate (t)
+#pragma acc routine
+void bar (int *);
+
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma acc parallel copyin(bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma acc parallel copyout(t[2:5]) /* { dg-error "is threadprivate variable" } */
+ ;
+ #pragma acc parallel copy(k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copyout(l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copyin(m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copy(n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copyin(o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma acc parallel create(s1) /* { dg-error "'s1' does not have a mappable type in 'map' clause" } */
+ ;
+ #pragma acc parallel create(s2) /* { dg-error "'s2' does not have a mappable type in 'map' clause" } */
+ ;
+ #pragma acc parallel copyin(a[:][:]) /* { dg-error "array type length expression must be specified" } */
+ bar (&a[0][0]); /* { dg-error "referenced in target region does not have a mappable type" } */
+ #pragma acc parallel copy(b[-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (b);
+ #pragma acc parallel copy(c[:-3][:]) /* { dg-error "negative length in array section" } */
+ bar (&c[0][0]);
+ #pragma acc parallel copyout(d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (d);
+ #pragma acc parallel copyin(e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (e);
+ #pragma acc parallel copyin(f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (f);
+ #pragma acc parallel copyout(g[:][0:10]) /* { dg-error "for array function parameter length expression must be specified" } */
+ bar (&g[0][0]);
+ #pragma acc parallel copyout(h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (&h[0][0]);
+ #pragma acc parallel copy(h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ bar (&h[0][0]);
+ #pragma acc parallel copy(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (&i[0][0]);
+ #pragma acc parallel copyout(j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc parallel copyin(j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc parallel copyin(a2[:1][2:4])
+ bar (&a2[0][0]);
+ #pragma acc parallel copy(a2[3:5][:])
+ bar (&a2[0][0]);
+ #pragma acc parallel copyin(a2[3:5][:10])
+ bar (&a2[0][0]);
+ #pragma acc parallel copy(b2[0:])
+ bar (b2);
+ #pragma acc parallel copy(c2[:3][:])
+ bar (&c2[0][0]);
+ #pragma acc parallel copyout(d2[9:])
+ bar (d2);
+ #pragma acc parallel copyin(e2[:10])
+ bar (e2);
+ #pragma acc parallel copyin(f2[1:9])
+ bar (f2);
+ #pragma acc parallel copy(g2[:1][2:4])
+ bar (&g2[0][0]);
+ #pragma acc parallel copyout(h2[2:2][0:])
+ bar (&h2[0][0]);
+ #pragma acc parallel copy(h2[:1][:3])
+ bar (&h2[0][0]);
+ #pragma acc parallel copyin(i2[:1][9:])
+ bar (&i2[0][0]);
+ #pragma acc parallel copyout(j2[3:4][:9])
+ bar (&j2[0][0]);
+ #pragma acc parallel copyin(j2[30:1][5:4])
+ bar (&j2[0][0]);
+ #pragma acc parallel copy(q[1:2])
+ ;
+ #pragma acc parallel copy(q[3:5][:10]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2])
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:][0:4])
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/data-clause-2.c b/gcc/testsuite/c-c++-common/goacc/data-clause-2.c
new file mode 100644
index 0000000..d4603b0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/data-clause-2.c
@@ -0,0 +1,49 @@
+/* Test data clause diagnostics. */
+
+/* See also corresponding OpenACC C++ variant: '../../g++.dg/goacc/data-clause-2.C'. */
+
+/* See also corresponding OpenACC 'cache' directive variant: 'cache-3-2.c'. */
+
+/* See also corresponding OpenMP variant: '../gomp/map-2.c'. */
+
+void
+foo (int *p, int (*q)[10], int r[10], int s[10][10])
+{
+ int a[10], b[10][10];
+ #pragma acc parallel copy (p[-1:2])
+ ;
+ #pragma acc parallel copy (q[-1:2][0:10])
+ ;
+ #pragma acc parallel copy (q[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (r[-1:2])
+ ;
+ #pragma acc parallel copy (s[-1:2][:])
+ ;
+ #pragma acc parallel copy (s[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (a[-1:2]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (b[-1:2][0:]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (b[1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (p[2:-3]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (q[2:-3][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (q[2:3][0:-1]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (r[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (s[2:-5][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (s[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (a[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (b[2:-5][0:10]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (b[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/if-clause-2.c b/gcc/testsuite/c-c++-common/goacc/if-clause-2.c
index 5ab8459..7bb1153 100644
--- a/gcc/testsuite/c-c++-common/goacc/if-clause-2.c
+++ b/gcc/testsuite/c-c++-common/goacc/if-clause-2.c
@@ -1,11 +1,21 @@
+/* { dg-additional-options "-fdump-tree-gimple" } */
+/* { dg-additional-options "-fopenacc-kernels=decompose" }
+ { dg-additional-options "-fdump-tree-omp_oacc_kernels_decompose" } */
+
void
f (short c)
{
-#pragma acc parallel if(c)
- ;
-#pragma acc kernels if(c)
- ;
-#pragma acc data if(c)
- ;
-#pragma acc update device(c) if(c)
+#pragma acc parallel if(c) copy(c)
+ ++c;
+
+#pragma acc kernels if(c) copy(c)
+ /* { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_kernels map\(tofrom:c \[len: [0-9]+\]\) if\(_[0-9]+\)$} 1 "gimple" } } */
+ /* { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_data_kernels map\(tofrom:c \[len: [0-9]+\]\) if\(_[0-9]+\)$} 1 "omp_oacc_kernels_decompose" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_gang_single async\(-1\) num_gangs\(1\) map\(force_present:c \[len: [0-9]+\]\) if\(_[0-9]+\)$} 1 "omp_oacc_kernels_decompose" } } */
+ ++c;
+
+#pragma acc data if(c) copy(c)
+ ++c;
+
+#pragma acc update if(c) device(c)
}
diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-1.c b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-1.c
new file mode 100644
index 0000000..e906443
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-1.c
@@ -0,0 +1,91 @@
+/* Test OpenACC 'kernels' construct decomposition. */
+
+/* { dg-additional-options "-fopt-info-omp-all" } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+/* { dg-additional-options "-fopenacc-kernels=decompose" }
+ { dg-additional-options "-fdump-tree-omp_oacc_kernels_decompose" } */
+
+/* See also '../../gfortran.dg/goacc/kernels-decompose-1.f95'. */
+
+/* It's only with Tcl 8.5 (released in 2007) that "the variable 'varName'
+ passed to 'incr' may be unset, and in that case, it will be set to [...]",
+ so to maintain compatibility with earlier Tcl releases, we manually
+ initialize counter variables:
+ { dg-line l_dummy[variable c_loop_i 0] }
+ { dg-message "dummy" "" { target iN-VAl-Id } l_dummy } to avoid
+ "WARNING: dg-line var l_dummy defined, but not used". */
+
+#define N 1024
+
+unsigned int a[N];
+
+int
+main (void)
+{
+ int i;
+ unsigned int sum = 1;
+
+#pragma acc kernels copyin(a[0:N]) copy(sum)
+ /* { dg-bogus "optimized: assigned OpenACC seq loop parallelism" "TODO" { xfail *-*-* } .-1 }
+ TODO Is this maybe the report that belongs to the XFAILed report further down? */
+ {
+ #pragma acc loop /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (i = 0; i < N; ++i)
+ sum += a[i];
+
+ sum++; /* { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" } */
+ a[0]++;
+
+ #pragma acc loop independent /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC gang vector loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (i = 0; i < N; ++i)
+ sum += a[i];
+
+ if (sum > 10) /* { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" } */
+ {
+ #pragma acc loop /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-missed "unparallelized loop nest in OpenACC 'kernels' region: it's executed conditionally" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /*TODO { dg-optimized "assigned OpenACC seq loop parallelism" "TODO" { xfail *-*-* } l_loop_i$c_loop_i } */
+ for (i = 0; i < N; ++i)
+ sum += a[i];
+ }
+
+ #pragma acc loop auto /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (i = 0; i < N; ++i)
+ sum += a[i];
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_kernels map\(tofrom:sum \[len: [0-9]+\]\) map\(to:a\[0\] \[len: [0-9]+\]\) map\(firstprivate:a \[pointer assign, bias: 0\]\)$} 1 "gimple" } }
+
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\)$} 2 "gimple" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop independent private\(i\)$} 1 "gimple" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop auto private\(i\)$} 1 "gimple" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop} 4 "gimple" } } */
+
+/* Check that the OpenACC 'kernels' got decomposed into 'data' and an enclosed
+ sequence of compute constructs.
+ { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_data_kernels map\(tofrom:sum \[len: [0-9]+\]\) map\(to:a\[0\] \[len: [0-9]+\]\)$} 1 "omp_oacc_kernels_decompose" } }
+ As noted above, we get three "old-style" kernel regions, one gang-single region, and one parallelized loop region.
+ { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_kernels async\(-1\) map\(force_present:sum \[len: [0-9]+\]\) map\(force_present:a\[0\] \[len: [0-9]+\]\) map\(firstprivate:a \[pointer assign, bias: 0\]\)$} 3 "omp_oacc_kernels_decompose" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_parallelized async\(-1\) map\(force_present:sum \[len: [0-9]+\]\) map\(force_present:a\[0\] \[len: [0-9]+\]\) map\(firstprivate:a \[pointer assign, bias: 0\]\)$} 1 "omp_oacc_kernels_decompose" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_gang_single async\(-1\) num_gangs\(1\) map\(force_present:sum \[len: [0-9]+\]\) map\(force_present:a\[0\] \[len: [0-9]+\]\) map\(firstprivate:a \[pointer assign, bias: 0\]\)$} 1 "omp_oacc_kernels_decompose" } }
+
+ 'data' plus five CCs.
+ { dg-final { scan-tree-dump-times {(?n)#pragma omp target } 6 "omp_oacc_kernels_decompose" } }
+
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\)$} 2 "omp_oacc_kernels_decompose" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop independent private\(i\)$} 1 "omp_oacc_kernels_decompose" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop auto private\(i\)$} 1 "omp_oacc_kernels_decompose" } }
+ { dg-final { scan-tree-dump-times {(?n)#pragma acc loop} 4 "omp_oacc_kernels_decompose" } }
+
+ Each of the parallel regions is async, and there is a final call to
+ __builtin_GOACC_wait.
+ { dg-final { scan-tree-dump-times "__builtin_GOACC_wait" 1 "omp_oacc_kernels_decompose" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-2.c b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-2.c
new file mode 100644
index 0000000..ec0f75c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-2.c
@@ -0,0 +1,149 @@
+/* Test OpenACC 'kernels' construct decomposition. */
+
+/* { dg-additional-options "-fopt-info-omp-all" } */
+/* { dg-additional-options "-fopenacc-kernels=decompose" }
+/* { dg-additional-options "-O2" } for 'parloops'. */
+
+/* See also '../../gfortran.dg/goacc/kernels-decompose-2.f95'. */
+
+/* It's only with Tcl 8.5 (released in 2007) that "the variable 'varName'
+ passed to 'incr' may be unset, and in that case, it will be set to [...]",
+ so to maintain compatibility with earlier Tcl releases, we manually
+ initialize counter variables:
+ { dg-line l_dummy[variable c_loop_i 0 c_loop_j 0 c_loop_k 0 c_part 0] }
+ { dg-message "dummy" "" { target iN-VAl-Id } l_dummy } to avoid
+ "WARNING: dg-line var l_dummy defined, but not used". */
+
+#pragma acc routine gang
+extern int
+f_g (int);
+
+#pragma acc routine worker
+extern int
+f_w (int);
+
+#pragma acc routine vector
+extern int
+f_v (int);
+
+#pragma acc routine seq
+extern int
+f_s (int);
+
+int
+main ()
+{
+ int x, y, z;
+#define N 10
+ int a[N], b[N], c[N];
+
+#pragma acc kernels
+ {
+ x = 0; /* { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" } */
+ y = x < 10;
+ z = x++;
+ ;
+ }
+
+ { /*TODO Instead of using 'for (int i = 0; [...])', move 'int i' outside, to work around for ICE detailed in 'kernels-decompose-ice-1.c'. */
+ int i;
+#pragma acc kernels /* { dg-optimized "assigned OpenACC gang loop parallelism" } */
+ for (i = 0; i < N; i++) /* { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" } */
+ a[i] = 0;
+ }
+
+#pragma acc kernels loop /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (int i = 0; i < N; i++)
+ b[i] = a[N - i - 1];
+
+#pragma acc kernels
+ {
+#pragma acc loop /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (int i = 0; i < N; i++)
+ b[i] = a[N - i - 1];
+
+#pragma acc loop /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (int i = 0; i < N; i++)
+ c[i] = a[i] * b[i];
+
+ a[z] = 0; /* { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" } */
+
+#pragma acc loop /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (int i = 0; i < N; i++)
+ c[i] += a[i];
+
+#pragma acc loop seq /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (int i = 0 + 1; i < N; i++)
+ c[i] += c[i - 1];
+ }
+
+#pragma acc kernels
+ /*TODO What does this mean?
+ TODO { dg-optimized "assigned OpenACC worker vector loop parallelism" "" { target *-*-* } .-2 } */
+ {
+#pragma acc loop independent /* { dg-line l_loop_i[incr c_loop_i] } */
+ /* { dg-optimized "assigned OpenACC gang loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i } */
+ /* { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_i$c_loop_i } */
+ for (int i = 0; i < N; ++i)
+#pragma acc loop independent /* { dg-line l_loop_j[incr c_loop_j] } */
+ /* { dg-optimized "assigned OpenACC worker loop parallelism" "" { target *-*-* } l_loop_j$c_loop_j } */
+ for (int j = 0; j < N; ++j)
+#pragma acc loop independent /* { dg-line l_loop_k[incr c_loop_k] } */
+ /* { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } l_loop_k$c_loop_k } */
+ /* { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_k$c_loop_k } */
+ for (int k = 0; k < N; ++k)
+ a[(i + j + k) % N]
+ = b[j]
+ + f_v (c[k]); /* { dg-optimized "assigned OpenACC vector loop parallelism" } */
+
+ /*TODO Should the following turn into "gang-single" instead of "parloops"?
+ TODO The problem is that the first STMT is 'if (y <= 4) goto <D.2547>; else goto <D.2548>;', thus "parloops". */
+ if (y < 5) /* { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" } */
+#pragma acc loop independent /* { dg-line l_loop_j[incr c_loop_j] } */
+ /* { dg-missed "unparallelized loop nest in OpenACC 'kernels' region: it's executed conditionally" "" { target *-*-* } l_loop_j$c_loop_j } */
+ for (int j = 0; j < N; ++j)
+ b[j] = f_w (c[j]);
+ }
+
+#pragma acc kernels
+ {
+ y = f_g (a[5]); /* { dg-line l_part[incr c_part] } */
+ /*TODO If such a construct is placed in its own part (like it is, here), can't this actually use gang paralelism, instead of "gang-single"?
+ { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" "" { target *-*-* } l_part$c_part } */
+ /* { dg-optimized "assigned OpenACC gang worker vector loop parallelism" "" { target *-*-* } l_part$c_part } */
+
+#pragma acc loop independent /* { dg-line l_loop_j[incr c_loop_j] } */
+ /* { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_j$c_loop_j } */
+ /* { dg-optimized "assigned OpenACC gang loop parallelism" "" { target *-*-* } l_loop_j$c_loop_j } */
+ for (int j = 0; j < N; ++j)
+ b[j] = y + f_w (c[j]); /* { dg-optimized "assigned OpenACC worker vector loop parallelism" } */
+ }
+
+#pragma acc kernels
+ {
+ y = 3; /* { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" } */
+
+#pragma acc loop independent /* { dg-line l_loop_j[incr c_loop_j] } */
+ /* { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_j$c_loop_j } */
+ /* { dg-optimized "assigned OpenACC gang worker loop parallelism" "" { target *-*-* } l_loop_j$c_loop_j } */
+ for (int j = 0; j < N; ++j)
+ b[j] = y + f_v (c[j]); /* { dg-optimized "assigned OpenACC vector loop parallelism" } */
+
+ z = 2; /* { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" } */
+ }
+
+#pragma acc kernels /* { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" } */
+ ;
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c
new file mode 100644
index 0000000..82e7bd1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-1.c
@@ -0,0 +1,109 @@
+/* Test OpenACC 'kernels' construct decomposition. */
+
+/* { dg-additional-options "-fopt-info-omp-all" } */
+/* { dg-additional-options "-fopenacc-kernels=decompose" } */
+/* { dg-ice "TODO" }
+ { dg-prune-output "during GIMPLE pass: omplower" } */
+
+/* Reduced from 'kernels-decompose-2.c'.
+ (Hopefully) similar instances:
+ - 'kernels-decompose-ice-2.c'
+ - 'libgomp.oacc-c-c++-common/declare-vla-kernels-decompose-ice-1.c'
+ - 'libgomp.oacc-c-c++-common/kernels-decompose-1.c'
+*/
+
+int
+main ()
+{
+#define N 10
+
+#pragma acc kernels
+ for (int i = 0; i < N; i++) /* { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" } */
+ ;
+
+ return 0;
+}
+
+/*
+ In 'gimple' we've got:
+
+ main ()
+ {
+ int D.2087;
+
+ {
+ int a[10];
+
+ try
+ {
+ #pragma omp target oacc_kernels map(tofrom:a [len: 40])
+ {
+ {
+ int i;
+
+ i = 0;
+ goto <D.2085>;
+ [...]
+
+ ..., which in 'omp_oacc_kernels_decompose' we turn into:
+
+ main ()
+ {
+ int D.2087;
+
+ {
+ int a[10];
+
+ try
+ {
+ #pragma omp target oacc_data_kernels map(tofrom:a [len: 40])
+ {
+ try
+ {
+ {
+ int i;
+
+ #pragma omp target oacc_data_kernels map(alloc:i [len: 4])
+ {
+ try
+ {
+ {
+ #pragma omp target oacc_kernels async(-1) map(force_present:i [len: 4]) map(force_present:a [len: 40])
+ {
+ i = 0;
+ goto <D.2085>;
+ [...]
+
+ ..., which results in ICE in:
+
+ #1 0x0000000000d2247b in lower_omp_target (gsi_p=gsi_p@entry=0x7fffffffbc90, ctx=ctx@entry=0x2c994c0) at [...]/gcc/omp-low.c:11981
+ 11981 gcc_assert (offloaded);
+ (gdb) list
+ 11976 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
+ 11977 gimplify_assign (x, var, &ilist);
+ 11978 }
+ 11979 else if (is_gimple_reg (var))
+ 11980 {
+ 11981 gcc_assert (offloaded);
+ 11982 tree avar = create_tmp_var (TREE_TYPE (var));
+ 11983 mark_addressable (avar);
+ 11984 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
+ 11985 if (GOMP_MAP_COPY_TO_P (map_kind)
+ (gdb) call debug_tree(var)
+ <var_decl 0x7ffff7feebd0 i
+ type <integer_type 0x7ffff67be5e8 int sizes-gimplified public SI
+ size <integer_cst 0x7ffff67a5f18 constant 32>
+ unit-size <integer_cst 0x7ffff67a5f30 constant 4>
+ align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff67be5e8 precision:32 min <integer_cst 0x7ffff67a5ed0 -2147483648> max <integer_cst 0x7ffff67a5ee8 2147483647>
+ pointer_to_this <pointer_type 0x7ffff67c69d8>>
+ used read SI [...]:15:12 size <integer_cst 0x7ffff67a5f18 32> unit-size <integer_cst 0x7ffff67a5f30 4>
+ align:32 warn_if_not_align:0 context <function_decl 0x7ffff68eea00 main>>
+
+ Just defusing the 'assert' is not sufficient:
+
+ libgomp: present clause: !acc_is_present (0x7ffe29cba3ec, 4 (0x4))
+
+ TODO Can't the 'omp_oacc_kernels_decompose' transformation be much simpler, such that we avoid the intermediate 'data' if we've got just one compute construct inside it?
+ TODO But it's not clear if that'd just resolve one simple instance of the general problem?
+
+*/
diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c
new file mode 100644
index 0000000..569f87a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/kernels-decompose-ice-2.c
@@ -0,0 +1,16 @@
+/* Test OpenACC 'kernels' construct decomposition. */
+
+/* { dg-additional-options "-fopenacc-kernels=decompose" } */
+/* { dg-ice "TODO" }
+ { dg-prune-output "during GIMPLE pass: omplower" } */
+
+/* Reduced from 'kernels-decompose-ice-1.c'. */
+
+int
+main ()
+{
+#pragma acc kernels
+ {
+ int i;
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-kernels.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-kernels.c
new file mode 100644
index 0000000..9323e2c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-kernels.c
@@ -0,0 +1,236 @@
+/* Test cases of nested 'reduction' clauses expected to compile cleanly. */
+
+/* See also 'gfortran.dg/goacc/nested-reductions-1-kernels.f90'. */
+
+void acc_kernels (void)
+{
+ int i, j, k, sum, diff;
+
+ #pragma acc kernels
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but using a combined kernels loop construct. */
+
+void acc_kernels_loop (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc kernels loop
+ for (int h = 0; h < 10; ++h)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but now the outermost reduction clause is on
+ the kernels region, not the outermost loop. */
+
+void acc_kernels_reduction (void)
+{
+ /* In contrast to the 'parallel' construct, the 'reduction' clause is not
+ supported on the 'kernels' construct. */
+}
+
+/* The same tests as above, but using a combined kernels loop construct, and
+ the outermost reduction clause is on that one, not the outermost loop. */
+void acc_kernels_loop_reduction (void)
+{
+ int i, j, k, sum, diff;
+
+ #pragma acc kernels loop reduction(+:sum)
+ for (int h = 0; h < 10; ++h)
+ {
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ for (i = 0; i < 10; i++)
+ #pragma acc loop
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-parallel.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-parallel.c
new file mode 100644
index 0000000..ce1d0a1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-parallel.c
@@ -0,0 +1,318 @@
+/* Test cases of nested 'reduction' clauses expected to compile cleanly. */
+
+/* See also 'gfortran.dg/goacc/nested-reductions-1-parallel.f90'. */
+
+void acc_parallel (void)
+{
+ int i, j, k, sum, diff;
+
+ #pragma acc parallel
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but using a combined parallel loop construct. */
+
+void acc_parallel_loop (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc parallel loop
+ for (int h = 0; h < 10; ++h)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but now the outermost reduction clause is on
+ the parallel region, not the outermost loop. */
+
+void acc_parallel_reduction (void)
+{
+ int i, j, k, sum, diff;
+
+ #pragma acc parallel reduction(+:sum)
+ {
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ for (i = 0; i < 10; i++)
+ #pragma acc loop
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but using a combined parallel loop construct, and
+ the outermost reduction clause is on that one, not the outermost loop. */
+void acc_parallel_loop_reduction (void)
+{
+ int i, j, k, sum, diff;
+
+ #pragma acc parallel loop reduction(+:sum)
+ for (int h = 0; h < 10; ++h)
+ {
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ for (i = 0; i < 10; i++)
+ #pragma acc loop
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "insufficient partitioning available to parallelize loop" }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-routine.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-routine.c
new file mode 100644
index 0000000..83d3995
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/nested-reductions-1-routine.c
@@ -0,0 +1,68 @@
+/* Test cases of nested 'reduction' clauses expected to compile cleanly. */
+
+/* See also 'gfortran.dg/goacc/nested-reductions-1-routine.f90'. */
+
+#pragma acc routine gang
+void acc_routine (void)
+{
+ int i, j, k, sum, diff;
+
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff)
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-kernels.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-kernels.c
new file mode 100644
index 0000000..dec7dbd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-kernels.c
@@ -0,0 +1,305 @@
+/* Test erroneous cases of nested 'reduction' clauses. */
+
+/* See also 'gfortran.dg/goacc/nested-reductions-2-kernels.f90'. */
+
+void acc_kernels (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc kernels
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but using a combined kernels loop construct. */
+
+void acc_kernels_loop (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc kernels loop
+ for (int h = 0; h < 10; ++h)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but now the outermost reduction clause is on
+ the kernels region, not the outermost loop. */
+void acc_kernels_reduction (void)
+{
+ /* In contrast to the 'parallel' construct, the 'reduction' clause is not
+ supported on the 'kernels' construct. */
+}
+
+/* The same tests as above, but using a combined kernels loop construct, and
+ the outermost reduction clause is on that one, not the outermost loop. */
+void acc_kernels_loop_reduction (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc kernels loop reduction(+:sum)
+ for (int h = 0; h < 10; ++h)
+ {
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-parallel.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-parallel.c
new file mode 100644
index 0000000..1f6b4e7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-parallel.c
@@ -0,0 +1,389 @@
+/* Test erroneous cases of nested 'reduction' clauses. */
+
+/* See also 'gfortran.dg/goacc/nested-reductions-2-parallel.f90'. */
+
+void acc_parallel (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc parallel
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but using a combined parallel loop construct. */
+
+void acc_parallel_loop (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc parallel loop
+ for (int h = 0; h < 10; ++h)
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but now the outermost reduction clause is on
+ the parallel region, not the outermost loop. */
+void acc_parallel_reduction (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc parallel reduction(+:sum)
+ {
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
+
+/* The same tests as above, but using a combined parallel loop construct, and
+ the outermost reduction clause is on that one, not the outermost loop. */
+void acc_parallel_loop_reduction (void)
+{
+ int i, j, k, l, sum, diff;
+
+ #pragma acc parallel loop reduction(+:sum)
+ for (int h = 0; h < 10; ++h)
+ {
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-routine.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-routine.c
new file mode 100644
index 0000000..5988d50
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/nested-reductions-2-routine.c
@@ -0,0 +1,93 @@
+/* Test erroneous cases of nested 'reduction' clauses. */
+
+/* See also 'gfortran.dg/goacc/nested-reductions-2-routine.f90'. */
+
+#pragma acc routine gang
+void acc_routine (void)
+{
+ int i, j, k, l, sum, diff;
+
+ {
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(+:sum)
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum)
+ for (i = 0; i < 10; i++)
+ #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ for (k = 0; k < 10; k++)
+ #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ for (l = 0; l < 10; l++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) reduction(-:diff)
+ for (i = 0; i < 10; i++)
+ {
+ #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(+:sum)
+ for (k = 0; k < 10; k++)
+ sum = 1;
+
+ #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ for (j = 0; j < 10; j++)
+ #pragma acc loop reduction(-:diff)
+ for (k = 0; k < 10; k++)
+ diff = 1;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions-warn.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions-warn.c
deleted file mode 100644
index e2af66e..0000000
--- a/gcc/testsuite/c-c++-common/goacc/nested-reductions-warn.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/* Test erroneous cases of nested reduction loops. */
-
-void acc_parallel (void)
-{
- int i, j, k, l, sum, diff;
-
- #pragma acc parallel
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but using a combined parallel loop construct. */
-
-void acc_parallel_loop (void)
-{
- int i, j, k, l, sum, diff;
-
- #pragma acc parallel loop
- for (int h = 0; h < 10; ++h)
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but now the outermost reduction clause is on
- the parallel region, not the outermost loop. */
-void acc_parallel_reduction (void)
-{
- int i, j, k, l, sum, diff;
-
- #pragma acc parallel reduction(+:sum)
- {
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but using a combined parallel loop construct, and
- the outermost reduction clause is on that one, not the outermost loop. */
-void acc_parallel_loop_reduction (void)
-{
- int i, j, k, l, sum, diff;
-
- #pragma acc parallel loop reduction(+:sum)
- for (int h = 0; h < 10; ++h)
- {
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(max:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but inside a routine construct. */
-#pragma acc routine gang
-void acc_routine (void)
-{
- int i, j, k, l, sum, diff;
-
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(+:sum)
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
- // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- for (k = 0; k < 10; k++)
- #pragma acc loop reduction(*:sum) // { dg-warning "conflicting reduction operations for .sum." }
- for (l = 0; l < 10; l++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-void acc_kernels (void)
-{
- int i, j, k, sum, diff;
-
- /* FIXME: No diagnostics are produced for these loops because reductions
- in kernels regions are not supported yet. */
- #pragma acc kernels
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:diff)
- for (j = 0; j < 10; j++)
- #pragma acc loop
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(-:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
- }
-}
diff --git a/gcc/testsuite/c-c++-common/goacc/nested-reductions.c b/gcc/testsuite/c-c++-common/goacc/nested-reductions.c
deleted file mode 100644
index 15385c4..0000000
--- a/gcc/testsuite/c-c++-common/goacc/nested-reductions.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/* Test cases of nested reduction loops that should compile cleanly. */
-
-void acc_parallel (void)
-{
- int i, j, k, sum, diff;
-
- #pragma acc parallel
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop collapse(2) reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but using a combined parallel loop construct. */
-
-void acc_parallel_loop (void)
-{
- int i, j, k, l, sum, diff;
-
- #pragma acc parallel loop
- for (int h = 0; h < 10; ++h)
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop collapse(2) reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but now the outermost reduction clause is on
- the parallel region, not the outermost loop. */
-
-void acc_parallel_reduction (void)
-{
- int i, j, k, sum, diff;
-
- #pragma acc parallel reduction(+:sum)
- {
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- for (i = 0; i < 10; i++)
- #pragma acc loop
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but using a combined parallel loop construct, and
- the outermost reduction clause is on that one, not the outermost loop. */
-void acc_parallel_loop_reduction (void)
-{
- int i, j, k, sum, diff;
-
- #pragma acc parallel loop reduction(+:sum)
- for (int h = 0; h < 10; ++h)
- {
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- for (i = 0; i < 10; i++)
- #pragma acc loop
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum) // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop // { dg-warning "insufficient partitioning available to parallelize loop" }
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-/* The same tests as above, but inside a routine construct. */
-#pragma acc routine gang
-void acc_routine (void)
-{
- int i, j, k, sum, diff;
-
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop collapse(2) reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop collapse(2) reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum) reduction(-:diff)
- for (i = 0; i < 10; i++)
- {
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(-:diff)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(-:diff)
- for (k = 0; k < 10; k++)
- diff = 1;
- }
- }
-}
-
-void acc_kernels (void)
-{
- int i, j, k, sum, diff;
-
- /* FIXME: These tests are not meaningful yet because reductions in
- kernels regions are not supported yet. */
- #pragma acc kernels
- {
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
-
- #pragma acc loop reduction(+:sum)
- for (i = 0; i < 10; i++)
- #pragma acc loop reduction(+:sum)
- for (j = 0; j < 10; j++)
- #pragma acc loop reduction(+:sum)
- for (k = 0; k < 10; k++)
- sum = 1;
- }
-}
diff --git a/gcc/testsuite/c-c++-common/goacc/pr79428-1.c b/gcc/testsuite/c-c++-common/goacc/pr79428-1.c
index 68dea5b..a8047e9 100644
--- a/gcc/testsuite/c-c++-common/goacc/pr79428-1.c
+++ b/gcc/testsuite/c-c++-common/goacc/pr79428-1.c
@@ -4,5 +4,5 @@ void
foo ()
{
#pragma acc routine /* { dg-error ".#pragma acc routine. must be at file scope" } */
-// { dg-error "expected" "end" { target c } .-1 }
-// { dg-error "-:expected" "end" { target c++ } .+1 }
+// { dg-error "expected" "end" { target *-*-* } .-1 }
+
diff --git a/gcc/testsuite/c-c++-common/goacc/pr92793-1.c b/gcc/testsuite/c-c++-common/goacc/pr92793-1.c
new file mode 100644
index 0000000..71a556e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/pr92793-1.c
@@ -0,0 +1,141 @@
+/* Verify column location information. */
+
+/* See also 'gfortran.dg/goacc/pr92793-1.f90'. */
+
+/* { dg-additional-options "-fdump-tree-original-lineno" }, and also
+ { dg-additional-options "-fdump-tree-gimple-lineno" } as the former doesn't
+ actually contain location information. */
+
+/* No tabs. Funny indentation/spacing for a reason. */
+
+
+static void
+check ()
+{
+ int i, j, sum, diff;
+
+ #pragma acc parallel \
+ /* C, C++ location information points to the 'a' in '#pragma acc parallel'. */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:17:12\\\] #pragma acc parallel" 1 "original" { xfail *-*-* } } } */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:17:12\\\] #pragma omp target oacc_parallel" 1 "gimple" } } */
+ {
+#pragma acc loop \
+ /* C, C++ location information points to the 'a' in '#pragma acc loop'. */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:22:13\\\] #pragma acc loop" 1 "original" { xfail *-*-* } } } */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:22:13\\\] #pragma acc loop" 1 "gimple" } } */ \
+ reduction ( + : sum) /* { dg-line sum1 } */ \
+ /* C location information points to the '(' in 'reduction(+:sum)'. */ \
+ /* { dg-message "19: location of the previous reduction for 'sum'" "" { target c } sum1 } */ \
+ /* C++ location information points to 'sum' in 'reduction(+:sum)'. */ \
+ /* { dg-message "28: location of the previous reduction for 'sum'" "" { target c++ } sum1 } */ \
+ independent
+ for (i = 1; i <= 10; i++)
+ {
+ #pragma acc loop \
+ /* C, C++ location information points to the 'a' in '#pragma acc loop'. */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:34:19\\\] #pragma acc loop" 1 "original" { xfail *-*-* } } } */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:34:19\\\] #pragma acc loop" 1 "gimple" } } */ \
+ reduction ( - : diff ) \
+reduction(-:sum ) /* { dg-line sum2 } */ \
+ /* C location information points to the '(' in 'reduction(-:sum)'. */ \
+ /* { dg-warning "10: conflicting reduction operations for 'sum'" "" { target c } sum2 } */ \
+ /* C++ location information points to 'sum' in 'reduction(-:sum)'. */ \
+ /* { dg-warning "13: conflicting reduction operations for 'sum'" "" { target c++ } sum2 } */ \
+ independent
+ for (j = 1; j <= 10; j++)
+ {
+ sum
+ =
+ 1 ;
+ /* C, C++ location information points to the '=' in 'sum = 1'. */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:48:19\\\] sum = 1" 1 "original" { xfail *-*-* } } } */ \
+ /* { dg-final { scan-tree-dump-times "pr92793-1\\\.c:48:19\\\] sum = 1" 1 "gimple" } } */
+ }
+ }
+ }
+}
+
+
+void
+gwv_sl_1() {
+#pragma acc serial loop /* { dg-message "9: enclosing parent compute construct" } */ \
+ gang(num:5) /* { dg-error "5: argument not permitted on 'gang' clause" } */ \
+ worker(num:5) /* { dg-error "3: argument not permitted on 'worker' clause" } */ \
+ vector(length:5) /* { dg-error "4: argument not permitted on 'vector' clause" } */
+ for (int i = 0; i < 10; i++)
+ ;
+}
+
+void
+gwv_sl_2() {
+#pragma acc serial loop /* { dg-message "9: enclosing parent compute construct" } */
+ for (int i = 0; i < 10; i++)
+ {
+#pragma acc loop /* { dg-bogus "enclosing parent compute construct" } */
+ for (int j = 0; j < 10; j++)
+ {
+#pragma acc loop \
+ gang(num:5) /* { dg-error "9: argument not permitted on 'gang' clause" } */ \
+ worker(num:5) /* { dg-error "5: argument not permitted on 'worker' clause" } */ \
+ vector(length:5) /* { dg-error "3: argument not permitted on 'vector' clause" } */
+ for (int k = 0; k < 10; k++)
+ ;
+ }
+ }
+}
+
+void
+gwv_s_l() {
+#pragma acc serial /* { dg-message "9: enclosing parent compute construct" } */
+ {
+#pragma acc loop \
+ gang(num:5) /* { dg-error "8: argument not permitted on 'gang' clause" } */ \
+ worker(num:5) /* { dg-error "4: argument not permitted on 'worker' clause" } */ \
+ vector(length:5) /* { dg-error "3: argument not permitted on 'vector' clause" } */
+ for (int i = 0; i < 10; i++)
+ ;
+
+#pragma acc loop
+ for (int i = 0; i < 10; i++)
+ {
+#pragma acc loop /* { dg-bogus "enclosing parent compute construct" } */
+ for (int j = 0; j < 10; j++)
+ {
+#pragma acc loop \
+ gang(num:5) /* { dg-error "10: argument not permitted on 'gang' clause" } */ \
+ worker(num:5) /* { dg-error "7: argument not permitted on 'worker' clause" } */ \
+ vector(length:5) /* { dg-error "5: argument not permitted on 'vector' clause" } */
+ for (int k = 0; k < 10; k++)
+ ;
+ }
+ }
+ }
+}
+
+void gwv_r();
+#pragma acc routine(gwv_r)
+
+void
+gwv_r() { /* { dg-message "1: enclosing routine" } */
+#pragma acc loop \
+ gang(num:5) /* { dg-error "4: argument not permitted on 'gang' clause" } */ \
+ worker(num:5) /* { dg-error "5: argument not permitted on 'worker' clause" } */ \
+ vector(length:5) /* { dg-error "3: argument not permitted on 'vector' clause" } */
+ for (int i = 0; i < 10; i++)
+ ;
+
+#pragma acc loop
+ for (int i = 0; i < 10; i++)
+ {
+#pragma acc loop
+ for (int j = 0; j < 10; j++)
+ {
+#pragma acc loop \
+ gang(num:5) /* { dg-error "6: argument not permitted on 'gang' clause" } */ \
+ worker(num:5) /* { dg-error "4: argument not permitted on 'worker' clause" } */ \
+ vector(length:5) /* { dg-error "6: argument not permitted on 'vector' clause" } */
+ for (int k = 0; k < 10; k++)
+ ;
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-1.c b/gcc/testsuite/c-c++-common/gomp/allocate-1.c
new file mode 100644
index 0000000..5630dac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-1.c
@@ -0,0 +1,84 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int bar (int, int *, int);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int y[16] = { 0 }, r = 0, i;
+ omp_allocator_handle_t h = baz ();
+ #pragma omp parallel allocate (x) allocate (omp_default_mem_alloc : y) \
+ allocate ((omp_allocator_handle_t) omp_default_mem_alloc:z) firstprivate (x, y, z)
+ bar (x, y, z);
+ #pragma omp task private (x) firstprivate (z) allocate (omp_low_lat_mem_alloc:x,z)
+ bar (0, &x, z);
+ #pragma omp taskwait
+ #pragma omp target teams distribute parallel for private (x) firstprivate (y) \
+ allocate ((omp_allocator_handle_t)(omp_default_mem_alloc + 0):z) \
+ allocate (omp_default_mem_alloc: x, y) allocate (omp_low_lat_mem_alloc: r) \
+ lastprivate (z) reduction(+:r)
+ for (i = 0; i < 64; i++)
+ {
+ z = bar (0, &x, 0);
+ r += bar (1, y, 0);
+ }
+ #pragma omp single private (x) allocate (h:x)
+ ;
+ #pragma omp single allocate (*&h : x) private (x)
+ ;
+ #pragma omp parallel shared (r, x, z)
+ #pragma omp single firstprivate (r) allocate (x, r, z) private (x, z)
+ ;
+ #pragma omp for allocate (x) private (x)
+ for (i = 0; i < 64; i++)
+ x = 1;
+ #pragma omp sections private (x) allocate (omp_low_lat_mem_alloc: x)
+ {
+ x = 1;
+ #pragma omp section
+ x = 2;
+ #pragma omp section
+ x = 3;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (omp_default_mem_alloc : r)
+ #pragma omp task in_reduction(+:r) allocate (omp_default_mem_alloc : r)
+ r += bar (r, &r, 0);
+ #pragma omp teams private (x) firstprivate (y) allocate (h : x, y)
+ bar (x, y, 0);
+ #pragma omp taskloop lastprivate (x) reduction (+:r) allocate (h : x, r)
+ for (i = 0; i < 16; i++)
+ {
+ r += bar (0, &r, 0);
+ x = i;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (omp_default_mem_alloc : r)
+ #pragma omp taskloop firstprivate (x) in_reduction (+:r) \
+ allocate (omp_default_mem_alloc : x, r)
+ for (i = 0; i < 16; i++)
+ r += bar (x, &r, 0);
+ #pragma omp taskwait
+}
+
+void
+qux (const omp_allocator_handle_t h)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (h: x)
+ x = 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-2.c b/gcc/testsuite/c-c++-common/gomp/allocate-2.c
new file mode 100644
index 0000000..cc77efc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-2.c
@@ -0,0 +1,45 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int bar (int, int *, int);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int i;
+ #pragma omp task allocate (x) /* { dg-error "'x' specified in 'allocate' clause but not in an explicit privatization clause" } */
+ bar (x, &x, 0);
+ #pragma omp taskwait
+ #pragma omp parallel allocate (x) /* { dg-error "'x' specified in 'allocate' clause but not in an explicit privatization clause" } */
+ bar (x, &x, 0);
+ #pragma omp parallel for simd private (x) allocate (x) /* { dg-error "'x' specified in 'allocate' clause but not in an explicit privatization clause" } */
+ for (i = 0; i < 16; i++)
+ x = i;
+ #pragma omp parallel allocate (foo) /* { dg-error "'\[^\n\r]*foo\[^\n\r]*' is not a variable in 'allocate' clause" } */
+ ;
+ #pragma omp parallel allocate (x) shared (x) /* { dg-error "'x' specified in 'allocate' clause but not in an explicit privatization clause" } */
+ bar (x, &x, 0);
+ #pragma omp parallel private (x) allocate (x) allocate (x) /* { dg-warning "'x' appears more than once in 'allocate' clauses" } */
+ bar (x, &x, 0);
+ #pragma omp parallel private (x) allocate (x, x) /* { dg-warning "'x' appears more than once in 'allocate' clauses" } */
+ bar (x, &x, 0);
+ #pragma omp parallel private (x) allocate (0.0 : x) /* { dg-error "'allocate' clause allocator expression has type 'double' rather than 'omp_allocator_handle_t'" } */
+ bar (x, &x, 0);
+ #pragma omp parallel private (x) allocate (0 : x) /* { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" } */
+ bar (x, &x, 0);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-3.c b/gcc/testsuite/c-c++-common/gomp/allocate-3.c
new file mode 100644
index 0000000..e61cc1e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-3.c
@@ -0,0 +1,38 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+omp_allocator_handle_t baz (int);
+
+int
+foo (omp_allocator_handle_t h1, omp_allocator_handle_t h2, int y)
+{
+ int x;
+ #pragma omp taskloop default(none) lastprivate (x) allocate (h1:x) firstprivate(y) allocate (h2:y)
+ for (int i = 0; i < 64; i++)
+ x = y + i;
+ return x;
+}
+
+int
+bar (int y)
+{
+ int x;
+ #pragma omp taskloop default(none) lastprivate (x) allocate (baz (0):x) allocate (baz (1):y) firstprivate(y)
+ for (int i = 0; i < 64; i++)
+ x = y + i;
+ return x;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-4.c b/gcc/testsuite/c-c++-common/gomp/allocate-4.c
new file mode 100644
index 0000000..4e0f44a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-4.c
@@ -0,0 +1,39 @@
+void
+foo (void)
+{
+ int s[4] = { 0, 0, 0, 0 };
+ int *p = s;
+#pragma omp parallel reduction (+: s) allocate(s)
+ s[0]++;
+#pragma omp parallel reduction (+: s[0:3]) allocate(s)
+ s[0]++;
+#pragma omp parallel reduction (+: s[2:2]) allocate(s)
+ s[2]++;
+#pragma omp parallel reduction (+: p[:2]) allocate(p)
+ p[0]++;
+#pragma omp parallel reduction (+: p[2:2]) allocate(p)
+ p[2]++;
+}
+
+void
+bar (void)
+{
+ int s[4] = { 0, 0, 0, 0 };
+ int *p = s;
+ int i;
+#pragma omp teams distribute parallel for reduction (+: s) allocate(s)
+ for (i = 0; i < 64; i++)
+ s[0]++;
+#pragma omp teams distribute parallel for reduction (+: s[0:3]) allocate(s)
+ for (i = 0; i < 64; i++)
+ s[0]++;
+#pragma omp teams distribute parallel for reduction (+: s[2:2]) allocate(s)
+ for (i = 0; i < 64; i++)
+ s[2]++;
+#pragma omp teams distribute parallel for reduction (+: p[:2]) allocate(p)
+ for (i = 0; i < 64; i++)
+ p[0]++;
+#pragma omp teams distribute parallel for reduction (+: p[2:2]) allocate(p)
+ for (i = 0; i < 64; i++)
+ p[2]++;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-5.c b/gcc/testsuite/c-c++-common/gomp/allocate-5.c
new file mode 100644
index 0000000..34dcb48
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-5.c
@@ -0,0 +1,41 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+void
+foo ()
+{
+ int a, b;
+ omp_allocator_handle_t my_allocator;
+#pragma omp allocate (a) /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" } */
+#pragma omp allocate (b) allocator(my_allocator) /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" } */
+}
+
+void
+bar ()
+{
+ int a, b;
+ omp_allocator_handle_t my_allocator;
+#pragma omp allocate /* { dg-error "expected '\\(' before end of line" } */
+ /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-1 } */
+#pragma omp allocate allocator(my_allocator) /* { dg-error "expected '\\(' before 'allocator'" } */
+ /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-1 } */
+#pragma omp allocate(a) foo(my_allocator) /* { dg-error "expected 'allocator'" } */
+ /* { dg-error "expected end of line before '\\(' token" "" { target *-*-* } .-1 } */
+ /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-2 } */
+#pragma omp allocate(a) allocator(b) /* { dg-error "'allocator' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" "todo: cp/semantics.c" { xfail c++ } } */
+ /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-1.c b/gcc/testsuite/c-c++-common/gomp/clauses-1.c
index be42797..105288e 100644
--- a/gcc/testsuite/c-c++-common/gomp/clauses-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/clauses-1.c
@@ -1,6 +1,23 @@
/* { dg-do compile } */
/* { dg-additional-options "-std=c99" { target c } } */
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
int t;
#pragma omp threadprivate (t)
@@ -14,20 +31,20 @@ foo (int d, int m, int i1, int i2, int p, int *idp, int s,
#pragma omp distribute parallel for \
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) schedule(static, 4) order(concurrent)
+ lastprivate (l) schedule(static, 4) order(concurrent) allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp distribute parallel for simd \
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \
if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
lastprivate (l) schedule(static, 4) nontemporal(ntm) \
- safelen(8) simdlen(4) aligned(q: 32) order(concurrent)
+ safelen(8) simdlen(4) aligned(q: 32) order(concurrent) allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp distribute simd \
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \
safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
}
@@ -49,20 +66,20 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s,
#pragma omp distribute parallel for \
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) schedule(static, 4) copyin(t) order(concurrent)
+ lastprivate (l) schedule(static, 4) copyin(t) order(concurrent) allocate (p)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp distribute parallel for simd \
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \
if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
lastprivate (l) schedule(static, 4) nontemporal(ntm) \
- safelen(8) simdlen(4) aligned(q: 32) copyin(t) order(concurrent)
+ safelen(8) simdlen(4) aligned(q: 32) copyin(t) order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp distribute simd \
private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \
safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp loop bind(parallel) order(concurrent) \
@@ -77,28 +94,28 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
{
#pragma omp for simd \
private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait \
- safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent)
+ safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel for \
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1)
+ lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel for \
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) order(concurrent)
+ lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel for simd \
private (p) firstprivate (f) if (i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \
lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) \
- safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) order(concurrent)
+ safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel sections \
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l)
+ lastprivate (l) allocate (f)
{
#pragma omp section
{}
@@ -108,35 +125,39 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
#pragma omp target parallel \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- nowait depend(inout: dd[0])
+ nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f)
;
#pragma omp target parallel for \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) nowait depend(inout: dd[0])
+ lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target parallel for \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) order(concurrent)
+ lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) order(concurrent) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target parallel for simd \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) \
- safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) order(concurrent)
+ safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) order(concurrent) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target teams \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
- shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0])
+ shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) \
+ allocate (omp_default_mem_alloc:f)
;
#pragma omp target teams distribute \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
- collapse(1) dist_schedule(static, 16) nowait depend(inout: dd[0])
+ collapse(1) dist_schedule(static, 16) nowait depend(inout: dd[0]) allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
;
#pragma omp target teams distribute parallel for \
@@ -144,7 +165,8 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
collapse(1) dist_schedule(static, 16) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
- lastprivate (l) schedule(static, 4) nowait depend(inout: dd[0]) order(concurrent)
+ lastprivate (l) schedule(static, 4) nowait depend(inout: dd[0]) order(concurrent) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target teams distribute parallel for simd \
@@ -153,47 +175,50 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
collapse(1) dist_schedule(static, 16) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
lastprivate (l) schedule(static, 4) order(concurrent) \
- safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3)
+ safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target teams distribute simd \
device(d) map (tofrom: m) if (i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
collapse(1) dist_schedule(static, 16) order(concurrent) \
- safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm)
+ safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target simd \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
safelen(8) simdlen(4) lastprivate (l) linear(ll: 1) aligned(q: 32) reduction(+:r) \
- nowait depend(inout: dd[0]) nontemporal(ntm) if(simd:i3) order(concurrent)
+ nowait depend(inout: dd[0]) nontemporal(ntm) if(simd:i3) order(concurrent) \
+ allocate (omp_default_mem_alloc:f)
for (int i = 0; i < 64; i++)
ll++;
- #pragma omp taskgroup task_reduction(+:r2)
+ #pragma omp taskgroup task_reduction(+:r2) allocate (r2)
#pragma omp taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
- #pragma omp taskgroup task_reduction(+:r)
+ #pragma omp taskgroup task_reduction(+:r) allocate (r)
#pragma omp taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(i1) final(fi) mergeable nogroup priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp taskwait
#pragma omp taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) if(taskloop: i1) final(fi) priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) if (simd: i3) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target nowait depend(inout: dd[0])
#pragma omp teams distribute \
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
- collapse(1) dist_schedule(static, 16)
+ collapse(1) dist_schedule(static, 16) allocate (omp_default_mem_alloc: f)
for (int i = 0; i < 64; i++)
;
#pragma omp target
@@ -201,7 +226,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
collapse(1) dist_schedule(static, 16) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
- lastprivate (l) schedule(static, 4) order(concurrent)
+ lastprivate (l) schedule(static, 4) order(concurrent) allocate (omp_default_mem_alloc: f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target
@@ -210,21 +235,23 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
collapse(1) dist_schedule(static, 16) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
lastprivate (l) schedule(static, 4) order(concurrent) \
- safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm)
+ safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) \
+ allocate (omp_default_mem_alloc: f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp target
#pragma omp teams distribute simd \
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
collapse(1) dist_schedule(static, 16) order(concurrent) \
- safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm)
+ safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) \
+ allocate (omp_default_mem_alloc: f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp teams distribute parallel for \
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
collapse(1) dist_schedule(static, 16) order(concurrent) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
- lastprivate (l) schedule(static, 4) copyin(t)
+ lastprivate (l) schedule(static, 4) copyin(t) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp teams distribute parallel for simd \
@@ -232,65 +259,66 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
collapse(1) dist_schedule(static, 16) \
if (parallel: i2) num_threads (nth) proc_bind(spread) \
lastprivate (l) schedule(static, 4) order(concurrent) \
- safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) copyin(t)
+ safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) copyin(t) \
+ allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp teams distribute simd \
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
collapse(1) dist_schedule(static, 16) order(concurrent) \
- safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm)
+ safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) allocate(f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel master \
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) \
- num_threads (nth) proc_bind(spread) copyin(t)
+ num_threads (nth) proc_bind(spread) copyin(t) allocate (f)
;
- #pragma omp taskgroup task_reduction (+:r2)
+ #pragma omp taskgroup task_reduction (+:r2) allocate (r2)
#pragma omp master taskloop \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) \
- reduction(default, +:r) in_reduction(+:r2)
+ reduction(default, +:r) in_reduction(+:r2) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
- #pragma omp taskgroup task_reduction (+:r2)
+ #pragma omp taskgroup task_reduction (+:r2) allocate (r2)
#pragma omp master taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel master taskloop \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) \
- reduction(default, +:r) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t)
+ reduction(default, +:r) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel master taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
- #pragma omp taskgroup task_reduction (+:r2)
+ #pragma omp taskgroup task_reduction (+:r2) allocate (r2)
#pragma omp master taskloop \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \
reduction(default, +:r) in_reduction(+:r2)
for (int i = 0; i < 64; i++)
ll++;
- #pragma omp taskgroup task_reduction (+:r2)
+ #pragma omp taskgroup task_reduction (+:r2) allocate (r2)
#pragma omp master taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel master taskloop \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \
- reduction(default, +:r) num_threads (nth) proc_bind(spread) copyin(t)
+ reduction(default, +:r) num_threads (nth) proc_bind(spread) copyin(t) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp parallel master taskloop simd \
private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \
safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) num_threads (nth) proc_bind(spread) copyin(t) \
- order(concurrent)
+ order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
#pragma omp loop bind(thread) order(concurrent) \
@@ -299,46 +327,50 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
ll++;
#pragma omp parallel loop \
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) collapse(1) bind(parallel) order(concurrent)
+ lastprivate (l) collapse(1) bind(parallel) order(concurrent) allocate (f)
for (l = 0; l < 64; l++)
ll++;
#pragma omp parallel loop \
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \
- lastprivate (l) collapse(1)
+ lastprivate (l) collapse(1) allocate (f)
for (l = 0; l < 64; l++)
ll++;
#pragma omp teams loop \
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
- collapse(1) lastprivate (l) bind(teams)
+ collapse(1) lastprivate (l) bind(teams) allocate (f)
for (l = 0; l < 64; ++l)
;
#pragma omp teams loop \
private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \
- collapse(1) lastprivate (l) order(concurrent)
+ collapse(1) lastprivate (l) order(concurrent) allocate (f)
for (l = 0; l < 64; ++l)
;
#pragma omp target parallel loop \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- nowait depend(inout: dd[0]) lastprivate (l) bind(parallel) order(concurrent) collapse(1)
+ nowait depend(inout: dd[0]) lastprivate (l) bind(parallel) order(concurrent) collapse(1) \
+ allocate (omp_default_mem_alloc: f)
for (l = 0; l < 64; ++l)
;
#pragma omp target parallel loop \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \
- nowait depend(inout: dd[0]) lastprivate (l) order(concurrent) collapse(1)
+ nowait depend(inout: dd[0]) lastprivate (l) order(concurrent) collapse(1) \
+ allocate (omp_default_mem_alloc: f)
for (l = 0; l < 64; ++l)
;
#pragma omp target teams loop \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) \
- lastprivate (l) bind(teams) collapse(1)
+ lastprivate (l) bind(teams) collapse(1) \
+ allocate (omp_default_mem_alloc: f)
for (l = 0; l < 64; ++l)
;
#pragma omp target teams loop \
device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) \
- lastprivate (l) order(concurrent) collapse(1)
+ lastprivate (l) order(concurrent) collapse(1) \
+ allocate (omp_default_mem_alloc: f)
for (l = 0; l < 64; ++l)
;
}
diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-2.c b/gcc/testsuite/c-c++-common/gomp/clauses-2.c
index ded1d74..bbc8fb4 100644
--- a/gcc/testsuite/c-c++-common/gomp/clauses-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/clauses-2.c
@@ -13,35 +13,35 @@ foo (int *p, int q, struct S t, int i, int j, int k, int l)
bar (p);
#pragma omp target map (p[0]) map (p) /* { dg-error "appears both in data and map clauses" } */
bar (p);
- #pragma omp target map (p) , map (p[0]) /* { dg-error "appears both in data and map clauses" } */
+ #pragma omp target map (p) , map (p[0])
bar (p);
#pragma omp target map (q) map (q) /* { dg-error "appears more than once in map clauses" } */
bar (&q);
#pragma omp target map (p[0]) map (p[0]) /* { dg-error "appears more than once in data clauses" } */
bar (p);
- #pragma omp target map (t) map (t.r) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t) map (t.r)
bar (&t.r);
- #pragma omp target map (t.r) map (t) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t.r) map (t)
bar (&t.r);
- #pragma omp target map (t.r) map (t.r) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t.r) map (t.r)
bar (&t.r);
#pragma omp target firstprivate (t), map (t.r) /* { dg-error "appears both in data and map clauses" } */
bar (&t.r);
#pragma omp target map (t.r) firstprivate (t) /* { dg-error "appears both in data and map clauses" } */
bar (&t.r);
- #pragma omp target map (t.s[0]) map (t) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t.s[0]) map (t)
bar (t.s);
- #pragma omp target map (t) map(t.s[0]) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t) map(t.s[0])
bar (t.s);
#pragma omp target firstprivate (t) map (t.s[0]) /* { dg-error "appears both in data and map clauses" } */
bar (t.s);
#pragma omp target map (t.s[0]) firstprivate (t) /* { dg-error "appears both in data and map clauses" } */
bar (t.s);
- #pragma omp target map (t.s[0]) map (t.s[2]) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t.s[0]) map (t.s[2])
bar (t.s);
- #pragma omp target map (t.t[0:2]) map (t.t[4:6]) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t.t[0:2]) map (t.t[4:6])
bar (t.t);
- #pragma omp target map (t.t[i:j]) map (t.t[k:l]) /* { dg-error "appears more than once in map clauses" } */
+ #pragma omp target map (t.t[i:j]) map (t.t[k:l])
bar (t.t);
#pragma omp target map (t.s[0]) map (t.r)
bar (t.s);
@@ -50,5 +50,5 @@ foo (int *p, int q, struct S t, int i, int j, int k, int l)
#pragma omp target map (t.r) map (t) map (t.s[0]) firstprivate (t) /* { dg-error "appears both in data and map clauses" } */
bar (t.s);
#pragma omp target map (t) map (t.r) firstprivate (t) map (t.s[0]) /* { dg-error "appears both in data and map clauses" } */
- bar (t.s); /* { dg-error "appears more than once in map clauses" "" { target *-*-* } .-1 } */
+ bar (t.s);
}
diff --git a/gcc/testsuite/c-c++-common/gomp/depobj-2.c b/gcc/testsuite/c-c++-common/gomp/depobj-2.c
new file mode 100644
index 0000000..d06910c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/depobj-2.c
@@ -0,0 +1,11 @@
+/* PR c++/98072 */
+
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+ char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+void
+foo (int *x, omp_depend_t *y, int z)
+{
+ #pragma omp depobj (*y) depend (in: x[z])
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-4.c b/gcc/testsuite/c-c++-common/gomp/doacross-4.c
new file mode 100644
index 0000000..a1182e3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/doacross-4.c
@@ -0,0 +1,30 @@
+/* PR middle-end/98205 */
+
+void baz (int) __attribute__((noreturn));
+
+void
+foo (int n)
+{
+ int i;
+ #pragma omp for ordered(1)
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered depend(source)
+ #pragma omp ordered depend(sink: i - 2)
+ baz (i);
+ }
+}
+
+void
+bar (int n)
+{
+ int i, j;
+ #pragma omp for collapse(2) ordered(2)
+ for (i = 0; i < 8; i += n)
+ for (j = 0; j < 8; j += n)
+ {
+ #pragma omp ordered depend(source)
+ #pragma omp ordered depend(sink: i - 2, j + 2)
+ baz (i);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/map-1.c b/gcc/testsuite/c-c++-common/gomp/map-1.c
index 508dc8d..ed88944 100644
--- a/gcc/testsuite/c-c++-common/gomp/map-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/map-1.c
@@ -1,5 +1,8 @@
-/* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
+/* Test 'map' clause diagnostics. */
+
+/* See also corresponding OpenMP C++ variant: '../../g++.dg/gomp/map-1.C'. */
+
+/* See also corresponding OpenACC variant: '../goacc/data-clause-1.c'. */
extern int a[][10], a2[][10];
int b[10], c[10][2], d[10], e[10], f[10];
diff --git a/gcc/testsuite/c-c++-common/gomp/map-2.c b/gcc/testsuite/c-c++-common/gomp/map-2.c
index 101f404..01fb4be 100644
--- a/gcc/testsuite/c-c++-common/gomp/map-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/map-2.c
@@ -1,5 +1,8 @@
-/* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
+/* Test 'map' clause diagnostics. */
+
+/* See also corresponding OpenMP C++ variant: '../../g++.dg/gomp/map-2.C'. */
+
+/* See also corresponding OpenACC variant: '../goacc/data-clause-2.c'. */
void
foo (int *p, int (*q)[10], int r[10], int s[10][10])
diff --git a/gcc/testsuite/c-c++-common/gomp/map-5.c b/gcc/testsuite/c-c++-common/gomp/map-5.c
new file mode 100644
index 0000000..1d9d925
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/map-5.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+void foo (void)
+{
+ /* Basic test to ensure to,from,tofrom is ordered before alloc,release,delete clauses. */
+ int a, b, c;
+ #pragma omp target enter data map(alloc:a) map(to:b) map(alloc:c)
+ #pragma omp target exit data map(from:a) map(release:b) map(from:c)
+
+ #pragma omp target map(alloc:a) map(tofrom:b) map(alloc:c)
+ a = b = c = 1;
+
+ #pragma omp target enter data map(to:a) map(alloc:b) map(to:c)
+ #pragma omp target exit data map(from:a) map(delete:b) map(from:c)
+}
+
+/* { dg-final { scan-tree-dump "pragma omp target enter data map\\(to:.* map\\(alloc:.* map\\(alloc:.*" "gimple" } } */
+/* { dg-final { scan-tree-dump "pragma omp target exit data map\\(from:.* map\\(from:.* map\\(release:.*" "gimple" } } */
+
+/* { dg-final { scan-tree-dump "pragma omp target num_teams.* map\\(tofrom:.* map\\(alloc:.* map\\(alloc:.*" "gimple" } } */
+
+/* { dg-final { scan-tree-dump "pragma omp target enter data map\\(to:.* map\\(to:.* map\\(alloc:.*" "gimple" } } */
+/* { dg-final { scan-tree-dump "pragma omp target exit data map\\(from:.* map\\(from:.* map\\(delete:.*" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/pr79428-2.c b/gcc/testsuite/c-c++-common/gomp/pr79428-2.c
index 0914963..6d162a2 100644
--- a/gcc/testsuite/c-c++-common/gomp/pr79428-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/pr79428-2.c
@@ -5,5 +5,4 @@ foo ()
{
#pragma omp sections
#pragma omp section /* { dg-error "'#pragma omp section' may only be used in '#pragma omp sections' construct|not allowed" } */
-// { dg-error "expected" "end" { target c } .-1 }
-// { dg-error "-:expected" "end" { target c++ } .+1 }
+// { dg-error "expected" "end" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/c-c++-common/gomp/pr97862.c b/gcc/testsuite/c-c++-common/gomp/pr97862.c
new file mode 100644
index 0000000..21aad3f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr97862.c
@@ -0,0 +1,15 @@
+/* PR middle-end/97862 */
+
+void
+foo (void)
+{
+ int i, j;
+#pragma omp for collapse(2)
+ for (i = 0; i < 1; ++i)
+ for (j = 0; j < i; ++j)
+ ;
+#pragma omp for collapse(2)
+ for (i = 0; i < 20; i++)
+ for (j = 0; j < i - 19; j += 1)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr97958.c b/gcc/testsuite/c-c++-common/gomp/pr97958.c
new file mode 100644
index 0000000..5a6de02
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr97958.c
@@ -0,0 +1,17 @@
+/* PR c/97958 */
+
+int *p;
+
+void
+foo (void)
+{
+ #pragma omp atomic
+ p = p + 1;
+}
+
+void
+bar (void)
+{
+ #pragma omp atomic /* { dg-error "invalid expression type for '#pragma omp atomic'" } */
+ bar = bar + 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr98187.c b/gcc/testsuite/c-c++-common/gomp/pr98187.c
new file mode 100644
index 0000000..fc252fd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr98187.c
@@ -0,0 +1,109 @@
+/* PR c++/98187 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -O2 -fdump-tree-gimple" } */
+/* { dg-final { scan-tree-dump-times "#pragma omp simd" 17 "gimple" } } */
+
+void
+foo (int *p)
+{
+ int i;
+ #pragma omp distribute parallel for
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp distribute parallel for simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp distribute simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+}
+
+void
+bar (int *p)
+{
+ int i;
+ #pragma omp for simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp master taskloop
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp master taskloop simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp parallel for
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp parallel for simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp parallel loop
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp parallel master
+ p[0]++;
+ #pragma omp parallel master taskloop
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp parallel master taskloop simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp parallel sections
+ {
+ p[0]++;
+ #pragma omp section
+ p[1]++;
+ #pragma omp section
+ p[2]++;
+ }
+ #pragma omp target parallel
+ #pragma omp master
+ p[0]++;
+ #pragma omp target parallel for
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target parallel for simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target parallel loop
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target teams private (i)
+ i = 0;
+ #pragma omp target teams distribute
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target teams distribute parallel for
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target teams distribute parallel for simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target teams distribute simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target teams loop
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp target simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp taskloop simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp teams distribute
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp teams distribute parallel for
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp teams distribute parallel for simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp teams distribute simd
+ for (i = 0; i < 64; i++)
+ p[i]++;
+ #pragma omp teams loop
+ for (i = 0; i < 64; i++)
+ p[i]++;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c
new file mode 100644
index 0000000..d38b1f3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* This program fails at runtime in the libhwasan library.
+ The allocator can't handle the requested invalid alignment. */
+
+int
+main ()
+{
+ void *p = __builtin_aligned_alloc (17, 100);
+ if (((unsigned long long)p & 0x10) == 0)
+ return 0;
+ return 1;
+}
+
+/* { dg-output "HWAddressSanitizer: invalid alignment requested in aligned_alloc: 17" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c
new file mode 100644
index 0000000..5e4c168
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+#define alloca __builtin_alloca
+
+int __attribute__ ((noinline))
+using_alloca (int num)
+{
+ int retval = 0;
+ int *big_array = (int*)alloca (num * sizeof (int));
+ for (int i = 0; i < num; ++i) {
+ retval += big_array[i];
+ }
+ return retval;
+}
+
+int __attribute__ ((noinline))
+using_vararray (int num)
+{
+ int retval = 0;
+ int big_array[num];
+ for (int i = 0; i < num; ++i) {
+ retval += big_array[i];
+ }
+ return retval;
+}
+
+int main()
+{
+ using_alloca (16);
+ using_vararray (12);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c b/gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c
new file mode 100644
index 0000000..3ebeaa0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-additional-options "--param hwasan-random-frame-tag=1" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+#include <alloca.h>
+
+/* This testcase checks that `alloca` calls ensure the `__hwasan_generate_tag`
+ function is called to initialize the base tag. `alloca` calls are treated
+ differently to standard variables. The prologue/epilogue sequence is
+ generated mainly based on normal stack-allocated objects.
+
+ We want to ensure that though the `alloca` call is not poisoned/unpoisoned
+ by the prologue and epilogue, the use of them in a given function still
+ triggers the prologue sequence to emit a call to __hwasan_generate_tag (and
+ hence that any call to __hwasan_generate_tag is emitted in the unconditional
+ part of the function code). */
+
+int choice = 0;
+int record = 1;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+__attribute__ ((noinline))
+unsigned char
+__hwasan_generate_tag ()
+{
+ record = 0;
+ return 3;
+}
+#ifdef __cplusplus
+}
+#endif
+
+__attribute__ ((noinline))
+int
+generate_tag_was_missed (void)
+{
+ return record;
+}
+
+__attribute__((noinline, noclone)) int
+foo (char *a)
+{
+ int i, j = 0;
+ asm volatile ("" : "+r" (a) : : "memory");
+ for (i = 0; i < 12; i++)
+ j += a[i];
+ return j;
+}
+
+int
+main ()
+{
+ if (choice)
+ {
+ char *x = (char *)alloca(100);
+ foo(x);
+ }
+ else
+ {
+ char *y = (char *)alloca(20);
+ foo(y);
+ }
+ return generate_tag_was_missed ();
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c b/gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c
new file mode 100644
index 0000000..e83734f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+/* Alloca is given a different tag to other variables.
+ vararray should behave in the same way. */
+
+#define alloca __builtin_alloca
+#define assert(x) if (!(x)) __builtin_abort ()
+
+struct two_values {
+ int left;
+ int right;
+};
+
+/* Require default hwasan tag ABI.
+ Know we're using AArch64 since that's the only architecture we run hwasan
+ tests on. */
+char tag_of (void * x) { return ((unsigned long long)x) >> 56; }
+
+int __attribute__ ((noinline))
+alloca_different_tag (int num)
+{
+ struct two_values tmp_object = {
+ .left = 100,
+ .right = num,
+ };
+ int *big_array = (int *)alloca (num * sizeof (int));
+ int other_array[100];
+
+ char first_tag = tag_of (&tmp_object);
+ char second_tag = tag_of (big_array);
+ char other_tag = tag_of (other_array);
+ assert (first_tag != second_tag);
+ assert (second_tag != other_tag);
+ assert (first_tag != other_tag);
+ return 0;
+}
+
+int __attribute__ ((noinline))
+vararray_different_tag (int num)
+{
+ struct two_values tmp_object = {
+ .left = 100,
+ .right = num,
+ };
+ int big_array[num];
+ int other_array[100];
+
+ char first_tag = tag_of (&tmp_object);
+ char second_tag = tag_of (big_array);
+ char other_tag = tag_of (other_array);
+ assert (first_tag != second_tag);
+ assert (second_tag != other_tag);
+ assert (first_tag != other_tag);
+ return 0;
+}
+
+int __attribute__ ((noinline))
+main ()
+{
+ alloca_different_tag (10);
+ vararray_different_tag (8);
+ return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c b/gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c
new file mode 100644
index 0000000..60d7a9a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+#define alloca __builtin_alloca
+
+int __attribute__ ((noinline))
+check_alloca (int num)
+{
+ volatile int *allocd_array = (int*)alloca (num * sizeof(int));
+ int other_array[10];
+ return allocd_array[12];
+}
+
+int __attribute__ ((noinline))
+main ()
+{
+ check_alloca (3);
+ return 1;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments-1.c b/gcc/testsuite/c-c++-common/hwasan/arguments-1.c
new file mode 100644
index 0000000..435dad3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/arguments-1.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=kernel-hwaddress" } */
+/* { dg-error ".*'-fsanitize=hwaddress' is incompatible with '-fsanitize=kernel-hwaddress'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments-2.c b/gcc/testsuite/c-c++-common/hwasan/arguments-2.c
new file mode 100644
index 0000000..fafde99
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/arguments-2.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=kernel-address" } */
+/* { dg-error ".*'-fsanitize=hwaddress' is incompatible with '-fsanitize=kernel-address'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments-3.c b/gcc/testsuite/c-c++-common/hwasan/arguments-3.c
new file mode 100644
index 0000000..6e907b4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/arguments-3.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=thread" } */
+/* { dg-error ".*'-fsanitize=thread' is incompatible with '-fsanitize=hwaddress'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments.c b/gcc/testsuite/c-c++-common/hwasan/arguments.c
new file mode 100644
index 0000000..7c11314
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/arguments.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=address" } */
+/* { dg-error ".*'-fsanitize=hwaddress' is incompatible with '-fsanitize=address'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c
new file mode 100644
index 0000000..dd3b3db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c
@@ -0,0 +1,24 @@
+/* PR sanitizer/63316 */
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void *malloc (__SIZE_TYPE__);
+extern void free (void *);
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+ int *p = (int *) malloc (sizeof (int));
+ *p = 3;
+ asm volatile ("" : : "r" (p) : "memory");
+ free (p);
+ return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c
new file mode 100644
index 0000000..ba2ed49
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+/* { dg-shouldfail "hwasan" } */
+
+#include <stdio.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void *malloc (__SIZE_TYPE__);
+extern void free (void *);
+#ifdef __cplusplus
+}
+#endif
+
+struct Simple {
+ int value;
+};
+
+int f(struct Simple simple) {
+ return simple.value;
+}
+
+int main() {
+ struct Simple *psimple = (struct Simple *) malloc(sizeof(struct Simple));
+ psimple->value = 42;
+ free(psimple);
+ printf("%d\n", f(*psimple));
+ return 0;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "freed by thread T0 here:.*" } */
+/* { dg-output "previously allocated here:" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c
new file mode 100644
index 0000000..3f53ad1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c
@@ -0,0 +1,31 @@
+/* PR sanitizer/78106 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=hwaddress -fdump-tree-sanopt-details -ffat-lto-objects" } */
+
+int *variable;
+
+void __attribute__((used)) release()
+{
+ __builtin_free (variable);
+}
+
+int main2(int argc)
+{
+ *variable = 2;
+
+ if (argc <= 5)
+ asm volatile ("call release");
+
+ *variable = 2;
+ __builtin_abort ();
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ variable = (int *)__builtin_malloc (sizeof(int));
+ return main2(argc);
+}
+
+/* { dg-final { scan-tree-dump-not "Optimizing out(\n|\r\n|\r) HWASAN_CHECK \\(7, variable.*" "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c
new file mode 100644
index 0000000..7d54f54
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c
@@ -0,0 +1,19 @@
+/* PR sanitizer/79944 */
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+struct S { int i; char p[1024]; };
+
+int
+main ()
+{
+ struct S *p = (struct S *) __builtin_malloc (__builtin_offsetof (struct S, p) + 64);
+ p->i = 5;
+ asm volatile ("" : "+r" (p) : : "memory");
+ __atomic_fetch_add ((int *) p, 5, __ATOMIC_RELAXED);
+ asm volatile ("" : "+r" (p) : : "memory");
+ if (p->i != 10)
+ __builtin_abort ();
+ __builtin_free (p);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c b/gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c
new file mode 100644
index 0000000..5426b8a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c
@@ -0,0 +1,24 @@
+/* Check that we properly report mmap failure. */
+
+/* { dg-do run { target setrlimit } } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+/* { dg-require-effective-target hw } */
+/* { dg-shouldfail "hwasan" } */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static volatile void *x;
+
+int main(int argc, char **argv) {
+ struct rlimit mmap_resource_limit = { 0, 0 };
+ if (setrlimit(RLIMIT_AS, &mmap_resource_limit)) return 1;
+ x = malloc(10000000);
+ return 0;
+}
+
+/* { dg-output "ERROR: Failed to mmap" } */
+
diff --git a/gcc/testsuite/c-c++-common/hwasan/bitfield-1.c b/gcc/testsuite/c-c++-common/hwasan/bitfield-1.c
new file mode 100644
index 0000000..0c3479e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/bitfield-1.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+struct bitmapped_struct {
+ unsigned one : 1;
+ unsigned two : 1;
+ unsigned three : 1;
+ unsigned four : 1;
+ unsigned five : 1;
+ unsigned six : 1;
+ unsigned seven : 1;
+ unsigned eight : 1;
+};
+
+/* Check that hwasan allows valid bitfield accesses. */
+int __attribute__ ((noinline))
+handle_unaligned_access (struct bitmapped_struct *foo)
+{
+ if (foo->three)
+ return foo->four;
+
+ foo->five = 1;
+ return 1;
+}
+
+int main()
+{
+ struct bitmapped_struct myvar = {0};
+ handle_unaligned_access (&myvar);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/bitfield-2.c b/gcc/testsuite/c-c++-common/hwasan/bitfield-2.c
new file mode 100644
index 0000000..0b3f3aaa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/bitfield-2.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+/* Ensure that hwasan instruments bitfield accesses. */
+struct A
+{
+ /* Ensure the offset from the start of this struct to the bitfield we access
+ is large enough to be in a different tag. */
+ char base[16];
+ int : 4;
+ long x : 7;
+};
+
+int __attribute__ ((noinline, noclone))
+f (void *p) {
+ return ((struct A *)p)->x;
+}
+
+int
+main ()
+{
+ char a = 0;
+ return f (&a);
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 2 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c b/gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c
new file mode 100644
index 0000000..a7a6d91
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-asan" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* Only skip the -flto tests without the -flto-partition=none.
+ With -flto-partition=none we still get a asan1 dump file, without that
+ parameter we only get the lto dump files (which means scan-tree-dump-times
+ doesn't work. */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "-flto-partition=none" } } */
+
+typedef __SIZE_TYPE__ size_t;
+/* Functions to observe that HWASAN instruments memory builtins in the expected
+ manner. */
+void * __attribute__((noinline))
+memset_builtin (void *dest, int value, size_t len)
+{
+ return __builtin_memset (dest, value, len);
+}
+
+/* HWASAN avoids strlen because it doesn't know the size of the memory access
+ until *after* the function call. */
+size_t __attribute__ ((noinline))
+strlen_builtin (char *element)
+{
+ return __builtin_strlen (element);
+}
+
+/* First test ensures that the HWASAN_CHECK was emitted before the
+ memset. Second test ensures there was only HWASAN_CHECK (which demonstrates
+ that strlen was not instrumented). */
+/* { dg-final { scan-tree-dump-times "HWASAN_CHECK.*memset" 1 "asan1" } } */
+/* { dg-final { scan-tree-dump-times "HWASAN_CHECK" 1 "asan1" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/check-interface.c b/gcc/testsuite/c-c++-common/hwasan/check-interface.c
new file mode 100644
index 0000000..90f52ca
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/check-interface.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/*
+ Test taken from LLVM
+ compiler-rt/test/hwasan/TestCases/check-interface.cpp
+ */
+// Utilizes all flavors of __hwasan_load/store interface functions to verify
+// that the instrumentation and the interface provided by HWASan do match.
+// In case of a discrepancy, this test fails to link.
+
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+#define F(T) void f_##T(T *a, T *b) { *a = *b; }
+
+F(uint8_t)
+F(uint16_t)
+F(uint32_t)
+F(uint64_t)
+
+typedef unsigned V32 __attribute__((__vector_size__(32)));
+F(V32)
+
+int main() {}
diff --git a/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c
new file mode 100644
index 0000000..90ca856
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c
@@ -0,0 +1,24 @@
+/* Test recovery mode. */
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-options "-fsanitize-recover=hwaddress" } */
+/* { dg-set-target-env-var HWASAN_OPTIONS "halt_on_error=false" } */
+/* { dg-shouldfail "hwasan" } */
+
+volatile int sixteen = 16;
+
+int main() {
+ char x[16];
+ __builtin_memset(x, 0, sixteen + 1);
+ asm volatile ("" : : : "memory");
+ volatile int res = x[sixteen];
+ x[sixteen] = res + 3;
+ res = x[sixteen];
+ return 0;
+}
+
+/* { dg-output "WRITE of size 17 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */
+
diff --git a/gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c b/gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c
new file mode 100644
index 0000000..685b780
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target aarch64-*-* } } */
+/* { dg-additional-options "-march=armv8.6-a+sve -fsanitize-address-use-after-scope" } */
+
+#include <arm_sve.h>
+
+__attribute__((noinline, noclone)) int
+foo (char *a)
+{
+ int i, j = 0;
+ asm volatile ("" : "+r" (a) : : "memory");
+ for (i = 0; i < 12; i++)
+ j += a[i];
+ return j;
+}
+
+int
+main ()
+{
+ int i, j = 0;
+ for (i = 0; i < 4; i++)
+ {
+ char a[12];
+ __SVInt8_t freq;
+ /* Just do something with that `freq` variable so that the compiler
+ doesn't optimise its use away. */
+ if (__builtin_bcmp (&freq, a, 10))
+ j += 1;
+ __builtin_memset (a, 0, sizeof (a));
+ j += foo (a);
+ }
+ return j;
+}
+
+/* Just ensure this compiles without giving an ICE.
+ This is the equivalent of PR 97696 but for HWASAN. HWASAN can handle
+ poly_int sized variables, and this testcase ensures that we don't ICE when
+ given them. */
diff --git a/gcc/testsuite/c-c++-common/hwasan/heap-overflow.c b/gcc/testsuite/c-c++-common/hwasan/heap-overflow.c
new file mode 100644
index 0000000..1374668
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/heap-overflow.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free -fno-builtin-memset" } */
+/* { dg-shouldfail "hwasan" } */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void *memset (void *, int, __SIZE_TYPE__);
+void *malloc (__SIZE_TYPE__);
+void free (void *);
+#ifdef __cplusplus
+}
+#endif
+
+volatile int ten = 10;
+int main(int argc, char **argv) {
+ char *x = (char*)malloc(10);
+ memset(x, 0, 10);
+ int res = x[ten]; /* BOOOM */
+ free(x);
+ return res;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "located 0 bytes to the right of 10-byte region.*" } */
+/* { dg-output "allocated here:.*" } */
+/* { dg-output "#1 0x\[0-9a-f\]+ +in _*main \[^\n\r]*heap-overflow.c:18" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c
new file mode 100644
index 0000000..2d6bab4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-additional-options "-fdump-tree-asan1 -save-temps" } */
+
+/* Here to check that the ASAN_POISON stuff works just fine.
+ This mechanism isn't very often used, but I should at least go through the
+ code-path once in my testfile. */
+int
+main ()
+{
+ int *ptr = 0;
+
+ {
+ int a;
+ ptr = &a;
+ *ptr = 12345;
+ }
+
+ return *ptr;
+}
+
+/* { dg-final { scan-tree-dump-times "ASAN_POISON" 1 "asan1" } } */
+/* { dg-final { scan-assembler-times "bl\\s*__hwasan_tag_mismatch4" 1 } } */
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c
new file mode 100644
index 0000000..828909d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "-lpthread" } */
+
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int printf (char const *, ...);
+#ifdef __cplusplus
+}
+#endif
+typedef __UINTPTR_TYPE__ uintptr_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+/* Test that tags are checked across different threads.
+ i.e. if this thread tries to access a different threads memory with the
+ incorrect tag, then this thread fails. */
+void *
+failing_thread_function (void *argument)
+{
+ void * other = (void *)((uint64_t)argument & 0xffffffffffffffULL);
+ int *num = (int*)argument;
+ printf ("(should succeed): first number = %d\n", num[0]);
+ printf ("(now should fail):\n");
+
+ int *othernum = (int*)other;
+ printf (" second number = %d\n", othernum[0]);
+ return (void *)1;
+}
+
+int
+main (int argc, char **argv)
+{
+ int argument[100] = {0};
+ argument[1] = 10;
+ pthread_t thread_index;
+ pthread_create (&thread_index, NULL, failing_thread_function, (void*)argument);
+
+ void *retval;
+ pthread_join (thread_index, &retval);
+
+ return (uintptr_t)retval;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: 00/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T1.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c
new file mode 100644
index 0000000..6a07521
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "-lpthread" } */
+
+/* Ensure the failure mode for hwasan under pthreads looks sane.
+ (Looks sane means that the same error message is printed out rather than an
+ opaque message due to mishandling). */
+
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int printf (char const *, ...);
+#ifdef __cplusplus
+}
+#endif
+typedef __UINTPTR_TYPE__ uintptr_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+void *
+failing_from_stack (void * argument)
+{
+ int internal_array[16] = {0};
+ printf ("(now should fail):");
+ printf (" problem number is %d\n", internal_array[17]);
+ return (void *)1;
+}
+
+int
+main (int argc, char **argv)
+{
+ int argument[100] = {0};
+ argument[1] = 10;
+ pthread_t thread_index;
+ pthread_create (&thread_index, NULL, failing_from_stack, (void*)argument);
+
+ void *retval;
+ pthread_join (thread_index, &retval);
+
+ return (uintptr_t)retval;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T1.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T1.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c
new file mode 100644
index 0000000..09c72a5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "-lpthread" } */
+
+/* This checks the interceptor ABI pthread hooks.
+ The stack of the thread that is finishing must be cleared of shadow tags
+ when that thread exits. */
+
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int printf (char const *, ...);
+#ifdef __cplusplus
+}
+#endif
+typedef __UINTPTR_TYPE__ uintptr_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+__attribute__ ((noinline))
+void * Ident (void * argument)
+{
+ return argument;
+}
+
+void *
+pthread_stack_is_cleared (void *argument)
+{
+ (void)argument;
+ int internal_array[16] = {0};
+ return Ident((void*)internal_array);
+}
+
+int
+main (int argc, char **argv)
+{
+ int argument[100] = {0};
+ argument[1] = 10;
+ pthread_t thread_index;
+ pthread_create (&thread_index, NULL, pthread_stack_is_cleared, (void*)argument);
+
+ void *retval;
+ pthread_join (thread_index, &retval);
+
+ printf ("(should fail): ");
+ printf ("value left in stack is: %d\n", ((int *)retval)[0]);
+
+ return (uintptr_t)retval;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "HWAddressSanitizer can not describe address in more detail\..*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c
new file mode 100644
index 0000000..b0281f7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-additional-options "-lpthread" } */
+
+/* Just ensure that a basic threaded program works while running with hwasan.
+ */
+
+#include <pthread.h>
+
+extern int printf (const char *, ...);
+typedef __UINTPTR_TYPE__ uintptr_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+void *
+successful_thread_function (void * argument)
+{
+ int *deref = (int *)argument;
+ if (deref[0] == 100)
+ deref[1] = 10;
+ return (void *)0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int argument[100] = {0};
+ argument[1] = 10;
+ pthread_t thread_index;
+ pthread_create (&thread_index, NULL, successful_thread_function, (void*)argument);
+
+ void *retval;
+ pthread_join (thread_index, &retval);
+
+ return (uintptr_t)retval;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c b/gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c
new file mode 100644
index 0000000..abfe735
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-sanitize=hwaddress -fsanitize=kernel-hwaddress" } */
+
+
+/* Defaults to check for kernel-hwaddress.
+ 1) No stack tagging => no calls to __hwasan_tag_memory.
+ 2) No block scope tagging (same again).
+ 3) Use sanitize-recover by default (everything ends in noabort). */
+int __attribute__ ((noinline))
+accessing_pointers (int *left, int *right)
+{
+ int x = right[2];
+ left[3] = right[1];
+ return right[1] + left[2];
+}
+
+int __attribute__ ((noinline))
+using_stack (int num)
+{
+ int big_array[10];
+ int other_array[20];
+ accessing_pointers(other_array, big_array);
+ return big_array[num];
+}
+
+#ifndef ARG
+#define ARG 0
+#endif
+int __attribute__ ((noinline))
+main ()
+{
+ using_stack (ARG);
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "__hwasan_tag_memory" } } */
+/* { dg-final { scan-assembler-not "__hwasan_(load|store)\\d(?!_noabort)" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c
new file mode 100644
index 0000000..5b0071a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+/* Handling large aligned variables.
+ Large aligned variables take a different code-path through expand_stack_vars
+ in cfgexpand.c. This testcase is just to exercise that code-path.
+
+ The alternate code-path produces a second base-pointer through some
+ instructions emitted in the prologue.
+
+ Test cases are:
+ 0) Valid access works without complaint.
+ 1) Invalid access is caught. */
+int __attribute__ ((noinline))
+handle_large_alignment (int num)
+{
+ int other_array[10];
+ int big_array[100] __attribute__ ((aligned (32)));
+ return big_array[num] + other_array[num];
+}
+
+#ifndef ARG
+#define ARG 1
+#endif
+
+int global;
+
+int __attribute__ ((noinline))
+main ()
+{
+ global += handle_large_alignment (ARG);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c
new file mode 100644
index 0000000..1aa1303
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+#define ARG 12
+#include "large-aligned-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c
new file mode 100644
index 0000000..11f422f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* Don't really need this option since there are no vararray/alloca objects in
+ the interesting function, however it never hurts to make doubly sure and
+ make it explicit that we're checking the alternate approach to deallocation.
+ */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+/* Handling large aligned variables.
+ Large aligned variables take a different code-path through expand_stack_vars
+ in cfgexpand.c. This testcase is just to exercise that code-path.
+
+ The alternate code-path produces a second base-pointer through some
+ instructions emitted in the prologue.
+
+ This eventually follows a different code path for untagging when not tagging
+ allocas. The untagging needs to work at the top of the frame, and this
+ should account for this different base when large aligned variables are
+ around. */
+__attribute__ ((noinline))
+void * Ident (void * argument)
+{
+ return argument;
+}
+
+#ifndef ALIGNMENT
+#define ALIGNMENT
+#endif
+void __attribute__ ((noinline))
+large_alignment_untagging (int num, int *retval, int **big, int **other)
+{
+ int other_array[100] ALIGNMENT;
+ int big_array[100] __attribute__ ((aligned (32)));
+ *retval = big_array[num] + other_array[num];
+ *big = (int*)Ident(big_array);
+ *other = (int*)Ident(other_array);
+}
+
+#ifndef ARG
+#define ARG 0
+#endif
+
+int global;
+
+int __attribute__ ((noinline))
+main ()
+{
+ int retval;
+ int *big, *other;
+ large_alignment_untagging (0, &retval, &big, &other);
+ /* Want to test that both ends of both variables are untagged. */
+ switch (ARG) {
+ case 0:
+ global += big[0];
+ break;
+ case 1:
+ global += big[99];
+ break;
+ case 2:
+ global += other[0];
+ break;
+ case 3:
+ global += other[99];
+ break;
+ }
+ return 0;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c
new file mode 100644
index 0000000..b2fc522
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 1
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c
new file mode 100644
index 0000000..ebc4648
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 2
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c
new file mode 100644
index 0000000..d3a226a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 3
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c
new file mode 100644
index 0000000..cdd122b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 0
+#define ALIGNMENT __attribute__ ((aligned (32)))
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c
new file mode 100644
index 0000000..7c4cb5c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 1
+#define ALIGNMENT __attribute__ ((aligned (32)))
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c
new file mode 100644
index 0000000..f429ed2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 2
+#define ALIGNMENT __attribute__ ((aligned (32)))
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c
new file mode 100644
index 0000000..56f16eb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */
+
+#define ARG 3
+#define ALIGNMENT __attribute__ ((aligned (32)))
+#include "large-aligned-untagging-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* NOTE: This assumes the current tagging mechanism (one at a time from the
+ base and large aligned variables being handled first). */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/macro-definition.c b/gcc/testsuite/c-c++-common/hwasan/macro-definition.c
new file mode 100644
index 0000000..5f654f5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/macro-definition.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+extern void testfunc(int);
+int foo()
+{
+#ifndef __SANITIZE_HWADDRESS__
+ testfunc(1);
+#endif
+ return 1;
+}
+
+/* { dg-final { scan-assembler-not "testfunc" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c b/gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c
new file mode 100644
index 0000000..c0a254d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+__attribute__((no_sanitize("hwaddress"))) int
+f (int *p, int *q)
+{
+ *p = 42;
+ return *q;
+}
+
+/* Only have one instance of __hwasan, it is __hwasan_init (the module
+ * constructor) there is no instrumentation in the function. */
+/* { dg-final { scan-assembler-times "__hwasan" 1 } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c
new file mode 100644
index 0000000..f1e6dc8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-additional-options "--param hwasan-instrument-mem-intrinsics=0" } */
+
+#include "builtin-special-handling.c"
+
+/* With this flag there should be no checking of builtins.
+ The above file only has builtins, and hence there should be no checking
+ after compilation. */
+/* { dg-final { scan-assembler-not "__hwasan_(load|store)" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c
new file mode 100644
index 0000000..1d565a2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param hwasan-instrument-writes=0" } */
+
+#include "param-instrument-reads.c"
+
+/* { dg-final { scan-assembler "__hwasan_load" } } */
+/* { dg-final { scan-assembler-not "__hwasan_store" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c
new file mode 100644
index 0000000..9b8049a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param hwasan-instrument-reads=0" } */
+
+typedef __SIZE_TYPE__ size_t;
+/* Particular code doesn't really matter, the requirement is that it has both
+ loads and stores in it. */
+__attribute__ ((noinline))
+int reader (int *array, size_t num)
+{
+ return array[num];
+}
+
+int __attribute__ ((noinline))
+writer (int *array, size_t num, int value)
+{
+ array[num] = value;
+ return num + value;
+}
+
+/* { dg-final { scan-assembler-not "__hwasan_load" } } */
+/* { dg-final { scan-assembler "__hwasan_store" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c
new file mode 100644
index 0000000..0f04fad
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param hwasan-instrument-reads=0 --param hwasan-instrument-writes=0" } */
+
+#include "param-instrument-reads.c"
+
+/* { dg-final { scan-assembler-not "__hwasan_load" } } */
+/* { dg-final { scan-assembler-not "__hwasan_store" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c b/gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c
new file mode 100644
index 0000000..8e55b29
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param hwasan-random-frame-tag=1" } */
+
+#include "stack-tagging-basic-0.c"
+
+/* Random frame tag => call to __hwasan_generate_tag. */
+/* { dg-final { scan-assembler "__hwasan_generate_tag" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c b/gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c
new file mode 100644
index 0000000..a42921bb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
+/* { dg-shouldfail "asan" } */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void *malloc (__SIZE_TYPE__);
+void free (void *);
+#ifdef __cplusplus
+}
+#endif
+
+int main() {
+ char *x = (char*)malloc(10);
+ free(x);
+ return x[5];
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "located 5 bytes inside of 10-byte region.*" } */
+/* { dg-output "freed by thread T0 here:.*" } */
+/* { dg-output "previously allocated here:" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c
new file mode 100644
index 0000000..019c4ea
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c
@@ -0,0 +1,54 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+#include <setjmp.h>
+#include <stdio.h>
+
+/*
+ Testing longjmp/setjmp should test.
+
+ 0) Nothing special happens with the jmp_buf.
+ 1) Accesses to scopes jmp'd over are caught.
+ */
+int __attribute__ ((noinline))
+uses_longjmp (int **other_array, int num, jmp_buf env)
+{
+ int internal_array[100] = {0};
+ *other_array = &internal_array[0];
+ if (num % 2)
+ longjmp (env, num);
+ else
+ return num % 8;
+}
+
+int __attribute__ ((noinline))
+uses_setjmp (int num)
+{
+ int big_array[100];
+ int *other_array = NULL;
+ sigjmp_buf cur_env;
+ int temp = 0;
+ if ((temp = sigsetjmp (cur_env, 1)) != 0)
+ {
+ if (other_array != NULL)
+ printf ("Value pointed to in other_array[0]: %d\n",
+ other_array[0]);
+
+ printf ("Longjmp returned %d.\n", temp);
+ return 10;
+ }
+ else
+ {
+ return uses_longjmp (&other_array, num, cur_env);
+ }
+}
+
+#ifndef ARG
+#define ARG 0
+#endif
+int __attribute__ ((noinline))
+main ()
+{
+ uses_setjmp (ARG);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c
new file mode 100644
index 0000000..6a4fcee
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+/*
+ Testing longjmp/setjmp should test.
+
+ 0) Nothing special happens with the jmp_buf.
+ 1) Accesses to scopes jmp'd over are caught.
+ */
+
+#define ARG 1
+#include "setjmp-longjmp-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c
new file mode 100644
index 0000000..1141141
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+/* Basic tests for stack tagging.
+
+ 0) Valid accesses work.
+ 1) Accesses outside of a variable crash.
+*/
+int __attribute__ ((noinline))
+accessing_pointers (int *left, int *right)
+{
+ int x = right[2];
+ left[3] = right[1];
+ return right[1] + left[2];
+}
+
+int __attribute__ ((noinline))
+using_stack (int num)
+{
+ int big_array[10];
+ int other_array[20];
+ accessing_pointers(other_array, big_array);
+ return big_array[num];
+}
+
+#ifndef ARG
+#define ARG 0
+#endif
+
+int global;
+
+int __attribute__ ((noinline))
+main ()
+{
+ global += using_stack (ARG);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c
new file mode 100644
index 0000000..90d5837
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+/* Basic tests for stack tagging.
+
+ 0) Accesses outside of a variable crash.
+ 1) Valid accesses work.
+*/
+
+#define ARG 17
+#include "stack-tagging-basic-0.c"
+#undef ARG
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c
new file mode 100644
index 0000000..9bcae16
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param hwasan-instrument-stack=0" } */
+
+
+/* No stack tagging => no calls to __hwasan_tag_memory. */
+int __attribute__ ((noinline))
+accessing_pointers (int *left, int *right)
+{
+ int x = right[2];
+ left[3] = right[1];
+ return right[1] + left[2];
+}
+
+int __attribute__ ((noinline))
+using_stack (int num)
+{
+ int big_array[10];
+ int other_array[20];
+ accessing_pointers(other_array, big_array);
+ return big_array[num];
+}
+
+#ifndef ARG
+#define ARG 0
+#endif
+int __attribute__ ((noinline))
+main ()
+{
+ using_stack (ARG);
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "__hwasan_tag_memory" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c
new file mode 100644
index 0000000..8846515
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0 -save-temps" } */
+/* Only run this test without optimisation. When running with optimisation we
+ use the unprotected-allocas-1.c file that also checks there are no memory
+ tagging calls (since when optimised the only variable on the stack should be
+ the vararray/alloca). */
+/* { dg-skip-if "" { *-*-* } { "-O1" "-O2" "-O3" } { "" } } */
+
+#define alloca __builtin_alloca
+#define assert(x) if (!(x)) __builtin_abort ()
+
+char tag_of (void * x) { return ((unsigned long long)x) >> 56; }
+
+int __attribute__ ((noinline))
+using_alloca (int num)
+{
+ int retval = 0;
+ int *big_array = (int*)alloca (num * sizeof (int));
+ char alloca_tag = tag_of (big_array);
+ assert (alloca_tag == 0);
+ for (int i = 0; i < num; ++i) {
+ retval += big_array[i];
+ }
+ return retval;
+}
+
+int __attribute__ ((noinline))
+using_vararray (int num)
+{
+ int retval = 0;
+ int big_array[num];
+ char vararray_tag = tag_of (big_array);
+ assert (vararray_tag == 0);
+ for (int i = 0; i < num; ++i) {
+ retval += big_array[i];
+ }
+ return retval;
+}
+
+int main()
+{
+ using_alloca (16);
+ using_vararray (12);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c
new file mode 100644
index 0000000..752edc1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-additional-options "--param hwasan-instrument-allocas=0 -save-temps" } */
+/* Only test there's no tagging done when not at -O0. Without optimisation
+ the compiler creates a bunch of other variables on the stack other than the
+ vararray/alloca object.
+ We also avoid checking when using -flto, since with LTO the compiler can
+ recognise the vararray is only used with one size and that size is known at
+ compile time -- when the compiler recognises that it instead creates a
+ static array, which gets tagged as is expected but not as the test expects.
+ */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-flto" } { "" } } */
+
+#include "unprotected-allocas-0.c"
+
+/* { dg-final { scan-assembler-not "__hwasan_tag_memory" } } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/use-after-free.c b/gcc/testsuite/c-c++-common/hwasan/use-after-free.c
new file mode 100644
index 0000000..41a3569
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/use-after-free.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
+/* { dg-shouldfail "hwasan" } */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void *malloc (__SIZE_TYPE__);
+void free (void *);
+#ifdef __cplusplus
+}
+#endif
+
+int main() {
+ char *x = (char*)malloc(10);
+ free(x);
+ return x[5];
+}
+
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "is located 5 bytes inside of 10-byte region.*" } */
+/* { dg-output "freed by thread T0 here:.*" } */
+/* { dg-output "#1\[^\n\r]*main\[^\n\r]*use-after-free.c:17.*" } */
+/* { dg-output "previously allocated here:.*" } */
+/* { dg-output "#1\[^\n\r]*main\[^\n\r]*use-after-free.c:16" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c b/gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c
new file mode 100644
index 0000000..35a344d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+int __attribute__ ((noinline))
+check_vararray (int num)
+{
+ int var_array[num];
+ int other_array[10];
+ return var_array[12];
+}
+
+int __attribute__ ((noinline))
+main ()
+{
+ return check_vararray (3);
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c b/gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c
new file mode 100644
index 0000000..f4e1f57
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+#include <stdio.h>
+
+/* Testing that a function with outgoing arguments correctly decrements the
+ stack pointer when a vararray goes out of scope. */
+
+const char *
+other (int argc, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l)
+{
+ const char ** other;
+ {
+ const char * test_array[argc];
+ test_array[0] = "test string";
+ test_array[argc - 1] = "hello";
+ /* To prevent optimisation. */
+ printf("While the value stored in our test_array is: %s\n",
+ test_array[argc - 1]);
+ other = test_array;
+ }
+ /* With the below function call (the one with many arguments), some of the
+ arguments have to be put on the stack, which means we have to reserve some
+ space on the stack for these arguments and that the VLA is stored at a
+ position that is not the stack pointer. */
+ printf("Hello there!\nOur numbers today are: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ a, b, c, d, e, f, g, h, i, j, k, l);
+ /* This should fail due to a bad read access. */
+ return other[0];
+}
+
+int
+main ()
+{
+ int a, b, c, d, e, f, g, h, i, j, k, l;
+ const char * retval = other (1, a, b, c, d, e, f, g, h, i, j, k, l);
+ /* Numbers don't matter here, just want to ensure the program is reading them
+ so we know they won't be optimised out. */
+ if (retval)
+ return 1;
+ return 10;
+}
diff --git a/gcc/testsuite/c-c++-common/hwasan/very-large-objects.c b/gcc/testsuite/c-c++-common/hwasan/very-large-objects.c
new file mode 100644
index 0000000..5526535
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/very-large-objects.c
@@ -0,0 +1,68 @@
+/* { dg-do compile } */
+
+/* Ensure the sanitizer can handle very large offsets (i.e. that the hooks
+ handle offsets too large for the relevant instructions).
+ Just want to make sure this compiles without an ICE. */
+#ifndef ASIZE
+# define ASIZE 0x10000000000UL
+#endif
+
+typedef __UINT64_TYPE__ uint64_t;
+
+#if __LONG_MAX__ < 8 * ASIZE
+# undef ASIZE
+# define ASIZE 4096
+#endif
+
+extern void abort (void);
+
+int __attribute__((noinline))
+foo (const char *s)
+{
+ if (!s)
+ return 1;
+ if (s[0] != 'a')
+ abort ();
+ s += ASIZE - 1;
+ if (s[0] != 'b')
+ abort ();
+ return 0;
+}
+
+int (*fn) (const char *) = foo;
+
+int __attribute__((noinline))
+bar (void)
+{
+ char s[ASIZE];
+ s[0] = 'a';
+ s[ASIZE - 1] = 'b';
+ foo (s);
+ foo (s);
+ return 0;
+}
+
+int __attribute__((noinline))
+baz (long i)
+{
+ if (i)
+ return fn (0);
+ else
+ {
+ char s[ASIZE];
+ s[0] = 'a';
+ s[ASIZE - 1] = 'b';
+ foo (s);
+ foo (s);
+ return fn (0);
+ }
+}
+
+int __attribute__((noinline))
+very_large_offset (int *p)
+{
+ char init_array[(uint64_t)0xfefefef];
+ char other_array[(uint64_t)0xfefefef];
+ return (int)init_array[p[1]] + (int)other_array[p[0]];
+}
+
diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-error-3.c b/gcc/testsuite/c-c++-common/patchable_function_entry-error-3.c
index 4490e5c..c3ef54d 100644
--- a/gcc/testsuite/c-c++-common/patchable_function_entry-error-3.c
+++ b/gcc/testsuite/c-c++-common/patchable_function_entry-error-3.c
@@ -3,15 +3,15 @@
void
__attribute__((patchable_function_entry(65536)))
-foo1 (void) { /* { dg-warning "'patchable_function_entry' attribute argument '65536' is out of range" } */
+foo1 (void) { /* { dg-warning "'patchable_function_entry' attribute argument '65536' exceeds 65535" } */
}
void
__attribute__((patchable_function_entry(65536,1)))
-foo2 (void) { /* { dg-warning "'patchable_function_entry' attribute argument '65536' is out of range" } */
+foo2 (void) { /* { dg-warning "'patchable_function_entry' attribute argument '65536' exceeds 65535" } */
}
void
__attribute__((patchable_function_entry(65536,65536)))
-foo3 (void) { /* { dg-warning "'patchable_function_entry' attribute argument '65536' is out of range" } */
+foo3 (void) { /* { dg-warning "'patchable_function_entry' attribute argument '65536' exceeds 65535" } */
}
diff --git a/gcc/testsuite/c-c++-common/raw-string-6.c b/gcc/testsuite/c-c++-common/raw-string-6.c
index a2cb30e..819dd44 100644
--- a/gcc/testsuite/c-c++-common/raw-string-6.c
+++ b/gcc/testsuite/c-c++-common/raw-string-6.c
@@ -3,5 +3,4 @@
// { dg-options "-std=c++0x" { target c++ } }
const void *s0 = R"ouch()ouCh"; // { dg-error "unterminated raw string" "unterminated" }
-// { dg-error "at end of input" "end" { target c } .-1 }
-// { dg-error "-:at end of input" "end" { target c++ } .+1 }
+// { dg-error "at end of input" "end" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-1.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-1.c
new file mode 100644
index 0000000..877e764
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-1.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-require-effective-target noinit } */
+/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
+/* { dg-options "-save-temps" } */
+/* { dg-final { scan-assembler ".section\t.noinit,\"aw\"\n" } } */
+
+#include "attr-noinit-main.inc"
diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-2.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-2.c
new file mode 100644
index 0000000..befa2a0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-2.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-require-effective-target noinit } */
+/* { dg-options "-fdata-sections -save-temps" } */
+/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
+/* { dg-final { scan-assembler ".section\t.noinit.var_noinit,\"aw\"\n" } } */
+
+/* Test the "noinit" attribute with -fdata-sections. */
+#include "attr-noinit-main.inc"
diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-3.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-3.c
new file mode 100644
index 0000000..519e88a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-3.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-require-effective-target noinit } */
+/* { dg-options "-flto -save-temps" } */
+/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
+/* { dg-final { scan-file attr-noinit-3.ltrans0.ltrans.s ".section\t\.noinit,\"aw\"\n" } } */
+
+/* Test the "noinit" attribute with -flto. Specifically examine the
+ final LTO assembly file, to ensure the "noinit" setting on the variable
+ hasn't been lost. */
+#include "attr-noinit-main.inc"
+
diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c
new file mode 100644
index 0000000..c3b5fff
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target noinit } */
+/* { dg-options "-Wattributes" } */
+
+/* Check warning/error messages for "noinit" attribute misuse. */
+int __attribute__((noinit)) noinit_fn (void); /* { dg-warning "ignoring 'noinit' attribute not set on a variable" } */
+int __attribute__((section ("mysection"), noinit)) noinit_section1; /* { dg-warning "because it conflicts with attribute" } */
+int __attribute__((noinit, section ("mysection"))) noinit_section2; /* { dg-warning "because it conflicts with attribute" } */
+const int __attribute__((noinit)) noinit_const; /* { dg-warning "ignoring 'noinit' attribute set on const variable" } */
+/* { dg-error "uninitialized 'const noinit_const'" "" { target c++ } .-1 } */
+int __attribute__((noinit)) noinit_init = 42; /* { dg-warning "ignoring 'noinit' attribute set on initialized variable" } */
+void foo (void) { int __attribute__((noinit)) local_noinit; } /* { dg-error "'noinit' attribute cannot be specified for local variables" } */
diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc b/gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc
new file mode 100644
index 0000000..92cdb9b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc
@@ -0,0 +1,58 @@
+/* This test checks that data marked with the "noinit" attribute is handled
+ correctly.
+ If data LMA != VMA (e.g. for simulating the copy of data from ROM to RAM),
+ then var_init will always be re-initialized to 2 and this test will loop
+ forever, so it must be skipped for those targets. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void _start (void) __attribute__ ((noreturn));
+#ifdef __cplusplus
+}
+#endif
+
+int var_common;
+int var_zero = 0;
+int var_one = 1;
+int __attribute__((noinit)) var_noinit;
+int var_init = 2;
+
+int
+main (void)
+{
+ /* Make sure that the C startup code has correctly initialized the ordinary variables. */
+ if (var_common != 0)
+ __builtin_abort ();
+
+ /* Initialized variables are not re-initialized during startup, so
+ check their original values only during the first run of this
+ test. */
+ if (var_init == 2)
+ if (var_zero != 0 || var_one != 1)
+ __builtin_abort ();
+
+ switch (var_init)
+ {
+ case 2:
+ /* First time through - change all the values. */
+ var_common = var_zero = var_one = var_noinit = var_init = 3;
+ break;
+
+ case 3:
+ /* Second time through - make sure that var_noinit has not been reset. */
+ if (var_noinit != 3)
+ __builtin_abort ();
+ __builtin_exit (0);
+
+ default:
+ /* Any other value for var_init is an error. */
+ __builtin_abort ();
+ }
+
+ /* Simulate a processor reset by calling the C startup code. */
+ _start ();
+
+ /* Should never reach here. */
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-1.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-1.c
new file mode 100644
index 0000000..72dc3c2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-1.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-require-effective-target persistent } */
+/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
+/* { dg-options "-save-temps" } */
+/* { dg-final { scan-assembler ".section\t.persistent,\"aw\"\n" } } */
+
+/* Test the "persistent" attribute. */
+#include "attr-persistent-main.inc"
diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-2.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-2.c
new file mode 100644
index 0000000..a7de0d5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-2.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target persistent } */
+/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
+/* { dg-options "-fdata-sections -save-temps" } */
+/* { dg-final { scan-assembler ".section\t.persistent.var_persistent,\"aw\"\n" } } */
+
+/* Test the "persistent" attribute with -fdata-sections. */
+#include "attr-persistent-main.inc"
diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-3.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-3.c
new file mode 100644
index 0000000..3e4fd28
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-3.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target persistent } */
+/* { dg-options "-flto -save-temps" } */
+/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
+/* { dg-final { scan-file attr-persistent-3.ltrans0.ltrans.s ".section\t\.persistent,\"aw\"\n" } } */
+
+/* Test the "persistent" attribute with -flto. Specifically examine the
+ final LTO assembly file, to ensure the "persistent" setting on the variable
+ hasn't been lost. */
+#include "attr-persistent-main.inc"
diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c
new file mode 100644
index 0000000..06d9f35
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target persistent } */
+/* { dg-options "-Wattributes" } */
+
+/* Check warning/error messages for "persistent" attribute misuse. */
+int __attribute__((persistent)) persistent_fn (void); /* { dg-warning "ignoring 'persistent' attribute not set on a variable" } */
+int __attribute__((section ("mysection"), persistent)) persistent_section1 = 1; /* { dg-warning "because it conflicts with attribute" } */
+int __attribute__((persistent, section ("mysection"))) persistent_section2 = 2; /* { dg-warning "because it conflicts with attribute" } */
+const int __attribute__((persistent)) persistent_const = 3; /* { dg-warning "ignoring 'persistent' attribute set on const variable" } */
+int __attribute__((persistent)) persistent_init; /* { dg-warning "ignoring 'persistent' attribute set on uninitialized variable" } */
+void foo (void) { int __attribute__((persistent)) local_persistent = 4; } /* { dg-error "'persistent' attribute cannot be specified for local variables" } */
diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc b/gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc
new file mode 100644
index 0000000..a442141
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc
@@ -0,0 +1,58 @@
+/* This test checks that data marked with the "persistent" attribute is handled
+ correctly.
+ If data LMA != VMA (e.g. for simulating the copy of data from ROM to RAM),
+ then var_init will always be re-initialized to 2 and this test will loop
+ forever, so it must be skipped for those targets. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void _start (void) __attribute__ ((noreturn));
+#ifdef __cplusplus
+}
+#endif
+
+int var_common;
+int var_zero = 0;
+int var_one = 1;
+int __attribute__((persistent)) var_persistent = 2;
+int var_init = 2;
+
+int
+main (void)
+{
+ /* Make sure that the C startup code has correctly initialized the ordinary variables. */
+ if (var_common != 0)
+ __builtin_abort ();
+
+ /* Initialized variables are not re-initialized during startup, so
+ check their original values only during the first run of this
+ test. */
+ if (var_init == 2)
+ if (var_zero != 0 || var_one != 1 || var_persistent != 2)
+ __builtin_abort ();
+
+ switch (var_init)
+ {
+ case 2:
+ /* First time through - change all the values. */
+ var_common = var_zero = var_one = var_persistent = var_init = 3;
+ break;
+
+ case 3:
+ /* Second time through - make sure that var_persistent has not been reset. */
+ if (var_persistent != 3)
+ __builtin_abort ();
+ __builtin_exit (0);
+
+ default:
+ /* Any other value for var_init is an error. */
+ __builtin_abort ();
+ }
+
+ /* Simulate a processor reset by calling the C startup code. */
+ _start ();
+
+ /* Should never reach here. */
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-1.c b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-1.c
new file mode 100644
index 0000000..6b01a56
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-1.c
@@ -0,0 +1,47 @@
+/* PR libstdc++/88101 */
+
+int i1, i2;
+long double l1, l2;
+struct S { char a; short b; char c; int d; char e; long long f; char g; long double h; } s1, s2;
+struct T { int a; struct S b[3]; int c; } t1, t2;
+struct U { int a : 3; int : 2; int b : 15; int : 14; int c : 1; int : 0; int : 3; int d : 2; int : 3; int e : 13; int : 3; signed char f; } u1, u2;
+
+__attribute__((noipa)) void
+foo (int *i, long double *l, struct S *s, struct T *t, struct U *u)
+{
+ *i = 123;
+ *l = -123.456L;
+ s->a = 1; s->b = 2; s->c = 3; s->d = 4; s->e = 5; s->f = 6; s->g = 7; s->h = 18.52L;
+ t->a = 8; t->c = 9;
+ t->b[0].a = 11; t->b[0].b = 12; t->b[0].c = 13; t->b[0].d = 14;
+ t->b[0].e = 15; t->b[0].f = 16; t->b[0].g = 17; t->b[0].h = 18.26L;
+ t->b[1].a = 21; t->b[1].b = 22; t->b[1].c = 23; t->b[1].d = 24;
+ t->b[1].e = 25; t->b[1].f = 26; t->b[1].g = 27; t->b[1].h = 28.26L;
+ t->b[2].a = 31; t->b[2].b = 32; t->b[2].c = 33; t->b[2].d = 34;
+ t->b[2].e = 35; t->b[2].f = 36; t->b[2].g = 37; t->b[2].h = 38.26L;
+ u->a = -1; u->b = -1; u->c = -1; u->d = -1; u->e = -1; u->f = -1;
+}
+
+int
+main ()
+{
+ __builtin_memset (&i2, -1, sizeof (i2));
+ __builtin_memset (&l2, -1, sizeof (i2));
+ __builtin_memset (&s2, -1, sizeof (s2));
+ __builtin_memset (&t2, -1, sizeof (t2));
+ __builtin_memset (&u2, -1, sizeof (u2));
+ foo (&i1, &l1, &s1, &t1, &u1);
+ foo (&i2, &l2, &s2, &t2, &u2);
+ __builtin_clear_padding (&i2);
+ __builtin_clear_padding (&l2);
+ __builtin_clear_padding (&s2);
+ __builtin_clear_padding (&t2);
+ __builtin_clear_padding (&u2);
+ if (__builtin_memcmp (&i1, &i2, sizeof (i1))
+ || __builtin_memcmp (&l1, &l2, sizeof (l1))
+ || __builtin_memcmp (&s1, &s2, sizeof (s1))
+ || __builtin_memcmp (&t1, &t2, sizeof (t1))
+ || __builtin_memcmp (&u1, &u2, sizeof (u1)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-2.c b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-2.c
new file mode 100644
index 0000000..1188bc0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-2.c
@@ -0,0 +1,24 @@
+/* PR libstdc++/88101 */
+
+typedef int T __attribute__((aligned (16384)));
+struct S { char a; short b; long double c; T d; T e; long long f; };
+
+__attribute__((noipa)) void
+foo (struct S *s)
+{
+ s->a = -1; s->b = -1; s->c = -18.52L; s->d = -1; s->e = -1; s->f = -1;
+}
+
+int
+main ()
+{
+ struct S s1, s2;
+ __builtin_memset (&s1, 0, sizeof (s1));
+ __builtin_memset (&s2, -1, sizeof (s2));
+ foo (&s1);
+ foo (&s2);
+ __builtin_clear_padding (&s2);
+ if (__builtin_memcmp (&s1, &s2, sizeof (s1)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-3.c b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-3.c
new file mode 100644
index 0000000..edb7c8e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-3.c
@@ -0,0 +1,65 @@
+/* PR libstdc++/88101 */
+
+union V { char a; signed char b; unsigned char c; };
+struct T { char a; int b; union V c; };
+union U { int a; long double b; struct T c; };
+struct S { char a; union U b; long long c; char d; } s1, s2;
+
+__attribute__((noipa)) void
+foo (struct S *s, int x)
+{
+ s->a = -1; s->c = -1; s->d = -1;
+ switch (x)
+ {
+ case 0:
+ s->b.a = -1;
+ break;
+ case 1:
+ s->b.b = -12345.25L;
+ break;
+ case 2:
+ s->b.c.a = -1;
+ s->b.c.b = -1;
+ s->b.c.c.b = -1;
+ break;
+ }
+}
+
+int
+main ()
+{
+ __builtin_memset (&s1, 0, sizeof (s1));
+ __builtin_memset (&s2, -1, sizeof (s2));
+ foo (&s1, 0);
+ foo (&s2, 0);
+ __builtin_clear_padding (&s2);
+ if (s2.b.a != (char) -1)
+ __builtin_abort ();
+ __builtin_clear_padding (&s2.b.a);
+ __builtin_memset (&s2.b.a + 1, 0, sizeof (union U) - sizeof (s2.b.a));
+ if (__builtin_memcmp (&s1, &s2, sizeof (s1)))
+ __builtin_abort ();
+ __builtin_memset (&s1, 0, sizeof (s1));
+ __builtin_memset (&s2, -1, sizeof (s2));
+ foo (&s1, 1);
+ foo (&s2, 1);
+ __builtin_clear_padding (&s2);
+ if (s2.b.b != -12345.25L)
+ __builtin_abort ();
+ __builtin_clear_padding (&s2.b.b);
+ __builtin_memset (&s2.b.b + 1, 0, sizeof (union U) - sizeof (s2.b.b));
+ if (__builtin_memcmp (&s1, &s2, sizeof (s1)))
+ __builtin_abort ();
+ __builtin_memset (&s1, 0, sizeof (s1));
+ __builtin_memset (&s2, -1, sizeof (s2));
+ foo (&s1, 2);
+ foo (&s2, 2);
+ __builtin_clear_padding (&s2);
+ if (s2.b.c.a != (char) -1 || s2.b.c.b != -1 || s2.b.c.c.b != -1)
+ __builtin_abort ();
+ __builtin_clear_padding (&s2.b.c);
+ __builtin_memset (&s2.b.c + 1, 0, sizeof (union U) - sizeof (s2.b.c));
+ if (__builtin_memcmp (&s1, &s2, sizeof (s1)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-4.c b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-4.c
new file mode 100644
index 0000000..d24f3b5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-4.c
@@ -0,0 +1,59 @@
+/* PR libstdc++/88101 */
+
+struct S { char a; short b; char c; };
+
+__attribute__((noipa)) void
+foo (int m, int n, int o)
+{
+ long double a1[m];
+ long double a2[m];
+ struct S b1[m][n];
+ struct S b2[m][n];
+ struct S c1[m][n][o];
+ struct S c2[m][n][o];
+ int i, j, k;
+ __builtin_memset (&a1, 0, sizeof (a1));
+ __builtin_memset (&a2, ~0, sizeof (a2));
+ __builtin_memset (&b1, 0, sizeof (b1));
+ __builtin_memset (&b2, ~0, sizeof (b2));
+ __builtin_memset (&c1, 0, sizeof (c1));
+ __builtin_memset (&c2, ~0, sizeof (c2));
+ for (i = 0; i < m; i++)
+ {
+ a1[i] = 13.132L;
+ a2[i] = 13.132L;
+ for (j = 0; j < n; j++)
+ {
+ b1[i][j].a = -1;
+ b1[i][j].b = -1;
+ b1[i][j].c = -1;
+ b2[i][j].a = -1;
+ b2[i][j].b = -1;
+ b2[i][j].c = -1;
+ for (k = 0; k < o; k++)
+ {
+ c1[i][j][k].a = -1;
+ c1[i][j][k].b = -1;
+ c1[i][j][k].c = -1;
+ c2[i][j][k].a = -1;
+ c2[i][j][k].b = -1;
+ c2[i][j][k].c = -1;
+ }
+ }
+ }
+ __builtin_clear_padding (&a2);
+ __builtin_clear_padding (&b2);
+ __builtin_clear_padding (&c2);
+ if (__builtin_memcmp (&a1, &a2, sizeof (a1))
+ || __builtin_memcmp (&b1, &b2, sizeof (b1))
+ || __builtin_memcmp (&c1, &c2, sizeof (c1)))
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ foo (5, 3, 4);
+ foo (17, 2, 1);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-5.c b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-5.c
new file mode 100644
index 0000000..d5dbafe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/builtin-clear-padding-5.c
@@ -0,0 +1,49 @@
+/* PR libstdc++/88101 */
+
+struct S { char a; short b; char c; } s1[24], s2[24];
+struct T { char a; long long b; char c; struct S d[3]; long long e; char f; } t1, t2;
+struct U { char a; long long b; char c; struct S d[25]; long long e; char f; } u1, u2;
+
+__attribute__((noipa)) void
+foo (struct S *s, struct T *t, struct U *u)
+{
+ int i;
+ t->a = -1; t->b = -1; t->c = -1; t->e = -1; t->f = -1;
+ u->a = -1; u->b = -1; u->c = -1; u->e = -1; u->f = -1;
+ for (i = 0; i < 24; i++)
+ {
+ s[i].a = -1;
+ s[i].b = -1;
+ s[i].c = -1;
+ }
+ for (i = 0; i < 3; i++)
+ {
+ t->d[i].a = -1;
+ t->d[i].b = -1;
+ t->d[i].c = -1;
+ }
+ for (i = 0; i < 25; i++)
+ {
+ u->d[i].a = -1;
+ u->d[i].b = -1;
+ u->d[i].c = -1;
+ }
+}
+
+int
+main ()
+{
+ __builtin_memset (&s2, -1, sizeof (s2));
+ __builtin_memset (&t2, -1, sizeof (t2));
+ __builtin_memset (&u2, -1, sizeof (u2));
+ foo (&s1[0], &t1, &u1);
+ foo (&s2[0], &t2, &u2);
+ __builtin_clear_padding (&s2);
+ __builtin_clear_padding (&t2);
+ __builtin_clear_padding (&u2);
+ if (__builtin_memcmp (&s1, &s2, sizeof (s1))
+ || __builtin_memcmp (&t1, &t2, sizeof (t1))
+ || __builtin_memcmp (&u1, &u2, sizeof (u1)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
index a571f2b..55db0c0 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
@@ -3,4 +3,4 @@
int i;
-/* { dg-error ".-fsanitize=address. and .-fsanitize=kernel-address. are incompatible with .-fsanitize=thread." "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize=thread. is incompatible with .-fsanitize=address." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-1.c
new file mode 100644
index 0000000..2463353
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+volatile int result = 0;
+int
+__attribute__((noipa))
+foo (int x)
+{
+ return x;
+}
+int main()
+{
+ result = foo (2);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c
new file mode 100644
index 0000000..193db8c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c
@@ -0,0 +1,93 @@
+/* { dg-do run } */
+/* { dg-skip-if "not implemented" { powerpc*-*-* } } */
+/* { dg-options "-O2" } */
+
+#include <assert.h>
+int result = 0;
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("skip")))
+foo1 (int x)
+{
+ return (x + 1);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("used-gpr-arg")))
+foo2 (int x)
+{
+ return (x + 2);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("used-gpr")))
+foo3 (int x)
+{
+ return (x + 3);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("used-arg")))
+foo4 (int x)
+{
+ return (x + 4);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("used")))
+foo5 (int x)
+{
+ return (x + 5);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("all-gpr-arg")))
+foo6 (int x)
+{
+ return (x + 6);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("all-gpr")))
+foo7 (int x)
+{
+ return (x + 7);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("all-arg")))
+foo8 (int x)
+{
+ return (x + 8);
+}
+
+int
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("all")))
+foo9 (int x)
+{
+ return (x + 9);
+}
+
+int main()
+{
+ result = foo1 (1);
+ result += foo2 (1);
+ result += foo3 (1);
+ result += foo4 (1);
+ result += foo5 (1);
+ result += foo6 (1);
+ result += foo7 (1);
+ result += foo8 (1);
+ result += foo9 (1);
+ assert (result == 54);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c
new file mode 100644
index 0000000..b04b6a2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-skip-if "not implemented" { powerpc*-*-* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all" } */
+
+#include "zero-scratch-regs-10.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-2.c
new file mode 100644
index 0000000..25891ac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-2.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-gpr-arg" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-3.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-3.c
new file mode 100644
index 0000000..7c3d286
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-3.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-gpr" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-4.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-4.c
new file mode 100644
index 0000000..ba28c06
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-4.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-arg" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-5.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-5.c
new file mode 100644
index 0000000..fde74d8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-5.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-skip-if "not implemented" { powerpc*-*-aix* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-6.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-6.c
new file mode 100644
index 0000000..80f5bbb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-6.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr-arg" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-7.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-7.c
new file mode 100644
index 0000000..159f35c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-7.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c
new file mode 100644
index 0000000..f612a04
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-skip-if "not implemented" { powerpc*-*-* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-arg" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c
new file mode 100644
index 0000000..2c63a69
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-skip-if "not implemented" { powerpc*-*-* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all" } */
+
+#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-attr-usages.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-attr-usages.c
new file mode 100644
index 0000000..1e75795
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-attr-usages.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int result __attribute__ ((zero_call_used_regs("all"))); /* { dg-error "attribute applies only to functions" } */
+int
+__attribute__ ((zero_call_used_regs("gpr-arg-all")))
+foo1 (int x) /* { dg-error "unrecognized 'zero_call_used_regs' attribute argument" } */
+{
+ return (x + 1);
+}
+int
+__attribute__ ((zero_call_used_regs(1)))
+foo2 (int x) /* { dg-error "argument not a string" } */
+{
+ return (x + 2);
+}
diff --git a/gcc/testsuite/g++.dg/DRs/dr2303.C b/gcc/testsuite/g++.dg/DRs/dr2303.C
new file mode 100644
index 0000000..b6acb6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2303.C
@@ -0,0 +1,37 @@
+// DR 2303
+// PR c++/97453
+// { dg-do compile { target c++11 } }
+
+template <typename... T> struct A;
+template <> struct A<>
+{
+};
+template <typename T, typename... Ts> struct A<T, Ts...> : A<Ts...>
+{
+};
+struct B : A<int, int>
+{
+};
+
+struct C : A<int, int>, A<int> // { dg-warning "direct base .A<int>. inaccessible in .C. due to ambiguity" }
+{
+};
+
+struct D : A<int>, A<int, int> // { dg-warning "direct base .A<int>. inaccessible in .D. due to ambiguity" }
+{
+};
+template <typename... T>
+void
+f (const A<T...> &)
+{
+ static_assert (sizeof...(T) == 2, "it should duduce to A<int,int>");
+}
+
+
+void
+g ()
+{
+ f (B{});
+ f (C{});
+ f (D{});
+}
diff --git a/gcc/testsuite/g++.dg/DRs/dr625.C b/gcc/testsuite/g++.dg/DRs/dr625.C
new file mode 100644
index 0000000..ce30a92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr625.C
@@ -0,0 +1,15 @@
+// DR 625 - Use of auto as a template-argument
+// PR c++/97479
+// { dg-do compile { target c++14 } }
+
+template<typename>
+struct A { };
+
+void f(int);
+
+int main()
+{
+ A<decltype(auto)> x = A<void>(); // { dg-error "not permitted|invalid|cannot convert" }
+ A<auto> a = A<void>(); // { dg-error "not permitted|invalid|cannot convert" }
+ void (*p)(auto); // { dg-error "parameter" }
+}
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess.C b/gcc/testsuite/g++.dg/Wclass-memaccess.C
index 57573b3..1dc23df 100644
--- a/gcc/testsuite/g++.dg/Wclass-memaccess.C
+++ b/gcc/testsuite/g++.dg/Wclass-memaccess.C
@@ -23,6 +23,10 @@ typedef unsigned char byte;
#endif
}
+#if __cplusplus < 201103L
+typedef unsigned short char16_t;
+#endif
+
/* Ordinary bzcopy and bzero aren't recognized as special. */
#define bcopy __builtin_bcopy
#define bzero __builtin_bzero
@@ -190,6 +194,7 @@ struct HasDefault { char a[4]; HasDefault (); };
void test (HasDefault *p, const HasDefault &x,
void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -247,6 +252,8 @@ void test (HasDefault *p, const HasDefault &x,
T (memcpy, (p, ia, sizeof *p)); // { dg-warning ".void\\* memcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const int." }
extern long *ip;
T (memcpy, (p, ip, sizeof *p)); // { dg-warning ".void\\* memcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .long." }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning ".void\\* memcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const signed char." }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning ".void\\* memcpy(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const \(char16_t\|unsigned short\)." }
T (memmove, (p, ia, sizeof *p)); // { dg-warning ".void\\* memmove(\[^\n\r\]*). copying an object of non-trivial type .struct HasDefault. from an array of .const int." }
@@ -274,6 +281,7 @@ struct HasTemplateDefault
void test (HasTemplateDefault *p, const HasTemplateDefault &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -291,24 +299,32 @@ void test (HasTemplateDefault *p, const HasTemplateDefault &x,
T (bcopy, (q, p, sizeof *p));
T (bcopy, (s, p, sizeof *p));
T (bcopy, (b, p, sizeof *p));
+ T (bcopy, (ss, p, sizeof *p)); // { dg-warning "bcopy" }
+ T (bcopy, (ws, p, sizeof *p)); // { dg-warning "bcopy" }
T (bcopy, (ia, p, sizeof *p)); // { dg-warning "bcopy" }
T (memcpy, (p, &x, sizeof *p));
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p));
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p));
T (mempcpy, (p, q, sizeof *p));
T (mempcpy, (p, s, sizeof *p));
T (mempcpy, (p, b, sizeof *p));
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -329,6 +345,7 @@ struct HasCopy { int i; HasCopy (const HasCopy&); };
void test (HasCopy *p, const HasCopy &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -348,24 +365,32 @@ void test (HasCopy *p, const HasCopy &x,
T (bcopy, (q, p, sizeof *p)); // { dg-warning "bcopy" }
T (bcopy, (s, p, sizeof *p)); // { dg-warning "bcopy" }
T (bcopy, (b, p, sizeof *p)); // { dg-warning "bcopy" }
+ T (bcopy, (ss, p, sizeof *p)); // { dg-warning "bcopy" }
+ T (bcopy, (ws, p, sizeof *p)); // { dg-warning "bcopy" }
T (bcopy, (ia, p, sizeof *p)); // { dg-warning "bcopy" }
T (memcpy, (p, &x, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -410,6 +435,7 @@ private:
void test (HasPrivateCopy *p, const HasPrivateCopy &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -429,18 +455,24 @@ void test (HasPrivateCopy *p, const HasPrivateCopy &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -459,6 +491,7 @@ struct HasDtor { int i; ~HasDtor (); };
void test (HasDtor *p, const HasDtor &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -479,18 +512,24 @@ void test (HasDtor *p, const HasDtor &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -503,7 +542,7 @@ void test (HasDtor *p, const HasDtor &x,
#if !defined TEST || TEST == TEST_HAS_DELETED_DTOR
-// HasDeletedDtor is trivial so clearing and cpying it is okay.
+// HasDeletedDtor is trivial so clearing and copying it is okay.
// Relocation would bypass the deleted dtor and so it's diagnosed.
struct HasDeletedDtor
@@ -514,6 +553,7 @@ struct HasDeletedDtor
void test (HasDeletedDtor *p, const HasDeletedDtor &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -528,18 +568,24 @@ void test (HasDeletedDtor *p, const HasDeletedDtor &x,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p));
+ T (memcpy, (p, ws, sizeof *p));
T (memcpy, (p, ia, sizeof *p));
T (memmove, (p, &x, sizeof *p));
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p));
+ T (memmove, (p, ws, sizeof *p));
T (memmove, (p, ia, sizeof *p));
T (mempcpy, (p, &x, sizeof *p));
T (mempcpy, (p, q, sizeof *p));
T (mempcpy, (p, s, sizeof *p));
T (mempcpy, (p, b, sizeof *p));
+ T (mempcpy, (p, ss, sizeof *p));
+ T (mempcpy, (p, ws, sizeof *p));
T (mempcpy, (p, ia, sizeof *p));
// Reallocating is diagnosed.
@@ -564,6 +610,7 @@ private:
void test (HasPrivateDtor *p, const HasPrivateDtor &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -578,18 +625,24 @@ void test (HasPrivateDtor *p, const HasPrivateDtor &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is diagnosed.
@@ -608,6 +661,7 @@ struct HasCopyAssign { void operator= (HasCopyAssign&); };
void test (HasCopyAssign *p, const HasCopyAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -626,18 +680,24 @@ void test (HasCopyAssign *p, const HasCopyAssign &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -665,6 +725,7 @@ struct HasMoveAssign
void test (HasMoveAssign *p, const HasMoveAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -683,18 +744,24 @@ void test (HasMoveAssign *p, const HasMoveAssign &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -727,6 +794,7 @@ struct TrivialCopyHasMoveAssign
void test (TrivialCopyHasMoveAssign *p, const TrivialCopyHasMoveAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -745,18 +813,24 @@ void test (TrivialCopyHasMoveAssign *p, const TrivialCopyHasMoveAssign &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -786,6 +860,7 @@ struct TrivialMoveNontrivialCopyAssign
void test (TrivialMoveNontrivialCopyAssign *p,
const TrivialMoveNontrivialCopyAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -804,18 +879,24 @@ void test (TrivialMoveNontrivialCopyAssign *p,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -841,6 +922,7 @@ struct TrivialAssignRefOverload {
void test (TrivialAssignRefOverload *p, const TrivialAssignRefOverload &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -855,18 +937,24 @@ void test (TrivialAssignRefOverload *p, const TrivialAssignRefOverload &x,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p));
+ T (memcpy, (p, ws, sizeof *p));
T (memcpy, (p, ia, sizeof *p));
T (memmove, (p, &x, sizeof *p));
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p));
+ T (memmove, (p, ws, sizeof *p));
T (memmove, (p, ia, sizeof *p));
T (mempcpy, (p, &x, sizeof *p));
T (mempcpy, (p, q, sizeof *p));
T (mempcpy, (p, s, sizeof *p));
T (mempcpy, (p, b, sizeof *p));
+ T (mempcpy, (p, ss, sizeof *p));
+ T (mempcpy, (p, ws, sizeof *p));
T (mempcpy, (p, ia, sizeof *p));
T (q = realloc, (p, 1));
@@ -892,6 +980,7 @@ struct TrivialAssignCstRefOverload {
void test (TrivialAssignCstRefOverload *p,
const TrivialAssignCstRefOverload &x,
const void *q, const unsigned char *s, std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -906,18 +995,24 @@ void test (TrivialAssignCstRefOverload *p,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p));
+ T (memcpy, (p, ws, sizeof *p));
T (memcpy, (p, ia, sizeof *p));
T (memmove, (p, &x, sizeof *p));
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p));
+ T (memmove, (p, ws, sizeof *p));
T (memmove, (p, ia, sizeof *p));
T (mempcpy, (p, &x, sizeof *p));
T (mempcpy, (p, q, sizeof *p));
T (mempcpy, (p, s, sizeof *p));
T (mempcpy, (p, b, sizeof *p));
+ T (mempcpy, (p, ss, sizeof *p));
+ T (mempcpy, (p, ws, sizeof *p));
T (mempcpy, (p, ia, sizeof *p));
T (q = realloc, (p, 1));
@@ -940,6 +1035,7 @@ struct TrivialRefHasVolRefAssign
void test (TrivialRefHasVolRefAssign *p,
const TrivialRefHasVolRefAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -958,18 +1054,24 @@ void test (TrivialRefHasVolRefAssign *p,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -991,6 +1093,7 @@ struct HasVolRefAssign {
void test (HasVolRefAssign *p, const HasVolRefAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1009,18 +1112,24 @@ void test (HasVolRefAssign *p, const HasVolRefAssign &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -1040,6 +1149,7 @@ struct HasVirtuals { int i; virtual void foo (); };
void test (HasVirtuals *p, const HasVirtuals &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1057,18 +1167,24 @@ void test (HasVirtuals *p, const HasVirtuals &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -1089,6 +1205,7 @@ struct HasConstData { const char a[4]; };
void test (HasConstData *p, const HasConstData &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1115,18 +1232,24 @@ void test (HasConstData *p, const HasConstData &x,
T (memcpy, (p, q, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, s, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memmove, (p, &x, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is not diagnosed except in C++ 98 due to a bug.
@@ -1147,6 +1270,7 @@ struct HasReference { int &ci; };
void test (HasReference *p, const HasReference &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1181,6 +1305,10 @@ void test (HasReference *p, const HasReference &x,
T (memcpy, (p, s, n)); // { dg-warning "memcpy" }
T (memcpy, (p, b, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, b, n)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, n)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, n)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, n)); // { dg-warning "memcpy" }
@@ -1188,12 +1316,16 @@ void test (HasReference *p, const HasReference &x,
T (memmove, (p, q, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, s, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, b, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (mempcpy, (p, &x, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, q, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, s, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, b, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is not diagnosed because a type with a reference
@@ -1218,6 +1350,7 @@ struct HasMemDataPtr { int HasMemDataPtr::*p; };
void test (HasMemDataPtr *p, const HasMemDataPtr &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1243,6 +1376,10 @@ void test (HasMemDataPtr *p, const HasMemDataPtr &x,
T (memcpy, (p, s, n));
T (memcpy, (p, b, sizeof *p));
T (memcpy, (p, b, n));
+ T (memcpy, (p, ss, sizeof *p));
+ T (memcpy, (p, ss, n));
+ T (memcpy, (p, ws, sizeof *p));
+ T (memcpy, (p, ws, n));
T (memcpy, (p, ia, sizeof *p));
T (memcpy, (p, ia, n));
@@ -1250,12 +1387,16 @@ void test (HasMemDataPtr *p, const HasMemDataPtr &x,
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p));
+ T (memmove, (p, ws, sizeof *p));
T (memmove, (p, ia, sizeof *p));
T (mempcpy, (p, &x, sizeof *p));
T (mempcpy, (p, q, sizeof *p));
T (mempcpy, (p, s, sizeof *p));
T (mempcpy, (p, b, sizeof *p));
+ T (mempcpy, (p, ss, sizeof *p));
+ T (mempcpy, (p, ws, sizeof *p));
T (mempcpy, (p, ia, sizeof *p));
// Reallocating is the same as calling memcpy.
@@ -1276,6 +1417,7 @@ struct HasSomePrivateData { char a[2]; private: char b[2]; };
void test (HasSomePrivateData *p, const HasSomePrivateData &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1298,6 +1440,10 @@ void test (HasSomePrivateData *p, const HasSomePrivateData &x,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, n)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, n)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, n)); // { dg-warning "memcpy" }
@@ -1307,6 +1453,10 @@ void test (HasSomePrivateData *p, const HasSomePrivateData &x,
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, n)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, n)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, n)); // { dg-warning "memmove" }
@@ -1319,6 +1469,10 @@ void test (HasSomePrivateData *p, const HasSomePrivateData &x,
T (mempcpy, (p, s, n));
T (mempcpy, (p, b, sizeof *p));
T (mempcpy, (p, b, n));
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, n)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, n)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, n)); // { dg-warning "mempcpy" }
@@ -1342,6 +1496,7 @@ struct HasSomeProtectedData { char a[2]; protected: char b[2]; };
void test (HasSomeProtectedData *p, const HasSomeProtectedData &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1364,6 +1519,10 @@ void test (HasSomeProtectedData *p, const HasSomeProtectedData &x,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, n)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, n)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, n)); // { dg-warning "memcpy" }
@@ -1373,6 +1532,10 @@ void test (HasSomeProtectedData *p, const HasSomeProtectedData &x,
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, n)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, n)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, n)); // { dg-warning "memmove" }
@@ -1385,6 +1548,10 @@ void test (HasSomeProtectedData *p, const HasSomeProtectedData &x,
T (mempcpy, (p, s, n));
T (mempcpy, (p, b, sizeof *p));
T (mempcpy, (p, b, n));
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, n)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, n)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, n)); // { dg-warning "mempcpy" }
@@ -1408,6 +1575,7 @@ struct HasAllPrivateData { private: char a[4]; };
void test (HasAllPrivateData *p, const HasAllPrivateData &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1430,6 +1598,10 @@ void test (HasAllPrivateData *p, const HasAllPrivateData &x,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, n)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, n)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, n)); // { dg-warning "memcpy" }
@@ -1439,6 +1611,10 @@ void test (HasAllPrivateData *p, const HasAllPrivateData &x,
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, n)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, n)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, n)); // { dg-warning "memmove" }
@@ -1451,6 +1627,10 @@ void test (HasAllPrivateData *p, const HasAllPrivateData &x,
T (mempcpy, (p, s, n));
T (mempcpy, (p, b, sizeof *p));
T (mempcpy, (p, b, n));
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, n)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, n)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, n)); // { dg-warning "mempcpy" }
@@ -1474,6 +1654,7 @@ struct HasAllProtectedData { protected: char a[4]; };
void test (HasAllProtectedData *p, const HasAllProtectedData &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1496,6 +1677,10 @@ void test (HasAllProtectedData *p, const HasAllProtectedData &x,
T (memcpy, (p, q, sizeof *p));
T (memcpy, (p, s, sizeof *p));
T (memcpy, (p, b, sizeof *p));
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ss, n)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "memcpy" }
+ T (memcpy, (p, ws, n)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "memcpy" }
T (memcpy, (p, ia, n)); // { dg-warning "memcpy" }
@@ -1505,6 +1690,10 @@ void test (HasAllProtectedData *p, const HasAllProtectedData &x,
T (memmove, (p, q, sizeof *p));
T (memmove, (p, s, sizeof *p));
T (memmove, (p, b, sizeof *p));
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ss, n)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, n)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, n)); // { dg-warning "memmove" }
@@ -1517,6 +1706,10 @@ void test (HasAllProtectedData *p, const HasAllProtectedData &x,
T (mempcpy, (p, s, n));
T (mempcpy, (p, b, sizeof *p));
T (mempcpy, (p, b, n));
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ss, n)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, n)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, n)); // { dg-warning "mempcpy" }
@@ -1543,6 +1736,7 @@ private:
void test (HasDefaultPrivateAssign *p, const HasDefaultPrivateAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1596,8 +1790,14 @@ void test (HasDefaultPrivateAssign *p, const HasDefaultPrivateAssign &x,
T (mempcpy, (p, q, 3)); // { dg-warning "mempcpy" } */
// Otherwise, copying from an object of an unrelated type is diagnosed.
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment." }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment." }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "writing to an object of type .struct HasDefaultPrivateAssign. with (deleted|no trivial) copy-assignment." }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
@@ -1621,6 +1821,7 @@ private:
void test (HasDefaultDeletedAssign *p, const HasDefaultDeletedAssign &x,
const void *q, const unsigned char *s, const std::byte *b,
+ const signed char *ss, const char16_t *ws,
const int ia[])
{
const int i = *ia;
@@ -1674,8 +1875,14 @@ void test (HasDefaultDeletedAssign *p, const HasDefaultDeletedAssign &x,
T (mempcpy, (p, q, 3)); // { dg-warning "mempcpy" } */
// Otherwise, copying from an object of an unrelated type is diagnosed.
+ T (memcpy, (p, ss, sizeof *p)); // { dg-warning "writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment." }
+ T (memcpy, (p, ws, sizeof *p)); // { dg-warning "writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment." }
T (memcpy, (p, ia, sizeof *p)); // { dg-warning "writing to an object of type .struct HasDefaultDeletedAssign. with (deleted|no trivial) copy-assignment." }
+ T (memmove, (p, ss, sizeof *p)); // { dg-warning "memmove" }
+ T (memmove, (p, ws, sizeof *p)); // { dg-warning "memmove" }
T (memmove, (p, ia, sizeof *p)); // { dg-warning "memmove" }
+ T (mempcpy, (p, ss, sizeof *p)); // { dg-warning "mempcpy" }
+ T (mempcpy, (p, ws, sizeof *p)); // { dg-warning "mempcpy" }
T (mempcpy, (p, ia, sizeof *p)); // { dg-warning "mempcpy" }
// Reallocating is the same as calling memcpy.
diff --git a/gcc/testsuite/g++.dg/abi/macro0.C b/gcc/testsuite/g++.dg/abi/macro0.C
index 0810600..7c3c170 100644
--- a/gcc/testsuite/g++.dg/abi/macro0.C
+++ b/gcc/testsuite/g++.dg/abi/macro0.C
@@ -1,6 +1,6 @@
// This testcase will need to be kept in sync with c_common_post_options.
// { dg-options "-fabi-version=0" }
-#if __GXX_ABI_VERSION != 1014
+#if __GXX_ABI_VERSION != 1015
#error "Incorrect value of __GXX_ABI_VERSION"
#endif
diff --git a/gcc/testsuite/g++.dg/asan/asan_test.cc b/gcc/testsuite/g++.dg/asan/asan_test.cc
index 5f2e2c2..dbf1a6a 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_test.cc
@@ -829,7 +829,7 @@ NOINLINE static int LargeFunction(bool do_bad_access) {
x[18]++;
x[19]++;
- delete x;
+ delete[] x;
return res;
}
diff --git a/gcc/testsuite/g++.dg/concepts/pack-1.C b/gcc/testsuite/g++.dg/concepts/pack-1.C
new file mode 100644
index 0000000..b4f2c36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pack-1.C
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+// distilled from <concepts>, via header units
+
+template<typename _ArgTypes>
+struct is_invocable;
+
+template<typename... _Args>
+concept invocable = is_invocable<_Args...>::value;
+
+template<typename _Is>
+requires invocable<_Is>
+class BUG;
+
+template<typename _Is>
+requires invocable<_Is>
+class BUG {}; // { dg-bogus "different constraints" }
+
+template<int> struct is_invocable_NT;
+
+template<int... Ints>
+concept invocable_NT = is_invocable_NT<Ints...>::value;
+
+template<int _Is>
+requires invocable_NT<_Is>
+class BUG_NT;
+
+template<int _Is>
+requires invocable_NT<_Is>
+class BUG_NT {};
diff --git a/gcc/testsuite/g++.dg/concepts/pr94252.C b/gcc/testsuite/g++.dg/concepts/pr94252.C
index 56ce5f8..b045703 100644
--- a/gcc/testsuite/g++.dg/concepts/pr94252.C
+++ b/gcc/testsuite/g++.dg/concepts/pr94252.C
@@ -16,6 +16,7 @@ static_assert(requires(S o, int i) {
template<typename T>
concept c = requires (T t) { requires (T)5; }; // { dg-error "has type .int." }
+// { dg-bogus "not satisfied" "" { target *-*-* } .-1 }
int
foo()
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof6.C b/gcc/testsuite/g++.dg/cpp0x/alignof6.C
new file mode 100644
index 0000000..b1a463d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof6.C
@@ -0,0 +1,19 @@
+// PR c++/88115
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-pedantic" }
+
+// Verify the non-standard extension alignof(expr) behaves like
+// alignof(type) to yield the ABI alignment of the type, and that
+// __alignof__(expr) behaves like __alignof__(type) to yield the
+// preferred alignment of the type.
+
+static_assert(alignof(double{}) == alignof(double), "");
+static_assert(__alignof__(double{}) == __alignof__(double), "");
+
+template <class T>
+void f() {
+ static_assert(alignof(T{}) == alignof(T), "");
+ static_assert(__alignof__(T{}) == __alignof__(T), "");
+}
+
+template void f<double>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof7.C b/gcc/testsuite/g++.dg/cpp0x/alignof7.C
new file mode 100644
index 0000000..a4d7f24
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof7.C
@@ -0,0 +1,22 @@
+// PR c++/88115
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-pedantic" }
+
+// Verify we mangle __alignof__ differently from alignof.
+
+#include <cstddef>
+
+template <class T> void f1(decltype(alignof(T))) { }
+template <class T> void f2(decltype(alignof(T{}))) { }
+template <class T> void f3(decltype(__alignof__(T))) { }
+template <class T> void f4(decltype(__alignof__(T{}))) { }
+
+template void f1<int>(std::size_t);
+template void f2<int>(std::size_t);
+template void f3<int>(std::size_t);
+template void f4<int>(std::size_t);
+
+// { dg-final { scan-assembler "_Z2f1IiEvDTatT_E" } }
+// { dg-final { scan-assembler "_Z2f2IiEvDTaztlT_EE" } }
+// { dg-final { scan-assembler "_Z2f3IiEvDTv111__alignof__T_E" } }
+// { dg-final { scan-assembler "_Z2f4IiEvDTv111__alignof__tlT_EE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof8.C b/gcc/testsuite/g++.dg/cpp0x/alignof8.C
new file mode 100644
index 0000000..a9368e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof8.C
@@ -0,0 +1,13 @@
+// PR c++/88115
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-pedantic -fabi-version=14 -Wabi" }
+
+#include "alignof7.C"
+
+// { dg-warning "changes between" "" { target *-*-* } 11 }
+// { dg-warning "changes between" "" { target *-*-* } 12 }
+
+// { dg-final { scan-assembler "_Z2f1IiEvDTatT_E" } }
+// { dg-final { scan-assembler "_Z2f2IiEvDTaztlT_EE" } }
+// { dg-final { scan-assembler "_Z2f3IiEvDTatT_E" } }
+// { dg-final { scan-assembler "_Z2f4IiEvDTaztlT_EE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto3.C b/gcc/testsuite/g++.dg/cpp0x/auto3.C
index 709898d..2cd0520 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto3.C
@@ -17,7 +17,7 @@ struct A { };
A<int> A1;
// CWG issue 625
-A<auto> A2 = A1; // { dg-error "" "" { target { ! concepts } } }
+A<auto> A2 = A1; // { dg-error "" }
auto foo() { } // { dg-error "auto" "" { target { ! c++14 } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto54.C b/gcc/testsuite/g++.dg/cpp0x/auto54.C
new file mode 100644
index 0000000..0c1815a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto54.C
@@ -0,0 +1,10 @@
+// PR c++/97895
+// { dg-do compile { target c++11 } }
+
+namespace std {
+ template<typename T> struct initializer_list {
+ const T *ptr;
+ decltype(sizeof 0) n;
+ };
+ auto a = {}; // { dg-error "unable to deduce" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C
index a3f9be5..0e80c30 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C
@@ -114,7 +114,7 @@ badthrow2 () throw (auto &) // { dg-error "invalid use of|expected" }
template <auto V = 4> struct G {}; // { dg-error "11:parameter" "" { target { ! c++17 } } }
template <typename T> struct H { H (); ~H (); };
-H<auto> h; // { dg-error "invalid|initializer" }
+H<auto> h; // { dg-error "invalid|initializer|not permitted in template argument" }
void qq (auto); // { dg-error "auto" "" { target { ! concepts } } }
void qr (auto*); // { dg-error "auto" "" { target { ! concepts } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
new file mode 100644
index 0000000..04f039f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C
@@ -0,0 +1,36 @@
+// PR c++/52830
+// { dg-do compile { target c++11 } }
+
+template<bool b> struct eif { typedef void type; };
+template<> struct eif<false> {};
+
+template<class A, class B> struct same
+{
+ static constexpr bool value = false;
+};
+template<class A>
+struct same<A, A>
+{
+ static constexpr bool value = true;
+};
+
+
+struct foo {
+ template<class T>
+ void func(T && a,
+ typename eif<same<decltype(a), int&&>::value>::type * = 0);
+};
+
+template<class T>
+void
+foo::
+func(T && a,
+ typename eif<same<decltype(a), int&&>::value>::type * )
+{
+}
+
+void do_stuff()
+{
+ foo f;
+ f.func(12);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow3.C
new file mode 100644
index 0000000..6176625
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow3.C
@@ -0,0 +1,7 @@
+// PR c++/98332
+// { dg-do compile { target c++11 } }
+
+#include <limits.h>
+
+struct S { int a = INT_MAX + 1; }; // { dg-warning "overflow" }
+struct { S b[2][1][1][1]; } c;
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype63.C b/gcc/testsuite/g++.dg/cpp0x/decltype63.C
index b588bc3..ab1a4111 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype63.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype63.C
@@ -4,5 +4,4 @@
template<typename T>
class C{
T t;
- decltype(t)::a:: // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+ decltype(t)::a:: // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum41.C b/gcc/testsuite/g++.dg/cpp0x/enum41.C
new file mode 100644
index 0000000..5f6ef13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum41.C
@@ -0,0 +1,32 @@
+// PR c++/98043
+// { dg-do compile { target c++11 } }
+
+enum class B { A };
+struct C { B c : 8; };
+
+bool
+foo (C x)
+{
+ switch (x.c)
+ {
+ case B::A:
+ return false;
+ default:
+ return true;
+ }
+}
+
+enum E { X };
+struct D { E c : 7; };
+
+bool
+bar (D x)
+{
+ switch (x.c)
+ {
+ case E::X:
+ return false;
+ default:
+ return true;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/fallthrough2.C b/gcc/testsuite/g++.dg/cpp0x/fallthrough2.C
index f2d0ce1..071c2cb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/fallthrough2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/fallthrough2.C
@@ -14,7 +14,7 @@ f (int i)
[[fallthrough]];
case 3:
bar (1);
- [[gnu::fallthrough, gnu::fallthrough]]; // { dg-warning ".fallthrough. attribute specified multiple times" }
+ [[gnu::fallthrough, gnu::fallthrough]]; // { dg-warning ".fallthrough. specified multiple times" }
case 2:
bar (2);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/friend6.C b/gcc/testsuite/g++.dg/cpp0x/friend6.C
new file mode 100644
index 0000000..fce7e55
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/friend6.C
@@ -0,0 +1,23 @@
+// PR c++/68451
+// { dg-do compile { target c++11 } }
+
+struct A {};
+
+struct B
+{
+ A a;
+ friend decltype(a);
+};
+
+template <typename T>
+struct C
+{
+ A a;
+ friend decltype(a);
+};
+
+int main()
+{
+ B b;
+ C<int> c;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
index cb0c31e..9203d1d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
@@ -1,4 +1,4 @@
// PR c++/60365
// { dg-do compile { target c++11 } }
-void func [[noreturn, noreturn]] (); // { dg-error "at most once" }
+void func [[noreturn, noreturn]] (); // { dg-warning "specified multiple times" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-64.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-64.C
index 822b64e..c82beb9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-64.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-64.C
@@ -2,4 +2,3 @@
// { dg-do compile { target c++11 } }
namespace alignas() N {} // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C
new file mode 100644
index 0000000..3c235b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C
@@ -0,0 +1,45 @@
+// DR 1914 - Duplicate standard attributes
+// { dg-do compile { target c++11 } }
+
+#define ATTR_NORETURN [[noreturn, noreturn]]
+
+[[noreturn, noreturn]] void fn0(); // { dg-warning "specified multiple times" }
+ATTR_NORETURN void fn0a();
+[[noreturn]] [[noreturn]] void fn1();
+[[deprecated, deprecated]] void fn2(); // { dg-warning "specified multiple times" }
+[[deprecated]] [[deprecated]] void fn3();
+[[maybe_unused]] [[maybe_unused]] int fn4();
+[[maybe_unused, maybe_unused]] int fn5(); // { dg-warning "specified multiple times" }
+[[nodiscard]] [[nodiscard]] int fn6();
+[[nodiscard, nodiscard]] int fn7(); // { dg-warning "specified multiple times" }
+
+struct E { };
+struct A {
+ [[no_unique_address]] [[no_unique_address]] E e;
+};
+struct B {
+ [[no_unique_address, no_unique_address]] E e; // { dg-warning "specified multiple times" }
+};
+
+int
+f (int n)
+{
+ switch (n)
+ {
+ case 1:
+ [[fallthrough, fallthrough]]; // { dg-warning "specified multiple times" }
+ case 2:
+ [[fallthrough]] [[fallthrough]]; // { dg-warning "specified multiple times" }
+ case 3:
+ return 15;
+ }
+
+ if (n == 10)
+ [[likely]] [[likely]] return 42; // { dg-warning "ignoring attribute" }
+ else if (n == 11)
+ [[unlikely]] [[unlikely]] return 10; // { dg-warning "ignoring attribute" }
+ else if (n == 12)
+ [[likely, likely]] return 42; // { dg-warning "specified multiple times" }
+ else
+ [[unlikely, unlikely]] return 0; // { dg-warning "specified multiple times" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
index 90a06c6..59801a1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
@@ -4,4 +4,4 @@
struct A {};
struct B : virtual A {};
struct C : virtual A {};
-struct D : B,C { using A::A; }; // { dg-error "indirect" }
+struct D : B,C { using A::A; }; // { dg-error "not a direct base" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C
index 95b7812..4e61290 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C
@@ -10,7 +10,7 @@ public:
class Y : public X { };
class Z : public Y {
- using X::X; // { dg-error "cannot inherit constructors from indirect base .X." }
+ using X::X; // { dg-error ".X. is not a direct base of .Z." }
};
int main()
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce3.C b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce3.C
new file mode 100644
index 0000000..b8417d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce3.C
@@ -0,0 +1,22 @@
+// PR c++/93107
+// { dg-do compile { target c++11 } }
+
+using size_t = decltype(sizeof 0);
+
+namespace std {
+ template<typename T> struct initializer_list {
+ const T *ptr;
+ size_t n;
+ initializer_list(const T*, size_t);
+ };
+}
+
+template<typename T>
+void Task() {}
+
+auto a = &Task<int>;
+auto b = { &Task<int> };
+auto e{ &Task<int> };
+auto f = { &Task<int>, &Task<int> };
+std::initializer_list<void(*)()> c = { &Task<int> };
+auto d = { static_cast<void(*)()>(&Task<int>) };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-template3.C b/gcc/testsuite/g++.dg/cpp0x/initlist-template3.C
new file mode 100644
index 0000000..b65a847
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-template3.C
@@ -0,0 +1,13 @@
+// PR c++/97899
+// { dg-do compile { target c++11 } }
+
+template <typename T = int>
+int fn()
+{
+ return 1;
+}
+
+template <typename T>
+void bar() {
+ const int i = int{fn()};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/linkage2.C b/gcc/testsuite/g++.dg/cpp0x/linkage2.C
index 5285868..549bd82 100644
--- a/gcc/testsuite/g++.dg/cpp0x/linkage2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/linkage2.C
@@ -29,5 +29,5 @@ void f() {
ba.g(a); // OK
ba.h(a); // error, B<T>::h never defined
i(ba, a); // OK
- e1+e2+e3;
+ e1+e2+e3; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/new4.C b/gcc/testsuite/g++.dg/cpp0x/new4.C
new file mode 100644
index 0000000..728ef4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/new4.C
@@ -0,0 +1,36 @@
+// PR c++/59238
+// { dg-do compile { target c++11 } }
+
+struct A { ~A () = delete; };
+A *pa{new A{}};
+A *pa2{new A[2]{}};
+
+class B { ~B () = default; };
+B *pb{new B{}};
+
+struct E {
+ ~E () = delete;
+private:
+ int x;
+};
+E *pe{new E{}};
+
+class C { ~C (); };
+C *pc{new C{}};
+
+class D { ~D () {} };
+D *pd{new D{}};
+
+struct F {
+ F () = default;
+ ~F () = delete;
+};
+F *pf{new F{}};
+
+struct G {
+ G () = default;
+ ~G () = delete;
+private:
+ int x;
+};
+G *pg{new G{}};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr68726.C b/gcc/testsuite/g++.dg/cpp0x/pr68726.C
index 636a20c..8edd439 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr68726.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr68726.C
@@ -5,4 +5,3 @@ template <typename> struct A {
template <typename... _Args>
using __has_construct typename __construct_helper<_Args...>::type; // { dg-error "expected" }
} struct : A<int> { // { dg-error "expected" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr78341.C b/gcc/testsuite/g++.dg/cpp0x/pr78341.C
index 8573f9f..0a69210 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr78341.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr78341.C
@@ -2,4 +2,3 @@
// { dg-do compile { target c++11 } }
alignas (alignas double // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/using-enum-1.C b/gcc/testsuite/g++.dg/cpp0x/using-enum-1.C
index 9904d59..bf251ba 100644
--- a/gcc/testsuite/g++.dg/cpp0x/using-enum-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/using-enum-1.C
@@ -1,6 +1,9 @@
// PR c++/60265
// { dg-do compile { target c++11 } }
+// [namespace.udecl]/7 shall not name a scoped enumerator.
+// (so unscoped enumerator is ok)
+
namespace A
{
enum E { V };
diff --git a/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C b/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C
index faa3817..8ea70d7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C
@@ -1,20 +1,23 @@
// PR c++/60265
// { dg-do compile { target c++11 } }
+// [namespace.udecl]/7 shall not name a scoped enumerator.
+// (this changes in C++2a)
+
namespace A
{
enum class E { V };
- using E::V; // { dg-error "name enumerator" }
+ using E::V; // { dg-error "enum" "" { target { ! c++2a } } }
}
void foo()
{
- using A::E::V; // { dg-error "name enumerator" }
+ using A::E::V; // { dg-error "enum" "" { target { ! c++2a } } }
}
-using A::E::V; // { dg-error "name enumerator" }
+using A::E::V; // { dg-error "enum" "" { target { ! c++2a } } }
enum class F { U };
-using F::U; // { dg-error "name enumerator" }
+using F::U; // { dg-error "enum" "" { target { ! c++2a } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C b/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C
index ecc4ddc..34f8bf4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C
@@ -1,15 +1,24 @@
// PR c++/89511
// { dg-do compile { target c++11 } }
+// [namespace.udecl] In a using-declaration used as a
+// member-declaration, the nested-name-specifier shall name a base
+// class of the class being defined
+// (this changes in C++2a)
+
void f ()
{
enum e { a };
- using e::a; // { dg-error "name enumerator" }
+ using e::a; // { dg-error "redeclaration" }
+ // { dg-error "enum" "" { target { ! c++2a } } .-1 }
}
+enum E { A };
+
struct S {
enum E { A };
- using E::A; // { dg-error "type .S. is not a base type for type .S." }
+ using E::A; // { dg-error "not a base" "" { target { ! c++2a } } }
+ // { dg-error "conflicts" "" { target c++2a } .-1 }
};
namespace N {
@@ -17,5 +26,5 @@ namespace N {
}
struct T {
- using N::E::B; // { dg-error "using-declaration for non-member at class scope" }
+ using N::E::B; // { dg-error "enum" "" { target { ! c++2a } } }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-88982.C b/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
new file mode 100644
index 0000000..cb9530d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-88982.C
@@ -0,0 +1,14 @@
+// PR c++/88982
+// { dg-do compile { target c++11 } }
+// { dg-ice "tsubst_pack_expansion" }
+
+template<typename...Ts> struct A {
+ template<template<typename, Ts = 0> class ...Cs, Cs<Ts> ...Vs> struct B {
+ B() {
+ }
+ };
+};
+
+template<typename, int> using Int = int;
+template<typename, short> using Char = char;
+A<int, short>::B<Int, Char> b;
diff --git a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
index 12c75c7..ac6c4ae 100644
--- a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
+++ b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
@@ -1,4 +1,4 @@
// PR c++/60365
// { dg-do compile { target c++14 } }
-void func [[deprecated, deprecated]] (); // { dg-error "at most once" }
+void func [[deprecated, deprecated]] (); // { dg-warning "specified multiple times" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-98122.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-98122.C
new file mode 100644
index 0000000..86b8aa9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-98122.C
@@ -0,0 +1,14 @@
+// PR c++/98122
+// { dg-do compile { target c++14 } }
+
+union U { int a; };
+
+constexpr bool
+foo ()
+{
+ U f { 42 };
+ constexpr auto m = &U::a;
+ return (f.*m) == 42;
+}
+
+static_assert (foo (), "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
new file mode 100644
index 0000000..a2d113c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C
@@ -0,0 +1,9 @@
+// PR c++/97846
+// { dg-do compile { target c++14 } }
+
+constexpr int
+f ()
+{
+x: // { dg-error "label definition is not a constant expression" }
+ return 42;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto1.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto1.C
new file mode 100644
index 0000000..13baf8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto1.C
@@ -0,0 +1,8 @@
+// PR c++/78209
+// { dg-do compile { target c++14 } }
+
+int main()
+{
+ int &&i = 0;
+ decltype(auto) j = i; // { dg-error "cannot bind rvalue reference" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr65202.C b/gcc/testsuite/g++.dg/cpp1y/pr65202.C
index a76f8da..1f7219b 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr65202.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr65202.C
@@ -24,5 +24,4 @@ int main()
{
foo<ns::bar> f;
adl::swap(f, f) // { dg-error "expected ';'" }
-}
-// { dg-error "-:expected '.'" "expected end of namespace" { target *-*-* } .+1 }
+} // { dg-error "2:expected" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr65340.C b/gcc/testsuite/g++.dg/cpp1y/pr65340.C
index d3e03f7..e0ce681 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr65340.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr65340.C
@@ -17,4 +17,4 @@ struct traverse {
}
auto &traverse = constant < functors :: traverse > ;
operator()()->decltype(traverse(0, 0))// { dg-error "no match" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "39:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68578.C b/gcc/testsuite/g++.dg/cpp1y/pr68578.C
index 9b38981..f4be9da 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr68578.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr68578.C
@@ -1,4 +1,4 @@
// { dg-do compile { target c++14 } }
template <typename> struct bar foo; template <> struct foo<>: // { dg-error "class template|redeclared" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "62:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction44.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction44.C
index 95caa99..419aaa2 100644
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction44.C
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction44.C
@@ -3,4 +3,3 @@
template <typename> struct A;
template <typename> struct B : A < B { , // { dg-error "" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction69.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction69.C
index 8291f4a..d336366 100644
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction69.C
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction69.C
@@ -6,7 +6,7 @@ namespace a {
template <typename...> using c = b;
}
template <typename... d> struct e : a::c<d...> { // { dg-error "incomplete" }
- using a::c<>::c; // { dg-prune-output "not a base" }
+ using a::c<>::c; // { dg-prune-output "not a direct base" }
};
template <template <typename> typename f> void g() { f(); }
void h() { g<e>(); }
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction75.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction75.C
new file mode 100644
index 0000000..52e6131
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction75.C
@@ -0,0 +1,15 @@
+// PR c++/97663
+
+template <class T> struct foo {};
+template <class T> struct bar {};
+template <class T> struct baz {};
+template <class T> struct qux {};
+template <class T> struct corge {};
+
+namespace N {
+ unsigned foo ();
+ signed bar ();
+ long baz ();
+ long long qux ();
+ short corge ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction76.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction76.C
new file mode 100644
index 0000000..23bb6e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction76.C
@@ -0,0 +1,25 @@
+// PR c++/90799
+// { dg-do compile { target c++17 } }
+// { dg-ice "unify" }
+
+template<class T>
+void foo() noexcept(T::value);
+
+struct S {
+ static constexpr const bool value = true;
+
+ template<class T>
+ void bar() noexcept(T::value);
+};
+
+template<class... Args, bool is_noexcept>
+constexpr bool is_noexcept_function(void(Args...) noexcept(is_noexcept)) noexcept {
+ return is_noexcept;
+}
+
+template<class... Args, bool is_noexcept>
+constexpr bool is_noexcept_member_function(void(S::*)(Args...) noexcept(is_noexcept)) noexcept {
+ return is_noexcept;
+}
+
+static_assert(is_noexcept_function(foo<S>));
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
new file mode 100644
index 0000000..d6c8bae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda26.C
@@ -0,0 +1,13 @@
+// PR c++/87765
+// { dg-do compile { target c++17 } }
+// { dg-ice "cxx_eval_constant_expression" }
+
+template <int N>
+using foo = int;
+
+struct A {
+ constexpr int bar() const { return 42; }
+};
+
+void baz(A a) {
+ [=](auto c) { return foo<a.bar()> { }; }; }
diff --git a/gcc/testsuite/g++.dg/cpp1z/fold12.C b/gcc/testsuite/g++.dg/cpp1z/fold12.C
new file mode 100644
index 0000000..90d74cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/fold12.C
@@ -0,0 +1,13 @@
+// PR c++/86773
+// { dg-do compile { target c++17 } }
+
+template <typename ... Param>
+auto work(Param && ...param)
+{
+ return ("asda" ... / param); // { dg-error "expected" }
+}
+
+int main()
+{
+ work(1.0, 2.0, 5, 4.0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inline-var8.C b/gcc/testsuite/g++.dg/cpp1z/inline-var8.C
new file mode 100644
index 0000000..8db3c19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inline-var8.C
@@ -0,0 +1,17 @@
+// PR c++/97975
+// { dg-do compile { target c++17 } }
+
+template <class>
+class A
+{
+ static const float b;
+ static inline const int c = b;
+};
+
+A<int> a;
+
+struct B
+{
+ static const float b;
+ static inline const int c = b;
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/attr-likely2.C b/gcc/testsuite/g++.dg/cpp2a/attr-likely2.C
index ee178de..0bc5f1e 100644
--- a/gcc/testsuite/g++.dg/cpp2a/attr-likely2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/attr-likely2.C
@@ -4,7 +4,7 @@ bool b;
int main()
{
if (b)
- [[likely, likely]] b; // { dg-warning "ignoring" }
+ [[likely, likely]] b; // { dg-warning "specified multiple times" }
else
[[unlikely]] [[likely]] b; // { dg-warning "ignoring" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast1.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast1.C
new file mode 100644
index 0000000..34cd1b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast1.C
@@ -0,0 +1,47 @@
+// { dg-do compile }
+
+struct S { short a, b; };
+struct T { float a[16]; };
+struct U { int b[16]; };
+
+#if __SIZEOF_FLOAT__ == __SIZEOF_INT__
+int
+f1 (float x)
+{
+ return __builtin_bit_cast (int, x);
+}
+#endif
+
+#if 2 * __SIZEOF_SHORT__ == __SIZEOF_INT__
+S
+f2 (int x)
+{
+ return __builtin_bit_cast (S, x);
+}
+
+int
+f3 (S x)
+{
+ return __builtin_bit_cast (int, x);
+}
+#endif
+
+#if __SIZEOF_FLOAT__ == __SIZEOF_INT__
+U
+f4 (T &x)
+{
+ return __builtin_bit_cast (U, x);
+}
+
+T
+f5 (int (&x)[16])
+{
+ return __builtin_bit_cast (T, x);
+}
+#endif
+
+int
+f6 ()
+{
+ return __builtin_bit_cast (unsigned char, (signed char) 0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
new file mode 100644
index 0000000..6bb1760
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
@@ -0,0 +1,57 @@
+// { dg-do compile }
+
+struct S { ~S (); int s; };
+S s;
+struct V; // { dg-message "forward declaration of 'struct V'" }
+extern V v; // { dg-error "'v' has incomplete type" }
+extern V *p;
+struct U { int a, b; };
+U u;
+
+void
+foo (int *q)
+{
+ __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' source type 'S' is not trivially copyable" }
+ __builtin_bit_cast (S, 0); // { dg-error "'__builtin_bit_cast' destination type 'S' is not trivially copyable" }
+ __builtin_bit_cast (int &, q); // { dg-error "'__builtin_bit_cast' destination type 'int&' is not trivially copyable" }
+ __builtin_bit_cast (int [1], 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is an array type" }
+ __builtin_bit_cast (V, 0); // { dg-error "invalid use of incomplete type 'struct V'" }
+ __builtin_bit_cast (int, v);
+ __builtin_bit_cast (int, *p); // { dg-error "invalid use of incomplete type 'struct V'" }
+ __builtin_bit_cast (U, 0); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" }
+ __builtin_bit_cast (int, u); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" }
+}
+
+template <int N>
+void
+bar (int *q)
+{
+ __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' source type 'S' is not trivially copyable" }
+ __builtin_bit_cast (S, 0); // { dg-error "'__builtin_bit_cast' destination type 'S' is not trivially copyable" }
+ __builtin_bit_cast (int &, q); // { dg-error "'__builtin_bit_cast' destination type 'int&' is not trivially copyable" }
+ __builtin_bit_cast (int [1], 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is an array type" }
+ __builtin_bit_cast (V, 0); // { dg-error "invalid use of incomplete type 'struct V'" }
+ __builtin_bit_cast (int, *p); // { dg-error "invalid use of incomplete type 'struct V'" }
+ __builtin_bit_cast (U, 0); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" }
+ __builtin_bit_cast (int, u); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" }
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void
+baz (T3 s, T4 *p, T1 *q)
+{
+ __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' source type 'S' is not trivially copyable" }
+ __builtin_bit_cast (T3, 0); // { dg-error "'__builtin_bit_cast' destination type 'S' is not trivially copyable" }
+ __builtin_bit_cast (T1 &, q); // { dg-error "'__builtin_bit_cast' destination type 'int&' is not trivially copyable" }
+ __builtin_bit_cast (T2, 0); // { dg-error "'__builtin_bit_cast' destination type \[^\n\r]* is an array type" }
+ __builtin_bit_cast (T4, 0); // { dg-error "invalid use of incomplete type 'struct V'" }
+ __builtin_bit_cast (int, *p); // { dg-error "invalid use of incomplete type 'struct V'" }
+ __builtin_bit_cast (U, (T1) 0); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" }
+ __builtin_bit_cast (T1, u); // { dg-error "'__builtin_bit_cast' source size '\[0-9]*' not equal to destination type size '\[0-9]*'" }
+}
+
+void
+qux (int *q)
+{
+ baz <int, int [1], S, V> (s, p, q);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast3.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast3.C
new file mode 100644
index 0000000..a3ff211
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast3.C
@@ -0,0 +1,229 @@
+// { dg-do compile { target c++11 } }
+
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+
+template <typename To, typename From>
+constexpr bool
+check (const From &from)
+{
+ return bit_cast <From> (bit_cast <To> (from)) == from;
+}
+
+struct A
+{
+ int a, b, c;
+ constexpr bool operator == (const A &x) const
+ {
+ return x.a == a && x.b == b && x.c == c;
+ }
+};
+
+struct B
+{
+ unsigned a[3];
+ constexpr bool operator == (const B &x) const
+ {
+ return x.a[0] == a[0] && x.a[1] == a[1] && x.a[2] == a[2];
+ }
+};
+
+struct C
+{
+ char a[2][3][2];
+ constexpr bool operator == (const C &x) const
+ {
+ return x.a[0][0][0] == a[0][0][0]
+ && x.a[0][0][1] == a[0][0][1]
+ && x.a[0][1][0] == a[0][1][0]
+ && x.a[0][1][1] == a[0][1][1]
+ && x.a[0][2][0] == a[0][2][0]
+ && x.a[0][2][1] == a[0][2][1]
+ && x.a[1][0][0] == a[1][0][0]
+ && x.a[1][0][1] == a[1][0][1]
+ && x.a[1][1][0] == a[1][1][0]
+ && x.a[1][1][1] == a[1][1][1]
+ && x.a[1][2][0] == a[1][2][0]
+ && x.a[1][2][1] == a[1][2][1];
+ }
+};
+
+struct D
+{
+ int a, b;
+ constexpr bool operator == (const D &x) const
+ {
+ return x.a == a && x.b == b;
+ }
+};
+
+struct E {};
+struct F { char c, d, e, f; };
+struct G : public D, E, F
+{
+ int g;
+ constexpr bool operator == (const G &x) const
+ {
+ return x.a == a && x.b == b && x.c == c && x.d == d
+ && x.e == e && x.f == f && x.g == g;
+ }
+};
+
+struct H
+{
+ int a, b[2], c;
+ constexpr bool operator == (const H &x) const
+ {
+ return x.a == a && x.b[0] == b[0] && x.b[1] == b[1] && x.c == c;
+ }
+};
+
+#if __SIZEOF_INT__ == 4
+struct I
+{
+ int a;
+ int b : 3;
+ int c : 24;
+ int d : 5;
+ int e;
+ constexpr bool operator == (const I &x) const
+ {
+ return x.a == a && x.b == b && x.c == c && x.d == d && x.e == e;
+ }
+};
+#endif
+
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+struct J
+{
+ long long int a, b : 11, c : 3, d : 37, e : 1, f : 10, g : 2, h;
+ constexpr bool operator == (const J &x) const
+ {
+ return x.a == a && x.b == b && x.c == c && x.d == d && x.e == e
+ && x.f == f && x.g == g && x.h == h;
+ }
+};
+
+struct K
+{
+ long long int a, b, c;
+ constexpr bool operator == (const K &x) const
+ {
+ return x.a == a && x.b == b && x.c == c;
+ }
+};
+
+struct M
+{
+ signed a : 6, b : 7, c : 6, d : 5;
+ unsigned char e;
+ unsigned int f;
+ long long int g;
+ constexpr bool operator == (const M &x) const
+ {
+ return x.a == a && x.b == b && x.c == c && x.d == d && x.e == e
+ && x.f == f && x.g == g;
+ }
+};
+
+struct N
+{
+ unsigned long long int a, b;
+ constexpr bool operator == (const N &x) const
+ {
+ return x.a == a && x.b == b;
+ }
+};
+#endif
+
+static_assert (check <unsigned int> (0), "");
+static_assert (check <long long int> (0xdeadbeeffeedbac1ULL), "");
+static_assert (check <signed char> ((unsigned char) 42), "");
+static_assert (check <char> ((unsigned char) 42), "");
+static_assert (check <unsigned char> ((unsigned char) 42), "");
+static_assert (check <signed char> ((signed char) 42), "");
+static_assert (check <char> ((signed char) 42), "");
+static_assert (check <unsigned char> ((signed char) 42), "");
+static_assert (check <signed char> ((char) 42), "");
+static_assert (check <char> ((char) 42), "");
+static_assert (check <unsigned char> ((char) 42), "");
+#if __SIZEOF_INT__ == __SIZEOF_FLOAT__
+static_assert (check <int> (2.5f), "");
+static_assert (check <unsigned int> (136.5f), "");
+#endif
+#if __SIZEOF_LONG_LONG__ == __SIZEOF_DOUBLE__
+static_assert (check <long long> (2.5), "");
+static_assert (check <long long unsigned> (123456.75), "");
+#endif
+
+static_assert (check <B> (A{ 1, 2, 3 }), "");
+static_assert (check <A> (B{ 4, 5, 6 }), "");
+
+#if __SIZEOF_INT__ == 4
+static_assert (check <C> (A{ 7, 8, 9 }), "");
+static_assert (check <C> (B{ 10, 11, 12 }), "");
+static_assert (check <A> (C{ { { { 13, 14 }, { 15, 16 }, { 17, 18 } },
+ { { 19, 20 }, { 21, 22 }, { 23, 24 } } } }), "");
+constexpr unsigned char c[] = { 1, 2, 3, 4 };
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+static_assert (bit_cast <unsigned int> (c) == 0x04030201U, "");
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+static_assert (bit_cast <unsigned int> (c) == 0x01020304U, "");
+#endif
+
+#if __cplusplus >= 201703L
+static_assert (check <G> (H { 0x12345678, { 0x23456789, 0x5a876543 }, 0x3ba78654 }), "");
+#endif
+constexpr int d[] = { 0x12345678, 0x23456789, 0x5a876543, 0x3ba78654 };
+static_assert (bit_cast <G> (d) == bit_cast <G> (H { 0x12345678, { 0x23456789, 0x5a876543 }, 0x3ba78654 }), "");
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+static_assert (bit_cast <I> (A { 0x7efa3412, 0x5a876543, 0x1eeffeed })
+ == I { 0x7efa3412, 3, 0x50eca8, 0xb, 0x1eeffeed }, "");
+static_assert (bit_cast <A> (I { 0x7efa3412, 3, 0x50eca8, 0xb, 0x1eeffeed })
+ == A { 0x7efa3412, 0x5a876543, 0x1eeffeed }, "");
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+static_assert (bit_cast <I> (A { 0x7efa3412, 0x5a876543, 0x1eeffeed })
+ == I { 0x7efa3412, 2, -0x2bc4d6, 0x3, 0x1eeffeed }, "");
+static_assert (bit_cast <A> (I { 0x7efa3412, 2, -0x2bc4d6, 0x3, 0x1eeffeed })
+ == A { 0x7efa3412, 0x5a876543, 0x1eeffeed }, "");
+#endif
+#endif
+
+#if 2 * __SIZEOF_INT__ == __SIZEOF_LONG_LONG__ && __SIZEOF_INT__ >= 4
+constexpr unsigned long long a = 0xdeadbeeffee1deadULL;
+constexpr unsigned b[] = { 0xfeedbacU, 0xbeeffeedU };
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+static_assert (bit_cast <D> (a) == D { int (0xfee1deadU), int (0xdeadbeefU) }, "");
+static_assert (bit_cast <unsigned long long> (b) == 0xbeeffeed0feedbacULL, "");
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+static_assert (bit_cast <D> (a) == D { int (0xdeadbeefU), int (0xfee1deadU) }, "");
+static_assert (bit_cast <unsigned long long> (b) == 0x0feedbacbeeffeedULL, "");
+#endif
+#endif
+
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+static_assert (bit_cast <J> (K { 0x0feedbacdeadbeefLL, 7862463375103529997LL, 0x0feedbacdeadbeefLL })
+ == J { 0x0feedbacdeadbeefLL, -1011, 2, -0xbacdeadbeLL, -1, -303, 1, 0x0feedbacdeadbeefLL }, "");
+static_assert (bit_cast <K> (J { 0x0feedbacdeadbeefLL, -1011, 2, -0xbacdeadbeLL, -1, -303, 1, 0x0feedbacdeadbeefLL })
+ == K { 0x0feedbacdeadbeefLL, 7862463375103529997LL, 0x0feedbacdeadbeefLL }, "");
+static_assert (bit_cast <M> (N { 0xfeedbacdeadbeef8ULL, 0x123456789abcde42ULL })
+ == M { -8, 59, 31, -5, 234, 0xfeedbacdU, 0x123456789abcde42ULL }, "");
+static_assert (bit_cast <N> (M { -8, 59, 31, -5, 234, 0xfeedbacdU, 0x123456789abcde42ULL })
+ == N { 0xfeedbacdeadbeef8ULL, 0x123456789abcde42ULL }, "");
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+static_assert (bit_cast <J> (K { 0x0feedbacdeadbeefLL, -9103311533965288635LL, 0x0feedbacdeadbeefLL })
+ == J { 0x0feedbacdeadbeefLL, -1011, 2, -0xbacdeadbeLL, -1, -303, 1, 0x0feedbacdeadbeefLL }, "");
+static_assert (bit_cast <K> (J { 0x0feedbacdeadbeefLL, -1011, 2, -0xbacdeadbeLL, -1, -303, 1, 0x0feedbacdeadbeefLL })
+ == K { 0x0feedbacdeadbeefLL, -9103311533965288635LL, 0x0feedbacdeadbeefLL }, "");
+static_assert (bit_cast <M> (N { 0xfeedbacdeadbeef8ULL, 0x123456789abcde42ULL })
+ == M { -1, -35, -19, -6, 205, 0xeadbeef8U, 0x123456789abcde42ULL }, "");
+static_assert (bit_cast <N> (M { -1, -35, -19, -6, 205, 0xeadbeef8U, 0x123456789abcde42ULL })
+ == N { 0xfeedbacdeadbeef8ULL, 0x123456789abcde42ULL }, "");
+#endif
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast4.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast4.C
new file mode 100644
index 0000000..9ffa2ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast4.C
@@ -0,0 +1,44 @@
+// { dg-do compile { target c++11 } }
+
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'U' is a union type" "U" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'const U' is a union type" "const U" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'B' contains a union type" "B" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'char\\\*' is a pointer type" "char ptr" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'const int\\\*' is a pointer type" "const int ptr" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'C' contains a pointer type" "C" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'const C' contains a pointer type" "const C" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'int D::\\\*' is a pointer to member type" "ptrmem 1" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'int \\\(D::\\\*\\\)\\\(\\\) const' is a pointer to member type" "ptrmem 2" { target *-*-* } 7 }
+// { dg-error "'__builtin_bit_cast' is not a constant expression because 'int \\\(D::\\\*\\\)\\\(\\\)' is a pointer to member type" "ptrmem 3" { target *-*-* } 7 }
+
+union U { int u; };
+struct A { int a; U b; };
+struct B : public A { int c; };
+struct C { const int *p; };
+constexpr int a[] = { 1, 2, 3 };
+constexpr const int *b = &a[0];
+constexpr C c = { b };
+struct D { int d; constexpr int foo () const { return 1; } };
+constexpr int D::*d = &D::d;
+constexpr int (D::*e) () const = &D::foo;
+struct E { __INTPTR_TYPE__ e, f; };
+constexpr E f = { 1, 2 };
+constexpr U g { 0 };
+
+constexpr auto z = bit_cast <U> (0);
+constexpr auto y = bit_cast <int> (g);
+constexpr auto x = bit_cast <B> (a);
+constexpr auto w = bit_cast <char *> ((__INTPTR_TYPE__) 0);
+constexpr auto v = bit_cast <__UINTPTR_TYPE__> (b);
+constexpr auto u = bit_cast <C> ((__INTPTR_TYPE__) 0);
+constexpr auto t = bit_cast <__INTPTR_TYPE__> (c);
+constexpr auto s = bit_cast <__INTPTR_TYPE__> (d);
+constexpr auto r = bit_cast <E> (e);
+constexpr auto q = bit_cast <int D::*> ((__INTPTR_TYPE__) 0);
+constexpr auto p = bit_cast <int (D::*) ()> (f);
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast5.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast5.C
new file mode 100644
index 0000000..9d536d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast5.C
@@ -0,0 +1,69 @@
+// { dg-do compile { target { c++20 && { ilp32 || lp64 } } } }
+
+struct A { signed char a, b, c, d, e, f; };
+struct B {};
+struct C { B a, b; short c; B d; };
+struct D { int a : 4, b : 24, c : 4; };
+struct E { B a, b; short c; };
+struct F { B a; signed char b, c; B d; };
+
+constexpr bool
+f1 ()
+{
+ A a;
+ a.c = 23; a.d = 42;
+ C b = __builtin_bit_cast (C, a); // OK
+ return false;
+}
+
+constexpr bool
+f2 ()
+{
+ A a;
+ a.a = 1; a.b = 2; a.c = 3; a.e = 4; a.f = 5;
+ C b = __builtin_bit_cast (C, a); // { dg-error "'__builtin_bit_cast' accessing uninitialized byte at offset 3" }
+ return false;
+}
+
+constexpr bool
+f3 ()
+{
+ D a;
+ a.b = 1;
+ F b = __builtin_bit_cast (F, a); // OK
+ return false;
+}
+
+constexpr bool
+f4 ()
+{
+ D a;
+ a.b = 1; a.c = 2;
+ E b = __builtin_bit_cast (E, a); // OK
+ return false;
+}
+
+constexpr bool
+f5 ()
+{
+ D a;
+ a.b = 1;
+ E b = __builtin_bit_cast (E, a); // { dg-error "'__builtin_bit_cast' accessing uninitialized byte at offset 3" }
+ return false;
+}
+
+constexpr bool
+f6 ()
+{
+ D a;
+ a.c = 1;
+ E b = __builtin_bit_cast (E, a); // { dg-error "'__builtin_bit_cast' accessing uninitialized byte at offset 2" }
+ return false;
+}
+
+constexpr bool a = f1 ();
+constexpr bool b = f2 ();
+constexpr bool c = f3 ();
+constexpr bool d = f4 ();
+constexpr bool e = f5 ();
+constexpr bool f = f6 ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C
new file mode 100644
index 0000000..4b70da1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C
@@ -0,0 +1,31 @@
+// PR libstd++/93121
+// { dg-do compile { target c++20 } }
+
+namespace std
+{
+enum class byte : unsigned char {};
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+}
+
+struct S { unsigned short s[2]; };
+constexpr std::byte from1[sizeof (S)]{};
+constexpr auto to1 = std::bit_cast<S>(from1);
+constexpr unsigned char from2[sizeof (S)]{};
+constexpr auto to2 = std::bit_cast<S>(from2);
+
+constexpr bool
+cmp (const S &s1, const S &s2)
+{
+ for (int i = 0; i < sizeof (s1.s) / sizeof (s1.s[0]); i++)
+ if (s1.s[i] != s2.s[i])
+ return false;
+ return true;
+}
+
+static_assert (cmp (to1, S{}));
+static_assert (cmp (to2, S{}));
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast7.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast7.C
new file mode 100644
index 0000000..4a3c682
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast7.C
@@ -0,0 +1,39 @@
+// PR c++/98193
+// { dg-do compile { target c++20 } }
+
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+
+struct J
+{
+ long int a, b : 11, h;
+};
+
+struct K
+{
+ long int a, b : 11, c;
+ constexpr bool operator == (const K &x)
+ {
+ return a == x.a && b == x.b && c == x.c;
+ }
+};
+
+struct L
+{
+ long long int a, b : 11, h;
+};
+struct M
+{
+ long long int a, b : 11, c;
+ constexpr bool operator == (const M &x)
+ {
+ return a == x.a && b == x.b && c == x.c;
+ }
+};
+
+static_assert (bit_cast <K> (J{}) == K{}, "");
+static_assert (bit_cast <M> (L{0x0feedbacdeadbeefLL}) == M{0x0feedbacdeadbeefLL}, "");
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-abbrev1.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-abbrev1.C
new file mode 100644
index 0000000..f931009
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-abbrev1.C
@@ -0,0 +1,13 @@
+ // { dg-do compile { target c++20 } }
+
+template <class T> struct A { };
+template <class T> concept is_A = requires { A(T()); };
+
+void f(auto); // OK
+void f(is_A auto); // OK
+void f(A); // { dg-error "placeholder" }
+
+int main()
+{
+ f(A<int>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-complete1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-complete1.C
index 63f3696..e8487bf 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-complete1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-complete1.C
@@ -1,11 +1,18 @@
+// Verify we diagnose an unstable satisfaction result that depends on
+// completeness of the type A below.
+//
// { dg-do compile { target c++20 } }
template <class T> concept has_mem_type = requires { typename T::type; };
+// { dg-message "satisfaction of 'has_mem_type<T>' .with T = A." "" { target *-*-* } .-1 }
+// { dg-error "satisfaction value of atomic constraint 'requires.typename T::type;. .with T = A.' changed from 'false' to 'true'" "" { target *-*-* } .-2 }
template <has_mem_type T> int f () { return 0; }
template <class T> char f() { return 0; }
struct A;
-static_assert (sizeof (f<A>()) == 1);
+static_assert (sizeof (f<A>()) == 1); // { dg-message "first evaluated to 'false' from here" }
struct A { typedef int type; };
+static_assert (sizeof (f<A>()) > 1); // { dg-error "assert" }
+// { dg-message "required from here" "" { target *-*-* } .-1 }
static_assert (sizeof (f<A>()) > 1);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-complete2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-complete2.C
new file mode 100644
index 0000000..b2c1160
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-complete2.C
@@ -0,0 +1,23 @@
+// Verify we diagnose an unstable satisfaction result that depends on
+// completeness of the type A below.
+//
+// Like in the previous test, here satisfaction also initially fails,
+// but this time due to failed substitution into the atom's parameter mapping.
+//
+// { dg-do compile { target c++20 } }
+
+template <class T> concept valid_type = requires { typename T; };
+// { dg-message "satisfaction of 'valid_type<typename T::type>' .with T = A." "" { target *-*-* } .-1 }
+// { dg-error "satisfaction value of atomic constraint 'requires.T;. .with T = typename T::type.' changed from 'false' to 'true'" "" { target *-*-* } .-2 }
+
+template <class T> concept has_mem_type = valid_type<typename T::type>;
+// { dg-message "satisfaction of 'has_mem_type<T>' .with T = A." "" { target *-*-* } .-1 }
+
+template <has_mem_type T> int f () { return 0; }
+template <class T> char f() { return 0; }
+
+struct A;
+static_assert (sizeof (f<A>()) == 1); // { dg-message "first evaluated to 'false' from here" }
+struct A { typedef int type; };
+static_assert (sizeof (f<A>()) > 1); // { dg-error "assert" }
+static_assert (sizeof (f<A>()) > 1);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-complete3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-complete3.C
new file mode 100644
index 0000000..5b07371
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-complete3.C
@@ -0,0 +1,16 @@
+// Verify we diagnose an unstable satisfaction result that depends on
+// return type deduction of the member function A::foo() below.
+//
+// { dg-do compile { target c++20 } }
+
+template <class T> concept fooable = requires (T t) { t.foo(); };
+// { dg-error "'false' to 'true'" "" { target *-*-* } .-1 }
+
+template <fooable T> int f () { return 0; }
+template <class T> char f() { return 0; }
+
+struct A { auto foo(); };
+static_assert (sizeof (f<A>()) == 1); // { dg-message "first evaluated to 'false' from here" }
+auto A::foo() { }
+static_assert (sizeof (f<A>()) > 1); // { dg-error "assert" }
+static_assert (sizeof (f<A>()) > 1);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-conv3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-conv3.C
new file mode 100644
index 0000000..d53f37c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-conv3.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++20 } }
+
+// Here, normal overload resolution would consider B::operator bool when
+// evaluating A(b), leading to a hard error instantiating Error<int>, but we
+// avoid considering it by noticing that converting bool (a scalar) to A (a
+// class) would require a user-defined conversion, which is not allowed when
+// we're already dealing with the user-defined conversion to A.
+
+// This seems to be allowed by [temp.inst]/9: "If the function selected by
+// overload resolution (12.4) can be determined without instantiating a class
+// template definition, it is unspecified whether that instantiation actually
+// takes place."
+
+template <class T>
+struct Error { static constexpr auto value = T::value; };
+
+struct A { A(const A&); };
+
+template <class T>
+struct B { operator bool() requires Error<T>::value; };
+
+template <class T>
+concept C = requires (B<T> b) { A(b); };
+
+static_assert(!C<int>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-conv3a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-conv3a.C
new file mode 100644
index 0000000..7e9e284
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-conv3a.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++20 } }
+
+// But make sure we do consider template conversions that could produce the
+// right type.
+
+template <class T>
+struct Error { static constexpr auto value = T::value; }; // { dg-error "not a member" }
+
+struct A { A(const A&); };
+
+template <class T>
+struct B { template <class U> operator U() requires Error<T>::value; };
+
+template <class T>
+concept C = requires (B<T> b) { A(b); }; // { dg-message "required from here" }
+
+static_assert(!C<int>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-decltype2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype2.C
new file mode 100644
index 0000000..529dab1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype2.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++20 } }
+
+template <class T> concept C = requires(T t) { t; };
+
+template <class T> using A = decltype((T{}, int{}));
+
+template <class T> concept D = C<A<T>>;
+
+template <class T> void f() requires D<T>;
+
+template <class, class>
+void g() { f<int>(); }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C
new file mode 100644
index 0000000..837855c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++20 } }
+
+template <class T> concept C = requires(T t) { t; };
+
+template <class T> using A = decltype((T{}, int{}));
+
+template <class T> concept D = C<A<T>>;
+
+template <class T, class U> void f() requires D<T>;
+template <class T> void g() requires D<T>;
+
+void h() {
+ f<int, int>();
+ g<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C b/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C
new file mode 100644
index 0000000..62111df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C
@@ -0,0 +1,11 @@
+// PR c++/95132
+// { dg-do compile { target c++20 } }
+
+template <class T> struct A {
+ static auto f() requires false { return T::fail; }
+};
+
+template <class T>
+concept C = requires { A<T>::f(); };
+
+static_assert(!C<int>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
new file mode 100644
index 0000000..3d5cd85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
@@ -0,0 +1,11 @@
+// PR c++/98019
+// { dg-do compile { target c++20 } }
+// Don't give [[nodiscard]] warning for an expression requirement.
+
+template <class T, class U> concept same_as = __is_same_as (T, U);
+
+[[nodiscard]] int foo() { return 0; }
+[[maybe_unused]] constexpr bool b = requires {
+ { foo() } -> same_as<int>;
+};
+[[maybe_unused]] constexpr auto x = sizeof(foo());
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nonbool3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nonbool3.C
new file mode 100644
index 0000000..2a2af54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nonbool3.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++20 } }
+
+template <auto V> concept C = false || V || false; // { dg-error "has type 'int'" }
+template <auto V> int f() requires C<V>;
+int a = f<0>(); // { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr78173.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr78173.C
new file mode 100644
index 0000000..50f561a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr78173.C
@@ -0,0 +1,9 @@
+// PR c++/78173
+// { dg-do compile { target c++20 } }
+
+template <class T>
+concept CanDifference = requires(T x, T y) {
+ x - y;
+};
+
+static_assert(!CanDifference<void*>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C
index ce69a0f..290aaf8 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C
@@ -4,9 +4,9 @@
template <typename T>
void foo1(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- (typename T::template D<auto> (t)); // { dg-error "invalid" }
+ typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } }
+ T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" }
+ (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted" }
}
struct T1 {
@@ -22,9 +22,9 @@ struct T1 {
template <typename T>
void foo2(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- T::template D<auto> (t); // { dg-error "invalid" }
+ typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } }
+ T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" }
+ T::template D<auto> (t); // { dg-error "invalid|not permitted" }
}
struct T2 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C
index 3809c2d..d612327 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C
@@ -8,9 +8,9 @@
template <typename T>
void foo1(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- (typename T::template D<auto> (t)); // { dg-error "invalid" }
+ typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } }
+ T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" }
+ (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted" }
}
struct T1 {
@@ -26,9 +26,9 @@ struct T1 {
template <typename T>
void foo2(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- T::template D<auto> (t); // { dg-error "yields a type" }
+ typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } }
+ T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" }
+ T::template D<auto> (t); // { dg-error "yields a type|not permitted" }
}
struct T2 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979.C
index 9bd40df..81555eb 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979.C
@@ -5,5 +5,5 @@ template<typename> void foo() {}
void bar()
{
- foo<auto>(); // { dg-error "invalid" }
+ foo<auto>(); // { dg-error "not permitted|invalid|no matching function" }
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
index 1c25252..e1792e1 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
@@ -1,9 +1,9 @@
// { dg-do compile { target c++20 } }
template <class T, class U>
-concept Concept2 = requires (T t, U u)
+concept Concept2 = requires (T t, U u) // { dg-error "depends on itself" }
{
- t += u; // { dg-error "template instantiation depth" }
+ t += u;
};
template <class T>
@@ -17,7 +17,5 @@ struct S
constexpr S operator * (S a, S b)
{
- return a += b;
+ return a += b; // { dg-error "no match" }
}
-
-// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr97093.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr97093.C
new file mode 100644
index 0000000..d662552
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr97093.C
@@ -0,0 +1,32 @@
+// PR c++/97093
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fconcepts-diagnostics-depth=3 --param=hash-table-verification-limit=10000" }
+
+template <typename T>
+concept C = requires (T t)
+{
+ requires t.some_const < 2 || requires { t.some_fn (); };
+};
+
+template <unsigned, unsigned>
+struct c
+{};
+
+template <typename T>
+concept P = requires (T t, c <0, 1> v) { { t (v) }; }; // { dg-error "no match" }
+
+template <P auto, P auto ...>
+struct m
+{
+ constexpr auto operator () (C auto) const
+ {};
+};
+
+struct pc
+{
+ constexpr auto operator () (C auto) const
+ {};
+};
+
+constexpr auto cc = pc {};
+constexpr auto mmcc = m <cc> {}; // { dg-error "not satisfied" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
index 992fcbb..9bc96f5 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
@@ -1,7 +1,7 @@
// { dg-do compile { target c++20 } }
template<typename T>
-concept Fooable = requires(T t) { foo(t); }; // { dg-error "template instantiation depth" }
+concept Fooable = requires(T t) { foo(t); }; // { dg-error "depends on itself" }
template<Fooable T>
void foo(T t) { }
@@ -9,7 +9,5 @@ void foo(T t) { }
void test()
{
struct S {} s;
- foo(s);
+ foo(s); // { dg-error "no match" }
}
-
-// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat4.C
new file mode 100644
index 0000000..18d126e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat4.C
@@ -0,0 +1,13 @@
+// PR c++/96840
+// { dg-do compile { target c++20 } }
+
+template <class T, class U> concept C = requires(T t, U u) { t * u; };
+// { dg-message "required for the satisfaction of 'C<T, Rep>' .with T = Int<int>; Rep = int." "" { target *-*-* } .-1 }
+// { dg-error "depends on itself" "" { target *-*-* } .-2 }
+
+template <class Rep> struct Int {
+ template <class T> requires C<T, Rep> friend void operator*(T, Int) { }
+ template <class T> requires C<T, Rep> friend void operator*(Int, T) { }
+};
+
+void f() { 0 * Int<int>{}; }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C
index a9b7720..9e45c58 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C
@@ -4,7 +4,7 @@ template<typename T>
concept integer = __is_same_as(T, int);
template<typename T>
-concept subst = requires (T x) { requires true; }; // { dg-error "parameter type .void." }
+concept subst = requires (T x) { requires true; };
template<typename T>
concept c1 = requires { requires integer<T> || subst<T&>; }; // { dg-message "in requirements" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C
index bc38b89..8aead2f 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires21.C
@@ -5,3 +5,4 @@ template<typename T, typename U>
constexpr bool is_same_v = __is_same (T, U);
static_assert(is_same_v<bool, decltype(requires { requires false; })>);
+// { dg-bogus "evaluated to 'false" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires22.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires22.C
new file mode 100644
index 0000000..5afcbbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires22.C
@@ -0,0 +1,18 @@
+// PR c++/97093
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fconcepts-diagnostics-depth=3" }
+
+template<class X, X x>
+concept C = requires {
+ requires (X)x; // { dg-message "false" }
+ };
+
+template<class X, X x>
+concept D = requires {
+ requires false || (X)x; // { dg-message "false" }
+ };
+
+int main() {
+ static_assert(C<bool, 0>); // { dg-error "failed" }
+ static_assert(D<bool, 0>); // { dg-error "failed" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires23.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires23.C
new file mode 100644
index 0000000..e109bea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires23.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++20 } }
+
+// Verify f<A>'s associated constraints evaluate to false due
+// to return type deduction failure for A::foo().
+
+template <class T> concept fooable = requires { T::foo(0); };
+template <fooable T> int f ();
+struct A { static auto *foo(auto); };
+int a = f<A>(); // { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using3.C
new file mode 100644
index 0000000..2c8ad40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using3.C
@@ -0,0 +1,52 @@
+// PR c++/93907
+// { dg-options -std=gnu++20 }
+
+// This testcase is a variadic version of concepts-using2.C; the only
+// difference is that 'cd' and 'ce' are now variadic concepts.
+
+template <int a> struct c {
+ static constexpr int d = a;
+ typedef c e;
+};
+template <typename> struct f;
+template <typename b> using g = typename f<b>::e;
+struct b;
+template <typename b> struct f { using e = b; };
+template <typename ai> struct m { typedef g<ai> aj; };
+template <typename b> struct n { typedef typename m<b>::aj e; };
+template <typename b> using an = typename n<b>::e;
+template <typename> constexpr bool ao = c<true>::d;
+template <typename> constexpr bool i = c<1>::d;
+template <typename> concept bb = i<b>;
+#ifdef __SIZEOF_INT128__
+using cc = __int128;
+#else
+using cc = long long;
+#endif
+template <typename...> concept cd = bb<cc>;
+template <typename... bt> concept ce = requires { requires cd<bt...>; };
+template <typename bt> concept h = ce<bt>;
+template <typename bt> concept l = h<bt>;
+template <typename> concept cl = ao<b>;
+template <typename b> concept cp = requires(b j) {
+ requires h<an<decltype(j.begin())>>;
+};
+struct o {
+ template <cl b> requires cp<b> auto operator()(b) {}
+};
+template <typename b> using cm = decltype(o{}(b()));
+template <typename bt> concept ct = l<bt>;
+template <typename da> concept dd = ct<cm<da>>;
+template <typename da> concept de = dd<da>;
+struct {
+ template <de da, typename b> void operator()(da, b);
+} di;
+struct p {
+ void begin();
+};
+template <typename> using df = p;
+template <int> void q() {
+ df<int> k;
+ int d;
+ di(k, d);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-variadic2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-variadic2.C
new file mode 100644
index 0000000..ce61aef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-variadic2.C
@@ -0,0 +1,12 @@
+// PR c++/97412
+// { dg-do compile { target c++20 } }
+
+template <class T, class... TArgs>
+concept call_bar_with = requires(T t, TArgs... args) {
+ t.bar(args...);
+};
+
+template <class T, class... TArgs>
+concept foo = requires {
+ requires call_bar_with<T, TArgs...>;
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C
new file mode 100644
index 0000000..826ee25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg1.C
@@ -0,0 +1,11 @@
+// Test that late-parsed default args have the same consteval semantics.
+// { dg-do compile { target c++20 } }
+
+consteval bool foo (bool x) { if (x) throw 1; return false; }
+consteval bool bar (bool x = foo (true)) { return true; }
+struct S
+{
+ consteval static bool baz (bool x = foo (true)) { return true; }
+};
+constexpr bool a = bar (true);
+constexpr bool b = S::baz (true);
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-defarg2.C b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg2.C
new file mode 100644
index 0000000..e8462c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg2.C
@@ -0,0 +1,29 @@
+// Test that late-parsed default args have the same consteval semantics.
+// { dg-do compile { target c++20 } }
+
+template <int N>
+consteval bool foo (bool x) { if (x) throw N; return false; }
+consteval bool qux (bool x) { if (x) throw 1; return false; }
+template <int N>
+consteval bool bar (bool x = foo<N> (true)) { return true; }
+template <int N>
+consteval bool corge (bool x = qux (true)) { return true; }
+template <int N>
+struct S
+{
+ consteval static bool baz (bool x = foo<N> (true)) { return true; }
+ consteval static bool garply (bool x = qux (true)) { return true; }
+};
+struct T
+{
+ template <int N>
+ consteval static bool baz (bool x = foo<N> (true)) { return true; }
+ template <int N>
+ consteval static bool garply (bool x = qux (true)) { return true; }
+};
+constexpr bool a = bar<0> (true);
+constexpr bool b = corge<0> (true);
+constexpr bool c = S<0>::baz (true);
+constexpr bool d = S<0>::garply (true);
+constexpr bool e = T::baz<0> (true);
+constexpr bool f = T::garply<0> (true);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C
new file mode 100644
index 0000000..01bdfa5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C
@@ -0,0 +1,25 @@
+// PR c++/98122
+// { dg-do compile { target c++20 } }
+
+union V { int a; char b; };
+union W { int a; int b; };
+
+constexpr bool
+bar ()
+{
+ V f { .b = 42 };
+ constexpr auto m = &V::a;
+ return (f.*m) == 42;
+}
+
+constexpr bool
+baz ()
+{
+ W f { .b = 42 };
+ constexpr auto m = &W::b;
+ return (f.*m) == 42;
+}
+
+static_assert (bar (), ""); // { dg-error "non-constant condition for static assertion" }
+ // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" "" { target *-*-* } .-1 }
+static_assert (baz (), "");
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor10.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor10.C
new file mode 100644
index 0000000..1551746
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor10.C
@@ -0,0 +1,16 @@
+// PR c++/97427
+// { dg-do compile { target c++20 } }
+
+struct Foo {
+ int n = 1;
+ constexpr ~Foo() {
+ n = 0;
+ }
+};
+
+constexpr bool foo() {
+ const Foo b;
+ return true;
+}
+
+static_assert(foo());
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor5.C
new file mode 100644
index 0000000..1739afb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor5.C
@@ -0,0 +1,35 @@
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int m;
+ constexpr S () : m(1) {}
+ constexpr ~S () noexcept (false) { if (m == 1) { throw; } }
+};
+
+constexpr bool
+foo (S v)
+{
+ v.m = 2;
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ return foo (S ());
+}
+
+constexpr bool
+baz ()
+{
+ foo (S ());
+ return foo (S ());
+}
+
+static_assert (foo (S ()));
+static_assert (bar ());
+static_assert (baz ());
+constexpr bool x = foo (S ());
+constexpr bool y = bar ();
+constexpr bool z = baz ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor6.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor6.C
new file mode 100644
index 0000000..ce783a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor6.C
@@ -0,0 +1,36 @@
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int *s;
+ constexpr S () : s(new int ()) {}
+ constexpr S (S &&x) noexcept : s(x.s) { x.s = nullptr; }
+ constexpr ~S () noexcept { delete s; }
+};
+
+constexpr bool
+foo (S v)
+{
+ auto x = static_cast<S &&> (v);
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ return foo (S ());
+}
+
+constexpr bool
+baz ()
+{
+ foo (S ());
+ return foo (S ());
+}
+
+static_assert (foo (S ()));
+static_assert (bar ());
+static_assert (baz ());
+constexpr bool x = foo (S ());
+constexpr bool y = bar ();
+constexpr bool z = baz ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C
new file mode 100644
index 0000000..463eaca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C
@@ -0,0 +1,19 @@
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int *s;
+ constexpr S () : s(new int) {} // { dg-error "is not a constant expression because allocated storage has not been deallocated" }
+ S (const S &) = delete;
+ S &operator= (const S &) = delete;
+ constexpr ~S () { delete s; }
+};
+
+constexpr bool
+foo (S v)
+{
+ v.s = nullptr;
+ return true;
+}
+
+static_assert (foo (S ())); // { dg-error "non-constant condition for static assertion" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor8.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor8.C
new file mode 100644
index 0000000..3048110
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor8.C
@@ -0,0 +1,19 @@
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int *s;
+ constexpr S () : s(new int) {}
+ S (const S &) = delete;
+ S &operator= (const S &) = delete;
+ constexpr ~S () { delete s; } // { dg-error "already deallocated" }
+};
+
+constexpr bool
+foo (S v)
+{
+ delete v.s;
+ return true;
+}
+
+static_assert (foo (S ())); // { dg-error "non-constant condition for static assertion" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C
new file mode 100644
index 0000000..975e5fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C
@@ -0,0 +1,31 @@
+// PR c++/97790
+// { dg-do compile { target c++20 } }
+
+struct S
+{
+ int *d;
+ int n;
+ constexpr S () : d(new int[1]{}), n(1) {}
+ constexpr ~S () { delete [] d; }
+};
+
+constexpr S
+foo ()
+{
+ return S ();
+}
+
+constexpr int
+bar ()
+{
+ return foo ().n;
+}
+
+constexpr int
+baz ()
+{
+ return S ().n;
+}
+
+constexpr int a = baz ();
+constexpr int b = bar ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C
new file mode 100644
index 0000000..e97e7aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C
@@ -0,0 +1,21 @@
+// PR c++/95808
+// { dg-do compile { target c++20 } }
+
+constexpr
+bool foo ()
+{
+ int *p = new int; // { dg-message "allocation performed here" }
+ delete[] p; // { dg-error "array deallocation of object allocated with non-array allocation" }
+ return false;
+}
+
+constexpr
+bool bar ()
+{
+ int *p = new int[1]; // { dg-message "allocation performed here" }
+ delete p; // { dg-error "non-array deallocation of object allocated with array allocation" }
+ return false;
+}
+
+constexpr auto x = foo ();
+constexpr auto y = bar ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C b/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C
new file mode 100644
index 0000000..4571b5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C
@@ -0,0 +1,117 @@
+// PR c++/97573
+// { dg-do compile }
+// No special options. In C++20 (only), we should get the deprecated warnings
+// by default. -Wenum-compare is enabled by default so some of them will be
+// printed even pre-C++20.
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+__extension__ static enum { } u1;
+__extension__ static enum { } u2;
+static double d;
+
+void
+conv ()
+{
+ bool b1 = e == e1;
+ bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } }
+ bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type .double. with enumeration type .E2." "" { target c++20 } }
+ int n1 = true ? e : f; // { dg-warning "enumerated mismatch" }
+ int n2 = true ? e : 0.0; // { dg-warning "conditional expression between" "" { target c++20 } }
+}
+
+int
+enum_enum (bool b)
+{
+ int r = 0;
+ const E1 e1c = e;
+
+ r += e - e;
+ r += e - e1;
+ r += e - f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += f - e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } }
+
+ r += f + f;
+ r += f + e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } }
+ r += e + f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+
+ r += e1 - e2; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += e1 - e1c;
+ r += e1c - e1;
+
+ r += e * f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += f * e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } }
+ r += e * e;
+
+ r += e1 < e1c;
+ r += e < e1;
+ r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += e1 == e1c;
+ r += e == e1;
+ r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+ r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += b ? e1 : e1c;
+ r += b ? e1 : e;
+ r += b ? f : e; // { dg-warning "enumerated mismatch in conditional expression: .E2. vs .E1." }
+ r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional expression: .E1. vs .E2." }
+
+ r += e | f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += e ^ f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += e & f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += !e;
+ r += e1 | e;
+
+ r += e << f;
+ r += e >> f;
+ r += e || f;
+ r += e && f;
+ e1 = e1c;
+
+ // Anonymous enum.
+ r += u1 - u1;
+ r += u1 + u2; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
+ r += u1 * u2; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
+ r += u1 == u2; // { dg-warning "comparison between" }
+ r += u1 & u2; // { dg-warning "bitwise operation between different enumeration types" "" { target c++20 } }
+
+ return r;
+}
+
+double
+enum_float (bool b)
+{
+ double r = 0.0;
+
+ r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += d - e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += d + e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += d * e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += u1 * d; // { dg-warning "arithmetic between enumeration type" "" { target c++20 } }
+ r += d * u1; // { dg-warning "arithmetic between floating-point type" "" { target c++20 } }
+
+ r += e1 < d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } }
+ r += d < e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target c++20 } }
+ r += d == e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target c++20 } }
+ r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } }
+ r += u1 == d; // { dg-warning "comparison of enumeration type" "" { target c++20 } }
+ r += d == u1; // { dg-warning "comparison of floating-point type" "" { target c++20 } }
+
+ r += b ? e1 : d; // { dg-warning "conditional expression between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += b ? d : e1; // { dg-warning "conditional expression between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += b ? d : u1; // { dg-warning "conditional expression between" "" { target c++20 } }
+ r += b ? u1 : d; // { dg-warning "conditional expression between" "" { target c++20 } }
+
+ d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ d = e1;
+
+ return r;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/enum-conv2.C b/gcc/testsuite/g++.dg/cpp2a/enum-conv2.C
new file mode 100644
index 0000000..f15827b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/enum-conv2.C
@@ -0,0 +1,115 @@
+// PR c++/97573
+// { dg-do compile { target c++20 } }
+// { dg-options "-Wno-deprecated -Wno-enum-compare" }
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+__extension__ static enum { } u1;
+__extension__ static enum { } u2;
+static double d;
+
+void
+conv ()
+{
+ bool b1 = e == e1;
+ bool b2 = e == f;
+ bool b3 = e == 0.0;
+ bool b4 = 0.0 == f;
+ int n1 = true ? e : f;
+ int n2 = true ? e : 0.0;
+}
+
+int
+enum_enum (bool b)
+{
+ int r = 0;
+ const E1 e1c = e;
+
+ r += e - e;
+ r += e - e1;
+ r += e - f;
+ r += f - e;
+
+ r += f + f;
+ r += f + e;
+ r += e + f;
+
+ r += e1 - e2;
+ r += e1 - e1c;
+ r += e1c - e1;
+
+ r += e * f;
+ r += f * e;
+ r += e * e;
+
+ r += e1 < e1c;
+ r += e < e1;
+ r += e1 < e2;
+ r += e < f;
+ r += f < e;
+
+ r += e1 == e1c;
+ r += e == e1;
+ r += e == f;
+ r += f == e;
+ r += e1 == e2;
+ r += e2 == e1;
+
+ r += b ? e1 : e1c;
+ r += b ? e1 : e;
+ r += b ? f : e;
+ r += b ? e1 : e2;
+
+ r += e | f;
+ r += e ^ f;
+ r += e & f;
+ r += !e;
+ r += e1 | e;
+
+ r += e << f;
+ r += e >> f;
+ r += e || f;
+ r += e && f;
+ e1 = e1c;
+
+ // Anonymous enum.
+ r += u1 - u1;
+ r += u1 + u2;
+ r += u1 * u2;
+ r += u1 == u2;
+ r += u1 & u2;
+
+ return r;
+}
+
+double
+enum_float (bool b)
+{
+ double r = 0.0;
+
+ r += e1 - d;
+ r += d - e1;
+ r += e1 + d;
+ r += d + e1;
+ r += e1 * d;
+ r += d * e1;
+ r += u1 * d;
+ r += d * u1;
+
+ r += e1 < d;
+ r += d < e1;
+ r += d == e1;
+ r += e1 == d;
+ r += u1 == d;
+ r += d == u1;
+
+ r += b ? e1 : d;
+ r += b ? d : e1;
+ r += b ? d : u1;
+ r += b ? u1 : d;
+
+ d += e1;
+ d = e1;
+
+ return r;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/enum-conv3.C b/gcc/testsuite/g++.dg/cpp2a/enum-conv3.C
new file mode 100644
index 0000000..67bdf16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/enum-conv3.C
@@ -0,0 +1,115 @@
+// PR c++/97573
+// { dg-do compile { target { c++17_down } } }
+// { dg-options "-Wenum-conversion" }
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+__extension__ static enum { } u1;
+__extension__ static enum { } u2;
+static double d;
+
+void
+conv ()
+{
+ bool b1 = e == e1;
+ bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." }
+ bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type .double. with enumeration type .E2." }
+ int n1 = true ? e : f; // { dg-warning "enumerated mismatch" }
+ int n2 = true ? e : 0.0; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+}
+
+int
+enum_enum (bool b)
+{
+ int r = 0;
+ const E1 e1c = e;
+
+ r += e - e;
+ r += e - e1;
+ r += e - f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+ r += f - e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." }
+
+ r += f + f;
+ r += f + e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." }
+ r += e + f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+
+ r += e1 - e2; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+ r += e1 - e1c;
+ r += e1c - e1;
+
+ r += e * f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+ r += f * e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." }
+ r += e * e;
+
+ r += e1 < e1c;
+ r += e < e1;
+ r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += e1 == e1c;
+ r += e == e1;
+ r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+ r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += b ? e1 : e1c;
+ r += b ? e1 : e;
+ r += b ? f : e; // { dg-warning "enumerated mismatch in conditional expression: .E2. vs .E1." }
+ r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional expression: .E1. vs .E2." }
+
+ r += e | f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." }
+ r += e ^ f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." }
+ r += e & f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." }
+ r += !e;
+ r += e1 | e;
+
+ r += e << f;
+ r += e >> f;
+ r += e || f;
+ r += e && f;
+ e1 = e1c;
+
+ // Anonymous enum.
+ r += u1 - u1;
+ r += u1 + u2; // { dg-warning "arithmetic between different enumeration types" }
+ r += u1 * u2; // { dg-warning "arithmetic between different enumeration types" }
+ r += u1 == u2; // { dg-warning "comparison between" }
+ r += u1 & u2; // { dg-warning "bitwise operation between different enumeration types" }
+
+ return r;
+}
+
+double
+enum_float (bool b)
+{
+ double r = 0.0;
+
+ r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." }
+ r += d - e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." }
+ r += d + e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." }
+ r += d * e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ r += u1 * d; // { dg-warning "arithmetic between enumeration type" }
+ r += d * u1; // { dg-warning "arithmetic between floating-point type" }
+
+ r += e1 < d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." }
+ r += d < e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." }
+ r += d == e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." }
+ r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." }
+ r += u1 == d; // { dg-warning "comparison of enumeration type" }
+ r += d == u1; // { dg-warning "comparison of floating-point type" }
+
+ r += b ? e1 : d; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+ r += b ? d : e1; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+ r += b ? d : u1; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+ r += b ? u1 : d; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+
+ d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ d = e1;
+
+ return r;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
index 7f1fe34..dc46e48 100644
--- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
+++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
@@ -533,3 +533,9 @@
#elif __cpp_concepts != 201907
# error "__cpp_concepts != 201907"
#endif
+
+#ifndef __cpp_using_enum
+# error "__cpp_using_enum"
+#elif __cpp_using_enum != 201907
+# error "__cpp_using_enum != 201907"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template16.C b/gcc/testsuite/g++.dg/cpp2a/fn-template16.C
index becaff1..8ee783a 100644
--- a/gcc/testsuite/g++.dg/cpp2a/fn-template16.C
+++ b/gcc/testsuite/g++.dg/cpp2a/fn-template16.C
@@ -7,7 +7,7 @@ struct undeclared<int> { }; // { dg-error "not a class template" }
int
main ()
{
- int foo ();
+ int foo (); // { dg-warning "empty parentheses" }
int foo (int);
int foo (int, int);
int a, b = 10;
diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template7.C b/gcc/testsuite/g++.dg/cpp2a/fn-template7.C
index d048606..2c5ee12 100644
--- a/gcc/testsuite/g++.dg/cpp2a/fn-template7.C
+++ b/gcc/testsuite/g++.dg/cpp2a/fn-template7.C
@@ -7,7 +7,7 @@ struct undeclared<int> { }; // { dg-error "not a class template" }
int
main ()
{
- int foo ();
+ int foo (); // { dg-warning "empty parentheses" }
int a, b = 10;
a = foo<; // { dg-error "invalid template-argument-list|invalid" }
a = foo < b; // { dg-error "invalid template-argument-list|invalid" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic8.C b/gcc/testsuite/g++.dg/cpp2a/lambda-generic8.C
new file mode 100644
index 0000000..f3c3809
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic8.C
@@ -0,0 +1,9 @@
+// PR c++/97839
+// { dg-do compile { target c++20 } }
+// Test that a lambda with <template-param-list> doesn't require
+// a lambda-declarator.
+
+int main()
+{
+ []<typename T>{}.operator()<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C b/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
index c810fd0..c95fa1b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
@@ -2,7 +2,7 @@
/* { dg-do compile { target c++20 } } */
/* { dg-options "-O -ftrack-macro-expansion=0" } */
-[[nodiscard, nodiscard]] int check1 (void); /* { dg-error "nodiscard\[^\n\r]*can appear at most once" } */
+[[nodiscard, nodiscard]] int check1 (void); // { dg-warning "specified multiple times" }
void
test (void)
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
new file mode 100644
index 0000000..f5f79a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
@@ -0,0 +1,12 @@
+// PR c++/89565
+// { dg-do compile { target c++20 } }
+// { dg-ice "resolve_args" }
+
+template <auto>
+struct N{};
+
+template <N>
+struct S {};
+
+template <typename T>
+using NS = S<T::value>;
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
new file mode 100644
index 0000000..d193544
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
@@ -0,0 +1,79 @@
+// PR c++/93083
+// { dg-do compile { target c++20 } }
+
+template<unsigned N>
+struct FixedString
+{
+ char buf[N + 1]{};
+ constexpr FixedString(char const* s) {
+ for (unsigned i = 0; i != N; ++i) buf[i] = s[i];
+ }
+
+ auto operator<=>(const FixedString&) const = default;
+ constexpr operator char const*() const { return buf; }
+ constexpr static unsigned size() noexcept { return N; }
+};
+
+template<unsigned N> FixedString(char const (&)[N]) -> FixedString<N - 1>;
+
+template <FixedString... names>
+struct name_list
+{
+ template <FixedString name>
+ using add_name = name_list<
+ names...,
+ FixedString<name.size()>{ name }
+ >;
+};
+
+
+int main()
+{
+ using names =
+ name_list<>
+ ::add_name<"Zaphod Beeblebrox">;
+
+}
+
+// ----------------
+
+template <int N> struct literal {
+ constexpr literal(const char (&input)[N]) noexcept { }
+ constexpr literal(const literal &) noexcept { }
+};
+
+template <literal Name, int id> struct field { };
+
+template <literal Name> struct field<Name, 1u> { };
+
+// ----------------
+
+template <int N>
+struct use_as_nttp {};
+
+template <use_as_nttp Value>
+struct has_nttp {};
+
+template <use_as_nttp Value>
+using has_nttp_2 = has_nttp<Value>;
+
+// ----------------
+
+using size_t = decltype(sizeof(0));
+
+template <size_t N>
+struct string_literal
+{
+ constexpr string_literal(const char*) {}
+ string_literal(string_literal const&) = default;
+};
+template <size_t N>
+string_literal(const char (&)[N]) -> string_literal<N - 1>;
+
+template <string_literal Str>
+struct type_string { };
+
+template <string_literal Str>
+void foo() {
+ type_string<Str>{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/pr98082.C b/gcc/testsuite/g++.dg/cpp2a/pr98082.C
new file mode 100644
index 0000000..b2caacb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/pr98082.C
@@ -0,0 +1,14 @@
+/* PR middle-end/98082 */
+/* Reported by Martin Liska <marxin@gcc.gnu.org> */
+
+/* { dg-do compile { target c++20 } } */
+/* { dg-options "-fipa-icf" } */
+
+class GoodIter {
+public:
+ GoodIter();
+ GoodIter(GoodIter &);
+};
+
+GoodIter operator-(int, GoodIter) { return GoodIter(); }
+GoodIter operator+(int, GoodIter) { return GoodIter(); }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C
new file mode 100644
index 0000000..3dc2a0f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++20 } }
+// Test [depr.arith.conv.enum] for <=>.
+
+#include <compare>
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+static double d;
+
+void
+g ()
+{
+ void(e1 <=> e);
+ e1 <=> d; // { dg-error "invalid operands of types .E1. and .double." }
+ d <=> e1; // { dg-error "invalid operands of types .double. and .E1." }
+ e <=> d; // { dg-error "invalid operands of types .E1. and .double." }
+ d <=> e; // { dg-error "invalid operands of types .double. and .E1." }
+
+ e <=> f; // { dg-error "invalid operands of types .E1. and .E2." }
+ f <=> e; // { dg-error "invalid operands of types .E2. and .E1." }
+ e1 <=> e2; // { dg-error "invalid operands of types .E1. and .E2." }
+ e2 <=> e1; // { dg-error "invalid operands of types .E2. and .E1." }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-p1186.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-p1186.C
new file mode 100644
index 0000000..a979fcb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-p1186.C
@@ -0,0 +1,117 @@
+// PR c++/96299
+// P1186R3
+// { dg-do compile { target c++20 } }
+
+#include <compare>
+
+struct H {
+ bool operator==(H const &) const;
+ bool operator<(H const &) const;
+};
+
+// Can't deduce category from op< and op==.
+struct A {
+ int i;
+ char c;
+ H h; // { dg-error "operator<=>" }
+ auto operator<=>(A const &) const = default;
+};
+
+// OK, explicit return type tells us how to interpret op</==.
+struct B {
+ int i;
+ char c;
+ H h;
+ std::strong_ordering operator<=>(B const &) const = default;
+};
+
+struct C {
+ bool operator<(C const &) const;
+};
+
+// C's op< isn't enough, need op== as well.
+struct D {
+ C c; // { dg-error "operator<=>" }
+ std::strong_ordering operator<=>(D const &) const = default;
+};
+
+struct E {
+ std::partial_ordering operator<=>(E const &) const;
+};
+
+// Can't use a weak op<=> to build a strong op<=>.
+struct F {
+ E e; // { dg-error "strong_ordering" }
+ H h;
+ std::strong_ordering operator<=>(F const &) const = default;
+};
+
+struct G {
+ std::strong_ordering operator<=>(G const &) const;
+};
+
+// OK, uses op<=> for g and op</op== for h.
+struct I {
+ G g;
+ H h;
+ std::partial_ordering operator<=>(I const &) const = default;
+};
+
+template <class T>
+struct J {
+ T t; // { dg-error "no match|ambiguous" }
+ auto operator<=>(J const &) const = default;
+};
+
+template <class T>
+struct K {
+ T t; // { dg-error "no match" }
+ std::partial_ordering operator<=>(K const &) const = default;
+};
+
+template <class T>
+struct M {
+ T t; // { dg-error "no match|strong_ordering" }
+ std::strong_ordering operator<=>(M const &) const = default;
+};
+
+// Test that we don't fall back to </== if <=> is ambiguous.
+struct N {
+ bool operator==(N const &) const;
+ bool operator<(N const &) const;
+};
+template <class T>
+std::partial_ordering operator<=>(N const &, T&&);
+template <class T>
+std::partial_ordering operator<=>(T&&, N const &);
+
+void
+foo (A &a1, A &a2, B &b1, B &b2, D& d1, D& d2, F& f1, F& f2, I& i1, I& i2)
+{
+ auto a = a1 < a2; // { dg-error "deleted" }
+ auto b = b1 < b2;
+ auto d = d1 < d2; // { dg-error "deleted" }
+ auto f = f1 < f2; // { dg-error "deleted" }
+ auto i = i1 < i2;
+
+ auto j1 = J<int>() < J<int>();
+ auto j2 = J<H>() < J<H>(); // { dg-error "deleted" }
+ auto j3 = J<C>() < J<C>(); // { dg-error "deleted" }
+ auto j4 = J<E>() < J<E>();
+ auto j5 = J<G>() < J<G>();
+ auto j6 = J<N>() < J<N>(); // { dg-error "deleted" }
+
+ auto k1 = K<int>() < K<int>();
+ auto k2 = K<H>() < K<H>();
+ auto k3 = K<C>() < K<C>(); // { dg-error "deleted" }
+ auto k4 = K<E>() < K<E>();
+ auto k5 = K<G>() < K<G>();
+ auto k6 = K<N>() < K<N>(); // { dg-error "deleted" }
+
+ auto m1 = M<int>() < M<int>();
+ auto m2 = M<H>() < M<H>();
+ auto m3 = M<C>() < M<C>(); // { dg-error "deleted" }
+ auto m4 = M<E>() < M<E>(); // { dg-error "deleted" }
+ auto m5 = M<G>() < M<G>();
+ auto m6 = M<N>() < M<N>(); // { dg-error "deleted" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C
index 486db6c..c6acb7b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C
@@ -14,9 +14,9 @@ bool operator<(const X<T>&, const X<T>&) { return true; }
struct Y
{
int a;
- X<int> c;
+ X<int> c; // { dg-error "no match" }
- auto operator <=>(Y const&) const = default; // { dg-error "no match" }
+ auto operator <=>(Y const&) const = default;
};
void f()
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg5.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg5.C
new file mode 100644
index 0000000..a01d3d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg5.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+#include <compare>
+
+struct C {
+ int y;
+ int x[]; // { dg-message "cannot default compare flexible array member" }
+ auto operator<=>(C const&) const = default; // { dg-message "is implicitly deleted because the default definition would be ill-formed" }
+};
+
+bool
+foo (C &c1, C &c2)
+{
+ return c1 > c2; // { dg-error "use of deleted function" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth10.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth10.C
new file mode 100644
index 0000000..235e002
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth10.C
@@ -0,0 +1,57 @@
+// { dg-do run { target c++20 } }
+// { dg-options "" }
+
+#include <compare>
+
+struct C {
+ int y;
+ int x[4];
+ auto operator<=>(C const&) const = default;
+};
+
+struct D {
+ int y;
+ int x[1];
+ auto operator<=>(D const&) const = default;
+};
+
+struct E {
+ int y;
+ int x[0];
+ auto operator<=>(E const&) const = default;
+};
+
+int
+main ()
+{
+ constexpr C c1 = { 1, { 2, 3, 4, 5 } };
+ constexpr C c2 = { 1, { 2, 3, 5, 4 } };
+ constexpr C c3 = { 1, { 2, 2, 6, 7 } };
+ static_assert (c1 < c2);
+ static_assert (c3 < c1);
+ constexpr D d1 = { 1, { 2 } };
+ constexpr D d2 = { 1, { 3 } };
+ constexpr D d3 = { 1, { 1 } };
+ static_assert (d1 < d2);
+ static_assert (d3 < d1);
+ constexpr E e1 = { 1, {} };
+ constexpr E e2 = { 2, {} };
+ constexpr E e3 = { 1, {} };
+ static_assert (e1 < e2);
+ static_assert (e1 == e3);
+ C c4 = { 1, { 2, 3, 4, 5 } };
+ C c5 = { 1, { 2, 3, 5, 4 } };
+ C c6 = { 1, { 2, 2, 6, 7 } };
+ if (c4 >= c5 || c6 >= c4)
+ __builtin_abort ();
+ D d4 = { 1, { 2 } };
+ D d5 = { 1, { 3 } };
+ D d6 = { 1, { 1 } };
+ if (d4 >= d5 || d6 >= d4)
+ __builtin_abort ();
+ E e4 = { 1, {} };
+ E e5 = { 2, {} };
+ E e6 = { 1, {} };
+ if (e4 >= e5 || e4 != e6)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc1.C b/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
index 6e19ff7..029a037 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
@@ -88,7 +88,7 @@ quux ()
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
- const char *function2 = __FUNCTION__;
+ const char *function2 = __PRETTY_FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc15.C b/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
new file mode 100644
index 0000000..d02617e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
@@ -0,0 +1,119 @@
+// { dg-do run { target c++20 } }
+
+namespace std {
+ struct source_location {
+ struct __impl {
+ const char *_M_file_name;
+ const char *_M_function_name;
+ unsigned int _M_line, _M_column;
+ };
+ const __impl *__ptr;
+ constexpr source_location () : __ptr (nullptr) {}
+ static consteval source_location
+ current (const void *__p = __builtin_source_location ()) {
+ source_location __ret;
+ __ret.__ptr = static_cast <const __impl *> (__p);
+ return __ret;
+ }
+ constexpr const char *file_name () const {
+ return __ptr ? __ptr->_M_file_name : "";
+ }
+ constexpr const char *function_name () const {
+ return __ptr ? __ptr->_M_function_name : "";
+ }
+ constexpr unsigned line () const {
+ return __ptr ? __ptr->_M_line : 0;
+ }
+ constexpr unsigned column () const {
+ return __ptr ? __ptr->_M_column : 0;
+ }
+ };
+}
+
+using namespace std;
+
+constexpr source_location
+foo (const source_location x = source_location::current ())
+{
+ return x;
+}
+
+struct S {
+ const char *func;
+ unsigned line = 0;
+ source_location loc = source_location::current ();
+
+ constexpr S (int l, source_location loc = source_location::current ())
+ : func(__PRETTY_FUNCTION__), line(l), loc(loc)
+ {}
+
+ constexpr S (double)
+ : func(__PRETTY_FUNCTION__), line(__LINE__)
+ // ^ column 45
+ {}
+};
+
+constexpr bool
+cmp (const char *p, const char *q)
+{
+ for (; *p && *q; p++, q++)
+ if (*p != *q)
+ return true;
+ return *p || *q;
+}
+
+constexpr bool
+bar ()
+{
+ int line = __LINE__;
+ source_location a = foo ();
+ source_location b = source_location::current ();
+ source_location c = foo ();
+ // ^ column 28
+ // ^ column 49
+ const source_location *d[3] = { &a, &b, &c };
+ const char *file1 = __FILE__;
+ const char *function1 = __PRETTY_FUNCTION__;
+ for (int j = 0; j < 3; j++)
+ {
+ int i= 0;
+ if (cmp (d[j]->file_name (), file1))
+ return false;
+ if (cmp (d[j]->function_name (), function1))
+ return false;
+ if (d[j]->line () != line + j + 1)
+ return false;
+ if (d[j]->column () != (j == 1 ? 49 : 28))
+ return false;
+ }
+
+ S e = __LINE__;
+ // ^ column 9
+ S f = 1.0;
+ if (cmp (e.loc.file_name (), file1))
+ return false;
+ if (cmp (f.loc.file_name (), file1))
+ return false;
+ if (cmp (e.loc.function_name (), function1))
+ return false;
+ if (cmp (f.loc.function_name (), f.func))
+ return false;
+ if (e.loc.line () != e.line)
+ return false;
+ if (f.loc.line () != f.line)
+ return false;
+ if (e.loc.column () != 9)
+ return false;
+ if (f.loc.column () != 45)
+ return false;
+ return true;
+}
+
+static_assert (bar ());
+
+int
+main ()
+{
+ if (!bar ())
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc16.C b/gcc/testsuite/g++.dg/cpp2a/srcloc16.C
new file mode 100644
index 0000000..c8bd281
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc16.C
@@ -0,0 +1,97 @@
+// { dg-do run { target c++20 } }
+
+namespace std {
+ struct source_location {
+ struct __impl {
+ const char *_M_file_name;
+ const char *_M_function_name;
+ unsigned int _M_line, _M_column;
+ };
+ const __impl *__ptr;
+ constexpr source_location () : __ptr (nullptr) {}
+ static consteval source_location
+ current (const void *__p = __builtin_source_location ()) {
+ source_location __ret;
+ __ret.__ptr = static_cast <const __impl *> (__p);
+ return __ret;
+ }
+ constexpr const char *file_name () const {
+ return __ptr ? __ptr->_M_file_name : "";
+ }
+ constexpr const char *function_name () const {
+ return __ptr ? __ptr->_M_function_name : "";
+ }
+ constexpr unsigned line () const {
+ return __ptr ? __ptr->_M_line : 0;
+ }
+ constexpr unsigned column () const {
+ return __ptr ? __ptr->_M_column : 0;
+ }
+ };
+}
+
+using namespace std;
+
+struct S
+{
+ source_location a = source_location::current ();
+ source_location b = source_location::current ();
+ source_location c = source_location ();
+ constexpr S () { c = source_location::current (); }
+};
+
+struct T
+{
+ int t;
+ source_location u = source_location::current ();
+ int v = __builtin_LINE ();
+};
+
+constexpr S s;
+constexpr T t = { 1 };
+
+constexpr bool
+cmp (const char *p, const char *q)
+{
+ for (; *p && *q; p++, q++)
+ if (*p != *q)
+ return true;
+ return *p || *q;
+}
+
+constexpr bool
+foo ()
+{
+ T u = { 2 };
+ source_location v = source_location::current ();
+ if (cmp (s.a.file_name (), s.c.file_name ())
+ || cmp (s.b.file_name (), s.c.file_name ())
+ || cmp (t.u.file_name (), s.c.file_name ())
+ || cmp (u.u.file_name (), s.c.file_name ())
+ || cmp (v.file_name (), s.c.file_name ())
+ || cmp (s.a.function_name (), s.c.function_name ())
+ || cmp (s.b.function_name (), s.c.function_name ())
+ || cmp (t.u.function_name (), "")
+ || cmp (u.u.function_name (), v.function_name ())
+ || s.a.line () != s.c.line ()
+ || s.b.line () != s.c.line ()
+ || t.u.line () != t.v
+ || u.u.line () + 1 != v.line ()
+ || s.a.column () != 18
+ || s.b.column () != 18
+ || s.c.column () != 50
+ || t.u.column () != 21
+ || u.u.column () != 13
+ || v.column () != 49)
+ return false;
+ return true;
+}
+
+static_assert (foo ());
+
+int
+main ()
+{
+ if (!foo ())
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc17.C b/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
new file mode 100644
index 0000000..a02ea48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
@@ -0,0 +1,122 @@
+// { dg-do run { target c++20 } }
+
+namespace std {
+ struct source_location {
+ struct __impl {
+ const char *_M_file_name;
+ const char *_M_function_name;
+ unsigned int _M_line, _M_column;
+ };
+ const __impl *__ptr;
+ constexpr source_location () : __ptr (nullptr) {}
+ static consteval source_location
+ current (const void *__p = __builtin_source_location ()) {
+ source_location __ret;
+ __ret.__ptr = static_cast <const __impl *> (__p);
+ return __ret;
+ }
+ constexpr const char *file_name () const {
+ return __ptr ? __ptr->_M_file_name : "";
+ }
+ constexpr const char *function_name () const {
+ return __ptr ? __ptr->_M_function_name : "";
+ }
+ constexpr unsigned line () const {
+ return __ptr ? __ptr->_M_line : 0;
+ }
+ constexpr unsigned column () const {
+ return __ptr ? __ptr->_M_column : 0;
+ }
+ };
+}
+
+using namespace std;
+
+template <int N>
+constexpr source_location
+foo (const source_location x = source_location::current ())
+{
+ return x;
+}
+
+template <int N>
+struct S {
+ const char *func;
+ unsigned line = 0;
+ source_location loc = source_location::current ();
+
+ constexpr S (int l, source_location loc = source_location::current ())
+ : func(__PRETTY_FUNCTION__), line(l), loc(loc)
+ {}
+
+ constexpr S (double)
+ : func(__PRETTY_FUNCTION__), line(__LINE__)
+ // ^ column 45
+ {}
+};
+
+constexpr bool
+cmp (const char *p, const char *q)
+{
+ for (; *p && *q; p++, q++)
+ if (*p != *q)
+ return true;
+ return *p || *q;
+}
+
+template <int N>
+constexpr bool
+bar ()
+{
+ int line = __LINE__;
+ source_location a = foo<N> ();
+ source_location b = source_location::current ();
+ source_location c = foo<N> ();
+ // ^ column 30
+ // ^ column 48
+ const source_location *d[3] = { &a, &b, &c };
+ const char *file1 = __FILE__;
+ const char *function1 = __PRETTY_FUNCTION__;
+ for (int j = 0; j < 3; j++)
+ {
+ int i= 0;
+ if (cmp (d[j]->file_name (), file1))
+ return false;
+ if (cmp (d[j]->function_name (), function1))
+ return false;
+ if (d[j]->line () != line + j + 1)
+ return false;
+ if (d[j]->column () != (j == 1 ? 48 : 30))
+ return false;
+ }
+
+ S<N> e = __LINE__;
+ // ^ column 8
+ S<N> f = 1.0;
+ if (cmp (e.loc.file_name (), file1))
+ return false;
+ if (cmp (f.loc.file_name (), file1))
+ return false;
+ if (cmp (e.loc.function_name (), function1))
+ return false;
+ if (cmp (f.loc.function_name (), f.func))
+ return false;
+ if (e.loc.line () != e.line)
+ return false;
+ if (f.loc.line () != f.line)
+ return false;
+ if (e.loc.column () != 8)
+ return false;
+ if (f.loc.column () != 45)
+ return false;
+ return true;
+}
+
+static_assert (bar<0> ());
+
+int
+main ()
+{
+ if (!bar<0> ())
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc18.C b/gcc/testsuite/g++.dg/cpp2a/srcloc18.C
new file mode 100644
index 0000000..7e685ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc18.C
@@ -0,0 +1,100 @@
+// { dg-do run { target c++20 } }
+
+namespace std {
+ struct source_location {
+ struct __impl {
+ const char *_M_file_name;
+ const char *_M_function_name;
+ unsigned int _M_line, _M_column;
+ };
+ const __impl *__ptr;
+ constexpr source_location () : __ptr (nullptr) {}
+ static consteval source_location
+ current (const void *__p = __builtin_source_location ()) {
+ source_location __ret;
+ __ret.__ptr = static_cast <const __impl *> (__p);
+ return __ret;
+ }
+ constexpr const char *file_name () const {
+ return __ptr ? __ptr->_M_file_name : "";
+ }
+ constexpr const char *function_name () const {
+ return __ptr ? __ptr->_M_function_name : "";
+ }
+ constexpr unsigned line () const {
+ return __ptr ? __ptr->_M_line : 0;
+ }
+ constexpr unsigned column () const {
+ return __ptr ? __ptr->_M_column : 0;
+ }
+ };
+}
+
+using namespace std;
+
+template <int N>
+struct S
+{
+ source_location a = source_location::current ();
+ source_location b = source_location::current ();
+ source_location c = source_location ();
+ constexpr S () { c = source_location::current (); }
+};
+
+template <int N>
+struct T
+{
+ int t;
+ source_location u = source_location::current ();
+ int v = __builtin_LINE ();
+};
+
+constexpr S<0> s;
+constexpr T<0> t = { 1 };
+
+constexpr bool
+cmp (const char *p, const char *q)
+{
+ for (; *p && *q; p++, q++)
+ if (*p != *q)
+ return true;
+ return *p || *q;
+}
+
+template <int N>
+constexpr bool
+foo ()
+{
+ T<N> u = { 2 };
+ source_location v = source_location::current ();
+ if (cmp (s.a.file_name (), s.c.file_name ())
+ || cmp (s.b.file_name (), s.c.file_name ())
+ || cmp (t.u.file_name (), s.c.file_name ())
+ || cmp (u.u.file_name (), s.c.file_name ())
+ || cmp (v.file_name (), s.c.file_name ())
+ || cmp (s.a.function_name (), s.c.function_name ())
+ || cmp (s.b.function_name (), s.c.function_name ())
+ || cmp (t.u.function_name (), "")
+ || cmp (u.u.function_name (), v.function_name ())
+ || s.a.line () != s.c.line ()
+ || s.b.line () != s.c.line ()
+ || t.u.line () != t.v
+ || u.u.line () + 1 != v.line ()
+ || s.a.column () != 18
+ || s.b.column () != 18
+ || s.c.column () != 49
+ || t.u.column () != 24
+ || u.u.column () != 8
+ || v.column () != 48)
+ return false;
+ return true;
+}
+
+static_assert (foo<1> ());
+
+int
+main ()
+{
+ if (!foo<1> ())
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc2.C b/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
index 5ef09bb..4e0b960 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
@@ -92,7 +92,7 @@ quux ()
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
- const char *function2 = __FUNCTION__;
+ const char *function2 = __PRETTY_FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-1.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-1.C
new file mode 100644
index 0000000..fd34ca8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-1.C
@@ -0,0 +1,62 @@
+// Test of using an enumerator.
+// { dg-do compile { target c++2a } }
+
+// using ENUM::V;
+enum class E {v};
+
+using E::v;
+using E::v; // OK
+
+E a = v;
+
+class C
+{
+ using E::v; // { dg-message "declared private here" }
+
+ static inline const E m = v;
+};
+
+E b = C::v; // { dg-error "private" }
+
+struct B
+{
+ enum E {e};
+ enum class EC {f};
+ using EC::f;
+};
+
+struct D
+{
+private:
+ using B::e; // { dg-message "declared private here" }
+ using B::f; // { dg-message "declared private here" }
+};
+
+struct F : D
+{
+ static inline const auto bad1 = e; // { dg-error "private" }
+ static inline const auto bad2 = f; // { dg-error "private" }
+
+ static inline const auto ok1 = B::e;
+ static inline const auto ok2 = B::f;
+ static inline const auto also_ok1 = B::E::e;
+ static inline const auto also_ok2 = B::EC::f;
+};
+
+using B::e;
+auto bob = e;
+
+struct Q
+{
+ using B::e;
+};
+using Q::e; // OK
+
+using D::e; // { dg-error "private" }
+
+template <class T>
+struct X : T
+{
+ using T::e;
+};
+auto fob = X<Q>::e;
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-2.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-2.C
new file mode 100644
index 0000000..66b37f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-2.C
@@ -0,0 +1,48 @@
+// Test of 'using enum' in different scopes.
+// { dg-do compile { target c++20 } }
+
+namespace N
+{
+ enum class E { e, f };
+}
+
+int main()
+{
+ using enum N::E;
+ static_assert (e < f);
+}
+
+struct A
+{
+ using enum N::E;
+ static_assert (e < f);
+};
+
+namespace M
+{
+ using enum N::E;
+ static_assert (e < f);
+
+ enum class X: int; // { dg-message "opaque" }
+ using enum X; // { dg-error "enum-specifier" }
+}
+
+template <class T>
+void f()
+{
+ using enum N::E;
+ static_assert (e < f);
+}
+
+template <class T>
+struct AT
+{
+ using enum N::E;
+ static_assert (e < f);
+};
+
+template <class T>
+struct BT
+{
+ using enum T::E; // { dg-error "dependent" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-3.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-3.C
new file mode 100644
index 0000000..d09bd6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-3.C
@@ -0,0 +1,6 @@
+// Test of 'using enum' syntax error recovery.
+// { dg-do compile { target c++20 } }
+
+using enum 2 + garbage3'850%^&; // { dg-error "" }
+
+void f() {}
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-4.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-4.C
new file mode 100644
index 0000000..03432cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-4.C
@@ -0,0 +1,13 @@
+// Test for suggestion to try 'using enum'.
+// { dg-do compile { target c++20 } }
+
+struct A
+{
+ enum E { e };
+};
+
+struct B
+{
+ using A::E; // { dg-error "" }
+ // { dg-message "using enum" "" { target *-*-* } .-1 }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-5.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-5.C
new file mode 100644
index 0000000..e5fe820
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-5.C
@@ -0,0 +1,132 @@
+// Examples from P1099R5
+// { dg-do compile { target c++20 } }
+
+namespace my_lib {
+
+ enum class errcode
+ {
+ SUCCESS = 0,
+ ENOMEM = 1,
+ EAGAIN = 2,
+ ETOOSLOW = 3
+ };
+ using enum errcode; // import enumerators into namespace
+}
+
+namespace NS {
+ my_lib::errcode get_widget() {
+ using namespace my_lib;
+ return ETOOSLOW; // works, and conversions to int don't.
+ int i = ETOOSLOW; // { dg-error "" }
+ }
+}
+
+enum class rgba_color_channel { red, green, blue, alpha};
+
+const char * to_string(rgba_color_channel channel) {
+ switch (channel) {
+ using enum rgba_color_channel;
+ case red: return "red";
+ case green: return "green";
+ case blue: return "blue";
+ case alpha: return "alpha";
+ }
+ return nullptr;
+}
+
+namespace ns {
+ struct E_detail {
+ enum E { e1, e2 };
+ friend void swap(E&, E&); // adl-only swap in the only associated scope of the enum
+ };
+ using E = E_detail::E; // import E into ns
+ using enum E; // expose the enumerators of E in ns. Also note the direct reference to E.
+}
+
+int main() {
+ auto x = ns::e1;
+ auto y = ns::e2;
+ swap(x, y); // finds the swap in the associated struct
+}
+
+namespace N0 {
+ enum E { x };
+ struct S {
+ enum H { y };
+ enum class K { z };
+ using E::x; // OK, introduces x into S
+ using E::x; // { dg-error "" } redeclaration in class scope
+ using H::y; // { dg-error "" } redeclaration in class scope
+ using K::z; // OK, introduces z into S
+ };
+ namespace NS {
+ enum H { y };
+ enum class K { z };
+ using E::x; // OK, introduces x into NS
+ using E::x; // OK, just a redeclaration of the same entity
+ using H::y; // OK, redeclaration of the same entity
+ using K::z; // OK, introduces z into NS
+ };
+}
+namespace N1 {
+ struct S {
+ enum E { x };
+ enum class EC { y };
+ using EC::y;
+ };
+
+ void f() {
+ using S::x; // OK
+ x; // resolves to S::E::x;
+ using S::y; // OK
+ y; // resolves to S::EC::y;
+ }
+}
+
+namespace N2 {
+ enum class E { a, b, c };
+ using E::a, E::b, E::c; // OK, imports all three
+ auto x = (a,b,c);
+}
+
+namespace N3 {
+ struct B {
+ enum class E { x };
+ };
+ enum class H { y };
+ struct C : B {
+ using enum B::E; // OK, introduces E::x into C
+ using enum H; // OK, introduces y into C. Does not introduce H
+ };
+ auto i = C::y; // OK
+ C::H h; // { dg-error "" }
+}
+
+namespace N4 {
+ enum class button { up, down };
+ struct S {
+ using button::up;
+ button b = up; // OK
+ };
+}
+
+namespace N5 {
+ enum class fruit { orange, apple };
+ struct S {
+ using enum fruit; // OK, introduces orange and apple into S
+ };
+ void f() {
+ S s;
+ s.orange; // OK, names fruit::orange
+ S::orange; // OK, names fruit::orange
+ }
+}
+
+namespace N6 {
+ enum class fruit { orange, apple };
+ enum class color { red, orange };
+ void f() {
+ using enum fruit; // OK
+ using enum color; // { dg-error "" } color::orange and fruit::orange conflict
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-6.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-6.C
new file mode 100644
index 0000000..732cdfd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-6.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++2a } }
+
+using enum void; // { dg-error "non-enum" }
+struct A {}; // { dg-message "declared here" }
+using enum A; // { dg-error "non-enum" }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C
new file mode 100644
index 0000000..460294c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++17 -gdwarf-5 -dA" }
+// For -gdwarf-6 hopefully DW_LANG_C_plus_plus_17
+// DW_LANG_C_plus_plus_14 = 0x0021
+// { dg-final { scan-assembler "0x21\[^\n\r]* DW_AT_language" } } */
+
+int version;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C
new file mode 100644
index 0000000..abd7351
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++20 -gdwarf-5 -dA" }
+// For -gdwarf-6 hopefully DW_LANG_C_plus_plus_20
+// DW_LANG_C_plus_plus_14 = 0x0021
+// { dg-final { scan-assembler "0x21\[^\n\r]* DW_AT_language" } } */
+
+int version;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/using-enum.C b/gcc/testsuite/g++.dg/debug/dwarf2/using-enum.C
new file mode 100644
index 0000000..7663a13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/using-enum.C
@@ -0,0 +1,21 @@
+// Test of 'using enum' debug info.
+// { dg-do compile { target c++20 } }
+// { dg-options "-g -dA" }
+
+struct A
+{
+ // All the counts are +1 for the abbreviation table.
+ // { dg-final { scan-assembler-times "DW_TAG_enumeration_type" 2 } }
+ // { dg-final { scan-assembler-times "DW_TAG_enumerator" 3 } }
+ enum E { e, f };
+};
+
+struct B
+{
+ // The using-enum-declaration is represented by two
+ // DW_TAG_imported_declaration, one for each enumerator.
+ // { dg-final { scan-assembler-times "DW_TAG_imported_declaration" 3 } }
+ using enum A::E;
+};
+
+B b;
diff --git a/gcc/testsuite/g++.dg/debug/localclass2.C b/gcc/testsuite/g++.dg/debug/localclass2.C
new file mode 100644
index 0000000..9897eec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/localclass2.C
@@ -0,0 +1,24 @@
+// PR c++/97918
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target lto }
+// { dg-additional-options "-g -O -flto" }
+
+namespace { class A {}; }
+class B {};
+template <typename T> struct H {
+ constexpr static unsigned h = 0;
+};
+
+template <typename T> A bar ()
+{
+ struct J {
+ static void foo();
+ };
+ H<J>();
+ return A ();
+}
+
+void fn ()
+{
+ bar<B>; // only mentions the function
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/nullptr.C b/gcc/testsuite/g++.dg/diagnostic/nullptr.C
new file mode 100644
index 0000000..bc0d829
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/nullptr.C
@@ -0,0 +1,8 @@
+// PR c++/97517
+// { dg-do compile { target c++20 } }
+// Test that we print "decltype(nullptr)" correctly.
+
+template<typename T> struct Trait { static constexpr bool value = false; };
+template<typename T> concept Concept = Trait<T>::value; // { dg-message {\[with T = std::nullptr_t\]} }
+static_assert( Concept<decltype(nullptr)> ); // { dg-error "static assertion failed" }
+// { dg-message "constraints not satisfied" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr87386.C b/gcc/testsuite/g++.dg/diagnostic/pr87386.C
index 85726af..679a517 100644
--- a/gcc/testsuite/g++.dg/diagnostic/pr87386.C
+++ b/gcc/testsuite/g++.dg/diagnostic/pr87386.C
@@ -14,5 +14,5 @@ static_assert (foo::test<int>::value, "foo"); // { dg-error "static assertion f
static_assert (foo::test<int>::value && true, "bar"); // { dg-error "static assertion failed: bar" }
/* { dg-begin-multiline-output "" }
static_assert (foo::test<int>::value && true, "bar");
- ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
+ ~~~~~~~~~~~~~~~~^~~~~
{ dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr96045-1.C b/gcc/testsuite/g++.dg/diagnostic/pr96045-1.C
new file mode 100644
index 0000000..b84a5d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr96045-1.C
@@ -0,0 +1,4 @@
+// PR 96045 EOF location
+
+template <class> class A {};
+struct A <int> // { dg-error "15:" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr96045-2.C b/gcc/testsuite/g++.dg/diagnostic/pr96045-2.C
new file mode 100644
index 0000000..1009ad0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr96045-2.C
@@ -0,0 +1,6 @@
+// PR 96045 EOF location
+
+template <class> class A {};
+struct A <int> // { dg-error "15:" }
+/* A comment */
+
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr96045-3.C b/gcc/testsuite/g++.dg/diagnostic/pr96045-3.C
new file mode 100644
index 0000000..ad1f2a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr96045-3.C
@@ -0,0 +1,6 @@
+// PR 96045 EOF location
+
+#define BORKED <int> // { dg-error "20:" }
+
+template <class> class A {};
+struct A BORKED // { dg-message "10: in expansion of" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/static_assert1.C b/gcc/testsuite/g++.dg/diagnostic/static_assert1.C
new file mode 100644
index 0000000..fecf3cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/static_assert1.C
@@ -0,0 +1,30 @@
+// PR c++/97518
+// { dg-do compile { target c++17 } }
+
+template <typename T, typename U> struct is_same { static constexpr bool value = false; };
+template <typename T> struct is_same<T, T> { static constexpr bool value = true; };
+
+template <typename T> using some_metafunction_t = T;
+
+template <typename T>
+void foo(T ) {
+ using X = T*;
+ using Y = some_metafunction_t<T>;
+
+ static_assert(is_same<X, Y>::value); // { dg-error "static assertion failed" }
+ // { dg-message {.is_same<int\*, int>::value. evaluates to false} "" { target *-*-* } .-1 }
+ static_assert(is_same<X, Y>::value, "foo"); // { dg-error "static assertion failed: foo" }
+ // { dg-message {.is_same<int\*, int>::value. evaluates to false} "" { target *-*-* } .-1 }
+ static_assert(is_same<X, X>::value && is_same<X, Y>::value); // { dg-error "static assertion failed" }
+ // { dg-message {.is_same<int\*, int>::value. evaluates to false} "" { target *-*-* } .-1 }
+ static_assert(is_same<X, Y>::value && is_same<X, X>::value); // { dg-error "static assertion failed" }
+ // { dg-message {.is_same<int\*, int>::value. evaluates to false} "" { target *-*-* } .-1 }
+ static_assert(is_same<X, X>::value
+ && is_same<Y, Y>::value
+ && is_same<X, Y>::value); // { dg-error "static assertion failed" }
+ // { dg-message {.is_same<int\*, int>::value. evaluates to false} "" { target *-*-* } .-1 }
+}
+
+void bar() {
+ foo(0);
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/static_assert2.C b/gcc/testsuite/g++.dg/diagnostic/static_assert2.C
new file mode 100644
index 0000000..542697f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/static_assert2.C
@@ -0,0 +1,68 @@
+// PR c++/97518
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+constexpr bool yes () { return true; }
+constexpr bool no () { return false; }
+constexpr bool yay = true;
+constexpr bool nay = false;
+
+void
+bar ()
+{
+ static_assert (true && true && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (true && true && no(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert (yay && nay, ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (yay && nay, "");
+ ^~~
+ { dg-end-multiline-output "" } */
+ static_assert (yes() && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (yes() && no(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert (no() && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (no() && yes(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert (no() && no() && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (no() && no() && yes(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert (yes() && yes() && yes () && no() && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (yes() && yes() && yes () && no() && yes(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert (yes() && yes() && yes () && (no() && yes()), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert (yes() && yes() && yes () && (no() && yes()), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert ((yes() && no()) && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert ((yes() && no()) && no(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert ((yes() && no()) && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert ((yes() && no()) && no(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+ static_assert ((no() || no()) && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert ((no() || no()) && yes(), "");
+ ~~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+ static_assert ((yes() || no()) && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert ((yes() || no()) && no(), "");
+ ~~^~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/static_assert3.C b/gcc/testsuite/g++.dg/diagnostic/static_assert3.C
new file mode 100644
index 0000000..5d36388
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/static_assert3.C
@@ -0,0 +1,36 @@
+// PR c++/97518
+// { dg-do compile { target c++17 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+template <typename T, typename U> struct is_same { static constexpr bool value = false; };
+template <typename T> struct is_same<T, T> { static constexpr bool value = true; };
+
+template <typename T, typename U>
+void f(T, U)
+{
+ static_assert(is_same<T, T>::value && is_same<T, U>::value); // { dg-error "56:static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert(is_same<T, T>::value && is_same<T, U>::value);
+ ^~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message ".is_same<int, double>::value. evaluates to false" "" { target *-*-* } .-5 }
+ static_assert(is_same<U, T>::value && is_same<U, U>::value); // { dg-error "32:static assertion failed" }
+/* { dg-begin-multiline-output "" }
+ static_assert(is_same<U, T>::value && is_same<U, U>::value);
+ ^~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message ".is_same<double, int>::value. evaluates to false" "" { target *-*-* } .-5 }
+ static_assert(is_same<U, U>::value
+ && is_same<U, T>::value // { dg-error "35:static assertion failed" }
+ && is_same<T, T>::value);
+/* { dg-begin-multiline-output "" }
+ && is_same<U, T>::value
+ ^~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message ".is_same<double, int>::value. evaluates to false" "" { target *-*-* } .-6 }
+}
+
+void g()
+{
+ f(0, 1.3);
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
index f905e4f..4dad8a2 100644
--- a/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
@@ -10,4 +10,4 @@ void bar (void);
void test (void);
// { message "12: to match this '.'" "" { target *-*-* } open_extern_c }
-/* { dg-error "-:expected '.' at end of input" "" { target *-*-* } .+1 } */
+/* { dg-error "18:expected '.' at end of input" "" { target *-*-* } .-2 } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C
index 4d841d5..ff94bc7 100644
--- a/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-function.C
@@ -1,4 +1,3 @@
void test (void)
{ /* { dg-message "1: to match this '.'" } */
- int filler;
- /* { dg-error "-:expected '.' at end of input" "" { target *-*-* } .+1 } */
+ int filler; /* { dg-error "14:expected '.' at end of input" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C
index 0887bc1..fc3fc08 100644
--- a/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-namespace.C
@@ -1,3 +1,2 @@
namespace unclosed { /* { dg-message "20: to match this '.'" } */
-int filler;
-/* { dg-error "-:expected '.' at end of input" "" { target *-*-* } .+1 } */
+int filler; /* { dg-error "12:expected '.' at end of input" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C b/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C
index e68e599..e3faaae 100644
--- a/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C
+++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-struct.C
@@ -1,3 +1,2 @@
struct unclosed { /* { dg-message "17: to match this '.'" } */
- int dummy;
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
+ int dummy; // { dg-error "13:expected" }
diff --git a/gcc/testsuite/g++.dg/eh/crash2.C b/gcc/testsuite/g++.dg/eh/crash2.C
new file mode 100644
index 0000000..fff8e14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/crash2.C
@@ -0,0 +1,20 @@
+// PR c++/97187
+// { dg-do compile { target c++14 } }
+// { dg-options "-fno-exceptions" }
+
+auto yp = [] { return 0; };
+
+template <class DI>
+DI
+zl ()
+{
+ auto au = [] () -> DI { return *new auto (true ? yp : throw); }; // { dg-error "exception handling disabled" }
+
+ return au ();
+}
+
+auto
+vd ()
+{
+ return zl <decltype (yp)> ();
+}
diff --git a/gcc/testsuite/g++.dg/eh/pr42859.C b/gcc/testsuite/g++.dg/eh/pr42859.C
index a9f1473..0de9140 100644
--- a/gcc/testsuite/g++.dg/eh/pr42859.C
+++ b/gcc/testsuite/g++.dg/eh/pr42859.C
@@ -13,7 +13,7 @@ ptw32_terminate (void)
catch (int)
{
}
- catch (int)
+ catch (int) // { dg-warning "will be caught by earlier handler" }
{
}
}
diff --git a/gcc/testsuite/g++.dg/expr/anew5.C b/gcc/testsuite/g++.dg/expr/anew5.C
new file mode 100644
index 0000000..d597caf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/anew5.C
@@ -0,0 +1,26 @@
+// PR c++/97523
+// { dg-do compile }
+// We were turning the () into {} which made it seem like
+// aggregate-initialization (we are dealing with arrays here), which
+// performs copy-initialization, which only accepts converting constructors.
+
+struct T {
+ explicit T();
+ T(int);
+};
+
+void
+fn (int n)
+{
+ new T[1]();
+ new T[2]();
+ new T[3]();
+ new T[n]();
+#if __cpp_aggregate_paren_init
+ new T[]();
+ new T[2](1, 2);
+ // T[2] is initialized via copy-initialization, so we can't call
+ // explicit T().
+ new T[3](1, 2); // { dg-error "explicit constructor" "" { target c++20 } }
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/expr/anew6.C b/gcc/testsuite/g++.dg/expr/anew6.C
new file mode 100644
index 0000000..0542daa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/anew6.C
@@ -0,0 +1,33 @@
+// PR c++/97523
+// { dg-do compile { target c++11 } }
+
+// [expr.new]/24: If the new-expression creates an object or an array of
+// objects of class type, access and ambiguity control are done for the
+// [...] constructor selected for the initialization (if any).
+// NB: We only check for a default constructor if the array has a non-constant
+// bound, or there are insufficient initializers. Since an array is an
+// aggregate, we perform aggregate-initialization, which performs
+// copy-initialization, so we only accept converting constructors.
+
+struct T {
+ explicit T();
+ T(int);
+};
+
+struct S {
+ S(int);
+};
+
+void
+fn (int n)
+{
+ new T[1]{}; // { dg-error "explicit constructor" }
+ new T[2]{1, 2};
+ new T[3]{1, 2}; // { dg-error "explicit constructor" }
+ new T[n]{}; // { dg-error "explicit constructor" }
+
+ new S[1]{}; // { dg-error "could not convert" }
+ new S[2]{1, 2};
+ new S[3]{1, 2}; // { dg-error "could not convert" }
+ new S[n]{}; // { dg-error "could not convert" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-used-2.C b/gcc/testsuite/g++.dg/ext/attr-used-2.C
new file mode 100644
index 0000000..d7cf6e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-used-2.C
@@ -0,0 +1,15 @@
+// PR c++/67453
+// { dg-do compile }
+// { dg-final { scan-assembler "_ZN1SC\[12]Ev" } }
+// { dg-final { scan-assembler "_ZN1SD\[12]Ev" } }
+// { dg-final { scan-assembler "_ZN1SC\[12]ERKS_" } }
+
+struct S {
+ S();
+ ~S();
+ S(const S&);
+};
+
+__attribute__((used)) inline S::S() { }
+__attribute__((used)) inline S::~S() { }
+__attribute__((used)) inline S::S(const S&) { }
diff --git a/gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C b/gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C
new file mode 100644
index 0000000..d188186
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C
@@ -0,0 +1,15 @@
+// PR middle-end/97943
+// { dg-do compile }
+// { dg-options "" }
+
+struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); }; // { dg-error "flexible array member 'S::b' not at end of 'struct \[TV]'" }
+struct T { int a; struct S b; int c; }; // { dg-message "next member 'int T::c' declared here|in the definition of 'struct T'" }
+union U { int a; struct S b; };
+struct V { int a; union U b; int : 15; int c; }; // { dg-message "next member 'int V::c' declared here|in the definition of 'struct V'" }
+
+void
+foo (struct T *t, struct V *v)
+{
+ __builtin_clear_padding (t); // { dg-error "flexible array member 'S::b' does not have well defined padding bits for '__builtin_clear_padding'" }
+ __builtin_clear_padding (v); // { dg-error "flexible array member 'S::b' does not have well defined padding bits for '__builtin_clear_padding'" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible1.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible1.C
new file mode 100644
index 0000000..472acf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible1.C
@@ -0,0 +1,48 @@
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B { B(); operator int(); };
+struct C {
+ C() = default;
+ C(const C&);
+ C(C&&) = default;
+ C& operator=(C&&);
+ C& operator= (const C&) = default;
+};
+struct D { ~D() noexcept(false) {} };
+
+#define SA(X) static_assert((X),#X)
+
+SA(__is_nothrow_constructible(A));
+SA(__is_nothrow_constructible(A,A));
+SA(!__is_nothrow_constructible(B));
+SA(__is_nothrow_constructible(B,B));
+
+SA(!__is_nothrow_constructible(A,B));
+SA(!__is_nothrow_constructible(B,A));
+
+SA(__is_nothrow_constructible(C));
+SA(__is_nothrow_constructible(C,C));
+SA(!__is_nothrow_constructible(C,C&));
+SA(__is_nothrow_assignable(C,C&));
+SA(!__is_nothrow_assignable(C,C));
+SA(!__is_nothrow_assignable(C,C&&));
+SA(!__is_nothrow_assignable(void,int));
+SA(!__is_nothrow_assignable(const void,int));
+SA(!__is_nothrow_assignable(volatile void,int));
+SA(!__is_nothrow_assignable(const volatile void,int));
+
+SA(__is_nothrow_constructible(int,int));
+SA(__is_nothrow_constructible(int,double));
+SA(!__is_nothrow_constructible(int,B));
+SA(!__is_nothrow_constructible(void,int));
+SA(!__is_nothrow_constructible(const void,int));
+SA(!__is_nothrow_constructible(volatile void,int));
+SA(!__is_nothrow_constructible(const volatile void,int));
+SA(!__is_nothrow_constructible(int, void*));
+SA(!__is_nothrow_constructible(int, int*));
+SA(!__is_nothrow_constructible(int, const int*));
+SA(!__is_nothrow_constructible(int*, void*));
+SA(!__is_nothrow_constructible(int*, const int*));
+
+SA(!__is_nothrow_constructible(D));
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible2.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible2.C
new file mode 100644
index 0000000..86b9668
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible2.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct X {
+ X() = default;
+ template<class... U> X(U...) noexcept;
+};
+
+struct Y {
+ template<class... U> Y(U...);
+};
+
+#define SA(X) static_assert((X),#X)
+
+SA(__is_nothrow_constructible(X));
+SA(!__is_nothrow_constructible(Y));
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible3.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible3.C
new file mode 100644
index 0000000..220ee0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible3.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+
+template <class T, class... Args> void bar() {
+ static_assert(__is_nothrow_constructible(T, Args...), "");
+}
+
+template void bar<int>();
+template void bar<int,int>();
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible4.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible4.C
new file mode 100644
index 0000000..9448c2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible4.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+void f()
+{
+ int x;
+ auto l = [=]{ return x; };
+ typedef decltype(l) C;
+ SA(__is_nothrow_constructible(C,C));
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible5.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible5.C
new file mode 100644
index 0000000..b847113
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible5.C
@@ -0,0 +1,12 @@
+// PR c++/80991
+// { dg-do compile { target c++11 } }
+
+template<bool> void foo()
+{
+ static_assert(__is_nothrow_constructible(int, int), "");
+}
+
+void bar()
+{
+ foo<true>();
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_constructible6.C b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible6.C
new file mode 100644
index 0000000..bdfdfb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_constructible6.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// PR c++/81589
+
+template <typename k>
+struct z {
+ z() noexcept {
+ k::error;
+ }
+};
+
+int x = __is_nothrow_constructible(z<int>);
diff --git a/gcc/testsuite/g++.dg/ext/pr84598.C b/gcc/testsuite/g++.dg/ext/pr84598.C
index 8b78e0f..1dd09f9 100644
--- a/gcc/testsuite/g++.dg/ext/pr84598.C
+++ b/gcc/testsuite/g++.dg/ext/pr84598.C
@@ -1,4 +1,4 @@
// { dg-options "-fpermissive -w" }
-template<int b> __attribute__ a([] { class c, __attribute__(vector_size(operator+()))) d; // { dg-error "" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+template<int b> __attribute__ a([] { class c, __attribute__(vector_size(operator+()))) d; // { dg-error "before" }
+// { dg-error "90:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/ext/sve-sizeless-1.C b/gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
index 7f82922..9f05ca5 100644
--- a/gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
+++ b/gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
@@ -72,10 +72,37 @@ template class templated_struct4<svint8_t>;
template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
template class templated_struct5<svint8_t>;
+template<typename T, unsigned N> struct templated_struct6 { T x[N]; }; // { dg-error {array elements cannot have SVE type '(__SVInt8_t|svint8_t)'} }
+template class templated_struct6<svint8_t, 2>;
+
+template<typename T>
+struct templated_struct7 {
+ static const int size = sizeof (T); // { dg-error {SVE type '(__SVInt8_t|svint8_t)' does not have a fixed size} }
+#if __cplusplus >= 201103L
+ static const int align = alignof (T); // { dg-error {SVE type '(__SVInt8_t|svint8_t)' does not have a defined alignment} "" { target c++11 } }
+#endif
+
+ void f1 (T (&)[2]); // { dg-error {array elements cannot have SVE type '(__SVInt8_t|svint8_t)'} }
+#if __cplusplus >= 201103L
+ auto f2 () -> decltype (new T); // { dg-error {cannot allocate objects with SVE type '(__SVInt8_t|svint8_t)'} "" { target c++11 } }
+ auto f3 (T *a) -> decltype (delete a); // { dg-error {cannot delete objects with SVE type '(__SVInt8_t|svint8_t)'} "" { target c++11 } }
+#else
+ void f2 () throw (T); // { dg-error {cannot throw or catch SVE type '(__SVInt8_t|svint8_t)'} "" { target c++98_only } }
+#endif
+};
+template class templated_struct7<svint8_t>;
+
+template<typename T> struct templated_struct8 { typedef int type; };
+
+template<typename T>
+void sfinae_f1 (typename templated_struct8<T[2]>::type);
+template<typename T>
+void sfinae_f1 (T &);
+
#if __cplusplus >= 201103L
template<int N> using typedef_sizeless1 = svint8_t;
template<int N> using typedef_sizeless1 = svint8_t;
-template<typename T> using array = T[2];
+template<typename T> using array = T[2]; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
#endif
// Pointers to sizeless types.
@@ -119,7 +146,7 @@ statements (int n)
__alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
#if __cplusplus >= 201103L
- array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
+ array<svint8_t> foo = {}; // { dg-message {required from here} "" { target c++11 } }
#endif
// Initialization.
@@ -298,6 +325,8 @@ statements (int n)
thrower2 ();
#endif
+ sfinae_f1<svint8_t> (sve_sc1);
+
// Use in traits. Doesn't use static_assert so that tests work with
// earlier -std=s.
diff --git a/gcc/testsuite/g++.dg/ext/sve-sizeless-2.C b/gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
index 40b65d3..0b86d9e 100644
--- a/gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
+++ b/gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
@@ -72,10 +72,37 @@ template class templated_struct4<svint8_t>;
template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
template class templated_struct5<svint8_t>;
+template<typename T, unsigned N> struct templated_struct6 { T x[N]; }; // { dg-error {array elements cannot have SVE type '(__SVInt8_t|svint8_t)'} }
+template class templated_struct6<svint8_t, 2>;
+
+template<typename T>
+struct templated_struct7 {
+ static const int size = sizeof (T); // { dg-error {SVE type '(__SVInt8_t|svint8_t)' does not have a fixed size} }
+#if __cplusplus >= 201103L
+ static const int align = alignof (T); // { dg-error {SVE type '(__SVInt8_t|svint8_t)' does not have a defined alignment} "" { target c++11 } }
+#endif
+
+ void f1 (T (&)[2]); // { dg-error {array elements cannot have SVE type '(__SVInt8_t|svint8_t)'} }
+#if __cplusplus >= 201103L
+ auto f2 () -> decltype (new T); // { dg-error {cannot allocate objects with SVE type '(__SVInt8_t|svint8_t)'} "" { target c++11 } }
+ auto f3 (T *a) -> decltype (delete a); // { dg-error {cannot delete objects with SVE type '(__SVInt8_t|svint8_t)'} "" { target c++11 } }
+#else
+ void f2 () throw (T); // { dg-error {cannot throw or catch SVE type '(__SVInt8_t|svint8_t)'} "" { target c++98_only } }
+#endif
+};
+template class templated_struct7<svint8_t>;
+
+template<typename T> struct templated_struct8 { typedef int type; };
+
+template<typename T>
+void sfinae_f1 (typename templated_struct8<T[2]>::type);
+template<typename T>
+void sfinae_f1 (T &);
+
#if __cplusplus >= 201103L
template<int N> using typedef_sizeless1 = svint8_t;
template<int N> using typedef_sizeless1 = svint8_t;
-template<typename T> using array = T[2];
+template<typename T> using array = T[2]; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
#endif
// Pointers to sizeless types.
@@ -119,7 +146,7 @@ statements (int n)
__alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
#if __cplusplus >= 201103L
- array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
+ array<svint8_t> foo = {}; // { dg-message {required from here} "" { target c++11 } }
#endif
// Initialization.
@@ -298,6 +325,8 @@ statements (int n)
thrower2 ();
#endif
+ sfinae_f1<svint8_t> (sve_sc1);
+
// Use in traits. Doesn't use static_assert so that tests work with
// earlier -std=s.
diff --git a/gcc/testsuite/g++.dg/goacc/cache-1.C b/gcc/testsuite/g++.dg/goacc/cache-1.C
new file mode 100644
index 0000000..a8d5ab3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/cache-1.C
@@ -0,0 +1,15 @@
+/* OpenACC 'cache' directive: valid usage. */
+
+/* See also corresponding C/C++ variant '../../c-c++-common/goacc/cache-1.c'. */
+
+/* For execution testing, this file is '#include'd from
+ '../../../../libgomp/testsuite/libgomp.oacc-c++/cache-1.C'. */
+
+#define TEMPLATIZE
+#include "../../c-c++-common/goacc/cache-1.c"
+
+static void
+instantiate ()
+{
+ &test<0>;
+}
diff --git a/gcc/testsuite/g++.dg/goacc/cache-2.C b/gcc/testsuite/g++.dg/goacc/cache-2.C
new file mode 100644
index 0000000..ef0b8a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/cache-2.C
@@ -0,0 +1,64 @@
+/* OpenACC 'cache' directive: invalid usage. */
+
+/* See also corresponding C/C++ variant '../../c-c++-common/goacc/cache-2.c'. */
+
+template <int N>
+static void
+test ()
+{
+#define N 2
+ int a[N], b[N];
+ int i;
+
+ for (i = 0; i < N; i++)
+ {
+ a[i] = 3;
+ b[i] = 0;
+ }
+
+#pragma acc parallel copyin (a[0:N]) copyout (b[0:N])
+{
+ int ii;
+
+ for (ii = 0; ii < N; ii++)
+ {
+ const int idx = ii;
+ int n = 1;
+ const int len = n;
+
+#pragma acc cache /* { dg-error "expected '\\\(' before end of line" } */
+#pragma acc cache a[0:N] /* { dg-error "expected '\\\(' before 'a'" } */
+ /* { dg-bogus "expected end of line before 'a'" "" { xfail c++ } .-1 } */
+#pragma acc cache (a) /* { dg-error "expected '\\\['" } */
+#pragma acc cache ( /* { dg-error "expected (identifier|unqualified-id) before end of line" } */
+#pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
+#pragma acc cache (,) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" } */
+#pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
+#pragma acc cache (a[0:N],) /* { dg-error "expected (identifier|unqualified-id) before '(,|\\\))' token" "" { xfail c } } */
+#pragma acc cache (a[0:N]) copyin (a[0:N]) /* { dg-error "expected end of line before 'copyin'" } */
+#pragma acc cache () /* { dg-error "expected (identifier|unqualified-id) before '\\\)' token" } */
+#pragma acc cache (a[0:N] b[0:N]) /* { dg-error "expected '\\\)' before 'b'" } */
+#pragma acc cache (a[0:N] b[0:N}) /* { dg-error "expected '\\\)' before 'b'" } */
+ /* { dg-bogus "expected end of line before '\\\}' token" "" { xfail c++ } .-1 } */
+#pragma acc cache (a[0:N] /* { dg-error "expected '\\\)' before end of line" } */
+#pragma acc cache (a[0:N]) ( /* { dg-error "expected end of line before '\\(' token" } */
+#pragma acc cache (a[0:N]) ii /* { dg-error "expected end of line before 'ii'" } */
+#pragma acc cache (a[0:N] ii) /* { dg-error "expected '\\)' before 'ii'" } */
+
+ b[ii] = a[ii];
+ }
+}
+
+
+ for (i = 0; i < N; i++)
+ {
+ if (a[i] != b[i])
+ __builtin_abort ();
+ }
+}
+
+static void
+instantiate ()
+{
+ &test<0>;
+}
diff --git a/gcc/testsuite/g++.dg/goacc/cache-3-1.C b/gcc/testsuite/g++.dg/goacc/cache-3-1.C
new file mode 100644
index 0000000..ceafb38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/cache-3-1.C
@@ -0,0 +1,123 @@
+/* Test 'cache' directive diagnostics. */
+
+/* See also corresponding C/C++ variant: '../../c-c++-common/goacc/cache-3-1.c'. */
+
+/* See also corresponding C++ data clause variant: 'data-clause-1.C'. */
+
+/* { dg-additional-options "-fopenmp" } for '#pragma omp threadprivate'. */
+
+/* The current implementation doesn't restrict where a 'cache' directive may
+ appear, so we don't make any special arrangements. */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+int **q;
+int r[4][4][4][4][4];
+extern struct s s1;
+extern struct s s2[1]; /* { dg-error "array type has incomplete element type" "" { target c } } */
+int t[10];
+#pragma omp threadprivate (t)
+#pragma acc routine
+void bar (int *);
+
+template <int N>
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma acc cache(bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma acc cache(t[2:5]) /* { dg-error "is threadprivate variable" } */
+ ;
+ #pragma acc cache(k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc cache(o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma acc cache(s1) /* { dg-error "expected '\\\['" } */
+ ;
+ #pragma acc cache(s2) /* { dg-error "expected '\\\['" } */
+ ;
+ #pragma acc cache(a[:][:]) /* { dg-error "array type length expression must be specified" } */
+ bar (&a[0][0]);
+ #pragma acc cache(b[-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (b);
+ #pragma acc cache(c[:-3][:]) /* { dg-error "negative length in array section" } */
+ bar (&c[0][0]);
+ #pragma acc cache(d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (d);
+ #pragma acc cache(e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (e);
+ #pragma acc cache(f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (f);
+ #pragma acc cache(g[:][0:10]) /* { dg-error "for array function parameter length expression must be specified" } */
+ bar (&g[0][0]);
+ #pragma acc cache(h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (&h[0][0]);
+ #pragma acc cache(h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ bar (&h[0][0]);
+ #pragma acc cache(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (&i[0][0]);
+ #pragma acc cache(j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc cache(j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc cache(a2[:1][2:4])
+ bar (&a2[0][0]);
+ #pragma acc cache(a2[3:5][:])
+ bar (&a2[0][0]);
+ #pragma acc cache(a2[3:5][:10])
+ bar (&a2[0][0]);
+ #pragma acc cache(b2[0:])
+ bar (b2);
+ #pragma acc cache(c2[:3][:])
+ bar (&c2[0][0]);
+ #pragma acc cache(d2[9:])
+ bar (d2);
+ #pragma acc cache(e2[:10])
+ bar (e2);
+ #pragma acc cache(f2[1:9])
+ bar (f2);
+ #pragma acc cache(g2[:1][2:4])
+ bar (&g2[0][0]);
+ #pragma acc cache(h2[2:2][0:])
+ bar (&h2[0][0]);
+ #pragma acc cache(h2[:1][:3])
+ bar (&h2[0][0]);
+ #pragma acc cache(i2[:1][9:])
+ bar (&i2[0][0]);
+ #pragma acc cache(j2[3:4][:9])
+ bar (&j2[0][0]);
+ #pragma acc cache(j2[30:1][5:4])
+ bar (&j2[0][0]);
+ #pragma acc cache(q[1:2])
+ ;
+ #pragma acc cache(q[3:5][:10]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2])
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:][0:4])
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc cache(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */
+ ;
+}
+
+static void
+instantiate ()
+{
+ &foo<0>;
+}
diff --git a/gcc/testsuite/g++.dg/goacc/cache-3-2.C b/gcc/testsuite/g++.dg/goacc/cache-3-2.C
new file mode 100644
index 0000000..5561e17
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/cache-3-2.C
@@ -0,0 +1,57 @@
+/* Test 'cache' directive diagnostics. */
+
+/* See also corresponding C/C++ variant: '../../c-c++-common/goacc/cache-3-2.c'. */
+
+/* See also corresponding C++ data clause variant: 'data-clause-2.C'. */
+
+/* The current implementation doesn't restrict where a 'cache' directive may
+ appear, so we don't make any special arrangements. */
+
+template <int N>
+void
+foo (int *p, int (*q)[10], int r[10], int s[10][10])
+{
+ int a[10], b[10][10];
+ #pragma acc cache (p[-1:2])
+ ;
+ #pragma acc cache (q[-1:2][0:10])
+ ;
+ #pragma acc cache (q[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (r[-1:2])
+ ;
+ #pragma acc cache (s[-1:2][:])
+ ;
+ #pragma acc cache (s[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (a[-1:2]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (b[-1:2][0:]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (b[1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc cache (p[2:-3]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (q[2:-3][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (q[2:3][0:-1]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (r[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (s[2:-5][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (s[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (a[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (b[2:-5][0:10]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc cache (b[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+}
+
+static void
+instantiate ()
+{
+ &foo<0>;
+}
diff --git a/gcc/testsuite/g++.dg/goacc/data-clause-1.C b/gcc/testsuite/g++.dg/goacc/data-clause-1.C
new file mode 100644
index 0000000..07ef6ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/data-clause-1.C
@@ -0,0 +1,122 @@
+/* Test data clause diagnostics. */
+
+/* See also corresponding OpenACC C/C++ variant: '../../c-c++-common/goacc/data-clause-1.c'. */
+
+/* See also corresponding OpenACC 'cache' directive variant: 'cache-3-1.C'. */
+
+/* See also corresponding OpenMP variant: '../gomp/map-1.C'. */
+
+/* { dg-additional-options "-fopenmp" } for '#pragma omp threadprivate'. */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+int **q;
+int r[4][4][4][4][4];
+extern struct s s1;
+extern struct s s2[1]; /* { dg-error "array type has incomplete element type" "" { target c } } */
+int t[10];
+#pragma omp threadprivate (t)
+#pragma acc routine
+void bar (int *);
+
+template <int N>
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma acc parallel copyin(bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma acc parallel copyout(t[2:5]) /* { dg-error "is threadprivate variable" } */
+ ;
+ #pragma acc parallel copy(k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copyout(l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copyin(m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copy(n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma acc parallel copyin(o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma acc parallel create(s1) /* { dg-error "'s1' does not have a mappable type in 'map' clause" } */
+ ;
+ #pragma acc parallel create(s2) /* { dg-error "'s2' does not have a mappable type in 'map' clause" } */
+ ;
+ #pragma acc parallel copyin(a[:][:]) /* { dg-error "array type length expression must be specified" } */
+ bar (&a[0][0]); /* { dg-error "referenced in target region does not have a mappable type" "PR97996" { xfail *-*-* } } */
+ #pragma acc parallel copy(b[-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (b);
+ #pragma acc parallel copy(c[:-3][:]) /* { dg-error "negative length in array section" } */
+ bar (&c[0][0]);
+ #pragma acc parallel copyout(d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (d);
+ #pragma acc parallel copyin(e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (e);
+ #pragma acc parallel copyin(f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (f);
+ #pragma acc parallel copyout(g[:][0:10]) /* { dg-error "for array function parameter length expression must be specified" } */
+ bar (&g[0][0]);
+ #pragma acc parallel copyout(h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (&h[0][0]);
+ #pragma acc parallel copy(h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ bar (&h[0][0]);
+ #pragma acc parallel copy(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (&i[0][0]);
+ #pragma acc parallel copyout(j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc parallel copyin(j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma acc parallel copyin(a2[:1][2:4])
+ bar (&a2[0][0]);
+ #pragma acc parallel copy(a2[3:5][:])
+ bar (&a2[0][0]);
+ #pragma acc parallel copyin(a2[3:5][:10])
+ bar (&a2[0][0]);
+ #pragma acc parallel copy(b2[0:])
+ bar (b2);
+ #pragma acc parallel copy(c2[:3][:])
+ bar (&c2[0][0]);
+ #pragma acc parallel copyout(d2[9:])
+ bar (d2);
+ #pragma acc parallel copyin(e2[:10])
+ bar (e2);
+ #pragma acc parallel copyin(f2[1:9])
+ bar (f2);
+ #pragma acc parallel copy(g2[:1][2:4])
+ bar (&g2[0][0]);
+ #pragma acc parallel copyout(h2[2:2][0:])
+ bar (&h2[0][0]);
+ #pragma acc parallel copy(h2[:1][:3])
+ bar (&h2[0][0]);
+ #pragma acc parallel copyin(i2[:1][9:])
+ bar (&i2[0][0]);
+ #pragma acc parallel copyout(j2[3:4][:9])
+ bar (&j2[0][0]);
+ #pragma acc parallel copyin(j2[30:1][5:4])
+ bar (&j2[0][0]);
+ #pragma acc parallel copy(q[1:2])
+ ;
+ #pragma acc parallel copy(q[3:5][:10]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2])
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:][0:4])
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma acc parallel copy(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */
+ ;
+}
+
+static void
+instantiate ()
+{
+ &foo<0>;
+}
diff --git a/gcc/testsuite/g++.dg/goacc/data-clause-2.C b/gcc/testsuite/g++.dg/goacc/data-clause-2.C
new file mode 100644
index 0000000..57d1823
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/data-clause-2.C
@@ -0,0 +1,56 @@
+/* Test data clause diagnostics. */
+
+/* See also corresponding OpenACC C/C++ variant: '../../c-c++-common/goacc/data-clause-2.c'. */
+
+/* See also corresponding OpenACC 'cache' directive variant: 'cache-3-2.C'. */
+
+/* See also corresponding OpenMP variant: '../gomp/map-2.C'. */
+
+template <int N>
+void
+foo (int *p, int (*q)[10], int r[10], int s[10][10])
+{
+ int a[10], b[10][10];
+ #pragma acc parallel copy (p[-1:2])
+ ;
+ #pragma acc parallel copy (q[-1:2][0:10])
+ ;
+ #pragma acc parallel copy (q[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (r[-1:2])
+ ;
+ #pragma acc parallel copy (s[-1:2][:])
+ ;
+ #pragma acc parallel copy (s[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (a[-1:2]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (b[-1:2][0:]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (b[1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma acc parallel copy (p[2:-3]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (q[2:-3][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (q[2:3][0:-1]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (r[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (s[2:-5][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (s[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (a[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (b[2:-5][0:10]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma acc parallel copy (b[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+}
+
+static void
+instantiate ()
+{
+ &foo<0>;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-1.C b/gcc/testsuite/g++.dg/gomp/allocate-1.C
new file mode 100644
index 0000000..e70c65e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-1.C
@@ -0,0 +1,88 @@
+// { dg-do compile }
+// { dg-additional-options "-std=c++11" }
+
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+namespace N1
+{
+ using ::omp_allocator_handle_t;
+ void
+ foo (const omp_allocator_handle_t h)
+ {
+ int x = 0;
+ #pragma omp parallel allocate (h: x) private (x)
+ x = 1;
+ }
+}
+
+namespace N2
+{
+ typedef enum omp_allocator_handle_t { my = 0 } omp_allocator_handle_t;
+ void
+ foo (omp_allocator_handle_t h)
+ {
+ int x = 0;
+ #pragma omp parallel allocate (h: x) private (x) // { dg-error "'allocate' clause allocator expression has type 'N2::omp_allocator_handle_t' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ }
+}
+
+struct S
+{
+ void foo ()
+ {
+ #pragma omp parallel allocate (omp_default_mem_alloc:s) firstprivate (s)
+ s++;
+ }
+ int s;
+};
+
+template <typename T>
+struct U
+{
+ int foo ()
+ {
+ #pragma omp parallel allocate (omp_default_mem_alloc:s) firstprivate (s)
+ s++;
+ return 1;
+ }
+ T s;
+};
+
+template <typename T>
+int foo (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (t: x)
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int bar (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (t: x) // { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ return 0;
+}
+
+omp_allocator_handle_t h;
+int a = foo (h);
+int b = bar (0);
+int c = U<int> ().foo ();
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-2.C b/gcc/testsuite/g++.dg/gomp/allocate-2.C
new file mode 100644
index 0000000..b8cf480
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-2.C
@@ -0,0 +1,11 @@
+// PR c++/97670
+
+struct S { int s; };
+
+void
+foo ()
+{
+ S s[1] = { S () };
+#pragma omp parallel reduction (+: s) allocate(s) // { dg-error "user defined reduction not found for 's'" }
+ s[0].s++;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-3.C b/gcc/testsuite/g++.dg/gomp/allocate-3.C
new file mode 100644
index 0000000..e778314
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-3.C
@@ -0,0 +1,206 @@
+template <typename T>
+void
+foo (T &x, T (&y)[4], T *&z, int &u, int (&v)[4], int *&w)
+{
+ T s[4] = { 0, 0, 0, 0 };
+ T *p = s;
+#pragma omp parallel reduction (+: s) allocate(s)
+ s[0]++;
+#pragma omp parallel reduction (+: s[0:3]) allocate(s)
+ s[0]++;
+#pragma omp parallel reduction (+: s[2:2]) allocate(s)
+ s[2]++;
+#pragma omp parallel reduction (+: p[:2]) allocate(p)
+ p[0]++;
+#pragma omp parallel reduction (+: p[2:2]) allocate(p)
+ p[2]++;
+ int s2[4] = { 0, 0, 0, 0 };
+ int *p2 = s2;
+#pragma omp parallel reduction (+: s2) allocate(s2)
+ s2[0]++;
+#pragma omp parallel reduction (+: s2[0:3]) allocate(s2)
+ s2[0]++;
+#pragma omp parallel reduction (+: s2[2:2]) allocate(s2)
+ s2[2]++;
+#pragma omp parallel reduction (+: p2[:2]) allocate(p2)
+ p2[0]++;
+#pragma omp parallel reduction (+: p2[2:2]) allocate(p2)
+ p2[2]++;
+#pragma omp parallel reduction (+: x) allocate(x)
+ x++;
+#pragma omp parallel reduction (+: y) allocate(y)
+ y[0]++;
+#pragma omp parallel reduction (+: y[0:3]) allocate(y)
+ y[0]++;
+#pragma omp parallel reduction (+: y[2:2]) allocate(y)
+ y[2]++;
+#pragma omp parallel reduction (+: z[:2]) allocate(z)
+ z[0]++;
+#pragma omp parallel reduction (+: z[2:2]) allocate(z)
+ z[2]++;
+#pragma omp parallel reduction (+: u) allocate(u)
+ u++;
+#pragma omp parallel reduction (+: v) allocate(v)
+ v[0]++;
+#pragma omp parallel reduction (+: v[0:3]) allocate(v)
+ v[0]++;
+#pragma omp parallel reduction (+: v[2:2]) allocate(v)
+ v[2]++;
+#pragma omp parallel reduction (+: w[:2]) allocate(w)
+ w[0]++;
+#pragma omp parallel reduction (+: w[2:2]) allocate(w)
+ w[2]++;
+}
+
+template <typename T>
+void
+bar (T &x, T (&y)[4], T *&z, int &u, int (&v)[4], int *&w)
+{
+ T s[4] = { 0, 0, 0, 0 };
+ T *p = s;
+ int i;
+#pragma omp teams distribute parallel for reduction (+: s) allocate(s)
+ for (i = 0; i < 64; i++)
+ s[0]++;
+#pragma omp teams distribute parallel for reduction (+: s[0:3]) allocate(s)
+ for (i = 0; i < 64; i++)
+ s[0]++;
+#pragma omp teams distribute parallel for reduction (+: s[2:2]) allocate(s)
+ for (i = 0; i < 64; i++)
+ s[2]++;
+#pragma omp teams distribute parallel for reduction (+: p[:2]) allocate(p)
+ for (i = 0; i < 64; i++)
+ p[0]++;
+#pragma omp teams distribute parallel for reduction (+: p[2:2]) allocate(p)
+ for (i = 0; i < 64; i++)
+ p[2]++;
+ int s2[4] = { 0, 0, 0, 0 };
+ int *p2 = s2;
+#pragma omp teams distribute parallel for reduction (+: s2) allocate(s2)
+ for (i = 0; i < 64; i++)
+ s2[0]++;
+#pragma omp teams distribute parallel for reduction (+: s2[0:3]) allocate(s2)
+ for (i = 0; i < 64; i++)
+ s2[0]++;
+#pragma omp teams distribute parallel for reduction (+: s2[2:2]) allocate(s2)
+ for (i = 0; i < 64; i++)
+ s2[2]++;
+#pragma omp teams distribute parallel for reduction (+: p2[:2]) allocate(p2)
+ for (i = 0; i < 64; i++)
+ p2[0]++;
+#pragma omp teams distribute parallel for reduction (+: p2[2:2]) allocate(p2)
+ for (i = 0; i < 64; i++)
+ p2[2]++;
+#pragma omp teams distribute parallel for reduction (+: x) allocate(x)
+ for (i = 0; i < 64; i++)
+ x++;
+#pragma omp teams distribute parallel for reduction (+: y) allocate(y)
+ for (i = 0; i < 64; i++)
+ y[0]++;
+#pragma omp teams distribute parallel for reduction (+: y[0:3]) allocate(y)
+ for (i = 0; i < 64; i++)
+ y[0]++;
+#pragma omp teams distribute parallel for reduction (+: y[2:2]) allocate(y)
+ for (i = 0; i < 64; i++)
+ y[2]++;
+#pragma omp teams distribute parallel for reduction (+: z[:2]) allocate(z)
+ for (i = 0; i < 64; i++)
+ z[0]++;
+#pragma omp teams distribute parallel for reduction (+: z[2:2]) allocate(z)
+ for (i = 0; i < 64; i++)
+ z[2]++;
+#pragma omp teams distribute parallel for reduction (+: u) allocate(u)
+ for (i = 0; i < 64; i++)
+ u++;
+#pragma omp teams distribute parallel for reduction (+: v) allocate(v)
+ for (i = 0; i < 64; i++)
+ v[0]++;
+#pragma omp teams distribute parallel for reduction (+: v[0:3]) allocate(v)
+ for (i = 0; i < 64; i++)
+ v[0]++;
+#pragma omp teams distribute parallel for reduction (+: v[2:2]) allocate(v)
+ for (i = 0; i < 64; i++)
+ v[2]++;
+#pragma omp teams distribute parallel for reduction (+: w[:2]) allocate(w)
+ for (i = 0; i < 64; i++)
+ w[0]++;
+#pragma omp teams distribute parallel for reduction (+: w[2:2]) allocate(w)
+ for (i = 0; i < 64; i++)
+ w[2]++;
+}
+
+void
+baz (long int &x, long int (&y)[4], long int *&z)
+{
+#pragma omp parallel reduction (+: x) allocate(x)
+ x++;
+#pragma omp parallel reduction (+: y) allocate(y)
+ y[0]++;
+#pragma omp parallel reduction (+: y[0:3]) allocate(y)
+ y[0]++;
+#pragma omp parallel reduction (+: y[2:2]) allocate(y)
+ y[2]++;
+#pragma omp parallel reduction (+: z[:2]) allocate(z)
+ z[0]++;
+#pragma omp parallel reduction (+: z[2:2]) allocate(z)
+ z[2]++;
+}
+
+void
+qux (long long int &x, long long int (&y)[4], long long int *&z)
+{
+ int i;
+#pragma omp teams distribute parallel for reduction (+: x) allocate(x)
+ for (i = 0; i < 64; i++)
+ x++;
+#pragma omp teams distribute parallel for reduction (+: y) allocate(y)
+ for (i = 0; i < 64; i++)
+ y[0]++;
+#pragma omp teams distribute parallel for reduction (+: y[0:3]) allocate(y)
+ for (i = 0; i < 64; i++)
+ y[0]++;
+#pragma omp teams distribute parallel for reduction (+: y[2:2]) allocate(y)
+ for (i = 0; i < 64; i++)
+ y[2]++;
+#pragma omp teams distribute parallel for reduction (+: z[:2]) allocate(z)
+ for (i = 0; i < 64; i++)
+ z[0]++;
+#pragma omp teams distribute parallel for reduction (+: z[2:2]) allocate(z)
+ for (i = 0; i < 64; i++)
+ z[2]++;
+}
+
+void
+test ()
+{
+ long int x = 0;
+ long int y[4] = { 0, 0, 0, 0 };
+ long int *z = y;
+ int u = 0;
+ int v[4] = { 0, 0, 0, 0 };
+ int *w = v;
+ long long int x2 = 0;
+ long long int y2[4] = { 0, 0, 0, 0 };
+ long long int *z2 = y2;
+ foo (x, y, z, u, v, w);
+ bar (x2, y2, z2, u, v, w);
+}
+
+namespace N
+{
+ int a;
+ void foo ()
+ {
+ int i;
+ #pragma omp parallel firstprivate (N::a) allocate (a)
+ a++;
+ #pragma omp parallel firstprivate (a) allocate (N::a)
+ a++;
+ #pragma omp teams distribute parallel for firstprivate (N::a) allocate (a)
+ for (i = 0; i < 64; i++)
+ a++;
+ #pragma omp teams distribute parallel for firstprivate (a) allocate (N::a)
+ for (i = 0; i < 64; i++)
+ a++;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/declare-target-3.C b/gcc/testsuite/g++.dg/gomp/declare-target-3.C
new file mode 100644
index 0000000..1e23c86
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-target-3.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+// Test implicit marking of declare target to.
+
+int foo () { return 1; }
+int bar () { return 2; } // Implicitly marked (due to b)
+int baz () { return 3; } // Implicitly marked (due to d via c)
+int qux () { return 4; } // Implicitly marked (due to g via f and e)
+
+int a = foo ();
+int b = bar (); // Explicitly marked
+int c = baz (); // Implicitly marked (due to d)
+int *d = &c; // Explicitly marked
+int e = qux (); // Implicitly marked (due to g via f)
+int f = e + 1; // Implicitly marked (due to g)
+int *g = &f; // Explicitly marked
+
+#pragma omp declare target to(b, d, g)
+
+// { dg-final { scan-tree-dump-not "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint foo \\\(\\\)" "gimple" } }
+// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint bar \\\(\\\)" "gimple" } }
+// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint baz \\\(\\\)" "gimple" } }
+// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint qux \\\(\\\)" "gimple" } }
+// { dg-final { scan-assembler-not "\\\.offload_var_table:\\n.+\\\.quad\\s+a" { target { offloading_enabled } } } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+b" { target { offloading_enabled } } } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+c" { target { offloading_enabled } } } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+d" { target { offloading_enabled } } } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+e" { target { offloading_enabled } } } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+f" { target { offloading_enabled } } } }
+// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+g" { target { offloading_enabled } } } }
diff --git a/gcc/testsuite/g++.dg/gomp/map-1.C b/gcc/testsuite/g++.dg/gomp/map-1.C
new file mode 100644
index 0000000..27dc7a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/map-1.C
@@ -0,0 +1,119 @@
+/* Test 'map' clause diagnostics. */
+
+/* See also corresponding OpenMP C/C++ variant: '../../c-c++-common/gomp/map-1.c'. */
+
+/* See also corresponding OpenACC variant: '../goacc/data-clause-1.C'. */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+int **q;
+int r[4][4][4][4][4];
+extern struct s s1;
+extern struct s s2[1]; /* { dg-error "array type has incomplete element type" "" { target c } } */
+int t[10];
+#pragma omp threadprivate (t)
+#pragma omp declare target
+void bar (int *);
+#pragma omp end declare target
+
+template <int N>
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma omp target map(to: bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma omp target map(from: t[2:5]) /* { dg-error "is threadprivate variable" } */
+ ;
+ #pragma omp target map(tofrom: k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(from: l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(to: m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(tofrom: n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(to: o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma omp target map(alloc: s1) /* { dg-error "'s1' does not have a mappable type in 'map' clause" } */
+ ;
+ #pragma omp target map(alloc: s2) /* { dg-error "'s2' does not have a mappable type in 'map' clause" } */
+ ;
+ #pragma omp target map(to: a[:][:]) /* { dg-error "array type length expression must be specified" } */
+ bar (&a[0][0]); /* { dg-error "referenced in target region does not have a mappable type" "PR97996" { xfail *-*-* } } */
+ #pragma omp target map(tofrom: b[-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (b);
+ #pragma omp target map(tofrom: c[:-3][:]) /* { dg-error "negative length in array section" } */
+ bar (&c[0][0]);
+ #pragma omp target map(from: d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (d);
+ #pragma omp target map(to: e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (e);
+ #pragma omp target map(to: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (f);
+ #pragma omp target map(from: g[:][0:10]) /* { dg-error "for array function parameter length expression must be specified" } */
+ bar (&g[0][0]);
+ #pragma omp target map(from: h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (&h[0][0]);
+ #pragma omp target map(tofrom: h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ bar (&h[0][0]);
+ #pragma omp target map(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (&i[0][0]);
+ #pragma omp target map(from: j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma omp target map(to: j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma omp target map(to: a2[:1][2:4])
+ bar (&a2[0][0]);
+ #pragma omp target map(a2[3:5][:])
+ bar (&a2[0][0]);
+ #pragma omp target map(to: a2[3:5][:10])
+ bar (&a2[0][0]);
+ #pragma omp target map(tofrom: b2[0:])
+ bar (b2);
+ #pragma omp target map(tofrom: c2[:3][:])
+ bar (&c2[0][0]);
+ #pragma omp target map(from: d2[9:])
+ bar (d2);
+ #pragma omp target map(to: e2[:10])
+ bar (e2);
+ #pragma omp target map(to: f2[1:9])
+ bar (f2);
+ #pragma omp target map(g2[:1][2:4])
+ bar (&g2[0][0]);
+ #pragma omp target map(from: h2[2:2][0:])
+ bar (&h2[0][0]);
+ #pragma omp target map(tofrom: h2[:1][:3])
+ bar (&h2[0][0]);
+ #pragma omp target map(to: i2[:1][9:])
+ bar (&i2[0][0]);
+ #pragma omp target map(from: j2[3:4][:9])
+ bar (&j2[0][0]);
+ #pragma omp target map(to: j2[30:1][5:4])
+ bar (&j2[0][0]);
+ #pragma omp target map(q[1:2])
+ ;
+ #pragma omp target map(tofrom: q[3:5][:10]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2])
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:][0:4])
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */
+ ;
+}
+
+static void
+instantiate ()
+{
+ &foo<0>;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/map-2.C b/gcc/testsuite/g++.dg/gomp/map-2.C
new file mode 100644
index 0000000..bbe2606
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/map-2.C
@@ -0,0 +1,54 @@
+/* Test 'map' clause diagnostics. */
+
+/* See also corresponding OpenMP C/C++ variant: '../../c-c++-common/gomp/map-2.c'. */
+
+/* See also corresponding OpenACC variant: '../goacc/data-clause-2.C'. */
+
+template <int N>
+void
+foo (int *p, int (*q)[10], int r[10], int s[10][10])
+{
+ int a[10], b[10][10];
+ #pragma omp target map (tofrom: p[-1:2])
+ ;
+ #pragma omp target map (tofrom: q[-1:2][0:10])
+ ;
+ #pragma omp target map (tofrom: q[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma omp target map (tofrom: r[-1:2])
+ ;
+ #pragma omp target map (tofrom: s[-1:2][:])
+ ;
+ #pragma omp target map (tofrom: s[-1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma omp target map (tofrom: a[-1:2]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma omp target map (tofrom: b[-1:2][0:]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma omp target map (tofrom: b[1:2][-2:10]) /* { dg-error "negative low bound in array section in" } */
+ ;
+ #pragma omp target map (tofrom: p[2:-3]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: q[2:-3][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: q[2:3][0:-1]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: r[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: s[2:-5][:]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: s[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: a[2:-5]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: b[2:-5][0:10]) /* { dg-error "negative length in array section in" } */
+ ;
+ #pragma omp target map (tofrom: b[2:5][0:-4]) /* { dg-error "negative length in array section in" } */
+ ;
+}
+
+static void
+instantiate ()
+{
+ &foo<0>;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/pr98383.C b/gcc/testsuite/g++.dg/gomp/pr98383.C
new file mode 100644
index 0000000..8106138
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/pr98383.C
@@ -0,0 +1,18 @@
+// PR c++/98383
+// { dg-options "-fopenmp -O1" }
+
+int bar (const int &);
+
+void
+foo (int *a)
+{
+#pragma omp simd
+ for (int i = 0; i < bar (8); ++i)
+ a[i]++;
+#pragma omp simd
+ for (int i = bar (9); i < 16; ++i)
+ a[i]++;
+#pragma omp simd
+ for (int i = 0; i < 32; i += bar (10))
+ a[i]++;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/tls-5.C b/gcc/testsuite/g++.dg/gomp/tls-5.C
index e83ff11..eb187b6 100644
--- a/gcc/testsuite/g++.dg/gomp/tls-5.C
+++ b/gcc/testsuite/g++.dg/gomp/tls-5.C
@@ -1,6 +1,8 @@
// The reference temp should be TLS, not normal data.
// { dg-require-effective-target c++11 }
// { dg-final { scan-assembler-not "\\.data" { target tls_native xfail powerpc-*-aix* } } }
+// { dg-final { scan-assembler-symbol-section {^_?ir$} {^\.tbss|\[TL\]} { target tls_native } } }
+// { dg-final { scan-assembler-symbol-section {^_?_ZGR2ir_$} {^\.tdata|\[TL\]} { target tls_native } } }
extern int&& ir;
#pragma omp threadprivate (ir)
diff --git a/gcc/testsuite/g++.dg/guality/guality.exp b/gcc/testsuite/g++.dg/guality/guality.exp
index 33571f1..1d5b65f 100644
--- a/gcc/testsuite/g++.dg/guality/guality.exp
+++ b/gcc/testsuite/g++.dg/guality/guality.exp
@@ -38,7 +38,7 @@ global GDB
if ![info exists ::env(GUALITY_GDB_NAME)] {
if [info exists GDB] {
set guality_gdb_name "$GDB"
- } elseif [file exists $rootme/../gdb/gdb] {
+ } elseif { [info exists rootme] && [file exists $rootme/../gdb/gdb] } {
# If we're doing a combined build, and gdb is available, use it.
set guality_gdb_name "$rootme/../gdb/gdb"
} else {
diff --git a/gcc/testsuite/g++.dg/guality/redeclaration1.C b/gcc/testsuite/g++.dg/guality/redeclaration1.C
index 93b0750..bd0209f 100644
--- a/gcc/testsuite/g++.dg/guality/redeclaration1.C
+++ b/gcc/testsuite/g++.dg/guality/redeclaration1.C
@@ -3,6 +3,7 @@
// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
volatile int l;
+int *volatile p;
namespace S
{
@@ -11,10 +12,11 @@ namespace S
f()
{
int i = 42;
- l = i; // { dg-final { gdb-test 14 "i" "42" } }
+ l = i; // { dg-final { gdb-test 15 "i" "42" } }
{
extern int i;
- l = i; // { dg-final { gdb-test 17 "i" "24" } }
+ p[0]++;
+ l = i; // { dg-final { gdb-test 19 "i" "24" } }
}
}
}
@@ -22,6 +24,8 @@ namespace S
int
main (void)
{
+ int x = 0;
+ p = &x;
S::f ();
return 0;
}
diff --git a/gcc/testsuite/g++.dg/hwasan/hwasan.exp b/gcc/testsuite/g++.dg/hwasan/hwasan.exp
new file mode 100644
index 0000000..559cf06
--- /dev/null
+++ b/gcc/testsuite/g++.dg/hwasan/hwasan.exp
@@ -0,0 +1,34 @@
+# Copyright (C) 2012-2019 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Load support procs.
+load_lib g++-dg.exp
+load_lib hwasan-dg.exp
+
+# Initialize `dg'.
+dg-init
+hwasan_init
+
+# Main loop.
+if [check_effective_target_fsanitize_hwaddress] {
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/hwasan/*.c]] "" ""
+}
+
+# All done.
+hwasan_finish
+dg-finish
diff --git a/gcc/testsuite/g++.dg/hwasan/rvo-handled.C b/gcc/testsuite/g++.dg/hwasan/rvo-handled.C
new file mode 100644
index 0000000..0e30ff0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/hwasan/rvo-handled.C
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+#define assert(x) if (!(x)) __builtin_abort ()
+typedef __UINTPTR_TYPE__ uintptr_t;
+void *untagged (void *ptr)
+{
+ /* Untag by removing the top byte. */
+ return (void*)((uintptr_t)ptr & 0xffffffffffffff);
+}
+
+struct big_struct {
+ int left;
+ int right;
+ void *ptr;
+ int big_array[100];
+};
+
+/*
+ Tests for RVO (basically, checking -fsanitize=hwaddress has not broken RVO
+ in any way).
+
+ 0) The value is accessible in both functions without a hwasan complaint.
+ 1) RVO does happen.
+ */
+
+struct big_struct __attribute__ ((noinline))
+return_on_stack()
+{
+ struct big_struct x;
+ x.left = 100;
+ x.right = 20;
+ x.big_array[10] = 30;
+ x.ptr = untagged(&x);
+ return x;
+}
+
+int main()
+{
+ struct big_struct x;
+ x = return_on_stack();
+ /* Check that RVO happens by checking the address that the callee saw. */
+ assert (x.ptr == untagged(&x));
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/inherit/thunk8.C b/gcc/testsuite/g++.dg/inherit/thunk8.C
index ef64535..ecb9cbf 100644
--- a/gcc/testsuite/g++.dg/inherit/thunk8.C
+++ b/gcc/testsuite/g++.dg/inherit/thunk8.C
@@ -4,6 +4,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-mthumb -fPIC" } */
struct A {
diff --git a/gcc/testsuite/g++.dg/inherit/using5.C b/gcc/testsuite/g++.dg/inherit/using5.C
index b8e5107..514cd8d 100644
--- a/gcc/testsuite/g++.dg/inherit/using5.C
+++ b/gcc/testsuite/g++.dg/inherit/using5.C
@@ -6,7 +6,7 @@
template<int> struct A
{
- A::A; // { dg-error "constructor|not a base" }
+ A::A; // { dg-error "constructor|not a direct base" }
};
struct B
diff --git a/gcc/testsuite/g++.dg/init/array60.C b/gcc/testsuite/g++.dg/init/array60.C
new file mode 100644
index 0000000..db5095a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array60.C
@@ -0,0 +1,8 @@
+// PR c++/91506
+
+double
+test(int *arr, int x)
+{
+ double ret(double(arr[x]) + 1);
+ return ret;
+}
diff --git a/gcc/testsuite/g++.dg/init/empty3.C b/gcc/testsuite/g++.dg/init/empty3.C
new file mode 100644
index 0000000..510338b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/empty3.C
@@ -0,0 +1,18 @@
+// PR c++/97597
+
+struct pq {
+ pq (const pq &);
+};
+
+struct a9 {
+ operator pq () const;
+};
+
+struct zp : pq {
+ zp (const a9 &k3) : pq (k3) { }
+};
+
+int main()
+{
+ zp z = a9();
+}
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-24.C b/gcc/testsuite/g++.dg/ipa/devirt-24.C
index eaef1f5..7b5b806 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-24.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-24.C
@@ -37,4 +37,4 @@ C *b = new (C);
}
}
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" { xfail *-*-* } } } */
-/* { dg-final { scan-ipa-dump-times "Aggregate passed by reference" 1 "cp" } } */
+/* { dg-final { scan-ipa-dump-times "Aggregate passed by reference" 2 "cp" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/pr98057.C b/gcc/testsuite/g++.dg/ipa/pr98057.C
new file mode 100644
index 0000000..9de9254
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr98057.C
@@ -0,0 +1,18 @@
+/* PR ipa/98057 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -ffunction-sections" } */
+
+class JITSymbolResolver {
+ virtual void anchor();
+};
+class MemoryManager {
+ virtual void anchor();
+};
+class MCJITMemoryManager : MemoryManager {
+ void anchor();
+};
+class RTDyldMemoryManager : MCJITMemoryManager, JITSymbolResolver {
+ void anchor();
+};
+void RTDyldMemoryManager::anchor() {}
+void MCJITMemoryManager::anchor() {}
diff --git a/gcc/testsuite/g++.dg/ipa/pr98075.C b/gcc/testsuite/g++.dg/ipa/pr98075.C
new file mode 100644
index 0000000..0c4219d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr98075.C
@@ -0,0 +1,30 @@
+/* PR ipa/98075 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-inline" } */
+
+template <typename BS>
+class xg {
+public:
+ BS *
+ fw ()
+ {
+ return static_cast<BS *> (operator new (sizeof (BS)));
+ }
+};
+
+class zp : xg<int> {
+public:
+ __attribute__ ((always_inline)) zp ()
+ {
+ hy = xg<int>::fw ();
+ }
+
+private:
+ int *hy;
+};
+
+void
+e5 ()
+{
+ zp ix;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/pr80891-5.C b/gcc/testsuite/g++.dg/lookup/pr80891-5.C
index e018922..10d1ce3 100644
--- a/gcc/testsuite/g++.dg/lookup/pr80891-5.C
+++ b/gcc/testsuite/g++.dg/lookup/pr80891-5.C
@@ -14,7 +14,7 @@ template <typename, typename, typename, typename,
struct B {
B(A, A, int, int, int, int);
void m_fn1(SubGraphIsoMapCallback p1) {
- __normal_iterator __trans_tmp_1();
+ __normal_iterator __trans_tmp_1(); // { dg-warning "empty parentheses" }
p1(__trans_tmp_1, 0);
}
};
diff --git a/gcc/testsuite/g++.dg/lookup/pr97877.C b/gcc/testsuite/g++.dg/lookup/pr97877.C
new file mode 100644
index 0000000..294edd2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr97877.C
@@ -0,0 +1,8 @@
+// PR 97877, duplicate decls smashed decl_lang_specific
+
+void f ()
+{
+ extern int a;
+ extern int a;
+ a = 2;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/pr97905.C b/gcc/testsuite/g++.dg/lookup/pr97905.C
new file mode 100644
index 0000000..22a7e5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr97905.C
@@ -0,0 +1,7 @@
+// PR 97905
+
+
+template <typename> void a() {
+ extern int *b; // This decl gets an (unneeded) decl-lang-specific
+}
+int *b; // this does not
diff --git a/gcc/testsuite/g++.dg/lookup/using26.C b/gcc/testsuite/g++.dg/lookup/using26.C
index 857c134..dd4e130 100644
--- a/gcc/testsuite/g++.dg/lookup/using26.C
+++ b/gcc/testsuite/g++.dg/lookup/using26.C
@@ -17,9 +17,9 @@ struct C
int next;
};
-struct D : A, B, C // { dg-error "context" }
+struct D : A, B, C
{
- using B::next;
+ using B::next; // { dg-error "context" }
void f()
{
next = 12;
diff --git a/gcc/testsuite/g++.dg/lookup/using53.C b/gcc/testsuite/g++.dg/lookup/using53.C
index 595612e..f9e59e6 100644
--- a/gcc/testsuite/g++.dg/lookup/using53.C
+++ b/gcc/testsuite/g++.dg/lookup/using53.C
@@ -43,6 +43,7 @@ template class DT<int>;
namespace N
{
int i;
+ enum bob {Q};
}
void
diff --git a/gcc/testsuite/g++.dg/lto/pr79050_0.C b/gcc/testsuite/g++.dg/lto/pr79050_0.C
index 1f31b5d..464f559 100644
--- a/gcc/testsuite/g++.dg/lto/pr79050_0.C
+++ b/gcc/testsuite/g++.dg/lto/pr79050_0.C
@@ -3,5 +3,5 @@
int main ()
{
- auto foo ();
+ extern auto foo ();
}
diff --git a/gcc/testsuite/g++.dg/lto/pr84805_0.C b/gcc/testsuite/g++.dg/lto/pr84805_0.C
index 1509eae..668ba36 100644
--- a/gcc/testsuite/g++.dg/lto/pr84805_0.C
+++ b/gcc/testsuite/g++.dg/lto/pr84805_0.C
@@ -149,5 +149,5 @@ public:
class XclImpRoot : XclRoot {};
class XclImpColRowSettings : XclImpRoot {};
void lcl_ExportExcelBiff() {
-XclRootData aExpData();
+extern XclRootData aExpData();
}
diff --git a/gcc/testsuite/g++.dg/modules/access-1_a.C b/gcc/testsuite/g++.dg/modules/access-1_a.C
new file mode 100644
index 0000000..2417017
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/access-1_a.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export class Base
+{
+public:
+ int m;
+};
diff --git a/gcc/testsuite/g++.dg/modules/access-1_b.C b/gcc/testsuite/g++.dg/modules/access-1_b.C
new file mode 100644
index 0000000..454dea5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/access-1_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Bar;
+// { dg-module-cmi Bar }
+
+import Foo;
+
+export class Derived : public Base
+{
+private:
+ using Base::m;
+};
diff --git a/gcc/testsuite/g++.dg/modules/access-1_c.C b/gcc/testsuite/g++.dg/modules/access-1_c.C
new file mode 100644
index 0000000..27b84c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/access-1_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+import Bar;
+import Foo;
+
+void foo (Derived *d)
+{
+ d->m = 1; // { dg-error "inaccessible within this context" }
+ static_cast<Base *> (d)->m = 1; //ok
+}
diff --git a/gcc/testsuite/g++.dg/modules/adhoc-1_a.C b/gcc/testsuite/g++.dg/modules/adhoc-1_a.C
new file mode 100644
index 0000000..50067ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adhoc-1_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi bob }
+
+export module bob;
+export int massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea (int);
+ export void massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea (float);
diff --git a/gcc/testsuite/g++.dg/modules/adhoc-1_b.C b/gcc/testsuite/g++.dg/modules/adhoc-1_b.C
new file mode 100644
index 0000000..59907a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adhoc-1_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -fdiagnostics-show-caret" }
+
+import bob;
+void foo ()
+{
+ massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea ();
+}
+
+// { dg-regexp "\n\[^\n]*adhoc-1_b.C:6:74: error: no matching function for call to 'massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea\\(\\)'\n massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea \\(\\);\n \\^$" }
+// { dg-regexp "\nIn module bob, imported at \[^\n]*adhoc-1_b.C:3:\n\[^\n]*adhoc-1_a.C:5:12: note: candidate: 'int massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea@bob\\(int\\)'\n export int massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea \\(int\\);\n \\^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~$" }
+// { dg-regexp "\nIn module bob, imported at \[^\n]*adhoc-1_b.C:3:\n\[^\n]*adhoc-1_a.C:6:188: note: candidate: 'void massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea@bob\\(float\\)'\n\[ \t]*export void massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea \\(float\\);\n\[ \t]*\\^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~?$" }
+// For some reason dg-regexp inserts a blank line
+// { dg-allow-blank-lines-in-output 1 }
diff --git a/gcc/testsuite/g++.dg/modules/adl-1_a.C b/gcc/testsuite/g++.dg/modules/adl-1_a.C
new file mode 100644
index 0000000..d4a53cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-1_a.C
@@ -0,0 +1,13 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module worker;
+// { dg-module-cmi worker }
+
+namespace details {
+
+export int fn (int x)
+{
+ return x;
+}
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-1_b.C b/gcc/testsuite/g++.dg/modules/adl-1_b.C
new file mode 100644
index 0000000..6cf123e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-1_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+export module inter;
+// { dg-module-cmi inter }
+
+import worker;
+
+namespace hidden {
+export int fn (int x)
+{
+ return -x;
+}
+}
+
+export template <typename T>
+int TPL (T &t)
+{
+ return fn (t);
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-1_c.C b/gcc/testsuite/g++.dg/modules/adl-1_c.C
new file mode 100644
index 0000000..8be02e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-1_c.C
@@ -0,0 +1,57 @@
+// { dg-additional-options -fmodules-ts }
+
+import inter;
+
+namespace details
+{
+
+struct X
+{
+
+ int m;
+ X (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+namespace hidden
+{
+
+struct Y
+{
+
+ int m;
+ Y (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+int main ()
+{
+ details::X x(2);
+ hidden::Y y(2);
+
+ // details::fn@worker is visible from TPL@inter
+ if (TPL (x) != 2) // instantiate TPL<details::X>(T&)
+ return 1;
+
+ // hidden::fn@inter is visible from TPL@inter
+ if (TPL (y) != -2) // instantiate TPL<hidden::Y>(T&)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-2_a.C b/gcc/testsuite/g++.dg/modules/adl-2_a.C
new file mode 100644
index 0000000..d8f481ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-2_a.C
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export template <typename T>
+int TPL (T const &t)
+{
+ return frob (t);
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-2_b.C b/gcc/testsuite/g++.dg/modules/adl-2_b.C
new file mode 100644
index 0000000..60e7943
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-2_b.C
@@ -0,0 +1,21 @@
+// { dg-additional-options -fmodules-ts }
+
+export module hidden;
+// { dg-module-cmi hidden }
+
+export struct X
+{
+ int m;
+
+ X(int m) :m(m) {}
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+export int frob (int x)
+{
+ return x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-2_c.C b/gcc/testsuite/g++.dg/modules/adl-2_c.C
new file mode 100644
index 0000000..9c75b6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-2_c.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+import hidden;
+
+int main ()
+{
+ X x (2);
+
+ if (frob (x) != 2)
+ return 1;
+
+ if (TPL (x) != 2)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-3_a.C b/gcc/testsuite/g++.dg/modules/adl-3_a.C
new file mode 100644
index 0000000..a263978
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-3_a.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules-ts }
+export module worker;
+// { dg-module-cmi worker }
+
+namespace details {
+
+int fn (int x)
+{
+ return x;
+}
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-3_b.C b/gcc/testsuite/g++.dg/modules/adl-3_b.C
new file mode 100644
index 0000000..1f3011f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-3_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+export module inter;
+// { dg-module-cmi inter }
+
+export template <typename T>
+int TPL (T &t)
+{
+ return fn (t);
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-3_c.C b/gcc/testsuite/g++.dg/modules/adl-3_c.C
new file mode 100644
index 0000000..c4dc0ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-3_c.C
@@ -0,0 +1,36 @@
+// { dg-additional-options -fmodules-ts }
+
+import inter;
+import worker;
+
+namespace details
+{
+struct X
+{
+
+ int m;
+ X (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+int main ()
+{
+ details::X x(2);
+
+ if (fn (x) != 2) // { dg-error "not declared in" }
+ return 1;
+
+ // { dg-regexp "\n\[^\n]*adl-3_b.C:8:13: error: 'fn' was not declared in this scope$" }
+ if (TPL (x) != 2) // { dg-message "required from here" }
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-4_a.C b/gcc/testsuite/g++.dg/modules/adl-4_a.C
new file mode 100644
index 0000000..5d956c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-4_a.C
@@ -0,0 +1,15 @@
+// { dg-additional-options -fmodules-ts }
+export module inter;
+// { dg-module-cmi inter }
+
+namespace hidden {
+// not found via ADL
+int fn (int x);
+
+}
+
+export template <typename T>
+int TPL (T &t)
+{
+ return fn (t);
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-4_b.C b/gcc/testsuite/g++.dg/modules/adl-4_b.C
new file mode 100644
index 0000000..aa1396f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-4_b.C
@@ -0,0 +1,36 @@
+// { dg-additional-options -fmodules-ts }
+
+import inter;
+
+namespace hidden
+{
+
+struct Y
+{
+
+ int m;
+ Y (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+int main ()
+{
+ hidden::Y y(2);
+
+ // unexported hidden::fn@inter is not visible from TPL@inter
+ if (TPL (y) != -2)
+ return 2;
+
+ return 0;
+}
+
+// ADL fails
+// { dg-regexp {[^\n]*/adl-4_a.C:14:[0-9]*: error: 'fn' was not declared in this scope\n} }
diff --git a/gcc/testsuite/g++.dg/modules/adl-5_a.c b/gcc/testsuite/g++.dg/modules/adl-5_a.c
new file mode 100644
index 0000000..5b86922
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-5_a.c
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export template <typename T>
+int TPL (T const &t)
+{
+ return frob (t);
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-5_b.C b/gcc/testsuite/g++.dg/modules/adl-5_b.C
new file mode 100644
index 0000000..3c64cd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-5_b.C
@@ -0,0 +1,22 @@
+// { dg-additional-options -fmodules-ts }
+
+export module hidden;
+// { dg-module-cmi hidden }
+
+export struct X
+{
+ int m;
+
+ X(int m) :m(m) {}
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+// Not found via any ADL outside of module hidden
+int frob (int x)
+{
+ return x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-5_c.C b/gcc/testsuite/g++.dg/modules/adl-5_c.C
new file mode 100644
index 0000000..e047aec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-5_c.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+module hidden;
+import foo;
+
+int frob ()
+{
+ X x (2);
+
+ if (frob (x) != 2)
+ return 1;
+
+ if (TPL (x) != 2)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/adl-5_d.C b/gcc/testsuite/g++.dg/modules/adl-5_d.C
new file mode 100644
index 0000000..9c75b6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/adl-5_d.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+import hidden;
+
+int main ()
+{
+ X x (2);
+
+ if (frob (x) != 2)
+ return 1;
+
+ if (TPL (x) != 2)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/alias-1_a.H b/gcc/testsuite/g++.dg/modules/alias-1_a.H
new file mode 100644
index 0000000..8c56836
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-1_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodule-header -isystem [srcdir]" }
+// { dg-module-cmi {} }
+
+#ifndef ALIAS_1_A
+#define ALIAS_1_A
+
+int frob ();
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/alias-1_b.C b/gcc/testsuite/g++.dg/modules/alias-1_b.C
new file mode 100644
index 0000000..b3d7c2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-1_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]" }
+
+// Alias at the header file. We have one CMI file
+import "alias-1_a.H";
+import <alias-1_a.H>;
+
+int main ()
+{
+ frob ();
+}
+
+// { dg-final { scan-lang-dump-times {CMI is } 1 module } }
diff --git a/gcc/testsuite/g++.dg/modules/alias-1_c.C b/gcc/testsuite/g++.dg/modules/alias-1_c.C
new file mode 100644
index 0000000..6f9f1aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-1_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-module-cmi bob }
+
+export module bob;
+import "alias-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/alias-1_d.C b/gcc/testsuite/g++.dg/modules/alias-1_d.C
new file mode 100644
index 0000000..9b481e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-1_d.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-module-cmi kevin }
+
+export module kevin;
+import <alias-1_a.H>;
diff --git a/gcc/testsuite/g++.dg/modules/alias-1_e.C b/gcc/testsuite/g++.dg/modules/alias-1_e.C
new file mode 100644
index 0000000..862ae32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-1_e.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+
+import bob;
+import kevin;
diff --git a/gcc/testsuite/g++.dg/modules/alias-1_f.C b/gcc/testsuite/g++.dg/modules/alias-1_f.C
new file mode 100644
index 0000000..4c694d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-1_f.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]" }
+
+import kevin;
+import bob;
diff --git a/gcc/testsuite/g++.dg/modules/alias-2_a.H b/gcc/testsuite/g++.dg/modules/alias-2_a.H
new file mode 100644
index 0000000..1befe85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-2_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodule-header -isystem [srcdir]/sys" }
+// { dg-module-cmi {} }
+// { dg-module-headers test sys/alias-2_a.H }
+#ifndef ALIAS_2_A
+#define ALIAS_2_A
+
+int frob ();
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/alias-2_b.C b/gcc/testsuite/g++.dg/modules/alias-2_b.C
new file mode 100644
index 0000000..00eff59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/alias-2_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]/sys" }
+
+// These find different headers
+import "alias-2_a.H";
+import <alias-2_a.H>;
+
+int main ()
+{
+ frob ();
+ frob (1);
+}
+
+// { dg-final { scan-lang-dump-times {CMI is} 2 module } }
diff --git a/gcc/testsuite/g++.dg/modules/align-type-1_a.C b/gcc/testsuite/g++.dg/modules/align-type-1_a.C
new file mode 100644
index 0000000..7124034
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/align-type-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export using aint = __attribute__ ((aligned(16))) int;
+
+
diff --git a/gcc/testsuite/g++.dg/modules/align-type-1_b.C b/gcc/testsuite/g++.dg/modules/align-type-1_b.C
new file mode 100644
index 0000000..8372e6f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/align-type-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct B
+{
+ aint m;
+};
+
+static_assert (alignof (B) == 16);
diff --git a/gcc/testsuite/g++.dg/modules/ambig-1_a.C b/gcc/testsuite/g++.dg/modules/ambig-1_a.C
new file mode 100644
index 0000000..fbb3db2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ambig-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+export module One;
+// { dg-module-cmi One }
+
+export int foo ();
+export char bax ();
+export int quux (float);
+
+
diff --git a/gcc/testsuite/g++.dg/modules/ambig-1_b.C b/gcc/testsuite/g++.dg/modules/ambig-1_b.C
new file mode 100644
index 0000000..c1de919
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ambig-1_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+import One;
+
+int foo (); // { dg-error "conflicts with import" }
+int bax (); // { dg-error "ambiguating new declaration" }
+int quux (int);
diff --git a/gcc/testsuite/g++.dg/modules/anon-1_a.C b/gcc/testsuite/g++.dg/modules/anon-1_a.C
new file mode 100644
index 0000000..e56b85c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/anon-1_a.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+
+export module anon;
+// { dg-module-cmi anon }
+
+export struct foo
+{
+ enum {bob};
+ union
+ {
+ int i;
+ float f;
+ };
+};
diff --git a/gcc/testsuite/g++.dg/modules/anon-1_b.C b/gcc/testsuite/g++.dg/modules/anon-1_b.C
new file mode 100644
index 0000000..66d2505
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/anon-1_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+export module namer;
+// { dg-module-cmi namer }
+
+import anon;
+
+export inline int &get_int (foo &obj)
+{
+ return obj.i;
+}
+
+export inline float &get_float (foo &obj)
+{
+ return obj.f;
+}
+
+
diff --git a/gcc/testsuite/g++.dg/modules/anon-1_c.C b/gcc/testsuite/g++.dg/modules/anon-1_c.C
new file mode 100644
index 0000000..cbe89e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/anon-1_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+
+import namer;
+import anon;
+
+int main ()
+{
+ foo obj;
+ int *ip = &get_int (obj);
+ float *fp = &get_float (obj);
+
+ return !((void *)ip == (void *)fp);
+}
diff --git a/gcc/testsuite/g++.dg/modules/anon-2.h b/gcc/testsuite/g++.dg/modules/anon-2.h
new file mode 100644
index 0000000..81c793c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/anon-2.h
@@ -0,0 +1,6 @@
+
+
+struct __pthread_cond_s
+{
+ union {};
+};
diff --git a/gcc/testsuite/g++.dg/modules/anon-2_a.H b/gcc/testsuite/g++.dg/modules/anon-2_a.H
new file mode 100644
index 0000000..6861c19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/anon-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "anon-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/anon-2_b.C b/gcc/testsuite/g++.dg/modules/anon-2_b.C
new file mode 100644
index 0000000..24bb61b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/anon-2_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "anon-2.h"
+import "anon-2_a.H";
+
diff --git a/gcc/testsuite/g++.dg/modules/atom-decl-0_a.C b/gcc/testsuite/g++.dg/modules/atom-decl-0_a.C
new file mode 100644
index 0000000..d226f32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-decl-0_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module thing;
+// { dg-module-cmi "thing" }
+
+export int baz ();
diff --git a/gcc/testsuite/g++.dg/modules/atom-decl-0_b.C b/gcc/testsuite/g++.dg/modules/atom-decl-0_b.C
new file mode 100644
index 0000000..8ca006d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-decl-0_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+import thing;
+
+void bink ()
+{
+ baz ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/atom-decl-0_c.C b/gcc/testsuite/g++.dg/modules/atom-decl-0_c.C
new file mode 100644
index 0000000..96e7495
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-decl-0_c.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+export module pop;
+// { dg-module-cmi "pop" }
+export import thing;
+
+void bink ();
+
+void bonk ()
+{
+ baz ();
+ bink ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/atom-decl-2.C b/gcc/testsuite/g++.dg/modules/atom-decl-2.C
new file mode 100644
index 0000000..b463dc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-decl-2.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+export module thing;
+int i;
+import baz; // { dg-error "must be contiguous" }
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/atom-decl-3.C b/gcc/testsuite/g++.dg/modules/atom-decl-3.C
new file mode 100644
index 0000000..6eb6e6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-decl-3.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+int i;
+import bazza;
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/atom-pragma-1.C b/gcc/testsuite/g++.dg/modules/atom-pragma-1.C
new file mode 100644
index 0000000..133382e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-pragma-1.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+#pragma bob
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/atom-pragma-3.C b/gcc/testsuite/g++.dg/modules/atom-pragma-3.C
new file mode 100644
index 0000000..b95b2c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-pragma-3.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+export module foo;
+// { dg-module-cmi !foo }
+;
+
+#pragma pack(2)
+import baz; // { dg-error "must be contiguous" }
+
+int i;
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-1.C b/gcc/testsuite/g++.dg/modules/atom-preamble-1.C
new file mode 100644
index 0000000..1161d41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-1.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+#define EXPORT export // { dg-error "only occur after a module" }
+EXPORT module bob; // { dg-error "does not name a type" }
+// { dg-message "not recognized as" "" { target *-*-* } .-1 }
+
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C b/gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C
new file mode 100644
index 0000000..02fbd84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+#define malcolm kevin
+export module malcolm;
+// { dg-module-cmi kevin }
+
+export class X;
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-2_b.C b/gcc/testsuite/g++.dg/modules/atom-preamble-2_b.C
new file mode 100644
index 0000000..a97d975
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-2_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+#if 1
+export module bob;
+// { dg-module-cmi bob }
+#endif
+
+import kevin;
+
+X *f;
+
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-2_c.C b/gcc/testsuite/g++.dg/modules/atom-preamble-2_c.C
new file mode 100644
index 0000000..d3804c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-2_c.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+#pragma bob
+
+import kevin;
+
+X *f;
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-2_d.C b/gcc/testsuite/g++.dg/modules/atom-preamble-2_d.C
new file mode 100644
index 0000000..0c3b290
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-2_d.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+import kevin;
+
+#if 1
+#if 1
+import kevin;
+#endif
+#elif 1
+int i;
+#endif
+
+int j; // end here
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-2_e.C b/gcc/testsuite/g++.dg/modules/atom-preamble-2_e.C
new file mode 100644
index 0000000..074f8eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-2_e.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+import kevin;
+
+#if 0
+#if 1
+import kevin;
+#endif
+#elif 1
+import kevin;
+#endif
+
+int i; // end here
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-2_f.C b/gcc/testsuite/g++.dg/modules/atom-preamble-2_f.C
new file mode 100644
index 0000000..28e54b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-2_f.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+export module stuart;
+// { dg-module-cmi !stuart }
+
+# 6 "atom-preamble-2_f.C" 1
+import kevin; // { dg-error "not be from header" }
+# 8 "" 2
+
+import kevin; // ok
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-3.C b/gcc/testsuite/g++.dg/modules/atom-preamble-3.C
new file mode 100644
index 0000000..74dba7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-3.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+#define import import
+import malcolm; // { dg-error "object-like macro" }
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+
+// { dg-prune-output "compilation terminated" }
+// { dg-prune-output "fatal error:" }
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-4.C b/gcc/testsuite/g++.dg/modules/atom-preamble-4.C
new file mode 100644
index 0000000..21a8d57
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-4.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+#define NAME(X) X;
+
+export module NAME(bob)
+
diff --git a/gcc/testsuite/g++.dg/modules/auto-1.h b/gcc/testsuite/g++.dg/modules/auto-1.h
new file mode 100644
index 0000000..f8ae751
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-1.h
@@ -0,0 +1,19 @@
+
+template <typename T> auto frob (T t)
+{
+ return t;
+}
+
+struct Bob
+{
+ operator auto ()
+ {
+ return 0;
+ }
+};
+
+inline auto foo ()
+{
+ return frob (1) + int (Bob ());
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/auto-1_a.H b/gcc/testsuite/g++.dg/modules/auto-1_a.H
new file mode 100644
index 0000000..4d3bc77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "auto-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/auto-1_b.C b/gcc/testsuite/g++.dg/modules/auto-1_b.C
new file mode 100644
index 0000000..9635066
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "auto-1.h"
+import "auto-1_a.H";
+
+int bar ()
+{
+ return foo () + frob (0u);
+}
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/auto-2.h b/gcc/testsuite/g++.dg/modules/auto-2.h
new file mode 100644
index 0000000..4759ab8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-2.h
@@ -0,0 +1,13 @@
+
+template<typename _Callable>
+struct _RangeAdaptor
+{
+ constexpr _RangeAdaptor(const _Callable &) { }
+};
+
+template<typename _Callable>
+_RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>;
+
+template<unsigned _Nm>
+inline constexpr _RangeAdaptor elements = [] (auto&& __r) {};
+
diff --git a/gcc/testsuite/g++.dg/modules/auto-2_a.H b/gcc/testsuite/g++.dg/modules/auto-2_a.H
new file mode 100644
index 0000000..46bd746
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "auto-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/auto-2_b.C b/gcc/testsuite/g++.dg/modules/auto-2_b.C
new file mode 100644
index 0000000..5ed882f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-2_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -fconcepts -fdump-lang-module-alias -fno-module-lazy" }
+
+#include "auto-2.h"
+import "auto-2_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-1.C b/gcc/testsuite/g++.dg/modules/bad-mapper-1.C
new file mode 100644
index 0000000..7ed75b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bad-mapper-1.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|this-will-not-work" }
+import unique1.bob;
+// { dg-error "-:failed exec.*mapper.* .*this-will-not-work" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-2.C b/gcc/testsuite/g++.dg/modules/bad-mapper-2.C
new file mode 100644
index 0000000..f35d16b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bad-mapper-2.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=not-a-host:3838" }
+import unique2.bob;
+// { dg-error "failed .* mapper 'not-a-host" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-3.C b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
new file mode 100644
index 0000000..9dab332
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=localhost:172477262" }
+import unique3.bob;
+// { dg-error {failed connecting mapper 'localhost:172477262'} "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/ben-1.map b/gcc/testsuite/g++.dg/modules/ben-1.map
new file mode 100644
index 0000000..182183a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ben-1.map
@@ -0,0 +1,3 @@
+$root .
+module:import partitions/module:import.mod
+module module.mod
diff --git a/gcc/testsuite/g++.dg/modules/ben-1_a.C b/gcc/testsuite/g++.dg/modules/ben-1_a.C
new file mode 100644
index 0000000..7e9b566
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ben-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/ben-1.map" }
+// { dg-additional-files ben-1.map }
+
+export module module:import;
+// { dg-module-cmi =partitions/module:import.mod }
+
+export int b() {
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/ben-1_b.C b/gcc/testsuite/g++.dg/modules/ben-1_b.C
new file mode 100644
index 0000000..e16fa2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ben-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/ben-1.map" }
+// { dg-additional-files ben-1.map }
+
+export module module;
+// { dg-module-cmi =module.mod }
+export import :import;
+
+export int c ()
+{
+ return b ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/bfield-1_a.C b/gcc/testsuite/g++.dg/modules/bfield-1_a.C
new file mode 100644
index 0000000..15b8cb6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bfield-1_a.C
@@ -0,0 +1,15 @@
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export struct timex
+{
+ int a;
+ int :32;
+ int :32;
+ int :32;
+ int :32;
+ int :32;
+ int :32;
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/bfield-1_b.C b/gcc/testsuite/g++.dg/modules/bfield-1_b.C
new file mode 100644
index 0000000..6c8dae6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bfield-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodules-ts }
+import foo;
+
+timex v = {1};
diff --git a/gcc/testsuite/g++.dg/modules/bfield-2_a.C b/gcc/testsuite/g++.dg/modules/bfield-2_a.C
new file mode 100644
index 0000000..5329e62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bfield-2_a.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct ting
+{
+ int a;
+ int b : 3;
+ int c : 5;
+};
diff --git a/gcc/testsuite/g++.dg/modules/bfield-2_b.C b/gcc/testsuite/g++.dg/modules/bfield-2_b.C
new file mode 100644
index 0000000..7371736
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bfield-2_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodules-ts }
+import foo;
+
+ting v = {1, 2, 3};
diff --git a/gcc/testsuite/g++.dg/modules/bool-1.h b/gcc/testsuite/g++.dg/modules/bool-1.h
new file mode 100644
index 0000000..80f0ec1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bool-1.h
@@ -0,0 +1,8 @@
+typedef signed char __v16qs __attribute__ ((__vector_size__ (16)));
+
+
+inline auto
+_mm_cmplt_epi8 (__v16qs __A, __v16qs __B)
+{
+ return __A < __B;
+}
diff --git a/gcc/testsuite/g++.dg/modules/bool-1_a.H b/gcc/testsuite/g++.dg/modules/bool-1_a.H
new file mode 100644
index 0000000..3b4232c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bool-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options {-fmodule-header -Wno-psabi} }
+// { dg-module-cmi {} }
+
+#include "bool-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/bool-1_b.H b/gcc/testsuite/g++.dg/modules/bool-1_b.H
new file mode 100644
index 0000000..d22e1d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bool-1_b.H
@@ -0,0 +1,5 @@
+// { dg-additional-options {-fmodule-header -fno-module-lazy -Wno-psabi} }
+// { dg-module-cmi {} }
+
+#include "bool-1.h"
+import "bool-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/bool-1_c.C b/gcc/testsuite/g++.dg/modules/bool-1_c.C
new file mode 100644
index 0000000..01b0877
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bool-1_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options {-fmodules-ts -Wno-psabi} }
+
+import "bool-1_b.H";
+
+void frob (signed char __attribute__ ((__vector_size__ (16))) arg)
+{
+ _mm_cmplt_epi8 (arg, arg);
+}
diff --git a/gcc/testsuite/g++.dg/modules/bug-1_a.C b/gcc/testsuite/g++.dg/modules/bug-1_a.C
new file mode 100644
index 0000000..b828b7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bug-1_a.C
@@ -0,0 +1,9 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export int Frob (int a)
+{
+ return -a;
+}
diff --git a/gcc/testsuite/g++.dg/modules/bug-1_b.C b/gcc/testsuite/g++.dg/modules/bug-1_b.C
new file mode 100644
index 0000000..7b5baeb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bug-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int main ()
+{
+ if (Frob (2) != -2)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/builtin-1_a.C b/gcc/testsuite/g++.dg/modules/builtin-1_a.C
new file mode 100644
index 0000000..6d0731a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-1_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias-uid" }
+export module builtin;
+// { dg-module-cmi builtin }
+
+export inline void ary_del (int *ptr)
+{
+ delete[] ptr;
+}
+
+export inline void scalar_del (int *ptr)
+{
+ delete ptr;
+}
+
+// { dg-final { scan-lang-dump {Wrote GMF:-[0-9]* function_decl:'::operator delete'@builtin} module } }
+// { dg-final { scan-lang-dump {Wrote GMF:-[0-9]* function_decl:'::operator delete \[\]'@builtin} module } }
+
+// { dg-final { scan-lang-dump {Writing named:-[0-9]* function_decl:'::operator delete'\n *Wrote[^\n]*\n *Writing:-[0-9]*'s named merge key \(decl\) function_decl:'::operator delete'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/builtin-1_b.C b/gcc/testsuite/g++.dg/modules/builtin-1_b.C
new file mode 100644
index 0000000..e9f7348
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-1_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+import builtin;
+
+int main ()
+{
+ ary_del (nullptr);
+ scalar_del (nullptr);
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::operator delete \[\]'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::operator delete'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/builtin-2.C b/gcc/testsuite/g++.dg/modules/builtin-2.C
new file mode 100644
index 0000000..f9de98f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-2.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+
+extern "C"
+{
+ extern int printf (const char *__restrict __format, ...);
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/builtin-3_b.C b/gcc/testsuite/g++.dg/modules/builtin-3_b.C
new file mode 100644
index 0000000..93489bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-3_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+import builtins;
+
+int main ()
+{
+ length ("");
+ count (1, "", "", nullptr);
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::__builtin_strlen'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) type_decl:'::__builtin_va_list'} module { target { x86_64-*-linux* } } } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) type_decl:'::va_list'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) type_decl:'::__gnuc_va_list'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/builtin-4_a.H b/gcc/testsuite/g++.dg/modules/builtin-4_a.H
new file mode 100644
index 0000000..f7bc6af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-4_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+void* operator new(__SIZE_TYPE__);
+void* operator new[](__SIZE_TYPE__);
+
+void operator delete (void*) noexcept;
+void operator delete[](void*) noexcept;
+
diff --git a/gcc/testsuite/g++.dg/modules/builtin-4_b.C b/gcc/testsuite/g++.dg/modules/builtin-4_b.C
new file mode 100644
index 0000000..1d780e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-4_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "builtin-4_a.H";
+
+int main ()
+{
+ operator delete (operator new (10));
+ operator delete[] (operator new[] (10));
+}
+
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator new'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator delete'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator new \[\]'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator delete \[\]'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/builtin-5_a.H b/gcc/testsuite/g++.dg/modules/builtin-5_a.H
new file mode 100644
index 0000000..735d323
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-5_a.H
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+extern "C" int printf (char const *, ...);
diff --git a/gcc/testsuite/g++.dg/modules/builtin-5_b.C b/gcc/testsuite/g++.dg/modules/builtin-5_b.C
new file mode 100644
index 0000000..bfaa64f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-5_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+import "builtin-5_a.H";
+
+void foo ()
+{
+ printf ("bob\n");
+}
+
+extern "C" int printf (char const *, int);
+
+// { dg-regexp {[^\n]*builtin-5_b.C:10:[0-9]*: error: conflicting declaration of C function 'int printf\(const char\*, int\)'\nIn module [^\n]*builtin-5_a.H, imported at [^\n]*builtin-5_b.C:3:\n[^\n]*builtin-5_a.H:3:[0-9]*: note: previous declaration 'int printf\(const char\*, ...\)'} }
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) function_decl:'::printf'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/builtin-6_a.H b/gcc/testsuite/g++.dg/modules/builtin-6_a.H
new file mode 100644
index 0000000..b3263bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-6_a.H
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C" {
+
+static double sin (double)
+{
+ // extra small angle approximation :)
+ return 0.0;
+}
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/builtin-6_b.C b/gcc/testsuite/g++.dg/modules/builtin-6_b.C
new file mode 100644
index 0000000..80f8dc6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-6_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+
+import "builtin-6_a.H";
+
+int main ()
+{
+ return sin (0.0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/builtin-7_a.H b/gcc/testsuite/g++.dg/modules/builtin-7_a.H
new file mode 100644
index 0000000..a98a7b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-7_a.H
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module_cmi {} }
+
+extern "C"
+{
+extern double nan(const char *);
+inline long double nanl(const char * __x) { return nan(__x); }
+}
diff --git a/gcc/testsuite/g++.dg/modules/builtin-7_b.C b/gcc/testsuite/g++.dg/modules/builtin-7_b.C
new file mode 100644
index 0000000..2851457
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/builtin-7_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "builtin-7_a.H";
+
+void f ()
+{
+ nanl ("");
+}
diff --git a/gcc/testsuite/g++.dg/modules/by-name-1.C b/gcc/testsuite/g++.dg/modules/by-name-1.C
new file mode 100644
index 0000000..44eb447
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/by-name-1.C
@@ -0,0 +1,15 @@
+// check internals by name unless SCC
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+class X
+{
+ int i;
+};
+
+export X *f ();
+
+// { dg-final { scan-lang-dump {Wrote purview:-[0-9]* type_decl:'::X'} "module" } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::X'} "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/cexpr-1_a.C b/gcc/testsuite/g++.dg/modules/cexpr-1_a.C
new file mode 100644
index 0000000..b9c4b16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cexpr-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Const;
+// { dg-module-cmi "Const" }
+
+export constexpr int SQ (int b)
+{
+ return b * b;
+}
diff --git a/gcc/testsuite/g++.dg/modules/cexpr-1_b.C b/gcc/testsuite/g++.dg/modules/cexpr-1_b.C
new file mode 100644
index 0000000..3056611
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cexpr-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts" }
+import Const;
+
+static_assert (SQ(88) == 88 * 88, "waaa!");
diff --git a/gcc/testsuite/g++.dg/modules/cexpr-2_a.C b/gcc/testsuite/g++.dg/modules/cexpr-2_a.C
new file mode 100644
index 0000000..632a4e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cexpr-2_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts" }
+export module sqrt;
+// { dg-module-cmi "sqrt" }
+
+export constexpr unsigned sqrt (unsigned X, unsigned x = 1)
+{
+ // Newton-Raphson, not binary restoring
+ // x <= x - f(x)/f'(x)
+ // f(x) = x^2 - X
+ // f'(x) = 2x
+ // x <= x - (x^2 - X) / 2x
+ // x <= x - x/2 + X/2x
+ // x <= x/2 + X/2x
+ // x <= 1/2(x + X/x)
+ unsigned nx = (x + X/x) / 2;
+ if (nx != x)
+ nx = sqrt (X, nx);
+ return nx;
+}
diff --git a/gcc/testsuite/g++.dg/modules/cexpr-2_b.C b/gcc/testsuite/g++.dg/modules/cexpr-2_b.C
new file mode 100644
index 0000000..6a589ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cexpr-2_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts" }
+import sqrt;
+
+static_assert (sqrt(81) == 9, "waaa!");
diff --git a/gcc/testsuite/g++.dg/modules/circ-1_a.C b/gcc/testsuite/g++.dg/modules/circ-1_a.C
new file mode 100644
index 0000000..fa56c78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/circ-1_a.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Bob;
+// { dg-module-cmi Bob }
+
+export int bob ();
diff --git a/gcc/testsuite/g++.dg/modules/circ-1_b.C b/gcc/testsuite/g++.dg/modules/circ-1_b.C
new file mode 100644
index 0000000..9174c15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/circ-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Kevin;
+// { dg-module-cmi Kevin }
+
+import Bob;
+
+export int kevin ();
diff --git a/gcc/testsuite/g++.dg/modules/circ-1_c.C b/gcc/testsuite/g++.dg/modules/circ-1_c.C
new file mode 100644
index 0000000..cea17d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/circ-1_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Bob; // { dg-message "declared here" }
+// No need to dg-module-cmi
+
+import Kevin;
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+// { dg-error "cannot import module" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/circ-1_d.C b/gcc/testsuite/g++.dg/modules/circ-1_d.C
new file mode 100644
index 0000000..b6f6b7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/circ-1_d.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+module;
+import Kevin;
+
+export module Bob; // { dg-error "module already imported" }
+// { dg-message "imported here" "Kevin.nms:" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/modules/class-1_a.C b/gcc/testsuite/g++.dg/modules/class-1_a.C
new file mode 100644
index 0000000..6463719
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-1_a.C
@@ -0,0 +1,15 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+namespace Bob
+{
+ struct X;
+ export struct Y {
+ unsigned a;
+ unsigned b;
+ };
+}
+
+export void copy (Bob::Y *, const Bob::Y *);
diff --git a/gcc/testsuite/g++.dg/modules/class-1_b.C b/gcc/testsuite/g++.dg/modules/class-1_b.C
new file mode 100644
index 0000000..5eac51d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-1_b.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+struct Bob::X
+{
+ int i;
+};
+
+
+int x = sizeof (Bob::X);
+
+void copy (Bob::Y *dst, Bob::Y const *src)
+{
+ dst->a = src->a;
+ dst->b = src->b;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-1_c.C b/gcc/testsuite/g++.dg/modules/class-1_c.C
new file mode 100644
index 0000000..8e23c4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-1_c.C
@@ -0,0 +1,35 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int y = sizeof (Bob::Y);
+
+unsigned Foo (Bob::Y *ptr)
+{
+ return ptr->a + ptr->b;
+}
+
+int main ()
+{
+ if (y != 2 * sizeof (int))
+ return 1;
+
+ unsigned pun[4];
+ pun[0] = 0xdeadbeef;
+ pun[1] = 0xfeedface;
+ pun[2] = 0x8badf00d;
+ pun[3] = 0xcafed00d;
+
+ copy ((Bob::Y *)pun, (Bob::Y *)&pun[2]);
+
+ if (pun[0] != 0x8badf00d)
+ return 2;
+ if (pun[1] != 0xcafed00d)
+ return 3;
+ if (pun[2] != 0x8badf00d)
+ return 4;
+
+ if (Foo ((Bob::Y *)&pun[1]) != 0xcafed00d + 0x8badf00d)
+ return 5;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-2_a.C b/gcc/testsuite/g++.dg/modules/class-2_a.C
new file mode 100644
index 0000000..04f11cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-2_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+// This sequence is for errors
+
+export module One;
+// { dg-module-cmi "One" }
+
+namespace Bob
+{
+ struct X;
+ export struct Y {
+ unsigned a;
+ unsigned b;
+ };
+}
+
+export void copy (Bob::Y *, const Bob::Y *);
diff --git a/gcc/testsuite/g++.dg/modules/class-2_b.C b/gcc/testsuite/g++.dg/modules/class-2_b.C
new file mode 100644
index 0000000..0f8edb8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-2_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int z = sizeof (Bob::X); // { dg-error "not a member of .Bob." }
diff --git a/gcc/testsuite/g++.dg/modules/class-3_a.C b/gcc/testsuite/g++.dg/modules/class-3_a.C
new file mode 100644
index 0000000..c775f7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-3_a.C
@@ -0,0 +1,15 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct X
+{
+ X (int, int);
+ X (int a_)
+ : a(a_), b (a_ << 16)
+ {
+ }
+ int a;
+ int b;
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-3_b.C b/gcc/testsuite/g++.dg/modules/class-3_b.C
new file mode 100644
index 0000000..0e07e88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-3_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+export module Two;
+
+export import One;
+
+export inline void Frob (X &q)
+{
+ q.b = q.a;
+}
+
+// { dg-final { scan-lang-dump {Wrote import:-1 type_decl:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Indirect:-2 decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::X@One:.'@One} module } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::X@One:.'@One} module } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Wrote member:-[0-9]* field_decl:'::X@One:.::a'} module } }
+// { dg-final { scan-lang-dump {Wrote member:-[0-9]* field_decl:'::X@One:.::b'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/class-3_c.C b/gcc/testsuite/g++.dg/modules/class-3_c.C
new file mode 100644
index 0000000..6b82d1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-3_c.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+X::X (int a_, int b_)
+ : a (a_), b (b_)
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-3_d.C b/gcc/testsuite/g++.dg/modules/class-3_d.C
new file mode 100644
index 0000000..0710941
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-3_d.C
@@ -0,0 +1,25 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import Two;
+
+int main ()
+{
+ X x (0xdead, 0xbeef);
+
+ if (x.a != 0xdead || x.b != 0xbeef)
+ return 1;
+
+ Frob (x);
+ if (x.b != 0xdead)
+ return 2;
+
+ X y (0xcafe);
+ if (y.a != 0xcafe || y.b != 0xcafe << 16)
+ return 3;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Imported:-1 type_decl:'::X@One:.'@One} module } }
+// { dg-final { scan-lang-dump {Indirect:-2 decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Read member:-[0-9]* field_decl:'::X@One:.::a'} module } }
+// { dg-final { scan-lang-dump {Read member:-[0-9]* field_decl:'::X@One:.::b'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/class-4_a.C b/gcc/testsuite/g++.dg/modules/class-4_a.C
new file mode 100644
index 0000000..a9810ab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-4_a.C
@@ -0,0 +1,25 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ int b;
+
+ base (int b_)
+ : b (b_)
+ {
+ }
+
+};
+
+export struct derived : base
+{
+ int d;
+
+ derived (int b_, int d_)
+ : base (b_), d (d_)
+ {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-4_b.C b/gcc/testsuite/g++.dg/modules/class-4_b.C
new file mode 100644
index 0000000..1cd3998
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-4_b.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int main ()
+{
+ base b (0xfeed);
+ if (!(b.b == 0xfeed))
+ return 1;
+
+ derived d (0xcafe, 0xbeef);
+ if (!(d.b == 0xcafe && d.d == 0xbeef))
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-5_a.C b/gcc/testsuite/g++.dg/modules/class-5_a.C
new file mode 100644
index 0000000..417cb6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-5_a.C
@@ -0,0 +1,16 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ int b;
+
+ base (int b_)
+ : b (b_)
+ {
+ }
+
+ virtual int getter () const;
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-5_b.C b/gcc/testsuite/g++.dg/modules/class-5_b.C
new file mode 100644
index 0000000..89db01c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-5_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+int base::getter () const
+{
+ return b;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-5_c.C b/gcc/testsuite/g++.dg/modules/class-5_c.C
new file mode 100644
index 0000000..ee3250d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-5_c.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int vcall (base *ptr)
+{
+ return ptr->getter ();
+}
+
+int main ()
+{
+ base b (0xfeed);
+
+ if (!(vcall (&b) == 0xfeed))
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-6_a.C b/gcc/testsuite/g++.dg/modules/class-6_a.C
new file mode 100644
index 0000000..9c117c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-6_a.C
@@ -0,0 +1,30 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ int b;
+
+ base (int b_)
+ : b (b_)
+ {
+ }
+
+ virtual int getter () const;
+};
+
+export struct pad
+{
+ int pad;
+ virtual ~pad ();
+};
+
+export struct derived : pad, virtual base
+{
+ derived (int v)
+ :base (v)
+ {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-6_b.C b/gcc/testsuite/g++.dg/modules/class-6_b.C
new file mode 100644
index 0000000..1a49ced
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-6_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+pad::~pad ()
+{
+}
+
+int base::getter () const
+{
+ return b;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-6_c.C b/gcc/testsuite/g++.dg/modules/class-6_c.C
new file mode 100644
index 0000000..4d3abf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-6_c.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int vcall (derived *ptr)
+{
+ return ptr->getter ();
+}
+
+int main ()
+{
+ derived b (0xfeed);
+
+ if (!(vcall (&b) == 0xfeed))
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-7_a.C b/gcc/testsuite/g++.dg/modules/class-7_a.C
new file mode 100644
index 0000000..20fd54b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-7_a.C
@@ -0,0 +1,19 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ long long b;
+
+ base (int b_)
+ :b (b_)
+ {
+ }
+
+ base ()
+ :b(99)
+ {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-7_b.C b/gcc/testsuite/g++.dg/modules/class-7_b.C
new file mode 100644
index 0000000..3ed936f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-7_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Two;
+// { dg-module-cmi "Two" }
+import One;
+
+export struct middle : virtual base
+{
+ long long m;
+
+ middle (int b_, int m_)
+ : base (b_), m (m_)
+ {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-7_c.C b/gcc/testsuite/g++.dg/modules/class-7_c.C
new file mode 100644
index 0000000..d1f2f56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-7_c.C
@@ -0,0 +1,39 @@
+// { dg-additional-options "-fmodules-ts" }
+import One;
+import Two;
+
+struct derived : middle
+{
+ long long d;
+
+ derived (int b_, int m_, int d_)
+ : middle (b_, m_), d (d_)
+ {
+ }
+};
+
+int check (derived *d)
+{
+ if ((char *)&d->b != (char *)&d->d + sizeof (long long))
+ return 3;
+ if ((char *)&d->d != (char *)&d->m + sizeof (long long))
+ return 4;
+ return 0;
+}
+
+
+int main ()
+{
+ middle m (1, 2);
+
+
+ if (m.b != 1 || m.m != 2)
+ return 1;
+
+ derived d (1, 2, 3);
+
+ if (d.b != 99 || d.m != 2 || d.d != 3)
+ return 2;
+
+ return check (&d);
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-8_a.C b/gcc/testsuite/g++.dg/modules/class-8_a.C
new file mode 100644
index 0000000..53caa5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-8_a.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+class A;
+
+class B
+{
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-8_b.C b/gcc/testsuite/g++.dg/modules/class-8_b.C
new file mode 100644
index 0000000..0bb01ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-8_b.C
@@ -0,0 +1,23 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+module foo;
+
+// completes class A from interface
+class A
+{
+};
+
+void bill ()
+{
+ A a;
+}
+
+// redeclaration of class B{} from interface
+class B;
+
+void bob ()
+{
+ B b;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::A'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::B'@'foo' section:} module } }
diff --git a/gcc/testsuite/g++.dg/modules/clone-1_a.C b/gcc/testsuite/g++.dg/modules/clone-1_a.C
new file mode 100644
index 0000000..43c4bbd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/clone-1_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _CharT >
+struct basic_string
+{
+ template<typename = unsigned> basic_string();
+};
+
+inline basic_string<char>
+to_string ()
+{
+ basic_string<char> __str;
+
+ return __str;
+}
diff --git a/gcc/testsuite/g++.dg/modules/clone-1_b.C b/gcc/testsuite/g++.dg/modules/clone-1_b.C
new file mode 100644
index 0000000..a013b9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/clone-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void frob ()
+{
+ to_string ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/concept-1_a.C b/gcc/testsuite/g++.dg/modules/concept-1_a.C
new file mode 100644
index 0000000..1b4d831
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-1_a.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T>
+requires (!!sizeof (bool (T{})))
+T f1 (T x)
+{ return x; }
+
diff --git a/gcc/testsuite/g++.dg/modules/concept-1_b.C b/gcc/testsuite/g++.dg/modules/concept-1_b.C
new file mode 100644
index 0000000..d6542e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-1_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+import foo;
+
+struct X {};
+
+void foo (int i, X &x)
+{
+ f1 (i); // ok
+ f1 (x); // { dg-error "no match" }
+}
+
+// { dg-regexp {[^\n]*concept-1_a.C:7:[0-9]*: error: invalid cast[^\n]*\n} }
diff --git a/gcc/testsuite/g++.dg/modules/concept-2_a.C b/gcc/testsuite/g++.dg/modules/concept-2_a.C
new file mode 100644
index 0000000..b1d477d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-2_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T>
+requires (sizeof (T) == 1)
+ char f1 (T x) { return 0; }
+
+export template<typename T>
+requires (sizeof (T) != 1)
+ int f1 (T x) { return 0; }
+
+void foo (int i, char c)
+{
+ static_assert (sizeof (f1 (i)) == sizeof (int));
+ static_assert (sizeof (f1 (c)) == sizeof (char));
+}
diff --git a/gcc/testsuite/g++.dg/modules/concept-2_b.C b/gcc/testsuite/g++.dg/modules/concept-2_b.C
new file mode 100644
index 0000000..af0ab3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-2_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+import foo;
+
+void foo (int i, char c)
+{
+ static_assert (sizeof (f1 (i)) == sizeof (int));
+ static_assert (sizeof (f1 (c)) == sizeof (char));
+}
diff --git a/gcc/testsuite/g++.dg/modules/concept-3_a.C b/gcc/testsuite/g++.dg/modules/concept-3_a.C
new file mode 100644
index 0000000..36fc086
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-3_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+export template<typename _Tp>
+concept Addable = requires(_Tp& __t)
+ {
+ __t + __t;
+ };
+}
diff --git a/gcc/testsuite/g++.dg/modules/concept-3_b.C b/gcc/testsuite/g++.dg/modules/concept-3_b.C
new file mode 100644
index 0000000..46bfe03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-3_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+import foo;
+
+template <foo::Addable T> T Add (T a, T b)
+{
+ return a + b;
+}
+
+void frob ()
+{
+ Add (1, 2);
+ Add ((int *)0, (int *)0); // { dg-error "no match" }
+}
diff --git a/gcc/testsuite/g++.dg/modules/concept-4.H b/gcc/testsuite/g++.dg/modules/concept-4.H
new file mode 100644
index 0000000..66d1201
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-4.H
@@ -0,0 +1,18 @@
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline constexpr bool disable = false;
+
+template<typename U>
+concept sized = true;
+
+template<typename V>
+class TPL
+{
+};
+
+template<typename W>
+requires (!sized<W>)
+inline constexpr bool disable<TPL<W>>
+= true;
diff --git a/gcc/testsuite/g++.dg/modules/concept-5.h b/gcc/testsuite/g++.dg/modules/concept-5.h
new file mode 100644
index 0000000..1b049f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-5.h
@@ -0,0 +1,7 @@
+template<typename T>
+requires (sizeof (T) == 1)
+constexpr int f1 (T x) { return 1; }
+
+template<typename T>
+requires (sizeof (T) != 1)
+constexpr int f1 (T x) { return 0; }
diff --git a/gcc/testsuite/g++.dg/modules/concept-5_a.H b/gcc/testsuite/g++.dg/modules/concept-5_a.H
new file mode 100644
index 0000000..f38febe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-5_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "concept-5.h"
diff --git a/gcc/testsuite/g++.dg/modules/concept-5_b.C b/gcc/testsuite/g++.dg/modules/concept-5_b.C
new file mode 100644
index 0000000..6a196d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-5_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fconcepts -fdump-lang-module-alias" }
+
+#include "concept-5.h"
+import "concept-5_a.H";
+
+static_assert (f1 ('a') == 1);
+static_assert (f1 (0xa) == 0);
+
+// { dg-final { scan-lang-dump-times {named merge key \(matched\) template_decl:'::template f1'} 2 module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/concept-6.h b/gcc/testsuite/g++.dg/modules/concept-6.h
new file mode 100644
index 0000000..0e98c98
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-6.h
@@ -0,0 +1,19 @@
+
+template<typename _Callable>
+struct Base
+{
+ Base (const _Callable &)
+ requires true
+ {}
+};
+
+template<typename _Callable>
+struct Derived : Base<_Callable>
+{
+ using Base<_Callable>::Base;
+};
+
+template<typename _Callable>
+Derived (_Callable) -> Derived<_Callable>;
+
+inline Derived all = [] (auto&& __r) {};
diff --git a/gcc/testsuite/g++.dg/modules/concept-6_a.H b/gcc/testsuite/g++.dg/modules/concept-6_a.H
new file mode 100644
index 0000000..e677531
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-6_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "concept-6.h"
diff --git a/gcc/testsuite/g++.dg/modules/concept-6_b.C b/gcc/testsuite/g++.dg/modules/concept-6_b.C
new file mode 100644
index 0000000..4c2058d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-6_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fconcepts -fdump-lang-module-alias -fno-module-lazy" }
+
+#include "concept-6.h"
+import "concept-6_a.H";
+
+// { dg-final { scan-lang-dump-times {named merge key \(matched\) function_decl:'::Derived<::._anon_0>::__ct '} 6 module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/constrained-partial-1_a.C b/gcc/testsuite/g++.dg/modules/constrained-partial-1_a.C
new file mode 100644
index 0000000..5a5482e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/constrained-partial-1_a.C
@@ -0,0 +1,38 @@
+// { dg-additional-options "-fmodules-ts -std=c++20" }
+
+export module M;
+// { dg-module-cmi M }
+
+export template <typename T0>
+struct traits
+{
+ static constexpr int variant = 0;
+};
+
+// #2
+template <typename T2>
+requires requires { typename T2::element_type; }
+struct traits<T2 *>
+{
+ using type = typename T2::element_type;
+ static constexpr int variant = 2;
+};
+
+
+// #1
+template <typename T1>
+struct traits<T1 *>
+{
+ using type = T1;
+ static constexpr int variant = 1;
+};
+
+
+// #3
+template <typename T3>
+requires requires { typename T3::value_type; }
+struct traits<T3 *>
+{
+ using type = typename T3::value_type;
+ static constexpr int variant = 3;
+};
diff --git a/gcc/testsuite/g++.dg/modules/constrained-partial-1_b.C b/gcc/testsuite/g++.dg/modules/constrained-partial-1_b.C
new file mode 100644
index 0000000..bbbbab5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/constrained-partial-1_b.C
@@ -0,0 +1,31 @@
+// { dg-additional-options "-fmodules-ts -std=c++20" }
+
+import M;
+
+struct Variant0
+{
+};
+
+
+struct Variant2
+{
+ using element_type = double;
+};
+
+struct Variant3
+{
+ using value_type = float;
+};
+
+void f()
+{
+ using v0 = traits<Variant0>;
+ using v1 = traits<Variant0 *>;
+ using v2 = traits<Variant2 *>;
+ using v3 = traits<Variant3 *>;
+
+ static_assert (v0::variant == 0);
+ static_assert (v1::variant == 1);
+ static_assert (v2::variant == 2);
+ static_assert (v3::variant == 3);
+}
diff --git a/gcc/testsuite/g++.dg/modules/convop-1_a.C b/gcc/testsuite/g++.dg/modules/convop-1_a.C
new file mode 100644
index 0000000..d0edec8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/convop-1_a.C
@@ -0,0 +1,12 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module frob;
+// { dg-module-cmi "frob" }
+
+export struct A
+{
+ operator int ()
+ {
+ return 0;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/convop-1_b.C b/gcc/testsuite/g++.dg/modules/convop-1_b.C
new file mode 100644
index 0000000..65350ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/convop-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts" }
+import frob;
+
+int main ()
+{
+ A a;
+
+ if (static_cast<int> (a))
+ return 1;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/cpp-1.C b/gcc/testsuite/g++.dg/modules/cpp-1.C
new file mode 100644
index 0000000..2ad9637
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-1.C
@@ -0,0 +1,14 @@
+// { dg-do preprocess }
+
+module bob;
+#if 1
+export import stuart;
+#else
+import kevin;
+#endif
+import gru;
+#define EXPORT
+EXPORT import mabel;
+int i;
+
+// { dg-final { scan-file cpp-1.i "cpp-1.C\"\n\n\nmodule bob;\n\nexport import stuart;\n\n\n\nimport gru;\n\n import mabel;\n" } }
diff --git a/gcc/testsuite/g++.dg/modules/cpp-2_a.H b/gcc/testsuite/g++.dg/modules/cpp-2_a.H
new file mode 100644
index 0000000..391843f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+#define STRING_H
+#define NOPE
diff --git a/gcc/testsuite/g++.dg/modules/cpp-2_b.H b/gcc/testsuite/g++.dg/modules/cpp-2_b.H
new file mode 100644
index 0000000..34c138d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-2_b.H
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#define STDIO_H
+#define think THIS IS STDIO
+#define CLOSE ]]
diff --git a/gcc/testsuite/g++.dg/modules/cpp-2_c.C b/gcc/testsuite/g++.dg/modules/cpp-2_c.C
new file mode 100644
index 0000000..c6e02b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-2_c.C
@@ -0,0 +1,17 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts" }
+
+module bob;
+#pragma GCC unused
+import "./cpp-2_b.H" [[ CLOSE ]];
+import "cpp-2_a.H" [[ CLOSE;
+int i;
+#ifndef NOPE
+import nope;
+#endif
+think
+
+// { dg-final { scan-file cpp-2_c.i {cpp-2_c.C"\n\n\n\nmodule bob;\n#pragma GCC unused\nimport "[^\n]*\./cpp-2_b.H" \[\[ CLOSE ]];\nimport "[^\n]*cpp-2_a.H" \[\[ ]];\n} } }
+// { dg-final { scan-file cpp-2_c.i "int i;" } }
+// { dg-final { scan-file-not cpp-2_c.i "import *nope;" } }
+// { dg-final { scan-file cpp-2_c.i "THIS IS STDIO\n" } }
diff --git a/gcc/testsuite/g++.dg/modules/cpp-3.C b/gcc/testsuite/g++.dg/modules/cpp-3.C
new file mode 100644
index 0000000..3aa0c6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-3.C
@@ -0,0 +1,9 @@
+// { dg-do preprocess }
+
+#define NAME(X) X;
+
+export module NAME(bob)
+
+int i;
+// { dg-final { scan-file cpp-3.i "\nexport module bob;\n" } }
+// { dg-final { scan-file cpp-3.i "\nint i;\n" } }
diff --git a/gcc/testsuite/g++.dg/modules/cpp-4.C b/gcc/testsuite/g++.dg/modules/cpp-4.C
new file mode 100644
index 0000000..6c19431
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-4.C
@@ -0,0 +1,10 @@
+// { dg-do preprocess }
+
+#if 1
+#include "cpp-4.h"
+#endif
+
+// { dg-final { scan-file cpp-4.i "/cpp-4.h\\\" 1" } }
+// { dg-final { scan-file cpp-4.i "/cpp-4.C\\\" 2" } }
+// { dg-final { scan-file cpp-4.i "import x;\n" } }
+// { dg-final { scan-file cpp-4.i "int" } }
diff --git a/gcc/testsuite/g++.dg/modules/cpp-4.h b/gcc/testsuite/g++.dg/modules/cpp-4.h
new file mode 100644
index 0000000..aec9547
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-4.h
@@ -0,0 +1,4 @@
+#if 1
+import x;
+int i; // end here in middle of #if (ok)
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/cpp-5_a.H b/gcc/testsuite/g++.dg/modules/cpp-5_a.H
new file mode 100644
index 0000000..3941ee8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-5_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef AA
+#define AA
+
+#define Q 0
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/cpp-5_b.C b/gcc/testsuite/g++.dg/modules/cpp-5_b.C
new file mode 100644
index 0000000..504e792
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-5_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+// missing semicolon
+import "cpp-5_a.H" // { dg-error "expected" }
+
+int main ()
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/cpp-5_c.C b/gcc/testsuite/g++.dg/modules/cpp-5_c.C
new file mode 100644
index 0000000..e0a78a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-5_c.C
@@ -0,0 +1,10 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts" }
+#define Q 0
+#undef Q
+
+import "cpp-5_a.H";
+
+Q
+
+// { dg-final { scan-file cpp-5_c.i {\nimport "[^\n]*cpp-5_a.H";\n\n0\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/cpp-6_a.H b/gcc/testsuite/g++.dg/modules/cpp-6_a.H
new file mode 100644
index 0000000..0bb1f41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-6_a.H
@@ -0,0 +1,3 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+#define bibity cpp-6_b.H
diff --git a/gcc/testsuite/g++.dg/modules/cpp-6_b.H b/gcc/testsuite/g++.dg/modules/cpp-6_b.H
new file mode 100644
index 0000000..2d5bccc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-6_b.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define bobity cpp-6_b
diff --git a/gcc/testsuite/g++.dg/modules/cpp-6_c.C b/gcc/testsuite/g++.dg/modules/cpp-6_c.C
new file mode 100644
index 0000000..f9b1e2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-6_c.C
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+
+#define empty
+#define nop(X) X
+
+ONE bibity bobity
+import <cpp-6_a.H>;
+TWO bibity bobity
+import empty nop(<bibity>);
+THREE bibity bobity
+import empty <bobity.H>;
+FOUR bibity bobity
+
+// { dg-final { scan-file cpp-6_c.i {ONE bibity bobity\n} } }
+// { dg-final { scan-file cpp-6_c.i {TWO cpp-6_b.H bobity\n} } }
+// { dg-final { scan-file cpp-6_c.i {THREE cpp-6_b.H cpp-6_b\n} } }
+// { dg-final { scan-file cpp-6_c.i {FOUR cpp-6_b.H cpp-6_b\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/debug-1_a.C b/gcc/testsuite/g++.dg/modules/debug-1_a.C
new file mode 100644
index 0000000..b0f1763
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/debug-1_a.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts -g" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+export struct thingy
+{
+ virtual void X ()
+ {
+ thingy w;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/debug-1_b.C b/gcc/testsuite/g++.dg/modules/debug-1_b.C
new file mode 100644
index 0000000..7fca87b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/debug-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -g" }
+
+import frob;
+
+struct thongy : thingy
+{
+ void X ()
+ {
+ thongy w;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/decomp-1_a.C b/gcc/testsuite/g++.dg/modules/decomp-1_a.C
new file mode 100644
index 0000000..07506c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/decomp-1_a.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+export module foo;
+// { dg-module-cmi foo }
+
+struct tuple { int a, b, c;};
+
+tuple maker ();
+
+export inline int bob ()
+{
+ auto [a, b, c] = maker ();
+
+ return a + b + c;
+}
diff --git a/gcc/testsuite/g++.dg/modules/decomp-1_b.C b/gcc/testsuite/g++.dg/modules/decomp-1_b.C
new file mode 100644
index 0000000..709c333
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/decomp-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+import foo;
+
+void x ()
+{
+ bob ();
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/deferred-1.h b/gcc/testsuite/g++.dg/modules/deferred-1.h
new file mode 100644
index 0000000..dc0fd78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/deferred-1.h
@@ -0,0 +1,12 @@
+template<bool _Const>
+struct _Iterator
+{
+private:
+ static void mover (const _Iterator &arg = {}) noexcept (noexcept (arg));
+
+public:
+ _Iterator() = default;
+
+ friend void move (const _Iterator &arg2) noexcept (noexcept (mover (arg2)))
+ {}
+};
diff --git a/gcc/testsuite/g++.dg/modules/deferred-1_a.H b/gcc/testsuite/g++.dg/modules/deferred-1_a.H
new file mode 100644
index 0000000..88e6fab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/deferred-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "deferred-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/deferred-1_b.C b/gcc/testsuite/g++.dg/modules/deferred-1_b.C
new file mode 100644
index 0000000..5f75aec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/deferred-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "deferred-1.h"
+import "deferred-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/dep-1_a.C b/gcc/testsuite/g++.dg/modules/dep-1_a.C
new file mode 100644
index 0000000..766f436
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dep-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -MD" }
+
+export module m:part;
+// { dg-module-cmi m:part }
+
+// All The Backslashes!
+// { dg-final { scan-file dep-1_a.d {\nm\\:part\.c\+\+m: gcm.cache/m-part\.gcm} } }
+// { dg-final { scan-file dep-1_a.d {\ngcm.cache/m-part\.gcm:| dep-1_a\.o} } }
+// { dg-final { scan-file dep-1_a.d {\n\.PHONY: m\\:part\.c\+\+m} } }
diff --git a/gcc/testsuite/g++.dg/modules/dep-1_b.C b/gcc/testsuite/g++.dg/modules/dep-1_b.C
new file mode 100644
index 0000000..138832f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dep-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -MD" }
+export module m;
+// { dg-module-cmi m }
+
+export import :part;
+// { dg-final { scan-file dep-1_b.d {\ndep-1_b\.s gcm.cache/m\.gcm: m\\:part\.c\+\+m} } }
+// { dg-final { scan-file dep-1_b.d {\nm\.c\+\+m: gcm.cache/m\.gcm} } }
+// { dg-final { scan-file dep-1_b.d {\n\.PHONY: m\.c\+\+m} } }
+// { dg-final { scan-file dep-1_b.d {\ngcm.cache/m\.gcm:| dep-1_b.o} } }
+// { dg-final { scan-file dep-1_b.d {\nCXX_IMPORTS \+= m\\:part\.c\+\+m} } }
diff --git a/gcc/testsuite/g++.dg/modules/dep-2.C b/gcc/testsuite/g++.dg/modules/dep-2.C
new file mode 100644
index 0000000..5e112c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dep-2.C
@@ -0,0 +1,12 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -MD" }
+
+module m:part;
+// { dg-module-cmi !m:part }
+
+// All The Backslashes!
+// { dg-final { scan-file dep-2.d {\nm\\:part\.c\+\+m: gcm.cache/m-part\.gcm} } }
+// { dg-final { scan-file dep-2.d {\ngcm.cache/m\\:part\.gcm:| dep-2\.o} } }
+// { dg-final { scan-file dep-2.d {\n\.PHONY: m\\:part\.c\+\+m} } }
+
+// { dg-final { scan-file dep-2.i {\nmodule m:part;\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/dep-3.C b/gcc/testsuite/g++.dg/modules/dep-3.C
new file mode 100644
index 0000000..f0f883e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dep-3.C
@@ -0,0 +1,9 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -MD -Mno-modules" }
+
+module m:part;
+// { dg-module-cmi !m:part }
+
+// All The Backslashes!
+// { dg-final { scan-file-not dep-3.d {part\.gcm} } }
+// { dg-final { scan-file-not dep-3.d {part\.c\+\+m} } }
diff --git a/gcc/testsuite/g++.dg/modules/dir-only-1.C b/gcc/testsuite/g++.dg/modules/dir-only-1.C
new file mode 100644
index 0000000..d035b5f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dir-only-1.C
@@ -0,0 +1,16 @@
+// { dg-do preprocess }
+// { dg-additional-options -fdirectives-only }
+
+#define major NO NOT ME
+
+#ifdef major
+# undef major
+#else
+# error major not initially defined
+#endif
+
+#ifdef major
+# error major still defined
+#endif
+
+// { dg-final { scan-file dir-only-1.i "#undef major\n" } }
diff --git a/gcc/testsuite/g++.dg/modules/dir-only-2_a.H b/gcc/testsuite/g++.dg/modules/dir-only-2_a.H
new file mode 100644
index 0000000..3ed0de5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dir-only-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define X 1
diff --git a/gcc/testsuite/g++.dg/modules/dir-only-2_b.C b/gcc/testsuite/g++.dg/modules/dir-only-2_b.C
new file mode 100644
index 0000000..0691f76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dir-only-2_b.C
@@ -0,0 +1,28 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -fdirectives-only -isystem [srcdir]" }
+// a comment
+module; // line
+frob
+export
+import foo; // line
+import 7;
+
+im\
+port \
+sing;
+// comment
+import "dir-only-2_a.H";
+import <dir-only-2_a.H>;
+X
+#if !X
+#error "no X!"
+#endif
+export module bob;
+
+export import q;
+
+// { dg-final { scan-file dir-only-2_b.i {// a comment\nmodule ;\nfrob} } }
+// { dg-final { scan-file dir-only-2_b.i {frob\nexport\nimport foo;\nimport 7;} } }
+// { dg-final { scan-file dir-only-2_b.i {import "[^\n]*/dir-only-2_a.H";\nimport "[^\n]*/dir-only-2_a.H";\nX} } }
+// { dg-final { scan-file dir-only-2_b.i {export module bob;\n\nexport import q;} } }
+// { dg-final { scan-file dir-only-2_b.i {import sing;\n\n\n// comment} } }
diff --git a/gcc/testsuite/g++.dg/modules/dir-only-3.C b/gcc/testsuite/g++.dg/modules/dir-only-3.C
new file mode 100644
index 0000000..6e3af8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dir-only-3.C
@@ -0,0 +1,18 @@
+# 0 "dir-only-3.C"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 31 "<command-line>"
+# 1 "/usr/include/stdc-predef.h" 1 3 4
+
+# 32 "<command-line>" 2
+# 1 "dir-only-3.C"
+// { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} }
+// { dg-module-cmi foo }
+module;
+#define foo baz
+export module foo;
+
+class import {};
+
+import
+x;
diff --git a/gcc/testsuite/g++.dg/modules/dir-only-4.C b/gcc/testsuite/g++.dg/modules/dir-only-4.C
new file mode 100644
index 0000000..80d6461
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dir-only-4.C
@@ -0,0 +1,10 @@
+// { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} }
+// { dg-module-cmi !foo }
+module;
+#define foo baz
+export module foo;
+
+class import {};
+
+import x; // { dg-error "post-module-declaration" }
+ // { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/dir-recovery.C b/gcc/testsuite/g++.dg/modules/dir-recovery.C
new file mode 100644
index 0000000..90794b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dir-recovery.C
@@ -0,0 +1,9 @@
+// { dg-additional-options {-fmodules-ts -fpreprocessed} }
+module;
+
+; export module Hello; // { dg-error "global module fragment" }
+// { dg-error "after a module interface" "" { target *-*-* } .-1 }
+// { dg-error "not name a type" "" { target *-*-* } .-2 }
+// { dg-message "not recognized as a module control-line" "" { target *-*-* } .-3 }
+
+void SayHello ();
diff --git a/gcc/testsuite/g++.dg/modules/enum-1_a.C b/gcc/testsuite/g++.dg/modules/enum-1_a.C
new file mode 100644
index 0000000..53e2ac8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-1_a.C
@@ -0,0 +1,30 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+export module enUm;
+// { dg-module-cmi "enUm" }
+
+export enum Bill
+{
+ Zero,
+ One,
+ Three = 3
+};
+
+export enum class Ben
+{
+ Zero,
+ Two = 2,
+ Three
+};
+
+export inline Ben func1 ()
+{
+ return Ben::Three;
+}
+
+export inline Ben func2 ()
+{
+ return Ben (4);
+}
+
+// { dg-final { scan-lang-dump-times {Written enum value '::Ben::Three'} 2 module } }
diff --git a/gcc/testsuite/g++.dg/modules/enum-1_b.C b/gcc/testsuite/g++.dg/modules/enum-1_b.C
new file mode 100644
index 0000000..4b8c647
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-1_b.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts" }
+import enUm;
+
+Bill x = Three;
+Ben y = Ben::Three;
+
+int main ()
+{
+ if (x != 3)
+ return 1;
+
+ if (int (y) != 3)
+ return 2;
+
+ if (int (func1 ()) != 3)
+ return 3;
+
+ if (int (func2 ()) != 4)
+ return 4;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/enum-2_a.C b/gcc/testsuite/g++.dg/modules/enum-2_a.C
new file mode 100644
index 0000000..9e5e42a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-2_a.C
@@ -0,0 +1,21 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct X
+{
+ enum q
+ {
+ frob
+ };
+};
+
+export template <int I> struct TPL
+{
+ enum p
+ {
+ u,
+ v = I
+ };
+};
diff --git a/gcc/testsuite/g++.dg/modules/enum-2_b.C b/gcc/testsuite/g++.dg/modules/enum-2_b.C
new file mode 100644
index 0000000..4e0aed4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-2_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int i = X::frob;
+
+int k = TPL<2>::v;
+
+static_assert (!TPL<1>::u);
diff --git a/gcc/testsuite/g++.dg/modules/enum-3_a.C b/gcc/testsuite/g++.dg/modules/enum-3_a.C
new file mode 100644
index 0000000..514bdd0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-3_a.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+// from https://godbolt.org/beta/z/V45BSw
+
+export module m0;
+// { dg-module-cmi m0 }
+namespace m0_ns
+{
+template <typename T> struct s0 {
+ enum t { a };
+};
+}
diff --git a/gcc/testsuite/g++.dg/modules/enum-3_b.C b/gcc/testsuite/g++.dg/modules/enum-3_b.C
new file mode 100644
index 0000000..073611c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-3_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodules-ts }
+module m0;
+
+static_assert (!m0_ns::s0<int>::a);
diff --git a/gcc/testsuite/g++.dg/modules/enum-4_a.C b/gcc/testsuite/g++.dg/modules/enum-4_a.C
new file mode 100644
index 0000000..96880b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-4_a.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export template <typename T, typename U>
+struct same
+{
+ enum { value = 0 };
+};
+
+template<typename T>
+struct same <T, T>
+{
+ enum { value = 1 };
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/enum-4_b.C b/gcc/testsuite/g++.dg/modules/enum-4_b.C
new file mode 100644
index 0000000..0f88fa1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-4_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+static_assert (same<int, float>::value == 0);
+static_assert (same<int *, int *>::value == 1);
diff --git a/gcc/testsuite/g++.dg/modules/enum-5_a.H b/gcc/testsuite/g++.dg/modules/enum-5_a.H
new file mode 100644
index 0000000..1f2e84f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-5_a.H
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+enum
+{
+ Zero,
+};
diff --git a/gcc/testsuite/g++.dg/modules/enum-5_b.C b/gcc/testsuite/g++.dg/modules/enum-5_b.C
new file mode 100644
index 0000000..385c1d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-5_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodules-ts }
+import "enum-5_a.H";
+
+int i = Zero;
diff --git a/gcc/testsuite/g++.dg/modules/enum-6_a.H b/gcc/testsuite/g++.dg/modules/enum-6_a.H
new file mode 100644
index 0000000..0669046
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-6_a.H
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+enum { _S_chunk_size = 7 };
+
+template<typename T> T getter ()
+{
+ return _S_chunk_size;
+}
diff --git a/gcc/testsuite/g++.dg/modules/enum-6_b.C b/gcc/testsuite/g++.dg/modules/enum-6_b.C
new file mode 100644
index 0000000..04c1ee2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-6_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "enum-6_a.H";
+
+int main ()
+{
+ return !(getter<int> () == 7);
+}
diff --git a/gcc/testsuite/g++.dg/modules/enum-7.C b/gcc/testsuite/g++.dg/modules/enum-7.C
new file mode 100644
index 0000000..8cf31a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-7.C
@@ -0,0 +1,20 @@
+// { dg-additional-options -fmodules-ts }
+
+// ICE getting template info of a function-scope enum
+
+template <typename T> void adl (T) {}
+
+template <typename T>
+void frob (T arg)
+{
+ enum class case_conv {none};
+
+ case_conv x = case_conv::none;
+
+ adl (x);
+}
+
+void foo ()
+{
+ frob (1);
+}
diff --git a/gcc/testsuite/g++.dg/modules/enum-8_a.H b/gcc/testsuite/g++.dg/modules/enum-8_a.H
new file mode 100644
index 0000000..90ccb91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-8_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodule-header }
+
+enum : char
+{
+ Foo = 1,
+};
diff --git a/gcc/testsuite/g++.dg/modules/enum-8_b.H b/gcc/testsuite/g++.dg/modules/enum-8_b.H
new file mode 100644
index 0000000..021ad17
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-8_b.H
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodule-header }
+
+enum : int
+{
+ Foo = 2,
+};
diff --git a/gcc/testsuite/g++.dg/modules/enum-8_c.C b/gcc/testsuite/g++.dg/modules/enum-8_c.C
new file mode 100644
index 0000000..d14469b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-8_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
+
+export module Char;
+
+import "enum-8_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/enum-8_d.C b/gcc/testsuite/g++.dg/modules/enum-8_d.C
new file mode 100644
index 0000000..6650773
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-8_d.C
@@ -0,0 +1,11 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -fdump-lang-module-alias} }
+
+import "enum-8_b.H";
+
+import Char;
+
+
+// { dg-final { scan-lang-dump {Read:-1's enum merge key \(new\) type_decl:'#null#'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) const_decl:'::._anon_0@[^\n]*/enum-8_b.H:1::Foo'} module } }
+// { dg-final { scan-lang-dump {Read:-1's enum merge key \(new\) type_decl:'#null#'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) const_decl:'::._anon_1@[^\n]*/enum-8_a.H:2::Foo'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/enum-bad-1_a.H b/gcc/testsuite/g++.dg/modules/enum-bad-1_a.H
new file mode 100644
index 0000000..2d8a7ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-bad-1_a.H
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+
+enum ONE {A};
+enum {TWO, THREE};
+enum FOUR {B = 5};
+enum FIVE {C, D, E};
diff --git a/gcc/testsuite/g++.dg/modules/enum-bad-1_b.C b/gcc/testsuite/g++.dg/modules/enum-bad-1_b.C
new file mode 100644
index 0000000..b01cd66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-bad-1_b.C
@@ -0,0 +1,26 @@
+// { dg-additional-options {-fmodules-ts} }
+
+enum ONE {Q};
+enum {TWO, DREI};
+enum FOUR {B = 3};
+enum FIVE {C, D};
+
+import "enum-bad-1_a.H";
+
+
+
+
+
+
+ONE one;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:5:6: error: definition of 'enum ONE' does not match\n[^\n]*enum-bad-1_b.C:3:6: note: existing definition 'enum ONE'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:5:11: note: ... this enumerator 'A'\n[^\n]*enum-bad-1_b.C:3:11: note: enumerator 'Q' does not match ...\n[^\n]*enum-bad-1_b.C:15:1: note: during load of binding '::ONE'\n} }
+
+int i = TWO;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:6:6: error: definition of 'enum<unnamed>' does not match\n[^\n]*enum-bad-1_b.C:4:6: note: existing definition 'enum<unnamed>'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:6:12: note: ... this enumerator 'THREE'\n[^\n]*enum-bad-1_b.C:4:12: note: enumerator 'DREI' does not match ...\n[^\n]*enum-bad-1_b.C:18:9: note: during load of binding '::TWO'\n} }
+
+FOUR four;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:7:6: error: definition of 'enum FOUR' does not match\n[^\n]*enum-bad-1_b.C:5:6: note: existing definition 'enum FOUR'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:7:12: note: ... this enumerator 'B'\n[^\n]*enum-bad-1_b.C:5:12: note: enumerator 'B' does not match ...\n[^\n]*enum-bad-1_b.C:21:1: note: during load of binding '::FOUR'\n} }
+
+FIVE five;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:8:6: error: definition of 'enum FIVE' does not match\n[^\n]*enum-bad-1_b.C:6:6: note: existing definition 'enum FIVE'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:8:18: note: additional enumerators beginning with 'E'\n[^\n]*enum-bad-1_b.C:24:1: note: during load of binding '::FIVE'\n} }
+
diff --git a/gcc/testsuite/g++.dg/modules/err-1_a.C b/gcc/testsuite/g++.dg/modules/err-1_a.C
new file mode 100644
index 0000000..1f7ddec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/err-1_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export int Frob (int, int, long);
+export int Frob (int, long, int);
diff --git a/gcc/testsuite/g++.dg/modules/err-1_b.C b/gcc/testsuite/g++.dg/modules/err-1_b.C
new file mode 100644
index 0000000..6d5609c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/err-1_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+export int Frob (long, int, int);
diff --git a/gcc/testsuite/g++.dg/modules/err-1_c.C b/gcc/testsuite/g++.dg/modules/err-1_c.C
new file mode 100644
index 0000000..3a93cc6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/err-1_c.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts" }
+import Foo;
+
+void One ()
+{
+ Frob (0, 0, 0L);
+ Frob (0, 0L, 0);
+ Frob (0L, 0, 0); // { dg-error "ambiguous" }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, long int, int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, int, long int\)'} }
+}
+
+import Bar;
+
+void Two ()
+{
+ Frob (0L, 0, 0);
+ Frob (0, 0, 0); // { dg-error "ambiguous" }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, long int, int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, int, long int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Bar\(long int, int, int\)'} }
+}
diff --git a/gcc/testsuite/g++.dg/modules/err-1_d.C b/gcc/testsuite/g++.dg/modules/err-1_d.C
new file mode 100644
index 0000000..eb6b4ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/err-1_d.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+import Foo;
+import Bar;
+
+
+void Three ()
+{
+ Frob (0L, 0, 0);
+
+ Frob (0, 0, 0); // { dg-error "ambiguous" }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, long int, int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, int, long int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Bar\(long int, int, int\)'} }
+}
diff --git a/gcc/testsuite/g++.dg/modules/except-1.C b/gcc/testsuite/g++.dg/modules/except-1.C
new file mode 100644
index 0000000..6135c8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-1.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+export module bill;
+// { dg-module-cmi bill }
+
+// Make sure no deferred parse exception spec detritus remains
+
+template<typename T>
+class bob
+{
+ void frob () noexcept(T::frob ());
+ template<typename U> void frobber (int) noexcept (T::frob ());
+};
+
+
+class bill
+{
+ template<typename U> void frobbest (int) noexcept (U::frob ());
+};
diff --git a/gcc/testsuite/g++.dg/modules/except-2.h b/gcc/testsuite/g++.dg/modules/except-2.h
new file mode 100644
index 0000000..38355ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-2.h
@@ -0,0 +1,42 @@
+
+// Causes the CMI to have instantiated a deferred noexept spec that
+// the textually included file has not.
+
+typedef long unsigned int size_t;
+
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+ static constexpr _Tp value = __v;
+ typedef integral_constant<_Tp, __v> type;
+};
+template<typename _Tp, _Tp __v>
+constexpr _Tp integral_constant<_Tp, __v>::value;
+
+template<typename _Head>
+struct _Tuple_impl : _Head
+{
+ _Tuple_impl(_Tuple_impl&& __in)
+ noexcept (integral_constant<bool,
+ noexcept(_Head(static_cast<_Head &&>(*(_Head *) (0))))>::type::value);
+};
+
+template <typename _Dp>
+struct __uniq_ptr_impl
+{
+ __uniq_ptr_impl (__uniq_ptr_impl&& __u) noexcept
+ : _M_t(static_cast <_Tuple_impl<_Dp> &&>(__u._M_t))
+ {}
+
+ _Tuple_impl<_Dp> _M_t;
+};
+
+struct _Impl_deleter {};
+
+typedef __uniq_ptr_impl<_Impl_deleter> up;
+
+inline void frob (up && p)
+{
+ up _M_cmpts (static_cast <up &&> (p));
+}
diff --git a/gcc/testsuite/g++.dg/modules/except-2_a.H b/gcc/testsuite/g++.dg/modules/except-2_a.H
new file mode 100644
index 0000000..966169c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "except-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/except-2_b.C b/gcc/testsuite/g++.dg/modules/except-2_b.C
new file mode 100644
index 0000000..78ed8f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-2_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "except-2.h"
+import "except-2_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/except-3.h b/gcc/testsuite/g++.dg/modules/except-3.h
new file mode 100644
index 0000000..8bf0f84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-3.h
@@ -0,0 +1,24 @@
+
+template<typename _Tp>
+struct is_nothrow_move_constructible
+{
+ static constexpr bool value = false;
+};
+
+template<typename _Head>
+struct _Tuple_impl
+{
+ _Tuple_impl () noexcept(is_nothrow_move_constructible<_Head>::value)
+ { }
+};
+
+template<typename T>
+void TPL (_Tuple_impl<T> &) noexcept
+{
+ _Tuple_impl<T> m;
+}
+
+inline void foo (_Tuple_impl<int> &p)
+{
+ TPL<int> (p);
+}
diff --git a/gcc/testsuite/g++.dg/modules/except-3_a.H b/gcc/testsuite/g++.dg/modules/except-3_a.H
new file mode 100644
index 0000000..2f9f00e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-3_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+// We end up with instantiated noexcept specs in the CMI data matching
+// textually loaded fns with uninstantiated ones. Have to propagate,
+// not reinstantiate.
+#include "except-3.h"
diff --git a/gcc/testsuite/g++.dg/modules/except-3_b.C b/gcc/testsuite/g++.dg/modules/except-3_b.C
new file mode 100644
index 0000000..0cb8472
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/except-3_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "except-3.h"
+import "except-3_a.H";
+
+// { dg-final { scan-lang-dump-times {merge key \(new\) function_decl:'::_Tuple_impl<int>::__[cd]t '} 3 module } }
+// { dg-final { scan-lang-dump-times {Propagating instantiated noexcept to '::_Tuple_impl<int>::__ct <int>'} 1 module } }
diff --git a/gcc/testsuite/g++.dg/modules/exp-xlate-1_a.H b/gcc/testsuite/g++.dg/modules/exp-xlate-1_a.H
new file mode 100644
index 0000000..2079f90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/exp-xlate-1_a.H
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define PROTECT 1
+int foo ();
diff --git a/gcc/testsuite/g++.dg/modules/exp-xlate-1_b.C b/gcc/testsuite/g++.dg/modules/exp-xlate-1_b.C
new file mode 100644
index 0000000..3295a6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/exp-xlate-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+export module evil;
+// { dg-module-cmi !evil }
+
+export // { dg-error "not part of following" }
+#include "exp-xlate-1_a.H" // { dg-error "must be contiguous" }
+// { dg-prune-output {not writing module} }
diff --git a/gcc/testsuite/g++.dg/modules/export-1.C b/gcc/testsuite/g++.dg/modules/export-1.C
new file mode 100644
index 0000000..8ca696e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-1.C
@@ -0,0 +1,22 @@
+// { dg-additional-options -fmodules-ts }
+
+export module frob;
+// { dg-module-cmi !frob }
+
+int x ();
+export int x (); // { dg-error "conflicting exporting declaration" }
+
+int y;
+export extern int y; // { dg-error "conflicting exporting declaration" }
+
+typedef int z;
+export typedef int z; // { dg-error "conflicting exporting declaration" }
+
+template <typename T> int f (T);
+export template <typename T> int f (T); // { dg-error "conflicting exporting declaration" }
+
+// doesn't go via duplicate_decls so we miss this for now
+class A;
+export class A; // { dg-error "conflicting exporting declaration" "" { xfail *-*-* } }
+
+// { dg-warning "due to errors" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-1_a.H b/gcc/testsuite/g++.dg/modules/extern-tpl-1_a.H
new file mode 100644
index 0000000..93afc4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-1_a.H
@@ -0,0 +1,23 @@
+// { dg-module-do link }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template <unsigned I> struct TPL
+{
+ int Source ()
+ {
+ return I;
+ }
+};
+
+extern template class TPL<1>;
+
+struct Foo
+{
+ TPL<1> m;
+
+ Foo () {m.Source ();};
+
+};
+
+static Foo __ioinit;
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-1_b.C b/gcc/testsuite/g++.dg/modules/extern-tpl-1_b.C
new file mode 100644
index 0000000..f3c0dc4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options {-fmodules-ts -fmodule-mapper=|@g++-mapper-server} }
+
+// Have to textually include, because we currently get confused about
+// the explicit instantiations and think they conflict
+#include "extern-tpl-1_a.H"
+
+template class TPL<1>;
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-1_c.C b/gcc/testsuite/g++.dg/modules/extern-tpl-1_c.C
new file mode 100644
index 0000000..d1b6cb6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-1_c.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+
+import "extern-tpl-1_a.H";
+
+int main ()
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-2_a.H b/gcc/testsuite/g++.dg/modules/extern-tpl-2_a.H
new file mode 100644
index 0000000..a90d50e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-2_a.H
@@ -0,0 +1,13 @@
+// { dg-module-do link }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template <unsigned I> struct TPL
+{
+ int Source ()
+ {
+ return I;
+ }
+};
+
+extern template class TPL<1>;
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-2_b.H b/gcc/testsuite/g++.dg/modules/extern-tpl-2_b.H
new file mode 100644
index 0000000..5f9875c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-2_b.H
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+import "extern-tpl-2_a.H";
+
+struct Foo
+{
+ TPL<1> m;
+
+ Foo () {m.Source ();};
+
+};
+
+static Foo __ioinit;
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-2_c.C b/gcc/testsuite/g++.dg/modules/extern-tpl-2_c.C
new file mode 100644
index 0000000..b73ec6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-2_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodules-ts }
+
+import "extern-tpl-2_a.H";
+
+template class TPL<1>;
diff --git a/gcc/testsuite/g++.dg/modules/extern-tpl-2_d.C b/gcc/testsuite/g++.dg/modules/extern-tpl-2_d.C
new file mode 100644
index 0000000..25a977f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/extern-tpl-2_d.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+
+import "extern-tpl-2_b.H";
+
+int main ()
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/flag-1_a.C b/gcc/testsuite/g++.dg/modules/flag-1_a.C
new file mode 100644
index 0000000..9f73320
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/flag-1_a.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -std=c++17" }
+export module opt;
+
+// { dg-module-cmi opt }
diff --git a/gcc/testsuite/g++.dg/modules/flag-1_b.C b/gcc/testsuite/g++.dg/modules/flag-1_b.C
new file mode 100644
index 0000000..32bfd82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/flag-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+// { dg-error "language dialect differs" "" { target *-*-* } 0 }
+
+import opt;
+
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+// { dg-prune-output "compilation terminated" }
+// { dg-prune-output "fatal error" }
diff --git a/gcc/testsuite/g++.dg/modules/fn-inline-1_a.C b/gcc/testsuite/g++.dg/modules/fn-inline-1_a.C
new file mode 100644
index 0000000..13e717bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/fn-inline-1_a.C
@@ -0,0 +1,21 @@
+// { dg-require-weak "" }
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+
+export inline int frob (int a)
+{
+ return -a;
+}
+
+inline int frob (int s, int a)
+{
+ while (s--)
+ a <<= 1;
+ return a;
+}
+
+export int Frob (int s, int a);
+
+// { dg-final { scan-assembler-not "_Z4frobi:" } }
+// { dg-final { scan-assembler-not "_ZW3bobE4frobii:" } }
diff --git a/gcc/testsuite/g++.dg/modules/fn-inline-1_b.C b/gcc/testsuite/g++.dg/modules/fn-inline-1_b.C
new file mode 100644
index 0000000..72de1a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/fn-inline-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts" }
+module bob;
+
+int Frob (int n, int a)
+{
+ return frob (n, a);
+}
+
+// { dg-final { scan-assembler "_ZW3bobE4frobii:" } }
+// { dg-final { scan-assembler ".weak(_definition)?\[\t ]*_?_ZW3bobE4frobii" } }
+// { dg-final { scan-assembler "_Z4Frobii:" } }
diff --git a/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C b/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C
new file mode 100644
index 0000000..55a7aaa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+import bob;
+
+int main ()
+{
+ if (frob (2) != -2)
+ return 1;
+ if (Frob (0, 2) != 2)
+ return 1;
+ if (Frob (2, 2) != 8)
+ return 1;
+ return 0;
+}
+
+// { dg-final { scan-assembler "_Z4frobi:" } }
+// { dg-final { scan-assembler ".weak(_definition)?\[\t ]*_?_Z4frobi" } }
diff --git a/gcc/testsuite/g++.dg/modules/freeze-1_a.C b/gcc/testsuite/g++.dg/modules/freeze-1_a.C
new file mode 100644
index 0000000..f05dd3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/freeze-1_a.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+
+export void bob ();
diff --git a/gcc/testsuite/g++.dg/modules/freeze-1_b.C b/gcc/testsuite/g++.dg/modules/freeze-1_b.C
new file mode 100644
index 0000000..36d1323
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/freeze-1_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module stuart;
+// { dg-module-cmi "stuart" }
+
+export void stuart ();
diff --git a/gcc/testsuite/g++.dg/modules/freeze-1_c.C b/gcc/testsuite/g++.dg/modules/freeze-1_c.C
new file mode 100644
index 0000000..3941d30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/freeze-1_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module kevin;
+// { dg-module-cmi "kevin" }
+
+export void kevin ();
diff --git a/gcc/testsuite/g++.dg/modules/freeze-1_d.C b/gcc/testsuite/g++.dg/modules/freeze-1_d.C
new file mode 100644
index 0000000..faeae14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/freeze-1_d.C
@@ -0,0 +1,21 @@
+// { dg-additional-options "-fmodules-ts --param lazy-modules=1 -fdump-lang-module" }
+
+import bob;
+import stuart;
+import kevin;
+
+int main ()
+{
+ stuart ();
+ bob ();
+ kevin ();
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Freezing 'bob.[^']*'} module } }
+// { dg-final { scan-lang-dump {Freezing 'stuart.[^']*'} module } }
+// { dg-final { scan-lang-dump {Freezing 'kevin.[^']*'} module } }
+// { dg-final { scan-lang-dump {Defrosting 'bob.[^']*'} module } }
+// { dg-final { scan-lang-dump {Defrosting 'stuart.[^']*'} module } }
+// { dg-final { scan-lang-dump {Defrosting 'kevin.[^']*'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/friend-1_a.C b/gcc/testsuite/g++.dg/modules/friend-1_a.C
new file mode 100644
index 0000000..2cfab400
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-1_a.C
@@ -0,0 +1,37 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export struct peeker
+{
+ static int peek (void *);
+};
+
+
+export class hidey
+{
+protected:
+ int key;
+
+public:
+ hidey (int key) :key (key)
+ {
+ }
+
+ friend class peeker;
+};
+
+export class secret : public hidey
+{
+public:
+ secret (int key) : hidey (key)
+ {
+ }
+};
+
+// hidey, peeker & secret are all in different clusters
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::peeker'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::peeker'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::hidey'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::hidey'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::secret'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::secret'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/friend-1_b.C b/gcc/testsuite/g++.dg/modules/friend-1_b.C
new file mode 100644
index 0000000..380bbc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module bob;
+
+int peeker::peek (void *data)
+{
+ return reinterpret_cast <secret *> (data)->key;
+}
+
+// { dg-final { scan-lang-dump {Class '::hidey@bob:.' befriending record_type:'::peeker@bob:.'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/friend-1_c.C b/gcc/testsuite/g++.dg/modules/friend-1_c.C
new file mode 100644
index 0000000..2fb2988
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-1_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+int main ()
+{
+ secret s (5);
+
+ if (peeker::peek (&s) != 5)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/friend-2_a.C b/gcc/testsuite/g++.dg/modules/friend-2_a.C
new file mode 100644
index 0000000..ed329d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-2_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bink;
+// { dg-module-cmi bink }
+
+class pusher
+{
+ friend void frob (pusher *){}
+public:
+ pusher (){}
+};
+
+inline void grabber (pusher *p)
+{
+ frob (p);
+}
diff --git a/gcc/testsuite/g++.dg/modules/friend-2_b.C b/gcc/testsuite/g++.dg/modules/friend-2_b.C
new file mode 100644
index 0000000..27034c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-2_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+
+module bink;
+
+struct other {};
+
+void f (pusher *p, other *q)
+{
+ grabber (p);
+
+ frob (p); // ok, found by ADL
+
+ frob (q); // { dg-error "not declared" }
+}
diff --git a/gcc/testsuite/g++.dg/modules/friend-3.C b/gcc/testsuite/g++.dg/modules/friend-3.C
new file mode 100644
index 0000000..48320eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-3.C
@@ -0,0 +1,34 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi !foo }
+
+namespace bob {
+
+export void corge ();
+void grault ();
+
+export class Q
+{
+ friend void foo ();
+ friend void bar ();
+ friend void corge ();
+ friend void grault ();
+};
+
+export void foo ();
+void bar (); // exported
+
+class R
+{
+ friend void quux ();
+ friend void toto ();
+ friend void corge ();
+ friend void grault ();
+};
+
+export void quux (); // { dg-error "conflicting export" }
+void toto (); // not exported
+
+}
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/friend-4_a.C b/gcc/testsuite/g++.dg/modules/friend-4_a.C
new file mode 100644
index 0000000..d9559c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-4_a.C
@@ -0,0 +1,33 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace bob {
+
+export void corge ();
+void grault ();
+
+export class Q
+{
+ friend void foo ();
+ friend void bar ();
+ friend void corge ();
+ friend void grault ();
+ friend void xyzzy (Q);
+};
+
+export void foo ();
+void bar (); // exported
+
+class R
+{
+ friend void toto ();
+ friend void corge ();
+ friend void grault ();
+ friend void xyzzy (R);
+};
+
+void toto (); // not exported
+export R getR ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/friend-4_b.C b/gcc/testsuite/g++.dg/modules/friend-4_b.C
new file mode 100644
index 0000000..759dbb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-4_b.C
@@ -0,0 +1,19 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+using namespace bob;
+
+void doit ()
+{
+ corge ();
+ foo ();
+ bar ();
+
+ grault (); // { dg-error "not declared" }
+ toto (); // { dg-error "not declared" }
+ xyzzy (); // { dg-error "not declared" }
+
+ xyzzy (getR); // ADL
+ xyzzy (Q{}); // ADL
+}
diff --git a/gcc/testsuite/g++.dg/modules/friend-5_a.C b/gcc/testsuite/g++.dg/modules/friend-5_a.C
new file mode 100644
index 0000000..4d005a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-5_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+// From Andrew Sutton
+
+export module foo;
+// { dg-module-cmi foo }
+export class A {
+ friend class B;
+};
diff --git a/gcc/testsuite/g++.dg/modules/friend-5_b.C b/gcc/testsuite/g++.dg/modules/friend-5_b.C
new file mode 100644
index 0000000..f043d7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-5_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+// From Andrew Sutton
+
+export module bar;
+import foo;
+
+class B { // { dg-error "in a different module" }
+ B() { object.value = 42; }
+ A object;
+};
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/gc-1_a.C b/gcc/testsuite/g++.dg/modules/gc-1_a.C
new file mode 100644
index 0000000..5ee20c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gc-1_a.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts --param ggc-min-expand=0 --param ggc-min-heapsize=0" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export int bob ();
+
+void frink ()
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/gc-1_b.C b/gcc/testsuite/g++.dg/modules/gc-1_b.C
new file mode 100644
index 0000000..d6ff09c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gc-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts" }
+export module stuart;
+
+export int stuart ();
diff --git a/gcc/testsuite/g++.dg/modules/gc-1_c.C b/gcc/testsuite/g++.dg/modules/gc-1_c.C
new file mode 100644
index 0000000..289a999
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gc-1_c.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts" }
+export module kevin;
+
+export int kevin ();
diff --git a/gcc/testsuite/g++.dg/modules/gc-1_d.C b/gcc/testsuite/g++.dg/modules/gc-1_d.C
new file mode 100644
index 0000000..a27e5d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gc-1_d.C
@@ -0,0 +1,28 @@
+// { dg-additional-options "-fmodules-ts --param ggc-min-expand=0 --param ggc-min-heapsize=0" }
+
+import bob;
+import stuart;
+import kevin;
+
+void frob ()
+{
+}
+
+void stuart (int);
+
+void quux ()
+{
+ bob ();
+}
+
+void toto ()
+{
+ stuart (1);
+}
+
+void fido ()
+{
+ stuart ();
+ kevin ();
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/gc-2.map b/gcc/testsuite/g++.dg/modules/gc-2.map
new file mode 100644
index 0000000..58963bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gc-2.map
@@ -0,0 +1,2 @@
+$root .
+frob map-1_a.nms
diff --git a/gcc/testsuite/g++.dg/modules/gc-2_a.C b/gcc/testsuite/g++.dg/modules/gc-2_a.C
new file mode 100644
index 0000000..a006fb3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gc-2_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts --param ggc-min-expand=0 --param ggc-min-heapsize=0 -fno-module-lazy -fmodule-mapper=[srcdir]/gc-2.map" }
+// { dg-additional-files map-1.map }
+
+// Make sure the module hash table survives GC
+
+// { dg-module-cmi "=map-1_a.nms" }
+export module frob;
+
+int thing;
diff --git a/gcc/testsuite/g++.dg/modules/global-1_a.C b/gcc/testsuite/g++.dg/modules/global-1_a.C
new file mode 100644
index 0000000..68e18e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/global-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "gmf" 1
+int bar ();
+# 6 "" 2
+export module thing;
+// { dg-module-cmi "thing" }
+
+export int baz ();
diff --git a/gcc/testsuite/g++.dg/modules/global-1_b.C b/gcc/testsuite/g++.dg/modules/global-1_b.C
new file mode 100644
index 0000000..9a67fb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/global-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+import thing;
+
+void bink ()
+{
+ baz ();
+ bar (); // { dg-error "not declared" "" }
+}
diff --git a/gcc/testsuite/g++.dg/modules/gmf-1_a.C b/gcc/testsuite/g++.dg/modules/gmf-1_a.C
new file mode 100644
index 0000000..a340e3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-1_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+
+# 6 "std" 1
+template<typename T>
+class basic_string_view
+{
+public:
+ basic_string_view(const char* __str) noexcept;
+};
+
+# 14 "" 2
+export module hello;
+// { dg-module-cmi hello }
+export void greeter (basic_string_view<char> const &name)
+{
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/gmf-1_b.C b/gcc/testsuite/g++.dg/modules/gmf-1_b.C
new file mode 100644
index 0000000..7162d2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-1_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import hello;
+int main (void)
+{
+ greeter ("world");
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading definition of '::template basic_string_view@hello:1'} module } }
+// { dg-final { scan-lang-dump {Read declaration of '::basic_string_view@hello:1<char>'} module } }
+// { dg-final { scan-lang-dump {Read declaration of '::greeter@hello:1'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/gmf-2_a.H b/gcc/testsuite/g++.dg/modules/gmf-2_a.H
new file mode 100644
index 0000000..4318b16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-2_a.H
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define MACRO(X) X
+
+inline int frob (int x)
+{
+ return x + 2;
+}
diff --git a/gcc/testsuite/g++.dg/modules/gmf-2_b.C b/gcc/testsuite/g++.dg/modules/gmf-2_b.C
new file mode 100644
index 0000000..15fafd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-2_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+module;
+
+import "gmf-2_a.H";
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export inline int MACRO (fn) (int i)
+{
+ return frob (i);
+}
+
+export int (MACRO) (int i);
diff --git a/gcc/testsuite/g++.dg/modules/gmf-2_c.C b/gcc/testsuite/g++.dg/modules/gmf-2_c.C
new file mode 100644
index 0000000..4b4acc6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-2_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+module Foo;
+
+// We see no frob from primary's GMF
+int frob (int x)
+{
+ return fn (-x);
+}
+
+// We see no macro from primary's GMF
+int MACRO (int i)
+{
+ return frob (i);
+}
diff --git a/gcc/testsuite/g++.dg/modules/gmf-2_d.C b/gcc/testsuite/g++.dg/modules/gmf-2_d.C
new file mode 100644
index 0000000..357c8e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-2_d.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+import Foo;
+
+// We see no MACRO
+
+int main ()
+{
+ return !(MACRO (5) == -3);
+}
diff --git a/gcc/testsuite/g++.dg/modules/gvar_a.C b/gcc/testsuite/g++.dg/modules/gvar_a.C
new file mode 100644
index 0000000..2855b33
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gvar_a.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 3 __FILE__ 1
+
+int v1;
+
+# 9 "" 2
+export module b;
+// { dg-module-cmi b }
+
+export inline auto get ()
+{
+ return v1;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/gvar_b.C b/gcc/testsuite/g++.dg/modules/gvar_b.C
new file mode 100644
index 0000000..e53e3f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gvar_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+import b;
+
+int main ()
+{
+ get ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/hdr-1_a.H b/gcc/testsuite/g++.dg/modules/hdr-1_a.H
new file mode 100644
index 0000000..4ce045b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/hdr-1_a.H
@@ -0,0 +1,10 @@
+// { dg-additional-options {-fmodule-header -fdump-lang-module-blocks} }
+
+// { dg-module-cmi {} }
+
+class frob;
+
+template<int I> class FROB;
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::frob'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::template FROB'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/hdr-1_b.H b/gcc/testsuite/g++.dg/modules/hdr-1_b.H
new file mode 100644
index 0000000..6817f93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/hdr-1_b.H
@@ -0,0 +1,21 @@
+// { dg-additional-options {-fmodule-header -fdump-lang-module-blocks} }
+
+// { dg-module-cmi {} }
+
+import "hdr-1_a.H";
+
+class frob
+{
+public:
+ int field;
+};
+
+template<int J>
+class FROB
+{
+public:
+ static constexpr int val = J;
+};
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::frob'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template FROB'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/hdr-1_c.C b/gcc/testsuite/g++.dg/modules/hdr-1_c.C
new file mode 100644
index 0000000..f8fa093
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/hdr-1_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options {-fmodules-ts} }
+
+import "hdr-1_b.H";
+
+int foo (frob *p)
+{
+ return p->field;
+}
+
+int foo (FROB<2> *p)
+{
+ return p->val;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/hdr-init-1_a.H b/gcc/testsuite/g++.dg/modules/hdr-init-1_a.H
new file mode 100644
index 0000000..25cbf3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/hdr-init-1_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+int bob ();
+
+static int var = bob ();
diff --git a/gcc/testsuite/g++.dg/modules/hdr-init-1_b.H b/gcc/testsuite/g++.dg/modules/hdr-init-1_b.H
new file mode 100644
index 0000000..25cbf3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/hdr-init-1_b.H
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+int bob ();
+
+static int var = bob ();
diff --git a/gcc/testsuite/g++.dg/modules/hdr-init-1_c.C b/gcc/testsuite/g++.dg/modules/hdr-init-1_c.C
new file mode 100644
index 0000000..efcc485
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/hdr-init-1_c.C
@@ -0,0 +1,24 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+
+import "hdr-init-1_a.H";
+import "hdr-init-1_b.H";
+
+int bob ()
+{
+ static int i;
+
+ return ++i;
+}
+
+int main ()
+{
+ return !(var == 1);
+}
+
+// { dg-final { scan-lang-dump-times {Reading 1 initializers} 2 module } }
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(new\) var_decl:'::var'} module } }
+// { dg-final { scan-lang-dump-times {Reading definition var_decl '::var@[^\n]*/hdr-init-1_a.H:1'} 2 module } }
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) var_decl:'::var'} module } }
+
diff --git a/gcc/testsuite/g++.dg/modules/horcrux-1_a.C b/gcc/testsuite/g++.dg/modules/horcrux-1_a.C
new file mode 100644
index 0000000..ff548d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/horcrux-1_a.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{};
+
+template<bool __v>
+using __bool_constant = integral_constant<bool, __v>;
+
+template<typename _Tp, typename... _Args>
+struct __is_constructible_impl
+ : public __bool_constant<__is_constructible(_Tp, _Args...)>
+{ };
+
diff --git a/gcc/testsuite/g++.dg/modules/horcrux-1_b.C b/gcc/testsuite/g++.dg/modules/horcrux-1_b.C
new file mode 100644
index 0000000..842bf41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/horcrux-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+int main ()
+{
+ __is_constructible_impl<bool> x;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/ice-1.C b/gcc/testsuite/g++.dg/modules/ice-1.C
new file mode 100644
index 0000000..128734d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ice-1.C
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodules-ts" }
+// we ICED on malformed preambles ending at EOF.
+import bob // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/modules/imp-inline-1_a.C b/gcc/testsuite/g++.dg/modules/imp-inline-1_a.C
new file mode 100644
index 0000000..56bbbdd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-inline-1_a.C
@@ -0,0 +1,37 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+
+# 6 __FILE__ 1
+struct Bob
+{
+ // inline
+ static auto frob ()
+ {
+ }
+};
+
+# 14 "" 2
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export struct Bill
+{
+ // not inline
+ static auto dob ()
+ {
+ }
+ static inline auto frob ()
+ {
+ }
+};
+
+export inline auto GMF ()
+{
+ return Bob::frob ();
+}
+
+// { dg-final { scan-assembler-not {_ZN3Bob4frobEv:} } }
+// { dg-final { scan-assembler-not {_ZN4Bill4frobEv:} } }
+// { dg-final { scan-assembler {_ZN4Bill3dobEv:} } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-inline-1_b.C b/gcc/testsuite/g++.dg/modules/imp-inline-1_b.C
new file mode 100644
index 0000000..c127f70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-inline-1_b.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+
+import Foo;
+
+int main ()
+{
+ GMF ();
+ Bill::dob ();
+ Bill::frob ();
+
+ return 0;
+}
+
+// { dg-final { scan-assembler {_ZN3Bob4frobEv:} } }
+// { dg-final { scan-assembler {_ZN4Bill4frobEv:} } }
+// { dg-final { scan-assembler-not {_ZN4Bill3dobEv:} } }
+// { dg-final { scan-assembler {_Z3GMFv:} } }
+
+// { dg-final { scan-assembler {call[ \t]+_?_ZN3Bob4frobEv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {call[ \t]+_?_Z3GMFv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {call[ \t]+_?_ZN4Bill3dobEv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {call[ \t]+_?_ZN4Bill4frobEv} { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-1_a.C b/gcc/testsuite/g++.dg/modules/imp-member-1_a.C
new file mode 100644
index 0000000..4798ce5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-1_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module A;
+// { dg-module-cmi A }
+
+struct M
+{
+ M (){}
+};
+
+export struct C
+{
+ M m;
+ // lazy implicit ctor
+};
+
+// { dg-final { scan-lang-dump-not {'::C::__ct '} module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-1_b.C b/gcc/testsuite/g++.dg/modules/imp-member-1_b.C
new file mode 100644
index 0000000..849cf3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-1_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module B;
+// { dg-module-cmi B }
+export import A;
+
+export struct D
+{
+ C c;
+
+ // ctor causes C::C to exist, and we need to put it in out CMI
+ inline D (){}
+};
+
+// { dg-final { scan-lang-dump {\[.*\]=decl definition '::C@A:1::__ct '} module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-1_c.C b/gcc/testsuite/g++.dg/modules/imp-member-1_c.C
new file mode 100644
index 0000000..b354ca8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-1_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+import B;
+
+void fn ()
+{
+ D d; // reads in C::C implicit ctor
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::__ct '\n} module } }
+// { dg-final { scan-lang-dump {Adding implicit member '::C@A:.::__ct @B:.} module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-1_d.C b/gcc/testsuite/g++.dg/modules/imp-member-1_d.C
new file mode 100644
index 0000000..c7f3158
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-1_d.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+import B;
+
+void fn ()
+{
+ C c; // creates C::C implicitly (we never read B's version)
+}
+
+// { dg-final { scan-lang-dump-not {Read:-1's named merge key \([a-z]*\) function_decl:'::C@A:.::__ct '\n} module } }
+// { dg-final { scan-lang-dump-not {Adding implicit member '::C@A:.::__ct @B:.} module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-1_e.C b/gcc/testsuite/g++.dg/modules/imp-member-1_e.C
new file mode 100644
index 0000000..b771850
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-1_e.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+import B;
+
+void fn ()
+{
+ C c; // created C::C implicitly
+}
+
+void fn2 ()
+{
+ D d; // merges implicit C::C
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::C@A:.::__ct '\n} module } }
+// { dg-final { scan-lang-dump-not {Adding implicit member '::C@A:.::__ct @B:.} module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-2_a.C b/gcc/testsuite/g++.dg/modules/imp-member-2_a.C
new file mode 100644
index 0000000..8d4d839
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-2_a.C
@@ -0,0 +1,28 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+// A more complete imp-member test
+export module A;
+// { dg-module-cmi A }
+
+struct M
+{
+ M (){}
+ M (M const &){}
+ M (M &&){}
+ ~M (){}
+ M &operator=(M const &){ return *this;}
+ M &operator=(M &&){ return *this;}
+};
+
+export struct C
+{
+ M m;
+ // lazy implicit ctors, dtors, assop
+};
+
+// C doesn't contain a lot
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::C'\n \[1\]=decl declaration '::C::C'\n \[2\]=binding '::C'\n} module } }
+
+// particularly not ...
+// { dg-final { scan-lang-dump-not {'::C::__ct '} module } }
+// { dg-final { scan-lang-dump-not {'::C::__dt '} module } }
+// { dg-final { scan-lang-dump-not {'::C::operator= '} module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-2_b.C b/gcc/testsuite/g++.dg/modules/imp-member-2_b.C
new file mode 100644
index 0000000..09795af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-2_b.C
@@ -0,0 +1,21 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module B;
+// { dg-module-cmi B }
+export import A;
+
+export struct D
+{
+ C c;
+
+ // cause all C's implicit members to exist, and we need to put it in out CMI
+ inline D (){}
+ inline D (D const &v) : c (v.c) {}
+ inline D (D &&v) : c (static_cast<C &&> (v.c)) {}
+ inline ~D () {}
+ inline D &operator= (D const &v) { c = v.c; return *this;}
+ inline D &operator= (D &&v) { c =static_cast<C &&> (v.c); return *this;}
+};
+
+// { dg-final { scan-lang-dump-times {\[0\]=decl definition '::C@A:1::__dt '} 1 module } }
+// { dg-final { scan-lang-dump-times {\[0\]=decl definition '::C@A:1::__ct '} 3 module } }
+// { dg-final { scan-lang-dump-times {\[0\]=decl definition '::C@A:1::operator='} 2 module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-2_c.C b/gcc/testsuite/g++.dg/modules/imp-member-2_c.C
new file mode 100644
index 0000000..bb6b5de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-2_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+import B;
+
+void fn ()
+{
+ D d; // reads in C::C implicits
+}
+
+// { dg-final { scan-lang-dump-times {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::__dt '\n} 1 module } }
+// { dg-final { scan-lang-dump-times {Adding implicit member '::C@A:.::__dt @B:.} 1 module } }
+// { dg-final { scan-lang-dump-times {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::__ct '\n} 3 module } }
+// { dg-final { scan-lang-dump-times {Adding implicit member '::C@A:.::__ct @B:.} 3 module } }
+// { dg-final { scan-lang-dump-times {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::operator='\n} 2 module } }
+// { dg-final { scan-lang-dump-times {Adding implicit member '::C@A:.::operator=@B:.} 2 module } }
diff --git a/gcc/testsuite/g++.dg/modules/imp-member-3.H b/gcc/testsuite/g++.dg/modules/imp-member-3.H
new file mode 100644
index 0000000..d26b13c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/imp-member-3.H
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+class bad_optional_access
+{
+public:
+
+ virtual ~bad_optional_access() noexcept = default; // { dg-bogus "" }
+};
+
+inline void
+__throw_bad_optional_access()
+{
+ throw bad_optional_access ();
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/import-1_a.C b/gcc/testsuite/g++.dg/modules/import-1_a.C
new file mode 100644
index 0000000..b42153c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_a.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+export void Quux (int);
diff --git a/gcc/testsuite/g++.dg/modules/import-1_b.C b/gcc/testsuite/g++.dg/modules/import-1_b.C
new file mode 100644
index 0000000..ec15856
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Baz;
+// { dg-module-cmi "Baz" }
+
+export void Quux (int, int);
diff --git a/gcc/testsuite/g++.dg/modules/import-1_c.C b/gcc/testsuite/g++.dg/modules/import-1_c.C
new file mode 100644
index 0000000..b01aa5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// { dg-final { scan-lang-dump "Writing exported import:.->. Baz" "module" } }
+// { dg-final { scan-lang-dump "Writing exported import:.->. Bar" "module" } }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export import Bar;
+export import Baz;
+
diff --git a/gcc/testsuite/g++.dg/modules/import-1_d.C b/gcc/testsuite/g++.dg/modules/import-1_d.C
new file mode 100644
index 0000000..45e6340
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_d.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Foop;
+// { dg-module-cmi "Foop" }
+
+import Bar;
+
+export int Thing ();
diff --git a/gcc/testsuite/g++.dg/modules/import-1_e.C b/gcc/testsuite/g++.dg/modules/import-1_e.C
new file mode 100644
index 0000000..ae7cce2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_e.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import Foo;
+
+int main ()
+{
+ Quux (1); // from Bar
+ Quux (1, 2); // from Baz
+ return 0;
+}
+
+// { dg-final { scan-lang-dump "Found exported import:1 Bar->1" "module" } }
+// { dg-final { scan-lang-dump "Found exported import:2 Baz->2" "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/import-1_f.C b/gcc/testsuite/g++.dg/modules/import-1_f.C
new file mode 100644
index 0000000..8dbe9c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_f.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+module Foop;
+
+int Thing ()
+{
+ Quux (1); // from Bar
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/import-1_g.C b/gcc/testsuite/g++.dg/modules/import-1_g.C
new file mode 100644
index 0000000..556ba80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-1_g.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts" }
+import Foop;
+
+int main ()
+{
+ Thing ();
+ Quux (1); // { dg-error "not declared" }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/import-2.C b/gcc/testsuite/g++.dg/modules/import-2.C
new file mode 100644
index 0000000..86a1494
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/import-2.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+// Don't segfault on missing module BMI
+
+// { dg-module-cmi "!bob" }
+// { dg-module-cmi "!bill" }
+
+import bill;
+// { dg-regexp "In module imported at \[^\n]*import-2.C:7:.:\nbill: error: failed to read compiled module: \[^\n]*\n" }
+
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
+
diff --git a/gcc/testsuite/g++.dg/modules/inc-xlate-1.map b/gcc/testsuite/g++.dg/modules/inc-xlate-1.map
new file mode 100644
index 0000000..f2429bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inc-xlate-1.map
@@ -0,0 +1,2 @@
+<stdarg.h>
+<stdio.h>
diff --git a/gcc/testsuite/g++.dg/modules/inc-xlate-1_a.H b/gcc/testsuite/g++.dg/modules/inc-xlate-1_a.H
new file mode 100644
index 0000000..cd906a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inc-xlate-1_a.H
@@ -0,0 +1,15 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#ifndef _STDARG_H
+#define _STDARG_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern void frob ();
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/inc-xlate-1_b.H b/gcc/testsuite/g++.dg/modules/inc-xlate-1_b.H
new file mode 100644
index 0000000..50b27ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inc-xlate-1_b.H
@@ -0,0 +1,21 @@
+// { dg-do preprocess }
+// { dg-additional-options -fmodule-header }
+
+#ifndef _STDIO_H
+#define _STDIO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Yes, inside extern "C" block :(
+ #include "inc-xlate-1_a.H"
+ #ifndef _STDARG_H
+ #error barf
+ #endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+// { dg-final { scan-file inc-xlate-1_b.i {import "[^\n]*inc-xlate-1_a.H" \[\[__translated\]\];\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/inc-xlate-1_c.C b/gcc/testsuite/g++.dg/modules/inc-xlate-1_c.C
new file mode 100644
index 0000000..e1247e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inc-xlate-1_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+extern "C" {
+ #include "inc-xlate-1_a.H"
+}
+
+int main ()
+{
+ frob ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/inc-xlate-1_e.C b/gcc/testsuite/g++.dg/modules/inc-xlate-1_e.C
new file mode 100644
index 0000000..f33c464
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inc-xlate-1_e.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|@g++-mapper-server\\ -t\\ [srcdir]/inc-xlate-1.map" }
+export module bad;
+#include "inc-xlate-1_a.H" // { dg-error "not be include-translated" }
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-1_a.C b/gcc/testsuite/g++.dg/modules/indirect-1_a.C
new file mode 100644
index 0000000..f241717
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-1_a.C
@@ -0,0 +1,41 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import. Non-template cases
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo {
+
+ export int frob (int i)
+ {
+ return i;
+ }
+
+
+ export class X
+ {
+ int i;
+
+ public:
+ X (int i) :i(i) { }
+ operator int () const { return i; }
+ };
+
+ export class Y : public virtual X
+ {
+ int j;
+ public:
+ Y (int i, int j) : X(i), j(j){}
+ virtual int frob () const;
+ };
+
+ int Y::frob () const
+ {
+ return *this + j;
+ }
+
+ export enum Plain {A, B, C, D};
+ export enum class Scoped {A, B, C, D};
+}
diff --git a/gcc/testsuite/g++.dg/modules/indirect-1_b.C b/gcc/testsuite/g++.dg/modules/indirect-1_b.C
new file mode 100644
index 0000000..c450fa9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-1_b.C
@@ -0,0 +1,54 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int frob (int i = foo::frob (0))
+ {
+ return i;
+ }
+
+ export int quux (int i = foo::X (0) )
+ {
+ return i;
+ }
+
+ export class Z : public foo::Y
+ {
+ public:
+ Z (int i, int j) : X(i), Y(i, j)
+ {
+ }
+ };
+
+ export constexpr auto Plain_One (bool b) { return b ? foo::B : foo::C; }
+ export constexpr auto Scoped_One (bool b) { return b ? foo::Scoped::B
+ : foo::Scoped::C; }
+
+ export extern auto const Plain_Const_Three = foo::D;
+ export extern auto const Scoped_Const_Three = foo::Scoped::D;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::frob'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {namespace:-[0-9]* namespace_decl:'::foo'} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* function_decl:'::foo@foo:.::frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::X'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::foo@foo:.::X@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::Y'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::foo@foo:.::Y@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::B'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::C@foo:.'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::Scoped'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::Scoped@foo:.::[ABCD]'@'foo' section:} module } }
+
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Plain@\(foo\)::C'@foo} module } }
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Plain@\(foo\)::B'@foo} module } }
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Scoped@\(foo\)::C'@foo} module } }
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Scoped@\(foo\)::B'@foo} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-1_c.C b/gcc/testsuite/g++.dg/modules/indirect-1_c.C
new file mode 100644
index 0000000..73d5974
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-1_c.C
@@ -0,0 +1,49 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import bar;
+
+
+int main ()
+{
+ if (bar::frob ())
+ return 1;
+ if (bar::quux ())
+ return 2;
+
+ if (bar::Z (1, 2).frob () != 3)
+ return 3;
+
+ static_assert (bar::Plain_One (true) == 1);
+ static_assert (bar::Plain_One (false) == 2);
+ static_assert (int (bar::Scoped_One (true)) == 1);
+ static_assert (int (bar::Scoped_One (false)) == 2);
+
+ static_assert (bar::Plain_Const_Three == 3);
+ static_assert (int (bar::Scoped_Const_Three) == 3);
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::frob'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[14\] section:4} module } }
+// { dg-final { scan-lang-dump {Named:-[0-9]* namespace_decl:'::foo@foo:1'@foo} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* function_decl:'::foo@foo:.::frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* type_decl:'::foo@foo:.::X@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Z'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[8\] section:2} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* type_decl:'::foo@foo:.::Y@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Read member:-[0-9]* field_decl:'::foo@foo:.::Y@foo:.::_vptr.Y'} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* function_decl:'::foo@foo:.::Y@foo:.::frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Plain_One'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[13\] section:3} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Scoped_One'@'bar' section} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[15\] section:5} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::[ABC]'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::Scoped@\(foo\)::[ABC]'@'foo' section:} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Plain_Const_Three'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Scoped_Const_Three'@'bar' section} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-2_a.C b/gcc/testsuite/g++.dg/modules/indirect-2_a.C
new file mode 100644
index 0000000..20febb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-2_a.C
@@ -0,0 +1,24 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import, simple templates
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+ export template<int I> int frob ()
+ {
+ return I;
+ }
+
+ export template<int I> class X
+ {
+ int i = I;
+
+ public:
+ operator int () const { return i; }
+ };
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/indirect-2_b.C b/gcc/testsuite/g++.dg/modules/indirect-2_b.C
new file mode 100644
index 0000000..16e060a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-2_b.C
@@ -0,0 +1,31 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias-uid" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int frob (int i = foo::frob<0> ())
+ {
+ return i;
+ }
+
+ export int quux (int i = foo::X<0> ())
+ {
+ return i;
+ }
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::frob'@'foo' section} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template frob@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo@foo:.::frob<0x0>'} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::X'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template X@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::X<0x0>'\n \[1\]=specialization declaration '::foo@foo:.::X<0x0>::__conv_op <0x0>'\n \[2\]=specialization declaration '::foo@foo:.::X<0x0>::X<0x0>'\n( \[.\]=[^\n]* '\n)*} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::X<0x0>'} module } }
+// { dg-final { scan-lang-dump {Depset:. specialization entity:. type_decl:'::foo@foo:.::X<0x0>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::X<0x0>'} module } }
+// { dg-final { scan-lang-dump {Wrote purview:-[0-9]* type_decl:'::foo@foo:.::X<0x0>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-2_c.C b/gcc/testsuite/g++.dg/modules/indirect-2_c.C
new file mode 100644
index 0000000..a5cf44b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-2_c.C
@@ -0,0 +1,25 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import bar;
+
+int main ()
+{
+
+ if (bar::frob ())
+ return 1;
+
+ if (bar::quux ())
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::frob'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[4\] section:2} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template frob@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump-not {Wrote mergeable} module } }
+
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template X@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]* function_decl:'::foo@foo:.::frob<0x0>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-3_a.C b/gcc/testsuite/g++.dg/modules/indirect-3_a.C
new file mode 100644
index 0000000..fad9ecf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-3_a.C
@@ -0,0 +1,23 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import, template member non-template or
+// non-template member of template cases
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+ export class X
+ {
+ public:
+ template <int I> int frob () const { return I; }
+ };
+
+ export template<int I> class TPL
+ {
+ public:
+ int frob () const { return I; }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/modules/indirect-3_b.C b/gcc/testsuite/g++.dg/modules/indirect-3_b.C
new file mode 100644
index 0000000..5bdfc1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-3_b.C
@@ -0,0 +1,30 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-uid-alias" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int quux (int i = foo::X().frob<0> ())
+ {
+ return i;
+ }
+
+ export int toto (int i = foo::TPL<0>().frob ())
+ {
+ return i;
+ }
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::X'@'foo' section} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::X@foo:.::template frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::TPL'@'foo' section} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x0>'\n \[1\]=specialization declaration '::foo@foo:.::TPL<0x0>::TPL<0x0>'\n( \[.\]=[^\n]* '\n)* \[.\]=decl definition '::foo@foo:.::TPL<0x0>::frob<0x0>'\n} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::X@foo:.::frob<0x0>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::TPL<0x0>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo@foo:.::X@foo:.::frob<0x0>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-3_c.C b/gcc/testsuite/g++.dg/modules/indirect-3_c.C
new file mode 100644
index 0000000..9c5cb23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-3_c.C
@@ -0,0 +1,24 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import bar;
+
+int main ()
+{
+
+ if (bar::quux ())
+ return 1;
+
+ if (bar::toto ())
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[5\] section:2} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::X@foo:.::template frob@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump-not {Instantiation:-[0-9]* function_decl:'::foo::X@foo:.::frob@.()<0x0>'} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::toto'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Reading definition type_decl '::foo@foo:.::TPL@bar:.<0x0>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-4_a.C b/gcc/testsuite/g++.dg/modules/indirect-4_a.C
new file mode 100644
index 0000000..44f4b66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-4_a.C
@@ -0,0 +1,20 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import, template member of template case
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+ export template<int I> class TPL
+ {
+ public:
+ template <int J> int frob () const
+ {
+ return I + J;
+ }
+ };
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/indirect-4_b.C b/gcc/testsuite/g++.dg/modules/indirect-4_b.C
new file mode 100644
index 0000000..8c51ce8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-4_b.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias-uid" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int quux (int i = foo::TPL<1> ().frob<2> ())
+ {
+ return i;
+ }
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::TPL'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x1>'\n \[1\]=specialization declaration '::foo@foo:.::TPL<0x1>::template frob<#unnamed#>'\n \[2\]=specialization declaration '::foo@foo:.::TPL<0x1>::TPL<0x1>'\n( \[.\]=[^\n]* '\n)*} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x1>::frob<0x2>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::TPL<0x1>'} module } }
+// { dg-final { scan-lang-dump {Wrote purview:-[0-9]* type_decl:'::foo@foo:.::TPL<0x1>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo@foo:.::TPL<0x1>::frob<0x2>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/indirect-4_c.C b/gcc/testsuite/g++.dg/modules/indirect-4_c.C
new file mode 100644
index 0000000..7efcc11
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/indirect-4_c.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid-alias" }
+import bar;
+
+int main ()
+{
+ if (bar::quux () != 3)
+ return 1;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[2\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Reading definition function_decl '::foo@foo:.::TPL@bar:.<0x1>::frob@bar:.<0x2>'} module } }
+// { dg-final { scan-lang-dump {Reading definition type_decl '::foo@foo:.::TPL@bar:.<0x1>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inext-1.H b/gcc/testsuite/g++.dg/modules/inext-1.H
new file mode 100644
index 0000000..7708c39
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inext-1.H
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodule-header -isystem [srcdir] -isystem [srcdir]/sys -fdump-lang-module" }
+
+#ifndef _PROTECT
+#define _PROTECT
+
+/* We were found on the system inc path, so have been turned into a
+ system header, so no warning on the following extension. */
+#include_next <inext-1.H>
+
+#endif
+
diff --git a/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1.h b/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1.h
new file mode 100644
index 0000000..13f769f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1.h
@@ -0,0 +1,35 @@
+
+template <typename _Tp>
+struct Base
+{
+ // template constructor
+ template<typename _Del> Base(_Tp *__p, _Del __d);
+};
+
+template <typename _Tp, typename _Dp>
+struct Derived : Base<_Tp>
+{
+ // Inheriting the template constructor
+ using Base<_Tp>::Base;
+};
+
+template <typename _Tp>
+class unique_ptr
+{
+ Derived<_Tp, int> _M_t;
+
+public:
+ // Instantiates Derived<ResultDerived,int>::Derived
+ template<typename _Up> unique_ptr(unique_ptr<_Up>&& __u) noexcept
+ : _M_t ((_Tp *)0, 1) { }
+};
+
+struct ResultBase { };
+struct ResultDerived : ResultBase { };
+
+void Frob (unique_ptr<ResultBase> &&__res) ;
+
+inline void X (unique_ptr<ResultDerived> &parm)
+{
+ Frob (static_cast <unique_ptr<ResultDerived> &&> (parm));
+}
diff --git a/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_a.H b/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_a.H
new file mode 100644
index 0000000..8222212
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "inh-tmpl-ctor-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_b.C b/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_b.C
new file mode 100644
index 0000000..ae1612c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inh-tmpl-ctor-1_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "inh-tmpl-ctor-1.h"
+import "inh-tmpl-ctor-1_a.H";
+
diff --git a/gcc/testsuite/g++.dg/modules/init-1_a.C b/gcc/testsuite/g++.dg/modules/init-1_a.C
new file mode 100644
index 0000000..b5727d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-1_a.C
@@ -0,0 +1,11 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+export module Foo;
+// { dg-module-cmi Foo }
+
+int Frob (int i)
+{
+ return i;
+}
+
+export int j = Frob (5);
diff --git a/gcc/testsuite/g++.dg/modules/init-1_b.C b/gcc/testsuite/g++.dg/modules/init-1_b.C
new file mode 100644
index 0000000..3d2239f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-1_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+import Foo;
+
+int frob (int j)
+{
+ return j + 1;
+}
+
+int q = frob (j);
+
+int main ()
+{
+ return !(q == 6);
+}
diff --git a/gcc/testsuite/g++.dg/modules/init-2_a.C b/gcc/testsuite/g++.dg/modules/init-2_a.C
new file mode 100644
index 0000000..1e9093ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-2_a.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+export module Foo;
+// { dg-module-cmi Foo }
+
+// { dg-final { scan-assembler {_ZGIW3FooEv:} } }
diff --git a/gcc/testsuite/g++.dg/modules/init-2_b.C b/gcc/testsuite/g++.dg/modules/init-2_b.C
new file mode 100644
index 0000000..b9692ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-2_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+export module Bar;
+// { dg-module-cmi Bar }
+
+import Foo;
+
+// { dg-final { scan-assembler {_?_ZGIW3BarEv:} } }
+// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3FooEv} { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/modules/init-2_c.C b/gcc/testsuite/g++.dg/modules/init-2_c.C
new file mode 100644
index 0000000..c1fa5d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-2_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+
+import Foo;
+import Bar;
+
+// We know Bar imports Foo, so only call Bar's Global Init
+// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3BarEv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler-not {call[ \t]+_?_ZGIW3FooEv} { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-1_a.C b/gcc/testsuite/g++.dg/modules/inst-1_a.C
new file mode 100644
index 0000000..e1d438b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-1_a.C
@@ -0,0 +1,42 @@
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+int i_baz (int i)
+{
+ return i;
+}
+
+inline int baz (int i)
+{
+ return i_baz (i);
+}
+
+int f_baz (float f)
+{
+ return int (f);
+}
+
+inline int baz (float f)
+{
+ return f_baz (f);
+}
+
+export template <typename T>
+int foo (T t)
+{
+ return baz (t);
+}
+
+export inline void user ()
+{
+ foo (1);
+ foo (1.0f);
+}
+
+// { dg-final { scan-lang-dump {Depending definition function_decl:'::foo<float>'} module } }
+// { dg-final { scan-lang-dump {Depending definition function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {\[0\]=specialization definition '::foo<float>'} module } }
+// { dg-final { scan-lang-dump {\[0\]=specialization definition '::foo<int>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-1_b.C b/gcc/testsuite/g++.dg/modules/inst-1_b.C
new file mode 100644
index 0000000..08a92ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-1_b.C
@@ -0,0 +1,16 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-uid-alias} }
+import foo;
+
+int main ()
+{
+ user ();
+ foo ('a'); // new inst
+ foo (1); // find foo's inst
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading definition function_decl '::foo@foo:.<int>'} module } }
+// { dg-final { scan-lang-dump {Reading definition function_decl '::foo@foo:.<float>'} module } }
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(unique\) function_decl:'::baz'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(unique\) function_decl:'::baz'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-2_a.C b/gcc/testsuite/g++.dg/modules/inst-2_a.C
new file mode 100644
index 0000000..40d6229
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-2_a.C
@@ -0,0 +1,26 @@
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-blocks-uid-alias} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+inline int baz (int i)
+{
+ return i;
+}
+
+export template <typename T>
+inline int foo (T t)
+{
+ return baz (t);
+}
+
+export inline void user ()
+{
+ foo (1);
+}
+
+// { dg-final { scan-lang-dump {\[0\]=specialization definition '::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s named merge key \(decl\) function_decl:'::baz'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo<int>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-2_b.C b/gcc/testsuite/g++.dg/modules/inst-2_b.C
new file mode 100644
index 0000000..3e918bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-2_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-uid-alias} }
+import foo;
+
+int main ()
+{
+ foo (1); // read pending inst
+ user (); //
+ foo (1); // reuse inst
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations} module } }
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(new\) function_decl:'::foo'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-3_a.C b/gcc/testsuite/g++.dg/modules/inst-3_a.C
new file mode 100644
index 0000000..3305805
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-3_a.C
@@ -0,0 +1,21 @@
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks-alias} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T> struct TPL
+{
+ T m;
+};
+
+export inline int user (int i)
+{
+ TPL<int> x;
+ x.m = i;
+ return x.m;
+}
+
+// { dg-final { scan-lang-dump {Cluster members:\n( \[.\]=[^\n]*'\n)* \[.\]=specialization definition '::TPL<int>'\n \[.\]=specialization declaration '::TPL<int>::TPL<int>'\n} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::TPL<int>'} module } }
+// { dg-final { scan-lang-dump {Depset:. specialization entity:. type_decl:'::TPL<int>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-3_b.C b/gcc/testsuite/g++.dg/modules/inst-3_b.C
new file mode 100644
index 0000000..80a9946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-3_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias-uid} }
+import foo;
+
+int main ()
+{
+ if (user (1) != 1)
+ return 1;
+ TPL<int> x;
+ TPL<float> y;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s type spec merge key \(new\) type_decl:'::TPL'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(new\) type_decl:'::template TPL@foo:.<T>::TPL'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-4_a.C b/gcc/testsuite/g++.dg/modules/inst-4_a.C
new file mode 100644
index 0000000..e7435ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-4_a.C
@@ -0,0 +1,20 @@
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks-alias} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T> struct TPL
+{
+ T m;
+};
+
+export inline int user (int i)
+{
+ TPL<int> x;
+ x.m = i;
+ return x.m;
+}
+
+// { dg-final { scan-lang-dump {Specialization '::TPL<int>' entity:. keyed to foo\[.\] '::template TPL'} module } }
+// { dg-final { scan-lang-dump {Specialization '::TPL<int>::TPL<int>' entity:. keyed to foo\[.\] '::template TPL<T>::template TPL'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-4_b.C b/gcc/testsuite/g++.dg/modules/inst-4_b.C
new file mode 100644
index 0000000..c83e1c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-4_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias-uid} }
+import foo;
+
+int main ()
+{
+ TPL<int> x;
+ if (user (1) != 1)
+ return 1;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to foo\[.\] '::template TPL@foo:.'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s type spec merge key \(new\) type_decl:'::TPL'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/inst-5_a.H b/gcc/testsuite/g++.dg/modules/inst-5_a.H
new file mode 100644
index 0000000..46d9432
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-5_a.H
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template <int I> int fn ()
+{
+ return I;
+}
+
+inline void g ()
+{
+ fn<1> (); // instantiation gets emitted
+}
diff --git a/gcc/testsuite/g++.dg/modules/inst-5_b.C b/gcc/testsuite/g++.dg/modules/inst-5_b.C
new file mode 100644
index 0000000..7cc94c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/inst-5_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+template <int I> int fn ()
+{
+ return I;
+}
+
+void f ()
+{
+ fn<1> ();
+}
+
+import "inst-5_a.H";
+// no longer need to instantate
diff --git a/gcc/testsuite/g++.dg/modules/internal-1.C b/gcc/testsuite/g++.dg/modules/internal-1.C
new file mode 100644
index 0000000..45d3bf0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-1.C
@@ -0,0 +1,21 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob; // { dg-error "failed to write" }
+// { dg-module-cmi !frob }
+
+namespace {
+// We shouldn't be complaining about members of internal linkage
+// entities
+class X // { dg-bogus "internal linkage" "" { xfail *-*-* } }
+{ // { dg-bogus "internal linkage" "" { xfail *-*-* } }
+};
+
+}
+
+static int frob ()
+{
+ return 1;
+}
+
+export int f (int = frob ()); // { dg-error "references internal linkage" }
+int goof (X &); // { dg-error "references internal linkage" }
diff --git a/gcc/testsuite/g++.dg/modules/internal-2_a.H b/gcc/testsuite/g++.dg/modules/internal-2_a.H
new file mode 100644
index 0000000..4b530bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-2_a.H
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options {-fmodule-header -fdump-lang-module-blocks} }
+// { dg-module-cmi {} }
+
+static int bob (int x)
+{
+ return x;
+}
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::bob'\n \[1\]=binding '::bob'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/internal-2_b.H b/gcc/testsuite/g++.dg/modules/internal-2_b.H
new file mode 100644
index 0000000..cdcbe77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-2_b.H
@@ -0,0 +1,7 @@
+// { dg-additional-options {-fmodule-header} }
+// { dg-module-cmi {} }
+
+static int bob (int x)
+{
+ return x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/internal-2_c.C b/gcc/testsuite/g++.dg/modules/internal-2_c.C
new file mode 100644
index 0000000..c0bc46d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-2_c.C
@@ -0,0 +1,12 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+
+import "internal-2_a.H";
+import "internal-2_b.H";
+
+int main ()
+{
+ bob (2);
+}
+
+// { dg-final { scan-lang-dump { Read:-1's named merge key \(new\) function_decl:'::bob'} module } }
+// { dg-final { scan-lang-dump { Read:-1's named merge key \(matched\) function_decl:'::bob'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/isalnum.H b/gcc/testsuite/g++.dg/modules/isalnum.H
new file mode 100644
index 0000000..2fac358
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/isalnum.H
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C"
+{
+ extern int isalnum (int) __attribute__ ((__nothrow__, __leaf__));
+}
+
+namespace std
+{
+using ::isalnum;
+}
diff --git a/gcc/testsuite/g++.dg/modules/keyword-1_a.C b/gcc/testsuite/g++.dg/modules/keyword-1_a.C
new file mode 100644
index 0000000..190f573
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/keyword-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export struct import {};
+export ::import *a;
+export ::import (b);
diff --git a/gcc/testsuite/g++.dg/modules/keyword-1_b.C b/gcc/testsuite/g++.dg/modules/keyword-1_b.C
new file mode 100644
index 0000000..24a5b5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/keyword-1_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import bob;
+
+::import (d); // not import
+import (e); // not import
+
+void foo ()
+{
+ void *c = a;
+ void *e = &b;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/lambda-1_a.C b/gcc/testsuite/g++.dg/modules/lambda-1_a.C
new file mode 100644
index 0000000..1b97187
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-1_a.C
@@ -0,0 +1,15 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module tom.riddle;
+// { dg-module-cmi tom.riddle }
+
+export inline auto One (int a)
+{
+ return [=] (int b) { return a + b; };
+}
+
+// Look Ma! this isn't inline!
+export auto Two (int a)
+{
+ return [=] (int b) { return a * b; };
+}
diff --git a/gcc/testsuite/g++.dg/modules/lambda-1_b.C b/gcc/testsuite/g++.dg/modules/lambda-1_b.C
new file mode 100644
index 0000000..af21349
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-1_b.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+import tom.riddle;
+
+int main ()
+{
+ auto one = One (2);
+
+ if (one (1) != 3)
+ return 1;
+
+ auto two = Two (3);
+ if (two (2) != 6)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/lambda-2.h b/gcc/testsuite/g++.dg/modules/lambda-2.h
new file mode 100644
index 0000000..3433686
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-2.h
@@ -0,0 +1,2 @@
+// The lambda is attached to 'all', and should be merged keyed by that.
+inline constexpr auto all = [] () {};
diff --git a/gcc/testsuite/g++.dg/modules/lambda-2_a.H b/gcc/testsuite/g++.dg/modules/lambda-2_a.H
new file mode 100644
index 0000000..7940120
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-2_a.H
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias" }
+// { dg-module-cmi {} }
+
+#include "lambda-2.h"
+
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s attached merge key \(decl\) type_decl:'::._anon_0'} module } }
+// { dg-final { scan-lang-dump {Written -[0-9]*\[0\] attached decl '::._anon_0'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/lambda-2_b.C b/gcc/testsuite/g++.dg/modules/lambda-2_b.C
new file mode 100644
index 0000000..56ec9e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-2_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+// Not an ODR violation!
+#include "lambda-2.h"
+import "lambda-2_a.H";
+
+// { dg-bogus "conflicting" "not an odr violation" }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s attached merge key \(matched\) type_decl:'#null#'} module } }
+// { dg-final { scan-lang-dump {Read -[0-9]*\[0\] matched attached decl '::._anon_0'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/lambda-2_c.C b/gcc/testsuite/g++.dg/modules/lambda-2_c.C
new file mode 100644
index 0000000..c626b9d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-2_c.C
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "lambda-2_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/lambda-3.h b/gcc/testsuite/g++.dg/modules/lambda-3.h
new file mode 100644
index 0000000..8f60a82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-3.h
@@ -0,0 +1,5 @@
+
+template<int I> inline constexpr auto tmpl = [] {return I;};
+
+inline const auto tpl_1 = tmpl<1>;
+inline const auto tpl_2 = tmpl<2>;
diff --git a/gcc/testsuite/g++.dg/modules/lambda-3_a.H b/gcc/testsuite/g++.dg/modules/lambda-3_a.H
new file mode 100644
index 0000000..171a263
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-3_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias" }
+// { dg-module-cmi {} }
+
+#include "lambda-3.h"
diff --git a/gcc/testsuite/g++.dg/modules/lambda-3_b.C b/gcc/testsuite/g++.dg/modules/lambda-3_b.C
new file mode 100644
index 0000000..25a418b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-3_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "lambda-3.h"
+import "lambda-3_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump {Read -1\[0\] matched attached decl '::template ._anon_0<#unnamed#>'} module } }
+// { dg-final { scan-lang-dump {Read -1\[0\] matched attached decl '::._anon_2'} module } }
+// { dg-final { scan-lang-dump {Read -1\[0\] matched attached decl '::._anon_1'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/lambda-3_c.C b/gcc/testsuite/g++.dg/modules/lambda-3_c.C
new file mode 100644
index 0000000..69efa50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-3_c.C
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "lambda-3_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/lambda-4.h b/gcc/testsuite/g++.dg/modules/lambda-4.h
new file mode 100644
index 0000000..fe9a06b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-4.h
@@ -0,0 +1,2 @@
+
+inline void (*all) (int) = [] (auto) {};
diff --git a/gcc/testsuite/g++.dg/modules/lambda-4_a.H b/gcc/testsuite/g++.dg/modules/lambda-4_a.H
new file mode 100644
index 0000000..738ea8b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-4_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias" }
+// { dg-module-cmi {} }
+
+#include "lambda-4.h"
diff --git a/gcc/testsuite/g++.dg/modules/lambda-4_b.C b/gcc/testsuite/g++.dg/modules/lambda-4_b.C
new file mode 100644
index 0000000..772045d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-4_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "lambda-4.h"
+import "lambda-4_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) template_decl:'::._anon_0::template _FUN'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) template_decl:'::._anon_0::template __conv_op '} module } }
diff --git a/gcc/testsuite/g++.dg/modules/lang-1_a.H b/gcc/testsuite/g++.dg/modules/lang-1_a.H
new file mode 100644
index 0000000..8131d3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lang-1_a.H
@@ -0,0 +1,15 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C"
+{
+ int cfunc ();
+}
+
+extern "C++"
+{
+ int cxxfunc ();
+}
+
+
+
diff --git a/gcc/testsuite/g++.dg/modules/lang-1_b.C b/gcc/testsuite/g++.dg/modules/lang-1_b.C
new file mode 100644
index 0000000..0db144c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lang-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+extern "C"
+{
+ import "lang-1_a.H";
+}
+
+extern "C" int cfunc (int); // { dg-error "conflicting declaration" }
+extern "C" int cxxfunc (int);
diff --git a/gcc/testsuite/g++.dg/modules/lang-1_c.C b/gcc/testsuite/g++.dg/modules/lang-1_c.C
new file mode 100644
index 0000000..e3b939d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lang-1_c.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules-ts }
+
+extern "C++"
+{
+ import "lang-1_a.H";
+}
+
+extern "C"
+import "lang-1_a.H"; // { dg-error "cannot appear directly" }
+
+extern "C" int cfunc (int); // { dg-error "conflicting declaration" }
+extern "C" int cxxfunc (int);
diff --git a/gcc/testsuite/g++.dg/modules/lang-2_a.C b/gcc/testsuite/g++.dg/modules/lang-2_a.C
new file mode 100644
index 0000000..a3bbe72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lang-2_a.C
@@ -0,0 +1,3 @@
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
diff --git a/gcc/testsuite/g++.dg/modules/lang-2_b.C b/gcc/testsuite/g++.dg/modules/lang-2_b.C
new file mode 100644
index 0000000..0a7a0d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lang-2_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+extern "C"
+{
+ import foo; // { dg-warning "inside language-linkage" }
+}
+extern "C++"
+{
+ import foo; // { dg-warning "inside language-linkage" }
+}
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-1.H b/gcc/testsuite/g++.dg/modules/late-ret-1.H
new file mode 100644
index 0000000..fb73e51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-1.H
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _Iterator>
+struct reverse_iterator
+{
+ _Iterator base() const;
+};
+
+template<typename _Iterator>
+reverse_iterator<_Iterator> __make_reverse_iterator (_Iterator __i);
+
+template<typename _Iterator>
+auto __niter_base(reverse_iterator<_Iterator> __it)
+ -> decltype (__make_reverse_iterator(__niter_base(__it.base())))
+{ return __make_reverse_iterator(__niter_base(__it.base())); }
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-2_a.H b/gcc/testsuite/g++.dg/modules/late-ret-2_a.H
new file mode 100644
index 0000000..0ff435f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-2_a.H
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module-blocks" }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL {operator T () const {return 0;}};
+
+template<typename T>
+auto Foo (T *arg)
+ -> TPL<decltype (+*arg)> {return TPL<int> ();}
+
+template<typename T>
+auto Bar (T *arg)
+ -> TPL<decltype (arg)> ;
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::template Foo'\n \[1\]=specialization declaration '::TPL<#null#>'\n \[2\]=binding '::Foo'\n} module } }
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-2_b.H b/gcc/testsuite/g++.dg/modules/late-ret-2_b.H
new file mode 100644
index 0000000..80b83f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-2_b.H
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL {operator T () const {return 0;}};
+
+template<typename T>
+auto Foo (T *arg)
+ -> TPL<decltype (+*arg)> {return TPL<int> ();}
+
+// Deliberately different to 2_a's Bar
+template<typename T>
+auto Bar (T *arg)
+ -> TPL<decltype (*arg)> ;
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-2_c.C b/gcc/testsuite/g++.dg/modules/late-ret-2_c.C
new file mode 100644
index 0000000..c5898fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-2_c.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+import "late-ret-2_a.H";
+import "late-ret-2_b.H";
+
+int main ()
+{
+ int *p = 0;
+ int j = Foo (p);
+
+ Bar (p); // { dg-error "ambiguous" }
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template Foo'\n Deduping '::template Foo@[^\n]*/late-ret-2_a.H:.'\n} module } }
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-3_a.H b/gcc/testsuite/g++.dg/modules/late-ret-3_a.H
new file mode 100644
index 0000000..54f95db
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-3_a.H
@@ -0,0 +1,20 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module-blocks" }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL_1 { using type = T;};
+
+template<typename U> struct TPL_2 { using type = int;};
+
+template<typename V> using TPL_3 = typename TPL_2<V>::type;
+
+template<typename A>
+auto Foo (const A& arg)
+ -> TPL_3<typename TPL_1<decltype(arg)>::type>
+ {return 3;}
+
+template<typename A>
+auto Bar (const A& arg)
+ -> TPL_3<typename TPL_1<decltype(arg)>::type>
+ {return 3;}
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::template Foo'\n \[1\]=specialization declaration '::TPL_1<#null#>'\n \[2\]=specialization declaration '::TPL_3<::TPL_1<#null#>::type>'\n \[3\]=specialization declaration '::TPL_2<::TPL_1<#null#>::type>'\n \[4\]=binding '::Foo'\n} module } }
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-3_b.H b/gcc/testsuite/g++.dg/modules/late-ret-3_b.H
new file mode 100644
index 0000000..2ec63ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-3_b.H
@@ -0,0 +1,20 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL_1 { using type = T;};
+
+template<typename U> struct TPL_2 { using type = int;};
+
+template<typename V> using TPL_3 = typename TPL_2<V>::type;
+
+template<typename A>
+auto Foo (const A& arg)
+ -> TPL_3<typename TPL_1<decltype(arg)>::type>
+ {return 3;}
+
+// Deliberately different to 3_a's Bar
+template<typename A>
+auto Bar (const A& arg)
+ -> TPL_3<typename TPL_1<int>::type>
+ {return 3;}
+
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-3_c.C b/gcc/testsuite/g++.dg/modules/late-ret-3_c.C
new file mode 100644
index 0000000..fae9565
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/late-ret-3_c.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+import "late-ret-3_a.H";
+import "late-ret-3_b.H";
+
+struct Arg
+{
+ int type;
+};
+
+int main ()
+{
+ Arg arg;
+
+ int j = Foo (arg);
+
+ Bar (arg); // { dg-error "ambiguous" }
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) template_decl:'::template Foo'\n Deduping '::template Foo@[^\n]*/late-ret-3_a.H:.'\n} module } }
diff --git a/gcc/testsuite/g++.dg/modules/lazy-1_a.C b/gcc/testsuite/g++.dg/modules/lazy-1_a.C
new file mode 100644
index 0000000..0f7c7c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lazy-1_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi "foo" }
+
+export int bar ()
+{
+ return 1;
+}
+
+export int baz ()
+{
+ return 2;
+}
+
+export int quux ()
+{
+ return 3;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/lazy-1_b.C b/gcc/testsuite/g++.dg/modules/lazy-1_b.C
new file mode 100644
index 0000000..af213d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lazy-1_b.C
@@ -0,0 +1,21 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+// Check some lazy loading
+
+import foo;
+
+int main ()
+{
+ bar ();
+
+ baz ();
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar'@'foo' section} "module" } }
+// { dg-final { scan-lang-dump {Lazily binding '::baz'@'foo' section} "module" } }
+// quux is not referenced, so never loaded
+// { dg-final { scan-lang-dump {Bindings '::quux' section} "module" } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::quux'@'foo' section} "module" } }
+// { dg-final { scan-lang-dump-not {Read -[0-9]* function_decl:'::quux'} "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-1_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-1_a.H
new file mode 100644
index 0000000..e7506b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-1_a.H
@@ -0,0 +1,5 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+int bob (int);
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-1_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-1_b.H
new file mode 100644
index 0000000..07ae824
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-1_b.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+int bob (int);
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-1_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-1_c.C
new file mode 100644
index 0000000..b204d54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-1_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-1_a.H";
+import "leg-merge-1_b.H";
+
+int main ()
+{
+ return bob (0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-1_d.C b/gcc/testsuite/g++.dg/modules/leg-merge-1_d.C
new file mode 100644
index 0000000..f785452
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-1_d.C
@@ -0,0 +1,4 @@
+int bob (int i)
+{
+ return i;
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-2_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-2_a.H
new file mode 100644
index 0000000..d891c89
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-2_a.H
@@ -0,0 +1,5 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+class X;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-2_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-2_b.H
new file mode 100644
index 0000000..b9be14d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-2_b.H
@@ -0,0 +1,5 @@
+// { dg-module-do link }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+class X;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-2_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-2_c.C
new file mode 100644
index 0000000..d5a4da9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-2_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-2_a.H";
+import "leg-merge-2_b.H";
+
+int main ()
+{
+ X *ptr = 0;
+
+ return ptr != 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-3_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-3_a.H
new file mode 100644
index 0000000..9142340
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-3_a.H
@@ -0,0 +1,5 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern int bob;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-3_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-3_b.H
new file mode 100644
index 0000000..2ba847b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-3_b.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern int bob;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-3_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-3_c.C
new file mode 100644
index 0000000..c6b71b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-3_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-3_a.H";
+import "leg-merge-3_b.H";
+
+int main ()
+{
+ return !(bob == 17);
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-3_d.C b/gcc/testsuite/g++.dg/modules/leg-merge-3_d.C
new file mode 100644
index 0000000..36f028c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-3_d.C
@@ -0,0 +1 @@
+int bob = 17;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-4_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-4_a.H
new file mode 100644
index 0000000..9c61ea2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-4_a.H
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern int bob;
+void frob ();
+class X;
+
+extern int ok;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-4_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-4_b.H
new file mode 100644
index 0000000..09c895f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-4_b.H
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern float bob;
+int frob ();
+union X;
+
+int ok ();
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-4_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-4_c.C
new file mode 100644
index 0000000..f1b1aeb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-4_c.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-4_a.H";
+import "leg-merge-4_b.H";
+
+void foo ()
+{
+ 2[0]; // { dg-error "" }
+ bob = 5;
+ frob ();
+ X *p;
+}
+
+// { dg-regexp "\nIn module \[^\n]*leg-merge-4_b.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_b.H:4:\[0-9]*: error: conflicting global module declaration 'float bob'\nIn module \[^\n]*leg-merge-4_a.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_a.H:4:\[0-9]*: note: existing declaration 'int bob'\n\[^\n]*leg-merge-4_c.C:9:\[0-9]*: note: during load of binding '::bob'$" }
+
+// { dg-regexp "\nIn module \[^\n]*leg-merge-4_b.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_b.H:5:\[0-9]*: error: conflicting global module declaration 'int frob\\(\\)'\nIn module \[^\n]*leg-merge-4_a.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_a.H:5:\[0-9]*: note: existing declaration 'void frob\\(\\)'\n\[^\n]*leg-merge-4_c.C:10:\[0-9]*: note: during load of binding '::frob'$" }
+
+// { dg-regexp "In module \[^\n]*leg-merge-4_b.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_b.H:6:\[0-9]*: error: conflicting global module declaration 'union X'\nIn module \[^\n]*leg-merge-4_a.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_a.H:6:\[0-9]*: note: existing declaration 'class X'\n\[^\n]*leg-merge-4_c.C:11:\[0-9]*: note: during load of binding '::X'$" }
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-5_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-5_a.H
new file mode 100644
index 0000000..ba92696
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-5_a.H
@@ -0,0 +1,9 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+inline int bob (int x)
+{
+ return x;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-5_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-5_b.H
new file mode 100644
index 0000000..b77efb3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-5_b.H
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+inline int bob (int x)
+{
+ return x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-5_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-5_c.C
new file mode 100644
index 0000000..cd1e757
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-5_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-5_a.H";
+import "leg-merge-5_b.H";
+
+int main ()
+{
+ return bob (0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-6_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-6_a.H
new file mode 100644
index 0000000..64e8d28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-6_a.H
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+struct X
+{
+ int m;
+ X (int m) :m(m) {}
+ operator int () const { return m; }
+};
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-6_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-6_b.H
new file mode 100644
index 0000000..2179d90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-6_b.H
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+struct X
+{
+ int m;
+ X (int m) :m(m) {}
+ operator int () const { return m; }
+};
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-6_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-6_c.C
new file mode 100644
index 0000000..dddd88c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-6_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-6_a.H";
+import "leg-merge-6_b.H";
+
+int main ()
+{
+ X x (75);
+
+ return !(int (x) == 75);
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-7_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-7_a.H
new file mode 100644
index 0000000..d8ea859
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-7_a.H
@@ -0,0 +1,8 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> int foo (int i)
+{
+ return I == i;
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-7_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-7_b.H
new file mode 100644
index 0000000..9ec045b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-7_b.H
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> int foo (int i)
+{
+ return I == i;
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-7_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-7_c.C
new file mode 100644
index 0000000..0efdc0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-7_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-7_a.H";
+import "leg-merge-7_b.H";
+
+int main ()
+{
+ return !foo<2> (2);
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-8_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-8_a.H
new file mode 100644
index 0000000..ad9a2f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-8_a.H
@@ -0,0 +1,13 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> struct Tpl
+{
+ int i;
+ Tpl () : i (I){}
+ operator int () const
+ {
+ return i;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-8_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-8_b.H
new file mode 100644
index 0000000..845984c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-8_b.H
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> struct Tpl
+{
+ int i;
+ Tpl () : i (I){}
+ operator int () const
+ {
+ return i;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-8_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-8_c.C
new file mode 100644
index 0000000..fa67db9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-8_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-8_a.H";
+import "leg-merge-8_b.H";
+
+int main ()
+{
+ Tpl<1> one;
+
+ return !(one == 1);
+}
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-9_a.H b/gcc/testsuite/g++.dg/modules/leg-merge-9_a.H
new file mode 100644
index 0000000..518ecbd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-9_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef int X;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-9_b.H b/gcc/testsuite/g++.dg/modules/leg-merge-9_b.H
new file mode 100644
index 0000000..518ecbd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-9_b.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef int X;
diff --git a/gcc/testsuite/g++.dg/modules/leg-merge-9_c.C b/gcc/testsuite/g++.dg/modules/leg-merge-9_c.C
new file mode 100644
index 0000000..3c75dc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/leg-merge-9_c.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+import "leg-merge-9_a.H";
+import "leg-merge-9_b.H";
+
+X an_int;
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-1_a.H b/gcc/testsuite/g++.dg/modules/legacy-1_a.H
new file mode 100644
index 0000000..3ab0856
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-1_a.H
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef HEADER_H
+#define HEADER_H
+
+int frob (int);
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/legacy-1_b.C b/gcc/testsuite/g++.dg/modules/legacy-1_b.C
new file mode 100644
index 0000000..f758e3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-1_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+int frob (int a)
+{
+ return a + 2;
+}
diff --git a/gcc/testsuite/g++.dg/modules/legacy-1_c.C b/gcc/testsuite/g++.dg/modules/legacy-1_c.C
new file mode 100644
index 0000000..277231c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-1_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "legacy-1_a.H";
+
+int main ()
+{
+ return !(frob (-2) == 0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/legacy-2.h b/gcc/testsuite/g++.dg/modules/legacy-2.h
new file mode 100644
index 0000000..2bac5c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-2.h
@@ -0,0 +1 @@
+#define FROB frob
diff --git a/gcc/testsuite/g++.dg/modules/legacy-2.map b/gcc/testsuite/g++.dg/modules/legacy-2.map
new file mode 100644
index 0000000..9de5392
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-2.map
@@ -0,0 +1 @@
+"legacy-2_a.H"
diff --git a/gcc/testsuite/g++.dg/modules/legacy-2_a.H b/gcc/testsuite/g++.dg/modules/legacy-2_a.H
new file mode 100644
index 0000000..076bdbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-2_a.H
@@ -0,0 +1,8 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+// this is a legacy header
+
+int frob (int);
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-2_b.H b/gcc/testsuite/g++.dg/modules/legacy-2_b.H
new file mode 100644
index 0000000..0d4ae07
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-2_b.H
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodule-header -fmodule-mapper=|@g++-mapper-server\\ -mt\\ $srcdir/g++.dg/modules/legacy-2.map" }
+// { dg-module-cmi {} }
+
+#define frob FROB
+
+// this should be diverted, if it isn't the above #define will break us
+#include "legacy-2_a.H"
+int move (int X = __LINE__); // Capture __LINE__ in a non-definition
+
+// this should not be diverted
+#include "legacy-2.h"
+
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-2_c.C b/gcc/testsuite/g++.dg/modules/legacy-2_c.C
new file mode 100644
index 0000000..ff31bd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-2_c.C
@@ -0,0 +1,8 @@
+int frob (int a)
+{
+ return a * 2;
+}
+int move (int a)
+{
+ return a;
+}
diff --git a/gcc/testsuite/g++.dg/modules/legacy-2_d.C b/gcc/testsuite/g++.dg/modules/legacy-2_d.C
new file mode 100644
index 0000000..5384d32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-2_d.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import "legacy-2_b.H";
+
+int main ()
+{
+ if (frob (2) != 4)
+ return 1;
+ /* Check line number is not disturbed. */
+ if (move () != 8)
+ return 2;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/legacy-3.h b/gcc/testsuite/g++.dg/modules/legacy-3.h
new file mode 100644
index 0000000..2bac5c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-3.h
@@ -0,0 +1 @@
+#define FROB frob
diff --git a/gcc/testsuite/g++.dg/modules/legacy-3_a.H b/gcc/testsuite/g++.dg/modules/legacy-3_a.H
new file mode 100644
index 0000000..74d2755
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-3_a.H
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+// this is a legacy header
+
+int frob (int);
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-3_b.H b/gcc/testsuite/g++.dg/modules/legacy-3_b.H
new file mode 100644
index 0000000..3bf819d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-3_b.H
@@ -0,0 +1,16 @@
+// { dg-do preprocess }
+// { dg-additional-options -fmodule-header }
+
+#define frob FROB
+
+// Enough blank lines to force a line sync before the legacy import
+
+// this should be diverted, if it isn't the above #define will break us
+#include "legacy-3_a.H"
+int move (int X = __LINE__); // Capture __LINE__ in a non-definition
+
+// this should not be diverted
+#include "legacy-3.h"
+
+// { dg-final { scan-file legacy-3_b.i {\n# 9 "[^\n]*legacy-3_b.H"\nimport "[^\n]*legacy-3_a.H" \[\[__translated\]\];\nint move \(int X = 10\);\n} } }
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-3_c.H b/gcc/testsuite/g++.dg/modules/legacy-3_c.H
new file mode 100644
index 0000000..56b8172
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-3_c.H
@@ -0,0 +1,25 @@
+// { dg-do preprocess }
+// { dg-additional-options -fmodule-header }
+
+#define frob FROB
+
+// this should be translated, if it isn't the above #define will break
+// us
+MARK1 __LINE__
+#include "legacy-3_a.H"
+MARK2 __LINE__
+int move (int X = __LINE__); // Capture __LINE__ in a non-definition
+// this should also be translated, but elided too
+MARK2 __LINE__
+#include "legacy-3_a.H"
+MARK3 __LINE__
+
+// this should not be translated
+#include "legacy-3.h"
+
+// { dg-final { scan-file legacy-3_c.i {MARK1 8\nimport "[^\n]*legacy-3_a.H" \[\[__translated\]\];\nMARK2 10\n} } }
+// We should have stopped.
+// { dg-final { scan-file legacy-3_c.i {move} } }
+// { dg-final { scan-file legacy-3_c.i {MARK2 13\n\nMARK3 15\n} } }
+// { dg-final { scan-file-not legacy-3_c.i {# [^\n]*legacy-3_a.H} } }
+// { dg-final { scan-file legacy-3_c.i {# [^\n]*legacy-3.h} } }
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6.map b/gcc/testsuite/g++.dg/modules/legacy-6.map
new file mode 100644
index 0000000..8199bf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6.map
@@ -0,0 +1,2 @@
+./legacy-6_a.H
+./legacy-6_b.H
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6_a.H b/gcc/testsuite/g++.dg/modules/legacy-6_a.H
new file mode 100644
index 0000000..7d7e970
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+// this is a legacy user header
+
+int frob (int);
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6_b.H b/gcc/testsuite/g++.dg/modules/legacy-6_b.H
new file mode 100644
index 0000000..1a52d42
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6_b.H
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+// this is a legacy user header
+
+int frob (float);
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6_c.C b/gcc/testsuite/g++.dg/modules/legacy-6_c.C
new file mode 100644
index 0000000..0b5bd7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6_c.C
@@ -0,0 +1,8 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|@g++-mapper-server\\ -mt\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+#include "legacy-6_b.H"
+int i;
+
+// { dg-final { scan-file legacy-6_c.i {import "[^\n]*legacy-6_a.H" \[\[__translated\]\];\nimport "[^\n]*legacy-6_b.H" \[\[__translated\]\];\nint i;} } }
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6_d.C b/gcc/testsuite/g++.dg/modules/legacy-6_d.C
new file mode 100644
index 0000000..58ca21d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6_d.C
@@ -0,0 +1,9 @@
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|@g++-mapper-server\\ -mt\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+int i;
+#include "legacy-6_b.H"
+
+// { dg-final { scan-file legacy-6_d.i {import "[^\n]*legacy-6_a.H" \[\[__translated\]\];\nint i;} } }
+// { dg-final { scan-file legacy-6_d.i {int i;\nimport "[^\n]*legacy-6_b.H" \[\[__translated\]\];\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6_e.C b/gcc/testsuite/g++.dg/modules/legacy-6_e.C
new file mode 100644
index 0000000..9d4dd92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6_e.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodule-mapper=|@mapper-server\\ -f\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+#include "legacy-6_b.H"
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/legacy-6_f.C b/gcc/testsuite/g++.dg/modules/legacy-6_f.C
new file mode 100644
index 0000000..c15eade
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-6_f.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodule-mapper=|@mapper-server\\ -f\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+int i;
+#include "legacy-6_b.H"
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-7_a.H b/gcc/testsuite/g++.dg/modules/legacy-7_a.H
new file mode 100644
index 0000000..49578a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-7_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+#define throw(...) /* { dg-warning "-:not exporting" } */ \
+ noexcept(__VA_OPT__(false))
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-7_b.C b/gcc/testsuite/g++.dg/modules/legacy-7_b.C
new file mode 100644
index 0000000..d78f45c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-7_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+import "legacy-7_a.H";
+
+#ifdef throw
+#error barf
+#endif
+
diff --git a/gcc/testsuite/g++.dg/modules/legacy-8_a.H b/gcc/testsuite/g++.dg/modules/legacy-8_a.H
new file mode 100644
index 0000000..a30cd88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-8_a.H
@@ -0,0 +1,5 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+int sqr (int);
diff --git a/gcc/testsuite/g++.dg/modules/legacy-8_b.H b/gcc/testsuite/g++.dg/modules/legacy-8_b.H
new file mode 100644
index 0000000..62366e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-8_b.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+float sqr (float);
diff --git a/gcc/testsuite/g++.dg/modules/legacy-8_c.C b/gcc/testsuite/g++.dg/modules/legacy-8_c.C
new file mode 100644
index 0000000..88300b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-8_c.C
@@ -0,0 +1,13 @@
+#include "legacy-8_a.H"
+#include "legacy-8_a.H"
+
+int sqr (int a)
+{
+ return a * a;
+}
+
+
+float sqr (float a)
+{
+ return a * a;
+}
diff --git a/gcc/testsuite/g++.dg/modules/legacy-8_d.C b/gcc/testsuite/g++.dg/modules/legacy-8_d.C
new file mode 100644
index 0000000..85377d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-8_d.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+import "legacy-8_a.H";
+import "legacy-8_b.H";
+
+export inline int Sqr (int a)
+{
+ return sqr (a);
+}
+
+export inline float Sqr (float a)
+{
+ return sqr (a);
+}
diff --git a/gcc/testsuite/g++.dg/modules/legacy-8_e.C b/gcc/testsuite/g++.dg/modules/legacy-8_e.C
new file mode 100644
index 0000000..afeb19a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/legacy-8_e.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+int main ()
+{
+ int (*ifp) (int) = Sqr;
+ float (*ffp) (float) = Sqr;
+
+ if (ifp (2) != 4)
+ return 1;
+
+ // Comparing these two floats is ok
+ if (ffp (2.0f) != 4.0f)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/libfn-1_a.C b/gcc/testsuite/g++.dg/modules/libfn-1_a.C
new file mode 100644
index 0000000..a8a8ee8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/libfn-1_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodules-ts }
+// Make sure we're not confused by an imported declaration of a
+// library fn
+export module foo;
+// { dg-module-cmi foo }
+
+export inline void thrower ()
+{
+ try
+ {
+ throw 1;
+ }
+ catch (...)
+ {
+ }
+}
diff --git a/gcc/testsuite/g++.dg/modules/libfn-1_b.C b/gcc/testsuite/g++.dg/modules/libfn-1_b.C
new file mode 100644
index 0000000..0e8346b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/libfn-1_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+import foo;
+
+void bar ()
+{
+ thrower ();
+}
+
+void baz ()
+{
+ try
+ {
+ throw 1;
+ }
+ catch (...)
+ {
+ }
+}
diff --git a/gcc/testsuite/g++.dg/modules/literals-1_a.C b/gcc/testsuite/g++.dg/modules/literals-1_a.C
new file mode 100644
index 0000000..9fb2aea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/literals-1_a.C
@@ -0,0 +1,51 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -Wno-pedantic -Wno-psabi" }
+
+// Make sure e can serialize various literals. */
+
+export module real2reel;
+// { dg-module-cmi real2reel }
+
+export inline float assassing ()
+{
+ return 2.0f;
+}
+
+export inline double market (float square, double heroes)
+{
+ return 4.0 * square * heroes;
+}
+
+using cplx_i = __complex__ int;
+using cplx_f = __complex__ float;
+using cplx_d = __complex__ double;
+
+export inline cplx_i cinderella_search ()
+{
+ return (cplx_i) {1, 2};
+}
+export inline cplx_f emerald_lies ()
+{
+ return (cplx_f) {3, 4};
+}
+export inline cplx_d forgotten_sons ()
+{
+ return (cplx_d) {5, 6};
+}
+
+export inline int garden_party (unsigned ix)
+{
+ return "invites call the debs to play"[ix];
+}
+
+using vec = int __attribute__((vector_size (sizeof (int) * 4)));
+
+export inline vec incubus ()
+{
+ return (vec){1,7,3,9}; // Not an arithmetic series
+}
+
+export inline vec charting_the_single ()
+{
+ return (vec){1,2,3,4}; // An arithmetic series
+}
diff --git a/gcc/testsuite/g++.dg/modules/literals-1_b.C b/gcc/testsuite/g++.dg/modules/literals-1_b.C
new file mode 100644
index 0000000..5468944
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/literals-1_b.C
@@ -0,0 +1,39 @@
+// { dg-additional-options {-fmodules-ts -Wno-psabi} }
+
+import real2reel;
+
+int main ()
+{
+ if (assassing () != 2.0f)
+ return 1;
+
+ if (market (/*square=*/2.0f, /*heroes=*/7.0) != 56.0)
+ return 2;
+
+ auto c_i = cinderella_search ();
+ if (__real__ (c_i) != 1 || __imag__ (c_i) != 2)
+ return 3;
+
+ auto c_f = emerald_lies ();
+ if (__real__ (c_f) != 3.0f || __imag__ (c_f) != 4.0f)
+ return 4;
+
+ auto c_d = forgotten_sons ();
+ if (__real__ (c_d) != 5.0 || __imag__ (c_d) != 6.0)
+ return 5;
+
+
+ if (garden_party (7) != ' ')
+ return 6;
+
+ auto v = incubus ();
+ if (v[0] != 1 || v[1] != 7 || v[2] != 3 || v[3] != 9)
+ return 7;
+
+ v = charting_the_single ();
+ if (v[0] != 1 || v[1] != 2 || v[2] != 3 || v[3] != 4)
+ return 8;
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/loc-1_a.C b/gcc/testsuite/g++.dg/modules/loc-1_a.C
new file mode 100644
index 0000000..8155181
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-1_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export int frob (int *); // line 5
diff --git a/gcc/testsuite/g++.dg/modules/loc-1_b.C b/gcc/testsuite/g++.dg/modules/loc-1_b.C
new file mode 100644
index 0000000..0a0b85e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module stuart;
+// { dg-module-cmi stuart }
+
+
+export int frob (float *); // line 6
+
diff --git a/gcc/testsuite/g++.dg/modules/loc-1_c.C b/gcc/testsuite/g++.dg/modules/loc-1_c.C
new file mode 100644
index 0000000..f952259
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-1_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import bob;
+import stuart;
+
+void kevin ()
+{
+ frob (nullptr); // { dg-error "call of overload" }
+}
+
+// { dg-regexp "In module stuart, imported at \[^\n]*loc-1_c.C:4:\n\[^\n]*loc-1_b.C:7:12: note:.*" }
+// { dg-regexp "In module bob, imported at \[^\n]*loc-1_c.C:3:\n\[^\n]*loc-1_a.C:6:12: note:.*" }
+
+
diff --git a/gcc/testsuite/g++.dg/modules/loc-2_a.C b/gcc/testsuite/g++.dg/modules/loc-2_a.C
new file mode 100644
index 0000000..a4bbce3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-2_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export int frob (int *);
diff --git a/gcc/testsuite/g++.dg/modules/loc-2_b.C b/gcc/testsuite/g++.dg/modules/loc-2_b.C
new file mode 100644
index 0000000..4264009
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-2_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module stuart;
+// { dg-module-cmi stuart }
+
+export import bob;
diff --git a/gcc/testsuite/g++.dg/modules/loc-2_c.C b/gcc/testsuite/g++.dg/modules/loc-2_c.C
new file mode 100644
index 0000000..e731d50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-2_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module kevin;
+// { dg-module-cmi kevin }
+
+export import stuart;
+export import bob; // Bob should be reseated in the export map
+export import stuart;
diff --git a/gcc/testsuite/g++.dg/modules/loc-2_d.C b/gcc/testsuite/g++.dg/modules/loc-2_d.C
new file mode 100644
index 0000000..4ae8a69
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-2_d.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import stuart;
+
+void foo ()
+{
+ frob (2); /* { dg-error "invalid conversion" } */
+}
+
+// { dg-regexp "In module bob, imported at \[^\n]*loc-2_b.C:6,\nof module stuart, imported at \[^\n]*loc-2_d.C:3:\n\[^\n]*loc-2_a.C:6:18: note:.*" }
diff --git a/gcc/testsuite/g++.dg/modules/loc-2_e.C b/gcc/testsuite/g++.dg/modules/loc-2_e.C
new file mode 100644
index 0000000..c4d0acb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-2_e.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import stuart;
+import bob;
+import stuart;
+
+void foo ()
+{
+ frob (2); // { dg-error "invalid conversion" }
+}
+
+// { dg-regexp "In module bob, imported at \[^\n]*loc-2_e.C:4:\n\[^\n]*loc-2_a.C:6:18: note:.*" }
diff --git a/gcc/testsuite/g++.dg/modules/loc-2_f.C b/gcc/testsuite/g++.dg/modules/loc-2_f.C
new file mode 100644
index 0000000..2888d04
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-2_f.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import kevin;
+
+void foo ()
+{
+ frob (2); // { dg-error "invalid conversion" }
+}
+
+// { dg-regexp "In module bob, imported at \[^\n]*loc-2_c.C:7,\nof module kevin, imported at \[^\n]*loc-2_f.C:3:\n\[^\n]*loc-2_a.C:6:18: note:.*" }
diff --git a/gcc/testsuite/g++.dg/modules/loc-wrapper-1.h b/gcc/testsuite/g++.dg/modules/loc-wrapper-1.h
new file mode 100644
index 0000000..04e62d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-wrapper-1.h
@@ -0,0 +1,14 @@
+template<typename _Tp>
+struct __is_integer
+{
+ enum { __value = 0 };
+};
+
+template<typename _Tp>
+struct __is_integer_nonstrict
+
+{
+ using __is_integer<_Tp>::__value;
+
+ enum { __width = __value ? sizeof(_Tp) * 8 : 0 };
+};
diff --git a/gcc/testsuite/g++.dg/modules/loc-wrapper-1_a.H b/gcc/testsuite/g++.dg/modules/loc-wrapper-1_a.H
new file mode 100644
index 0000000..cddb46f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-wrapper-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+#include "loc-wrapper-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/loc-wrapper-1_b.C b/gcc/testsuite/g++.dg/modules/loc-wrapper-1_b.C
new file mode 100644
index 0000000..6d0229a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/loc-wrapper-1_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+// ICEd comparing VIEW_CONVERT_EXPR location wrappers with null types
+#include "loc-wrapper-1.h"
+import "loc-wrapper-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/local-1_a.C b/gcc/testsuite/g++.dg/modules/local-1_a.C
new file mode 100644
index 0000000..c1a3343
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/local-1_a.C
@@ -0,0 +1,13 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module the.shop;
+// { dg-module-cmi the.shop }
+
+export int for_local_people ()
+{
+ struct X {int a;};
+ X m;
+ m.a = 5;
+ return m.a;
+}
diff --git a/gcc/testsuite/g++.dg/modules/local-1_b.C b/gcc/testsuite/g++.dg/modules/local-1_b.C
new file mode 100644
index 0000000..37a9461
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/local-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+import the.shop;
+
+int main ()
+{
+ if (for_local_people () != 5)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/local-extern-1.C b/gcc/testsuite/g++.dg/modules/local-extern-1.C
new file mode 100644
index 0000000..7b01605
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/local-extern-1.C
@@ -0,0 +1,20 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+# 4 __FILE__ 1
+inline void frob ()
+{
+ extern int bob; // OK
+}
+
+# 11 "" 2
+export module bob;
+// { dg-module-cmi !bob }
+
+inline void dob ()
+{
+ extern int bob; // { dg-error "block-scope extern" }
+}
+
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/local-extern-2.H b/gcc/testsuite/g++.dg/modules/local-extern-2.H
new file mode 100644
index 0000000..dab5ee4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/local-extern-2.H
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+
+inline int *wcstok(int *__wcstok_ws1)
+{
+ extern int *__iso_wcstok(int * bob);
+
+ return __iso_wcstok(__wcstok_ws1);
+}
diff --git a/gcc/testsuite/g++.dg/modules/local-struct-1_a.C b/gcc/testsuite/g++.dg/modules/local-struct-1_a.C
new file mode 100644
index 0000000..b4323b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/local-struct-1_a.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export inline int __inline_signbitf (float __x)
+{
+ union x { float __f; unsigned int __u; } __u;
+
+ __u.__f = __x;
+
+ return int (__u.__u >> 31);
+}
diff --git a/gcc/testsuite/g++.dg/modules/local-struct-1_b.C b/gcc/testsuite/g++.dg/modules/local-struct-1_b.C
new file mode 100644
index 0000000..96968e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/local-struct-1_b.C
@@ -0,0 +1,3 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
+
+import foo;
diff --git a/gcc/testsuite/g++.dg/modules/macloc-1_a.C b/gcc/testsuite/g++.dg/modules/macloc-1_a.C
new file mode 100644
index 0000000..a152b51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macloc-1_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module agnes;
+// { dg-module-cmi agnes }
+
+int a;
+
+#define BOB(X) int X ()
+#define KEVIN(X) int X ()
+
+export BOB(me);
+export KEVIN(you);
+
diff --git a/gcc/testsuite/g++.dg/modules/macloc-1_b.C b/gcc/testsuite/g++.dg/modules/macloc-1_b.C
new file mode 100644
index 0000000..8f8f1f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macloc-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module edith;
+// { dg-module-cmi edith }
+
+#define STUART(X) X
+
+import STUART(agnes);
+
+export void STUART(gru) ();
diff --git a/gcc/testsuite/g++.dg/modules/macloc-1_c.C b/gcc/testsuite/g++.dg/modules/macloc-1_c.C
new file mode 100644
index 0000000..9b8f7fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macloc-1_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module edith;
+
+void gru ()
+{
+ me (1);
+ you (1);
+}
+
+// { dg-regexp "\[^\n]*macloc-1_c.C:7:8: error: too many arguments to function 'int me@agnes\\(\\)'\nIn module agnes, imported at \[^\n]*macloc-1_b.C:8,\nof module edith, imported at \[^\n]*macloc-1_c.C:3:\n\[^\n]*macloc-1_a.C:11:12: note: declared here\n\[^\n]*macloc-1_a.C:8:20: note: in definition of macro 'BOB'\n" }
+
+// { dg-regexp "\[^\n]*macloc-1_c.C:8:9: error: too many arguments to function 'int you@agnes\\(\\)'\nIn module agnes, imported at \[^\n]*macloc-1_b.C:8,\nof module edith, imported at \[^\n]*macloc-1_c.C:3:\n\[^\n]*macloc-1_a.C:12:14: note: declared here\n\[^\n]*macloc-1_a.C:9:22: note: in definition of macro 'KEVIN'\n" }
diff --git a/gcc/testsuite/g++.dg/modules/macloc-1_d.C b/gcc/testsuite/g++.dg/modules/macloc-1_d.C
new file mode 100644
index 0000000..5b2b7ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macloc-1_d.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import edith;
+import agnes;
+
+void margo ()
+{
+ me (1);
+ gru (2);
+}
+
+// { dg-regexp "\[^\n]*macloc-1_d.C:8:8: error: too many arguments to function 'int me@agnes\\(\\)'\nIn module agnes, imported at \[^\n]*macloc-1_d.C:4:\n\[^\n]*macloc-1_a.C:11:12: note: declared here\n\[^\n]*macloc-1_a.C:8:20: note: in definition of macro 'BOB'\n" }
+// { dg-regexp "\[^\n]*macloc-1_d.C:9:9: error: too many arguments to function 'void gru@edith\\(\\)'\nIn module edith, imported at \[^\n]*macloc-1_d.C:3:\n\[^\n]*macloc-1_b.C:10:20: note: declared here\n\[^\n]*macloc-1_b.C:6:19: note: in definition of macro 'STUART'\n" }
diff --git a/gcc/testsuite/g++.dg/modules/macloc-2_a.H b/gcc/testsuite/g++.dg/modules/macloc-2_a.H
new file mode 100644
index 0000000..99f0884
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macloc-2_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options {-fmodule-header -nostdinc} }
+// { dg-module-cmi {} }
+
+#define MACRO(X) X
+
+inline int frob (int x)
+{
+ return x + 2;
+}
diff --git a/gcc/testsuite/g++.dg/modules/macloc-2_b.C b/gcc/testsuite/g++.dg/modules/macloc-2_b.C
new file mode 100644
index 0000000..601a477
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macloc-2_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options {-fmodules-ts -nostdinc} }
+module;
+
+import "macloc-2_a.H";
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export inline int MACRO (fn) (int i)
+{
+ return frob (i);
+}
+
+export int (MACRO) (int i);
diff --git a/gcc/testsuite/g++.dg/modules/macro-1_a.H b/gcc/testsuite/g++.dg/modules/macro-1_a.H
new file mode 100644
index 0000000..5b212a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-1_a.H
@@ -0,0 +1,12 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_1_H
+#define MACRO_1_H
+#define foo bar baz
+#define kevin(X) stuart (X)
+#define stuart(X) bob ("banana", X) // Yes we have X bananas
+#define bob(...) {__VA_ARGS__}
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-1_b.C b/gcc/testsuite/g++.dg/modules/macro-1_b.C
new file mode 100644
index 0000000..afbcab2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-1_b.C
@@ -0,0 +1,25 @@
+// { dg-additional-options "-fmodules-ts" }
+import "macro-1_a.H";
+
+#define baz = + 1
+int foo;
+struct X
+{
+ const char *s;
+ int v;
+}
+;
+X x kevin (5);
+
+int main ()
+{
+ if (foo != 1)
+ return 1;
+ if (x.v != 5)
+ return 2;
+ const char *banana = "banana";
+ for (unsigned ix = 0; banana[ix]; ix++)
+ if (banana[ix] != x.s[ix])
+ return 3;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/macro-2_a.H b/gcc/testsuite/g++.dg/modules/macro-2_a.H
new file mode 100644
index 0000000..89d66a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-2_a.H
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_2a_H
+#define MACRO_2a_H
+
+#define FOO_OK foo
+#define BAR_OK(BAZ) BINKY(2)
+
+#define FOO_BAD foo
+#define BAR_BAD(BAZ) BINKY(2)
+
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-2_b.H b/gcc/testsuite/g++.dg/modules/macro-2_b.H
new file mode 100644
index 0000000..5690712
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-2_b.H
@@ -0,0 +1,24 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+
+
+
+// Make line numbers distinct from macro-2_a.H
+
+
+
+
+
+
+#ifndef MACRO_2b_H
+#define MACRO_2b_H
+
+#define FOO_OK foo
+#define BAR_OK(BAZ) BINKY(2)
+
+#define FOO_BAD foot
+#define BAR_BAD(BAZ) BINKY(3)
+
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-2_c.H b/gcc/testsuite/g++.dg/modules/macro-2_c.H
new file mode 100644
index 0000000..ed05323
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-2_c.H
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_2c_H
+#define MACRO_2c_H
+import "macro-2_a.H";
+
+#endif
+
+// { dg-final { scan-lang-dump-not {Read new macro #define MACRO_2a_H at} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-2_d.C b/gcc/testsuite/g++.dg/modules/macro-2_d.C
new file mode 100644
index 0000000..04b80fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-2_d.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+
+#define BINKY(X) X
+
+import "macro-2_a.H";
+import "macro-2_b.H";
+
+int FOO_OK = BAR_OK(1);
+
+int BAR_BAD;
+// { dg-regexp {[^\n]*macro-2_d.C:10:5: error: inconsistent imported macro definition 'BAR_BAD'\nIn module [^\n]*macro-2_a.H, imported at [^\n]*macro-2_d.C:5:\n[^\n]*macro-2_a.H:11: note: '#define BAR_BAD\(BAZ\) BINKY\(2\)'\nIn module [^\n]*macro-2_b.H, imported at [^\n]*macro-2_d.C:6:\n[^\n]*macro-2_b.H:21: note: '#define BAR_BAD\(BAZ\) BINKY\(3\)'\n} }
+
+int FOO_BAD;
+// { dg-regexp {[^\n]*macro-2_d.C:13:5: error: inconsistent imported macro definition 'FOO_BAD'\nIn module [^\n]*macro-2_a.H, imported at [^\n]*macro-2_d.C:5:\n[^\n]*macro-2_a.H:10: note: '#define FOO_BAD foo'\nIn module [^\n]*macro-2_b.H, imported at [^\n]*macro-2_d.C:6:\n[^\n]*macro-2_b.H:20: note: '#define FOO_BAD foot'\n} }
diff --git a/gcc/testsuite/g++.dg/modules/macro-3_a.H b/gcc/testsuite/g++.dg/modules/macro-3_a.H
new file mode 100644
index 0000000..6582e3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-3_a.H
@@ -0,0 +1,19 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header -fdump-lang-module-vops" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_3a_H
+#define MACRO_3a_H
+
+#undef nothing
+#define bob x
+#undef bob
+#define foo 1
+#define bar 2
+
+#endif
+
+// { dg-final { scan-lang-dump {Writing macro #define foo at} module } }
+// { dg-final { scan-lang-dump {Writing macro #define bar at} module } }
+// { dg-final { scan-lang-dump-not {Writing macro #define bob at} module } }
+// { dg-final { scan-lang-dump-not {Writing macro #undef nothing at} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-3_b.H b/gcc/testsuite/g++.dg/modules/macro-3_b.H
new file mode 100644
index 0000000..2af92ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-3_b.H
@@ -0,0 +1,24 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header -fdump-lang-module-vops" }
+// { dg-module-cmi {} }
+
+import "macro-3_a.H";
+
+// Not the controlling macro, because of above tokens
+#ifndef MACRO_3b_H
+#define MACRO_3b_H
+
+#define bob 1
+#undef foo
+#undef bar
+#define bar 3
+
+#endif
+
+// { dg-final { scan-lang-dump {Read new macro #define foo at} module } }
+// { dg-final { scan-lang-dump {Read new macro #define bar at} module } }
+// { dg-final { scan-lang-dump-not {Read [^ ]* macro #define bob at} module } }
+
+// { dg-final { scan-lang-dump {Writing macro #define bob at} module } }
+// { dg-final { scan-lang-dump {Writing macro #undef & #define bar at} module } }
+// { dg-final { scan-lang-dump {Writing macro #undef foo at} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-3_c.C b/gcc/testsuite/g++.dg/modules/macro-3_c.C
new file mode 100644
index 0000000..f079580
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-3_c.C
@@ -0,0 +1,24 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-vops" }
+
+import "macro-3_b.H";
+import "macro-3_a.H";
+
+int main ()
+{
+#ifdef foo
+ return 1;
+#endif
+ if (bar != 3)
+ return 2;
+#define foo 2
+ if (foo != 2)
+ return 3;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read new macro #define foo at} module } }
+// { dg-final { scan-lang-dump {Read new macro #define bar at} module } }
+
+// { dg-final { scan-lang-dump {Read add macro #undef foo} module } }
+// { dg-final { scan-lang-dump {Read new macro #define bob} module } }
+// { dg-final { scan-lang-dump {Read add macro #undef & #define bar} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_a.H b/gcc/testsuite/g++.dg/modules/macro-4_a.H
new file mode 100644
index 0000000..c04854e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_a.H
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodule-header -Winvalid-imported-macros" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_4_a
+#define MACRO_4_a
+
+#define ONE 1
+#define TWO 2
+#define THREE 3
+#define FOUR 4
+#define FIVE 5
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_b.H b/gcc/testsuite/g++.dg/modules/macro-4_b.H
new file mode 100644
index 0000000..0403938
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_b.H
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodule-header -Winvalid-imported-macros" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_4_b
+#define MACRO_4_b
+
+#define ONE 1
+#define TWO 2a
+#undef THREE // no effect
+#define THREE 3b
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_c.H b/gcc/testsuite/g++.dg/modules/macro-4_c.H
new file mode 100644
index 0000000..ec2bed9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_c.H
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodule-header -Winvalid-imported-macros" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_4_c
+#define MACRO_4_c
+
+#undef FIVE // no effect
+import "macro-4_a.H";
+int a;
+#undef THREE
+#undef FOUR
+#define FOUR 4c
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_d.C b/gcc/testsuite/g++.dg/modules/macro-4_d.C
new file mode 100644
index 0000000..bff9494
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_d.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import "macro-4_b.H";
+import "macro-4_a.H";
+
+// { dg-regexp {[^\n]*macro-4_d.C: warning: inconsistent imported macro definition 'TWO' \[-Winvalid-imported-macros\]\nIn module [^\n]*macro-4_b.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_b.H:[0-9]*: note: .#define TWO 2a.\nIn module [^\n]*macro-4_a.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_a.H:[0-9]*: note: .#define TWO 2.\n} }
+
+// { dg-regexp {[^\n]*macro-4_d.C: warning: inconsistent imported macro definition 'THREE' \[-Winvalid-imported-macros\]\nIn module [^\n]*macro-4_b.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_b.H:[0-9]*: note: .#define THREE 3b.\nIn module [^\n]*macro-4_a.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_a.H:[0-9]*: note: .#define THREE 3.\n} }
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_e.C b/gcc/testsuite/g++.dg/modules/macro-4_e.C
new file mode 100644
index 0000000..38fa6c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_e.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import "macro-4_b.H";
+import "macro-4_a.H";
+import "macro-4_c.H";
+
+int stop;
+
+#ifndef FIVE
+#error bah!
+#endif
+
+// { dg-regexp {[^\n]*macro-4_e.C: warning: inconsistent imported macro definition 'TWO' \[-Winvalid-imported-macros\]\nIn module [^\n]*macro-4_b.H, imported at [^\n]*macro-4_e.C:[0-9]*:\n[^\n]*macro-4_b.H:[0-9]*: note: .#define TWO 2a.\nIn module [^\n]*macro-4_a.H, imported at [^\n]*macro-4_e.C:[0-9]*:\n[^\n]*macro-4_a.H:[0-9]*: note: .#define TWO 2.\n} }
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_f.C b/gcc/testsuite/g++.dg/modules/macro-4_f.C
new file mode 100644
index 0000000..1279de2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_f.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+export import "macro-4_b.H";
diff --git a/gcc/testsuite/g++.dg/modules/macro-4_g.C b/gcc/testsuite/g++.dg/modules/macro-4_g.C
new file mode 100644
index 0000000..f3ff0e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-4_g.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import bob;
+import "macro-4_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/macro-5_a.H b/gcc/testsuite/g++.dg/modules/macro-5_a.H
new file mode 100644
index 0000000..d0913d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-5_a.H
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodule-header -Dfoo=bar -Dbaz=1 -fdump-lang-module-vops" }
+// command line macros are not exported
+// { dg-module-cmi {} }
+
+// { dg-final { scan-lang-dump-not {Writing macro #define [_a-zA-Z0-9]* at [0-9]*} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-5_b.H b/gcc/testsuite/g++.dg/modules/macro-5_b.H
new file mode 100644
index 0000000..656d511
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-5_b.H
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodule-header -Dfoo=bar -Dbaz=2 -fdump-lang-module-vops" }
+// { dg-module-cmi {} }
+
+#undef baz // not exported
+#define baz 3 // exported
+
+
+// { dg-final { scan-lang-dump {Writing macro #define baz at [0-9]*} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-5_c.C b/gcc/testsuite/g++.dg/modules/macro-5_c.C
new file mode 100644
index 0000000..17f6fe2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-5_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import "macro-5_a.H";
+import "macro-5_b.H";
+
+#if baz != 3
+#error
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-6_a.H b/gcc/testsuite/g++.dg/modules/macro-6_a.H
new file mode 100644
index 0000000..4947e2e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-6_a.H
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_6_H
+#define MACRO_6_H
+#define foo bar baz
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/macro-6_b.C b/gcc/testsuite/g++.dg/modules/macro-6_b.C
new file mode 100644
index 0000000..cbc3b2a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-6_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module macro;
+// { dg-module-cmi {macro} }
+import "macro-6_a.H";
+
+#ifndef foo
+#error bad
+#endif
+
+// { dg-final { scan-lang-dump {Reading macro table [^\n]*macro-6_a.H} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-6_c.C b/gcc/testsuite/g++.dg/modules/macro-6_c.C
new file mode 100644
index 0000000..a9a6f4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-6_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// Macro tables are only loaded when transitively reachable from top
+// level
+
+import macro;
+
+#ifdef foo
+#error bad
+#endif
+
+// { dg-final { scan-lang-dump-not {>Reading macro table "macro-6_a.H"} module } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-7_a.C b/gcc/testsuite/g++.dg/modules/macro-7_a.C
new file mode 100644
index 0000000..f336f00
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-7_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+#define MACRO(X) X
+
+export template<int I> int Factory ()
+{
+ // this macro expansion location ends up in the instantiation
+ // emitted by an importer
+ return MACRO(I);
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/macro-7_b.C b/gcc/testsuite/g++.dg/modules/macro-7_b.C
new file mode 100644
index 0000000..025f5eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-7_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+export inline int One ()
+{
+ return Factory<1> ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/macro-7_c.C b/gcc/testsuite/g++.dg/modules/macro-7_c.C
new file mode 100644
index 0000000..902f1a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-7_c.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+import bar;
+
+int main ()
+{
+ return !(One () == 1);
+}
diff --git a/gcc/testsuite/g++.dg/modules/map-1.map b/gcc/testsuite/g++.dg/modules/map-1.map
new file mode 100644
index 0000000..58963bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/map-1.map
@@ -0,0 +1,2 @@
+$root .
+frob map-1_a.nms
diff --git a/gcc/testsuite/g++.dg/modules/map-1_a.C b/gcc/testsuite/g++.dg/modules/map-1_a.C
new file mode 100644
index 0000000..f714672
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/map-1_a.C
@@ -0,0 +1,13 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/map-1.map" }
+
+// Ick! no cross-host testing for you!
+// { dg-additional-files map-1.map }
+
+export module frob;
+// { dg-module-cmi "=map-1_a.nms" }
+
+export int frob (int i)
+{
+ return -i;
+}
diff --git a/gcc/testsuite/g++.dg/modules/map-1_b.C b/gcc/testsuite/g++.dg/modules/map-1_b.C
new file mode 100644
index 0000000..0e306d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/map-1_b.C
@@ -0,0 +1,13 @@
+// Ick!
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/map-1_b.map?MAP" }
+// { dg-additional-files map-1.map }
+
+import frob;
+
+int main ()
+{
+ if (frob (-2) != 2)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/map-1_b.map b/gcc/testsuite/g++.dg/modules/map-1_b.map
new file mode 100644
index 0000000..f125dc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/map-1_b.map
@@ -0,0 +1,3 @@
+MAP $root .
+MAP frob map-1_a.nms
+I can't see you
diff --git a/gcc/testsuite/g++.dg/modules/map-2.C b/gcc/testsuite/g++.dg/modules/map-2.C
new file mode 100644
index 0000000..dceb183
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/map-2.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/map-2.map" }
+
+
+// Ick! no cross-host testing for you!
+// { dg-additional-files map-2.map }
+
+export module foo;
+// { dg-error "Interface: no such module" "" { target *-*-* } .-1 }
+// { dg-error "failed reading mapper" "" { target *-*-* } 0 }
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/map-2.map b/gcc/testsuite/g++.dg/modules/map-2.map
new file mode 100644
index 0000000..43aecde
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/map-2.map
@@ -0,0 +1 @@
+$bad .
diff --git a/gcc/testsuite/g++.dg/modules/member-def-1_a.C b/gcc/testsuite/g++.dg/modules/member-def-1_a.C
new file mode 100644
index 0000000..f7a508c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+struct frob
+{
+ struct inner;
+};
diff --git a/gcc/testsuite/g++.dg/modules/member-def-1_b.C b/gcc/testsuite/g++.dg/modules/member-def-1_b.C
new file mode 100644
index 0000000..fbe1ac4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-1_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module foo:part2;
+// { dg-module-cmi {foo:part2} }
+
+import :part1;
+
+struct frob::inner
+{
+ int i;
+};
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1::inner'\n \[1\]=decl declaration '::frob@foo:part1:1::inner::inner'\n} module } }
+// { dg-final { scan-lang-dump {Member '::frob@foo:part1:1::inner' entity:0 keyed to foo:part1\[0\] '::frob@foo:part1:1'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/member-def-1_c.C b/gcc/testsuite/g++.dg/modules/member-def-1_c.C
new file mode 100644
index 0000000..c7c3f6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-1_c.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :part2;
+export import :part1;
+
+export auto foo ()
+{
+ return frob::inner ();
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending members keyed to foo:part1\[0\] '::frob@foo:part1:1'} module } }
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1'\n \[1\]=decl definition '::frob@foo:part1:1::inner@foo:part1:1'\n \[2\]=decl declaration '::frob@foo:part1:1::inner@foo:part1:1::__dt '\n( \[.\]=decl declaration '::frob@foo:part1:1::inner@foo:part1:1::__ct '\n)* \[6\]=decl declaration '::frob@foo:part1:1::inner@foo:part1:1::inner@foo:part2:2'\n \[7\]=decl declaration '::frob@foo:part1:1::frob@foo:part1:1'\n \[8\]=decl declaration '::frob@foo:part1:1::__as_base @foo:part1:1'\n \[9\]=binding '::frob'\n} module } }
+// { dg-final { scan-lang-dump {Pendings 0} module } }
diff --git a/gcc/testsuite/g++.dg/modules/member-def-1_d.C b/gcc/testsuite/g++.dg/modules/member-def-1_d.C
new file mode 100644
index 0000000..5609d47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-1_d.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module foo;
+
+void f ()
+{
+ frob::inner x;
+ x.i = 17;
+}
+
+// { dg-final { scan-lang-dump {Loaded 1 clusters} module } }
diff --git a/gcc/testsuite/g++.dg/modules/member-def-2_a.C b/gcc/testsuite/g++.dg/modules/member-def-2_a.C
new file mode 100644
index 0000000..b4904da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-2_a.C
@@ -0,0 +1,10 @@
+// { dg-module-do link }
+// { dg-additional-options -fmodules-ts }
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+
+export struct frob
+{
+ void member ();
+};
diff --git a/gcc/testsuite/g++.dg/modules/member-def-2_b.C b/gcc/testsuite/g++.dg/modules/member-def-2_b.C
new file mode 100644
index 0000000..dedcbe7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-2_b.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module foo:part2;
+// { dg-module-cmi {foo:part2} }
+
+import :part1;
+
+inline void frob::member ()
+{
+}
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1::member'\n} module } }
+// { dg-final { scan-lang-dump {Pendings 1} module } }
+// { dg-final { scan-lang-dump {Bindings 0} module } }
+
+// { dg-final { scan-assembler-not {_ZN4frob6memberEv:} } }
diff --git a/gcc/testsuite/g++.dg/modules/member-def-2_c.C b/gcc/testsuite/g++.dg/modules/member-def-2_c.C
new file mode 100644
index 0000000..f0a193f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-2_c.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :part2;
+export import :part1;
+
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1'\n \[1\]=decl declaration '::frob@foo:part1:1::frob@foo:part1:1'\n \[2\]=decl definition '::frob@foo:part1:1::member@foo:part1:1'\n \[3\]=decl declaration '::frob@foo:part1:1::__as_base @foo:part1:1'\n \[4\]=binding '::frob'\n} module } }
+// { dg-final { scan-lang-dump {Bindings 1} module } }
+// { dg-final { scan-lang-dump {Pendings 0} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key .matched. function_decl:'::frob@foo:part1:1::member'} module } }
+
+// { dg-final { scan-assembler-not {_ZN4frob6memberEv:} } }
diff --git a/gcc/testsuite/g++.dg/modules/member-def-2_d.C b/gcc/testsuite/g++.dg/modules/member-def-2_d.C
new file mode 100644
index 0000000..c2b9c3e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/member-def-2_d.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import foo;
+
+int main ()
+{
+ frob x;
+ x.member ();
+}
+
+// { dg-final { scan-lang-dump {Reading function definition '::frob@foo:1::member@foo:1'} module } }
+
+// { dg-final { scan-assembler {_ZN4frob6memberEv:} } }
diff --git a/gcc/testsuite/g++.dg/modules/memref-1_a.C b/gcc/testsuite/g++.dg/modules/memref-1_a.C
new file mode 100644
index 0000000..e780999
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/memref-1_a.C
@@ -0,0 +1,24 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export class Bit
+{
+private:
+ unsigned _M_msb:1;
+};
+
+Bit Make () noexcept;
+
+export class Container
+{
+public:
+ void Frob ()
+ {
+ _M_rep = Make ();
+ }
+
+private:
+ Bit _M_rep;
+};
diff --git a/gcc/testsuite/g++.dg/modules/memref-1_b.C b/gcc/testsuite/g++.dg/modules/memref-1_b.C
new file mode 100644
index 0000000..82c52fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/memref-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import Foo;
+
+void X ()
+{
+ Container c;
+ c.Frob ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/merge-10.h b/gcc/testsuite/g++.dg/modules/merge-10.h
new file mode 100644
index 0000000..9df9d2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-10.h
@@ -0,0 +1,8 @@
+
+struct timex
+{
+ unsigned modes;
+ int :32;
+ int :32;
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/merge-10_a.H b/gcc/testsuite/g++.dg/modules/merge-10_a.H
new file mode 100644
index 0000000..dc4be18
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-10_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-10.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-10_b.C b/gcc/testsuite/g++.dg/modules/merge-10_b.C
new file mode 100644
index 0000000..9df07ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-10_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-10.h"
+import "merge-10_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-11.h b/gcc/testsuite/g++.dg/modules/merge-11.h
new file mode 100644
index 0000000..87342e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-11.h
@@ -0,0 +1,15 @@
+
+
+
+template<typename _From, bool>
+struct __is_nt_convertible_helper;
+
+template<typename _From>
+class __is_nt_convertible_helper<_From, false>
+{
+ template<typename> static int __test (int);
+ template<typename> static void __test(...);
+
+public:
+ using type = decltype(__test<_From>(0));
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-11_a.H b/gcc/testsuite/g++.dg/modules/merge-11_a.H
new file mode 100644
index 0000000..6de063d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-11_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-11.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-11_b.C b/gcc/testsuite/g++.dg/modules/merge-11_b.C
new file mode 100644
index 0000000..2c30e34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-11_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-11.h"
+import "merge-11_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-12.h b/gcc/testsuite/g++.dg/modules/merge-12.h
new file mode 100644
index 0000000..96b2ba3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-12.h
@@ -0,0 +1,23 @@
+
+template<typename _Functor, typename _ArgTypes>
+struct invoke_result;
+
+template<typename _Fn, typename _ArgTypes>
+struct is_invocable;
+
+template<typename _Fn, typename... _Args>
+concept invocable = is_invocable<_Fn, _Args...>::value;
+
+template<typename _Fn, typename _Is>
+requires invocable<_Fn, _Is>
+ using indirect_result_t = typename invoke_result<_Fn, _Is>::type;
+
+template<typename _Tp>
+struct remove_cv;
+
+template<typename _Iter, typename _Proj>
+struct projected
+{
+ using value_type = remove_cv<indirect_result_t<_Proj&, _Iter>>;
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/merge-12_a.H b/gcc/testsuite/g++.dg/modules/merge-12_a.H
new file mode 100644
index 0000000..4ee061f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-12_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "merge-12.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-12_b.C b/gcc/testsuite/g++.dg/modules/merge-12_b.C
new file mode 100644
index 0000000..4bafbdd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-12_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fconcepts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-12.h"
+import "merge-12_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-13.h b/gcc/testsuite/g++.dg/modules/merge-13.h
new file mode 100644
index 0000000..ad282a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-13.h
@@ -0,0 +1,10 @@
+template<typename T> class Base;
+
+template<typename U> class Derived : Base<U>
+{
+ using Base_ = Base<U>;
+ using typename Base_::base_member;
+
+public:
+ base_member Func ();
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-13_a.H b/gcc/testsuite/g++.dg/modules/merge-13_a.H
new file mode 100644
index 0000000..ecf0c31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-13_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "merge-13.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-13_b.C b/gcc/testsuite/g++.dg/modules/merge-13_b.C
new file mode 100644
index 0000000..b62101f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-13_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fconcepts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-13.h"
+import "merge-13_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-14.h b/gcc/testsuite/g++.dg/modules/merge-14.h
new file mode 100644
index 0000000..0b867b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-14.h
@@ -0,0 +1,7 @@
+template<typename T>
+struct TPL
+{
+ T val = 0;
+};
+
+inline TPL<int> x;
diff --git a/gcc/testsuite/g++.dg/modules/merge-14_a.H b/gcc/testsuite/g++.dg/modules/merge-14_a.H
new file mode 100644
index 0000000..c197ec8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-14_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-14.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-14_b.C b/gcc/testsuite/g++.dg/modules/merge-14_b.C
new file mode 100644
index 0000000..4d92b08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-14_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-14.h"
+import "merge-14_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-15.h b/gcc/testsuite/g++.dg/modules/merge-15.h
new file mode 100644
index 0000000..ccf3b84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-15.h
@@ -0,0 +1,5 @@
+struct optional
+{
+ int &get () &;
+ int &&get () &&;
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-15_a.H b/gcc/testsuite/g++.dg/modules/merge-15_a.H
new file mode 100644
index 0000000..afef95d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-15_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-15.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-15_b.C b/gcc/testsuite/g++.dg/modules/merge-15_b.C
new file mode 100644
index 0000000..07378d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-15_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-15.h"
+import "merge-15_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-1_a.C b/gcc/testsuite/g++.dg/modules/merge-1_a.C
new file mode 100644
index 0000000..966fd4bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-1_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+};
+
+typedef integral_constant<bool, true> true_type;
+
+void __throw_with_nested_impl (true_type);
diff --git a/gcc/testsuite/g++.dg/modules/merge-1_b.C b/gcc/testsuite/g++.dg/modules/merge-1_b.C
new file mode 100644
index 0000000..c7f533f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void frob ()
+{
+ __throw_with_nested_impl (integral_constant<bool, true> ());
+}
diff --git a/gcc/testsuite/g++.dg/modules/merge-2_a.H b/gcc/testsuite/g++.dg/modules/merge-2_a.H
new file mode 100644
index 0000000..ac6d06a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-2_a.H
@@ -0,0 +1,29 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _CharT> class istreambuf_iterator;
+
+void move(char __t);
+void move(istreambuf_iterator<char> &__u);
+
+template<typename _Tp> struct allocator {};
+
+template<typename _Alloc> struct __alloc_traits
+{
+ static void _S_on_swap(_Alloc& __b)
+ {
+ move (__b);
+ }
+
+ typedef allocator<char> other;
+};
+
+template<typename _CharT> class basic_string
+{
+ typedef __alloc_traits<char>::other _Char_alloc_type;
+};
+
+template<typename _CharT> class istreambuf_iterator
+{
+ void frob (const basic_string<char>& __s);
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-2_b.C b/gcc/testsuite/g++.dg/modules/merge-2_b.C
new file mode 100644
index 0000000..21bbd04
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-2_b.C
@@ -0,0 +1,2 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
+import "merge-2_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/merge-3_a.H b/gcc/testsuite/g++.dg/modules/merge-3_a.H
new file mode 100644
index 0000000..80dfd9c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-3_a.H
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module_cmi {} }
+
+struct bob
+{
+ int i;
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-3_b.C b/gcc/testsuite/g++.dg/modules/merge-3_b.C
new file mode 100644
index 0000000..1e863f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-3_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+struct bob;
+import "merge-3_a.H";
+
+bob b = {1};
+
+void frob ()
+{
+ b.i = 7;
+}
diff --git a/gcc/testsuite/g++.dg/modules/merge-4.h b/gcc/testsuite/g++.dg/modules/merge-4.h
new file mode 100644
index 0000000..842fedc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-4.h
@@ -0,0 +1,7 @@
+template<typename T> struct Bob
+{
+ struct M
+ {
+ int m;
+ };
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-4_a.H b/gcc/testsuite/g++.dg/modules/merge-4_a.H
new file mode 100644
index 0000000..78b0ec7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-4_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-4.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-4_b.C b/gcc/testsuite/g++.dg/modules/merge-4_b.C
new file mode 100644
index 0000000..89b6961
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-4_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-4.h"
+import "merge-4_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template Bob'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template Bob<T>::template M'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-5.h b/gcc/testsuite/g++.dg/modules/merge-5.h
new file mode 100644
index 0000000..5db1b0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-5.h
@@ -0,0 +1,8 @@
+
+template<bool> struct __truth_type;
+
+template<typename T> struct __traitor
+{
+ enum X { __value = true };
+ typedef typename __truth_type<__value>::__type __type;
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-5_a.H b/gcc/testsuite/g++.dg/modules/merge-5_a.H
new file mode 100644
index 0000000..e3d8c69
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-5_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-5.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-5_b.C b/gcc/testsuite/g++.dg/modules/merge-5_b.C
new file mode 100644
index 0000000..58c2a34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-5_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-5.h"
+import "merge-5_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) const_decl:'::template __traitor<T>::template X<T>::__value'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-6.h b/gcc/testsuite/g++.dg/modules/merge-6.h
new file mode 100644
index 0000000..6a1d654
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-6.h
@@ -0,0 +1,10 @@
+
+template<bool>
+struct __truth_type;
+
+template<typename T>
+struct __traitor
+{
+ enum { __value = true }; // Oh, an anonymous templatey thing!
+ typedef typename __truth_type<__value>::__type __type;
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-6_a.H b/gcc/testsuite/g++.dg/modules/merge-6_a.H
new file mode 100644
index 0000000..4e0b81c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-6_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-6.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-6_b.C b/gcc/testsuite/g++.dg/modules/merge-6_b.C
new file mode 100644
index 0000000..11fe631
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-6_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-6.h"
+import "merge-6_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s field merge key \(matched\) template_decl:'::template __traitor<T>::template #null#'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-7.h b/gcc/testsuite/g++.dg/modules/merge-7.h
new file mode 100644
index 0000000..6350e74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-7.h
@@ -0,0 +1,5 @@
+template<typename _Tp2, typename _Up2>
+struct __promote_2
+{
+ typedef __typeof__(_Tp2() + _Up2()) __type;
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-7_a.H b/gcc/testsuite/g++.dg/modules/merge-7_a.H
new file mode 100644
index 0000000..3c32b33
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-7_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-7.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-7_b.C b/gcc/testsuite/g++.dg/modules/merge-7_b.C
new file mode 100644
index 0000000..da9632d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-7_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-7.h"
+import "merge-7_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template __promote_2<_Tp2,_Up2>::template __type'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-8.h b/gcc/testsuite/g++.dg/modules/merge-8.h
new file mode 100644
index 0000000..d253902
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-8.h
@@ -0,0 +1,17 @@
+
+struct __do_is_destructible_impl
+{
+ template<typename _Tp, typename = decltype(_Tp().~_Tp())>
+ static bool __test(int);
+
+ template<typename>
+ static float __test(...);
+};
+
+template<typename _Tp>
+struct __is_destructible_impl
+ : public __do_is_destructible_impl
+{
+ // Requires BINFO merging
+ typedef decltype(__test<_Tp>(0)) type;
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-8_a.H b/gcc/testsuite/g++.dg/modules/merge-8_a.H
new file mode 100644
index 0000000..d2add6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-8_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-8.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-8_b.C b/gcc/testsuite/g++.dg/modules/merge-8_b.C
new file mode 100644
index 0000000..c489e30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-8_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-8.h"
+import "merge-8_a.H";
+
+// { dg-final { scan-lang-dump {Deduping binfo '::__do_is_destructible_impl'\[0\]} module } }
+// { dg-final { scan-lang-dump {Deduping binfo '::template __is_destructible_impl<_Tp>'\[0\]} module } }
+// { dg-final { scan-lang-dump {Deduping binfo '::template __is_destructible_impl<_Tp>'\[1\]} module } }
diff --git a/gcc/testsuite/g++.dg/modules/merge-9.h b/gcc/testsuite/g++.dg/modules/merge-9.h
new file mode 100644
index 0000000..1944779
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-9.h
@@ -0,0 +1,9 @@
+using size_t = __SIZE_TYPE__;
+
+namespace std
+{
+// This is a builtin, but should not be a global tree
+ enum class align_val_t: size_t {};
+ // as is this
+ class type_info;
+}
diff --git a/gcc/testsuite/g++.dg/modules/merge-9_a.H b/gcc/testsuite/g++.dg/modules/merge-9_a.H
new file mode 100644
index 0000000..69f32cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-9_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-9.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-9_b.C b/gcc/testsuite/g++.dg/modules/merge-9_b.C
new file mode 100644
index 0000000..0a92cf3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-9_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-9.h"
+import "merge-9_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[10-9]*'s named merge key \(matched\) type_decl:'::std::align_val_t'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-0-2a.C b/gcc/testsuite/g++.dg/modules/mod-decl-0-2a.C
new file mode 100644
index 0000000..75406f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-0-2a.C
@@ -0,0 +1,6 @@
+// { dg-options "-fno-modules -std=c++2a" }
+
+export // { dg-message "enabled with" }
+module nope; // { dg-error "not name a type" }
+// { dg-message "only available with .-fmodules." "" { target *-*-* } .-1 }
+// { dg-module-cmi "!nope" }
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-0.C b/gcc/testsuite/g++.dg/modules/mod-decl-0.C
new file mode 100644
index 0000000..fcafc0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-0.C
@@ -0,0 +1,6 @@
+// { dg-options "-fno-modules -std=c++17" }
+
+export // { dg-message "ignored" }
+module nope; // { dg-error "not name a type" }
+// { dg-message "only available with .-fmodules." "" { target *-*-* } .-1 }
+// { dg-module-cmi "!nope" }
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-1.C b/gcc/testsuite/g++.dg/modules/mod-decl-1.C
new file mode 100644
index 0000000..b2665be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-1.C
@@ -0,0 +1,29 @@
+// { dg-additional-options "-fmodules-ts" }
+module;
+
+export module frist;
+// { dg-module-cmi "!frist" }
+
+import frist; // { dg-error {cannot import module.* in its own purview} }
+
+module foo.second; // { dg-error "not permitted here" }
+
+namespace Foo
+{
+module third; // { dg-error "not permitted here" }
+}
+
+struct Baz
+{
+ module forth; // { dg-error "expected" }
+};
+
+void Bink ()
+{
+ module fifth; // { dg-error "expected" }
+}
+
+module a.; // { dg-error "not permitted" }
+
+// { dg-prune-output "not writing module" }
+
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-2_a.C b/gcc/testsuite/g++.dg/modules/mod-decl-2_a.C
new file mode 100644
index 0000000..9b4a920
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-2_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+export void Foo ();
+export
+{
+ void Bar ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-2_b.C b/gcc/testsuite/g++.dg/modules/mod-decl-2_b.C
new file mode 100644
index 0000000..a3ea9b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-2_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts" }
+module bob;
+
+import bob; // { dg-error "cannot import module.* in its own purview" }
+
+// module linkage
+void Baz ()
+{
+ Foo ();
+ Bar ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-2_c.C b/gcc/testsuite/g++.dg/modules/mod-decl-2_c.C
new file mode 100644
index 0000000..4808ad2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-2_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+import bob;
+
+void Baz ()
+{
+ Foo ();
+ Bar ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-3.C b/gcc/testsuite/g++.dg/modules/mod-decl-3.C
new file mode 100644
index 0000000..16fa5a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-3.C
@@ -0,0 +1,26 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "mod-decl-3.C" 1
+export void Foo (); // { dg-error "after a module interface" }
+
+# 7 "" 2
+export module bob;
+// { dg-module-cmi "!bob" }
+
+export
+export // { dg-error "occur once" }
+void Baz ();
+
+export
+{
+ export // { dg-error "occur once" }
+ void Bar ();
+}
+
+namespace Bink
+{
+ import // { dg-error "does not name" }
+ ben;
+}
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-5_a.C b/gcc/testsuite/g++.dg/modules/mod-decl-5_a.C
new file mode 100644
index 0000000..c39807d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-5_a.C
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodules-ts" }
+export module thing.baz;
+// { dg-module-cmi "thing.baz" }
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-5_b.C b/gcc/testsuite/g++.dg/modules/mod-decl-5_b.C
new file mode 100644
index 0000000..b3eea76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-5_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "gmf" 1
+import thing.baz;
+
+export int foo (); // { dg-error "after a module interface" }
+# 8 "" 2
+export module thing.baz; // { dg-error "module already imported" }
+
+import thing.baz;
+
diff --git a/gcc/testsuite/g++.dg/modules/mod-exp-1_a.C b/gcc/testsuite/g++.dg/modules/mod-exp-1_a.C
new file mode 100644
index 0000000..800752d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-exp-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Baz;
+// { dg-module-cmi "Baz" }
+
+void Quux (void);
+
+export void Bar (void);
+
+void Foo (void);
diff --git a/gcc/testsuite/g++.dg/modules/mod-exp-1_b.C b/gcc/testsuite/g++.dg/modules/mod-exp-1_b.C
new file mode 100644
index 0000000..efea205
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-exp-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "gmf" 1
+void Frob (void);
+# 6 "" 2
+
+module Baz;
diff --git a/gcc/testsuite/g++.dg/modules/mod-imp-1_a.C b/gcc/testsuite/g++.dg/modules/mod-imp-1_a.C
new file mode 100644
index 0000000..cf9e1d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-imp-1_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-imp-1_b.C b/gcc/testsuite/g++.dg/modules/mod-imp-1_b.C
new file mode 100644
index 0000000..0dc4bdb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-imp-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module Foo;
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-imp-1_c.C b/gcc/testsuite/g++.dg/modules/mod-imp-1_c.C
new file mode 100644
index 0000000..e32aaaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-imp-1_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module Baz;
+// { dg-module-cmi "Baz" }
+
+import Foo;
+
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
+// { dg-final { scan-lang-dump "Starting module Baz" "module" } }
+// { dg-final { scan-lang-dump "Writing import:1->1 Foo" "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-imp-1_d.C b/gcc/testsuite/g++.dg/modules/mod-imp-1_d.C
new file mode 100644
index 0000000..ca6f649
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-imp-1_d.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module Baz;
+
+// { dg-final { scan-lang-dump "Starting module Baz" "module" } }
+// { dg-final { scan-lang-dump "Found import:1 Foo->1" "module" } }
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-impl-1_a.C b/gcc/testsuite/g++.dg/modules/mod-impl-1_a.C
new file mode 100644
index 0000000..9f9dfd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-impl-1_a.C
@@ -0,0 +1,12 @@
+// { dg-module-do "run" }
+// { dg-additional-options "-fmodules-ts" }
+
+export module baz;
+// { dg-module-cmi "baz" }
+
+export int Square (int);
+
+float Square (int, int);
+export int Square (int, int, int);
+
+int Prod (int, int);
diff --git a/gcc/testsuite/g++.dg/modules/mod-impl-1_b.C b/gcc/testsuite/g++.dg/modules/mod-impl-1_b.C
new file mode 100644
index 0000000..c1f9a5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-impl-1_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+module baz;
+
+int Square (int a)
+{
+ return Prod (a, a);
+}
+
+float Square (int a, int b)
+{
+ return a * b * 1.5f;
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-impl-1_c.C b/gcc/testsuite/g++.dg/modules/mod-impl-1_c.C
new file mode 100644
index 0000000..c50aade
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-impl-1_c.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+module baz;
+
+int Prod (int a, int b)
+{
+ return a * b;
+}
+
+int Square (int a, int b, int c)
+{
+ return Prod (Square (a, b), c);
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-impl-1_d.C b/gcc/testsuite/g++.dg/modules/mod-impl-1_d.C
new file mode 100644
index 0000000..4f05a76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-impl-1_d.C
@@ -0,0 +1,27 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import baz;
+
+int Prod (int a, int b)
+{
+ return -a * b; // What kind of crazy math is this?
+}
+
+int Square (float a)
+{
+ return Prod (int (a), int (a));
+}
+
+int main ()
+{
+ if (Square (2) != 4)
+ return 1;
+
+ if (Square (2.0f) != -4)
+ return 1;
+
+ if (Square (2, 3, 4) != 9 * 4)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-indirect-1_a.C b/gcc/testsuite/g++.dg/modules/mod-indirect-1_a.C
new file mode 100644
index 0000000..a27153c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-indirect-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-do run }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export int bob (int);
+export float bob (float);
diff --git a/gcc/testsuite/g++.dg/modules/mod-indirect-1_b.C b/gcc/testsuite/g++.dg/modules/mod-indirect-1_b.C
new file mode 100644
index 0000000..7e466f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-indirect-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+import Foo;
+
+export int frob (int, float);
diff --git a/gcc/testsuite/g++.dg/modules/mod-indirect-1_c.C b/gcc/testsuite/g++.dg/modules/mod-indirect-1_c.C
new file mode 100644
index 0000000..e19f41d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-indirect-1_c.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+module Foo;
+
+int bob (int a)
+{
+ return a * 2;
+}
+
+float bob (float b)
+{
+ return b * 1.5f;
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-indirect-1_d.C b/gcc/testsuite/g++.dg/modules/mod-indirect-1_d.C
new file mode 100644
index 0000000..304be95
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-indirect-1_d.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+module Bar;
+
+int frob (int a, float b)
+{
+ return bob (a) * bob (b);
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-indirect-1_e.C b/gcc/testsuite/g++.dg/modules/mod-indirect-1_e.C
new file mode 100644
index 0000000..23241b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-indirect-1_e.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+import Bar;
+
+int main ()
+{
+ return frob (2, 4) != 4 * 6;
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-stamp-1_a.C b/gcc/testsuite/g++.dg/modules/mod-stamp-1_a.C
new file mode 100644
index 0000000..cf8e73f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-stamp-1_a.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export int bob ();
+
diff --git a/gcc/testsuite/g++.dg/modules/mod-stamp-1_b.C b/gcc/testsuite/g++.dg/modules/mod-stamp-1_b.C
new file mode 100644
index 0000000..3a5e8e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-stamp-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+import Foo;
+
+export int bill ();
diff --git a/gcc/testsuite/g++.dg/modules/mod-stamp-1_c.C b/gcc/testsuite/g++.dg/modules/mod-stamp-1_c.C
new file mode 100644
index 0000000..554ba3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-stamp-1_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module Foo;
+
+export int bob (int);
diff --git a/gcc/testsuite/g++.dg/modules/mod-stamp-1_d.C b/gcc/testsuite/g++.dg/modules/mod-stamp-1_d.C
new file mode 100644
index 0000000..f16833e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-stamp-1_d.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import Bar;
+// { dg-error "CRC mismatch" "" { target *-*-* } 0 }
+// { dg-regexp "Foo: error: failed to read compiled module: Bad file data\n" }
+// { dg-regexp "Bar: error: failed to read compiled module: Bad import dependency\n" }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
+
+int bill ();
diff --git a/gcc/testsuite/g++.dg/modules/mod-sym-1.C b/gcc/testsuite/g++.dg/modules/mod-sym-1.C
new file mode 100644
index 0000000..b207101
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-sym-1.C
@@ -0,0 +1,34 @@
+// { dg-additional-options "-fmodules-ts" }
+export module linkage;
+// { dg-module-cmi "linkage" }
+
+inline void Foo () {}
+
+export inline void Baz () __attribute__((used));
+
+inline void Bink () {}
+
+export inline void Baz () { Foo (); Bink (); }
+
+extern "C" inline void cfunc (void) __attribute__((used));
+extern "C" inline void cfunc (void) {}
+
+namespace Inner
+{
+ inline void Foo2 () {}
+
+ export inline void Baz2 () __attribute__((used));
+
+ inline void Bink2 () {}
+
+ export inline void Baz2 () { Foo2 (); Bink2 (); }
+}
+
+// These fail until namespace hack is removed
+// { dg-final { scan-assembler "_ZW7linkageE3Foov:" } }
+// { dg-final { scan-assembler "_ZW7linkageE4Binkv:" } }
+// { dg-final { scan-assembler "_ZW7linkageEN5Inner4Foo2Ev:" } }
+// { dg-final { scan-assembler "_ZW7linkageEN5Inner5Bink2Ev:" } }
+// { dg-final { scan-assembler "_Z3Bazv:" } }
+// { dg-final { scan-assembler "_ZN5Inner4Baz2Ev:" } }
+// { dg-final { scan-assembler "cfunc:" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-sym-2.C b/gcc/testsuite/g++.dg/modules/mod-sym-2.C
new file mode 100644
index 0000000..ef0c3f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-sym-2.C
@@ -0,0 +1,23 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "header" 1
+inline void Foo () {}
+# 6 "" 2
+export module okely.dokely;
+// { dg-module-cmi "okely.dokely" }
+
+namespace One {
+ namespace Two {
+ inline namespace Three
+ {
+ inline void Foo2 () {}
+
+ export inline void Baz2 () __attribute__((used));
+ export inline void Baz2 () { Foo (); Foo2 (); }
+ }
+ }
+}
+
+// { dg-final { scan-assembler "_Z3Foov:" } }
+// { dg-final { scan-assembler "_ZW5okely6dokelyEN3One3Two5Three4Foo2Ev:" } }
+// { dg-final { scan-assembler "_ZN3One3Two5Three4Baz2Ev:" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-sym-3.C b/gcc/testsuite/g++.dg/modules/mod-sym-3.C
new file mode 100644
index 0000000..9481ad1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-sym-3.C
@@ -0,0 +1,26 @@
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+
+namespace X
+{
+ inline void Foo () __attribute__((used));
+ export inline void Baz () __attribute__((used));
+
+ namespace Y
+ {
+ inline void Quux () __attribute__((used));
+ export inline void Bar () __attribute__((used));
+ }
+
+ inline void Y::Quux () {}
+ inline void Y::Bar () {}
+}
+
+inline void X::Foo () {}
+inline void X::Baz () {}
+
+// { dg-final { scan-assembler "_ZW3bobEN1X3FooEv:" } }
+// { dg-final { scan-assembler "_ZN1X3BazEv:" } }
+// { dg-final { scan-assembler "_ZW3bobEN1X1Y4QuuxEv:" } }
+// { dg-final { scan-assembler "_ZN1X1Y3BarEv:" } }
diff --git a/gcc/testsuite/g++.dg/modules/mod-tpl-1_a.C b/gcc/testsuite/g++.dg/modules/mod-tpl-1_a.C
new file mode 100644
index 0000000..f48e123
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-tpl-1_a.C
@@ -0,0 +1,12 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module Frob;
+// { dg-module-cmi "Frob" }
+
+export template <typename T>
+T twice (T x)
+{
+ return x * 2;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/mod-tpl-1_b.C b/gcc/testsuite/g++.dg/modules/mod-tpl-1_b.C
new file mode 100644
index 0000000..669f2c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-tpl-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+import Frob;
+
+int main ()
+{
+ return twice (2) != 4;
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-tpl-2_a.C b/gcc/testsuite/g++.dg/modules/mod-tpl-2_a.C
new file mode 100644
index 0000000..86281bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-tpl-2_a.C
@@ -0,0 +1,16 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi "frob" }
+
+export template <typename T>
+class X
+{
+ T m;
+
+public:
+ void frob (T v) { m = v; }
+
+ T frobber (T v) { return v + m; }
+};
diff --git a/gcc/testsuite/g++.dg/modules/mod-tpl-2_b.C b/gcc/testsuite/g++.dg/modules/mod-tpl-2_b.C
new file mode 100644
index 0000000..8452c7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-tpl-2_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+int main ()
+{
+ X<int> x;
+
+ x.frob (3);
+
+ return ! (x.frobber (-3) == 0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/modules.exp b/gcc/testsuite/g++.dg/modules/modules.exp
new file mode 100644
index 0000000..e2fd2a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/modules.exp
@@ -0,0 +1,376 @@
+# Copyright (C) 2017, 2018 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+#
+# Contributed by Nathan Sidwell <nathan@acm.org> while at Facebook
+
+
+# Test C++ modules, which requires multiple TUs
+#
+# A test case might consist of multiple source files, each is compiled
+# separately, in a well-defined order. The resulting object files might
+# be optionally linked and optionally executed. Grouping is indicated by
+# naming files '*_[a-z].[CH]'
+
+# { dg-module-cmi "[!]module-name" } # an interface file is (not) expected
+# { dg-module-do [link|run] [xfail] [options] } # link [and run]
+
+load_lib g++-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+ set DEFAULT_CXXFLAGS " -pedantic-errors -Wno-long-long"
+}
+set DEFAULT_MODFLAGS $DEFAULT_CXXFLAGS
+set MOD_STD_LIST { 17 2a }
+
+setenv CXX_MODULE_PATH "$srcdir/$subdir"
+dg-init
+
+global module_do
+global module_cmis
+global module_headers
+
+set DEFAULT_REPO "gcm.cache"
+
+# Register the module name this produces.
+# dg-module-cmi !?=?NAME WHEN?
+# dg-module-cmi !?{} - header unit
+proc dg-module-cmi { args } {
+ if { [llength $args] > 3 } {
+ error "[lindex $args 0]: too many arguments"
+ return
+ }
+ set spec [lindex $args 1]
+ if { [llength $args] > 2 } {
+ set when [lindex $args 2]
+ } else {
+ set when {}
+ }
+
+ if { [string index $spec 0] == "!" } {
+ set name [string range $spec 1 end]
+ set not 1
+ } else {
+ set name $spec
+ set not 0
+ }
+
+ if { [string index $name 0] == "=" } {
+ set cmi [string range $name 1 end]
+ } else {
+ if { $name == "" } {
+ # get the source file name. ick!
+ upvar prog srcname
+ set cmi "$srcname.gcm"
+ if { [string index $cmi 0] == "/" } {
+ set cmi [string range $cmi 1 end]
+ } else {
+ set cmi ",/$cmi"
+ }
+ set path [file split $cmi]
+ # subst /../ -> /,,/
+ # sadly tcl 8.5 does not have lmap
+ set rplac {}
+ foreach elt $path {lappend rplac [expr {$elt == ".." ? ",," : $elt}]}
+ set cmi [file join {*}$rplac]
+ } else {
+ set cmi "[regsub : $name -].gcm"
+ }
+ global DEFAULT_REPO
+ set cmi "$DEFAULT_REPO/$cmi"
+ }
+
+ # delete file, so we don't get confused by a stale one.
+ file_on_host delete "$cmi"
+
+ global module_cmis
+ lappend module_cmis [list $spec $when $not $cmi]
+}
+
+# check the expected module files exist (or not)
+# return list to delete
+proc module_cmi_p { src ifs } {
+ set res {}
+ foreach if_arg $ifs {
+ set spec [lindex $if_arg 0]
+ set when [lindex $if_arg 1]
+ if { $when != "" } {
+ switch [dg-process-target $when] {
+ "S" { }
+ "N" { continue }
+ "F" { setup_xfail "*-*-*" }
+ "P" { }
+ }
+ }
+ set not [lindex $if_arg 2]
+ set cmi [lindex $if_arg 3]
+ if { $not != [file_on_host exists $cmi] } {
+ pass "$src module-cmi $spec ($cmi)"
+ } else {
+ fail "$src module-cmi $spec ($cmi)"
+ set not [expr ! $not ]
+ }
+ if { ! $not } {
+ lappend res $cmi
+ }
+ }
+ return $res
+}
+
+# Append required header unit names to module_headers var
+proc dg-module-headers { args } {
+ if { [llength $args] != 3 } {
+ error "[lindex $args 0]: wrong number of arguments"
+ return
+ }
+}
+
+proc do_module_headers { srcdir subdir std flags} {
+ global module_headers
+ foreach header $module_headers {
+ set kind [lindex $header 0]
+ set hdr [lindex $header 1]
+ verbose "Header $hdr $std" 1
+ switch $kind {
+ test {
+ global module_cmis
+ set module_cmis {}
+ dg-test -keep-output $srcdir/$subdir/$hdr "$std" $flags
+ global mod_files
+ lappend mod_files [module_cmi_p $subdir/$hdr $module_cmis]
+ }
+ system -
+ user {
+ # FIXME
+ }
+ default {
+ error "$kind unknown header"
+ }
+ }
+ }
+}
+
+# link and maybe run a set of object files
+# dg-module-do WHAT WHEN
+proc dg-module-do { args } {
+ if { [llength $args] > 3 } {
+ error "[lindex $args 0]: too many arguments"
+ return
+ }
+
+ set do_what [lindex $args 1]
+ set expected "P"
+ if { [llength $args] > 2 } {
+ set expected [dg-process-target [lindex $args 2]]
+ }
+
+ global module_do
+ set module_do [list $do_what $expected]
+}
+
+proc module_do_it { do_what testcase std asm_list } {
+ global tool
+
+ set run 0
+ switch [lindex $do_what 0] {
+ "compile" { return 1 }
+ "link" { }
+ "run" { set run 1 }
+ default { error "unknown module-do action [lindex $do_what 0]" }
+ }
+
+ set xfail {}
+ switch [lindex $do_what 1] {
+ "S" { }
+ "N" { return 1 }
+ "F" { set xfail {setup_xfail "*-*-*"} }
+ "P" { }
+ }
+
+ set ok 1
+ # make sure all asms are around
+ foreach asm $asm_list {
+ if { ! [file_on_host exists $asm] } {
+ set ok 0
+ }
+ }
+
+ set options { }
+ if { $std != "" } {
+ lappend options "additional_flags=$std"
+ }
+ if { [llength $do_what] > 3 } {
+ lappend options "additional_flags=[lindex $do_what 3]"
+ }
+
+ set execname "./[file tail $testcase].exe"
+
+ # link it
+ verbose "Linking $asm_list" 1
+ if { !$ok } {
+ unresolved "$testcase link"
+ } else {
+ set out [${tool}_target_compile $asm_list \
+ $execname executable $options]
+ eval $xfail
+ if { $out == "" } {
+ pass "$testcase link"
+ } else {
+ fail "$testcase link"
+ set ok 0
+ }
+ }
+
+ # run it?
+ if { !$run } {
+ } elseif { !$ok } {
+ unresolved "$testcase execute"
+ } else {
+ set out [${tool}_load $execname "" ""]
+ set status [lindex $out 0]
+ eval $xfail
+ $status "$testcase execute"
+ if { $status != "pass" } {
+ set $ok 0
+ }
+ }
+
+ if { $ok } {
+ file_on_host delete $execname
+ }
+
+ return $ok
+}
+
+# delete the specified set of module files
+proc cleanup_module_files { files } {
+ foreach file $files {
+ file_on_host delete $file
+ }
+}
+
+global testdir
+set testdir $srcdir/$subdir
+proc srcdir {} {
+ global testdir
+ return $testdir
+}
+
+# Return set of std options to iterate over, taken from g++-dg.exp & compat.exp
+proc module-init { src } {
+ set tmp [dg-get-options $src]
+ set option_list {}
+ global module_headers
+ set module_headers {}
+ set have_std 0
+ set std_prefix "-std=c++"
+
+ foreach op $tmp {
+ switch [lindex $op 0] {
+ "dg-options" {
+ set std_prefix "-std=gnu++"
+ if { [string match "*-std=*" [lindex $op 2]] } {
+ set have_std 1
+ }
+ }
+ "dg-additional-options" {
+ if { [string match "*-std=*" [lindex $op 2]] } {
+ set have_std 1
+ }
+ }
+ "dg-module-headers" {
+ set kind [lindex $op 2]
+ foreach header [lindex $op 3] {
+ lappend module_headers [list $kind $header]
+ }
+ }
+ }
+ }
+
+ if { !$have_std } {
+ global MOD_STD_LIST
+ foreach x $MOD_STD_LIST {
+ lappend option_list "${std_prefix}$x"
+ }
+ } else {
+ lappend option_list ""
+ }
+
+ return $option_list
+}
+
+# not grouped tests, sadly tcl doesn't have negated glob
+foreach test [prune [lsort [find $srcdir/$subdir {*.[CH]}]] \
+ "$srcdir/$subdir/*_?.\[CH\]"] {
+ if [runtest_file_p $runtests $test] {
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+
+ set std_list [module-init $test]
+ foreach std $std_list {
+ do_module_headers $srcdir $subdir $std $DEFAULT_MODFLAGS
+ set module_cmis {}
+ verbose "Testing $nshort $std" 1
+ dg-test $test "$std" $DEFAULT_MODFLAGS
+ set testcase [string range $test [string length "$srcdir/"] end]
+ cleanup_module_files [module_cmi_p $testcase $module_cmis]
+ }
+ }
+}
+
+# grouped tests
+foreach src [lsort [find $srcdir/$subdir {*_a.[CH}]] {
+ # use the FOO_a.C name as the parallelization key
+ if [runtest_file_p $runtests $src] {
+ set tests [lsort [find [file dirname $src] \
+ [regsub {_a.[CH]$} [file tail $src] {_[a-z].[CH]}]]]
+
+ set std_list [module-init $src]
+ foreach std $std_list {
+ set mod_files {}
+ global module_do
+ set module_do {"compile" "P"}
+ set asm_list {}
+ do_module_headers $srcdir $subdir $std $DEFAULT_MODFLAGS
+ foreach test $tests {
+ if { [lindex $module_do 1] != "N" } {
+ set module_cmis {}
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+ verbose "Testing $nshort $std" 1
+ if { [file extension $test] == ".C" } {
+ lappend asm_list [file rootname [file tail $test]].s
+ }
+ dg-test -keep-output $test "$std" $DEFAULT_MODFLAGS
+ set testcase [string range $test [string length "$srcdir/"] end]
+ lappend mod_files [module_cmi_p $testcase $module_cmis]
+ }
+ }
+ set ok 1
+ set testcase [regsub {_a.[CH]} $src {}]
+ set testcase \
+ [string range $testcase [string length "$srcdir/"] end]
+ set ok [module_do_it $module_do $testcase $std $asm_list]
+ if { $ok } {
+ foreach asm $asm_list {
+ file_on_host delete $asm
+ }
+ cleanup_module_files $mod_files
+ }
+ }
+ }
+}
+
+dg-finish
diff --git a/gcc/testsuite/g++.dg/modules/mutual-friend.ii b/gcc/testsuite/g++.dg/modules/mutual-friend.ii
new file mode 100644
index 0000000..b42b979
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mutual-friend.ii
@@ -0,0 +1,11 @@
+class exception_ptr;
+
+
+void rethrow_exception(exception_ptr);
+
+
+class exception_ptr
+{
+ friend void rethrow_exception(exception_ptr);
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/namespace-1_a.C b/gcc/testsuite/g++.dg/modules/namespace-1_a.C
new file mode 100644
index 0000000..1929acc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-1_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Frob;
+// { dg-module-cmi Frob }
+
+namespace impl
+{
+ export int doit (int);
+}
+
+namespace ompl
+{
+ export int doneit (int);
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-1_b.C b/gcc/testsuite/g++.dg/modules/namespace-1_b.C
new file mode 100644
index 0000000..096e6ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+export module Frink;
+// { dg-module-cmi Frink }
+
+import Frob;
+
+export int frab (int x)
+{
+ return impl::doit (x) + ompl::doneit (x);
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-1_c.C b/gcc/testsuite/g++.dg/modules/namespace-1_c.C
new file mode 100644
index 0000000..748ef5d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-1_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+// The indirect import of frob, with namespaces impl and ompl doesn't
+// affect us.
+static int impl;
+import Frink;
+
+static int ompl;
+
+void corge (int x)
+{
+ impl = x;
+ ompl = frab (x);
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-2_a.C b/gcc/testsuite/g++.dg/modules/namespace-2_a.C
new file mode 100644
index 0000000..18327e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-2_a.C
@@ -0,0 +1,40 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -Wno-pedantic" }
+
+module;
+# 5 "gmf" 1
+namespace not_exported
+{
+ // not in purview
+}
+# 10 "" 2
+export module foo;
+// { dg-module-cmi foo }
+
+namespace explicit_export
+{
+}
+
+namespace implicit_export
+{
+ export int bob ();
+}
+
+namespace also_not_exported
+{
+ int bob ();
+}
+
+export namespace explicit_export
+{
+ namespace also_exported
+ {
+ }
+}
+
+// { dg-final { scan-lang-dump-not {Writable bindings at '::not_exported'} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::implicit_export', export, public} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::explicit_export', export, public} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::also_not_exported', public} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::explicit_export::also_exported', export, public} "module" } }
+// { dg-final { scan-lang-dump-not {Writing namespace:[0-9] '::not_exported'} "module" } }
+// { dg-final { scan-lang-dump-not {Writing namespace:[0-9] '::std'} "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/namespace-2_b.C b/gcc/testsuite/g++.dg/modules/namespace-2_b.C
new file mode 100644
index 0000000..6ab5113
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-2_b.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+static int also_not_exported; // ok
+
+void X ()
+{
+ implicit_export::bob ();
+}
+
+static int implicit_export; // { dg-error "different kind" }
+
+void Y ()
+{
+ also_not_exported = 1;
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-3_a.C b/gcc/testsuite/g++.dg/modules/namespace-3_a.C
new file mode 100644
index 0000000..8e9508d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-3_a.C
@@ -0,0 +1,21 @@
+// Check namespace needed only by internal reference is not made visible
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+namespace silent
+{
+ namespace inner
+ {
+ static int X ()
+ {
+ return 1;
+ }
+ }
+}
+
+export int f (int y)
+{
+ return y + silent::inner::X ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-3_b.C b/gcc/testsuite/g++.dg/modules/namespace-3_b.C
new file mode 100644
index 0000000..f779ffe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-3_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+int x = silent; // { dg-error "not declared" }
+
+static int silent;
+
+int user ()
+{
+ return f (silent);
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-4_a.C b/gcc/testsuite/g++.dg/modules/namespace-4_a.C
new file mode 100644
index 0000000..b49e0ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-4_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+namespace
+{
+ int nope;
+}
+
+export int f (int)
+{
+ return nope;
+}
+
+int g (int *a);
diff --git a/gcc/testsuite/g++.dg/modules/namespace-4_b.C b/gcc/testsuite/g++.dg/modules/namespace-4_b.C
new file mode 100644
index 0000000..3530bcd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-4_b.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module frob;
+
+namespace
+{
+void *nope; // ok, different nope
+}
+
+void *q (int)
+{
+ f (bool (nope));
+ g (static_cast <int *> (nope));
+ return nope; // Ok sees above nope
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-4_c.C b/gcc/testsuite/g++.dg/modules/namespace-4_c.C
new file mode 100644
index 0000000..2526289
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/namespace-4_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+namespace
+{
+ float *nope;
+}
+
+float *q ()
+{
+ f (int (*nope));
+ return nope;
+}
diff --git a/gcc/testsuite/g++.dg/modules/nest-1_a.C b/gcc/testsuite/g++.dg/modules/nest-1_a.C
new file mode 100644
index 0000000..4788d5d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nest-1_a.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo {
+
+ export int frob (int i)
+ {
+ return i;
+ }
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/nest-1_b.C b/gcc/testsuite/g++.dg/modules/nest-1_b.C
new file mode 100644
index 0000000..cc30278
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nest-1_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int frob (int i)
+ {
+ return i;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/modules/nest-1_c.C b/gcc/testsuite/g++.dg/modules/nest-1_c.C
new file mode 100644
index 0000000..05ca02f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nest-1_c.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts --param lazy-modules=1" }
+import bar;
+
+int main ()
+{
+ return bar::frob (0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/nested-1_a.C b/gcc/testsuite/g++.dg/modules/nested-1_a.C
new file mode 100644
index 0000000..3172657
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-1_a.C
@@ -0,0 +1,19 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module blinky;
+// { dg-module-cmi blinky }
+
+export struct X
+{
+ struct Inner
+ {
+ int m;
+ Inner (int);
+ int getter () const
+ {
+ return m;
+ }
+ };
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/nested-1_b.C b/gcc/testsuite/g++.dg/modules/nested-1_b.C
new file mode 100644
index 0000000..9f775b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module blinky;
+
+X::Inner::Inner (int m_)
+ :m (m_)
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/nested-1_c.C b/gcc/testsuite/g++.dg/modules/nested-1_c.C
new file mode 100644
index 0000000..f46e6df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-1_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import blinky;
+
+int main ()
+{
+ X::Inner i (7);
+
+ if (i.getter () != 7)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/nested-2_a.C b/gcc/testsuite/g++.dg/modules/nested-2_a.C
new file mode 100644
index 0000000..e219735
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-2_a.C
@@ -0,0 +1,24 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export struct X
+{
+ typedef X *iter;
+
+ int m;
+ X() :m(-1)
+ {
+ }
+
+ void set (int m_)
+ {
+ m = m_;
+ }
+ operator int () const
+ {
+ return m;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/nested-2_b.C b/gcc/testsuite/g++.dg/modules/nested-2_b.C
new file mode 100644
index 0000000..1ca02bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-2_b.C
@@ -0,0 +1,20 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import bob;
+
+int main ()
+{
+ X ary[10];
+ X::iter iter;
+ unsigned ix;
+
+ for (ix = 10, iter = ary; ix--; iter++)
+ iter->set (ix);
+
+ for (ix = 10; ix--;)
+ if (ary[ix] + ix != 9)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/nested-constr-1.h b/gcc/testsuite/g++.dg/modules/nested-constr-1.h
new file mode 100644
index 0000000..6962cca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-constr-1.h
@@ -0,0 +1,15 @@
+
+template<typename T>
+struct traits
+{
+ template<typename U>
+ struct nested
+ { using type = void; };
+
+ template<typename U> requires requires { typename U::type; }
+ struct nested<U>
+ { using type = typename U::type; };
+};
+
+using V = traits<char>::nested<int>::type;
+
diff --git a/gcc/testsuite/g++.dg/modules/nested-constr-1_a.H b/gcc/testsuite/g++.dg/modules/nested-constr-1_a.H
new file mode 100644
index 0000000..9398986
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-constr-1_a.H
@@ -0,0 +1,3 @@
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+#include "nested-constr-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/nested-constr-1_b.C b/gcc/testsuite/g++.dg/modules/nested-constr-1_b.C
new file mode 100644
index 0000000..7043ffa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-constr-1_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "nested-constr-1.h"
+import "nested-constr-1_a.H";
+
+struct X
+{
+ using type = int;
+};
+
+traits<char>::nested<X>::type b;
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/nested-constr-2_a.C b/gcc/testsuite/g++.dg/modules/nested-constr-2_a.C
new file mode 100644
index 0000000..b29d670
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-constr-2_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T>
+struct traits
+{
+ template<typename U>
+ struct nested
+ { using type = void; };
+
+ template<typename U> requires requires { typename U::type; }
+ struct nested<U>
+ { using type = typename U::type; };
+};
+
+export using V = traits<char>::nested<int>::type;
+
diff --git a/gcc/testsuite/g++.dg/modules/nested-constr-2_b.C b/gcc/testsuite/g++.dg/modules/nested-constr-2_b.C
new file mode 100644
index 0000000..a34ef52
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-constr-2_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+export module bar;
+// { dg-module-cmi bar }
+import foo;
+
+struct X
+{
+ using type = int;
+};
+
+export traits<char>::nested<X>::type b;
diff --git a/gcc/testsuite/g++.dg/modules/nested-constr-2_c.C b/gcc/testsuite/g++.dg/modules/nested-constr-2_c.C
new file mode 100644
index 0000000..5c81b3b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nested-constr-2_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+
+import bar;
+
+decltype(b) c;
diff --git a/gcc/testsuite/g++.dg/modules/nodes-1_a.C b/gcc/testsuite/g++.dg/modules/nodes-1_a.C
new file mode 100644
index 0000000..446461c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nodes-1_a.C
@@ -0,0 +1,46 @@
+// { dg-additional-options -fmodules-ts }
+// { dg-module-do run }
+
+export module node;
+// { dg-module-cmi node }
+
+export template <typename T> void assert (T t)
+{
+ static_assert (sizeof (T) == sizeof (int), "whoops");
+}
+
+export class other
+{
+public:
+ other () :f (5) {}
+ void o () { }
+ int f;
+};
+
+export template<typename T> class baselink : T, other
+{
+public:
+ int Frob ()
+ {
+ o ();
+ return this->T::frob ();
+ }
+};
+
+export template <typename T> bool trait ()
+{
+ return __has_nothrow_assign(T);
+}
+
+export inline bool ptrmemdata (other const &obj)
+{
+ int other::*ptr = &other::f;
+
+ return (obj.*ptr) == 5;
+}
+
+export template<typename T> int ptrmemfn (T const &obj)
+{
+ int (T::*ptr) () const = &T::frob;
+ return (obj.*ptr) ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/nodes-1_b.C b/gcc/testsuite/g++.dg/modules/nodes-1_b.C
new file mode 100644
index 0000000..1567e90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nodes-1_b.C
@@ -0,0 +1,27 @@
+// { dg-additional-options -fmodules-ts }
+import node;
+
+struct b
+{
+ int frob () const
+ {
+ return 0;
+ }
+};
+
+int main ()
+{
+ assert (0);
+ baselink<b> thing;
+ thing.Frob ();
+ if (!trait<b> ())
+ return 1;
+
+ if (!ptrmemdata (other ()))
+ return 2;
+
+ if (ptrmemfn (b ()))
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-1.h b/gcc/testsuite/g++.dg/modules/noexcept-1.h
new file mode 100644
index 0000000..a4a0de5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/noexcept-1.h
@@ -0,0 +1,78 @@
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+ static constexpr _Tp value = __v;
+ typedef _Tp value_type;
+ typedef integral_constant<_Tp, __v> type;
+};
+
+template<typename _Tp, _Tp __v>
+constexpr _Tp integral_constant<_Tp, __v>::value;
+
+typedef integral_constant<bool, false> false_type;
+
+
+template<typename _T1>
+struct Alien
+{
+};
+
+template<typename _T1>
+bool operator==(const Alien<_T1>& __x, const Alien<_T1>& __y);
+
+template<typename _Rep>
+struct duration;
+
+template<bool _DenIsOne>
+struct __duration_cast_impl
+{
+};
+
+template<typename _ToDur, typename _Rep>
+long Frob (const duration<_Rep>& __d)
+{
+ typedef __duration_cast_impl<// finds ::operator==
+ _ToDur::num == 1> __dc;
+
+ return 0;
+}
+
+template<typename _Rep>
+struct duration
+{
+public:
+ constexpr duration() = default;
+
+ duration (const duration& __d)
+ {
+ Frob <duration> (__d);
+ }
+};
+
+template<typename _Tp>
+struct __atomic_semaphore
+{
+ template<typename _Rep>
+ bool _M_try_acquire_for (const duration<_Rep>& __rtime) noexcept;
+
+ void _M_release() noexcept;
+};
+
+template<long __least_max_value>
+class counting_semaphore
+{
+ __atomic_semaphore<unsigned> _M_sem;
+
+public:
+ explicit counting_semaphore() noexcept;
+
+ void release() noexcept (noexcept (_M_sem._M_release ()));
+};
+
+class stop_token
+{
+public:
+ counting_semaphore<1> _M_done;
+};
+
+bool operator==(const stop_token& __a, const stop_token& __b);
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-1_a.H b/gcc/testsuite/g++.dg/modules/noexcept-1_a.H
new file mode 100644
index 0000000..00949cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/noexcept-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options {-std=c++20 -fmodule-header} }
+// { dg-module-cmi {} }
+
+#include "noexcept-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-1_b.C b/gcc/testsuite/g++.dg/modules/noexcept-1_b.C
new file mode 100644
index 0000000..62a13fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/noexcept-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options {-std=c++20 -fmodules-ts -fno-module-lazy} }
+
+#include "noexcept-1.h"
+import "noexcept-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/ns-alias-1_a.C b/gcc/testsuite/g++.dg/modules/ns-alias-1_a.C
new file mode 100644
index 0000000..9f501ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-alias-1_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export namespace detail {
+ using bob = int;
+}
+
+namespace elsewhere {
+export namespace det = ::detail;
+namespace ail = ::detail;
+
+void frob (det::bob);
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-alias-1_b.C b/gcc/testsuite/g++.dg/modules/ns-alias-1_b.C
new file mode 100644
index 0000000..55fd926
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-alias-1_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module foo;
+
+elsewhere::det::bob j;
+elsewhere::ail::bob k;
diff --git a/gcc/testsuite/g++.dg/modules/ns-alias-1_c.C b/gcc/testsuite/g++.dg/modules/ns-alias-1_c.C
new file mode 100644
index 0000000..9e4a81d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-alias-1_c.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+elsewhere::det::bob j;
+elsewhere::ail::bob k; // { dg-error "does not name a type" }
diff --git a/gcc/testsuite/g++.dg/modules/ns-dir-1_a.C b/gcc/testsuite/g++.dg/modules/ns-dir-1_a.C
new file mode 100644
index 0000000..d63f9fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-dir-1_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace detail {
+int i;
+}
+
+namespace elsewhere {
+
+export inline void frob ()
+{
+ using namespace detail;
+ i = 5;
+}
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-dir-1_b.C b/gcc/testsuite/g++.dg/modules/ns-dir-1_b.C
new file mode 100644
index 0000000..b26e787
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-dir-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+void foo ()
+{
+ elsewhere::frob ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-dup-1_a.C b/gcc/testsuite/g++.dg/modules/ns-dup-1_a.C
new file mode 100644
index 0000000..600f518
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-dup-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export namespace std
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-dup-1_b.C b/gcc/testsuite/g++.dg/modules/ns-dup-1_b.C
new file mode 100644
index 0000000..23190db
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-dup-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+module;
+# 5 __FILE__ 1
+namespace std {}
+# 7 "" 2
+export module bob;
+// { dg-module-cmi bob }
+
+import foo;
+namespace std {}
diff --git a/gcc/testsuite/g++.dg/modules/ns-imp-1_a.C b/gcc/testsuite/g++.dg/modules/ns-imp-1_a.C
new file mode 100644
index 0000000..9a91a1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-imp-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi {Foo} }
+
+namespace Bob
+{
+export int Random ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-imp-1_b.C b/gcc/testsuite/g++.dg/modules/ns-imp-1_b.C
new file mode 100644
index 0000000..449c705
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-imp-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Bar;
+// { dg-module-cmi {Bar} }
+
+export import Foo;
+
+namespace Bob
+{
+export int Quux ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-imp-1_c.C b/gcc/testsuite/g++.dg/modules/ns-imp-1_c.C
new file mode 100644
index 0000000..2a58a91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-imp-1_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+
+export import Foo;
+export import Bar;
+
+namespace Bob
+{
+void Widget ()
+{
+ Random ();
+ Quux ();
+}
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-part-1_a.C b/gcc/testsuite/g++.dg/modules/ns-part-1_a.C
new file mode 100644
index 0000000..5b761df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-part-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Foo:A;
+// { dg-module-cmi {Foo:A} }
+
+namespace Bob
+{
+export int Random ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-part-1_b.C b/gcc/testsuite/g++.dg/modules/ns-part-1_b.C
new file mode 100644
index 0000000..d5b49b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-part-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Foo:B;
+// { dg-module-cmi {Foo:B} }
+
+export import :A;
+
+namespace Bob
+{
+export int Quux ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/ns-part-1_c.C b/gcc/testsuite/g++.dg/modules/ns-part-1_c.C
new file mode 100644
index 0000000..ee0ec40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ns-part-1_c.C
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi {Foo} }
+
+export import :A;
+export import :B;
+
+namespace Bob
+{
+export void Widget ()
+{
+ Random ();
+ Quux ();
+}
+}
diff --git a/gcc/testsuite/g++.dg/modules/nsdmi-1_a.C b/gcc/testsuite/g++.dg/modules/nsdmi-1_a.C
new file mode 100644
index 0000000..8e26d3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nsdmi-1_a.C
@@ -0,0 +1,9 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module nsdmi;
+// { dg-module-cmi nsdmi }
+
+export struct Bob
+{
+ int m = 42;
+};
diff --git a/gcc/testsuite/g++.dg/modules/nsdmi-1_b.C b/gcc/testsuite/g++.dg/modules/nsdmi-1_b.C
new file mode 100644
index 0000000..032cf5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nsdmi-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+import nsdmi;
+
+int main ()
+{
+ Bob b;
+
+ return b.m != 42;
+}
diff --git a/gcc/testsuite/g++.dg/modules/nsdmi-2.C b/gcc/testsuite/g++.dg/modules/nsdmi-2.C
new file mode 100644
index 0000000..081c1a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/nsdmi-2.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module foo;
+// { dg-module-cmi foo }
+
+
+export enum class file_type : signed char { none = 0 };
+
+export class directory_entry
+{
+public:
+ directory_entry(int);
+
+ int _M_path;
+
+ // ICE from deferred_parse NSDMI in as_base class
+ file_type _M_type = file_type::none;
+};
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::directory_entry'\n \[1\]=decl definition '::directory_entry::__as_base '\n \[2\]=decl declaration '::directory_entry::__ct '\n} module } }
diff --git a/gcc/testsuite/g++.dg/modules/omp-1_a.C b/gcc/testsuite/g++.dg/modules/omp-1_a.C
new file mode 100644
index 0000000..722720a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-1_a.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export inline void frob (unsigned (&ary)[64])
+{
+ int sum = 0;
+
+#pragma omp for
+ for (unsigned ix = 0; ix < 64; ix++)
+ sum += ary[ix];
+
+#pragma omp simd safelen(16) aligned (ary : 16)
+ for (unsigned ix = 0; ix < 64; ix++)
+ ary[ix] *= 2;
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-1_b.C b/gcc/testsuite/g++.dg/modules/omp-1_b.C
new file mode 100644
index 0000000..f3f5d92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+
+import foo;
+
+unsigned ary[64];
+
+int main ()
+{
+ frob (ary);
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-1_c.C b/gcc/testsuite/g++.dg/modules/omp-1_c.C
new file mode 100644
index 0000000..f30f611
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-1_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+// { dg-regexp "In module imported at \[^\n]*omp-1_c.C:3:1:\nfoo: error: module contains OpenMP, use '-fopenmp' to enable\n" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/omp-2_a.C b/gcc/testsuite/g++.dg/modules/omp-2_a.C
new file mode 100644
index 0000000..d2291b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-2_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+// The OpenMPness doesn't escape to the interface.
+export void frob (unsigned (&ary)[64])
+{
+ int sum = 0;
+
+#pragma omp for
+ for (unsigned ix = 0; ix < 64; ix++)
+ sum += ary[ix];
+
+#pragma omp simd safelen(16) aligned (ary : 16)
+ for (unsigned ix = 0; ix < 64; ix++)
+ ary[ix] *= 2;
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-2_b.C b/gcc/testsuite/g++.dg/modules/omp-2_b.C
new file mode 100644
index 0000000..39f34c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-2_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+unsigned ary[64];
+
+int main ()
+{
+ frob (ary);
+}
diff --git a/gcc/testsuite/g++.dg/modules/only-1.C b/gcc/testsuite/g++.dg/modules/only-1.C
new file mode 100644
index 0000000..97dcb1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/only-1.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fmodule-only" }
+
+export module bob;
+// { dg-module-cmi bob }
diff --git a/gcc/testsuite/g++.dg/modules/only-2.C b/gcc/testsuite/g++.dg/modules/only-2.C
new file mode 100644
index 0000000..6be8c76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/only-2.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodule-only" }
+
+
+int i;
+// { dg-warning "for non-interface" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/modules/only-3.C b/gcc/testsuite/g++.dg/modules/only-3.C
new file mode 100644
index 0000000..a3c61c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/only-3.C
@@ -0,0 +1,5 @@
+// { dg-options "-fmodule-only" }
+
+
+int i;
+// { dg-warning "for non-interface" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/modules/operator-1_a.C b/gcc/testsuite/g++.dg/modules/operator-1_a.C
new file mode 100644
index 0000000..d7a7176
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/operator-1_a.C
@@ -0,0 +1,18 @@
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+module;
+# 5 __FILE__ 1
+
+struct Type {};
+bool operator==(Type const &, Type const &);
+
+# 10 "" 2
+export module Foo;
+// { dg-module-cmi Foo }
+
+export template<typename T>
+bool equal (T const &x, T const &y)
+{
+ return x == y;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/operator-1_b.C b/gcc/testsuite/g++.dg/modules/operator-1_b.C
new file mode 100644
index 0000000..dab8d10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/operator-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+struct Type {};
+
+import Foo;
+
+bool foo (Type const &t)
+{
+ return equal (t, t);
+}
diff --git a/gcc/testsuite/g++.dg/modules/p0713-1.C b/gcc/testsuite/g++.dg/modules/p0713-1.C
new file mode 100644
index 0000000..f7d8006
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p0713-1.C
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodules-ts" }
+module;
+module; // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/modules/p0713-2.C b/gcc/testsuite/g++.dg/modules/p0713-2.C
new file mode 100644
index 0000000..c7846e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p0713-2.C
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodules-ts" }
+int j;
+module; // { dg-error "not permitted" }
diff --git a/gcc/testsuite/g++.dg/modules/p0713-3.C b/gcc/testsuite/g++.dg/modules/p0713-3.C
new file mode 100644
index 0000000..3c539eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/p0713-3.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+int k;
+module frob; // { dg-error "not permitted" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/modules/part-1_a.C b/gcc/testsuite/g++.dg/modules/part-1_a.C
new file mode 100644
index 0000000..de58a20
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi foo:baz }
+
+export module foo:baz;
+
+export int baz ()
+{
+ return -1;
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-1_b.C b/gcc/testsuite/g++.dg/modules/part-1_b.C
new file mode 100644
index 0000000..c908c22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :baz;
+
+export int foo (int a)
+{
+ return a;
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-1_c.C b/gcc/testsuite/g++.dg/modules/part-1_c.C
new file mode 100644
index 0000000..88b0330
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-1_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int main ()
+{
+ if (baz () != -1)
+ return 1;
+
+ if (foo (42) != 42)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-2_a.C b/gcc/testsuite/g++.dg/modules/part-2_a.C
new file mode 100644
index 0000000..60fbe99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-2_a.C
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo:inter;
+// { dg-module-cmi foo:inter }
diff --git a/gcc/testsuite/g++.dg/modules/part-2_b.C b/gcc/testsuite/g++.dg/modules/part-2_b.C
new file mode 100644
index 0000000..c9bbac8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-2_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo:imp;
+// { dg-module-cmi foo:imp }
+
+import :inter; // ok
diff --git a/gcc/testsuite/g++.dg/modules/part-2_c.C b/gcc/testsuite/g++.dg/modules/part-2_c.C
new file mode 100644
index 0000000..759f1c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-2_c.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo:inter2;
+// { dg-module-cmi foo:inter2 }
+
+import :imp; // ok
+
+import :inter; // ok at this point
diff --git a/gcc/testsuite/g++.dg/modules/part-2_d.C b/gcc/testsuite/g++.dg/modules/part-2_d.C
new file mode 100644
index 0000000..b2e7289
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-2_d.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi !foo }
+
+import :imp; // ok
+
+export import :inter2; // ok
+
+// { dg-regexp "In module imported at \[^\n]*part-2_b.C:6:.,\nof module foo:imp, imported at \[^\n]*part-2_d.C:6:\nfoo:inter: error: interface partition is not exported\n" }
diff --git a/gcc/testsuite/g++.dg/modules/part-2_e.C b/gcc/testsuite/g++.dg/modules/part-2_e.C
new file mode 100644
index 0000000..677c066
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-2_e.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+import :imp; // ok
+
+export import :inter2; // ok
+
+export import :inter; // ok now
+
diff --git a/gcc/testsuite/g++.dg/modules/part-3_a.C b/gcc/testsuite/g++.dg/modules/part-3_a.C
new file mode 100644
index 0000000..85100d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-3_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+export module foo:bar;
+// { dg-module-cmi foo:bar }
+
+int foo (int x)
+{
+ return -x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-3_b.C b/gcc/testsuite/g++.dg/modules/part-3_b.C
new file mode 100644
index 0000000..a60ad3e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-3_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo:baz;
+// { dg-module-cmi foo:baz }
+
+int foo (int);
diff --git a/gcc/testsuite/g++.dg/modules/part-3_c.C b/gcc/testsuite/g++.dg/modules/part-3_c.C
new file mode 100644
index 0000000..aff7476
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-3_c.C
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :bar;
+export import :baz;
+
+export inline int frob (int x)
+{
+ return foo (x);
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]'s named merge key \(new\) function_decl:'::foo'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]'s named merge key \(matched\) function_decl:'::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster sections are \[1,3\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/part-3_d.C b/gcc/testsuite/g++.dg/modules/part-3_d.C
new file mode 100644
index 0000000..d07274a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-3_d.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+import foo;
+
+int main ()
+{
+ int r = frob (75);
+ return !(r == -75);
+}
+
+// { dg-final { scan-lang-dump { Read:-[0-9]'s named merge key \(unique\) function_decl:'::frob'} module } }
+// { dg-final { scan-lang-dump {> Read:-[0-9]'s named merge key \(unique\) function_decl:'::foo'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/part-4_a.C b/gcc/testsuite/g++.dg/modules/part-4_a.C
new file mode 100644
index 0000000..edd606b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-4_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+
+struct frob {
+ struct inner {};
+};
diff --git a/gcc/testsuite/g++.dg/modules/part-4_b.C b/gcc/testsuite/g++.dg/modules/part-4_b.C
new file mode 100644
index 0000000..a200eca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-4_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// detecting an ICE in dumping machinery
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :part1;
+
+export frob foo ()
+{
+ return frob ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-4_c.C b/gcc/testsuite/g++.dg/modules/part-4_c.C
new file mode 100644
index 0000000..1f319cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-4_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import foo;
+
+void f ()
+{
+ auto f = foo ();
+
+ decltype (f)::inner x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-6_a.C b/gcc/testsuite/g++.dg/modules/part-6_a.C
new file mode 100644
index 0000000..8fece83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-6_a.C
@@ -0,0 +1,15 @@
+// { dg-module-do link }
+// { dg-additional-options -fmodules-ts }
+
+export module foo:exp;
+// { dg-module-cmi foo:exp }
+
+export class Foo
+{
+ Foo ();
+
+public:
+ void Func ();
+
+ static Foo *Factory ();
+};
diff --git a/gcc/testsuite/g++.dg/modules/part-6_b.C b/gcc/testsuite/g++.dg/modules/part-6_b.C
new file mode 100644
index 0000000..0bad008
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-6_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :exp;
diff --git a/gcc/testsuite/g++.dg/modules/part-6_c.C b/gcc/testsuite/g++.dg/modules/part-6_c.C
new file mode 100644
index 0000000..395e709
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-6_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+module foo:bits;
+import :exp;
+
+void Foo::Func ()
+{
+}
+
+inline Foo::Foo ()
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-6_d.C b/gcc/testsuite/g++.dg/modules/part-6_d.C
new file mode 100644
index 0000000..71783a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-6_d.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+module foo;
+import :bits;
+
+Foo *Foo::Factory ()
+{
+ return new Foo ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-6_e.C b/gcc/testsuite/g++.dg/modules/part-6_e.C
new file mode 100644
index 0000000..6c1ba4c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-6_e.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int main ()
+{
+ Foo::Factory ()->Func ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-7_a.C b/gcc/testsuite/g++.dg/modules/part-7_a.C
new file mode 100644
index 0000000..32b10f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-7_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo:bill;
+// { dg-module-cmi foo:bill }
+
+export class frob;
+
+export template<int I> class FROB;
diff --git a/gcc/testsuite/g++.dg/modules/part-7_b.C b/gcc/testsuite/g++.dg/modules/part-7_b.C
new file mode 100644
index 0000000..9a7eb13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-7_b.C
@@ -0,0 +1,20 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-blocks} }
+
+module foo:bob;
+// { dg-module-cmi foo:bob }
+
+class frob
+{
+public:
+ int field;
+};
+
+template<int J>
+class FROB
+{
+public:
+ static constexpr int val = J;
+};
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::frob'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template FROB'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/part-7_c.C b/gcc/testsuite/g++.dg/modules/part-7_c.C
new file mode 100644
index 0000000..4e1df2a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-7_c.C
@@ -0,0 +1,19 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-blocks} }
+
+export module foo;
+// { dg-module-cmi foo }
+import :bob;
+export import :bill;
+
+int foo (frob *p)
+{
+ return p->field;
+}
+
+int foo (FROB<2> *p)
+{
+ return p->val;
+}
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::frob@foo:bob:1'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template FROB@foo:bob:1'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/part-hdr-1_a.H b/gcc/testsuite/g++.dg/modules/part-hdr-1_a.H
new file mode 100644
index 0000000..62f3b7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-hdr-1_a.H
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
diff --git a/gcc/testsuite/g++.dg/modules/part-hdr-1_b.C b/gcc/testsuite/g++.dg/modules/part-hdr-1_b.C
new file mode 100644
index 0000000..9375909
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-hdr-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+// { dg-module-cmi {mod:impl} }
+
+module;
+# 6 "inner" 1
+import "part-hdr-1_a.H";
+# 8 "" 2
+module mod:impl;
+
diff --git a/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C b/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
new file mode 100644
index 0000000..78a53d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi {mod} }
+
+export module mod;
+import mod:impl;
diff --git a/gcc/testsuite/g++.dg/modules/part-mac-1_a.H b/gcc/testsuite/g++.dg/modules/part-mac-1_a.H
new file mode 100644
index 0000000..191525d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-mac-1_a.H
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#define FOO(X) int X
+
diff --git a/gcc/testsuite/g++.dg/modules/part-mac-1_b.C b/gcc/testsuite/g++.dg/modules/part-mac-1_b.C
new file mode 100644
index 0000000..2adc3b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-mac-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+// { dg-module-cmi {mod:impl} }
+
+module;
+# 6 "inner" 1
+import "part-mac-1_a.H";
+# 8 "" 2
+module mod:impl;
+
+FOO(k);
diff --git a/gcc/testsuite/g++.dg/modules/part-mac-1_c.C b/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
new file mode 100644
index 0000000..78a53d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi {mod} }
+
+export module mod;
+import mod:impl;
diff --git a/gcc/testsuite/g++.dg/modules/partial-1.h b/gcc/testsuite/g++.dg/modules/partial-1.h
new file mode 100644
index 0000000..0f91107
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-1.h
@@ -0,0 +1,30 @@
+
+template<typename _Tp>
+class allocator {};
+
+template<typename _Alloc> struct allocator_traits;
+
+template<typename _Tp>
+struct allocator_traits <allocator<_Tp>>
+{
+ using pointer = _Tp*;
+};
+
+struct mutex {};
+
+template<typename _Tp, typename _Alloc>
+class Inplace
+{
+public:
+ virtual void _M_dispose() noexcept
+ {
+ // bogus error ambiguous partial specializations
+ typename allocator_traits<_Alloc>::pointer v;
+ }
+};
+
+inline void *
+allocate_shared()
+{
+ return new Inplace<mutex, allocator<mutex>> ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/partial-1_a.H b/gcc/testsuite/g++.dg/modules/partial-1_a.H
new file mode 100644
index 0000000..164a54c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "partial-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/partial-1_b.C b/gcc/testsuite/g++.dg/modules/partial-1_b.C
new file mode 100644
index 0000000..7e981eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "partial-1.h"
+import "partial-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/pmf-1.h b/gcc/testsuite/g++.dg/modules/pmf-1.h
new file mode 100644
index 0000000..e4c99f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmf-1.h
@@ -0,0 +1,10 @@
+
+struct X
+{
+ int mfn ();
+};
+
+inline void bob (X &)
+{
+ int (X::*pmf) () = &X::mfn;
+}
diff --git a/gcc/testsuite/g++.dg/modules/pmf-1_a.H b/gcc/testsuite/g++.dg/modules/pmf-1_a.H
new file mode 100644
index 0000000..c597db1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmf-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "pmf-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/pmf-1_b.C b/gcc/testsuite/g++.dg/modules/pmf-1_b.C
new file mode 100644
index 0000000..0b08610
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmf-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "pmf-1.h"
+import "pmf-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// The function-scope var is unique
+// { dg-final { scan-lang-dump-times {merge key \(unique\)} 1 module } }
diff --git a/gcc/testsuite/g++.dg/modules/pmf-2.h b/gcc/testsuite/g++.dg/modules/pmf-2.h
new file mode 100644
index 0000000..890b985
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmf-2.h
@@ -0,0 +1,26 @@
+template<typename _Tp>
+struct remove_reference
+{ typedef _Tp FOO; };
+
+template<typename _Tp>
+void forward (typename remove_reference<_Tp>::FOO const& __t)
+{
+}
+
+template<typename _Callable>
+void __invoke(_Callable const & __fn)
+{
+ forward<_Callable const>(__fn);
+}
+
+class _State_baseV2
+{
+public:
+ void _M_set_result()
+ {
+ __invoke (&_State_baseV2::_M_do_set);
+ }
+
+ void _M_do_set();
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/pmf-2_a.H b/gcc/testsuite/g++.dg/modules/pmf-2_a.H
new file mode 100644
index 0000000..b6bd763
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmf-2_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options {-fmodule-header -fdump-lang-module-uid} }
+// { dg-module-cmi {} }
+
+#include "pmf-2.h"
+
+// { dg-final { scan-lang-dump-times {Written:-[0-9]* ptrmem type} 1 module } }
diff --git a/gcc/testsuite/g++.dg/modules/pmf-2_b.C b/gcc/testsuite/g++.dg/modules/pmf-2_b.C
new file mode 100644
index 0000000..b76f090
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmf-2_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-uid" }
+
+#include "pmf-2.h"
+import "pmf-2_a.H";
+
+// { dg-final { scan-lang-dump {Cloned:-[0-9]* typedef template_type_parm:'::template remove_reference<_Tp>::template FOO<_Tp>'} module } }
+// { dg-final { scan-lang-dump {Created:-[0-9]* ptrmem type} module } }
diff --git a/gcc/testsuite/g++.dg/modules/pmp-1_a.C b/gcc/testsuite/g++.dg/modules/pmp-1_a.C
new file mode 100644
index 0000000..2832692
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmp-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+int k;
+
+module :private; // { dg-message "sorry, unimplemented: private module fragment" }
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/pmp-1_b.C b/gcc/testsuite/g++.dg/modules/pmp-1_b.C
new file mode 100644
index 0000000..40cb0fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmp-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+
+module bob;
+int k;
+
+module :private; // { dg-error "private module fragment" }
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/pmp-2.C b/gcc/testsuite/g++.dg/modules/pmp-2.C
new file mode 100644
index 0000000..56ce48f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmp-2.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+module :private; // { dg-message "sorry, unimplemented: private module fragment" }
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/pmp-3.C b/gcc/testsuite/g++.dg/modules/pmp-3.C
new file mode 100644
index 0000000..8c68bbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pmp-3.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+int k;
+
+module :private; // { dg-error "private module fragment" }
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/pragma-1_a.H b/gcc/testsuite/g++.dg/modules/pragma-1_a.H
new file mode 100644
index 0000000..6eb0a59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pragma-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+int i;
diff --git a/gcc/testsuite/g++.dg/modules/pragma-1_b.C b/gcc/testsuite/g++.dg/modules/pragma-1_b.C
new file mode 100644
index 0000000..55d5de3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pragma-1_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+#pragma GCC visibility push (default)
+#pragma GCC visibility pop
+
+import "pragma-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/predef-1.C b/gcc/testsuite/g++.dg/modules/predef-1.C
new file mode 100644
index 0000000..07a85b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/predef-1.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -nostdinc -include [srcdir]/predef-1.h" }
+// { dg-additional-files predef-1.C }
+
+// test macro expansion inside forced header
+
+export module bob;
diff --git a/gcc/testsuite/g++.dg/modules/predef-1.h b/gcc/testsuite/g++.dg/modules/predef-1.h
new file mode 100644
index 0000000..ab366d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/predef-1.h
@@ -0,0 +1,10 @@
+
+// expands a macro (inside #if conditional) inside forced header.
+// modelled on glibc's stdc_predef.h
+
+#define GCC_IEC_559 1
+
+# if GCC_IEC_559 > 0
+# define STDC_IEC_559__ 1
+# endif
+
diff --git a/gcc/testsuite/g++.dg/modules/predef-2.h b/gcc/testsuite/g++.dg/modules/predef-2.h
new file mode 100644
index 0000000..79486f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/predef-2.h
@@ -0,0 +1,7 @@
+
+// expands a macro (inside #if conditional) inside forced header.
+// modelled on glibc's stdc_predef.h
+
+// some builtin macro
+# if __GNUC__ > 0
+# endif
diff --git a/gcc/testsuite/g++.dg/modules/predef-2_a.C b/gcc/testsuite/g++.dg/modules/predef-2_a.C
new file mode 100644
index 0000000..bbf8344
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/predef-2_a.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -nostdinc -include [srcdir]/predef-2.h" }
+// { dg-additional-files predef-2.h }
+
+// test macro expansion inside forced header
+
+export module bob:part;
+// { dg-module-cmi bob:part }
diff --git a/gcc/testsuite/g++.dg/modules/predef-2_b.C b/gcc/testsuite/g++.dg/modules/predef-2_b.C
new file mode 100644
index 0000000..d0dfb88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/predef-2_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -nostdinc -include [srcdir]/predef-2.h" }
+// { dg-additional-files predef-2.h }
+
+// test macro expansion inside forced header
+
+export module bob;
+// { dg-module-cmi bob }
+
+export import :part;
diff --git a/gcc/testsuite/g++.dg/modules/preproc-1.C b/gcc/testsuite/g++.dg/modules/preproc-1.C
new file mode 100644
index 0000000..e7ba6d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/preproc-1.C
@@ -0,0 +1,3 @@
+# 0 "preproc-1.C"
+// { dg-additional-options "-fmodule-header -fpreprocessed" }
+// { dg-module-cmi {=gcm.cache/,/preproc-1.C.gcm} }
diff --git a/gcc/testsuite/g++.dg/modules/preproc-2_a.H b/gcc/testsuite/g++.dg/modules/preproc-2_a.H
new file mode 100644
index 0000000..8e81fb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/preproc-2_a.H
@@ -0,0 +1,11 @@
+# 0 "preproc-2_a.H"
+# 0 "<built-in>"
+#define __STDC__ 1
+# 0 "<command-line>"
+#define NAME bob
+# 1 "preproc-2_a.H"
+# 8 "preproc-2_a.H"
+void NAME ();
+
+// { dg-additional-options "-fmodules-ts -fpreprocessed -fdirectives-only" }
+// { dg-module-cmi {,/preproc-2_a.H} }
diff --git a/gcc/testsuite/g++.dg/modules/preproc-2_b.C b/gcc/testsuite/g++.dg/modules/preproc-2_b.C
new file mode 100644
index 0000000..8ce21fdc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/preproc-2_b.C
@@ -0,0 +1,21 @@
+# 0 "preproc-2_b.C"
+# 0 "<built-in>"
+#define __STDC__ 1
+# 0 "<command-line>"
+# 1 "preproc-2_b.C"
+# 7 "preproc-2_b.C"
+import "./preproc-2_a.H";
+
+#define NAME bill
+
+int NAME = 4;
+
+int bob; // error with header
+
+float NAME; // error with self
+
+// { dg-additional-options "-fmodules-ts -fpreprocessed -fdirectives-only" }
+
+// { dg-regexp {preproc-2_b.C:13:5: error: 'int bob' redeclared as different kind of entity\nIn module ./preproc-2_a.H, imported at preproc-2_b.C:7:\n<command-line>: note: previous declaration 'void bob\(\)'\npreproc-2_a.H:8:6: note: in expansion of macro 'NAME'} }
+
+// { dg-regexp {preproc-2_b.C:9:14: error: conflicting declaration 'float bill'\npreproc-2_b.C:15:7: note: in expansion of macro 'NAME'\npreproc-2_b.C:9:14: note: previous declaration as 'int bill'\npreproc-2_b.C:11:5: note: in expansion of macro 'NAME'} }
diff --git a/gcc/testsuite/g++.dg/modules/printf-1_a.H b/gcc/testsuite/g++.dg/modules/printf-1_a.H
new file mode 100644
index 0000000..900c063
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/printf-1_a.H
@@ -0,0 +1,9 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C"
+{
+ // this matches an anticipated fn
+ extern int printf (const char *__restrict, ...);
+}
diff --git a/gcc/testsuite/g++.dg/modules/printf-1_b.C b/gcc/testsuite/g++.dg/modules/printf-1_b.C
new file mode 100644
index 0000000..a434e76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/printf-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+import "printf-1_a.H";
+
+int main ()
+{
+ printf ("hello world!\n");
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/reparent-1_a.C b/gcc/testsuite/g++.dg/modules/reparent-1_a.C
new file mode 100644
index 0000000..c545098
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reparent-1_a.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi foo }
+
+
+export module foo;
+export void v ();
diff --git a/gcc/testsuite/g++.dg/modules/reparent-1_b.C b/gcc/testsuite/g++.dg/modules/reparent-1_b.C
new file mode 100644
index 0000000..b44ae1c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reparent-1_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+// { dg-module-cmi bar }
+
+
+module;
+# 7 "gmf1" 1
+# 8 "gmf2" 1
+# 9 "gmf3" 1
+import foo;
+# 11 "" 2
+# 12 "" 2
+# 13 "" 2
+export module bar;
+export import foo;
diff --git a/gcc/testsuite/g++.dg/modules/reparent-1_c.C b/gcc/testsuite/g++.dg/modules/reparent-1_c.C
new file mode 100644
index 0000000..e4e984c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reparent-1_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+import bar;
+
+int main ()
+{
+ v (0); // { dg-error "too many arguments" }
+}
+
+// { dg -regexp {In module foo, imported at [^\n]*/reparent-1_b.C:14,\nof module bar, imported at [^\n]*/reparent-1_c.C:2:\n[^\n]*/reparent-1_a.C:6:13: note: declared here\n} }
diff --git a/gcc/testsuite/g++.dg/modules/scc-1.C b/gcc/testsuite/g++.dg/modules/scc-1.C
new file mode 100644
index 0000000..a5d71f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/scc-1.C
@@ -0,0 +1,16 @@
+// Check SCC regions are atomic
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export int bar (int);
+export int baz (int = bar (1));
+export int bar (int = baz (1));
+
+// The ordering depends on hash table iteration, which is address-dependent
+
+// { dg-final { scan-lang-dump { Writing named:-[0-9]* function_decl:'::bar'} "module" } }
+// { dg-final { scan-lang-dump { Writing named:-[0-9]* function_decl:'::baz'} "module" } }
+// { dg-final { scan-lang-dump { \.[0-9]*\. Wrote backref:-[0-9]* function_decl:'::ba[rz]'} "module" } }
+// { dg-final { scan-lang-dump { Wrote backref:-[0-9]* function_decl:'::ba[rz]'} "module" } }
diff --git a/gcc/testsuite/g++.dg/modules/scc-2.C b/gcc/testsuite/g++.dg/modules/scc-2.C
new file mode 100644
index 0000000..385f27c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/scc-2.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+export module frob;
+// { dg-module-cmi frob }
+
+export enum X
+{
+ One, Two, Three
+};
diff --git a/gcc/testsuite/g++.dg/modules/shadow-1_a.C b/gcc/testsuite/g++.dg/modules/shadow-1_a.C
new file mode 100644
index 0000000..e4641aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/shadow-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+export module shadow;
+// { dg-module-cmi shadow }
+
+export struct stat
+{
+};
+
+export void stat ();
diff --git a/gcc/testsuite/g++.dg/modules/shadow-1_b.C b/gcc/testsuite/g++.dg/modules/shadow-1_b.C
new file mode 100644
index 0000000..6463812
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/shadow-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+import shadow;
+
+// unfortunately not the exact same diagnostic in both cases :(
+
+void stat (); // { dg-error "conflicts with import" }
+
+struct stat {}; // { dg-error "in a different module" }
diff --git a/gcc/testsuite/g++.dg/modules/stat-tpl-1_a.H b/gcc/testsuite/g++.dg/modules/stat-tpl-1_a.H
new file mode 100644
index 0000000..fa4991f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/stat-tpl-1_a.H
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _CharT>
+static inline __attribute__((__always_inline__)) constexpr void
+__constant_char_array_p ()
+{
+}
+
+inline void foo ()
+{
+ __constant_char_array_p<char> ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/static-1_a.C b/gcc/testsuite/g++.dg/modules/static-1_a.C
new file mode 100644
index 0000000..6bfced5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/static-1_a.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+# 5 "gmf" 1
+static void Bar () {}
+# 7 "" 2
+export module Foo;
+// { dg-module-cmi Foo }
+
+static void Baz () {}
+
diff --git a/gcc/testsuite/g++.dg/modules/static-1_b.C b/gcc/testsuite/g++.dg/modules/static-1_b.C
new file mode 100644
index 0000000..f2f170d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/static-1_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module Foo;
+
+void Frob ()
+{
+ Bar (); // { dg-error "not declared" }
+ Baz (); // { dg-error "not declared" }
+}
+
+static void Baz () {}
+static void Bar () {}
+
+void Quux ()
+{
+ Bar ();
+ Baz ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/static-1_c.C b/gcc/testsuite/g++.dg/modules/static-1_c.C
new file mode 100644
index 0000000..a7ab89a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/static-1_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import Foo;
+
+void Frob ()
+{
+ Bar (); // { dg-error "not declared" }
+ Baz (); // { dg-error "not declared" }
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/std-1_a.C b/gcc/testsuite/g++.dg/modules/std-1_a.C
new file mode 100644
index 0000000..53bdc7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/std-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+
+namespace std
+{
+int bob;
+}
diff --git a/gcc/testsuite/g++.dg/modules/std-1_b.C b/gcc/testsuite/g++.dg/modules/std-1_b.C
new file mode 100644
index 0000000..3fa4f40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/std-1_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+int *i = &std::bob;
diff --git a/gcc/testsuite/g++.dg/modules/stdns_a.C b/gcc/testsuite/g++.dg/modules/stdns_a.C
new file mode 100644
index 0000000..2d2cdbb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/stdns_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+
+export module std;
+// { dg-module-cmi std }
+
+namespace std
+{
+export int frob ()
+{
+ return 1;
+}
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/stdns_b.C b/gcc/testsuite/g++.dg/modules/stdns_b.C
new file mode 100644
index 0000000..c00e120
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/stdns_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import std;
+
+int main ()
+{
+ return !std::frob ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/sv-1.h b/gcc/testsuite/g++.dg/modules/sv-1.h
new file mode 100644
index 0000000..113ae1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sv-1.h
@@ -0,0 +1,75 @@
+template<bool __v>
+struct integral_constant {};
+
+typedef integral_constant<true> true_type;
+typedef integral_constant<false> false_type;
+
+template<typename>
+struct __is_not_void_helper
+ : public true_type { };
+
+template<> struct __is_not_void_helper<void>
+ : public false_type { };
+
+template<typename _Tp, typename _Up>
+struct is_same
+ : public integral_constant<__is_same_as(_Tp, _Up)> {};
+
+template<typename _Iterator>
+struct iterator_traits;
+
+template<typename _Tp> requires __is_not_void_helper<_Tp>::value
+struct iterator_traits<_Tp*>;
+
+template<typename _Tp>
+struct iterator {};
+
+template<typename _Iterator>
+class reverse_iterator
+ : public iterator<typename iterator_traits<_Iterator>::value_type>
+{
+};
+
+template<typename _Tp> struct _Deque_iterator;
+
+template<typename _Tp> void __copy_move_a1(_Deque_iterator<_Tp>);
+
+template<typename _Iterator>
+decltype (NOPE (_Iterator{})) __niter_base (reverse_iterator<_Iterator> __it);
+
+
+template<typename _II>
+inline void __copy_move_a (_II __first)
+{
+ __copy_move_a1 (__niter_base (__first));
+}
+
+template<typename _CharT>
+struct __gnu_char_traits
+{
+ static void move (const char* __s2)
+ {
+ __copy_move_a (__s2);
+ }
+};
+
+class string_view
+{
+ using t = __gnu_char_traits<char>;
+
+public:
+ string_view (const char* __str) noexcept;
+};
+
+template<typename _Ret>
+void __stoa ()
+{
+ struct _Range_chk {
+ static bool _S_chk (false_type) { return false; }
+ static bool _S_chk (true_type) { return true; }
+ };
+
+ _Range_chk::_S_chk (is_same<_Ret, long>{});
+}
+
+inline void stoi () { __stoa<long> (); }
diff --git a/gcc/testsuite/g++.dg/modules/sv-1_a.C b/gcc/testsuite/g++.dg/modules/sv-1_a.C
new file mode 100644
index 0000000..8d866fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sv-1_a.C
@@ -0,0 +1,7 @@
+// { dg-additional-options {-fmodules-ts -std=c++2a} }
+module;
+#include "sv-1.h"
+export module Hello;
+// { dg-module-cmi Hello }
+
+export void SayHello (string_view const &name);
diff --git a/gcc/testsuite/g++.dg/modules/sv-1_b.C b/gcc/testsuite/g++.dg/modules/sv-1_b.C
new file mode 100644
index 0000000..72dbe59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sv-1_b.C
@@ -0,0 +1,15 @@
+// { dg-additional-options {-std=c++2a -fmodules-ts -fno-module-lazy} }
+#include "sv-1.h"
+import Hello;
+
+#if 0
+int main ()
+{
+ SayHello ("World");
+}
+#endif
+
+void foo ()
+{
+ is_same<long, int> q;
+}
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-1.C b/gcc/testsuite/g++.dg/modules/sym-subst-1.C
new file mode 100644
index 0000000..96ee25c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-1.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+export module bob.stuart.kevin;
+// { dg-module-cmi bob.stuart.kevin }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW3bob6stuart5kevinE4frobRW_2E6mytype:} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-2_a.C b/gcc/testsuite/g++.dg/modules/sym-subst-2_a.C
new file mode 100644
index 0000000..cd0a79d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-2_a.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob.stuart;
+// { dg-module-cmi bob.stuart }
+
+template <typename T> void inner (T &)
+{
+}
+
+export template <typename T> void foo (T &x)
+{
+ inner (x);
+}
+
+// { dg-final { scan-assembler-not {all must have scan-assembler} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-2_b.C b/gcc/testsuite/g++.dg/modules/sym-subst-2_b.C
new file mode 100644
index 0000000..fc3db0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-2_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob.kevin;
+// { dg-module-cmi bob.kevin }
+
+import bob.stuart;
+
+class mytype
+{
+};
+
+void bar (mytype &m)
+{
+ foo (m);
+}
+
+// { dg-final { scan-assembler {_ZW3bob5kevinE3barRW_1E6mytype:} } }
+// { dg-final { scan-assembler {_ZW3bob6stuartE5innerIW_05kevinE6mytypeEvRT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-3_a.C b/gcc/testsuite/g++.dg/modules/sym-subst-3_a.C
new file mode 100644
index 0000000..bd958dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-3_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -std=c++17" }
+export module t.s;
+// { dg-module-cmi t.s }
+
+struct s;
+
+export s *S;
+
+// { dg-final { scan-assembler {.globa?l[ \t]*_?S\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-3_b.C b/gcc/testsuite/g++.dg/modules/sym-subst-3_b.C
new file mode 100644
index 0000000..9ae3f8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-3_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -std=c++17" }
+export module t;
+// { dg-module-cmi t }
+import t.s;
+struct t;
+export void f (t*, decltype (S)){}
+// { dg-final { scan-assembler {_Z1fPW1tE1tPW_01sE1s:} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-4.C b/gcc/testsuite/g++.dg/modules/sym-subst-4.C
new file mode 100644
index 0000000..d2266c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-4.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+export module zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun;
+// We're in cologne!
+// { dg-module-cmi zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW4zero4eins4zwei4drei4vier4funf5sechs6sieben4acht4neunE4frobRW_9E6mytype:} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-5.C b/gcc/testsuite/g++.dg/modules/sym-subst-5.C
new file mode 100644
index 0000000..1e26e75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-5.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+export module zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn;
+// We're in cologne!
+// { dg-module-cmi zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW4zero4eins4zwei4drei4vier4funf5sechs6sieben4acht4neun4zehnE4frobRWW0_E6mytype:} } }
diff --git a/gcc/testsuite/g++.dg/modules/sym-subst-6.C b/gcc/testsuite/g++.dg/modules/sym-subst-6.C
new file mode 100644
index 0000000..0a9ac6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sym-subst-6.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+export module zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn.elf;
+// We're in cologne!
+// { dg-module-cmi zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn.elf }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW4zero4eins4zwei4drei4vier4funf5sechs6sieben4acht4neun4zehn3elfE4frobRWW1_E6mytype:} } }
diff --git a/gcc/testsuite/g++.dg/modules/sys/alias-2_a.H b/gcc/testsuite/g++.dg/modules/sys/alias-2_a.H
new file mode 100644
index 0000000..5a05808
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sys/alias-2_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodule-header -isystem [srcdir]/sys" }
+// { dg-module-cmi {} }
+
+#ifndef ALIAS_2_A_SYS
+#define ALIAS_2_A_SYS
+
+int frob (int);
+
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/sys/inext-1.H b/gcc/testsuite/g++.dg/modules/sys/inext-1.H
new file mode 100644
index 0000000..1ecfe80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/sys/inext-1.H
@@ -0,0 +1,2 @@
+#define NEXT bob
+int foo ();
diff --git a/gcc/testsuite/g++.dg/modules/tdef-1_a.C b/gcc/testsuite/g++.dg/modules/tdef-1_a.C
new file mode 100644
index 0000000..6bec202
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-1_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module tdef;
+// { dg-module-cmi tdef }
+
+export struct A
+{
+ typedef int I;
+};
diff --git a/gcc/testsuite/g++.dg/modules/tdef-1_b.C b/gcc/testsuite/g++.dg/modules/tdef-1_b.C
new file mode 100644
index 0000000..627d672
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import tdef;
+
+A::I main ()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-2_a.C b/gcc/testsuite/g++.dg/modules/tdef-2_a.C
new file mode 100644
index 0000000..f7abf30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-2_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module tdef;
+// { dg-module-cmi tdef }
+
+export typedef int I;
+typedef int J;
+
diff --git a/gcc/testsuite/g++.dg/modules/tdef-2_b.C b/gcc/testsuite/g++.dg/modules/tdef-2_b.C
new file mode 100644
index 0000000..128e95e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-2_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module tdef;
+
+I yup;
+J yupper;
diff --git a/gcc/testsuite/g++.dg/modules/tdef-2_c.C b/gcc/testsuite/g++.dg/modules/tdef-2_c.C
new file mode 100644
index 0000000..387a41d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-2_c.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import tdef;
+
+I main ()
+{
+ return 0;
+}
+
+J nope; // { dg-error "does not name a type" }
+
+typedef char J;
+
+static J ok;
diff --git a/gcc/testsuite/g++.dg/modules/tdef-3_a.C b/gcc/testsuite/g++.dg/modules/tdef-3_a.C
new file mode 100644
index 0000000..8cc2276
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-3_a.C
@@ -0,0 +1,7 @@
+// { dg-module-do run }
+
+// { dg-additional-options -fmodules-ts }
+export module frob;
+// { dg-module-cmi frob }
+
+export typedef struct { int m; } frob;
diff --git a/gcc/testsuite/g++.dg/modules/tdef-3_b.C b/gcc/testsuite/g++.dg/modules/tdef-3_b.C
new file mode 100644
index 0000000..9980acf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-3_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+export module quux;
+// { dg-module-cmi quux }
+import frob;
+
+export int foo (frob *p)
+{
+ return p->m;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-3_c.C b/gcc/testsuite/g++.dg/modules/tdef-3_c.C
new file mode 100644
index 0000000..378415d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-3_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+
+import frob;
+import quux;
+
+int main ()
+{
+ frob f {2};
+
+ return !(foo (&f) == 2);
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-4_a.C b/gcc/testsuite/g++.dg/modules/tdef-4_a.C
new file mode 100644
index 0000000..6136b38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-4_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct pthread_attr_t
+// guess where this came from?
+{
+ int m;
+};
+typedef struct pthread_attr_t pthread_attr_t;
+
+struct bob
+{
+};
+export typedef struct bob bob;
diff --git a/gcc/testsuite/g++.dg/modules/tdef-4_b.C b/gcc/testsuite/g++.dg/modules/tdef-4_b.C
new file mode 100644
index 0000000..af488e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-4_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+pthread_attr_t obj1;
+struct pthread_attr_t obj2;
+
+bob obj3;
+struct bob obj4; // OK -- we see the implicit typedef
diff --git a/gcc/testsuite/g++.dg/modules/tdef-4_c.C b/gcc/testsuite/g++.dg/modules/tdef-4_c.C
new file mode 100644
index 0000000..a85a4d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-4_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+struct pthread_attr_t obj2;
+pthread_attr_t obj1; // OK -- we see the implicit typedef
+
+bob obj4;
+// the structure tag is not exported. We find the typedef-name, which
+// is ill-formed
+struct bob obj5; // { dg-error "using typedef-name" }
diff --git a/gcc/testsuite/g++.dg/modules/tdef-5_a.C b/gcc/testsuite/g++.dg/modules/tdef-5_a.C
new file mode 100644
index 0000000..4d23ae1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-5_a.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+typedef float _IO_lock_t;
+
+_IO_lock_t _lock;
diff --git a/gcc/testsuite/g++.dg/modules/tdef-5_b.C b/gcc/testsuite/g++.dg/modules/tdef-5_b.C
new file mode 100644
index 0000000..d37b7e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-5_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+_IO_lock_t bob ()
+{
+ return _lock;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-6_a.H b/gcc/testsuite/g++.dg/modules/tdef-6_a.H
new file mode 100644
index 0000000..aff5994
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-6_a.H
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef struct x
+{
+ int __count;
+} X;
+
+typedef struct
+{
+ int __count;
+} __mbstate_t;
diff --git a/gcc/testsuite/g++.dg/modules/tdef-6_b.C b/gcc/testsuite/g++.dg/modules/tdef-6_b.C
new file mode 100644
index 0000000..2d12a2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-6_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+typedef struct
+{
+ int __count;
+} __mbstate_t;
+
+typedef struct x
+{
+ int __count;
+} X;
+
+import "tdef-6_a.H";
+
+X y;
+__mbstate_t x;
+
+// { dg-final { scan-lang-dump {Read:-[0-9]'s named merge key \(matched\) type_decl:'::__mbstate_t'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tdef-7.h b/gcc/testsuite/g++.dg/modules/tdef-7.h
new file mode 100644
index 0000000..5bc21e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-7.h
@@ -0,0 +1,7 @@
+
+constexpr void duration_cast ()
+{
+ // the constexpr's body's clone merely duplicates the TYPE_DECL, it
+ // doesn't create a kosher typedef
+ typedef int __to_rep;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-7_a.H b/gcc/testsuite/g++.dg/modules/tdef-7_a.H
new file mode 100644
index 0000000..9c6db65
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-7_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tdef-7.h"
diff --git a/gcc/testsuite/g++.dg/modules/tdef-7_b.C b/gcc/testsuite/g++.dg/modules/tdef-7_b.C
new file mode 100644
index 0000000..c526ca8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-7_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias-uid" }
+
+#include "tdef-7.h"
+import "tdef-7_a.H";
+
+// { dg-final { scan-lang-dump-times {merge key \(matched\) function_decl:'::duration_cast} 1 module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-times {merge key \(unique\) type_decl:'#null#'} 2 module } }
+// { dg-final { scan-lang-dump-times {Cloned:-[0-9]* typedef integer_type:'::duration_cast::__to_rep'} 1 module } }
diff --git a/gcc/testsuite/g++.dg/modules/tdef-8_a.C b/gcc/testsuite/g++.dg/modules/tdef-8_a.C
new file mode 100644
index 0000000..3ad2094
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-8_a.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+// from tr1/type_traits
+export struct __sfinae_types
+{
+ // anon struct with tdef name
+ typedef struct { int i; } __two;
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/tdef-8_b.C b/gcc/testsuite/g++.dg/modules/tdef-8_b.C
new file mode 100644
index 0000000..2cf59d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-8_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+int frob (__sfinae_types::__two *p)
+{
+ return p->i;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-inst-1.h b/gcc/testsuite/g++.dg/modules/tdef-inst-1.h
new file mode 100644
index 0000000..757113c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-inst-1.h
@@ -0,0 +1,14 @@
+
+template <typename T>
+class basic_string;
+
+typedef basic_string<char> string;
+
+template <typename T>
+class basic_string
+{
+ public:
+ string Frob ();
+
+ basic_string (int);
+};
diff --git a/gcc/testsuite/g++.dg/modules/tdef-inst-1_a.C b/gcc/testsuite/g++.dg/modules/tdef-inst-1_a.C
new file mode 100644
index 0000000..ab302bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-inst-1_a.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+// The instantiation of the *definition* of basic_string is used in
+// importers, *after* they have instantiated a declaration of it *and*
+// created type variants.
+
+module;
+
+#include "tdef-inst-1.h"
+
+export module foo;
+// { dg-module-cmi foo }
+
+export inline int greeter (string const &bob)
+{
+ return sizeof (bob); // instantiates string
+}
diff --git a/gcc/testsuite/g++.dg/modules/tdef-inst-1_b.C b/gcc/testsuite/g++.dg/modules/tdef-inst-1_b.C
new file mode 100644
index 0000000..ccf7052
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tdef-inst-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+#include "tdef-inst-1.h"
+import foo;
+
+string Quux ()
+{
+ return 1; // failed to find converting ctor of string
+}
diff --git a/gcc/testsuite/g++.dg/modules/thunk-1_a.C b/gcc/testsuite/g++.dg/modules/thunk-1_a.C
new file mode 100644
index 0000000..7652400
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/thunk-1_a.C
@@ -0,0 +1,23 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct Base
+{
+ virtual ~Base () {}
+ int m;
+};
+
+// Force the creation of implicit members, because we get that wrong
+// in the importer and think its imported (as of 2018-11-27 this
+// causes an ICE, previously it happened to work in this particular
+// testcase.
+Base x;
+
+export struct Derived : virtual Base
+{
+ ~Derived () {}
+};
+
+Derived y;
diff --git a/gcc/testsuite/g++.dg/modules/thunk-1_b.C b/gcc/testsuite/g++.dg/modules/thunk-1_b.C
new file mode 100644
index 0000000..99eb029
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/thunk-1_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+export module baz;
+// { dg-module-cmi baz }
+
+import foo;
+
+export struct Container : virtual Derived
+{
+ Container () {}
+ ~Container () {}
+};
+
+
+
diff --git a/gcc/testsuite/g++.dg/modules/tmpl-part-req-1.h b/gcc/testsuite/g++.dg/modules/tmpl-part-req-1.h
new file mode 100644
index 0000000..09de429
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tmpl-part-req-1.h
@@ -0,0 +1,15 @@
+
+template<typename _Iterator, typename>
+struct Trait;
+
+template<typename _Iterator>
+struct Trait<_Iterator, void> {};
+
+template<typename _Iterator>
+requires true
+struct Trait<_Iterator, void>
+{
+ template<typename _Iter> struct __diff {};
+
+ template<typename _Iter> requires true struct __diff<_Iter> {};
+};
diff --git a/gcc/testsuite/g++.dg/modules/tmpl-part-req-1_a.H b/gcc/testsuite/g++.dg/modules/tmpl-part-req-1_a.H
new file mode 100644
index 0000000..20804d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tmpl-part-req-1_a.H
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodule-header -std=c++2a" }
+// { dg-module-cmi {} }
+#include "tmpl-part-req-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/tmpl-part-req-1_b.C b/gcc/testsuite/g++.dg/modules/tmpl-part-req-1_b.C
new file mode 100644
index 0000000..4c00d54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tmpl-part-req-1_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "tmpl-part-req-1.h"
+import "tmpl-part-req-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tmpl-part-req-2.h b/gcc/testsuite/g++.dg/modules/tmpl-part-req-2.h
new file mode 100644
index 0000000..0ca0593
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tmpl-part-req-2.h
@@ -0,0 +1,24 @@
+
+template<typename _Iterator, typename>
+struct Trait;
+
+template<typename _Iterator>
+struct Trait<_Iterator, void> {};
+
+template<typename _Iterator>
+requires true && true
+struct Trait<_Iterator, void>
+{
+ template<typename _Iter> struct __cat {};
+
+ template<typename _Iter> requires true struct __cat<_Iter> {};
+};
+
+template<typename _Iterator>
+requires true
+struct Trait<_Iterator, void>
+{
+ template<typename _Iter> struct __diff {};
+
+ template<typename _Iter> requires true struct __diff<_Iter> {};
+};
diff --git a/gcc/testsuite/g++.dg/modules/tmpl-part-req-2_a.H b/gcc/testsuite/g++.dg/modules/tmpl-part-req-2_a.H
new file mode 100644
index 0000000..66b97ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tmpl-part-req-2_a.H
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodule-header -std=c++2a" }
+// { dg-module-cmi {} }
+#include "tmpl-part-req-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/tmpl-part-req-2_b.C b/gcc/testsuite/g++.dg/modules/tmpl-part-req-2_b.C
new file mode 100644
index 0000000..1176f60
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tmpl-part-req-2_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "tmpl-part-req-2.h"
+import "tmpl-part-req-2_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/token-1.C b/gcc/testsuite/g++.dg/modules/token-1.C
new file mode 100644
index 0000000..50eee4c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/token-1.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+# 3 __FILE__ 1
+module ; // { dg-error "cannot be in included file" }
+export module bob; // { dg-error "cannot be in included file" }
+# 6 "" 2
+// { dg-module-cmi !bob }
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/token-2_a.C b/gcc/testsuite/g++.dg/modules/token-2_a.C
new file mode 100644
index 0000000..a1dfbf7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/token-2_a.C
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+# 1 "other_name"
+module ;
+export module bob;
+// { dg-module-cmi bob }
diff --git a/gcc/testsuite/g++.dg/modules/token-2_b.C b/gcc/testsuite/g++.dg/modules/token-2_b.C
new file mode 100644
index 0000000..52b7498
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/token-2_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodules-ts }
+#define SEMI ; // this is ok since p1857
+import bob SEMI
+#define IMPORT import // { dg-error "does not name a type" }
+IMPORT bob ;
diff --git a/gcc/testsuite/g++.dg/modules/token-3.C b/gcc/testsuite/g++.dg/modules/token-3.C
new file mode 100644
index 0000000..5bab426
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/token-3.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+# 3 __FILE__ 1
+export module bob; // { dg-error "in included file" }
+# 6 "" 2
+// { dg-module-cmi !bob }
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/token-4.C b/gcc/testsuite/g++.dg/modules/token-4.C
new file mode 100644
index 0000000..5a85237
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/token-4.C
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodules-ts }
+#define MODULE module // { dg-error "does not name a type" }
+export MODULE bob; // { dg-error "may only occur after" }
+// { dg-module-cmi !bob }
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/token-5.C b/gcc/testsuite/g++.dg/modules/token-5.C
new file mode 100644
index 0000000..29d3ec8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/token-5.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+module;
+
+class X; // { dg-error "global module fragment contents" }
+
+class Y;
+
+export module frob;
+// { dg-module-cmi !frob }
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-alias-1.h b/gcc/testsuite/g++.dg/modules/tpl-alias-1.h
new file mode 100644
index 0000000..00f2d9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-alias-1.h
@@ -0,0 +1,70 @@
+template<typename _Ptr> struct pointer_traits;
+
+template<typename _Tp>
+struct pointer_traits<_Tp*>
+{
+ template<typename _Up> using rebind = _Up*;
+};
+
+template<typename _Ptr, typename _Tp>
+using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
+
+template<typename _Tp>
+struct allocator
+{
+ typedef _Tp value_type;
+ typedef _Tp* pointer;
+};
+
+template<typename _Alloc> struct allocator_traits;
+
+template<typename _Tp>
+struct allocator_traits<allocator<_Tp>>
+{
+ using pointer = _Tp*;
+ template<typename _Up>
+ using rebind_alloc = allocator<_Up>;
+};
+
+template<typename _Alloc, typename = typename _Alloc::value_type>
+struct __alloc_traits
+ : allocator_traits<_Alloc>
+{
+ typedef _Alloc allocator_type;
+ typedef allocator_traits<_Alloc> _Base_type;
+ template<typename _Tp>
+ struct rebind
+ {
+ typedef typename _Base_type::template rebind_alloc<_Tp> other;
+ };
+};
+
+template<typename _Ref, typename _Ptr>
+struct _Deque_iterator
+{
+ template<typename _CvTp>
+ using __iter = _Deque_iterator<_CvTp&, __ptr_rebind<_Ptr, _CvTp>>;
+
+ typedef __ptr_rebind<_Ptr, long> _Elt_pointer;
+ typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer;
+};
+
+template<typename _Alloc>
+struct _Deque_base
+{
+ typedef typename __alloc_traits<_Alloc>::template rebind<long>::other _Tp_alloc_type;
+
+ typedef __alloc_traits<_Tp_alloc_type> _Alloc_traits;
+
+ typedef typename _Alloc_traits::pointer _Ptr;
+
+ typedef _Deque_iterator<long&, _Ptr> iterator;
+
+ typedef typename iterator::_Map_pointer _Map_pointer;
+};
+
+
+inline void stack ()
+{
+ _Deque_base<allocator<long>> c;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H
new file mode 100644
index 0000000..502a649
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias-uid" }
+// { dg-module-cmi {} }
+
+#include "tpl-alias-1.h"
+
+// { dg-final { scan-lang-dump {Writing named:-[0-9]* template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump {Writing decl spec:-[0-9]* type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump {Wrote\(-[0-9]*\) alias template type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C
new file mode 100644
index 0000000..59fd09c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-uid-alias" }
+
+#include "tpl-alias-1.h"
+import "tpl-alias-1_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(matched\) type_decl:'::allocator_traits<::allocator<_Tp>>::rebind_alloc'} module } }
+// { dg-final { scan-lang-dump {Read alias template type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-ary-1.h b/gcc/testsuite/g++.dg/modules/tpl-ary-1.h
new file mode 100644
index 0000000..2f745af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-ary-1.h
@@ -0,0 +1,15 @@
+
+int ary[4];
+extern int unb[];
+typedef int z[0];
+
+
+template<typename _Tp>
+struct __aligned_membuf
+{
+ unsigned char _M_storage[sizeof(_Tp)];
+ _Tp bob[5];
+
+ typedef _Tp ary[5];
+ typedef const ary c_ary;
+};
diff --git a/gcc/testsuite/g++.dg/modules/tpl-ary-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-ary-1_a.H
new file mode 100644
index 0000000..0534e93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-ary-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header -Wno-pedantic" }
+// { dg-module-cmi {} }
+
+#include "tpl-ary-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-ary-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-ary-1_b.C
new file mode 100644
index 0000000..c647580
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-ary-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "tpl-ary-1.h"
+import "tpl-ary-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H
new file mode 100644
index 0000000..f0aba54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_a.H
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline void Foo ()
+{
+ {
+ void Frob ();
+ }
+ {
+ void Frob ();
+ }
+ {
+ void Frob ();
+ }
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C
new file mode 100644
index 0000000..8b093d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-fn-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-extern-fn-1_a.H";
+
+int main ()
+{
+ Foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H
new file mode 100644
index 0000000..4a6437a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_a.H
@@ -0,0 +1,19 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline void Foo ()
+{
+ {
+ extern int EXTERN_;
+ EXTERN_++;
+ }
+ {
+ extern int EXTERN_;
+ EXTERN_++;
+ }
+ {
+ extern int EXTERN_;
+ EXTERN_++;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C
new file mode 100644
index 0000000..2224181
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-extern-var-1_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-extern-var-1_a.H";
+
+int main ()
+{
+ Foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-1_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-1_a.C
new file mode 100644
index 0000000..88bb6e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-1_a.C
@@ -0,0 +1,40 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+// declarations followed by friend injection
+
+export module foo;
+// { dg-module-cmi foo }
+
+void foo (int, void *);
+void foo (float, void *);
+
+template <typename T> class TPL
+{
+ friend void foo (T, void *); // { dg-warning "non-template function" }
+
+ T member;
+};
+
+template class TPL<float>; // instantiate
+
+// binding->465500
+// FUNCTION_DECL->465500
+// DECL_TEMPLATE_INFO->NULL
+// DECL_USE_TEMPLATE->0
+
+// specialization 465500
+// tmpl->333580 template_decl
+// the friend decl implicit template
+
+// args->46b640 tree_vec
+// length:1
+// elt:0 real_type
+
+// do not add this (non-)specialization to the depset table
+// the ::foo fns and TPL should be in different depsets
+// the friend decl should be streamed as part of TPL's definition
+
+// { dg-final { scan-lang-dump-not {Connecting declaration decl template_decl:'::foo'} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::foo'\n \[1\]=decl declaration '::foo'\n \[2\]=binding '::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template TPL'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::TPL'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::TPL<float>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-1_b.C
new file mode 100644
index 0000000..e4c42d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-1_b.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void foo (int x, void *p)
+{
+ auto *obj = reinterpret_cast<TPL<int> *> (p);
+
+ obj->member = x;
+}
+
+void foo (float x, void *p)
+{
+ auto *obj = reinterpret_cast<TPL<float> *> (p);
+
+ obj->member = x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C
new file mode 100644
index 0000000..3acacf8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C
@@ -0,0 +1,20 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+// injection followed by declaration
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T> class TPL
+{
+ friend void foo (T, void *); // { dg-warning "non-template function" }
+
+ T member;
+};
+
+template class TPL<int>; // instantiate
+
+void foo (int, void *);
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template TPL'\n( \[.\]=[^\n]*'\n)* \[.\]=decl declaration '::template foo'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::TPL'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::foo<int>'\n \[.\]=binding '::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::TPL<int>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-2_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-2_b.C
new file mode 100644
index 0000000..38d89f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-2_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+void foo (int x, void *p)
+{
+ auto *obj = reinterpret_cast<TPL<int> *> (p);
+
+ obj->member = x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-3_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-3_a.C
new file mode 100644
index 0000000..e71a258
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-3_a.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts" }
+// declarations followed by friend definition injection
+
+export module foo;
+// { dg-module-cmi foo }
+
+void foo (int, void *);
+void foo (float, void *);
+
+template <typename T> class TPL
+{
+ friend void foo (T x, void *p)
+ {
+ auto *obj = reinterpret_cast<TPL<T> *> (p);
+
+ obj->member = x;
+ }
+
+ T member;
+};
+
+template class TPL<float>; // instantiate
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-3_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-3_b.C
new file mode 100644
index 0000000..accf5d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-3_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+template class TPL<int>;
+// (instantiated in interface) template class TPL<float>;
+
+void m ()
+{
+ // friend definitions instantiated on-demand here
+ foo (1, 0);
+ foo (1.0f, 0);
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-4_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-4_a.C
new file mode 100644
index 0000000..8acf5b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-4_a.C
@@ -0,0 +1,25 @@
+// { dg-additional-options "-fmodules-ts" }
+// friend injection then definition injection
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T> class TPL
+{
+ friend void foo (T, void *); // { dg-warning "non-template function" }
+
+ T member;
+};
+
+template <typename U> class DEF
+{
+ friend void foo (U x, void *p)
+ {
+ auto *obj = reinterpret_cast<TPL<U> *> (p);
+
+ obj->member = x;
+ }
+};
+
+template class TPL<float>; // instantiate
+template class DEF<float>; // instantiate
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-4_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-4_b.C
new file mode 100644
index 0000000..3dd8741
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-4_b.C
@@ -0,0 +1,21 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+template class TPL<int>;
+template class DEF<int>;
+
+void m ()
+{
+ // ADL to find hidden functions
+ foo (1, (TPL<int> *)0);
+ foo (1.0f, (TPL<int> *)0);
+
+ // no ADL, no find
+ {
+ foo (1, 0); // { dg-error "not declared" }
+ }
+ {
+ foo (1.0f, 0); // { dg-error "not declared" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-5_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-5_a.C
new file mode 100644
index 0000000..e894c73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-5_a.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _CharT> class basic_ios;
+
+template<typename _CharT>
+class basic_streambuf
+{
+ friend class basic_ios<_CharT>;
+
+ _CharT member;
+};
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-5_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-5_b.C
new file mode 100644
index 0000000..adbe85d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-5_b.C
@@ -0,0 +1,23 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module foo;
+
+template class basic_streambuf<char>;
+
+template<typename _CharT> class basic_ios
+{
+public:
+ static void frob (basic_streambuf<_CharT> *p, _CharT val)
+ {
+ p->member = val;
+ }
+};
+
+void bill (basic_streambuf<char> *p)
+{
+ basic_ios<char>::frob (p, 5);
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::basic_streambuf'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Loading entity foo\[0\] section:1} module } }
+// { dg-final { scan-lang-dump {Loading entity foo\[1\] section:2} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-6_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-6_a.C
new file mode 100644
index 0000000..cc07c60
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-6_a.C
@@ -0,0 +1,26 @@
+// { dg-additional-options -fmodules-ts }
+// befriending a specialization
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace not_std {
+
+template<typename T>
+class basic_streambuf;
+
+template<typename T>
+void __copy_streambufs_eof(basic_streambuf<T>*);
+
+template<typename T>
+class basic_streambuf
+{
+ friend void __copy_streambufs_eof<>(basic_streambuf*);
+
+ T member;
+};
+
+template<>
+void
+__copy_streambufs_eof(basic_streambuf<char>* __sbin);
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-6_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-6_b.C
new file mode 100644
index 0000000..942fe70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-6_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+namespace not_std {
+
+template<>
+void
+__copy_streambufs_eof(basic_streambuf<char>* __sbin)
+{
+ __sbin->member = 0;
+}
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-7_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-7_a.C
new file mode 100644
index 0000000..bf13cf7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-7_a.C
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp>
+class new_allocator
+{
+ template<typename _Up>
+ friend bool
+ operator!=(const new_allocator&, const new_allocator<_Up>&)
+ noexcept
+ { return false; }
+};
+
+new_allocator<char> x;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-7_b.C b/gcc/testsuite/g++.dg/modules/tpl-friend-7_b.C
new file mode 100644
index 0000000..e6e4461
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-7_b.C
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+new_allocator<char> y;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.cc b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.cc
new file mode 100644
index 0000000..a4a1d21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.cc
@@ -0,0 +1,6 @@
+void __istream_extract (int)
+{
+ (void)basic_streambuf<char>::field;
+ (void)basic_streambuf<int>::field;
+ (void)basic_streambuf<long>::field;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.h b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.h
new file mode 100644
index 0000000..fd45536
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1.h
@@ -0,0 +1,9 @@
+
+template<typename T>
+class basic_streambuf
+{
+ friend void __istream_extract (int);
+
+ // something private
+ static constexpr int field = 5;
+};
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_a.H
new file mode 100644
index 0000000..566b860
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options {-fmodule-header -W} }
+
+// { dg-module-cmi {} }
+
+#include "tpl-friend-merge-1.h"
+extern template class basic_streambuf<char>;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_b.H b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_b.H
new file mode 100644
index 0000000..b35d8e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_b.H
@@ -0,0 +1,6 @@
+// { dg-additional-options {-fmodule-header -W} }
+
+// { dg-module-cmi {} }
+
+#include "tpl-friend-merge-1.h"
+extern template class basic_streambuf<int>;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_c.H b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_c.H
new file mode 100644
index 0000000..197b831
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_c.H
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+
+void __istream_extract (int);
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_d.C b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_d.C
new file mode 100644
index 0000000..e6f46ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_d.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "tpl-friend-merge-1_a.H";
+import "tpl-friend-merge-1_b.H";
+import "tpl-friend-merge-1_c.H";
+
+#include "tpl-friend-merge-1.cc"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_e.C b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_e.C
new file mode 100644
index 0000000..185242b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_e.C
@@ -0,0 +1,7 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -fdump-lang-module-alias} }
+
+import "tpl-friend-merge-1_a.H";
+import "tpl-friend-merge-1_c.H";
+import "tpl-friend-merge-1_b.H";
+
+#include "tpl-friend-merge-1.cc"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_f.C b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_f.C
new file mode 100644
index 0000000..4ec7cde
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-merge-1_f.C
@@ -0,0 +1,7 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -fdump-lang-module-alias} }
+
+import "tpl-friend-merge-1_c.H";
+import "tpl-friend-merge-1_a.H";
+import "tpl-friend-merge-1_b.H";
+
+#include "tpl-friend-merge-1.cc"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-1_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-1_a.C
new file mode 100644
index 0000000..26350f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-1_a.C
@@ -0,0 +1,22 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T> int foo (T x)
+{
+ return int (x);
+}
+
+// Body is emitted in module-unit itself
+template <> int foo<int> (int y)
+{
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Dependencies of specialization function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump-not {Depending definition function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization declaration '::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::foo<int>' entity:[0-9]* keyed to TPL\[0\] '::template foo'} module } }
+
+// { dg-final { scan-assembler {_Z3fooIiEiT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-1_b.C
new file mode 100644
index 0000000..1f64fbb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-1_b.C
@@ -0,0 +1,20 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import TPL;
+
+int main ()
+{
+ if (foo (1.0f) != 1)
+ return 1;
+
+ if (foo (1) != 0)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::foo@TPL:.<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization keyed to TPL\[0\] entity:1} module } }
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template foo@TPL:1'} module } }
+
+// { dg-final { scan-assembler-not {_Z3fooIiEiT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-2_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-2_a.C
new file mode 100644
index 0000000..bb136d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-2_a.C
@@ -0,0 +1,11 @@
+// { dg-additional-options {-fmodules-ts} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T> int foo (T x)
+{
+ return int (x);
+}
+
+// { dg-final { scan-assembler-not {^[a-zA-Z0-9_]*:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-2_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-2_b.C
new file mode 100644
index 0000000..d137481
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-2_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module SPEC;
+
+export import TPL;
+
+// Body is emitted in module-unit itself
+template <> int foo<int> (int y)
+{
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Dependencies of specialization function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump-not {Depending definition function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization declaration '::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::foo<int>' entity:[0-9]* keyed to TPL\[.\] '::template foo@TPL:.'} module } }
+
+// { dg-final { scan-assembler {_Z3fooIiEiT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-2_c.C b/gcc/testsuite/g++.dg/modules/tpl-spec-2_c.C
new file mode 100644
index 0000000..3b0a7c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-2_c.C
@@ -0,0 +1,19 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import SPEC;
+
+int main ()
+{
+ if (foo (1.0f) != 1)
+ return 1;
+
+ if (foo (1) != 0)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template foo@TPL:.'} module } }
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::foo@TPL:.<int>'} module } }
+
+// { dg-final { scan-assembler-not {_Z3fooIiEiT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-2_d.C b/gcc/testsuite/g++.dg/modules/tpl-spec-2_d.C
new file mode 100644
index 0000000..4095dea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-2_d.C
@@ -0,0 +1,27 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import TPL;
+
+int one ()
+{
+ if (foo (1.0f) != 1)
+ return 1;
+ return 0;
+}
+
+
+import SPEC;
+
+int two ()
+{
+ if (foo (1) != 0)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template foo@TPL:.'} module } }
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::foo@TPL:.<int>'} module } }
+
+// { dg-final { scan-assembler-not {_Z3fooIiEiT_:} } }
+// { dg-final { scan-assembler {_Z3fooIfEiT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-3_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-3_a.C
new file mode 100644
index 0000000..1f3fb40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-3_a.C
@@ -0,0 +1,27 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export struct frob
+{
+ int i;
+
+ template<typename T> void store (T i_)
+ {
+ i = int (i_);
+ }
+};
+
+// Not inline!
+template <> void frob::store (int i_)
+{
+ i = -i_;
+}
+
+// { dg-final { scan-lang-dump {Dependencies of specialization function_decl:'::frob::store<int>'} module } }
+// { dg-final { scan-lang-dump-not {Depending definition function_decl:'::frob::store<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization declaration '::frob::store<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::frob::store<int>' entity:[0-9]* keyed to TPL\[1\] '::frob::template store'} module } }
+
+// { dg-final { scan-assembler {_ZN4frob5storeIiEEvT_:} } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-3_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-3_b.C
new file mode 100644
index 0000000..a9cd8d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-3_b.C
@@ -0,0 +1,24 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import TPL;
+
+int main ()
+{
+ frob f;
+
+ f.store (1);
+ if (f.i != -1)
+ return 1;
+
+ f.store (1.0f);
+ if (f.i != 1)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[1\] '::frob@TPL:.::template store@TPL:.'} module } }
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::frob@TPL:.::store@TPL:.<int>'} module } }
+
+// { dg-final { scan-assembler-not {_ZN4frob5storeIiEEvT_:} } }
+
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-4_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-4_a.C
new file mode 100644
index 0000000..29e09de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-4_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T>
+struct X
+{
+ T f;
+};
+
+template<> struct X<int>
+{
+ int m;
+};
+
+// { dg-final { scan-lang-dump {Dependencies of specialization type_decl:'::X<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n( \[.\]=[^\n]*'\n)* \[.\]=specialization definition '::X<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::X<int>' entity:[0-9]* keyed to TPL\[0\] '::template X'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-4_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-4_b.C
new file mode 100644
index 0000000..94ced9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-4_b.C
@@ -0,0 +1,17 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+import TPL;
+
+int main ()
+{
+ X<int> q;
+
+ q.m = 5;
+
+ X<float> p;
+ p.f = 4.0f;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template X@TPL:.'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-5_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-5_a.C
new file mode 100644
index 0000000..08bcac2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-5_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T, int I>
+struct X
+{
+ T ary[I];
+};
+
+template<typename T> struct X<T,1>
+{
+ T scalar;
+};
+
+// { dg-final { scan-lang-dump {Dependency on partial template_decl:'::template X<T,0x1>' found} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n( \[.\][^\n]*'\n)* \[.\]=partial definition '::template X<T,0x1>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::template X<T,0x1>' entity:[0-9]* keyed to TPL\[0\] '::template X'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-5_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-5_b.C
new file mode 100644
index 0000000..8a1a557
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-5_b.C
@@ -0,0 +1,17 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+
+import TPL;
+
+int main ()
+{
+ X<int,2> q;
+
+ q.ary[0] = 5;
+
+ X<float,1> p;
+ p.scalar = 4.0f;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template X@TPL:.'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-6_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-6_a.C
new file mode 100644
index 0000000..111c718
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-6_a.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant;
+
+template<typename _From, typename _To, bool>
+struct __is_nt_convertible_helper;
+
+template<typename _From, typename _To>
+class __is_nt_convertible_helper<_From, _To, false>
+{
+ template<typename _To1>
+ static void __test_aux(_To1) noexcept;
+
+ template<typename _From1, typename _To1>
+ static
+ integral_constant<bool, noexcept(__test_aux<_To1> (_From1 ()))>
+ __test(int);
+};
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-6_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-6_b.C
new file mode 100644
index 0000000..3a11428
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-6_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module foo;
+
+__is_nt_convertible_helper<int, int, false> ok;
+__is_nt_convertible_helper<int, int, true> not_ok; // { dg-error "incomplete" }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-7.C b/gcc/testsuite/g++.dg/modules/tpl-spec-7.C
new file mode 100644
index 0000000..71f821d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-spec-7.C
@@ -0,0 +1,38 @@
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+typedef unsigned long size_t;
+
+template<typename _Tp, bool _IsInt, bool _IsEnum>
+class __make_unsigned_selector;
+
+class __make_unsigned_selector_base
+{
+protected:
+ template<typename...> struct _List { };
+
+ template<typename _Tp, typename... _Up>
+ struct _List<_Tp, _Up...> : _List<_Up...>
+ { static constexpr size_t __size = sizeof(_Tp); };
+
+ template<size_t _Sz, typename _Tp, bool = (_Sz <= _Tp::__size)>
+ struct __select;
+};
+
+template<typename _Tp>
+class __make_unsigned_selector<_Tp, false, true>
+ : __make_unsigned_selector_base
+{
+ using _UInts = _List<unsigned char, unsigned short, unsigned int,
+ unsigned long, unsigned long long>;
+
+ using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type;
+};
+
+
+
+
+
+
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_a.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_a.C
new file mode 100644
index 0000000..23ebfde
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_a.C
@@ -0,0 +1,15 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T> class TPL
+{
+ template <typename U> friend void foo (U);
+};
+
+template class TPL<char>;
+
+template <typename V> void foo (V x)
+{
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_b.C
new file mode 100644
index 0000000..276a7d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-friend-1_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void m ()
+{
+ foo ('a');
+ foo (0);
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_a.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_a.C
new file mode 100644
index 0000000..2d58465
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T>
+class outer
+{
+public:
+ template <typename U>
+ struct inner
+ {
+ typedef outer<U> other;
+ };
+
+ using type = T;
+};
+
+template class outer<int>;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_b.C
new file mode 100644
index 0000000..3e90ac8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-mem-1_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+static_assert (sizeof (outer<int>::inner<char>::other::type) == 1);
+static_assert (sizeof (outer<char>::inner<int>::other::type) == sizeof (int));
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1.h b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1.h
new file mode 100644
index 0000000..71ee192
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1.h
@@ -0,0 +1,22 @@
+typedef long unsigned int size_t;
+
+template<typename _Tp, typename _Up>
+struct Replace;
+
+template<template<typename> class _Template>
+struct Replace<_Template<char>, char>
+{
+ using type = _Template<char>;
+};
+
+template<typename _Tp>
+struct TPL;
+
+template<typename _Alloc>
+struct Traits
+{
+ template<typename _Tp>
+ using Rebind = typename Replace<_Alloc, _Tp>::type;
+};
+
+using tdef = Traits<TPL<char>>::template Rebind<char>;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_a.H
new file mode 100644
index 0000000..ccd4508
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tpl-tpl-merge-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_b.C
new file mode 100644
index 0000000..d953ec3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "tpl-tpl-merge-1.h"
+import "tpl-tpl-merge-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2.h b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2.h
new file mode 100644
index 0000000..005523e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2.h
@@ -0,0 +1,65 @@
+typedef long unsigned int size_t;
+
+template<typename> class allocator;
+
+template<typename _Tp, typename _Up>
+struct __replace_first_arg
+{ };
+
+template<template<typename, typename...> class _Template, typename _Up,
+ typename _Tp, typename... _Types>
+struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
+{
+ using type = _Template<_Up, _Types...>;
+};
+
+template<typename _Tp, typename _Up>
+using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type;
+
+template<typename _Tp>
+class new_allocator
+{
+public:
+ typedef _Tp value_type;
+};
+
+template<typename _Tp>
+using __allocator_base = new_allocator<_Tp>;
+
+template<typename _Tp>
+class allocator : public __allocator_base<_Tp>
+{
+public:
+};
+
+struct __allocator_traits_base
+{
+ template<typename _Tp, typename _Up, typename = void>
+ struct __rebind : __replace_first_arg<_Tp, _Up> { };
+};
+
+template<typename _Alloc, typename _Up>
+using __alloc_rebind
+= typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
+
+template<typename _Alloc>
+struct allocator_traits : __allocator_traits_base
+{
+public:
+ template<typename _Tp>
+ using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
+};
+
+template<typename _Alloc, typename = typename _Alloc::value_type>
+struct __alloc_traits
+
+{
+ template<typename _Tp>
+ struct rebind
+ {
+ typedef typename allocator_traits<_Alloc>::template rebind_alloc<_Tp> other;
+ };
+};
+
+typedef typename __alloc_traits<allocator<char>>::template
+rebind<char>::other _Char_alloc_type;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_a.H b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_a.H
new file mode 100644
index 0000000..051c19b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tpl-tpl-merge-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_b.C
new file mode 100644
index 0000000..54da419
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-merge-2_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "tpl-tpl-merge-2.h"
+import "tpl-tpl-merge-2_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_a.H b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_a.H
new file mode 100644
index 0000000..159efc3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_a.H
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<template<typename> class _TQual>
+struct basic_common_reference;
+
+template<typename _Tp>
+struct __xref;
+
+template<typename _Tp1>
+using __basic_common_ref
+= typename basic_common_reference<__xref<_Tp1>::template __type>::type;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_b.C
new file mode 100644
index 0000000..c8918d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-1_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-tpl-parm-1_a.H";
+
+template<> struct __xref<int>
+{
+ template <typename T> struct __type;
+};
+
+template<> struct basic_common_reference<__xref<int>::__type>
+{
+ typedef int type;
+};
+
+__basic_common_ref<int> main ()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2.h b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2.h
new file mode 100644
index 0000000..16832bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2.h
@@ -0,0 +1,16 @@
+
+
+
+template<typename _Alloc>
+struct allocator_traits
+{
+ template<template<typename> class _Func>
+ struct _Ptr {};
+
+ using rebind_alloc = int;
+};
+
+inline void frob ()
+{
+ allocator_traits<int> _M_unpooled;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_a.H b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_a.H
new file mode 100644
index 0000000..cec1a67
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tpl-tpl-parm-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_b.C b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_b.C
new file mode 100644
index 0000000..3504e50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-2_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "tpl-tpl-parm-2.h"
+import "tpl-tpl-parm-2_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/tplmem-1_a.C b/gcc/testsuite/g++.dg/modules/tplmem-1_a.C
new file mode 100644
index 0000000..97e228a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tplmem-1_a.C
@@ -0,0 +1,32 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi "frob" }
+
+export struct A
+{
+ A ()
+ {
+ }
+
+ template<typename T> operator T () const
+ {
+ return T(99);
+ }
+};
+
+export template<typename T> struct B
+{
+ T m;
+
+ B(T t) : m(t)
+ {
+ }
+
+ template<typename S> operator S () const
+ {
+ return S (m);
+ }
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/tplmem-1_b.C b/gcc/testsuite/g++.dg/modules/tplmem-1_b.C
new file mode 100644
index 0000000..352ad0c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tplmem-1_b.C
@@ -0,0 +1,28 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+int main ()
+{
+ A a;
+
+ if (int (a) != 99)
+ return 1;
+ if (float (a) != 99)
+ return 2;
+ if (static_cast <void *> (a) != (void *)99)
+ return 3;
+
+ B<int> bi(1);
+ B<float> bf(1.25f);
+ if (int (bi) != 1)
+ return 4;
+ if (int (bf) != 1)
+ return 5;
+
+ // 1.25 is exactly representable
+ if (float (bf) != 1.25f)
+ return 6;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/tplmem-3_a.C b/gcc/testsuite/g++.dg/modules/tplmem-3_a.C
new file mode 100644
index 0000000..9d9cc0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tplmem-3_a.C
@@ -0,0 +1,17 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module billy.bob.thornton;
+// { dg-module-cmi "billy.bob.thornton" }
+
+export template<unsigned I> struct Outer
+{
+ template<unsigned J> struct Inner
+ {
+ static unsigned m ()
+ {
+ return I * J;
+ }
+ };
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/tplmem-3_b.C b/gcc/testsuite/g++.dg/modules/tplmem-3_b.C
new file mode 100644
index 0000000..c5225ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tplmem-3_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import billy.bob.thornton;
+
+int main ()
+{
+ Outer<4>::Inner<16> v;
+
+ if (v.m () != 64)
+ return 1;
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/ttp-1_a.C b/gcc/testsuite/g++.dg/modules/ttp-1_a.C
new file mode 100644
index 0000000..eb2d939
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ttp-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+export module bob;
+
+export template<template<typename> class TPL, typename T>
+struct Wrapper
+{
+ using type = TPL<T>;
+};
diff --git a/gcc/testsuite/g++.dg/modules/ttp-1_b.C b/gcc/testsuite/g++.dg/modules/ttp-1_b.C
new file mode 100644
index 0000000..30a73c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ttp-1_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+template<typename T> struct X
+{
+ using type = T;
+};
+
+template<typename X, typename Y> struct same;
+template<typename X> struct same<X, X> {};
+
+void frob ()
+{
+ using type = Wrapper<X, int>::type::type;
+
+ same<type, int> v;
+}
diff --git a/gcc/testsuite/g++.dg/modules/ttp-2_a.C b/gcc/testsuite/g++.dg/modules/ttp-2_a.C
new file mode 100644
index 0000000..c14aeea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ttp-2_a.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<template<typename...> class Arg1>
+struct TPL1;
+
+template<template<typename...> class Arg2>
+struct TPL2;
diff --git a/gcc/testsuite/g++.dg/modules/ttp-2_b.C b/gcc/testsuite/g++.dg/modules/ttp-2_b.C
new file mode 100644
index 0000000..bf0242a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ttp-2_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+template <template<typename ...> class Arg4>
+struct TPL1
+{
+};
+
+template <template<typename ...> class Arg4>
+struct TPL2
+{
+};
+
+template <typename> class Arg;
+
+
+template struct TPL1<Arg>;
diff --git a/gcc/testsuite/g++.dg/modules/ttp-3_a.C b/gcc/testsuite/g++.dg/modules/ttp-3_a.C
new file mode 100644
index 0000000..d1f5857
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ttp-3_a.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename Arg1, template<typename> typename Arg2>
+struct TPL
+{
+ using type = char;
+};
+
+/// Implementation of the detection idiom (positive case).
+template<template<typename> typename Op>
+struct TPL <Op<int>, Op>
+{
+ using type = int;
+};
diff --git a/gcc/testsuite/g++.dg/modules/ttp-3_b.C b/gcc/testsuite/g++.dg/modules/ttp-3_b.C
new file mode 100644
index 0000000..7f61b7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ttp-3_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+
+template <typename> class Y;
+
+static_assert (sizeof (TPL<Y<char>, Y>::type) == 1);
+static_assert (sizeof (TPL<Y<int>, Y>::type) != 1, "where's my specialization?");
diff --git a/gcc/testsuite/g++.dg/modules/typename-1_a.C b/gcc/testsuite/g++.dg/modules/typename-1_a.C
new file mode 100644
index 0000000..e8b5599
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/typename-1_a.C
@@ -0,0 +1,13 @@
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template <typename T>
+struct TPL
+{
+ typename T::type m;
+ using type = typename T::type;
+ const type cm;
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/typename-1_b.C b/gcc/testsuite/g++.dg/modules/typename-1_b.C
new file mode 100644
index 0000000..ba7aecf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/typename-1_b.C
@@ -0,0 +1,15 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct X
+{
+ using type = int;
+};
+
+int main ()
+{
+ TPL<X> x {0,1};
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/unnamed-1_a.C b/gcc/testsuite/g++.dg/modules/unnamed-1_a.C
new file mode 100644
index 0000000..8c5674a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/unnamed-1_a.C
@@ -0,0 +1,20 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module PiL;
+// { dg-module-cmi PiL }
+
+int counter = 0;
+
+export inline int get ()
+{
+ return counter++;
+}
+
+export inline int hwm ()
+{
+ return counter;
+}
+
+// { dg-final { scan-lang-dump {Bindings '::counter' section:1} module } }
+// { dg-final { scan-lang-dump-not {horcrux} module } }
+// { dg-final { scan-lang-dump-not {Unnamed . '::counter'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/unnamed-1_b.C b/gcc/testsuite/g++.dg/modules/unnamed-1_b.C
new file mode 100644
index 0000000..847ced6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/unnamed-1_b.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import PiL;
+
+// Until the linkage is promoted, this won't link.
+
+int main ()
+{
+ int i = get ();
+ if (i)
+ return 1;
+ int h = hwm ();
+ if (h != 1)
+ return 2;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Bindings '::counter'} module } }
+// { dg-final { scan-lang-dump {>Loading entity PiL\[0\] section:1} module } }
diff --git a/gcc/testsuite/g++.dg/modules/unnamed-2.C b/gcc/testsuite/g++.dg/modules/unnamed-2.C
new file mode 100644
index 0000000..2b58930
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/unnamed-2.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+export module PiL;
+// { dg-module-cmi PiL }
+
+static int counter = 0;
+
+// These are not inlined, so their bodies don't get into the BMI
+export int get ()
+{
+ return counter++;
+}
+
+export int hwm ()
+{
+ return counter;
+}
+
+// { dg-final { scan-lang-dump-not {Bindings '::counter' section:} module } }
+// { dg-final { scan-lang-dump-not {Unnamed . '::counter'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/used-1_a.H b/gcc/testsuite/g++.dg/modules/used-1_a.H
new file mode 100644
index 0000000..39aacf5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/used-1_a.H
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+inline int frob (int x)
+{
+ return x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/used-1_b.H b/gcc/testsuite/g++.dg/modules/used-1_b.H
new file mode 100644
index 0000000..05f29db
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/used-1_b.H
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+import "used-1_a.H";
+
+inline int wrapper (int x)
+{
+ return frob (x);
+}
diff --git a/gcc/testsuite/g++.dg/modules/used-1_c.C b/gcc/testsuite/g++.dg/modules/used-1_c.C
new file mode 100644
index 0000000..0d1514e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/used-1_c.C
@@ -0,0 +1,10 @@
+// { dg-additional-options -fmodules-ts }
+
+import "used-1_b.H";
+
+int main ()
+{
+ return wrapper (0);
+}
+
+// { dg-final { scan-assembler {_Z4frobi:} } }
diff --git a/gcc/testsuite/g++.dg/modules/using-1_a.C b/gcc/testsuite/g++.dg/modules/using-1_a.C
new file mode 100644
index 0000000..010c7fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-1_a.C
@@ -0,0 +1,19 @@
+// { dg-module-do link }
+// { dg-additional-options "-fmodules-ts" }
+export module frob;
+// { dg-module-cmi frob }
+
+namespace details
+{
+void foo ()
+{
+}
+}
+
+using details::foo;
+void footle ();
+export void bink ()
+{
+ foo ();
+ footle ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/using-1_b.C b/gcc/testsuite/g++.dg/modules/using-1_b.C
new file mode 100644
index 0000000..e36caaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-1_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodules-ts }
+module frob;
+
+void footle ()
+{
+ foo ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/using-1_c.C b/gcc/testsuite/g++.dg/modules/using-1_c.C
new file mode 100644
index 0000000..d9835bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-1_c.C
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+
+import frob;
+
+int main ()
+{
+ bink ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/using-2_a.C b/gcc/testsuite/g++.dg/modules/using-2_a.C
new file mode 100644
index 0000000..ef6f5e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-2_a.C
@@ -0,0 +1,19 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace N {
+export int foo (int a)
+{
+ return -a;
+}
+int bar (int a)
+{
+ return -a;
+}
+}
+
+export using N::foo;
+using N::bar;
+
diff --git a/gcc/testsuite/g++.dg/modules/using-2_b.C b/gcc/testsuite/g++.dg/modules/using-2_b.C
new file mode 100644
index 0000000..6181073
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-2_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options -fmodules-ts }
+
+module bob;
+
+int a = foo (1);
+int b = bar (2);
diff --git a/gcc/testsuite/g++.dg/modules/using-2_c.C b/gcc/testsuite/g++.dg/modules/using-2_c.C
new file mode 100644
index 0000000..c3c0670
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-2_c.C
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodules-ts }
+import bob;
+
+int a = foo (1);
diff --git a/gcc/testsuite/g++.dg/modules/using-3.C b/gcc/testsuite/g++.dg/modules/using-3.C
new file mode 100644
index 0000000..d21512f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-3.C
@@ -0,0 +1,17 @@
+// { dg-additional-options -fmodules-ts }
+export module bad;
+// { dg-module-cmi !bad }
+
+namespace N
+{
+static int foo ();
+int bar ();
+}
+
+using N::foo;
+using N::bar;
+
+export using N::foo; // { dg-error "does not have external linkage" }
+export using N::bar; // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/using-4_a.C b/gcc/testsuite/g++.dg/modules/using-4_a.C
new file mode 100644
index 0000000..1eba527
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-4_a.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace N {
+export int foo ();
+}
+
+// Only one using decl exported!
+using N::foo;
+export using N::foo;
+
+// { dg-final { scan-lang-dump {Writing section:2 2 depsets} module } }
+// { dg-final { scan-lang-dump {Depset:0 using overload:'::N::foo'} module } }
+// { dg-final { scan-lang-dump {Depset:1 binding namespace_decl:'::foo'} module } }
+
diff --git a/gcc/testsuite/g++.dg/modules/using-4_b.C b/gcc/testsuite/g++.dg/modules/using-4_b.C
new file mode 100644
index 0000000..f899f50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-4_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+import bob;
+
+int a = foo ();
+
+// { dg-final { scan-lang-dump {Binding of '::foo'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/using-5_a.C b/gcc/testsuite/g++.dg/modules/using-5_a.C
new file mode 100644
index 0000000..88cbaf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-5_a.C
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module foo;
+// { dg-module-cmi foo }
+
+namespace One {
+class X;
+}
+
+namespace Two {
+using One::X;
+}
+
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::One::X'\n \[1\]=binding '::One::X'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=using declaration '::One::X'\n \[1\]=binding '::Two::X'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/using-5_b.C b/gcc/testsuite/g++.dg/modules/using-5_b.C
new file mode 100644
index 0000000..9fbe14e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-5_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+module foo;
+
+Two::X *p;
diff --git a/gcc/testsuite/g++.dg/modules/using-6_a.C b/gcc/testsuite/g++.dg/modules/using-6_a.C
new file mode 100644
index 0000000..40c32b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-6_a.C
@@ -0,0 +1,20 @@
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace A
+{
+export void swap (int &, int &);
+void copy (int &);
+}
+
+export template <typename T>
+void Foo (T & a, T &b)
+{
+ using A::swap;
+ swap (a, b);
+
+ using A::copy;
+ copy (b);
+}
diff --git a/gcc/testsuite/g++.dg/modules/using-6_b.C b/gcc/testsuite/g++.dg/modules/using-6_b.C
new file mode 100644
index 0000000..feac0ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-6_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+import bob;
+
+int main ()
+{
+ int a = 0, b = 1;
+ Foo (a, b);
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/using-7.C b/gcc/testsuite/g++.dg/modules/using-7.C
new file mode 100644
index 0000000..01a5ad3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-7.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export namespace __gnu_cxx
+{
+enum _Lock_policy { _S_single};
+}
+
+export namespace std
+{
+ using __gnu_cxx::_S_single;
+}
+
+// { dg-final { scan-lang-dump {Writing section:1 4 depsets\n Cluster members:\n \[0\]=decl definition '::__gnu_cxx::_Lock_policy'\n \[1\]=using declaration '::__gnu_cxx::_Lock_policy::_S_single'\n \[2\]=binding '::__gnu_cxx::_[A-Za-z_]*'\n \[3\]=binding '::__gnu_cxx::_[A-Za-z_]*'\n} module } }
+// { dg-final { scan-lang-dump {Writing section:2 2 depsets\n Cluster members:\n \[0\]=using declaration '::__gnu_cxx::_Lock_policy::_S_single'\n \[1\]=binding '::std::_S_single'\n} module } }
diff --git a/gcc/testsuite/g++.dg/modules/using-8_a.C b/gcc/testsuite/g++.dg/modules/using-8_a.C
new file mode 100644
index 0000000..1e71d2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-8_a.C
@@ -0,0 +1,21 @@
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 __FILE__ 1
+namespace A
+{
+void swap (int &, int &);
+void copy (int &);
+}
+# 10 "" 2
+export module bob;
+// { dg-module-cmi bob }
+
+export template <typename T>
+void Foo (T & a, T &b)
+{
+ using A::swap;
+ swap (a, b);
+
+ using A::copy;
+ copy (b);
+}
diff --git a/gcc/testsuite/g++.dg/modules/using-8_b.C b/gcc/testsuite/g++.dg/modules/using-8_b.C
new file mode 100644
index 0000000..feac0ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-8_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options -fmodules-ts }
+import bob;
+
+int main ()
+{
+ int a = 0, b = 1;
+ Foo (a, b);
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/using-enum-1_a.H b/gcc/testsuite/g++.dg/modules/using-enum-1_a.H
new file mode 100644
index 0000000..a4204b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-enum-1_a.H
@@ -0,0 +1,16 @@
+// { dg-additional-options {-fmodule-header -std=c++2a} }
+// { dg-module-cmi {} }
+
+enum class E {a, b, c};
+struct C
+{
+ using enum E;
+};
+
+struct D: C
+{
+ int foo ()
+ {
+ return int (a);
+ }
+};
diff --git a/gcc/testsuite/g++.dg/modules/using-enum-1_b.C b/gcc/testsuite/g++.dg/modules/using-enum-1_b.C
new file mode 100644
index 0000000..af0610a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-enum-1_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -std=c++2a } }
+
+#include "using-enum-1_a.H"
+import "using-enum-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/var-1_a.C b/gcc/testsuite/g++.dg/modules/var-1_a.C
new file mode 100644
index 0000000..2a5d6bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-1_a.C
@@ -0,0 +1,9 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module Var;
+// { dg-module-cmi Var }
+
+export int counter = 2;
+export extern const int limit = 5;
+
diff --git a/gcc/testsuite/g++.dg/modules/var-1_b.C b/gcc/testsuite/g++.dg/modules/var-1_b.C
new file mode 100644
index 0000000..9a57f61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-1_b.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import Var;
+
+int main ()
+{
+ if (counter != 2)
+ return 1;
+ if (limit != 5)
+ return 2;
+ static_assert (limit == 5, "huh?");
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/var-tpl-1_a.C b/gcc/testsuite/g++.dg/modules/var-tpl-1_a.C
new file mode 100644
index 0000000..f538304
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-tpl-1_a.C
@@ -0,0 +1,21 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+
+export module frob;
+// { dg-module-cmi frob }
+
+export template<typename T> T sum (T a)
+{
+ return a;
+}
+
+export template<typename T, typename... R>
+inline T sum (T a, R... b)
+{
+ return a + static_cast<T> (sum (b...));
+}
+
+export inline int add (int a, int b, int c)
+{
+ return sum (a, b, c);
+}
diff --git a/gcc/testsuite/g++.dg/modules/var-tpl-1_b.C b/gcc/testsuite/g++.dg/modules/var-tpl-1_b.C
new file mode 100644
index 0000000..a8c8524
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-tpl-1_b.C
@@ -0,0 +1,14 @@
+// { dg-additional-options -fmodules-ts }
+
+import frob;
+
+int main ()
+{
+ if (6 != add (1, 2, 3))
+ return 1;
+
+ if (10 != sum (1, unsigned (2), 3.0f, 4.0))
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/var-tpl-concept-1.h b/gcc/testsuite/g++.dg/modules/var-tpl-concept-1.h
new file mode 100644
index 0000000..1dbd07f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-tpl-concept-1.h
@@ -0,0 +1,70 @@
+
+template<class _CharT> struct char_traits;
+
+template<typename _CharT, typename _Traits = char_traits<_CharT>>
+class basic_string;
+
+typedef basic_string<char> string;
+
+template<typename> struct iterator_traits;
+
+template<bool _Cond> struct conditional;
+
+template<typename _Iter>
+inline constexpr bool disable_sized_sentinel_for = false;
+
+template<typename _Iter>
+concept sized_sentinel_for = !disable_sized_sentinel_for<_Iter>;
+
+template<typename _Iterator>
+class __normal_iterator
+{
+ typedef iterator_traits<_Iterator> __traits_type;
+};
+
+template<typename _Iterator>
+class reverse_iterator
+{
+public:
+ using iterator_concept
+ = typename conditional<sized_sentinel_for<_Iterator>>::type;
+};
+
+
+template<typename _Iterator>
+requires (!sized_sentinel_for<_Iterator>)
+bool disable_sized_sentinel_for<reverse_iterator<_Iterator>> = true;
+
+
+template<typename _Iterator>
+bool operator==(const reverse_iterator<_Iterator>& __x,
+ const reverse_iterator<_Iterator>& __y);
+template<typename _Iterator>
+bool operator==(const __normal_iterator<_Iterator>& __lhs,
+ const __normal_iterator<_Iterator>& __rhs);
+
+template<typename _It >
+class common_iterator
+{
+public:
+ friend bool operator==(const common_iterator& __x,
+ const common_iterator& __y)
+ {
+ return __x._M_it == __y._M_it;
+ }
+
+private:
+ _It _M_it;
+};
+
+template<typename _It>
+struct iterator_traits<common_iterator<_It>>
+{
+};
+
+template<typename _CharT>
+struct char_traits
+{
+ static bool eq(const _CharT& __c1, const _CharT& __c2)
+ { return __c1 == __c2; }
+};
diff --git a/gcc/testsuite/g++.dg/modules/var-tpl-concept-1_a.C b/gcc/testsuite/g++.dg/modules/var-tpl-concept-1_a.C
new file mode 100644
index 0000000..4655e39
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-tpl-concept-1_a.C
@@ -0,0 +1,8 @@
+// { dg-additional-options {-fmodules-ts -fconcepts} }
+module;
+#include "var-tpl-concept-1.h"
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+
+export void bar (string &);
diff --git a/gcc/testsuite/g++.dg/modules/var-tpl-concept-1_b.C b/gcc/testsuite/g++.dg/modules/var-tpl-concept-1_b.C
new file mode 100644
index 0000000..2c44ede
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/var-tpl-concept-1_b.C
@@ -0,0 +1,10 @@
+// { dg-additional-options {-fmodules-ts -fconcepts} }
+module;
+#include "var-tpl-concept-1.h"
+
+export module foo;
+// { dg-module-cmi {foo} }
+
+export import :part1;
+
+export void baz (string &);
diff --git a/gcc/testsuite/g++.dg/modules/virt-1_a.C b/gcc/testsuite/g++.dg/modules/virt-1_a.C
new file mode 100644
index 0000000..7719a28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/virt-1_a.C
@@ -0,0 +1,25 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export struct Visitor
+{
+ virtual int Visit ();
+};
+
+// Key function explicitly not in line (regardless of p1779's state)
+// We emit vtables & rtti only in this TU
+int Visitor::Visit ()
+{
+ return 0;
+}
+
+export int Visit (Visitor *v)
+{
+ return v->Visit ();
+}
+
+// { dg-final { scan-assembler {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
diff --git a/gcc/testsuite/g++.dg/modules/virt-1_b.C b/gcc/testsuite/g++.dg/modules/virt-1_b.C
new file mode 100644
index 0000000..b4372e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/virt-1_b.C
@@ -0,0 +1,23 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct Mine : Visitor
+{
+ int Visit () override
+ {
+ return 1;
+ }
+};
+
+int main ()
+{
+ Mine me;
+
+ return !(Visit (&me) == 1);
+}
+
+// We do not emit Visitor vtable or rtti here
+// { dg-final { scan-assembler-not {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler-not {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler-not {_ZTS7Visitor:} } }
diff --git a/gcc/testsuite/g++.dg/modules/virt-2_a.C b/gcc/testsuite/g++.dg/modules/virt-2_a.C
new file mode 100644
index 0000000..9115cc1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/virt-2_a.C
@@ -0,0 +1,27 @@
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export struct Visitor
+{
+ virtual int Visit ();
+};
+
+// Key function explicitly inline (regardless of p1779's state)
+// We emit vtables & rtti only in this TU
+inline // Yoink!
+ int Visitor::Visit ()
+{
+ return 0;
+}
+
+export int Visit (Visitor *v)
+{
+ return v->Visit ();
+}
+
+// Emit here
+// { dg-final { scan-assembler {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
diff --git a/gcc/testsuite/g++.dg/modules/virt-2_b.C b/gcc/testsuite/g++.dg/modules/virt-2_b.C
new file mode 100644
index 0000000..5432189
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/virt-2_b.C
@@ -0,0 +1,28 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct Mine : Visitor
+{
+ int Visit () override
+ {
+ return 1;
+ }
+};
+
+extern int Foo ();
+
+int main ()
+{
+ Mine me;
+
+ if (auto b = Foo ())
+ return b;
+ return !(Visit (&me) == 1);
+}
+
+// We do not emit Visitor vtable
+// but we do emit rtti here
+// { dg-final { scan-assembler-not {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
diff --git a/gcc/testsuite/g++.dg/modules/virt-2_c.C b/gcc/testsuite/g++.dg/modules/virt-2_c.C
new file mode 100644
index 0000000..1ac7f99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/virt-2_c.C
@@ -0,0 +1,16 @@
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int Foo ()
+{
+ Visitor v;
+
+ return !(Visit (&v) == 0);
+}
+
+// We do emit Visitor vtable
+// andl also we do emit rtti here
+// { dg-final { scan-assembler {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
diff --git a/gcc/testsuite/g++.dg/modules/vmort-1_a.C b/gcc/testsuite/g++.dg/modules/vmort-1_a.C
new file mode 100644
index 0000000..aa404dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vmort-1_a.C
@@ -0,0 +1,34 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module tom.riddle;
+// { dg-module-cmi tom.riddle }
+
+export inline auto One (int a)
+{
+ struct X {
+ int x;
+ // p1779 makes these things not-inline, which is a surprise.
+ // Asking CWG
+ inline X(int a) :x(a){}
+ inline operator int () const {return x;}
+ };
+
+ return X(a);
+}
+
+// Look Ma! this isn't inline!
+export auto Two (int a)
+{
+ struct Y {
+ int x;
+ // In this case we do manage to emit these fns (if not marked as
+ // inline), but we give them internal linkage, so they are not
+ // nameable from elsewhere. Workaround for now.
+ inline Y(int a) :x(a){}
+ inline operator int () const {return x;}
+ };
+
+ return Y(a);
+}
+
diff --git a/gcc/testsuite/g++.dg/modules/vmort-1_b.C b/gcc/testsuite/g++.dg/modules/vmort-1_b.C
new file mode 100644
index 0000000..9ba49f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vmort-1_b.C
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import tom.riddle;
+
+int main ()
+{
+ auto one = One (2);
+
+ if (int (one) != 2)
+ return 1;
+
+ int two = Two (3);
+ if (two != 3)
+ return 2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/modules/vmort-2_a.C b/gcc/testsuite/g++.dg/modules/vmort-2_a.C
new file mode 100644
index 0000000..27d114d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vmort-2_a.C
@@ -0,0 +1,15 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+
+export module voldy;
+// { dg-module-cmi voldy }
+
+export auto frobber (int i)
+{
+ return [=] (int j) { return i + j; };
+}
+
+// { dg-final { scan-lang-dump {Connecting definition decl type_decl:'::frobber::._anon_0'} module } }
+// { dg-final { scan-lang-dump {Entities 5} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::frobber'\n \[1\]=decl definition '::frobber::._anon_0'\n( \[.\]=decl [^\n]*'\n)* \[.\]=binding '::frobber'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/vmort-2_b.C b/gcc/testsuite/g++.dg/modules/vmort-2_b.C
new file mode 100644
index 0000000..e7376cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vmort-2_b.C
@@ -0,0 +1,20 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+
+export module malfoy;
+// { dg-module-cmi malfoy }
+
+import voldy;
+
+void interpose ()
+{
+ // Force renumber of anon vars
+ auto lambda = [] () {};
+}
+
+export auto conduit (int i)
+{
+ return frobber (i);
+}
+
+// { dg-final { scan-lang-dump-not {Cluster import } module } }
+// { dg-final { scan-lang-dump-not {onnecting definition decl type_decl:'::frobber@voldy:.::._anon_1@voldy:.'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/vmort-2_c.C b/gcc/testsuite/g++.dg/modules/vmort-2_c.C
new file mode 100644
index 0000000..f50c407
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vmort-2_c.C
@@ -0,0 +1,21 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+import malfoy;
+
+void interpose ()
+{
+ // Force renumber of anon vars
+ auto lambda0 = [] () {};
+ auto lambda1 = [] () {};
+ auto lambda2 = [] () {};
+}
+
+int main ()
+{
+ auto widget = conduit (2);
+
+ return !(widget (8) == 10);
+}
+
+// { dg-final { scan-lang-dump {Loading entity voldy\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::frobber@voldy:.::._anon_3@voldy:.'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/vtt-1_a.C b/gcc/testsuite/g++.dg/modules/vtt-1_a.C
new file mode 100644
index 0000000..11a1f6f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-1_a.C
@@ -0,0 +1,36 @@
+// { dg-additional-options "-fmodules-ts -O2 -fno-inline" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct base
+{
+ base () {}
+ virtual ~base ();
+ int m;
+};
+
+base::~base ()
+{
+}
+
+export struct derived : virtual base
+{
+ derived () {}
+ virtual ~derived ();
+ int m2;
+};
+
+derived::~derived ()
+{
+}
+
+export void make_foo ()
+{
+ base b;
+ derived d;
+}
+
+// { dg-final {scan-assembler "_ZTV4base:" } }
+// { dg-final {scan-assembler "_ZTV7derived:" } }
+// { dg-final {scan-assembler "_ZTT7derived:" } }
diff --git a/gcc/testsuite/g++.dg/modules/vtt-1_b.C b/gcc/testsuite/g++.dg/modules/vtt-1_b.C
new file mode 100644
index 0000000..2f1b965
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-1_b.C
@@ -0,0 +1,28 @@
+// { dg-additional-options "-fmodules-ts -O2 -fno-inline" }
+
+export module bar;
+// { dg-module-cmi bar }
+
+export import foo;
+
+export struct mine : derived
+{
+ mine () {}
+ ~mine ();
+ int mm;
+};
+
+mine::~mine ()
+{
+}
+
+export inline void make_bar ()
+{
+ mine m;
+}
+
+// { dg-final {scan-assembler-not "_ZTV4base:" } }
+// { dg-final {scan-assembler-not "_ZTV7derived:" } }
+// { dg-final {scan-assembler-not "_ZTT7derived:" } }
+// { dg-final {scan-assembler "_ZTV4mine:" } }
+// { dg-final {scan-assembler "_ZTT4mine:" } }
diff --git a/gcc/testsuite/g++.dg/modules/vtt-1_c.C b/gcc/testsuite/g++.dg/modules/vtt-1_c.C
new file mode 100644
index 0000000..9acdd32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-1_c.C
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodules-ts -O2 -fno-inline" }
+
+import bar;
+
+int main ()
+{
+ make_foo ();
+ make_bar ();
+
+ mine m0;
+
+ return 0;
+}
+
+// { dg-final {scan-assembler-not "_ZTV4base:" } }
+// { dg-final {scan-assembler-not "_ZTV7derived:" } }
+// { dg-final {scan-assembler-not "_ZTT7derived:" } }
+// { dg-final {scan-assembler-not "_ZTV4mine:" } }
+// { dg-final {scan-assembler-not "_ZTT4mine:" } }
diff --git a/gcc/testsuite/g++.dg/modules/vtt-2.h b/gcc/testsuite/g++.dg/modules/vtt-2.h
new file mode 100644
index 0000000..5ae0db0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-2.h
@@ -0,0 +1,14 @@
+
+class basic_ios
+{
+public:
+ virtual ~basic_ios();
+ basic_ios();
+};
+
+class basic_ostream : virtual public basic_ios
+{
+public:
+ basic_ostream();
+ virtual ~basic_ostream();
+};
diff --git a/gcc/testsuite/g++.dg/modules/vtt-2_a.H b/gcc/testsuite/g++.dg/modules/vtt-2_a.H
new file mode 100644
index 0000000..0e01872
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-2_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "vtt-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/vtt-2_b.C b/gcc/testsuite/g++.dg/modules/vtt-2_b.C
new file mode 100644
index 0000000..c1ed3d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/vtt-2_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "vtt-2.h"
+import "vtt-2_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-times {merge key \(unique\)} 2 module } }
diff --git a/gcc/testsuite/g++.dg/opt/const4.C b/gcc/testsuite/g++.dg/opt/const4.C
index 883c24b..75ee0e6 100644
--- a/gcc/testsuite/g++.dg/opt/const4.C
+++ b/gcc/testsuite/g++.dg/opt/const4.C
@@ -3,7 +3,8 @@
// that have it.
// { dg-do compile }
-const int a[] __attribute__ ((__used__)) = { 0, 1, 2, 3 };
+// { dg-final { scan-assembler-symbol-section {constant_variable} {^\.(const|rodata)|\[RO\]} } }
+const int constant_variable[] __attribute__ ((__used__)) = { 0, 1, 2, 3 };
// The MMIX port always switches to the .data section at the end of a file.
// { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail powerpc*-*-aix* mmix-*-* } } }
diff --git a/gcc/testsuite/g++.dg/opt/pr64411.C b/gcc/testsuite/g++.dg/opt/pr64411.C
index 122b9ee..6ecc0a8 100644
--- a/gcc/testsuite/g++.dg/opt/pr64411.C
+++ b/gcc/testsuite/g++.dg/opt/pr64411.C
@@ -1,5 +1,6 @@
// PR target/64411
// { dg-do compile { target { { i?86-*-* x86_64-*-* } && lp64 } } }
+// { dg-require-effective-target fpic }
// { dg-options "-Os -mcmodel=medium -fPIC -fschedule-insns -fselective-scheduling" }
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/g++.dg/opt/pr97767.C b/gcc/testsuite/g++.dg/opt/pr97767.C
new file mode 100644
index 0000000..da0879d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr97767.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-O -fstrict-enums -ftree-vrp -w" }
+
+enum { E0 = 0, E1 = 1, E2 = 2 } e;
+
+int
+foo (void)
+{
+ return __builtin_popcount ((int) e);
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr98130.C b/gcc/testsuite/g++.dg/opt/pr98130.C
new file mode 100644
index 0000000..0af55ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr98130.C
@@ -0,0 +1,25 @@
+// PR c++/98130
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+#include <new>
+
+typedef int *T;
+
+static unsigned char storage[sizeof (T)] alignas (T);
+static T *p = (T *) storage;
+
+static inline __attribute__((__always_inline__)) void
+foo (T value)
+{
+ new (p) T(value);
+}
+
+int
+main ()
+{
+ int a;
+ foo (&a);
+ if (!*p)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr98353.C b/gcc/testsuite/g++.dg/opt/pr98353.C
new file mode 100644
index 0000000..e3d0a47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr98353.C
@@ -0,0 +1,17 @@
+// PR c++/98353
+// { dg-do compile { target c++11 } }
+
+template <int N> struct A {};
+template <typename T>
+struct B
+{
+ static const int n = 1;
+ template <class> A <B<T>::n> foo ();
+ _Complex double c[2], d = 1.0;
+};
+
+void
+bar ()
+{
+ B<int>().foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/other/abstract1.C b/gcc/testsuite/g++.dg/other/abstract1.C
index 53d767a..6ded7ec 100644
--- a/gcc/testsuite/g++.dg/other/abstract1.C
+++ b/gcc/testsuite/g++.dg/other/abstract1.C
@@ -5,34 +5,38 @@
// c++/9256: Make sure that a pointer to an array of abstract elements
// cannot be created, not even during template substitution (DR337).
+// Changed massively by P0929R2: now only creating an object of the array type
+// is ill-formed, not merely forming the array type.
+
struct Abstract { virtual void f() = 0; }; // { dg-message "note" }
struct Complete { void f(); };
/*
* TEST 1
- * Arrays of abstract elements cannot be declared.
+ * Arrays of abstract elements cannot be defined.
*/
Abstract a0[2]; // { dg-error "" }
-Abstract (*a1)[2]; // { dg-error "" }
-Abstract (**a2)[2]; // { dg-error "" }
-Abstract (***a3)[2]; // { dg-error "" }
+Abstract (*a1)[2];
+Abstract (**a2)[2];
+Abstract (***a3)[2];
Abstract *a4;
Abstract *a5[2];
-Abstract (*a6[2])[2]; // { dg-error "" }
+Abstract (*a6[2])[2];
Abstract **a7[2];
-Abstract *(*a8[2])[2];
-Abstract (**a9[2])[2]; // { dg-error "" }
+Abstract *(*a8[2])[2];
+Abstract (**a9[2])[2];
/*
* TEST 2
- * If a pointer to an array of abstract elements is created during template
+ * If an array of abstract elements is created during template
* instantiation, an error should occur.
*/
template <class T> struct K {
- T (*a)[2]; // { dg-error "abstract class type" }
+ T (*a1)[2];
+ T (a2)[2]; // { dg-error "abstract" }
};
template struct K<Abstract>; // { dg-message "required" }
@@ -41,8 +45,9 @@ template struct K<Abstract>; // { dg-message "required" }
/*
* TEST 3
- * Deducing an array of abstract elements during type deduction is a silent
- * failure (rejects overload).
+
+ * Deducing an array of abstract elements during type deduction is no longer a
+ * silent failure.
*/
template <bool> struct StaticAssert;
@@ -54,6 +59,6 @@ typedef struct { char x[2]; } No;
template<typename U> No is_abstract(U (*k)[1]);
template<typename U> Yes is_abstract(...);
-StaticAssert<sizeof(is_abstract<Abstract>(0)) == sizeof(Yes)> b1;
+StaticAssert<sizeof(is_abstract<Abstract>(0)) == sizeof(No)> b1;
StaticAssert<sizeof(is_abstract<Complete>(0)) == sizeof(No)> b2;
StaticAssert<sizeof(is_abstract<int>(0)) == sizeof(No)> b3;
diff --git a/gcc/testsuite/g++.dg/other/abstract2.C b/gcc/testsuite/g++.dg/other/abstract2.C
index 60a4e41..0a8009e 100644
--- a/gcc/testsuite/g++.dg/other/abstract2.C
+++ b/gcc/testsuite/g++.dg/other/abstract2.C
@@ -5,54 +5,59 @@
namespace N1 {
struct X;
- struct Y1 {
- void g(X parm1); // { dg-error "abstract" }
- void g(X parm2[2]); // { dg-error "abstract" }
- void g(X (*parm3)[2]); // { dg-error "abstract" }
+ struct X { // { dg-message "note" }
+ virtual void xfunc(void) = 0; // { dg-message "note" }
};
+ struct Y1 {
+ void g(X parm1) {} // { dg-error "abstract" }
+ void g(X parm2[2]) {}
+ void g(X (*parm3)[2]) {}
+ };
template <int N>
struct Y2 {
- void g(X parm4); // { dg-error "abstract" }
- void g(X parm5[2]); // { dg-error "abstract" }
- void g(X (*parm6)[2]); // { dg-error "abstract" }
+ void g(X parm4) {} // { dg-error "abstract" }
+ void g(X parm5[2]) {}
+ void g(X (*parm6)[2]) {}
};
- struct X { // { dg-message "note" }
- virtual void xfunc(void) = 0; // { dg-message "note" }
- };
+ template struct Y2<42>;
}
namespace N2 {
struct X1 { // { dg-message "note" }
virtual void xfunc(void) = 0; // { dg-message "note" }
- void g(X1 parm7); // { dg-error "abstract" }
- void g(X1 parm8[2]); // { dg-error "abstract" }
- void g(X1 (*parm9)[2]); // { dg-error "abstract" }
+ void g(X1 parm7) {} // { dg-error "abstract" }
+ void g(X1 parm8[2]) {}
+ void g(X1 (*parm9)[2]) {}
};
template <int N>
struct X2 { // { dg-message "note" }
virtual void xfunc(void) = 0; // { dg-message "note" }
- void g(X2 parm10); // { dg-error "abstract" }
- void g(X2 parm11[2]); // { dg-error "abstract" }
- void g(X2 (*parm12)[2]); // { dg-error "abstract" }
+ void g(X2 parm10) {} // { dg-error "abstract" }
+ void g(X2 parm11[2]) {}
+ void g(X2 (*parm12)[2]) {}
};
+
+ template struct X2<42>;
}
namespace N3 {
struct X { // { dg-message "note" }
virtual void xfunc(void) = 0; // { dg-message "note" }
};
- void g(X parm13); // { dg-error "abstract" }
- void g(X parm14[2]); // { dg-error "abstract" }
- void g(X (*parm15)[2]); // { dg-error "abstract" }
-
- template <int N>
- void g(X parm16); // { dg-error "abstract" }
- template <int N>
- void g(X parm17[2]); // { dg-error "abstract" }
- template <int N>
- void g(X (*parm18)[2]); // { dg-error "abstract" }
+ void g(X parm13) {} // { dg-error "abstract" }
+ void g(X parm14[2]) {}
+ void g(X (*parm15)[2]) {}
+
+ template <int N>
+ void g(X parm16) {} // { dg-error "abstract" }
+ template <int N>
+ void g(X parm17[2]) {}
+ template <int N>
+ void g(X (*parm18)[2]) {}
+
+ template void g<42>(X);
}
diff --git a/gcc/testsuite/g++.dg/other/abstract4.C b/gcc/testsuite/g++.dg/other/abstract4.C
index 68b2eb2..6a8c8c7 100644
--- a/gcc/testsuite/g++.dg/other/abstract4.C
+++ b/gcc/testsuite/g++.dg/other/abstract4.C
@@ -13,6 +13,6 @@ struct Abs
int main()
{
- S<Abs(int)> s; // { dg-error "abstract" }
- foo<Abs(int)>(); // { dg-error "abstract" }
+ S<Abs(int)> s;
+ foo<Abs(int)>();
}
diff --git a/gcc/testsuite/g++.dg/other/abstract5.C b/gcc/testsuite/g++.dg/other/abstract5.C
index d13dd9e..c17d60d 100644
--- a/gcc/testsuite/g++.dg/other/abstract5.C
+++ b/gcc/testsuite/g++.dg/other/abstract5.C
@@ -3,4 +3,4 @@ struct A
virtual void f() = 0;
};
-typedef A (*fp)(); // { dg-error "abstract" }
+typedef A (*fp)();
diff --git a/gcc/testsuite/g++.dg/other/abstract8.C b/gcc/testsuite/g++.dg/other/abstract8.C
new file mode 100644
index 0000000..bc5afbb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/abstract8.C
@@ -0,0 +1,40 @@
+// P0929R2: Checking for abstract class types.
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -Wno-return-type }
+
+struct A
+{
+ virtual void f() = 0;
+};
+
+struct B
+{
+ A a; // { dg-error "abstract" }
+ A ar[4]; // { dg-error "abstract" }
+};
+
+using Aa = A[4]; // OK
+Aa* aap; // OK
+
+extern A a; // OK
+extern Aa aa; // OK
+A f(); // OK
+void g(A); // OK
+
+A a; // { dg-error "abstract" }
+Aa aa; // { dg-error "abstract" }
+A f() { } // { dg-error "abstract" }
+void g(A) { } // { dg-error "abstract" }
+
+int main()
+{
+ (A(a)); // { dg-error "abstract" }
+ A{}; // { dg-error "abstract" }
+ static_cast<A>(a); // { dg-error "abstract" }
+ Aa{}; // { dg-error "abstract" }
+ f(); // { dg-error "abstract" }
+ decltype(f())* p; // OK
+ g(a); // { dg-error "abstract" }
+
+ throw a; // { dg-error "abstract" }
+}
diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
index 449f30d..62b2132 100644
--- a/gcc/testsuite/g++.dg/other/i386-2.C
+++ b/gcc/testsuite/g++.dg/other/i386-2.C
@@ -1,5 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16" } */
+/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni" } */
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h,
xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
diff --git a/gcc/testsuite/g++.dg/other/i386-3.C b/gcc/testsuite/g++.dg/other/i386-3.C
index 29e9891..843aa2b 100644
--- a/gcc/testsuite/g++.dg/other/i386-3.C
+++ b/gcc/testsuite/g++.dg/other/i386-3.C
@@ -1,5 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16" } */
+/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni" } */
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h,
xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
diff --git a/gcc/testsuite/g++.dg/other/pr88187.C b/gcc/testsuite/g++.dg/other/pr88187.C
index ebdafdd..13466d3 100644
--- a/gcc/testsuite/g++.dg/other/pr88187.C
+++ b/gcc/testsuite/g++.dg/other/pr88187.C
@@ -4,4 +4,4 @@
template <int> struct A;
void f (A ()); // { dg-error "6:variable or field 'f' declared void" "" { target c++14_down } }
// { dg-error "missing template arguments before '\\(' token" "" { target c++14_down } .-1 }
- // { dg-error "'auto' parameter not permitted in this context" "" { target c++17 } .-2 }
+ // { dg-error "placeholder .A. not permitted in this context" "" { target c++17 } .-2 }
diff --git a/gcc/testsuite/g++.dg/other/switch4.C b/gcc/testsuite/g++.dg/other/switch4.C
index 5d0047b..070c55e 100644
--- a/gcc/testsuite/g++.dg/other/switch4.C
+++ b/gcc/testsuite/g++.dg/other/switch4.C
@@ -3,5 +3,4 @@
class a b; // { dg-error "aggregate" }
void c() {
switch () // { dg-error "expected" }
- case b // { dg-error "expected" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
+ case b // { dg-error "9:expected" }
diff --git a/gcc/testsuite/g++.dg/parse/attr3.C b/gcc/testsuite/g++.dg/parse/attr3.C
index 57fa60e..de09598 100644
--- a/gcc/testsuite/g++.dg/parse/attr3.C
+++ b/gcc/testsuite/g++.dg/parse/attr3.C
@@ -10,5 +10,5 @@ int main () {
S::F y; // { dg-warning "'F' is deprecated" }
y = S::f;
- return x + y;
+ return x + y; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
}
diff --git a/gcc/testsuite/g++.dg/parse/attr4.C b/gcc/testsuite/g++.dg/parse/attr4.C
index 36ebdbd..f16bf47 100644
--- a/gcc/testsuite/g++.dg/parse/attr4.C
+++ b/gcc/testsuite/g++.dg/parse/attr4.C
@@ -1,4 +1,3 @@
// PR c++/93684 - ICE-on-invalid with broken attribute.
[[a:: // { dg-error "expected" }
- // { dg-error "-:expected" "" { target c++11 } .+1 }
diff --git a/gcc/testsuite/g++.dg/parse/cond4.C b/gcc/testsuite/g++.dg/parse/cond4.C
index 893caea..6484f86 100644
--- a/gcc/testsuite/g++.dg/parse/cond4.C
+++ b/gcc/testsuite/g++.dg/parse/cond4.C
@@ -3,5 +3,4 @@
void foo()
{
- if (struct A{}// { dg-error "types may not be defined|expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+ if (struct A{}// { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/parse/crash10.C b/gcc/testsuite/g++.dg/parse/crash10.C
index 7e2dec6..f713c3c 100644
--- a/gcc/testsuite/g++.dg/parse/crash10.C
+++ b/gcc/testsuite/g++.dg/parse/crash10.C
@@ -9,4 +9,3 @@ class
{
typename::
; // { dg-error "expected" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/parse/crash18.C b/gcc/testsuite/g++.dg/parse/crash18.C
index 596d310..2531133 100644
--- a/gcc/testsuite/g++.dg/parse/crash18.C
+++ b/gcc/testsuite/g++.dg/parse/crash18.C
@@ -4,4 +4,4 @@
// PR 18095: ICE
// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
-struct A // { dg-error "-:expected" "" { target *-*-* } .+1 }
+struct A // { dg-error "9:expected" }
diff --git a/gcc/testsuite/g++.dg/parse/crash27.C b/gcc/testsuite/g++.dg/parse/crash27.C
index 08977b2..4090fc5 100644
--- a/gcc/testsuite/g++.dg/parse/crash27.C
+++ b/gcc/testsuite/g++.dg/parse/crash27.C
@@ -2,4 +2,4 @@
void Dispatcher()
(__builtin_offsetof (ArgsType, largeMsgLen)) // { dg-error "initialize" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "54:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/crash34.C b/gcc/testsuite/g++.dg/parse/crash34.C
index 86f79cc..60f44ae 100644
--- a/gcc/testsuite/g++.dg/parse/crash34.C
+++ b/gcc/testsuite/g++.dg/parse/crash34.C
@@ -4,4 +4,4 @@
void foo()
{
namespace N { /* { dg-error "is not allowed" } */
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "16:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/crash35.C b/gcc/testsuite/g++.dg/parse/crash35.C
index 05f0a63..24b69f1 100644
--- a/gcc/testsuite/g++.dg/parse/crash35.C
+++ b/gcc/testsuite/g++.dg/parse/crash35.C
@@ -4,4 +4,4 @@
struct a {};
class foo : public a, a // { dg-error "duplicate base" }
-{ // { dg-error "-:at end of input" "" { target *-*-* } .+1 }
+{ // { dg-error "2:at end of input" }
diff --git a/gcc/testsuite/g++.dg/parse/crash52.C b/gcc/testsuite/g++.dg/parse/crash52.C
index 5dfb69c..ab30a7a 100644
--- a/gcc/testsuite/g++.dg/parse/crash52.C
+++ b/gcc/testsuite/g++.dg/parse/crash52.C
@@ -1,4 +1,4 @@
// PR c++/39053
void foo() = // { dg-error "initialized" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "13:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/crash59.C b/gcc/testsuite/g++.dg/parse/crash59.C
index 7526b08..52b6b24 100644
--- a/gcc/testsuite/g++.dg/parse/crash59.C
+++ b/gcc/testsuite/g++.dg/parse/crash59.C
@@ -1,4 +1,4 @@
// PR c++/53003
struct A{ void a{} return b // { dg-error "16:function definition" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "28:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/crash61.C b/gcc/testsuite/g++.dg/parse/crash61.C
index 713fe9f..b2004b8 100644
--- a/gcc/testsuite/g++.dg/parse/crash61.C
+++ b/gcc/testsuite/g++.dg/parse/crash61.C
@@ -5,4 +5,3 @@
struct pair { constexpr pair (const) : }; // { dg-error "" }
template <0> make_pair () {} // { dg-error "" }
pair prefix[] = { 0, make_pair } // { dg-error "" }
-// { dg-error "-:expected" "" { target c++11 } .+1 }
diff --git a/gcc/testsuite/g++.dg/parse/crash67.C b/gcc/testsuite/g++.dg/parse/crash67.C
index 2a5bb3f..8f6305d 100644
--- a/gcc/testsuite/g++.dg/parse/crash67.C
+++ b/gcc/testsuite/g++.dg/parse/crash67.C
@@ -4,4 +4,4 @@
class x0;
template <x1> x2() { // { dg-error "declared|type" }
x0 x3 = x3. // { dg-error "incomplete type" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "12:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/defarg17.C b/gcc/testsuite/g++.dg/parse/defarg17.C
new file mode 100644
index 0000000..c39a819
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/defarg17.C
@@ -0,0 +1,11 @@
+typedef int I;
+
+int f(float I = 0.0, int b = I(2)); // { dg-error "parameter" }
+int g(int b = I(2), float I = 0.0);
+
+struct A
+{
+ int f(float I = 0.0, int b = I(2)); // { dg-error "parameter" }
+ int g(int b = I(2), float I = 0.0);
+};
+
diff --git a/gcc/testsuite/g++.dg/parse/error14.C b/gcc/testsuite/g++.dg/parse/error14.C
index fd654180..3d87d46 100644
--- a/gcc/testsuite/g++.dg/parse/error14.C
+++ b/gcc/testsuite/g++.dg/parse/error14.C
@@ -20,4 +20,4 @@ struct X
// }
}; // { dg-error "1:expected primary-expression before '.' token" "primary" }
-// { dg-error "-:expected" "at end of input" { target *-*-* } .+1 }
+// { dg-error "3:expected" "at end of input" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/error56.C b/gcc/testsuite/g++.dg/parse/error56.C
index 11d3197..bd3d27e 100644
--- a/gcc/testsuite/g++.dg/parse/error56.C
+++ b/gcc/testsuite/g++.dg/parse/error56.C
@@ -4,4 +4,3 @@ template <0> int __copy_streambufs_eof; // { dg-error "" }
class {
// { dg-error "forbids" "" { target *-*-* } .+1 }
friend __copy_streambufs_eof <> ( // { dg-error "" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/parse/invalid1.C b/gcc/testsuite/g++.dg/parse/invalid1.C
index cb4ef1a..971898f 100644
--- a/gcc/testsuite/g++.dg/parse/invalid1.C
+++ b/gcc/testsuite/g++.dg/parse/invalid1.C
@@ -3,4 +3,4 @@
// { dg-options "-w" }
int foo ( foo += *[ // { dg-error "expected" }
-// { dg-error "-:invalid|expected" "" { target *-*-* } .+1 }
+// { dg-error "20:invalid|expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/parameter-declaration-1.C b/gcc/testsuite/g++.dg/parse/parameter-declaration-1.C
index c6106d5..bd8f7f9 100644
--- a/gcc/testsuite/g++.dg/parse/parameter-declaration-1.C
+++ b/gcc/testsuite/g++.dg/parse/parameter-declaration-1.C
@@ -3,5 +3,5 @@
// { dg-do compile }
struct {
- a(void = 0; a(0), a(0) // { dg-error "" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+ a(void = 0; a(0), a(0) // { dg-error "invalid|cannot|before|forbid|member" }
+// { dg-error "25:end of input" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/parser-pr28152-2.C b/gcc/testsuite/g++.dg/parse/parser-pr28152-2.C
index 28048bd..8f6cce8 100644
--- a/gcc/testsuite/g++.dg/parse/parser-pr28152-2.C
+++ b/gcc/testsuite/g++.dg/parse/parser-pr28152-2.C
@@ -8,4 +8,4 @@ main (void)
z = __complex__ (1.90000007326203904e+19, 0.0); // { dg-error "expected primary-expression before '__complex__'" "primary-expression" }
z = __complex__ (1.0e+0, 0.0) / z; // { dg-error "expected primary-expression before '__complex__'" "primaty-expression" }
- // { dg-error "-:at end of input" "end" { target *-*-* } .+1 }
+ // { dg-error "37:at end of input" "end" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/parser-pr28152.C b/gcc/testsuite/g++.dg/parse/parser-pr28152.C
index 3461734..748c355 100644
--- a/gcc/testsuite/g++.dg/parse/parser-pr28152.C
+++ b/gcc/testsuite/g++.dg/parse/parser-pr28152.C
@@ -8,4 +8,4 @@ main (void)
z = _Complex (1.90000007326203904e+19, 0.0); // { dg-error "expected primary-expression before '_Complex'" "primary-expression" }
z = _Complex (1.0e+0, 0.0) / z; // { dg-error "expected primary-expression before '_Complex'" "primary-expression" }
- // { dg-error "-:at end of input" "end" { target *-*-* } .+1 }
+ // { dg-error "34:at end of input" "end" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/pr58898.C b/gcc/testsuite/g++.dg/parse/pr58898.C
index e788c91..e67011d2 100644
--- a/gcc/testsuite/g++.dg/parse/pr58898.C
+++ b/gcc/testsuite/g++.dg/parse/pr58898.C
@@ -5,12 +5,12 @@ struct Foo
{
Foo()
{
- int t(int()); // Error
+ int t(int()); // { dg-warning "parentheses were disambiguated" }
}
};
int main()
{
- int t(int()); // OK
+ int t(int()); // { dg-warning "parentheses were disambiguated" }
Foo<> a; // Error
}
diff --git a/gcc/testsuite/g++.dg/parse/pr68722.C b/gcc/testsuite/g++.dg/parse/pr68722.C
index 26f6d11..6d2f100 100644
--- a/gcc/testsuite/g++.dg/parse/pr68722.C
+++ b/gcc/testsuite/g++.dg/parse/pr68722.C
@@ -6,4 +6,3 @@ class A {
A _M_ios_locale ios_base(ios_base &) template <_Traits> class basic_ios { // { dg-error "" }
basic_ios basic_ios = operator= // { dg-error "" }
// { dg-prune-output "file ends in default argument" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/parse/pr96258.C b/gcc/testsuite/g++.dg/parse/pr96258.C
index 1b642e1..4d14a80 100644
--- a/gcc/testsuite/g++.dg/parse/pr96258.C
+++ b/gcc/testsuite/g++.dg/parse/pr96258.C
@@ -1,5 +1,3 @@
// { dg-additional-options -fopenmp }
// { dg-require-effective-target fopenmp }
-#pragma omp declare simd // { dg-error "not immediately followed by" }
-
-// { dg-error "-:expected unqualified-id" "" { target *-*-* } .+1 }
+#pragma omp declare simd // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/pch/pr98343.C b/gcc/testsuite/g++.dg/pch/pr98343.C
new file mode 100644
index 0000000..095a4f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/pr98343.C
@@ -0,0 +1,6 @@
+// PR c++/98343
+// { dg-options "-std=c++2a" }
+
+#include "pr98343.H"
+
+const void *ptr2 = __builtin_source_location ();
diff --git a/gcc/testsuite/g++.dg/pch/pr98343.Hs b/gcc/testsuite/g++.dg/pch/pr98343.Hs
new file mode 100644
index 0000000..33c8542
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/pr98343.Hs
@@ -0,0 +1,18 @@
+// PR c++/98343
+// { dg-options "-std=c++2a" }
+
+namespace std
+{
+ struct source_location
+ {
+ struct __impl
+ {
+ const char* _M_file_name;
+ const char* _M_function_name;
+ unsigned _M_line;
+ unsigned _M_column;
+ };
+ const __impl* _M_impl;
+ };
+}
+const void *ptr = __builtin_source_location ();
diff --git a/gcc/testsuite/g++.dg/pr46852.C b/gcc/testsuite/g++.dg/pr46852.C
index 5cfeaf9..e3cb402 100644
--- a/gcc/testsuite/g++.dg/pr46852.C
+++ b/gcc/testsuite/g++.dg/pr46852.C
@@ -5,4 +5,3 @@ template
<
class
{ // { dg-error "" }
-// { dg-error "-:" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/pr46868.C b/gcc/testsuite/g++.dg/pr46868.C
index 25b8c96..544c7b2 100644
--- a/gcc/testsuite/g++.dg/pr46868.C
+++ b/gcc/testsuite/g++.dg/pr46868.C
@@ -2,4 +2,3 @@
// { dg-do compile }
template < int > struct S { S < // { dg-error "" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/pr57878.C b/gcc/testsuite/g++.dg/pr57878.C
index 5df2b7c9e..ee9142b 100644
--- a/gcc/testsuite/g++.dg/pr57878.C
+++ b/gcc/testsuite/g++.dg/pr57878.C
@@ -1,5 +1,6 @@
/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
// { dg-require-effective-target c++11 }
+// { dg-require-effective-target fpic }
/* { dg-options "-O2 -fno-omit-frame-pointer -fPIC" } */
typedef int int32;
diff --git a/gcc/testsuite/g++.dg/pr65032.C b/gcc/testsuite/g++.dg/pr65032.C
index d6b6768..6e348f8 100644
--- a/gcc/testsuite/g++.dg/pr65032.C
+++ b/gcc/testsuite/g++.dg/pr65032.C
@@ -1,4 +1,5 @@
// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-require-effective-target fpic }
// { dg-options "-Os -std=c++11 -fPIC -fstack-protector-strong -fomit-frame-pointer" }
#pragma GCC visibility push(hidden)
diff --git a/gcc/testsuite/g++.dg/pr84279.C b/gcc/testsuite/g++.dg/pr84279.C
index a88d3fb..b2b5b8e 100644
--- a/gcc/testsuite/g++.dg/pr84279.C
+++ b/gcc/testsuite/g++.dg/pr84279.C
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-require-effective-target fpic } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-options "-O3 -mcpu=power8 -g -fPIC -fvisibility=hidden -fstack-protector-strong" } */
diff --git a/gcc/testsuite/g++.dg/pr93195a.C b/gcc/testsuite/g++.dg/pr93195a.C
new file mode 100644
index 0000000..26d265d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr93195a.C
@@ -0,0 +1,27 @@
+/* { dg-do link { target { ! { nvptx*-*-* visium-*-* } } } } */
+// { dg-require-effective-target o_flag_in_section }
+/* { dg-options "-O0 -fpatchable-function-entry=1" } */
+/* { dg-additional-options "-fno-pie" { target sparc*-*-* } } */
+/* { dg-additional-sources pr93195b.C } */
+
+extern void bar1 (void);
+
+inline void
+foo (void)
+{
+}
+
+void
+bar (void)
+{
+ foo ();
+ bar1 ();
+}
+
+int
+main ()
+{
+ bar ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/pr93195b.C b/gcc/testsuite/g++.dg/pr93195b.C
new file mode 100644
index 0000000..303d858
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr93195b.C
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! { nvptx*-*-* visium-*-* } } } } */
+/* { dg-options "-O0 -fpatchable-function-entry=1" } */
+/* { dg-additional-options "-fno-pie" { target sparc*-*-* } } */
+
+inline void
+foo (void)
+{
+}
+
+void
+bar1 (void)
+{
+ foo ();
+}
diff --git a/gcc/testsuite/g++.dg/pr97560.C b/gcc/testsuite/g++.dg/pr97560.C
new file mode 100644
index 0000000..59313f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr97560.C
@@ -0,0 +1,45 @@
+// PR tree-optimization/97560
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -fno-tree-forwprop -fnon-call-exceptions" }
+
+template <typename>
+struct pv;
+
+template <typename CY>
+struct pv<CY &> {
+ typedef CY g7;
+};
+
+template <typename Q6>
+typename pv<Q6>::g7 hq (Q6 &&lb)
+{
+ return static_cast<typename pv<Q6>::g7 &&> (lb);
+}
+
+struct fk {
+ fk *j6;
+ fk *od;
+};
+
+fk *qi;
+
+struct xz : fk {
+ xz (xz &&)
+ {
+ qi = this;
+
+ if (j6)
+ od = this;
+ }
+};
+
+struct el {
+ struct {
+ xz ls;
+ } eu;
+};
+
+struct be : el {
+};
+
+be l1 = hq (l1);
diff --git a/gcc/testsuite/g++.dg/pr97609.C b/gcc/testsuite/g++.dg/pr97609.C
new file mode 100644
index 0000000..8e582c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr97609.C
@@ -0,0 +1,46 @@
+// PR tree-optimization/97609
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -fno-tree-fre -fnon-call-exceptions" }
+
+struct _Fwd_list_node_base {
+ _Fwd_list_node_base *_M_next;
+ void _M_transfer_after() { _Fwd_list_node_base *__keep = _M_next = __keep; }
+};
+struct _Fwd_list_const_iterator {
+ _Fwd_list_const_iterator(_Fwd_list_node_base *__n) : _M_node(__n) {}
+ _Fwd_list_const_iterator(int);
+ _Fwd_list_node_base *_M_node;
+};
+template <typename, typename> struct forward_list {
+ _Fwd_list_node_base _M_head;
+ template <typename _InputIterator>
+ forward_list(_InputIterator, _InputIterator);
+ forward_list(int);
+ _Fwd_list_const_iterator cbefore_begin() { return &_M_head; }
+ void splice_after(_Fwd_list_const_iterator) noexcept;
+ void splice_after(_Fwd_list_const_iterator __pos, forward_list &) {
+ splice_after(__pos, 0);
+ }
+ using __remove_return_type = void;
+ __remove_return_type unique() { unique(0); }
+ template <typename _BinPred> __remove_return_type unique(_BinPred);
+};
+template <typename _Tp, typename _Alloc>
+void forward_list<_Tp, _Alloc>::splice_after(_Fwd_list_const_iterator __pos)
+ noexcept {
+ __pos._M_node->_M_transfer_after();
+}
+template <typename _Tp, typename _Alloc>
+template <typename _BinPred>
+auto forward_list<_Tp, _Alloc>::unique(_BinPred) -> __remove_return_type {
+ forward_list __to_destroy(0);
+ splice_after(__to_destroy.cbefore_begin());
+}
+
+void
+foo ()
+{
+ forward_list<int, int> c1 (0, 0);
+ c1.unique ();
+}
+
diff --git a/gcc/testsuite/g++.dg/pr98213.C b/gcc/testsuite/g++.dg/pr98213.C
new file mode 100644
index 0000000..1a744eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr98213.C
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+#include <algorithm>
+
+long var_23;
+int var_24, test_var_8;
+extern bool arr_20[][13];
+char arr_21_0_0_0_0_0;
+int *test_arr_0;
+void test(unsigned long long var_1)
+{
+ int arr_16;
+ for (int i_0 = 0;;)
+ for (int i_5; i_5;) {
+ for (int i_6 = 0; i_6 < 19; i_6 += 4)
+ for (long i_7(test_var_8); i_7; i_7 += 2) {
+ arr_20[0][i_7] = arr_21_0_0_0_0_0 = 0;
+ var_23 = test_arr_0[0];
+ }
+ var_24 = std::max((unsigned long long)arr_16,
+ std::min((unsigned long long)5, var_1));
+ }
+}
diff --git a/gcc/testsuite/g++.dg/template/crash115.C b/gcc/testsuite/g++.dg/template/crash115.C
index c1a7235..80f8683 100644
--- a/gcc/testsuite/g++.dg/template/crash115.C
+++ b/gcc/testsuite/g++.dg/template/crash115.C
@@ -1,4 +1,3 @@
// PR c++/56534
template < struct template rebind < > // { dg-error "expected|must follow" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/template/crash132.C b/gcc/testsuite/g++.dg/template/crash132.C
new file mode 100644
index 0000000..f6f4863
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash132.C
@@ -0,0 +1,6 @@
+// PR c++/97993
+// { dg-do compile { target c++14 } }
+
+template <class T> T a;
+template <class T, class A, class=decltype(::new T (A()))> auto foo ();
+struct S decltype (foo <int, S>); // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/template/crash43.C b/gcc/testsuite/g++.dg/template/crash43.C
index 3647a17..ae644ed 100644
--- a/gcc/testsuite/g++.dg/template/crash43.C
+++ b/gcc/testsuite/g++.dg/template/crash43.C
@@ -5,4 +5,3 @@ extern "C" {
struct ___is_pod {
enum {
__value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "expected|declared" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/template/crash90.C b/gcc/testsuite/g++.dg/template/crash90.C
index e2a58e3..125ab0a 100644
--- a/gcc/testsuite/g++.dg/template/crash90.C
+++ b/gcc/testsuite/g++.dg/template/crash90.C
@@ -5,5 +5,4 @@ struct A ;
template < typename >
struct B ;
template < typename T , A < B < T > {} // { dg-error "parse error|non-type|initializer" }
-
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "39:expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/error-recovery1.C b/gcc/testsuite/g++.dg/template/error-recovery1.C
index 6f9ce6d..9625714 100644
--- a/gcc/testsuite/g++.dg/template/error-recovery1.C
+++ b/gcc/testsuite/g++.dg/template/error-recovery1.C
@@ -7,4 +7,3 @@ template < typename > struct T
template < bool > struct T < S > // { dg-error "" }
{
void f () { // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/template/error25.C b/gcc/testsuite/g++.dg/template/error25.C
index 8901157..77b59cd 100644
--- a/gcc/testsuite/g++.dg/template/error25.C
+++ b/gcc/testsuite/g++.dg/template/error25.C
@@ -12,5 +12,5 @@ extern void f2 ();
template<>
extern void f2<void> (); // { dg-error "explicit template specialization cannot have a storage class" }
-export template<class T> // { dg-warning "keyword 'export' not implemented" }
+export template<class T> // { dg-warning "keyword 'export'" }
static void* f3 ();
diff --git a/gcc/testsuite/g++.dg/template/error57.C b/gcc/testsuite/g++.dg/template/error57.C
index 121fbb1..f67e0a6 100644
--- a/gcc/testsuite/g++.dg/template/error57.C
+++ b/gcc/testsuite/g++.dg/template/error57.C
@@ -2,4 +2,4 @@
template <int()> struct a;
template <int(b)> a < b // { dg-error "int" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/lookup16.C b/gcc/testsuite/g++.dg/template/lookup16.C
new file mode 100644
index 0000000..5b34c08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/lookup16.C
@@ -0,0 +1,23 @@
+// PR c++/94799
+// { dg-do compile { target c++11 } }
+
+template <typename> struct A {
+ typedef int type;
+ operator int();
+};
+
+template <typename T> using B = A<T>;
+
+template <typename T> typename B<T>::type foo(B<T> b)
+{
+ auto r1 = b.operator typename A<T>::type();
+ auto r2 = b.operator typename A<T>::template A<T>::type();
+ auto r3 = b.operator typename B<T>::type();
+ auto r4 = b.operator typename B<T>::template A<T>::type();
+ return r1 + r2 + r3 + r4;
+}
+
+void bar()
+{
+ foo(A<int>());
+}
diff --git a/gcc/testsuite/g++.dg/template/pr98115.C b/gcc/testsuite/g++.dg/template/pr98115.C
new file mode 100644
index 0000000..0bfc57a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr98115.C
@@ -0,0 +1,4 @@
+// PR 98115, dependent array types lead to specialization issues
+
+template <class> class Stringify;
+template <long N> class Stringify<const char[N]>;
diff --git a/gcc/testsuite/g++.dg/template/pr98116-2.C b/gcc/testsuite/g++.dg/template/pr98116-2.C
new file mode 100644
index 0000000..fd12bb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr98116-2.C
@@ -0,0 +1,34 @@
+// PR 98116, ICE with stripping typedef array type
+// { dg-do compile { target c++11 } }
+// { dg-additional-options {--param=hash-table-verification-limit=10000000 -fchecking=2} }
+
+// We got confused by alias templates that alias the same type. Their
+// hashes were different (good), but they compared equal (bad)
+
+namespace std {
+typedef int is_convertible;
+template <typename _Tp> using remove_pointer_t = typename _Tp ::type;
+template <bool> struct enable_if;
+template <typename> void declval();
+template <bool _Cond> using enable_if_t = typename enable_if<_Cond>::type;
+template <typename, typename> class Trans_NS___cxx11_basic_string {
+ long _M_string_length;
+};
+} // namespace std
+struct string16_char_traits;
+template class std::Trans_NS___cxx11_basic_string<unsigned short,
+ string16_char_traits>;
+template <typename, typename> using IsLegalDataConversion = std::is_convertible;
+template <typename Container, typename T>
+using ContainerHasConvertibleData = IsLegalDataConversion<
+ std::remove_pointer_t<decltype(std::declval<Container>)>, T>;
+template <typename Array, typename T, long>
+using EnableIfSpanCompatibleArray =
+ std::enable_if_t<!!sizeof (ContainerHasConvertibleData<Array, T>)>;
+template <int Extent> class span {
+ template <long N, EnableIfSpanCompatibleArray<
+ const std::Trans_NS___cxx11_basic_string<
+ unsigned short, string16_char_traits>[N],
+ std::Trans_NS___cxx11_basic_string<short, int>, Extent>>
+ span();
+};
diff --git a/gcc/testsuite/g++.dg/template/pr98116.C b/gcc/testsuite/g++.dg/template/pr98116.C
new file mode 100644
index 0000000..7d54314
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr98116.C
@@ -0,0 +1,34 @@
+// PR 98116, ICE with stripping typedef array type
+// { dg-do compile { target c++11 } }
+// { dg-additional-options {--param=hash-table-verification-limit=10000000 -fchecking=2} }
+
+// We got confused by alias templates that alias the same type. Their
+// hashes were different (good), but they compared equal (bad)
+
+namespace std {
+struct is_convertible;
+template <typename _Tp> using remove_pointer_t = typename _Tp ::type;
+template <bool> struct enable_if;
+template <typename> void declval();
+template <bool _Cond> using enable_if_t = typename enable_if<_Cond>::type;
+template <typename, typename> class Trans_NS___cxx11_basic_string {
+ long _M_string_length;
+};
+} // namespace std
+struct string16_char_traits;
+template class std::Trans_NS___cxx11_basic_string<unsigned short,
+ string16_char_traits>;
+template <typename, typename> using IsLegalDataConversion = std::is_convertible;
+template <typename Container, typename T>
+using ContainerHasConvertibleData = IsLegalDataConversion<
+ std::remove_pointer_t<decltype(std::declval<Container>)>, T>;
+template <typename Array, typename T, long>
+using EnableIfSpanCompatibleArray =
+ std::enable_if_t<ContainerHasConvertibleData<Array, T>::value>;
+template <int Extent> class span {
+ template <long N, EnableIfSpanCompatibleArray<
+ const std::Trans_NS___cxx11_basic_string<
+ unsigned short, string16_char_traits>[N],
+ std::Trans_NS___cxx11_basic_string<short, int>, Extent>>
+ span();
+};
diff --git a/gcc/testsuite/g++.dg/template/pr98297.C b/gcc/testsuite/g++.dg/template/pr98297.C
new file mode 100644
index 0000000..0dd63a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr98297.C
@@ -0,0 +1,6 @@
+// PR 98297, ICE
+// { dg-do compile { target c++11 } }
+template <template <class> class a>
+struct [[b]]
+a <int>; // { dg-error "does not declare anything" }
+// { dg-warning "ignored" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/scope5.C b/gcc/testsuite/g++.dg/template/scope5.C
index cf23a08..b20d897 100644
--- a/gcc/testsuite/g++.dg/template/scope5.C
+++ b/gcc/testsuite/g++.dg/template/scope5.C
@@ -59,7 +59,7 @@ template <typename av> struct ac : ao<av> { typedef c::e<am::an> aq; };
template <typename aw, typename i, typename ax> void ay(aw, i, ax) {
// Not sure if this has been creduced from an initialization of a
// variable to a block-scope extern function decl
- au<c::e<ap<typename ak<i>::o>::f> > az2();
+ au<c::e<ap<typename ak<i>::o>::f> > az2(); // { dg-warning "empty parentheses" }
}
void v() {
ad a;
diff --git a/gcc/testsuite/g++.dg/template/sfinae-dr657.C b/gcc/testsuite/g++.dg/template/sfinae-dr657.C
index b78b5a9..36c11e6 100644
--- a/gcc/testsuite/g++.dg/template/sfinae-dr657.C
+++ b/gcc/testsuite/g++.dg/template/sfinae-dr657.C
@@ -1,6 +1,7 @@
-// DR 657
-// Test that a return or parameter type with abstract class type causes a
-// deduction failure.
+// DR 657 SUPERSEDED BY DR 1646
+// Test that a return or parameter type with abstract class type DOES NOT cause
+// a deduction failure, but there is no implicit conversion sequence for
+// a parameter of abstract class type.
struct A
{
@@ -17,6 +18,6 @@ template<class T> int arg(...);
int main()
{
- int i = declval<A>();
+ int i = declval<A>(); // { dg-error "ambiguous" }
i = arg<A>(1);
}
diff --git a/gcc/testsuite/g++.dg/torture/builtin-clear-padding-1.C b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-1.C
new file mode 100644
index 0000000..625a047
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-1.C
@@ -0,0 +1,31 @@
+/* PR libstdc++/88101 */
+
+struct S {} s1, s2;
+struct T : public S { char a; short b; char c; } t1, t2;
+struct U : public T { char d; long long e; char f; } u1, u2;
+
+__attribute__((noipa)) void
+foo (T *t, U *u)
+{
+ int i;
+ t->a = -1; t->b = -1; t->c = -1;
+ u->a = -1; u->b = -1; u->c = -1; u->d = -1; u->e = -1; u->f = -1;
+}
+
+int
+main ()
+{
+ __builtin_memset (&s2, -1, sizeof (s2));
+ __builtin_memset (&t2, -1, sizeof (t2));
+ __builtin_memset (&u2, -1, sizeof (u2));
+ foo (&t1, &u1);
+ foo (&t2, &u2);
+ __builtin_clear_padding (&s2);
+ __builtin_clear_padding (&t2);
+ __builtin_clear_padding (&u2);
+ if (__builtin_memcmp (&s1, &s2, sizeof (s1))
+ || __builtin_memcmp (&t1, &t2, sizeof (t1))
+ || __builtin_memcmp (&u1, &u2, sizeof (u1)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/torture/builtin-clear-padding-2.C b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-2.C
new file mode 100644
index 0000000..19cc78f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-2.C
@@ -0,0 +1,34 @@
+/* PR libstdc++/88101 */
+
+#include <new>
+
+struct S { char a; short b; char c; long long d; char e; decltype (nullptr) f; char g; };
+alignas (S) unsigned char buf1[sizeof (S)];
+alignas (S) unsigned char buf2[sizeof (S)];
+
+template <int N>
+void
+foo ()
+{
+ __builtin_clear_padding ((S *) buf2);
+}
+
+void
+bar (S *s)
+{
+ s->a = -1; s->b = -1; s->c = -1; s->d = -1; s->e = -1; s->g = -1;
+}
+
+int
+main ()
+{
+ S *s1 = new (buf1) S;
+ S *s2 = new (buf2) S;
+ __builtin_memset (s1, 0, sizeof (S));
+ __builtin_memset (s2, ~0, sizeof (S));
+ bar (s1);
+ bar (s2);
+ foo <0> ();
+ if (__builtin_memcmp (s1, s2, sizeof (S)) != 0)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C
new file mode 100644
index 0000000..d528196
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C
@@ -0,0 +1,24 @@
+/* PR libstdc++/88101 */
+
+struct D { int a; int : 24; int b : 8; };
+struct E {};
+struct F { char c, d, e; };
+struct G : public D, E, F { int f; } g1, g2;
+
+__attribute__((noipa)) void
+foo (G *g)
+{
+ g->a = -1; g->b = -1; g->c = -1; g->d = -1; g->e = -1; g->f = -1;
+}
+
+int
+main ()
+{
+ __builtin_memset (&g2, -1, sizeof (g2));
+ foo (&g1);
+ foo (&g2);
+ __builtin_clear_padding (&g2);
+ if (__builtin_memcmp (&g1, &g2, sizeof (g1)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr81659.C b/gcc/testsuite/g++.dg/torture/pr81659.C
index 3696957..074099b 100644
--- a/gcc/testsuite/g++.dg/torture/pr81659.C
+++ b/gcc/testsuite/g++.dg/torture/pr81659.C
@@ -12,7 +12,7 @@ a (int b)
catch (int)
{
}
- catch (int)
+ catch (int) // { dg-warning "will be caught by earlier handler" }
{
}
}
diff --git a/gcc/testsuite/g++.dg/torture/pr93347.C b/gcc/testsuite/g++.dg/torture/pr93347.C
index 3b5cc26..6e3b1af 100644
--- a/gcc/testsuite/g++.dg/torture/pr93347.C
+++ b/gcc/testsuite/g++.dg/torture/pr93347.C
@@ -1,306 +1,20 @@
// { dg-additional-options "--param early-inlining-insns=3 --param ipa-cp-eval-threshold=100" }
-namespace Test1 {
- struct A {
- virtual int f() final;
- };
- // CHECK-LABEL: define i32 @_ZN5Test11fEPNS_1AE
- int f(A *a) {
- // CHECK: call i32 @_ZN5Test11A1fEv
- return a->f();
- }
-}
-
-namespace Test2 {
- struct A final {
- virtual int f();
- };
-
- // CHECK-LABEL: define i32 @_ZN5Test21fEPNS_1AE
- int f(A *a) {
- // CHECK: call i32 @_ZN5Test21A1fEv
- return a->f();
- }
-}
-
-namespace Test2a {
- struct A {
- virtual ~A() final {}
- virtual int f();
- };
-
- // CHECK-LABEL: define i32 @_ZN6Test2a1fEPNS_1AE
- int f(A *a) {
- // CHECK: call i32 @_ZN6Test2a1A1fEv
- return a->f();
- }
-}
-
-
-namespace Test3 {
- struct A {
- virtual int f(); };
-
- struct B final : A { };
-
- // CHECK-LABEL: define i32 @_ZN5Test31fEPNS_1BE
- int f(B *b) {
- // CHECK: call i32 @_ZN5Test31A1fEv
- return b->f();
- }
-
- // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE
- int f(B &b) {
- // CHECK: call i32 @_ZN5Test31A1fEv
- return b.f();
- }
-
- // CHECK-LABEL: define i32 @_ZN5Test31fEPv
- int f(void *v) {
- // CHECK: call i32 @_ZN5Test31A1fEv
- return static_cast<B*>(v)->f();
- }
-}
-
-namespace Test4 {
- struct A {
- virtual void f();
- virtual int operator-();
- };
-
- struct B final : A {
- virtual void f();
- virtual int operator-();
- };
-
- // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE
- void f(B* d) {
- // CHECK: call void @_ZN5Test41B1fEv
- static_cast<A*>(d)->f();
- // CHECK: call i32 @_ZN5Test41BngEv
- -static_cast<A&>(*d);
- }
-}
-
-namespace Test5 {
- struct A {
- virtual void f();
- virtual int operator-();
- };
-
- struct B : A {
- virtual void f();
- virtual int operator-();
- };
-
- struct C final : B {
- };
-
- // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE
- void f(C* d) {
- // FIXME: It should be possible to devirtualize this case, but that is
- // not implemented yet.
- // CHECK: getelementptr
- // CHECK-NEXT: %[[FUNC:.*]] = load
- // CHECK-NEXT: call void %[[FUNC]]
- static_cast<A*>(d)->f();
- }
- // CHECK-LABEL: define void @_ZN5Test53fopEPNS_1CE
- void fop(C* d) {
- // FIXME: It should be possible to devirtualize this case, but that is
- // not implemented yet.
- // CHECK: getelementptr
- // CHECK-NEXT: %[[FUNC:.*]] = load
- // CHECK-NEXT: call i32 %[[FUNC]]
- -static_cast<A&>(*d);
- }
-}
-
-namespace Test6 {
- struct A {
- virtual ~A();
- };
-
- struct B : public A {
- virtual ~B();
- };
-
- struct C {
- virtual ~C();
- };
-
- struct D final : public C, public B {
- };
-
- // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE
- void f(D* d) {
- // CHECK: call void @_ZN5Test61DD1Ev
- static_cast<A*>(d)->~A();
- }
-}
-
-namespace Test7 {
- struct foo {
- virtual void g() {}
- };
-
- struct bar {
- virtual int f() { return 0; }
- };
-
- struct zed final : public foo, public bar {
- int z;
- virtual int f() {return z;}
- };
-
- // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE
- int f(zed *z) {
- // CHECK: alloca
- // CHECK-NEXT: store
- // CHECK-NEXT: load
- // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv
- // CHECK-NEXT: ret
- return static_cast<bar*>(z)->f();
- }
-}
-
-namespace Test8 {
- struct A { virtual ~A() {} };
- struct B {
- int b;
- virtual int foo() { return b; }
- };
- struct C final : A, B { };
- // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE
- int test(C *c) {
- // CHECK: %[[THIS:.*]] = phi
- // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
- return static_cast<B*>(c)->foo();
- }
-}
-
-namespace Test9 {
- struct A {
- int a;
- };
- struct B {
- int b;
- };
- struct C : public B, public A {
- };
- struct RA {
- virtual A *f() {
- return 0;
- }
- virtual A *operator-() {
- return 0;
- }
- };
- struct RC final : public RA {
- virtual C *f() {
- C *x = new C();
- x->a = 1;
- x->b = 2;
- return x;
- }
- virtual C *operator-() {
- C *x = new C();
- x->a = 1;
- x->b = 2;
- return x;
- }
- };
- // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
- A *f(RC *x) {
- // FIXME: It should be possible to devirtualize this case, but that is
- // not implemented yet.
- // CHECK: load
- // CHECK: bitcast
- // CHECK: [[F_PTR_RA:%.+]] = bitcast
- // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]]
- // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0
- // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
- // CHECK-NEXT: = call {{.*}} %[[FUNC]]
- return static_cast<RA*>(x)->f();
- }
- // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE
- A *fop(RC *x) {
- // FIXME: It should be possible to devirtualize this case, but that is
- // not implemented yet.
- // CHECK: load
- // CHECK: bitcast
- // CHECK: [[F_PTR_RA:%.+]] = bitcast
- // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]]
- // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1
- // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
- // CHECK-NEXT: = call {{.*}} %[[FUNC]]
- return -static_cast<RA&>(*x);
- }
-}
-
-namespace Test10 {
- struct A {
- virtual int f();
- };
-
- struct B : A {
- int f() final;
- };
-
- // CHECK-LABEL: define i32 @_ZN6Test101fEPNS_1BE
- int f(B *b) {
- // CHECK: call i32 @_ZN6Test101B1fEv
- return static_cast<A *>(b)->f();
- }
-}
-
-namespace Test11 {
- // Check that the definitions of Derived's operators are emitted.
-
- // CHECK-LABEL: define linkonce_odr void @_ZN6Test111SIiE4foo1Ev(
- // CHECK: call void @_ZN6Test111SIiE7DerivedclEv(
- // CHECK: call zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE(
- // CHECK: call zeroext i1 @_ZN6Test111SIiE7DerivedntEv(
- // CHECK: call dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi(
- // CHECK: define linkonce_odr void @_ZN6Test111SIiE7DerivedclEv(
- // CHECK: define linkonce_odr zeroext i1 @_ZN6Test111SIiE7DerivedeqERKNS_4BaseE(
- // CHECK: define linkonce_odr zeroext i1 @_ZN6Test111SIiE7DerivedntEv(
- // CHECK: define linkonce_odr dereferenceable(4) %"class.Test11::Base"* @_ZN6Test111SIiE7DerivedixEi(
- class Base {
- public:
- virtual void operator()() {}
- virtual bool operator==(const Base &other) { return false; }
- virtual bool operator!() { return false; }
- virtual Base &operator[](int i) { return *this; }
- };
-
- template<class T>
- struct S {
- class Derived final : public Base {
- public:
- void operator()() override {}
- bool operator==(const Base &other) override { return true; }
- bool operator!() override { return true; }
- Base &operator[](int i) override { return *this; }
- };
-
- Derived *ptr = nullptr, *ptr2 = nullptr;
-
- void foo1() {
- if (ptr && ptr2) {
- // These calls get devirtualized. Linkage fails if the definitions of
- // the called functions are not emitted.
- (*ptr)();
- (void)(*ptr == *ptr2);
- (void)(!(*ptr));
- (void)((*ptr)[1]);
- }
- }
- };
-
- void foo2() {
- S<int> *s = new S<int>;
- s->foo1();
- }
-}
+struct A {
+ int a;
+};
+struct B {
+ int b;
+};
+struct C : B, A {};
+struct RA {
+ virtual A *operator-();
+};
+struct RC : RA {
+ C *operator-() {
+ C *x = new C();
+ return x;
+ }
+};
+void fop(RC *x) { -static_cast<RA &>(*x); }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/if-to-switch-1.C b/gcc/testsuite/g++.dg/tree-ssa/if-to-switch-1.C
new file mode 100644
index 0000000..5cb3a7e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/if-to-switch-1.C
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+
+void fancy_abort(const char *, int, const char *);
+
+enum machine_mode
+{
+ MODE_FLOAT,
+ MODE_DECIMAL_FLOAT,
+ MODE_COMPLEX_INT,
+ MODE_COMPLEX_FLOAT,
+ MODE_VECTOR_BOOL,
+ MODE_VECTOR_FLOAT
+} extern const mode_class;
+
+void tree_node() {
+ if (mode_class)
+ mode_class == MODE_FLOAT || mode_class == MODE_DECIMAL_FLOAT ||
+ mode_class == MODE_COMPLEX_FLOAT || mode_class == MODE_VECTOR_FLOAT
+ ? fancy_abort("aaa", 2, __FUNCTION__),
+ 0 : 0;
+ int g = 0;
+}
+
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr90883.C b/gcc/testsuite/g++.dg/tree-ssa/pr90883.C
index 0e622f2..37df17d 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr90883.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr90883.C
@@ -15,6 +15,6 @@
// We want to match enough here to capture that we deleted an empty
// constructor store
-// aarch64 and mips will expand to loop to clear because CLEAR_RATIO.
-// { dg-final { scan-tree-dump "Deleted redundant store: .*\.a = {}" "dse1" { xfail { aarch64-*-* mips*-*-* } } } }
+// mips will expand to loop to clear because CLEAR_RATIO.
+// { dg-final { scan-tree-dump "Deleted redundant store: .*\.a = {}" "dse1" { xfail { mips*-*-* } } } }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr97736.C b/gcc/testsuite/g++.dg/tree-ssa/pr97736.C
new file mode 100644
index 0000000..bda77e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr97736.C
@@ -0,0 +1,12 @@
+/* PR tree-optimization/97736 */
+/* { dg-do compile { target { { x86_64-*-* aarch64-*-* ia64-*-* powerpc64-*-* } && lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-switchlower1" } */
+
+bool is_vowel(char c) {
+ switch (c)
+ case'a':case'e':case'i':case'o':case'u':
+ return true;
+ return false;
+}
+
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:97-117" "switchlower1" } } */
diff --git a/gcc/testsuite/g++.dg/ubsan/align-4.C b/gcc/testsuite/g++.dg/ubsan/align-4.C
new file mode 100644
index 0000000..42c091b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/align-4.C
@@ -0,0 +1,31 @@
+// PR c++/98206
+// { dg-do run }
+// { dg-options "-fsanitize=alignment -std=c++11 -fno-sanitize-recover=alignment" }
+
+template <typename Derived>
+struct Base1
+{
+ char c1;
+};
+
+template <typename Derived>
+struct Base2
+{
+ char c2;
+ const Derived &get2 () const { return static_cast<const Derived &> (*this); }
+};
+
+struct X : public Base1<X>, public Base2<X>
+{
+ X (const char *d) : data{d} {}
+ const char *data;
+};
+
+int
+main ()
+{
+ X x = X{"cheesecake"};
+ const char *p = x.get2 ().data;
+ if (p[0] != 'c')
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/pr61272.C b/gcc/testsuite/g++.dg/ubsan/pr61272.C
index 11dd1ec..cb4751e 100644
--- a/gcc/testsuite/g++.dg/ubsan/pr61272.C
+++ b/gcc/testsuite/g++.dg/ubsan/pr61272.C
@@ -12,10 +12,10 @@ namespace std
};
namespace __gnu_cxx
{
- template < typename _Alloc > struct __alloc_traits:std::allocator_traits < _Alloc > // { dg-error "within this context" }
+ template < typename _Alloc > struct __alloc_traits:std::allocator_traits < _Alloc >
{
typedef std::allocator_traits < _Alloc > _Base_type;
- using _Base_type::construct;
+ using _Base_type::construct; // { dg-error "within this context" }
};
template < typename _Tp, typename _Alloc > struct _Vector_base { typedef typename __gnu_cxx::__alloc_traits < _Alloc >::template rebind < _Tp >::other _Tp_alloc_type; }; // { dg-error "no class template" }
template < typename _Tp, typename _Alloc = std::allocator < _Tp > >class vector : protected _Vector_base < _Tp, _Alloc > { };
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-18.C b/gcc/testsuite/g++.dg/ubsan/vptr-18.C
new file mode 100644
index 0000000..cd2ca0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/vptr-18.C
@@ -0,0 +1,25 @@
+// PR c++/98103
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+// Modified constexpr-dynamic17.C.
+
+struct V {
+ virtual void f();
+};
+
+struct A : V { };
+
+struct B : V {
+ constexpr B(V*, A*);
+};
+
+struct D : B, A {
+ constexpr D() : B((A*)this, this) { }
+};
+
+constexpr B::B(V* v, A* a)
+{
+ dynamic_cast<B*>(a); // { dg-error "uninitialized" }
+}
+
+constexpr D d;
diff --git a/gcc/testsuite/g++.dg/vect/pr98064.cc b/gcc/testsuite/g++.dg/vect/pr98064.cc
new file mode 100644
index 0000000..74043ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr98064.cc
@@ -0,0 +1,25 @@
+// { dg-do compile }
+// { dg-additional-options "-O3" }
+
+const long long &min(const long long &__a, long long &__b) {
+ if (__b < __a)
+ return __b;
+ return __a;
+}
+extern long var_2;
+extern int var_3, var_8;
+extern long long var_5;
+extern unsigned short arr_353[];
+extern short arr_362[];
+extern int arr_518[];
+void test() {
+ for (char d = 0; d < 013; d += 4) {
+ for (char e = 0; e < 11; e++)
+ arr_353[e] = var_2 | min((long long)7, var_5);
+ for (int f = var_5; f; f += 4)
+ for (short g = var_8; g; g++)
+ arr_362[g] = 0;
+ }
+ for (short h = 5; (short)var_2; h += 5)
+ arr_518[h] = 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-11.cc b/gcc/testsuite/g++.dg/vect/simd-11.cc
new file mode 100644
index 0000000..912d184
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-11.cc
@@ -0,0 +1,61 @@
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-additional-options "-Ofast" }
+
+template <typename> class h {
+public:
+ ~h();
+};
+template <typename> struct l;
+template <typename c> struct l<h<c> > {
+ using d = c;
+ template <typename e> using f = h<e>;
+};
+template <typename g> struct o {
+ typedef l<g> j;
+ typedef typename j::d k;
+ template <typename c> struct p { typedef typename j::f<c> m; };
+};
+template <typename c, typename g> struct F {
+ typedef typename o<g>::p<c>::m q;
+ struct : q {
+ } r;
+};
+template <typename c, typename g = h<c> > class s : F<c, g> {
+public:
+ s(long);
+ typename o<typename F<c, g>::q>::k operator[](long);
+};
+template <int> class t {
+public:
+ int dimension;
+ t(const t &);
+ void operator+=(t);
+ double values[];
+};
+template <int dim> t<dim>::t(const t &p1) {
+ for (int i = 0; i < dim; ++i)
+ values[i] = p1.values[i];
+}
+template <int dim> class u : public t<dim> {
+public:
+ double m_fn1(const u &) const;
+};
+template <int dim> double u<dim>::m_fn1(const u &) const {
+ double a;
+ for (int i = 0; i < dim; ++i) {
+ double b = this->values[i];
+ a += b;
+ }
+ return a;
+}
+int m_fn2(const u<2> &p1, const u<2> &w) {
+ int n;
+ s<u<2> > c(n);
+ s<double> d(n);
+ double e = p1.m_fn1(w);
+ for (;;) {
+ c[0] += p1;
+ d = e;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-12.cc b/gcc/testsuite/g++.dg/vect/simd-12.cc
new file mode 100644
index 0000000..a3f18d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-12.cc
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ffast-math -g" } */
+
+template <typename> class complex;
+template <typename _Tp> complex<_Tp> operator+(complex<_Tp>, complex<_Tp> __y) {
+ complex<_Tp> __r;
+ __r += __y;
+ return __r;
+}
+template <typename _Tp> complex<_Tp> operator*(complex<_Tp>, complex<_Tp> __y) {
+ complex<_Tp> __r;
+ __r *= __y;
+ return __r;
+}
+template <> class complex<double> {
+public:
+ void operator+=(complex __z) { _M_value += __z.__rep(); }
+ void operator*=(complex __z) {
+ _Complex __t = __z.__rep();
+ _M_value *= __t;
+ }
+ _Complex __rep() { return _M_value; }
+ _Complex _M_value;
+};
+template <typename> class Vector {
+ void equ();
+ complex<double> *val;
+};
+template <typename Number> void Vector<Number>::equ() {
+ Number c;
+ for (int i; i; ++i) {
+ complex<double> __trans_tmp_2 = c * val[i];
+ val[i] = val[i] + __trans_tmp_2;
+ }
+}
+template class Vector<complex<double> >;
diff --git a/gcc/testsuite/g++.dg/vect/slp-pr97636.cc b/gcc/testsuite/g++.dg/vect/slp-pr97636.cc
new file mode 100644
index 0000000..0123420
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/slp-pr97636.cc
@@ -0,0 +1,83 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target c++17 } */
+
+struct u {
+ int b;
+ int c;
+ template <typename d, typename e> u(d, e);
+};
+template <class, class> struct f { u g; };
+template <class h, class i> class v {
+ typedef f<h, i> k;
+ k *l[4];
+ k m;
+public:
+ v(h, h);
+ void aa(h, i);
+};
+template <class h, class i> void v<h, i>::aa(h, i) { n(&l[1], &m); }
+template <class h, class i> void n(f<h, i> **o, f<h, i> *ab) {
+ bool p, r;
+ f q = **o;
+ f<h, i> *t;
+ h a = q.g;
+ h b = t->g;
+ if (r)
+ ;
+ else
+ goto ac;
+s:
+ p = a.b || a.c < b.c;
+ if (p)
+ goto s;
+ac:
+ ab->g = b;
+ b = t->g;
+ goto s;
+}
+template <class, class, class> class w {};
+template <class> class x;
+template <class, class> class z;
+class ad {
+public:
+ template <typename, typename y, typename ae, typename af, typename ag>
+ static void ah(const z<y, ae> &, const z<y, af> &, x<ag> *&);
+};
+template <typename, typename y, typename ae, typename af, typename ag>
+void ad::ah(const z<y, ae> &ai, const z<y, af> &aj, x<ag> *&) {
+ u c(0, 0), d(0, 0), g(aj, ai);
+ v<u, y> e(c, d);
+ e.aa(g, 0);
+}
+template <class, class> class ak;
+template <class, class, class al, class am, class an>
+void ao(ak<al, am> ap, ak<al, an> aq) {
+ x<double> *f;
+ ad::ah<int>(*ap.ar, *aq.ar, f);
+}
+template <typename, typename, typename al, typename am, typename an,
+ typename as, typename at>
+void au(w<al, am, as> ap, w<al, an, at> aq) {
+ ao<int, double>(static_cast<as &>(ap), static_cast<at &>(aq));
+}
+template <class, class> class z {};
+template <class, class> class ak : public w<int, int, ak<int, int>> {
+public:
+ z<int, int> *ar;
+};
+template <class, class, class> class av;
+template <typename, typename, typename, typename al, typename am, typename an,
+ typename aw, typename ax>
+void ay(av<al, am, aw>, av<al, an, ax>) {
+ aw h, i;
+ au<int, double>(h, i);
+}
+template <class, class, class> class av {};
+class az {
+public:
+ typedef av<int, double, ak<int, double>> ba;
+};
+int main() {
+ az::ba j, k;
+ ay<int, double, az>(j, k);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-14.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-14.C
new file mode 100644
index 0000000..0812f83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-14.C
@@ -0,0 +1,25 @@
+/* PR middle-end/97595 - bogus -Wstringop-overflow due to DECL_SIZE_UNIT
+ underreporting field size
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+struct A { char a[32]; };
+struct B: virtual A { };
+struct C: B { };
+
+struct D
+{
+ B &b;
+ D (B&);
+};
+
+D::D (B &b): b (b) { } // { dg-bogus "-Warray-bounds" }
+
+void f (void*);
+
+void g ()
+{
+ C c;
+ D d (c);
+ f (&d);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-8.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-8.C
index 6db2013..6e0d7f3 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-8.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-8.C
@@ -3,7 +3,7 @@
See Wstringop-overflow-3.C for the same test that exercises the other
warning.
{ dg-do compile }
- { dg-options "-O2 -Wall -Wno-stringop-overflow" }
+ { dg-options "-O2 -Wall -Wno-stringop-overflow -fno-ipa-icf" }
{ dg-skip-if "" { *-*-aix* } } */
void sink (void*);
diff --git a/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C b/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C
index 424eb0c..01f691f 100644
--- a/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C
+++ b/gcc/testsuite/g++.dg/warn/Wdiv-by-zero-3.C
@@ -5,8 +5,10 @@ foo (T t, int i)
{
int m1 = 10 / t;
int m2 = 10 / i;
- int m3 = 10 / (sizeof(T) - sizeof(int)); // { dg-warning "division by" }
- int m4 = 10 / N; // { dg-warning "division by" }
+ // People don't want to see warnings for type- or value-dependent
+ // expressions.
+ int m3 = 10 / (sizeof(T) - sizeof(int)); // { dg-bogus "division by" }
+ int m4 = 10 / N; // { dg-bogus "division by" }
return m1 + m2 + m3 + m4;
}
diff --git a/gcc/testsuite/g++.dg/warn/Wexceptions1.C b/gcc/testsuite/g++.dg/warn/Wexceptions1.C
new file mode 100644
index 0000000..af140fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wexceptions1.C
@@ -0,0 +1,9 @@
+// PR c++/97675
+
+struct Base { };
+struct Child : Base { };
+int main() {
+ try { throw Child(); }
+ catch (Base const&) { }
+ catch (Child const&) { } // { dg-warning "exception of type .Child. will be caught by earlier handler" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wexceptions2.C b/gcc/testsuite/g++.dg/warn/Wexceptions2.C
new file mode 100644
index 0000000..07c5155
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wexceptions2.C
@@ -0,0 +1,10 @@
+// PR c++/97675
+// { dg-additional-options -Wno-exceptions }
+
+struct Base { };
+struct Child : Base { };
+int main() {
+ try { throw Child(); }
+ catch (Base const&) { }
+ catch (Child const&) { } // { dg-bogus "exception of type .Child. will be caught by earlier handler" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wexceptions3.C b/gcc/testsuite/g++.dg/warn/Wexceptions3.C
new file mode 100644
index 0000000..97fda9d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wexceptions3.C
@@ -0,0 +1,29 @@
+// PR c++/81660
+
+void bar (int);
+
+void
+fn (int b)
+{
+ if (b)
+ throw;
+ try
+ {
+ bar (3);
+ }
+ catch (int)
+ {
+ }
+ catch (int) // { dg-warning "will be caught by earlier handler" }
+ {
+ }
+ catch (const int) // { dg-warning "will be caught by earlier handler" }
+ {
+ }
+ catch (int &) // { dg-warning "will be caught by earlier handler" }
+ {
+ }
+ catch (const int &) // { dg-warning "will be caught by earlier handler" }
+ {
+ }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C
new file mode 100644
index 0000000..9d4d2a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C
@@ -0,0 +1,274 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern "C"
+{
+ void free (void*);
+ extern void* malloc (size_t);
+ extern void* realloc (void *p, size_t);
+}
+
+void sink (void*, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = (void*)warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = (char*)"123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = (char*)"234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = (char*)"345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = (char*)"456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ void *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-3.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-3.C
new file mode 100644
index 0000000..47f97dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-3.C
@@ -0,0 +1,38 @@
+/* PR c++/57111 - Generalize -Wfree-nonheap-object to delete
+ Verify that even without -Wsystem-headers the warning is issued
+ for pairs of library functions defined in system headers.
+ { dg-do compile { target c++11 } }
+ { dg-options "-O2 -Wall" } */
+
+#include <memory>
+#include <string>
+
+void test_string ()
+{
+ std::string str ("abc"); // { dg-message "declared here" }
+
+ const char *s = str.c_str ();
+ __builtin_printf ("%s\n", s);
+
+ /* Because the delete call is made directly in the function this
+ does not exercise the same thing as test_unique_ptr. */
+ delete s; // { dg-warning "'void operator delete\\(void\\*\[^\\)\]*\\)' called on unallocated object 'str'" }
+}
+
+void test_unique_ptr ()
+{
+ int arr[]= { 1, 2 }; // { dg-message "declared here" }
+
+ std::unique_ptr<int[]> up (arr);
+ __builtin_printf ("%i %i\n", up[0], up[1]);
+
+ /* TO DO: verify that the warning is printed, including its inlining
+ context (the directive below doesn't work):
+ { Xdg-message "In member function.*inlined from 'void test_unique_ptr\\(\\)'.*warning: 'void operator delete \\\[]\\(void\\*\\)' called on unallocated object 'arr'" "" { target *-*-* } 0 } */
+
+ /* Here, the delete call is made indirectly from std::unique_ptr
+ dtor. */
+}
+
+/* Prune out the warning from test_unique_ptr().
+ { dg-prune-output "-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-4.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-4.C
new file mode 100644
index 0000000..943ef0c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-4.C
@@ -0,0 +1,26 @@
+/* PR middle-end/98160: bogus -Wfree-nonheap-object calling member delete
+ on the result of inline member new plus offset
+ { dg-do compile }
+ { dg-options "-O2" } */
+
+struct MemoryManager { void* allocate (); };
+
+struct XMemory
+{
+ void* operator new (__SIZE_TYPE__, MemoryManager *mgr)
+ {
+ void *p = mgr->allocate ();
+ return (char*)p + sizeof(MemoryManager);
+ }
+
+ void operator delete (void*, MemoryManager*);
+};
+
+struct XMLMutex: XMemory {
+ XMLMutex();
+};
+
+void gValidatorMutex (MemoryManager *mgr)
+{
+ new (mgr) XMLMutex; // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C
new file mode 100644
index 0000000..82b081a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C
@@ -0,0 +1,124 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempts to deallocate objects by pointers with nonzero
+ offsets is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+char* source (void);
+
+void nowarn_op_delete (void *p, void ***ppp, size_t n, intptr_t iptr)
+{
+ operator delete (p);
+
+ p = 0;
+ operator delete (p);
+
+ p = operator new (n);
+ sink (p);
+ operator delete (p);
+
+ p = operator new (n);
+ sink (p);
+
+ operator delete ((void*)iptr);
+
+ p = source ();
+ operator delete (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ operator delete (p);
+
+ operator delete (**ppp);
+ operator delete (*ppp);
+ operator delete (ppp);
+}
+
+void warn_op_delete_cstaddr (void *p)
+{
+ operator delete (p);
+ p = (void*)~0;
+ operator delete (p); // { dg-warning "called on a pointer to an unallocated object" } */
+}
+
+void warn_op_delete_funcaddr ()
+{
+ void *p = (void*)&warn_op_delete_funcaddr;
+ operator delete (p); // { dg-warning "called on unallocated object 'void warn_op_delete_funcaddr()" } */
+}
+
+void warn_op_delete_string (void *p)
+{
+ operator delete (p);
+ p = (void*)"";
+ operator delete (p); // { dg-warning "called on a pointer to an unallocated object" } */
+}
+
+void warn_op_delete_ptr_to_self (void *p)
+{
+ operator delete (p);
+ p = &p;
+ operator delete (p); // { dg-warning "called on unallocated object 'p'" } */
+}
+
+void nowarn_op_new_delete (size_t n)
+{
+ void *p = operator new (n);
+ sink (p);
+ operator delete (p);
+}
+
+void nowarn_op_new_delete_ptr_plus (size_t n)
+{
+ void *p0_1 = operator new (n);
+ void *p1 = (char*)p0_1 + 1;
+ sink (p0_1, p1);
+ void *p0_2 = (char*)p1 - 1;
+ sink (p0_1, p1, p0_2);
+ operator delete (p0_2);
+}
+
+void warn_op_new_delete_cstoff (size_t n)
+{
+ void *p = operator new (n);
+ void *q = (char*)p + 1;
+ sink (p, q);
+ operator delete (q); // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer '\[^'\]+' with nonzero offset 1" }
+}
+
+void warn_op_new_delete_ptr_plus (size_t n)
+{
+ char *p = (char*)operator new (n);
+ sink (++p);
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset 1" }
+}
+
+void warn_op_delete_funcret_plus (size_t n)
+{
+ char *p = source ();
+ sink (++p);
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset 1" }
+}
+
+void warn_op_delete_eptr_plus (int i)
+{
+ extern char *ecp;
+
+ if (i < 1)
+ i = 1;
+
+ char *p = ecp + i;
+ sink (p);
+
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset \\\[1, \\d+]" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s
diff --git a/gcc/testsuite/g++.dg/warn/Winit-list4.C b/gcc/testsuite/g++.dg/warn/Winit-list4.C
new file mode 100644
index 0000000..d136187
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winit-list4.C
@@ -0,0 +1,15 @@
+// PR c++/97632
+// { dg-do compile { target c++20 } }
+// Test we don't warn in an unevaluated operand.
+
+#include <initializer_list>
+
+template<typename _Tp>
+concept default_initializable
+ = requires
+ {
+ _Tp{};
+ (void) ::new _Tp; // { dg-bogus "does not extend the lifetime" }
+ };
+
+static_assert(default_initializable<std::initializer_list<int>>);
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C
new file mode 100644
index 0000000..3aea02f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C
@@ -0,0 +1,185 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ The detection doesn't require optimization.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void free (void *);
+ void* realloc (void *, size_t);
+}
+
+void sink (void *);
+
+void mydealloc (int, void*);
+void* A (mydealloc, 2) myalloc (void*);
+
+
+void my_delete (const char*, void*);
+void my_array_delete (const char*, void*);
+
+typedef void OpDelete1 (void*);
+typedef void OpDelete2 (void*, size_t);
+
+A ((OpDelete1*)operator delete, 1)
+#if __cplusplus >= 201402L
+A ((OpDelete2*)operator delete, 1)
+#endif
+A (my_delete, 2)
+int* my_new (size_t);
+
+A ((OpDelete1*)operator delete[], 1)
+#if __cplusplus >= 201402L
+A ((OpDelete2*)operator delete[], 1)
+#endif
+A (my_array_delete, 2)
+int* my_array_new (size_t);
+
+
+void test_my_new ()
+{
+ {
+ void *p = my_new (1);
+ operator delete (p);
+ }
+ {
+ void *p = my_new (1);
+ sink (p);
+ operator delete (p);
+ }
+ {
+ int *p = my_new (1);
+ sink (p);
+ delete p;
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ operator delete[] (p);
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete[] (p);
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ int *p = my_new (1);
+ sink (p);
+ delete[] p;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ my_delete ("1", p);
+ }
+ {
+ void *p = my_new (1);
+ sink (p);
+ my_delete ("2", p);
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ my_array_delete ("3", p);
+ // { dg-warning "'void my_array_delete\\\(const char\\\*, void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, 123);
+ // { dg-warning "'void\\\* realloc\\\(void\\\*, size_t\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+void test_my_array_new ()
+{
+ {
+ void *p = my_array_new (1);
+ operator delete[] (p);
+ }
+ {
+ void *p = my_array_new (1);
+ sink (p);
+ operator delete[] (p);
+ }
+ {
+ int *p = my_array_new (1);
+ sink (p);
+ delete[] p;
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ int *p = my_array_new (1);
+ sink (p);
+ delete p;
+ // { dg-warning "'void operator delete\\\(void\\\*\[^\)\]*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ my_array_delete ("1", p);
+ }
+ {
+ void *p = my_array_new (1);
+ sink (p);
+ my_array_delete ("2", p);
+ }
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ my_delete ("3", p);
+ // { dg-warning "'void my_delete\\\(const char\\\*, void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, 123);
+ // { dg-warning "'void\\\* realloc\\\(void\\\*, size_t\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C
new file mode 100644
index 0000000..682db6f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C
@@ -0,0 +1,27 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ { dg-do compile { target c++11 } }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef __SIZE_TYPE__ size_t;
+
+void mydealloc (int, void*);
+void* A (mydealloc, 2) myalloc (void*);
+
+
+void* A (operator delete, 1)
+ bad_new (size_t); // { dg-error "attribute argument 1 is ambiguous" }
+void* A (operator delete[], 1)
+ bad_array_new (size_t); // { dg-error "attribute argument 1 is ambiguous" }
+
+void my_delete (const char*, void*);
+void my_array_delete (const char*, void*);
+
+typedef void OpDelete (void*);
+
+int* A ((OpDelete*)operator delete, 1) A (my_delete, 2)
+ my_new (size_t);
+int* A ((OpDelete*)operator delete[], 1) A (my_array_delete, 2)
+ my_array_new (size_t);
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-2.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-2.C
new file mode 100644
index 0000000..d0d53b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-2.C
@@ -0,0 +1,249 @@
+/* Verify that implicit and explicit calls to member operator new and delete
+ are handled correctly.
+ { dg-do compile }
+ { dg-options "-Wmismatched-new-delete" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std
+{
+#if __cplusplus >= 201703L
+enum class align_val_t: size_t { };
+#else
+enum align_val_t { };
+#endif
+
+struct nothrow_t { };
+const nothrow_t nothrow = { };
+}
+
+void sink (void*, ...);
+
+struct POD
+{
+ void* operator new (size_t);
+ void operator delete (void*);
+
+ void* operator new[] (size_t);
+ void operator delete[] (void*);
+};
+
+POD* nowarn_pod ()
+{
+ POD *p = new POD;
+ delete p;
+ return new POD;
+}
+
+void warn_pod_array_mismatch ()
+{
+ POD *p = new POD;
+ delete[] p; // { dg-warning "'static void POD::operator delete \\\[]\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+ p = new POD[3];
+ delete p; // { dg-warning "'static void POD::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+}
+
+
+struct X1
+{
+ X1 ();
+
+ void* operator new (size_t);
+ void* operator new (size_t, std::align_val_t);
+ void* operator new (size_t, std::nothrow_t) throw ();
+ void* operator new (size_t, std::align_val_t, std::nothrow_t) throw ();
+
+ void* operator new[] (size_t);
+ void* operator new[] (size_t, std::align_val_t);
+ void* operator new[] (size_t, std::nothrow_t) throw ();
+ void* operator new[] (size_t, std::align_val_t, std::nothrow_t) throw ();
+
+ void operator delete (void*);
+ void operator delete (void*, size_t);
+ void operator delete (void*, std::align_val_t);
+ void operator delete (void*, size_t, std::align_val_t);
+ void operator delete (void*, std::nothrow_t) throw ();
+ void operator delete (void*, std::align_val_t, std::nothrow_t) throw ();
+
+ void operator delete[] (void*);
+ void operator delete[] (void*, size_t);
+ void operator delete[] (void*, std::align_val_t);
+ void operator delete[] (void*, size_t, std::align_val_t);
+ void operator delete[] (void*, std::nothrow_t) throw ();
+ void operator delete[] (void*, std::align_val_t, std::nothrow_t) throw ();
+};
+
+X1* nowarn_x1 ()
+{
+ return new X1;
+}
+
+X1* nowarn_x1_array ()
+{
+ return new X1[2];
+}
+
+X1* nowarn_align_val ()
+{
+ X1 *p = new (std::align_val_t (32)) X1;
+ delete p;
+ return new (std::align_val_t (64)) X1;
+}
+
+X1* nowarn_align_val_array ()
+{
+ X1 *p = new (std::align_val_t (32)) X1[2];
+ delete[] p;
+ return new (std::align_val_t (64)) X1[2];
+}
+
+X1* nowarn_x1_nothrow ()
+{
+ X1 *p = new (std::nothrow) X1;
+ delete p;
+ return new (std::nothrow) X1;
+}
+
+X1* nowarn_x1_nothrow_array ()
+{
+ X1 *p = new (std::nothrow) X1[3];
+ delete[] p;
+ return new (std::nothrow) X1[3];
+}
+
+X1* nowarn_align_val_nothrow ()
+{
+ X1 *p = new (std::align_val_t (32), std::nothrow) X1;
+ delete p;
+ return new (std::align_val_t (64), std::nothrow) X1;
+}
+
+X1* nowarn_align_val_nothrow_array ()
+{
+ X1 *p = new (std::align_val_t (32), std::nothrow) X1[4];
+ delete[] p;
+ return new (std::align_val_t (64), std::nothrow) X1[4];
+}
+
+void warn_x1_array_mismatch ()
+{
+ {
+ X1 *p = new X1;
+ delete[] p; // { dg-warning "'static void X1::operator delete \\\[]\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ X1 *p = new X1[2];
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ X1 *p = new (std::align_val_t (32)) X1[2];
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ // The following requires optimization (see warn_x1_array_mismatch()).
+ X1 *p = new (std::nothrow) X1[3];
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" "pr?????" { xfail *-*-* } }
+ }
+}
+
+#pragma GCC push_options
+#pragma GCC optimize "1"
+
+void warn_x1_nothrow_array_mismatch ()
+{
+ X1 *p = new (std::nothrow) X1[3];
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+}
+
+#pragma GCC pop_options
+
+
+struct X2: X1
+{
+ X2 ();
+
+ void* operator new (size_t);
+ void operator delete (void*);
+};
+
+X2* nowarn_x2 ()
+{
+ X2 *p = new X2;
+ sink (p);
+ return new X2;
+}
+
+void warn_x2 ()
+{
+ X1 *p = new X2; // { dg-message "returned from 'static void\\* X2::operator new\\(size_t\\)'" "note" }
+ sink (p);
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+}
+
+namespace N {
+namespace NS {
+namespace NmSpc {
+namespace NameSpace {
+
+namespace dl { // same name as operator delete
+namespace nw { // and as operator new
+
+struct X3: X2
+{
+ X3 ();
+
+ void* operator new (size_t);
+ void operator delete (void*);
+};
+
+X3* nowarn_x3 ()
+{
+ X3 *p = new X3;
+ sink (p);
+ return new X3;
+}
+
+void warn_x3 ()
+{
+ X1 *p = new X3; // { dg-message "returned from 'static void\\* N::NS::NmSpc::NameSpace::dl::nw::X3::operator new\\(size_t\\)'" "note" }
+ sink (p);
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+}
+
+template <int N>
+struct X4: X2
+{
+ X4 ();
+
+ void* operator new (size_t);
+ void operator delete (void*);
+};
+
+void* nowarn_x4 ()
+{
+ X4<0> *p = new X4<0>;
+ sink (p);
+ return new X4<1>;
+}
+
+void warn_x4 ()
+{
+ X1 *p = new X4<1>; // { dg-message "returned from 'static void\\* N::NS::NmSpc::NameSpace::dl::nw::X4<N>::operator new\\(size_t\\) \\\[with int N = 1]'" "note" }
+ sink (p);
+ delete p; // { dg-warning "'static void X1::operator delete\\(void\\*\\)' called on pointer returned from a mismatched allocation function" }
+}
+
+void warn_x4_inst_mismatch ()
+{
+ void *p = new X4<2>; // { dg-message "returned from 'static void\\* N::NS::NmSpc::NameSpace::dl::nw::X4<N>::operator new\\(size_t\\) \\\[with int N = 2]'" "note" }
+ sink (p);
+ X4<3> *q = (X4<3>*)p;
+ delete q; // { dg-warning "'static void N::NS::NmSpc::NameSpace::dl::nw::X4<N>::operator delete\\(void\\*\\) \\\[with int N = 3]' called on pointer returned from a mismatched allocation function" }
+}
+
+} // nw
+} // dl
+} // NameSpace
+} // NmSpc
+} // NS
+} // N
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C
new file mode 100644
index 0000000..fc07149
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C
@@ -0,0 +1,212 @@
+/* PR c++/90629 - Support for -Wmismatched-new-delete
+ The detection doesn't require optimization.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void free (void *);
+ void* malloc (size_t);
+ void* realloc (void *, size_t);
+ char* strdup (const char *);
+ char* strndup (const char *, size_t);
+}
+
+void sink (void *);
+
+void nowarn_op_new_delete (int n)
+{
+ void *p = operator new (n);
+ sink (p);
+ operator delete (p);
+}
+
+void nowarn_new_delete (int n)
+{
+ {
+ char *p = new char;
+ sink (p);
+ delete p;
+ }
+
+ {
+ char *p = new char[n];
+ sink (p);
+ delete[] p;
+ }
+}
+
+/* Verify a warning for calls to free() with a pointer returned from
+ a call to operator new() or the new expressopm. */
+
+void warn_new_free (int n)
+{
+ {
+ void *p = operator new (n);
+ // { dg-message "returned from 'void\\\* operator new\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+ {
+ char *p = new char[n];
+ // { dg-message "returned from 'void\\\* operator new \\\[" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for calls to realloc() with a pointer returned from
+ a call to operator new() or the new expressopm. */
+
+void warn_new_realloc (int n)
+{
+ {
+ void *p = operator new (n);
+ // { dg-message "returned from 'void\\\* operator new\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, n * 2);
+ // { dg-warning "'void\\\* realloc\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ sink (p);
+ }
+ {
+ void *p = new char[n];
+ // { dg-message "returned from 'void\\\* operator new \\\[" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, n * 2);
+ // { dg-warning "'void\\\* realloc\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ sink (p);
+ }
+}
+
+
+/* Verify a warning for a call to operator_delete() with a pointer returned
+ from a call to malloc(). */
+
+void warn_malloc_op_delete (int n)
+{
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from malloc(). */
+
+void warn_malloc_delete (int n)
+{
+ {
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete p;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ delete[] p;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from realloc(). */
+
+void warn_realloc_delete (void *p1, void *p2, int n)
+{
+ {
+ char *q = (char *)realloc (p1, n);
+ // { dg-message "returned from 'void\\\* realloc\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = (char *)realloc (p2, n);
+ // { dg-message "returned from 'void\\\* realloc\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from strdup(). */
+
+void warn_strdup_delete (const char *s1, const char *s2)
+{
+ {
+ char *q = strdup (s1);
+ // { dg-message "returned from 'char\\\* strdup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = strdup (s2);
+ // { dg-message "returned from 'char\\\* strdup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from strndup(). */
+
+void warn_strdup_delete (const char *s1, const char *s2, size_t n)
+{
+ {
+ char *q = strndup (s1, n);
+ // { dg-message "returned from 'char\\\* strndup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = strndup (s2, n);
+ // { dg-message "returned from 'char\\\* strndup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+struct Base { virtual ~Base (); };
+struct Derived: Base { };
+
+void warn_new_free_base_derived ()
+{
+ Base *p = new Derived ();
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wmismatched-new-delete" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull5.C b/gcc/testsuite/g++.dg/warn/Wnonnull5.C
index 8b25d2d..78862d4 100644
--- a/gcc/testsuite/g++.dg/warn/Wnonnull5.C
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull5.C
@@ -36,7 +36,7 @@ struct S
void warn_nullptr_this ()
{
((S*)nullptr)->f0 (""); // { dg-warning "3:'this' pointer null" "pr86568" { xfail *-*-* } }
- // { dg-warning "this' pointer null" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "this' pointer null" "pr86568 second variant" { target *-*-* } .-1 }
}
void warn_null_this_cst ()
@@ -49,15 +49,15 @@ void warn_null_this_var ()
{
S* null = 0;
null->f2 (&null); // { dg-warning "3:'this' pointer null" "pr86568" { xfail *-*-* } }
- // { dg-warning "'this' pointer null" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "'this' pointer null" "pr86568 second variant" { target *-*-* } .-1 }
}
void warn_nullptr (S s)
{
s.f3 (nullptr, &s); // { dg-warning "9:argument 1 null where non-null expected" "pr86568" { xfail *-*-* } }
- // { dg-warning "argument 1 null where non-null expected" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "argument 1 null where non-null expected" "pr86568 second variant" { target *-*-* } .-1 }
s.f3 (&s, nullptr); // { dg-warning "13:argument 2 null where non-null expected" "pr86568" { xfail *-*-* } }
- // { dg-warning "argument 2 null where non-null expected" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "argument 2 null where non-null expected" "pr86568 second variant" { target *-*-* } .-1 }
}
@@ -72,9 +72,9 @@ void warn_null_var (S s)
{
void* null = 0;
s.f5 (null, &s); // { dg-warning "9:argument 1 null where non-null expected" "pr86568" { xfail *-*-* } }
- // { dg-warning "argument 1 null where non-null expected" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "argument 1 null where non-null expected" "pr86568 second variant" { target *-*-* } .-1 }
s.f5 (&s, null); // { dg-warning "16:argument 2 null where non-null expected" "pr86568" { xfail *-*-* } }
- // { dg-warning "argument 2 null where non-null expected" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "argument 2 null where non-null expected" "pr86568 second variant" { target *-*-* } .-1 }
}
void warn_null_cond (S s, void *null)
@@ -83,9 +83,9 @@ void warn_null_cond (S s, void *null)
return;
s.f6 (null, &s); // { dg-warning "9:argument 1 null where non-null expected" "pr86568" { xfail *-*-* } }
- // { dg-warning "argument 1 null where non-null expected" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "argument 1 null where non-null expected" "pr86568 second variant" { target *-*-* } .-1 }
s.f6 (&s, null); // { dg-warning "13:argument 2 null where non-null expected" "pr86568" { xfail *-*-* } }
- // { dg-warning "argument 2 null where non-null expected" "pr86568" { target *-*-* } .-1 }
+ // { dg-warning "argument 2 null where non-null expected" "pr86568 second variant" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-8.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-8.C
index 77bd331..12cd4cd 100644
--- a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-8.C
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-8.C
@@ -43,7 +43,7 @@ void test_cst_off ()
/* Offsets are treated as signed so SIZE_MAX is indistinguishable
from -1. */
char ca1[1]; // { dg-message "at offset \\d+ from 'ca1' declared here" "note" { xfail *-*-* } }
- // { dg-message "at offset -1 from 'ca1' declared here" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset -1 from 'ca1' declared here" "note second variant" { target *-*-* } .-1 }
new (ca1 + SIZE_MAX) S<1>; // { dg-warning "constructing an object of type 'S<1>' and size '1' in a region of type 'char \\\[1]' and size '0'" }
}
}
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size.C
index 48d6b15..25325b3 100644
--- a/gcc/testsuite/g++.dg/warn/Wplacement-new-size.C
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size.C
@@ -332,11 +332,11 @@ void test (void *p, int32_t n)
new (&uac2.c) int32_t; // { dg-warning "placement" }
new (&uac3.c) int32_t; // { dg-warning "placement" }
- // Diagnose the following even though the size of uac4.c could be
- // expected to extend to the end of the union (as it is by Built-in
- // Object Size and so isn't diagnosed in calls to functions like
- // memset(&uac4.c, 0, sizeof(int32_t)) when _FORTIFY_SOURCE is non-zero. */
- new (&uac4.c) int32_t; // { dg-warning "placement" }
+ /* The following isn't diagnosed (anymore) for consistency with
+ the middle end where members of unions are considered to extend
+ to the end of the enclosing object.
+ See gcc.dg/Wstringop-overflow-60.c for the middle end test. */
+ new (&uac4.c) int32_t;
new (&uac4.c + 1) int32_t; // { dg-warning "placement" }
}
diff --git a/gcc/testsuite/g++.dg/warn/Wrange-loop-construct2.C b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct2.C
new file mode 100644
index 0000000..5bb08cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct2.C
@@ -0,0 +1,212 @@
+// PR c++/94695
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wrange-loop-construct" }
+
+struct Foo { };
+struct Bar {
+ char arr[100];
+ Bar(Foo);
+ Bar(int);
+ operator int();
+};
+
+template<typename T>
+struct It {
+ T operator*();
+ It operator++();
+ bool operator!=(const It);
+};
+
+template<typename T>
+struct Cont {
+ using I = It<T>;
+ I begin();
+ I end();
+};
+
+void
+fn1 ()
+{
+ int arr[10];
+ Cont<int> cont_int;
+
+ for (const double &x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const double x : arr) { (void) x; }
+ for (const int &x : arr) { (void) x; }
+ for (double &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (double x : arr) { (void) x; }
+
+ for (const int &&x : cont_int) { (void) x; }
+ for (const int &x : cont_int) { (void) x; }
+ for (const int x : cont_int) { (void) x; }
+ for (int&& x : cont_int) { (void) x; }
+ for (int x : cont_int) { (void) x; }
+
+ for (const double &&x : cont_int) { (void) x; }
+ for (const double &x : cont_int) { (void) x; }
+ for (const double x : cont_int) { (void) x; }
+
+ for (double &&x : cont_int) { (void) x; }
+ for (double x : cont_int) { (void) x; }
+
+ for (const Bar &&x : cont_int) { (void) x; }
+ for (const Bar x : cont_int) { (void) x; }
+}
+
+void
+fn2 ()
+{
+ Cont<int &> cont_int_ref;
+
+ for (const int &x : cont_int_ref) { (void) x; }
+ for (const int x : cont_int_ref) { (void) x; }
+ for (int &x : cont_int_ref) { (void) x; }
+ for (int x : cont_int_ref) { (void) x; }
+
+ for (const double &&x : cont_int_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const double &x : cont_int_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const double x : cont_int_ref) { (void) x; }
+ for (double &&x : cont_int_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (double x : cont_int_ref) { (void) x; }
+
+ for (const Bar &&x : cont_int_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar &x : cont_int_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar x : cont_int_ref) { (void) x; }
+ for (Bar &&x : cont_int_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (Bar x : cont_int_ref) { (void) x; }
+}
+
+void
+fn3 ()
+{
+ Cont<Bar> cont_bar;
+
+ for (const Bar &&x : cont_bar) { (void) x; }
+ for (const Bar &x : cont_bar) { (void) x; }
+ for (const Bar x : cont_bar) { (void) x; }
+ for (Bar &&x : cont_bar) { (void) x; }
+ for (Bar x : cont_bar) { (void) x; }
+
+ for (const int &&x : cont_bar) { (void) x; }
+ for (const int &x : cont_bar) { (void) x; }
+ for (const int x : cont_bar) { (void) x; }
+ for (int &&x : cont_bar) { (void) x; }
+ for (int x : cont_bar) { (void) x; }
+}
+
+void
+fn4 ()
+{
+ Cont<Bar &> cont_bar_ref;
+
+ for (const Bar &x : cont_bar_ref) { (void) x; }
+ for (Bar &x : cont_bar_ref) { (void) x; }
+ for (Bar x : cont_bar_ref) { (void) x; }
+
+ for (const int &&x : cont_bar_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const int &x : cont_bar_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const int x : cont_bar_ref) { (void) x; }
+ for (int &&x : cont_bar_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (int x : cont_bar_ref) { (void) x; }
+}
+
+void
+fn5 ()
+{
+ Cont<Foo> cont_foo;
+
+ for (const Bar &&x : cont_foo) { (void) x; }
+ for (const Bar &x : cont_foo) { (void) x; }
+ for (const Bar x : cont_foo) { (void) x; }
+ for (Bar &&x : cont_foo) { (void) x; }
+ for (Bar x : cont_foo) { (void) x; }
+}
+
+void
+fn6 ()
+{
+ Cont<Foo &> cont_foo_ref;
+
+ for (const Bar &&x : cont_foo_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar &x : cont_foo_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar x : cont_foo_ref) { (void) x; }
+ for (Bar &&x : cont_foo_ref) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (Bar x : cont_foo_ref) { (void) x; }
+}
+
+void
+fn7 ()
+{
+ double arr[2];
+
+ for (const double &x : arr) { (void) x; }
+ for (const double x : arr) { (void) x; }
+ for (double &x : arr) { (void) x; }
+ for (double x : arr) { (void) x; }
+
+ for (const int &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const int &x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const int x : arr) { (void) x; }
+ for (int &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (int x : arr) { (void) x; }
+
+ for (const Bar &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar &x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar x : arr) { (void) x; }
+ for (Bar &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (Bar x : arr) { (void) x; }
+}
+
+void
+fn8 ()
+{
+ Foo arr[2];
+
+ for (const Foo &x : arr) { (void) x; }
+ for (const Foo x : arr) { (void) x; }
+ for (Foo &x : arr) { (void) x; }
+ for (Foo x : arr) { (void) x; }
+
+ for (const Bar &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar &x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const Bar x : arr) { (void) x; }
+ for (Bar &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (Bar x : arr) { (void) x; }
+}
+
+void
+fn9 ()
+{
+ Bar arr[2] = { 1, 2 };
+
+ for (const Bar &x : arr) { (void) x; }
+ for (Bar &x : arr) { (void) x; }
+ for (Bar x : arr) { (void) x; }
+
+ for (const int &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const int &x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (const int x : arr) { (void) x; }
+ for (int &&x : arr) { (void) x; } // { dg-warning "binds to a temporary constructed from type" }
+ for (int x : arr) { (void) x; }
+}
+
+template<typename T>
+void
+fn10 ()
+{
+ Cont<Bar> cont_bar;
+
+ for (const Bar &x : cont_bar) { (void) x; }
+
+ Cont<T> cont_dep;
+ for (const T &x : cont_dep) { (void) x; }
+}
+template void fn10<Bar>();
+
+struct S {
+ void fn()
+ {
+ Cont<Bar> cont_bar;
+ for (const Bar &x : cont_bar) { (void) x; }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wsequence-point-4.C b/gcc/testsuite/g++.dg/warn/Wsequence-point-4.C
new file mode 100644
index 0000000..b3d9cf1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsequence-point-4.C
@@ -0,0 +1,53 @@
+// PR c++/98126
+// { dg-do compile }
+// { dg-options "-Wsequence-point" }
+// Make sure we don't hang when verify_tree processes a large expression.
+
+struct T { bool operator==(const T &ot) const; };
+
+#define CMP(M, N, L) t[100 * M + 10 * N + L] == ot.t[100 * M + 10 * N + L] &&
+
+#define CMP1(M, N) \
+ CMP(M, N, 0) \
+ CMP(M, N, 1) \
+ CMP(M, N, 2) \
+ CMP(M, N, 3) \
+ CMP(M, N, 4) \
+ CMP(M, N, 5) \
+ CMP(M, N, 6) \
+ CMP(M, N, 7) \
+ CMP(M, N, 8) \
+ CMP(M, N, 9)
+
+#define CMP2(M) \
+ CMP1(M, 0) \
+ CMP1(M, 1) \
+ CMP1(M, 2) \
+ CMP1(M, 3) \
+ CMP1(M, 4) \
+ CMP1(M, 5) \
+ CMP1(M, 6) \
+ CMP1(M, 7) \
+ CMP1(M, 8) \
+ CMP1(M, 9)
+
+#define GENERATE_CMPS \
+ CMP2(0) \
+ CMP2(1) \
+ CMP2(2) \
+ CMP2(3) \
+ CMP2(4) \
+ CMP2(5) \
+ CMP2(6) \
+ CMP2(7) \
+ CMP2(8) \
+ CMP2(9)
+
+struct C {
+ bool operator==(const C &ot) const {
+ return
+ GENERATE_CMPS
+ true;
+ }
+ T t[999];
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C
index da9ad6f..c68e82a 100644
--- a/gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C
+++ b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C
@@ -12,7 +12,7 @@ void sink (void*);
struct Ax
{
char n;
- char a[]; // { dg-message "at offset \[0-2\] to object 'Ax::a' declared here" "note: flexarray" }
+ char a[]; // { dg-message "destination object 'Ax::a' of size 0" "note: flexarray" }
};
// Verify warning for a definition with no initializer.
@@ -93,7 +93,7 @@ NOIPA void gaxx ()
struct A0
{
char n;
- char a[0]; // { dg-message "at offset \[0-2\] to object 'A0::a' with size 0 declared here" "note: trailing zero-length array" }
+ char a[0]; // { dg-message "destination object 'A0::a' of size 0" "note: trailing zero-length array" }
};
// Verify warning for a definition with no initializer.
@@ -160,7 +160,7 @@ NOIPA void ga0x ()
struct A1
{
char n;
- char a[1]; // { dg-message "at offset \[1-9\] to object 'A1::a' with size 1 declared here" "note: trailing one-element array" }
+ char a[1]; // { dg-message "at offset \[1-2\] into destination object 'A1::a' of size 1" "note: trailing one-element array" }
};
// Verify warning for a definition with no initializer.
@@ -234,7 +234,7 @@ NOIPA void ga1x ()
struct A1i
{
char n;
- char a[1]; // { dg-message "at offset \[1-9\] to object 'A1i::a' with size 1 declared here" "note: interior one-element array" }
+ char a[1]; // { dg-message "at offset \[1-2\] into destination object 'A1i::a' of size 1" "note: interior one-element array" }
char x;
};
@@ -307,7 +307,7 @@ NOIPA void ga1ix ()
struct Bx
{
char n;
- char a[]; // { dg-message "at offset 0 to object 'Bx::a' declared here" "note: flexarray class member" }
+ char a[]; // { dg-message "destination object 'Bx::a' of size 0" "note: flexarray class member" }
// Verify the warning for a constant.
Bx () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
@@ -332,7 +332,7 @@ NOIPA void gbxi (int i)
struct B0
{
char n;
- char a[0]; // { dg-message "at offset 0 to object 'B0::a' with size 0 declared here" "note: zero-length trailing array class member" }
+ char a[0]; // { dg-message "destination object 'B0::a' of size 0" "note: zero-length trailing array class member" }
B0 () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
@@ -348,7 +348,7 @@ NOIPA void gb0 (void)
struct B1
{
char n;
- char a[1]; // { dg-message "at offset 1 to object 'B1::a' with size 1 declared here" "note: one-element trailing array class member" }
+ char a[1]; // { dg-message "at offset 1 into destination object 'B1::a' of size 1" "note: one-element trailing array class member" }
B1 () { a[1] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
@@ -362,7 +362,7 @@ NOIPA void gb1 (void)
struct B123
{
- char a[123]; // { dg-message "at offset 123 to object 'B123::a' with size 123 declared here" "note: large trailing array class member" }
+ char a[123]; // { dg-message "at offset 123 into destination object 'B123::a' of size 123" "note: large trailing array class member" }
B123 () { a[123] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
@@ -376,7 +376,7 @@ NOIPA void gb123 (void)
struct B234
{
- char a[234]; // { dg-message "at offset 234 to object 'B234::a' with size 234 declared here" "note: large trailing array class member" }
+ char a[234]; // { dg-message "at offset 234 into destination object 'B234::a' of size 234" "note: large trailing array class member" }
B234 (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
diff --git a/gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C
new file mode 100644
index 0000000..8173e60
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-6.C
@@ -0,0 +1,8 @@
+/* PR middle-end/97595 - bogus -Wstringop-overflow due to DECL_SIZE_UNIT
+ underreporting field size
+ { dg-do compile { target c++11 } }
+ { dg-options "-O2 -Wall -Wsystem-headers" } */
+
+#include <iostream>
+
+template void std::basic_iostream<char>::swap (basic_iostream&);
diff --git a/gcc/testsuite/g++.dg/warn/Wtautological-compare3.C b/gcc/testsuite/g++.dg/warn/Wtautological-compare3.C
new file mode 100644
index 0000000..89bf1b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wtautological-compare3.C
@@ -0,0 +1,11 @@
+// PR c++/96675
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wtautological-compare" }
+
+template<char c>
+constexpr bool f(char d) {
+ return 'a' <= c && c <= 'z' ? (d | 0x20) == c :
+ 'A' <= c && c <= 'Z' ? (d & ~0x20) == c :
+ d == c;
+}
+static_assert(f<'p'>('P'), "");
diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits5.C b/gcc/testsuite/g++.dg/warn/Wtype-limits5.C
new file mode 100644
index 0000000..5e79123
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits5.C
@@ -0,0 +1,11 @@
+// PR c++/96742
+// { dg-additional-options "-Wtype-limits" }
+
+template <unsigned N>
+bool f(unsigned x) {
+ return unsigned(x < N);
+}
+
+int main() {
+ f<0>(1);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse.C
new file mode 100644
index 0000000..b02e904
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse.C
@@ -0,0 +1,110 @@
+// PR c++/25814
+// { dg-do compile }
+// Test -Wvexing-parse.
+
+struct T { };
+
+struct X {
+ X();
+};
+
+struct S {
+ S(int);
+ S foo (int (int));
+ S(T);
+ int m;
+};
+
+struct W {
+ W();
+ W(X, X);
+ int m;
+};
+
+int g;
+int g1(int(g));
+int g2(int());
+void fg(int);
+
+void
+fn1 (double (a))
+{
+ extern int f0();
+ extern int f1(int(a));
+ int f2(int(a)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ int (*f3)(int(a));
+ int f4(int a);
+ int f5(int()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ int f6(...);
+ int f7((int(a)));
+ int (f8);
+ int f9(S(s)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ int(f10) __attribute__(());
+ int(f11(int()));
+ if (int(a) = 1) { }
+ int j, k, l(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ int m, f12(int(j)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+
+ T t1(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ T t2(T()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ /* Declares a variable t3. */
+ T(t3);
+ T t4(), // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ t5(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+
+ extern S s1(int(a));
+ S s2(int(a)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ S s3(int a);
+ S s4(int()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ S s5(int(int)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ S s6(...);
+ S s7((int(a)));
+ S s8((int)a);
+ S s9 = int(a);
+ S(T());
+ S s10(S()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ S s11(T());
+ S s12(X()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ S s13 = S(T());
+ S(T()).foo(0);
+ S (S::*foo)(int (int));
+ S(*s14)(int(a));
+ S s15(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ S s16(void);
+
+ /* Don't warn here. */
+ void fv1(int(a));
+ void fv2(int());
+ void (fv3)();
+ void (fv4)(void);
+ void (fv5)(int);
+
+ int n(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ int (n2)(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ int n3(void);
+
+ typedef int F(const char*);
+ typedef int F2();
+ typedef int F3() const;
+ typedef int F4(int(a)) const;
+
+ W w(X(), X()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+}
+
+struct C1 {
+ C1(int);
+};
+
+struct C2 {
+ C2(C1, int);
+};
+
+template<int N> int value() { return N; }
+
+void
+fn2 ()
+{
+ int i = 0;
+ C2 c2(C1(int(i)), i);
+ C1(value<0>());
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse2.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse2.C
new file mode 100644
index 0000000..0dbeb72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse2.C
@@ -0,0 +1,24 @@
+// PR c++/25814
+// { dg-do compile { target c++11 } }
+// Test -Wvexing-parse. C++11 features.
+
+struct X { };
+struct T {
+ T(X);
+};
+
+void
+fn1 (double (a))
+{
+ auto l = [](){
+ int f(int(a)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ };
+
+ [[noreturn]] int(e)(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+
+ T t1{X()};
+ T t2(X{});
+ T t3{X{}};
+
+ using U = int();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse3.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse3.C
new file mode 100644
index 0000000..43fcdf2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse3.C
@@ -0,0 +1,129 @@
+// PR c++/25814
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fdiagnostics-show-caret" }
+// Test -Wvexing-parse's fix-it hints in C++11.
+
+#include <initializer_list>
+
+struct X { };
+
+struct S {
+ S(X);
+ S(std::initializer_list<X>);
+ int m;
+};
+
+struct T {
+ T(X);
+ int m;
+};
+
+struct W {
+ W();
+ W(std::initializer_list<X>);
+ int m;
+};
+
+struct U {
+ U();
+ int m;
+};
+
+int
+main ()
+{
+ /*
+ Careful what we're suggesting:
+ S a((X())) -> S(X)
+ S a({X()}) -> (std::initializer_list<X>)
+ S a{X()} -> (std::initializer_list<X>)
+ */
+ S a(X()); // { dg-warning "6:parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ S a(X());
+ ^~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:add parentheses to declare a variable" "" { target *-*-* } 41 }
+ /* { dg-begin-multiline-output "" }
+ S a(X());
+ ^~~~~
+ ( )
+ { dg-end-multiline-output "" } */
+
+ T t(X()); // { dg-warning "6:parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ T t(X());
+ ^~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:replace parentheses with braces to declare a variable" "" { target *-*-* } 53 }
+ /* { dg-begin-multiline-output "" }
+ T t(X());
+ ^~~~~
+ -
+ { -
+ }
+ { dg-end-multiline-output "" } */
+
+ int n( ); // { dg-warning "8:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ int n( );
+ ^~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "8:remove parentheses to default-initialize a variable" "" { target *-*-* } 67 }
+ /* { dg-begin-multiline-output "" }
+ int n( );
+ ^~~~~
+ -----
+ { dg-end-multiline-output "" } */
+ // { dg-message "8:or replace parentheses with braces to value-initialize a variable" "" { target *-*-* } 67 }
+
+ S s(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ S s();
+ ^~
+ { dg-end-multiline-output "" } */
+
+ X x(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ X x();
+ ^~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:remove parentheses to default-initialize a variable" "" { target *-*-* } 86 }
+ /* { dg-begin-multiline-output "" }
+ X x();
+ ^~
+ --
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:or replace parentheses with braces to aggregate-initialize a variable" "" { target *-*-* } 86 }
+
+ W w(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ W w();
+ ^~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:remove parentheses to default-initialize a variable" "" { target *-*-* } 99 }
+ /* { dg-begin-multiline-output "" }
+ W w();
+ ^~
+ --
+ { dg-end-multiline-output "" } */
+
+ T t2(); // { dg-warning "7:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ T t2();
+ ^~
+ { dg-end-multiline-output "" } */
+
+ U u(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ U u();
+ ^~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:remove parentheses to default-initialize a variable" "" { target *-*-* } 117 }
+ /* { dg-begin-multiline-output "" }
+ U u();
+ ^~
+ --
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:or replace parentheses with braces to value-initialize a variable" "" { target *-*-* } 117 }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse4.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse4.C
new file mode 100644
index 0000000..3e010aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse4.C
@@ -0,0 +1,74 @@
+// PR c++/25814
+// { dg-do compile { target c++98_only } }
+// { dg-additional-options "-fdiagnostics-show-caret" }
+// Test -Wvexing-parse's fix-it hints in C++98.
+
+struct X { };
+
+struct T {
+ T(X);
+ int m;
+};
+
+struct U {
+ U();
+ int m;
+};
+
+int
+main ()
+{
+ T t(X()); // { dg-warning "6:parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ T t(X());
+ ^~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:add parentheses to declare a variable" "" { target *-*-* } 21 }
+ /* { dg-begin-multiline-output "" }
+ T t(X());
+ ^~~~~
+ ( )
+ { dg-end-multiline-output "" } */
+
+ int n( ); // { dg-warning "8:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ int n( );
+ ^~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "8:remove parentheses to default-initialize a variable" "" { target *-*-* } 33 }
+ /* { dg-begin-multiline-output "" }
+ int n( );
+ ^~~~~
+ -----
+ { dg-end-multiline-output "" } */
+
+ T y(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ T y();
+ ^~
+ { dg-end-multiline-output "" } */
+
+ X x(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ X x();
+ ^~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:remove parentheses to default-initialize a variable" "" { target *-*-* } 51 }
+ /* { dg-begin-multiline-output "" }
+ X x();
+ ^~
+ --
+ { dg-end-multiline-output "" } */
+
+ U u(); // { dg-warning "6:empty parentheses were disambiguated as a function declaration" }
+ /* { dg-begin-multiline-output "" }
+ U u();
+ ^~
+ { dg-end-multiline-output "" } */
+ // { dg-message "6:remove parentheses to default-initialize a variable" "" { target *-*-* } 63 }
+ /* { dg-begin-multiline-output "" }
+ U u();
+ ^~
+ --
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse5.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse5.C
new file mode 100644
index 0000000..3422e70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse5.C
@@ -0,0 +1,14 @@
+// PR c++/25814
+// { dg-do compile }
+// Test -Wvexing-parse in a template.
+
+struct X { };
+
+template<typename T>
+void fn ()
+{
+ T t(); // { dg-warning "empty parentheses were disambiguated as a function declaration" }
+ T a(X()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ X x(T()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ int i(T()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse6.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse6.C
new file mode 100644
index 0000000..58fa725
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse6.C
@@ -0,0 +1,24 @@
+// PR c++/25814
+// { dg-do compile }
+// Test from Wikipedia.
+
+class Timer {
+ public:
+ Timer();
+};
+
+class TimeKeeper {
+ public:
+ TimeKeeper(const Timer& t);
+
+ int get_time();
+};
+
+void f(double adouble) {
+ int i(int(adouble)); // { dg-warning "parentheses were disambiguated as a function declaration" }
+}
+
+int main() {
+ TimeKeeper time_keeper(Timer()); // { dg-warning "parentheses were disambiguated as a function declaration" }
+ return time_keeper.get_time(); // { dg-error "request for member" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse7.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse7.C
new file mode 100644
index 0000000..9f4c702
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse7.C
@@ -0,0 +1,27 @@
+// PR c++/25814
+// { dg-do compile }
+
+struct X { };
+struct W {
+ W(X, X);
+};
+
+void
+fn ()
+{
+ W w1(X(), X()); // { dg-warning "parentheses" }
+ W w2(X(a), X()); // { dg-warning "parentheses" }
+ W w3(X(), X(a)); // { dg-warning "parentheses" }
+ W w4(X(a), X(b)); // { dg-warning "parentheses" }
+ W w5(X, X);
+ W w6(X(a), X);
+ W w7(X, X(a));
+ W w8(X(a), X()); // { dg-warning "parentheses" }
+ W w9(X, X());
+ W w10(X, X());
+
+ // Not function declarations.
+ W z1(X(), (X()));
+ W z2((X()), X());
+ W z3((X()), (X()));
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse8.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse8.C
new file mode 100644
index 0000000..2d26d22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse8.C
@@ -0,0 +1,11 @@
+// PR c++/97762
+// { dg-do compile }
+
+void
+g ()
+{
+ long a(); // { dg-warning "empty parentheses" }
+ signed b(); // { dg-warning "empty parentheses" }
+ unsigned c(); // { dg-warning "empty parentheses" }
+ short d(); // { dg-warning "empty parentheses" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse9.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse9.C
new file mode 100644
index 0000000..92724bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse9.C
@@ -0,0 +1,8 @@
+// PR c++/97881
+// { dg-do compile }
+
+void
+cb ()
+{
+ volatile _Atomic (int) a1; // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/delete-array-1.C b/gcc/testsuite/g++.dg/warn/delete-array-1.C
index c3af713..95fa7d4 100644
--- a/gcc/testsuite/g++.dg/warn/delete-array-1.C
+++ b/gcc/testsuite/g++.dg/warn/delete-array-1.C
@@ -5,7 +5,7 @@ struct S { int a [1]; } s;
void foo (S *p)
{
- delete a; // { dg-warning "deleting array" }
- delete s.a; // { dg-warning "deleting array" }
- delete p->a; // { dg-warning "deleting array" }
+ delete a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
+ delete s.a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
+ delete p->a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
}
diff --git a/gcc/testsuite/g++.dg/warn/mvp3.C b/gcc/testsuite/g++.dg/warn/mvp3.C
new file mode 100644
index 0000000..4d371c5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/mvp3.C
@@ -0,0 +1,30 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses -fdiagnostics-show-caret" }
+// Test fix-it hints for the MVP warning.
+
+void
+g ()
+{
+ int (i); // { dg-warning "7:unnecessary parentheses" }
+/* { dg-begin-multiline-output "" }
+ int (i);
+ ^~~
+ { dg-end-multiline-output "" } */
+// { dg-message "7:remove parentheses" "" { target *-*-* } 8 }
+/* { dg-begin-multiline-output "" }
+ int (i);
+ ^~~
+ - -
+ { dg-end-multiline-output "" } */
+ int (fn(void)); // { dg-warning "7:unnecessary parentheses" }
+/* { dg-begin-multiline-output "" }
+ int (fn(void));
+ ^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message "7:remove parentheses" "" { target *-*-* } 19 }
+/* { dg-begin-multiline-output "" }
+ int (fn(void));
+ ^~~~~~~~~~
+ - -
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/warn/pr98104.C b/gcc/testsuite/g++.dg/warn/pr98104.C
new file mode 100644
index 0000000..6ca617b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr98104.C
@@ -0,0 +1,20 @@
+// PR c++/98104
+
+#include <new>
+
+struct B
+{
+ B ();
+ int *a;
+ char b;
+};
+
+struct D : public B {};
+void bar (B *);
+
+void
+foo ()
+{
+ D d;
+ bar (::new (static_cast<B*>(&d)) B); // { dg-bogus "placement new constructing an object of type 'B' and size '\[0-9]*' in a region of type 'B' and size '\[0-9]*'" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/pr98160.C b/gcc/testsuite/g++.dg/warn/pr98160.C
new file mode 100644
index 0000000..b3c5783
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr98160.C
@@ -0,0 +1,30 @@
+/* PR middle-end/98160 - ICE in warn_dealloc_offset on member placement
+ new and delete
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* (*pf) (size_t);
+
+struct A;
+struct B
+{
+ B ();
+
+ void* operator new (size_t, A*);
+ void operator delete (void*, A*);
+};
+
+void operator delete (void *, A*);
+
+void B::operator delete (void*, A *p)
+{
+ void *q = pf (1);
+ ::operator delete ((char*)q + 1, p);
+}
+
+void* f (A *p)
+{
+ return new (p) B;
+}
diff --git a/gcc/testsuite/g++.dg/warn/pr98413.C b/gcc/testsuite/g++.dg/warn/pr98413.C
new file mode 100644
index 0000000..877871a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr98413.C
@@ -0,0 +1,23 @@
+/* PR c++/98413 - ICE on placement new and member pointer
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void* operator new (__SIZE_TYPE__, void *p) { return p; }
+
+struct A { int m; } a;
+
+void fc (int A::*p)
+{
+ new (&(a.*p)) char;
+}
+
+void fi (int A::*p)
+{
+ new (&(a.*p)) int;
+}
+
+void fB (int A::*p)
+{
+ struct B { int a[2]; };
+ new (&(a.*p)) B; // { dg-warning "\\\[-Wplacement-new" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/uninit-1.C b/gcc/testsuite/g++.dg/warn/uninit-1.C
new file mode 100644
index 0000000..30f3cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/uninit-1.C
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wmaybe-uninitialized" } */
+struct a {int a;};
+__attribute__ ((noinline))
+void
+nowarn (const struct a *ptr)
+{
+ if (ptr)
+ asm volatile ("");
+}
+void
+test()
+{
+ struct a ptr;
+ nowarn (&ptr);
+}
+__attribute__ ((noinline))
+int
+nowarn2 (const struct a *ptr, const struct a ptr2)
+{
+ return ptr != 0 || ptr2.a;
+}
+int mem;
+int
+test2()
+{
+ struct a ptr,ptr2={0};
+ return nowarn2 (&ptr, ptr2);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/recurse.C b/gcc/testsuite/g++.old-deja/g++.brendan/recurse.C
index de20a07..0af1c14 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/recurse.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/recurse.C
@@ -73,7 +73,7 @@ public:
int main()
{
- DBpathrec a(), b();
+ DBpathrec a(), b(); // { dg-warning "empty parentheses" }
a = b;// { dg-error "" } non-lvalue in assignment.*
}
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/catch10.C b/gcc/testsuite/g++.old-deja/g++.eh/catch10.C
index 2300a94..7cc6096 100644
--- a/gcc/testsuite/g++.old-deja/g++.eh/catch10.C
+++ b/gcc/testsuite/g++.old-deja/g++.eh/catch10.C
@@ -13,8 +13,8 @@ void g()
catch (A*) { }
try { f(); }
- catch (A*) { } // { dg-warning "" } A* before B*
- catch (B*) { } // { dg-warning "" } A* before B*
+ catch (A*) { } // { dg-message "for type" } A* before B*
+ catch (B*) { } // { dg-warning "will be caught" } A* before B*
try { f(); }
catch (A*) { }
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/template4.C b/gcc/testsuite/g++.old-deja/g++.jason/template4.C
index de7d331..1cf5a61 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/template4.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/template4.C
@@ -17,5 +17,5 @@ template <class T>
ccList <T> cc_List<T>::copy (){}
int main (int, char **) {
- ccList <int> size1();
+ ccList <int> size1(); // { dg-warning "empty parentheses" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arm4.C b/gcc/testsuite/g++.old-deja/g++.law/arm4.C
index bbcf7df..59492ca 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arm4.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arm4.C
@@ -20,7 +20,7 @@ int main(void)
{
double a = 2.0;
- S x(int (a));
+ S x(int (a)); // { dg-warning "parentheses were disambiguated" }
if (count > 0)
{ printf ("FAIL\n"); return 1; }
else
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/for2.C b/gcc/testsuite/g++.old-deja/g++.mike/for2.C
index 6eb5d66..4a7c304 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/for2.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/for2.C
@@ -14,7 +14,7 @@ void bar() {
void bee () {
int i = 0;
- for (int fun() = 0; i != 2; ++i) { // { dg-warning "extern" "extern" }
+ for (int fun() = 0; i != 2; ++i) { // { dg-warning "extern|empty parentheses" "extern" }
// { dg-error "initialized" "init" { target *-*-* } .-1 }
}
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash31.C b/gcc/testsuite/g++.old-deja/g++.other/crash31.C
index 610dfe1..d777691 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/crash31.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/crash31.C
@@ -6,5 +6,4 @@ namespace bar
struct foo
{
foo();
-};
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+}; // { dg-error "3:expected" }
diff --git a/gcc/testsuite/g++.old-deja/g++.other/decl3.C b/gcc/testsuite/g++.old-deja/g++.other/decl3.C
index bdcfcb0..4534bd1 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/decl3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/decl3.C
@@ -13,7 +13,7 @@ struct cow_t { // { dg-message "pure" }
int main()
{
- cow_t cow[2]; // { dg-error "invalid abstract type" }
+ cow_t cow[2]; // { dg-error "abstract" }
cow[0].f();
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete2.C b/gcc/testsuite/g++.old-deja/g++.other/delete2.C
index 1d0554f..76ae355 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/delete2.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/delete2.C
@@ -9,5 +9,7 @@ void bar(foo a) {
delete[] a; // should be accepted
char b[1];
delete b; // { dg-warning "deleting array" } expecting pointer type
+ // { dg-warning "-Wfree-nonheap-object" "" { target *-*-* } .-1 }
delete[] b; // { dg-warning "deleting array" } expecting pointer type
+ // { dg-warning "-Wfree-nonheap-object" "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/local4.C b/gcc/testsuite/g++.old-deja/g++.other/local4.C
index b5514a5..492ce2b 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/local4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/local4.C
@@ -6,6 +6,6 @@ int f (int);
int main ()
{
- int f ();
+ int f (); // { dg-warning "empty parentheses" }
return f ();
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/using1.C b/gcc/testsuite/g++.old-deja/g++.other/using1.C
index 6cebc29..8910091 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/using1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/using1.C
@@ -10,9 +10,9 @@ protected:
friend class D2;
};
-class D : public B { // { dg-error "" } within this context
+class D : public B {
public:
- using B::a;
+ using B::a; // { dg-error "" } within this context
using B::b;
};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
index 012e3d0..a84b190 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C
@@ -6,7 +6,6 @@ public:
enum { val = (N == 0) ? M : GCD<N, M % N>::val };
// { dg-error "constant expression" "valid" { target *-*-* } .-1 }
// { dg-message "template argument" "valid" { target *-*-* } .-2 }
-// { dg-warning "division by" "" { target *-*-* } .-3 }
};
int main() {
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash3.C b/gcc/testsuite/g++.old-deja/g++.pt/crash3.C
index 52701b7..d1d9b12 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash3.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash3.C
@@ -7,11 +7,13 @@ public:
{
// local-extern :)
CVector<int> v(); // { dg-message "old declaration" }
+ // { dg-warning "empty parentheses" "" { target *-*-* } .-1 }
return v; // { dg-error "convert" }
}
CVector<long> g() const
{
CVector<long> v(); // { dg-error "ambiguating new" }
+ // { dg-warning "empty parentheses" "" { target *-*-* } .-1 }
return v; // { dg-error "convert" }
}
};
diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr98177-1.C b/gcc/testsuite/g++.target/aarch64/sve/pr98177-1.C
new file mode 100644
index 0000000..9789193
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/pr98177-1.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=128" } */
+
+int a, b;
+short c;
+void d(long e) {
+ for (int f = 0; f < b; f += 1)
+ for (short g = 0; g < c; g += 5)
+ a = (short)e;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr98177-2.C b/gcc/testsuite/g++.target/aarch64/sve/pr98177-2.C
new file mode 100644
index 0000000..c7244ef
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/pr98177-2.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=128" } */
+
+int a, b, c;
+
+void foo(long e) {
+ for (int f = 0; f < b; f ++)
+ for (int g = 0; g < c; g ++)
+ a = (short)e;
+}
diff --git a/gcc/testsuite/g++.target/i386/mv29.C b/gcc/testsuite/g++.target/i386/mv29.C
new file mode 100644
index 0000000..c7723e3
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv29.C
@@ -0,0 +1,79 @@
+// Test that dispatching can choose the right multiversion
+// for AMD CPUs with the same internal GCC processor id
+
+// { dg-do run }
+// { dg-require-ifunc "" }
+// { dg-options "-O2" }
+
+#include <assert.h>
+
+int __attribute__ ((target("default")))
+foo ()
+{
+ return 0;
+}
+
+int __attribute__ ((target("arch=amdfam10"))) foo () {
+ return 1;
+}
+
+int __attribute__ ((target("arch=btver1"))) foo () {
+ return 2;
+}
+
+int __attribute__ ((target("arch=btver2"))) foo () {
+ return 3;
+}
+
+int __attribute__ ((target("arch=bdver1"))) foo () {
+ return 4;
+}
+
+int __attribute__ ((target("arch=bdver2"))) foo () {
+ return 5;
+}
+
+int __attribute__ ((target("arch=bdver3"))) foo () {
+ return 6;
+}
+
+int __attribute__ ((target("arch=znver1"))) foo () {
+ return 7;
+}
+
+int __attribute__ ((target("arch=znver2"))) foo () {
+ return 8;
+}
+
+int __attribute__ ((target("arch=znver3"))) foo () {
+ return 9;
+}
+
+
+int main ()
+{
+ int val = foo ();
+
+ if (__builtin_cpu_is ("amdfam10h"))
+ assert (val == 1);
+ else if (__builtin_cpu_is ("btver1"))
+ assert (val == 2);
+ else if (__builtin_cpu_is ("btver2"))
+ assert (val == 3);
+ else if (__builtin_cpu_is ("bdver1"))
+ assert (val == 4);
+ else if (__builtin_cpu_is ("bdver2"))
+ assert (val == 5);
+ else if (__builtin_cpu_is ("bdver3"))
+ assert (val == 6);
+ else if (__builtin_cpu_is ("znver1"))
+ assert (val == 7);
+ else if (__builtin_cpu_is ("znver2"))
+ assert (val == 8);
+ else if (__builtin_cpu_is ("znver3"))
+ assert (val == 9);
+ else
+ assert (val == 0);
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/msp430/data-attributes.C b/gcc/testsuite/g++.target/msp430/data-attributes.C
new file mode 100644
index 0000000..b7faf2c
--- /dev/null
+++ b/gcc/testsuite/g++.target/msp430/data-attributes.C
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" } } */
+/* { dg-options "-mlarge" } */
+
+/* The msp430-specific variable attributes "upper", either", "noinit"
+ and "persistent", all conflict with one another.
+ "lower" can be used to indicate that a variable with a section set by the
+ "section", "noinit", or "persistent" attributes is in lower memory, so it
+ does not conflict with these.
+ These attributes also conflict with the "section" attribute, since they
+ specify sections to put the variables into. */
+int __attribute__((persistent)) p = 10;
+int __attribute__((persistent,lower)) pl = 20;
+int __attribute__((persistent,upper)) pu = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent,either)) pe = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'persistent'" } */
+/* This one results in an error because the handler for persistent sets the
+ section to .persistent there and then. */
+int __attribute__((persistent,section(".data.foo"))) ps = 20; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent,noinit)) pn = 2; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent)) zz; /* { dg-warning "ignoring 'persistent' attribute set on uninitialized variable" } */
+
+int __attribute__((noinit)) n;
+int __attribute__((noinit,lower)) nl;
+int __attribute__((noinit,upper)) nu; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,either)) ne; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,persistent)) np; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,section(".data.foo"))) ns; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'noinit'" } */
+
+int __attribute__((lower)) l = 20;
+int __attribute__((lower,upper)) lu = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,either)) le = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,persistent)) lp = 20;
+int __attribute__((lower,noinit)) ln;
+int __attribute__((lower,section(".data.foo"))) ls = 30;
+
+int __attribute__((upper)) u = 20;
+int __attribute__((upper,lower)) ul = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,either)) ue = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,persistent)) up = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,noinit)) un; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,section(".data.foo"))) us = 30; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'upper'" } */
+
+int __attribute__((either)) e = 20;
+int __attribute__((either,lower)) el = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'either'" } */
+int __attribute__((either,upper)) ee = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'either'" } */
+int __attribute__((either,persistent)) ep = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'either'" } */
+int __attribute__((either,noinit)) en; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'either'" } */
+int __attribute__((either,section(".data.foo"))) es = 30; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'either'" } */
+
+int __attribute__((section(".data.foo"))) s = 20;
+int __attribute__((section(".data.foo"),noinit)) sn; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),persistent)) sp = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),lower)) sl = 2;
+int __attribute__((section(".data.foo"),upper)) su = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),either)) se = 2; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'section'" } */
diff --git a/gcc/testsuite/g++.target/msp430/msp430.exp b/gcc/testsuite/g++.target/msp430/msp430.exp
new file mode 100644
index 0000000..3574c0f
--- /dev/null
+++ b/gcc/testsuite/g++.target/msp430/msp430.exp
@@ -0,0 +1,44 @@
+# Specific regression driver for MSP430.
+# Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an MSP430 target.
+if {![istarget msp430*-*-*] } then {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+ set DEFAULT_CXXFLAGS " -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \
+ "" $DEFAULT_CXXFLAGS
+
+# All done.
+dg-finish
+
diff --git a/gcc/testsuite/g++.target/powerpc/pr97947.C b/gcc/testsuite/g++.target/powerpc/pr97947.C
new file mode 100644
index 0000000..94e5ed6
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/pr97947.C
@@ -0,0 +1,12 @@
+/* PR c++/97947 */
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+/* Verify we do not ICE on the test below. */
+
+void
+bug (__vector_pair *src)
+{
+ volatile __vector_pair dd = *src;
+}
diff --git a/gcc/testsuite/g++.target/riscv/pr97682.C b/gcc/testsuite/g++.target/riscv/pr97682.C
new file mode 100644
index 0000000..03c7a44
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/pr97682.C
@@ -0,0 +1,160 @@
+/* PR target/97682 */
+/* { dg-do compile } */
+/* { dg-options "-fPIC -O2 -march=rv64g -mabi=lp64" } */
+
+template <typename ab, int ac> struct g { ab b[ac]; };
+long i, m;
+
+namespace std
+{
+ template <typename c> struct t
+ {
+ int a;
+ c h;
+ };
+
+ struct ad
+ {
+ enum { j };
+ };
+
+ template <typename k> k l(k);
+ struct al {};
+ template <typename k> k aa(k);
+
+ struct v
+ {
+ template <typename n, typename q> static q o(n, n, q);
+ };
+
+ template <int, typename n, typename q> void p(n z, n ao, q ap)
+ {
+ v::o(z, ao, ap);
+ }
+
+ template <int ae, typename n, typename q> void r(n z, n ao, q ap)
+ {
+ p<ae>(z, ao, ap);
+ }
+
+ template <int ae, typename n, typename q> void af(n z, n ao, q)
+ {
+ r<ae>(aa(z), aa(ao), 0);
+ }
+
+ template <typename n, typename q> void ag(n z, n ao, q ap)
+ {
+ af<ad::j>(l(z), l(ao), ap);
+ }
+
+ template <typename> class allocator;
+ template <typename ah, typename ai, typename aj> void ak(ah, ai, aj);
+
+ template <typename s> class aq
+ {
+ template <typename am> struct ar { using f = am *; };
+ public:
+ using an = typename ar<s>::f;
+ };
+
+ template <typename s> class as
+ {
+ public:
+ using an = typename aq<s>::an;
+ an operator->();
+ };
+
+ struct ay
+ {
+ int at();
+ };
+
+ template <typename s, typename = allocator<s>> class vector : ay
+ {
+ public:
+ long au();
+ long x;
+ void av() { _M_default_append(x); }
+ void _M_default_append(unsigned long);
+ void aw();
+ long ax(int);
+ };
+
+ template <typename s, typename y>
+ void vector<s, y>::_M_default_append(unsigned long z)
+ {
+ long az = au();
+ int w = at(), bc = at();
+ i = ax(w);
+ m = ax(w);
+ if (i || m)
+ aw();
+ ak(az, z, bc);
+ }
+}
+
+namespace llvm
+{
+ template <int bd> class bh
+ {
+ enum { bf = bd } * bg[bf];
+ };
+
+ template <class> class bi;
+
+ class bm
+ {
+ using bj = bi<int>;
+ std::as<bj> bk;
+ void bl();
+ };
+
+ template <class> struct bn;
+
+ class br
+ {
+ bh<8> bo;
+ };
+
+ class ca
+ {
+ int *d;
+ int e;
+ };
+
+ template <class bp> class bv : std::al, br
+ {
+ g<std::t<ca>, 8> b;
+ };
+
+ template <class ab> bv<ab> bt(ab);
+
+ class BlockFrequencyInfoImplBase
+ {
+ public:
+ struct FrequencyData;
+ std::vector<FrequencyData> bu;
+ };
+
+ template <class> struct cb { using bw = int; };
+ template <class bx> class bi : BlockFrequencyInfoImplBase
+ {
+ using bw = typename cb<bx>::bw;
+ public:
+ void bl();
+ };
+
+ template <class bx> void bi<bx>::bl()
+ {
+ const bw *by;
+ bv<const int *> bz;
+ ag(bz, bt(by), 0);
+ bu.av();
+ }
+
+ template <> struct bn<const int *> { using u = ca; };
+ void bm::bl() { bk->bl(); }
+}
+
+/* The t1 register is to initial symbol reference for call instruction. */
+/* { dg-final { scan-assembler "la\tt1,.*FrequencyData.*_M_default_append.*" } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/asmgoto-2.c b/gcc/testsuite/gcc.c-torture/compile/asmgoto-2.c
new file mode 100644
index 0000000..f1b30c0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/asmgoto-2.c
@@ -0,0 +1,65 @@
+/* This test should be switched off for a new target with less than 4 allocatable registers */
+/* { dg-do compile } */
+int
+foo (void)
+{
+ int x, y, z, v;
+
+ asm goto ("": "=r" (x), "=r" (y), "=r" (z), "=r" (v) : : : lab, lab2, lab3, lab4);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+}
+
+int
+foo2 (void)
+{
+ int x = 0, y = 1, z = 2, v = 3;
+
+ asm goto ("": "+r" (x), "+r" (y), "+r" (z), "+r" (v) : : : lab, lab2, lab3, lab4);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+}
+
+int
+foo3 (void)
+{
+ int x, y, z, v;
+
+ asm goto ("": "=rm" (x), "=mr" (y), "=rm" (z), "=mr" (v) : : : lab, lab2, lab3, lab4);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+}
+
+int
+foo4 (void)
+{
+ int x, y, z, v;
+
+ asm goto ("": "=r,m" (x), "=m,r" (y), "=r,m" (z), "=m,r" (v) : : : lab, lab2, lab3, lab4);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/asmgoto-3.c b/gcc/testsuite/gcc.c-torture/compile/asmgoto-3.c
new file mode 100644
index 0000000..842b73e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/asmgoto-3.c
@@ -0,0 +1,89 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+int
+foo (void)
+{
+ int x;
+
+ asm goto ("": "=a" (x) : : : lab);
+ lab:
+ return x;
+}
+
+int
+foo2 (void)
+{
+ int x, y;
+
+ asm goto ("": "=a" (x), "=d" (y) : : : lab, lab2);
+ lab:
+ return x;
+ lab2:
+ return y;
+}
+
+int
+foo3 (void)
+{
+ int x, y, z;
+
+ asm goto ("": "=a" (x), "=d" (y), "=c" (z) : : : lab, lab2, lab3);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+}
+
+int
+foo4 (void)
+{
+ int x, y, z, v;
+
+ asm goto ("": "=a" (x), "=d" (y), "=c" (z) , "=b" (v) : : : lab, lab2, lab3, lab4);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+}
+
+int
+foo5 (void)
+{
+ int x, y, z, v, w;
+
+ asm goto ("": "=a" (x), "=d" (y), "=c" (z), "=b" (v), "=S" (w) : : : lab, lab2, lab3, lab4, lab5);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+ lab5:
+ return w;
+}
+
+int
+foo6 (void)
+{
+ int x = 0, y = 1, z = 2, v = 3, w = 4;
+
+ asm goto ("": "+a" (x), "+d" (y), "+c" (z), "+b" (v), "+S" (w) : : : lab, lab2, lab3, lab4, lab5);
+ lab:
+ return x;
+ lab2:
+ return y;
+ lab3:
+ return z;
+ lab4:
+ return v;
+ lab5:
+ return w;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/asmgoto-4.c b/gcc/testsuite/gcc.c-torture/compile/asmgoto-4.c
new file mode 100644
index 0000000..844157e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/asmgoto-4.c
@@ -0,0 +1,14 @@
+/* Check that LRA really puts output reloads for p4 in two successors blocks */
+/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
+/* { dg-options "-O0 -fdump-rtl-reload" } */
+
+int f (int *p1, int *p2, int *p3, int *p4) {
+ asm volatile goto (
+ ""
+ : "=r" (*p2), "=a" (p4)
+ : "r" (*p2), "r" (p2)
+ : "r8", "r9" : lab, lab2);
+ lab: return p2 - p4;
+ lab2: return p3 - p4;
+}
+/* { dg-final { scan-rtl-dump-times "Inserting insn reload after in bb" 2 "reload" } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/asmgoto-5.c b/gcc/testsuite/gcc.c-torture/compile/asmgoto-5.c
new file mode 100644
index 0000000..94c14dd
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/asmgoto-5.c
@@ -0,0 +1,56 @@
+/* Test to generate output reload in asm goto on x86_64. */
+/* { dg-do compile } */
+/* { dg-skip-if "no O0" { { i?86-*-* x86_64-*-* } && { ! ia32 } } { "-O0" } { "" } } */
+
+#if defined __x86_64__
+#define ASM(s) asm (s)
+#else
+#define ASM(s)
+#endif
+
+int
+foo (int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8,
+ int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16)
+{
+ register int v0 ASM ("rax") = a3;
+ register int v1 ASM ("rbx") = a4;
+ register int v2 ASM ("rcx") = a5;
+ register int v3 ASM ("rdx") = a6;
+ register int v4 ASM ("rsi") = a7;
+ register int v5 ASM ("rdi") = a8;
+ register int v6 ASM ("r8") = a9;
+ register int v7 ASM ("r9") = a10;
+ register int v8 ASM ("r10") = a11;
+ register int v9 ASM ("r11") = a12;
+ register int v10 ASM ("r12") = a13;
+ register int v11 ASM ("r13") = a14;
+ register int v12 ASM ("r14") = a15;
+ register int v13 ASM ("r15") = a16;
+ int x;
+
+ v0 += a0;
+ v1 += a1;
+ v2 += a2;
+ v0 |= a0;
+ v1 |= a1;
+ v2 |= a2;
+ v0 ^= a0;
+ v1 ^= a1;
+ v2 ^= a2;
+ v0 &= a0;
+ v1 &= a1;
+ v2 &= a2;
+ asm goto ("": "=r" (x) : : : lab);
+ a1 ^= a0;
+ a2 = a1;
+ a0 |= a2;
+ a0 |= x;
+ lab:
+ v0 += x + a0 + a1 + a2;
+ v1 -= a0 - a1 - a2;
+ v2 |= a0 | a1 | a2;
+ v3 |= a0 & a1 & a2;
+ v4 ^= a0 ^ a1 ^ a2;
+ return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 + v11 + v12 + v13 + a0 + a1 + a2;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
new file mode 100644
index 0000000..5f6cbca
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.*,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections. */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
+
+int __attribute__((used,section(".data.used_foo_sec"))) used_foo = 2;
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
new file mode 100644
index 0000000..be5f391
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm,\"awR\"" { target arm-*-* } } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm2,\"awR\"" { target arm-*-* } } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+/* { dg-options "-ffunction-sections -fdata-sections" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58901-0.c b/gcc/testsuite/gcc.c-torture/compile/pr58901-0.c
new file mode 100644
index 0000000..d98e29e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58901-0.c
@@ -0,0 +1,17 @@
+typedef int __attribute__ ((mode (SI))) int_t;
+
+struct s
+{
+ int_t n;
+ int_t c[];
+};
+
+int_t
+ashlsi (int_t x, const struct s *s)
+{
+ int_t i;
+
+ for (i = 0; i < s->n; i++)
+ x ^= 1 << s->c[i];
+ return x;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58901-1.c b/gcc/testsuite/gcc.c-torture/compile/pr58901-1.c
new file mode 100644
index 0000000..e01dba0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58901-1.c
@@ -0,0 +1,21 @@
+typedef signed int __attribute__ ((mode (SI))) int_t;
+
+struct s
+{
+ int_t n;
+ int_t m : 1;
+ int_t l : 31;
+};
+
+int_t
+movdi (int_t x, const struct s *s)
+{
+ int_t i;
+
+ for (i = 0; i < x; i++)
+ {
+ const struct s t = s[i];
+ x += t.m ? 1 : 0;
+ }
+ return x;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr96998.c b/gcc/testsuite/gcc.c-torture/compile/pr96998.c
new file mode 100644
index 0000000..a75d5dc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr96998.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target arm*-*-* aarch64*-*-* } } */
+
+int h(void);
+struct c d;
+struct c {
+ int e[1];
+};
+
+void f(void) {
+ int g;
+ for (;; g = h()) {
+ int *i = &d.e[g];
+ asm("" : "=Q"(*i));
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr97205.c b/gcc/testsuite/gcc.c-torture/compile/pr97205.c
new file mode 100644
index 0000000..6600011
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr97205.c
@@ -0,0 +1,7 @@
+int a;
+typedef __attribute__((aligned(2))) int x;
+int f ()
+{
+ x b = a;
+ return b;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr97576.c b/gcc/testsuite/gcc.c-torture/compile/pr97576.c
new file mode 100644
index 0000000..28294c8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr97576.c
@@ -0,0 +1,18 @@
+void
+pc (void);
+
+void __attribute__ ((simd))
+ty (void);
+
+void __attribute__ ((simd))
+gf ()
+{
+ ty ();
+}
+
+void __attribute__ ((simd))
+ty (void)
+{
+ gf (pc);
+ gf (gf);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr97578.c b/gcc/testsuite/gcc.c-torture/compile/pr97578.c
new file mode 100644
index 0000000..e007724
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr97578.c
@@ -0,0 +1,11 @@
+int printf (const char *, ...);
+
+int a;
+static void b(int c) {
+ if (c)
+ printf("%d", a);
+}
+void e() {
+ int d = 0;
+ b(d);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr97979.c b/gcc/testsuite/gcc.c-torture/compile/pr97979.c
new file mode 100644
index 0000000..f4f88a4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr97979.c
@@ -0,0 +1,7 @@
+/* PR tree-optimization/97979 */
+
+int
+foo (int x)
+{
+ return (x & 0x123) << -3;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98087.c b/gcc/testsuite/gcc.c-torture/compile/pr98087.c
new file mode 100644
index 0000000..8cac770
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr98087.c
@@ -0,0 +1,14 @@
+/* PR c/98087 */
+
+struct S { char a; long long b; };
+struct T { struct S c[0]; char d; };
+void foo (int n)
+{
+ struct S a[n][0];
+ __builtin_clear_padding (a);
+ __builtin_clear_padding (&a);
+ struct S b[7][0];
+ __builtin_clear_padding (&b);
+ struct T c;
+ __builtin_clear_padding (&c);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98199.c b/gcc/testsuite/gcc.c-torture/compile/pr98199.c
new file mode 100644
index 0000000..b5c8d20
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr98199.c
@@ -0,0 +1,7 @@
+/* PR tree-optimization/98199 */
+
+struct A { long a; short d; int c, f, e, g; };
+struct B { int a, i; short j; struct A k; signed : 20; int e, g; } __attribute__((packed));
+struct C { short a; unsigned i, k; struct B d; const int : 30; signed e : 20; signed : 18; };
+const struct C l = { 1, 6, 0, {}, 0 };
+int foo (void) { return l.e || 0; }
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98229.c b/gcc/testsuite/gcc.c-torture/compile/pr98229.c
new file mode 100644
index 0000000..509719d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr98229.c
@@ -0,0 +1,7 @@
+/* PR rtl-optimization/98229 */
+
+unsigned long long
+foo (unsigned long long x)
+{
+ return x % ~0U;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98256.c b/gcc/testsuite/gcc.c-torture/compile/pr98256.c
new file mode 100644
index 0000000..44839c7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr98256.c
@@ -0,0 +1,9 @@
+/* PR tree-optimization/98256 */
+
+unsigned a, b;
+
+int
+foo (void)
+{
+ return !!(~a / b);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98407.c b/gcc/testsuite/gcc.c-torture/compile/pr98407.c
new file mode 100644
index 0000000..29eb080
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr98407.c
@@ -0,0 +1,10 @@
+/* PR tree-optimization/98407 */
+
+struct S { int a; int b[]; };
+const struct S c = { 0, { 0 } }, d = { 0, { 0 } };
+
+int
+foo (void)
+{
+ return __builtin_memcmp (&c, &d, sizeof d);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/index-1.c b/gcc/testsuite/gcc.c-torture/execute/index-1.c
index b00090d..d96be4c 100644
--- a/gcc/testsuite/gcc.c-torture/execute/index-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/index-1.c
@@ -1,3 +1,5 @@
+/* { dg-skip-if "strict reloc overflow checking" { msp430-*-* } { "*" } { "-mcpu=msp430" "-mlarge"} } */
+
int a[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
diff --git a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c b/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c
deleted file mode 100644
index 20a2a45..0000000
--- a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* { dg-do run } */
-/* { dg-require-effective-target noinit } */
-/* { dg-options "-O2" } */
-/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
-
-/* This test checks that noinit data is handled correctly.
- If data LMA != VMA (e.g. for simulating the copy of data from ROM to RAM),
- then var_init will always be re-initialized to 2 and this test will loop
- forever. */
-
-extern void _start (void) __attribute__ ((noreturn));
-extern void abort (void) __attribute__ ((noreturn));
-extern void exit (int) __attribute__ ((noreturn));
-
-int var_common;
-int var_zero = 0;
-int var_one = 1;
-int __attribute__((noinit)) var_noinit;
-int var_init = 2;
-
-int __attribute__((noinit)) func(); /* { dg-warning "attribute only applies to variables" } */
-int __attribute__((section ("mysection"), noinit)) var_section1; /* { dg-warning "because it conflicts with attribute" } */
-int __attribute__((noinit, section ("mysection"))) var_section2; /* { dg-warning "because it conflicts with attribute" } */
-
-
-int
-main (void)
-{
- /* Make sure that the C startup code has correctly initialized the ordinary variables. */
- if (var_common != 0)
- abort ();
-
- /* Initialized variables are not re-initialized during startup, so
- check their original values only during the first run of this
- test. */
- if (var_init == 2)
- if (var_zero != 0 || var_one != 1)
- abort ();
-
- switch (var_init)
- {
- case 2:
- /* First time through - change all the values. */
- var_common = var_zero = var_one = var_noinit = var_init = 3;
- break;
-
- case 3:
- /* Second time through - make sure that d has not been reset. */
- if (var_noinit != 3)
- abort ();
- exit (0);
-
- default:
- /* Any other value for var_init is an error. */
- abort ();
- }
-
- /* Simulate a processor reset by calling the C startup code. */
- _start ();
-
- /* Should never reach here. */
- abort ();
-}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97421-1.c b/gcc/testsuite/gcc.c-torture/execute/pr97421-1.c
new file mode 100644
index 0000000..e32fb12
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97421-1.c
@@ -0,0 +1,23 @@
+/* PR rtl-optimization/97421 */
+/* { dg-additional-options "-fmodulo-sched" } */
+
+int a, b, d, e;
+int *volatile c = &a;
+
+__attribute__((noinline))
+void f(void)
+{
+ for (int g = 2; g >= 0; g--) {
+ d = 0;
+ for (b = 0; b <= 2; b++)
+ ;
+ e = *c;
+ }
+}
+
+int main(void)
+{
+ f();
+ if (b != 3)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97421-2.c b/gcc/testsuite/gcc.c-torture/execute/pr97421-2.c
new file mode 100644
index 0000000..142bcbc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97421-2.c
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/97421 */
+/* { dg-additional-options "-fmodulo-sched -fno-dce -fno-strict-aliasing" } */
+
+static int a, b, c;
+int *d = &c;
+int **e = &d;
+int ***f = &e;
+int main()
+{
+ int h;
+ for (a = 2; a; a--)
+ for (h = 0; h <= 2; h++)
+ for (b = 0; b <= 2; b++)
+ ***f = 6;
+
+ if (b != 3)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97421-3.c b/gcc/testsuite/gcc.c-torture/execute/pr97421-3.c
new file mode 100644
index 0000000..3f1485a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97421-3.c
@@ -0,0 +1,22 @@
+/* PR rtl-optimization/97421 */
+/* { dg-additional-options "-fmodulo-sched" } */
+
+int a, b, c;
+short d;
+void e(void) {
+ unsigned f = 0;
+ for (; f <= 2; f++) {
+ int g[1];
+ int h = (long)g;
+ c = 0;
+ for (; c < 10; c++)
+ g[0] = a = 0;
+ for (; a <= 2; a++)
+ b = d;
+ }
+}
+int main(void) {
+ e();
+ if (a != 3)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97695.c b/gcc/testsuite/gcc.c-torture/execute/pr97695.c
new file mode 100644
index 0000000..36f48b4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97695.c
@@ -0,0 +1,20 @@
+int *a, b, **c = &a, d, e;
+
+int f(int g, int h) { return !h || (g && h == 1) ? 0 : g / h; }
+
+static void *i(int g) {
+ while (e < 2)
+ if (!f(g, 9)) {
+ while (b)
+ ;
+ return 0;
+ }
+ return 0;
+}
+
+void j() {
+ i(1);
+ *c = i(d);
+}
+
+int main() { j(); return 0; }
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97764.c b/gcc/testsuite/gcc.c-torture/execute/pr97764.c
new file mode 100644
index 0000000..4ceaab8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97764.c
@@ -0,0 +1,14 @@
+/* PR tree-optimization/97764 */
+/* { dg-require-effective-target int32plus } */
+
+struct S { int b : 3; int c : 28; int d : 1; };
+
+int
+main ()
+{
+ struct S e = {};
+ e.c = -1;
+ if (e.d)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97836.c b/gcc/testsuite/gcc.c-torture/execute/pr97836.c
new file mode 100644
index 0000000..4585e1f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97836.c
@@ -0,0 +1,17 @@
+int a;
+
+int b(int c) { return 0; }
+
+static int *d(int *e) {
+ if (a) {
+ a = a && b(*e);
+ }
+ return e;
+}
+
+int main() {
+ int f;
+ if (d(&f) != &f)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97888-1.c b/gcc/testsuite/gcc.c-torture/execute/pr97888-1.c
new file mode 100644
index 0000000..21fb6fc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97888-1.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/97888 */
+
+int a = 1, c = 4, d, e;
+
+int
+main ()
+{
+ int f = -173;
+ int b;
+ for (b = 0; b < 10; b++)
+ {
+ int g = f % (~0 && a), h = 0, i = 0;
+ if (g)
+ __builtin_unreachable ();
+ if (c)
+ h = f;
+ if (h > -173)
+ e = d / i;
+ f = h;
+ }
+ if (f != -173)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97888-2.c b/gcc/testsuite/gcc.c-torture/execute/pr97888-2.c
new file mode 100644
index 0000000..4f06ce6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr97888-2.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/97888 */
+
+__attribute__((noipa)) void
+foo (int i)
+{
+ if ((i % 7) >= 0)
+ {
+ if (i >= 0)
+ __builtin_abort ();
+ }
+}
+
+int
+main ()
+{
+ foo (-7);
+ foo (-21);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98366.c b/gcc/testsuite/gcc.c-torture/execute/pr98366.c
new file mode 100644
index 0000000..14415bf
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr98366.c
@@ -0,0 +1,13 @@
+/* PR middle-end/98366 */
+/* { dg-require-effective-target int32 } */
+
+typedef struct S { int a, b, c : 7, d : 8, e : 17; } S;
+const S f[] = { {0, 3, 4, 2, 0} };
+
+int
+main ()
+{
+ if (__builtin_memcmp (f, (S[]){{.b = 3, .c = 4, .d = 2, .e = 0}}, sizeof (S)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98474.c b/gcc/testsuite/gcc.c-torture/execute/pr98474.c
new file mode 100644
index 0000000..8c28799
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr98474.c
@@ -0,0 +1,30 @@
+/* PR tree-optimization/98474 */
+
+#ifdef __SIZEOF_INT128__
+typedef __uint128_t T;
+#define N (__SIZEOF_INT128__ * __CHAR_BIT__ / 2)
+#else
+typedef unsigned long long T;
+#define N (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ / 2)
+#endif
+
+__attribute__ ((noipa)) void
+foo (T *x)
+{
+ *x += ((T) 1) << (N + 1);
+}
+
+int
+main ()
+{
+ T a = ((T) 1) << (N + 1);
+ T b = a;
+ T n;
+ foo (&b);
+ n = b;
+ while (n >= a)
+ n -= a;
+ if ((int) (n >> N) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/20021029-1.c b/gcc/testsuite/gcc.dg/20021029-1.c
index f11a6e4..d13f669 100644
--- a/gcc/testsuite/gcc.dg/20021029-1.c
+++ b/gcc/testsuite/gcc.dg/20021029-1.c
@@ -3,6 +3,7 @@
/* { dg-do compile { target fpic } } */
/* { dg-options "-O2 -fpic" } */
/* { dg-final { scan-assembler-not ".data.rel.ro.local" } } */
+/* { dg-final { scan-assembler-symbol-section {^_?ar} {^\.(const|rodata)|\[RO\]} } } */
/* { dg-require-effective-target label_values } */
/* { dg-require-effective-target indirect_jumps } */
diff --git a/gcc/testsuite/gcc.dg/20031223-1.c b/gcc/testsuite/gcc.dg/20031223-1.c
index 68aa74f..c529739 100644
--- a/gcc/testsuite/gcc.dg/20031223-1.c
+++ b/gcc/testsuite/gcc.dg/20031223-1.c
@@ -3,11 +3,10 @@
because GCC was trying to expand the trees to rtl. */
/* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-std=c17 -pedantic-errors" } */
void f ()
{
l: int; /* { dg-error "a label can only be part of a statement and a declaration is not a statement" "not stmt" } */
- /* { dg-warning "useless type name in empty declaration" "type name" { target *-*-* } .-1 } */
- /* { dg-error "label at end of compound statement" "label" { target *-*-* } .-2 } */
+ /* { dg-error "useless type name in empty declaration" "type name" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-43.c b/gcc/testsuite/gcc.dg/Warray-bounds-43.c
index 8892921..0f521a7 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-43.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-43.c
@@ -5,20 +5,9 @@
#define NOIPA __attribute__ ((noipa))
-const char a0[] = "";
-const char a1[] = "1";
-const char a2[] = "12";
-const char a3[] = "123";
-const char a4[] = "1234";
-const char a5[] = "12345";
-const char a6[] = "123456";
-const char a7[] = "1234567";
-const char a8[] = "12345678";
const char a9[] = "123456789";
-void f (const char*, ...);
-
-int i0, i1, i2, i3, i4, i5, i6, i7, i8;
+void sink (const char*, ...);
NOIPA int g2 (int i)
{
@@ -28,7 +17,7 @@ NOIPA int g2 (int i)
const char *p1 = p0 + i;
const char *p2 = p1 + i;
- f (p0, p1, p2);
+ sink (p0, p1, p2);
return p2[8]; // { dg-warning "\\\[-Warray-bounds]" }
}
@@ -42,7 +31,7 @@ NOIPA int g3 (int i)
const char *p2 = p1 + i;
const char *p3 = p2 + i;
- f (p0, p1, p2, p3);
+ sink (p0, p1, p2, p3);
return p3[7]; // { dg-warning "\\\[-Warray-bounds]" }
}
@@ -57,7 +46,7 @@ NOIPA int g4 (int i)
const char *p3 = p2 + i;
const char *p4 = p3 + i;
- f (p0, p1, p2, p3, p4);
+ sink (p0, p1, p2, p3, p4);
return p4[6]; // { dg-warning "\\\[-Warray-bounds]" }
}
@@ -73,7 +62,7 @@ NOIPA int g5 (int i)
const char *p4 = p3 + i;
const char *p5 = p4 + i;
- f (p0, p1, p2, p3, p4, p5);
+ sink (p0, p1, p2, p3, p4, p5);
return p5[5];
}
@@ -90,7 +79,7 @@ NOIPA int g6 (int i)
const char *p5 = p4 + i;
const char *p6 = p5 + i;
- f (p0, p1, p2, p3, p4, p5, p6);
+ sink (p0, p1, p2, p3, p4, p5, p6);
return p6[4];
}
@@ -108,7 +97,7 @@ NOIPA int g7 (int i)
const char *p6 = p5 + i;
const char *p7 = p6 + i;
- f (p0, p1, p2, p3, p4, p5, p6, p7);
+ sink (p0, p1, p2, p3, p4, p5, p6, p7);
return p7[3];
}
@@ -127,7 +116,7 @@ NOIPA int g8 (int i)
const char *p7 = p6 + i;
const char *p8 = p7 + i;
- f (p0, p1, p2, p3, p4, p5, p6, p7, p8);
+ sink (p0, p1, p2, p3, p4, p5, p6, p7, p8);
return p8[2];
}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-70.c b/gcc/testsuite/gcc.dg/Warray-bounds-70.c
new file mode 100644
index 0000000..087e255
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-70.c
@@ -0,0 +1,18 @@
+/* PR middle-end/97556 - ICE on excessively large index into a multidimensional
+ array
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+#define SIZE_MAX __SIZE_MAX__
+
+typedef __SIZE_TYPE__ size_t;
+
+char a[1][3];
+
+void f (int c)
+{
+ size_t i = c ? SIZE_MAX / 2 : SIZE_MAX;
+ a[i][0] = 0; // { dg-warning "\\\[-Warray-bounds" }
+}
+
+// { dg-prune-output "\\\[-Wstringop-overflow=" }
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
new file mode 100644
index 0000000..2b00d77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
@@ -0,0 +1,279 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempting to reallocate unallocated objects referenced
+ either directly or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* alloca (size_t);
+extern void* realloc (void*, size_t);
+
+void sink (void*, ...);
+
+extern void* eparr[];
+extern char *eptr;
+
+extern size_t n;
+
+
+void nowarn_realloc (void *p, size_t n)
+{
+ char *q = realloc (p, n);
+ sink (q);
+
+ q = realloc (0, n);
+ sink (q);
+
+ q = realloc (q, n * 2);
+ sink (q);
+}
+
+/* Verify that calling realloc on a pointer to an unknown object minus
+ some nonzero offset isn't diagnosed, but a pointer plus a positive
+ offset is (a positive offset cannot point at the beginning). */
+
+void test_realloc_offset (char *p1, char *p2, char *p3, size_t n, int i)
+{
+ char *q;
+ q = realloc (p1 - 1, n);
+ sink (q);
+
+ q = realloc (p2 + 1, n); // { dg-warning "'realloc' called on pointer 'p2' with nonzero offset 1" }
+ sink (q);
+
+ q = realloc (p3 + i, n);
+ sink (q);
+}
+
+void warn_realloc_extern_arr (void)
+{
+ extern char ecarr[]; // { gg-message "declared here" }
+ char *p = ecarr;
+ char *q = realloc (p, n); // { dg-warning "'realloc' called on unallocated object 'ecarr'" }
+ sink (q);
+}
+
+void warn_realloc_extern_arr_offset (int i)
+{
+ extern char ecarr[];
+ char *p = ecarr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void warn_realloc_string (int i)
+{
+ char *p, *q;
+ {
+ p = "123";
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "234" + 1;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "123" + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_alloca (int n, int i)
+{
+ char *p, *q;
+ {
+ p = alloca (n);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 1);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 2) + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_local_arr (int i)
+{
+ char *q;
+ {
+ char a[4];
+ sink (a);
+ q = realloc (a, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char b[5];
+ sink (b);
+ q = realloc (b + 1, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char c[6];
+ sink (c);
+ q = realloc (&c[2], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char d[7];
+ sink (d);
+ q = realloc (&d[i], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void warn_realloc_vla (int n1, int n2, int i)
+{
+ char *q;
+ {
+ char vla[n1];
+ sink (vla);
+ q = realloc (vla, n2); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlb[n1 + 1];
+ sink (vlb);
+ q = realloc (vlb + 1, n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlc[n1 + 2];
+ sink (vlc);
+ q = realloc (&vlc[2], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vld[7];
+ sink (vld);
+ q = realloc (&vld[i], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void nowarn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (*eparr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (eparr, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void warn_realloc_extern_ptrarr_offset (int i)
+{
+ void *p = eparr + i;
+ void *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_extern_ptr (void)
+{
+ char *q = realloc (eptr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *p = eptr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void nowarn_realloc_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void nowarn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // The offset is from p, not *p.
+ void *q = *(p + i);
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // Unlike in the function above the offset is from *p.
+ void *q = *p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
new file mode 100644
index 0000000..a472b93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
@@ -0,0 +1,57 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced indirectly through
+ pointers obtained from function calls is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern char* memchr (const void*, int, size_t);
+extern char* strchr (const char*, int);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+
+void warn_free_memchr_ecarr (int x, size_t n)
+{
+ char *p = memchr (ecarr, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_ecarr_offset (int i, int j, int x, size_t n)
+{
+ char *p = memchr (ecarr + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_memchr_local_arr (int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_local_arr_offset (int i, int j, int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
new file mode 100644
index 0000000..bb222cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
@@ -0,0 +1,273 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed. In most cases this doesn't require
+ optimization.
+ { dg-do compile }
+ { dg-options "-Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* malloc (size_t);
+extern void* realloc (void *p, size_t);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = "123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = "456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+// Range information requires optimization.
+#pragma GCC optimize "1"
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wmismatched-dealloc-2.c b/gcc/testsuite/gcc.dg/Wmismatched-dealloc-2.c
new file mode 100644
index 0000000..21a5ea7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmismatched-dealloc-2.c
@@ -0,0 +1,141 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments has the expected
+ effect on diagnostics.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__), noipa))
+
+typedef __SIZE_TYPE__ size_t;
+typedef struct A A;
+typedef struct B B;
+
+/* A pointer returned by any of the four functions must be deallocated
+ either by dealloc() or by realloc_{A,B}(). */
+A (__builtin_free) A* alloc_A (int);
+A (__builtin_free) B* alloc_B (int);
+A (__builtin_free) A* realloc_A (A *p, int n) { return p; }
+A (__builtin_free) B* realloc_B (B *p, int n) { return p; }
+
+A (realloc_A) A* alloc_A (int);
+A (realloc_B) B* alloc_B (int);
+A (realloc_A) A* realloc_A (A*, int);
+A (realloc_B) B* realloc_B (B*, int);
+
+void dealloc (void*);
+A (dealloc) void* alloc (int);
+
+void sink (void*);
+
+void test_alloc_A (void)
+{
+ {
+ void *p = alloc_A (1);
+ p = realloc_A (p, 2);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = alloc_A (1);
+ /* Verify that calling realloc doesn't trigger a warning even though
+ alloc_A is not directly associated with it. */
+ p = __builtin_realloc (p, 2);
+ sink (p);
+ }
+
+ {
+ void *p = alloc_A (1); // { dg-message "returned from 'alloc_A'" }
+ dealloc (p); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ /* Because alloc_A() and realloc_B() share free() as a deallocator
+ they must also be valid as each other's deallocators. */
+ void *p = alloc_A (1);
+ p = realloc_B ((B*)p, 2);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = alloc_A (1);
+ p = realloc_A (p, 2);
+ p = __builtin_realloc (p, 3);
+ __builtin_free (p);
+ }
+}
+
+
+void test_realloc_A (void *ptr)
+{
+ {
+ void *p = realloc_A (0, 1);
+ p = realloc_A (p, 2);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = realloc_A (ptr, 2);
+ p = realloc_A (p, 2);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = realloc_A (0, 3);
+ p = __builtin_realloc (p, 2);
+ sink (p);
+ }
+
+ {
+ void *p = realloc_A (0, 4); // { dg-message "returned from 'realloc_A'" }
+ dealloc (p); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ /* Because realloc_A() and realloc_B() share free() as a deallocator
+ they must also be valid as each other's deallocators. */
+ void *p = realloc_A (0, 5);
+ p = realloc_B ((B*)p, 2);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = realloc_A (0, 6);
+ p = realloc_A ((A*)p, 2);
+ p = __builtin_realloc (p, 3);
+ __builtin_free (p);
+ }
+}
+
+
+void test_realloc (void *ptr)
+{
+ extern void free (void*);
+ extern void* realloc (void*, size_t);
+
+ {
+ void *p = realloc (ptr, 1);
+ p = realloc_A (p, 2);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = realloc (ptr, 2);
+ p = realloc_A (p, 2);
+ free (p);
+ }
+
+ {
+ void *p = realloc (ptr, 3);
+ free (p);
+ }
+
+ {
+ void *p = realloc (ptr, 4);
+ __builtin_free (p);
+ }
+
+ {
+ void *p = realloc (ptr, 5); // { dg-message "returned from 'realloc'" }
+ dealloc (p); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wmismatched-dealloc-3.c b/gcc/testsuite/gcc.dg/Wmismatched-dealloc-3.c
new file mode 100644
index 0000000..5afcea3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmismatched-dealloc-3.c
@@ -0,0 +1,265 @@
+/* Verify that Glibc <stdlib.h> declarations are handled correctly
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__), noipa))
+
+typedef __SIZE_TYPE__ size_t;
+
+/* All functions with the same standard deallocator are associated
+ with each other. */
+void free (void*);
+void* calloc (size_t, size_t);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+A (__builtin_free) void* aligned_alloc (size_t, size_t);
+
+/* Like realloc(), reallocarray() is both an allocator and a deallocator.
+ It must be associated with both free() and with itself, but nothing
+ else. */
+A (__builtin_free) void* reallocarray (void*, size_t, size_t);
+A (reallocarray) void* reallocarray (void*, size_t, size_t);
+
+A (__builtin_free) extern char *canonicalize_file_name (const char*);
+
+
+void dealloc (void*);
+A (dealloc) void* alloc (size_t);
+
+
+void sink (void*);
+void* source (void);
+
+
+void test_builtin_aligned_alloc (void *p)
+{
+ {
+ void *q = __builtin_aligned_alloc (1, 2);
+ sink (q);
+ __builtin_free (q);
+ }
+
+ {
+ void *q = __builtin_aligned_alloc (1, 2);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_aligned_alloc (1, 2);
+ q = __builtin_realloc (q, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_aligned_alloc (1, 2);
+ q = realloc (q, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q;
+ q = __builtin_aligned_alloc (1, 2); // { dg-message "returned from '__builtin_aligned_alloc'" }
+ sink (q);
+ dealloc (q); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_aligned_alloc (void *p)
+{
+ {
+ void *q = aligned_alloc (1, 2);
+ sink (q);
+ __builtin_free (q);
+ }
+
+ {
+ void *q = aligned_alloc (1, 2);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = aligned_alloc (1, 2);
+ q = __builtin_realloc (q, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = aligned_alloc (1, 2);
+ q = realloc (q, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = aligned_alloc (1, 2); // { dg-message "returned from 'aligned_alloc'" }
+ sink (q);
+ dealloc (q); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_reallocarray (void *p)
+{
+ {
+ void *q = __builtin_aligned_alloc (1, 2);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = aligned_alloc (1, 2);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_calloc (1, 2);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = calloc (1, 2);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_malloc (1);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = malloc (1);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_realloc (p, 1);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = realloc (p, 1);
+ q = reallocarray (q, 2, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_strdup ("abc");
+ q = reallocarray (q, 3, 4);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = __builtin_strndup ("abcd", 3);
+ q = reallocarray (q, 4, 5);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = source ();
+ q = reallocarray (q, 5, 6);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = alloc (1); // { dg-message "returned from 'alloc'" }
+ q = reallocarray (q, 6, 7); // { dg-warning "'reallocarray' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = reallocarray (p, 7, 8);
+ q = __builtin_realloc (q, 9);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = reallocarray (p, 7, 8);
+ q = realloc (q, 9);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = reallocarray (p, 8, 9);
+ q = reallocarray (q, 3, 4);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = reallocarray (p, 9, 10);
+ q = reallocarray (q, 3, 4);
+ sink (q);
+ dealloc (q); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_canonicalize_filename (void *p)
+{
+ {
+ void *q = canonicalize_file_name ("a");
+ sink (q);
+ __builtin_free (q);
+ }
+
+ {
+ void *q = canonicalize_file_name ("b");
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = canonicalize_file_name ("c");
+ q = __builtin_realloc (q, 2);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = canonicalize_file_name ("d");
+ q = realloc (q, 3);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q = canonicalize_file_name ("e");
+ q = reallocarray (q, 4, 5);
+ sink (q);
+ free (q);
+ }
+
+ {
+ void *q;
+ q = canonicalize_file_name ("f"); // { dg-message "returned from 'canonicalize_file_name'" }
+ sink (q);
+ dealloc (q); // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
new file mode 100644
index 0000000..6336efa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
@@ -0,0 +1,327 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments has the expected
+ effect on diagnostics.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+void free (void*);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+/* Declare functions with the minimum attributes malloc how they're
+ likely going to be declared in <stdio.h>. */
+ int fclose (FILE*);
+A (fclose) FILE* fdopen (int);
+A (fclose) FILE* fopen (const char*, const char*);
+A (fclose) FILE* fmemopen(void *, size_t, const char *);
+A (fclose) FILE* freopen (const char*, const char*, FILE*);
+A (freopen, 3) FILE* freopen (const char*, const char*, FILE*);
+A (fclose) FILE* tmpfile (void);
+
+A (fclose) FILE* open_memstream (char**, size_t*);
+A (fclose) FILE* open_wmemstream (char**, size_t*);
+
+ int pclose (FILE*);
+A (pclose) FILE* popen (const char*, const char*);
+
+ void release (void*);
+A (release) FILE* acquire (void);
+
+void sink (FILE*);
+
+
+void nowarn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ q = freopen ("1", "r", q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ sink (q);
+ }
+}
+
+
+void warn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void nowarn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("2", "r");
+ sink (q);
+ q = freopen ("3", "r", q);
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("4", "r");
+ sink (q);
+ }
+}
+
+
+void warn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void test_freopen (FILE *p[])
+{
+ {
+ FILE *q = freopen ("1", "r", p[0]);
+ sink (q);
+ fclose (q);
+ }
+ {
+ FILE *q = freopen ("2", "r", p[1]);
+ sink (q);
+ q = freopen ("3", "r", q);
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q;
+ q = freopen ("3", "r", p[2]); // { dg-message "returned from 'freopen'" }
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void test_tmpfile (void)
+{
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ p = freopen ("1", "r", p);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile (); // { dg-message "returned from 'tmpfile'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_open_memstream (char **bufp, size_t *sizep)
+{
+ {
+ FILE *p = open_memstream (bufp, sizep);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = open_memstream (bufp, sizep);
+ sink (p);
+ p = freopen ("1", "r", p);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p;
+ p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p;
+ p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
+ sink (p);
+ free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p;
+ p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
+ sink (p);
+ release (p); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_open_wmemstream (char **bufp, size_t *sizep)
+{
+ {
+ FILE *p = open_wmemstream (bufp, sizep);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = open_wmemstream (bufp, sizep);
+ sink (p);
+ p = freopen ("1", "r", p);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p;
+ p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p;
+ p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
+ sink (p);
+ free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p;
+ p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
+ sink (p);
+ release (p); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void warn_malloc (void)
+{
+ {
+ FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_acquire (void)
+{
+ {
+ FILE *p = acquire ();
+ release (p);
+ }
+
+ {
+ FILE *p = acquire ();
+ sink (p);
+ release (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p); // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
+ sink (p);
+ free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
+ sink (p);
+ p = realloc (p, 123); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstring-compare-3.c b/gcc/testsuite/gcc.dg/Wstring-compare-3.c
new file mode 100644
index 0000000..d4d7121
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstring-compare-3.c
@@ -0,0 +1,106 @@
+/* PR middle-end/95673 - missing -Wstring-compare for an impossible strncmp test
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wstring-compare -ftrack-macro-expansion=0" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern int strcmp (const char*, const char*);
+extern int strncmp (const char*, const char*, size_t);
+
+void sink (int, ...);
+
+extern char a3[3];
+
+int nowarn_strcmp_one_use_ltz (int c)
+{
+ const char *s = c ? "1234" : a3;
+ int n = strcmp (s, "123");
+ return n < 0;
+}
+
+
+int nowarn_strcmp_one_use_eqnz (int c)
+{
+ const char *s = c ? "12345" : a3;
+ int n = strcmp (s, "123");
+ return n == 1;
+}
+
+
+int warn_strcmp_one_use_eqz (int c)
+{
+ const char *s = c ? "123456" : a3;
+ int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" }
+ return n == 0; // { dg-message "in this expression" }
+}
+
+
+int warn_strcmp_one_use_bang (int c)
+{
+ const char *s = c ? "1234567" : a3;
+ int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" }
+ return !n; // { dg-message "in this expression" }
+}
+
+
+int warn_strcmp_one_use_bang_bang (int c)
+{
+ const char *s = c ? "12345678" : a3;
+ int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" }
+ return !!n; // { dg-message "in this expression" }
+}
+
+
+_Bool warn_one_use_bool (int c)
+{
+ const char *s = c ? "123456789" : a3;
+ int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" }
+ return (_Bool)n; // { dg-message "in this expression" }
+}
+
+
+int warn_strcmp_one_use_cond (int c)
+{
+ const char *s = c ? "1234567890" : a3;
+ int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" }
+ return n ? 3 : 5; // { dg-message "in this expression" }
+}
+
+
+int nowarn_strcmp_multiple_uses (int c)
+{
+ const char *s = c ? "1234" : a3;
+ int n = strcmp (s, "123");
+ sink (n < 0);
+ sink (n > 0);
+ sink (n <= 0);
+ sink (n >= 0);
+ sink (n + 1);
+ return n;
+}
+
+
+int warn_strcmp_multiple_uses (int c)
+{
+ const char *s = c ? "12345" : a3;
+ int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" }
+ sink (n < 0);
+ sink (n > 0);
+ sink (n <= 0);
+ sink (n >= 0);
+ sink (n == 0); // { dg-message "in this expression" }
+ return n;
+}
+
+
+int warn_strncmp_multiple_uses (int c)
+{
+ const char *s = a3;
+ int n = strncmp (s, "1234", 4); // { dg-warning "'strncmp' of a string of length 4, an array of size 3 and bound of 4 evaluates to nonzero" }
+ sink (n < 0);
+ sink (n > 0);
+ sink (n <= 0);
+ sink (n >= 0);
+ sink (n == 0); // { dg-message "in this expression" }
+ return n;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c
index f5dac45..ec3c97e 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c
@@ -72,7 +72,7 @@ void test_memset_array_range_cst_off (void)
{
T (SR (-7, 7), 1, 7);
T (SR (-1, 1), 1, 7);
- T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */
+ T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (SR ( 1, 2), 1, 1);
T (SR ( 1, 2), 1, 5);
@@ -147,7 +147,7 @@ void test_memcpy_array_range_cst_off (const void *s)
{
T (SR (-7, 7), 1, 7);
T (SR (-1, 1), 1, 7);
- T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */
+ T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (SR ( 1, 2), 1, 1);
T (SR ( 1, 2), 1, 5);
@@ -224,7 +224,7 @@ void test_strcpy_array_range_cst_off (const char *s)
{
T (SR (-7, 7), 1, 6);
T (SR (-1, 1), 1, 6);
- T (SR (-1, 1), 1, 8); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */
+ T (SR (-1, 1), 1, 8); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (SR ( 1, 2), 1, 0);
T (SR ( 1, 2), 1, 1);
T (SR ( 1, 2), 1, 4);
@@ -290,7 +290,7 @@ void test_strncpy_array_range_cst_off (const char *s)
{
T (SR (-7, 7), 1, 7);
T (SR (-1, 1), 1, 7);
- T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */
+ T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */
T (SR ( 1, 2), 1, 1);
T (SR ( 1, 2), 1, 5);
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c
index 1e67b5f..7c3dc8c 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c
@@ -25,7 +25,9 @@ void test_memcpy_array_cst_range_off (const void *s)
T (d + UR (1, 2), 5);
T (d + UR (0, 1), 6);
- T (d + UR (0, 1), 7); /* { dg-warning ".memcpy. writing 6 bytes into a region of size 5 overflows the destination" "pr89428" { xfail *-*-* } } */
+ /* The warning below should be "writing" but the [0, 1] range
+ is somehow lost and get_range_info() returns VR_VARYING. */
+ T (d + UR (0, 1), 7); /* { dg-warning ".memcpy. writing 7 bytes into a region of size 6 overflows the destination" "pr89428" { xfail *-*-* } } */
T (d + UR (1, 2), 6); /* { dg-warning ".memcpy. writing 6 bytes into a region of size 5 overflows the destination" } */
T (d + UR (1, 2), 7); /* { dg-warning "writing 7 bytes into a region of size 5 " } */
@@ -48,7 +50,8 @@ void test_memcpy_array_range_range_off (const void *s)
char *d = ga7 + UR (0, 1);
T (d + SR (-1, 0), 1);
T (d + SR (-1, 0), 7);
- T (d + SR (-1, 0), 9); /* { dg-warning "writing 1 byte into a region of size 0 " "pr89350" { xfail *-*-* } } */
+ T (d + SR (-1, 0), 8); /* { dg-warning "writing 8 bytes into a region of size 7 " } */
+ T (d + SR (-1, 0), 9); /* { dg-warning "writing 9 bytes into a region of size 7 " "pr89350" } */
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c
index fb81420..9c05d04 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c
@@ -13,7 +13,7 @@ void sink (void*);
void call_copy_n (const char *s)
{
- char a[7]; // { dg-message "declared here" }
+ char a[7]; // { dg-message "at offset 7 into destination object 'a'" }
copy_n (a, "1234567", 7);
sink (a);
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c
index 37c1ca2..607c279 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c
@@ -261,8 +261,7 @@ void test_strcpy_warn (const char *s)
that the conversion from signed int to size_t doesn't prevent
the detection. */
int n = strlen (a);
- char *t = (char*)calloc (n, 1); // { dg-message "at offset 0 to an object with size 3 allocated by 'calloc' here" "calloc note 1" { xfail *-*-* } }
- // { dg-message "at offset 0 to an object with size at most 3 allocated by 'calloc' here" "calloc note 2" { target *-*-* } .-1 }
+ char *t = (char*)calloc (n, 1); // { dg-message "destination object of size 3 allocated by 'calloc'" "note" }
strcpy (t, a); // { dg-warning "writing 4 bytes into a region of size (between 0 and )?3 " }
sink (t);
@@ -271,8 +270,7 @@ void test_strcpy_warn (const char *s)
{
const char a[] = "1234";
size_t n = strlen (a);
- char *t = (char*)malloc (n); // { dg-message "at offset 0 to an object with size 4 allocated by 'malloc' here" "malloc note 1" { xfail *-*-* } }
- // { dg-message "at offset 0 to an object with size at most 4 allocated by 'malloc' here" "malloc note 2" { target *-*-* } .-1 }
+ char *t = (char*)malloc (n); // { dg-message "destination object of size 4 allocated by 'malloc'" "note" }
strcpy (t, a); // { dg-warning "writing 5 bytes into a region of size (between 0 and )?4 " }
sink (t);
}
@@ -280,14 +278,14 @@ void test_strcpy_warn (const char *s)
// Exercise PR middle-end/85484.
{
size_t len = strlen (s);
- char vla[len]; // { dg-message "at offset 0 to an object declared here" "vla note" }
+ char vla[len]; // { dg-message "destination object 'vla'" "vla note" }
strcpy (vla, s); // { dg-warning "writing one too many bytes into a region of a size that depends on 'strlen'" }
sink (vla);
}
{
size_t n = strlen (s);
- char *t = (char*)malloc (n); // { dg-message "at offset 0 to an object allocated by 'malloc' here" "malloc note" }
+ char *t = (char*)malloc (n); // { dg-message "allocated by 'malloc'" "malloc note" }
strcpy (t, s); // { dg-warning "writing one too many bytes into a region of a size that depends on 'strlen'" }
sink (t);
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c
index be7f51a..5009fb5 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c
@@ -40,27 +40,27 @@ void same_size_and_offset_idx_cst (void)
const size_t n = UR (2, 3);
T (n, n, -4); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[-2, -1] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[-2, -1] into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
T (n, n, -3);
T (n, n, -2);
T (n, n, -1);
T (n, n, 0);
T (n, n, 1); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[3, 4] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset 3 into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
}
{
const size_t n = UR (3, 4);
T (n, n, -5); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[-2, -1] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[-2, -1] into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
T (n, n, -4);
T (n, n, -3);
T (n, n, -2);
T (n, n, -1);
T (n, n, 0);
T (n, n, 1); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[4, 5] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset 4 into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
}
{
@@ -84,15 +84,15 @@ void different_size_and_offset_idx_cst (void)
const size_t i = UR (1, 2);
T (n, i, -4); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[-3, -2] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[-3, -2] into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
T (n, i, -3); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[-2, -1] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[-2, -1] into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
T (n, i, -2);
T (n, i, -1);
T (n, i, 0);
T (n, i, 1);
T (n, i, 2); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[3, 4] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset 3 into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
}
{
@@ -100,20 +100,20 @@ void different_size_and_offset_idx_cst (void)
const size_t i = UR (2, 5);
T (n, i, -6); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[-4, -1] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[-4, -2] into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
- /* The offsets -5 and -4 are both necessarily invalid even if the sum
- (i - 5) and (i - 4) are (or could be) in bounds because they imply
- that the intermediate offset (p + i) is out of bounds. */
- T (n, i, -5); // { dg-warning "" "intermediate offset" { xfail *-*-* } }
- T (n, i, -4); // { dg-warning "" "intermediate offset" { xfail *-*-* } }
+ /* The offset -5 is necessarily invalid even if the sum (i - 5) is (or
+ could be) in bounds because it implies that the intermediate offset
+ (p + i) is out of bounds. */
+ T (n, i, -5); // { dg-warning "writing 1 byte into a region of size 0 " }
+ T (n, i, -4);
T (n, i, -3);
T (n, i, -2);
T (n, i, -1);
T (n, i, 0);
T (n, i, 1);
T (n, i, 2); // { dg-warning "writing 1 byte into a region of size 0" }
- // { dg-message "at offset \\\[4, 7] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset 4 into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 }
}
}
@@ -133,11 +133,8 @@ void different_size_and_offset_idx_var (void)
T (n, i, SR ( 0, 1));
T (n, i, SR ( 1, 2));
T (n, i, SR ( 2, 3));
- /* The warning is issued below but the offset and the size in
- the note are wrong. See the FIXME in compute_objsize(). */
T (n, i, SR ( 3, 4)); // { dg-warning "\\\[-Wstringop-overflow" }
- // { dg-message "at offset 4 to an object with size between 3 and 4 allocated by 'alloc1'" "pr92940 note: offset addition" { xfail *-*-* } .-1 }
- // { dg-message "at offset . to an object with size . allocated by 'alloc1'" "note: offset addition" { target *-*-* } .-2 }
+ // { dg-message "at offset 4 into destination object of size \\\[3, 4] allocated by 'alloc1'" "pr92940 note: offset addition" { target *-*-* } .-1 }
}
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c
index c011d05..f13abbd 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c
@@ -11,7 +11,7 @@ void sink (void*);
void direct_call (void)
{
- char *q = allocfn (0); // { dg-message "at offset 0 to an object with size 0 allocated by 'allocfn'" }
+ char *q = allocfn (0); // { dg-message "object of size 0 allocated by 'allocfn'" "note" }
q[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
sink (q);
}
@@ -20,7 +20,7 @@ void direct_call (void)
void local_ptr_call (void)
{
allocfn_t *ptr = allocfn;
- char *q = ptr (1); // { dg-message "at offset -1 to an object with size 1 allocated by 'allocfn'" }
+ char *q = ptr (1); // { dg-message "at offset -1 into destination object of size 1 allocated by 'allocfn'" "note" }
q[0] = 0;
q[-1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
sink (q);
@@ -32,7 +32,7 @@ void global_ptr_call (void)
extern allocfn_t *ptralloc;
allocfn_t *ptr = ptralloc;
- char *q = ptr (2); // { dg-message "at offset 3 to an object with size 2 allocated by 'ptralloc'" }
+ char *q = ptr (2); // { dg-message "at offset 3 into destination object of size 2 allocated by 'ptralloc'" "note" }
q[0] = 0;
q[1] = 1;
q[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
@@ -44,7 +44,7 @@ void global_ptr_array_call (void)
extern allocfn_t * (arralloc[]);
allocfn_t *ptr = arralloc[0];
- char *q = ptr (2); // { dg-message "at offset 3 to an object with size 2 allocated by 'ptr'" }
+ char *q = ptr (2); // { dg-message "at offset 3 into destination object of size 2 allocated by 'ptr'" "note" }
q[0] = 1;
q[1] = 2;
q[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
@@ -56,7 +56,7 @@ struct S { allocfn_t *ptralloc; };
void member_ptr_call (struct S *p)
{
- char *q = p->ptralloc (3); // { dg-message "at offset 5 to an object with size 3 allocated by 'ptralloc' here" }
+ char *q = p->ptralloc (3); // { dg-message "at offset 5 into destination object of size 3 allocated by 'ptralloc'" "note" }
q[0] = 0;
q[1] = 1;
q[2] = 2;
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c
index 46f8fed..d9cf32d 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c
@@ -67,7 +67,7 @@ void* warn_malloc_3_5 (const char *s, unsigned n)
{
if (n < 3 || 5 < n)
n = 3;
- char *p = (char*)malloc (n); // { dg-message "at offset 1 into destination object of size \\\[3, 5] allocated by 'malloc'" }
+ char *p = (char*)malloc (n); // { dg-message "at offset 1 into destination object of size \\\[3, 5] allocated by 'malloc'" "note" }
// The size below should be a range like the one above.
strncpy (p + 1, s, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
return p;
@@ -89,7 +89,7 @@ void* warn_usr_alloc_3_5 (UsrAlloc *usr_alloc, const char *s, unsigned n)
{
if (n < 3 || 5 < n)
n = 3;
- char *p = (char*)usr_alloc (n, 3); // { dg-message "at offset 1 into destination object of size \\\[9, 15] allocated by 'usr_alloc'" }
+ char *p = (char*)usr_alloc (n, 3); // { dg-message "at offset 1 into destination object of size \\\[9, 15] allocated by 'usr_alloc'" "note" }
// The size below should be a range like the one above.
strncpy (p + 1, s, 15); // { dg-warning "writing 15 bytes into a region of size 14 " }
return p;
@@ -179,67 +179,67 @@ void test_note (const char *s)
extern void sink (void*);
{
- char a[1][1][2]; // { dg-message "destination object" }
+ char a[1][1][2]; // { dg-message "destination object" "note" }
strncpy (a[0][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
sink (a);
}
{
- char a[1][1][2]; // { dg-message "at offset 2 into " }
+ char a[1][1][2]; // { dg-message "at offset 2 into " "note" }
strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " }
sink (a);
}
{
- char a[1][2][2]; // { dg-message "destination object" }
+ char a[1][2][2]; // { dg-message "destination object" "note" }
strncpy (a[0][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
sink (a);
}
{
- char a[1][2][2]; // { dg-message "at offset 2 into " }
+ char a[1][2][2]; // { dg-message "at offset 2 into " "note" }
strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
sink (a);
}
{
- char a[1][2][2]; // { dg-message "at offset 4 into " }
+ char a[1][2][2]; // { dg-message "at offset 4 into " "note" }
strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " }
sink (a);
}
{
- char a[2][1][2]; // { dg-message "at offset 2 into " }
+ char a[2][1][2]; // { dg-message "at offset 2 into " "note" }
strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " }
sink (a);
}
{
- char a[2][1][2]; // { dg-message "at offset 2 into " }
+ char a[2][1][2]; // { dg-message "at offset 2 into " "note" }
strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
sink (a);
}
{
- char a[2][2][3]; // { dg-message "at offset 9 into " }
+ char a[2][2][3]; // { dg-message "at offset 9 into " "note" }
strncpy (a[1][1], s, 4); // { dg-warning "writing 4 bytes into a region of size 3 " }
sink (a);
}
{
- char a[2][3][3]; // { dg-message "at offset 12 into " }
+ char a[2][3][3]; // { dg-message "at offset 12 into " "note" }
strncpy (a[1][1], s, 5); // { dg-warning "writing 5 bytes into a region of size 3 " }
sink (a);
}
{
- char a[2][3][3]; // { dg-message "at offset 12 into " }
+ char a[2][3][3]; // { dg-message "at offset 12 into " "note" }
strncpy (a[1][1], s, 6); // { dg-warning "writing 6 bytes into a region of size 3 " }
sink (a);
}
{
- char a[2][3][3]; // { dg-message "at offset 15 into " }
+ char a[2][3][3]; // { dg-message "at offset 15 into " "note" }
strncpy (a[1][2], s, 7); // { dg-warning "writing 7 bytes into a region of size 3 " }
sink (a);
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-44.s b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.s
deleted file mode 100644
index 0fc73a9..0000000
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-44.s
+++ /dev/null
@@ -1,271 +0,0 @@
- .file "Wstringop-overflow-44.c"
- .text
- .p2align 4
- .globl f0
- .type f0, @function
-f0:
-.LFB0:
- .cfi_startproc
- ret
- .cfi_endproc
-.LFE0:
- .size f0, .-f0
- .p2align 4
- .globl f1
- .type f1, @function
-f1:
-.LFB1:
- .cfi_startproc
- ret
- .cfi_endproc
-.LFE1:
- .size f1, .-f1
- .p2align 4
- .globl f2
- .type f2, @function
-f2:
-.LFB2:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L12
-.L4:
- ret
- .p2align 4,,10
- .p2align 3
-.L12:
- movslq %eax, %rdx
- movq d(%rip), %rcx
- testq %rdx, %rdx
- je .L4
- xorl %eax, %eax
-.L6:
- movb $0, (%rcx,%rax)
- addq $1, %rax
- cmpq %rdx, %rax
- jb .L6
- ret
- .cfi_endproc
-.LFE2:
- .size f2, .-f2
- .p2align 4
- .globl f3
- .type f3, @function
-f3:
-.LFB3:
- .cfi_startproc
- movslq n(%rip), %rdx
- testl %edx, %edx
- jle .L15
- ret
- .p2align 4,,10
- .p2align 3
-.L15:
- movq %rdi, %rsi
- movq d(%rip), %rdi
- jmp strncpy
- .cfi_endproc
-.LFE3:
- .size f3, .-f3
- .p2align 4
- .globl f4
- .type f4, @function
-f4:
-.LFB4:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L18
- ret
- .p2align 4,,10
- .p2align 3
-.L18:
- movq d(%rip), %rax
- movq %rdi, %rsi
- movb $0, (%rax)
- movslq n(%rip), %rdx
- movq d(%rip), %rdi
- jmp strncat
- .cfi_endproc
-.LFE4:
- .size f4, .-f4
- .p2align 4
- .globl g0
- .type g0, @function
-g0:
-.LFB5:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L25
- ret
- .p2align 4,,10
- .p2align 3
-.L25:
- subq $24, %rsp
- .cfi_def_cfa_offset 32
- leaq 15(%rsp), %rdi
- call sink
- addq $24, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE5:
- .size g0, .-g0
- .p2align 4
- .globl g1
- .type g1, @function
-g1:
-.LFB6:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L32
- ret
- .p2align 4,,10
- .p2align 3
-.L32:
- subq $24, %rsp
- .cfi_def_cfa_offset 32
- leaq 15(%rsp), %rdi
- call sink
- addq $24, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE6:
- .size g1, .-g1
- .p2align 4
- .globl g2
- .type g2, @function
-g2:
-.LFB7:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L45
- ret
- .p2align 4,,10
- .p2align 3
-.L45:
- movslq %eax, %rdx
- subq $24, %rsp
- .cfi_def_cfa_offset 32
- testq %rdx, %rdx
- je .L36
- xorl %eax, %eax
-.L35:
- movb $0, 15(%rsp,%rax)
- addq $1, %rax
- cmpq %rdx, %rax
- jb .L35
-.L36:
- leaq 15(%rsp), %rdi
- call sink
- addq $24, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE7:
- .size g2, .-g2
- .p2align 4
- .globl g3
- .type g3, @function
-g3:
-.LFB8:
- .cfi_startproc
- movslq n(%rip), %rdx
- testl %edx, %edx
- jle .L52
- ret
- .p2align 4,,10
- .p2align 3
-.L52:
- subq $24, %rsp
- .cfi_def_cfa_offset 32
- movq %rdi, %rsi
- leaq 15(%rsp), %rdi
- call strncpy
- leaq 15(%rsp), %rdi
- call sink
- addq $24, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE8:
- .size g3, .-g3
- .p2align 4
- .globl g4
- .type g4, @function
-g4:
-.LFB9:
- .cfi_startproc
- movslq n(%rip), %rdx
- testl %edx, %edx
- jle .L59
- ret
- .p2align 4,,10
- .p2align 3
-.L59:
- subq $24, %rsp
- .cfi_def_cfa_offset 32
- movq %rdi, %rsi
- leaq 15(%rsp), %rdi
- movb $0, 15(%rsp)
- call strncat
- leaq 15(%rsp), %rdi
- call sink
- addq $24, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE9:
- .size g4, .-g4
- .p2align 4
- .globl h0
- .type h0, @function
-h0:
-.LFB10:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L66
- ret
- .p2align 4,,10
- .p2align 3
-.L66:
- subq $8, %rsp
- .cfi_def_cfa_offset 16
- movl $1, %edi
- call malloc
- movq %rax, d(%rip)
- addq $8, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE10:
- .size h0, .-h0
- .p2align 4
- .globl h1
- .type h1, @function
-h1:
-.LFB16:
- .cfi_startproc
- movl n(%rip), %eax
- testl %eax, %eax
- jle .L73
- ret
- .p2align 4,,10
- .p2align 3
-.L73:
- subq $8, %rsp
- .cfi_def_cfa_offset 16
- movl $1, %edi
- call malloc
- movq %rax, d(%rip)
- addq $8, %rsp
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-.LFE16:
- .size h1, .-h1
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c
index a4d78b2..b126fcb 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c
@@ -53,7 +53,7 @@ void nowarn_memchr_anti_range_memset_cst (const void *s, size_t n)
void warn_memchr_cst_memset_cst (const void *s)
{
- char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" }
+ char *p = malloc (4); // { dg-message "destination object of size 4 " "note" }
sink (p);
p = memchr (p, '1', 4);
@@ -62,7 +62,7 @@ void warn_memchr_cst_memset_cst (const void *s)
void warn_memchr_var_memset_cst (const void *s, unsigned n)
{
- char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" }
+ char *p = malloc (4); // { dg-message "destination object of size 4 " "note" }
sink (p);
p = memchr (p, '1', n);
@@ -79,9 +79,9 @@ void warn_memchr_var_memset_range (const void *s, unsigned n)
as in the first two notes. The exact value probably isn't too
important. */
char *p0 = malloc (UR (5, 7));
- // { dg-message "at offset \\\[0, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-1 }
- // { dg-message "at offset \\\[1, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-2 }
- // { dg-message "at offset \\\[2, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-3 }
+ // { dg-message ": destination object of size \\\[5, 7]" "note 1" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[1, 7] into destination object of size \\\[5, 7]" "note 2" { target *-*-* } .-2 }
+ // { dg-message "at offset \\\[2, 7] into destination object of size \\\[5, 7]" "note 3" { target *-*-* } .-3 }
sink (p0);
char *p1 = memchr (p0, '1', n);
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c
index 02b14ee..cb2c329 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c
@@ -26,7 +26,7 @@ void nowarn_c32 (char c)
void warn_c32 (char c)
{
- extern char warn_a32[32]; // { dg-message "at offset 32 to object 'warn_a32' with size 32" }
+ extern char warn_a32[32]; // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "note" }
void *p = warn_a32 + 1;
*(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c
index 26568f8..f5929c9 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c
@@ -15,7 +15,7 @@ void sink (void*);
void char_flexarray_cst_off_cst_size (void)
{
extern struct { char n, a[]; }
- caxcc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'caxcc'" }
+ caxcc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'caxcc'" "note" }
char *p = caxcc.a;
size_t idx = DIFF_MAX - 4;
@@ -38,7 +38,7 @@ void char_flexarray_cst_off_cst_size (void)
void char_flexarray_var_off_cst_size (ptrdiff_t idx)
{
extern struct { char n, a[]; }
- caxvc; // { dg-message "destination object 'caxvc'" }
+ caxvc; // { dg-message "destination object 'caxvc'" "note" }
char *p = caxvc.a;
@@ -55,7 +55,7 @@ void char_flexarray_var_off_cst_size (ptrdiff_t idx)
void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx)
{
extern struct { char n, a[]; }
- caxvv; // { dg-message "destination object 'caxvv'" }
+ caxvv; // { dg-message "destination object 'caxvv'" "note" }
char *p = caxvv.a;
@@ -76,7 +76,7 @@ void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx)
void alloc_array_var_off_cst_size (size_t n, ptrdiff_t idx)
{
struct { char n, a[]; }
- *p = __builtin_malloc (n); // { dg-message "at offset \\d+ into destination object" }
+ *p = __builtin_malloc (n); // { dg-message "at offset \\d+ into destination object" "note" }
if (idx < DIFF_MAX - 4)
idx = DIFF_MAX - 4;
@@ -91,7 +91,7 @@ void alloc_array_var_off_cst_size (size_t n, ptrdiff_t idx)
void int_array_cst_off_cst_size (void)
{
extern struct { int n, a[]; }
- iaxc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'iaxc'" }
+ iaxc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'iaxc'" "note" }
int *p = iaxc.a;
size_t idx = DIFF_MAX / sizeof *p - 1;
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-56.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-56.c
new file mode 100644
index 0000000..b3e598c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-56.c
@@ -0,0 +1,163 @@
+/* PR middle-end/92942 - missing -Wstringop-overflow for allocations with
+ a negative lower bound size
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+#define SIZE_MAX __SIZE_MAX__
+#define UINT8_MAX __UINT8_MAX__
+#define UINT16_MAX __UINT16_MAX__
+
+typedef __SIZE_TYPE__ size_t;
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+
+void* usr_alloc1 (size_t) __attribute__ ((alloc_size (1)));
+void* usr_alloc2 (size_t, size_t) __attribute__ ((alloc_size (1, 2)));
+
+void* malloc (size_t);
+void* memcpy (void*, const void*, size_t);
+void* memset (void*, int, size_t);
+char* strcpy (char*, const char*);
+
+void sink (void*);
+
+void malloc_uint_range_strcpy (unsigned n)
+{
+ void *p = malloc (5 < n ? 5 : n);
+
+ strcpy (p, "01234"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "0123");
+ sink (p);
+}
+
+void malloc_uint16_anti_range_memset (uint16_t n)
+{
+ if (5 <= n && n <= 9) return;
+ void *p = malloc (n);
+
+ if (UINT16_MAX < SIZE_MAX)
+ {
+ size_t sz = (uint16_t)-1 + (size_t)1;
+ memset (p, 0, sz); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+ }
+
+ memset (p, 0, 1);
+ sink (p);
+ memset (p, 0, 5);
+ sink (p);
+ memset (p, 0, 6);
+ sink (p);
+ memset (p, 0, UINT16_MAX - 1);
+ sink (p);
+ memset (p, 0, UINT16_MAX);
+ sink (p);
+}
+
+void malloc_int_strcpy (int n)
+{
+ void *p = malloc (7 < n ? 7 : n);
+
+ strcpy (p, "0123456"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "012345");
+ sink (p);
+}
+
+void vla_int_strcpy (int n)
+{
+ char a[9 < n ? 9 : n];
+
+ strcpy (a, "012345678"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (a);
+
+ strcpy (a, "01234567");
+ sink (a);
+}
+
+void usr_alloc1_int_strcpy (int n)
+{
+ void *p = usr_alloc1 (7 < n ? 7 : n);
+
+ strcpy (p, "0123456"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "012345");
+ sink (p);
+}
+
+void usr_alloc2_cst_ir_strcpy (int n)
+{
+ void *p = usr_alloc2 (1, 5 < n ? 5 : n);
+
+ strcpy (p, "01234"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "0123");
+ sink (p);
+}
+
+void usr_alloc2_ir_ir_strcpy (int m, int n)
+{
+ void *p = usr_alloc2 (3 < n ? 3 : n, 5 < n ? 5 : n);
+
+ strcpy (p, "0123456789abcde"); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ strcpy (p, "0123456789abcd");
+ sink (p);
+}
+
+void usr_alloc2_uint8_memset (uint8_t m, uint8_t n)
+{
+ if (3 <= m && m <= 7) return;
+ if (5 <= n && n <= 9) return;
+ void *p = usr_alloc2 (m, n);
+
+ size_t sz = UINT8_MAX * UINT8_MAX + 1;
+ memset (p, 0, sz); // { dg-warning "\\\[-Wstringop-overflow" "" { xfail *-*-* } }
+ // { dg-warning "\\\[-Warray-bounds" "pr?????" { target *-*-* } .-1 }
+ sink (p);
+
+ memset (p, 0, sz - 1);
+ sink (p);
+ memset (p, 0, 64);
+ sink (p);
+ memset (p, 0, 63);
+ sink (p);
+ memset (p, 0, 16);
+ sink (p);
+ memset (p, 0, 15);
+ sink (p);
+ memset (p, 0, 14);
+ sink (p);
+ memset (p, 0, 3);
+ sink (p);
+}
+
+
+
+void malloc_int_memset (int n)
+{
+ void *p = malloc (11 < n ? 11 : n);
+
+ memset (p, 0, 12); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (p);
+
+ memset (p, 0, 11);
+ sink (p);
+}
+
+void vla_int_memset (int n)
+{
+ char a[13 < n ? 13 : n];
+
+ memset (a, 0, 14); // { dg-warning "\\\[-Wstringop-overflow" }
+ sink (a);
+
+ memset (a, 0, 13);
+ sink (a);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-57.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-57.c
new file mode 100644
index 0000000..173aa16
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-57.c
@@ -0,0 +1,91 @@
+/* Verify that an anti-range ~[A, B] with small positive A and B
+ is handled correctly and doesn't trigger warnings.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __typeof__ (sizeof 0) size_t;
+
+int f (void*, size_t);
+int g (void*);
+
+// Test case distilled from gcc/cp/semantics.c
+
+int omp_reduction_id (int i, int j, const char *mm)
+{
+ const char *p = 0;
+ const char *m = 0;
+
+ switch (i)
+ {
+ case 1:
+ p = "min";
+ break;
+ case 2:
+ p = "max";
+ break;
+ default:
+ break;
+ }
+
+ if (j)
+ m = mm;
+
+ const char prefix[] = "omp declare reduction ";
+ size_t lenp = sizeof (prefix);
+
+ if (__builtin_strncmp (p, prefix, lenp - 1) == 0)
+ lenp = 1;
+
+ size_t len = __builtin_strlen (p);
+ size_t lenm = m ? __builtin_strlen (m) + 1 : 0;
+ char *name = ((char *) __builtin_alloca(lenp + len + lenm));
+
+ if (lenp > 1)
+ __builtin_memcpy (name, prefix, lenp - 1);
+
+ __builtin_memcpy (name + lenp - 1, p, len + 1);
+ if (m)
+ {
+ name[lenp + len - 1] = '~';
+ __builtin_memcpy (name + lenp + len, m, lenm);
+ }
+ return (__builtin_constant_p (name)
+ ? f (name, __builtin_strlen (name)) : g (name));
+}
+
+// Test case derived from gcc/d/dmd/root/filename.c.
+
+const char *ext (const char *str)
+{
+ size_t len = __builtin_strlen(str);
+
+ const char *e = str + len;
+ for (;;)
+ {
+ switch (*e)
+ {
+ case '.': return e + 1;
+ case '/': break;
+ default:
+ if (e == str)
+ break;
+ e--;
+ continue;
+ }
+ return 0;
+ }
+}
+
+const char *removeExt (const char *str)
+{
+ const char *e = ext (str);
+ if (e)
+ {
+ size_t len = (e - str) - 1;
+ char *n = (char *)__builtin_malloc (len + 1);
+ __builtin_memcpy(n, str, len);
+ n[len] = 0;
+ return n;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-58.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-58.c
new file mode 100644
index 0000000..b81186c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-58.c
@@ -0,0 +1,260 @@
+/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
+ Exercise warnings for writing into one of two or more declared objects.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+#include "range.h"
+
+#define INT_MAX __INT_MAX__
+
+extern void* memset (void*, int, size_t);
+#define memset(d, c, n) sink (memset (d, c, n))
+
+void sink (int, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+volatile int cond1, cond2;
+
+extern char ca0[0], ca1[1], ca2[2], ca3[3], ca4[4],
+ ca5[5], ca6[6], ca7[7], ca8[8], ca9[9], cax[];
+
+#define CHOOSE_DECL_2(n1, n2) \
+ (cond1 ? ca ## n1 : ca ## n2)
+#define CHOOSE_DECL_3(n1, n2, n3) \
+ (cond1 < 0 ? ca ## n1 : 0 < cond1 ? ca ## n2 : ca ## n3)
+
+
+void memset_decl_2 (void)
+{
+ {
+ char *p0_1 = CHOOSE_DECL_2 (0, 1);
+
+ memset (p0_1, 0, 0);
+ /* Writing more than the smallest destination should trigger a "may
+ write" warning if the access is unconditionally reachable from
+ the block where the pointer to either object is assigned. */
+ memset (p0_1, 0, 1);
+ memset (p0_1, 0, 2); // { dg-warning "memset' writing 2 bytes into a region of size 1 " }
+ memset (p0_1, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 1 " }
+ }
+
+ {
+ char *p0_x = CHOOSE_DECL_2 (0, x);
+
+ memset (p0_x, 0, 0);
+ memset (p0_x, 0, 1);
+ memset (p0_x, 0, 2);
+ memset (p0_x, 0, 9);
+ }
+
+ {
+ char *p3_5 = CHOOSE_DECL_2 (3, 5);
+
+ memset (p3_5, 0, 1);
+ memset (p3_5, 0, 3);
+ memset (p3_5, 0, 4);
+ memset (p3_5, 0, 5);
+ memset (p3_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *p5_3 = CHOOSE_DECL_2 (5, 3);
+
+ memset (p5_3, 0, 3);
+ memset (p5_3, 0, 4);
+ memset (p5_3, 0, 5);
+ memset (p5_3, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *px_3 = CHOOSE_DECL_2 (x, 3);
+
+ memset (px_3, 0, 1);
+ memset (px_3, 0, 3);
+ memset (px_3, 0, 4);
+ memset (px_3, 0, 1234);
+ }
+
+ {
+ char *p5_x = CHOOSE_DECL_2 (5, x);
+
+ memset (p5_x, 0, 1);
+ memset (p5_x, 0, 5);
+ memset (p5_x, 0, 6);
+ memset (p5_x, 0, 1234);
+ }
+
+}
+
+
+void memset_decl_3 (void)
+{
+ {
+ char *p0_1_2 = CHOOSE_DECL_3 (0, 1, 2);
+ memset (p0_1_2, 0, 0);
+ memset (p0_1_2, 0, 1);
+ memset (p0_1_2, 0, 2);
+ memset (p0_1_2, 0, 3); // { dg-warning "memset' writing 3 bytes into a region of size 2 " }
+ memset (p0_1_2, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 2 " }
+ }
+
+ {
+ char *p0_2_x = CHOOSE_DECL_3 (0, 2, x);
+
+ memset (p0_2_x, 0, 0);
+ memset (p0_2_x, 0, 1);
+ memset (p0_2_x, 0, 3);
+ memset (p0_2_x, 0, 9);
+ }
+
+ {
+ char *p3_4_5 = CHOOSE_DECL_3 (3, 4, 5);
+
+ memset (p3_4_5, 0, 3);
+ memset (p3_4_5, 0, 4);
+ memset (p3_4_5, 0, 5);
+ memset (p3_4_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *p5_3_4 = CHOOSE_DECL_3 (5, 3, 4);
+
+ memset (p5_3_4, 0, 3);
+ memset (p5_3_4, 0, 4);
+ memset (p5_3_4, 0, 5);
+ memset (p5_3_4, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *p9_8_7 = CHOOSE_DECL_3 (9, 8, 7);
+
+ memset (p9_8_7, 0, 7);
+ memset (p9_8_7, 0, 8);
+ memset (p9_8_7, 0, 9);
+ memset (p9_8_7, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9 " }
+ }
+}
+
+
+/* Verify conditionally writing into one of two objects with the same
+ size. */
+
+void memset_decl_2_same_size (int i)
+{
+ {
+ char a4_1[4], a4_2[4];
+ char *p4 = cond1 ? a4_1 : a4_2;
+
+ memset (p4, 0, 1);
+ memset (p4, 0, 2);
+ memset (p4, 0, 3);
+ memset (p4, 0, 4);
+ memset (p4, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" }
+ }
+
+ {
+ char a4_1[4]; // { dg-message "destination object 'a4_1" "note" }
+ char a4_2[4]; // { dg-message "destination object 'a4_2" "note" }
+ char *p4 = cond1 ? a4_1 : a4_2;
+ char *p4_i = p4 + i;
+
+ memset (p4_i, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" }
+ }
+
+ {
+ if (i < 1)
+ i = 1;
+
+ char a4_1[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" }
+ char a4_2[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" }
+ char *p4 = cond1 ? a4_1 : a4_2;
+ char *p4_i = p4 + i;
+
+ memset (p4_i, 0, 3);
+ memset (p4_i, 0, 4); // { dg-warning "memset' writing 4 bytes into a region of size 3 " }
+ }
+}
+
+
+void memset_decl_2_off (void)
+{
+ int i1 = SR (1, INT_MAX);
+ int i2 = SR (2, INT_MAX);
+
+ {
+ char a5[5]; // { dg-warning "at offset [1, 5] into destination object 'a5'
+ char a7[7]; // { dg-warning "at offset [2, 7] into destination object 'a7'
+ char *p5_p1 = a5 + i1;
+ char *p7_p2 = a7 + i2;
+ char *p5_7 = cond1 ? p5_p1 : p7_p2;
+
+ memset (p5_7, 0, 1);
+ memset (p5_7, 0, 2);
+ memset (p5_7, 0, 3);
+ memset (p5_7, 0, 4);
+ memset (p5_7, 0, 5);
+ memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ int i3 = SR (3, INT_MAX);
+
+ {
+ char a5[5];
+ // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
+ // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
+ // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
+ char a9[9];
+ // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
+ // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
+ // { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 }
+ char *p5_p2 = a5 + i2; // 3 bytes left
+ char *p9_p3 = a9 + i3; // 6 bytes left
+ char *p =
+ cond1 ? p5_p2 : p9_p3; // [3 - 6] bytes left
+ char *q = p + i1; // [2 - 5] bytes left
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" }
+
+ --q; // [3 - 6] bytes left
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6);
+ memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
+
+ --q; // [4 - 7] bytes left
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6);
+ memset (q, 0, 7);
+ memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
+
+ int m1_x = SR (-1, INT_MAX);
+ int m2_x = SR (-2, INT_MAX);
+
+ q += cond2 ? m1_x : m2_x; // [5 - 9] bytes left
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6);
+ memset (q, 0, 7);
+ memset (q, 0, 8);
+ memset (q, 0, 9);
+ memset (q, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9" }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-59.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-59.c
new file mode 100644
index 0000000..c45a92d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-59.c
@@ -0,0 +1,267 @@
+/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
+ Exercise warnings for writing into one of two or more allocated objects.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+#include "range.h"
+
+#define INT_MAX __INT_MAX__
+
+extern void* malloc (size_t);
+extern void* memset (void*, int, size_t);
+#define memset(d, c, n) sink (memset (d, c, n))
+
+void sink (int, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+volatile int cond1, cond2, x;
+
+#define CHOOSE_MALLOC_2(n1, n2) \
+ (cond1 ? malloc (n1) : malloc (n2))
+#define CHOOSE_MALLOC_3(n1, n2, n3) \
+ (cond1 < 0 ? malloc (n1) : 0 < cond1 ? malloc (n2) : malloc (n3))
+
+
+void memset_malloc_2 (void)
+{
+ {
+ char *p0_1 = CHOOSE_MALLOC_2 (0, 1);
+
+ memset (p0_1, 0, 0);
+ /* Writing more than the smallest destination should trigger a "may
+ write" warning if the access is unconditionally reachable from
+ the block where the pointer to either object is assigned. */
+ memset (p0_1, 0, 1);
+ memset (p0_1, 0, 2); // { dg-warning "memset' writing 2 bytes into a region of size 1 " }
+ memset (p0_1, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 1 " }
+ }
+
+ {
+ char *p0_x = CHOOSE_MALLOC_2 (0, x);
+
+ memset (p0_x, 0, 0);
+ memset (p0_x, 0, 1);
+ memset (p0_x, 0, 2);
+ memset (p0_x, 0, 12345);
+ }
+
+ {
+ char *px_x = CHOOSE_MALLOC_2 (x, x);
+
+ memset (px_x, 0, 0);
+ memset (px_x, 0, 1);
+ memset (px_x, 0, 2);
+ memset (px_x, 0, 12345);
+ }
+
+ {
+ char *p3_5 = CHOOSE_MALLOC_2 (3, 5);
+
+ memset (p3_5, 0, 1);
+ memset (p3_5, 0, 3);
+ memset (p3_5, 0, 4);
+ memset (p3_5, 0, 5);
+ memset (p3_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *p5_3 = CHOOSE_MALLOC_2 (5, 3);
+
+ memset (p5_3, 0, 3);
+ memset (p5_3, 0, 4);
+ memset (p5_3, 0, 5);
+ memset (p5_3, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *px_3 = CHOOSE_MALLOC_2 (x, 3);
+
+ memset (px_3, 0, 1);
+ memset (px_3, 0, 3);
+ memset (px_3, 0, 4);
+ memset (px_3, 0, 1234);
+ }
+
+ {
+ char *p5_x = CHOOSE_MALLOC_2 (5, x);
+
+ memset (p5_x, 0, 1);
+ memset (p5_x, 0, 5);
+ memset (p5_x, 0, 6);
+ memset (p5_x, 0, 1234);
+ }
+
+}
+
+
+void memset_malloc_3 (void)
+{
+ {
+ char *p0_1_2 = CHOOSE_MALLOC_3 (0, 1, 2);
+ memset (p0_1_2, 0, 0);
+ memset (p0_1_2, 0, 1);
+ memset (p0_1_2, 0, 2);
+ memset (p0_1_2, 0, 3); // { dg-warning "memset' writing 3 bytes into a region of size 2 " }
+ memset (p0_1_2, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 2 " }
+ }
+
+ {
+ char *p0_2_x = CHOOSE_MALLOC_3 (0, 2, x);
+
+ memset (p0_2_x, 0, 0);
+ memset (p0_2_x, 0, 1);
+ memset (p0_2_x, 0, 3);
+ memset (p0_2_x, 0, 9);
+ }
+
+ {
+ char *p3_4_5 = CHOOSE_MALLOC_3 (3, 4, 5);
+
+ memset (p3_4_5, 0, 3);
+ memset (p3_4_5, 0, 4);
+ memset (p3_4_5, 0, 5);
+ memset (p3_4_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *p5_3_4 = CHOOSE_MALLOC_3 (5, 3, 4);
+
+ memset (p5_3_4, 0, 3);
+ memset (p5_3_4, 0, 4);
+ memset (p5_3_4, 0, 5);
+ memset (p5_3_4, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char *p9_8_7 = CHOOSE_MALLOC_3 (9, 8, 7);
+
+ memset (p9_8_7, 0, 7);
+ memset (p9_8_7, 0, 8);
+ memset (p9_8_7, 0, 9);
+ memset (p9_8_7, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9 " }
+ }
+}
+
+
+/* Verify conditionally writing into one of two objects with the same
+ size. */
+
+void memset_malloc_2_same_size (int i)
+{
+ {
+ char a4_1[4], a4_2[4];
+ char *p4 = cond1 ? a4_1 : a4_2;
+
+ memset (p4, 0, 1);
+ memset (p4, 0, 2);
+ memset (p4, 0, 3);
+ memset (p4, 0, 4);
+ memset (p4, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" }
+ }
+
+ {
+ char a4_1[4]; // { dg-message "destination object 'a4_1" "note" }
+ char a4_2[4]; // { dg-message "destination object 'a4_2" "note" }
+ char *p4 = cond1 ? a4_1 : a4_2;
+ char *p4_i = p4 + i;
+
+ memset (p4_i, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" }
+ }
+
+ {
+ if (i < 1)
+ i = 1;
+
+ char a4_1[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" }
+ char a4_2[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" }
+ char *p4 = cond1 ? a4_1 : a4_2;
+ char *p4_i = p4 + i;
+
+ memset (p4_i, 0, 3);
+ memset (p4_i, 0, 4); // { dg-warning "memset' writing 4 bytes into a region of size 3 " }
+ }
+}
+
+
+void memset_malloc_2_off (void)
+{
+ int i1 = SR (1, INT_MAX);
+ int i2 = SR (2, INT_MAX);
+
+ {
+ char a5[5]; // { dg-warning "at offset [1, 5] into destination object 'a5'
+ char a7[7]; // { dg-warning "at offset [2, 7] into destination object 'a7'
+ char *p5_p1 = a5 + i1;
+ char *p7_p2 = a7 + i2;
+ char *p5_7 = cond1 ? p5_p1 : p7_p2;
+
+ memset (p5_7, 0, 1);
+ memset (p5_7, 0, 2);
+ memset (p5_7, 0, 3);
+ memset (p5_7, 0, 4);
+ memset (p5_7, 0, 5);
+ memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
+ }
+
+ int i3 = SR (3, INT_MAX);
+
+ {
+ char a5[5];
+ // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
+ // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
+ // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
+ char a9[9];
+ // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
+ // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
+ // { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 }
+ char *p5_p2 = a5 + i2; // 3 bytes left
+ char *p9_p3 = a9 + i3; // 6 bytes left
+ char *p =
+ cond1 ? p5_p2 : p9_p3; // [3 - 6] bytes left
+ char *q = p + i1; // [2 - 5] bytes left
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" }
+
+ --q; // [3 - 6] bytes left
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6);
+ memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
+
+ --q; // [4 - 7] bytes left
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6);
+ memset (q, 0, 7);
+ memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
+
+ int m1_x = SR (-1, INT_MAX);
+ int m2_x = SR (-2, INT_MAX);
+
+ q += cond2 ? m1_x : m2_x; // [5 - 9] bytes left
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5);
+ memset (q, 0, 6);
+ memset (q, 0, 7);
+ memset (q, 0, 8);
+ memset (q, 0, 9);
+ memset (q, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9" }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c
new file mode 100644
index 0000000..8c9de20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c
@@ -0,0 +1,72 @@
+/* Test derived from Glibc's getifaddrs_internal. The code could be
+ rewritten to avoid the warning for the memcpy call but since unions
+ are designed to have their members treated as interchangeable there
+ isn't a whole lot to be gained from issuing one.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void* memcpy (void*, const void*, size_t);
+
+struct sockaddr
+{
+ short sa_family;
+ char sa_data[14];
+};
+
+struct in_addr
+{
+ int s_addr;
+};
+
+struct in6_addr
+{
+ union
+ {
+ char __u6_addr8[16];
+ short __u6_addr16[8];
+ int __u6_addr32[4];
+ } __in6_u;
+};
+
+struct sockaddr_in
+{
+ short sin_family;
+ short sin_port;
+ struct in_addr sin_addr;
+ unsigned char sin_zero[sizeof (struct sockaddr) -
+ (sizeof (short)) -
+ sizeof (short) -
+ sizeof (struct in_addr)];
+};
+
+struct sockaddr_in6
+{
+ short sin6_family;
+ short sin6_port;
+ int sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ int sin6_scope_id;
+};
+
+union
+{
+ struct sockaddr sa;
+ struct sockaddr_in s4;
+ struct sockaddr_in6 s6;
+} u1, u2;
+
+struct sockaddr *sa;
+
+void test_unconditional (void *p)
+{
+ sa = &u1.sa;
+ memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, p, 16);
+}
+
+void test_conditional (void *p, int i)
+{
+ sa = i ? &u1.sa : &u2.sa;
+ memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, p, 16);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c
new file mode 100644
index 0000000..7601679
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c
@@ -0,0 +1,88 @@
+/* { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* malloc (size_t);
+void* memcpy (void*, const void*, size_t);
+size_t strlen (const char *);
+
+// Test case reduced from gcc/attribs.c.
+
+char* sorted_attr_string (char *argv[])
+{
+ size_t n = 0;
+ unsigned int i;
+
+ for (i = 0; argv[i]; ++i)
+ n += strlen (argv[i]);
+
+ char *s = (char*)malloc (n);
+ n = 0;
+ for (i = 0; argv[i]; ++i)
+ {
+ const char *str = argv[i];
+ size_t len = strlen (str);
+ memcpy (s + n, str, len);
+ n += len + 1;
+ }
+
+ /* Replace "=,-" with "_". */
+ for (i = 0; i < strlen (s); i++)
+ if (s[i] == '=')
+ s[i] = '_'; // { dg-bogus "\\\[-Wstringop-overflow" }
+
+ return s;
+}
+
+
+void f (void*);
+
+void nowarn_cond_escape (int c, int *x)
+{
+ extern char a3[3], a5[5];
+
+ char *p;
+ if (c)
+ {
+ p = a3;
+ *x = 2;
+ }
+ else
+ {
+ p = a5;
+ *x = 4;
+ }
+
+ f (p); // may modify *x
+
+ if (*x == 2)
+ p[2] = 0;
+ else if (*x == 4)
+ p[4] = 0; // { dg-bogus "\\\[-Wstringop-overflow" }
+}
+
+void warn_cond_escape (int c, int *x)
+{
+ extern char a3_2[3];
+ extern char a5_2[5]; // { dg-message "at offset 5 into destination object 'a5_2'" }
+
+ char *p;
+ if (c)
+ {
+ p = a3_2;
+ *x = 2;
+ }
+ else
+ {
+ p = a5_2;
+ *x = 5;
+ }
+
+ f (p); // may modify *x
+
+ if (*x == 2)
+ p[2] = 0;
+ else if (*x == 5)
+ p[5] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
new file mode 100644
index 0000000..318d9bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
@@ -0,0 +1,363 @@
+/* Test for MIN and MAX expressions involving pointers.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+#include "range.h"
+
+#define INT_MAX __INT_MAX__
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define MAX(x, y) ((x) < (y) ? (y) : (x))
+
+typedef __SIZE_TYPE__ size_t;
+
+void* memset (void*, int, size_t);
+#define memset(...) sink (memset (__VA_ARGS__))
+
+void sink (void*, ...);
+
+volatile int cond, vi;
+char* volatile ptr;
+
+void test_min (void)
+{
+ const int i1 = SR (1, INT_MAX);
+ const int i2 = SR (2, INT_MAX);
+
+ {
+ /* Exercise both pointers pointing to a different unknown object plus
+ positive constant offset. Since PTR is volatile P1 and P2 cannot
+ normally be considered to point to the same object. It can only
+ be inferred from the MIN expression. */
+ char *p1 = ptr + 1;
+ char *p2 = ptr + 2;
+
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, INT_MAX);
+ // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
+ memset (q, 0, DIFF_MAX - 2);
+ memset (q, 0, DIFF_MAX);
+ // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
+ // { dg-warning "writing 9223372036854775807 bytes into a region of size 9223372036854775806" "lp64" { target lp64 } .-2 }
+ }
+
+ {
+ /* Exercise both pointers pointing to a different unknown object plus
+ variable offset. */
+ char *p1 = ptr + vi;
+ char *p2 = ptr + vi;
+
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, INT_MAX);
+ }
+
+ {
+ /* Exercise both pointers pointing to the same object plus constant
+ offset. */
+ char a2[2]; // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" }
+ char *p1 = a2 + 1;
+ char *p2 = a2 + 2;
+
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2); // { dg-warning "writing 2 bytes into a region of size 1 " }
+ }
+
+ {
+ /* Exercise both pointers pointing to the same object plus offset
+ in a known range. */
+ char a3[3]; // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" }
+ char *pi = a3 + i1;
+ char *pj = a3 + i2;
+
+ char *q = MIN (pi, pj);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
+ }
+
+ {
+ /* Exercise both pointers pointing to the same object plus variable
+ offset. Verify that no offset is mentioned in the note (since
+ its unknown, printing its full range is unnecessary). */
+ char a4[4]; // { dg-message ": destination object 'a4'" "note" }
+ char *pi = a4 + vi;
+ char *pj = a4 + vi;
+
+ char *q = MIN (pi, pj);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object with one pointing
+ to an unknown object. */
+ char a5[5]; // { dg-message ": destination object 'a5'" "note" }
+ char *p = ptr;
+ char *q = MIN (p, a5);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object plus constant offset
+ with one pointing to an unknown object. */
+ char a6[6]; // { dg-message ": destination object 'a6'" "note" }
+ char *p1 = ptr;
+ char *p2 = a6 + 1;
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 6);
+ memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object with one pointing
+ to an unknown object plus constant offset. */
+ char a7[7]; // { dg-message ": destination object 'a7'" "note" }
+ char *p1 = a7;
+ char *p2 = ptr + 1;
+ /* Since p1 points to a7[0] it must be less than any pointer to a7
+ plus positive offset, and so Q == P1. */
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 7);
+ memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 7 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object plus constant offset
+ with one pointing to an unknown object plus a different constant
+ offset. */
+ char a8[8]; // { dg-message "at offset 1 into destination object 'a8'" "note" }
+ char *p1 = a8 + 1;
+ char *p2 = ptr + 2;
+ /* Since P1 points to A8[1] it must be less than or equal to any
+ pointer to A8 plus positive offset. Either way, Q must point
+ to A8[1]. */
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 7);
+ memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 7 " }
+ }
+
+ {
+ /* Same as above but with larger offsets. */
+ char a9[9]; // { dg-message "at offset 3 into destination object 'a9'" "note" }
+ char *p1 = a9 + 3;
+ char *p2 = ptr + 4;
+ /* Since P1 points to A9[3] it must be less than or equal to any
+ pointer anywhere into A9 plus 4, so Q must point to A9[3]. */
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 6);
+ memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
+ }
+
+ {
+ /* Same as above but with the offsets reversed. */
+ char a10[10]; // { dg-message "at offset 5 into destination object 'a10'" "note" }
+ char *p1 = a10 + 10;
+ char *p2 = ptr + 5;
+ /* Since P1 points just past the end of A10 it could be either less
+ or equal to another pointer anywhere into A10 plus 3 because
+ the other pointer itself could start at a non-zero offset that's
+ not reflected in the determined offset). */
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ char a3[3]; // { dg-message ": destination object 'a3'" "note" }
+ char *p1 = ptr;
+ char *p2 = a3 + i1;
+ char *q = MIN (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4); // { dg-warning "writing 4 bytes into a region of size 3 " }
+ }
+}
+
+
+void test_max (void)
+{
+ const int i1 = SR (1, INT_MAX);
+ const int i2 = SR (2, INT_MAX);
+
+ {
+ /* Exercise both pointers pointing to the same object plus constant
+ offset. */
+ char a2[2]; // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" }
+ char *pi = a2 + 1;
+ char *pj = a2 + 2;
+
+ char *q = MAX (pi, pj);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2); // { dg-warning "writing 2 bytes into a region of size 1 " }
+ }
+
+ {
+ /* Exercise both pointers pointing to the same object plus offset
+ in a known range. */
+ char a3[3]; // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" }
+ char *pi = a3 + i1;
+ char *pj = a3 + i2;
+
+ char *q = MAX (pi, pj);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
+ }
+
+ {
+ /* Exercise both pointers pointing to the same object plus variable
+ offset. Verify that no offset is mentioned in the note (since
+ its unknown, printing its full range is unnecessary). */
+ char a4[4]; // { dg-message ": destination object 'a4'" "note" }
+ char *pi = a4 + vi;
+ char *pj = a4 + vi;
+
+ char *q = MAX (pi, pj);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 3);
+ memset (q, 0, 4);
+ memset (q, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object with one pointing
+ to an unknown object. */
+ char a5[5]; // { dg-message ": destination object 'a5'" "note" }
+ char *p = ptr;
+ char *q = MAX (p, a5);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object plus constant offset
+ with one pointing to an unknown object. */
+ char a6[6]; // { dg-message "at offset 1 into destination object 'a6'" "note" }
+ char *p1 = ptr;
+ char *p2 = a6 + 1;
+ char *q = MAX (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
+ memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 5 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object with one pointing
+ to an unknown object plus constant offset. */
+ char a7[7]; // { dg-message "at offset 1 into destination object 'a7'" "note" }
+ char *p1 = a7;
+ char *p2 = ptr + 1;
+ /* Since p1 points to a7[0] it must be less than any pointer to a7
+ plus positive offset, and so Q == P2. */
+ char *q = MAX (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 6);
+ memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
+ memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 6 " }
+ }
+
+ {
+ /* Exercise a pointer pointing to a known object plus constant offset
+ with one pointing to an unknown object plus a different constant
+ offset. */
+ char a8[8]; // { dg-message "at offset 2 into destination object 'a8'" "note" }
+ char *p1 = a8 + 1;
+ char *p2 = ptr + 2;
+ /* Since P1 points to A8[1] it must be less than or equal to any
+ pointer to A8 plus positive offset. Either way, Q must point
+ to A8[2]. */
+ char *q = MAX (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 6);
+ memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
+ memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 6 " }
+ }
+
+ {
+ /* Same as above but with larger offsets. */
+ char a9[9]; // { dg-message "at offset 4 into destination object 'a9'" "note" }
+ char *p1 = a9 + 3;
+ char *p2 = ptr + 4;
+ /* Since P1 points to A9[3] it must be less than or equal to any
+ pointer anywhere into A9 plus 4, so Q must point to A9[4]. */
+ char *q = MAX (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 5);
+ memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
+ }
+
+ {
+ /* Same as above but with the offsets reversed. */
+ char a10[10]; // { dg-message "at offset 10 into destination object 'a10'" "note" }
+ char *p1 = a10 + 10;
+ char *p2 = ptr + 5;
+ /* Since P1 points just past the end of A10 it could be either less
+ or equal to another pointer anywhere into A10 plus 3 because
+ the other pointer itself could start at a non-zero offset that's
+ not reflected in the determaxed offset). */
+ char *q = MAX (p1, p2);
+
+ memset (q, 0, 1); // { dg-warning "writing 1 byte into a region of size 0 " }
+ }
+
+ {
+ char a11[11]; // { dg-message "at offset \\\[1, 11] into destination object 'a11'" "note" }
+ char *p1 = ptr;
+ char *p2 = a11 + i1;
+ char *q = MAX (p1, p2);
+
+ memset (q, 0, 1);
+ memset (q, 0, 2);
+ memset (q, 0, 10);
+ memset (q, 0, 11); // { dg-warning "writing 11 bytes into a region of size 10 " }
+ }
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-63.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-63.c
new file mode 100644
index 0000000..c98721d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-63.c
@@ -0,0 +1,33 @@
+/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
+ Test case derived from gcc/opts-common.c.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+char* f (const void*, ...);
+
+const char *
+candidates_list_and_hint (const char *arg, char **str, const char *a[])
+{
+ size_t len = 0;
+ int i;
+
+ for (i = 0; a[i]; ++i)
+ len += __builtin_strlen (a[i]) + 1;
+
+ char *p = (char*)__builtin_malloc (len);
+ *str = p;
+
+ for (i = 0; a[i]; ++i)
+ {
+ len = __builtin_strlen (a[i]);
+ __builtin_memcpy (p, a[i], len);
+ p[len] = ' ';
+ p += len + 1;
+ }
+
+ p[-1] = '\0'; // { dg-bogus "\\\[-Wstringop-overflow" }
+
+ return f (arg, &a);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c
new file mode 100644
index 0000000..88b9d29
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c
@@ -0,0 +1,74 @@
+/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* malloc (size_t);
+void* memset (void*, int, size_t);
+
+extern char a3[3], a5[5], a9[9];
+
+extern int cnd[];
+
+void* f2 (void)
+{
+ char *p0 = cnd[0] ? a3 : 0;
+ char *p1 = cnd[1] ? a5 : p0;
+
+ return memset (p1, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+}
+
+void* f3 (void)
+{
+ char *p0 = cnd[0] ? a3 : 0;
+ char *p1 = cnd[1] ? a5 : 0;
+ char *p2 = cnd[2] ? p0 : p1;
+
+ return memset (p2, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+}
+
+void* f3_2 (void)
+{
+ char *p0 = cnd[0] ? a3 : 0;
+ char *p1 = cnd[1] ? a5 : 0;
+ char *p2 = cnd[2] ? p1 : p0;
+
+ return memset (p2, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+}
+
+void* f3_3 (void)
+{
+ char *p0 = cnd[0] ? a5 : 0;
+ char *p1 = cnd[1] ? p0 : a5;
+ char *p2 = cnd[2] ? p1 : p0;
+
+ return memset (p2, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+}
+
+void* f4 (void)
+{
+ char *p0 = cnd[0] ? a3 : 0;
+ char *p1 = cnd[1] ? a5 : 0;
+ char *p2 = cnd[2] ? p0 : 0;
+ char *p3 = cnd[3] ? p1 : p2;
+
+ return memset (p3, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+}
+
+void* f9 (void)
+{
+ char *p0 = cnd[0] ? a5 : 0;
+ char *p1 = cnd[1] ? a5 + 1 : 0;
+ char *p2 = cnd[2] ? a5 + 2 : 0;
+ char *p3 = cnd[3] ? a5 + 3 : 0;
+ char *p4 = cnd[4] ? a5 + 4 : 0;
+
+ char *p5 = cnd[5] ? p0 : p1;
+ char *p6 = cnd[6] ? p5 : p2;
+ char *p7 = cnd[7] ? p6 : p3;
+ char *p8 = cnd[8] ? p7 : p4;
+ char *p9 = cnd[9] ? p8 : p5;
+
+ return memset (p9, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-7.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-7.c
new file mode 100644
index 0000000..cb2addf3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-7.c
@@ -0,0 +1,124 @@
+/* Test to verify that --param ssa_name_def_chain_limit can be used to
+ limit the maximum number of SSA_NAME assignments the warning follows.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds --param ssa-name-def-chain-limit=5" } */
+
+#define NOIPA __attribute__ ((noipa))
+
+void* memset (void*, int, __SIZE_TYPE__);
+
+char a9[9];
+
+void sink (const char*, ...);
+
+NOIPA void g2 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+
+ sink (p0, p1, p2);
+
+ memset (p2, 0, 8); // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+NOIPA void g3 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+ char *p3 = p2 + i;
+
+ sink (p0, p1, p2, p3);
+
+ memset (p3, 0, 7); // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+NOIPA void g4 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+ char *p3 = p2 + i;
+ char *p4 = p3 + i;
+
+ sink (p0, p1, p2, p3, p4);
+
+ memset (p4, 0, 6); // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+NOIPA void g5 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+ char *p3 = p2 + i;
+ char *p4 = p3 + i;
+ char *p5 = p4 + i;
+
+ sink (p0, p1, p2, p3, p4, p5);
+
+ memset (p5, 0, 5); // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+NOIPA void g6 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+ char *p3 = p2 + i;
+ char *p4 = p3 + i;
+ char *p5 = p4 + i;
+ char *p6 = p5 + i;
+
+ sink (p0, p1, p2, p3, p4, p5, p6);
+
+ memset (p6, 0, 4);
+}
+
+NOIPA void g7 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+ char *p3 = p2 + i;
+ char *p4 = p3 + i;
+ char *p5 = p4 + i;
+ char *p6 = p5 + i;
+ char *p7 = p6 + i;
+
+ sink (p0, p1, p2, p3, p4, p5, p6, p7);
+
+ memset (p7, 0, 4);
+}
+
+NOIPA void g8 (int i)
+{
+ if (i < 1) i = 1;
+
+ char *p0 = a9;
+ char *p1 = p0 + i;
+ char *p2 = p1 + i;
+ char *p3 = p2 + i;
+ char *p4 = p3 + i;
+ char *p5 = p4 + i;
+ char *p6 = p5 + i;
+ char *p7 = p6 + i;
+ char *p8 = p7 + i;
+
+ sink (p0, p1, p2, p3, p4, p5, p6, p7, p8);
+
+ memset (p8, 0, 2);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c b/gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c
new file mode 100644
index 0000000..08e5272
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/97424. */
+
+#include <stdint.h>
+
+static inline uint32_t
+_dl_hwcaps_subdirs_build_bitmask (int subdirs, int active)
+{
+ /* Leading subdirectories that are not active. */
+ int inactive = subdirs - active;
+ if (inactive == 32)
+ return 0;
+
+ uint32_t mask;
+ if (subdirs != 32)
+ mask = (1 << subdirs) - 1; /* { dg-message "shift by count \\('33'\\) >= precision of type \\('\[0-9\]+'\\)" } */
+ else
+ mask = -1;
+ return mask ^ ((1U << inactive) - 1); /* { dg-message "shift by negative count \\('-1'\\)" } */
+}
+
+void f1 (int);
+
+void
+f2 (void)
+{
+ f1 (_dl_hwcaps_subdirs_build_bitmask (1, 2));
+ f1 (_dl_hwcaps_subdirs_build_bitmask (33, 31));
+}
+
+static int __attribute__((noinline)) op3 (int op, int c) { return op << c; } /* { dg-message "shift by negative count \\('-1'\\)" } */
+int test_3 (void) { return op3 (1, -1); }
+
+static int __attribute__((noinline)) op4 (int op, int c) { return op << c; }
+int test_4 (void) { return op4 (1, 0); }
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
index c3e1330..26d8288 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
@@ -30,14 +30,14 @@ void test_2a (void *ptr)
int *test_3 (void)
{
int *ptr = (int *)malloc (sizeof (int));
- *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */
+ *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
return ptr;
}
int *test_3a (void)
{
int *ptr = (int *)__builtin_malloc (sizeof (int));
- *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */
+ *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
return ptr;
}
@@ -47,7 +47,7 @@ int *test_4 (void)
if (ptr)
*ptr = 42;
else
- *ptr = 43; /* { dg-warning "dereference of NULL 'ptr'" } */
+ *ptr = 43; /* { dg-warning "dereference of NULL 'ptr' \\\[CWE-476\\\]" } */
return ptr;
}
@@ -260,14 +260,14 @@ void test_22 (void)
int *test_23 (int n)
{
int *ptr = (int *)calloc (n, sizeof (int));
- ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */
+ ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
return ptr;
}
int *test_23a (int n)
{
int *ptr = (int *)__builtin_calloc (n, sizeof (int));
- ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */
+ ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
return ptr;
}
@@ -302,7 +302,7 @@ struct coord {
struct coord *test_27 (void)
{
struct coord *p = (struct coord *) malloc (sizeof (struct coord)); /* { dg-message "this call could return NULL" } */
- p->x = 0.f; /* { dg-warning "dereference of possibly-NULL 'p'" } */
+ p->x = 0.f; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */
/* Only the first such usage should be reported: */
p->y = 0.f;
@@ -313,7 +313,7 @@ struct coord *test_27 (void)
struct coord *test_28 (void)
{
struct coord *p = NULL;
- p->x = 0.f; /* { dg-warning "dereference of NULL 'p'" } */
+ p->x = 0.f; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
/* Only the first such usage should be reported: */
p->y = 0.f;
@@ -416,7 +416,7 @@ void test_36 (void)
void *test_37a (void)
{
void *ptr = malloc(4096); /* { dg-message "this call could return NULL" } */
- __builtin_memset(ptr, 0, 4096); /* { dg-warning "use of possibly-NULL 'ptr' where non-null expected" } */
+ __builtin_memset(ptr, 0, 4096); /* { dg-warning "use of possibly-NULL 'ptr' where non-null expected \\\[CWE-690\\\]" } */
return ptr;
}
@@ -427,7 +427,7 @@ int test_37b (void)
if (p) {
__builtin_memset(p, 0, 4096); /* Not a bug: checked */
} else {
- __builtin_memset(q, 0, 4096); /* { dg-warning "use of possibly-NULL 'q' where non-null expected" } */
+ __builtin_memset(q, 0, 4096); /* { dg-warning "use of possibly-NULL 'q' where non-null expected \\\[CWE-690\\\]" } */
}
free(p);
free(q);
@@ -452,7 +452,7 @@ int *
test_39 (int i)
{
int *p = (int*)malloc(sizeof(int*)); /* { dg-message "this call could return NULL" } */
- *p = i; /* { dg-warning "dereference of possibly-NULL 'p'" } */
+ *p = i; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */
return p;
}
@@ -460,7 +460,7 @@ int *
test_40 (int i)
{
int *p = (int*)malloc(sizeof(int*));
- i = *p; /* { dg-warning "dereference of possibly-NULL 'p'" } */
+ i = *p; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */
/* TODO: (it's also uninitialized) */
return p;
}
@@ -476,8 +476,8 @@ test_41 (int flag)
buffer = NULL;
}
- buffer[0] = 'a'; /* { dg-warning "dereference of possibly-NULL 'buffer'" "possibly-NULL" } */
- /* { dg-warning "dereference of NULL 'buffer'" "NULL" { target *-*-* } .-1 } */
+ buffer[0] = 'a'; /* { dg-warning "dereference of possibly-NULL 'buffer' \\\[CWE-690\\\]" "possibly-NULL" } */
+ /* { dg-warning "dereference of NULL 'buffer' \\\[CWE-476\\\]" "NULL" { target *-*-* } .-1 } */
return buffer;
}
@@ -509,6 +509,14 @@ void test_42c (void)
free (q - 64); /* this is probably OK. */
} /* { dg-bogus "leak of 'p'" } */
+void *
+test_42d (void)
+{
+ void *p = malloc (1024);
+ void *q = p + 64;
+ return q;
+} /* { dg-bogus "leak of 'p'" } */
+
#if 0
void test_31 (void *p)
{
@@ -586,7 +594,7 @@ int test_47 (void)
void test_48 (void)
{
int *p = NULL; /* { dg-message "'p' is NULL" } */
- *p = 1; /* { dg-warning "dereference of NULL 'p'" } */
+ *p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
}
/* As test_48, but where the assignment of NULL is not at the start of a BB. */
@@ -598,6 +606,8 @@ int test_49 (int i)
x = i * 2;
p = NULL; /* { dg-message "'p' is NULL" } */
- *p = 1; /* { dg-warning "dereference of NULL 'p'" } */
+ *p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
return x;
}
+
+/* { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97568.c b/gcc/testsuite/gcc.dg/analyzer/pr97568.c
new file mode 100644
index 0000000..22d574b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr97568.c
@@ -0,0 +1,29 @@
+#include "analyzer-decls.h"
+
+#define NULL ((void *)0)
+
+extern int *const p1;
+
+int *const p2;
+
+int v3;
+extern int *const p3 = &v3; /* { dg-warning "'p3' initialized and declared 'extern'" } */
+
+int v4;
+int *const p4 = &v4;
+
+int main (void)
+{
+ __analyzer_describe (0, p1); /* { dg-message "INIT_VAL\\(p1\\)" } */
+ __analyzer_eval (p1 == NULL); /* { dg-message "UNKNOWN" } */
+
+ __analyzer_eval (p2 == NULL); /* { dg-message "TRUE" } */
+
+ __analyzer_describe (0, p3); /* { dg-message "&v3" } */
+ __analyzer_eval (p3 == NULL); /* { dg-message "FALSE" } */
+
+ __analyzer_describe (0, p4); /* { dg-message "&v4" } */
+ __analyzer_eval (p4 == NULL); /* { dg-message "FALSE" } */
+
+ return p1[0];
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97608.c b/gcc/testsuite/gcc.dg/analyzer/pr97608.c
new file mode 100644
index 0000000..a2bc130
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr97608.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+void *f (void)
+{
+ void *p = malloc (8);
+ if (p == NULL)
+ abort ();
+ return (void *) ((char *) p + 0);
+}
+
+void *g (void)
+{
+ void *p = malloc (8);
+ if (p == NULL)
+ abort ();
+ return (void *) ((char *) p + 1);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97668.c b/gcc/testsuite/gcc.dg/analyzer/pr97668.c
new file mode 100644
index 0000000..6ec8164
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr97668.c
@@ -0,0 +1,27 @@
+/* { dg-additional-options "-O1" } */
+
+void
+wb (_Complex double jh)
+{
+ _Complex double af = 0.0;
+
+ do
+ {
+ af += jh;
+ }
+ while (af != 0.0);
+}
+
+_Complex double
+o6 (void)
+{
+ _Complex double ba = 0.0;
+
+ for (;;)
+ {
+ wb (ba);
+ ba = 1.0;
+ }
+
+ return ba;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c
index bf5b9bf..4787fa3 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c
@@ -51,18 +51,25 @@ void outer (void)
| | |
| | (4) 'setjmp' called here
|
+ 'inner': event 5
+ |
+ | NN | }
+ | | ^
+ | | |
+ | | (5) stack frame is popped here, invalidating saved environment
+ |
<------+
|
- 'outer': events 5-6
+ 'outer': events 6-7
|
| NN | inner ();
| | ^~~~~~~~
| | |
- | | (5) returning to 'outer' from 'inner'
+ | | (6) returning to 'outer' from 'inner'
| NN |
| NN | longjmp (env, 42);
| | ~~~~~~~~~~~~~~~~~
| | |
- | | (6) here
+ | | (7) 'longjmp' called after enclosing function of 'setjmp' returned at (5)
|
{ dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/array-quals-1.c b/gcc/testsuite/gcc.dg/array-quals-1.c
index 3981c91..31aa1d3 100644
--- a/gcc/testsuite/gcc.dg/array-quals-1.c
+++ b/gcc/testsuite/gcc.dg/array-quals-1.c
@@ -6,26 +6,46 @@
/* { dg-options "-Wno-discarded-array-qualifiers" } */
/* The MMIX port always switches to the .data section at the end of a file. */
/* { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail powerpc*-*-aix* mmix-*-* x86_64-*-mingw* } } } */
+/* { dg-final { scan-assembler-symbol-section {^_?a$} {^\.(const|rodata)|\[RO\]} } } */
static const int a[2] = { 1, 2 };
+/* { dg-final { scan-assembler-symbol-section {^_?a1$} {^\.(const|rodata)|\[RO\]} } } */
const int a1[2] = { 1, 2 };
typedef const int ci;
+/* { dg-final { scan-assembler-symbol-section {^_?b$} {^\.(const|rodata)|\[RO\]} } } */
static ci b[2] = { 3, 4 };
+/* { dg-final { scan-assembler-symbol-section {^_?b1$} {^\.(const|rodata)|\[RO\]} } } */
ci b1[2] = { 3, 4 };
typedef int ia[2];
+/* { dg-final { scan-assembler-symbol-section {^_?c$} {^\.(const|rodata)|\[RO\]} } } */
static const ia c = { 5, 6 };
+/* { dg-final { scan-assembler-symbol-section {^_?c1$} {^\.(const|rodata)|\[RO\]} } } */
const ia c1 = { 5, 6 };
typedef const int cia[2];
+/* { dg-final { scan-assembler-symbol-section {^_?d$} {^\.(const|rodata)|\[RO\]} } } */
static cia d = { 7, 8 };
+/* { dg-final { scan-assembler-symbol-section {^_?d1$} {^\.(const|rodata)|\[RO\]} } } */
cia d1 = { 7, 8 };
+/* { dg-final { scan-assembler-symbol-section {^_?e$} {^\.(const|rodata)|\[RO\]} } } */
static cia e[2] = { { 1, 2 }, { 3, 4 } };
+/* { dg-final { scan-assembler-symbol-section {^_?e1$} {^\.(const|rodata)|\[RO\]} } } */
cia e1[2] = { { 1, 2 }, { 3, 4 } };
+/* { dg-final { scan-assembler-symbol-section {^_?p$} {^\.(const|rodata)|\[RW\]} } } */
void *const p = &a;
+/* { dg-final { scan-assembler-symbol-section {^_?q$} {^\.(const|rodata)|\[RW\]} } } */
void *const q = &b;
+/* { dg-final { scan-assembler-symbol-section {^_?r$} {^\.(const|rodata)|\[RW\]} } } */
void *const r = &c;
+/* { dg-final { scan-assembler-symbol-section {^_?s$} {^\.(const|rodata)|\[RW\]} } } */
void *const s = &d;
+/* { dg-final { scan-assembler-symbol-section {^_?t$} {^\.(const|rodata)|\[RW\]} } } */
void *const t = &e;
+/* { dg-final { scan-assembler-symbol-section {^_?p1$} {^\.(const|rodata)|\[RW\]} } } */
void *const p1 = &a1;
+/* { dg-final { scan-assembler-symbol-section {^_?q1$} {^\.(const|rodata)|\[RW\]} } } */
void *const q1 = &b1;
+/* { dg-final { scan-assembler-symbol-section {^_?r1$} {^\.(const|rodata)|\[RW\]} } } */
void *const r1 = &c1;
+/* { dg-final { scan-assembler-symbol-section {^_?s1$} {^\.(const|rodata)|\[RW\]} } } */
void *const s1 = &d1;
+/* { dg-final { scan-assembler-symbol-section {^_?t1$} {^\.(const|rodata)|\[RW\]} } } */
void *const t1 = &e1;
diff --git a/gcc/testsuite/gcc.dg/attr-access-3.c b/gcc/testsuite/gcc.dg/attr-access-3.c
new file mode 100644
index 0000000..45dd1aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-access-3.c
@@ -0,0 +1,21 @@
+/* PR middle-end/97879 - ICE on invalid mode in attribute access
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((access (__VA_ARGS__)))
+
+A (" ", 1) void f1 (int *); // { dg-error "attribute 'access' mode '\" \"' is not an identifier; expected one of 'read_only', 'read_write', 'write_only', or 'none'" }
+ void f1 (int *);
+
+
+A ("none", 1) void f2 (char *); // { dg-error "not an identifier" }
+ void f2 (char *);
+
+A (1) void f3 (); // { dg-error "not an identifier" }
+
+A (1, 2) void f4 (); // { dg-error "not an identifier" }
+A (2., 3.) void f5 (); // { dg-error "not an identifier" }
+
+// Verify that copying a valid access attribute doesn't cause errors.
+A (read_only, 1, 2) void f6 (void*, int);
+__attribute__ ((copy (f6))) void f7 (void*, int);
diff --git a/gcc/testsuite/gcc.dg/attr-access-4.c b/gcc/testsuite/gcc.dg/attr-access-4.c
new file mode 100644
index 0000000..7a2870a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-access-4.c
@@ -0,0 +1,8 @@
+/* PR middle-end/97861 - ICE on an invalid redeclaration of a function
+ with attribute access
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+__attribute__ ((access (read_only, 2)))
+void f (int, int*);
+void f (int a) { } // { dg-error "conflicting types for 'f'" }
diff --git a/gcc/testsuite/gcc.dg/attr-access-5.c b/gcc/testsuite/gcc.dg/attr-access-5.c
new file mode 100644
index 0000000..e78b360
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-access-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile }
+ { dg-options "-fdump-tree-gimple" } */
+
+__attribute__ ((aligned (32)))
+__attribute__ ((access (write_only, 2, 1)))
+void f (int n, void *p)
+{
+ __builtin_memset (p, 0, n);
+}
+
+/* Verify the DECL_ATTRIBUTE "aligned" is mentioned:
+ { dg-final { scan-tree-dump "__attribute__\\(\\(aligned" "gimple" } }
+ and the TYPE_ATTRIBUTE "access" is also mentioned:
+ { dg-final { scan-tree-dump "__attribute__\\(\\(access" "gimple" } }
+ and the function signature including its return type is mentioned:
+ { dg-final { scan-tree-dump "void f *\\(int n, void *\\* *p\\)" "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/attr-malloc.c b/gcc/testsuite/gcc.dg/attr-malloc.c
new file mode 100644
index 0000000..14f1980
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-malloc.c
@@ -0,0 +1,75 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments is accepted where
+ intended and rejected where it's invalid.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+A (0) void* alloc_zero (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+A ("") void* alloc_string (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+int var;
+A (var) void* alloc_var (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+typedef struct Type { int i; } Type;
+A (Type) void* alloc_type (int); // { dg-error "expected expression|identifier" }
+
+A (unknown) void* alloc_unknown (int); // { dg-error "'unknown' undeclared" }
+
+void fv_ (); // { dg-message "declared here" }
+A (fv_) void* alloc_fv_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument" }
+
+void fvi (int); // { dg-message "declared here" }
+A (fvi) void* alloc_fvi (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvv (void); // { dg-message "declared here" }
+A (fvv) void* alloc_fvv (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'void'" }
+
+void fvi_ (int, ...); // { dg-message "declared here" }
+A (fvi_) void* alloc_fvi_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvi_vp (Type, void*); // { dg-message "declared here" }
+A (fvi_vp) void* alloc_fvi_vp (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'Type'" }
+
+
+void fpv (void*);
+A (fpv) void* alloc_fpv (int);
+
+void fpv_i (void*, int);
+A (fpv_i) void* alloc_fpv_i (int);
+
+void fpv_pv (void*, void*);
+A (fpv_i) void* alloc_fpv_pv (int);
+
+
+void gpc (char*);
+void hpi (int*);
+A (fpv) A (gpc) A (hpi) Type* alloc_fpv_gpv (int);
+
+
+/* Verify that the attribute can be applied to <stdio.h> functions. */
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+int fclose (FILE*);
+FILE* fdopen (int);
+FILE* fopen (const char*, const char*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+FILE* popen (const char*, const char*);
+FILE* tmpfile (void);
+
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* freopen (const char*, const char*, FILE*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* tmpfile (void);
diff --git a/gcc/testsuite/gcc.dg/binary-constants-2.c b/gcc/testsuite/gcc.dg/binary-constants-2.c
index 6c3928a..5339d57 100644
--- a/gcc/testsuite/gcc.dg/binary-constants-2.c
+++ b/gcc/testsuite/gcc.dg/binary-constants-2.c
@@ -9,8 +9,8 @@
int
foo (void)
{
-#if FOO /* { dg-warning "binary constants are a GCC extension" } */
+#if FOO /* { dg-warning "binary constants are a C2X feature or GCC extension" } */
return 23;
#endif
- return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */
+ return 0b1101; /* { dg-warning "binary constants are a C2X feature or GCC extension" } */
}
diff --git a/gcc/testsuite/gcc.dg/binary-constants-3.c b/gcc/testsuite/gcc.dg/binary-constants-3.c
index 410fc4c..5b49cb4 100644
--- a/gcc/testsuite/gcc.dg/binary-constants-3.c
+++ b/gcc/testsuite/gcc.dg/binary-constants-3.c
@@ -9,8 +9,8 @@
int
foo (void)
{
-#if FOO /* { dg-error "binary constants are a GCC extension" } */
+#if FOO /* { dg-error "binary constants are a C2X feature or GCC extension" } */
return 23;
#endif
- return 0b1101; /* { dg-error "binary constants are a GCC extension" } */
+ return 0b1101; /* { dg-error "binary constants are a C2X feature or GCC extension" } */
}
diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c
new file mode 100644
index 0000000..ab7d82a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c
@@ -0,0 +1,43 @@
+/* PR c/90628 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+_Atomic int a = 1, b = 2, c = 3;
+_Atomic long d = 4, e = 5, f = 6;
+_Atomic long long g = 7, h = 8, i = 9;
+
+void
+f1 ()
+{
+ __builtin_add_overflow (a, b, &c); /* { dg-error "argument 3 in call to function '__builtin_add_overflow' has pointer to '_Atomic' type" } */
+}
+
+void
+f2 ()
+{
+ __builtin_sub_overflow (d, e, &f); /* { dg-error "argument 3 in call to function '__builtin_sub_overflow' has pointer to '_Atomic' type" } */
+}
+
+void
+f3 ()
+{
+ __builtin_mul_overflow (g, h, &i); /* { dg-error "argument 3 in call to function '__builtin_mul_overflow' has pointer to '_Atomic' type" } */
+}
+
+void
+f4 ()
+{
+ __builtin_sadd_overflow (a, b, &c); /* { dg-warning "passing argument 3 of '__builtin_sadd_overflow' from incompatible pointer type" } */
+}
+
+void
+f5 ()
+{
+ __builtin_ssubl_overflow (d, e, &f); /* { dg-warning "passing argument 3 of '__builtin_ssubl_overflow' from incompatible pointer type" } */
+}
+
+void
+f6 ()
+{
+ __builtin_smulll_overflow (g, h, &i); /* { dg-warning "passing argument 3 of '__builtin_smulll_overflow' from incompatible pointer type" } */
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c
new file mode 100644
index 0000000..b43fd18
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c
@@ -0,0 +1,87 @@
+/* PR rtl-optimization/95862 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+f1 (int a, int b)
+{
+ unsigned long long c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+int
+f2 (int a, unsigned b)
+{
+ unsigned long long c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+int
+f3 (unsigned a, unsigned b)
+{
+ long long c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+int
+f4 (int a, unsigned b)
+{
+ long long c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+short
+f5 (short a, short b)
+{
+ unsigned c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+short
+f6 (short a, unsigned short b)
+{
+ unsigned c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+short
+f7 (unsigned short a, unsigned short b)
+{
+ int c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+short
+f8 (short a, unsigned short b)
+{
+ int c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+signed char
+f9 (signed char a, signed char b)
+{
+ unsigned short c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+signed char
+f10 (signed char a, unsigned char b)
+{
+ unsigned short c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+signed char
+f11 (unsigned char a, unsigned char b)
+{
+ short c;
+ return __builtin_mul_overflow (a, b, &c);
+}
+
+signed char
+f12 (signed char a, unsigned char b)
+{
+ short c;
+ return __builtin_mul_overflow (a, b, &c);
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-clear-padding-1.c b/gcc/testsuite/gcc.dg/builtin-clear-padding-1.c
new file mode 100644
index 0000000..27ffc0a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-clear-padding-1.c
@@ -0,0 +1,10 @@
+/* PR libstdc++/88101 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+foo (int n)
+{
+ struct S { char a; int b[n]; long long c; } s;
+ __builtin_clear_padding (&s); /* { dg-message "unimplemented: __builtin_clear_padding not supported for variable length aggregates" } */
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c b/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c
new file mode 100644
index 0000000..641d47d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c
@@ -0,0 +1,15 @@
+/* PR middle-end/97943 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); };
+struct T { int a; struct S b; int c; };
+union U { int a; struct S b; };
+struct V { int a; union U b; int : 15; int c; };
+
+void
+foo (struct T *t, struct V *v)
+{
+ __builtin_clear_padding (t); /* { dg-error "flexible array member 'b' does not have well defined padding bits for '__builtin_clear_padding'" } */
+ __builtin_clear_padding (v); /* { dg-error "flexible array member 'b' does not have well defined padding bits for '__builtin_clear_padding'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c11-binary-constants-1.c b/gcc/testsuite/gcc.dg/c11-binary-constants-1.c
new file mode 100644
index 0000000..fdc7df4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-binary-constants-1.c
@@ -0,0 +1,11 @@
+/* Test that binary constants are diagnosed in C11 mode: -pedantic. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+int a = 0b1; /* { dg-warning "binary constants" } */
+#if 0b101 /* { dg-warning "binary constants" } */
+#endif
+
+int b = 0B1; /* { dg-warning "binary constants" } */
+#if 0B101 /* { dg-warning "binary constants" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/c11-binary-constants-2.c b/gcc/testsuite/gcc.dg/c11-binary-constants-2.c
new file mode 100644
index 0000000..6b48a5d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-binary-constants-2.c
@@ -0,0 +1,11 @@
+/* Test that binary constants are diagnosed in C11 mode: -pedantic-errors. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int a = 0b1; /* { dg-error "binary constants" } */
+#if 0b101 /* { dg-error "binary constants" } */
+#endif
+
+int b = 0B1; /* { dg-error "binary constants" } */
+#if 0B101 /* { dg-error "binary constants" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/c11-bool-1.c b/gcc/testsuite/gcc.dg/c11-bool-1.c
new file mode 100644
index 0000000..0412624
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-bool-1.c
@@ -0,0 +1,50 @@
+/* Test macro expansions in <stdbool.h> in C11. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdbool.h>
+
+#define str(x) xstr(x)
+#define xstr(x) #x
+
+extern void abort (void);
+extern void exit (int);
+extern int strcmp (const char *, const char *);
+
+#if false - 1 >= 0
+#error "false unsigned in #if"
+#endif
+
+#if false != 0
+#error "false not 0 in #if"
+#endif
+
+#if true - 2 >= 0
+#error "true unsigned in #if"
+#endif
+
+#if true != 1
+#error "true not 1 in #if"
+#endif
+
+int
+main (void)
+{
+ if (strcmp (str (bool), "_Bool") != 0)
+ abort ();
+ if (_Generic (true, int : 1) != 1)
+ abort ();
+ if (true != 1)
+ abort ();
+ if (strcmp (str (true), "1") != 0)
+ abort ();
+ if (_Generic (false, int : 1) != 1)
+ abort ();
+ if (false != 0)
+ abort ();
+ if (strcmp (str (false), "0") != 0)
+ abort ();
+ if (strcmp (str (__bool_true_false_are_defined), "1") != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c b/gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c
new file mode 100644
index 0000000..b1c05cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c
@@ -0,0 +1,52 @@
+/* Test comparisons of pointers to complete and incomplete types are
+ accepted in C11 mode. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int
+f (int (*p)[], int (*q)[3])
+{
+ return p < q;
+}
+
+int
+f2 (int (*p)[], int (*q)[3])
+{
+ return p <= q;
+}
+
+int
+f3 (int (*p)[], int (*q)[3])
+{
+ return p > q;
+}
+
+int
+f4 (int (*p)[], int (*q)[3])
+{
+ return p >= q;
+}
+
+int
+g (int (*p)[], int (*q)[3])
+{
+ return q < p;
+}
+
+int
+g2 (int (*p)[], int (*q)[3])
+{
+ return q <= p;
+}
+
+int
+g3 (int (*p)[], int (*q)[3])
+{
+ return q > p;
+}
+
+int
+g4 (int (*p)[], int (*q)[3])
+{
+ return q >= p;
+}
diff --git a/gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c b/gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c
new file mode 100644
index 0000000..8e809e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c
@@ -0,0 +1,52 @@
+/* Test comparisons of pointers to complete and incomplete types are
+ diagnosed in C11 mode with -Wc99-c11-compat. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -Wc99-c11-compat" } */
+
+int
+f (int (*p)[], int (*q)[3])
+{
+ return p < q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+f2 (int (*p)[], int (*q)[3])
+{
+ return p <= q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+f3 (int (*p)[], int (*q)[3])
+{
+ return p > q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+f4 (int (*p)[], int (*q)[3])
+{
+ return p >= q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g (int (*p)[], int (*q)[3])
+{
+ return q < p; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g2 (int (*p)[], int (*q)[3])
+{
+ return q <= p; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g3 (int (*p)[], int (*q)[3])
+{
+ return q > p; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g4 (int (*p)[], int (*q)[3])
+{
+ return q >= p; /* { dg-warning "complete and incomplete" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c11-float-4.c b/gcc/testsuite/gcc.dg/c11-float-4.c
new file mode 100644
index 0000000..ceac6ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-float-4.c
@@ -0,0 +1,25 @@
+/* Test infinity and NaN macros not defined for C11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <float.h>
+
+#ifdef INFINITY
+#error "INFINITY defined"
+#endif
+
+#ifdef NAN
+#error "NAN defined"
+#endif
+
+#ifdef FLT_SNAN
+#error "FLT_SNAN defined"
+#endif
+
+#ifdef DBL_SNAN
+#error "DBL_SNAN defined"
+#endif
+
+#ifdef LDBL_SNAN
+#error "LDBL_SNAN defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c11-float-5.c b/gcc/testsuite/gcc.dg/c11-float-5.c
new file mode 100644
index 0000000..bb48695
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-float-5.c
@@ -0,0 +1,35 @@
+/* Test sNaN macros for _FloatN and _FloatNx not defined for C11 with
+ __STDC_WANT_IEC_60559_TYPES_EXT__. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+
+#ifdef FLT16_SNAN
+#error "FLT16_SNAN defined"
+#endif
+
+#ifdef FLT32_SNAN
+#error "FLT32_SNAN defined"
+#endif
+
+#ifdef FLT64_SNAN
+#error "FLT64_SNAN defined"
+#endif
+
+#ifdef FLT128_SNAN
+#error "FLT128_SNAN defined"
+#endif
+
+#ifdef FLT32X_SNAN
+#error "FLT32X_SNAN defined"
+#endif
+
+#ifdef FLT64X_SNAN
+#error "FLT64X_SNAN defined"
+#endif
+
+#ifdef FLT128X_SNAN
+#error "FLT128X_SNAN defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c11-float-6.c b/gcc/testsuite/gcc.dg/c11-float-6.c
new file mode 100644
index 0000000..b0381e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-float-6.c
@@ -0,0 +1,17 @@
+/* Test *_IS_IEC_60559 not defined for C11. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <float.h>
+
+#ifdef FLT_IS_IEC_60559
+#error "FLT_IS_IEC_60559 defined"
+#endif
+
+#ifdef DBL_IS_IEC_60559
+#error "DBL_IS_IEC_60559 defined"
+#endif
+
+#ifdef LDBL_IS_IEC_60559
+#error "LDBL_IS_IEC_60559 defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c11-float-dfp-2.c b/gcc/testsuite/gcc.dg/c11-float-dfp-2.c
new file mode 100644
index 0000000..e63ebbc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-float-dfp-2.c
@@ -0,0 +1,6 @@
+/* Test DFP macros not defined in <float.h> for C11. Infinity and NaN
+ macros. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+#include "c2x-float-no-dfp-3.c"
diff --git a/gcc/testsuite/gcc.dg/c11-labels-1.c b/gcc/testsuite/gcc.dg/c11-labels-1.c
new file mode 100644
index 0000000..6350403
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-labels-1.c
@@ -0,0 +1,15 @@
+/* Tests for labels before declarations and at ends of compound statements. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+int f(int x)
+{
+ goto b;
+ a: int i = 2 * x;
+ goto c;
+ b: goto a;
+ { i *= 3; c: }
+ return i;
+ d:
+}
+
diff --git a/gcc/testsuite/gcc.dg/c11-labels-2.c b/gcc/testsuite/gcc.dg/c11-labels-2.c
new file mode 100644
index 0000000..e9b4924
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-labels-2.c
@@ -0,0 +1,15 @@
+/* Tests for labels before declarations and at ends of compound statements. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+int f(int x)
+{
+ goto b;
+ a: int i = 2 * x; /* { dg-warning "a label can only be part of a statement and a declaration is not a statement" } */
+ goto c;
+ b: goto a;
+ { i *= 3; c: } /* { dg-warning "label at end of compound statement" } */
+ return i;
+ d: /* { dg-warning "label at end of compound statement" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/c11-labels-3.c b/gcc/testsuite/gcc.dg/c11-labels-3.c
new file mode 100644
index 0000000..1e4be63
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-labels-3.c
@@ -0,0 +1,15 @@
+/* Tests for labels before declarations and at ends of compound statements. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int f(int x)
+{
+ goto b;
+ a: int i = 2 * x; /* { dg-error "a label can only be part of a statement and a declaration is not a statement" } */
+ goto c;
+ b: goto a;
+ { i *= 3; c: } /* { dg-error "label at end of compound statement" } */
+ return i;
+ d: /* { dg-error "label at end of compound statement" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/c11-parm-omit-1.c b/gcc/testsuite/gcc.dg/c11-parm-omit-1.c
new file mode 100644
index 0000000..83d1b50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-parm-omit-1.c
@@ -0,0 +1,5 @@
+/* Test omitted parameter names not in C11: -pedantic-errors. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+void f (int) { } /* { dg-error "omitting parameter names" } */
diff --git a/gcc/testsuite/gcc.dg/c11-parm-omit-2.c b/gcc/testsuite/gcc.dg/c11-parm-omit-2.c
new file mode 100644
index 0000000..2efd450
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-parm-omit-2.c
@@ -0,0 +1,5 @@
+/* Test omitted parameter names not in C11: -pedantic. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+void f (int) { } /* { dg-warning "omitting parameter names" } */
diff --git a/gcc/testsuite/gcc.dg/c11-parm-omit-3.c b/gcc/testsuite/gcc.dg/c11-parm-omit-3.c
new file mode 100644
index 0000000..5bf27a0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-parm-omit-3.c
@@ -0,0 +1,5 @@
+/* Test omitted parameter names not in C11: -pedantic -Wno-c11-c2x-compat. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic -Wno-c11-c2x-compat" } */
+
+void f (int) { }
diff --git a/gcc/testsuite/gcc.dg/c11-parm-omit-4.c b/gcc/testsuite/gcc.dg/c11-parm-omit-4.c
new file mode 100644
index 0000000..ea4cbfa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-parm-omit-4.c
@@ -0,0 +1,6 @@
+/* Test omitted parameter names not in C11: accepted by default in the
+ absence of -pedantic. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+void f (int) { }
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c
index f1848a2..7698434 100644
--- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c
+++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c
@@ -1,13 +1,11 @@
-/* Test C2x deprecated attribute: duplicates. */
+/* Test C2x deprecated attribute: duplicates (allowed after N2557). */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
-[[deprecated, __deprecated__]] int a; /* { dg-error "can appear at most once" } */
-[[__deprecated__, deprecated("message")]] int b; /* { dg-error "can appear at most once" } */
-int c [[deprecated("message"), deprecated]]; /* { dg-error "can appear at most once" } */
-[[deprecated, deprecated]]; /* { dg-error "can appear at most once" } */
+[[deprecated, __deprecated__]] int a;
+[[__deprecated__, deprecated("message")]] int b;
+int c [[deprecated("message"), deprecated]];
+[[deprecated, deprecated]];
/* { dg-error "ignored" "ignored" { target *-*-* } .-1 } */
-/* Separate attribute lists in the same attribute specifier sequence,
- with the same attribute in them, are OK. */
[[deprecated]] [[deprecated]] int d [[deprecated]] [[deprecated]];
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c b/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c
index 75aceff..a6cedcd 100644
--- a/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c
+++ b/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c
@@ -1,4 +1,4 @@
-/* Test C2x fallthrough attribute: duplicates. */
+/* Test C2x fallthrough attribute: duplicates (allowed after N2557). */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
@@ -9,12 +9,9 @@ f (int a)
{
case 1:
a++;
- [[fallthrough, __fallthrough__]]; /* { dg-error "can appear at most once" } */
+ [[fallthrough, __fallthrough__]]; /* { dg-warning "specified multiple times" } */
case 2:
a++;
- /* Separate attribute lists in the same attribute specifier
- sequence, with the same attribute in them, are OK (but
- receive a warning). */
[[fallthrough]] [[fallthrough]]; /* { dg-warning "specified multiple times" } */
case 3:
a++;
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c b/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c
index 300c0da..6b997aa 100644
--- a/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c
+++ b/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c
@@ -1,13 +1,11 @@
-/* Test C2x maybe_unused attribute: duplicates. */
+/* Test C2x maybe_unused attribute: duplicates (allowed after N2557). */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
-[[maybe_unused, __maybe_unused__]] int a; /* { dg-error "can appear at most once" } */
-[[__maybe_unused__, maybe_unused]] int b; /* { dg-error "can appear at most once" } */
-int c [[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */
-[[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */
+[[maybe_unused, __maybe_unused__]] int a;
+[[__maybe_unused__, maybe_unused]] int b;
+int c [[maybe_unused, maybe_unused]];
+[[maybe_unused, maybe_unused]];
/* { dg-error "ignored" "ignored" { target *-*-* } .-1 } */
-/* Separate attribute lists in the same attribute specifier sequence,
- with the same attribute in them, are OK. */
[[maybe_unused]] [[maybe_unused]] int d [[maybe_unused]] [[maybe_unused]];
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-1.c b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-1.c
new file mode 100644
index 0000000..f4893bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-1.c
@@ -0,0 +1,62 @@
+/* Test C2x deprecated attribute: valid uses. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[nodiscard]] int c1 (void); /* { dg-message "declared here" } */
+[[__nodiscard__ ("some reason")]] int c2 (void); /* { dg-message "declared here" } */
+
+struct [[nodiscard ("struct reason")]] s1 { int a; };
+struct [[__nodiscard__]] s2 { long b; };
+struct s1 cs1 (void); /* { dg-message "declared here" } */
+struct s2 cs2 (void); /* { dg-message "declared here" } */
+typedef struct s2 s2t;
+s2t cs3 (void); /* { dg-message "declared here" } */
+
+union [[nodiscard]] u1 { int a; long b; };
+union [[nodiscard ("union reason")]] u2 { short c; float d; };
+union u1 cu1 (void); /* { dg-message "declared here" } */
+union u2 cu2 (void); /* { dg-message "declared here" } */
+
+enum [[nodiscard]] e1 { E1 };
+enum [[nodiscard ("enum reason")]] e2 { E2 };
+enum e1 ce1 (void); /* { dg-message "declared here" } */
+enum e2 ce2 (void); /* { dg-message "declared here" } */
+enum e1 ce1a (void);
+int i;
+
+[[nodiscard]] void v (void); /* { dg-warning "void return type" } */
+
+int ok (void);
+
+void
+f (void)
+{
+ c1 (); /* { dg-warning "ignoring return value" } */
+ c2 (); /* { dg-warning "some reason" } */
+ cs1 (); /* { dg-warning "struct reason" } */
+ cs2 (); /* { dg-warning "ignoring return value of type" } */
+ cs3 (); /* { dg-warning "ignoring return value of type" } */
+ cu1 (); /* { dg-warning "ignoring return value of type" } */
+ cu2 (); /* { dg-warning "union reason" } */
+ ce1 (); /* { dg-warning "ignoring return value of type" } */
+ ce2 (); /* { dg-warning "enum reason" } */
+ ok ();
+ c1 (), ok (); /* { dg-warning "ignoring return value" } */
+ cs1 (), ok (); /* { dg-warning "struct reason" } */
+ ok (), cu1 (); /* { dg-warning "ignoring return value" } */
+ ok (), (ok (), (ok (), ce2 ())); /* { dg-warning "enum reason" } */
+ (ok (), cu1 ()), ok (); /* { dg-warning "ignoring return value" } */
+ v ();
+ (i ? ce1 : ce1a) (); /* { dg-warning "ignoring return value of type" } */
+ (void) c1 ();
+ (void) c2 ();
+ (void) cs1 ();
+ (void) cs2 ();
+ (void) cs3 ();
+ (void) cu1 ();
+ (void) cu2 ();
+ (void) ce1 ();
+ (void) ce2 ();
+ (void) (ok (), cu1 ());
+ (void) (i ? ce1 : ce1a) ();
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c
new file mode 100644
index 0000000..45c4d50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c
@@ -0,0 +1,42 @@
+/* Test C2x nodiscard attribute: invalid contexts. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+/* This attribute is not valid on types other than their definitions,
+ or on declarations other than function declarations, or on
+ statements, or as an attribute-declaration. */
+
+[[nodiscard]]; /* { dg-error "ignored" } */
+
+int [[nodiscard]] var; /* { dg-error "ignored" } */
+
+int [[nodiscard ("reason")]] var2; /* { dg-error "ignored" } */
+
+int array_with_nod_type[2] [[nodiscard]]; /* { dg-error "ignored" } */
+
+void fn_with_nod_type () [[nodiscard]]; /* { dg-error "ignored" } */
+
+int z = sizeof (int [[__nodiscard__]]); /* { dg-error "ignored" } */
+
+[[nodiscard]] typedef int nod_int; /* { dg-error "can only be applied" } */
+
+[[nodiscard]] int nvar; /* { dg-error "can only be applied" } */
+
+struct s { int a; };
+
+[[nodiscard]] typedef struct s nod_s; /* { dg-error "can only be applied" } */
+
+struct t { [[nodiscard]] int b; }; /* { dg-error "can only be applied" } */
+
+enum e { E [[nodiscard]] }; /* { dg-error "can only be applied" } */
+
+void fx ([[nodiscard]] int p); /* { dg-error "can only be applied" } */
+
+void
+f (void)
+{
+ int a;
+ [[nodiscard ("reason")]] int b = 1; /* { dg-error "can only be applied" } */
+ [[nodiscard]]; /* { dg-error "ignored" } */
+ [[nodiscard]] a = 1; /* { dg-error "ignored" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-3.c b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-3.c
new file mode 100644
index 0000000..2e70d12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-3.c
@@ -0,0 +1,11 @@
+/* Test C2x nodiscard attribute: invalid syntax. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[nodiscard()]] int a (void); /* { dg-error "parentheses must be omitted if attribute argument list is empty" } */
+
+[[nodiscard(0)]] int b (void); /* { dg-error "expected" } */
+
+[[nodiscard("", 123)]] int c (void); /* { dg-error "expected" } */
+
+[[nodiscard((""))]] int d (void); /* { dg-error "expected" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-4.c b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-4.c
new file mode 100644
index 0000000..278f55d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-4.c
@@ -0,0 +1,6 @@
+/* Test C2x nodiscard attribute: duplicates (allowed after N2557). */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[nodiscard, __nodiscard__]] int f (void);
+[[__nodiscard__, nodiscard("message")]] int g (void);
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-3.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-3.c
index 1f883d8..2f0d9f6 100644
--- a/gcc/testsuite/gcc.dg/c2x-attr-syntax-3.c
+++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-3.c
@@ -25,13 +25,14 @@ f2 (void)
}
/* Declarations, including attribute declarations, cannot appear after
- labels. */
+ labels when a statement is expected. */
void
f3 (void)
{
- x: [[]];; /* { dg-error "can only be part of a statement" } */
-}
+ if (1)
+ x: [[]]; /* { dg-error "expected" } */
+}
/* Prefix attributes cannot appear on type names. */
diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-5.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-5.c
index 37a2411..b261be0 100644
--- a/gcc/testsuite/gcc.dg/c2x-attr-syntax-5.c
+++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-5.c
@@ -49,8 +49,3 @@ func (void) [[unknown_attribute]] { /* { dg-error "attribute ignored" } */
[[unknown_attribute]] x: var = 2; /* { dg-error "attribute ignored" } */
for ([[unknown_attribute]] int zz = 1; zz < 10; zz++) ; /* { dg-error "attribute ignored" } */
}
-
-/* nodiscard is not yet implemented, but is a standard attribute, so
- its use is not a constraint violation and should only receive a
- warning. */
-[[nodiscard]] int ndfunc (void); /* { dg-warning "attribute directive ignored" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-binary-constants-1.c b/gcc/testsuite/gcc.dg/c2x-binary-constants-1.c
new file mode 100644
index 0000000..bbb2bc8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-binary-constants-1.c
@@ -0,0 +1,5 @@
+/* Test C2x binary constants. Valid syntax and types. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include "binary-constants-1.c"
diff --git a/gcc/testsuite/gcc.dg/c2x-binary-constants-2.c b/gcc/testsuite/gcc.dg/c2x-binary-constants-2.c
new file mode 100644
index 0000000..4379427
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-binary-constants-2.c
@@ -0,0 +1,11 @@
+/* Test that binary constants are accepted in C2X mode: compat warnings. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
+
+int a = 0b1; /* { dg-warning "C2X feature" } */
+#if 0b101 /* { dg-warning "C2X feature" } */
+#endif
+
+int b = 0B1; /* { dg-warning "C2X feature" } */
+#if 0B101 /* { dg-warning "C2X feature" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-binary-constants-3.c b/gcc/testsuite/gcc.dg/c2x-binary-constants-3.c
new file mode 100644
index 0000000..7604791f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-binary-constants-3.c
@@ -0,0 +1,9 @@
+/* Test C2x binary constants. Invalid constants. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+int a = 0b; /* { dg-error "invalid suffix" } */
+int b = 0B2; /* { dg-error "invalid suffix" } */
+int c = 0B02; /* { dg-error "invalid digit" } */
+int d = 0b1.1; /* { dg-error "invalid prefix" } */
+int e = 0B0p0; /* { dg-error "invalid suffix" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-bool-1.c b/gcc/testsuite/gcc.dg/c2x-bool-1.c
new file mode 100644
index 0000000..b64da1f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-bool-1.c
@@ -0,0 +1,50 @@
+/* Test macro expansions in <stdbool.h> in C2x. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <stdbool.h>
+
+#define str(x) xstr(x)
+#define xstr(x) #x
+
+extern void abort (void);
+extern void exit (int);
+extern int strcmp (const char *, const char *);
+
+#if false - 1 < 0
+#error "false signed in #if"
+#endif
+
+#if false != 0
+#error "false not 0 in #if"
+#endif
+
+#if true - 2 < 0
+#error "true signed in #if"
+#endif
+
+#if true != 1
+#error "true not 1 in #if"
+#endif
+
+int
+main (void)
+{
+ if (strcmp (str (bool), "_Bool") != 0)
+ abort ();
+ if (_Generic (true, _Bool : 1) != 1)
+ abort ();
+ if (true != 1)
+ abort ();
+ if (strcmp (str (true), "((_Bool)+1u)") != 0)
+ abort ();
+ if (_Generic (false, _Bool : 1) != 1)
+ abort ();
+ if (false != 0)
+ abort ();
+ if (strcmp (str (false), "((_Bool)+0u)") != 0)
+ abort ();
+ if (strcmp (str (__bool_true_false_are_defined), "1") != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-10.c b/gcc/testsuite/gcc.dg/c2x-float-10.c
new file mode 100644
index 0000000..7b53a6a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-10.c
@@ -0,0 +1,33 @@
+/* Test *_IS_IEC_60559 macros. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <float.h>
+
+#ifndef FLT_IS_IEC_60559
+#error "FLT_IS_IEC_60559 undefined"
+#endif
+
+#ifndef DBL_IS_IEC_60559
+#error "DBL_IS_IEC_60559 undefined"
+#endif
+
+#ifndef LDBL_IS_IEC_60559
+#error "LDBL_IS_IEC_60559 undefined"
+#endif
+
+#if defined __pdp11__ || defined __vax__
+_Static_assert (FLT_IS_IEC_60559 == 0);
+_Static_assert (DBL_IS_IEC_60559 == 0);
+_Static_assert (LDBL_IS_IEC_60559 == 0);
+#else
+_Static_assert (FLT_IS_IEC_60559 == 2);
+_Static_assert (DBL_IS_IEC_60559 == 2);
+#if LDBL_MANT_DIG == 106 || LDBL_MIN_EXP == -16382
+/* IBM long double and m68k extended format do not meet the definition
+ of an IEC 60559 interchange or extended format. */
+_Static_assert (LDBL_IS_IEC_60559 == 0);
+#else
+_Static_assert (LDBL_IS_IEC_60559 == 2);
+#endif
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-float-2.c b/gcc/testsuite/gcc.dg/c2x-float-2.c
new file mode 100644
index 0000000..4f669fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-2.c
@@ -0,0 +1,23 @@
+/* Test INFINITY macro. Generic test even if infinities not
+ supported. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -w" } */
+/* { dg-add-options ieee } */
+
+#include <float.h>
+
+#ifndef INFINITY
+#error "INFINITY undefined"
+#endif
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (INFINITY, float : 0);
+ if (!(INFINITY >= FLT_MAX))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-3.c b/gcc/testsuite/gcc.dg/c2x-float-3.c
new file mode 100644
index 0000000..7c6298b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-3.c
@@ -0,0 +1,27 @@
+/* Test INFINITY macro. Test when infinities supported. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target inff } */
+
+#include <float.h>
+
+#ifndef INFINITY
+#error "INFINITY undefined"
+#endif
+
+volatile float f = INFINITY;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (INFINITY, float : 0);
+ if (!(INFINITY > FLT_MAX))
+ abort ();
+ if (!(f > FLT_MAX))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-4.c b/gcc/testsuite/gcc.dg/c2x-float-4.c
new file mode 100644
index 0000000..bca8435
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-4.c
@@ -0,0 +1,33 @@
+/* Test NAN macro. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+/* { dg-add-options ieee } */
+
+#include <float.h>
+
+/* This should be defined if and only if quiet NaNs are supported for
+ type float. If the testsuite gains effective-target support for
+ targets not supporting NaNs, or not supporting them for all types,
+ this test should be split into versions for targets with and
+ without NaNs for float. */
+#ifndef NAN
+#error "NAN undefined"
+#endif
+
+volatile float f = NAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (NAN, float : 0);
+ if (!__builtin_isnan (NAN))
+ abort ();
+ if (!__builtin_isnan (f))
+ abort ();
+ if (!__builtin_isnan (f + f))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-5.c b/gcc/testsuite/gcc.dg/c2x-float-5.c
new file mode 100644
index 0000000..477f9cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-5.c
@@ -0,0 +1,32 @@
+/* Test NAN macro. Runtime exceptions test, to verify NaN is quiet
+ not signaling. */
+/* { dg-do run } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+/* { dg-add-options ieee } */
+
+#include <fenv.h>
+#include <float.h>
+
+/* This should be defined if and only if quiet NaNs are supported for
+ type float. If the testsuite gains effective-target support for
+ targets not supporting NaNs, or not supporting them for all types,
+ this test should only be run for targets supporting quiet NaNs for
+ float. */
+#ifndef NAN
+#error "NAN undefined"
+#endif
+
+volatile float f = NAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ f += f;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-6.c b/gcc/testsuite/gcc.dg/c2x-float-6.c
new file mode 100644
index 0000000..573540b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-6.c
@@ -0,0 +1,49 @@
+/* Test SNAN macros. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors -fsignaling-nans" } */
+/* { dg-add-options ieee } */
+
+#include <float.h>
+
+/* These should be defined if and only if signaling NaNs are supported
+ for the given types. If the testsuite gains effective-target
+ support for targets not supporting signaling NaNs, or not
+ supporting them for all types, this test should be made
+ appropriately conditional. */
+#ifndef FLT_SNAN
+#error "FLT_SNAN undefined"
+#endif
+#ifndef DBL_SNAN
+#error "DBL_SNAN undefined"
+#endif
+#ifndef LDBL_SNAN
+#error "LDBL_SNAN undefined"
+#endif
+
+volatile float f = FLT_SNAN;
+volatile double d = DBL_SNAN;
+volatile long double ld = LDBL_SNAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (FLT_SNAN, float : 0);
+ (void) _Generic (DBL_SNAN, double : 0);
+ (void) _Generic (LDBL_SNAN, long double : 0);
+ if (!__builtin_isnan (FLT_SNAN))
+ abort ();
+ if (!__builtin_isnan (f))
+ abort ();
+ if (!__builtin_isnan (DBL_SNAN))
+ abort ();
+ if (!__builtin_isnan (d))
+ abort ();
+ if (!__builtin_isnan (LDBL_SNAN))
+ abort ();
+ if (!__builtin_isnan (ld))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-7.c b/gcc/testsuite/gcc.dg/c2x-float-7.c
new file mode 100644
index 0000000..0c90ff2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-7.c
@@ -0,0 +1,49 @@
+/* Test SNAN macros. Runtime exceptions test, to verify NaN is
+ signaling. */
+/* { dg-do run } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-options "-std=c2x -pedantic-errors -fsignaling-nans" } */
+/* { dg-add-options ieee } */
+
+#include <fenv.h>
+#include <float.h>
+
+/* These should be defined if and only if signaling NaNs are supported
+ for the given types. If the testsuite gains effective-target
+ support for targets not supporting signaling NaNs, or not
+ supporting them for all types, this test should be made
+ appropriately conditional. */
+#ifndef FLT_SNAN
+#error "FLT_SNAN undefined"
+#endif
+#ifndef DBL_SNAN
+#error "DBL_SNAN undefined"
+#endif
+#ifndef LDBL_SNAN
+#error "LDBL_SNAN undefined"
+#endif
+
+volatile float f = FLT_SNAN;
+volatile double d = DBL_SNAN;
+volatile long double ld = LDBL_SNAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ feclearexcept (FE_ALL_EXCEPT);
+ f += f;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d += d;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ ld += ld;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-float-8.c b/gcc/testsuite/gcc.dg/c2x-float-8.c
new file mode 100644
index 0000000..b10cb85
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-8.c
@@ -0,0 +1,7 @@
+/* Test including <math.h> then <float.h> does not result in errors
+ from duplicate NAN and INFINITY macros. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <math.h>
+#include <float.h>
diff --git a/gcc/testsuite/gcc.dg/c2x-float-9.c b/gcc/testsuite/gcc.dg/c2x-float-9.c
new file mode 100644
index 0000000..0a54bc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-9.c
@@ -0,0 +1,7 @@
+/* Test including <float.h> then <math.h> does not result in errors
+ from duplicate NAN and INFINITY macros. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <float.h>
+#include <math.h>
diff --git a/gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c
new file mode 100644
index 0000000..aa790c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c
@@ -0,0 +1,26 @@
+/* Test DFP macros not defined in <float.h> if no DFP support.
+ Infinity and NaN macros. */
+/* { dg-do compile { target { ! dfp } } } */
+/* { dg-options "-std=c2x" } */
+
+#include <float.h>
+
+#ifdef DEC_INFINITY
+# error "DEC_INFINITY defined"
+#endif
+
+#ifdef DEC_NAN
+# error "DEC_NAN defined"
+#endif
+
+#ifdef DEC32_SNAN
+# error "DEC32_SNAN defined"
+#endif
+
+#ifdef DEC64_SNAN
+# error "DEC64_SNAN defined"
+#endif
+
+#ifdef DEC128_SNAN
+# error "DEC128_SNAN defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c
new file mode 100644
index 0000000..855922a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c
@@ -0,0 +1,10 @@
+/* Test DFP macros not defined in <float.h> if no DFP support.
+ Infinity and NaN macros. Test with feature test macros
+ defined. */
+/* { dg-do compile { target { ! dfp } } } */
+/* { dg-options "-std=c2x" } */
+
+#define __STDC_WANT_DEC_FP__
+#define __STDC_WANT_IEC_60559_DFP_EXT__
+
+#include "c2x-float-no-dfp-3.c"
diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c
new file mode 100644
index 0000000..fe06abf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c
@@ -0,0 +1,28 @@
+/* Test __has_c_attribute. Test basic properties. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#ifdef __has_c_attribute
+/* OK. */
+#else
+#error "__has_c_attribute not defined"
+#endif
+
+#ifndef __has_c_attribute
+#error "__has_c_attribute not defined"
+#endif
+
+#if defined __has_c_attribute
+/* OK. */
+#else
+#error "__has_c_attribute not defined"
+#endif
+
+#if __has_c_attribute(foo)
+#error "foo attribute supported"
+#endif
+
+#if 0
+#elif __has_c_attribute(foo)
+#error "foo attribute supported"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c
new file mode 100644
index 0000000..d6c4c6d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c
@@ -0,0 +1,41 @@
+/* Test __has_c_attribute. Test supported attributes. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#if __has_c_attribute ( nodiscard ) != 202003L
+#error "bad result for nodiscard"
+#endif
+
+#if __has_c_attribute ( __nodiscard__ ) != 202003L
+#error "bad result for __nodiscard__"
+#endif
+
+#if __has_c_attribute(maybe_unused) != 201904L
+#error "bad result for maybe_unused"
+#endif
+
+#if __has_c_attribute(__maybe_unused__) != 201904L
+#error "bad result for __maybe_unused__"
+#endif
+
+#if __has_c_attribute (deprecated) != 201904L
+#error "bad result for deprecated"
+#endif
+
+#if __has_c_attribute (__deprecated__) != 201904L
+#error "bad result for __deprecated__"
+#endif
+
+#if __has_c_attribute (fallthrough) != 201904L
+#error "bad result for fallthrough"
+#endif
+
+#if __has_c_attribute (__fallthrough__) != 201904L
+#error "bad result for __fallthrough__"
+#endif
+
+/* Macros in the attribute name are expanded. */
+#define foo deprecated
+#if __has_c_attribute (foo) != 201904L
+#error "bad result for foo"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c
new file mode 100644
index 0000000..36842ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c
@@ -0,0 +1,25 @@
+/* Test __has_c_attribute. Test GNU attributes. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#if __has_c_attribute (gnu::packed) != 1
+#error "bad result for gnu::packed"
+#endif
+
+#if __has_c_attribute (__gnu__::__packed__) != 1
+#error "bad result for __gnu__::__packed__"
+#endif
+
+#if __has_c_attribute (gnu::__packed__) != 1
+#error "bad result for gnu::__packed__"
+#endif
+
+#if __has_c_attribute (__gnu__::packed) != 1
+#error "bad result for __gnu__::packed"
+#endif
+
+/* GNU attributes should not be reported as accepted without a scope
+ specified. */
+#if __has_c_attribute (packed) != 0
+#error "bad result for packed"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c
new file mode 100644
index 0000000..acd35d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c
@@ -0,0 +1,18 @@
+/* Test __has_c_attribute. Test syntax errors. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#if __has_c_attribute /* { dg-error "missing '\\('" } */
+#endif
+
+#if __has_c_attribute 0 /* { dg-error "missing '\\('" } */
+#endif
+
+#if __has_c_attribute (0 /* { dg-error "requires an identifier" } */
+#endif
+
+#if __has_c_attribute (x /* { dg-error "missing '\\)'" } */
+#endif
+
+#if __has_c_attribute (x::0) /* { dg-error "required after scope" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/c2x-labels-1.c b/gcc/testsuite/gcc.dg/c2x-labels-1.c
new file mode 100644
index 0000000..439cf78
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-labels-1.c
@@ -0,0 +1,23 @@
+/* Tests for labels before declarations and at ends of compound statements. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+int f(int x)
+{
+ goto b;
+ a: int i = 2 * x;
+ aa: int u = 0; int v = 0;
+ goto c;
+ b: goto a;
+ { i *= 3; c: }
+ return i + u + v;
+ d:
+}
+
+int main(void)
+{
+ if (2 != f(1))
+ __builtin_abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-labels-2.c b/gcc/testsuite/gcc.dg/c2x-labels-2.c
new file mode 100644
index 0000000..bd010e9e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-labels-2.c
@@ -0,0 +1,15 @@
+/* Tests for labels before declarations and at ends of compound statements. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
+
+int f(int x)
+{
+ goto b;
+ a: int i = 2 * x; /* { dg-warning "a label can only be part of a statement and a declaration is not a statement" } */
+ goto c;
+ b: goto a;
+ { i *= 3; c: } /* { dg-warning "label at end of compound statement" } */
+ return i;
+ d: /* { dg-warning "label at end of compound statement" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/c2x-labels-3.c b/gcc/testsuite/gcc.dg/c2x-labels-3.c
new file mode 100644
index 0000000..159116d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-labels-3.c
@@ -0,0 +1,38 @@
+/* Tests for labels before declarations and at ends of compound statements
+ * in combination with attributes. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wall" } */
+
+int f(void)
+{
+ goto b;
+ a: int i = 0;
+ aa: __attribute__((unused)) int u = 0; int v = 0; /* { dg-warning "GNU-style attribute between label and declaration appertains to the label" } */
+ goto c;
+ { c: }
+ b: goto a;
+ return i + u + v;
+ d: __attribute__((unused)) (void)0;
+ e: __attribute__((unused))
+}
+
+int g(void)
+{
+ goto b;
+ a: int i = 0;
+ [[maybe_unused]] aa: int u = 0; int v = 0;
+ goto c;
+ { c: }
+ b: goto a;
+ return i + u + v;
+ [[maybe_unused]] d: (void)0;
+ [[maybe_unused]] e:
+}
+
+void h(void)
+{
+ [[maybe_unused]] a: [[maybe_unused]] b: [[maybe_unused]] int x;
+
+ if (1)
+ [[maybe_unused]] c: [[maybe_unused]] d: (void)0;
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-parm-omit-1.c b/gcc/testsuite/gcc.dg/c2x-parm-omit-1.c
new file mode 100644
index 0000000..0dc89bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-parm-omit-1.c
@@ -0,0 +1,5 @@
+/* Test omitted parameter names in C2x. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+void f (int) { }
diff --git a/gcc/testsuite/gcc.dg/c2x-parm-omit-2.c b/gcc/testsuite/gcc.dg/c2x-parm-omit-2.c
new file mode 100644
index 0000000..7d68933
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-parm-omit-2.c
@@ -0,0 +1,10 @@
+/* Test omitted parameter names in C2x. Warning test: there should be
+ no warning for an unnamed parameter being unused. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors -Wall -Wextra" } */
+
+int
+f (int a, int, int c, int d) /* { dg-warning "unused parameter 'd'" } */
+{
+ return a + c;
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-parm-omit-3.c b/gcc/testsuite/gcc.dg/c2x-parm-omit-3.c
new file mode 100644
index 0000000..dac258b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-parm-omit-3.c
@@ -0,0 +1,23 @@
+/* Test omitted parameter names in C2x. Execution test. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+void
+f (int a, int [++a], int b)
+{
+ /* Verify array size expression of unnamed parameter is processed as
+ expected. */
+ if (a != 2 || b != 3)
+ abort ();
+}
+
+int
+main (void)
+{
+ int t[2];
+ f (1, t, 3);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-parm-omit-4.c b/gcc/testsuite/gcc.dg/c2x-parm-omit-4.c
new file mode 100644
index 0000000..a4b0deb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-parm-omit-4.c
@@ -0,0 +1,5 @@
+/* Test omitted parameter names in C2x: diagnosed with -Wc11-c2x-compat. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */
+
+void f (int) { } /* { dg-warning "omitting parameter names" } */
diff --git a/gcc/testsuite/gcc.dg/c99-bool-4.c b/gcc/testsuite/gcc.dg/c99-bool-4.c
new file mode 100644
index 0000000..5cae18a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-bool-4.c
@@ -0,0 +1,46 @@
+/* Test macro expansions in <stdbool.h> in C99. */
+/* { dg-do run } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+#include <stdbool.h>
+
+#define str(x) xstr(x)
+#define xstr(x) #x
+
+extern void abort (void);
+extern void exit (int);
+extern int strcmp (const char *, const char *);
+
+#if false - 1 >= 0
+#error "false unsigned in #if"
+#endif
+
+#if false != 0
+#error "false not 0 in #if"
+#endif
+
+#if true - 2 >= 0
+#error "true unsigned in #if"
+#endif
+
+#if true != 1
+#error "true not 1 in #if"
+#endif
+
+int
+main (void)
+{
+ if (strcmp (str (bool), "_Bool") != 0)
+ abort ();
+ if (true != 1)
+ abort ();
+ if (strcmp (str (true), "1") != 0)
+ abort ();
+ if (false != 0)
+ abort ();
+ if (strcmp (str (false), "0") != 0)
+ abort ();
+ if (strcmp (str (__bool_true_false_are_defined), "1") != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c b/gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c
new file mode 100644
index 0000000..dfafc39
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c
@@ -0,0 +1,52 @@
+/* Test comparisons of pointers to complete and incomplete types are
+ diagnosed in C99 mode: -pedantic. */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic" } */
+
+int
+f (int (*p)[], int (*q)[3])
+{
+ return p < q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+f2 (int (*p)[], int (*q)[3])
+{
+ return p <= q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+f3 (int (*p)[], int (*q)[3])
+{
+ return p > q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+f4 (int (*p)[], int (*q)[3])
+{
+ return p >= q; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g (int (*p)[], int (*q)[3])
+{
+ return q < p; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g2 (int (*p)[], int (*q)[3])
+{
+ return q <= p; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g3 (int (*p)[], int (*q)[3])
+{
+ return q > p; /* { dg-warning "complete and incomplete" } */
+}
+
+int
+g4 (int (*p)[], int (*q)[3])
+{
+ return q >= p; /* { dg-warning "complete and incomplete" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c b/gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c
new file mode 100644
index 0000000..5ae7f30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c
@@ -0,0 +1,52 @@
+/* Test comparisons of pointers to complete and incomplete types are
+ diagnosed in C99 mode: -pedantic-errors. */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+int
+f (int (*p)[], int (*q)[3])
+{
+ return p < q; /* { dg-error "complete and incomplete" } */
+}
+
+int
+f2 (int (*p)[], int (*q)[3])
+{
+ return p <= q; /* { dg-error "complete and incomplete" } */
+}
+
+int
+f3 (int (*p)[], int (*q)[3])
+{
+ return p > q; /* { dg-error "complete and incomplete" } */
+}
+
+int
+f4 (int (*p)[], int (*q)[3])
+{
+ return p >= q; /* { dg-error "complete and incomplete" } */
+}
+
+int
+g (int (*p)[], int (*q)[3])
+{
+ return q < p; /* { dg-error "complete and incomplete" } */
+}
+
+int
+g2 (int (*p)[], int (*q)[3])
+{
+ return q <= p; /* { dg-error "complete and incomplete" } */
+}
+
+int
+g3 (int (*p)[], int (*q)[3])
+{
+ return q > p; /* { dg-error "complete and incomplete" } */
+}
+
+int
+g4 (int (*p)[], int (*q)[3])
+{
+ return q >= p; /* { dg-error "complete and incomplete" } */
+}
diff --git a/gcc/testsuite/gcc.dg/cond-constqual-1.c b/gcc/testsuite/gcc.dg/cond-constqual-1.c
index 3354c72..b5a09cb 100644
--- a/gcc/testsuite/gcc.dg/cond-constqual-1.c
+++ b/gcc/testsuite/gcc.dg/cond-constqual-1.c
@@ -11,5 +11,5 @@ test (void)
__typeof__ (1 ? foo (0) : 0) texpr;
__typeof__ (1 ? i : 0) texpr2;
texpr = 0; /* { dg-bogus "read-only variable" "conditional expression with call to const function" } */
- texpr2 = 0; /* { dg-error "read-only variable" "conditional expression with const variable" } */
+ texpr2 = 0; /* { dg-bogus "read-only variable" "conditional expression with const variable" } */
}
diff --git a/gcc/testsuite/gcc.dg/cpp/line10.c b/gcc/testsuite/gcc.dg/cpp/line10.c
new file mode 100644
index 0000000..9f5f079
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/line10.c
@@ -0,0 +1,5 @@
+/* Test #line overflow checks: bug 97602. */
+/* { dg-do preprocess } */
+/* { dg-options "-pedantic" } */
+
+#line 4294967296 /* { dg-warning "line number out of range" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/line9.c b/gcc/testsuite/gcc.dg/cpp/line9.c
new file mode 100644
index 0000000..8060aff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/line9.c
@@ -0,0 +1,5 @@
+/* Test #line overflow checks: bug 97602. */
+/* { dg-do preprocess } */
+/* { dg-options "-pedantic" } */
+
+#line 5000000000 /* { dg-warning "line number out of range" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/pr97989-1.c b/gcc/testsuite/gcc.dg/cpp/pr97989-1.c
new file mode 100644
index 0000000..108dcba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pr97989-1.c
@@ -0,0 +1,8 @@
+/* PR debug/97989 */
+/* { dg-do preprocess } */
+/* { dg-options "-g3 -g2 -P" } */
+
+#define foo bar
+int i;
+
+/* { dg-final { scan-file-not pr97989-1.i "(^|\\n)#define foo bar($|\\n)" } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/pr97989-2.c b/gcc/testsuite/gcc.dg/cpp/pr97989-2.c
new file mode 100644
index 0000000..77a295a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pr97989-2.c
@@ -0,0 +1,8 @@
+/* PR debug/97989 */
+/* { dg-do preprocess } */
+/* { dg-options "-g2 -g3 -P" } */
+
+#define foo bar
+int i;
+
+/* { dg-final { scan-file pr97989-2.i "(^|\\n)#define foo bar($|\\n)" } } */
diff --git a/gcc/testsuite/gcc.dg/cr-decimal-dig-3.c b/gcc/testsuite/gcc.dg/cr-decimal-dig-3.c
new file mode 100644
index 0000000..8e07b67
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cr-decimal-dig-3.c
@@ -0,0 +1,14 @@
+/* Test C2x CR_DECIMAL_DIG: defined for __STDC_WANT_IEC_60559_EXT__. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+#define __STDC_WANT_IEC_60559_EXT__
+#include <float.h>
+
+#ifndef CR_DECIMAL_DIG
+#error "CR_DECIMAL_DIG not defined"
+#endif
+
+#if CR_DECIMAL_DIG < DECIMAL_DIG + 3
+#error "CR_DECIMAL_DIG too small"
+#endif
diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-link.c b/gcc/testsuite/gcc.dg/darwin-minversion-link.c
index 0a80048..765fb79 100644
--- a/gcc/testsuite/gcc.dg/darwin-minversion-link.c
+++ b/gcc/testsuite/gcc.dg/darwin-minversion-link.c
@@ -13,8 +13,9 @@
/* { dg-additional-options "-mmacosx-version-min=010.011.06 -DCHECK=101106" { target *-*-darwin15* } } */
/* { dg-additional-options "-mmacosx-version-min=010.012.06 -DCHECK=101206" { target *-*-darwin16* } } */
/* { dg-additional-options "-mmacosx-version-min=010.013.06 -DCHECK=101306" { target *-*-darwin17* } } */
-/* This next test covers 10.18 and (currently unreleased) 10.19 for now. */
-/* { dg-additional-options "-mmacosx-version-min=010.014.05 -DCHECK=101405" { target *-*-darwin1[89]* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.014.05 -DCHECK=101405" { target *-*-darwin18* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.015.06 -DCHECK=101506" { target *-*-darwin19* } } */
+/* { dg-additional-options "-mmacosx-version-min=011.000.00 -DCHECK=110000" { target *-*-darwin20 } } */
int
main ()
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c
new file mode 100644
index 0000000..c07b904
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c
@@ -0,0 +1,13 @@
+/* PR debug/97060 */
+/* { dg-do compile } */
+/* { dg-options "-g -dA" } */
+/* { dg-final { scan-assembler-times "DW_AT_declaration" 2 } } */
+
+extern int foo (unsigned int, unsigned int);
+
+int
+bar (void)
+{
+ foo (1, 2);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/decl-9.c b/gcc/testsuite/gcc.dg/decl-9.c
index eeca8e0..9bb1560 100644
--- a/gcc/testsuite/gcc.dg/decl-9.c
+++ b/gcc/testsuite/gcc.dg/decl-9.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-std=gnu89" } */
+/* { dg-options "-std=gnu89 -pedantic-errors" } */
w *x; /* { dg-error "unknown type name 'w'" } */
@@ -12,6 +12,7 @@ int f1()
int d, e;
d * e; /* { dg-bogus "unknown type name 'd'" } */
g * h; /* { dg-error "unknown type name 'g'" } */
+ /* { dg-error "mixed declarations" "" { target *-*-* } .-1 } */
g i; /* { dg-error "unknown type name 'g'" } */
}
diff --git a/gcc/testsuite/gcc.dg/dfp/builtin-snan-1.c b/gcc/testsuite/gcc.dg/dfp/builtin-snan-1.c
new file mode 100644
index 0000000..49a32c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/builtin-snan-1.c
@@ -0,0 +1,23 @@
+/* Test __builtin_nansd* functions. Test not requiring runtime
+ exceptions support. */
+/* { dg-do run } */
+/* { dg-options "" } */
+
+volatile _Decimal32 d32 = __builtin_nansd32 ("");
+volatile _Decimal64 d64 = __builtin_nansd64 ("");
+volatile _Decimal128 d128 = __builtin_nansd128 ("");
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ if (!__builtin_isnan (d32))
+ abort ();
+ if (!__builtin_isnan (d64))
+ abort ();
+ if (!__builtin_isnan (d128))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/builtin-snan-2.c b/gcc/testsuite/gcc.dg/dfp/builtin-snan-2.c
new file mode 100644
index 0000000..248481b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/builtin-snan-2.c
@@ -0,0 +1,44 @@
+/* Test __builtin_nansd* functions. Test requiring runtime exceptions
+ support. */
+/* { dg-do run } */
+/* { dg-require-effective-target fenv_exceptions_dfp } */
+/* { dg-options "" } */
+
+#include <fenv.h>
+
+volatile _Decimal32 d32 = __builtin_nansd32 ("");
+volatile _Decimal64 d64 = __builtin_nansd64 ("");
+volatile _Decimal128 d128 = __builtin_nansd128 ("");
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ feclearexcept (FE_ALL_EXCEPT);
+ d32 += d32;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d32 += d32;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d64 += d64;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d64 += d64;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d128 += d128;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d128 += d128;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c
new file mode 100644
index 0000000..58ee74d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c
@@ -0,0 +1,25 @@
+/* Test DEC_INFINITY defined in <float.h> with DFP support. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x" } */
+
+#include <float.h>
+
+#ifndef DEC_INFINITY
+# error "DEC_INFINITY not defined"
+#endif
+
+volatile _Decimal32 d = DEC_INFINITY;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (DEC_INFINITY, _Decimal32 : 0);
+ if (!(DEC_INFINITY > DEC32_MAX))
+ abort ();
+ if (!(d > DEC32_MAX))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c
new file mode 100644
index 0000000..8d09725
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c
@@ -0,0 +1,25 @@
+/* Test DEC_NAN defined in <float.h> with DFP support. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x" } */
+
+#include <float.h>
+
+#ifndef DEC_NAN
+# error "DEC_NAN not defined"
+#endif
+
+volatile _Decimal32 d = DEC_NAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (DEC_NAN, _Decimal32 : 0);
+ if (!__builtin_isnan (DEC_NAN))
+ abort ();
+ if (!__builtin_isnan (d))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c
new file mode 100644
index 0000000..4533c61
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c
@@ -0,0 +1,28 @@
+/* Test DEC_NAN macro. Runtime exceptions test, to verify NaN is
+ quiet not signaling. (This would only actually fail for a
+ signaling NaN in the hardware DFP case, because the software DFP
+ support in libgcc does not integrate with hardware exceptions.) */
+/* { dg-do run } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-options "-std=c2x" } */
+
+#include <fenv.h>
+#include <float.h>
+
+#ifndef DEC_NAN
+# error "DEC_NAN not defined"
+#endif
+
+volatile _Decimal32 d = DEC_NAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ d += d;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c
new file mode 100644
index 0000000..dec6b50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c
@@ -0,0 +1,45 @@
+/* Test DEC*_SNAN macros defined in <float.h> with DFP support. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x" } */
+
+#include <float.h>
+
+#ifndef DEC32_SNAN
+# error "DEC32_SNAN not defined"
+#endif
+
+#ifndef DEC64_SNAN
+# error "DEC64_SNAN not defined"
+#endif
+
+#ifndef DEC128_SNAN
+# error "DEC128_SNAN not defined"
+#endif
+
+volatile _Decimal32 d32 = DEC32_SNAN;
+volatile _Decimal64 d64 = DEC64_SNAN;
+volatile _Decimal128 d128 = DEC128_SNAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ (void) _Generic (DEC32_SNAN, _Decimal32 : 0);
+ if (!__builtin_isnan (DEC32_SNAN))
+ abort ();
+ if (!__builtin_isnan (d32))
+ abort ();
+ (void) _Generic (DEC64_SNAN, _Decimal64 : 0);
+ if (!__builtin_isnan (DEC64_SNAN))
+ abort ();
+ if (!__builtin_isnan (d64))
+ abort ();
+ (void) _Generic (DEC128_SNAN, _Decimal128 : 0);
+ if (!__builtin_isnan (DEC128_SNAN))
+ abort ();
+ if (!__builtin_isnan (d128))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c
new file mode 100644
index 0000000..4169602
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c
@@ -0,0 +1,45 @@
+/* Test DEC*_SNAN macros. Test requiring runtime exceptions
+ support. */
+/* { dg-do run } */
+/* { dg-require-effective-target fenv_exceptions_dfp } */
+/* { dg-options "-std=c2x" } */
+
+#include <fenv.h>
+#include <float.h>
+
+volatile _Decimal32 d32 = DEC32_SNAN;
+volatile _Decimal64 d64 = DEC64_SNAN;
+volatile _Decimal128 d128 = DEC128_SNAN;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ feclearexcept (FE_ALL_EXCEPT);
+ d32 += d32;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d32 += d32;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d64 += d64;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d64 += d64;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d128 += d128;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ feclearexcept (FE_ALL_EXCEPT);
+ d128 += d128;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/fold-isfinite-1.c b/gcc/testsuite/gcc.dg/fold-isfinite-1.c
new file mode 100644
index 0000000..2ea0192
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isfinite-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+ return __builtin_finite((double)x);
+}
+
+int foof(int x)
+{
+ return __builtin_finitef((float)x);
+}
+
+int fool(int x)
+{
+ return __builtin_finitel((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_finite" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u> " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isfinite-2.c b/gcc/testsuite/gcc.dg/fold-isfinite-2.c
new file mode 100644
index 0000000..ff70d8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isfinite-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(unsigned int x)
+{
+ return __builtin_finite((double)x);
+}
+
+int foof(unsigned int x)
+{
+ return __builtin_finitef((float)x);
+}
+
+int fool(unsigned int x)
+{
+ return __builtin_finitel((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_finite" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u> " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isinf-1.c b/gcc/testsuite/gcc.dg/fold-isinf-1.c
new file mode 100644
index 0000000..485816e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isinf-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+ return __builtin_isinf((double)x);
+}
+
+int foof(int x)
+{
+ return __builtin_isinff((float)x);
+}
+
+int fool(int x)
+{
+ return __builtin_isinfl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isinf" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u<= " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isinf-2.c b/gcc/testsuite/gcc.dg/fold-isinf-2.c
new file mode 100644
index 0000000..a236ca1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isinf-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(unsigned int x)
+{
+ return __builtin_isinf((double)x);
+}
+
+int foof(unsigned int x)
+{
+ return __builtin_isinff((float)x);
+}
+
+int fool(unsigned int x)
+{
+ return __builtin_isinfl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isinf" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u<= " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isnan-1.c b/gcc/testsuite/gcc.dg/fold-isnan-1.c
new file mode 100644
index 0000000..05ee930
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isnan-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+ return __builtin_isnan((double)x);
+}
+
+int foof(int x)
+{
+ return __builtin_isnanf((float)x);
+}
+
+int fool(int x)
+{
+ return __builtin_isnanl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isnan" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " unord " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isnan-2.c b/gcc/testsuite/gcc.dg/fold-isnan-2.c
new file mode 100644
index 0000000..32b8833
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isnan-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(unsigned int x)
+{
+ return __builtin_isnan((double)x);
+}
+
+int foof(unsigned int x)
+{
+ return __builtin_isnanf((float)x);
+}
+
+int fool(unsigned int x)
+{
+ return __builtin_isnanl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isnan" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " unord " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c b/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c
index d8c51ea..f46f155 100644
--- a/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c
+++ b/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c
@@ -9,13 +9,33 @@
#include "format.h"
void
-foo (int i, char *s, size_t n, va_list v0, va_list v1, va_list v2, va_list v3,
+foo (int i, char *s, size_t n, long l, llong ll, double d,
+ long double ld, va_list v0, va_list v1, va_list v2, va_list v3,
va_list v4, va_list v5, va_list v6, va_list v7)
{
fprintf (stdout, "%d", i);
fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */
printf ("%d", i);
printf ("%ld", i); /* { dg-warning "format" "printf" } */
+ /* These are accepted since MSVCR80, MSVCRT from Vista, UCRT,
+ * and mingw-w64 8.0 with C99/C++11. */
+ printf ("%lld", i); /* { dg-warning "format" "printf" } */
+ printf ("%lld", l); /* { dg-warning "format" "printf" } */
+ printf ("%lld", ll);
+ printf ("%llu", i); /* { dg-warning "format" "printf" } */
+ printf ("%llu", l); /* { dg-warning "format" "printf" } */
+ printf ("%llu", ll);
+ printf ("%llx", i); /* { dg-warning "format" "printf" } */
+ printf ("%llx", l); /* { dg-warning "format" "printf" } */
+ printf ("%llx", ll);
+ /* As MSABI uses an 8-byte `long double`, `%Lg` matches GCC's
+ * `double` instead of `long double` which takes 10 bytes. */
+ printf ("%Lg", d);
+ printf ("%Lg", ld); /* { dg-warning "format" "printf" } */
+ printf ("%Le", d);
+ printf ("%Le", ld); /* { dg-warning "format" "printf" } */
+ printf ("%Lf", d);
+ printf ("%Lf", ld); /* { dg-warning "format" "printf" } */
/* The "unlocked" functions shouldn't warn in c99 mode. */
fprintf_unlocked (stdout, "%ld", i);
printf_unlocked ("%ld", i);
diff --git a/gcc/testsuite/gcc.dg/free-1.c b/gcc/testsuite/gcc.dg/free-1.c
index 5496c84..ad49d78 100644
--- a/gcc/testsuite/gcc.dg/free-1.c
+++ b/gcc/testsuite/gcc.dg/free-1.c
@@ -13,14 +13,14 @@ void foo (void)
static char buf4[10], e;
char *q = buf;
free (p);
- free (q); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf2); /* { dg-warning "attempt to free a non-heap object" } */
- free (&c); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf3); /* { dg-warning "attempt to free a non-heap object" } */
- free (&d); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf4); /* { dg-warning "attempt to free a non-heap object" } */
- free (&e); /* { dg-warning "attempt to free a non-heap object" } */
+ free (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
free (&r->a);
- free ("abcd"); /* { dg-warning "attempt to free a non-heap object" } */
- free (L"abcd"); /* { dg-warning "attempt to free a non-heap object" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/free-2.c b/gcc/testsuite/gcc.dg/free-2.c
index eb94651..edbcdc7 100644
--- a/gcc/testsuite/gcc.dg/free-2.c
+++ b/gcc/testsuite/gcc.dg/free-2.c
@@ -13,14 +13,14 @@ void foo (void)
static char buf4[10], e;
char *q = buf;
free (p);
- free (q); /* At -O0 no warning is reported here. */
- free (buf2); /* { dg-warning "attempt to free a non-heap object" } */
- free (&c); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf3); /* { dg-warning "attempt to free a non-heap object" } */
- free (&d); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf4); /* { dg-warning "attempt to free a non-heap object" } */
- free (&e); /* { dg-warning "attempt to free a non-heap object" } */
+ free (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
free (&r->a);
- free ("abcd"); /* { dg-warning "attempt to free a non-heap object" } */
- free (L"abcd"); /* { dg-warning "attempt to free a non-heap object" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-error-8.c b/gcc/testsuite/gcc.dg/gimplefe-error-8.c
new file mode 100644
index 0000000..59e81eb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-error-8.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() f(int x, int y)
+{
+ int a;
+ a = (x < y) ? 1 : 2; /* { dg-error "expected" } */
+ return a;
+}
diff --git a/gcc/testsuite/gcc.dg/goacc/pr98183.c b/gcc/testsuite/gcc.dg/goacc/pr98183.c
new file mode 100644
index 0000000..b041011
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/goacc/pr98183.c
@@ -0,0 +1,15 @@
+/* PR middle-end/98183 */
+/* { dg-additional-options "-fexceptions -O0" } */
+
+void bar (void);
+int x, y;
+
+void
+foo (void)
+{
+#pragma acc data copyout(x)
+ {
+#pragma acc data copyout(y)
+ bar ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/goacc/tile-1.c b/gcc/testsuite/gcc.dg/goacc/tile-1.c
new file mode 100644
index 0000000..6898397
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/goacc/tile-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+/* PR c/97880 */
+
+void f ()
+{
+ #pragma acc parallel loop tile(2, 3)
+ for (int i = 0; i < 8; i++)
+ for (long j = 0; j < 8; j++);
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/barrier-2.c b/gcc/testsuite/gcc.dg/gomp/barrier-2.c
index 5a70919..c0d62f5 100644
--- a/gcc/testsuite/gcc.dg/gomp/barrier-2.c
+++ b/gcc/testsuite/gcc.dg/gomp/barrier-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-options "-Wall -std=c17 -fopenmp -pedantic-errors" } */
void f1(void)
{
@@ -16,6 +17,7 @@ void f1(void)
void f2(void)
{
label: /* { dg-error "label at end of compound statement" } */
+ /* { dg-warning "defined but not used" "" { target *-*-* } .-1 } */
#pragma omp barrier /* { dg-error "may only be used in compound statements" } */
}
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-simd-5.c b/gcc/testsuite/gcc.dg/gomp/declare-simd-5.c
index fe23652..b9a4161 100644
--- a/gcc/testsuite/gcc.dg/gomp/declare-simd-5.c
+++ b/gcc/testsuite/gcc.dg/gomp/declare-simd-5.c
@@ -1,5 +1,6 @@
/* Test parsing of #pragma omp declare simd */
/* { dg-do compile } */
+/* { dg-options "-std=c17 -fopenmp -pedantic-errors" } */
int
f1 (int x)
@@ -14,7 +15,7 @@ f1 (int x)
lab:
#pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
extern int f5 (int a, int *b, int c); /* { dg-error "must be followed by function declaration or definition" } */
- x++; /* { dg-error "expected expression before" "" { target *-*-* } .-1 } */
+ x++; /* { dg-error "a label can only be part of a statement and a declaration is not a statement" "" { target *-*-* } .-1 } */
}
return x;
}
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-variant-2.c b/gcc/testsuite/gcc.dg/gomp/declare-variant-2.c
index 701d83b..39c2c1d 100644
--- a/gcc/testsuite/gcc.dg/gomp/declare-variant-2.c
+++ b/gcc/testsuite/gcc.dg/gomp/declare-variant-2.c
@@ -1,5 +1,6 @@
/* Test parsing of #pragma omp declare variant */
/* { dg-do compile } */
+/* { dg-options "-std=c17 -fopenmp -pedantic-errors" } */
int f0 (int, int *, int);
@@ -16,7 +17,7 @@ f1 (int x)
lab:
#pragma omp declare variant (fn0) match (user={condition(0)})
extern int f5 (int a, int *b, int c); /* { dg-error "must be followed by function declaration or definition" } */
- x++; /* { dg-error "expected expression before" "" { target *-*-* } .-1 } */
+ x++; /* { dg-error "a label can only be part of a statement and a declaration is not a statement" "" { target *-*-* } .-1 } */
}
return x;
}
diff --git a/gcc/testsuite/gcc.dg/gomp/pr98183.c b/gcc/testsuite/gcc.dg/gomp/pr98183.c
new file mode 100644
index 0000000..dd11499
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/pr98183.c
@@ -0,0 +1,15 @@
+/* PR middle-end/98183 */
+/* { dg-additional-options "-fexceptions -O0" } */
+
+void bar (void);
+int x, y;
+
+void
+foo (void)
+{
+#pragma omp target data map(tofrom: x)
+ {
+#pragma omp target data map(tofrom: y)
+ bar ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/guality/guality.exp b/gcc/testsuite/gcc.dg/guality/guality.exp
index 89cd896..ba87132 100644
--- a/gcc/testsuite/gcc.dg/guality/guality.exp
+++ b/gcc/testsuite/gcc.dg/guality/guality.exp
@@ -38,7 +38,7 @@ global GDB
if ![info exists ::env(GUALITY_GDB_NAME)] {
if [info exists GDB] {
set guality_gdb_name "$GDB"
- } elseif [file exists $rootme/../gdb/gdb] {
+ } elseif { [info exists rootme] && [file exists $rootme/../gdb/gdb] } {
# If we're doing a combined build, and gdb is available, use it.
set guality_gdb_name "$rootme/../gdb/gdb"
} else {
diff --git a/gcc/testsuite/gcc.dg/guality/pr59776.c b/gcc/testsuite/gcc.dg/guality/pr59776.c
index 6c1c816..7c95a9f 100644
--- a/gcc/testsuite/gcc.dg/guality/pr59776.c
+++ b/gcc/testsuite/gcc.dg/guality/pr59776.c
@@ -6,7 +6,7 @@
struct S { float f, g; };
-__attribute__((noinline, noclone)) void
+__attribute__((noipa)) void
foo (struct S *p)
{
struct S s1, s2; /* { dg-final { gdb-test pr59776.c:17 "s1.f" "5.0" } } */
diff --git a/gcc/testsuite/gcc.dg/guality/pr98219-1.c b/gcc/testsuite/gcc.dg/guality/pr98219-1.c
new file mode 100644
index 0000000..c9cb8a5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr98219-1.c
@@ -0,0 +1,49 @@
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
+/* { dg-options "-g -muintr -mgeneral-regs-only" } */
+
+#include <x86gprintrin.h>
+
+extern void exit (int);
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
+#define UIRRV 0x12345670
+#define RIP 0x12345671
+#define RFLAGS 0x12345672
+#define RSP 0x12345673
+
+#define STRING(x) XSTRING(x)
+#define XSTRING(x) #x
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) XSTRING (prefix) cname
+
+void
+__attribute__((interrupt, used))
+fn (struct __uintr_frame *frame, uword_t uirrv)
+{
+ if (UIRRV != uirrv) /* BREAK */
+ __builtin_abort ();
+ if (RIP != frame->rip)
+ __builtin_abort ();
+ if (RFLAGS != frame->rflags)
+ __builtin_abort ();
+ if (RSP != frame->rsp)
+ __builtin_abort ();
+
+ exit (0);
+}
+
+int
+main ()
+{
+ asm ("push $" STRING (RSP) "; \
+ push $" STRING (RFLAGS) "; \
+ push $" STRING (RIP) "; \
+ push $" STRING (UIRRV) "; \
+ jmp " ASMNAME ("fn"));
+ return 0;
+}
+
+/* { dg-final { gdb-test 22 "uirrv" "0x12345670" } } */
+/* { dg-final { gdb-test 22 "frame->rip" "0x12345671" } } */
+/* { dg-final { gdb-test 22 "frame->rflags" "0x12345672" } } */
+/* { dg-final { gdb-test 22 "frame->rsp" "0x12345673" } } */
diff --git a/gcc/testsuite/gcc.dg/guality/pr98219-2.c b/gcc/testsuite/gcc.dg/guality/pr98219-2.c
new file mode 100644
index 0000000..1f74eb3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr98219-2.c
@@ -0,0 +1,63 @@
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
+/* { dg-options "-g -muintr -mgeneral-regs-only" } */
+
+#include <x86gprintrin.h>
+
+extern void exit (int);
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+typedef int aligned __attribute__((aligned(64)));
+
+#define UIRRV 0x12345670
+#define RIP 0x12345671
+#define RFLAGS 0x12345672
+#define RSP 0x12345673
+
+#define STRING(x) XSTRING(x)
+#define XSTRING(x) #x
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) XSTRING (prefix) cname
+
+int
+check_int (int *i, int align)
+{
+ *i = 20;
+ if ((((ptrdiff_t) i) & (align - 1)) != 0)
+ __builtin_abort ();
+ return *i;
+}
+
+void
+__attribute__((interrupt, used))
+fn (struct __uintr_frame *frame, uword_t uirrv)
+{
+ aligned i;
+ if (check_int (&i, __alignof__(i)) != i)
+ __builtin_abort ();
+
+ if (UIRRV != uirrv) /* BREAK */
+ __builtin_abort ();
+ if (RIP != frame->rip)
+ __builtin_abort ();
+ if (RFLAGS != frame->rflags)
+ __builtin_abort ();
+ if (RSP != frame->rsp)
+ __builtin_abort ();
+
+ exit (0);
+}
+
+int
+main ()
+{
+ asm ("push $" STRING (RSP) "; \
+ push $" STRING (RFLAGS) "; \
+ push $" STRING (RIP) "; \
+ push $" STRING (UIRRV) "; \
+ jmp " ASMNAME ("fn"));
+ return 0;
+}
+
+/* { dg-final { gdb-test 34 "uirrv" "0x12345670" } } */
+/* { dg-final { gdb-test 34 "frame->rip" "0x12345671" } } */
+/* { dg-final { gdb-test 34 "frame->rflags" "0x12345672" } } */
+/* { dg-final { gdb-test 34 "frame->rsp" "0x12345673" } } */
diff --git a/gcc/testsuite/gcc.dg/hwasan/hwasan.exp b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp
new file mode 100644
index 0000000..5c040ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp
@@ -0,0 +1,36 @@
+# Copyright (C) 2012-2019 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+load_lib hwasan-dg.exp
+
+# Initialize `dg'.
+dg-init
+hwasan_init
+
+# Main loop.
+if [check_effective_target_fsanitize_hwaddress] {
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/hwasan/*.c]] "" ""
+}
+
+# All done.
+hwasan_finish
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c
new file mode 100644
index 0000000..0afcc10
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+
+/*
+ Tests of nested funtions are:
+ 0) Accessing closed over variables works.
+ 1) Accesses outside of variables is caught.
+ 2) Accessing variable out of scope is caught.
+
+ Here we test that accessing closed over variables works.
+ */
+
+/* We need a second layer of indirection so that GCC doesn't notice we're
+ returning the address of a local variable and put 0 in it's place. */
+__attribute__((noinline))
+int *Ident(void *x) {
+ return x;
+}
+
+int __attribute__ ((noinline))
+intermediate (void (*f) (int, char),
+ char num)
+{
+ if (num == 1)
+ /* NOTE: We need to overrun by an amount greater than the "extra data" in a
+ nonlocal goto structure. The entire structure is allocated on the stack
+ with a single tag, which means hwasan can't tell if a closed-over buffer
+ was overrun by an amount small enough that the access was still to some
+ data in that nonlocal goto structure. */
+ f (100, 100);
+ else
+ f (3, 100);
+ /* Just return something ... */
+ return num % 3;
+}
+
+int* __attribute__ ((noinline))
+nested_function (char num)
+{
+ int big_array[16];
+ int other_array[16];
+ void store (int index, char value)
+ { big_array[index] = value; }
+ return Ident(&other_array[intermediate (store, num)]);
+}
+
+#ifndef MAIN
+int main ()
+{
+ nested_function (0);
+ return 0;
+}
+#endif
diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c
new file mode 100644
index 0000000..0161281
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+/*
+ Tests of nested funtions are:
+ 0) Accessing closed over variables works.
+ 1) Accesses outside of variables is caught.
+ 2) Accessing variable out of scope is caught.
+
+ Here we test option 1.
+ */
+
+#define MAIN 0
+#include "nested-functions-0.c"
+#undef MAIN
+
+int main ()
+{
+ nested_function (1);
+ return 0;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c
new file mode 100644
index 0000000..b1a033f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+
+/*
+ Tests of nested funtions are:
+ 0) Accessing closed over variables works.
+ 1) Accesses outside of variables is caught.
+ 2) Accessing variable out of scope is caught.
+
+ Here we test option 2.
+ */
+
+#define MAIN 0
+#include "nested-functions-0.c"
+#undef MAIN
+
+int main ()
+{
+ int *retval = nested_function (2);
+ *retval = 100;
+ return 0;
+}
+
+/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */
+/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */
+/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */
+/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */
diff --git a/gcc/testsuite/gcc.dg/ipa/modref-2.c b/gcc/testsuite/gcc.dg/ipa/modref-2.c
new file mode 100644
index 0000000..51ac658
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/modref-2.c
@@ -0,0 +1,16 @@
+/* { dg-options "-O2 -fdump-ipa-modref" } */
+/* { dg-do compile } */
+void
+test (int *a, int size)
+{
+ __builtin_memset (a, 0, 321);
+}
+void
+test2 (double x, double *y)
+{
+ __builtin_modf (x,y);
+}
+/* 321*8 */
+/* { dg-final { scan-ipa-dump "Parm 0 param offset:0 offset:0 size:-1 max_size:2568" "modref" } } */
+/* { dg-final { scan-ipa-dump "Parm 1 param offset:0 offset:0 size:-1 max_size:64" "modref" { target lp64 } } } */
+/* { dg-final { scan-ipa-dump "Parm 1 param offset:0 offset:0 size:-1 max_size:32" "modref" { target ilp32 } } } */
diff --git a/gcc/testsuite/gcc.dg/label-compound-stmt-1.c b/gcc/testsuite/gcc.dg/label-compound-stmt-1.c
index 2f8fa4e..2ae2b82 100644
--- a/gcc/testsuite/gcc.dg/label-compound-stmt-1.c
+++ b/gcc/testsuite/gcc.dg/label-compound-stmt-1.c
@@ -1,7 +1,7 @@
/* Test that labels at ends of compound statements are hard errors. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-std=c17 -pedantic-errors" } */
void f(void) { g: } /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "label|parse|syntax" "label at end of compound statement" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/loop-8.c b/gcc/testsuite/gcc.dg/loop-8.c
index af317d8..90ea1c4 100644
--- a/gcc/testsuite/gcc.dg/loop-8.c
+++ b/gcc/testsuite/gcc.dg/loop-8.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-rtl-loop2_invariant" } */
-/* { dg-skip-if "unexpected IV" { "hppa*-*-* mips*-*-* visium-*-* powerpc*-*-* riscv*-*-* mmix-*-*" } } */
+/* { dg-skip-if "unexpected IV" { "hppa*-*-* mips*-*-* visium-*-* powerpc*-*-* riscv*-*-* mmix-*-* vax-*-*" } } */
/* Load immediate on condition is available from z13 on and prevents moving
the load out of the loop, so always run this test with -march=zEC12 that
does not have load immediate on condition. */
diff --git a/gcc/testsuite/gcc.dg/lto/modref-2_0.c b/gcc/testsuite/gcc.dg/lto/modref-2_0.c
new file mode 100644
index 0000000..cf84ed9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/modref-2_0.c
@@ -0,0 +1,27 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options {"-O2 -flto-partition=max -flto -fno-ipa-sra"} } */
+__attribute__ ((noinline))
+void
+test (char *a)
+{
+ __builtin_memset (a,0,321);
+}
+__attribute__ ((noinline))
+void
+test2 (double *x, double *y)
+{
+ __builtin_modf (*x,y);
+}
+int
+main (void)
+{
+ char array[321];
+ double x=1, y=2;
+ char arrayz[321];
+ arrayz[0]=1;
+ test (array);
+ test2 (&x,&y);
+ if (!__builtin_constant_p (x==2) || !__builtin_constant_p (arrayz[0]==1))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/modref-3_0.c b/gcc/testsuite/gcc.dg/lto/modref-3_0.c
new file mode 100644
index 0000000..bd8f96f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/modref-3_0.c
@@ -0,0 +1,17 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { {-O2 -flto-partition=max -fdump-ipa-modref -fno-ipa-sra -fno-ipa-cp -flto} } } */
+extern void copy (int *a, int *b);
+extern void barrier ();
+extern int *ptr;
+int
+main()
+{
+ int a = 1, b = 2;
+ copy (&a,&b);
+ barrier ();
+ *ptr = 1;
+ if (!__builtin_constant_p (b == 2))
+ __builtin_abort ();
+ return 0;
+}
+/* { dg-final { scan-wpa-ipa-dump "parm 1 flags: nodirectescape" "modref" } } */
diff --git a/gcc/testsuite/gcc.dg/lto/modref-3_1.c b/gcc/testsuite/gcc.dg/lto/modref-3_1.c
new file mode 100644
index 0000000..c36f3d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/modref-3_1.c
@@ -0,0 +1,13 @@
+__attribute__ ((noinline))
+void
+copy (int *a, int *b)
+{
+ *a=*b;
+}
+int p, *ptr = &p;
+__attribute__ ((noinline))
+void
+barrier ()
+{
+ asm ("":"=r"(ptr):"0"(ptr));
+}
diff --git a/gcc/testsuite/gcc.dg/lto/modref-4_0.c b/gcc/testsuite/gcc.dg/lto/modref-4_0.c
new file mode 100644
index 0000000..db90b4f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/modref-4_0.c
@@ -0,0 +1,17 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { {-O2 -flto-partition=max -fdump-ipa-modref -fno-ipa-sra -flto} } } */
+extern void copy (int *a, int *b);
+extern void barrier ();
+extern int *ptr;
+int
+main()
+{
+ int a = 1, b = 2;
+ copy (&a,&b);
+ barrier ();
+ *ptr = 1;
+ if (!__builtin_constant_p (b == 2))
+ __builtin_abort ();
+ return 0;
+}
+/* { dg-final { scan-wpa-ipa-dump "parm 1 flags: nodirectescape" "modref" } } */
diff --git a/gcc/testsuite/gcc.dg/lto/modref-4_1.c b/gcc/testsuite/gcc.dg/lto/modref-4_1.c
new file mode 100644
index 0000000..c36f3d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/modref-4_1.c
@@ -0,0 +1,13 @@
+__attribute__ ((noinline))
+void
+copy (int *a, int *b)
+{
+ *a=*b;
+}
+int p, *ptr = &p;
+__attribute__ ((noinline))
+void
+barrier ()
+{
+ asm ("":"=r"(ptr):"0"(ptr));
+}
diff --git a/gcc/testsuite/gcc.dg/lvalue-11.c b/gcc/testsuite/gcc.dg/lvalue-11.c
new file mode 100644
index 0000000..d8b5a60c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lvalue-11.c
@@ -0,0 +1,40 @@
+/* test that lvalue conversions drops qualifiers, Bug 97702 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+
+const int jc;
+extern int j;
+extern typeof(0,jc) j;
+extern typeof(+jc) j;
+extern typeof(-jc) j;
+extern typeof(1?jc:0) j;
+extern typeof((int)jc) j;
+extern typeof((const int)jc) j;
+
+volatile int kv;
+extern int k;
+extern typeof(0,kv) k;
+extern typeof(+kv) k;
+extern typeof(-kv) k;
+extern typeof(1?kv:0) k;
+extern typeof((int)kv) k;
+extern typeof((volatile int)kv) k;
+
+_Atomic int la;
+extern int l;
+extern typeof(0,la) l;
+extern typeof(+la) l;
+extern typeof(-la) l;
+extern typeof(1?la:0) l;
+extern typeof((int)la) l;
+extern typeof((_Atomic int)la) l;
+
+int * restrict mr;
+extern int *m;
+extern typeof(0,mr) m;
+extern typeof(1?mr:0) m;
+extern typeof((int *)mr) m;
+extern typeof((int * restrict)mr) m;
+
+
diff --git a/gcc/testsuite/gcc.dg/memchr-3.c b/gcc/testsuite/gcc.dg/memchr-3.c
new file mode 100644
index 0000000..c38d9cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memchr-3.c
@@ -0,0 +1,25 @@
+/* PR middle-end/97956 - ICE due to type mismatch in pointer_plus_expr
+ during memchr folding
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT32_TYPE__ int32_t;
+
+extern void* memchr (const void*, int, long);
+
+struct SX
+{
+ int32_t n;
+ int8_t a[];
+};
+
+const struct SX sx = { 0x1221 };
+const char sx_rep[] = { };
+
+void test_find (void)
+{
+ int n = 0, nb = (const char*)&sx.a - (const char*)&sx;
+ const char *p = (const char*)&sx, *q = sx_rep;
+ n += p + 1 == memchr (p, q[1], nb);
+}
diff --git a/gcc/testsuite/gcc.dg/nextafter-1.c b/gcc/testsuite/gcc.dg/nextafter-1.c
index 1916ac2..646a741 100644
--- a/gcc/testsuite/gcc.dg/nextafter-1.c
+++ b/gcc/testsuite/gcc.dg/nextafter-1.c
@@ -6,12 +6,14 @@
/* { dg-final { scan-tree-dump-not "nextafter" "optimized" } } */
/* { dg-final { scan-tree-dump-not "nexttoward" "optimized" } } */
+#ifndef _NEXT_AFTER_2
float nextafterf (float, float);
double nextafter (double, double);
long double nextafterl (long double, long double);
float nexttowardf (float, long double);
double nexttoward (double, long double);
long double nexttowardl (long double, long double);
+#endif
#define CHECK(x) if (!(x)) __builtin_abort ()
diff --git a/gcc/testsuite/gcc.dg/nextafter-2.c b/gcc/testsuite/gcc.dg/nextafter-2.c
index e51ae94..b36bc8b 100644
--- a/gcc/testsuite/gcc.dg/nextafter-2.c
+++ b/gcc/testsuite/gcc.dg/nextafter-2.c
@@ -6,6 +6,18 @@
#include <stdlib.h>
+/* In order to run on systems like the PowerPC that have 3 different long
+ double types, include math.h so it can choose what is the appropriate
+ nextafterl function to use.
+
+ If we didn't use -fno-builtin for this test, the PowerPC compiler would have
+ changed the names of the built-in functions that use long double. The
+ nextafter-1.c function runs with this mapping.
+
+ Since this test uses -fno-builtin, include math.h, so that math.h can make
+ the appropriate choice to use. */
+#include <math.h>
+
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if !__GLIBC_PREREQ (2, 24)
/* Workaround buggy nextafterl in glibc 2.23 and earlier,
@@ -13,4 +25,7 @@
# define NO_LONG_DOUBLE 1
# endif
#endif
+
+#define _NEXT_AFTER_2
+
#include "nextafter-1.c"
diff --git a/gcc/testsuite/gcc.dg/no-strict-overflow-4.c b/gcc/testsuite/gcc.dg/no-strict-overflow-4.c
index b6d3da3..90145ff9 100644
--- a/gcc/testsuite/gcc.dg/no-strict-overflow-4.c
+++ b/gcc/testsuite/gcc.dg/no-strict-overflow-4.c
@@ -4,7 +4,8 @@
/* Source: Ian Lance Taylor. Dual of strict-overflow-4.c. */
/* We can only simplify the conditional when using strict overflow
- semantics. */
+ semantics or when using wrap overflow semantics. -fno-strict-overflow is
+ equivalent to -fwrapv. */
int
foo (int i)
@@ -12,4 +13,4 @@ foo (int i)
return i + 1 > i;
}
-/* { dg-final { scan-tree-dump "\[^ \]*_.(\\\(D\\\))? (>|<) \[^ \]*_." "optimized" } } */
+/* { dg-final { scan-tree-dump "\[^ \]*_.(\\\(D\\\))? != \[0-9]+" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/noncompile/pr79758.c b/gcc/testsuite/gcc.dg/noncompile/pr79758.c
index aeaf7c7..a312160 100644
--- a/gcc/testsuite/gcc.dg/noncompile/pr79758.c
+++ b/gcc/testsuite/gcc.dg/noncompile/pr79758.c
@@ -1,6 +1,6 @@
/* PR c/79758 */
/* { dg-do compile } */
-void fn1 (int[a]) { }; /* { dg-error "undeclared here|parameter name omitted" } */
+void fn1 (int[a]) { }; /* { dg-error "undeclared here" } */
void fn1 (b) { }; /* { dg-error "redefinition" } */
/* { dg-warning "defaults to 'int'" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/parse-decl-after-label.c b/gcc/testsuite/gcc.dg/parse-decl-after-label.c
index 9c9886a..6e2a047e 100644
--- a/gcc/testsuite/gcc.dg/parse-decl-after-label.c
+++ b/gcc/testsuite/gcc.dg/parse-decl-after-label.c
@@ -1,6 +1,6 @@
/* PR 29062
{ dg-do compile }
-{ dg-options "-fsyntax-only" }
+{ dg-options "-std=c17 -pedantic-errors -fsyntax-only" }
*/
int f(int x)
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c
new file mode 100644
index 0000000..05133d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c
@@ -0,0 +1,436 @@
+/* Proof-of-concept of a -fanalyzer plugin.
+ Detect (some) uses of CPython API outside of the Global Interpreter Lock.
+ https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock
+*/
+/* { dg-options "-g" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic.h"
+#include "tree.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "diagnostic-event-id.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/analyzer-logging.h"
+#include "json.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
+
+int plugin_is_GPL_compatible;
+
+#if ENABLE_ANALYZER
+
+namespace ana {
+
+static bool
+type_based_on_pyobject_p (tree type)
+{
+ /* Ideally we'd also check for "subclasses" here by iterating up the
+ first field of each struct. */
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return false;
+ tree name = TYPE_IDENTIFIER (type);
+ if (!name)
+ return false;
+ return id_equal (name, "PyObject");
+}
+
+/* An experimental state machine, for tracking whether the GIL is held,
+ as global state.. */
+
+class gil_state_machine : public state_machine
+{
+public:
+ gil_state_machine (logger *logger);
+
+ bool inherited_state_p () const FINAL OVERRIDE { return false; }
+
+ bool on_stmt (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt) const FINAL OVERRIDE;
+
+ void on_condition (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt,
+ tree lhs,
+ enum tree_code op,
+ tree rhs) const FINAL OVERRIDE;
+
+ bool can_purge_p (state_t s) const FINAL OVERRIDE;
+
+ void check_for_pyobject_usage_without_gil (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt,
+ tree op) const;
+
+ private:
+ void check_for_pyobject_in_call (sm_context *sm_ctxt,
+ const supernode *node,
+ const gcall *call,
+ tree callee_fndecl) const;
+
+ public:
+ /* These states are "global", rather than per-expression. */
+
+ /* State for when we've released the GIL. */
+ state_t m_released_gil;
+
+ /* Stop state. */
+ state_t m_stop;
+};
+
+/* Subclass for diagnostics involving the GIL. */
+
+class gil_diagnostic : public pending_diagnostic
+{
+public:
+ location_t fixup_location (location_t loc) const FINAL OVERRIDE
+ {
+ /* Ideally we'd check for specific macros here, and only
+ resolve certain macros. */
+ if (linemap_location_from_macro_expansion_p (line_table, loc))
+ loc = linemap_resolve_location (line_table, loc,
+ LRK_MACRO_EXPANSION_POINT, NULL);
+ return loc;
+ }
+
+ label_text describe_state_change (const evdesc::state_change &change)
+ FINAL OVERRIDE
+ {
+ if (change.is_global_p ()
+ && change.m_new_state == m_sm.m_released_gil)
+ return change.formatted_print ("releasing the GIL here");
+ if (change.is_global_p ()
+ && change.m_new_state == m_sm.get_start_state ())
+ return change.formatted_print ("acquiring the GIL here");
+ return label_text ();
+ }
+
+ protected:
+ gil_diagnostic (const gil_state_machine &sm) : m_sm (sm)
+ {
+ }
+
+ private:
+ const gil_state_machine &m_sm;
+};
+
+class double_save_thread : public gil_diagnostic
+{
+ public:
+ double_save_thread (const gil_state_machine &sm, const gcall *call)
+ : gil_diagnostic (sm), m_call (call)
+ {}
+
+ const char *get_kind () const FINAL OVERRIDE
+ {
+ return "double_save_thread";
+ }
+
+ bool subclass_equal_p (const pending_diagnostic &base_other) const OVERRIDE
+ {
+ const double_save_thread &sub_other
+ = (const double_save_thread &)base_other;
+ return m_call == sub_other.m_call;
+ }
+
+ bool emit (rich_location *rich_loc) FINAL OVERRIDE
+ {
+ return warning_at (rich_loc, 0,
+ "nested usage of %qs", "Py_BEGIN_ALLOW_THREADS");
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
+ {
+ return ev.formatted_print ("nested usage of %qs here",
+ "Py_BEGIN_ALLOW_THREADS");
+ }
+
+ private:
+ const gcall *m_call;
+};
+
+class fncall_without_gil : public gil_diagnostic
+{
+ public:
+ fncall_without_gil (const gil_state_machine &sm, const gcall *call,
+ tree callee_fndecl, unsigned arg_idx)
+ : gil_diagnostic (sm), m_call (call), m_callee_fndecl (callee_fndecl),
+ m_arg_idx (arg_idx)
+ {}
+
+ const char *get_kind () const FINAL OVERRIDE
+ {
+ return "fncall_without_gil";
+ }
+
+ bool subclass_equal_p (const pending_diagnostic &base_other) const OVERRIDE
+ {
+ const fncall_without_gil &sub_other
+ = (const fncall_without_gil &)base_other;
+ return (m_call == sub_other.m_call
+ && m_callee_fndecl == sub_other.m_callee_fndecl
+ && m_arg_idx == sub_other.m_arg_idx);
+ }
+
+ bool emit (rich_location *rich_loc) FINAL OVERRIDE
+ {
+ auto_diagnostic_group d;
+ /* There isn't a warning ID for use to use. */
+ if (m_callee_fndecl)
+ return warning_at (rich_loc, 0,
+ "use of PyObject as argument %i of %qE"
+ " without the GIL",
+ m_arg_idx + 1, m_callee_fndecl);
+ else
+ return warning_at (rich_loc, 0,
+ "use of PyObject as argument %i of call"
+ " without the GIL",
+ m_arg_idx + 1, m_callee_fndecl);
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
+ {
+ if (m_callee_fndecl)
+ return ev.formatted_print ("use of PyObject as argument %i of %qE here"
+ " without the GIL",
+ m_arg_idx + 1, m_callee_fndecl);
+ else
+ return ev.formatted_print ("use of PyObject as argument %i of call here"
+ " without the GIL",
+ m_arg_idx + 1, m_callee_fndecl);
+ }
+
+ private:
+ const gcall *m_call;
+ tree m_callee_fndecl;
+ unsigned m_arg_idx;
+};
+
+class pyobject_usage_without_gil : public gil_diagnostic
+{
+ public:
+ pyobject_usage_without_gil (const gil_state_machine &sm, tree expr)
+ : gil_diagnostic (sm), m_expr (expr)
+ {}
+
+ const char *get_kind () const FINAL OVERRIDE
+ {
+ return "pyobject_usage_without_gil";
+ }
+
+ bool subclass_equal_p (const pending_diagnostic &base_other) const OVERRIDE
+ {
+ return same_tree_p (m_expr,
+ ((const pyobject_usage_without_gil&)base_other).m_expr);
+ }
+
+ bool emit (rich_location *rich_loc) FINAL OVERRIDE
+ {
+ auto_diagnostic_group d;
+ /* There isn't a warning ID for use to use. */
+ return warning_at (rich_loc, 0,
+ "use of PyObject %qE without the GIL", m_expr);
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
+ {
+ return ev.formatted_print ("PyObject %qE used here without the GIL",
+ m_expr);
+ }
+
+ private:
+ tree m_expr;
+};
+
+/* gil_state_machine's ctor. */
+
+gil_state_machine::gil_state_machine (logger *logger)
+: state_machine ("gil", logger)
+{
+ m_released_gil = add_state ("released_gil");
+ m_stop = add_state ("stop");
+}
+
+struct cb_data
+{
+ cb_data (const gil_state_machine &sm, sm_context *sm_ctxt,
+ const supernode *snode, const gimple *stmt)
+ : m_sm (sm), m_sm_ctxt (sm_ctxt), m_snode (snode), m_stmt (stmt)
+ {
+ }
+
+ const gil_state_machine &m_sm;
+ sm_context *m_sm_ctxt;
+ const supernode *m_snode;
+ const gimple *m_stmt;
+};
+
+static bool
+check_for_pyobject (gimple *, tree op, tree, void *data)
+{
+ cb_data *d = (cb_data *)data;
+ d->m_sm.check_for_pyobject_usage_without_gil (d->m_sm_ctxt, d->m_snode,
+ d->m_stmt, op);
+ return true;
+}
+
+/* Assuming that the GIL has been released, complain about any
+ PyObject * arguments passed to CALL. */
+
+void
+gil_state_machine::check_for_pyobject_in_call (sm_context *sm_ctxt,
+ const supernode *node,
+ const gcall *call,
+ tree callee_fndecl) const
+{
+ for (unsigned i = 0; i < gimple_call_num_args (call); i++)
+ {
+ tree arg = gimple_call_arg (call, i);
+ if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
+ continue;
+ tree type = TREE_TYPE (TREE_TYPE (arg));
+ if (type_based_on_pyobject_p (type))
+ {
+ sm_ctxt->warn (node, call, NULL_TREE,
+ new fncall_without_gil (*this, call,
+ callee_fndecl,
+ i));
+ sm_ctxt->set_global_state (m_stop);
+ }
+ }
+}
+
+/* Implementation of state_machine::on_stmt vfunc for gil_state_machine. */
+
+bool
+gil_state_machine::on_stmt (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt) const
+{
+ const state_t global_state = sm_ctxt->get_global_state ();
+ if (const gcall *call = dyn_cast <const gcall *> (stmt))
+ {
+ if (tree callee_fndecl = sm_ctxt->get_fndecl_for_call (call))
+ {
+ if (is_named_call_p (callee_fndecl, "PyEval_SaveThread", call, 0))
+ {
+ if (0)
+ inform (input_location, "found call to %qs",
+ "PyEval_SaveThread");
+ if (global_state == m_released_gil)
+ {
+ sm_ctxt->warn (node, stmt, NULL_TREE,
+ new double_save_thread (*this, call));
+ sm_ctxt->set_global_state (m_stop);
+ }
+ else
+ sm_ctxt->set_global_state (m_released_gil);
+ return true;
+ }
+ else if (is_named_call_p (callee_fndecl, "PyEval_RestoreThread",
+ call, 1))
+ {
+ if (0)
+ inform (input_location, "found call to %qs",
+ "PyEval_SaveThread");
+ if (global_state == m_released_gil)
+ sm_ctxt->set_global_state (m_start);
+ return true;
+ }
+ else if (global_state == m_released_gil)
+ {
+ /* Find PyObject * args of calls to fns with unknown bodies. */
+ if (!fndecl_has_gimple_body_p (callee_fndecl))
+ check_for_pyobject_in_call (sm_ctxt, node, call, callee_fndecl);
+ }
+ }
+ else if (global_state == m_released_gil)
+ check_for_pyobject_in_call (sm_ctxt, node, call, NULL);
+ }
+ else
+ if (global_state == m_released_gil)
+ {
+ /* Walk the stmt, finding uses of PyObject (or "subclasses"). */
+ cb_data d (*this, sm_ctxt, node, stmt);
+ walk_stmt_load_store_addr_ops (const_cast <gimple *> (stmt), &d,
+ check_for_pyobject,
+ check_for_pyobject,
+ check_for_pyobject);
+ }
+ return false;
+}
+
+/* Implementation of state_machine::on_condition vfunc for
+ gil_state_machine. */
+
+void
+gil_state_machine::on_condition (sm_context *sm_ctxt ATTRIBUTE_UNUSED,
+ const supernode *node ATTRIBUTE_UNUSED,
+ const gimple *stmt ATTRIBUTE_UNUSED,
+ tree lhs ATTRIBUTE_UNUSED,
+ enum tree_code op ATTRIBUTE_UNUSED,
+ tree rhs ATTRIBUTE_UNUSED) const
+{
+ // Empty
+}
+
+bool
+gil_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
+{
+ return true;
+}
+
+void
+gil_state_machine::check_for_pyobject_usage_without_gil (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt,
+ tree op) const
+{
+ tree type = TREE_TYPE (op);
+ if (type_based_on_pyobject_p (type))
+ {
+ sm_ctxt->warn (node, stmt, NULL_TREE,
+ new pyobject_usage_without_gil (*this, op));
+ sm_ctxt->set_global_state (m_stop);
+ }
+}
+
+/* Callback handler for the PLUGIN_ANALYZER_INIT event. */
+
+static void
+gil_analyzer_init_cb (void *gcc_data, void */*user_data*/)
+{
+ ana::plugin_analyzer_init_iface *iface
+ = (ana::plugin_analyzer_init_iface *)gcc_data;
+ LOG_SCOPE (iface->get_logger ());
+ if (0)
+ inform (input_location, "got here: gil_analyzer_init_cb");
+ iface->register_state_machine (new gil_state_machine (iface->get_logger ()));
+}
+
+} // namespace ana
+
+#endif /* #if ENABLE_ANALYZER */
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+#if ENABLE_ANALYZER
+ const char *plugin_name = plugin_info->base_name;
+ if (0)
+ inform (input_location, "got here; %qs", plugin_name);
+ register_callback (plugin_info->base_name,
+ PLUGIN_ANALYZER_INIT,
+ ana::gil_analyzer_init_cb,
+ NULL); /* void *user_data */
+#else
+ sorry_no_analyzer ();
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/gil-1.c b/gcc/testsuite/gcc.dg/plugin/gil-1.c
new file mode 100644
index 0000000..4e8f535
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/gil-1.c
@@ -0,0 +1,90 @@
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+
+#include "gil.h"
+
+void test_1 (void)
+{
+ Py_BEGIN_ALLOW_THREADS
+ Py_END_ALLOW_THREADS
+}
+
+void test_2 (PyObject *obj)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */
+
+ Py_INCREF (obj); /* { dg-warning "use of PyObject '\\*\\(obj\\)' without the GIL" } */
+ Py_DECREF (obj);
+
+ Py_END_ALLOW_THREADS
+}
+
+void test_3 (PyObject *obj)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */
+
+ Py_BEGIN_ALLOW_THREADS /* { dg-warning "nested usage of 'Py_BEGIN_ALLOW_THREADS'" } */
+ Py_END_ALLOW_THREADS
+
+ Py_END_ALLOW_THREADS
+}
+
+void test_4 (PyObject *obj)
+{
+ /* These aren't nested, so should be OK. */
+ Py_BEGIN_ALLOW_THREADS
+ Py_END_ALLOW_THREADS
+
+ Py_BEGIN_ALLOW_THREADS
+ Py_END_ALLOW_THREADS
+}
+
+/* Interprocedural example of erroneously nested usage. */
+
+static void __attribute__((noinline))
+called_by_test_5 (void)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-warning "nested usage of 'Py_BEGIN_ALLOW_THREADS'" } */
+ Py_END_ALLOW_THREADS
+}
+
+void test_5 (PyObject *obj)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */
+ called_by_test_5 ();
+ Py_END_ALLOW_THREADS
+}
+
+/* Interprocedural example of bogusly using a PyObject outside of GIL. */
+
+static void __attribute__((noinline))
+called_by_test_6 (PyObject *obj)
+{
+ Py_INCREF (obj); /* { dg-warning "use of PyObject '\\*\\(obj\\)' without the GIL" } */
+ Py_DECREF (obj);
+}
+
+void test_6 (PyObject *obj)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */
+ called_by_test_6 (obj);
+ Py_END_ALLOW_THREADS
+}
+
+extern void called_by_test_7 (PyObject *obj);
+
+void test_7 (PyObject *obj)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */
+ called_by_test_7 (obj); /* { dg-warning "use of PyObject as argument 1 of 'called_by_test_7' without the GIL" } */
+ Py_END_ALLOW_THREADS
+}
+
+typedef void (*callback_t) (PyObject *);
+
+void test_8 (PyObject *obj, callback_t cb)
+{
+ Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */
+ cb (obj); /* { dg-warning "use of PyObject as argument 1 of call without the GIL" } */
+ Py_END_ALLOW_THREADS
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/gil.h b/gcc/testsuite/gcc.dg/plugin/gil.h
new file mode 100644
index 0000000..b0610cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/gil.h
@@ -0,0 +1,32 @@
+/* Adapted from CPython 3.8's ceval.h. */
+typedef struct PyThreadState PyThreadState;
+extern PyThreadState * PyEval_SaveThread(void);
+extern void PyEval_RestoreThread(PyThreadState *);
+
+#define Py_BEGIN_ALLOW_THREADS { \
+ PyThreadState *_save; \
+ _save = PyEval_SaveThread();
+#define Py_BLOCK_THREADS PyEval_RestoreThread(_save);
+#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread();
+#define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \
+ }
+
+/* Adapted/hacked up from CPython 3.8's object.h. */
+
+typedef struct _object {
+ int ob_refcnt;
+} PyObject;
+
+#define _PyObject_CAST(op) ((PyObject*)(op))
+
+extern void _Py_Dealloc(PyObject *);
+
+#define _Py_INCREF(OP) do { (OP)->ob_refcnt++; } while (0);
+#define _Py_DECREF(OP) do { \
+ if (--(OP)->ob_refcnt == 0) { \
+ _Py_Dealloc(OP); \
+ } \
+ } while (0)
+
+#define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op))
+#define Py_DECREF(op) _Py_DECREF(_PyObject_CAST(op))
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 5dd102a..7f0ffd6 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -118,6 +118,8 @@ set plugin_test_list [list \
{ dump_plugin.c \
dump-1.c \
dump-2.c } \
+ { analyzer_gil_plugin.c \
+ gil-1.c } \
]
foreach plugin_test $plugin_test_list {
diff --git a/gcc/testsuite/gcc.dg/pr25376.c b/gcc/testsuite/gcc.dg/pr25376.c
index 3008b09..d66f2e1 100644
--- a/gcc/testsuite/gcc.dg/pr25376.c
+++ b/gcc/testsuite/gcc.dg/pr25376.c
@@ -7,3 +7,4 @@ void simple (void)
}
/* { dg-final { scan-assembler "my_named_section" } } */
+/* { dg-final { scan-assembler-symbol-section {simple$} {^\.?my_named_section|simple\[DS\]|^\"\.opd\"} } } */
diff --git a/gcc/testsuite/gcc.dg/pr46309-2.c b/gcc/testsuite/gcc.dg/pr46309-2.c
index f56df42..2903fff 100644
--- a/gcc/testsuite/gcc.dg/pr46309-2.c
+++ b/gcc/testsuite/gcc.dg/pr46309-2.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/46309 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-reassoc-details" } */
+/* { dg-options "-O2 -fno-ipa-icf -fno-jump-tables -fno-bit-tests -fdump-tree-reassoc-details" } */
int foo (void);
diff --git a/gcc/testsuite/gcc.dg/pr83072.c b/gcc/testsuite/gcc.dg/pr83072.c
new file mode 100644
index 0000000..3bed8d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr83072.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre" } */
+
+void kill (void);
+
+int f(int c){
+ c |= 1;
+ if (c == 0)
+ kill ();
+
+ return c;
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr85811.c b/gcc/testsuite/gcc.dg/pr85811.c
new file mode 100644
index 0000000..868f66c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr85811.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+#include <stdio.h>
+
+int main() {
+ const double negval = -1.0;
+ const double nanval = 0.0 / 0.0;
+ const double val = __builtin_fmax(negval, nanval);
+ const double absval = __builtin_fabs(val);
+ printf("fabs(%.16e) = %.16e\n", val, absval);
+ return absval >= 0 ? 0 : 1;
+}
+
+/* We hope not to see: printf ("fabs(%.16e) = %.16e\n", val_4, val_4); */
+/* { dg-final { scan-tree-dump-not "val_\[0-9\]*, val_\[0-9\]*" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr91029.c b/gcc/testsuite/gcc.dg/pr91029.c
new file mode 100644
index 0000000..4904764
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr91029.c
@@ -0,0 +1,48 @@
+/* PR tree-optimization/91029 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+int xx;
+
+void f1 (int i)
+{
+ if ((i % 7) == 3)
+ {
+ xx = (i < 0);
+ if (xx)
+ kill ();
+ }
+}
+
+void f2 (int i)
+{
+ if ((i % 7) > 0)
+ {
+ xx = (i < 0);
+ if (xx)
+ kill ();
+ }
+}
+
+void f3 (int i)
+{
+ if ((i % 7) == -3)
+ {
+ xx = (i > 0);
+ if (xx)
+ kill ();
+ }
+}
+
+void f4 (int i)
+{
+ if ((i % 7) < 0)
+ {
+ xx = (i > 0);
+ if (xx)
+ kill ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr91441.c b/gcc/testsuite/gcc.dg/pr91441.c
new file mode 100644
index 0000000..4f7a8fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr91441.c
@@ -0,0 +1,11 @@
+/* PR target/91441 */
+/* { dg-do compile } */
+/* { dg-require-effective-target no_fsanitize_address }*/
+/* { dg-options "--param asan-stack=1 -fsanitize=kernel-address" } */
+
+int *bar(int *);
+int *f( int a)
+{
+ return bar(&a);
+}
+/* { dg-warning ".'-fsanitize=kernel-address' with stack protection is not supported without '-fasan-shadow-offset=' for this target" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr95853.c b/gcc/testsuite/gcc.dg/pr95853.c
new file mode 100644
index 0000000..fdd3c30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr95853.c
@@ -0,0 +1,59 @@
+/* PR tree-optimization/95853 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-widening_mul" } */
+
+#if __SIZEOF_INT128__
+typedef __uint128_t W;
+typedef unsigned long long T;
+#else
+typedef unsigned long long W;
+typedef unsigned int T;
+#endif
+
+struct S { int p; T r; };
+
+struct S
+foo (T x, T y)
+{
+ W z = (W) x + y;
+ return (struct S) { z > ~(T) 0, (T) z };
+}
+
+struct S
+bar (T x)
+{
+ W z = (W) x + 132;
+ return (struct S) { z > ~(T) 0, (T) z };
+}
+
+struct S
+baz (T x, unsigned short y)
+{
+ W z = (W) x + y;
+ return (struct S) { z > ~(T) 0, (T) z };
+}
+
+struct S
+qux (unsigned short x, T y)
+{
+ W z = (W) x + y;
+ return (struct S) { z > ~(T) 0, (T) z };
+}
+
+struct S
+corge (T x, T y)
+{
+ T w = x + y;
+ W z = (W) x + y;
+ return (struct S) { z > ~(T) 0, w };
+}
+
+struct S
+garple (T x, T y)
+{
+ W z = (W) x + y;
+ T w = x + y;
+ return (struct S) { z > ~(T) 0, w };
+}
+
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 6 "widening_mul" { target { i?86-*-* x86_64-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/pr96239.c b/gcc/testsuite/gcc.dg/pr96239.c
new file mode 100644
index 0000000..8af56e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr96239.c
@@ -0,0 +1,54 @@
+/* PR tree-optimization/96239 */
+/* { dg-do run { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " r>> 8;" 1 "optimized" { target bswap } } } */
+/* { dg-final { scan-tree-dump-times " = __builtin_bswap64 " 1 "optimized" { target bswap } } } */
+/* { dg-final { scan-tree-dump-not " >> \(8\|16\|24\|32\|40\|48\|56\);" "optimized" { target bswap } } } */
+
+typedef unsigned char V __attribute__((vector_size (2)));
+typedef unsigned char W __attribute__((vector_size (8)));
+
+__attribute__((noipa)) void
+foo (unsigned short x, V *p)
+{
+ *p = (V) { x >> 8, x };
+}
+
+__attribute__((noipa)) void
+bar (unsigned long long x, W *p)
+{
+ *p = (W) { x >> 56, x >> 48, x >> 40, x >> 32, x >> 24, x >> 16, x >> 8, x };
+}
+
+__attribute__((noipa)) void
+baz (unsigned short x, V *p)
+{
+ *p = (V) { x, x >> 8 };
+}
+
+__attribute__((noipa)) void
+qux (unsigned long long x, W *p)
+{
+ *p = (W) { x, x >> 8, x >> 16, x >> 24, x >> 32, x >> 40, x >> 48, x >> 56 };
+}
+
+int
+main ()
+{
+ V a, c, e, g;
+ W b, d, f, h;
+ foo (0xcafe, &a);
+ bar (0xdeadbeefcafebabeULL, &b);
+ baz (0xdead, &c);
+ qux (0xfeedbac1beefdeadULL, &d);
+ e = (V) { 0xca, 0xfe };
+ f = (W) { 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe };
+ g = (V) { 0xad, 0xde };
+ h = (W) { 0xad, 0xde, 0xef, 0xbe, 0xc1, 0xba, 0xed, 0xfe };
+ if (__builtin_memcmp (&a, &e, sizeof (V))
+ || __builtin_memcmp (&b, &f, sizeof (W))
+ || __builtin_memcmp (&c, &g, sizeof (V))
+ || __builtin_memcmp (&d, &h, sizeof (W)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr96260.c b/gcc/testsuite/gcc.dg/pr96260.c
new file mode 100644
index 0000000..734832f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr96260.c
@@ -0,0 +1,10 @@
+/* PR target/96260 */
+/* { dg-do compile } */
+/* { dg-require-effective-target no_fsanitize_address }*/
+/* { dg-options "--param asan-stack=1 -fsanitize=kernel-address -fasan-shadow-offset=0x100000" } */
+
+int *bar(int *);
+int *f( int a)
+{
+ return bar(&a);
+}
diff --git a/gcc/testsuite/gcc.dg/pr96307.c b/gcc/testsuite/gcc.dg/pr96307.c
new file mode 100644
index 0000000..cd1c17c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr96307.c
@@ -0,0 +1,25 @@
+/* PR target/96307 */
+/* { dg-do compile } */
+/* { dg-require-effective-target no_fsanitize_address }*/
+/* { dg-additional-options "-fsanitize=kernel-address --param=asan-instrumentation-with-call-threshold=8" } */
+
+#include <limits.h>
+enum a {test1, test2, test3=INT_MAX};
+enum a a;
+enum a *b;
+
+void reset (void);
+
+void
+t()
+{
+ if (a != test2)
+ __builtin_abort ();
+ if (*b != test2)
+ __builtin_abort ();
+ reset ();
+ if (a != test1)
+ __builtin_abort ();
+ if (*b != test1)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr96708-negative.c b/gcc/testsuite/gcc.dg/pr96708-negative.c
new file mode 100644
index 0000000..91964d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr96708-negative.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+#include <stdbool.h>
+
+bool __attribute__ ((noinline))
+test1 (int a, int b)
+{
+ int tmp = (a < b) ? b : a;
+ return tmp <= a;
+}
+
+bool __attribute__ ((noinline))
+test2 (int a, int b)
+{
+ int tmp = (a < b) ? b : a;
+ return tmp > a;
+}
+
+bool __attribute__ ((noinline))
+test3 (int a, int b)
+{
+ int tmp = (a > b) ? b : a;
+ return tmp >= a;
+}
+
+bool __attribute__ ((noinline))
+test4 (int a, int b)
+{
+ int tmp = (a > b) ? b : a;
+ return tmp < a;
+}
+
+int main()
+{
+ if (test1 (1, 2) || !test1 (2, 1) ||
+ !test2 (1, 2) || test2 (2, 1) ||
+ !test3 (1, 2) || test3 (2, 1) ||
+ test4 (1, 2) || !test4 (2, 1)) {
+ __builtin_abort();
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-not { "return 1;" } "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr96708-positive.c b/gcc/testsuite/gcc.dg/pr96708-positive.c
new file mode 100644
index 0000000..65af853
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr96708-positive.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+#include <stdbool.h>
+
+bool __attribute__ ((noinline))
+test1(int a, int b)
+{
+ int tmp = (a < b) ? b : a;
+ return tmp >= a;
+}
+
+bool __attribute__ ((noinline))
+test2(int a, int b)
+{
+ int tmp = (a < b) ? b : a;
+ return tmp < a;
+}
+
+bool __attribute__ ((noinline))
+test3(int a, int b)
+{
+ int tmp = (a > b) ? b : a;
+ return tmp <= a;
+}
+
+bool __attribute__ ((noinline))
+test4(int a, int b)
+{
+ int tmp = (a > b) ? b : a;
+ return tmp > a;
+}
+
+int main()
+{
+ if (!test1 (1, 2) || !test1 (2, 1) ||
+ test2 (1, 2) || test2 (2, 1) ||
+ !test3 (1, 2) || !test3 (2, 1) ||
+ test4 (1, 2) || test4 (2, 1)) {
+ __builtin_abort();
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "return 0;" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-not { "MAX_EXPR" } "optimized" } } */
+/* { dg-final { scan-tree-dump-not { "MIN_EXPR" } "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr97459-1.c b/gcc/testsuite/gcc.dg/pr97459-1.c
new file mode 100644
index 0000000..96c7ab6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97459-1.c
@@ -0,0 +1,54 @@
+/* PR rtl-optimization/97459 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */
+
+#ifdef __SIZEOF_INT128__
+typedef __uint128_t T;
+#else
+typedef unsigned long long T;
+#endif
+
+T __attribute__((noipa)) foo (T x, T n) { return x % n; }
+#define C(n) T __attribute__((noipa)) foo##n (T x) { return x % (n - 10000); }
+
+#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9)
+#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \
+ C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9)
+#ifdef EXPENSIVE
+#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \
+ C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9)
+#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \
+ C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9)
+#else
+#define C3(n) C2(n##0) C2(n##4) C2(n##9)
+#define C4(n) C3(n##0) C3(n##3) C3(n##7)
+#endif
+#define TESTS C4(1) C1(10010) C1(10012) C1(16144)
+
+TESTS
+
+struct S { T x; T (*foo) (T); };
+
+#undef C
+#define C(n) { n - 10000, foo##n },
+
+struct S tests[] = {
+TESTS
+ { 0, 0 }
+};
+
+int
+main ()
+{
+ int i, j, k;
+ for (k = 0; tests[k].x; k++)
+ for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++)
+ for (j = -5; j <= 5; j++)
+ {
+ T x = ((T) 1 << i) + j;
+ if (foo (x, tests[k].x) != tests[k].foo (x))
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97459-2.c b/gcc/testsuite/gcc.dg/pr97459-2.c
new file mode 100644
index 0000000..0e2bfbd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97459-2.c
@@ -0,0 +1,57 @@
+/* PR rtl-optimization/97459 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */
+
+#ifdef __SIZEOF_INT128__
+typedef __int128_t T;
+typedef __uint128_t U;
+#else
+typedef long long T;
+typedef unsigned long long U;
+#endif
+
+T __attribute__((noipa)) foo (T x, T n) { return x % n; }
+#define C(n) T __attribute__((noipa)) foo##n (T x) { return x % (n - 10000); }
+
+#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9)
+#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \
+ C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9)
+#ifdef EXPENSIVE
+#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \
+ C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9)
+#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \
+ C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9)
+#else
+#define C3(n) C2(n##0) C2(n##4) C2(n##9)
+#define C4(n) C3(n##0) C3(n##3) C3(n##7)
+#endif
+#define TESTS C4(1) C1(10010) C1(10012) C1(16144)
+
+TESTS
+
+struct S { T x; T (*foo) (T); };
+
+#undef C
+#define C(n) { n - 10000, foo##n },
+
+struct S tests[] = {
+TESTS
+ { 0, 0 }
+};
+
+int
+main ()
+{
+ int i, j, k;
+ for (k = 0; tests[k].x; k++)
+ for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++)
+ for (j = -5; j <= 5; j++)
+ {
+ U x = ((U) 1 << i) + j;
+ if (foo ((T) x, tests[k].x) != tests[k].foo ((T) x)
+ || foo ((T) -x, tests[k].x) != tests[k].foo ((T) -x))
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97459-3.c b/gcc/testsuite/gcc.dg/pr97459-3.c
new file mode 100644
index 0000000..7fbb7ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97459-3.c
@@ -0,0 +1,54 @@
+/* PR rtl-optimization/97459 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */
+
+#ifdef __SIZEOF_INT128__
+typedef __uint128_t T;
+#else
+typedef unsigned long long T;
+#endif
+
+T __attribute__((noipa)) foo (T x, T n) { return x / n; }
+#define C(n) T __attribute__((noipa)) foo##n (T x) { return x / (n - 10000); }
+
+#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9)
+#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \
+ C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9)
+#ifdef EXPENSIVE
+#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \
+ C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9)
+#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \
+ C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9)
+#else
+#define C3(n) C2(n##0) C2(n##4) C2(n##9)
+#define C4(n) C3(n##0) C3(n##3) C3(n##7)
+#endif
+#define TESTS C4(1) C1(10010) C1(10012) C1(16144)
+
+TESTS
+
+struct S { T x; T (*foo) (T); };
+
+#undef C
+#define C(n) { n - 10000, foo##n },
+
+struct S tests[] = {
+TESTS
+ { 0, 0 }
+};
+
+int
+main ()
+{
+ int i, j, k;
+ for (k = 0; tests[k].x; k++)
+ for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++)
+ for (j = -5; j <= 5; j++)
+ {
+ T x = ((T) 1 << i) + j;
+ if (foo (x, tests[k].x) != tests[k].foo (x))
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97459-4.c b/gcc/testsuite/gcc.dg/pr97459-4.c
new file mode 100644
index 0000000..33e49a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97459-4.c
@@ -0,0 +1,57 @@
+/* PR rtl-optimization/97459 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */
+
+#ifdef __SIZEOF_INT128__
+typedef __int128_t T;
+typedef __uint128_t U;
+#else
+typedef long long T;
+typedef unsigned long long U;
+#endif
+
+T __attribute__((noipa)) foo (T x, T n) { return x / n; }
+#define C(n) T __attribute__((noipa)) foo##n (T x) { return x / (n - 10000); }
+
+#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9)
+#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \
+ C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9)
+#ifdef EXPENSIVE
+#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \
+ C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9)
+#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \
+ C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9)
+#else
+#define C3(n) C2(n##0) C2(n##4) C2(n##9)
+#define C4(n) C3(n##0) C3(n##3) C3(n##7)
+#endif
+#define TESTS C4(1) C1(10010) C1(10012) C1(16144)
+
+TESTS
+
+struct S { T x; T (*foo) (T); };
+
+#undef C
+#define C(n) { n - 10000, foo##n },
+
+struct S tests[] = {
+TESTS
+ { 0, 0 }
+};
+
+int
+main ()
+{
+ int i, j, k;
+ for (k = 0; tests[k].x; k++)
+ for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++)
+ for (j = -5; j <= 5; j++)
+ {
+ U x = ((U) 1 << i) + j;
+ if (foo ((T) x, tests[k].x) != tests[k].foo ((T) x)
+ || foo ((T) -x, tests[k].x) != tests[k].foo ((T) -x))
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97459-5.c b/gcc/testsuite/gcc.dg/pr97459-5.c
new file mode 100644
index 0000000..f658a5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97459-5.c
@@ -0,0 +1,56 @@
+/* PR rtl-optimization/97459 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */
+
+#ifdef __SIZEOF_INT128__
+typedef __uint128_t T;
+#else
+typedef unsigned long long T;
+#endif
+
+T __attribute__((noipa)) foo (T x, T n, T *r) { *r = x % n; return x / n; }
+#define C(n) T __attribute__((noipa)) foo##n (T x, T *r) { *r = x % (n - 10000); return x / (n - 10000); }
+
+#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9)
+#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \
+ C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9)
+#ifdef EXPENSIVE
+#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \
+ C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9)
+#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \
+ C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9)
+#else
+#define C3(n) C2(n##0) C2(n##4) C2(n##9)
+#define C4(n) C3(n##0) C3(n##3) C3(n##7)
+#endif
+#define TESTS C4(1) C1(10010) C1(10012) C1(16144)
+
+TESTS
+
+struct S { T x; T (*foo) (T, T *); };
+
+#undef C
+#define C(n) { n - 10000, foo##n },
+
+struct S tests[] = {
+TESTS
+ { 0, 0 }
+};
+
+int
+main ()
+{
+ int i, j, k;
+ for (k = 0; tests[k].x; k++)
+ for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++)
+ for (j = -5; j <= 5; j++)
+ {
+ T x = ((T) 1 << i) + j;
+ T r1, r2;
+ if (foo (x, tests[k].x, &r1) != tests[k].foo (x, &r2)
+ || r1 != r2)
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97459-6.c b/gcc/testsuite/gcc.dg/pr97459-6.c
new file mode 100644
index 0000000..d4602be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97459-6.c
@@ -0,0 +1,62 @@
+/* PR rtl-optimization/97459 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */
+
+#ifdef __SIZEOF_INT128__
+typedef __int128_t T;
+typedef __uint128_t U;
+#else
+typedef long long T;
+typedef unsigned long long U;
+#endif
+
+T __attribute__((noipa)) foo (T x, T n, T *r) { *r = x % n; return x / n; }
+#define C(n) T __attribute__((noipa)) foo##n (T x, T *r) { *r = x % (n - 10000); return x / (n - 10000); }
+
+#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9)
+#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \
+ C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9)
+#ifdef EXPENSIVE
+#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \
+ C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9)
+#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \
+ C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9)
+#else
+#define C3(n) C2(n##0) C2(n##4) C2(n##9)
+#define C4(n) C3(n##0) C3(n##3) C3(n##7)
+#endif
+#define TESTS C4(1) C1(10010) C1(10012) C1(16144)
+
+TESTS
+
+struct S { T x; T (*foo) (T, T *); };
+
+#undef C
+#define C(n) { n - 10000, foo##n },
+
+struct S tests[] = {
+TESTS
+ { 0, 0 }
+};
+
+int
+main ()
+{
+ int i, j, k;
+ for (k = 0; tests[k].x; k++)
+ for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++)
+ for (j = -5; j <= 5; j++)
+ {
+ U x = ((U) 1 << i) + j;
+ T r1 = 0, r2 = 0;
+ if (foo ((T) x, tests[k].x, &r1) != tests[k].foo ((T) x, &r2)
+ || r1 != r2)
+ __builtin_abort ();
+ r1 = 0; r2 = 0;
+ if (foo ((T) -x, tests[k].x, &r1) != tests[k].foo ((T) -x, &r2)
+ || r1 != r2)
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97505.c b/gcc/testsuite/gcc.dg/pr97505.c
new file mode 100644
index 0000000..f01d912
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97505.c
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-Os -fsanitize=signed-integer-overflow -fdump-tree-evrp" }
+
+// Test that .UBSAN_CHECK_SUB(y, x) is treated as y-x for range
+// purposes, where X and Y are related to each other.
+//
+// This effectively checks that range relationals work with builtins.
+
+void unreachable();
+
+int foobar(int x, int y)
+{
+ if (x < y)
+ {
+ int z = y - x;
+ if (z == 0)
+ unreachable();
+ return z;
+ }
+ return 5;
+}
+
+// { dg-final { scan-tree-dump-not "unreachable" "evrp" } }
diff --git a/gcc/testsuite/gcc.dg/pr97515.c b/gcc/testsuite/gcc.dg/pr97515.c
index 2b6185e..b4f2481 100644
--- a/gcc/testsuite/gcc.dg/pr97515.c
+++ b/gcc/testsuite/gcc.dg/pr97515.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fdump-tree-ccp2" } */
int
e7 (int gg)
@@ -19,3 +19,9 @@ e7 (int gg)
return xe;
}
+
+/* EVRP should be able to reduce this to a single goto when we can
+ * revisit statements to try folding again based on changed inputs.
+ * Until then, make sure its gone by ccp2. */
+
+/* { dg-final { scan-tree-dump-times "goto" 1 "ccp2" } } */
diff --git a/gcc/testsuite/gcc.dg/pr97534.c b/gcc/testsuite/gcc.dg/pr97534.c
new file mode 100644
index 0000000..b363a32
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97534.c
@@ -0,0 +1,9 @@
+/* PR target/97534 - ICE in decompose on arm*-*-*. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -O2 -g" } */
+
+int f (int a)
+{
+ int b;
+ __atomic_fetch_sub(&b, (int)(-__INT_MAX__ - 1), (int)0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr97539.c b/gcc/testsuite/gcc.dg/pr97539.c
new file mode 100644
index 0000000..def55e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97539.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -g" } */
+
+int a, b;
+void c() {
+ char d;
+ for (; b;)
+ for (;;)
+ for (; d <= 7; d += 1) {
+ a = 7;
+ for (; a; a += 1)
+ e:
+ d += d;
+ d ^= 0;
+ }
+ goto e;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97555.c b/gcc/testsuite/gcc.dg/pr97555.c
new file mode 100644
index 0000000..625bc6f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97555.c
@@ -0,0 +1,22 @@
+// { dg-do run }
+// { dg-options "-Os" }
+
+struct {
+ int a:1;
+} b;
+
+int c, d, e, f = 1, g;
+
+int main ()
+{
+ for (; d < 3; d++) {
+ char h = 1 % f, i = ~(0 || ~0);
+ c = h;
+ f = ~b.a;
+ ~b.a | 1 ^ ~i && g;
+ if (~e)
+ i = b.a;
+ b.a = i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97567-2.c b/gcc/testsuite/gcc.dg/pr97567-2.c
new file mode 100644
index 0000000..dee31c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97567-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+char a[2];
+
+extern int x;
+
+void foo(void);
+
+signed char g (signed char min, signed char max)
+{
+ signed char i = x;
+ return i < min || max < i ? min : i;
+}
+
+void gg (void)
+{
+ signed char t = g (0, 9);
+ /* Ranger should be able to remove the call to foo (). */
+ if (t > 9 || t < 0)
+ foo ();
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr97567.c b/gcc/testsuite/gcc.dg/pr97567.c
new file mode 100644
index 0000000..8922f27
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97567.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int a, b, c, d;
+void k() {
+ unsigned f = 1;
+ long long g = 4073709551615;
+ for (; a; a++)
+ for (;;) {
+ d = 0;
+ L1:
+ break;
+ }
+ if (f)
+ for (; a; a++)
+ ;
+ g || f;
+ int i = 0 - f || g;
+ long long j = g - f;
+ if (j || f) {
+ if (g < 4073709551615)
+ for (;;)
+ ;
+ int e = ~f, h = b / ~e;
+ if (c)
+ goto L2;
+ g = f = h;
+ }
+ g || d;
+L2:
+ if (c)
+ goto L1;
+}
+int main() { k(); return 0; }
diff --git a/gcc/testsuite/gcc.dg/pr97579.c b/gcc/testsuite/gcc.dg/pr97579.c
new file mode 100644
index 0000000..5cd5427
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97579.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 --param=max-unswitch-insns=1024" } */
+/* { dg-additional-options "-mavx512vl" { target x86_64-*-* i?86-*-* } } */
+
+int bad_odd_rows_0_0, rows_bad_row1, rows_bad_group_okay, calc_rows_row2;
+
+int
+rows_bad() {
+ int i, in_zeroes;
+ char block;
+ i = 0;
+ for (; i < 5; i++)
+ if (rows_bad_row1 & i)
+ in_zeroes = 0;
+ else {
+ if (!in_zeroes)
+ in_zeroes = 1;
+ if (block & 1)
+ rows_bad_group_okay = 1;
+ }
+ if (in_zeroes)
+ return rows_bad_group_okay;
+}
+
+void
+calc_rows() {
+ for (; calc_rows_row2; calc_rows_row2++) {
+ rows_bad();
+ bad_odd_rows_0_0 = rows_bad();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr97596.c b/gcc/testsuite/gcc.dg/pr97596.c
new file mode 100644
index 0000000..b0726ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97596.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+void
+q8 (__int128 *uv, unsigned short int nf)
+{
+ __int128 i4;
+
+ i4 = -nf;
+ if (i4 << 1 != 0)
+ *uv += nf;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97721.c b/gcc/testsuite/gcc.dg/pr97721.c
new file mode 100644
index 0000000..c2a2848
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97721.c
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-O -fno-tree-dominator-opts" }
+
+int ot;
+
+void
+z6 (char *tw)
+{
+ while (ot >= 0)
+ --ot;
+
+ __builtin_strcpy (&tw[ot], tw);
+}
diff --git a/gcc/testsuite/gcc.dg/pr97725.c b/gcc/testsuite/gcc.dg/pr97725.c
new file mode 100644
index 0000000..2fcb12c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97725.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int a;
+unsigned b;
+
+int main() {
+ if (a) {
+ goto L1;
+ while (1)
+ while (1) {
+ long e = -1L, g;
+ int f, h, i;
+ L1:
+ a = f;
+ L2:
+ g = e;
+ f = h || g;
+ e = ~(f & b);
+ if (i || g < -1L) {
+ ~(g || 0);
+ break;
+ }
+ goto L2;
+ }
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97737.c b/gcc/testsuite/gcc.dg/pr97737.c
new file mode 100644
index 0000000..eef1c35
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97737.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int a = 1, b, c;
+
+void d() {
+ int e = 1;
+L1:
+ b = e;
+L2:
+ e = e / a;
+ if (!(e || c || e - 1))
+ goto L1;
+ if (!b)
+ goto L2;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97741.c b/gcc/testsuite/gcc.dg/pr97741.c
new file mode 100644
index 0000000..47115d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97741.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wextra -fno-strict-aliasing -fwrapv -Os -fno-toplevel-reorder -fno-tree-ccp -fno-tree-fre" } */
+
+short a = 0;
+long b = 0;
+char c = 0;
+void d() {
+ int e = 0;
+f:
+ for (a = 6; a;)
+ c = e;
+ e = 0;
+ for (; e == 20; ++e)
+ for (; b;)
+ goto f;
+}
+int main() { return 0; }
diff --git a/gcc/testsuite/gcc.dg/pr97750.c b/gcc/testsuite/gcc.dg/pr97750.c
new file mode 100644
index 0000000..90c3dc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97750.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/97750 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wextra" } */
+
+char CopyPlane_src;
+long CopyPlane_copy_pitch;
+char *CopyFromUswc_src;
+int CopyFromUswc_height;
+void CopyPlane(char *dst) {
+ __builtin_memcpy(dst, &CopyPlane_src, CopyPlane_copy_pitch);
+}
+void CopyFromUswc(long src_pitch) {
+ char *dst;
+ for (; CopyFromUswc_height;) {
+ unsigned unaligned = (long)CopyFromUswc_src;
+ if (unaligned)
+ CopyPlane(&dst[unaligned]);
+ CopyFromUswc_src += src_pitch;
+ }
+}
+/* { dg-prune-output "-Wmaybe-uninitialized" } */
diff --git a/gcc/testsuite/gcc.dg/pr97806.c b/gcc/testsuite/gcc.dg/pr97806.c
new file mode 100644
index 0000000..9ec3299
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97806.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int b;
+long c;
+int g();
+void h(long *);
+void i(long *);
+void d() {
+ int e, f = b - e;
+ if (g())
+ h(&c + f);
+ else
+ i(&c + f);
+ __builtin_memset(0, 0, f * 8);
+}
diff --git a/gcc/testsuite/gcc.dg/pr97830.c b/gcc/testsuite/gcc.dg/pr97830.c
new file mode 100644
index 0000000..3729a65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97830.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef enum { LangC } cLanguage;
+typedef enum { FunctionOneArg, FunctionStandard } cFunctionType;
+void *CCTK_CallFunction_function;
+cLanguage CCTK_CallFunction_fdata_0;
+cFunctionType CCTK_CallFunction_fdata_1;
+void CCTK_CallFunction_data() {
+ void (*standardfunc)();
+ int (*oneargfunc)();
+ switch (CCTK_CallFunction_fdata_1) {
+ case FunctionOneArg:
+ oneargfunc = CCTK_CallFunction_function;
+ oneargfunc(CCTK_CallFunction_data);
+ break;
+ case FunctionStandard:
+ switch (CCTK_CallFunction_fdata_0) {
+ case LangC:
+ standardfunc = CCTK_CallFunction_function;
+ standardfunc(CCTK_CallFunction_data);
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr97860.c b/gcc/testsuite/gcc.dg/pr97860.c
new file mode 100644
index 0000000..04c0f19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97860.c
@@ -0,0 +1,11 @@
+/* PR c/97860 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+foo (int n)
+{
+ typedef int T[0];
+ typedef T V[n];
+ void bar (V);
+}
diff --git a/gcc/testsuite/gcc.dg/pr97897.c b/gcc/testsuite/gcc.dg/pr97897.c
new file mode 100644
index 0000000..084c1cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97897.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void h ();
+void f () __attribute__ ((returns_twice));
+void g (_Complex int a)
+{
+ f ();
+ if (a != 0)
+ {
+ a = 0;
+ h ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr97953.c b/gcc/testsuite/gcc.dg/pr97953.c
new file mode 100644
index 0000000..6219619
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97953.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-tree-fre" } */
+
+int __attribute__((noipa))
+foo (int flag, int *p)
+{
+ int val = *p;
+ if (flag)
+ {
+ if (val != 1)
+ __builtin_unreachable ();
+ return 0;
+ }
+ int val2 = *p;
+ return val2 == 2;
+}
+
+int main()
+{
+ int i = 2;
+ if (foo (0, &i) != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97954.c b/gcc/testsuite/gcc.dg/pr97954.c
new file mode 100644
index 0000000..178e1d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97954.c
@@ -0,0 +1,12 @@
+/* PR rtl-optimization/97954 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+foo (void)
+{
+ int x;
+ lab:
+ asm goto ("": "=r" (x) : : : lab);
+ return x;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97955.c b/gcc/testsuite/gcc.dg/pr97955.c
new file mode 100644
index 0000000..a5236c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97955.c
@@ -0,0 +1,7 @@
+/* PR 97955 - ICE in build_array_type_1 on invalid redeclaration of function
+ with VLA parameter
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void f (int n, int a[n]);
+void f (int *b) { } // { dg-error "conflicting types" }
diff --git a/gcc/testsuite/gcc.dg/pr97979.c b/gcc/testsuite/gcc.dg/pr97979.c
new file mode 100644
index 0000000..44aaff2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97979.c
@@ -0,0 +1,13 @@
+/* PR tree-optimization/97979 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp" } */
+
+short a = 0;
+int b = 0;
+
+void
+foo (void)
+{
+ unsigned short d = b;
+ a = d >> -2U; /* { dg-warning "right shift count >= width of type" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr97981.c b/gcc/testsuite/gcc.dg/pr97981.c
new file mode 100644
index 0000000..846b875
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97981.c
@@ -0,0 +1,15 @@
+/* PR c/97981 */
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-original" } */
+/* { dg-final { scan-tree-dump-times "atomic_load" 2 "original" } } */
+
+
+void f(void)
+{
+ volatile _Atomic int x;
+ x;
+ volatile _Atomic double a;
+ double b;
+ b = a;
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr98099.c b/gcc/testsuite/gcc.dg/pr98099.c
new file mode 100644
index 0000000..12e52f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98099.c
@@ -0,0 +1,12 @@
+/* PR middle-end/98099 */
+/* Reported by G. Steinmetz <gscfq@t-online.de> */
+
+/* { dg-do compile { target dfp } } */
+/* { dg-options "-fsso-struct=big-endian" } */
+
+struct S { _Decimal128 a; };
+
+_Decimal128 f (struct S x)
+{
+ return x.a; /* { dg-message "sorry, unimplemented: reverse storage order" "" { target { ! int128 } } } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr98147.c b/gcc/testsuite/gcc.dg/pr98147.c
new file mode 100644
index 0000000..3edc798
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98147.c
@@ -0,0 +1,10 @@
+/* PR target/98147 */
+
+char buffer[32] = "foo bar";
+
+int
+main ()
+{
+ __builtin___clear_cache (buffer, buffer + 32);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr98190.c b/gcc/testsuite/gcc.dg/pr98190.c
new file mode 100644
index 0000000..bfdd17d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98190.c
@@ -0,0 +1,33 @@
+/* PR middle-end/98190 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+static int __attribute__((noipa))
+foo (const char *p, const char *q, const int len)
+{
+ for (int i = 0; i < len; p++, q++, i++)
+ {
+ int equal;
+ _Bool x, y;
+ __builtin_memcpy ((char *) &x, p, sizeof x);
+ __builtin_memcpy ((char *) &y, q, sizeof y);
+ equal = (x == y);
+ if (equal <= 0)
+ return equal;
+ }
+ return 1;
+}
+
+int
+main ()
+{
+ const _Bool buf[4] = { 1, 0, 0, 0 };
+#ifdef __aarch64__
+ register long x4 asm ("x4") = 0xdeadbeefULL;
+ register long x5 asm ("x5") = 0xcafebabeULL;
+ asm volatile (""::"r" (x4), "r" (x5));
+#endif
+ if (foo ((char *) &buf[0], (char *) &buf[0], 1) != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr98211.c b/gcc/testsuite/gcc.dg/pr98211.c
new file mode 100644
index 0000000..cea371d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98211.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-std=gnu90 -O3 -fgimple" } */
+
+int test_var_3;
+short arr_20[16];
+void __GIMPLE (ssa,startwith("slp"))
+test (int var_1, short int a, short int b, short int c, short int d)
+{
+ _Bool tem2;
+ _Bool tem;
+ unsigned int i_5;
+ int _24;
+ _Bool _28;
+ short int _30;
+ short int _32;
+
+ __BB(2):
+ _24 = test_var_3;
+ tem_25 = _24 != 0;
+ tem2_26 = var_1_11(D) != 0;
+ _28 = tem_25 | tem2_26;
+ _30 = _28 != _Literal (_Bool) 0 ? a_16(D) : b_15(D);
+ arr_20[0u] = _30;
+ _32 = _28 != _Literal (_Bool) 0 ? c_19(D) : d_18(D);
+ arr_20[8u] = _32;
+ arr_20[1u] = _30;
+ arr_20[9u] = _32;
+ arr_20[2u] = _30;
+ arr_20[10u] = _32;
+ arr_20[3u] = _30;
+ arr_20[11u] = _32;
+ arr_20[4u] = _30;
+ arr_20[12u] = _32;
+ arr_20[5u] = _30;
+ arr_20[13u] = _32;
+ arr_20[6u] = _30;
+ arr_20[14u] = _32;
+ arr_20[7u] = _30;
+ arr_20[15u] = _32;
+ return;
+}
+
+
+int
+main()
+{
+ test (1, 0x88, 0x77, 0x77, 0x88);
+ if (arr_20[0] != 0x88)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr98271.c b/gcc/testsuite/gcc.dg/pr98271.c
new file mode 100644
index 0000000..b453434
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98271.c
@@ -0,0 +1,13 @@
+/* PR rtl-optimization/98271 */
+/* PR rtl-optimization/98276 */
+/* PR tree-optimization/98279 */
+/* { dg-do compile } */
+/* { dg-options "-O --param=align-loop-iterations=1197120096074465280 --param=gcse-cost-distance-ratio=2147483648 --param=hot-bb-frequency-fraction=2147483648" } */
+/* { dg-error "argument to .--param=align-loop-iterations=. is bigger than 2147483647" "" { target *-*-* } 0 } */
+/* { dg-error "argument to .--param=gcse-cost-distance-ratio=. is bigger than 2147483647" "" { target *-*-* } 0 } */
+/* { dg-error "argument to .--param=hot-bb-frequency-fraction=. is bigger than 2147483647" "" { target *-*-* } 0 } */
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.dg/pr98272.c b/gcc/testsuite/gcc.dg/pr98272.c
new file mode 100644
index 0000000..126a616
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98272.c
@@ -0,0 +1,22 @@
+/* PR tree-optimization/98272 */
+/* Reported by Zdenek Sojka <zsojka@seznam.cz> */
+
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-forwprop" } */
+
+void bar (void);
+
+void
+foo (unsigned char uc)
+{
+ if (uc >= 5)
+ return;
+
+ switch (uc)
+ {
+ case 0:
+ case 2:
+ case 4:
+ bar ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-6.c b/gcc/testsuite/gcc.dg/pragma-diag-6.c
index 0dca1dc..f2df88d 100644
--- a/gcc/testsuite/gcc.dg/pragma-diag-6.c
+++ b/gcc/testsuite/gcc.dg/pragma-diag-6.c
@@ -2,7 +2,10 @@
#pragma GCC diagnostic error "-Wnoexcept" /* { dg-warning "is valid for C../ObjC.. but not for C" } */
#pragma GCC diagnostic error "-fstrict-aliasing" /* { dg-warning "not an option that controls warnings" } */
#pragma GCC diagnostic error "-Werror" /* { dg-warning "not an option that controls warnings" } */
-#pragma GCC diagnostic error "-Wvla2" /* { dg-warning "unknown option after '#pragma GCC diagnostic' kind; did you mean '-Wvla'" } */
-#pragma GCC diagnostic error "-Walla" /* { dg-warning "unknown option after '#pragma GCC diagnostic' kind; did you mean '-Wall'" } */
-#pragma GCC diagnostic warning "-Walla" /* { dg-warning "unknown option after '#pragma GCC diagnostic' kind; did you mean '-Wall'" } */
+#pragma GCC diagnostic error "-Wvla2" /* { dg-warning "unknown option after '#pragma GCC diagnostic' kind" } */
+/* { dg-message "did you mean '-Wvla'" "" { target *-*-* } .-1 } */
+#pragma GCC diagnostic error "-Walla" /* { dg-warning "unknown option after '#pragma GCC diagnostic' kind" } */
+/* { dg-message "did you mean '-Wall'" "" { target *-*-* } .-1 } */
+#pragma GCC diagnostic warning "-Walla" /* { dg-warning "unknown option after '#pragma GCC diagnostic' kind" } */
+/* { dg-message "did you mean '-Wall'" "" { target *-*-* } .-1 } */
int i;
diff --git a/gcc/testsuite/gcc.dg/predict-8.c b/gcc/testsuite/gcc.dg/predict-8.c
index 5578175..ec755e2 100644
--- a/gcc/testsuite/gcc.dg/predict-8.c
+++ b/gcc/testsuite/gcc.dg/predict-8.c
@@ -8,4 +8,4 @@ int foo(float a, float b) {
return 2;
}
-/* { dg-final { scan-rtl-dump-times "65.\[34]. .guessed" 2 "expand"} } */
+/* { dg-final { scan-rtl-dump-times "99.\[678]. .guessed" 2 "expand"} } */
diff --git a/gcc/testsuite/gcc.dg/profile-info-section.c b/gcc/testsuite/gcc.dg/profile-info-section.c
new file mode 100644
index 0000000..8f31f3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/profile-info-section.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-skip-if "profile-info-section" { powerpc-ibm-aix* } } */
+/* { dg-options "-fprofile-arcs -fprofile-info-section -fdump-tree-optimized" } */
+
+int foo()
+{
+ return 0;
+}
+
+int bar()
+{
+ return 1;
+}
+
+int main ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-tree-dump-not "__gcov_init" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__gcov_exit" "optimized" } } */
+/* { dg-final { scan-assembler "\.gcov_info" } } */
diff --git a/gcc/testsuite/gcc.dg/qual-assign-7.c b/gcc/testsuite/gcc.dg/qual-assign-7.c
new file mode 100644
index 0000000..3e064e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/qual-assign-7.c
@@ -0,0 +1,18 @@
+/* test that assignment drops qualifiers, Bug 98047 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+
+volatile int jv;
+extern int j;
+extern typeof(jv = 1) j;
+
+_Atomic int ja;
+extern typeof(ja = 1) j;
+
+int * __restrict pa;
+extern int *p;
+extern typeof(pa = 0) p;
+
+
+
diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c
index 075f744..1dadf55 100644
--- a/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c
+++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c
@@ -31,7 +31,7 @@ int __RTL (startwith ("fwprop1")) test_returning_constant (void)
}
/* Verify that insn 5 is eliminated. */
-/* { dg-final { scan-rtl-dump "deferring deletion of insn with uid = 5" "fwprop1" } } */
+/* { dg-final { scan-rtl-dump "deleting insn with uid = 5" "fwprop1" } } */
/* { dg-final { scan-rtl-dump "Deleted 1 trivially dead insns" "fwprop1" } } */
int main (void)
diff --git a/gcc/testsuite/gcc.dg/self-right-shift.c b/gcc/testsuite/gcc.dg/self-right-shift.c
new file mode 100644
index 0000000..c457ee5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/self-right-shift.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Self right-shift should be optimized to 0. */
+
+int
+foo (int i)
+{
+ return i >> i;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/sin_cos.c b/gcc/testsuite/gcc.dg/sin_cos.c
new file mode 100644
index 0000000..aa71dca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sin_cos.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* This maps to essentially the same gimple that is generated for
+ gnat.dg/sin_cos.adb, on platforms that use the wraplf variant of
+ Ada.Numerics.Aux_Float. The value of EPSILON is not relevant to
+ the test, but the test must be there to keep the conversions in
+ different BBs long enough to trigger the problem that prevented the
+ sincos optimization, because the arguments passed to sin and cos
+ didn't get unified into a single SSA_NAME in time for sincos. */
+
+#include <math.h>
+
+#define EPSILON 3.4526697709225118160247802734375e-4
+
+static float my_sinf(float x) {
+ return (float) sin ((double) x);
+}
+
+static float wrap_sinf(float x) {
+ if (fabs (x) < EPSILON)
+ return 0;
+ return my_sinf (x);
+}
+
+static float my_cosf(float x) {
+ return (float) cos ((double) x);
+}
+
+static float wrap_cosf(float x) {
+ if (fabs (x) < EPSILON)
+ return 1;
+ return my_cosf (x);
+}
+
+float my_sin_cos(float x, float *s, float *c) {
+ *s = wrap_sinf (x);
+ *c = wrap_cosf (x);
+}
+
+/* { dg-final { scan-assembler "sincos\|cexp" { target *-linux-gnu* *-w64-mingw* *-*-vxworks* } } } */
diff --git a/gcc/testsuite/gcc.dg/sms-12.c b/gcc/testsuite/gcc.dg/sms-12.c
index aef32ee..3ec50f2 100644
--- a/gcc/testsuite/gcc.dg/sms-12.c
+++ b/gcc/testsuite/gcc.dg/sms-12.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-skip-if "" { ! { aarch64*-*-* } } } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fmodulo-sched -funroll-loops -fdump-rtl-sms --param sms-min-sc=1 -fmodulo-sched-allow-regmoves -fPIC" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/strncmp-2.c b/gcc/testsuite/gcc.dg/strncmp-2.c
index 6818b30..0d84f93 100644
--- a/gcc/testsuite/gcc.dg/strncmp-2.c
+++ b/gcc/testsuite/gcc.dg/strncmp-2.c
@@ -40,6 +40,7 @@ static void test_driver_strncmp (void (test_strncmp)(const char *, const char *,
e = lib_memcmp(buf1,p2,sz);
(*test_memcmp)(buf1,p2,e);
}
+ mprotect (buf2+pgsz,pgsz,PROT_READ|PROT_WRITE);
free(buf2);
}
diff --git a/gcc/testsuite/gcc.dg/system-binary-constants-1.c b/gcc/testsuite/gcc.dg/system-binary-constants-1.c
index 921ee20..ca16215 100644
--- a/gcc/testsuite/gcc.dg/system-binary-constants-1.c
+++ b/gcc/testsuite/gcc.dg/system-binary-constants-1.c
@@ -14,5 +14,5 @@ foo (void)
warning. */
return 23;
#endif
- return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */
+ return 0b1101; /* { dg-warning "binary constants are a C2X feature or GCC extension" } */
}
diff --git a/gcc/testsuite/gcc.dg/torture/float128-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float128-nan-floath.c
new file mode 100644
index 0000000..69fd45a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float128 NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float128 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float128_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c
new file mode 100644
index 0000000..5be4c07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float128x NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float128x } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float128x_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float16-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float16-nan-floath.c
new file mode 100644
index 0000000..cf03b45
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float16-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float16 NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float16 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float16_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float32-nan-floath.c
new file mode 100644
index 0000000..2976a40
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float32 NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float32 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float32_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c
new file mode 100644
index 0000000..0aab4be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float32x NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float32x } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float32x_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float64-nan-floath.c
new file mode 100644
index 0000000..1f5298b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float64 NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float64 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float64_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c
new file mode 100644
index 0000000..fbc8676
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c
@@ -0,0 +1,11 @@
+/* Test _Float64x NaNs in <float.h>. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -fsignaling-nans" } */
+/* { dg-add-options float64x } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target float64x_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-nan-floath.h"
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h b/gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h
new file mode 100644
index 0000000..9892fd0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h
@@ -0,0 +1,36 @@
+/* Tests for _FloatN / _FloatNx types: compile and execution tests for
+ NaNs, SNAN macros in <float.h>. Before including this file, define
+ WIDTH as the value N; define EXT to 1 for _FloatNx and 0 for
+ _FloatN. */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define SNAN CONCAT3 (FLT, WIDTH, X_SNAN)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define SNAN CONCAT3 (FLT, WIDTH, _SNAN)
+#endif
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <fenv.h>
+#include <float.h>
+
+extern void exit (int);
+extern void abort (void);
+
+volatile TYPE nans_cst = SNAN;
+
+int
+main (void)
+{
+ volatile TYPE r;
+ r = nans_cst + nans_cst;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr71816.c b/gcc/testsuite/gcc.dg/torture/pr71816.c
index be37ad9..cc143fa 100644
--- a/gcc/testsuite/gcc.dg/torture/pr71816.c
+++ b/gcc/testsuite/gcc.dg/torture/pr71816.c
@@ -20,3 +20,7 @@ struct ext2_icount_el *insert_icount_el() {
ext2fs_resize_mem(&insert_icount_el_icount_1);
return 0;
}
+
+/* Passing the address of a declared object to realloc triggers
+ -Wfree-nonheap-object unless -flto is used.
+ { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr97559-1.c b/gcc/testsuite/gcc.dg/torture/pr97559-1.c
new file mode 100644
index 0000000..d5de3bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr97559-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int printf (char *, ...);
+
+int a, b, c, d;
+
+void e () {
+ int f = a;
+ if (b) {
+ L1:
+ b = 0;
+ L2:
+ if (c) {
+ if (f)
+ printf("0");
+ goto L1;
+ }
+ }
+ if (d)
+ goto L2;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr97559-2.c b/gcc/testsuite/gcc.dg/torture/pr97559-2.c
new file mode 100644
index 0000000..b512e6d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr97559-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+
+void e() {
+ int f = b;
+ if (a) {
+ L1:
+ a = 0;
+ L2:
+ if (a) {
+ c = b;
+ goto L1;
+ }
+ }
+ if (d)
+ goto L2;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr97812.c b/gcc/testsuite/gcc.dg/torture/pr97812.c
new file mode 100644
index 0000000..4d468ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr97812.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fdisable-tree-evrp" } */
+
+unsigned char c;
+
+int main() {
+volatile short b = 4066;
+ unsigned short bp = b;
+ unsigned d = bp & 2305;
+ signed char e = d;
+ c = e ? : e;
+ if (!d)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr97901.c b/gcc/testsuite/gcc.dg/torture/pr97901.c
new file mode 100644
index 0000000..a6a89ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr97901.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+int a[1], b, *c, *d;
+
+int main() {
+L:
+ d = c;
+ for (b = 0; b < 2; b++)
+ d = &a[0];
+ if (c)
+ goto L;
+ if (*d)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr98117.c b/gcc/testsuite/gcc.dg/torture/pr98117.c
new file mode 100644
index 0000000..f216025
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr98117.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fno-tree-scev-cprop" } */
+
+unsigned char c;
+void __attribute__((noipa))
+e()
+{
+ do
+ {
+ }
+ while (++c);
+}
+int main()
+{
+ e();
+ if (c != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr98191.c b/gcc/testsuite/gcc.dg/torture/pr98191.c
new file mode 100644
index 0000000..7c4a6d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr98191.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-w -Wno-psabi" } */
+
+typedef double v2df __attribute__((vector_size(2*sizeof(double))));
+
+v2df foo (double *y)
+{
+ v2df x = (v2df){ 1.0, 2.0 };
+ x[0] = *y;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr98219-1.c b/gcc/testsuite/gcc.dg/torture/pr98219-1.c
new file mode 100644
index 0000000..89b5aa3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr98219-1.c
@@ -0,0 +1,45 @@
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
+/* { dg-skip-if "PR81210 sp not aligned to 16 bytes" { *-*-darwin* } } */
+/* { dg-options "-muintr -mgeneral-regs-only" } */
+
+#include <x86gprintrin.h>
+
+extern void exit (int);
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
+#define UIRRV 0x12345670
+#define RIP 0x12345671
+#define RFLAGS 0x12345672
+#define RSP 0x12345673
+
+#define STRING(x) XSTRING(x)
+#define XSTRING(x) #x
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) XSTRING (prefix) cname
+
+void
+__attribute__((interrupt, used))
+fn (struct __uintr_frame *frame, uword_t uirrv)
+{
+ if (UIRRV != uirrv)
+ __builtin_abort ();
+ if (RIP != frame->rip)
+ __builtin_abort ();
+ if (RFLAGS != frame->rflags)
+ __builtin_abort ();
+ if (RSP != frame->rsp)
+ __builtin_abort ();
+
+ exit (0);
+}
+
+int
+main ()
+{
+ asm ("push $" STRING (RSP) "; \
+ push $" STRING (RFLAGS) "; \
+ push $" STRING (RIP) "; \
+ push $" STRING (UIRRV) "; \
+ jmp " ASMNAME ("fn"));
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr98219-2.c b/gcc/testsuite/gcc.dg/torture/pr98219-2.c
new file mode 100644
index 0000000..c2f33f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr98219-2.c
@@ -0,0 +1,59 @@
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
+/* { dg-skip-if "PR81210 sp not aligned to 16 bytes" { *-*-darwin* } } */
+/* { dg-options "-muintr -mgeneral-regs-only" } */
+
+#include <x86gprintrin.h>
+
+extern void exit (int);
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+typedef int aligned __attribute__((aligned(64)));
+
+#define UIRRV 0x12345670
+#define RIP 0x12345671
+#define RFLAGS 0x12345672
+#define RSP 0x12345673
+
+#define STRING(x) XSTRING(x)
+#define XSTRING(x) #x
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) XSTRING (prefix) cname
+
+int
+check_int (int *i, int align)
+{
+ *i = 20;
+ if ((((ptrdiff_t) i) & (align - 1)) != 0)
+ __builtin_abort ();
+ return *i;
+}
+
+void
+__attribute__((interrupt, used))
+fn (struct __uintr_frame *frame, uword_t uirrv)
+{
+ aligned i;
+ if (check_int (&i, __alignof__(i)) != i)
+ __builtin_abort ();
+
+ if (UIRRV != uirrv)
+ __builtin_abort ();
+ if (RIP != frame->rip)
+ __builtin_abort ();
+ if (RFLAGS != frame->rflags)
+ __builtin_abort ();
+ if (RSP != frame->rsp)
+ __builtin_abort ();
+
+ exit (0);
+}
+
+int
+main ()
+{
+ asm ("push $" STRING (RSP) "; \
+ push $" STRING (RFLAGS) "; \
+ push $" STRING (RIP) "; \
+ push $" STRING (UIRRV) "; \
+ jmp " ASMNAME ("fn"));
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr98235.c b/gcc/testsuite/gcc.dg/torture/pr98235.c
new file mode 100644
index 0000000..5f59013
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr98235.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fallow-store-data-races" } */
+
+char tcube[3][9];
+int cur_move;
+void perm_cube(void) {
+ int i, j, k, tmp;
+ for (; i < cur_move; i++)
+ while (k-- >= 0)
+ switch (j) {
+ case 0:
+ tmp = tcube[0][6];
+ tcube[2][8] = tcube[0][8];
+ tcube[0][8] = tmp;
+ tmp = tcube[0][5];
+ tcube[0][5] = tcube[1][8];
+ tcube[1][8] = tcube[2][5];
+ tcube[2][5] = tcube[1][2];
+ tcube[1][2] = tcube[2][1];
+ tcube[2][1] = tcube[1][0];
+ tcube[0][6] = tmp;
+ tmp = tcube[0][3];
+ tcube[0][3] = tcube[1][0];
+ tcube[1][0] = tcube[2][3];
+ tcube[2][3] = tcube[1][6];
+ tcube[1][6] = tmp;
+ break;
+ case 5:
+ tmp = tcube[2][0];
+ tcube[2][0] = tcube[2][2];
+ tcube[2][2] = tcube[2][8];
+ tcube[2][3] = tmp;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr98289.c b/gcc/testsuite/gcc.dg/torture/pr98289.c
new file mode 100644
index 0000000..07094a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr98289.c
@@ -0,0 +1,52 @@
+/* PR rtl-optimization/98289 */
+/* { dg-do compile { target freorder } } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+
+int bar (void) __attribute__((cold));
+
+void
+foo (int x)
+{
+ if (x)
+ __builtin_abort ();
+}
+
+void
+baz (int x)
+{
+ if (__builtin_expect (x, 0))
+ {
+ bar ();
+ bar ();
+ bar ();
+ }
+}
+
+void
+qux (int x, int y, int z, int w)
+{
+ if (x || y || z || w)
+ __builtin_abort ();
+}
+
+int
+corge (int x, int y, int z, int w, int u)
+{
+ if (__builtin_expect (x, 0))
+ goto lab;
+ u++;
+ if (__builtin_expect (y, 0))
+ goto lab;
+ u *= 2;
+ if (__builtin_expect (z, 0))
+ goto lab;
+ u |= 42;
+ if (__builtin_expect (w, 0))
+ {
+ lab:;
+ bar ();
+ bar ();
+ if (bar () > 32) goto lab;
+ }
+ return u;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
index 99a5488..85b6806 100644
--- a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
+++ b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
@@ -6,11 +6,14 @@ struct Foo {
int *p;
};
+struct Foo *ff;
+
void __attribute__((noinline))
foo (void *p)
{
struct Foo *f = (struct Foo *)p - 1;
*f->p = 0;
+ ff = f;
}
int bar (void)
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c
index 180fd72..1915b9a 100644
--- a/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c
+++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c
@@ -11,14 +11,14 @@ foo ()
int * p;
int i;
int x[4];
- long unsigned int _1;
- long unsigned int _2;
+ __SIZETYPE__ _1;
+ __SIZETYPE__ _2;
int _7;
__BB(2):
i_3 = 0;
- _1 = (long unsigned int) i_3;
- _2 = _1 * 4ul;
+ _1 = (__SIZETYPE__) i_3;
+ _2 = _1 * _Literal (__SIZETYPE__) 4;
p_4 = _Literal (int *) &x + _2;
__MEM <v4si> ((v4si *)p_4) = _Literal (v4si) { 1, 2, 3, 4 };
_7 = x[0];
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c
index 2c4235f..041d921 100644
--- a/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c
+++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c
@@ -11,14 +11,14 @@ foo ()
int * p;
int i;
int x[4];
- long unsigned int _1;
- long unsigned int _2;
+ __SIZETYPE__ _1;
+ __SIZETYPE__ _2;
int _7;
__BB(2):
i_3 = 0;
- _1 = (long unsigned int) i_3;
- _2 = _1 * 4ul;
+ _1 = (__SIZETYPE__) i_3;
+ _2 = _1 * _Literal (__SIZETYPE__) 4;
p_4 = _Literal (int *) &x + _2;
__MEM <v4si> ((v4si *)p_4) = _Literal (v4si) {};
_7 = x[0];
diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr97461.c b/gcc/testsuite/gcc.dg/tree-prof/pr97461.c
new file mode 100644
index 0000000..213fac9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/pr97461.c
@@ -0,0 +1,64 @@
+/* PR gcov-profile/97461 */
+/* { dg-options "-O2 -ldl" } */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int malloc_depth = 0;
+
+static char memory[128* 1024];
+static size_t memory_p = 0;
+
+void f1(void) {}
+void f2(void) {}
+
+typedef void (*fun_t)(void);
+static const fun_t funs[2] = { f1, f2, };
+
+static void * malloc_impl(size_t size) {
+ void * r = &memory[memory_p];
+ /* The malloc() and calloc() functions return a pointer to the allocated
+ * memory, which is suitably aligned for any built-in type. Use 16
+ * bytes here as the basic alignment requirement for user-defined malloc
+ * and calloc. See PR97594 for the details. */
+ #define ROUND_UP_FOR_16B_ALIGNMENT(x) ((x + 15) & (-16))
+
+ memory_p += ROUND_UP_FOR_16B_ALIGNMENT(size);
+
+ // force TOPN profile
+ funs[size % 2]();
+ return r;
+}
+
+// Override default malloc, check it it get s called recursively
+void * malloc(size_t size) {
+ // Must not be called recursively. Malloc implementation does not support it.
+ if (malloc_depth != 0) __builtin_trap();
+
+ ++malloc_depth;
+ void * r = malloc_impl(size);
+ --malloc_depth;
+ return r;
+}
+
+// Called from gcov
+void *calloc(size_t nmemb, size_t size) {
+ // Must not be called recursively. Malloc implementation does not support it.
+ if (malloc_depth != 0) __builtin_trap();
+
+ ++malloc_depth;
+ void * r = malloc_impl(size * nmemb);
+ memset(r, 0, size * nmemb);
+ --malloc_depth;
+ return r;
+}
+
+void free(void *ptr){}
+
+int main() {
+ void * p = malloc(8);
+ return p != 0 ? 0 : 1;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
index b7471bf..e8b1644 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
@@ -20,6 +20,6 @@ main()
return 0;
}
/* autofdo doesn't support value profiling for now: */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile" { target { ! aarch64*-*-* } } } } */
/* The versioned memset of size 4 should be optimized to an assignment.
- { dg-final-use-not-autofdo { scan-tree-dump "MEM <\[a-z \]+> \\\[\\(void .\\)&a\\\] = 168430090" "optimized" } } */
+ { dg-final-use-not-autofdo { scan-tree-dump "MEM <\[a-z \]+> \\\[\\(void .\\)&a\\\] = 168430090" "optimized" { target { ! aarch64*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c b/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c
index 00c3079..8f747b7 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c
@@ -7,9 +7,13 @@
#ifdef __moxie__
#define REGISTER "2"
#else
+#ifdef __iq2000__
+#define REGISTER "3"
+#else
#define REGISTER "0"
#endif
#endif
+#endif
void baz(void)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c b/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c
index 9e49303..7808634 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c
@@ -8,9 +8,13 @@
#ifdef __moxie__
#define REGISTER "8"
#else
+#ifdef __iq2000__
+#define REGISTER "3"
+#else
#define REGISTER "0"
#endif
#endif
+#endif
void foo (int);
void bar (int);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
index a94d123..0cc03ff 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
@@ -112,17 +112,21 @@ void test_sprintf_c_const (void)
T ( 3, "%1$c%2$c", '1', '2');
/* Verify that a warning is issued for exceeding INT_MAX bytes and
- not otherwise. */
+ not otherwise. In ILP32 the maximum object size is INT_MAX - 1
+ bytes so the calls are diagnosed due to the overflow. */
T (-1, "%*c", INT_MAX - 1, '1');
- T (-1, "%*c", INT_MAX, '1');
- T (-1, "X%*c", INT_MAX - 1, '1');
- T (-1, "X%*c", INT_MAX, '1'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
+ T (-1, "%*c", INT_MAX, '1'); /* { dg-warning "writing a terminating nul past the end " "ilp32" { target ilp32 } } */
+ T (-1, "X%*c", INT_MAX - 1, '1'); /* { dg-warning "writing a terminating nul past the end " "ilp32" { target ilp32 } } */
+ T (-1, "X%*c", INT_MAX, '1'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */
+ /* { dg-warning "directive writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 } */
- T (-1, "%*c%*c", INT_MAX - 1, '1', INT_MAX - 1, '2'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
+ T (-1, "%*c%*c", INT_MAX - 1, '1', INT_MAX - 1, '2'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */
+ /* { dg-warning "directive writing 2147483646 bytes into a region of size 1" "ilp32" { target ilp32 } .-1 } */
T (-1, "%*cX", INT_MAX - 2, '1');
- T (-1, "%*cX", INT_MAX - 1, '1');
- T (-1, "%*cX", INT_MAX, '1'); /* { dg-warning "output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
+ T (-1, "%*cX", INT_MAX - 1, '1'); /* { dg-warning "writing a terminating nul past the end of the destination" "ilp32" { target ilp32 } } */
+ T (-1, "%*cX", INT_MAX, '1'); /* { dg-warning "output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */
+ /* { dg-warning "directive writing 1 byte into a region of size 0" "ilp32" { target ilp32 } .-1 } */
}
/* Verify that no warning is issued for calls that write into a flexible
@@ -288,8 +292,9 @@ void test_sprintf_chk_s_const (void)
/* Verify that output in excess of INT_MAX bytes is diagnosed even
when the size of the destination object is unknown. */
T (-1, "%*s", INT_MAX - 1, "");
- T (-1, "%*s", INT_MAX, "");
- T (-1, "X%*s", INT_MAX, ""); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
+ T (-1, "%*s", INT_MAX, ""); /* { dg-warning "writing a terminating nul past the end" "ilp32" { target ilp32 } } */
+ T (-1, "X%*s", INT_MAX, ""); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */
+ /* { dg-warning "directive writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 } */
/* Multiple directives. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c
index 02072b5..134967d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c
@@ -197,17 +197,21 @@ void test_narrow_string_with_width_and_precision (void)
IR (imax / 9, imax / 8), IR (imax / 7, imax / 6), SR (x, y),
IR (imax / 5, imax / 4), IR (imax / 3, imax / 2), SR (x, y));
- /* The two directives below combined convert to [INT_MAX, INT_MAX + 1].
+ /* The two directives below combined convert to [INT_MAX -1, INT_MAX + 1].
Since the lower end of the range doesn't exceed INT_MAX no warning
is expected. */
T (-1, "%*.*s%*.*s",
- IR (imax - 5, imax - 3), IR (1, 2), SR (x, y),
+ IR (imax - 6, imax - 3), IR (1, 2), SR (x, y),
IR ( 5, 6), IR (3, 4), SR (x, y));
/* The three directives below (the two %s plus the space in between)
combined convert to [INT_MAX + 1, INT_MAX + 2]. Since the lower
- end of the range exceeds INT_MAX a warning is expected. */
- T (-1, "%*.*s %*.*s", /* { dg-warning "INT_MAX" } */
+ end of the range exceeds INT_MAX a warning is expected. In ILP32,
+ the output overflows the maximum object size. */
+ T (-1, "%*.*s %*.*s",
+ /* { dg-warning "INT_MAX" "LP64" { target lp64 } .-1 }
+ { dg-warning "directive writing between 5 and 6 bytes into a region of size between 2 and 4" "ILP32" { target ilp32 } .-2 }
+ */
IR (imax - 5, imax - 3), IR (1, 2), SR (x, y),
IR ( 5, 6), IR (3, 4), SR (x, y));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c
index 6a18f17..2c410b1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c
@@ -117,10 +117,10 @@ void test_width_and_precision_out_of_range (char *d)
{
/* The range here happens to be a property of the compiler, not
one of the target. */
- T ("%9223372036854775808i", 0); /* { dg-warning "width out of range" "first" } */
- /* { dg-warning "exceeds .INT_MAX." "second" { target *-*-* } .-1 } */
- T ("%.9223372036854775808i", 0); /* { dg-warning "precision out of range" "first" } */
- /* { dg-warning "exceeds .INT_MAX." "second" { target *-*-* } .-1 } */
+ T ("%9223372036854775808i", 0); /* { dg-warning "width out of range|exceeds 'INT_MAX'" "first" } */
+ /* { dg-warning "directive writing \\d+ bytes into a region of size \\d+" "" { target ilp32 } .-1 } */
+ T ("%.9223372036854775808i", 0); /* { dg-warning "precision out of range|exceeds 'INT_MAX'" "first" } */
+ /* { dg-warning "directive writing \\d+ bytes into a region of size \\d+" "ilp32" { target ilp32 } .-1 } */
/* The following is diagnosed by -Wformat (disabled here). */
/* T ("%9223372036854775808$i", 0); */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c
new file mode 100644
index 0000000..df46023
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c
@@ -0,0 +1,76 @@
+/* PR middle-end/97373 - missing warning on sprintf into allocated destination
+ { dg-do compile }
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+#include "../range.h"
+
+extern void* alloca (size_t);
+extern void* malloc (size_t);
+
+extern int sprintf (char*, const char*, ...);
+#define sprintf(d, ...) (sprintf (d, __VA_ARGS__), sink (d))
+
+void sink (void*, ...);
+
+void test_alloca_range (void)
+{
+ int n1_2 = UR (1, 2);
+ int n5_9 = UR (5, 9);
+
+ char *d = (char*)alloca (n5_9);
+
+ sprintf (d, "%i", 12345);
+
+ d += n1_2;
+ sprintf (d, "%i", 12345);
+
+ d += n1_2;
+ sprintf (d, "%i", 12345);
+
+ d += n1_2;
+ sprintf (d, "%i", 12345);
+
+ d += n1_2;
+ sprintf (d, "%i", 12345); // { dg-warning "writing a terminating nul past the end of the destination" }
+
+ d += n1_2;
+ sprintf (d, "%i", 12345); // { dg-warning "'%i' directive writing 5 bytes into a region of size 4" }
+}
+
+
+void test_malloc_range (void)
+{
+ int n2_3 = UR (2, 3);
+ int n5_9 = UR (5, 9);
+
+ char *d = (char*)malloc (n5_9);
+
+ sprintf (d, "%i", 12345);
+
+ d += n2_3;
+ sprintf (d, "%i", 12345);
+
+ d += n2_3;
+ sprintf (d, "%i", 12345); // { dg-warning "writing a terminating nul past the end of the destination" }
+
+ d += n2_3;
+ sprintf (d, "%i", 12345); // { dg-warning "'%i' directive writing 5 bytes into a region of size 3" }
+}
+
+
+void test_vla_range (void)
+{
+ int n3_4 = UR (3, 4);
+ int n5_9 = UR (5, 9);
+
+ char vla[n5_9];
+ char *d = vla;
+
+ sprintf (d, "%i", 12345);
+
+ d += n3_4;
+ sprintf (d, "%i", 12345);
+
+ d += n3_4;
+ sprintf (d, "%i", 12345); // { dg-warning "'%i' directive writing 5 bytes into a region of size 3" }
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp20.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp20.c
new file mode 100644
index 0000000..7d4d55f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp20.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void call (void);
+
+void foo (int base)
+{
+ unsigned i;
+
+ // Ranger should be able to remove the (i > 123) comparison.
+ for (i = base; i < 10; i++)
+ if (i > 123)
+ {
+ call ();
+ return;
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "call" "evrp"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp21.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp21.c
new file mode 100644
index 0000000..dae788c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp21.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+extern void vrp_keep (void);
+extern void vrp_kill (void);
+
+void
+f2 (int s, int b)
+{
+ if (s > 4)
+ s = 4;
+ if (s < -16)
+ s = -16;
+ /* s in [-16, 4]. */
+ b = (b & 1) + 1;
+ /* b in range [1, 2]. */
+ b = s << b;
+ /* b in range [-64, 16]. */
+ if (b == -2)
+ vrp_keep ();
+ if (b <= -65)
+ vrp_kill ();
+ if (b >= 17)
+ vrp_kill ();
+}
+
+/* { dg-final { scan-tree-dump-times "vrp_keep \\(" 1 "evrp"} } */
+/* { dg-final { scan-tree-dump-times "vrp_kill \\(" 0 "evrp"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp22.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp22.c
new file mode 100644
index 0000000..3dd47e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp22.c
@@ -0,0 +1,43 @@
+/* See backwards thru casts if the range fits the LHS type. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+extern void kill(int i);
+extern void keep(int i);
+
+void
+foo (int i)
+{
+ if (i >= 10)
+ {
+ if (i <= 100)
+ {
+ /* i has a range of [10, 100] */
+ char c = (char) i;
+ if (c < 30)
+ {
+ /* If we wind back thru the cast with the range of c being [10,29]
+ * from the branch, and recognize that the range of i fits within
+ * a cast to c, then there is no missing information in a cast
+ * back to int. We can use the range calculated for 'c' with 'i'
+ * as well and Ranger should be able to kill the call. */
+ if (i > 29)
+ kill (i);
+ }
+ }
+ /* i has a range of [10, MAX] */
+ char d = (char) i;
+ if (d < 30)
+ {
+ /* Here, a cast to a char and back is NOT equivalent, so we cannot use
+ * the value of d to remove the call. */
+ if (i > 29)
+ keep (i);
+ }
+
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "kill \\(" 0 "evrp"} } */
+/* { dg-final { scan-tree-dump-times "keep \\(" 1 "evrp"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c
new file mode 100644
index 0000000..e5da00b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
+
+int global;
+int foo ();
+
+int main(int argc, char **argv)
+{
+ if (argc == 1)
+ foo ();
+ else if (argc == 2)
+ {
+ global += 1;
+ }
+ else if (argc == 3)
+ {
+ foo ();
+ foo ();
+ }
+ else if (argc == 4)
+ {
+ foo ();
+ }
+ else if (argc == 5)
+ {
+ global = 2;
+ }
+ else
+ global -= 123;
+
+ global -= 12;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-10.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-10.c
new file mode 100644
index 0000000..7b21c99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-10.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
+
+int global;
+int foo ();
+
+int main(int argc, char **argv)
+{
+ if (argc != 1)
+ {
+ if (argc != 2)
+ {
+ if (argc == 3)
+ {
+ foo ();
+ foo ();
+ }
+ else if (argc == 4)
+ {
+ foo ();
+ }
+ else if (argc == 5)
+ {
+ global = 2;
+ }
+ else
+ global -= 123;
+ }
+ else
+ {
+ global += 1;
+ }
+ }
+ else
+ foo ();
+
+
+ global -= 12;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Canonical GIMPLE case clusters: 1 2 3 4 5" "iftoswitch" } } */
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c
new file mode 100644
index 0000000..252bea6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+
+int isMyRandomCharacter(int aChar)
+{
+ return aChar == 0x0001 || aChar == 0x000A ||
+ aChar == 0x000C || aChar == 0x000E ||
+ aChar == 0x0020;
+}
+
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c
new file mode 100644
index 0000000..707e630
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+
+int IsMySuperRandomChar(int aChar)
+{
+ return aChar == 0x0009 || aChar == 0x000A ||
+ aChar == 0x000C || aChar == 0x000D ||
+ aChar == 0x0020 || aChar == 0x0030;
+}
+
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
new file mode 100644
index 0000000..e6dd4be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
+
+int global;
+int foo ();
+
+int main(int argc, char **argv)
+{
+ if (argc == 1)
+ foo ();
+ else if (argc == 2)
+ {
+ global += 1;
+ }
+ else if (argc == 3)
+ {
+ foo ();
+ foo ();
+ }
+ else if (argc == 4)
+ {
+ foo ();
+ }
+ /* This will be removed with EVRP. */
+ else if (argc == 1)
+ {
+ global = 2;
+ }
+ else
+ global -= 123;
+
+ global -= 12;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c
new file mode 100644
index 0000000..ceeae90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+
+int crud (unsigned char c)
+{
+ return (((((((((((int) c == 46) || (int) c == 44)
+ || (int) c == 58) || (int) c == 59) || (int) c == 60)
+ || (int) c == 62) || (int) c == 34) || (int) c == 92)
+ || (int) c == 39) != 0);
+}
+
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
new file mode 100644
index 0000000..b164067
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
+
+int global;
+int foo ();
+
+int main(int argc, char **argv)
+{
+ if (argc >= 1 && argc <= 10)
+ foo ();
+ else if (argc == 12)
+ {
+ global += 1;
+ }
+ else if (argc == 13)
+ {
+ foo ();
+ foo ();
+ }
+ else if (argc == 14)
+ {
+ foo ();
+ }
+ /* This will be removed with EVRP. */
+ else if (argc == 5)
+ {
+ global = 2;
+ }
+ /* This will be removed with EVRP. */
+ else if (argc >= 7 && argc <= 9)
+ {
+ global = 2;
+ }
+
+ else
+ global -= 123;
+
+ global -= 12;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c
new file mode 100644
index 0000000..4a176f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+
+int global;
+
+int foo(int a)
+{
+ int x = 0;
+ for (unsigned i = 0; i < a; i++)
+ {
+ if (a == 2)
+ {
+ global += 123;
+ x = 1;
+ }
+ else if (a == 3)
+ x = 2;
+ else if (a == 10)
+ x = 3;
+ }
+
+ return x;
+}
+
+/* { dg-final { scan-tree-dump-not "Condition chain " "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
new file mode 100644
index 0000000..f4d06fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
+
+int global;
+int global1;
+int global2;
+int global3;
+
+int foo(int a, int b)
+{
+ int x = 0;
+ for (unsigned i = 0; i < a; i++)
+ {
+ if (b == 1)
+ global += 2;
+ else if (a == 2)
+ global = 123;
+ else if (a == 3)
+ global1 = 1234;
+ else if (a == 10)
+ global2 = 12345;
+ else if (a == 1)
+ global2 = 123456;
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c
new file mode 100644
index 0000000..e67198b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c
@@ -0,0 +1,11 @@
+/* PR tree-optimization/88702 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+
+int IsHTMLWhitespace(int aChar) {
+ return aChar == 0x0009 || aChar == 0x000A ||
+ aChar == 0x000C || aChar == 0x000D ||
+ aChar == 0x0020;
+}
+
+/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c b/gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c
new file mode 100644
index 0000000..d71b757
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-tree-ch -w -fdump-tree-loopdone-details" } */
+
+void
+t6 (int qz, int wh)
+{
+ int jl = wh;
+
+ while (1.0 * qz / wh < 1)
+ {
+ qz = wh * (wh + 2);
+
+ while (wh < 1)
+ jl = 0;
+ }
+
+ while (qz < 1)
+ qz = jl * wh;
+}
+
+/* { dg-final { scan-tree-dump-times "Replacing" 2 "loopdone"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-5.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-5.c
new file mode 100644
index 0000000..fde3177
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-5.c
@@ -0,0 +1,27 @@
+/* { dg-options "-O2 -fdump-tree-modref1" } */
+/* { dg-do run } */
+__attribute__ ((noinline))
+void
+copy (int *a, int *b)
+{
+ *a=*b;
+}
+int p, *ptr = &p;
+__attribute__ ((noinline))
+void
+barrier ()
+{
+ asm ("":"=r"(ptr):"0"(ptr));
+}
+int
+main()
+{
+ int a = 1, b = 2;
+ copy (&a,&b);
+ barrier ();
+ *ptr = 1;
+ if (!__builtin_constant_p (b == 2))
+ __builtin_abort ();
+ return 0;
+}
+/* { dg-final { scan-tree-dump "parm 1 flags: nodirectescape" "modref1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
new file mode 100644
index 0000000..fd37066
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
@@ -0,0 +1,11 @@
+/* PR tree-optimization/97690 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-phiopt2" } */
+
+int foo (_Bool d) { return d ? 2 : 0; }
+int bar (_Bool d) { return d ? 1 : 0; }
+int baz (_Bool d) { return d ? -__INT_MAX__ - 1 : 0; }
+int qux (_Bool d) { return d ? 1024 : 0; }
+
+/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */
+/* { dg-final { scan-tree-dump-times " << " 3 "phiopt2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
index 55b4fd0..df4120d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
@@ -5,7 +5,7 @@ void test1(void)
{
int *p = __builtin_malloc (sizeof (int) * 4);
*p++ = 4;
- __builtin_free (p);
+ __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
}
/* Undefined. We can't do anything here. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
index fb8aebf..a93fcaf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
@@ -19,5 +19,5 @@ int ffff(int i)
/* We should not use extra temporaries apart from for i1 + i2. */
-/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "int" 6 "gimple" } } */
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
index 84dfcc9..5c1945b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
@@ -13,5 +13,5 @@ int qqq (int a)
/* We should not use an extra temporary for the result of the
function call. */
-/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "int" 4 "gimple" } } */
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr56719.c b/gcc/testsuite/gcc.dg/tree-ssa/pr56719.c
new file mode 100644
index 0000000..5030b69
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56719.c
@@ -0,0 +1,33 @@
+/* PR tree-optimization/56719 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " > 1023;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " > 2047;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " > 8191;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= 1023;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= 4095;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= 8191;" 1 "optimized" } } */
+
+int
+f1 (int x, int y)
+{
+ return x > 0x3ffU || y > 0x3ffU;
+}
+
+int
+f2 (int x, int y, int z, unsigned w)
+{
+ return x > 0x1fffU || z > 0x7ffU || w > 0x7ffU || y > 0x1fffU;
+}
+
+int
+f3 (int x, int y)
+{
+ return x <= 0x3ffU && y <= 0x3ffU;
+}
+
+int
+f4 (int x, int y, unsigned z, unsigned w)
+{
+ return x <= 0x1fffU && z <= 0xfff && w <= 0xfff && y <= 0x1fffU;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71077.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71077.c
index 4753740..259055f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr71077.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71077.c
@@ -1,5 +1,6 @@
/* PR c++/71077 */
/* { dg-do link { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-require-effective-target lto } */
/* { dg-options "-O3 -flto -march=core-avx2" } */
int *a;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c
new file mode 100644
index 0000000..e9158e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fdump-tree-evrp" } */
+
+struct A{int a,b;};
+inline int*f1(struct A*p){return&p->a;} /* offset of 0. */
+inline int*f2(struct A*p){return&p->b;} /* Offset of non-zero. */
+inline int*g(struct A*p){return(int*)p+1;} /* Always non-zero offet. */
+
+/* Should be able to eliminate all calls to bad(). */
+
+void bad(void);
+
+int
+main()
+{
+ struct A* ptr = 0;
+ struct A addr;
+
+ if (f1 (ptr) != 0)
+ bad();
+ if (f1 (&addr) == 0)
+ bad();
+
+ if (f2 (ptr) == 0)
+ bad();
+ if (f2 (&addr) == 0)
+ bad();
+
+ if (g (ptr) == 0)
+ bad();
+ if (g (&addr) == 0)
+ bad();
+
+}
+
+/* { dg-final { scan-tree-dump-not "bad" "evrp"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c
index 0e61636..ea88407 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c
@@ -1,7 +1,7 @@
/* PR tree-optimization/88676 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-phiopt1" } */
-/* { dg-final { scan-tree-dump-not " = PHI <" "phiopt1" { target le } } } */
+/* { dg-options "-O2 -fdump-tree-phiopt2" } */
+/* { dg-final { scan-tree-dump-not " = PHI <" "phiopt2" { target le } } } */
struct foo1 {
int i:1;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c
new file mode 100644
index 0000000..d52734b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c
@@ -0,0 +1,68 @@
+/* PR tree-optimization/91029 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+int xx;
+
+void f1 (int i, int j)
+{
+ if ((i % j) == 3)
+ {
+ xx = (i < 3);
+ if (xx)
+ kill ();
+ }
+}
+
+void f2 (int i, int j)
+{
+ if ((i % j) > 0)
+ {
+ xx = (i <= 0);
+ if (xx)
+ kill ();
+ }
+}
+
+void f3 (int i, int j)
+{
+ if ((i % j) == -3)
+ {
+ xx = (i > -3);
+ if (xx)
+ kill ();
+ }
+}
+
+void f4 (int i, int j)
+{
+ if ((i % j) < 0)
+ {
+ xx = (i >= 0);
+ if (xx)
+ kill ();
+ }
+}
+
+void f5 (int i, int j)
+{
+ if ((i % j) > 42)
+ {
+ xx = (i <= 42);
+ if (xx)
+ kill ();
+ }
+}
+
+void f6 (int i, int j)
+{
+ if ((i % j) < -124)
+ {
+ xx = (i >= -124);
+ if (xx)
+ kill ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c
new file mode 100644
index 0000000..ad9213a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c
@@ -0,0 +1,98 @@
+/* PR tree-optimization/91029 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+int xx;
+
+void f1 (int i, int j)
+{
+ if ((i % j) == 3)
+ {
+ xx = (j <= 3 && j >= -3);
+ if (xx)
+ kill ();
+ }
+}
+
+void f2 (int i, int j)
+{
+ if ((i % j) > 0)
+ {
+ xx = (j <= 1 && j >= -1);
+ if (xx)
+ kill ();
+ }
+}
+
+void f3 (int i, int j)
+{
+ if ((i % j) == -3)
+ {
+ xx = (j <= 3 && j >= -3);
+ if (xx)
+ kill ();
+ }
+}
+
+void f4 (int i, int j)
+{
+ if ((i % j) < 0)
+ {
+ xx = (j <= 1 && j >= -1);
+ if (xx)
+ kill ();
+ }
+}
+
+void f5 (int i, int j)
+{
+ if ((i % j) > 42)
+ {
+ xx = (j <= 43 && j >= -43);
+ if (xx)
+ kill ();
+ }
+}
+
+void f6 (int i, int j)
+{
+ if ((i % j) < -124)
+ {
+ xx = (j <= 125 && j >= -125);
+ if (xx)
+ kill ();
+ }
+}
+
+void f7 (unsigned int i, unsigned int j)
+{
+ if ((i % j) == 3)
+ {
+ xx = (j <= 3);
+ if (xx)
+ kill ();
+ }
+}
+
+void f8 (unsigned int i, unsigned int j)
+{
+ if ((i % j) > 0)
+ {
+ xx = (j <= 1);
+ if (xx)
+ kill ();
+ }
+}
+
+void f9 (unsigned int i, unsigned int j)
+{
+ if ((i % j) >= 124)
+ {
+ xx = (j <= 124);
+ if (xx)
+ kill ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c
new file mode 100644
index 0000000..5ebd805
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+
+void foo (unsigned int arg)
+{
+ int a = arg - 3;
+ unsigned int b = 4;
+ int x = 0x1 << arg;
+
+ if (a < 0)
+ b = x;
+
+ /* In the fullness of time, we will delete this call. */
+ if (b >= 5)
+ kill ();;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c
new file mode 100644
index 0000000..c9b2878
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+
+void foo (unsigned int arg)
+{
+ unsigned int C000003FE = 4;
+
+ if (arg + 1 < 4) // work for if (arg < 3)
+ C000003FE = 0x1 << arg;
+
+ if (C000003FE >= 5)
+ kill ();
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c
new file mode 100644
index 0000000..e1d2be0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void kill (void);
+
+void foo (unsigned int arg)
+{
+ int a = arg - 3;
+ unsigned int b = 4;
+
+ if (a < 0)
+ {
+ int x = 0x1 << arg;
+ b = x;
+ }
+
+ if (b >= 5)
+ kill ();
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94785.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94785.c
new file mode 100644
index 0000000..9239284
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94785.c
@@ -0,0 +1,36 @@
+/* PR tree-optimization/94785 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " = ABS_EXPR <v_\[0-9]*\\\(D\\\)>;" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " = ABSU_EXPR <v_\[0-9]*\\\(D\\\)>;" 2 "optimized" } } */
+
+int
+f1 (int v)
+{
+ return (1 | -(v < 0)) * v;
+}
+
+unsigned
+f2 (int v)
+{
+ return (1U | -(v < 0)) * v;
+}
+
+int
+f3 (int v)
+{
+ int a = v < 0;
+ int b = -a;
+ int c = 1 | b;
+ return c * v;
+}
+
+unsigned
+f4 (int v)
+{
+ int a = v < 0;
+ int b = -a;
+ unsigned c = b;
+ unsigned d = c | 1;
+ return d * v;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94802-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94802-1.c
new file mode 100644
index 0000000..8175704
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94802-1.c
@@ -0,0 +1,68 @@
+/* PR tree-optimization/94802 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not " = __builtin_clz " "optimized" } } */
+
+__attribute__((noipa)) int
+f1 (int a, int b)
+{
+ return __builtin_clz (a - b) != 0;
+}
+
+__attribute__((noipa)) int
+f2 (int x)
+{
+ return __builtin_clz (x) == 0;
+}
+
+__attribute__((noipa)) int
+f3 (int x)
+{
+ return __builtin_clz (x) != 0;
+}
+
+__attribute__((noipa)) int
+f4 (int a, int b)
+{
+ return __builtin_clz (a - b) == sizeof (int) * __CHAR_BIT__ - 1;
+}
+
+__attribute__((noipa)) int
+f5 (int x)
+{
+ return __builtin_clz (x) == sizeof (int) * __CHAR_BIT__ - 1;
+}
+
+__attribute__((noipa)) int
+f6 (int x)
+{
+ return __builtin_clz (x) != sizeof (int) * __CHAR_BIT__ - 1;
+}
+
+int
+main ()
+{
+ if (f1 (5, 7) != 0
+ || f1 (7, 5) != 1
+ || f2 (1) != 0
+ || f2 (137) != 0
+ || f2 (-1) != 1
+ || f2 (-137) != 1
+ || f3 (1) != 1
+ || f3 (137) != 1
+ || f3 (-1) != 0
+ || f3 (-137) != 0
+ || f4 (5, 4) != 1
+ || f4 (6, 4) != 0
+ || f4 (4, 5) != 0
+ || f5 (1) != 1
+ || f5 (17) != 0
+ || f5 (-1) != 0
+ || f5 (-17) != 0
+ || f6 (1) != 0
+ || f6 (17) != 1
+ || f6 (-1) != 1
+ || f6 (-17) != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96094.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96094.c
new file mode 100644
index 0000000..fe9163d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96094.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/96094 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 34;" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return y_\[0-9]*\\\(D\\\);" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return \[^\n\r;]*;" 4 "optimized" } } */
+
+int
+foo (int x)
+{
+ if (x >= 2U)
+ return 34;
+ return 34 / x;
+}
+
+int
+bar (int x, int y)
+{
+ if (x >= 2U)
+ return y;
+ return y / x;
+}
+
+int
+baz (_Bool x)
+{
+ return 34 / x;
+}
+
+int
+qux (_Bool x, int y)
+{
+ return y / x;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96232-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96232-1.c
new file mode 100644
index 0000000..3170ffd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96232-1.c
@@ -0,0 +1,11 @@
+/* PR tree-optimization/96232 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " \\+ -1;" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "~x_\[0-9]*\\\(D\\\)" "optimized" } } */
+
+int
+foo (_Bool x)
+{
+ return x ? 0 : -1;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c
new file mode 100644
index 0000000..9f51820
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c
@@ -0,0 +1,18 @@
+/* PR tree-optimization/96232 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " 38 - " "optimized" } } */
+/* { dg-final { scan-tree-dump " \\+ 97;" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "PHI <" "optimized" } } */
+
+int
+foo (_Bool x)
+{
+ return x ? 37 : 38;
+}
+
+int
+bar (_Bool x)
+{
+ return x ? 98 : 97;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96272.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96272.c
new file mode 100644
index 0000000..4c9fa63
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96272.c
@@ -0,0 +1,37 @@
+/* PR tree-optimization/96272 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-widening_mul" } */
+
+unsigned
+foo (unsigned a, unsigned b)
+{
+ if (a > ~0U - b)
+ return ~0U;
+ return a + b;
+}
+
+unsigned
+bar (unsigned a, unsigned b)
+{
+ if (a <= ~0U - b)
+ return ~0U;
+ return a + b;
+}
+
+unsigned
+baz (unsigned a, unsigned b)
+{
+ if (~0U - b < a)
+ return ~0U;
+ return a + b;
+}
+
+unsigned
+qux (unsigned a, unsigned b)
+{
+ if (~0U - b >= a)
+ return ~0U;
+ return a + b;
+}
+
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 4 "widening_mul" { target { i?86-*-* x86_64-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c
index f2a91ef..fc2103d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/96480 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-bit-tests -fno-jump-tables" } */
/* { dg-final { scan-tree-dump " = _\[0-9]* <= 3;" "optimized" } } */
int v[4];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96685-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96685-1.c
new file mode 100644
index 0000000..eb3b1ea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96685-1.c
@@ -0,0 +1,52 @@
+/* PR tree-optimization/96685 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 6 "optimized" } } */
+
+unsigned
+f1 (unsigned x, unsigned y)
+{
+ unsigned a = ~(x - y);
+ unsigned b = ~x + y;
+ return a == b;
+}
+
+unsigned
+f2 (unsigned x)
+{
+ unsigned a = ~(x + -124U);
+ unsigned b = ~x + 124U;
+ return a == b;
+}
+
+unsigned
+f3 (unsigned x)
+{
+ unsigned a = ~(x + 124U);
+ unsigned b = ~x + -124U;
+ return a == b;
+}
+
+int
+f4 (int x, int y)
+{
+ int a = ~(x - y);
+ int b = ~x + y;
+ return a == b;
+}
+
+int
+f5 (int x)
+{
+ int a = ~(x + -124);
+ int b = ~x + 124;
+ return a == b;
+}
+
+int
+f6 (int x)
+{
+ int a = ~(x + 124);
+ int b = ~x + -124;
+ return a == b;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96685-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96685-2.c
new file mode 100644
index 0000000..e3c1ac7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96685-2.c
@@ -0,0 +1,40 @@
+/* PR tree-optimization/96685 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" } } */
+
+int
+f1 (unsigned x, unsigned y)
+{
+ unsigned int r1 = (x - y);
+ r1 = ~r1;
+ unsigned int r2 = ~(x - y);
+ return r1 == r2;
+}
+
+int
+f2 (unsigned x, unsigned y)
+{
+ unsigned int r1 = (x - 23);
+ r1 = ~r1;
+ unsigned int r2 = ~(x - 23);
+ return r1 == r2;
+}
+
+int
+f3 (int x, int y)
+{
+ int r1 = (x - y);
+ r1 = ~r1;
+ int r2 = ~(x - y);
+ return r1 == r2;
+}
+
+int
+f4 (int x, int y)
+{
+ int r1 = (x - 23);
+ r1 = ~r1;
+ int r2 = ~(x - 23);
+ return r1 == r2;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96685-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96685-3.c
new file mode 100644
index 0000000..b3c1855
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96685-3.c
@@ -0,0 +1,43 @@
+/* PR tree-optimization/96685 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" } } */
+
+int
+f1 (unsigned x, unsigned y)
+{
+ unsigned int r1 = (x - y);
+ r1 = ~r1;
+ unsigned int r2 = (y - x);
+ r2 = r2 - 1;
+ return r1 == r2;
+}
+
+int
+f2 (unsigned x, unsigned y)
+{
+ unsigned int r1 = (x - 23);
+ r1 = ~r1;
+ unsigned int r2 = (23 - x);
+ r2 = r2 - 1;
+ return r1 == r2;
+}
+
+int
+f3 (int x, int y)
+{
+ int r1 = (x - 23);
+ r1 = ~r1;
+ int r2 = (23 - x);
+ --r2;
+ return r1 == r2;
+}
+
+int
+f4 (int x, int y)
+{
+ int r1 = (x - 23);
+ r1 = ~r1;
+ int r2 = (22 - x);
+ return r1 == r2;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c
new file mode 100644
index 0000000..5704952
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* Disable loop vectorization to avoid that loop vectorizer
+ optimizes those two loops that operate tmp array so that
+ subsequent dse3 won't eliminate expected tmp stores. */
+/* { dg-options "-O2 -funroll-loops -ftree-slp-vectorize -fno-tree-loop-vectorize -fdump-tree-dse-details" } */
+
+/* Test if scalar cleanup pass takes effects, mainly check
+ its secondary pass DSE can remove dead stores on array
+ tmp. */
+
+#include "stdint.h"
+
+static inline void
+foo (int16_t *diff, int i_size, uint8_t *val1, int i_val1, uint8_t *val2,
+ int i_val2)
+{
+ for (int y = 0; y < i_size; y++)
+ {
+ for (int x = 0; x < i_size; x++)
+ diff[x + y * i_size] = val1[x] - val2[x];
+ val1 += i_val1;
+ val2 += i_val2;
+ }
+}
+
+void
+bar (int16_t res[16], uint8_t *val1, uint8_t *val2)
+{
+ int16_t d[16];
+ int16_t tmp[16];
+
+ foo (d, 4, val1, 16, val2, 32);
+
+ for (int i = 0; i < 4; i++)
+ {
+ int s03 = d[i * 4 + 0] + d[i * 4 + 3];
+ int s12 = d[i * 4 + 1] + d[i * 4 + 2];
+ int d03 = d[i * 4 + 0] - d[i * 4 + 3];
+ int d12 = d[i * 4 + 1] - d[i * 4 + 2];
+
+ tmp[0 * 4 + i] = s03 + s12;
+ tmp[1 * 4 + i] = 2 * d03 + d12;
+ tmp[2 * 4 + i] = s03 - s12;
+ tmp[3 * 4 + i] = d03 - 2 * d12;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ int s03 = tmp[i * 4 + 0] + tmp[i * 4 + 3];
+ int s12 = tmp[i * 4 + 1] + tmp[i * 4 + 2];
+ int d03 = tmp[i * 4 + 0] - tmp[i * 4 + 3];
+ int d12 = tmp[i * 4 + 1] - tmp[i * 4 + 2];
+
+ res[i * 4 + 0] = s03 + s12;
+ res[i * 4 + 1] = 2 * d03 + d12;
+ res[i * 4 + 2] = s03 - s12;
+ res[i * 4 + 3] = d03 - 2 * d12;
+ }
+}
+
+/* { dg-final { scan-tree-dump {Deleted dead store:.*tmp} "dse3" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96929.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96929.c
new file mode 100644
index 0000000..65b6147
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96929.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/96929 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump "baz \\\(\\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return -1;" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " >> " "optimized" } } */
+
+int baz (void);
+
+int
+foo (void)
+{
+ return -1 >> baz ();
+}
+
+int
+bar (int y)
+{
+ int z = -1;
+ return z >> y;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97849.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97849.c
new file mode 100644
index 0000000..57a31e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97849.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftree-vectorize" } */
+/* { dg-additional-options "-march=armv8.2-a+sve" { target aarch64*-*-* } } */
+
+int a, b, c;
+
+int g() {
+ char i = 0;
+ for (c = 0; c <= 8; c++)
+ --i;
+
+ while (b) {
+ _Bool f = i <= 0;
+ a = (a == 0) ? 0 : f / a;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97964.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97964.c
new file mode 100644
index 0000000..0ee0196
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97964.c
@@ -0,0 +1,18 @@
+/* PR tree-optimization/97964 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "link_failure \\\(\\\);" "optimized" } } */
+
+void link_failure (void);
+
+void
+foo (int a)
+{
+ long b = -2;
+ int c = a > 0;
+ int d = b * c;
+ int e = 1 - d;
+ int t = (-1 / e) == 1;
+ if (t != 0)
+ link_failure ();
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c
new file mode 100644
index 0000000..3c4b468
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c
@@ -0,0 +1,52 @@
+/* PR tree-optimization/97997 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return x_\[0-9]*\\\(D\\\);" 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */
+
+unsigned short
+f1 (unsigned short x)
+{
+ return x * 10 / 10;
+}
+
+unsigned short
+f2 (unsigned short x)
+{
+ int a = x;
+ int b = 10;
+ int c = 10;
+ return a * b / c;
+}
+
+unsigned short
+f3 (unsigned short x)
+{
+ return x * 10U / 10;
+}
+
+unsigned short
+f4 (unsigned short x)
+{
+ unsigned a = x;
+ unsigned b = 10;
+ unsigned c = 10;
+ return a * b / c;
+}
+
+unsigned short
+f5 (unsigned short x, unsigned short y)
+{
+ return (unsigned) x * y / y;
+}
+
+unsigned int
+f6 (unsigned int x, unsigned int y)
+{
+ if (x >= 30000)
+ __builtin_unreachable ();
+ if (y >= ~0U / 30000)
+ __builtin_unreachable ();
+ return x * y / y;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c
new file mode 100644
index 0000000..a9d5075
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c
@@ -0,0 +1,41 @@
+/* PR tree-optimization/97997 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized -fwrapv" } */
+/* { dg-final { scan-tree-dump-times "return x_\[0-9]*\\\(D\\\);" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */
+
+unsigned short
+f1 (unsigned short x)
+{
+ return x * 10 / 10;
+}
+
+unsigned short
+f2 (unsigned short x)
+{
+ int a = x;
+ int b = 10;
+ int c = 10;
+ return a * b / c;
+}
+
+short
+f3 (short x, short y)
+{
+ return x * y / y;
+}
+
+int
+f4 (int x, int y)
+{
+ if (x >= 30000)
+ __builtin_unreachable ();
+ if (x <= -30000)
+ __builtin_unreachable ();
+ if (y >= __INT_MAX__ / 30000)
+ __builtin_unreachable ();
+ if (y <= -__INT_MAX__ / 30000)
+ __builtin_unreachable ();
+ return x * y / y;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98084.c b/gcc/testsuite/gcc.dg/tree-ssa/pr98084.c
new file mode 100644
index 0000000..6379624
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98084.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/98084 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+enum {
+ JSON_VARIANT_STRING,
+ JSON_VARIANT_UNSIGNED,
+ JSON_VARIANT_REAL,
+ JSON_VARIANT_ARRAY,
+ _JSON_VARIANT_TYPE_INVALID,
+ _JSON_VARIANT_MAGIC_ZERO_UNSIGNED,
+ _JSON_VARIANT_MAGIC_ZERO_REAL,
+ _JSON_VARIANT_MAGIC_EMPTY_STRING,
+ _JSON_VARIANT_MAGIC_EMPTY_ARRAY
+} json_variant_type(int *v) {
+ if (!v)
+ return _JSON_VARIANT_TYPE_INVALID;
+ if (v == (int *)_JSON_VARIANT_MAGIC_ZERO_UNSIGNED)
+ return JSON_VARIANT_UNSIGNED;
+ if (v == (int *)_JSON_VARIANT_MAGIC_ZERO_REAL)
+ return JSON_VARIANT_REAL;
+ if (v == (int *)_JSON_VARIANT_MAGIC_EMPTY_STRING)
+ return JSON_VARIANT_STRING;
+ if (v == (int *)_JSON_VARIANT_MAGIC_EMPTY_ARRAY)
+ return JSON_VARIANT_ARRAY;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98094.c b/gcc/testsuite/gcc.dg/tree-ssa/pr98094.c
new file mode 100644
index 0000000..f88534a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98094.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/98084 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct
+{
+ unsigned a : 10;
+} b;
+
+int c;
+void e();
+void d ()
+{
+ c = b.a;
+ if (c == 8 || c == 0)
+ ;
+ else if (c > 8 * 8)
+ ;
+ else if (c < 8 * 8)
+ e ();
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98182.c b/gcc/testsuite/gcc.dg/tree-ssa/pr98182.c
new file mode 100644
index 0000000..29a547e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98182.c
@@ -0,0 +1,18 @@
+/* PR tree-optimization/98182 */
+/* { dg-do compile } */
+/* { dg-options "-O1 --param case-values-threshold=1 -fdump-tree-iftoswitch-optimized" } */
+
+int global;
+int foo ();
+
+int main(int argc, char **argv)
+{
+ if (argc != 1)
+ __builtin_abort ();
+ else if (argc != 2)
+ __builtin_abort ();
+ else
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c
index 944362a..093e7a5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c
@@ -1,6 +1,6 @@
/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
-/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1" } */
+/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1 -fno-bit-tests" } */
/* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
index 585b660..479f40f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
@@ -23,7 +23,7 @@ f (int s, int *c, int *d)
However, this proves to be a useful test for introducing an
initializer with a cast, so we'll keep it as is. */
-/* There are 4 ' * ' instances in the decls (since "int * iftmp.0;" is
- added), 2 parms, 3 in the code. The second one in the code may
- be a widening multiply (for example, on AArch64). */
-/* { dg-final { scan-tree-dump-times " w?\\* " 9 "optimized" } } */
+/* There are 5 ' * ' instances in the decls (since "int * iftmp.0;" is
+ added), 2 parms, 3 in the code, and the return value. The second one
+ in the code may be a widening multiply (for example, on AArch64). */
+/* { dg-final { scan-tree-dump-times " w?\\* " 10 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c
index 36b8e7f..d70ea5a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
/* Test for CPROP across a DAG. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c
index d3a1bbc..b81cabe 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-28.c
@@ -17,5 +17,5 @@ int foo (int *p, int b)
/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse1"} } */
/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse2"} } */
-/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse3"} } */
+/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse4"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c
index 31529e7..f4ef89c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c
@@ -22,5 +22,5 @@ foo(int cond, struct z *s)
/* { dg-final { scan-tree-dump-times "Deleted dead store" 3 "dse1"} } */
/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse2"} } */
-/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse3"} } */
+/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse4"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c
index 51ba59c..de3051b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c
@@ -15,4 +15,4 @@ int test (int a, int b, int c, int g)
/* We should hoist and CSE only the multiplication. */
/* { dg-final { scan-tree-dump-times " \\* " 1 "pre" } } */
-/* { dg-final { scan-tree-dump "Insertions: 1" "pre" } } */
+/* { dg-final { scan-tree-dump "HOIST inserted: 1" "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c
new file mode 100644
index 0000000..fdb6a3e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c
@@ -0,0 +1,54 @@
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+
+void baz();
+int tem;
+void foo (int a, int b, int c, int d, int e, int x, int y, int z)
+{
+ if (a)
+ {
+ if (b)
+ {
+ if (c)
+ {
+ if (d)
+ {
+ if (e)
+ {
+ tem = x + y;
+ }
+ else
+ {
+ if (z) baz ();
+ tem = x + y;
+ }
+ }
+ else
+ {
+ if (z) baz ();
+ tem = x + y;
+ }
+ }
+ else
+ {
+ if (z) baz ();
+ tem = x + y;
+ }
+ }
+ else
+ {
+ if (z) baz ();
+ tem = x + y;
+ }
+ }
+ else
+ {
+ if (z) baz ();
+ tem = x + y;
+ }
+}
+
+/* Now inserting x + y five times is unnecessary but the cascading
+ cannot be avoided with the simple-minded dataflow. But make sure
+ we do not iterate PRE insertion. */
+/* { dg-final { scan-tree-dump "insert iterations == 1" "pre" } } */
+/* { dg-final { scan-tree-dump "HOIST inserted: 5" "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c
index 59af63a..cf93173 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c
@@ -24,4 +24,4 @@ bar (int b, int x)
/* We should see the partial redundant loads of f even though they
are using different types (of the same size). */
-/* { dg-final { scan-tree-dump-times "Replaced MEM" 2 "pre" } } */
+/* { dg-final { scan-tree-dump-times "Replaced MEM" 3 "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c
index 149687c..6f70c9d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c
@@ -54,7 +54,7 @@ int foo3 (int x)
}
}
-/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: JT:0-62" "switchlower1" } } */
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:0-62" "switchlower1" } } */
int foo4 (int x)
{
@@ -77,7 +77,7 @@ int foo4 (int x)
}
}
-/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: -100 JT:10-62 600-700" "switchlower1" } } */
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: -100 BT:10-62 600-700" "switchlower1" } } */
int foo5 (int x)
{
@@ -107,4 +107,4 @@ int foo5 (int x)
}
}
-/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: JT:10-62 600-700 JT:1000-1021 111111" "switchlower1" } } */
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:10-62 600-700 JT:1000-1021 111111" "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-4.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-4.c
new file mode 100644
index 0000000..5953ef3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-4.c
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { { x86_64-*-* aarch64-*-* ia64-*-* powerpc64-*-* } && lp64 } } } */
+/* { dg-options "-O2 -fno-bit-tests -fdump-tree-switchlower1" } */
+
+int global;
+
+int foo (int x)
+{
+ switch (x) {
+ case 0:
+ case 10:
+ return 1;
+ case 20:
+ case 30:
+ case 62:
+ return 2;
+ case 1000:
+ case 1010:
+ case 1025 ... 1030:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "BT:" "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tsan/atomic-fence.c b/gcc/testsuite/gcc.dg/tsan/atomic-fence.c
new file mode 100644
index 0000000..013720c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tsan/atomic-fence.c
@@ -0,0 +1,11 @@
+/* PR sanitizer/97868 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=thread" } */
+
+int
+main ()
+{
+ __atomic_thread_fence (__ATOMIC_RELAXED); /* { dg-warning ".atomic_thread_fence. is not supported with .-fsanitize=thread." } */
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/typeof-2.c b/gcc/testsuite/gcc.dg/typeof-2.c
index 21ef5b0..68f91c6 100644
--- a/gcc/testsuite/gcc.dg/typeof-2.c
+++ b/gcc/testsuite/gcc.dg/typeof-2.c
@@ -1,21 +1,23 @@
-/* Test qualifier discard of typeof for atomic types. */
+/* Test qualifier preservation of typeof and discarded for __auto_type. */
/* { dg-do compile } */
/* { dg-options "-std=c11" } */
-/* Check that the qualifiers are discarded for atomic types. */
+/* Check that the qualifiers are preserved for atomic types. */
extern int i;
extern int * p;
extern int _Atomic const ci;
-extern __typeof (ci) i;
+extern __typeof (ci) ci;
extern int _Atomic volatile vi;
-extern __typeof (vi) i;
+extern __typeof (vi) vi;
extern int * _Atomic restrict ri;
-extern __typeof (ri) p;
+extern __typeof (ri) ri;
+
+/* Check that the qualifiers are discarded for atomic types. */
void f(void)
{
@@ -46,14 +48,16 @@ extern __typeof (nvi) k;
extern int * restrict nri;
extern __typeof (nri) q;
+/* Check that the qualifiers are discarded for non-atomic types. */
+
void g(void)
{
__auto_type aci = nci;
- int const *paci = &aci;
+ int *paci = &aci;
__auto_type avi = nvi;
- int volatile *pavi = &avi;
+ int *pavi = &avi;
__auto_type ari = nri;
- int * restrict *pari = &ari;
+ int **pari = &ari;
}
diff --git a/gcc/testsuite/gcc.dg/unused-9.c b/gcc/testsuite/gcc.dg/unused-9.c
new file mode 100644
index 0000000..bdf36e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unused-9.c
@@ -0,0 +1,13 @@
+/* PR c/98260 */
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+
+void g(void)
+{
+ int i = 0;
+ volatile int x;
+ (x, i++); /* { dg-bogus "set but not used" } */
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c
index f8c36a8..24b2fa8 100644
--- a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c
+++ b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c
@@ -30,4 +30,4 @@ int *foo(void)
return &c[0][0];
}
-/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" } } */
+/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" { xfail vect_element_align_preferred } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-41.c b/gcc/testsuite/gcc.dg/vect/bb-slp-41.c
index 7de5ed1..7224511 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-41.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-41.c
@@ -10,7 +10,10 @@ foo (int *a, int *b)
a[i] = b[0] + b[1] + b[i+1] + b[i+2];
}
-void bar (int *a, int *b)
+/* Disable pre-slp FRE to avoid unexpected SLP on the epilogue
+ of the 1st loop. */
+void __attribute__((optimize("-fno-tree-fre")))
+bar (int *a, int *b)
{
int i;
for (i = 0; i < (ARR_SIZE - 2); ++i)
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-43.c b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c
index a65d951..40bd2e0 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-43.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c
@@ -14,4 +14,4 @@ f (int *restrict x, short *restrict y)
}
/* { dg-final { scan-tree-dump-not "mixed mask and nonmask" "slp2" } } */
-/* { dg-final { scan-tree-dump-not "vector operands from scalars" "slp2" { target { { vect_int && vect_bool_cmp } && { vect_unpack && vect_hw_misalign } } xfail vect_variable_length } } } */
+/* { dg-final { scan-tree-dump-not "vector operands from scalars" "slp2" { target { { vect_int && vect_bool_cmp } && { vect_unpack && vect_hw_misalign } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-54.c b/gcc/testsuite/gcc.dg/vect/bb-slp-54.c
new file mode 100644
index 0000000..d05ce33
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-54.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+
+double a[2], b[2], c[2];
+
+void foo(int flag)
+{
+ double tem1, tem2;
+ if (flag)
+ {
+ tem1 = a[0];
+ tem2 = a[1];
+ }
+ else
+ {
+ tem1 = b[0];
+ tem2 = b[1];
+ }
+ c[0] = tem1;
+ c[1] = tem2;
+}
+
+/* { dg-final { scan-tree-dump-times "transform load" 2 "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-55.c b/gcc/testsuite/gcc.dg/vect/bb-slp-55.c
new file mode 100644
index 0000000..57a042b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-55.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+typedef struct {
+ int a;
+ int b;
+ int c;
+ int d;
+} e;
+e *f;
+int g;
+void h() {
+ e *i;
+ if (g) {
+ i->c = f[g].b;
+ i->d = f[g].a;
+ } else
+ i->c = i->d = 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-56.c b/gcc/testsuite/gcc.dg/vect/bb-slp-56.c
new file mode 100644
index 0000000..90d1751
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-56.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+typedef struct {
+ double a, b;
+} c;
+int d, e;
+int i(void);
+void h(c, c);
+void f() {
+ c a, g;
+ do {
+ a.a = e ?: g.a;
+ a.b = g.b + d;
+ h(g, a);
+ g = a;
+ } while (i());
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-57.c b/gcc/testsuite/gcc.dg/vect/bb-slp-57.c
new file mode 100644
index 0000000..6f13507
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-57.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ffast-math" } */
+/* { dg-require-effective-target vect_float } */
+
+float *a;
+typedef struct {
+ int c;
+ float bbmax[3];
+} d;
+d e;
+int f[3];
+int g, h, i, j;
+float k, k;
+void l()
+{
+ for (unsigned z = 0; z < 2048; ++z) {
+ {
+ j = e.bbmax[1] > k ? e.bbmax[1] : k;
+ }
+ e.bbmax[1] = j;
+ { i = e.bbmax[2] > k ? e.bbmax[2] : k; }
+ e.bbmax[2] = i;
+ f[2] = a[2];
+ {
+ float b;
+ h = e.bbmax[1] > b ? e.bbmax[1] : b;
+ }
+ e.bbmax[1] = h;
+ {
+ float b;
+ g = e.bbmax[2] > b ? e.bbmax[2] : b;
+ }
+ e.bbmax[2] = g;
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "transform load" 1 "slp1" { target { { x86_64-*-* i?86-*-* } && lp64 } } } } */
+/* { dg-final { scan-tree-dump "optimized: basic block" "slp1" { target { { x86_64-*-* i?86-*-* } && lp64 } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-58.c b/gcc/testsuite/gcc.dg/vect/bb-slp-58.c
new file mode 100644
index 0000000..5a3d3b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-58.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+
+double x[1024];
+void bar (void);
+
+void foo (void)
+{
+ double tem1 = x[0];
+ double tem2 = x[1];
+ for (int i = 0; i < 511; ++i)
+ {
+ x[2*i] = tem1;
+ x[2*i+1] = tem2;
+ bar ();
+ tem1 = x[2*(i+1)];
+ tem2 = x[2*(i+1)+1];
+ }
+}
+
+/* We should be able to vectorize the cycle in one SLP attempt including
+ both load groups. */
+/* { dg-final { scan-tree-dump-times "transform load" 2 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-59.c b/gcc/testsuite/gcc.dg/vect/bb-slp-59.c
new file mode 100644
index 0000000..815b44e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-59.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-fdump-tree-loopdone" } */
+
+double x[1024];
+void bar (void);
+
+void foo (void)
+{
+ double tem1 = x[0];
+ double tem2 = x[1];
+ for (int i = 0; i < 511; ++i)
+ {
+ x[2*i] = tem2;
+ x[2*i+1] = tem1;
+ bar ();
+ tem1 = x[2*(i+1)];
+ tem2 = x[2*(i+1)+1];
+ }
+}
+
+/* We should be able to vectorize the cycle in one SLP attempt including
+ both load groups and do only one permutation. */
+/* { dg-final { scan-tree-dump-times "transform load" 2 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "loopdone" } } */
+/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-60.c b/gcc/testsuite/gcc.dg/vect/bb-slp-60.c
new file mode 100644
index 0000000..52643bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-60.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+enum { a = 1, b };
+float *c, *e;
+float d, h;
+int f, g;
+void i()
+{
+ float j = h;
+ for (; g;)
+ for (; f; f++)
+ {
+ c[a] = j * d;
+ c[b] = h * d;
+ j = 0;
+ h = e[2];
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-61.c b/gcc/testsuite/gcc.dg/vect/bb-slp-61.c
new file mode 100644
index 0000000..3323a2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-61.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+struct a {
+ enum { b, c } d;
+ unsigned e;
+ unsigned f;
+};
+void j(struct a *a, int i, int h)
+{
+ unsigned f = a->f;
+ switch (a->d)
+ while (1)
+ {
+ if (i)
+ {
+ case b:
+ if (h)
+ goto k;
+ }
+ else
+ f = 0;
+ case c:;
+ }
+k:
+ a->e = a->f = f;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-62.c b/gcc/testsuite/gcc.dg/vect/bb-slp-62.c
new file mode 100644
index 0000000..84ee04c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-62.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+typedef struct {
+ char a;
+ int b[];
+} c;
+int d, f;
+c e;
+void g() {
+ int h, i, j;
+ for (; i;)
+ switch (i)
+ case 4: {
+ h = (__UINTPTR_TYPE__)g >= 3;
+ for (; h; h -= 1)
+ if (d)
+ j = f;
+ }
+ for (; i < 3; i++)
+ e.b[i] = j;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-63.c b/gcc/testsuite/gcc.dg/vect/bb-slp-63.c
new file mode 100644
index 0000000..6519c97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-63.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+struct {
+ unsigned a;
+ unsigned c;
+} d;
+int e, g;
+void h(unsigned b) {
+ unsigned a, c;
+ while (e) {
+ if (b) {
+ ++e;
+ continue;
+ }
+ c = g;
+ if (g)
+ a |= 10;
+ }
+ d.a = a;
+ d.c = c;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-64.c b/gcc/testsuite/gcc.dg/vect/bb-slp-64.c
new file mode 100644
index 0000000..dcb6a14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-64.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+enum { a, b };
+double *c, *e;
+int d, f;
+void g() {
+ for (;;) {
+ c[a] = c[b] = d * e[b];
+ f = d -= f;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-65.c b/gcc/testsuite/gcc.dg/vect/bb-slp-65.c
new file mode 100644
index 0000000..ec1707b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-65.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+/* { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } } */
+
+int *a;
+int b, c, d, e;
+void f() {
+ int g;
+ for (;;)
+ for (; b;)
+ if (d)
+ for (; c;)
+ if (g)
+ e += a[1] = a[2] = e;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-66.c b/gcc/testsuite/gcc.dg/vect/bb-slp-66.c
new file mode 100644
index 0000000..b59a2cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-66.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef struct {
+ double a, b;
+} c;
+typedef struct {
+ c d;
+ long coordinates;
+} e;
+int f;
+c g;
+e h;
+void k(int);
+int n();
+void j() { int i; k(i); }
+void k(int l) {
+ double a;
+ int b;
+ c m[4];
+ long i;
+ for (; l;)
+ do {
+ g.a = b ?: a;
+ m[3] = g;
+ if (f)
+ m[0] = m[1] = m[3];
+ i = 0;
+ for (; i < 4; i++)
+ (&h + i)->d = m[i];
+ } while (n());
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-67.c b/gcc/testsuite/gcc.dg/vect/bb-slp-67.c
new file mode 100644
index 0000000..ff959c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-67.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+
+float a[6];
+
+void foo (float x, float y)
+{
+ a[0] = 1.;
+ a[1] = 2.;
+ a[2] = 3.;
+ a[3] = 4.;
+ a[4] = 5.;
+ a[5] = x + y;
+}
+
+/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-68.c b/gcc/testsuite/gcc.dg/vect/bb-slp-68.c
new file mode 100644
index 0000000..8718031
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-68.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-mavx" { target avx } } */
+
+double x[10], y[6], z[4];
+
+void foo ()
+{
+ x[0] = y[0];
+ x[1] = y[1];
+ x[2] = y[2];
+ x[3] = y[3];
+ x[4] = y[4];
+ x[5] = y[5];
+ x[6] = z[0] + 1.;
+ x[7] = z[1] + 1.;
+ x[8] = z[2] + 1.;
+ x[9] = z[3] + 1.;
+}
+
+/* We want to have the store group split into 4, 2, 4 when using 32byte vectors. */
+/* { dg-final { scan-tree-dump-not "from scalars" "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-69.c b/gcc/testsuite/gcc.dg/vect/bb-slp-69.c
new file mode 100644
index 0000000..16c0d74
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-69.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_condition } */
+
+_Bool arr[16];
+
+void foo(char *q)
+{
+ char *p = __builtin_assume_aligned (q, 16);
+ _Bool b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;
+ b0 = p[0] != 0;
+ b1 = p[1] != 0;
+ b2 = p[2] != 0;
+ b3 = p[3] != 0;
+ b4 = p[4] != 0;
+ b5 = p[5] != 0;
+ b6 = p[6] != 0;
+ b7 = p[7] != 0;
+ b8 = p[8] != 0;
+ b9 = p[9] != 0;
+ b10 = p[10] != 0;
+ b11 = p[11] != 0;
+ b12 = p[12] != 0;
+ b13 = p[13] != 0;
+ b14 = p[14] != 0;
+ b15 = p[15] != 0;
+ arr[0] = b0;
+ arr[1] = b1;
+ arr[2] = b2;
+ arr[3] = b3;
+ arr[4] = b4;
+ arr[5] = b5;
+ arr[6] = b6;
+ arr[7] = b7;
+ arr[8] = b8;
+ arr[9] = b9;
+ arr[10] = b10;
+ arr[11] = b11;
+ arr[12] = b12;
+ arr[13] = b13;
+ arr[14] = b14;
+ arr[15] = b15;
+}
+
+/* { dg-final { scan-tree-dump "transform load" "slp2" } } */
+/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-70.c b/gcc/testsuite/gcc.dg/vect/bb-slp-70.c
new file mode 100644
index 0000000..0eb7011
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-70.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mavx512vl -mavx512vpopcntdq" { target avx512vpopcntdq } } */
+
+typedef unsigned uv4si __attribute__((vector_size(16)));
+
+uv4si __attribute__((noinline))
+vpopctf (uv4si a)
+{
+ uv4si r;
+ r[2] = __builtin_popcount (a[2]);
+ r[1] = __builtin_popcount (a[1]);
+ r[0] = __builtin_popcount (a[0]);
+ r[3] = __builtin_popcount (a[3]);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target avx512vpopcntdq } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c
index 87ffc9b..1eea923 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c
@@ -16,4 +16,7 @@ f (void)
x[7] /= 9;
}
-/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { xfail *-*-* } } } */
+/* We can vectorize the store from a CTOR built from scalar division
+ results but ideally we'd like to see vectorizing the load and the
+ division as well. */
+/* { dg-final { scan-tree-dump "transform load" "slp2" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c
index f6b99ea..c50560b 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c
@@ -13,13 +13,13 @@ foo (short * __restrict__ a, int * __restrict__ b, int stride)
for (i = 0; i < N/stride; i++, a += stride, b += stride)
{
a[0] = b[0] ? 1 : 7;
- a[1] = b[1] ? 2 : 0;
+ a[1] = b[1] ? 2 : 7;
a[2] = b[2] ? 3 : 0;
- a[3] = b[3] ? 4 : 0;
+ a[3] = b[3] ? 4 : 7;
a[4] = b[4] ? 5 : 0;
a[5] = b[5] ? 6 : 0;
a[6] = b[6] ? 7 : 0;
- a[7] = b[7] ? 8 : 0;
+ a[7] = b[7] ? 8 : 7;
}
}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
index ea37e4e..5d80f56 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
@@ -60,6 +60,7 @@ int main()
/* We should also be able to use 2-lane SLP to initialize the real and
imaginary components in the first loop of main. */
/* { dg-final { scan-tree-dump-times "optimized: basic block" 10 "slp1" } } */
-/* We should see the s->phase[dir] operand and only that operand built
+/* We should see the s->phase[dir] operand splatted and no other operand built
from scalars. See PR97334. */
-/* { dg-final { scan-tree-dump-times "Building vector operands from scalars" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump "Using a splat" "slp1" } } */
+/* { dg-final { scan-tree-dump-times "Building vector operands from scalars" 0 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c
index 8cd3a6a..e9909cf 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c
@@ -15,6 +15,6 @@ void foo(void)
/* ??? Due to the gaps we fall back to scalar loads which makes the
vectorization profitable. */
-/* { dg-final { scan-tree-dump "not profitable" "slp2" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "BB vectorization with gaps at the end of a load is not supported" 1 "slp2" } } */
-/* { dg-final { scan-tree-dump-times "Basic block will be vectorized" 1 "slp2" } } */
+/* { dg-final { scan-tree-dump "not profitable" "slp2" { xfail { ! aarch64*-*-* } } } } */
+/* { dg-final { scan-tree-dump "BB vectorization with gaps at the end of a load is not supported" "slp2" } } */
+/* { dg-final { scan-tree-dump-times "Basic block will be vectorized" 1 "slp2" { xfail aarch64*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c
index edcaf17..14826b5 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c
@@ -13,5 +13,5 @@ void foo()
}
/* The scalar shift argument should be extracted from the available vector. */
-/* { dg-final { scan-tree-dump "BIT_FIELD_REF" "slp2" } } */
+/* { dg-final { scan-tree-dump "BIT_FIELD_REF" "slp2" { target sse2 } } } */
/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97615.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97615.c
new file mode 100644
index 0000000..b4a8aa2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97615.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+
+short *a;
+int e, f;
+
+void
+foo (int c, int d)
+{
+ short *a1, *a2, *a3;
+ a1 = a++;
+ *a1 = c;
+ a2 = a++;
+ *a2 = *a1;
+ a3 = a++;
+ *a3 = d;
+}
+
+void
+bar (void)
+{
+ foo (e + f - 2, e + f - 1);
+ foo (e + f - 1, 0);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97626.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97626.c
new file mode 100644
index 0000000..943d8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97626.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+
+struct {
+ int x;
+ int y;
+} do_plasma_rect;
+
+int do_plasma_context_0, do_plasma_x2, do_plasma_y2, do_plasma_plasma_depth,
+ do_plasma_xm, do_plasma_ym;
+void gegl_buffer_set();
+
+void do_plasma(int x1, int y1) {
+ if (__builtin_expect(({
+ int _g_boolean_var_;
+ if (do_plasma_context_0)
+ _g_boolean_var_ = 1;
+ else
+ _g_boolean_var_ = 0;
+ _g_boolean_var_;
+ }),
+ 0)) {
+ do_plasma_rect.x = x1;
+ do_plasma_rect.y = y1;
+ gegl_buffer_set();
+ }
+ do_plasma_xm = (x1 + do_plasma_x2) / 2;
+ do_plasma_ym = (y1 + do_plasma_y2) / 2;
+ if (do_plasma_plasma_depth) {
+ do_plasma_rect.x = do_plasma_xm;
+ do_plasma_rect.y = do_plasma_ym;
+ return;
+ }
+ do_plasma(do_plasma_xm, do_plasma_ym);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97633.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97633.c
new file mode 100644
index 0000000..ab0ae1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97633.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+extern short i (void);
+
+struct {
+ short a;
+ short b;
+} c;
+
+int d, e;
+static int f = 1;
+
+void g () {
+ if (e) {
+ if (f)
+ goto L;
+ while (d) {
+ i ();
+ short j = d, k = i (), l = k;
+ L:
+ if (!(d && e) || l)
+ goto L;
+ c.a = j;
+ c.b = k;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97650.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97650.c
new file mode 100644
index 0000000..f9c91fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97650.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Os -fallow-store-data-races" } */
+
+short a=0;
+unsigned long *volatile *volatile *volatile *b;
+unsigned long *volatile *volatile *volatile **c[7];
+void d() {
+ short e=0;
+ for (; a;) {
+ e = 0;
+ for (; e < 7; e++)
+ c[e] = &b;
+ }
+}
+int main() { return 0; }
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97706.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97706.c
new file mode 100644
index 0000000..228ae70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97706.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+
+_Bool arr[16];
+void bar();
+void foo(int n, char *p)
+{
+ _Bool b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;
+ do
+ {
+ b0 = p[0] != 0;
+ b1 = p[1] != 0;
+ b2 = p[2] != 0;
+ b3 = p[3] != 0;
+ b4 = p[4] != 0;
+ b5 = p[5] != 0;
+ b6 = p[6] != 0;
+ b7 = p[7] != 0;
+ b8 = p[8] != 0;
+ b9 = p[9] != 0;
+ b10 = p[10] != 0;
+ b11 = p[11] != 0;
+ b12 = p[12] != 0;
+ b13 = p[13] != 0;
+ b14 = p[14] != 0;
+ b15 = p[15] != 0;
+ arr[0] = b0;
+ arr[1] = b1;
+ arr[2] = b2;
+ arr[3] = b3;
+ arr[4] = b4;
+ arr[5] = b5;
+ arr[6] = b6;
+ arr[7] = b7;
+ arr[8] = b8;
+ arr[9] = b9;
+ arr[10] = b10;
+ arr[11] = b11;
+ arr[12] = b12;
+ arr[13] = b13;
+ arr[14] = b14;
+ arr[15] = b15;
+ bar ();
+ }
+ while (--n);
+ arr[0] = b0;
+ arr[1] = b1;
+ arr[2] = b2;
+ arr[3] = b3;
+ arr[4] = b4;
+ arr[5] = b5;
+ arr[6] = b6;
+ arr[7] = b7;
+ arr[8] = b8;
+ arr[9] = b9;
+ arr[10] = b10;
+ arr[11] = b11;
+ arr[12] = b12;
+ arr[13] = b13;
+ arr[14] = b14;
+ arr[15] = b15;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
new file mode 100644
index 0000000..672807f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97709.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+int a;
+struct b {
+ int c;
+ int d;
+};
+void k (struct b);
+struct b
+e()
+{
+ void *f[] = {&&g, &&h, &&i, &&j};
+ int d, c;
+j:
+ goto *a;
+g:
+ d = 0;
+h:
+ c = 1;
+ goto *a;
+i:
+ {
+ struct b b = {c, d};
+ k(b);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97732.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97732.c
new file mode 100644
index 0000000..5187090
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97732.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+struct S { int a, b; } *e;
+int d;
+
+void
+foo (struct S *x)
+{
+ for (e = x; d; d++, e++)
+ e->a = e->b = (int) (__UINTPTR_TYPE__) e;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr97746.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97746.c
new file mode 100644
index 0000000..c5a615d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr97746.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+int a, b;
+short c;
+
+extern void f (short*);
+
+void d()
+{
+ short e[2] = {0, 0};
+ while (a)
+ {
+ f(e);
+ int g = 0 || a, h = 8 && c;
+ short i = c;
+ c = h & g;
+ if (b)
+ b = g || i;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr98137.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr98137.c
new file mode 100644
index 0000000..ecf7df2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr98137.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+/* { dg-require-effective-target vect_double } */
+
+void
+gemm (const double* __restrict__ A, const double* __restrict__ B,
+ double* __restrict__ C)
+{
+ unsigned int l_m = 0;
+ unsigned int l_n = 0;
+ unsigned int l_k = 0;
+
+ for ( l_n = 0; l_n < 9; l_n++ ) {
+ /* Use -O3 so this loop is unrolled completely early. */
+ for ( l_m = 0; l_m < 10; l_m++ ) { C[(l_n*10)+l_m] = 0.0; }
+ for ( l_k = 0; l_k < 17; l_k++ ) {
+ /* Use -O3 so this loop is unrolled completely early. */
+ for ( l_m = 0; l_m < 10; l_m++ ) {
+ C[(l_n*10)+l_m] += A[(l_k*20)+l_m] * B[(l_n*20)+l_k];
+ }
+ }
+ }
+}
+
+/* Exact scanning is difficult but we expect all loads and stores
+ and computations to be vectorized. */
+/* { dg-final { scan-tree-dump "optimized: basic block" "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c
index fe36f90..03c062a 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_int_mult } */
/* PR tree-optimization/67682. */
#include "tree-vect.h"
@@ -38,4 +39,7 @@ main (int argc, char **argv)
}
/* { dg-final { scan-tree-dump-times "Basic block will be vectorized using SLP" 1 "slp2" } } */
-/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" } } */
+/* Because we disable the cost model, targets with variable-length
+ vectors can end up vectorizing the store to a[0..7] on its own.
+ With the cost model we do something sensible. */
+/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" { xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-byte.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-byte.c
new file mode 100644
index 0000000..aadee7f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-byte.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_byte } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int8_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" { xfail aarch64_sve2 } } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-int.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-int.c
new file mode 100644
index 0000000..8eba24d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-int.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_int } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int32_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-long.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-long.c
new file mode 100644
index 0000000..9275ff1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-long.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_long } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int64_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-short.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-short.c
new file mode 100644
index 0000000..8cbbdb8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-short.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_short } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int16_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-byte.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-byte.c
new file mode 100644
index 0000000..b753914
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-byte.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_byte } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint8_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" { xfail aarch64_sve2 } } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-int.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-int.c
new file mode 100644
index 0000000..270c49e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-int.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_int } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint32_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-long.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-long.c
new file mode 100644
index 0000000..88144e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-long.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_long } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint64_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-short.c b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-short.c
new file mode 100644
index 0000000..445af39
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/bb-slp-complex-add-pattern-unsigned-short.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_short } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint16_t
+#define N 16
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail aarch64_sve2 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/complex-add-pattern-template.c b/gcc/testsuite/gcc.dg/vect/complex/complex-add-pattern-template.c
new file mode 100644
index 0000000..a99a929
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/complex-add-pattern-template.c
@@ -0,0 +1,60 @@
+void add90 (TYPE a[restrict N], TYPE b[restrict N], TYPE c[restrict N])
+{
+ for (int i=0; i < N; i+=2)
+ {
+ c[i] = a[i] - b[i+1];
+ c[i+1] = a[i+1] + b[i];
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+
+void add270 (TYPE a[restrict N], TYPE b[restrict N], TYPE c[restrict N])
+{
+ for (int i=0; i < N; i+=2)
+ {
+ c[i] = a[i] + b[i+1];
+ c[i+1] = a[i+1] - b[i];
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
+
+void addMixed (TYPE a[restrict N], TYPE b[restrict N], TYPE c[restrict N])
+{
+ for (int i=0; i < N; i+=4)
+ {
+ c[i] = a[i] - b[i+1];
+ c[i+1] = a[i+1] + b[i];
+ c[i+2] = a[i+2] + b[i+3];
+ c[i+3] = a[i+3] - b[i+2];
+ }
+}
+
+void add90HandUnrolled (TYPE a[restrict N], TYPE b[restrict N],
+ TYPE c[restrict N])
+{
+ for (int i=0; i < (N /2); i+=4)
+ {
+ c[i] = a[i] - b[i+1];
+ c[i+2] = a[i+2] - b[i+3];
+ c[i+1] = a[i+1] + b[i];
+ c[i+3] = a[i+3] + b[i+2];
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+
+void add90Hybrid (TYPE a[restrict N], TYPE b[restrict N], TYPE c[restrict N],
+ TYPE d[restrict N])
+{
+ for (int i=0; i < N; i+=2)
+ {
+ c[i] = a[i] - b[i+1];
+ c[i+1] = a[i+1] + b[i];
+ d[i] = a[i] - b[i];
+ d[i+1] = a[i+1] - b[i+1];
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 2 "vect" } } */ \ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/vect/complex/complex-add-template.c b/gcc/testsuite/gcc.dg/vect/complex/complex-add-template.c
new file mode 100644
index 0000000..32c81e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/complex-add-template.c
@@ -0,0 +1,79 @@
+#include <complex.h>
+
+void add0 (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + b[i];
+}
+
+void add90snd (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + (b[i] * I);
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+
+void add180snd (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + (b[i] * I * I);
+}
+
+void add270snd (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + (b[i] * I * I * I);
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
+
+void add90fst (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = (a[i] * I) + b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+
+void add180fst (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = (a[i] * I * I) + b[i];
+}
+
+void add270fst (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = (a[i] * I * I * I) + b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
+
+void addconjfst (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = ~a[i] + b[i];
+}
+
+void addconjsnd (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + ~b[i];
+}
+
+void addconjboth (_Complex TYPE a[restrict N], _Complex TYPE b[restrict N],
+ _Complex TYPE c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = ~a[i] + ~b[i];
+}
diff --git a/gcc/testsuite/gcc.dg/vect/complex/complex-operations-run.c b/gcc/testsuite/gcc.dg/vect/complex/complex-operations-run.c
new file mode 100644
index 0000000..a0348a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/complex-operations-run.c
@@ -0,0 +1,103 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vect_complex_add_double } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#include <stdio.h>
+#include <complex.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+
+#define PREF old
+#pragma GCC push_options
+#pragma GCC optimize ("no-tree-vectorize")
+# include "complex-operations.c"
+#pragma GCC pop_options
+#undef PREF
+
+#define PREF new
+# include "complex-operations.c"
+#undef PREF
+
+#define TYPE double
+#define TYPE2 double
+#define EP pow(2, -45)
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define FCMP(A, B) \
+ ((fabs (creal (A) - creal (B)) <= EP) && (fabs (cimag (A) - cimag (B)) <= EP))
+
+#define CMP(A, B) \
+ (FCMP(A,B) ? "PASS" : "FAIL")
+
+#define COMPARE(A,B) \
+ memset (&c1, 0, sizeof (c1)); \
+ memset (&c2, 0, sizeof (c2)); \
+ A; B; \
+ if (!FCMP(c1[0],c2[0]) || !FCMP(c1[1], c2[1])) \
+ { \
+ printf ("=> %s vs %s\n", xstr (A), xstr (B)); \
+ printf ("%a\n", creal (c1[0]) - creal (c2[0])); \
+ printf ("%a\n", cimag (c1[1]) - cimag (c2[1])); \
+ printf ("%.2f+%.2fI == %.2f+%.2fI (%s)\n", creal (c1[0]), cimag (c1[0]), creal (c2[0]), cimag (c2[0]), CMP (c1[0], c2[0])); \
+ printf ("%.2f+%.2fI == %.2f+%.2fI (%s)\n", creal (c1[1]), cimag (c1[1]), creal (c2[1]), cimag (c2[1]), CMP (c1[1], c2[1])); \
+ printf ("\n"); \
+ __builtin_abort (); \
+ }
+
+int main ()
+{
+ TYPE2 complex a[] = { 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I, 1.0 + 3.0 * I, 2.0 + 3.5 * I };
+ TYPE complex b[] = { 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I, 1.1 + 3.1 * I, 2.1 + 3.6 * I };
+ TYPE complex c2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ TYPE complex c1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ TYPE diff1, diff2;
+
+ COMPARE(fma0_old(a, b, c1), fma0_new(a, b, c2));
+ COMPARE(fma90_old(a, b, c1), fma90_new(a, b, c2));
+ COMPARE(fma180_old(a, b, c1), fma180_new(a, b, c2));
+ COMPARE(fma270_old(a, b, c1), fma270_new(a, b, c2));
+ COMPARE(fma0_snd_old(a, b, c1), fma0_snd_new(a, b, c2));
+ COMPARE(fma90_snd_old(a, b, c1), fma90_snd_new(a, b, c2));
+ COMPARE(fma180_snd_old(a, b, c1), fma180_snd_new(a, b, c2));
+ COMPARE(fma270_snd_old(a, b, c1), fma270_snd_new(a, b, c2));
+ COMPARE(fma_conj_first_old(a, b, c1), fma_conj_first_new(a, b, c2));
+ COMPARE(fma_conj_second_old(a, b, c1), fma_conj_second_new(a, b, c2));
+ COMPARE(fma_conj_both_old(a, b, c1), fma_conj_both_new(a, b, c2));
+ COMPARE(fms0_old(a, b, c1), fms0_new(a, b, c2));
+ COMPARE(fms90_old(a, b, c1), fms90_new(a, b, c2));
+ COMPARE(fms180_old(a, b, c1), fms180_new(a, b, c2));
+ COMPARE(fms270_old(a, b, c1), fms270_new(a, b, c2));
+ COMPARE(fms0_snd_old(a, b, c1), fms0_snd_new(a, b, c2));
+ COMPARE(fms90_snd_old(a, b, c1), fms90_snd_new(a, b, c2));
+ COMPARE(fms180_snd_old(a, b, c1), fms180_snd_new(a, b, c2));
+ COMPARE(fms270_snd_old(a, b, c1), fms270_snd_new(a, b, c2));
+ COMPARE(fms_conj_first_old(a, b, c1), fms_conj_first_new(a, b, c2));
+ COMPARE(fms_conj_second_old(a, b, c1), fms_conj_second_new(a, b, c2));
+ COMPARE(fms_conj_both_old(a, b, c1), fms_conj_both_new(a, b, c2));
+ COMPARE(mul0_old(a, b, c1), mul0_new(a, b, c2));
+ COMPARE(mul90_old(a, b, c1), mul90_new(a, b, c2));
+ COMPARE(mul180_old(a, b, c1), mul180_new(a, b, c2));
+ COMPARE(mul270_old(a, b, c1), mul270_new(a, b, c2));
+ COMPARE(mul0_snd_old(a, b, c1), mul0_snd_new(a, b, c2));
+ COMPARE(mul90_snd_old(a, b, c1), mul90_snd_new(a, b, c2));
+ COMPARE(mul180_snd_old(a, b, c1), mul180_snd_new(a, b, c2));
+ COMPARE(mul270_snd_old(a, b, c1), mul270_snd_new(a, b, c2));
+ COMPARE(mul_conj_first_old(a, b, c1), mul_conj_first_new(a, b, c2));
+ COMPARE(mul_conj_second_old(a, b, c1), mul_conj_second_new(a, b, c2));
+ COMPARE(mul_conj_both_old(a, b, c1), mul_conj_both_new(a, b, c2));
+ COMPARE(add0_old(a, b, c1), add0_new(a, b, c2));
+ COMPARE(add90_old(a, b, c1), add90_new(a, b, c2));
+ COMPARE(add180_old(a, b, c1), add180_new(a, b, c2));
+ COMPARE(add270_old(a, b, c1), add270_new(a, b, c2));
+ COMPARE(add0_snd_old(a, b, c1), add0_snd_new(a, b, c2));
+ COMPARE(add90_snd_old(a, b, c1), add90_snd_new(a, b, c2));
+ COMPARE(add180_snd_old(a, b, c1), add180_snd_new(a, b, c2));
+ COMPARE(add270_snd_old(a, b, c1), add270_snd_new(a, b, c2));
+ COMPARE(add_conj_first_old(a, b, c1), add_conj_first_new(a, b, c2));
+ COMPARE(add_conj_second_old(a, b, c1), add_conj_second_new(a, b, c2));
+ COMPARE(add_conj_both_old(a, b, c1), add_conj_both_new(a, b, c2));
+}
diff --git a/gcc/testsuite/gcc.dg/vect/complex/complex-operations.c b/gcc/testsuite/gcc.dg/vect/complex/complex-operations.c
new file mode 100644
index 0000000..fdce995
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/complex-operations.c
@@ -0,0 +1,358 @@
+#include <stdio.h>
+#include <complex.h>
+
+#ifndef PREF
+#define PREF c
+#endif
+
+#define FX(N,P) P ## _ ## N
+#define MK(N,P) FX(P,N)
+
+#define N 32
+#define TYPE double
+
+// ------ FMA
+
+// Complex FMA instructions rotating the result
+
+__attribute__((noinline,noipa))
+void MK(fma0, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(fma90, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * b[i] * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(fma180, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * b[i] * I * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(fma270, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * b[i] * I * I * I;
+}
+
+// Complex FMA instructions rotating the second parameter.
+
+
+__attribute__((noinline,noipa))
+void MK(fma0_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(fma90_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * (b[i] * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(fma180_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * (b[i] * I * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(fma270_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * (b[i] * I * I * I);
+}
+
+// Complex FMA instructions with conjucated values.
+
+
+__attribute__((noinline,noipa))
+void MK(fma_conj_first, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += conj (a[i]) * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(fma_conj_second, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += a[i] * conj (b[i]);
+}
+
+__attribute__((noinline,noipa))
+void MK(fma_conj_both, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] += conj (a[i]) * conj (b[i]);
+}
+
+// ----- FMS
+
+// Complex FMS instructions rotating the result
+
+__attribute__((noinline,noipa))
+void MK(fms0, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(fms90, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * b[i] * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(fms180, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * b[i] * I * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(fms270, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * b[i] * I * I * I;
+}
+
+// Complex FMS instructions rotating the second parameter.
+
+__attribute__((noinline,noipa))
+void MK(fms0_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(fms90_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * (b[i] * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(fms180_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * (b[i] * I * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(fms270_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * (b[i] * I * I * I);
+}
+
+// Complex FMS instructions with conjucated values.
+
+__attribute__((noinline,noipa))
+void MK(fms_conj_first, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= conj (a[i]) * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(fms_conj_second, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= a[i] * conj (b[i]);
+}
+
+__attribute__((noinline,noipa))
+void MK(fms_conj_both, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] -= conj (a[i]) * conj (b[i]);
+}
+
+
+// ----- MUL
+
+// Complex MUL instructions rotating the result
+
+__attribute__((noinline,noipa))
+void MK(mul0, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(mul90, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * b[i] * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(mul180, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * b[i] * I * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(mul270, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * b[i] * I * I * I;
+}
+
+// Complex MUL instructions rotating the second parameter.
+
+__attribute__((noinline,noipa))
+void MK(mul0_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(mul90_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * (b[i] * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(mul180_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * (b[i] * I * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(mul270_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * (b[i] * I * I * I);
+}
+
+// Complex FMS instructions with conjucated values.
+
+__attribute__((noinline,noipa))
+void MK(mul_conj_first, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = conj (a[i]) * b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(mul_conj_second, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] * conj (b[i]);
+}
+
+__attribute__((noinline,noipa))
+void MK(mul_conj_both, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = conj (a[i]) * conj (b[i]);
+}
+
+
+// ----- ADD
+
+// Complex ADD instructions rotating the result
+
+__attribute__((noinline,noipa))
+void MK(add0, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(add90, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = (a[i] + b[i]) * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(add180, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = (a[i] + b[i]) * I * I;
+}
+
+__attribute__((noinline,noipa))
+void MK(add270, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = (a[i] + b[i]) * I * I * I;
+}
+
+// Complex ADD instructions rotating the second parameter.
+
+__attribute__((noinline,noipa))
+void MK(add0_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(add90_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + (b[i] * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(add180_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + (b[i] * I * I);
+}
+
+__attribute__((noinline,noipa))
+void MK(add270_snd, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + (b[i] * I * I * I);
+}
+
+// Complex ADD instructions with conjucated values.
+
+__attribute__((noinline,noipa))
+void MK(add_conj_first, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = conj (a[i]) + b[i];
+}
+
+__attribute__((noinline,noipa))
+void MK(add_conj_second, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = a[i] + conj (b[i]);
+}
+
+__attribute__((noinline,noipa))
+void MK(add_conj_both, PREF) (TYPE complex a[restrict N], TYPE complex b[restrict N], TYPE complex c[restrict N])
+{
+ for (int i=0; i < N; i++)
+ c[i] = conj (a[i]) + conj (b[i]);
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/vect/complex/complex.exp b/gcc/testsuite/gcc.dg/vect/complex/complex.exp
new file mode 100644
index 0000000..daeb028
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/complex.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_file $srcdir/$subdir/../vect.exp
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-double.c
new file mode 100644
index 0000000..7bbb61a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-double.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_double } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE double
+#define N 16
+#include "complex-add-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-float.c
new file mode 100644
index 0000000..cf99f1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-float.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_float } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE float
+#define N 16
+#include "complex-add-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-half-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-half-float.c
new file mode 100644
index 0000000..9f535dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-half-float.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_half } */
+/* { dg-add-options arm_v8_3a_fp16_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE _Float16
+#define N 16
+#include "complex-add-template.c"
+
+/* Vectorization is failing for these cases. They should work but for now ignore. */
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-double.c
new file mode 100644
index 0000000..e121113
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-double.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_double } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE double
+#define N 16
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-float.c
new file mode 100644
index 0000000..8565833
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-float.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_float } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE float
+#define N 16
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-half-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-half-float.c
new file mode 100644
index 0000000..857ee9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-add-pattern-half-float.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_half } */
+/* { dg-add-options arm_v8_3a_fp16_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE _Float16
+#define N 16
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "slp1" { xfail arm*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-double.c
new file mode 100644
index 0000000..0d4d3ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-double.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_double } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE double
+#define N 200
+#include "complex-add-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 2 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 2 "vect" } } */ \ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-float.c
new file mode 100644
index 0000000..b986696
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-float.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_float } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE float
+#define N 200
+#include "complex-add-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 2 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 2 "vect" } } */ \ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-half-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-half-float.c
new file mode 100644
index 0000000..c3dca57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-half-float.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_half } */
+/* { dg-add-options arm_v8_3a_fp16_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE _Float16
+#define N 200
+#include "complex-add-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 2 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 2 "vect" } } */ \ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-double.c
new file mode 100644
index 0000000..df4d3f6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-double.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_double } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE double
+#define N 200
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 4 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-float.c
new file mode 100644
index 0000000..6df5c6d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-float.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_float } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE float
+#define N 200
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 4 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-half-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-half-float.c
new file mode 100644
index 0000000..a725112
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-complex-add-pattern-half-float.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_half } */
+/* { dg-add-options arm_v8_3a_fp16_complex_neon } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE _Float16
+#define N 200
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 4 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-byte.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-byte.c
new file mode 100644
index 0000000..438d219
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-byte.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_byte } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int8_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-int.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-int.c
new file mode 100644
index 0000000..04c27dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-int.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_int } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int32_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-long.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-long.c
new file mode 100644
index 0000000..27988ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-long.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_long } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int64_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-short.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-short.c
new file mode 100644
index 0000000..88d225d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-short.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_short } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE int16_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-byte.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-byte.c
new file mode 100644
index 0000000..59109c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-byte.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_byte } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint8_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-int.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-int.c
new file mode 100644
index 0000000..44d9635
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-int.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_int } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint32_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-long.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-long.c
new file mode 100644
index 0000000..6671457
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-long.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_long } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint64_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-short.c b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-short.c
new file mode 100644
index 0000000..841adf8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/complex/vect-complex-add-pattern-unsigned-short.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_complex_add_short } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+#define TYPE uint16_t
+#define N 200
+#include <stdint.h>
+#include "complex-add-pattern-template.c"
+
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT90" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "stmt.*COMPLEX_ADD_ROT270" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c
index 877de4e..495c031 100644
--- a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c
+++ b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c
@@ -97,4 +97,4 @@ main ()
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { { vect_call_copysignf && vect_call_sqrtf } && vect_perm3_int } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c
index 3bfe498..6834b9a 100644
--- a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c
+++ b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c
@@ -5,8 +5,8 @@ void
vadd (int *dst, int *op1, int *op2, int count)
{
/* { dg-prune-output " version\[^\n\r]* alignment" } */
-/* { dg-optimized "loop vectorized" "" { target *-*-* } .+2 } */
-/* { dg-optimized "loop versioned for vectorization because of possible aliasing" "" { target *-*-* } .+1 } */
+/* { dg-optimized "21: loop vectorized" "" { target *-*-* } .+2 } */
+/* { dg-optimized "21: loop versioned for vectorization because of possible aliasing" "" { target *-*-* } .+1 } */
for (int i = 0; i < count; ++i)
dst[i] = op1[i] + op2[i];
}
diff --git a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c
index 94c55a9..23a3b39 100644
--- a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c
+++ b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c
@@ -6,7 +6,7 @@ extern void accumulate (int x, int *a);
int test_missing_function_defn (int *arr, int n) /* { dg-message "vectorized 0 loops in function" } */
{
int sum = 0;
- for (int i = 0; i < n; ++i) /* { dg-missed "couldn't vectorize loop" } */
- accumulate (arr[i], &sum); /* { dg-missed "statement clobbers memory: accumulate \\(.*\\);" } */
+ for (int i = 0; i < n; ++i) /* { dg-missed "21: couldn't vectorize loop" } */
+ accumulate (arr[i], &sum); /* { dg-missed "5: statement clobbers memory: accumulate \\(.*\\);" } */
return sum;
}
diff --git a/gcc/testsuite/gcc.dg/vect/pr65947-8.c b/gcc/testsuite/gcc.dg/vect/pr65947-8.c
index a2a940d..d042679 100644
--- a/gcc/testsuite/gcc.dg/vect/pr65947-8.c
+++ b/gcc/testsuite/gcc.dg/vect/pr65947-8.c
@@ -41,6 +41,6 @@ main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" { target { ! amdgcn*-*-* } } } } */
-/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target amdgcn*-*-* } } } */
-/* { dg-final { scan-tree-dump "multiple types in double reduction or condition reduction" "vect" { target { ! amdgcn*-*-* } } } } */
+/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" { target { ! { amdgcn*-*-* || aarch64_sve } } } } } */
+/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target { amdgcn*-*-* || aarch64_sve } } } } */
+/* { dg-final { scan-tree-dump "multiple types in double reduction or condition reduction" "vect" { target { ! { amdgcn*-*-* || aarch64_sve } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr91750.c b/gcc/testsuite/gcc.dg/vect/pr91750.c
index fe914b2..3586f11 100644
--- a/gcc/testsuite/gcc.dg/vect/pr91750.c
+++ b/gcc/testsuite/gcc.dg/vect/pr91750.c
@@ -11,5 +11,5 @@ foo (int n)
}
/* Make sure the induction IV uses an unsigned increment. */
-/* { dg-final { scan-tree-dump "vector\\\(\[0-9\]*\\\) unsigned int" "vect" } } */
+/* { dg-final { scan-tree-dump {vector\([][0-9,]*\) unsigned int} "vect" } } */
/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr97457.c b/gcc/testsuite/gcc.dg/vect/pr97457.c
new file mode 100644
index 0000000..506ba24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97457.c
@@ -0,0 +1,15 @@
+/* { dg-additional-options "-O3" } */
+
+int a;
+long c;
+signed char d(char e, char f) { return e + f; }
+int main(void) {
+ for (; a <= 1; a++) {
+ c = -8;
+ for (; c != 3; c = d(c, 1))
+ ;
+ }
+ char b = c;
+ if (b != 3)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97558-2.c b/gcc/testsuite/gcc.dg/vect/pr97558-2.c
new file mode 100644
index 0000000..8f08086
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97558-2.c
@@ -0,0 +1,54 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O3 -fno-tree-forwprop -fno-tree-scev-cprop" } */
+
+#include "tree-vect.h"
+
+#define N 40
+
+int a[N];
+int b[N];
+
+__attribute__ ((noinline)) int
+foo (int n){
+ int i,j;
+ int sum,x,y;
+
+ if (n<=0)
+ return 0;
+
+ for (i = 0; i < N/2; i++) {
+ sum = 0;
+ x = b[2*i];
+ y = b[2*i+1];
+ for (j = 0; j < n; j++) {
+ sum += j;
+ }
+ a[2*i] = sum + x;
+ a[2*i+1] = sum + y;
+ }
+}
+
+int main (void)
+{
+ int i,j;
+ int sum;
+
+ check_vect ();
+
+ for (i=0; i<N; i++)
+ b[i] = i;
+
+ foo (N-1);
+
+ /* check results: */
+ for (i=0; i<N/2; i++)
+ {
+ sum = 0;
+ for (j = 0; j < N-1; j++)
+ sum += j;
+ if (a[2*i] != sum + b[2*i] || a[2*i+1] != sum + b[2*i+1])
+ abort();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97558.c b/gcc/testsuite/gcc.dg/vect/pr97558.c
new file mode 100644
index 0000000..fef9623
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97558.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-dce -Ofast" } */
+
+long int x1;
+int fr;
+
+int
+us (int sk, int jx)
+{
+ while (sk < 1)
+ {
+ jx *= 2;
+ fr += x1 + 1;
+ ++sk;
+ }
+
+ return jx;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97678.c b/gcc/testsuite/gcc.dg/vect/pr97678.c
new file mode 100644
index 0000000..7fb6c93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97678.c
@@ -0,0 +1,32 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_int_mult } */
+/* { dg-require-effective-target vect_pack_trunc } */
+/* { dg-additional-options "-mavx2" { target avx2_runtime } } */
+
+#include "tree-vect.h"
+
+int
+main ()
+{
+ unsigned int i = 0;
+ unsigned short b[158 * 2];
+
+ check_vect ();
+
+ for (i = 0; i < 158; i++)
+ {
+ b[i * 2] = i * 7;
+ b[i * 2 + 1] = i * 8;
+ }
+
+ for (i = 0; i < 158; ++i)
+ if (b[i*2] != (unsigned short)(i*7)
+ || b[i*2+1] != (unsigned short)(i*8))
+ abort ();
+
+ return 0;
+}
+
+/* The init loop should be vectorized with SLP. */
+/* We don't yet support SLP inductions for variable length vectors. */
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr97693.c b/gcc/testsuite/gcc.dg/vect/pr97693.c
new file mode 100644
index 0000000..4da44c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97693.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+extern short a[];
+int b;
+short c, d;
+unsigned e() {
+ if (c)
+ return c;
+ return d;
+}
+void f() {
+ for (unsigned g = b; g; g += 6)
+ for (_Bool h = 0; h < (_Bool)e(); h = 1)
+ a[g] = 1 / b;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97730.c b/gcc/testsuite/gcc.dg/vect/pr97730.c
new file mode 100644
index 0000000..af4bca4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97730.c
@@ -0,0 +1,12 @@
+/* { dg-additional-options "-O1" } */
+unsigned b = 0xce8e5a48, c = 0xb849691a;
+unsigned a[8080];
+int main() {
+ a[0] = b;
+ c = c;
+ unsigned f = 0xb1e8;
+ for (int h = 0; h < 5; h++)
+ a[h] = (b & c) ^ f;
+ if (a[0] != 0x8808f9e0)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97753.c b/gcc/testsuite/gcc.dg/vect/pr97753.c
new file mode 100644
index 0000000..e49a848
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97753.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+long a[6];
+void d(int c)
+{
+ for (; c; c++)
+ for (int b = 0; b < 8; b++)
+ ((char *)&a[c])[b] = c;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97760.c b/gcc/testsuite/gcc.dg/vect/pr97760.c
new file mode 100644
index 0000000..da5ac93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97760.c
@@ -0,0 +1,26 @@
+#include "tree-vect.h"
+
+int b=1;
+static int *g = &b;
+
+void __attribute__((noipa))
+h (unsigned int n)
+{
+ int i = 3;
+ int f = 3;
+ for (; f <= 50; f += 4) {
+ i += 4;
+ *g = i;
+ i += n;
+ }
+}
+
+int main ()
+{
+ check_vect ();
+
+ h (9);
+ if (*g != 150 || b != 150)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97769.c b/gcc/testsuite/gcc.dg/vect/pr97769.c
new file mode 100644
index 0000000..127f91a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97769.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef struct {
+ int alg;
+ int h1[8];
+ unsigned d1[1];
+} tmp;
+typedef struct {
+ tmp itmp;
+ tmp otmp;
+} h1;
+h1 c;
+
+static void
+fn1(char *p1, int p2)
+{
+ int i = 0;
+ for (; i < 4; i++)
+ *p1++ = p2;
+}
+
+static void
+fn2(tmp *p1)
+{
+ char *d = (char *)p1->d1;
+ int *b = p1->h1;
+ for (int a; a; a++, d += 4)
+ fn1(d, *b++);
+}
+
+void fn3() { fn2(&(&c)->otmp); }
diff --git a/gcc/testsuite/gcc.dg/vect/pr97835.c b/gcc/testsuite/gcc.dg/vect/pr97835.c
new file mode 100644
index 0000000..a90c773
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97835.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+struct co {
+ int gx;
+ int ty;
+};
+
+void
+x0 (struct co *yy, long int kc, int wi, int md)
+{
+ while (wi < 1)
+ {
+ yy[wi].gx = md;
+ yy[wi].ty = wi;
+ md += kc;
+ ++wi;
+ }
+}
+
+/* We don't yet support SLP inductions for variable length vectors. */
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr97838.c b/gcc/testsuite/gcc.dg/vect/pr97838.c
new file mode 100644
index 0000000..06ec035
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97838.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+
+void f() {
+ while (c++) {
+ int e = -1;
+ d = a ? e / a : e;
+ b ^= ~d;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr97929.c b/gcc/testsuite/gcc.dg/vect/pr97929.c
new file mode 100644
index 0000000..a027b31
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr97929.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+#include <stdint.h>
+#define ARR_SIZE 1024
+extern void foo (int32_t *bar, int16_t a)
+{
+ for( int i = 0; i < ARR_SIZE;i++)
+ {
+ bar[i] = a + 1;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr98048.c b/gcc/testsuite/gcc.dg/vect/pr98048.c
new file mode 100644
index 0000000..e61a376
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr98048.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+extern short var_0;
+extern int var_3;
+extern int arr_277[];
+int a(int b, int c) { return b < c ? b : c; }
+int e;
+void test()
+{
+ e = var_0;
+ for (int d = 0; d < 9; d++)
+ if (var_3)
+ arr_277[d] = a(var_0, -var_0);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr98069.c b/gcc/testsuite/gcc.dg/vect/pr98069.c
new file mode 100644
index 0000000..e60549f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr98069.c
@@ -0,0 +1,22 @@
+long long int var_3 = -166416893043554447LL;
+short var_8 = (short)27092;
+unsigned int var_17 = 75036300U;
+short arr_165[23];
+
+static long c(long e, long f) { return f ? e : f; }
+void __attribute((noipa)) test()
+{
+ for (int b = 0; b < 19; b = var_17)
+ for (int d = (int)(~c(-2147483647 - 1, var_3)) - 2147483647; d < 22; d++)
+ arr_165[d] = var_8;
+}
+
+int main()
+{
+ for (unsigned i_3 = 0; i_3 < 23; ++i_3)
+ arr_165[i_3] = (short)-8885;
+ test();
+ if (arr_165[0] != 27092)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/slp-11b.c b/gcc/testsuite/gcc.dg/vect/slp-11b.c
index 0cc2377..0aece80 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-11b.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-11b.c
@@ -45,4 +45,5 @@ int main (void)
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided4 && vect_int_mult } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_strided4 && vect_int_mult } } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! vect_load_lanes } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_load_lanes } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-21.c b/gcc/testsuite/gcc.dg/vect/slp-21.c
index 1f8c82e..117d65c 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-21.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-21.c
@@ -201,6 +201,16 @@ int main (void)
/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target { vect_strided4 || vect_extract_even_odd } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided4 || vect_extract_even_odd } } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_strided4 } } } */
+/* Some targets can vectorize the second of the three main loops using
+ hybrid SLP. For 128-bit vectors, the required 4->3 permutations are:
+
+ { 0, 1, 2, 4, 5, 6, 8, 9 }
+ { 2, 4, 5, 6, 8, 9, 10, 12 }
+ { 5, 6, 8, 9, 10, 12, 13, 14 }
+
+ Not all vect_perm targets support that, and it's a bit too specific to have
+ its own effective-target selector, so we just test targets directly. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { aarch64*-*-* arm*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_strided4 && { ! { aarch64*-*-* arm*-*-* } } } } } } */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { vect_strided4 } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-46.c b/gcc/testsuite/gcc.dg/vect/slp-46.c
index 58a238a..18476a4 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-46.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-46.c
@@ -94,4 +94,4 @@ main ()
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { xfail vect_load_lanes } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-49.c b/gcc/testsuite/gcc.dg/vect/slp-49.c
new file mode 100644
index 0000000..4141a09
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/slp-49.c
@@ -0,0 +1,39 @@
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+int a[1024];
+
+void __attribute__((noipa))
+foo(int k)
+{
+ int j = 5;
+ for (int i = 0; i < 512; ++i)
+ {
+ a[2*i] = j;
+ a[2*i+1] = k;
+ j++;
+ k+=3;
+ }
+}
+
+int
+main()
+{
+ check_vect ();
+
+ foo (17);
+
+ for (int i = 0; i < 512; ++i)
+ {
+ if (a[2*i] != 5 + i
+ || a[2*i+1] != 17 + 3 * i)
+ __builtin_abort ();
+ }
+
+ return 0;
+}
+
+/* We don't yet support SLP inductions for variable length vectors. */
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */
+/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c
index 4128cca..ca7803e 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c
@@ -80,9 +80,7 @@ int main (int argc, const char* argv[])
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */
-/* The epilogues are vectorized using partial vectors. */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && {! vect_load_lanes } } } } } */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */
/* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */
/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-5.c b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c
index b137821..b86a3dc 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-perm-5.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c
@@ -104,9 +104,7 @@ int main (int argc, const char* argv[])
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */
-/* The epilogues are vectorized using partial vectors. */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */
/* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */
/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c
index 3848929..bec1544 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c
@@ -103,10 +103,7 @@ int main (int argc, const char* argv[])
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */
-/* The epilogues are vectorized using partial vectors. */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_load_lanes } } } */
-/* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */
-/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */
-/* { dg-final { scan-tree-dump "STORE_LANES" "vect" { target vect_load_lanes } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_perm3_int } } } */
+/* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes xfail vect_perm3_int } } } */
+/* { dg-final { scan-tree-dump "STORE_LANES" "vect" { target vect_load_lanes xfail vect_perm3_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c
index 498999a..346411f 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c
@@ -96,9 +96,7 @@ int main (int argc, const char* argv[])
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */
-/* The epilogues are vectorized using partial vectors. */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */
/* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */
/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c
index 266b439..cffb011 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c
@@ -57,6 +57,8 @@ int main (void)
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_min_max } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_min_max || vect_variable_length } } } } */
-/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */
+/* For variable-length SVE, the number of scalar statements in the
+ reduction exceeds the number of elements in a 128-bit granule. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_min_max || { aarch64_sve && vect_variable_length } } } } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" { xfail { aarch64_sve && vect_variable_length } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c
index 05cc9ed..7a958f2 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c
@@ -55,5 +55,7 @@ int main (void)
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_add } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_add || vect_variable_length } } } } */
-/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */
+/* For variable-length SVE, the number of scalar statements in the
+ reduction exceeds the number of elements in a 128-bit granule. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_add || { aarch64_sve && vect_variable_length } } } } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" { xfail { aarch64_sve && vect_variable_length } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/tree-vect.h b/gcc/testsuite/gcc.dg/vect/tree-vect.h
index 5d8d9eb..c4b8144 100644
--- a/gcc/testsuite/gcc.dg/vect/tree-vect.h
+++ b/gcc/testsuite/gcc.dg/vect/tree-vect.h
@@ -52,7 +52,7 @@ check_vect (void)
want_level = 1, want_d = bit_SSE2;
# endif
- if (!__get_cpuid (want_level, &a, &b, &c, &d)
+ if (!__get_cpuid_count (want_level, 0, &a, &b, &c, &d)
|| ((b & want_b) | (c & want_c) | (d & want_d)) == 0)
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c
index ca57a10..28a99c9 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c
@@ -20,10 +20,6 @@ int main1 ()
s.b[i] = i;
}
- /* Dependence analysis fails cause s.a and s.b may overlap.
- Try to use runtime aliasing test with versioning, and
- later versioning/vectorization are skipped because the
- overlap is proven at compilation time. */
for (i = 0; i < N; i++)
{
s.a[i] = s.b[i] + 1;
@@ -47,5 +43,4 @@ int main (void)
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */
-/* { dg-final { scan-tree-dump "can't determine dependence between" "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-35.c b/gcc/testsuite/gcc.dg/vect/vect-35.c
index 76fe32d..a7ec0f16 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-35.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-35.c
@@ -20,10 +20,6 @@ int main1 ()
s.b[i] = i;
}
- /* Dependence analysis fails cause s.a and s.b may overlap.
- Try to use runtime aliasing test with versioning, and
- later versioning/vectorization are skipped because the
- overlap is proven at compilation time. */
for (i = 0; i < N; i++)
{
s.a[i] = s.b[i] + 1;
@@ -47,5 +43,4 @@ int main (void)
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */
-/* { dg-final { scan-tree-dump "can't determine dependence between" "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c
new file mode 100644
index 0000000..0737da5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=cheap" } */
+
+void
+f (int *x, int *y)
+{
+ for (unsigned int i = 0; i < 1024; ++i)
+ x[i] += y[i];
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c
new file mode 100644
index 0000000..fa9bdb6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=very-cheap" } */
+
+void
+f (int *x, int *y)
+{
+ for (unsigned int i = 0; i < 1024; ++i)
+ x[i] += y[i];
+}
+
+/* { dg-final { scan-tree-dump-not {LOOP VECTORIZED} vect { target vect_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c
new file mode 100644
index 0000000..d7c6cfd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=cheap" } */
+
+void
+f (int *restrict x, int *restrict y)
+{
+ for (unsigned int i = 0; i < 1024; ++i)
+ x[i] += y[i];
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c
new file mode 100644
index 0000000..bb018ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=very-cheap" } */
+
+int x[1024], y[1024];
+
+void
+f (void)
+{
+ for (unsigned int i = 0; i < 1024; ++i)
+ x[i] += y[i];
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c
new file mode 100644
index 0000000..536ec0a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=cheap" } */
+
+void
+f (int *restrict x, int *restrict y)
+{
+ for (unsigned int i = 0; i < 1023; ++i)
+ x[i] += y[i];
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c
new file mode 100644
index 0000000..552febb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=very-cheap" } */
+
+void
+f (int *restrict x, int *restrict y)
+{
+ for (unsigned int i = 0; i < 1023; ++i)
+ x[i] += y[i];
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target { vect_int && vect_partial_vectors_usage_2 } } } } */
+/* { dg-final { scan-tree-dump-not {LOOP VECTORIZED} vect { target { vect_int && { ! vect_partial_vectors_usage_2 } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-epilogues.c b/gcc/testsuite/gcc.dg/vect/vect-epilogues.c
index a146bb6..ab7e8a1 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-epilogues.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-epilogues.c
@@ -16,4 +16,4 @@ void pixel_avg( unsigned char *dst, int i_dst_stride,
}
}
-/* { dg-final { scan-tree-dump "LOOP EPILOGUE VECTORIZED" "vect" { target vect_multiple_sizes xfail { arm32 && be } } } } */
+/* { dg-final { scan-tree-dump "LOOP EPILOGUE VECTORIZED" "vect" { target vect_multiple_sizes xfail { { arm32 && be } || vect_partial_vectors_usage_2 } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-live-6.c b/gcc/testsuite/gcc.dg/vect/vect-live-6.c
index c986c97..0e7aa22 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-live-6.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-live-6.c
@@ -28,4 +28,4 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target vect_int } } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target { vect_int && vect_condition } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c
new file mode 100644
index 0000000..445157d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+int a[1024];
+
+void foo (void)
+{
+ for (int i = 0; i < 1020; i += 4)
+ {
+ int suma = a[i];
+ int sumb = a[i+1];
+ int sumc = a[i+2];
+ int sumd = a[i+3];
+ for (unsigned j = 0; j < 77; ++j)
+ {
+ suma = (suma ^ i) + 1;
+ sumb = (sumb ^ i) + 2;
+ sumc = (sumc ^ i) + 3;
+ sumd = (sumd ^ i) + 4;
+ }
+ a[i] = suma;
+ a[i+1] = sumb;
+ a[i+2] = sumc;
+ a[i+3] = sumd;
+ }
+}
+
+/* We should vectorize this outer loop with SLP. */
+/* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" } } */
+/* We don't yet support SLP inductions for variable length vectors. */
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */
+/* { dg-final { scan-tree-dump-not "VEC_PERM_EXPR" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c
new file mode 100644
index 0000000..ec1e103
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c
@@ -0,0 +1,52 @@
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_intdouble_cvt } */
+
+#include "tree-vect.h"
+
+double image[40];
+
+void __attribute__((noipa))
+foo (void)
+{
+ for (int i = 0; i < 20; i++)
+ {
+ double suma = 0;
+ double sumb = 0;
+ for (int j = 0; j < 40; j++)
+ {
+ suma += j+i;
+ sumb += j+i;
+ }
+ image[2*i] = suma;
+ image[2*i+1] = sumb;
+ }
+}
+
+int main ()
+{
+ check_vect ();
+
+ foo ();
+
+ for (int i = 0; i < 20; i++)
+ {
+ double suma = 0;
+ double sumb = 0;
+ for (int j = 0; j < 40; j++)
+ {
+ suma += j+i;
+ sumb += j+i;
+ asm ("" : "+g" (suma));
+ asm ("" : "+g" (sumb));
+ }
+ if (image[2*i] != suma
+ || image[2*i+1] != sumb)
+ abort ();
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" } } */
+/* We don't yet support SLP inductions for variable length vectors. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c
new file mode 100644
index 0000000..53865d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c
@@ -0,0 +1,63 @@
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_intdouble_cvt } */
+
+#include "tree-vect.h"
+
+double image[40];
+
+void __attribute__((noipa))
+foo (void)
+{
+ for (int i = 0; i < 20; i++)
+ {
+ double suma = 0;
+ double sumb = 0;
+ int k = image[2*i];
+ int l = image[2*i+1];
+ for (int j = 0; j < 40; j++)
+ {
+ suma += k+i;
+ sumb += l+i;
+ k++;
+ l++;
+ }
+ image[2*i] = suma;
+ image[2*i+1] = sumb;
+ }
+}
+
+int main ()
+{
+ check_vect ();
+
+ for (int i = 0; i < 40; ++i)
+ image[i] = 1.;
+
+ foo ();
+
+ for (int i = 0; i < 20; i++)
+ {
+ double suma = 0;
+ double sumb = 0;
+ int k = 1;
+ int l = 1;
+ for (int j = 0; j < 40; j++)
+ {
+ suma += k+i;
+ sumb += l+i;
+ asm ("" : "+g" (suma));
+ asm ("" : "+g" (sumb));
+ k++;
+ l++;
+ }
+ if (image[2*i] != suma
+ || image[2*i+1] != sumb)
+ abort ();
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" } } */
+/* We don't yet support SLP inductions for variable length vectors. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c b/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c
index be70bc6..484efb1 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c
@@ -62,7 +62,10 @@ main (void)
{
int p = power2 (fns[i].po2);
for (int j = 0; j < N; j++)
- a[j] = ((p << 4) * j) / (N - 1) - (p << 5);
+ {
+ a[j] = ((p << 4) * j) / (N - 1) - (p << 5);
+ asm volatile ("" ::: "memory");
+ }
fns[i].div (b, a, N);
fns[i].mod (c, a, N);
diff --git a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c
index 02f6f3d..2afd2b5 100644
--- a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c
+++ b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c
@@ -143,11 +143,11 @@ T (v0 ? b[1] : "", bsz);
T (v0 ? b[2] : "", bsz);
T (v0 ? b[3] : "", bsz);
-T (v0 ? "" : b[0], bsz + 1);
+T (v0 ? "" : b[0], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" } */
T (v0 ? "" : b[1], bsz + 1);
T (v0 ? "" : b[2], bsz + 1);
T (v0 ? "" : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
-T (v0 ? b[0] : "", bsz + 1);
+T (v0 ? b[0] : "", bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" } */
T (v0 ? b[1] : "", bsz + 1);
T (v0 ? b[2] : "", bsz + 1);
T (v0 ? b[3] : "", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
@@ -185,8 +185,8 @@ T (v0 ? "1234" : b[i3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfa
T (v0 ? b[3] : "1234", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
T (v0 ? b[i3] : "1234", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
-T (v0 ? a : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
-T (v0 ? b[0] : b[2], bsz + 1);
+T (v0 ? a : b[3], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" "pr86937" { xfail *-*-*} } */
+T (v0 ? b[0] : b[2], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" "pr86937" } */
T (v0 ? b[2] : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
T (v0 ? b[3] : b[2], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */
diff --git a/gcc/testsuite/gcc.misc-tests/godump-1.c b/gcc/testsuite/gcc.misc-tests/godump-1.c
index f97bbec..d37ab0b 100644
--- a/gcc/testsuite/gcc.misc-tests/godump-1.c
+++ b/gcc/testsuite/gcc.misc-tests/godump-1.c
@@ -396,6 +396,15 @@ typedef enum { ET1, ET2 } et_t;
/* { dg-final { scan-file godump-1.out "(?n)^const _ET1 = 0$" } } */
/* { dg-final { scan-file godump-1.out "(?n)^const _ET2 = 1$" } } */
+typedef enum e_t_idem_v1 { ETIV1 } e_t_idem_v1;
+/* { dg-final { scan-file godump-1.out "(?n)^type _e_t_idem_v1 u?int\[0-9\]*$" } } */
+/* { dg-final { scan-file godump-1.out "(?n)^const _ETIV1 = 0$" } } */
+
+typedef enum e_t_idem_v2 e_t_idem_v2;
+enum e_t_idem_v2 { ETIV2 };
+/* { dg-final { scan-file godump-1.out "(?n)^type _e_t_idem_v2 u?int\[0-9\]*$" } } */
+/* { dg-final { scan-file godump-1.out "(?n)^const _ETIV2 = 0$" } } */
+
enum { ETV1, ETV2 } et_v1;
/* { dg-final { scan-file godump-1.out "(?n)^var _et_v1 u?int\[0-9\]*$" } } */
/* { dg-final { scan-file godump-1.out "(?n)^const _ETV1 = 0$" } } */
@@ -471,9 +480,19 @@ typedef struct s_undef_t s_undef_t2;
typedef struct s_fwd *s_fwd_p;
/* { dg-final { scan-file godump-1.out "(?n)^type _s_fwd_p \\*_s_fwd$" } } */
+struct s_fwd v_fwd;
+/* { dg-final { scan-file godump-1.out "(?n)^var _v_fwd _s_fwd" } } */
+
struct s_fwd { };
/* { dg-final { scan-file godump-1.out "(?n)^type _s_fwd struct \{ \}$" } } */
+typedef struct s_t_idem_v1 {} s_t_idem_v1;
+/* { dg-final { scan-file godump-1.out "(?n)^type _s_t_idem_v1 struct \{ \}$" } } */
+
+typedef struct s_t_idem_v2 s_t_idem_v2;
+struct s_t_idem_v2 { };
+/* { dg-final { scan-file godump-1.out "(?n)^type _s_t_idem_v2 struct \{ \}$" } } */
+
/*** nested structs ***/
typedef struct { struct { uint8_t ca[3]; } s; uint32_t i; } tsn;
/* { dg-final { scan-file godump-1.out "(?n)^type _tsn struct \{ s struct \{ ca \\\[2\\+1\\\]uint8; \}; i uint32; \}$" } } */
@@ -753,6 +772,13 @@ typedef union { } tue;
union { } ue;
/* { dg-final { scan-file godump-1.out "(?n)^var _ue struct \{ \}$" } } */
+typedef union u_t_idem_v1 { } u_t_idem_v1;
+/* { dg-final { scan-file godump-1.out "(?n)^type _u_t_idem_v1 struct \{ \}$" } } */
+
+typedef union u_t_idem_v2 u_t_idem_v2;
+union u_t_idem_v2 { };
+/* { dg-final { scan-file godump-1.out "(?n)^type _u_t_idem_v2 struct \{ \}$" } } */
+
typedef union { uint8_t c; uint64_t l; } tu1;
/* { dg-final { scan-file godump-1.out "(?n)^type _tu1 struct \{ c uint8; Godump_0_pad \\\[.\\\]byte; Godump_1_align \\\[0\\\]u?int64; \}$" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest-2.h b/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest-2.h
index 5749219..b917938 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest-2.h
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest-2.h
@@ -66,7 +66,7 @@ MYFUNCTYPE myfunc () PCSATTR;
of bugs like a short vector being returned in X0 after copied from V0. */
#undef FUNC_VAL_CHECK
#define FUNC_VAL_CHECK(id, type, var, offset, layout) \
-__attribute__ ((noinline)) type FUNC_NAME (id) (int i, double d, type t) \
+__attribute__ ((noipa)) type FUNC_NAME (id) (int i, double d, type t) \
{ \
asm (""::"r" (i),"r" (d)); /* asm prevents function from getting \
optimized away. Using i and d prevents \
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest.h b/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest.h
index af70937..667f4d0f 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest.h
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/abitest.h
@@ -73,7 +73,7 @@ MYFUNCTYPE myfunc(
/* Dummy function to help reset parameter passing registers, i.e. X0-X7
and V0-V7 (by being passed 0 in W0-W7 and 0.f in S0-S7). */
-__attribute__ ((noinline)) void
+__attribute__ ((noipa)) void
dummy_func (int w0, int w1, int w2, int w3, int w4, int w5, int w6, int w7,
float s0, float s1, float s2, float s3, float s4, float s5,
float s6, float s7)
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/arm-neon-ref.h b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/arm-neon-ref.h
index 791972c..61fe7e7 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/arm-neon-ref.h
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/arm-neon-ref.h
@@ -11,6 +11,8 @@ typedef uint16_t hfloat16_t;
typedef uint32_t hfloat32_t;
typedef uint64_t hfloat64_t;
+typedef uint16_t hbfloat16_t;
+
extern void abort(void);
extern void *memset(void *, int, size_t);
extern void *memcpy(void *, const void *, size_t);
@@ -107,7 +109,7 @@ extern size_t strlen(const char *);
{ \
union fp_operand { \
uint##W##_t i; \
- float##W##_t f; \
+ T##W##_t f; \
} tmp_res, tmp_exp; \
tmp_res.f = VECT_VAR(result, T, W, N)[i]; \
tmp_exp.i = VECT_VAR(EXPECTED, h##T, W, N)[i]; \
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get-be.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get-be.c
new file mode 100644
index 0000000..bd9bb11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get-be.c
@@ -0,0 +1,27 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-mbig-endian -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" {-O[^0]} } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+
+#include <arm_neon.h>
+
+/*
+**test_vget_low_bf16:
+** ret
+*/
+bfloat16x4_t test_vget_low_bf16 (bfloat16x8_t a)
+{
+ return vget_low_bf16 (a);
+}
+
+/*
+**test_vget_high_bf16:
+** dup d0, v0.d\[1\]
+** ret
+*/
+bfloat16x4_t test_vget_high_bf16 (bfloat16x8_t a)
+{
+ return vget_high_bf16 (a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get.c
new file mode 100644
index 0000000..2193753
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_get.c
@@ -0,0 +1,27 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-save-temps" } */
+/* { dg-final { check-function-bodies "**" "" {-O[^0]} } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+
+#include <arm_neon.h>
+
+/*
+**test_vget_low_bf16:
+** ret
+*/
+bfloat16x4_t test_vget_low_bf16 (bfloat16x8_t a)
+{
+ return vget_low_bf16 (a);
+}
+
+/*
+**test_vget_high_bf16:
+** dup d0, v0.d\[1\]
+** ret
+*/
+bfloat16x4_t test_vget_high_bf16 (bfloat16x8_t a)
+{
+ return vget_high_bf16 (a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vect_copy_lane_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vect_copy_lane_1.c
new file mode 100644
index 0000000..d5aa215
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vect_copy_lane_1.c
@@ -0,0 +1,32 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-additional-options "-march=armv8.2-a+bf16 -O3 --save-temps -std=gnu90" } */
+
+#include "arm_neon.h"
+
+bfloat16x4_t __attribute__((noinline,noclone))
+test_vcopy_lane_bf16 (bfloat16x4_t a, bfloat16x4_t b)
+{
+ return vcopy_lane_bf16 (a, 1, b, 2);
+}
+
+bfloat16x8_t __attribute__((noinline,noclone))
+test_vcopyq_lane_bf16 (bfloat16x8_t a, bfloat16x4_t b)
+{
+ return vcopyq_lane_bf16 (a, 1, b, 2);
+}
+
+bfloat16x4_t __attribute__((noinline,noclone))
+test_vcopy_laneq_bf16 (bfloat16x4_t a, bfloat16x8_t b)
+{
+ return vcopy_laneq_bf16 (a, 1, b, 2);
+}
+
+bfloat16x8_t __attribute__((noinline,noclone))
+test_vcopyq_laneq_bf16 (bfloat16x8_t a, bfloat16x8_t b)
+{
+ return vcopyq_laneq_bf16 (a, 1, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "ins\\tv0.h\\\[1\\\], v1.h\\\[2\\\]" 2 } } */
+/* { dg-final { scan-assembler-times "ins\\tv0.h\\\[1\\\], v1.h\\\[0\\\]" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_1.c
new file mode 100644
index 0000000..a83ed3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_1.c
@@ -0,0 +1,74 @@
+/* { dg-do run { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+extern void abort (void);
+
+typedef union
+{
+ bfloat16_t bf16;
+ uint16_t u16;
+} bfloat16_u_t;
+
+#define VARIANTS(VARIANT, STRUCT) \
+VARIANT (bfloat16, , 4, _bf16, 3, STRUCT) \
+VARIANT (bfloat16, q, 8, _bf16, 7, STRUCT)
+
+#define TESTMETH(BASE, Q, ELTS, SUFFIX, LANE, STRUCT) \
+ int \
+ test_vld##STRUCT##Q##_lane##SUFFIX (const bfloat16_u_t *data, \
+ const bfloat16_u_t *overwrite) \
+ { \
+ BASE##x##ELTS##x##STRUCT##_t vectors; \
+ bfloat16_u_t temp[ELTS]; \
+ int i,j; \
+ for (i = 0; i < STRUCT; i++, data += ELTS) \
+ vectors.val[i] = vld1##Q##SUFFIX ((bfloat16_t *)data); \
+ vectors = vld##STRUCT##Q##_lane##SUFFIX ((bfloat16_t *) overwrite, \
+ vectors, LANE); \
+ while (--i >= 0) \
+ { \
+ vst1##Q##SUFFIX ((bfloat16_t *)temp, vectors.val[i]); \
+ data -= ELTS; /* Point at value loaded before vldN_lane. */ \
+ for (j = 0; j < ELTS; j++) \
+ if (temp[j].u16 != (j == LANE ? overwrite[i].u16 : data[j].u16)) \
+ return 1; \
+ } \
+ return 0; \
+ }
+
+/* Tests of vld2_lane and vld2q_lane. */
+VARIANTS (TESTMETH, 2)
+/* Tests of vld3_lane and vld3q_lane. */
+VARIANTS (TESTMETH, 3)
+/* Tests of vld4_lane and vld4q_lane. */
+VARIANTS (TESTMETH, 4)
+
+#define CHECK(BASE, Q, ELTS, SUFFIX, LANE, STRUCT) \
+ if (test_vld##STRUCT##Q##_lane##SUFFIX ((const bfloat16_u_t *)orig_data, \
+ BASE##_data) != 0) \
+ abort ();
+
+int
+main (int argc, char **argv)
+{
+ /* Original data for all vector formats. */
+ uint64_t orig_data[8] = {0x1234567890abcdefULL, 0x13579bdf02468aceULL,
+ 0x012389ab4567cdefULL, 0xdeeddadacafe0431ULL,
+ 0x1032547698badcfeULL, 0xbadbadbadbad0badULL,
+ 0x0102030405060708ULL, 0x0f0e0d0c0b0a0908ULL};
+
+ /* Data with which vldN_lane will overwrite some of previous. */
+ bfloat16_u_t bfloat16_data[4];
+ bfloat16_data[0].u16 = 0xABAB;
+ bfloat16_data[1].u16 = 0x0;
+ bfloat16_data[2].u16 = 0xCAFE;
+ bfloat16_data[3].u16 = 0x1234;
+
+ VARIANTS (CHECK, 2);
+ VARIANTS (CHECK, 3);
+ VARIANTS (CHECK, 4);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_2.c
new file mode 100644
index 0000000..670cf0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vldN_lane_2.c
@@ -0,0 +1,52 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-O2 --save-temps" } */
+
+#include <arm_neon.h>
+
+bfloat16x4x2_t
+test_vld2_lane_bf16 (const bfloat16_t *ptr, bfloat16x4x2_t b)
+{
+ return vld2_lane_bf16 (ptr, b, 2);
+}
+
+bfloat16x8x2_t
+test_vld2q_lane_bf16 (const bfloat16_t *ptr, bfloat16x8x2_t b)
+{
+ return vld2q_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "ld2\\t{v2.h - v3.h}\\\[2\\\], \\\[x0\\\]" 2 } } */
+
+bfloat16x4x3_t
+test_vld3_lane_bf16 (const bfloat16_t *ptr, bfloat16x4x3_t b)
+{
+ return vld3_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "ld3\t{v4.h - v6.h}\\\[2\\\], \\\[x0\\\]" 1 } } */
+
+bfloat16x8x3_t
+test_vld3q_lane_bf16 (const bfloat16_t *ptr, bfloat16x8x3_t b)
+{
+ return vld3q_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "ld3\t{v1.h - v3.h}\\\[2\\\], \\\[x0\\\]" 1 } } */
+
+bfloat16x4x4_t
+test_vld4_lane_bf16 (const bfloat16_t *ptr, bfloat16x4x4_t b)
+{
+ return vld4_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "ld4\t{v4.h - v7.h}\\\[2\\\], \\\[x0\\\]" 1 } } */
+
+bfloat16x8x4_t
+test_vld4q_lane_bf16 (const bfloat16_t *ptr, bfloat16x8x4_t b)
+{
+ return vld4q_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "ld4\t{v0.h - v3.h}\\\[2\\\], \\\[x0\\\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_1.c
new file mode 100644
index 0000000..2c70bb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_1.c
@@ -0,0 +1,227 @@
+/* { dg-do run { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+#include "arm-neon-ref.h"
+#include "compute-ref-data.h"
+
+/* Expected results for vst2, chunk 0. */
+VECT_VAR_DECL(expected_st2_0,hbfloat,16,4) [] = { 0xABAB, 0x3210, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st2_0,hbfloat,16,8) [] = { 0xABAB, 0x3210, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst2, chunk 1. */
+VECT_VAR_DECL(expected_st2_1,hbfloat,16,4) [] = { 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st2_1,hbfloat,16,8) [] = { 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst3, chunk 0. */
+VECT_VAR_DECL(expected_st3_0,hbfloat,16,4) [] = { 0xABAB, 0x3210, 0xCAFE, 0x0 };
+VECT_VAR_DECL(expected_st3_0,hbfloat,16,8) [] = { 0xABAB, 0x3210, 0xCAFE, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst3, chunk 1. */
+VECT_VAR_DECL(expected_st3_1,hbfloat,16,4) [] = { 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st3_1,hbfloat,16,8) [] = { 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst3, chunk 2. */
+VECT_VAR_DECL(expected_st3_2,hbfloat,16,4) [] = { 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st3_2,hbfloat,16,8) [] = { 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst4, chunk 0. */
+VECT_VAR_DECL(expected_st4_0,hbfloat,16,4) [] =
+ { 0xABAB, 0x3210, 0xCAFE, 0x1234 };
+VECT_VAR_DECL(expected_st4_0,hbfloat,16,8) [] =
+ { 0xABAB, 0x3210, 0xCAFE, 0x1234, 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst4, chunk 1. */
+VECT_VAR_DECL(expected_st4_1,hbfloat,16,4) [] = { 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st4_1,hbfloat,16,8) [] = { 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst4, chunk 2. */
+VECT_VAR_DECL(expected_st4_2,hbfloat,16,4) [] = { 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st4_2,hbfloat,16,8) [] = { 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+/* Expected results for vst4, chunk 3. */
+VECT_VAR_DECL(expected_st4_3,hbfloat,16,4) [] = { 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_st4_3,hbfloat,16,8) [] = { 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+
+typedef union
+{
+ bfloat16_t bf16;
+ uint16_t u16;
+} bfloat16_u_t;
+
+static bfloat16_t result_bfloat16x4[4];
+static bfloat16_t result_bfloat16x8[8];
+
+void exec_vstX_lane (void)
+{
+ bfloat16_u_t bfloat16_data[4];
+ bfloat16_data[0].u16 = 0xABAB;
+ bfloat16_data[1].u16 = 0x3210;
+ bfloat16_data[2].u16 = 0xCAFE;
+ bfloat16_data[3].u16 = 0x1234;
+
+ bfloat16_t buffer_vld2_lane_bfloat16x2 [2] =
+ { bfloat16_data[0].bf16,
+ bfloat16_data[1].bf16 };
+ bfloat16_t buffer_vld3_lane_bfloat16x3 [3] =
+ { bfloat16_data[0].bf16,
+ bfloat16_data[1].bf16,
+ bfloat16_data[2].bf16 };
+ bfloat16_t buffer_vld4_lane_bfloat16x4 [4] =
+ { bfloat16_data[0].bf16,
+ bfloat16_data[1].bf16,
+ bfloat16_data[2].bf16,
+ bfloat16_data[3].bf16 };
+
+ /* In this case, input variables are arrays of vectors. */
+#define DECL_VSTX_LANE(T1, W, N, X) \
+ VECT_ARRAY_TYPE(T1, W, N, X) VECT_ARRAY_VAR(vector, T1, W, N, X); \
+ VECT_ARRAY_TYPE(T1, W, N, X) VECT_ARRAY_VAR(vector_src, T1, W, N, X); \
+ VECT_VAR_DECL(result_bis_##X, T1, W, N)[X * N]
+
+ /* We need to use a temporary result buffer (result_bis), because
+ the one used for other tests is not large enough. A subset of the
+ result data is moved from result_bis to result, and it is this
+ subset which is used to check the actual behavior. The next
+ macro enables to move another chunk of data from result_bis to
+ result. */
+ /* We also use another extra input buffer (buffer_src), which we
+ fill with 0xAA, and which it used to load a vector from which we
+ read a given lane. */
+#define TEST_VSTX_LANE(Q, T1, T2, W, N, X, L) \
+ memset (VECT_VAR(buffer_src, T1, W, N), 0xAA, \
+ sizeof(VECT_VAR(buffer_src, T1, W, N))); \
+ memset (VECT_VAR(result_bis_##X, T1, W, N), 0, \
+ sizeof(VECT_VAR(result_bis_##X, T1, W, N))); \
+ \
+ VECT_ARRAY_VAR(vector_src, T1, W, N, X) = \
+ vld##X##Q##_##T2##W(VECT_VAR(buffer_src, T1, W, N)); \
+ \
+ VECT_ARRAY_VAR(vector, T1, W, N, X) = \
+ /* Use dedicated init buffer, of size X. */ \
+ vld##X##Q##_lane_##T2##W(VECT_VAR(buffer_vld##X##_lane, T1, W, X), \
+ VECT_ARRAY_VAR(vector_src, T1, W, N, X), \
+ L); \
+ vst##X##Q##_lane_##T2##W(VECT_VAR(result_bis_##X, T1, W, N), \
+ VECT_ARRAY_VAR(vector, T1, W, N, X), \
+ L); \
+ memcpy(VECT_VAR(result, T1, W, N), VECT_VAR(result_bis_##X, T1, W, N), \
+ sizeof(VECT_VAR(result, T1, W, N)));
+
+ /* Overwrite "result" with the contents of "result_bis"[Y]. */
+#define TEST_EXTRA_CHUNK(T1, W, N, X, Y) \
+ memcpy(VECT_VAR(result, T1, W, N), \
+ &(VECT_VAR(result_bis_##X, T1, W, N)[Y*N]), \
+ sizeof(VECT_VAR(result, T1, W, N)));
+
+#define DUMMY_ARRAY(V, T, W, N, L) VECT_VAR_DECL(V,T,W,N)[N*L]
+
+ DECL_VSTX_LANE(bfloat, 16, 4, 2);
+ DECL_VSTX_LANE(bfloat, 16, 8, 2);
+ DECL_VSTX_LANE(bfloat, 16, 4, 3);
+ DECL_VSTX_LANE(bfloat, 16, 8, 3);
+ DECL_VSTX_LANE(bfloat, 16, 4, 4);
+ DECL_VSTX_LANE(bfloat, 16, 8, 4);
+
+ DUMMY_ARRAY(buffer_src, bfloat, 16, 4, 4);
+ DUMMY_ARRAY(buffer_src, bfloat, 16, 8, 4);
+
+ /* Check vst2_lane/vst2q_lane. */
+ clean_results ();
+ TEST_VSTX_LANE(, bfloat, bf, 16, 4, 2, 2);
+ TEST_VSTX_LANE(q, bfloat, bf, 16, 8, 2, 6);
+
+#undef CMT
+#define CMT " (chunk 0)"
+#undef TEST_MSG
+#define TEST_MSG "VST2_LANE/VST2Q_LANE"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st2_0, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st2_0, CMT);
+ TEST_EXTRA_CHUNK(bfloat, 16, 4, 2, 1);
+ TEST_EXTRA_CHUNK(bfloat, 16, 8, 2, 1);
+
+#undef CMT
+#define CMT " (chunk 1)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st2_1, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st2_1, CMT);
+
+ /* Check vst3_lane/vst3q_lane. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VST3_LANE/VST3Q_LANE"
+ TEST_VSTX_LANE(, bfloat, bf, 16, 4, 3, 2);
+ TEST_VSTX_LANE(q, bfloat, bf, 16, 8, 3, 6);
+
+#undef CMT
+#define CMT " (chunk 0)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st3_0, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st3_0, CMT);
+
+ TEST_EXTRA_CHUNK(bfloat, 16, 4, 3, 1);
+ TEST_EXTRA_CHUNK(bfloat, 16, 8, 3, 1);
+
+
+#undef CMT
+#define CMT " (chunk 1)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st3_1, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st3_1, CMT);
+
+ TEST_EXTRA_CHUNK(bfloat, 16, 4, 3, 2);
+ TEST_EXTRA_CHUNK(bfloat, 16, 8, 3, 2);
+
+#undef CMT
+#define CMT " (chunk 2)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st3_2, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st3_2, CMT);
+
+ /* Check vst4_lane/vst4q_lane. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VST4_LANE/VST4Q_LANE"
+ TEST_VSTX_LANE(, bfloat, bf, 16, 4, 4, 2);
+ TEST_VSTX_LANE(q, bfloat, bf, 16, 8, 4, 6);
+
+#undef CMT
+#define CMT " (chunk 0)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st4_0, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st4_0, CMT);
+
+ TEST_EXTRA_CHUNK(bfloat, 16, 4, 4, 1);
+ TEST_EXTRA_CHUNK(bfloat, 16, 8, 4, 1);
+
+#undef CMT
+#define CMT " (chunk 1)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st4_1, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st4_1, CMT);
+
+ TEST_EXTRA_CHUNK(bfloat, 16, 4, 4, 2);
+ TEST_EXTRA_CHUNK(bfloat, 16, 8, 4, 2);
+
+#undef CMT
+#define CMT " (chunk 2)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st4_2, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st4_2, CMT);
+
+ TEST_EXTRA_CHUNK(bfloat, 16, 4, 4, 3);
+ TEST_EXTRA_CHUNK(bfloat, 16, 8, 4, 3);
+
+#undef CMT
+#define CMT " (chunk 3)"
+ CHECK_FP(TEST_MSG, bfloat, 16, 4, PRIx16, expected_st4_3, CMT);
+ CHECK_FP(TEST_MSG, bfloat, 16, 8, PRIx16, expected_st4_3, CMT);
+}
+
+int main (void)
+{
+ exec_vstX_lane ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_2.c
new file mode 100644
index 0000000..822968d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bf16_vstN_lane_2.c
@@ -0,0 +1,48 @@
+/* { dg-do assemble { target { aarch64*-*-* } } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-O2 --save-temps" } */
+
+#include <arm_neon.h>
+
+void
+test_vst2_lane_bf16 (bfloat16_t *ptr, bfloat16x4x2_t b)
+{
+ vst2_lane_bf16 (ptr, b, 2);
+}
+
+void
+test_vst2q_lane_bf16 (bfloat16_t *ptr, bfloat16x8x2_t b)
+{
+ vst2q_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "st2\\t{v\[0-9\]+.h - v\[0-9\]+.h}\\\[2\\\], \\\[x\[0-9\]+\\\]" 2 } } */
+
+void
+test_vst3_lane_bf16 (bfloat16_t *ptr, bfloat16x4x3_t b)
+{
+ vst3_lane_bf16 (ptr, b, 2);
+}
+
+void
+test_vst3q_lane_bf16 (bfloat16_t *ptr, bfloat16x8x3_t b)
+{
+ vst3q_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "st3\\t{v\[0-9\]+.h - v\[0-9\]+.h}\\\[2\\\], \\\[x\[0-9\]+\\\]" 2 } } */
+
+void
+test_vst4_lane_bf16 (bfloat16_t *ptr, bfloat16x4x4_t b)
+{
+ vst4_lane_bf16 (ptr, b, 2);
+}
+
+void
+test_vst4q_lane_bf16 (bfloat16_t *ptr, bfloat16x8x4_t b)
+{
+ vst4q_lane_bf16 (ptr, b, 2);
+}
+
+/* { dg-final { scan-assembler-times "st4\\t{v\[0-9\]+.h - v\[0-9\]+.h}\\\[2\\\], \\\[x\[0-9\]+\\\]" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bfcvt-compile.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bfcvt-compile.c
index bbea630..47af7c4 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bfcvt-compile.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/bfcvt-compile.c
@@ -46,3 +46,43 @@ bfloat16_t test_bfcvt (float32_t a)
{
return vcvth_bf16_f32 (a);
}
+
+/*
+**test_vcvt_f32_bf16:
+** shll v0.4s, v0.4h, #16
+** ret
+*/
+float32x4_t test_vcvt_f32_bf16 (bfloat16x4_t a)
+{
+ return vcvt_f32_bf16 (a);
+}
+
+/*
+**test_vcvtq_low_f32_bf16:
+** shll v0.4s, v0.4h, #16
+** ret
+*/
+float32x4_t test_vcvtq_low_f32_bf16 (bfloat16x8_t a)
+{
+ return vcvtq_low_f32_bf16 (a);
+}
+
+/*
+**test_vcvtq_high_f32_bf16:
+** shll2 v0.4s, v0.8h, #16
+** ret
+*/
+float32x4_t test_vcvtq_high_f32_bf16 (bfloat16x8_t a)
+{
+ return vcvtq_high_f32_bf16 (a);
+}
+
+/*
+**test_vcvtah_f32_bf16:
+** shl d0, d0, #16
+** ret
+*/
+float32_t test_vcvtah_f32_bf16 (bfloat16_t a)
+{
+ return vcvtah_f32_bf16 (a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_1.c
new file mode 100644
index 0000000..7057980
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4_t
+test_vcopy_lane_bf16 (bfloat16x4_t a, bfloat16x4_t b)
+{
+ bfloat16x4_t res;
+ res = vcopy_lane_bf16 (a, 0, b, 4);
+ res = vcopy_lane_bf16 (a, 0, b, -1);
+ return res;
+}
+
+/* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+/* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_2.c
new file mode 100644
index 0000000..a8ef930
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_lane_bf16_indices_2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4_t
+test_vcopy_lane_bf16 (bfloat16x4_t a, bfloat16x4_t b)
+{
+ bfloat16x4_t res;
+ res = vcopy_lane_bf16 (a, -1, b, 2);
+ res = vcopy_lane_bf16 (a, 4, b, 2);
+ return res;
+}
+
+/* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+/* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_1.c
new file mode 100644
index 0000000..c156204
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4_t
+test_vcopy_laneq_bf16 (bfloat16x4_t a, bfloat16x8_t b)
+{
+ bfloat16x4_t res;
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vcopy_laneq_bf16 (a, -1, b, 2);
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vcopy_laneq_bf16 (a, 4, b, 2);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_2.c
new file mode 100644
index 0000000..036690b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopy_laneq_bf16_indices_2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4_t
+test_vcopy_laneq_bf16 (bfloat16x4_t a, bfloat16x8_t b)
+{
+ bfloat16x4_t res;
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopy_laneq_bf16 (a, 1, b, -1);
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopy_laneq_bf16 (a, 1, b, 8);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_1.c
new file mode 100644
index 0000000..15fce1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8_t
+test_vcopyq_lane_bf16 (bfloat16x8_t a, bfloat16x4_t b)
+{
+ bfloat16x8_t res;
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopyq_lane_bf16 (a, -1, b, 2);
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopyq_lane_bf16 (a, 8, b, 2);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_2.c
new file mode 100644
index 0000000..6e8004a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_lane_bf16_indices_2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8_t
+test_vcopyq_lane_bf16 (bfloat16x8_t a, bfloat16x4_t b)
+{
+ bfloat16x8_t res;
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vcopyq_lane_bf16 (a, 2, b, -1);
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vcopyq_lane_bf16 (a, 2, b, 4);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_1.c
new file mode 100644
index 0000000..2a26b42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8_t
+test_vcopyq_laneq_bf16 (bfloat16x8_t a, bfloat16x8_t b)
+{
+ bfloat16x8_t res;
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopyq_laneq_bf16 (a, -1, b, 2);
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopyq_laneq_bf16 (a, 8, b, 2);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_2.c
new file mode 100644
index 0000000..421cb2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vcopyq_laneq_bf16_indices_2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { aarch64*-*-* } } } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8_t
+test_vcopyq_laneq_bf16 (bfloat16x8_t a, bfloat16x8_t b)
+{
+ bfloat16x8_t res;
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopyq_laneq_bf16 (a, 2, b, -1);
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vcopyq_laneq_bf16 (a, 2, b, 8);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2_lane_bf16_indices_1.c
new file mode 100644
index 0000000..d568a26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4x2_t
+f_vld2_lane_bf16 (bfloat16_t * p, bfloat16x4x2_t v)
+{
+ bfloat16x4x2_t res;
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vld2_lane_bf16 (p, v, 4);
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vld2_lane_bf16 (p, v, -1);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..b91f14a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld2q_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8x2_t
+f_vld2q_lane_bf16 (bfloat16_t * p, bfloat16x8x2_t v)
+{
+ bfloat16x8x2_t res;
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vld2q_lane_bf16 (p, v, 8);
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vld2q_lane_bf16 (p, v, -1);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3_lane_bf16_indices_1.c
new file mode 100644
index 0000000..331abf4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4x3_t
+f_vld3_lane_bf16 (bfloat16_t * p, bfloat16x4x3_t v)
+{
+ bfloat16x4x3_t res;
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vld3_lane_bf16 (p, v, 4);
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vld3_lane_bf16 (p, v, -1);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..1c52887
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld3q_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8x3_t
+f_vld3q_lane_bf16 (bfloat16_t * p, bfloat16x8x3_t v)
+{
+ bfloat16x8x3_t res;
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vld3q_lane_bf16 (p, v, 8);
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vld3q_lane_bf16 (p, v, -1);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4_lane_bf16_indices_1.c
new file mode 100644
index 0000000..3f486f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x4x4_t
+f_vld4_lane_bf16 (bfloat16_t * p, bfloat16x4x4_t v)
+{
+ bfloat16x4x4_t res;
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vld4_lane_bf16 (p, v, 4);
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ res = vld4_lane_bf16 (p, v, -1);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..7159cd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld4q_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+bfloat16x8x4_t
+f_vld4q_lane_bf16 (bfloat16_t * p, bfloat16x8x4_t v)
+{
+ bfloat16x8x4_t res;
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vld4q_lane_bf16 (p, v, 8);
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ res = vld4q_lane_bf16 (p, v, -1);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrn_high_n.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrn_high_n.c
new file mode 100644
index 0000000..6ebe074
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrn_high_n.c
@@ -0,0 +1,195 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { arm*-*-* } } */
+
+#include <arm_neon.h>
+#include "arm-neon-ref.h"
+#include "compute-ref-data.h"
+
+/* Expected results. */
+VECT_VAR_DECL(expected,int,8,16) [] = { 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfb, 0xfb, 0xfc };
+VECT_VAR_DECL(expected,int,16,8) [] = { 0xfff0, 0xfff1, 0xfff2, 0xfff3,
+ 0xfff8, 0xfff9, 0xfff9, 0xfffa };
+VECT_VAR_DECL(expected,int,32,4) [] = { 0xfffffff0, 0xfffffff1,
+ 0xfffffffc, 0xfffffffc };
+VECT_VAR_DECL(expected,uint,8,16) [] = { 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected,uint,16,8) [] = { 0xfff0, 0xfff1, 0xfff2, 0xfff3,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected,uint,32,4) [] = { 0xfffffff0, 0xfffffff1,
+ 0xffffffff, 0xffffffff };
+
+/* Expected results with shift by 3. */
+VECT_VAR_DECL(expected_sh3,int,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f };
+VECT_VAR_DECL(expected_sh3,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0x7fff, 0x7fff, 0x7fff, 0x7fff };
+VECT_VAR_DECL(expected_sh3,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0x7fffffff, 0x7fffffff };
+VECT_VAR_DECL(expected_sh3,uint,8,16) [] = { 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected_sh3,uint,16,8) [] = { 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected_sh3,uint,32,4) [] = { 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff };
+
+/* Expected results with shift by max amount. */
+VECT_VAR_DECL(expected_shmax,int,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f };
+VECT_VAR_DECL(expected_shmax,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0x7fff, 0x7fff, 0x7fff, 0x7fff };
+VECT_VAR_DECL(expected_shmax,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0x7fffffff, 0x7fffffff };
+VECT_VAR_DECL(expected_shmax,uint,8,16) [] = { 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected_shmax,uint,16,8) [] = { 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected_shmax,uint,32,4) [] = { 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff };
+
+#define INSN vqrshrn_high_n
+#define TEST_MSG "VQRSHRN_HIGH_N"
+
+#define FNNAME1(NAME) void exec_ ## NAME (void)
+#define FNNAME(NAME) FNNAME1(NAME)
+
+FNNAME (INSN)
+{
+ /* Basic test: y=vqrshrn_high_n(x,v), then store the result. */
+#define TEST_VQRSHRN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V) \
+ VECT_VAR(vector_res, T1, W2, N2) = \
+ INSN##_##T2##W(VECT_VAR(vector1, T1, W2, N), \
+ VECT_VAR(vector2, T1, W, N), V); \
+ vst1q_##T2##W2(VECT_VAR(result, T1, W2, N2), \
+ VECT_VAR(vector_res, T1, W2, N2)); \
+
+ /* Two auxliary macros are necessary to expand INSN */
+#define TEST_VQRSHRN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V) \
+ TEST_VQRSHRN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V)
+
+#define TEST_VQRSHRN_HIGH_N(T1, T2, W, W2, N, N2, V) \
+ TEST_VQRSHRN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V)
+
+
+ DECL_VARIABLE(vector1, int, 8, 8);
+ DECL_VARIABLE(vector1, int, 16, 4);
+ DECL_VARIABLE(vector1, int, 32, 2);
+ DECL_VARIABLE(vector1, uint, 8, 8);
+ DECL_VARIABLE(vector1, uint, 16, 4);
+ DECL_VARIABLE(vector1, uint, 32, 2);
+
+ /* vector is twice as large as vector_res. */
+ DECL_VARIABLE(vector2, int, 16, 8);
+ DECL_VARIABLE(vector2, int, 32, 4);
+ DECL_VARIABLE(vector2, int, 64, 2);
+ DECL_VARIABLE(vector2, uint, 16, 8);
+ DECL_VARIABLE(vector2, uint, 32, 4);
+ DECL_VARIABLE(vector2, uint, 64, 2);
+
+ DECL_VARIABLE(vector_res, int, 8, 16);
+ DECL_VARIABLE(vector_res, int, 16, 8);
+ DECL_VARIABLE(vector_res, int, 32, 4);
+ DECL_VARIABLE(vector_res, uint, 8, 16);
+ DECL_VARIABLE(vector_res, uint, 16, 8);
+ DECL_VARIABLE(vector_res, uint, 32, 4);
+
+ clean_results ();
+
+ VLOAD(vector1, buffer, , int, s, 8, 8);
+ VLOAD(vector1, buffer, , int, s, 16, 4);
+ VLOAD(vector1, buffer, , int, s, 32, 2);
+ VLOAD(vector1, buffer, , uint, u, 8, 8);
+ VLOAD(vector1, buffer, , uint, u, 16, 4);
+ VLOAD(vector1, buffer, , uint, u, 32, 2);
+
+ VLOAD(vector2, buffer, q, int, s, 16, 8);
+ VLOAD(vector2, buffer, q, int, s, 32, 4);
+ VLOAD(vector2, buffer, q, int, s, 64, 2);
+ VLOAD(vector2, buffer, q, uint, u, 16, 8);
+ VLOAD(vector2, buffer, q, uint, u, 32, 4);
+ VLOAD(vector2, buffer, q, uint, u, 64, 2);
+
+ /* Choose shift amount arbitrarily. */
+#define CMT ""
+ TEST_VQRSHRN_HIGH_N(int, s, 16, 8, 8, 16, 1);
+ TEST_VQRSHRN_HIGH_N(int, s, 32, 16, 4, 8, 1);
+ TEST_VQRSHRN_HIGH_N(int, s, 64, 32, 2, 4, 2);
+ TEST_VQRSHRN_HIGH_N(uint, u, 16, 8, 8, 16, 2);
+ TEST_VQRSHRN_HIGH_N(uint, u, 32, 16, 4, 8, 3);
+ TEST_VQRSHRN_HIGH_N(uint, u, 64, 32, 2, 4, 3);
+
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected, CMT);
+ CHECK(TEST_MSG, int, 16, 8, PRIx16, expected, CMT);
+ CHECK(TEST_MSG, int, 32, 4, PRIx32, expected, CMT);
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected, CMT);
+
+
+ /* Another set of tests, shifting max value by 3. */
+ VDUP(vector1, , int, s, 8, 8, 0x7F);
+ VDUP(vector1, , int, s, 16, 4, 0x7FFF);
+ VDUP(vector1, , int, s, 32, 2, 0x7FFFFFFFLL);
+ VDUP(vector1, , uint, u, 8, 8, 0xFF);
+ VDUP(vector1, , uint, u, 16, 4, 0xFFFF);
+ VDUP(vector1, , uint, u, 32, 2, 0xFFFFFFFFULL);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x7FFF);
+ VDUP(vector2, q, int, s, 32, 4, 0x7FFFFFFF);
+ VDUP(vector2, q, int, s, 64, 2, 0x7FFFFFFFFFFFFFFFLL);
+ VDUP(vector2, q, uint, u, 16, 8, 0xFFFF);
+ VDUP(vector2, q, uint, u, 32, 4, 0xFFFFFFFF);
+ VDUP(vector2, q, uint, u, 64, 2, 0xFFFFFFFFFFFFFFFFULL);
+
+#undef CMT
+#define CMT " (check saturation: shift by 3)"
+ TEST_VQRSHRN_HIGH_N(int, s, 16, 8, 8, 16, 3);
+ TEST_VQRSHRN_HIGH_N(int, s, 32, 16, 4, 8, 3);
+ TEST_VQRSHRN_HIGH_N(int, s, 64, 32, 2, 4, 3);
+ TEST_VQRSHRN_HIGH_N(uint, u, 16, 8, 8, 16, 3);
+ TEST_VQRSHRN_HIGH_N(uint, u, 32, 16, 4, 8, 3);
+ TEST_VQRSHRN_HIGH_N(uint, u, 64, 32, 2, 4, 3);
+
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_sh3, CMT);
+ CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_sh3, CMT);
+ CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_sh3, CMT);
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_sh3, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_sh3, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_sh3, CMT);
+
+
+ /* Shift by max amount. */
+#undef CMT
+#define CMT " (check saturation: shift by max)"
+ TEST_VQRSHRN_HIGH_N(int, s, 16, 8, 8, 16, 8);
+ TEST_VQRSHRN_HIGH_N(int, s, 32, 16, 4, 8, 16);
+ TEST_VQRSHRN_HIGH_N(int, s, 64, 32, 2, 4, 32);
+ TEST_VQRSHRN_HIGH_N(uint, u, 16, 8, 8, 16, 8);
+ TEST_VQRSHRN_HIGH_N(uint, u, 32, 16, 4, 8, 16);
+ TEST_VQRSHRN_HIGH_N(uint, u, 64, 32, 2, 4, 32);
+
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_shmax, CMT);
+ CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_shmax, CMT);
+ CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_shmax, CMT);
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_shmax, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_shmax, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_shmax, CMT);
+}
+
+int main (void)
+{
+ exec_vqrshrn_high_n ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrun_high_n.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrun_high_n.c
new file mode 100644
index 0000000..49d319d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqrshrun_high_n.c
@@ -0,0 +1,197 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { arm*-*-* } } */
+
+#include <arm_neon.h>
+#include "arm-neon-ref.h"
+#include "compute-ref-data.h"
+
+/* Expected results with negative input. */
+VECT_VAR_DECL(expected_neg,uint,8,16) [] = { 0xfe, 0xfe, 0xfe, 0xfe,
+ 0xfe, 0xfe, 0xfe, 0xfe,
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_neg,uint,16,8) [] = { 0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_neg,uint,32,4) [] = { 0xfffffffc, 0xfffffffc, 0x0, 0x0 };
+
+/* Expected results with max input value shifted by 1. */
+VECT_VAR_DECL(expected_max_sh1,uint,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected_max_sh1,uint,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected_max_sh1,uint,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0xffffffff, 0xffffffff };
+
+/* Expected results with max input value shifted by max amount. */
+VECT_VAR_DECL(expected_max_shmax,uint,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80 };
+VECT_VAR_DECL(expected_max_shmax,uint,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0x8000, 0x8000, 0x8000, 0x8000 };
+VECT_VAR_DECL(expected_max_shmax,uint,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0x80000000, 0x80000000 };
+
+/* Expected results with min input value shifted by max amount. */
+VECT_VAR_DECL(expected_min_shmax,uint,8,16) [] = { 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80,
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_min_shmax,uint,16,8) [] = { 0x8000, 0x8000, 0x8000, 0x8000,
+ 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_min_shmax,uint,32,4) [] = { 0x80000000, 0x80000000,
+ 0x0, 0x0 };
+
+/* Expected results with inputs in usual range. */
+VECT_VAR_DECL(expected,uint,8,16) [] = { 0x12, 0x12, 0x12, 0x12,
+ 0x12, 0x12, 0x12, 0x12,
+ 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49 };
+VECT_VAR_DECL(expected,uint,16,8) [] = { 0x4321, 0x4321, 0x4321, 0x4321,
+ 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected,uint,32,4) [] = { 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbf, 0xdeadbf };
+
+#define INSN vqrshrun_high_n
+#define TEST_MSG "VQRSHRUN_HIGH_N"
+
+#define FNNAME1(NAME) void exec_ ## NAME (void)
+#define FNNAME(NAME) FNNAME1(NAME)
+
+FNNAME (INSN)
+{
+ /* Basic test: y=vqrshrun_high_n(x,v), then store the result. */
+#define TEST_VQRSHRUN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V) \
+ VECT_VAR(vector_res, uint, W2, N2) = \
+ INSN##_##T2##W(VECT_VAR(vector1, uint, W2, N), \
+ VECT_VAR(vector2, T1, W, N), V); \
+ vst1q_u##W2(VECT_VAR(result, uint, W2, N2), \
+ VECT_VAR(vector_res, uint, W2, N2)); \
+
+ /* Two auxliary macros are necessary to expand INSN */
+#define TEST_VQRSHRUN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V) \
+ TEST_VQRSHRUN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V)
+
+#define TEST_VQRSHRUN_HIGH_N(T1, T2, W, W2, N, N2, V) \
+ TEST_VQRSHRUN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V)
+
+
+ DECL_VARIABLE(vector1, uint, 8, 8);
+ DECL_VARIABLE(vector1, uint, 16, 4);
+ DECL_VARIABLE(vector1, uint, 32, 2);
+
+ /* vector is twice as large as vector_res. */
+ DECL_VARIABLE(vector2, int, 16, 8);
+ DECL_VARIABLE(vector2, int, 32, 4);
+ DECL_VARIABLE(vector2, int, 64, 2);
+
+ DECL_VARIABLE(vector_res, uint, 8, 16);
+ DECL_VARIABLE(vector_res, uint, 16, 8);
+ DECL_VARIABLE(vector_res, uint, 32, 4);
+
+ clean_results ();
+
+ /* Fill input vector with negative values, to check saturation on
+ limits. */
+ VDUP(vector1, , uint, u, 8, 8, -2);
+ VDUP(vector1, , uint, u, 16, 4, -3);
+ VDUP(vector1, , uint, u, 32, 2, -4);
+
+ VDUP(vector2, q, int, s, 16, 8, -2);
+ VDUP(vector2, q, int, s, 32, 4, -3);
+ VDUP(vector2, q, int, s, 64, 2, -4);
+
+ /* Choose shift amount arbitrarily. */
+#define CMT " (negative input)"
+ TEST_VQRSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 3);
+ TEST_VQRSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 4);
+ TEST_VQRSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 2);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_neg, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_neg, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_neg, CMT);
+
+
+ /* Fill input vector with max value, to check saturation on
+ limits. */
+ VDUP(vector1, , uint, u, 8, 8, 0x7F);
+ VDUP(vector1, , uint, u, 16, 4, 0x7FFF);
+ VDUP(vector1, , uint, u, 32, 2, 0x7FFFFFFFLL);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x7FFF);
+ VDUP(vector2, q, int, s, 32, 4, 0x7FFFFFFF);
+ VDUP(vector2, q, int, s, 64, 2, 0x7FFFFFFFFFFFFFFFLL);
+
+ /* shift by 1. */
+#undef CMT
+#define CMT " (check cumulative saturation: shift by 1)"
+ TEST_VQRSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 1);
+ TEST_VQRSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 1);
+ TEST_VQRSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 1);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_max_sh1, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_max_sh1, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_max_sh1, CMT);
+
+
+ /* shift by max. */
+#undef CMT
+#define CMT " (check cumulative saturation: shift by max, positive input)"
+ TEST_VQRSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 8);
+ TEST_VQRSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 16);
+ TEST_VQRSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 32);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_max_shmax, CMT);
+
+
+ /* Fill input vector with min value, to check saturation on limits. */
+ VDUP(vector1, , uint, u, 8, 8, 0x80);
+ VDUP(vector1, , uint, u, 16, 4, 0x8000);
+ VDUP(vector1, , uint, u, 32, 2, 0x80000000LL);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x8000);
+ VDUP(vector2, q, int, s, 32, 4, 0x80000000);
+ VDUP(vector2, q, int, s, 64, 2, 0x8000000000000000LL);
+
+ /* shift by max */
+#undef CMT
+#define CMT " (check cumulative saturation: shift by max, negative input)"
+ TEST_VQRSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 8);
+ TEST_VQRSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 16);
+ TEST_VQRSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 32);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_min_shmax, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_min_shmax, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_min_shmax, CMT);
+
+
+ /* Fill input vector with positive values, to check normal case. */
+ VDUP(vector1, , uint, u, 8, 8, 0x12);
+ VDUP(vector1, , uint, u, 16, 4, 0x4321);
+ VDUP(vector1, , uint, u, 32, 2, 0xDEADBEEF);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x1234);
+ VDUP(vector2, q, int, s, 32, 4, 0x87654321);
+ VDUP(vector2, q, int, s, 64, 2, 0xDEADBEEF);
+
+ /* shift arbitrary amount. */
+#undef CMT
+#define CMT ""
+ TEST_VQRSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 6);
+ TEST_VQRSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 7);
+ TEST_VQRSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 8);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected, CMT);
+}
+
+int main (void)
+{
+ exec_vqrshrun_high_n ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrn_high_n.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrn_high_n.c
new file mode 100644
index 0000000..8d06f11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrn_high_n.c
@@ -0,0 +1,193 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { arm*-*-* } } */
+
+#include <arm_neon.h>
+#include "arm-neon-ref.h"
+#include "compute-ref-data.h"
+
+/* Expected results. */
+VECT_VAR_DECL(expected,int,8,16) [] = { 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf8, 0xf9, 0xf9,
+ 0xfa, 0xfa, 0xfb, 0xfb };
+VECT_VAR_DECL(expected,int,16,8) [] = { 0xfff0, 0xfff1, 0xfff2, 0xfff3,
+ 0xfff8, 0xfff8, 0xfff9, 0xfff9 };
+VECT_VAR_DECL(expected,int,32,4) [] = { 0xfffffff0, 0xfffffff1,
+ 0xfffffffc, 0xfffffffc };
+VECT_VAR_DECL(expected,uint,8,16) [] = { 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected,uint,16,8) [] = { 0xfff0, 0xfff1, 0xfff2, 0xfff3,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected,uint,32,4) [] = { 0xfffffff0, 0xfffffff1,
+ 0xffffffff, 0xffffffff };
+
+/* Expected results with max input value shifted by 3. */
+VECT_VAR_DECL(expected_max_sh3,int,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f };
+VECT_VAR_DECL(expected_max_sh3,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0x7fff, 0x7fff, 0x7fff, 0x7fff };
+VECT_VAR_DECL(expected_max_sh3,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0x7fffffff, 0x7fffffff };
+VECT_VAR_DECL(expected_max_sh3,uint,8,16) [] = { 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected_max_sh3,uint,16,8) [] = { 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected_max_sh3,uint,32,4) [] = { 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff };
+
+/* Expected results with max input value shifted by type size. */
+VECT_VAR_DECL(expected_max_shmax,int,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f };
+VECT_VAR_DECL(expected_max_shmax,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0x7fff, 0x7fff, 0x7fff, 0x7fff };
+VECT_VAR_DECL(expected_max_shmax,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0x7fffffff, 0x7fffffff };
+VECT_VAR_DECL(expected_max_shmax,uint,8,16) [] = { 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected_max_shmax,uint,16,8) [] = { 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected_max_shmax,uint,32,4) [] = { 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff };
+
+#define INSN vqshrn_high_n
+#define TEST_MSG "VQSHRN_HIGH_N"
+
+#define FNNAME1(NAME) void exec_ ## NAME (void)
+#define FNNAME(NAME) FNNAME1(NAME)
+
+FNNAME (INSN)
+{
+ /* Basic test: y=vqshrn_high_n(x1,x2,v), then store the result. */
+#define TEST_VQSHRN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V) \
+ VECT_VAR(vector_res, T1, W2, N2) = \
+ INSN##_##T2##W(VECT_VAR(vector1, T1, W2, N), \
+ VECT_VAR(vector2, T1, W, N), V); \
+ vst1q_##T2##W2(VECT_VAR(result, T1, W2, N2), \
+ VECT_VAR(vector_res, T1, W2, N2));
+
+ /* Two auxliary macros are necessary to expand INSN */
+#define TEST_VQSHRN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V) \
+ TEST_VQSHRN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V)
+
+#define TEST_VQSHRN_HIGH_N(T1, T2, W, W2, N, N2, V) \
+ TEST_VQSHRN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V)
+
+
+ DECL_VARIABLE(vector1, int, 8, 8);
+ DECL_VARIABLE(vector1, int, 16, 4);
+ DECL_VARIABLE(vector1, int, 32, 2);
+ DECL_VARIABLE(vector1, uint, 8, 8);
+ DECL_VARIABLE(vector1, uint, 16, 4);
+ DECL_VARIABLE(vector1, uint, 32, 2);
+
+ /* vector is twice as large as vector_res. */
+ DECL_VARIABLE(vector2, int, 16, 8);
+ DECL_VARIABLE(vector2, int, 32, 4);
+ DECL_VARIABLE(vector2, int, 64, 2);
+ DECL_VARIABLE(vector2, uint, 16, 8);
+ DECL_VARIABLE(vector2, uint, 32, 4);
+ DECL_VARIABLE(vector2, uint, 64, 2);
+
+ DECL_VARIABLE(vector_res, int, 8, 16);
+ DECL_VARIABLE(vector_res, int, 16, 8);
+ DECL_VARIABLE(vector_res, int, 32, 4);
+ DECL_VARIABLE(vector_res, uint, 8, 16);
+ DECL_VARIABLE(vector_res, uint, 16, 8);
+ DECL_VARIABLE(vector_res, uint, 32, 4);
+
+ clean_results ();
+
+ VLOAD(vector1, buffer, , int, s, 8, 8);
+ VLOAD(vector1, buffer, , int, s, 16, 4);
+ VLOAD(vector1, buffer, , int, s, 32, 2);
+ VLOAD(vector1, buffer, , uint, u, 8, 8);
+ VLOAD(vector1, buffer, , uint, u, 16, 4);
+ VLOAD(vector1, buffer, , uint, u, 32, 2);
+
+ VLOAD(vector2, buffer, q, int, s, 16, 8);
+ VLOAD(vector2, buffer, q, int, s, 32, 4);
+ VLOAD(vector2, buffer, q, int, s, 64, 2);
+ VLOAD(vector2, buffer, q, uint, u, 16, 8);
+ VLOAD(vector2, buffer, q, uint, u, 32, 4);
+ VLOAD(vector2, buffer, q, uint, u, 64, 2);
+
+ /* Choose shift amount arbitrarily. */
+#define CMT ""
+ TEST_VQSHRN_HIGH_N(int, s, 16, 8, 8, 16, 1);
+ TEST_VQSHRN_HIGH_N(int, s, 32, 16, 4, 8, 1);
+ TEST_VQSHRN_HIGH_N(int, s, 64, 32, 2, 4, 2);
+ TEST_VQSHRN_HIGH_N(uint, u, 16, 8, 8, 16, 2);
+ TEST_VQSHRN_HIGH_N(uint, u, 32, 16, 4, 8, 3);
+ TEST_VQSHRN_HIGH_N(uint, u, 64, 32, 2, 4, 3);
+
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected, CMT);
+ CHECK(TEST_MSG, int, 16, 8, PRIx16, expected, CMT);
+ CHECK(TEST_MSG, int, 32, 4, PRIx32, expected, CMT);
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected, CMT);
+
+ /* Use max possible value as input. */
+ VDUP(vector1, , int, s, 8, 8, 0x7F);
+ VDUP(vector1, , int, s, 16, 4, 0x7FFF);
+ VDUP(vector1, , int, s, 32, 2, 0x7FFFFFFFLL);
+ VDUP(vector1, , uint, u, 8, 8, 0xFF);
+ VDUP(vector1, , uint, u, 16, 4, 0xFFFF);
+ VDUP(vector1, , uint, u, 32, 2, 0xFFFFFFFFULL);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x7FFF);
+ VDUP(vector2, q, int, s, 32, 4, 0x7FFFFFFF);
+ VDUP(vector2, q, int, s, 64, 2, 0x7FFFFFFFFFFFFFFFLL);
+ VDUP(vector2, q, uint, u, 16, 8, 0xFFFF);
+ VDUP(vector2, q, uint, u, 32, 4, 0xFFFFFFFF);
+ VDUP(vector2, q, uint, u, 64, 2, 0xFFFFFFFFFFFFFFFFULL);
+
+#undef CMT
+#define CMT " (check saturation: shift by 3)"
+ TEST_VQSHRN_HIGH_N(int, s, 16, 8, 8, 16, 3);
+ TEST_VQSHRN_HIGH_N(int, s, 32, 16, 4, 8, 3);
+ TEST_VQSHRN_HIGH_N(int, s, 64, 32, 2, 4, 3);
+ TEST_VQSHRN_HIGH_N(uint, u, 16, 8, 8, 16, 3);
+ TEST_VQSHRN_HIGH_N(uint, u, 32, 16, 4, 8, 3);
+ TEST_VQSHRN_HIGH_N(uint, u, 64, 32, 2, 4, 3);
+
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_max_sh3, CMT);
+ CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_max_sh3, CMT);
+ CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_max_sh3, CMT);
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_max_sh3, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_max_sh3, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_max_sh3, CMT);
+
+
+#undef CMT
+#define CMT " (check saturation: shift by max)"
+ TEST_VQSHRN_HIGH_N(int, s, 16, 8, 8, 16, 8);
+ TEST_VQSHRN_HIGH_N(int, s, 32, 16, 4, 8, 16);
+ TEST_VQSHRN_HIGH_N(int, s, 64, 32, 2, 4, 32);
+ TEST_VQSHRN_HIGH_N(uint, u, 16, 8, 8, 16, 8);
+ TEST_VQSHRN_HIGH_N(uint, u, 32, 16, 4, 8, 16);
+ TEST_VQSHRN_HIGH_N(uint, u, 64, 32, 2, 4, 32);
+
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_max_shmax, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_max_shmax, CMT);
+}
+
+int main (void)
+{
+ exec_vqshrn_high_n ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrun_high_n.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrun_high_n.c
new file mode 100644
index 0000000..e8235fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqshrun_high_n.c
@@ -0,0 +1,143 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { arm*-*-* } } */
+
+#include <arm_neon.h>
+#include "arm-neon-ref.h"
+#include "compute-ref-data.h"
+
+/* Expected results with negative input. */
+VECT_VAR_DECL(expected_neg,uint,8,16) [] = { 0xfe, 0xfe, 0xfe, 0xfe,
+ 0xfe, 0xfe, 0xfe, 0xfe,
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0,0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_neg,uint,16,8) [] = { 0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0x0, 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected_neg,uint,32,4) [] = { 0xfffffffc, 0xfffffffc,
+ 0x0, 0x0 };
+
+/* Expected results with max input value shifted by 1. */
+VECT_VAR_DECL(expected_max_sh1,uint,8,16) [] = { 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff };
+VECT_VAR_DECL(expected_max_sh1,uint,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+ 0xffff, 0xffff, 0xffff, 0xffff };
+VECT_VAR_DECL(expected_max_sh1,uint,32,4) [] = { 0x7fffffff, 0x7fffffff,
+ 0xffffffff, 0xffffffff };
+
+/* Expected results. */
+VECT_VAR_DECL(expected,uint,8,16) [] = { 0x12, 0x12, 0x12, 0x12,
+ 0x12, 0x12, 0x12, 0x12,
+ 0x48, 0x48, 0x48, 0x48,
+ 0x48, 0x48, 0x48, 0x48 };
+VECT_VAR_DECL(expected,uint,16,8) [] = { 0x4321, 0x4321, 0x4321, 0x4321,
+ 0x0, 0x0, 0x0, 0x0 };
+VECT_VAR_DECL(expected,uint,32,4) [] = { 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbe, 0xdeadbe };
+
+#define INSN vqshrun_high_n
+#define TEST_MSG "VQSHRUN_HIGH_N"
+
+#define FNNAME1(NAME) void exec_ ## NAME (void)
+#define FNNAME(NAME) FNNAME1(NAME)
+
+FNNAME (INSN)
+{
+ /* Basic test: y=vqshrun_high_n(x,v), then store the result. */
+#define TEST_VQSHRUN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V) \
+ VECT_VAR(vector_res, uint, W2, N2) = \
+ INSN##_##T2##W(VECT_VAR(vector1,uint, W2, N), \
+ VECT_VAR(vector2, T1, W, N), V); \
+ vst1q_u##W2(VECT_VAR(result, uint, W2, N2), \
+ VECT_VAR(vector_res, uint, W2, N2)); \
+
+ /* Two auxliary macros are necessary to expand INSN */
+#define TEST_VQSHRUN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V) \
+ TEST_VQSHRUN_HIGH_N2(INSN, T1, T2, W, W2, N, N2, V)
+
+#define TEST_VQSHRUN_HIGH_N(T1, T2, W, W2, N, N2, V) \
+ TEST_VQSHRUN_HIGH_N1(INSN, T1, T2, W, W2, N, N2, V)
+
+
+ DECL_VARIABLE(vector1, uint, 8, 8);
+ DECL_VARIABLE(vector1, uint, 16, 4);
+ DECL_VARIABLE(vector1, uint, 32, 2);
+
+ /* vector is twice as large as vector_res. */
+ DECL_VARIABLE(vector2, int, 16, 8);
+ DECL_VARIABLE(vector2, int, 32, 4);
+ DECL_VARIABLE(vector2, int, 64, 2);
+
+ DECL_VARIABLE(vector_res, uint, 8, 16);
+ DECL_VARIABLE(vector_res, uint, 16, 8);
+ DECL_VARIABLE(vector_res, uint, 32, 4);
+
+ clean_results ();
+
+ /* Fill input vector with negative values, to check saturation on
+ limits. */
+ VDUP(vector1, , uint, u, 8, 8, -2);
+ VDUP(vector1, , uint, u, 16, 4, -3);
+ VDUP(vector1, , uint, u, 32, 2, -4);
+
+ VDUP(vector2, q, int, s, 16, 8, -2);
+ VDUP(vector2, q, int, s, 32, 4, -3);
+ VDUP(vector2, q, int, s, 64, 2, -4);
+
+ /* Choose shift amount arbitrarily. */
+#define CMT " (negative input)"
+ TEST_VQSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 3);
+ TEST_VQSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 4);
+ TEST_VQSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 2);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_neg, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_neg, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_neg, CMT);
+
+
+ /* Fill input vector with max value, to check saturation on
+ limits. */
+ VDUP(vector1, , uint, u, 8, 8, 0x7F);
+ VDUP(vector1, , uint, u, 16, 4, 0x7FFF);
+ VDUP(vector1, , uint, u, 32, 2, 0x7FFFFFFFLL);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x7FFF);
+ VDUP(vector2, q, int, s, 32, 4, 0x7FFFFFFF);
+ VDUP(vector2, q, int, s, 64, 2, 0x7FFFFFFFFFFFFFFFLL);
+
+#undef CMT
+#define CMT " (check cumulative saturation)"
+ TEST_VQSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 1);
+ TEST_VQSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 1);
+ TEST_VQSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 1);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_max_sh1, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected_max_sh1, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected_max_sh1, CMT);
+
+
+ /* Fill input vector with positive values, to check normal case. */
+ VDUP(vector1, , uint, u, 8, 8, 0x12);
+ VDUP(vector1, , uint, u, 16, 4, 0x4321);
+ VDUP(vector1, , uint, u, 32, 2, 0xDEADBEEF);
+
+ VDUP(vector2, q, int, s, 16, 8, 0x1234);
+ VDUP(vector2, q, int, s, 32, 4, 0x87654321);
+ VDUP(vector2, q, int, s, 64, 2, 0xDEADBEEF);
+
+#undef CMT
+#define CMT ""
+ TEST_VQSHRUN_HIGH_N(int, s, 16, 8, 8, 16, 6);
+ TEST_VQSHRUN_HIGH_N(int, s, 32, 16, 4, 8, 7);
+ TEST_VQSHRUN_HIGH_N(int, s, 64, 32, 2, 4, 8);
+
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected, CMT);
+ CHECK(TEST_MSG, uint, 16, 8, PRIx16, expected, CMT);
+ CHECK(TEST_MSG, uint, 32, 4, PRIx32, expected, CMT);
+}
+
+int main (void)
+{
+ exec_vqshrun_high_n ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2_lane_bf16_indices_1.c
new file mode 100644
index 0000000..7421dc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2_lane_bf16_indices_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+void
+f_vst2_lane_bf16 (bfloat16_t * p, bfloat16x4x2_t v)
+{
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ vst2_lane_bf16 (p, v, 4);
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ vst2_lane_bf16 (p, v, -1);
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..92aecfc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst2q_lane_bf16_indices_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+void
+f_vst2q_lane_bf16 (bfloat16_t * p, bfloat16x8x2_t v)
+{
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ vst2q_lane_bf16 (p, v, 8);
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ vst2q_lane_bf16 (p, v, -1);
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3_lane_bf16_indices_1.c
new file mode 100644
index 0000000..5d1f4f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3_lane_bf16_indices_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+void
+f_vst3_lane_bf16 (bfloat16_t * p, bfloat16x4x3_t v)
+{
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ vst3_lane_bf16 (p, v, 4);
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ vst3_lane_bf16 (p, v, -1);
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..65592db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst3q_lane_bf16_indices_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+void
+f_vst3q_lane_bf16 (bfloat16_t * p, bfloat16x8x3_t v)
+{
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ vst3q_lane_bf16 (p, v, 8);
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ vst3q_lane_bf16 (p, v, -1);
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4_lane_bf16_indices_1.c
new file mode 100644
index 0000000..8abd402
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4_lane_bf16_indices_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+void
+f_vst4_lane_bf16 (bfloat16_t * p, bfloat16x4x4_t v)
+{
+ /* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
+ vst4_lane_bf16 (p, v, 4);
+ /* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+ vst4_lane_bf16 (p, v, -1);
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..7d4d4ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vst4q_lane_bf16_indices_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+
+#include <arm_neon.h>
+
+void
+f_vst4q_lane_bf16 (bfloat16_t * p, bfloat16x8x4_t v)
+{
+ /* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
+ vst4q_lane_bf16 (p, v, 8);
+ /* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+ vst4q_lane_bf16 (p, v, -1);
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c
new file mode 100644
index 0000000..c43f019
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c
@@ -0,0 +1,88 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdint.h>
+
+/* One byte variable set should be scalar
+**set1byte:
+** strb w1, \[x0\]
+** ret
+*/
+void __attribute__((__noinline__))
+set1byte (int64_t *src, char c)
+{
+ __builtin_memset (src, c, 1);
+}
+
+/* Special cases for setting 0. */
+/* 1-byte should be STRB with wzr
+**set0byte:
+** strb wzr, \[x0\]
+** ret
+*/
+void __attribute__((__noinline__))
+set0byte (int64_t *src)
+{
+ __builtin_memset (src, 0, 1);
+}
+
+/* 35bytes would become 4 scalar instructions. So favour NEON.
+**set0neon:
+** movi v0.4s, 0
+** stp q0, q0, \[x0\]
+** str wzr, \[x0, 31\]
+** ret
+*/
+void __attribute__((__noinline__))
+set0neon (int64_t *src)
+{
+ __builtin_memset (src, 0, 35);
+}
+
+/* 36bytes should be scalar however.
+**set0scalar:
+** stp xzr, xzr, \[x0\]
+** stp xzr, xzr, \[x0, 16\]
+** str wzr, \[x0, 32\]
+** ret
+*/
+void __attribute__((__noinline__))
+set0scalar (int64_t *src)
+{
+ __builtin_memset (src, 0, 36);
+}
+
+
+/* 256-bytes expanded
+**set256byte:
+** dup v0.16b, w1
+** stp q0, q0, \[x0\]
+** stp q0, q0, \[x0, 32\]
+** stp q0, q0, \[x0, 64\]
+** stp q0, q0, \[x0, 96\]
+** stp q0, q0, \[x0, 128\]
+** stp q0, q0, \[x0, 160\]
+** stp q0, q0, \[x0, 192\]
+** stp q0, q0, \[x0, 224\]
+** ret
+*/
+void __attribute__((__noinline__))
+set256byte (int64_t *src, char c)
+{
+ __builtin_memset (src, c, 256);
+}
+
+/* More than 256 bytes goes to memset
+**set257byte:
+** mov x2, 257
+** mov w1, 99
+** b memset
+*/
+void __attribute__((__noinline__))
+set257byte (int64_t *src)
+{
+ __builtin_memset (src, 'c', 257);
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memset-q-reg.c b/gcc/testsuite/gcc.target/aarch64/memset-q-reg.c
new file mode 100644
index 0000000..156146b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memset-q-reg.c
@@ -0,0 +1,81 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdint.h>
+
+/*
+**set128bits:
+** dup v0.16b, w1
+** str q0, \[x0\]
+** ret
+*/
+void __attribute__((__noinline__))
+set128bits (int64_t *src, char c)
+{
+ __builtin_memset (src, c, 2*sizeof(int64_t));
+}
+
+/*
+**set128bitszero:
+** stp xzr, xzr, \[x0\]
+** ret
+*/
+void __attribute__((__noinline__))
+set128bitszero (int64_t *src)
+{
+ __builtin_memset (src, 0, 2*sizeof(int64_t));
+}
+
+/*
+** set128bitsplus:
+** dup v0.16b, w1
+** str q0, \[x0\]
+** str q0, \[x0, 12\]
+** ret
+*/
+void __attribute__((__noinline__))
+set128bitsplus (int64_t *src, char c)
+{
+ __builtin_memset (src, c, 7*sizeof(int32_t));
+}
+
+/*
+** set256bits:
+** movi v0.16b, 0x63
+** stp q0, q0, \[x0\]
+** ret
+*/
+void __attribute__((__noinline__))
+set256bits (int64_t *src)
+{
+ __builtin_memset (src, 'c', 4*sizeof(int64_t));
+}
+
+/*
+**set256bitszero:
+** stp xzr, xzr, \[x0\]
+** stp xzr, xzr, \[x0, 16\]
+** ret
+*/
+void __attribute__((__noinline__))
+set256bitszero (int64_t *src)
+{
+ __builtin_memset (src, 0, 4*sizeof(int64_t));
+}
+
+/*
+** set256bitsplus:
+** movi v0.16b, 0x63
+** stp q0, q0, \[x0\]
+** str q0, \[x0, 32\]
+** str d0, \[x0, 48\]
+** ret
+*/
+void __attribute__((__noinline__))
+set256bitsplus (int64_t *src)
+{
+ __builtin_memset (src, 'c', 7*sizeof(int64_t));
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/narrow_high-intrinsics.c b/gcc/testsuite/gcc.target/aarch64/narrow_high-intrinsics.c
index 8b8a630..07d7803 100644
--- a/gcc/testsuite/gcc.target/aarch64/narrow_high-intrinsics.c
+++ b/gcc/testsuite/gcc.target/aarch64/narrow_high-intrinsics.c
@@ -113,12 +113,12 @@ ONE (vmovn_high, uint32x4_t, uint32x2_t, uint64x2_t, u64)
/* { dg-final { scan-assembler-times "raddhn2\\tv" 6} } */
/* { dg-final { scan-assembler-times "\\trshrn2 v" 6} } */
/* { dg-final { scan-assembler-times "\\tshrn2 v" 6} } */
-/* { dg-final { scan-assembler-times "sqshrun2 v" 3} } */
-/* { dg-final { scan-assembler-times "sqrshrun2 v" 3} } */
-/* { dg-final { scan-assembler-times "sqshrn2 v" 3} } */
-/* { dg-final { scan-assembler-times "uqshrn2 v" 3} } */
-/* { dg-final { scan-assembler-times "sqrshrn2 v" 3} } */
-/* { dg-final { scan-assembler-times "uqrshrn2 v" 3} } */
+/* { dg-final { scan-assembler-times "sqshrun2\\tv" 3} } */
+/* { dg-final { scan-assembler-times "sqrshrun2\\tv" 3} } */
+/* { dg-final { scan-assembler-times "sqshrn2\\tv" 3} } */
+/* { dg-final { scan-assembler-times "uqshrn2\\tv" 3} } */
+/* { dg-final { scan-assembler-times "sqrshrn2\\tv" 3} } */
+/* { dg-final { scan-assembler-times "uqrshrn2\\tv" 3} } */
/* { dg-final { scan-assembler-times "uqxtn2 v" 3} } */
/* { dg-final { scan-assembler-times "sqxtn2 v" 3} } */
/* { dg-final { scan-assembler-times "sqxtun2 v" 3} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr97535.c b/gcc/testsuite/gcc.target/aarch64/pr97535.c
new file mode 100644
index 0000000..7d4db48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr97535.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ilp32 } } } */
+
+#include <string.h>
+
+#define SIZE 2181038080
+
+extern char raw_buffer[SIZE];
+
+void setRaw(const void *raw)
+{
+ memcpy(raw_buffer, raw, SIZE);
+}
+
+/* At any optimization level this should be a function call
+ and not inlined. */
+/* { dg-final { scan-assembler "bl\tmemcpy" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr97638.c b/gcc/testsuite/gcc.target/aarch64/pr97638.c
new file mode 100644
index 0000000..e5869e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr97638.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=bti" } */
+
+char *foo (const char *s, const int c)
+{
+ const char *p = 0;
+ for (;;)
+ {
+ if (*s == c)
+ p = s;
+ if (p != 0 || *s++ == 0)
+ break;
+ }
+ return (char *)p;
+}
+
+/* { dg-final { scan-assembler "hint\t34" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f16.c
index 2aa8736..0960532 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_f16_x_tied1, svfloat16_t,
/*
** abs_f16_x_untied:
+** movprfx z0, z1
** fabs z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f32.c
index 30286af..797a418 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_f32_x_tied1, svfloat32_t,
/*
** abs_f32_x_untied:
+** movprfx z0, z1
** fabs z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f64.c
index 28ef9fb..4290ac3 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_f64_x_tied1, svfloat64_t,
/*
** abs_f64_x_untied:
+** movprfx z0, z1
** fabs z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s16.c
index 3b16a9c..fcd5c34 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_s16_x_tied1, svint16_t,
/*
** abs_s16_x_untied:
+** movprfx z0, z1
** abs z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s32.c
index 14bcbd5..58d183e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_s32_x_tied1, svint32_t,
/*
** abs_s32_x_untied:
+** movprfx z0, z1
** abs z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s64.c
index c7b60ff..2842048 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_s64_x_tied1, svint64_t,
/*
** abs_s64_x_untied:
+** movprfx z0, z1
** abs z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s8.c
index 0bc64c0..ec0d89d 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/abs_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (abs_s8_x_tied1, svint8_t,
/*
** abs_s8_x_untied:
+** movprfx z0, z1
** abs z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s16.c
index 7af3123..5f82612 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s16.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cls_s16_z, svuint16_t, svint16_t,
/*
** cls_s16_x:
+** movprfx z0, z4
** cls z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s32.c
index 813876f..0db651f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s32.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cls_s32_z, svuint32_t, svint32_t,
/*
** cls_s32_x:
+** movprfx z0, z4
** cls z0\.s, p0/m, z4\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s64.c
index 660a205..e809e2f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s64.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cls_s64_z, svuint64_t, svint64_t,
/*
** cls_s64_x:
+** movprfx z0, z4
** cls z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s8.c
index 56f5c26..f296c9f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cls_s8.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cls_s8_z, svuint8_t, svint8_t,
/*
** cls_s8_x:
+** movprfx z0, z4
** cls z0\.b, p0/m, z4\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s16.c
index 58f8900..dc2c4e9 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s16.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (clz_s16_z, svuint16_t, svint16_t,
/*
** clz_s16_x:
+** movprfx z0, z4
** clz z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s32.c
index a919807..17f54bc 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s32.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (clz_s32_z, svuint32_t, svint32_t,
/*
** clz_s32_x:
+** movprfx z0, z4
** clz z0\.s, p0/m, z4\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s64.c
index 02c0c99..a42b730 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s64.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (clz_s64_z, svuint64_t, svint64_t,
/*
** clz_s64_x:
+** movprfx z0, z4
** clz z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s8.c
index 642d298..66c2359 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_s8.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (clz_s8_z, svuint8_t, svint8_t,
/*
** clz_s8_x:
+** movprfx z0, z4
** clz z0\.b, p0/m, z4\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u16.c
index f087230..ab31f56 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (clz_u16_x_tied1, svuint16_t,
/*
** clz_u16_x_untied:
+** movprfx z0, z1
** clz z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u32.c
index e004241..2a74404 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (clz_u32_x_tied1, svuint32_t,
/*
** clz_u32_x_untied:
+** movprfx z0, z1
** clz z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u64.c
index e879e1b..8ff73c4 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (clz_u64_x_tied1, svuint64_t,
/*
** clz_u64_x_untied:
+** movprfx z0, z1
** clz z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u8.c
index ce6cb8f..89d8c540 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/clz_u8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (clz_u8_x_tied1, svuint8_t,
/*
** clz_u8_x_untied:
+** movprfx z0, z1
** clz z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s16.c
index 19d46be..8f047fb 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_s16_x_tied1, svint16_t,
/*
** cnot_s16_x_untied:
+** movprfx z0, z1
** cnot z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s32.c
index 041b59a..f5b3395 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_s32_x_tied1, svint32_t,
/*
** cnot_s32_x_untied:
+** movprfx z0, z1
** cnot z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s64.c
index c7135cb..64121e3f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_s64_x_tied1, svint64_t,
/*
** cnot_s64_x_untied:
+** movprfx z0, z1
** cnot z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s8.c
index 0560f97..e5dab42 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_s8_x_tied1, svint8_t,
/*
** cnot_s8_x_untied:
+** movprfx z0, z1
** cnot z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u16.c
index 7ea9ff71..74c72c9 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_u16_x_tied1, svuint16_t,
/*
** cnot_u16_x_untied:
+** movprfx z0, z1
** cnot z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u32.c
index 972c775..b0f7531 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_u32_x_tied1, svuint32_t,
/*
** cnot_u32_x_untied:
+** movprfx z0, z1
** cnot z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u64.c
index f25e001..9aa698d 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_u64_x_tied1, svuint64_t,
/*
** cnot_u64_x_untied:
+** movprfx z0, z1
** cnot z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u8.c
index e135a72..67c46a2 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnot_u8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnot_u8_x_tied1, svuint8_t,
/*
** cnot_u8_x_untied:
+** movprfx z0, z1
** cnot z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_bf16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_bf16.c
index d92fbc1..bebf361 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_bf16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_bf16.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_bf16_z, svuint16_t, svbfloat16_t,
/*
** cnt_bf16_x:
+** movprfx z0, z4
** cnt z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f16.c
index b8061bb..20c95d6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f16.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_f16_z, svuint16_t, svfloat16_t,
/*
** cnt_f16_x:
+** movprfx z0, z4
** cnt z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f32.c
index b9292c9..8afeb49 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f32.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_f32_z, svuint32_t, svfloat32_t,
/*
** cnt_f32_x:
+** movprfx z0, z4
** cnt z0\.s, p0/m, z4\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f64.c
index 4976ee4..b7683a9 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_f64.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_f64_z, svuint64_t, svfloat64_t,
/*
** cnt_f64_x:
+** movprfx z0, z4
** cnt z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s16.c
index a8ff8f3..824c42a 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s16.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_s16_z, svuint16_t, svint16_t,
/*
** cnt_s16_x:
+** movprfx z0, z4
** cnt z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s32.c
index 3d16041..d6653d5 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s32.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_s32_z, svuint32_t, svint32_t,
/*
** cnt_s32_x:
+** movprfx z0, z4
** cnt z0\.s, p0/m, z4\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s64.c
index 8c8871b..c28db82 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s64.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_s64_z, svuint64_t, svint64_t,
/*
** cnt_s64_x:
+** movprfx z0, z4
** cnt z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s8.c
index 8d85c8e..e741b4c 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_s8.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (cnt_s8_z, svuint8_t, svint8_t,
/*
** cnt_s8_x:
+** movprfx z0, z4
** cnt z0\.b, p0/m, z4\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u16.c
index f173d31..49236cd 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnt_u16_x_tied1, svuint16_t,
/*
** cnt_u16_x_untied:
+** movprfx z0, z1
** cnt z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u32.c
index 11969a6..d302e32 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnt_u32_x_tied1, svuint32_t,
/*
** cnt_u32_x_untied:
+** movprfx z0, z1
** cnt z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u64.c
index 4eb69ea..b6e26ba 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnt_u64_x_tied1, svuint64_t,
/*
** cnt_u64_x_untied:
+** movprfx z0, z1
** cnt z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u8.c
index 30e7983..464dc4e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnt_u8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (cnt_u8_x_tied1, svuint8_t,
/*
** cnt_u8_x_untied:
+** movprfx z0, z1
** cnt z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_bf16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_bf16.c
index 52baa1f..d4f9150 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_bf16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_bf16.c
@@ -66,6 +66,7 @@ TEST_DUAL_Z_REV (cvt_bf16_f32_x_tied1, svbfloat16_t, svfloat32_t,
/*
** cvt_bf16_f32_x_untied:
+** movprfx z0, z4
** bfcvt z0\.h, p0/m, z4\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f16.c
index 5dcd480..dbb042d 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f16.c
@@ -421,6 +421,7 @@ TEST_DUAL_Z_REV (cvt_f16_f32_x_tied1, svfloat16_t, svfloat32_t,
/*
** cvt_f16_f32_x_untied:
+** movprfx z0, z4
** fcvt z0\.h, p0/m, z4\.s
** ret
*/
@@ -439,6 +440,7 @@ TEST_DUAL_Z_REV (cvt_f16_f64_x_tied1, svfloat16_t, svfloat64_t,
/*
** cvt_f16_f64_x_untied:
+** movprfx z0, z4
** fcvt z0\.h, p0/m, z4\.d
** ret
*/
@@ -457,6 +459,7 @@ TEST_DUAL_Z_REV (cvt_f16_s16_x_tied1, svfloat16_t, svint16_t,
/*
** cvt_f16_s16_x_untied:
+** movprfx z0, z4
** scvtf z0\.h, p0/m, z4\.h
** ret
*/
@@ -475,6 +478,7 @@ TEST_DUAL_Z_REV (cvt_f16_s32_x_tied1, svfloat16_t, svint32_t,
/*
** cvt_f16_s32_x_untied:
+** movprfx z0, z4
** scvtf z0\.h, p0/m, z4\.s
** ret
*/
@@ -493,6 +497,7 @@ TEST_DUAL_Z_REV (cvt_f16_s64_x_tied1, svfloat16_t, svint64_t,
/*
** cvt_f16_s64_x_untied:
+** movprfx z0, z4
** scvtf z0\.h, p0/m, z4\.d
** ret
*/
@@ -511,6 +516,7 @@ TEST_DUAL_Z_REV (cvt_f16_u16_x_tied1, svfloat16_t, svuint16_t,
/*
** cvt_f16_u16_x_untied:
+** movprfx z0, z4
** ucvtf z0\.h, p0/m, z4\.h
** ret
*/
@@ -529,6 +535,7 @@ TEST_DUAL_Z_REV (cvt_f16_u32_x_tied1, svfloat16_t, svuint32_t,
/*
** cvt_f16_u32_x_untied:
+** movprfx z0, z4
** ucvtf z0\.h, p0/m, z4\.s
** ret
*/
@@ -547,6 +554,7 @@ TEST_DUAL_Z_REV (cvt_f16_u64_x_tied1, svfloat16_t, svuint64_t,
/*
** cvt_f16_u64_x_untied:
+** movprfx z0, z4
** ucvtf z0\.h, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f32.c
index c164699..f7bfe57 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f32.c
@@ -319,6 +319,7 @@ TEST_DUAL_Z_REV (cvt_f32_f16_x_tied1, svfloat32_t, svfloat16_t,
/*
** cvt_f32_f16_x_untied:
+** movprfx z0, z4
** fcvt z0\.s, p0/m, z4\.h
** ret
*/
@@ -337,6 +338,7 @@ TEST_DUAL_Z_REV (cvt_f32_f64_x_tied1, svfloat32_t, svfloat64_t,
/*
** cvt_f32_f64_x_untied:
+** movprfx z0, z4
** fcvt z0\.s, p0/m, z4\.d
** ret
*/
@@ -355,6 +357,7 @@ TEST_DUAL_Z_REV (cvt_f32_s32_x_tied1, svfloat32_t, svint32_t,
/*
** cvt_f32_s32_x_untied:
+** movprfx z0, z4
** scvtf z0\.s, p0/m, z4\.s
** ret
*/
@@ -373,6 +376,7 @@ TEST_DUAL_Z_REV (cvt_f32_s64_x_tied1, svfloat32_t, svint64_t,
/*
** cvt_f32_s64_x_untied:
+** movprfx z0, z4
** scvtf z0\.s, p0/m, z4\.d
** ret
*/
@@ -391,6 +395,7 @@ TEST_DUAL_Z_REV (cvt_f32_u32_x_tied1, svfloat32_t, svuint32_t,
/*
** cvt_f32_u32_x_untied:
+** movprfx z0, z4
** ucvtf z0\.s, p0/m, z4\.s
** ret
*/
@@ -409,6 +414,7 @@ TEST_DUAL_Z_REV (cvt_f32_u64_x_tied1, svfloat32_t, svuint64_t,
/*
** cvt_f32_u64_x_untied:
+** movprfx z0, z4
** ucvtf z0\.s, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f64.c
index 1d08e6e..bfa36ba 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_f64.c
@@ -319,6 +319,7 @@ TEST_DUAL_Z_REV (cvt_f64_f16_x_tied1, svfloat64_t, svfloat16_t,
/*
** cvt_f64_f16_x_untied:
+** movprfx z0, z4
** fcvt z0\.d, p0/m, z4\.h
** ret
*/
@@ -337,6 +338,7 @@ TEST_DUAL_Z_REV (cvt_f64_f32_x_tied1, svfloat64_t, svfloat32_t,
/*
** cvt_f64_f32_x_untied:
+** movprfx z0, z4
** fcvt z0\.d, p0/m, z4\.s
** ret
*/
@@ -355,6 +357,7 @@ TEST_DUAL_Z_REV (cvt_f64_s32_x_tied1, svfloat64_t, svint32_t,
/*
** cvt_f64_s32_x_untied:
+** movprfx z0, z4
** scvtf z0\.d, p0/m, z4\.s
** ret
*/
@@ -373,6 +376,7 @@ TEST_DUAL_Z_REV (cvt_f64_s64_x_tied1, svfloat64_t, svint64_t,
/*
** cvt_f64_s64_x_untied:
+** movprfx z0, z4
** scvtf z0\.d, p0/m, z4\.d
** ret
*/
@@ -391,6 +395,7 @@ TEST_DUAL_Z_REV (cvt_f64_u32_x_tied1, svfloat64_t, svuint32_t,
/*
** cvt_f64_u32_x_untied:
+** movprfx z0, z4
** ucvtf z0\.d, p0/m, z4\.s
** ret
*/
@@ -409,6 +414,7 @@ TEST_DUAL_Z_REV (cvt_f64_u64_x_tied1, svfloat64_t, svuint64_t,
/*
** cvt_f64_u64_x_untied:
+** movprfx z0, z4
** ucvtf z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s16.c
index 81761ab..6b6883b 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s16.c
@@ -64,6 +64,7 @@ TEST_DUAL_Z_REV (cvt_s16_f16_x_tied1, svint16_t, svfloat16_t,
/*
** cvt_s16_f16_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s32.c
index d30da5c..bf87356 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s32.c
@@ -166,6 +166,7 @@ TEST_DUAL_Z_REV (cvt_s32_f16_x_tied1, svint32_t, svfloat16_t,
/*
** cvt_s32_f16_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.s, p0/m, z4\.h
** ret
*/
@@ -184,6 +185,7 @@ TEST_DUAL_Z_REV (cvt_s32_f32_x_tied1, svint32_t, svfloat32_t,
/*
** cvt_s32_f32_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.s, p0/m, z4\.s
** ret
*/
@@ -202,6 +204,7 @@ TEST_DUAL_Z_REV (cvt_s32_f64_x_tied1, svint32_t, svfloat64_t,
/*
** cvt_s32_f64_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.s, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s64.c
index 68cd807..9be3e05 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_s64.c
@@ -166,6 +166,7 @@ TEST_DUAL_Z_REV (cvt_s64_f16_x_tied1, svint64_t, svfloat16_t,
/*
** cvt_s64_f16_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.d, p0/m, z4\.h
** ret
*/
@@ -184,6 +185,7 @@ TEST_DUAL_Z_REV (cvt_s64_f32_x_tied1, svint64_t, svfloat32_t,
/*
** cvt_s64_f32_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.d, p0/m, z4\.s
** ret
*/
@@ -202,6 +204,7 @@ TEST_DUAL_Z_REV (cvt_s64_f64_x_tied1, svint64_t, svfloat64_t,
/*
** cvt_s64_f64_x_untied:
+** movprfx z0, z4
** fcvtzs z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u16.c
index 4db0dff..33a608b 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u16.c
@@ -64,6 +64,7 @@ TEST_DUAL_Z_REV (cvt_u16_f16_x_tied1, svuint16_t, svfloat16_t,
/*
** cvt_u16_f16_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u32.c
index 52ef49f..4791d27 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u32.c
@@ -166,6 +166,7 @@ TEST_DUAL_Z_REV (cvt_u32_f16_x_tied1, svuint32_t, svfloat16_t,
/*
** cvt_u32_f16_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.s, p0/m, z4\.h
** ret
*/
@@ -184,6 +185,7 @@ TEST_DUAL_Z_REV (cvt_u32_f32_x_tied1, svuint32_t, svfloat32_t,
/*
** cvt_u32_f32_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.s, p0/m, z4\.s
** ret
*/
@@ -202,6 +204,7 @@ TEST_DUAL_Z_REV (cvt_u32_f64_x_tied1, svuint32_t, svfloat64_t,
/*
** cvt_u32_f64_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.s, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u64.c
index 0c43758..e6c10c1 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cvt_u64.c
@@ -166,6 +166,7 @@ TEST_DUAL_Z_REV (cvt_u64_f16_x_tied1, svuint64_t, svfloat16_t,
/*
** cvt_u64_f16_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.d, p0/m, z4\.h
** ret
*/
@@ -184,6 +185,7 @@ TEST_DUAL_Z_REV (cvt_u64_f32_x_tied1, svuint64_t, svfloat32_t,
/*
** cvt_u64_f32_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.d, p0/m, z4\.s
** ret
*/
@@ -202,6 +204,7 @@ TEST_DUAL_Z_REV (cvt_u64_f64_x_tied1, svuint64_t, svfloat64_t,
/*
** cvt_u64_f64_x_untied:
+** movprfx z0, z4
** fcvtzu z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s16.c
index 32e836f..76c7143 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (extb_s16_x_tied1, svint16_t,
/*
** extb_s16_x_untied:
+** movprfx z0, z1
** sxtb z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s32.c
index e2f13f4..084c1c1 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (extb_s32_x_tied1, svint32_t,
/*
** extb_s32_x_untied:
+** movprfx z0, z1
** sxtb z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s64.c
index 83363ef..8f3ee8d 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extb_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (extb_s64_x_tied1, svint64_t,
/*
** extb_s64_x_untied:
+** movprfx z0, z1
** sxtb z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s32.c
index 3bb0bf31..d15cf7a 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (exth_s32_x_tied1, svint32_t,
/*
** exth_s32_x_untied:
+** movprfx z0, z1
** sxth z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s64.c
index 0718b67..d8adf52 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/exth_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (exth_s64_x_tied1, svint64_t,
/*
** exth_s64_x_untied:
+** movprfx z0, z1
** sxth z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extw_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extw_s64.c
index a6edadf..978a622 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extw_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/extw_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (extw_s64_x_tied1, svint64_t,
/*
** extw_s64_x_untied:
+** movprfx z0, z1
** sxtw z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f16.c
index c31eba9..c43c6eb 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_f16_x_tied1, svfloat16_t,
/*
** neg_f16_x_untied:
+** movprfx z0, z1
** fneg z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f32.c
index a57d264..3e9fd5b 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_f32_x_tied1, svfloat32_t,
/*
** neg_f32_x_untied:
+** movprfx z0, z1
** fneg z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f64.c
index 90cadd4..880f5e8 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_f64_x_tied1, svfloat64_t,
/*
** neg_f64_x_untied:
+** movprfx z0, z1
** fneg z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s16.c
index 80b2ee0..6a43bb2 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_s16_x_tied1, svint16_t,
/*
** neg_s16_x_untied:
+** movprfx z0, z1
** neg z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s32.c
index b880503..ea92412 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_s32_x_tied1, svint32_t,
/*
** neg_s32_x_untied:
+** movprfx z0, z1
** neg z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s64.c
index 82abe67..911d1f3 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_s64_x_tied1, svint64_t,
/*
** neg_s64_x_untied:
+** movprfx z0, z1
** neg z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s8.c
index b7c9949..ace74b7 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/neg_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (neg_s8_x_tied1, svint8_t,
/*
** neg_s8_x_untied:
+** movprfx z0, z1
** neg z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s16.c
index bacd6b1..9cafba9 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_s16_x_tied1, svint16_t,
/*
** not_s16_x_untied:
+** movprfx z0, z1
** not z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s32.c
index 8b15d6e..2185b78 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_s32_x_tied1, svint32_t,
/*
** not_s32_x_untied:
+** movprfx z0, z1
** not z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s64.c
index 8e7f7b9..09b3c25 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_s64_x_tied1, svint64_t,
/*
** not_s64_x_untied:
+** movprfx z0, z1
** not z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s8.c
index e807f08..029909e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_s8_x_tied1, svint8_t,
/*
** not_s8_x_untied:
+** movprfx z0, z1
** not z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u16.c
index c812005..fc33c99 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_u16_x_tied1, svuint16_t,
/*
** not_u16_x_untied:
+** movprfx z0, z1
** not z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u32.c
index 7b7e9ca..3f5e822 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_u32_x_tied1, svuint32_t,
/*
** not_u32_x_untied:
+** movprfx z0, z1
** not z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u64.c
index 27b92ad..01dde36e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_u64_x_tied1, svuint64_t,
/*
** not_u64_x_untied:
+** movprfx z0, z1
** not z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u8.c
index bd2f36c..e8553e3 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/not_u8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (not_u8_x_tied1, svuint8_t,
/*
** not_u8_x_untied:
+** movprfx z0, z1
** not z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s16.c
index 4f794f6..5889c92 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_s16_x_tied1, svint16_t,
/*
** rbit_s16_x_untied:
+** movprfx z0, z1
** rbit z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s32.c
index 8b5e1a4..1414e3e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_s32_x_tied1, svint32_t,
/*
** rbit_s32_x_untied:
+** movprfx z0, z1
** rbit z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s64.c
index cec27a4..3b76f54 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_s64_x_tied1, svint64_t,
/*
** rbit_s64_x_untied:
+** movprfx z0, z1
** rbit z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s8.c
index 9c15211..1fc80e3 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_s8_x_tied1, svint8_t,
/*
** rbit_s8_x_untied:
+** movprfx z0, z1
** rbit z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u16.c
index 001ef2b..6479337 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_u16_x_tied1, svuint16_t,
/*
** rbit_u16_x_untied:
+** movprfx z0, z1
** rbit z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u32.c
index 4d91e95..3e95964 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_u32_x_tied1, svuint32_t,
/*
** rbit_u32_x_untied:
+** movprfx z0, z1
** rbit z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u64.c
index 77f88d1..5163b82 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_u64_x_tied1, svuint64_t,
/*
** rbit_u64_x_untied:
+** movprfx z0, z1
** rbit z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u8.c
index fa347e4..2372398 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rbit_u8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rbit_u8_x_tied1, svuint8_t,
/*
** rbit_u8_x_untied:
+** movprfx z0, z1
** rbit z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f16.c
index 2dd7ada..da63f26 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (recpx_f16_x_tied1, svfloat16_t,
/*
** recpx_f16_x_untied:
+** movprfx z0, z1
** frecpx z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f32.c
index 6364fb8..ea8cb78 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (recpx_f32_x_tied1, svfloat32_t,
/*
** recpx_f32_x_untied:
+** movprfx z0, z1
** frecpx z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f64.c
index ca52323..1eaca67 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/recpx_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (recpx_f64_x_tied1, svfloat64_t,
/*
** recpx_f64_x_untied:
+** movprfx z0, z1
** frecpx z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s16.c
index ecfabe6..a99260f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revb_s16_x_tied1, svint16_t,
/*
** revb_s16_x_untied:
+** movprfx z0, z1
** revb z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s32.c
index a46a819..adbf128 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revb_s32_x_tied1, svint32_t,
/*
** revb_s32_x_untied:
+** movprfx z0, z1
** revb z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s64.c
index 2154723..d21db75 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revb_s64_x_tied1, svint64_t,
/*
** revb_s64_x_untied:
+** movprfx z0, z1
** revb z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u16.c
index d58bd3d..d48704f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revb_u16_x_tied1, svuint16_t,
/*
** revb_u16_x_untied:
+** movprfx z0, z1
** revb z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u32.c
index 33df990..cf9293b 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revb_u32_x_tied1, svuint32_t,
/*
** revb_u32_x_untied:
+** movprfx z0, z1
** revb z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u64.c
index 50ad618..54db72d 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revb_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revb_u64_x_tied1, svuint64_t,
/*
** revb_u64_x_untied:
+** movprfx z0, z1
** revb z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s32.c
index 07d512d..fb63c17 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revh_s32_x_tied1, svint32_t,
/*
** revh_s32_x_untied:
+** movprfx z0, z1
** revh z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s64.c
index b144634..967600a 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revh_s64_x_tied1, svint64_t,
/*
** revh_s64_x_untied:
+** movprfx z0, z1
** revh z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u32.c
index 9ea5188..265f865 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revh_u32_x_tied1, svuint32_t,
/*
** revh_u32_x_untied:
+** movprfx z0, z1
** revh z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u64.c
index 7b2da27..733b229 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revh_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revh_u64_x_tied1, svuint64_t,
/*
** revh_u64_x_untied:
+** movprfx z0, z1
** revh z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_s64.c
index 26ca0f0..0894131 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revw_s64_x_tied1, svint64_t,
/*
** revw_s64_x_untied:
+** movprfx z0, z1
** revw z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_u64.c
index c70cdb4..ebde929 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_u64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/revw_u64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (revw_u64_x_tied1, svuint64_t,
/*
** revw_u64_x_untied:
+** movprfx z0, z1
** revw z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f16.c
index 99a6042..3e1a788 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rinta_f16_x_tied1, svfloat16_t,
/*
** rinta_f16_x_untied:
+** movprfx z0, z1
** frinta z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f32.c
index b4e3714..ae6fe65 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rinta_f32_x_tied1, svfloat32_t,
/*
** rinta_f32_x_untied:
+** movprfx z0, z1
** frinta z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f64.c
index 24d6b7d..2f7be6c 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinta_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rinta_f64_x_tied1, svfloat64_t,
/*
** rinta_f64_x_untied:
+** movprfx z0, z1
** frinta z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f16.c
index 1f0ac85..ec3b908 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rinti_f16_x_tied1, svfloat16_t,
/*
** rinti_f16_x_untied:
+** movprfx z0, z1
** frinti z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f32.c
index cf54fde..061f5c8 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rinti_f32_x_tied1, svfloat32_t,
/*
** rinti_f32_x_untied:
+** movprfx z0, z1
** frinti z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f64.c
index 08b861c..eca3be0 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rinti_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rinti_f64_x_tied1, svfloat64_t,
/*
** rinti_f64_x_untied:
+** movprfx z0, z1
** frinti z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f16.c
index 194d01c..35cb976 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintm_f16_x_tied1, svfloat16_t,
/*
** rintm_f16_x_untied:
+** movprfx z0, z1
** frintm z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f32.c
index 6c3297a..d65baf5 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintm_f32_x_tied1, svfloat32_t,
/*
** rintm_f32_x_untied:
+** movprfx z0, z1
** frintm z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f64.c
index ecbb244..d3824ec 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintm_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintm_f64_x_tied1, svfloat64_t,
/*
** rintm_f64_x_untied:
+** movprfx z0, z1
** frintm z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f16.c
index 273307e..cc2bf0e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintn_f16_x_tied1, svfloat16_t,
/*
** rintn_f16_x_untied:
+** movprfx z0, z1
** frintn z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f32.c
index bafd431..aa0c65a 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintn_f32_x_tied1, svfloat32_t,
/*
** rintn_f32_x_untied:
+** movprfx z0, z1
** frintn z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f64.c
index 0142315..a9317ad 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintn_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintn_f64_x_tied1, svfloat64_t,
/*
** rintn_f64_x_untied:
+** movprfx z0, z1
** frintn z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f16.c
index 0e85c34..f511452 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintp_f16_x_tied1, svfloat16_t,
/*
** rintp_f16_x_untied:
+** movprfx z0, z1
** frintp z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f32.c
index cec360d..34596c4 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintp_f32_x_tied1, svfloat32_t,
/*
** rintp_f32_x_untied:
+** movprfx z0, z1
** frintp z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f64.c
index 1305fb6..a68a579 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintp_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintp_f64_x_tied1, svfloat64_t,
/*
** rintp_f64_x_untied:
+** movprfx z0, z1
** frintp z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f16.c
index 96f7f2c..a86e063 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintx_f16_x_tied1, svfloat16_t,
/*
** rintx_f16_x_untied:
+** movprfx z0, z1
** frintx z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f32.c
index 1c42d2a..9565150 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintx_f32_x_tied1, svfloat32_t,
/*
** rintx_f32_x_untied:
+** movprfx z0, z1
** frintx z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f64.c
index bee806b..a5c7a01 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintx_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintx_f64_x_tied1, svfloat64_t,
/*
** rintx_f64_x_untied:
+** movprfx z0, z1
** frintx z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f16.c
index be13d82..cb61080 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintz_f16_x_tied1, svfloat16_t,
/*
** rintz_f16_x_untied:
+** movprfx z0, z1
** frintz z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f32.c
index 873c0d4..a479909 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintz_f32_x_tied1, svfloat32_t,
/*
** rintz_f32_x_untied:
+** movprfx z0, z1
** frintz z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f64.c
index e6c9d1f..f80f907 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rintz_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rintz_f64_x_tied1, svfloat64_t,
/*
** rintz_f64_x_untied:
+** movprfx z0, z1
** frintz z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f16.c
index 6dc5940..335fb86 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (sqrt_f16_x_tied1, svfloat16_t,
/*
** sqrt_f16_x_untied:
+** movprfx z0, z1
** fsqrt z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f32.c
index 71d1f8f..0887996 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (sqrt_f32_x_tied1, svfloat32_t,
/*
** sqrt_f32_x_untied:
+** movprfx z0, z1
** fsqrt z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f64.c
index 7771df5..7dbab87 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sqrt_f64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (sqrt_f64_x_tied1, svfloat64_t,
/*
** sqrt_f64_x_untied:
+** movprfx z0, z1
** fsqrt z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_s8.c
index 1eb0bf1..c916d20 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_s8.c
@@ -74,7 +74,7 @@ TEST_STORE (st4_s8_28, svint8x4_t, int8_t,
/*
** st4_s8_32:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_s8_32, svint8x4_t, int8_t,
@@ -135,7 +135,7 @@ TEST_STORE (st4_s8_m32, svint8x4_t, int8_t,
/*
** st4_s8_m36:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_s8_m36, svint8x4_t, int8_t,
@@ -205,7 +205,7 @@ TEST_STORE (st4_vnum_s8_28, svint8x4_t, int8_t,
/*
** st4_vnum_s8_32:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_vnum_s8_32, svint8x4_t, int8_t,
@@ -266,7 +266,7 @@ TEST_STORE (st4_vnum_s8_m32, svint8x4_t, int8_t,
/*
** st4_vnum_s8_m36:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_vnum_s8_m36, svint8x4_t, int8_t,
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_u8.c
index e7c2e7d..32b8c8c 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_u8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st4_u8.c
@@ -74,7 +74,7 @@ TEST_STORE (st4_u8_28, svuint8x4_t, uint8_t,
/*
** st4_u8_32:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_u8_32, svuint8x4_t, uint8_t,
@@ -135,7 +135,7 @@ TEST_STORE (st4_u8_m32, svuint8x4_t, uint8_t,
/*
** st4_u8_m36:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_u8_m36, svuint8x4_t, uint8_t,
@@ -205,7 +205,7 @@ TEST_STORE (st4_vnum_u8_28, svuint8x4_t, uint8_t,
/*
** st4_vnum_u8_32:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_vnum_u8_32, svuint8x4_t, uint8_t,
@@ -266,7 +266,7 @@ TEST_STORE (st4_vnum_u8_m32, svuint8x4_t, uint8_t,
/*
** st4_vnum_u8_m36:
** [^{]*
-** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+\]
+** st4b {z0\.b - z3\.b}, p0, \[x[0-9]+, x[0-9]+\]
** ret
*/
TEST_STORE (st4_vnum_u8_m36, svuint8x4_t, uint8_t,
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr97546.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr97546.c
new file mode 100644
index 0000000..25707cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr97546.c
@@ -0,0 +1,22 @@
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+static svbool_t visinf_vo_vf(svfloat32_t d)
+{
+ return svcmpeq_n_f32 (svptrue_b8 (),
+ svabs_f32_x (svptrue_b8 (), d),
+ __builtin_inff ());
+}
+
+const svint32_t _ZGVsNxv_ilogbf(svfloat32_t d)
+{
+ svint32_t e = svreinterpret_s32_f32 (svdup_n_f32 (0.0f));
+ e = svsel_s32 (svcmpne_f32 (svptrue_b8(), d, d),
+ svdup_n_s32 (2147483647),
+ e);
+ e = svsel_s32 (visinf_vo_vf (d),
+ svdup_n_s32 (0x7fffffff),
+ e);
+ return e;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr98037.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr98037.c
new file mode 100644
index 0000000..b91e940
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr98037.c
@@ -0,0 +1,6 @@
+/* { dg-options "-msve-vector-bits=1024 -O3" } */
+
+typedef __SVInt8_t vec __attribute__((arm_sve_vector_bits(1024)));
+struct pair { vec v[2]; };
+void use (struct pair *);
+vec f (struct pair p) { vec v = p.v[1]; use (&p); return v; }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/undef_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/undef_1.c
new file mode 100644
index 0000000..793593b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/undef_1.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O2 -W -Wall -Werror" } */
+
+#include <arm_sve.h>
+
+svfloat32x2_t
+foo (svfloat32_t x, svfloat32_t y)
+{
+ svfloat32x2_t res = svundef2_f32 ();
+ res = svset2 (res, 0, x);
+ res = svset2 (res, 1, y);
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cmp_1.c b/gcc/testsuite/gcc.target/aarch64/sve/cmp_1.c
new file mode 100644
index 0000000..7cf66c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cmp_1.c
@@ -0,0 +1,57 @@
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+#define TEST_PAIR(TYPE1, TYPE2) \
+ void \
+ f_##TYPE1##_##TYPE2 (TYPE1 *restrict x, \
+ TYPE2 *restrict g, int n) \
+ { \
+ for (int i = 0; i < n; ++i) \
+ if (g[i] < 4) \
+ x[i] += 1; \
+ }
+
+#define TEST_SINGLE(TYPE) \
+ TEST_PAIR (TYPE, int8_t) \
+ TEST_PAIR (TYPE, uint8_t) \
+ TEST_PAIR (TYPE, int16_t) \
+ TEST_PAIR (TYPE, uint16_t) \
+ TEST_PAIR (TYPE, int32_t) \
+ TEST_PAIR (TYPE, uint32_t) \
+ TEST_PAIR (TYPE, int64_t) \
+ TEST_PAIR (TYPE, uint64_t)
+
+TEST_SINGLE (int8_t)
+TEST_SINGLE (uint8_t)
+TEST_SINGLE (int16_t)
+TEST_SINGLE (uint16_t)
+TEST_SINGLE (int32_t)
+TEST_SINGLE (uint32_t)
+TEST_SINGLE (int64_t)
+TEST_SINGLE (uint64_t)
+
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b,} 8 } } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.h,} 8 } } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.s,} 8 } } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.d,} 8 } } */
+
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h,} 16 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s,} 8 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d,} 8 } } */
+
+/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s,} 24 } } */
+/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d,} 8 } } */
+
+/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d,} 32 } } */
+
+/* { dg-final { scan-assembler-times {\tcmpl[et]\tp[0-9]+\.b,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[so]\tp[0-9]+\.b,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[et]\tp[0-9]+\.h,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[so]\tp[0-9]+\.h,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[et]\tp[0-9]+\.s,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[so]\tp[0-9]+\.s,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[et]\tp[0-9]+\.d,} 8 } } */
+/* { dg-final { scan-assembler-times {\tcmpl[so]\tp[0-9]+\.d,} 8 } } */
+
+/* { dg-final { scan-assembler-not {\tpunpk} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cmp_2.c b/gcc/testsuite/gcc.target/aarch64/sve/cmp_2.c
new file mode 100644
index 0000000..b221206
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cmp_2.c
@@ -0,0 +1,72 @@
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+#define TEST_PAIR(TYPE1, TYPE2) \
+ void \
+ f_##TYPE1##_##TYPE2 (TYPE1 *restrict x, TYPE1 y, TYPE1 z, \
+ TYPE2 *restrict g, TYPE2 h, int n) \
+ { \
+ for (int i = 0; i < n; ++i) \
+ x[i] = g[i] < h ? y : z; \
+ }
+
+#define TEST_SINGLE(TYPE) \
+ TEST_PAIR (TYPE, int8_t) \
+ TEST_PAIR (TYPE, uint8_t) \
+ TEST_PAIR (TYPE, int16_t) \
+ TEST_PAIR (TYPE, uint16_t) \
+ TEST_PAIR (TYPE, int32_t) \
+ TEST_PAIR (TYPE, uint32_t) \
+ TEST_PAIR (TYPE, int64_t) \
+ TEST_PAIR (TYPE, uint64_t)
+
+TEST_SINGLE (int8_t)
+TEST_SINGLE (uint8_t)
+TEST_SINGLE (int16_t)
+TEST_SINGLE (uint16_t)
+TEST_SINGLE (int32_t)
+TEST_SINGLE (uint32_t)
+TEST_SINGLE (float)
+TEST_SINGLE (int64_t)
+TEST_SINGLE (uint64_t)
+TEST_SINGLE (double)
+
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b,} 4 } } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.h,} 4 } } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.s,} 6 } } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.d,} 6 } } */
+
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h,} 8 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s,} 6 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d,} 6 } } */
+
+/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s,} 14 } } */
+/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d,} 6 } } */
+
+/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d,} 20 } } */
+
+/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b,} 4 } } */
+/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.h,} 4 } } */
+/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.s,} 4 } } */
+/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.d,} 4 } } */
+
+/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.h,} 8 } } */
+/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.s,} 4 } } */
+/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+\.d,} 4 } } */
+
+/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s,} 18 } } */
+/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.d,} 6 } } */
+
+/* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d,} 24 } } */
+
+/* { dg-final { scan-assembler-times {\tcmp(?:h[is]|l[os])\tp[0-9]+\.b,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp[lg][et]\tp[0-9]+\.b,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp(?:h[is]|l[os])\tp[0-9]+\.h,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp[lg][et]\tp[0-9]+\.h,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp(?:h[is]|l[os])\tp[0-9]+\.s,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp[lg][et]\tp[0-9]+\.s,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp(?:h[is]|l[os])\tp[0-9]+\.d,} 10 } } */
+/* { dg-final { scan-assembler-times {\tcmp[lg][et]\tp[0-9]+\.d,} 10 } } */
+
+/* { dg-final { scan-assembler-not {\tpunpk} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1.c
index 52138d2..d831e9c 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-options "-O2 -ftree-vectorize --param aarch64-sve-compare-costs=0" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1_run.c
index 876f98f..5808e0a 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1_run.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_1_run.c
@@ -1,5 +1,5 @@
/* { dg-do run { target aarch64_sve_hw } } */
-/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-options "-O2 -ftree-vectorize --param aarch64-sve-compare-costs=0" } */
#include "cond_arith_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3.c
index 94eb255..068e0b6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-options "-O2 -ftree-vectorize --param aarch64-sve-compare-costs=0" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3_run.c
index 31457da..d258004 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3_run.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_arith_3_run.c
@@ -1,5 +1,5 @@
/* { dg-do run { target aarch64_sve_hw } } */
-/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-options "-O2 -ftree-vectorize --param aarch64-sve-compare-costs=0" } */
#include "cond_arith_3.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_1.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_1.c
index bd87766..49f0b18 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_1.c
@@ -31,5 +31,4 @@ TEST_ALL (DEF_LOOP)
/* { dg-final { scan-assembler-not {\tmov\tz} } } */
/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */
-/* Currently we canonicalize the ?: so that !b[i] is the "false" value. */
-/* { dg-final { scan-assembler-not {\tsel\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_1.c
index 2b5f9c3..0492476 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_1.c
@@ -54,6 +54,4 @@ TEST_ALL (DEF_LOOP)
/* { dg-final { scan-assembler-not {\tmov\tz} } } */
/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */
-/* XFAILed because the ?: gets canonicalized so that the operation is in
- the false arm. */
-/* { dg-final { scan-assembler-not {\tsel\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_2.c b/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_2.c
new file mode 100644
index 0000000..3d74ff9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_2.c
@@ -0,0 +1,331 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B) B, B
+#define PERM1(B) PERM0 (B), PERM0 (B)
+#define PERM2(B) PERM1 (B), PERM1 (B)
+#define PERM3(B) PERM2 (B), PERM2 (B)
+#define PERM4(B) PERM3 (B), PERM3 (B)
+#define PERM5(B) PERM4 (B), PERM4 (B)
+#define PERM6(B) PERM5 (B), PERM5 (B)
+
+/*
+** qi_dup_h_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** dup (z[0-9]+)\.h, \2\.h\[1\]
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_dup_h_1 (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (1) });
+}
+
+/*
+** qi_dup_h_31:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** dup (z[0-9]+)\.h, \2\.h\[31\]
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_dup_h_31 (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (31) });
+}
+
+/*
+** qi_dup_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[1\]
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_dup_s_1 (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (1) });
+}
+
+/*
+** qi_dup_s_15:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[15\]
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_dup_s_15 (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (15) });
+}
+
+/*
+** qi_dup_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[1\]
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_dup_d_1 (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (1) });
+}
+
+/*
+** qi_dup_d_7:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[7\]
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_dup_d_7 (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (7) });
+}
+
+/*
+** hi_dup_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[1\]
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_dup_s_1 (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hi_dup_s_15:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[15\]
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_dup_s_15 (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (15) });
+}
+
+/*
+** hf_dup_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[1\]
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_dup_s_1 (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hf_dup_s_11:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[11\]
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_dup_s_11 (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (11) });
+}
+
+/*
+** bf_dup_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[1\]
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_dup_s_1 (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** bf_dup_s_13:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** dup (z[0-9]+)\.s, \2\.s\[13\]
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_dup_s_13 (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (13) });
+}
+
+/*
+** hi_dup_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[1\]
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_dup_d_1 (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hi_dup_d_7:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[7\]
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_dup_d_7 (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (7) });
+}
+
+/*
+** hf_dup_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[1\]
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_dup_d_1 (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hf_dup_d_5:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[5\]
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_dup_d_5 (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (5) });
+}
+
+/*
+** bf_dup_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[1\]
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_dup_d_1 (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** bf_dup_d_6:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[6\]
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_dup_d_6 (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (6) });
+}
+
+/*
+** si_dup_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[1\]
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_dup_d_1 (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1) });
+}
+
+/*
+** si_dup_d_7:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[7\]
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_dup_d_7 (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (7) });
+}
+
+/*
+** sf_dup_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[1\]
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_dup_d_1 (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1) });
+}
+
+/*
+** sf_dup_d_7:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** dup (z[0-9]+)\.d, \2\.d\[7\]
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_dup_d_7 (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (7) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_3.c b/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_3.c
new file mode 100644
index 0000000..50f73a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/dup_lane_3.c
@@ -0,0 +1,90 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B) B, B
+#define PERM1(B) PERM0 (B), PERM0 (B)
+#define PERM2(B) PERM1 (B), PERM1 (B)
+#define PERM3(B) PERM2 (B), PERM2 (B)
+#define PERM4(B) PERM3 (B), PERM3 (B)
+#define PERM5(B) PERM4 (B), PERM4 (B)
+#define PERM6(B) PERM5 (B), PERM5 (B)
+
+v128qi
+qi_dup_h_32 (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (32) });
+}
+
+v64qi
+qi_dup_s_16 (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (16) });
+}
+
+v32qi
+qi_dup_d_8 (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (8) });
+}
+
+v64hi
+hi_dup_s_16 (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (16) });
+}
+
+v64hf
+hf_dup_s_16 (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (16) });
+}
+
+v64bf
+bf_dup_s_16 (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (16) });
+}
+
+v32hi
+hi_dup_d_8 (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (8) });
+}
+
+v32hf
+hf_dup_d_8 (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (8) });
+}
+
+v32bf
+bf_dup_d_8 (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (8) });
+}
+
+v32si
+si_dup_d_8 (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (8) });
+}
+
+v32sf
+sf_dup_d_8 (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (8) });
+}
+
+/* { dg-final { scan-assembler-not {\tdup\tz} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/ext_4.c b/gcc/testsuite/gcc.target/aarch64/sve/ext_4.c
new file mode 100644
index 0000000..4637b5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/ext_4.c
@@ -0,0 +1,353 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B) B, B + 1
+#define PERM1(B) PERM0 (B), PERM0 (B + 2)
+#define PERM2(B) PERM1 (B), PERM1 (B + 4)
+#define PERM3(B) PERM2 (B), PERM2 (B + 8)
+#define PERM4(B) PERM3 (B), PERM3 (B + 16)
+#define PERM5(B) PERM4 (B), PERM4 (B + 32)
+#define PERM6(B) PERM5 (B), PERM5 (B + 64)
+
+/*
+** qi_ext_h_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #2
+** st1b \2\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_ext_h_1 (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (1) });
+}
+
+/*
+** qi_ext_h_1_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ext \3\.b, \3\.b, \2\.b, #2
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ext \4\.b, \4\.b, \5\.b, #2
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_ext_h_1_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (1) });
+}
+
+/*
+** qi_ext_h_127:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #254
+** st1b \2\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_ext_h_127 (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (127) });
+}
+
+/*
+** qi_ext_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #4
+** st1b \2\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_ext_s_1 (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (1) });
+}
+
+/*
+** qi_ext_s_63:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #252
+** st1b \2\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_ext_s_63 (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (63) });
+}
+
+/*
+** qi_ext_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #8
+** st1b \2\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_ext_d_1 (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (1) });
+}
+
+/*
+** qi_ext_d_31:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #248
+** st1b \2\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_ext_d_31 (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (31) });
+}
+
+/*
+** hi_ext_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #4
+** st1h \2\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_ext_s_1 (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hi_ext_s_63:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #252
+** st1h \2\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_ext_s_63 (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (63) });
+}
+
+/*
+** hf_ext_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #4
+** st1h \2\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_ext_s_1 (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hf_ext_s_60:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #240
+** st1h \2\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_ext_s_60 (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (60) });
+}
+
+/*
+** bf_ext_s_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #4
+** st1h \2\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_ext_s_1 (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** bf_ext_s_40:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #160
+** st1h \2\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_ext_s_40 (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (40) });
+}
+
+/*
+** hi_ext_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #8
+** st1h \2\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_ext_d_1 (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hi_ext_d_31:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #248
+** st1h \2\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_ext_d_31 (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (31) });
+}
+
+/*
+** hf_ext_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #8
+** st1h \2\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_ext_d_1 (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hf_ext_d_18:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #144
+** st1h \2\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_ext_d_18 (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (18) });
+}
+
+/*
+** bf_ext_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #8
+** st1h \2\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_ext_d_1 (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** bf_ext_d_7:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #56
+** st1h \2\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_ext_d_7 (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (7) });
+}
+
+/*
+** si_ext_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #8
+** st1w \2\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_ext_d_1 (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1) });
+}
+
+/*
+** si_ext_d_31:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #248
+** st1w \2\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_ext_d_31 (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (31) });
+}
+
+/*
+** sf_ext_d_1:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #8
+** st1w \2\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_ext_d_1 (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1) });
+}
+
+/*
+** sf_ext_d_31:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** ext \2\.b, \2\.b, \2\.b, #248
+** st1w \2\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_ext_d_31 (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (31) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_7.c b/gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_7.c
index cd2661e..687716e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_7.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_7.c
@@ -1,5 +1,5 @@
/* { dg-do assemble { target aarch64_asm_sve_ok } } */
-/* { dg-options "-O2 -ftree-vectorize -ffast-math --save-temps" } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math --save-temps --param aarch64-sve-compare-costs=0" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c b/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c
index 78c70b2..a38b92d 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-options "-O2 -ftree-vectorize --param aarch64-sve-compare-costs=0" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr97092.c b/gcc/testsuite/gcc.target/aarch64/sve/pr97092.c
new file mode 100644
index 0000000..69f7a3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr97092.c
@@ -0,0 +1,24 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O1 -ftree-vectorize -march=armv8.2-a+sve" } */
+
+void g (void);
+long a;
+
+signed char
+bar (int c, int d)
+{
+ return c + d;
+}
+
+void
+foo (void)
+{
+ int f;
+ for (; (long)foo < 4;) {
+ f = 0;
+ for (; f < 10; f++);
+ g ();
+ a = -4;
+ for (; a; a = bar (a, 1));
+ }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr98177-1.c b/gcc/testsuite/gcc.target/aarch64/sve/pr98177-1.c
new file mode 100644
index 0000000..9789193
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr98177-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=128" } */
+
+int a, b;
+short c;
+void d(long e) {
+ for (int f = 0; f < b; f += 1)
+ for (short g = 0; g < c; g += 5)
+ a = (short)e;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr98177-2.c b/gcc/testsuite/gcc.target/aarch64/sve/pr98177-2.c
new file mode 100644
index 0000000..c7244ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr98177-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=128" } */
+
+int a, b, c;
+
+void foo(long e) {
+ for (int f = 0; f < b; f ++)
+ for (int g = 0; g < c; g ++)
+ a = (short)e;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/rev_2.c b/gcc/testsuite/gcc.target/aarch64/sve/rev_2.c
new file mode 100644
index 0000000..417da37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/rev_2.c
@@ -0,0 +1,177 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B) B, B - 1
+#define PERM1(B) PERM0 (B), PERM0 (B - 2)
+#define PERM2(B) PERM1 (B), PERM1 (B - 4)
+#define PERM3(B) PERM2 (B), PERM2 (B - 8)
+#define PERM4(B) PERM3 (B), PERM3 (B - 16)
+#define PERM5(B) PERM4 (B), PERM4 (B - 32)
+#define PERM6(B) PERM5 (B), PERM5 (B - 64)
+
+/*
+** qi_rev_h:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** rev (z[0-9]+)\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_rev_h (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (127) });
+}
+
+/*
+** qi_rev_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** rev (z[0-9]+)\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_rev_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (63) });
+}
+
+/*
+** qi_rev_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** rev (z[0-9]+)\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_rev_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (31) });
+}
+
+/*
+** hi_rev_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** rev (z[0-9]+)\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_rev_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (63) });
+}
+
+/*
+** hf_rev_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** rev (z[0-9]+)\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_rev_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (63) });
+}
+
+/*
+** bf_rev_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** rev (z[0-9]+)\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_rev_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (63) });
+}
+
+/*
+** hi_rev_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** rev (z[0-9]+)\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_rev_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (31) });
+}
+
+/*
+** hf_rev_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** rev (z[0-9]+)\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_rev_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (31) });
+}
+
+/*
+** bf_rev_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** rev (z[0-9]+)\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_rev_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (31) });
+}
+
+/*
+** si_rev_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** rev (z[0-9]+)\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_rev_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (31) });
+}
+
+/*
+** sf_rev_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** rev (z[0-9]+)\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_rev_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (31) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/revhw_1.c b/gcc/testsuite/gcc.target/aarch64/sve/revhw_1.c
new file mode 100644
index 0000000..62de812
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/revhw_1.c
@@ -0,0 +1,127 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+
+#define PERM0(B) B + 1, B
+#define PERM1(B) PERM0 (B), PERM0 (B + 2)
+#define PERM2(B) PERM1 (B), PERM1 (B + 4)
+#define PERM3(B) PERM2 (B), PERM2 (B + 8)
+#define PERM4(B) PERM3 (B), PERM3 (B + 16)
+#define PERM5(B) PERM4 (B), PERM4 (B + 32)
+#define PERM6(B) PERM5 (B), PERM5 (B + 64)
+
+/*
+** qi_revh_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** revh (z[0-9]+)\.s, \1/m, \2\.s
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_revh_s (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+/*
+** qi_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_revw_d (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0) });
+}
+
+/*
+** hi_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_revw_d (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** hf_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_revw_d (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** bf_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_revw_d (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+#undef PERM1
+#define PERM1(B) PERM0 (B + 2), PERM0 (B)
+
+/*
+** qi_revh_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** revh (z[0-9]+)\.d, \1/m, \2\.d
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_revh_d (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+v64qi
+qi_revw_q (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0) });
+}
+
+v64hi
+hi_revw_q (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+#undef PERM2
+#define PERM2(B) PERM0 (B + 4), PERM0 (B)
+
+v128qi
+qi_revh_q (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+/* { dg-final { scan-assembler-times {\trev.\t} 6 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c b/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c
new file mode 100644
index 0000000..7634d01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c
@@ -0,0 +1,127 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mbig-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+
+#define PERM0(B) B + 1, B
+#define PERM1(B) PERM0 (B), PERM0 (B + 2)
+#define PERM2(B) PERM1 (B), PERM1 (B + 4)
+#define PERM3(B) PERM2 (B), PERM2 (B + 8)
+#define PERM4(B) PERM3 (B), PERM3 (B + 16)
+#define PERM5(B) PERM4 (B), PERM4 (B + 32)
+#define PERM6(B) PERM5 (B), PERM5 (B + 64)
+
+/*
+** qi_revh_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** revh (z[0-9]+)\.s, \1/m, \2\.s
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_revh_s (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+/*
+** qi_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_revw_d (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0) });
+}
+
+/*
+** hi_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_revw_d (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** hf_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_revw_d (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** bf_revw_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** revw (z[0-9]+)\.d, \1/m, \2\.d
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_revw_d (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+#undef PERM1
+#define PERM1(B) PERM0 (B + 2), PERM0 (B)
+
+/*
+** qi_revh_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** revh (z[0-9]+)\.d, \1/m, \2\.d
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_revh_d (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+v64qi
+qi_revw_q (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0) });
+}
+
+v64hi
+hi_revw_q (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+#undef PERM2
+#define PERM2(B) PERM0 (B + 4), PERM0 (B)
+
+v128qi
+qi_revh_q (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+/* { dg-final { scan-assembler-times {\trev.\t} 6 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_8.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_8.c
new file mode 100644
index 0000000..fe25000
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_8.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+void
+f (short *restrict s, signed char *restrict c)
+{
+ for (int i = 0; i < 8; i += 2)
+ {
+ s[i] = c[i];
+ s[i + 1] = c[i];
+ }
+}
+
+/* Ideally this would use LD1SB, but currently we use LD1B and
+ sign-extend it after the permute. */
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl6\n} } } */
+/* { dg-final { scan-assembler {\tld1s?b\tz[0-9]+\.h} } } */
+/* { dg-final { scan-assembler {\ttrn1\tz[0-9]+\.h,} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/trn1_2.c b/gcc/testsuite/gcc.target/aarch64/sve/trn1_2.c
new file mode 100644
index 0000000..df059dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/trn1_2.c
@@ -0,0 +1,403 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B, C) B, B + C
+#define PERM1(B, C) PERM0 (B, C), PERM0 (B + 2, C)
+#define PERM2(B, C) PERM1 (B, C), PERM1 (B + 4, C)
+#define PERM3(B, C) PERM2 (B, C), PERM2 (B + 8, C)
+#define PERM4(B, C) PERM3 (B, C), PERM3 (B + 16, C)
+#define PERM5(B, C) PERM4 (B, C), PERM4 (B + 32, C)
+#define PERM6(B, C) PERM5 (B, C), PERM5 (B + 64, C)
+
+/*
+** qi_trn1_h_a:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_trn1_h_a (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0, 0) });
+}
+
+/*
+** qi_trn1_h_b:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_trn1_h_b (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0, 128) });
+}
+
+/*
+** qi_trn1_h_c:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_trn1_h_c (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (128, 0) });
+}
+
+/*
+** qi_trn1_h_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn1 \3\.h, \3\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** trn1 \4\.h, \4\.h, \5\.h
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_trn1_h_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (0, 128) });
+}
+
+/*
+** qi_trn1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_trn1_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0, 64) });
+}
+
+/*
+** qi_trn1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 \3\.s, \3\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** trn1 \4\.s, \4\.s, \5\.s
+** st1b \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64qi
+qi_trn1_s_two_op (v64qi x, v64qi y)
+{
+ return __builtin_shuffle (x, y, (v64qi) { PERM5 (0, 64) });
+}
+
+/*
+** qi_trn1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_trn1_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (0, 32) });
+}
+
+/*
+** qi_trn1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 \3\.d, \3\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** trn1 \4\.d, \4\.d, \5\.d
+** st1b \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32qi
+qi_trn1_d_two_op (v32qi x, v32qi y)
+{
+ return __builtin_shuffle (x, y, (v32qi) { PERM4 (0, 32) });
+}
+
+/*
+** hi_trn1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_trn1_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hi_trn1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** trn1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hi
+hi_trn1_s_two_op (v64hi x, v64hi y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hf_trn1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_trn1_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hf_trn1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** trn1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hf
+hf_trn1_s_two_op (v64hf x, v64hf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** bf_trn1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_trn1_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** bf_trn1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** trn1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64bf
+bf_trn1_s_two_op (v64bf x, v64bf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hi_trn1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_trn1_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** hi_trn1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** trn1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hi
+hi_trn1_d_two_op (v32hi x, v32hi y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** hf_trn1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_trn1_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** hf_trn1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** trn1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hf
+hf_trn1_d_two_op (v32hf x, v32hf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** bf_trn1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_trn1_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** bf_trn1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** trn1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32bf
+bf_trn1_d_two_op (v32bf x, v32bf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** si_trn1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_trn1_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (0, 32) });
+}
+
+/*
+** sf_trn1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** trn1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_trn1_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (0, 32) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/trn2_2.c b/gcc/testsuite/gcc.target/aarch64/sve/trn2_2.c
new file mode 100644
index 0000000..290ce8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/trn2_2.c
@@ -0,0 +1,403 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B, C) B, B + C
+#define PERM1(B, C) PERM0 (B, C), PERM0 (B + 2, C)
+#define PERM2(B, C) PERM1 (B, C), PERM1 (B + 4, C)
+#define PERM3(B, C) PERM2 (B, C), PERM2 (B + 8, C)
+#define PERM4(B, C) PERM3 (B, C), PERM3 (B + 16, C)
+#define PERM5(B, C) PERM4 (B, C), PERM4 (B + 32, C)
+#define PERM6(B, C) PERM5 (B, C), PERM5 (B + 64, C)
+
+/*
+** qi_trn2_h_a:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_trn2_h_a (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (1, 0) });
+}
+
+/*
+** qi_trn2_h_b:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_trn2_h_b (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (1, 128) });
+}
+
+/*
+** qi_trn2_h_c:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_trn2_h_c (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (1, 0) });
+}
+
+/*
+** qi_trn2_h_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** trn2 \3\.h, \3\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** trn2 \4\.h, \4\.h, \5\.h
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_trn2_h_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (1, 128) });
+}
+
+/*
+** qi_trn2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_trn2_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (1, 64) });
+}
+
+/*
+** qi_trn2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 \3\.s, \3\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** trn2 \4\.s, \4\.s, \5\.s
+** st1b \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64qi
+qi_trn2_s_two_op (v64qi x, v64qi y)
+{
+ return __builtin_shuffle (x, y, (v64qi) { PERM5 (1, 64) });
+}
+
+/*
+** qi_trn2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_trn2_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (1, 32) });
+}
+
+/*
+** qi_trn2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 \3\.d, \3\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** trn2 \4\.d, \4\.d, \5\.d
+** st1b \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32qi
+qi_trn2_d_two_op (v32qi x, v32qi y)
+{
+ return __builtin_shuffle (x, y, (v32qi) { PERM4 (1, 32) });
+}
+
+/*
+** hi_trn2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_trn2_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1, 64) });
+}
+
+/*
+** hi_trn2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** trn2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hi
+hi_trn2_s_two_op (v64hi x, v64hi y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (1, 64) });
+}
+
+/*
+** hf_trn2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_trn2_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1, 64) });
+}
+
+/*
+** hf_trn2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** trn2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hf
+hf_trn2_s_two_op (v64hf x, v64hf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (1, 64) });
+}
+
+/*
+** bf_trn2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_trn2_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1, 64) });
+}
+
+/*
+** bf_trn2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** trn2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** trn2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64bf
+bf_trn2_s_two_op (v64bf x, v64bf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (1, 64) });
+}
+
+/*
+** hi_trn2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_trn2_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1, 32) });
+}
+
+/*
+** hi_trn2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** trn2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hi
+hi_trn2_d_two_op (v32hi x, v32hi y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (1, 32) });
+}
+
+/*
+** hf_trn2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_trn2_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1, 32) });
+}
+
+/*
+** hf_trn2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** trn2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hf
+hf_trn2_d_two_op (v32hf x, v32hf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (1, 32) });
+}
+
+/*
+** bf_trn2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_trn2_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1, 32) });
+}
+
+/*
+** bf_trn2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** trn2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32bf
+bf_trn2_d_two_op (v32bf x, v32bf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (1, 32) });
+}
+
+/*
+** si_trn2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_trn2_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1, 32) });
+}
+
+/*
+** sf_trn2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** trn2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_trn2_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1, 32) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/uzp1_2.c b/gcc/testsuite/gcc.target/aarch64/sve/uzp1_2.c
new file mode 100644
index 0000000..e2f2692
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/uzp1_2.c
@@ -0,0 +1,375 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B) B, B + 2
+#define PERM1(B) PERM0 (B), PERM0 (B + 4)
+#define PERM2(B) PERM1 (B), PERM1 (B + 8)
+#define PERM3(B) PERM2 (B), PERM2 (B + 16)
+#define PERM4(B) PERM3 (B), PERM3 (B + 32)
+#define PERM5(B) PERM4 (B), PERM4 (B + 64)
+#define PERM6(B) PERM5 (B), PERM5 (B + 128)
+
+/*
+** qi_uzp1_h:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_uzp1_h (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0) });
+}
+
+/*
+** qi_uzp1_h_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** uzp1 \3\.h, \3\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** uzp1 \4\.h, \4\.h, \5\.h
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_uzp1_h_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (0) });
+}
+
+/*
+** qi_uzp1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_uzp1_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0) });
+}
+
+/*
+** qi_uzp1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 \3\.s, \3\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp1 \4\.s, \4\.s, \5\.s
+** st1b \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64qi
+qi_uzp1_s_two_op (v64qi x, v64qi y)
+{
+ return __builtin_shuffle (x, y, (v64qi) { PERM5 (0) });
+}
+
+/*
+** qi_uzp1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_uzp1_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (0) });
+}
+
+/*
+** qi_uzp1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 \3\.d, \3\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp1 \4\.d, \4\.d, \5\.d
+** st1b \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32qi
+qi_uzp1_d_two_op (v32qi x, v32qi y)
+{
+ return __builtin_shuffle (x, y, (v32qi) { PERM4 (0) });
+}
+
+/*
+** hi_uzp1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_uzp1_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** hi_uzp1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hi
+hi_uzp1_s_two_op (v64hi x, v64hi y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0) });
+}
+
+/*
+** hf_uzp1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_uzp1_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** hf_uzp1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hf
+hf_uzp1_s_two_op (v64hf x, v64hf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0) });
+}
+
+/*
+** bf_uzp1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_uzp1_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0) });
+}
+
+/*
+** bf_uzp1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64bf
+bf_uzp1_s_two_op (v64bf x, v64bf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0) });
+}
+
+/*
+** hi_uzp1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_uzp1_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0) });
+}
+
+/*
+** hi_uzp1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hi
+hi_uzp1_d_two_op (v32hi x, v32hi y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0) });
+}
+
+/*
+** hf_uzp1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_uzp1_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0) });
+}
+
+/*
+** hf_uzp1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hf
+hf_uzp1_d_two_op (v32hf x, v32hf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0) });
+}
+
+/*
+** bf_uzp1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_uzp1_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0) });
+}
+
+/*
+** bf_uzp1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32bf
+bf_uzp1_d_two_op (v32bf x, v32bf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0) });
+}
+
+/*
+** si_uzp1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_uzp1_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (0) });
+}
+
+/*
+** sf_uzp1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_uzp1_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (0) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/uzp2_2.c b/gcc/testsuite/gcc.target/aarch64/sve/uzp2_2.c
new file mode 100644
index 0000000..0d8eda5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/uzp2_2.c
@@ -0,0 +1,375 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B) B, B + 2
+#define PERM1(B) PERM0 (B), PERM0 (B + 4)
+#define PERM2(B) PERM1 (B), PERM1 (B + 8)
+#define PERM3(B) PERM2 (B), PERM2 (B + 16)
+#define PERM4(B) PERM3 (B), PERM3 (B + 32)
+#define PERM5(B) PERM4 (B), PERM4 (B + 64)
+#define PERM6(B) PERM5 (B), PERM5 (B + 128)
+
+/*
+** qi_uzp2_h:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_uzp2_h (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (1) });
+}
+
+/*
+** qi_uzp2_h_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** uzp2 \3\.h, \3\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** uzp2 \4\.h, \4\.h, \5\.h
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_uzp2_h_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (1) });
+}
+
+/*
+** qi_uzp2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_uzp2_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (1) });
+}
+
+/*
+** qi_uzp2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 \3\.s, \3\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp2 \4\.s, \4\.s, \5\.s
+** st1b \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64qi
+qi_uzp2_s_two_op (v64qi x, v64qi y)
+{
+ return __builtin_shuffle (x, y, (v64qi) { PERM5 (1) });
+}
+
+/*
+** qi_uzp2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_uzp2_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (1) });
+}
+
+/*
+** qi_uzp2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 \3\.d, \3\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp2 \4\.d, \4\.d, \5\.d
+** st1b \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32qi
+qi_uzp2_d_two_op (v32qi x, v32qi y)
+{
+ return __builtin_shuffle (x, y, (v32qi) { PERM4 (1) });
+}
+
+/*
+** hi_uzp2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_uzp2_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hi_uzp2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hi
+hi_uzp2_s_two_op (v64hi x, v64hi y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hf_uzp2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_uzp2_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hf_uzp2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hf
+hf_uzp2_s_two_op (v64hf x, v64hf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (1) });
+}
+
+/*
+** bf_uzp2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_uzp2_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (1) });
+}
+
+/*
+** bf_uzp2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** uzp2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** uzp2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64bf
+bf_uzp2_s_two_op (v64bf x, v64bf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (1) });
+}
+
+/*
+** hi_uzp2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_uzp2_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hi_uzp2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hi
+hi_uzp2_d_two_op (v32hi x, v32hi y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hf_uzp2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_uzp2_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** hf_uzp2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hf
+hf_uzp2_d_two_op (v32hf x, v32hf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (1) });
+}
+
+/*
+** bf_uzp2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_uzp2_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (1) });
+}
+
+/*
+** bf_uzp2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** uzp2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32bf
+bf_uzp2_d_two_op (v32bf x, v32bf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (1) });
+}
+
+/*
+** si_uzp2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_uzp2_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1) });
+}
+
+/*
+** sf_uzp2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** uzp2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_uzp2_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (1) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_11.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_11.c
index 3c9e340..4efcf3a 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/vcond_11.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -march=armv8-a+sve" } */
+/* { dg-options "-O2 -ftree-vectorize -march=armv8-a+sve --param aarch64-sve-compare-costs=0" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_11_run.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_11_run.c
index 9a4edb8..4cbe4a6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/vcond_11_run.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_11_run.c
@@ -1,5 +1,5 @@
/* { dg-do run { target aarch64_sve_hw } } */
-/* { dg-options "-O2 -ftree-vectorize -march=armv8-a+sve" } */
+/* { dg-options "-O2 -ftree-vectorize -march=armv8-a+sve --param aarch64-sve-compare-costs=0" } */
#include "vcond_11.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/zip1_2.c b/gcc/testsuite/gcc.target/aarch64/sve/zip1_2.c
new file mode 100644
index 0000000..395b96f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/zip1_2.c
@@ -0,0 +1,403 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B, C) B, B + C
+#define PERM1(B, C) PERM0 (B, C), PERM0 (B + 1, C)
+#define PERM2(B, C) PERM1 (B, C), PERM1 (B + 2, C)
+#define PERM3(B, C) PERM2 (B, C), PERM2 (B + 4, C)
+#define PERM4(B, C) PERM3 (B, C), PERM3 (B + 8, C)
+#define PERM5(B, C) PERM4 (B, C), PERM4 (B + 16, C)
+#define PERM6(B, C) PERM5 (B, C), PERM5 (B + 32, C)
+
+/*
+** qi_zip1_h_a:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_zip1_h_a (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0, 0) });
+}
+
+/*
+** qi_zip1_h_b:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_zip1_h_b (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (0, 128) });
+}
+
+/*
+** qi_zip1_h_c:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_zip1_h_c (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (128, 0) });
+}
+
+/*
+** qi_zip1_h_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip1 \3\.h, \3\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** zip1 \4\.h, \4\.h, \5\.h
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_zip1_h_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (0, 128) });
+}
+
+/*
+** qi_zip1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_zip1_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (0, 64) });
+}
+
+/*
+** qi_zip1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 \3\.s, \3\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** zip1 \4\.s, \4\.s, \5\.s
+** st1b \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64qi
+qi_zip1_s_two_op (v64qi x, v64qi y)
+{
+ return __builtin_shuffle (x, y, (v64qi) { PERM5 (0, 64) });
+}
+
+/*
+** qi_zip1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_zip1_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (0, 32) });
+}
+
+/*
+** qi_zip1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 \3\.d, \3\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** zip1 \4\.d, \4\.d, \5\.d
+** st1b \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32qi
+qi_zip1_d_two_op (v32qi x, v32qi y)
+{
+ return __builtin_shuffle (x, y, (v32qi) { PERM4 (0, 32) });
+}
+
+/*
+** hi_zip1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_zip1_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hi_zip1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** zip1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hi
+hi_zip1_s_two_op (v64hi x, v64hi y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hf_zip1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_zip1_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hf_zip1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** zip1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hf
+hf_zip1_s_two_op (v64hf x, v64hf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** bf_zip1_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_zip1_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** bf_zip1_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip1 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** zip1 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64bf
+bf_zip1_s_two_op (v64bf x, v64bf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (0, 64) });
+}
+
+/*
+** hi_zip1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_zip1_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** hi_zip1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** zip1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hi
+hi_zip1_d_two_op (v32hi x, v32hi y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** hf_zip1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_zip1_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** hf_zip1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** zip1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hf
+hf_zip1_d_two_op (v32hf x, v32hf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** bf_zip1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_zip1_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** bf_zip1_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** zip1 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32bf
+bf_zip1_d_two_op (v32bf x, v32bf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (0, 32) });
+}
+
+/*
+** si_zip1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_zip1_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (0, 32) });
+}
+
+/*
+** sf_zip1_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** zip1 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_zip1_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (0, 32) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/zip2_2.c b/gcc/testsuite/gcc.target/aarch64/sve/zip2_2.c
new file mode 100644
index 0000000..9158ace
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/zip2_2.c
@@ -0,0 +1,403 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=2048 -mlittle-endian --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+typedef unsigned char v128qi __attribute__((vector_size(128)));
+typedef unsigned char v64qi __attribute__((vector_size(64)));
+typedef unsigned char v32qi __attribute__((vector_size(32)));
+typedef unsigned short v64hi __attribute__((vector_size(128)));
+typedef unsigned short v32hi __attribute__((vector_size(64)));
+typedef _Float16 v64hf __attribute__((vector_size(128)));
+typedef _Float16 v32hf __attribute__((vector_size(64)));
+typedef __bf16 v64bf __attribute__((vector_size(128)));
+typedef __bf16 v32bf __attribute__((vector_size(64)));
+typedef unsigned int v32si __attribute__((vector_size(128)));
+typedef float v32sf __attribute__((vector_size(128)));
+
+#define PERM0(B, C) B, B + C
+#define PERM1(B, C) PERM0 (B, C), PERM0 (B + 1, C)
+#define PERM2(B, C) PERM1 (B, C), PERM1 (B + 2, C)
+#define PERM3(B, C) PERM2 (B, C), PERM2 (B + 4, C)
+#define PERM4(B, C) PERM3 (B, C), PERM3 (B + 8, C)
+#define PERM5(B, C) PERM4 (B, C), PERM4 (B + 16, C)
+#define PERM6(B, C) PERM5 (B, C), PERM5 (B + 32, C)
+
+/*
+** qi_zip2_h_a:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_zip2_h_a (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (64, 128) });
+}
+
+/*
+** qi_zip2_h_b:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_zip2_h_b (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (64, 128) });
+}
+
+/*
+** qi_zip2_h_c:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.h, \2\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** ret
+*/
+v128qi
+qi_zip2_h_c (v128qi x)
+{
+ return __builtin_shuffle (x, x, (v128qi) { PERM6 (192, 0) });
+}
+
+/*
+** qi_zip2_h_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** zip2 \3\.h, \3\.h, \2\.h
+** st1b \3\.h, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.h, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.h, \1/z, \[x1\]
+** zip2 \4\.h, \4\.h, \5\.h
+** st1b \4\.h, \1, \[x8\]
+** )
+** ret
+*/
+v128qi
+qi_zip2_h_two_op (v128qi x, v128qi y)
+{
+ return __builtin_shuffle (x, y, (v128qi) { PERM6 (64, 128) });
+}
+
+/*
+** qi_zip2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** ret
+*/
+v64qi
+qi_zip2_s (v64qi x)
+{
+ return __builtin_shuffle (x, x, (v64qi) { PERM5 (32, 64) });
+}
+
+/*
+** qi_zip2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 \3\.s, \3\.s, \2\.s
+** st1b \3\.s, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.s, \1/z, \[x1\]
+** zip2 \4\.s, \4\.s, \5\.s
+** st1b \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64qi
+qi_zip2_s_two_op (v64qi x, v64qi y)
+{
+ return __builtin_shuffle (x, y, (v64qi) { PERM5 (32, 64) });
+}
+
+/*
+** qi_zip2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** ret
+*/
+v32qi
+qi_zip2_d (v32qi x)
+{
+ return __builtin_shuffle (x, x, (v32qi) { PERM4 (16, 32) });
+}
+
+/*
+** qi_zip2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 \3\.d, \3\.d, \2\.d
+** st1b \3\.d, \1, \[x8\]
+** |
+** ld1b (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1b (z[0-9]+)\.d, \1/z, \[x1\]
+** zip2 \4\.d, \4\.d, \5\.d
+** st1b \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32qi
+qi_zip2_d_two_op (v32qi x, v32qi y)
+{
+ return __builtin_shuffle (x, y, (v32qi) { PERM4 (16, 32) });
+}
+
+/*
+** hi_zip2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hi
+hi_zip2_s (v64hi x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (32, 64) });
+}
+
+/*
+** hi_zip2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** zip2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hi
+hi_zip2_s_two_op (v64hi x, v64hi y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (32, 64) });
+}
+
+/*
+** hf_zip2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64hf
+hf_zip2_s (v64hf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (32, 64) });
+}
+
+/*
+** hf_zip2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** zip2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64hf
+hf_zip2_s_two_op (v64hf x, v64hf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (32, 64) });
+}
+
+/*
+** bf_zip2_s:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.s, \2\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** ret
+*/
+v64bf
+bf_zip2_s (v64bf x)
+{
+ return __builtin_shuffle (x, x, (v64hi) { PERM5 (32, 64) });
+}
+
+/*
+** bf_zip2_s_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** zip2 \3\.s, \3\.s, \2\.s
+** st1h \3\.s, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.s, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.s, \1/z, \[x1\]
+** zip2 \4\.s, \4\.s, \5\.s
+** st1h \4\.s, \1, \[x8\]
+** )
+** ret
+*/
+v64bf
+bf_zip2_s_two_op (v64bf x, v64bf y)
+{
+ return __builtin_shuffle (x, y, (v64hi) { PERM5 (32, 64) });
+}
+
+/*
+** hi_zip2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hi
+hi_zip2_d (v32hi x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (16, 32) });
+}
+
+/*
+** hi_zip2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** zip2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hi
+hi_zip2_d_two_op (v32hi x, v32hi y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (16, 32) });
+}
+
+/*
+** hf_zip2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32hf
+hf_zip2_d (v32hf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (16, 32) });
+}
+
+/*
+** hf_zip2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** zip2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32hf
+hf_zip2_d_two_op (v32hf x, v32hf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (16, 32) });
+}
+
+/*
+** bf_zip2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** ret
+*/
+v32bf
+bf_zip2_d (v32bf x)
+{
+ return __builtin_shuffle (x, x, (v32hi) { PERM4 (16, 32) });
+}
+
+/*
+** bf_zip2_d_two_op:
+** ptrue (p[0-7])\.b, vl256
+** (
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 \3\.d, \3\.d, \2\.d
+** st1h \3\.d, \1, \[x8\]
+** |
+** ld1h (z[0-9]+)\.d, \1/z, \[x0\]
+** ld1h (z[0-9]+)\.d, \1/z, \[x1\]
+** zip2 \4\.d, \4\.d, \5\.d
+** st1h \4\.d, \1, \[x8\]
+** )
+** ret
+*/
+v32bf
+bf_zip2_d_two_op (v32bf x, v32bf y)
+{
+ return __builtin_shuffle (x, y, (v32hi) { PERM4 (16, 32) });
+}
+
+/*
+** si_zip2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32si
+si_zip2_d (v32si x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (16, 32) });
+}
+
+/*
+** sf_zip2_d:
+** ptrue (p[0-7])\.b, vl256
+** ld1w (z[0-9]+)\.d, \1/z, \[x0\]
+** zip2 (z[0-9]+)\.d, \2\.d, \2\.d
+** st1w \3\.d, \1, \[x8\]
+** ret
+*/
+v32sf
+sf_zip2_d (v32sf x)
+{
+ return __builtin_shuffle (x, x, (v32si) { PERM4 (16, 32) });
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f32.c
index 911defa..f66fa90 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f32.c
@@ -42,7 +42,13 @@ TEST_DUAL_Z_REV (cvtlt_f32_f16_x_tied1, svfloat32_t, svfloat16_t,
/*
** cvtlt_f32_f16_x_untied:
-** fcvtlt z0\.s, p0/m, z4\.h
+** (
+** mov z0\.d, z4\.d
+** fcvtlt z0\.s, p0/m, z0\.h
+** |
+** fcvtlt z4\.s, p0/m, z4\.h
+** mov z0\.d, z4\.d
+** )
** ret
*/
TEST_DUAL_Z (cvtlt_f32_f16_x_untied, svfloat32_t, svfloat16_t,
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f64.c
index c34947b..b262e25 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtlt_f64.c
@@ -42,7 +42,13 @@ TEST_DUAL_Z_REV (cvtlt_f64_f32_x_tied1, svfloat64_t, svfloat32_t,
/*
** cvtlt_f64_f32_x_untied:
-** fcvtlt z0\.d, p0/m, z4\.s
+** (
+** mov z0\.d, z4\.d
+** fcvtlt z0\.d, p0/m, z0\.s
+** |
+** fcvtlt z4\.d, p0/m, z4\.s
+** mov z0\.d, z4\.d
+** )
** ret
*/
TEST_DUAL_Z (cvtlt_f64_f32_x_untied, svfloat64_t, svfloat32_t,
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtx_f32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtx_f32.c
index 21724c8..85fbc79 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtx_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/cvtx_f32.c
@@ -64,6 +64,7 @@ TEST_DUAL_Z_REV (cvtx_f32_f64_x_tied1, svfloat32_t, svfloat64_t,
/*
** cvtx_f32_f64_x_untied:
+** movprfx z0, z4
** fcvtx z0\.s, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f16.c
index bc68156..fe65e64 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f16.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (logb_f16_z, svint16_t, svfloat16_t,
/*
** logb_f16_x:
+** movprfx z0, z4
** flogb z0\.h, p0/m, z4\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f32.c
index 35bdcd1..847e1b1 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f32.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (logb_f32_z, svint32_t, svfloat32_t,
/*
** logb_f32_x:
+** movprfx z0, z4
** flogb z0\.s, p0/m, z4\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f64.c
index c7c2cb2..4113a37 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/logb_f64.c
@@ -33,6 +33,7 @@ TEST_DUAL_Z (logb_f64_z, svint64_t, svfloat64_t,
/*
** logb_f64_x:
+** movprfx z0, z4
** flogb z0\.d, p0/m, z4\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s16.c
index 0756488..d7acf47 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qabs_s16_x_tied1, svint16_t,
/*
** qabs_s16_x_untied:
+** movprfx z0, z1
** sqabs z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s32.c
index 5341f78..fc35d10 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qabs_s32_x_tied1, svint32_t,
/*
** qabs_s32_x_untied:
+** movprfx z0, z1
** sqabs z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s64.c
index 3679e65..b572785 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qabs_s64_x_tied1, svint64_t,
/*
** qabs_s64_x_untied:
+** movprfx z0, z1
** sqabs z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s8.c
index dca25f9..48b8560 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qabs_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qabs_s8_x_tied1, svint8_t,
/*
** qabs_s8_x_untied:
+** movprfx z0, z1
** sqabs z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s16.c
index ca78f9d..d8b6c87 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s16.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qneg_s16_x_tied1, svint16_t,
/*
** qneg_s16_x_untied:
+** movprfx z0, z1
** sqneg z0\.h, p0/m, z1\.h
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s32.c
index 3d2ed87..2342504 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qneg_s32_x_tied1, svint32_t,
/*
** qneg_s32_x_untied:
+** movprfx z0, z1
** sqneg z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s64.c
index e137986..61ccb98 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s64.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qneg_s64_x_tied1, svint64_t,
/*
** qneg_s64_x_untied:
+** movprfx z0, z1
** sqneg z0\.d, p0/m, z1\.d
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s8.c
index 13c60ef..c7ec611 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/qneg_s8.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (qneg_s8_x_tied1, svint8_t,
/*
** qneg_s8_x_untied:
+** movprfx z0, z1
** sqneg z0\.b, p0/m, z1\.b
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/recpe_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/recpe_u32.c
index 17c6a72..c484cec 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/recpe_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/recpe_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (recpe_u32_x_tied1, svuint32_t,
/*
** recpe_u32_x_untied:
+** movprfx z0, z1
** urecpe z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rsqrte_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rsqrte_u32.c
index e9e4fb7..082a810 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rsqrte_u32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rsqrte_u32.c
@@ -73,6 +73,7 @@ TEST_UNIFORM_Z (rsqrte_u32_x_tied1, svuint32_t,
/*
** rsqrte_u32_x_untied:
+** movprfx z0, z1
** ursqrte z0\.s, p0/m, z1\.s
** ret
*/
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/bcax_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/bcax_1.c
index 4b0d5a9..7c31afc 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/bcax_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/bcax_1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details --save-temps" } */
-#define OP(x,y,z) ((x) ^ ((y) & (z)))
+#define OP(x,y,z) ((x) ^ (~(y) & (z)))
#include "bitsel_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-widen-add.c b/gcc/testsuite/gcc.target/aarch64/vect-widen-add.c
new file mode 100644
index 0000000..220bd93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-widen-add.c
@@ -0,0 +1,92 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -save-temps" } */
+#include <stdint.h>
+#include <string.h>
+
+#pragma GCC target "+nosve"
+
+#define ARR_SIZE 1024
+
+/* Should produce an uaddl */
+void uadd_opt (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] + b[i];
+ foo[i+1] = a[i+1] + b[i+1];
+ foo[i+2] = a[i+2] + b[i+2];
+ foo[i+3] = a[i+3] + b[i+3];
+ }
+}
+
+__attribute__((optimize (0)))
+void uadd_nonopt (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] + b[i];
+ foo[i+1] = a[i+1] + b[i+1];
+ foo[i+2] = a[i+2] + b[i+2];
+ foo[i+3] = a[i+3] + b[i+3];
+ }
+}
+
+/* Should produce an saddl */
+void sadd_opt (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] + b[i];
+ foo[i+1] = a[i+1] + b[i+1];
+ foo[i+2] = a[i+2] + b[i+2];
+ foo[i+3] = a[i+3] + b[i+3];
+ }
+}
+
+__attribute__((optimize (0)))
+void sadd_nonopt (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] + b[i];
+ foo[i+1] = a[i+1] + b[i+1];
+ foo[i+2] = a[i+2] + b[i+2];
+ foo[i+3] = a[i+3] + b[i+3];
+ }
+}
+
+
+void __attribute__((optimize (0)))
+init(uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE;i++)
+ {
+ a[i] = i;
+ b[i] = 2*i;
+ }
+}
+
+int __attribute__((optimize (0)))
+main()
+{
+ uint32_t foo_arr[ARR_SIZE];
+ uint32_t bar_arr[ARR_SIZE];
+ uint16_t a[ARR_SIZE];
+ uint16_t b[ARR_SIZE];
+
+ init(a, b);
+ uadd_opt(foo_arr, a, b);
+ uadd_nonopt(bar_arr, a, b);
+ if (memcmp(foo_arr, bar_arr, ARR_SIZE) != 0)
+ return 1;
+ sadd_opt((int32_t*) foo_arr, (int16_t*) a, (int16_t*) b);
+ sadd_nonopt((int32_t*) bar_arr, (int16_t*) a, (int16_t*) b);
+ if (memcmp(foo_arr, bar_arr, ARR_SIZE) != 0)
+ return 1;
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tuaddl\t} 1} } */
+/* { dg-final { scan-assembler-times {\tuaddl2\t} 1} } */
+/* { dg-final { scan-assembler-times {\tsaddl\t} 1} } */
+/* { dg-final { scan-assembler-times {\tsaddl2\t} 1} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-widen-lshift.c b/gcc/testsuite/gcc.target/aarch64/vect-widen-lshift.c
new file mode 100644
index 0000000..48a3719
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-widen-lshift.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -save-temps" } */
+#include <stdint.h>
+#include <string.h>
+
+#pragma GCC target "+nosve"
+
+#define ARR_SIZE 1024
+
+/* Should produce an shll,shll2 pair*/
+void sshll_opt (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] << 16;
+ foo[i+1] = a[i+1] << 16;
+ foo[i+2] = a[i+2] << 16;
+ foo[i+3] = a[i+3] << 16;
+ }
+}
+
+__attribute__((optimize (0)))
+void sshll_nonopt (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] << 16;
+ foo[i+1] = a[i+1] << 16;
+ foo[i+2] = a[i+2] << 16;
+ foo[i+3] = a[i+3] << 16;
+ }
+}
+
+
+void __attribute__((optimize (0)))
+init(uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE;i++)
+ {
+ a[i] = i;
+ b[i] = 2*i;
+ }
+}
+
+int __attribute__((optimize (0)))
+main()
+{
+ uint32_t foo_arr[ARR_SIZE];
+ uint32_t bar_arr[ARR_SIZE];
+ uint16_t a[ARR_SIZE];
+ uint16_t b[ARR_SIZE];
+
+ init(a, b);
+ sshll_opt(foo_arr, a, b);
+ sshll_nonopt(bar_arr, a, b);
+ if (memcmp(foo_arr, bar_arr, ARR_SIZE) != 0)
+ return 1;
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tshll\t} 1} } */
+/* { dg-final { scan-assembler-times {\tshll2\t} 1} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-widen-sub.c b/gcc/testsuite/gcc.target/aarch64/vect-widen-sub.c
new file mode 100644
index 0000000..a2bed63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-widen-sub.c
@@ -0,0 +1,92 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -save-temps" } */
+#include <stdint.h>
+#include <string.h>
+
+#pragma GCC target "+nosve"
+
+#define ARR_SIZE 1024
+
+/* Should produce an usubl */
+void usub_opt (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] - b[i];
+ foo[i+1] = a[i+1] - b[i+1];
+ foo[i+2] = a[i+2] - b[i+2];
+ foo[i+3] = a[i+3] - b[i+3];
+ }
+}
+
+__attribute__((optimize (0)))
+void usub_nonopt (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] - b[i];
+ foo[i+1] = a[i+1] - b[i+1];
+ foo[i+2] = a[i+2] - b[i+2];
+ foo[i+3] = a[i+3] - b[i+3];
+ }
+}
+
+/* Should produce an ssubl */
+void ssub_opt (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] - b[i];
+ foo[i+1] = a[i+1] - b[i+1];
+ foo[i+2] = a[i+2] - b[i+2];
+ foo[i+3] = a[i+3] - b[i+3];
+ }
+}
+
+__attribute__((optimize (0)))
+void ssub_nonopt (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE - 3;i=i+4)
+ {
+ foo[i] = a[i] - b[i];
+ foo[i+1] = a[i+1] - b[i+1];
+ foo[i+2] = a[i+2] - b[i+2];
+ foo[i+3] = a[i+3] - b[i+3];
+ }
+}
+
+
+void __attribute__((optimize (0)))
+init(uint16_t *a, uint16_t *b)
+{
+ for( int i = 0; i < ARR_SIZE;i++)
+ {
+ a[i] = i;
+ b[i] = 2*i;
+ }
+}
+
+int __attribute__((optimize (0)))
+main()
+{
+ uint32_t foo_arr[ARR_SIZE];
+ uint32_t bar_arr[ARR_SIZE];
+ uint16_t a[ARR_SIZE];
+ uint16_t b[ARR_SIZE];
+
+ init(a, b);
+ usub_opt(foo_arr, a, b);
+ usub_nonopt(bar_arr, a, b);
+ if (memcmp(foo_arr, bar_arr, ARR_SIZE) != 0)
+ return 1;
+ ssub_opt((int32_t*) foo_arr, (int16_t*) a, (int16_t*) b);
+ ssub_nonopt((int32_t*) bar_arr, (int16_t*) a, (int16_t*) b);
+ if (memcmp(foo_arr, bar_arr, ARR_SIZE) != 0)
+ return 1;
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tusubl\t} 1} } */
+/* { dg-final { scan-assembler-times {\tusubl2\t} 1} } */
+/* { dg-final { scan-assembler-times {\tssubl\t} 1} } */
+/* { dg-final { scan-assembler-times {\tssubl2\t} 1} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/with-tune-config.c b/gcc/testsuite/gcc.target/aarch64/with-tune-config.c
new file mode 100644
index 0000000..0940e9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/with-tune-config.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { tune_cortex_a76 } } } */
+/* { dg-additional-options " -dA " } */
+
+void foo ()
+{}
+
+/* { dg-final { scan-assembler "//.tune cortex-a76" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/with-tune-march.c b/gcc/testsuite/gcc.target/aarch64/with-tune-march.c
new file mode 100644
index 0000000..61039ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/with-tune-march.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { tune_cortex_a76 } } } */
+/* { dg-additional-options " -dA -march=armv8.6-a " } */
+
+void foo ()
+{}
+
+/* { dg-final { scan-assembler "//.tune cortex-a76" } } */
+/* { dg-final { scan-assembler ".arch armv8.6-a" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/with-tune-mcpu.c b/gcc/testsuite/gcc.target/aarch64/with-tune-mcpu.c
new file mode 100644
index 0000000..4f8267a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/with-tune-mcpu.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { tune_cortex_a76 } } } */
+/* { dg-additional-options " -dA -mcpu=cortex-a73" } */
+
+void foo ()
+{}
+
+/* { dg-final { scan-assembler "//.tune cortex-a73" } } */
+/* { dg-final { scan-assembler ".arch armv8-a" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/with-tune-mtune.c b/gcc/testsuite/gcc.target/aarch64/with-tune-mtune.c
new file mode 100644
index 0000000..60f795a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/with-tune-mtune.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { tune_cortex_a76 } } } */
+/* { dg-additional-options " -dA -mtune=cortex-a73" } */
+
+void foo ()
+{}
+
+/* { dg-final { scan-assembler "//.tune cortex-a73" } } */
diff --git a/gcc/testsuite/gcc.target/arc/loop-3.c b/gcc/testsuite/gcc.target/arc/loop-3.c
index bf7aec9..7f55e2f 100644
--- a/gcc/testsuite/gcc.target/arc/loop-3.c
+++ b/gcc/testsuite/gcc.target/arc/loop-3.c
@@ -23,5 +23,5 @@ void fn1(void)
}
}
-/* { dg-final { scan-assembler "bne_s @.L2" } } */
+/* { dg-final { scan-assembler "bne.*@.L2" } } */
/* { dg-final { scan-assembler-not "add.eq" } } */
diff --git a/gcc/testsuite/gcc.target/arc/pmpyd.c b/gcc/testsuite/gcc.target/arc/pmpyd.c
new file mode 100644
index 0000000..0eb0ff7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pmpyd.c
@@ -0,0 +1,15 @@
+/* { dg-do assemble } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=hs38 -Os -EB" } */
+
+/* This example is found during big-endian build. The compiler is
+ matching mpydu.hi r12,r13,r3 as a predicated instruction, which is
+ incorrect. The error is due to different predicates between the
+ output operand and the first operand of the instruction. */
+unsigned int test(unsigned int x, unsigned long long y)
+{
+ y /= 0x20000000;
+ if (x > 1)
+ y *= x;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/arc/tmac-1.c b/gcc/testsuite/gcc.target/arc/tmac-1.c
index 3fcabf5..5b302ca 100644
--- a/gcc/testsuite/gcc.target/arc/tmac-1.c
+++ b/gcc/testsuite/gcc.target/arc/tmac-1.c
@@ -7,5 +7,5 @@
/* { dg-final { scan-assembler "macd " } } */
/* { dg-final { scan-assembler "macdu" } } */
-/* { dg-final { scan-assembler "mpyd " } } */
+/* { dg-final { scan-assembler "mpyd\\t" } } */
/* { dg-final { scan-assembler "mpydu" } } */
diff --git a/gcc/testsuite/gcc.target/arc/uncached-9.c b/gcc/testsuite/gcc.target/arc/uncached-9.c
new file mode 100644
index 0000000..4caba29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/uncached-9.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include <stdlib.h>
+
+struct uncached_st
+{
+ int value;
+} __attribute__((uncached));
+
+struct cached_st
+{
+ int value;
+};
+
+struct uncached_st g_uncached_st =
+ {
+ .value = 17
+ };
+
+struct cached_st g_cached_st =
+ {
+ .value = 4
+ };
+
+void __attribute__((noinline)) test_struct_copy (void)
+{
+ g_cached_st.value = g_uncached_st.value;
+}
+
+int main (void)
+{
+ test_struct_copy();
+
+ if (g_cached_st.value != g_uncached_st.value)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-hard.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-hard.c
index b3c7fd0..92c1511 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-hard.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-hard.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nodsp -mfloat-abi=hard -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nodsp -mthumb -mfloat-abi=hard -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler "\.arch_extension fp" } } */
/* { dg-final { scan-assembler "\.arch_extension fp.dp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension dsp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-softfp.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-softfp.c
index 3806554..89d778f 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-softfp.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-flag-softfp.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nodsp -mfloat-abi=softfp -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nodsp -mthumb -mfloat-abi=softfp -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler "\.arch_extension fp" } } */
/* { dg-final { scan-assembler "\.arch_extension fp.dp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension dsp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-nofp-flag-softfp.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-nofp-flag-softfp.c
index d22eb4e..405090c 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-nofp-flag-softfp.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nodsp-nofp-flag-softfp.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nodsp+nofp -mfloat-abi=softfp -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nodsp+nofp -mthumb -mfloat-abi=softfp -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler-not "\.arch_extension fp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension fp.dp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension dsp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-hard.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-hard.c
index da1cc25..6a92ded 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-hard.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-hard.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nofp -mfloat-abi=hard -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nofp -mthumb -mfloat-abi=hard -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler "\.arch_extension mve" } } */
/* { dg-final { scan-assembler "\.arch_extension dsp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension fp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-softfp.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-softfp.c
index 0a4fb14..25e80e9 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-softfp.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-flag-softfp.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nofp -mfloat-abi=softfp -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nofp -mthumb -mfloat-abi=softfp -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler "\.arch_extension mve" } } */
/* { dg-final { scan-assembler "\.arch_extension dsp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension fp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-nomve-flag-softfp.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-nomve-flag-softfp.c
index 2ae7f34..38042cc 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-nomve-flag-softfp.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nofp-nomve-flag-softfp.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nomve+nofp -mfloat-abi=softfp -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nomve+nofp -mthumb -mfloat-abi=softfp -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler-not "\.arch_extension mve" } } */
/* { dg-final { scan-assembler-not "\.arch_extension mve.fp" } } */
/* { dg-final { scan-assembler-not "\.arch_extension fp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-hard.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-hard.c
index a6ccd7b..2366e99 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-hard.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-hard.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nomve -mfloat-abi=hard -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nomve -mthumb -mfloat-abi=hard -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler-not "\.arch_extension mve" } } */
/* { dg-final { scan-assembler "\.arch_extension dsp" } } */
/* { dg-final { scan-assembler "\.arch_extension fp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-softfp.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-softfp.c
index 2ad976a..eb2d63d 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-softfp.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve-flag-softfp.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nomve -mfloat-abi=softfp -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nomve -mthumb -mfloat-abi=softfp -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler-not "\.arch_extension mve" } } */
/* { dg-final { scan-assembler "\.arch_extension dsp" } } */
/* { dg-final { scan-assembler "\.arch_extension fp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-hard.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-hard.c
index 40d54b8..e7e57d9 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-hard.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-hard.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nomve.fp -mfloat-abi=hard -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nomve.fp -mthumb -mfloat-abi=hard -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler-not "\.arch_extension mve.fp" } } */
/* { dg-final { scan-assembler "\.arch_extension mve" } } */
/* { dg-final { scan-assembler "\.arch_extension dsp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c
index c726803..42889aa 100644
--- a/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c
+++ b/gcc/testsuite/gcc.target/arm/cortex-m55-nomve.fp-flag-softfp.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
-/* { dg-additional-options "-mcpu=cortex-m55+nomve.fp -mfloat-abi=softfp -mfpu=auto --save-temps" } */
+/* { dg-additional-options "-mcpu=cortex-m55+nomve.fp -mthumb -mfloat-abi=softfp -mfpu=auto --save-temps" } */
/* { dg-final { scan-assembler-not "\.arch_extension mve.fp" } } */
/* { dg-final { scan-assembler "\.arch_extension mve" } } */
/* { dg-final { scan-assembler "\.arch_extension dsp" } } */
diff --git a/gcc/testsuite/gcc.target/arm/data-rel-1.c b/gcc/testsuite/gcc.target/arm/data-rel-1.c
index a09e235..5931b44 100644
--- a/gcc/testsuite/gcc.target/arm/data-rel-1.c
+++ b/gcc/testsuite/gcc.target/arm/data-rel-1.c
@@ -1,5 +1,6 @@
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
/* { dg-options "-fPIC -mno-pic-data-is-text-relative" } */
+/* { dg-require-effective-target fpic } */
/* { dg-final { scan-assembler-not "j-\\(.LPIC" } } */
/* { dg-final { scan-assembler-not "_GLOBAL_OFFSET_TABLE_-\\(.LPIC" } } */
/* { dg-final { scan-assembler "j\\(GOT\\)" } } */
diff --git a/gcc/testsuite/gcc.target/arm/data-rel-2.c b/gcc/testsuite/gcc.target/arm/data-rel-2.c
index 56a54e8..3ed83e2 100644
--- a/gcc/testsuite/gcc.target/arm/data-rel-2.c
+++ b/gcc/testsuite/gcc.target/arm/data-rel-2.c
@@ -1,6 +1,7 @@
/* { dg-skip-if "Not supported in FDPIC" { arm*-*-uclinuxfdpiceabi } "*" "" } */
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
/* { dg-options "-fPIC -mno-pic-data-is-text-relative -mno-single-pic-base" } */
+/* { dg-require-effective-target fpic } */
/* { dg-final { scan-assembler-not "j-\\(.LPIC" } } */
/* { dg-final { scan-assembler "_GLOBAL_OFFSET_TABLE_-\\(.LPIC" } } */
/* { dg-final { scan-assembler "j\\(GOT\\)" } } */
diff --git a/gcc/testsuite/gcc.target/arm/data-rel-3.c b/gcc/testsuite/gcc.target/arm/data-rel-3.c
index 4ce9048..5ab6ba7 100644
--- a/gcc/testsuite/gcc.target/arm/data-rel-3.c
+++ b/gcc/testsuite/gcc.target/arm/data-rel-3.c
@@ -1,6 +1,7 @@
/* { dg-skip-if "Not supported in FDPIC" { arm*-*-uclinuxfdpiceabi } "*" "" } */
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
/* { dg-options "-fPIC -mpic-data-is-text-relative" } */
+/* { dg-require-effective-target fpic } */
/* { dg-final { scan-assembler "j-\\(.LPIC" } } */
/* { dg-final { scan-assembler-not "_GLOBAL_OFFSET_TABLE_-\\(.LPIC" } } */
/* { dg-final { scan-assembler-not "j\\(GOT\\)" } } */
diff --git a/gcc/testsuite/gcc.target/arm/lob2.c b/gcc/testsuite/gcc.target/arm/lob2.c
index fdeb268..d174857 100644
--- a/gcc/testsuite/gcc.target/arm/lob2.c
+++ b/gcc/testsuite/gcc.target/arm/lob2.c
@@ -2,7 +2,7 @@
if a non-inlineable function call takes place inside the loop. */
/* { dg-do compile } */
/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
-/* { dg-options "-march=armv8.1-m.main -mthumb -O3 --save-temps" } */
+/* { dg-options "-march=armv8.1-m.main+fp -mthumb -O3 --save-temps" } */
#include <stdlib.h>
#include "lob.h"
diff --git a/gcc/testsuite/gcc.target/arm/lob3.c b/gcc/testsuite/gcc.target/arm/lob3.c
index 70314ea..f529006 100644
--- a/gcc/testsuite/gcc.target/arm/lob3.c
+++ b/gcc/testsuite/gcc.target/arm/lob3.c
@@ -1,7 +1,7 @@
/* Check that GCC does not generate Armv8.1-M low over head loop instructions
if causes VFP emulation library calls to happen inside the loop. */
/* { dg-do compile } */
-/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" "-mfloat-abi=hard" } } */
/* { dg-options "-march=armv8.1-m.main -mthumb -O3 --save-temps -mfloat-abi=soft" } */
/* { dg-require-effective-target arm_softfloat } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.target/arm/lob4.c b/gcc/testsuite/gcc.target/arm/lob4.c
index 792f352..86c774e 100644
--- a/gcc/testsuite/gcc.target/arm/lob4.c
+++ b/gcc/testsuite/gcc.target/arm/lob4.c
@@ -1,7 +1,7 @@
/* Check that GCC does not generate Armv8.1-M low over head loop instructions
if LR is modified within the loop. */
/* { dg-do compile } */
-/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" "-mfloat-abi=hard" } } */
/* { dg-options "-march=armv8.1-m.main -mthumb -O3 --save-temps -mfloat-abi=soft" } */
/* { dg-require-effective-target arm_softfloat } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.target/arm/lob5.c b/gcc/testsuite/gcc.target/arm/lob5.c
index 1a6adf1..df5383b 100644
--- a/gcc/testsuite/gcc.target/arm/lob5.c
+++ b/gcc/testsuite/gcc.target/arm/lob5.c
@@ -3,7 +3,7 @@
therefore is not optimizable. Outer loops are not optimized. */
/* { dg-do compile } */
/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
-/* { dg-options "-march=armv8.1-m.main -mthumb -O3 --save-temps" } */
+/* { dg-options "-march=armv8.1-m.main+fp -mthumb -O3 --save-temps" } */
#include <stdlib.h>
#include "lob.h"
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr97327.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr97327.c
index 8f6d360..d19bde5 100644
--- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr97327.c
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/pr97327.c
@@ -1,6 +1,6 @@
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
/* { dg-skip-if "Incompatible float ABI" { *-*-* } { "-mfloat-abi=hard" } { "" } } */
-/* { dg-additional-options "-mcpu=cortex-m55 -mfloat-abi=soft -mfpu=auto -Werror" } */
+/* { dg-additional-options "-mcpu=cortex-m55 -mthumb -mfloat-abi=soft -mfpu=auto -Werror" } */
int main ()
{
diff --git a/gcc/testsuite/gcc.target/arm/pr44788.c b/gcc/testsuite/gcc.target/arm/pr44788.c
index e69bbc6..470db32 100644
--- a/gcc/testsuite/gcc.target/arm/pr44788.c
+++ b/gcc/testsuite/gcc.target/arm/pr44788.c
@@ -2,6 +2,7 @@
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
/* { dg-require-effective-target arm_thumb2_ok } */
/* { dg-options "-Os -fno-strict-aliasing -fPIC -mthumb -march=armv7-a -mfpu=vfp3 -mfloat-abi=softfp" } */
+/* { dg-require-effective-target fpic } */
extern void foo (float *);
diff --git a/gcc/testsuite/gcc.target/arm/pr52006.c b/gcc/testsuite/gcc.target/arm/pr52006.c
index 136a39d..f818818 100644
--- a/gcc/testsuite/gcc.target/arm/pr52006.c
+++ b/gcc/testsuite/gcc.target/arm/pr52006.c
@@ -4,6 +4,7 @@
/* { dg-skip-if "no support for hard-float VFP ABI" { arm_thumb1 } { "-march=*" } { "" } } */
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
/* { dg-options "-march=armv7-a+fp -mfloat-abi=hard -O2 -fPIC" } */
+/* { dg-require-effective-target fpic } */
unsigned long a;
static int b;
diff --git a/gcc/testsuite/gcc.target/arm/pr59858.c b/gcc/testsuite/gcc.target/arm/pr59858.c
index bcfd5d5..3360b48 100644
--- a/gcc/testsuite/gcc.target/arm/pr59858.c
+++ b/gcc/testsuite/gcc.target/arm/pr59858.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-march=armv5te -fno-builtin -mfloat-abi=soft -mthumb -fno-stack-protector -Os -fno-tree-loop-optimize -fno-tree-dominator-opts -fPIC -w" } */
+/* { dg-require-effective-target fpic } */
/* { dg-skip-if "Incompatible command line options: -mfloat-abi=soft -mfloat-abi=hard" { *-*-* } { "-mfloat-abi=hard" } { "" } } */
/* { dg-require-effective-target arm_arch_v5te_thumb_ok } */
diff --git a/gcc/testsuite/gcc.target/arm/pr91816.c b/gcc/testsuite/gcc.target/arm/pr91816.c
new file mode 100644
index 0000000..f126914
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr91816.c
@@ -0,0 +1,64 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-additional-options "-mthumb" } */
+/* { dg-timeout-factor 4.0 } */
+
+int printf(const char *, ...);
+
+#define HW0 printf("Hello World!\n");
+#define HW1 HW0 HW0 HW0 HW0 HW0 HW0 HW0 HW0 HW0 HW0
+#define HW2 HW1 HW1 HW1 HW1 HW1 HW1 HW1 HW1 HW1 HW1
+#define HW3 HW2 HW2 HW2 HW2 HW2 HW2 HW2 HW2 HW2 HW2
+#define HW4 HW3 HW3 HW3 HW3 HW3 HW3 HW3 HW3 HW3 HW3
+#define HW5 HW4 HW4 HW4 HW4 HW4 HW4 HW4 HW4 HW4 HW4
+#define HW6 HW5 HW5
+
+__attribute__((noinline,noclone)) void f1 (int a)
+{
+ if (a) { HW0 }
+}
+
+__attribute__((noinline,noclone)) void f2 (int a)
+{
+ if (a) { HW3 }
+}
+
+
+__attribute__((noinline,noclone)) void f3 (int a)
+{
+ if (a) { HW6 }
+}
+
+__attribute__((noinline,noclone)) void f4 (int a)
+{
+ if (a == 1) { HW0 }
+}
+
+__attribute__((noinline,noclone)) void f5 (int a)
+{
+ if (a == 1) { HW3 }
+}
+
+
+__attribute__((noinline,noclone)) void f6 (int a)
+{
+ if (a == 1) { HW6 }
+}
+
+
+int main(void)
+{
+ f1(0);
+ f2(0);
+ f3(0);
+ f4(0);
+ f5(0);
+ f6(0);
+ return 0;
+}
+
+
+/* { dg-final { scan-assembler-times "beq\\t.L\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "beq\\t.Lbcond\[0-9\]" 1 } } */
+/* { dg-final { scan-assembler-times "bne\\t.L\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "bne\\t.Lbcond\[0-9\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr97528.c b/gcc/testsuite/gcc.target/arm/pr97528.c
new file mode 100644
index 0000000..6cc59f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr97528.c
@@ -0,0 +1,28 @@
+/* PR target/97528 */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-O1" } */
+/* { dg-add-options arm_neon } */
+
+#include <arm_neon.h>
+
+typedef __simd64_int16_t T;
+typedef __simd64_uint16_t U;
+unsigned short c;
+int d;
+U e;
+
+void
+foo (void)
+{
+ unsigned short *dst = &c;
+ int g = d, b = 4;
+ U dc = e;
+ for (int h = 0; h < b; h++)
+ {
+ unsigned short *i = dst;
+ U j = dc;
+ vst1_s16 ((int16_t *) i, (T) j);
+ dst += g;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr97872.c b/gcc/testsuite/gcc.target/arm/pr97872.c
new file mode 100644
index 0000000..eeb4dd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr97872.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-O3" } */
+/* { dg-add-options arm_neon } */
+
+#include <arm_neon.h>
+
+uint8x8_t f1(int8x8_t a, int8x8_t b) {
+ return a < b;
+}
+
+/* { dg-final { scan-assembler-not "vbsl" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m0.c b/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m0.c
new file mode 100644
index 0000000..bd6f4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m0.c
@@ -0,0 +1,176 @@
+/* { dg-do compile } */
+/* { dg-skip-if "skip override" { *-*-* } { "-mfloat-abi=hard" } { "" } } */
+/* { dg-options "-mpure-code -mcpu=cortex-m0 -march=armv6s-m -mthumb -mfloat-abi=soft" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Does not use thumb1_gen_const_int.
+** test_0:
+** ...
+** movs r[0-3], #0
+** ...
+*/
+int
+test_0 ()
+{
+ return 0;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_128:
+** ...
+** movs r[0-3], #128
+** ...
+*/
+int
+test_128 ()
+{
+ return 128;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_264:
+** ...
+** movs r[0-3], #132
+** lsls r[0-3], r[0-3], #1
+** ...
+*/
+int
+test_264 ()
+{
+ return 264;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_510:
+** ...
+** movs r[0-3], #255
+** lsls r[0-3], r[0-3], #1
+** ...
+*/
+int
+test_510 ()
+{
+ return 510;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_512:
+** ...
+** movs r[0-3], #128
+** lsls r[0-3], r[0-3], #2
+** ...
+*/
+int
+test_512 ()
+{
+ return 512;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_764:
+** ...
+** movs r[0-3], #191
+** lsls r[0-3], r[0-3], #2
+** ...
+*/
+int
+test_764 ()
+{
+ return 764;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_65536:
+** ...
+** movs r[0-3], #128
+** lsls r[0-3], r[0-3], #9
+** ...
+*/
+int
+test_65536 ()
+{
+ return 65536;
+}
+
+/*
+** test_0x123456:
+** ...
+** movs r[0-3], #18
+** lsls r[0-3], r[0-3], #8
+** adds r[0-3], r[0-3], #52
+** lsls r[0-3], r[0-3], #8
+** adds r[0-3], r[0-3], #86
+** ...
+*/
+int
+test_0x123456 ()
+{
+ return 0x123456;
+}
+
+/*
+** test_0x1123456:
+** ...
+** movs r[0-3], #137
+** lsls r[0-3], r[0-3], #8
+** adds r[0-3], r[0-3], #26
+** lsls r[0-3], r[0-3], #8
+** adds r[0-3], r[0-3], #43
+** lsls r[0-3], r[0-3], #1
+** ...
+*/
+int
+test_0x1123456 ()
+{
+ return 0x1123456;
+}
+
+/* With -Os, we generate:
+ movs r0, #16
+ lsls r0, r0, r0
+ With the other optimization levels, we generate:
+ movs r0, #16
+ lsls r0, r0, #16
+ hence the two alternatives. */
+/*
+** test_0x1000010:
+** ...
+** movs r[0-3], #16
+** lsls r[0-3], r[0-3], (#16|r[0-3])
+** adds r[0-3], r[0-3], #1
+** lsls r[0-3], r[0-3], #4
+** ...
+*/
+int
+test_0x1000010 ()
+{
+ return 0x1000010;
+}
+
+/*
+** test_0x1000011:
+** ...
+** movs r[0-3], #1
+** lsls r[0-3], r[0-3], #24
+** adds r[0-3], r[0-3], #17
+** ...
+*/
+int
+test_0x1000011 ()
+{
+ return 0x1000011;
+}
+
+/*
+** test_m8192:
+** ...
+** movs r[0-3], #1
+** lsls r[0-3], r[0-3], #13
+** rsbs r[0-3], r[0-3], #0
+** ...
+*/
+int
+test_m8192 ()
+{
+ return -8192;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m23.c b/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m23.c
new file mode 100644
index 0000000..9537012
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool-m23.c
@@ -0,0 +1,172 @@
+/* { dg-do compile } */
+/* { dg-skip-if "skip override" { *-*-* } { "-mfloat-abi=hard" } { "" } } */
+/* { dg-options "-mpure-code -mcpu=cortex-m23 -march=armv8-m.base -mthumb -mfloat-abi=soft" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** testi:
+** ...
+** movs r[0-3], #1
+** lsls r[0-3], #13
+** rsbs r[0-3], #0
+** ...
+*/
+int
+testi (int *p)
+{
+ if (*p > 0x12345678)
+ return *p-8192;
+ else
+ return *p+8192;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_0:
+** ...
+** movs r[0-3], #0
+** ...
+*/
+int
+test_0 ()
+{
+ return 0;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_128:
+** ...
+** movs r[0-3], #128
+** ...
+*/
+int
+test_128 ()
+{
+ return 128;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_264:
+** ...
+** movw r[0-3], #264
+** ...
+*/
+int
+test_264 ()
+{
+ return 264;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_510:
+** ...
+** movw r[0-3], #510
+** ...
+*/
+int
+test_510 ()
+{
+ return 510;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_512:
+** ...
+** movw r[0-3], #512
+** ...
+*/
+int
+test_512 ()
+{
+ return 512;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_764:
+** ...
+** movw r[0-3], #764
+** ...
+*/
+int
+test_764 ()
+{
+ return 764;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_65536:
+** ...
+** movs r[0-3], #128
+** lsls r[0-3], r[0-3], #9
+** ...
+*/
+int
+test_65536 ()
+{
+ return 65536;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_0x123456:
+** ...
+** movw r[0-3], #13398
+** movt r[0-3], 18
+** ...
+*/
+int
+test_0x123456 ()
+{
+ return 0x123456;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_0x1123456:
+** ...
+** movw r[0-3], #13398
+** movt r[0-3], 274
+** ...
+*/
+int
+test_0x1123456 ()
+{
+ return 0x1123456;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_0x1000010:
+** ...
+** movs r[0-3], #16
+** movt r[0-3], 256
+** ...
+*/
+int
+test_0x1000010 ()
+{
+ return 0x1000010;
+}
+
+/* Does not use thumb1_gen_const_int.
+** test_0x1000011:
+** ...
+** movs r[0-3], #17
+** movt r[0-3], 256
+** ...
+*/
+int
+test_0x1000011 ()
+{
+ return 0x1000011;
+}
+
+/*
+** test_m8192:
+** ...
+** movs r[0-3], #1
+** lsls r[0-3], #13
+** rsbs r[0-3], #0
+** ...
+*/
+int
+test_m8192 ()
+{
+ return -8192;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pure-code/pr96767.c b/gcc/testsuite/gcc.target/arm/pure-code/pr96767.c
new file mode 100644
index 0000000..cb3ee68
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pure-code/pr96767.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mpure-code" } */
+
+int x;
+int f1 (void) { return x; }
+
+/* We expect only one indirect load like ldr r3, [r3]. In some
+ configurations there is an additional ldr rX, [sp], #4 which is not
+ related to what we check here, so make sure not to match it. */
+/* { dg-final { scan-assembler-times "ldr\tr\[0-9\]+, \\\[r\[0-9\]+\\\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pure-code/pr96770.c b/gcc/testsuite/gcc.target/arm/pure-code/pr96770.c
new file mode 100644
index 0000000..a43d71f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pure-code/pr96770.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-mpure-code" } */
+
+int arr[1000];
+int *f4 (void) { return &arr[1]; }
+
+/* For cortex-m0 (thumb-1/v6m), we generate 4 movs with upper/lower:#arr+4. */
+/* { dg-final { scan-assembler-times "\\+4" 4 { target { { ! arm_thumb1_movt_ok } && { ! arm_thumb2_ok } } } } } */
+
+/* For cortex-m with movt/movw (thumb-1/v8m.base or thumb-2), we
+ generate a movt/movw pair with upper/lower:#arr+4. */
+/* { dg-final { scan-assembler-times "\\+4" 2 { target { arm_thumb1_movt_ok || arm_thumb2_ok } } } } */
+
+int *f5 (void) { return &arr[80]; }
+
+/* For cortex-m0 (thumb-1/v6m), we generate 1 ldr from rodata pointer to arr+320. */
+/* { dg-final { scan-assembler-times "\\+320" 1 { target { { ! arm_thumb1_movt_ok } && { ! arm_thumb2_ok } } } } } */
+
+/* For cortex-m with movt/movw (thumb-1/v8m.base or thumb-2), we
+ generate a movt/movw pair with upper/lower:arr+320. */
+/* { dg-final { scan-assembler-times "\\+320" 2 { target { arm_thumb1_movt_ok || arm_thumb2_ok } } } } */
diff --git a/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
index 9f089ee..9c532f3 100644
--- a/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
+++ b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
@@ -1,15 +1,16 @@
/* { dg-do compile } */
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
/* { dg-options "-g -fPIC" } */
+/* { dg-require-effective-target fpic } */
void *v;
void a (void *x) { }
void b (void) { }
- /* line 8. */
-int /* line 9. */
-main (int argc) /* line 10. */
-{ /* line 11. */
- if (argc == 12345) /* line 12. */
+ /* line 9. */
+int /* line 10. */
+main (int argc) /* line 11. */
+{ /* line 12. */
+ if (argc == 12345) /* line 13. */
{
a (v);
return 1;
@@ -19,12 +20,12 @@ main (int argc) /* line 10. */
return 0;
}
-/* { dg-final { scan-assembler-not "\.loc 1 8 \[0-9\]\+" } } */
/* { dg-final { scan-assembler-not "\.loc 1 9 \[0-9\]\+" } } */
/* { dg-final { scan-assembler-not "\.loc 1 10 \[0-9\]\+" } } */
+/* { dg-final { scan-assembler-not "\.loc 1 11 \[0-9\]\+" } } */
/* The loc at the start of the prologue. */
-/* { dg-final { scan-assembler-times "\.loc 1 11 \[0-9\]\+" 1 } } */
+/* { dg-final { scan-assembler-times "\.loc 1 12 \[0-9\]\+" 1 } } */
/* The loc at the end of the prologue, with the first user line. */
-/* { dg-final { scan-assembler-times "\.loc 1 12 \[0-9\]\+" 1 } } */
+/* { dg-final { scan-assembler-times "\.loc 1 13 \[0-9\]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/bf16_vldn_1.c b/gcc/testsuite/gcc.target/arm/simd/bf16_vldn_1.c
index 222e7af..663e769 100644
--- a/gcc/testsuite/gcc.target/arm/simd/bf16_vldn_1.c
+++ b/gcc/testsuite/gcc.target/arm/simd/bf16_vldn_1.c
@@ -10,8 +10,8 @@
/*
**test_vld2_bf16:
** ...
-** vld2.16 {d0-d1}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+-d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x4x2_t
test_vld2_bf16 (bfloat16_t * ptr)
@@ -22,8 +22,8 @@ test_vld2_bf16 (bfloat16_t * ptr)
/*
**test_vld2q_bf16:
** ...
-** vld2.16 {d0-d3}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+-d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x8x2_t
test_vld2q_bf16 (bfloat16_t * ptr)
@@ -34,8 +34,8 @@ test_vld2q_bf16 (bfloat16_t * ptr)
/*
**test_vld2_dup_bf16:
** ...
-** vld2.16 {d0\[\], d1\[\]}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+\[\], d[0-9]+\[\]}, \[r[0-9]+\]
+** ...
*/
bfloat16x4x2_t
test_vld2_dup_bf16 (bfloat16_t * ptr)
@@ -46,8 +46,8 @@ test_vld2_dup_bf16 (bfloat16_t * ptr)
/*
**test_vld2q_dup_bf16:
** ...
-** vld2.16 {d0, d1, d2, d3}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+, d[0-9]+, d[0-9]+, d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x8x2_t
test_vld2q_dup_bf16 (bfloat16_t * ptr)
@@ -58,8 +58,8 @@ test_vld2q_dup_bf16 (bfloat16_t * ptr)
/*
**test_vld3_bf16:
** ...
-** vld3.16 {d0-d2}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+-d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x4x3_t
test_vld3_bf16 (bfloat16_t * ptr)
@@ -70,8 +70,8 @@ test_vld3_bf16 (bfloat16_t * ptr)
/*
**test_vld3q_bf16:
** ...
-** vld3.16 {d1, d3, d5}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+, d[0-9]+, d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x8x3_t
test_vld3q_bf16 (bfloat16_t * ptr)
@@ -82,8 +82,8 @@ test_vld3q_bf16 (bfloat16_t * ptr)
/*
**test_vld3_dup_bf16:
** ...
-** vld3.16 {d0\[\], d1\[\], d2\[\]}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+\[\], d[0-9]+\[\], d[0-9]+\[\]}, \[r[0-9]+\]
+** ...
*/
bfloat16x4x3_t
test_vld3_dup_bf16 (bfloat16_t * ptr)
@@ -94,8 +94,8 @@ test_vld3_dup_bf16 (bfloat16_t * ptr)
/*
**test_vld3q_dup_bf16:
** ...
-** vld3.16 {d0\[\], d1\[\], d2\[\]}, \[r0\]
-** bx lr
+** vld[0-9]+.16 {d[0-9]+\[\], d[0-9]+\[\], d[0-9]+\[\]}, \[r[0-9]+\]
+** ...
*/
bfloat16x8x3_t
test_vld3q_dup_bf16 (bfloat16_t * ptr)
@@ -106,8 +106,8 @@ test_vld3q_dup_bf16 (bfloat16_t * ptr)
/*
**test_vld4_bf16:
** ...
-** vld4.16 {d0-d3}, \[r0\]
-** bx lr
+** vld4.16 {d[0-9]+-d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x4x4_t
test_vld4_bf16 (bfloat16_t * ptr)
@@ -118,8 +118,8 @@ test_vld4_bf16 (bfloat16_t * ptr)
/*
**test_vld4q_bf16:
** ...
-** vld4.16 {d1, d3, d5, d7}, \[r0\]
-** bx lr
+** vld4.16 {d[0-9]+, d[0-9]+, d[0-9]+, d[0-9]+}, \[r[0-9]+\]
+** ...
*/
bfloat16x8x4_t
test_vld4q_bf16 (bfloat16_t * ptr)
@@ -130,8 +130,8 @@ test_vld4q_bf16 (bfloat16_t * ptr)
/*
**test_vld4_dup_bf16:
** ...
-** vld4.16 {d0\[\], d1\[\], d2\[\], d3\[\]}, \[r0\]
-** bx lr
+** vld4.16 {d[0-9]+\[\], d[0-9]+\[\], d[0-9]+\[\], d[0-9]+\[\]}, \[r[0-9]+\]
+** ...
*/
bfloat16x4x4_t
test_vld4_dup_bf16 (bfloat16_t * ptr)
@@ -142,8 +142,8 @@ test_vld4_dup_bf16 (bfloat16_t * ptr)
/*
**test_vld4q_dup_bf16:
** ...
-** vld4.16 {d0\[\], d1\[\], d2\[\], d3\[\]}, \[r0\]
-** bx lr
+** vld4.16 {d[0-9]+\[\], d[0-9]+\[\], d[0-9]+\[\], d[0-9]+\[\]}, \[r[0-9]+\]
+** ...
*/
bfloat16x8x4_t
test_vld4q_dup_bf16 (bfloat16_t * ptr)
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vand.c b/gcc/testsuite/gcc.target/arm/simd/mve-vand.c
new file mode 100644
index 0000000..26247dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vand.c
@@ -0,0 +1,63 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP b[i]; \
+ } \
+}
+
+#define FUNC_IMM(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP 1; \
+ } \
+}
+
+/* 64-bit vectors. */
+FUNC(s, int, 32, 2, &, vand)
+FUNC(u, uint, 32, 2, &, vand)
+FUNC(s, int, 16, 4, &, vand)
+FUNC(u, uint, 16, 4, &, vand)
+FUNC(s, int, 8, 8, &, vand)
+FUNC(u, uint, 8, 8, &, vand)
+
+/* 128-bit vectors. */
+FUNC(s, int, 32, 4, &, vand)
+FUNC(u, uint, 32, 4, &, vand)
+FUNC(s, int, 16, 8, &, vand)
+FUNC(u, uint, 16, 8, &, vand)
+FUNC(s, int, 8, 16, &, vand)
+FUNC(u, uint, 8, 16, &, vand)
+
+/* 64-bit vectors. */
+FUNC_IMM(s, int, 32, 2, &, vandimm)
+FUNC_IMM(u, uint, 32, 2, &, vandimm)
+FUNC_IMM(s, int, 16, 4, &, vandimm)
+FUNC_IMM(u, uint, 16, 4, &, vandimm)
+FUNC_IMM(s, int, 8, 8, &, vandimm)
+FUNC_IMM(u, uint, 8, 8, &, vandimm)
+
+/* 128-bit vectors. */
+FUNC_IMM(s, int, 32, 4, &, vandimm)
+FUNC_IMM(u, uint, 32, 4, &, vandimm)
+FUNC_IMM(s, int, 16, 8, &, vandimm)
+FUNC_IMM(u, uint, 16, 8, &, vandimm)
+FUNC_IMM(s, int, 8, 16, &, vandimm)
+FUNC_IMM(u, uint, 8, 16, &, vandimm)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+ functions above. */
+/* Although float16 and float32 types are supported at assembly level,
+ we cannot test them with the '&' operator, so we check only the
+ integer variants. */
+/* For some reason, we do not generate the immediate version, we still
+ use vldr to load the vector of immediates. */
+/* { dg-final { scan-assembler-times {vand\tq[0-9]+, q[0-9]+, q[0-9]+} 12 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vbic.c b/gcc/testsuite/gcc.target/arm/simd/mve-vbic.c
new file mode 100644
index 0000000..c9a64c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vbic.c
@@ -0,0 +1,65 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP b[i]; \
+ } \
+}
+
+#define FUNC_IMM(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP 1; \
+ } \
+}
+
+/* 64-bit vectors. */
+FUNC(s, int, 32, 2, & ~ , vbic)
+FUNC(u, uint, 32, 2, & ~ , vbic)
+FUNC(s, int, 16, 4, & ~ , vbic)
+FUNC(u, uint, 16, 4, & ~ , vbic)
+FUNC(s, int, 8, 8, & ~ , vbic)
+FUNC(u, uint, 8, 8, & ~ , vbic)
+
+/* 128-bit vectors. */
+FUNC(s, int, 32, 4, & ~ , vbic)
+FUNC(u, uint, 32, 4, & ~ , vbic)
+FUNC(s, int, 16, 8, & ~ , vbic)
+FUNC(u, uint, 16, 8, & ~ , vbic)
+FUNC(s, int, 8, 16, & ~ , vbic)
+FUNC(u, uint, 8, 16, & ~ , vbic)
+
+/* 64-bit vectors. */
+FUNC_IMM(s, int, 32, 2, & ~, vbicimm)
+FUNC_IMM(u, uint, 32, 2, & ~, vbicimm)
+FUNC_IMM(s, int, 16, 4, & ~, vbicimm)
+FUNC_IMM(u, uint, 16, 4, & ~, vbicimm)
+FUNC_IMM(s, int, 8, 8, & ~, vbicimm)
+FUNC_IMM(u, uint, 8, 8, & ~, vbicimm)
+
+/* 128-bit vectors. */
+FUNC_IMM(s, int, 32, 4, & ~, vbicimm)
+FUNC_IMM(u, uint, 32, 4, & ~, vbicimm)
+FUNC_IMM(s, int, 16, 8, & ~, vbicimm)
+FUNC_IMM(u, uint, 16, 8, & ~, vbicimm)
+FUNC_IMM(s, int, 8, 16, & ~, vbicimm)
+FUNC_IMM(u, uint, 8, 16, & ~, vbicimm)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+ functions above. */
+/* We emit vand.i[16|32] qX, #XX for the first four versions of the
+ 128-bit vector vbicimm tests. */
+/* For some reason, we do not generate the immediate version for
+ int8x16 and uint8x16, we still use vldr to load the vector of
+ immediates. */
+/* { dg-final { scan-assembler-times {vbic\tq[0-9]+, q[0-9]+, q[0-9]+} 6 } } */
+/* { dg-final { scan-assembler-times {vand.i[0-9]+\tq[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {vand\tq[0-9]+, q[0-9]+, q[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-veor.c b/gcc/testsuite/gcc.target/arm/simd/mve-veor.c
new file mode 100644
index 0000000..321961f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-veor.c
@@ -0,0 +1,61 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP b[i]; \
+ } \
+}
+
+#define FUNC_IMM(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP 1; \
+ } \
+}
+
+/* 64-bit vectors. */
+FUNC(s, int, 32, 2, ^, veor)
+FUNC(u, uint, 32, 2, ^, veor)
+FUNC(s, int, 16, 4, ^, veor)
+FUNC(u, uint, 16, 4, ^, veor)
+FUNC(s, int, 8, 8, ^, veor)
+FUNC(u, uint, 8, 8, ^, veor)
+
+/* 128-bit vectors. */
+FUNC(s, int, 32, 4, ^, veor)
+FUNC(u, uint, 32, 4, ^, veor)
+FUNC(s, int, 16, 8, ^, veor)
+FUNC(u, uint, 16, 8, ^, veor)
+FUNC(s, int, 8, 16, ^, veor)
+FUNC(u, uint, 8, 16, ^, veor)
+
+/* 64-bit vectors. */
+FUNC_IMM(s, int, 32, 2, ^, veorimm)
+FUNC_IMM(u, uint, 32, 2, ^, veorimm)
+FUNC_IMM(s, int, 16, 4, ^, veorimm)
+FUNC_IMM(u, uint, 16, 4, ^, veorimm)
+FUNC_IMM(s, int, 8, 8, ^, veorimm)
+FUNC_IMM(u, uint, 8, 8, ^, veorimm)
+
+/* 128-bit vectors. */
+FUNC_IMM(s, int, 32, 4, ^, veorimm)
+FUNC_IMM(u, uint, 32, 4, ^, veorimm)
+FUNC_IMM(s, int, 16, 8, ^, veorimm)
+FUNC_IMM(u, uint, 16, 8, ^, veorimm)
+FUNC_IMM(s, int, 8, 16, ^, veorimm)
+FUNC_IMM(u, uint, 8, 16, ^, veorimm)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+ functions above. */
+/* Although float16 and float32 types are supported at assembly level,
+ we cannot test them with the '^' operator, so we check only the
+ integer variants. */
+/* { dg-final { scan-assembler-times {veor\tq[0-9]+, q[0-9]+, q[0-9]+} 12 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vmvn.c b/gcc/testsuite/gcc.target/arm/simd/mve-vmvn.c
new file mode 100644
index 0000000..73e897a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vmvn.c
@@ -0,0 +1,35 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = OP a[i]; \
+ } \
+}
+
+/* vmnvq supports only 16-bit and 32-bit elements. */
+/* 64-bit vectors. */
+FUNC(s, int, 32, 2, ~, vmvn)
+FUNC(u, uint, 32, 2, ~, vmvn)
+FUNC(s, int, 16, 4, ~, vmvn)
+FUNC(u, uint, 16, 4, ~, vmvn)
+FUNC(s, int, 8, 8, ~, vmvn)
+FUNC(u, uint, 8, 8, ~, vmvn)
+
+/* 128-bit vectors. */
+FUNC(s, int, 32, 4, ~, vmvn)
+FUNC(u, uint, 32, 4, ~, vmvn)
+FUNC(s, int, 16, 8, ~, vmvn)
+FUNC(u, uint, 16, 8, ~, vmvn)
+FUNC(s, int, 8, 16, ~, vmvn)
+FUNC(u, uint, 8, 16, ~, vmvn)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+ functions above. */
+/* { dg-final { scan-assembler-times {vmvn\tq[0-9]+, q[0-9]+} 6 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vneg.c b/gcc/testsuite/gcc.target/arm/simd/mve-vneg.c
new file mode 100644
index 0000000..afd0d60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vneg.c
@@ -0,0 +1,49 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+#include <arm_mve.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = OP a[i]; \
+ } \
+}
+
+#define FUNC_FLOAT(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE * __restrict__ dest, TYPE *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = OP a[i]; \
+ } \
+}
+
+/* vmnvq supports only 16-bit and 32-bit elements. */
+/* 64-bit vectors. */
+FUNC(s, int, 32, 2, -, vneg)
+FUNC(u, uint, 32, 2, -, vneg)
+FUNC(s, int, 16, 4, -, vneg)
+FUNC(u, uint, 16, 4, -, vneg)
+FUNC(s, int, 8, 8, -, vneg)
+FUNC(u, uint, 8, 8, -, vneg)
+FUNC_FLOAT(f, float, 32, 2, -, vneg)
+FUNC(f, float, 16, 4, -, vneg)
+
+/* 128-bit vectors. */
+FUNC(s, int, 32, 4, -, vneg)
+FUNC(u, uint, 32, 4, -, vneg)
+FUNC(s, int, 16, 8, -, vneg)
+FUNC(u, uint, 16, 8, -, vneg)
+FUNC(s, int, 8, 16, -, vneg)
+FUNC(u, uint, 8, 16, -, vneg)
+FUNC_FLOAT(f, float, 32, 4, -, vneg)
+FUNC(f, float, 16, 8, -, vneg)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+ functions above. */
+/* { dg-final { scan-assembler-times {vneg.s[0-9]+ q[0-9]+, q[0-9]+} 6 } } */
+/* { dg-final { scan-assembler-times {vneg.f[0-9]+ q[0-9]+, q[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vorr.c b/gcc/testsuite/gcc.target/arm/simd/mve-vorr.c
new file mode 100644
index 0000000..b1190f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vorr.c
@@ -0,0 +1,64 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP b[i]; \
+ } \
+}
+
+#define FUNC_IMM(SIGN, TYPE, BITS, NB, OP, NAME) \
+ void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a) { \
+ int i; \
+ for (i=0; i<NB; i++) { \
+ dest[i] = a[i] OP 1; \
+ } \
+}
+
+/* 64-bit vectors. */
+FUNC(s, int, 32, 2, |, vorr)
+FUNC(u, uint, 32, 2, |, vorr)
+FUNC(s, int, 16, 4, |, vorr)
+FUNC(u, uint, 16, 4, |, vorr)
+FUNC(s, int, 8, 8, |, vorr)
+FUNC(u, uint, 8, 8, |, vorr)
+
+/* 128-bit vectors. */
+FUNC(s, int, 32, 4, |, vorr)
+FUNC(u, uint, 32, 4, |, vorr)
+FUNC(s, int, 16, 8, |, vorr)
+FUNC(u, uint, 16, 8, |, vorr)
+FUNC(s, int, 8, 16, |, vorr)
+FUNC(u, uint, 8, 16, |, vorr)
+
+/* 64-bit vectors. */
+FUNC_IMM(s, int, 32, 2, |, vorrimm)
+FUNC_IMM(u, uint, 32, 2, |, vorrimm)
+FUNC_IMM(s, int, 16, 4, |, vorrimm)
+FUNC_IMM(u, uint, 16, 4, |, vorrimm)
+FUNC_IMM(s, int, 8, 8, |, vorrimm)
+FUNC_IMM(u, uint, 8, 8, |, vorrimm)
+
+/* 128-bit vectors. */
+FUNC_IMM(s, int, 32, 4, |, vorrimm)
+FUNC_IMM(u, uint, 32, 4, |, vorrimm)
+FUNC_IMM(s, int, 16, 8, |, vorrimm)
+FUNC_IMM(u, uint, 16, 8, |, vorrimm)
+FUNC_IMM(s, int, 8, 16, |, vorrimm)
+FUNC_IMM(u, uint, 8, 16, |, vorrimm)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+ functions above. */
+/* Although float16 and float32 types are supported at assembly level,
+ we cannot test them with the '|' operator, so we check only the
+ integer variants. */
+/* We emit vorr.i[16|32] qX, #1 for the first four versions of the
+ 128-bit vector vorrimm tests. */
+/* { dg-final { scan-assembler-times {vorr\tq[0-9]+, q[0-9]+, q[0-9]+} 8 } } */
+/* { dg-final { scan-assembler-times {vorr.i[0-9]+\tq[0-9]+} 4 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c b/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c
index cb3ef3a..842e5c6 100644
--- a/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c
@@ -1,7 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
/* { dg-add-options arm_v8_1m_mve_fp } */
-/* { dg -additional-options "-O3 -funsafe-math-optimizations" } */
/* { dg-additional-options "-O3" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/arm/simd/vld1_bf16_1.c b/gcc/testsuite/gcc.target/arm/simd/vld1_bf16_1.c
new file mode 100644
index 0000000..b6b00dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vld1_bf16_1.c
@@ -0,0 +1,29 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-save-temps -O2 -mfloat-abi=hard" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon.h"
+
+/*
+**test_vld1_bf16:
+** vld1.16 {d0}, \[r0\]
+** bx lr
+*/
+bfloat16x4_t
+test_vld1_bf16 (bfloat16_t const *p)
+{
+ return vld1_bf16 (p);
+}
+
+/*
+**test_vld1q_bf16:
+** vld1.16 {d0-d1}, \[r0\]
+** bx lr
+*/
+bfloat16x8_t
+test_vld1q_bf16 (bfloat16_t const *p)
+{
+ return vld1q_bf16 (p);
+}
diff --git a/gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_1.c b/gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_1.c
new file mode 100644
index 0000000..94fb38f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_1.c
@@ -0,0 +1,22 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-require-effective-target arm_hard_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-O3 --save-temps -mfloat-abi=hard" } */
+
+#include "arm_neon.h"
+
+bfloat16x4_t
+test_vld1_lane_bf16 (bfloat16_t *a, bfloat16x4_t b)
+{
+ return vld1_lane_bf16 (a, b, 1);
+}
+
+bfloat16x8_t
+test_vld1q_lane_bf16 (bfloat16_t *a, bfloat16x8_t b)
+{
+ return vld1q_lane_bf16 (a, b, 2);
+}
+
+/* { dg-final { scan-assembler "vld1.16\t{d0\\\[1\\\]}, \\\[r0\\\]" } } */
+/* { dg-final { scan-assembler "vld1.16\t{d0\\\[2\\\]}, \\\[r0\\\]" } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_indices_1.c
new file mode 100644
index 0000000..d9af512
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vld1_lane_bf16_indices_1.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-require-effective-target arm_hard_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-mfloat-abi=hard" } */
+
+#include "arm_neon.h"
+
+bfloat16x4_t
+test_vld1_lane_bf16 (bfloat16_t *a, bfloat16x4_t b)
+{
+ bfloat16x4_t res;
+ res = vld1_lane_bf16 (a, b, -1);
+ res = vld1_lane_bf16 (a, b, 4);
+ return res;
+}
+
+/* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+/* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vld1q_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/arm/simd/vld1q_lane_bf16_indices_1.c
new file mode 100644
index 0000000..a73184c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vld1q_lane_bf16_indices_1.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-require-effective-target arm_hard_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-mfloat-abi=hard" } */
+
+#include "arm_neon.h"
+
+bfloat16x8_t
+test_vld1q_lane_bf16 (bfloat16_t *a, bfloat16x8_t b)
+{
+ bfloat16x8_t res;
+ res = vld1q_lane_bf16 (a, b, -1);
+ res = vld1q_lane_bf16 (a, b, 8);
+ return res;
+}
+
+/* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+/* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vldn_lane_bf16_1.c b/gcc/testsuite/gcc.target/arm/simd/vldn_lane_bf16_1.c
new file mode 100644
index 0000000..b235b1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vldn_lane_bf16_1.c
@@ -0,0 +1,79 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-save-temps -O2 -mfloat-abi=hard" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon.h"
+
+/*
+**test_vld2_lane_bf16:
+** ...
+** vld2.16 {d[0-9]+\[2\], d[0-9]+\[2\]}, \[r[0-9]+\]
+** ...
+*/
+bfloat16x4x2_t
+test_vld2_lane_bf16 (const bfloat16_t *a, bfloat16x4x2_t b)
+{
+ return vld2_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vld2q_lane_bf16:
+** ...
+** vld2.16 {d[0-9]+\[2\], d[0-9]+\[2\]}, \[r[0-9]+\]
+** ...
+*/
+bfloat16x8x2_t
+test_vld2q_lane_bf16 (const bfloat16_t *a, bfloat16x8x2_t b)
+{
+ return vld2q_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vld3_lane_bf16:
+** ...
+** vld3.16 {d[0-9]+\[2\], d[0-9]+\[2\], d[0-9]+\[2\]}, \[r[0-9]+\]
+** ...
+*/
+bfloat16x4x3_t
+test_vld3_lane_bf16 (const bfloat16_t *a, bfloat16x4x3_t b)
+{
+ return vld3_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vld3q_lane_bf16:
+** ...
+** vld3.16 {d[0-9]+\[2\], d[0-9]+\[2\], d[0-9]+\[2\]}, \[r0\]
+** ...
+*/
+bfloat16x8x3_t
+test_vld3q_lane_bf16 (const bfloat16_t *a, bfloat16x8x3_t b)
+{
+ return vld3q_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vld4_lane_bf16:
+** ...
+** vld4.16 {d[0-9]+\[2\], d[0-9]+\[2\], d[0-9]+\[2\], d[0-9]+\[2\]}, \[r0\]
+** ...
+*/
+bfloat16x4x4_t
+test_vld4_lane_bf16 (const bfloat16_t *a, bfloat16x4x4_t b)
+{
+ return vld4_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vld4q_lane_bf16:
+** ...
+** vld4.16 {d[0-9]+\[2\], d[0-9]+\[2\], d[0-9]+\[2\], d[0-9]+\[2\]}, \[r0\]
+** ...
+*/
+bfloat16x8x4_t
+test_vld4q_lane_bf16 (const bfloat16_t *a, bfloat16x8x4_t b)
+{
+ return vld4q_lane_bf16 (a, b, 2);
+}
diff --git a/gcc/testsuite/gcc.target/arm/simd/vmmla_1.c b/gcc/testsuite/gcc.target/arm/simd/vmmla_1.c
index fa512d9..aeb4a35 100644
--- a/gcc/testsuite/gcc.target/arm/simd/vmmla_1.c
+++ b/gcc/testsuite/gcc.target/arm/simd/vmmla_1.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-require-effective-target arm_v8_2a_i8mm_ok } */
-/* { dg-options "-save-temps -O2 -march=armv8.2-a+i8mm" } */
+/* { dg-options "-save-temps -O2 -march=armv8.2-a+i8mm -mfloat-abi=hard" } */
#include "arm_neon.h"
diff --git a/gcc/testsuite/gcc.target/arm/simd/vst1_bf16_1.c b/gcc/testsuite/gcc.target/arm/simd/vst1_bf16_1.c
new file mode 100644
index 0000000..06fb58e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vst1_bf16_1.c
@@ -0,0 +1,29 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-save-temps -O2 -mfloat-abi=hard" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon.h"
+
+/*
+**test_vst1_bf16:
+** vst1.16 {d0}, \[r0\]
+** bx lr
+*/
+void
+test_vst1_bf16 (bfloat16_t *a, bfloat16x4_t b)
+{
+ vst1_bf16 (a, b);
+}
+
+/*
+**test_vst1q_bf16:
+** vst1.16 {d0-d1}, \[r0\]
+** bx lr
+*/
+void
+test_vst1q_bf16 (bfloat16_t *a, bfloat16x8_t b)
+{
+ vst1q_bf16 (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_1.c b/gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_1.c
new file mode 100644
index 0000000..8564b8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_1.c
@@ -0,0 +1,22 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-require-effective-target arm_hard_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-O3 --save-temps -mfloat-abi=hard" } */
+
+#include "arm_neon.h"
+
+void
+test_vst1_lane_bf16 (bfloat16_t *a, bfloat16x4_t b)
+{
+ vst1_lane_bf16 (a, b, 1);
+}
+
+void
+test_vst1q_lane_bf16 (bfloat16_t *a, bfloat16x8_t b)
+{
+ vst1q_lane_bf16 (a, b, 2);
+}
+
+/* { dg-final { scan-assembler "vst1.16\t{d0\\\[1\\\]}, \\\[r0\\\]" } } */
+/* { dg-final { scan-assembler "vst1.16\t{d0\\\[2\\\]}, \\\[r0\\\]" } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_indices_1.c
new file mode 100644
index 0000000..1bd6871
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vst1_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-require-effective-target arm_hard_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-mfloat-abi=hard" } */
+
+#include "arm_neon.h"
+
+void
+test_vst1_lane_bf16 (bfloat16_t *a, bfloat16x4_t b)
+{
+ vst1_lane_bf16 (a, b, -1);
+ vst1_lane_bf16 (a, b, 4);
+}
+
+/* { dg-error "lane -1 out of range 0 - 3" "" { target *-*-* } 0 } */
+/* { dg-error "lane 4 out of range 0 - 3" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vstn_lane_bf16_1.c b/gcc/testsuite/gcc.target/arm/simd/vstn_lane_bf16_1.c
new file mode 100644
index 0000000..416ae77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vstn_lane_bf16_1.c
@@ -0,0 +1,73 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-save-temps -O2 -mfloat-abi=hard" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon.h"
+
+/*
+**test_vst2_lane_bf16:
+** vst2.16 {d0\[2\], d1\[2\]}, \[r0\]
+** bx lr
+*/
+void
+test_vst2_lane_bf16 (bfloat16_t *a, bfloat16x4x2_t b)
+{
+ return vst2_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vst2q_lane_bf16:
+** vst2.16 {d0\[2\], d2\[2\]}, \[r0\]
+** bx lr
+*/
+void
+test_vst2q_lane_bf16 (bfloat16_t *a, bfloat16x8x2_t b)
+{
+ return vst2q_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vst3_lane_bf16:
+** vst3.16 {d0\[2\], d1\[2\], d2\[2\]}, \[r0\]
+** bx lr
+*/
+void
+test_vst3_lane_bf16 (bfloat16_t *a, bfloat16x4x3_t b)
+{
+ return vst3_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vst3q_lane_bf16:
+** vst3.16 {d0\[2\], d2\[2\], d4\[2\]}, \[r0\]
+** bx lr
+*/
+void
+test_vst3q_lane_bf16 (bfloat16_t *a, bfloat16x8x3_t b)
+{
+ return vst3q_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vst4_lane_bf16:
+** vst4.16 {d0\[2\], d1\[2\], d2\[2\], d3\[2\]}, \[r0\]
+** bx lr
+*/
+void
+test_vst4_lane_bf16 (bfloat16_t *a, bfloat16x4x4_t b)
+{
+ return vst4_lane_bf16 (a, b, 2);
+}
+
+/*
+**test_vst4q_lane_bf16:
+** vst4.16 {d0\[2\], d2\[2\], d4\[2\], d6\[2\]}, \[r0\]
+** bx lr
+*/
+void
+test_vst4q_lane_bf16 (bfloat16_t *a, bfloat16x8x4_t b)
+{
+ return vst4q_lane_bf16 (a, b, 2);
+}
diff --git a/gcc/testsuite/gcc.target/arm/simd/vstq1_lane_bf16_indices_1.c b/gcc/testsuite/gcc.target/arm/simd/vstq1_lane_bf16_indices_1.c
new file mode 100644
index 0000000..f18a479
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vstq1_lane_bf16_indices_1.c
@@ -0,0 +1,17 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_bf16_neon_ok } */
+/* { dg-require-effective-target arm_hard_ok } */
+/* { dg-add-options arm_v8_2a_bf16_neon } */
+/* { dg-additional-options "-mfloat-abi=hard" } */
+
+#include "arm_neon.h"
+
+void
+test_vstq1_lane_bf16 (bfloat16_t *a, bfloat16x8_t b)
+{
+ vst1q_lane_bf16 (a, b, -1);
+ vst1q_lane_bf16 (a, b, 8);
+}
+
+/* { dg-error "lane -1 out of range 0 - 7" "" { target *-*-* } 0 } */
+/* { dg-error "lane 8 out of range 0 - 7" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/arm/tlscall.c b/gcc/testsuite/gcc.target/arm/tlscall.c
index 71366ef..8d5609a 100644
--- a/gcc/testsuite/gcc.target/arm/tlscall.c
+++ b/gcc/testsuite/gcc.target/arm/tlscall.c
@@ -2,6 +2,7 @@
/* { dg-do assemble } */
/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
+/* { dg-require-effective-target fpic } */
/* { dg-skip-if "FDPIC does not support gnu2 TLS dialect" { arm*-*-uclinuxfdpiceabi } "*" "" } */
/* { dg-skip-if "-mpure-code and -fPIC incompatible" { *-*-* } { "-mpure-code" } } */
diff --git a/gcc/testsuite/gcc.target/arm/vect-half-floats.c b/gcc/testsuite/gcc.target/arm/vect-half-floats.c
new file mode 100644
index 0000000..49ca2e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vect-half-floats.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -ftree-vectorize -fdump-tree-vect-all -std=c11" } */
+/* { dg-require-effective-target float16 } */
+/* { dg-require-effective-target arm_fp16_ok } */
+/* { dg-add-options float16 } */
+
+void foo (_Float16 n1[], _Float16 n2[], _Float16 r[], int n)
+{
+ for (int i = 0; i < n; i++)
+ r[i] = n1[i] + n2[i];
+}
+
+/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */
+
diff --git a/gcc/testsuite/gcc.target/h8300/add-2.c b/gcc/testsuite/gcc.target/h8300/add-2.c
new file mode 100644
index 0000000..27f9b2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/add-2.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-ms -mint32 -O2" } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+#include "add.c"
diff --git a/gcc/testsuite/gcc.target/h8300/add-3.c b/gcc/testsuite/gcc.target/h8300/add-3.c
new file mode 100644
index 0000000..20de647
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/add-3.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-msx -mint32 -O2" } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+#include "add.c"
diff --git a/gcc/testsuite/gcc.target/h8300/add.c b/gcc/testsuite/gcc.target/h8300/add.c
new file mode 100644
index 0000000..ebeea57
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/add.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-mh -mint32 -O2" } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+typedef unsigned char uchar;
+typedef signed char schar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+
+volatile void abort (void);
+
+
+#define ADD(T)\
+T addE##T (T x, T y) { T t = x + y ; if (t == 0) abort (); return t; } \
+T addNE##T (T x, T y) { T t = x + y ; if (t != 0) return t; abort (); } \
+T addGE##T (T x, T y) { T t = x + y ; if (t >= 0) abort (); return t; } \
+T addLT##T (T x, T y) { T t = x + y ; if (t < 0) abort (); return t; }
+
+#define ADDC(T,N)\
+T addEQ##N##T (T a) { T t = a + N; if (t == 0) abort (); return t; } \
+T addNE##N##T (T a) { T t = a + N; if (t != 0) return t; abort (); } \
+T addGE##N##T (T a) { T t = a + N; if (t >= 0) abort (); return t; } \
+T addLT##N##T (T a) { T t = a + N; if (t < 0) abort (); return t; }
+
+#define ADDNC(T,N)\
+T addEQN##N##T (T a) { T t = a + -N; if (t == 0) abort (); return t; } \
+T addNEN##N##T (T a) { T t = a + -N; if (t != 0) return t; abort (); } \
+T addGEN##N##T (T a) { T t = a + -N; if (t >= 0) abort (); return t; } \
+T addLTN##N##T (T a) { T t = a + -N; if (t < 0) abort (); return t; }
+
+
+ADD (schar)
+ADD (short)
+ADD (long)
+ADD (uchar)
+ADD (ushort)
+ADD (ulong)
+
+
+
+ADDC (schar,1)
+ADDC (schar,2)
+ADDC (schar,3)
+ADDC (schar,4)
+ADDC (schar,6)
+ADDC (schar,8)
+ADDNC (schar,1)
+ADDNC (schar,2)
+ADDNC (schar,3)
+ADDNC (schar,4)
+ADDNC (schar,6)
+ADDNC (schar,8)
+
+ADDC (uchar,1)
+ADDC (uchar,2)
+ADDC (uchar,3)
+ADDC (uchar,4)
+ADDC (uchar,6)
+ADDC (uchar,8)
+ADDNC (uchar,1)
+ADDNC (uchar,2)
+ADDNC (uchar,3)
+ADDNC (uchar,4)
+ADDNC (uchar,6)
+ADDNC (uchar,8)
+
+ADDC (short,1)
+ADDC (short,2)
+ADDC (short,3)
+ADDC (short,4)
+ADDC (short,6)
+ADDC (short,8)
+ADDNC (short,1)
+ADDNC (short,2)
+ADDNC (short,3)
+ADDNC (short,4)
+ADDNC (short,6)
+ADDNC (short,8)
+
+ADDC (ushort,1)
+ADDC (ushort,2)
+ADDC (ushort,3)
+ADDC (ushort,4)
+ADDC (ushort,6)
+ADDC (ushort,8)
+ADDNC (ushort,1)
+ADDNC (ushort,2)
+ADDNC (ushort,3)
+ADDNC (ushort,4)
+ADDNC (ushort,6)
+ADDNC (ushort,8)
+
+ADDC (long,1)
+ADDC (long,2)
+ADDC (long,3)
+ADDC (long,4)
+ADDC (long,6)
+ADDC (long,8)
+ADDNC (long,1)
+ADDNC (long,2)
+ADDNC (long,3)
+ADDNC (long,4)
+ADDNC (long,6)
+ADDNC (long,8)
+
+ADDC (ulong,1)
+ADDC (ulong,2)
+ADDC (ulong,3)
+ADDC (ulong,4)
+ADDC (ulong,6)
+ADDC (ulong,8)
+ADDNC (ulong,1)
+ADDNC (ulong,2)
+ADDNC (ulong,3)
+ADDNC (ulong,4)
+ADDNC (ulong,6)
+ADDNC (ulong,8)
+
diff --git a/gcc/testsuite/gcc.target/h8300/sub-2.c b/gcc/testsuite/gcc.target/h8300/sub-2.c
new file mode 100644
index 0000000..c2914bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/sub-2.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-ms -mint32 -O2" } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+#include "sub.c"
diff --git a/gcc/testsuite/gcc.target/h8300/sub-3.c b/gcc/testsuite/gcc.target/h8300/sub-3.c
new file mode 100644
index 0000000..72bcf04
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/sub-3.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-msx -mint32 -O2" } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+#include "sub.c"
diff --git a/gcc/testsuite/gcc.target/h8300/sub.c b/gcc/testsuite/gcc.target/h8300/sub.c
new file mode 100644
index 0000000..66b63ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/sub.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-mh -mint32 -O2" } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+typedef unsigned char uchar;
+typedef signed char schar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+
+volatile void abort (void);
+
+
+#define SUB(T)\
+T subE##T (T x, T y) { T t = x - y ; if (t == 0) abort (); return t; } \
+T subNE##T (T x, T y) { T t = x - y ; if (t != 0) return t; abort (); } \
+T subGE##T (T x, T y) { T t = x - y ; if (t >= 0) abort (); return t; } \
+T subLT##T (T x, T y) { T t = x - y ; if (t < 0) abort (); return t; }
+
+#define SUBC(T,N)\
+T subEQ##N##T (T a) { T t = a - N; if (t == 0) abort (); return t; } \
+T subNE##N##T (T a) { T t = a - N; if (t != 0) return t; abort (); } \
+T subGE##N##T (T a) { T t = a - N; if (t >= 0) abort (); return t; } \
+T subLT##N##T (T a) { T t = a - N; if (t < 0) abort (); return t; }
+
+#define SUBNC(T,N)\
+T subEQN##N##T (T a) { T t = a - -N; if (t == 0) abort (); return t; } \
+T subNEN##N##T (T a) { T t = a - -N; if (t != 0) return t; abort (); } \
+T subGEN##N##T (T a) { T t = a - -N; if (t >= 0) abort (); return t; } \
+T subLTN##N##T (T a) { T t = a - -N; if (t < 0) abort (); return t; }
+
+
+SUB (schar)
+SUB (short)
+SUB (long)
+SUB (uchar)
+SUB (ushort)
+SUB (ulong)
+
+
+
+SUBC (schar,1)
+SUBC (schar,2)
+SUBC (schar,3)
+SUBC (schar,4)
+SUBC (schar,6)
+SUBC (schar,8)
+SUBNC (schar,1)
+SUBNC (schar,2)
+SUBNC (schar,3)
+SUBNC (schar,4)
+SUBNC (schar,6)
+SUBNC (schar,8)
+
+SUBC (uchar,1)
+SUBC (uchar,2)
+SUBC (uchar,3)
+SUBC (uchar,4)
+SUBC (uchar,6)
+SUBC (uchar,8)
+SUBNC (uchar,1)
+SUBNC (uchar,2)
+SUBNC (uchar,3)
+SUBNC (uchar,4)
+SUBNC (uchar,6)
+SUBNC (uchar,8)
+
+SUBC (short,1)
+SUBC (short,2)
+SUBC (short,3)
+SUBC (short,4)
+SUBC (short,6)
+SUBC (short,8)
+SUBNC (short,1)
+SUBNC (short,2)
+SUBNC (short,3)
+SUBNC (short,4)
+SUBNC (short,6)
+SUBNC (short,8)
+
+SUBC (ushort,1)
+SUBC (ushort,2)
+SUBC (ushort,3)
+SUBC (ushort,4)
+SUBC (ushort,6)
+SUBC (ushort,8)
+SUBNC (ushort,1)
+SUBNC (ushort,2)
+SUBNC (ushort,3)
+SUBNC (ushort,4)
+SUBNC (ushort,6)
+SUBNC (ushort,8)
+
+SUBC (long,1)
+SUBC (long,2)
+SUBC (long,3)
+SUBC (long,4)
+SUBC (long,6)
+SUBC (long,8)
+SUBNC (long,1)
+SUBNC (long,2)
+SUBNC (long,3)
+SUBNC (long,4)
+SUBNC (long,6)
+SUBNC (long,8)
+
+SUBC (ulong,1)
+SUBC (ulong,2)
+SUBC (ulong,3)
+SUBC (ulong,4)
+SUBC (ulong,6)
+SUBC (ulong,8)
+SUBNC (ulong,1)
+SUBNC (ulong,2)
+SUBNC (ulong,3)
+SUBNC (ulong,4)
+SUBNC (ulong,6)
+SUBNC (ulong,8)
+
diff --git a/gcc/testsuite/gcc.target/i386/amxbf16-asmintel-1.c b/gcc/testsuite/gcc.target/i386/amxbf16-asmintel-1.c
index c2d6074..54194e1 100644
--- a/gcc/testsuite/gcc.target/i386/amxbf16-asmintel-1.c
+++ b/gcc/testsuite/gcc.target/i386/amxbf16-asmintel-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target masm_intel } */
/* { dg-options "-O2 -mamx-bf16 -masm=intel" } */
/* { dg-final { scan-assembler "tdpbf16ps\[ \\t]+\[^\n\]*%tmm1+\[^\n\]*%tmm2+\[^\n\]*%tmm3" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/amxint8-asmintel-1.c b/gcc/testsuite/gcc.target/i386/amxint8-asmintel-1.c
index bcfbb3f..f8c376a 100644
--- a/gcc/testsuite/gcc.target/i386/amxint8-asmintel-1.c
+++ b/gcc/testsuite/gcc.target/i386/amxint8-asmintel-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target masm_intel } */
/* { dg-options "-O2 -mamx-int8 -masm=intel" } */
/* { dg-final { scan-assembler "tdpbssd\[ \\t]+\[^\n\]*%tmm1+\[^\n\]*%tmm2+\[^\n\]*%tmm3" } } */
/* { dg-final { scan-assembler "tdpbsud\[ \\t]+\[^\n\]*%tmm1+\[^\n\]*%tmm2+\[^\n\]*%tmm3" } } *
diff --git a/gcc/testsuite/gcc.target/i386/amxtile-asmintel-1.c b/gcc/testsuite/gcc.target/i386/amxtile-asmintel-1.c
index 88ef612..6c08fec 100644
--- a/gcc/testsuite/gcc.target/i386/amxtile-asmintel-1.c
+++ b/gcc/testsuite/gcc.target/i386/amxtile-asmintel-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target masm_intel } */
/* { dg-options "-O2 -mamx-tile -masm=intel " } */
/* { dg-final { scan-assembler "ldtilecfg\[ \\t]" } } */
/* { dg-final { scan-assembler "sttilecfg\[ \\t]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-vnni-1.c b/gcc/testsuite/gcc.target/i386/avx-vnni-1.c
new file mode 100644
index 0000000..a22d12a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vnni-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavxvnni -O2" } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+
+void extern
+avxvnni_test (void)
+{
+ x = _mm256_dpbusd_epi32 (x, y, z);
+ x_ = _mm_dpbusd_epi32 (x_, y_, z_);
+ x = _mm256_dpbusds_epi32 (x, y, z);
+ x_ = _mm_dpbusds_epi32 (x_, y_, z_);
+ x = _mm256_dpwssd_epi32 (x, y, z);
+ x_ = _mm_dpwssd_epi32 (x_, y_, z_);
+ x = _mm256_dpwssds_epi32 (x, y, z);
+ x_ = _mm_dpwssds_epi32 (x_, y_, z_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vnni-2.c b/gcc/testsuite/gcc.target/i386/avx-vnni-2.c
new file mode 100644
index 0000000..4ab6f0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vnni-2.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+
+__attribute__((target("avxvnni")))
+void
+avxvnni_test (void)
+{
+ x = _mm256_dpbusd_epi32 (x, y, z);
+ x_ = _mm_dpbusd_epi32 (x_, y_, z_);
+ x = _mm256_dpbusds_epi32 (x, y, z);
+ x_ = _mm_dpbusds_epi32 (x_, y_, z_);
+ x = _mm256_dpwssd_epi32 (x, y, z);
+ x_ = _mm_dpwssd_epi32 (x_, y_, z_);
+ x = _mm256_dpwssds_epi32 (x, y, z);
+ x_ = _mm_dpwssds_epi32 (x_, y_, z_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vnni-3.c b/gcc/testsuite/gcc.target/i386/avx-vnni-3.c
new file mode 100644
index 0000000..fdea7f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vnni-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+
+__attribute__ ((__gnu_inline__, __always_inline__, target("avxvnni")))
+inline int
+foo (void) /* { dg-error "inlining failed in call to 'always_inline' .* target specific option mismatch" } */
+{
+ return 0;
+}
+
+__attribute__ ((target("avx512vnni,avx512vl")))
+int
+bar (void)
+{
+ return foo (); /* { dg-message "called from here" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vnni-4.c b/gcc/testsuite/gcc.target/i386/avx-vnni-4.c
new file mode 100644
index 0000000..1ef3edc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vnni-4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+
+__attribute__ ((__gnu_inline__, __always_inline__, target("avx512vnni,avx512vl")))
+inline int
+foo (void) /* { dg-error "inlining failed in call to 'always_inline' .* target specific option mismatch" } */
+{
+ return 0;
+}
+
+__attribute__ ((target("avxvnni")))
+int
+bar (void)
+{
+ return foo (); /* { dg-message "called from here" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vnni-5.c b/gcc/testsuite/gcc.target/i386/avx-vnni-5.c
new file mode 100644
index 0000000..6556a32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vnni-5.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavxvnni -mavx512vnni -mavx512vl" } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+
+void
+avxvnni_test (void)
+{
+ x = _mm256_dpbusd_epi32 (x, y, z);
+ x_ = _mm_dpbusd_epi32 (x_, y_, z_);
+ x = _mm256_dpbusds_epi32 (x, y, z);
+ x_ = _mm_dpbusds_epi32 (x_, y_, z_);
+ x = _mm256_dpwssd_epi32 (x, y, z);
+ x_ = _mm_dpwssd_epi32 (x_, y_, z_);
+ x = _mm256_dpwssds_epi32 (x, y, z);
+ x_ = _mm_dpwssds_epi32 (x_, y_, z_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vnni-6.c b/gcc/testsuite/gcc.target/i386/avx-vnni-6.c
new file mode 100644
index 0000000..2c42627
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vnni-6.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mavxvnni -O2" } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+
+void extern
+avxvnni_test (void)
+{
+ x = _mm256_dpbusd_avx_epi32 (x, y, z);
+ x_ = _mm_dpbusd_avx_epi32 (x_, y_, z_);
+ x = _mm256_dpbusds_avx_epi32 (x, y, z);
+ x_ = _mm_dpbusds_avx_epi32 (x_, y_, z_);
+ x = _mm256_dpwssd_avx_epi32 (x, y, z);
+ x_ = _mm_dpwssd_avx_epi32 (x_, y_, z_);
+ x = _mm256_dpwssds_avx_epi32 (x, y, z);
+ x_ = _mm_dpwssds_avx_epi32 (x_, y_, z_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vpdpbusd-2.c b/gcc/testsuite/gcc.target/i386/avx-vpdpbusd-2.c
new file mode 100644
index 0000000..d4b8d89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vpdpbusd-2.c
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavxvnni" } */
+/* { dg-require-effective-target avxvnni } */
+
+#ifndef CHECK
+#define CHECK "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK
+
+static void
+CALC (int *r, int *dst, unsigned char *s1, char *s2, int size)
+{
+ short tempres[32];
+ for (int i = 0; i < size; i++) {
+ tempres[i] = ((unsigned short)(s1[i]) * (short)(s2[i]));
+ }
+ for (int i = 0; i < size / 4; i++) {
+ long long test = (long long)dst[i] + tempres[i*4] + tempres[i*4 + 1] + tempres[i*4 + 2] + tempres[i*4 + 3];
+ r[i] = test;
+ }
+}
+
+void
+TEST (void)
+{
+ int i;
+ union256i_d res_256;
+ union256i_b src2_256;
+ union256i_ub src1_256;
+ int res_ref_256[8];
+
+ if (!__builtin_cpu_supports ("avxvnni"))
+ return;
+
+ for (i = 0; i < 32; i++)
+ {
+ int sign = i % 2 ? 1 : -1;
+ src1_256.a[i] = 10 + 3*i + sign;
+ src2_256.a[i] = sign*10*i*i;
+ }
+
+ for (i = 0; i < 8; i++)
+ res_256.a[i] = 0x7fffffff;
+
+ CALC (res_ref_256, res_256.a, src1_256.a, src2_256.a, 32);
+ res_256.x = _mm256_dpbusd_avx_epi32 (res_256.x, src1_256.x, src2_256.x);
+ if (check_union256i_d (res_256, res_ref_256))
+ abort ();
+
+ union128i_d res_128;
+ union128i_b src2_128;
+ union128i_ub src1_128;
+ int res_ref_128[4];
+
+ for (i = 0; i < 16; i++)
+ {
+ int sign = i % 2 ? 1 : -1;
+ src1_128.a[i] = 10 + 3*i*i + sign;
+ src2_128.a[i] = sign*10*i*i;
+ }
+
+ for (i = 0; i < 4; i++)
+ res_128.a[i] = 0x7fffffff;
+
+ CALC (res_ref_128, res_128.a, src1_128.a, src2_128.a, 16);
+ res_128.x = _mm_dpbusd_avx_epi32 (res_128.x, src1_128.x, src2_128.x);
+ if (check_union128i_d (res_128, res_ref_128))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vpdpbusds-2.c b/gcc/testsuite/gcc.target/i386/avx-vpdpbusds-2.c
new file mode 100644
index 0000000..5041ffe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vpdpbusds-2.c
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavxvnni " } */
+/* { dg-require-effective-target avxvnni } */
+
+#ifndef CHECK
+#define CHECK "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK
+
+static void
+CALC (int *r, int *dst, unsigned char *s1, char *s2, int size)
+{
+ short tempres[32];
+ for (int i = 0; i < size; i++) {
+ tempres[i] = ((unsigned short)(s1[i]) * (short)(s2[i]));
+ }
+ for (int i = 0; i < size / 4; i++) {
+ long long test = (long long)dst[i] + tempres[i*4] + tempres[i*4 + 1] + tempres[i*4 + 2] + tempres[i*4 + 3];
+ r[i] = test > 0x7FFFFFFF ? 0x7FFFFFFF : test;
+ }
+}
+
+void
+TEST (void)
+{
+ int i;
+ union256i_d res_256;
+ union256i_b src2_256;
+ union256i_ub src1_256;
+ int res_ref_256[8];
+
+ if (!__builtin_cpu_supports ("avxvnni"))
+ return;
+
+ for (i = 0; i < 32; i++)
+ {
+ int sign = i % 2 ? 1 : -1;
+ src1_256.a[i] = 10 + 3*i*i + sign;
+ src2_256.a[i] = sign*10*i*i;
+ }
+
+ for (i = 0; i < 8; i++)
+ res_256.a[i] = 0x7fffffff;
+
+ CALC (res_ref_256, res_256.a, src1_256.a, src2_256.a, 32);
+ res_256.x = _mm256_dpbusds_avx_epi32 (res_256.x, src1_256.x, src2_256.x);
+ if (check_union256i_d (res_256, res_ref_256))
+ abort ();
+
+ union128i_d res_128;
+ union128i_b src2_128;
+ union128i_ub src1_128;
+ int res_ref_128[4];
+
+ for (i = 0; i < 16; i++)
+ {
+ int sign = i % 2 ? 1 : -1;
+ src1_128.a[i] = 10 + 3*i*i + sign;
+ src2_128.a[i] = sign*10*i*i;
+ }
+
+ for (i = 0; i < 4; i++)
+ res_128.a[i] = 0x7fffffff;
+
+ CALC (res_ref_128, res_128.a, src1_128.a, src2_128.a, 16);
+ res_128.x = _mm_dpbusds_avx_epi32 (res_128.x, src1_128.x, src2_128.x);
+ if (check_union128i_d (res_128, res_ref_128))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vpdpwssd-2.c b/gcc/testsuite/gcc.target/i386/avx-vpdpwssd-2.c
new file mode 100644
index 0000000..2630c97
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vpdpwssd-2.c
@@ -0,0 +1,70 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavxvnni" } */
+/* { dg-require-effective-target avxvnni } */
+
+#ifndef CHECK
+#define CHECK "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK
+
+static void
+CALC (int *r, int *dst, short *s1, short *s2, int size)
+{
+ short tempres[16];
+ for (int i = 0; i < size; i++) {
+ tempres[i] = ((int)(s1[i]) * (int)(s2[i]));
+ }
+ for (int i = 0; i < size / 2; i++) {
+ long long test = (long long)dst[i] + tempres[i*2] + tempres[i*2 + 1];
+ r[i] = test;
+ }
+}
+
+void
+TEST (void)
+{
+ int i;
+ union256i_d res_256;
+ union256i_w src1_256, src2_256;
+ int res_ref_256[8];
+
+ if (!__builtin_cpu_supports ("avxvnni"))
+ return;
+
+ for (i = 0; i < 16; i++)
+ {
+ src1_256.a[i] = 1 + i;
+ src2_256.a[i] = 2 + 2*i + i * i;
+ }
+
+ for (i = 0; i < 8; i++)
+ res_256.a[i] = 0x7fffffff;
+
+ CALC (res_ref_256, res_256.a, src1_256.a, src2_256.a, 16);
+ res_256.x = _mm256_dpwssd_avx_epi32 (res_256.x, src1_256.x, src2_256.x);
+ if (check_union256i_d (res_256, res_ref_256))
+ abort ();
+
+ union128i_d res_128;
+ union128i_w src1_128, src2_128;
+ int res_ref_128[4];
+
+ for (i = 0; i < 8; i++)
+ {
+ src1_128.a[i] = 1 + i;
+ src2_128.a[i] = 2 + 2*i + i * i;
+ }
+
+ for (i = 0; i < 4; i++)
+ res_128.a[i] = 0x7fffffff;
+
+ CALC (res_ref_128, res_128.a, src1_128.a, src2_128.a, 8);
+ res_128.x = _mm_dpwssd_avx_epi32 (res_128.x, src1_128.x, src2_128.x);
+ if (check_union128i_d (res_128, res_ref_128))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-vpdpwssds-2.c b/gcc/testsuite/gcc.target/i386/avx-vpdpwssds-2.c
new file mode 100644
index 0000000..bc4395a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vpdpwssds-2.c
@@ -0,0 +1,70 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavxvnni" } */
+/* { dg-require-effective-target avxvnni } */
+
+#ifndef CHECK
+#define CHECK "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK
+
+static void
+CALC (int *r, int *dst, short *s1, short *s2, int size)
+{
+ short tempres[16];
+ for (int i = 0; i < size; i++) {
+ tempres[i] = ((int)(s1[i]) * (int)(s2[i]));
+ }
+ for (int i = 0; i < size / 2; i++) {
+ long long test = (long long)dst[i] + tempres[i*2] + tempres[i*2 + 1];
+ r[i] = test > 0x7FFFFFFF ? 0x7FFFFFFF : test;
+ }
+}
+
+void
+TEST (void)
+{
+ int i;
+ union256i_d res_256;
+ union256i_w src1_256, src2_256;
+ int res_ref_256[8];
+
+ if (!__builtin_cpu_supports ("avxvnni"))
+ return;
+
+ for (i = 0; i < 16; i++)
+ {
+ src1_256.a[i] = 1 + i;
+ src2_256.a[i] = 2 + 2*i + i * i;
+ }
+
+ for (i = 0; i < 8; i++)
+ res_256.a[i] = 0x7fffffff;
+
+ CALC (res_ref_256, res_256.a, src1_256.a, src2_256.a, 16);
+ res_256.x = _mm256_dpwssds_avx_epi32 (res_256.x, src1_256.x, src2_256.x);
+ if (check_union256i_d (res_256, res_ref_256))
+ abort ();
+
+ union128i_d res_128;
+ union128i_w src1_128, src2_128;
+ int res_ref_128[4];
+
+ for (i = 0; i < 8; i++)
+ {
+ src1_128.a[i] = 1 + i;
+ src2_128.a[i] = 2 + 2*i + i * i;
+ }
+
+ for (i = 0; i < 4; i++)
+ res_128.a[i] = 0x7fffffff;
+
+ CALC (res_ref_128, res_128.a, src1_128.a, src2_128.a, 8);
+ res_128.x = _mm_dpwssds_avx_epi32 (res_128.x, src1_128.x, src2_128.x);
+ if (check_union128i_d (res_128, res_ref_128))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr98461.c b/gcc/testsuite/gcc.target/i386/avx2-pr98461.c
new file mode 100644
index 0000000..15f49b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-pr98461.c
@@ -0,0 +1,54 @@
+/* PR target/98461 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2 -masm=att" } */
+/* { dg-final { scan-assembler-times "\tvpmovmskb\t" 6 } } */
+/* { dg-final { scan-assembler-times "\tnotl\t" 6 } } */
+/* { dg-final { scan-assembler-not "\tvpcmpeq" } } */
+/* { dg-final { scan-assembler-not "\tvpxor" } } */
+/* { dg-final { scan-assembler-not "\tvpandn" } } */
+
+#include <x86intrin.h>
+
+int
+f1 (__m256i x)
+{
+ return ~_mm256_movemask_epi8 (x);
+}
+
+int
+f2 (__m256i x)
+{
+ return _mm256_movemask_epi8 (_mm256_andnot_si256 (x, _mm256_set1_epi8 (255)));
+}
+
+int
+f3 (__v32qi x)
+{
+ x ^= (__v32qi) { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+ return _mm256_movemask_epi8 ((__m256i) x);
+}
+
+long
+f4 (__m256i x)
+{
+ return (unsigned) ~_mm256_movemask_epi8 (x);
+}
+
+long
+f5 (__m256i x)
+{
+ return (unsigned) _mm256_movemask_epi8 (_mm256_andnot_si256 (x, _mm256_set1_epi8 (255)));
+}
+
+long
+f6 (__v32qi x)
+{
+ x ^= (__v32qi) { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+ return (unsigned) _mm256_movemask_epi8 ((__m256i) x);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vec-set-1.c b/gcc/testsuite/gcc.target/i386/avx2-vec-set-1.c
new file mode 100644
index 0000000..4c16ec5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vec-set-1.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx2 -O2 -mno-avx512f" } */
+/* { dg-final { scan-assembler-times {(?n)vpcmpeq[bwdq]} 12 } } */
+/* { dg-final { scan-assembler-times {(?n)vp?blendv} 12 } } */
+
+typedef char v32qi __attribute__ ((vector_size (32)));
+typedef char v16qi __attribute__ ((vector_size (16)));
+
+typedef short v16hi __attribute__ ((vector_size (32)));
+typedef short v8hi __attribute__ ((vector_size (16)));
+
+typedef int v8si __attribute__ ((vector_size (32)));
+typedef int v4si __attribute__ ((vector_size (16)));
+
+typedef long long v4di __attribute__ ((vector_size (32)));
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+typedef float v8sf __attribute__ ((vector_size (32)));
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+typedef double v4df __attribute__ ((vector_size (32)));
+typedef double v2df __attribute__ ((vector_size (16)));
+
+#define FOO(VTYPE, TYPE) \
+ VTYPE \
+ __attribute__ ((noipa)) \
+ foo_##VTYPE (VTYPE a, TYPE b, unsigned int c) \
+ { \
+ a[c] = b; \
+ return a; \
+ } \
+
+FOO (v16qi, char);
+FOO (v32qi, char);
+
+FOO (v8hi, short);
+FOO (v16hi, short);
+
+FOO (v4si, int);
+FOO (v8si, int);
+
+FOO (v2di, long long);
+FOO (v4di, long long);
+
+FOO (v4sf, float);
+FOO (v8sf, float);
+
+FOO (v2df, double);
+FOO (v4df, double);
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vec-set-2.c b/gcc/testsuite/gcc.target/i386/avx2-vec-set-2.c
new file mode 100644
index 0000000..9086ef4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vec-set-2.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-options "-O2 -mavx2" } */
+
+
+#ifndef CHECK
+#define CHECK "avx2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx2_test
+#endif
+
+#include CHECK
+
+#include "avx2-vec-set-1.c"
+
+#define CALC_TEST(vtype, type, N, idx) \
+do \
+ { \
+ int i,val = idx * idx - idx * 3 + 16; \
+ type res[N],exp[N]; \
+ vtype resv; \
+ for (i = 0; i < N; i++) \
+ { \
+ res[i] = i * i - i * 3 + 15; \
+ exp[i] = res[i]; \
+ } \
+ exp[idx] = val; \
+ resv = foo_##vtype (*(vtype *)&res[0], val, idx); \
+ for (i = 0; i < N; i++) \
+ { \
+ if (resv[i] != exp[i]) \
+ abort (); \
+ } \
+ } \
+while (0)
+
+static void
+TEST (void)
+{
+ CALC_TEST (v32qi, char, 32, 17);
+ CALC_TEST (v16qi, char, 16, 5);
+ CALC_TEST (v16hi, short, 16, 9);
+ CALC_TEST (v8hi, short, 8, 6);
+ CALC_TEST (v8si, int, 8, 3);
+ CALC_TEST (v4si, int, 4, 2);
+ CALC_TEST (v4di, long long, 4, 1);
+ CALC_TEST (v2di, long long, 2, 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bitalg-pr97770-1.c b/gcc/testsuite/gcc.target/i386/avx512bitalg-pr97770-1.c
new file mode 100644
index 0000000..c83a477
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bitalg-pr97770-1.c
@@ -0,0 +1,60 @@
+/* PR target/97770 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512bitalg -mavx512vl -mprefer-vector-width=512" } */
+/* Add xfail since no IFN for QI/HImode popcount */
+/* { dg-final { scan-assembler-times "vpopcntb\[ \\t\]+\[^\\n\\r\]*xmm" 1 {xfail *-*-*} } } */
+/* { dg-final { scan-assembler-times "vpopcntw\[ \\t\]+\[^\\n\\r\]*xmm" 1 {xfail *-*-*} } } */
+/* { dg-final { scan-assembler-times "vpopcntb\[ \\t\]+\[^\\n\\r\]*ymm" 1 {xfail *-*-*} } } */
+/* { dg-final { scan-assembler-times "vpopcntw\[ \\t\]+\[^\\n\\r\]*ymm" 1 {xfail *-*-*} } } */
+/* { dg-final { scan-assembler-times "vpopcntb\[ \\t\]+\[^\\n\\r\]*zmm" 1 {xfail *-*-*} } } */
+/* { dg-final { scan-assembler-times "vpopcntw\[ \\t\]+\[^\\n\\r\]*zmm" 1 {xfail *-*-*} } } */
+
+#include <immintrin.h>
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountb_128 (char * __restrict dest, char* src)
+{
+ for (int i = 0; i != 16; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountw_128 (short* __restrict dest, short* src)
+{
+ for (int i = 0; i != 8; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountb_256 (char * __restrict dest, char* src)
+{
+ for (int i = 0; i != 32; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountw_256 (short* __restrict dest, short* src)
+{
+ for (int i = 0; i != 16; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountb_512 (char * __restrict dest, char* src)
+{
+ for (int i = 0; i != 64; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountw_512 (short* __restrict dest, short* src)
+{
+ for (int i = 0; i != 32; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr96906-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr96906-1.c
new file mode 100644
index 0000000..81d7e06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr96906-1.c
@@ -0,0 +1,68 @@
+/* PR target/96906 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512bw -mavx512vl -masm=att" } */
+/* { dg-final { scan-assembler-times {(?n)vpcmpub[ \t]*\$2} 9 } } */
+/* { dg-final { scan-assembler-times {(?n)vpcmpub[ \t]*\$6} 9 } } */
+/* { dg-final { scan-assembler-times {(?n)vpcmpuw[ \t]*\$2} 9 } } */
+/* { dg-final { scan-assembler-times {(?n)vpcmpuw[ \t]*\$6} 9 } } */
+
+
+#include<immintrin.h>
+
+#define FOO(LENGTH,SUFFIX,TYPE,UTYPE,RTYPE,PRED) \
+ __mmask##RTYPE \
+ foo_##LENGTH##_##TYPE##_##PRED (__m##LENGTH##i x, __m##LENGTH##i y) \
+ { \
+ return \
+ _mm##SUFFIX##_cmp_##TYPE##_mask (_mm##SUFFIX##_subs_##UTYPE (x, y), \
+ _mm##SUFFIX##_setzero_si##LENGTH (), \
+ PRED); \
+ } \
+
+FOO (128,, epi16, epu16, 8, 0);
+FOO (128,, epi16, epu16, 8, 4);
+
+FOO (128,, epu16, epu16, 8, 0);
+FOO (128,, epu16, epu16, 8, 2);
+FOO (128,, epu16, epu16, 8, 4);
+FOO (128,, epu16, epu16, 8, 6);
+
+FOO (256, 256, epi16, epu16, 16, 0);
+FOO (256, 256, epi16, epu16, 16, 4);
+
+FOO (256, 256, epu16, epu16, 16, 0);
+FOO (256, 256, epu16, epu16, 16, 2);
+FOO (256, 256, epu16, epu16, 16, 4);
+FOO (256, 256, epu16, epu16, 16, 6);
+
+FOO (512, 512, epi16, epu16, 32, 0);
+FOO (512, 512, epi16, epu16, 32, 4);
+
+FOO (512, 512, epu16, epu16, 32, 0);
+FOO (512, 512, epu16, epu16, 32, 2);
+FOO (512, 512, epu16, epu16, 32, 4);
+FOO (512, 512, epu16, epu16, 32, 6);
+
+FOO (128,, epi8, epu8, 16, 0);
+FOO (128,, epi8, epu8, 16, 4);
+
+FOO (128,, epu8, epu8, 16, 0);
+FOO (128,, epu8, epu8, 16, 2);
+FOO (128,, epu8, epu8, 16, 4);
+FOO (128,, epu8, epu8, 16, 6);
+
+FOO (256, 256, epi8, epu8, 32, 0);
+FOO (256, 256, epi8, epu8, 32, 4);
+
+FOO (256, 256, epu8, epu8, 32, 0);
+FOO (256, 256, epu8, epu8, 32, 2);
+FOO (256, 256, epu8, epu8, 32, 4);
+FOO (256, 256, epu8, epu8, 32, 6);
+
+FOO (512, 512, epi8, epu8, 64, 0);
+FOO (512, 512, epi8, epu8, 64, 4);
+
+FOO (512, 512, epu8, epu8, 64, 0);
+FOO (512, 512, epu8, epu8, 64, 2);
+FOO (512, 512, epu8, epu8, 64, 4);
+FOO (512, 512, epu8, epu8, 64, 6);
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vec-set-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vec-set-1.c
new file mode 100644
index 0000000..5cfbc85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vec-set-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512bw -O2" } */
+/* { dg-final { scan-assembler-times {(?n)(?:vp?broadcast|vmovddup)} 36 } } */
+/* { dg-final { scan-assembler-times {(?n)vpcmp[bwdq][ \t]+\$0} 18 } } */
+
+typedef char v64qi __attribute__ ((vector_size (64)));
+typedef short v32hi __attribute__ ((vector_size (64)));
+typedef int v16si __attribute__ ((vector_size (64)));
+typedef long long v8di __attribute__ ((vector_size (64)));
+typedef float v16sf __attribute__ ((vector_size (64)));
+typedef double v8df __attribute__ ((vector_size (64)));
+
+#include "avx2-vec-set-1.c"
+
+FOO (v64qi, char);
+FOO (v32hi, short);
+FOO (v16si, int);
+FOO (v8di, long long);
+FOO (v16sf, float);
+FOO (v8df, double);
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vec-set-2.c b/gcc/testsuite/gcc.target/i386/avx512bw-vec-set-2.c
new file mode 100644
index 0000000..22e6418
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vec-set-2.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512bw } */
+/* { dg-options "-O2 -mavx512bw" } */
+
+
+#ifndef CHECK
+#define CHECK "avx512f-check.h"
+#endif
+
+#define AVX512BW
+
+#include CHECK
+
+#include "avx512bw-vec-set-1.c"
+
+#define CALC_TEST(vtype, type, N, idx) \
+do \
+ { \
+ int i,val = idx * idx - idx * 3 + 16; \
+ type res[N],exp[N]; \
+ vtype resv; \
+ for (i = 0; i < N; i++) \
+ { \
+ res[i] = i * i - i * 3 + 15; \
+ exp[i] = res[i]; \
+ } \
+ exp[idx] = val; \
+ resv = foo_##vtype (*(vtype *)&res[0], val, idx); \
+ for (i = 0; i < N; i++) \
+ { \
+ if (resv[i] != exp[i]) \
+ abort (); \
+ } \
+ } \
+while (0)
+
+static void
+test_512 (void)
+{
+ CALC_TEST (v64qi, char, 64, 50);
+ CALC_TEST (v32hi, short, 32, 30);
+ CALC_TEST (v16si, int, 16, 15);
+ CALC_TEST (v8di, long long, 8, 7);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-1.c
index dcb8caa..8603a19 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu16-1.c
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovdqu16|vpblendmw)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqu16\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu8-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu8-1.c
index a335bca..d1e3392 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu8-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vmovdqu8-1.c
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovdqu8|vpblendmb)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovdqu8|vpblendmb)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovdqu8|vpblendmb)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqu8\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vandnpd-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vandnpd-2.c
index 0be2b7c..0a7d19b 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vandnpd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vandnpd-2.c
@@ -16,8 +16,11 @@ CALC (double *s1, double *s2, double *r)
for (i = 0; i < SIZE; i++)
{
- tmp = (~(*(long long *) &s1[i])) & (*(long long *) &s2[i]);
- r[i] = *(double *) &tmp;
+ union U { double d; long long l; } u1, u2;
+ u1.d = s1[i];
+ u2.d = s2[i];
+ u1.l = (~u1.l) & u2.l;
+ r[i] = u1.d;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vandnps-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vandnps-2.c
index 39a45c1..836a7ab 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vandnps-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vandnps-2.c
@@ -16,8 +16,11 @@ CALC (float *s1, float *s2, float *r)
for (i = 0; i < SIZE; i++)
{
- tmp = (~(*(int *) &s1[i])) & (*(int *) &s2[i]);
- r[i] = *(float *) &tmp;
+ union U { float f; int i; } u1, u2;
+ u1.f = s1[i];
+ u2.f = s2[i];
+ u1.i = (~u1.i) & u2.i;
+ r[i] = u1.f;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vandpd-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vandpd-2.c
index 208336b6..b629c9f 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vandpd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vandpd-2.c
@@ -16,8 +16,11 @@ CALC (double *s1, double *s2, double *r)
for (i = 0; i < SIZE; i++)
{
- tmp = (*(long long *) &s1[i]) & (*(long long *) &s2[i]);
- r[i] = *(double *) &tmp;
+ union U { double d; long long l; } u1, u2;
+ u1.d = s1[i];
+ u2.d = s2[i];
+ u1.l &= u2.l;
+ r[i] = u1.d;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vandps-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vandps-2.c
index 50268b9..6e55e66 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vandps-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vandps-2.c
@@ -16,8 +16,11 @@ CALC (float *s1, float *s2, float *r)
for (i = 0; i < SIZE; i++)
{
- tmp = (*(int *) &s1[i]) & (*(int *) &s2[i]);
- r[i] = *(float *) &tmp;
+ union U { float f; int i; } u1, u2;
+ u1.f = s1[i];
+ u2.f = s2[i];
+ u1.i &= u2.i;
+ r[i] = u1.f;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vorpd-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vorpd-2.c
index 97fe84e..6376c1c 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vorpd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vorpd-2.c
@@ -15,8 +15,11 @@ CALC (double *src1, double *src2, double *dst)
for (i = 0; i < SIZE; i++)
{
- long long tmp = (*(long long *) &src1[i]) | (*(long long *) &src2[i]);
- dst[i] = *(double *) &tmp;
+ union U { double d; long long l; } u1, u2;
+ u1.d = src1[i];
+ u2.d = src2[i];
+ u1.l |= u2.l;
+ dst[i] = u1.d;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vorps-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vorps-2.c
index 95a7c5f..3d30247 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vorps-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vorps-2.c
@@ -15,8 +15,11 @@ CALC (float *src1, float *src2, float *dst)
for (i = 0; i < SIZE; i++)
{
- int tmp = (*(int *) &src1[i]) | (*(int *) &src2[i]);
- dst[i] = *(float *) &tmp;
+ union U { float f; int i; } u1, u2;
+ u1.f = src1[i];
+ u2.f = src2[i];
+ u1.i |= u2.i;
+ dst[i] = u1.f;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vxorpd-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vxorpd-2.c
index 4f4a07e..068be60 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vxorpd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vxorpd-2.c
@@ -15,8 +15,11 @@ CALC (double *src1, double *src2, double *dst)
for (i = 0; i < SIZE; i++)
{
- long long tmp = (*(long long *) &src1[i]) ^ (*(long long *) &src2[i]);
- dst[i] = *(double *) &tmp;
+ union U { double d; long long l; } u1, u2;
+ u1.d = src1[i];
+ u2.d = src2[i];
+ u1.l ^= u2.l;
+ dst[i] = u1.d;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vxorps-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vxorps-2.c
index 144283e..716bb81 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vxorps-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vxorps-2.c
@@ -15,8 +15,11 @@ CALC (float *src1, float *src2, float *dst)
for (i = 0; i < SIZE; i++)
{
- int tmp = (*(int *) &src1[i]) ^ (*(int *) &src2[i]);
- dst[i] = *(float *) &tmp;
+ union U { float f; int i; } u1, u2;
+ u1.f = src1[i];
+ u2.f = src2[i];
+ u1.i ^= u2.i;
+ dst[i] = u1.f;
}
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vec-set-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vec-set-2.c
new file mode 100644
index 0000000..8f2aa03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vec-set-2.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-options "-O2 -mavx512f -mno-avx512bw" } */
+
+
+#ifndef CHECK
+#define CHECK "avx512f-check.h"
+#endif
+
+#define AVX512F
+
+#include CHECK
+
+#include "avx512bw-vec-set-1.c"
+
+#define CALC_TEST(vtype, type, N, idx) \
+do \
+ { \
+ int i,val = idx * idx - idx * 3 + 16; \
+ type res[N],exp[N]; \
+ vtype resv; \
+ for (i = 0; i < N; i++) \
+ { \
+ res[i] = i * i - i * 3 + 15; \
+ exp[i] = res[i]; \
+ } \
+ exp[idx] = val; \
+ resv = foo_##vtype (*(vtype *)&res[0], val, idx); \
+ for (i = 0; i < N; i++) \
+ { \
+ if (resv[i] != exp[i]) \
+ abort (); \
+ } \
+ } \
+while (0)
+
+static void
+test_512 (void)
+{
+ CALC_TEST (v64qi, char, 64, 50);
+ CALC_TEST (v32hi, short, 32, 30);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovapd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovapd-1.c
index 7fc84b1..e869f70 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vmovapd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovapd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovapd|vblendmpd)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovaps-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovaps-1.c
index c2e2655..a7635a3 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vmovaps-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovaps-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovaps|vblendmps)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa32-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa32-1.c
index 8fb816c..b93727d 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa32-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa32-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovdqa32|vpblendmd)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa64-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa64-1.c
index 4352b12..1c372c4 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa64-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqa64-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovdqa64|vpblendmq)\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vec-set-2.c b/gcc/testsuite/gcc.target/i386/avx512vl-vec-set-2.c
new file mode 100644
index 0000000..4f32742
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vec-set-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512bw } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-options "-O2 -mavx512bw -mavx512vl" } */
+
+
+#ifndef CHECK
+#define CHECK "avx512f-check.h"
+#endif
+
+#define AVX512VL
+#define AVX512BW
+
+#include CHECK
+
+#include "avx512bw-vec-set-1.c"
+
+#define CALC_TEST(vtype, type, N, idx) \
+do \
+ { \
+ int i,val = idx * idx - idx * 3 + 16; \
+ type res[N],exp[N]; \
+ vtype resv; \
+ for (i = 0; i < N; i++) \
+ { \
+ res[i] = i * i - i * 3 + 15; \
+ exp[i] = res[i]; \
+ } \
+ exp[idx] = val; \
+ resv = foo_##vtype (*(vtype *)&res[0], val, idx); \
+ for (i = 0; i < N; i++) \
+ { \
+ if (resv[i] != exp[i]) \
+ abort (); \
+ } \
+ } \
+while (0)
+
+static void
+test_256 (void)
+{
+ CALC_TEST (v32qi, char, 32, 17);
+ CALC_TEST (v16hi, short, 16, 9);
+ CALC_TEST (v8si, int, 8, 3);
+ CALC_TEST (v4di, long long, 4, 1);
+}
+
+static void
+test_128 (void)
+{
+ CALC_TEST (v16qi, char, 16, 5);
+ CALC_TEST (v8hi, short, 8, 6);
+ CALC_TEST (v4si, int, 4, 2);
+ CALC_TEST (v2di, long long, 2, 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovapd-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovapd-1.c
index fd59660..89c3ebe 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovapd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovapd-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovapd|vblendmpd)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovapd|vblendmpd)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovapd\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovaps-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovaps-1.c
index 455b1a9..2196ebb 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovaps-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovaps-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovaps|vblendmps)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovaps|vblendmps)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovaps\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa32-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa32-1.c
index 5c6a3d0..9f991db 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa32-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa32-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovdqa32|vpblendmd)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovdqa32|vpblendmd)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa32\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa64-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa64-1.c
index 592541a..d20b4a7 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa64-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vmovdqa64-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "(?:vmovdqa64|vpblendmq)\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "(?:vmovdqa64|vpblendmq)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovdqa\[ \\t\]+\\(\[^\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 { target nonpic } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1a.c
index e63bc19..e63bc19 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1a.c
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1b.c b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1b.c
new file mode 100644
index 0000000..067e631
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-1b.c
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -mavx512vnni -mavx512bw -mavxvnni -O2" } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\\n\\r]*%ymm\[0-9\]+\[^\\n\\r\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\{vex\} vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\\n\\r]*%xmm\[0-9\]+\[^\\n\\r\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+volatile __mmask32 m;
+
+void extern
+avx512f_test (void)
+{
+ x = _mm256_dpbusd_epi32 (x, y, z);
+ x = _mm256_mask_dpbusd_epi32 (x, m, y, z);
+ x = _mm256_maskz_dpbusd_epi32 (m, x, y, z);
+
+ x_ = _mm_dpbusd_epi32 (x_, y_, z_);
+ x_ = _mm_mask_dpbusd_epi32 (x_, m, y_, z_);
+ x_ = _mm_maskz_dpbusd_epi32 (m, x_, y_, z_);
+
+ x = _mm256_dpbusds_epi32 (x, y, z);
+ x = _mm256_mask_dpbusds_epi32 (x, m, y, z);
+ x = _mm256_maskz_dpbusds_epi32 (m, x, y, z);
+
+ x_ = _mm_dpbusds_epi32 (x_, y_, z_);
+ x_ = _mm_mask_dpbusds_epi32 (x_, m, y_, z_);
+ x_ = _mm_maskz_dpbusds_epi32 (m, x_, y_, z_);
+
+ x = _mm256_dpwssd_epi32 (x, y, z);
+ x = _mm256_mask_dpwssd_epi32 (x, m, y, z);
+ x = _mm256_maskz_dpwssd_epi32 (m, x, y, z);
+
+ x_ = _mm_dpwssd_epi32 (x_, y_, z_);
+ x_ = _mm_mask_dpwssd_epi32 (x_, m, y_, z_);
+ x_ = _mm_maskz_dpwssd_epi32 (m, x_, y_, z_);
+
+ x = _mm256_dpwssds_epi32 (x, y, z);
+ x = _mm256_mask_dpwssds_epi32 (x, m, y, z);
+ x = _mm256_maskz_dpwssds_epi32 (m, x, y, z);
+
+ x_ = _mm_dpwssds_epi32 (x_, y_, z_);
+ x_ = _mm_mask_dpwssds_epi32 (x_, m, y_, z_);
+ x_ = _mm_maskz_dpwssds_epi32 (m, x_, y_, z_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vnni-2.c b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-2.c
new file mode 100644
index 0000000..d4b4635
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-2.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+
+__attribute__((target("avx512vnni,avx512vl")))
+void
+avxvnni_test (void)
+{
+ x = _mm256_dpbusd_epi32 (x, y, z);
+ x_ = _mm_dpbusd_epi32 (x_, y_, z_);
+ x = _mm256_dpbusds_epi32 (x, y, z);
+ x_ = _mm_dpbusds_epi32 (x_, y_, z_);
+ x = _mm256_dpwssd_epi32 (x, y, z);
+ x_ = _mm_dpwssd_epi32 (x_, y_, z_);
+ x = _mm256_dpwssds_epi32 (x, y, z);
+ x_ = _mm_dpwssds_epi32 (x_, y_, z_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vnni-3.c b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-3.c
new file mode 100644
index 0000000..15a95ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vnni-3.c
@@ -0,0 +1,47 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mavxvnni -mavx512vnni -mavx512vl" } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpbusds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssds\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "\\tvpdpwssds\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+
+
+#include <immintrin.h>
+
+volatile __m256i x,y,z;
+volatile __m128i x_,y_,z_;
+
+void
+avxvnni_test (void)
+{
+ register __m256i a __asm ("xmm16");
+ register __m128i a_ __asm ("xmm26");
+ a = _mm256_dpbusd_epi32 (x, y, z);
+ asm volatile ("" : "+v" (a));
+ x = a;
+ a_ = _mm_dpbusd_epi32 (x_, y_, z_);
+ asm volatile ("" : "+v" (a_));
+ x_ = a_;
+ a = _mm256_dpbusds_epi32 (x, y, z);
+ asm volatile ("" : "+v" (a));
+ x = a;
+ a_ = _mm_dpbusds_epi32 (x_, y_, z_);
+ asm volatile ("" : "+v" (a_));
+ x_ = a_;
+ a = _mm256_dpwssd_epi32 (x, y, z);
+ asm volatile ("" : "+v" (a));
+ x = a;
+ a_ = _mm_dpwssd_epi32 (x_, y_, z_);
+ asm volatile ("" : "+v" (a_));
+ x_ = a_;
+ a = _mm256_dpwssds_epi32 (x, y, z);
+ asm volatile ("" : "+v" (a));
+ x = a;
+ a_ = _mm_dpwssds_epi32 (x_, y_, z_);
+ asm volatile ("" : "+v" (a_));
+ x_ = a_;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vnnivl-builtin.c b/gcc/testsuite/gcc.target/i386/avx512vnnivl-builtin.c
new file mode 100644
index 0000000..97aaba0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vnnivl-builtin.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -mno-avxvnni -mavx512vnni -mavx512vl" } */
+typedef int v8si __attribute__ ((vector_size (32)));
+v8si
+foo (v8si a, v8si b, v8si c)
+{
+ return __builtin_ia32_vpdpbusd_v8si (a, b, c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-1.c b/gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-1.c
new file mode 100644
index 0000000..63bb00d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-1.c
@@ -0,0 +1,63 @@
+/* PR target/97770 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512vpopcntdq -mavx512vl -mprefer-vector-width=512" } */
+/* { dg-final { scan-assembler-times "vpopcntd\[ \\t\]+\[^\\n\\r\]*xmm" 1 } } */
+/* { dg-final { scan-assembler-times "vpopcntd\[ \\t\]+\[^\\n\\r\]*ymm" 1 } } */
+/* { dg-final { scan-assembler-times "vpopcntd\[ \\t\]+\[^\\n\\r\]*zmm" 1 } } */
+/* Add xfail since current vectorizor cannot generate expected code for DImode popcount */
+/* { dg-final { scan-assembler-times "vpopcntq\[ \\t\]+\[^\\n\\r\]*xmm" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "vpopcntq\[ \\t\]+\[^\\n\\r\]*ymm" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "vpopcntq\[ \\t\]+\[^\\n\\r\]*zmm" 1 { xfail *-*-* } } } */
+#ifndef AVX512VPOPCNTQ_H_INCLUDED
+#define AVX512VPOPCNTQ_H_INCLUDED
+
+#include <immintrin.h>
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountd_128 (int* __restrict dest, int* src)
+{
+ for (int i = 0; i != 4; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountq_128 (long long* __restrict dest, long long* src)
+{
+ for (int i = 0; i != 2; i++)
+ dest[i] = __builtin_popcountll (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountd_256 (int* __restrict dest, int* src)
+{
+ for (int i = 0; i != 8; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountq_256 (long long* __restrict dest, long long* src)
+{
+ for (int i = 0; i != 4; i++)
+ dest[i] = __builtin_popcountll (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountd_512 (int* __restrict dest, int* src)
+{
+ for (int i = 0; i != 16; i++)
+ dest[i] = __builtin_popcount (src[i]);
+}
+
+void
+__attribute__ ((noipa, optimize("-O3")))
+popcountq_512 (long long* __restrict dest, long long* src)
+{
+ for (int i = 0; i != 8; i++)
+ dest[i] = __builtin_popcountll (src[i]);
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-2.c b/gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-2.c
new file mode 100644
index 0000000..f9d0578
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vpopcntdq-pr97770-2.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512vpopcntdq" } */
+/* { dg-require-effective-target avx512vpopcntdq } */
+
+#define AVX512VPOPCNTDQ
+
+#include "avx512f-helper.h"
+#include "avx512vpopcntdq-pr97770-1.c"
+
+#define SIZE_D AVX512F_LEN / 32
+#define SIZE_Q AVX512F_LEN / 64
+
+
+#define RTEST(TYPE, LEN, SIZE, MODE) \
+ do \
+ { \
+ TYPE res[SIZE], src[SIZE], res_ref[SIZE], v; \
+ int i, j, ret; \
+ for (i = 0; i < SIZE; i++) \
+ { \
+ v = src[i] = i * 2 + 3; \
+ ret = 0; \
+ for (j = 0; j < sizeof(v) * 8; j++) \
+ if ((v & ((TYPE)1 << (TYPE) j))) \
+ ret++; \
+ res_ref[i] = ret; \
+ } \
+ EVAL(popcount, MODE, LEN) (res, src); \
+ for (i = 0; i < SIZE; i++) \
+ if (res[i] != res_ref[i]) \
+ abort (); \
+ } \
+ while (0)
+
+void
+TEST (void)
+{
+ RTEST (long long, AVX512F_LEN, SIZE_Q, q_);
+ RTEST (int, AVX512F_LEN, SIZE_D, d_);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c b/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c
new file mode 100644
index 0000000..df4c23c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mavx512vpopcntdq -mavx512vl" } */
+/* { dg-require-effective-target avx512vpopcntdq } */
+/* { dg-require-effective-target avx512vl } */
+
+#define AVX512VL
+#define AVX512F_LEN 256
+#define AVX512F_LEN_HALF 128
+#include "avx512vpopcntdq-pr97770-2.c"
+
+#undef AVX512F_LEN
+#undef AVX512F_LEN_HALF
+
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+#include "avx512vpopcntdq-pr97770-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/avxvnni-builtin.c b/gcc/testsuite/gcc.target/i386/avxvnni-builtin.c
new file mode 100644
index 0000000..893a62a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avxvnni-builtin.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -mavxvnni -mno-avx512vnni" } */
+typedef int v8si __attribute__ ((vector_size (32)));
+v8si
+foo (v8si a, v8si b, v8si c)
+{
+ return __builtin_ia32_vpdpbusd_v8si (a, b, c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/builtin_thread_pointer.c b/gcc/testsuite/gcc.target/i386/builtin_thread_pointer.c
index 16a7ca4..09b704b 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_thread_pointer.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_thread_pointer.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target tls_native } */
/* { dg-options "-mtls-direct-seg-refs -O2 -masm=att" } */
int*
diff --git a/gcc/testsuite/gcc.target/i386/fentryname1.c b/gcc/testsuite/gcc.target/i386/fentryname1.c
index 1265342..a9d1c72 100644
--- a/gcc/testsuite/gcc.target/i386/fentryname1.c
+++ b/gcc/testsuite/gcc.target/i386/fentryname1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target mfentry } */
+/* { dg-require-profiling "-pg" } */
/* { dg-options "-pg -mfentry -mfentry-name=foo" } */
/* { dg-final { scan-assembler "call.*foo" } } */
/* { dg-final { scan-assembler "call.*bar" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fentryname2.c b/gcc/testsuite/gcc.target/i386/fentryname2.c
index c51c5d1..13a43ec 100644
--- a/gcc/testsuite/gcc.target/i386/fentryname2.c
+++ b/gcc/testsuite/gcc.target/i386/fentryname2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target mfentry } */
+/* { dg-require-profiling "-pg" } */
/* { dg-options "-pg -mfentry -mrecord-mcount -mfentry-section=foo" } */
/* { dg-final { scan-assembler "section.*foo" } } */
/* { dg-final { scan-assembler "section.*bar" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fentryname3.c b/gcc/testsuite/gcc.target/i386/fentryname3.c
index 5688109..bd7c997 100644
--- a/gcc/testsuite/gcc.target/i386/fentryname3.c
+++ b/gcc/testsuite/gcc.target/i386/fentryname3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target mfentry } */
+/* { dg-require-profiling "-pg" } */
/* { dg-options "-pg -mfentry" } */
/* { dg-final { scan-assembler "section.*__entry_loc" } } */
/* { dg-final { scan-assembler "0x0f, 0x1f, 0x44, 0x00, 0x00" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma4-256-maccXX.c b/gcc/testsuite/gcc.target/i386/fma4-256-maccXX.c
index 134200a..ee0ddf1 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-256-maccXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-256-maccXX.c
@@ -17,7 +17,6 @@ union
double d[NUM * 4];
} dst, res, src1, src2, src3;
-
/* Note that in macc*,msub*,mnmacc* and mnsub* instructions, the intermdediate
product is not rounded, only the addition is rounded. */
@@ -56,7 +55,7 @@ check_maccps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -70,7 +69,7 @@ check_maccpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
diff --git a/gcc/testsuite/gcc.target/i386/fma4-256-msubXX.c b/gcc/testsuite/gcc.target/i386/fma4-256-msubXX.c
index d6cafb4..0251eb2 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-256-msubXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-256-msubXX.c
@@ -55,7 +55,7 @@ check_msubps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -69,7 +69,7 @@ check_msubpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
@@ -92,5 +92,4 @@ fma4_test (void)
if (check_msubpd ())
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/fma4-256-nmaccXX.c b/gcc/testsuite/gcc.target/i386/fma4-256-nmaccXX.c
index 261f302..d9671f3 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-256-nmaccXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-256-nmaccXX.c
@@ -55,7 +55,7 @@ check_nmaccps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -69,7 +69,7 @@ check_nmaccpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
@@ -92,5 +92,4 @@ fma4_test (void)
if (check_nmaccpd ())
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/fma4-256-nmsubXX.c b/gcc/testsuite/gcc.target/i386/fma4-256-nmsubXX.c
index ccbdf0e..385cd95 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-256-nmsubXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-256-nmsubXX.c
@@ -55,7 +55,7 @@ check_nmsubps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -69,7 +69,7 @@ check_nmsubpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
@@ -92,5 +92,4 @@ fma4_test (void)
if (check_nmsubpd (&dst.y[i], &src1.d[i * 2], &src2.d[i * 2], &src3.d[i * 2]))
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/fma4-maccXX.c b/gcc/testsuite/gcc.target/i386/fma4-maccXX.c
index 4b4c005..d401d4e 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-maccXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-maccXX.c
@@ -17,7 +17,6 @@ union
double d[NUM * 2];
} dst, res, src1, src2, src3;
-
/* Note that in macc*,msub*,mnmacc* and mnsub* instructions, the intermdediate
product is not rounded, only the addition is rounded. */
@@ -56,7 +55,7 @@ check_maccps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -70,7 +69,7 @@ check_maccpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
@@ -84,7 +83,7 @@ check_maccss ()
if (dst.f[i] != res.f[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -97,7 +96,7 @@ check_maccsd ()
if (dst.d[i] != res.d[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
@@ -132,5 +131,4 @@ fma4_test (void)
if (check_maccsd ())
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/fma4-msubXX.c b/gcc/testsuite/gcc.target/i386/fma4-msubXX.c
index eed7558..192cb5d 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-msubXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-msubXX.c
@@ -55,7 +55,7 @@ check_msubps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -69,10 +69,9 @@ check_msubpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
-
static int
check_msubss ()
{
@@ -83,7 +82,7 @@ check_msubss ()
if (dst.f[i] != res.f[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -96,7 +95,7 @@ check_msubsd ()
if (dst.d[i] != res.d[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
diff --git a/gcc/testsuite/gcc.target/i386/fma4-nmaccXX.c b/gcc/testsuite/gcc.target/i386/fma4-nmaccXX.c
index 9abf746..7a89fb0 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-nmaccXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-nmaccXX.c
@@ -55,7 +55,7 @@ check_nmaccps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -69,10 +69,9 @@ check_nmaccpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
-
static int
check_nmaccss ()
{
@@ -83,7 +82,7 @@ check_nmaccss ()
if (dst.f[i] != res.f[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -96,7 +95,7 @@ check_nmaccsd ()
if (dst.d[i] != res.d[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
@@ -112,7 +111,6 @@ fma4_test (void)
if (check_nmaccps ())
abort ();
-
for (i = 0; i < NUM; i++)
dst.x[i] = _mm_nmacc_ss (src1.x[i], src2.x[i], src3.x[i]);
@@ -126,12 +124,10 @@ fma4_test (void)
if (check_nmaccpd ())
abort ();
-
for (i = 0; i < NUM; i++)
dst.y[i] = _mm_nmacc_sd (src1.y[i], src2.y[i], src3.y[i]);
if (check_nmaccsd ())
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/fma4-nmsubXX.c b/gcc/testsuite/gcc.target/i386/fma4-nmsubXX.c
index 85fbecd..c0bce41 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-nmsubXX.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-nmsubXX.c
@@ -55,7 +55,7 @@ check_nmsubps ()
if (dst.f[i + j] != res.f[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -69,10 +69,9 @@ check_nmsubpd ()
if (dst.d[i + j] != res.d[i + j])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
-
static int
check_nmsubss ()
{
@@ -83,7 +82,7 @@ check_nmsubss ()
if (dst.f[i] != res.f[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -96,7 +95,7 @@ check_nmsubsd ()
if (dst.d[i] != res.d[i])
check_fails++;
}
- return check_fails++;
+ return check_fails;
}
static void
@@ -111,7 +110,6 @@ fma4_test (void)
if (check_nmsubps (&dst.x[i], &src1.f[i * 4], &src2.f[i * 4], &src3.f[i * 4]))
abort ();
-
for (i = 0; i < NUM; i++)
dst.x[i] = _mm_nmsub_ss (src1.x[i], src2.x[i], src3.x[i]);
@@ -126,12 +124,10 @@ fma4_test (void)
if (check_nmsubpd (&dst.y[i], &src1.d[i * 2], &src2.d[i * 2], &src3.d[i * 2]))
abort ();
-
for (i = 0; i < NUM; i++)
dst.y[i] = _mm_nmsub_sd (src1.y[i], src2.y[i], src3.y[i]);
if (check_nmsubsd (&dst.y[i], &src1.d[i * 2], &src2.d[i * 2], &src3.d[i * 2]))
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
index 02cdc34..5d4800f 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
@@ -76,6 +76,9 @@ extern void test_amx_int8 (void) __attribute__((__target__("amx-int8")));
extern void test_amx_bf16 (void) __attribute__((__target__("amx-bf16")));
extern void test_uintr (void) __attribute__((__target__("uintr")));
extern void test_hreset (void) __attribute__((__target__("hreset")));
+extern void test_keylocker (void) __attribute__((__target__("kl")));
+extern void test_widekl (void) __attribute__((__target__("widekl")));
+extern void test_avxvnni (void) __attribute__((__target__("avxvnni")));
extern void test_no_sgx (void) __attribute__((__target__("no-sgx")));
extern void test_no_avx5124fmaps(void) __attribute__((__target__("no-avx5124fmaps")));
@@ -153,6 +156,9 @@ extern void test_no_amx_int8 (void) __attribute__((__target__("no-amx-int8")));
extern void test_no_amx_bf16 (void) __attribute__((__target__("no-amx-bf16")));
extern void test_no_uintr (void) __attribute__((__target__("no-uintr")));
extern void test_no_hreset (void) __attribute__((__target__("no-hreset")));
+extern void test_no_keylocker (void) __attribute__((__target__("no-kl")));
+extern void test_no_widekl (void) __attribute__((__target__("no-widekl")));
+extern void test_no_avxvnni (void) __attribute__((__target__("no-avxvnni")));
extern void test_arch_nocona (void) __attribute__((__target__("arch=nocona")));
extern void test_arch_core2 (void) __attribute__((__target__("arch=core2")));
@@ -187,6 +193,9 @@ extern void test_arch_barcelona (void) __attribute__((__target__("arch=barcelon
extern void test_arch_bdver1 (void) __attribute__((__target__("arch=bdver1")));
extern void test_arch_bdver2 (void) __attribute__((__target__("arch=bdver2")));
extern void test_arch_bdver3 (void) __attribute__((__target__("arch=bdver3")));
+extern void test_arch_znver1 (void) __attribute__((__target__("arch=znver1")));
+extern void test_arch_znver2 (void) __attribute__((__target__("arch=znver2")));
+extern void test_arch_znver3 (void) __attribute__((__target__("arch=znver3")));
extern void test_tune_nocona (void) __attribute__((__target__("tune=nocona")));
extern void test_tune_core2 (void) __attribute__((__target__("tune=core2")));
@@ -206,6 +215,9 @@ extern void test_tune_bdver1 (void) __attribute__((__target__("tune=bdver1")));
extern void test_tune_bdver2 (void) __attribute__((__target__("tune=bdver2")));
extern void test_tune_bdver3 (void) __attribute__((__target__("tune=bdver3")));
extern void test_tune_generic (void) __attribute__((__target__("tune=generic")));
+extern void test_tune_znver1 (void) __attribute__((__target__("tune=znver1")));
+extern void test_tune_znver2 (void) __attribute__((__target__("tune=znver2")));
+extern void test_tune_znver3 (void) __attribute__((__target__("tune=znver3")));
extern void test_fpmath_sse (void) __attribute__((__target__("sse2,fpmath=sse")));
extern void test_fpmath_387 (void) __attribute__((__target__("sse2,fpmath=387")));
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c
new file mode 100644
index 0000000..d134612
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdec128kl.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "aesdec128kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+__m128i k1, k2;
+const char h1[48];
+
+unsigned char
+test_keylocker_1 (void)
+{
+ return _mm_aesdec128kl_u8 (&k1, k2, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c
new file mode 100644
index 0000000..34736d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdec256kl.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "aesdec256kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+__m128i k1, k2;
+const char h1[48];
+
+unsigned char
+test_keylocker_3 (void)
+{
+ return _mm_aesdec256kl_u8 (&k1, k2, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c
new file mode 100644
index 0000000..d23cf4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide128kl.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mwidekl -O2" } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*16\[^\\n\\r\]*, %xmm1" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*32\[^\\n\\r\]*, %xmm2" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*48\[^\\n\\r\]*, %xmm3" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*64\[^\\n\\r\]*, %xmm4" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*80\[^\\n\\r\]*, %xmm5" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */
+/* { dg-final { scan-assembler "aesdecwide128kl\[ \\t\]+\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm3,\[^\\n\\r\]*48\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm4,\[^\\n\\r\]*64\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+const char h1[48];
+const __m128i idata[8];
+__m128i odata[8];
+
+unsigned char
+test_keylocker_5 (void)
+{
+ return _mm_aesdecwide128kl_u8 (odata, idata, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c
new file mode 100644
index 0000000..44c3252
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesdecwide256kl.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mwidekl -O2" } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*16\[^\\n\\r\]*, %xmm1" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*32\[^\\n\\r\]*, %xmm2" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*48\[^\\n\\r\]*, %xmm3" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*64\[^\\n\\r\]*, %xmm4" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*80\[^\\n\\r\]*, %xmm5" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */
+/* { dg-final { scan-assembler "aesdecwide256kl\[ \\t\]+\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm3,\[^\\n\\r\]*48\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm4,\[^\\n\\r\]*64\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+const char h1[48];
+const __m128i idata[8];
+__m128i odata[8];
+
+unsigned char
+test_keylocker_6 (void)
+{
+ return _mm_aesdecwide256kl_u8 (odata, idata, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c
new file mode 100644
index 0000000..9ff4836
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesenc128kl.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "aesenc128kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+__m128i k1, k2;
+const char h1[48];
+
+unsigned char
+test_keylocker_2 (void)
+{
+ return _mm_aesenc128kl_u8 (&k1, k2, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c
new file mode 100644
index 0000000..1c5e076
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesenc256kl.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "aesenc256kl\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+__m128i k1, k2;
+const char h1[48];
+
+unsigned char
+test_keylocker_4 (void)
+{
+ return _mm_aesenc256kl_u8 (&k1, k2, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c
new file mode 100644
index 0000000..9fb9c49
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide128kl.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mwidekl -O2" } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*16\[^\\n\\r\]*, %xmm1" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*32\[^\\n\\r\]*, %xmm2" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*48\[^\\n\\r\]*, %xmm3" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*64\[^\\n\\r\]*, %xmm4" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*80\[^\\n\\r\]*, %xmm5" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */
+/* { dg-final { scan-assembler "aesencwide128kl\[ \\t\]+\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm3,\[^\\n\\r\]*48\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm4,\[^\\n\\r\]*64\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+const char h1[48];
+const __m128i idata[8];
+__m128i odata[8];
+
+unsigned char
+test_keylocker_7 (void)
+{
+ return _mm_aesencwide128kl_u8 (odata, idata, h1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c
new file mode 100644
index 0000000..125a787
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-aesencwide256kl.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-mwidekl -O2" } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*16\[^\\n\\r\]*, %xmm1" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*32\[^\\n\\r\]*, %xmm2" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*48\[^\\n\\r\]*, %xmm3" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*64\[^\\n\\r\]*, %xmm4" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*80\[^\\n\\r\]*, %xmm5" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*96\[^\\n\\r\]*, %xmm6" } } */
+/* { dg-final { scan-assembler "movdqu\[ \\t\]+\[^\\n\\r\]*112\[^\\n\\r\]*, %xmm7" } } */
+/* { dg-final { scan-assembler "aesencwide256kl\[ \\t\]+\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm0,\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm3,\[^\\n\\r\]*48\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm4,\[^\\n\\r\]*64\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm5,\[^\\n\\r\]*80\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm6,\[^\\n\\r\]*96\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\\r\]*%xmm7,\[^\\n\\r\]*112\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+const char h1[48];
+const __m128i idata[8];
+__m128i odata[8];
+
+unsigned char
+test_keylocker_8 (void)
+{
+ return _mm_aesencwide256kl_u8 (odata, idata, h1);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c b/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c
new file mode 100644
index 0000000..805e062
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-encodekey128.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+\[^\\n\\r\]*, %eax" } } */
+/* { dg-final { scan-assembler "encodekey128\[ \\t\]+\[^\\n\]*%eax\[^\\n\\r\]*%eax" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm0,\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqa|movaps)\[ \\t\]+\[^\\n\]*%xmm\[4-6\],\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+unsigned int ctrl;
+char h2[48];
+__m128i k1, k2;
+
+unsigned int
+test_keylocker_9 (void)
+{
+ unsigned int ret;
+
+ ret = _mm_encodekey128_u32 (ctrl, k1, h2);
+
+ if (ret)
+ k2 = (__m128i){0};
+
+ return ret;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c b/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c
new file mode 100644
index 0000000..26f04dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-encodekey256.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm0" } } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\\n\\r\]*, %xmm1" } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+\[^\\n\\r\]*, %eax" } } */
+/* { dg-final { scan-assembler "encodekey256\[ \\t\]+\[^\\n\]*%eax\[^\\n\\r\]*%eax" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm0,\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm1,\[^\\n\\r\]*16\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm2,\[^\\n\\r\]*32\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqu|movups)\[ \\t\]+\[^\\n\]*%xmm3,\[^\\n\\r\]*48\[^\\n\\r\]*" } } */
+/* { dg-final { scan-assembler "(?:movdqa|movaps)\[ \\t\]+\[^\\n\]*%xmm\[4-6\],\[^\\n\\r\]*" } } */
+
+#include <immintrin.h>
+
+unsigned int ctrl;
+char h2[48];
+__m128i k1, k2, k3;
+
+unsigned int
+test_keylocker_10 (void)
+{
+ unsigned int ret;
+ ret = _mm_encodekey256_u32 (ctrl, k1, k2, h2);
+
+ if (ret)
+ k3 = (__m128i){0};
+
+ return ret;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/keylocker-loadiwkey.c b/gcc/testsuite/gcc.target/i386/keylocker-loadiwkey.c
new file mode 100644
index 0000000..cc0f2e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/keylocker-loadiwkey.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-mkl -O2" } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+\[^\n\]*ctrl(\\(%rip\\))?\[^\n\r]*%eax" } } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\n\]*k2(\\(%rip\\))?\[^\n\r]*%xmm1" } } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\n\]*k3(\\(%rip\\))?\[^\n\r]*%xmm2" } } */
+/* { dg-final { scan-assembler "movdqa\[ \\t\]+\[^\n\]*k1(\\(%rip\\))?\[^\n\r]*%xmm0" } } */
+/* { dg-final { scan-assembler "loadiwkey\[ \\t\]+\[^\n\]*%xmm1\[^\n\r]*%xmm2" } } */
+
+#include <immintrin.h>
+
+unsigned int ctrl;
+__m128i k1, k2, k3;
+
+void
+test_keylocker_11 (void)
+{
+ _mm_loadiwkey (ctrl, k1, k2, k3);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c b/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
index e11bcc0..12e54c0 100644
--- a/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
+++ b/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
@@ -4,6 +4,8 @@
/* { dg-require-effective-target ms_hook_prologue } */
/* { dg-options "-O2 -fomit-frame-pointer" } */
+#include <stdio.h>
+
int __attribute__ ((__ms_hook_prologue__)) foo ()
{
unsigned char *ptr = (unsigned char *) foo;
@@ -32,7 +34,16 @@ int __attribute__ ((__ms_hook_prologue__)) foo ()
return 0;
}
+unsigned int __attribute__ ((noinline, __ms_hook_prologue__)) test_func()
+{
+ static int value;
+
+ if (value++) puts("");
+
+ return 0;
+}
+
int main ()
{
- return foo();
+ return foo() || test_func();
}
diff --git a/gcc/testsuite/gcc.target/i386/pr31799.c b/gcc/testsuite/gcc.target/i386/pr31799.c
new file mode 100644
index 0000000..c72c4ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr31799.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (int x, int *y, int *z)
+{
+ *z = ++x;
+ if (x != 0)
+ *y = 1;
+}
+
+/* { dg-final { scan-assembler-not "test" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr45352-1.c b/gcc/testsuite/gcc.target/i386/pr45352-1.c
index 5cd1bd8..f5e96b2 100644
--- a/gcc/testsuite/gcc.target/i386/pr45352-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr45352-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-mtune=amdfam10 -O3 -fpeel-loops -fselective-scheduling2 -fsel-sched-pipelining -fPIC" } */
static int FIR_Tab_16[16][16];
diff --git a/gcc/testsuite/gcc.target/i386/pr47602.c b/gcc/testsuite/gcc.target/i386/pr47602.c
index fa5f5bd..5ed1e1f 100644
--- a/gcc/testsuite/gcc.target/i386/pr47602.c
+++ b/gcc/testsuite/gcc.target/i386/pr47602.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target ia32 } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-fPIC" } */
/* Test verifies that %ebx is no longer fixed when generating PIC code on i686. */
diff --git a/gcc/testsuite/gcc.target/i386/pr55151.c b/gcc/testsuite/gcc.target/i386/pr55151.c
index 62da8cb..d6255a8 100644
--- a/gcc/testsuite/gcc.target/i386/pr55151.c
+++ b/gcc/testsuite/gcc.target/i386/pr55151.c
@@ -1,5 +1,6 @@
/* PR rtl-optimization/55151 */
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-fPIC" } */
int a, b, c, d, e, f, g, h, i, j, k, l;
diff --git a/gcc/testsuite/gcc.target/i386/pr55458.c b/gcc/testsuite/gcc.target/i386/pr55458.c
index 7164ca9..1dea55c 100644
--- a/gcc/testsuite/gcc.target/i386/pr55458.c
+++ b/gcc/testsuite/gcc.target/i386/pr55458.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target ia32 } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-fPIC" } */
/* Test verifies that %ebx is no longer fixed when generating PIC code on i686. */
diff --git a/gcc/testsuite/gcc.target/i386/pr56348.c b/gcc/testsuite/gcc.target/i386/pr56348.c
index c31814f..93423d9 100644
--- a/gcc/testsuite/gcc.target/i386/pr56348.c
+++ b/gcc/testsuite/gcc.target/i386/pr56348.c
@@ -1,5 +1,6 @@
/* PR target/56348 */
/* { dg-do compile { target ia32 } } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fPIC -mfpmath=sse -msse2" } */
typedef unsigned int size_t;
diff --git a/gcc/testsuite/gcc.target/i386/pr57097.c b/gcc/testsuite/gcc.target/i386/pr57097.c
index 2f00938..debacbf 100644
--- a/gcc/testsuite/gcc.target/i386/pr57097.c
+++ b/gcc/testsuite/gcc.target/i386/pr57097.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fPIC" } */
extern double ad[], bd[], cd[], dd[];
extern long long all[], bll[], cll[], dll[];
diff --git a/gcc/testsuite/gcc.target/i386/pr65753.c b/gcc/testsuite/gcc.target/i386/pr65753.c
index 562f54b..117d6ed 100644
--- a/gcc/testsuite/gcc.target/i386/pr65753.c
+++ b/gcc/testsuite/gcc.target/i386/pr65753.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-fPIC -O2" } */
/* { dg-final { scan-assembler-not "call" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65915.c b/gcc/testsuite/gcc.target/i386/pr65915.c
index 990c5aa..6588de4 100644
--- a/gcc/testsuite/gcc.target/i386/pr65915.c
+++ b/gcc/testsuite/gcc.target/i386/pr65915.c
@@ -1,4 +1,5 @@
/* { dg-do run } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -mavx512f -fpic -mcmodel=medium" } */
/* { dg-require-effective-target avx512f } */
/* { dg-require-effective-target lp64 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-5.c b/gcc/testsuite/gcc.target/i386/pr66232-5.c
index 87f9380..76705a5 100644
--- a/gcc/testsuite/gcc.target/i386/pr66232-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr66232-5.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-require-effective-target maybe_x32 } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fpic -mx32" } */
extern void (*bar) (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr66334.c b/gcc/testsuite/gcc.target/i386/pr66334.c
index 97dfecc..19c2396 100644
--- a/gcc/testsuite/gcc.target/i386/pr66334.c
+++ b/gcc/testsuite/gcc.target/i386/pr66334.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target ia32 } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fpic -fexceptions -fasynchronous-unwind-tables" } */
/* { dg-final { scan-assembler "movl\[ \\t\].+, %ebx" } } */
extern int foo (int);
diff --git a/gcc/testsuite/gcc.target/i386/pr66819-2.c b/gcc/testsuite/gcc.target/i386/pr66819-2.c
index 9de4f97..ad2a33e 100644
--- a/gcc/testsuite/gcc.target/i386/pr66819-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr66819-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target ia32 } } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-fPIC -O2 -mregparm=3" } */
/* { dg-final { scan-assembler-not "call" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67265.c b/gcc/testsuite/gcc.target/i386/pr67265.c
index 2671acc..1708d53 100644
--- a/gcc/testsuite/gcc.target/i386/pr67265.c
+++ b/gcc/testsuite/gcc.target/i386/pr67265.c
@@ -3,6 +3,7 @@
/* { dg-do compile } */
/* { dg-require-stack-check "" } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O -fstack-check -fPIC" } */
int a, b, c, d, e;
diff --git a/gcc/testsuite/gcc.target/i386/pr78102.c b/gcc/testsuite/gcc.target/i386/pr78102.c
index 0fc3326..60abddc 100644
--- a/gcc/testsuite/gcc.target/i386/pr78102.c
+++ b/gcc/testsuite/gcc.target/i386/pr78102.c
@@ -1,7 +1,7 @@
/* PR target/78102 */
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse4.2 -msse4.1" } */
-/* { dg-final { scan-assembler-times "pcmpeqq" 3 } } */
+/* { dg-final { scan-assembler-times "pcmpeq" 4 } } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr79804.c b/gcc/testsuite/gcc.target/i386/pr79804.c
index 08d1a3e..fcfcef7 100644
--- a/gcc/testsuite/gcc.target/i386/pr79804.c
+++ b/gcc/testsuite/gcc.target/i386/pr79804.c
@@ -4,7 +4,7 @@
void foo (void)
{
- register int r19 asm ("19");
+ register int r19 asm ("19"); /* { dg-error "register specified for 'r19' is an internal GCC implementation detail" } */
- asm volatile ("# %0" : "=r"(r19)); /* { dg-error "invalid use of register" } */
-} /* { dg-error "cannot be used in 'asm' here" } */
+ asm volatile ("# %0" : "=r"(r19));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81481.c b/gcc/testsuite/gcc.target/i386/pr81481.c
index a5b936f..49f7821 100644
--- a/gcc/testsuite/gcc.target/i386/pr81481.c
+++ b/gcc/testsuite/gcc.target/i386/pr81481.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target ssse3 } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fpic -mssse3" } */
/* { dg-final { scan-assembler-not "pshufb\[ \t\]\\(%esp\\)" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr83994.c b/gcc/testsuite/gcc.target/i386/pr83994.c
index dc0b7cb..1eb47e3 100644
--- a/gcc/testsuite/gcc.target/i386/pr83994.c
+++ b/gcc/testsuite/gcc.target/i386/pr83994.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -march=i686 -fpic -fstack-clash-protection" } */
/* { dg-require-effective-target ia32 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr88178.c b/gcc/testsuite/gcc.target/i386/pr88178.c
index a5fbd35..622e1c2 100644
--- a/gcc/testsuite/gcc.target/i386/pr88178.c
+++ b/gcc/testsuite/gcc.target/i386/pr88178.c
@@ -4,5 +4,5 @@
void foo (void)
{
- register int r19 asm ("19");
+ register int r19 asm ("19"); /* { dg-error "register specified for 'r19' is an internal GCC implementation detail" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/pr92180.c b/gcc/testsuite/gcc.target/i386/pr92180.c
new file mode 100644
index 0000000..177af74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92180.c
@@ -0,0 +1,9 @@
+/* PR rtl-optimization/92180 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned int foo() {
+ return __builtin_ia32_rdtsc();
+}
+
+/* { dg-final { scan-assembler-not "sal" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92469.c b/gcc/testsuite/gcc.target/i386/pr92469.c
new file mode 100644
index 0000000..8cff36b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92469.c
@@ -0,0 +1,24 @@
+/* PR target/92469 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+void
+foo (void)
+{
+ register int x asm ("frame"); /* { dg-error "register specified for 'x' is an internal GCC implementation detail" } */
+ int y = x;
+}
+
+void
+bar (void)
+{
+ register int x asm ("19"); /* { dg-error "register specified for 'x' is an internal GCC implementation detail" } */
+ int y = x;
+}
+
+void
+baz (void)
+{
+ register int x asm ("argp"); /* { dg-error "register specified for 'x' is an internal GCC implementation detail" } */
+ int y = x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx2-2.c b/gcc/testsuite/gcc.target/i386/pr92658-avx2-2.c
new file mode 100644
index 0000000..7aad858
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92658-avx2-2.c
@@ -0,0 +1,192 @@
+/* PR target/92658 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -mavx2" } */
+
+typedef char v32qi __attribute__((vector_size (32)));
+typedef short v16hi __attribute__((vector_size (32)));
+typedef int v8si __attribute__((vector_size (32)));
+typedef long long v4di __attribute__((vector_size (32)));
+
+void
+foo_s8_s16 (v16hi * dst, v32qi * __restrict src)
+{
+ short tem[16];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ tem[8] = (*src)[8];
+ tem[9] = (*src)[9];
+ tem[10] = (*src)[10];
+ tem[11] = (*src)[11];
+ tem[12] = (*src)[12];
+ tem[13] = (*src)[13];
+ tem[14] = (*src)[14];
+ tem[15] = (*src)[15];
+ dst[0] = *(v16hi *) tem;
+}
+
+void
+bar_s8_s16 (v16hi * dst, v32qi src)
+{
+ short tem[16];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ tem[8] = src[8];
+ tem[9] = src[9];
+ tem[10] = src[10];
+ tem[11] = src[11];
+ tem[12] = src[12];
+ tem[13] = src[13];
+ tem[14] = src[14];
+ tem[15] = src[15];
+ dst[0] = *(v16hi *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbw" 2 } } */
+
+void
+foo_s8_s32 (v8si * dst, v32qi * __restrict src)
+{
+ int tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v8si *) tem;
+}
+
+void
+bar_s8_s32 (v8si * dst, v32qi src)
+{
+ int tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v8si *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbd" 2 } } */
+
+void
+foo_s8_s64 (v4di * dst, v32qi * __restrict src)
+{
+ long long tem[4];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ dst[0] = *(v4di *) tem;
+}
+
+void
+bar_s8_s64 (v4di * dst, v32qi src)
+{
+ long long tem[4];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ dst[0] = *(v4di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbq" 2 { xfail *-*-* } } } */
+
+void
+foo_s16_s32 (v8si * dst, v16hi * __restrict src)
+{
+ int tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v8si *) tem;
+}
+
+void
+bar_s16_s32 (v8si * dst, v16hi src)
+{
+ int tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v8si *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxwd" 2 } } */
+
+void
+foo_s16_s64 (v4di * dst, v16hi * __restrict src)
+{
+ long long tem[4];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ dst[0] = *(v4di *) tem;
+}
+
+void
+bar_s16_s64 (v4di * dst, v16hi src)
+{
+ long long tem[4];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ dst[0] = *(v4di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxwq" 2 } } */
+
+void
+foo_s32_s64 (v4di * dst, v8si * __restrict src)
+{
+ long long tem[4];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ dst[0] = *(v4di *) tem;
+}
+
+void
+bar_s32_s64 (v4di * dst, v8si src)
+{
+ long long tem[4];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ dst[0] = *(v4di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxdq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-avx512bw-2.c b/gcc/testsuite/gcc.target/i386/pr92658-avx512bw-2.c
new file mode 100644
index 0000000..811f21a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92658-avx512bw-2.c
@@ -0,0 +1,280 @@
+/* PR target/92658 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -mavx512bw" } */
+
+typedef char v64qi __attribute__((vector_size (64)));
+typedef short v32hi __attribute__((vector_size (64)));
+typedef int v16si __attribute__((vector_size (64)));
+typedef long long v8di __attribute__((vector_size (64)));
+
+void
+foo_s8_s16 (v32hi * dst, v64qi * __restrict src)
+{
+ short tem[32];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ tem[8] = (*src)[8];
+ tem[9] = (*src)[9];
+ tem[10] = (*src)[10];
+ tem[11] = (*src)[11];
+ tem[12] = (*src)[12];
+ tem[13] = (*src)[13];
+ tem[14] = (*src)[14];
+ tem[15] = (*src)[15];
+ tem[16] = (*src)[16];
+ tem[17] = (*src)[17];
+ tem[18] = (*src)[18];
+ tem[19] = (*src)[19];
+ tem[20] = (*src)[20];
+ tem[21] = (*src)[21];
+ tem[22] = (*src)[22];
+ tem[23] = (*src)[23];
+ tem[24] = (*src)[24];
+ tem[25] = (*src)[25];
+ tem[26] = (*src)[26];
+ tem[27] = (*src)[27];
+ tem[28] = (*src)[28];
+ tem[29] = (*src)[29];
+ tem[30] = (*src)[30];
+ tem[31] = (*src)[31];
+ dst[0] = *(v32hi *) tem;
+}
+
+void
+bar_s8_s16 (v32hi * dst, v64qi src)
+{
+ short tem[32];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ tem[8] = src[8];
+ tem[9] = src[9];
+ tem[10] = src[10];
+ tem[11] = src[11];
+ tem[12] = src[12];
+ tem[13] = src[13];
+ tem[14] = src[14];
+ tem[15] = src[15];
+ tem[16] = src[16];
+ tem[17] = src[17];
+ tem[18] = src[18];
+ tem[19] = src[19];
+ tem[20] = src[20];
+ tem[21] = src[21];
+ tem[22] = src[22];
+ tem[23] = src[23];
+ tem[24] = src[24];
+ tem[25] = src[25];
+ tem[26] = src[26];
+ tem[27] = src[27];
+ tem[28] = src[28];
+ tem[29] = src[29];
+ tem[30] = src[30];
+ tem[31] = src[31];
+ dst[0] = *(v32hi *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbw" 2 } } */
+
+void
+foo_s8_s32 (v16si * dst, v64qi * __restrict src)
+{
+ int tem[16];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ tem[8] = (*src)[8];
+ tem[9] = (*src)[9];
+ tem[10] = (*src)[10];
+ tem[11] = (*src)[11];
+ tem[12] = (*src)[12];
+ tem[13] = (*src)[13];
+ tem[14] = (*src)[14];
+ tem[15] = (*src)[15];
+ dst[0] = *(v16si *) tem;
+}
+
+void
+bar_s8_s32 (v16si * dst, v64qi src)
+{
+ int tem[16];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ tem[8] = src[8];
+ tem[9] = src[9];
+ tem[10] = src[10];
+ tem[11] = src[11];
+ tem[12] = src[12];
+ tem[13] = src[13];
+ tem[14] = src[14];
+ tem[15] = src[15];
+ dst[0] = *(v16si *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbd" 2 } } */
+
+void
+foo_s8_s64 (v8di * dst, v64qi * __restrict src)
+{
+ long long tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v8di *) tem;
+}
+
+void
+bar_s8_s64 (v8di * dst, v64qi src)
+{
+ long long tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v8di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbq" 2 } } */
+
+void
+foo_s16_s32 (v16si * dst, v32hi * __restrict src)
+{
+ int tem[16];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ tem[8] = (*src)[8];
+ tem[9] = (*src)[9];
+ tem[10] = (*src)[10];
+ tem[11] = (*src)[11];
+ tem[12] = (*src)[12];
+ tem[13] = (*src)[13];
+ tem[14] = (*src)[14];
+ tem[15] = (*src)[15];
+ dst[0] = *(v16si *) tem;
+}
+
+void
+bar_s16_s32 (v16si * dst, v32hi src)
+{
+ int tem[16];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ tem[8] = src[8];
+ tem[9] = src[9];
+ tem[10] = src[10];
+ tem[11] = src[11];
+ tem[12] = src[12];
+ tem[13] = src[13];
+ tem[14] = src[14];
+ tem[15] = src[15];
+ dst[0] = *(v16si *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxwd" 2 } } */
+
+void
+foo_s16_s64 (v8di * dst, v32hi * __restrict src)
+{
+ long long tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v8di *) tem;
+}
+
+void
+bar_s16_s64 (v8di * dst, v32hi src)
+{
+ long long tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v8di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxwq" 2 } } */
+
+void
+foo_s32_s64 (v8di * dst, v16si * __restrict src)
+{
+ long long tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v8di *) tem;
+}
+
+void
+bar_s32_s64 (v8di * dst, v16si src)
+{
+ long long tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v8di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxdq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92658-sse4-2.c b/gcc/testsuite/gcc.target/i386/pr92658-sse4-2.c
new file mode 100644
index 0000000..ca174ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92658-sse4-2.c
@@ -0,0 +1,148 @@
+/* PR target/92658 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse4.1" } */
+
+typedef char v16qi __attribute__((vector_size (16)));
+typedef short v8hi __attribute__((vector_size (16)));
+typedef int v4si __attribute__((vector_size (16)));
+typedef long long v2di __attribute__((vector_size (16)));
+
+void
+foo_s8_s16 (v8hi * dst, v16qi * __restrict src)
+{
+ short tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v8hi *) tem;
+}
+
+void
+bar_s8_s16 (v8hi * dst, v16qi src)
+{
+ short tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v8hi *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbw" 2 } } */
+
+void
+foo_s8_s32 (v4si * dst, v16qi * __restrict src)
+{
+ int tem[4];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ dst[0] = *(v4si *) tem;
+}
+
+void
+bar_s8_s32 (v4si * dst, v16qi src)
+{
+ int tem[4];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ dst[0] = *(v4si *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbd" 2 { xfail *-*-* } } } */
+
+void
+foo_s8_s64 (v2di * dst, v16qi * __restrict src)
+{
+ long long tem[2];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ dst[0] = *(v2di *) tem;
+}
+
+void
+bar_s8_s64 (v2di * dst, v16qi src)
+{
+ long long tem[2];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ dst[0] = *(v2di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxbq" 2 { xfail *-*-* } } } */
+
+void
+foo_s16_s32 (v4si * dst, v8hi * __restrict src)
+{
+ int tem[4];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ dst[0] = *(v4si *) tem;
+}
+
+void
+bar_s16_s32 (v4si * dst, v8hi src)
+{
+ int tem[4];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ dst[0] = *(v4si *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxwd" 2 } } */
+
+void
+foo_s16_s64 (v2di * dst, v8hi * __restrict src)
+{
+ long long tem[2];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ dst[0] = *(v2di *) tem;
+}
+
+void
+bar_s16_s64 (v2di * dst, v8hi src)
+{
+ long long tem[2];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ dst[0] = *(v2di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxwq" 2 { xfail *-*-* } } } */
+
+void
+foo_s32_s64 (v2di * dst, v4si * __restrict src)
+{
+ long long tem[2];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ dst[0] = *(v2di *) tem;
+}
+
+void
+bar_s32_s64 (v2di * dst, v4si src)
+{
+ long long tem[2];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ dst[0] = *(v2di *) tem;
+}
+
+/* { dg-final { scan-assembler-times "pmovsxdq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr94440-1.c b/gcc/testsuite/gcc.target/i386/pr94440-1.c
new file mode 100644
index 0000000..c18b16b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr94440-1.c
@@ -0,0 +1,23 @@
+/* PR target/94440 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-mfpmath=sse,387 -msse2 -Ofast -fexcess-precision=standard -fno-graphite --param=scev-max-expr-size=0" } */
+
+int b;
+double c, d;
+
+void
+foo (void)
+{
+ int i;
+ for (i = 0; i < b; i++)
+ c += i;
+}
+
+int __attribute__((optimize(1)))
+main ()
+{
+ double a[9];
+ int i;
+ for (i = 0; i < 9; i++)
+ d += a[i];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr94440-2.c b/gcc/testsuite/gcc.target/i386/pr94440-2.c
new file mode 100644
index 0000000..3ac78e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr94440-2.c
@@ -0,0 +1,19 @@
+/* PR target/94440 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -msse2 -ffast-math" } */
+
+double a;
+int b;
+long double c;
+
+void
+foo (void)
+{
+ float d = (double)(long double)b;
+}
+
+__attribute__((optimize("O0"))) void
+bar (void)
+{
+ a = c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr95151-1.c b/gcc/testsuite/gcc.target/i386/pr95151-1.c
new file mode 100644
index 0000000..54a7510
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95151-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -minline-all-stringops" } */
+
+struct foo
+{
+ char array[257];
+};
+
+extern struct foo x;
+
+int
+func (struct foo i)
+{
+ return __builtin_memcmp (&x, &i, sizeof (x)) ? 1 : 2;
+}
+
+/* { dg-final { scan-assembler-not "call\[\\t \]*_?memcmp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95151-2.c b/gcc/testsuite/gcc.target/i386/pr95151-2.c
new file mode 100644
index 0000000..8f9d8ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95151-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -minline-all-stringops" } */
+
+int
+func (void *d, void *s, unsigned int l)
+{
+ return __builtin_memcmp (d, s, l) ? 1 : 2;
+}
+
+/* { dg-final { scan-assembler-not "call\[\\t \]*_?memcmp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95151-3.c b/gcc/testsuite/gcc.target/i386/pr95151-3.c
new file mode 100644
index 0000000..14cbdec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95151-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-inline-all-stringops" } */
+
+struct foo
+{
+ char array[257];
+};
+
+extern struct foo x;
+
+int
+func (struct foo i)
+{
+ return __builtin_memcmp (&x, &i, sizeof (x)) ? 1 : 2;
+}
+
+/* { dg-final { scan-assembler "call\[\\t \]*_?memcmp" } } */
+/* { dg-final { scan-assembler-not "cmpsb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95151-4.c b/gcc/testsuite/gcc.target/i386/pr95151-4.c
new file mode 100644
index 0000000..c93b2b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95151-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-inline-all-stringops" } */
+
+int
+func (void *d, void *s, unsigned int l)
+{
+ return __builtin_memcmp (d, s, l) ? 1 : 2;
+}
+
+/* { dg-final { scan-assembler "call\[\\t \]*_?memcmp" } } */
+/* { dg-final { scan-assembler-not "cmpsb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95458-1.c b/gcc/testsuite/gcc.target/i386/pr95458-1.c
new file mode 100644
index 0000000..231a478
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95458-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -minline-all-stringops" } */
+
+int
+func (char *d, unsigned int l)
+{
+ return __builtin_strncmp (d, "foo", l) ? 1 : 2;
+}
+
+/* { dg-final { scan-assembler-not "call\[\\t \]*_?strncmp" } } */
+/* { dg-final { scan-assembler "cmpsb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95458-2.c b/gcc/testsuite/gcc.target/i386/pr95458-2.c
new file mode 100644
index 0000000..1a62044
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95458-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-inline-all-stringops" } */
+
+#include "pr95458-1.c"
+
+/* { dg-final { scan-assembler "call\[\\t \]*_?strncmp" } } */
+/* { dg-final { scan-assembler-not "cmpsb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95866-1.c b/gcc/testsuite/gcc.target/i386/pr95866-1.c
index 991370c..553d415 100644
--- a/gcc/testsuite/gcc.target/i386/pr95866-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr95866-1.c
@@ -13,6 +13,6 @@ void foo(int i)
/* We should not use vector operations for i + 1 and (i + 1) & 31 but
instead use { j, j, j, j }. */
-/* { dg-final { scan-tree-dump-times "Building parent vector operands from scalars" 2 "slp2" } } */
+/* { dg-final { scan-tree-dump-times "Using a splat of the uniform operand" 2 "slp2" } } */
/* { dg-final { scan-tree-dump-not " = \{i_" "slp2" } } */
/* { dg-final { scan-tree-dump-times " = \{j_" 1 "slp2" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96226.c b/gcc/testsuite/gcc.target/i386/pr96226.c
new file mode 100644
index 0000000..cc010fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96226.c
@@ -0,0 +1,16 @@
+/* PR target/96226 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "\troll\t" 4 } } */
+/* { dg-final { scan-assembler-times "\trolq\t" 4 { target { ! ia32 } } } } */
+
+int f1 (int x) { return ~(1U << (x & 0x1f)); }
+int f2 (int x) { return ~(1U << x); }
+int f3 (unsigned char *x) { return ~(1U << (x[0] & 0x1f)); }
+int f4 (unsigned char *x) { return ~(1U << x[0]); }
+#ifdef __x86_64__
+long int f5 (int x) { return ~(1ULL << (x & 0x3f)); }
+long int f6 (int x) { return ~(1ULL << x); }
+long int f7 (unsigned char *x) { return ~(1ULL << (x[0] & 0x3f)); }
+long int f8 (unsigned char *x) { return ~(1ULL << x[0]); }
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/pr96793-1.c b/gcc/testsuite/gcc.target/i386/pr96793-1.c
new file mode 100644
index 0000000..b205d39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96793-1.c
@@ -0,0 +1,28 @@
+/* PR target/96793 */
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-require-effective-target fenv } */
+/* { dg-options "-O2 -frounding-math -msse2 -mno-sse4 -mfpmath=sse" } */
+
+#include <fenv.h>
+
+double
+__attribute__((noinline))
+test (double value)
+{
+ return __builtin_trunc (value);
+}
+
+int
+main ()
+{
+ double result;
+
+ fesetround (FE_DOWNWARD);
+
+ result = test (0.25);
+
+ if (__builtin_signbit (result) != 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr96793-2.c b/gcc/testsuite/gcc.target/i386/pr96793-2.c
new file mode 100644
index 0000000..14efaab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96793-2.c
@@ -0,0 +1,28 @@
+/* PR target/96793 */
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-require-effective-target fenv } */
+/* { dg-options "-O2 -frounding-math -msse2 -mno-sse4 -mfpmath=sse" } */
+
+#include <fenv.h>
+
+double
+__attribute__((noinline))
+test (double value)
+{
+ return __builtin_rint (value);
+}
+
+int
+main ()
+{
+ double result;
+
+ fesetround (FE_DOWNWARD);
+
+ result = test (0.25);
+
+ if (__builtin_signbit (result) != 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr96793.c b/gcc/testsuite/gcc.target/i386/pr96793.c
new file mode 100644
index 0000000..4a96478
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96793.c
@@ -0,0 +1,28 @@
+/* PR target/96793 */
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-require-effective-target fenv } */
+/* { dg-options "-O2 -frounding-math -msse2 -mno-sse4 -mfpmath=sse" } */
+
+#include <fenv.h>
+
+double
+__attribute__((noinline))
+test (double value)
+{
+ return __builtin_floor (value);
+}
+
+int
+main ()
+{
+ double result;
+
+ fesetround (FE_DOWNWARD);
+
+ result = test (0.25);
+
+ if (__builtin_signbit (result) != 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr96906-1.c b/gcc/testsuite/gcc.target/i386/pr96906-1.c
new file mode 100644
index 0000000..b1b41bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96906-1.c
@@ -0,0 +1,62 @@
+/* PR target/96906 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2 -mno-avx512f" } */
+/* { dg-final { scan-assembler-times "\tvpminub\[^\n\r]*xmm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpminuw\[^\n\r]*xmm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpminub\[^\n\r]*ymm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpminuw\[^\n\r]*ymm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpcmpeqb\[^\n\r]*xmm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpcmpeqw\[^\n\r]*xmm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpcmpeqb\[^\n\r]*ymm" 2 } } */
+/* { dg-final { scan-assembler-times "\tvpcmpeqw\[^\n\r]*ymm" 2 } } */
+/* { dg-final { scan-assembler-not "\tvpsubus\[bw]" } } */
+
+#include <x86intrin.h>
+
+__m128i
+f1 (__m128i x, __m128i y)
+{
+ return _mm_cmpeq_epi16 (_mm_subs_epu16 (x, y), _mm_setzero_si128 ());
+}
+
+__m128i
+f2 (__m128i x, __m128i y)
+{
+ return _mm_cmpeq_epi16 (_mm_min_epu16 (x, y), x);
+}
+
+__m128i
+f3 (__m128i x, __m128i y)
+{
+ return _mm_cmpeq_epi8 (_mm_subs_epu8 (x, y), _mm_setzero_si128 ());
+}
+
+__m128i
+f4 (__m128i x, __m128i y)
+{
+ return _mm_cmpeq_epi8 (_mm_min_epu8 (x, y), x);
+}
+
+__m256i
+f5 (__m256i x, __m256i y)
+{
+ return _mm256_cmpeq_epi16 (_mm256_subs_epu16 (x, y), _mm256_setzero_si256 ());
+}
+
+__m256i
+f6 (__m256i x, __m256i y)
+{
+ return _mm256_cmpeq_epi16 (_mm256_min_epu16 (x, y), x);
+}
+
+__m256i
+f7 (__m256i x, __m256i y)
+{
+ return _mm256_cmpeq_epi8 (_mm256_subs_epu8 (x, y), _mm256_setzero_si256 ());
+}
+
+__m256i
+f8 (__m256i x, __m256i y)
+{
+ return _mm256_cmpeq_epi8 (_mm256_min_epu8 (x, y), x);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97140.c b/gcc/testsuite/gcc.target/i386/pr97140.c
new file mode 100644
index 0000000..edb39d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97140.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-mmx -Wno-psabi" } */
+
+typedef int __m64 __attribute__ ((__vector_size__ (8), __may_alias__));
+typedef char __v8qi __attribute__ ((__vector_size__ (8)));
+void
+_mm_maskmove_si64 (__m64 __A, __m64 __N, char *__P)
+{
+ __builtin_ia32_maskmovq ((__v8qi)__A, (__v8qi)__N, __P); /* { dg-error "needs isa option -msse -m3dnowa -mmmx" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97282.c b/gcc/testsuite/gcc.target/i386/pr97282.c
index 6fb10c8..94ce50b 100644
--- a/gcc/testsuite/gcc.target/i386/pr97282.c
+++ b/gcc/testsuite/gcc.target/i386/pr97282.c
@@ -18,8 +18,8 @@ foo (T x)
unsigned long ret = 0;
while (x > 0)
{
- ret = ret + x % 10;
- x = x / 10;
+ ret = ret + x % 123456;
+ x = x / 123456;
}
return ret;
}
diff --git a/gcc/testsuite/gcc.target/i386/pr97521.c b/gcc/testsuite/gcc.target/i386/pr97521.c
new file mode 100644
index 0000000..804ffd6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97521.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-O -mno-sse2" } */
+
+typedef unsigned char __attribute__ ((__vector_size__ (8))) V;
+typedef unsigned long long __attribute__ ((__vector_size__ (16))) W;
+
+V c;
+W d, e;
+
+V
+foo (W f)
+{
+ W g = (W) { 0, 209 } <7 <= (0 < f);
+ W h = e + g + d;
+ V j = (V) (h[0]) + (V) c;
+ return j;
+}
+
+int
+main (void)
+{
+ V x = foo ((W) { 3 });
+ for (unsigned i = 0; i < sizeof (x); i++)
+ if (x[i] != 0xff)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97540.c b/gcc/testsuite/gcc.target/i386/pr97540.c
new file mode 100644
index 0000000..20f8717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97540.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int mt7615_add_interface_dev_0;
+int ffs(int x) { asm("" : : "rm"(x)); }
+int mt7615_add_interface() { ffs(~mt7615_add_interface_dev_0); }
diff --git a/gcc/testsuite/gcc.target/i386/pr97642-1.c b/gcc/testsuite/gcc.target/i386/pr97642-1.c
new file mode 100644
index 0000000..f511440
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97642-1.c
@@ -0,0 +1,41 @@
+/* PR target/97642 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512vl -O2" } */
+/* { dg-final { scan-assembler-not { k[0-8] } } } */
+
+#include <immintrin.h>
+__m128i
+foo1 (__m128i src, void const* P)
+{
+ return _mm_mask_loadu_epi32 (src, 15, P);
+}
+
+__m256i
+foo2 (__m256i src, void const* P)
+{
+ return _mm256_mask_loadu_epi32 (src, 255, P);
+}
+
+__m512i
+foo3 (__m512i src, void const* P)
+{
+ return _mm512_mask_loadu_epi32 (src, 65535 , P);
+}
+
+__m128i
+foo4 (__m128i src, void const* P)
+{
+ return _mm_mask_loadu_epi32 (src, -1, P);
+}
+
+__m256i
+foo5 (__m256i src, void const* P)
+{
+ return _mm256_mask_loadu_epi32 (src, -1, P);
+}
+
+__m512i
+foo6 (__m512i src, void const* P)
+{
+ return _mm512_mask_loadu_epi32 (src, -1 , P);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97642-2.c b/gcc/testsuite/gcc.target/i386/pr97642-2.c
new file mode 100644
index 0000000..53a6154
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97642-2.c
@@ -0,0 +1,77 @@
+/* PR target/97642 */
+/* { dg-do run { target *-*-linux* } } */
+/* { dg-options "-O2 -mavx512dq -mavx512vl -mavx512bw" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target avx512dq } */
+/* { dg-require-effective-target avx512bw } */
+
+#include <assert.h>
+#include <immintrin.h>
+#include <stdint.h>
+#include <sys/mman.h>
+
+#define N 5
+
+// Faults with GCC because usage of vpblendd
+__m256i __attribute__((noinline)) mask_load(uint32_t * arr) {
+ __m256i tmp;
+ return _mm256_mask_loadu_epi32(tmp, (1 << N) - 1, arr);
+}
+
+// Faults
+__m256i __attribute__((noinline)) blend_load_asm(uint32_t * arr) {
+ __m256i tmp = _mm256_set1_epi64x(0);
+ asm volatile("vpblendd %[m], (%[arr]), %[tmp], %[tmp]\n\t"
+ : [ tmp ] "+x"(tmp)
+ : [ arr ] "r"(arr), [ m ] "i"(((1 << N) - 1))
+ :);
+ return tmp;
+}
+
+// Does not fault
+__m256i __attribute__((noinline)) mask_load_asm(uint32_t * arr) {
+ __m256i tmp;
+ asm volatile(
+ "movb %[m], %%al\n\t"
+ "kmovb %%eax, %%k1\n\t"
+ "vmovdqu32 (%[arr]), %[tmp] %{%%k1} %{z%}\n\t"
+ : [ tmp ] "+x"(tmp)
+ : [ arr ] "r"(arr), [ m ] "i"(((1 << N) - 1))
+ : "eax", "k1");
+ return tmp;
+}
+
+
+void __attribute__((noinline)) mask_store(uint32_t * arr, __m256i v) {
+ return _mm256_mask_storeu_epi32(arr, (1 << N) - 1, v);
+}
+
+
+#define NPAGES (2)
+#define END_OF_PAGE (1024 - N)
+
+#ifndef LOAD_METHOD
+#define LOAD_METHOD mask_load // mask_load_asm does not fault
+#endif
+
+
+int
+main() {
+ if (!(__builtin_cpu_supports ("avx512dq")
+ && __builtin_cpu_supports ("avx512vl")
+ && __builtin_cpu_supports ("avx512bw")))
+ return 0;
+
+ uint32_t * addr =
+ (uint32_t *)mmap(NULL, NPAGES * 4096, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+ for (uint32_t i = 0; i < NPAGES; i += 2) {
+
+ uint32_t page_offset = 1024 * i + END_OF_PAGE;
+ uint32_t next_page_offset = 1024 * (i + 1);
+
+ assert(!mprotect(addr + next_page_offset, 4096, PROT_NONE));
+ mask_store(addr + page_offset, LOAD_METHOD(addr + page_offset));
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97777.c b/gcc/testsuite/gcc.target/i386/pr97777.c
new file mode 100644
index 0000000..fcefc09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97777.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O -fzero-call-used-regs=used -ffinite-math-only" } */
+
+float
+foo (void)
+{
+ return __builtin_fmod (0, 0);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr97873-1.c b/gcc/testsuite/gcc.target/i386/pr97873-1.c
new file mode 100644
index 0000000..48c1d27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97873-1.c
@@ -0,0 +1,12 @@
+/* PR target/97873 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mavx512vl -mstv -mno-stackrealign" } */
+/* { dg-final { scan-assembler "pabsq" } } */
+
+extern long long z;
+
+void
+foo (long long x)
+{
+ z = (x < 0) ? -x : x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97873-2.c b/gcc/testsuite/gcc.target/i386/pr97873-2.c
new file mode 100644
index 0000000..22519ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97873-2.c
@@ -0,0 +1,23 @@
+/* PR target/97873 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-sse3 -mtune=generic" } */
+
+#ifdef __SIZEOF_INT128__
+typedef __int128_t T;
+#else
+typedef long long T;
+#endif
+
+T test_abs (T x)
+{
+ return (x < 0) ? -x : x;
+}
+
+/* { dg-final { scan-assembler "adc" } } */
+
+T test_smin (T x, T y)
+{
+ return (x < y) ? x : y;
+}
+
+/* { dg-final { scan-assembler "sbb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr97873-3.c b/gcc/testsuite/gcc.target/i386/pr97873-3.c
new file mode 100644
index 0000000..e682f14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97873-3.c
@@ -0,0 +1,27 @@
+/* PR target/97873 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-sse3 -mtune=generic" } */
+
+short test_absw (short x)
+{
+ return (x < 0) ? -x : x;
+}
+
+short test_sminw (short x, short y)
+{
+ return (x < y) ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "movswl" } } */
+
+char test_absb (char x)
+{
+ return (x < 0) ? -x : x;
+}
+
+char test_sminb (char x, char y)
+{
+ return (x < y) ? x : y;
+}
+
+/* { dg-final { scan-assembler-not "movsbl" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr97873.c b/gcc/testsuite/gcc.target/i386/pr97873.c
new file mode 100644
index 0000000..ec598f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97873.c
@@ -0,0 +1,9 @@
+/* PR target/97873 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-sse3 -mtune=generic" } */
+/* { dg-final { scan-assembler-not "test|cmp" } } */
+
+int foo (int x)
+{
+ return (x < 0) ? -x : x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr97887.c b/gcc/testsuite/gcc.target/i386/pr97887.c
new file mode 100644
index 0000000..b457f05
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97887.c
@@ -0,0 +1,15 @@
+/* PR target/97887 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+
+float f (float a)
+{
+ return -a / a;
+}
+
+double d (double a)
+{
+ return -a / a;
+}
+
+/* { dg-final { scan-assembler-not "fchs" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr97950.c b/gcc/testsuite/gcc.target/i386/pr97950.c
new file mode 100644
index 0000000..277311d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97950.c
@@ -0,0 +1,153 @@
+/* PR target/95950 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=generic" } */
+/* { dg-final { scan-assembler-times "\tseta\t" 4 } } */
+/* { dg-final { scan-assembler-times "\tseto\t" 16 } } */
+/* { dg-final { scan-assembler-times "\tsetc\t" 4 } } */
+/* { dg-final { scan-assembler-not "\tjn?a\t" } } */
+/* { dg-final { scan-assembler-not "\tjn?o\t" } } */
+/* { dg-final { scan-assembler-not "\tjn?c\t" } } */
+
+char
+f1 (short a, short b)
+{
+ return __builtin_mul_overflow_p (a, b, (short) 0);
+}
+
+char
+f2 (short a, short b)
+{
+ return __builtin_add_overflow_p (a, b, (short) 0);
+}
+
+char
+f3 (short a, short b)
+{
+ return __builtin_sub_overflow_p (a, b, (short) 0);
+}
+
+char
+f4 (unsigned short a, unsigned short b)
+{
+ return __builtin_mul_overflow_p (a, b, (unsigned short) 0);
+}
+
+char
+f5 (unsigned short a, unsigned short b)
+{
+ return __builtin_add_overflow_p (a, b, (unsigned short) 0);
+}
+
+char
+f6 (unsigned short a, unsigned short b)
+{
+ return __builtin_sub_overflow_p (a, b, (unsigned short) 0);
+}
+
+char
+f7 (short a, short b)
+{
+ return __builtin_mul_overflow_p (a, b, (short) 0);
+}
+
+char
+f8 (short a, short b)
+{
+ return __builtin_add_overflow_p (a, b, (short) 0);
+}
+
+char
+f9 (short a, short b)
+{
+ return __builtin_sub_overflow_p (a, b, (short) 0);
+}
+
+char
+f10 (unsigned short a, unsigned short b)
+{
+ return __builtin_mul_overflow_p (a, b, (unsigned short) 0);
+}
+
+char
+f11 (unsigned short a, unsigned short b)
+{
+ return __builtin_add_overflow_p (a, b, (unsigned short) 0);
+}
+
+char
+f12 (unsigned short a, unsigned short b)
+{
+ return __builtin_sub_overflow_p (a, b, (unsigned short) 0);
+}
+
+unsigned short
+f13 (short a, short b)
+{
+ return __builtin_mul_overflow_p (a, b, (short) 0);
+}
+
+unsigned short
+f14 (short a, short b)
+{
+ return __builtin_add_overflow_p (a, b, (short) 0);
+}
+
+unsigned short
+f15 (short a, short b)
+{
+ return __builtin_sub_overflow_p (a, b, (short) 0);
+}
+
+unsigned short
+f16 (unsigned short a, unsigned short b)
+{
+ return __builtin_mul_overflow_p (a, b, (unsigned short) 0);
+}
+
+unsigned short
+f17 (unsigned short a, unsigned short b)
+{
+ return __builtin_add_overflow_p (a, b, (unsigned short) 0);
+}
+
+unsigned short
+f18 (unsigned short a, unsigned short b)
+{
+ return __builtin_sub_overflow_p (a, b, (unsigned short) 0);
+}
+
+unsigned short
+f19 (short a, short b)
+{
+ return __builtin_mul_overflow_p (a, b, (short) 0);
+}
+
+unsigned short
+f20 (short a, short b)
+{
+ return __builtin_add_overflow_p (a, b, (short) 0);
+}
+
+unsigned short
+f21 (short a, short b)
+{
+ return __builtin_sub_overflow_p (a, b, (short) 0);
+}
+
+unsigned short
+f22 (unsigned short a, unsigned short b)
+{
+ return __builtin_mul_overflow_p (a, b, (unsigned short) 0);
+}
+
+unsigned short
+f23 (unsigned short a, unsigned short b)
+{
+ return __builtin_add_overflow_p (a, b, (unsigned short) 0);
+}
+
+unsigned short
+f24 (unsigned short a, unsigned short b)
+{
+ return __builtin_sub_overflow_p (a, b, (unsigned short) 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98063.c b/gcc/testsuite/gcc.target/i386/pr98063.c
new file mode 100644
index 0000000..f76435a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98063.c
@@ -0,0 +1,13 @@
+/* PR target/98063 */
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -fpic -mcmodel=large -fno-plt -save-temps" } */
+/* { dg-final { scan-assembler-not "puts@GOTPCREL" } } */
+
+int
+main ()
+{
+ __builtin_puts ("Hello, world!");
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98079.c b/gcc/testsuite/gcc.target/i386/pr98079.c
new file mode 100644
index 0000000..8de0ec3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98079.c
@@ -0,0 +1,13 @@
+/* PR target/98079 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -march=pentium3" } */
+
+typedef __UINT8_TYPE__ uint8_t;
+
+uint8_t foo (uint8_t x)
+{
+ if (x & 0x80)
+ x = -x;
+
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98086.c b/gcc/testsuite/gcc.target/i386/pr98086.c
new file mode 100644
index 0000000..254a3b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98086.c
@@ -0,0 +1,17 @@
+/* PR target/98086 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#ifdef __x86_64__
+typedef __int128 T;
+#else
+typedef long long T;
+#endif
+
+T x;
+
+void
+foo (void)
+{
+ __asm ("" : "=@ccc" (x));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98100.c b/gcc/testsuite/gcc.target/i386/pr98100.c
new file mode 100644
index 0000000..09c2e32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98100.c
@@ -0,0 +1,10 @@
+/* PR target/98100 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx -fvar-tracking-assignments -g0" } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target_clones("default","avx2"))) void
+foo ()
+{
+ __attribute__((__vector_size__(8 * sizeof(int)))) int b = {};
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98161.c b/gcc/testsuite/gcc.target/i386/pr98161.c
new file mode 100644
index 0000000..5825b9b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98161.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -msse4" } */
+/* { dg-require-effective-target sse4} */
+
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned char u8;
+
+u32
+__attribute__((__force_align_arg_pointer__))
+unreach(const u16 * pu16, u16 *dst, u32 dstlen, const u8 *src, u32 srclen)
+{
+ for (u32 i = dstlen; srclen && i; i--, srclen--, src++, dst++)
+ {
+ u16 off = pu16[*src];
+ if (off)
+ {
+ src++; srclen--;
+ *dst = pu16[off + *src];
+ }
+ }
+ return 56;
+}
+
+u32
+__attribute__((__force_align_arg_pointer__))
+__attribute__((noipa))
+bug(const u16 * pu16, u16 *dst, u32 dstlen, const u8 *src, u32 srclen)
+{
+ if (pu16)
+ /* Branch should not execute, but stack realignment
+ * reads wrong 'pu16' value from stack. */
+ return unreach(pu16, dst, dstlen, src, srclen);
+
+ return (srclen < dstlen) ? srclen : dstlen;
+}
+
+int
+main()
+{
+ if (__builtin_cpu_supports ("sse4.1"))
+ {
+ /* Should return 12 */
+ if (bug(0, 0, 12, 0, 34) != 12)
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98169.c b/gcc/testsuite/gcc.target/i386/pr98169.c
new file mode 100644
index 0000000..b192731
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98169.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/98169 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-finite-math-only" } */
+/* { dg-final { scan-assembler-times "\tsetn\?p\t" 4 } } */
+/* { dg-final { scan-assembler-not "\tjn\?\[ep]\t" } } */
+
+int
+f1 (float a)
+{
+ return a == a;
+}
+
+int
+f2 (float a)
+{
+ return !__builtin_isnanf (a);
+}
+
+int
+f3 (double a)
+{
+ return a == a;
+}
+
+int
+f4 (double a)
+{
+ return !__builtin_isnan (a);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98212.c b/gcc/testsuite/gcc.target/i386/pr98212.c
new file mode 100644
index 0000000..b8ed023
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98212.c
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/98212 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse -mno-avx" } */
+/* { dg-final { scan-assembler-times "\tucomiss\t" 2 } } */
+/* { dg-final { scan-assembler-not "\tcomiss\t" } } */
+
+void foo (void);
+
+void
+bar (float a, float b)
+{
+ if (a != b)
+ foo ();
+}
+
+void
+baz (float a, float b)
+{
+ if (a == b)
+ foo ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98264.c b/gcc/testsuite/gcc.target/i386/pr98264.c
new file mode 100644
index 0000000..ea23527
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98264.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3 -w" } */
+
+a[], g[], h[];
+double b, c;
+double j[];
+i;
+l() {
+ int e = 0;
+ for (; e < 80; e += 4) {
+ a[0] = h[e];
+ a[1] = h[e + 1];
+ j[0] = a[0] - c;
+ j[1] = a[1] + b;
+ __attribute__(()) k = *(double *)a, e, f = e = 0;
+ *g = k;
+ double *d = j;
+ for (; e < 2; e++)
+ if (d[e])
+ i = f;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98274.c b/gcc/testsuite/gcc.target/i386/pr98274.c
new file mode 100644
index 0000000..dd08f33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98274.c
@@ -0,0 +1,8 @@
+/* PR target/98274 */
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-mabi=sysv -O2 -march=x86-64-v2" } */
+
+void __attribute__((target ("avx")))
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr98289.c b/gcc/testsuite/gcc.target/i386/pr98289.c
new file mode 100644
index 0000000..9c620d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98289.c
@@ -0,0 +1,54 @@
+/* PR rtl-optimization/98289 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition -fdump-rtl-pro_and_epilogue-details" } */
+/* { dg-final { scan-rtl-dump-times "Performing shrink-wrapping" 4 "pro_and_epilogue" } } */
+
+int bar (void) __attribute__((cold));
+
+void
+foo (int x)
+{
+ if (x)
+ __builtin_abort ();
+}
+
+void
+baz (int x)
+{
+ if (__builtin_expect (x, 0))
+ {
+ bar ();
+ bar ();
+ bar ();
+ }
+}
+
+void
+qux (int x, int y, int z, int w)
+{
+ if (x || y || z || w)
+ __builtin_abort ();
+}
+
+int
+corge (int x, int y, int z, int w, int u)
+{
+ if (__builtin_expect (x, 0))
+ goto lab;
+ u++;
+ if (__builtin_expect (y, 0))
+ goto lab;
+ u *= 2;
+ if (__builtin_expect (z, 0))
+ goto lab;
+ u |= 42;
+ if (__builtin_expect (w, 0))
+ {
+ lab:;
+ bar ();
+ bar ();
+ if (bar () > 32) goto lab;
+ }
+ return u;
+}
diff --git a/gcc/testsuite/gcc.target/i386/returninst1.c b/gcc/testsuite/gcc.target/i386/returninst1.c
index 133fdee..74d10c9 100644
--- a/gcc/testsuite/gcc.target/i386/returninst1.c
+++ b/gcc/testsuite/gcc.target/i386/returninst1.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-require-effective-target mfentry } */
+/* { dg-require-profiling "-pg" } */
/* { dg-options "-pg -mfentry -minstrument-return=call -mrecord-return" } */
/* { dg-final { scan-assembler "call.*__return__" } } */
/* { dg-final { scan-assembler "section.*return_loc" } } */
diff --git a/gcc/testsuite/gcc.target/i386/returninst2.c b/gcc/testsuite/gcc.target/i386/returninst2.c
index 3629310..e19f0d0 100644
--- a/gcc/testsuite/gcc.target/i386/returninst2.c
+++ b/gcc/testsuite/gcc.target/i386/returninst2.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-require-effective-target mfentry } */
+/* { dg-require-profiling "-pg" } */
/* { dg-options "-pg -mfentry -minstrument-return=nop5 -mrecord-return" } */
/* { dg-final { scan-assembler-times "0x0f, 0x1f, 0x44, 0x00, 0x00" 3 } } */
/* { dg-final { scan-assembler "section.*return_loc" } } */
diff --git a/gcc/testsuite/gcc.target/i386/returninst3.c b/gcc/testsuite/gcc.target/i386/returninst3.c
index b84cc77..acb8984 100644
--- a/gcc/testsuite/gcc.target/i386/returninst3.c
+++ b/gcc/testsuite/gcc.target/i386/returninst3.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-require-effective-target mfentry } */
+/* { dg-require-profiling "-pg" } */
/* { dg-options "-pg -mfentry -minstrument-return=call" } */
/* { dg-final { scan-assembler-not "call.*__return__" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c
index 61146b2b..375d4d1 100644
--- a/gcc/testsuite/gcc.target/i386/sse-12.c
+++ b/gcc/testsuite/gcc.target/i386/sse-12.c
@@ -3,7 +3,7 @@
popcntintrin.h gfniintrin.h and mm_malloc.h are usable
with -O -std=c89 -pedantic-errors. */
/* { dg-do compile } */
-/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16" } */
+/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni" } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index dd6dd55..7029771 100644
--- a/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mavx512vp2intersect -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16" } */
+/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mavx512vp2intersect -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index 837b51c..4ce0fff 100644
--- a/gcc/testsuite/gcc.target/i386/sse-14.c
+++ b/gcc/testsuite/gcc.target/i386/sse-14.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mpconfig -mwbnoinvd -mavx512vl -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16" } */
+/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx512vbmi2 -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mpconfig -mwbnoinvd -mavx512vl -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index fc75669f..6e8b6f3 100644
--- a/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -103,7 +103,7 @@
#ifndef DIFFERENT_PRAGMAS
-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,avx512vl,avx512bw,avx512dq,avx512vbmi,avx512vbmi2,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16")
+#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,avx512vl,avx512bw,avx512dq,avx512vbmi,avx512vbmi2,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni")
#endif
/* Following intrinsics require immediate arguments. They
@@ -220,7 +220,7 @@ test_4 (_mm_cmpestrz, int, __m128i, int, __m128i, int, 1)
/* immintrin.h (AVX/AVX2/RDRND/FSGSBASE/F16C/RTM/AVX512F/SHA) */
#ifdef DIFFERENT_PRAGMAS
-#pragma GCC target ("avx,avx2,rdrnd,fsgsbase,f16c,rtm,avx512f,avx512er,avx512cd,avx512pf,sha,avx512vl,avx512bw,avx512dq,avx512ifma,avx512vbmi,avx512vbmi2,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16")
+#pragma GCC target ("avx,avx2,rdrnd,fsgsbase,f16c,rtm,avx512f,avx512er,avx512cd,avx512pf,sha,avx512vl,avx512bw,avx512dq,avx512ifma,avx512vbmi,avx512vbmi2,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni")
#endif
#include <immintrin.h>
test_1 (_cvtss_sh, unsigned short, float, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index b51644c..7faa053 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -708,6 +708,6 @@
#define __builtin_ia32_vpclmulqdq_v2di(A, B, C) __builtin_ia32_vpclmulqdq_v2di(A, B, 1)
#define __builtin_ia32_vpclmulqdq_v8di(A, B, C) __builtin_ia32_vpclmulqdq_v8di(A, B, 1)
-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16")
+#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni")
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse2-pr98461.c b/gcc/testsuite/gcc.target/i386/sse2-pr98461.c
new file mode 100644
index 0000000..9fae755
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-pr98461.c
@@ -0,0 +1,50 @@
+/* PR target/98461 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-sse3 -masm=att" } */
+/* { dg-final { scan-assembler-times "\tpmovmskb\t" 6 } } */
+/* { dg-final { scan-assembler-times "\txorl\t" 6 } } */
+/* { dg-final { scan-assembler-not "\tpcmpeq" } } */
+/* { dg-final { scan-assembler-not "\tpxor" } } */
+/* { dg-final { scan-assembler-not "\tpandn" } } */
+
+#include <x86intrin.h>
+
+int
+f1 (__m128i x)
+{
+ return _mm_movemask_epi8 (x) ^ 65535;
+}
+
+int
+f2 (__m128i x)
+{
+ return _mm_movemask_epi8 (_mm_andnot_si128 (x, _mm_set1_epi8 (255)));
+}
+
+int
+f3 (__v16qi x)
+{
+ x ^= (__v16qi) { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+ return _mm_movemask_epi8 ((__m128i) x);
+}
+
+long
+f4 (__m128i x)
+{
+ return (unsigned) (_mm_movemask_epi8 (x) ^ 65535);
+}
+
+long
+f5 (__m128i x)
+{
+ return (unsigned) _mm_movemask_epi8 (_mm_andnot_si128 (x, _mm_set1_epi8 (255)));
+}
+
+long
+f6 (__v16qi x)
+{
+ x ^= (__v16qi) { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+ return (unsigned) _mm_movemask_epi8 ((__m128i) x);
+}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-2.c b/gcc/testsuite/gcc.target/i386/uintr-2.c
index e705732..0a83c66 100644
--- a/gcc/testsuite/gcc.target/i386/uintr-2.c
+++ b/gcc/testsuite/gcc.target/i386/uintr-2.c
@@ -1,17 +1,20 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-options "-O2 -muintr -mgeneral-regs-only" } */
/* { dg-final { scan-assembler-times "uiret" "2" } } */
+/* { dg-final { scan-assembler-times "add\[lq]\[ \t]\+\\\$8, %\[er\]sp" "2" } } */
#include <x86gprintrin.h>
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
void
__attribute__((interrupt))
-foo (void *frame)
+foo (void *frame, uword_t uirrv)
{
}
void
__attribute__((interrupt))
-UINTR_hanlder (struct __uintr_frame *frame)
+UINTR_hanlder (struct __uintr_frame *frame, uword_t uirrv)
{
}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-3.c b/gcc/testsuite/gcc.target/i386/uintr-3.c
index d284349..92476cf 100644
--- a/gcc/testsuite/gcc.target/i386/uintr-3.c
+++ b/gcc/testsuite/gcc.target/i386/uintr-3.c
@@ -1,9 +1,13 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-options "-O2 -muintr" } */
/* { dg-final { scan-assembler "uiret" } } */
+/* { dg-final { scan-assembler "add\[lq]\[ \t]\+\\\$8, %\[er\]sp" } } */
+
#include <x86gprintrin.h>
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
void __attribute__ ((target("general-regs-only"), interrupt))
-UINTR_handler (struct __uintr_frame *p)
+UINTR_handler (struct __uintr_frame *p, uword_t uirrv)
{
}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-4.c b/gcc/testsuite/gcc.target/i386/uintr-4.c
index f3b371b..4d0ec34 100644
--- a/gcc/testsuite/gcc.target/i386/uintr-4.c
+++ b/gcc/testsuite/gcc.target/i386/uintr-4.c
@@ -3,7 +3,9 @@
#include <x86gprintrin.h>
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
void __attribute__ ((interrupt))
-UINTR_handler (struct __uintr_frame *p)
-{ /* { dg-message "SSE instructions aren't allowed in an interrupt service routine" } */
+UINTR_handler (struct __uintr_frame *p, uword_t uirrv)
+{ /* { dg-message "SSE instructions aren't allowed in an exception service routine" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/uintr-5.c b/gcc/testsuite/gcc.target/i386/uintr-5.c
index ac44be0..49cb2ec 100644
--- a/gcc/testsuite/gcc.target/i386/uintr-5.c
+++ b/gcc/testsuite/gcc.target/i386/uintr-5.c
@@ -4,7 +4,9 @@
#include <x86gprintrin.h>
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
void
-UINTR_hanlder (struct __uintr_frame *frame)
+UINTR_hanlder (struct __uintr_frame *frame, uword_t uirrv)
{
}
diff --git a/gcc/testsuite/gcc.target/i386/vnni_inline_error.c b/gcc/testsuite/gcc.target/i386/vnni_inline_error.c
new file mode 100644
index 0000000..eaed984
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vnni_inline_error.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -mavx512vnni -mavx512vl -mno-popcnt" } */
+
+inline int __attribute__ ((__gnu_inline__, __always_inline__, target("popcnt")))
+foo () /* { dg-error "inlining failed in call to 'always_inline' .* target specific option mismatch" } */
+{
+ return 0;
+}
+
+int bar()
+{
+ return foo (); /* { dg-message "called from here" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v2-msabi.c b/gcc/testsuite/gcc.target/i386/x86-64-v2-msabi.c
new file mode 100644
index 0000000..109589b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v2-msabi.c
@@ -0,0 +1,5 @@
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-mabi=ms -march=x86-64-v2" } */
+
+/* Verify -march=x86-64-v2 works even with -mabi=ms. */
+#include "x86-64-v2.c"
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v2-other.c b/gcc/testsuite/gcc.target/i386/x86-64-v2-other.c
new file mode 100644
index 0000000..1750b7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v2-other.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=x86-64-v2" } */
+
+/* Verify -march=x86-64-v2 works even with -m32 or -mabi=ms. */
+#include "x86-64-v2.c"
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v2.c b/gcc/testsuite/gcc.target/i386/x86-64-v2.c
index f17a15d..e4b7e88 100644
--- a/gcc/testsuite/gcc.target/i386/x86-64-v2.c
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v2.c
@@ -12,8 +12,10 @@
#ifndef __SSE2__
# error __SSE2__ not defined
#endif
-#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
-# error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 not defined
+#ifdef __x86_64__
+# ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
+# error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 not defined
+# endif
#endif
#ifndef __LAHF_SAHF__
# error __LAHF_SAHF__ not defined
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v3-msabi.c b/gcc/testsuite/gcc.target/i386/x86-64-v3-msabi.c
new file mode 100644
index 0000000..dcf7cb0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v3-msabi.c
@@ -0,0 +1,5 @@
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-mabi=ms -march=x86-64-v3" } */
+
+/* Verify -march=x86-64-v3 works even with -mabi=ms. */
+#include "x86-64-v3.c"
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v3-other.c b/gcc/testsuite/gcc.target/i386/x86-64-v3-other.c
new file mode 100644
index 0000000..d80ac1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v3-other.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=x86-64-v3" } */
+
+/* Verify -march=x86-64-v3 works even with -m32 or -mabi=ms. */
+#include "x86-64-v3.c"
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v3.c b/gcc/testsuite/gcc.target/i386/x86-64-v3.c
index 784202f..5357720 100644
--- a/gcc/testsuite/gcc.target/i386/x86-64-v3.c
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v3.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-options "-mabi=sysv -march=x86-64-v3" } */
-/* Verify that the CPU features required by x86-64-v4 are enabled. */
+/* Verify that the CPU features required by x86-64-v3 are enabled. */
#ifndef __MMX__
# error __MMX__ not defined
@@ -12,8 +12,10 @@
#ifndef __SSE2__
# error __SSE2__ not defined
#endif
-#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
-# error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 not defined
+#ifdef __x86_64__
+# ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
+# error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 not defined
+# endif
#endif
#ifndef __LAHF_SAHF__
# error __LAHF_SAHF__ not defined
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v4-msabi.c b/gcc/testsuite/gcc.target/i386/x86-64-v4-msabi.c
new file mode 100644
index 0000000..fe8565f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v4-msabi.c
@@ -0,0 +1,5 @@
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-mabi=ms -march=x86-64-v4" } */
+
+/* Verify -march=x86-64-v4 works even with -mabi=ms. */
+#include "x86-64-v4.c"
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v4-other.c b/gcc/testsuite/gcc.target/i386/x86-64-v4-other.c
new file mode 100644
index 0000000..0e1a284
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v4-other.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=x86-64-v4" } */
+
+/* Verify -march=x86-64-v4 works even with -m32 or -mabi=ms. */
+#include "x86-64-v4.c"
diff --git a/gcc/testsuite/gcc.target/i386/x86-64-v4.c b/gcc/testsuite/gcc.target/i386/x86-64-v4.c
index 7c202a4..718b1a1 100644
--- a/gcc/testsuite/gcc.target/i386/x86-64-v4.c
+++ b/gcc/testsuite/gcc.target/i386/x86-64-v4.c
@@ -12,8 +12,10 @@
#ifndef __SSE2__
# error __SSE2__ not defined
#endif
-#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
-# error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 not defined
+#ifdef __x86_64__
+# ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
+# error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 not defined
+# endif
#endif
#ifndef __LAHF_SAHF__
# error __LAHF_SAHF__ not defined
diff --git a/gcc/testsuite/gcc.target/i386/x86-needed-1.c b/gcc/testsuite/gcc.target/i386/x86-needed-1.c
new file mode 100644
index 0000000..b4584df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-needed-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -march=x86-64 -mneeded" } */
+/* { dg-final { scan-assembler-times ".note.gnu.property" 1 } } */
+/* { dg-final { scan-assembler-times ".long 0xc0000002" 1 } } */
+/* { dg-final { scan-assembler-times ".long 0xc0008002" 1 } } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/x86-needed-2.c b/gcc/testsuite/gcc.target/i386/x86-needed-2.c
new file mode 100644
index 0000000..2d91656
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-needed-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fcf-protection=none -march=x86-64 -mno-needed" } */
+/* { dg-final { scan-assembler-not ".note.gnu.property" } } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/x86-needed-3.c b/gcc/testsuite/gcc.target/i386/x86-needed-3.c
new file mode 100644
index 0000000..1d93726
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/x86-needed-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-fcf-protection=none -march=i686 -msoft-float -mneeded" } */
+/* { dg-final { scan-assembler-not ".note.gnu.property" } } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/xop-haddX.c b/gcc/testsuite/gcc.target/i386/xop-haddX.c
index 7d3220b..68f2752 100644
--- a/gcc/testsuite/gcc.target/i386/xop-haddX.c
+++ b/gcc/testsuite/gcc.target/i386/xop-haddX.c
@@ -34,7 +34,6 @@ init_sword ()
src1.si[i] = i;
}
-
static void
init_sdword ()
{
@@ -58,6 +57,7 @@ check_sbyte2word ()
check_fails++;
}
}
+ return check_fails;
}
static int
@@ -76,7 +76,7 @@ check_sbyte2dword ()
check_fails++;
}
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -96,14 +96,14 @@ check_sbyte2qword ()
check_fails++;
}
}
- return check_fails++;
+ return check_fails;
}
static int
check_sword2dword ()
{
int i, j, s, t, check_fails = 0;
- for (i = 0; i < (NUM * 8); i = i + 8)
+ for (i = 0; i < NUM * 8; i = i + 8)
{
for (j = 0; j < 4; j++)
{
@@ -114,6 +114,7 @@ check_sword2dword ()
check_fails++;
}
}
+ return check_fails;
}
static int
@@ -132,14 +133,14 @@ check_sword2qword ()
check_fails++;
}
}
- return check_fails++;
+ return check_fails;
}
static int
check_dword2qword ()
{
int i, j, s, t, check_fails = 0;
- for (i = 0; i < (NUM * 4); i = i + 4)
+ for (i = 0; i < NUM * 4; i = i + 4)
{
for (j = 0; j < 2; j++)
{
@@ -150,6 +151,7 @@ check_dword2qword ()
check_fails++;
}
}
+ return check_fails;
}
static void
@@ -163,15 +165,13 @@ xop_test (void)
dst.x[i] = _mm_haddw_epi8 (src1.x[i]);
if (check_sbyte2word())
- abort ();
-
+ abort ();
- for (i = 0; i < (NUM ); i++)
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddd_epi8 (src1.x[i]);
if (check_sbyte2dword())
abort ();
-
for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddq_epi8 (src1.x[i]);
@@ -179,10 +179,9 @@ xop_test (void)
if (check_sbyte2qword())
abort ();
-
init_sword ();
- for (i = 0; i < (NUM ); i++)
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddd_epi16 (src1.x[i]);
if (check_sword2dword())
@@ -193,14 +192,12 @@ xop_test (void)
if (check_sword2qword())
abort ();
-
init_sdword ();
- for (i = 0; i < NUM; i++)
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddq_epi32 (src1.x[i]);
if (check_dword2qword())
abort ();
-
}
diff --git a/gcc/testsuite/gcc.target/i386/xop-hadduX.c b/gcc/testsuite/gcc.target/i386/xop-hadduX.c
index 9c7ea9a..06a4a2e 100644
--- a/gcc/testsuite/gcc.target/i386/xop-hadduX.c
+++ b/gcc/testsuite/gcc.target/i386/xop-hadduX.c
@@ -34,7 +34,6 @@ init_word ()
src1.si[i] = i;
}
-
static void
init_dword ()
{
@@ -58,6 +57,7 @@ check_byte2word ()
check_fails++;
}
}
+ return check_fails;
}
static int
@@ -76,7 +76,7 @@ check_byte2dword ()
check_fails++;
}
}
- return check_fails++;
+ return check_fails;
}
static int
@@ -96,14 +96,14 @@ check_byte2qword ()
check_fails++;
}
}
- return check_fails++;
+ return check_fails;
}
static int
check_word2dword ()
{
int i, j, s, t, check_fails = 0;
- for (i = 0; i < (NUM * 8); i = i + 8)
+ for (i = 0; i < NUM * 8; i = i + 8)
{
for (j = 0; j < 4; j++)
{
@@ -114,6 +114,7 @@ check_word2dword ()
check_fails++;
}
}
+ return check_fails;
}
static int
@@ -132,14 +133,14 @@ check_word2qword ()
check_fails++;
}
}
- return check_fails++;
+ return check_fails;
}
static int
check_dword2qword ()
{
int i, j, s, t, check_fails = 0;
- for (i = 0; i < (NUM * 4); i = i + 4)
+ for (i = 0; i < NUM * 4; i = i + 4)
{
for (j = 0; j < 2; j++)
{
@@ -150,6 +151,7 @@ check_dword2qword ()
check_fails++;
}
}
+ return check_fails;
}
static void
@@ -167,7 +169,7 @@ xop_test (void)
abort ();
/* Check haddubd */
- for (i = 0; i < (NUM ); i++)
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddd_epu8 (src1.x[i]);
if (check_byte2dword())
@@ -183,14 +185,13 @@ xop_test (void)
/* Check hadduwd */
init_word ();
- for (i = 0; i < (NUM ); i++)
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddd_epu16 (src1.x[i]);
if (check_word2dword())
abort ();
/* Check haddbuwq */
-
for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddq_epu16 (src1.x[i]);
@@ -199,7 +200,8 @@ xop_test (void)
/* Check hadudq */
init_dword ();
- for (i = 0; i < NUM; i++)
+
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_haddq_epu32 (src1.x[i]);
if (check_dword2qword())
diff --git a/gcc/testsuite/gcc.target/i386/xop-hsubX.c b/gcc/testsuite/gcc.target/i386/xop-hsubX.c
index f0fa9b3..e4c4373 100644
--- a/gcc/testsuite/gcc.target/i386/xop-hsubX.c
+++ b/gcc/testsuite/gcc.target/i386/xop-hsubX.c
@@ -34,7 +34,6 @@ init_sword ()
src1.si[i] = i;
}
-
static void
init_sdword ()
{
@@ -58,13 +57,14 @@ check_sbyte2word ()
check_fails++;
}
}
+ return check_fails;
}
static int
check_sword2dword ()
{
int i, j, s, t, check_fails = 0;
- for (i = 0; i < (NUM * 8); i = i + 8)
+ for (i = 0; i < NUM * 8; i = i + 8)
{
for (j = 0; j < 4; j++)
{
@@ -75,13 +75,14 @@ check_sword2dword ()
check_fails++;
}
}
+ return check_fails;
}
static int
check_dword2qword ()
{
int i, j, s, t, check_fails = 0;
- for (i = 0; i < (NUM * 4); i = i + 4)
+ for (i = 0; i < NUM * 4; i = i + 4)
{
for (j = 0; j < 2; j++)
{
@@ -92,6 +93,7 @@ check_dword2qword ()
check_fails++;
}
}
+ return check_fails;
}
static void
@@ -106,13 +108,12 @@ xop_test (void)
dst.x[i] = _mm_hsubw_epi8 (src1.x[i]);
if (check_sbyte2word())
- abort ();
-
+ abort ();
/* Check hsubwd */
init_sword ();
- for (i = 0; i < (NUM ); i++)
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_hsubd_epi16 (src1.x[i]);
if (check_sword2dword())
@@ -120,7 +121,8 @@ xop_test (void)
/* Check hsubdq */
init_sdword ();
- for (i = 0; i < NUM; i++)
+
+ for (i = 0; i < NUM; i++)
dst.x[i] = _mm_hsubq_epi32 (src1.x[i]);
if (check_dword2qword())
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c
new file mode 100644
index 0000000..1ea6de8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c
new file mode 100644
index 0000000..389b114
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+extern int foo (int) __attribute__ ((zero_call_used_regs("all-gpr")));
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c
new file mode 100644
index 0000000..4862688
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-gpr" } */
+
+struct S { int i; };
+__attribute__((const, noinline, noclone))
+struct S foo (int x)
+{
+ struct S s;
+ s.i = x;
+ return s;
+}
+
+int a[2048], b[2048], c[2048], d[2048];
+struct S e[2048];
+
+__attribute__((noinline, noclone)) void
+bar (void)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ {
+ e[i] = foo (i);
+ a[i+2] = a[i] + a[i+1];
+ b[10] = b[10] + i;
+ c[i] = c[2047 - i];
+ d[i] = d[i + 1];
+ }
+}
+
+int
+main ()
+{
+ int i;
+ bar ();
+ for (i = 0; i < 1024; i++)
+ if (e[i].i != i)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c
new file mode 100644
index 0000000..500251b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
+
+struct S { int i; };
+__attribute__((const, noinline, noclone))
+struct S foo (int x)
+{
+ struct S s;
+ s.i = x;
+ return s;
+}
+
+int a[2048], b[2048], c[2048], d[2048];
+struct S e[2048];
+
+__attribute__((noinline, noclone)) void
+bar (void)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ {
+ e[i] = foo (i);
+ a[i+2] = a[i] + a[i+1];
+ b[10] = b[10] + i;
+ c[i] = c[2047 - i];
+ d[i] = d[i + 1];
+ }
+}
+
+int
+main ()
+{
+ int i;
+ bar ();
+ for (i = 0; i < 1024; i++)
+ if (e[i].i != i)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c
new file mode 100644
index 0000000..07d8de7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */
+/* { dg-final { scan-assembler-times "movaps\[ \t\]+%xmm0, %xmm\[0-9\]+" 7 { target { ia32 } } } } */
+/* { dg-final { scan-assembler-times "movaps\[ \t\]+%xmm0, %xmm\[0-9\]+" 15 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c
new file mode 100644
index 0000000..55a272c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7 -mavx" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-times "vzeroall" 1 } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c
new file mode 100644
index 0000000..d0e975c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+extern void foo (void) __attribute__ ((zero_call_used_regs("used")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c
new file mode 100644
index 0000000..d41a255
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all" } */
+
+extern void foo (void) __attribute__ ((zero_call_used_regs("skip")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c
new file mode 100644
index 0000000..c79fcd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" { target ia32 } } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edi, %edi" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c
new file mode 100644
index 0000000..6f90723
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used -march=corei7" } */
+
+float
+foo (float z, float y, float x)
+{
+ return x + y;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm1, %xmm2" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c
new file mode 100644
index 0000000..491d2d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used -march=corei7" } */
+
+float
+foo (float z, float y, float x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm2, %xmm2" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c
new file mode 100644
index 0000000..52406fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c
new file mode 100644
index 0000000..ccd4917
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7" } */
+
+float
+foo (float z, float y, float x)
+{
+ return x + y;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" { target { ia32 } } } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "movaps\[ \t\]+%xmm0, %xmm\[0-9\]+" 7 { target { ia32 } } } } */
+/* { dg-final { scan-assembler-times "movaps\[ \t\]+%xmm1, %xmm\[0-9\]+" 14 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c
new file mode 100644
index 0000000..b3570f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip -march=corei7" } */
+
+__attribute__ ((zero_call_used_regs("used")))
+float
+foo (float z, float y, float x)
+{
+ return x + y;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm1, %xmm1" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm1, %xmm2" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c
new file mode 100644
index 0000000..b253420
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7 -mavx" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "vzeroall" } } */
+/* { dg-final { scan-assembler-times "fldz" 8 } } */
+/* { dg-final { scan-assembler-times "fstp\[ \t\]+%st\\(0\\)" 8 } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c
new file mode 100644
index 0000000..69d42d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c
@@ -0,0 +1,29 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7 -mavx512f" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "vzeroall" } } */
+/* { dg-final { scan-assembler-times "fldz" 8 } } */
+/* { dg-final { scan-assembler-times "fstp\[ \t\]+%st\\(0\\)" 8 } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kxorw\[ \t\]+%k0, %k0, %k0" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k1" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k2" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k3" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k4" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k5" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k6" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "kmovw\[ \t\]+%k0, %k7" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-24.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-24.c
new file mode 100644
index 0000000..5c68287
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-24.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-gpr-arg" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edi, %edi" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-25.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-25.c
new file mode 100644
index 0000000..902d3ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-25.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-arg" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edi, %edi" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-26.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-26.c
new file mode 100644
index 0000000..8fb5299
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-26.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -msse2 -fzero-call-used-regs=all-arg" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "pxor\[ \t\]+%xmm0, %xmm0" } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm1" } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm2" } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm3" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm4" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm5" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm6" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movaps\[ \t\]+%xmm0, %xmm7" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-27.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-27.c
new file mode 100644
index 0000000..26ceacf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-27.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr-arg" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r9d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-28.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-28.c
new file mode 100644
index 0000000..044e4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-28.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mmmx -fzero-call-used-regs=all" } */
+/* { dg-require-effective-target ia32 } */
+
+typedef int __v2si __attribute__ ((vector_size (8)));
+
+__v2si ret_mmx (void)
+{
+ return (__v2si) { 123, 345 };
+}
+
+/* { dg-final { scan-assembler "pxor\[ \t\]+%mm1, %mm1" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm2" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm3" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm4" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm5" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm6" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm7" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-29.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-29.c
new file mode 100644
index 0000000..6270645
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-29.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all" } */
+
+long double ret_x87 (void)
+{
+ return 1.1L;
+}
+
+/* { dg-final { scan-assembler-times "fldz" 7 } } */
+/* { dg-final { scan-assembler-times "fstp\[ \t\]+%st\\(0\\)" 7 } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c
new file mode 100644
index 0000000..89e69b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-30.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-30.c
new file mode 100644
index 0000000..c4e9930
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-30.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all" } */
+
+_Complex long double ret_x87_cplx (void)
+{
+ return 1.1L + 1.2iL;
+}
+
+/* { dg-final { scan-assembler-times "fldz" 8 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "fstp\[ \t\]+%st\\(0\\)" 8 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "fldz" 6 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "fstp\[ \t\]+%st\\(0\\)" 6 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-31.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-31.c
new file mode 100644
index 0000000..afa8b33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-31.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mmmx -fzero-call-used-regs=all-arg" } */
+/* { dg-require-effective-target ia32 } */
+
+typedef int __v2si __attribute__ ((vector_size (8)));
+
+__v2si ret_mmx (void)
+{
+ return (__v2si) { 123, 345 };
+}
+
+/* { dg-final { scan-assembler "pxor\[ \t\]+%mm1, %mm1" } } */
+/* { dg-final { scan-assembler "movq\[ \t\]+%mm1, %mm2" } } */
+/* { dg-final { scan-assembler-not "movq\[ \t\]+%mm1, %mm\[34567\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-32.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-32.c
new file mode 100644
index 0000000..ca3261f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-32.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all -mno-80387" } */
+
+int
+foo (int x)
+{
+ return (x + 1);
+}
+
+/* { dg-final { scan-assembler-not "fldz" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c
new file mode 100644
index 0000000..1e98d17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+extern void foo (void) __attribute__ ((zero_call_used_regs("used-gpr")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c
new file mode 100644
index 0000000..56aecda
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+__attribute__ ((zero_call_used_regs("all-gpr")))
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%eax, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c
new file mode 100644
index 0000000..fa83185
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
+
+extern void foo (void) __attribute__ ((zero_call_used_regs("skip")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c
new file mode 100644
index 0000000..0444a21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=used-gpr" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" { target ia32 } } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edi, %edi" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c
new file mode 100644
index 0000000..75356db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %ecx" } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %esi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %edi" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r8d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r9d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r10d" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+%edx, %r11d" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c
new file mode 100644
index 0000000..64755b00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
+
+extern int foo (int) __attribute__ ((zero_call_used_regs("used-gpr")));
+
+int
+foo (int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" { target ia32 } } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edi, %edi" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/microblaze/others/strings1.c b/gcc/testsuite/gcc.target/microblaze/others/strings1.c
index 7a63faf..efaf3c6 100644
--- a/gcc/testsuite/gcc.target/microblaze/others/strings1.c
+++ b/gcc/testsuite/gcc.target/microblaze/others/strings1.c
@@ -1,13 +1,14 @@
/* { dg-options "-O3" } */
+/* { dg-final { scan-assembler "\.rodata*" } } */
+/* { dg-final { scan-assembler "addik\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),\\\$LC.*" } } */
+/* { dg-final { scan-assembler "\lwi\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),*" } } */
#include <string.h>
-/* { dg-final { scan-assembler "\.rodata*" } } */
extern void somefunc (char *);
int testfunc ()
{
char string2[80];
-/* { dg-final { scan-assembler "\lwi\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r0,.LC*" } } */
strcpy (string2, "hello");
somefunc (string2);
}
diff --git a/gcc/testsuite/gcc.target/msp430/data-attributes-2.c b/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
index 6113e99..cf456f1 100644
--- a/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
+++ b/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
@@ -7,16 +7,17 @@
These attributes also conflict with the "section" attribute, since they
specify sections to put the variables into. */
int __attribute__((persistent)) p = 10;
-int __attribute__((persistent,lower)) pl = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent,lower)) pl = 20;
int __attribute__((persistent,upper)) pu = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'persistent'" } */
int __attribute__((persistent,either)) pe = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'persistent'" } */
/* This one results in an error because the handler for persistent sets the
section to .persistent there and then. */
-int __attribute__((persistent,section(".data.foo"))) ps = 20; /* { dg-error "section of 'ps' conflicts with previous declaration" } */
-int __attribute__((persistent,noinit)) pn = 2; /* { dg-warning "'noinit' attribute cannot be applied to variables with specific sections" } */
+int __attribute__((persistent,section(".data.foo"))) ps = 20; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent,noinit)) pn = 2; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent)) zz; /* { dg-warning "ignoring 'persistent' attribute set on uninitialized variable" } */
int __attribute__((noinit)) n;
-int __attribute__((noinit,lower)) nl; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,lower)) nl;
int __attribute__((noinit,upper)) nu; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'noinit'" } */
int __attribute__((noinit,either)) ne; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'noinit'" } */
int __attribute__((noinit,persistent)) np; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'noinit'" } */
@@ -25,8 +26,8 @@ int __attribute__((noinit,section(".data.foo"))) ns; /* { dg-warning "ignoring a
int __attribute__((lower)) l = 20;
int __attribute__((lower,upper)) lu = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'lower'" } */
int __attribute__((lower,either)) le = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'lower'" } */
-int __attribute__((lower,persistent)) lp = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'lower'" } */
-int __attribute__((lower,noinit)) ln; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,persistent)) lp = 20;
+int __attribute__((lower,noinit)) ln;
int __attribute__((lower,section(".data.foo"))) ls = 30;
int __attribute__((upper)) u = 20;
diff --git a/gcc/testsuite/gcc.target/msp430/pr78818-auto-warn.c b/gcc/testsuite/gcc.target/msp430/pr78818-auto-warn.c
index 3dba361..7ed5ca8 100644
--- a/gcc/testsuite/gcc.target/msp430/pr78818-auto-warn.c
+++ b/gcc/testsuite/gcc.target/msp430/pr78818-auto-warn.c
@@ -8,8 +8,8 @@ static __attribute__((persistent)) int persistent_4_g = 0;
int
main (void)
{
- __attribute__((persistent)) int persistent_1 = 1; /* { dg-warning "attribute has no effect on automatic" } */
- __attribute__((persistent)) int persistent_2 = 0; /* { dg-warning "attribute has no effect on automatic" } */
+ __attribute__((persistent)) int persistent_1 = 1; /* { dg-error "'persistent' attribute cannot be specified for local variables" } */
+ __attribute__((persistent)) int persistent_2 = 0; /* { dg-error "'persistent' attribute cannot be specified for local variables" } */
static __attribute__((persistent)) int persistent_3 = 1;
static __attribute__((persistent)) int persistent_4 = 0;
return 0;
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c
new file mode 100644
index 0000000..1bd6a14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+ (msp430x) and hwmult (none), when compiling at -O3. */
+
+char arr[2];
+char a;
+char *ptr;
+
+/*
+** foo:
+** ...
+** MOV.B \&a, \&arr\+1
+** MOV.* #arr\+2, \&ptr
+** ...
+*/
+
+void
+foo (void)
+{
+ arr[1] = a;
+ ptr = arr + 2;
+}
+
+extern void ext (void);
+
+/*
+** bar:
+** ...
+** CALL.* #ext
+** CALL.* #ext
+** ...
+*/
+
+void
+bar (void)
+{
+ ext ();
+ ext ();
+}
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c
new file mode 100644
index 0000000..1e48625
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mhwmult=f5series" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+ (msp430x) and f5series hwmult, when compiling at -O3. */
+
+volatile unsigned long a;
+volatile unsigned int b;
+volatile unsigned long c;
+unsigned long res1;
+unsigned long res2;
+unsigned long res3;
+
+/*
+** foo:
+** ...
+** MOV.B #16, R14
+** CALL.* #__mspabi_slll
+** ...
+** MOV.* \&res2.*
+** ...
+** RLA.*RLC.*
+** ...
+** MOV.* \&res3.*
+** ...
+** RLA.*RLC.*
+** ...
+*/
+void foo (void)
+{
+ /* Use the shift library function for this. */
+ res1 = (a << 16) | b;
+ /* Emit 7 inline shifts for this. */
+ res2 *= 128;
+ /* Perform this multiplication inline, using addition and shifts. */
+ res3 *= 100;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c
new file mode 100644
index 0000000..8f3d1b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+ (msp430x) and hwmult (none), when compiling at -Os. */
+
+char arr[2];
+char a;
+char *ptr;
+
+/*
+** foo:
+** ...
+** MOV.B \&a, \&arr\+1
+** MOV.* #arr\+2, \&ptr
+** ...
+*/
+
+void
+foo (void)
+{
+ arr[1] = a;
+ ptr = arr + 2;
+}
+
+extern void ext (void);
+
+/*
+** bar:
+** ...
+** MOV.* #ext, R10
+** CALL.* R10
+** CALL.* R10
+** ...
+*/
+
+void
+bar (void)
+{
+ ext ();
+ ext ();
+}
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c
new file mode 100644
index 0000000..67d9198
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mhwmult=f5series" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+ (msp430x) and f5series hwmult, when compiling at -Os. */
+
+volatile unsigned long a;
+volatile unsigned int b;
+volatile unsigned long c;
+unsigned long res1;
+unsigned long res2;
+unsigned long res3;
+
+/*
+** foo:
+** ...
+** MOV.B #16, R14
+** CALL.* #__mspabi_slll
+** ...
+** MOV.B #7, R14
+** CALL.* #__mspabi_slll
+** ...
+** MOV.B #100, R14
+** MOV.B #0, R15
+** ...
+** CALL.* #__mspabi_mpyl_f5hw
+** ...
+*/
+void foo (void)
+{
+ /* Use the shift library function for this. */
+ res1 = (a << 16) | b;
+ /* Likewise. */
+ res2 *= 128;
+ /* Use the hardware multiply library function for this. */
+ res3 *= 100;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-consts.c b/gcc/testsuite/gcc.target/powerpc/altivec-consts.c
index d59f9b4..c68c681 100644
--- a/gcc/testsuite/gcc.target/powerpc/altivec-consts.c
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-consts.c
@@ -1,7 +1,7 @@
/* { dg-do run { target vmx_hw } } */
-/* { dg-do compile } */
+/* { dg-do compile { target { ! vmx_hw } } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
-/* { dg-options "-maltivec -mabi=altivec -O2" } */
+/* { dg-options "-maltivec -mabi=altivec -O2 -save-temps" } */
/* Check that "easy" AltiVec constants are correctly synthesized. */
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-2.c b/gcc/testsuite/gcc.target/powerpc/bcd-2.c
index 2f51dee..95c3699 100644
--- a/gcc/testsuite/gcc.target/powerpc/bcd-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-2.c
@@ -14,6 +14,8 @@
/* { dg-final { scan-assembler-not "stxvw4x" } } */
/* { dg-final { scan-assembler-not "stxvd2x" } } */
+#include <altivec.h>
+
typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t;
typedef __int128_t scalar_128_t;
typedef unsigned long long scalar_64_t;
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-3.c b/gcc/testsuite/gcc.target/powerpc/bcd-3.c
index 1b20841..7948a0c 100644
--- a/gcc/testsuite/gcc.target/powerpc/bcd-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-3.c
@@ -18,6 +18,8 @@ typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t;
typedef __int128_t scalar_128_t;
typedef unsigned long long scalar_64_t;
+#include <altivec.h>
+
/* Test whether the peephole works to allow folding a bcdadd, with a
bcdadd_<test> into a single instruction. */
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-4.c b/gcc/testsuite/gcc.target/powerpc/bcd-4.c
new file mode 100644
index 0000000..2c8554d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-4.c
@@ -0,0 +1,521 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-require-effective-target power10_hw } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
+/* { dg-final { scan-assembler-times {\mbcdadd\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mbcdsub\M} 18 } } */
+/* { dg-final { scan-assembler-times {\mbcds\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mdenbcdq\M} 1 } } */
+
+#include <altivec.h>
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#endif
+
+
+#define BCD_POS0 12 // 0xC
+#define BCD_POS1 15 // 0xF
+#define BCD_NEG 13 // 0xD
+
+void abort (void);
+
+ union conv_t
+ {
+ _Decimal128 d128;
+ vector unsigned char ch;
+ vector long long unsigned int vllui;
+ } conv;
+
+_Decimal128 convert_vec_char (vector unsigned char a)
+{
+ union conv_t conv;
+ _Decimal128 result;
+
+ conv.ch = a;
+ result = conv.d128;
+ return result;
+}
+
+vector unsigned char maxbcd(unsigned int sign)
+{
+ vector unsigned char result;
+ int i;
+
+ for (i = 15; i > 0; i--)
+ result[i] = 0x99;
+
+ result[0] = sign << 4 | 0x9;
+}
+
+vector unsigned char num2bcd(long int a, int encoding)
+{
+ int i;
+ unsigned int hi, low, sign;
+
+ vector unsigned char result;
+
+ if (a > 0) {
+ if (encoding == 0)
+ sign = BCD_POS0;
+ else
+ sign = BCD_POS1;
+
+ } else {
+ sign = BCD_NEG;
+ a = -a;
+ }
+
+ hi = a % 10; // 1st digit
+ a = a / 10;
+ result[0] = hi << 4| sign;
+
+ for (i = 1; i < 16; i++)
+ {
+ low = a % 10;
+ a = a / 10;
+ hi = a % 10;
+ a = a / 10;
+ result[i] = hi << 4 | low;
+ }
+
+
+ return result;
+}
+
+int main ()
+{
+ int i;
+ long int value_a, value_b, value_result;
+ vector unsigned char a, b, result, exp_result;
+ _Decimal128 result_d128, exp_result_d128;
+
+ /* Make a and b positive BCD numbers */
+ value_a = 1020304;
+ a = num2bcd(value_a, 0);
+
+ value_b = 101010;
+ b = num2bcd(value_b, 0);
+
+ value_result = value_a + value_b;
+ exp_result = num2bcd(value_result, 0);
+
+ result = __builtin_bcdadd (a, b, 0);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd result[%d] = %d does not match "
+ "expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* result should be positive */
+ if ((result[0] & 0xF) != BCD_POS0)
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd sign of result is %d. Does not match "
+ "expected_result = %d\n",
+ result[0] & 0xF, BCD_POS0);
+#else
+ abort();
+#endif
+
+ /* Make a and b positive BCD numbers using alternate positive encoding. */
+ value_a = 1030507;
+ a = num2bcd(value_a, 1);
+
+ value_b = 204060;
+ b = num2bcd(value_b, 1);
+
+ value_result = value_a + value_b;
+ exp_result = num2bcd(value_result, 1);
+
+ result = __builtin_bcdadd (a, b, 1);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd result[%d] = %d does not match "
+ "expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* Result should be positive, alternate encoding. */
+ if ((result[0] & 0xF) != BCD_POS1)
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd sign of result is %d. Does not "
+ "match expected_result = %d\n",
+ result[0] & 0xF, BCD_POS1);
+#else
+ abort();
+#endif
+
+ /* Make a and b negative BCD numbers */
+ value_a = -1030507;
+ a = num2bcd(value_a, 0);
+
+ value_b = -1010101;
+ b = num2bcd(value_b, 0);
+
+ value_result = value_a + value_b;
+ exp_result = num2bcd(value_result, 0);
+
+ result = __builtin_bcdadd (a, b, 0);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd, neg result[%d] = %d does not match "
+ "expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* result should be negative */
+ if ((result[0] & 0xF) != BCD_NEG)
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd sign, neg of result is %d. Does not "
+ "match expected_result = %d\n",
+ result[0] & 0xF, BCD_NEG);
+#else
+ abort();
+#endif
+
+
+ /* Make a negative, b positive BCD numbers */
+ value_a = -1030507;
+ a = num2bcd(value_a, 0);
+
+ value_b = 1010101;
+ b = num2bcd(value_b, 0);
+
+ value_result = value_a - value_b;
+ exp_result = num2bcd(value_result, 0);
+
+ result = __builtin_bcdsub (a, b, 0);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+#if DEBUG
+ printf("ERROR: __builtin_bcdsub, neg result[%d] = %d does not match "
+ "expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* result should be positive, alt encoding */
+ if ((result[0] & 0xF) != BCD_NEG)
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd sign, of result is %d. Does not match "
+ "expected_result = %d\n",
+ result[0] & 0xF, BCD_NEG);
+#else
+ abort();
+#endif
+
+ /* Make a and b positive BCD numbers */
+ value_a = 1030507;
+ a = num2bcd(value_a, 1);
+
+ value_b = 1010101;
+ b = num2bcd(value_b, 1);
+
+ value_result = value_a - value_b;
+ exp_result = num2bcd(value_result, 1);
+
+ result = __builtin_bcdsub (a, b, 1);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+#if DEBUG
+ printf("ERROR:carll __builtin_bcdsub, pos result[%d] = %d does not "
+ "match expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* result should be positive */
+ if ((result[0] & 0xF) != BCD_POS1)
+#if DEBUG
+ printf("ERROR: __builtin_bcdsub sign, result is %d. Does not match "
+ "expected_result = %d\n",
+ result[0] & 0xF, BCD_POS1);
+#else
+ abort();
+#endif
+
+ /* Test overflow add and subtract. */
+ a = maxbcd(BCD_POS0);
+ b = maxbcd(BCD_POS0);
+
+ if(__builtin_bcdadd_ofl (a, b, 0) == 0)
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd did not overflow as expected\n");
+#else
+ abort();
+#endif
+
+ value_a = 99999999;
+ a = num2bcd(value_a, 0);
+
+ value_b = 999999999;
+ b = num2bcd(value_b, 0);
+
+ if(__builtin_bcdadd_ofl (a, b, 0))
+#if DEBUG
+ printf("ERROR: __builtin_bcdadd unexpectedly overflowed\n");
+#else
+ abort();
+#endif
+
+ a = maxbcd(BCD_NEG);
+ b = maxbcd(BCD_NEG);
+
+ if (__builtin_bcdsub_ofl (a, b, 0) == 0)
+#if DEBUG
+ printf("ERROR: __builtin_bcdsub did not overflow as expected\n");
+#else
+ abort();
+#endif
+
+ value_a = -99999999;
+ a = num2bcd(value_a, 0);
+
+ value_b = -999999999;
+ b = num2bcd(value_b, 0);
+
+ if (__builtin_bcdsub_ofl (a, b, 0))
+#if DEBUG
+ printf("ERROR: __builtin_bcdsub unexpectedly overflowed\n");
+#else
+ abort();
+#endif
+
+ /* Test arguments for valid/invalid */
+ if (__builtin_bcdinvalid (a))
+#if DEBUG
+ printf("ERROR: __builtin_invalid input is unexpectedly invalid.\n");
+#else
+ abort();
+#endif
+
+ a[3] = 0xBB; /* an invalid BCD digit */
+ if (!__builtin_bcdinvalid (a))
+#if DEBUG
+ printf("ERROR: __builtin_invalid input is unexpectedly valid.\n");
+#else
+ abort();
+#endif
+
+ value_a = 1020304;
+ a = num2bcd(value_a, 0);
+
+ value_b = 101010;
+ b = num2bcd(value_b, 0);
+
+ /* Test equality */
+ if (__builtin_bcdcmpeq (a, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 1.\n");
+#else
+ abort();
+#endif
+
+ if (!__builtin_bcdcmpeq (a, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 0.\n");
+#else
+ abort();
+#endif
+
+
+ /* Test a greater then b, inputs already setup this way. */
+ if (!__builtin_bcdcmpgt (a, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 0.\n");
+#else
+ abort();
+#endif
+
+ if (__builtin_bcdcmpgt (b, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 1.\n");
+#else
+ abort();
+#endif
+
+ if (__builtin_bcdcmpgt (a, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpgt input equal, result is unexpectedly "
+ "1.\n");
+#else
+ abort();
+#endif
+
+
+ if (!__builtin_bcdcmpge (a, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpge result is unexpectedly 0.\n");
+#else
+ abort();
+#endif
+
+ if (__builtin_bcdcmpge (b, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpge result is unexpectedly 1.\n");
+#else
+ abort();
+#endif
+
+ if (!__builtin_bcdcmpge (b, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmpge inputs equal result is unexpectedly "
+ "0.\n");
+#else
+ abort();
+#endif
+
+ /* Test a less then b. */
+ value_a = 101010;
+ a = num2bcd(value_a, 0);
+ value_b = 1020304;
+ b = num2bcd(value_b, 0);
+
+ if (!__builtin_bcdcmplt (a, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmplt result is unexpectedly 0.\n");
+#else
+ abort();
+#endif
+
+ if (__builtin_bcdcmplt (b, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmplt result is unexpectedly 1.\n");
+#else
+ abort();
+#endif
+
+ if (__builtin_bcdcmplt (b, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmplt inputs equal result is unexpectedly "
+ "1.\n");
+#else
+ abort();
+#endif
+
+
+ if (!__builtin_bcdcmple (a, b))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmple result is unexpectedly 0.\n");
+#else
+ abort();
+#endif
+
+ if (__builtin_bcdcmple (b, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmple result is unexpectedly 1.\n");
+#else
+ abort();
+#endif
+
+ if (!__builtin_bcdcmple (a, a))
+#if DEBUG
+ printf("ERROR: __builtin__bcdcmple inputs equal result is unexpectedly "
+ "0.\n");
+#else
+ abort();
+#endif
+
+ /* Test multipy 10 */
+ value_a = 1020304;
+ a = num2bcd(value_a, 0);
+
+ value_result = value_a * 10;
+ exp_result = num2bcd(value_result, 0);
+
+ result = __builtin_bcdmul10 (a);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+#if DEBUG
+ printf("ERROR:carll __builtin_bcdmul10, pos result[%d] = %d does not "
+ "match expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* result should be positive */
+ if ((result[0] & 0xF) != BCD_POS0)
+#if 0
+ printf("ERROR: __builtin_bcdmul10 sign, result is %d. Does not match "
+ "expected_result = %d\n",
+ result[0] & 0xF, BCD_POS1);
+#else
+ abort();
+#endif
+
+ /* Test divide 10 */
+ value_a = 1020304;
+ a = num2bcd(value_a, 0);
+
+ value_result = value_a / 10;
+ exp_result = num2bcd(value_result, 0);
+
+ result = __builtin_bcddiv10 (a);
+
+ for (i = 0; i < 16; i++)
+ if (exp_result[i] != result[i]) {
+#if DEBUG
+ printf("ERROR:carll __builtin_bcddiv10, pos result[%d] = %d does not "
+ "match expected_result[%d] = %d\n",
+ i, result[i], i, exp_result[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* result should be positive */
+ if ((result[0] & 0xF) != BCD_POS0)
+#if DEBUG
+ printf("ERROR: __builtin_bcddiv10 sign, result is %d. Does not match "
+ "expected_result = %d\n",
+ result[0] & 0xF, BCD_POS1);
+#else
+ abort();
+#endif
+
+ value_a = 1020304;
+ exp_result_d128 = 1020304;
+ a = num2bcd(value_a, 0);
+
+ conv.ch = a;
+ conv.d128 = __builtin_bcd2dfp (a);
+ result_d128 = conv.d128;
+
+ if (result_d128 != exp_result_d128)
+#if DEBUG
+ printf("ERROR: __builtin_bcd2dfp, result does not match expected_result."
+ "\n");
+#else
+ abort();
+#endif
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bswap64-4.c b/gcc/testsuite/gcc.target/powerpc/bswap64-4.c
index a3c0553..5acbb91 100644
--- a/gcc/testsuite/gcc.target/powerpc/bswap64-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/bswap64-4.c
@@ -7,6 +7,12 @@
/* { dg-final { scan-assembler-times "ldbrx" 1 { target has_arch_pwr7 } } } */
/* { dg-final { scan-assembler-times "stdbrx" 1 { target has_arch_pwr7 } } } */
+/* On some versions of dejagnu this test will fail when biarch testing
+ with RUNTESTFLAGS="--target_board=unix'{-m64,-m32}'" due to -m32
+ being added on the command line after the dg-options -mpowerpc64.
+ common/config/rs6000/rs6000-common.c:rs6000_handle_option disables
+ -mpowerpc64 for -m32. */
+
long long swap_load (long long *a) { return __builtin_bswap64 (*a); }
long long swap_reg (long long a) { return __builtin_bswap64 (a); }
void swap_store (long long *a, long long b) { *a = __builtin_bswap64 (b); }
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c b/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c
index a5300b4..647186d 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c b/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c
index e67fb66..3a07f7f 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power8" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c b/gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c
index ca58afe..9603177 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c b/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c
index 4f4ad8f..ec1740d 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power8" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c
index 777d00d..16126bf 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c
@@ -1,7 +1,6 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed only on 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c
index a369dc1..53fa5d8 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c
@@ -1,7 +1,6 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power8" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
index 9a80c27..44cc778 100644
--- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
@@ -1,7 +1,6 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target ilp32 } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
#include <altivec.h>
@@ -11,5 +10,5 @@
int
test_byte_in_set (unsigned char b, unsigned long long set_members)
{
- return __builtin_byte_in_set (b, set_members); /* { dg-error "'__builtin_byte_in_set' is not supported in this compiler configuration" } */
+ return __builtin_byte_in_set (b, set_members); /* { dg-warning "implicit declaration of function" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/cfuged-1.c b/gcc/testsuite/gcc.target/powerpc/cfuged-1.c
index 198d541..0088309 100644
--- a/gcc/testsuite/gcc.target/powerpc/cfuged-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/cfuged-1.c
@@ -1,6 +1,7 @@
-/* { dg-do run } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
/* { dg-require-effective-target lp64 } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/powerpc/cntlzdm-1.c b/gcc/testsuite/gcc.target/powerpc/cntlzdm-1.c
index e9ee835..a6bc2d6 100644
--- a/gcc/testsuite/gcc.target/powerpc/cntlzdm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/cntlzdm-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-mdejagnu-cpu=power10" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/cnttzdm-1.c b/gcc/testsuite/gcc.target/powerpc/cnttzdm-1.c
index 4c05c1b..ba94871 100644
--- a/gcc/testsuite/gcc.target/powerpc/cnttzdm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/cnttzdm-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-mdejagnu-cpu=power10" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/cprophard.c b/gcc/testsuite/gcc.target/powerpc/cprophard.c
index f93081f..0aac9a5 100644
--- a/gcc/testsuite/gcc.target/powerpc/cprophard.c
+++ b/gcc/testsuite/gcc.target/powerpc/cprophard.c
@@ -1,6 +1,6 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-do compile { target lp64 } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mno-pcrel" } */
/* { dg-final { scan-assembler {ld 2,(24|40)\(1\)} } } */
/* From a linux kernel mis-compile of net/core/skbuff.c. */
diff --git a/gcc/testsuite/gcc.target/powerpc/dg-future-1.c b/gcc/testsuite/gcc.target/powerpc/dg-future-1.c
index 0dbfb06..bc2b3b7 100644
--- a/gcc/testsuite/gcc.target/powerpc/dg-future-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/dg-future-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run { target { powerpc*-*-* } } } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
/* This tests that power10_hw works. */
diff --git a/gcc/testsuite/gcc.target/powerpc/dimode_off.c b/gcc/testsuite/gcc.target/powerpc/dimode_off.c
index 19ca40c..12718ea 100644
--- a/gcc/testsuite/gcc.target/powerpc/dimode_off.c
+++ b/gcc/testsuite/gcc.target/powerpc/dimode_off.c
@@ -1,5 +1,5 @@
/* { dg-do assemble } */
-/* { dg-options "-O2 -fno-align-functions -fno-asynchronous-unwind-tables -mtraceback=no -save-temps" } */
+/* { dg-options "-O2 -fno-align-functions -fno-asynchronous-unwind-tables -mtraceback=no -mno-prefixed -save-temps" } */
void w1 (void *x, long long y) { *(long long *) (x + 32767) = y; }
void w2 (void *x, long long y) { *(long long *) (x + 32766) = y; }
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-hw3.c b/gcc/testsuite/gcc.target/powerpc/float128-hw3.c
index b3bbeb2..630c93d 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-hw3.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-hw3.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target lp64 } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-require-effective-target float128 } */
-/* { dg-options "-mpower9-vector -O2 -ffast-math -std=c11" } */
+/* { dg-options "-mpower9-vector -O2 -ffast-math -std=c11 -mno-pcrel" } */
/* Test to make sure the compiler calls the external function instead of doing
the built-in processing for _Float128 functions that have hardware support
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-mix-2.c b/gcc/testsuite/gcc.target/powerpc/float128-mix-2.c
new file mode 100644
index 0000000..6122713
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-mix-2.c
@@ -0,0 +1,16 @@
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-O2 -mvsx -Wno-psabi -mabi=ieeelongdouble -mlong-double-128" } */
+
+/* Test to make sure that __float128 and long double do not generate errors if
+ long double uses the IEEE 128-bit format. */
+__float128
+add (__float128 a, long double b)
+{
+ return a+b;
+}
+
+long double
+sub (long double a, __float128 b)
+{
+ return a-b;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-mix-3.c b/gcc/testsuite/gcc.target/powerpc/float128-mix-3.c
new file mode 100644
index 0000000..a2582bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-mix-3.c
@@ -0,0 +1,16 @@
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-O2 -mvsx -Wno-psabi -mabi=ibmlongdouble -mlong-double-128" } */
+
+/* Test to make sure that __float128 and __ibm128 cannot be combined
+ together. */
+__float128
+add (__float128 a, __ibm128 b)
+{
+ return a+b; /* { dg-error "IEEE 128-bit and IBM 128-bit floating point" } */
+}
+
+__ibm128
+sub (__ibm128 a, __float128 b)
+{
+ return a-b; /* { dg-error "IEEE 128-bit and IBM 128-bit floating point" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-mix.c b/gcc/testsuite/gcc.target/powerpc/float128-mix.c
index 71f840c..48e651c 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-mix.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-mix.c
@@ -1,15 +1,17 @@
-/* { dg-do compile { target { powerpc*-*-linux* } } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-O2 -mvsx" } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-O2 -mvsx -Wno-psabi -mabi=ibmlongdouble -mlong-double-128" } */
-
-/* Test to make sure that __float128 and long double cannot be combined together. */
-__float128 add (__float128 a, long double b)
+/* Test to make sure that __float128 and long double cannot be combined
+ together, when long double uses the IBM extended double format, and
+ __float128 uses the IEEE 128-bit format. */
+__float128
+add (__float128 a, long double b)
{
- return a+b; /* { dg-error "__float128 and long double cannot be used in the same expression" } */
+ return a+b; /* { dg-error "IEEE 128-bit and IBM 128-bit floating point" } */
}
-__ibm128 sub (long double a, __float128 b)
+long double
+sub (long double a, __float128 b)
{
- return a-b; /* { dg-error "__float128 and long double cannot be used in the same expression" } */
+ return a-b; /* { dg-error "IEEE 128-bit and IBM 128-bit floating point" } */
}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-type-1.c b/gcc/testsuite/gcc.target/powerpc/float128-type-1.c
index 13152ac..53f9e35 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-type-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-type-1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { powerpc64*-*-linux* && lp64 } } } */
+/* { dg-do compile { target { *-*-linux* && lp64 } } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mdejagnu-cpu=power8 -O2 -mno-float128" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-type-2.c b/gcc/testsuite/gcc.target/powerpc/float128-type-2.c
index 5644281..02dbad1 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-type-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-type-2.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { powerpc64-*-linux* && lp64 } } } */
+/* { dg-do compile { target { *-*-linux* && lp64 } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-options "-mdejagnu-cpu=power9 -O2 -mno-float128" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p9.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p9.c
index ff03c9a..8a4c380 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p9.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-char.p9.c
@@ -12,7 +12,6 @@
/* { dg-final { scan-assembler-times "stxv" 6 { target ilp32 } } } */
/* { dg-final { scan-assembler-times "lbz" 6 { target ilp32 } } } */
-/* { dg-final { scan-assembler-times "addi" 3 { target ilp32 } } } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p9.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p9.c
index 868b673..1abf19d 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p9.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-int.p9.c
@@ -18,7 +18,6 @@
/* { dg-final { scan-assembler-times {\madd\M} 3 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mstxv\M} 6 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mlwz\M} 6 { target ilp32 } } } */
-/* { dg-final { scan-assembler-times {\maddi\M} 3 { target ilp32 } } } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p7.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p7.c
index 033d21c..b97fcb4 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p7.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p7.c
@@ -22,7 +22,6 @@
/* -m32 target with constant test uses (+2)li where the -m64 has an ld */
/* { dg-final { scan-assembler-times {\mli\M} 5 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\maddi\M} 6 { target lp64 } } } */
-/* { dg-final { scan-assembler-times {\maddi\M} 4 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mstxvd2x\M|\mstvx\M} 3 } } */
/* { dg-final { scan-assembler-times {\mrldic\M|\mrlwinm\M} 3 } } */
/* { dg-final { scan-assembler-times {\mldx\M} 3 { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p8.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p8.c
index 0b624d2..8ddce3fd 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p8.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-extract-longlong.p8.c
@@ -17,7 +17,6 @@
/* { dg-final { scan-assembler-times {\mstxvd2x\M|\mstxvw4x\M} 4 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\madd\M} 3 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mlwz\M} 11 { target ilp32 } } } */
-/* { dg-final { scan-assembler-times {\maddi\M} 4 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mmfvsrd\M} 6 { target lp64 } } } */
/* { dg-final { scan-assembler-times {\mmtvsrd\M} 3 { target lp64 } } } */
/* { dg-final { scan-assembler-times {\mxxpermdi\M} 3 { target le } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-insert-int-p9.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-insert-int-p9.c
index 81ac1f1..a851fd6 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-insert-int-p9.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-insert-int-p9.c
@@ -58,8 +58,6 @@ testui2_cst(unsigned int x, vector unsigned int v)
/* { dg-final { scan-assembler-times {\mmtvsrwz\M} 4 { target lp64 } } } */
/* { dg-final { scan-assembler-times {\mxxinsertw\M} 4 { target lp64 } } } */
-
-/* { dg-final { scan-assembler-times {\maddi\M} 8 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mstw\M} 8 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mlxv\M} 8 { target ilp32 } } } */
/* { dg-final { scan-assembler-times {\mlvewx\M} 4 { target ilp32 } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-char.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-char.c
index 7406039..713fed7 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-char.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-char.c
@@ -120,6 +120,6 @@ test6_nor (vector unsigned char x, vector unsigned char y)
return *foo;
}
-/* { dg-final { scan-assembler-times {\mxxlor\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlor\M} 7 } } */
/* { dg-final { scan-assembler-times {\mxxlxor\M} 6 } } */
-/* { dg-final { scan-assembler-times {\mxxlnor\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxlnor\M} 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-int.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-int.c
index a7c6366..4d1c78f 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-int.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-int.c
@@ -119,6 +119,6 @@ test6_nor (vector unsigned int x, vector unsigned int y)
return *foo;
}
-/* { dg-final { scan-assembler-times {\mxxlor\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlor\M} 7 } } */
/* { dg-final { scan-assembler-times {\mxxlxor\M} 6 } } */
-/* { dg-final { scan-assembler-times {\mxxlnor\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxlnor\M} 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-longlong.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-longlong.c
index 10c69d3..27ef09a 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-longlong.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-longlong.c
@@ -156,6 +156,6 @@ test6_nor (vector unsigned long long x, vector unsigned long long y)
// For simplicity, this test now only targets "powerpc_p8vector_ok" environments
// where the answer is expected to be 6.
-/* { dg-final { scan-assembler-times {\mxxlor\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlor\M} 9 } } */
/* { dg-final { scan-assembler-times {\mxxlxor\M} 6 } } */
-/* { dg-final { scan-assembler-times {\mxxlnor\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlnor\M} 3 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-short.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-short.c
index 8352a7f..f796c5b3 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-short.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-ors-short.c
@@ -119,6 +119,6 @@ test6_nor (vector unsigned short x, vector unsigned short y)
return *foo;
}
-/* { dg-final { scan-assembler-times {\mxxlor\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlor\M} 7 } } */
/* { dg-final { scan-assembler-times {\mxxlxor\M} 6 } } */
-/* { dg-final { scan-assembler-times {\mxxlnor\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxlnor\M} 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-char.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-char.c
index 7fe3e0b..e74308c 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-char.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-char.c
@@ -104,5 +104,5 @@ test6_nand (vector unsigned char x, vector unsigned char y)
return *foo;
}
-/* { dg-final { scan-assembler-times {\mxxlnand\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlnand\M} 3 } } */
/* { dg-final { scan-assembler-times {\mxxlorc\M} 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-int.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-int.c
index 61d3405..57edaad 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-int.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-int.c
@@ -104,5 +104,5 @@ test6_nand (vector unsigned int x, vector unsigned int y)
return *foo;
}
-/* { dg-final { scan-assembler-times {\mxxlnand\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlnand\M} 3 } } */
/* { dg-final { scan-assembler-times {\mxxlorc\M} 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-longlong.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-longlong.c
index 8e14927..d4b8579 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-longlong.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-longlong.c
@@ -102,5 +102,5 @@ test6_nand (vector unsigned long long x, vector unsigned long long y)
return *foo;
}
+/* { dg-final { scan-assembler-times {\mxxlnand\M} 3 } } */
/* { dg-final { scan-assembler-times {\mxxlorc\M} 6 } } */
-/* { dg-final { scan-assembler-times {\mxxlnand\M} 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-short.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-short.c
index cc354b9..bf98652 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-short.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-logical-other-short.c
@@ -104,5 +104,5 @@ test6_nand (vector unsigned short x, vector unsigned short y)
return *foo;
}
-/* { dg-final { scan-assembler-times {\mxxlnand\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mxxlnand\M} 3 } } */
/* { dg-final { scan-assembler-times {\mxxlorc\M} 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/le-altivec-consts.c b/gcc/testsuite/gcc.target/powerpc/le-altivec-consts.c
index f48ef44..a1db5e9 100644
--- a/gcc/testsuite/gcc.target/powerpc/le-altivec-consts.c
+++ b/gcc/testsuite/gcc.target/powerpc/le-altivec-consts.c
@@ -1,7 +1,7 @@
/* { dg-do run { target vmx_hw } } */
-/* { dg-do compile } */
+/* { dg-do compile { target { ! vmx_hw } } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
-/* { dg-options "-maltivec -mabi=altivec -O2" } */
+/* { dg-options "-maltivec -mabi=altivec -O2 -save-temps" } */
/* Check that "easy" AltiVec constants are correctly synthesized. */
diff --git a/gcc/testsuite/gcc.target/powerpc/localentry-1.c b/gcc/testsuite/gcc.target/powerpc/localentry-1.c
index c3c5168..1343df2 100644
--- a/gcc/testsuite/gcc.target/powerpc/localentry-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/localentry-1.c
@@ -1,11 +1,10 @@
/* { dg-do compile } */
-/* { dg-options "-mdejagnu-cpu=power10 -O2 -mpcrel" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
/* { dg-require-effective-target powerpc_elfv2 } */
/* { dg-require-effective-target power10_ok } */
-/* Ensure we generate ".localentry fn,1" for both leaf and non-leaf functions.
- At present, -mcpu=power10 does not enable pc-relative mode, so make sure we
- enable it to be able to check for .localentry. */
+/* Ensure we generate ".localentry fn,1" for both leaf and non-leaf
+ functions. */
extern int y (int);
diff --git a/gcc/testsuite/gcc.target/powerpc/lsbb-runnable.c b/gcc/testsuite/gcc.target/powerpc/lsbb-runnable.c
index 7da530c..2e97cc1 100644
--- a/gcc/testsuite/gcc.target/powerpc/lsbb-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/lsbb-runnable.c
@@ -6,8 +6,9 @@
int vec_test_lsbb_all_ones (vector unsigned char);
*/
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-fno-inline -mdejagnu-cpu=power10 -O2" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/mma-alignment.c b/gcc/testsuite/gcc.target/powerpc/mma-alignment.c
new file mode 100644
index 0000000..0981893
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mma-alignment.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hard_float } */
+/* { dg-options "-O2 -mhard-float" } */
+
+#include <stdlib.h>
+
+/* The MMA types below are enabled for pre-power10 compiles, because the
+ built-ins that use them must always be initialized in case the user has
+ a target attribute or pragma on a function that uses the MMA built-ins.
+ Since the test below doesn't need any other MMA support, we can enable
+ this test case on basically any cpu that has hard floating point
+ registers. */
+
+struct
+{
+ int __attribute__ ((__aligned__)) ivar;
+ __vector_pair pair;
+ __vector_quad quad;
+} s;
+
+int
+main (void)
+{
+ /* Verify default alignment is 16-byte aligned (BIGGEST_ALIGNMENT).
+ This may change in the future, but that is an ABI break, so this
+ hardcoded test case is here to be a noisy FAIL as a warning, in
+ case the ABI change was unintended and unwanted. An example of where
+ this can break an ABI is in glibc's struct _Unwind_Exception. */
+ if (__alignof__ (s.ivar) != 16)
+ abort ();
+
+ /* Verify __vector_pair types are 32-byte aligned. */
+ if (__alignof__ (s.pair) != 32)
+ abort ();
+
+ /* Verify __vector_quad types are 64-byte aligned. */
+ if (__alignof__ (s.quad) != 64)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mma-double-test.c b/gcc/testsuite/gcc.target/powerpc/mma-double-test.c
index 044a288..254af7f 100755
--- a/gcc/testsuite/gcc.target/powerpc/mma-double-test.c
+++ b/gcc/testsuite/gcc.target/powerpc/mma-double-test.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target ppc_mma_hw } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
@@ -180,6 +181,9 @@ main (int argc, char *argv[])
printf ("MMA double test fail: %d errors\n",ret);
else
printf ("MMA single test success: 0 MMA errors\n");
+#else
+ if (ret)
+ abort();
#endif
return ret;
diff --git a/gcc/testsuite/gcc.target/powerpc/mma-single-test.c b/gcc/testsuite/gcc.target/powerpc/mma-single-test.c
index 7e628df..ebbc5ae 100755
--- a/gcc/testsuite/gcc.target/powerpc/mma-single-test.c
+++ b/gcc/testsuite/gcc.target/powerpc/mma-single-test.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target ppc_mma_hw } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
@@ -188,6 +189,9 @@ main (int argc, char *argv[])
printf ("MMA single test fail: %d errors\n",ret);
else
printf ("MMA single test success: 0 MMA errors\n");
+#else
+ if (ret)
+ abort();
#endif
return ret;
diff --git a/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c b/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c
index 74187e1..8fa09b0 100644
--- a/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c
@@ -1,11 +1,10 @@
/* { dg-do compile } */
-/* { dg-options "-mdejagnu-cpu=power10 -O2 -mpcrel" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
/* { dg-require-effective-target powerpc_elfv2 } */
/* { dg-require-effective-target power10_ok } */
-/* Test that calls generated from PC-relative code are annotated with @notoc.
- At present, -mcpu=power10 does not enable pc-relative mode. Enable it here
- explicitly until it is turned on by default. */
+/* Test that calls generated from PC-relative code are annotated with
+ @notoc. */
extern int yy0 (int);
extern void yy1 (int);
@@ -40,4 +39,3 @@ int ww (void)
/* { dg-final { scan-assembler {yy0@notoc} } } */
/* { dg-final { scan-assembler {zz1@notoc} } } */
/* { dg-final { scan-assembler {zz0@notoc} } } */
-
diff --git a/gcc/testsuite/gcc.target/powerpc/p10-arch31.c b/gcc/testsuite/gcc.target/powerpc/p10-arch31.c
index a9a75ec..d4ec18c 100644
--- a/gcc/testsuite/gcc.target/powerpc/p10-arch31.c
+++ b/gcc/testsuite/gcc.target/powerpc/p10-arch31.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
/* This test will only run when the power10_hw_available test passes.
diff --git a/gcc/testsuite/gcc.target/powerpc/p10-identify.c b/gcc/testsuite/gcc.target/powerpc/p10-identify.c
index 8532697..6b00abf 100644
--- a/gcc/testsuite/gcc.target/powerpc/p10-identify.c
+++ b/gcc/testsuite/gcc.target/powerpc/p10-identify.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
/* This test will only run when the power10_hw_available test passes.
diff --git a/gcc/testsuite/gcc.target/powerpc/pdep-1.c b/gcc/testsuite/gcc.target/powerpc/pdep-1.c
index ab0efd2..458bcea 100644
--- a/gcc/testsuite/gcc.target/powerpc/pdep-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pdep-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-mdejagnu-cpu=power10" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pextd-1.c b/gcc/testsuite/gcc.target/powerpc/pextd-1.c
index ab08142..4f00cc9 100644
--- a/gcc/testsuite/gcc.target/powerpc/pextd-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pextd-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-mdejagnu-cpu=power10" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr64505.c b/gcc/testsuite/gcc.target/powerpc/pr64505.c
index 8601f2d..42b961f 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr64505.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr64505.c
@@ -1,231 +1,52 @@
-/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */
+/* { dg-do compile } */
/* { dg-skip-if "" { powerpc*-*-aix* } } */
-/* { dg-options "-O2 -mpowerpc64" } */
+/* { dg-options "-w -O2 -mpowerpc64" } */
/*
- * (below is inlined and simplified from previously included headers)
+ * (below is minimized test case)
*/
-struct fltcom_st {
- short fltbuf[950];
-} fltcom_ __attribute__((common)) ;
-#define CM_PLIBOR (*(((double *)&fltcom_ + 1)))
-#define CM_QMRG (*(((double *)&fltcom_ + 2)))
+extern double pow(double x, double y);
+extern long func ();
+short global0, global1;
+static int i0, i1, i2, i3, i4, i5;
+double dbl, *array0, *array1;
-struct fltcom2_st {
- short fltbuf2[56];
-} fltcom2_ __attribute__((common)) ;
-#define CM_FLPRV ((short *)&fltcom2_ + 17)
-#define CM_FLNXT ((short *)&fltcom2_ + 20)
-#define CM_FLCPN (*(((double *)&fltcom2_)))
-#define CM_FLCNT (*(((short *)&fltcom2_ + 12)))
-
-struct aidatcm_st {
- double cm_aid, cm_ext, cm_basis;
- short cm_aiday, cm_exday, cm_dperd, cm_aiexf, cm_aidex, cm_aiok,
- cm_aigdo, cm_aildo, cm_prev[3], cm_next[3], cm_aid_pad[2];
- double cm_rvgfact, cm_ai1st, cm_ai2nd;
- int cm_aieurok;
-} aidatcm_ __attribute__((common)) ;
-#define CM_EXDAY aidatcm_.cm_exday
-#define CM_BASIS aidatcm_.cm_basis
-#define CM_PREV aidatcm_.cm_prev
-
-struct cshfcm_st {
- short bufff[10862];
-} cshfcm_ __attribute__((common)) ;
-#define CM_FNUM (*(((short *)&cshfcm_ + 9038)))
-#define CM_FIFLX ((double *)&cshfcm_ + 1)
-#define CM_FEXTX ((double *)&cshfcm_ + 1201)
-#define CM_FSHDT ((short *)&cshfcm_ + 7230)
-
-struct calctsdb_st {
- short calctsdbbuff[115];
-} calctsdb_ __attribute__((common)) ;
-#define CM_CTUP_GOOD_TO_GO (*(((short *)&calctsdb_ + 16)))
-#define CM_PAYMENT_FREQUENCY (*(((short *)&calctsdb_ + 61)))
-#define CM_DISCOUNTING_DAYTYP (*(((short *)&calctsdb_ + 59)))
-
-struct cf600cm_st {
- short bufcf[14404];
-} cf600cm_ __attribute__((common)) ;
-#define CM_FLT_RFIXRATES ((double *)&cf600cm_ + 600)
-
-typedef struct { int id; int type; const char *name; } bregdb_bitinfo_t;
-
-int
-bregdb_eval_bbitcxt_bool_rv(const bregdb_bitinfo_t * const bbit,
- const int bbit_default,
- const void * const bregucxt);
-
-static const bregdb_bitinfo_t bbit_calc_dr_d33 =
- { 160667, 5, "bbit_calc_dr_d33" };
-#define bbit_calc_dr_d33__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_dr_d33, 0, 0)
-static const bregdb_bitinfo_t bbit_calc_sx_b24 =
- { 158854, 5, "bbit_calc_sx_b24" };
-#define bbit_calc_sx_b24__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_sx_b24, 0, 0)
-static const bregdb_bitinfo_t bbit_calc_dr_d36 =
- { 161244, 5, "bbit_calc_dr_d36" };
-#define bbit_calc_dr_d36__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_dr_d36, 0, 0)
-static const bregdb_bitinfo_t bbit_calc_dr_d37 =
- { 161315, 5, "bbit_calc_dr_d37" };
-#define bbit_calc_dr_d37__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_dr_d37, 0, 0)
-static const bregdb_bitinfo_t bbit_calc_dr_d47 =
- { 163259, 5, "bbit_calc_dr_d47" };
-#define bbit_calc_dr_d47__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_dr_d47, 0, 0)
-static const bregdb_bitinfo_t bbit_calc_dr_d46 =
- { 163239, 5, "bbit_calc_dr_d46" };
-#define bbit_calc_dr_d46__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_dr_d46, 0, 0)
-static const bregdb_bitinfo_t bbit_calc_dr_d62 =
- { 166603, 5, "bbit_calc_dr_d62" };
-#define bbit_calc_dr_d62__value() \
- bregdb_eval_bbitcxt_bool_rv(&bbit_calc_dr_d62, 0, 0)
-
-
-
-int dtyp_is_actact_(short *daytyp);
-double rnd_trunc_numb(double in, short num_digits, short rnd_or_trunc);
-void datetrn_(const short* dt, short* dt2);
-short difday_(short* daytyp_in, short* srtdti, short* enddti, short* ercode);
-
-
-double pow(double x, double y);
-
-
-/*
- * (above is inlined and simplified from previously included headers)
- */
-
-
-void calc_1566(
- short sCalcType,
- short sDayType,
- short sFreq,
- short asSettleDt[3],
- short asMtyDt[3],
- short asIssueDt[3],
- short asFCpnDt[3],
- double dCpn,
- short *psNoPer,
- double *pdExt,
- double *pdAI,
- double *pdAI2,
- double *pdFCpn,
- short *psRcode)
+void
+pr64505 (short *arg0, double *arg1)
{
-
- short ercode = 0;
- int isactact;
- short days_to_next_cpn = 0;
- const short discDaytype = CM_DISCOUNTING_DAYTYP;
-
- if(bbit_calc_sx_b24__value())
- isactact = (dtyp_is_actact_(&sDayType) != 0);
- else
- isactact = (sDayType == 1 || sDayType == 10);
-
- short days_in_current_period = difday_(&sDayType,CM_FLPRV,CM_FLNXT,&ercode);
- const short sfreq1 = (CM_CTUP_GOOD_TO_GO == 1 && CM_PAYMENT_FREQUENCY == 1);
-
- for (int j = 0; j < CM_FNUM; j++) {
-
- if(j == 0) {
- days_to_next_cpn = difday_(&sDayType,asSettleDt,CM_FLNXT,&ercode);
-
- if(isactact) {
- CM_FIFLX[j] = CM_FLCPN / sFreq;
- CM_FEXTX[j] = (double)days_to_next_cpn / (double)days_in_current_period;
- }
- else {
- CM_FIFLX[j] = CM_FLCPN * days_in_current_period;
- CM_FEXTX[j] = (double)days_to_next_cpn / (double)(1/sfreq1);
- }
-
- if(CM_FNUM == 1) {
- CM_FEXTX[j] = (double)days_to_next_cpn / ((double)1/sfreq1);
- }
- }
- else {
-
- short days_from_settle, days_in_period;
-
- if(bbit_calc_dr_d46__value()){
- days_from_settle = difday_(&sDayType,asSettleDt,
- &CM_FSHDT[j*3],&ercode);
- days_in_period = difday_(&sDayType,&CM_FSHDT[(j-1)*3],
- &CM_FSHDT[j*3],&ercode);
- }
-
- double cpn_rate = CM_PLIBOR;
-
- if(bbit_calc_dr_d62__value()) {
- if(j < CM_FLCNT && CM_FLT_RFIXRATES[j] != 0) cpn_rate = CM_FLT_RFIXRATES[j];
- }
- else {
- if(j < CM_FLCNT ) cpn_rate = CM_FLT_RFIXRATES[j];
- }
-
- if(bbit_calc_dr_d37__value()&& j >= CM_FLCNT && sCalcType == 1570) {
- cpn_rate = CM_PLIBOR + CM_QMRG;
-
- if(bbit_calc_dr_d36__value()){
- double projected_rate = pow((1 + CM_PLIBOR/100.0),
- (days_in_period)) - 1;
-
- projected_rate = projected_rate + CM_QMRG/100.0 * days_in_period;
- cpn_rate = 100 * projected_rate * (1/days_in_period);
- }
- }
-
-
- if(isactact) {
- CM_FIFLX[j] = cpn_rate / sFreq;
- CM_FEXTX[j] = CM_FEXTX[j-1] + 1;
-
- if(bbit_calc_dr_d46__value() && discDaytype != 0) {
- CM_FEXTX[j] = (double)days_from_settle / (double)(1/sfreq1);
- }
- }
- else {
- if(!bbit_calc_dr_d46__value()){
- days_from_settle = difday_(&sDayType,asSettleDt,
- &CM_FSHDT[j*3],&ercode);
- days_in_period = difday_(&sDayType,&CM_FSHDT[(j-1)*3],
- &CM_FSHDT[j*3],&ercode);
-
- }
-
- CM_FIFLX[j] = cpn_rate * days_in_period;
- CM_FEXTX[j] = (double)days_from_settle / (double)(1/sfreq1);
- }
-
- }
-
- if(bbit_calc_dr_d33__value() && CM_CTUP_GOOD_TO_GO != 0) {
- CM_FIFLX[j] = rnd_trunc_numb (CM_FIFLX[j], 0, 0);
- }
-
+ int error = 0;
+ short num = func (&global1 + 15, &error);
+ for (int j = 0; j < array0[0]; j++)
+ {
+ if (j == 0)
+ {
+ func (arg0, &global1 + 20, &error);
+ array0[0] = num;
+ }
+ else
+ {
+ double cr = (&dbl)[1];
+ if (func (&i4))
+ func (0, &(&array0)[j]);
+ if (func (&i5))
+ {
+ if ((&global1)[12])
+ cr = array1[j];
+ }
+ if (func (&i2)
+ && (&global1)[12])
+ {
+ if (func (&i1))
+ pow ((&dbl)[1], 2);
+ }
+ array0[j] = cr;
+ }
+ if (func (&i0) && global0)
+ func (((short *) array0 + 1)[j]);
}
-
-
- short accrued_days = difday_(&sDayType,CM_FLPRV,asSettleDt,&ercode);
-
- if(!bbit_calc_dr_d47__value()) {
- if(isactact) {
- *pdAI = (CM_FLCPN / sFreq)* accrued_days / ((double)days_in_current_period);
- }
- else{
- *pdAI = (CM_FLCPN / sFreq)* accrued_days / ((double)1/sFreq);
- }
- }
-
- CM_EXDAY = days_to_next_cpn;
- CM_BASIS = days_in_current_period;
- datetrn_(CM_FLPRV,CM_PREV);
+ short ad = func (&global1 + 15, 0);
+ if (func (&i3) && func ())
+ *arg1 = *((double *) &global1) * ad;
+ func (&global1 + 15);
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr67789.c b/gcc/testsuite/gcc.target/powerpc/pr67789.c
index 371d7a3..05d01ef 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr67789.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr67789.c
@@ -1,4 +1,5 @@
/* { dg-do assemble } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -msecure-plt -fPIC" } */
/* { dg-skip-if "" { powerpc*-*-darwin* powerpc-ibm-aix* } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr79439-1.c b/gcc/testsuite/gcc.target/powerpc/pr79439-1.c
index 539c96f..8eb08a4 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr79439-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr79439-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
-/* { dg-options "-O2 -fpic -fno-reorder-blocks -fno-inline-functions" } */
+/* { dg-options "-O2 -fpic -fno-reorder-blocks -fno-inline-functions -mno-pcrel" } */
/* On the Linux 64-bit ABIs, we eliminate NOP in the 'rec' call even if
-fpic is used. The recursive call should call the local alias. The
diff --git a/gcc/testsuite/gcc.target/powerpc/pr79439-2.c b/gcc/testsuite/gcc.target/powerpc/pr79439-2.c
index b53af44..9ebcf25 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr79439-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr79439-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
-/* { dg-options "-O2 -fpic -fno-reorder-blocks" } */
+/* { dg-options "-O2 -fpic -fno-reorder-blocks -mno-pcrel" } */
/* On the Linux 64-bit ABIs, we should not eliminate NOP in the 'rec' call if
-fpic is used because rec can be interposed at link time (since it has an
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83629.c b/gcc/testsuite/gcc.target/powerpc/pr83629.c
index 250378e..976b564 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr83629.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr83629.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-O2 -fPIC -frename-registers --param=sched-autopref-queue-depth=0 -mdejagnu-cpu=603" } */
extern void bar (void *);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr84112.c b/gcc/testsuite/gcc.target/powerpc/pr84112.c
index cd429df..8fbafa1 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr84112.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr84112.c
@@ -1,4 +1,5 @@
-/* { dg-do compile { target powerpc*-*-* } }*/
+/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
/* { dg-options "-mdejagnu-cpu=power8 -O3 -fstack-protector-strong -fpic" } */
char *b;
diff --git a/gcc/testsuite/gcc.target/powerpc/pr93122.c b/gcc/testsuite/gcc.target/powerpc/pr93122.c
index 8ea4eb6..97bcb0c 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr93122.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr93122.c
@@ -1,7 +1,7 @@
/* PR target/93122 */
/* { dg-require-effective-target power10_ok } */
/* { dg-do compile { target lp64 } } */
-/* { dg-options "-fstack-clash-protection -mprefixed -mcpu=power10" } */
+/* { dg-options "-fstack-clash-protection -mprefixed -mdejagnu-cpu=power10" } */
void bar (char *);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr94740.c b/gcc/testsuite/gcc.target/powerpc/pr94740.c
index 9c2b464..09decc3 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr94740.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr94740.c
@@ -1,7 +1,7 @@
/* PR rtl-optimization/94740 */
/* { dg-do compile } */
/* { dg-require-effective-target power10_ok } */
-/* { dg-options "-O2 -mdejagnu-cpu=power10 -mpcrel" } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
int array[8];
int
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96506-1.c b/gcc/testsuite/gcc.target/powerpc/pr96506-1.c
new file mode 100644
index 0000000..91835ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96506-1.c
@@ -0,0 +1,42 @@
+/* PR target/96506 */
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
+
+extern void bar0();
+extern void bar1();
+extern void bar2();
+extern void bar3();
+
+typedef __vector_pair vpair_t;
+typedef __vector_quad vquad_t;
+
+/* Verify we flag errors on the following. */
+
+void
+foo0 (void)
+{
+ __vector_pair v;
+ bar0 (v); /* { dg-error "invalid use of MMA operand of type .__vector_pair. as a function parameter" } */
+}
+
+void
+foo1 (void)
+{
+ vpair_t v;
+ bar1 (v); /* { dg-error "invalid use of MMA operand of type .__vector_pair. as a function parameter" } */
+}
+
+void
+foo2 (void)
+{
+ __vector_quad v;
+ bar2 (v); /* { dg-error "invalid use of MMA operand of type .__vector_quad. as a function parameter" } */
+}
+
+void
+foo3 (void)
+{
+ vquad_t v;
+ bar3 (v); /* { dg-error "invalid use of MMA operand of type .__vector_quad. as a function parameter" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96506-2.c b/gcc/testsuite/gcc.target/powerpc/pr96506-2.c
new file mode 100644
index 0000000..9cffd25
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96506-2.c
@@ -0,0 +1,38 @@
+/* PR target/96506 */
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
+
+extern void bar0();
+extern void bar1();
+extern void bar2();
+extern void bar3();
+
+typedef __vector_pair vpair_t;
+typedef __vector_quad vquad_t;
+
+/* Verify we flag errors on the following. */
+
+__vector_pair
+foo4 (__vector_pair *src)
+{ /* { dg-error "invalid use of MMA type .__vector_pair. as a function return value" } */
+ return *src;
+}
+
+vpair_t
+foo5 (vpair_t *src)
+{ /* { dg-error "invalid use of MMA type .__vector_pair. as a function return value" } */
+ return *src;
+}
+
+__vector_quad
+foo6 (__vector_quad *src)
+{ /* { dg-error "invalid use of MMA type .__vector_quad. as a function return value" } */
+ return *src;
+}
+
+vquad_t
+foo7 (vquad_t *src)
+{ /* { dg-error "invalid use of MMA type .__vector_quad. as a function return value" } */
+ return *src;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96506.c b/gcc/testsuite/gcc.target/powerpc/pr96506.c
deleted file mode 100644
index b1b40c5..0000000
--- a/gcc/testsuite/gcc.target/powerpc/pr96506.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* PR target/96506 */
-/* { dg-do compile } */
-/* { dg-require-effective-target power10_ok } */
-/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
-
-extern void bar0();
-extern void bar1();
-extern void bar2();
-extern void bar3();
-
-typedef __vector_pair vpair_t;
-typedef __vector_quad vquad_t;
-
-/* Verify we flag errors on the following. */
-
-void
-foo0 (void)
-{
- __vector_pair v;
- bar0 (v); /* { dg-error "invalid use of MMA operand of type .__vector_pair. as a function parameter" } */
-}
-
-void
-foo1 (void)
-{
- vpair_t v;
- bar1 (v); /* { dg-error "invalid use of MMA operand of type .__vector_pair. as a function parameter" } */
-}
-
-void
-foo2 (void)
-{
- __vector_quad v;
- bar2 (v); /* { dg-error "invalid use of MMA operand of type .__vector_quad. as a function parameter" } */
-}
-
-void
-foo3 (void)
-{
- vquad_t v;
- bar3 (v); /* { dg-error "invalid use of MMA operand of type .__vector_quad. as a function parameter" } */
-}
-
-__vector_pair
-foo4 (__vector_pair *src) /* { dg-error "invalid use of MMA type .__vector_pair. as a function return value" } */
-{
- return *src;
-}
-
-vpair_t
-foo5 (vpair_t *src) /* { dg-error "invalid use of MMA type .__vector_pair. as a function return value" } */
-{
- return *src;
-}
-
-__vector_quad
-foo6 (__vector_quad *src) /* { dg-error "invalid use of MMA type .__vector_quad. as a function return value" } */
-{
- return *src;
-}
-
-vquad_t
-foo7 (vquad_t *src) /* { dg-error "invalid use of MMA type .__vector_quad. as a function return value" } */
-{
- return *src;
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96787-2.c b/gcc/testsuite/gcc.target/powerpc/pr96787-2.c
index b10ab7a8..8c4469d 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr96787-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr96787-2.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
/* Verify that we generate an indirect sibcall for ELFv2 on P10 and
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96933-1.c b/gcc/testsuite/gcc.target/powerpc/pr96933-1.c
new file mode 100644
index 0000000..71d7208
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96933-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power9" } */
+
+/* Test vector constructions with char/short type values whether use 128bit
+ direct move instructions mtvsrdd on Power9 or later, rather than transfering
+ with memory store/load with stb/sth and vector load. */
+
+#include "pr96933.h"
+
+/* { dg-final { scan-assembler-times {\mmtvsrdd\M} 24 } } */
+/* { dg-final { scan-assembler-times {\mvpkudum\M} 12 } } */
+/* { dg-final { scan-assembler-not {\mstb\M} } } */
+/* { dg-final { scan-assembler-not {\msth\M} } } */
+/* { dg-final { scan-assembler-not {\mrlwinm\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96933-2.c b/gcc/testsuite/gcc.target/powerpc/pr96933-2.c
new file mode 100644
index 0000000..9fa1512
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96933-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power8" } */
+
+/* Test vector constructions with char/short type values whether use direct
+ move instructions like mtvsrd/mtvsrwz on Power8, rather than transfering
+ with memory store/load with stb/sth and vector load. */
+
+#include "pr96933.h"
+
+/* { dg-final { scan-assembler-times {\mmtvsrd\M} 48 {target lp64 } } } */
+/* { dg-final { scan-assembler-times {\mmtvsrwz\M} 48 {target {! lp64 } } } } */
+/* { dg-final { scan-assembler-times {\mxxpermdi\M} 4 } } */
+/* { dg-final { scan-assembler-not {\mstb\M} } } */
+/* { dg-final { scan-assembler-not {\msth\M} } } */
+/* { dg-final { scan-assembler-not {\mrlwinm\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96933-3.c b/gcc/testsuite/gcc.target/powerpc/pr96933-3.c
new file mode 100644
index 0000000..3e5709a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96933-3.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-options "-O2 -mdejagnu-cpu=power8" } */
+
+/* Test vector constructions with char/short run successfully on Power8. */
+
+#include <stdlib.h>
+#include "pr96933.h"
+#include "pr96933-run.h"
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96933-4.c b/gcc/testsuite/gcc.target/powerpc/pr96933-4.c
new file mode 100644
index 0000000..5a1c3d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96933-4.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-O2 -mdejagnu-cpu=power9" } */
+
+/* Test vector constructions with char/short run successfully on Power9. */
+
+#include <stdlib.h>
+#include "pr96933.h"
+#include "pr96933-run.h"
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96933-run.h b/gcc/testsuite/gcc.target/powerpc/pr96933-run.h
new file mode 100644
index 0000000..7fa8dac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96933-run.h
@@ -0,0 +1,56 @@
+/* Test function for pr96933-{3,4}.c run result verification. */
+
+int
+main ()
+{
+ unsigned char uc[16];
+ signed char sc[16];
+
+ for (int i = 0; i < 16; i++)
+ {
+ uc[i] = (unsigned char) (i * 2 + 1);
+ sc[i] = (signed char) ((i % 2 == 0) ? (i + 1) : -i);
+ }
+
+ vector unsigned char ucv
+ = test_uchar (uc[0], uc[1], uc[2], uc[3], uc[4], uc[5], uc[6], uc[7], uc[8],
+ uc[9], uc[10], uc[11], uc[12], uc[13], uc[14], uc[15]);
+ vector signed char scv
+ = test_schar (sc[0], sc[1], sc[2], sc[3], sc[4], sc[5], sc[6], sc[7], sc[8],
+ sc[9], sc[10], sc[11], sc[12], sc[13], sc[14], sc[15]);
+
+ for (int i = 0; i < 16; i++)
+ {
+ unsigned char uexp = (unsigned char) (i * 2 + 1);
+ signed char sexp = (signed char) ((i % 2 == 0) ? (i + 1) : -i);
+ if (ucv[i] != uexp)
+ abort ();
+ if (scv[i] != sexp)
+ abort ();
+ }
+
+ unsigned short us[8];
+ signed short ss[8];
+ for (int i = 0; i < 8; i++)
+ {
+ us[i] = (unsigned short) (i * 2 + 1);
+ ss[i] = (signed short) ((i % 2 == 0) ? (i + 1) : -i);
+ }
+
+ vector unsigned short usv
+ = test_ushort (us[0], us[1], us[2], us[3], us[4], us[5], us[6], us[7]);
+ vector signed short ssv
+ = test_sshort (ss[0], ss[1], ss[2], ss[3], ss[4], ss[5], ss[6], ss[7]);
+
+ for (int i = 0; i < 8; i++)
+ {
+ unsigned short uexp = (unsigned short) (i * 2 + 1);
+ signed short sexp = (signed short) ((i % 2 == 0) ? (i + 1) : -i);
+ if (usv[i] != uexp)
+ abort ();
+ if (ssv[i] != sexp)
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr96933.h b/gcc/testsuite/gcc.target/powerpc/pr96933.h
new file mode 100644
index 0000000..4bc2b94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr96933.h
@@ -0,0 +1,50 @@
+/* Source file for pr96933-*.c testing, this mainly contains 4
+ functions as below:
+
+ - test_uchar // vector unsigned char
+ - test_schar // vector signed char
+ - test_ushort // vector unsigned short
+ - test_sshort // vector signed short
+*/
+
+__attribute__ ((noipa)) vector unsigned char
+test_uchar (unsigned char c1, unsigned char c2, unsigned char c3,
+ unsigned char c4, unsigned char c5, unsigned char c6,
+ unsigned char c7, unsigned char c8, unsigned char c9,
+ unsigned char c10, unsigned char c11, unsigned char c12,
+ unsigned char c13, unsigned char c14, unsigned char c15,
+ unsigned char c16)
+{
+ vector unsigned char v
+ = {c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16};
+ return v;
+}
+
+__attribute__ ((noipa)) vector signed char
+test_schar (signed char c1, signed char c2, signed char c3, signed char c4,
+ signed char c5, signed char c6, signed char c7, signed char c8,
+ signed char c9, signed char c10, signed char c11, signed char c12,
+ signed char c13, signed char c14, signed char c15, signed char c16)
+{
+ vector signed char v
+ = {c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16};
+ return v;
+}
+
+__attribute__ ((noipa)) vector unsigned short
+test_ushort (unsigned short c1, unsigned short c2, unsigned short c3,
+ unsigned short c4, unsigned short c5, unsigned short c6,
+ unsigned short c7, unsigned short c8)
+{
+ vector unsigned short v = {c1, c2, c3, c4, c5, c6, c7, c8};
+ return v;
+}
+
+__attribute__ ((noipa)) vector signed short
+test_sshort (signed short c1, signed short c2, signed short c3,
+ signed short c4, signed short c5, signed short c6,
+ signed short c7, signed short c8)
+{
+ vector signed short v = {c1, c2, c3, c4, c5, c6, c7, c8};
+ return v;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr97267.c b/gcc/testsuite/gcc.target/powerpc/pr97267.c
new file mode 100644
index 0000000..cab4624
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr97267.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+static int __attribute__ ((__noclone__, __noinline__))
+reg_args (int j1, int j2, int j3, int j4, int j5, int j6, int j7, int j8)
+{
+ return j1 + j2 + j3 + j4 + j5 + j6 + j7 + j8;
+}
+
+int __attribute__ ((__noclone__, __noinline__))
+stack_args (int j1, int j2, int j3, int j4, int j5, int j6, int j7, int j8,
+ int j9)
+{
+ if (j9 == 0)
+ return 0;
+ return reg_args (j1, j2, j3, j4, j5, j6, j7, j8);
+}
+
+/* { dg-final { scan-assembler-not {(?n)^\s+bl\s} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/r2_shrink-wrap.c b/gcc/testsuite/gcc.target/powerpc/r2_shrink-wrap.c
index b81b9b1..a74da38 100644
--- a/gcc/testsuite/gcc.target/powerpc/r2_shrink-wrap.c
+++ b/gcc/testsuite/gcc.target/powerpc/r2_shrink-wrap.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target lp64 } } */
-/* { dg-options "-O2 -fdump-rtl-pro_and_epilogue" } */
+/* { dg-options "-O2 -fdump-rtl-pro_and_epilogue -mno-pcrel" } */
/* Verify we move the prologue past the TOC reference of 'j' and shrink-wrap
the function. */
diff --git a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-1.c
index 9cc14e4..326a821 100644
--- a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-1.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-O3 -mdejagnu-cpu=power9" } */
/* Verify that we vectorize this SAD loop using vabsdub. */
diff --git a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-2.c b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-2.c
index e1de52b..3ae5c48 100644
--- a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-2.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-O3 -mdejagnu-cpu=power9" } */
/* Verify that we vectorize this SAD loop using vabsduh. */
diff --git a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-3.c b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-3.c
index bb10fe6..2986abb 100644
--- a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-3.c
@@ -1,5 +1,5 @@
-/* { dg-do run { target { powerpc*-*-linux* && { lp64 && p9vector_hw } } } } */
-/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-do run } */
+/* { dg-require-effective-target p9vector_hw } */
/* { dg-options "-O3 -mdejagnu-cpu=power9" } */
/* Verify that we get correct code when we vectorize this SAD loop using
diff --git a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-4.c b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-4.c
index 15f5d14..d24e2a8 100644
--- a/gcc/testsuite/gcc.target/powerpc/sad-vectorize-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/sad-vectorize-4.c
@@ -1,5 +1,5 @@
-/* { dg-do run { target { powerpc*-*-linux* && { lp64 && p9vector_hw } } } } */
-/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-do run } */
+/* { dg-require-effective-target p9vector_hw } */
/* { dg-options "-O3 -mdejagnu-cpu=power9" } */
/* Verify that we get correct code when we vectorize this SAD loop using
diff --git a/gcc/testsuite/gcc.target/powerpc/signbit-1.c b/gcc/testsuite/gcc.target/powerpc/signbit-1.c
index 552dd1b..1642bf4 100644
--- a/gcc/testsuite/gcc.target/powerpc/signbit-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/signbit-1.c
@@ -1,5 +1,6 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_float128_sw } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mdejagnu-cpu=power8 -O2 -mfloat128" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/signbit-2.c b/gcc/testsuite/gcc.target/powerpc/signbit-2.c
index d17fc81..1b79291 100644
--- a/gcc/testsuite/gcc.target/powerpc/signbit-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/signbit-2.c
@@ -1,6 +1,6 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-require-effective-target ppc_float128_sw } */
/* { dg-options "-mdejagnu-cpu=power9 -O2 -mfloat128" } */
int do_signbit_kf (__float128 *a) { return __builtin_signbit (*a); }
@@ -13,5 +13,7 @@ int do_signbit_kf (__float128 *a) { return __builtin_signbit (*a); }
/* { dg-final { scan-assembler-not "lxvw4x" } } */
/* { dg-final { scan-assembler-not "lxsd" } } */
/* { dg-final { scan-assembler-not "lxsdx" } } */
-/* { dg-final { scan-assembler-times "ld" 1 } } */
-/* { dg-final { scan-assembler-times "srdi" 1 } } */
+/* { dg-final { scan-assembler-times "ld" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "srdi" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "lwz" 1 { target ilp32 } } } */
+/* { dg-final { scan-assembler-times "rlwinm" 1 { target ilp32 } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/signbit-3.c b/gcc/testsuite/gcc.target/powerpc/signbit-3.c
index 68d641e..2d1ecb9 100644
--- a/gcc/testsuite/gcc.target/powerpc/signbit-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/signbit-3.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-do run } */
/* { dg-require-effective-target ppc_float128_sw } */
/* { dg-options "-mdejagnu-cpu=power7 -O2 -mfloat128 -lm" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-22.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-22.c
index 83f6ab3..847aebc 100644
--- a/gcc/testsuite/gcc.target/powerpc/swaps-p8-22.c
+++ b/gcc/testsuite/gcc.target/powerpc/swaps-p8-22.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { *-*-aix* || { *-*-linux* && lp64 } } } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power8 -maltivec -mcmodel=large" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdu-0.c b/gcc/testsuite/gcc.target/powerpc/vadsdu-0.c
index 26c9e53..e02ba44 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdu-0.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdu-0.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdu-1.c b/gcc/testsuite/gcc.target/powerpc/vadsdu-1.c
index 7c54cfe..2f02d39 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdu-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdu-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdu-2.c b/gcc/testsuite/gcc.target/powerpc/vadsdu-2.c
index a2a668b..2530e67 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdu-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdu-2.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdu-3.c b/gcc/testsuite/gcc.target/powerpc/vadsdu-3.c
index 9755c6f..17d7c8d 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdu-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdu-3.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdu-4.c b/gcc/testsuite/gcc.target/powerpc/vadsdu-4.c
index 4a3dd41..d6e56cc 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdu-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdu-4.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdu-5.c b/gcc/testsuite/gcc.target/powerpc/vadsdu-5.c
index 9d5947c..ff6d436 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdu-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdu-5.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdub-1.c b/gcc/testsuite/gcc.target/powerpc/vadsdub-1.c
index 58f2797..a460962 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdub-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdub-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsdub-2.c b/gcc/testsuite/gcc.target/powerpc/vadsdub-2.c
index 1d51766..c3d1bc8 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsdub-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsdub-2.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsduh-1.c b/gcc/testsuite/gcc.target/powerpc/vadsduh-1.c
index 1084e75..d08395a 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsduh-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsduh-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsduh-2.c b/gcc/testsuite/gcc.target/powerpc/vadsduh-2.c
index 0448917..7f17694 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsduh-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsduh-2.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsduw-1.c b/gcc/testsuite/gcc.target/powerpc/vadsduw-1.c
index 4844e3e..8a809d5 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsduw-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsduw-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vadsduw-2.c b/gcc/testsuite/gcc.target/powerpc/vadsduw-2.c
index 021772f..a330f52 100644
--- a/gcc/testsuite/gcc.target/powerpc/vadsduw-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vadsduw-2.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
/* This test should succeed on both 32- and 64-bit configurations. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-blend-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-blend-runnable.c
index 0c3d472..d63dfee 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-blend-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-blend-runnable.c
@@ -1,11 +1,12 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
#define DEBUG 0
-#ifdef DEBUG
+#if DEBUG
#include <stdio.h>
#endif
@@ -144,7 +145,8 @@ main (int argc, char *argv [])
if (!vec_all_eq (vresult_ushort, expected_vresult_ushort)) {
#if DEBUG
- printf("ERROR, vec_blendv (vsrc_a_ushort, vsrc_b_ushort, vsrc_c_ushort)\n");
+ printf("ERROR, vec_blendv (vsrc_a_ushort, vsrc_b_ushort, "
+ "vsrc_c_ushort)\n");
for(i = 0; i < 8; i++)
printf(" vresult_ushort[%d] = %d, expected_vresult_ushort[%d] = %d\n",
i, vresult_ushort[i], i, expected_vresult_ushort[i]);
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-cfuged-1.c b/gcc/testsuite/gcc.target/powerpc/vec-cfuged-1.c
index 2a6f5ed..7507c63 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-cfuged-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-cfuged-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-clrl-1.c b/gcc/testsuite/gcc.target/powerpc/vec-clrl-1.c
index 7f7d28b..43ab32c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-clrl-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-clrl-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-clrl-3.c b/gcc/testsuite/gcc.target/powerpc/vec-clrl-3.c
index 26eae79..0ae5abc 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-clrl-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-clrl-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-clrr-1.c b/gcc/testsuite/gcc.target/powerpc/vec-clrr-1.c
index 307617e..c72ae86 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-clrr-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-clrr-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-clrr-3.c b/gcc/testsuite/gcc.target/powerpc/vec-clrr-3.c
index b46995d..1413c11 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-clrr-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-clrr-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-cntlzm-1.c b/gcc/testsuite/gcc.target/powerpc/vec-cntlzm-1.c
index b92bccf..f356970 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-cntlzm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-cntlzm-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-cnttzm-1.c b/gcc/testsuite/gcc.target/powerpc/vec-cnttzm-1.c
index 83bdd95..b460c16 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-cnttzm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-cnttzm-1.c
@@ -1,5 +1,6 @@
-/* { dg-do compile } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c
index 13618ce..8109abc 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c
index 1d8a690..7ba9768 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c
index 17229f4..c59dea0 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-5.c
@@ -1,4 +1,6 @@
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c b/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c
index 64ca22e..e74ea5c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extracth-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c
index 879c253..4153956 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c
index b3ab433..babd25f 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c
index df239e8..e642e31 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-5.c
@@ -1,4 +1,6 @@
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c b/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c
index fd1ab60..4c3c7cb 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extractl-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c
index 527cc3f..e64fe02 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target int128 } */
/* { dg-options "-mdejagnu-cpu=power10" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-insert-word-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-insert-word-runnable.c
index 8c2721a..bd96e13 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-insert-word-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-insert-word-runnable.c
@@ -1,11 +1,12 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
#define DEBUG 0
-#ifdef DEBUG
+#if DEBUG
#include <stdio.h>
#endif
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-pdep-1.c b/gcc/testsuite/gcc.target/powerpc/vec-pdep-1.c
index 02404a6d..d7e6484 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-pdep-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-pdep-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-permute-ext-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-permute-ext-runnable.c
index c2dcd48..f833265 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-permute-ext-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-permute-ext-runnable.c
@@ -1,11 +1,12 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
#define DEBUG 0
-#ifdef DEBUG
+#if DEBUG
#include <stdio.h>
#endif
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-pext-1.c b/gcc/testsuite/gcc.target/powerpc/vec-pext-1.c
index ed289bf..286fdce 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-pext-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-pext-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-replace-word-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-replace-word-runnable.c
index 94af210..9497cbf 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-replace-word-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-replace-word-runnable.c
@@ -1,12 +1,13 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
#define DEBUG 0
-#ifdef DEBUG
+#if DEBUG
#include <stdio.h>
#endif
@@ -212,7 +213,8 @@ main (int argc, char *argv [])
if (!vec_all_eq (vresult_float, expected_vresult_float)) {
#if DEBUG
- printf("ERROR, vec_replace_unaligned (src_vb_float, src_va_float, index)\n");
+ printf("ERROR, vec_replace_unaligned (src_vb_float, src_va_float, "
+ "index)\n");
for(i = 0; i < 4; i++)
printf(" vresult_float[%d] = %f, expected_vresult_float[%d] = %f\n",
i, vresult_float[i], i, expected_vresult_float[i]);
@@ -233,7 +235,8 @@ main (int argc, char *argv [])
if (!vec_all_eq (vresult_ullint, expected_vresult_ullint)) {
#if DEBUG
- printf("ERROR, vec_replace_unaligned (src_vb_ullint, src_va_ullint, index)\n");
+ printf("ERROR, vec_replace_unaligned (src_vb_ullint, src_va_ullint, "
+ "index)\n");
for(i = 0; i < 2; i++)
printf(" vresult_ullint[%d] = %d, expected_vresult_ullint[%d] = %d\n",
i, vresult_ullint[i], i, expected_vresult_ullint[i]);
@@ -252,7 +255,8 @@ main (int argc, char *argv [])
if (!vec_all_eq (vresult_llint, expected_vresult_llint)) {
#if DEBUG
- printf("ERROR, vec_replace_unaligned (src_vb_llint, src_va_llint, index)\n");
+ printf("ERROR, vec_replace_unaligned (src_vb_llint, src_va_llint, "
+ "index)\n");
for(i = 0; i < 2; i++)
printf(" vresult_llint[%d] = %d, expected_vresult_llint[%d] = %d\n",
i, vresult_llint[i], i, expected_vresult_llint[i]);
@@ -270,8 +274,8 @@ main (int argc, char *argv [])
if (!vec_all_eq (vresult_double, expected_vresult_double)) {
#if DEBUG
- printf("ERROR, vec_replace_unaligned (src_vb_double, src_va_double, index)\
-n");
+ printf("ERROR, vec_replace_unaligned (src_vb_double, src_va_double, "
+ "index)\n");
for(i = 0; i < 2; i++)
printf(" vresult_double[%d] = %f, expected_vresult_double[%d] = %f\n",
i, vresult_double[i], i, expected_vresult_double[i]);
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-shift-double-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-shift-double-runnable.c
index 13213bd..90b19f0 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-shift-double-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-shift-double-runnable.c
@@ -1,11 +1,12 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
#define DEBUG 0
-#ifdef DEBUG
+#if DEBUG
#include <stdio.h>
#endif
@@ -378,7 +379,5 @@ main (int argc, char *argv [])
return 0;
}
-/* { dg-final { scan-assembler-times {\msldbi\M} 6 } } */
-/* { dg-final { scan-assembler-times {\msrdbi\M} 6 } } */
-
-
+/* { dg-final { scan-assembler-times {\mvsldbi\M} 8 } } */
+/* { dg-final { scan-assembler-times {\mvsrdbi\M} 8 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-splati-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-splati-runnable.c
index e5a4935..e84ce77 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-splati-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-splati-runnable.c
@@ -1,6 +1,7 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
#define DEBUG 0
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-1.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-1.c
index 98ee29f..ce83f77 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-16.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-16.c
index 6aaad99..ad888d8 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-16.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-16.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-stril-17.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-17.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-17.c
index 2015aad..6274f2a 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-17.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-17.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-18.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-18.c
index fce56937..be48daa 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-18.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-18.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-stril-19.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-19.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-19.c
index 6226dde..74ab15c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-19.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-19.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-20.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-20.c
index 9da116c..a2db6a7 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-20.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-20.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-stril-21.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-21.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-21.c
index b281c45..07274c68 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-21.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-21.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-22.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-22.c
index a63dab7..a2e6bac 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-22.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-22.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-stril-23.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-23.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-23.c
index ec0e483..a5ef78d 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-23.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-23.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-3.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-3.c
index 970c1a1..49cb232 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-5.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-5.c
index c74cad6..8e29d55 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-5.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril-7.c b/gcc/testsuite/gcc.target/powerpc/vec-stril-7.c
index 9c5d454..6b39dfc 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-1.c b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-1.c
index cd9c468..ca2c76c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-3.c b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-3.c
index 24b0a86..8fb3fe7 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-5.c b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-5.c
index 2c2ff34..bc8834a 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-5.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-7.c b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-7.c
index 900aaf1..d235a53 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-stril_p-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-stril_p-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-1.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-1.c
index ff09cd3..5bee3f7 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-16.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-16.c
index 19e051e..86a450e 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-16.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-16.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-strir-17.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-17.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-17.c
index 00f27cc..d660092 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-17.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-17.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-18.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-18.c
index d69b474..c6dd6ca 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-18.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-18.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-strir-19.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-19.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-19.c
index 3728d49..54277cc 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-19.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-19.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-20.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-20.c
index a635a04..3baa035 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-20.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-20.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-strir-21.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-21.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-21.c
index 5557d5d..1a90e56 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-21.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-21.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-22.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-22.c
index 328a56b..5621f3c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-22.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-22.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O1 -mdejagnu-cpu=power10" } */
/* See vec-strir-23.c for the same test with -O2 optimization. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-23.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-23.c
index 5f05ab2..118c702 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-23.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-23.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-3.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-3.c
index 5fb2306..c266d3a 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-5.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-5.c
index eabecaf..f18d91b 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-5.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir-7.c b/gcc/testsuite/gcc.target/powerpc/vec-strir-7.c
index a73efea..2641985 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-1.c b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-1.c
index 569b8b4..3744c90 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-3.c b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-3.c
index 3a411fe..70ab0f6 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-3.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-5.c b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-5.c
index 0edff34..ad02c97 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-5.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-7.c b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-7.c
index 18926b0..71ce608 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-strir_p-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-strir_p-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c
index 052d99d..3cd0a55 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c
@@ -1,5 +1,6 @@
-/* { dg-do run} */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c
index 411bafe..9697068 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c
@@ -1,6 +1,7 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c
index 527e8f2..4d4344b 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c
index b754195..45936f3 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c
@@ -1,5 +1,6 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c
index 0d9998e..bcf4a35 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c
@@ -1,7 +1,8 @@
-/* { dg-do run } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
/* { dg-require-effective-target int128 } */
-/* { dg-options "-mdejagnu-cpu=power10" } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vslv-0.c b/gcc/testsuite/gcc.target/powerpc/vslv-0.c
index b7e5172..f921b2c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vslv-0.c
+++ b/gcc/testsuite/gcc.target/powerpc/vslv-0.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vslv-1.c b/gcc/testsuite/gcc.target/powerpc/vslv-1.c
index c1a58c8..37407c1 100644
--- a/gcc/testsuite/gcc.target/powerpc/vslv-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vslv-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vsrv-0.c b/gcc/testsuite/gcc.target/powerpc/vsrv-0.c
index fc3be46..8ecd326 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsrv-0.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsrv-0.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vsrv-1.c b/gcc/testsuite/gcc.target/powerpc/vsrv-1.c
index 112899a..186e79a 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsrv-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsrv-1.c
@@ -1,6 +1,5 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-mdejagnu-cpu=power9" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-char.c b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-char.c
index 0b8cfd6..c23a912 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-char.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-char.c
@@ -2,9 +2,11 @@
Test of vec_xl_sext and vec_xl_zext (load into rightmost
vector element and zero/sign extend). */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
-/* { dg-options "-mdejagnu-cpu=power10 -O3" } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-mdejagnu-cpu=power10 -O3 -save-temps" } */
/* At the time of writing, the number of lxvrbx instructions is
double what we expect because we are generating a
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-int.c b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-int.c
index b10d3cb..c40e1a3 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-int.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-int.c
@@ -2,14 +2,16 @@
Test of vec_xl_sext and vec_xl_zext (load into rightmost
vector element and zero/sign extend). */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Deliberately set optization to zero for this test to confirm
the lxvr*x instruction is generated. At higher optimization levels
the instruction we are looking for is sometimes replaced by other
load instructions. */
-/* { dg-options "-mdejagnu-cpu=power10 -O0" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O0 -save-temps" } */
/* { dg-final { scan-assembler-times {\mlxvrwx\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-longlong.c b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-longlong.c
index 52fcf2e..405b424 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-longlong.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-longlong.c
@@ -2,9 +2,11 @@
Test of vec_xl_sext and vec_xl_zext (load into rightmost
vector element and zero/sign extend). */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
-/* { dg-options "-mdejagnu-cpu=power10 -O3" } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-mdejagnu-cpu=power10 -O3 -save-temps" } */
/* At time of writing, we also geenerate a .constrprop copy
of the function, so our instruction hit count is
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-short.c b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-short.c
index 8fc0cc6..837ba79 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-short.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-load-element-extend-short.c
@@ -2,14 +2,16 @@
Test of vec_xl_sext and vec_xl_zext (load into rightmost
vector element and zero/sign extend). */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Deliberately set optization to zero for this test to confirm
the lxvr*x instruction is generated. At higher optimization levels
the instruction we are looking for is sometimes replaced by other
load instructions. */
-/* { dg-options "-mdejagnu-cpu=power10 -O0" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O0 -save-temps" } */
/* { dg-final { scan-assembler-times {\mlxvrhx\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-char.c b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-char.c
index 99f3904..3049b1c 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-char.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-char.c
@@ -1,13 +1,15 @@
/*
Test of vec_xst_trunc (truncate and store rightmost vector element) */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Deliberately set optization to zero for this test to confirm
the stxvr*x instruction is generated. At higher optimization levels
the instruction we are looking for is sometimes replaced by other
store instructions. */
-/* { dg-options "-mdejagnu-cpu=power10 -O0" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O0 -save-temps" } */
/* { dg-final { scan-assembler-times {\mstxvrbx\M} 2 } } */
/* { dg-final { scan-assembler-times {\mstbx\M} 0 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-int.c b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-int.c
index 6e2acf8..7cc7699 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-int.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-int.c
@@ -1,13 +1,15 @@
/*
Test of vec_xst_trunc (truncate and store rightmost vector element) */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Deliberately set optization to zero for this test to confirm
the stxvr*x instruction is generated. At higher optimization levels
the instruction we are looking for is sometimes replaced by other
store instructions. */
-/* { dg-options "-mdejagnu-cpu=power10 -O0" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O0 -save-temps" } */
/* { dg-final { scan-assembler-times {\mstxvrwx\M} 2 } } */
/* { dg-final { scan-assembler-times {\mstwx\M} 0 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-longlong.c b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-longlong.c
index 7fce6a4..e1bd021 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-longlong.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-longlong.c
@@ -1,14 +1,16 @@
/*
Test of vec_xst_trunc (truncate and store rightmost vector element) */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Deliberately set optization to zero for this test to confirm
the stxvr*x instruction is generated. At higher optimization levels
the instruction we are looking for is sometimes replaced by other
store instructions. */
-/* { dg-options "-mdejagnu-cpu=power10 -O0" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O0 -save-temps" } */
/* { dg-final { scan-assembler-times {\mstxvrdx\M} 2 } } */
/* { dg-final { scan-assembler-times {\mstwx\M} 0 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-short.c b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-short.c
index 17925c8..b173b36 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-short.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-store-element-truncate-short.c
@@ -1,14 +1,16 @@
/*
Test of vec_xst_trunc (truncate and store rightmost vector element) */
-/* { dg-do compile {target power10_ok} } */
-/* { dg-do run {target power10_hw} } */
+/* { dg-do run { target power10_hw } } */
+/* { dg-do compile { target { ! power10_hw } } } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Deliberately set optization to zero for this test to confirm
the stxvr*x instruction is generated. At higher optimization levels
the instruction we are looking for is sometimes replaced by other
store instructions. */
-/* { dg-options "-mdejagnu-cpu=power10 -O0" } */
+/* { dg-options "-mdejagnu-cpu=power10 -O0 -save-temps" } */
/* { dg-final { scan-assembler-times {\mstxvrhx\M} 2 } } */
/* { dg-final { scan-assembler-times {\msthx\M} 0 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_mask-count-runnable.c b/gcc/testsuite/gcc.target/powerpc/vsx_mask-count-runnable.c
index f1e3860..1ea2d65 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx_mask-count-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx_mask-count-runnable.c
@@ -1,6 +1,8 @@
-/* { dg-do run } */
-/* { dg-options "-mcpu=power10 -O2" } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Check that the expected 128-bit instructions are generated if the processor
supports the 128-bit integer instructions. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_mask-expand-runnable.c b/gcc/testsuite/gcc.target/powerpc/vsx_mask-expand-runnable.c
index 0c5695e..2c49814 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx_mask-expand-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx_mask-expand-runnable.c
@@ -1,6 +1,8 @@
-/* { dg-do run } */
-/* { dg-options "-mcpu=power10 -O2" } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Check that the expected 128-bit instructions are generated if the processor
supports the 128-bit integer instructions. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_mask-extract-runnable.c b/gcc/testsuite/gcc.target/powerpc/vsx_mask-extract-runnable.c
index 93c3c72..9e257f5 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx_mask-extract-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx_mask-extract-runnable.c
@@ -1,6 +1,8 @@
-/* { dg-do run } */
-/* { dg-options "-mcpu=power10 -O2" } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Check that the expected 128-bit instructions are generated if the processor
supports the 128-bit integer instructions. */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx_mask-move-runnable.c b/gcc/testsuite/gcc.target/powerpc/vsx_mask-move-runnable.c
index 41dee58..53fd99e 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx_mask-move-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx_mask-move-runnable.c
@@ -1,6 +1,8 @@
-/* { dg-do run } */
-/* { dg-options "-mcpu=power10 -O2" } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target int128 } */
/* Check that the expected 128-bit instructions are generated if the processor
supports the 128-bit integer instructions. */
diff --git a/gcc/testsuite/gcc.target/powerpc/xxgenpc-runnable.c b/gcc/testsuite/gcc.target/powerpc/xxgenpc-runnable.c
index 244c573..d4040ea 100644
--- a/gcc/testsuite/gcc.target/powerpc/xxgenpc-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/xxgenpc-runnable.c
@@ -1,6 +1,7 @@
-/* { dg-do run } */
+/* { dg-do run { target { power10_hw } } } */
+/* { dg-do link { target { ! power10_hw } } } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
-/* { dg-require-effective-target power10_hw } */
+/* { dg-require-effective-target power10_ok } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/pru/halt.c b/gcc/testsuite/gcc.target/pru/halt.c
new file mode 100644
index 0000000..8aed576
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/halt.c
@@ -0,0 +1,9 @@
+/* Test HALT builtin. */
+
+void
+test_halt (void)
+{
+ /* { dg-final { scan-assembler "halt" } } */
+ __halt();
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/lmbd.c b/gcc/testsuite/gcc.target/pru/lmbd.c
new file mode 100644
index 0000000..bfe4beb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/lmbd.c
@@ -0,0 +1,14 @@
+/* Test LMBD builtin. */
+
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it zero_extend
+ operation may not be optimized. */
+
+unsigned int
+test_lmbd (unsigned char a, unsigned short b)
+{
+ /* { dg-final { scan-assembler "lmbd\\tr14, r14.w1, r14.b0" } } */
+ return __lmbd(b, a);
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/arch-10.c b/gcc/testsuite/gcc.target/riscv/arch-10.c
new file mode 100644
index 0000000..47dbda3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-10.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gf2 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-error "Extension `f' appear more than one time." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-11.c b/gcc/testsuite/gcc.target/riscv/arch-11.c
new file mode 100644
index 0000000..129d8f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-11.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32g_zicsr2 -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-7.c b/gcc/testsuite/gcc.target/riscv/arch-7.c
new file mode 100644
index 0000000..74ab248
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-7.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32i -march=rv32im_s -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-error ".'-march=rv32im_s': name of supervisor extension must be more than 1 letter" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-8.c b/gcc/testsuite/gcc.target/riscv/arch-8.c
new file mode 100644
index 0000000..d7760fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-8.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O -march=rv32id_zicsr_zifence -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-9.c b/gcc/testsuite/gcc.target/riscv/arch-9.c
new file mode 100644
index 0000000..74e6410
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-9.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32g2 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-warning "version of `g` will be omitted, please specify version for individual extension." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-10.c b/gcc/testsuite/gcc.target/riscv/attribute-10.c
index a874a62..26fdd08 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-10.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-10.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=rv32i -march=rv32im_s_sx_unexpectedstring -mabi=ilp32" } */
+/* { dg-options "-O2 -march=rv32i -march=rv32im_sx_unexpectedstring -mabi=ilp32" } */
int foo()
{
}
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-11.c b/gcc/testsuite/gcc.target/riscv/attribute-11.c
index a864950..98bd8d4 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-11.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-11.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32 -misa-spec=2.2" } */
int foo()
{
}
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-12.c b/gcc/testsuite/gcc.target/riscv/attribute-12.c
index df27fc3..44fccad 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-12.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-12.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32 -misa-spec=2.2" } */
int foo()
{
}
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-13.c b/gcc/testsuite/gcc.target/riscv/attribute-13.c
index 1e86001..1b8f93c 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-13.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-13.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32 -misa-spec=2.2" } */
int foo()
{
}
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-14.c b/gcc/testsuite/gcc.target/riscv/attribute-14.c
new file mode 100644
index 0000000..2591c1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-14.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32 -misa-spec=20190608" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_f2p2_zicsr2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-15.c b/gcc/testsuite/gcc.target/riscv/attribute-15.c
new file mode 100644
index 0000000..9cae1a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-15.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=2.2" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0_c2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-16.c b/gcc/testsuite/gcc.target/riscv/attribute-16.c
new file mode 100644
index 0000000..f090363
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-16.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20190608" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p0_f2p2_d2p2_c2p0_zicsr2p0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-17.c b/gcc/testsuite/gcc.target/riscv/attribute-17.c
new file mode 100644
index 0000000..19ef540
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-17.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20191213" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-6.c b/gcc/testsuite/gcc.target/riscv/attribute-6.c
deleted file mode 100644
index c75b0d6..0000000
--- a/gcc/testsuite/gcc.target/riscv/attribute-6.c
+++ /dev/null
@@ -1,6 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32g2p0 -mabi=ilp32" } */
-int foo()
-{
-}
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-8.c b/gcc/testsuite/gcc.target/riscv/attribute-8.c
index 1d16176..90f5a40 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-8.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-8.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xv5_xabc -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xabc_xv5 -mabi=ilp32" } */
int foo()
{
}
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xv5p0_xabc2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xabc_xv5p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-9.c b/gcc/testsuite/gcc.target/riscv/attribute-9.c
index bc4db0e..4598872 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-9.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-9.c
@@ -3,4 +3,4 @@
int foo()
{
}
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc2p0_xbar2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc_xbar\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-3.c b/gcc/testsuite/gcc.target/riscv/interrupt-3.c
index bc9e0c1..3d1d44d 100644
--- a/gcc/testsuite/gcc.target/riscv/interrupt-3.c
+++ b/gcc/testsuite/gcc.target/riscv/interrupt-3.c
@@ -1,4 +1,4 @@
-/* Verify t1 is saved before use. */
+/* Verify t0 is saved before use. */
/* { dg-do compile } */
/* { dg-options "-O0 -fomit-frame-pointer" } */
void __attribute__ ((interrupt))
@@ -6,4 +6,4 @@ foo (void)
{
char array[4096];
}
-/* { dg-final { scan-assembler "s\[wd\]\tt1" } } */
+/* { dg-final { scan-assembler "s\[wd\]\tt0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-4.c b/gcc/testsuite/gcc.target/riscv/interrupt-4.c
index b6fdd19..658aa17 100644
--- a/gcc/testsuite/gcc.target/riscv/interrupt-4.c
+++ b/gcc/testsuite/gcc.target/riscv/interrupt-4.c
@@ -1,4 +1,4 @@
-/* Verify t1 is saved before use. */
+/* Verify t0 is saved before use. */
/* { dg-do compile } */
/* { dg-options "-O0 -fomit-frame-pointer" } */
void __attribute__ ((interrupt))
@@ -15,4 +15,4 @@ foo2 (void)
COUNTER++;
#endif
}
-/* { dg-final { scan-assembler "s\[wd\]\tt1" } } */
+/* { dg-final { scan-assembler "s\[wd\]\tt0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr91441.c b/gcc/testsuite/gcc.target/riscv/pr91441.c
deleted file mode 100644
index b55df5e..0000000
--- a/gcc/testsuite/gcc.target/riscv/pr91441.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* PR target/91441 */
-/* { dg-do compile } */
-/* { dg-options "--param asan-stack=1 -fsanitize=kernel-address" } */
-
-int *bar(int *);
-int *f( int a)
-{
- return bar(&a);
-}
-/* { dg-warning ".'-fsanitize=kernel-address' with stack protection is not supported without '-fasan-shadow-offset=' for this target" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr96260.c b/gcc/testsuite/gcc.target/riscv/pr96260.c
deleted file mode 100644
index 229997f..0000000
--- a/gcc/testsuite/gcc.target/riscv/pr96260.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* PR target/96260 */
-/* { dg-do compile } */
-/* { dg-options "--param asan-stack=1 -fsanitize=kernel-address -fasan-shadow-offset=0x100000" } */
-
-int *bar(int *);
-int *f( int a)
-{
- return bar(&a);
-}
diff --git a/gcc/testsuite/gcc.target/s390/builtin-constant-p-threading.c b/gcc/testsuite/gcc.target/s390/builtin-constant-p-threading.c
new file mode 100644
index 0000000..5f0acdc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/builtin-constant-p-threading.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z196 -mzarch" } */
+
+typedef struct
+{
+ int counter;
+} atomic_t;
+
+static inline __attribute__ ((__gnu_inline__)) int
+__atomic_add (int val, int *ptr)
+{
+ int old;
+ asm volatile("laa %[old],%[val],%[ptr]\n"
+ : [old] "=d" (old), [ptr] "+Q"(*ptr)
+ : [val] "d" (val)
+ : "cc", "memory");
+ return old;
+}
+
+static inline __attribute__ ((__gnu_inline__)) void
+__atomic_add_const (int val, int *ptr)
+{
+ asm volatile("asi %[ptr],%[val]\n"
+ : [ptr] "+Q" (*ptr)
+ : [val] "i" (val)
+ : "cc", "memory");
+}
+
+static inline __attribute__ ((__gnu_inline__)) void
+atomic_add (int i, atomic_t *v)
+{
+ if (__builtin_constant_p (i) && (i > -129) && (i < 128))
+ {
+ __atomic_add_const (i, &v->counter);
+ return;
+ }
+ __atomic_add (i, &v->counter);
+}
+
+static atomic_t num_active_cpus = { (0) };
+
+void
+ledtrig_cpu (_Bool is_active)
+{
+ atomic_add (is_active ? 1 : -1, &num_active_cpus);
+}
diff --git a/gcc/testsuite/gcc.target/s390/float_t-1.c b/gcc/testsuite/gcc.target/s390/float_t-1.c
new file mode 100644
index 0000000..3455694
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/float_t-1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-std=c99" } */
+#include <math.h>
+#include <stdlib.h>
+
+int main()
+{
+ /* In standard-compliant mode, the size of float_t and FLT_EVAL_METHOD must
+ match. */
+ if (sizeof(float_t) == sizeof(double) && __FLT_EVAL_METHOD__ != 1)
+ abort();
+ if (sizeof(float_t) == sizeof(float) && __FLT_EVAL_METHOD__ != 0)
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/float_t-2.c b/gcc/testsuite/gcc.target/s390/float_t-2.c
new file mode 100644
index 0000000..ebeda28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/float_t-2.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-std=gnu99" } */
+#include <math.h>
+#include <stdlib.h>
+
+int main()
+{
+ /* In gnuXY mode, the size of float_t and FLT_EVAL_METHOD must
+ match, with the historic exception of permitting double and 0. */
+ if (sizeof(float_t) == sizeof(float) && __FLT_EVAL_METHOD__ == 1)
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/load-imm64-1.c b/gcc/testsuite/gcc.target/s390/load-imm64-1.c
new file mode 100644
index 0000000..03d17f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/load-imm64-1.c
@@ -0,0 +1,14 @@
+/* Test that large 64-bit constants are loaded with llihf + oilf when lgrl is
+ not available. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z9-109" } */
+
+unsigned long
+magic (void)
+{
+ return 0x3f08c5392f756cd;
+}
+
+/* { dg-final { scan-assembler-times {\n\tllihf\t} 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\n\toilf\t} 1 { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/s390/load-imm64-2.c b/gcc/testsuite/gcc.target/s390/load-imm64-2.c
new file mode 100644
index 0000000..ee0ff3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/load-imm64-2.c
@@ -0,0 +1,14 @@
+/* Test that large 64-bit constants are loaded with llihf + oilf when lgrl is
+ available. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10" } */
+
+unsigned long
+magic (void)
+{
+ return 0x3f08c5392f756cd;
+}
+
+/* { dg-final { scan-assembler-times {\n\tllihf\t} 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\n\toilf\t} 1 { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/s390/pr97497.c b/gcc/testsuite/gcc.target/s390/pr97497.c
new file mode 100644
index 0000000..460c850
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr97497.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -march=z900 -mzarch -fpic" } */
+
+char *t;
+
+void __attribute__((noinline,noclone))
+bar(int a, char* b)
+{
+ if (a != 1)
+ __builtin_abort();
+}
+
+void __attribute__((noinline,noclone))
+baz(char* a, int b)
+{
+ if (b != 1)
+ __builtin_abort();
+}
+
+int __attribute__((noinline,noclone))
+foo (int a)
+{
+ bar (1, t);
+ if (a)
+ baz (t, 1);
+
+ bar (1, t);
+}
+
+int
+main ()
+{
+ foo (1);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/s390.exp b/gcc/testsuite/gcc.target/s390/s390.exp
index 387a720..d76d80d 100644
--- a/gcc/testsuite/gcc.target/s390/s390.exp
+++ b/gcc/testsuite/gcc.target/s390/s390.exp
@@ -192,6 +192,23 @@ proc check_effective_target_s390_z13_hw { } {
}
}] "-march=z13 -m64 -mzarch" ] } { return 0 } else { return 1 }
}
+proc check_effective_target_s390_z14_hw { } {
+ if { ![check_runtime s390_check_s390_z14_hw [subst {
+ int main (void)
+ {
+ int x = 0;
+ asm ("msgrkc %%0,%%0,%%0" : "+r" (x) : );
+ return x;
+ }
+ }] "-march=z14 -m64 -mzarch" ] } { return 0 } else { return 1 }
+}
+# Return 1 if the default compiler options enable z/Architecture mode
+proc check_effective_target_s390_zarch { } {
+ return [check_no_compiler_messages s390_zarch object {
+ int dummy[sizeof (int __attribute__((__mode__(__word__)))) == 8
+ ? 1 : -1];
+ }]
+}
# If a testcase doesn't have special options, use these.
global DEFAULT_CFLAGS
diff --git a/gcc/testsuite/gcc.target/s390/stack-clash-1.c b/gcc/testsuite/gcc.target/s390/stack-clash-1.c
index 3d29cab..45221c4 100644
--- a/gcc/testsuite/gcc.target/s390/stack-clash-1.c
+++ b/gcc/testsuite/gcc.target/s390/stack-clash-1.c
@@ -13,5 +13,5 @@ void large_stack() {
/* We use a compare for the stack probe. There needs to be one inside
a loop and another for the remaining bytes. */
-/* { dg-final { scan-assembler-times "cg\t" 2 { target lp64 } } } */
-/* { dg-final { scan-assembler-times "c\t" 2 { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler-times "cg\t" 2 { target s390_zarch } } } */
+/* { dg-final { scan-assembler-times "c\t" 2 { target { ! s390_zarch } } } } */
diff --git a/gcc/testsuite/gcc.target/s390/stack-clash-2.c b/gcc/testsuite/gcc.target/s390/stack-clash-2.c
index e554ad5..20f645d 100644
--- a/gcc/testsuite/gcc.target/s390/stack-clash-2.c
+++ b/gcc/testsuite/gcc.target/s390/stack-clash-2.c
@@ -13,5 +13,5 @@ foo ()
/* For alloca a common code routine emits the probes. Make sure the
"probe_stack" expander is used in that case. We want to use mem
compares instead of stores. */
-/* { dg-final { scan-assembler-times "cg\t" 5 { target lp64 } } } */
-/* { dg-final { scan-assembler-times "c\t" 5 { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler-times "cg\t" 5 { target s390_zarch } } } */
+/* { dg-final { scan-assembler-times "c\t" 5 { target { ! s390_zarch } } } } */
diff --git a/gcc/testsuite/gcc.target/s390/stack-clash-3.c b/gcc/testsuite/gcc.target/s390/stack-clash-3.c
index 929d3fb..12a2d34 100644
--- a/gcc/testsuite/gcc.target/s390/stack-clash-3.c
+++ b/gcc/testsuite/gcc.target/s390/stack-clash-3.c
@@ -13,5 +13,5 @@ foo ()
/* For alloca a common code routine emits the probes. Make sure the
"probe_stack" expander is used in that case. We want to use mem
compares instead of stores. */
-/* { dg-final { scan-assembler-times "cg\t" 5 { target lp64 } } } */
-/* { dg-final { scan-assembler-times "c\t" 5 { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler-times "cg\t" 5 { target s390_zarch } } } */
+/* { dg-final { scan-assembler-times "c\t" 5 { target { ! s390_zarch } } } } */
diff --git a/gcc/testsuite/gcc.target/s390/stack-clash-4.c b/gcc/testsuite/gcc.target/s390/stack-clash-4.c
new file mode 100644
index 0000000..619d99d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/stack-clash-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -m31 -mzarch -fstack-clash-protection" } */
+
+extern void c(char*);
+
+void
+a() {
+ char *b = __builtin_alloca(3);
+ c(b);
+}
diff --git a/gcc/testsuite/gcc.target/s390/stack-clash-5.c b/gcc/testsuite/gcc.target/s390/stack-clash-5.c
new file mode 100644
index 0000000..81e202e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/stack-clash-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -m31 -mzarch -fstack-clash-protection" } */
+
+extern void bar (char*);
+
+void
+foo() {
+ char a[4000];
+ bar (a) ;
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-callee-abi-scan.c b/gcc/testsuite/gcc.target/s390/vector/long-double-callee-abi-scan.c
new file mode 100644
index 0000000..69e8c61
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-callee-abi-scan.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -fno-unroll-loops" } */
+#include <stdarg.h>
+
+__attribute__ ((noipa, used)) long double
+long_double_callee (long double x, int n, ...)
+{
+ long double sum = x;
+ va_list vl;
+ int i;
+
+ va_start (vl, n);
+ for (i = 0; i < n; i++)
+ sum += va_arg (vl, long double);
+ va_end (vl);
+
+ return sum;
+}
+
+/* { dg-final { scan-assembler-times {\n\tvl\t} 3 } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-run.c b/gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-run.c
new file mode 100644
index 0000000..f7315f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-run.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include "long-double-callee-abi-scan.c"
+#include "long-double-caller-abi-scan.c"
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-scan.c b/gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-scan.c
new file mode 100644
index 0000000..c1ec5b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-caller-abi-scan.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include <assert.h>
+
+long double long_double_callee (long double x, int n, ...);
+
+int
+main ()
+{
+ assert (long_double_callee (1.L, 2, 2.L, 3.L) == 6.L);
+}
+
+/* { dg-final { scan-assembler-times {\n\tvst\t} 3 } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-copysign.c b/gcc/testsuite/gcc.target/s390/vector/long-double-copysign.c
new file mode 100644
index 0000000..5d69e0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-copysign.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_copysign (long double x, long double y)
+{
+ return __builtin_copysignl (x, y);
+}
+
+/* { dg-final { scan-assembler-times {\n\tvsel\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_copysign (1.1L, 2.2L) == 1.1L);
+ assert (long_double_copysign (1.1L, -2.2L) == -1.1L);
+ assert (long_double_copysign (-1.1L, 2.2L) == 1.1L);
+ assert (long_double_copysign (-1.1L, -2.2L) == -1.1L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-fprx2-constant.c b/gcc/testsuite/gcc.target/s390/vector/long-double-fprx2-constant.c
new file mode 100644
index 0000000..02a6a1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-fprx2-constant.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mtune=z14 -funroll-loops" } */
+
+long double a;
+int d;
+void
+b ()
+{
+ for (int c = 0; c < d; ++c)
+ a = (a - c) / (c + 1);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-double.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-double.c
new file mode 100644
index 0000000..d98e44d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-double.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_double (double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_double (42.) == 42.L);
+ assert (long_double_from_double (-42.) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-float.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-float.c
new file mode 100644
index 0000000..0ddd47d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-float.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_float (float x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tldebr\t} 1 } } */
+/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_float (42.F) == 42.L);
+ assert (long_double_from_float (-42.F) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-i16.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i16.c
new file mode 100644
index 0000000..f7d37c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i16.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_i16 (int16_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_i16 (42) == 42.L);
+ assert (long_double_from_i16 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-i32.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i32.c
new file mode 100644
index 0000000..49d919d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i32.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_i32 (int32_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_i32 (42) == 42.L);
+ assert (long_double_from_i32 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-i64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i64.c
new file mode 100644
index 0000000..986a5eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i64.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_i64 (int64_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxgbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_i64 (42) == 42.L);
+ assert (long_double_from_i64 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-i8.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i8.c
new file mode 100644
index 0000000..9356af1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-i8.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_i8 (int8_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_i8 (42) == 42.L);
+ assert (long_double_from_i8 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-u16.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u16.c
new file mode 100644
index 0000000..3aafeb4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u16.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_u16 (uint16_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_u16 (42) == 42.L);
+ assert (long_double_from_u16 (-42) == 65494.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-u32.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u32.c
new file mode 100644
index 0000000..655f5d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u32.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_u32 (uint32_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_u32 (42) == 42.L);
+ assert (long_double_from_u32 (-42) == 4294967254.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-u64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u64.c
new file mode 100644
index 0000000..601ff9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u64.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_u64 (uint64_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlgbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_u64 (42) == 42.L);
+ assert (long_double_from_u64 (-42) == 18446744073709551574.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-u8.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u8.c
new file mode 100644
index 0000000..a43b4c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-from-u8.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static long double
+long_double_from_u8 (uint8_t x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_from_u8 (42) == 42.L);
+ assert (long_double_from_u8 (-42) == 214.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-double.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-double.c
new file mode 100644
index 0000000..71ed8b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-double.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+__attribute__ ((noipa)) static double
+long_double_to_double (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\twflrx\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_double (42.L) == 42.);
+ assert (long_double_to_double (-42.L) == -42.);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-float.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-float.c
new file mode 100644
index 0000000..a2855e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-float.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+__attribute__ ((noipa)) static float
+long_double_to_float (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\twflrx\t%v\d+,%v\d+,0,3\n} 1 } } */
+/* { dg-final { scan-assembler-times {\n\tledbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_float (42.L) == 42.F);
+ assert (long_double_to_float (-42.L) == -42.F);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-i16.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i16.c
new file mode 100644
index 0000000..1dd0e81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i16.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static int16_t
+long_double_to_i16 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_i16 (42.L) == 42);
+ assert (long_double_to_i16 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-i32.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i32.c
new file mode 100644
index 0000000..0d5678b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i32.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static int32_t
+long_double_to_i32 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_i32 (42.L) == 42);
+ assert (long_double_to_i32 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-i64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i64.c
new file mode 100644
index 0000000..2dbbb5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i64.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static int64_t
+long_double_to_i64 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,1\n} 1 } } */
+/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,5\n} 1 } } */
+/* { dg-final { scan-assembler-times {\n\tcgxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_i64 (42.L) == 42);
+ assert (long_double_to_i64 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-i8.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i8.c
new file mode 100644
index 0000000..9b0b45d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-i8.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static int8_t
+long_double_to_i8 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_i8 (42.L) == 42);
+ assert (long_double_to_i8 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-u16.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u16.c
new file mode 100644
index 0000000..f9ad0c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u16.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static uint16_t
+long_double_to_u16 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_u16 (42.L) == 42);
+ /* Not (-42 & 0xffff) due to loss of precision. */
+ assert (long_double_to_u16 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-u32.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u32.c
new file mode 100644
index 0000000..37b0616
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u32.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static uint32_t
+long_double_to_u32 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_u32 (42.L) == 42);
+ /* Not (-42 & 0xffffffff) due to loss of precision. */
+ assert (long_double_to_u32 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-u64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u64.c
new file mode 100644
index 0000000..051934d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u64.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static uint64_t
+long_double_to_u64 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclgxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_u64 (42.L) == 42);
+ /* Not (-42 & 0xffffffffffffffff) due to loss of precision. */
+ assert (long_double_to_u64 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-u8.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u8.c
new file mode 100644
index 0000000..cf3204c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-to-u8.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+#include <stdint.h>
+
+__attribute__ ((noipa)) static uint8_t
+long_double_to_u8 (long double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
+
+int
+main (void)
+{
+ assert (long_double_to_u8 (42.L) == 42);
+ /* Not (-42 & 0xff) due to loss of precision. */
+ assert (long_double_to_u8 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-vec-duplicate.c b/gcc/testsuite/gcc.target/s390/vector/long-double-vec-duplicate.c
new file mode 100644
index 0000000..2ce9da3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-vec-duplicate.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -funroll-loops -march=z14 -mtune=z14" } */
+
+long double a, b;
+double *c;
+long double *d;
+
+void
+e ()
+{
+ while (d != &a)
+ *d++ = b * *c++;
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wf.h b/gcc/testsuite/gcc.target/s390/vector/long-double-wf.h
new file mode 100644
index 0000000..a564fc6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wf.h
@@ -0,0 +1,60 @@
+#ifndef LONG_DOUBLE_WF_H
+#define LONG_DOUBLE_WF_H 1
+
+#include <math.h>
+
+#define ADD(x, y, z) ((x) + (z))
+#define DIV(x, y, z) ((x) / (z))
+#define FABSL(x, y, z) (fabsl (y))
+#define ISINFL(x, y, z) (isinfl (x) ? (y) : (z))
+#define MUL(x, y, z) ((x) * (z))
+#define MUL_ADD(x, y, z) ((x) * (y) + (z))
+#define MUL_SUB(x, y, z) ((x) * (y) - (z))
+#define NEG(x, y, z) \
+ ({ \
+ volatile long double r = -(y); \
+ r; \
+ })
+#define NEG_MUL_ADD(x, y, z) NEG (0, MUL_ADD (x, y, z), 0)
+#define NEG_MUL_SUB(x, y, z) NEG (0, MUL_SUB (x, y, z), 0)
+#define QUIET_IFEQUAL(x, y, z) ((x) == (y) ? (z) : 0)
+#define QUIET_IFGREATER(x, y, z) (__builtin_isgreater (x, y) ? (z) : 0)
+#define QUIET_IFLESS(x, y, z) (__builtin_isless (x, y) ? (z) : 0)
+#define QUIET_IFUNORDERED(x, y, z) (__builtin_isunordered (x, y) ? (z) : 0)
+#define SIGNALING_IFEQUAL(x, y, z) (((x) >= (y) && (x) <= (y)) ? (z) : 0)
+#define SIGNALING_IFGREATER(x, y, z) ((x) > (y) ? (z) : 0)
+#define SIGNALING_IFLESS(x, y, z) ((x) < (y) ? (z) : 0)
+#define ROUNDL(x, y, z) (roundl (y))
+#define SQRTL(x, y, z) (sqrtl (y))
+#define SUB(x, y, z) ((x) - (z))
+
+#define LONG_DOUBLE_WF(op) \
+ long double test ( \
+ long double x0, long double x1, long double x2, long double x3, \
+ long double x4, long double x5, long double x6, long double x7, \
+ long double x8, long double x9, long double x10, long double x11, \
+ long double x12, long double x13, long double x14, long double x15) \
+ { \
+ while (x15 < 1E+30) \
+ { \
+ x0 = op (x1, x2, x3); \
+ x1 = op (x2, x3, x4) + 1; \
+ x2 = op (x3, x4, x5) + 2; \
+ x3 = op (x4, x5, x6) + 3; \
+ x4 = op (x5, x6, x7) + 4; \
+ x5 = op (x6, x7, x8) + 5; \
+ x6 = op (x7, x8, x9) + 6; \
+ x7 = op (x8, x9, x10) + 7; \
+ x8 = op (x9, x10, x11) + 8; \
+ x9 = op (x10, x11, x12) + 9; \
+ x10 = op (x11, x12, x13) + 10; \
+ x11 = op (x12, x13, x14) + 11; \
+ x12 = op (x13, x14, x15) + 12; \
+ x13 = op (x14, x15, x0) + 13; \
+ x14 = op (x15, x0, x1) + 14; \
+ x15 = op (x0, x1, x2) + 15; \
+ } \
+ return x15; \
+ }
+
+#endif
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfaxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfaxb.c
new file mode 100644
index 0000000..5a10bd1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfaxb.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+__attribute__ ((noipa)) static long double
+wfaxb (long double x, long double y, long double z)
+{
+ return x + y + z;
+}
+
+/* { dg-final { scan-assembler-times {\n\twfaxb\t} 2 } } */
+
+int
+main (void)
+{
+ assert (wfaxb (1.11L, 2.22L, 3.33L) == 6.66L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0001.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0001.c
new file mode 100644
index 0000000..9ffff6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0001.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFUNORDERED);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jo == brc 0b0001, ... */
+/* { dg-final { scan-assembler {\n\tjo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0111.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0111.c
new file mode 100644
index 0000000..3ade835
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-0111.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFEQUAL);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jne == brc 0b0111, ... */
+/* { dg-final { scan-assembler {\n\tjne\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1011.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1011.c
new file mode 100644
index 0000000..a9c819d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1011.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFLESS);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jnl == brc 0b1011, ... */
+/* { dg-final { scan-assembler {\n\tjnl\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1101.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1101.c
new file mode 100644
index 0000000..47ea7c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfcxb-1101.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFGREATER);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jnh == brc 0b1101, ... */
+/* { dg-final { scan-assembler {\n\tjnh\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfdxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfdxb.c
new file mode 100644
index 0000000..db517e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfdxb.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+__attribute__ ((noipa)) static long double
+wfdxb (long double x, long double y, long double z)
+{
+ return (x / y) / z;
+}
+
+/* { dg-final { scan-assembler-times {\n\twfdxb\t} 2 } } */
+
+int
+main (void)
+{
+ assert (wfdxb (2.22L, 1.11L, 2.L) == 1.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfixb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfixb.c
new file mode 100644
index 0000000..69348bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfixb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (ROUNDL);
+
+/* { dg-final { scan-assembler {\n\twfixb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-0111.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-0111.c
new file mode 100644
index 0000000..0f7b209
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-0111.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SIGNALING_IFEQUAL);
+
+/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
+/* jne == brc 0b0111, ... */
+/* { dg-final { scan-assembler {\n\tjne\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1011.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1011.c
new file mode 100644
index 0000000..b76dbb0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1011.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SIGNALING_IFLESS);
+
+/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
+/* jnl == brc 0b1011, ... */
+/* { dg-final { scan-assembler {\n\tjnl\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1101.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1101.c
new file mode 100644
index 0000000..61f0ec4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfkxb-1101.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SIGNALING_IFGREATER);
+
+/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
+/* jnh == brc 0b1101, ... */
+/* { dg-final { scan-assembler {\n\tjnh\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wflcxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wflcxb.c
new file mode 100644
index 0000000..ddcf972
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wflcxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG);
+
+/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wflpxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wflpxb.c
new file mode 100644
index 0000000..df90505
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wflpxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (FABSL);
+
+/* { dg-final { scan-assembler {\n\twflpxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-2.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-2.c
new file mode 100644
index 0000000..0b2fdcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -mvx-long-double-fma" } */
+
+int a, c, d, f, k, l, m;
+long double b, e, g, h, i;
+double j;
+
+void
+n (void)
+{
+ while (m)
+ {
+ a = b * d;
+ b = c;
+ c = d * e + 2;
+ e = f + g + 4;
+ f = h + 6;
+ g = h * 0 + i + 7;
+ h = i + 9;
+ i = j * k + 0 + 10;
+ j = l;
+ m = a * b;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-3.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-3.c
new file mode 100644
index 0000000..9ef49c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -mvx-long-double-fma" } */
+
+long double a, c, d;
+int b;
+void
+e (void)
+{
+ while (d)
+ {
+ a = 0 * c + 0;
+ d = b;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-disabled.c
new file mode 100644
index 0000000..59bc80a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb-disabled.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb.c
new file mode 100644
index 0000000..319a02f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmaxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -mvx-long-double-fma" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfmaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb-disabled.c
new file mode 100644
index 0000000..bb5c0f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb-disabled.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb.c
new file mode 100644
index 0000000..c14f673
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmsxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -mvx-long-double-fma" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfmsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfmxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmxb.c
new file mode 100644
index 0000000..6ab1e68
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfmxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb-disabled.c
new file mode 100644
index 0000000..8c5298e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb-disabled.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
+/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb.c
new file mode 100644
index 0000000..9f0da13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmaxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -mvx-long-double-fma" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfnmaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb-disabled.c
new file mode 100644
index 0000000..39e4f60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb-disabled.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
+/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb.c
new file mode 100644
index 0000000..698e277
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfnmsxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch -mvx-long-double-fma" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfnmsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfsqxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfsqxb.c
new file mode 100644
index 0000000..09f9128
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfsqxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SQRTL);
+
+/* { dg-final { scan-assembler {\n\twfsqxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb-1.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb-1.c
new file mode 100644
index 0000000..06750a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+#include <assert.h>
+
+typedef float tf __attribute__ ((mode (TF)));
+static tf x;
+static tf y;
+
+__attribute__ ((noipa)) static tf
+sub (void)
+{
+ return x - y;
+}
+
+int
+main (void)
+{
+ x = 1.5L;
+ y = 2.5L;
+ assert (sub () == -1.0L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb.c
new file mode 100644
index 0000000..1c430ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wfsxb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SUB);
+
+/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb-1.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb-1.c
new file mode 100644
index 0000000..224995f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=z14 -mzarch" } */
+
+int a, b;
+
+void
+c (void)
+{
+ long double d;
+ a = d;
+ if (__builtin_isinf (d))
+ b = 0;
+}
+
+/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb.c b/gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb.c
new file mode 100644
index 0000000..c2658b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-wftcixb.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (ISINFL);
+
+/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
index 3d6da30..7c9b20f 100644
--- a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
@@ -5,6 +5,9 @@
AUTOVEC_DOUBLE (QUIET_UNEQ);
+/* { dg-final { scan-assembler {\n\tvzero\t} } } */
+/* { dg-final { scan-assembler {\n\tvgmg\t} } } */
/* { dg-final { scan-assembler-times {\n\tvfchdb\t} 2 } } */
/* { dg-final { scan-assembler {\n\tvo\t} } } */
-/* { dg-final { scan-assembler {\n\tvx\t} } } */
+/* { dg-final { scan-assembler {\n\tvsel\t} } } */
+/* { dg-final { scan-assembler-not {\n\tvx\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
index a8402b9..3645d3c 100644
--- a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fexceptions -fnon-call-exceptions" } */
#include "autovec.h"
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
index 1df53a9..5ab9337 100644
--- a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
@@ -5,6 +5,9 @@
AUTOVEC_FLOAT (QUIET_UNEQ);
+/* { dg-final { scan-assembler {\n\tvzero\t} } } */
+/* { dg-final { scan-assembler {\n\tvgmf\t} } } */
/* { dg-final { scan-assembler-times {\n\tvfchsb\t} 2 } } */
/* { dg-final { scan-assembler {\n\tvo\t} } } */
-/* { dg-final { scan-assembler {\n\tvx\t} } } */
+/* { dg-final { scan-assembler {\n\tvsel\t} } } */
+/* { dg-final { scan-assembler-not {\n\tvx\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
index 7dd91a5..d98aa0c 100644
--- a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fexceptions -fnon-call-exceptions" } */
#include "autovec.h"
diff --git a/gcc/testsuite/gcc.target/sparc/overflow-6.c b/gcc/testsuite/gcc.target/sparc/overflow-6.c
new file mode 100644
index 0000000..11aafc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/overflow-6.c
@@ -0,0 +1,20 @@
+/* PR target/97939 */
+/* Reported by Vincent Lefevre <vincent-gcc@vinc17.net> */
+
+/* { dg-do run } */
+
+#include <limits.h>
+
+long add (long i)
+{
+ long r;
+ if (!__builtin_add_overflow (i, 4096, &r))
+ __builtin_abort ();
+ return r;
+}
+
+int main (void)
+{
+ add (LONG_MAX);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/vax/bbcci.c b/gcc/testsuite/gcc.target/vax/bbcci.c
new file mode 100644
index 0000000..f58d3a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/bbcci.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#include <stdatomic.h>
+
+extern volatile atomic_flag guard;
+
+void
+try_atomic_flag_clear (void)
+{
+ atomic_flag_clear (&guard);
+}
+
+/* Expect assembly like:
+
+ jbcci $0,guard,.L2
+.L2:
+
+ */
+
+/* { dg-final { scan-assembler "\tjbcci \\\$0,guard," } } */
diff --git a/gcc/testsuite/gcc.target/vax/bbssi.c b/gcc/testsuite/gcc.target/vax/bbssi.c
new file mode 100644
index 0000000..65111e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/bbssi.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#include <stdatomic.h>
+
+extern volatile atomic_flag guard;
+
+void
+try_atomic_flag_test_and_set (void)
+{
+ atomic_flag_test_and_set (&guard);
+}
+
+/* Expect assembly like:
+
+ jbssi $0,guard,.L1
+.L1:
+
+ */
+
+/* { dg-final { scan-assembler "\tjbssi \\\$0,guard," } } */
diff --git a/gcc/testsuite/gcc.target/vax/bswapdi-1.c b/gcc/testsuite/gcc.target/vax/bswapdi-1.c
index c658d91..1baa018 100644
--- a/gcc/testsuite/gcc.target/vax/bswapdi-1.c
+++ b/gcc/testsuite/gcc.target/vax/bswapdi-1.c
@@ -1,3 +1,5 @@
+/* { dg-options "" } */
+
typedef int DItype __attribute__ ((mode (DI)));
DItype
__bswapdi2 (DItype u)
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-adddf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-adddf.c
new file mode 100644
index 0000000..872d46b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-adddf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+eq_adddf (float_t x, float_t y)
+{
+ x += y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addd3 4(%ap),12(%ap),%r0 # 35 [c=68] *adddf3_ccz/2
+ jeql .L1 # 37 [c=26] *branch_ccz
+ addd2 $0d2.0e+0,%r0 # 34 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "adddf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-addhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addhi.c
new file mode 100644
index 0000000..3a5dbad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_addhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x + *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ addw3 *8(%ap),*12(%ap),%r0 # 33 [c=64] *addhi3_ccz
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addw2 $2,%r0 # 32 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-addqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addqi.c
new file mode 100644
index 0000000..b0fe468
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_addqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x + *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ addb3 *8(%ap),*12(%ap),%r0 # 33 [c=64] *addqi3_ccz
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addb2 $2,%r0 # 32 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-addsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addsf.c
new file mode 100644
index 0000000..de9e9c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+eq_addsf (float_t x, float_t y)
+{
+ x += y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addf3 4(%ap),8(%ap),%r0 # 34 [c=48] *addsf3_ccz/2
+ jeql .L1 # 36 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 33 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-addsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addsi.c
new file mode 100644
index 0000000..6998e60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-addsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_addsi (int_t x, int_t y)
+{
+ x += y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addl3 4(%ap),8(%ap),%r0 # 33 [c=48] *addsi3_ccz
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-andhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-andhi.c
new file mode 100644
index 0000000..d4d0c59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-andhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_andhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & ~*y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bicw3 *12(%ap),*8(%ap),%r0 # 34 [c=44] *andhi3_2_ccz/1
+ jeql .L2 # 36 [c=26] *branch_ccz
+ addw2 $2,%r0 # 33 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-andqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-andqi.c
new file mode 100644
index 0000000..efa0dfe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-andqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_andqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & ~*y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bicb3 *12(%ap),*8(%ap),%r0 # 34 [c=44] *andqi3_2_ccz/1
+ jeql .L2 # 36 [c=26] *branch_ccz
+ addb2 $2,%r0 # 33 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-andsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-andsi.c
new file mode 100644
index 0000000..9afc860
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-andsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_andsi (int_t x, int_t y)
+{
+ x &= ~y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ bicl3 8(%ap),4(%ap),%r0 # 35 [c=28] *andsi3_2_ccz/1
+ jeql .L1 # 37 [c=26] *branch_ccz
+ addl2 $2,%r0 # 34 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-ashlsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-ashlsi.c
new file mode 100644
index 0000000..a824f2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-ashlsi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+eq_ashlsi (int_t x, short_t y)
+{
+ x <<= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ ashl 8(%ap),4(%ap),%r0 # 35 [c=56] *ashlsi3_ccz
+ jeql .L1 # 37 [c=26] *branch_ccz
+ addl2 $2,%r0 # 34 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ashlsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-ashrsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-ashrsi.c
new file mode 100644
index 0000000..5f1e3a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-ashrsi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+eq_ashrsi (int_t x, short_t y)
+{
+ x >>= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mnegb 8(%ap),%r0 # 36 [c=16] *negqi2
+ ashl %r0,4(%ap),%r0 # 37 [c=52] *ashlnegsi3_2_ccz
+ jeql .L1 # 39 [c=26] *branch_ccz
+ addl2 $2,%r0 # 35 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ashlnegsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-divdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divdf.c
new file mode 100644
index 0000000..7101960
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divdf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+eq_divdf (float_t x, float_t y)
+{
+ x /= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divd3 12(%ap),4(%ap),%r0 # 35 [c=112] *divdf3_ccz/1
+ jeql .L1 # 37 [c=26] *branch_ccz
+ addd2 $0d2.0e+0,%r0 # 34 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divdf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-divhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divhi.c
new file mode 100644
index 0000000..03866f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI), vector_size (2))) int_t;
+
+void
+eq_divhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x / *y;
+ if (v[0] == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ divw3 *12(%ap),*8(%ap),%r0 # 38 [c=76] *divhi3_ccz/1
+ jeql .L2 # 40 [c=26] *branch_ccz
+ addw2 $2,%r0 # 37 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-divqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divqi.c
new file mode 100644
index 0000000..e4cfbf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI), vector_size (1))) int_t;
+
+void
+eq_divqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x / *y;
+ if (v[0] == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ divb3 *12(%ap),*8(%ap),%r0 # 38 [c=76] *divqi3_ccz/1
+ jeql .L2 # 40 [c=26] *branch_ccz
+ addb2 $2,%r0 # 37 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-divsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divsf.c
new file mode 100644
index 0000000..492becf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+eq_divsf (float_t x, float_t y)
+{
+ x /= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divf3 8(%ap),4(%ap),%r0 # 34 [c=60] *divsf3_ccz/1
+ jeql .L1 # 36 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 33 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divsf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-divsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divsi.c
new file mode 100644
index 0000000..324614f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-divsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_divsi (int_t x, int_t y)
+{
+ x /= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divl3 8(%ap),4(%ap),%r0 # 33 [c=60] *divsi3_ccz/1
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-extendhisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extendhisi.c
new file mode 100644
index 0000000..f875da9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extendhisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (HI))) short_t;
+
+int_t
+eq_extendhisi (int_t x)
+{
+ x = (short_t) x;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ cvtwl 4(%ap),%r0 # 33 [c=20] *extendhisi2_ccz
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extendhisi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-extendqisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extendqisi.c
new file mode 100644
index 0000000..16a6acd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extendqisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+eq_extendqisi (int_t x)
+{
+ x = (short_t) x;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ cvtbl 4(%ap),%r0 # 33 [c=20] *extendqisi2_ccz
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extendqisi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-extvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extvsi.c
new file mode 100644
index 0000000..5383059
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extvsi.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+eq_extvsi (bit_t x)
+{
+ int_t v;
+
+ v = x.i;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ extv $7,$18,4(%ap),%r0 # 32 [c=68] *extv_non_const_2_ccz
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-extzvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extzvsi.c
new file mode 100644
index 0000000..d21fa29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-extzvsi.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+eq_extzvsi (bit_t x)
+{
+ int_t v;
+
+ v = x.i;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ rotl $25,4(%ap),%r0 # 32 [c=68] *extzv_non_const_2_ccz
+ bicl2 $-262144,%r0
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extzv\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfhi.c
new file mode 100644
index 0000000..8912d14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfhi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_fixdfhi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdw 8(%ap),%r0 # 31 [c=36] *fix_truncdfhi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addw2 $2,%r0 # 30 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfqi.c
new file mode 100644
index 0000000..12f9385
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfqi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_fixdfqi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdb 8(%ap),%r0 # 31 [c=36] *fix_truncdfqi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addb2 $2,%r0 # 30 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfsi.c
new file mode 100644
index 0000000..ad54d88
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixdfsi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_fixdfsi (float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdl 4(%ap),%r0 # 32 [c=36] *fix_truncdfsi2_ccz
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfhi.c
new file mode 100644
index 0000000..0c26857
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfhi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_fixsfhi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfw 8(%ap),%r0 # 31 [c=36] *fix_truncsfhi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addw2 $2,%r0 # 30 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfqi.c
new file mode 100644
index 0000000..2d32525
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfqi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_fixsfqi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfb 8(%ap),%r0 # 31 [c=36] *fix_truncsfqi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addb2 $2,%r0 # 30 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfsi.c
new file mode 100644
index 0000000..a704ad8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-fixsfsi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_fixsfsi (float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfl 4(%ap),%r0 # 32 [c=36] *fix_truncsfsi2_ccz
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-floatsisf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-floatsisf.c
new file mode 100644
index 0000000..1ea83cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-floatsisf.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+float_t
+eq_floatsisf (int_t x)
+{
+ float_t v;
+
+ v = x;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtlf 4(%ap),%r0 # 33 [c=32] *floatsisf2_ccz
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 32 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "floatsisf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-insvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-insvsi.c
new file mode 100644
index 0000000..fbdcdb4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-insvsi.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef union
+ {
+ int_t i;
+ struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ } b;
+ }
+bit_t;
+
+int
+eq_insvsi (bit_t x, int_t y)
+{
+ int_t v;
+
+ v = x.b.i;
+ x.b.i = y;
+ if (v != 0)
+ return x.i;
+ else
+ return x.i + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 35 [c=16] *movsi_2
+ extv $7,$18,%r0,%r1 # 36 [c=60] *extv_non_const_2_ccz
+ insv 8(%ap),$7,$18,%r0 # 8 [c=16] *insv_2
+ jneq .L1 # 38 [c=26] *branch_ccz
+ addl2 $2,%r0 # 34 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "extv.*insv.*branch" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorhi.c
new file mode 100644
index 0000000..9bbe881
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_iorhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x | *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bisw3 *12(%ap),*8(%ap),%r0 # 32 [c=44] *iorhi3_ccz/2
+ jeql .L2 # 34 [c=26] *branch_ccz
+ addw2 $2,%r0 # 31 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorqi.c
new file mode 100644
index 0000000..82f3f6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_iorqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x | *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bisb3 *12(%ap),*8(%ap),%r0 # 32 [c=44] *iorqi3_ccz/2
+ jeql .L2 # 34 [c=26] *branch_ccz
+ addb2 $2,%r0 # 31 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorsi.c
new file mode 100644
index 0000000..dd4490d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-iorsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_iorsi (int_t x, int_t y)
+{
+ x |= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ bisl3 8(%ap),4(%ap),%r0 # 33 [c=28] *iorsi3_ccz/2
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-mova.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mova.c
new file mode 100644
index 0000000..286025f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mova.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+extern char __attribute__ ((weak)) c;
+
+char *
+eq_mova (char *p)
+{
+ char *v;
+
+ v = &c;
+ if (v)
+ return v;
+ return p;
+}
+
+/* Expect assembly like:
+
+ movab c,%r0 # 35 [c=12] *movsym_2_ccz
+ jeql .L6 # 37 [c=26] *branch_ccz
+ ret # 43 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsym\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-movdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movdf.c
new file mode 100644
index 0000000..c83e966
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movdf.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+eq_movdf (float_t x)
+{
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movd 4(%ap),%r0 # 34 [c=24] *movdf_ccz/1
+ jeql .L2 # 36 [c=26] *branch_ccz
+ addd2 $0d2.0e+0,%r0 # 33 [c=56] *adddf3/0
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movdf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-movhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movhi.c
new file mode 100644
index 0000000..99832dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_movhi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = *x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movw *8(%ap),%r0 # 31 [c=24] *movhi_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addw2 $2,%r0 # 30 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-movqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movqi.c
new file mode 100644
index 0000000..5014b8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_movqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = *x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movb *8(%ap),%r0 # 31 [c=24] *movqi_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addb2 $2,%r0 # 30 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-movsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movsf.c
new file mode 100644
index 0000000..8907461
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movsf.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+eq_movsf (float_t x)
+{
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movf 4(%ap),%r0 # 33 [c=16] *movsf_ccz/1
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 32 [c=36] *addsf3/0
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-movsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movsi.c
new file mode 100644
index 0000000..1e65f4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-movsi.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_movsi (int_t x)
+{
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 32 [c=16] *movsi_2_ccz
+ jeql .L2 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-muldf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-muldf.c
new file mode 100644
index 0000000..7271c21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-muldf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+eq_muldf (float_t x, float_t y)
+{
+ x *= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ muld3 4(%ap),12(%ap),%r0 # 35 [c=80] *muldf3_ccz/2
+ jeql .L1 # 37 [c=26] *branch_ccz
+ addd2 $0d2.0e+0,%r0 # 34 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "muldf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulhi.c
new file mode 100644
index 0000000..d44a622
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_mulhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x * *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mulw3 *8(%ap),*12(%ap),%r0 # 33 [c=72] *mulhi3_ccz/2
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addw2 $2,%r0 # 32 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulqi.c
new file mode 100644
index 0000000..2451843
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_mulqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x * *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mulb3 *8(%ap),*12(%ap),%r0 # 33 [c=72] *mulqi3_ccz/2
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addb2 $2,%r0 # 32 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsf.c
new file mode 100644
index 0000000..824487b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+eq_mulsf (float_t x, float_t y)
+{
+ x *= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mulf3 4(%ap),8(%ap),%r0 # 34 [c=52] *mulsf3_ccz/2
+ jeql .L1 # 36 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 33 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulsf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsi.c
new file mode 100644
index 0000000..fbefa54
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-mulsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_mulsi (int_t x, int_t y)
+{
+ x *= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mull3 4(%ap),8(%ap),%r0 # 33 [c=56] *mulsi3_ccz/2
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-nothi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-nothi.c
new file mode 100644
index 0000000..79b274c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-nothi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_nothi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = ~*x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mcomw *8(%ap),%r0 # 31 [c=24] *one_cmplhi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addw2 $2,%r0 # 30 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-notqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-notqi.c
new file mode 100644
index 0000000..ae98a2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-notqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_notqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = ~*x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mcomb *8(%ap),%r0 # 31 [c=24] *one_cmplqi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addb2 $2,%r0 # 30 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-notsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-notsi.c
new file mode 100644
index 0000000..ba5b735
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-notsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_notsi (int_t x)
+{
+ x = ~x;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mcoml 4(%ap),%r0 # 32 [c=16] *one_cmplsi2_ccz
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-rotlsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-rotlsi.c
new file mode 100644
index 0000000..17c4868
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-rotlsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) ulong_t;
+typedef int __attribute__ ((mode (SI))) long_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+ulong_t
+eq_rotlsi (ulong_t x, int_t y)
+{
+ long_t v;
+
+ v = x << y | x >> 8 * sizeof (x) - y;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ rotl 8(%ap),4(%ap),%r0 # 36 [c=40] *rotlsi3_ccz
+ jeql .L1 # 38 [c=26] *branch_ccz
+ addl2 $2,%r0 # 35 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "rotlsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-rotrsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-rotrsi.c
new file mode 100644
index 0000000..ffbca23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-rotrsi.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) ulong_t;
+typedef int __attribute__ ((mode (SI))) long_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+ulong_t
+eq_rotrsi (ulong_t x, int_t y)
+{
+ long_t v;
+
+ v = x >> y | x << 8 * sizeof (x) - y;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ mnegb 8(%ap),%r0 # 37 [c=16] *negqi2
+ rotl %r0,4(%ap),%r0 # 38 [c=36] *rotrnegsi3_2_ccz
+ jeql .L1 # 40 [c=26] *branch_ccz
+ addl2 $2,%r0 # 36 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "rotrnegsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-subdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subdf.c
new file mode 100644
index 0000000..a8d3f1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subdf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+eq_subdf (float_t x, float_t y)
+{
+ x -= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subd3 12(%ap),4(%ap),%r0 # 35 [c=68] *subdf3_ccz/1
+ jeql .L1 # 37 [c=26] *branch_ccz
+ addd2 $0d2.0e+0,%r0 # 34 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subdf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-subhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subhi.c
new file mode 100644
index 0000000..f01b4b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_subhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ subw3 *12(%ap),*8(%ap),%r0 # 33 [c=64] *subhi3_ccz/1
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addw2 $2,%r0 # 32 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-subqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subqi.c
new file mode 100644
index 0000000..733e30f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_subqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ subb3 *12(%ap),*8(%ap),%r0 # 33 [c=64] *subqi3_ccz/1
+ jeql .L2 # 35 [c=26] *branch_ccz
+ addb2 $2,%r0 # 32 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-subsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subsf.c
new file mode 100644
index 0000000..34e8555
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+eq_subsf (float_t x, float_t y)
+{
+ x -= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subf3 8(%ap),4(%ap),%r0 # 34 [c=48] *subsf3_ccz/1
+ jeql .L1 # 36 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 33 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-subsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subsi.c
new file mode 100644
index 0000000..456e35a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-subsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_subsi (int_t x, int_t y)
+{
+ x -= y;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subl3 8(%ap),4(%ap),%r0 # 33 [c=48] *subsi3_ccz/1
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncdfsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncdfsf.c
new file mode 100644
index 0000000..7192d87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncdfsf.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) single_t;
+typedef float __attribute__ ((mode (DF))) double_t;
+
+single_t
+eq_truncdfsf (double_t x)
+{
+ single_t v;
+
+ v = x;
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdf 4(%ap),%r0 # 33 [c=20] *truncdfsf2_ccz
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addf2 $0f2.0e+0,%r0 # 32 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "truncdfsf\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-trunchiqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-trunchiqi.c
new file mode 100644
index 0000000..9e7a885
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-trunchiqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (HI))) int_t;
+typedef unsigned int __attribute__ ((mode (QI))) short_t;
+
+void
+eq_trunchiqi (short_t *w, int_t *x, int y)
+{
+ short_t v;
+
+ v = x[y];
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movl 12(%ap),%r0 # 33 [c=16] *movsi_2
+ cvtwb *8(%ap)[%r0],%r0 # 34 [c=28] *trunchiqi2_ccz
+ jeql .L2 # 36 [c=26] *branch_ccz
+ addb2 $2,%r0 # 32 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "trunchiqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsihi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsihi.c
new file mode 100644
index 0000000..36dd7df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsihi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+typedef unsigned int __attribute__ ((mode (HI))) short_t;
+
+void
+eq_truncsihi (short_t *w, int_t *x, int y)
+{
+ short_t v;
+
+ v = x[y];
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movl 12(%ap),%r0 # 33 [c=16] *movsi_2
+ cvtlw *8(%ap)[%r0],%r0 # 34 [c=28] *truncsihi2_ccz
+ jeql .L2 # 36 [c=26] *branch_ccz
+ addw2 $2,%r0 # 32 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "truncsihi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsiqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsiqi.c
new file mode 100644
index 0000000..a0ee4cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-truncsiqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+typedef unsigned int __attribute__ ((mode (QI))) short_t;
+
+void
+eq_truncsiqi (short_t *w, int_t *x, int y)
+{
+ short_t v;
+
+ v = x[y];
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movl 12(%ap),%r0 # 33 [c=16] *movsi_2
+ cvtlb *8(%ap)[%r0],%r0 # 34 [c=28] *truncsiqi2_ccz
+ jeql .L2 # 36 [c=26] *branch_ccz
+ addb2 $2,%r0 # 32 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "truncsiqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendhisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendhisi.c
new file mode 100644
index 0000000..2fa86dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendhisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+typedef unsigned int __attribute__ ((mode (HI))) short_t;
+
+int_t
+eq_zextendhisi (int_t x)
+{
+ x = (short_t) x;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movzwl 4(%ap),%r0 # 32 [c=20] *zero_extendhisi2_ccz
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "zero_extendhisi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqihi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqihi.c
new file mode 100644
index 0000000..16613c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqihi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (HI))) int_t;
+typedef unsigned int __attribute__ ((mode (QI))) short_t;
+
+void
+eq_zextendqihi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = (short_t) *x;
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movzbw *8(%ap),%r0 # 31 [c=28] *zero_extendqihi2_ccz
+ jeql .L2 # 33 [c=26] *branch_ccz
+ addw2 $2,%r0 # 30 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "zero_extendqihi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqisi.c
new file mode 100644
index 0000000..bb75f73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-eq-zextendqisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+typedef unsigned int __attribute__ ((mode (QI))) short_t;
+
+int_t
+eq_zextendqisi (int_t x)
+{
+ x = (short_t) x;
+ if (x == 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movzbl 4(%ap),%r0 # 32 [c=20] *zero_extendqisi2_ccz
+ jeql .L1 # 34 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "zero_extendqisi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-adddf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-adddf.c
new file mode 100644
index 0000000..383d51d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-adddf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+le_adddf (float_t x, float_t y)
+{
+ x += y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addd3 4(%ap),12(%ap),%r0 # 29 [c=68] *adddf3_ccnz/2
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "adddf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-addhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-addhi.c
new file mode 100644
index 0000000..19cc621
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-addhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_addhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x + *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ addw3 *8(%ap),*12(%ap),%r0 # 29 [c=64] *addhi3_ccnz
+ jleq .L2 # 31 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 28 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-addqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-addqi.c
new file mode 100644
index 0000000..291beb0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-addqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_addqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x + *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ addb3 *8(%ap),*12(%ap),%r0 # 29 [c=64] *addqi3_ccnz
+ jleq .L2 # 31 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 28 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-addsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-addsf.c
new file mode 100644
index 0000000..e4596fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-addsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+le_addsf (float_t x, float_t y)
+{
+ x += y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addf3 4(%ap),8(%ap),%r0 # 28 [c=48] *addsf3_ccnz/2
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-addsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-addsi.c
new file mode 100644
index 0000000..254b30c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-addsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_addsi (int_t x, int_t y)
+{
+ x += y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addl3 4(%ap),8(%ap),%r0 # 29 [c=48] *addsi3_ccnz
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-andhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-andhi.c
new file mode 100644
index 0000000..ddf04d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-andhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_andhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & ~*y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bicw3 *12(%ap),*8(%ap),%r0 # 30 [c=44] *andhi3_2_ccnz/1
+ jleq .L2 # 32 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 29 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-andqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-andqi.c
new file mode 100644
index 0000000..bd781dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-andqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_andqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & ~*y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bicb3 *12(%ap),*8(%ap),%r0 # 30 [c=44] *andqi3_2_ccnz/1
+ jleq .L2 # 32 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 29 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-andsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-andsi.c
new file mode 100644
index 0000000..81fd7ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-andsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_andsi (int_t x, int_t y)
+{
+ x &= ~y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ bicl3 8(%ap),4(%ap),%r0 # 31 [c=28] *andsi3_2_ccnz/1
+ jleq .L1 # 33 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 30 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-ashlsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-ashlsi.c
new file mode 100644
index 0000000..2b67742
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-ashlsi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+le_ashlsi (int_t x, short_t y)
+{
+ x <<= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ ashl 8(%ap),4(%ap),%r0 # 31 [c=56] *ashlsi3_ccnz
+ jleq .L1 # 33 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 30 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ashlsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-ashrsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-ashrsi.c
new file mode 100644
index 0000000..c4d9f28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-ashrsi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+le_ashrsi (int_t x, short_t y)
+{
+ x >>= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mnegb 8(%ap),%r0 # 32 [c=16] *negqi2
+ ashl %r0,4(%ap),%r0 # 33 [c=52] *ashlnegsi3_2_ccnz
+ jleq .L1 # 35 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ashlnegsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-divdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-divdf.c
new file mode 100644
index 0000000..62b419c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-divdf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+le_divdf (float_t x, float_t y)
+{
+ x /= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divd3 12(%ap),4(%ap),%r0 # 29 [c=112] *divdf3_ccnz/1
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divdf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-divhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-divhi.c
new file mode 100644
index 0000000..68ee484
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-divhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI), vector_size (2))) int_t;
+
+void
+le_divhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x / *y;
+ if (v[0] <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ divw3 *12(%ap),*8(%ap),%r0 # 34 [c=76] *divhi3_ccnz/1
+ jleq .L2 # 36 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 33 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-divqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-divqi.c
new file mode 100644
index 0000000..e0b0cd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-divqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI), vector_size (1))) int_t;
+
+void
+le_divqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x / *y;
+ if (v[0] <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ divb3 *12(%ap),*8(%ap),%r0 # 34 [c=76] *divqi3_ccnz/1
+ jleq .L2 # 36 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 33 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-divsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-divsf.c
new file mode 100644
index 0000000..b55b36e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-divsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+le_divsf (float_t x, float_t y)
+{
+ x /= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divf3 8(%ap),4(%ap),%r0 # 28 [c=60] *divsf3_ccnz/1
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divsf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-divsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-divsi.c
new file mode 100644
index 0000000..6a45a38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-divsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_divsi (int_t x, int_t y)
+{
+ x /= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divl3 8(%ap),4(%ap),%r0 # 29 [c=60] *divsi3_ccnz/1
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-extendhisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-extendhisi.c
new file mode 100644
index 0000000..693c752f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-extendhisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (HI))) short_t;
+
+int_t
+le_extendhisi (int_t x)
+{
+ x = (short_t) x;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ cvtwl 4(%ap),%r0 # 29 [c=20] *extendhisi2_ccnz
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extendhisi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-extendqisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-extendqisi.c
new file mode 100644
index 0000000..4965bcf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-extendqisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+le_extendqisi (int_t x)
+{
+ x = (short_t) x;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ cvtbl 4(%ap),%r0 # 29 [c=20] *extendqisi2_ccnz
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extendqisi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-extvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-extvsi.c
new file mode 100644
index 0000000..641c8f0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-extvsi.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+le_extvsi (bit_t x)
+{
+ int_t v;
+
+ v = x.i;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ extv $7,$18,4(%ap),%r0 # 28 [c=68] *extv_non_const_2_ccnz
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-extzvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-extzvsi.c
new file mode 100644
index 0000000..18dd7ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-extzvsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+uint_t
+le_extzvsi (uint_t x, int_t y)
+{
+ int_t v;
+
+ v = x >> y;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ subb3 8(%ap),$32,%r0 # 31 [c=40] *subqi3/1
+ extzv 8(%ap),%r0,4(%ap),%r0 # 32 [c=76] *extzv_non_const_2_ccnz
+ jleq .L1 # 34 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 30 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extzv\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfhi.c
new file mode 100644
index 0000000..ea649c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfhi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_fixdfhi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdw 8(%ap),%r0 # 27 [c=36] *fix_truncdfhi2_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfqi.c
new file mode 100644
index 0000000..a53e936
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfqi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_fixdfqi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdb 8(%ap),%r0 # 27 [c=36] *fix_truncdfqi2_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfsi.c
new file mode 100644
index 0000000..bcf5f36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixdfsi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_fixdfsi (float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdl 4(%ap),%r0 # 28 [c=36] *fix_truncdfsi2_ccnz
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfhi.c
new file mode 100644
index 0000000..2301500
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfhi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_fixsfhi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfw 8(%ap),%r0 # 27 [c=36] *fix_truncsfhi2_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfqi.c
new file mode 100644
index 0000000..34a4783
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfqi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_fixsfqi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfb 8(%ap),%r0 # 27 [c=36] *fix_truncsfqi2_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfsi.c
new file mode 100644
index 0000000..39735af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-fixsfsi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_fixsfsi (float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfl 4(%ap),%r0 # 28 [c=36] *fix_truncsfsi2_ccnz
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-floatsisf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-floatsisf.c
new file mode 100644
index 0000000..bab7101c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-floatsisf.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+float_t
+le_floatsisf (int_t x)
+{
+ float_t v;
+
+ v = x;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtlf 4(%ap),%r0 # 27 [c=32] *floatsisf2_ccnz
+ jleq .L1 # 29 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 26 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "floatsisf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-insvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-insvsi.c
new file mode 100644
index 0000000..26c368b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-insvsi.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef union
+ {
+ int_t i;
+ struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ } b;
+ }
+bit_t;
+
+int
+le_insvsi (bit_t x, int_t y)
+{
+ int_t v;
+
+ v = x.b.i;
+ x.b.i = y;
+ if (v <= 0)
+ return x.i;
+ else
+ return x.i + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 37 [c=16] *movsi_2
+ extv $7,$18,%r0,%r1 # 38 [c=60] *extv_non_const_2_ccnz
+ insv 8(%ap),$7,$18,%r0 # 8 [c=16] *insv_2
+ jleq .L1 # 40 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 36 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "extv.*insv.*branch" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-iorhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-iorhi.c
new file mode 100644
index 0000000..26a4d76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-iorhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_iorhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x | *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bisw3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *iorhi3_ccnz/2
+ jleq .L2 # 30 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 27 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-iorqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-iorqi.c
new file mode 100644
index 0000000..fbb97b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-iorqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_iorqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x | *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bisb3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *iorqi3_ccnz/2
+ jleq .L2 # 30 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 27 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-iorsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-iorsi.c
new file mode 100644
index 0000000..4cf50fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-iorsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_iorsi (int_t x, int_t y)
+{
+ x |= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ bisl3 8(%ap),4(%ap),%r0 # 29 [c=28] *iorsi3_ccnz/2
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-movdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-movdf.c
new file mode 100644
index 0000000..acbaa2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-movdf.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+le_movdf (float_t x)
+{
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movd 4(%ap),%r0 # 34 [c=24] *movdf_ccnz/1
+ jleq .L1 # 36 [c=26] *branch_ccnz
+ addd2 $0d2.0e+0,%r0 # 33 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movdf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-movhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-movhi.c
new file mode 100644
index 0000000..3e99f87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-movhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_movhi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = *x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movw *8(%ap),%r0 # 27 [c=24] *movhi_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-movqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-movqi.c
new file mode 100644
index 0000000..8c73a82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-movqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_movqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = *x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movb *8(%ap),%r0 # 27 [c=24] *movqi_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-movsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-movsf.c
new file mode 100644
index 0000000..71a70b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-movsf.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+le_movsf (float_t x)
+{
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movf 4(%ap),%r0 # 33 [c=16] *movsf_ccnz/1
+ jleq .L1 # 35 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 32 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-movsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-movsi.c
new file mode 100644
index 0000000..2203f8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-movsi.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_movsi (int_t x)
+{
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 34 [c=16] *movsi_2_ccnz
+ jleq .L1 # 36 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 33 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-muldf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-muldf.c
new file mode 100644
index 0000000..ed3193d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-muldf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+le_muldf (float_t x, float_t y)
+{
+ x *= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ muld3 4(%ap),12(%ap),%r0 # 29 [c=80] *muldf3_ccnz/2
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "muldf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-mulhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulhi.c
new file mode 100644
index 0000000..426a469
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_mulhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x * *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mulw3 *8(%ap),*12(%ap),%r0 # 29 [c=72] *mulhi3_ccnz/2
+ jleq .L2 # 31 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 28 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-mulqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulqi.c
new file mode 100644
index 0000000..ca3bb48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_mulqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x * *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mulb3 *8(%ap),*12(%ap),%r0 # 29 [c=72] *mulqi3_ccnz/2
+ jleq .L2 # 31 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 28 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-mulsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulsf.c
new file mode 100644
index 0000000..0d3ac37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+le_mulsf (float_t x, float_t y)
+{
+ x *= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mulf3 4(%ap),8(%ap),%r0 # 28 [c=52] *mulsf3_ccnz/2
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulsf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-mulsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulsi.c
new file mode 100644
index 0000000..de72158
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-mulsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_mulsi (int_t x, int_t y)
+{
+ x *= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mull3 4(%ap),8(%ap),%r0 # 29 [c=56] *mulsi3_ccnz/2
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-nothi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-nothi.c
new file mode 100644
index 0000000..6884a78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-nothi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_nothi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = ~*x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mcomw *8(%ap),%r0 # 27 [c=24] *one_cmplhi2_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-notqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-notqi.c
new file mode 100644
index 0000000..60a9e61
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-notqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_notqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = ~*x;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mcomb *8(%ap),%r0 # 27 [c=24] *one_cmplqi2_ccnz
+ jleq .L2 # 29 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-notsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-notsi.c
new file mode 100644
index 0000000..938a6b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-notsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_notsi (int_t x)
+{
+ x = ~x;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mcoml 4(%ap),%r0 # 28 [c=16] *one_cmplsi2_ccnz
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-rotlsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-rotlsi.c
new file mode 100644
index 0000000..9e01429
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-rotlsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) ulong_t;
+typedef int __attribute__ ((mode (SI))) long_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+ulong_t
+le_rotlsi (ulong_t x, int_t y)
+{
+ long_t v;
+
+ v = x << y | x >> 8 * sizeof (x) - y;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ rotl 8(%ap),4(%ap),%r0 # 32 [c=40] *rotlsi3_ccnz
+ jleq .L1 # 34 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "rotlsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-rotrsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-rotrsi.c
new file mode 100644
index 0000000..4fe533b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-rotrsi.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) ulong_t;
+typedef int __attribute__ ((mode (SI))) long_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+ulong_t
+le_rotrsi (ulong_t x, int_t y)
+{
+ long_t v;
+
+ v = x >> y | x << 8 * sizeof (x) - y;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ mnegb 8(%ap),%r0 # 33 [c=16] *negqi2
+ rotl %r0,4(%ap),%r0 # 34 [c=36] *rotrnegsi3_2_ccnz
+ jleq .L1 # 36 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "rotrnegsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-subdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-subdf.c
new file mode 100644
index 0000000..0456cd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-subdf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+le_subdf (float_t x, float_t y)
+{
+ x -= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subd3 12(%ap),4(%ap),%r0 # 29 [c=68] *subdf3_ccnz/1
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subdf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-subhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-subhi.c
new file mode 100644
index 0000000..4391b76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-subhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_subhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ subw3 *12(%ap),*8(%ap),%r0 # 29 [c=64] *subhi3_ccnz/1
+ jleq .L2 # 31 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 28 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-subqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-subqi.c
new file mode 100644
index 0000000..f725be9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-subqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_subqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ subb3 *12(%ap),*8(%ap),%r0 # 29 [c=64] *subqi3_ccnz/1
+ jleq .L2 # 31 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 28 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-subsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-subsf.c
new file mode 100644
index 0000000..77a9bf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-subsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+le_subsf (float_t x, float_t y)
+{
+ x -= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subf3 8(%ap),4(%ap),%r0 # 28 [c=48] *subsf3_ccnz/1
+ jleq .L1 # 30 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-subsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-subsi.c
new file mode 100644
index 0000000..db64ffc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-subsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_subsi (int_t x, int_t y)
+{
+ x -= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subl3 8(%ap),4(%ap),%r0 # 29 [c=48] *subsi3_ccnz/1
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-truncdfsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-truncdfsf.c
new file mode 100644
index 0000000..6e7673d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-truncdfsf.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) single_t;
+typedef float __attribute__ ((mode (DF))) double_t;
+
+single_t
+le_truncdfsf (double_t x)
+{
+ single_t v;
+
+ v = x;
+ if (v <= 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdf 4(%ap),%r0 # 27 [c=20] *truncdfsf2_ccnz
+ jleq .L1 # 29 [c=26] *branch_ccnz
+ addf2 $0f2.0e+0,%r0 # 26 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "truncdfsf\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-xorhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-xorhi.c
new file mode 100644
index 0000000..e65eed8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-xorhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_xorhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x ^ *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ xorw3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *xorhi3_ccnz/2
+ jleq .L2 # 30 [c=26] *branch_ccnz
+ addw2 $2,%r0 # 27 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "xorhi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-xorqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-xorqi.c
new file mode 100644
index 0000000..ca8d5fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-xorqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_xorqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x ^ *y;
+ if (v <= 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ xorb3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *xorqi3_ccnz/2
+ jleq .L2 # 30 [c=26] *branch_ccnz
+ addb2 $2,%r0 # 27 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "xorqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-le-xorsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-le-xorsi.c
new file mode 100644
index 0000000..3de63ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-le-xorsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_xorsi (int_t x, int_t y)
+{
+ x ^= y;
+ if (x <= 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ xorl3 8(%ap),4(%ap),%r0 # 29 [c=28] *xorsi3_ccnz/2
+ jleq .L1 # 31 [c=26] *branch_ccnz
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "xorsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-leu-subhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-leu-subhi.c
new file mode 100644
index 0000000..5f3e372
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-leu-subhi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (HI))) int_t;
+
+void
+leu_subhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (*x <= *y)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movw *8(%ap),%r2 # 28 [c=24] *movhi
+ movw *12(%ap),%r1 # 29 [c=24] *movhi
+ subw3 %r1,%r2,%r0 # 30 [c=32] *subhi3_cc/1
+ jlequ .L2 # 32 [c=26] *branch_cc
+ addw2 $2,%r0 # 27 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subhi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-leu-subqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-leu-subqi.c
new file mode 100644
index 0000000..97ef2a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-leu-subqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (QI))) int_t;
+
+void
+leu_subqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (*x <= *y)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movb *8(%ap),%r2 # 28 [c=24] *movqi
+ movb *12(%ap),%r1 # 29 [c=24] *movqi
+ subb3 %r1,%r2,%r0 # 30 [c=32] *subqi3_cc/1
+ jlequ .L2 # 32 [c=26] *branch_cc
+ addb2 $2,%r0 # 27 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subqi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-leu-subsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-leu-subsi.c
new file mode 100644
index 0000000..9402fab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-leu-subsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+
+int_t
+leu_subsi (int_t x, int_t y)
+{
+ int_t v;
+
+ v = x - y;
+ if (x <= y)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r2 # 27 [c=16] *movsi_2
+ movl 8(%ap),%r1 # 28 [c=16] *movsi_2
+ subl3 %r1,%r2,%r0 # 29 [c=32] *subsi3_cc/1
+ jlequ .L1 # 31 [c=26] *branch_cc
+ addl2 $2,%r0 # 26 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-adddf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-adddf.c
new file mode 100644
index 0000000..6e3718d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-adddf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+lt_adddf (float_t x, float_t y)
+{
+ x += y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addd3 4(%ap),12(%ap),%r0 # 29 [c=68] *adddf3_ccn/2
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "adddf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-addhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addhi.c
new file mode 100644
index 0000000..a93675a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_addhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x + *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ addw3 *8(%ap),*12(%ap),%r0 # 29 [c=64] *addhi3_ccn
+ jlss .L2 # 31 [c=26] *branch_ccn
+ addw2 $2,%r0 # 28 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-addqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addqi.c
new file mode 100644
index 0000000..32a1328
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_addqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x + *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ addb3 *8(%ap),*12(%ap),%r0 # 29 [c=64] *addqi3_ccn
+ jlss .L2 # 31 [c=26] *branch_ccn
+ addb2 $2,%r0 # 28 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-addsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addsf.c
new file mode 100644
index 0000000..19c0b68
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+lt_addsf (float_t x, float_t y)
+{
+ x += y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addf3 4(%ap),8(%ap),%r0 # 28 [c=48] *addsf3_ccn/2
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-addsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addsi.c
new file mode 100644
index 0000000..1bb59d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-addsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_addsi (int_t x, int_t y)
+{
+ x += y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ addl3 4(%ap),8(%ap),%r0 # 29 [c=48] *addsi3_ccn
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-andhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-andhi.c
new file mode 100644
index 0000000..f725931
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-andhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_andhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & ~*y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bicw3 *12(%ap),*8(%ap),%r0 # 30 [c=44] *andhi3_2_ccn/1
+ jlss .L2 # 32 [c=26] *branch_ccn
+ addw2 $2,%r0 # 29 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-andqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-andqi.c
new file mode 100644
index 0000000..afae635
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-andqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_andqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & ~*y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bicb3 *12(%ap),*8(%ap),%r0 # 30 [c=44] *andqi3_2_ccn/1
+ jlss .L2 # 32 [c=26] *branch_ccn
+ addb2 $2,%r0 # 29 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-andsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-andsi.c
new file mode 100644
index 0000000..5a86ddb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-andsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_andsi (int_t x, int_t y)
+{
+ x &= ~y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ bicl3 8(%ap),4(%ap),%r0 # 31 [c=28] *andsi3_2_ccn/1
+ jlss .L1 # 33 [c=26] *branch_ccn
+ addl2 $2,%r0 # 30 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "andsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-ashlsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-ashlsi.c
new file mode 100644
index 0000000..0c85893
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-ashlsi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+lt_ashlsi (int_t x, short_t y)
+{
+ x <<= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ ashl 8(%ap),4(%ap),%r0 # 31 [c=56] *ashlsi3_ccn
+ jlss .L1 # 33 [c=26] *branch_ccn
+ addl2 $2,%r0 # 30 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ashlsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-ashrsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-ashrsi.c
new file mode 100644
index 0000000..977f32c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-ashrsi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+lt_ashrsi (int_t x, short_t y)
+{
+ x >>= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mnegb 8(%ap),%r0 # 32 [c=16] *negqi2
+ ashl %r0,4(%ap),%r0 # 33 [c=52] *ashlnegsi3_2_ccn
+ jlss .L1 # 35 [c=26] *branch_ccn
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ashlnegsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-divdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divdf.c
new file mode 100644
index 0000000..ddcb8c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divdf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+lt_divdf (float_t x, float_t y)
+{
+ x /= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divd3 12(%ap),4(%ap),%r0 # 29 [c=112] *divdf3_ccn/1
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divdf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-divhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divhi.c
new file mode 100644
index 0000000..23bbf42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI), vector_size (2))) int_t;
+
+void
+lt_divhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x / *y;
+ if (v[0] < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ divw3 *12(%ap),*8(%ap),%r0 # 34 [c=76] *divhi3_ccn/1
+ jlss .L2 # 36 [c=26] *branch_ccn
+ addw2 $2,%r0 # 33 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-divqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divqi.c
new file mode 100644
index 0000000..5401b6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI), vector_size (1))) int_t;
+
+void
+lt_divqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x / *y;
+ if (v[0] < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ divb3 *12(%ap),*8(%ap),%r0 # 34 [c=76] *divqi3_ccn/1
+ jlss .L2 # 36 [c=26] *branch_ccn
+ addb2 $2,%r0 # 33 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-divsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divsf.c
new file mode 100644
index 0000000..89d5930
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+lt_divsf (float_t x, float_t y)
+{
+ x /= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divf3 8(%ap),4(%ap),%r0 # 28 [c=60] *divsf3_ccn/1
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divsf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-divsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divsi.c
new file mode 100644
index 0000000..5c50635
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-divsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_divsi (int_t x, int_t y)
+{
+ x /= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ divl3 8(%ap),4(%ap),%r0 # 29 [c=60] *divsi3_ccn/1
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "divsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-extendhisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extendhisi.c
new file mode 100644
index 0000000..5dcc89a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extendhisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (HI))) short_t;
+
+int_t
+lt_extendhisi (int_t x)
+{
+ x = (short_t) x;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ cvtwl 4(%ap),%r0 # 29 [c=20] *extendhisi2_ccn
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extendhisi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-extendqisi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extendqisi.c
new file mode 100644
index 0000000..9ec5a41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extendqisi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+typedef int __attribute__ ((mode (QI))) short_t;
+
+int_t
+lt_extendqisi (int_t x)
+{
+ x = (short_t) x;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ cvtbl 4(%ap),%r0 # 29 [c=20] *extendqisi2_ccn
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extendqisi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-extvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extvsi.c
new file mode 100644
index 0000000..a10435b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extvsi.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+lt_extvsi (bit_t x)
+{
+ int_t v;
+
+ v = x.i;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ extv $7,$18,4(%ap),%r0 # 28 [c=68] *extv_non_const_2_ccn
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-extzvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extzvsi.c
new file mode 100644
index 0000000..e019d74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-extzvsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+uint_t
+lt_extzvsi (uint_t x, int_t y)
+{
+ int_t v;
+
+ v = x >> y;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ subb3 8(%ap),$32,%r0 # 31 [c=40] *subqi3/1
+ extzv 8(%ap),%r0,4(%ap),%r0 # 32 [c=76] *extzv_non_const_2_ccn
+ jlss .L1 # 34 [c=26] *branch_ccn
+ addl2 $2,%r0 # 30 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extzv\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfhi.c
new file mode 100644
index 0000000..5d63a22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfhi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_fixdfhi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdw 8(%ap),%r0 # 27 [c=36] *fix_truncdfhi2_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfqi.c
new file mode 100644
index 0000000..d161655
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfqi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_fixdfqi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdb 8(%ap),%r0 # 27 [c=36] *fix_truncdfqi2_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfsi.c
new file mode 100644
index 0000000..b07d1de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixdfsi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_fixdfsi (float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdl 4(%ap),%r0 # 28 [c=36] *fix_truncdfsi2_ccn
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncdfsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfhi.c
new file mode 100644
index 0000000..42c8d74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfhi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_fixsfhi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfw 8(%ap),%r0 # 27 [c=36] *fix_truncsfhi2_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfqi.c
new file mode 100644
index 0000000..49327ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfqi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_fixsfqi (int_t *w, float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfb 8(%ap),%r0 # 27 [c=36] *fix_truncsfqi2_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfsi.c
new file mode 100644
index 0000000..3d17291
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-fixsfsi.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_fixsfsi (float_t x)
+{
+ int_t v;
+
+ v = x;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtfl 4(%ap),%r0 # 28 [c=36] *fix_truncsfsi2_ccn
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "fix_truncsfsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-floatsisf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-floatsisf.c
new file mode 100644
index 0000000..cefc71e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-floatsisf.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+float_t
+lt_floatsisf (int_t x)
+{
+ float_t v;
+
+ v = x;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtlf 4(%ap),%r0 # 27 [c=32] *floatsisf2_ccn
+ jlss .L1 # 29 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 26 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "floatsisf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-insvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-insvsi.c
new file mode 100644
index 0000000..52f97ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-insvsi.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef union
+ {
+ int_t i;
+ struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ } b;
+ }
+bit_t;
+
+int
+lt_insvsi (bit_t x, int_t y)
+{
+ int_t v;
+
+ v = x.b.i;
+ x.b.i = y;
+ if (v < 0)
+ return x.i;
+ else
+ return x.i + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 37 [c=16] *movsi_2
+ extv $7,$18,%r0,%r1 # 38 [c=60] *extv_non_const_2_ccn
+ insv 8(%ap),$7,$18,%r0 # 8 [c=16] *insv_2
+ jlss .L1 # 40 [c=26] *branch_ccn
+ addl2 $2,%r0 # 36 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "extv.*insv.*branch" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorhi.c
new file mode 100644
index 0000000..edd91e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_iorhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x | *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bisw3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *iorhi3_ccn/2
+ jlss .L2 # 30 [c=26] *branch_ccn
+ addw2 $2,%r0 # 27 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorqi.c
new file mode 100644
index 0000000..82a9e04
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_iorqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x | *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ bisb3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *iorqi3_ccn/2
+ jlss .L2 # 30 [c=26] *branch_ccn
+ addb2 $2,%r0 # 27 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorsi.c
new file mode 100644
index 0000000..1246686
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-iorsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_iorsi (int_t x, int_t y)
+{
+ x |= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ bisl3 8(%ap),4(%ap),%r0 # 29 [c=28] *iorsi3_ccn/2
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "iorsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-movdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movdf.c
new file mode 100644
index 0000000..02b4c5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movdf.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+lt_movdf (float_t x)
+{
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movd 4(%ap),%r0 # 34 [c=24] *movdf_ccn/1
+ jlss .L1 # 36 [c=26] *branch_ccn
+ addd2 $0d2.0e+0,%r0 # 33 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movdf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-movhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movhi.c
new file mode 100644
index 0000000..51ce5b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_movhi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = *x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movw *8(%ap),%r0 # 27 [c=24] *movhi_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-movqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movqi.c
new file mode 100644
index 0000000..fb5450c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_movqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = *x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movb *8(%ap),%r0 # 27 [c=24] *movqi_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-movsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movsf.c
new file mode 100644
index 0000000..1669f16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movsf.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+lt_movsf (float_t x)
+{
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movf 4(%ap),%r0 # 33 [c=16] *movsf_ccn/1
+ jlss .L1 # 35 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 32 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-movsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movsi.c
new file mode 100644
index 0000000..b4cd073
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-movsi.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_movsi (int_t x)
+{
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 34 [c=16] *movsi_2_ccn
+ jlss .L1 # 36 [c=26] *branch_ccn
+ addl2 $2,%r0 # 33 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "movsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-muldf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-muldf.c
new file mode 100644
index 0000000..1f9279b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-muldf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+lt_muldf (float_t x, float_t y)
+{
+ x *= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ muld3 4(%ap),12(%ap),%r0 # 29 [c=80] *muldf3_ccn/2
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "muldf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulhi.c
new file mode 100644
index 0000000..29a77e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_mulhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x * *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mulw3 *8(%ap),*12(%ap),%r0 # 29 [c=72] *mulhi3_ccn/2
+ jlss .L2 # 31 [c=26] *branch_ccn
+ addw2 $2,%r0 # 28 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulqi.c
new file mode 100644
index 0000000..844456e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_mulqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x * *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mulb3 *8(%ap),*12(%ap),%r0 # 29 [c=72] *mulqi3_ccn/2
+ jlss .L2 # 31 [c=26] *branch_ccn
+ addb2 $2,%r0 # 28 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsf.c
new file mode 100644
index 0000000..ea1c083
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+lt_mulsf (float_t x, float_t y)
+{
+ x *= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mulf3 4(%ap),8(%ap),%r0 # 28 [c=52] *mulsf3_ccn/2
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulsf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsi.c
new file mode 100644
index 0000000..5f46c8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-mulsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_mulsi (int_t x, int_t y)
+{
+ x *= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mull3 4(%ap),8(%ap),%r0 # 29 [c=56] *mulsi3_ccn/2
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "mulsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-nothi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-nothi.c
new file mode 100644
index 0000000..59d1d9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-nothi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_nothi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = ~*x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mcomw *8(%ap),%r0 # 27 [c=24] *one_cmplhi2_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addw2 $2,%r0 # 26 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-notqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-notqi.c
new file mode 100644
index 0000000..7a2ef96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-notqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_notqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = ~*x;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ mcomb *8(%ap),%r0 # 27 [c=24] *one_cmplqi2_ccn
+ jlss .L2 # 29 [c=26] *branch_ccn
+ addb2 $2,%r0 # 26 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-notsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-notsi.c
new file mode 100644
index 0000000..c3586b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-notsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_notsi (int_t x)
+{
+ x = ~x;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ mcoml 4(%ap),%r0 # 28 [c=16] *one_cmplsi2_ccn
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addl2 $2,%r0 # 27 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "one_cmplsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-rotlsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-rotlsi.c
new file mode 100644
index 0000000..7f5c89d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-rotlsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) ulong_t;
+typedef int __attribute__ ((mode (SI))) long_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+ulong_t
+lt_rotlsi (ulong_t x, int_t y)
+{
+ long_t v;
+
+ v = x << y | x >> 8 * sizeof (x) - y;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ rotl 8(%ap),4(%ap),%r0 # 32 [c=40] *rotlsi3_ccn
+ jlss .L1 # 34 [c=26] *branch_ccn
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "rotlsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-rotrsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-rotrsi.c
new file mode 100644
index 0000000..6c9daf4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-rotrsi.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) ulong_t;
+typedef int __attribute__ ((mode (SI))) long_t;
+typedef int __attribute__ ((mode (QI))) int_t;
+
+ulong_t
+lt_rotrsi (ulong_t x, int_t y)
+{
+ long_t v;
+
+ v = x >> y | x << 8 * sizeof (x) - y;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ mnegb 8(%ap),%r0 # 33 [c=16] *negqi2
+ rotl %r0,4(%ap),%r0 # 34 [c=36] *rotrnegsi3_2_ccn
+ jlss .L1 # 36 [c=26] *branch_ccn
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "rotrnegsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-subdf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subdf.c
new file mode 100644
index 0000000..fb7bb1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subdf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (DF))) float_t;
+
+float_t
+lt_subdf (float_t x, float_t y)
+{
+ x -= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subd3 12(%ap),4(%ap),%r0 # 29 [c=68] *subdf3_ccn/1
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addd2 $0d2.0e+0,%r0 # 28 [c=56] *adddf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subdf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-subhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subhi.c
new file mode 100644
index 0000000..d06af83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_subhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ subw3 *12(%ap),*8(%ap),%r0 # 29 [c=64] *subhi3_ccn/1
+ jlss .L2 # 31 [c=26] *branch_ccn
+ addw2 $2,%r0 # 28 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-subqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subqi.c
new file mode 100644
index 0000000..254ad71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_subqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ subb3 *12(%ap),*8(%ap),%r0 # 29 [c=64] *subqi3_ccn/1
+ jlss .L2 # 31 [c=26] *branch_ccn
+ addb2 $2,%r0 # 28 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-subsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subsf.c
new file mode 100644
index 0000000..26181d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subsf.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) float_t;
+
+float_t
+lt_subsf (float_t x, float_t y)
+{
+ x -= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subf3 8(%ap),4(%ap),%r0 # 28 [c=48] *subsf3_ccn/1
+ jlss .L1 # 30 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 27 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-subsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subsi.c
new file mode 100644
index 0000000..6e98e4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-subsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_subsi (int_t x, int_t y)
+{
+ x -= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ subl3 8(%ap),4(%ap),%r0 # 29 [c=48] *subsi3_ccn/1
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-truncdfsf.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-truncdfsf.c
new file mode 100644
index 0000000..98fac66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-truncdfsf.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef float __attribute__ ((mode (SF))) single_t;
+typedef float __attribute__ ((mode (DF))) double_t;
+
+single_t
+lt_truncdfsf (double_t x)
+{
+ single_t v;
+
+ v = x;
+ if (v < 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtdf 4(%ap),%r0 # 27 [c=20] *truncdfsf2_ccn
+ jlss .L1 # 29 [c=26] *branch_ccn
+ addf2 $0f2.0e+0,%r0 # 26 [c=36] *addsf3/0
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "truncdfsf\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorhi.c
new file mode 100644
index 0000000..be36e0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorhi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+lt_xorhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x ^ *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ xorw3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *xorhi3_ccn/2
+ jlss .L2 # 30 [c=26] *branch_ccn
+ addw2 $2,%r0 # 27 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "xorhi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorqi.c
new file mode 100644
index 0000000..51b05e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorqi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_xorqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x ^ *y;
+ if (v < 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ xorb3 *12(%ap),*8(%ap),%r0 # 28 [c=44] *xorqi3_ccn/2
+ jlss .L2 # 30 [c=26] *branch_ccn
+ addb2 $2,%r0 # 27 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "xorqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorsi.c
new file mode 100644
index 0000000..439e36d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-lt-xorsi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_xorsi (int_t x, int_t y)
+{
+ x ^= y;
+ if (x < 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ xorl3 8(%ap),4(%ap),%r0 # 29 [c=28] *xorsi3_ccn/2
+ jlss .L1 # 31 [c=26] *branch_ccn
+ addl2 $2,%r0 # 28 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "xorsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subhi.c b/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subhi.c
new file mode 100644
index 0000000..7965322
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subhi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (HI))) int_t;
+
+void
+ltu_subhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (*x < *y)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movw *8(%ap),%r2 # 28 [c=24] *movhi
+ movw *12(%ap),%r1 # 29 [c=24] *movhi
+ subw3 %r1,%r2,%r0 # 30 [c=32] *subhi3_cc/1
+ jlssu .L2 # 32 [c=26] *branch_cc
+ addw2 $2,%r0 # 27 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subhi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subqi.c b/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subqi.c
new file mode 100644
index 0000000..3ba1d0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (QI))) int_t;
+
+void
+ltu_subqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x - *y;
+ if (*x < *y)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movb *8(%ap),%r2 # 28 [c=24] *movqi
+ movb *12(%ap),%r1 # 29 [c=24] *movqi
+ subb3 %r1,%r2,%r0 # 30 [c=32] *subqi3_cc/1
+ jlssu .L2 # 32 [c=26] *branch_cc
+ addb2 $2,%r0 # 27 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subqi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subsi.c
new file mode 100644
index 0000000..542ff80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-ltu-subsi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+
+int_t
+ltu_subsi (int_t x, int_t y)
+{
+ int_t v;
+
+ v = x - y;
+ if (x < y)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r2 # 27 [c=16] *movsi_2
+ movl 8(%ap),%r1 # 28 [c=16] *movsi_2
+ subl3 %r1,%r2,%r0 # 29 [c=32] *subsi3_cc/1
+ jlssu .L1 # 31 [c=26] *branch_cc
+ addl2 $2,%r0 # 26 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 1 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-xx-addsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-xx-addsi.c
new file mode 100644
index 0000000..033b119
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-xx-addsi.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+xx_addsi (int_t x, int_t y)
+{
+ x += y;
+ if (x == 0)
+ return x;
+ else if (x >= 0)
+ return x + 2;
+ else
+ return x - 3;
+}
+
+/* Expect assembly like:
+
+ addl3 4(%ap),8(%ap),%r0 # 47 [c=48] *addsi3_ccnz
+ jeql .L1 # 49 [c=26] *branch_ccz
+ jlss .L3 # 46 [c=26] *branch_ccn
+ addl2 $2,%r0 # 44 [c=32] *addsi3
+ ret # 39 [c=0] return
+.L3:
+ subl2 $3,%r0 # 43 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 2 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "addsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-xx-insvsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-xx-insvsi.c
new file mode 100644
index 0000000..8f3e4ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-xx-insvsi.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef union
+ {
+ int_t i;
+ struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ } b;
+ }
+bit_t;
+
+int
+xx_insvsi (bit_t x, int_t y)
+{
+ int_t v;
+
+ v = x.b.i;
+ x.b.i = y;
+ if (v == 0)
+ return x.i;
+ else if (v >= 0)
+ return x.i + 2;
+ else
+ return x.i - 3;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0 # 50 [c=16] *movsi_2
+ extv $7,$18,%r0,%r1 # 51 [c=60] *extv_non_const_2_ccnz
+ insv 8(%ap),$7,$18,%r0 # 8 [c=16] *insv_2
+ jeql .L1 # 53 [c=26] *branch_ccz
+ jlss .L4 # 49 [c=26] *branch_ccn
+ addl2 $2,%r0 # 47 [c=32] *addsi3
+ ret # 42 [c=0] return
+.L4:
+ subl2 $3,%r0 # 46 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 2 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "extv\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "extv.*insv.*branch" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/cmpelim-xxu-subsi.c b/gcc/testsuite/gcc.target/vax/cmpelim-xxu-subsi.c
new file mode 100644
index 0000000..b9f7304
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cmpelim-xxu-subsi.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-cmpelim -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+
+int_t
+xxu_subsi (int_t x, int_t y)
+{
+ int_t v;
+
+ v = x - y;
+ if (x == y)
+ return v;
+ else if (x >= y)
+ return v + 2;
+ else
+ return v - 3;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r2 # 39 [c=16] *movsi_2
+ movl 8(%ap),%r1 # 40 [c=16] *movsi_2
+ subl3 %r1,%r2,%r0 # 41 [c=32] *subsi3_cc/1
+ jeql .L1 # 43 [c=26] *branch_ccz
+ jlssu .L3 # 38 [c=26] *branch_cc
+ addl2 $2,%r0 # 36 [c=32] *addsi3
+ ret # 31 [c=0] return
+.L3:
+ subl2 $3,%r0 # 35 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "deleting insn with uid" 2 "cmpelim" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "subsi\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/compare-add-zero.c b/gcc/testsuite/gcc.target/vax/compare-add-zero.c
new file mode 100644
index 0000000..97d4c53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/compare-add-zero.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int
+compare_add (int x, int y)
+{
+ int z;
+
+ z = x + y;
+ if (z < 0)
+ return z;
+ else
+ return z + 2;
+}
+
+/* Expect assembly like:
+
+ addl3 4(%ap),8(%ap),%r0
+ jlss .L1
+ addl2 $2,%r0
+.L1:
+
+A reverse branch may be used at some optimization levels. */
+
+/* Make sure the comparison is made against 0 rather than -1. */
+/* { dg-final { scan-assembler-not "\tj(gtr|leq) " } } */
+/* { dg-final { scan-assembler "\tj(geq|lss) " } } */
diff --git a/gcc/testsuite/gcc.target/vax/compare-mov-zero.c b/gcc/testsuite/gcc.target/vax/compare-mov-zero.c
new file mode 100644
index 0000000..c802049
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/compare-mov-zero.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int
+compare_mov (int x)
+{
+ if (x > 0)
+ return x;
+ else
+ return x + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r0
+ jgtr .L2
+ addl2 $2,%r0
+.L2:
+
+A reverse branch may be used at some optimization levels. */
+
+/* Make sure the comparison is made against 0 rather than 1. */
+/* { dg-final { scan-assembler-not "\tj(geq|lss) " } } */
+/* { dg-final { scan-assembler "\tj(gtr|leq) " } } */
diff --git a/gcc/testsuite/gcc.target/vax/cpymem.c b/gcc/testsuite/gcc.target/vax/cpymem.c
new file mode 100644
index 0000000..91805a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/cpymem.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+#include <stddef.h>
+
+void *
+memcpy8 (void *to, const void *from, size_t size)
+{
+ unsigned char s8 = size;
+ return __builtin_memcpy (to, from, s8);
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r6
+ movzbl 12(%ap),%r7
+ movl 8(%ap),%r8
+ movc3 %r7,(%r8),(%r6)
+ movl %r6,%r0
+
+ */
+
+/* { dg-final { scan-assembler "\tmovc3 " } } */
diff --git a/gcc/testsuite/gcc.target/vax/ctzhi.c b/gcc/testsuite/gcc.target/vax/ctzhi.c
new file mode 100644
index 0000000..fcc9f06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/ctzhi.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (HI))) int_t;
+
+int
+ctzhi (int_t *x)
+{
+ return __builtin_ctz (*x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$16,*4(%ap),%r0
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler "\tffs \\\$0,\\\$16," } } */
diff --git a/gcc/testsuite/gcc.target/vax/ctzqi.c b/gcc/testsuite/gcc.target/vax/ctzqi.c
new file mode 100644
index 0000000..067334b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/ctzqi.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (QI))) int_t;
+
+int
+ctzqi (int_t *x)
+{
+ return __builtin_ctz (*x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$8,*4(%ap),%r0
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler "\tffs \\\$0,\\\$8," } } */
diff --git a/gcc/testsuite/gcc.target/vax/ctzsi.c b/gcc/testsuite/gcc.target/vax/ctzsi.c
new file mode 100644
index 0000000..8be4271
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/ctzsi.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+int
+ctzsi (unsigned int x)
+{
+ return __builtin_ctz (x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$32,4(%ap),%r0
+
+ */
+
+/* { dg-final { scan-assembler "\tffs \\\$0,\\\$32," } } */
diff --git a/gcc/testsuite/gcc.target/vax/ffshi.c b/gcc/testsuite/gcc.target/vax/ffshi.c
new file mode 100644
index 0000000..db592fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/ffshi.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+int
+ffshi (int_t *x)
+{
+ return __builtin_ffs (*x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$16,*4(%ap),%r0
+ jneq .L2
+ mnegl $1,%r0
+.L2:
+ incl %r0
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler "\tffs \\\$0,\\\$16," } } */
diff --git a/gcc/testsuite/gcc.target/vax/ffsqi.c b/gcc/testsuite/gcc.target/vax/ffsqi.c
new file mode 100644
index 0000000..ebcd946
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/ffsqi.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+int
+ffsqi (int_t *x)
+{
+ return __builtin_ffs (*x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$8,*4(%ap),%r0
+ jneq .L2
+ mnegl $1,%r0
+.L2:
+ incl %r0
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler "\tffs \\\$0,\\\$8," } } */
diff --git a/gcc/testsuite/gcc.target/vax/ffssi.c b/gcc/testsuite/gcc.target/vax/ffssi.c
new file mode 100644
index 0000000..3e7a3c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/ffssi.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+int
+ffssi (int x)
+{
+ return __builtin_ffs (x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$32,%r1,%r0
+ jneq .L2
+ mnegl $1,%r0
+.L2:
+ incl %r0
+
+ */
+
+/* { dg-final { scan-assembler "\tffs \\\$0,\\\$32," } } */
diff --git a/gcc/testsuite/gcc.target/vax/movmem.c b/gcc/testsuite/gcc.target/vax/movmem.c
new file mode 100644
index 0000000..b907d8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/movmem.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+#include <stddef.h>
+
+void *
+memmove8 (void *to, const void *from, size_t size)
+{
+ unsigned char s8 = size;
+ return __builtin_memmove (to, from, s8);
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r6
+ movzbl 12(%ap),%r7
+ movl 8(%ap),%r8
+ movc3 %r7,(%r8),(%r6)
+ movl %r6,%r0
+
+ */
+
+/* { dg-final { scan-assembler "\tmovc3 " } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-andhi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-andhi.c
new file mode 100644
index 0000000..485b324
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-andhi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_andhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & *y;
+ if (v == 0)
+ *w = 1;
+ else
+ *w = 2;
+}
+
+/* Expect assembly like:
+
+ bitw *8(%ap),*12(%ap) # 50 [c=50] *bithi_ccz
+ jneq .L3 # 40 [c=26] *branch_ccz
+ movw $1,%r0 # 36 [c=4] *movhi
+ movw %r0,*4(%ap) # 34 [c=4] *movhi
+ ret # 46 [c=0] return
+.L3:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bithi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-andqi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-andqi.c
new file mode 100644
index 0000000..ffea453
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-andqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_andqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & *y;
+ if (v == 0)
+ *w = 1;
+ else
+ *w = 2;
+}
+
+/* Expect assembly like:
+
+ bitb *8(%ap),*12(%ap) # 50 [c=50] *bitqi_ccz
+ jneq .L3 # 40 [c=26] *branch_ccz
+ movb $1,%r0 # 36 [c=4] *movqi
+ movb %r0,*4(%ap) # 34 [c=4] *movqi
+ ret # 46 [c=0] return
+.L3:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bitqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-andsi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-andsi.c
new file mode 100644
index 0000000..b84c352
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-andsi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_andsi (int_t x, int_t y)
+{
+ x &= y;
+ if (x == 0)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ bitl 4(%ap),8(%ap) # 52 [c=34] *bitsi_ccz
+ jneq .L6 # 41 [c=26] *branch_ccz
+ movl $1,%r0 # 36 [c=4] *movsi_2
+ ret # 47 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bitsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-cmpvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-cmpvsi.c
new file mode 100644
index 0000000..3e09a78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-cmpvsi.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+eq_cmpvsi (bit_t x, int_t y)
+{
+ if (x.i == y)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ cmpv $7,$18,4(%ap),8(%ap) # 50 [c=88] *cmpv_ccz
+ jeql .L3 # 39 [c=26] *branch_ccz
+ movl $2,%r0 # 36 [c=4] *movsi_2
+ ret # 31 [c=0] return
+.L3:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpv\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-cmpzvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-cmpzvsi.c
new file mode 100644
index 0000000..3713c1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-cmpzvsi.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+eq_extzvsi (bit_t x, int_t y)
+{
+ if (x.i == y)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ cmpzv $7,$18,4(%ap),8(%ap) # 50 [c=88] *cmpzv_ccz
+ jeql .L3 # 39 [c=26] *branch_ccz
+ movl $2,%r0 # 36 [c=4] *movsi_2
+ ret # 31 [c=0] return
+.L3:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpzv\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-0.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-0.c
new file mode 100644
index 0000000..8a56451
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-0.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_ctzhi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = __builtin_ctz (*x);
+ if (*x == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movw *8(%ap),%r1 # 34 [c=24] *movhi
+ ffs $0,$16,%r1,%r0 # 49 [c=4] *ctzhi2_ccz
+ jeql .L3 # 38 [c=26] *branch_ccz
+ addw2 $2,%r0 # 33 [c=32] *addhi3
+.L3:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 2 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ctzhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-1.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-1.c
new file mode 100644
index 0000000..db76da4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzhi-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_ctzhi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = __builtin_ctz (*x + 1);
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtwl *8(%ap),%r0 # 34 [c=28] *extendhisi2
+ incl %r0 # 35 [c=32] *addsi3
+ ffs $0,$32,%r0,%r0 # 36 [c=4] *ctzsi2
+ tstl %r0 # 37 [c=6] *cmpsi_ccz/0
+ jeql .L2 # 38 [c=26] *branch_ccz
+ addw2 $2,%r0 # 33 [c=32] *addhi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-not "Splitting with gen_peephole2" "peephole2" } } */
+/* { dg-final { scan-assembler "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "cmpsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-0.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-0.c
new file mode 100644
index 0000000..b6078bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-0.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_ctzqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = __builtin_ctz (*x);
+ if (*x == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ movb *8(%ap),%r1 # 34 [c=24] *movqi
+ ffs $0,$8,%r1,%r0 # 49 [c=4] *ctzqi2_ccz
+ jeql .L3 # 38 [c=26] *branch_ccz
+ addb2 $2,%r0 # 33 [c=32] *addqi3
+.L3:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 2 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ctzqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-1.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-1.c
new file mode 100644
index 0000000..44311b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzqi-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_ctzqi (int_t *w, int_t *x)
+{
+ int_t v;
+
+ v = __builtin_ctz (*x + 1);
+ if (v == 0)
+ *w = v;
+ else
+ *w = v + 2;
+}
+
+/* Expect assembly like:
+
+ cvtbl *8(%ap),%r0 # 34 [c=28] *extendqisi2
+ incl %r0 # 35 [c=32] *addsi3
+ ffs $0,$32,%r0,%r0 # 36 [c=4] *ctzsi2
+ tstl %r0 # 37 [c=6] *cmpsi_ccz/0
+ jeql .L2 # 38 [c=26] *branch_ccz
+ addb2 $2,%r0 # 33 [c=32] *addqi3
+.L2:
+
+ */
+
+/* { dg-final { scan-rtl-dump-not "Splitting with gen_peephole2" "peephole2" } } */
+/* { dg-final { scan-assembler "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "cmpsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-0.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-0.c
new file mode 100644
index 0000000..bf84bdc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-0.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_ctzsi (int_t x)
+{
+ int_t v;
+
+ v = __builtin_ctz (x);
+ if (x == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r1 # 32 [c=16] *movsi_2
+ ffs $0,$32,%r1,%r0 # 45 [c=4] *ctzsi2_ccz
+ jeql .L1 # 35 [c=26] *branch_ccz
+ addl2 $2,%r0 # 31 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ctzsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-1.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-1.c
new file mode 100644
index 0000000..0cc40ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ctzsi-1.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_ctzsi (int_t x)
+{
+ int_t v;
+
+ v = __builtin_ctz (x + 1);
+ if (v == 0)
+ return v;
+ else
+ return v + 2;
+}
+
+/* Expect assembly like:
+
+ addl3 4(%ap),$1,%r0 # 33 [c=40] *addsi3
+ ffs $0,$32,%r0,%r0 # 34 [c=4] *ctzsi2
+ tstl %r0 # 35 [c=6] *cmpsi_ccz/0
+ jeql .L1 # 36 [c=26] *branch_ccz
+ addl2 $2,%r0 # 32 [c=32] *addsi3
+.L1:
+
+ */
+
+/* { dg-final { scan-rtl-dump-not "Splitting with gen_peephole2" "peephole2" } } */
+/* { dg-final { scan-assembler "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "cmpsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ffshi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ffshi.c
new file mode 100644
index 0000000..50a6cdb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ffshi.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+eq_ffshi (int_t *w, int_t *x)
+{
+ *w = __builtin_ffs (*x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$16,*8(%ap),%r1 # 40 [c=28] *ctzhi2_ccz
+ jneq .L2 # 30 [c=26] *branch_ccz
+ mnegl $1,%r1 # 26 [c=8] *negsi2
+.L2:
+ addw3 %r1,$1,*4(%ap) # 25 [c=32] *addhi3
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ctzhi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ffsqi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ffsqi.c
new file mode 100644
index 0000000..0b3ef0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ffsqi.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+eq_ffsqi (int_t *w, int_t *x)
+{
+ *w = __builtin_ffs (*x);
+}
+
+/* Expect assembly like:
+
+ ffs $0,$8,*8(%ap),%r1 # 40 [c=28] *ctzqi2_ccz
+ jneq .L2 # 30 [c=26] *branch_ccz
+ mnegl $1,%r1 # 26 [c=8] *negsi2
+.L2:
+ addb3 %r1,$1,*4(%ap) # 25 [c=32] *addqi3
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ctzqi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-eq-ffssi.c b/gcc/testsuite/gcc.target/vax/peephole2-eq-ffssi.c
new file mode 100644
index 0000000..0e32121
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-eq-ffssi.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+eq_ffssi (int_t x)
+{
+ return __builtin_ffs (x);
+}
+
+/* Expect assembly like:
+
+ movl 4(%ap),%r1 # 28 [c=16] *movsi_2
+ ffs $0,$32,%r1,%r0 # 41 [c=4] *ctzsi2_ccz
+ jneq .L2 # 31 [c=26] *branch_ccz
+ mnegl $1,%r0 # 27 [c=8] *negsi2
+.L2:
+ incl %r0 # 26 [c=32] *addsi3
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "ctzsi\[^ \]*_ccz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-le-andhi.c b/gcc/testsuite/gcc.target/vax/peephole2-le-andhi.c
new file mode 100644
index 0000000..9eb40c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-le-andhi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_andhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & *y;
+ if (v <= 0)
+ *w = 1;
+ else
+ *w = 2;
+}
+
+/* Expect assembly like:
+
+ bitw *8(%ap),*12(%ap) # 56 [c=50] *bithi_ccnz
+ jleq .L6 # 46 [c=26] *branch_ccnz
+ movw $2,%r0 # 41 [c=4] *movhi
+ movw %r0,*4(%ap) # 40 [c=4] *movhi
+ ret # 52 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bithi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-le-andqi.c b/gcc/testsuite/gcc.target/vax/peephole2-le-andqi.c
new file mode 100644
index 0000000..14797b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-le-andqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+le_andqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & *y;
+ if (v <= 0)
+ *w = 1;
+ else
+ *w = 2;
+}
+
+/* Expect assembly like:
+
+ bitb *8(%ap),*12(%ap) # 56 [c=50] *bitqi_ccnz
+ jleq .L6 # 46 [c=26] *branch_ccnz
+ movb $2,%r0 # 41 [c=4] *movqi
+ movb %r0,*4(%ap) # 40 [c=4] *movqi
+ ret # 52 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bitqi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-le-andsi.c b/gcc/testsuite/gcc.target/vax/peephole2-le-andsi.c
new file mode 100644
index 0000000..6d1193e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-le-andsi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+le_andsi (int_t x, int_t y)
+{
+ x &= y;
+ if (x <= 0)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ bitl 4(%ap),8(%ap) # 58 [c=34] *bitsi_ccnz
+ jgtr .L6 # 47 [c=26] *branch_ccnz
+ movl $1,%r0 # 42 [c=4] *movsi_2
+ ret # 53 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bitsi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-le-cmpvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-le-cmpvsi.c
new file mode 100644
index 0000000..dd26849
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-le-cmpvsi.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+le_cmpvsi (bit_t x, int_t y)
+{
+ if (x.i <= y)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ cmpv $7,$18,4(%ap),8(%ap) # 50 [c=88] *cmpv_ccnz
+ jgtr .L6 # 39 [c=26] *branch_ccnz
+ movl $1,%r0 # 35 [c=4] *movsi_2
+ ret # 45 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpv\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-le-cmpzvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-le-cmpzvsi.c
new file mode 100644
index 0000000..3cf028a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-le-cmpzvsi.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+uint_t
+le_cmpzvsi (uint_t x, int_t y, int_t z)
+{
+ int_t v;
+
+ v = x >> y;
+ if (v <= z)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ subb3 8(%ap),$32,%r0 # 39 [c=40] *subqi3/1
+ cmpzv 8(%ap),%r0,4(%ap),12(%ap) # 53 [c=96] *cmpzv_ccnz
+ jgtr .L6 # 42 [c=26] *branch_ccnz
+ movl $1,%r0 # 37 [c=4] *movsi_2
+ ret # 48 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpzv\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-leu-cmpvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-leu-cmpvsi.c
new file mode 100644
index 0000000..0a0468b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-leu-cmpvsi.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+leu_cmpvsi (bit_t x, uint_t y)
+{
+ uint_t v;
+
+ v = x.i;
+ if (v <= y)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ cmpv $7,$18,4(%ap),8(%ap) # 50 [c=88] *cmpv_cc
+ jgtru .L6 # 39 [c=26] *branch_cc
+ movl $1,%r0 # 35 [c=4] *movsi_2
+ ret # 45 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpv\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-leu-cmpzvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-leu-cmpzvsi.c
new file mode 100644
index 0000000..ca7cfe4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-leu-cmpzvsi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+uint_t
+leu_cmpzvsi (uint_t x, int_t y, uint_t z)
+{
+ if (x >> y <= z)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ subb3 8(%ap),$32,%r0 # 39 [c=40] *subqi3/1
+ cmpzv 8(%ap),%r0,4(%ap),12(%ap) # 53 [c=96] *cmpzv_cc
+ jgtru .L6 # 42 [c=26] *branch_cc
+ movl $1,%r0 # 37 [c=4] *movsi_2
+ ret # 48 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpzv\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-lt-andhi.c b/gcc/testsuite/gcc.target/vax/peephole2-lt-andhi.c
new file mode 100644
index 0000000..9eb40c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-lt-andhi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (HI))) int_t;
+
+void
+le_andhi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & *y;
+ if (v <= 0)
+ *w = 1;
+ else
+ *w = 2;
+}
+
+/* Expect assembly like:
+
+ bitw *8(%ap),*12(%ap) # 56 [c=50] *bithi_ccnz
+ jleq .L6 # 46 [c=26] *branch_ccnz
+ movw $2,%r0 # 41 [c=4] *movhi
+ movw %r0,*4(%ap) # 40 [c=4] *movhi
+ ret # 52 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bithi\[^ \]*_ccnz(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccnz\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-lt-andqi.c b/gcc/testsuite/gcc.target/vax/peephole2-lt-andqi.c
new file mode 100644
index 0000000..d71c46d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-lt-andqi.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (QI))) int_t;
+
+void
+lt_andqi (int_t *w, int_t *x, int_t *y)
+{
+ int_t v;
+
+ v = *x & *y;
+ if (v < 0)
+ *w = 1;
+ else
+ *w = 2;
+}
+
+/* Expect assembly like:
+
+ bitb *8(%ap),*12(%ap) # 68 [c=50] *bitqi_ccn
+ jlss .L6 # 58 [c=26] *branch_ccn
+ movb $2,%r0 # 53 [c=4] *movqi
+ movb %r0,*4(%ap) # 52 [c=4] *movqi
+ ret # 64 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bitqi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-lt-andsi.c b/gcc/testsuite/gcc.target/vax/peephole2-lt-andsi.c
new file mode 100644
index 0000000..4045b36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-lt-andsi.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef int __attribute__ ((mode (SI))) int_t;
+
+int_t
+lt_andsi (int_t x, int_t y)
+{
+ x &= y;
+ if (x < 0)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ bitl 4(%ap),8(%ap) # 68 [c=34] *bitsi_ccn
+ jgeq .L6 # 57 [c=26] *branch_ccn
+ movl $1,%r0 # 52 [c=4] *movsi_2
+ ret # 63 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(cmpz?|tst). " } } */
+/* { dg-final { scan-assembler "bitsi\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-lt-cmpvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-lt-cmpvsi.c
new file mode 100644
index 0000000..a50f322
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-lt-cmpvsi.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+lt_cmpvsi (bit_t x, int_t y)
+{
+ if (x.i < y)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ cmpv $7,$18,4(%ap),8(%ap) # 50 [c=88] *cmpv_ccn
+ jgeq .L6 # 39 [c=26] *branch_ccn
+ movl $1,%r0 # 35 [c=4] *movsi_2
+ ret # 45 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpv\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-lt-cmpzvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-lt-cmpzvsi.c
new file mode 100644
index 0000000..de38643
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-lt-cmpzvsi.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+uint_t
+lt_cmpzvsi (uint_t x, int_t y, int_t z)
+{
+ int_t v;
+
+ v = x >> y;
+ if (v < z)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ subb3 8(%ap),$32,%r0 # 39 [c=40] *subqi3/1
+ cmpzv 8(%ap),%r0,4(%ap),12(%ap) # 53 [c=96] *cmpzv_ccn
+ jgeq .L6 # 42 [c=26] *branch_ccn
+ movl $1,%r0 # 37 [c=4] *movsi_2
+ ret # 48 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpzv\[^ \]*_ccn(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_ccn\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpvsi.c
new file mode 100644
index 0000000..8eba505
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpvsi.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef signed int __attribute__ ((mode (SI))) int_t;
+typedef struct
+ {
+ int_t h : 7;
+ int_t i : 18;
+ int_t l : 7;
+ }
+bit_t;
+
+int_t
+ltu_cmpvsi (bit_t x, uint_t y)
+{
+ uint_t v;
+
+ v = x.i;
+ if (v < y)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ cmpv $7,$18,4(%ap),8(%ap) # 50 [c=88] *cmpv_cc
+ jgequ .L6 # 39 [c=26] *branch_cc
+ movl $1,%r0 # 35 [c=4] *movsi_2
+ ret # 45 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpv\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpzvsi.c b/gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpzvsi.c
new file mode 100644
index 0000000..9cdee86
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/peephole2-ltu-cmpzvsi.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-rtl-peephole2 -dp" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned int __attribute__ ((mode (SI))) uint_t;
+typedef int __attribute__ ((mode (SI))) int_t;
+
+uint_t
+ltu_cmpzvsi (uint_t x, int_t y, uint_t z)
+{
+ if (x >> y < z)
+ return 1;
+ else
+ return 2;
+}
+
+/* Expect assembly like:
+
+ subb3 8(%ap),$32,%r0 # 39 [c=40] *subqi3/1
+ cmpzv 8(%ap),%r0,4(%ap),12(%ap) # 53 [c=96] *cmpzv_cc
+ jgequ .L6 # 42 [c=26] *branch_cc
+ movl $1,%r0 # 37 [c=4] *movsi_2
+ ret # 48 [c=0] return
+.L6:
+
+ */
+
+/* { dg-final { scan-rtl-dump-times "Splitting with gen_peephole2" 1 "peephole2" } } */
+/* { dg-final { scan-assembler-not "\t(bit|cmp|tst)\[bwl\] " } } */
+/* { dg-final { scan-assembler "cmpzv\[^ \]*_cc(/\[0-9\]+)?\n" } } */
+/* { dg-final { scan-assembler "branch_cc\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/pr56875.c b/gcc/testsuite/gcc.target/vax/pr56875.c
index f409afe..191e05e 100644
--- a/gcc/testsuite/gcc.target/vax/pr56875.c
+++ b/gcc/testsuite/gcc.target/vax/pr56875.c
@@ -1,13 +1,10 @@
/* { dg-do compile } */
-/* { dg-options "-O0" } */
+/* { dg-options "" } */
/* { dg-final { scan-assembler "ashq .*,\\\$0xffffffffffffffff," } } */
/* { dg-final { scan-assembler-not "ashq .*,\\\$-1," } } */
-void
-a (void)
+unsigned long long
+a (unsigned long i)
{
- unsigned long i = 1;
- unsigned long long v;
-
- v = ~ (unsigned long long) 0 << i;
+ return ~(unsigned long long) 0 << i;
}
diff --git a/gcc/testsuite/gcc.target/vax/push.c b/gcc/testsuite/gcc.target/vax/push.c
new file mode 100644
index 0000000..647ea60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/push.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+void bar (void (*) (void), int, int);
+
+void
+foo (void)
+{
+ bar (foo, 1, 0);
+}
+
+/* Expect assembly like:
+
+ pushl $0
+ pushl $1
+ pushab foo
+ calls $3,bar
+
+rather than:
+
+ clrl -(%sp)
+ movl $1,-(%sp)
+ movab foo,-(%sp)
+ calls $3,bar
+
+ */
+
+/* { dg-final { scan-assembler "\[ \t\]+pushl\[ \t\]+\\\$0\n\[ \t\]+pushl\[ \t\]+\\\$1\n\[ \t\]+pushab\[ \t\]+foo\n" } } */
diff --git a/gcc/testsuite/gcc.target/vax/vax.exp b/gcc/testsuite/gcc.target/vax/vax.exp
index 4f48055..678e900 100644
--- a/gcc/testsuite/gcc.target/vax/vax.exp
+++ b/gcc/testsuite/gcc.target/vax/vax.exp
@@ -34,7 +34,7 @@ if ![info exists DEFAULT_CFLAGS] then {
dg-init
# Main loop.
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
"" $DEFAULT_CFLAGS
# All done.
diff --git a/gcc/testsuite/gcc.target/xtensa/bswap.c b/gcc/testsuite/gcc.target/xtensa/bswap.c
new file mode 100644
index 0000000..057a356
--- /dev/null
+++ b/gcc/testsuite/gcc.target/xtensa/bswap.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+unsigned long f32(unsigned long v)
+{
+ return __builtin_bswap32(v);
+}
+
+unsigned long long f64(unsigned long long v)
+{
+ return __builtin_bswap64(v);
+}
+
+/* { dg-final { scan-assembler-times "ssai" 2 } } */
diff --git a/gcc/testsuite/gcc.target/xtensa/pr98285.c b/gcc/testsuite/gcc.target/xtensa/pr98285.c
new file mode 100644
index 0000000..2c037d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/xtensa/pr98285.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int mul3(int v)
+{
+ return v * 3;
+}
+
+int mul5(int v)
+{
+ return v * 5;
+}
+
+int mul7(int v)
+{
+ return v * 7;
+}
+
+int mul9(int v)
+{
+ return v * 9;
+}
+
+int mul2sub(int a, int b)
+{
+ return a * 2 - b;
+}
+
+int mul4sub(int a, int b)
+{
+ return a * 4 - b;
+}
+
+short index2(short *p, int i)
+{
+ return p[i];
+}
+
+int index4(int *p, int i)
+{
+ return p[i];
+}
+
+long long index8(long long *p, int i)
+{
+ return p[i];
+}
+
+/* { dg-final { scan-assembler-times "addx2" 2 } } */
+/* { dg-final { scan-assembler-times "addx4" 2 } } */
+/* { dg-final { scan-assembler-times "addx8" 2 } } */
+/* { dg-final { scan-assembler-times "subx2" 1 } } */
+/* { dg-final { scan-assembler-times "subx4" 1 } } */
+/* { dg-final { scan-assembler-times "subx8" 1 } } */
diff --git a/gcc/testsuite/gcc.target/xtensa/shifts.c b/gcc/testsuite/gcc.target/xtensa/shifts.c
new file mode 100644
index 0000000..8d7e4a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/xtensa/shifts.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+int lshift1(int v)
+{
+ return v << 1;
+}
+
+int lshift2(int v, int s)
+{
+ return v << (s * 8);
+}
+
+unsigned int lshift3(unsigned int v, int s)
+{
+ return v << (s * 8);
+}
+
+int rshift1(int v, int s)
+{
+ return v >> (s * 8);
+}
+
+unsigned int rshift2(unsigned int v, int s)
+{
+ return v >> (s * 8);
+}
+
+/* { dg-final { scan-assembler-not "slli" } } */
+/* { dg-final { scan-assembler-times "ssa8l" 2 } } */
+/* { dg-final { scan-assembler-times "ssa8b" 2 } } */
diff --git a/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
new file mode 100644
index 0000000..b4d5b47
--- /dev/null
+++ b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
@@ -0,0 +1,13 @@
+// Test the scan-symbol-section directive.
+// scan-symbol-section should fail with 'FAIL' if a symbol has a different
+// section than expected.
+
+// { dg-do preprocess }
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-1-exp-F.i" {^_test_symbol_.*$} {nomatch} } }
+// The above assertion should fail with the following messages:
+// FAIL: gcc.test-framework/dg-scan-symbol-section-1-exp-F.S scan-symbol-section symbol ^_test_symbol_.*$ (found _test_symbol_1) has section nomatch (found .text)
+// FAIL: gcc.test-framework/dg-scan-symbol-section-1-exp-F.S scan-symbol-section symbol ^_test_symbol_.*$ (found _test_symbol_2) has section nomatch (found .data)
+ .text
+_test_symbol_1:
+ .data
+_test_symbol_2:
diff --git a/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
new file mode 100644
index 0000000..0187275
--- /dev/null
+++ b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
@@ -0,0 +1,9 @@
+// Test the scan-symbol-section directive.
+// scan-symbol-section should fail with 'UNSUPPORTED' if a symbol has no
+// associated section.
+
+// { dg-do preprocess }
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-2-exp-F.i" {^_test_symbol$} {^\.text$} } }
+// The above assertion should fail with the following message:
+// FAIL: gcc.test-framework/dg-scan-symbol-section-2-exp-F.S scan-symbol-section symbol ^_test_symbol$ (found _test_symbol) has section ^\\.text$ (no section detected)
+_test_symbol:
diff --git a/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
new file mode 100644
index 0000000..87b09a3
--- /dev/null
+++ b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
@@ -0,0 +1,10 @@
+// Test the scan-symbol-section directive.
+// scan-symbol-section should fail with 'UNSUPPORTED' if a symbol has no
+// associated section.
+
+// { dg-do preprocess }
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-3-exp-F.i" {^_test_symbol$} {^\.text$} } }
+// The above assertion should fail with the following message:
+// FAIL: gcc.test-framework/dg-scan-symbol-section-3-exp-F.S scan-symbol-section symbol ^_test_symbol$ (no symbol detected) has section ^\\.text$
+ .text
+_test_wrong_symbol:
diff --git a/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S
new file mode 100644
index 0000000..4e7df41
--- /dev/null
+++ b/gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S
@@ -0,0 +1,50 @@
+// Test the scan-symbol-section directive.
+
+// { dg-do preprocess }
+
+// The .section directive changes the section for all following symbols.
+ .section .text
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_1$} {^\.text$} } }
+_test_function_1:
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_2$} {^\.text$} } }
+_test_function_2:
+
+// For ELF targets, the .section directive can take multiple arguments.
+ .section .other_text_section,"ax",progbits
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_elf_function$} {^\.other_text_section$} } }
+_test_elf_function:
+
+// For Mach-O targets, the .section directive takes a segment name and a section name.
+ .section __TEXT,__my_text_section
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_macho_function$} {^__TEXT,__my_text_section$} } }
+_test_macho_function:
+// Extra whitespace between .section arguments should be ignored.
+ .section __DATA , __testsection
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_macho_var$} {^__DATA,__testsection$} } }
+_test_macho_var:
+
+// The .data directive sets the section for all following symbols to '.data'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_var_1$} {^\.data$} } }
+ .data
+_test_var_1:
+
+// The .text directive sets the section for all following symbols to '.text'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_3$} {^\.text$} } }
+ .text
+_test_function_3:
+
+// The .const directive sets the section for all following symbols to '.const'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_data_1$} {^\.const$} } }
+ .const
+_test_data_1:
+
+// Other directives do not affect the section of following symbols.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_var_2$} {^\.data$} } }
+ .data
+ .p2align 2
+ .size _test_var_2, 4
+_test_var_2:
+
+// Symbol name patterns can match multiple symbols, and section name patterns
+// can match multiple sections.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_} {^(\.|__TEXT,).*text} } }
diff --git a/gcc/testsuite/gcc.test-framework/test-framework.exp b/gcc/testsuite/gcc.test-framework/test-framework.exp
index c269594..45328bf 100644
--- a/gcc/testsuite/gcc.test-framework/test-framework.exp
+++ b/gcc/testsuite/gcc.test-framework/test-framework.exp
@@ -23,6 +23,7 @@ if { ![info exists env(CHECK_TEST_FRAMEWORK)] } {
}
load_lib gcc-dg.exp
+load_lib scanasm.exp
proc dg-require-true { args } {
verbose "dg-require-true" 2
@@ -59,7 +60,7 @@ set dg-do-what-default compile
dg-init
# Run tests from the source directory.
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dg-*.c]] "" ""
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dg-*.S $srcdir/$subdir/dg-*.c]] "" ""
# Skip generated tests unless CHECK_TEST_FRAMEWORK is 1.
if { $env(CHECK_TEST_FRAMEWORK) != 1 } {
diff --git a/gcc/testsuite/gdc.dg/debug/debug.exp b/gcc/testsuite/gdc.dg/debug/debug.exp
new file mode 100644
index 0000000..1607c4d
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/debug.exp
@@ -0,0 +1,28 @@
+# Copyright (C) 2020 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+# Load support procs.
+load_lib gdc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+gcc-dg-debug-runtest gdc_target_compile trivial.d [list -O -O3] \
+ [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gdc.dg/debug/dwarf2/dwarf2.exp b/gcc/testsuite/gdc.dg/debug/dwarf2/dwarf2.exp
new file mode 100644
index 0000000..c81afd0
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/dwarf2/dwarf2.exp
@@ -0,0 +1,31 @@
+# Copyright (C) 2020 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+# Load support procs.
+load_lib gdc-dg.exp
+
+# Main loop.
+set comp_output [gdc_target_compile \
+ "$srcdir/$subdir/../trivial.d" "trivial.S" assembly \
+ "additional_flags=-gdwarf"]
+if { ! [string match "*: target system does not support the * debug format*" \
+ $comp_output] } {
+ remove-build-file "trivial.S"
+ gdc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.d ] ] "" "-gdwarf"
+}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gdc.dg/debug/dwarf2/imports/pr98067.d b/gcc/testsuite/gdc.dg/debug/dwarf2/imports/pr98067.d
new file mode 100644
index 0000000..d740d71
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/dwarf2/imports/pr98067.d
@@ -0,0 +1,3 @@
+module imports.pr98067;
+
+enum MAP_ANON = 0x10;
diff --git a/gcc/testsuite/gdc.dg/debug/dwarf2/langdw2.d b/gcc/testsuite/gdc.dg/debug/dwarf2/langdw2.d
new file mode 100644
index 0000000..61c3927
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/dwarf2/langdw2.d
@@ -0,0 +1,7 @@
+// DW_LANG_D is not available in dwarf2, so we should produce DW_LANG_C (0x2)
+// as AT_language.
+// { dg-do compile }
+// { dg-options "-gdwarf-2 -gstrict-dwarf -dA" }
+// { dg-final { scan-assembler "0x2\[^\n\r\]*AT_language" } }
+
+module langdw2;
diff --git a/gcc/testsuite/gdc.dg/debug/dwarf2/langdw3.d b/gcc/testsuite/gdc.dg/debug/dwarf2/langdw3.d
new file mode 100644
index 0000000..7bdc68c
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/dwarf2/langdw3.d
@@ -0,0 +1,6 @@
+// We should produce DW_LANG_D (0x13) as AT_language.
+// { dg-do compile }
+// { dg-options "-gdwarf-3 -dA" }
+// { dg-final { scan-assembler "0x13\[^\n\r\]*AT_language" } }
+
+module langdw3;
diff --git a/gcc/testsuite/gdc.dg/debug/dwarf2/pr98067.d b/gcc/testsuite/gdc.dg/debug/dwarf2/pr98067.d
new file mode 100644
index 0000000..4beb268
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/dwarf2/pr98067.d
@@ -0,0 +1,6 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98067
+// { dg-options "-gdwarf-2 -gstrict-dwarf -I $srcdir/gdc.dg/debug/dwarf2" }
+// { dg-do compile }
+module pr98067;
+
+import imports.pr98067 : MAP_ANON;
diff --git a/gcc/testsuite/gdc.dg/debug/trivial.d b/gcc/testsuite/gdc.dg/debug/trivial.d
new file mode 100644
index 0000000..dab2b68
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/debug/trivial.d
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+
+int main()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.dg/intrinsics.d b/gcc/testsuite/gdc.dg/intrinsics.d
index 5888361..a775237 100644
--- a/gcc/testsuite/gdc.dg/intrinsics.d
+++ b/gcc/testsuite/gdc.dg/intrinsics.d
@@ -8,65 +8,77 @@ import core.stdc.stdarg;
//////////////////////////////////////////////////////
// core.bitop
-// { dg-final { scan-tree-dump-not " bsf " "original" } }
+// { dg-final { scan-tree-dump " __builtin_ctz " "original" } }
int test_bsf(uint a) { return bsf(a); }
+// { dg-final { scan-tree-dump " __builtin_ctz(l|ll) " "original" } }
int test_bsf(ulong a) { return bsf(a); }
-// { dg-final { scan-tree-dump-not " bsr " "original" } }
+// { dg-final { scan-tree-dump " __builtin_clz " "original" } }
int test_bsr(uint a) { return bsr(a); }
+// { dg-final { scan-tree-dump " __builtin_clz(l|ll) " "original" } }
int test_bsr(ulong a) { return bsr(a); }
-// { dg-final { scan-tree-dump-not " bt " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = bt " "original" } }
int test_bt(size_t *a, size_t b) { return bt(a, b); }
-// { dg-final { scan-tree-dump-not " btc " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = btc " "original" } }
int test_btc(size_t *a, size_t b) { return btc(a, b); }
-// { dg-final { scan-tree-dump-not " btr " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = btr " "original" } }
int test_btr(size_t *a, size_t b) { return btr(a, b); }
-// { dg-final { scan-tree-dump-not " bts " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = bts " "original" } }
int test_bts(size_t *a, size_t b) { return bts(a, b); }
-// { dg-final { scan-tree-dump-not " bswap " "original" } }
+// { dg-final { scan-tree-dump " __builtin_bswap32 " "original" } }
uint test_bswap(uint a) { return bswap(a); }
+// { dg-final { scan-tree-dump " __builtin_bswap64 " "original" } }
ulong test_bswap(ulong a) { return bswap(a); }
-// { dg-final { scan-tree-dump-not " popcnt " "original" } }
+// { dg-final { scan-tree-dump " __builtin_popcount " "original" } }
int test_popcnt(uint a) { return popcnt(a); }
+// { dg-final { scan-tree-dump " __builtin_popcount(l|ll) " "original" } }
int test_popcnt(ulong a) { return popcnt(a); }
-// { dg-final { scan-tree-dump-not " volatileLoad " "original" } }
+// { dg-final { scan-tree-dump "\\(volatile ubyte \\*\\) a;" "original" } }
ubyte test_volatileLoad(ubyte *a) { return volatileLoad(a); }
+// { dg-final { scan-tree-dump "\\(volatile ushort \\*\\) a;" "original" } }
ushort test_volatileLoad(ushort *a) { return volatileLoad(a); }
+// { dg-final { scan-tree-dump "\\(volatile uint \\*\\) a;" "original" } }
uint test_volatileLoad(uint *a) { return volatileLoad(a); }
+// { dg-final { scan-tree-dump "\\(volatile ulong \\*\\) a;" "original" } }
ulong test_volatileLoad(ulong *a) { return volatileLoad(a); }
-// { dg-final { scan-tree-dump-not " volatileStore " "original" } }
+// { dg-final { scan-tree-dump "\\(volatile ubyte \\*\\) a = b" "original" } }
void test_volatileStore(ubyte *a, ubyte b) { return volatileStore(a, b); }
+// { dg-final { scan-tree-dump "\\(volatile ushort \\*\\) a = b" "original" } }
void test_volatileStore(ushort *a, ushort b) { return volatileStore(a, b); }
+// { dg-final { scan-tree-dump "\\(volatile uint \\*\\) a = b" "original" } }
void test_volatileStore(uint *a, uint b) { return volatileStore(a, b); }
+// { dg-final { scan-tree-dump "\\(volatile ulong \\*\\) a = b" "original" } }
void test_volatileStore(ulong *a, ulong b) { return volatileStore(a, b); }
-// { dg-final { scan-tree-dump-not " rol " "original" } }
+// { dg-final { scan-tree-dump " a r<< b;" "original" } }
ubyte test_rol(ubyte a, uint b) { return rol!ubyte(a, b); }
+// { dg-final { scan-tree-dump " a r>> 31;" "original" } }
uint test_rol(uint a) { return rol!(1, uint)(a); }
-// { dg-final { scan-tree-dump-not " ror " "original" } }
+// { dg-final { scan-tree-dump " a r>> b;" "original" } }
ushort test_ror(ushort a, uint b) { return ror!ushort(a, b); }
+// { dg-final { scan-tree-dump " a r>> 1;" "original" } }
ulong test_ror(ulong a) { return ror!(1, ulong)(a); }
//////////////////////////////////////////////////////
// core.checkedint
-// { dg-final { scan-tree-dump-not " adds " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = adds " "original" } }
int test_adds(int a, int b, ref bool c) { return adds(a, b, c); }
long test_adds(long a, long b, ref bool c) { return adds(a, b, c); }
-// { dg-final { scan-tree-dump-not " addu " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = addu " "original" } }
uint test_addu(uint a, uint b, ref bool c) { return addu(a, b, c); }
ulong test_addu(ulong a, ulong b, ref bool c) { return addu(a, b, c); }
-// { dg-final { scan-tree-dump-not " subs " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = subs " "original" } }
int test_subs(int a, int b, ref bool c) { return subs(a, b, c); }
long test_subs(long a, long b, ref bool c) { return subs(a, b, c); }
-// { dg-final { scan-tree-dump-not " subu " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = subu " "original" } }
uint test_subu(uint a, uint b, ref bool c) { return subu(a, b, c); }
ulong test_subu(ulong a, ulong b, ref bool c) { return subu(a, b, c); }
-// { dg-final { scan-tree-dump-not " negs " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = negs " "original" } }
int test_negs(int a, ref bool b) { return negs(a, b); }
long test_negs(long a, ref bool b) { return negs(a, b); }
-// { dg-final { scan-tree-dump-not " muls " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = muls " "original" } }
int test_muls(int a, int b, ref bool c) { return muls(a, b, c); }
long test_muls(long a, long b, ref bool c) { return muls(a, b, c); }
-// { dg-final { scan-tree-dump-not " mulu " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = mulu " "original" } }
uint test_mulu(uint a, uint b, ref bool c) { return mulu(a, b, c); }
ulong test_mulu(ulong a, uint b, ref bool c) { return mulu(a, b, c); }
ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); }
@@ -74,50 +86,62 @@ ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); }
//////////////////////////////////////////////////////
// core.math
-// { dg-final { scan-tree-dump-not " cos " "original" } }
+// { dg-final { scan-tree-dump " __builtin_cosf " "original" } }
float test_cos(float a) { return cos(a); }
+// { dg-final { scan-tree-dump " __builtin_cos " "original" } }
double test_cos(double a) { return cos(a); }
+// { dg-final { scan-tree-dump " __builtin_cosl " "original" } }
real test_cos(real a) { return cos(a); }
-// { dg-final { scan-tree-dump-not " sin " "original" } }
+// { dg-final { scan-tree-dump " __builtin_sinf " "original" } }
float test_sin(float a) { return sin(a); }
+// { dg-final { scan-tree-dump " __builtin_sin " "original" } }
double test_sin(double a) { return sin(a); }
+// { dg-final { scan-tree-dump " __builtin_sinl " "original" } }
real test_sin(real a) { return sin(a); }
-// { dg-final { scan-tree-dump-not " rndtol " "original" } }
+// { dg-final { scan-tree-dump " __builtin_llroundf " "original" } }
long test_rndtol(float a) { return rndtol(a); }
+// { dg-final { scan-tree-dump " __builtin_llround " "original" } }
long test_rndtol(double a) { return rndtol(a); }
+// { dg-final { scan-tree-dump " __builtin_llroundl " "original" } }
long test_rndtol(real a) { return rndtol(a); }
-// { dg-final { scan-tree-dump-not " sqrt " "original" } }
+// { dg-final { scan-tree-dump " __builtin_sqrtf " "original" } }
float test_sqrt(float a) { return sqrt(a); }
+// { dg-final { scan-tree-dump " __builtin_sqrt " "original" } }
double test_sqrt(double a) { return sqrt(a); }
+// { dg-final { scan-tree-dump " __builtin_sqrtl " "original" } }
real test_sqrt(real a) { return sqrt(a); }
-// { dg-final { scan-tree-dump-not " ldexp " "original" } }
+// { dg-final { scan-tree-dump " __builtin_ldexpf " "original" } }
float test_ldexp(float a, int b) { return ldexp(a, b); }
+// { dg-final { scan-tree-dump " __builtin_ldexp " "original" } }
double test_ldexp(double a, int b) { return ldexp(a, b); }
+// { dg-final { scan-tree-dump " __builtin_ldexpl " "original" } }
real test_ldexp(real a, int b) { return ldexp(a, b); }
-// { dg-final { scan-tree-dump-not " fabs " "original" } }
+// { dg-final { scan-tree-dump-not " <retval> = fabs " "original" } }
float test_fabs(float a) { return fabs(a); }
double test_fabs(double a) { return fabs(a); }
real test_fabs(real a) { return fabs(a); }
-// { dg-final { scan-tree-dump-not " rint " "original" } }
+// { dg-final { scan-tree-dump " __builtin_rintf " "original" } }
float test_rint(float a) { return rint(a); }
+// { dg-final { scan-tree-dump " __builtin_rint " "original" } }
double test_rint(double a) { return rint(a); }
+// { dg-final { scan-tree-dump " __builtin_rintl " "original" } }
real test_rint(real a) { return rint(a); }
-// { dg-final { scan-tree-dump-not " toPrec " "original" } }
-float test_toPrec(float a) { return toPrec!float(a); }
-float test_toPrec(double a) { return toPrec!float(a); }
-float test_toPrec(real a) { return toPrec!float(a); }
+// { dg-final { scan-tree-dump-not " <retval> = toPrec " "original" } }
+float test_toPrecf(float a) { return toPrec!float(a); }
+float test_toPrecf(double a) { return toPrec!float(a); }
+float test_toPrecf(real a) { return toPrec!float(a); }
double test_toPrec(float a) { return toPrec!double(a); }
double test_toPrec(double a) { return toPrec!double(a); }
double test_toPrec(real a) { return toPrec!double(a); }
-real test_toPrec(float a) { return toPrec!real(a); }
-real test_toPrec(double a) { return toPrec!real(a); }
-real test_toPrec(real a) { return toPrec!real(a); }
+real test_toPrecl(float a) { return toPrec!real(a); }
+real test_toPrecl(double a) { return toPrec!real(a); }
+real test_toPrecl(real a) { return toPrec!real(a); }
//////////////////////////////////////////////////////
// core.stdc.stdarg
// { dg-final { scan-tree-dump-not " va_arg " "original" } }
-void test_va_arg(...) { int a; return va_arg!int(_argptr, a); }
+void test_va_argc(...) { int a; return va_arg!int(_argptr, a); }
int test_va_arg(...) { return va_arg!int(_argptr); }
// { dg-final { scan-tree-dump-not " va_start " "original" } }
void test_va_start(int a, ...) { return va_start(_argptr, a); }
diff --git a/gcc/testsuite/gdc.dg/pr92216.d b/gcc/testsuite/gdc.dg/pr92216.d
index 6a87025..3aff160 100644
--- a/gcc/testsuite/gdc.dg/pr92216.d
+++ b/gcc/testsuite/gdc.dg/pr92216.d
@@ -1,8 +1,8 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92216
// { dg-options "-I $srcdir/gdc.dg" }
// { dg-do compile }
-// { dg-final { scan-assembler "_DT(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv\[: \t\n\]" } }
-// { dg-final { scan-assembler-not "(.globl|.global)\[ \]+_DT(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv" } }
+// { dg-final { scan-assembler "_DTi(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv\[: \t\n\]" } }
+// { dg-final { scan-assembler-not "(.globl|.global)\[ \]+_DTi(4|8|16)_D7imports7pr922161B8__mixin24getSMFZPv" } }
module pr92216;
private import imports.pr92216;
diff --git a/gcc/testsuite/gdc.dg/pr98277.d b/gcc/testsuite/gdc.dg/pr98277.d
new file mode 100644
index 0000000..d3b859f
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr98277.d
@@ -0,0 +1,13 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98277
+// { dg-do compile }
+
+enum Side
+{
+ left,
+ right
+}
+
+ref int getSide(Side side, ref int left, ref int right)
+{
+ return side == Side.left ? left : right;
+}
diff --git a/gcc/testsuite/gdc.dg/pr98427.d b/gcc/testsuite/gdc.dg/pr98427.d
new file mode 100644
index 0000000..225db8b
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr98427.d
@@ -0,0 +1,23 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98427
+// { dg-do compile }
+// { dg-options "-O2 -fno-inline" }
+
+@trusted memoizeExpr()
+{
+ struct CodepointSet
+ {
+ struct CowArray
+ {
+ uint *ptr;
+ }
+
+ const CodepointSet binary(U)(U rhs)
+ {
+ return rhs;
+ }
+
+ CowArray array;
+ }
+
+ CodepointSet().binary(CodepointSet());
+}
diff --git a/gcc/testsuite/gdc.dg/torture/pr97843.d b/gcc/testsuite/gdc.dg/torture/pr97843.d
new file mode 100644
index 0000000..1a417b3
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/torture/pr97843.d
@@ -0,0 +1,37 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97843
+// { dg-additional-options "-fmain -funittest" }
+// { dg-do run }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+struct Sdtor
+{
+ int value;
+ ~this() { }
+}
+
+Sdtor sum(Sdtor[] sdtors)
+{
+ int result;
+ foreach (s; sdtors)
+ result += s.value;
+ return Sdtor(result);
+}
+
+uint sum(uint[] ints)
+{
+ uint result;
+ foreach(i; ints)
+ result += i;
+ return result;
+}
+
+unittest
+{
+ Sdtor[] sdtors = [Sdtor(0), Sdtor(1)];
+ sdtors ~= sum(sdtors);
+ assert(sdtors == [Sdtor(0), Sdtor(1), Sdtor(1)]);
+
+ uint[] ints = [0, 1];
+ ints ~= ints.sum;
+ assert(ints == [0, 1, 1]);
+}
diff --git a/gcc/testsuite/gdc.dg/torture/pr97889.d b/gcc/testsuite/gdc.dg/torture/pr97889.d
new file mode 100644
index 0000000..9135c8f
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/torture/pr97889.d
@@ -0,0 +1,29 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97889
+// { dg-additional-options "-fmain -funittest" }
+// { dg-do run }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+auto cat11ret3(T)(ref T s)
+{
+ s ~= 11;
+ return [3];
+}
+
+unittest
+{
+ static auto test1(int[] val) { val ~= cat11ret3(val); return val; }
+ assert(test1([1]) == [1, 11, 3]);
+ static assert(test1([1]) == [1, 11, 3]);
+
+ static auto test2(int[] val) { val = val ~ cat11ret3(val); return val; }
+ // FIXME: assert(test2([1]) == [1, 3]);
+ static assert(test2([1]) == [1, 3]);
+
+ static auto test3(int[] val) { (val ~= 7) ~= cat11ret3(val); return val; }
+ assert(test3([2]) == [2, 7, 11, 3]);
+ static assert(test3([2]) == [2, 7, 11, 3]);
+
+ static auto test4(int[] val) { (val ~= cat11ret3(val)) ~= 7; return val; }
+ assert(test4([2]) == [2, 11, 3, 7]);
+ static assert(test4([2]) == [2, 11, 3, 7]);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/callconv.d b/gcc/testsuite/gdc.test/compilable/callconv.d
index fbb78ed..145ebb1 100644
--- a/gcc/testsuite/gdc.test/compilable/callconv.d
+++ b/gcc/testsuite/gdc.test/compilable/callconv.d
@@ -11,24 +11,6 @@ ABC abc;
int x,y,z;
-extern (Pascal):
-ABC test1(int xx, int yy, int zz)
-{
- x = xx;
- y = yy;
- z = zz;
- return abc;
-}
-
-extern (Pascal):
-ABC test1v(int xx, int yy, int zz, ...)
-{
- x = xx;
- y = yy;
- z = zz;
- return abc;
-}
-
extern (C):
ABC test2v(int xx, int yy, int zz, ...)
{
@@ -71,5 +53,3 @@ ABC test4v(int xx, int yy, int zz, ...)
z = zz;
return abc;
}
-
-
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21299/func.d b/gcc/testsuite/gdc.test/compilable/imports/test21299/func.d
new file mode 100644
index 0000000..fe3321f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21299/func.d
@@ -0,0 +1,8 @@
+module imports.test21299.func;
+import imports.test21299.mtype;
+import imports.test21299.rootstringtable;
+class FuncDeclaration {
+ StringTable!Type stringtable;
+ StringTable2!Type stringtable2;
+ StringTable3!Type stringtable3;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d b/gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d
new file mode 100644
index 0000000..01bac82
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d
@@ -0,0 +1,8 @@
+module imports.test21299.mtype;
+import imports.test21299.func;
+import imports.test21299.rootstringtable;
+class Type {
+ StringTable!Type stringtable;
+ StringTable2!Type stringtable2;
+ StringTable3!Type stringtable3;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d b/gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d
new file mode 100644
index 0000000..12a2d92
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d
@@ -0,0 +1,96 @@
+module imports.test21299.rootstringtable;
+struct StringValue(T)
+{
+ char* lstring()
+ {
+ return cast(char*)&this;
+ }
+}
+
+struct StringTable(T)
+{
+ StringValue!T* insert()
+ {
+ allocValue;
+ return getValue;
+ }
+
+ uint allocValue()
+ {
+ StringValue!(T) sv;
+ sv.lstring[0] = 0;
+ return 0;
+ }
+
+ StringValue!T* getValue()
+ {
+ return cast(StringValue!T*)&this;
+ }
+}
+
+// Other tests are the same as the original issue, but use other kinds of
+// nesting Dsymbols that need to be handled by templateInstanceSemantic().
+struct StringValue2(T)
+{
+ char* lstring()
+ {
+ return cast(char*)&this;
+ }
+}
+
+struct StringTable2(T)
+{
+ @nogc // AttribDeclaration (also covers pragma, extern(), static foreach, ...)
+ {
+ StringValue2!T* insert()
+ {
+ allocValue;
+ return getValue;
+ }
+
+ uint allocValue()
+ {
+ StringValue2!(T) sv;
+ sv.lstring[0] = 0;
+ return 0;
+ }
+
+ StringValue2!T* getValue()
+ {
+ return cast(StringValue2!T*)&this;
+ }
+ }
+}
+
+//
+struct StringValue3(T)
+{
+ char* lstring()
+ {
+ return cast(char*)&this;
+ }
+}
+
+struct StringTable3(T)
+{
+ static if (true) // ConditionalDeclaration (static if)
+ {
+ StringValue3!T* insert()
+ {
+ allocValue;
+ return getValue;
+ }
+
+ uint allocValue()
+ {
+ StringValue3!(T) sv;
+ sv.lstring[0] = 0;
+ return 0;
+ }
+
+ StringValue3!T* getValue()
+ {
+ return cast(StringValue3!T*)&this;
+ }
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test17419.d b/gcc/testsuite/gdc.test/compilable/test17419.d
index d67c5b9..295c563 100644
--- a/gcc/testsuite/gdc.test/compilable/test17419.d
+++ b/gcc/testsuite/gdc.test/compilable/test17419.d
@@ -10,14 +10,12 @@ static assert(__traits(getLinkage, aliasc) == "C");
extern (D) int food();
extern (C++) int foocpp();
extern (Windows) int foow();
-extern (Pascal) int foop();
extern (Objective-C) int fooobjc();
extern (System) int foos();
static assert(__traits(getLinkage, food) == "D");
static assert(__traits(getLinkage, foocpp) == "C++");
static assert(__traits(getLinkage, foow) == "Windows");
-static assert(__traits(getLinkage, foop) == "Pascal");
static assert(__traits(getLinkage, fooobjc) == "Objective-C");
version (Windows)
static assert(__traits(getLinkage, foos) == "Windows");
diff --git a/gcc/testsuite/gdc.test/compilable/test21299a.d b/gcc/testsuite/gdc.test/compilable/test21299a.d
new file mode 100644
index 0000000..049ee6a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21299a.d
@@ -0,0 +1,4 @@
+// EXTRA_SOURCES: imports/test21299/mtype.d imports/test21299/rootstringtable.d
+// REQUIRED_ARGS: -main
+// LINK
+module test21299a;
diff --git a/gcc/testsuite/gdc.test/compilable/test21299b.d b/gcc/testsuite/gdc.test/compilable/test21299b.d
new file mode 100644
index 0000000..b9d992a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21299b.d
@@ -0,0 +1,4 @@
+// EXTRA_SOURCES: imports/test21299/func.d imports/test21299/rootstringtable.d
+// REQUIRED_ARGS: -main
+// LINK:
+module test21299b;
diff --git a/gcc/testsuite/gdc.test/compilable/test21299c.d b/gcc/testsuite/gdc.test/compilable/test21299c.d
new file mode 100644
index 0000000..88ed21f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21299c.d
@@ -0,0 +1,5 @@
+// EXTRA_SOURCES: imports/test21299/mtype.d imports/test21299/func.d imports/test21299/rootstringtable.d
+// COMPILE_SEPARATELY:
+// LINK:
+module test21299c;
+void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/test21299d.d b/gcc/testsuite/gdc.test/compilable/test21299d.d
new file mode 100644
index 0000000..67ec60a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21299d.d
@@ -0,0 +1,27 @@
+// REQUIRED_ARGS: -main
+// LINK:
+module test21299d;
+
+struct DefaultPredicates
+{
+ struct IsEqual(T)
+ {
+ static opCall(in T, in T)
+ {
+ return 0;
+ }
+ }
+}
+
+void moveToEnd(T, Pred = DefaultPredicates.IsEqual!T)(T[] array, T element, Pred pred = Pred.init)
+{
+ pred(array[0], element);
+}
+
+class Task
+{
+ void removeTerminationHook(void delegate() hook)
+ {
+ moveToEnd([], hook);
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testInference.d b/gcc/testsuite/gdc.test/compilable/testInference.d
index 95f4fcb..5a8e1e2 100644
--- a/gcc/testsuite/gdc.test/compilable/testInference.d
+++ b/gcc/testsuite/gdc.test/compilable/testInference.d
@@ -261,11 +261,13 @@ void test8234()
/***************************************************/
// 8504
+import core.demangle : demangle;
+
void foo8504()()
{
static assert(typeof(foo8504!()).stringof == "void()");
static assert(typeof(foo8504!()).mangleof == "FZv");
- static assert(foo8504!().mangleof == "_D13testInference12__T7foo8504Z7foo8504FZv");
+ static assert(demangle(foo8504!().mangleof) == "void testInference.foo8504!().foo8504()");
}
auto toDelegate8504a(F)(auto ref F fp) { return fp; }
@@ -277,7 +279,7 @@ void test8504()
{
static assert(typeof(foo8504!()).stringof == "pure nothrow @nogc @safe void()");
static assert(typeof(foo8504!()).mangleof == "FNaNbNiNfZv");
- static assert(foo8504!().mangleof == "_D13testInference12__T7foo8504Z7foo8504FNaNbNiNfZv");
+ static assert(demangle(foo8504!().mangleof) == "pure nothrow @nogc @safe void testInference.foo8504!().foo8504()");
auto fp1 = toDelegate8504a(&testC8504);
auto fp2 = toDelegate8504b(&testC8504);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12485.d b/gcc/testsuite/gdc.test/fail_compilation/fail12485.d
index 71f8698..e1b1577 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12485.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail12485.d
@@ -1,11 +1,12 @@
void dorecursive()
{
- recursive([0]);
+ recursive!"ratherLongSymbolNameToHitTheMaximumSymbolLengthEarlierThanTheTemplateRecursionLimit_";
}
-void recursive(R)(R r)
+void recursive(string name)()
{
- import std.algorithm;
- recursive( r.filter!(e=>true) );
+ struct S {} // define type to kick off mangler
+ static if (name.length <= (4 << 20))
+ recursive!(name ~ name);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
new file mode 100644
index 0000000..0ec53c8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
@@ -0,0 +1,37 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail18970.d(22): Error: no property `y` for type `S`
+fail_compilation/fail18970.d(29): Error: no property `yyy` for type `S2`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=18970
+
+struct S
+{
+ auto opDispatch(string name)(int)
+ {
+ alias T = typeof(x);
+ static assert(!is(T.U));
+ return 0;
+ }
+}
+void f()
+{
+ S().y(1);
+}
+
+struct S2
+{
+ this(int)
+ {
+ this.yyy;
+ }
+
+ auto opDispatch(string name)()
+ {
+ alias T = typeof(x);
+ static if(is(T.U)) {}
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test21164a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164a.d
new file mode 100644
index 0000000..e5fcd43
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164a.d
@@ -0,0 +1,9 @@
+struct D(E)
+{
+ void G() {
+ import imports.test21164d;
+ I;
+ }
+
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test21164b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164b.d
new file mode 100644
index 0000000..ece5476
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164b.d
@@ -0,0 +1,4 @@
+import imports.test21164c;
+enum N = O();
+alias Q = R!(N, S);
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test21164c.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164c.d
new file mode 100644
index 0000000..21a252f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164c.d
@@ -0,0 +1,10 @@
+enum S = 1;
+
+struct O
+{
+}
+
+struct R(O U, int W)
+{
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test21164d.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164d.d
new file mode 100644
index 0000000..08f83ea
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test21164d.d
@@ -0,0 +1,9 @@
+auto AB()
+{
+static if}
+
+auto I()
+{
+AB;
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21164.d b/gcc/testsuite/gdc.test/fail_compilation/test21164.d
new file mode 100644
index 0000000..f42c4bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21164.d
@@ -0,0 +1,13 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/imports/test21164d.d(3): Error: (expression) expected following `static if`
+fail_compilation/imports/test21164d.d(3): Error: found `}` instead of statement
+fail_compilation/test21164.d(11): Error: template instance `test21164a.D!(R!(O(), 1))` error instantiating
+---
+*/
+import imports.test21164a;
+import imports.test21164b;
+auto GB(D!Q)
+{
+}
diff --git a/gcc/testsuite/gdc.test/runnable/dhry.d b/gcc/testsuite/gdc.test/runnable/dhry.d
deleted file mode 100644
index 40f9ccff..0000000
--- a/gcc/testsuite/gdc.test/runnable/dhry.d
+++ /dev/null
@@ -1,927 +0,0 @@
-// PERMUTE_ARGS:
-// REQUIRED_ARGS: -release -O -g -inline
-// DISABLED: freebsd
-
-/*
- *************************************************************************
- *
- * "DHRYSTONE" Benchmark Program
- * -----------------------------
- *
- * Version: C, Version 2.1
- *
- * File: dhry.h (part 1 of 3)
- *
- * Date: May 25, 1988
- *
- * Author: Reinhold P. Weicker
- * Siemens Nixdorf Inf. Syst.
- * STM OS 32
- * Otto-Hahn-Ring 6
- * W-8000 Muenchen 83
- * Germany
- * Phone: [+49]-89-636-42436
- * (8-17 Central European Time)
- * UUCP: weicker@ztivax.uucp@unido.uucp
- * Internet: weicker@ztivax.siemens.com
- *
- * Original Version (in Ada) published in
- * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
- * pp. 1013 - 1030, together with the statistics
- * on which the distribution of statements etc. is based.
- *
- * In this C version, the following C library functions are
- * used:
- * - strcpy, strcmp (inside the measurement loop)
- * - printf, scanf (outside the measurement loop)
- *
- * Collection of Results:
- * Reinhold Weicker (address see above) and
- *
- * Rick Richardson
- * PC Research. Inc.
- * 94 Apple Orchard Drive
- * Tinton Falls, NJ 07724
- * Phone: (201) 834-1378 (9-17 EST)
- * UUCP: ...!uunet!pcrat!rick
- *
- * Please send results to Rick Richardson and/or Reinhold Weicker.
- * Complete information should be given on hardware and software
- * used. Hardware information includes: Machine type, CPU, type and
- * size of caches; for microprocessors: clock frequency, memory speed
- * (number of wait states). Software information includes: Compiler
- * (and runtime library) manufacturer and version, compilation
- * switches, OS version. The Operating System version may give an
- * indication about the compiler; Dhrystone itself performs no OS
- * calls in the measurement loop.
- *
- * The complete output generated by the program should be mailed
- * such that at least some checks for correctness can be made.
- *
- *************************************************************************
- *
- * History: This version C/2.1 has been made for two reasons:
- *
- * 1) There is an obvious need for a common C version of
- * Dhrystone, since C is at present the most popular system
- * programming language for the class of processors
- * (microcomputers, minicomputers) where Dhrystone is used
- * most. There should be, as far as possible, only one C
- * version of Dhrystone such that results can be compared
- * without restrictions. In the past, the C versions
- * distributed by Rick Richardson (Version 1.1) and by
- * Reinhold Weicker had small (though not significant)
- * differences.
- *
- * 2) As far as it is possible without changes to the
- * Dhrystone statistics, optimizing compilers should be
- * prevented from removing significant statements.
- *
- * This C version has been developed in cooperation with
- * Rick Richardson (Tinton Falls, NJ), it incorporates many
- * ideas from the "Version 1.1" distributed previously by
- * him over the UNIX network Usenet.
- * I also thank Chaim Benedelac (National Semiconductor),
- * David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
- * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
- * for their help with comments on earlier versions of the
- * benchmark.
- *
- * Changes: In the initialization part, this version follows mostly
- * Rick Richardson's version distributed via Usenet, not the
- * version distributed earlier via floppy disk by Reinhold
- * Weicker. As a concession to older compilers, names have
- * been made unique within the first 8 characters. Inside the
- * measurement loop, this version follows the version
- * previously distributed by Reinhold Weicker.
- *
- * At several places in the benchmark, code has been added,
- * but within the measurement loop only in branches that
- * are not executed. The intention is that optimizing
- * compilers should be prevented from moving code out of the
- * measurement loop, or from removing code altogether. Since
- * the statements that are executed within the measurement
- * loop have NOT been changed, the numbers defining the
- * "Dhrystone distribution" (distribution of statements,
- * operand types and locality) still hold. Except for
- * sophisticated optimizing compilers, execution times for
- * this version should be the same as for previous versions.
- *
- * Since it has proven difficult to subtract the time for the
- * measurement loop overhead in a correct way, the loop check
- * has been made a part of the benchmark. This does have
- * an impact - though a very minor one - on the distribution
- * statistics which have been updated for this version.
- *
- * All changes within the measurement loop are described
- * and discussed in the companion paper "Rationale for
- * Dhrystone version 2".
- *
- * Because of the self-imposed limitation that the order and
- * distribution of the executed statements should not be
- * changed, there are still cases where optimizing compilers
- * may not generate code for some statements. To a certain
- * degree, this is unavoidable for small synthetic
- * benchmarks. Users of the benchmark are advised to check
- * code listings whether code is generated for all statements
- * of Dhrystone.
- *
- * Version 2.1 is identical to version 2.0 distributed via
- * the UNIX network Usenet in March 1988 except that it
- * corrects some minor deficiencies that were found by users
- * of version 2.0. The only change within the measurement
- * loop is that a non-executed "else" part was added to the
- * "if" statement in Func_3, and a non-executed "else" part
- * removed from Proc_3.
- *
- *************************************************************************
- *
- * Defines: The following "Defines" are possible:
- * -DROPT (default: Not defined)
- * As an approximation to what an average C
- * programmer might do, the "register" storage class
- * is applied (if enabled by -DROPT)
- * - for local variables, if they are used
- * (dynamically) five or more times
- * - for parameters if they are used (dynamically)
- * six or more times
- * Note that an optimal "register" strategy is
- * compiler-dependent, and that "register"
- * declarations do not necessarily lead to faster
- * execution.
- * -DNOSTRUCTASSIGN (default: Not defined)
- * Define if the C compiler does not support
- * assignment of structures.
- * -DNOENUMS (default: Not defined)
- * Define if the C compiler does not support
- * enumeration types.
- *
- *************************************************************************
- *
- * Compilation model and measurement (IMPORTANT):
- *
- * This C version of Dhrystone consists of three files:
- * - dhry.h (this file, containing global definitions and comments)
- * - dhry_1.c (containing the code corresponding to Ada package Pack_1)
- * - dhry_2.c (containing the code corresponding to Ada package Pack_2)
- *
- * The following "ground rules" apply for measurements:
- * - Separate compilation
- * - No procedure merging
- * - Otherwise, compiler optimizations are allowed but should be
- * indicated
- * - Default results are those without register declarations
- * See the companion paper "Rationale for Dhrystone Version 2" for a more
- * detailed discussion of these ground rules.
- *
- * For 16-Bit processors (e.g. 80186, 80286), times for all compilation
- * models ("small", "medium", "large" etc.) should be given if possible,
- * together with a definition of these models for the compiler system
- * used.
- *
- *************************************************************************
- *
- * Dhrystone (C version) statistics:
- *
- * [Comment from the first distribution, updated for version 2.
- * Note that because of language differences, the numbers are slightly
- * different from the Ada version.]
- *
- * The following program contains statements of a high level programming
- * language (here: C) in a distribution considered representative:
- *
- * assignments 52 (51.0 %)
- * control statements 33 (32.4 %)
- * procedure, function calls 17 (16.7 %)
- *
- * 103 statements are dynamically executed. The program is balanced with
- * respect to the three aspects:
- *
- * - statement type
- * - operand type
- * - operand locality
- * operand global, local, parameter, or constant.
- *
- * The combination of these three aspects is balanced only approximately.
- *
- * 1. Statement Type:
- * ----------------- number
- *
- * V1 = V2 9
- * (incl. V1 = F(..)
- * V = Constant 12
- * Assignment, 7
- * with array element
- * Assignment, 6
- * with record component
- * --
- * 34 34
- *
- * X = Y +|-|"&&"|"|" Z 5
- * X = Y +|-|"==" Constant 6
- * X = X +|- 1 3
- * X = Y *|/ Z 2
- * X = Expression, 1
- * two operators
- * X = Expression, 1
- * three operators
- * --
- * 18 18
- *
- * if .... 14
- * with "else" 7
- * without "else" 7
- * executed 3
- * not executed 4
- * for ... 7 | counted every time
- * while ... 4 | the loop condition
- * do ... while 1 | is evaluated
- * switch ... 1
- * break 1
- * declaration with 1
- * initialization
- * --
- * 34 34
- *
- * P (...) procedure call 11
- * user procedure 10
- * library procedure 1
- * X = F (...)
- * function call 6
- * user function 5
- * library function 1
- * --
- * 17 17
- * ---
- * 103
- *
- * The average number of parameters in procedure or function calls
- * is 1.82 (not counting the function values as implicit parameters).
- *
- *
- * 2. Operators
- * ------------
- * number approximate
- * percentage
- *
- * Arithmetic 32 50.8
- *
- * + 21 33.3
- * - 7 11.1
- * * 3 4.8
- * / (int div) 1 1.6
- *
- * Comparison 27 42.8
- *
- * == 9 14.3
- * /= 4 6.3
- * > 1 1.6
- * < 3 4.8
- * >= 1 1.6
- * <= 9 14.3
- *
- * Logic 4 6.3
- *
- * && (AND-THEN) 1 1.6
- * | (OR) 1 1.6
- * ! (NOT) 2 3.2
- *
- * -- -----
- * 63 100.1
- *
- *
- * 3. Operand Type (counted once per operand reference):
- * ---------------
- * number approximate
- * percentage
- *
- * Integer 175 72.3 %
- * Character 45 18.6 %
- * Pointer 12 5.0 %
- * String30 6 2.5 %
- * Array 2 0.8 %
- * Record 2 0.8 %
- * --- -------
- * 242 100.0 %
- *
- * When there is an access path leading to the final operand (e.g. a
- * record component), only the final data type on the access path is
- * counted.
- *
- *
- * 4. Operand Locality:
- * -------------------
- * number approximate
- * percentage
- *
- * local variable 114 47.1 %
- * global variable 22 9.1 %
- * parameter 45 18.6 %
- * value 23 9.5 %
- * reference 22 9.1 %
- * function result 6 2.5 %
- * constant 55 22.7 %
- * --- -------
- * 242 100.0 %
- *
- *
- * The program does not compute anything meaningful, but it is
- * syntactically and semantically correct. All variables have a value
- * assigned to them before they are used as a source operand.
- *
- * There has been no explicit effort to account for the effects of a
- * cache, or to balance the use of long or short displacements for code
- * or data.
- *
- *************************************************************************
- */
-
-import core.stdc.stdio;
-import core.stdc.string;
-import core.stdc.stdlib;
-import std.string;
-
-
-/* Compiler and system dependent definitions: */
-
-const double Mic_secs_Per_Second = 1000000.0;
- /* Berkeley UNIX C returns process times in seconds/HZ */
-
-enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
-alias int Enumeration;
- /* for boolean and enumeration types in Ada, Pascal */
-
-/* General definitions: */
-
-const int StrLen = 30;
-
-alias int One_Thirty;
-alias int One_Fifty;
-alias char Capital_Letter;
-alias bool Boolean;
-alias char Str_30 [StrLen];
-alias int Arr_1_Dim [50];
-alias int Arr_2_Dim [50] [50];
-
-struct record
-{
- record *Ptr_Comp;
- Enumeration Discr;
- union V {
- struct V1 {
- Enumeration Enum_Comp;
- int Int_Comp;
- char Str_Comp [StrLen];
- }
- V1 var_1;
- struct V2 {
- Enumeration E_Comp_2;
- char Str_2_Comp [StrLen];
- }
- V2 var_2;
- struct V3 {
- char Ch_1_Comp;
- char Ch_2_Comp;
- }
- V3 var_3;
- }
- V variant;
-}
-
-alias record Rec_Type;
-alias record *Rec_Pointer;
-
-
-/* Global Variables: */
-
-Rec_Pointer Ptr_Glob,
- Next_Ptr_Glob;
-int Int_Glob;
-Boolean Bool_Glob;
-char Ch_1_Glob,
- Ch_2_Glob;
-int Arr_1_Glob [50];
-int Arr_2_Glob [50] [50];
-
-char[StrLen] Reg_Define = "Register option selected.";
-
-/* variables for time measurement: */
-
-const int Too_Small_Time = 2;
- /* Measurements should last at least 2 seconds */
-
-double Begin_Time,
- End_Time,
- User_Time;
-
-double Microseconds,
- Dhrystones_Per_Second,
- Vax_Mips;
-
-/* end of variables for time measurement */
-
-
-void main ()
-/*****/
-
- /* main program, corresponds to procedures */
- /* Main and Proc_0 in the Ada version */
-{
- One_Fifty Int_1_Loc;
- One_Fifty Int_2_Loc;
- One_Fifty Int_3_Loc;
- char Ch_Index;
- Enumeration Enum_Loc;
- Str_30 Str_1_Loc;
- Str_30 Str_2_Loc;
- int Run_Index;
- int Number_Of_Runs;
-
-/+
- FILE *Ap;
-
- /* Initializations */
-
- if ((Ap = fopen("dhry.res","a+")) == null)
- {
- printf("Can not open dhry.res\n\n");
- exit(1);
- }
-+/
-
- Next_Ptr_Glob = cast(Rec_Pointer) malloc (Rec_Type.sizeof);
- Ptr_Glob = cast(Rec_Pointer) malloc (Rec_Type.sizeof);
-
- Ptr_Glob.Ptr_Comp = Next_Ptr_Glob;
- Ptr_Glob.Discr = Ident_1;
- Ptr_Glob.variant.var_1.Enum_Comp = Ident_3;
- Ptr_Glob.variant.var_1.Int_Comp = 40;
-// strcpy (Ptr_Glob.variant.var_1.Str_Comp,
-// "DHRYSTONE PROGRAM, SOME STRING");
-// strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
- Ptr_Glob.variant.var_1.Str_Comp[] = "DHRYSTONE PROGRAM, SOME STRING";
- Str_1_Loc[] = "DHRYSTONE PROGRAM, 1'ST STRING";
-
- Arr_2_Glob [8][7] = 10;
- /* Was missing in published program. Without this statement, */
- /* Arr_2_Glob [8][7] would have an undefined value. */
- /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
- /* overflow may occur for this array element. */
-
- printf ("\n");
- printf ("Dhrystone Benchmark, Version 2.1 (Language: D)\n");
- printf ("\n");
- printf ("Please give the number of runs through the benchmark: ");
- {
- int n;
- //scanf ("%d", &n);
- n = 10000000;
- Number_Of_Runs = n;
- }
- printf ("\n");
-
- printf ("Execution starts, %d runs through Dhrystone\n",Number_Of_Runs);
-
- /***************/
- /* Start timer */
- /***************/
-
- Begin_Time = dtime();
-
- for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
- {
-
- Proc_5();
- Proc_4();
- /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
- Int_1_Loc = 2;
- Int_2_Loc = 3;
- //strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
- Str_2_Loc[] = "DHRYSTONE PROGRAM, 2'ND STRING";
- Enum_Loc = Ident_2;
- Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
- /* Bool_Glob == 1 */
- while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
- {
- Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
- /* Int_3_Loc == 7 */
- Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
- /* Int_3_Loc == 7 */
- Int_1_Loc += 1;
- } /* while */
- /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
- Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
- /* Int_Glob == 5 */
- Proc_1 (Ptr_Glob);
- for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
- /* loop body executed twice */
- {
- if (Enum_Loc == Func_1 (Ch_Index, 'C'))
- /* then, not executed */
- {
- Proc_6 (Ident_1, &Enum_Loc);
- //strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
- Str_2_Loc[] = "DHRYSTONE PROGRAM, 3'RD STRING";
- Int_2_Loc = Run_Index;
- Int_Glob = Run_Index;
- }
- }
- /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
- Int_2_Loc = Int_2_Loc * Int_1_Loc;
- Int_1_Loc = Int_2_Loc / Int_3_Loc;
- Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
- /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
- Proc_2 (&Int_1_Loc);
- /* Int_1_Loc == 5 */
-
- } /* loop "for Run_Index" */
-
- /**************/
- /* Stop timer */
- /**************/
-
- End_Time = dtime();
-
- printf ("Execution ends\n");
- printf ("\n");
- printf ("Final values of the variables used in the benchmark:\n");
- printf ("\n");
- printf ("Int_Glob: %d\n", Int_Glob);
- printf (" should be: %d\n", 5);
- printf ("Bool_Glob: %d\n", Bool_Glob);
- printf (" should be: %d\n", 1);
- printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
- printf (" should be: %c\n", cast(int)'A');
- printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
- printf (" should be: %c\n", cast(int)'B');
- printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
- printf (" should be: %d\n", 7);
- printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
- printf (" should be: Number_Of_Runs + 10\n");
- printf ("Ptr_Glob.\n");
- printf (" Ptr_Comp: %d\n", cast(int) Ptr_Glob.Ptr_Comp);
- printf (" should be: (implementation-dependent)\n");
- printf (" Discr: %d\n", Ptr_Glob.Discr);
- printf (" should be: %d\n", 0);
- printf (" Enum_Comp: %d\n", Ptr_Glob.variant.var_1.Enum_Comp);
- printf (" should be: %d\n", 2);
- printf (" Int_Comp: %d\n", Ptr_Glob.variant.var_1.Int_Comp);
- printf (" should be: %d\n", 17);
- printf (" Str_Comp: %.*s\n", Ptr_Glob.variant.var_1.Str_Comp.length, Ptr_Glob.variant.var_1.Str_Comp.ptr);
- printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
- printf ("Next_Ptr_Glob.\n");
- printf (" Ptr_Comp: %d\n", cast(int) Next_Ptr_Glob.Ptr_Comp);
- printf (" should be: (implementation-dependent), same as above\n");
- printf (" Discr: %d\n", Next_Ptr_Glob.Discr);
- printf (" should be: %d\n", 0);
- printf (" Enum_Comp: %d\n", Next_Ptr_Glob.variant.var_1.Enum_Comp);
- printf (" should be: %d\n", 1);
- printf (" Int_Comp: %d\n", Next_Ptr_Glob.variant.var_1.Int_Comp);
- printf (" should be: %d\n", 18);
- printf (" Str_Comp: %.*s\n", Next_Ptr_Glob.variant.var_1.Str_Comp.length, Next_Ptr_Glob.variant.var_1.Str_Comp.ptr);
- printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
- printf ("Int_1_Loc: %d\n", Int_1_Loc);
- printf (" should be: %d\n", 5);
- printf ("Int_2_Loc: %d\n", Int_2_Loc);
- printf (" should be: %d\n", 13);
- printf ("Int_3_Loc: %d\n", Int_3_Loc);
- printf (" should be: %d\n", 7);
- printf ("Enum_Loc: %d\n", Enum_Loc);
- printf (" should be: %d\n", 1);
- printf ("Str_1_Loc: %.*s\n", Str_1_Loc.length, Str_1_Loc.ptr);
- printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
- printf ("Str_2_Loc: %.*s\n", Str_2_Loc.length, Str_2_Loc.ptr);
- printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
- printf ("\n");
-
- User_Time = End_Time - Begin_Time;
-
- if (User_Time < Too_Small_Time)
- {
- printf ("Measured time too small to obtain meaningful results\n");
- printf ("Please increase number of runs\n");
- printf ("\n");
- }
- else
- {
- Microseconds = User_Time * Mic_secs_Per_Second
- / cast(double) Number_Of_Runs;
- Dhrystones_Per_Second = cast(double) Number_Of_Runs / User_Time;
- Vax_Mips = Dhrystones_Per_Second / 1757.0;
-
- printf ("Register option selected? NO\n");
- strcpy(Reg_Define.ptr, "Register option not selected.");
- printf ("Microseconds for one run through Dhrystone: ");
- printf ("%7.1lf \n", Microseconds);
- printf ("Dhrystones per Second: ");
- printf ("%10.1lf \n", Dhrystones_Per_Second);
- printf ("VAX MIPS rating = %10.3lf \n",Vax_Mips);
- printf ("\n");
-
- /+
- fprintf(Ap,"\n");
- fprintf(Ap,"Dhrystone Benchmark, Version 2.1 (Language: D)\n");
- fprintf(Ap,"%.*s\n",Reg_Define.length, Reg_Define.ptr);
- fprintf(Ap,"Microseconds for one loop: %7.1lf\n",Microseconds);
- fprintf(Ap,"Dhrystones per second: %10.1lf\n",Dhrystones_Per_Second);
- fprintf(Ap,"VAX MIPS rating: %10.3lf\n",Vax_Mips);
- fclose(Ap);
- +/
-
- }
-
-}
-
-void Proc_1 (Rec_Pointer Ptr_Val_Par)
-/******************/
-
- /* executed once */
-{
- Rec_Pointer Next_Record = Ptr_Val_Par.Ptr_Comp;
- /* == Ptr_Glob_Next */
- /* Local variable, initialized with Ptr_Val_Par.Ptr_Comp, */
- /* corresponds to "rename" in Ada, "with" in Pascal */
-
- *Ptr_Val_Par.Ptr_Comp = *Ptr_Glob;
- Ptr_Val_Par.variant.var_1.Int_Comp = 5;
- Next_Record.variant.var_1.Int_Comp
- = Ptr_Val_Par.variant.var_1.Int_Comp;
- Next_Record.Ptr_Comp = Ptr_Val_Par.Ptr_Comp;
- Proc_3 (&Next_Record.Ptr_Comp);
- /* Ptr_Val_Par.Ptr_Comp.Ptr_Comp
- == Ptr_Glob.Ptr_Comp */
- if (Next_Record.Discr == Ident_1)
- /* then, executed */
- {
- Next_Record.variant.var_1.Int_Comp = 6;
- Proc_6 (Ptr_Val_Par.variant.var_1.Enum_Comp,
- &Next_Record.variant.var_1.Enum_Comp);
- Next_Record.Ptr_Comp = Ptr_Glob.Ptr_Comp;
- Proc_7 (Next_Record.variant.var_1.Int_Comp, 10,
- &Next_Record.variant.var_1.Int_Comp);
- }
- else /* not executed */
- *Ptr_Val_Par = *Ptr_Val_Par.Ptr_Comp;
-} /* Proc_1 */
-
-void Proc_2 (One_Fifty *Int_Par_Ref)
-/******************/
- /* executed once */
- /* *Int_Par_Ref == 1, becomes 4 */
-{
- One_Fifty Int_Loc;
- Enumeration Enum_Loc;
-
- Int_Loc = *Int_Par_Ref + 10;
- do /* executed once */
- if (Ch_1_Glob == 'A')
- /* then, executed */
- {
- Int_Loc -= 1;
- *Int_Par_Ref = Int_Loc - Int_Glob;
- Enum_Loc = Ident_1;
- } /* if */
- while (Enum_Loc != Ident_1); /* true */
-} /* Proc_2 */
-
-
-void Proc_3 (Rec_Pointer *Ptr_Ref_Par)
-/******************/
- /* executed once */
- /* Ptr_Ref_Par becomes Ptr_Glob */
-
-{
- if (Ptr_Glob != null)
- /* then, executed */
- *Ptr_Ref_Par = Ptr_Glob.Ptr_Comp;
- Proc_7 (10, Int_Glob, &Ptr_Glob.variant.var_1.Int_Comp);
-} /* Proc_3 */
-
-void Proc_4 () /* without parameters */
-/*******/
- /* executed once */
-{
- Boolean Bool_Loc;
-
- Bool_Loc = Ch_1_Glob == 'A';
- Bool_Glob = Bool_Loc | Bool_Glob;
- Ch_2_Glob = 'B';
-} /* Proc_4 */
-
-
-void Proc_5 () /* without parameters */
-/*******/
- /* executed once */
-{
- Ch_1_Glob = 'A';
- Bool_Glob = false;
-} /* Proc_5 */
-
-
-void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
-/*********************************/
- /* executed once */
- /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
-{
- *Enum_Ref_Par = Enum_Val_Par;
- if (! Func_3 (Enum_Val_Par))
- /* then, not executed */
- *Enum_Ref_Par = Ident_4;
- final switch (Enum_Val_Par)
- {
- case Ident_1:
- *Enum_Ref_Par = Ident_1;
- break;
- case Ident_2:
- if (Int_Glob > 100)
- /* then */
- *Enum_Ref_Par = Ident_1;
- else *Enum_Ref_Par = Ident_4;
- break;
- case Ident_3: /* executed */
- *Enum_Ref_Par = Ident_2;
- break;
- case Ident_4: break;
- case Ident_5:
- *Enum_Ref_Par = Ident_3;
- break;
- } /* switch */
-} /* Proc_6 */
-
-
-void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
-/**********************************************/
- /* executed three times */
- /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
- /* Int_Par_Ref becomes 7 */
- /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
- /* Int_Par_Ref becomes 17 */
- /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
- /* Int_Par_Ref becomes 18 */
-{
- One_Fifty Int_Loc;
-
- Int_Loc = Int_1_Par_Val + 2;
- *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
-} /* Proc_7 */
-
-
-void Proc_8 (ref Arr_1_Dim Arr_1_Par_Ref, ref Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
-/*********************************************************************/
- /* executed once */
- /* Int_Par_Val_1 == 3 */
- /* Int_Par_Val_2 == 7 */
-{
- One_Fifty Int_Index;
- One_Fifty Int_Loc;
-
- Int_Loc = Int_1_Par_Val + 5;
- Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
- Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
- Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
- for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
- Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
- Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
- Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
- Int_Glob = 5;
-} /* Proc_8 */
-
-
-Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
-/*************************************************/
- /* executed three times */
- /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
- /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
- /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
-{
- Capital_Letter Ch_1_Loc;
- Capital_Letter Ch_2_Loc;
-
- Ch_1_Loc = Ch_1_Par_Val;
- Ch_2_Loc = Ch_1_Loc;
- if (Ch_2_Loc != Ch_2_Par_Val)
- /* then, executed */
- return (Ident_1);
- else /* not executed */
- {
- Ch_1_Glob = Ch_1_Loc;
- return (Ident_2);
- }
-} /* Func_1 */
-
-
-Boolean Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
-/*************************************************/
- /* executed once */
- /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
- /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
-{
- One_Thirty Int_Loc;
- Capital_Letter Ch_Loc;
-
- Int_Loc = 2;
- while (Int_Loc <= 2) /* loop body executed once */
- if (Func_1 (Str_1_Par_Ref[Int_Loc],
- Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
- /* then, executed */
- {
- Ch_Loc = 'A';
- Int_Loc += 1;
- } /* if, while */
- if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
- /* then, not executed */
- Int_Loc = 7;
- if (Ch_Loc == 'R')
- /* then, not executed */
- return (true);
- else /* executed */
- {
- //if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
- //if (memcmp (Str_1_Par_Ref, Str_2_Par_Ref, 30) > 0)
- if (Str_1_Par_Ref > Str_2_Par_Ref)
- /* then, not executed */
- {
- Int_Loc += 7;
- Int_Glob = Int_Loc;
- return (true);
- }
- else /* executed */
- return (false);
- } /* if Ch_Loc */
-} /* Func_2 */
-
-
-Boolean Func_3 (Enumeration Enum_Par_Val)
-/***************************/
- /* executed once */
- /* Enum_Par_Val == Ident_3 */
-{
- Enumeration Enum_Loc;
-
- Enum_Loc = Enum_Par_Val;
- if (Enum_Loc == Ident_3)
- /* then, executed */
- return (true);
- else /* not executed */
- return (false);
-} /* Func_3 */
-
-version (Windows)
-{
- import core.sys.windows.windows;
-
- double dtime()
- {
- double q;
-
- q = cast(double)GetTickCount() * 1.0e-03;
-
- return q;
- }
-}
-
-version (linux)
-{
- import core.stdc.time;
-
- double dtime()
- {
- double q;
-
- q = cast(double)time(null);
-
- return q;
- }
-}
-
-version (OSX) // supplied by Anders F Bjorklund
-{
- import core.sys.posix.sys.time;
-
- double dtime()
- {
- double q;
- timeval tv;
-
- gettimeofday(&tv,null);
- q = cast(double)tv.tv_sec + cast(double)tv.tv_usec * 1.0e-6;
-
- return q;
- }
-}
-
-version (NetBSD)
-{
- import core.sys.posix.sys.time;
-
- double dtime()
- {
- double q;
- timeval tv;
-
- gettimeofday(&tv,null);
- q = cast(double)tv.tv_sec + cast(double)tv.tv_usec * 1.0e-6;
-
- return q;
- }
-}
diff --git a/gcc/testsuite/gdc.test/runnable/imports/testmangle.d b/gcc/testsuite/gdc.test/runnable/imports/testmangle.d
new file mode 100644
index 0000000..5311a83
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/imports/testmangle.d
@@ -0,0 +1,66 @@
+// helper for mangling tests with back references
+
+module imports.testmangle;
+
+public import core.demangle : demangle, demangleType;
+
+// detect mangle version
+private
+{
+ struct Detect;
+ Detect* detectMangle(Detect*);
+ void DetectTmpl(T)() {}
+}
+
+pragma(msg,detectMangle.mangleof);
+static if(detectMangle.mangleof == "_D7imports10testmangle12detectMangleFPSQL3H6DetectZQ1e")
+ enum { BackRefs = true, BackRefSymbols = true }
+else static if(detectMangle.mangleof == "_D7imports10testmangle12detectMangleFPSQBlQBg6DetectZQq")
+ enum { BackRefs = true, BackRefSymbols = false }
+else static if(detectMangle.mangleof == "_D7imports10testmangle12detectMangleFPS7imports10testmangle6DetectZPS7imports10testmangle6Detect")
+ enum { BackRefs = false, BackRefSymbols = false }
+else
+ static assert(false, "unknown mangling");
+
+private enum tmplMangle = (DetectTmpl!int).mangleof;
+pragma(msg,tmplMangle);
+static if(tmplMangle[0..40] == "_D7imports10testmangle__T10DetectTmplTiZ")
+ enum HasTemplateLength = false;
+else static if(tmplMangle[0..42] == "_D7imports10testmangle18__T10DetectTmplTiZ")
+ enum HasTemplateLength = true;
+else
+ static assert(false, "unknown mangling");
+
+pragma(msg,BackRefs);
+pragma(msg,BackRefSymbols);
+
+static if (BackRefs)
+{
+ string tl(string s)() { return null; }
+ string id(string s, string r, string r2 = null)() { return BackRefSymbols && r2 !is null ? r2 : r; }
+}
+else
+{
+ string tl(string s)() { return HasTemplateLength ? s : null; }
+ string id(string s, string r, string r2 = null)() { return s; }
+}
+
+bool equalDemangle(string m1, string m2)
+{
+ auto dm1 = demangle(m1);
+ auto dm2 = demangle(m2);
+ return dm1 == dm2;
+}
+
+string unsignedToString(ulong x)
+{
+ string s;
+ s ~= cast(char)('0' + (x % 10));
+ x /= 10;
+ while (x > 0)
+ {
+ s = cast(char)('0' + (x % 10)) ~ s;
+ x /= 10;
+ }
+ return s;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/link6574.d b/gcc/testsuite/gdc.test/runnable/link6574.d
index 0f97ed7..ab5e552 100644
--- a/gcc/testsuite/gdc.test/runnable/link6574.d
+++ b/gcc/testsuite/gdc.test/runnable/link6574.d
@@ -1,16 +1,18 @@
// PERMUTE_ARGS:
module link6574;
+import imports.testmangle;
+
enum Method { A, B, }
int foo(Method method = Method.A)()
{
- static assert(foo.mangleof == "_D8link657428__T3fooVE8link65746Methodi0Z3fooFZi");
+ static assert(foo.mangleof == "_D8link6574"~tl!"28"~"__T3fooVE"~id!("8link6574","Qs")~"6Methodi0Z"~id!("3foo","Qs")~"FZi");
return 10 * foo!method();
}
int foo(Method method : Method.A)()
{
- static assert(foo.mangleof == "_D8link657429__T3fooHVE8link65746Methodi0Z3fooFZi");
+ static assert(foo.mangleof == "_D8link6574"~tl!"29"~"__T3fooHVE"~id!("8link6574","Qt")~"6Methodi0Z"~id!("3foo","Qt")~"FZi");
return 2;
}
int foo(Method method : Method.B)()
@@ -21,7 +23,7 @@ int foo(Method method : Method.B)()
int bar(Method method = Method.B)()
{
- static assert(bar.mangleof == "_D8link657428__T3barVE8link65746Methodi1Z3barFZi");
+ static assert(bar.mangleof == "_D8link6574"~tl!"28"~"__T3barVE"~id!("8link6574","Qs")~"6Methodi1Z"~id!("3bar","Qs")~"FZi");
return 10 * bar!method();
}
int bar(Method method : Method.A)()
@@ -31,7 +33,7 @@ int bar(Method method : Method.A)()
}
int bar(Method method : Method.B)()
{
- static assert(bar.mangleof == "_D8link657429__T3barHVE8link65746Methodi1Z3barFZi");
+ static assert(bar.mangleof == "_D8link6574"~tl!"29"~"__T3barHVE"~id!("8link6574","Qt")~"6Methodi1Z"~id!("3bar","Qt")~"FZi");
return 3;
}
diff --git a/gcc/testsuite/gdc.test/runnable/mangle.d b/gcc/testsuite/gdc.test/runnable/mangle.d
index 8820a6d..883d58a 100644
--- a/gcc/testsuite/gdc.test/runnable/mangle.d
+++ b/gcc/testsuite/gdc.test/runnable/mangle.d
@@ -1,6 +1,8 @@
// PERMUTE_ARGS:
// EXTRA_SOURCES: imports/mangle10077.d
+import imports.testmangle;
+
/***************************************************/
// 10077 - pragma(mangle)
@@ -79,7 +81,7 @@ class C2774
static assert(C2774.foo2774.mangleof == "_D6mangle5C27747foo2774MFZi");
template TFoo2774(T) {}
-static assert(TFoo2774!int.mangleof == "6mangle15__T8TFoo2774TiZ");
+static assert(TFoo2774!int.mangleof == "6mangle"~tl!"15"~"__T8TFoo2774TiZ");
void test2774()
{
@@ -175,8 +177,8 @@ void test8847b()
struct Test8847
{
- enum result1 = "S6mangle8Test88478__T3fooZ3fooMFZ6Result";
- enum result2 = "S6mangle8Test88478__T3fooZ3fooMxFiZ6Result";
+ enum result1 = "S6mangle8Test8847"~tl!("8")~"__T3fooZ"~id!("3foo","Qf")~"MFZ6Result";
+ enum result2 = "S6mangle8Test8847"~tl!("8")~"__T3fooZ"~id!("3foo","Qf")~"MxFiZ6Result";
auto foo()()
{
@@ -236,9 +238,10 @@ void test8847d()
void test8847e()
{
- enum resultHere = "6mangle"~"9test8847eFZ"~"8__T3fooZ"~"3foo";
+ enum resultHere = "6mangle"~"9test8847eFZ"~tl!"8"~"__T3fooZ"~id!("3foo","Qf");
enum resultBar = "S"~resultHere~"MFNaNfNgiZ3Bar";
- enum resultFoo = "_D"~resultHere~"MFNaNbNiNfNgiZNg"~resultBar; // added 'Nb'
+ static if(BackRefs) {} else
+ enum resultFoo = "_D"~resultHere~"MFNaNbNiNfNgiZNg"~resultBar; // added 'Nb'
// Make template function to infer 'nothrow' attributes
auto foo()(inout int) pure @safe
@@ -248,10 +251,16 @@ void test8847e()
return inout(Bar)();
}
+ import core.demangle : demangle, demangleType;
auto bar = foo(0);
static assert(typeof(bar).stringof == "Bar");
static assert(typeof(bar).mangleof == resultBar);
- static assert(foo!().mangleof == resultFoo);
+ enum fooDemangled = "pure nothrow @nogc @safe inout(mangle.test8847e().foo!().foo(inout(int)).Bar) mangle.test8847e().foo!().foo(inout(int))";
+
+ static if (BackRefs)
+ static assert(demangle(foo!().mangleof) == fooDemangled);
+ else
+ static assert(foo!().mangleof == resultFoo);
}
// --------
@@ -287,7 +296,7 @@ auto bar12352()
return S();
}
-static assert( bar12352 .mangleof == "_D6mangle8bar12352FNaNbNiNfZS6mangle8bar12352FZ1S");
+static assert( bar12352 .mangleof == "_D6mangle8bar12352FNaNbNiNfZS"~id!("6mangle8bar12352FZ","QBbQxFZ","QL2H")~"1S");
static assert(typeof(bar12352()) .mangleof == "S6mangle8bar12352FZ1S");
static assert(typeof(bar12352()).func.mangleof == "_D6mangle8bar12352FZ1S4funcMFZv");
@@ -301,7 +310,7 @@ auto baz12352()
return new C();
}
-static assert( baz12352 .mangleof == "_D6mangle8baz12352FNaNbNfZC6mangle8baz12352FZ1C");
+static assert( baz12352 .mangleof == "_D6mangle8baz12352FNaNbNfZC"~id!("6mangle8baz12352FZ","QzQuFZ","QL2F")~"1C");
static assert(typeof(baz12352()) .mangleof == "C6mangle8baz12352FZ1C");
static assert(typeof(baz12352()).func.mangleof == "_D6mangle8baz12352FZ1C4funcMFZv");
@@ -312,8 +321,8 @@ void f9525(T)(in T*) { }
void test9525()
{
- enum result1 = "S6mangle8test9525FZ26__T5test1S136mangle5f9525Z5test1MFZ1S";
- enum result2 = "S6mangle8test9525FZ26__T5test2S136mangle5f9525Z5test2MFNaNbZ1S";
+ enum result1 = "S6mangle8test9525FZ"~tl!"26"~"__T5test1S"~tl!"13"~id!("6mangle","QBc")~"5f9525Z"~id!("5test1","Qr")~"MFZ1S";
+ enum result2 = "S6mangle8test9525FZ"~tl!"26"~"__T5test2S"~tl!"13"~id!("6mangle","QBc")~"5f9525Z"~id!("5test2","Qr")~"MFNaNbZ1S";
void test1(alias a)()
{
@@ -383,23 +392,32 @@ void test11718()
string TyName(string tail)()
{
enum s = "__T7Ty11718" ~ tail;
- enum int len = s.length;
- return "S6mangle" ~ len.stringof ~ s;
+ enum len = unsignedToString(s.length);
+ return "S6mangle" ~ tl!(len) ~ s;
}
string fnName(string paramPart)()
{
- enum s = "_D6mangle35__T7fn11718T"~
+ enum s = "_D6mangle"~tl!("35")~"__T7fn11718T"~
"S6mangle9test11718FZ1AZ7fn11718"~paramPart~"1a"~
"S6mangle9test11718FZ1A";
- enum int len = s.length;
- return len.stringof ~ s;
+ enum len = unsignedToString(s.length);
+ return tl!len ~ s;
}
enum result1 = TyName!("S" ~ fnName!("F"~"S6mangle9test11718FZ1A"~"Z") ~ "Z") ~ "7Ty11718";
enum result2 = TyName!("S" ~ fnName!("F"~"" ~"Z") ~ "Z") ~ "7Ty11718";
struct A {}
- static assert(fn11718(A.init) == result1);
- static assert(fn11718!A() == result2);
+ static if (BackRefs)
+ {
+ static assert(fn11718(A.init) == "S6mangle__T7Ty11718S_DQv__T7fn11718TSQBk9test11718FZ1AZQBcFQxZ1aQBcZQCf");
+ static assert(fn11718!A() == "S6mangle__T7Ty11718S_DQv__T7fn11718TSQBk9test11718FZ1AZQBcFZ1aQBaZQCd");
+ }
+ else
+ {
+ pragma(msg, fn11718(A.init));
+ static assert(fn11718(A.init) == result1);
+ static assert(fn11718!A() == result2);
+ }
}
/*******************************************/
@@ -417,9 +435,10 @@ void test11776()
{
auto s = S11776!(a => 1)();
static assert(typeof(s).mangleof ==
- "S"~"6mangle"~"56"~(
- "__T"~"6S11776"~"S42"~("6mangle"~"9test11776"~"FZ"~"9__lambda1MFZ"~"9__lambda1")~"Z"
- )~"6S11776");
+ "S"~"6mangle"~tl!("56")~
+ ("__T"~"6S11776"~"S"~tl!("42")~
+ (id!("6mangle","Qs")~"9test11776"~"FZ"~"9__lambda1MFZ"~id!("9__lambda1","Qn"))~"Z"
+ )~id!("6S11776", "QBm"));
}
};
}
@@ -464,7 +483,7 @@ void test12217(int)
static assert( S.mangleof == "S6mangle9test12217FiZ1S");
static assert( bar.mangleof == "_D6mangle9test12217FiZ3barMFNaNbNiNfZv");
static assert( var.mangleof == "_D6mangle9test12217FiZ3vari");
- static assert(X!int.mangleof == "6mangle9test12217FiZ8__T1XTiZ");
+ static assert(X!int.mangleof == "6mangle9test12217FiZ"~tl!("8")~"__T1XTiZ");
}
void test12217() {}
@@ -476,22 +495,21 @@ void func12231a()()
if (is(typeof({
class C {}
static assert(C.mangleof ==
- "C6mangle16__U10func12231aZ10func12231aFZ9__lambda1MFZ1C");
+ "C6mangle"~tl!("16")~"__U10func12231aZ"~id!("10func12231a","Qn")~"FZ9__lambda1MFZ1C");
// ### L #
})))
{}
void func12231b()()
if (is(typeof({
- class C {}
- static assert(C.mangleof ==
- "C6mangle16__U10func12231bZ10func12231bFZ9__lambda1MFZ1C");
+ class C {} static assert(C.mangleof ==
+ "C6mangle"~tl!("16")~"__U10func12231bZ"~id!("10func12231b","Qn")~"FZ9__lambda1MFZ1C");
// L__L L LL
- })) &&
+ })) &&
is(typeof({
class C {}
static assert(C.mangleof ==
- "C6mangle16__U10func12231bZ10func12231bFZ9__lambda2MFZ1C");
+ "C6mangle"~tl!("16")~"__U10func12231bZ"~id!("10func12231b","Qn")~"FZ9__lambda2MFZ1C");
// L__L L LL
})))
{}
@@ -500,14 +518,14 @@ void func12231c()()
if (is(typeof({
class C {}
static assert(C.mangleof ==
- "C6mangle16__U10func12231cZ10func12231cFZ9__lambda1MFZ1C");
+ "C6mangle"~tl!("16")~"__U10func12231cZ"~id!("10func12231c","Qn")~"FZ9__lambda1MFZ1C");
// L__L L LL
})))
{
(){
class C {}
static assert(C.mangleof ==
- "C6mangle16__T10func12231cZ10func12231cFZ9__lambda1MFZ1C");
+ "C6mangle"~tl!("16")~"__T10func12231cZ"~id!("10func12231c","Qn")~"FZ9__lambda1MFZ1C");
// L__L L LL
}();
}
@@ -515,15 +533,15 @@ if (is(typeof({
void func12231c(X)()
if (is(typeof({
class C {}
- static assert(C.mangleof ==
- "C6mangle20__U10func12231cTAyaZ10func12231cFZ9__lambda1MFZ1C");
+ static assert(C.mangleof ==
+ "C6mangle"~tl!("20")~"__U10func12231cTAyaZ"~id!("10func12231c","Qr")~"FZ9__lambda1MFZ1C");
// L__L L___L LL
})))
{
(){
class C {}
static assert(C.mangleof ==
- "C6mangle20__T10func12231cTAyaZ10func12231cFZ9__lambda1MFZ1C");
+ "C6mangle"~tl!("20")~"__T10func12231cTAyaZ"~id!("10func12231c","Qr")~"FZ9__lambda1MFZ1C");
// L__L L___L LL
}();
}
diff --git a/gcc/testsuite/gdc.test/runnable/nested.d b/gcc/testsuite/gdc.test/runnable/nested.d
index 98261ff..fa012b5 100644
--- a/gcc/testsuite/gdc.test/runnable/nested.d
+++ b/gcc/testsuite/gdc.test/runnable/nested.d
@@ -790,18 +790,9 @@ void test33()
return 3;
}
- extern (Pascal) int Foo4(int a, int b, int c)
- {
- assert(a == 1);
- assert(b == 2);
- assert(c == 3);
- return 4;
- }
-
assert(Foo1(1, 2, 3) == 1);
assert(Foo2(1, 2, 3) == 2);
assert(Foo3(1, 2, 3) == 3);
- assert(Foo4(1, 2, 3) == 4);
printf("test33 success\n");
}
diff --git a/gcc/testsuite/gdc.test/runnable/template4.d b/gcc/testsuite/gdc.test/runnable/template4.d
index 77d6254..81723f6 100644
--- a/gcc/testsuite/gdc.test/runnable/template4.d
+++ b/gcc/testsuite/gdc.test/runnable/template4.d
@@ -1074,22 +1074,27 @@ struct Foo7469d(T...) { }
struct Foo7469e(int a, T...) { }
struct Foo7469f(T, int k=1) { }
struct Foo7469g(T, int k=1) { }
+struct Foo7469h(uint x) { }
+
+import core.demangle : demangleType;
void test7469()
{
- static assert(Foo7469a!(3 ) .mangleof[$-28 .. $] == "17__T8Foo7469aVii3Z8Foo7469a");
- static assert(Foo7469a!(3u) .mangleof[$-28 .. $] == "17__T8Foo7469aVii3Z8Foo7469a");
- static assert(Foo7469b!(3u) .mangleof[$-28 .. $] == "17__T8Foo7469bVii3Z8Foo7469b");
- static assert(Foo7469b!(3 ) .mangleof[$-28 .. $] == "17__T8Foo7469bVii3Z8Foo7469b");
- static assert(Foo7469c!(3 ) .mangleof[$-28 .. $] == "17__T8Foo7469cVii3Z8Foo7469c");
- static assert(Foo7469c!(3u) .mangleof[$-28 .. $] == "17__T8Foo7469cVki3Z8Foo7469c");
- static assert(Foo7469d!(3 ) .mangleof[$-28 .. $] == "17__T8Foo7469dVii3Z8Foo7469d");
- static assert(Foo7469d!(3u) .mangleof[$-28 .. $] == "17__T8Foo7469dVki3Z8Foo7469d");
- static assert(Foo7469e!(3u, 5u).mangleof[$-32 .. $] == "21__T8Foo7469eVii3Vki5Z8Foo7469e");
- static assert(Foo7469f!(int, 1).mangleof[$-30 .. $] == "19__T8Foo7469fTiVii1Z8Foo7469f");
- static assert(Foo7469f!(int) .mangleof[$-30 .. $] == "19__T8Foo7469fTiVii1Z8Foo7469f");
- static assert(Foo7469g!(int) .mangleof[$-30 .. $] == "19__T8Foo7469gTiVii1Z8Foo7469g");
- static assert(Foo7469g!(int, 1).mangleof[$-30 .. $] == "19__T8Foo7469gTiVii1Z8Foo7469g");
+ static assert(demangleType(Foo7469a!(3 ) .mangleof) == "template4.Foo7469a!(3).Foo7469a");
+ static assert(demangleType(Foo7469a!(3u) .mangleof) == "template4.Foo7469a!(3).Foo7469a");
+ static assert(demangleType(Foo7469b!(3u) .mangleof) == "template4.Foo7469b!(3).Foo7469b");
+ static assert(demangleType(Foo7469b!(3 ) .mangleof) == "template4.Foo7469b!(3).Foo7469b");
+ static assert(demangleType(Foo7469c!(3 ) .mangleof) == "template4.Foo7469c!(3).Foo7469c");
+ static assert(demangleType(Foo7469c!(3u) .mangleof) == "template4.Foo7469c!(3u).Foo7469c");
+ static assert(demangleType(Foo7469d!(3 ) .mangleof) == "template4.Foo7469d!(3).Foo7469d");
+ static assert(demangleType(Foo7469d!(3u) .mangleof) == "template4.Foo7469d!(3u).Foo7469d");
+ static assert(demangleType(Foo7469e!(3u, 5u).mangleof) == "template4.Foo7469e!(3, 5u).Foo7469e");
+ static assert(demangleType(Foo7469f!(int, 1).mangleof) == "template4.Foo7469f!(int, 1).Foo7469f");
+ static assert(demangleType(Foo7469f!(int) .mangleof) == "template4.Foo7469f!(int, 1).Foo7469f");
+ static assert(demangleType(Foo7469g!(int) .mangleof) == "template4.Foo7469g!(int, 1).Foo7469g");
+ static assert(demangleType(Foo7469g!(int, 1).mangleof) == "template4.Foo7469g!(int, 1).Foo7469g");
+ static assert(demangleType(Foo7469h!(3 ) .mangleof) == "template4.Foo7469h!(3u).Foo7469h");
+ static assert(demangleType(Foo7469h!(3u) .mangleof) == "template4.Foo7469h!(3u).Foo7469h");
}
/******************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/template9.d b/gcc/testsuite/gdc.test/runnable/template9.d
index 4f18295..b016ff9 100644
--- a/gcc/testsuite/gdc.test/runnable/template9.d
+++ b/gcc/testsuite/gdc.test/runnable/template9.d
@@ -4465,6 +4465,7 @@ void test13807()
/******************************************/
// 14174
+import imports.testmangle;
struct Config14174(a, b) {}
@@ -4474,22 +4475,22 @@ alias defConfig14174 = Config14174!(N14174, N14174);
void accepter14174a(Config : Config14174!(T) = defConfig14174, T...)()
{
- static assert(accepter14174a.mangleof
- == "_D7breaker131__T14"~
+ static assert(equalDemangle(accepter14174a.mangleof,
+ "_D7breaker131__T14"~
"accepter14174a"~
"HTS7breaker51__T11Config14174TS7breaker6N14174TS7breaker6N14174Z11Config14174TS7breaker6N14174TS7breaker6N14174Z14"~
"accepter14174a"~
- "FZv");
+ "FZv"));
}
void accepter14174b(Config : Config14174!(T) = defConfig14174, T...)()
{
- static assert(accepter14174b.mangleof
- == "_D7breaker131__T14"~
+ static assert(equalDemangle(accepter14174b.mangleof,
+ "_D7breaker131__T14"~
"accepter14174b"~
"HTS7breaker51__T11Config14174TS7breaker6N14174TS7breaker6N14174Z11Config14174TS7breaker6N14174TS7breaker6N14174Z14"~
"accepter14174b"~
- "FZv");
+ "FZv"));
}
void test14174()
diff --git a/gcc/testsuite/gdc.test/runnable/test4.d b/gcc/testsuite/gdc.test/runnable/test4.d
index b5263e7..1d03572 100644
--- a/gcc/testsuite/gdc.test/runnable/test4.d
+++ b/gcc/testsuite/gdc.test/runnable/test4.d
@@ -605,11 +605,6 @@ extern (C) int cfc(int x, int y)
return x * 10 + y;
}
-extern (Pascal) int cfp(int x, int y)
-{
- return x * 10 + y;
-}
-
int cfd(int x, int y)
{
return x * 10 + y;
@@ -618,7 +613,6 @@ int cfd(int x, int y)
extern (Windows) int function (int, int) fpw;
extern (C) int function (int, int) fpc;
-extern (Pascal) int function (int, int) fpp;
int function (int, int) fpd;
void test20()
@@ -628,7 +622,6 @@ void test20()
fpw = &cfw;
fpc = &cfc;
- fpp = &cfp;
fpd = &cfd;
//printf("test w\n");
@@ -639,10 +632,6 @@ void test20()
i = (*fpc)(3, 4);
assert(i == 34);
-//printf("test p\n");
- i = (*fpp)(5, 6);
- assert(i == 56);
-
//printf("test d\n");
i = (*fpd)(7, 8);
assert(i == 78);
@@ -1480,4 +1469,3 @@ int main()
printf("Success\n");
return 0;
}
-
diff --git a/gcc/testsuite/gdc.test/runnable/testconst.d b/gcc/testsuite/gdc.test/runnable/testconst.d
index 2da39a2..42f9c1b 100644
--- a/gcc/testsuite/gdc.test/runnable/testconst.d
+++ b/gcc/testsuite/gdc.test/runnable/testconst.d
@@ -84,10 +84,11 @@ void foo8(const char[] s, const C8 c, const int x)
void test8()
{
+ import core.demangle : demangle;
auto p = &foo8;
showf(p.mangleof);
assert(typeof(p).mangleof == "PFxAaxC9testconst2C8xiZv");
- assert(p.mangleof == "_D9testconst5test8FZ1pPFxAaxC9testconst2C8xiZv");
+ assert(demangle(p.mangleof) == "void function(const(char[]), const(testconst.C8), const(int))* testconst.test8().p");
}
/************************************/
diff --git a/gcc/testsuite/gfortran.dg/analyzer/pr97668.f b/gcc/testsuite/gfortran.dg/analyzer/pr97668.f
new file mode 100644
index 0000000..568c891
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/analyzer/pr97668.f
@@ -0,0 +1,26 @@
+c { dg-additional-options "-std=legacy" }
+
+ SUBROUTINE PPADD (A, C, BH)
+
+ COMPLEX DD, FP, FPP, R1, R2
+ DIMENSION A(*), C(*), BH(*)
+
+ DO 136 IG=IS,1
+ FP = (0.,0.)
+ FPP = (0.,0.)
+
+ DO 121 J=1,1
+ DD = 1./2
+ FP = DD
+ FPP = DD+1
+ 121 CONTINUE
+
+ R2 = -FP
+ IF (ABS(R1)-ABS(R2)) 129,129,133
+ 129 R1 = R2/FPP
+ 133 IT = IT+1
+
+ 136 CONTINUE
+
+ RETURN
+ END
diff --git a/gcc/testsuite/gfortran.dg/attr_deprecated.f90 b/gcc/testsuite/gfortran.dg/attr_deprecated.f90
new file mode 100644
index 0000000..aa3f513
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/attr_deprecated.f90
@@ -0,0 +1,30 @@
+! { dg-do compile }
+
+module m
+ implicit none
+ integer :: A
+ integer, parameter :: PARM = 5 ! { dg-warning "Using parameter 'parm' declared at .1. is deprecated" }
+!GCC$ ATTRIBUTES DEPRECATED :: A, foo, func, parm
+contains
+subroutine foo
+end
+integer function func()
+ func = 42
+end
+subroutine bar
+ integer :: i
+ call foo ! { dg-warning "Using subroutine 'foo' at .1. is deprecated" }
+ print *, A ! { dg-warning "Using variable 'a' at .1. is deprecated" }
+ i = func() ! { dg-warning "Using function 'func' at .1. is deprecated" }
+ print *, PARM
+end
+
+end module m
+
+use m ! { dg-warning "Using parameter 'parm' declared at .1. is deprecated" }
+ integer :: i
+ call foo ! { dg-warning "Using subroutine 'foo' at .1. is deprecated" }
+ print *, A ! { dg-warning "Using variable 'a' at .1. is deprecated" }
+ i = func() ! { dg-warning "Using function 'func' at .1. is deprecated" }
+ print *, PARM
+end
diff --git a/gcc/testsuite/gfortran.dg/class_allocate_25.f90 b/gcc/testsuite/gfortran.dg/class_allocate_25.f90
new file mode 100644
index 0000000..4e5855f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_allocate_25.f90
@@ -0,0 +1,58 @@
+! { dg-do run }
+! { dg-options "-fdump-tree-original" }
+!
+! In the course of fixing PR83118, lots of issues came up with class array
+! assignment, where temporaries are generated. This testcase checks that
+! the use of assignment by allocate with source is OK, especially with array
+! constructors using class arrays. While this test did run previously, the
+! temporaries for such arrays were malformed with the class as the type and
+! element lengths of 72 bytes rather than the 4 bytes of the decalred type.
+!
+! Contributed by Dominique d'Humieres <dhumieres.dominique@free.fr>
+!
+type t1
+ integer :: i = 5
+end type t1
+type, extends(t1) :: t2
+ integer :: j = 6
+end type t2
+
+class(t1), allocatable :: a(:), b(:), c(:)
+integer :: i
+
+allocate(t2 :: a(3))
+allocate(t2 :: b(5))
+if (.not.check_t1 (a, [(5, i = 1, 3)], 2)) stop 1
+
+allocate(c, source=[a, b ]) ! F2008, PR 44672
+if (.not.check_t1 (c, [(5, i = 1, 8)], 1)) stop 2
+
+deallocate(c)
+allocate(c(8), source=[ a, b ])
+if (.not.check_t1 (c, [(5, i = 1, 8)], 1)) stop 3
+
+deallocate(c)
+c = [t1 :: a, b ] ! F2008, PR 43366
+if (.not.check_t1 (c, [(5, i = 1, 8)], 1)) stop 4
+deallocate(a, b, c)
+
+contains
+
+ logical function check_t1 (arg, array, t)
+ class(t1) :: arg(:)
+ integer :: array (:), t
+ check_t1 = .true.
+ select type (arg)
+ type is (t1)
+ if (any (arg%i .ne. array)) check_t1 = .false.
+ if (t .eq. 2) check_t1 = .false.
+ type is (t2)
+ if (any (arg%i .ne. array)) check_t1 = .false.
+ if (t .eq. 1) check_t1 = .false.
+ class default
+ check_t1 = .false.
+ end select
+ end function check_t1
+
+end
+! { dg-final { scan-tree-dump-times "elem_len=72" 0 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/class_assign_4.f90 b/gcc/testsuite/gfortran.dg/class_assign_4.f90
new file mode 100644
index 0000000..517e312
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_assign_4.f90
@@ -0,0 +1,183 @@
+! { dg-do run }
+!
+! In the course of fixing PR83118, lots of issues came up with class array
+! assignment, where temporaries are generated. This testcase checks that
+! it all works correctly.
+!
+! Contributed by Paul Thomas <pault@gcc.gnu.org>
+!
+module m
+ implicit none
+ type :: t1
+ integer :: i
+ CONTAINS
+ PROCEDURE :: add_t1
+ GENERIC :: OPERATOR(+) => add_t1
+ end type
+ type, extends(t1) :: t2
+ real :: r
+ end type
+
+contains
+ impure elemental function add_t1 (a, b) result (c)
+ class(t1), intent(in) :: a, b
+ class(t1), allocatable :: c
+ allocate (c, source = a)
+ c%i = a%i + b%i
+ select type (c)
+ type is (t2)
+ select type (b)
+ type is (t2)
+ c%r = c%r + b%r
+ end select
+ end select
+ end function add_t1
+
+end module m
+
+subroutine test_t1
+ use m
+ implicit none
+
+ class(t1), dimension(:), allocatable :: x, y
+
+ x = [t2(1,10.0),t2(2,20.0),t2(3,30.0)]
+ if (.not.check_t1 (x, [1,2,3], 2, [10, 20, 30]) ) stop 1
+
+ y = x
+ x = realloc_t1 (y)
+ if (.not.check_t1 (x, [3,2,1], 1) ) stop 2
+
+ x = realloc_t1 (x)
+ if (.not.check_t1 (x, [2,3,1], 1) ) stop 3
+
+ x = x([3,1,2])
+ if (.not.check_t1 (x, [1,2,3], 1) ) stop 4
+
+ x = x(3:1:-1) + y
+ if (.not.check_t1 (x, [4,4,4], 1) ) stop 5
+
+ x = y + x(3:1:-1)
+ if (.not.check_t1 (x, [5,6,7], 2) ) stop 6
+
+! Now check that the dynamic type survives assignments.
+ x = [t2(1,10.0),t2(2,20.0),t2(3,30.0)]
+ y = x
+
+ x = y(3:1:-1)
+ if (.not.check_t1 (x, [3,2,1], 2, [30,20,10]) ) stop 7
+
+ x = x(3:1:-1) + y
+ if (.not.check_t1 (x, [2,4,6], 2, [20,40,60]) ) stop 8
+
+ x = x(3:1:-1)
+ if (.not.check_t1 (x, [6,4,2], 2, [60,40,20]) ) stop 9
+
+ x = x([3,2,1])
+ if (.not.check_t1 (x, [2,4,6], 2, [20,40,60]) ) stop 10
+
+contains
+
+ function realloc_t1 (arg) result (res)
+ class(t1), dimension(:), allocatable :: arg
+ class(t1), dimension(:), allocatable :: res
+ select type (arg)
+ type is (t2)
+ allocate (res, source = [t1 (arg(3)%i), t1 (arg(2)%i), t1 (arg(1)%i)])
+ type is (t1)
+ allocate (res, source = [t1 (arg(2)%i), t1 (arg(1)%i), t1 (arg(3)%i)])
+ end select
+ end function realloc_t1
+
+ logical function check_t1 (arg, array, t, array2)
+ class(t1) :: arg(:)
+ integer :: array (:), t
+ integer, optional :: array2(:)
+ check_t1 = .true.
+ select type (arg)
+ type is (t1)
+ if (any (arg%i .ne. array)) check_t1 = .false.
+ if (t .eq. 2) check_t1 = .false.
+ type is (t2)
+ if (any (arg%i .ne. array)) check_t1 = .false.
+ if (t .eq. 1) check_t1 = .false.
+ if (present (array2)) then
+ if (any(int (arg%r) .ne. array2)) check_t1 = .false.
+ end if
+ class default
+ check_t1 = .false.
+ end select
+ end function check_t1
+
+end subroutine test_t1
+
+subroutine test_star
+ use m
+ implicit none
+
+ class(*), dimension(:), allocatable :: x, y
+
+ x = [t2(1,10.0),t2(2,20.0),t2(3,30.0)]
+ if (.not.check_star (x, [1,2,3], 2) ) stop 11
+
+ y = x
+ x = realloc_star (y)
+ if (.not.check_star (x, [3,2,1], 1) ) stop 12
+
+ x = realloc_star (x)
+ if (.not.check_star (x, [2,3,1], 1) ) stop 13
+
+ x = x([3,1,2])
+ if (.not.check_star (x, [1,2,3], 1) ) stop 14
+
+ x = x(3:1:-1)
+ if (.not.check_star (x, [3,2,1], 1) ) stop 15
+
+! Make sure that all is similarly well with type t2.
+ x = [t2(1,10.0),t2(2,20.0),t2(3,30.0)]
+
+ x = x([3,1,2])
+ if (.not.check_star (x, [3,1,2], 2, [30,10,20]) ) stop 16
+
+ x = x(3:1:-1)
+ if (.not.check_star (x, [2,1,3], 2, [20,10,30]) ) stop 17
+
+contains
+
+ function realloc_star (arg) result (res)
+ class(*), dimension(:), allocatable :: arg
+ class(*), dimension(:), allocatable :: res
+ select type (arg)
+ type is (t2)
+ allocate (res, source = [t1 (arg(3)%i), t1 (arg(2)%i), t1 (arg(1)%i)])
+ type is (t1)
+ allocate (res, source = [t1 (arg(2)%i), t1 (arg(1)%i), t1 (arg(3)%i)])
+ end select
+ end function realloc_star
+
+ logical function check_star (arg, array, t, array2)
+ class(*) :: arg(:)
+ integer :: array (:), t
+ integer, optional :: array2(:)
+ check_star = .true.
+ select type (arg)
+ type is (t1)
+ if (any (arg%i .ne. array)) check_star = .false.
+ if (t .eq. 2) check_star = .false.
+ type is (t2)
+ if (any (arg%i .ne. array)) check_star = .false.
+ if (t .eq. 1) check_star = .false.
+ if (present (array2)) then
+ if (any (int(arg%r) .ne. array2)) check_star = .false.
+ endif
+ class default
+ check_star = .false.
+ end select
+ end function check_star
+
+end subroutine test_star
+
+
+ call test_t1
+ call test_star
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray/alloc_comp_1.f90 b/gcc/testsuite/gfortran.dg/coarray/alloc_comp_1.f90
index f809a5f..cf3ece2 100644
--- a/gcc/testsuite/gfortran.dg/coarray/alloc_comp_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray/alloc_comp_1.f90
@@ -10,7 +10,7 @@ allocate (a%caf[3:*])
a%caf = 7
if (a%caf /= 7) STOP 1
if (any (lcobound (a%caf) /= [ 3 ]) &
- .or. ucobound (a%caf, dim=1) /= this_image ()+2) &
+ .or. ucobound (a%caf, dim=1) /= num_images ()+2) &
STOP 2
deallocate (a%caf)
end
diff --git a/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90 b/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90
index 3e16fa8..b3caf80 100644
--- a/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray/send_char_array_1.f90
@@ -25,28 +25,28 @@ program send_convert_char_array
allocate(character(kind=4, len=5)::co_str_k4_arr(4)[*])
! First check send/copy to self
- co_str_k1_scal[1] = str_k1_scal
+ co_str_k1_scal[this_image()] = str_k1_scal
if (co_str_k1_scal /= str_k1_scal // ' ') STOP 1
- co_str_k4_scal[1] = str_k4_scal
+ co_str_k4_scal[this_image()] = str_k4_scal
if (co_str_k4_scal /= str_k4_scal // 4_' ') STOP 2
- co_str_k4_scal[1] = str_k1_scal
+ co_str_k4_scal[this_image()] = str_k1_scal
if (co_str_k4_scal /= str_k4_scal // 4_' ') STOP 3
- co_str_k1_scal[1] = str_k4_scal
+ co_str_k1_scal[this_image()] = str_k4_scal
if (co_str_k1_scal /= str_k1_scal // ' ') STOP 4
- co_str_k1_arr(:)[1] = str_k1_arr
+ co_str_k1_arr(:)[this_image()] = str_k1_arr
if (any(co_str_k1_arr /= ['abc ', 'EFG ', 'klm ', 'NOP '])) STOP 5
- co_str_k4_arr(:)[1] = [4_'abc', 4_'EFG', 4_'klm', 4_'NOP']! str_k4_arr
+ co_str_k4_arr(:)[this_image()] = [4_'abc', 4_'EFG', 4_'klm', 4_'NOP']! str_k4_arr
if (any(co_str_k4_arr /= [4_'abc ', 4_'EFG ', 4_'klm ', 4_'NOP '])) STOP 6
- co_str_k4_arr(:)[1] = str_k1_arr
+ co_str_k4_arr(:)[this_image()] = str_k1_arr
if (any(co_str_k4_arr /= [ 4_'abc ', 4_'EFG ', 4_'klm ', 4_'NOP '])) STOP 7
- co_str_k1_arr(:)[1] = str_k4_arr
+ co_str_k1_arr(:)[this_image()] = str_k4_arr
if (any(co_str_k1_arr /= ['abc ', 'EFG ', 'klm ', 'NOP '])) STOP 8
end program send_convert_char_array
diff --git a/gcc/testsuite/gfortran.dg/coverage.f90 b/gcc/testsuite/gfortran.dg/coverage.f90
new file mode 100644
index 0000000..e0800f8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coverage.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-additional-options "-fprofile-arcs -ftest-coverage" }
+!
+! PR fortran/95847
+!
+module foo
+contains
+ subroutine sbr()
+ end subroutine sbr
+end module foo
+
+function foo_suite() result(suite)
+ use foo
+ integer :: bar
+ integer :: res
+ res = bar(sbr)
+end function foo_suite
diff --git a/gcc/testsuite/gfortran.dg/data_inquiry_ref.f90 b/gcc/testsuite/gfortran.dg/data_inquiry_ref.f90
new file mode 100644
index 0000000..de320f1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_inquiry_ref.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+!
+! Test the fix for PR98022. Code is in place to deliver the expected result.
+! However, it was determined that the data statements below violate F18(R841)
+! and so an error results.
+!
+! Contributed by Arseny Solokha <asolokha@gmx.com>
+!
+module ur
+contains
+! The reporter's test.
+ function kn1() result(hm2)
+ complex :: hm(1:2), hm2(1:3), scalar
+ data (hm(md)%re, md=1,2)/1.0, 2.0/, scalar%re/42.0/ ! { dg-error "neither an array-element" }
+ data (hm(md)%im, md=1,2)/0.0, 0.0/, scalar%im/-42.0/ ! { dg-error "neither an array-element" }
+ hm2(1:2) = hm
+ hm2(3) = scalar
+ end function kn1
+
+! Check for derived types with complex components.
+ function kn2() result(hm2)
+ type t
+ complex :: c
+ integer :: i
+ end type
+ type (t) :: hm(1:2), scalar
+ complex :: hm2(1:3)
+ data (hm(md)%c%re, md=1,2)/0.0, 0.0/, scalar%c%re/42.0/ ! { dg-error "neither an array-element" }
+ data (hm(md)%c%im, md=1,2)/1.0, 2.0/, scalar%c%im/-42.0/ ! { dg-error "neither an array-element" }
+ data (hm(md)%i, md=1,2)/1, 2/
+ hm2(1:2) = hm%c
+ hm2(3) = scalar%c
+ end function kn2
+end module ur
+
+! use ur
+! if (any (kn1() .ne. [(1.0,0.0),(2.0,0.0),(42.0,-42.0)])) stop 1
+! if (any (kn2() .ne. [(0.0,1.0),(0.0,2.0),(42.0,-42.0)])) stop 2
+end
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_36.f90 b/gcc/testsuite/gfortran.dg/deferred_character_36.f90
new file mode 100644
index 0000000..65f2464
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_36.f90
@@ -0,0 +1,16 @@
+! { dg-do run }
+!
+! Test the fix for PR93833, which ICEd as shown.
+!
+! Contributed by Gerhard Steinmetz <gscfq@t-online.de>
+!
+program p
+ character(:), allocatable :: c
+ c = "wxyz"
+contains
+ subroutine s
+ associate (y => [c])
+ if (any(y /= [c])) stop 1
+ end associate
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/dependency_60.f90 b/gcc/testsuite/gfortran.dg/dependency_60.f90
new file mode 100644
index 0000000..bf10812
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dependency_60.f90
@@ -0,0 +1,19 @@
+! { dg-do run }
+! PR 92755 - this used to cause an ICE (see dependency_57.f90)
+! PR83118 - fixed so that it would run :-)
+! Original test case by Gerhard Steinmetz
+program p
+ type t
+ integer :: i
+ end type
+ type t2
+ class(t), allocatable :: a(:)
+ end type
+ type(t2) :: z
+ z%a = [t(1),t(2),t(3)]
+ z%a = [z%a]
+ select type (y => z%a)
+ type is (t)
+ if (any (y%i .ne. [1, 2, 3])) stop 1
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/entry_23.f b/gcc/testsuite/gfortran.dg/entry_23.f
new file mode 100644
index 0000000..ebc5f66
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/entry_23.f
@@ -0,0 +1,57 @@
+! { dg-do run }
+! PR 97799 - this used to segfault intermittently.
+! Test case by George Hockney.
+ PROGRAM MAIN
+ IMPLICIT NONE
+
+ character *(20) CA(4) ! four cells of length 20
+
+ call CHAR_ENTRY(CA) ! call char_sub through entry
+
+ write (*,*) CA ! write result -- not needed for bug
+ call CHAR_SUB(CA) ! call char_sb directly -- not needed
+ write (*,*) CA ! write result -- not needed for bug
+ STOP
+ END
+
+
+
+ SUBROUTINE CHAR_SUB(CARRAY) ! sets carray cells to 'Something'
+ IMPLICIT NONE
+
+ CHARACTER*(*) CARRAY(*)
+
+ integer i
+ integer nelts
+
+ nelts = 4 ! same as size of array in main program
+ write (*,*) 'CHAR_SUB'
+ write (*,*) 'len(carray(1))', len(carray(1)) ! len is OK at 20
+ call flush() ! since the next loop segfaults
+ do 1 i=1, nelts
+ CARRAY(i) = 'Something'
+ 1 continue
+ RETURN
+ END
+
+
+ SUBROUTINE TOP_ENTRY
+!
+! TOP_ENTRY is never called directly. It organizes entry points
+! and sometimes saves variables for other entry points. Its
+! signature does not matter for the failure
+!
+ IMPLICIT NONE
+!
+! Declare input variables for all entry points. Just one here
+!
+ CHARACTER*(*) CARRAY(*)
+!
+! Entry point CHAR_ENTRY
+!
+ ENTRY CHAR_ENTRY( CARRAY)
+ CALL CHAR_SUB(CARRAY)
+ RETURN
+
+ END SUBROUTINE TOP_ENTRY
+
diff --git a/gcc/testsuite/gfortran.dg/finalize_37.f90 b/gcc/testsuite/gfortran.dg/finalize_37.f90
new file mode 100644
index 0000000..6d5be02
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/finalize_37.f90
@@ -0,0 +1,80 @@
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
+!
+! PR fortran/92587
+!
+
+module m
+ implicit none (type, external)
+ type t2
+ contains
+ final :: fini
+ end type
+ type t3
+ type(t2) :: a
+ end type
+ type, extends(t3) :: t4
+ end type
+ class(t4), allocatable :: y
+ class(t4), allocatable :: z
+ integer :: fini_cnt = 0
+contains
+ subroutine sub
+ y = z
+ end
+ subroutine fini(x)
+ type(t2) :: x
+ fini_cnt = fini_cnt + 1
+ end
+end
+
+module m2
+ use m
+ implicit none (type, external)
+ type, extends(t3) :: t5
+ end type
+ type, extends(t3) :: t6
+ contains
+ final :: fin2
+ end type
+ integer :: fin2_cnt = 0
+contains
+ subroutine bar(x, y, z)
+ class(t4), allocatable, intent(out) :: x
+ class(t5), allocatable, intent(out) :: y
+ class(t6), allocatable, intent(out) :: z
+ end
+ subroutine fin2 (x)
+ type(t6) :: x
+ fin2_cnt = fin2_cnt + 1
+ end
+end
+
+ use m
+ use m2
+ implicit none (type, external)
+ class(t4), allocatable :: x2
+ class(t5), allocatable :: y2
+ class(t6), allocatable :: z2
+
+ if (fini_cnt /= 0 .or. fin2_cnt /= 0) stop 1
+ call bar (x2, y2, z2)
+ if (fini_cnt /= 0 .or. fin2_cnt /= 0) stop 2
+ if (allocated(x2) .or. allocated(y2) .or. allocated(z2)) stop 3
+
+ allocate(t4 :: x2)
+ allocate(t5 :: y2)
+ allocate(t6 :: z2)
+ call bar (x2, y2, z2)
+ if (fini_cnt /= 3 .or. fin2_cnt /= 1) stop 4
+ if (allocated(x2) .or. allocated(y2) .or. allocated(z2)) stop 5
+
+ allocate(t6 :: z2)
+ call bar (x2, y2, z2)
+ if (fini_cnt /= 4 .or. fin2_cnt /= 2) stop 6
+ if (allocated(x2) .or. allocated(y2) .or. allocated(z2)) stop 7
+end
+
+! { dg-final { scan-tree-dump "__final_m_T2 \\\(struct" "original" } }
+! { dg-final { scan-tree-dump "__final_m_T3 \\\(struct" "original" } }
+! { dg-final { scan-tree-dump "__final_m2_T6 \\\(struct" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/forall_19.f90 b/gcc/testsuite/gfortran.dg/forall_19.f90
new file mode 100644
index 0000000..ef05c97
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/forall_19.f90
@@ -0,0 +1,32 @@
+! { dg-do run }
+! PR fortran/98307 - Dependency check fails when using "allocatable"
+
+program forall_deps
+ implicit none
+ type t
+ logical :: valid = .true.
+ integer :: s = 0
+ integer, allocatable :: p(:)
+ end type
+ type(t) :: v(2)
+ integer :: i
+
+ allocate (v(1)%p(8))
+ allocate (v(2)%p(8))
+ v(1)%s = 8
+ v(2)%s = 6
+
+ v(1)%p(:) = [1, 2, 3, 4, 5, 6, 7, 8]
+ v(2)%p(:) = [13, 14, 15, 16, 17, 18, 19, 20]
+ forall (i=1:2)
+ v(i)%p(1:v(i)%s) = v(3-i)%p(1:v(i)%s)
+ end forall
+ if (any(v(2)%p(:) /= [1, 2, 3, 4, 5, 6, 19, 20])) stop 1
+
+ v(1)%p(:) = [1, 2, 3, 4, 5, 6, 7, 8]
+ v(2)%p(:) = [13, 14, 15, 16, 17, 18, 19, 20]
+ forall (i=1:2, v(i)%valid)
+ v(i)%p(1:v(i)%s) = v(3-i)%p(1:v(i)%s)
+ end forall
+ if (any(v(2)%p(:) /= [1, 2, 3, 4, 5, 6, 19, 20])) stop 2
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc-gomp/atomic.f90 b/gcc/testsuite/gfortran.dg/goacc-gomp/atomic.f90
new file mode 100644
index 0000000..59186a2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc-gomp/atomic.f90
@@ -0,0 +1,48 @@
+! { dg-do compile } */
+! { dg-additional-options "-fdump-tree-original" } */
+
+subroutine foo
+ !$omp requires atomic_default_mem_order(acq_rel)
+ integer :: i, v
+
+ !$omp atomic read
+ i = v
+
+ !$acc atomic read
+ i = v
+
+ !$omp atomic write
+ i = v
+
+ !$acc atomic write
+ i = v
+
+ !$omp atomic update
+ i = i + 1
+
+ !$acc atomic update
+ i = i + 1
+
+ !$omp atomic capture
+ i = i + 1
+ v = i
+ !$omp end atomic
+
+ !$acc atomic capture
+ i = i + 1
+ v = i
+ !$acc end atomic
+
+ ! Valid in C/C++ since OpenACC 2.5 but not in Fortran:
+ ! !$acc atomic update capture
+ ! i = i + 1
+ ! v = i
+ ! !$acc end atomic
+end
+
+! { dg-final { scan-tree-dump-times "i = #pragma omp atomic read acquire" 1 "original" } }
+! { dg-final { scan-tree-dump-times "i = #pragma omp atomic read relaxed" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp atomic release" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp atomic relaxed" 2 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture acq_rel" 1 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture relaxed" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc-gomp/fixed-1.f b/gcc/testsuite/gfortran.dg/goacc-gomp/fixed-1.f
new file mode 100644
index 0000000..b6bab4c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc-gomp/fixed-1.f
@@ -0,0 +1,81 @@
+! { dg-additional-options "-fdump-tree-original -Wunused-variable" }
+ implicit none
+ integer :: a,b,c,d,e,f,g,h,i,j,k,ll
+
+c$bogus
+!$bogus
+*$bogus
+
+c$ bogus
+!$ bogus
+*$ bogus
+
+c$a23 bogus
+!$ a bogus
+*$12a bogus
+
+! The following should be parsed as OpenMP conditional sentinel
+! If not, expect a unused-variable warning
+
+c$ a = 1
+!$ b = 2
+*$ c = 3
+
+c$ 1 d = 4
+!$ 22 e = 5
+*$34 f = 6
+
+c$ g =
+c$ *7
+!$ 2 h =
+*$ & 8
+*$ 3 i
+!$ & = 9
+
+c$ j
+*$ &=
+c$ *10
+!$ 5 k
+*$ * =
+c$ & 1
+*$ & 1
+*$9 9 ll
+!$ & =
+!$ * 12
+
+c$ bogus
+!$ bogus
+*$ bogus
+
+c$bogus
+!$bogus
+*$bogus
+
+c$ acc bogus
+!$ acc bogus
+*$ acc bogus
+
+c$ omp bogus
+!$ omp bogus
+*$ omp bogus
+ end
+
+!{ dg-final { scan-tree-dump-times "a = 1;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "b = 2;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "c = 3;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "d = 4;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "e = 5;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "f = 6;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "g = 7;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "h = 8;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "i = 9;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "j = 10;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "k = 11;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "ll = 12;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000001:;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000022:;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000034:;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000002:;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000003:;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000005:;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "__label_000099:;" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc-gomp/free-1.f90 b/gcc/testsuite/gfortran.dg/goacc-gomp/free-1.f90
new file mode 100644
index 0000000..0d6f2b2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc-gomp/free-1.f90
@@ -0,0 +1,34 @@
+! { dg-additional-options "-fdump-tree-original -Wunused-variable" }
+implicit none
+integer :: a,b,c,d,e,f,g,h
+
+!$bogus
+
+ !$bogus
+!$& bogus
+ !$& bogus
+
+!$ a = 1
+!$ b = 2
+!$ c = &
+!$3
+
+!$ d = &
+!$&4
+
+ !$ e = 5
+ !$ f = 6
+ !$ g = &
+ !$7
+
+ !$ h = &
+!$&8
+ end
+
+!{ dg-final { scan-tree-dump-times "a = 1;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "b = 2;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "c = 3;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "d = 4;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "e = 5;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "f = 6;" 1 "original" } }
+!{ dg-final { scan-tree-dump-times "g = 7;" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc-gomp/goacc-gomp.exp b/gcc/testsuite/gfortran.dg/goacc-gomp/goacc-gomp.exp
new file mode 100644
index 0000000..6073fb3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc-gomp/goacc-gomp.exp
@@ -0,0 +1,37 @@
+# Copyright (C) 2005-2020 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gfortran-dg.exp
+
+if { ![check_effective_target_fopenacc] \
+ || ![check_effective_target_fopenmp] } {
+ return
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+gfortran-dg-runtest [lsort \
+ [find $srcdir/$subdir *.\[fF\]{,90,95,03,08} ] ] "" "-fopenacc -fopenmp"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gfortran.dg/goacc/atomic.f90 b/gcc/testsuite/gfortran.dg/goacc/atomic.f90
new file mode 100644
index 0000000..072d024
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/atomic.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+
+subroutine foo
+ integer :: i, v
+ !$acc atomic read bar ! { dg-error "21: Unexpected junk after !.ACC ATOMIC statement" }
+ i = v
+
+ !$acc atomic read write ! { dg-error "21: Unexpected junk after !.ACC ATOMIC statement" }
+ i = v
+
+ !$acc atomic read seq_cst ! { dg-error "21: Unexpected junk after !.ACC ATOMIC statement" }
+ i = v
+
+ !$acc atomic read relaxed ! { dg-error "21: Unexpected junk after !.ACC ATOMIC statement" }
+ i = v
+
+ !$acc atomic update hint(1) ! { dg-error "23: Unexpected junk after !.ACC ATOMIC statement" }
+ i = i + 1
+
+ !$acc atomic update update capture ! { dg-error "23: Unexpected junk after !.ACC ATOMIC statement" }
+ i = i + 1
+ v = i
+
+ !$acc atomic update capture capture ! { dg-error "23: Unexpected junk after !.ACC ATOMIC statement" }
+ i = i + 1
+ v = i
+
+ !$acc atomic write capture ! { dg-error "22: Unexpected junk after !.ACC ATOMIC statement" }
+ i = 1
+
+ ! Valid in C/C++ since OpenACC 2.5 but not in Fortran:
+ !$acc atomic update capture ! { dg-error "23: Unexpected junk after !.ACC ATOMIC statement" }
+ i = i + 1
+ v = i
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95
index 0877242..6cca3d6 100644
--- a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95
@@ -19,8 +19,8 @@ program main
call setup(a, b)
- !$acc kernels copyin (a(0:n-1), b(0:n-1)) copyout (c(0:n-1))
- do i = 0, n - 1 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+ !$acc kernels copyin (a(0:n-1), b(0:n-1)) copyout (c(0:n-1)) ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+ do i = 0, n - 1
c(i) = a(f (i)) + b(f (i))
end do
!$acc end kernels
diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95
index f2c4736..715a983 100644
--- a/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95
@@ -15,8 +15,8 @@ program main
call setup(a, b)
- !$acc kernels copyin (a(0:n-1), b(0:n-1)) copyout (c(0:n-1))
- do i = 0, n - 1 ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+ !$acc kernels copyin (a(0:n-1), b(0:n-1)) copyout (c(0:n-1)) ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+ do i = 0, n - 1
c(i) = a(i) + b(i)
end do
!$acc end kernels
diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95
index a23ea81..01f06bb 100644
--- a/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95
@@ -22,10 +22,10 @@ program main
end program main
! Check the offloaded function's attributes.
-! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp target entrypoint\\)\\)" 1 "ompexp" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc parallel, omp target entrypoint\\)\\)" 1 "ompexp" } }
! Check the offloaded function's classification and compute dimensions (will
! always be 1 x 1 x 1 for non-offloading compilation).
! { dg-final { scan-tree-dump-times "(?n)Function is OpenACC parallel offload" 1 "oaccdevlow" } }
! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
-! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), omp target entrypoint\\)\\)" 1 "oaccdevlow" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc parallel, omp target entrypoint\\)\\)" 1 "oaccdevlow" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95
new file mode 100644
index 0000000..51061af
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95
@@ -0,0 +1,31 @@
+! Check offloaded function's attributes and classification for OpenACC
+! serial.
+
+! { dg-additional-options "-O2" }
+! { dg-additional-options "-fopt-info-optimized-omp" }
+! { dg-additional-options "-fdump-tree-ompexp" }
+! { dg-additional-options "-fdump-tree-oaccdevlow" }
+
+program main
+ implicit none
+ integer, parameter :: n = 1024
+ integer, dimension (0:n-1) :: a, b, c
+ integer :: i
+
+ call setup(a, b)
+
+ !$acc serial loop copyin (a(0:n-1), b(0:n-1)) copyout (c(0:n-1)) ! { dg-message "optimized: assigned OpenACC gang vector loop parallelism" }
+ do i = 0, n - 1
+ c(i) = a(i) + b(i)
+ end do
+ !$acc end serial loop
+end program main
+
+! Check the offloaded function's attributes.
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc serial, omp target entrypoint\\)\\)" 1 "ompexp" } }
+
+! Check the offloaded function's classification and compute dimensions (will
+! always be 1 x 1 x 1 for non-offloading compilation).
+! { dg-final { scan-tree-dump-times "(?n)Function is OpenACC serial offload" 1 "oaccdevlow" } }
+! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc serial, omp target entrypoint\\)\\)" 1 "oaccdevlow" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/clause-locations.f90 b/gcc/testsuite/gfortran.dg/goacc/clause-locations.f90
deleted file mode 100644
index 29798d3..0000000
--- a/gcc/testsuite/gfortran.dg/goacc/clause-locations.f90
+++ /dev/null
@@ -1,18 +0,0 @@
-! Verify that the location information for clauses is correct.
-! See also PR 92793.
-
-subroutine check_clause_columns ()
- implicit none (type, external)
- integer :: i, j, sum, diff
-
- !$acc parallel
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:diff) reduction(-:sum) ! { dg-warning "47: conflicting reduction operations for .sum." }
- do j = 1, 10
- sum = 1
- end do
- end do
- !$acc end parallel
-end subroutine check_clause_columns
-
diff --git a/gcc/testsuite/gfortran.dg/goacc/fixed-5.f b/gcc/testsuite/gfortran.dg/goacc/fixed-5.f
new file mode 100644
index 0000000..ab51b21
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/fixed-5.f
@@ -0,0 +1,30 @@
+! Check that OpenMP conditional compilations sentinels ('!$ ') are ignored
+
+c$ bogus
+!$ bogus
+*$ bogus
+c$ bogus
+!$ bogus
+*$ bogus
+
+c$a23 bogus
+!$ a bogus
+*$12a bogus
+
+c$ 1 bogus
+!$ 22 bogus
+*$34 bogus
+
+c$bogus
+!$bogus
+*$bogus
+
+c$ acc bogus
+!$ acc bogus
+*$ acc bogus
+
+c$ acc bogus
+!$ acc bogus
+*$ acc bogus
+
+ end
diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-decompose-1.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-decompose-1.f95
new file mode 100644
index 0000000..7e513f8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/kernels-decompose-1.f95
@@ -0,0 +1,89 @@
+! Test OpenACC 'kernels' construct decomposition.
+
+! { dg-additional-options "-fopt-info-omp-all" }
+! { dg-additional-options "-fdump-tree-gimple" }
+! { dg-additional-options "-fopenacc-kernels=decompose" }
+! { dg-additional-options "-fdump-tree-omp_oacc_kernels_decompose" }
+
+! See also '../../c-c++-common/goacc/kernels-decompose-1.c'.
+
+! It's only with Tcl 8.5 (released in 2007) that "the variable 'varName'
+! passed to 'incr' may be unset, and in that case, it will be set to [...]",
+! so to maintain compatibility with earlier Tcl releases, we manually
+! initialize counter variables:
+! { dg-line l_dummy[variable c_loop_i 0] }
+! { dg-message "dummy" "" { target iN-VAl-Id } l_dummy } to avoid
+! "WARNING: dg-line var l_dummy defined, but not used".
+
+program main
+ implicit none
+ integer, parameter :: N = 1024
+ integer, dimension (1:N) :: a
+ integer :: i, sum
+
+ !$acc kernels copyin(a(1:N)) copy(sum)
+ ! { dg-bogus "optimized: assigned OpenACC seq loop parallelism" "TODO" { xfail *-*-* } .-1 }
+ !TODO Is this maybe the report that belongs to the XFAILed report further down? */
+
+ !$acc loop ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ sum = sum + a(i)
+ end do
+
+ sum = sum + 1 ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" }
+ a(1) = a(1) + 1
+
+ !$acc loop independent ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC gang vector loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ sum = sum + a(i)
+ end do
+
+ if (sum .gt. 10) then ! { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" }
+ !$acc loop ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-missed "unparallelized loop nest in OpenACC 'kernels' region: it's executed conditionally" "" { target *-*-* } l_loop_i$c_loop_i }
+ !TODO { dg-optimized "assigned OpenACC seq loop parallelism" "TODO" { xfail *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ sum = sum + a(i)
+ end do
+ end if
+
+ !$acc loop auto ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ sum = sum + a(i)
+ end do
+
+ !$acc end kernels
+end program main
+
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_kernels map\(to:a\[_[0-9]+\] \[len: _[0-9]+\]\) map\(alloc:a \[pointer assign, bias: _[0-9]+\]\) map\(tofrom:sum \[len: [0-9]+\]\)$} 1 "gimple" } }
+
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\)$} 2 "gimple" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\) independent$} 1 "gimple" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\) auto$} 1 "gimple" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop} 4 "gimple" } }
+
+! Check that the OpenACC 'kernels' got decomposed into 'data' and an enclosed
+! sequence of compute constructs.
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_data_kernels map\(to:a\[_[0-9]+\] \[len: _[0-9]+\]\) map\(tofrom:sum \[len: [0-9]+\]\)$} 1 "omp_oacc_kernels_decompose" } }
+! As noted above, we get three "old-style" kernel regions, one gang-single region, and one parallelized loop region.
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_kernels async\(-1\) map\(force_present:a\[_[0-9]+\] \[len: _[0-9]+\]\) map\(alloc:a \[pointer assign, bias: _[0-9]+\]\) map\(force_present:sum \[len: [0-9]+\]\)$} 3 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_parallelized async\(-1\) map\(force_present:a\[_[0-9]+\] \[len: _[0-9]+\]\) map\(alloc:a \[pointer assign, bias: _[0-9]+\]\) map\(force_present:sum \[len: [0-9]+\]\)$} 1 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_gang_single async\(-1\) num_gangs\(1\) map\(force_present:a\[_[0-9]+\] \[len: _[0-9]+\]\) map\(alloc:a \[pointer assign, bias: _[0-9]+\]\) map\(force_present:sum \[len: [0-9]+\]\)$} 1 "omp_oacc_kernels_decompose" } }
+!
+! 'data' plus five CCs.
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target } 6 "omp_oacc_kernels_decompose" } }
+
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\)$} 2 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\) independent$} 1 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop private\(i\) auto} 1 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma acc loop} 4 "omp_oacc_kernels_decompose" } }
+
+! Each of the parallel regions is async, and there is a final call to
+! __builtin_GOACC_wait.
+! { dg-final { scan-tree-dump-times "__builtin_GOACC_wait" 1 "omp_oacc_kernels_decompose" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-decompose-2.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-decompose-2.f95
new file mode 100644
index 0000000..22f65e5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/kernels-decompose-2.f95
@@ -0,0 +1,150 @@
+! Test OpenACC 'kernels' construct decomposition.
+
+! { dg-additional-options "-fopt-info-omp-all" }
+! { dg-additional-options "-fopenacc-kernels=decompose" }
+! { dg-additional-options "-O2" } for 'parloops'.
+
+! See also '../../c-c++-common/goacc/kernels-decompose-2.c'.
+
+! It's only with Tcl 8.5 (released in 2007) that "the variable 'varName'
+! passed to 'incr' may be unset, and in that case, it will be set to [...]",
+! so to maintain compatibility with earlier Tcl releases, we manually
+! initialize counter variables:
+! { dg-line l_dummy[variable c_loop_i 0 c_loop_j 0 c_loop_k 0 c_part 0] }
+! { dg-message "dummy" "" { target iN-VAl-Id } l_dummy } to avoid
+! "WARNING: dg-line var l_dummy defined, but not used".
+
+program main
+ implicit none
+
+ integer, external :: f_g
+ !$acc routine (f_g) gang
+ integer, external :: f_w
+ !$acc routine (f_w) worker
+ integer, external :: f_v
+ !$acc routine (f_v) vector
+ integer, external :: f_s
+ !$acc routine (f_s) seq
+
+ integer :: i, j, k
+ integer :: x, y, z
+ logical :: y_l
+ integer, parameter :: N = 10
+ integer :: a(N), b(N), c(N)
+
+ !$acc kernels
+ x = 0 ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" }
+ y = 0
+ y_l = x < 10
+ z = x
+ x = x + 1
+ ;
+ !$acc end kernels
+
+ !$acc kernels ! { dg-optimized "assigned OpenACC gang loop parallelism" }
+ do i = 1, N ! { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" }
+ a(i) = 0
+ end do
+ !$acc end kernels
+
+ !$acc kernels loop ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ b(i) = a(N - i + 1)
+ end do
+
+ !$acc kernels
+ !$acc loop ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ b(i) = a(N - i + 1)
+ end do
+
+ !$acc loop ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ c(i) = a(i) * b(i)
+ end do
+
+ a(z) = 0 ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" }
+
+ !$acc loop ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: forwarded loop nest in OpenACC 'kernels' region to 'parloops' for analysis" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ c(i) = c(i) + a(i)
+ end do
+
+ !$acc loop seq ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1 + 1, N
+ c(i) = c(i) + c(i - 1)
+ end do
+ !$acc end kernels
+
+ !$acc kernels
+ !TODO What does this mean?
+ !TODO { dg-optimized "assigned OpenACC worker vector loop parallelism" "" { target *-*-* } .-2 }
+ !$acc loop independent ! { dg-line l_loop_i[incr c_loop_i] }
+ ! { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_i$c_loop_i }
+ ! { dg-optimized "assigned OpenACC gang loop parallelism" "" { target *-*-* } l_loop_i$c_loop_i }
+ do i = 1, N
+ !$acc loop independent ! { dg-line l_loop_j[incr c_loop_j] }
+ ! { dg-optimized "assigned OpenACC worker loop parallelism" "" { target *-*-* } l_loop_j$c_loop_j }
+ do j = 1, N
+ !$acc loop independent ! { dg-line l_loop_k[incr c_loop_k] }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } l_loop_k$c_loop_k }
+ ! { dg-optimized "assigned OpenACC seq loop parallelism" "" { target *-*-* } l_loop_k$c_loop_k }
+ do k = 1, N
+ a(1 + mod(i + j + k, N)) &
+ = b(j) &
+ + f_v (c(k)) ! { dg-optimized "assigned OpenACC vector loop parallelism" }
+ end do
+ end do
+ end do
+
+ !TODO Should the following turn into "gang-single" instead of "parloops"?
+ !TODO The problem is that the first STMT is 'if (y <= 4) goto <D.2547>; else goto <D.2548>;', thus "parloops".
+ if (y < 5) then ! { dg-message "note: beginning 'parloops' part in OpenACC 'kernels' region" }
+ !$acc loop independent ! { dg-line l_loop_j[incr c_loop_j] }
+ ! { dg-missed "unparallelized loop nest in OpenACC 'kernels' region: it's executed conditionally" "" { target *-*-* } l_loop_j$c_loop_j }
+ do j = 1, N
+ b(j) = f_w (c(j))
+ end do
+ end if
+ !$acc end kernels
+
+ !$acc kernels
+ y = f_g (a(5)) ! { dg-line l_part[incr c_part] }
+ !TODO If such a construct is placed in its own part (like it is, here), can't this actually use gang paralelism, instead of "gang-single"?
+ ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" "" { target *-*-* } l_part$c_part }
+ ! { dg-optimized "assigned OpenACC gang worker vector loop parallelism" "" { target *-*-* } l_part$c_part }
+
+ !$acc loop independent ! { dg-line l_loop_j[incr c_loop_j] }
+ ! { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_j$c_loop_j }
+ ! { dg-optimized "assigned OpenACC gang loop parallelism" "" { target *-*-* } l_loop_j$c_loop_j }
+ do j = 1, N
+ b(j) = y + f_w (c(j)) ! { dg-optimized "assigned OpenACC worker vector loop parallelism" }
+ end do
+ !$acc end kernels
+
+ !$acc kernels
+ y = 3 ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" }
+
+ !$acc loop independent ! { dg-line l_loop_j[incr c_loop_j] }
+ ! { dg-message "note: parallelized loop nest in OpenACC 'kernels' region" "" { target *-*-* } l_loop_j$c_loop_j }
+ ! { dg-optimized "assigned OpenACC gang worker loop parallelism" "" { target *-*-* } l_loop_j$c_loop_j }
+ do j = 1, N
+ b(j) = y + f_v (c(j)) ! { dg-optimized "assigned OpenACC vector loop parallelism" }
+ end do
+
+ z = 2 ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" }
+ !$acc end kernels
+
+ !$acc kernels ! { dg-message "note: beginning 'gang-single' part in OpenACC 'kernels' region" }
+ !$acc end kernels
+end program main
diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
index 5583ffb..d01eee2 100644
--- a/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
@@ -1,5 +1,7 @@
! { dg-do compile }
! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-fopenacc-kernels=decompose" }
+! { dg-additional-options "-fdump-tree-omp_oacc_kernels_decompose" }
program test
implicit none
@@ -34,3 +36,6 @@ end program test
! { dg-final { scan-tree-dump-times "map\\(alloc:t\\)" 1 "original" } }
! { dg-final { scan-tree-dump-times "map\\(force_deviceptr:u\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_data_kernels if\(D\.[0-9]+\)$} 1 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_gang_single num_gangs\(1\) if\(D\.[0-9]+\) async\(-1\)$} 1 "omp_oacc_kernels_decompose" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-3.f95 b/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-3.f95
index 03cae74..5379fba 100644
--- a/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-3.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-3.f95
@@ -5,52 +5,52 @@ program test
integer :: i
!$acc parallel
- !$acc loop gang(5) ! { dg-error "num arguments" }
+ !$acc loop gang(5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc loop gang(num:5) ! { dg-error "num arguments" }
+ !$acc loop gang(num:5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc loop worker(5) ! { dg-error "num arguments" }
+ !$acc loop worker(5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc loop worker(num:5) ! { dg-error "num arguments" }
+ !$acc loop worker(num:5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc loop vector(5) ! { dg-error "length arguments" }
+ !$acc loop vector(5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc loop vector(length:5) ! { dg-error "length arguments" }
+ !$acc loop vector(length:5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
!$acc end parallel
- !$acc parallel loop gang(5) ! { dg-error "num arguments" }
+ !$acc parallel loop gang(5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc parallel loop gang(num:5) ! { dg-error "num arguments" }
+ !$acc parallel loop gang(num:5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc parallel loop worker(5) ! { dg-error "num arguments" }
+ !$acc parallel loop worker(5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc parallel loop worker(num:5) ! { dg-error "num arguments" }
+ !$acc parallel loop worker(num:5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc parallel loop vector(5) ! { dg-error "length arguments" }
+ !$acc parallel loop vector(5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
- !$acc parallel loop vector(length:5) ! { dg-error "length arguments" }
+ !$acc parallel loop vector(length:5) ! { dg-error "argument not permitted" }
DO i = 1,10
ENDDO
end
diff --git a/gcc/testsuite/gfortran.dg/goacc/loop-5.f95 b/gcc/testsuite/gfortran.dg/goacc/loop-5.f95
deleted file mode 100644
index d059cf7..0000000
--- a/gcc/testsuite/gfortran.dg/goacc/loop-5.f95
+++ /dev/null
@@ -1,357 +0,0 @@
-program test
- implicit none
- integer :: i, j
-
- !$acc kernels
- !$acc loop auto
- DO i = 1,10
- ENDDO
- !$acc loop gang
- DO i = 1,10
- ENDDO
- !$acc loop gang(5)
- DO i = 1,10
- ENDDO
- !$acc loop gang(num:5)
- DO i = 1,10
- ENDDO
- !$acc loop gang(static:5)
- DO i = 1,10
- ENDDO
- !$acc loop gang(static:*)
- DO i = 1,10
- ENDDO
- !$acc loop gang
- DO i = 1,10
- !$acc loop vector
- DO j = 1,10
- ENDDO
- !$acc loop worker
- DO j = 1,10
- ENDDO
- ENDDO
-
- !$acc loop worker
- DO i = 1,10
- ENDDO
- !$acc loop worker(5)
- DO i = 1,10
- ENDDO
- !$acc loop worker(num:5)
- DO i = 1,10
- ENDDO
- !$acc loop worker
- DO i = 1,10
- !$acc loop vector
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc loop gang worker
- DO i = 1,10
- ENDDO
-
- !$acc loop vector
- DO i = 1,10
- ENDDO
- !$acc loop vector(5)
- DO i = 1,10
- ENDDO
- !$acc loop vector(length:5)
- DO i = 1,10
- ENDDO
- !$acc loop vector
- DO i = 1,10
- ENDDO
- !$acc loop gang vector
- DO i = 1,10
- ENDDO
- !$acc loop worker vector
- DO i = 1,10
- ENDDO
-
- !$acc loop auto
- DO i = 1,10
- ENDDO
-
- !$acc loop tile(1)
- DO i = 1,10
- ENDDO
- !$acc loop tile(2)
- DO i = 1,10
- ENDDO
- !$acc loop tile(6-2)
- DO i = 1,10
- ENDDO
- !$acc loop tile(6+2)
- DO i = 1,10
- ENDDO
- !$acc loop tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop tile(*, 1)
- DO i = 1,10
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc loop tile(-1) ! { dg-warning "must be positive" }
- do i = 1,10
- enddo
- !$acc loop vector tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop vector gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop vector worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop gang worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc end kernels
-
-
- !$acc parallel
- !$acc loop tile(1)
- DO i = 1,10
- ENDDO
- !$acc loop tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop tile(2)
- DO i = 1,10
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc loop tile(-1) ! { dg-warning "must be positive" }
- do i = 1,10
- enddo
- !$acc loop vector tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop vector gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop vector worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc loop gang worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc end parallel
-
- !$acc kernels loop auto
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang(5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang(num:5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang(static:5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang(static:*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang
- DO i = 1,10
- !$acc kernels loop gang ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- ENDDO
-
- !$acc kernels loop worker
- DO i = 1,10
- ENDDO
- !$acc kernels loop worker(5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop worker(num:5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop worker
- DO i = 1,10
- !$acc kernels loop worker ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- !$acc kernels loop gang ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc kernels loop gang worker
- DO i = 1,10
- ENDDO
-
- !$acc kernels loop vector
- DO i = 1,10
- ENDDO
- !$acc kernels loop vector(5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop vector(length:5)
- DO i = 1,10
- ENDDO
- !$acc kernels loop vector
- DO i = 1,10
- !$acc kernels loop vector ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- !$acc kernels loop worker ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- !$acc kernels loop gang ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc kernels loop gang vector
- DO i = 1,10
- ENDDO
- !$acc kernels loop worker vector
- DO i = 1,10
- ENDDO
-
- !$acc kernels loop auto
- DO i = 1,10
- ENDDO
-
- !$acc kernels loop tile(1)
- DO i = 1,10
- ENDDO
- !$acc kernels loop tile(*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop tile(*, 1)
- DO i = 1,10
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc kernels loop tile(-1) ! { dg-warning "must be positive" }
- do i = 1,10
- enddo
- !$acc kernels loop vector tile(*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop vector gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop vector worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc kernels loop gang worker tile(*)
- DO i = 1,10
- ENDDO
-
- !$acc parallel loop auto
- DO i = 1,10
- ENDDO
- !$acc parallel loop gang
- DO i = 1,10
- ENDDO
- !$acc parallel loop gang(static:5)
- DO i = 1,10
- ENDDO
- !$acc parallel loop gang(static:*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop gang
- DO i = 1,10
- !$acc parallel loop gang ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- ENDDO
-
- !$acc parallel loop worker
- DO i = 1,10
- ENDDO
- !$acc parallel loop worker
- DO i = 1,10
- !$acc parallel loop worker ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- !$acc parallel loop gang ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc parallel loop gang worker
- DO i = 1,10
- ENDDO
-
- !$acc parallel loop vector
- DO i = 1,10
- !$acc parallel loop vector ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- !$acc parallel loop worker ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- !$acc parallel loop gang ! { dg-error "OpenACC construct inside of non-OpenACC region" }
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc parallel loop gang vector
- DO i = 1,10
- ENDDO
- !$acc parallel loop worker vector
- DO i = 1,10
- ENDDO
-
- !$acc parallel loop auto
- DO i = 1,10
- ENDDO
-
- !$acc parallel loop tile(1)
- DO i = 1,10
- ENDDO
- !$acc parallel loop tile(*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop tile(*, 1)
- DO i = 1,10
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc parallel loop tile(-1) ! { dg-warning "must be positive" }
- do i = 1,10
- enddo
- !$acc parallel loop vector tile(*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop vector gang tile(*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop vector worker tile(*)
- DO i = 1,10
- ENDDO
- !$acc parallel loop gang worker tile(*)
- DO i = 1,10
- ENDDO
-end
diff --git a/gcc/testsuite/gfortran.dg/goacc/loop-6.f95 b/gcc/testsuite/gfortran.dg/goacc/loop-6.f95
deleted file mode 100644
index d0855b4..0000000
--- a/gcc/testsuite/gfortran.dg/goacc/loop-6.f95
+++ /dev/null
@@ -1,74 +0,0 @@
-program test
- implicit none
- integer :: i, j
-
- !$acc parallel
- !$acc loop auto
- DO i = 1,10
- ENDDO
- !$acc loop gang
- DO i = 1,10
- ENDDO
- !$acc loop gang(static:5)
- DO i = 1,10
- ENDDO
- !$acc loop gang(static:*)
- DO i = 1,10
- ENDDO
- !$acc loop gang
- DO i = 1,10
- !$acc loop vector
- DO j = 1,10
- ENDDO
- !$acc loop worker
- DO j = 1,10
- ENDDO
- ENDDO
-
- !$acc loop worker
- DO i = 1,10
- ENDDO
- !$acc loop worker
- DO i = 1,10
- !$acc loop vector
- DO j = 1,10
- ENDDO
- ENDDO
- !$acc loop gang worker
- DO i = 1,10
- ENDDO
-
- !$acc loop vector
- DO i = 1,10
- ENDDO
- !$acc loop vector(5) ! { dg-error "length arguments" }
- DO i = 1,10
- ENDDO
- !$acc loop vector(length:5) ! { dg-error "length arguments" }
- DO i = 1,10
- ENDDO
- !$acc loop vector
- DO i = 1,10
- ENDDO
- !$acc loop gang vector
- DO i = 1,10
- ENDDO
- !$acc loop worker vector
- DO i = 1,10
- ENDDO
-
- !$acc loop auto
- DO i = 1,10
- ENDDO
- !$acc end parallel
-
- !$acc parallel loop vector
- DO i = 1,10
- ENDDO
- !$acc parallel loop vector(5) ! { dg-error "length arguments" }
- DO i = 1,10
- ENDDO
- !$acc parallel loop vector(length:5) ! { dg-error "length arguments" }
- DO i = 1,10
- ENDDO
-end
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-kernels.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-kernels.f90
new file mode 100644
index 0000000..60cb630
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-kernels.f90
@@ -0,0 +1,300 @@
+! Test cases of nested 'reduction' clauses expected to compile cleanly.
+
+! See also 'c-c++-common/goacc/nested-reductions-1-kernels.c'.
+
+subroutine acc_kernels ()
+ implicit none (type, external)
+ integer :: i, j, k, sum, diff
+
+ !$acc kernels
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop collapse(2) reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff)
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ !$acc end kernels
+end subroutine acc_kernels
+
+! The same tests as above, but using a combined kernels loop construct.
+
+subroutine acc_kernels_loop ()
+ implicit none (type, external)
+ integer :: h, i, j, k, l, sum, diff
+
+ !$acc kernels loop
+ do h = 1, 10
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop collapse(2) reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_kernels_loop
+
+! The same tests as above, but now the outermost reduction clause is on
+! the kernels region, not the outermost loop. */
+
+subroutine acc_kernels_reduction ()
+ implicit none (type, external)
+
+ ! In contrast to the 'parallel' construct, the 'reduction' clause is not
+ ! supported on the 'kernels' construct.
+end subroutine acc_kernels_reduction
+
+! The same tests as above, but using a combined kernels loop construct, and
+! the outermost reduction clause is on that one, not the outermost loop. */
+subroutine acc_kernels_loop_reduction ()
+ implicit none (type, external)
+ integer :: h, i, j, k, sum, diff
+
+ !$acc kernels loop reduction(+:sum)
+ do h = 1, 10
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ do i = 1, 10
+ !$acc loop
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_kernels_loop_reduction
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-parallel.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-parallel.f90
new file mode 100644
index 0000000..2915d67
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-parallel.f90
@@ -0,0 +1,404 @@
+! Test cases of nested 'reduction' clauses expected to compile cleanly.
+
+! See also 'c-c++-common/goacc/nested-reductions-1-parallel.c'.
+
+subroutine acc_parallel ()
+ implicit none (type, external)
+ integer :: i, j, k, sum, diff
+
+ !$acc parallel
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop collapse(2) reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff)
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ !$acc end parallel
+end subroutine acc_parallel
+
+! The same tests as above, but using a combined parallel loop construct.
+
+subroutine acc_parallel_loop ()
+ implicit none (type, external)
+ integer :: h, i, j, k, l, sum, diff
+
+ !$acc parallel loop
+ do h = 1, 10
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop collapse(2) reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_parallel_loop
+
+! The same tests as above, but now the outermost reduction clause is on
+! the parallel region, not the outermost loop. */
+
+subroutine acc_parallel_reduction ()
+ implicit none (type, external)
+ integer :: i, j, k, sum, diff
+
+ !$acc parallel reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ do i = 1, 10
+ !$acc loop
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff)
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff)
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ !$acc end parallel
+end subroutine acc_parallel_reduction
+
+! The same tests as above, but using a combined parallel loop construct, and
+! the outermost reduction clause is on that one, not the outermost loop. */
+subroutine acc_parallel_loop_reduction ()
+ implicit none (type, external)
+ integer :: h, i, j, k, sum, diff
+
+ !$acc parallel loop reduction(+:sum)
+ do h = 1, 10
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ do i = 1, 10
+ !$acc loop
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "insufficient partitioning available to parallelize loop" }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_parallel_loop_reduction
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-routine.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-routine.f90
new file mode 100644
index 0000000..17a5861
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-1-routine.f90
@@ -0,0 +1,88 @@
+! Test cases of nested 'reduction' clauses expected to compile cleanly.
+
+! See also 'c-c++-common/goacc/nested-reductions-1-routine.c'.
+
+subroutine acc_routine ()
+ implicit none (type, external)
+ !$acc routine gang
+
+ integer :: i, j, k, sum, diff
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop collapse(2) reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) reduction(+:sum)
+ do j = 1, 10
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(+:sum)
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(-:diff)
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+end subroutine acc_routine
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-kernels.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-kernels.f90
new file mode 100644
index 0000000..6ee41843
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-kernels.f90
@@ -0,0 +1,389 @@
+! Test erroneous cases of nested 'reduction' clauses.
+
+! See also 'c-c++-common/goacc/nested-reductions-2-kernels.c'.
+
+subroutine acc_kernels ()
+ implicit none (type, external)
+ integer :: i, j, k, l, sum, diff
+
+ !$acc kernels
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ !$acc end kernels
+end subroutine acc_kernels
+
+! The same tests as above, but using a combined kernels loop construct.
+
+subroutine acc_kernels_loop ()
+ implicit none (type, external)
+ integer :: h, i, j, k, l, sum, diff
+
+ !$acc kernels loop
+ do h = 1, 10
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_kernels_loop
+
+! The same tests as above, but now the outermost reduction clause is on
+! the kernels region, not the outermost loop.
+
+subroutine acc_kernels_reduction ()
+ implicit none (type, external)
+
+ ! In contrast to the 'parallel' construct, the 'reduction' clause is not
+ ! supported on the 'kernels' construct.
+end subroutine acc_kernels_reduction
+
+! The same tests as above, but using a combined kernels loop construct, and
+! the outermost reduction clause is on that one, not the outermost loop. */
+subroutine acc_kernels_loop_reduction ()
+ implicit none (type, external)
+ integer :: h, i, j, k, l, sum, diff
+
+ !$acc kernels loop reduction(+:sum)
+ do h = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "TODO" { xfail *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_kernels_loop_reduction
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-parallel.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-parallel.f90
new file mode 100644
index 0000000..8fa2cab
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-parallel.f90
@@ -0,0 +1,499 @@
+! Test erroneous cases of nested 'reduction' clauses.
+
+! See also 'c-c++-common/goacc/nested-reductions-2-parallel.c'.
+
+subroutine acc_parallel ()
+ implicit none (type, external)
+ integer :: i, j, k, l, sum, diff
+
+ !$acc parallel
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ !$acc end parallel
+end subroutine acc_parallel
+
+! The same tests as above, but using a combined parallel loop construct.
+
+subroutine acc_parallel_loop ()
+ implicit none (type, external)
+ integer :: h, i, j, k, l, sum, diff
+
+ !$acc parallel loop
+ do h = 1, 10
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_parallel_loop
+
+! The same tests as above, but now the outermost reduction clause is on
+! the parallel region, not the outermost loop.
+
+subroutine acc_parallel_reduction ()
+ implicit none (type, external)
+ integer :: i, j, k, l, sum, diff
+
+ !$acc parallel reduction(+:sum)
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ !$acc end parallel
+end subroutine acc_parallel_reduction
+
+! The same tests as above, but using a combined parallel loop construct, and
+! the outermost reduction clause is on that one, not the outermost loop. */
+subroutine acc_parallel_loop_reduction ()
+ implicit none (type, external)
+ integer :: h, i, j, k, l, sum, diff
+
+ !$acc parallel loop reduction(+:sum)
+ do h = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+ end do
+end subroutine acc_parallel_loop_reduction
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-routine.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-routine.f90
new file mode 100644
index 0000000..cc7802e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-2-routine.f90
@@ -0,0 +1,119 @@
+! Test erroneous cases of nested 'reduction' clauses.
+
+! See also 'c-c++-common/goacc/nested-reductions-2-routine.c'.
+
+subroutine acc_routine ()
+ implicit none (type, external)
+ !$acc routine gang
+ integer :: i, j, k, l, sum, diff
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(+:sum)
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(-:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, 10
+ !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do k = 1, 10
+ !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ do l = 1, 10
+ sum = 1
+ end do
+ end do
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) reduction(-:diff)
+ do i = 1, 10
+ !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ do j = 1, 10
+ !$acc loop reduction(+:sum)
+ do k = 1, 10
+ sum = 1
+ end do
+ end do
+
+ !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ do j = 1, 10
+ !$acc loop reduction(-:diff)
+ do k = 1, 10
+ diff = 1
+ end do
+ end do
+ end do
+end subroutine acc_routine
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-warn.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions-warn.f90
deleted file mode 100644
index ec36bc9..0000000
--- a/gcc/testsuite/gfortran.dg/goacc/nested-reductions-warn.f90
+++ /dev/null
@@ -1,674 +0,0 @@
-! Test erroneous cases of nested reduction loops.
-
-subroutine acc_parallel ()
- implicit none (type, external)
- integer :: i, j, k, l, sum, diff
-
- !$acc parallel
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(-:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- !$acc end parallel
-end subroutine acc_parallel
-
-! The same tests as above, but using a combined parallel loop construct.
-
-subroutine acc_parallel_loop ()
- implicit none (type, external)
- integer :: h, i, j, k, l, sum, diff
-
- !$acc parallel loop
- do h = 1, 10
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(-:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- end do
-end subroutine acc_parallel_loop
-
-! The same tests as above, but now the outermost reduction clause is on
-! the parallel region, not the outermost loop.
-
-subroutine acc_parallel_reduction ()
- implicit none (type, external)
- integer :: i, j, k, l, sum, diff
-
- !$acc parallel reduction(+:sum)
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(-:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- !$acc end parallel
-end subroutine acc_parallel_reduction
-
-! The same tests as above, but using a combined parallel loop construct, and
-! the outermost reduction clause is on that one, not the outermost loop. */
-subroutine acc_parallel_loop_reduction ()
- implicit none (type, external)
- integer :: h, i, j, k, l, sum, diff
-
- !$acc parallel loop reduction(+:sum)
- do h = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(-:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(max:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do i = 1, 10
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- end do
-end subroutine acc_parallel_loop_reduction
-
-! The same tests as above, but inside a routine construct.
-subroutine acc_routine ()
- implicit none (type, external)
- !$acc routine gang
- integer :: i, j, k, l, sum, diff
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(+:sum)
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(-:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
- do k = 1, 10
- !$acc loop reduction(*:sum) ! { dg-warning "conflicting reduction operations for .sum." }
- do l = 1, 10
- sum = 1
- end do
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
-end subroutine acc_routine
-
-subroutine acc_kernels ()
- integer :: i, j, k, sum, diff
-
- ! FIXME: No diagnostics are produced for these loops because reductions
- ! in kernels regions are not supported yet.
- !$acc kernels
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:diff)
- do j = 1, 10
- !$acc loop
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(-:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
- !$acc end kernels
-end subroutine acc_kernels
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-reductions.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-reductions.f90
deleted file mode 100644
index 3becafa..0000000
--- a/gcc/testsuite/gfortran.dg/goacc/nested-reductions.f90
+++ /dev/null
@@ -1,540 +0,0 @@
-! Test cases of nested reduction loops that should compile cleanly.
-
-subroutine acc_parallel ()
- implicit none (type, external)
- integer :: i, j, k, sum, diff
-
- !$acc parallel
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop collapse(2) reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop collapse(2) reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff)
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- !$acc end parallel
-end subroutine acc_parallel
-
-! The same tests as above, but using a combined parallel loop construct.
-
-subroutine acc_parallel_loop ()
- implicit none (type, external)
- integer :: h, i, j, k, l, sum, diff
-
- !$acc parallel loop
- do h = 1, 10
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop collapse(2) reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop collapse(2) reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- end do
-end subroutine acc_parallel_loop
-
-! The same tests as above, but now the outermost reduction clause is on
-! the parallel region, not the outermost loop. */
-
-subroutine acc_parallel_reduction ()
- implicit none (type, external)
- integer :: i, j, k, sum, diff
-
- !$acc parallel reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- do i = 1, 10
- !$acc loop
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- do i = 1, 10
- do j = 1, 10
- !$acc loop
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff)
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff)
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- !$acc end parallel
-end subroutine acc_parallel_reduction
-
-! The same tests as above, but using a combined parallel loop construct, and
-! the outermost reduction clause is on that one, not the outermost loop. */
-subroutine acc_parallel_loop_reduction ()
- implicit none (type, external)
- integer :: h, i, j, k, sum, diff
-
- !$acc parallel loop reduction(+:sum)
- do h = 1, 10
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- do i = 1, 10
- !$acc loop
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- do i = 1, 10
- do j = 1, 10
- !$acc loop
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum) ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop ! { dg-warning "insufficient partitioning available to parallelize loop" }
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
- end do
-end subroutine acc_parallel_loop_reduction
-
-! The same tests as above, but inside a routine construct.
-subroutine acc_routine ()
- implicit none (type, external)
- !$acc routine gang
-
- integer :: i, j, k, sum, diff
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop collapse(2) reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop collapse(2) reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum) reduction(-:diff)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
-
- !$acc loop reduction(-:diff)
- do j = 1, 10
- !$acc loop reduction(-:diff)
- do k = 1, 10
- diff = 1
- end do
- end do
- end do
-end subroutine acc_routine
-
-subroutine acc_kernels ()
- implicit none (type, external)
- integer :: i, j, k, sum, diff
-
- ! FIXME: These tests are not meaningful yet because reductions in
- ! kernels regions are not supported yet.
- !$acc kernels
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
-
- !$acc loop reduction(+:sum)
- do i = 1, 10
- !$acc loop reduction(+:sum)
- do j = 1, 10
- !$acc loop reduction(+:sum)
- do k = 1, 10
- sum = 1
- end do
- end do
- end do
-
- !$acc end kernels
-end subroutine acc_kernels
diff --git a/gcc/testsuite/gfortran.dg/goacc/pr92793-1.f90 b/gcc/testsuite/gfortran.dg/goacc/pr92793-1.f90
new file mode 100644
index 0000000..422131b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/pr92793-1.f90
@@ -0,0 +1,135 @@
+! Verify column location information.
+
+! See also 'c-c++-common/goacc/pr92793-1.c'.
+
+! { dg-additional-options "-fdump-tree-original-lineno" }
+! { dg-additional-options "-fdump-tree-gimple-lineno" }
+
+! No tabs. Funny indentation/spacing for a reason.
+
+
+subroutine check ()
+ implicit none (type, external)
+ integer :: i, j, sum, diff
+
+ !$acc parallel &
+ !$acc & & ! Fortran location information points to the last line, and last character of the directive.
+!$acc && ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:18:123\\\] #pragma acc parallel" 1 "original" } }
+ !$acc & ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:18:123\\\] #pragma omp target oacc_parallel" 1 "gimple" } }
+ !$acc loop &
+ !$acc & & ! Fortran location information points to the last line, and last character of the directive.
+ !$acc & & ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:26:22\\\] #pragma acc loop" 1 "original" } }
+ !$acc & & ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:26:22\\\] #pragma acc loop" 1 "gimple" } }
+ !$acc& reduction ( + : sum ) & ! { dg-line sum1 }
+ !$acc && ! Fortran location information points to the ':' in 'reduction(+:sum)'.
+ !$acc & & ! { dg-message "36: location of the previous reduction for 'sum'" "" { target *-*-* } sum1 }
+!$acc& independent
+ do i = 1, 10
+ !$acc loop &
+!$acc & & ! Fortran location information points to the last line, and last character of the directive.
+ !$acc & & ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:36:34\\\] #pragma acc loop" 1 "original" } }
+ !$acc & & ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:36:34\\\] #pragma acc loop" 1 "gimple" } }
+ !$acc & reduction(-: diff ) &
+ !$acc&reduction(- : sum) & ! { dg-line sum2 }
+ !$acc & & ! Fortran location information points to the ':' in 'reduction(-:sum)'.
+ !$acc& & ! { dg-warning "32: conflicting reduction operations for 'sum'" "" { target *-*-* } sum2 }
+ !$acc &independent
+ do j = 1, 10
+ sum &
+ & = &
+ & 1
+ ! Fortran location information points to the last line, and last character of the statement.
+ ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:40:9\\\] sum = 1" 1 "original" } }
+ ! { dg-final { scan-tree-dump-times "pr92793-1\\\.f90:40:9\\\] sum = 1" 1 "gimple" } }
+ end do
+ end do
+!$acc end parallel
+end subroutine check
+
+
+subroutine gwv_sl_1 ()
+ implicit none (type, external)
+ integer :: i
+
+ !$acc serial loop &
+ !$acc & gang(num:5) & ! { dg-error "25: argument not permitted on 'gang' clause" }
+ !$acc & worker(num:5) & ! { dg-error "24: argument not permitted on 'worker' clause" }
+ !$acc & vector(length:5) ! { dg-error "28: argument not permitted on 'vector' clause" }
+ ! { dg-message "93: enclosing parent compute construct" "" { target *-*-* } .-1 }
+ do i = 0, 10
+ end do
+ !$acc end serial loop
+end subroutine gwv_sl_1
+
+subroutine gwv_sl_2 ()
+ implicit none (type, external)
+ integer :: i, j, k
+
+ !$acc serial loop ! { dg-message "77: enclosing parent compute construct" }
+ do i = 0, 10
+ !$acc loop ! { dg-bogus "enclosing parent compute construct" }
+ do j = 0, 10
+ !$acc loop &
+ !$acc & gang(num:5) & ! { dg-error "35: argument not permitted on 'gang' clause" }
+ !$acc & worker(num:5) & ! { dg-error "32: argument not permitted on 'worker' clause" }
+ !$acc & vector(length:5) ! { dg-error "33: argument not permitted on 'vector' clause" }
+ do k = 0, 10
+ end do
+ end do
+ end do
+ !$acc end serial loop
+end subroutine gwv_sl_2
+
+subroutine gwv_s_l ()
+ implicit none (type, external)
+ integer :: i, j, k
+
+ !$acc serial ! { dg-message "72: enclosing parent compute construct" }
+ !$acc loop &
+ !$acc & gang(num:5) & ! { dg-error "27: argument not permitted on 'gang' clause" }
+ !$acc & worker(num:5) & ! { dg-error "23: argument not permitted on 'worker' clause" }
+ !$acc & vector(length:5) ! { dg-error "29: argument not permitted on 'vector' clause" }
+ do i = 0, 10
+ end do
+
+ !$acc loop
+ do i = 0, 10
+ !$acc loop ! { dg-bogus "enclosing parent compute construct" }
+ do j = 0, 10
+ !$acc loop &
+ !$acc & gang(num:5) & ! { dg-error "35: argument not permitted on 'gang' clause" }
+ !$acc & worker(num:5) & ! { dg-error "32: argument not permitted on 'worker' clause" }
+ !$acc & vector(length:5) ! { dg-error "37: argument not permitted on 'vector' clause" }
+ do k = 0, 10
+ end do
+ end do
+ end do
+!$acc end serial
+end subroutine gwv_s_l
+
+subroutine gwv_r () ! { dg-message "16: enclosing routine" }
+ implicit none (type, external)
+ integer :: i, j, k
+
+ !$acc routine(gwv_r)
+
+ !$acc loop &
+ !$acc & gang(num:5) & ! { dg-error "23: argument not permitted on 'gang' clause" }
+ !$acc & worker(num:5) & ! { dg-error "26: argument not permitted on 'worker' clause" }
+ !$acc & vector(length:5) ! { dg-error "27: argument not permitted on 'vector' clause" }
+ do i = 0, 10
+ end do
+
+ !$acc loop
+ do i = 0, 10
+ !$acc loop
+ do j = 0, 10
+ !$acc loop &
+ !$acc & gang(num:5) & ! { dg-error "31: argument not permitted on 'gang' clause" }
+ !$acc & worker(num:5) & ! { dg-error "31: argument not permitted on 'worker' clause" }
+ !$acc & vector(length:5) ! { dg-error "36: argument not permitted on 'vector' clause" }
+ do k = 0, 10
+ end do
+ end do
+ end do
+end subroutine gwv_r
diff --git a/gcc/testsuite/gfortran.dg/goacc/sentinel-free-form.f95 b/gcc/testsuite/gfortran.dg/goacc/sentinel-free-form.f95
index 1a3189c..00dac66 100644
--- a/gcc/testsuite/gfortran.dg/goacc/sentinel-free-form.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/sentinel-free-form.f95
@@ -10,7 +10,10 @@ program test
x = 0.0 !$acc parallel ! comment
! sentinel must appear as a single word
! $acc parallel ! comment
- !$ acc parallel ! { dg-error "Unclassifiable statement" }
+
+ ! note that '!$ ' is OpenMP's conditional compilation sentinel
+ !$ acc ignored_due_to_space ! comment
+
! directive lines must have space after sentinel
!$accparallel ! { dg-warning "followed by a space" }
do i = 1,10
@@ -18,4 +21,4 @@ program test
enddo
!$acc end parallel ! { dg-error "Unexpected" }
print *, x
-end \ No newline at end of file
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc/specification-part.f90 b/gcc/testsuite/gfortran.dg/goacc/specification-part.f90
new file mode 100644
index 0000000..14af6ae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/specification-part.f90
@@ -0,0 +1,100 @@
+! { dg-do compile }
+!
+! PR fortran/90111
+!
+! Check that OpenACC directives in everywhere in specification part,
+! i.e. it may appear before/after the use, import, implicit, and declaration
+!
+
+module m
+end module m
+
+subroutine foo0(kk)
+ use m
+ implicit none
+ integer :: jj, kk
+ !$acc routine
+end
+
+subroutine foo1()
+ use m
+ implicit none
+ !$acc routine
+ integer :: jj
+end
+
+subroutine foo2()
+ use m
+ !$acc routine
+ implicit none
+end
+
+subroutine foo3()
+ !$acc routine
+ use m
+ implicit none
+end
+
+module m2
+ interface
+ subroutine foo0(kk)
+ use m
+ import
+ implicit none
+ integer :: kk
+ !$acc routine
+ end
+ subroutine foo1()
+ use m
+ import
+ implicit none
+ !$acc routine
+ end
+ subroutine foo2()
+ use m
+ import
+ !$acc routine
+ implicit none
+ end
+ subroutine foo3()
+ use m
+ !$acc routine
+ import
+ implicit none
+ end
+ subroutine foo4()
+ use m
+ !$acc routine
+ import
+ implicit none
+ end
+ end interface
+end module m2
+
+subroutine bar0()
+ use m
+ implicit none
+ integer :: ii
+ !$acc declare copyin(ii)
+end
+
+subroutine bar1()
+ use m
+ implicit none
+ !$acc declare copyin(ii)
+ integer :: ii
+end
+
+subroutine bar2()
+ use m
+ !$acc declare copyin(ii)
+ implicit none
+ integer :: ii
+end
+
+subroutine bar3()
+ !$acc declare copyin(ii)
+ use m
+ implicit none
+ integer :: ii
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90
new file mode 100644
index 0000000..1de418d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic-2.f90
@@ -0,0 +1,70 @@
+! { dg-do compile }
+
+subroutine bar
+ integer :: i, v
+ real :: f
+ !$omp atomic update acq_rel hint("abc") ! { dg-error "OMP ATOMIC UPDATE at .1. incompatible with ACQ_REL or ACQUIRE clauses" }
+ ! { dg-error "HINT clause at .1. requires a scalar INTEGER expression" "" { target *-*-* } .-1 }
+ ! { dg-error "Value of HINT clause at .1. shall be a valid constant hint expression" "" { target *-*-* } .-2 }
+ i = i + 1
+ !$omp end atomic
+
+ !$omp atomic acq_rel ! { dg-error "OMP ATOMIC UPDATE at .1. incompatible with ACQ_REL or ACQUIRE clauses" }
+ i = i + 1
+ !$omp end atomic
+
+ !$omp atomic capture,acq_rel , hint (1)
+ i = i + 1
+ v = i
+ !$omp end atomic
+
+ !$omp atomic acq_rel , hint (1), update ! { dg-error "OMP ATOMIC UPDATE at .1. incompatible with ACQ_REL or ACQUIRE clauses" }
+ i = i + 1
+ !$omp end atomic
+
+ !$omp atomic hint(0),acquire capture
+ i = i + 1
+ v = i
+ !$omp end atomic
+
+ !$omp atomic write capture ! { dg-error "multiple atomic clauses" }
+ i = 2
+ v = i
+ !$omp end atomic
+
+ !$omp atomic foobar ! { dg-error "Failed to match clause" }
+end
+
+! moved here from atomic.f90
+subroutine openmp51_foo
+ integer :: x, v
+ !$omp atomic update seq_cst capture ! { dg-error "multiple atomic clauses" }
+ x = x + 2
+ v = x
+ !$omp end atomic
+ !$omp atomic seq_cst, capture, update ! { dg-error "multiple atomic clauses" }
+ x = x + 2
+ v = x
+ !$omp end atomic
+ !$omp atomic capture, seq_cst ,update ! { dg-error "multiple atomic clauses" }
+ x = x + 2
+ v = x
+ !$omp end atomic
+end
+
+subroutine openmp51_bar
+ integer :: i, v
+ real :: f
+ !$omp atomic relaxed capture update ! { dg-error "multiple atomic clauses" }
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic update capture,release , hint (1) ! { dg-error "multiple atomic clauses" }
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic hint(0),update relaxed capture ! { dg-error "multiple atomic clauses" }
+ i = i + 1
+ v = i
+ !$omp end atomic
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/atomic.f90 b/gcc/testsuite/gfortran.dg/gomp/atomic.f90
new file mode 100644
index 0000000..b4caf03
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/atomic.f90
@@ -0,0 +1,87 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+! { dg-final { scan-tree-dump-times "#pragma omp atomic relaxed" 4 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp atomic release" 4 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture relaxed" 2 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture release" 1 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic read acquire" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp atomic seq_cst" 7 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic read seq_cst" 3 "original" } }
+! { dg-final { scan-tree-dump-times "v = #pragma omp atomic capture seq_cst" 3 "original" } }
+
+
+subroutine foo ()
+ integer :: x, v
+ !$omp atomic
+ i = i + 2
+
+ !$omp atomic relaxed
+ i = i + 2
+
+ !$omp atomic seq_cst read
+ v = x
+ !$omp atomic seq_cst, read
+ v = x
+ !$omp atomic seq_cst write
+ x = v
+ !$omp atomic seq_cst ,write
+ x = v
+ !$omp atomic seq_cst update
+ x = x + v
+ !$omp atomic seq_cst , update
+ x = x + v
+ !$omp atomic seq_cst capture
+ x = x + 2
+ v = x
+ !$omp end atomic
+ !$omp atomic seq_cst, capture
+ x = x + 2
+ v = x
+ !$omp end atomic
+ !$omp atomic read , seq_cst
+ v = x
+ !$omp atomic write ,seq_cst
+ x = v
+ !$omp atomic update, seq_cst
+ x = x + v
+ !$omp atomic capture, seq_cst
+ x = x + 2
+ v = x
+ !$omp end atomic
+end
+
+subroutine bar
+ integer :: i, v
+ real :: f
+ !$omp atomic release, hint (0), update
+ i = i + 1
+ !$omp end atomic
+ !$omp atomic hint(0)seq_cst
+ i = i + 1
+ !$omp atomic relaxed,update,hint (0)
+ i = i + 1
+ !$omp atomic release
+ i = i + 1
+ !$omp atomic relaxed
+ i = i + 1
+ !$omp atomic relaxed capture
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic capture,release , hint (1)
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic hint(0),relaxed capture
+ i = i + 1
+ v = i
+ !$omp end atomic
+ !$omp atomic read acquire
+ v = i
+ !$omp atomic release,write
+ i = v
+ !$omp atomic hint(1),update,release
+ f = f + 2.0
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-target-4.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-target-4.f90
index 6e3f91e..8947b88 100644
--- a/gcc/testsuite/gfortran.dg/gomp/declare-target-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-target-4.f90
@@ -71,11 +71,11 @@ end module m2
! { dg-final { scan-tree-dump-times "omp declare target" 7 "original" } }
! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(" 7 "original" } }
-! { dg-final { scan-tree-dump-times "\[\n\r]\[\n\r]f1" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(any\\)\\)\\)\\)\[\n\r]f2" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(any\\)\\)\\)\\)\[\n\r]f3" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(host\\)\\)\\)\\)\[\n\r]f4" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(nohost\\)\\)\\)\\)\[\n\r]f5" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(any\\)\\)\\)\\)\[\n\r]s1" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(nohost\\)\\)\\)\\)\[\n\r]s2" 1 "original" } }
-! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(host\\)\\)\\)\\)\[\n\r]s3" 1 "original" } }
+! { dg-final { scan-tree-dump-not "__attribute__\\(\\(omp declare target \[^\n\r\]*\[\n\r\]void f1" "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(any\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r]void f2" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(any\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r\]void f3" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(host\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r\]void f4" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(nohost\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r\]void f5" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(any\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r\]void s1" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(nohost\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r\]void s2" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__attribute__\\(\\(omp declare target \\(device_type\\(host\\)\\)\\)\\)\[\n\r]__attribute__\[^\n\r]+\[\n\r\]void s3" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/map-2.f90 b/gcc/testsuite/gfortran.dg/gomp/map-2.f90
index 73c4f5a..79bab72 100644
--- a/gcc/testsuite/gfortran.dg/gomp/map-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/map-2.f90
@@ -2,5 +2,5 @@ type t
integer :: i
end type t
type(t) v
-!$omp target enter data map(to:v%i, v%i) ! { dg-error "appears more than once in map clauses" }
+!$omp target enter data map(to:v%i, v%i)
end
diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90
new file mode 100644
index 0000000..2e8aaa2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90
@@ -0,0 +1,143 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+!
+! (in_)reduction clause
+! Test all in-principle valid combinations, even if
+! not valid in this context (some fail at ME level)
+!
+implicit none
+integer :: a, b, i
+a = 0
+
+! ------------ parallel ------------
+!$omp parallel reduction(+:a)
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+!$omp parallel reduction(default,+:a)
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+!$omp parallel reduction(task,+:a)
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+
+! ------------ simd ------------
+!$omp simd reduction(+:a)
+do i=1,10
+ a = a + 1
+end do
+
+!$omp simd reduction(default,+:a)
+do i=1,10
+ a = a + 1
+end do
+
+!$omp simd reduction(task,+:a) ! { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'do' or 'sections'" }
+do i=1,10
+ a = a + 1
+end do
+
+! ------------ do ------------
+!$omp parallel
+!$omp do reduction(+:a)
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+!$omp parallel
+!$omp do reduction(default,+:a)
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+!$omp parallel
+!$omp do reduction(task,+:a)
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+! ------------ section ------------
+!$omp parallel
+!$omp sections reduction(+:a)
+ !$omp section
+ a = a + 1
+!$omp end sections
+!$omp end parallel
+
+!$omp parallel
+!$omp sections reduction(default,+:a)
+ !$omp section
+ a = a + 1
+!$omp end sections
+!$omp end parallel
+
+!$omp parallel
+!$omp sections reduction(task,+:a)
+ !$omp section
+ a = a + 1
+!$omp end sections
+!$omp end parallel
+
+! ------------ task ------------
+!$omp task in_reduction(+:a)
+ a = a + 1
+!$omp end task
+
+! ------------ taskloop ------------
+!$omp taskloop reduction(+:a) in_reduction(+:b)
+do i=1,10
+ a = a + 1
+end do
+
+!$omp taskloop reduction(default,+:a) in_reduction(+:b)
+do i=1,10
+ a = a + 1
+end do
+
+! ------------ target ------------
+!$omp target in_reduction(+:b)
+ a = a + 1
+!$omp end target
+
+! ------------ teams ------------
+!$omp teams reduction(+:b)
+ a = a + 1
+!$omp end teams
+
+!$omp teams reduction(default, +:b)
+ a = a + 1
+!$omp end teams
+
+! ------------ taskgroup --------
+
+!$omp taskgroup task_reduction(+:b)
+ a = a + 1
+!$omp end taskgroup
+
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(\\\+:a\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(task,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel\[\n\r\]" 6 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel private\\(i\\) reduction\\(\\\+:a\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel private\\(i\\) reduction\\(task,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp section\[\n\r\]" 3 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp sections reduction\\(\\\+:a\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp sections reduction\\(task,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(\\\+:a\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(task,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target in_reduction\\(\\\+:b\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task in_reduction\\(\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp teams reduction\\(\\\+:b\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp taskloop reduction\\(\\\+:a\\) in_reduction\\(\\\+:b\\)" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction5.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction5.f90
new file mode 100644
index 0000000..032703d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/reduction5.f90
@@ -0,0 +1,59 @@
+! { dg-do compile }
+!
+implicit none
+integer :: a, b, i
+a = 0
+
+!$omp parallel reduction(foo,+:a) ! { dg-error "26: Failed to match clause" }
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" }
+
+!$omp parallel reduction(task +:a) ! { dg-error "30: Comma expected at" }
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" }
+
+!$omp task in_reduction(foo,+:a) ! { dg-error "25: Failed to match clause" }
+ a = a + 1
+!$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" }
+
+!$omp taskloop reduction(inscan,+:a) in_reduction(+:b) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
+ ! { dg-error "34: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" "" { target *-*-* } .-1 }
+ ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause" "" { target *-*-* } .-2 }
+ ! { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" "" { target *-*-* } .-3 }
+do i=1,10
+ a = a + 1
+end do
+
+!$omp taskloop reduction(task,+:a) in_reduction(+:b) ! { dg-error "32: Only DEFAULT permitted as reduction-modifier in REDUCTION clause" }
+do i=1,10
+ a = a + 1
+end do
+
+!$omp teams reduction(inscan,+:b) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
+ ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause" "" { target *-*-* } .-1 }
+ a = a + 1
+!$omp end teams
+
+!$omp teams reduction(task, +:b) ! { dg-error "30: Only DEFAULT permitted as reduction-modifier in REDUCTION clause" }
+ a = a + 1
+!$omp end teams
+
+!$omp parallel reduction(inscan,+:a) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+
+!$omp parallel
+!$omp sections reduction(inscan,+:a) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
+ !$omp section
+ a = a + 1
+!$omp end sections
+!$omp end parallel
+
+
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction6.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction6.f90
new file mode 100644
index 0000000..6bf6851
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/reduction6.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+
+implicit none
+integer :: a, b, i
+a = 0
+
+!$omp simd reduction(inscan,+:a) ! { dg-error "30: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+do i=1,10
+ a = a + 1
+end do
+
+!$omp parallel
+!$omp do reduction(inscan,+:a) ! { dg-error "28: With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+do i=1,10
+ a = a + 1
+end do
+!$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction7.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction7.f90
new file mode 100644
index 0000000..7dc50e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/reduction7.f90
@@ -0,0 +1,9 @@
+implicit none
+integer :: a, b, i
+a = 0
+
+!$omp simd reduction(task,+:a) ! { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'do' or 'sections'" }
+do i=1,10
+ a = a + 1
+end do
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-4.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-4.f90
index e0eb4db..b17aceb 100644
--- a/gcc/testsuite/gfortran.dg/gomp/requires-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/requires-4.f90
@@ -26,11 +26,11 @@ program main
!$omp requires reverse_offload
contains
subroutine foo
- !$target
- !$end target
+ !$omp target
+ !$omp end target
end subroutine
subroutine bar
- !$omp requires unified_addres ! { dg-error "must appear in the specification part of a program unit" }
+ !$omp requires unified_address ! { dg-error "must appear in the specification part of a program unit" }
end subroutine bar
end
! { dg-prune-output "not yet supported" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-9.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-9.f90
index a2b0f50..d90940d 100644
--- a/gcc/testsuite/gfortran.dg/gomp/requires-9.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/requires-9.f90
@@ -80,6 +80,6 @@ end subroutine
! { dg-final { scan-tree-dump-times "#pragma omp atomic seq_cst\[\n\r]\[^\n\r]*&i5 =" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp atomic seq_cst\[\n\r]\[^\n\r]*&i5b =" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp atomic seq_cst\[\n\r]\[^\n\r]*&i6 =" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp atomic acq_rel\[\n\r]\[^\n\r]*&i7 =" 1 "original" } }
-! { dg-final { scan-tree-dump-times "#pragma omp atomic acq_rel\[\n\r]\[^\n\r]*&i7b =" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp atomic release\[\n\r]\[^\n\r]*&i7 =" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp atomic release\[\n\r]\[^\n\r]*&i7b =" 1 "original" } }
! { dg-final { scan-tree-dump-times "#pragma omp atomic seq_cst\[\n\r]\[^\n\r]*&i8 =" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-1.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-1.f90
new file mode 100644
index 0000000..8c879fd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-1.f90
@@ -0,0 +1,213 @@
+module m
+ integer a, b
+end module m
+
+subroutine f1
+ use m
+ !$omp scan inclusive (a) ! { dg-error "Unexpected ..OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+ !$omp scan exclusive (b) ! { dg-error "Unexpected ..OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+end
+
+subroutine f2 (c, d, e, f)
+ use m
+ implicit none
+ integer i, l, c(*), d(*), e(64), f(64)
+ l = 1
+
+ !$omp do reduction (inscan, +: a) reduction (+: b) ! { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" }
+ do i = 1, 64
+ block
+ b = b + 1
+ a = a + c(i)
+ end block
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+
+ !$omp do reduction (+: a) reduction (inscan, +: b) ! { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" }
+ do i = 1, 64
+ block
+ a = a + 1
+ b = b + c(i)
+ end block
+ !$omp scan inclusive (b)
+ d(i) = b
+ end do
+
+ !$omp do reduction (inscan, +: e)
+ do i = 1, 64
+ block
+ e(1) = e(1) + c(i)
+ e(2) = e(2) + c(i)
+ end block
+ !$omp scan inclusive (a, e)
+ block
+ d(1) = e(1)
+ f(2) = e(2)
+ end block
+ end do
+
+ !$omp do reduction (inscan, +: e(:2)) ! { dg-error "Syntax error in OpenMP variable list" }
+ do i = 1, 64
+ block
+ e(1) = e(1) + c(i)
+ e(2) = e(2) + c(i)
+ end block
+ !$omp scan inclusive (a, e) ! { dg-error "outside loop construct with 'inscan' REDUCTION clause" }
+ block
+ d(1) = e(1)
+ f(2) = e(2)
+ end block
+ end do
+
+ !$omp do reduction (inscan, +: a) ordered ! { dg-error "ORDERED clause specified together with 'inscan' REDUCTION clause" }
+ do i = 1, 64
+ a = a + c(i)
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+
+ !$omp do reduction (inscan, +: a) ordered(1) ! { dg-error "ORDERED clause specified together with 'inscan' REDUCTION clause" }
+ do i = 1, 64
+ a = a + c(i)
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+
+ !$omp do reduction (inscan, +: a) schedule(static) ! { dg-error "SCHEDULE clause specified together with 'inscan' REDUCTION clause" }
+ do i = 1, 64
+ a = a + c(i)
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+
+ !$omp do reduction (inscan, +: a) schedule(static, 2) ! { dg-error "SCHEDULE clause specified together with 'inscan' REDUCTION clause" }
+ do i = 1, 64
+ a = a + c(i)
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+
+ !$omp do reduction (inscan, +: a) schedule(nonmonotonic: dynamic, 2) ! { dg-error "SCHEDULE clause specified together with 'inscan' REDUCTION clause" }
+ do i = 1, 64
+ a = a + c(i)
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+end
+
+subroutine f3 (c, d)
+ use m
+ implicit none
+ integer i, c(64), d(64)
+ !$omp teams reduction (inscan, +: a) ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause at" }
+ ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
+ ! ...
+ !$omp end teams
+
+ !$omp target parallel do reduction (inscan, +: a) map (c, d)
+ ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+ !$omp teams
+ !$omp distribute parallel do reduction (inscan, +: a)
+ ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+ !$omp end teams
+
+ !$omp distribute parallel do simd reduction (inscan, +: a)
+ ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+end
+
+subroutine f4 (c, d)
+ use m
+ implicit none
+ integer i, c(64), d(64)
+ !$omp taskloop reduction (inscan, +: a) ! { dg-error "Only DEFAULT permitted as reduction-modifier in REDUCTION clause" }
+ ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" "" { target *-*-* } .-1 }
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+end
+
+subroutine f7
+ use m
+ implicit none
+ integer i
+ !$omp simd reduction (inscan, +: a)
+ do i = 1, 64
+ if (i == 23) then ! { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 }
+ cycle ! { dg-error "invalid branch to/from OpenMP structured block" "" { target c } }
+ elseif (i == 27) then
+ goto 123 ! Diagnostic by ME, see scan-7.f90
+ ! { dg-warning "is not in the same block as the GOTO statement" "" { target *-*-* } .-1 }
+ endif
+ !$omp scan exclusive (a)
+ block
+123 a = 0 ! { dg-error "jump to label 'l1'" "" { target c++ } }
+ ! { dg-warning "is not in the same block as the GOTO statement" "" { target *-*-* } .-1 }
+ if (i == 33) then ! { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 }
+ cycle ! { dg-error "invalid branch to/from OpenMP structured block" "" { target c } }
+ end if
+ end block
+ end do
+end
+
+subroutine f8 (c, d, e, f)
+ use m
+ implicit none
+ integer i, c(64), d(64), e(64), f(64)
+ !$omp do reduction (inscan, +: a, b) ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+ do i = 1, 64
+ block
+ a = a + c(i)
+ b = b + d(i)
+ end block
+ !$omp scan inclusive (a) inclusive (b) ! { dg-error "Unexpected junk after ..OMP SCAN" }
+ block
+ e(i) = a
+ f(i) = b
+ end block
+ end do
+
+ !$omp do reduction (inscan, +: a, b) ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+ do i = 1, 64
+ block
+ a = a + c(i)
+ b = b + d(i)
+ end block
+ !$omp scan ! { dg-error "Expected INCLUSIVE or EXCLUSIVE clause" }
+ block
+ e(i) = a
+ f(i) = b
+ end block
+ end do
+end
+
+subroutine f9
+ use m
+ implicit none
+ integer i
+! The first error (exit) causes two follow-up errors:
+ !$omp simd reduction (inscan, +: a) ! { dg-error "With INSCAN at .1., expected loop body with ..OMP SCAN between two structured-block-sequences" }
+ do i = 1, 64
+ if (i == 23) &
+ exit ! { dg-error "EXIT statement at .1. terminating ..OMP DO loop" } */
+ !$omp scan exclusive (a) ! { dg-error "Unexpected ..OMP SCAN at .1. outside loop construct with 'inscan' REDUCTION clause" }
+ a = a + 1
+ end do
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-2.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-2.f90
new file mode 100644
index 0000000..c057232
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-2.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+module m
+ integer :: a, b
+end module m
+
+subroutine f1 (c, d)
+ use m
+ implicit none
+ integer i, c(*), d(*)
+ !$omp simd reduction (inscan, +: a)
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(inscan,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp scan exclusive\\(a\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-3.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-3.f90
new file mode 100644
index 0000000..8318166
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-3.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+module m
+ integer :: a, b
+end module m
+
+subroutine f1 (c, d)
+ use m
+ implicit none
+ integer i, c(*), d(*)
+ !$omp do reduction (inscan, +: a)
+ do i = 1, 64
+ d(i) = a
+ !$omp scan inclusive (a)
+ a = a + c(i)
+ end do
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(inscan,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp scan inclusive\\(a\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-4.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-4.f90
new file mode 100644
index 0000000..c9e9d7e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-4.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+module m
+ integer a, b
+end module m
+
+subroutine f1 (c, d)
+ use m
+ implicit none
+ integer c(*), d(*), i
+ !$omp do simd reduction (inscan, +: a)
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(inscan,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(inscan,\\\+:a\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp scan exclusive\\(a\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-5.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-5.f90
new file mode 100644
index 0000000..a3789a5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-5.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+integer function foo(a,b, n) result(r)
+ implicit none
+ integer :: a(n), b(n), n, i
+ r = 0
+ !$omp parallel do reduction (inscan, +:r) default(none) firstprivate (a, b)
+ do i = 1, n
+ r = r + a(i)
+ !$omp scan inclusive (r)
+ b(i) = r
+ end do
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp parallel firstprivate\\(a\\) firstprivate\\(b\\) default\\(none\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for reduction\\(inscan,\\\+:r\\) nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp scan inclusive\\(r\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-6.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-6.f90
new file mode 100644
index 0000000..35d5869
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-6.f90
@@ -0,0 +1,16 @@
+module m
+ integer a, b
+end module m
+
+subroutine f3 (c, d)
+ use m
+ implicit none
+ integer i, c(64), d(64)
+ !$omp parallel reduction (inscan, +: a) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
+ ! ...
+ !$omp end parallel
+ !$omp sections reduction (inscan, +: a) ! { dg-error "'inscan' REDUCTION clause on construct other than DO, SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD" }
+ !$omp section
+ ! ...
+ !$omp end sections
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-7.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-7.f90
new file mode 100644
index 0000000..0446c5e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/scan-7.f90
@@ -0,0 +1,60 @@
+module m
+ integer a, b
+end module m
+
+subroutine f2 (c, d, e, f)
+ use m
+ implicit none
+ integer i, l, c(*), d(*), e(64), f(64)
+ l = 1
+
+ !$omp do reduction (inscan, +: a) linear (l) ! { dg-error "'inscan' 'reduction' clause used together with 'linear' clause for a variable other than loop iterator" }
+ do i = 1, 64
+ block
+ a = a + c(i)
+ l = l + 1
+ end block
+ !$omp scan inclusive (a)
+ d(i) = a
+ end do
+end
+
+subroutine f5 (c, d)
+ use m
+ implicit none
+ integer i, c(64), d(64)
+ !$omp simd reduction (inscan, +: a)
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a, b) ! { dg-error "'b' specified in 'exclusive' clause but not in 'inscan' 'reduction' clause on the containing construct" }
+ a = a + c(i)
+ end do
+end
+
+subroutine f6 (c, d)
+ use m
+ implicit none
+ integer i, c(64), d(64)
+ !$omp simd reduction (inscan, +: a, b) ! { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
+ do i = 1, 64
+ d(i) = a
+ !$omp scan exclusive (a)
+ a = a + c(i)
+ end do
+end
+
+subroutine f7
+ use m
+ implicit none
+ integer i
+ !$omp simd reduction (inscan, +: a)
+ do i = 1, 64
+ if (i == 27) goto 123 ! { dg-error "invalid branch to/from OpenMP structured block" }
+ ! { dg-warning "is not in the same block as the GOTO statement" "" { target *-*-* } .-1 }
+ !$omp scan exclusive (a)
+ block
+123 a = 0 ! { dg-error "jump to label 'l1'" "" { target c++ } }
+ ! { dg-warning "is not in the same block as the GOTO statement" "" { target *-*-* } .-1 }
+ end block
+ end do
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f90 b/gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f90
index 0be53cc..537fba2 100644
--- a/gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f90
@@ -3,16 +3,16 @@
subroutine foo
integer :: i
- !$omp do schedule (nonmonotonic: static, 2) ! { dg-error "NONMONOTONIC modifier specified for STATIC schedule kind" }
+ !$omp do schedule (nonmonotonic: static, 2)
do i = 0, 64
end do
- !$omp do schedule (nonmonotonic : static) ! { dg-error "NONMONOTONIC modifier specified for STATIC schedule kind" }
+ !$omp do schedule (nonmonotonic : static)
do i = 0, 64
end do
- !$omp do schedule (nonmonotonic : runtime) ! { dg-error "NONMONOTONIC modifier specified for RUNTIME schedule kind" }
+ !$omp do schedule (nonmonotonic : runtime)
do i = 0, 64
end do
- !$omp do schedule (nonmonotonic : auto) ! { dg-error "NONMONOTONIC modifier specified for AUTO schedule kind" }
+ !$omp do schedule (nonmonotonic : auto)
do i = 0, 64
end do
!$omp do schedule (nonmonotonic : dynamic) ordered ! { dg-error "NONMONOTONIC schedule modifier specified with ORDERED clause" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-1.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-1.f90
new file mode 100644
index 0000000..3e639d2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-1.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 0, 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_maybe_nonmonotonic_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (runtime)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-10.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-10.f90
new file mode 100644
index 0000000..e71ac3f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-10.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: static, 2)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-11.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-11.f90
new file mode 100644
index 0000000..9420220
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-11.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 2, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (dynamic)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-12.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-12.f90
new file mode 100644
index 0000000..66c6eb1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-12.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483650|-2147483646), 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: dynamic)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-13.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-13.f90
new file mode 100644
index 0000000..89782d2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-13.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 2, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: dynamic)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-14.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-14.f90
new file mode 100644
index 0000000..16b3e01
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-14.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 2, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (dynamic, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-15.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-15.f90
new file mode 100644
index 0000000..8bf126c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-15.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483650|-2147483646), 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: dynamic, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-16.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-16.f90
new file mode 100644
index 0000000..fe8d1ae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-16.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 2, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: dynamic, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-17.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-17.f90
new file mode 100644
index 0000000..1f2823d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-17.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 3, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (guided)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-18.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-18.f90
new file mode 100644
index 0000000..ad0856a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-18.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483651|-2147483645), 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: guided)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-19.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-19.f90
new file mode 100644
index 0000000..e884dbf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-19.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 3, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: guided)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-2.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-2.f90
new file mode 100644
index 0000000..2f78c0b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-2.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483648|-2147483648), 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: runtime)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-20.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-20.f90
new file mode 100644
index 0000000..8a4d6df
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-20.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 3, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (guided, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-21.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-21.f90
new file mode 100644
index 0000000..2d9362b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-21.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483651|-2147483645), 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: guided, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-22.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-22.f90
new file mode 100644
index 0000000..485171f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-22.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, 3, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: guided, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-23.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-23.f90
new file mode 100644
index 0000000..45dc000
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-23.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (auto)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-24.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-24.f90
new file mode 100644
index 0000000..e7fbe92
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-24.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: auto)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-25.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-25.f90
new file mode 100644
index 0000000..d5554c4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-25.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: auto)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-26.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-26.f90
new file mode 100644
index 0000000..d98f589
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-26.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 0, 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_maybe_nonmonotonic_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (runtime)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-27.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-27.f90
new file mode 100644
index 0000000..99a94f8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-27.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, (?:2147483648|-2147483648), 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: runtime)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-28.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-28.f90
new file mode 100644
index 0000000..bf28cba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-28.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 4, 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: runtime)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-29.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-29.f90
new file mode 100644
index 0000000..316b72e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-29.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-3.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-3.f90
new file mode 100644
index 0000000..bf28cba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-3.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 4, 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: runtime)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-30.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-30.f90
new file mode 100644
index 0000000..b9406d6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-30.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (static)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-31.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-31.f90
new file mode 100644
index 0000000..4a24604
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-31.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: static)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-32.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-32.f90
new file mode 100644
index 0000000..a7062d9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-32.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: static)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-33.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-33.f90
new file mode 100644
index 0000000..67c25c8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-33.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (static, 2)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-34.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-34.f90
new file mode 100644
index 0000000..f1e4d89
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-34.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: static, 2)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-35.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-35.f90
new file mode 100644
index 0000000..7d7c271
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-35.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: static, 2)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-36.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-36.f90
new file mode 100644
index 0000000..bfddf84
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-36.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 2, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (dynamic)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-37.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-37.f90
new file mode 100644
index 0000000..183d30b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-37.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, (?:2147483650|-2147483646), 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: dynamic)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-38.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-38.f90
new file mode 100644
index 0000000..3343388
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-38.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 2, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: dynamic)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-39.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-39.f90
new file mode 100644
index 0000000..a86a1e8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-39.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 2, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (dynamic, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-4.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-4.f90
new file mode 100644
index 0000000..c774427
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-4.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-40.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-40.f90
new file mode 100644
index 0000000..fedbd8f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-40.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, (?:2147483650|-2147483646), 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: dynamic, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-41.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-41.f90
new file mode 100644
index 0000000..a208b49
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-41.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 2, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: dynamic, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-42.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-42.f90
new file mode 100644
index 0000000..0542eca
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-42.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 3, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (guided)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-43.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-43.f90
new file mode 100644
index 0000000..bfd35c9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-43.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, (?:2147483651|-2147483645), 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: guided)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-44.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-44.f90
new file mode 100644
index 0000000..0cdc314
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-44.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 3, 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: guided)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-45.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-45.f90
new file mode 100644
index 0000000..a7130e9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-45.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 3, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (guided, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-46.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-46.f90
new file mode 100644
index 0000000..e769574
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-46.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, (?:2147483651|-2147483645), 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: guided, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-47.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-47.f90
new file mode 100644
index 0000000..06170d7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-47.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_start \[^\n\r]*, 3, 3, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_nonmonotonic_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: guided, 3)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-48.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-48.f90
new file mode 100644
index 0000000..1370010
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-48.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (auto)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-49.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-49.f90
new file mode 100644
index 0000000..ab2591f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-49.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: auto)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-5.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-5.f90
new file mode 100644
index 0000000..ce3db0f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-5.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (static)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-50.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-50.f90
new file mode 100644
index 0000000..8b89427
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-50.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_ull\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: auto)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-51.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-51.f90
new file mode 100644
index 0000000..13bde3a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-51.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_start \[^\n\r]*, (?:2147483648|-2147483648), 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_start " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do ordered reduction (task, *: j) schedule (runtime)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered
+ j = j + 1
+ !$omp end ordered
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-52.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-52.f90
new file mode 100644
index 0000000..50dce3d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-52.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_start \[^\n\r]*, (?:2147483649|-2147483647), 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_start " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_static_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do ordered reduction (task, *: j)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered
+ j = j + 1
+ !$omp end ordered
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-53.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-53.f90
new file mode 100644
index 0000000..0184209
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-53.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_start \[^\n\r]*, (?:2147483650|-2147483646), 4, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_start " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do ordered reduction (task, *: j) schedule (dynamic, 4)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered
+ j = j + 1
+ !$omp end ordered
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-54.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-54.f90
new file mode 100644
index 0000000..0681e43
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-54.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_start \[^\n\r]*, (?:2147483651|-2147483645), 6, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_start " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_ordered_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_ordered_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do ordered reduction (task, *: j) schedule (guided, 6)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered
+ j = j + 1
+ !$omp end ordered
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-55.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-55.f90
new file mode 100644
index 0000000..4d2e1e5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-55.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_doacross_start \[^\n\r]*, (?:2147483648|-2147483648), 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross_post " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross_wait " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_runtime_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do ordered(1) reduction (task, *: j) schedule (runtime)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered depend(sink: i - 1)
+ j = j + 1
+ !$omp ordered depend(source)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-56.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-56.f90
new file mode 100644
index 0000000..a5fa4c0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-56.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_doacross_start \[^\n\r]*, (?:2147483649|-2147483647), 0, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross(?:_ull)?_post " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross(?:_ull)?_wait " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_static_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do ordered(1) reduction (task, *: j)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered depend(sink: i - 1)
+ j = j + 1
+ !$omp ordered depend(source)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-57.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-57.f90
new file mode 100644
index 0000000..6c52aba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-57.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_doacross_start \[^\n\r]*, (?:2147483650|-2147483646), 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross(?:_ull)?_post " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross(?:_ull)?_wait " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop(?:_ull)?_dynamic_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer(8) :: j
+ interface
+ subroutine bar(i)
+ integer(8) :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer(8) :: a, b ,c
+ integer(8) :: i
+ !$omp parallel
+ !$omp do ordered(1) reduction (task, *: j) schedule (dynamic)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered depend(sink: i - 1)
+ j = j + 1
+ !$omp ordered depend(source)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-58.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-58.f90
new file mode 100644
index 0000000..ae4f8bc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-58.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_doacross_start \[^\n\r]*, (?:2147483651|-2147483645), 1, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross_post " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_doacross_wait " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_guided_next " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do ordered(1) reduction (task, *: j) schedule (guided)
+ do i = a, b, c
+ call bar (j)
+ !$omp ordered depend(sink: i - 1)
+ j = j + 1
+ !$omp ordered depend(source)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-6.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-6.f90
new file mode 100644
index 0000000..147f14a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-6.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: static)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-7.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-7.f90
new file mode 100644
index 0000000..dc99a75
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-7.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (nonmonotonic: static)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-8.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-8.f90
new file mode 100644
index 0000000..9d0a1ce
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-8.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (static, 2)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-9.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-9.f90
new file mode 100644
index 0000000..c613746
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/workshare-reduction-9.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-O2 -fopenmp -fdump-tree-optimized" }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_start \[^\n\r]*, (?:2147483649|-2147483647), 0, 0B, 0B, " 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_loop_end " 1 "optimized" } }
+! { dg-final { scan-tree-dump-not "__builtin_GOMP_loop\[^\n\r]*_next " "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_workshare_task_reduction_unregister \\(0\\)" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel " 1 "optimized" } }
+
+module m
+ implicit none (type, external)
+ integer :: j
+ interface
+ subroutine bar(i)
+ integer :: i
+ end subroutine
+ end interface
+end module m
+
+subroutine foo(a, b, c)
+ use m
+ implicit none (type, external)
+ integer :: a, b ,c
+ integer :: i
+ !$omp parallel
+ !$omp do reduction (task, *: j) schedule (monotonic: static, 2)
+ do i = a, b, c
+ j = j + 1
+ call bar (j)
+ end do
+ !$omp end parallel
+end
diff --git a/gcc/testsuite/gfortran.dg/guality/guality.exp b/gcc/testsuite/gfortran.dg/guality/guality.exp
index eaa7ae7..0375edf 100644
--- a/gcc/testsuite/gfortran.dg/guality/guality.exp
+++ b/gcc/testsuite/gfortran.dg/guality/guality.exp
@@ -19,7 +19,7 @@ global GDB
if ![info exists ::env(GUALITY_GDB_NAME)] {
if [info exists GDB] {
set guality_gdb_name "$GDB"
- } elseif [file exists $rootme/../gdb/gdb] {
+ } elseif { [info exists rootme] && [file exists $rootme/../gdb/gdb] } {
# If we're doing a combined build, and gdb is available, use it.
set guality_gdb_name "$rootme/../gdb/gdb"
} else {
diff --git a/gcc/testsuite/gfortran.dg/ipcp-array-2.f90 b/gcc/testsuite/gfortran.dg/ipcp-array-2.f90
new file mode 100644
index 0000000..9af8fff
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ipcp-array-2.f90
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! { dg-options "-O3 -fno-inline -fwhole-program -fdump-ipa-cp-details -fdump-tree-lversion-details" }
+
+module x
+ implicit none
+contains
+ subroutine foo(a, b)
+ real :: a(:,:)
+ real :: b
+ integer :: i,j
+ b = 0.
+ do j=1,size(a,2)
+ do i=1,size(a,1)
+ b = b + a(i,j) * i * j
+ end do
+ end do
+ end subroutine foo
+
+ subroutine bar(a, b)
+ real :: a(:,:)
+ real :: b
+ call foo (a,b)
+ end subroutine bar
+
+end module x
+
+program main
+ use x
+ implicit none
+ integer :: n, m
+ real, dimension(4,3) :: a
+ real, dimension(3,4) :: c
+ real :: b
+ call random_number(a)
+ call bar(a,b)
+ print *,b
+
+ call random_number(c)
+ call bar(c,b)
+ print *,b
+
+end program main
+
+! { dg-final { scan-ipa-dump "op assert_expr 1" "cp" } }
+! { dg-final { scan-tree-dump-not "versioned this loop for when certain strides are 1" "lversion" } }
diff --git a/gcc/testsuite/gfortran.dg/pr48958.f90 b/gcc/testsuite/gfortran.dg/pr48958.f90
new file mode 100644
index 0000000..2b10937
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr48958.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+! { dg-options "-fcheck=pointer -fdump-tree-original" }
+! { dg-shouldfail "Fortran runtime error: Allocatable argument 'a' is not allocated" }
+! { dg-output "At line 13 .*" }
+! PR48958 - Add runtime diagnostics for SIZE intrinsic function
+
+program p
+ integer :: n
+ integer, allocatable :: a(:)
+ integer, pointer :: b(:)
+ class(*), allocatable :: c(:)
+ integer :: d(10)
+ print *, size (a)
+ print *, size (b)
+ print *, size (c)
+ print *, size (d)
+ print *, size (f(n))
+contains
+ function f (n)
+ integer, intent(in) :: n
+ real, allocatable :: f(:)
+ end function f
+end
+
+! { dg-final { scan-tree-dump-times "_gfortran_runtime_error_at" 4 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/pr85796.f90 b/gcc/testsuite/gfortran.dg/pr85796.f90
new file mode 100644
index 0000000..7868378
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr85796.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR fortran/85796 - Floating point exception with implied do in data statement
+
+program p
+ implicit none
+ integer :: i, j, x(2,2)
+ data ((x(i,j),i=1,2,j-1),j=1,2) /3*789/ ! { dg-error "step of implied-do loop" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr93685_1.f90 b/gcc/testsuite/gfortran.dg/pr93685_1.f90
new file mode 100644
index 0000000..34d6e2c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr93685_1.f90
@@ -0,0 +1,20 @@
+! { dg-do run }
+! PR93685 - ICE in gfc_constructor_append_expr, at fortran/constructor.c:135
+
+program p
+ implicit none
+ type t
+ character, pointer :: a
+ end type t
+ type u
+ integer, pointer :: i
+ end type u
+ type(t) :: x
+ type(u) :: y
+ character, target :: c = 'c'
+ integer , target :: i = 10
+ data x%a /c/
+ data y%i /i/
+ if (x% a /= "c") stop 1
+ if (y% i /= 10) stop 2
+end
diff --git a/gcc/testsuite/gfortran.dg/pr93685_2.f90 b/gcc/testsuite/gfortran.dg/pr93685_2.f90
new file mode 100644
index 0000000..a09ce7e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr93685_2.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! PR93685 - ICE in gfc_constructor_append_expr, at fortran/constructor.c:135
+
+program p
+ implicit none
+ type t
+ character :: a
+ end type t
+ type u
+ integer :: i
+ end type u
+ type(t) :: x
+ type(u) :: y
+ character, target :: c = 'c'
+ integer , target :: i = 10
+ data x%a /c/ ! { dg-error "non-constant initialization expression" }
+ data y%i /i/ ! { dg-error "non-constant initialization expression" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr95342.f90 b/gcc/testsuite/gfortran.dg/pr95342.f90
new file mode 100644
index 0000000..41c987d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr95342.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! PR fortran/95342 - ICE in gfc_match_subroutine, at fortran/decl.c:7913
+
+module m1
+ interface
+ module subroutine s()
+ end
+ subroutine s() bind(c) ! { dg-error "EXTERNAL attribute conflicts" }
+ end ! { dg-error "END INTERFACE" }
+ end interface
+end
+
+module m2
+ interface
+ module function f()
+ end
+ function f() bind(c)
+ end ! { dg-error "Duplicate EXTERNAL attribute" }
+ end interface
+end
diff --git a/gcc/testsuite/gfortran.dg/pr97768_1.f90 b/gcc/testsuite/gfortran.dg/pr97768_1.f90
new file mode 100644
index 0000000..fce01e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr97768_1.f90
@@ -0,0 +1,25 @@
+! PR fortran/97768
+! { dg-do compile }
+
+module pr97768_1
+ interface operator(.in.)
+ module procedure substr_in_str
+ end interface
+contains
+ pure function to_upper (in_str) result (string)
+ character(len=*), intent(in) :: in_str
+ character(len=len(in_str)) :: string
+ string = in_str
+ end function to_upper
+ logical pure function substr_in_str (substring, string)
+ character(len=*), intent(in) :: string, substring
+ substr_in_str=.false.
+ end function
+end module
+function foo ()
+ use pr97768_1, only : to_upper, operator(.in.)
+ logical :: foo
+ character(len=8) :: str
+ str = 'abcde'
+ foo = 'b' .in. to_upper (str)
+end function foo
diff --git a/gcc/testsuite/gfortran.dg/pr97768_2.f90 b/gcc/testsuite/gfortran.dg/pr97768_2.f90
new file mode 100644
index 0000000..5dc1987
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr97768_2.f90
@@ -0,0 +1,53 @@
+! PR fortran/97768
+! { dg-do compile }
+
+module pr97768_2
+ interface operator(.in.)
+ module procedure substr_in_str
+ end interface
+contains
+ pure function to_upper (in_str) result (string)
+ character(len=*), intent(in) :: in_str
+ character(len=len(in_str)) :: string
+ string = in_str
+ end function to_upper
+ logical pure function substr_in_str (substring, string)
+ character(len=*), intent(in) :: string, substring
+ substr_in_str=.false.
+ end function
+end module
+function foo ()
+ use pr97768_2, only : to_upper, operator(.in.)
+ logical :: foo
+ character(len=8) :: str
+ str = 'abcde'
+ foo = to_upper (str) .in. 32 ! { dg-error "are CHARACTER/INTEGER" }
+end function foo
+function bar (str)
+ use pr97768_2, only : operator(.in.)
+ logical :: bar
+ character(len=*) :: str
+ foo = str .in. 32 ! { dg-error "are CHARACTER\\(\\*\\)/INTEGER" }
+end function bar
+function baz (lenstr)
+ use pr97768_2, only : operator(.in.)
+ logical :: baz
+ integer :: lenstr
+ character(len=lenstr) :: str
+ str = 'abc'
+ foo = str .in. 32 ! { dg-error "are CHARACTER/INTEGER" }
+end function baz
+function qux ()
+ use pr97768_2, only : operator(.in.)
+ logical :: qux
+ character(len=8) :: str
+ str = 'def'
+ foo = str .in. 32 ! { dg-error "are CHARACTER\\(8\\)/INTEGER" }
+end function qux
+function corge ()
+ use pr97768_2, only : operator(.in.)
+ logical :: corge
+ character(len=:), allocatable :: str
+ str = 'ghijk'
+ foo = str .in. 32 ! { dg-error "are CHARACTER\\(:\\)/INTEGER" }
+end function corge
diff --git a/gcc/testsuite/gfortran.dg/pr98016.f90 b/gcc/testsuite/gfortran.dg/pr98016.f90
new file mode 100644
index 0000000..71df67e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr98016.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+!
+! Fix for PR98016 - Used to fail with Error: Variable ‘n’ cannot appear in the
+! expression at (1) for line 16. Workaround was to declare y to be real.
+!
+! Posted by Juergen Reuter <juergen.reuter@desy.de>
+!
+program is_it_valid
+ dimension y(3)
+ n=3
+ y=func(1.0)
+ print *, y
+ stop
+contains
+ function func(x) result (y)
+ dimension y(n)
+ y=x
+ end function
+end
diff --git a/gcc/testsuite/gfortran.dg/pr98017.f90 b/gcc/testsuite/gfortran.dg/pr98017.f90
new file mode 100644
index 0000000..ab60407
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr98017.f90
@@ -0,0 +1,14 @@
+! { dg-do run }
+! PR98017 - [8/9/10/11 Regression] Suspected regression using PACK
+
+program p
+ implicit none
+ character(*), parameter :: s(1) = ['abc()']
+ character(*), parameter :: t(*) = s(:)(:1)
+ if (len (pack (s, s(:)(:1) == 'a')) /= len (s)) stop 1
+ if (any (pack (s, s(:)(:1) == 'a') /= s)) stop 2
+ if (len (pack (s, t == 'a')) /= len (s)) stop 3
+ if (any (pack (s, t == 'a') /= s)) stop 4
+ if (len (pack (s(:)(1:5), t == 'a')) /= len (s)) stop 5
+ if (any (pack (s(:)(1:5), t == 'a') /= s)) stop 6
+end
diff --git a/gcc/testsuite/gfortran.dg/pr98284.f90 b/gcc/testsuite/gfortran.dg/pr98284.f90
new file mode 100644
index 0000000..aa4b95c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr98284.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! PR fortran/98284 - ICE in get_array_index
+
+program p
+ implicit none
+ type t
+ integer, allocatable :: h(:)
+ end type t
+ type(t) :: u
+ integer :: i
+ data (u% h(i),i=1,8) /8*1/ ! { dg-error "cannot have the ALLOCATABLE attribute" }
+end
diff --git a/gcc/testsuite/gfortran.dg/select_rank_5.f90 b/gcc/testsuite/gfortran.dg/select_rank_5.f90
new file mode 100644
index 0000000..55aa9e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/select_rank_5.f90
@@ -0,0 +1,44 @@
+! { dg-do run }
+!
+! Test the fixes for PR97723 and PR97694.
+!
+! Contributed by Martin <mscfd@gmx.net>
+!
+module mod
+ implicit none
+ private
+ public cssel
+
+contains
+
+function cssel(x) result(s)
+ character(len=:), allocatable :: s
+ class(*), dimension(..), optional, intent(in) :: x
+ if (present(x)) then
+ select rank (x)
+ rank (0)
+ s = '0' ! PR97723: ‘assign’ at (1) is not a function
+ ! PR97694: ICE in trans-stmt.c(trans_associate_var)
+ rank (1)
+ s = '1' ! PR97723: ‘assign’ at (1) is not a function
+ rank default
+ s = '?' ! PR97723: ‘assign’ at (1) is not a function
+ end select
+ else
+ s = '-'
+ end if
+end function cssel
+
+end module mod
+
+program classstar_rank
+ use mod
+ implicit none
+
+ integer :: x
+ real, dimension(1:3) :: y
+ logical, dimension(1:2,1:2) :: z
+
+ if (any ([cssel(x),cssel(y),cssel(z),cssel()] .ne. ['0','1','?','-'])) stop 1
+
+end program classstar_rank
diff --git a/gcc/testsuite/gfortran.dg/structure_constructor_17.f90 b/gcc/testsuite/gfortran.dg/structure_constructor_17.f90
new file mode 100644
index 0000000..8b8230c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/structure_constructor_17.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+!
+! Test the fix for PR97612.
+!
+! Contributed by Martin Stein <mscfd@gmx.net>
+!
+program constructor_allocatable
+ implicit none
+
+ type :: s
+ integer, dimension(:), allocatable :: u
+ end type s
+
+ type :: t
+ type(s), dimension(:), allocatable :: x
+ end type t
+
+ type(t) :: a = t()
+ if (allocated (a%x)) stop 1
+
+end program constructor_allocatable
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f03 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f03
new file mode 100644
index 0000000..23d0540
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_32.f03
@@ -0,0 +1,59 @@
+! { dg-do run }
+!
+! Test the fix of the test case referenced in comment 17 of PR83118.
+!
+! Contributed by Damian Rouson <damian@sourceryinstitute.org>
+!
+ implicit none
+ type Wrapper
+ class(*), allocatable :: elements(:)
+ end type
+ type Mytype
+ real(4) :: r = 42.0
+ end type
+
+ call driver
+contains
+ subroutine driver
+ class(*), allocatable :: obj
+ type(Wrapper) w
+ integer(4) :: expected4(2) = [42_4, 43_4]
+ integer(8) :: expected8(3) = [42_8, 43_8, 44_8]
+
+ w = new_wrapper (expected4)
+ obj = w
+ call test (obj, 0)
+ obj = new_wrapper (expected8) ! Used to generate a linker error
+ call test (obj, 10)
+ obj = new_wrapper ([mytype (99.0)])
+ call test (obj, 100)
+ obj = Mytype (42.0) ! Used to generate a linker error
+ call test (obj, 1000)
+ end subroutine
+ function new_wrapper(array) result (res)
+ class(*) :: array(:)
+ type(Wrapper) :: res
+ res%elements = array ! Used to runtime segfault
+ end function
+ subroutine test (arg, idx)
+ class(*) :: arg
+ integer :: idx
+ select type (arg)
+ type is (wrapper)
+ select type (z => arg%elements)
+ type is (integer(4))
+ if (any (z .ne. [42_4, 43_4])) stop 1 + idx
+ type is (integer(8))
+ if (any (z .ne. [42_8, 43_8, 44_8])) stop 1 + idx
+ type is (Mytype)
+ if (abs (z(1)%r - 99.0) .ge. 1e-6) stop 1 + idx
+ class default
+ stop 2 + idx
+ end select
+ type is (Mytype)
+ if (abs (arg%r - 42.0) .ge. 1e-6) stop 1 + idx
+ class default
+ stop 3 + idx
+ end select
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/value_8.f90 b/gcc/testsuite/gfortran.dg/value_8.f90
new file mode 100644
index 0000000..8273fe8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/value_8.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! PR97491 - Wrong restriction for VALUE arguments of pure procedures
+
+pure function foo (x) result (ret)
+ integer :: ret
+ integer, value :: x
+ x = x / 2
+ ret = x
+end function foo
+
+elemental function foo1 (x)
+ integer :: foo1
+ integer, value :: x
+ x = x / 2
+ foo1 = x
+end function foo1
diff --git a/gcc/testsuite/gfortran.dg/vect/O3-bb-slp-1.f b/gcc/testsuite/gfortran.dg/vect/O3-bb-slp-1.f
new file mode 100644
index 0000000..74b3b17
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/O3-bb-slp-1.f
@@ -0,0 +1,28 @@
+! { dg-do compile }
+ subroutine tranx3 (jbeg,jend,kbeg,kend,dlo,den,mflx,zro)
+ parameter(in = 128+5
+ & , jn = 128+5
+ & , kn = 128+5)
+ parameter(ijkn = 128+5)
+ real*8 zro, dqm, dqp, dx3bi (kn)
+ real*8 mflux (ijkn,4), dtwid (ijkn,4), dd (ijkn,4)
+ real*8 mflx (in,jn,kn)
+ real*8 dlo (in,jn,kn), den (in,jn,kn)
+ do 2100 j=jbeg-1,jend
+ dtwid (k,1) = ( 0.5 + q1 ) * ( dlo(i ,j,k-1)
+ 3 - ( dx3a(k ) + xi ) * dd (k ,1) )
+ mflux (k,1) = dtwid (k,1) * ( v3(i ,j,k) - vg3(k) ) * dt
+ if (j.ge.jbeg) then
+ den(i ,j,k) = ( dlo(i ,j,k) * dvl3a(k)
+ 1 - etwid (k+1,1) + etwid (k,1) ) * dvl3a i(k)
+ if (kend .eq. ke) mflx(i ,j,ke+1) = mflux (ke+1,1)
+ endif
+ do 2030 k=max(kbeg-2,ks-1),kend+1
+ dqm = (dlo(i ,j,k ) - dlo(i ,j,k-1)) * dx3bi(k )
+ dqp = (dlo(i ,j,k+1) - dlo(i ,j,k )) * dx3bi(k+1)
+ dd(k,1) = max ( dqm * dqp, zro )
+2030 continue
+ dtwid (k,3) = ( 0.5 + q1 ) * ( dlo(i+2,j,k-1)
+ 3 - ( dx3a(k ) + xi ) * deod (k ,3) )
+2100 continue
+ end
diff --git a/gcc/testsuite/gfortran.dg/vect/O3-bb-slp-2.f b/gcc/testsuite/gfortran.dg/vect/O3-bb-slp-2.f
new file mode 100644
index 0000000..34c44de
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/O3-bb-slp-2.f
@@ -0,0 +1,40 @@
+! { dg-do compile }
+! { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } }
+ subroutine tranx3 (ibeg,jbeg,jend,kbeg,kend
+ & ,dlo,den
+ & ,edn)
+ parameter(in = 128+5
+ & , jn = 128+5
+ & , kn = 128+5)
+ parameter(ijkn = 128+5)
+ real*8 e (in,jn,kn), dqm, dvl3a (kn), dvl3ai (kn)
+ & , dtwid (ijkn,4), dd (ijkn,4)
+ & , etwid (ijkn,4), deod (ijkn,4)
+ real*8 dlo (in,jn,kn), den (in,jn,kn)
+ & , edn (in,jn,kn)
+ do 2100 j=jbeg-1,jend
+ i = ibeg - 1
+ do 1080 k=kbeg,kend
+ den(i ,j,k) = ( dlo(i ,j,k) * dvl3a(k)
+ 1 - etwid (k+1,1) + etwid (k,1) ) * dvl3a i(k)
+1080 continue
+ do 2030 k=max(kbeg-2,ks-1),kend+1
+ dqm = (dlo(i+2,j,k ) - dlo(i+2,j,k-1)) * dx3bi(k )
+ dd(k,4) = max ( dqm * dqp, zro )
+2030 continue
+ dtwid (k,3) = ( 0.5 + q1 ) * ( dlo(i+2,j,k-1)
+ 1 + ( dx3a(k-1) - xi ) * dd (k-1,3) )
+ 2 + ( 0.5 - q1 ) * ( dlo(i+2,j,k )
+ 3 - ( dx3a(k ) + xi ) * deod (k ,3) )
+ do 2080 k=kbeg,kend
+ den(i ,j,k) = ( dlo(i ,j,k) * dvl3a(k)
+ 1 - dtwid (k+1,3) + dtwid (k,3) ) * dvl3a i(k)
+ e (i+2,j,k) = ( e (i+2,j,k) * dvl3a(k)
+ 1 - etwid (k+1,3) + etwid (k,3) ) * dvl3a i(k)
+ edn(i+2,j,k) = e(i+2,j,k) / den(i+2,j,k)
+ e (i+3,j,k) = ( e (i+3,j,k) * dvl3a(k)
+ 1 - etwid (k+1,4) + etwid (k,4) ) * dvl3a i(k)
+ edn(i+3,j,k) = e(i+3,j,k) / den(i+3,j,k)
+2080 continue
+2100 continue
+ end
diff --git a/gcc/testsuite/gfortran.dg/vect/pr97761.f90 b/gcc/testsuite/gfortran.dg/vect/pr97761.f90
new file mode 100644
index 0000000..250e2bf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr97761.f90
@@ -0,0 +1,32 @@
+! { dg-do compile }
+! { dg-additional-options "-O1" }
+
+subroutine ni (ps)
+ type vector
+ real x, y
+ end type
+ type quad_inductor
+ type (vector) v1, v2
+ end type
+ type (quad_inductor), dimension(inout) :: ps
+ integer :: dl, nk = 1.0
+ fo = 1.0
+ if (f == 1) then
+ nk = 0.0
+ fo = 0.0
+ end if
+ ot = nk * 0.5
+ gb = -fo * 0.5
+ wu = fo * 0.5
+ up = nk * 0.1
+ xe = up * 0.1
+ do lx = 0, 7
+ ps%v2%y = -wu
+ ps(dl)%v1%x = xe + 1.0
+ ps(dl)%v1%y = wu - tn
+ end do
+ do lx = 0, 7
+ ps(dl)%v1%x = 0.1 - ot
+ ps(dl)%v1%y = 0.1 - wu
+ end do
+end
diff --git a/gcc/testsuite/gnat.dg/bias2.adb b/gcc/testsuite/gnat.dg/bias2.adb
new file mode 100644
index 0000000..a32e9a3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/bias2.adb
@@ -0,0 +1,33 @@
+-- { dg-do run }
+
+procedure Bias2 is
+
+ type Biased_T is range 1 .. 2 ** 6;
+ for Biased_T'Size use 6; -- { dg-warning "biased representation" }
+ X, Y : Biased_T;
+
+begin
+ X := 1;
+ Y := 1;
+ if X + Y /= 2 then
+ raise Program_Error;
+ end if;
+
+ X := 2;
+ Y := 1;
+ if X - Y /= 1 then
+ raise Program_Error;
+ end if;
+
+ X := 2;
+ Y := 3;
+ if X * Y /= 6 then
+ raise Program_Error;
+ end if;
+
+ X := 24;
+ Y := 3;
+ if X / Y /= 8 then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/debug15.adb b/gcc/testsuite/gnat.dg/debug15.adb
deleted file mode 100644
index 75470e3..0000000
--- a/gcc/testsuite/gnat.dg/debug15.adb
+++ /dev/null
@@ -1,23 +0,0 @@
--- { dg-do compile }
--- { dg-options "-g1" }
-
-procedure Debug15 is
-
- type Shape is abstract tagged record
- S : Integer;
- end record;
-
- type Rectangle is new Shape with record
- R : Integer;
- end record;
-
- X : Integer;
-
- R: Rectangle := (1, 2);
- S: Shape'Class := R;
-
-begin
- X := 12;
-end;
-
--- { dg-final { scan-assembler-not "loc 2" } }
diff --git a/gcc/testsuite/gnat.dg/interface6.adb b/gcc/testsuite/gnat.dg/interface6.adb
index 04eb1e1..556a0b7 100644
--- a/gcc/testsuite/gnat.dg/interface6.adb
+++ b/gcc/testsuite/gnat.dg/interface6.adb
@@ -35,7 +35,7 @@ procedure Interface6 is
end Test;
procedure Test_Instance1 is new Test (T => Rec_Type); -- { dg-error "actual must implement all interfaces of formal \"T\"" }
- procedure Test_Instance1 is new Test (T => Rec_Type1); -- { dg-error "Actual \"Rec_Type1\" must implement interface \"TI2\"" }
+ procedure Test_Instance1 is new Test (T => Rec_Type1); -- { dg-error "actual \"Rec_Type1\" must implement interface \"TI2\"" }
procedure Test_Instance2 is new Test (T => Rec_Type2);
procedure Test_Instance12 is new Test (T => Rec_Type12);
diff --git a/gcc/testsuite/gnat.dg/modular6.adb b/gcc/testsuite/gnat.dg/modular6.adb
new file mode 100644
index 0000000..f0f1c80
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/modular6.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Modular6 is
+ Max : Integer := 0;
+
+ type Modulus is mod 3;
+begin
+ Max := 30;
+
+ for N in 1 .. Max loop
+ Put_Line("N: " & Integer'Image(N) & " Modulus: " & Integer'Image(Modulus'Modulus) & " Mod:" & Modulus'Image(Modulus'Mod(N)));
+ end loop;
+end;
diff --git a/gcc/testsuite/gnat.dg/multfixed.adb b/gcc/testsuite/gnat.dg/multfixed.adb
index 572cd32..6eeda88 100644
--- a/gcc/testsuite/gnat.dg/multfixed.adb
+++ b/gcc/testsuite/gnat.dg/multfixed.adb
@@ -1,6 +1,7 @@
-- { dg-do run }
with Ada.Exceptions; use Ada.Exceptions;
+with Ada.Strings.Fixed; use Ada.Strings.Fixed;
procedure Multfixed is
Z : constant := 4387648782261400837.0;
@@ -18,7 +19,7 @@ begin
raise Program_Error;
exception
when Exc : Constraint_Error =>
- if Exception_Message (Exc) /= "System.Arith_64.Impl.Raise_Error: Double arithmetic overflow" then
+ if Count (Exception_Message (Exc), "overflow") = 0 then
raise Program_Error;
end if;
end Multfixed;
diff --git a/gcc/testsuite/gnat.dg/not_null.adb b/gcc/testsuite/gnat.dg/not_null.adb
index 3cbd86c..8f863d8 100644
--- a/gcc/testsuite/gnat.dg/not_null.adb
+++ b/gcc/testsuite/gnat.dg/not_null.adb
@@ -10,9 +10,9 @@ procedure not_null is
begin
declare
- pragma Warnings (Off, "*null not allowed in null-excluding objects");
+ pragma Warnings (Off, "*""null"" not allowed in null-excluding objects");
package Inst_2 is new GPack (null);
- pragma Warnings (On, "*null not allowed in null-excluding objects");
+ pragma Warnings (On, "*""null"" not allowed in null-excluding objects");
begin
null;
end;
diff --git a/gcc/testsuite/gnat.dg/opt39.adb b/gcc/testsuite/gnat.dg/opt39.adb
index 0a5ef67..f2e983f 100644
--- a/gcc/testsuite/gnat.dg/opt39.adb
+++ b/gcc/testsuite/gnat.dg/opt39.adb
@@ -1,5 +1,6 @@
-- { dg-do compile }
-- { dg-options "-O2 -fno-inline -fdump-tree-optimized" }
+-- { dg-additional-options "-cargs --param=sra-max-scalarization-size-Ospeed=32 -margs" { target powerpc*-*-* } }
procedure Opt39 (I : Integer) is
diff --git a/gcc/testsuite/gnat.dg/opt88.adb b/gcc/testsuite/gnat.dg/opt88.adb
new file mode 100644
index 0000000..a6abd01
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt88.adb
@@ -0,0 +1,52 @@
+-- { dg-do run }
+-- { dg-options "-O -ftree-vrp -fno-inline" }
+
+procedure Opt88 is
+
+ Val : Integer := 1;
+
+ procedure Dummy (B : out Boolean) is
+ begin
+ B := True;
+ end;
+
+ function Test return Boolean is
+ begin
+ return False;
+ end;
+
+ procedure Do_It (OK : out Boolean) is
+
+ Blue : Boolean := False;
+ Red : Boolean := False;
+
+ begin
+ OK := True;
+ Blue := True;
+ Dummy (Red);
+
+ if Red then
+ Red := False;
+
+ if Test then
+ Dummy (Red);
+ end if;
+ end if;
+
+ if Blue and not Red then
+ Val := 0;
+ end if;
+
+ if Red then
+ OK := False;
+ end if;
+ end;
+
+ OK : Boolean;
+
+begin
+ Do_It (OK);
+ if not OK then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt89.adb b/gcc/testsuite/gnat.dg/opt89.adb
new file mode 100644
index 0000000..3752008
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt89.adb
@@ -0,0 +1,18 @@
+-- { dg-do run }
+-- { dg-options "-O" }
+
+procedure Opt89 is
+
+ type Rec is record
+ I : Integer := 3;
+ end record;
+
+ subtype Index is Natural range 0..0;
+
+ type Arr is array (Index range <>) of Rec;
+
+ X : Arr (0 .. -1);
+
+begin
+ null;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt90a.adb b/gcc/testsuite/gnat.dg/opt90a.adb
new file mode 100644
index 0000000..7de6289
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90a.adb
@@ -0,0 +1,16 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Ada.Calendar; use Ada.Calendar;
+with Opt90a_Pkg; use Opt90a_Pkg;
+
+procedure Opt90a is
+ B : constant Integer := Year (Clock);
+ V : Data;
+
+begin
+ V := (R => (A => 0, B => B, C => "000000000000"));
+ if V.R.B /= B then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt90a_pkg.ads b/gcc/testsuite/gnat.dg/opt90a_pkg.ads
new file mode 100644
index 0000000..10a527b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90a_pkg.ads
@@ -0,0 +1,15 @@
+package Opt90a_Pkg is
+
+ type Rec is record
+ A : Short_Short_Integer;
+ B : Integer;
+ C : String (1 .. 12);
+ end record;
+ pragma Pack (Rec);
+ for Rec'Alignment use 1;
+
+ type Data is tagged record
+ R : Rec;
+ end record;
+
+end Opt90a_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt90b.adb b/gcc/testsuite/gnat.dg/opt90b.adb
new file mode 100644
index 0000000..6da58bb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90b.adb
@@ -0,0 +1,16 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Ada.Calendar; use Ada.Calendar;
+with Opt90b_Pkg; use Opt90b_Pkg;
+
+procedure Opt90b is
+ B : constant Integer := Year (Clock);
+ V : Data;
+
+begin
+ V := (R => (A => 0, B => B, C => 0, D => "000000000000"));
+ if V.R.B /= B then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt90b_pkg.ads b/gcc/testsuite/gnat.dg/opt90b_pkg.ads
new file mode 100644
index 0000000..f0b233c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90b_pkg.ads
@@ -0,0 +1,16 @@
+package Opt90b_Pkg is
+
+ type Rec is record
+ A : Short_Short_Integer;
+ B : Integer;
+ C : Short_Integer;
+ D : String (1 .. 12);
+ end record;
+ pragma Pack (Rec);
+ for Rec'Alignment use 1;
+
+ type Data is tagged record
+ R : Rec;
+ end record;
+
+end Opt90b_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt90c.adb b/gcc/testsuite/gnat.dg/opt90c.adb
new file mode 100644
index 0000000..b4f4c27
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90c.adb
@@ -0,0 +1,16 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Ada.Calendar; use Ada.Calendar;
+with Opt90c_Pkg; use Opt90c_Pkg;
+
+procedure Opt90c is
+ B : constant Integer := Year (Clock);
+ V : Data;
+
+begin
+ V := (R => (A => 0, B => B, C => 0, D => "000000000000"));
+ if V.R.B /= B then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt90c_pkg.ads b/gcc/testsuite/gnat.dg/opt90c_pkg.ads
new file mode 100644
index 0000000..e772340
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90c_pkg.ads
@@ -0,0 +1,16 @@
+package Opt90c_Pkg is
+
+ type Rec is record
+ D : String (1 .. 12);
+ B : Integer;
+ A : Short_Short_Integer;
+ C : Short_Integer;
+ end record;
+ pragma Pack (Rec);
+ for Rec'Alignment use 1;
+
+ type Data is tagged record
+ R : Rec;
+ end record;
+
+end Opt90c_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt90d.adb b/gcc/testsuite/gnat.dg/opt90d.adb
new file mode 100644
index 0000000..32ecb68
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90d.adb
@@ -0,0 +1,16 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Ada.Calendar; use Ada.Calendar;
+with Opt90d_Pkg; use Opt90d_Pkg;
+
+procedure Opt90d is
+ B : constant Integer := Year (Clock);
+ V : Data;
+
+begin
+ V := (R => (A => 0, B => B, C => 0, D => "000000000000"));
+ if V.R.B /= B then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt90d_pkg.ads b/gcc/testsuite/gnat.dg/opt90d_pkg.ads
new file mode 100644
index 0000000..a68b224
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90d_pkg.ads
@@ -0,0 +1,16 @@
+package Opt90d_Pkg is
+
+ type Rec is record
+ D : String (1 .. 12);
+ C : Short_Integer;
+ A : Short_Short_Integer;
+ B : Integer;
+ end record;
+ pragma Pack (Rec);
+ for Rec'Alignment use 1;
+
+ type Data is tagged record
+ R : Rec;
+ end record;
+
+end Opt90d_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt90e.adb b/gcc/testsuite/gnat.dg/opt90e.adb
new file mode 100644
index 0000000..6d62774
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90e.adb
@@ -0,0 +1,16 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Ada.Calendar; use Ada.Calendar;
+with Opt90e_Pkg; use Opt90e_Pkg;
+
+procedure Opt90e is
+ B : constant Integer := Year (Clock);
+ V : Data;
+
+begin
+ V := (R => (A => 0, B => B, C => 0, D => "000000000000"));
+ if V.R.B /= B then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt90e_pkg.ads b/gcc/testsuite/gnat.dg/opt90e_pkg.ads
new file mode 100644
index 0000000..fba16d7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt90e_pkg.ads
@@ -0,0 +1,16 @@
+package Opt90e_Pkg is
+
+ type Rec is record
+ D : String (1 .. 12);
+ A : Short_Short_Integer;
+ B : Integer;
+ C : Short_Integer;
+ end record;
+ pragma Pack (Rec);
+ for Rec'Alignment use 1;
+
+ type Data is tagged record
+ R : Rec;
+ end record;
+
+end Opt90e_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt91.adb b/gcc/testsuite/gnat.dg/opt91.adb
new file mode 100644
index 0000000..b0132f8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -fchecking=1" }
+
+package body Opt91 is
+
+ function Custom_Image (Self : True_Relation_Rec) return String is
+ begin
+ return "<True>";
+ end;
+
+end Opt91;
diff --git a/gcc/testsuite/gnat.dg/opt91.ads b/gcc/testsuite/gnat.dg/opt91.ads
new file mode 100644
index 0000000..b31aa8d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91.ads
@@ -0,0 +1,10 @@
+with Opt91_Pkg; use Opt91_Pkg;
+
+package Opt91 is
+
+ type True_Relation_Rec is null record;
+ function Custom_Image (Self : True_Relation_Rec) return String;
+
+ package True_Relation is new Pure_Relation (Ty => True_Relation_Rec);
+
+end Opt91;
diff --git a/gcc/testsuite/gnat.dg/opt91_pkg.adb b/gcc/testsuite/gnat.dg/opt91_pkg.adb
new file mode 100644
index 0000000..5b95fb2e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91_pkg.adb
@@ -0,0 +1,12 @@
+package body Opt91_Pkg is
+
+ package body Pure_Relation is
+
+ overriding function Custom_Image (Self : Rel) return String is
+ begin
+ return Custom_Image (Self.Rel);
+ end Custom_Image;
+
+ end Pure_Relation;
+
+end Opt91_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt91_pkg.ads b/gcc/testsuite/gnat.dg/opt91_pkg.ads
new file mode 100644
index 0000000..9bfd0f0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91_pkg.ads
@@ -0,0 +1,19 @@
+package Opt91_Pkg is
+
+ type Base_Relation is abstract tagged null record;
+
+ function Custom_Image (Self : Base_Relation) return String is abstract;
+
+ generic
+ type Ty is private;
+ with function Custom_Image (Self : Ty) return String is <>;
+ package Pure_Relation is
+
+ type Rel is new Base_Relation with record
+ Rel : Ty;
+ end record;
+
+ overriding function Custom_Image (Self : Rel) return String;
+ end Pure_Relation;
+
+end Opt91_Pkg;
diff --git a/gcc/testsuite/gnat.dg/protected_func.adb b/gcc/testsuite/gnat.dg/protected_func.adb
index f3eead4..055bf5d 100644
--- a/gcc/testsuite/gnat.dg/protected_func.adb
+++ b/gcc/testsuite/gnat.dg/protected_func.adb
@@ -4,8 +4,8 @@ package body Protected_Func with SPARK_Mode is
protected body Prot_Obj is
function Prot_Func return Integer is
begin
- Comp := Comp + 1; -- { dg-error "protected function cannot modify protected object" }
- Part_Of_Constit := Part_Of_Constit + 1; -- { dg-error "protected function cannot modify protected object" }
+ Comp := Comp + 1; -- { dg-error "protected function cannot modify its protected object" }
+ Part_Of_Constit := Part_Of_Constit + 1; -- { dg-error "protected function cannot modify its protected object" }
return Comp + Part_Of_Constit;
end Prot_Func;
diff --git a/gcc/testsuite/gnat.dg/shift1.adb b/gcc/testsuite/gnat.dg/shift1.adb
new file mode 100644
index 0000000..85a0fec
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/shift1.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+procedure Shift1 is
+
+ type T_Integer_8 is range -2 ** 7 .. 2 ** 7 - 1
+ with Size => 8;
+
+ pragma Provide_Shift_Operators (T_Integer_8);
+
+ X : T_Integer_8;
+
+begin
+ X := Shift_Right (X, 1);
+end;
diff --git a/gcc/testsuite/gnat.dg/sin_cos.adb b/gcc/testsuite/gnat.dg/sin_cos.adb
new file mode 100644
index 0000000..6e18df9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sin_cos.adb
@@ -0,0 +1,14 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -gnatn" }
+
+with Ada.Numerics.Elementary_Functions;
+use Ada.Numerics.Elementary_Functions;
+package body Sin_Cos is
+ procedure Sin_Cos (Angle : T; SinA, CosA : out T) is
+ begin
+ SinA := Sin (Angle);
+ CosA := Cos (Angle);
+ end;
+end Sin_Cos;
+
+-- { dg-final { scan-assembler "sincos\|cexp" { target *-linux-gnu* *-w64-mingw* *-*-vxworks* } } }
diff --git a/gcc/testsuite/gnat.dg/sin_cos.ads b/gcc/testsuite/gnat.dg/sin_cos.ads
new file mode 100644
index 0000000..a0eff3d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sin_cos.ads
@@ -0,0 +1,4 @@
+package Sin_Cos is
+ subtype T is Float;
+ procedure Sin_Cos (Angle : T; SinA, CosA : out T);
+end Sin_Cos;
diff --git a/gcc/testsuite/gnat.dg/warn14.adb b/gcc/testsuite/gnat.dg/warn14.adb
index d7fbece..f9d03d1 100644
--- a/gcc/testsuite/gnat.dg/warn14.adb
+++ b/gcc/testsuite/gnat.dg/warn14.adb
@@ -23,7 +23,7 @@ procedure Warn14 is
package YY is
type XX is tagged null record;
- function F4 (Y : XX; U : Boolean) return Natural is (1); -- { dg-warning "formal parameter \"U\" is not referenced" }
+ function F4 (Y : XX; U : Boolean) return Natural is (1);
end YY;
XXX : YY.XX;
diff --git a/gcc/testsuite/go.test/go-test.exp b/gcc/testsuite/go.test/go-test.exp
index 51f9b38..c7d5c72 100644
--- a/gcc/testsuite/go.test/go-test.exp
+++ b/gcc/testsuite/go.test/go-test.exp
@@ -101,50 +101,31 @@ proc errchk { test opts } {
set changed ""
while { $changed != $copy_line } {
set changed $copy_line
- regsub "\(// \[^\"\]*\"\[^\"\]*\)\" \"" $copy_line "\\1|" out_line
+ regsub {(// [^"]*"[^"]*)" "} $copy_line {\1|} out_line
set copy_line $out_line
}
- regsub "// \(GCCGO_\)?ERROR \"\(\[^\"\]*\)\".*$" $copy_line "// \{ dg-error \"\\2\" \}" out_line
- if [string match "*dg-error*\\\[*" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index -all "\\\\\\\[" $out_line "\\\\\\\\\\\[" out_line
- }
- if [string match "*dg-error*\\\]*" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index -all "\\\\\\\]" $out_line "\\\\\\\\\\\]" out_line
- }
- if [string match "*dg-error*.\**" $out_line] {
- # I worked out the right number of backslashes by
- # experimentation, not analysis.
- regsub -all "\\.\\*" $out_line "\\\\\[ -~\\\\\]*" out_line
- }
- if [string match "*dg-error*\\\[?\\\]*" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -all "\\\[\(.\)\\\]" $out_line "\\\\\[\\1\\\\\]" out_line
- }
- if [string match "*dg-error*\{*" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index -all "\(\[^\\\\]\)\{" $out_line "\\1\\\\\[\\\{\\\\\]" out_line
- }
- if [string match "*dg-error*\}*\}" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index -all "\(\[^\\\\]\)\}\(.\)" $out_line "\\1\\\\\[\\\}\\\\\]\\2" out_line
- }
- if [string match "*dg-error*\(*" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index -all "\\\\\\\(" $out_line "\\\\\[\\\(\\\\\]" out_line
- }
- if [string match "*dg-error*\)*\}" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index -all "\\\\\\\)\(.\)" $out_line "\\\\\[\\\)\\\\\]\\1" out_line
- }
- # Special case for bug332, in which the error message wants to
- # match the file name, which is not what dg-error expects.
- if [string match "*dg-error*bug332*" $out_line] {
- set index [string first "dg-error" $out_line]
- regsub -start $index "bug332" $out_line "undefined type" out_line
+ set index [string first // $copy_line]
+ set eindex [string first ERROR $copy_line]
+ if { $index >= 0 && $eindex > $index } {
+ # We're putting the regexp in curly braces, so replace any
+ # curly braces in the regexp with hex escapes.
+ regsub -start $index -all "\{" $copy_line {\x7b} copy_line
+ regsub -start $index -all "\}" $copy_line {\x7d} copy_line
+
+ # Replace .* with [ -~]* because .* will eat newlines.
+ # We can't easily use (?n) because this regexp will appear
+ # in the middle of a large regexp.
+ regsub -all {\.\*} $copy_line {[ -~]*} copy_line
}
+
+ # Change
+ # // ERROR "string"
+ # to
+ # // { dg-error {string} }
+ # The latter is what go-dg-runtest expects.
+ regsub {// (GCCGO_)?ERROR "([^"]*)"([^"]*)$} $copy_line "// \{ dg-error \{\\2\} \}\\3" out_line
+
puts $fdout $out_line
}
close $fdin
@@ -274,6 +255,53 @@ proc go-set-goarch { } {
setenv GOARCH $goarch
}
+# This be kept in sync with libgo/configure.ac.
+proc go-set-goos { } {
+ global target_triplet
+
+ switch -glob $target_triplet {
+ "*-*-darwin*" {
+ set goos "darwin"
+ }
+ "*-*-freebsd*" {
+ set goos "freebsd"
+ }
+ "*-*-irix6*" {
+ set goos "irix"
+ }
+ "*-*-linux*" {
+ set goos "linux"
+ }
+ "*-*-netbsd*" {
+ set goos "netbsd"
+ }
+ "*-*-openbsd*" {
+ set goos "openbsd"
+ }
+ "*-*-dragonfly*" {
+ set goos "dragonfly"
+ }
+ "*-*-rtems*" {
+ set goos "rtems"
+ }
+ "*-*-solaris2*" {
+ set goos "solaris"
+ }
+ "*-*-aix*" {
+ set goos "aix"
+ }
+ "*-*-gnu*" {
+ set goos "hurd"
+ }
+ default {
+ perror "$target_triplet: unhandled GOOS"
+ return
+ }
+ }
+ verbose -log "Setting GOOS=$goos" 1
+ setenv GOOS $goos
+}
+
# Take a list of files and return a lists of lists, where each list is
# the set of files in the same package.
proc go-find-packages { test name files } {
@@ -310,6 +338,27 @@ proc go-find-packages { test name files } {
return $packages
}
+proc go-gc-match { name } {
+ verbose -log "go-gc-match $name"
+ set idx [string first "," $name]
+ if { $idx >= 0 } {
+ set left [string range $name 0 [expr $idx - 1]]
+ set right [string range $name [expr $idx + 1] end]
+ return [expr [go-gc-match $left] && [go-gc-match $right]]
+ }
+ if { [string index $name 0] == "!" && [string index $name 1] == "!" } {
+ return 0
+ }
+ if { [string index $name 0] == "!" } {
+ return [expr ! [go-gc-match [string range $name 1 end]]]
+ }
+ if { $name == [getenv GOARCH] || $name == [getenv GOOS] || $name == "gccgo" } {
+ return 1
+ }
+
+ return 0
+}
+
proc go-gc-tests { } {
global srcdir subdir
global runtests
@@ -330,8 +379,9 @@ proc go-gc-tests { } {
set options ""
lappend options "additional_flags=$DEFAULT_GOCFLAGS"
- # Set GOARCH for tests that need it.
+ # Set GOARCH and GOOS for tests that need it.
go-set-goarch
+ go-set-goos
# Running all the torture options takes too long and, since the
# frontend ignores the standard options, it doesn't significantly
@@ -451,73 +501,61 @@ proc go-gc-tests { } {
set lines_ok 1
+ set test_line ""
while 1 {
- if { [gets $fd test_line] < 0 } {
- close $fd
- clone_output "$test: could not read first line"
+ if { [gets $fd file_line] < 0 } {
+ if [eof $fd] {
+ break
+ }
+ clone_output "$test: read failed"
unresolved $name
set lines_ok 0
break
}
- if { [ string match "*nacl*exit 0*" $test_line ] \
- || [ string match "*exit 0*nacl*" $test_line ] \
- || [ string match "*Android*exit 0*" $test_line ] \
- || [ string match "*exit 0*Android*" $test_line ] \
- || [ string match "*\"\$GOOS\" == windows*" $test_line ] } {
+ if { [ string match "*nacl*exit 0*" $file_line ] \
+ || [ string match "*exit 0*nacl*" $file_line ] \
+ || [ string match "*Android*exit 0*" $file_line ] \
+ || [ string match "*exit 0*Android*" $file_line ] \
+ || [ string match "*\"\$GOOS\" == windows*" $file_line ] } {
continue
}
- if { [ string match "// +build *" $test_line ] } {
- set matches_pos 0
- set matches_neg 0
- if { [ regexp -line "\[ \][getenv GOARCH]\(\[ \]\|\$\)" $test_line ] } {
- set matches_pos 1
- } elseif { [ regexp -line "\[ \]\![getenv GOARCH]\(\[ \]\|\$\)" $test_line ] } {
- set matches_neg 1
- } elseif { [ regexp -line "\[ \]linux\(\[ \]\|\$\)" $test_line ] } {
- set matches_pos 1
- } elseif { [ regexp -line "\[ \]\!linux\(\[ \]\|\$\)" $test_line ] } {
- set matches_neg 1
- } elseif { [ regexp -line "\[ \]\!windows\(\[ \]\|\$\)" $test_line ] } {
- set matches_pos 1
- } elseif { [ regexp -line "\[ \]windows\(\[ \]\|\$\)" $test_line ] } {
- set matches_neg 1
+ if ![string match "// *" $file_line] {
+ if { $file_line != "" } {
+ break
}
- if { $matches_pos == 1 && $matches_neg == 0 } {
+ continue
+ }
+
+ if { [ string match "// +build *" $file_line ] } {
+ set words [split $file_line]
+ set matches 0
+ for { set idx 2 } { $idx < [llength $words] } { incr idx } {
+ if { [go-gc-match [lindex $words $idx]] } {
+ set matches 1
+ break
+ }
+ }
+ if { $matches == 1 } {
continue
}
- close $fd
unsupported $name
set lines_ok 0
+ break
}
- break
- }
-
- if { $lines_ok == 0 } {
- continue
+ if { $test_line == "" } {
+ set test_line $file_line
+ }
}
- set lineno 1
- set test_line1 $test_line
+ close $fd
- while { [eval "string match \"//*&&\" \${test_line$lineno}"] } {
- set lineno [expr $lineno + 1]
- if { [eval "gets \$fd test_line$lineno"] < 0 } {
- close $fd
- clone_output "$test: could not read line $lineno"
- unresolved $name
- set lines_ok 0
- break
- }
- }
if { $lines_ok == 0 } {
continue
}
- close $fd
-
# runtest_file_p is already run above, and the code below can run
# runtest_file_p again, make sure everything for this test is
# performed if the above runtest_file_p decided this runtest
@@ -636,7 +674,7 @@ proc go-gc-tests { } {
go-execute-xfail $test
} elseif { $test_line == "// errorcheck" } {
errchk $test ""
- } elseif { $test_line == "// errorcheckdir" } {
+ } elseif { $test_line == "// errorcheckdir" || $test_line == "// errorcheckdir -n" } {
set hold_runtests $runtests
set runtests "go-test.exp"
set dir "[file rootname $test].dir"
@@ -648,7 +686,7 @@ proc go-gc-tests { } {
set last [lindex $packages end]
set packages [lreplace $packages end end]
foreach p $packages {
- dg-test -keep-output [lrange $p 1 end] "-O" "-w $DEFAULT_GOCFLAGS"
+ dg-test -keep-output [lrange $p 1 end] "-O -I." "-w $DEFAULT_GOCFLAGS"
lappend del "[file rootname [file tail [lindex $p 1]]].o"
}
errchk [lindex $last 1] "[lrange $last 2 end]"
@@ -692,7 +730,7 @@ proc go-gc-tests { } {
if { [llength $packages] > 0 } {
set del [list]
foreach p $packages {
- dg-test -keep-output [lindex $p 1] "[lrange $p 2 end] -O" "-w $DEFAULT_GOCFLAGS"
+ dg-test -keep-output [lindex $p 1] "[lrange $p 2 end] -O -I." "-w $DEFAULT_GOCFLAGS"
lappend del "[file rootname [file tail [lindex $p 1]]].o"
}
foreach f $del {
@@ -712,7 +750,7 @@ proc go-gc-tests { } {
set last [lindex $packages end]
set packages [lreplace $packages end end]
foreach p $packages {
- dg-test -keep-output [lrange $p 1 end] "-O" "-w $DEFAULT_GOCFLAGS"
+ dg-test -keep-output [lrange $p 1 end] "-O -I." "-w $DEFAULT_GOCFLAGS"
lappend del "[file rootname [file tail [lindex $p 1]]].o"
}
set dg-do-what-default "link"
@@ -737,11 +775,11 @@ proc go-gc-tests { } {
set last [lindex $packages end]
set packages [lreplace $packages end end]
foreach p $packages {
- dg-test -keep-output [lrange $p 1 end] "-O" "-w $DEFAULT_GOCFLAGS"
+ dg-test -keep-output [lrange $p 1 end] "-O -I." "-w $DEFAULT_GOCFLAGS"
lappend del "[file rootname [file tail [lindex $p 1]]].o"
}
set dg-do-what-default "link"
- dg-test -keep-output [lrange $last 1 end] "$del -O" "-w $DEFAULT_GOCFLAGS"
+ dg-test -keep-output [lrange $last 1 end] "$del -O -I." "-w $DEFAULT_GOCFLAGS"
set base "[file rootname [file tail [lindex $last 1]]]"
set output_file "./$base.exe"
lappend del $output_file
diff --git a/gcc/testsuite/go.test/test/alias.go b/gcc/testsuite/go.test/test/alias.go
index ec93a2d..aabaef8 100644
--- a/gcc/testsuite/go.test/test/alias.go
+++ b/gcc/testsuite/go.test/test/alias.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/alias1.go b/gcc/testsuite/go.test/test/alias1.go
index 42cf693..5707917 100644
--- a/gcc/testsuite/go.test/test/alias1.go
+++ b/gcc/testsuite/go.test/test/alias1.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/alias2.go b/gcc/testsuite/go.test/test/alias2.go
new file mode 100644
index 0000000..1c141ac
--- /dev/null
+++ b/gcc/testsuite/go.test/test/alias2.go
@@ -0,0 +1,104 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test basic restrictions on type aliases.
+
+package p
+
+import (
+ "reflect"
+ . "reflect"
+)
+
+type T0 struct{}
+
+// Valid type alias declarations.
+
+type _ = T0
+type _ = int
+type _ = struct{}
+type _ = reflect.Value
+type _ = Value
+
+type (
+ A0 = T0
+ A1 = int
+ A2 = struct{}
+ A3 = reflect.Value
+ A4 = Value
+ A5 = Value
+
+ N0 A0
+)
+
+// Methods can be declared on the original named type and the alias.
+func (T0) m1() {} // GCCGO_ERROR "previous"
+func (*T0) m1() {} // ERROR "method redeclared: T0\.m1|redefinition of .m1."
+func (A0) m1() {} // ERROR "T0\.m1 redeclared in this block|redefinition of .m1."
+func (A0) m1() {} // ERROR "T0\.m1 redeclared in this block|redefinition of .m1."
+func (A0) m2() {}
+
+// Type aliases and the original type name can be used interchangeably.
+var _ A0 = T0{}
+var _ T0 = A0{}
+
+// But aliases and original types cannot be used with new types based on them.
+var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
+var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
+
+var _ A5 = Value{}
+
+var _ interface {
+ m1()
+ m2()
+} = T0{}
+
+var _ interface {
+ m1()
+ m2()
+} = A0{}
+
+func _() {
+ type _ = T0
+ type _ = int
+ type _ = struct{}
+ type _ = reflect.Value
+ type _ = Value
+
+ type (
+ A0 = T0
+ A1 = int
+ A2 = struct{}
+ A3 = reflect.Value
+ A4 = Value
+ A5 Value
+
+ N0 A0
+ )
+
+ var _ A0 = T0{}
+ var _ T0 = A0{}
+
+ var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
+ var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
+
+ var _ A5 = Value{} // ERROR "cannot use reflect\.Value{} \(type reflect.Value\) as type A5 in assignment|incompatible type"
+}
+
+// Invalid type alias declarations.
+
+type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type|expected type"
+
+func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type"
+func (A2) m() {} // ERROR "invalid receiver type"
+func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
+func (A4) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
+
+type B1 = struct{}
+
+func (B1) m() {} // ERROR "invalid receiver type"
+
+// TODO(gri) expand
diff --git a/gcc/testsuite/go.test/test/alias3.dir/a.go b/gcc/testsuite/go.test/test/alias3.dir/a.go
new file mode 100644
index 0000000..09b3408
--- /dev/null
+++ b/gcc/testsuite/go.test/test/alias3.dir/a.go
@@ -0,0 +1,42 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "go/build"
+
+type (
+ Float64 = float64
+ Rune = rune
+)
+
+type (
+ Int int
+ IntAlias = Int
+ IntAlias2 = IntAlias
+ S struct {
+ Int
+ IntAlias
+ IntAlias2
+ }
+)
+
+type (
+ Context = build.Context
+)
+
+type (
+ I1 interface {
+ M1(IntAlias2) Float64
+ M2() Context
+ }
+
+ I2 = interface {
+ M1(Int) float64
+ M2() build.Context
+ }
+)
+
+var i1 I1
+var i2 I2 = i1
diff --git a/gcc/testsuite/go.test/test/alias3.dir/b.go b/gcc/testsuite/go.test/test/alias3.dir/b.go
new file mode 100644
index 0000000..8a86cc0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/alias3.dir/b.go
@@ -0,0 +1,26 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import (
+ "./a"
+ . "go/build"
+)
+
+func F(x float64) a.Float64 {
+ return x
+}
+
+type MyContext = Context // = build.Context
+
+var C a.Context = Default
+
+type S struct{}
+
+func (S) M1(x a.IntAlias) float64 { return a.Float64(x) }
+func (S) M2() Context { return Default }
+
+var _ a.I1 = S{}
+var _ a.I2 = S{}
diff --git a/gcc/testsuite/go.test/test/alias3.dir/c.go b/gcc/testsuite/go.test/test/alias3.dir/c.go
new file mode 100644
index 0000000..161d593
--- /dev/null
+++ b/gcc/testsuite/go.test/test/alias3.dir/c.go
@@ -0,0 +1,25 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "./a"
+ "./b"
+)
+
+func main() {
+ var _ float64 = b.F(0)
+ var _ a.Rune = int32(0)
+
+ // embedded types can have different names but the same types
+ var s a.S
+ s.Int = 1
+ s.IntAlias = s.Int
+ s.IntAlias2 = s.Int
+
+ // aliases denote identical types across packages
+ var c a.Context = b.C
+ var _ b.MyContext = c
+}
diff --git a/gcc/testsuite/go.test/test/alias3.go b/gcc/testsuite/go.test/test/alias3.go
new file mode 100644
index 0000000..c3732c3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/alias3.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/append.go b/gcc/testsuite/go.test/test/append.go
index 3f6251e..3d16063 100644
--- a/gcc/testsuite/go.test/test/append.go
+++ b/gcc/testsuite/go.test/test/append.go
@@ -13,14 +13,12 @@ import (
"reflect"
)
-
func verify(name string, result, expected interface{}) {
if !reflect.DeepEqual(result, expected) {
panic(name)
}
}
-
func main() {
for _, t := range tests {
verify(t.name, t.result, t.expected)
@@ -30,6 +28,10 @@ func main() {
verifyType()
}
+var (
+ zero int = 0
+ one int = 1
+)
var tests = []struct {
name string
@@ -49,7 +51,6 @@ var tests = []struct {
{"bool i", append([]bool{true, false, true}, []bool{true}...), []bool{true, false, true, true}},
{"bool j", append([]bool{true, false, true}, []bool{true, true, true}...), []bool{true, false, true, true, true, true}},
-
{"byte a", append([]byte{}), []byte{}},
{"byte b", append([]byte{}, 0), []byte{0}},
{"byte c", append([]byte{}, 0, 1, 2, 3), []byte{0, 1, 2, 3}},
@@ -84,7 +85,6 @@ var tests = []struct {
{"int16 i", append([]int16{0, 1, 2}, []int16{3}...), []int16{0, 1, 2, 3}},
{"int16 j", append([]int16{0, 1, 2}, []int16{3, 4, 5}...), []int16{0, 1, 2, 3, 4, 5}},
-
{"uint32 a", append([]uint32{}), []uint32{}},
{"uint32 b", append([]uint32{}, 0), []uint32{0}},
{"uint32 c", append([]uint32{}, 0, 1, 2, 3), []uint32{0, 1, 2, 3}},
@@ -99,7 +99,6 @@ var tests = []struct {
{"uint32 i", append([]uint32{0, 1, 2}, []uint32{3}...), []uint32{0, 1, 2, 3}},
{"uint32 j", append([]uint32{0, 1, 2}, []uint32{3, 4, 5}...), []uint32{0, 1, 2, 3, 4, 5}},
-
{"float64 a", append([]float64{}), []float64{}},
{"float64 b", append([]float64{}, 0), []float64{0}},
{"float64 c", append([]float64{}, 0, 1, 2, 3), []float64{0, 1, 2, 3}},
@@ -114,7 +113,6 @@ var tests = []struct {
{"float64 i", append([]float64{0, 1, 2}, []float64{3}...), []float64{0, 1, 2, 3}},
{"float64 j", append([]float64{0, 1, 2}, []float64{3, 4, 5}...), []float64{0, 1, 2, 3, 4, 5}},
-
{"complex128 a", append([]complex128{}), []complex128{}},
{"complex128 b", append([]complex128{}, 0), []complex128{0}},
{"complex128 c", append([]complex128{}, 0, 1, 2, 3), []complex128{0, 1, 2, 3}},
@@ -129,7 +127,6 @@ var tests = []struct {
{"complex128 i", append([]complex128{0, 1, 2}, []complex128{3}...), []complex128{0, 1, 2, 3}},
{"complex128 j", append([]complex128{0, 1, 2}, []complex128{3, 4, 5}...), []complex128{0, 1, 2, 3, 4, 5}},
-
{"string a", append([]string{}), []string{}},
{"string b", append([]string{}, "0"), []string{"0"}},
{"string c", append([]string{}, "0", "1", "2", "3"), []string{"0", "1", "2", "3"}},
@@ -143,8 +140,19 @@ var tests = []struct {
{"string i", append([]string{"0", "1", "2"}, []string{"3"}...), []string{"0", "1", "2", "3"}},
{"string j", append([]string{"0", "1", "2"}, []string{"3", "4", "5"}...), []string{"0", "1", "2", "3", "4", "5"}},
-}
+ {"make a", append([]string{}, make([]string, 0)...), []string{}},
+ {"make b", append([]string(nil), make([]string, 0)...), []string(nil)},
+
+ {"make c", append([]struct{}{}, make([]struct{}, 0)...), []struct{}{}},
+ {"make d", append([]struct{}{}, make([]struct{}, 2)...), make([]struct{}, 2)},
+
+ {"make e", append([]int{0, 1}, make([]int, 0)...), []int{0, 1}},
+ {"make f", append([]int{0, 1}, make([]int, 2)...), []int{0, 1, 0, 0}},
+
+ {"make g", append([]*int{&zero, &one}, make([]*int, 0)...), []*int{&zero, &one}},
+ {"make h", append([]*int{&zero, &one}, make([]*int, 2)...), []*int{&zero, &one, nil, nil}},
+}
func verifyStruct() {
type T struct {
@@ -185,7 +193,6 @@ func verifyStruct() {
verify("struct m", append(s, e...), r)
}
-
func verifyInterface() {
type T interface{}
type S []T
diff --git a/gcc/testsuite/go.test/test/assign.go b/gcc/testsuite/go.test/test/assign.go
index da0192f..62fd3b5 100644
--- a/gcc/testsuite/go.test/test/assign.go
+++ b/gcc/testsuite/go.test/test/assign.go
@@ -53,4 +53,16 @@ func main() {
_ = x
_ = y
}
+ {
+ var x = 1
+ {
+ x, x := 2, 3 // ERROR ".*x.* repeated on left side of :="
+ _ = x
+ }
+ _ = x
+ }
+ {
+ a, a := 1, 2 // ERROR ".*a.* repeated on left side of :="
+ _ = a
+ }
}
diff --git a/gcc/testsuite/go.test/test/bench/garbage/Makefile b/gcc/testsuite/go.test/test/bench/garbage/Makefile
index 9883845..c10ef0a 100644
--- a/gcc/testsuite/go.test/test/bench/garbage/Makefile
+++ b/gcc/testsuite/go.test/test/bench/garbage/Makefile
@@ -1,4 +1,4 @@
-# Copyright 2010 The Go Authors. All rights reserved.
+# Copyright 2010 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/garbage/parser.go b/gcc/testsuite/go.test/test/bench/garbage/parser.go
index d85110b..817afa9 100644
--- a/gcc/testsuite/go.test/test/bench/garbage/parser.go
+++ b/gcc/testsuite/go.test/test/bench/garbage/parser.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -85,7 +85,7 @@ func main() {
var t0 time.Time
var numGC uint32
var pauseTotalNs uint64
- pkgroot := runtime.GOROOT() + "/src/pkg/"
+ pkgroot := runtime.GOROOT() + "/src/"
for pass := 0; pass < 2; pass++ {
// Once the heap is grown to full size, reset counters.
// This hides the start-up pauses, which are much smaller
diff --git a/gcc/testsuite/go.test/test/bench/garbage/stats.go b/gcc/testsuite/go.test/test/bench/garbage/stats.go
index 6dc0aeb..937e00f 100644
--- a/gcc/testsuite/go.test/test/bench/garbage/stats.go
+++ b/gcc/testsuite/go.test/test/bench/garbage/stats.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/garbage/tree.go b/gcc/testsuite/go.test/test/bench/garbage/tree.go
index 0a3ec23..524cfeb 100644
--- a/gcc/testsuite/go.test/test/bench/garbage/tree.go
+++ b/gcc/testsuite/go.test/test/bench/garbage/tree.go
@@ -28,7 +28,7 @@ POSSIBILITY OF SUCH DAMAGE.
*/
/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
+ * https://benchmarksgame-team.pages.debian.net/benchmarksgame/
*
* contributed by The Go Authors.
* based on C program by Kevin Carson
diff --git a/gcc/testsuite/go.test/test/bench/garbage/tree2.go b/gcc/testsuite/go.test/test/bench/garbage/tree2.go
index a171c69..a70a106 100644
--- a/gcc/testsuite/go.test/test/bench/garbage/tree2.go
+++ b/gcc/testsuite/go.test/test/bench/garbage/tree2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/binarytree_test.go b/gcc/testsuite/go.test/test/bench/go1/binarytree_test.go
index c64c4b8..e5e49d5 100644
--- a/gcc/testsuite/go.test/test/bench/go1/binarytree_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/binarytree_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/fannkuch_test.go b/gcc/testsuite/go.test/test/bench/go1/fannkuch_test.go
index ae45bfd..0cf6115 100644
--- a/gcc/testsuite/go.test/test/bench/go1/fannkuch_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/fannkuch_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/fasta_test.go b/gcc/testsuite/go.test/test/bench/go1/fasta_test.go
index bff056f..af4fbac 100644
--- a/gcc/testsuite/go.test/test/bench/go1/fasta_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/fasta_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,11 +12,11 @@ var fastabytes = makefasta()
func makefasta() []byte {
var n int = 25e6
- if runtime.GOARCH == "arm" {
+ if runtime.GOARCH == "arm" || runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
// TODO(dfc) remove this limitation after precise gc.
- // A value of 25e6 consumes 465mb of heap on 32bit
- // platforms, which is too much for most ARM systems.
- // A value of 25e5 produces a memory layout that
+ // A value of 25e6 consumes 465mb of heap on 32bit
+ // platforms, which is too much for some systems.
+ // A value of 25e5 produces a memory layout that
// confuses the gc on 32bit platforms. So 25e4 it is.
n = 25e4
}
diff --git a/gcc/testsuite/go.test/test/bench/go1/gob_test.go b/gcc/testsuite/go.test/test/bench/go1/gob_test.go
index b172b80..224beff 100644
--- a/gcc/testsuite/go.test/test/bench/go1/gob_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/gob_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/gzip_test.go b/gcc/testsuite/go.test/test/bench/go1/gzip_test.go
index fe4c480..648eec5 100644
--- a/gcc/testsuite/go.test/test/bench/go1/gzip_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/gzip_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/http_test.go b/gcc/testsuite/go.test/test/bench/go1/http_test.go
index 34e789f..7ece9b2 100644
--- a/gcc/testsuite/go.test/test/bench/go1/http_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/http_test.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/json_test.go b/gcc/testsuite/go.test/test/bench/go1/json_test.go
index 1d42619..5ff1f8b 100644
--- a/gcc/testsuite/go.test/test/bench/go1/json_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/json_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go b/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go
index cf0fac1..281b6ca 100644
--- a/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -1816,4 +1816,4 @@ zJE6zEudHD27ZzbOeSgpk/HnkQbT7twqaaJXNvUzMuUt1hyhU7ceZcph42+VTlXU
cZ9UZZJyYojLjaeJHfJU1UZUEmBfLumu8yW5skuyE9uh2BmVxJZi6KxaXBNwSolw
BqBcQLj3ucNZIYZLYtirLu3brW6UYgZgZJiDIGiwpsgg7g1AITkgM6FHITxDDnGt
4SDHzZbL5s8fec5PCq5DOzDRdWS+0h5Y2INZak1D29cpVyb2aVrV3Wlt7rQhLa3e
-m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA== `)
+m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA==`)
diff --git a/gcc/testsuite/go.test/test/bench/go1/mandel_test.go b/gcc/testsuite/go.test/test/bench/go1/mandel_test.go
index 888c5e4..dd543b2 100644
--- a/gcc/testsuite/go.test/test/bench/go1/mandel_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/mandel_test.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/parserdata_test.go b/gcc/testsuite/go.test/test/bench/go1/parserdata_test.go
index 113e5e3..8255d18 100644
--- a/gcc/testsuite/go.test/test/bench/go1/parserdata_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/parserdata_test.go
@@ -1,10 +1,10 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Input for parser benchmark.
-// This was generated by starting with a the contents of
-// src/pkg/go/parser/parser.go at rev 9b455eb64690, then
+// This was generated by starting with the contents of
+// src/pkg/go/parser/parser.go at rev 9b455eb64690, then
// compressing with bzip2 -9, then encoding to base64.
// We compile the data into the binary so that the benchmark is
// a stand-alone binary that can be copied easily from machine to
diff --git a/gcc/testsuite/go.test/test/bench/go1/revcomp_test.go b/gcc/testsuite/go.test/test/bench/go1/revcomp_test.go
index 6b6c1e5..7d57bd6 100644
--- a/gcc/testsuite/go.test/test/bench/go1/revcomp_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/revcomp_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/go1/template_test.go b/gcc/testsuite/go.test/test/bench/go1/template_test.go
index db4839a..10dacaa 100644
--- a/gcc/testsuite/go.test/test/bench/go1/template_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/template_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.go b/gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.go
deleted file mode 100644
index 071a4e06..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.go
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Kevin Carson
- */
-
-package main
-
-import (
- "flag"
- "fmt"
-)
-
-var n = flag.Int("n", 15, "depth")
-
-type Node struct {
- item int
- left, right *Node
-}
-
-type Arena struct {
- head *Node
-}
-
-var arena Arena
-
-func (n *Node) free() {
- if n.left != nil {
- n.left.free()
- }
- if n.right != nil {
- n.right.free()
- }
- n.left = arena.head
- arena.head = n
-}
-
-func (a *Arena) New(item int, left, right *Node) *Node {
- if a.head == nil {
- nodes := make([]Node, 3<<uint(*n))
- for i := 0; i < len(nodes)-1; i++ {
- nodes[i].left = &nodes[i+1]
- }
- a.head = &nodes[0]
- }
- n := a.head
- a.head = a.head.left
- n.item = item
- n.left = left
- n.right = right
- return n
-}
-
-func bottomUpTree(item, depth int) *Node {
- if depth <= 0 {
- return arena.New(item, nil, nil)
- }
- return arena.New(item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1))
-}
-
-func (n *Node) itemCheck() int {
- if n.left == nil {
- return n.item
- }
- return n.item + n.left.itemCheck() - n.right.itemCheck()
-}
-
-const minDepth = 4
-
-func main() {
- flag.Parse()
-
- maxDepth := *n
- if minDepth+2 > *n {
- maxDepth = minDepth + 2
- }
- stretchDepth := maxDepth + 1
-
- check := bottomUpTree(0, stretchDepth).itemCheck()
- fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
-
- longLivedTree := bottomUpTree(0, maxDepth)
-
- for depth := minDepth; depth <= maxDepth; depth += 2 {
- iterations := 1 << uint(maxDepth-depth+minDepth)
- check = 0
-
- for i := 1; i <= iterations; i++ {
- t := bottomUpTree(i, depth)
- check += t.itemCheck()
- t.free()
- t = bottomUpTree(-i, depth)
- check += t.itemCheck()
- t.free()
- }
- fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
- }
- fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.txt b/gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.txt
deleted file mode 100644
index f8286dd..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/binary-tree-freelist.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-stretch tree of depth 16 check: -1
-65536 trees of depth 4 check: -65536
-16384 trees of depth 6 check: -16384
-4096 trees of depth 8 check: -4096
-1024 trees of depth 10 check: -1024
-256 trees of depth 12 check: -256
-64 trees of depth 14 check: -64
-long lived tree of depth 15 check: -1
diff --git a/gcc/testsuite/go.test/test/bench/shootout/binary-tree.c b/gcc/testsuite/go.test/test/bench/shootout/binary-tree.c
deleted file mode 100644
index 9c35ac5..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/binary-tree.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Shootout Benchmarks
- http://shootout.alioth.debian.org/
-
- contributed by Kevin Carson
- compilation:
- gcc -O3 -fomit-frame-pointer -funroll-loops -static binary-trees.c -lm
- icc -O3 -ip -unroll -static binary-trees.c -lm
-*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-typedef struct tn {
- struct tn* left;
- struct tn* right;
- long item;
-} treeNode;
-
-
-treeNode* NewTreeNode(treeNode* left, treeNode* right, long item)
-{
- treeNode* new;
-
- new = (treeNode*)malloc(sizeof(treeNode));
-
- new->left = left;
- new->right = right;
- new->item = item;
-
- return new;
-} /* NewTreeNode() */
-
-
-long ItemCheck(treeNode* tree)
-{
- if (tree->left == NULL)
- return tree->item;
- else
- return tree->item + ItemCheck(tree->left) - ItemCheck(tree->right);
-} /* ItemCheck() */
-
-
-treeNode* BottomUpTree(long item, unsigned depth)
-{
- if (depth > 0)
- return NewTreeNode
- (
- BottomUpTree(2 * item - 1, depth - 1),
- BottomUpTree(2 * item, depth - 1),
- item
- );
- else
- return NewTreeNode(NULL, NULL, item);
-} /* BottomUpTree() */
-
-
-void DeleteTree(treeNode* tree)
-{
- if (tree->left != NULL)
- {
- DeleteTree(tree->left);
- DeleteTree(tree->right);
- }
-
- free(tree);
-} /* DeleteTree() */
-
-
-int main(int argc, char* argv[])
-{
- unsigned N, depth, minDepth, maxDepth, stretchDepth;
- treeNode *stretchTree, *longLivedTree, *tempTree;
-
- N = atol(argv[1]);
-
- minDepth = 4;
-
- if ((minDepth + 2) > N)
- maxDepth = minDepth + 2;
- else
- maxDepth = N;
-
- stretchDepth = maxDepth + 1;
-
- stretchTree = BottomUpTree(0, stretchDepth);
- printf
- (
- "stretch tree of depth %u\t check: %li\n",
- stretchDepth,
- ItemCheck(stretchTree)
- );
-
- DeleteTree(stretchTree);
-
- longLivedTree = BottomUpTree(0, maxDepth);
-
- for (depth = minDepth; depth <= maxDepth; depth += 2)
- {
- long i, iterations, check;
-
- iterations = pow(2, maxDepth - depth + minDepth);
-
- check = 0;
-
- for (i = 1; i <= iterations; i++)
- {
- tempTree = BottomUpTree(i, depth);
- check += ItemCheck(tempTree);
- DeleteTree(tempTree);
-
- tempTree = BottomUpTree(-i, depth);
- check += ItemCheck(tempTree);
- DeleteTree(tempTree);
- } /* for(i = 1...) */
-
- printf
- (
- "%li\t trees of depth %u\t check: %li\n",
- iterations * 2,
- depth,
- check
- );
- } /* for(depth = minDepth...) */
-
- printf
- (
- "long lived tree of depth %u\t check: %li\n",
- maxDepth,
- ItemCheck(longLivedTree)
- );
-
- return 0;
-} /* main() */
diff --git a/gcc/testsuite/go.test/test/bench/shootout/binary-tree.go b/gcc/testsuite/go.test/test/bench/shootout/binary-tree.go
deleted file mode 100644
index 9f867d1..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/binary-tree.go
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Kevin Carson
- */
-
-package main
-
-import (
- "flag"
- "fmt"
-)
-
-var n = flag.Int("n", 15, "depth")
-
-type Node struct {
- item int
- left, right *Node
-}
-
-func bottomUpTree(item, depth int) *Node {
- if depth <= 0 {
- return &Node{item: item}
- }
- return &Node{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)}
-}
-
-func (n *Node) itemCheck() int {
- if n.left == nil {
- return n.item
- }
- return n.item + n.left.itemCheck() - n.right.itemCheck()
-}
-
-const minDepth = 4
-
-func main() {
- flag.Parse()
-
- maxDepth := *n
- if minDepth+2 > *n {
- maxDepth = minDepth + 2
- }
- stretchDepth := maxDepth + 1
-
- check := bottomUpTree(0, stretchDepth).itemCheck()
- fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
-
- longLivedTree := bottomUpTree(0, maxDepth)
-
- for depth := minDepth; depth <= maxDepth; depth += 2 {
- iterations := 1 << uint(maxDepth-depth+minDepth)
- check = 0
-
- for i := 1; i <= iterations; i++ {
- check += bottomUpTree(i, depth).itemCheck()
- check += bottomUpTree(-i, depth).itemCheck()
- }
- fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
- }
- fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/binary-tree.txt b/gcc/testsuite/go.test/test/bench/shootout/binary-tree.txt
deleted file mode 100644
index f8286dd..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/binary-tree.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-stretch tree of depth 16 check: -1
-65536 trees of depth 4 check: -65536
-16384 trees of depth 6 check: -16384
-4096 trees of depth 8 check: -4096
-1024 trees of depth 10 check: -1024
-256 trees of depth 12 check: -256
-64 trees of depth 14 check: -64
-long lived tree of depth 15 check: -1
diff --git a/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.c b/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.c
deleted file mode 100644
index ed78c31..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- http://shootout.alioth.debian.org/
-
- contributed by Michael Barker
- based on a Java contribution by Luzius Meisser
-
- convert to C by dualamd
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-
-
-enum Colour
-{
- blue = 0,
- red = 1,
- yellow = 2,
- Invalid = 3
-};
-
-const char* ColourName[] = {"blue", "red", "yellow"};
-const int STACK_SIZE = 32*1024;
-
-typedef unsigned int BOOL;
-const BOOL TRUE = 1;
-const BOOL FALSE = 0;
-
-int CreatureID = 0;
-
-
-enum Colour doCompliment(enum Colour c1, enum Colour c2)
-{
- switch (c1)
- {
- case blue:
- switch (c2)
- {
- case blue:
- return blue;
- case red:
- return yellow;
- case yellow:
- return red;
- default:
- goto errlb;
- }
- case red:
- switch (c2)
- {
- case blue:
- return yellow;
- case red:
- return red;
- case yellow:
- return blue;
- default:
- goto errlb;
- }
- case yellow:
- switch (c2)
- {
- case blue:
- return red;
- case red:
- return blue;
- case yellow:
- return yellow;
- default:
- goto errlb;
- }
- default:
- break;
- }
-
-errlb:
- printf("Invalid colour\n");
- exit( 1 );
-}
-
-/* convert integer to number string: 1234 -> "one two three four" */
-char* formatNumber(int n, char* outbuf)
-{
- int ochar = 0, ichar = 0;
- int i;
- char tmp[64];
-
- const char* NUMBERS[] =
- {
- "zero", "one", "two", "three", "four", "five",
- "six", "seven", "eight", "nine"
- };
-
- ichar = sprintf(tmp, "%d", n);
-
- for (i = 0; i < ichar; i++)
- ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] );
-
- return outbuf;
-}
-
-
-struct MeetingPlace
-{
- pthread_mutex_t mutex;
- int meetingsLeft;
- struct Creature* firstCreature;
-};
-
-struct Creature
-{
- pthread_t ht;
- pthread_attr_t stack_att;
-
- struct MeetingPlace* place;
- int count;
- int sameCount;
-
- enum Colour colour;
- int id;
-
- BOOL two_met;
- BOOL sameid;
-};
-
-
-void MeetingPlace_Init(struct MeetingPlace* m, int meetings )
-{
- pthread_mutex_init( &m->mutex, 0 );
- m->meetingsLeft = meetings;
- m->firstCreature = 0;
-}
-
-
-BOOL Meet( struct Creature* cr)
-{
- BOOL retval = TRUE;
-
- struct MeetingPlace* mp = cr->place;
- pthread_mutex_lock( &(mp->mutex) );
-
- if ( mp->meetingsLeft > 0 )
- {
- if ( mp->firstCreature == 0 )
- {
- cr->two_met = FALSE;
- mp->firstCreature = cr;
- }
- else
- {
- struct Creature* first;
- enum Colour newColour;
-
- first = mp->firstCreature;
- newColour = doCompliment( cr->colour, first->colour );
-
- cr->sameid = cr->id == first->id;
- cr->colour = newColour;
- cr->two_met = TRUE;
-
- first->sameid = cr->sameid;
- first->colour = newColour;
- first->two_met = TRUE;
-
- mp->firstCreature = 0;
- mp->meetingsLeft--;
- }
- }
- else
- retval = FALSE;
-
- pthread_mutex_unlock( &(mp->mutex) );
- return retval;
-}
-
-
-void* CreatureThreadRun(void* param)
-{
- struct Creature* cr = (struct Creature*)param;
-
- while (TRUE)
- {
- if ( Meet(cr) )
- {
- while (cr->two_met == FALSE)
- sched_yield();
-
- if (cr->sameid)
- cr->sameCount++;
- cr->count++;
- }
- else
- break;
- }
-
- return 0;
-}
-
-void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour )
-{
- cr->place = place;
- cr->count = cr->sameCount = 0;
-
- cr->id = ++CreatureID;
- cr->colour = colour;
- cr->two_met = FALSE;
-
- pthread_attr_init( &cr->stack_att );
- pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE );
- pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) );
-}
-
-/* format meeting times of each creature to string */
-char* Creature_getResult(struct Creature* cr, char* str)
-{
- char numstr[256];
- formatNumber(cr->sameCount, numstr);
-
- sprintf( str, "%u%s", cr->count, numstr );
- return str;
-}
-
-
-void runGame( int n_meeting, int ncolor, const enum Colour* colours )
-{
- int i;
- int total = 0;
- char str[256];
-
- struct MeetingPlace place;
- struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) );
-
- MeetingPlace_Init( &place, n_meeting );
-
- /* print initial color of each creature */
- for (i = 0; i < ncolor; i++)
- {
- printf( "%s ", ColourName[ colours[i] ] );
- Creature_Init( &(creatures[i]), &place, colours[i] );
- }
- printf("\n");
-
- /* wait for them to meet */
- for (i = 0; i < ncolor; i++)
- pthread_join( creatures[i].ht, 0 );
-
- /* print meeting times of each creature */
- for (i = 0; i < ncolor; i++)
- {
- printf( "%s\n", Creature_getResult(&(creatures[i]), str) );
- total += creatures[i].count;
- }
-
- /* print total meeting times, should equal n_meeting */
- printf( "%s\n\n", formatNumber(total, str) );
-
- /* cleaup & quit */
- pthread_mutex_destroy( &place.mutex );
- free( creatures );
-}
-
-
-void printColours( enum Colour c1, enum Colour c2 )
-{
- printf( "%s + %s -> %s\n",
- ColourName[c1],
- ColourName[c2],
- ColourName[doCompliment(c1, c2)] );
-}
-
-void printColoursTable(void)
-{
- printColours(blue, blue);
- printColours(blue, red);
- printColours(blue, yellow);
- printColours(red, blue);
- printColours(red, red);
- printColours(red, yellow);
- printColours(yellow, blue);
- printColours(yellow, red);
- printColours(yellow, yellow);
-}
-
-int main(int argc, char** argv)
-{
- int n = (argc == 2) ? atoi(argv[1]) : 600;
-
- printColoursTable();
- printf("\n");
-
- const enum Colour r1[] = { blue, red, yellow };
- const enum Colour r2[] = { blue, red, yellow,
- red, yellow, blue,
- red, yellow, red, blue };
-
- runGame( n, sizeof(r1) / sizeof(r1[0]), r1 );
- runGame( n, sizeof(r2) / sizeof(r2[0]), r2 );
-
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.go b/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.go
deleted file mode 100644
index 3395798..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "strconv"
-)
-
-const (
- blue = iota
- red
- yellow
- ncol
-)
-
-var complement = [...]int{
- red | red<<2: red,
- red | yellow<<2: blue,
- red | blue<<2: yellow,
- yellow | red<<2: blue,
- yellow | yellow<<2: yellow,
- yellow | blue<<2: red,
- blue | red<<2: yellow,
- blue | yellow<<2: red,
- blue | blue<<2: blue,
-}
-
-var colname = [...]string{
- blue: "blue",
- red: "red",
- yellow: "yellow",
-}
-
-// information about the current state of a creature.
-type info struct {
- colour int // creature's current colour.
- name int // creature's name.
-}
-
-// exclusive access data-structure kept inside meetingplace.
-// if mate is nil, it indicates there's no creature currently waiting;
-// otherwise the creature's info is stored in info, and
-// it is waiting to receive its mate's information on the mate channel.
-type rendez struct {
- n int // current number of encounters.
- mate chan<- info // creature waiting when non-nil.
- info info // info about creature waiting.
-}
-
-// result sent by each creature at the end of processing.
-type result struct {
- met int
- same int
-}
-
-var n = 600
-
-func main() {
- flag.Parse()
- if flag.NArg() > 0 {
- n, _ = strconv.Atoi(flag.Arg(0))
- }
-
- for c0 := 0; c0 < ncol; c0++ {
- for c1 := 0; c1 < ncol; c1++ {
- fmt.Printf("%s + %s -> %s\n", colname[c0], colname[c1], colname[complement[c0|c1<<2]])
- }
- }
- fmt.Print("\n")
-
- pallmall([]int{blue, red, yellow})
- pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue})
-}
-
-func pallmall(cols []int) {
-
- // invariant: meetingplace always contains a value unless a creature
- // is currently dealing with it (whereupon it must put it back).
- meetingplace := make(chan rendez, 1)
- meetingplace <- rendez{n: 0}
-
- ended := make(chan result)
- msg := ""
- for i, col := range cols {
- go creature(info{col, i}, meetingplace, ended)
- msg += " " + colname[col]
- }
- fmt.Println(msg)
- tot := 0
- // wait for all results
- for _ = range cols {
- result := <-ended
- tot += result.met
- fmt.Printf("%v%v\n", result.met, spell(result.same, true))
- }
- fmt.Printf("%v\n\n", spell(tot, true))
-}
-
-// in this function, variables ending in 0 refer to the local creature,
-// variables ending in 1 to the creature we've met.
-func creature(info0 info, meetingplace chan rendez, ended chan result) {
- c0 := make(chan info)
- met := 0
- same := 0
- for {
- var othername int
- // get access to rendez data and decide what to do.
- switch r := <-meetingplace; {
- case r.n >= n:
- // if no more meetings left, then send our result data and exit.
- meetingplace <- rendez{n: r.n}
- ended <- result{met, same}
- return
- case r.mate == nil:
- // no creature waiting; wait for someone to meet us,
- // get their info and send our info in reply.
- meetingplace <- rendez{n: r.n, info: info0, mate: c0}
- info1 := <-c0
- othername = info1.name
- info0.colour = complement[info0.colour|info1.colour<<2]
- default:
- // another creature is waiting for us with its info;
- // increment meeting count,
- // send them our info in reply.
- r.n++
- meetingplace <- rendez{n: r.n, mate: nil}
- r.mate <- info0
- othername = r.info.name
- info0.colour = complement[info0.colour|r.info.colour<<2]
- }
- if othername == info0.name {
- same++
- }
- met++
- }
-}
-
-var digits = [...]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
-
-func spell(n int, required bool) string {
- if n == 0 && !required {
- return ""
- }
- return spell(n/10, false) + " " + digits[n%10]
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.txt b/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.txt
deleted file mode 100644
index 6016d59..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/chameneosredux.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-blue + blue -> blue
-blue + red -> yellow
-blue + yellow -> red
-red + blue -> yellow
-red + red -> red
-red + yellow -> blue
-yellow + blue -> red
-yellow + red -> blue
-yellow + yellow -> yellow
-
- blue red yellow
-400 zero
-400 zero
-400 zero
- one two zero zero
-
- blue red yellow red yellow blue red yellow red blue
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
- one two zero zero
-
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.go b/gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.go
deleted file mode 100644
index 7e9b98d..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.go
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on fannkuch.scala by Rex Kerr
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "runtime"
-)
-
-var n = flag.Int("n", 7, "count")
-var nCPU = flag.Int("ncpu", 4, "number of cpus")
-
-type Job struct {
- start []int
- n int
-}
-
-type Found struct {
- who *Kucher
- k int
-}
-
-type Kucher struct {
- perm []int
- temp []int
- flip []int
- in chan Job
-}
-
-func NewKucher(length int) *Kucher {
- return &Kucher{
- perm: make([]int, length),
- temp: make([]int, length),
- flip: make([]int, length),
- in: make(chan Job),
- }
-}
-
-func (k *Kucher) permute(n int) bool {
- i := 0
- for ; i < n-1 && k.flip[i] == 0; i++ {
- t := k.perm[0]
- j := 0
- for ; j <= i; j++ {
- k.perm[j] = k.perm[j+1]
- }
- k.perm[j] = t
- }
- k.flip[i]--
- for i > 0 {
- i--
- k.flip[i] = i
- }
- return k.flip[n-1] >= 0
-}
-
-func (k *Kucher) count() int {
- K := 0
- copy(k.temp, k.perm)
- for k.temp[0] != 0 {
- m := k.temp[0]
- for i := 0; i < m; i++ {
- k.temp[i], k.temp[m] = k.temp[m], k.temp[i]
- m--
- }
- K++
- }
- return K
-}
-
-func (k *Kucher) Run(foreman chan<- Found) {
- for job := range k.in {
- verbose := 30
- copy(k.perm, job.start)
- for i, v := range k.perm {
- if v != i {
- verbose = 0
- }
- k.flip[i] = i
- }
- K := 0
- for {
- if verbose > 0 {
- for _, p := range k.perm {
- fmt.Print(p + 1)
- }
- fmt.Println()
- verbose--
- }
- count := k.count()
- if count > K {
- K = count
- }
- if !k.permute(job.n) {
- break
- }
- }
- foreman <- Found{k, K}
- }
-}
-
-type Fanner struct {
- jobind int
- jobsdone int
- k int
- jobs []Job
- workers []*Kucher
- in chan Found
- result chan int
-}
-
-func NewFanner(jobs []Job, workers []*Kucher) *Fanner {
- return &Fanner{
- jobs: jobs, workers: workers,
- in: make(chan Found),
- result: make(chan int),
- }
-}
-
-func (f *Fanner) Run(N int) {
- for msg := range f.in {
- if msg.k > f.k {
- f.k = msg.k
- }
- if msg.k >= 0 {
- f.jobsdone++
- }
- if f.jobind < len(f.jobs) {
- msg.who.in <- f.jobs[f.jobind]
- f.jobind++
- } else if f.jobsdone == len(f.jobs) {
- f.result <- f.k
- return
- }
- }
-}
-
-func swapped(a []int, i, j int) []int {
- b := make([]int, len(a))
- copy(b, a)
- b[i], b[j] = a[j], a[i]
- return b
-}
-
-func main() {
- flag.Parse()
- runtime.GOMAXPROCS(*nCPU)
- N := *n
- base := make([]int, N)
- for i := range base {
- base[i] = i
- }
-
- njobs := 1
- if N > 8 {
- njobs += (N*(N-1))/2 - 28 // njobs = 1 + sum(8..N-1) = 1 + sum(1..N-1) - sum(1..7)
- }
- jobs := make([]Job, njobs)
- jobsind := 0
-
- firstN := N
- if firstN > 8 {
- firstN = 8
- }
- jobs[jobsind] = Job{base, firstN}
- jobsind++
- for i := N - 1; i >= 8; i-- {
- for j := 0; j < i; j++ {
- jobs[jobsind] = Job{swapped(base, i, j), i}
- jobsind++
- }
- }
-
- nworkers := *nCPU
- if njobs < nworkers {
- nworkers = njobs
- }
- workers := make([]*Kucher, nworkers)
- foreman := NewFanner(jobs, workers)
- go foreman.Run(N)
- for i := range workers {
- k := NewKucher(N)
- workers[i] = k
- go k.Run(foreman.in)
- foreman.in <- Found{k, -1}
- }
- fmt.Printf("Pfannkuchen(%d) = %d\n", N, <-foreman.result)
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.txt b/gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.txt
deleted file mode 100644
index e66f779..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fannkuch-parallel.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-1234567
-2134567
-2314567
-3214567
-3124567
-1324567
-2341567
-3241567
-3421567
-4321567
-4231567
-2431567
-3412567
-4312567
-4132567
-1432567
-1342567
-3142567
-4123567
-1423567
-1243567
-2143567
-2413567
-4213567
-2345167
-3245167
-3425167
-4325167
-4235167
-2435167
-Pfannkuchen(7) = 16
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fannkuch.c b/gcc/testsuite/go.test/test/bench/shootout/fannkuch.c
deleted file mode 100644
index e576b54..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fannkuch.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Shootout
- * http://shootout.alioth.debian.org/
- * Contributed by Heiner Marxen
- *
- * "fannkuch" for C gcc
- *
- * $Id: fannkuch.1.gcc.code,v 1.15 2009-04-28 15:39:31 igouy-guest Exp $
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define Int int
-#define Aint int
-
- static long
-fannkuch( int n )
-{
- Aint* perm;
- Aint* perm1;
- Aint* count;
- long flips;
- long flipsMax;
- Int r;
- Int i;
- Int k;
- Int didpr;
- const Int n1 = n - 1;
-
- if( n < 1 ) return 0;
-
- perm = calloc(n, sizeof(*perm ));
- perm1 = calloc(n, sizeof(*perm1));
- count = calloc(n, sizeof(*count));
-
- for( i=0 ; i<n ; ++i ) perm1[i] = i; /* initial (trivial) permu */
-
- r = n; didpr = 0; flipsMax = 0;
- for(;;) {
- if( didpr < 30 ) {
- for( i=0 ; i<n ; ++i ) printf("%d", (int)(1+perm1[i]));
- printf("\n");
- ++didpr;
- }
- for( ; r!=1 ; --r ) {
- count[r-1] = r;
- }
-
-#define XCH(x,y) { Aint t_mp; t_mp=(x); (x)=(y); (y)=t_mp; }
-
- if( ! (perm1[0]==0 || perm1[n1]==n1) ) {
- flips = 0;
- for( i=1 ; i<n ; ++i ) { /* perm = perm1 */
- perm[i] = perm1[i];
- }
- k = perm1[0]; /* cache perm[0] in k */
- do { /* k!=0 ==> k>0 */
- Int j;
- for( i=1, j=k-1 ; i<j ; ++i, --j ) {
- XCH(perm[i], perm[j])
- }
- ++flips;
- /*
- * Now exchange k (caching perm[0]) and perm[k]... with care!
- * XCH(k, perm[k]) does NOT work!
- */
- j=perm[k]; perm[k]=k ; k=j;
- }while( k );
- if( flipsMax < flips ) {
- flipsMax = flips;
- }
- }
-
- for(;;) {
- if( r == n ) {
- return flipsMax;
- }
- /* rotate down perm[0..r] by one */
- {
- Int perm0 = perm1[0];
- i = 0;
- while( i < r ) {
- k = i+1;
- perm1[i] = perm1[k];
- i = k;
- }
- perm1[r] = perm0;
- }
- if( (count[r] -= 1) > 0 ) {
- break;
- }
- ++r;
- }
- }
-}
-
- int
-main( int argc, char* argv[] )
-{
- int n = (argc>1) ? atoi(argv[1]) : 0;
-
- printf("Pfannkuchen(%d) = %ld\n", n, fannkuch(n));
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fannkuch.go b/gcc/testsuite/go.test/test/bench/shootout/fannkuch.go
deleted file mode 100644
index b554c77..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fannkuch.go
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on fannkuch.c by Heiner Marxen
- */
-
-package main
-
-import (
- "flag"
- "fmt"
-)
-
-var n = flag.Int("n", 7, "count")
-
-func fannkuch(n int) int {
- if n < 1 {
- return 0
- }
-
- n1 := n - 1
- perm := make([]int, n)
- perm1 := make([]int, n)
- count := make([]int, n)
-
- for i := 0; i < n; i++ {
- perm1[i] = i // initial (trivial) permutation
- }
-
- r := n
- didpr := 0
- flipsMax := 0
- for {
- if didpr < 30 {
- for i := 0; i < n; i++ {
- fmt.Printf("%d", 1+perm1[i])
- }
- fmt.Printf("\n")
- didpr++
- }
- for ; r != 1; r-- {
- count[r-1] = r
- }
-
- if perm1[0] != 0 && perm1[n1] != n1 {
- flips := 0
- for i := 1; i < n; i++ { // perm = perm1
- perm[i] = perm1[i]
- }
- k := perm1[0] // cache perm[0] in k
- for { // k!=0 ==> k>0
- for i, j := 1, k-1; i < j; i, j = i+1, j-1 {
- perm[i], perm[j] = perm[j], perm[i]
- }
- flips++
- // Now exchange k (caching perm[0]) and perm[k]... with care!
- j := perm[k]
- perm[k] = k
- k = j
- if k == 0 {
- break
- }
- }
- if flipsMax < flips {
- flipsMax = flips
- }
- }
-
- for ; r < n; r++ {
- // rotate down perm[0..r] by one
- perm0 := perm1[0]
- for i := 0; i < r; i++ {
- perm1[i] = perm1[i+1]
- }
- perm1[r] = perm0
- count[r]--
- if count[r] > 0 {
- break
- }
- }
- if r == n {
- return flipsMax
- }
- }
- return 0
-}
-
-func main() {
- flag.Parse()
- fmt.Printf("Pfannkuchen(%d) = %d\n", *n, fannkuch(*n))
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fannkuch.txt b/gcc/testsuite/go.test/test/bench/shootout/fannkuch.txt
deleted file mode 100644
index e66f779..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fannkuch.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-1234567
-2134567
-2314567
-3214567
-3124567
-1324567
-2341567
-3241567
-3421567
-4321567
-4231567
-2431567
-3412567
-4312567
-4132567
-1432567
-1342567
-3142567
-4123567
-1423567
-1243567
-2143567
-2413567
-4213567
-2345167
-3245167
-3425167
-4325167
-4235167
-2435167
-Pfannkuchen(7) = 16
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fasta-1000.out b/gcc/testsuite/go.test/test/bench/shootout/fasta-1000.out
deleted file mode 100644
index f1caba0..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fasta-1000.out
+++ /dev/null
@@ -1,171 +0,0 @@
->ONE Homo sapiens alu
-GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
-TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
-AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
-GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
-CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
-GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
-GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
-TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
-AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
-GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
-AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
-AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
-GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
-CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
-AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
-TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
-TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
-GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
-TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
-CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
-CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
-TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
-CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
-AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
-GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
-TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
-TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
-GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
-GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
-ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
-TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
-CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
-CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
-GGCGACAGAGCGAGACTCCG
->TWO IUB ambiguity codes
-cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
-tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
-NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
-cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
-gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
-HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
-tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
-tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
-acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
-tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
-gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
-accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
-RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
-tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
-cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
-ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
-actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
-YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
-KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
-aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
-aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
-gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
-tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
-tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
-ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
-ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
-BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
-aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
-tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
-cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
-aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
-tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
-aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
-gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
-ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
-taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
-ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
-gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
-gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
-tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
-tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
-taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
-cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
-aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
-cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
-ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
-attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
-ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
-attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
-tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
->THREE Homo sapiens frequency
-aacacttcaccaggtatcgtgaaggctcaagattacccagagaacctttgcaatataaga
-atatgtatgcagcattaccctaagtaattatattctttttctgactcaaagtgacaagcc
-ctagtgtatattaaatcggtatatttgggaaattcctcaaactatcctaatcaggtagcc
-atgaaagtgatcaaaaaagttcgtacttataccatacatgaattctggccaagtaaaaaa
-tagattgcgcaaaattcgtaccttaagtctctcgccaagatattaggatcctattactca
-tatcgtgtttttctttattgccgccatccccggagtatctcacccatccttctcttaaag
-gcctaatattacctatgcaaataaacatatattgttgaaaattgagaacctgatcgtgat
-tcttatgtgtaccatatgtatagtaatcacgcgactatatagtgctttagtatcgcccgt
-gggtgagtgaatattctgggctagcgtgagatagtttcttgtcctaatatttttcagatc
-gaatagcttctatttttgtgtttattgacatatgtcgaaactccttactcagtgaaagtc
-atgaccagatccacgaacaatcttcggaatcagtctcgttttacggcggaatcttgagtc
-taacttatatcccgtcgcttactttctaacaccccttatgtatttttaaaattacgttta
-ttcgaacgtacttggcggaagcgttattttttgaagtaagttacattgggcagactcttg
-acattttcgatacgactttctttcatccatcacaggactcgttcgtattgatatcagaag
-ctcgtgatgattagttgtcttctttaccaatactttgaggcctattctgcgaaatttttg
-ttgccctgcgaacttcacataccaaggaacacctcgcaacatgccttcatatccatcgtt
-cattgtaattcttacacaatgaatcctaagtaattacatccctgcgtaaaagatggtagg
-ggcactgaggatatattaccaagcatttagttatgagtaatcagcaatgtttcttgtatt
-aagttctctaaaatagttacatcgtaatgttatctcgggttccgcgaataaacgagatag
-attcattatatatggccctaagcaaaaacctcctcgtattctgttggtaattagaatcac
-acaatacgggttgagatattaattatttgtagtacgaagagatataaaaagatgaacaat
-tactcaagtcaagatgtatacgggatttataataaaaatcgggtagagatctgctttgca
-attcagacgtgccactaaatcgtaatatgtcgcgttacatcagaaagggtaactattatt
-aattaataaagggcttaatcactacatattagatcttatccgatagtcttatctattcgt
-tgtatttttaagcggttctaattcagtcattatatcagtgctccgagttctttattattg
-ttttaaggatgacaaaatgcctcttgttataacgctgggagaagcagactaagagtcgga
-gcagttggtagaatgaggctgcaaaagacggtctcgacgaatggacagactttactaaac
-caatgaaagacagaagtagagcaaagtctgaagtggtatcagcttaattatgacaaccct
-taatacttccctttcgccgaatactggcgtggaaaggttttaaaagtcgaagtagttaga
-ggcatctctcgctcataaataggtagactactcgcaatccaatgtgactatgtaatactg
-ggaacatcagtccgcgatgcagcgtgtttatcaaccgtccccactcgcctggggagacat
-gagaccacccccgtggggattattagtccgcagtaatcgactcttgacaatccttttcga
-ttatgtcatagcaatttacgacagttcagcgaagtgactactcggcgaaatggtattact
-aaagcattcgaacccacatgaatgtgattcttggcaatttctaatccactaaagcttttc
-cgttgaatctggttgtagatatttatataagttcactaattaagatcacggtagtatatt
-gatagtgatgtctttgcaagaggttggccgaggaatttacggattctctattgatacaat
-ttgtctggcttataactcttaaggctgaaccaggcgtttttagacgacttgatcagctgt
-tagaatggtttggactccctctttcatgtcagtaacatttcagccgttattgttacgata
-tgcttgaacaatattgatctaccacacacccatagtatattttataggtcatgctgttac
-ctacgagcatggtattccacttcccattcaatgagtattcaacatcactagcctcagaga
-tgatgacccacctctaataacgtcacgttgcggccatgtgaaacctgaacttgagtagac
-gatatcaagcgctttaaattgcatataacatttgagggtaaagctaagcggatgctttat
-ataatcaatactcaataataagatttgattgcattttagagttatgacacgacatagttc
-actaacgagttactattcccagatctagactgaagtactgatcgagacgatccttacgtc
-gatgatcgttagttatcgacttaggtcgggtctctagcggtattggtacttaaccggaca
-ctatactaataacccatgatcaaagcataacagaatacagacgataatttcgccaacata
-tatgtacagaccccaagcatgagaagctcattgaaagctatcattgaagtcccgctcaca
-atgtgtcttttccagacggtttaactggttcccgggagtcctggagtttcgacttacata
-aatggaaacaatgtattttgctaatttatctatagcgtcatttggaccaatacagaatat
-tatgttgcctagtaatccactataacccgcaagtgctgatagaaaatttttagacgattt
-ataaatgccccaagtatccctcccgtgaatcctccgttatactaattagtattcgttcat
-acgtataccgcgcatatatgaacatttggcgataaggcgcgtgaattgttacgtgacaga
-gatagcagtttcttgtgatatggttaacagacgtacatgaagggaaactttatatctata
-gtgatgcttccgtagaaataccgccactggtctgccaatgatgaagtatgtagctttagg
-tttgtactatgaggctttcgtttgtttgcagagtataacagttgcgagtgaaaaaccgac
-gaatttatactaatacgctttcactattggctacaaaatagggaagagtttcaatcatga
-gagggagtatatggatgctttgtagctaaaggtagaacgtatgtatatgctgccgttcat
-tcttgaaagatacataagcgataagttacgacaattataagcaacatccctaccttcgta
-acgatttcactgttactgcgcttgaaatacactatggggctattggcggagagaagcaga
-tcgcgccgagcatatacgagacctataatgttgatgatagagaaggcgtctgaattgata
-catcgaagtacactttctttcgtagtatctctcgtcctctttctatctccggacacaaga
-attaagttatatatatagagtcttaccaatcatgttgaatcctgattctcagagttcttt
-ggcgggccttgtgatgactgagaaacaatgcaatattgctccaaatttcctaagcaaatt
-ctcggttatgttatgttatcagcaaagcgttacgttatgttatttaaatctggaatgacg
-gagcgaagttcttatgtcggtgtgggaataattcttttgaagacagcactccttaaataa
-tatcgctccgtgtttgtatttatcgaatgggtctgtaaccttgcacaagcaaatcggtgg
-tgtatatatcggataacaattaatacgatgttcatagtgacagtatactgatcgagtcct
-ctaaagtcaattacctcacttaacaatctcattgatgttgtgtcattcccggtatcgccc
-gtagtatgtgctctgattgaccgagtgtgaaccaaggaacatctactaatgcctttgtta
-ggtaagatctctctgaattccttcgtgccaacttaaaacattatcaaaatttcttctact
-tggattaactacttttacgagcatggcaaattcccctgtggaagacggttcattattatc
-ggaaaccttatagaaattgcgtgttgactgaaattagatttttattgtaagagttgcatc
-tttgcgattcctctggtctagcttccaatgaacagtcctcccttctattcgacatcgggt
-ccttcgtacatgtctttgcgatgtaataattaggttcggagtgtggccttaatgggtgca
-actaggaatacaacgcaaatttgctgacatgatagcaaatcggtatgccggcaccaaaac
-gtgctccttgcttagcttgtgaatgagactcagtagttaaataaatccatatctgcaatc
-gattccacaggtattgtccactatctttgaactactctaagagatacaagcttagctgag
-accgaggtgtatatgactacgctgatatctgtaaggtaccaatgcaggcaaagtatgcga
-gaagctaataccggctgtttccagctttataagattaaaatttggctgtcctggcggcct
-cagaattgttctatcgtaatcagttggttcattaattagctaagtacgaggtacaactta
-tctgtcccagaacagctccacaagtttttttacagccgaaacccctgtgtgaatcttaat
-atccaagcgcgttatctgattagagtttacaactcagtattttatcagtacgttttgttt
-ccaacattacccggtatgacaaaatgacgccacgtgtcgaataatggtctgaccaatgta
-ggaagtgaaaagataaatat
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fasta.c b/gcc/testsuite/go.test/test/bench/shootout/fasta.c
deleted file mode 100644
index 64c1c52..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fasta.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * http://shootout.alioth.debian.org/u32/program.php?test=fasta&lang=gcc&id=3
- */
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by Petr Prokhorenkov
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef fwrite_unlocked
-// not available on OS X
-#define fwrite_unlocked fwrite
-#define fputc_unlocked fputc
-#define fputs_unlocked fputs
-#endif
-
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
-#define unlikely(x) __builtin_expect((x), 0)
-
-#define IM 139968
-#define IA 3877
-#define IC 29573
-
-#define LINE_LEN 60
-#define LOOKUP_SIZE 4096
-#define LOOKUP_SCALE ((float)(LOOKUP_SIZE - 1))
-
-typedef unsigned random_t;
-
-void
-random_init(random_t *random) {
- *random = 42;
-}
-
-// Special version with result rescaled to LOOKUP_SCALE.
-static inline
-float
-random_next_lookup(random_t *random) {
- *random = (*random*IA + IC)%IM;
-
- return (*random)*(LOOKUP_SCALE/IM);
-}
-
-struct amino_acid {
- char sym;
- float prob;
- float cprob_lookup;
-};
-
-void
-repeat(const char *alu, const char *title, int n) {
- int len = strlen(alu);
- char buffer[len + LINE_LEN];
- int pos = 0;
-
- memcpy(buffer, alu, len);
- memcpy(buffer + len, alu, LINE_LEN);
-
- fputs_unlocked(title, stdout);
- while (n > 0) {
- int bytes = n > LINE_LEN ? LINE_LEN : n;
-
- fwrite_unlocked(buffer + pos, bytes, 1, stdout);
- pos += bytes;
- if (pos > len) {
- pos -= len;
- }
- fputc_unlocked('\n', stdout);
- n -= bytes;
- }
-}
-
-/*
- * Lookup table contains mapping from real values to cumulative
- * probabilities. Careful selection of table size allows lookup
- * virtually in constant time.
- *
- * All cumulative probabilities are rescaled to LOOKUP_SCALE,
- * this allows to save one multiplication operation on each iteration
- * in randomize().
- */
-
-void *
-fill_lookup(struct amino_acid **lookup, struct amino_acid *amino_acid, int amino_acid_size) {
- float p = 0;
- int i, j;
-
- for (i = 0; i < amino_acid_size; i++) {
- p += amino_acid[i].prob;
- amino_acid[i].cprob_lookup = p*LOOKUP_SCALE;
- }
-
- // Prevent rounding error.
- amino_acid[amino_acid_size - 1].cprob_lookup = LOOKUP_SIZE - 1;
-
- for (i = 0, j = 0; i < LOOKUP_SIZE; i++) {
- while (amino_acid[j].cprob_lookup < i) {
- j++;
- }
- lookup[i] = &amino_acid[j];
- }
-
- return 0;
-}
-
-void
-randomize(struct amino_acid *amino_acid, int amino_acid_size,
- const char *title, int n, random_t *rand) {
- struct amino_acid *lookup[LOOKUP_SIZE];
- char line_buffer[LINE_LEN + 1];
- int i, j;
-
- line_buffer[LINE_LEN] = '\n';
-
- fill_lookup(lookup, amino_acid, amino_acid_size);
-
- fputs_unlocked(title, stdout);
-
- for (i = 0, j = 0; i < n; i++, j++) {
- if (j == LINE_LEN) {
- fwrite_unlocked(line_buffer, LINE_LEN + 1, 1, stdout);
- j = 0;
- }
-
- float r = random_next_lookup(rand);
- struct amino_acid *u = lookup[(short)r];
- while (unlikely(u->cprob_lookup < r)) {
- ++u;
- }
- line_buffer[j] = u->sym;
- }
- line_buffer[j] = '\n';
- fwrite_unlocked(line_buffer, j + 1, 1, stdout);
-}
-
-struct amino_acid amino_acid[] = {
- { 'a', 0.27 },
- { 'c', 0.12 },
- { 'g', 0.12 },
- { 't', 0.27 },
-
- { 'B', 0.02 },
- { 'D', 0.02 },
- { 'H', 0.02 },
- { 'K', 0.02 },
- { 'M', 0.02 },
- { 'N', 0.02 },
- { 'R', 0.02 },
- { 'S', 0.02 },
- { 'V', 0.02 },
- { 'W', 0.02 },
- { 'Y', 0.02 },
-};
-
-struct amino_acid homo_sapiens[] = {
- { 'a', 0.3029549426680 },
- { 'c', 0.1979883004921 },
- { 'g', 0.1975473066391 },
- { 't', 0.3015094502008 },
-};
-
-static const char alu[] =
- "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG"
- "GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA"
- "GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA"
- "AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT"
- "CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC"
- "CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG"
- "CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
-
-int
-main(int argc, const char **argv) {
- int n = argc > 1 ? atoi( argv[1] ) : 512;
- random_t rand;
-
- random_init(&rand);
-
- repeat(alu, ">ONE Homo sapiens alu\n", n*2);
- randomize(amino_acid, ARRAY_SIZE(amino_acid),
- ">TWO IUB ambiguity codes\n", n*3, &rand);
- randomize(homo_sapiens, ARRAY_SIZE(homo_sapiens),
- ">THREE Homo sapiens frequency\n", n*5, &rand);
-
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fasta.go b/gcc/testsuite/go.test/test/bench/shootout/fasta.go
deleted file mode 100644
index 17ff5da..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fasta.go
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on C program by by Petr Prokhorenkov.
- */
-
-package main
-
-import (
- "flag"
- "os"
-)
-
-var out = make(buffer, 0, 32768)
-
-var n = flag.Int("n", 1000, "length of result")
-
-const Line = 60
-
-func Repeat(alu []byte, n int) {
- buf := append(alu, alu...)
- off := 0
- for n > 0 {
- m := n
- if m > Line {
- m = Line
- }
- buf1 := out.NextWrite(m + 1)
- copy(buf1, buf[off:])
- buf1[m] = '\n'
- if off += m; off >= len(alu) {
- off -= len(alu)
- }
- n -= m
- }
-}
-
-const (
- IM = 139968
- IA = 3877
- IC = 29573
-
- LookupSize = 4096
- LookupScale float64 = LookupSize - 1
-)
-
-var rand uint32 = 42
-
-type Acid struct {
- sym byte
- prob float64
- cprob float64
- next *Acid
-}
-
-func computeLookup(acid []Acid) *[LookupSize]*Acid {
- var lookup [LookupSize]*Acid
- var p float64
- for i := range acid {
- p += acid[i].prob
- acid[i].cprob = p * LookupScale
- if i > 0 {
- acid[i-1].next = &acid[i]
- }
- }
- acid[len(acid)-1].cprob = 1.0 * LookupScale
-
- j := 0
- for i := range lookup {
- for acid[j].cprob < float64(i) {
- j++
- }
- lookup[i] = &acid[j]
- }
-
- return &lookup
-}
-
-func Random(acid []Acid, n int) {
- lookup := computeLookup(acid)
- for n > 0 {
- m := n
- if m > Line {
- m = Line
- }
- buf := out.NextWrite(m + 1)
- f := LookupScale / IM
- myrand := rand
- for i := 0; i < m; i++ {
- myrand = (myrand*IA + IC) % IM
- r := float64(int(myrand)) * f
- a := lookup[int(r)]
- for a.cprob < r {
- a = a.next
- }
- buf[i] = a.sym
- }
- rand = myrand
- buf[m] = '\n'
- n -= m
- }
-}
-
-func main() {
- defer out.Flush()
-
- flag.Parse()
-
- iub := []Acid{
- {prob: 0.27, sym: 'a'},
- {prob: 0.12, sym: 'c'},
- {prob: 0.12, sym: 'g'},
- {prob: 0.27, sym: 't'},
- {prob: 0.02, sym: 'B'},
- {prob: 0.02, sym: 'D'},
- {prob: 0.02, sym: 'H'},
- {prob: 0.02, sym: 'K'},
- {prob: 0.02, sym: 'M'},
- {prob: 0.02, sym: 'N'},
- {prob: 0.02, sym: 'R'},
- {prob: 0.02, sym: 'S'},
- {prob: 0.02, sym: 'V'},
- {prob: 0.02, sym: 'W'},
- {prob: 0.02, sym: 'Y'},
- }
-
- homosapiens := []Acid{
- {prob: 0.3029549426680, sym: 'a'},
- {prob: 0.1979883004921, sym: 'c'},
- {prob: 0.1975473066391, sym: 'g'},
- {prob: 0.3015094502008, sym: 't'},
- }
-
- alu := []byte(
- "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
- "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
- "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
- "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
- "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
- "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
- "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")
-
- out.WriteString(">ONE Homo sapiens alu\n")
- Repeat(alu, 2**n)
- out.WriteString(">TWO IUB ambiguity codes\n")
- Random(iub, 3**n)
- out.WriteString(">THREE Homo sapiens frequency\n")
- Random(homosapiens, 5**n)
-}
-
-type buffer []byte
-
-func (b *buffer) Flush() {
- p := *b
- if len(p) > 0 {
- os.Stdout.Write(p)
- }
- *b = p[0:0]
-}
-
-func (b *buffer) WriteString(s string) {
- p := b.NextWrite(len(s))
- copy(p, s)
-}
-
-func (b *buffer) NextWrite(n int) []byte {
- p := *b
- if len(p)+n > cap(p) {
- b.Flush()
- p = *b
- }
- out := p[len(p) : len(p)+n]
- *b = p[:len(p)+n]
- return out
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/fasta.txt b/gcc/testsuite/go.test/test/bench/shootout/fasta.txt
deleted file mode 100644
index f1caba0..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/fasta.txt
+++ /dev/null
@@ -1,171 +0,0 @@
->ONE Homo sapiens alu
-GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
-TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
-AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
-GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
-CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
-GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
-GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
-TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
-AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
-GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
-AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
-AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
-GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
-CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
-AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
-TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
-TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
-GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
-TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
-CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
-CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
-TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
-CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
-AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
-GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
-TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
-TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
-GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
-GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
-ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
-TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
-CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
-CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
-GGCGACAGAGCGAGACTCCG
->TWO IUB ambiguity codes
-cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
-tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
-NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
-cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
-gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
-HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
-tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
-tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
-acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
-tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
-gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
-accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
-RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
-tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
-cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
-ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
-actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
-YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
-KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
-aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
-aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
-gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
-tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
-tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
-ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
-ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
-BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
-aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
-tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
-cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
-aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
-tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
-aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
-gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
-ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
-taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
-ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
-gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
-gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
-tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
-tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
-taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
-cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
-aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
-cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
-ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
-attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
-ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
-attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
-tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
->THREE Homo sapiens frequency
-aacacttcaccaggtatcgtgaaggctcaagattacccagagaacctttgcaatataaga
-atatgtatgcagcattaccctaagtaattatattctttttctgactcaaagtgacaagcc
-ctagtgtatattaaatcggtatatttgggaaattcctcaaactatcctaatcaggtagcc
-atgaaagtgatcaaaaaagttcgtacttataccatacatgaattctggccaagtaaaaaa
-tagattgcgcaaaattcgtaccttaagtctctcgccaagatattaggatcctattactca
-tatcgtgtttttctttattgccgccatccccggagtatctcacccatccttctcttaaag
-gcctaatattacctatgcaaataaacatatattgttgaaaattgagaacctgatcgtgat
-tcttatgtgtaccatatgtatagtaatcacgcgactatatagtgctttagtatcgcccgt
-gggtgagtgaatattctgggctagcgtgagatagtttcttgtcctaatatttttcagatc
-gaatagcttctatttttgtgtttattgacatatgtcgaaactccttactcagtgaaagtc
-atgaccagatccacgaacaatcttcggaatcagtctcgttttacggcggaatcttgagtc
-taacttatatcccgtcgcttactttctaacaccccttatgtatttttaaaattacgttta
-ttcgaacgtacttggcggaagcgttattttttgaagtaagttacattgggcagactcttg
-acattttcgatacgactttctttcatccatcacaggactcgttcgtattgatatcagaag
-ctcgtgatgattagttgtcttctttaccaatactttgaggcctattctgcgaaatttttg
-ttgccctgcgaacttcacataccaaggaacacctcgcaacatgccttcatatccatcgtt
-cattgtaattcttacacaatgaatcctaagtaattacatccctgcgtaaaagatggtagg
-ggcactgaggatatattaccaagcatttagttatgagtaatcagcaatgtttcttgtatt
-aagttctctaaaatagttacatcgtaatgttatctcgggttccgcgaataaacgagatag
-attcattatatatggccctaagcaaaaacctcctcgtattctgttggtaattagaatcac
-acaatacgggttgagatattaattatttgtagtacgaagagatataaaaagatgaacaat
-tactcaagtcaagatgtatacgggatttataataaaaatcgggtagagatctgctttgca
-attcagacgtgccactaaatcgtaatatgtcgcgttacatcagaaagggtaactattatt
-aattaataaagggcttaatcactacatattagatcttatccgatagtcttatctattcgt
-tgtatttttaagcggttctaattcagtcattatatcagtgctccgagttctttattattg
-ttttaaggatgacaaaatgcctcttgttataacgctgggagaagcagactaagagtcgga
-gcagttggtagaatgaggctgcaaaagacggtctcgacgaatggacagactttactaaac
-caatgaaagacagaagtagagcaaagtctgaagtggtatcagcttaattatgacaaccct
-taatacttccctttcgccgaatactggcgtggaaaggttttaaaagtcgaagtagttaga
-ggcatctctcgctcataaataggtagactactcgcaatccaatgtgactatgtaatactg
-ggaacatcagtccgcgatgcagcgtgtttatcaaccgtccccactcgcctggggagacat
-gagaccacccccgtggggattattagtccgcagtaatcgactcttgacaatccttttcga
-ttatgtcatagcaatttacgacagttcagcgaagtgactactcggcgaaatggtattact
-aaagcattcgaacccacatgaatgtgattcttggcaatttctaatccactaaagcttttc
-cgttgaatctggttgtagatatttatataagttcactaattaagatcacggtagtatatt
-gatagtgatgtctttgcaagaggttggccgaggaatttacggattctctattgatacaat
-ttgtctggcttataactcttaaggctgaaccaggcgtttttagacgacttgatcagctgt
-tagaatggtttggactccctctttcatgtcagtaacatttcagccgttattgttacgata
-tgcttgaacaatattgatctaccacacacccatagtatattttataggtcatgctgttac
-ctacgagcatggtattccacttcccattcaatgagtattcaacatcactagcctcagaga
-tgatgacccacctctaataacgtcacgttgcggccatgtgaaacctgaacttgagtagac
-gatatcaagcgctttaaattgcatataacatttgagggtaaagctaagcggatgctttat
-ataatcaatactcaataataagatttgattgcattttagagttatgacacgacatagttc
-actaacgagttactattcccagatctagactgaagtactgatcgagacgatccttacgtc
-gatgatcgttagttatcgacttaggtcgggtctctagcggtattggtacttaaccggaca
-ctatactaataacccatgatcaaagcataacagaatacagacgataatttcgccaacata
-tatgtacagaccccaagcatgagaagctcattgaaagctatcattgaagtcccgctcaca
-atgtgtcttttccagacggtttaactggttcccgggagtcctggagtttcgacttacata
-aatggaaacaatgtattttgctaatttatctatagcgtcatttggaccaatacagaatat
-tatgttgcctagtaatccactataacccgcaagtgctgatagaaaatttttagacgattt
-ataaatgccccaagtatccctcccgtgaatcctccgttatactaattagtattcgttcat
-acgtataccgcgcatatatgaacatttggcgataaggcgcgtgaattgttacgtgacaga
-gatagcagtttcttgtgatatggttaacagacgtacatgaagggaaactttatatctata
-gtgatgcttccgtagaaataccgccactggtctgccaatgatgaagtatgtagctttagg
-tttgtactatgaggctttcgtttgtttgcagagtataacagttgcgagtgaaaaaccgac
-gaatttatactaatacgctttcactattggctacaaaatagggaagagtttcaatcatga
-gagggagtatatggatgctttgtagctaaaggtagaacgtatgtatatgctgccgttcat
-tcttgaaagatacataagcgataagttacgacaattataagcaacatccctaccttcgta
-acgatttcactgttactgcgcttgaaatacactatggggctattggcggagagaagcaga
-tcgcgccgagcatatacgagacctataatgttgatgatagagaaggcgtctgaattgata
-catcgaagtacactttctttcgtagtatctctcgtcctctttctatctccggacacaaga
-attaagttatatatatagagtcttaccaatcatgttgaatcctgattctcagagttcttt
-ggcgggccttgtgatgactgagaaacaatgcaatattgctccaaatttcctaagcaaatt
-ctcggttatgttatgttatcagcaaagcgttacgttatgttatttaaatctggaatgacg
-gagcgaagttcttatgtcggtgtgggaataattcttttgaagacagcactccttaaataa
-tatcgctccgtgtttgtatttatcgaatgggtctgtaaccttgcacaagcaaatcggtgg
-tgtatatatcggataacaattaatacgatgttcatagtgacagtatactgatcgagtcct
-ctaaagtcaattacctcacttaacaatctcattgatgttgtgtcattcccggtatcgccc
-gtagtatgtgctctgattgaccgagtgtgaaccaaggaacatctactaatgcctttgtta
-ggtaagatctctctgaattccttcgtgccaacttaaaacattatcaaaatttcttctact
-tggattaactacttttacgagcatggcaaattcccctgtggaagacggttcattattatc
-ggaaaccttatagaaattgcgtgttgactgaaattagatttttattgtaagagttgcatc
-tttgcgattcctctggtctagcttccaatgaacagtcctcccttctattcgacatcgggt
-ccttcgtacatgtctttgcgatgtaataattaggttcggagtgtggccttaatgggtgca
-actaggaatacaacgcaaatttgctgacatgatagcaaatcggtatgccggcaccaaaac
-gtgctccttgcttagcttgtgaatgagactcagtagttaaataaatccatatctgcaatc
-gattccacaggtattgtccactatctttgaactactctaagagatacaagcttagctgag
-accgaggtgtatatgactacgctgatatctgtaaggtaccaatgcaggcaaagtatgcga
-gaagctaataccggctgtttccagctttataagattaaaatttggctgtcctggcggcct
-cagaattgttctatcgtaatcagttggttcattaattagctaagtacgaggtacaactta
-tctgtcccagaacagctccacaagtttttttacagccgaaacccctgtgtgaatcttaat
-atccaagcgcgttatctgattagagtttacaactcagtattttatcagtacgttttgttt
-ccaacattacccggtatgacaaaatgacgccacgtgtcgaataatggtctgaccaatgta
-ggaagtgaaaagataaatat
diff --git a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.go b/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.go
deleted file mode 100644
index 96c80d8..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.go
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "runtime"
- "sort"
-)
-
-func count(data string, n int) map[string]int {
- counts := make(map[string]int)
- top := len(data) - n
- for i := 0; i <= top; i++ {
- s := data[i : i+n]
- counts[s]++
- }
- return counts
-}
-
-func countOne(data string, s string) int {
- return count(data, len(s))[s]
-}
-
-type kNuc struct {
- name string
- count int
-}
-
-type kNucArray []kNuc
-
-func (kn kNucArray) Len() int { return len(kn) }
-func (kn kNucArray) Swap(i, j int) { kn[i], kn[j] = kn[j], kn[i] }
-func (kn kNucArray) Less(i, j int) bool {
- if kn[i].count == kn[j].count {
- return kn[i].name > kn[j].name // sort down
- }
- return kn[i].count > kn[j].count
-}
-
-func sortedArray(m map[string]int) kNucArray {
- kn := make(kNucArray, len(m))
- i := 0
- for k, v := range m {
- kn[i] = kNuc{k, v}
- i++
- }
- sort.Sort(kn)
- return kn
-}
-
-func printKnucs(a kNucArray) {
- sum := 0
- for _, kn := range a {
- sum += kn.count
- }
- for _, kn := range a {
- fmt.Printf("%s %.3f\n", kn.name, 100*float64(kn.count)/float64(sum))
- }
- fmt.Print("\n")
-}
-
-func main() {
- runtime.GOMAXPROCS(4)
- in := bufio.NewReader(os.Stdin)
- three := []byte(">THREE ")
- for {
- line, err := in.ReadSlice('\n')
- if err != nil {
- fmt.Fprintln(os.Stderr, "ReadLine err:", err)
- os.Exit(2)
- }
- if line[0] == '>' && bytes.Equal(line[0:len(three)], three) {
- break
- }
- }
- data, err := ioutil.ReadAll(in)
- if err != nil {
- fmt.Fprintln(os.Stderr, "ReadAll err:", err)
- os.Exit(2)
- }
- // delete the newlines and convert to upper case
- j := 0
- for i := 0; i < len(data); i++ {
- if data[i] != '\n' {
- data[j] = data[i] &^ ' ' // upper case
- j++
- }
- }
- str := string(data[0:j])
-
- var arr1, arr2 kNucArray
- countsdone := make(chan bool)
- go func() {
- arr1 = sortedArray(count(str, 1))
- countsdone <- true
- }()
- go func() {
- arr2 = sortedArray(count(str, 2))
- countsdone <- true
- }()
-
- interests := []string{"GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT"}
- results := make([]chan string, len(interests))
- for i, s := range interests {
- ch := make(chan string)
- results[i] = ch
- go func(result chan string, ss string) {
- result <- fmt.Sprintf("%d %s\n", countOne(str, ss), ss)
- }(ch, s)
- }
- <-countsdone
- <-countsdone
- printKnucs(arr1)
- printKnucs(arr2)
- for _, rc := range results {
- fmt.Print(<-rc)
- }
-
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.txt b/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.txt
deleted file mode 100644
index 84169b8..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide-parallel.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-T 31.520
-A 29.600
-C 19.480
-G 19.400
-
-AT 9.922
-TT 9.602
-TA 9.402
-AA 8.402
-GA 6.321
-TC 6.301
-TG 6.201
-GT 6.041
-CT 5.961
-AG 5.841
-CA 5.461
-AC 5.441
-CC 4.041
-CG 4.021
-GC 3.701
-GG 3.341
-
-54 GGT
-24 GGTA
-4 GGTATT
-0 GGTATTTTAATT
-0 GGTATTTTAATTTATAGT
diff --git a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.c b/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.c
deleted file mode 100644
index 9c30620..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <glib.h>
-
-typedef struct stat_s stat_t;
-struct stat_s
-{
- const gchar *key;
- long stat;
-};
-
-#define MAX_ELM (8192 / sizeof (stat_t))
-
-static int
-generate_frequencies (int fl, char *buffer, long buflen,
- GHashTable *ht, GTrashStack **ts, GPtrArray *roots, GStringChunk *sc)
-{
- gchar *key;
- long i;
-
- if (fl > buflen) return 0;
- if (fl == 0) return 0;
-
- for (i = 0; i < buflen - fl + 1; ++i)
- {
- char nulled;
- stat_t *stat;
-
- nulled = buffer[i + fl];
- buffer[i + fl] = '\0';
-
- key = g_string_chunk_insert_const(sc, buffer + i);
-
- stat = g_hash_table_lookup(ht, key);
- if (!stat)
- {
- stat = g_trash_stack_pop(ts);
- if (!stat)
- {
- int j;
-
- stat = malloc(sizeof (stat_t) * MAX_ELM);
- g_ptr_array_add(roots, stat);
-
- for (j = 1; j < MAX_ELM; ++j)
- g_trash_stack_push(ts, stat + j);
- }
- stat->stat = 1;
- stat->key = key;
-
- g_hash_table_insert(ht, key, stat);
- }
- else
- stat->stat++;
-
- buffer[i + fl] = nulled;
- }
-
- return buflen - fl + 1;
-}
-
-static int
-cmp_func(gconstpointer a, gconstpointer b)
-{
- const stat_t *left = a;
- const stat_t *right = b;
-
- return right->stat - left->stat;
-}
-
-static void
-sorted_list(gpointer key, gpointer value, gpointer user_data)
-{
- stat_t *data = value;
- GList **lst = user_data;
-
- *lst = g_list_insert_sorted(*lst, data, cmp_func);
-}
-
-static void
-display_stat(gpointer data, gpointer user_data)
-{
- long *total = user_data;
- stat_t *st = data;
-
- printf("%s %.3f\n", st->key, 100 * (float) st->stat / *total);
-}
-
-void
-write_frequencies (int fl, char *buffer, long buflen, GTrashStack **ts, GPtrArray *roots)
-{
- GStringChunk *sc;
- GHashTable *ht;
- GList *lst;
- long total;
-
- ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL /* free key */, NULL /* free value */);
- sc = g_string_chunk_new(buflen);
- lst = NULL;
-
- total = generate_frequencies (fl, buffer, buflen, ht, ts, roots, sc);
-
- if (!total) goto on_error;
-
- g_hash_table_foreach(ht, sorted_list, &lst);
- g_list_foreach(lst, display_stat, &total);
- g_list_free(lst);
-
- on_error:
- g_hash_table_destroy(ht);
- g_string_chunk_free(sc);
-}
-
-void
-write_count (char *searchFor, char *buffer, long buflen, GTrashStack **ts, GPtrArray *roots)
-{
- GStringChunk *sc;
- GHashTable *ht;
- stat_t *result;
- GList *lst;
- long total;
- long fl;
-
- fl = strlen(searchFor);
-
- ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL /* free key */, NULL /* free value */);
- sc = g_string_chunk_new(buflen);
- lst = NULL;
- result = NULL;
-
- total = generate_frequencies (fl, buffer, buflen, ht, ts, roots, sc);
-
- if (!total) goto on_error;
-
- result = g_hash_table_lookup(ht, searchFor);
-
- on_error:
- printf("%ld\t%s\n", result ? result->stat : 0, searchFor);
-
- g_hash_table_destroy(ht);
- g_string_chunk_free(sc);
-}
-
-int
-main ()
-{
- char buffer[4096];
- GTrashStack *ts;
- GPtrArray *roots;
- GString *stuff;
- gchar *s;
- int len;
-
- roots = g_ptr_array_new();
- ts = NULL;
-
- while (fgets(buffer, sizeof (buffer), stdin))
- if (strncmp(buffer, ">THREE", 6) == 0)
- break;
-
- stuff = g_string_new(NULL);
-
- while (fgets(buffer, sizeof (buffer), stdin))
- {
- size_t sz;
-
- if (buffer[0] == '>')
- break;
-
- sz = strlen(buffer);
- if (buffer[sz - 1] == '\n')
- --sz;
-
- stuff = g_string_append_len(stuff, buffer, sz);
- }
-
- stuff = g_string_ascii_up(stuff);
- len = stuff->len;
- s = g_string_free(stuff, FALSE);
-
- write_frequencies(1, s, len, &ts, roots);
- printf("\n");
- write_frequencies(2, s, len, &ts, roots);
- printf("\n");
- write_count("GGT", s, len, &ts, roots);
- write_count("GGTA", s, len, &ts, roots);
- write_count("GGTATT", s, len, &ts, roots);
- write_count("GGTATTTTAATT", s, len, &ts, roots);
- write_count("GGTATTTTAATTTATAGT", s, len, &ts, roots);
-
- free(s);
-
- g_ptr_array_foreach(roots, (GFunc)free, NULL);
- g_ptr_array_free(roots, TRUE);
-
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.go b/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.go
deleted file mode 100644
index fdc98ed..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.go
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "sort"
-)
-
-var in *bufio.Reader
-
-func count(data string, n int) map[string]int {
- counts := make(map[string]int)
- top := len(data) - n
- for i := 0; i <= top; i++ {
- s := data[i : i+n]
- counts[s]++
- }
- return counts
-}
-
-func countOne(data string, s string) int {
- return count(data, len(s))[s]
-}
-
-type kNuc struct {
- name string
- count int
-}
-
-type kNucArray []kNuc
-
-func (kn kNucArray) Len() int { return len(kn) }
-func (kn kNucArray) Swap(i, j int) { kn[i], kn[j] = kn[j], kn[i] }
-func (kn kNucArray) Less(i, j int) bool {
- if kn[i].count == kn[j].count {
- return kn[i].name > kn[j].name // sort down
- }
- return kn[i].count > kn[j].count
-}
-
-func sortedArray(m map[string]int) kNucArray {
- kn := make(kNucArray, len(m))
- i := 0
- for k, v := range m {
- kn[i].name = k
- kn[i].count = v
- i++
- }
- sort.Sort(kn)
- return kn
-}
-
-func print(m map[string]int) {
- a := sortedArray(m)
- sum := 0
- for _, kn := range a {
- sum += kn.count
- }
- for _, kn := range a {
- fmt.Printf("%s %.3f\n", kn.name, 100*float64(kn.count)/float64(sum))
- }
-}
-
-func main() {
- in = bufio.NewReader(os.Stdin)
- three := []byte(">THREE ")
- for {
- line, err := in.ReadSlice('\n')
- if err != nil {
- fmt.Fprintln(os.Stderr, "ReadLine err:", err)
- os.Exit(2)
- }
- if line[0] == '>' && bytes.Equal(line[0:len(three)], three) {
- break
- }
- }
- data, err := ioutil.ReadAll(in)
- if err != nil {
- fmt.Fprintln(os.Stderr, "ReadAll err:", err)
- os.Exit(2)
- }
- // delete the newlines and convert to upper case
- j := 0
- for i := 0; i < len(data); i++ {
- if data[i] != '\n' {
- data[j] = data[i] &^ ' ' // upper case
- j++
- }
- }
- str := string(data[0:j])
-
- print(count(str, 1))
- fmt.Print("\n")
-
- print(count(str, 2))
- fmt.Print("\n")
-
- interests := []string{"GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT"}
- for _, s := range interests {
- fmt.Printf("%d %s\n", countOne(str, s), s)
- }
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.txt b/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.txt
deleted file mode 100644
index 84169b8..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/k-nucleotide.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-T 31.520
-A 29.600
-C 19.480
-G 19.400
-
-AT 9.922
-TT 9.602
-TA 9.402
-AA 8.402
-GA 6.321
-TC 6.301
-TG 6.201
-GT 6.041
-CT 5.961
-AG 5.841
-CA 5.461
-AC 5.441
-CC 4.041
-CG 4.021
-GC 3.701
-GG 3.341
-
-54 GGT
-24 GGTA
-4 GGTATT
-0 GGTATTTTAATT
-0 GGTATTTTAATTTATAGT
diff --git a/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.c b/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.c
deleted file mode 100644
index c177c08..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Shootout
- http://shootout.alioth.debian.org/
-
- contributed by Greg Buchholz
-
- for the debian (AMD) machine...
- compile flags: -O3 -ffast-math -march=athlon-xp -funroll-loops
-
- for the gp4 (Intel) machine...
- compile flags: -O3 -ffast-math -march=pentium4 -funroll-loops
-*/
-
-#include<stdio.h>
-
-int main (int argc, char **argv)
-{
- int w, h, bit_num = 0;
- char byte_acc = 0;
- int i, iter = 50;
- double x, y, limit = 2.0;
- double Zr, Zi, Cr, Ci, Tr, Ti;
-
- w = h = atoi(argv[1]);
-
- printf("P4\n%d %d\n",w,h);
-
- for(y=0;y<h;++y)
- {
- for(x=0;x<w;++x)
- {
- Zr = Zi = Tr = Ti = 0.0;
- Cr = (2.0*x/w - 1.5); Ci=(2.0*y/h - 1.0);
-
- for (i=0;i<iter && (Tr+Ti <= limit*limit);++i)
- {
- Zi = 2.0*Zr*Zi + Ci;
- Zr = Tr - Ti + Cr;
- Tr = Zr * Zr;
- Ti = Zi * Zi;
- }
-
- byte_acc <<= 1;
- if(Tr+Ti <= limit*limit) byte_acc |= 0x01;
-
- ++bit_num;
-
- if(bit_num == 8)
- {
- putc(byte_acc,stdout);
- byte_acc = 0;
- bit_num = 0;
- }
- else if(x == w-1)
- {
- byte_acc <<= (8-w%8);
- putc(byte_acc,stdout);
- byte_acc = 0;
- bit_num = 0;
- }
- }
- }
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.go b/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.go
deleted file mode 100644
index df60343..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.go
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on mandelbrot.c contributed by Greg Buchholz
- */
-
-package main
-
-import (
- "bufio"
- "flag"
- "fmt"
- "os"
-)
-
-var n = flag.Int("n", 200, "size")
-
-func main() {
- flag.Parse()
- out := bufio.NewWriter(os.Stdout)
- defer out.Flush()
-
- w := float64(*n)
- h := float64(*n)
- bit_num := 0
- byte_acc := byte(0)
- const Iter = 50
- const Zero float64 = 0
- const Limit = 2.0
-
- fmt.Fprintf(out, "P4\n%d %d\n", *n, *n)
-
- for y := 0.0; y < h; y++ {
- for x := 0.0; x < w; x++ {
- Zr, Zi, Tr, Ti := Zero, Zero, Zero, Zero
- Cr := (2*x/w - 1.5)
- Ci := (2*y/h - 1.0)
-
- for i := 0; i < Iter && (Tr+Ti <= Limit*Limit); i++ {
- Zi = 2*Zr*Zi + Ci
- Zr = Tr - Ti + Cr
- Tr = Zr * Zr
- Ti = Zi * Zi
- }
-
- byte_acc <<= 1
- if Tr+Ti <= Limit*Limit {
- byte_acc |= 0x01
- }
-
- bit_num++
-
- if bit_num == 8 {
- out.WriteByte(byte_acc)
- byte_acc = 0
- bit_num = 0
- } else if x == w-1 {
- byte_acc <<= uint(8 - uint(*n)%8)
- out.WriteByte(byte_acc)
- byte_acc = 0
- bit_num = 0
- }
- }
- }
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.txt b/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.txt
deleted file mode 100644
index 2f7bbbc..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/mandelbrot.txt
+++ /dev/null
Binary files differ
diff --git a/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.c b/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.c
deleted file mode 100644
index 19c4340..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by Christian Vosteen
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#define TRUE 1
-#define FALSE 0
-
-/* The board is a 50 cell hexagonal pattern. For . . . . .
- * maximum speed the board will be implemented as . . . . .
- * 50 bits, which will fit into a 64 bit long long . . . . .
- * int. . . . . .
- * . . . . .
- * I will represent 0's as empty cells and 1's . . . . .
- * as full cells. . . . . .
- * . . . . .
- * . . . . .
- * . . . . .
- */
-
-unsigned long long board = 0xFFFC000000000000ULL;
-
-/* The puzzle pieces must be specified by the path followed
- * from one end to the other along 12 hexagonal directions.
- *
- * Piece 0 Piece 1 Piece 2 Piece 3 Piece 4
- *
- * O O O O O O O O O O O O O O O
- * O O O O O O O
- * O O O
- *
- * Piece 5 Piece 6 Piece 7 Piece 8 Piece 9
- *
- * O O O O O O O O O O O O O
- * O O O O O O O O O
- * O O O
- *
- * I had to make it 12 directions because I wanted all of the
- * piece definitions to fit into the same size arrays. It is
- * not possible to define piece 4 in terms of the 6 cardinal
- * directions in 4 moves.
- */
-
-#define E 0
-#define ESE 1
-#define SE 2
-#define S 3
-#define SW 4
-#define WSW 5
-#define W 6
-#define WNW 7
-#define NW 8
-#define N 9
-#define NE 10
-#define ENE 11
-#define PIVOT 12
-
-char piece_def[10][4] = {
- { E, E, E, SE},
- { SE, E, NE, E},
- { E, E, SE, SW},
- { E, E, SW, SE},
- { SE, E, NE, S},
- { E, E, SW, E},
- { E, SE, SE, NE},
- { E, SE, SE, W},
- { E, SE, E, E},
- { E, E, E, SW}
-};
-
-
-/* To minimize the amount of work done in the recursive solve function below,
- * I'm going to allocate enough space for all legal rotations of each piece
- * at each position on the board. That's 10 pieces x 50 board positions x
- * 12 rotations. However, not all 12 rotations will fit on every cell, so
- * I'll have to keep count of the actual number that do.
- * The pieces are going to be unsigned long long ints just like the board so
- * they can be bitwise-anded with the board to determine if they fit.
- * I'm also going to record the next possible open cell for each piece and
- * location to reduce the burden on the solve function.
- */
-unsigned long long pieces[10][50][12];
-int piece_counts[10][50];
-char next_cell[10][50][12];
-
-/* Returns the direction rotated 60 degrees clockwise */
-char rotate(char dir) {
- return (dir + 2) % PIVOT;
-}
-
-/* Returns the direction flipped on the horizontal axis */
-char flip(char dir) {
- return (PIVOT - dir) % PIVOT;
-}
-
-
-/* Returns the new cell index from the specified cell in the
- * specified direction. The index is only valid if the
- * starting cell and direction have been checked by the
- * out_of_bounds function first.
- */
-char shift(char cell, char dir) {
- switch(dir) {
- case E:
- return cell + 1;
- case ESE:
- if((cell / 5) % 2)
- return cell + 7;
- else
- return cell + 6;
- case SE:
- if((cell / 5) % 2)
- return cell + 6;
- else
- return cell + 5;
- case S:
- return cell + 10;
- case SW:
- if((cell / 5) % 2)
- return cell + 5;
- else
- return cell + 4;
- case WSW:
- if((cell / 5) % 2)
- return cell + 4;
- else
- return cell + 3;
- case W:
- return cell - 1;
- case WNW:
- if((cell / 5) % 2)
- return cell - 6;
- else
- return cell - 7;
- case NW:
- if((cell / 5) % 2)
- return cell - 5;
- else
- return cell - 6;
- case N:
- return cell - 10;
- case NE:
- if((cell / 5) % 2)
- return cell - 4;
- else
- return cell - 5;
- case ENE:
- if((cell / 5) % 2)
- return cell - 3;
- else
- return cell - 4;
- default:
- return cell;
- }
-}
-
-/* Returns wether the specified cell and direction will land outside
- * of the board. Used to determine if a piece is at a legal board
- * location or not.
- */
-char out_of_bounds(char cell, char dir) {
- char i;
- switch(dir) {
- case E:
- return cell % 5 == 4;
- case ESE:
- i = cell % 10;
- return i == 4 || i == 8 || i == 9 || cell >= 45;
- case SE:
- return cell % 10 == 9 || cell >= 45;
- case S:
- return cell >= 40;
- case SW:
- return cell % 10 == 0 || cell >= 45;
- case WSW:
- i = cell % 10;
- return i == 0 || i == 1 || i == 5 || cell >= 45;
- case W:
- return cell % 5 == 0;
- case WNW:
- i = cell % 10;
- return i == 0 || i == 1 || i == 5 || cell < 5;
- case NW:
- return cell % 10 == 0 || cell < 5;
- case N:
- return cell < 10;
- case NE:
- return cell % 10 == 9 || cell < 5;
- case ENE:
- i = cell % 10;
- return i == 4 || i == 8 || i == 9 || cell < 5;
- default:
- return FALSE;
- }
-}
-
-/* Rotate a piece 60 degrees clockwise */
-void rotate_piece(int piece) {
- int i;
- for(i = 0; i < 4; i++)
- piece_def[piece][i] = rotate(piece_def[piece][i]);
-}
-
-/* Flip a piece along the horizontal axis */
-void flip_piece(int piece) {
- int i;
- for(i = 0; i < 4; i++)
- piece_def[piece][i] = flip(piece_def[piece][i]);
-}
-
-/* Convenience function to quickly calculate all of the indices for a piece */
-void calc_cell_indices(char *cell, int piece, char index) {
- cell[0] = index;
- cell[1] = shift(cell[0], piece_def[piece][0]);
- cell[2] = shift(cell[1], piece_def[piece][1]);
- cell[3] = shift(cell[2], piece_def[piece][2]);
- cell[4] = shift(cell[3], piece_def[piece][3]);
-}
-
-/* Convenience function to quickly calculate if a piece fits on the board */
-int cells_fit_on_board(char *cell, int piece) {
- return (!out_of_bounds(cell[0], piece_def[piece][0]) &&
- !out_of_bounds(cell[1], piece_def[piece][1]) &&
- !out_of_bounds(cell[2], piece_def[piece][2]) &&
- !out_of_bounds(cell[3], piece_def[piece][3]));
-}
-
-/* Returns the lowest index of the cells of a piece.
- * I use the lowest index that a piece occupies as the index for looking up
- * the piece in the solve function.
- */
-char minimum_of_cells(char *cell) {
- char minimum = cell[0];
- minimum = cell[1] < minimum ? cell[1] : minimum;
- minimum = cell[2] < minimum ? cell[2] : minimum;
- minimum = cell[3] < minimum ? cell[3] : minimum;
- minimum = cell[4] < minimum ? cell[4] : minimum;
- return minimum;
-}
-
-/* Calculate the lowest possible open cell if the piece is placed on the board.
- * Used to later reduce the amount of time searching for open cells in the
- * solve function.
- */
-char first_empty_cell(char *cell, char minimum) {
- char first_empty = minimum;
- while(first_empty == cell[0] || first_empty == cell[1] ||
- first_empty == cell[2] || first_empty == cell[3] ||
- first_empty == cell[4])
- first_empty++;
- return first_empty;
-}
-
-/* Generate the unsigned long long int that will later be anded with the
- * board to determine if it fits.
- */
-unsigned long long bitmask_from_cells(char *cell) {
- unsigned long long piece_mask = 0ULL;
- int i;
- for(i = 0; i < 5; i++)
- piece_mask |= 1ULL << cell[i];
- return piece_mask;
-}
-
-/* Record the piece and other important information in arrays that will
- * later be used by the solve function.
- */
-void record_piece(int piece, int minimum, char first_empty,
- unsigned long long piece_mask) {
- pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask;
- next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty;
- piece_counts[piece][minimum]++;
-}
-
-
-/* Fill the entire board going cell by cell. If any cells are "trapped"
- * they will be left alone.
- */
-void fill_contiguous_space(char *board, int index) {
- if(board[index] == 1)
- return;
- board[index] = 1;
- if(!out_of_bounds(index, E))
- fill_contiguous_space(board, shift(index, E));
- if(!out_of_bounds(index, SE))
- fill_contiguous_space(board, shift(index, SE));
- if(!out_of_bounds(index, SW))
- fill_contiguous_space(board, shift(index, SW));
- if(!out_of_bounds(index, W))
- fill_contiguous_space(board, shift(index, W));
- if(!out_of_bounds(index, NW))
- fill_contiguous_space(board, shift(index, NW));
- if(!out_of_bounds(index, NE))
- fill_contiguous_space(board, shift(index, NE));
-}
-
-
-/* To thin the number of pieces, I calculate if any of them trap any empty
- * cells at the edges. There are only a handful of exceptions where the
- * the board can be solved with the trapped cells. For example: piece 8 can
- * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
- * can split the board in half where both halves are viable.
- */
-int has_island(char *cell, int piece) {
- char temp_board[50];
- char c;
- int i;
- for(i = 0; i < 50; i++)
- temp_board[i] = 0;
- for(i = 0; i < 5; i++)
- temp_board[((int)cell[i])] = 1;
- i = 49;
- while(temp_board[i] == 1)
- i--;
- fill_contiguous_space(temp_board, i);
- c = 0;
- for(i = 0; i < 50; i++)
- if(temp_board[i] == 0)
- c++;
- if(c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
- (c % 5 == 0 && piece == 0))
- return FALSE;
- else
- return TRUE;
-}
-
-
-/* Calculate all six rotations of the specified piece at the specified index.
- * We calculate only half of piece 3's rotations. This is because any solution
- * found has an identical solution rotated 180 degrees. Thus we can reduce the
- * number of attempted pieces in the solve algorithm by not including the 180-
- * degree-rotated pieces of ONE of the pieces. I chose piece 3 because it gave
- * me the best time ;)
- */
- void calc_six_rotations(char piece, char index) {
- char rotation, cell[5];
- char minimum, first_empty;
- unsigned long long piece_mask;
-
- for(rotation = 0; rotation < 6; rotation++) {
- if(piece != 3 || rotation < 3) {
- calc_cell_indices(cell, piece, index);
- if(cells_fit_on_board(cell, piece) && !has_island(cell, piece)) {
- minimum = minimum_of_cells(cell);
- first_empty = first_empty_cell(cell, minimum);
- piece_mask = bitmask_from_cells(cell);
- record_piece(piece, minimum, first_empty, piece_mask);
- }
- }
- rotate_piece(piece);
- }
-}
-
-/* Calculate every legal rotation for each piece at each board location. */
-void calc_pieces(void) {
- char piece, index;
-
- for(piece = 0; piece < 10; piece++) {
- for(index = 0; index < 50; index++) {
- calc_six_rotations(piece, index);
- flip_piece(piece);
- calc_six_rotations(piece, index);
- }
- }
-}
-
-
-
-/* Calculate all 32 possible states for a 5-bit row and all rows that will
- * create islands that follow any of the 32 possible rows. These pre-
- * calculated 5-bit rows will be used to find islands in a partially solved
- * board in the solve function.
- */
-#define ROW_MASK 0x1F
-#define TRIPLE_MASK 0x7FFF
-char all_rows[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
-int bad_even_rows[32][32];
-int bad_odd_rows[32][32];
-int bad_even_triple[32768];
-int bad_odd_triple[32768];
-
-int rows_bad(char row1, char row2, int even) {
- /* even is referring to row1 */
- int i, in_zeroes, group_okay;
- char block, row2_shift;
- /* Test for blockages at same index and shifted index */
- if(even)
- row2_shift = ((row2 << 1) & ROW_MASK) | 0x01;
- else
- row2_shift = (row2 >> 1) | 0x10;
- block = ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift);
- /* Test for groups of 0's */
- in_zeroes = FALSE;
- group_okay = FALSE;
- for(i = 0; i < 5; i++) {
- if(row1 & (1 << i)) {
- if(in_zeroes) {
- if(!group_okay)
- return TRUE;
- in_zeroes = FALSE;
- group_okay = FALSE;
- }
- } else {
- if(!in_zeroes)
- in_zeroes = TRUE;
- if(!(block & (1 << i)))
- group_okay = TRUE;
- }
- }
- if(in_zeroes)
- return !group_okay;
- else
- return FALSE;
-}
-
-/* Check for cases where three rows checked sequentially cause a false
- * positive. One scenario is when 5 cells may be surrounded where piece 5
- * or 7 can fit. The other scenario is when piece 2 creates a hook shape.
- */
-int triple_is_okay(char row1, char row2, char row3, int even) {
- if(even) {
- /* There are four cases:
- * row1: 00011 00001 11001 10101
- * row2: 01011 00101 10001 10001
- * row3: 011?? 00110 ????? ?????
- */
- return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
- ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
- ((row1 == 0x19) && (row2 == 0x11)) ||
- ((row1 == 0x15) && (row2 == 0x11));
- } else {
- /* There are two cases:
- * row1: 10011 10101
- * row2: 10001 10001
- * row3: ????? ?????
- */
- return ((row1 == 0x13) && (row2 == 0x11)) ||
- ((row1 == 0x15) && (row2 == 0x11));
- }
-}
-
-
-void calc_rows(void) {
- int row1, row2, row3;
- int result1, result2;
- for(row1 = 0; row1 < 32; row1++) {
- for(row2 = 0; row2 < 32; row2++) {
- bad_even_rows[row1][row2] = rows_bad(row1, row2, TRUE);
- bad_odd_rows[row1][row2] = rows_bad(row1, row2, FALSE);
- }
- }
- for(row1 = 0; row1 < 32; row1++) {
- for(row2 = 0; row2 < 32; row2++) {
- for(row3 = 0; row3 < 32; row3++) {
- result1 = bad_even_rows[row1][row2];
- result2 = bad_odd_rows[row2][row3];
- if(result1 == FALSE && result2 == TRUE
- && triple_is_okay(row1, row2, row3, TRUE))
- bad_even_triple[row1+(row2*32)+(row3*1024)] = FALSE;
- else
- bad_even_triple[row1+(row2*32)+(row3*1024)] = result1 || result2;
-
- result1 = bad_odd_rows[row1][row2];
- result2 = bad_even_rows[row2][row3];
- if(result1 == FALSE && result2 == TRUE
- && triple_is_okay(row1, row2, row3, FALSE))
- bad_odd_triple[row1+(row2*32)+(row3*1024)] = FALSE;
- else
- bad_odd_triple[row1+(row2*32)+(row3*1024)] = result1 || result2;
- }
- }
- }
-}
-
-
-
-/* Calculate islands while solving the board.
- */
-int boardHasIslands(char cell) {
- /* Too low on board, don't bother checking */
- if(cell >= 40)
- return FALSE;
- int current_triple = (board >> ((cell / 5) * 5)) & TRIPLE_MASK;
- if((cell / 5) % 2)
- return bad_odd_triple[current_triple];
- else
- return bad_even_triple[current_triple];
-}
-
-
-/* The recursive solve algorithm. Try to place each permutation in the upper-
- * leftmost empty cell. Mark off available pieces as it goes along.
- * Because the board is a bit mask, the piece number and bit mask must be saved
- * at each successful piece placement. This data is used to create a 50 char
- * array if a solution is found.
- */
-short avail = 0x03FF;
-char sol_nums[10];
-unsigned long long sol_masks[10];
-signed char solutions[2100][50];
-int solution_count = 0;
-int max_solutions = 2100;
-
-void record_solution(void) {
- int sol_no, index;
- unsigned long long sol_mask;
- for(sol_no = 0; sol_no < 10; sol_no++) {
- sol_mask = sol_masks[sol_no];
- for(index = 0; index < 50; index++) {
- if(sol_mask & 1ULL) {
- solutions[solution_count][index] = sol_nums[sol_no];
- /* Board rotated 180 degrees is a solution too! */
- solutions[solution_count+1][49-index] = sol_nums[sol_no];
- }
- sol_mask = sol_mask >> 1;
- }
- }
- solution_count += 2;
-}
-
-void solve(int depth, int cell) {
- int piece, rotation, max_rots;
- unsigned long long *piece_mask;
- short piece_no_mask;
-
- if(solution_count >= max_solutions)
- return;
-
- while(board & (1ULL << cell))
- cell++;
-
- for(piece = 0; piece < 10; piece++) {
- piece_no_mask = 1 << piece;
- if(!(avail & piece_no_mask))
- continue;
- avail ^= piece_no_mask;
- max_rots = piece_counts[piece][cell];
- piece_mask = pieces[piece][cell];
- for(rotation = 0; rotation < max_rots; rotation++) {
- if(!(board & *(piece_mask + rotation))) {
- sol_nums[depth] = piece;
- sol_masks[depth] = *(piece_mask + rotation);
- if(depth == 9) {
- /* Solution found!!!!!11!!ONE! */
- record_solution();
- avail ^= piece_no_mask;
- return;
- }
- board |= *(piece_mask + rotation);
- if(!boardHasIslands(next_cell[piece][cell][rotation]))
- solve(depth + 1, next_cell[piece][cell][rotation]);
- board ^= *(piece_mask + rotation);
- }
- }
- avail ^= piece_no_mask;
- }
-}
-
-
-/* qsort comparator - used to find first and last solutions */
-int solution_sort(const void *elem1, const void *elem2) {
- signed char *char1 = (signed char *) elem1;
- signed char *char2 = (signed char *) elem2;
- int i = 0;
- while(i < 50 && char1[i] == char2[i])
- i++;
- return char1[i] - char2[i];
-}
-
-
-/* pretty print a board in the specified hexagonal format */
-void pretty(signed char *b) {
- int i;
- for(i = 0; i < 50; i += 10) {
- printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
- b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
- b[i+7]+'0', b[i+8]+'0', b[i+9]+'0');
- }
- printf("\n");
-}
-
-int main(int argc, char **argv) {
- if(argc > 1)
- max_solutions = atoi(argv[1]);
- calc_pieces();
- calc_rows();
- solve(0, 0);
- printf("%d solutions found\n\n", solution_count);
- qsort(solutions, solution_count, 50 * sizeof(signed char), solution_sort);
- pretty(solutions[0]);
- pretty(solutions[solution_count-1]);
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.go b/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.go
deleted file mode 100644
index 34a4e23..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.go
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on meteor-contest.c by Christian Vosteen
- */
-
-package main
-
-import (
- "flag"
- "fmt"
-)
-
-var max_solutions = flag.Int("n", 2100, "maximum number of solutions")
-
-func boolInt(b bool) int8 {
- if b {
- return 1
- }
- return 0
-}
-
-/* The board is a 50 cell hexagonal pattern. For . . . . .
- * maximum speed the board will be implemented as . . . . .
- * 50 bits, which will fit into a 64 bit long long . . . . .
- * int. . . . . .
- * . . . . .
- * I will represent 0's as empty cells and 1's . . . . .
- * as full cells. . . . . .
- * . . . . .
- * . . . . .
- * . . . . .
- */
-
-var board uint64 = 0xFFFC000000000000
-
-/* The puzzle pieces must be specified by the path followed
- * from one end to the other along 12 hexagonal directions.
- *
- * Piece 0 Piece 1 Piece 2 Piece 3 Piece 4
- *
- * O O O O O O O O O O O O O O O
- * O O O O O O O
- * O O O
- *
- * Piece 5 Piece 6 Piece 7 Piece 8 Piece 9
- *
- * O O O O O O O O O O O O O
- * O O O O O O O O O
- * O O O
- *
- * I had to make it 12 directions because I wanted all of the
- * piece definitions to fit into the same size arrays. It is
- * not possible to define piece 4 in terms of the 6 cardinal
- * directions in 4 moves.
- */
-
-const (
- E = iota
- ESE
- SE
- S
- SW
- WSW
- W
- WNW
- NW
- N
- NE
- ENE
- PIVOT
-)
-
-var piece_def = [10][4]int8{
- [4]int8{E, E, E, SE},
- [4]int8{SE, E, NE, E},
- [4]int8{E, E, SE, SW},
- [4]int8{E, E, SW, SE},
- [4]int8{SE, E, NE, S},
- [4]int8{E, E, SW, E},
- [4]int8{E, SE, SE, NE},
- [4]int8{E, SE, SE, W},
- [4]int8{E, SE, E, E},
- [4]int8{E, E, E, SW},
-}
-
-/* To minimize the amount of work done in the recursive solve function below,
- * I'm going to allocate enough space for all legal rotations of each piece
- * at each position on the board. That's 10 pieces x 50 board positions x
- * 12 rotations. However, not all 12 rotations will fit on every cell, so
- * I'll have to keep count of the actual number that do.
- * The pieces are going to be unsigned long long ints just like the board so
- * they can be bitwise-anded with the board to determine if they fit.
- * I'm also going to record the next possible open cell for each piece and
- * location to reduce the burden on the solve function.
- */
-var (
- pieces [10][50][12]uint64
- piece_counts [10][50]int
- next_cell [10][50][12]int8
-)
-
-/* Returns the direction rotated 60 degrees clockwise */
-func rotate(dir int8) int8 { return (dir + 2) % PIVOT }
-
-/* Returns the direction flipped on the horizontal axis */
-func flip(dir int8) int8 { return (PIVOT - dir) % PIVOT }
-
-/* Returns the new cell index from the specified cell in the
- * specified direction. The index is only valid if the
- * starting cell and direction have been checked by the
- * out_of_bounds function first.
- */
-func shift(cell, dir int8) int8 {
- switch dir {
- case E:
- return cell + 1
- case ESE:
- if ((cell / 5) % 2) != 0 {
- return cell + 7
- } else {
- return cell + 6
- }
- case SE:
- if ((cell / 5) % 2) != 0 {
- return cell + 6
- } else {
- return cell + 5
- }
- case S:
- return cell + 10
- case SW:
- if ((cell / 5) % 2) != 0 {
- return cell + 5
- } else {
- return cell + 4
- }
- case WSW:
- if ((cell / 5) % 2) != 0 {
- return cell + 4
- } else {
- return cell + 3
- }
- case W:
- return cell - 1
- case WNW:
- if ((cell / 5) % 2) != 0 {
- return cell - 6
- } else {
- return cell - 7
- }
- case NW:
- if ((cell / 5) % 2) != 0 {
- return cell - 5
- } else {
- return cell - 6
- }
- case N:
- return cell - 10
- case NE:
- if ((cell / 5) % 2) != 0 {
- return cell - 4
- } else {
- return cell - 5
- }
- case ENE:
- if ((cell / 5) % 2) != 0 {
- return cell - 3
- } else {
- return cell - 4
- }
- }
- return cell
-}
-
-/* Returns wether the specified cell and direction will land outside
- * of the board. Used to determine if a piece is at a legal board
- * location or not.
- */
-func out_of_bounds(cell, dir int8) bool {
- switch dir {
- case E:
- return cell%5 == 4
- case ESE:
- i := cell % 10
- return i == 4 || i == 8 || i == 9 || cell >= 45
- case SE:
- return cell%10 == 9 || cell >= 45
- case S:
- return cell >= 40
- case SW:
- return cell%10 == 0 || cell >= 45
- case WSW:
- i := cell % 10
- return i == 0 || i == 1 || i == 5 || cell >= 45
- case W:
- return cell%5 == 0
- case WNW:
- i := cell % 10
- return i == 0 || i == 1 || i == 5 || cell < 5
- case NW:
- return cell%10 == 0 || cell < 5
- case N:
- return cell < 10
- case NE:
- return cell%10 == 9 || cell < 5
- case ENE:
- i := cell % 10
- return i == 4 || i == 8 || i == 9 || cell < 5
- }
- return false
-}
-
-/* Rotate a piece 60 degrees clockwise */
-func rotate_piece(piece int) {
- for i := 0; i < 4; i++ {
- piece_def[piece][i] = rotate(piece_def[piece][i])
- }
-}
-
-/* Flip a piece along the horizontal axis */
-func flip_piece(piece int) {
- for i := 0; i < 4; i++ {
- piece_def[piece][i] = flip(piece_def[piece][i])
- }
-}
-
-/* Convenience function to quickly calculate all of the indices for a piece */
-func calc_cell_indices(cell []int8, piece int, index int8) {
- cell[0] = index
- for i := 1; i < 5; i++ {
- cell[i] = shift(cell[i-1], piece_def[piece][i-1])
- }
-}
-
-/* Convenience function to quickly calculate if a piece fits on the board */
-func cells_fit_on_board(cell []int8, piece int) bool {
- return !out_of_bounds(cell[0], piece_def[piece][0]) &&
- !out_of_bounds(cell[1], piece_def[piece][1]) &&
- !out_of_bounds(cell[2], piece_def[piece][2]) &&
- !out_of_bounds(cell[3], piece_def[piece][3])
-}
-
-/* Returns the lowest index of the cells of a piece.
- * I use the lowest index that a piece occupies as the index for looking up
- * the piece in the solve function.
- */
-func minimum_of_cells(cell []int8) int8 {
- minimum := cell[0]
- for i := 1; i < 5; i++ {
- if cell[i] < minimum {
- minimum = cell[i]
- }
- }
- return minimum
-}
-
-/* Calculate the lowest possible open cell if the piece is placed on the board.
- * Used to later reduce the amount of time searching for open cells in the
- * solve function.
- */
-func first_empty_cell(cell []int8, minimum int8) int8 {
- first_empty := minimum
- for first_empty == cell[0] || first_empty == cell[1] ||
- first_empty == cell[2] || first_empty == cell[3] ||
- first_empty == cell[4] {
- first_empty++
- }
- return first_empty
-}
-
-/* Generate the unsigned long long int that will later be anded with the
- * board to determine if it fits.
- */
-func bitmask_from_cells(cell []int8) uint64 {
- var piece_mask uint64
- for i := 0; i < 5; i++ {
- piece_mask |= 1 << uint(cell[i])
- }
- return piece_mask
-}
-
-/* Record the piece and other important information in arrays that will
- * later be used by the solve function.
- */
-func record_piece(piece int, minimum int8, first_empty int8, piece_mask uint64) {
- pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask
- next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty
- piece_counts[piece][minimum]++
-}
-
-/* Fill the entire board going cell by cell. If any cells are "trapped"
- * they will be left alone.
- */
-func fill_contiguous_space(board []int8, index int8) {
- if board[index] == 1 {
- return
- }
- board[index] = 1
- if !out_of_bounds(index, E) {
- fill_contiguous_space(board, shift(index, E))
- }
- if !out_of_bounds(index, SE) {
- fill_contiguous_space(board, shift(index, SE))
- }
- if !out_of_bounds(index, SW) {
- fill_contiguous_space(board, shift(index, SW))
- }
- if !out_of_bounds(index, W) {
- fill_contiguous_space(board, shift(index, W))
- }
- if !out_of_bounds(index, NW) {
- fill_contiguous_space(board, shift(index, NW))
- }
- if !out_of_bounds(index, NE) {
- fill_contiguous_space(board, shift(index, NE))
- }
-}
-
-/* To thin the number of pieces, I calculate if any of them trap any empty
- * cells at the edges. There are only a handful of exceptions where the
- * the board can be solved with the trapped cells. For example: piece 8 can
- * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
- * can split the board in half where both halves are viable.
- */
-func has_island(cell []int8, piece int) bool {
- temp_board := make([]int8, 50)
- var i int
- for i = 0; i < 5; i++ {
- temp_board[cell[i]] = 1
- }
- i = 49
- for temp_board[i] == 1 {
- i--
- }
- fill_contiguous_space(temp_board, int8(i))
- c := 0
- for i = 0; i < 50; i++ {
- if temp_board[i] == 0 {
- c++
- }
- }
- if c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
- (c%5 == 0 && piece == 0) {
- return false
- }
- return true
-}
-
-/* Calculate all six rotations of the specified piece at the specified index.
- * We calculate only half of piece 3's rotations. This is because any solution
- * found has an identical solution rotated 180 degrees. Thus we can reduce the
- * number of attempted pieces in the solve algorithm by not including the 180-
- * degree-rotated pieces of ONE of the pieces. I chose piece 3 because it gave
- * me the best time ;)
- */
-func calc_six_rotations(piece, index int) {
- cell := make([]int8, 5)
- for rotation := 0; rotation < 6; rotation++ {
- if piece != 3 || rotation < 3 {
- calc_cell_indices(cell, piece, int8(index))
- if cells_fit_on_board(cell, piece) && !has_island(cell, piece) {
- minimum := minimum_of_cells(cell)
- first_empty := first_empty_cell(cell, minimum)
- piece_mask := bitmask_from_cells(cell)
- record_piece(piece, minimum, first_empty, piece_mask)
- }
- }
- rotate_piece(piece)
- }
-}
-
-/* Calculate every legal rotation for each piece at each board location. */
-func calc_pieces() {
- for piece := 0; piece < 10; piece++ {
- for index := 0; index < 50; index++ {
- calc_six_rotations(piece, index)
- flip_piece(piece)
- calc_six_rotations(piece, index)
- }
- }
-}
-
-/* Calculate all 32 possible states for a 5-bit row and all rows that will
- * create islands that follow any of the 32 possible rows. These pre-
- * calculated 5-bit rows will be used to find islands in a partially solved
- * board in the solve function.
- */
-const (
- ROW_MASK = 0x1F
- TRIPLE_MASK = 0x7FFF
-)
-
-var (
- all_rows = [32]int8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- }
- bad_even_rows [32][32]int8
- bad_odd_rows [32][32]int8
- bad_even_triple [32768]int8
- bad_odd_triple [32768]int8
-)
-
-func rows_bad(row1, row2 int8, even bool) int8 {
- /* even is referring to row1 */
- var row2_shift int8
- /* Test for blockages at same index and shifted index */
- if even {
- row2_shift = ((row2 << 1) & ROW_MASK) | 0x01
- } else {
- row2_shift = (row2 >> 1) | 0x10
- }
- block := ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift)
- /* Test for groups of 0's */
- in_zeroes := false
- group_okay := false
- for i := uint8(0); i < 5; i++ {
- if row1&(1<<i) != 0 {
- if in_zeroes {
- if !group_okay {
- return 1
- }
- in_zeroes = false
- group_okay = false
- }
- } else {
- if !in_zeroes {
- in_zeroes = true
- }
- if (block & (1 << i)) == 0 {
- group_okay = true
- }
- }
- }
- if in_zeroes {
- return boolInt(!group_okay)
- }
- return 0
-}
-
-/* Check for cases where three rows checked sequentially cause a false
- * positive. One scenario is when 5 cells may be surrounded where piece 5
- * or 7 can fit. The other scenario is when piece 2 creates a hook shape.
- */
-func triple_is_okay(row1, row2, row3 int, even bool) bool {
- if even {
- /* There are four cases:
- * row1: 00011 00001 11001 10101
- * row2: 01011 00101 10001 10001
- * row3: 011?? 00110 ????? ?????
- */
- return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
- ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
- ((row1 == 0x19) && (row2 == 0x11)) ||
- ((row1 == 0x15) && (row2 == 0x11))
- }
- /* There are two cases:
- * row1: 10011 10101
- * row2: 10001 10001
- * row3: ????? ?????
- */
- return ((row1 == 0x13) && (row2 == 0x11)) ||
- ((row1 == 0x15) && (row2 == 0x11))
-}
-
-func calc_rows() {
- for row1 := int8(0); row1 < 32; row1++ {
- for row2 := int8(0); row2 < 32; row2++ {
- bad_even_rows[row1][row2] = rows_bad(row1, row2, true)
- bad_odd_rows[row1][row2] = rows_bad(row1, row2, false)
- }
- }
- for row1 := 0; row1 < 32; row1++ {
- for row2 := 0; row2 < 32; row2++ {
- for row3 := 0; row3 < 32; row3++ {
- result1 := bad_even_rows[row1][row2]
- result2 := bad_odd_rows[row2][row3]
- if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, true) {
- bad_even_triple[row1+(row2*32)+(row3*1024)] = 0
- } else {
- bad_even_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
- }
-
- result1 = bad_odd_rows[row1][row2]
- result2 = bad_even_rows[row2][row3]
- if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, false) {
- bad_odd_triple[row1+(row2*32)+(row3*1024)] = 0
- } else {
- bad_odd_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
- }
- }
- }
- }
-}
-
-/* Calculate islands while solving the board.
- */
-func boardHasIslands(cell int8) int8 {
- /* Too low on board, don't bother checking */
- if cell >= 40 {
- return 0
- }
- current_triple := (board >> uint((cell/5)*5)) & TRIPLE_MASK
- if (cell/5)%2 != 0 {
- return bad_odd_triple[current_triple]
- }
- return bad_even_triple[current_triple]
-}
-
-/* The recursive solve algorithm. Try to place each permutation in the upper-
- * leftmost empty cell. Mark off available pieces as it goes along.
- * Because the board is a bit mask, the piece number and bit mask must be saved
- * at each successful piece placement. This data is used to create a 50 char
- * array if a solution is found.
- */
-var (
- avail uint16 = 0x03FF
- sol_nums [10]int8
- sol_masks [10]uint64
- solutions [2100][50]int8
- solution_count = 0
-)
-
-func record_solution() {
- for sol_no := 0; sol_no < 10; sol_no++ {
- sol_mask := sol_masks[sol_no]
- for index := 0; index < 50; index++ {
- if sol_mask&1 == 1 {
- solutions[solution_count][index] = sol_nums[sol_no]
- /* Board rotated 180 degrees is a solution too! */
- solutions[solution_count+1][49-index] = sol_nums[sol_no]
- }
- sol_mask = sol_mask >> 1
- }
- }
- solution_count += 2
-}
-
-func solve(depth, cell int8) {
- if solution_count >= *max_solutions {
- return
- }
-
- for board&(1<<uint(cell)) != 0 {
- cell++
- }
-
- for piece := int8(0); piece < 10; piece++ {
- var piece_no_mask uint16 = 1 << uint(piece)
- if avail&piece_no_mask == 0 {
- continue
- }
- avail ^= piece_no_mask
- max_rots := piece_counts[piece][cell]
- piece_mask := pieces[piece][cell]
- for rotation := 0; rotation < max_rots; rotation++ {
- if board&piece_mask[rotation] == 0 {
- sol_nums[depth] = piece
- sol_masks[depth] = piece_mask[rotation]
- if depth == 9 {
- /* Solution found!!!!!11!!ONE! */
- record_solution()
- avail ^= piece_no_mask
- return
- }
- board |= piece_mask[rotation]
- if boardHasIslands(next_cell[piece][cell][rotation]) == 0 {
- solve(depth+1, next_cell[piece][cell][rotation])
- }
- board ^= piece_mask[rotation]
- }
- }
- avail ^= piece_no_mask
- }
-}
-
-/* pretty print a board in the specified hexagonal format */
-func pretty(b *[50]int8) {
- for i := 0; i < 50; i += 10 {
- fmt.Printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
- b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
- b[i+7]+'0', b[i+8]+'0', b[i+9]+'0')
- }
- fmt.Printf("\n")
-}
-
-/* Find smallest and largest solutions */
-func smallest_largest() (smallest, largest *[50]int8) {
- smallest = &solutions[0]
- largest = &solutions[0]
- for i := 1; i < solution_count; i++ {
- candidate := &solutions[i]
- for j, s := range *smallest {
- c := candidate[j]
- if c == s {
- continue
- }
- if c < s {
- smallest = candidate
- }
- break
- }
- for j, s := range *largest {
- c := candidate[j]
- if c == s {
- continue
- }
- if c > s {
- largest = candidate
- }
- break
- }
- }
- return
-}
-
-func main() {
- flag.Parse()
- calc_pieces()
- calc_rows()
- solve(0, 0)
- fmt.Printf("%d solutions found\n\n", solution_count)
- smallest, largest := smallest_largest()
- pretty(smallest)
- pretty(largest)
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.txt b/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.txt
deleted file mode 100644
index 38d9783..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/meteor-contest.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-2098 solutions found
-
-0 0 0 0 1
- 2 2 2 0 1
-2 6 6 1 1
- 2 6 1 5 5
-8 6 5 5 5
- 8 6 3 3 3
-4 8 8 9 3
- 4 4 8 9 3
-4 7 4 7 9
- 7 7 7 9 9
-
-9 9 9 9 8
- 9 6 6 8 5
-6 6 8 8 5
- 6 8 2 5 5
-7 7 7 2 5
- 7 4 7 2 0
-1 4 2 2 0
- 1 4 4 0 3
-1 4 0 0 3
- 1 1 3 3 3
-
diff --git a/gcc/testsuite/go.test/test/bench/shootout/nbody.c b/gcc/testsuite/go.test/test/bench/shootout/nbody.c
deleted file mode 100644
index 3b95b05..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/nbody.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Great Computer Language Shootout
- * http://shootout.alioth.debian.org/
- *
- * contributed by Christoph Bauer
- *
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define pi 3.141592653589793
-#define solar_mass (4 * pi * pi)
-#define days_per_year 365.24
-
-struct planet {
- double x, y, z;
- double vx, vy, vz;
- double mass;
-};
-
-void advance(int nbodies, struct planet * bodies, double dt)
-{
- int i, j;
-
- for (i = 0; i < nbodies; i++) {
- struct planet * b = &(bodies[i]);
- for (j = i + 1; j < nbodies; j++) {
- struct planet * b2 = &(bodies[j]);
- double dx = b->x - b2->x;
- double dy = b->y - b2->y;
- double dz = b->z - b2->z;
- double distance = sqrt(dx * dx + dy * dy + dz * dz);
- double mag = dt / (distance * distance * distance);
- b->vx -= dx * b2->mass * mag;
- b->vy -= dy * b2->mass * mag;
- b->vz -= dz * b2->mass * mag;
- b2->vx += dx * b->mass * mag;
- b2->vy += dy * b->mass * mag;
- b2->vz += dz * b->mass * mag;
- }
- }
- for (i = 0; i < nbodies; i++) {
- struct planet * b = &(bodies[i]);
- b->x += dt * b->vx;
- b->y += dt * b->vy;
- b->z += dt * b->vz;
- }
-}
-
-double energy(int nbodies, struct planet * bodies)
-{
- double e;
- int i, j;
-
- e = 0.0;
- for (i = 0; i < nbodies; i++) {
- struct planet * b = &(bodies[i]);
- e += 0.5 * b->mass * (b->vx * b->vx + b->vy * b->vy + b->vz * b->vz);
- for (j = i + 1; j < nbodies; j++) {
- struct planet * b2 = &(bodies[j]);
- double dx = b->x - b2->x;
- double dy = b->y - b2->y;
- double dz = b->z - b2->z;
- double distance = sqrt(dx * dx + dy * dy + dz * dz);
- e -= (b->mass * b2->mass) / distance;
- }
- }
- return e;
-}
-
-void offset_momentum(int nbodies, struct planet * bodies)
-{
- double px = 0.0, py = 0.0, pz = 0.0;
- int i;
- for (i = 0; i < nbodies; i++) {
- px += bodies[i].vx * bodies[i].mass;
- py += bodies[i].vy * bodies[i].mass;
- pz += bodies[i].vz * bodies[i].mass;
- }
- bodies[0].vx = - px / solar_mass;
- bodies[0].vy = - py / solar_mass;
- bodies[0].vz = - pz / solar_mass;
-}
-
-#define NBODIES 5
-struct planet bodies[NBODIES] = {
- { /* sun */
- 0, 0, 0, 0, 0, 0, solar_mass
- },
- { /* jupiter */
- 4.84143144246472090e+00,
- -1.16032004402742839e+00,
- -1.03622044471123109e-01,
- 1.66007664274403694e-03 * days_per_year,
- 7.69901118419740425e-03 * days_per_year,
- -6.90460016972063023e-05 * days_per_year,
- 9.54791938424326609e-04 * solar_mass
- },
- { /* saturn */
- 8.34336671824457987e+00,
- 4.12479856412430479e+00,
- -4.03523417114321381e-01,
- -2.76742510726862411e-03 * days_per_year,
- 4.99852801234917238e-03 * days_per_year,
- 2.30417297573763929e-05 * days_per_year,
- 2.85885980666130812e-04 * solar_mass
- },
- { /* uranus */
- 1.28943695621391310e+01,
- -1.51111514016986312e+01,
- -2.23307578892655734e-01,
- 2.96460137564761618e-03 * days_per_year,
- 2.37847173959480950e-03 * days_per_year,
- -2.96589568540237556e-05 * days_per_year,
- 4.36624404335156298e-05 * solar_mass
- },
- { /* neptune */
- 1.53796971148509165e+01,
- -2.59193146099879641e+01,
- 1.79258772950371181e-01,
- 2.68067772490389322e-03 * days_per_year,
- 1.62824170038242295e-03 * days_per_year,
- -9.51592254519715870e-05 * days_per_year,
- 5.15138902046611451e-05 * solar_mass
- }
-};
-
-int main(int argc, char ** argv)
-{
- int n = atoi(argv[1]);
- int i;
-
- offset_momentum(NBODIES, bodies);
- printf ("%.9f\n", energy(NBODIES, bodies));
- for (i = 1; i <= n; i++)
- advance(NBODIES, bodies, 0.01);
- printf ("%.9f\n", energy(NBODIES, bodies));
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/nbody.go b/gcc/testsuite/go.test/test/bench/shootout/nbody.go
deleted file mode 100644
index 988f3ba..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/nbody.go
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Christoph Bauer
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "math"
-)
-
-var n = flag.Int("n", 1000, "number of iterations")
-
-type Body struct {
- x, y, z, vx, vy, vz, mass float64
-}
-
-const (
- solarMass = 4 * math.Pi * math.Pi
- daysPerYear = 365.24
-)
-
-func (b *Body) offsetMomentum(px, py, pz float64) {
- b.vx = -px / solarMass
- b.vy = -py / solarMass
- b.vz = -pz / solarMass
-}
-
-type System []*Body
-
-func NewSystem(body []Body) System {
- n := make(System, len(body))
- for i := 0; i < len(body); i++ {
- n[i] = new(Body) // copy to avoid overwriting the inputs
- *n[i] = body[i]
- }
- var px, py, pz float64
- for _, body := range n {
- px += body.vx * body.mass
- py += body.vy * body.mass
- pz += body.vz * body.mass
- }
- n[0].offsetMomentum(px, py, pz)
- return n
-}
-
-func (sys System) energy() float64 {
- var e float64
- for i, body := range sys {
- e += 0.5 * body.mass *
- (body.vx*body.vx + body.vy*body.vy + body.vz*body.vz)
- for j := i + 1; j < len(sys); j++ {
- body2 := sys[j]
- dx := body.x - body2.x
- dy := body.y - body2.y
- dz := body.z - body2.z
- distance := math.Sqrt(dx*dx + dy*dy + dz*dz)
- e -= (body.mass * body2.mass) / distance
- }
- }
- return e
-}
-
-func (sys System) advance(dt float64) {
- for i, body := range sys {
- for j := i + 1; j < len(sys); j++ {
- body2 := sys[j]
- dx := body.x - body2.x
- dy := body.y - body2.y
- dz := body.z - body2.z
-
- dSquared := dx*dx + dy*dy + dz*dz
- distance := math.Sqrt(dSquared)
- mag := dt / (dSquared * distance)
-
- body.vx -= dx * body2.mass * mag
- body.vy -= dy * body2.mass * mag
- body.vz -= dz * body2.mass * mag
-
- body2.vx += dx * body.mass * mag
- body2.vy += dy * body.mass * mag
- body2.vz += dz * body.mass * mag
- }
- }
-
- for _, body := range sys {
- body.x += dt * body.vx
- body.y += dt * body.vy
- body.z += dt * body.vz
- }
-}
-
-var (
- jupiter = Body{
- x: 4.84143144246472090e+00,
- y: -1.16032004402742839e+00,
- z: -1.03622044471123109e-01,
- vx: 1.66007664274403694e-03 * daysPerYear,
- vy: 7.69901118419740425e-03 * daysPerYear,
- vz: -6.90460016972063023e-05 * daysPerYear,
- mass: 9.54791938424326609e-04 * solarMass,
- }
- saturn = Body{
- x: 8.34336671824457987e+00,
- y: 4.12479856412430479e+00,
- z: -4.03523417114321381e-01,
- vx: -2.76742510726862411e-03 * daysPerYear,
- vy: 4.99852801234917238e-03 * daysPerYear,
- vz: 2.30417297573763929e-05 * daysPerYear,
- mass: 2.85885980666130812e-04 * solarMass,
- }
- uranus = Body{
- x: 1.28943695621391310e+01,
- y: -1.51111514016986312e+01,
- z: -2.23307578892655734e-01,
- vx: 2.96460137564761618e-03 * daysPerYear,
- vy: 2.37847173959480950e-03 * daysPerYear,
- vz: -2.96589568540237556e-05 * daysPerYear,
- mass: 4.36624404335156298e-05 * solarMass,
- }
- neptune = Body{
- x: 1.53796971148509165e+01,
- y: -2.59193146099879641e+01,
- z: 1.79258772950371181e-01,
- vx: 2.68067772490389322e-03 * daysPerYear,
- vy: 1.62824170038242295e-03 * daysPerYear,
- vz: -9.51592254519715870e-05 * daysPerYear,
- mass: 5.15138902046611451e-05 * solarMass,
- }
- sun = Body{
- mass: solarMass,
- }
-)
-
-func main() {
- flag.Parse()
-
- system := NewSystem([]Body{sun, jupiter, saturn, uranus, neptune})
- fmt.Printf("%.9f\n", system.energy())
- for i := 0; i < *n; i++ {
- system.advance(0.01)
- }
- fmt.Printf("%.9f\n", system.energy())
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/nbody.txt b/gcc/testsuite/go.test/test/bench/shootout/nbody.txt
deleted file mode 100644
index 1731557..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/nbody.txt
+++ /dev/null
@@ -1,2 +0,0 @@
--0.169075164
--0.169087605
diff --git a/gcc/testsuite/go.test/test/bench/shootout/pidigits.c b/gcc/testsuite/go.test/test/bench/shootout/pidigits.c
deleted file mode 100644
index c064da0..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/pidigits.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- http://shootout.alioth.debian.org/
-
- contributed by Paolo Bonzini & Sean Bartlett
- modified by Michael Mellor
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <gmp.h>
-
-static mpz_t numer, accum, denom, tmp1, tmp2;
-
-static int extract_digit()
-{
- if (mpz_cmp(numer, accum) > 0)
- return -1;
-
- /* Compute (numer * 3 + accum) / denom */
- mpz_mul_2exp(tmp1, numer, 1);
- mpz_add(tmp1, tmp1, numer);
- mpz_add(tmp1, tmp1, accum);
- mpz_fdiv_qr(tmp1, tmp2, tmp1, denom);
-
- /* Now, if (numer * 4 + accum) % denom... */
- mpz_add(tmp2, tmp2, numer);
-
- /* ... is normalized, then the two divisions have the same result. */
- if (mpz_cmp(tmp2, denom) >= 0)
- return -1;
-
- return mpz_get_ui(tmp1);
-}
-
-static void next_term(unsigned int k)
-{
- unsigned int y2 = k*2 + 1;
-
- mpz_mul_2exp(tmp1, numer, 1);
- mpz_add(accum, accum, tmp1);
- mpz_mul_ui(accum, accum, y2);
- mpz_mul_ui(numer, numer, k);
- mpz_mul_ui(denom, denom, y2);
-}
-
-static void eliminate_digit(unsigned int d)
-{
- mpz_submul_ui(accum, denom, d);
- mpz_mul_ui(accum, accum, 10);
- mpz_mul_ui(numer, numer, 10);
-}
-
-static void pidigits(unsigned int n)
-{
- int d;
- unsigned int i = 0, k = 0, m;
- mpz_init(tmp1);
- mpz_init(tmp2);
- mpz_init_set_ui(numer, 1);
- mpz_init_set_ui(accum, 0);
- mpz_init_set_ui(denom, 1);
-
- for(;;)
- {
- do {
- k++;
- next_term(k);
- d = extract_digit();
- } while(d == -1);
-
- putchar(d + '0');
-
- i++;
- m = i%10;
- if(m == 0)
- printf("\t:%d\n", i);
- if(i >= n)
- break;
- eliminate_digit(d);
- }
-
- if(m) {
- m = 10 - m;
- while(m--)
- putchar(' ');
- printf("\t:%d\n", n);
- }
-}
-
-int main(int argc, char **argv)
-{
- pidigits(argc > 1 ? atoi(argv[1]) : 27);
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/pidigits.go b/gcc/testsuite/go.test/test/bench/shootout/pidigits.go
deleted file mode 100644
index a0f21a9..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/pidigits.go
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on pidigits.c (by Paolo Bonzini & Sean Bartlett,
- * modified by Michael Mellor)
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "math/big"
-)
-
-var n = flag.Int("n", 27, "number of digits")
-var silent = flag.Bool("s", false, "don't print result")
-
-var (
- tmp1 = big.NewInt(0)
- tmp2 = big.NewInt(0)
- tmp3 = big.NewInt(0)
- y2 = big.NewInt(0)
- bigk = big.NewInt(0)
- numer = big.NewInt(1)
- accum = big.NewInt(0)
- denom = big.NewInt(1)
- ten = big.NewInt(10)
-)
-
-func extract_digit() int64 {
- if numer.Cmp(accum) > 0 {
- return -1
- }
-
- // Compute (numer * 3 + accum) / denom
- tmp1.Lsh(numer, 1)
- tmp1.Add(tmp1, numer)
- tmp1.Add(tmp1, accum)
- tmp1.DivMod(tmp1, denom, tmp2)
-
- // Now, if (numer * 4 + accum) % denom...
- tmp2.Add(tmp2, numer)
-
- // ... is normalized, then the two divisions have the same result.
- if tmp2.Cmp(denom) >= 0 {
- return -1
- }
-
- return tmp1.Int64()
-}
-
-func next_term(k int64) {
- y2.SetInt64(k*2 + 1)
- bigk.SetInt64(k)
-
- tmp1.Lsh(numer, 1)
- accum.Add(accum, tmp1)
- accum.Mul(accum, y2)
- numer.Mul(numer, bigk)
- denom.Mul(denom, y2)
-}
-
-func eliminate_digit(d int64) {
- tmp3.SetInt64(d)
- accum.Sub(accum, tmp3.Mul(denom, tmp3))
- accum.Mul(accum, ten)
- numer.Mul(numer, ten)
-}
-
-func printf(s string, arg ...interface{}) {
- if !*silent {
- fmt.Printf(s, arg...)
- }
-}
-
-func main() {
- flag.Parse()
-
- var m int // 0 <= m < 10
- for i, k := 0, int64(0); ; {
- d := int64(-1)
- for d < 0 {
- k++
- next_term(k)
- d = extract_digit()
- }
-
- printf("%c", d+'0')
-
- i++
- m = i % 10
- if m == 0 {
- printf("\t:%d\n", i)
- }
- if i >= *n {
- break
- }
- eliminate_digit(d)
- }
-
- if m > 0 {
- printf("%s\t:%d\n", " "[m:10], *n)
- }
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/pidigits.txt b/gcc/testsuite/go.test/test/bench/shootout/pidigits.txt
deleted file mode 100644
index ad946a9..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/pidigits.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-3141592653 :10
-5897932384 :20
-6264338 :27
diff --git a/gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.go b/gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.go
deleted file mode 100644
index 9c6d421..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.go
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "regexp"
- "runtime"
-)
-
-var variants = []string{
- "agggtaaa|tttaccct",
- "[cgt]gggtaaa|tttaccc[acg]",
- "a[act]ggtaaa|tttacc[agt]t",
- "ag[act]gtaaa|tttac[agt]ct",
- "agg[act]taaa|ttta[agt]cct",
- "aggg[acg]aaa|ttt[cgt]ccct",
- "agggt[cgt]aa|tt[acg]accct",
- "agggta[cgt]a|t[acg]taccct",
- "agggtaa[cgt]|[acg]ttaccct",
-}
-
-type Subst struct {
- pat, repl string
-}
-
-var substs = []Subst{
- Subst{"B", "(c|g|t)"},
- Subst{"D", "(a|g|t)"},
- Subst{"H", "(a|c|t)"},
- Subst{"K", "(g|t)"},
- Subst{"M", "(a|c)"},
- Subst{"N", "(a|c|g|t)"},
- Subst{"R", "(a|g)"},
- Subst{"S", "(c|g)"},
- Subst{"V", "(a|c|g)"},
- Subst{"W", "(a|t)"},
- Subst{"Y", "(c|t)"},
-}
-
-func countMatches(pat string, bytes []byte) int {
- re := regexp.MustCompile(pat)
- n := 0
- for {
- e := re.FindIndex(bytes)
- if e == nil {
- break
- }
- n++
- bytes = bytes[e[1]:]
- }
- return n
-}
-
-func main() {
- runtime.GOMAXPROCS(4)
- bytes, err := ioutil.ReadAll(os.Stdin)
- if err != nil {
- fmt.Fprintf(os.Stderr, "can't read input: %s\n", err)
- os.Exit(2)
- }
- ilen := len(bytes)
- // Delete the comment lines and newlines
- bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{})
- clen := len(bytes)
-
- mresults := make([]chan int, len(variants))
- for i, s := range variants {
- ch := make(chan int)
- mresults[i] = ch
- go func(ss string) {
- ch <- countMatches(ss, bytes)
- }(s)
- }
-
- lenresult := make(chan int)
- bb := bytes
- go func() {
- for _, sub := range substs {
- bb = regexp.MustCompile(sub.pat).ReplaceAll(bb, []byte(sub.repl))
- }
- lenresult <- len(bb)
- }()
-
- for i, s := range variants {
- fmt.Printf("%s %d\n", s, <-mresults[i])
- }
- fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, <-lenresult)
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.txt b/gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.txt
deleted file mode 100644
index e23e71f..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/regex-dna-parallel.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-agggtaaa|tttaccct 1
-[cgt]gggtaaa|tttaccc[acg] 0
-a[act]ggtaaa|tttacc[agt]t 0
-ag[act]gtaaa|tttac[agt]ct 0
-agg[act]taaa|ttta[agt]cct 1
-aggg[acg]aaa|ttt[cgt]ccct 0
-agggt[cgt]aa|tt[acg]accct 0
-agggta[cgt]a|t[acg]taccct 0
-agggtaa[cgt]|[acg]ttaccct 2
-
-10245
-10000
-13348
diff --git a/gcc/testsuite/go.test/test/bench/shootout/regex-dna.c b/gcc/testsuite/go.test/test/bench/shootout/regex-dna.c
deleted file mode 100644
index 134f821..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/regex-dna.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
-** The Computer Language Shootout
-** http://shootout.alioth.debian.org/
-** contributed by Mike Pall
-**
-** regex-dna benchmark using PCRE
-**
-** compile with:
-** gcc -O3 -fomit-frame-pointer -o regexdna regexdna.c -lpcre
-*/
-
-#define __USE_STRING_INLINES
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pcre.h>
-
-typedef struct fbuf {
- char *buf;
- size_t size, len;
-} fbuf_t;
-
-static void fb_init(fbuf_t *b)
-{
- b->buf = NULL;
- b->len = b->size = 0;
-}
-
-static char *fb_need(fbuf_t *b, size_t need)
-{
- need += b->len;
- if (need > b->size) {
- if (b->size == 0) b->size = need;
- else while (need > b->size) b->size += b->size;
- if (!(b->buf = realloc(b->buf, b->size))) exit(1);
- }
- return b->buf+b->len;
-}
-
-#define FB_MINREAD (3<<16)
-
-/* Read all of a stdio stream into dst buffer. */
-static size_t fb_readall(fbuf_t *dst, FILE *fp)
-{
- char *dp;
- int n;
- for (dp = fb_need(dst, FB_MINREAD);
- (n = fread(dp, 1, dst->size-dst->len, fp)) > 0;
- dp = fb_need(dst, FB_MINREAD)) dst->len += n;
- if (ferror(fp)) exit(1);
- return dst->len;
-}
-
-/* Substitute pattern p with replacement r, copying from src to dst buffer. */
-static size_t fb_subst(fbuf_t *dst, fbuf_t *src, const char *p, const char *r)
-{
- pcre *re;
- pcre_extra *re_ex;
- const char *re_e;
- char *dp;
- int re_eo, m[3], pos, rlen, clen;
- if (!(re = pcre_compile(p, PCRE_CASELESS, &re_e, &re_eo, NULL))) exit(1);
- re_ex = pcre_study(re, 0, &re_e);
- for (dst->len = 0, rlen = strlen(r), pos = 0;
- pcre_exec(re, re_ex, src->buf, src->len, pos, 0, m, 3) >= 0;
- pos = m[1]) {
- clen = m[0]-pos;
- dp = fb_need(dst, clen+rlen);
- dst->len += clen+rlen;
- memcpy(dp, src->buf+pos, clen);
- memcpy(dp+clen, r, rlen);
- }
- clen = src->len-pos;
- dp = fb_need(dst, clen);
- dst->len += clen;
- memcpy(dp, src->buf+pos, clen);
- return dst->len;
-}
-
-/* Count all matches with pattern p in src buffer. */
-static int fb_countmatches(fbuf_t *src, const char *p)
-{
- pcre *re;
- pcre_extra *re_ex;
- const char *re_e;
- int re_eo, m[3], pos, count;
- if (!(re = pcre_compile(p, PCRE_CASELESS, &re_e, &re_eo, NULL))) exit(1);
- re_ex = pcre_study(re, 0, &re_e);
- for (count = 0, pos = 0;
- pcre_exec(re, re_ex, src->buf, src->len, pos, 0, m, 3) >= 0;
- pos = m[1]) count++;
- return count;
-}
-
-static const char *variants[] = {
- "agggtaaa|tttaccct", "[cgt]gggtaaa|tttaccc[acg]",
- "a[act]ggtaaa|tttacc[agt]t", "ag[act]gtaaa|tttac[agt]ct",
- "agg[act]taaa|ttta[agt]cct", "aggg[acg]aaa|ttt[cgt]ccct",
- "agggt[cgt]aa|tt[acg]accct", "agggta[cgt]a|t[acg]taccct",
- "agggtaa[cgt]|[acg]ttaccct", NULL
-};
-
-static const char *subst[] = {
- "B", "(c|g|t)", "D", "(a|g|t)", "H", "(a|c|t)", "K", "(g|t)",
- "M", "(a|c)", "N", "(a|c|g|t)", "R", "(a|g)", "S", "(c|g)",
- "V", "(a|c|g)", "W", "(a|t)", "Y", "(c|t)", NULL
-};
-
-int main(int argc, char **argv)
-{
- fbuf_t seq[2];
- const char **pp;
- size_t ilen, clen, slen;
- int flip;
- fb_init(&seq[0]);
- fb_init(&seq[1]);
- ilen = fb_readall(&seq[0], stdin);
- clen = fb_subst(&seq[1], &seq[0], ">.*|\n", "");
- for (pp = variants; *pp; pp++)
- printf("%s %d\n", *pp, fb_countmatches(&seq[1], *pp));
- for (slen = 0, flip = 1, pp = subst; *pp; pp += 2, flip = 1-flip)
- slen = fb_subst(&seq[1-flip], &seq[flip], *pp, pp[1]);
- printf("\n%zu\n%zu\n%zu\n", ilen, clen, slen);
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/regex-dna.go b/gcc/testsuite/go.test/test/bench/shootout/regex-dna.go
deleted file mode 100644
index 042d7f2..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/regex-dna.go
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "regexp"
-)
-
-var variants = []string{
- "agggtaaa|tttaccct",
- "[cgt]gggtaaa|tttaccc[acg]",
- "a[act]ggtaaa|tttacc[agt]t",
- "ag[act]gtaaa|tttac[agt]ct",
- "agg[act]taaa|ttta[agt]cct",
- "aggg[acg]aaa|ttt[cgt]ccct",
- "agggt[cgt]aa|tt[acg]accct",
- "agggta[cgt]a|t[acg]taccct",
- "agggtaa[cgt]|[acg]ttaccct",
-}
-
-type Subst struct {
- pat, repl string
-}
-
-var substs = []Subst{
- Subst{"B", "(c|g|t)"},
- Subst{"D", "(a|g|t)"},
- Subst{"H", "(a|c|t)"},
- Subst{"K", "(g|t)"},
- Subst{"M", "(a|c)"},
- Subst{"N", "(a|c|g|t)"},
- Subst{"R", "(a|g)"},
- Subst{"S", "(c|g)"},
- Subst{"V", "(a|c|g)"},
- Subst{"W", "(a|t)"},
- Subst{"Y", "(c|t)"},
-}
-
-func countMatches(pat string, bytes []byte) int {
- re := regexp.MustCompile(pat)
- n := 0
- for {
- e := re.FindIndex(bytes)
- if len(e) == 0 {
- break
- }
- n++
- bytes = bytes[e[1]:]
- }
- return n
-}
-
-func main() {
- bytes, err := ioutil.ReadAll(os.Stdin)
- if err != nil {
- fmt.Fprintf(os.Stderr, "can't read input: %s\n", err)
- os.Exit(2)
- }
- ilen := len(bytes)
- // Delete the comment lines and newlines
- bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{})
- clen := len(bytes)
- for _, s := range variants {
- fmt.Printf("%s %d\n", s, countMatches(s, bytes))
- }
- for _, sub := range substs {
- bytes = regexp.MustCompile(sub.pat).ReplaceAll(bytes, []byte(sub.repl))
- }
- fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, len(bytes))
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/regex-dna.txt b/gcc/testsuite/go.test/test/bench/shootout/regex-dna.txt
deleted file mode 100644
index e23e71f..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/regex-dna.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-agggtaaa|tttaccct 1
-[cgt]gggtaaa|tttaccc[acg] 0
-a[act]ggtaaa|tttacc[agt]t 0
-ag[act]gtaaa|tttac[agt]ct 0
-agg[act]taaa|ttta[agt]cct 1
-aggg[acg]aaa|ttt[cgt]ccct 0
-agggt[cgt]aa|tt[acg]accct 0
-agggta[cgt]a|t[acg]taccct 0
-agggtaa[cgt]|[acg]ttaccct 2
-
-10245
-10000
-13348
diff --git a/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.c b/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.c
deleted file mode 100644
index b34c846..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org
- *
- * contributed by Bob W
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define JBFSIZE 82 // line input buffer size
-#define QBFSIZE 5200 // output buffer initial size
-#define Z16 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-#define V32 "\0TVGH\0\0CD\0\0M\0KN\0\0\0YSA\0BW\0R\0\0\0\0\0\0"
-#define VALL Z16 Z16 Z16 Z16 V32 V32 Z16 Z16 Z16 Z16 Z16 Z16 Z16 Z16
-
-int errex(char *s, int n) { // error message+value, return 1
- fprintf(stderr,"\n*** Error: %s [%d]!\n", s, n);
- return 1;
-}
-
-int main () { // ***** main *****
- char *pj, *pq, *pr; // buffer pointers: inp,out,/out
- char *jjj = malloc(JBFSIZE); // allocate input line buffer
- char *qqq = malloc(QBFSIZE); // output buffer (dyn. size)
- char *pqstop = qqq+QBFSIZE; // end-of-buffer pointer
- char xtab[256] = VALL; // char conversion table
-
- if (!jjj || !qqq)
- return errex("Buffer allocation", !jjj + !qqq);
- pj = fgets(jjj,JBFSIZE,stdin); // fetch 1st line
- if (!pj)
- return errex("No input data",0);
- if (*jjj != '>')
- return errex("1st char not '>'", 0);
-
- while (pj) { // MAIN LOOP: process data
- fputs(jjj, stdout); // output ID line
-
- for (pq=qqq+1, pr=pqstop; ; pq++) { // LOOP: fill output buffer
- pj = fgets(jjj, JBFSIZE, stdin); // get line from stdin
- if (!pj || (*jjj=='>')) break; // EOF or new ID line
- if (pr <= (pq+61)) { // need to resize buffer
- char *newstop = pqstop + 12777888;
- char *newptr = realloc(qqq, newstop-qqq);
- if (!newptr)
- return errex("Out of memory", 0);
- if (newptr != qqq) { // new base: adj. pointers
- size_t x = newptr-qqq; // offset for pointer update
- pq+=x; pr+=x; qqq+=x;
- newstop+=x; pqstop+=x;
- }
- pr = __builtin_memmove(newstop-(pqstop-pr), pr, pqstop-pr);
- pqstop = newstop; // buffer resize complete
- }
- while (*pj) { // LOOP: conv. & revert line
- char c = xtab[(unsigned char)(*pj++)];
- if (c) // conversion valid
- *(--pr) = c;
- }
- }
-
- for (pq = qqq; pr<pqstop; ) { // LOOP: format output
- size_t x = (pqstop-pr)<60 ? pqstop-pr : 60;
- __builtin_memmove(pq,pr,x); // move line to free space
- pr+=x; pq+=x; *(pq++) = 0xA; // adjust pointers, add LF
- }
- fwrite(qqq, 1, pq-qqq, stdout); // output converted data
- }
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.go b/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.go
deleted file mode 100644
index baa30ff..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.go
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "bufio"
- "os"
-)
-
-const lineSize = 60
-
-var complement = [256]uint8{
- 'A': 'T', 'a': 'T',
- 'C': 'G', 'c': 'G',
- 'G': 'C', 'g': 'C',
- 'T': 'A', 't': 'A',
- 'U': 'A', 'u': 'A',
- 'M': 'K', 'm': 'K',
- 'R': 'Y', 'r': 'Y',
- 'W': 'W', 'w': 'W',
- 'S': 'S', 's': 'S',
- 'Y': 'R', 'y': 'R',
- 'K': 'M', 'k': 'M',
- 'V': 'B', 'v': 'B',
- 'H': 'D', 'h': 'D',
- 'D': 'H', 'd': 'H',
- 'B': 'V', 'b': 'V',
- 'N': 'N', 'n': 'N',
-}
-
-func main() {
- in := bufio.NewReader(os.Stdin)
- buf := make([]byte, 1024*1024)
- line, err := in.ReadSlice('\n')
- for err == nil {
- os.Stdout.Write(line)
-
- // Accumulate reversed complement in buf[w:]
- nchar := 0
- w := len(buf)
- for {
- line, err = in.ReadSlice('\n')
- if err != nil || line[0] == '>' {
- break
- }
- line = line[0 : len(line)-1]
- nchar += len(line)
- if len(line)+nchar/60+128 >= w {
- nbuf := make([]byte, len(buf)*5)
- copy(nbuf[len(nbuf)-len(buf):], buf)
- w += len(nbuf) - len(buf)
- buf = nbuf
- }
-
- // This loop is the bottleneck.
- for _, c := range line {
- w--
- buf[w] = complement[c]
- }
- }
-
- // Copy down to beginning of buffer, inserting newlines.
- // The loop left room for the newlines and 128 bytes of padding.
- i := 0
- for j := w; j < len(buf); j += 60 {
- n := copy(buf[i:i+60], buf[j:])
- buf[i+n] = '\n'
- i += n + 1
- }
- os.Stdout.Write(buf[0:i])
- }
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.txt b/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.txt
deleted file mode 100644
index 14d792a..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/reverse-complement.txt
+++ /dev/null
@@ -1,171 +0,0 @@
->ONE Homo sapiens alu
-CGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAAC
-CTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACA
-GGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCAT
-GTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAA
-AGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTC
-TGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGG
-GTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACC
-ACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTG
-GTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTA
-CAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCT
-GGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTC
-TCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCCCGGCTAAT
-TTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTCGAACTCCT
-GACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCA
-CCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGC
-GCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCC
-TCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTA
-GTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGAT
-CCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCT
-TTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTC
-ACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTG
-GGATTACAGGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGT
-TTCACCATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGG
-CCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAG
-TCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCG
-CCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGC
-GCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGG
-CCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGC
-TGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCG
-CCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCA
-AGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCC
-CGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTC
-GAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGC
-GTGAGCCACCGCGCCCGGCC
->TWO IUB ambiguity codes
-TAGGDHACHATCRGTRGVTGAGWTATGYTGCTGTCABACDWVTRTAAGAVVAGATTTNDA
-GASMTCTGCATBYTTCAAKTTACMTATTACTTCATARGGYACMRTGTTTTYTATACVAAT
-TTCTAKGDACKADACTATATNTANTCGTTCACGBCGYSCBHTANGGTGATCGTAAAGTAA
-CTATBAAAAGATSTGWATBCSGAKHTTABBAACGTSYCATGCAAVATKTSKTASCGGAAT
-WVATTTNTCCTTCTTCTTDDAGTGGTTGGATACVGTTAYMTMTBTACTTTHAGCTAGBAA
-AAGAGKAAGTTRATWATCAGATTMDDTTTAAAVAAATATTKTCYTAAATTVCNKTTRACG
-ADTATATTTATGATSADSCAATAWAGCGRTAGTGTAAGTGACVGRADYGTGCTACHVSDT
-CTVCARCSYTTAATATARAAAATTTAATTTACDAATTGBACAGTAYAABATBTGCAGBVG
-TGATGGDCAAAATBNMSTTABKATTGGSTCCTAGBTTACTTGTTTAGTTTATHCGATSTA
-AAGTCGAKAAASTGTTTTAWAKCAGATATACTTTTMTTTTGBATAGAGGAGCMATGATRA
-AAGGNCAYDCCDDGAAAGTHGBTAATCKYTBTACBGTBCTTTTTGDTAASSWTAAWAARA
-TTGGCTAAGWGRADTYACATAGCTCBTAGATAWAGCAATNGTATMATGTTKMMAGTAWTC
-CCNTSGAAWATWCAAAAMACTGAADNTYGATNAATCCGAYWNCTAACGTTAGAGDTTTTC
-ATCTGGKRTAVGAABVCTGWGBTCTDVGKATTBTCTAAGGVADAAAVWTCTAGGGGAGGG
-TTAGAACAATTAAHTAATNAAATGCATKATCTAAYRTDTCAGSAYTTYHGATRTTWAVTA
-BGNTCDACAGBCCRCAGWCRTCABTGMMAWGMCTCAACCGATRTGBCAVAATCGTDWDAA
-CAYAWAATWCTGGTAHCCCTAAGATAACSCTTAGTGSAACAWTBGTCDTTDGACWDBAAC
-HTTTNGSKTYYAAYGGATNTGATTTAARTTAMBAATCTAAGTBTCATYTAACTTADTGTT
-TCGATACGAAHGGCYATATACCWDTKYATDCSHTDTCAAAATGTGBACTGSCCVGATGTA
-TCMMAGCCTTDAAABAATGAAGAGTAACTHATMGVTTAATAACCCGGTTVSANTGCAATT
-GTGAGATTTAMGTTTAMAAYGCTGACAYAAAAAGGCACAMYTAAGVGGCTGGAABVTACG
-GATTSTYGTBVAKTATWACCGTGTKAGTDTGTATGTTTAAAGGAAAAAGTAACATARAAA
-GGTYCAMNYAAABTATAGNTSATANAGTCATCCTATWADKAACTRGTMSACDGTATSAYT
-AAHSHGTAABYGACTYTATADTGSTATAGAGAAATCGNTAAAGGAAATCAGTTGTNCYMV
-TNACDRTATBNATATASTAGAAMSCGGGANRCKKMCAAACATTNAGTCTRMAATBMTACC
-CGTACTTCTBGDSYAATWGAAAATGACADDCHAKAAAYATATTKTTTTCACANACWAGAA
-AKATCCTTATTAYKHKCTAAACARTATTTTDATBTVWCYGCAATACTAGGKAAASTTDGA
-MGGCHTTHAATVCAHDRYAGGRCTATACGTCMAGAGAGCTBTHGNACARTCCBDCTAAGA
-GCGGCTTTARTAAAGAATCCNAGTAWBTGACTTGAATTACWTVACAGAAABCAATNAAAC
-CGTNTRANTTGAYCMAWBADTANABRGGTKTHTWTAGTTVCTMBKTAGMTVKCCAGCANT
-TVAGSWTTAGCCGCRHTTTCCTTHNTATTAAGAAGAATAGGMTRAARTCTABGTACDTTT
-TATAAVDHAHTATAGATCCTAGTAAGYTWATDWCATGAGGGATAGTAAMDMNGBASTWAM
-TSTATRBAYDABATGTATATYCGCACTGTTTTAACMCWBTATAWAGTATBTSTATVTTAR
-CCTMTTAAKADATCAACTAATYTSVTAKGDATTATGCKTCAYCAKAATACTTKAANGAGT
-ATTSDAGATCGGAAATACTTAAYAAVGTATMCGCTTGTGTDCTAATYTATTTTATTTWAA
-CAGWRCTATGTAGMTGTTTGTTYKTNGTTKTCAGAACNTRACCTACKTGSRATGTGGGGG
-CTGTCATTAAGTAAATNGSTTABCCCCTCGCAGCTCWHTCGCGAAGCAVATGCKACGHCA
-ACAKTTAATAACASAAADATTWNYTGTAATTGTTCGTMHACHTWATGTGCWTTTTGAAHY
-ACTTTGTAYAMSAAACTTAADAAATATAGTABMATATYAATGSGGTAGTTTGTGTBYGGT
-TWSGSVGWMATTDMTCCWWCABTCSVACAGBAATGTTKATBGTCAATAATCTTCTTAAAC
-ARVAATHAGYBWCTRWCABGTWWAATCTAAGTCASTAAAKTAAGVKBAATTBGABACGTA
-AGGTTAAATAAAAACTRMDTWBCTTTTTAATAAAAGATMGCCTACKAKNTBAGYRASTGT
-ASSTCGTHCGAAKTTATTATATTYTTTGTAGAACATGTCAAAACTWTWTHGKTCCYAATA
-AAGTGGAYTMCYTAARCSTAAATWAKTGAATTTRAGTCTSSATACGACWAKAASATDAAA
-TGYYACTSAACAAHAKTSHYARGASTATTATTHAGGYGGASTTTBGAKGATSANAACACD
-TRGSTTRAAAAAAAACAAGARTCVTAGTAAGATAWATGVHAAKATWGAAAAGTYAHVTAC
-TCTGRTGTCAWGATRVAAKTCGCAAVCGASWGGTTRTCSAMCCTAACASGWKKAWDAATG
-ACRCBACTATGTGTCTTCAAAHGSCTATATTTCGTVWAGAAGTAYCKGARAKSGKAGTAN
-TTTCYACATWATGTCTAAAADMDTWCAATSTKDACAMAADADBSAAATAGGCTHAHAGTA
-CGACVGAATTATAAAGAHCCVAYHGHTTTACATSTTTATGNCCMTAGCATATGATAVAAG
->THREE Homo sapiens frequency
-ATATTTATCTTTTCACTTCCTACATTGGTCAGACCATTATTCGACACGTGGCGTCATTTT
-GTCATACCGGGTAATGTTGGAAACAAAACGTACTGATAAAATACTGAGTTGTAAACTCTA
-ATCAGATAACGCGCTTGGATATTAAGATTCACACAGGGGTTTCGGCTGTAAAAAAACTTG
-TGGAGCTGTTCTGGGACAGATAAGTTGTACCTCGTACTTAGCTAATTAATGAACCAACTG
-ATTACGATAGAACAATTCTGAGGCCGCCAGGACAGCCAAATTTTAATCTTATAAAGCTGG
-AAACAGCCGGTATTAGCTTCTCGCATACTTTGCCTGCATTGGTACCTTACAGATATCAGC
-GTAGTCATATACACCTCGGTCTCAGCTAAGCTTGTATCTCTTAGAGTAGTTCAAAGATAG
-TGGACAATACCTGTGGAATCGATTGCAGATATGGATTTATTTAACTACTGAGTCTCATTC
-ACAAGCTAAGCAAGGAGCACGTTTTGGTGCCGGCATACCGATTTGCTATCATGTCAGCAA
-ATTTGCGTTGTATTCCTAGTTGCACCCATTAAGGCCACACTCCGAACCTAATTATTACAT
-CGCAAAGACATGTACGAAGGACCCGATGTCGAATAGAAGGGAGGACTGTTCATTGGAAGC
-TAGACCAGAGGAATCGCAAAGATGCAACTCTTACAATAAAAATCTAATTTCAGTCAACAC
-GCAATTTCTATAAGGTTTCCGATAATAATGAACCGTCTTCCACAGGGGAATTTGCCATGC
-TCGTAAAAGTAGTTAATCCAAGTAGAAGAAATTTTGATAATGTTTTAAGTTGGCACGAAG
-GAATTCAGAGAGATCTTACCTAACAAAGGCATTAGTAGATGTTCCTTGGTTCACACTCGG
-TCAATCAGAGCACATACTACGGGCGATACCGGGAATGACACAACATCAATGAGATTGTTA
-AGTGAGGTAATTGACTTTAGAGGACTCGATCAGTATACTGTCACTATGAACATCGTATTA
-ATTGTTATCCGATATATACACCACCGATTTGCTTGTGCAAGGTTACAGACCCATTCGATA
-AATACAAACACGGAGCGATATTATTTAAGGAGTGCTGTCTTCAAAAGAATTATTCCCACA
-CCGACATAAGAACTTCGCTCCGTCATTCCAGATTTAAATAACATAACGTAACGCTTTGCT
-GATAACATAACATAACCGAGAATTTGCTTAGGAAATTTGGAGCAATATTGCATTGTTTCT
-CAGTCATCACAAGGCCCGCCAAAGAACTCTGAGAATCAGGATTCAACATGATTGGTAAGA
-CTCTATATATATAACTTAATTCTTGTGTCCGGAGATAGAAAGAGGACGAGAGATACTACG
-AAAGAAAGTGTACTTCGATGTATCAATTCAGACGCCTTCTCTATCATCAACATTATAGGT
-CTCGTATATGCTCGGCGCGATCTGCTTCTCTCCGCCAATAGCCCCATAGTGTATTTCAAG
-CGCAGTAACAGTGAAATCGTTACGAAGGTAGGGATGTTGCTTATAATTGTCGTAACTTAT
-CGCTTATGTATCTTTCAAGAATGAACGGCAGCATATACATACGTTCTACCTTTAGCTACA
-AAGCATCCATATACTCCCTCTCATGATTGAAACTCTTCCCTATTTTGTAGCCAATAGTGA
-AAGCGTATTAGTATAAATTCGTCGGTTTTTCACTCGCAACTGTTATACTCTGCAAACAAA
-CGAAAGCCTCATAGTACAAACCTAAAGCTACATACTTCATCATTGGCAGACCAGTGGCGG
-TATTTCTACGGAAGCATCACTATAGATATAAAGTTTCCCTTCATGTACGTCTGTTAACCA
-TATCACAAGAAACTGCTATCTCTGTCACGTAACAATTCACGCGCCTTATCGCCAAATGTT
-CATATATGCGCGGTATACGTATGAACGAATACTAATTAGTATAACGGAGGATTCACGGGA
-GGGATACTTGGGGCATTTATAAATCGTCTAAAAATTTTCTATCAGCACTTGCGGGTTATA
-GTGGATTACTAGGCAACATAATATTCTGTATTGGTCCAAATGACGCTATAGATAAATTAG
-CAAAATACATTGTTTCCATTTATGTAAGTCGAAACTCCAGGACTCCCGGGAACCAGTTAA
-ACCGTCTGGAAAAGACACATTGTGAGCGGGACTTCAATGATAGCTTTCAATGAGCTTCTC
-ATGCTTGGGGTCTGTACATATATGTTGGCGAAATTATCGTCTGTATTCTGTTATGCTTTG
-ATCATGGGTTATTAGTATAGTGTCCGGTTAAGTACCAATACCGCTAGAGACCCGACCTAA
-GTCGATAACTAACGATCATCGACGTAAGGATCGTCTCGATCAGTACTTCAGTCTAGATCT
-GGGAATAGTAACTCGTTAGTGAACTATGTCGTGTCATAACTCTAAAATGCAATCAAATCT
-TATTATTGAGTATTGATTATATAAAGCATCCGCTTAGCTTTACCCTCAAATGTTATATGC
-AATTTAAAGCGCTTGATATCGTCTACTCAAGTTCAGGTTTCACATGGCCGCAACGTGACG
-TTATTAGAGGTGGGTCATCATCTCTGAGGCTAGTGATGTTGAATACTCATTGAATGGGAA
-GTGGAATACCATGCTCGTAGGTAACAGCATGACCTATAAAATATACTATGGGTGTGTGGT
-AGATCAATATTGTTCAAGCATATCGTAACAATAACGGCTGAAATGTTACTGACATGAAAG
-AGGGAGTCCAAACCATTCTAACAGCTGATCAAGTCGTCTAAAAACGCCTGGTTCAGCCTT
-AAGAGTTATAAGCCAGACAAATTGTATCAATAGAGAATCCGTAAATTCCTCGGCCAACCT
-CTTGCAAAGACATCACTATCAATATACTACCGTGATCTTAATTAGTGAACTTATATAAAT
-ATCTACAACCAGATTCAACGGAAAAGCTTTAGTGGATTAGAAATTGCCAAGAATCACATT
-CATGTGGGTTCGAATGCTTTAGTAATACCATTTCGCCGAGTAGTCACTTCGCTGAACTGT
-CGTAAATTGCTATGACATAATCGAAAAGGATTGTCAAGAGTCGATTACTGCGGACTAATA
-ATCCCCACGGGGGTGGTCTCATGTCTCCCCAGGCGAGTGGGGACGGTTGATAAACACGCT
-GCATCGCGGACTGATGTTCCCAGTATTACATAGTCACATTGGATTGCGAGTAGTCTACCT
-ATTTATGAGCGAGAGATGCCTCTAACTACTTCGACTTTTAAAACCTTTCCACGCCAGTAT
-TCGGCGAAAGGGAAGTATTAAGGGTTGTCATAATTAAGCTGATACCACTTCAGACTTTGC
-TCTACTTCTGTCTTTCATTGGTTTAGTAAAGTCTGTCCATTCGTCGAGACCGTCTTTTGC
-AGCCTCATTCTACCAACTGCTCCGACTCTTAGTCTGCTTCTCCCAGCGTTATAACAAGAG
-GCATTTTGTCATCCTTAAAACAATAATAAAGAACTCGGAGCACTGATATAATGACTGAAT
-TAGAACCGCTTAAAAATACAACGAATAGATAAGACTATCGGATAAGATCTAATATGTAGT
-GATTAAGCCCTTTATTAATTAATAATAGTTACCCTTTCTGATGTAACGCGACATATTACG
-ATTTAGTGGCACGTCTGAATTGCAAAGCAGATCTCTACCCGATTTTTATTATAAATCCCG
-TATACATCTTGACTTGAGTAATTGTTCATCTTTTTATATCTCTTCGTACTACAAATAATT
-AATATCTCAACCCGTATTGTGTGATTCTAATTACCAACAGAATACGAGGAGGTTTTTGCT
-TAGGGCCATATATAATGAATCTATCTCGTTTATTCGCGGAACCCGAGATAACATTACGAT
-GTAACTATTTTAGAGAACTTAATACAAGAAACATTGCTGATTACTCATAACTAAATGCTT
-GGTAATATATCCTCAGTGCCCCTACCATCTTTTACGCAGGGATGTAATTACTTAGGATTC
-ATTGTGTAAGAATTACAATGAACGATGGATATGAAGGCATGTTGCGAGGTGTTCCTTGGT
-ATGTGAAGTTCGCAGGGCAACAAAAATTTCGCAGAATAGGCCTCAAAGTATTGGTAAAGA
-AGACAACTAATCATCACGAGCTTCTGATATCAATACGAACGAGTCCTGTGATGGATGAAA
-GAAAGTCGTATCGAAAATGTCAAGAGTCTGCCCAATGTAACTTACTTCAAAAAATAACGC
-TTCCGCCAAGTACGTTCGAATAAACGTAATTTTAAAAATACATAAGGGGTGTTAGAAAGT
-AAGCGACGGGATATAAGTTAGACTCAAGATTCCGCCGTAAAACGAGACTGATTCCGAAGA
-TTGTTCGTGGATCTGGTCATGACTTTCACTGAGTAAGGAGTTTCGACATATGTCAATAAA
-CACAAAAATAGAAGCTATTCGATCTGAAAAATATTAGGACAAGAAACTATCTCACGCTAG
-CCCAGAATATTCACTCACCCACGGGCGATACTAAAGCACTATATAGTCGCGTGATTACTA
-TACATATGGTACACATAAGAATCACGATCAGGTTCTCAATTTTCAACAATATATGTTTAT
-TTGCATAGGTAATATTAGGCCTTTAAGAGAAGGATGGGTGAGATACTCCGGGGATGGCGG
-CAATAAAGAAAAACACGATATGAGTAATAGGATCCTAATATCTTGGCGAGAGACTTAAGG
-TACGAATTTTGCGCAATCTATTTTTTACTTGGCCAGAATTCATGTATGGTATAAGTACGA
-ACTTTTTTGATCACTTTCATGGCTACCTGATTAGGATAGTTTGAGGAATTTCCCAAATAT
-ACCGATTTAATATACACTAGGGCTTGTCACTTTGAGTCAGAAAAAGAATATAATTACTTA
-GGGTAATGCTGCATACATATTCTTATATTGCAAAGGTTCTCTGGGTAATCTTGAGCCTTC
-ACGATACCTGGTGAAGTGTT
diff --git a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm-parallel.go b/gcc/testsuite/go.test/test/bench/shootout/spectral-norm-parallel.go
deleted file mode 100644
index 2706f39..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm-parallel.go
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on spectral-norm.c by Sebastien Loisel
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "math"
- "runtime"
-)
-
-var n = flag.Int("n", 2000, "count")
-var nCPU = flag.Int("ncpu", 4, "number of cpus")
-
-func evalA(i, j int) float64 { return 1 / float64(((i+j)*(i+j+1)/2 + i + 1)) }
-
-type Vec []float64
-
-func (v Vec) Times(i, n int, u Vec, c chan int) {
- for ; i < n; i++ {
- v[i] = 0
- for j := 0; j < len(u); j++ {
- v[i] += evalA(i, j) * u[j]
- }
- }
- c <- 1
-}
-
-func (v Vec) TimesTransp(i, n int, u Vec, c chan int) {
- for ; i < n; i++ {
- v[i] = 0
- for j := 0; j < len(u); j++ {
- v[i] += evalA(j, i) * u[j]
- }
- }
- c <- 1
-}
-
-func wait(c chan int) {
- for i := 0; i < *nCPU; i++ {
- <-c
- }
-}
-
-func (v Vec) ATimesTransp(u Vec) {
- x := make(Vec, len(u))
- c := make(chan int, *nCPU)
- for i := 0; i < *nCPU; i++ {
- go x.Times(i*len(v) / *nCPU, (i+1)*len(v) / *nCPU, u, c)
- }
- wait(c)
- for i := 0; i < *nCPU; i++ {
- go v.TimesTransp(i*len(v) / *nCPU, (i+1)*len(v) / *nCPU, x, c)
- }
- wait(c)
-}
-
-func main() {
- flag.Parse()
- runtime.GOMAXPROCS(*nCPU)
- N := *n
- u := make(Vec, N)
- for i := 0; i < N; i++ {
- u[i] = 1
- }
- v := make(Vec, N)
- for i := 0; i < 10; i++ {
- v.ATimesTransp(u)
- u.ATimesTransp(v)
- }
- var vBv, vv float64
- for i := 0; i < N; i++ {
- vBv += u[i] * v[i]
- vv += v[i] * v[i]
- }
- fmt.Printf("%0.9f\n", math.Sqrt(vBv/vv))
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.c b/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.c
deleted file mode 100644
index 832eb3d..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* -*- mode: c -*-
- *
- * The Great Computer Language Shootout
- * http://shootout.alioth.debian.org/
- *
- * Contributed by Sebastien Loisel
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-double eval_A(int i, int j) { return 1.0/((i+j)*(i+j+1)/2+i+1); }
-
-void eval_A_times_u(int N, const double u[], double Au[])
-{
- int i,j;
- for(i=0;i<N;i++)
- {
- Au[i]=0;
- for(j=0;j<N;j++) Au[i]+=eval_A(i,j)*u[j];
- }
-}
-
-void eval_At_times_u(int N, const double u[], double Au[])
-{
- int i,j;
- for(i=0;i<N;i++)
- {
- Au[i]=0;
- for(j=0;j<N;j++) Au[i]+=eval_A(j,i)*u[j];
- }
-}
-
-void eval_AtA_times_u(int N, const double u[], double AtAu[])
-{ double v[N]; eval_A_times_u(N,u,v); eval_At_times_u(N,v,AtAu); }
-
-int main(int argc, char *argv[])
-{
- int i;
- int N = ((argc == 2) ? atoi(argv[1]) : 2000);
- double u[N],v[N],vBv,vv;
- for(i=0;i<N;i++) u[i]=1;
- for(i=0;i<10;i++)
- {
- eval_AtA_times_u(N,u,v);
- eval_AtA_times_u(N,v,u);
- }
- vBv=vv=0;
- for(i=0;i<N;i++) { vBv+=u[i]*v[i]; vv+=v[i]*v[i]; }
- printf("%0.9f\n",sqrt(vBv/vv));
- return 0;
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.go b/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.go
deleted file mode 100644
index 6667f3e..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.go
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on spectral-norm.c by Sebastien Loisel
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "math"
-)
-
-var n = flag.Int("n", 2000, "count")
-
-func evalA(i, j int) float64 { return 1 / float64(((i+j)*(i+j+1)/2 + i + 1)) }
-
-type Vec []float64
-
-func (v Vec) Times(u Vec) {
- for i := 0; i < len(v); i++ {
- v[i] = 0
- for j := 0; j < len(u); j++ {
- v[i] += evalA(i, j) * u[j]
- }
- }
-}
-
-func (v Vec) TimesTransp(u Vec) {
- for i := 0; i < len(v); i++ {
- v[i] = 0
- for j := 0; j < len(u); j++ {
- v[i] += evalA(j, i) * u[j]
- }
- }
-}
-
-func (v Vec) ATimesTransp(u Vec) {
- x := make(Vec, len(u))
- x.Times(u)
- v.TimesTransp(x)
-}
-
-func main() {
- flag.Parse()
- N := *n
- u := make(Vec, N)
- for i := 0; i < N; i++ {
- u[i] = 1
- }
- v := make(Vec, N)
- for i := 0; i < 10; i++ {
- v.ATimesTransp(u)
- u.ATimesTransp(v)
- }
- var vBv, vv float64
- for i := 0; i < N; i++ {
- vBv += u[i] * v[i]
- vv += v[i] * v[i]
- }
- fmt.Printf("%0.9f\n", math.Sqrt(vBv/vv))
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.txt b/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.txt
deleted file mode 100644
index b988598..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/spectral-norm.txt
+++ /dev/null
@@ -1 +0,0 @@
-1.274224152
diff --git a/gcc/testsuite/go.test/test/bench/shootout/threadring.c b/gcc/testsuite/go.test/test/bench/shootout/threadring.c
deleted file mode 100644
index a518134..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/threadring.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
-* The Computer Language Benchmarks Game
-* http://shootout.alioth.debian.org/
-
-* contributed by Premysl Hruby
-*/
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <string.h>
-#include <limits.h>
-
-#define THREADS (503)
-
-
-struct stack {
- char x[PTHREAD_STACK_MIN];
-};
-
-
-/* staticaly initialize mutex[0] mutex */
-static pthread_mutex_t mutex[THREADS];
-static int data[THREADS];
-static struct stack stacks[THREADS];
-/* stacks must be defined staticaly, or my i386 box run of virtual memory for this
- * process while creating thread +- #400 */
-
-static void* thread(void *num)
-{
- int l = (int)(uintptr_t)num;
- int r = (l+1) % THREADS;
- int token;
-
- while(1) {
- pthread_mutex_lock(mutex + l);
- token = data[l];
- if (token) {
- data[r] = token - 1;
- pthread_mutex_unlock(mutex + r);
- }
- else {
- printf("%i\n", l+1);
- exit(0);
- }
- }
-}
-
-
-
-int main(int argc, char **argv)
-{
- int i;
- pthread_t cthread;
- pthread_attr_t stack_attr;
-
- if (argc != 2)
- exit(255);
- data[0] = atoi(argv[1]);
-
- pthread_attr_init(&stack_attr);
-
- for (i = 0; i < THREADS; i++) {
- pthread_mutex_init(mutex + i, NULL);
- pthread_mutex_lock(mutex + i);
-
- pthread_attr_setstack(&stack_attr, &stacks[i], sizeof(struct stack));
- pthread_create(&cthread, &stack_attr, thread, (void*)(uintptr_t)i);
- }
-
- pthread_mutex_unlock(mutex + 0);
- pthread_join(cthread, NULL);
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/threadring.go b/gcc/testsuite/go.test/test/bench/shootout/threadring.go
deleted file mode 100644
index e76dd0b..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/threadring.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of "The Computer Language Benchmarks Game" nor the
- name of "The Computer Language Shootout Benchmarks" nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
- "flag"
- "fmt"
- "os"
-)
-
-var n = flag.Int("n", 1000, "how many passes")
-
-const Nthread = 503
-
-func f(i int, in <-chan int, out chan<- int) {
- for {
- n := <-in
- if n == 0 {
- fmt.Printf("%d\n", i)
- os.Exit(0)
- }
- out <- n - 1
- }
-}
-
-func main() {
- flag.Parse()
-
- one := make(chan int) // will be input to thread 1
- var in, out chan int = nil, one
- for i := 1; i <= Nthread-1; i++ {
- in, out = out, make(chan int)
- go f(i, in, out)
- }
- go f(Nthread, out, one)
- one <- *n
- <-make(chan int) // hang until ring completes
-}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/threadring.txt b/gcc/testsuite/go.test/test/bench/shootout/threadring.txt
deleted file mode 100644
index f9aaa4d..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/threadring.txt
+++ /dev/null
@@ -1 +0,0 @@
-498
diff --git a/gcc/testsuite/go.test/test/bench/shootout/timing.log b/gcc/testsuite/go.test/test/bench/shootout/timing.log
deleted file mode 100644
index 4e7d17a..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/timing.log
+++ /dev/null
@@ -1,1254 +0,0 @@
-All tests on r45 or r70
-
-Aug 3 2009
-
-First version of fasta. Translation of fasta.c, fetched from
- http://shootout.alioth.debian.org/u32q/benchmark.php?test=fasta&lang=gpp&id=4
-
-fasta -n 25000000
- gcc -O2 fasta.c 5.98u 0.00s 6.01r
- gccgo -O2 fasta.go 8.82u 0.02s 8.85r
- 6g fasta.go 13.50u 0.02s 13.53r
- 6g -B fata.go 12.99u 0.02s 13.02r
-
-Aug 4 2009
-[added timing.sh]
-
-# myrandom:
-# hand-written optimization of integer division
-# use int32->float conversion
-fasta -n 25000000
- # probably I/O library inefficiencies
- gcc -O2 fasta.c 5.99u 0.00s 6.00r
- gccgo -O2 fasta.go 8.82u 0.02s 8.85r
- gc fasta 10.70u 0.00s 10.77r
- gc_B fasta 10.09u 0.03s 10.12r
-
-reverse-complement < output-of-fasta-25000000
- # we don't know - memory cache behavior?
- gcc -O2 reverse-complement.c 2.04u 0.94s 10.54r
- gccgo -O2 reverse-complement.go 6.54u 0.63s 7.17r
- gc reverse-complement 6.55u 0.70s 7.26r
- gc_B reverse-complement 6.32u 0.70s 7.10r
-
-nbody 50000000
- # math.Sqrt needs to be in assembly; inlining is probably the other 50%
- gcc -O2 nbody.c 21.61u 0.01s 24.80r
- gccgo -O2 nbody.go 118.55u 0.02s 120.32r
- gc nbody 100.84u 0.00s 100.85r
- gc_B nbody 103.33u 0.00s 103.39r
-[
-hacked Sqrt in assembler
- gc nbody 31.97u 0.00s 32.01r
-]
-
-binary-tree 15 # too slow to use 20
- # memory allocation and garbage collection
- gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.87r
- gccgo -O2 binary-tree.go 1.69u 0.46s 2.15r
- gccgo -O2 binary-tree-freelist.go 8.48u 0.00s 8.48r
- gc binary-tree 9.60u 0.01s 9.62r
- gc binary-tree-freelist 0.48u 0.01s 0.50r
-
-August 5, 2009
-
-fannkuch 12
- # bounds checking is half the difference
- # rest might be registerization
- gcc -O2 fannkuch.c 60.09u 0.01s 60.32r
- gccgo -O2 fannkuch.go 64.89u 0.00s 64.92r
- gc fannkuch 124.59u 0.00s 124.67r
- gc_B fannkuch 91.14u 0.00s 91.16r
-
-regex-dna 100000
- # regexp code is slow on trivial regexp
- gcc -O2 regex-dna.c -lpcre 0.92u 0.00s 0.99r
- gc regexp-dna 26.94u 0.18s 28.75r
- gc_B regexp-dna 26.51u 0.09s 26.75r
-
-spectral-norm 5500
- gcc -O2 spectral-norm.c -lm 11.54u 0.00s 11.55r
- gccgo -O2 spectral-norm.go 12.20u 0.00s 12.23r
- gc spectral-norm 50.23u 0.00s 50.36r
- gc_B spectral-norm 49.69u 0.01s 49.83r
- gc spectral-norm-parallel 24.47u 0.03s 11.05r # has shift >>1 not div /2
- [using >>1 instead of /2 : gc gives 24.33u 0.00s 24.33r]
-
-August 6, 2009
-
-k-nucleotide 5000000
- # string maps are slower than glib string maps
- gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 k-nucleotide.c: 10.72u 0.01s 10.74r
- gccgo -O2 k-nucleotide.go 21.64u 0.83s 22.78r
- gc k-nucleotide 16.08u 0.06s 16.50r
- gc_B k-nucleotide 17.32u 0.02s 17.37r
-
-mandelbrot 5500
- # floating point code generator should use more registers
- gcc -O2 mandelbrot.c 56.13u 0.02s 56.17r
- gccgo -O2 mandelbrot.go 57.49u 0.01s 57.51r
- gc mandelbrot 74.32u 0.00s 74.35r
- gc_B mandelbrot 74.28u 0.01s 74.31r
-
-meteor 2100
- # we don't know
- gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r
- gccgo -O2 meteor-contest.go 0.12u 0.00s 0.14r
- gc meteor-contest 0.24u 0.00s 0.26r
- gc_B meteor-contest 0.23u 0.00s 0.24r
-
-pidigits 10000
- # bignum is slower than gmp
- gcc -O2 pidigits.c -lgmp 2.60u 0.00s 2.62r
- gc pidigits 77.69u 0.14s 78.18r
- gc_B pidigits 74.26u 0.18s 75.41r
- gc_B pidigits 68.48u 0.20s 69.31r # special case: no bounds checking in bignum
-
-August 7 2009
-
-# New gc does better division by powers of 2. Significant improvements:
-
-spectral-norm 5500
- # floating point code generator should use more registers; possibly inline evalA
- gcc -O2 spectral-norm.c -lm 11.50u 0.00s 11.50r
- gccgo -O2 spectral-norm.go 12.02u 0.00s 12.02r
- gc spectral-norm 23.98u 0.00s 24.00r # new time is 0.48 times old time, 52% faster
- gc_B spectral-norm 23.71u 0.01s 23.72r # ditto
- gc spectral-norm-parallel 24.04u 0.00s 6.26r # /2 put back. note: 4x faster (on r70, idle)
-
-k-nucleotide 1000000
- # string maps are slower than glib string maps
- gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 10.82u 0.04s 10.87r
- gccgo -O2 k-nucleotide.go 22.73u 0.89s 23.63r
- gc k-nucleotide 15.97u 0.03s 16.04r
- gc_B k-nucleotide 15.86u 0.06s 15.93r # 8.5% faster, but probably due to weird cache effeccts in previous version
-
-pidigits 10000
- # bignum is slower than gmp
- gcc -O2 pidigits.c -lgmp 2.58u 0.00s 2.58r
- gc pidigits 71.24u 0.04s 71.28r # 8.5% faster
- gc_B pidigits 71.25u 0.03s 71.29r # 4% faster
-
-threadring 50000000
- gcc -O2 threadring.c -lpthread 35.51u 160.21s 199.50r
- gccgo -O2 threadring.go 90.33u 459.95s 448.03r
- gc threadring 33.11u 0.00s 33.14r
- GOMAXPROCS=4 gc threadring 114.48u 226.65s 371.59r
- # change wait code to do <-make(chan int) instead of time.Sleep
- gc threadring 28.41u 0.01s 29.35r
- GOMAXPROCS=4 gc threadring 112.59u 232.83s 384.72r
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 18.14u 276.52s 76.93r
- gc chameneosredux 20.19u 0.01s 20.23r
-
-Aug 10 2009
-
-# new 6g with better fp registers, fast div and mod of integers
-# complete set of timings listed. significant changes marked ***
-
-fasta -n 25000000
- # probably I/O library inefficiencies
- gcc -O2 fasta.c 5.96u 0.00s 5.97r
- gc fasta 10.59u 0.01s 10.61r
- gc_B fasta 9.92u 0.02s 9.95r
-
-reverse-complement < output-of-fasta-25000000
- # we don't know - memory cache behavior?
- gcc -O2 reverse-complement.c 1.96u 1.56s 16.23r
- gccgo -O2 reverse-complement.go 6.41u 0.62s 7.05r
- gc reverse-complement 6.46u 0.70s 7.17r
- gc_B reverse-complement 6.22u 0.72s 6.95r
-
-nbody 50000000
- # math.Sqrt needs to be in assembly; inlining is probably the other 50%
- gcc -O2 nbody.c 21.26u 0.01s 21.28r
- gccgo -O2 nbody.go 116.68u 0.07s 116.80r
- gc nbody 86.64u 0.01s 86.68r # -14%
- gc_B nbody 85.72u 0.02s 85.77r # *** -17%
-
-binary-tree 15 # too slow to use 20
- # memory allocation and garbage collection
- gcc -O2 binary-tree.c -lm 0.87u 0.00s 0.87r
- gccgo -O2 binary-tree.go 1.61u 0.47s 2.09r
- gccgo -O2 binary-tree-freelist.go 0.00u 0.00s 0.01r
- gc binary-tree 9.11u 0.01s 9.13r # *** -5%
- gc binary-tree-freelist 0.47u 0.01s 0.48r
-
-fannkuch 12
- # bounds checking is half the difference
- # rest might be registerization
- gcc -O2 fannkuch.c 59.92u 0.00s 59.94r
- gccgo -O2 fannkuch.go 65.54u 0.00s 65.58r
- gc fannkuch 123.98u 0.01s 124.04r
- gc_B fannkuch 90.75u 0.00s 90.78r
-
-regex-dna 100000
- # regexp code is slow on trivial regexp
- gcc -O2 regex-dna.c -lpcre 0.91u 0.00s 0.92r
- gc regex-dna 27.25u 0.02s 27.28r
- gc_B regex-dna 29.51u 0.03s 29.55r
-
-spectral-norm 5500
- # possibly inline evalA
- gcc -O2 spectral-norm.c -lm 11.57u 0.00s 11.57r
- gccgo -O2 spectral-norm.go 12.07u 0.01s 12.08r
- gc spectral-norm 23.99u 0.00s 24.00r
- gc_B spectral-norm 23.73u 0.00s 23.75r
-
-k-nucleotide 1000000
- # string maps are slower than glib string maps
- gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 10.63u 0.02s 10.69r
- gccgo -O2 k-nucleotide.go 23.19u 0.91s 24.12r
- gc k-nucleotide 16.73u 0.04s 16.78r # *** +5% (but this one seems to vary by more than that)
- gc_B k-nucleotide 16.46u 0.04s 16.51r # *** +5%
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 56.16u 0.00s 56.16r
- gccgo -O2 mandelbrot.go 57.41u 0.01s 57.42r
- gc mandelbrot 64.05u 0.02s 64.08r # *** -14%
- gc_B mandelbrot 64.10u 0.02s 64.14r # *** -14%
-
-meteor 2100
- # we don't know
- gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r
- gccgo -O2 meteor-contest.go 0.12u 0.00s 0.12r
- gc meteor-contest 0.18u 0.00s 0.20r # *** -25%
- gc_B meteor-contest 0.17u 0.00s 0.18r # *** -24%
-
-pidigits 10000
- # bignum is slower than gmp
- gcc -O2 pidigits.c -lgmp 2.57u 0.00s 2.57r
- gc pidigits 71.82u 0.04s 71.89r
- gc_B pidigits 71.84u 0.08s 71.98r
-
-threadring 50000000
- gcc -O2 threadring.c -lpthread 30.91u 164.33s 204.57r
- gccgo -O2 threadring.go 87.12u 460.04s 447.61r
- gc threadring 38.55u 0.00s 38.56r # *** +16%
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 17.93u 323.65s 88.47r
- gc chameneosredux 21.72u 0.00s 21.73r
-
-August 10 2009
-
-# In-place versions for some bignum operations.
-pidigits 10000
- gcc -O2 pidigits.c -lgmp 2.56u 0.00s 2.57r
- gc pidigits 55.22u 0.04s 55.29r # *** -23%
- gc_B pidigits 55.49u 0.02s 55.60r # *** -23%
-
-September 3 2009
-
-# New 6g inlines slices, has a few other tweaks.
-# Complete rerun. Significant changes marked.
-
-fasta -n 25000000
- # probably I/O library inefficiencies
- gcc -O2 fasta.c 5.96u 0.00s 5.96r
- gc fasta 10.63u 0.02s 10.66r
- gc_B fasta 9.92u 0.01s 9.94r
-
-reverse-complement < output-of-fasta-25000000
- # we don't know - memory cache behavior?
- gcc -O2 reverse-complement.c 1.92u 0.33s 2.93r
- gccgo -O2 reverse-complement.go 6.76u 0.72s 7.58r # +5%
- gc reverse-complement 6.59u 0.70s 7.29r # +2%
- gc_B reverse-complement 5.57u 0.80s 6.37r # -10%
-
-nbody 50000000
- # math.Sqrt needs to be in assembly; inlining is probably the other 50%
- # also loop alignment appears to be critical
- gcc -O2 nbody.c 21.28u 0.00s 21.28r
- gccgo -O2 nbody.go 119.21u 0.00s 119.22r # +2%
- gc nbody 109.72u 0.00s 109.78r # + 28% *****
- gc_B nbody 85.90u 0.00s 85.91r
-
-binary-tree 15 # too slow to use 20
- # memory allocation and garbage collection
- gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.87r
- gccgo -O2 binary-tree.go 1.88u 0.54s 2.42r # +17%
- gccgo -O2 binary-tree-freelist.go 0.01u 0.01s 0.02r
- gc binary-tree 8.94u 0.01s 8.96r # -2%
- gc binary-tree-freelist 0.47u 0.01s 0.48r
-
-fannkuch 12
- # bounds checking is half the difference
- # rest might be registerization
- gcc -O2 fannkuch.c 60.12u 0.00s 60.12r
- gccgo -O2 fannkuch.go 92.62u 0.00s 92.66r # +41% ***
- gc fannkuch 123.90u 0.00s 123.92r
- gc_B fannkuch 89.71u 0.00s 89.74r # -1%
-
-regex-dna 100000
- # regexp code is slow on trivial regexp
- gcc -O2 regex-dna.c -lpcre 0.88u 0.00s 0.88r
- gc regex-dna 25.77u 0.01s 25.79r # -5%
- gc_B regex-dna 26.05u 0.02s 26.09r # -12% ***
-
-spectral-norm 5500
- # possibly inline evalA
- gcc -O2 spectral-norm.c -lm 11.51u 0.00s 11.51r
- gccgo -O2 spectral-norm.go 11.95u 0.00s 11.96r
- gc spectral-norm 24.23u 0.00s 24.23r
- gc_B spectral-norm 23.83u 0.00s 23.84r
-
-k-nucleotide 1000000
- # string maps are slower than glib string maps
- gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 10.68u 0.04s 10.72r
- gccgo -O2 k-nucleotide.go 23.03u 0.88s 23.92r
- gc k-nucleotide 15.79u 0.05s 15.85r # -5% (but this one seems to vary by more than that)
- gc_B k-nucleotide 17.88u 0.05s 17.95r # +8% (ditto)
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 56.17u 0.02s 56.20r
- gccgo -O2 mandelbrot.go 56.74u 0.02s 56.79r # -1%
- gc mandelbrot 63.31u 0.01s 63.35r # -1%
- gc_B mandelbrot 63.29u 0.00s 63.31r # -1%
-
-meteor 2100
- # we don't know
- gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r
- gccgo -O2 meteor-contest.go 0.11u 0.00s 0.12r
- gc meteor-contest 0.18u 0.00s 0.19r
- gc_B meteor-contest 0.17u 0.00s 0.18r
-
-pidigits 10000
- # bignum is slower than gmp
- gcc -O2 pidigits.c -lgmp 2.56u 0.00s 2.57r
- gc pidigits 55.87u 0.03s 55.91r
- gc_B pidigits 55.93u 0.03s 55.99r
-
-# these tests are compared using real time, since they run multiple processors
-# accuracy probably low
-threadring 50000000
- gcc -O2 threadring.c -lpthread 26.31u 164.69s 199.92r # -2%
- gccgo -O2 threadring.go 87.90u 487.26s 472.81r # +6%
- gc threadring 28.89u 0.00s 28.90r # -25% ***
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 16.41u 296.91s 81.17r # -8%
- gc chameneosredux 19.97u 0.00s 19.97r # -8%
-
-Sep 22, 2009
-
-# 6g inlines sliceslice in most cases.
-
-fasta -n 25000000
- # probably I/O library inefficiencies
- gc fasta 10.24u 0.00s 10.25r # -4%
- gc_B fasta 9.68u 0.01s 9.69r # -3%
-
-reverse-complement < output-of-fasta-25000000
- # we don't know - memory cache behavior?
- gc reverse-complement 6.67u 0.69s 7.37r # +1%
- gc_B reverse-complement 6.00u 0.64s 6.65r # +7%
-
-nbody -n 50000000
- # math.Sqrt needs to be in assembly; inlining is probably the other 50%
- # also loop alignment appears to be critical
- gc nbody 86.27u 0.00s 86.29r # -21%
- gc_B nbody 104.52u 0.00s 104.54r # +22%
-
-fannkuch 12
- # bounds checking is half the difference
- # rest might be registerization
- gc fannkuch 128.36u 0.00s 128.37r # +4%
- gc_B fannkuch 89.32u 0.00s 89.34r
-
-regex-dna 100000
- # regexp code is slow on trivial regexp
- gc regex-dna 24.82u 0.01s 24.86r # -4%
- gc_B regex-dna 24.55u 0.01s 24.57r # -6%
-
-spectral-norm 5500
- # possibly inline evalA
- gc spectral-norm 24.05u 0.00s 24.07r # -1%
- gc_B spectral-norm 23.60u 0.00s 23.65r # -1%
-
-k-nucleotide 1000000
- # string maps are slower than glib string maps
- gc k-nucleotide 17.84u 0.04s 17.89r # +13% but mysterious variation continues
- gc_B k-nucleotide 15.56u 0.08s 15.65r # -13% (ditto)
-
-mandelbrot 16000
- gc mandelbrot 64.08u 0.01s 64.11r # +1%
- gc_B mandelbrot 64.04u 0.00s 64.05r # +1%
-
-pidigits 10000
- # bignum is slower than gmp
- gc pidigits 58.68u 0.02s 58.72r # +5%
- gc_B pidigits 58.86u 0.05s 58.99r # +5%
-
-# these tests are compared using real time, since they run multiple processors
-# accuracy probably low
-threadring 50000000
- gc threadring 32.70u 0.02s 32.77r # +13%
-
-chameneos 6000000
- gc chameneosredux 26.62u 0.00s 26.63r # +13%
-
-Sep 24, 2009
-
-# Sqrt now in assembler for 6g.
-nbody -n 50000000
- # remember, at least for 6g, alignment of loops may be important
- gcc -O2 nbody.c 21.24u 0.00s 21.25r
- gccgo -O2 nbody.go 121.03u 0.00s 121.04r
- gc nbody 30.26u 0.00s 30.27r # -65% ***
- gc_B nbody 30.20u 0.02s 30.22r # -72% ***
-
-Nov 13 2009
-
-# fix bug in regexp; take performance hit. good regexps will come in time.
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.92u 0.00s 0.94r
- gc regex-dna 29.78u 0.03s 29.83r
- gc_B regex-dna 32.63u 0.03s 32.74r
-
-Nov 24 2009
-
-# Roger Peppe's rewrite of the benchmark
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 18.00u 303.29s 83.64r
- gc chameneosredux 12.10u 0.00s 12.10r # 2.22X faster
-
-Jan 6, 2010
-
-# Long-overdue update. All numbers included in this complete run.
-# Some programs (e.g. reverse-complement) rewritten for speed.
-# Regular expressions much faster in common cases (although still far behind PCRE)
-# Bignum stuff improved
-# Better (but sometimes slower) locking in channels.
-
-fasta -n 25000000
- gcc -O2 fasta.c 5.99u 0.01s 6.00r
- gc fasta 9.11u 0.00s 9.12r # -11%
- gc_B fasta 8.60u 0.00s 8.62r # +12% ??
-
-reverse-complement < output-of-fasta-25000000
- gcc -O2 reverse-complement.c 2.00u 0.80s 9.54r
-# gccgo -O2 reverse-complement.go 4.57u 0.35s 4.94r # 33% faster
- gc reverse-complement 2.01u 0.38s 2.40r # 3.3X faster
- gc_B reverse-complement 1.88u 0.36s 2.24r # 3.2X faster
-GOGC=off
- gc reverse-complement 2.01u 0.35s 2.37r
- gc_B reverse-complement 1.86u 0.32s 2.19r
-
-nbody -n 50000000
- gcc -O2 nbody.c 21.28u 0.00s 21.31r
- gccgo -O2 nbody.go 80.02u 0.00s 80.05r # 33% faster
- gc nbody 30.13u 0.00s 30.13r
- gc_B nbody 29.89u 0.01s 29.91r
-
-binary-tree 15 # too slow to use 20
- gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.87r
- gccgo -O2 binary-tree.go 4.82u 0.41s 5.24r # 2.5X slower
- gc binary-tree 7.23u 0.01s 7.25r # # -19%
- gc binary-tree-freelist 0.43u 0.00s 0.44r # -9%
-
-fannkuch 12
- gcc -O2 fannkuch.c 60.17u 0.00s 60.17r
- gccgo -O2 fannkuch.go 78.47u 0.01s 78.49r
- gc fannkuch 128.86u 0.00s 128.96r
- gc_B fannkuch 90.17u 0.00s 90.21r
-
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.90u 0.00s 0.92r
- gc regex-dna 9.48u 0.01s 9.50r # 3.1X faster
- gc_B regex-dna 9.08u 0.00s 9.10r # 3.6X faster
-
-spectral-norm 5500
- gcc -O2 spectral-norm.c -lm 11.48u 0.00s 11.48r
- gccgo -O2 spectral-norm.go 11.68u 0.00s 11.70r
- gc spectral-norm 23.98u 0.00s 23.99r
- gc_B spectral-norm 23.68u 0.00s 23.69r
-
-k-nucleotide 1000000
- gcc -O2 k-nucleotide.c 10.85u 0.04s 10.90r
- gccgo -O2 k-nucleotide.go 25.26u 0.87s 26.14r
- gc k-nucleotide 15.28u 0.06s 15.37r # restored; mysterious variation continues
- gc_B k-nucleotide 15.97u 0.03s 16.00r
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 56.12u 0.01s 56.15r
- gccgo -O2 mandelbrot.go 56.86u 0.01s 56.89r
- gc mandelbrot 66.05u 0.00s 66.07r # -3%
- gc_B mandelbrot 66.06u 0.00s 66.07r # -3%
-
-meteor 2100
- gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r
- gccgo -O2 meteor-contest.go 0.12u 0.00s 0.12r
- gc meteor-contest 0.17u 0.00s 0.17r
- gc_B meteor-contest 0.15u 0.00s 0.16r
-
-pidigits 10000
- gcc -O2 pidigits.c -lgmp 2.57u 0.00s 2.59r
- gc pidigits 38.27u 0.02s 38.30r # 1.5X faster
- gc_B pidigits 38.27u 0.02s 38.31r # 1.5X faster
-
-threadring 50000000
- gcc -O2 threadring.c 37.11u 170.59s 212.75r
- gccgo -O2 threadring.go 89.67u 447.56s 442.55r # -6.5%
- gc threadring 36.08u 0.04s 36.15r # +10%
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 19.02u 331.08s 90.79r
- gc chameneosredux 12.54u 0.00s 12.55r
-
-Oct 19, 2010
-
-# Another long-overdue update. Some of the code is new; parallel versions
-# of some are added. A few significant improvements.
-
-fasta -n 25000000
- gcc -O2 fasta.c 4.92u 0.00s 4.93r
- gccgo -O2 fasta.go 3.31u 0.00s 3.34r # new code
- gc fasta 3.68u 0.00s 3.69r # 2.5X faster with no code
- gc_B fasta 3.68u 0.00s 3.69r # 2.3X faster with no code
-
-reverse-complement < output-of-fasta-25000000
- gcc -O2 reverse-complement.c 1.93u 0.81s 11.24r
- gccgo -O2 reverse-complement.go 1.58u 0.43s 2.04r # first run with new code?
- gc reverse-complement 1.84u 0.34s 2.20r # 10% faster
- gc_B reverse-complement 1.85u 0.32s 2.18r
-
-nbody -n 50000000
- gcc -O2 nbody.c 21.35u 0.00s 21.36r
- gccgo -O2 nbody.go 21.62u 0.00s 21.66r # 3.7X faster - why??
- gc nbody 29.78u 0.00s 29.79r
- gc_B nbody 29.72u 0.00s 29.72r
-
-binary-tree 15 # too slow to use 20
- gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.88r
- gccgo -O2 binary-tree.go 4.05u 0.02s 4.08r # 28% faster
- gccgo -O2 binary-tree-freelist 0.34u 0.08s 0.34r
- gc binary-tree 5.94u 0.00s 5.95r # 20% faster
- gc binary-tree-freelist 0.50u 0.01s 0.54r
-
-fannkuch 12
- gcc -O2 fannkuch.c 60.45u 0.00s 60.45r
- gccgo -O2 fannkuch.go 64.64u 0.00s 64.64r
- gccgo -O2 fannkuch-parallel.go 115.63u 0.00s 31.58r
- gc fannkuch 126.52u 0.04s 126.68r
- gc fannkuch-parallel 238.82u 0.10s 65.93r # GOMAXPROCS=4
- gc_B fannkuch 88.99u 0.00s 89.02r
-
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.89u 0.00s 0.89r
- gc regex-dna 8.99u 0.02s 9.03r
- gc regex-dna-parallel 8.94u 0.02s 3.68r # GOMAXPROCS=4
- gc_B regex-dna 9.12u 0.00s 9.14r
-
-spectral-norm 5500
- gcc -O2 spectral-norm.c -lm 11.55u 0.00s 11.57r
- gccgo -O2 spectral-norm.go 11.73u 0.00s 11.75r
- gc spectral-norm 23.74u 0.00s 23.79r
- gc_B spectral-norm 24.49u 0.02s 24.54r
-
-k-nucleotide 1000000
- gcc -O2 k-nucleotide.c 11.44u 0.06s 11.50r
- gccgo -O2 k-nucleotide.go 8.65u 0.04s 8.71r
- gccgo -O2 k-nucleotide-parallel.go 8.75u 0.03s 2.97r # set GOMAXPROCS=4
- gc k-nucleotide 14.92u 0.05s 15.01r
- gc k-nucleotide-parallel 16.96u 0.06s 6.53r # set GOMAXPROCS=4
- gc_B k-nucleotide 15.97u 0.03s 16.08r
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 56.32u 0.00s 56.35r
- gccgo -O2 mandelbrot.go 55.62u 0.02s 55.77r
- gc mandelbrot 64.85u 0.01s 64.94r
- gc_B mandelbrot 65.02u 0.01s 65.14r
-
-meteor 2100
- gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r
- gccgo -O2 meteor-contest.go 0.10u 0.00s 0.11r
- gc meteor-contest 0.17u 0.00s 0.18r
- gc_B meteor-contest 0.16u 0.00s 0.16r
-
-pidigits 10000
- gcc -O2 pidigits.c -lgmp 2.58u 0.00s 2.59r
- gccgo -O2 pidigits.go 14.06u 0.01s 14.09r # first run?
- gc pidigits 8.47u 0.05s 8.55r # 4.5X faster due to package big
- gc_B pidigits 8.33u 0.01s 8.36r # 4.5X faster due to package big
-
-threadring 50000000
- gcc -O2 threadring.c 28.18u 153.19s 186.47r
- gccgo -O2 threadring.go 110.10u 516.48s 515.25r
- gc threadring 40.39u 0.00s 40.40r
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 18.20u 301.55s 83.10r
- gccgo -O2 chameneosredux.go 52.22u 324.54s 201.21r
- gc chameneosredux 13.52u 0.00s 13.54r
-
-Dec 14, 2010
-
-# Improved regex code (same algorithm) gets ~30%.
-
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.77u 0.01s 0.78r
- gc regex-dna 6.80u 0.00s 6.81r
- gc regex-dna-parallel 6.82u 0.01s 2.75r
- gc_B regex-dna 6.69u 0.02s 6.70r
-
-Feb 15, 2011
-
-# Improved GC, still single-threaded but more efficient
-
-fasta -n 25000000
- gcc -O2 fasta.c 3.40u 0.00s 3.40r
- gccgo -O2 fasta.go 3.51u 0.00s 3.50r
- gc fasta 3.66u 0.01s 3.66r
- gc_B fasta 3.66u 0.00s 3.66r
-
-reverse-complement < output-of-fasta-25000000
- gcc -O2 reverse-complement.c 1.86u 1.29s 4.93r
- gccgo -O2 reverse-complement.go 2.18u 0.41s 2.60r
- gc reverse-complement 1.67u 0.48s 2.15r
- gc_B reverse-complement 1.71u 0.45s 2.15r
-
-nbody -n 50000000
- gcc -O2 -lm nbody.c 21.64u 0.00s 21.64r
- gccgo -O2 nbody.go 21.46u 0.00s 21.45r
- gc nbody 29.07u 0.00s 29.06r
- gc_B nbody 31.61u 0.00s 31.61r
-
-binary-tree 15 # too slow to use 20
- gcc -O2 binary-tree.c -lm 0.88u 0.00s 0.87r
- gccgo -O2 binary-tree.go 2.74u 0.07s 2.81r
- gccgo -O2 binary-tree-freelist.go 0.01u 0.00s 0.00r
- gc binary-tree 4.22u 0.02s 4.24r
- gc binary-tree-freelist 0.54u 0.02s 0.55r
-
-fannkuch 12
- gcc -O2 fannkuch.c 57.64u 0.00s 57.64r
- gccgo -O2 fannkuch.go 65.79u 0.00s 65.82r
- gccgo -O2 fannkuch-parallel.go 160.91u 0.02s 43.90r
- gc fannkuch 126.36u 0.03s 126.53r
- gc fannkuch-parallel 175.23u 0.04s 45.49r
- gc_B fannkuch 89.23u 0.00s 89.24r
-
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.77u 0.01s 0.80r
- gccgo -O2 regex-dna.go 12.38u 0.10s 12.52r
- gccgo -O2 regex-dna-parallel.go 43.96u 4.64s 15.11r
- gc regex-dna 7.03u 0.01s 7.05r
- gc regex-dna-parallel 6.85u 0.05s 2.70r
- gc_B regex-dna 6.87u 0.02s 6.89r
-
-spectral-norm 5500
- gcc -O2 spectral-norm.c -lm 12.29u 0.00s 12.28r
- gccgo -O2 spectral-norm.go 11.79u 0.00s 11.79r
- gc spectral-norm 24.00u 0.02s 24.05r
- gc_B spectral-norm 24.59u 0.01s 24.59r
-
-k-nucleotide 1000000
- gcc -O2 k-nucleotide.c 9.75u 0.07s 9.82r
- gccgo -O2 k-nucleotide.go 8.92u 0.06s 8.98r
- gccgo -O2 k-nucleotide-parallel.go 8.40u 0.04s 2.76r
- gc k-nucleotide 17.01u 0.03s 17.04r
- gc k-nucleotide-parallel 16.51u 0.08s 6.21r
- gc_B k-nucleotide 16.94u 0.08s 17.02r
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 54.60u 0.00s 54.66r
- gccgo -O2 mandelbrot.go 59.38u 0.00s 59.41r
- gc mandelbrot 64.93u 0.04s 65.08r
- gc_B mandelbrot 64.85u 0.03s 64.92r
-
-meteor 2098
- gcc -O2 meteor-contest.c 0.10u 0.01s 0.10r
- gccgo -O2 meteor-contest.go 0.11u 0.00s 0.11r
- gc meteor-contest 0.18u 0.00s 0.17r
- gc_B meteor-contest 0.17u 0.00s 0.16r
-
-pidigits 10000
- gcc -O2 pidigits.c -lgmp 2.24u 0.00s 2.23r
- gccgo -O2 pidigits.go 14.05u 0.00s 14.06r
- gc pidigits 6.34u 0.05s 6.38r
- gc_B pidigits 6.37u 0.02s 6.38r
-
-threadring 50000000
- gcc -O2 threadring.c 30.50u 258.05s 325.72r
- gccgo -O2 threadring.go 92.87u 748.39s 728.46r
- gc threadring 38.03u 0.01s 38.04r
-
-# Apr 15, 2011
-# Move to new machine, Intel Xeon E5520@2.27GHz.
-# (Was Opteron(tm) Processor 8214 HE)
-
-fasta -n 25000000
-OLD:
- gcc -O2 fasta.c 3.39u 0.04s 3.42r
- gccgo -O2 fasta.go 3.52u 0.00s 3.52r
- gc fasta 3.63u 0.04s 3.67r
- gc_B fasta 3.66u 0.00s 3.66r
-NEW:
- gcc -O2 fasta.c 1.45u 0.02s 1.47r
- gccgo -O2 fasta.go 1.51u 0.01s 1.51r
- gc fasta 2.04u 0.00s 2.04r
- gc_B fasta 2.05u 0.00s 2.04r
-
-reverse-complement < output-of-fasta-25000000
-OLD:
- gcc -O2 reverse-complement.c 1.87u 1.51s 7.02r
- gccgo -O2 reverse-complement.go 1.56u 0.54s 3.37r
- gc reverse-complement 1.73u 0.36s 2.08r
- gc_B reverse-complement 1.75u 0.37s 2.12r
-NEW:
- gcc -O2 reverse-complement.c 1.20u 0.47s 12.96r
- gccgo -O2 reverse-complement.go 0.88u 0.14s 1.01r
- gc reverse-complement 1.13u 0.17s 1.30r
- gc_B reverse-complement 1.11u 0.09s 1.20r
-
-nbody -n 50000000
-OLD:
- gcc -O2 -lm nbody.c 21.90u 0.00s 21.92r
- gccgo -O2 nbody.go 23.12u 0.03s 23.19r
- gc nbody 29.07u 0.00s 29.07r
- gc_B nbody 31.84u 0.00s 31.85r
-NEW:
- gcc -O2 -lm nbody.c 13.01u 0.00s 13.03r
- gccgo -O2 nbody.go 13.35u 0.00s 13.37r
- gc nbody 21.78u 0.00s 21.82r
- gc_B nbody 21.72u 0.00s 21.76r
-
-binary-tree 15 # too slow to use 20
-OLD:
- gcc -O2 binary-tree.c -lm 0.83u 0.02s 0.84r
- gccgo -O2 binary-tree.go 2.61u 0.02s 2.62r
- gccgo -O2 binary-tree-freelist.go 0.32u 0.01s 0.32r
- gc binary-tree 3.93u 0.04s 3.97r
- gc binary-tree-freelist 0.47u 0.03s 0.50r
-NEW:
- gcc -O2 binary-tree.c -lm 0.60u 0.00s 0.59r
- gccgo -O2 binary-tree.go 1.53u 0.00s 1.52r
- gccgo -O2 binary-tree-freelist.go 0.01u 0.00s 0.00r
- gc binary-tree 1.93u 0.02s 1.95r
- gc binary-tree-freelist 0.32u 0.01s 0.32r
-
-fannkuch 12
-OLD:
- gcc -O2 fannkuch.c 57.64u 0.00s 57.64r
- gccgo -O2 fannkuch.go 65.56u 0.01s 65.65r
- gccgo -O2 fannkuch-parallel.go 179.12u 0.00s 49.82r
- gc fannkuch 126.39u 0.00s 126.39r
- gc fannkuch-parallel 172.49u 0.02s 45.44r
- gc_B fannkuch 89.30u 0.00s 89.28r
-NEW:
- gcc -O2 fannkuch.c 45.17u 0.00s 45.26r
- gccgo -O2 fannkuch.go 53.63u 0.00s 53.73r
- gccgo -O2 fannkuch-parallel.go 216.72u 0.00s 58.42r
- gc fannkuch 108.21u 0.00s 108.44r
- gc fannkuch-parallel 227.20u 0.00s 57.27r
- gc_B fannkuch 56.14u 0.00s 56.26r
-
-regex-dna 100000
-OLD:
- gcc -O2 regex-dna.c -lpcre 0.77u 0.01s 0.78r
- gccgo -O2 regex-dna.go 10.15u 0.02s 10.23r
- gccgo -O2 regex-dna-parallel.go 33.81u 3.22s 11.62r
- gc regex-dna 6.52u 0.04s 6.56r
- gc regex-dna-parallel 6.84u 0.03s 2.70r
- gc_B regex-dna 6.83u 0.01s 6.84r
-NEW:
- gcc -O2 regex-dna.c -lpcre 0.47u 0.00s 0.47r
- gccgo -O2 regex-dna.go 6.00u 0.00s 6.00r
- gccgo -O2 regex-dna-parallel.go 44.54u 1.57s 6.51r
- gc regex-dna 5.41u 0.01s 5.42r
- gc regex-dna-parallel 5.62u 0.01s 2.20r
- gc_B regex-dna 5.50u 0.00s 5.50r
-
-spectral-norm 5500
-OLD:
- gcc -O2 spectral-norm.c -lm 12.29u 0.00s 12.28r
- gccgo -O2 spectral-norm.go 11.56u 0.00s 11.55r
- gc spectral-norm 23.98u 0.00s 24.00r
- gc_B spectral-norm 24.62u 0.00s 24.65r
-NEW:
- gcc -O2 spectral-norm.c -lm 15.79u 0.00s 15.82r
- gccgo -O2 spectral-norm.go 15.32u 0.00s 15.35r
- gc spectral-norm 19.62u 0.01s 19.67r
- gc_B spectral-norm 19.62u 0.00s 19.66r
-
-k-nucleotide 1000000
-OLD:
- gcc -O2 k-nucleotide.c 9.82u 0.06s 9.87r
- gccgo -O2 k-nucleotide.go 8.30u 0.02s 8.32r
- gccgo -O2 k-nucleotide-parallel.go 8.84u 0.05s 3.02r
- gc k-nucleotide 15.38u 0.07s 15.44r
- gc k-nucleotide-parallel 16.40u 0.03s 5.93r
- gc_B k-nucleotide 15.19u 0.05s 15.23r
-NEW:
- gcc -O2 -k-nucleotide.c 4.88u 0.03s 4.92r
- gccgo -O2 k-nucleotide.go 5.94u 0.01s 5.96r
- gccgo -O2 k-nucleotide-parallel.go 6.44u 0.03s 1.47r
- gc k-nucleotide 9.61u 0.01s 9.63r
- gc k-nucleotide-parallel 9.70u 0.00s 3.39r
- gc_B k-nucleotide 9.19u 0.03s 9.23r
-
-mandelbrot 16000
-OLD:
- gcc -O2 mandelbrot.c 54.54u 0.00s 54.56r
- gccgo -O2 mandelbrot.go 59.63u 0.03s 59.67r
- gc mandelbrot 64.82u 0.00s 64.83r
- gc_B mandelbrot 64.84u 0.00s 64.91r
-NEW:
- gcc -O2 mandelbrot.c 36.07u 0.01s 36.15r
- gccgo -O2 mandelbrot.go 43.57u 0.00s 43.66r
- gc mandelbrot 60.66u 0.00s 60.79r
- gc_B mandelbrot 60.90u 0.00s 61.03r
-
-meteor 2098
-OLD:
- gcc -O2 meteor-contest.c 0.11u 0.00s 0.10r
- gccgo -O2 meteor-contest.go 0.10u 0.01s 0.10r
- gc meteor-contest 0.18u 0.00s 0.17r
- gc_B meteor-contest 0.17u 0.00s 0.16r
-NEW:
- gcc -O2 meteor-contest.c 0.10u 0.00s 0.09r
- gccgo -O2 meteor-contest.go 0.10u 0.00s 0.09r
- gc meteor-contest 0.14u 0.00s 0.14r
- gc_B meteor-contest 0.13u 0.00s 0.13r
-
-pidigits 10000
-OLD:
- gcc -O2 pidigits.c -lgmp 2.22u 0.00s 2.21r
- gccgo -O2 pidigits.go 13.39u 0.00s 13.40r
- gc pidigits 6.42u 0.04s 6.45r
- gc_B pidigits 6.45u 0.02s 6.47r
-NEW:
- gcc -O2 pidigits.c -lgmp 2.27u 0.00s 2.29r
- gccgo -O2 pidigits.go 9.21u 0.00s 9.22r
- gc pidigits 3.60u 0.00s 3.60r
- gc_B pidigits 3.56u 0.02s 3.58r
-
-threadring 50000000
-OLD:
- gcc -O2 threadring.c -lpthread 34.51u 267.95s 336.12r
- gccgo -O2 threadring.go 103.51u 588.57s 627.16r
- gc threadring 54.68u 0.00s 54.73r
-NEW:
- gcc -O2 threadring.c 32.00u 259.39s 369.74r
- gccgo -O2 threadring.go 133.06u 546.02s 595.33r
- gc threadring 16.75u 0.02s 16.80r
-
-chameneos 6000000
-OLD:
- gcc -O2 chameneosredux.c -lpthread 12.65u 31.02s 13.33r
- gccgo -O2 chameneosredux.go 47.04u 302.84s 252.29r
- gc chameneosredux 14.14u 0.00s 14.14r
-NEW:
- gcc -O2 chameneosredux.c -lpthread 8.05u 63.43s 11.16r
- gccgo -O2 chameneosredux.go 82.95u 304.37s 207.64r
- gc chameneosredux 9.42u 0.00s 9.43r
-
-# May 13, 2011
-# after gc update to inline append when possible - 35% faster
-
-regex-dna 100000
- gc regex-dna 3.94u 0.00s 3.95r
- gc regex-dna-parallel 4.15u 0.01s 1.63r
- gc_B regex-dna 4.01u 0.01s 4.02r
-
-# Aug 4, 2011
-# After various updates to locking code and some runtime changes.
-# Slowdowns believed due to slower (but more correct) memmove.
-
-fannkuch 12
- gccgo -O2 fannkuch.go 51.59u 0.00s 51.69r # -4%
- gccgo -O2 fannkuch-parallel.go 253.17u 0.00s 64.67r # -11%
- gc fannkuch 103.14u 0.00s 103.36r # -5%
- gc fannkuch-parallel 189.63u 0.00s 49.37r # +9%
- gc_B fannkuch 49.19u 0.00s 49.29r # -14%
-
-regex-dna 100000
- gc regex-dna 3.78u 0.00s 3.78r # -43%
- gc regex-dna-parallel 3.84u 0.02s 1.48r # -49%
- gc_B regex-dna 3.62u 0.00s 3.63r # -52%
-
-k-nucleotide 1000000
- gc k-nucleotide 12.23u 0.02s 12.27r # +27%
- gc k-nucleotide-parallel 12.76u 0.02s 4.37r # +29%
- gc_B k-nucleotide 12.18u 0.01s 12.21r # +33%
-
-threadring 50000000
- gc threadring 17.49u 0.00s 17.53r # +4%
-
-chameneos 6000000
- gc chameneosredux 7.61u 0.00s 7.63r # -24%
-
-Aug 9, 2011
-# After custom algorithms for 1- 2- 4- 8-byte scalars.
-
-fannkuch 12
- gc fannkuch-parallel 157.17u 0.00s 41.08r # -17%
-
-k-nucleotide 1000000
- gc k-nucleotide 8.72u 0.03s 8.76r # -39%
- gc k-nucleotide-parallel 8.79u 0.01s 3.14r # -39%
- gc_B k-nucleotide 8.65u 0.03s 8.69r # -39%
-
-pidigits 10000
- gc pidigits 3.71u 0.02s 3.73r # +4%
- gc_B pidigits 3.73u 0.00s 3.73r # +4%
-
-threadring 50000000
- gc threadring 14.51u 0.00s 14.54r # -17%
-
-chameneos 6000000
- gc chameneosredux 7.41u 0.00s 7.42r # -3%
-
-# A complete run at the Go 1 release.
-# Significant changes:
-# - gccgo is now enabled for all tests (goroutines are cheap enough)
-# - threadring and chameneos are 14% faster, probably due to runtime changes
-# - regex-dna 36% faster
-# - fannkuch-parallel (only) slowed down 40%
-# - gccgo on binary-tree-freelist is still optimized to nothing
-# Other changes are modest.
-
-fasta -n 25000000
- gcc -O2 fasta.c 1.45u 0.02s 1.48r
- gccgo -O2 fasta.go 1.46u 0.00s 1.47r
- gc fasta 1.99u 0.01s 2.00r
- gc_B fasta 1.99u 0.01s 2.01r
-
-reverse-complement < output-of-fasta-25000000
- gcc -O2 reverse-complement.c 0.95u 0.48s 4.99r
- gccgo -O2 reverse-complement.go 0.93u 0.16s 1.09r
- gc reverse-complement 1.20u 0.19s 1.39r
- gc_B reverse-complement 1.04u 0.16s 1.20r
-
-nbody -n 50000000
- gcc -O2 -lm nbody.c 13.02u 0.00s 13.05r
- gccgo -O2 nbody.go 14.46u 0.00s 14.49r
- gc nbody 21.79u 0.00s 21.84r
- gc_B nbody 21.74u 0.00s 21.79r
-
-binary-tree 15 # too slow to use 20
- gcc -O2 binary-tree.c -lm 0.60u 0.01s 0.61r
- gccgo -O2 binary-tree.go 1.30u 0.01s 1.32r
- gccgo -O2 binary-tree-freelist.go 0.00u 0.00s 0.00r
- gc binary-tree 1.84u 0.01s 1.86r
- gc binary-tree-freelist 0.33u 0.00s 0.33r
-
-fannkuch 12
- gcc -O2 fannkuch.c 45.24u 0.00s 45.34r
- gccgo -O2 fannkuch.go 59.76u 0.01s 59.90r
- gccgo -O2 fannkuch-parallel.go 218.20u 0.01s 61.60r
- gc fannkuch 103.92u 0.00s 104.16r
- gc fannkuch-parallel 221.61u 0.00s 60.49r
- gc_B fannkuch 53.17u 0.00s 53.30r
-
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.47u 0.00s 0.48r
- gccgo -O2 regex-dna.go 6.52u 0.00s 6.54r
- gccgo -O2 regex-dna-parallel.go 14.40u 0.73s 4.35r
- gc regex-dna 2.63u 0.02s 2.66r # -36%
- gc regex-dna-parallel 2.87u 0.01s 1.11r
- gc_B regex-dna 2.65u 0.00s 2.66r
-
-spectral-norm 5500
- gcc -O2 spectral-norm.c -lm 15.78u 0.00s 15.82r
- gccgo -O2 spectral-norm.go 15.79u 0.00s 15.83r
- gc spectral-norm 19.76u 0.00s 19.80r
- gc_B spectral-norm 19.73u 0.01s 19.78r
-
-k-nucleotide 1000000
- gcc -O2 k-nucleotide.c 5.59u 0.03s 5.63r
- gccgo -O2 k-nucleotide.go 4.09u 0.03s 4.13r
- gccgo -O2 k-nucleotide-parallel.go 4.50u 0.06s 1.63r
- gc k-nucleotide 9.23u 0.02s 9.27r
- gc k-nucleotide-parallel 9.87u 0.03s 3.55r
- gc_B k-nucleotide 9.20u 0.00s 9.22r
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 36.09u 0.00s 36.18r
- gccgo -O2 mandelbrot.go 41.69u 0.01s 41.80r
- gc mandelbrot 60.91u 0.02s 61.07r
- gc_B mandelbrot 60.90u 0.00s 61.04r
-
-meteor 2098
- gcc -O2 meteor-contest.c 0.09u 0.00s 0.09r
- gccgo -O2 meteor-contest.go 0.09u 0.00s 0.09r
- gc meteor-contest 0.14u 0.00s 0.15r
- gc_B meteor-contest 0.14u 0.00s 0.14r
-
-pidigits 10000
- gcc -O2 pidigits.c -lgmp 2.27u 0.00s 2.27r
- gccgo -O2 pidigits.go 8.65u 0.00s 8.67r
- gc pidigits 3.70u 0.04s 3.75r
- gc_B pidigits 3.72u 0.02s 3.75r
-
-threadring 50000000
- gcc -O2 threadring.c 40.91u 369.85s 323.31r
- gccgo -O2 threadring.go 26.97u 30.82s 57.93r
- gc threadring 12.81u 0.01s 12.85r # -13%
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 9.44u 72.90s 12.65r
- gccgo -O2 chameneosredux.go 7.73u 7.53s 15.30r
- gc chameneosredux 6.51u 0.00s 6.53r # - 14%
-
-# After http://codereview.appspot.com/6248049, moving panicindex
-# calls out of line (putting the likely code into a single path and shortening
-# loops). Significant changes since the last run (note: some are slower for
-# unrelated and as yet undiagnosed reasons):
-
-nbody -n 50000000
- gc nbody 19.10u 0.01s 19.19r # -12%
- gc_B nbody 19.19u 0.00s 19.23r # -12%
-
-binary-tree 15 # too slow to use 20
- gc binary-tree 1.49u 0.01s 1.51r # -19%
-
-fannkuch 12
- gc fannkuch 60.79u 0.00s 60.92r # -41%
- gc fannkuch-parallel 183.51u 0.01s 51.75r # -14%
- gc_B fannkuch 51.68u 0.00s 51.79r # -3%
-
-k-nucleotide 1000000
- gc k-nucleotide 9.74u 0.04s 9.80r # +6%
- gc k-nucleotide-parallel 9.89u 0.05s 3.59r # +1%
- gc_B k-nucleotide 9.39u 0.02s 9.43r # +2%
-
-mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)
- gc mandelbrot 100.98u 0.00s 101.20r # +65%
- gc_B mandelbrot 100.90u 0.01s 101.17r # +65%
-
-meteor 2098
- gc meteor-contest 0.13u 0.00s 0.13r # -13%
- gc_B meteor-contest 0.13u 0.00s 0.13r # -7%
-
-# May 30, 2012.
-# After http://codereview.appspot.com/6261051, restoring old code generated
-# for floating-point constants. Mandelbrot is back to its previous numbers.
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 36.07u 0.00s 36.16r
- gccgo -O2 mandelbrot.go 41.72u 0.01s 41.90r
- gc mandelbrot 60.62u 0.00s 60.76r
- gc_B mandelbrot 60.68u 0.00s 60.82r
-
-# May 30, 2012.
-# After http://codereview.appspot.com/6248068, better FP code
-# by avoiding MOVSD between registers.
-# Plus some other timing changes that have crept in from other speedups,
-# from garbage collection to Printf.
-
-fasta -n 25000000
- gc fasta 1.76u 0.00s 1.76r # -12%
- gc_B fasta 1.71u 0.00s 1.72r # -12%
-
-nbody -n 50000000
- gc nbody 17.56u 0.00s 17.60r # -8%
- gc_B nbody 17.30u 0.00s 17.34r # -10%
-
-fannkuch 12
- gc fannkuch-parallel 155.92u 0.01s 44.05r # -15%
-
-k-nucleotide 1000000
- gc k-nucleotide 9.22u 0.01s 9.26r # -5%
- gc k-nucleotide-parallel 9.23u 0.03s 3.26r # -9%
- gc_B k-nucleotide 9.22u 0.03s 9.28r # -2%
-
-mandelbrot 16000
- gc mandelbrot 44.80u 0.00s 44.90r # -27%
- gc_B mandelbrot 44.81u 0.00s 44.92r # -26%
-
-pidigits 10000
- gc pidigits 3.51u 0.00s 3.52r # -6%
- gc_B pidigits 3.51u 0.00s 3.52r # -6%
-
-# Aug 28, 2012
-# After some assembler work in package big.
-pidigits 10000
- gc pidigits 2.85u 0.02s 2.88r # -22%
- gc_B pidigits 2.88u 0.01s 2.90r # -21%
-
-# Sep 26, 2012
-# 64-bit ints, plus significantly better floating-point code.
-# Interesting details:
-# Generally something in the 0-10% slower range, some (binary tree) more
-# Floating-point noticeably faster:
-# nbody -25%
-# mandelbrot -37% relative to Go 1.
-# Other:
-# regex-dna +47%
-fasta -n 25000000
- gcc -O2 fasta.c 1.43u 0.03s 1.46r
- gccgo -O2 fasta.go 1.47u 0.00s 1.47r
- gc fasta 1.78u 0.01s 1.80r
- gc_B fasta 1.76u 0.00s 1.76r
-
-reverse-complement < output-of-fasta-25000000
- gcc -O2 reverse-complement.c 1.14u 0.39s 11.19r
- gccgo -O2 reverse-complement.go 0.91u 0.17s 1.09r
- gc reverse-complement 1.12u 0.18s 1.31r
- gc_B reverse-complement 1.12u 0.15s 1.28r
-
-nbody -n 50000000
- gcc -O2 nbody.c -lm 13.02u 0.00s 13.05r
- gccgo -O2 nbody.go 13.90u 0.00s 13.93r
- gc nbody 17.05u 0.00s 17.09r
- gc_B nbody 16.30u 0.00s 16.34r
-
-binary-tree 15 # too slow to use 20
- gcc -O2 binary-tree.c -lm 0.61u 0.00s 0.61r
- gccgo -O2 binary-tree.go 1.24u 0.04s 1.29r
- gccgo -O2 binary-tree-freelist.go 0.21u 0.01s 0.22r
- gc binary-tree 1.93u 0.02s 1.96r
- gc binary-tree-freelist 0.32u 0.00s 0.33r
-
-fannkuch 12
- gcc -O2 fannkuch.c 45.19u 0.00s 45.29r
- gccgo -O2 fannkuch.go 60.32u 0.00s 60.45r
- gccgo -O2 fannkuch-parallel.go 185.59u 0.00s 59.49r
- gc fannkuch 72.14u 0.00s 72.30r
- gc fannkuch-parallel 172.54u 0.00s 43.59r
- gc_B fannkuch 53.55u 0.00s 53.67r
-
-regex-dna 100000
- gcc -O2 regex-dna.c -lpcre 0.47u 0.00s 0.47r
- gccgo -O2 regex-dna.go 6.49u 0.05s 6.56r
- gccgo -O2 regex-dna-parallel.go 14.60u 0.67s 4.42r
- gc regex-dna 3.91u 0.00s 3.92r
- gc regex-dna-parallel 4.01u 0.03s 1.56r
- gc_B regex-dna 3.91u 0.00s 3.92r
-
-spectral-norm 5500
- gcc -O2 spectral-norm.c -lm 15.85u 0.00s 15.89r
- gccgo -O2 spectral-norm.go 15.86u 0.00s 15.89r
- gc spectral-norm 19.72u 0.00s 19.76r
- gc_B spectral-norm 19.68u 0.01s 19.74r
-
-k-nucleotide 1000000
- gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lglib-2.0 4.90u 0.01s 4.93r
- gccgo -O2 k-nucleotide.go 4.78u 0.01s 4.80r
- gccgo -O2 k-nucleotide-parallel.go 6.49u 0.02s 2.18r
- gc k-nucleotide 9.05u 0.02s 9.09r
- gc k-nucleotide-parallel 9.27u 0.01s 3.29r
- gc_B k-nucleotide 8.95u 0.03s 9.00r
-
-mandelbrot 16000
- gcc -O2 mandelbrot.c 36.11u 0.00s 36.19r
- gccgo -O2 mandelbrot.go 43.67u 0.00s 43.77r
- gc mandelbrot 38.57u 0.00s 38.66r
- gc_B mandelbrot 38.59u 0.00s 38.68r
-
-meteor 2098
- gcc -O2 meteor-contest.c 0.09u 0.00s 0.09r
- gccgo -O2 meteor-contest.go 0.09u 0.00s 0.09r
- gc meteor-contest 0.13u 0.00s 0.14r
- gc_B meteor-contest 0.12u 0.00s 0.13r
-
-pidigits 10000
- gcc -O2 pidigits.c -lgmp 2.26u 0.00s 2.27r
- gccgo -O2 pidigits.go 9.05u 0.00s 9.07r
- gc pidigits 2.88u 0.02s 2.90r
- gc_B pidigits 2.89u 0.00s 2.90r
-
-threadring 50000000
- gcc -O2 threadring.c -lpthread 37.30u 327.81s 289.28r
- gccgo -O2 threadring.go 42.83u 26.15s 69.14r
- gc threadring 13.00u 0.00s 13.03r
-
-chameneos 6000000
- gcc -O2 chameneosredux.c -lpthread 8.80u 71.67s 12.19r
- gccgo -O2 chameneosredux.go 11.28u 6.68s 18.00r
- gc chameneosredux 6.94u 0.00s 6.96r
-
-# May 23, 2013
-# Go 1.1, which includes precise GC, new scheduler, faster maps.
-# 20%-ish speedups across many benchmarks.
-# gccgo showing significant improvement (even though it's not yet up to Go 1.1)
-#
-# Standouts:
-# fannkuch, regex-dna, k-nucleotide, threadring, chameneos
-
-fasta -n 25000000
- gcc -m64 -O2 fasta.c 1.54u 0.01s 1.55r
- gccgo -O2 fasta.go 1.42u 0.00s 1.43r
- gc fasta 1.50u 0.01s 1.52r # -16%
- gc_B fasta 1.46u 0.00s 1.46r # -17%
-
-reverse-complement < output-of-fasta-25000000
- gcc -m64 -O2 reverse-complement.c 0.87u 0.37s 4.36r
- gccgo -O2 reverse-complement.go 0.77u 0.15s 0.93r # -15%
- gc reverse-complement 0.99u 0.12s 1.12r # -15%
- gc_B reverse-complement 0.85u 0.17s 1.02r # -21%
-
-nbody -n 50000000
- gcc -m64 -O2 nbody.c -lm 13.50u 0.00s 13.53r
- gccgo -O2 nbody.go 13.98u 0.01s 14.02r
- gc nbody 16.63u 0.01s 16.67r
- gc_B nbody 15.74u 0.00s 15.76r
-
-binary-tree 15 # too slow to use 20
- gcc -m64 -O2 binary-tree.c -lm 0.61u 0.00s 0.61r
- gccgo -O2 binary-tree.go 1.11u 0.01s 1.12r # -13%
- gccgo -O2 binary-tree-freelist.go 0.22u 0.01s 0.23r
- gc binary-tree 1.83u 0.02s 1.83r # -7%
- gc binary-tree-freelist 0.32u 0.00s 0.32r
-
-fannkuch 12
- gcc -m64 -O2 fannkuch.c 45.56u 0.00s 45.67r
- gccgo -O2 fannkuch.go 57.71u 0.00s 57.85r # -4%
- gccgo -O2 fannkuch-parallel.go 146.31u 0.00s 37.50r #-37%
- gc fannkuch 70.06u 0.03s 70.17r # -3%
- gc fannkuch-parallel 131.88u 0.06s 33.59r # -23%
- gc_B fannkuch 45.55u 0.02s 45.63r # -15%
-
-regex-dna 100000
- gcc -m64 -O2 regex-dna.c -lpcre 0.44u 0.01s 0.45r
- gccgo -O2 regex-dna.go 5.59u 0.00s 5.61r # -14%
- gccgo -O2 regex-dna-parallel.go 10.85u 0.30s 3.34r # -24%
- gc regex-dna 2.23u 0.01s 2.25r # -43%
- gc regex-dna-parallel 2.35u 0.00s 0.93r # -40%
- gc_B regex-dna 2.24u 0.01s 2.25r # -43%
-
-spectral-norm 5500
- gcc -m64 -O2 spectral-norm.c -lm 14.84u 0.00s 14.88r
- gccgo -O2 spectral-norm.go 15.33u 0.00s 15.37r
- gc spectral-norm 16.75u 0.02s 16.79r # -15%
- gc_B spectral-norm 16.77u 0.01s 16.79r # -15%
-
-k-nucleotide 1000000
- gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0 4.50u 0.00s 4.52r
- gccgo -O2 k-nucleotide.go 3.72u 0.04s 3.77r # -21%
- gccgo -O2 k-nucleotide-parallel.go 3.88u 0.03s 1.42r # -35%
- gc k-nucleotide 6.32u 0.01s 6.33r # -31%
- gc k-nucleotide-parallel 6.47u 0.05s 2.13r # -33%
- gc_B k-nucleotide 6.45u 0.01s 6.47r # - 28%
-
-mandelbrot 16000
- gcc -m64 -O2 mandelbrot.c 36.03u 0.00s 36.11r
- gccgo -O2 mandelbrot.go 37.61u 0.00s 37.74r # -14%
- gc mandelbrot 38.19u 0.05s 38.29r
- gc_B mandelbrot 38.19u 0.03s 38.26r
-
-meteor 2098
- gcc -m64 -O2 meteor-contest.c 0.08u 0.00s 0.08r
- gccgo -O2 meteor-contest.go 0.09u 0.01s 0.10r
- gc meteor-contest 0.12u 0.00s 0.12r # -15% although perhaps just noise
- gc_B meteor-contest 0.11u 0.00s 0.12r # -8% although perhaps just noise
-
-pidigits 10000
- gcc -m64 -O2 pidigits.c -lgmp 2.27u 0.00s 2.28r
- gccgo -O2 pidigits.go 8.95u 0.02s 8.99r
- gc pidigits 2.88u 0.14s 2.91r
- gc_B pidigits 2.92u 0.10s 2.91r
-
-threadring 50000000
- gcc -m64 -O2 threadring.c -lpthread 14.75u 167.88s 212.23r
- gccgo -O2 threadring.go 36.72u 12.08s 48.91r # -29%
- gc threadring 10.93u 0.01s 10.95r # -16%
-
-chameneos 6000000
- gcc -m64 -O2 chameneosredux.c -lpthread 8.89u 56.62s 9.75r
- gccgo -O2 chameneosredux.go 9.48u 2.48s 11.99r # -33%
- gc chameneosredux 5.80u 0.00s 5.81r # -16%
-
diff --git a/gcc/testsuite/go.test/test/bench/shootout/timing.sh b/gcc/testsuite/go.test/test/bench/shootout/timing.sh
deleted file mode 100755
index 2db895c..0000000
--- a/gcc/testsuite/go.test/test/bench/shootout/timing.sh
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-set -e
-
-eval $(go tool dist env)
-O=$GOCHAR
-GC="go tool ${O}g"
-LD="go tool ${O}l"
-
-gccm=""
-case "$O" in
-8)
- gccm=-m32;;
-6)
- gccm=-m64;;
-esac
-
-PATH=.:$PATH
-
-havegccgo=false
-if which gccgo >/dev/null 2>&1
-then
- havegccgo=true
-fi
-
-mode=run
-case X"$1" in
-X-test)
- mode=test
- shift
-esac
-
-gc() {
- $GC $1.go; $LD $1.$O
-}
-
-gc_B() {
- $GC -B $1.go; $LD $1.$O
-}
-
-runonly() {
- if [ $mode = run ]
- then
- "$@"
- fi
-}
-
-run() {
- if [ $mode = test ]
- then
- if echo $1 | grep -q '^gc '
- then
- $1 # compile the program
- program=$(echo $1 | sed 's/gc //')
- shift
- echo $program
- $1 <fasta-1000.out > /tmp/$$
- case $program in
- chameneosredux)
- # exact numbers may vary but non-numbers should match
- grep -v '[0-9]' /tmp/$$ > /tmp/$$x
- grep -v '[0-9]' chameneosredux.txt > /tmp/$$y
- cmp /tmp/$$x /tmp/$$y
- rm -f /tmp/$$ /tmp/$$x /tmp/$$y
- ;;
- *)
- cmp /tmp/$$ $program.txt
- rm -f /tmp/$$
- esac
- fi
- return
- fi
- if ! $havegccgo && echo $1 | grep -q '^gccgo '
- then
- return
- fi
- echo -n ' '$1' '
- $1
- shift
-
- echo $((time -p $* >/dev/null) 2>&1) | awk '{print $4 "u " $6 "s " $2 "r"}'
-}
-
-fasta() {
- runonly echo 'fasta -n 25000000'
- run "gcc $gccm -O2 fasta.c" a.out 25000000
- run 'gccgo -O2 fasta.go' a.out -n 25000000 #commented out until WriteString is in bufio
- run 'gc fasta' $O.out -n 25000000
- run 'gc_B fasta' $O.out -n 25000000
-}
-
-revcomp() {
- runonly gcc -O2 fasta.c
- runonly a.out 25000000 > x
- runonly echo 'reverse-complement < output-of-fasta-25000000'
- run "gcc $gccm -O2 reverse-complement.c" a.out < x
- run 'gccgo -O2 reverse-complement.go' a.out < x
- run 'gc reverse-complement' $O.out < x
- run 'gc_B reverse-complement' $O.out < x
- rm x
-}
-
-nbody() {
- runonly echo 'nbody -n 50000000'
- run "gcc $gccm -O2 nbody.c -lm" a.out 50000000
- run 'gccgo -O2 nbody.go' a.out -n 50000000
- run 'gc nbody' $O.out -n 50000000
- run 'gc_B nbody' $O.out -n 50000000
-}
-
-binarytree() {
- runonly echo 'binary-tree 15 # too slow to use 20'
- run "gcc $gccm -O2 binary-tree.c -lm" a.out 15
- run 'gccgo -O2 binary-tree.go' a.out -n 15
- run 'gccgo -O2 binary-tree-freelist.go' a.out -n 15
- run 'gc binary-tree' $O.out -n 15
- run 'gc binary-tree-freelist' $O.out -n 15
-}
-
-fannkuch() {
- runonly echo 'fannkuch 12'
- run "gcc $gccm -O2 fannkuch.c" a.out 12
- run 'gccgo -O2 fannkuch.go' a.out -n 12
- run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12
- run 'gc fannkuch' $O.out -n 12
- run 'gc fannkuch-parallel' $O.out -n 12
- run 'gc_B fannkuch' $O.out -n 12
-}
-
-regexdna() {
- runonly gcc -O2 fasta.c
- runonly a.out 100000 > x
- runonly echo 'regex-dna 100000'
- run "gcc $gccm -O2 regex-dna.c -lpcre" a.out <x
- run 'gccgo -O2 regex-dna.go' a.out <x
- run 'gccgo -O2 regex-dna-parallel.go' a.out <x
- run 'gc regex-dna' $O.out <x
- run 'gc regex-dna-parallel' $O.out <x
- run 'gc_B regex-dna' $O.out <x
- rm x
-}
-
-spectralnorm() {
- runonly echo 'spectral-norm 5500'
- run "gcc $gccm -O2 spectral-norm.c -lm" a.out 5500
- run 'gccgo -O2 spectral-norm.go' a.out -n 5500
- run 'gc spectral-norm' $O.out -n 5500
- run 'gc_B spectral-norm' $O.out -n 5500
-}
-
-knucleotide() {
- runonly gcc -O2 fasta.c
- runonly a.out 1000000 > x # should be using 25000000
- runonly echo 'k-nucleotide 1000000'
- if [ $mode = run ]; then
- run "gcc -O2 k-nucleotide.c $(pkg-config glib-2.0 --cflags --libs)" a.out <x
- fi
- run 'gccgo -O2 k-nucleotide.go' a.out <x
- run 'gccgo -O2 k-nucleotide-parallel.go' a.out <x
- run 'gc k-nucleotide' $O.out <x
- run 'gc k-nucleotide-parallel' $O.out <x
- run 'gc_B k-nucleotide' $O.out <x
- rm x
-}
-
-mandelbrot() {
- runonly echo 'mandelbrot 16000'
- run "gcc $gccm -O2 mandelbrot.c" a.out 16000
- run 'gccgo -O2 mandelbrot.go' a.out -n 16000
- run 'gc mandelbrot' $O.out -n 16000
- run 'gc_B mandelbrot' $O.out -n 16000
-}
-
-meteor() {
- runonly echo 'meteor 2098'
- run "gcc $gccm -O2 meteor-contest.c" a.out 2098
- run 'gccgo -O2 meteor-contest.go' a.out -n 2098
- run 'gc meteor-contest' $O.out -n 2098
- run 'gc_B meteor-contest' $O.out -n 2098
-}
-
-pidigits() {
- runonly echo 'pidigits 10000'
- run "gcc $gccm -O2 pidigits.c -lgmp" a.out 10000
- run 'gccgo -O2 pidigits.go' a.out -n 10000
- run 'gc pidigits' $O.out -n 10000
- run 'gc_B pidigits' $O.out -n 10000
-}
-
-threadring() {
- runonly echo 'threadring 50000000'
- run "gcc $gccm -O2 threadring.c -lpthread" a.out 50000000
- run 'gccgo -O2 threadring.go' a.out -n 50000000
- run 'gc threadring' $O.out -n 50000000
-}
-
-chameneos() {
- runonly echo 'chameneos 6000000'
- run "gcc $gccm -O2 chameneosredux.c -lpthread" a.out 6000000
- run 'gccgo -O2 chameneosredux.go' a.out 6000000
- run 'gc chameneosredux' $O.out 6000000
-}
-
-case $# in
-0)
- run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring chameneos"
- ;;
-*)
- run=$*
-esac
-
-for i in $run
-do
- $i
- runonly echo
-done
diff --git a/gcc/testsuite/go.test/test/blank1.go b/gcc/testsuite/go.test/test/blank1.go
index b60f9e1..70e01b1 100644
--- a/gcc/testsuite/go.test/test/blank1.go
+++ b/gcc/testsuite/go.test/test/blank1.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test that incorrect uses of the blank identifer are caught.
+// Test that incorrect uses of the blank identifier are caught.
// Does not compile.
package _ // ERROR "invalid package name"
@@ -13,6 +13,10 @@ var t struct {
_ int
}
+func (x int) _() { // ERROR "methods on non-local type"
+ println(x)
+}
+
type T struct {
_ []int
}
diff --git a/gcc/testsuite/go.test/test/bombad.go b/gcc/testsuite/go.test/test/bombad.go
index b894d9b..6b79a98 100644
--- a/gcc/testsuite/go.test/test/bombad.go
+++ b/gcc/testsuite/go.test/test/bombad.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/bounds.go b/gcc/testsuite/go.test/test/bounds.go
index 50f7ad7..aa1d51b 100644
--- a/gcc/testsuite/go.test/test/bounds.go
+++ b/gcc/testsuite/go.test/test/bounds.go
@@ -1,6 +1,6 @@
// errorcheck -0 -m -l
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,23 +12,23 @@ package foo
var (
s []int
- a1 [1]int
- a1k [1000]int
+ a1 [1]int
+ a1k [1000]int
a100k [100000]int
- p1 *[1]int
- p1k *[1000]int
+ p1 *[1]int
+ p1k *[1000]int
p100k *[100000]int
- i int
- ui uint
- i8 int8
- ui8 uint8
- i16 int16
+ i int
+ ui uint
+ i8 int8
+ ui8 uint8
+ i16 int16
ui16 uint16
- i32 int32
+ i32 int32
ui32 uint32
- i64 int64
+ i64 int64
ui64 uint64
)
@@ -61,11 +61,11 @@ func main() {
// Unsigned 8-bit numbers don't need checks for len >= 2⁸.
use(s[ui8])
use(a1[ui8])
- use(a1k[ui8]) // ERROR "index bounds check elided"
- use(a100k[ui8]) // ERROR "index bounds check elided"
+ use(a1k[ui8]) // ERROR "index bounds check elided"
+ use(a100k[ui8]) // ERROR "index bounds check elided"
use(p1[ui8])
- use(p1k[ui8]) // ERROR "index bounds check elided"
- use(p100k[ui8]) // ERROR "index bounds check elided"
+ use(p1k[ui8]) // ERROR "index bounds check elided"
+ use(p100k[ui8]) // ERROR "index bounds check elided"
use(s[i16])
use(a1[i16])
@@ -79,10 +79,10 @@ func main() {
use(s[ui16])
use(a1[ui16])
use(a1k[ui16])
- use(a100k[ui16]) // ERROR "index bounds check elided"
+ use(a100k[ui16]) // ERROR "index bounds check elided"
use(p1[ui16])
use(p1k[ui16])
- use(p100k[ui16]) // ERROR "index bounds check elided"
+ use(p100k[ui16]) // ERROR "index bounds check elided"
use(s[i32])
use(a1[i32])
@@ -128,11 +128,11 @@ func main() {
use(s[ui%999])
use(a1[ui%999])
- use(a1k[ui%999]) // ERROR "index bounds check elided"
- use(a100k[ui%999]) // ERROR "index bounds check elided"
+ use(a1k[ui%999]) // ERROR "index bounds check elided"
+ use(a100k[ui%999]) // ERROR "index bounds check elided"
use(p1[ui%999])
- use(p1k[ui%999]) // ERROR "index bounds check elided"
- use(p100k[ui%999]) // ERROR "index bounds check elided"
+ use(p1k[ui%999]) // ERROR "index bounds check elided"
+ use(p100k[ui%999]) // ERROR "index bounds check elided"
use(s[i%1000])
use(a1[i%1000])
@@ -144,11 +144,11 @@ func main() {
use(s[ui%1000])
use(a1[ui%1000])
- use(a1k[ui%1000]) // ERROR "index bounds check elided"
- use(a100k[ui%1000]) // ERROR "index bounds check elided"
+ use(a1k[ui%1000]) // ERROR "index bounds check elided"
+ use(a100k[ui%1000]) // ERROR "index bounds check elided"
use(p1[ui%1000])
- use(p1k[ui%1000]) // ERROR "index bounds check elided"
- use(p100k[ui%1000]) // ERROR "index bounds check elided"
+ use(p1k[ui%1000]) // ERROR "index bounds check elided"
+ use(p100k[ui%1000]) // ERROR "index bounds check elided"
use(s[i%1001])
use(a1[i%1001])
@@ -161,45 +161,59 @@ func main() {
use(s[ui%1001])
use(a1[ui%1001])
use(a1k[ui%1001])
- use(a100k[ui%1001]) // ERROR "index bounds check elided"
+ use(a100k[ui%1001]) // ERROR "index bounds check elided"
use(p1[ui%1001])
use(p1k[ui%1001])
- use(p100k[ui%1001]) // ERROR "index bounds check elided"
+ use(p100k[ui%1001]) // ERROR "index bounds check elided"
// Bitwise and truncates the maximum value to the mask value.
// The result (for a positive mask) cannot be negative, so elision
// applies to both signed and unsigned indexes.
use(s[i&999])
use(a1[i&999])
- use(a1k[i&999]) // ERROR "index bounds check elided"
- use(a100k[i&999]) // ERROR "index bounds check elided"
+ use(a1k[i&999]) // ERROR "index bounds check elided"
+ use(a100k[i&999]) // ERROR "index bounds check elided"
use(p1[i&999])
- use(p1k[i&999]) // ERROR "index bounds check elided"
- use(p100k[i&999]) // ERROR "index bounds check elided"
+ use(p1k[i&999]) // ERROR "index bounds check elided"
+ use(p100k[i&999]) // ERROR "index bounds check elided"
use(s[ui&999])
use(a1[ui&999])
- use(a1k[ui&999]) // ERROR "index bounds check elided"
- use(a100k[ui&999]) // ERROR "index bounds check elided"
+ use(a1k[ui&999]) // ERROR "index bounds check elided"
+ use(a100k[ui&999]) // ERROR "index bounds check elided"
use(p1[ui&999])
- use(p1k[ui&999]) // ERROR "index bounds check elided"
- use(p100k[ui&999]) // ERROR "index bounds check elided"
+ use(p1k[ui&999]) // ERROR "index bounds check elided"
+ use(p100k[ui&999]) // ERROR "index bounds check elided"
use(s[i&1000])
use(a1[i&1000])
use(a1k[i&1000])
- use(a100k[i&1000]) // ERROR "index bounds check elided"
+ use(a100k[i&1000]) // ERROR "index bounds check elided"
use(p1[i&1000])
use(p1k[i&1000])
- use(p100k[i&1000]) // ERROR "index bounds check elided"
+ use(p100k[i&1000]) // ERROR "index bounds check elided"
use(s[ui&1000])
use(a1[ui&1000])
use(a1k[ui&1000])
- use(a100k[ui&1000]) // ERROR "index bounds check elided"
+ use(a100k[ui&1000]) // ERROR "index bounds check elided"
use(p1[ui&1000])
use(p1k[ui&1000])
- use(p100k[ui&1000]) // ERROR "index bounds check elided"
+ use(p100k[ui&1000]) // ERROR "index bounds check elided"
+
+ use(a1[i&^-1]) // ERROR "index bounds check elided"
+ use(a1[i&^0])
+ use(a1[i&^-2])
+ use(a1[i&^1])
+ use(a1k[i&^-1]) // ERROR "index bounds check elided"
+ use(a1k[i&^0])
+ use(a1k[i&^-2]) // ERROR "index bounds check elided"
+ use(a1k[i&^1])
+ use(a1k[i8&^0])
+ use(a1k[i8&^-128]) // ERROR "index bounds check elided"
+ use(a1k[ui8&^1]) // ERROR "index bounds check elided"
+ use(a1k[ui16&^0xf000])
+ use(a1k[ui16&^0xff00]) // ERROR "index bounds check elided"
// Right shift cuts the effective number of bits in the index,
// but only for unsigned (signed stays negative).
@@ -214,10 +228,10 @@ func main() {
use(s[ui32>>22])
use(a1[ui32>>22])
use(a1k[ui32>>22])
- use(a100k[ui32>>22]) // ERROR "index bounds check elided"
+ use(a100k[ui32>>22]) // ERROR "index bounds check elided"
use(p1[ui32>>22])
use(p1k[ui32>>22])
- use(p100k[ui32>>22]) // ERROR "index bounds check elided"
+ use(p100k[ui32>>22]) // ERROR "index bounds check elided"
use(s[i32>>23])
use(a1[i32>>23])
@@ -229,11 +243,11 @@ func main() {
use(s[ui32>>23])
use(a1[ui32>>23])
- use(a1k[ui32>>23]) // ERROR "index bounds check elided"
- use(a100k[ui32>>23]) // ERROR "index bounds check elided"
+ use(a1k[ui32>>23]) // ERROR "index bounds check elided"
+ use(a100k[ui32>>23]) // ERROR "index bounds check elided"
use(p1[ui32>>23])
- use(p1k[ui32>>23]) // ERROR "index bounds check elided"
- use(p100k[ui32>>23]) // ERROR "index bounds check elided"
+ use(p1k[ui32>>23]) // ERROR "index bounds check elided"
+ use(p100k[ui32>>23]) // ERROR "index bounds check elided"
// Division cuts the range like right shift does.
use(s[i/1e6])
@@ -263,7 +277,7 @@ func main() {
use(p1[ui/1e7])
}
-var sum int
+var sum int
func use(x int) {
sum += x
diff --git a/gcc/testsuite/go.test/test/bugs/bug395.go b/gcc/testsuite/go.test/test/bugs/bug395.go
deleted file mode 100644
index 4632dcd..0000000
--- a/gcc/testsuite/go.test/test/bugs/bug395.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// echo bug395 is broken # takes 90+ seconds to break
-// # $G $D/$F.go || echo bug395
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Issue 1909
-// Would OOM due to exponential recursion on Foo's expanded methodset in nodefmt
-package test
-
-type Foo interface {
- Bar() interface {
- Foo
- }
- Baz() interface {
- Foo
- }
- Bug() interface {
- Foo
- }
-}
diff --git a/gcc/testsuite/go.test/test/bugs/placeholder b/gcc/testsuite/go.test/test/bugs/placeholder
deleted file mode 100644
index b816d34..0000000
--- a/gcc/testsuite/go.test/test/bugs/placeholder
+++ /dev/null
@@ -1,2 +0,0 @@
-This file keeps Mercurial from deleting the directory
-when there are no known bugs.
diff --git a/gcc/testsuite/go.test/test/chan/doubleselect.go b/gcc/testsuite/go.test/test/chan/doubleselect.go
index 6be3faf..ff69dbe 100644
--- a/gcc/testsuite/go.test/test/chan/doubleselect.go
+++ b/gcc/testsuite/go.test/test/chan/doubleselect.go
@@ -61,6 +61,7 @@ func recver(in <-chan int) {
func main() {
runtime.GOMAXPROCS(2)
+ flag.Parse()
c1 := make(chan int)
c2 := make(chan int)
c3 := make(chan int)
diff --git a/gcc/testsuite/go.test/test/chan/fifo.go b/gcc/testsuite/go.test/test/chan/fifo.go
index 70d20b3..0001bcf 100644
--- a/gcc/testsuite/go.test/test/chan/fifo.go
+++ b/gcc/testsuite/go.test/test/chan/fifo.go
@@ -54,4 +54,3 @@ func main() {
AsynchFifo()
SynchFifo()
}
-
diff --git a/gcc/testsuite/go.test/test/chan/perm.go b/gcc/testsuite/go.test/test/chan/perm.go
index 7e152c5..0c96d92 100644
--- a/gcc/testsuite/go.test/test/chan/perm.go
+++ b/gcc/testsuite/go.test/test/chan/perm.go
@@ -24,19 +24,23 @@ func main() {
cr = cs // ERROR "illegal types|incompatible|cannot"
cs = cr // ERROR "illegal types|incompatible|cannot"
- c <- 0 // ok
- <-c // ok
- x, ok := <-c // ok
+ var n int
+ <-n // ERROR "receive from non-chan|expected channel"
+ n <- 2 // ERROR "send to non-chan|must be channel"
+
+ c <- 0 // ok
+ <-c // ok
+ x, ok := <-c // ok
_, _ = x, ok
- cr <- 0 // ERROR "send"
- <-cr // ok
- x, ok = <-cr // ok
+ cr <- 0 // ERROR "send"
+ <-cr // ok
+ x, ok = <-cr // ok
_, _ = x, ok
- cs <- 0 // ok
- <-cs // ERROR "receive"
- x, ok = <-cs // ERROR "receive"
+ cs <- 0 // ok
+ <-cs // ERROR "receive"
+ x, ok = <-cs // ERROR "receive"
_, _ = x, ok
select {
@@ -53,10 +57,14 @@ func main() {
_ = x
}
- for _ = range cs {// ERROR "receive"
+ for _ = range cs { // ERROR "receive"
+ }
+
+ for range cs { // ERROR "receive"
}
close(c)
close(cs)
- close(cr) // ERROR "receive"
+ close(cr) // ERROR "receive"
+ close(n) // ERROR "invalid operation.*non-chan type|must be channel"
}
diff --git a/gcc/testsuite/go.test/test/chan/powser1.go b/gcc/testsuite/go.test/test/chan/powser1.go
index 6bf2a91..e999dde 100644
--- a/gcc/testsuite/go.test/test/chan/powser1.go
+++ b/gcc/testsuite/go.test/test/chan/powser1.go
@@ -11,18 +11,18 @@
// coefficients. A denominator of zero signifies the end.
// Original code in Newsqueak by Doug McIlroy.
// See Squinting at Power Series by Doug McIlroy,
-// http://www.cs.bell-labs.com/who/rsc/thread/squint.pdf
+// https://swtch.com/~rsc/thread/squint.pdf
package main
import "os"
-type rat struct {
- num, den int64 // numerator, denominator
+type rat struct {
+ num, den int64 // numerator, denominator
}
func (u rat) pr() {
- if u.den==1 {
+ if u.den == 1 {
print(u.num)
} else {
print(u.num, "/", u.den)
@@ -35,12 +35,12 @@ func (u rat) eq(c rat) bool {
}
type dch struct {
- req chan int
- dat chan rat
+ req chan int
+ dat chan rat
nam int
}
-type dch2 [2] *dch
+type dch2 [2]*dch
var chnames string
var chnameserial int
@@ -77,17 +77,17 @@ func mkdch2() *dch2 {
// a signal on the release-wait channel tells the next newer
// generation to begin servicing out[1].
-func dosplit(in *dch, out *dch2, wait chan int ) {
- both := false // do not service both channels
+func dosplit(in *dch, out *dch2, wait chan int) {
+ both := false // do not service both channels
select {
case <-out[0].req:
-
+
case <-wait:
both = true
select {
case <-out[0].req:
-
+
case <-out[1].req:
out[0], out[1] = out[1], out[0]
}
@@ -95,7 +95,7 @@ func dosplit(in *dch, out *dch2, wait chan int ) {
seqno++
in.req <- seqno
- release := make(chan int)
+ release := make(chan int)
go dosplit(in, out, release)
dat := <-in.dat
out[0].dat <- dat
@@ -128,17 +128,19 @@ func get(in *dch) rat {
func getn(in []*dch) []rat {
n := len(in)
- if n != 2 { panic("bad n in getn") }
- req := new([2] chan int)
- dat := new([2] chan rat)
+ if n != 2 {
+ panic("bad n in getn")
+ }
+ req := new([2]chan int)
+ dat := new([2]chan rat)
out := make([]rat, 2)
var i int
var it rat
- for i=0; i<n; i++ {
+ for i = 0; i < n; i++ {
req[i] = in[i].req
dat[i] = nil
}
- for n=2*n; n>0; n-- {
+ for n = 2 * n; n > 0; n-- {
seqno++
select {
@@ -178,8 +180,8 @@ func repeat(dat rat, out *dch) {
}
}
-type PS *dch // power series
-type PS2 *[2] PS // pair of power series
+type PS *dch // power series
+type PS2 *[2]PS // pair of power series
var Ones PS
var Twos PS
@@ -200,23 +202,27 @@ func mkPS2() *dch2 {
// Integer gcd; needed for rational arithmetic
-func gcd (u, v int64) int64 {
- if u < 0 { return gcd(-u, v) }
- if u == 0 { return v }
+func gcd(u, v int64) int64 {
+ if u < 0 {
+ return gcd(-u, v)
+ }
+ if u == 0 {
+ return v
+ }
return gcd(v%u, u)
}
// Make a rational from two ints and from one int
func i2tor(u, v int64) rat {
- g := gcd(u,v)
+ g := gcd(u, v)
var r rat
if v > 0 {
- r.num = u/g
- r.den = v/g
+ r.num = u / g
+ r.den = v / g
} else {
- r.num = -u/g
- r.den = -v/g
+ r.num = -u / g
+ r.den = -v / g
}
return r
}
@@ -228,29 +234,30 @@ func itor(u int64) rat {
var zero rat
var one rat
-
// End mark and end test
var finis rat
func end(u rat) int64 {
- if u.den==0 { return 1 }
+ if u.den == 0 {
+ return 1
+ }
return 0
}
// Operations on rationals
func add(u, v rat) rat {
- g := gcd(u.den,v.den)
- return i2tor(u.num*(v.den/g)+v.num*(u.den/g),u.den*(v.den/g))
+ g := gcd(u.den, v.den)
+ return i2tor(u.num*(v.den/g)+v.num*(u.den/g), u.den*(v.den/g))
}
func mul(u, v rat) rat {
- g1 := gcd(u.num,v.den)
- g2 := gcd(u.den,v.num)
+ g1 := gcd(u.num, v.den)
+ g2 := gcd(u.den, v.num)
var r rat
- r.num = (u.num/g1)*(v.num/g2)
- r.den = (u.den/g2)*(v.den/g1)
+ r.num = (u.num / g1) * (v.num / g2)
+ r.den = (u.den / g2) * (v.den / g1)
return r
}
@@ -262,23 +269,25 @@ func sub(u, v rat) rat {
return add(u, neg(v))
}
-func inv(u rat) rat { // invert a rat
- if u.num == 0 { panic("zero divide in inv") }
+func inv(u rat) rat { // invert a rat
+ if u.num == 0 {
+ panic("zero divide in inv")
+ }
return i2tor(u.den, u.num)
}
// print eval in floating point of PS at x=c to n terms
func evaln(c rat, U PS, n int) {
xn := float64(1)
- x := float64(c.num)/float64(c.den)
+ x := float64(c.num) / float64(c.den)
val := float64(0)
- for i:=0; i<n; i++ {
+ for i := 0; i < n; i++ {
u := get(U)
if end(u) != 0 {
break
}
- val = val + x * float64(u.num)/float64(u.den)
- xn = xn*x
+ val = val + x*float64(u.num)/float64(u.den)
+ xn = xn * x
}
print(val, "\n")
}
@@ -286,7 +295,7 @@ func evaln(c rat, U PS, n int) {
// Print n terms of a power series
func printn(U PS, n int) {
done := false
- for ; !done && n>0; n-- {
+ for ; !done && n > 0; n-- {
u := get(U)
if end(u) != 0 {
done = true
@@ -299,10 +308,14 @@ func printn(U PS, n int) {
// Evaluate n terms of power series U at x=c
func eval(c rat, U PS, n int) rat {
- if n==0 { return zero }
+ if n == 0 {
+ return zero
+ }
y := get(U)
- if end(y) != 0 { return zero }
- return add(y,mul(c,eval(c,U,n-1)))
+ if end(y) != 0 {
+ return zero
+ }
+ return add(y, mul(c, eval(c, U, n-1)))
}
// Power-series constructors return channels on which power
@@ -313,7 +326,7 @@ func eval(c rat, U PS, n int) rat {
func Split(U PS) *dch2 {
UU := mkdch2()
- go split(U,UU)
+ go split(U, UU)
return UU
}
@@ -324,16 +337,16 @@ func Add(U, V PS) PS {
var uv []rat
for {
<-Z.req
- uv = get2(U,V)
- switch end(uv[0])+2*end(uv[1]) {
+ uv = get2(U, V)
+ switch end(uv[0]) + 2*end(uv[1]) {
case 0:
Z.dat <- add(uv[0], uv[1])
case 1:
Z.dat <- uv[1]
- copy(V,Z)
+ copy(V, Z)
case 2:
Z.dat <- uv[0]
- copy(U,Z)
+ copy(U, Z)
case 3:
Z.dat <- finis
}
@@ -343,7 +356,7 @@ func Add(U, V PS) PS {
}
// Multiply a power series by a constant
-func Cmul(c rat,U PS) PS {
+func Cmul(c rat, U PS) PS {
Z := mkPS()
go func() {
done := false
@@ -353,7 +366,7 @@ func Cmul(c rat,U PS) PS {
if end(u) != 0 {
done = true
} else {
- Z.dat <- mul(c,u)
+ Z.dat <- mul(c, u)
}
}
Z.dat <- finis
@@ -372,8 +385,10 @@ func Sub(U, V PS) PS {
func Monmul(U PS, n int) PS {
Z := mkPS()
go func() {
- for ; n>0; n-- { put(zero,Z) }
- copy(U,Z)
+ for ; n > 0; n-- {
+ put(zero, Z)
+ }
+ copy(U, Z)
}()
return Z
}
@@ -381,25 +396,27 @@ func Monmul(U PS, n int) PS {
// Multiply by x
func Xmul(U PS) PS {
- return Monmul(U,1)
+ return Monmul(U, 1)
}
func Rep(c rat) PS {
Z := mkPS()
- go repeat(c,Z)
+ go repeat(c, Z)
return Z
}
// Monomial c*x^n
func Mon(c rat, n int) PS {
- Z:=mkPS()
+ Z := mkPS()
go func() {
- if(c.num!=0) {
- for ; n>0; n=n-1 { put(zero,Z) }
- put(c,Z)
+ if c.num != 0 {
+ for ; n > 0; n = n - 1 {
+ put(zero, Z)
+ }
+ put(c, Z)
}
- put(finis,Z)
+ put(finis, Z)
}()
return Z
}
@@ -407,8 +424,8 @@ func Mon(c rat, n int) PS {
func Shift(c rat, U PS) PS {
Z := mkPS()
go func() {
- put(c,Z)
- copy(U,Z)
+ put(c, Z)
+ copy(U, Z)
}()
return Z
}
@@ -440,20 +457,20 @@ func Poly(a []rat) PS {
// then UV = u*v + x*(u*VV+v*UU) + x*x*UU*VV
func Mul(U, V PS) PS {
- Z:=mkPS()
+ Z := mkPS()
go func() {
<-Z.req
- uv := get2(U,V)
- if end(uv[0])!=0 || end(uv[1]) != 0 {
+ uv := get2(U, V)
+ if end(uv[0]) != 0 || end(uv[1]) != 0 {
Z.dat <- finis
} else {
- Z.dat <- mul(uv[0],uv[1])
+ Z.dat <- mul(uv[0], uv[1])
UU := Split(U)
VV := Split(V)
- W := Add(Cmul(uv[0],VV[0]),Cmul(uv[1],UU[0]))
+ W := Add(Cmul(uv[0], VV[0]), Cmul(uv[1], UU[0]))
<-Z.req
Z.dat <- get(W)
- copy(Add(W,Mul(UU[1],VV[1])),Z)
+ copy(Add(W, Mul(UU[1], VV[1])), Z)
}
}()
return Z
@@ -462,18 +479,18 @@ func Mul(U, V PS) PS {
// Differentiate
func Diff(U PS) PS {
- Z:=mkPS()
+ Z := mkPS()
go func() {
<-Z.req
u := get(U)
if end(u) == 0 {
- done:=false
- for i:=1; !done; i++ {
+ done := false
+ for i := 1; !done; i++ {
u = get(U)
if end(u) != 0 {
done = true
} else {
- Z.dat <- mul(itor(int64(i)),u)
+ Z.dat <- mul(itor(int64(i)), u)
<-Z.req
}
}
@@ -484,16 +501,18 @@ func Diff(U PS) PS {
}
// Integrate, with const of integration
-func Integ(c rat,U PS) PS {
- Z:=mkPS()
+func Integ(c rat, U PS) PS {
+ Z := mkPS()
go func() {
- put(c,Z)
- done:=false
- for i:=1; !done; i++ {
+ put(c, Z)
+ done := false
+ for i := 1; !done; i++ {
<-Z.req
u := get(U)
- if end(u) != 0 { done= true }
- Z.dat <- mul(i2tor(1,int64(i)),u)
+ if end(u) != 0 {
+ done = true
+ }
+ Z.dat <- mul(i2tor(1, int64(i)), u)
}
Z.dat <- finis
}()
@@ -503,17 +522,17 @@ func Integ(c rat,U PS) PS {
// Binomial theorem (1+x)^c
func Binom(c rat) PS {
- Z:=mkPS()
+ Z := mkPS()
go func() {
n := 1
t := itor(1)
- for c.num!=0 {
- put(t,Z)
- t = mul(mul(t,c),i2tor(1,int64(n)))
- c = sub(c,one)
+ for c.num != 0 {
+ put(t, Z)
+ t = mul(mul(t, c), i2tor(1, int64(n)))
+ c = sub(c, one)
n++
}
- put(finis,Z)
+ put(finis, Z)
}()
return Z
}
@@ -527,14 +546,14 @@ func Binom(c rat) PS {
// ZZ = -UU*(z+x*ZZ)/u
func Recip(U PS) PS {
- Z:=mkPS()
+ Z := mkPS()
go func() {
- ZZ:=mkPS2()
+ ZZ := mkPS2()
<-Z.req
z := inv(get(U))
Z.dat <- z
- split(Mul(Cmul(neg(z),U),Shift(z,ZZ[0])),ZZ)
- copy(ZZ[1],Z)
+ split(Mul(Cmul(neg(z), U), Shift(z, ZZ[0])), ZZ)
+ copy(ZZ[1], Z)
}()
return Z
}
@@ -548,7 +567,7 @@ func Recip(U PS) PS {
func Exp(U PS) PS {
ZZ := mkPS2()
- split(Integ(one,Mul(ZZ[0],Diff(U))),ZZ)
+ split(Integ(one, Mul(ZZ[0], Diff(U))), ZZ)
return ZZ[1]
}
@@ -559,7 +578,7 @@ func Exp(U PS) PS {
// bug: a nonzero constant term is ignored
func Subst(U, V PS) PS {
- Z:= mkPS()
+ Z := mkPS()
go func() {
VV := Split(V)
<-Z.req
@@ -567,20 +586,20 @@ func Subst(U, V PS) PS {
Z.dat <- u
if end(u) == 0 {
if end(get(VV[0])) != 0 {
- put(finis,Z)
+ put(finis, Z)
} else {
- copy(Mul(VV[0],Subst(U,VV[1])),Z)
+ copy(Mul(VV[0], Subst(U, VV[1])), Z)
}
}
}()
return Z
}
-// Monomial Substition: U(c x^n)
+// Monomial Substitution: U(c x^n)
// Each Ui is multiplied by c^i and followed by n-1 zeros
func MonSubst(U PS, c0 rat, n int) PS {
- Z:= mkPS()
+ Z := mkPS()
go func() {
c := one
for {
@@ -601,14 +620,13 @@ func MonSubst(U PS, c0 rat, n int) PS {
return Z
}
-
func Init() {
chnameserial = -1
seqno = 0
chnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
zero = itor(0)
one = itor(1)
- finis = i2tor(1,0)
+ finis = i2tor(1, 0)
Ones = Rep(one)
Twos = Rep(itor(2))
}
@@ -627,7 +645,8 @@ func check(U PS, c rat, count int, str string) {
}
}
-const N=10
+const N = 10
+
func checka(U PS, a []rat, str string) {
for i := 0; i < N; i++ {
check(U, a[i], 1, str)
@@ -636,53 +655,64 @@ func checka(U PS, a []rat, str string) {
func main() {
Init()
- if len(os.Args) > 1 { // print
- print("Ones: "); printn(Ones, 10)
- print("Twos: "); printn(Twos, 10)
- print("Add: "); printn(Add(Ones, Twos), 10)
- print("Diff: "); printn(Diff(Ones), 10)
- print("Integ: "); printn(Integ(zero, Ones), 10)
- print("CMul: "); printn(Cmul(neg(one), Ones), 10)
- print("Sub: "); printn(Sub(Ones, Twos), 10)
- print("Mul: "); printn(Mul(Ones, Ones), 10)
- print("Exp: "); printn(Exp(Ones), 15)
- print("MonSubst: "); printn(MonSubst(Ones, neg(one), 2), 10)
- print("ATan: "); printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
- } else { // test
+ if len(os.Args) > 1 { // print
+ print("Ones: ")
+ printn(Ones, 10)
+ print("Twos: ")
+ printn(Twos, 10)
+ print("Add: ")
+ printn(Add(Ones, Twos), 10)
+ print("Diff: ")
+ printn(Diff(Ones), 10)
+ print("Integ: ")
+ printn(Integ(zero, Ones), 10)
+ print("CMul: ")
+ printn(Cmul(neg(one), Ones), 10)
+ print("Sub: ")
+ printn(Sub(Ones, Twos), 10)
+ print("Mul: ")
+ printn(Mul(Ones, Ones), 10)
+ print("Exp: ")
+ printn(Exp(Ones), 15)
+ print("MonSubst: ")
+ printn(MonSubst(Ones, neg(one), 2), 10)
+ print("ATan: ")
+ printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
+ } else { // test
check(Ones, one, 5, "Ones")
- check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
+ check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
check(Add(Ones, Twos), itor(3), 0, "Add Ones Twos") // 3 3 3 3 3
a := make([]rat, N)
d := Diff(Ones)
- for i:=0; i < N; i++ {
- a[i] = itor(int64(i+1))
+ for i := 0; i < N; i++ {
+ a[i] = itor(int64(i + 1))
}
- checka(d, a, "Diff") // 1 2 3 4 5
+ checka(d, a, "Diff") // 1 2 3 4 5
in := Integ(zero, Ones)
- a[0] = zero // integration constant
- for i:=1; i < N; i++ {
+ a[0] = zero // integration constant
+ for i := 1; i < N; i++ {
a[i] = i2tor(1, int64(i))
}
- checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
- check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
- check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
+ checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
+ check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
+ check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
m := Mul(Ones, Ones)
- for i:=0; i < N; i++ {
- a[i] = itor(int64(i+1))
+ for i := 0; i < N; i++ {
+ a[i] = itor(int64(i + 1))
}
- checka(m, a, "Mul") // 1 2 3 4 5
+ checka(m, a, "Mul") // 1 2 3 4 5
e := Exp(Ones)
a[0] = itor(1)
a[1] = itor(1)
- a[2] = i2tor(3,2)
- a[3] = i2tor(13,6)
- a[4] = i2tor(73,24)
- a[5] = i2tor(167,40)
- a[6] = i2tor(4051,720)
- a[7] = i2tor(37633,5040)
- a[8] = i2tor(43817,4480)
- a[9] = i2tor(4596553,362880)
- checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
+ a[2] = i2tor(3, 2)
+ a[3] = i2tor(13, 6)
+ a[4] = i2tor(73, 24)
+ a[5] = i2tor(167, 40)
+ a[6] = i2tor(4051, 720)
+ a[7] = i2tor(37633, 5040)
+ a[8] = i2tor(43817, 4480)
+ a[9] = i2tor(4596553, 362880)
+ checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
at := Integ(zero, MonSubst(Ones, neg(one), 2))
for c, i := 1, 0; i < N; i++ {
if i%2 == 0 {
@@ -692,20 +722,20 @@ func main() {
c *= -1
}
}
- checka(at, a, "ATan") // 0 -1 0 -1/3 0 -1/5
-/*
- t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
- a[0] = zero
- a[1] = itor(1)
- a[2] = zero
- a[3] = i2tor(1,3)
- a[4] = zero
- a[5] = i2tor(2,15)
- a[6] = zero
- a[7] = i2tor(17,315)
- a[8] = zero
- a[9] = i2tor(62,2835)
- checka(t, a, "Tan") // 0 1 0 1/3 0 2/15
-*/
+ checka(at, a, "ATan") // 0 -1 0 -1/3 0 -1/5
+ /*
+ t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
+ a[0] = zero
+ a[1] = itor(1)
+ a[2] = zero
+ a[3] = i2tor(1,3)
+ a[4] = zero
+ a[5] = i2tor(2,15)
+ a[6] = zero
+ a[7] = i2tor(17,315)
+ a[8] = zero
+ a[9] = i2tor(62,2835)
+ checka(t, a, "Tan") // 0 1 0 1/3 0 2/15
+ */
}
}
diff --git a/gcc/testsuite/go.test/test/chan/powser2.go b/gcc/testsuite/go.test/test/chan/powser2.go
index 33abd5c..72cbba8 100644
--- a/gcc/testsuite/go.test/test/chan/powser2.go
+++ b/gcc/testsuite/go.test/test/chan/powser2.go
@@ -15,14 +15,14 @@
// coefficients. A denominator of zero signifies the end.
// Original code in Newsqueak by Doug McIlroy.
// See Squinting at Power Series by Doug McIlroy,
-// http://www.cs.bell-labs.com/who/rsc/thread/squint.pdf
+// https://swtch.com/~rsc/thread/squint.pdf
package main
import "os"
-type rat struct {
- num, den int64 // numerator, denominator
+type rat struct {
+ num, den int64 // numerator, denominator
}
type item interface {
@@ -30,8 +30,8 @@ type item interface {
eq(c item) bool
}
-func (u *rat) pr(){
- if u.den==1 {
+func (u *rat) pr() {
+ if u.den == 1 {
print(u.num)
} else {
print(u.num, "/", u.den)
@@ -45,12 +45,12 @@ func (u *rat) eq(c item) bool {
}
type dch struct {
- req chan int
- dat chan item
+ req chan int
+ dat chan item
nam int
}
-type dch2 [2] *dch
+type dch2 [2]*dch
var chnames string
var chnameserial int
@@ -87,25 +87,25 @@ func mkdch2() *dch2 {
// a signal on the release-wait channel tells the next newer
// generation to begin servicing out[1].
-func dosplit(in *dch, out *dch2, wait chan int ){
- both := false // do not service both channels
+func dosplit(in *dch, out *dch2, wait chan int) {
+ both := false // do not service both channels
select {
case <-out[0].req:
-
+
case <-wait:
both = true
select {
case <-out[0].req:
-
+
case <-out[1].req:
- out[0],out[1] = out[1], out[0]
+ out[0], out[1] = out[1], out[0]
}
}
seqno++
in.req <- seqno
- release := make(chan int)
+ release := make(chan int)
go dosplit(in, out, release)
dat := <-in.dat
out[0].dat <- dat
@@ -117,13 +117,13 @@ func dosplit(in *dch, out *dch2, wait chan int ){
release <- 0
}
-func split(in *dch, out *dch2){
+func split(in *dch, out *dch2) {
release := make(chan int)
go dosplit(in, out, release)
release <- 0
}
-func put(dat item, out *dch){
+func put(dat item, out *dch) {
<-out.req
out.dat <- dat
}
@@ -137,21 +137,23 @@ func get(in *dch) *rat {
// Get one item from each of n demand channels
func getn(in []*dch) []item {
- n:=len(in)
- if n != 2 { panic("bad n in getn") }
- req := make([] chan int, 2)
- dat := make([] chan item, 2)
+ n := len(in)
+ if n != 2 {
+ panic("bad n in getn")
+ }
+ req := make([]chan int, 2)
+ dat := make([]chan item, 2)
out := make([]item, 2)
var i int
var it item
- for i=0; i<n; i++ {
+ for i = 0; i < n; i++ {
req[i] = in[i].req
dat[i] = nil
}
- for n=2*n; n>0; n-- {
+ for n = 2 * n; n > 0; n-- {
seqno++
- select{
+ select {
case req[0] <- seqno:
dat[0] = in[0].dat
req[0] = nil
@@ -171,25 +173,25 @@ func getn(in []*dch) []item {
// Get one item from each of 2 demand channels
-func get2(in0 *dch, in1 *dch) []item {
+func get2(in0 *dch, in1 *dch) []item {
return getn([]*dch{in0, in1})
}
-func copy(in *dch, out *dch){
+func copy(in *dch, out *dch) {
for {
<-out.req
out.dat <- get(in)
}
}
-func repeat(dat item, out *dch){
+func repeat(dat item, out *dch) {
for {
put(dat, out)
}
}
-type PS *dch // power series
-type PS2 *[2] PS // pair of power series
+type PS *dch // power series
+type PS2 *[2]PS // pair of power series
var Ones PS
var Twos PS
@@ -210,93 +212,100 @@ func mkPS2() *dch2 {
// Integer gcd; needed for rational arithmetic
-func gcd (u, v int64) int64{
- if u < 0 { return gcd(-u, v) }
- if u == 0 { return v }
+func gcd(u, v int64) int64 {
+ if u < 0 {
+ return gcd(-u, v)
+ }
+ if u == 0 {
+ return v
+ }
return gcd(v%u, u)
}
// Make a rational from two ints and from one int
-func i2tor(u, v int64) *rat{
- g := gcd(u,v)
+func i2tor(u, v int64) *rat {
+ g := gcd(u, v)
r := new(rat)
if v > 0 {
- r.num = u/g
- r.den = v/g
+ r.num = u / g
+ r.den = v / g
} else {
- r.num = -u/g
- r.den = -v/g
+ r.num = -u / g
+ r.den = -v / g
}
return r
}
-func itor(u int64) *rat{
+func itor(u int64) *rat {
return i2tor(u, 1)
}
var zero *rat
var one *rat
-
// End mark and end test
var finis *rat
func end(u *rat) int64 {
- if u.den==0 { return 1 }
+ if u.den == 0 {
+ return 1
+ }
return 0
}
// Operations on rationals
func add(u, v *rat) *rat {
- g := gcd(u.den,v.den)
- return i2tor(u.num*(v.den/g)+v.num*(u.den/g),u.den*(v.den/g))
+ g := gcd(u.den, v.den)
+ return i2tor(u.num*(v.den/g)+v.num*(u.den/g), u.den*(v.den/g))
}
-func mul(u, v *rat) *rat{
- g1 := gcd(u.num,v.den)
- g2 := gcd(u.den,v.num)
+func mul(u, v *rat) *rat {
+ g1 := gcd(u.num, v.den)
+ g2 := gcd(u.den, v.num)
r := new(rat)
- r.num =(u.num/g1)*(v.num/g2)
- r.den = (u.den/g2)*(v.den/g1)
+ r.num = (u.num / g1) * (v.num / g2)
+ r.den = (u.den / g2) * (v.den / g1)
return r
}
-func neg(u *rat) *rat{
+func neg(u *rat) *rat {
return i2tor(-u.num, u.den)
}
-func sub(u, v *rat) *rat{
+func sub(u, v *rat) *rat {
return add(u, neg(v))
}
-func inv(u *rat) *rat{ // invert a rat
- if u.num == 0 { panic("zero divide in inv") }
+func inv(u *rat) *rat { // invert a rat
+ if u.num == 0 {
+ panic("zero divide in inv")
+ }
return i2tor(u.den, u.num)
}
// print eval in floating point of PS at x=c to n terms
func Evaln(c *rat, U PS, n int) {
xn := float64(1)
- x := float64(c.num)/float64(c.den)
+ x := float64(c.num) / float64(c.den)
val := float64(0)
- for i:=0; i<n; i++ {
+ for i := 0; i < n; i++ {
u := get(U)
if end(u) != 0 {
break
}
- val = val + x * float64(u.num)/float64(u.den)
- xn = xn*x
+ val = val + x*float64(u.num)/float64(u.den)
+ xn = xn * x
}
print(val, "\n")
}
// Print n terms of a power series
-func Printn(U PS, n int){
+func Printn(U PS, n int) {
done := false
- for ; !done && n>0; n-- {
+ for ; !done && n > 0; n-- {
u := get(U)
if end(u) != 0 {
done = true
@@ -307,16 +316,20 @@ func Printn(U PS, n int){
print(("\n"))
}
-func Print(U PS){
- Printn(U,1000000000)
+func Print(U PS) {
+ Printn(U, 1000000000)
}
// Evaluate n terms of power series U at x=c
-func eval(c *rat, U PS, n int) *rat{
- if n==0 { return zero }
+func eval(c *rat, U PS, n int) *rat {
+ if n == 0 {
+ return zero
+ }
y := get(U)
- if end(y) != 0 { return zero }
- return add(y,mul(c,eval(c,U,n-1)))
+ if end(y) != 0 {
+ return zero
+ }
+ return add(y, mul(c, eval(c, U, n-1)))
}
// Power-series constructors return channels on which power
@@ -325,29 +338,29 @@ func eval(c *rat, U PS, n int) *rat{
// Make a pair of power series identical to a given power series
-func Split(U PS) *dch2{
+func Split(U PS) *dch2 {
UU := mkdch2()
- go split(U,UU)
+ go split(U, UU)
return UU
}
// Add two power series
-func Add(U, V PS) PS{
+func Add(U, V PS) PS {
Z := mkPS()
- go func(U, V, Z PS){
- var uv [] item
+ go func(U, V, Z PS) {
+ var uv []item
for {
<-Z.req
- uv = get2(U,V)
- switch end(uv[0].(*rat))+2*end(uv[1].(*rat)) {
+ uv = get2(U, V)
+ switch end(uv[0].(*rat)) + 2*end(uv[1].(*rat)) {
case 0:
Z.dat <- add(uv[0].(*rat), uv[1].(*rat))
case 1:
Z.dat <- uv[1]
- copy(V,Z)
+ copy(V, Z)
case 2:
Z.dat <- uv[0]
- copy(U,Z)
+ copy(U, Z)
case 3:
Z.dat <- finis
}
@@ -357,9 +370,9 @@ func Add(U, V PS) PS{
}
// Multiply a power series by a constant
-func Cmul(c *rat,U PS) PS{
+func Cmul(c *rat, U PS) PS {
Z := mkPS()
- go func(c *rat, U, Z PS){
+ go func(c *rat, U, Z PS) {
done := false
for !done {
<-Z.req
@@ -367,7 +380,7 @@ func Cmul(c *rat,U PS) PS{
if end(u) != 0 {
done = true
} else {
- Z.dat <- mul(c,u)
+ Z.dat <- mul(c, u)
}
}
Z.dat <- finis
@@ -377,52 +390,56 @@ func Cmul(c *rat,U PS) PS{
// Subtract
-func Sub(U, V PS) PS{
+func Sub(U, V PS) PS {
return Add(U, Cmul(neg(one), V))
}
// Multiply a power series by the monomial x^n
-func Monmul(U PS, n int) PS{
+func Monmul(U PS, n int) PS {
Z := mkPS()
- go func(n int, U PS, Z PS){
- for ; n>0; n-- { put(zero,Z) }
- copy(U,Z)
+ go func(n int, U PS, Z PS) {
+ for ; n > 0; n-- {
+ put(zero, Z)
+ }
+ copy(U, Z)
}(n, U, Z)
return Z
}
// Multiply by x
-func Xmul(U PS) PS{
- return Monmul(U,1)
+func Xmul(U PS) PS {
+ return Monmul(U, 1)
}
-func Rep(c *rat) PS{
+func Rep(c *rat) PS {
Z := mkPS()
- go repeat(c,Z)
+ go repeat(c, Z)
return Z
}
// Monomial c*x^n
-func Mon(c *rat, n int) PS{
- Z:=mkPS()
- go func(c *rat, n int, Z PS){
- if(c.num!=0) {
- for ; n>0; n=n-1 { put(zero,Z) }
- put(c,Z)
+func Mon(c *rat, n int) PS {
+ Z := mkPS()
+ go func(c *rat, n int, Z PS) {
+ if c.num != 0 {
+ for ; n > 0; n = n - 1 {
+ put(zero, Z)
+ }
+ put(c, Z)
}
- put(finis,Z)
+ put(finis, Z)
}(c, n, Z)
return Z
}
-func Shift(c *rat, U PS) PS{
+func Shift(c *rat, U PS) PS {
Z := mkPS()
- go func(c *rat, U, Z PS){
- put(c,Z)
- copy(U,Z)
+ go func(c *rat, U, Z PS) {
+ put(c, Z)
+ copy(U, Z)
}(c, U, Z)
return Z
}
@@ -453,21 +470,21 @@ func Poly(a [] *rat) PS{
// let V = v + x*VV
// then UV = u*v + x*(u*VV+v*UU) + x*x*UU*VV
-func Mul(U, V PS) PS{
- Z:=mkPS()
- go func(U, V, Z PS){
+func Mul(U, V PS) PS {
+ Z := mkPS()
+ go func(U, V, Z PS) {
<-Z.req
- uv := get2(U,V)
- if end(uv[0].(*rat))!=0 || end(uv[1].(*rat)) != 0 {
+ uv := get2(U, V)
+ if end(uv[0].(*rat)) != 0 || end(uv[1].(*rat)) != 0 {
Z.dat <- finis
} else {
- Z.dat <- mul(uv[0].(*rat),uv[1].(*rat))
+ Z.dat <- mul(uv[0].(*rat), uv[1].(*rat))
UU := Split(U)
VV := Split(V)
- W := Add(Cmul(uv[0].(*rat),VV[0]),Cmul(uv[1].(*rat),UU[0]))
+ W := Add(Cmul(uv[0].(*rat), VV[0]), Cmul(uv[1].(*rat), UU[0]))
<-Z.req
Z.dat <- get(W)
- copy(Add(W,Mul(UU[1],VV[1])),Z)
+ copy(Add(W, Mul(UU[1], VV[1])), Z)
}
}(U, V, Z)
return Z
@@ -475,19 +492,19 @@ func Mul(U, V PS) PS{
// Differentiate
-func Diff(U PS) PS{
- Z:=mkPS()
- go func(U, Z PS){
+func Diff(U PS) PS {
+ Z := mkPS()
+ go func(U, Z PS) {
<-Z.req
u := get(U)
if end(u) == 0 {
- done:=false
- for i:=1; !done; i++ {
+ done := false
+ for i := 1; !done; i++ {
u = get(U)
if end(u) != 0 {
- done=true
+ done = true
} else {
- Z.dat <- mul(itor(int64(i)),u)
+ Z.dat <- mul(itor(int64(i)), u)
<-Z.req
}
}
@@ -498,16 +515,18 @@ func Diff(U PS) PS{
}
// Integrate, with const of integration
-func Integ(c *rat,U PS) PS{
- Z:=mkPS()
- go func(c *rat, U, Z PS){
- put(c,Z)
- done:=false
- for i:=1; !done; i++ {
+func Integ(c *rat, U PS) PS {
+ Z := mkPS()
+ go func(c *rat, U, Z PS) {
+ put(c, Z)
+ done := false
+ for i := 1; !done; i++ {
<-Z.req
u := get(U)
- if end(u) != 0 { done= true }
- Z.dat <- mul(i2tor(1,int64(i)),u)
+ if end(u) != 0 {
+ done = true
+ }
+ Z.dat <- mul(i2tor(1, int64(i)), u)
}
Z.dat <- finis
}(c, U, Z)
@@ -516,18 +535,18 @@ func Integ(c *rat,U PS) PS{
// Binomial theorem (1+x)^c
-func Binom(c *rat) PS{
- Z:=mkPS()
- go func(c *rat, Z PS){
+func Binom(c *rat) PS {
+ Z := mkPS()
+ go func(c *rat, Z PS) {
n := 1
t := itor(1)
- for c.num!=0 {
- put(t,Z)
- t = mul(mul(t,c),i2tor(1,int64(n)))
- c = sub(c,one)
+ for c.num != 0 {
+ put(t, Z)
+ t = mul(mul(t, c), i2tor(1, int64(n)))
+ c = sub(c, one)
n++
}
- put(finis,Z)
+ put(finis, Z)
}(c, Z)
return Z
}
@@ -540,15 +559,15 @@ func Binom(c *rat) PS{
// u*ZZ + z*UU +x*UU*ZZ = 0
// ZZ = -UU*(z+x*ZZ)/u
-func Recip(U PS) PS{
- Z:=mkPS()
- go func(U, Z PS){
- ZZ:=mkPS2()
+func Recip(U PS) PS {
+ Z := mkPS()
+ go func(U, Z PS) {
+ ZZ := mkPS2()
<-Z.req
z := inv(get(U))
Z.dat <- z
- split(Mul(Cmul(neg(z),U),Shift(z,ZZ[0])),ZZ)
- copy(ZZ[1],Z)
+ split(Mul(Cmul(neg(z), U), Shift(z, ZZ[0])), ZZ)
+ copy(ZZ[1], Z)
}(U, Z)
return Z
}
@@ -560,9 +579,9 @@ func Recip(U PS) PS{
// DZ = Z*DU
// integrate to get Z
-func Exp(U PS) PS{
+func Exp(U PS) PS {
ZZ := mkPS2()
- split(Integ(one,Mul(ZZ[0],Diff(U))),ZZ)
+ split(Integ(one, Mul(ZZ[0], Diff(U))), ZZ)
return ZZ[1]
}
@@ -573,7 +592,7 @@ func Exp(U PS) PS{
// bug: a nonzero constant term is ignored
func Subst(U, V PS) PS {
- Z:= mkPS()
+ Z := mkPS()
go func(U, V, Z PS) {
VV := Split(V)
<-Z.req
@@ -581,20 +600,20 @@ func Subst(U, V PS) PS {
Z.dat <- u
if end(u) == 0 {
if end(get(VV[0])) != 0 {
- put(finis,Z)
+ put(finis, Z)
} else {
- copy(Mul(VV[0],Subst(U,VV[1])),Z)
+ copy(Mul(VV[0], Subst(U, VV[1])), Z)
}
}
}(U, V, Z)
return Z
}
-// Monomial Substition: U(c x^n)
+// Monomial Substitution: U(c x^n)
// Each Ui is multiplied by c^i and followed by n-1 zeros
func MonSubst(U PS, c0 *rat, n int) PS {
- Z:= mkPS()
+ Z := mkPS()
go func(U, Z PS, c0 *rat, n int) {
c := one
for {
@@ -615,14 +634,13 @@ func MonSubst(U PS, c0 *rat, n int) PS {
return Z
}
-
func Init() {
chnameserial = -1
seqno = 0
chnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
zero = itor(0)
one = itor(1)
- finis = i2tor(1,0)
+ finis = i2tor(1, 0)
Ones = Rep(one)
Twos = Rep(itor(2))
}
@@ -641,7 +659,8 @@ func check(U PS, c *rat, count int, str string) {
}
}
-const N=10
+const N = 10
+
func checka(U PS, a []*rat, str string) {
for i := 0; i < N; i++ {
check(U, a[i], 1, str)
@@ -650,53 +669,64 @@ func checka(U PS, a []*rat, str string) {
func main() {
Init()
- if len(os.Args) > 1 { // print
- print("Ones: "); Printn(Ones, 10)
- print("Twos: "); Printn(Twos, 10)
- print("Add: "); Printn(Add(Ones, Twos), 10)
- print("Diff: "); Printn(Diff(Ones), 10)
- print("Integ: "); Printn(Integ(zero, Ones), 10)
- print("CMul: "); Printn(Cmul(neg(one), Ones), 10)
- print("Sub: "); Printn(Sub(Ones, Twos), 10)
- print("Mul: "); Printn(Mul(Ones, Ones), 10)
- print("Exp: "); Printn(Exp(Ones), 15)
- print("MonSubst: "); Printn(MonSubst(Ones, neg(one), 2), 10)
- print("ATan: "); Printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
- } else { // test
+ if len(os.Args) > 1 { // print
+ print("Ones: ")
+ Printn(Ones, 10)
+ print("Twos: ")
+ Printn(Twos, 10)
+ print("Add: ")
+ Printn(Add(Ones, Twos), 10)
+ print("Diff: ")
+ Printn(Diff(Ones), 10)
+ print("Integ: ")
+ Printn(Integ(zero, Ones), 10)
+ print("CMul: ")
+ Printn(Cmul(neg(one), Ones), 10)
+ print("Sub: ")
+ Printn(Sub(Ones, Twos), 10)
+ print("Mul: ")
+ Printn(Mul(Ones, Ones), 10)
+ print("Exp: ")
+ Printn(Exp(Ones), 15)
+ print("MonSubst: ")
+ Printn(MonSubst(Ones, neg(one), 2), 10)
+ print("ATan: ")
+ Printn(Integ(zero, MonSubst(Ones, neg(one), 2)), 10)
+ } else { // test
check(Ones, one, 5, "Ones")
- check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
+ check(Add(Ones, Ones), itor(2), 0, "Add Ones Ones") // 1 1 1 1 1
check(Add(Ones, Twos), itor(3), 0, "Add Ones Twos") // 3 3 3 3 3
a := make([]*rat, N)
d := Diff(Ones)
- for i:=0; i < N; i++ {
- a[i] = itor(int64(i+1))
+ for i := 0; i < N; i++ {
+ a[i] = itor(int64(i + 1))
}
- checka(d, a, "Diff") // 1 2 3 4 5
+ checka(d, a, "Diff") // 1 2 3 4 5
in := Integ(zero, Ones)
- a[0] = zero // integration constant
- for i:=1; i < N; i++ {
+ a[0] = zero // integration constant
+ for i := 1; i < N; i++ {
a[i] = i2tor(1, int64(i))
}
- checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
- check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
- check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
+ checka(in, a, "Integ") // 0 1 1/2 1/3 1/4 1/5
+ check(Cmul(neg(one), Twos), itor(-2), 10, "CMul") // -1 -1 -1 -1 -1
+ check(Sub(Ones, Twos), itor(-1), 0, "Sub Ones Twos") // -1 -1 -1 -1 -1
m := Mul(Ones, Ones)
- for i:=0; i < N; i++ {
- a[i] = itor(int64(i+1))
+ for i := 0; i < N; i++ {
+ a[i] = itor(int64(i + 1))
}
- checka(m, a, "Mul") // 1 2 3 4 5
+ checka(m, a, "Mul") // 1 2 3 4 5
e := Exp(Ones)
a[0] = itor(1)
a[1] = itor(1)
- a[2] = i2tor(3,2)
- a[3] = i2tor(13,6)
- a[4] = i2tor(73,24)
- a[5] = i2tor(167,40)
- a[6] = i2tor(4051,720)
- a[7] = i2tor(37633,5040)
- a[8] = i2tor(43817,4480)
- a[9] = i2tor(4596553,362880)
- checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
+ a[2] = i2tor(3, 2)
+ a[3] = i2tor(13, 6)
+ a[4] = i2tor(73, 24)
+ a[5] = i2tor(167, 40)
+ a[6] = i2tor(4051, 720)
+ a[7] = i2tor(37633, 5040)
+ a[8] = i2tor(43817, 4480)
+ a[9] = i2tor(4596553, 362880)
+ checka(e, a, "Exp") // 1 1 3/2 13/6 73/24
at := Integ(zero, MonSubst(Ones, neg(one), 2))
for c, i := 1, 0; i < N; i++ {
if i%2 == 0 {
@@ -706,20 +736,20 @@ func main() {
c *= -1
}
}
- checka(at, a, "ATan"); // 0 -1 0 -1/3 0 -1/5
-/*
- t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
- a[0] = zero
- a[1] = itor(1)
- a[2] = zero
- a[3] = i2tor(1,3)
- a[4] = zero
- a[5] = i2tor(2,15)
- a[6] = zero
- a[7] = i2tor(17,315)
- a[8] = zero
- a[9] = i2tor(62,2835)
- checka(t, a, "Tan") // 0 1 0 1/3 0 2/15
-*/
+ checka(at, a, "ATan") // 0 -1 0 -1/3 0 -1/5
+ /*
+ t := Revert(Integ(zero, MonSubst(Ones, neg(one), 2)))
+ a[0] = zero
+ a[1] = itor(1)
+ a[2] = zero
+ a[3] = i2tor(1,3)
+ a[4] = zero
+ a[5] = i2tor(2,15)
+ a[6] = zero
+ a[7] = i2tor(17,315)
+ a[8] = zero
+ a[9] = i2tor(62,2835)
+ checka(t, a, "Tan") // 0 1 0 1/3 0 2/15
+ */
}
}
diff --git a/gcc/testsuite/go.test/test/chan/select2.go b/gcc/testsuite/go.test/test/chan/select2.go
index ccf9dab..31e27d7 100644
--- a/gcc/testsuite/go.test/test/chan/select2.go
+++ b/gcc/testsuite/go.test/test/chan/select2.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/chan/select3.go b/gcc/testsuite/go.test/test/chan/select3.go
index 847d8ed..dd14c73 100644
--- a/gcc/testsuite/go.test/test/chan/select3.go
+++ b/gcc/testsuite/go.test/test/chan/select3.go
@@ -14,12 +14,10 @@ import "time"
const always = "function did not"
const never = "function did"
-
func unreachable() {
panic("control flow shouldn't reach here")
}
-
// Calls f and verifies that f always/never panics depending on signal.
func testPanic(signal string, f func()) {
defer func() {
@@ -34,7 +32,6 @@ func testPanic(signal string, f func()) {
f()
}
-
// Calls f and empirically verifies that f always/never blocks depending on signal.
func testBlock(signal string, f func()) {
c := make(chan string)
@@ -43,15 +40,21 @@ func testBlock(signal string, f func()) {
c <- never // f didn't block
}()
go func() {
- time.Sleep(1e8) // 0.1s seems plenty long
- c <- always // f blocked always
+ if signal == never {
+ // Wait a long time to make sure that we don't miss our window by accident on a slow machine.
+ time.Sleep(10 * time.Second)
+ } else {
+ // Wait as short a time as we can without false negatives.
+ // 10ms should be long enough to catch most failures.
+ time.Sleep(10 * time.Millisecond)
+ }
+ c <- always // f blocked always
}()
if <-c != signal {
panic(signal + " block")
}
}
-
func main() {
const async = 1 // asynchronous channels
var nilch chan int
@@ -114,8 +117,7 @@ func main() {
// empty selects always block
testBlock(always, func() {
- select {
- }
+ select {}
})
// selects with only nil channels always block
diff --git a/gcc/testsuite/go.test/test/chan/select5.go b/gcc/testsuite/go.test/test/chan/select5.go
index f72cfe4..8b98c3a 100644
--- a/gcc/testsuite/go.test/test/chan/select5.go
+++ b/gcc/testsuite/go.test/test/chan/select5.go
@@ -1,6 +1,6 @@
// runoutput
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -27,16 +27,16 @@ func main() {
fmt.Fprintln(out, header)
a := new(arg)
- // Generate each kind of test as a separate function to avoid
- // hitting the 6g optimizer with one enormous function.
+ // Generate each test as a separate function to avoid
+ // hitting the gc optimizer with one enormous function.
// If we name all the functions init we don't have to
// maintain a list of which ones to run.
do := func(t *template.Template) {
- fmt.Fprintln(out, `func init() {`)
for ; next(); a.reset() {
+ fmt.Fprintln(out, `func init() {`)
run(t, a, out)
+ fmt.Fprintln(out, `}`)
}
- fmt.Fprintln(out, `}`)
}
do(recv)
diff --git a/gcc/testsuite/go.test/test/chan/select6.go b/gcc/testsuite/go.test/test/chan/select6.go
index af470a0..6e8129f 100644
--- a/gcc/testsuite/go.test/test/chan/select6.go
+++ b/gcc/testsuite/go.test/test/chan/select6.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/chan/select7.go b/gcc/testsuite/go.test/test/chan/select7.go
index 20456a9..f7222ca 100644
--- a/gcc/testsuite/go.test/test/chan/select7.go
+++ b/gcc/testsuite/go.test/test/chan/select7.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/chan/select8.go b/gcc/testsuite/go.test/test/chan/select8.go
new file mode 100644
index 0000000..20bca3a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/chan/select8.go
@@ -0,0 +1,55 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test break statements in a select.
+// Gccgo had a bug in handling this.
+// Test 1,2,3-case selects, so it covers both the general
+// code path and the specialized optimizations for one-
+// and two-case selects.
+
+package main
+
+var ch = make(chan int)
+
+func main() {
+ go func() {
+ for {
+ ch <- 5
+ }
+ }()
+
+ select {
+ case <-ch:
+ break
+ panic("unreachable")
+ }
+
+ select {
+ default:
+ break
+ panic("unreachable")
+ }
+
+ select {
+ case <-ch:
+ break
+ panic("unreachable")
+ default:
+ break
+ panic("unreachable")
+ }
+
+ select {
+ case <-ch:
+ break
+ panic("unreachable")
+ case ch <- 10:
+ panic("unreachable")
+ default:
+ break
+ panic("unreachable")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/chan/sendstmt.go b/gcc/testsuite/go.test/test/chan/sendstmt.go
index a92c4f6..d296a55 100644
--- a/gcc/testsuite/go.test/test/chan/sendstmt.go
+++ b/gcc/testsuite/go.test/test/chan/sendstmt.go
@@ -1,11 +1,11 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test various parsing cases that are a little
-// different now that send is a statement, not a expression.
+// different now that send is a statement, not an expression.
package main
@@ -30,7 +30,7 @@ func chanchan() {
func sendprec() {
c := make(chan bool, 1)
- c <- false || true // not a syntax error: same as c <- (false || true)
+ c <- false || true // not a syntax error: same as c <- (false || true)
if !<-c {
panic("sent false")
}
diff --git a/gcc/testsuite/go.test/test/chancap.go b/gcc/testsuite/go.test/test/chancap.go
index b3e4023..8dce924 100644
--- a/gcc/testsuite/go.test/test/chancap.go
+++ b/gcc/testsuite/go.test/test/chancap.go
@@ -8,8 +8,17 @@
package main
+import (
+ "strings"
+ "unsafe"
+)
+
+type T chan int
+
+const ptrSize = unsafe.Sizeof((*byte)(nil))
+
func main() {
- c := make(chan int, 10)
+ c := make(T, 10)
if len(c) != 0 || cap(c) != 10 {
println("chan len/cap ", len(c), cap(c), " want 0 10")
panic("fail")
@@ -23,9 +32,40 @@ func main() {
panic("fail")
}
- c = make(chan int)
+ c = make(T)
if len(c) != 0 || cap(c) != 0 {
println("chan len/cap ", len(c), cap(c), " want 0 0")
panic("fail")
}
+
+ n := -1
+ shouldPanic("makechan: size out of range", func() { _ = make(T, n) })
+ shouldPanic("makechan: size out of range", func() { _ = make(T, int64(n)) })
+ if ptrSize == 8 {
+ // Test mem > maxAlloc
+ var n2 int64 = 1 << 59
+ shouldPanic("makechan: size out of range", func() { _ = make(T, int(n2)) })
+ // Test elem.size*cap overflow
+ n2 = 1<<63 - 1
+ shouldPanic("makechan: size out of range", func() { _ = make(T, int(n2)) })
+ } else {
+ n = 1<<31 - 1
+ shouldPanic("makechan: size out of range", func() { _ = make(T, n) })
+ shouldPanic("makechan: size out of range", func() { _ = make(T, int64(n)) })
+ }
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ s := err.(error).Error()
+ if !strings.Contains(s, str) {
+ panic("got panic " + s + ", want " + str)
+ }
+ }()
+
+ f()
}
diff --git a/gcc/testsuite/go.test/test/cmp.go b/gcc/testsuite/go.test/test/cmp.go
index 73de502..6db9ce5 100644
--- a/gcc/testsuite/go.test/test/cmp.go
+++ b/gcc/testsuite/go.test/test/cmp.go
@@ -35,6 +35,10 @@ func istrue(b bool) {
type T *int
+type X int
+
+func (X) x() {}
+
func main() {
var a []int
var b map[string]int
@@ -111,7 +115,7 @@ func main() {
isfalse(ic != d)
isfalse(ie != e)
- // 6g used to let this go through as true.
+ // gc used to let this go through as true.
var g uint64 = 123
var h int64 = 123
var ig interface{} = g
@@ -129,6 +133,44 @@ func main() {
panic("bad m[c]")
}
+ // interface comparisons (issue 7207)
+ {
+ type I1 interface {
+ x()
+ }
+ type I2 interface {
+ x()
+ }
+ a1 := I1(X(0))
+ b1 := I1(X(1))
+ a2 := I2(X(0))
+ b2 := I2(X(1))
+ a3 := I1(a2)
+ a4 := I2(a1)
+ var e interface{} = X(0)
+ a5 := e.(I1)
+ a6 := e.(I2)
+ isfalse(a1 == b1)
+ isfalse(a1 == b2)
+ isfalse(a2 == b1)
+ isfalse(a2 == b2)
+ istrue(a1 == a2)
+ istrue(a1 == a3)
+ istrue(a1 == a4)
+ istrue(a1 == a5)
+ istrue(a1 == a6)
+ istrue(a2 == a3)
+ istrue(a2 == a4)
+ istrue(a2 == a5)
+ istrue(a2 == a6)
+ istrue(a3 == a4)
+ istrue(a3 == a5)
+ istrue(a3 == a6)
+ istrue(a4 == a5)
+ istrue(a4 == a6)
+ istrue(a5 == a6)
+ }
+
// non-interface comparisons
{
c := make(chan int)
@@ -387,6 +429,23 @@ func main() {
isfalse(iz != x)
}
+ // named booleans
+ {
+ type mybool bool
+ var b mybool
+
+ type T struct{ data [20]byte }
+ var x, y T
+ b = x == y
+ istrue(x == y)
+ istrue(bool(b))
+
+ m := make(map[string][10]interface{})
+ b = m["x"] == m["y"]
+ istrue(m["x"] == m["y"])
+ istrue(bool(b))
+ }
+
shouldPanic(p1)
shouldPanic(p2)
shouldPanic(p3)
diff --git a/gcc/testsuite/go.test/test/cmp6.go b/gcc/testsuite/go.test/test/cmp6.go
index 839c274..7cf7604 100644
--- a/gcc/testsuite/go.test/test/cmp6.go
+++ b/gcc/testsuite/go.test/test/cmp6.go
@@ -18,7 +18,10 @@ type T3 struct{ z []int }
var t3 T3
-type T4 struct { _ []int; a float64 }
+type T4 struct {
+ _ []int
+ a float64
+}
var t4 T4
@@ -51,6 +54,14 @@ func main() {
use(p3 == p1)
use(p3 == p2)
+ // Arrays are comparable if and only if their element type is comparable.
+ var a1 [1]int
+ var a2 [1]func()
+ var a3 [0]func()
+ use(a1 == a1)
+ use(a2 == a2) // ERROR "invalid operation|invalid comparison"
+ use(a3 == a3) // ERROR "invalid operation|invalid comparison"
+
// Comparison of structs should have a good message
use(t3 == t3) // ERROR "struct|expected"
use(t4 == t4) // ERROR "cannot be compared|non-comparable"
diff --git a/gcc/testsuite/go.test/test/cmplx.go b/gcc/testsuite/go.test/test/cmplx.go
index 2d8a622..d63c7eb 100644
--- a/gcc/testsuite/go.test/test/cmplx.go
+++ b/gcc/testsuite/go.test/test/cmplx.go
@@ -28,6 +28,14 @@ var (
C128 Complex128
)
+func F1() int {
+ return 1
+}
+
+func F3() (int, int, int) {
+ return 1, 2, 3
+}
+
func main() {
// ok
c64 = complex(f32, f32)
@@ -41,6 +49,11 @@ func main() {
_ = complex(f64, F64) // ERROR "complex"
_ = complex(F64, f64) // ERROR "complex"
+ _ = complex(F1()) // ERROR "not enough arguments"
+ _ = complex(F3()) // ERROR "too many arguments"
+
+ _ = complex() // ERROR "not enough arguments"
+
c128 = complex(f32, f32) // ERROR "cannot use"
c64 = complex(f64, f64) // ERROR "cannot use"
@@ -51,4 +64,5 @@ func main() {
C64 = complex(f32, f32) // ERROR "cannot use"
C128 = complex(f64, f64) // ERROR "cannot use"
+
}
diff --git a/gcc/testsuite/go.test/test/cmplxdivide.c b/gcc/testsuite/go.test/test/cmplxdivide.c
index 12dc4f1..89a2868 100644
--- a/gcc/testsuite/go.test/test/cmplxdivide.c
+++ b/gcc/testsuite/go.test/test/cmplxdivide.c
@@ -1,8 +1,19 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// gcc '-std=c99' cmplxdivide.c && a.out >cmplxdivide1.go
+// This C program generates the file cmplxdivide1.go. It uses the
+// output of the operations by C99 as the reference to check
+// the implementation of complex numbers in Go.
+// The generated file, cmplxdivide1.go, is compiled along
+// with the driver cmplxdivide.go (the names are confusing
+// and unimaginative) to run the actual test. This is done by
+// the usual test runner.
+//
+// The file cmplxdivide1.go is checked in to the repository, but
+// if it needs to be regenerated, compile and run this C program
+// like this:
+// gcc '-std=c99' cmplxdivide.c && a.out >cmplxdivide1.go
#include <complex.h>
#include <math.h>
@@ -12,50 +23,63 @@
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
double f[] = {
- 0,
- 1,
- -1,
- 2,
+ 0.0,
+ -0.0,
+ 1.0,
+ -1.0,
+ 2.0,
NAN,
INFINITY,
-INFINITY,
};
-char*
-fmt(double g)
-{
+char* fmt(double g) {
static char buf[10][30];
static int n;
char *p;
-
+
p = buf[n++];
- if(n == 10)
+ if(n == 10) {
n = 0;
+ }
+
sprintf(p, "%g", g);
- if(strcmp(p, "-0") == 0)
- strcpy(p, "negzero");
- return p;
-}
-int
-iscnan(double complex d)
-{
- return !isinf(creal(d)) && !isinf(cimag(d)) && (isnan(creal(d)) || isnan(cimag(d)));
-}
+ if(strcmp(p, "0") == 0) {
+ strcpy(p, "zero");
+ return p;
+ }
+
+ if(strcmp(p, "-0") == 0) {
+ strcpy(p, "-zero");
+ return p;
+ }
-double complex zero; // attempt to hide zero division from gcc
+ return p;
+}
-int
-main(void)
-{
+int main(void) {
int i, j, k, l;
double complex n, d, q;
-
+
printf("// skip\n");
printf("// # generated by cmplxdivide.c\n");
printf("\n");
printf("package main\n");
- printf("var tests = []Test{\n");
+ printf("\n");
+ printf("import \"math\"\n");
+ printf("\n");
+ printf("var (\n");
+ printf("\tnan = math.NaN()\n");
+ printf("\tinf = math.Inf(1)\n");
+ printf("\tzero = 0.0\n");
+ printf(")\n");
+ printf("\n");
+ printf("var tests = []struct {\n");
+ printf("\tf, g complex128\n");
+ printf("\tout complex128\n");
+ printf("}{\n");
+
for(i=0; i<nelem(f); i++)
for(j=0; j<nelem(f); j++)
for(k=0; k<nelem(f); k++)
@@ -63,17 +87,8 @@ main(void)
n = f[i] + f[j]*I;
d = f[k] + f[l]*I;
q = n/d;
-
- // BUG FIX.
- // Gcc gets the wrong answer for NaN/0 unless both sides are NaN.
- // That is, it treats (NaN+NaN*I)/0 = NaN+NaN*I (a complex NaN)
- // but it then computes (1+NaN*I)/0 = Inf+NaN*I (a complex infinity).
- // Since both numerators are complex NaNs, it seems that the
- // results should agree in kind. Override the gcc computation in this case.
- if(iscnan(n) && d == 0)
- q = (NAN+NAN*I) / zero;
- printf("\tTest{complex(%s, %s), complex(%s, %s), complex(%s, %s)},\n",
+ printf("\t{complex(%s, %s), complex(%s, %s), complex(%s, %s)},\n",
fmt(creal(n)), fmt(cimag(n)),
fmt(creal(d)), fmt(cimag(d)),
fmt(creal(q)), fmt(cimag(q)));
diff --git a/gcc/testsuite/go.test/test/cmplxdivide.go b/gcc/testsuite/go.test/test/cmplxdivide.go
index 40c8448..49cd5bf 100644
--- a/gcc/testsuite/go.test/test/cmplxdivide.go
+++ b/gcc/testsuite/go.test/test/cmplxdivide.go
@@ -1,36 +1,29 @@
// run cmplxdivide1.go
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Driver for complex division table defined in cmplxdivide1.go
+// For details, see the comment at the top of cmplxdivide.c.
package main
import (
"fmt"
"math"
- "math/cmplx"
)
-type Test struct {
- f, g complex128
- out complex128
-}
-
-var nan = math.NaN()
-var inf = math.Inf(1)
-var negzero = math.Copysign(0, -1)
-
func calike(a, b complex128) bool {
- switch {
- case cmplx.IsInf(a) && cmplx.IsInf(b):
- return true
- case cmplx.IsNaN(a) && cmplx.IsNaN(b):
- return true
+ if imag(a) != imag(b) && !(math.IsNaN(imag(a)) && math.IsNaN(imag(b))) {
+ return false
}
- return a == b
+
+ if real(a) != real(b) && !(math.IsNaN(real(a)) && math.IsNaN(real(b))) {
+ return false
+ }
+
+ return true
}
func main() {
diff --git a/gcc/testsuite/go.test/test/cmplxdivide1.go b/gcc/testsuite/go.test/test/cmplxdivide1.go
index e9031dd..a52fb6f 100644
--- a/gcc/testsuite/go.test/test/cmplxdivide1.go
+++ b/gcc/testsuite/go.test/test/cmplxdivide1.go
@@ -2,2406 +2,4113 @@
// # generated by cmplxdivide.c
package main
-var tests = []Test{
- Test{complex(0, 0), complex(0, 0), complex(-nan, -nan)},
- Test{complex(0, 0), complex(0, 1), complex(0, 0)},
- Test{complex(0, 0), complex(0, -1), complex(negzero, 0)},
- Test{complex(0, 0), complex(0, 2), complex(0, 0)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 0), complex(1, 0), complex(0, 0)},
- Test{complex(0, 0), complex(1, 1), complex(0, 0)},
- Test{complex(0, 0), complex(1, -1), complex(0, 0)},
- Test{complex(0, 0), complex(1, 2), complex(0, 0)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 0), complex(-1, 0), complex(negzero, negzero)},
- Test{complex(0, 0), complex(-1, 1), complex(negzero, negzero)},
- Test{complex(0, 0), complex(-1, -1), complex(negzero, negzero)},
- Test{complex(0, 0), complex(-1, 2), complex(0, negzero)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 0), complex(2, 0), complex(0, 0)},
- Test{complex(0, 0), complex(2, 1), complex(0, 0)},
- Test{complex(0, 0), complex(2, -1), complex(0, 0)},
- Test{complex(0, 0), complex(2, 2), complex(0, 0)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(0, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(0, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(0, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 0), complex(inf, 0), complex(0, 0)},
- Test{complex(0, 0), complex(inf, 1), complex(0, 0)},
- Test{complex(0, 0), complex(inf, -1), complex(0, 0)},
- Test{complex(0, 0), complex(inf, 2), complex(0, 0)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 0), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(0, 0), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(0, 0), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(0, 0), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(0, 0), complex(-nan, inf)},
- Test{complex(0, 1), complex(0, 1), complex(1, 0)},
- Test{complex(0, 1), complex(0, -1), complex(-1, 0)},
- Test{complex(0, 1), complex(0, 2), complex(0.5, 0)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(1, 0), complex(0, 1)},
- Test{complex(0, 1), complex(1, 1), complex(0.5, 0.5)},
- Test{complex(0, 1), complex(1, -1), complex(-0.5, 0.5)},
- Test{complex(0, 1), complex(1, 2), complex(0.4, 0.2)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(-1, 0), complex(negzero, -1)},
- Test{complex(0, 1), complex(-1, 1), complex(0.5, -0.5)},
- Test{complex(0, 1), complex(-1, -1), complex(-0.5, -0.5)},
- Test{complex(0, 1), complex(-1, 2), complex(0.4, -0.2)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(2, 0), complex(0, 0.5)},
- Test{complex(0, 1), complex(2, 1), complex(0.2, 0.4)},
- Test{complex(0, 1), complex(2, -1), complex(-0.2, 0.4)},
- Test{complex(0, 1), complex(2, 2), complex(0.25, 0.25)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(0, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(0, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(0, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(inf, 0), complex(0, 0)},
- Test{complex(0, 1), complex(inf, 1), complex(0, 0)},
- Test{complex(0, 1), complex(inf, -1), complex(0, 0)},
- Test{complex(0, 1), complex(inf, 2), complex(0, 0)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 1), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(0, 1), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(0, 1), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(0, 1), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(0, 0), complex(-nan, -inf)},
- Test{complex(0, -1), complex(0, 1), complex(-1, negzero)},
- Test{complex(0, -1), complex(0, -1), complex(1, negzero)},
- Test{complex(0, -1), complex(0, 2), complex(-0.5, negzero)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, -1), complex(1, 0), complex(0, -1)},
- Test{complex(0, -1), complex(1, 1), complex(-0.5, -0.5)},
- Test{complex(0, -1), complex(1, -1), complex(0.5, -0.5)},
- Test{complex(0, -1), complex(1, 2), complex(-0.4, -0.2)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, -1), complex(-1, 0), complex(negzero, 1)},
- Test{complex(0, -1), complex(-1, 1), complex(-0.5, 0.5)},
- Test{complex(0, -1), complex(-1, -1), complex(0.5, 0.5)},
- Test{complex(0, -1), complex(-1, 2), complex(-0.4, 0.2)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, -1), complex(2, 0), complex(0, -0.5)},
- Test{complex(0, -1), complex(2, 1), complex(-0.2, -0.4)},
- Test{complex(0, -1), complex(2, -1), complex(0.2, -0.4)},
- Test{complex(0, -1), complex(2, 2), complex(-0.25, -0.25)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(0, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(0, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(0, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, -1), complex(inf, 0), complex(0, negzero)},
- Test{complex(0, -1), complex(inf, 1), complex(0, negzero)},
- Test{complex(0, -1), complex(inf, -1), complex(0, negzero)},
- Test{complex(0, -1), complex(inf, 2), complex(0, negzero)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, -1), complex(-inf, 0), complex(negzero, 0)},
- Test{complex(0, -1), complex(-inf, 1), complex(negzero, 0)},
- Test{complex(0, -1), complex(-inf, -1), complex(negzero, 0)},
- Test{complex(0, -1), complex(-inf, 2), complex(negzero, 0)},
- Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(0, 2), complex(0, 0), complex(-nan, inf)},
- Test{complex(0, 2), complex(0, 1), complex(2, 0)},
- Test{complex(0, 2), complex(0, -1), complex(-2, 0)},
- Test{complex(0, 2), complex(0, 2), complex(1, 0)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 2), complex(1, 0), complex(0, 2)},
- Test{complex(0, 2), complex(1, 1), complex(1, 1)},
- Test{complex(0, 2), complex(1, -1), complex(-1, 1)},
- Test{complex(0, 2), complex(1, 2), complex(0.8, 0.4)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 2), complex(-1, 0), complex(negzero, -2)},
- Test{complex(0, 2), complex(-1, 1), complex(1, -1)},
- Test{complex(0, 2), complex(-1, -1), complex(-1, -1)},
- Test{complex(0, 2), complex(-1, 2), complex(0.8, -0.4)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 2), complex(2, 0), complex(0, 1)},
- Test{complex(0, 2), complex(2, 1), complex(0.4, 0.8)},
- Test{complex(0, 2), complex(2, -1), complex(-0.4, 0.8)},
- Test{complex(0, 2), complex(2, 2), complex(0.5, 0.5)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(0, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(0, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(0, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 2), complex(inf, 0), complex(0, 0)},
- Test{complex(0, 2), complex(inf, 1), complex(0, 0)},
- Test{complex(0, 2), complex(inf, -1), complex(0, 0)},
- Test{complex(0, 2), complex(inf, 2), complex(0, 0)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(0, 2), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(0, 2), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(0, 2), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(0, 2), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(1, 0), complex(0, 0), complex(inf, -nan)},
- Test{complex(1, 0), complex(0, 1), complex(0, -1)},
- Test{complex(1, 0), complex(0, -1), complex(negzero, 1)},
- Test{complex(1, 0), complex(0, 2), complex(0, -0.5)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 0), complex(1, 0), complex(1, 0)},
- Test{complex(1, 0), complex(1, 1), complex(0.5, -0.5)},
- Test{complex(1, 0), complex(1, -1), complex(0.5, 0.5)},
- Test{complex(1, 0), complex(1, 2), complex(0.2, -0.4)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 0), complex(-1, 0), complex(-1, negzero)},
- Test{complex(1, 0), complex(-1, 1), complex(-0.5, -0.5)},
- Test{complex(1, 0), complex(-1, -1), complex(-0.5, 0.5)},
- Test{complex(1, 0), complex(-1, 2), complex(-0.2, -0.4)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 0), complex(2, 0), complex(0.5, 0)},
- Test{complex(1, 0), complex(2, 1), complex(0.4, -0.2)},
- Test{complex(1, 0), complex(2, -1), complex(0.4, 0.2)},
- Test{complex(1, 0), complex(2, 2), complex(0.25, -0.25)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(1, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(1, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(1, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 0), complex(inf, 0), complex(0, 0)},
- Test{complex(1, 0), complex(inf, 1), complex(0, 0)},
- Test{complex(1, 0), complex(inf, -1), complex(0, 0)},
- Test{complex(1, 0), complex(inf, 2), complex(0, 0)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 0), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(1, 0), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(1, 0), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(1, 0), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(0, 0), complex(inf, inf)},
- Test{complex(1, 1), complex(0, 1), complex(1, -1)},
- Test{complex(1, 1), complex(0, -1), complex(-1, 1)},
- Test{complex(1, 1), complex(0, 2), complex(0.5, -0.5)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(1, 0), complex(1, 1)},
- Test{complex(1, 1), complex(1, 1), complex(1, 0)},
- Test{complex(1, 1), complex(1, -1), complex(0, 1)},
- Test{complex(1, 1), complex(1, 2), complex(0.6, -0.2)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(-1, 0), complex(-1, -1)},
- Test{complex(1, 1), complex(-1, 1), complex(negzero, -1)},
- Test{complex(1, 1), complex(-1, -1), complex(-1, negzero)},
- Test{complex(1, 1), complex(-1, 2), complex(0.2, -0.6)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(2, 0), complex(0.5, 0.5)},
- Test{complex(1, 1), complex(2, 1), complex(0.6, 0.2)},
- Test{complex(1, 1), complex(2, -1), complex(0.2, 0.6)},
- Test{complex(1, 1), complex(2, 2), complex(0.5, 0)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(1, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(1, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(1, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(inf, 0), complex(0, 0)},
- Test{complex(1, 1), complex(inf, 1), complex(0, 0)},
- Test{complex(1, 1), complex(inf, -1), complex(0, 0)},
- Test{complex(1, 1), complex(inf, 2), complex(0, 0)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 1), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(1, 1), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(1, 1), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(1, 1), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, -1), complex(0, 0), complex(inf, -inf)},
- Test{complex(1, -1), complex(0, 1), complex(-1, -1)},
- Test{complex(1, -1), complex(0, -1), complex(1, 1)},
- Test{complex(1, -1), complex(0, 2), complex(-0.5, -0.5)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, -1), complex(1, 0), complex(1, -1)},
- Test{complex(1, -1), complex(1, 1), complex(0, -1)},
- Test{complex(1, -1), complex(1, -1), complex(1, 0)},
- Test{complex(1, -1), complex(1, 2), complex(-0.2, -0.6)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, -1), complex(-1, 0), complex(-1, 1)},
- Test{complex(1, -1), complex(-1, 1), complex(-1, negzero)},
- Test{complex(1, -1), complex(-1, -1), complex(negzero, 1)},
- Test{complex(1, -1), complex(-1, 2), complex(-0.6, -0.2)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, -1), complex(2, 0), complex(0.5, -0.5)},
- Test{complex(1, -1), complex(2, 1), complex(0.2, -0.6)},
- Test{complex(1, -1), complex(2, -1), complex(0.6, -0.2)},
- Test{complex(1, -1), complex(2, 2), complex(0, -0.5)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(1, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(1, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(1, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, -1), complex(inf, 0), complex(0, negzero)},
- Test{complex(1, -1), complex(inf, 1), complex(0, negzero)},
- Test{complex(1, -1), complex(inf, -1), complex(0, negzero)},
- Test{complex(1, -1), complex(inf, 2), complex(0, negzero)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, -1), complex(-inf, 0), complex(negzero, 0)},
- Test{complex(1, -1), complex(-inf, 1), complex(negzero, 0)},
- Test{complex(1, -1), complex(-inf, -1), complex(negzero, 0)},
- Test{complex(1, -1), complex(-inf, 2), complex(negzero, 0)},
- Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(1, 2), complex(0, 0), complex(inf, inf)},
- Test{complex(1, 2), complex(0, 1), complex(2, -1)},
- Test{complex(1, 2), complex(0, -1), complex(-2, 1)},
- Test{complex(1, 2), complex(0, 2), complex(1, -0.5)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 2), complex(1, 0), complex(1, 2)},
- Test{complex(1, 2), complex(1, 1), complex(1.5, 0.5)},
- Test{complex(1, 2), complex(1, -1), complex(-0.5, 1.5)},
- Test{complex(1, 2), complex(1, 2), complex(1, 0)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 2), complex(-1, 0), complex(-1, -2)},
- Test{complex(1, 2), complex(-1, 1), complex(0.5, -1.5)},
- Test{complex(1, 2), complex(-1, -1), complex(-1.5, -0.5)},
- Test{complex(1, 2), complex(-1, 2), complex(0.6, -0.8)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 2), complex(2, 0), complex(0.5, 1)},
- Test{complex(1, 2), complex(2, 1), complex(0.8, 0.6)},
- Test{complex(1, 2), complex(2, -1), complex(0, 1)},
- Test{complex(1, 2), complex(2, 2), complex(0.75, 0.25)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(1, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(1, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(1, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 2), complex(inf, 0), complex(0, 0)},
- Test{complex(1, 2), complex(inf, 1), complex(0, 0)},
- Test{complex(1, 2), complex(inf, -1), complex(0, 0)},
- Test{complex(1, 2), complex(inf, 2), complex(0, 0)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(1, 2), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(1, 2), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(1, 2), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(1, 2), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-1, 0), complex(0, 0), complex(-inf, -nan)},
- Test{complex(-1, 0), complex(0, 1), complex(0, 1)},
- Test{complex(-1, 0), complex(0, -1), complex(negzero, -1)},
- Test{complex(-1, 0), complex(0, 2), complex(0, 0.5)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 0), complex(1, 0), complex(-1, 0)},
- Test{complex(-1, 0), complex(1, 1), complex(-0.5, 0.5)},
- Test{complex(-1, 0), complex(1, -1), complex(-0.5, -0.5)},
- Test{complex(-1, 0), complex(1, 2), complex(-0.2, 0.4)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 0), complex(-1, 0), complex(1, negzero)},
- Test{complex(-1, 0), complex(-1, 1), complex(0.5, 0.5)},
- Test{complex(-1, 0), complex(-1, -1), complex(0.5, -0.5)},
- Test{complex(-1, 0), complex(-1, 2), complex(0.2, 0.4)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 0), complex(2, 0), complex(-0.5, 0)},
- Test{complex(-1, 0), complex(2, 1), complex(-0.4, 0.2)},
- Test{complex(-1, 0), complex(2, -1), complex(-0.4, -0.2)},
- Test{complex(-1, 0), complex(2, 2), complex(-0.25, 0.25)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(-1, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(-1, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(-1, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 0), complex(inf, 0), complex(negzero, 0)},
- Test{complex(-1, 0), complex(inf, 1), complex(negzero, 0)},
- Test{complex(-1, 0), complex(inf, -1), complex(negzero, 0)},
- Test{complex(-1, 0), complex(inf, 2), complex(negzero, 0)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 0), complex(-inf, 0), complex(0, negzero)},
- Test{complex(-1, 0), complex(-inf, 1), complex(0, negzero)},
- Test{complex(-1, 0), complex(-inf, -1), complex(0, negzero)},
- Test{complex(-1, 0), complex(-inf, 2), complex(0, negzero)},
- Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 1), complex(0, 0), complex(-inf, inf)},
- Test{complex(-1, 1), complex(0, 1), complex(1, 1)},
- Test{complex(-1, 1), complex(0, -1), complex(-1, -1)},
- Test{complex(-1, 1), complex(0, 2), complex(0.5, 0.5)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 1), complex(1, 0), complex(-1, 1)},
- Test{complex(-1, 1), complex(1, 1), complex(0, 1)},
- Test{complex(-1, 1), complex(1, -1), complex(-1, 0)},
- Test{complex(-1, 1), complex(1, 2), complex(0.2, 0.6)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 1), complex(-1, 0), complex(1, -1)},
- Test{complex(-1, 1), complex(-1, 1), complex(1, negzero)},
- Test{complex(-1, 1), complex(-1, -1), complex(negzero, -1)},
- Test{complex(-1, 1), complex(-1, 2), complex(0.6, 0.2)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 1), complex(2, 0), complex(-0.5, 0.5)},
- Test{complex(-1, 1), complex(2, 1), complex(-0.2, 0.6)},
- Test{complex(-1, 1), complex(2, -1), complex(-0.6, 0.2)},
- Test{complex(-1, 1), complex(2, 2), complex(0, 0.5)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(-1, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(-1, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(-1, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 1), complex(inf, 0), complex(negzero, 0)},
- Test{complex(-1, 1), complex(inf, 1), complex(negzero, 0)},
- Test{complex(-1, 1), complex(inf, -1), complex(negzero, 0)},
- Test{complex(-1, 1), complex(inf, 2), complex(negzero, 0)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 1), complex(-inf, 0), complex(0, negzero)},
- Test{complex(-1, 1), complex(-inf, 1), complex(0, negzero)},
- Test{complex(-1, 1), complex(-inf, -1), complex(0, negzero)},
- Test{complex(-1, 1), complex(-inf, 2), complex(0, negzero)},
- Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, -1), complex(0, 0), complex(-inf, -inf)},
- Test{complex(-1, -1), complex(0, 1), complex(-1, 1)},
- Test{complex(-1, -1), complex(0, -1), complex(1, -1)},
- Test{complex(-1, -1), complex(0, 2), complex(-0.5, 0.5)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, -1), complex(1, 0), complex(-1, -1)},
- Test{complex(-1, -1), complex(1, 1), complex(-1, 0)},
- Test{complex(-1, -1), complex(1, -1), complex(0, -1)},
- Test{complex(-1, -1), complex(1, 2), complex(-0.6, 0.2)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, -1), complex(-1, 0), complex(1, 1)},
- Test{complex(-1, -1), complex(-1, 1), complex(negzero, 1)},
- Test{complex(-1, -1), complex(-1, -1), complex(1, negzero)},
- Test{complex(-1, -1), complex(-1, 2), complex(-0.2, 0.6)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, -1), complex(2, 0), complex(-0.5, -0.5)},
- Test{complex(-1, -1), complex(2, 1), complex(-0.6, -0.2)},
- Test{complex(-1, -1), complex(2, -1), complex(-0.2, -0.6)},
- Test{complex(-1, -1), complex(2, 2), complex(-0.5, 0)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(-1, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(-1, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(-1, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, -1), complex(inf, 0), complex(negzero, negzero)},
- Test{complex(-1, -1), complex(inf, 1), complex(negzero, negzero)},
- Test{complex(-1, -1), complex(inf, -1), complex(negzero, negzero)},
- Test{complex(-1, -1), complex(inf, 2), complex(negzero, negzero)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, -1), complex(-inf, 0), complex(0, 0)},
- Test{complex(-1, -1), complex(-inf, 1), complex(0, 0)},
- Test{complex(-1, -1), complex(-inf, -1), complex(0, 0)},
- Test{complex(-1, -1), complex(-inf, 2), complex(0, 0)},
- Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
- Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
- Test{complex(-1, 2), complex(0, 0), complex(-inf, inf)},
- Test{complex(-1, 2), complex(0, 1), complex(2, 1)},
- Test{complex(-1, 2), complex(0, -1), complex(-2, -1)},
- Test{complex(-1, 2), complex(0, 2), complex(1, 0.5)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 2), complex(1, 0), complex(-1, 2)},
- Test{complex(-1, 2), complex(1, 1), complex(0.5, 1.5)},
- Test{complex(-1, 2), complex(1, -1), complex(-1.5, 0.5)},
- Test{complex(-1, 2), complex(1, 2), complex(0.6, 0.8)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 2), complex(-1, 0), complex(1, -2)},
- Test{complex(-1, 2), complex(-1, 1), complex(1.5, -0.5)},
- Test{complex(-1, 2), complex(-1, -1), complex(-0.5, -1.5)},
- Test{complex(-1, 2), complex(-1, 2), complex(1, 0)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 2), complex(2, 0), complex(-0.5, 1)},
- Test{complex(-1, 2), complex(2, 1), complex(0, 1)},
- Test{complex(-1, 2), complex(2, -1), complex(-0.8, 0.6)},
- Test{complex(-1, 2), complex(2, 2), complex(0.25, 0.75)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(-1, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(-1, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(-1, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 2), complex(inf, 0), complex(negzero, 0)},
- Test{complex(-1, 2), complex(inf, 1), complex(negzero, 0)},
- Test{complex(-1, 2), complex(inf, -1), complex(negzero, 0)},
- Test{complex(-1, 2), complex(inf, 2), complex(negzero, 0)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(-1, 2), complex(-inf, 0), complex(0, negzero)},
- Test{complex(-1, 2), complex(-inf, 1), complex(0, negzero)},
- Test{complex(-1, 2), complex(-inf, -1), complex(0, negzero)},
- Test{complex(-1, 2), complex(-inf, 2), complex(0, negzero)},
- Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
- Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(2, 0), complex(0, 0), complex(inf, -nan)},
- Test{complex(2, 0), complex(0, 1), complex(0, -2)},
- Test{complex(2, 0), complex(0, -1), complex(negzero, 2)},
- Test{complex(2, 0), complex(0, 2), complex(0, -1)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 0), complex(1, 0), complex(2, 0)},
- Test{complex(2, 0), complex(1, 1), complex(1, -1)},
- Test{complex(2, 0), complex(1, -1), complex(1, 1)},
- Test{complex(2, 0), complex(1, 2), complex(0.4, -0.8)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 0), complex(-1, 0), complex(-2, negzero)},
- Test{complex(2, 0), complex(-1, 1), complex(-1, -1)},
- Test{complex(2, 0), complex(-1, -1), complex(-1, 1)},
- Test{complex(2, 0), complex(-1, 2), complex(-0.4, -0.8)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 0), complex(2, 0), complex(1, 0)},
- Test{complex(2, 0), complex(2, 1), complex(0.8, -0.4)},
- Test{complex(2, 0), complex(2, -1), complex(0.8, 0.4)},
- Test{complex(2, 0), complex(2, 2), complex(0.5, -0.5)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(2, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(2, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(2, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 0), complex(inf, 0), complex(0, 0)},
- Test{complex(2, 0), complex(inf, 1), complex(0, 0)},
- Test{complex(2, 0), complex(inf, -1), complex(0, 0)},
- Test{complex(2, 0), complex(inf, 2), complex(0, 0)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 0), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(2, 0), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(2, 0), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(2, 0), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(0, 0), complex(inf, inf)},
- Test{complex(2, 1), complex(0, 1), complex(1, -2)},
- Test{complex(2, 1), complex(0, -1), complex(-1, 2)},
- Test{complex(2, 1), complex(0, 2), complex(0.5, -1)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(1, 0), complex(2, 1)},
- Test{complex(2, 1), complex(1, 1), complex(1.5, -0.5)},
- Test{complex(2, 1), complex(1, -1), complex(0.5, 1.5)},
- Test{complex(2, 1), complex(1, 2), complex(0.8, -0.6)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(-1, 0), complex(-2, -1)},
- Test{complex(2, 1), complex(-1, 1), complex(-0.5, -1.5)},
- Test{complex(2, 1), complex(-1, -1), complex(-1.5, 0.5)},
- Test{complex(2, 1), complex(-1, 2), complex(0, -1)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(2, 0), complex(1, 0.5)},
- Test{complex(2, 1), complex(2, 1), complex(1, 0)},
- Test{complex(2, 1), complex(2, -1), complex(0.6, 0.8)},
- Test{complex(2, 1), complex(2, 2), complex(0.75, -0.25)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(2, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(2, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(2, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(inf, 0), complex(0, 0)},
- Test{complex(2, 1), complex(inf, 1), complex(0, 0)},
- Test{complex(2, 1), complex(inf, -1), complex(0, 0)},
- Test{complex(2, 1), complex(inf, 2), complex(0, 0)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 1), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(2, 1), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(2, 1), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(2, 1), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, -1), complex(0, 0), complex(inf, -inf)},
- Test{complex(2, -1), complex(0, 1), complex(-1, -2)},
- Test{complex(2, -1), complex(0, -1), complex(1, 2)},
- Test{complex(2, -1), complex(0, 2), complex(-0.5, -1)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, -1), complex(1, 0), complex(2, -1)},
- Test{complex(2, -1), complex(1, 1), complex(0.5, -1.5)},
- Test{complex(2, -1), complex(1, -1), complex(1.5, 0.5)},
- Test{complex(2, -1), complex(1, 2), complex(0, -1)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, -1), complex(-1, 0), complex(-2, 1)},
- Test{complex(2, -1), complex(-1, 1), complex(-1.5, -0.5)},
- Test{complex(2, -1), complex(-1, -1), complex(-0.5, 1.5)},
- Test{complex(2, -1), complex(-1, 2), complex(-0.8, -0.6)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, -1), complex(2, 0), complex(1, -0.5)},
- Test{complex(2, -1), complex(2, 1), complex(0.6, -0.8)},
- Test{complex(2, -1), complex(2, -1), complex(1, 0)},
- Test{complex(2, -1), complex(2, 2), complex(0.25, -0.75)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(2, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(2, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(2, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, -1), complex(inf, 0), complex(0, negzero)},
- Test{complex(2, -1), complex(inf, 1), complex(0, negzero)},
- Test{complex(2, -1), complex(inf, -1), complex(0, negzero)},
- Test{complex(2, -1), complex(inf, 2), complex(0, negzero)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, -1), complex(-inf, 0), complex(negzero, 0)},
- Test{complex(2, -1), complex(-inf, 1), complex(negzero, 0)},
- Test{complex(2, -1), complex(-inf, -1), complex(negzero, 0)},
- Test{complex(2, -1), complex(-inf, 2), complex(negzero, 0)},
- Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
- Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
- Test{complex(2, 2), complex(0, 0), complex(inf, inf)},
- Test{complex(2, 2), complex(0, 1), complex(2, -2)},
- Test{complex(2, 2), complex(0, -1), complex(-2, 2)},
- Test{complex(2, 2), complex(0, 2), complex(1, -1)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 2), complex(1, 0), complex(2, 2)},
- Test{complex(2, 2), complex(1, 1), complex(2, 0)},
- Test{complex(2, 2), complex(1, -1), complex(0, 2)},
- Test{complex(2, 2), complex(1, 2), complex(1.2, -0.4)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 2), complex(-1, 0), complex(-2, -2)},
- Test{complex(2, 2), complex(-1, 1), complex(negzero, -2)},
- Test{complex(2, 2), complex(-1, -1), complex(-2, negzero)},
- Test{complex(2, 2), complex(-1, 2), complex(0.4, -1.2)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 2), complex(2, 0), complex(1, 1)},
- Test{complex(2, 2), complex(2, 1), complex(1.2, 0.4)},
- Test{complex(2, 2), complex(2, -1), complex(0.4, 1.2)},
- Test{complex(2, 2), complex(2, 2), complex(1, 0)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(2, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(2, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(2, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 2), complex(inf, 0), complex(0, 0)},
- Test{complex(2, 2), complex(inf, 1), complex(0, 0)},
- Test{complex(2, 2), complex(inf, -1), complex(0, 0)},
- Test{complex(2, 2), complex(inf, 2), complex(0, 0)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(2, 2), complex(-inf, 0), complex(negzero, negzero)},
- Test{complex(2, 2), complex(-inf, 1), complex(negzero, negzero)},
- Test{complex(2, 2), complex(-inf, -1), complex(negzero, negzero)},
- Test{complex(2, 2), complex(-inf, 2), complex(negzero, negzero)},
- Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
- Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, 0), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, 0), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, 0), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, 1), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, 1), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, 1), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, -1), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, -1), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, -1), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, 2), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, 2), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, 2), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(0, 0), complex(inf, -nan)},
- Test{complex(inf, 0), complex(0, 1), complex(-nan, -inf)},
- Test{complex(inf, 0), complex(0, -1), complex(-nan, inf)},
- Test{complex(inf, 0), complex(0, 2), complex(-nan, -inf)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(1, 0), complex(inf, -nan)},
- Test{complex(inf, 0), complex(1, 1), complex(inf, -inf)},
- Test{complex(inf, 0), complex(1, -1), complex(inf, inf)},
- Test{complex(inf, 0), complex(1, 2), complex(inf, -inf)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-1, 0), complex(-inf, -nan)},
- Test{complex(inf, 0), complex(-1, 1), complex(-inf, -inf)},
- Test{complex(inf, 0), complex(-1, -1), complex(-inf, inf)},
- Test{complex(inf, 0), complex(-1, 2), complex(-inf, -inf)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(2, 0), complex(inf, -nan)},
- Test{complex(inf, 0), complex(2, 1), complex(inf, -inf)},
- Test{complex(inf, 0), complex(2, -1), complex(inf, inf)},
- Test{complex(inf, 0), complex(2, 2), complex(inf, -inf)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(inf, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(inf, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(inf, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(0, 0), complex(inf, inf)},
- Test{complex(inf, 1), complex(0, 1), complex(-nan, -inf)},
- Test{complex(inf, 1), complex(0, -1), complex(-nan, inf)},
- Test{complex(inf, 1), complex(0, 2), complex(-nan, -inf)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(1, 0), complex(inf, -nan)},
- Test{complex(inf, 1), complex(1, 1), complex(inf, -inf)},
- Test{complex(inf, 1), complex(1, -1), complex(inf, inf)},
- Test{complex(inf, 1), complex(1, 2), complex(inf, -inf)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-1, 0), complex(-inf, -nan)},
- Test{complex(inf, 1), complex(-1, 1), complex(-inf, -inf)},
- Test{complex(inf, 1), complex(-1, -1), complex(-inf, inf)},
- Test{complex(inf, 1), complex(-1, 2), complex(-inf, -inf)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(2, 0), complex(inf, -nan)},
- Test{complex(inf, 1), complex(2, 1), complex(inf, -inf)},
- Test{complex(inf, 1), complex(2, -1), complex(inf, inf)},
- Test{complex(inf, 1), complex(2, 2), complex(inf, -inf)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(inf, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(inf, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(inf, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(0, 0), complex(inf, -inf)},
- Test{complex(inf, -1), complex(0, 1), complex(-nan, -inf)},
- Test{complex(inf, -1), complex(0, -1), complex(-nan, inf)},
- Test{complex(inf, -1), complex(0, 2), complex(-nan, -inf)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(1, 0), complex(inf, -nan)},
- Test{complex(inf, -1), complex(1, 1), complex(inf, -inf)},
- Test{complex(inf, -1), complex(1, -1), complex(inf, inf)},
- Test{complex(inf, -1), complex(1, 2), complex(inf, -inf)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-1, 0), complex(-inf, -nan)},
- Test{complex(inf, -1), complex(-1, 1), complex(-inf, -inf)},
- Test{complex(inf, -1), complex(-1, -1), complex(-inf, inf)},
- Test{complex(inf, -1), complex(-1, 2), complex(-inf, -inf)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(2, 0), complex(inf, -nan)},
- Test{complex(inf, -1), complex(2, 1), complex(inf, -inf)},
- Test{complex(inf, -1), complex(2, -1), complex(inf, inf)},
- Test{complex(inf, -1), complex(2, 2), complex(inf, -inf)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(inf, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(inf, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(inf, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(0, 0), complex(inf, inf)},
- Test{complex(inf, 2), complex(0, 1), complex(-nan, -inf)},
- Test{complex(inf, 2), complex(0, -1), complex(-nan, inf)},
- Test{complex(inf, 2), complex(0, 2), complex(-nan, -inf)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(1, 0), complex(inf, -nan)},
- Test{complex(inf, 2), complex(1, 1), complex(inf, -inf)},
- Test{complex(inf, 2), complex(1, -1), complex(inf, inf)},
- Test{complex(inf, 2), complex(1, 2), complex(inf, -inf)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-1, 0), complex(-inf, -nan)},
- Test{complex(inf, 2), complex(-1, 1), complex(-inf, -inf)},
- Test{complex(inf, 2), complex(-1, -1), complex(-inf, inf)},
- Test{complex(inf, 2), complex(-1, 2), complex(-inf, -inf)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(2, 0), complex(inf, -nan)},
- Test{complex(inf, 2), complex(2, 1), complex(inf, -inf)},
- Test{complex(inf, 2), complex(2, -1), complex(inf, inf)},
- Test{complex(inf, 2), complex(2, 2), complex(inf, -inf)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(inf, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(inf, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(inf, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(0, 0), complex(-inf, -nan)},
- Test{complex(-inf, 0), complex(0, 1), complex(-nan, inf)},
- Test{complex(-inf, 0), complex(0, -1), complex(-nan, -inf)},
- Test{complex(-inf, 0), complex(0, 2), complex(-nan, inf)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(1, 0), complex(-inf, -nan)},
- Test{complex(-inf, 0), complex(1, 1), complex(-inf, inf)},
- Test{complex(-inf, 0), complex(1, -1), complex(-inf, -inf)},
- Test{complex(-inf, 0), complex(1, 2), complex(-inf, inf)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-1, 0), complex(inf, -nan)},
- Test{complex(-inf, 0), complex(-1, 1), complex(inf, inf)},
- Test{complex(-inf, 0), complex(-1, -1), complex(inf, -inf)},
- Test{complex(-inf, 0), complex(-1, 2), complex(inf, inf)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(2, 0), complex(-inf, -nan)},
- Test{complex(-inf, 0), complex(2, 1), complex(-inf, inf)},
- Test{complex(-inf, 0), complex(2, -1), complex(-inf, -inf)},
- Test{complex(-inf, 0), complex(2, 2), complex(-inf, inf)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(nan, 0), complex(nan, nan)},
- Test{complex(-inf, 0), complex(nan, 1), complex(nan, nan)},
- Test{complex(-inf, 0), complex(nan, -1), complex(nan, nan)},
- Test{complex(-inf, 0), complex(nan, 2), complex(nan, nan)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(0, 0), complex(-inf, inf)},
- Test{complex(-inf, 1), complex(0, 1), complex(-nan, inf)},
- Test{complex(-inf, 1), complex(0, -1), complex(-nan, -inf)},
- Test{complex(-inf, 1), complex(0, 2), complex(-nan, inf)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(1, 0), complex(-inf, -nan)},
- Test{complex(-inf, 1), complex(1, 1), complex(-inf, inf)},
- Test{complex(-inf, 1), complex(1, -1), complex(-inf, -inf)},
- Test{complex(-inf, 1), complex(1, 2), complex(-inf, inf)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-1, 0), complex(inf, -nan)},
- Test{complex(-inf, 1), complex(-1, 1), complex(inf, inf)},
- Test{complex(-inf, 1), complex(-1, -1), complex(inf, -inf)},
- Test{complex(-inf, 1), complex(-1, 2), complex(inf, inf)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(2, 0), complex(-inf, -nan)},
- Test{complex(-inf, 1), complex(2, 1), complex(-inf, inf)},
- Test{complex(-inf, 1), complex(2, -1), complex(-inf, -inf)},
- Test{complex(-inf, 1), complex(2, 2), complex(-inf, inf)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(nan, 0), complex(nan, nan)},
- Test{complex(-inf, 1), complex(nan, 1), complex(nan, nan)},
- Test{complex(-inf, 1), complex(nan, -1), complex(nan, nan)},
- Test{complex(-inf, 1), complex(nan, 2), complex(nan, nan)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(0, 0), complex(-inf, -inf)},
- Test{complex(-inf, -1), complex(0, 1), complex(-nan, inf)},
- Test{complex(-inf, -1), complex(0, -1), complex(-nan, -inf)},
- Test{complex(-inf, -1), complex(0, 2), complex(-nan, inf)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(1, 0), complex(-inf, -nan)},
- Test{complex(-inf, -1), complex(1, 1), complex(-inf, inf)},
- Test{complex(-inf, -1), complex(1, -1), complex(-inf, -inf)},
- Test{complex(-inf, -1), complex(1, 2), complex(-inf, inf)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-1, 0), complex(inf, -nan)},
- Test{complex(-inf, -1), complex(-1, 1), complex(inf, inf)},
- Test{complex(-inf, -1), complex(-1, -1), complex(inf, -inf)},
- Test{complex(-inf, -1), complex(-1, 2), complex(inf, inf)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(2, 0), complex(-inf, -nan)},
- Test{complex(-inf, -1), complex(2, 1), complex(-inf, inf)},
- Test{complex(-inf, -1), complex(2, -1), complex(-inf, -inf)},
- Test{complex(-inf, -1), complex(2, 2), complex(-inf, inf)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(nan, 0), complex(nan, nan)},
- Test{complex(-inf, -1), complex(nan, 1), complex(nan, nan)},
- Test{complex(-inf, -1), complex(nan, -1), complex(nan, nan)},
- Test{complex(-inf, -1), complex(nan, 2), complex(nan, nan)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(0, 0), complex(-inf, inf)},
- Test{complex(-inf, 2), complex(0, 1), complex(-nan, inf)},
- Test{complex(-inf, 2), complex(0, -1), complex(-nan, -inf)},
- Test{complex(-inf, 2), complex(0, 2), complex(-nan, inf)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(1, 0), complex(-inf, -nan)},
- Test{complex(-inf, 2), complex(1, 1), complex(-inf, inf)},
- Test{complex(-inf, 2), complex(1, -1), complex(-inf, -inf)},
- Test{complex(-inf, 2), complex(1, 2), complex(-inf, inf)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-1, 0), complex(inf, -nan)},
- Test{complex(-inf, 2), complex(-1, 1), complex(inf, inf)},
- Test{complex(-inf, 2), complex(-1, -1), complex(inf, -inf)},
- Test{complex(-inf, 2), complex(-1, 2), complex(inf, inf)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(2, 0), complex(-inf, -nan)},
- Test{complex(-inf, 2), complex(2, 1), complex(-inf, inf)},
- Test{complex(-inf, 2), complex(2, -1), complex(-inf, -inf)},
- Test{complex(-inf, 2), complex(2, 2), complex(-inf, inf)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(nan, 0), complex(nan, nan)},
- Test{complex(-inf, 2), complex(nan, 1), complex(nan, nan)},
- Test{complex(-inf, 2), complex(nan, -1), complex(nan, nan)},
- Test{complex(-inf, 2), complex(nan, 2), complex(nan, nan)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
- Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
- Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
- Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
- Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
- Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
- Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
- Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
- Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
- Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
- Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
- Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
- Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
- Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
- Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
- Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
- Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
- Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
- Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+
+import "math"
+
+var (
+ nan = math.NaN()
+ inf = math.Inf(1)
+ zero = 0.0
+)
+
+var tests = []struct {
+ f, g complex128
+ out complex128
+}{
+ {complex(zero, zero), complex(zero, zero), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, -zero), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(zero, -1), complex(-zero, zero)},
+ {complex(zero, zero), complex(zero, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(zero, zero), complex(nan, nan)},
+ {complex(zero, zero), complex(-zero, -zero), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(-zero, -1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(zero, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(1, zero), complex(zero, zero)},
+ {complex(zero, zero), complex(1, -zero), complex(zero, zero)},
+ {complex(zero, zero), complex(1, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(1, -1), complex(zero, zero)},
+ {complex(zero, zero), complex(1, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(-1, zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, -zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, 1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, -1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, 2), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(2, zero), complex(zero, zero)},
+ {complex(zero, zero), complex(2, -zero), complex(zero, zero)},
+ {complex(zero, zero), complex(2, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(2, -1), complex(zero, zero)},
+ {complex(zero, zero), complex(2, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(inf, zero), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(zero, zero), complex(nan, nan)},
+ {complex(zero, -zero), complex(zero, -zero), complex(nan, nan)},
+ {complex(zero, -zero), complex(zero, 1), complex(zero, -zero)},
+ {complex(zero, -zero), complex(zero, -1), complex(zero, -zero)},
+ {complex(zero, -zero), complex(zero, 2), complex(zero, -zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(zero, zero), complex(nan, nan)},
+ {complex(zero, -zero), complex(-zero, -zero), complex(nan, nan)},
+ {complex(zero, -zero), complex(zero, 1), complex(zero, -zero)},
+ {complex(zero, -zero), complex(-zero, -1), complex(-zero, zero)},
+ {complex(zero, -zero), complex(zero, 2), complex(zero, -zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(1, zero), complex(zero, -zero)},
+ {complex(zero, -zero), complex(1, -zero), complex(zero, zero)},
+ {complex(zero, -zero), complex(1, 1), complex(zero, -zero)},
+ {complex(zero, -zero), complex(1, -1), complex(zero, zero)},
+ {complex(zero, -zero), complex(1, 2), complex(zero, -zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(-1, zero), complex(-zero, -zero)},
+ {complex(zero, -zero), complex(-1, -zero), complex(-zero, zero)},
+ {complex(zero, -zero), complex(-1, 1), complex(-zero, -zero)},
+ {complex(zero, -zero), complex(-1, -1), complex(-zero, zero)},
+ {complex(zero, -zero), complex(-1, 2), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(2, zero), complex(zero, -zero)},
+ {complex(zero, -zero), complex(2, -zero), complex(zero, zero)},
+ {complex(zero, -zero), complex(2, 1), complex(zero, -zero)},
+ {complex(zero, -zero), complex(2, -1), complex(zero, zero)},
+ {complex(zero, -zero), complex(2, 2), complex(zero, -zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(inf, zero), complex(zero, -zero)},
+ {complex(zero, -zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, -zero), complex(inf, 1), complex(zero, -zero)},
+ {complex(zero, -zero), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, -zero), complex(inf, 2), complex(zero, -zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, -zero), complex(-inf, -zero), complex(-zero, zero)},
+ {complex(zero, -zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, -zero), complex(-inf, -1), complex(-zero, zero)},
+ {complex(zero, -zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -zero), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, 1), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 1), complex(zero, -zero), complex(nan, inf)},
+ {complex(zero, 1), complex(zero, 1), complex(1, zero)},
+ {complex(zero, 1), complex(zero, -1), complex(-1, zero)},
+ {complex(zero, 1), complex(zero, 2), complex(0.5, zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 1), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(zero, 1), complex(zero, 1), complex(1, zero)},
+ {complex(zero, 1), complex(-zero, -1), complex(-1, -zero)},
+ {complex(zero, 1), complex(zero, 2), complex(0.5, zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(1, zero), complex(zero, 1)},
+ {complex(zero, 1), complex(1, -zero), complex(zero, 1)},
+ {complex(zero, 1), complex(1, 1), complex(0.5, 0.5)},
+ {complex(zero, 1), complex(1, -1), complex(-0.5, 0.5)},
+ {complex(zero, 1), complex(1, 2), complex(0.4, 0.2)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(-1, zero), complex(-zero, -1)},
+ {complex(zero, 1), complex(-1, -zero), complex(-zero, -1)},
+ {complex(zero, 1), complex(-1, 1), complex(0.5, -0.5)},
+ {complex(zero, 1), complex(-1, -1), complex(-0.5, -0.5)},
+ {complex(zero, 1), complex(-1, 2), complex(0.4, -0.2)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(2, zero), complex(zero, 0.5)},
+ {complex(zero, 1), complex(2, -zero), complex(zero, 0.5)},
+ {complex(zero, 1), complex(2, 1), complex(0.2, 0.4)},
+ {complex(zero, 1), complex(2, -1), complex(-0.2, 0.4)},
+ {complex(zero, 1), complex(2, 2), complex(0.25, 0.25)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(inf, zero), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, 1), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, 2), complex(zero, zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(zero, zero), complex(nan, -inf)},
+ {complex(zero, -1), complex(zero, -zero), complex(nan, -inf)},
+ {complex(zero, -1), complex(zero, 1), complex(-1, -zero)},
+ {complex(zero, -1), complex(zero, -1), complex(1, -zero)},
+ {complex(zero, -1), complex(zero, 2), complex(-0.5, -zero)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(zero, zero), complex(nan, -inf)},
+ {complex(zero, -1), complex(-zero, -zero), complex(nan, inf)},
+ {complex(zero, -1), complex(zero, 1), complex(-1, -zero)},
+ {complex(zero, -1), complex(-zero, -1), complex(1, zero)},
+ {complex(zero, -1), complex(zero, 2), complex(-0.5, -zero)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(1, zero), complex(zero, -1)},
+ {complex(zero, -1), complex(1, -zero), complex(zero, -1)},
+ {complex(zero, -1), complex(1, 1), complex(-0.5, -0.5)},
+ {complex(zero, -1), complex(1, -1), complex(0.5, -0.5)},
+ {complex(zero, -1), complex(1, 2), complex(-0.4, -0.2)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(-1, zero), complex(-zero, 1)},
+ {complex(zero, -1), complex(-1, -zero), complex(-zero, 1)},
+ {complex(zero, -1), complex(-1, 1), complex(-0.5, 0.5)},
+ {complex(zero, -1), complex(-1, -1), complex(0.5, 0.5)},
+ {complex(zero, -1), complex(-1, 2), complex(-0.4, 0.2)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(2, zero), complex(zero, -0.5)},
+ {complex(zero, -1), complex(2, -zero), complex(zero, -0.5)},
+ {complex(zero, -1), complex(2, 1), complex(-0.2, -0.4)},
+ {complex(zero, -1), complex(2, -1), complex(0.2, -0.4)},
+ {complex(zero, -1), complex(2, 2), complex(-0.25, -0.25)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(inf, zero), complex(zero, -zero)},
+ {complex(zero, -1), complex(inf, -zero), complex(zero, -zero)},
+ {complex(zero, -1), complex(inf, 1), complex(zero, -zero)},
+ {complex(zero, -1), complex(inf, -1), complex(zero, -zero)},
+ {complex(zero, -1), complex(inf, 2), complex(zero, -zero)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, -1), complex(-inf, zero), complex(-zero, zero)},
+ {complex(zero, -1), complex(-inf, -zero), complex(-zero, zero)},
+ {complex(zero, -1), complex(-inf, 1), complex(-zero, zero)},
+ {complex(zero, -1), complex(-inf, -1), complex(-zero, zero)},
+ {complex(zero, -1), complex(-inf, 2), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, 2), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 2), complex(zero, -zero), complex(nan, inf)},
+ {complex(zero, 2), complex(zero, 1), complex(2, zero)},
+ {complex(zero, 2), complex(zero, -1), complex(-2, zero)},
+ {complex(zero, 2), complex(zero, 2), complex(1, zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 2), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(zero, 2), complex(zero, 1), complex(2, zero)},
+ {complex(zero, 2), complex(-zero, -1), complex(-2, -zero)},
+ {complex(zero, 2), complex(zero, 2), complex(1, zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(1, zero), complex(zero, 2)},
+ {complex(zero, 2), complex(1, -zero), complex(zero, 2)},
+ {complex(zero, 2), complex(1, 1), complex(1, 1)},
+ {complex(zero, 2), complex(1, -1), complex(-1, 1)},
+ {complex(zero, 2), complex(1, 2), complex(0.8, 0.4)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(-1, zero), complex(-zero, -2)},
+ {complex(zero, 2), complex(-1, -zero), complex(-zero, -2)},
+ {complex(zero, 2), complex(-1, 1), complex(1, -1)},
+ {complex(zero, 2), complex(-1, -1), complex(-1, -1)},
+ {complex(zero, 2), complex(-1, 2), complex(0.8, -0.4)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(2, zero), complex(zero, 1)},
+ {complex(zero, 2), complex(2, -zero), complex(zero, 1)},
+ {complex(zero, 2), complex(2, 1), complex(0.4, 0.8)},
+ {complex(zero, 2), complex(2, -1), complex(-0.4, 0.8)},
+ {complex(zero, 2), complex(2, 2), complex(0.5, 0.5)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(inf, zero), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, 1), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, 2), complex(zero, zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, zero), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, -zero), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(zero, -1), complex(-zero, zero)},
+ {complex(zero, zero), complex(zero, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(zero, zero), complex(nan, nan)},
+ {complex(zero, zero), complex(-zero, -zero), complex(nan, nan)},
+ {complex(zero, zero), complex(zero, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(-zero, -1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(zero, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(1, zero), complex(zero, zero)},
+ {complex(zero, zero), complex(1, -zero), complex(zero, zero)},
+ {complex(zero, zero), complex(1, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(1, -1), complex(zero, zero)},
+ {complex(zero, zero), complex(1, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(-1, zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, -zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, 1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, -1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-1, 2), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(2, zero), complex(zero, zero)},
+ {complex(zero, zero), complex(2, -zero), complex(zero, zero)},
+ {complex(zero, zero), complex(2, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(2, -1), complex(zero, zero)},
+ {complex(zero, zero), complex(2, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(inf, zero), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, 1), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, zero), complex(inf, 2), complex(zero, zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(zero, zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(zero, zero), complex(nan, nan)},
+ {complex(-zero, -zero), complex(zero, -zero), complex(nan, nan)},
+ {complex(-zero, -zero), complex(zero, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(zero, -1), complex(-zero, -zero)},
+ {complex(-zero, -zero), complex(zero, 2), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(zero, zero), complex(nan, nan)},
+ {complex(-zero, -zero), complex(-zero, -zero), complex(nan, nan)},
+ {complex(-zero, -zero), complex(zero, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(-zero, -1), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(zero, 2), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(1, zero), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(1, -zero), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(1, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(1, -1), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(1, 2), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(-1, zero), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(-1, -zero), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(-1, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(-1, -1), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(-1, 2), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(2, zero), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(2, -zero), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(2, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(2, -1), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(2, 2), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(inf, zero), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(inf, -zero), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(inf, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(inf, -1), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(inf, 2), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(-inf, zero), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(-inf, -zero), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(-inf, 1), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(-inf, -1), complex(zero, -zero)},
+ {complex(-zero, -zero), complex(-inf, 2), complex(-zero, zero)},
+ {complex(-zero, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-zero, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, 1), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 1), complex(zero, -zero), complex(nan, inf)},
+ {complex(zero, 1), complex(zero, 1), complex(1, zero)},
+ {complex(zero, 1), complex(zero, -1), complex(-1, zero)},
+ {complex(zero, 1), complex(zero, 2), complex(0.5, zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 1), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(zero, 1), complex(zero, 1), complex(1, zero)},
+ {complex(zero, 1), complex(-zero, -1), complex(-1, -zero)},
+ {complex(zero, 1), complex(zero, 2), complex(0.5, zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(1, zero), complex(zero, 1)},
+ {complex(zero, 1), complex(1, -zero), complex(zero, 1)},
+ {complex(zero, 1), complex(1, 1), complex(0.5, 0.5)},
+ {complex(zero, 1), complex(1, -1), complex(-0.5, 0.5)},
+ {complex(zero, 1), complex(1, 2), complex(0.4, 0.2)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(-1, zero), complex(-zero, -1)},
+ {complex(zero, 1), complex(-1, -zero), complex(-zero, -1)},
+ {complex(zero, 1), complex(-1, 1), complex(0.5, -0.5)},
+ {complex(zero, 1), complex(-1, -1), complex(-0.5, -0.5)},
+ {complex(zero, 1), complex(-1, 2), complex(0.4, -0.2)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(2, zero), complex(zero, 0.5)},
+ {complex(zero, 1), complex(2, -zero), complex(zero, 0.5)},
+ {complex(zero, 1), complex(2, 1), complex(0.2, 0.4)},
+ {complex(zero, 1), complex(2, -1), complex(-0.2, 0.4)},
+ {complex(zero, 1), complex(2, 2), complex(0.25, 0.25)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(inf, zero), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, 1), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, 1), complex(inf, 2), complex(zero, zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 1), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(zero, 1), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(zero, zero), complex(nan, -inf)},
+ {complex(-zero, -1), complex(zero, -zero), complex(nan, -inf)},
+ {complex(-zero, -1), complex(zero, 1), complex(-1, zero)},
+ {complex(-zero, -1), complex(zero, -1), complex(1, -zero)},
+ {complex(-zero, -1), complex(zero, 2), complex(-0.5, zero)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(zero, zero), complex(nan, -inf)},
+ {complex(-zero, -1), complex(-zero, -zero), complex(nan, inf)},
+ {complex(-zero, -1), complex(zero, 1), complex(-1, zero)},
+ {complex(-zero, -1), complex(-zero, -1), complex(1, -zero)},
+ {complex(-zero, -1), complex(zero, 2), complex(-0.5, zero)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(1, zero), complex(-zero, -1)},
+ {complex(-zero, -1), complex(1, -zero), complex(zero, -1)},
+ {complex(-zero, -1), complex(1, 1), complex(-0.5, -0.5)},
+ {complex(-zero, -1), complex(1, -1), complex(0.5, -0.5)},
+ {complex(-zero, -1), complex(1, 2), complex(-0.4, -0.2)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(-1, zero), complex(-zero, 1)},
+ {complex(-zero, -1), complex(-1, -zero), complex(zero, 1)},
+ {complex(-zero, -1), complex(-1, 1), complex(-0.5, 0.5)},
+ {complex(-zero, -1), complex(-1, -1), complex(0.5, 0.5)},
+ {complex(-zero, -1), complex(-1, 2), complex(-0.4, 0.2)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(2, zero), complex(-zero, -0.5)},
+ {complex(-zero, -1), complex(2, -zero), complex(zero, -0.5)},
+ {complex(-zero, -1), complex(2, 1), complex(-0.2, -0.4)},
+ {complex(-zero, -1), complex(2, -1), complex(0.2, -0.4)},
+ {complex(-zero, -1), complex(2, 2), complex(-0.25, -0.25)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(inf, zero), complex(-zero, -zero)},
+ {complex(-zero, -1), complex(inf, -zero), complex(zero, -zero)},
+ {complex(-zero, -1), complex(inf, 1), complex(-zero, -zero)},
+ {complex(-zero, -1), complex(inf, -1), complex(zero, -zero)},
+ {complex(-zero, -1), complex(inf, 2), complex(-zero, -zero)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(-zero, -1), complex(-inf, zero), complex(-zero, zero)},
+ {complex(-zero, -1), complex(-inf, -zero), complex(zero, zero)},
+ {complex(-zero, -1), complex(-inf, 1), complex(-zero, zero)},
+ {complex(-zero, -1), complex(-inf, -1), complex(zero, zero)},
+ {complex(-zero, -1), complex(-inf, 2), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-zero, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-zero, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(zero, 2), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 2), complex(zero, -zero), complex(nan, inf)},
+ {complex(zero, 2), complex(zero, 1), complex(2, zero)},
+ {complex(zero, 2), complex(zero, -1), complex(-2, zero)},
+ {complex(zero, 2), complex(zero, 2), complex(1, zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(zero, zero), complex(nan, inf)},
+ {complex(zero, 2), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(zero, 2), complex(zero, 1), complex(2, zero)},
+ {complex(zero, 2), complex(-zero, -1), complex(-2, -zero)},
+ {complex(zero, 2), complex(zero, 2), complex(1, zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(1, zero), complex(zero, 2)},
+ {complex(zero, 2), complex(1, -zero), complex(zero, 2)},
+ {complex(zero, 2), complex(1, 1), complex(1, 1)},
+ {complex(zero, 2), complex(1, -1), complex(-1, 1)},
+ {complex(zero, 2), complex(1, 2), complex(0.8, 0.4)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(-1, zero), complex(-zero, -2)},
+ {complex(zero, 2), complex(-1, -zero), complex(-zero, -2)},
+ {complex(zero, 2), complex(-1, 1), complex(1, -1)},
+ {complex(zero, 2), complex(-1, -1), complex(-1, -1)},
+ {complex(zero, 2), complex(-1, 2), complex(0.8, -0.4)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(2, zero), complex(zero, 1)},
+ {complex(zero, 2), complex(2, -zero), complex(zero, 1)},
+ {complex(zero, 2), complex(2, 1), complex(0.4, 0.8)},
+ {complex(zero, 2), complex(2, -1), complex(-0.4, 0.8)},
+ {complex(zero, 2), complex(2, 2), complex(0.5, 0.5)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(inf, zero), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, -zero), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, 1), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, -1), complex(zero, zero)},
+ {complex(zero, 2), complex(inf, 2), complex(zero, zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(zero, 2), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(zero, 2), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(zero, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(zero, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(zero, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(1, zero), complex(zero, zero), complex(inf, nan)},
+ {complex(1, zero), complex(zero, -zero), complex(inf, nan)},
+ {complex(1, zero), complex(zero, 1), complex(zero, -1)},
+ {complex(1, zero), complex(zero, -1), complex(-zero, 1)},
+ {complex(1, zero), complex(zero, 2), complex(zero, -0.5)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(zero, zero), complex(inf, nan)},
+ {complex(1, zero), complex(-zero, -zero), complex(-inf, nan)},
+ {complex(1, zero), complex(zero, 1), complex(zero, -1)},
+ {complex(1, zero), complex(-zero, -1), complex(-zero, 1)},
+ {complex(1, zero), complex(zero, 2), complex(zero, -0.5)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(1, zero), complex(1, zero)},
+ {complex(1, zero), complex(1, -zero), complex(1, zero)},
+ {complex(1, zero), complex(1, 1), complex(0.5, -0.5)},
+ {complex(1, zero), complex(1, -1), complex(0.5, 0.5)},
+ {complex(1, zero), complex(1, 2), complex(0.2, -0.4)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(-1, zero), complex(-1, -zero)},
+ {complex(1, zero), complex(-1, -zero), complex(-1, -zero)},
+ {complex(1, zero), complex(-1, 1), complex(-0.5, -0.5)},
+ {complex(1, zero), complex(-1, -1), complex(-0.5, 0.5)},
+ {complex(1, zero), complex(-1, 2), complex(-0.2, -0.4)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(2, zero), complex(0.5, zero)},
+ {complex(1, zero), complex(2, -zero), complex(0.5, zero)},
+ {complex(1, zero), complex(2, 1), complex(0.4, -0.2)},
+ {complex(1, zero), complex(2, -1), complex(0.4, 0.2)},
+ {complex(1, zero), complex(2, 2), complex(0.25, -0.25)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(1, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(1, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(1, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(1, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(inf, zero), complex(zero, zero)},
+ {complex(1, zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(1, zero), complex(inf, 1), complex(zero, zero)},
+ {complex(1, zero), complex(inf, -1), complex(zero, zero)},
+ {complex(1, zero), complex(inf, 2), complex(zero, zero)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(1, zero), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(1, zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(1, zero), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(1, zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, -zero), complex(zero, zero), complex(inf, nan)},
+ {complex(1, -zero), complex(zero, -zero), complex(inf, nan)},
+ {complex(1, -zero), complex(zero, 1), complex(zero, -1)},
+ {complex(1, -zero), complex(zero, -1), complex(zero, 1)},
+ {complex(1, -zero), complex(zero, 2), complex(zero, -0.5)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(zero, zero), complex(inf, nan)},
+ {complex(1, -zero), complex(-zero, -zero), complex(-inf, nan)},
+ {complex(1, -zero), complex(zero, 1), complex(zero, -1)},
+ {complex(1, -zero), complex(-zero, -1), complex(-zero, 1)},
+ {complex(1, -zero), complex(zero, 2), complex(zero, -0.5)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(1, zero), complex(1, -zero)},
+ {complex(1, -zero), complex(1, -zero), complex(1, zero)},
+ {complex(1, -zero), complex(1, 1), complex(0.5, -0.5)},
+ {complex(1, -zero), complex(1, -1), complex(0.5, 0.5)},
+ {complex(1, -zero), complex(1, 2), complex(0.2, -0.4)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(-1, zero), complex(-1, -zero)},
+ {complex(1, -zero), complex(-1, -zero), complex(-1, zero)},
+ {complex(1, -zero), complex(-1, 1), complex(-0.5, -0.5)},
+ {complex(1, -zero), complex(-1, -1), complex(-0.5, 0.5)},
+ {complex(1, -zero), complex(-1, 2), complex(-0.2, -0.4)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(2, zero), complex(0.5, -zero)},
+ {complex(1, -zero), complex(2, -zero), complex(0.5, zero)},
+ {complex(1, -zero), complex(2, 1), complex(0.4, -0.2)},
+ {complex(1, -zero), complex(2, -1), complex(0.4, 0.2)},
+ {complex(1, -zero), complex(2, 2), complex(0.25, -0.25)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(inf, zero), complex(zero, -zero)},
+ {complex(1, -zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(1, -zero), complex(inf, 1), complex(zero, -zero)},
+ {complex(1, -zero), complex(inf, -1), complex(zero, zero)},
+ {complex(1, -zero), complex(inf, 2), complex(zero, -zero)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(1, -zero), complex(-inf, -zero), complex(-zero, zero)},
+ {complex(1, -zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(1, -zero), complex(-inf, -1), complex(-zero, zero)},
+ {complex(1, -zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, 1), complex(zero, zero), complex(inf, inf)},
+ {complex(1, 1), complex(zero, -zero), complex(inf, inf)},
+ {complex(1, 1), complex(zero, 1), complex(1, -1)},
+ {complex(1, 1), complex(zero, -1), complex(-1, 1)},
+ {complex(1, 1), complex(zero, 2), complex(0.5, -0.5)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(zero, zero), complex(inf, inf)},
+ {complex(1, 1), complex(-zero, -zero), complex(-inf, -inf)},
+ {complex(1, 1), complex(zero, 1), complex(1, -1)},
+ {complex(1, 1), complex(-zero, -1), complex(-1, 1)},
+ {complex(1, 1), complex(zero, 2), complex(0.5, -0.5)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(1, zero), complex(1, 1)},
+ {complex(1, 1), complex(1, -zero), complex(1, 1)},
+ {complex(1, 1), complex(1, 1), complex(1, zero)},
+ {complex(1, 1), complex(1, -1), complex(zero, 1)},
+ {complex(1, 1), complex(1, 2), complex(0.6, -0.2)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(-1, zero), complex(-1, -1)},
+ {complex(1, 1), complex(-1, -zero), complex(-1, -1)},
+ {complex(1, 1), complex(-1, 1), complex(-zero, -1)},
+ {complex(1, 1), complex(-1, -1), complex(-1, -zero)},
+ {complex(1, 1), complex(-1, 2), complex(0.2, -0.6)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(2, zero), complex(0.5, 0.5)},
+ {complex(1, 1), complex(2, -zero), complex(0.5, 0.5)},
+ {complex(1, 1), complex(2, 1), complex(0.6, 0.2)},
+ {complex(1, 1), complex(2, -1), complex(0.2, 0.6)},
+ {complex(1, 1), complex(2, 2), complex(0.5, zero)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(1, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(1, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(1, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(1, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(inf, zero), complex(zero, zero)},
+ {complex(1, 1), complex(inf, -zero), complex(zero, zero)},
+ {complex(1, 1), complex(inf, 1), complex(zero, zero)},
+ {complex(1, 1), complex(inf, -1), complex(zero, zero)},
+ {complex(1, 1), complex(inf, 2), complex(zero, zero)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 1), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(1, 1), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(1, 1), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(1, 1), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(1, 1), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, -1), complex(zero, zero), complex(inf, -inf)},
+ {complex(1, -1), complex(zero, -zero), complex(inf, -inf)},
+ {complex(1, -1), complex(zero, 1), complex(-1, -1)},
+ {complex(1, -1), complex(zero, -1), complex(1, 1)},
+ {complex(1, -1), complex(zero, 2), complex(-0.5, -0.5)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(zero, zero), complex(inf, -inf)},
+ {complex(1, -1), complex(-zero, -zero), complex(-inf, inf)},
+ {complex(1, -1), complex(zero, 1), complex(-1, -1)},
+ {complex(1, -1), complex(-zero, -1), complex(1, 1)},
+ {complex(1, -1), complex(zero, 2), complex(-0.5, -0.5)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(1, zero), complex(1, -1)},
+ {complex(1, -1), complex(1, -zero), complex(1, -1)},
+ {complex(1, -1), complex(1, 1), complex(zero, -1)},
+ {complex(1, -1), complex(1, -1), complex(1, zero)},
+ {complex(1, -1), complex(1, 2), complex(-0.2, -0.6)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(-1, zero), complex(-1, 1)},
+ {complex(1, -1), complex(-1, -zero), complex(-1, 1)},
+ {complex(1, -1), complex(-1, 1), complex(-1, -zero)},
+ {complex(1, -1), complex(-1, -1), complex(-zero, 1)},
+ {complex(1, -1), complex(-1, 2), complex(-0.6, -0.2)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(2, zero), complex(0.5, -0.5)},
+ {complex(1, -1), complex(2, -zero), complex(0.5, -0.5)},
+ {complex(1, -1), complex(2, 1), complex(0.2, -0.6)},
+ {complex(1, -1), complex(2, -1), complex(0.6, -0.2)},
+ {complex(1, -1), complex(2, 2), complex(zero, -0.5)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(1, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(1, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(1, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(1, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(inf, zero), complex(zero, -zero)},
+ {complex(1, -1), complex(inf, -zero), complex(zero, -zero)},
+ {complex(1, -1), complex(inf, 1), complex(zero, -zero)},
+ {complex(1, -1), complex(inf, -1), complex(zero, -zero)},
+ {complex(1, -1), complex(inf, 2), complex(zero, -zero)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, -1), complex(-inf, zero), complex(-zero, zero)},
+ {complex(1, -1), complex(-inf, -zero), complex(-zero, zero)},
+ {complex(1, -1), complex(-inf, 1), complex(-zero, zero)},
+ {complex(1, -1), complex(-inf, -1), complex(-zero, zero)},
+ {complex(1, -1), complex(-inf, 2), complex(-zero, zero)},
+ {complex(1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(1, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(1, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(1, 2), complex(zero, zero), complex(inf, inf)},
+ {complex(1, 2), complex(zero, -zero), complex(inf, inf)},
+ {complex(1, 2), complex(zero, 1), complex(2, -1)},
+ {complex(1, 2), complex(zero, -1), complex(-2, 1)},
+ {complex(1, 2), complex(zero, 2), complex(1, -0.5)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(zero, zero), complex(inf, inf)},
+ {complex(1, 2), complex(-zero, -zero), complex(-inf, -inf)},
+ {complex(1, 2), complex(zero, 1), complex(2, -1)},
+ {complex(1, 2), complex(-zero, -1), complex(-2, 1)},
+ {complex(1, 2), complex(zero, 2), complex(1, -0.5)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(1, zero), complex(1, 2)},
+ {complex(1, 2), complex(1, -zero), complex(1, 2)},
+ {complex(1, 2), complex(1, 1), complex(1.5, 0.5)},
+ {complex(1, 2), complex(1, -1), complex(-0.5, 1.5)},
+ {complex(1, 2), complex(1, 2), complex(1, zero)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(-1, zero), complex(-1, -2)},
+ {complex(1, 2), complex(-1, -zero), complex(-1, -2)},
+ {complex(1, 2), complex(-1, 1), complex(0.5, -1.5)},
+ {complex(1, 2), complex(-1, -1), complex(-1.5, -0.5)},
+ {complex(1, 2), complex(-1, 2), complex(0.6, -0.8)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(2, zero), complex(0.5, 1)},
+ {complex(1, 2), complex(2, -zero), complex(0.5, 1)},
+ {complex(1, 2), complex(2, 1), complex(0.8, 0.6)},
+ {complex(1, 2), complex(2, -1), complex(zero, 1)},
+ {complex(1, 2), complex(2, 2), complex(0.75, 0.25)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(1, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(1, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(1, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(1, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(inf, zero), complex(zero, zero)},
+ {complex(1, 2), complex(inf, -zero), complex(zero, zero)},
+ {complex(1, 2), complex(inf, 1), complex(zero, zero)},
+ {complex(1, 2), complex(inf, -1), complex(zero, zero)},
+ {complex(1, 2), complex(inf, 2), complex(zero, zero)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(1, 2), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(1, 2), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(1, 2), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(1, 2), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(1, 2), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(1, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(1, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(-1, zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-1, zero), complex(zero, -zero), complex(-inf, nan)},
+ {complex(-1, zero), complex(zero, 1), complex(zero, 1)},
+ {complex(-1, zero), complex(zero, -1), complex(-zero, -1)},
+ {complex(-1, zero), complex(zero, 2), complex(zero, 0.5)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-1, zero), complex(-zero, -zero), complex(inf, nan)},
+ {complex(-1, zero), complex(zero, 1), complex(zero, 1)},
+ {complex(-1, zero), complex(-zero, -1), complex(-zero, -1)},
+ {complex(-1, zero), complex(zero, 2), complex(zero, 0.5)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(1, zero), complex(-1, zero)},
+ {complex(-1, zero), complex(1, -zero), complex(-1, zero)},
+ {complex(-1, zero), complex(1, 1), complex(-0.5, 0.5)},
+ {complex(-1, zero), complex(1, -1), complex(-0.5, -0.5)},
+ {complex(-1, zero), complex(1, 2), complex(-0.2, 0.4)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(-1, zero), complex(1, -zero)},
+ {complex(-1, zero), complex(-1, -zero), complex(1, -zero)},
+ {complex(-1, zero), complex(-1, 1), complex(0.5, 0.5)},
+ {complex(-1, zero), complex(-1, -1), complex(0.5, -0.5)},
+ {complex(-1, zero), complex(-1, 2), complex(0.2, 0.4)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(2, zero), complex(-0.5, zero)},
+ {complex(-1, zero), complex(2, -zero), complex(-0.5, zero)},
+ {complex(-1, zero), complex(2, 1), complex(-0.4, 0.2)},
+ {complex(-1, zero), complex(2, -1), complex(-0.4, -0.2)},
+ {complex(-1, zero), complex(2, 2), complex(-0.25, 0.25)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(inf, zero), complex(-zero, zero)},
+ {complex(-1, zero), complex(inf, -zero), complex(-zero, zero)},
+ {complex(-1, zero), complex(inf, 1), complex(-zero, zero)},
+ {complex(-1, zero), complex(inf, -1), complex(-zero, zero)},
+ {complex(-1, zero), complex(inf, 2), complex(-zero, zero)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, zero), complex(-inf, zero), complex(zero, -zero)},
+ {complex(-1, zero), complex(-inf, -zero), complex(zero, -zero)},
+ {complex(-1, zero), complex(-inf, 1), complex(zero, -zero)},
+ {complex(-1, zero), complex(-inf, -1), complex(zero, -zero)},
+ {complex(-1, zero), complex(-inf, 2), complex(zero, -zero)},
+ {complex(-1, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-1, -zero), complex(zero, -zero), complex(-inf, nan)},
+ {complex(-1, -zero), complex(zero, 1), complex(-zero, 1)},
+ {complex(-1, -zero), complex(zero, -1), complex(-zero, -1)},
+ {complex(-1, -zero), complex(zero, 2), complex(-zero, 0.5)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-1, -zero), complex(-zero, -zero), complex(inf, nan)},
+ {complex(-1, -zero), complex(zero, 1), complex(-zero, 1)},
+ {complex(-1, -zero), complex(-zero, -1), complex(zero, -1)},
+ {complex(-1, -zero), complex(zero, 2), complex(-zero, 0.5)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(1, zero), complex(-1, zero)},
+ {complex(-1, -zero), complex(1, -zero), complex(-1, -zero)},
+ {complex(-1, -zero), complex(1, 1), complex(-0.5, 0.5)},
+ {complex(-1, -zero), complex(1, -1), complex(-0.5, -0.5)},
+ {complex(-1, -zero), complex(1, 2), complex(-0.2, 0.4)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(-1, zero), complex(1, zero)},
+ {complex(-1, -zero), complex(-1, -zero), complex(1, -zero)},
+ {complex(-1, -zero), complex(-1, 1), complex(0.5, 0.5)},
+ {complex(-1, -zero), complex(-1, -1), complex(0.5, -0.5)},
+ {complex(-1, -zero), complex(-1, 2), complex(0.2, 0.4)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(2, zero), complex(-0.5, zero)},
+ {complex(-1, -zero), complex(2, -zero), complex(-0.5, -zero)},
+ {complex(-1, -zero), complex(2, 1), complex(-0.4, 0.2)},
+ {complex(-1, -zero), complex(2, -1), complex(-0.4, -0.2)},
+ {complex(-1, -zero), complex(2, 2), complex(-0.25, 0.25)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(inf, zero), complex(-zero, zero)},
+ {complex(-1, -zero), complex(inf, -zero), complex(-zero, -zero)},
+ {complex(-1, -zero), complex(inf, 1), complex(-zero, zero)},
+ {complex(-1, -zero), complex(inf, -1), complex(-zero, -zero)},
+ {complex(-1, -zero), complex(inf, 2), complex(-zero, zero)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -zero), complex(-inf, zero), complex(zero, zero)},
+ {complex(-1, -zero), complex(-inf, -zero), complex(zero, -zero)},
+ {complex(-1, -zero), complex(-inf, 1), complex(zero, zero)},
+ {complex(-1, -zero), complex(-inf, -1), complex(zero, -zero)},
+ {complex(-1, -zero), complex(-inf, 2), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -zero), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, -zero), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, 1), complex(zero, zero), complex(-inf, inf)},
+ {complex(-1, 1), complex(zero, -zero), complex(-inf, inf)},
+ {complex(-1, 1), complex(zero, 1), complex(1, 1)},
+ {complex(-1, 1), complex(zero, -1), complex(-1, -1)},
+ {complex(-1, 1), complex(zero, 2), complex(0.5, 0.5)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(zero, zero), complex(-inf, inf)},
+ {complex(-1, 1), complex(-zero, -zero), complex(inf, -inf)},
+ {complex(-1, 1), complex(zero, 1), complex(1, 1)},
+ {complex(-1, 1), complex(-zero, -1), complex(-1, -1)},
+ {complex(-1, 1), complex(zero, 2), complex(0.5, 0.5)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(1, zero), complex(-1, 1)},
+ {complex(-1, 1), complex(1, -zero), complex(-1, 1)},
+ {complex(-1, 1), complex(1, 1), complex(zero, 1)},
+ {complex(-1, 1), complex(1, -1), complex(-1, zero)},
+ {complex(-1, 1), complex(1, 2), complex(0.2, 0.6)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(-1, zero), complex(1, -1)},
+ {complex(-1, 1), complex(-1, -zero), complex(1, -1)},
+ {complex(-1, 1), complex(-1, 1), complex(1, -zero)},
+ {complex(-1, 1), complex(-1, -1), complex(-zero, -1)},
+ {complex(-1, 1), complex(-1, 2), complex(0.6, 0.2)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(2, zero), complex(-0.5, 0.5)},
+ {complex(-1, 1), complex(2, -zero), complex(-0.5, 0.5)},
+ {complex(-1, 1), complex(2, 1), complex(-0.2, 0.6)},
+ {complex(-1, 1), complex(2, -1), complex(-0.6, 0.2)},
+ {complex(-1, 1), complex(2, 2), complex(zero, 0.5)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(inf, zero), complex(-zero, zero)},
+ {complex(-1, 1), complex(inf, -zero), complex(-zero, zero)},
+ {complex(-1, 1), complex(inf, 1), complex(-zero, zero)},
+ {complex(-1, 1), complex(inf, -1), complex(-zero, zero)},
+ {complex(-1, 1), complex(inf, 2), complex(-zero, zero)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 1), complex(-inf, zero), complex(zero, -zero)},
+ {complex(-1, 1), complex(-inf, -zero), complex(zero, -zero)},
+ {complex(-1, 1), complex(-inf, 1), complex(zero, -zero)},
+ {complex(-1, 1), complex(-inf, -1), complex(zero, -zero)},
+ {complex(-1, 1), complex(-inf, 2), complex(zero, -zero)},
+ {complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 1), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 1), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, -1), complex(zero, zero), complex(-inf, -inf)},
+ {complex(-1, -1), complex(zero, -zero), complex(-inf, -inf)},
+ {complex(-1, -1), complex(zero, 1), complex(-1, 1)},
+ {complex(-1, -1), complex(zero, -1), complex(1, -1)},
+ {complex(-1, -1), complex(zero, 2), complex(-0.5, 0.5)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(zero, zero), complex(-inf, -inf)},
+ {complex(-1, -1), complex(-zero, -zero), complex(inf, inf)},
+ {complex(-1, -1), complex(zero, 1), complex(-1, 1)},
+ {complex(-1, -1), complex(-zero, -1), complex(1, -1)},
+ {complex(-1, -1), complex(zero, 2), complex(-0.5, 0.5)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(1, zero), complex(-1, -1)},
+ {complex(-1, -1), complex(1, -zero), complex(-1, -1)},
+ {complex(-1, -1), complex(1, 1), complex(-1, zero)},
+ {complex(-1, -1), complex(1, -1), complex(zero, -1)},
+ {complex(-1, -1), complex(1, 2), complex(-0.6, 0.2)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(-1, zero), complex(1, 1)},
+ {complex(-1, -1), complex(-1, -zero), complex(1, 1)},
+ {complex(-1, -1), complex(-1, 1), complex(-zero, 1)},
+ {complex(-1, -1), complex(-1, -1), complex(1, -zero)},
+ {complex(-1, -1), complex(-1, 2), complex(-0.2, 0.6)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(2, zero), complex(-0.5, -0.5)},
+ {complex(-1, -1), complex(2, -zero), complex(-0.5, -0.5)},
+ {complex(-1, -1), complex(2, 1), complex(-0.6, -0.2)},
+ {complex(-1, -1), complex(2, -1), complex(-0.2, -0.6)},
+ {complex(-1, -1), complex(2, 2), complex(-0.5, zero)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(inf, zero), complex(-zero, -zero)},
+ {complex(-1, -1), complex(inf, -zero), complex(-zero, -zero)},
+ {complex(-1, -1), complex(inf, 1), complex(-zero, -zero)},
+ {complex(-1, -1), complex(inf, -1), complex(-zero, -zero)},
+ {complex(-1, -1), complex(inf, 2), complex(-zero, -zero)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, -1), complex(-inf, zero), complex(zero, zero)},
+ {complex(-1, -1), complex(-inf, -zero), complex(zero, zero)},
+ {complex(-1, -1), complex(-inf, 1), complex(zero, zero)},
+ {complex(-1, -1), complex(-inf, -1), complex(zero, zero)},
+ {complex(-1, -1), complex(-inf, 2), complex(zero, zero)},
+ {complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, -1), complex(nan, inf), complex(-zero, zero)},
+ {complex(-1, -1), complex(nan, -inf), complex(zero, -zero)},
+ {complex(-1, 2), complex(zero, zero), complex(-inf, inf)},
+ {complex(-1, 2), complex(zero, -zero), complex(-inf, inf)},
+ {complex(-1, 2), complex(zero, 1), complex(2, 1)},
+ {complex(-1, 2), complex(zero, -1), complex(-2, -1)},
+ {complex(-1, 2), complex(zero, 2), complex(1, 0.5)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(zero, zero), complex(-inf, inf)},
+ {complex(-1, 2), complex(-zero, -zero), complex(inf, -inf)},
+ {complex(-1, 2), complex(zero, 1), complex(2, 1)},
+ {complex(-1, 2), complex(-zero, -1), complex(-2, -1)},
+ {complex(-1, 2), complex(zero, 2), complex(1, 0.5)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(1, zero), complex(-1, 2)},
+ {complex(-1, 2), complex(1, -zero), complex(-1, 2)},
+ {complex(-1, 2), complex(1, 1), complex(0.5, 1.5)},
+ {complex(-1, 2), complex(1, -1), complex(-1.5, 0.5)},
+ {complex(-1, 2), complex(1, 2), complex(0.6, 0.8)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(-1, zero), complex(1, -2)},
+ {complex(-1, 2), complex(-1, -zero), complex(1, -2)},
+ {complex(-1, 2), complex(-1, 1), complex(1.5, -0.5)},
+ {complex(-1, 2), complex(-1, -1), complex(-0.5, -1.5)},
+ {complex(-1, 2), complex(-1, 2), complex(1, zero)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(2, zero), complex(-0.5, 1)},
+ {complex(-1, 2), complex(2, -zero), complex(-0.5, 1)},
+ {complex(-1, 2), complex(2, 1), complex(zero, 1)},
+ {complex(-1, 2), complex(2, -1), complex(-0.8, 0.6)},
+ {complex(-1, 2), complex(2, 2), complex(0.25, 0.75)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(inf, zero), complex(-zero, zero)},
+ {complex(-1, 2), complex(inf, -zero), complex(-zero, zero)},
+ {complex(-1, 2), complex(inf, 1), complex(-zero, zero)},
+ {complex(-1, 2), complex(inf, -1), complex(-zero, zero)},
+ {complex(-1, 2), complex(inf, 2), complex(-zero, zero)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(-1, 2), complex(-inf, zero), complex(zero, -zero)},
+ {complex(-1, 2), complex(-inf, -zero), complex(zero, -zero)},
+ {complex(-1, 2), complex(-inf, 1), complex(zero, -zero)},
+ {complex(-1, 2), complex(-inf, -1), complex(zero, -zero)},
+ {complex(-1, 2), complex(-inf, 2), complex(zero, -zero)},
+ {complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-1, 2), complex(nan, inf), complex(zero, zero)},
+ {complex(-1, 2), complex(nan, -inf), complex(-zero, -zero)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(2, zero), complex(zero, zero), complex(inf, nan)},
+ {complex(2, zero), complex(zero, -zero), complex(inf, nan)},
+ {complex(2, zero), complex(zero, 1), complex(zero, -2)},
+ {complex(2, zero), complex(zero, -1), complex(-zero, 2)},
+ {complex(2, zero), complex(zero, 2), complex(zero, -1)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(zero, zero), complex(inf, nan)},
+ {complex(2, zero), complex(-zero, -zero), complex(-inf, nan)},
+ {complex(2, zero), complex(zero, 1), complex(zero, -2)},
+ {complex(2, zero), complex(-zero, -1), complex(-zero, 2)},
+ {complex(2, zero), complex(zero, 2), complex(zero, -1)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(1, zero), complex(2, zero)},
+ {complex(2, zero), complex(1, -zero), complex(2, zero)},
+ {complex(2, zero), complex(1, 1), complex(1, -1)},
+ {complex(2, zero), complex(1, -1), complex(1, 1)},
+ {complex(2, zero), complex(1, 2), complex(0.4, -0.8)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(-1, zero), complex(-2, -zero)},
+ {complex(2, zero), complex(-1, -zero), complex(-2, -zero)},
+ {complex(2, zero), complex(-1, 1), complex(-1, -1)},
+ {complex(2, zero), complex(-1, -1), complex(-1, 1)},
+ {complex(2, zero), complex(-1, 2), complex(-0.4, -0.8)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(2, zero), complex(1, zero)},
+ {complex(2, zero), complex(2, -zero), complex(1, zero)},
+ {complex(2, zero), complex(2, 1), complex(0.8, -0.4)},
+ {complex(2, zero), complex(2, -1), complex(0.8, 0.4)},
+ {complex(2, zero), complex(2, 2), complex(0.5, -0.5)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(2, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(2, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(2, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(2, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(inf, zero), complex(zero, zero)},
+ {complex(2, zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(2, zero), complex(inf, 1), complex(zero, zero)},
+ {complex(2, zero), complex(inf, -1), complex(zero, zero)},
+ {complex(2, zero), complex(inf, 2), complex(zero, zero)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(2, zero), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(2, zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(2, zero), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(2, zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(2, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, zero), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, zero), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, -zero), complex(zero, zero), complex(inf, nan)},
+ {complex(2, -zero), complex(zero, -zero), complex(inf, nan)},
+ {complex(2, -zero), complex(zero, 1), complex(zero, -2)},
+ {complex(2, -zero), complex(zero, -1), complex(zero, 2)},
+ {complex(2, -zero), complex(zero, 2), complex(zero, -1)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(zero, zero), complex(inf, nan)},
+ {complex(2, -zero), complex(-zero, -zero), complex(-inf, nan)},
+ {complex(2, -zero), complex(zero, 1), complex(zero, -2)},
+ {complex(2, -zero), complex(-zero, -1), complex(-zero, 2)},
+ {complex(2, -zero), complex(zero, 2), complex(zero, -1)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(1, zero), complex(2, -zero)},
+ {complex(2, -zero), complex(1, -zero), complex(2, zero)},
+ {complex(2, -zero), complex(1, 1), complex(1, -1)},
+ {complex(2, -zero), complex(1, -1), complex(1, 1)},
+ {complex(2, -zero), complex(1, 2), complex(0.4, -0.8)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(-1, zero), complex(-2, -zero)},
+ {complex(2, -zero), complex(-1, -zero), complex(-2, zero)},
+ {complex(2, -zero), complex(-1, 1), complex(-1, -1)},
+ {complex(2, -zero), complex(-1, -1), complex(-1, 1)},
+ {complex(2, -zero), complex(-1, 2), complex(-0.4, -0.8)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(2, zero), complex(1, -zero)},
+ {complex(2, -zero), complex(2, -zero), complex(1, zero)},
+ {complex(2, -zero), complex(2, 1), complex(0.8, -0.4)},
+ {complex(2, -zero), complex(2, -1), complex(0.8, 0.4)},
+ {complex(2, -zero), complex(2, 2), complex(0.5, -0.5)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(inf, zero), complex(zero, -zero)},
+ {complex(2, -zero), complex(inf, -zero), complex(zero, zero)},
+ {complex(2, -zero), complex(inf, 1), complex(zero, -zero)},
+ {complex(2, -zero), complex(inf, -1), complex(zero, zero)},
+ {complex(2, -zero), complex(inf, 2), complex(zero, -zero)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -zero), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(2, -zero), complex(-inf, -zero), complex(-zero, zero)},
+ {complex(2, -zero), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(2, -zero), complex(-inf, -1), complex(-zero, zero)},
+ {complex(2, -zero), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -zero), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -zero), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, 1), complex(zero, zero), complex(inf, inf)},
+ {complex(2, 1), complex(zero, -zero), complex(inf, inf)},
+ {complex(2, 1), complex(zero, 1), complex(1, -2)},
+ {complex(2, 1), complex(zero, -1), complex(-1, 2)},
+ {complex(2, 1), complex(zero, 2), complex(0.5, -1)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(zero, zero), complex(inf, inf)},
+ {complex(2, 1), complex(-zero, -zero), complex(-inf, -inf)},
+ {complex(2, 1), complex(zero, 1), complex(1, -2)},
+ {complex(2, 1), complex(-zero, -1), complex(-1, 2)},
+ {complex(2, 1), complex(zero, 2), complex(0.5, -1)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(1, zero), complex(2, 1)},
+ {complex(2, 1), complex(1, -zero), complex(2, 1)},
+ {complex(2, 1), complex(1, 1), complex(1.5, -0.5)},
+ {complex(2, 1), complex(1, -1), complex(0.5, 1.5)},
+ {complex(2, 1), complex(1, 2), complex(0.8, -0.6)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(-1, zero), complex(-2, -1)},
+ {complex(2, 1), complex(-1, -zero), complex(-2, -1)},
+ {complex(2, 1), complex(-1, 1), complex(-0.5, -1.5)},
+ {complex(2, 1), complex(-1, -1), complex(-1.5, 0.5)},
+ {complex(2, 1), complex(-1, 2), complex(zero, -1)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(2, zero), complex(1, 0.5)},
+ {complex(2, 1), complex(2, -zero), complex(1, 0.5)},
+ {complex(2, 1), complex(2, 1), complex(1, zero)},
+ {complex(2, 1), complex(2, -1), complex(0.6, 0.8)},
+ {complex(2, 1), complex(2, 2), complex(0.75, -0.25)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(2, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(2, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(2, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(2, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(inf, zero), complex(zero, zero)},
+ {complex(2, 1), complex(inf, -zero), complex(zero, zero)},
+ {complex(2, 1), complex(inf, 1), complex(zero, zero)},
+ {complex(2, 1), complex(inf, -1), complex(zero, zero)},
+ {complex(2, 1), complex(inf, 2), complex(zero, zero)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 1), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(2, 1), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(2, 1), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(2, 1), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(2, 1), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(2, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 1), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 1), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, -1), complex(zero, zero), complex(inf, -inf)},
+ {complex(2, -1), complex(zero, -zero), complex(inf, -inf)},
+ {complex(2, -1), complex(zero, 1), complex(-1, -2)},
+ {complex(2, -1), complex(zero, -1), complex(1, 2)},
+ {complex(2, -1), complex(zero, 2), complex(-0.5, -1)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(zero, zero), complex(inf, -inf)},
+ {complex(2, -1), complex(-zero, -zero), complex(-inf, inf)},
+ {complex(2, -1), complex(zero, 1), complex(-1, -2)},
+ {complex(2, -1), complex(-zero, -1), complex(1, 2)},
+ {complex(2, -1), complex(zero, 2), complex(-0.5, -1)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(1, zero), complex(2, -1)},
+ {complex(2, -1), complex(1, -zero), complex(2, -1)},
+ {complex(2, -1), complex(1, 1), complex(0.5, -1.5)},
+ {complex(2, -1), complex(1, -1), complex(1.5, 0.5)},
+ {complex(2, -1), complex(1, 2), complex(zero, -1)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(-1, zero), complex(-2, 1)},
+ {complex(2, -1), complex(-1, -zero), complex(-2, 1)},
+ {complex(2, -1), complex(-1, 1), complex(-1.5, -0.5)},
+ {complex(2, -1), complex(-1, -1), complex(-0.5, 1.5)},
+ {complex(2, -1), complex(-1, 2), complex(-0.8, -0.6)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(2, zero), complex(1, -0.5)},
+ {complex(2, -1), complex(2, -zero), complex(1, -0.5)},
+ {complex(2, -1), complex(2, 1), complex(0.6, -0.8)},
+ {complex(2, -1), complex(2, -1), complex(1, zero)},
+ {complex(2, -1), complex(2, 2), complex(0.25, -0.75)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(2, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(2, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(2, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(2, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(inf, zero), complex(zero, -zero)},
+ {complex(2, -1), complex(inf, -zero), complex(zero, -zero)},
+ {complex(2, -1), complex(inf, 1), complex(zero, -zero)},
+ {complex(2, -1), complex(inf, -1), complex(zero, -zero)},
+ {complex(2, -1), complex(inf, 2), complex(zero, -zero)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, -1), complex(-inf, zero), complex(-zero, zero)},
+ {complex(2, -1), complex(-inf, -zero), complex(-zero, zero)},
+ {complex(2, -1), complex(-inf, 1), complex(-zero, zero)},
+ {complex(2, -1), complex(-inf, -1), complex(-zero, zero)},
+ {complex(2, -1), complex(-inf, 2), complex(-zero, zero)},
+ {complex(2, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(2, -1), complex(nan, inf), complex(-zero, -zero)},
+ {complex(2, -1), complex(nan, -inf), complex(zero, zero)},
+ {complex(2, 2), complex(zero, zero), complex(inf, inf)},
+ {complex(2, 2), complex(zero, -zero), complex(inf, inf)},
+ {complex(2, 2), complex(zero, 1), complex(2, -2)},
+ {complex(2, 2), complex(zero, -1), complex(-2, 2)},
+ {complex(2, 2), complex(zero, 2), complex(1, -1)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(zero, zero), complex(inf, inf)},
+ {complex(2, 2), complex(-zero, -zero), complex(-inf, -inf)},
+ {complex(2, 2), complex(zero, 1), complex(2, -2)},
+ {complex(2, 2), complex(-zero, -1), complex(-2, 2)},
+ {complex(2, 2), complex(zero, 2), complex(1, -1)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(1, zero), complex(2, 2)},
+ {complex(2, 2), complex(1, -zero), complex(2, 2)},
+ {complex(2, 2), complex(1, 1), complex(2, zero)},
+ {complex(2, 2), complex(1, -1), complex(zero, 2)},
+ {complex(2, 2), complex(1, 2), complex(1.2, -0.4)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(-1, zero), complex(-2, -2)},
+ {complex(2, 2), complex(-1, -zero), complex(-2, -2)},
+ {complex(2, 2), complex(-1, 1), complex(-zero, -2)},
+ {complex(2, 2), complex(-1, -1), complex(-2, -zero)},
+ {complex(2, 2), complex(-1, 2), complex(0.4, -1.2)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(2, zero), complex(1, 1)},
+ {complex(2, 2), complex(2, -zero), complex(1, 1)},
+ {complex(2, 2), complex(2, 1), complex(1.2, 0.4)},
+ {complex(2, 2), complex(2, -1), complex(0.4, 1.2)},
+ {complex(2, 2), complex(2, 2), complex(1, zero)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(2, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(2, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(2, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(2, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(inf, zero), complex(zero, zero)},
+ {complex(2, 2), complex(inf, -zero), complex(zero, zero)},
+ {complex(2, 2), complex(inf, 1), complex(zero, zero)},
+ {complex(2, 2), complex(inf, -1), complex(zero, zero)},
+ {complex(2, 2), complex(inf, 2), complex(zero, zero)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(2, 2), complex(-inf, zero), complex(-zero, -zero)},
+ {complex(2, 2), complex(-inf, -zero), complex(-zero, -zero)},
+ {complex(2, 2), complex(-inf, 1), complex(-zero, -zero)},
+ {complex(2, 2), complex(-inf, -1), complex(-zero, -zero)},
+ {complex(2, 2), complex(-inf, 2), complex(-zero, -zero)},
+ {complex(2, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(2, 2), complex(nan, inf), complex(zero, -zero)},
+ {complex(2, 2), complex(nan, -inf), complex(-zero, zero)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(1, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(1, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(1, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(1, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(2, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(2, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(2, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(2, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, zero), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, zero), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, zero), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, zero), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, zero), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(1, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(1, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(1, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(1, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(2, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(2, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(2, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(2, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -zero), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -zero), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -zero), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, 1), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, 1), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, 1), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, 1), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(1, zero), complex(nan, nan)},
+ {complex(nan, 1), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, 1), complex(1, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(1, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(1, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, 1), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, 1), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(2, zero), complex(nan, nan)},
+ {complex(nan, 1), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, 1), complex(2, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(2, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(2, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, 1), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, 1), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 1), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, 1), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, 1), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, 1), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, 1), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -1), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -1), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -1), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -1), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(1, zero), complex(nan, nan)},
+ {complex(nan, -1), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, -1), complex(1, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(1, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(1, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, -1), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, -1), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(2, zero), complex(nan, nan)},
+ {complex(nan, -1), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, -1), complex(2, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(2, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(2, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -1), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -1), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -1), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -1), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -1), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -1), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -1), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, 2), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, 2), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, 2), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, 2), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(1, zero), complex(nan, nan)},
+ {complex(nan, 2), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, 2), complex(1, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(1, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(1, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, 2), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, 2), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(2, zero), complex(nan, nan)},
+ {complex(nan, 2), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, 2), complex(2, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(2, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(2, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, 2), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, 2), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, 2), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, 2), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, 2), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, 2), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, 2), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(zero, zero), complex(inf, nan)},
+ {complex(inf, zero), complex(zero, -zero), complex(inf, nan)},
+ {complex(inf, zero), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, zero), complex(zero, -1), complex(nan, inf)},
+ {complex(inf, zero), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(zero, zero), complex(inf, nan)},
+ {complex(inf, zero), complex(-zero, -zero), complex(-inf, nan)},
+ {complex(inf, zero), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, zero), complex(-zero, -1), complex(nan, inf)},
+ {complex(inf, zero), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(1, zero), complex(inf, nan)},
+ {complex(inf, zero), complex(1, -zero), complex(inf, nan)},
+ {complex(inf, zero), complex(1, 1), complex(inf, -inf)},
+ {complex(inf, zero), complex(1, -1), complex(inf, inf)},
+ {complex(inf, zero), complex(1, 2), complex(inf, -inf)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(-1, zero), complex(-inf, nan)},
+ {complex(inf, zero), complex(-1, -zero), complex(-inf, nan)},
+ {complex(inf, zero), complex(-1, 1), complex(-inf, -inf)},
+ {complex(inf, zero), complex(-1, -1), complex(-inf, inf)},
+ {complex(inf, zero), complex(-1, 2), complex(-inf, -inf)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(2, zero), complex(inf, nan)},
+ {complex(inf, zero), complex(2, -zero), complex(inf, nan)},
+ {complex(inf, zero), complex(2, 1), complex(inf, -inf)},
+ {complex(inf, zero), complex(2, -1), complex(inf, inf)},
+ {complex(inf, zero), complex(2, 2), complex(inf, -inf)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(inf, zero), complex(nan, nan)},
+ {complex(inf, zero), complex(inf, -zero), complex(nan, nan)},
+ {complex(inf, zero), complex(inf, 1), complex(nan, nan)},
+ {complex(inf, zero), complex(inf, -1), complex(nan, nan)},
+ {complex(inf, zero), complex(inf, 2), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, zero), complex(-inf, zero), complex(nan, nan)},
+ {complex(inf, zero), complex(-inf, -zero), complex(nan, nan)},
+ {complex(inf, zero), complex(-inf, 1), complex(nan, nan)},
+ {complex(inf, zero), complex(-inf, -1), complex(nan, nan)},
+ {complex(inf, zero), complex(-inf, 2), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(zero, zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(zero, -zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, -zero), complex(zero, -1), complex(nan, inf)},
+ {complex(inf, -zero), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(zero, zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(-zero, -zero), complex(-inf, nan)},
+ {complex(inf, -zero), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, -zero), complex(-zero, -1), complex(nan, inf)},
+ {complex(inf, -zero), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(1, zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(1, -zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(1, 1), complex(inf, -inf)},
+ {complex(inf, -zero), complex(1, -1), complex(inf, inf)},
+ {complex(inf, -zero), complex(1, 2), complex(inf, -inf)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(-1, zero), complex(-inf, nan)},
+ {complex(inf, -zero), complex(-1, -zero), complex(-inf, nan)},
+ {complex(inf, -zero), complex(-1, 1), complex(-inf, -inf)},
+ {complex(inf, -zero), complex(-1, -1), complex(-inf, inf)},
+ {complex(inf, -zero), complex(-1, 2), complex(-inf, -inf)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(2, zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(2, -zero), complex(inf, nan)},
+ {complex(inf, -zero), complex(2, 1), complex(inf, -inf)},
+ {complex(inf, -zero), complex(2, -1), complex(inf, inf)},
+ {complex(inf, -zero), complex(2, 2), complex(inf, -inf)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(inf, zero), complex(nan, nan)},
+ {complex(inf, -zero), complex(inf, -zero), complex(nan, nan)},
+ {complex(inf, -zero), complex(inf, 1), complex(nan, nan)},
+ {complex(inf, -zero), complex(inf, -1), complex(nan, nan)},
+ {complex(inf, -zero), complex(inf, 2), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(-inf, zero), complex(nan, nan)},
+ {complex(inf, -zero), complex(-inf, -zero), complex(nan, nan)},
+ {complex(inf, -zero), complex(-inf, 1), complex(nan, nan)},
+ {complex(inf, -zero), complex(-inf, -1), complex(nan, nan)},
+ {complex(inf, -zero), complex(-inf, 2), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(zero, zero), complex(inf, inf)},
+ {complex(inf, 1), complex(zero, -zero), complex(inf, inf)},
+ {complex(inf, 1), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, 1), complex(zero, -1), complex(nan, inf)},
+ {complex(inf, 1), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(zero, zero), complex(inf, inf)},
+ {complex(inf, 1), complex(-zero, -zero), complex(-inf, -inf)},
+ {complex(inf, 1), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, 1), complex(-zero, -1), complex(nan, inf)},
+ {complex(inf, 1), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(1, zero), complex(inf, nan)},
+ {complex(inf, 1), complex(1, -zero), complex(inf, nan)},
+ {complex(inf, 1), complex(1, 1), complex(inf, -inf)},
+ {complex(inf, 1), complex(1, -1), complex(inf, inf)},
+ {complex(inf, 1), complex(1, 2), complex(inf, -inf)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(-1, zero), complex(-inf, nan)},
+ {complex(inf, 1), complex(-1, -zero), complex(-inf, nan)},
+ {complex(inf, 1), complex(-1, 1), complex(-inf, -inf)},
+ {complex(inf, 1), complex(-1, -1), complex(-inf, inf)},
+ {complex(inf, 1), complex(-1, 2), complex(-inf, -inf)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(2, zero), complex(inf, nan)},
+ {complex(inf, 1), complex(2, -zero), complex(inf, nan)},
+ {complex(inf, 1), complex(2, 1), complex(inf, -inf)},
+ {complex(inf, 1), complex(2, -1), complex(inf, inf)},
+ {complex(inf, 1), complex(2, 2), complex(inf, -inf)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(inf, zero), complex(nan, nan)},
+ {complex(inf, 1), complex(inf, -zero), complex(nan, nan)},
+ {complex(inf, 1), complex(inf, 1), complex(nan, nan)},
+ {complex(inf, 1), complex(inf, -1), complex(nan, nan)},
+ {complex(inf, 1), complex(inf, 2), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 1), complex(-inf, zero), complex(nan, nan)},
+ {complex(inf, 1), complex(-inf, -zero), complex(nan, nan)},
+ {complex(inf, 1), complex(-inf, 1), complex(nan, nan)},
+ {complex(inf, 1), complex(-inf, -1), complex(nan, nan)},
+ {complex(inf, 1), complex(-inf, 2), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(zero, zero), complex(inf, -inf)},
+ {complex(inf, -1), complex(zero, -zero), complex(inf, -inf)},
+ {complex(inf, -1), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, -1), complex(zero, -1), complex(nan, inf)},
+ {complex(inf, -1), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(zero, zero), complex(inf, -inf)},
+ {complex(inf, -1), complex(-zero, -zero), complex(-inf, inf)},
+ {complex(inf, -1), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, -1), complex(-zero, -1), complex(nan, inf)},
+ {complex(inf, -1), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(1, zero), complex(inf, nan)},
+ {complex(inf, -1), complex(1, -zero), complex(inf, nan)},
+ {complex(inf, -1), complex(1, 1), complex(inf, -inf)},
+ {complex(inf, -1), complex(1, -1), complex(inf, inf)},
+ {complex(inf, -1), complex(1, 2), complex(inf, -inf)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(-1, zero), complex(-inf, nan)},
+ {complex(inf, -1), complex(-1, -zero), complex(-inf, nan)},
+ {complex(inf, -1), complex(-1, 1), complex(-inf, -inf)},
+ {complex(inf, -1), complex(-1, -1), complex(-inf, inf)},
+ {complex(inf, -1), complex(-1, 2), complex(-inf, -inf)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(2, zero), complex(inf, nan)},
+ {complex(inf, -1), complex(2, -zero), complex(inf, nan)},
+ {complex(inf, -1), complex(2, 1), complex(inf, -inf)},
+ {complex(inf, -1), complex(2, -1), complex(inf, inf)},
+ {complex(inf, -1), complex(2, 2), complex(inf, -inf)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(inf, zero), complex(nan, nan)},
+ {complex(inf, -1), complex(inf, -zero), complex(nan, nan)},
+ {complex(inf, -1), complex(inf, 1), complex(nan, nan)},
+ {complex(inf, -1), complex(inf, -1), complex(nan, nan)},
+ {complex(inf, -1), complex(inf, 2), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, -1), complex(-inf, zero), complex(nan, nan)},
+ {complex(inf, -1), complex(-inf, -zero), complex(nan, nan)},
+ {complex(inf, -1), complex(-inf, 1), complex(nan, nan)},
+ {complex(inf, -1), complex(-inf, -1), complex(nan, nan)},
+ {complex(inf, -1), complex(-inf, 2), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(zero, zero), complex(inf, inf)},
+ {complex(inf, 2), complex(zero, -zero), complex(inf, inf)},
+ {complex(inf, 2), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, 2), complex(zero, -1), complex(nan, inf)},
+ {complex(inf, 2), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(zero, zero), complex(inf, inf)},
+ {complex(inf, 2), complex(-zero, -zero), complex(-inf, -inf)},
+ {complex(inf, 2), complex(zero, 1), complex(nan, -inf)},
+ {complex(inf, 2), complex(-zero, -1), complex(nan, inf)},
+ {complex(inf, 2), complex(zero, 2), complex(nan, -inf)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(1, zero), complex(inf, nan)},
+ {complex(inf, 2), complex(1, -zero), complex(inf, nan)},
+ {complex(inf, 2), complex(1, 1), complex(inf, -inf)},
+ {complex(inf, 2), complex(1, -1), complex(inf, inf)},
+ {complex(inf, 2), complex(1, 2), complex(inf, -inf)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(-1, zero), complex(-inf, nan)},
+ {complex(inf, 2), complex(-1, -zero), complex(-inf, nan)},
+ {complex(inf, 2), complex(-1, 1), complex(-inf, -inf)},
+ {complex(inf, 2), complex(-1, -1), complex(-inf, inf)},
+ {complex(inf, 2), complex(-1, 2), complex(-inf, -inf)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(2, zero), complex(inf, nan)},
+ {complex(inf, 2), complex(2, -zero), complex(inf, nan)},
+ {complex(inf, 2), complex(2, 1), complex(inf, -inf)},
+ {complex(inf, 2), complex(2, -1), complex(inf, inf)},
+ {complex(inf, 2), complex(2, 2), complex(inf, -inf)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(inf, zero), complex(nan, nan)},
+ {complex(inf, 2), complex(inf, -zero), complex(nan, nan)},
+ {complex(inf, 2), complex(inf, 1), complex(nan, nan)},
+ {complex(inf, 2), complex(inf, -1), complex(nan, nan)},
+ {complex(inf, 2), complex(inf, 2), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(inf, 2), complex(-inf, zero), complex(nan, nan)},
+ {complex(inf, 2), complex(-inf, -zero), complex(nan, nan)},
+ {complex(inf, 2), complex(-inf, 1), complex(nan, nan)},
+ {complex(inf, 2), complex(-inf, -1), complex(nan, nan)},
+ {complex(inf, 2), complex(-inf, 2), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(zero, -zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, zero), complex(zero, -1), complex(nan, -inf)},
+ {complex(-inf, zero), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(-zero, -zero), complex(inf, nan)},
+ {complex(-inf, zero), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, zero), complex(-zero, -1), complex(nan, -inf)},
+ {complex(-inf, zero), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(1, zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(1, -zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(1, 1), complex(-inf, inf)},
+ {complex(-inf, zero), complex(1, -1), complex(-inf, -inf)},
+ {complex(-inf, zero), complex(1, 2), complex(-inf, inf)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(-1, zero), complex(inf, nan)},
+ {complex(-inf, zero), complex(-1, -zero), complex(inf, nan)},
+ {complex(-inf, zero), complex(-1, 1), complex(inf, inf)},
+ {complex(-inf, zero), complex(-1, -1), complex(inf, -inf)},
+ {complex(-inf, zero), complex(-1, 2), complex(inf, inf)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(2, zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(2, -zero), complex(-inf, nan)},
+ {complex(-inf, zero), complex(2, 1), complex(-inf, inf)},
+ {complex(-inf, zero), complex(2, -1), complex(-inf, -inf)},
+ {complex(-inf, zero), complex(2, 2), complex(-inf, inf)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, zero), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, 1), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -1), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, 2), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(inf, zero), complex(nan, nan)},
+ {complex(-inf, zero), complex(inf, -zero), complex(nan, nan)},
+ {complex(-inf, zero), complex(inf, 1), complex(nan, nan)},
+ {complex(-inf, zero), complex(inf, -1), complex(nan, nan)},
+ {complex(-inf, zero), complex(inf, 2), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(-inf, zero), complex(nan, nan)},
+ {complex(-inf, zero), complex(-inf, -zero), complex(nan, nan)},
+ {complex(-inf, zero), complex(-inf, 1), complex(nan, nan)},
+ {complex(-inf, zero), complex(-inf, -1), complex(nan, nan)},
+ {complex(-inf, zero), complex(-inf, 2), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(zero, -zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, -zero), complex(zero, -1), complex(nan, -inf)},
+ {complex(-inf, -zero), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(zero, zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(-zero, -zero), complex(inf, nan)},
+ {complex(-inf, -zero), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, -zero), complex(-zero, -1), complex(nan, -inf)},
+ {complex(-inf, -zero), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(1, zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(1, -zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(1, 1), complex(-inf, inf)},
+ {complex(-inf, -zero), complex(1, -1), complex(-inf, -inf)},
+ {complex(-inf, -zero), complex(1, 2), complex(-inf, inf)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(-1, zero), complex(inf, nan)},
+ {complex(-inf, -zero), complex(-1, -zero), complex(inf, nan)},
+ {complex(-inf, -zero), complex(-1, 1), complex(inf, inf)},
+ {complex(-inf, -zero), complex(-1, -1), complex(inf, -inf)},
+ {complex(-inf, -zero), complex(-1, 2), complex(inf, inf)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(2, zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(2, -zero), complex(-inf, nan)},
+ {complex(-inf, -zero), complex(2, 1), complex(-inf, inf)},
+ {complex(-inf, -zero), complex(2, -1), complex(-inf, -inf)},
+ {complex(-inf, -zero), complex(2, 2), complex(-inf, inf)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, zero), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -zero), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, 1), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -1), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, 2), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(inf, zero), complex(nan, nan)},
+ {complex(-inf, -zero), complex(inf, -zero), complex(nan, nan)},
+ {complex(-inf, -zero), complex(inf, 1), complex(nan, nan)},
+ {complex(-inf, -zero), complex(inf, -1), complex(nan, nan)},
+ {complex(-inf, -zero), complex(inf, 2), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(-inf, zero), complex(nan, nan)},
+ {complex(-inf, -zero), complex(-inf, -zero), complex(nan, nan)},
+ {complex(-inf, -zero), complex(-inf, 1), complex(nan, nan)},
+ {complex(-inf, -zero), complex(-inf, -1), complex(nan, nan)},
+ {complex(-inf, -zero), complex(-inf, 2), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -zero), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(zero, zero), complex(-inf, inf)},
+ {complex(-inf, 1), complex(zero, -zero), complex(-inf, inf)},
+ {complex(-inf, 1), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, 1), complex(zero, -1), complex(nan, -inf)},
+ {complex(-inf, 1), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(zero, zero), complex(-inf, inf)},
+ {complex(-inf, 1), complex(-zero, -zero), complex(inf, -inf)},
+ {complex(-inf, 1), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, 1), complex(-zero, -1), complex(nan, -inf)},
+ {complex(-inf, 1), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(1, zero), complex(-inf, nan)},
+ {complex(-inf, 1), complex(1, -zero), complex(-inf, nan)},
+ {complex(-inf, 1), complex(1, 1), complex(-inf, inf)},
+ {complex(-inf, 1), complex(1, -1), complex(-inf, -inf)},
+ {complex(-inf, 1), complex(1, 2), complex(-inf, inf)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(-1, zero), complex(inf, nan)},
+ {complex(-inf, 1), complex(-1, -zero), complex(inf, nan)},
+ {complex(-inf, 1), complex(-1, 1), complex(inf, inf)},
+ {complex(-inf, 1), complex(-1, -1), complex(inf, -inf)},
+ {complex(-inf, 1), complex(-1, 2), complex(inf, inf)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(2, zero), complex(-inf, nan)},
+ {complex(-inf, 1), complex(2, -zero), complex(-inf, nan)},
+ {complex(-inf, 1), complex(2, 1), complex(-inf, inf)},
+ {complex(-inf, 1), complex(2, -1), complex(-inf, -inf)},
+ {complex(-inf, 1), complex(2, 2), complex(-inf, inf)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, zero), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -zero), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, 1), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -1), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, 2), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(inf, zero), complex(nan, nan)},
+ {complex(-inf, 1), complex(inf, -zero), complex(nan, nan)},
+ {complex(-inf, 1), complex(inf, 1), complex(nan, nan)},
+ {complex(-inf, 1), complex(inf, -1), complex(nan, nan)},
+ {complex(-inf, 1), complex(inf, 2), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(-inf, zero), complex(nan, nan)},
+ {complex(-inf, 1), complex(-inf, -zero), complex(nan, nan)},
+ {complex(-inf, 1), complex(-inf, 1), complex(nan, nan)},
+ {complex(-inf, 1), complex(-inf, -1), complex(nan, nan)},
+ {complex(-inf, 1), complex(-inf, 2), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(zero, zero), complex(-inf, -inf)},
+ {complex(-inf, -1), complex(zero, -zero), complex(-inf, -inf)},
+ {complex(-inf, -1), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, -1), complex(zero, -1), complex(nan, -inf)},
+ {complex(-inf, -1), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(zero, zero), complex(-inf, -inf)},
+ {complex(-inf, -1), complex(-zero, -zero), complex(inf, inf)},
+ {complex(-inf, -1), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, -1), complex(-zero, -1), complex(nan, -inf)},
+ {complex(-inf, -1), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(1, zero), complex(-inf, nan)},
+ {complex(-inf, -1), complex(1, -zero), complex(-inf, nan)},
+ {complex(-inf, -1), complex(1, 1), complex(-inf, inf)},
+ {complex(-inf, -1), complex(1, -1), complex(-inf, -inf)},
+ {complex(-inf, -1), complex(1, 2), complex(-inf, inf)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(-1, zero), complex(inf, nan)},
+ {complex(-inf, -1), complex(-1, -zero), complex(inf, nan)},
+ {complex(-inf, -1), complex(-1, 1), complex(inf, inf)},
+ {complex(-inf, -1), complex(-1, -1), complex(inf, -inf)},
+ {complex(-inf, -1), complex(-1, 2), complex(inf, inf)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(2, zero), complex(-inf, nan)},
+ {complex(-inf, -1), complex(2, -zero), complex(-inf, nan)},
+ {complex(-inf, -1), complex(2, 1), complex(-inf, inf)},
+ {complex(-inf, -1), complex(2, -1), complex(-inf, -inf)},
+ {complex(-inf, -1), complex(2, 2), complex(-inf, inf)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, zero), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -zero), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, 1), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -1), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, 2), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(inf, zero), complex(nan, nan)},
+ {complex(-inf, -1), complex(inf, -zero), complex(nan, nan)},
+ {complex(-inf, -1), complex(inf, 1), complex(nan, nan)},
+ {complex(-inf, -1), complex(inf, -1), complex(nan, nan)},
+ {complex(-inf, -1), complex(inf, 2), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(-inf, zero), complex(nan, nan)},
+ {complex(-inf, -1), complex(-inf, -zero), complex(nan, nan)},
+ {complex(-inf, -1), complex(-inf, 1), complex(nan, nan)},
+ {complex(-inf, -1), complex(-inf, -1), complex(nan, nan)},
+ {complex(-inf, -1), complex(-inf, 2), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, -1), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(zero, zero), complex(-inf, inf)},
+ {complex(-inf, 2), complex(zero, -zero), complex(-inf, inf)},
+ {complex(-inf, 2), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, 2), complex(zero, -1), complex(nan, -inf)},
+ {complex(-inf, 2), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(zero, zero), complex(-inf, inf)},
+ {complex(-inf, 2), complex(-zero, -zero), complex(inf, -inf)},
+ {complex(-inf, 2), complex(zero, 1), complex(nan, inf)},
+ {complex(-inf, 2), complex(-zero, -1), complex(nan, -inf)},
+ {complex(-inf, 2), complex(zero, 2), complex(nan, inf)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(1, zero), complex(-inf, nan)},
+ {complex(-inf, 2), complex(1, -zero), complex(-inf, nan)},
+ {complex(-inf, 2), complex(1, 1), complex(-inf, inf)},
+ {complex(-inf, 2), complex(1, -1), complex(-inf, -inf)},
+ {complex(-inf, 2), complex(1, 2), complex(-inf, inf)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(-1, zero), complex(inf, nan)},
+ {complex(-inf, 2), complex(-1, -zero), complex(inf, nan)},
+ {complex(-inf, 2), complex(-1, 1), complex(inf, inf)},
+ {complex(-inf, 2), complex(-1, -1), complex(inf, -inf)},
+ {complex(-inf, 2), complex(-1, 2), complex(inf, inf)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(2, zero), complex(-inf, nan)},
+ {complex(-inf, 2), complex(2, -zero), complex(-inf, nan)},
+ {complex(-inf, 2), complex(2, 1), complex(-inf, inf)},
+ {complex(-inf, 2), complex(2, -1), complex(-inf, -inf)},
+ {complex(-inf, 2), complex(2, 2), complex(-inf, inf)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, zero), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -zero), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, 1), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -1), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, 2), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(inf, zero), complex(nan, nan)},
+ {complex(-inf, 2), complex(inf, -zero), complex(nan, nan)},
+ {complex(-inf, 2), complex(inf, 1), complex(nan, nan)},
+ {complex(-inf, 2), complex(inf, -1), complex(nan, nan)},
+ {complex(-inf, 2), complex(inf, 2), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(-inf, zero), complex(nan, nan)},
+ {complex(-inf, 2), complex(-inf, -zero), complex(nan, nan)},
+ {complex(-inf, 2), complex(-inf, 1), complex(nan, nan)},
+ {complex(-inf, 2), complex(-inf, -1), complex(nan, nan)},
+ {complex(-inf, 2), complex(-inf, 2), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, inf), complex(nan, nan)},
+ {complex(-inf, 2), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-zero, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(zero, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(2, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(2, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, nan), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(zero, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(-zero, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(zero, 1), complex(inf, nan)},
+ {complex(nan, inf), complex(-zero, -1), complex(-inf, nan)},
+ {complex(nan, inf), complex(zero, 2), complex(inf, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(1, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(1, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(1, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(1, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-1, zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, -zero), complex(nan, -inf)},
+ {complex(nan, inf), complex(-1, 1), complex(inf, -inf)},
+ {complex(nan, inf), complex(-1, -1), complex(-inf, -inf)},
+ {complex(nan, inf), complex(-1, 2), complex(inf, -inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(2, zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, -zero), complex(nan, inf)},
+ {complex(nan, inf), complex(2, 1), complex(inf, inf)},
+ {complex(nan, inf), complex(2, -1), complex(-inf, inf)},
+ {complex(nan, inf), complex(2, 2), complex(inf, inf)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(zero, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(-zero, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(zero, 1), complex(-inf, nan)},
+ {complex(nan, -inf), complex(-zero, -1), complex(inf, nan)},
+ {complex(nan, -inf), complex(zero, 2), complex(-inf, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(1, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(1, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(1, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(1, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-1, zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, -zero), complex(nan, inf)},
+ {complex(nan, -inf), complex(-1, 1), complex(-inf, inf)},
+ {complex(nan, -inf), complex(-1, -1), complex(inf, inf)},
+ {complex(nan, -inf), complex(-1, 2), complex(-inf, inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(2, zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, -zero), complex(nan, -inf)},
+ {complex(nan, -inf), complex(2, 1), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(2, -1), complex(inf, -inf)},
+ {complex(nan, -inf), complex(2, 2), complex(-inf, -inf)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -zero), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, -1), complex(nan, nan)},
+ {complex(nan, -inf), complex(-inf, 2), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, nan), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, inf), complex(nan, nan)},
+ {complex(nan, -inf), complex(nan, -inf), complex(nan, nan)},
}
diff --git a/gcc/testsuite/go.test/test/complit1.go b/gcc/testsuite/go.test/test/complit1.go
index 521401d..7c2a4e2 100644
--- a/gcc/testsuite/go.test/test/complit1.go
+++ b/gcc/testsuite/go.test/test/complit1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -22,6 +22,10 @@ var (
_ = m[0][:] // ERROR "slice of unaddressable value"
_ = f()[:] // ERROR "slice of unaddressable value"
+ _ = 301[:] // ERROR "cannot slice|attempt to slice object that is not"
+ _ = 3.1[:] // ERROR "cannot slice|attempt to slice object that is not"
+ _ = true[:] // ERROR "cannot slice|attempt to slice object that is not"
+
// these are okay because they are slicing a pointer to an array
_ = (&[3]int{1, 2, 3})[:]
_ = mp[0][:]
@@ -35,8 +39,27 @@ type T struct {
next *T
}
+type TP *T
+type Ti int
+
var (
_ = &T{0, 0, "", nil} // ok
_ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal|omit types within composite literal"
_ = &T{0, 0, "", {}} // ERROR "missing type in composite literal|omit types within composite literal"
+ _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP|omit types within composite literal"
+ _ = &Ti{} // ERROR "invalid composite literal type Ti|expected.*type for composite literal"
+)
+
+type M map[T]T
+
+var (
+ _ = M{{i:1}: {i:2}}
+ _ = M{T{i:1}: {i:2}}
+ _ = M{{i:1}: T{i:2}}
+ _ = M{T{i:1}: T{i:2}}
)
+
+type S struct { s [1]*M1 }
+type M1 map[S]int
+var _ = M1{{s:[1]*M1{&M1{{}:1}}}:2}
+
diff --git a/gcc/testsuite/go.test/test/compos.go b/gcc/testsuite/go.test/test/compos.go
index de688b3..e6375f2 100644
--- a/gcc/testsuite/go.test/test/compos.go
+++ b/gcc/testsuite/go.test/test/compos.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/const.go b/gcc/testsuite/go.test/test/const.go
index d583659..f8aa1dd 100644
--- a/gcc/testsuite/go.test/test/const.go
+++ b/gcc/testsuite/go.test/test/const.go
@@ -19,8 +19,15 @@ const (
c3div2 = 3 / 2
c1e3 = 1e3
+ rsh1 = 1e100 >> 1000
+ rsh2 = 1e302 >> 1000
+
ctrue = true
cfalse = !ctrue
+
+ // Issue #34563
+ _ = string(int(123))
+ _ = string(rune(456))
)
const (
@@ -48,6 +55,8 @@ func ints() {
assert(c3div2 == 1, "3/2")
assert(c1e3 == 1000, "c1e3 int")
assert(c1e3 == 1e3, "c1e3 float")
+ assert(rsh1 == 0, "rsh1")
+ assert(rsh2 == 9, "rsh2")
// verify that all (in range) are assignable as ints
var i int
@@ -118,9 +127,83 @@ func floats() {
assert(f == f1e3, "f == f1e3")
}
+func interfaces() {
+ var (
+ nilN interface{}
+ nilI *int
+ five = 5
+
+ _ = nil == interface{}(nil)
+ _ = interface{}(nil) == nil
+ )
+ ii := func(i1 interface{}, i2 interface{}) bool { return i1 == i2 }
+ ni := func(n interface{}, i int) bool { return n == i }
+ in := func(i int, n interface{}) bool { return i == n }
+ pi := func(p *int, i interface{}) bool { return p == i }
+ ip := func(i interface{}, p *int) bool { return i == p }
+
+ assert((interface{}(nil) == interface{}(nil)) == ii(nilN, nilN),
+ "for interface{}==interface{} compiler == runtime")
+
+ assert(((*int)(nil) == interface{}(nil)) == pi(nilI, nilN),
+ "for *int==interface{} compiler == runtime")
+ assert((interface{}(nil) == (*int)(nil)) == ip(nilN, nilI),
+ "for interface{}==*int compiler == runtime")
+
+ assert((&five == interface{}(nil)) == pi(&five, nilN),
+ "for interface{}==*int compiler == runtime")
+ assert((interface{}(nil) == &five) == ip(nilN, &five),
+ "for interface{}==*int compiler == runtime")
+
+ assert((5 == interface{}(5)) == ni(five, five),
+ "for int==interface{} compiler == runtime")
+ assert((interface{}(5) == 5) == in(five, five),
+ "for interface{}==int comipiler == runtime")
+}
+
+// Test that typed floating-point and complex arithmetic
+// is computed with correct precision.
+func truncate() {
+ const (
+ x30 = 1 << 30
+ x60 = 1 << 60
+
+ staticF32 = float32(x30) + 1 - x30
+ staticF64 = float64(x60) + 1 - x60
+ staticC64 = complex64(x30) + 1 - x30
+ staticC128 = complex128(x60) + 1 - x60
+ )
+ dynamicF32 := float32(x30)
+ dynamicF32 += 1
+ dynamicF32 -= x30
+
+ dynamicF64 := float64(x60)
+ dynamicF64 += 1
+ dynamicF64 -= x60
+
+ dynamicC64 := complex64(x30)
+ dynamicC64 += 1
+ dynamicC64 -= x30
+
+ dynamicC128 := complex128(x60)
+ dynamicC128 += 1
+ dynamicC128 -= x60
+
+ assert(staticF32 == 0, "staticF32 == 0")
+ assert(staticF64 == 0, "staticF64 == 0")
+ assert(dynamicF32 == 0, "dynamicF32 == 0")
+ assert(dynamicF64 == 0, "dynamicF64 == 0")
+ assert(staticC64 == 0, "staticC64 == 0")
+ assert(staticC128 == 0, "staticC128 == 0")
+ assert(dynamicC64 == 0, "dynamicC64 == 0")
+ assert(dynamicC128 == 0, "dynamicC128 == 0")
+}
+
func main() {
ints()
floats()
+ interfaces()
+ truncate()
assert(ctrue == true, "ctrue == true")
assert(cfalse == false, "cfalse == false")
diff --git a/gcc/testsuite/go.test/test/const1.go b/gcc/testsuite/go.test/test/const1.go
index 58bddee..3fd5b55 100644
--- a/gcc/testsuite/go.test/test/const1.go
+++ b/gcc/testsuite/go.test/test/const1.go
@@ -68,7 +68,7 @@ var (
c3 float64 = float64(Big) * Big // ERROR "overflow"
c4 = Big * Big // ERROR "overflow"
c5 = Big / 0 // ERROR "division by zero"
- c6 = 1000 % 1e3 // ERROR "floating-point % operation|expected integer type"
+ c6 = 1000 % 1e3 // ERROR "invalid operation|expected integer type"
)
func f(int)
@@ -90,5 +90,5 @@ func main() {
const ptr = nil // ERROR "const.*nil"
const _ = string([]byte(nil)) // ERROR "is not a? ?constant"
const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a? ?constant"
-const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type"
-const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type"
+const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type|is not a constant"
+const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type|is not a constant"
diff --git a/gcc/testsuite/go.test/test/const4.go b/gcc/testsuite/go.test/test/const4.go
index 2fb2d06..785e1ec 100644
--- a/gcc/testsuite/go.test/test/const4.go
+++ b/gcc/testsuite/go.test/test/const4.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test len constants and non-constants, http://golang.org/issue/3244.
+// Test len constants and non-constants, https://golang.org/issue/3244.
package main
diff --git a/gcc/testsuite/go.test/test/const5.go b/gcc/testsuite/go.test/test/const5.go
index 87fe33a..51e46cb 100644
--- a/gcc/testsuite/go.test/test/const5.go
+++ b/gcc/testsuite/go.test/test/const5.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test that len non-constants are not constants, http://golang.org/issue/3244.
+// Test that len non-constants are not constants, https://golang.org/issue/3244.
package p
@@ -18,6 +18,7 @@ var s [][30]int
func f() *[40]int
var c chan *[50]int
+var z complex128
const (
n1 = len(b.a)
@@ -29,5 +30,8 @@ const (
n6 = cap(f()) // ERROR "is not a constant|is not constant"
n7 = cap(<-c) // ERROR "is not a constant|is not constant"
+ n8 = real(z) // ERROR "is not a constant|is not constant"
+ n9 = len([4]float64{real(z)}) // ERROR "is not a constant|is not constant"
+
)
diff --git a/gcc/testsuite/go.test/test/const6.go b/gcc/testsuite/go.test/test/const6.go
index c005ac3..b340e58 100644
--- a/gcc/testsuite/go.test/test/const6.go
+++ b/gcc/testsuite/go.test/test/const6.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/convert1.go b/gcc/testsuite/go.test/test/convert1.go
index 0f417a3..afb63cd 100644
--- a/gcc/testsuite/go.test/test/convert1.go
+++ b/gcc/testsuite/go.test/test/convert1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/convlit.go b/gcc/testsuite/go.test/test/convlit.go
index 8a6145d..1c66c89 100644
--- a/gcc/testsuite/go.test/test/convlit.go
+++ b/gcc/testsuite/go.test/test/convlit.go
@@ -9,6 +9,8 @@
package main
+import "unsafe"
+
// explicit conversion of constants
var x1 = string(1)
var x2 string = string(1)
@@ -18,11 +20,16 @@ var x5 = "a" + string(1)
var x6 = int(1e100) // ERROR "overflow"
var x7 = float32(1e1000) // ERROR "overflow"
+// unsafe.Pointer can only convert to/from uintptr
+var _ = string(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion"
+var _ = float64(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion"
+var _ = int(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion"
+
// implicit conversions merit scrutiny
var s string
var bad1 string = 1 // ERROR "conver|incompatible|invalid|cannot"
-var bad2 = s + 1 // ERROR "conver|incompatible|invalid"
-var bad3 = s + 'a' // ERROR "conver|incompatible|invalid"
+var bad2 = s + 1 // ERROR "conver|incompatible|invalid|cannot"
+var bad3 = s + 'a' // ERROR "conver|incompatible|invalid|cannot"
var bad4 = "a" + 1 // ERROR "literals|incompatible|convert|invalid"
var bad5 = "a" + 'a' // ERROR "literals|incompatible|convert|invalid"
diff --git a/gcc/testsuite/go.test/test/ddd.go b/gcc/testsuite/go.test/test/ddd.go
index 01768b8..84503f7 100644
--- a/gcc/testsuite/go.test/test/ddd.go
+++ b/gcc/testsuite/go.test/test/ddd.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/ddd1.go b/gcc/testsuite/go.test/test/ddd1.go
index 07981af..01b9c0e 100644
--- a/gcc/testsuite/go.test/test/ddd1.go
+++ b/gcc/testsuite/go.test/test/ddd1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -18,8 +18,8 @@ var (
_ = sum()
_ = sum(1.0, 2.0)
_ = sum(1.5) // ERROR "integer"
- _ = sum("hello") // ERROR ".hello. .type string. as type int|incompatible"
- _ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible"
+ _ = sum("hello") // ERROR ".hello. .type untyped string. as type int|incompatible"
+ _ = sum([]int{1}) // ERROR "\[\]int{...}.*as type int|incompatible"
)
func sum3(int, int, int) int { return 0 }
@@ -27,9 +27,9 @@ func tuple() (int, int, int) { return 1, 2, 3 }
var (
_ = sum(tuple())
- _ = sum(tuple()...) // ERROR "multiple-value|[.][.][.]"
+ _ = sum(tuple()...) // ERROR "multiple-value"
_ = sum3(tuple())
- _ = sum3(tuple()...) // ERROR "multiple-value|[.][.][.]" "not enough"
+ _ = sum3(tuple()...) // ERROR "multiple-value"
)
type T []T
@@ -42,6 +42,8 @@ var (
_ = funny([]T{}) // ok because []T{} is a T; passes []T{[]T{}}
)
+func Foo(n int) {}
+
func bad(args ...int) {
print(1, 2, args...) // ERROR "[.][.][.]"
println(args...) // ERROR "[.][.][.]"
@@ -51,12 +53,12 @@ func bad(args ...int) {
_ = new(int...) // ERROR "[.][.][.]"
n := 10
_ = make([]byte, n...) // ERROR "[.][.][.]"
- // TODO(rsc): enable after gofmt bug is fixed
- // _ = make([]byte, 10 ...) // error "[.][.][.]"
+ _ = make([]byte, 10 ...) // ERROR "[.][.][.]"
var x int
_ = unsafe.Pointer(&x...) // ERROR "[.][.][.]"
_ = unsafe.Sizeof(x...) // ERROR "[.][.][.]"
_ = [...]byte("foo") // ERROR "[.][.][.]"
_ = [...][...]int{{1,2,3},{4,5,6}} // ERROR "[.][.][.]"
-}
+ Foo(x...) // ERROR "invalid use of .*[.][.][.]"
+}
diff --git a/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go b/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go
index c9a2675..f3f863c 100644
--- a/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go
+++ b/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go b/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go
index 5486fe8..608091d 100644
--- a/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go
+++ b/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/ddd2.go b/gcc/testsuite/go.test/test/ddd2.go
index 0d9f634..612ba29 100644
--- a/gcc/testsuite/go.test/test/ddd2.go
+++ b/gcc/testsuite/go.test/test/ddd2.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/deferprint.go b/gcc/testsuite/go.test/test/deferprint.go
index 72c98b1..b74677a 100644
--- a/gcc/testsuite/go.test/test/deferprint.go
+++ b/gcc/testsuite/go.test/test/deferprint.go
@@ -1,6 +1,6 @@
-// cmpout
+// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/divide.go b/gcc/testsuite/go.test/test/divide.go
index b20f106..b557041 100644
--- a/gcc/testsuite/go.test/test/divide.go
+++ b/gcc/testsuite/go.test/test/divide.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/divmod.go b/gcc/testsuite/go.test/test/divmod.go
index 49fed02..ab85b7f 100644
--- a/gcc/testsuite/go.test/test/divmod.go
+++ b/gcc/testsuite/go.test/test/divmod.go
@@ -1,12 +1,12 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test division of variables. Generate many test cases,
// compute correct answer using shift and subtract,
-// and then compare against results from divison and
+// and then compare against results from division and
// modulus operators.
//
// Primarily useful for testing software div/mod.
diff --git a/gcc/testsuite/go.test/test/eof.go b/gcc/testsuite/go.test/test/eof.go
index 06c7790..d051f33 100644
--- a/gcc/testsuite/go.test/test/eof.go
+++ b/gcc/testsuite/go.test/test/eof.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/eof1.go b/gcc/testsuite/go.test/test/eof1.go
index 2105b89..90792ca 100644
--- a/gcc/testsuite/go.test/test/eof1.go
+++ b/gcc/testsuite/go.test/test/eof1.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/errchk b/gcc/testsuite/go.test/test/errchk
deleted file mode 100755
index de0c4fd..0000000
--- a/gcc/testsuite/go.test/test/errchk
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env perl
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# This script checks that the compilers emit the errors which we expect.
-# Usage: errchk COMPILER [OPTS] SOURCEFILES. This will run the command
-# COMPILER [OPTS] SOURCEFILES. The compilation is expected to fail; if
-# it succeeds, this script will report an error. The stderr output of
-# the compiler will be matched against comments in SOURCEFILES. For each
-# line of the source files which should generate an error, there should
-# be a comment of the form // ERROR "regexp". If the compiler generates
-# an error for a line which has no such comment, this script will report
-# an error. Likewise if the compiler does not generate an error for a
-# line which has a comment, or if the error message does not match the
-# <regexp>. The <regexp> syntax is Perl but its best to stick to egrep.
-
-use POSIX;
-
-my $exitcode = 1;
-
-if(@ARGV >= 1 && $ARGV[0] eq "-0") {
- $exitcode = 0;
- shift;
-}
-
-if(@ARGV < 1) {
- print STDERR "Usage: errchk COMPILER [OPTS] SOURCEFILES\n";
- exit 1;
-}
-
-# Grab SOURCEFILES
-foreach(reverse 0 .. @ARGV-1) {
- unless($ARGV[$_] =~ /\.(go|s)$/) {
- @file = @ARGV[$_+1 .. @ARGV-1];
- last;
- }
-}
-
-foreach $file (@file) {
- open(SRC, $file) || die "BUG: errchk: open $file: $!";
- $src{$file} = [<SRC>];
- close(SRC);
-}
-
-# Run command
-$cmd = join(' ', @ARGV);
-open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!";
-
-# 6g error messages continue onto additional lines with leading tabs.
-# Split the output at the beginning of each line that doesn't begin with a tab.
-$out = join('', <CMD>);
-@out = split(/^(?!\t)/m, $out);
-
-close CMD;
-
-if($exitcode != 0 && $? == 0) {
- print STDERR "BUG: errchk: command succeeded unexpectedly\n";
- print STDERR @out;
- exit 0;
-}
-
-if($exitcode == 0 && $? != 0) {
- print STDERR "BUG: errchk: command failed unexpectedly\n";
- print STDERR @out;
- exit 0;
-}
-
-if(!WIFEXITED($?)) {
- print STDERR "BUG: errchk: compiler crashed\n";
- print STDERR @out, "\n";
- exit 0;
-}
-
-sub bug() {
- if(!$bug++) {
- print STDERR "BUG: ";
- }
-}
-
-sub chk {
- my $file = shift;
- my $line = 0;
- my $regexp;
- my @errmsg;
- my @match;
- foreach my $src (@{$src{$file}}) {
- $line++;
- next if $src =~ m|////|; # double comment disables ERROR
- next unless $src =~ m|// (GC_)?ERROR (.*)|;
- my $all = $2;
- if($all !~ /^"([^"]*)"/) {
- print STDERR "$file:$line: malformed regexp\n";
- next;
- }
- @errmsg = grep { /$file:$line[:[]/ } @out;
- @out = grep { !/$file:$line[:[]/ } @out;
- if(@errmsg == 0) {
- bug();
- print STDERR "errchk: $file:$line: missing expected error: '$all'\n";
- next;
- }
- foreach my $regexp ($all =~ /"([^"]*)"/g) {
- # Turn relative line number in message into absolute line number.
- if($regexp =~ /LINE(([+-])([0-9]+))?/) {
- my $n = $line;
- if(defined($1)) {
- if($2 eq "+") {
- $n += int($3);
- } else {
- $n -= int($3);
- }
- }
- $regexp = "$`$file:$n$'";
- }
-
- @match = grep { /$regexp/ } @errmsg;
- if(@match == 0) {
- bug();
- print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n";
- next;
- }
- @errmsg = grep { !/$regexp/ } @errmsg;
- }
- if(@errmsg != 0) {
- bug();
- print STDERR "errchk: $file:$line: unmatched error messages:\n";
- foreach my $l (@errmsg) {
- print STDERR "> $l";
- }
- }
- }
-}
-
-foreach $file (@file) {
- chk($file)
-}
-
-if(@out != 0) {
- bug();
- print STDERR "errchk: unmatched error messages:\n";
- print STDERR "==================================================\n";
- print STDERR @out;
- print STDERR "==================================================\n";
-}
-
-exit 0;
diff --git a/gcc/testsuite/go.test/test/escape2.go b/gcc/testsuite/go.test/test/escape2.go
index be89c2d..5c6eb55 100644
--- a/gcc/testsuite/go.test/test/escape2.go
+++ b/gcc/testsuite/go.test/test/escape2.go
@@ -1,12 +1,14 @@
// errorcheck -0 -m -l
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test, using compiler diagnostic flags, that the escape analysis is working.
// Compiles but does not run. Inlining is disabled.
+// escape2n.go contains all the same tests but compiles with -N.
+
package foo
import (
@@ -16,94 +18,94 @@ import (
var gxx *int
-func foo1(x int) { // ERROR "moved to heap: x"
- gxx = &x // ERROR "&x escapes to heap"
+func foo1(x int) { // ERROR "moved to heap: x$"
+ gxx = &x
}
-func foo2(yy *int) { // ERROR "leaking param: yy"
+func foo2(yy *int) { // ERROR "leaking param: yy$"
gxx = yy
}
-func foo3(x int) *int { // ERROR "moved to heap: x"
- return &x // ERROR "&x escapes to heap"
+func foo3(x int) *int { // ERROR "moved to heap: x$"
+ return &x
}
type T *T
-func foo3b(t T) { // ERROR "leaking param: t"
+func foo3b(t T) { // ERROR "leaking param: t$"
*t = t
}
// xx isn't going anywhere, so use of yy is ok
-func foo4(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+func foo4(xx, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
xx = yy
}
// xx isn't going anywhere, so taking address of yy is ok
-func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape"
- xx = &yy // ERROR "&yy does not escape"
+func foo5(xx **int, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
+ xx = &yy
}
-func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy"
+func foo6(xx **int, yy *int) { // ERROR "xx does not escape$" "leaking param: yy$"
*xx = yy
}
-func foo7(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+func foo7(xx **int, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
**xx = *yy
}
-func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape"
+func foo8(xx, yy *int) int { // ERROR "xx does not escape$" "yy does not escape$"
xx = yy
return *xx
}
-func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy"
+func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$"
xx = yy
return xx
}
-func foo10(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape"
+func foo10(xx, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
*xx = *yy
}
func foo11() int {
x, y := 0, 42
- xx := &x // ERROR "&x does not escape"
- yy := &y // ERROR "&y does not escape"
+ xx := &x
+ yy := &y
*xx = *yy
return x
}
var xxx **int
-func foo12(yyy **int) { // ERROR "leaking param: yyy"
+func foo12(yyy **int) { // ERROR "leaking param: yyy$"
xxx = yyy
}
-// Must treat yyy as leaking because *yyy leaks, and the escape analysis
+// Must treat yyy as leaking because *yyy leaks, and the escape analysis
// summaries in exported metadata do not distinguish these two cases.
-func foo13(yyy **int) { // ERROR "leaking param: yyy"
+func foo13(yyy **int) { // ERROR "leaking param content: yyy$"
*xxx = *yyy
}
-func foo14(yyy **int) { // ERROR "yyy does not escape"
+func foo14(yyy **int) { // ERROR "yyy does not escape$"
**xxx = **yyy
}
-func foo15(yy *int) { // ERROR "moved to heap: yy"
- xxx = &yy // ERROR "&yy escapes to heap"
+func foo15(yy *int) { // ERROR "moved to heap: yy$"
+ xxx = &yy
}
-func foo16(yy *int) { // ERROR "leaking param: yy"
+func foo16(yy *int) { // ERROR "leaking param: yy$"
*xxx = yy
}
-func foo17(yy *int) { // ERROR "yy does not escape"
+func foo17(yy *int) { // ERROR "yy does not escape$"
**xxx = *yy
}
-func foo18(y int) { // ERROR "moved to heap: "y"
- *xxx = &y // ERROR "&y escapes to heap"
+func foo18(y int) { // ERROR "moved to heap: y$"
+ *xxx = &y
}
func foo19(y int) {
@@ -116,52 +118,52 @@ type Bar struct {
}
func NewBar() *Bar {
- return &Bar{42, nil} // ERROR "&Bar literal escapes to heap"
+ return &Bar{42, nil} // ERROR "&Bar{...} escapes to heap$"
}
-func NewBarp(x *int) *Bar { // ERROR "leaking param: x"
- return &Bar{42, x} // ERROR "&Bar literal escapes to heap"
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x$"
+ return &Bar{42, x} // ERROR "&Bar{...} escapes to heap$"
}
-func NewBarp2(x *int) *Bar { // ERROR "x does not escape"
- return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap"
+func NewBarp2(x *int) *Bar { // ERROR "x does not escape$"
+ return &Bar{*x, nil} // ERROR "&Bar{...} escapes to heap$"
}
-func (b *Bar) NoLeak() int { // ERROR "b does not escape"
+func (b *Bar) NoLeak() int { // ERROR "b does not escape$"
return *(b.ii)
}
-func (b *Bar) Leak() *int { // ERROR "leaking param: b"
- return &b.i // ERROR "&b.i escapes to heap"
+func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return &b.i
}
-func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape"
+func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: b to result ~r0 level=1$"
return b.ii
}
-func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b"
+func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
return b.ii
}
-func (b Bar) LeaksToo() *int { // ERROR "leaking param: b"
- v := 0 // ERROR "moved to heap: v"
- b.ii = &v // ERROR "&v escapes"
+func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ v := 0 // ERROR "moved to heap: v$"
+ b.ii = &v
return b.ii
}
-func (b *Bar) LeaksABit() *int { // ERROR "b does not escape"
- v := 0 // ERROR "moved to heap: v"
- b.ii = &v // ERROR "&v escapes"
+func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$"
+ v := 0 // ERROR "moved to heap: v$"
+ b.ii = &v
return b.ii
}
-func (b Bar) StillNoLeak() int { // ERROR "b does not escape"
+func (b Bar) StillNoLeak() int { // ERROR "b does not escape$"
v := 0
- b.ii = &v // ERROR "&v does not escape"
+ b.ii = &v
return b.i
}
-func goLeak(b *Bar) { // ERROR "leaking param: b"
+func goLeak(b *Bar) { // ERROR "leaking param: b$"
go b.NoLeak()
}
@@ -171,90 +173,105 @@ type Bar2 struct {
}
func NewBar2() *Bar2 {
- return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap"
+ return &Bar2{[12]int{42}, nil} // ERROR "&Bar2{...} escapes to heap$"
}
-func (b *Bar2) NoLeak() int { // ERROR "b does not escape"
+func (b *Bar2) NoLeak() int { // ERROR "b does not escape$"
return b.i[0]
}
-func (b *Bar2) Leak() []int { // ERROR "leaking param: b"
- return b.i[:] // ERROR "b.i escapes to heap"
+func (b *Bar2) Leak() []int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return b.i[:]
}
-func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape"
+func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 level=1$"
return b.ii[0:1]
}
-func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape"
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape$"
return b.i
}
-func (b *Bar2) LeakSelf() { // ERROR "leaking param: b"
- b.ii = b.i[0:4] // ERROR "b.i escapes to heap"
+func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$"
+ b.ii = b.i[0:4]
}
-func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b"
+func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$"
var buf []int
- buf = b.i[0:] // ERROR "b.i escapes to heap"
+ buf = b.i[0:]
b.ii = buf
}
func foo21() func() int {
- x := 42 // ERROR "moved to heap: x"
- return func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ x := 42
+ return func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+}
+
+func foo21a() func() int {
+ x := 42 // ERROR "moved to heap: x$"
+ return func() int { // ERROR "func literal escapes to heap$"
+ x++
+ return x
}
}
func foo22() int {
x := 42
- return func() int { // ERROR "func literal does not escape"
+ return func() int { // ERROR "func literal does not escape$"
return x
}()
}
-func foo23(x int) func() int { // ERROR "moved to heap: x"
- return func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+func foo23(x int) func() int {
+ return func() int { // ERROR "func literal escapes to heap$"
+ return x
}
}
-func foo23a(x int) func() int { // ERROR "moved to heap: x"
- f := func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+func foo23a(x int) func() int {
+ f := func() int { // ERROR "func literal escapes to heap$"
+ return x
}
return f
}
-func foo23b(x int) *(func() int) { // ERROR "moved to heap: x"
- f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap"
- return &f // ERROR "&f escapes to heap"
+func foo23b(x int) *(func() int) {
+ f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$"
+ return &f
+}
+
+func foo23c(x int) func() int { // ERROR "moved to heap: x$"
+ return func() int { // ERROR "func literal escapes to heap$"
+ x++
+ return x
+ }
}
func foo24(x int) int {
- return func() int { // ERROR "func literal does not escape"
+ return func() int { // ERROR "func literal does not escape$"
return x
}()
}
var x *int
-func fooleak(xx *int) int { // ERROR "leaking param: xx"
+func fooleak(xx *int) int { // ERROR "leaking param: xx$"
x = xx
return *x
}
-func foonoleak(xx *int) int { // ERROR "xx does not escape"
+func foonoleak(xx *int) int { // ERROR "xx does not escape$"
return *x + *xx
}
-func foo31(x int) int { // ERROR "moved to heap: x"
- return fooleak(&x) // ERROR "&x escapes to heap"
+func foo31(x int) int { // ERROR "moved to heap: x$"
+ return fooleak(&x)
}
func foo32(x int) int {
- return foonoleak(&x) // ERROR "&x does not escape"
+ return foonoleak(&x)
}
type Foo struct {
@@ -265,114 +282,114 @@ type Foo struct {
var F Foo
var pf *Foo
-func (f *Foo) fooleak() { // ERROR "leaking param: f"
+func (f *Foo) fooleak() { // ERROR "leaking param: f$"
pf = f
}
-func (f *Foo) foonoleak() { // ERROR "f does not escape"
+func (f *Foo) foonoleak() { // ERROR "f does not escape$"
F.x = f.x
}
-func (f *Foo) Leak() { // ERROR "leaking param: f"
+func (f *Foo) Leak() { // ERROR "leaking param: f$"
f.fooleak()
}
-func (f *Foo) NoLeak() { // ERROR "f does not escape"
+func (f *Foo) NoLeak() { // ERROR "f does not escape$"
f.foonoleak()
}
-func foo41(x int) { // ERROR "moved to heap: x"
- F.xx = &x // ERROR "&x escapes to heap"
+func foo41(x int) { // ERROR "moved to heap: x$"
+ F.xx = &x
}
-func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x"
- f.xx = &x // ERROR "&x escapes to heap"
+func (f *Foo) foo42(x int) { // ERROR "f does not escape$" "moved to heap: x$"
+ f.xx = &x
}
-func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x"
- f.xx = &x // ERROR "&x escapes to heap"
+func foo43(f *Foo, x int) { // ERROR "f does not escape$" "moved to heap: x$"
+ f.xx = &x
}
-func foo44(yy *int) { // ERROR "leaking param: yy"
+func foo44(yy *int) { // ERROR "leaking param: yy$"
F.xx = yy
}
-func (f *Foo) foo45() { // ERROR "f does not escape"
+func (f *Foo) foo45() { // ERROR "f does not escape$"
F.x = f.x
}
// See foo13 above for explanation of why f leaks.
-func (f *Foo) foo46() { // ERROR "leaking param: f"
+func (f *Foo) foo46() { // ERROR "leaking param content: f$"
F.xx = f.xx
}
-func (f *Foo) foo47() { // ERROR "leaking param: f"
- f.xx = &f.x // ERROR "&f.x escapes to heap"
+func (f *Foo) foo47() { // ERROR "leaking param: f$"
+ f.xx = &f.x
}
var ptrSlice []*int
-func foo50(i *int) { // ERROR "leaking param: i"
+func foo50(i *int) { // ERROR "leaking param: i$"
ptrSlice[0] = i
}
var ptrMap map[*int]*int
-func foo51(i *int) { // ERROR "leaking param: i"
+func foo51(i *int) { // ERROR "leaking param: i$"
ptrMap[i] = i
}
-func indaddr1(x int) *int { // ERROR "moved to heap: x"
- return &x // ERROR "&x escapes to heap"
+func indaddr1(x int) *int { // ERROR "moved to heap: x$"
+ return &x
}
-func indaddr2(x *int) *int { // ERROR "leaking param: x"
- return *&x // ERROR "&x does not escape"
+func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return *&x
}
-func indaddr3(x *int32) *int { // ERROR "leaking param: x"
- return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape"
+func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return *(**int)(unsafe.Pointer(&x))
}
// From package math:
func Float32bits(f float32) uint32 {
- return *(*uint32)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
+ return *(*uint32)(unsafe.Pointer(&f))
}
func Float32frombits(b uint32) float32 {
- return *(*float32)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
+ return *(*float32)(unsafe.Pointer(&b))
}
func Float64bits(f float64) uint64 {
- return *(*uint64)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
+ return *(*uint64)(unsafe.Pointer(&f))
}
func Float64frombits(b uint64) float64 {
- return *(*float64)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
+ return *(*float64)(unsafe.Pointer(&b))
}
// contrast with
-func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f"
- return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap"
+func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$"
+ return (*uint64)(unsafe.Pointer(&f))
}
-func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f"
+func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$"
return (*uint64)(unsafe.Pointer(f))
}
-func typesw(i interface{}) *int { // ERROR "leaking param: i"
+func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level=0$"
switch val := i.(type) {
case *int:
return val
case *int8:
- v := int(*val) // ERROR "moved to heap: v"
- return &v // ERROR "&v escapes to heap"
+ v := int(*val) // ERROR "moved to heap: v$"
+ return &v
}
return nil
}
-func exprsw(i *int) *int { // ERROR "leaking param: i"
+func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
switch j := i; *j + 110 {
case 12:
return j
@@ -384,20 +401,20 @@ func exprsw(i *int) *int { // ERROR "leaking param: i"
}
// assigning to an array element is like assigning to the array
-func foo60(i *int) *int { // ERROR "leaking param: i"
+func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
var a [12]*int
a[0] = i
return a[1]
}
-func foo60a(i *int) *int { // ERROR "i does not escape"
+func foo60a(i *int) *int { // ERROR "i does not escape$"
var a [12]*int
a[0] = i
return nil
}
// assigning to a struct field is like assigning to the struct
-func foo61(i *int) *int { // ERROR "leaking param: i"
+func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
type S struct {
a, b *int
}
@@ -406,7 +423,7 @@ func foo61(i *int) *int { // ERROR "leaking param: i"
return s.b
}
-func foo61a(i *int) *int { // ERROR "i does not escape"
+func foo61a(i *int) *int { // ERROR "i does not escape$"
type S struct {
a, b *int
}
@@ -418,11 +435,11 @@ func foo61a(i *int) *int { // ERROR "i does not escape"
// assigning to a struct field is like assigning to the struct but
// here this subtlety is lost, since s.a counts as an assignment to a
// track-losing dereference.
-func foo62(i *int) *int { // ERROR "leaking param: i"
+func foo62(i *int) *int { // ERROR "leaking param: i$"
type S struct {
a, b *int
}
- s := new(S) // ERROR "new[(]S[)] does not escape"
+ s := new(S) // ERROR "new\(S\) does not escape$"
s.a = i
return nil // s.b
}
@@ -431,14 +448,14 @@ type M interface {
M()
}
-func foo63(m M) { // ERROR "m does not escape"
+func foo63(m M) { // ERROR "m does not escape$"
}
-func foo64(m M) { // ERROR "leaking param: m"
+func foo64(m M) { // ERROR "leaking param: m$"
m.M()
}
-func foo64b(m M) { // ERROR "leaking param: m"
+func foo64b(m M) { // ERROR "leaking param: m$"
defer m.M()
}
@@ -448,55 +465,56 @@ func (MV) M() {}
func foo65() {
var mv MV
- foo63(&mv) // ERROR "&mv does not escape"
+ foo63(&mv)
}
func foo66() {
- var mv MV // ERROR "moved to heap: mv"
- foo64(&mv) // ERROR "&mv escapes to heap"
+ var mv MV // ERROR "moved to heap: mv$"
+ foo64(&mv)
}
func foo67() {
var mv MV
- foo63(mv)
+ foo63(mv) // ERROR "mv does not escape$"
}
func foo68() {
var mv MV
- foo64(mv) // escapes but it's an int so irrelevant
+ // escapes but it's an int so irrelevant
+ foo64(mv) // ERROR "mv escapes to heap$"
}
-func foo69(m M) { // ERROR "leaking param: m"
+func foo69(m M) { // ERROR "leaking param: m$"
foo64(m)
}
-func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m"
+func foo70(mv1 *MV, m M) { // ERROR "leaking param: m$" "leaking param: mv1$"
m = mv1
foo64(m)
}
-func foo71(x *int) []*int { // ERROR "leaking param: x"
+func foo71(x *int) []*int { // ERROR "leaking param: x$"
var y []*int
y = append(y, x)
return y
}
-func foo71a(x int) []*int { // ERROR "moved to heap: x"
+func foo71a(x int) []*int { // ERROR "moved to heap: x$"
var y []*int
- y = append(y, &x) // ERROR "&x escapes to heap"
+ y = append(y, &x)
return y
}
func foo72() {
var x int
var y [1]*int
- y[0] = &x // ERROR "&x does not escape"
+ y[0] = &x
}
func foo72aa() [10]*int {
- var x int // ERROR "moved to heap: x"
+ var x int // ERROR "moved to heap: x$"
var y [10]*int
- y[0] = &x // ERROR "&x escapes to heap"
+ y[0] = &x
return y
}
@@ -504,8 +522,8 @@ func foo72a() {
var y [10]*int
for i := 0; i < 10; i++ {
// escapes its scope
- x := i // ERROR "moved to heap: x"
- y[i] = &x // ERROR "&x escapes to heap"
+ x := i // ERROR "moved to heap: x$"
+ y[i] = &x
}
return
}
@@ -513,31 +531,56 @@ func foo72a() {
func foo72b() [10]*int {
var y [10]*int
for i := 0; i < 10; i++ {
- x := i // ERROR "moved to heap: x"
- y[i] = &x // ERROR "&x escapes to heap"
+ x := i // ERROR "moved to heap: x$"
+ y[i] = &x
}
return y
}
// issue 2145
func foo73() {
- s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$"
for _, v := range s {
- vv := v // ERROR "moved to heap: vv"
+ vv := v
// actually just escapes its scope
- defer func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ defer func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }()
+ }
+}
+
+func foo731() {
+ s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap$"
+ vv = 42
+ println(vv)
}()
}
}
func foo74() {
- s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$"
for _, v := range s {
- vv := v // ERROR "moved to heap: vv"
+ vv := v
// actually just escapes its scope
- fn := func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ fn := func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+func foo74a() {
+ s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap$"
+ vv += 1
+ println(vv)
}
defer fn()
}
@@ -546,110 +589,138 @@ func foo74() {
// issue 3975
func foo74b() {
var array [3]func()
- s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$"
+ for i, v := range s {
+ vv := v
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }
+ }
+}
+
+func foo74c() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "\[\]int{...} does not escape$"
for i, v := range s {
- vv := v // ERROR "moved to heap: vv"
+ vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
- array[i] = func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ array[i] = func() { // ERROR "func literal escapes to heap$"
+ println(&vv)
}
}
}
-func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y"
+func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "x does not escape$"
return y
}
-func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x"
- return &x[0] // ERROR "&x.0. escapes to heap"
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "y does not escape$"
+ return &x[0]
}
-func foo75(z *int) { // ERROR "z does not escape"
- myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+func foo75(z *int) { // ERROR "z does not escape$"
+ myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
-func foo75a(z *int) { // ERROR "z does not escape"
- myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+func foo75a(z *int) { // ERROR "z does not escape$"
+ myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
-func foo75esc(z *int) { // ERROR "leaking param: z"
- gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+func foo75esc(z *int) { // ERROR "leaking param: z$"
+ gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
-func foo75aesc(z *int) { // ERROR "z does not escape"
+func foo75aesc(z *int) { // ERROR "z does not escape$"
var ppi **interface{} // assignments to pointer dereferences lose track
- *ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ *ppi = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+}
+
+func foo75aesc1(z *int) { // ERROR "z does not escape$"
+ sink = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
}
-func foo76(z *int) { // ERROR "leaking param: z"
- myprint(nil, z) // ERROR "[.][.][.] argument does not escape"
+func foo76(z *int) { // ERROR "z does not escape"
+ myprint(nil, z) // ERROR "... argument does not escape$"
}
-func foo76a(z *int) { // ERROR "leaking param: z"
- myprint1(nil, z) // ERROR "[.][.][.] argument does not escape"
+func foo76a(z *int) { // ERROR "z does not escape"
+ myprint1(nil, z) // ERROR "... argument does not escape$"
}
func foo76b() {
- myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+ myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
func foo76c() {
- myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+ myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
func foo76d() {
- defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+ defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
func foo76e() {
- defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+ defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
func foo76f() {
for {
// TODO: This one really only escapes its scope, but we don't distinguish yet.
- defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ defer myprint(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
}
}
func foo76g() {
for {
- defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ defer myprint1(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
}
}
-func foo77(z []interface{}) { // ERROR "z does not escape"
+func foo77(z []interface{}) { // ERROR "z does not escape$"
myprint(nil, z...) // z does not escape
}
-func foo77a(z []interface{}) { // ERROR "z does not escape"
+func foo77a(z []interface{}) { // ERROR "z does not escape$"
myprint1(nil, z...)
}
-func foo77b(z []interface{}) { // ERROR "leaking param: z"
+func foo77b(z []interface{}) { // ERROR "leaking param: z$"
var ppi **interface{}
*ppi = myprint1(nil, z...)
}
-func foo78(z int) *int { // ERROR "moved to heap: z"
- return &z // ERROR "&z escapes to heap"
+func foo77c(z []interface{}) { // ERROR "leaking param: z$"
+ sink = myprint1(nil, z...)
+}
+
+func dotdotdot() {
+ i := 0
+ myprint(nil, &i) // ERROR "... argument does not escape$"
+
+ j := 0
+ myprint1(nil, &j) // ERROR "... argument does not escape$"
}
-func foo78a(z int) *int { // ERROR "moved to heap: z"
- y := &z // ERROR "&z escapes to heap"
- x := &y // ERROR "&y does not escape"
+func foo78(z int) *int { // ERROR "moved to heap: z$"
+ return &z
+}
+
+func foo78a(z int) *int { // ERROR "moved to heap: z$"
+ y := &z
+ x := &y
return *x // really return y
}
func foo79() *int {
- return new(int) // ERROR "new[(]int[)] escapes to heap"
+ return new(int) // ERROR "new\(int\) escapes to heap$"
}
func foo80() *int {
var z *int
for {
// Really just escapes its scope but we don't distinguish
- z = new(int) // ERROR "new[(]int[)] escapes to heap"
+ z = new(int) // ERROR "new\(int\) escapes to heap$"
}
_ = z
return nil
@@ -657,24 +728,24 @@ func foo80() *int {
func foo81() *int {
for {
- z := new(int) // ERROR "new[(]int[)] does not escape"
+ z := new(int) // ERROR "new\(int\) does not escape$"
_ = z
}
return nil
}
-func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param"
+func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param: p to result x level=0$" "leaking param: p to result y level=0$"
-func noop(x, y *int) {} // ERROR "does not escape"
+func noop(x, y *int) {} // ERROR "x does not escape$" "y does not escape$"
func foo82() {
- var x, y, z int // ERROR "moved to heap"
- go noop(tee(&z)) // ERROR "&z escapes to heap"
- go noop(&x, &y) // ERROR "escapes to heap"
+ var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
+ go noop(tee(&z))
+ go noop(&x, &y)
for {
- var u, v, w int // ERROR "moved to heap"
- defer noop(tee(&u)) // ERROR "&u escapes to heap"
- defer noop(&v, &w) // ERROR "escapes to heap"
+ var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$"
+ defer noop(tee(&u))
+ defer noop(&v, &w)
}
}
@@ -687,24 +758,24 @@ type LimitedFooer struct {
N int64
}
-func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r"
- return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap"
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r$"
+ return &LimitedFooer{r, n} // ERROR "&LimitedFooer{...} escapes to heap$"
}
-func foo90(x *int) map[*int]*int { // ERROR "leaking param: x"
- return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap"
+func foo90(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} escapes to heap$"
}
-func foo91(x *int) map[*int]*int { // ERROR "leaking param: x"
- return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap"
+func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$"
}
-func foo92(x *int) [2]*int { // ERROR "leaking param: x"
+func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$"
return [2]*int{x, nil}
}
// does not leak c
-func foo93(c chan *int) *int { // ERROR "c does not escape"
+func foo93(c chan *int) *int { // ERROR "c does not escape$"
for v := range c {
return v
}
@@ -712,7 +783,7 @@ func foo93(c chan *int) *int { // ERROR "c does not escape"
}
// does not leak m
-func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape"
+func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r2 level=1"
for k, v := range m {
if b {
return k
@@ -723,32 +794,32 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape"
}
// does leak x
-func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x"
+func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape$" "leaking param: x$"
m[x] = x
}
-// does not leak m
-func foo96(m []*int) *int { // ERROR "m does not escape"
+// does not leak m but does leak content
+func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1"
return m[0]
}
// does leak m
-func foo97(m [1]*int) *int { // ERROR "leaking param: m"
+func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
return m[0]
}
// does not leak m
-func foo98(m map[int]*int) *int { // ERROR "m does not escape"
+func foo98(m map[int]*int) *int { // ERROR "m does not escape$"
return m[0]
}
// does leak m
-func foo99(m *[1]*int) []*int { // ERROR "leaking param: m"
+func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r1 level=0$"
return m[:]
}
// does not leak m
-func foo100(m []*int) *int { // ERROR "m does not escape"
+func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1"
for _, v := range m {
return v
}
@@ -756,7 +827,7 @@ func foo100(m []*int) *int { // ERROR "m does not escape"
}
// does leak m
-func foo101(m [1]*int) *int { // ERROR "leaking param: m"
+func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
for _, v := range m {
return v
}
@@ -764,109 +835,109 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: m"
}
// does not leak m
-func foo101a(m [1]*int) *int { // ERROR "m does not escape"
- for i := range m { // ERROR "moved to heap: i"
- return &i // ERROR "&i escapes to heap"
+func foo101a(m [1]*int) *int { // ERROR "m does not escape$"
+ for i := range m { // ERROR "moved to heap: i$"
+ return &i
}
return nil
}
// does leak x
-func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x"
+func foo102(m []*int, x *int) { // ERROR "m does not escape$" "leaking param: x$"
m[0] = x
}
// does not leak x
-func foo103(m [1]*int, x *int) { // ERROR "m does not escape" "x does not escape"
+func foo103(m [1]*int, x *int) { // ERROR "m does not escape$" "x does not escape$"
m[0] = x
}
var y []*int
-// does not leak x
-func foo104(x []*int) { // ERROR "x does not escape"
+// does not leak x but does leak content
+func foo104(x []*int) { // ERROR "leaking param content: x"
copy(y, x)
}
-// does not leak x
-func foo105(x []*int) { // ERROR "x does not escape"
+// does not leak x but does leak content
+func foo105(x []*int) { // ERROR "leaking param content: x"
_ = append(y, x...)
}
// does leak x
-func foo106(x *int) { // ERROR "leaking param: x"
+func foo106(x *int) { // ERROR "leaking param: x$"
_ = append(y, x)
}
-func foo107(x *int) map[*int]*int { // ERROR "leaking param: x"
- return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap"
+func foo107(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$"
}
-func foo108(x *int) map[*int]*int { // ERROR "leaking param: x"
- return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap"
+func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} escapes to heap$"
}
-func foo109(x *int) *int { // ERROR "leaking param: x"
- m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape"
+func foo109(x *int) *int { // ERROR "leaking param: x$"
+ m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} does not escape$"
for k, _ := range m {
return k
}
return nil
}
-func foo110(x *int) *int { // ERROR "leaking param: x"
- m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape"
+func foo110(x *int) *int { // ERROR "leaking param: x$"
+ m := map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int{...} does not escape$"
return m[nil]
}
-func foo111(x *int) *int { // ERROR "leaking param: x"
- m := []*int{x} // ERROR "\[\]\*int literal does not escape"
+func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0"
+ m := []*int{x} // ERROR "\[\]\*int{...} does not escape$"
return m[0]
}
-func foo112(x *int) *int { // ERROR "leaking param: x"
+func foo112(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
m := [1]*int{x}
return m[0]
}
-func foo113(x *int) *int { // ERROR "leaking param: x"
+func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
m := Bar{ii: x}
return m.ii
}
-func foo114(x *int) *int { // ERROR "leaking param: x"
- m := &Bar{ii: x} // ERROR "&Bar literal does not escape"
+func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := &Bar{ii: x} // ERROR "&Bar{...} does not escape$"
return m.ii
}
-func foo115(x *int) *int { // ERROR "leaking param: x"
+func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
}
func foo116(b bool) *int {
if b {
- x := 1 // ERROR "moved to heap: x"
- return &x // ERROR "&x escapes to heap"
+ x := 1 // ERROR "moved to heap: x$"
+ return &x
} else {
- y := 1 // ERROR "moved to heap: y"
- return &y // ERROR "&y escapes to heap"
+ y := 1 // ERROR "moved to heap: y$"
+ return &y
}
return nil
}
-func foo117(unknown func(interface{})) { // ERROR "unknown does not escape"
- x := 1 // ERROR "moved to heap: x"
- unknown(&x) // ERROR "&x escapes to heap"
+func foo117(unknown func(interface{})) { // ERROR "unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x)
}
-func foo118(unknown func(*int)) { // ERROR "unknown does not escape"
- x := 1 // ERROR "moved to heap: x"
- unknown(&x) // ERROR "&x escapes to heap"
+func foo118(unknown func(*int)) { // ERROR "unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x)
}
func external(*int)
-func foo119(x *int) { // ERROR "leaking param: x"
+func foo119(x *int) { // ERROR "leaking param: x$"
external(x)
}
@@ -1077,16 +1148,16 @@ L100:
func foo121() {
for i := 0; i < 10; i++ {
- defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap"
- go myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap"
+ defer myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ go myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
}
}
// same as foo121 but check across import
func foo121b() {
for i := 0; i < 10; i++ {
- defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap"
- go fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap"
+ defer fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
}
}
@@ -1096,7 +1167,7 @@ func foo122() {
goto L1
L1:
- i = new(int) // ERROR "new.int. does not escape"
+ i = new(int) // ERROR "new\(int\) does not escape$"
_ = i
}
@@ -1105,25 +1176,25 @@ func foo123() {
var i *int
L1:
- i = new(int) // ERROR "new.int. escapes to heap"
+ i = new(int) // ERROR "new\(int\) escapes to heap$"
goto L1
_ = i
}
-func foo124(x **int) { // ERROR "x does not escape"
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes"
- func() { // ERROR "func literal does not escape"
- *x = p // ERROR "leaking closure reference p"
+func foo124(x **int) { // ERROR "x does not escape$"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "func literal does not escape$"
+ *x = p
}()
}
-func foo125(ch chan *int) { // ERROR "does not escape"
- var i int // ERROR "moved to heap"
- p := &i // ERROR "&i escapes to heap"
- func() { // ERROR "func literal does not escape"
- ch <- p // ERROR "leaking closure reference p"
+func foo125(ch chan *int) { // ERROR "ch does not escape$"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "func literal does not escape$"
+ ch <- p
}()
}
@@ -1131,9 +1202,9 @@ func foo126() {
var px *int // loopdepth 0
for {
// loopdepth 1
- var i int // ERROR "moved to heap"
- func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes"
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "func literal does not escape$"
+ px = &i
}()
}
_ = px
@@ -1142,26 +1213,26 @@ func foo126() {
var px *int
func foo127() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
q := p
px = q
}
func foo128() {
var i int
- p := &i // ERROR "&i does not escape"
+ p := &i
q := p
_ = q
}
func foo129() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap"
- func() { // ERROR "func literal does not escape"
- q := p // ERROR "leaking closure reference p"
- func() { // ERROR "func literal does not escape"
- r := q // ERROR "leaking closure reference q"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "func literal does not escape$"
+ q := p
+ func() { // ERROR "func literal does not escape$"
+ r := q
px = r
}()
}()
@@ -1169,40 +1240,40 @@ func foo129() {
func foo130() {
for {
- var i int // ERROR "moved to heap"
- func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "func literal does not escape$"
+ px = &i
}()
}
}
func foo131() {
- var i int // ERROR "moved to heap"
- func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "func literal does not escape$"
+ px = &i
}()
}
func foo132() {
- var i int // ERROR "moved to heap"
- go func() { // ERROR "func literal escapes to heap"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ var i int // ERROR "moved to heap: i$"
+ go func() { // ERROR "func literal escapes to heap$"
+ px = &i
}()
}
func foo133() {
- var i int // ERROR "moved to heap"
- defer func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ var i int // ERROR "moved to heap: i$"
+ defer func() { // ERROR "func literal does not escape$"
+ px = &i
}()
}
func foo134() {
var i int
- p := &i // ERROR "&i does not escape"
- func() { // ERROR "func literal does not escape"
+ p := &i
+ func() { // ERROR "func literal does not escape$"
q := p
- func() { // ERROR "func literal does not escape"
+ func() { // ERROR "func literal does not escape$"
r := q
_ = r
}()
@@ -1210,11 +1281,11 @@ func foo134() {
}
func foo135() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
- go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap"
- func() { // ERROR "func literal does not escape"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ go func() { // ERROR "func literal escapes to heap$"
+ q := p
+ func() { // ERROR "func literal does not escape$"
r := q
_ = r
}()
@@ -1222,24 +1293,24 @@ func foo135() {
}
func foo136() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
- go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap" "leaking closure reference p"
- func() { // ERROR "func literal does not escape"
- r := q // ERROR "leaking closure reference q"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ go func() { // ERROR "func literal escapes to heap$"
+ q := p
+ func() { // ERROR "func literal does not escape$"
+ r := q
px = r
}()
}()
}
func foo137() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap"
- func() { // ERROR "func literal does not escape"
- q := p // ERROR "leaking closure reference p" "moved to heap: q"
- go func() { // ERROR "func literal escapes to heap"
- r := q // ERROR "&q escapes to heap"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "func literal does not escape$"
+ q := p
+ go func() { // ERROR "func literal escapes to heap$"
+ r := q
_ = r
}()
}()
@@ -1249,8 +1320,8 @@ func foo138() *byte {
type T struct {
x [1]byte
}
- t := new(T) // ERROR "new.T. escapes to heap"
- return &t.x[0] // ERROR "&t.x.0. escapes to heap"
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
+ return &t.x[0]
}
func foo139() *byte {
@@ -1259,8 +1330,8 @@ func foo139() *byte {
y byte
}
}
- t := new(T) // ERROR "new.T. escapes to heap"
- return &t.x.y // ERROR "&t.x.y escapes to heap"
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
+ return &t.x.y
}
// issue 4751
@@ -1272,8 +1343,8 @@ func foo140() interface{} {
X string
T *T
}
- t := &T{} // ERROR "&T literal escapes to heap"
- return U{
+ t := &T{} // ERROR "&T{} escapes to heap$"
+ return U{ // ERROR "U{...} escapes to heap$"
X: t.X,
T: t,
}
@@ -1287,53 +1358,53 @@ func F2([]byte)
//go:noescape
-func F3(x []byte) // ERROR "F3 x does not escape"
+func F3(x []byte) // ERROR "x does not escape$"
-func F4(x []byte)
+func F4(x []byte) // ERROR "leaking param: x$"
func G() {
var buf1 [10]byte
- F1(buf1[:]) // ERROR "buf1 does not escape"
-
- var buf2 [10]byte // ERROR "moved to heap: buf2"
- F2(buf2[:]) // ERROR "buf2 escapes to heap"
+ F1(buf1[:])
+
+ var buf2 [10]byte // ERROR "moved to heap: buf2$"
+ F2(buf2[:])
var buf3 [10]byte
- F3(buf3[:]) // ERROR "buf3 does not escape"
-
- var buf4 [10]byte // ERROR "moved to heap: buf4"
- F4(buf4[:]) // ERROR "buf4 escapes to heap"
+ F3(buf3[:])
+
+ var buf4 [10]byte // ERROR "moved to heap: buf4$"
+ F4(buf4[:])
}
type Tm struct {
x int
}
-func (t *Tm) M() { // ERROR "t does not escape"
+func (t *Tm) M() { // ERROR "t does not escape$"
}
func foo141() {
var f func()
-
- t := new(Tm) // ERROR "escapes to heap"
- f = t.M // ERROR "t.M does not escape"
+
+ t := new(Tm) // ERROR "new\(Tm\) does not escape$"
+ f = t.M // ERROR "t.M does not escape$"
_ = f
}
var gf func()
func foo142() {
- t := new(Tm) // ERROR "escapes to heap"
- gf = t.M // ERROR "t.M escapes to heap"
+ t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ gf = t.M // ERROR "t.M escapes to heap$"
}
// issue 3888.
func foo143() {
for i := 0; i < 1000; i++ {
- func() { // ERROR "func literal does not escape"
+ func() { // ERROR "func literal does not escape$"
for i := 0; i < 1; i++ {
var t Tm
- t.M() // ERROR "t does not escape"
+ t.M()
}
}()
}
@@ -1349,11 +1420,427 @@ func foo144a(*int)
func foo144() {
var x int
- foo144a(&x) // ERROR "&x does not escape"
+ foo144a(&x)
var y int
- foo144b(&y) // ERROR "&y does not escape"
+ foo144b(&y)
}
//go:noescape
func foo144b(*int)
+
+// issue 7313: for loop init should not be treated as "in loop"
+
+type List struct {
+ Next *List
+}
+
+func foo145(l List) { // ERROR "l does not escape$"
+ var p *List
+ for p = &l; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo146(l List) { // ERROR "l does not escape$"
+ var p *List
+ p = &l
+ for ; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo147(l List) { // ERROR "l does not escape$"
+ var p *List
+ p = &l
+ for p.Next != nil {
+ p = p.Next
+ }
+}
+
+func foo148(l List) { // ERROR "l does not escape$"
+ for p := &l; p.Next != nil; p = p.Next {
+ }
+}
+
+// related: address of variable should have depth of variable, not of loop
+
+func foo149(l List) { // ERROR "l does not escape$"
+ var p *List
+ for {
+ for p = &l; p.Next != nil; p = p.Next {
+ }
+ }
+}
+
+// issue 7934: missed ... if element type had no pointers
+
+var save150 []byte
+
+func foo150(x ...byte) { // ERROR "leaking param: x$"
+ save150 = x
+}
+
+func bar150() {
+ foo150(1, 2, 3) // ERROR "... argument escapes to heap$"
+}
+
+// issue 7931: bad handling of slice of array
+
+var save151 *int
+
+func foo151(x *int) { // ERROR "leaking param: x$"
+ save151 = x
+}
+
+func bar151() {
+ var a [64]int // ERROR "moved to heap: a$"
+ a[4] = 101
+ foo151(&(&a)[4:8][0])
+}
+
+func bar151b() {
+ var a [10]int // ERROR "moved to heap: a$"
+ b := a[:]
+ foo151(&b[4:8][0])
+}
+
+func bar151c() {
+ var a [64]int // ERROR "moved to heap: a$"
+ a[4] = 101
+ foo151(&(&a)[4:8:8][0])
+}
+
+func bar151d() {
+ var a [10]int // ERROR "moved to heap: a$"
+ b := a[:]
+ foo151(&b[4:8:8][0])
+}
+
+// issue 8120
+
+type U struct {
+ s *string
+}
+
+func (u *U) String() *string { // ERROR "leaking param: u to result ~r0 level=1$"
+ return u.s
+}
+
+type V struct {
+ s *string
+}
+
+func NewV(u U) *V { // ERROR "leaking param: u$"
+ return &V{u.String()} // ERROR "&V{...} escapes to heap$"
+}
+
+func foo152() {
+ a := "a" // ERROR "moved to heap: a$"
+ u := U{&a}
+ v := NewV(u)
+ println(v)
+}
+
+// issue 8176 - &x in type switch body not marked as escaping
+
+func foo153(v interface{}) *int { // ERROR "v does not escape"
+ switch x := v.(type) {
+ case int: // ERROR "moved to heap: x$"
+ return &x
+ }
+ panic(0)
+}
+
+// issue 8185 - &result escaping into result
+
+func f() (x int, y *int) { // ERROR "moved to heap: x$"
+ y = &x
+ return
+}
+
+func g() (x interface{}) { // ERROR "moved to heap: x$"
+ x = &x
+ return
+}
+
+var sink interface{}
+
+type Lit struct {
+ p *int
+}
+
+func ptrlitNoescape() {
+ // Both literal and element do not escape.
+ i := 0
+ x := &Lit{&i} // ERROR "&Lit{...} does not escape$"
+ _ = x
+}
+
+func ptrlitNoEscape2() {
+ // Literal does not escape, but element does.
+ i := 0 // ERROR "moved to heap: i$"
+ x := &Lit{&i} // ERROR "&Lit{...} does not escape$"
+ sink = *x
+}
+
+func ptrlitEscape() {
+ // Both literal and element escape.
+ i := 0 // ERROR "moved to heap: i$"
+ x := &Lit{&i} // ERROR "&Lit{...} escapes to heap$"
+ sink = x
+}
+
+// self-assignments
+
+type Buffer struct {
+ arr [64]byte
+ arrPtr *[64]byte
+ buf1 []byte
+ buf2 []byte
+ str1 string
+ str2 string
+}
+
+func (b *Buffer) foo() { // ERROR "b does not escape$"
+ b.buf1 = b.buf1[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2\]$"
+ b.buf1 = b.buf1[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2:3\]$"
+ b.buf1 = b.buf2[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2\]$"
+ b.buf1 = b.buf2[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2:3\]$"
+}
+
+func (b *Buffer) bar() { // ERROR "leaking param: b$"
+ b.buf1 = b.arr[1:2]
+}
+
+func (b *Buffer) arrayPtr() { // ERROR "b does not escape"
+ b.buf1 = b.arrPtr[1:2] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2\]$"
+ b.buf1 = b.arrPtr[1:2:3] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2:3\]$"
+}
+
+func (b *Buffer) baz() { // ERROR "b does not escape$"
+ b.str1 = b.str1[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str1\[1:2\]$"
+ b.str1 = b.str2[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str2\[1:2\]$"
+}
+
+func (b *Buffer) bat() { // ERROR "leaking param content: b$"
+ o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap$"
+ o.buf1 = b.buf1[1:2]
+ sink = o
+}
+
+func quux(sp *string, bp *[]byte) { // ERROR "bp does not escape$" "sp does not escape$"
+ *sp = (*sp)[1:2] // ERROR "quux ignoring self-assignment in \*sp = \(\*sp\)\[1:2\]$"
+ *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment in \*bp = \(\*bp\)\[1:2\]$"
+}
+
+type StructWithString struct {
+ p *int
+ s string
+}
+
+// This is escape analysis false negative.
+// We assign the pointer to x.p but leak x.s. Escape analysis coarsens flows
+// to just x, and thus &i looks escaping.
+func fieldFlowTracking() {
+ var x StructWithString
+ i := 0 // ERROR "moved to heap: i$"
+ x.p = &i
+ sink = x.s // ERROR "x.s escapes to heap$"
+}
+
+// String operations.
+
+func slicebytetostring0() {
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) does not escape$"
+ _ = s
+}
+
+func slicebytetostring1() {
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) does not escape$"
+ s1 := s[0:1]
+ _ = s1
+}
+
+func slicebytetostring2() {
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) escapes to heap$"
+ s1 := s[0:1] // ERROR "moved to heap: s1$"
+ sink = &s1
+}
+
+func slicebytetostring3() {
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) escapes to heap$"
+ s1 := s[0:1]
+ sink = s1 // ERROR "s1 escapes to heap$"
+}
+
+func addstr0() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 does not escape$"
+ _ = s
+}
+
+func addstr1() {
+ s0 := "a"
+ s1 := "b"
+ s := "c"
+ s += s0 + s1 // ERROR "s0 \+ s1 does not escape$"
+ _ = s
+}
+
+func addstr2() {
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s0 := "a"
+ s := string(b) + s0 // ERROR "string\(b\) \+ s0 does not escape$" "string\(b\) does not escape$"
+ _ = s
+}
+
+func addstr3() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap$"
+ s2 := s[0:1]
+ sink = s2 // ERROR "s2 escapes to heap$"
+}
+
+func intstring0() bool {
+ // string does not escape
+ x := '0'
+ s := string(x) // ERROR "string\(x\) does not escape$"
+ return s == "0"
+}
+
+func intstring1() string {
+ // string does not escape, but the buffer does
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap$"
+ return s
+}
+
+func intstring2() {
+ // string escapes to heap
+ x := '0'
+ s := string(x) // ERROR "moved to heap: s$" "string\(x\) escapes to heap$"
+ sink = &s
+}
+
+func stringtoslicebyte0() {
+ s := "foo"
+ x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$"
+ _ = x
+}
+
+func stringtoslicebyte1() []byte {
+ s := "foo"
+ return []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$"
+}
+
+func stringtoslicebyte2() {
+ s := "foo"
+ sink = []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$"
+}
+
+func stringtoslicerune0() {
+ s := "foo"
+ x := []rune(s) // ERROR "\(\[\]rune\)\(s\) does not escape$"
+ _ = x
+}
+
+func stringtoslicerune1() []rune {
+ s := "foo"
+ return []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$"
+}
+
+func stringtoslicerune2() {
+ s := "foo"
+ sink = []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$"
+}
+
+func slicerunetostring0() {
+ r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$"
+ s := string(r) // ERROR "string\(r\) does not escape$"
+ _ = s
+}
+
+func slicerunetostring1() string {
+ r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$"
+ return string(r) // ERROR "string\(r\) escapes to heap$"
+}
+
+func slicerunetostring2() {
+ r := []rune{1, 2, 3} // ERROR "\[\]rune{...} does not escape$"
+ sink = string(r) // ERROR "string\(r\) escapes to heap$"
+}
+
+func makemap0() {
+ m := make(map[int]int) // ERROR "make\(map\[int\]int\) does not escape$"
+ m[0] = 0
+ m[1]++
+ delete(m, 1)
+ sink = m[0] // ERROR "m\[0\] escapes to heap$"
+}
+
+func makemap1() map[int]int {
+ return make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
+}
+
+func makemap2() {
+ m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
+ sink = m
+}
+
+func nonescapingEface(m map[interface{}]bool) bool { // ERROR "m does not escape$"
+ return m["foo"] // ERROR ".foo. does not escape$"
+}
+
+func nonescapingIface(m map[M]bool) bool { // ERROR "m does not escape$"
+ return m[MV(0)] // ERROR "MV\(0\) does not escape$"
+}
+
+func issue10353() {
+ x := new(int) // ERROR "new\(int\) escapes to heap$"
+ issue10353a(x)()
+}
+
+func issue10353a(x *int) func() { // ERROR "leaking param: x$"
+ return func() { // ERROR "func literal escapes to heap$"
+ println(*x)
+ }
+}
+
+func issue10353b() {
+ var f func()
+ for {
+ x := new(int) // ERROR "new\(int\) escapes to heap$"
+ f = func() { // ERROR "func literal escapes to heap$"
+ println(*x)
+ }
+ }
+ _ = f
+}
+
+func issue11387(x int) func() int {
+ f := func() int { return x } // ERROR "func literal escapes to heap"
+ slice1 := []func() int{f} // ERROR "\[\].* does not escape"
+ slice2 := make([]func() int, 1) // ERROR "make\(.*\) does not escape"
+ copy(slice2, slice1)
+ return slice2[0]
+}
+
+func issue12397(x, y int) { // ERROR "moved to heap: y$"
+ // x does not escape below, because all relevant code is dead.
+ if false {
+ gxx = &x
+ } else {
+ gxx = &y
+ }
+
+ if true {
+ gxx = &y
+ } else {
+ gxx = &x
+ }
+}
diff --git a/gcc/testsuite/go.test/test/escape3.go b/gcc/testsuite/go.test/test/escape3.go
index 4c19891..f1131a2 100644
--- a/gcc/testsuite/go.test/test/escape3.go
+++ b/gcc/testsuite/go.test/test/escape3.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/escape4.go b/gcc/testsuite/go.test/test/escape4.go
index 83bc8eb..a4a9c14 100644
--- a/gcc/testsuite/go.test/test/escape4.go
+++ b/gcc/testsuite/go.test/test/escape4.go
@@ -1,6 +1,6 @@
// errorcheck -0 -m
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,38 +12,38 @@ package foo
var p *int
func alloc(x int) *int { // ERROR "can inline alloc" "moved to heap: x"
- return &x // ERROR "&x escapes to heap"
+ return &x
}
var f func()
func f1() {
- p = alloc(2) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
+ p = alloc(2) // ERROR "inlining call to alloc" "moved to heap: x"
// Escape analysis used to miss inlined code in closures.
- func() { // ERROR "func literal does not escape"
- p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
- }()
+ func() { // ERROR "can inline f1.func1"
+ p = alloc(3) // ERROR "inlining call to alloc"
+ }() // ERROR "inlining call to f1.func1" "inlining call to alloc" "moved to heap: x"
- f = func() { // ERROR "func literal escapes to heap"
- p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
+ f = func() { // ERROR "func literal escapes to heap" "can inline f1.func2"
+ p = alloc(3) // ERROR "inlining call to alloc" "moved to heap: x"
}
f()
}
func f2() {} // ERROR "can inline f2"
-// No inline for panic, recover.
-func f3() { panic(1) }
+// No inline for recover; panic now allowed to inline.
+func f3() { panic(1) } // ERROR "can inline f3"
func f4() { recover() }
func f5() *byte {
type T struct {
x [1]byte
}
- t := new(T) // ERROR "new.T. escapes to heap"
- return &t.x[0] // ERROR "&t.x.0. escapes to heap"
+ t := new(T) // ERROR "new.T. escapes to heap"
+ return &t.x[0]
}
func f6() *byte {
@@ -52,6 +52,6 @@ func f6() *byte {
y byte
}
}
- t := new(T) // ERROR "new.T. escapes to heap"
- return &t.x.y // ERROR "&t.x.y escapes to heap"
+ t := new(T) // ERROR "new.T. escapes to heap"
+ return &t.x.y
}
diff --git a/gcc/testsuite/go.test/test/escape5.go b/gcc/testsuite/go.test/test/escape5.go
index c964687..2ed2023 100644
--- a/gcc/testsuite/go.test/test/escape5.go
+++ b/gcc/testsuite/go.test/test/escape5.go
@@ -1,6 +1,6 @@
// errorcheck -0 -m -l
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,6 +9,11 @@
package foo
+import (
+ "runtime"
+ "unsafe"
+)
+
func noleak(p *int) int { // ERROR "p does not escape"
return *p
}
@@ -17,19 +22,19 @@ func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
return p
}
-func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2"
+func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2"
return p, p
}
-func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3"
+func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
return p, q
}
-func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
+func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
return leaktoret22(q, p)
}
-func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
+func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
r, s := leaktoret22(q, p)
return r, s
}
@@ -58,37 +63,37 @@ func leaktosink(p *int) *int { // ERROR "leaking param: p"
func f1() {
var x int
- p := noleak(&x) // ERROR "&x does not escape"
+ p := noleak(&x)
_ = p
}
func f2() {
var x int
- p := leaktoret(&x) // ERROR "&x does not escape"
+ p := leaktoret(&x)
_ = p
}
func f3() {
- var x int // ERROR "moved to heap: x"
- p := leaktoret(&x) // ERROR "&x escapes to heap"
+ var x int // ERROR "moved to heap: x"
+ p := leaktoret(&x)
gp = p
}
func f4() {
- var x int // ERROR "moved to heap: x"
- p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
+ var x int // ERROR "moved to heap: x"
+ p, q := leaktoret2(&x)
gp = p
gp = q
}
func f5() {
var x int
- leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
+ leaktoret22(leaktoret2(&x))
}
func f6() {
- var x int // ERROR "moved to heap: x"
- px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
+ var x int // ERROR "moved to heap: x"
+ px1, px2 := leaktoret22(leaktoret2(&x))
gp = px1
_ = px2
}
@@ -117,7 +122,6 @@ func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaki
return p, q
}
-
var global interface{}
type T1 struct {
@@ -128,24 +132,140 @@ type T2 struct {
Y *T1
}
-func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
+func f8(p *T1) (k T2) { // ERROR "leaking param: p$"
if p == nil {
k = T2{}
return
}
- global = p // should make p leak always
+ // should make p leak always
+ global = p
return T2{p}
}
func f9() {
var j T1 // ERROR "moved to heap: j"
- f8(&j) // ERROR "&j escapes to heap"
+ f8(&j)
}
func f10() {
// These don't escape but are too big for the stack
- var x [1<<30]byte // ERROR "moved to heap: x"
- var y = make([]byte, 1<<30) // ERROR "does not escape"
+ var x [1 << 30]byte // ERROR "moved to heap: x"
+ var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
_ = x[0] + y[0]
}
+
+// Test for issue 19687 (passing to unnamed parameters does not escape).
+func f11(**int) {
+}
+func f12(_ **int) {
+}
+func f13() {
+ var x *int
+ f11(&x)
+ f12(&x)
+ runtime.KeepAlive(&x)
+}
+
+// Test for issue 24305 (passing to unnamed receivers does not escape).
+type U int
+
+func (*U) M() {}
+func (_ *U) N() {}
+
+func _() {
+ var u U
+ u.M()
+ u.N()
+}
+
+func fbad24305() {
+ // BAD u should not be heap allocated
+ var u U // ERROR "moved to heap: u"
+ (*U).M(&u)
+ (*U).N(&u)
+}
+
+// Issue 24730: taking address in a loop causes unnecessary escape
+type T24730 struct {
+ x [64]byte
+}
+
+func (t *T24730) g() { // ERROR "t does not escape"
+ y := t.x[:]
+ for i := range t.x[:] {
+ y = t.x[:]
+ y[i] = 1
+ }
+
+ var z *byte
+ for i := range t.x[:] {
+ z = &t.x[i]
+ *z = 2
+ }
+}
+
+// Issue 15730: copy causes unnecessary escape
+
+var sink []byte
+var sink2 []int
+var sink3 []*int
+
+func f15730a(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case string:
+ copy(sink, a)
+ }
+ }
+}
+
+func f15730b(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []int:
+ copy(sink2, a)
+ }
+ }
+}
+
+func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []*int:
+ // copy pointerful data should cause escape
+ copy(sink3, a)
+ }
+ }
+}
+
+// Issue 29000: unnamed parameter is not handled correctly
+
+var sink4 interface{}
+var alwaysFalse = false
+
+func f29000(_ int, x interface{}) { // ERROR "leaking param: x"
+ sink4 = x
+ if alwaysFalse {
+ g29000()
+ }
+}
+
+func g29000() {
+ x := 1
+ f29000(2, x) // ERROR "x escapes to heap"
+}
+
+// Issue 28369: taking an address of a parameter and converting it into a uintptr causes an
+// unnecessary escape.
+
+var sink28369 uintptr
+
+func f28369(n int) int {
+ if n == 0 {
+ sink28369 = uintptr(unsafe.Pointer(&n))
+ return n
+ }
+
+ return 1 + f28369(n-1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug0.go b/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug0.go
index e312256..2f59d81 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug0.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug0.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug1.go b/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug1.go
index 486fe76..ea5bcfe 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug083.dir/bug1.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug0.go b/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug0.go
index af9d991..7a6e347 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug0.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug0.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug1.go b/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug1.go
index cadf0e6..2568e37 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug088.dir/bug1.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug0.go b/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug0.go
index d9c26a0..7494c58 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug0.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug0.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug1.go b/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug1.go
index 0f1d20e..eff0d36 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug106.dir/bug1.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug108.go b/gcc/testsuite/go.test/test/fixedbugs/bug108.go
index 9f2a27e..cfec4c9 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug108.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug108.go
@@ -6,6 +6,6 @@
package main
func f() {
- v := 1 << 1025; // ERROR "overflow|stupid shift"
+ v := 1 << 1025; // ERROR "overflow|shift count too large"
_ = v
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug121.go b/gcc/testsuite/go.test/test/fixedbugs/bug121.go
index 5adf982..22c7181 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug121.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug121.go
@@ -15,4 +15,3 @@ type I interface {
type J interface {
h T; // ERROR "syntax|signature"
}
-
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug0.go b/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug0.go
index 48cd104..19a2bfb 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug0.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug0.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug1.go b/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug1.go
index 7562147..dd59b2f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug1.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug2.go b/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug2.go
index e531001..b6184c2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug133.dir/bug2.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug13343.go b/gcc/testsuite/go.test/test/fixedbugs/bug13343.go
new file mode 100644
index 0000000..a7febea
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug13343.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var (
+ a, b = f() // ERROR "initialization loop|depends upon itself|depend upon each other"
+ c = b // GCCGO_ERROR "depends upon itself|depend upon each other"
+)
+
+func f() (int, int) {
+ return c, c
+}
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug1515.go b/gcc/testsuite/go.test/test/fixedbugs/bug1515.go
index a4baccd..5fef5ad 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug1515.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug1515.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/x.go b/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/x.go
index bd52c6c..2673552 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/x.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/x.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/y.go b/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/y.go
index 27e2f35..428808d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/y.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug160.dir/y.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug169.go b/gcc/testsuite/go.test/test/fixedbugs/bug169.go
index f63c2f3..62ab7c2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug169.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug169.go
@@ -5,6 +5,6 @@
// license that can be found in the LICENSE file.
package main
-var x = '''; // ERROR "char"
+var x = '''; // ERROR "char|rune"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug173.go b/gcc/testsuite/go.test/test/fixedbugs/bug173.go
index 6479bb2..3515c64 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug173.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug173.go
@@ -18,4 +18,6 @@ func main() {
}
for _ = range t {
}
+ for range t {
+ }
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug176.go b/gcc/testsuite/go.test/test/fixedbugs/bug176.go
index 82f8dba..7001dd0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug176.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug176.go
@@ -9,6 +9,6 @@ package main
var x int
var a = []int{ x: 1} // ERROR "constant"
-var b = [...]int{ x : 1} // ERROR "constant"
+var b = [...]int{x: 1} // GCCGO_ERROR "constant"
var c = map[int]int{ x: 1}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug19403.go b/gcc/testsuite/go.test/test/fixedbugs/bug19403.go
new file mode 100644
index 0000000..94c0fb4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug19403.go
@@ -0,0 +1,134 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test for golang.org/issue/19403.
+// F15 should not be clobbered by float-to-int conversion on ARM.
+// This test requires enough locals that can be put in registers that the compiler can choose to use F15.
+package main
+
+var count float32 = 16
+var i0 int
+var i1 int
+var i2 int
+var i3 int
+var i4 int
+var i5 int
+var i6 int
+var i7 int
+var i8 int
+var i9 int
+var i10 int
+var i11 int
+var i12 int
+var i13 int
+var i14 int
+var i15 int
+var i16 int
+
+func main() {
+ var f0 float32 = 0.0
+ var f1 float32 = 1.0
+ var f2 float32 = 2.0
+ var f3 float32 = 3.0
+ var f4 float32 = 4.0
+ var f5 float32 = 5.0
+ var f6 float32 = 6.0
+ var f7 float32 = 7.0
+ var f8 float32 = 8.0
+ var f9 float32 = 9.0
+ var f10 float32 = 10.0
+ var f11 float32 = 11.0
+ var f12 float32 = 12.0
+ var f13 float32 = 13.0
+ var f14 float32 = 14.0
+ var f15 float32 = 15.0
+ var f16 float32 = 16.0
+ i0 = int(f0)
+ i1 = int(f1)
+ i2 = int(f2)
+ i3 = int(f3)
+ i4 = int(f4)
+ i5 = int(f5)
+ i6 = int(f6)
+ i7 = int(f7)
+ i8 = int(f8)
+ i9 = int(f9)
+ i10 = int(f10)
+ i11 = int(f11)
+ i12 = int(f12)
+ i13 = int(f13)
+ i14 = int(f14)
+ i15 = int(f15)
+ i16 = int(f16)
+ if f16 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f15 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f14 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f13 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f12 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f11 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f10 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f9 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f8 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f7 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f6 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f5 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f4 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f3 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f2 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f1 != count {
+ panic("fail")
+ }
+ count -= 1
+ if f0 != count {
+ panic("fail")
+ }
+ count -= 1
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug195.go b/gcc/testsuite/go.test/test/fixedbugs/bug195.go
index 85367cb..94f61ff 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug195.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug195.go
@@ -6,22 +6,22 @@
package main
-type I1 interface { I2 } // ERROR "interface"
+type I1 interface{ I2 } // ERROR "interface"
type I2 int
-type I3 interface { int } // ERROR "interface"
+type I3 interface{ int } // ERROR "interface"
type S struct {
- x interface{ S } // ERROR "interface"
+ x interface{ S } // ERROR "interface"
}
-type I4 interface {
- I4 // ERROR "interface"
+type I4 interface { // GC_ERROR "invalid recursive type I4\n\tLINE: I4 refers to\n\tLINE: I4$"
+ I4 // GCCGO_ERROR "interface"
}
-type I5 interface {
- I6 // GCCGO_ERROR "interface"
+type I5 interface { // GC_ERROR "invalid recursive type I5\n\tLINE: I5 refers to\n\tLINE+4: I6 refers to\n\tLINE: I5$"
+ I6
}
type I6 interface {
- I5 // ERROR "interface"
+ I5 // GCCGO_ERROR "interface"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug203.go b/gcc/testsuite/go.test/test/fixedbugs/bug203.go
index 2fb084b..68647ec 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug203.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug203.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug206.go b/gcc/testsuite/go.test/test/fixedbugs/bug206.go
index c2382ac..91efa3f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug206.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug206.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug214.go b/gcc/testsuite/go.test/test/fixedbugs/bug214.go
index 5420058..f3c25e7 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug214.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug214.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Used to crash the compiler.
-// http://code.google.com/p/go/issues/detail?id=88
+// https://golang.org/issue/88
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug215.go b/gcc/testsuite/go.test/test/fixedbugs/bug215.go
index 08ed662..b27cc7d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug215.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug215.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Used to crash the compiler.
-// http://code.google.com/p/go/issues/detail?id=158
+// https://golang.org/issue/158
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug216.go b/gcc/testsuite/go.test/test/fixedbugs/bug216.go
index c83a522..470369a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug216.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug216.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Used to be rejected
-// http://code.google.com/p/go/issues/detail?id=188
+// https://golang.org/issue/188
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug217.go b/gcc/testsuite/go.test/test/fixedbugs/bug217.go
index ec93c25..ea836b9 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug217.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug217.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Used to crash
-// http://code.google.com/p/go/issues/detail?id=204
+// https://golang.org/issue/204
package main
@@ -13,3 +13,5 @@ func () x() // ERROR "no receiver"
func (a b, c d) x() // ERROR "multiple receiver"
+type b int
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug218.go b/gcc/testsuite/go.test/test/fixedbugs/bug218.go
index 0e008db..f159f05 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug218.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug218.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Crashes 6g, 8g
-// http://code.google.com/p/go/issues/detail?id=238
+// https://golang.org/issue/238
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug221.go b/gcc/testsuite/go.test/test/fixedbugs/bug221.go
index 86fda20..4275474 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug221.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug221.go
@@ -7,7 +7,7 @@
// function call arg reordering was picking out 1 call that
// didn't need to be in a temporary, but it was picking
// out the first call instead of the last call.
-// http://code.google.com/p/go/issues/detail?id=370
+// https://golang.org/issue/370
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug227.go b/gcc/testsuite/go.test/test/fixedbugs/bug227.go
index ea8d02d..afbdd97 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug227.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug227.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug228.go b/gcc/testsuite/go.test/test/fixedbugs/bug228.go
index 3fccd17..f7ac670 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug228.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug228.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug229.go b/gcc/testsuite/go.test/test/fixedbugs/bug229.go
index 1977688..a30202f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug229.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug229.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,11 +10,11 @@ import "testing"
func main() {
var t testing.T
-
+
// make sure error mentions that
// name is unexported, not just "name not found".
- t.name = nil // ERROR "unexported"
-
- println(testing.anyLowercaseName("asdf")) // ERROR "unexported" "undefined: testing.anyLowercaseName"
+ t.common.name = nil // ERROR "unexported"
+
+ println(testing.anyLowercaseName("asdf")) // ERROR "unexported"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug230.go b/gcc/testsuite/go.test/test/fixedbugs/bug230.go
index 210acc4..e5eead5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug230.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug230.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug231.go b/gcc/testsuite/go.test/test/fixedbugs/bug231.go
index a9d409b..f64ddc3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug231.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug231.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug232.go b/gcc/testsuite/go.test/test/fixedbugs/bug232.go
index d18727e..10b0c52 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug232.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug232.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug233.go b/gcc/testsuite/go.test/test/fixedbugs/bug233.go
index 63f8ee2..d4e1e07 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug233.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug233.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug234.go b/gcc/testsuite/go.test/test/fixedbugs/bug234.go
index 9f503f0..0d37ce2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug234.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug234.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug235.go b/gcc/testsuite/go.test/test/fixedbugs/bug235.go
index d12d9e7..a33092b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug235.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug235.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug236.go b/gcc/testsuite/go.test/test/fixedbugs/bug236.go
index 6c24556..de7e8e3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug236.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug236.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug237.go b/gcc/testsuite/go.test/test/fixedbugs/bug237.go
index 58996ca..75d6132 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug237.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug237.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug243.go b/gcc/testsuite/go.test/test/fixedbugs/bug243.go
index 4870c36..5b6bb75 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug243.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug243.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug245.go b/gcc/testsuite/go.test/test/fixedbugs/bug245.go
index c607a6d..adf62f9 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug245.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug245.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug247.go b/gcc/testsuite/go.test/test/fixedbugs/bug247.go
index b6851e1..6550bd8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug247.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug247.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug1.go b/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug1.go
index 78433f5..f1db77d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug1.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
-package p
+package q
type T struct {
X, Y int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go b/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go
index ba547d6..c0fdecf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go
@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
-package main
+package s
import (
p0 "./bug0"
p1 "./bug1"
-
- "reflect"
- "strings"
)
+// both p0.T and p1.T are struct { X, Y int }.
+
var v0 p0.T
var v1 p1.T
+// interfaces involving the two
+
type I0 interface {
M(p0.T)
}
@@ -23,83 +24,50 @@ type I1 interface {
M(p1.T)
}
+// t0 satisfies I0 and p0.I
type t0 int
func (t0) M(p0.T) {}
+// t1 satisfies I1 and p1.I
type t1 float64
func (t1) M(p1.T) {}
+// check static interface assignments
var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok
+var i2 I0 = t1(0) // ERROR "does not implement|incompatible"
+var i3 I1 = t0(0) // ERROR "does not implement|incompatible"
+
var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok
-func main() {
- // check that reflect paths are correct,
- // meaning that reflect data for v0, v1 didn't get confused.
-
- // path is full (rooted) path name. check suffix for gc, prefix for gccgo
- if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
- println("bad v0 path", len(s), s)
- panic("fail")
- }
- if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
- println("bad v1 path", s)
- panic("fail")
- }
-
- // check that dynamic interface check doesn't get confused
- var i interface{} = t0(0)
- if _, ok := i.(I1); ok {
- println("used t0 as i1")
- panic("fail")
- }
- if _, ok := i.(p1.I); ok {
- println("used t0 as p1.I")
- panic("fail")
- }
-
- i = t1(1)
- if _, ok := i.(I0); ok {
- println("used t1 as i0")
- panic("fail")
- }
- if _, ok := i.(p0.I); ok {
- println("used t1 as p0.I")
- panic("fail")
- }
-
- // check that type switch works.
- // the worry is that if p0.T and p1.T have the same hash,
- // the binary search will handle one of them incorrectly.
- for j := 0; j < 3; j++ {
- switch j {
- case 0:
- i = p0.T{}
- case 1:
- i = p1.T{}
- case 2:
- i = 3.14
- }
- switch i.(type) {
- case p0.T:
- if j != 0 {
- println("type switch p0.T")
- panic("fail")
- }
- case p1.T:
- if j != 1 {
- println("type switch p1.T")
- panic("fail")
- }
- default:
- if j != 2 {
- println("type switch default", j)
- panic("fail")
- }
- }
- }
+var p0i1 p0.I = t1(0) // ERROR "does not implement|incompatible"
+var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible"
+
+func foobar() {
+ // check that cannot assign one to the other,
+ // but can convert.
+ v0 = v1 // ERROR "assign"
+ v1 = v0 // ERROR "assign"
+
+ v0 = p0.T(v1)
+ v1 = p1.T(v0)
+
+ i0 = i1 // ERROR "cannot use|incompatible"
+ i1 = i0 // ERROR "cannot use|incompatible"
+ p0i = i1 // ERROR "cannot use|incompatible"
+ p1i = i0 // ERROR "cannot use|incompatible"
+ i0 = p1i // ERROR "cannot use|incompatible"
+ i1 = p0i // ERROR "cannot use|incompatible"
+ p0i = p1i // ERROR "cannot use|incompatible"
+ p1i = p0i // ERROR "cannot use|incompatible"
+
+ i0 = p0i
+ p0i = i0
+
+ i1 = p1i
+ p1i = i1
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug3.go b/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug3.go
index 4a56c5c..ba547d6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug3.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug3.go
@@ -7,15 +7,14 @@ package main
import (
p0 "./bug0"
p1 "./bug1"
-)
-// both p0.T and p1.T are struct { X, Y int }.
+ "reflect"
+ "strings"
+)
var v0 p0.T
var v1 p1.T
-// interfaces involving the two
-
type I0 interface {
M(p0.T)
}
@@ -24,50 +23,83 @@ type I1 interface {
M(p1.T)
}
-// t0 satisfies I0 and p0.I
type t0 int
func (t0) M(p0.T) {}
-// t1 satisfies I1 and p1.I
type t1 float64
func (t1) M(p1.T) {}
-// check static interface assignments
var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok
-var i2 I0 = t1(0) // ERROR "does not implement|incompatible"
-var i3 I1 = t0(0) // ERROR "does not implement|incompatible"
-
var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok
-var p0i1 p0.I = t1(0) // ERROR "does not implement|incompatible"
-var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible"
-
func main() {
- // check that cannot assign one to the other,
- // but can convert.
- v0 = v1 // ERROR "assign"
- v1 = v0 // ERROR "assign"
-
- v0 = p0.T(v1)
- v1 = p1.T(v0)
-
- i0 = i1 // ERROR "cannot use|incompatible"
- i1 = i0 // ERROR "cannot use|incompatible"
- p0i = i1 // ERROR "cannot use|incompatible"
- p1i = i0 // ERROR "cannot use|incompatible"
- i0 = p1i // ERROR "cannot use|incompatible"
- i1 = p0i // ERROR "cannot use|incompatible"
- p0i = p1i // ERROR "cannot use|incompatible"
- p1i = p0i // ERROR "cannot use|incompatible"
-
- i0 = p0i
- p0i = i0
-
- i1 = p1i
- p1i = i1
+ // check that reflect paths are correct,
+ // meaning that reflect data for v0, v1 didn't get confused.
+
+ // path is full (rooted) path name. check suffix for gc, prefix for gccgo
+ if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
+ println("bad v0 path", len(s), s)
+ panic("fail")
+ }
+ if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
+ println("bad v1 path", s)
+ panic("fail")
+ }
+
+ // check that dynamic interface check doesn't get confused
+ var i interface{} = t0(0)
+ if _, ok := i.(I1); ok {
+ println("used t0 as i1")
+ panic("fail")
+ }
+ if _, ok := i.(p1.I); ok {
+ println("used t0 as p1.I")
+ panic("fail")
+ }
+
+ i = t1(1)
+ if _, ok := i.(I0); ok {
+ println("used t1 as i0")
+ panic("fail")
+ }
+ if _, ok := i.(p0.I); ok {
+ println("used t1 as p0.I")
+ panic("fail")
+ }
+
+ // check that type switch works.
+ // the worry is that if p0.T and p1.T have the same hash,
+ // the binary search will handle one of them incorrectly.
+ for j := 0; j < 3; j++ {
+ switch j {
+ case 0:
+ i = p0.T{}
+ case 1:
+ i = p1.T{}
+ case 2:
+ i = 3.14
+ }
+ switch i.(type) {
+ case p0.T:
+ if j != 0 {
+ println("type switch p0.T")
+ panic("fail")
+ }
+ case p1.T:
+ if j != 1 {
+ println("type switch p1.T")
+ panic("fail")
+ }
+ default:
+ if j != 2 {
+ println("type switch default", j)
+ panic("fail")
+ }
+ }
+ }
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug248.go b/gcc/testsuite/go.test/test/fixedbugs/bug248.go
index 98cda35..93d2fdb 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug248.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug248.go
@@ -1,15 +1,12 @@
-// $G $D/$F.dir/bug0.go &&
-// $G $D/$F.dir/bug1.go &&
-// $G $D/$F.dir/bug2.go &&
-// errchk $G -e $D/$F.dir/bug3.go &&
-// $L bug2.$A &&
-// ./$A.out || echo BUG: failed to compile
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// +build !nacl,!js,!plan9
+// errorcheckandrundir -1
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-ignored
+package ignored
+
+// Compile: bug0.go, bug1.go
+// Compile and errorCheck: bug2.go
+// Link and run: bug3.go
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug249.go b/gcc/testsuite/go.test/test/fixedbugs/bug249.go
index dc92245..ec9699a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug249.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug249.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug250.go b/gcc/testsuite/go.test/test/fixedbugs/bug250.go
index 5140f3e..9fb34c3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug250.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug250.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug251.go b/gcc/testsuite/go.test/test/fixedbugs/bug251.go
index 706bb8d..977aa49 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug251.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug251.go
@@ -8,7 +8,7 @@ package main
type I1 interface { // GC_ERROR "invalid recursive type"
m() I2
- I2 // GCCGO_ERROR "loop|interface"
+ I2
}
type I2 interface {
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug252.go b/gcc/testsuite/go.test/test/fixedbugs/bug252.go
index 6f007fb..f678925 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug252.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug252.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug253.go b/gcc/testsuite/go.test/test/fixedbugs/bug253.go
index f6ab712..933f3f1 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug253.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug253.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug254.go b/gcc/testsuite/go.test/test/fixedbugs/bug254.go
index 9b1c819..3902cd5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug254.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug254.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug255.go b/gcc/testsuite/go.test/test/fixedbugs/bug255.go
index acf4f23..458fb97 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug255.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug255.go
@@ -1,15 +1,20 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
-var a [10]int // ok
-var b [1e1]int // ok
-var c [1.5]int // ERROR "truncated"
-var d ["abc"]int // ERROR "invalid array bound|not numeric"
-var e [nil]int // ERROR "invalid array bound|not numeric"
-var f [e]int // ERROR "invalid array bound|not constant"
-var g [1<<65]int // ERROR "array bound is too large|overflows"
+var a [10]int // ok
+var b [1e1]int // ok
+var c [1.5]int // ERROR "truncated"
+var d ["abc"]int // ERROR "invalid array bound|not numeric"
+var e [nil]int // ERROR "use of untyped nil|invalid array bound|not numeric"
+var f [e]int // ok: error already reported for e
+var g [1 << 65]int // ERROR "array bound is too large|overflows"
+var h [len(a)]int // ok
+
+func ff() string
+
+var i [len([1]string{ff()})]int // ERROR "non-constant array bound|not constant"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug256.go b/gcc/testsuite/go.test/test/fixedbugs/bug256.go
index 0498a40..705a032 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug256.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug256.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug257.go b/gcc/testsuite/go.test/test/fixedbugs/bug257.go
index 003f3ff..b05c37a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug257.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug257.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug258.go b/gcc/testsuite/go.test/test/fixedbugs/bug258.go
index d362e5a..075da87 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug258.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug258.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug259.go b/gcc/testsuite/go.test/test/fixedbugs/bug259.go
index e4dcaeb2f..857b442 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug259.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug259.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug261.go b/gcc/testsuite/go.test/test/fixedbugs/bug261.go
index f7879b0..abe6431 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug261.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug261.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug264.go b/gcc/testsuite/go.test/test/fixedbugs/bug264.go
index fcf373c..2f320def 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug264.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug264.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test case for http://code.google.com/p/go/issues/detail?id=692
+// Test case for https://golang.org/issue/692
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug265.go b/gcc/testsuite/go.test/test/fixedbugs/bug265.go
index 7f06fce..5e05166 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug265.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug265.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test case for http://code.google.com/p/go/issues/detail?id=700
+// Test case for https://golang.org/issue/700
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug266.go b/gcc/testsuite/go.test/test/fixedbugs/bug266.go
index d4da891..5d2334c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug266.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug266.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug269.go b/gcc/testsuite/go.test/test/fixedbugs/bug269.go
index c13eb26..ec0dbc6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug269.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug269.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=749
+// https://golang.org/issue/749
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug271.go b/gcc/testsuite/go.test/test/fixedbugs/bug271.go
index 88add70..a6abbfe 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug271.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug271.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=662
+// https://golang.org/issue/662
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug272.go b/gcc/testsuite/go.test/test/fixedbugs/bug272.go
index c27f7ee..6b8862f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug272.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug272.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=589
+// https://golang.org/issue/589
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug273.go b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
index 7305c60..2af8800 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug273.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
@@ -14,7 +14,7 @@ var bug = false
var minus1 = -1
var five = 5
-var big int64 = 10 | 1<<40
+var big int64 = 10 | 1<<46
type block [1 << 19]byte
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug274.go b/gcc/testsuite/go.test/test/fixedbugs/bug274.go
index beb2d61..e93f30e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug274.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug274.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -13,7 +13,7 @@
// Both gccgo and gofmt correctly refuse this program as is and accept it
// when the semicolons are present.
-// This is a test case for issue 777 ( http://code.google.com/p/go/issues/detail?id=777 ).
+// This is a test case for issue 777 ( https://golang.org/issue/777 ).
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug275.go b/gcc/testsuite/go.test/test/fixedbugs/bug275.go
index f5f6b14..d3be754 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug275.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug275.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug278.go b/gcc/testsuite/go.test/test/fixedbugs/bug278.go
index 68a3d81..4817ebf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug278.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug278.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug279.go b/gcc/testsuite/go.test/test/fixedbugs/bug279.go
index e5ec594..3b1df3b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug279.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug279.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=799
+// https://golang.org/issue/799
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug280.go b/gcc/testsuite/go.test/test/fixedbugs/bug280.go
index ba594a2..afec57f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug280.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug280.go
@@ -1,10 +1,10 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=808
+// https://golang.org/issue/808
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug281.go b/gcc/testsuite/go.test/test/fixedbugs/bug281.go
index 24d6fdc..c65530f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug281.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug281.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=807
+// https://golang.org/issue/807
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p1.go
index b562755..0f7422c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p1.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p2.go
index 3f8bd9d..f614507 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug282.dir/p2.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug283.go b/gcc/testsuite/go.test/test/fixedbugs/bug283.go
index eefed03..ef1953b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug283.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug283.go
@@ -1,10 +1,10 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=806
+// https://golang.org/issue/806
// triggered out of registers on 8g
package bug283
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug285.go b/gcc/testsuite/go.test/test/fixedbugs/bug285.go
index 0a8a0f0..0632ab4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug285.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug285.go
@@ -1,12 +1,12 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test for issue 778: Map key values that are assignment
// compatible with the map key type must be accepted according
-// to the spec: http://golang.org/doc/go_spec.html#Indexes .
+// to the spec: https://golang.org/doc/go_spec.html#Indexes .
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug286.go b/gcc/testsuite/go.test/test/fixedbugs/bug286.go
index 44f0515..b1271f4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug286.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug286.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug287.go b/gcc/testsuite/go.test/test/fixedbugs/bug287.go
index 2ed81c5..94582a8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug287.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug287.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug288.go b/gcc/testsuite/go.test/test/fixedbugs/bug288.go
index d2461e6..0a53d32 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug288.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug288.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug289.go b/gcc/testsuite/go.test/test/fixedbugs/bug289.go
index 3c6b687..3fc7fb2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug289.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug289.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,14 +9,14 @@
package main
func f1() {
- a, b := f() // ERROR "mismatch|does not match"
+ a, b := f() // ERROR "assignment mismatch|does not match"
_ = a
_ = b
}
func f2() {
var a, b int
- a, b = f() // ERROR "mismatch|does not match"
+ a, b = f() // ERROR "assignment mismatch|does not match"
_ = a
_ = b
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug290.go b/gcc/testsuite/go.test/test/fixedbugs/bug290.go
index c8ff0bc..4eee285 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug290.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug290.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=920
+// https://golang.org/issue/920
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug291.go b/gcc/testsuite/go.test/test/fixedbugs/bug291.go
index 17a5483..ac84a7e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug291.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug291.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=915
+// https://golang.org/issue/915
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug292.go b/gcc/testsuite/go.test/test/fixedbugs/bug292.go
index 07051dd..1130a28 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug292.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug292.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=843
+// https://golang.org/issue/843
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug293.go b/gcc/testsuite/go.test/test/fixedbugs/bug293.go
index bf926f5..ae7cc1f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug293.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug293.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=846
+// https://golang.org/issue/846
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug294.go b/gcc/testsuite/go.test/test/fixedbugs/bug294.go
index 0f3e380..b35b771 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug294.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug294.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=800
+// https://golang.org/issue/800
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug295.go b/gcc/testsuite/go.test/test/fixedbugs/bug295.go
index 63a12a3..d1c961c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug295.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug295.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug296.go b/gcc/testsuite/go.test/test/fixedbugs/bug296.go
index a7c4e0c..2ef4e66 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug296.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug296.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug297.go b/gcc/testsuite/go.test/test/fixedbugs/bug297.go
index ee2ff92..c2bd253 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug297.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug297.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -11,5 +11,5 @@ package main
type ByteSize float64
const (
_ = iota; // ignore first value by assigning to blank identifier
- KB ByteSize = 1<<(10*X) // ERROR "undefined" "is not a constant|as type ByteSize"
+ KB ByteSize = 1<<(10*X) // ERROR "undefined"
)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug298.go b/gcc/testsuite/go.test/test/fixedbugs/bug298.go
index bd362ac..0aed032 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug298.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug298.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug299.go b/gcc/testsuite/go.test/test/fixedbugs/bug299.go
index 1067fd1..cf11bcc 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug299.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug299.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug300.go b/gcc/testsuite/go.test/test/fixedbugs/bug300.go
index 1ef43a0..1695a96 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug300.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug300.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug301.go b/gcc/testsuite/go.test/test/fixedbugs/bug301.go
index 572668f..2be62b8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug301.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug301.go
@@ -1,10 +1,10 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=990
+// https://golang.org/issue/990
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/main.go
index 9f874d0..52c054f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/main.go
@@ -1,12 +1,12 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
// Check that the export information is correct in p.6.
-import _ "./p"
+import _ "p"
// Check that it's still correct in pp.a (which contains p.6).
-import _ "./pp"
+import _ "pp"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/p.go b/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/p.go
index 7c54b90..0be521b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/p.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug302.dir/p.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug302.go b/gcc/testsuite/go.test/test/fixedbugs/bug302.go
index dc7637f..a2ab661 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug302.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug302.go
@@ -1,9 +1,45 @@
-// $G $D/bug302.dir/p.go && pack grc pp.a p.$A && $G $D/bug302.dir/main.go
+// +build !nacl,!js,gc
+// run
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+var tmpDir string
+
+func main() {
+ fb, err := filepath.Abs("fixedbugs")
+ if err == nil {
+ tmpDir, err = ioutil.TempDir("", "bug302")
+ }
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ run("go", "tool", "compile", filepath.Join(fb, "bug302.dir", "p.go"))
+ run("go", "tool", "pack", "grc", "pp.a", "p.o")
+ run("go", "tool", "compile", "-I", ".", filepath.Join(fb, "bug302.dir", "main.go"))
+}
+
+func run(cmd string, args ...string) {
+ c := exec.Command(cmd, args...)
+ c.Dir = tmpDir
+ out, err := c.CombinedOutput()
+ if err != nil {
+ fmt.Println(string(out))
+ fmt.Println(err)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug303.go b/gcc/testsuite/go.test/test/fixedbugs/bug303.go
index 94ca07e..aef8b22 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug303.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug303.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug304.go b/gcc/testsuite/go.test/test/fixedbugs/bug304.go
index ad71b20..4073073 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug304.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug304.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug305.go b/gcc/testsuite/go.test/test/fixedbugs/bug305.go
index d0a4b24..0c34b1a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug305.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug305.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p1.go
index bf87ea1..b285518 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p1.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p2.go
index 3f8bd9d..f614507 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug306.dir/p2.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug308.go b/gcc/testsuite/go.test/test/fixedbugs/bug308.go
index 5bea517..a23903c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug308.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug308.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug309.go b/gcc/testsuite/go.test/test/fixedbugs/bug309.go
index 948ca5c..d707aa3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug309.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug309.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug311.go b/gcc/testsuite/go.test/test/fixedbugs/bug311.go
index edcd975..f5cab44 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug311.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug311.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug312.go b/gcc/testsuite/go.test/test/fixedbugs/bug312.go
index c7c17e1..af423e5b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug312.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug312.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/a.go
index cb4ca72..335f84d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/b.go
index 7eda72b..26e6413 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug313.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug313.go b/gcc/testsuite/go.test/test/fixedbugs/bug313.go
index a7c1d36..f7e0238 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug313.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug313.go
@@ -1,6 +1,6 @@
// errorcheckdir
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug317.go b/gcc/testsuite/go.test/test/fixedbugs/bug317.go
index 3ff4dc4..4cd9ec28 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug317.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug317.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug319.go b/gcc/testsuite/go.test/test/fixedbugs/bug319.go
index f8e959a..b93106d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug319.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug319.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug320.go b/gcc/testsuite/go.test/test/fixedbugs/bug320.go
index c2dd31b..0406b96 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug320.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug320.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug321.go b/gcc/testsuite/go.test/test/fixedbugs/bug321.go
index 7d01827..19970af 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug321.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug321.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug323.go b/gcc/testsuite/go.test/test/fixedbugs/bug323.go
index 9730ae5..3cb8eaa 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug323.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug323.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug325.go b/gcc/testsuite/go.test/test/fixedbugs/bug325.go
index 6ccd0e3..e6528ae 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug325.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug325.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug326.go b/gcc/testsuite/go.test/test/fixedbugs/bug326.go
index 57f6471..75d620c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug326.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug326.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug327.go b/gcc/testsuite/go.test/test/fixedbugs/bug327.go
index 0598d95..ecb5d22 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug327.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug327.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug328.go b/gcc/testsuite/go.test/test/fixedbugs/bug328.go
index 73ab46d..57043f3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug328.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug328.go
@@ -1,6 +1,6 @@
-// cmpout
+// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug329.go b/gcc/testsuite/go.test/test/fixedbugs/bug329.go
index 74fc781..37c93d0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug329.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug329.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug330.go b/gcc/testsuite/go.test/test/fixedbugs/bug330.go
index ef6a077..2f33feb 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug330.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug330.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug331.go b/gcc/testsuite/go.test/test/fixedbugs/bug331.go
index fac0e36..9eb57cd 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug331.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug331.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug332.go b/gcc/testsuite/go.test/test/fixedbugs/bug332.go
index 702779b..159c8b4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug332.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug332.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -13,5 +13,5 @@ func main() {}
// issue 1474
// important: no newline on end of next line.
-// 6g used to print <epoch> instead of bug332.go:111
-func (t *T) F() {} // ERROR "bug332" \ No newline at end of file
+// 6g used to print <epoch> instead of bug332.go:111
+func (t *T) F() {} // ERROR "undefined.*T" \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug333.go b/gcc/testsuite/go.test/test/fixedbugs/bug333.go
index bb690f0..149843a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug333.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug333.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug334.go b/gcc/testsuite/go.test/test/fixedbugs/bug334.go
index bd671696..9558c06 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug334.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug334.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/a.go
index 256c110..6ecc5c4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/b.go
index 1474470..a7735a8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug335.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug335.go b/gcc/testsuite/go.test/test/fixedbugs/bug335.go
index 37c97d7..fda9eb8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug335.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug335.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug336.go b/gcc/testsuite/go.test/test/fixedbugs/bug336.go
index fbf2320..fbcd3a5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug336.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug336.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug337.go b/gcc/testsuite/go.test/test/fixedbugs/bug337.go
index 38dc665..1a0616f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug337.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug337.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug338.go b/gcc/testsuite/go.test/test/fixedbugs/bug338.go
index c2193fc..a4537a4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug338.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug338.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug339.go b/gcc/testsuite/go.test/test/fixedbugs/bug339.go
index 59921d4..36be761 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug339.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug339.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug340.go b/gcc/testsuite/go.test/test/fixedbugs/bug340.go
index d996ab6..8c543c9 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug340.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug340.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,6 +12,6 @@ func main() {
var x interface{}
switch t := x.(type) {
case 0: // ERROR "type"
- t.x = 1 // ERROR "type interface \{\}|reference to undefined field or method"
+ t.x = 1 // ERROR "type interface \{\}|reference to undefined field or method|interface with no methods"
}
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug341.go b/gcc/testsuite/go.test/test/fixedbugs/bug341.go
index db1af3e..baab282 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug341.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug341.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug342.go b/gcc/testsuite/go.test/test/fixedbugs/bug342.go
index ffcb668..f90f6f3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug342.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug342.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug343.go b/gcc/testsuite/go.test/test/fixedbugs/bug343.go
index 8220108..fd8bd76 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug343.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug343.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug344.go b/gcc/testsuite/go.test/test/fixedbugs/bug344.go
index 4a92624..b53abd2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug344.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug344.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/io.go b/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/io.go
index 1d695c3..ca7a509 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/io.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/io.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/main.go
index ddba8da..b77a2fa 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug345.dir/main.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -6,8 +6,9 @@ package main
import (
"bufio"
- "./io"
goio "io"
+
+ "./io"
)
func main() {
@@ -22,7 +23,7 @@ func main() {
// main.go:27: cannot use &x (type *"io".SectionReader) as type *"/Users/rsc/g/go/test/fixedbugs/bug345.dir/io".SectionReader in function argument
var w io.Writer
- bufio.NewWriter(w) // ERROR "test/io|has incompatible type"
+ bufio.NewWriter(w) // ERROR "[\w.]+[^.]/io|has incompatible type"
var x goio.SectionReader
- io.SR(&x) // ERROR "test/io|has incompatible type"
+ io.SR(&x) // ERROR "[\w.]+[^.]/io|has incompatible type"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug345.go b/gcc/testsuite/go.test/test/fixedbugs/bug345.go
index e3705f6..b974a61 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug345.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug345.go
@@ -1,10 +1,10 @@
-// $G $D/$F.dir/io.go && errchk $G -e $D/$F.dir/main.go
+// +build !windows
+// errorcheckdir -n
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored
+
+// TODO(ysmolsky): Fix golang.org/issue/25693 to enable on Windows.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug346.go b/gcc/testsuite/go.test/test/fixedbugs/bug346.go
index d9203aa..f69b58d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug346.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug346.go
@@ -9,11 +9,28 @@ package main
import "os"
func main() {
- x := 4
- a, b, c, d := func(i int) (p int, q int, r int, s int) { return 1, i, 3, x }(2)
+ // Test unclosed closure.
+ {
+ x := 4
+ a, b, c, d := func(i int) (p int, q int, r int, s int) { return 1, i, 3, x }(2)
- if a != 1 || b != 2 || c != 3 || d != 4 {
- println("abcd: expected 1 2 3 4 got", a, b, c, d)
- os.Exit(1)
+ if a != 1 || b != 2 || c != 3 || d != 4 {
+ println("1# abcd: expected 1 2 3 4 got", a, b, c, d)
+ os.Exit(1)
+ }
+ }
+ // Test real closure.
+ {
+ x := 4
+ gf = func(i int) (p int, q int, r int, s int) { return 1, i, 3, x }
+
+ a, b, c, d := gf(2)
+
+ if a != 1 || b != 2 || c != 3 || d != 4 {
+ println("2# abcd: expected 1 2 3 4 got", a, b, c, d)
+ os.Exit(1)
+ }
}
}
+
+var gf func(int) (int, int, int, int)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug347.go b/gcc/testsuite/go.test/test/fixedbugs/bug347.go
index 08edf0f..92afb2e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug347.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug347.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug348.go b/gcc/testsuite/go.test/test/fixedbugs/bug348.go
index 54a289a..c7f1346 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug348.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug348.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug349.go b/gcc/testsuite/go.test/test/fixedbugs/bug349.go
index a3e6bd1..a6e8386 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug349.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug349.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug350.go b/gcc/testsuite/go.test/test/fixedbugs/bug350.go
index 5ce8996..cdce1cf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug350.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug350.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug351.go b/gcc/testsuite/go.test/test/fixedbugs/bug351.go
index 4c5c7c3..8fd63e3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug351.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug351.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug352.go b/gcc/testsuite/go.test/test/fixedbugs/bug352.go
index 1ae2d61..464ad7b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug352.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug352.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug353.go b/gcc/testsuite/go.test/test/fixedbugs/bug353.go
index 2a532c4..4a65f77 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug353.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug353.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug354.go b/gcc/testsuite/go.test/test/fixedbugs/bug354.go
index 1245d91..293180f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug354.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug354.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug355.go b/gcc/testsuite/go.test/test/fixedbugs/bug355.go
index fcf859b..880353a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug355.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug355.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug356.go b/gcc/testsuite/go.test/test/fixedbugs/bug356.go
index 273c5b8..6d93860 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug356.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug356.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug357.go b/gcc/testsuite/go.test/test/fixedbugs/bug357.go
index ceb2009..e9db50e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug357.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug357.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug358.go b/gcc/testsuite/go.test/test/fixedbugs/bug358.go
index 063c2e0..5ca0be1 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug358.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug358.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,13 +10,14 @@
package main
import (
- "io/ioutil" // GCCGO_ERROR "imported and not used"
+ // avoid imported and not used errors
+ // "io/ioutil"
"net/http"
- "os" // GCCGO_ERROR "imported and not used"
+ // "os"
)
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) // ERROR "syntax error|invalid use of type"
+ return func(w http.ResponseWriter, r *http.Request) // ERROR "syntax error|not an expression|invalid use of type"
}
type Page struct {
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug361.go b/gcc/testsuite/go.test/test/fixedbugs/bug361.go
index 3e3b7c1..8e28243 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug361.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug361.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug362.go b/gcc/testsuite/go.test/test/fixedbugs/bug362.go
index b888ccb..771d13d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug362.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug362.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug363.go b/gcc/testsuite/go.test/test/fixedbugs/bug363.go
index 615c668..1bd14009 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug363.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug363.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug365.go b/gcc/testsuite/go.test/test/fixedbugs/bug365.go
index 795323b..985b6de 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug365.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug365.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug366.go b/gcc/testsuite/go.test/test/fixedbugs/bug366.go
index 33a1a5a..3af5bea 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug366.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug366.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug368.go b/gcc/testsuite/go.test/test/fixedbugs/bug368.go
index c38cc7f..353ea5a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug368.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug368.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/main.go
new file mode 100644
index 0000000..03b53a5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/main.go
@@ -0,0 +1,55 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "os"
+ "runtime"
+ "testing"
+
+ fast "./fast"
+ slow "./slow"
+)
+
+var buf = make([]byte, 1048576)
+
+func BenchmarkFastNonASCII(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ fast.NonASCII(buf, 0)
+ }
+}
+
+func BenchmarkSlowNonASCII(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ slow.NonASCII(buf, 0)
+ }
+}
+
+func main() {
+ testing.Init()
+ os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
+ flag.Parse()
+
+ rslow := testing.Benchmark(BenchmarkSlowNonASCII)
+ rfast := testing.Benchmark(BenchmarkFastNonASCII)
+ tslow := rslow.NsPerOp()
+ tfast := rfast.NsPerOp()
+
+ // Optimization should be good for at least 2x, but be forgiving.
+ // On the ARM simulator we see closer to 1.5x.
+ speedup := float64(tslow) / float64(tfast)
+ want := 1.8
+ if runtime.GOARCH == "arm" {
+ want = 1.3
+ }
+ if speedup < want {
+ // TODO(rsc): doesn't work on linux-amd64 or darwin-amd64 builders, nor on
+ // a Lenovo x200 (linux-amd64) laptop.
+ // println("fast:", tfast, "slow:", tslow, "speedup:", speedup, "want:", want)
+ // println("not fast enough")
+ // os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/pkg.go b/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/pkg.go
index cf57041..9964347 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/pkg.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug369.dir/pkg.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug369.go b/gcc/testsuite/go.test/test/fixedbugs/bug369.go
index 7c9583a..83f638d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug369.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug369.go
@@ -1,11 +1,7 @@
-// $G -N -o slow.$A $D/bug369.dir/pkg.go &&
-// $G -o fast.$A $D/bug369.dir/pkg.go &&
+// +build !nacl,!js,!windows,gc
// run
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -14,50 +10,45 @@
package main
import (
- "flag"
+ "fmt"
+ "io/ioutil"
"os"
- "runtime"
- "testing"
-
- fast "./fast"
- slow "./slow"
+ "os/exec"
+ "path/filepath"
)
-var buf = make([]byte, 1048576)
+func main() {
+ err := os.Chdir(filepath.Join(".", "fixedbugs", "bug369.dir"))
+ check(err)
+
+ tmpDir, err := ioutil.TempDir("", "bug369")
+ check(err)
+ defer os.RemoveAll(tmpDir)
-func BenchmarkFastNonASCII(b *testing.B) {
- for i := 0; i < b.N; i++ {
- fast.NonASCII(buf, 0)
+ tmp := func(name string) string {
+ return filepath.Join(tmpDir, name)
}
+
+ run("go", "tool", "compile", "-N", "-o", tmp("slow.o"), "pkg.go")
+ run("go", "tool", "compile", "-o", tmp("fast.o"), "pkg.go")
+ run("go", "tool", "compile", "-D", tmpDir, "-o", tmp("main.o"), "main.go")
+ run("go", "tool", "link", "-o", tmp("a.exe"), tmp("main.o"))
+ run(tmp("a.exe"))
}
-func BenchmarkSlowNonASCII(b *testing.B) {
- for i := 0; i < b.N; i++ {
- slow.NonASCII(buf, 0)
+func run(name string, args ...string) {
+ cmd := exec.Command(name, args...)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Println(string(out))
+ fmt.Println(err)
+ os.Exit(1)
}
}
-func main() {
- testing.Init()
- os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
- flag.Parse()
-
- rslow := testing.Benchmark(BenchmarkSlowNonASCII)
- rfast := testing.Benchmark(BenchmarkFastNonASCII)
- tslow := rslow.NsPerOp()
- tfast := rfast.NsPerOp()
-
- // Optimization should be good for at least 2x, but be forgiving.
- // On the ARM simulator we see closer to 1.5x.
- speedup := float64(tslow)/float64(tfast)
- want := 1.8
- if runtime.GOARCH == "arm" {
- want = 1.3
- }
- if speedup < want {
- // TODO(rsc): doesn't work on linux-amd64 or darwin-amd64 builders, nor on
- // a Lenovo x200 (linux-amd64) laptop.
- //println("fast:", tfast, "slow:", tslow, "speedup:", speedup, "want:", want)
- //println("not fast enough")
+func check(err error) {
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
}
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug370.go b/gcc/testsuite/go.test/test/fixedbugs/bug370.go
index 246bc7c..c5165c5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug370.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug370.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug371.go b/gcc/testsuite/go.test/test/fixedbugs/bug371.go
index 86c73bf..3a626e5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug371.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug371.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug372.go b/gcc/testsuite/go.test/test/fixedbugs/bug372.go
index 3457856..5fba131d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug372.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug372.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug373.go b/gcc/testsuite/go.test/test/fixedbugs/bug373.go
index e91f26d..6b7a312 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug373.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug373.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,7 +9,7 @@
package foo
func f(x interface{}) {
- switch t := x.(type) { // ERROR "declared and not used"
+ switch t := x.(type) { // ERROR "declared but not used"
case int:
}
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug374.go b/gcc/testsuite/go.test/test/fixedbugs/bug374.go
index 4f0b721..2d604cb 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug374.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug374.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug375.go b/gcc/testsuite/go.test/test/fixedbugs/bug375.go
index cb159b0..08d5afc 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug375.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug375.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug376.go b/gcc/testsuite/go.test/test/fixedbugs/bug376.go
index 5fbbc9c..cd70012 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug376.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug376.go
@@ -1,11 +1,10 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// issue 1951
package foo
import "unsafe"
-var v = unsafe.Sizeof // ERROR "must be called"
-
+var v = unsafe.Sizeof // ERROR "not in function call|must be called"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug378.go b/gcc/testsuite/go.test/test/fixedbugs/bug378.go
index f3346c6..c7b0dac 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug378.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug378.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug379.go b/gcc/testsuite/go.test/test/fixedbugs/bug379.go
index 14abe46..5638123 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug379.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug379.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug380.go b/gcc/testsuite/go.test/test/fixedbugs/bug380.go
index 96e1ede..0cb3487 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug380.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug380.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug381.go b/gcc/testsuite/go.test/test/fixedbugs/bug381.go
index 0253e14..a0a1c8a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug381.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug381.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/pkg.go b/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/pkg.go
index f8d75d4..92fe4e3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/pkg.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/pkg.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug383.go b/gcc/testsuite/go.test/test/fixedbugs/bug383.go
index 503779c..dc2ecd6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug383.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug383.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug384.go b/gcc/testsuite/go.test/test/fixedbugs/bug384.go
index 0233c19..d02352b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug384.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug384.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go b/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go
index 4c3cad7..73a1311 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go
@@ -1,7 +1,7 @@
-// +build 386 arm
+// +build 386 amd64p32 arm
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go b/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go
index 6789c0a..0f941ca 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go
@@ -1,7 +1,7 @@
// +build amd64
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug386.go b/gcc/testsuite/go.test/test/fixedbugs/bug386.go
index ec358bd..889c8b0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug386.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug386.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug387.go b/gcc/testsuite/go.test/test/fixedbugs/bug387.go
index 59d5ef9..d885445 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug387.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug387.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug388.go b/gcc/testsuite/go.test/test/fixedbugs/bug388.go
index d41f9ea..2d50850 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug388.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug388.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,12 +9,12 @@
package main
import "runtime"
-func foo(runtime.UintType, i int) { // ERROR "cannot declare name runtime.UintType|named/anonymous mix|undefined identifier"
+func foo(runtime.UintType, i int) { // ERROR "cannot declare name runtime.UintType|mixed named and unnamed|undefined identifier"
println(i, runtime.UintType) // GCCGO_ERROR "undefined identifier"
}
func bar(i int) {
- runtime.UintType := i // ERROR "cannot declare name runtime.UintType|non-name on left side|undefined identifier"
+ runtime.UintType := i // ERROR "non-name runtime.UintType|non-name on left side|undefined identifier"
println(runtime.UintType) // GCCGO_ERROR "invalid use of type|undefined identifier"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug389.go b/gcc/testsuite/go.test/test/fixedbugs/bug389.go
index 55a02e0..14804c8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug389.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug389.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug391.go b/gcc/testsuite/go.test/test/fixedbugs/bug391.go
index 07d129d..9211b1c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug391.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug391.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/one.go
index 8242f28..aba8649 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/one.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg2.go b/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg2.go
index 8320b2f..2ee41f0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg3.go b/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg3.go
index 402c3b0..1403798 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg3.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug392.dir/pkg3.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug393.go b/gcc/testsuite/go.test/test/fixedbugs/bug393.go
index f8a9c65..61af578 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug393.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug393.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug394.go b/gcc/testsuite/go.test/test/fixedbugs/bug394.go
index 2d77156..08bac18 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug394.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug394.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/one.go
index 96a1dd7..66eba63f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/one.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/two.go b/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/two.go
index 9b32508..9152bec 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/two.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug396.dir/two.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug397.go b/gcc/testsuite/go.test/test/fixedbugs/bug397.go
index 56cc7cd..6188e3e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug397.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug397.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug398.go b/gcc/testsuite/go.test/test/fixedbugs/bug398.go
index 1dd3fa4..a1583bd 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug398.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug398.go
@@ -1,23 +1,43 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Used to crash compiler in interface type equality check.
+// (This test used to have problems - see #15596.)
package p
+// exported interfaces
+
type I1 interface {
F() interface{I1}
}
type I2 interface {
F() interface{I2}
-}
+}
+
+var V1 I1
+var V2 I2
+
+func F() bool {
+ return V1 == V2
+}
+
+// non-exported interfaces
+
+type i1 interface {
+ F() interface{i1}
+}
+
+type i2 interface {
+ F() interface{i2}
+}
-var v1 I1
-var v2 I2
+var v1 i1
+var v2 i2
func f() bool {
return v1 == v2
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug399.go b/gcc/testsuite/go.test/test/fixedbugs/bug399.go
index 94852c9..e460d81 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug399.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug399.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug401.go b/gcc/testsuite/go.test/test/fixedbugs/bug401.go
index 5589b5b..215498e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug401.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug401.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,9 +9,8 @@ package main
type T struct{}
+//go:noinline
func (T) cplx() complex128 {
- for false {
- } // avoid inlining
return complex(1, 0)
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug402.go b/gcc/testsuite/go.test/test/fixedbugs/bug402.go
index db3f3da..f9f554d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug402.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug402.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug403.go b/gcc/testsuite/go.test/test/fixedbugs/bug403.go
index ed7b49a..aa3c1ea 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug403.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug403.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/one.go
index 2024eb0..9fc4770 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/one.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/two.go b/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/two.go
index 162eae7..0c70a23 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/two.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug404.dir/two.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug406.go b/gcc/testsuite/go.test/test/fixedbugs/bug406.go
index c6f8534..32cf3e3 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug406.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug406.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -14,6 +14,8 @@ type matrix struct {
func (a matrix) equal() bool {
for _ = range a.e {
}
+ for range a.e {
+ }
return true
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/one.go
index a91d904..c85b077 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/one.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/two.go b/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/two.go
index 67e1852..640305c6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/two.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug407.dir/two.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug409.go b/gcc/testsuite/go.test/test/fixedbugs/bug409.go
index 1dca43b..e854636 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug409.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug409.go
@@ -1,6 +1,6 @@
-// cmpout
+// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug410.go b/gcc/testsuite/go.test/test/fixedbugs/bug410.go
index 430ddcb..a4eef64 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug410.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug410.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug411.go b/gcc/testsuite/go.test/test/fixedbugs/bug411.go
index 3b90db8..a1c36f6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug411.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug411.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug412.go b/gcc/testsuite/go.test/test/fixedbugs/bug412.go
index c7ddc0c..183fb7e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug412.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug412.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug413.go b/gcc/testsuite/go.test/test/fixedbugs/bug413.go
index ba80464..819bd1a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug413.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug413.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go
index 2463834..143e600 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go
index f55d946..8945d65 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.go
index 35e19be..5b435b4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug414.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug414.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/p.go b/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/p.go
index b4152d6..e86a697 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/p.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/p.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/prog.go
index b894453..1ffde18 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/prog.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug415.dir/prog.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug415.go b/gcc/testsuite/go.test/test/fixedbugs/bug415.go
index 8cd4c49..daf4f0c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug415.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug415.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug416.go b/gcc/testsuite/go.test/test/fixedbugs/bug416.go
index 1d24fa9..9fc3532 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug416.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug416.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/lib.go b/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/lib.go
index 97054da..31df8c6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/lib.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/lib.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go
index c2fe146..28b41e6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug424.go b/gcc/testsuite/go.test/test/fixedbugs/bug424.go
index 59c2cd3..9c59abe 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug424.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug424.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug425.go b/gcc/testsuite/go.test/test/fixedbugs/bug425.go
index 5546bd9..c3035f6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug425.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug425.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=3119
+// https://golang.org/issue/3119
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug427.go b/gcc/testsuite/go.test/test/fixedbugs/bug427.go
index 1239e7a..c13bb81 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug427.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug427.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// http://code.google.com/p/go/issues/detail?id=3351
+// https://golang.org/issue/3351
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug428.go b/gcc/testsuite/go.test/test/fixedbugs/bug428.go
index 298c455..d9ad276 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug428.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug428.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug429.go b/gcc/testsuite/go.test/test/fixedbugs/bug429.go
index 794d293..2c31f32 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug429.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug429.go
@@ -1,13 +1,11 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out || echo BUG: bug429
+// skip
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Should print deadlock message, not hang.
+// This test is run by bug429_run.go.
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug435.go b/gcc/testsuite/go.test/test/fixedbugs/bug435.go
index 45323d8..692a492 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug435.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug435.go
@@ -1,13 +1,13 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that a syntax error caused by an unexpected EOF
// gives an error message with the correct line number.
//
-// https://code.google.com/p/go/issues/detail?id=3392
+// https://golang.org/issue/3392
package main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/one.go
index 8d3caad..633573e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/one.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/two.go b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/two.go
index 406dd59..61da121 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/two.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/two.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go
index 364d017..585b480 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug437.go b/gcc/testsuite/go.test/test/fixedbugs/bug437.go
index 5c4a2ad..98adce7 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug437.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug437.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug441.go b/gcc/testsuite/go.test/test/fixedbugs/bug441.go
index 8562bfe..b67125b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug441.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug441.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug442.go b/gcc/testsuite/go.test/test/fixedbugs/bug442.go
index 1d1a948..684d54f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug442.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug442.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug443.go b/gcc/testsuite/go.test/test/fixedbugs/bug443.go
index b67bd8c..9abd254 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug443.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug443.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug444.go b/gcc/testsuite/go.test/test/fixedbugs/bug444.go
index b54fb4f5..29a60f5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug444.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug444.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug445.go b/gcc/testsuite/go.test/test/fixedbugs/bug445.go
index 497ecd3..45c3290 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug445.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug445.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug447.go b/gcc/testsuite/go.test/test/fixedbugs/bug447.go
index a4c871b..8358f00 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug447.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug447.go
@@ -1,6 +1,6 @@
// runoutput
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg1.go b/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg1.go
index 032e5d9..291903c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg1.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg2.go b/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg2.go
index 5c78c7d..20d8509 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug448.dir/pkg2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug448.go b/gcc/testsuite/go.test/test/fixedbugs/bug448.go
index 242f599..481acda 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug448.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug448.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug450.go b/gcc/testsuite/go.test/test/fixedbugs/bug450.go
index 3f13de1..af27b72 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug450.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug450.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug452.go b/gcc/testsuite/go.test/test/fixedbugs/bug452.go
index d2e4a0b..f1f8b08 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug452.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug452.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug453.go b/gcc/testsuite/go.test/test/fixedbugs/bug453.go
index 136abef..1f4f3ea 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug453.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug453.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug454.go b/gcc/testsuite/go.test/test/fixedbugs/bug454.go
index a10abba..9e3344d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug454.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug454.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug455.go b/gcc/testsuite/go.test/test/fixedbugs/bug455.go
index 8e3c770..9f6974d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug455.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug455.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug456.go b/gcc/testsuite/go.test/test/fixedbugs/bug456.go
index 064e1aa..c77a76d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug456.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug456.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug457.go b/gcc/testsuite/go.test/test/fixedbugs/bug457.go
index ee70489..84f8db4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug457.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug457.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug458.go b/gcc/testsuite/go.test/test/fixedbugs/bug458.go
index ddc97bd..6332697 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug458.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug458.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug459.go b/gcc/testsuite/go.test/test/fixedbugs/bug459.go
index 014f2ef..c71cb1b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug459.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug459.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go
index 29049d9..51c6836 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go
index 5c0a0c4..ef64694 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug460.go b/gcc/testsuite/go.test/test/fixedbugs/bug460.go
index 79234a3..a1b6f47 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug460.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug460.go
@@ -1,6 +1,6 @@
// errorcheckdir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug461.go b/gcc/testsuite/go.test/test/fixedbugs/bug461.go
index f0f7b0e..d7fe802 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug461.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug461.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug462.go b/gcc/testsuite/go.test/test/fixedbugs/bug462.go
index 1a23ad0..3df63b0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug462.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug462.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug463.go b/gcc/testsuite/go.test/test/fixedbugs/bug463.go
index 3e7a184..c7f9237 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug463.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug463.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug464.go b/gcc/testsuite/go.test/test/fixedbugs/bug464.go
index 5821939..3e2c18a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug464.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug464.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go
index a9a8614..3e5d012 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go
index c84c683..db7f731 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug465.go b/gcc/testsuite/go.test/test/fixedbugs/bug465.go
index a6ef587..84ff07b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug465.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug465.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go
index b9de63e..e27699c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go
index 82d66ea..04e3626 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug466.go b/gcc/testsuite/go.test/test/fixedbugs/bug466.go
index 6b65b33..dc909d4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug466.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug466.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug467.go b/gcc/testsuite/go.test/test/fixedbugs/bug467.go
index d73adba..4126f92 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug467.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug467.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go
index ca17577..cdda735 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go
index 1793c0e..dbb4693 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug468.go b/gcc/testsuite/go.test/test/fixedbugs/bug468.go
index 12e4997..77941ce 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug468.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug468.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug470.go b/gcc/testsuite/go.test/test/fixedbugs/bug470.go
index 0a35918..c21663f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug470.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug470.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug471.go b/gcc/testsuite/go.test/test/fixedbugs/bug471.go
index e454259..343661f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug471.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug471.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go
index 9d47fd8..cda1aa7 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go
index 34a3f04..581ec40 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go
index 6c29dd0..eb791bf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.go
index c79c64c..6939e64 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug472.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug473.go b/gcc/testsuite/go.test/test/fixedbugs/bug473.go
index 49ce7d7..7649b6b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug473.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug473.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug474.go b/gcc/testsuite/go.test/test/fixedbugs/bug474.go
index b826487..1efabe4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug474.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug474.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug475.go b/gcc/testsuite/go.test/test/fixedbugs/bug475.go
index 1bd6fa3..0145aab 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug475.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug475.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug476.go b/gcc/testsuite/go.test/test/fixedbugs/bug476.go
index 4ea2174..8695f95 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug476.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug476.go
@@ -1,11 +1,11 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Logical operation on named boolean type returns the same type,
-// supporting an implicit convertion to an interface type. This used
+// supporting an implicit conversion to an interface type. This used
// to crash gccgo.
package p
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug477.go b/gcc/testsuite/go.test/test/fixedbugs/bug477.go
index 86289af..f1fbffa 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug477.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug477.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/a.go
index a40e454..b5a2dbc 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/b.go
index c0fdf11..cfd1d27 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug478.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug478.go b/gcc/testsuite/go.test/test/fixedbugs/bug478.go
index 5e339e8..8757f46 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug478.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug478.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/a.go
index 5ff3bef..eddb4cf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/b.go
index a1b27b3..9f3f5e8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug479.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug479.go b/gcc/testsuite/go.test/test/fixedbugs/bug479.go
index f8a0f93..80012ba 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug479.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug479.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/a.go
index 6dff515..26a8d11 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/b.go
index 6207365..5bd40f6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug480.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug480.go b/gcc/testsuite/go.test/test/fixedbugs/bug480.go
index 5b44af4..ad2f73c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug480.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug480.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug481.go b/gcc/testsuite/go.test/test/fixedbugs/bug481.go
index d0922a5..13a5339 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug481.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug481.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug482.go b/gcc/testsuite/go.test/test/fixedbugs/bug482.go
index 10c4828..0e5417d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug482.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug482.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug483.go b/gcc/testsuite/go.test/test/fixedbugs/bug483.go
new file mode 100644
index 0000000..8db6425
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug483.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test for a garbage collection bug involving not
+// marking x as having its address taken by &x[0]
+// when x is an array value.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "runtime"
+)
+
+func main() {
+ var x = [4]struct{ x, y interface{} }{
+ {"a", "b"},
+ {"c", "d"},
+ {"e", "f"},
+ {"g", "h"},
+ }
+
+ var buf bytes.Buffer
+ for _, z := range x {
+ runtime.GC()
+ fmt.Fprintf(&buf, "%s %s ", z.x.(string), z.y.(string))
+ }
+
+ if buf.String() != "a b c d e f g h " {
+ println("BUG wrong output\n", buf.String())
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug484.go b/gcc/testsuite/go.test/test/fixedbugs/bug484.go
new file mode 100644
index 0000000..bd4fa51
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug484.go
@@ -0,0 +1,78 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The liveness code used to say that, in func g, s was live
+// starting at its declaration, because it appears to have its
+// address taken by the closure (different s, but the parser
+// gets slightly confused, a separate bug). The liveness analysis
+// saw s as having its address taken but the register optimizer
+// did not. This mismatch meant that s would be marked live
+// (and therefore initialized) at the call to f, but the register optimizer
+// would optimize away the initialization of s before f, causing the
+// garbage collector to use unused data.
+// The register optimizer has been changed to respect the
+// same "address taken" flag that the liveness analysis uses,
+// even if it cannot see any address being taken in the actual
+// machine code. This is conservative but keeps the two consistent,
+// which is the most important thing.
+
+package main
+
+import "runtime"
+
+//go:noinline
+func f() interface{} {
+ runtime.GC()
+ return nil
+}
+
+//go:noinline
+func g() {
+ var s interface{}
+ _ = func() {
+ s := f()
+ _ = s
+ }
+ s = f()
+ useiface(s)
+ useiface(s)
+}
+
+//go:noinline
+func useiface(x interface{}) {
+}
+
+//go:noinline
+func h() {
+ var x [16]uintptr
+ for i := range x {
+ x[i] = 1
+ }
+
+ useint(x[0])
+ useint(x[1])
+ useint(x[2])
+ useint(x[3])
+}
+
+//go:noinline
+func useint(x uintptr) {
+}
+
+func main() {
+ // scribble non-zero values on stack
+ h()
+ // call function that used to let the garbage collector
+ // see uninitialized stack values; it will see the
+ // nonzero values.
+ g()
+}
+
+func big(x int) {
+ if x >= 0 {
+ big(x - 1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug485.go b/gcc/testsuite/go.test/test/fixedbugs/bug485.go
new file mode 100644
index 0000000..c99faed
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug485.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo chose the wrong embedded method when the same type appeared
+// at different levels and the correct choice was not the first
+// appearance of the type in a depth-first search.
+
+package main
+
+type embedded string
+
+func (s embedded) val() string {
+ return string(s)
+}
+
+type A struct {
+ embedded
+}
+
+type B struct {
+ A
+ embedded
+}
+
+func main() {
+ b := &B{
+ A: A{
+ embedded: "a",
+ },
+ embedded: "b",
+ }
+ s := b.val()
+ if s != "b" {
+ panic(s)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug486.go b/gcc/testsuite/go.test/test/fixedbugs/bug486.go
new file mode 100644
index 0000000..9ad23b3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug486.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo lexer had a bug handling nested comments.
+// http://gcc.gnu.org/PR61746
+// http://code.google.com/p/gofrontend/issues/detail?id=35
+
+package main
+
+/*// comment
+*/
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug487.go b/gcc/testsuite/go.test/test/fixedbugs/bug487.go
new file mode 100644
index 0000000..e60af6c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug487.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo compiler did not reliably report mismatches between the
+// number of function results and the number of expected results.
+
+package p
+
+func G() (int, int, int) {
+ return 0, 0, 0
+}
+
+func F() {
+ a, b := G() // ERROR "mismatch"
+ a, b = G() // ERROR "mismatch"
+ _, _ = a, b
+}
+
+func H() (int, int) {
+ return G() // ERROR "too many|mismatch"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug488.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug488.dir/a.go
new file mode 100644
index 0000000..fc49420
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug488.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var p2 = Printf // ERROR "undefined"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug488.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug488.dir/b.go
new file mode 100644
index 0000000..f93328c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug488.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import . "fmt"
+
+var p1 = Print
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug488.go b/gcc/testsuite/go.test/test/fixedbugs/bug488.go
new file mode 100644
index 0000000..3912deb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug488.go
@@ -0,0 +1,12 @@
+// errorcheckdir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo compiler had a bug: if one file in a package did a dot
+// import, then an earlier file in the package would incorrectly
+// resolve to the imported names rather than reporting undefined
+// errors.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug489.go b/gcc/testsuite/go.test/test/fixedbugs/bug489.go
new file mode 100644
index 0000000..34250cd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug489.go
@@ -0,0 +1,22 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo compiler had a bug: mentioning a function type in an
+// expression in a function literal messed up the list of variables
+// referenced in enclosing functions.
+
+package main
+
+func main() {
+ v1, v2 := 0, 0
+ f := func() {
+ a := v1
+ g := (func())(nil)
+ b := v2
+ _, _, _ = a, g, b
+ }
+ _, _, _ = v1, v2, f
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug490.go b/gcc/testsuite/go.test/test/fixedbugs/bug490.go
new file mode 100644
index 0000000..387a680
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug490.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo compiler used to crash building a comparison between an
+// interface and an empty struct literal.
+
+package p
+
+type S struct{}
+
+func F(v interface{}) bool {
+ return v == S{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug491.go b/gcc/testsuite/go.test/test/fixedbugs/bug491.go
new file mode 100644
index 0000000..39a3509
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug491.go
@@ -0,0 +1,110 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test order of calls to builtin functions.
+// Discovered during CL 144530045 review.
+
+package main
+
+func main() {
+ // append
+ {
+ x := make([]int, 0)
+ f := func() int { x = make([]int, 2); return 2 }
+ a, b, c := append(x, 1), f(), append(x, 1)
+ if len(a) != 1 || len(c) != 3 {
+ bug()
+ println("append call not ordered:", len(a), b, len(c))
+ }
+ }
+
+ // cap
+ {
+ x := make([]int, 1)
+ f := func() int { x = make([]int, 3); return 2 }
+ a, b, c := cap(x), f(), cap(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("cap call not ordered:", a, b, c)
+ }
+ }
+
+ // complex
+ {
+ x := 1.0
+ f := func() int { x = 3; return 2 }
+ a, b, c := complex(x, 0), f(), complex(x, 0)
+ if real(a) != 1 || real(c) != 3 {
+ bug()
+ println("complex call not ordered:", a, b, c)
+ }
+ }
+
+ // copy
+ {
+ tmp := make([]int, 100)
+ x := make([]int, 1)
+ f := func() int { x = make([]int, 3); return 2 }
+ a, b, c := copy(tmp, x), f(), copy(tmp, x)
+ if a != 1 || c != 3 {
+ bug()
+ println("copy call not ordered:", a, b, c)
+ }
+ }
+
+ // imag
+ {
+ x := 1i
+ f := func() int { x = 3i; return 2 }
+ a, b, c := imag(x), f(), imag(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("imag call not ordered:", a, b, c)
+ }
+ }
+
+ // len
+ {
+ x := make([]int, 1)
+ f := func() int { x = make([]int, 3); return 2 }
+ a, b, c := len(x), f(), len(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("len call not ordered:", a, b, c)
+ }
+ }
+
+ // make
+ {
+ x := 1
+ f := func() int { x = 3; return 2 }
+ a, b, c := make([]int, x), f(), make([]int, x)
+ if len(a) != 1 || len(c) != 3 {
+ bug()
+ println("make call not ordered:", len(a), b, len(c))
+ }
+ }
+
+ // real
+ {
+ x := 1 + 0i
+ f := func() int { x = 3; return 2 }
+ a, b, c := real(x), f(), real(x)
+ if a != 1 || c != 3 {
+ bug()
+ println("real call not ordered:", a, b, c)
+ }
+ }
+}
+
+var bugged = false
+
+func bug() {
+ if !bugged {
+ println("BUG")
+ bugged = true
+ }
+} \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug492.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug492.dir/a.go
new file mode 100644
index 0000000..90917e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug492.dir/a.go
@@ -0,0 +1,16 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type s struct {
+ s string
+}
+
+func F1(s s) {
+}
+
+func F2() s {
+ return s{""}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug492.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug492.dir/b.go
new file mode 100644
index 0000000..5b8c4f2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug492.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ defer a.F1(a.F2())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug492.go b/gcc/testsuite/go.test/test/fixedbugs/bug492.go
new file mode 100644
index 0000000..050a9e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug492.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case that gccgo failed to link.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug493.go b/gcc/testsuite/go.test/test/fixedbugs/bug493.go
new file mode 100644
index 0000000..643e9af
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug493.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case that gccgo failed to compile.
+
+package p
+
+func F() []string {
+ return []string{""}
+}
+
+var V = append(F())
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug494.go b/gcc/testsuite/go.test/test/fixedbugs/bug494.go
new file mode 100644
index 0000000..42f1879
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug494.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo incorrectly executed functions multiple times when they
+// appeared in a composite literal that required a conversion between
+// different interface types.
+
+package main
+
+type MyInt int
+
+var c MyInt
+
+func (c *MyInt) S(i int) {
+ *c = MyInt(i)
+}
+
+func (c *MyInt) V() int {
+ return int(*c)
+}
+
+type i1 interface {
+ S(int)
+ V() int
+}
+
+type i2 interface {
+ V() int
+}
+
+type s struct {
+ i i2
+}
+
+func f() i1 {
+ c++
+ return &c
+}
+
+func main() {
+ p := &s{f()}
+ if v := p.i.V(); v != 1 {
+ panic(v)
+ }
+ if c != 1 {
+ panic(c)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug495.go b/gcc/testsuite/go.test/test/fixedbugs/bug495.go
new file mode 100644
index 0000000..dfc0c9f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug495.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo used to give an incorrect error
+// bug495.go:16:2: error: missing statement after label
+
+package p
+
+func F(i int) {
+ switch i {
+ case 0:
+ goto lab
+ lab:
+ fallthrough
+ case 1:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug496.go b/gcc/testsuite/go.test/test/fixedbugs/bug496.go
new file mode 100644
index 0000000..4307c75
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug496.go
@@ -0,0 +1,29 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo used to give an error:
+// <built-in>: error: redefinition of ‘s$F$hash’
+// <built-in>: note: previous definition of ‘s$F$hash’ was here
+// <built-in>: error: redefinition of ‘s$F$equal’
+// <built-in>: note: previous definition of ‘s$F$equal’ was here
+
+package p
+
+type T1 int
+
+func (t T1) F() {
+ type s struct {
+ f string
+ }
+}
+
+type T2 int
+
+func (t T2) F() {
+ type s struct {
+ f string
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug497.go b/gcc/testsuite/go.test/test/fixedbugs/bug497.go
new file mode 100644
index 0000000..7081b1c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug497.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo used to miscompile passing a global variable with a
+// zero-sized type to a function.
+
+package main
+
+type T struct {
+ field s
+}
+
+type s struct{}
+
+var X T
+
+func F(_ T, c interface{}) int {
+ return len(c.(string))
+}
+
+func main() {
+ if v := F(X, "hi"); v != 2 {
+ panic(v)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug498.go b/gcc/testsuite/go.test/test/fixedbugs/bug498.go
new file mode 100644
index 0000000..91b5c2f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug498.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo incorrectly rejected an assignment to multiple instances of
+// the same variable.
+
+package main
+
+var a int
+
+func F() {
+ a, a, a = 1, 2, 3
+}
+
+func main() {
+ F()
+ if a != 3 {
+ panic(a)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug499.go b/gcc/testsuite/go.test/test/fixedbugs/bug499.go
new file mode 100644
index 0000000..e4142e9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug499.go
@@ -0,0 +1,15 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo got confused when a type was used both for a map bucket type
+// and for a map key type.
+
+package main
+
+func main() {
+ _ = make(map[byte]byte)
+ _ = make(map[[8]byte]chan struct{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug500.go b/gcc/testsuite/go.test/test/fixedbugs/bug500.go
new file mode 100644
index 0000000..2dd5df1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug500.go
@@ -0,0 +1,41 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo generated incorrect GC info when a global variable was
+// initialized to a slice of a value containing pointers. The initial
+// backing array for the slice was allocated in the .data section,
+// which is fine, but the backing array was not registered as a GC
+// root.
+
+package main
+
+import (
+ "runtime"
+)
+
+type s struct {
+ str string
+}
+
+var a = []struct {
+ str string
+}{
+ {""},
+}
+
+var b = "b"
+var c = "c"
+
+func init() {
+ a[0].str = b + c
+}
+
+func main() {
+ runtime.GC()
+ if a[0].str != b + c {
+ panic(a[0].str)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug501.go b/gcc/testsuite/go.test/test/fixedbugs/bug501.go
new file mode 100644
index 0000000..8e951b1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug501.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo got a compiler crash compiling the addition of more than five
+// strings with mixed constants and variables.
+
+package main
+
+func F(s string) (string, error) {
+ return s, nil
+}
+
+func G(a, b, c string) (string, error) {
+ return F("a" + a + "b" + b + "c" + c)
+}
+
+func main() {
+ if got, _ := G("x", "y", "z"); got != "axbycz" {
+ panic(got)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug502.go b/gcc/testsuite/go.test/test/fixedbugs/bug502.go
new file mode 100644
index 0000000..cff73e7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug502.go
@@ -0,0 +1,28 @@
+// build
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Linking this with gccgo got an undefined symbol reference,
+// because the private method in testing.TB led gccgo to assume that
+// the interface method table would be defined in the testing package.
+
+package main
+
+import "testing"
+
+type I interface {
+ testing.TB
+ Parallel()
+}
+
+func F(i I) {
+ i.Log("F")
+}
+
+var t testing.T
+
+func main() {
+ F(&t)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug503.go b/gcc/testsuite/go.test/test/fixedbugs/bug503.go
new file mode 100644
index 0000000..7bbc798
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug503.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo crashed compiling this file, due to failing to correctly emit
+// the type descriptor for a named alias.
+
+package p
+
+type entry = struct {
+ a, b, c int
+}
+
+var V entry
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/a.go
new file mode 100644
index 0000000..ac0be93
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type MyInt = int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/b.go
new file mode 100644
index 0000000..e8f8da9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func F() a.MyInt {
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/c.go
new file mode 100644
index 0000000..5a6e889
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/c.go
@@ -0,0 +1,9 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import "./b"
+
+var V = b.F()
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/main.go
new file mode 100644
index 0000000..bdbd95c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug504.dir/main.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./c"
+
+func main() {
+ println(c.V)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug504.go b/gcc/testsuite/go.test/test/fixedbugs/bug504.go
new file mode 100644
index 0000000..ae1f2e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug504.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo mishandled a reference to a type alias in a package that was
+// not directly imported.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug505.go b/gcc/testsuite/go.test/test/fixedbugs/bug505.go
new file mode 100644
index 0000000..062a087
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug505.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo crashed compiling this file with a failed conversion to the
+// alias type when constructing the composite literal.
+
+package p
+
+type I interface{ M() }
+type A = I
+type S struct {
+ f A
+}
+
+func F(i I) S {
+ return S{f: i}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug506.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug506.dir/a.go
new file mode 100644
index 0000000..8e8a200
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug506.dir/a.go
@@ -0,0 +1,16 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type internal struct {
+ f1 string
+ f2 float64
+}
+
+type S struct {
+ F struct {
+ I internal
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug506.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug506.dir/main.go
new file mode 100644
index 0000000..1b60e40
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug506.dir/main.go
@@ -0,0 +1,20 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+
+ "./a"
+)
+
+var v = a.S{}
+
+func main() {
+ want := "{{ 0}}"
+ if got := fmt.Sprint(v.F); got != want {
+ panic(got)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug506.go b/gcc/testsuite/go.test/test/fixedbugs/bug506.go
new file mode 100644
index 0000000..7c8ccc6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug506.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo caused an undefined symbol reference building hash functions
+// for an imported struct with unexported fields.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/a.go
new file mode 100644
index 0000000..0929adc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type I interface {
+ M()
+}
+
+type S struct {
+ I I
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/b.go
new file mode 100644
index 0000000..bddce2d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import . "./a"
+
+var V2 I
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/c.go
new file mode 100644
index 0000000..e67f0fd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug507.dir/c.go
@@ -0,0 +1,9 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+var V1 = a.S{I: nil}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug507.go b/gcc/testsuite/go.test/test/fixedbugs/bug507.go
new file mode 100644
index 0000000..2d7aa59
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug507.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo mishandled a combination of normal import and dot import.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug508.go b/gcc/testsuite/go.test/test/fixedbugs/bug508.go
new file mode 100644
index 0000000..69b1ada
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug508.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo mishandles composite literals of map with type bool.
+
+package p
+
+var M = map[bool]uint8{
+ false: 0,
+ true: 1,
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug509.go b/gcc/testsuite/go.test/test/fixedbugs/bug509.go
new file mode 100644
index 0000000..df6ed61
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug509.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo mishandles a couple of alias cases.
+
+package p
+
+type S struct{}
+
+func (*S) M() {}
+
+type I interface {
+ M()
+}
+
+type A = *S
+
+var V1 I
+var _ = V1.(*S)
+var _ = V1.(A)
+
+func F() {
+ var v I
+ v = (*S)(nil)
+ v = A(nil)
+ _ = v
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug510.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug510.dir/a.go
new file mode 100644
index 0000000..db1cfef
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug510.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "reflect"
+
+type A = map[int] bool
+
+func F() interface{} {
+ return reflect.New(reflect.TypeOf((*A)(nil))).Elem().Interface()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug510.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug510.dir/b.go
new file mode 100644
index 0000000..56b0201
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug510.dir/b.go
@@ -0,0 +1,14 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ _, ok := a.F().(*map[int]bool)
+ if !ok {
+ panic("bad type")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug510.go b/gcc/testsuite/go.test/test/fixedbugs/bug510.go
new file mode 100644
index 0000000..8a6da5d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug510.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo confused type descriptors for aliases.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61204.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61204.go
new file mode 100644
index 0000000..e175f83
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61204.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61204: Making temporaries for zero-sized types caused an ICE in gccgo.
+// This is a reduction of a program reported by GoSmith.
+
+package main
+
+func main() {
+ type t [0]int
+ var v t
+ v, _ = [0]int{}, 0
+ _ = v
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61244.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61244.go
new file mode 100644
index 0000000..642bc61
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61244.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61244: Type descriptors expressions were not traversed, causing an ICE
+// in gccgo when producing the backend representation.
+// This is a reduction of a program reported by GoSmith.
+
+package main
+
+const a = 0
+
+func main() {
+ switch i := (interface{})(a); i.(type) {
+ case [0]string:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61246.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61246.go
new file mode 100644
index 0000000..797d6c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61246.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61246: Switch conditions could be untyped, causing an ICE when the
+// conditions were lowered into temporaries.
+// This is a reduction of a program reported by GoSmith.
+
+package main
+
+func main() {
+ switch 1 != 1 {
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61248.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61248.go
new file mode 100644
index 0000000..cb59c9f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61248.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61248: Transformations to recover calls made them fail typechecking in gccgo.
+
+package main
+
+func main() {
+ var f func(int, interface{})
+ go f(0, recover())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61253.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61253.go
new file mode 100644
index 0000000..696b26e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61253.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61253: gccgo incorrectly parsed the
+// `RecvStmt = ExpressionList "=" RecvExpr` production.
+
+package main
+
+func main() {
+ c := make(chan int)
+ v := new(int)
+ b := new(bool)
+ select {
+ case (*v), (*b) = <-c:
+ }
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61254.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61254.go
new file mode 100644
index 0000000..82e666e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61254.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61254: gccgo failed to compile a slice expression with missing indices.
+
+package main
+
+func main() {
+ [][]int{}[:][0][0]++
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61255.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61255.go
new file mode 100644
index 0000000..288fb54
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61255.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61255: gccgo failed to compile IncDec statements on variadic functions.
+
+package main
+
+func main() {
+ append([]byte{}, 0)[0]++
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61258.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61258.go
new file mode 100644
index 0000000..e4dcb337
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61258.go
@@ -0,0 +1,13 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61258: gccgo crashed when deleting a zero-sized key from a map.
+
+package main
+
+func main() {
+ delete(make(map[[0]bool]int), [0]bool{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61264.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61264.go
new file mode 100644
index 0000000..a4092f5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61264.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61264: IncDec statements involving composite literals caused in ICE in gccgo.
+
+package main
+
+func main() {
+ map[int]int{}[0]++
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61265.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61265.go
new file mode 100644
index 0000000..be79233
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61265.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61265: The gccgo middle-end failed to represent array composite literals
+// where the elements are zero-sized values.
+// This is a reduction of a program reported by GoSmith.
+
+package p
+
+var a = [1][0]int{B}[0]
+var B = [0]int{}
+var c = [1]struct{}{D}[0]
+var D = struct{}{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc61273.go b/gcc/testsuite/go.test/test/fixedbugs/gcc61273.go
new file mode 100644
index 0000000..ed78b1e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc61273.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR61273: gccgo failed to compile a SendStmt in the PostStmt of a ForClause
+// that involved predefined constants.
+
+package main
+
+func main() {
+ c := make(chan bool, 1)
+ for ; false; c <- false {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc65755.go b/gcc/testsuite/go.test/test/fixedbugs/gcc65755.go
new file mode 100644
index 0000000..1e5d116
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc65755.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PR65755: Incorrect type descriptor for type defined within method.
+
+package main
+
+import "reflect"
+
+type S1 struct{}
+
+func (S1) Fix() string {
+ type s struct {
+ f int
+ }
+ return reflect.TypeOf(s{}).Field(0).Name
+}
+
+type S2 struct{}
+
+func (S2) Fix() string {
+ type s struct {
+ g bool
+ }
+ return reflect.TypeOf(s{}).Field(0).Name
+}
+
+func main() {
+ f1 := S1{}.Fix()
+ f2 := S2{}.Fix()
+ if f1 != "f" || f2 != "g" {
+ panic(f1 + f2)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/a.go
new file mode 100644
index 0000000..9f51a7a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/a.go
@@ -0,0 +1,12 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T int
+
+func (a *T) Foo() [1]string {
+ var r [1]string
+ return r
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/b.go
new file mode 100644
index 0000000..41b62d2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc67968.dir/b.go
@@ -0,0 +1,12 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func F() (interface{}) {
+ var v *a.T
+ return v.Foo()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc67968.go b/gcc/testsuite/go.test/test/fixedbugs/gcc67968.go
new file mode 100644
index 0000000..8db3dd8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc67968.go
@@ -0,0 +1,14 @@
+// compiledir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// https://gcc.gnu.org/PR67968
+
+// gccgo compiler crash building the equality and hash functions for a
+// type when a return statement requires a conversion to interface
+// type of a call of function defined in a different package that
+// returns an unnamed type.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc78763.go b/gcc/testsuite/go.test/test/fixedbugs/gcc78763.go
new file mode 100644
index 0000000..3e34127
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc78763.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo compiler crashed while compiling this code.
+// https://gcc.gnu.org/PR78763.
+
+package p
+
+import "unsafe"
+
+func F() int {
+ if unsafe.Sizeof(0) == 8 {
+ return 8
+ }
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc80226.go b/gcc/testsuite/go.test/test/fixedbugs/gcc80226.go
new file mode 100644
index 0000000..530b397
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc80226.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The gccgo compiler crashed while compiling a function that returned
+// multiple zero-sized structs.
+// https://gcc.gnu.org/PR80226.
+
+package p
+
+type S struct{}
+
+func F() (S, S) {
+ return S{}, S{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/gcc89321.go b/gcc/testsuite/go.test/test/fixedbugs/gcc89321.go
new file mode 100644
index 0000000..93ca6b4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/gcc89321.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// https://gcc.gnu.org/PR89321
+// gccgo compiler crash building map literals with a zero-sized value type.
+
+package p
+
+type M map[byte]struct{}
+
+var (
+ M1 = M{1: {}, 2: {}, 3: {}}
+ M2 = M{1: {}, 2: {}}
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10047.go b/gcc/testsuite/go.test/test/fixedbugs/issue10047.go
new file mode 100644
index 0000000..dcbde48
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10047.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10047: gccgo failed to compile a type switch where the switch variable
+// and the base type of a case share the same identifier.
+
+package main
+
+func main() {
+ type t int
+ var p interface{}
+ switch t := p.(type) {
+ case t:
+ _ = t
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/a.go
new file mode 100644
index 0000000..8bb3b30
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/a.go
@@ -0,0 +1,11 @@
+package a
+
+import "log"
+
+func Do() {
+ Do2()
+}
+
+func Do2() {
+ println(log.Ldate | log.Ltime | log.Lshortfile)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/b.go
new file mode 100644
index 0000000..46d2f55
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10066.dir/b.go
@@ -0,0 +1,7 @@
+package b
+
+import "./a"
+
+func test() {
+ a.Do()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10066.go b/gcc/testsuite/go.test/test/fixedbugs/issue10066.go
new file mode 100644
index 0000000..3ea552f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10066.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10066: constants are printed in the original form
+// in export data. This is the opposite of issue 9076.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10135.go b/gcc/testsuite/go.test/test/fixedbugs/issue10135.go
new file mode 100644
index 0000000..9985e5a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10135.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10135: append a slice with zero-sized element used
+// to always return a slice with the same data pointer as the
+// old slice, even if it's nil, so this program used to panic
+// with nil pointer dereference because after append, s is a
+// slice with nil data pointer but non-zero len and cap.
+
+package main
+
+type empty struct{}
+
+func main() {
+ var s []empty
+
+ s = append(s, empty{})
+
+ for _, v := range s {
+ _ = v
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/a.go
new file mode 100644
index 0000000..c61d02b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/a.go
@@ -0,0 +1,24 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type m struct {
+ S string
+}
+
+var g = struct {
+ m
+ P string
+}{
+ m{"a"},
+ "",
+}
+
+type S struct{}
+
+func (s *S) M(p string) {
+ r := g
+ r.P = p
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/b.go
new file mode 100644
index 0000000..09d8911
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func F() *a.S {
+ return &a.S{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/c.go
new file mode 100644
index 0000000..d331495
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10219.dir/c.go
@@ -0,0 +1,12 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import "./b"
+
+func F() {
+ s := b.F()
+ s.M("c")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10219.go b/gcc/testsuite/go.test/test/fixedbugs/issue10219.go
new file mode 100644
index 0000000..325818c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10219.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10219: failure of inlinable function that uses embedded types
+// in an anonymous struct via :=.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10253.go b/gcc/testsuite/go.test/test/fixedbugs/issue10253.go
new file mode 100644
index 0000000..fafca6c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10253.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 10253: cmd/7g: bad codegen, probably regopt related
+
+package main
+
+func main() {
+ if !eq() {
+ panic("wrong value")
+ }
+}
+
+var text = "abc"
+var s = &str{text}
+
+func eq() bool {
+ return text[0] == s.text[0]
+}
+
+type str struct {
+ text string
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10284.go b/gcc/testsuite/go.test/test/fixedbugs/issue10284.go
new file mode 100644
index 0000000..39028e7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10284.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10284: gccgo failed to allow converting a user-defined
+// type whose underlying type is uintptr to unsafe.Pointer.
+
+package p
+
+import "unsafe"
+
+type T uintptr
+
+var _ unsafe.Pointer = unsafe.Pointer(T(0))
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10320.go b/gcc/testsuite/go.test/test/fixedbugs/issue10320.go
new file mode 100644
index 0000000..c7e2bab
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10320.go
@@ -0,0 +1,55 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10320: 7g failed to compile a program because it attempted
+// to use ZR as register. Other programs compiled but failed to
+// execute correctly because they clobbered the g register.
+
+package main
+
+func main() {
+ var x00, x01, x02, x03, x04, x05, x06, x07, x08, x09 int
+ var x10, x11, x12, x13, x14, x15, x16, x17, x18, x19 int
+ var x20, x21, x22, x23, x24, x25, x26, x27, x28, x29 int
+ var x30, x31, x32 int
+
+ _ = x00
+ _ = x01
+ _ = x02
+ _ = x03
+ _ = x04
+ _ = x05
+ _ = x06
+ _ = x07
+ _ = x08
+ _ = x09
+
+ _ = x10
+ _ = x11
+ _ = x12
+ _ = x13
+ _ = x14
+ _ = x15
+ _ = x16
+ _ = x17
+ _ = x18
+ _ = x19
+
+ _ = x20
+ _ = x21
+ _ = x22
+ _ = x23
+ _ = x24
+ _ = x25
+ _ = x26
+ _ = x27
+ _ = x28
+ _ = x29
+
+ _ = x30
+ _ = x31
+ _ = x32
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10332.go b/gcc/testsuite/go.test/test/fixedbugs/issue10332.go
new file mode 100644
index 0000000..096b7a5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10332.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The PkgPath of unexported fields of types defined in package main was incorrectly ""
+
+package main
+
+import (
+ "fmt"
+ "reflect"
+)
+
+type foo struct {
+ bar int
+}
+
+func main() {
+ pkgpath := reflect.ValueOf(foo{}).Type().Field(0).PkgPath
+ if pkgpath != "main" {
+ fmt.Printf("BUG: incorrect PkgPath: %v", pkgpath)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10353.go b/gcc/testsuite/go.test/test/fixedbugs/issue10353.go
new file mode 100644
index 0000000..87771d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10353.go
@@ -0,0 +1,49 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 10253: cmd/gc: incorrect escape analysis of closures
+// Partial call x.foo was not promoted to heap.
+
+package main
+
+func main() {
+ c := make(chan bool)
+ // Create a new goroutine to get a default-size stack segment.
+ go func() {
+ x := new(X)
+ clos(x.foo)()
+ c <- true
+ }()
+ <-c
+}
+
+type X int
+
+func (x *X) foo() {
+}
+
+func clos(x func()) func() {
+ f := func() {
+ print("")
+ x() // This statement crashed, because the partial call was allocated on the old stack.
+ }
+ // Grow stack so that partial call x becomes invalid if allocated on stack.
+ growstack(10000)
+ c := make(chan bool)
+ // Spoil the previous stack segment.
+ go func() {
+ c <- true
+ }()
+ <-c
+ return f
+}
+
+func growstack(x int) {
+ if x == 0 {
+ return
+ }
+ growstack(x - 1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10407.go b/gcc/testsuite/go.test/test/fixedbugs/issue10407.go
new file mode 100644
index 0000000..c6461a3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10407.go
@@ -0,0 +1,16 @@
+// runoutput
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10407: gccgo failed to remove carriage returns
+// from raw string literals.
+
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("package main\nfunc main() { if `a\rb\r\nc` != \"ab\\nc\" { panic(42) }}")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10441.go b/gcc/testsuite/go.test/test/fixedbugs/issue10441.go
new file mode 100644
index 0000000..9bc4948
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10441.go
@@ -0,0 +1,17 @@
+// build
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func bar() {
+ f := func() {}
+ foo(&f)
+}
+
+//go:noinline
+func foo(f *func()) func() {
+ return *f
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10486.go b/gcc/testsuite/go.test/test/fixedbugs/issue10486.go
new file mode 100644
index 0000000..3b62cb9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10486.go
@@ -0,0 +1,31 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10486.
+// Check stack walk during div by zero fault,
+// especially on software divide systems.
+
+package main
+
+import "runtime"
+
+var A, B int
+
+func divZero() int {
+ defer func() {
+ if p := recover(); p != nil {
+ var pcs [512]uintptr
+ runtime.Callers(2, pcs[:])
+ runtime.GC()
+ }
+ }()
+ return A / B
+}
+
+func main() {
+ A = 1
+ divZero()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10607.go b/gcc/testsuite/go.test/test/fixedbugs/issue10607.go
new file mode 100644
index 0000000..448a37d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10607.go
@@ -0,0 +1,34 @@
+// +build linux,!ppc64,!riscv64,gc
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that a -B option is passed through when using both internal
+// and external linking mode.
+
+// TODO(jsing): Re-enable on riscv64 when it has support for external
+// linking - see golang.org/issue/36739
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+func main() {
+ test("internal")
+ test("external")
+}
+
+func test(linkmode string) {
+ out, err := exec.Command("go", "run", "-ldflags", "-B=0x12345678 -linkmode="+linkmode, filepath.Join("fixedbugs", "issue10607a.go")).CombinedOutput()
+ if err != nil {
+ fmt.Printf("BUG: linkmode=%s %v\n%s\n", linkmode, err, out)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10607a.go b/gcc/testsuite/go.test/test/fixedbugs/issue10607a.go
new file mode 100644
index 0000000..51399e4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10607a.go
@@ -0,0 +1,81 @@
+// skip
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is built by issue10607.go with a -B option.
+// Verify that we have one build-id note with the expected value.
+
+package main
+
+import (
+ "bytes"
+ "debug/elf"
+ "fmt"
+ "os"
+)
+
+func main() {
+ f, err := elf.Open("/proc/self/exe")
+ if err != nil {
+ if os.IsNotExist(err) {
+ return
+ }
+ fmt.Fprintln(os.Stderr, "opening /proc/self/exe:", err)
+ os.Exit(1)
+ }
+
+ c := 0
+ fail := false
+ for i, s := range f.Sections {
+ if s.Type != elf.SHT_NOTE {
+ continue
+ }
+
+ d, err := s.Data()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "reading data of note section %d: %v\n", i, err)
+ continue
+ }
+
+ for len(d) > 0 {
+ namesz := f.ByteOrder.Uint32(d)
+ descsz := f.ByteOrder.Uint32(d[4:])
+ typ := f.ByteOrder.Uint32(d[8:])
+
+ an := (namesz + 3) &^ 3
+ ad := (descsz + 3) &^ 3
+
+ if int(12+an+ad) > len(d) {
+ fmt.Fprintf(os.Stderr, "note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))\n", i, len(d), namesz, descsz)
+ break
+ }
+
+ // 3 == NT_GNU_BUILD_ID
+ if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
+ id := string(d[12+an:12+an+descsz])
+ if id == "\x12\x34\x56\x78" {
+ c++
+ } else {
+ fmt.Fprintf(os.Stderr, "wrong build ID data: %q\n", id)
+ fail = true
+ }
+ }
+
+ d = d[12+an+ad:]
+ }
+ }
+
+ if c == 0 {
+ fmt.Fprintln(os.Stderr, "no build-id note")
+ fail = true
+ } else if c > 1 {
+ fmt.Fprintln(os.Stderr, c, "build-id notes")
+ fail = true
+ }
+
+ if fail {
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10654.go b/gcc/testsuite/go.test/test/fixedbugs/issue10654.go
new file mode 100644
index 0000000..0600a80
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10654.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10654: Failure to use generated temps
+// for function calls etc. in boolean codegen.
+
+package main
+
+var s string
+
+func main() {
+ if (s == "this") != (s == "that") {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/other.go b/gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/other.go
new file mode 100644
index 0000000..12908b9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/other.go
@@ -0,0 +1,10 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package other
+
+type Exported interface {
+ Do()
+ secret()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/test.go b/gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/test.go
new file mode 100644
index 0000000..2dfc24a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10700.dir/test.go
@@ -0,0 +1,49 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./other"
+
+type Imported interface {
+ Do()
+}
+
+type HasAMethod struct {
+ x int
+}
+
+func (me *HasAMethod) Do() {
+ println(me.x)
+}
+
+func InMyCode(x *Imported, y *HasAMethod, z *other.Exported) {
+ x.Do() // ERROR "x\.Do undefined \(type \*Imported is pointer to interface, not interface\)|type that is pointer to interface"
+ x.do() // ERROR "x\.do undefined \(type \*Imported is pointer to interface, not interface\)|type that is pointer to interface"
+ (*x).Do()
+ x.Dont() // ERROR "x\.Dont undefined \(type \*Imported is pointer to interface, not interface\)|type that is pointer to interface"
+ (*x).Dont() // ERROR "\(\*x\)\.Dont undefined \(type Imported has no field or method Dont\)|reference to undefined field or method"
+
+ y.Do()
+ y.do() // ERROR "y\.do undefined \(type \*HasAMethod has no field or method do, but does have Do\)|reference to undefined field or method"
+ (*y).Do()
+ (*y).do() // ERROR "\(\*y\)\.do undefined \(type HasAMethod has no field or method do, but does have Do\)|reference to undefined field or method"
+ y.Dont() // ERROR "y\.Dont undefined \(type \*HasAMethod has no field or method Dont\)|reference to undefined field or method"
+ (*y).Dont() // ERROR "\(\*y\)\.Dont undefined \(type HasAMethod has no field or method Dont\)|reference to undefined field or method"
+
+ z.Do() // ERROR "z\.Do undefined \(type \*other\.Exported is pointer to interface, not interface\)|type that is pointer to interface"
+ z.do() // ERROR "z\.do undefined \(type \*other\.Exported is pointer to interface, not interface\)|type that is pointer to interface"
+ (*z).Do()
+ (*z).do() // ERROR "\(\*z\)\.do undefined \(type other.Exported has no field or method do, but does have Do\)|reference to undefined field or method"
+ z.Dont() // ERROR "z\.Dont undefined \(type \*other\.Exported is pointer to interface, not interface\)|type that is pointer to interface"
+ (*z).Dont() // ERROR "\(\*z\)\.Dont undefined \(type other\.Exported has no field or method Dont\)|reference to undefined field or method"
+ z.secret() // ERROR "z\.secret undefined \(type \*other\.Exported is pointer to interface, not interface\)|type that is pointer to interface"
+ (*z).secret() // ERROR "\(\*z\)\.secret undefined \(cannot refer to unexported field or method secret\)|reference to unexported field or method"
+
+}
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10700.go b/gcc/testsuite/go.test/test/fixedbugs/issue10700.go
new file mode 100644
index 0000000..25544ef
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10700.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10925.go b/gcc/testsuite/go.test/test/fixedbugs/issue10925.go
new file mode 100644
index 0000000..30add82
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10925.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func prototype(xyz []string) {}
+func main() {
+ var got [][]string
+ f := prototype
+ f = func(ss []string) { got = append(got, ss) }
+ for _, s := range []string{"one", "two", "three"} {
+ f([]string{s})
+ }
+ if got[0][0] != "one" || got[1][0] != "two" || got[2][0] != "three" {
+ // Bug's wrong output was [[three] [three] [three]]
+ fmt.Println("Expected [[one] [two] [three]], got", got)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10958.go b/gcc/testsuite/go.test/test/fixedbugs/issue10958.go
new file mode 100644
index 0000000..52487fb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10958.go
@@ -0,0 +1,95 @@
+// +build !nacl,!js,disabled_see_issue_18589
+// buildrun -t 10 -gcflags=-d=ssa/insert_resched_checks/on,ssa/check/on
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test is disabled because it flakes when run in all.bash
+// on some platforms, but is useful standalone to verify
+// that rescheduling checks are working (and we may wish
+// to investigate the flake, since it suggests that the
+// loop rescheduling check may not work right on those
+// platforms).
+
+// This checks to see that call-free infinite loops do not
+// block garbage collection. IF YOU RUN IT STANDALONE without
+// -gcflags=-d=ssa/insert_resched_checks/on in a not-experimental
+// build, it should hang.
+
+package main
+
+import (
+ "runtime"
+)
+
+var someglobal1 int
+var someglobal2 int
+var someglobal3 int
+
+//go:noinline
+func f() {}
+
+func standinacorner1() {
+ for someglobal1&1 == 0 {
+ someglobal1++
+ someglobal1++
+ }
+}
+
+func standinacorner2(i int) {
+ // contains an irreducible loop containing changes to memory
+ if i != 0 {
+ goto midloop
+ }
+
+loop:
+ if someglobal2&1 != 0 {
+ goto done
+ }
+ someglobal2++
+midloop:
+ someglobal2++
+ goto loop
+
+done:
+ return
+}
+
+func standinacorner3() {
+ for someglobal3&1 == 0 {
+ if someglobal3&2 != 0 {
+ for someglobal3&3 == 2 {
+ someglobal3++
+ someglobal3++
+ someglobal3++
+ someglobal3++
+ }
+ }
+ someglobal3++
+ someglobal3++
+ someglobal3++
+ someglobal3++
+ }
+}
+
+func main() {
+ go standinacorner1()
+ go standinacorner2(0)
+ go standinacorner3()
+ // println("About to stand in a corner1")
+ for someglobal1 == 0 {
+ runtime.Gosched()
+ }
+ // println("About to stand in a corner2")
+ for someglobal2 == 0 {
+ runtime.Gosched()
+ }
+ // println("About to stand in a corner3")
+ for someglobal3 == 0 {
+ runtime.Gosched()
+ }
+ // println("About to GC")
+ runtime.GC()
+ // println("Success")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10975.go b/gcc/testsuite/go.test/test/fixedbugs/issue10975.go
new file mode 100644
index 0000000..933badf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10975.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 10975: Returning an invalid interface would cause
+// `internal compiler error: getinarg: not a func`.
+
+package main
+
+type I interface {
+ int // ERROR "interface contains embedded non-interface"
+}
+
+func New() I {
+ return struct{}{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue10977.go b/gcc/testsuite/go.test/test/fixedbugs/issue10977.go
new file mode 100644
index 0000000..0b18c70
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue10977.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct{}
+
+var (
+ t = T{}
+ u = t.New()
+)
+
+func x(T) (int, int) { return 0, 0 }
+
+var _, _ = x(u)
+
+func (T) New() T { return T{} }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p.go b/gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p.go
new file mode 100644
index 0000000..81b412a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p.go
@@ -0,0 +1,9 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func Int32(i int32) *int32 {
+ return &i
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p_test.go b/gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p_test.go
new file mode 100644
index 0000000..542c2a3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11053.dir/p_test.go
@@ -0,0 +1,51 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "p"
+)
+
+type I interface {
+ Add(out *P)
+}
+
+type P struct {
+ V *int32
+}
+
+type T struct{}
+
+var x int32 = 42
+
+func Int32x(i int32) *int32 {
+ return &i
+}
+
+func (T) Add(out *P) {
+ out.V = p.Int32(x) // inlined, p.i.2 moved to heap
+}
+
+var PP P
+var out *P = &PP
+
+func F(s I) interface{} {
+ s.Add(out) // not inlined.
+ return out
+}
+
+var s T
+
+func main() {
+ println("Starting")
+ fmt.Sprint(new(int32))
+ resp := F(s).(*P)
+ println("Before, *resp.V=", *resp.V) // Trashes *resp.V in process of printing.
+ println("After, *resp.V=", *resp.V)
+ if got, want := *resp.V, int32(42); got != want {
+ fmt.Printf("FAIL, got %v, want %v", got, want)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11053.go b/gcc/testsuite/go.test/test/fixedbugs/issue11053.go
new file mode 100644
index 0000000..06005d3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11053.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11053: Compiler does not run escape analysis on an inlined
+// generated method wrapper.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11053.out b/gcc/testsuite/go.test/test/fixedbugs/issue11053.out
new file mode 100644
index 0000000..a75f73c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11053.out
@@ -0,0 +1,3 @@
+Starting
+Before, *resp.V= 42
+After, *resp.V= 42
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11256.go b/gcc/testsuite/go.test/test/fixedbugs/issue11256.go
new file mode 100644
index 0000000..69fc3e8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11256.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that stack barriers are reset when a goroutine exits without
+// returning.
+
+package main
+
+import (
+ "runtime"
+ "sync/atomic"
+ "time"
+)
+
+func main() {
+ // Let the garbage collector run concurrently.
+ runtime.GOMAXPROCS(2)
+
+ var x [100][]byte
+
+ for i := range x {
+ var done int32
+
+ go func() {
+ // Use enough stack to get stack barriers, but
+ // not so much that we go over _FixedStack.
+ // There's a very narrow window here on most
+ // OSs, so we basically can't do anything (not
+ // even a time.Sleep or a channel).
+ var buf [1024]byte
+ buf[0]++
+ for atomic.LoadInt32(&done) == 0 {
+ runtime.Gosched()
+ }
+ atomic.StoreInt32(&done, 0)
+ // Exit without unwinding stack barriers.
+ runtime.Goexit()
+ }()
+
+ // Generate some garbage.
+ x[i] = make([]byte, 1024*1024)
+
+ // Give GC some time to install stack barriers in the G.
+ time.Sleep(50 * time.Microsecond)
+ atomic.StoreInt32(&done, 1)
+ for atomic.LoadInt32(&done) == 1 {
+ runtime.Gosched()
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11286.go b/gcc/testsuite/go.test/test/fixedbugs/issue11286.go
new file mode 100644
index 0000000..560b7d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11286.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that pointer bitmaps of types with large scalar tails are
+// correctly repeated when unrolled into the heap bitmap.
+
+package main
+
+import "runtime"
+
+const D = 57
+
+type T struct {
+ a [D]float64
+ b map[string]int
+ c [D]float64
+}
+
+var ts []T
+
+func main() {
+ ts = make([]T, 4)
+ for i := range ts {
+ ts[i].b = make(map[string]int)
+ }
+ ts[3].b["abc"] = 42
+ runtime.GC()
+ if ts[3].b["abc"] != 42 {
+ panic("bad field value")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11326b.go b/gcc/testsuite/go.test/test/fixedbugs/issue11326b.go
new file mode 100644
index 0000000..b5f933b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11326b.go
@@ -0,0 +1,48 @@
+// run
+
+// Does not work with gccgo, which uses a smaller (but still permitted)
+// exponent size.
+// +build !gccgo
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Tests for golang.org/issue/11326.
+
+func main() {
+ {
+ const n = 1e646456992
+ const d = 1e646456991
+ x := n / d
+ if x != 10.0 {
+ println("incorrect value:", x)
+ }
+ }
+ {
+ const n = 1e64645699
+ const d = 1e64645698
+ x := n / d
+ if x != 10.0 {
+ println("incorrect value:", x)
+ }
+ }
+ {
+ const n = 1e6464569
+ const d = 1e6464568
+ x := n / d
+ if x != 10.0 {
+ println("incorrect value:", x)
+ }
+ }
+ {
+ const n = 1e646456
+ const d = 1e646455
+ x := n / d
+ if x != 10.0 {
+ println("incorrect value:", x)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11354.go b/gcc/testsuite/go.test/test/fixedbugs/issue11354.go
new file mode 100644
index 0000000..3980e8f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11354.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type X int
+
+var foo = map[int]X{}
+
+var bar = map[int][8]X{}
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11359.go b/gcc/testsuite/go.test/test/fixedbugs/issue11359.go
new file mode 100644
index 0000000..6ffffed
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11359.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// identifiers beginning with non-ASCII digits were incorrectly accepted.
+// issue 11359.
+
+package p
+var ۶ = 0 // ERROR "identifier cannot begin with digit"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11361.go b/gcc/testsuite/go.test/test/fixedbugs/issue11361.go
new file mode 100644
index 0000000..63dbf05d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11361.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "fmt" // GC_ERROR "imported and not used"
+
+const n = fmt // ERROR "fmt without selector|unexpected reference to package"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11362.go b/gcc/testsuite/go.test/test/fixedbugs/issue11362.go
new file mode 100644
index 0000000..964e5fd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11362.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11362: prints empty canonical import path
+
+package main
+
+import _ "unicode//utf8" // GC_ERROR "non-canonical import path .unicode//utf8. \(should be .unicode/utf8.\)" "can't find import: .unicode//utf8."
+
+func main() {
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11369.go b/gcc/testsuite/go.test/test/fixedbugs/issue11369.go
new file mode 100644
index 0000000..9df37c3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11369.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that the half multiply resulting from a division
+// by a constant generates correct code.
+
+package main
+
+func main() {
+ var _ = 7 / "0"[0] // test case from #11369
+ var _ = 1 / "."[0] // test case from #11358
+ var x = 0 / "0"[0]
+ var y = 48 / "0"[0]
+ var z = 5 * 48 / "0"[0]
+ if x != 0 {
+ panic("expected 0")
+ }
+ if y != 1 {
+ panic("expected 1")
+ }
+ if z != 5 {
+ panic("expected 5")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11370.go b/gcc/testsuite/go.test/test/fixedbugs/issue11370.go
new file mode 100644
index 0000000..30f2904
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11370.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 11370: cmd/compile: "0"[0] should not be a constant
+
+package p
+
+func main() {
+ println(-"abc"[1] >> 1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11371.go b/gcc/testsuite/go.test/test/fixedbugs/issue11371.go
new file mode 100644
index 0000000..8acd18f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11371.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11371 (cmd/compile: meaningless error message "truncated to
+// integer")
+
+package issue11371
+
+const a int = 1.1 // ERROR "constant 1.1 truncated to integer|floating-point constant truncated to integer"
+const b int = 1e20 // ERROR "overflows int|integer constant overflow"
+const c int = 1 + 1e-70 // ERROR "constant truncated to integer"
+const d int = 1 - 1e-70 // ERROR "constant truncated to integer"
+const e int = 1.00000001 // ERROR "constant truncated to integer"
+const f int = 0.00000001 // ERROR "constant 1e-08 truncated to integer|floating-point constant truncated to integer"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11590.go b/gcc/testsuite/go.test/test/fixedbugs/issue11590.go
new file mode 100644
index 0000000..f2a955f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11590.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = int8(4) * 300 // ERROR "constant 300 overflows int8" "constant 1200 overflows int8|integer constant overflow"
+var _ = complex64(1) * 1e200 // ERROR "constant 1e\+200 overflows complex64|complex real part overflow"
+var _ = complex128(1) * 1e500 // ERROR "constant 1e\+500 overflows complex128|complex real part overflow"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11610.go b/gcc/testsuite/go.test/test/fixedbugs/issue11610.go
new file mode 100644
index 0000000..7ebfae6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11610.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test an internal compiler error on ? symbol in declaration
+// following an empty import.
+
+package a
+import"" // ERROR "import path is empty"
+var? // ERROR "invalid character U\+003F '\?'|invalid character 0x3f in input file"
+
+var x int // ERROR "unexpected var|expected identifier|expected type"
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11614.go b/gcc/testsuite/go.test/test/fixedbugs/issue11614.go
new file mode 100644
index 0000000..de15f98
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11614.go
@@ -0,0 +1,26 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that incorrect expressions involving wrong anonymous interface
+// do not generate panics in Type Stringer.
+// Does not compile.
+
+package main
+
+type I interface {
+ int // ERROR "interface contains embedded non-interface"
+}
+
+func n() {
+ (I)
+}
+
+func m() {
+ (interface{int}) // ERROR "interface contains embedded non-interface" "type interface { int } is not an expression"
+}
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11674.go b/gcc/testsuite/go.test/test/fixedbugs/issue11674.go
new file mode 100644
index 0000000..b43032d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11674.go
@@ -0,0 +1,40 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11674: cmd/compile: does not diagnose constant division by
+// zero
+
+package p
+
+const x complex64 = 0
+const y complex128 = 0
+
+var _ = x / 1e-20
+var _ = x / 1e-50 // GC_ERROR "complex division by zero"
+var _ = x / 1e-1000 // GC_ERROR "complex division by zero"
+var _ = x / 1e-20i
+var _ = x / 1e-50i // GC_ERROR "complex division by zero"
+var _ = x / 1e-1000i // GC_ERROR "complex division by zero"
+
+var _ = x / 1e-45 // smallest positive float32
+
+var _ = x / (1e-20 + 1e-20i)
+var _ = x / (1e-50 + 1e-20i)
+var _ = x / (1e-20 + 1e-50i)
+var _ = x / (1e-50 + 1e-50i) // GC_ERROR "complex division by zero"
+var _ = x / (1e-1000 + 1e-1000i) // GC_ERROR "complex division by zero"
+
+var _ = y / 1e-50
+var _ = y / 1e-1000 // GC_ERROR "complex division by zero"
+var _ = y / 1e-50i
+var _ = y / 1e-1000i // GC_ERROR "complex division by zero"
+
+var _ = y / 5e-324 // smallest positive float64
+
+var _ = y / (1e-50 + 1e-50)
+var _ = y / (1e-1000 + 1e-50i)
+var _ = y / (1e-50 + 1e-1000i)
+var _ = y / (1e-1000 + 1e-1000i) // GC_ERROR "complex division by zero"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11699.go b/gcc/testsuite/go.test/test/fixedbugs/issue11699.go
new file mode 100644
index 0000000..755e9a1f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11699.go
@@ -0,0 +1,12 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 11699; used to fail with duplicate _.args_stackmap symbols.
+
+package p
+
+func _()
+func _()
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11750.go b/gcc/testsuite/go.test/test/fixedbugs/issue11750.go
new file mode 100644
index 0000000..d5a2b22
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11750.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11750: mkdotargslice: typecheck failed
+
+package main
+
+func main() {
+ fn := func(names string) {
+
+ }
+ func(names ...string) {
+ for _, name := range names {
+ fn(name)
+ }
+ }("one", "two")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11771.go b/gcc/testsuite/go.test/test/fixedbugs/issue11771.go
new file mode 100644
index 0000000..c95dd6b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11771.go
@@ -0,0 +1,64 @@
+// +build !nacl,!js,gc
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11771: Magic comments should ignore carriage returns.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+)
+
+func main() {
+ if runtime.Compiler != "gc" {
+ return
+ }
+
+ dir, err := ioutil.TempDir("", "go-issue11771")
+ if err != nil {
+ log.Fatalf("creating temp dir: %v\n", err)
+ }
+ defer os.RemoveAll(dir)
+
+ // The go:nowritebarrier magic comment is only permitted in
+ // the runtime package. So we confirm that the compilation
+ // fails.
+
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, `
+package main
+
+func main() {
+}
+`)
+ fmt.Fprintln(&buf, "//go:nowritebarrier\r")
+ fmt.Fprintln(&buf, `
+func x() {
+}
+`)
+
+ if err := ioutil.WriteFile(filepath.Join(dir, "x.go"), buf.Bytes(), 0666); err != nil {
+ log.Fatal(err)
+ }
+
+ cmd := exec.Command("go", "tool", "compile", "x.go")
+ cmd.Dir = dir
+ output, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatal("compile succeeded unexpectedly")
+ }
+ if !bytes.Contains(output, []byte("only allowed in runtime")) {
+ log.Fatalf("wrong error message from compiler; got:\n%s\n", output)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11790.go b/gcc/testsuite/go.test/test/fixedbugs/issue11790.go
new file mode 100644
index 0000000..096b297
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11790.go
@@ -0,0 +1,36 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11790: Incorrect error following named pointer dereference on field
+
+package main
+
+import "fmt"
+
+type T0 struct {
+ x int
+}
+
+func (*T0) M0() {
+ fmt.Println("M0")
+}
+
+type T2 struct {
+ *T0
+}
+
+type Q *T2
+
+func main() {
+ // If run, expected output is
+ // 42
+ // M0
+ t0 := T0{42}
+ t2 := T2{&t0}
+ var q Q = &t2
+ fmt.Println(q.x) // Comment out either this line or the next line and the program works
+ (*q).T0.M0()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11945.go b/gcc/testsuite/go.test/test/fixedbugs/issue11945.go
new file mode 100644
index 0000000..510b655
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11945.go
@@ -0,0 +1,71 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+// issue 17446
+const (
+ _ = real(0) // from bug report
+ _ = imag(0) // from bug report
+
+ // if the arguments are untyped, the results must be untyped
+ // (and compatible with types that can represent the values)
+ _ int = real(1)
+ _ int = real('a')
+ _ int = real(2.0)
+ _ int = real(3i)
+
+ _ float32 = real(1)
+ _ float32 = real('a')
+ _ float32 = real(2.1)
+ _ float32 = real(3.2i)
+
+ _ float64 = real(1)
+ _ float64 = real('a')
+ _ float64 = real(2.1)
+ _ float64 = real(3.2i)
+
+ _ int = imag(1)
+ _ int = imag('a')
+ _ int = imag(2.1 + 3i)
+ _ int = imag(3i)
+
+ _ float32 = imag(1)
+ _ float32 = imag('a')
+ _ float32 = imag(2.1 + 3.1i)
+ _ float32 = imag(3i)
+
+ _ float64 = imag(1)
+ _ float64 = imag('a')
+ _ float64 = imag(2.1 + 3.1i)
+ _ float64 = imag(3i)
+)
+
+var tests = []struct {
+ code string
+ got, want interface{}
+}{
+ {"real(1)", real(1), 1.0},
+ {"real('a')", real('a'), float64('a')},
+ {"real(2.0)", real(2.0), 2.0},
+ {"real(3.2i)", real(3.2i), 0.0},
+
+ {"imag(1)", imag(1), 0.0},
+ {"imag('a')", imag('a'), 0.0},
+ {"imag(2.1 + 3.1i)", imag(2.1 + 3.1i), 3.1},
+ {"imag(3i)", imag(3i), 3.0},
+}
+
+func main() {
+ // verify compile-time evaluated constant expressions
+ for _, test := range tests {
+ if test.got != test.want {
+ panic(fmt.Sprintf("%s: %v (%T) != %v (%T)", test.code, test.got, test.got, test.want, test.want))
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue11987.go b/gcc/testsuite/go.test/test/fixedbugs/issue11987.go
new file mode 100644
index 0000000..9b665dc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue11987.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 11987. The ppc64 SRADCC instruction was misassembled in a way
+// lost bit 5 of the immediate so v>>32 was assembled as v>>0. SRADCC
+// is only ever inserted by peep so it's hard to be sure when it will
+// be used. This formulation worked when the bug was fixed.
+
+package main
+
+import "fmt"
+
+var v int64 = 0x80000000
+
+func main() {
+ s := fmt.Sprintf("%v", v>>32 == 0)
+ if s != "true" {
+ fmt.Printf("BUG: v>>32 == 0 evaluated as %q\n", s)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12006.go b/gcc/testsuite/go.test/test/fixedbugs/issue12006.go
new file mode 100644
index 0000000..0a2ef8d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12006.go
@@ -0,0 +1,174 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test escape analysis through ... parameters.
+
+package foo
+
+func FooN(vals ...*int) (s int) { // ERROR "vals does not escape"
+ for _, v := range vals {
+ s += *v
+ }
+ return s
+}
+
+// Append forces heap allocation and copies entries in vals to heap, therefore they escape to heap.
+func FooNx(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param content: vals"
+ vals = append(vals, x)
+ return FooN(vals...)
+}
+
+var sink []*int
+
+func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals"
+ vals = append(vals, x)
+ sink = vals
+ return FooN(vals...)
+}
+
+func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals"
+ sink = vals
+ return FooN(vals...)
+}
+
+func TFooN() {
+ for i := 0; i < 1000; i++ {
+ var i, j int
+ FooN(&i, &j) // ERROR "... argument does not escape"
+ }
+}
+
+func TFooNx() {
+ for i := 0; i < 1000; i++ {
+ var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
+ FooNx(&k, &i, &j) // ERROR "... argument does not escape"
+ }
+}
+
+func TFooNy() {
+ for i := 0; i < 1000; i++ {
+ var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
+ FooNy(&k, &i, &j) // ERROR "... argument escapes to heap"
+ }
+}
+
+func TFooNz() {
+ for i := 0; i < 1000; i++ {
+ var i, j int // ERROR "moved to heap: i" "moved to heap: j"
+ FooNz(&i, &j) // ERROR "... argument escapes to heap"
+ }
+}
+
+var isink *int32
+
+func FooI(args ...interface{}) { // ERROR "leaking param content: args"
+ for i := 0; i < len(args); i++ {
+ switch x := args[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ isink = x
+ case string:
+ println("is string")
+ }
+ }
+}
+
+func TFooI() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape"
+}
+
+func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+ for i := 0; i < len(args); i++ {
+ switch x := args[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ return x
+ case string:
+ println("is string")
+ }
+ }
+ return nil
+}
+
+func TFooJ1() {
+ a := int32(1)
+ b := "cat"
+ c := &a
+ FooJ(a, b, c) // ERROR "a does not escape" "b does not escape" "... argument does not escape"
+}
+
+func TFooJ2() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape"
+}
+
+type fakeSlice struct {
+ l int
+ a *[4]interface{}
+}
+
+func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+ for i := 0; i < args.l; i++ {
+ switch x := (*args.a)[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ return x
+ case string:
+ println("is string")
+ }
+ }
+ return nil
+}
+
+func TFooK2() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "&\[4\]interface {}{...} does not escape"
+ isink = FooK(fs)
+}
+
+func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+ for i := 0; i < len(args); i++ {
+ switch x := args[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ return x
+ case string:
+ println("is string")
+ }
+ }
+ return nil
+}
+
+func TFooL2() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "\[\]interface {}{...} does not escape"
+ isink = FooL(s)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12108.go b/gcc/testsuite/go.test/test/fixedbugs/issue12108.go
new file mode 100644
index 0000000..c7a7425
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12108.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// A generated method with a return value large enough to be
+// initialized by duffzero is not a leaf method, which violated
+// assumptions made by cmd/internal/obj/ppc64.
+
+package main
+
+const N = 9 // values > 8 cause (Super).Method to use duffzero
+
+type Base struct {
+}
+
+func (b *Base) Method() (x [N]uintptr) {
+ return
+}
+
+type Super struct {
+ Base
+}
+
+type T interface {
+ Method() [N]uintptr
+}
+
+func f(q T) {
+ q.Method()
+}
+
+func main() {
+ var s Super
+ f(&s)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12133.go b/gcc/testsuite/go.test/test/fixedbugs/issue12133.go
new file mode 100644
index 0000000..bbf9fb0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12133.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 12133. The CX register was getting clobbered
+// because we did not keep track of its allocation correctly.
+
+package main
+
+import "fmt"
+
+func main() {
+ want := uint(48)
+ got := f1(48)
+ if got != want {
+ fmt.Println("got", got, ", wanted", want)
+ panic("bad")
+ }
+}
+
+//go:noinline
+func f1(v1 uint) uint {
+ return v1 >> ((1 >> v1) + (1 >> v1))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12226.go b/gcc/testsuite/go.test/test/fixedbugs/issue12226.go
new file mode 100644
index 0000000..2246711
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12226.go
@@ -0,0 +1,15 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func main() {
+ if []byte("foo")[0] == []byte("b")[0] {
+ fmt.Println("BUG: \"foo\" and \"b\" appear to have the same first byte")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12347.go b/gcc/testsuite/go.test/test/fixedbugs/issue12347.go
new file mode 100644
index 0000000..fc5678e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12347.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f_ssa(x int, p *int) {
+ if false {
+ y := x + 5
+ for {
+ *p = y
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12411.go b/gcc/testsuite/go.test/test/fixedbugs/issue12411.go
new file mode 100644
index 0000000..ff49314
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12411.go
@@ -0,0 +1,24 @@
+// +build !386
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 12411. Loss of AX during %.
+
+package main
+
+func main() {
+ x := f(4)
+ if x != 0 {
+ println("BUG: x=", x)
+ }
+}
+
+//go:noinline
+func f(x int) int {
+ // AX was live on entry to one of the % code generations,
+ // and the % code generation smashed it.
+ return ((2 * x) % 3) % (2 % ((x << 2) ^ (x % 3)))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12413.go b/gcc/testsuite/go.test/test/fixedbugs/issue12413.go
new file mode 100644
index 0000000..a054765
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12413.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 12413: invalid variable name x in type switch: code would fail
+// to compile if the variable used in the short variable declaration was
+// previously declared as a constant.
+
+package main
+
+func main() {
+ const x = 42
+ switch x := interface{}(nil).(type) {
+ default:
+ _ = x
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12536.go b/gcc/testsuite/go.test/test/fixedbugs/issue12536.go
new file mode 100644
index 0000000..ceeaec4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12536.go
@@ -0,0 +1,22 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 12536: compiler crashes while checking keys in a map literal for equality
+
+package p
+
+func main() {
+ m1 := map[interface{}]interface{}{
+ nil: 0,
+ true: 1,
+ }
+ m2 := map[interface{}]interface{}{
+ true: 1,
+ nil: 0,
+ }
+ println(len(m1))
+ println(len(m2))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12577.go b/gcc/testsuite/go.test/test/fixedbugs/issue12577.go
new file mode 100644
index 0000000..249b4f2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12577.go
@@ -0,0 +1,66 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 12577: Test that there are no -0 floating-point constants.
+
+package main
+
+import "math"
+
+const (
+ z0 = 0.0
+ z1 = -0.0
+ z2 = -z0
+ z3 = -z2
+)
+
+var (
+ x0 float32 = z0
+ x1 float32 = z1
+ x2 float32 = z2
+ x3 float32 = z3
+
+ y0 float64 = z0
+ y1 float64 = z1
+ y2 float64 = z2
+ y3 float64 = z3
+)
+
+func test32(f float32) {
+ if f != 0 || math.Signbit(float64(f)) {
+ println("BUG: got", f, "want 0.0")
+ return
+ }
+}
+
+func test64(f float64) {
+ if f != 0 || math.Signbit(f) {
+ println("BUG: got", f, "want 0.0")
+ return
+ }
+}
+
+func main() {
+ if f := -x0; f != 0 || !math.Signbit(float64(f)) {
+ println("BUG: got", f, "want -0.0")
+ }
+
+ test32(-0.0)
+ test32(x0)
+ test32(x1)
+ test32(x2)
+ test32(x3)
+
+ if f := -y0; f != 0 || !math.Signbit(f) {
+ println("BUG: got", f, "want -0.0")
+ }
+
+ test64(-0.0)
+ test64(y0)
+ test64(y1)
+ test64(y2)
+ test64(y3)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12588.go b/gcc/testsuite/go.test/test/fixedbugs/issue12588.go
new file mode 100644
index 0000000..950ef36
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12588.go
@@ -0,0 +1,88 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests escape analysis for range of arrays.
+// Compiles but need not run. Inlining is disabled.
+
+package main
+
+type A struct {
+ b [3]uint64
+}
+
+type B struct {
+ b [3]*uint64
+}
+
+func f(a A) int {
+ for i, x := range &a.b {
+ if x != 0 {
+ return 64*i + int(x)
+ }
+ }
+ return 0
+}
+
+func g(a *A) int { // ERROR "a does not escape"
+ for i, x := range &a.b {
+ if x != 0 {
+ return 64*i + int(x)
+ }
+ }
+ return 0
+}
+
+func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
+ for i, x := range &a.b {
+ if i == 0 {
+ return x
+ }
+ }
+ return nil
+}
+
+func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
+ p := &a.b
+ for i, x := range p {
+ if i == 0 {
+ return x
+ }
+ }
+ return nil
+}
+
+// Seems like below should be level=1, not 0.
+func k(a B) *uint64 { // ERROR "leaking param: a to result ~r1 level=0"
+ for i, x := range &a.b {
+ if i == 0 {
+ return x
+ }
+ }
+ return nil
+}
+
+var sink *uint64
+
+func main() {
+ var a1, a2 A
+ var b1, b2, b3, b4 B
+ var x1, x2, x3, x4 uint64 // ERROR "moved to heap: x1" "moved to heap: x3"
+ b1.b[0] = &x1
+ b2.b[0] = &x2
+ b3.b[0] = &x3
+ b4.b[0] = &x4
+ f(a1)
+ g(&a2)
+ sink = h(&b1)
+ h(&b2)
+ sink = h2(&b1)
+ h2(&b4)
+ x1 = 17
+ println("*sink=", *sink) // Verify that sink addresses x1
+ x3 = 42
+ sink = k(b3)
+ println("*sink=", *sink) // Verify that sink addresses x3
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12621.go b/gcc/testsuite/go.test/test/fixedbugs/issue12621.go
new file mode 100644
index 0000000..379a362
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12621.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issues 12576 and 12621: Negative untyped floating point constants
+// with small magnitude round to 0, not negative zero.
+
+package main
+
+import "math"
+
+var m = -1e-10000
+
+func main() {
+ if math.Signbit(m) {
+ panic(m)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/p.go b/gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/p.go
new file mode 100644
index 0000000..e395071
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/p.go
@@ -0,0 +1,8 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+func Baz(f int) float64 {
+ return 1 / float64(int(1)<<(uint(f)))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/q.go b/gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/q.go
new file mode 100644
index 0000000..fd39c8a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12677.dir/q.go
@@ -0,0 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package q
+import "./p"
+func f() { println(p.Baz(2)) }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12677.go b/gcc/testsuite/go.test/test/fixedbugs/issue12677.go
new file mode 100644
index 0000000..6ad7161
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12677.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 12677: Type loss during export/import of inlined function body.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue12686.go b/gcc/testsuite/go.test/test/fixedbugs/issue12686.go
new file mode 100644
index 0000000..bde4255
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue12686.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// golang.org/issue/12686.
+// interesting because it's a non-constant but ideal value
+// and we used to incorrectly attach a constant Val to the Node.
+
+package p
+
+func f(i uint) uint {
+ x := []uint{1 << i}
+ return x[0]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue1304.go b/gcc/testsuite/go.test/test/fixedbugs/issue1304.go
new file mode 100644
index 0000000..9e0ca5a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue1304.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var a = 1
+
+func main() {
+ defer func() {
+ recover()
+ if a != 2 {
+ println("BUG a =", a)
+ }
+ }()
+ a = 2
+ b := a - a
+ c := 4
+ a = c / b
+ a = 3
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13160.go b/gcc/testsuite/go.test/test/fixedbugs/issue13160.go
new file mode 100644
index 0000000..c21ecf6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13160.go
@@ -0,0 +1,70 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+const N = 100000
+
+func main() {
+ // Allocate more Ps than processors. This raises
+ // the chance that we get interrupted by the OS
+ // in exactly the right (wrong!) place.
+ p := runtime.NumCPU()
+ runtime.GOMAXPROCS(2 * p)
+
+ // Allocate some pointers.
+ ptrs := make([]*int, p)
+ for i := 0; i < p; i++ {
+ ptrs[i] = new(int)
+ }
+
+ // Arena where we read and write pointers like crazy.
+ collider := make([]*int, p)
+
+ done := make(chan struct{}, 2*p)
+
+ // Start writers. They alternately write a pointer
+ // and nil to a slot in the collider.
+ for i := 0; i < p; i++ {
+ i := i
+ go func() {
+ for j := 0; j < N; j++ {
+ // Write a pointer using memmove.
+ copy(collider[i:i+1], ptrs[i:i+1])
+ // Write nil using memclr.
+ // (This is a magic loop that gets lowered to memclr.)
+ r := collider[i : i+1]
+ for k := range r {
+ r[k] = nil
+ }
+ }
+ done <- struct{}{}
+ }()
+ }
+ // Start readers. They read pointers from slots
+ // and make sure they are valid.
+ for i := 0; i < p; i++ {
+ i := i
+ go func() {
+ for j := 0; j < N; j++ {
+ var ptr [1]*int
+ copy(ptr[:], collider[i:i+1])
+ if ptr[0] != nil && ptr[0] != ptrs[i] {
+ panic(fmt.Sprintf("bad pointer read %p!", ptr[0]))
+ }
+ }
+ done <- struct{}{}
+ }()
+ }
+ for i := 0; i < 2*p; i++ {
+ <-done
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13162.go b/gcc/testsuite/go.test/test/fixedbugs/issue13162.go
new file mode 100644
index 0000000..f8b3150
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13162.go
@@ -0,0 +1,82 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that range loops over a string have the requisite side-effects.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func check(n int) {
+ var i int
+ var r rune
+
+ b := make([]byte, n)
+ for i = range b {
+ b[i] = byte(i + 1)
+ }
+ s := string(b)
+
+ // When n == 0, i is untouched by the range loop.
+ // Picking an initial value of -1 for i makes the
+ // "want" calculation below correct in all cases.
+ i = -1
+ for i = range s {
+ b[i] = s[i]
+ }
+ if want := n - 1; i != want {
+ fmt.Printf("index after range with side-effect = %d want %d\n", i, want)
+ os.Exit(1)
+ }
+
+ i = -1
+ r = '\x00'
+ for i, r = range s {
+ b[i] = byte(r)
+ }
+ if want := n - 1; i != want {
+ fmt.Printf("index after range with side-effect = %d want %d\n", i, want)
+ os.Exit(1)
+ }
+ if want := rune(n); r != want {
+ fmt.Printf("rune after range with side-effect = %q want %q\n", r, want)
+ os.Exit(1)
+ }
+
+ i = -1
+ // i is shadowed here, so its value should be unchanged.
+ for i := range s {
+ b[i] = s[i]
+ }
+ if want := -1; i != want {
+ fmt.Printf("index after range without side-effect = %d want %d\n", i, want)
+ os.Exit(1)
+ }
+
+ i = -1
+ r = -1
+ // i and r are shadowed here, so their values should be unchanged.
+ for i, r := range s {
+ b[i] = byte(r)
+ }
+ if want := -1; i != want {
+ fmt.Printf("index after range without side-effect = %d want %d\n", i, want)
+ os.Exit(1)
+ }
+ if want := rune(-1); r != want {
+ fmt.Printf("rune after range without side-effect = %q want %q\n", r, want)
+ os.Exit(1)
+ }
+}
+
+func main() {
+ check(0)
+ check(1)
+ check(15)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13169.go b/gcc/testsuite/go.test/test/fixedbugs/issue13169.go
new file mode 100644
index 0000000..03c52e2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13169.go
@@ -0,0 +1,49 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T struct {
+ a, b, c int
+}
+
+func usestack() {
+ usestack1(32)
+}
+func usestack1(d int) byte {
+ if d == 0 {
+ return 0
+ }
+ var b [1024]byte
+ usestack1(d - 1)
+ return b[3]
+}
+
+const n = 100000
+
+func main() {
+ c := make(chan interface{})
+ done := make(chan bool)
+
+ for i := 0; i < 10; i++ {
+ go func() {
+ for j := 0; j < n; j++ {
+ c <- new(T)
+ }
+ done <- true
+ }()
+ go func() {
+ for j := 0; j < n; j++ {
+ _ = (<-c).(*T)
+ usestack()
+ }
+ done <- true
+ }()
+ }
+ for i := 0; i < 20; i++ {
+ <-done
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13171.go b/gcc/testsuite/go.test/test/fixedbugs/issue13171.go
new file mode 100644
index 0000000..addb872
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13171.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Make sure the compiler knows that DUFFCOPY clobbers X0
+
+import "fmt"
+
+//go:noinline
+func f(x float64) float64 {
+ // y is allocated to X0
+ y := x + 5
+ // marshals z before y. Marshaling z
+ // calls DUFFCOPY.
+ return g(z, y)
+}
+
+//go:noinline
+func g(b [64]byte, y float64) float64 {
+ return y
+}
+
+var z [64]byte
+
+func main() {
+ got := f(5)
+ if got != 10 {
+ panic(fmt.Sprintf("want 10, got %f", got))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13248.go b/gcc/testsuite/go.test/test/fixedbugs/issue13248.go
new file mode 100644
index 0000000..e23ba47
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13248.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This program caused an infinite loop with the recursive-descent parser.
+
+package main
+
+func main() {
+ foo( // GCCGO_ERROR "undefined name"
+} // ERROR "unexpected }|expected operand|missing"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13261.go b/gcc/testsuite/go.test/test/fixedbugs/issue13261.go
new file mode 100644
index 0000000..a944f3a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13261.go
@@ -0,0 +1,29 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Taking the address of a parenthesized composite literal is permitted.
+
+package main
+
+type T struct{}
+
+func main() {
+ _ = &T{}
+ _ = &(T{})
+ _ = &((T{}))
+
+ _ = &struct{}{}
+ _ = &(struct{}{})
+ _ = &((struct{}{}))
+
+ switch (&T{}) {}
+ switch &(T{}) {}
+ switch &((T{})) {}
+
+ switch &struct{}{} {}
+ switch &(struct{}{}) {}
+ switch &((struct{}{})) {}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13262.go b/gcc/testsuite/go.test/test/fixedbugs/issue13262.go
new file mode 100644
index 0000000..8837c00
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13262.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 13262: cmd/compile: bogus "fallthrough
+// statement out of place" error
+
+package p
+
+func f() int {
+ var a int
+ switch a {
+ case 0:
+ return func() int { return 1 }()
+ fallthrough
+ default:
+ }
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13263.go b/gcc/testsuite/go.test/test/fixedbugs/issue13263.go
new file mode 100644
index 0000000..1933f2b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13263.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+var (
+ x uint
+ y = x
+ z = uintptr(y)
+ a = uint32(y)
+ b = uint64(y)
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13266.go b/gcc/testsuite/go.test/test/fixedbugs/issue13266.go
new file mode 100644
index 0000000..73c9e16
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13266.go
@@ -0,0 +1,10 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Offending character % must not be interpreted as
+// start of format verb when emitting error message.
+
+package% // ERROR "unexpected %|package name must be an identifier|after package clause|expected declaration"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13268.go b/gcc/testsuite/go.test/test/fixedbugs/issue13268.go
new file mode 100644
index 0000000..53a82d5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13268.go
@@ -0,0 +1,43 @@
+// +build gc
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test error message when EOF is encountered in the
+// middle of a BOM.
+//
+// Since the error requires an EOF, we cannot use the
+// errorcheckoutput mechanism.
+
+package main
+
+import (
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ // create source
+ f, err := ioutil.TempFile("", "issue13268-")
+ if err != nil {
+ log.Fatalf("could not create source file: %v", err)
+ }
+ f.Write([]byte("package p\n\nfunc \xef\xef")) // if this fails, we will die later
+ f.Close()
+ defer os.Remove(f.Name())
+
+ // compile and test output
+ cmd := exec.Command("go", "tool", "compile", f.Name())
+ out, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatalf("expected cmd/compile to fail")
+ }
+ if strings.HasPrefix(string(out), "illegal UTF-8 sequence") {
+ log.Fatalf("error %q not found", out)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13274.go b/gcc/testsuite/go.test/test/fixedbugs/issue13274.go
new file mode 100644
index 0000000..816bd9b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13274.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that we don't ignore EOF.
+
+package p
+
+var f = func() { // ERROR "unexpected EOF|expected .*}.*" \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13337.go b/gcc/testsuite/go.test/test/fixedbugs/issue13337.go
new file mode 100644
index 0000000..81f984b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13337.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 13337: The Go compiler limited how deeply embedded types
+// were searched for promoted fields and methods.
+
+package s
+
+type S0 struct{ f int }
+func (S0) m() {}
+
+type S1 struct{ S0 }
+type S2 struct{ S1 }
+type S3 struct{ S2 }
+type S4 struct{ S3 }
+type S5 struct{ S4 }
+type S6 struct{ S5 }
+type S7 struct{ S6 }
+type S8 struct{ S7 }
+type S9 struct{ S8 }
+type S10 struct{ S9 }
+type S11 struct{ S10 }
+type S12 struct{ S11 }
+type S13 struct{ S12 }
+
+var _ = S13{}.f
+var _ = S13.m
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13365.go b/gcc/testsuite/go.test/test/fixedbugs/issue13365.go
new file mode 100644
index 0000000..31a663e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13365.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 13365: confusing error message (array vs slice)
+
+package main
+
+var t struct{}
+
+func main() {
+ _ = []int{-1: 0} // ERROR "index must be non\-negative integer constant|index expression is negative"
+ _ = [10]int{-1: 0} // ERROR "index must be non\-negative integer constant|index expression is negative"
+ _ = [...]int{-1: 0} // ERROR "index must be non\-negative integer constant|index expression is negative"
+
+ _ = []int{100: 0}
+ _ = [10]int{100: 0} // ERROR "array index 100 out of bounds|out of range"
+ _ = [...]int{100: 0}
+
+ _ = []int{t} // ERROR "cannot use .* as type int in slice literal|incompatible type"
+ _ = [10]int{t} // ERROR "cannot use .* as type int in array literal|incompatible type"
+ _ = [...]int{t} // ERROR "cannot use .* as type int in array literal|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13415.go b/gcc/testsuite/go.test/test/fixedbugs/issue13415.go
new file mode 100644
index 0000000..4c4655e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13415.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that error message regarding := appears on
+// correct line (and not on the line of the 2nd :=).
+
+package p
+
+func f() {
+ select {
+ case x, x := <-func() chan int { // ERROR "x repeated on left side of :=|redefinition|declared but not used"
+ c := make(chan int)
+ return c
+ }():
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13471.go b/gcc/testsuite/go.test/test/fixedbugs/issue13471.go
new file mode 100644
index 0000000..9069412
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13471.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests for golang.org/issue/13471
+
+package main
+
+func main() {
+ const _ int64 = 1e646456992 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ int32 = 1e64645699 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ int16 = 1e6464569 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ int8 = 1e646456 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ int = 1e64645 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+
+ const _ uint64 = 1e646456992 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ uint32 = 1e64645699 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ uint16 = 1e6464569 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ uint8 = 1e646456 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+ const _ uint = 1e64645 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+
+ const _ rune = 1e64645 // ERROR "integer too large|floating-point constant truncated to integer|exponent too large"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13480.go b/gcc/testsuite/go.test/test/fixedbugs/issue13480.go
new file mode 100644
index 0000000..cd2f05d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13480.go
@@ -0,0 +1,38 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that comparisons of slice/map/func values against converted nil
+// values are properly rejected.
+
+package p
+
+func bug() {
+ type S []byte
+ type M map[int]int
+ type F func()
+
+ var s S
+ var m M
+ var f F
+
+ _ = s == S(nil) // ERROR "compare.*to nil"
+ _ = S(nil) == s // ERROR "compare.*to nil"
+ switch s {
+ case S(nil): // ERROR "compare.*to nil"
+ }
+
+ _ = m == M(nil) // ERROR "compare.*to nil"
+ _ = M(nil) == m // ERROR "compare.*to nil"
+ switch m {
+ case M(nil): // ERROR "compare.*to nil"
+ }
+
+ _ = f == F(nil) // ERROR "compare.*to nil"
+ _ = F(nil) == f // ERROR "compare.*to nil"
+ switch f {
+ case F(nil): // ERROR "compare.*to nil"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13485.go b/gcc/testsuite/go.test/test/fixedbugs/issue13485.go
new file mode 100644
index 0000000..a9beea1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13485.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var (
+ _ [10]int
+ _ [10.0]int
+ _ [float64(10)]int // ERROR "invalid array bound"
+ _ [10 + 0i]int
+ _ [complex(10, 0)]int
+ _ [complex128(complex(10, 0))]int // ERROR "invalid array bound"
+ _ ['a']int
+ _ [rune(65)]int
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13539.go b/gcc/testsuite/go.test/test/fixedbugs/issue13539.go
new file mode 100644
index 0000000..72c3ab0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13539.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that a label named like a package is recognized
+// as a label rather than a package and that the package
+// remains unused.
+
+package main
+
+import "math" // ERROR "imported and not used"
+
+func main() {
+math:
+ for {
+ break math
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13684.go b/gcc/testsuite/go.test/test/fixedbugs/issue13684.go
new file mode 100644
index 0000000..a1d8856
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13684.go
@@ -0,0 +1,17 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that a label name matching a constant name
+// is permitted.
+
+package main
+
+const labelname = 1
+
+func main() {
+ goto labelname
+labelname:
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/burnin.go b/gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/burnin.go
new file mode 100644
index 0000000..5125639
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/burnin.go
@@ -0,0 +1,19 @@
+package burnin
+
+type sendCmdFunc func(string)
+
+func sendCommand(c string) {}
+
+func NewSomething() {
+ // This works...
+ // var sendCmd sendCmdFunc
+ // sendCmd = sendCommand
+
+ // So does this...
+ //sendCmd := sendCmdFunc(sendCommand)
+
+ // This fails...
+ sendCmd := sendCommand
+
+ _ = sendCmd
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/main.go
new file mode 100644
index 0000000..2512b93
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13777.dir/main.go
@@ -0,0 +1,11 @@
+// build
+
+package main
+
+import (
+ x "./burnin"
+)
+
+func main() {
+ x.NewSomething()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13777.go b/gcc/testsuite/go.test/test/fixedbugs/issue13777.go
new file mode 100644
index 0000000..8f83c13
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13777.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13799.go b/gcc/testsuite/go.test/test/fixedbugs/issue13799.go
new file mode 100644
index 0000000..fbdd4c3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13799.go
@@ -0,0 +1,190 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test, using compiler diagnostic flags, that the escape analysis is working.
+// Compiles but does not run. Inlining is disabled.
+// Registerization is disabled too (-N), which should
+// have no effect on escape analysis.
+
+package main
+
+import "fmt"
+
+func main() {
+ // Just run test over and over again. This main func is just for
+ // convenience; if test were the main func, we could also trigger
+ // the panic just by running the program over and over again
+ // (sometimes it takes 1 time, sometimes it takes ~4,000+).
+ for iter := 0; ; iter++ {
+ if iter%50 == 0 {
+ fmt.Println(iter) // ERROR "iter escapes to heap$" "... argument does not escape$"
+ }
+ test1(iter)
+ test2(iter)
+ test3(iter)
+ test4(iter)
+ test5(iter)
+ test6(iter)
+ }
+}
+
+func test1(iter int) {
+
+ const maxI = 500
+ m := make(map[int][]int) // ERROR "make\(map\[int\]\[\]int\) escapes to heap$"
+
+ // The panic seems to be triggered when m is modified inside a
+ // closure that is both recursively called and reassigned to in a
+ // loop.
+
+ // Cause of bug -- escape of closure failed to escape (shared) data structures
+ // of map. Assign to fn declared outside of loop triggers escape of closure.
+ // Heap -> stack pointer eventually causes badness when stack reallocation
+ // occurs.
+
+ var fn func() // ERROR "moved to heap: fn$"
+ for i := 0; i < maxI; i++ { // ERROR "moved to heap: i$"
+ // var fn func() // this makes it work, because fn stays off heap
+ j := 0 // ERROR "moved to heap: j$"
+ fn = func() { // ERROR "func literal escapes to heap$"
+ m[i] = append(m[i], 0)
+ if j < 25 {
+ j++
+ fn()
+ }
+ }
+ fn()
+ }
+
+ if len(m) != maxI {
+ panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
+ }
+}
+
+func test2(iter int) {
+
+ const maxI = 500
+ m := make(map[int][]int) // ERROR "make\(map\[int\]\[\]int\) does not escape$"
+
+ // var fn func()
+ for i := 0; i < maxI; i++ {
+ var fn func() // this makes it work, because fn stays off heap
+ j := 0
+ fn = func() { // ERROR "func literal does not escape$"
+ m[i] = append(m[i], 0)
+ if j < 25 {
+ j++
+ fn()
+ }
+ }
+ fn()
+ }
+
+ if len(m) != maxI {
+ panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
+ }
+}
+
+func test3(iter int) {
+
+ const maxI = 500
+ var x int // ERROR "moved to heap: x$"
+ m := &x
+
+ var fn func() // ERROR "moved to heap: fn$"
+ for i := 0; i < maxI; i++ {
+ // var fn func() // this makes it work, because fn stays off heap
+ j := 0 // ERROR "moved to heap: j$"
+ fn = func() { // ERROR "func literal escapes to heap$"
+ if j < 100 {
+ j++
+ fn()
+ } else {
+ *m = *m + 1
+ }
+ }
+ fn()
+ }
+
+ if *m != maxI {
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
+ }
+}
+
+func test4(iter int) {
+
+ const maxI = 500
+ var x int
+ m := &x
+
+ // var fn func()
+ for i := 0; i < maxI; i++ {
+ var fn func() // this makes it work, because fn stays off heap
+ j := 0
+ fn = func() { // ERROR "func literal does not escape$"
+ if j < 100 {
+ j++
+ fn()
+ } else {
+ *m = *m + 1
+ }
+ }
+ fn()
+ }
+
+ if *m != maxI {
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
+ }
+}
+
+type str struct {
+ m *int
+}
+
+func recur1(j int, s *str) { // ERROR "s does not escape"
+ if j < 100 {
+ j++
+ recur1(j, s)
+ } else {
+ *s.m++
+ }
+}
+
+func test5(iter int) {
+
+ const maxI = 500
+ var x int // ERROR "moved to heap: x$"
+ m := &x
+
+ var fn *str
+ for i := 0; i < maxI; i++ {
+ // var fn *str // this makes it work, because fn stays off heap
+ fn = &str{m} // ERROR "&str{...} escapes to heap"
+ recur1(0, fn)
+ }
+
+ if *m != maxI {
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
+ }
+}
+
+func test6(iter int) {
+
+ const maxI = 500
+ var x int
+ m := &x
+
+ // var fn *str
+ for i := 0; i < maxI; i++ {
+ var fn *str // this makes it work, because fn stays off heap
+ fn = &str{m} // ERROR "&str{...} does not escape"
+ recur1(0, fn)
+ }
+
+ if *m != maxI {
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13821.go b/gcc/testsuite/go.test/test/fixedbugs/issue13821.go
new file mode 100644
index 0000000..187e4b4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13821.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 13821. Compiler rejected "bool(true)" as not a constant.
+
+package p
+
+const (
+ A = true
+ B = bool(A)
+ C = bool(true)
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue13821b.go b/gcc/testsuite/go.test/test/fixedbugs/issue13821b.go
new file mode 100644
index 0000000..df68e8d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue13821b.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 13821. Additional regress tests.
+
+package p
+
+type B bool
+type B2 bool
+
+var b B
+var b2 B2
+var x1 = b && 1 < 2 // x1 has type B, not ideal bool
+var x2 = 1 < 2 && b // x2 has type B, not ideal bool
+var x3 = b && b2 // ERROR "mismatched types B and B2|incompatible types"
+var x4 = x1 && b2 // ERROR "mismatched types B and B2|incompatible types"
+var x5 = x2 && b2 // ERROR "mismatched types B and B2|incompatible types"
+var x6 = b2 && x1 // ERROR "mismatched types B2 and B|incompatible types"
+var x7 = b2 && x2 // ERROR "mismatched types B2 and B|incompatible types"
+
+var x8 = b && !B2(true) // ERROR "mismatched types B and B2|incompatible types"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14006.go b/gcc/testsuite/go.test/test/fixedbugs/issue14006.go
new file mode 100644
index 0000000..9cad2b4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14006.go
@@ -0,0 +1,67 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Literals that happen to resolve to named constants
+// may be used as label names (see issue 13684). Make
+// sure that other literals don't crash the compiler.
+
+package main
+
+const labelname = 1
+
+func main() {
+ goto labelname
+labelname:
+}
+
+func f() {
+ var x int
+ switch x {
+ case 1:
+ 2: // ERROR "unexpected :|expected .*;.* or .*}.* or newline|value computed is not used"
+ case 2:
+ }
+
+ switch x {
+ case 1:
+ 2: ; // ERROR "unexpected :|expected .*;.* or .*}.* or newline|value computed is not used"
+ case 2:
+ }
+
+ var y string
+ switch y {
+ case "foo":
+ "bar": // ERROR "unexpected :|expected .*;.* or .*}.* or newline|value computed is not used"
+ case "bar":
+ }
+
+ switch y {
+ case "foo":
+ "bar": ; // ERROR "unexpected :|expected .*;.* or .*}.* or newline|value computed is not used"
+ case "bar":
+ }
+
+ var z bool
+ switch {
+ case z:
+ labelname: // ERROR "missing statement after label"
+ case false:
+ }
+}
+
+func g() {
+ var z bool
+ switch {
+ case z:
+ labelname: // ERROR "label labelname defined and not used|previous definition|defined and not used"
+ }
+
+ switch {
+ case z:
+ labelname: ; // ERROR "label labelname already defined at LINE-5|label .*labelname.* already defined"
+ case false:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14010.go b/gcc/testsuite/go.test/test/fixedbugs/issue14010.go
new file mode 100644
index 0000000..0b23334
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14010.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that built-in types don't get printed with
+// (empty) package qualification.
+
+package main
+
+func main() {
+ true = false // ERROR "cannot assign to true|invalid left hand side"
+ byte = 0 // ERROR "not an expression|invalid left hand side|invalid use of type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14136.go b/gcc/testsuite/go.test/test/fixedbugs/issue14136.go
new file mode 100644
index 0000000..38308cd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14136.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that > 10 non-syntax errors on the same line
+// don't lead to early exit. Specifically, here test
+// that we see the initialization error for variable
+// s.
+
+package main
+
+type T struct{}
+
+func main() {
+ t := T{X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1} // ERROR "unknown field 'X' in struct literal of type T|unknown field .*X.* in .*T.*"
+ var s string = 1 // ERROR "cannot use 1|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/a.go
new file mode 100644
index 0000000..bf03051
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/a.go
@@ -0,0 +1,47 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+// F is an exported function, small enough to be inlined.
+// It defines a local interface with an unexported method
+// f, which will appear with a package-qualified method
+// name in the export data.
+func F(x interface{}) bool {
+ _, ok := x.(interface {
+ f()
+ })
+ return ok
+}
+
+// Like F but with the unexported interface method f
+// defined via an embedded interface t. The compiler
+// always flattens embedded interfaces so there should
+// be no difference between F and G. Alas, currently
+// G is not inlineable (at least via export data), so
+// the issue is moot, here.
+func G(x interface{}) bool {
+ type t0 interface {
+ f()
+ }
+ _, ok := x.(interface {
+ t0
+ })
+ return ok
+}
+
+// Like G but now the embedded interface is declared
+// at package level. This function is inlineable via
+// export data. The export data representation is like
+// for F.
+func H(x interface{}) bool {
+ _, ok := x.(interface {
+ t1
+ })
+ return ok
+}
+
+type t1 interface {
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/main.go
new file mode 100644
index 0000000..bcc6a63
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14164.dir/main.go
@@ -0,0 +1,12 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Verify that we can import package "a" containing an inlineable
+// function F that declares a local interface with a non-exported
+// method f.
+import _ "./a"
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14164.go b/gcc/testsuite/go.test/test/fixedbugs/issue14164.go
new file mode 100644
index 0000000..5247599
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14164.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/a.go
new file mode 100644
index 0000000..f1e57ef
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/a.go
@@ -0,0 +1,14 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var S struct {
+ Str string `tag`
+}
+
+func F() string {
+ v := S
+ return v.Str
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/b.go
new file mode 100644
index 0000000..a2280a3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14331.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func G() string {
+ return a.F()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14331.go b/gcc/testsuite/go.test/test/fixedbugs/issue14331.go
new file mode 100644
index 0000000..b8ee2fb1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14331.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Inline function misses struct tags.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14405.go b/gcc/testsuite/go.test/test/fixedbugs/issue14405.go
new file mode 100644
index 0000000..94592fd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14405.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Mention of field with large offset in struct literal causes crash
+package p
+
+type T struct {
+ Slice [1 << 20][]int
+ Ptr *int
+}
+
+func New(p *int) *T {
+ return &T{Ptr: p}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14520.go b/gcc/testsuite/go.test/test/fixedbugs/issue14520.go
new file mode 100644
index 0000000..0b840ff
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14520.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package f
+
+import /* // ERROR "import path" */ `
+bogus`
+
+func f(x int /* // GC_ERROR "unexpected newline"
+
+*/) // GCCGO_ERROR "expected .*\).*|expected declaration"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14540.go b/gcc/testsuite/go.test/test/fixedbugs/issue14540.go
new file mode 100644
index 0000000..62b17a0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14540.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x int) {
+ switch x {
+ case 0:
+ fallthrough
+ ; // ok
+ case 1:
+ fallthrough // ERROR "fallthrough statement out of place"
+ {}
+ case 2:
+ fallthrough // ERROR "cannot fallthrough"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14553.go b/gcc/testsuite/go.test/test/fixedbugs/issue14553.go
new file mode 100644
index 0000000..d7ebb12
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14553.go
@@ -0,0 +1,45 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test checks if the compiler's internal constant
+// arithmetic correctly rounds denormal float32 values.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+func main() {
+ for _, t := range []struct {
+ value float32
+ bits uint32
+ }{
+ {0e+00, 0x00000000},
+ {1e-46, 0x00000000},
+ {0.5e-45, 0x00000000},
+ {0.8e-45, 0x00000001},
+ {1e-45, 0x00000001},
+ {2e-45, 0x00000001},
+ {3e-45, 0x00000002},
+ {4e-45, 0x00000003},
+ {5e-45, 0x00000004},
+ {6e-45, 0x00000004},
+ {7e-45, 0x00000005},
+ {8e-45, 0x00000006},
+ {9e-45, 0x00000006},
+ {1.0e-44, 0x00000007},
+ {1.1e-44, 0x00000008},
+ {1.2e-44, 0x00000009},
+ } {
+ got := math.Float32bits(t.value)
+ want := t.bits
+ if got != want {
+ panic(fmt.Sprintf("bits(%g) = 0x%08x; want 0x%08x", t.value, got, want))
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14591.go b/gcc/testsuite/go.test/test/fixedbugs/issue14591.go
new file mode 100644
index 0000000..626fbbc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14591.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test to make sure we don't think values are dead
+// when they are assigned to a PPARAMOUT slot before
+// the last GC safepoint.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+// When a T is deallocated, T[1] is certain to
+// get clobbered (the runtime writes 0xdeaddeaddeaddead there).
+type T [4]int
+
+func f() (r, s *T) {
+ r = &T{0x30, 0x31, 0x32, 0x33}
+ runtime.GC()
+ s = &T{0x40, 0x41, 0x42, 0x43}
+ runtime.GC()
+ return
+}
+
+func main() {
+ r, s := f()
+ if r[1] != 0x31 {
+ fmt.Printf("bad r[1], want 0x31 got %x\n", r[1])
+ }
+ if s[1] != 0x41 {
+ fmt.Printf("bad s[1], want 0x41 got %x\n", s[1])
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14636.go b/gcc/testsuite/go.test/test/fixedbugs/issue14636.go
new file mode 100644
index 0000000..06fd193
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14636.go
@@ -0,0 +1,43 @@
+// +build !nacl,!js,!android,gc
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "log"
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ checkLinkOutput("", "-B argument must start with 0x")
+ checkLinkOutput("0", "-B argument must start with 0x")
+ checkLinkOutput("0x", "usage")
+ checkLinkOutput("0x0", "-B argument must have even number of digits")
+ checkLinkOutput("0x00", "usage")
+ checkLinkOutput("0xYZ", "-B argument contains invalid hex digit")
+ checkLinkOutput("0x"+strings.Repeat("00", 32), "usage")
+ checkLinkOutput("0x"+strings.Repeat("00", 33), "-B option too long (max 32 digits)")
+}
+
+func checkLinkOutput(buildid string, message string) {
+ cmd := exec.Command("go", "tool", "link", "-B", buildid)
+ out, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatalf("expected cmd/link to fail")
+ }
+
+ firstLine := string(bytes.SplitN(out, []byte("\n"), 2)[0])
+ if strings.HasPrefix(firstLine, "panic") {
+ log.Fatalf("cmd/link panicked:\n%s", out)
+ }
+
+ if !strings.Contains(firstLine, message) {
+ log.Fatalf("cmd/link output did not include expected message %q: %s", message, firstLine)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14646.go b/gcc/testsuite/go.test/test/fixedbugs/issue14646.go
new file mode 100644
index 0000000..96a6854
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14646.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime"
+
+func main() {
+ var file string
+ var line int
+ func() {
+ defer func() {
+ _, file, line, _ = runtime.Caller(1)
+ }()
+ }() // this is the expected line
+ const EXPECTED = 18
+ if line != EXPECTED {
+ println("Expected line =", EXPECTED, "but got line =", line, "and file =", file)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14651.go b/gcc/testsuite/go.test/test/fixedbugs/issue14651.go
new file mode 100644
index 0000000..4c756e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14651.go
@@ -0,0 +1,71 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test checks if the compiler's internal constant
+// arithmetic correctly rounds up floating-point values
+// that become the smallest denormal value.
+//
+// See also related issue 14553 and test issue14553.go.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+const (
+ p149 = 1.0 / (1 << 149) // 1p-149
+ p500 = 1.0 / (1 << 500) // 1p-500
+ p1074 = p500 * p500 / (1<<74) // 1p-1074
+)
+
+const (
+ m0000p149 = 0x0 / 16.0 * p149 // = 0.0000p-149
+ m1000p149 = 0x8 / 16.0 * p149 // = 0.1000p-149
+ m1001p149 = 0x9 / 16.0 * p149 // = 0.1001p-149
+ m1011p149 = 0xb / 16.0 * p149 // = 0.1011p-149
+ m1100p149 = 0xc / 16.0 * p149 // = 0.1100p-149
+
+ m0000p1074 = 0x0 / 16.0 * p1074 // = 0.0000p-1074
+ m1000p1074 = 0x8 / 16.0 * p1074 // = 0.1000p-1074
+ m1001p1074 = 0x9 / 16.0 * p1074 // = 0.1001p-1074
+ m1011p1074 = 0xb / 16.0 * p1074 // = 0.1011p-1074
+ m1100p1074 = 0xc / 16.0 * p1074 // = 0.1100p-1074
+)
+
+func main() {
+ test32(float32(m0000p149), f32(m0000p149))
+ test32(float32(m1000p149), f32(m1000p149))
+ test32(float32(m1001p149), f32(m1001p149))
+ test32(float32(m1011p149), f32(m1011p149))
+ test32(float32(m1100p149), f32(m1100p149))
+
+ test64(float64(m0000p1074), f64(m0000p1074))
+ test64(float64(m1000p1074), f64(m1000p1074))
+ test64(float64(m1001p1074), f64(m1001p1074))
+ test64(float64(m1011p1074), f64(m1011p1074))
+ test64(float64(m1100p1074), f64(m1100p1074))
+}
+
+func f32(x float64) float32 { return float32(x) }
+func f64(x float64) float64 { return float64(x) }
+
+func test32(a, b float32) {
+ abits := math.Float32bits(a)
+ bbits := math.Float32bits(b)
+ if abits != bbits {
+ panic(fmt.Sprintf("%08x != %08x\n", abits, bbits))
+ }
+}
+
+func test64(a, b float64) {
+ abits := math.Float64bits(a)
+ bbits := math.Float64bits(b)
+ if abits != bbits {
+ panic(fmt.Sprintf("%016x != %016x\n", abits, bbits))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14652.go b/gcc/testsuite/go.test/test/fixedbugs/issue14652.go
new file mode 100644
index 0000000..d53b412
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14652.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x any // ERROR "undefined: any|undefined type .*any.*"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14725.go b/gcc/testsuite/go.test/test/fixedbugs/issue14725.go
new file mode 100644
index 0000000..49f3fbc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14725.go
@@ -0,0 +1,57 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func f1() (x int) {
+ for {
+ defer func() {
+ recover()
+ x = 1
+ }()
+ panic(nil)
+ }
+}
+
+var sink *int
+
+func f2() (x int) {
+ sink = &x
+ defer func() {
+ recover()
+ x = 1
+ }()
+ panic(nil)
+}
+
+func f3(b bool) (x int) {
+ sink = &x
+ defer func() {
+ recover()
+ x = 1
+ }()
+ if b {
+ panic(nil)
+ }
+ return
+}
+
+func main() {
+ if x := f1(); x != 1 {
+ panic(fmt.Sprintf("f1 returned %d, wanted 1", x))
+ }
+ if x := f2(); x != 1 {
+ panic(fmt.Sprintf("f2 returned %d, wanted 1", x))
+ }
+ if x := f3(true); x != 1 {
+ panic(fmt.Sprintf("f3(true) returned %d, wanted 1", x))
+ }
+ if x := f3(false); x != 1 {
+ panic(fmt.Sprintf("f3(false) returned %d, wanted 1", x))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14729.go b/gcc/testsuite/go.test/test/fixedbugs/issue14729.go
new file mode 100644
index 0000000..9b30fd2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14729.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 14729: structs cannot embed unsafe.Pointer per the spec.
+
+package main
+
+import "unsafe"
+
+type s struct { unsafe.Pointer } // ERROR "embedded type cannot be a pointer|embedded type may not be a pointer"
+type s1 struct { p unsafe.Pointer }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue14988.go b/gcc/testsuite/go.test/test/fixedbugs/issue14988.go
new file mode 100644
index 0000000..4ddc7e7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue14988.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 14988: defining a map with an invalid forward declaration array
+// key doesn't cause a fatal.
+
+package main
+
+type m map[k]int // ERROR "invalid map key type"
+type k [1]m
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15002.go b/gcc/testsuite/go.test/test/fixedbugs/issue15002.go
new file mode 100644
index 0000000..936105e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15002.go
@@ -0,0 +1,132 @@
+// run
+// +build amd64
+// +build linux darwin
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "syscall"
+)
+
+// Use global variables so the compiler
+// doesn't know that they are constants.
+var p = syscall.Getpagesize()
+var zero = 0
+var one = 1
+
+func main() {
+ // Allocate 2 pages of memory.
+ b, err := syscall.Mmap(-1, 0, 2*p, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
+ if err != nil {
+ panic(err)
+ }
+ // Mark the second page as faulting.
+ err = syscall.Mprotect(b[p:], syscall.PROT_NONE)
+ if err != nil {
+ panic(err)
+ }
+ // Get a slice pointing to the last byte of the good page.
+ x := b[p-one : p]
+
+ test16(x)
+ test16i(x, 0)
+ test32(x)
+ test32i(x, 0)
+ test64(x)
+ test64i(x, 0)
+}
+
+func test16(x []byte) uint16 {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("no fault or bounds check failure happened")
+ }
+ s := fmt.Sprintf("%s", r)
+ if s != "runtime error: index out of range [1] with length 1" {
+ panic("bad panic: " + s)
+ }
+ }()
+ // Try to read 2 bytes from x.
+ return uint16(x[0]) | uint16(x[1])<<8
+
+ // We expect to get an "index out of range" error from x[1].
+ // If we promote the first load to a 2-byte load, it will segfault, which we don't want.
+}
+
+func test16i(x []byte, i int) uint16 {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("no fault or bounds check failure happened")
+ }
+ s := fmt.Sprintf("%s", r)
+ if s != "runtime error: index out of range [1] with length 1" {
+ panic("bad panic: " + s)
+ }
+ }()
+ return uint16(x[i]) | uint16(x[i+1])<<8
+}
+
+func test32(x []byte) uint32 {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("no fault or bounds check failure happened")
+ }
+ s := fmt.Sprintf("%s", r)
+ if s != "runtime error: index out of range [1] with length 1" {
+ panic("bad panic: " + s)
+ }
+ }()
+ return uint32(x[0]) | uint32(x[1])<<8 | uint32(x[2])<<16 | uint32(x[3])<<24
+}
+
+func test32i(x []byte, i int) uint32 {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("no fault or bounds check failure happened")
+ }
+ s := fmt.Sprintf("%s", r)
+ if s != "runtime error: index out of range [1] with length 1" {
+ panic("bad panic: " + s)
+ }
+ }()
+ return uint32(x[i]) | uint32(x[i+1])<<8 | uint32(x[i+2])<<16 | uint32(x[i+3])<<24
+}
+
+func test64(x []byte) uint64 {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("no fault or bounds check failure happened")
+ }
+ s := fmt.Sprintf("%s", r)
+ if s != "runtime error: index out of range [1] with length 1" {
+ panic("bad panic: " + s)
+ }
+ }()
+ return uint64(x[0]) | uint64(x[1])<<8 | uint64(x[2])<<16 | uint64(x[3])<<24 |
+ uint64(x[4])<<32 | uint64(x[5])<<40 | uint64(x[6])<<48 | uint64(x[7])<<56
+}
+
+func test64i(x []byte, i int) uint64 {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("no fault or bounds check failure happened")
+ }
+ s := fmt.Sprintf("%s", r)
+ if s != "runtime error: index out of range [1] with length 1" {
+ panic("bad panic: " + s)
+ }
+ }()
+ return uint64(x[i+0]) | uint64(x[i+1])<<8 | uint64(x[i+2])<<16 | uint64(x[i+3])<<24 |
+ uint64(x[i+4])<<32 | uint64(x[i+5])<<40 | uint64(x[i+6])<<48 | uint64(x[i+7])<<56
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15013.go b/gcc/testsuite/go.test/test/fixedbugs/issue15013.go
new file mode 100644
index 0000000..9e218e6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15013.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// CL 21202 introduced a compiler crash in the handling of a varargs
+// function in the same recursive group as a function that calls it.
+// Nothing in the standard library caught the problem, so adding a test.
+
+package p
+
+func F1(p *int, a ...*int) (int, *int) {
+ if p == nil {
+ return F2(), a[0]
+ }
+ return 0, a[0]
+}
+
+func F2() int {
+ var i0, i1 int
+ a, _ := F1(&i0, &i1)
+ return a
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15039.go b/gcc/testsuite/go.test/test/fixedbugs/issue15039.go
new file mode 100644
index 0000000..85d9e83
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15039.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ const fffd = "\uFFFD"
+
+ // runtime.intstring used to convert int64 to rune without checking
+ // for truncation.
+ u := uint64(0x10001f4a9)
+ big := string(u)
+ if big != fffd {
+ panic("big != bad")
+ }
+
+ // cmd/compile used to require integer constants to fit into an "int".
+ const huge = string(1<<100)
+ if huge != fffd {
+ panic("huge != bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15042.go b/gcc/testsuite/go.test/test/fixedbugs/issue15042.go
new file mode 100644
index 0000000..85d5d6c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15042.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Exchanging two struct fields was compiled incorrectly.
+
+package main
+
+type S struct {
+ i int
+}
+
+func F(c bool, s1, s2 S) (int, int) {
+ if c {
+ s1.i, s2.i = s2.i, s1.i
+ }
+ return s1.i, s2.i
+}
+
+func main() {
+ i, j := F(true, S{1}, S{20})
+ if i != 20 || j != 1 {
+ panic(i+j)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/exp.go b/gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/exp.go
new file mode 100644
index 0000000..e6041e6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/exp.go
@@ -0,0 +1,24 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package exp
+
+func Exported(x int) int {
+ return inlined(x)
+}
+
+func inlined(x int) int {
+ y := 0
+ switch {
+ case x > 0:
+ y += 5
+ return 0 + y
+ case x < 1:
+ y += 6
+ fallthrough
+ default:
+ y += 7
+ return 2 + y
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/main.go
new file mode 100644
index 0000000..96790da
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15071.dir/main.go
@@ -0,0 +1,14 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "os"
+import "./exp"
+
+func main() {
+ _ = exp.Exported(len(os.Args))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15071.go b/gcc/testsuite/go.test/test/fixedbugs/issue15071.go
new file mode 100644
index 0000000..af6f134
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15071.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15084.go b/gcc/testsuite/go.test/test/fixedbugs/issue15084.go
new file mode 100644
index 0000000..7eb294e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15084.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x
+
+type T struct {
+ i int
+ e interface{}
+}
+
+func (t *T) F() bool {
+ if t.i != 0 {
+ return false
+ }
+ _, ok := t.e.(string)
+ return ok
+}
+
+var x int
+
+func g(t *T) {
+ if t.F() || true {
+ if t.F() {
+ x = 0
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15141.go b/gcc/testsuite/go.test/test/fixedbugs/issue15141.go
new file mode 100644
index 0000000..752f530
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15141.go
@@ -0,0 +1,33 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ a := f(1, 99)
+ b := g(0xFFFFFFe, 98)
+ c := h(0xFFFFFFe, 98)
+ println(a[1], b[1], c[1], a[0xFFFFFFe], b[0xFFFFFFe], c[0xFFFFFFe])
+}
+
+//go:noinline
+func f(i, y int) (a [0xFFFFFFF]byte) {
+ a[i] = byte(y)
+ return
+}
+
+//go:noinline
+func g(i, y int) [0xFFFFFFF]byte {
+ var a [0xFFFFFFF]byte
+ a[i] = byte(y)
+ return a
+}
+
+//go:noinline
+func h(i, y int) (a [0xFFFFFFF]byte) {
+ a[i] = byte(y)
+ return a
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15175.go b/gcc/testsuite/go.test/test/fixedbugs/issue15175.go
new file mode 100644
index 0000000..55a8f7d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15175.go
@@ -0,0 +1,66 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure unsigned shift results get sign-extended correctly.
+package main
+
+import "fmt"
+
+func main() {
+ failed := false
+ a6 := uint8(253)
+ if got := a6 >> 0; got != 253 {
+ fmt.Printf("uint8(253)>>0 = %v, wanted 253\n", got)
+ failed = true
+ }
+ if got := f1(0, 2, 1, 0, 0, 1, true); got != 255 {
+ fmt.Printf("f1(...) = %v, wanted 255\n", got)
+ failed = true
+ }
+ if got := f2(1); got != 242 {
+ fmt.Printf("f2(...) = %v, wanted 242\n", got)
+ failed = true
+ }
+ if got := f3(false, 0, 0); got != 254 {
+ fmt.Printf("f3(...) = %v, wanted 254\n", got)
+ failed = true
+ }
+ if failed {
+ panic("bad")
+ }
+}
+
+func f1(a1 uint, a2 int8, a3 int8, a4 int8, a5 uint8, a6 int, a7 bool) uint8 {
+ a5--
+ a4 += (a2 << a1 << 2) | (a4 ^ a4<<(a1&a1)) - a3 // int8
+ a6 -= a6 >> (2 + uint32(a2)>>3) // int
+ a1 += a1 // uint
+ a3 *= a4 << (a1 | a1) << (uint16(3) >> 2 & (1 - 0) & (uint16(1) << a5 << 3)) // int8
+ a7 = a7 || ((a2 == a4) || (a7 && a7) || ((a5 == a5) || (a7 || a7))) // bool
+ return a5 >> a1
+}
+
+func f2(a1 uint8) uint8 {
+ a1--
+ a1--
+ a1 -= a1 + (a1 << 1) - (a1*a1*a1)<<(2-0+(3|3)-1) // uint8
+ v1 := 0 * ((2 * 1) ^ 1) & ((uint(0) >> a1) + (2+0)*(uint(2)+0)) // uint
+ _ = v1
+ return a1 >> (((2 ^ 2) >> (v1 | 2)) + 0)
+}
+
+func f3(a1 bool, a2 uint, a3 int64) uint8 {
+ a3--
+ v1 := 1 & (2 & 1 * (1 ^ 2) & (uint8(3*1) >> 0)) // uint8
+ _ = v1
+ v1 += v1 - (v1 >> a2) + (v1 << (a2 ^ a2) & v1) // uint8
+ v1 *= v1 // uint8
+ a3--
+ v1 += v1 & v1 // uint8
+ v1--
+ v1 = ((v1 << 0) | v1>>0) + v1 // uint8
+ return v1 >> 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15252.go b/gcc/testsuite/go.test/test/fixedbugs/issue15252.go
new file mode 100644
index 0000000..370a885
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15252.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test makes sure that we use all 64 bits of an
+// index, even on 32 bit machines. It also tests that nacl
+// can compile 64 bit indexes loaded from ODOTPTR properly.
+
+package main
+
+type T struct {
+ i int64
+}
+
+func f(t *T) byte {
+ b := [2]byte{3, 4}
+ return b[t.i]
+}
+
+func main() {
+ t := &T{0x100000001}
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("panic wasn't recoverable")
+ }
+ }()
+ f(t)
+ panic("index didn't panic")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15277.go b/gcc/testsuite/go.test/test/fixedbugs/issue15277.go
new file mode 100644
index 0000000..af165f7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15277.go
@@ -0,0 +1,40 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+// +build amd64
+
+package main
+
+import "runtime"
+
+type big [10 << 20]byte
+
+func f(x *big, start int64) {
+ if delta := inuse() - start; delta < 9<<20 {
+ println("after alloc: expected delta at least 9MB, got: ", delta)
+ }
+ runtime.KeepAlive(x)
+ x = nil
+ if delta := inuse() - start; delta > 1<<20 {
+ println("after drop: expected delta below 1MB, got: ", delta)
+ }
+ x = new(big)
+ if delta := inuse() - start; delta < 9<<20 {
+ println("second alloc: expected delta at least 9MB, got: ", delta)
+ }
+ runtime.KeepAlive(x)
+}
+
+func main() {
+ x := inuse()
+ f(new(big), x)
+}
+
+func inuse() int64 {
+ runtime.GC()
+ var st runtime.MemStats
+ runtime.ReadMemStats(&st)
+ return int64(st.Alloc)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15303.go b/gcc/testsuite/go.test/test/fixedbugs/issue15303.go
new file mode 100644
index 0000000..c8dfa30
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15303.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that inlined struct/array comparisons have the right side-effects.
+
+package main
+
+import "os"
+
+func main() {
+ var x int
+ f := func() (r [4]int) {
+ x++
+ return
+ }
+ _ = f() == f()
+ if x != 2 {
+ println("f evaluated ", x, " times, want 2")
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15329.go b/gcc/testsuite/go.test/test/fixedbugs/issue15329.go
new file mode 100644
index 0000000..30fbf13
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15329.go
@@ -0,0 +1,79 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Previously, cmd/compile would rewrite
+//
+// check(unsafe.Pointer(testMeth(1).Pointer()), unsafe.Pointer(testMeth(2).Pointer()))
+//
+// to
+//
+// var autotmp_1 uintptr = testMeth(1).Pointer()
+// var autotmp_2 uintptr = testMeth(2).Pointer()
+// check(unsafe.Pointer(autotmp_1), unsafe.Pointer(autotmp_2))
+//
+// However, that means autotmp_1 is the only reference to the int
+// variable containing the value "1", but it's not a pointer type,
+// so it was at risk of being garbage collected by the evaluation of
+// testMeth(2).Pointer(), even though package unsafe's documentation
+// says the original code was allowed.
+//
+// Now cmd/compile rewrites it to
+//
+// var autotmp_1 unsafe.Pointer = unsafe.Pointer(testMeth(1).Pointer())
+// var autotmp_2 unsafe.Pointer = unsafe.Pointer(testMeth(2).Pointer())
+// check(autotmp_1, autotmp_2)
+//
+// to ensure the pointed-to variables are visible to the GC.
+
+package main
+
+import (
+ "fmt"
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+func main() {
+ // Test all the different ways we can invoke reflect.Value.Pointer.
+
+ // Direct method invocation.
+ check(unsafe.Pointer(testMeth(1).Pointer()), unsafe.Pointer(testMeth(2).Pointer()))
+
+ // Invocation via method expression.
+ check(unsafe.Pointer(reflect.Value.Pointer(testMeth(1))), unsafe.Pointer(reflect.Value.Pointer(testMeth(2))))
+
+ // Invocation via interface.
+ check(unsafe.Pointer(testInter(1).Pointer()), unsafe.Pointer(testInter(2).Pointer()))
+
+ // Invocation via method value.
+ check(unsafe.Pointer(testFunc(1)()), unsafe.Pointer(testFunc(2)()))
+}
+
+func check(p, q unsafe.Pointer) {
+ a, b := *(*int)(p), *(*int)(q)
+ if a != 1 || b != 2 {
+ fmt.Printf("got %v, %v; expected 1, 2\n", a, b)
+ }
+}
+
+func testMeth(x int) reflect.Value {
+ // Force GC to run.
+ runtime.GC()
+ return reflect.ValueOf(&x)
+}
+
+type Pointerer interface {
+ Pointer() uintptr
+}
+
+func testInter(x int) Pointerer {
+ return testMeth(x)
+}
+
+func testFunc(x int) func() uintptr {
+ return testMeth(x).Pointer
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15439.go b/gcc/testsuite/go.test/test/fixedbugs/issue15439.go
new file mode 100644
index 0000000..840a3c0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15439.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "reflect"
+
+func main() {
+ a := &struct{ x int }{}
+ b := &struct{ x int "" }{}
+
+ ta := reflect.TypeOf(a)
+ tb := reflect.TypeOf(b)
+
+ // Ensure cmd/compile treats absent and empty tags as equivalent.
+ a = b
+
+ // Ensure package reflect treats absent and empty tags as equivalent.
+ if !tb.AssignableTo(ta) {
+ panic("fail")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/a.go
new file mode 100644
index 0000000..1fcf3ea
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/a.go
@@ -0,0 +1,24 @@
+package a
+
+import "io"
+
+type T interface {
+ M0(_ int)
+ M1(x, _ int) // _ (blank) caused crash
+ M2() (x, _ int)
+}
+
+type S struct{}
+
+func (S) M0(_ int) {}
+func (S) M1(x, _ int) {}
+func (S) M2() (x, _ int) { return }
+func (_ S) M3() {}
+
+// Snippet from x/tools/godoc/analysis/analysis.go.
+// Offending code from #5470.
+type Link interface {
+ Start() int
+ End() int
+ Write(w io.Writer, _ int, start bool) // _ (blank) caused crash
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/b.go
new file mode 100644
index 0000000..863ee9f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15470.dir/b.go
@@ -0,0 +1,3 @@
+package b
+
+import _ "./a" // must not fail
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15470.go b/gcc/testsuite/go.test/test/fixedbugs/issue15470.go
new file mode 100644
index 0000000..22b48fe
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15470.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 15470: Make sure special-case signatures can
+// be exported and imported w/o problems.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/a.go
new file mode 100644
index 0000000..663303b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type A struct{ _ int32 }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/b.go
new file mode 100644
index 0000000..f0750d3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/b.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+func B() (_ struct{ _ int32 }) { return }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/c.go
new file mode 100644
index 0000000..dc2ef5b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15514.dir/c.go
@@ -0,0 +1,10 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import "./a"
+import "./b"
+
+var _ a.A = b.B() // ERROR "cannot use b\.B|incompatible type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15514.go b/gcc/testsuite/go.test/test/fixedbugs/issue15514.go
new file mode 100644
index 0000000..626f7ad
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15514.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15528.go b/gcc/testsuite/go.test/test/fixedbugs/issue15528.go
new file mode 100644
index 0000000..b1f9dfb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15528.go
@@ -0,0 +1,131 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "unsafe"
+)
+
+type RWS struct{}
+
+func (x *RWS) Read(p []byte) (n int, err error) { return }
+func (x *RWS) Write(p []byte) (n int, err error) { return }
+func (x *RWS) Seek(offset int64, whence int) (n int64, err error) { return }
+func (x *RWS) String() string { return "rws" }
+
+func makeRWS() io.ReadWriteSeeker { return &RWS{} }
+func makeStringer() fmt.Stringer { return &RWS{} }
+
+// Test correct construction of static empty interface values
+var efaces = [...]struct {
+ x interface{}
+ s string
+}{
+ {nil, "<nil> <nil>"},
+ {1, "int 1"},
+ {int(1), "int 1"},
+ {Int(int(2)), "main.Int Int=2"},
+ {int(Int(3)), "int 3"},
+ {[1]int{2}, "[1]int [2]"},
+ {io.Reader(io.ReadWriter(io.ReadWriteSeeker(nil))), "<nil> <nil>"},
+ {io.Reader(io.ReadWriter(io.ReadWriteSeeker(&RWS{}))), "*main.RWS rws"},
+ {makeRWS(), "*main.RWS rws"},
+ {map[string]string{"here": "there"}, "map[string]string map[here:there]"},
+ {chan bool(nil), "chan bool <nil>"},
+ {unsafe.Pointer(uintptr(0)), "unsafe.Pointer <nil>"},
+ {(*byte)(nil), "*uint8 <nil>"},
+ {io.Writer((*os.File)(nil)), "*os.File <nil>"},
+ {(interface{})(io.Writer((*os.File)(nil))), "*os.File <nil>"},
+ {fmt.Stringer(Strunger(((*Int)(nil)))), "*main.Int <nil>"},
+}
+
+type Int int
+
+func (i Int) String() string { return fmt.Sprintf("Int=%d", i) }
+func (i Int) Strung() {}
+
+type Strunger interface {
+ fmt.Stringer
+ Strung()
+}
+
+// Test correct construction of static non-empty interface values
+var ifaces = [...]struct {
+ x fmt.Stringer
+ s string
+}{
+ {nil, "<nil> <nil> %!s(<nil>)"},
+ {Int(3), "main.Int 3 Int=3"},
+ {Int(int(Int(4))), "main.Int 4 Int=4"},
+ {Strunger(Int(5)), "main.Int 5 Int=5"},
+ {makeStringer(), "*main.RWS &main.RWS{} rws"},
+ {fmt.Stringer(nil), "<nil> <nil> %!s(<nil>)"},
+ {(*RWS)(nil), "*main.RWS (*main.RWS)(nil) rws"},
+}
+
+// Test correct handling of direct interface values
+var (
+ one int = 1
+ iptr interface{} = &one
+ clos int
+ f interface{} = func() { clos++ }
+ deep interface{} = [1]struct{ a *[2]byte }{{a: &[2]byte{'z', 'w'}}}
+ ch interface{} = make(chan bool, 1)
+)
+
+func main() {
+ var fail bool
+ for i, test := range efaces {
+ s := fmt.Sprintf("%[1]T %[1]v", test.x)
+ if s != test.s {
+ fmt.Printf("eface(%d)=%q want %q\n", i, s, test.s)
+ fail = true
+ }
+ }
+
+ for i, test := range ifaces {
+ s := fmt.Sprintf("%[1]T %#[1]v %[1]s", test.x)
+ if s != test.s {
+ fmt.Printf("iface(%d)=%q want %q\n", i, s, test.s)
+ fail = true
+ }
+ }
+
+ if got := *(iptr.(*int)); got != 1 {
+ fmt.Printf("bad int ptr %d\n", got)
+ fail = true
+ }
+
+ f.(func())()
+ f.(func())()
+ f.(func())()
+ if clos != 3 {
+ fmt.Printf("bad closure exec %d\n", clos)
+ fail = true
+ }
+
+ if !reflect.DeepEqual(*(deep.([1]struct{ a *[2]byte })[0].a), [2]byte{'z', 'w'}) {
+ fmt.Printf("bad deep directiface\n")
+ fail = true
+ }
+
+ cc := ch.(chan bool)
+ cc <- true
+ if got := <-cc; !got {
+ fmt.Printf("bad chan\n")
+ fail = true
+ }
+
+ if fail {
+ fmt.Println("BUG")
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/a.go
new file mode 100644
index 0000000..3c593fc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/a.go
@@ -0,0 +1,17 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type I0 interface {
+ I1
+}
+
+type T struct {
+ I1
+}
+
+type I1 interface {
+ M(*T) // removing * makes crash go away
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/b.go
new file mode 100644
index 0000000..b46f5ad
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+var X a.T
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/c.go
new file mode 100644
index 0000000..6d3f3be
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15548.dir/c.go
@@ -0,0 +1,10 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import (
+ _ "./b"
+ _ "./a"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15548.go b/gcc/testsuite/go.test/test/fixedbugs/issue15548.go
new file mode 100644
index 0000000..4d2844d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15548.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15550.go b/gcc/testsuite/go.test/test/fixedbugs/issue15550.go
new file mode 100644
index 0000000..f2853fc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15550.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+const (
+ _ = unsafe.Sizeof(func() int {
+ const (
+ _ = 1
+ _
+ _
+ )
+ return 0
+ }())
+
+ y = iota
+)
+
+func main() {
+ if y != 1 {
+ panic(y)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/a.go
new file mode 100644
index 0000000..1356601
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/a.go
@@ -0,0 +1,40 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T struct {
+}
+
+func F() []T {
+ return []T{T{}}
+}
+
+func Fi() []T {
+ return []T{{}} // element with implicit composite literal type
+}
+
+func Fp() []*T {
+ return []*T{&T{}}
+}
+
+func Fip() []*T {
+ return []*T{{}} // element with implicit composite literal type
+}
+
+func Gp() map[int]*T {
+ return map[int]*T{0: &T{}}
+}
+
+func Gip() map[int]*T {
+ return map[int]*T{0: {}} // element with implicit composite literal type
+}
+
+func Hp() map[*T]int {
+ return map[*T]int{&T{}: 0}
+}
+
+func Hip() map[*T]int {
+ return map[*T]int{{}: 0} // key with implicit composite literal type
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/b.go
new file mode 100644
index 0000000..355accc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15572.dir/b.go
@@ -0,0 +1,27 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func F() {
+ a.F()
+ a.Fi()
+}
+
+func Fp() {
+ a.Fp()
+ a.Fip()
+}
+
+func Gp() {
+ a.Gp()
+ a.Gip()
+}
+
+func Hp() {
+ a.Hp()
+ a.Hip()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15572.go b/gcc/testsuite/go.test/test/fixedbugs/issue15572.go
new file mode 100644
index 0000000..cf77778
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15572.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that exporting composite literals with implicit
+// types doesn't crash the typechecker when running over
+// inlined function bodies containing such literals.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15585.go b/gcc/testsuite/go.test/test/fixedbugs/issue15585.go
new file mode 100644
index 0000000..79eb13f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15585.go
@@ -0,0 +1,45 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bug
+
+func example(n int) (rc int) {
+ var cc, ll, pp, rr [27]int
+ for q0 := 0; q0 < n-2; q0++ {
+ for q1 := q0 + 2; q1 < n; q1++ {
+ var c, d, l, p, r int
+ b0 := 1 << uint(q0)
+ b1 := 1 << uint(q1)
+ l = ((b0 << 1) | b1) << 1
+ c = b0 | b1 | (-1 << uint(n))
+ r = ((b0 >> 1) | b1) >> 1
+ E:
+ if c != -1 {
+ p = ^(l | c | r)
+ } else {
+ rc++
+ goto R
+ }
+ L:
+ if p != 0 {
+ lsb := p & -p
+ p &^= lsb
+ ll[d], cc[d], rr[d], pp[d] = l, c, r, p
+ l, c, r = (l|lsb)<<1, c|lsb, (r|lsb)>>1
+ d++
+ goto E
+ }
+ R:
+ d--
+ if d >= 0 {
+ l, c, r, p = ll[d], cc[d], rr[d], pp[d]
+ goto L
+ }
+ }
+ }
+ rc <<= 1
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15602.go b/gcc/testsuite/go.test/test/fixedbugs/issue15602.go
new file mode 100644
index 0000000..badf813
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15602.go
@@ -0,0 +1,11 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(i interface{}) {
+ i, _ = i.(error)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15604.go b/gcc/testsuite/go.test/test/fixedbugs/issue15604.go
new file mode 100644
index 0000000..4dc0b0b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15604.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bug
+
+import "os"
+
+func f(err error) {
+ var ok bool
+ if err, ok = err.(*os.PathError); ok {
+ if err == os.ErrNotExist {
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call.go b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call.go
new file mode 100644
index 0000000..41a489c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call.go
@@ -0,0 +1,7 @@
+// +build !amd64,!386
+
+package main
+
+func jump() {
+ target()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_386.s b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_386.s
new file mode 100644
index 0000000..751084c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_386.s
@@ -0,0 +1,8 @@
+#include "textflag.h"
+
+DATA ·pointer(SB)/4, $·target(SB)
+GLOBL ·pointer(SB),RODATA,$4
+
+TEXT ·jump(SB),NOSPLIT,$4
+ CALL *·pointer(SB)
+ RET
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_amd64.s b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_amd64.s
new file mode 100644
index 0000000..09fbe5d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_amd64.s
@@ -0,0 +1,8 @@
+#include "textflag.h"
+
+DATA ·pointer(SB)/8, $·target(SB)
+GLOBL ·pointer(SB),RODATA,$8
+
+TEXT ·jump(SB),NOSPLIT,$8
+ CALL *·pointer(SB)
+ RET
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_decl.go b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_decl.go
new file mode 100644
index 0000000..d9c5a4e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/call_decl.go
@@ -0,0 +1,5 @@
+// +build amd64 386
+
+package main
+
+func jump()
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/main.go
new file mode 100644
index 0000000..4855e31
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15609.dir/main.go
@@ -0,0 +1,14 @@
+package main
+
+var called bool
+
+func target() {
+ called = true
+}
+
+func main() {
+ jump()
+ if !called {
+ panic("target not called")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/a.go
new file mode 100644
index 0000000..842f196
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/a.go
@@ -0,0 +1,23 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T struct{}
+
+func (T) m() string {
+ return "m"
+}
+
+func (*T) mp() string {
+ return "mp"
+}
+
+func F() func(T) string {
+ return T.m // method expression
+}
+
+func Fp() func(*T) string {
+ return (*T).mp // method expression
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/b.go
new file mode 100644
index 0000000..3d011ba
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15646.dir/b.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a" // import must succeed
+
+func main() {
+ if a.F()(a.T{}) != "m" {
+ panic(0)
+ }
+ if a.Fp()(nil) != "mp" {
+ panic(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15646.go b/gcc/testsuite/go.test/test/fixedbugs/issue15646.go
new file mode 100644
index 0000000..cd4ba9d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15646.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that method expressions are correctly encoded
+// in binary export data and can be imported again.
+package ignore \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15722.go b/gcc/testsuite/go.test/test/fixedbugs/issue15722.go
new file mode 100644
index 0000000..dec5458
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15722.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Checks to make sure that the compiler can catch a specific invalid
+// method type expression. NB: gccgo and gc have slightly different
+// error messages, hence the generic test for 'method' and not something
+// more specific.
+
+package issue15722
+
+type T int
+type P *T
+
+func (T) t() {}
+
+func _(p P) {
+ P.t(p) // ERROR "method"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15733.go b/gcc/testsuite/go.test/test/fixedbugs/issue15733.go
new file mode 100644
index 0000000..8f609e6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15733.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type S struct {
+ a [1 << 16]byte
+}
+
+func f1() {
+ p := &S{}
+ _ = p
+}
+
+type T [1 << 16]byte
+
+func f2() {
+ p := &T{}
+ _ = p
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/a.go
new file mode 100644
index 0000000..15b7f1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/a.go
@@ -0,0 +1,61 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func F1() {
+L:
+ goto L
+}
+
+func F2() {
+L:
+ for {
+ break L
+ }
+}
+
+func F3() {
+L:
+ for {
+ continue L
+ }
+}
+
+func F4() {
+ switch {
+ case true:
+ fallthrough
+ default:
+ }
+}
+
+type T struct{}
+
+func (T) M1() {
+L:
+ goto L
+}
+
+func (T) M2() {
+L:
+ for {
+ break L
+ }
+}
+
+func (T) M3() {
+L:
+ for {
+ continue L
+ }
+}
+
+func (T) M4() {
+ switch {
+ case true:
+ fallthrough
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/b.go
new file mode 100644
index 0000000..9fd6efc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15838.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type T struct{ a.T }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15838.go b/gcc/testsuite/go.test/test/fixedbugs/issue15838.go
new file mode 100644
index 0000000..fb1c64d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15838.go
@@ -0,0 +1,12 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test cases for issue #15838, and related failures.
+// Make sure the importer correctly sets up nodes for
+// label decls, goto, continue, break, and fallthrough
+// statements.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15895.go b/gcc/testsuite/go.test/test/fixedbugs/issue15895.go
new file mode 100644
index 0000000..3ef295c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15895.go
@@ -0,0 +1,27 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// func bad used to fail to compile.
+
+package p
+
+type A [1]int
+
+func bad(x A) {
+ switch x {
+ case A([1]int{1}):
+ case A([1]int{1}):
+ }
+}
+
+func good(x A) {
+ y := A([1]int{1})
+ z := A([1]int{1})
+ switch x {
+ case y:
+ case z:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15898.go b/gcc/testsuite/go.test/test/fixedbugs/issue15898.go
new file mode 100644
index 0000000..94369f9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15898.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(e interface{}) {
+ switch e.(type) {
+ case nil, nil: // ERROR "multiple nil cases in type switch|duplicate type in switch"
+ }
+
+ switch e.(type) {
+ case nil:
+ case nil: // ERROR "multiple nil cases in type switch|duplicate type in switch"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15902.go b/gcc/testsuite/go.test/test/fixedbugs/issue15902.go
new file mode 100644
index 0000000..9511a22
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15902.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test makes sure we don't use 4-byte unaligned writes
+// to zero memory on architectures that don't support them.
+
+package main
+
+type T struct {
+ a byte
+ b [10]byte
+}
+
+//go:noinline
+func f(t *T) {
+ // t will be aligned, so &t.b won't be.
+ t.b = [10]byte{}
+}
+
+var t T
+
+func main() {
+ f(&t)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/a.go
new file mode 100644
index 0000000..15f9235
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Error error
+
+func F() Error { return nil }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/b.go
new file mode 100644
index 0000000..0a36c5c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15920.dir/b.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import _ "./a"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15920.go b/gcc/testsuite/go.test/test/fixedbugs/issue15920.go
new file mode 100644
index 0000000..4d2844d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15920.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15926.go b/gcc/testsuite/go.test/test/fixedbugs/issue15926.go
new file mode 100644
index 0000000..76e25eb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15926.go
@@ -0,0 +1,20 @@
+// build
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 15926: linker was adding .def to the end of symbols, causing
+// a name collision with a method actually named def.
+
+package main
+
+type S struct{}
+
+func (s S) def() {}
+
+var I = S.def
+
+func main() {
+ I(S{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15961.go b/gcc/testsuite/go.test/test/fixedbugs/issue15961.go
new file mode 100644
index 0000000..db3d662
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15961.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package y
+
+type symSet []int
+
+//go:noinline
+func (s symSet) len() (r int) {
+ return 0
+}
+
+func f(m map[int]symSet) {
+ var symSet []int
+ for _, x := range symSet {
+ m[x] = nil
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15988.go b/gcc/testsuite/go.test/test/fixedbugs/issue15988.go
new file mode 100644
index 0000000..2bed2a9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15988.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(p, q []int) {
+ p = append(q, 5)
+ sink = &p
+}
+
+var sink *[]int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15992.go b/gcc/testsuite/go.test/test/fixedbugs/issue15992.go
new file mode 100644
index 0000000..cda5527
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15992.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+func f(a []byte) ([]byte, []byte) {
+ return a, []byte("abc")
+}
+
+func g(a []byte) ([]byte, string) {
+ return a, "abc"
+}
+
+func h(m map[int]int) (map[int]int, int) {
+ return m, 0
+}
+
+func main() {
+ a := []byte{1, 2, 3}
+ n := copy(f(a))
+ fmt.Println(n, a)
+
+ b := []byte{1, 2, 3}
+ n = copy(g(b))
+ fmt.Println(n, b)
+
+ m := map[int]int{0: 0}
+ fmt.Println(len(m))
+ delete(h(m))
+ fmt.Println(len(m))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue15992.out b/gcc/testsuite/go.test/test/fixedbugs/issue15992.out
new file mode 100644
index 0000000..e0011e3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue15992.out
@@ -0,0 +1,4 @@
+3 [97 98 99]
+3 [97 98 99]
+1
+0
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16016.go b/gcc/testsuite/go.test/test/fixedbugs/issue16016.go
new file mode 100644
index 0000000..e738e1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16016.go
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "time"
+
+type T struct{}
+
+func (*T) Foo(vals []interface{}) {
+ switch v := vals[0].(type) {
+ case string:
+ _ = v
+ }
+}
+
+type R struct{ *T }
+
+type Q interface {
+ Foo([]interface{})
+}
+
+func main() {
+ var q Q = &R{&T{}}
+ for i := 0; i < 10000; i++ {
+ go func() {
+ defer q.Foo([]interface{}{"meow"})
+ time.Sleep(100 * time.Millisecond)
+ }()
+ }
+ time.Sleep(1 * time.Second)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16037_run.go b/gcc/testsuite/go.test/test/fixedbugs/issue16037_run.go
new file mode 100644
index 0000000..68104a9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16037_run.go
@@ -0,0 +1,70 @@
+// +build !nacl,!js,!android,!gccgo
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+var tmpl = template.Must(template.New("main").Parse(`
+package main
+
+type T struct {
+ {{range .Names}}
+ {{.Name}} *string
+ {{end}}
+}
+
+{{range .Names}}
+func (t *T) Get{{.Name}}() string {
+ if t.{{.Name}} == nil {
+ return ""
+ }
+ return *t.{{.Name}}
+}
+{{end}}
+
+func main() {}
+`))
+
+func main() {
+ const n = 5000
+
+ type Name struct{ Name string }
+ var t struct{ Names []Name }
+ for i := 0; i < n; i++ {
+ t.Names = append(t.Names, Name{Name: fmt.Sprintf("H%06X", i)})
+ }
+
+ buf := new(bytes.Buffer)
+ if err := tmpl.Execute(buf, t); err != nil {
+ log.Fatal(err)
+ }
+
+ dir, err := ioutil.TempDir("", "issue16037-")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+ path := filepath.Join(dir, "ridiculous_number_of_fields.go")
+ if err := ioutil.WriteFile(path, buf.Bytes(), 0664); err != nil {
+ log.Fatal(err)
+ }
+
+ out, err := exec.Command("go", "build", "-o="+filepath.Join(dir, "out"), path).CombinedOutput()
+ if err != nil {
+ log.Fatalf("build failed: %v\n%s", err, out)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16095.go b/gcc/testsuite/go.test/test/fixedbugs/issue16095.go
new file mode 100644
index 0000000..864b4b7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16095.go
@@ -0,0 +1,104 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+var sink *[20]byte
+
+func f() (x [20]byte) {
+ // Initialize x.
+ for i := range x {
+ x[i] = byte(i)
+ }
+
+ // Force x to be allocated on the heap.
+ sink = &x
+ sink = nil
+
+ // Go to deferreturn after the panic below.
+ defer func() {
+ recover()
+ }()
+
+ // This call collects the heap-allocated version of x (oops!)
+ runtime.GC()
+
+ // Allocate that same object again and clobber it.
+ y := new([20]byte)
+ for i := 0; i < 20; i++ {
+ y[i] = 99
+ }
+ // Make sure y is heap allocated.
+ sink = y
+
+ panic(nil)
+
+ // After the recover we reach the deferreturn, which
+ // copies the heap version of x back to the stack.
+ // It gets the pointer to x from a stack slot that was
+ // not marked as live during the call to runtime.GC().
+}
+
+var sinkint int
+
+func g(p *int) (x [20]byte) {
+ // Initialize x.
+ for i := range x {
+ x[i] = byte(i)
+ }
+
+ // Force x to be allocated on the heap.
+ sink = &x
+ sink = nil
+
+ // Go to deferreturn after the panic below.
+ defer func() {
+ recover()
+ }()
+
+ // This call collects the heap-allocated version of x (oops!)
+ runtime.GC()
+
+ // Allocate that same object again and clobber it.
+ y := new([20]byte)
+ for i := 0; i < 20; i++ {
+ y[i] = 99
+ }
+ // Make sure y is heap allocated.
+ sink = y
+
+ // panic with a non-call (with no fallthrough)
+ for {
+ sinkint = *p
+ }
+
+ // After the recover we reach the deferreturn, which
+ // copies the heap version of x back to the stack.
+ // It gets the pointer to x from a stack slot that was
+ // not marked as live during the call to runtime.GC().
+}
+
+func main() {
+ x := f()
+ for i, v := range x {
+ if v != byte(i) {
+ fmt.Printf("%v\n", x)
+ panic("bad f")
+ }
+ }
+ x = g(nil)
+ for i, v := range x {
+ if v != byte(i) {
+ fmt.Printf("%v\n", x)
+ panic("bad g")
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16130.go b/gcc/testsuite/go.test/test/fixedbugs/issue16130.go
new file mode 100644
index 0000000..c4e3ffd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16130.go
@@ -0,0 +1,43 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that an interface conversion error panics with an "interface
+// conversion" run-time error. It was (incorrectly) panicking with a
+// "nil pointer dereference."
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+)
+
+type I interface {
+ Get() int
+}
+
+func main() {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("expected panic")
+ }
+ re, ok := r.(runtime.Error)
+ if !ok {
+ panic(fmt.Sprintf("got %T, expected runtime.Error", r))
+ }
+ if !strings.Contains(re.Error(), "interface conversion") {
+ panic(fmt.Sprintf("got %q, expected interface conversion error", re.Error()))
+ }
+ }()
+ e := (interface{})(0)
+ if _, ok := e.(I); ok {
+ panic("unexpected interface conversion success")
+ }
+ fmt.Println(e.(I))
+ panic("unexpected interface conversion success")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a1.go b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a1.go
new file mode 100644
index 0000000..497cccf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a1.go
@@ -0,0 +1,7 @@
+package a
+
+type X string
+
+func NewX() X {
+ return ""
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a2.go b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a2.go
new file mode 100644
index 0000000..497cccf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/a2.go
@@ -0,0 +1,7 @@
+package a
+
+type X string
+
+func NewX() X {
+ return ""
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/b.go
new file mode 100644
index 0000000..be1bebf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/b.go
@@ -0,0 +1,7 @@
+package b
+
+import "./a2"
+
+type T struct {
+ X a.X
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/c.go
new file mode 100644
index 0000000..b25fe5a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16133.dir/c.go
@@ -0,0 +1,10 @@
+package p
+
+import (
+ "./a1"
+ "./b"
+)
+
+var _ = b.T{
+ X: a.NewX(), // ERROR `cannot use "a1"\.NewX\(\)`
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16193.go b/gcc/testsuite/go.test/test/fixedbugs/issue16193.go
new file mode 100644
index 0000000..eada62d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16193.go
@@ -0,0 +1,27 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The compiler used the name "glob" as the function holding a global
+// function literal, colliding with an actual function named "glob".
+
+package main
+
+func glob() {
+ func() {
+ }()
+}
+
+var c1 = func() {
+}
+
+var c2 = func() {
+}
+
+func main() {
+ glob()
+ c1()
+ c2()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16249.go b/gcc/testsuite/go.test/test/fixedbugs/issue16249.go
new file mode 100644
index 0000000..723d5d9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16249.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Liveness calculations were wrong for a result parameter pushed onto
+// the heap in a function that used defer. Program would crash with
+// runtime: bad pointer in frame main.A at 0xc4201e6838: 0x1
+
+package main
+
+import "errors"
+
+var sink interface{}
+
+//go:noinline
+func f(err *error) {
+ if err != nil {
+ sink = err
+ }
+}
+
+//go:noinline
+func A(n, m int64) (res int64, err error) {
+ defer f(&err) // output parameter's address escapes to a defer.
+ if n < 0 {
+ err = errors.New("No negative")
+ return
+ }
+ if n <= 1 {
+ res = n
+ return
+ }
+ res = B(m) // This call to B drizzles a little junk on the stack.
+ res, err = A(n-1, m)
+ res++
+ return
+}
+
+// B does a little bit of recursion dribbling not-zero onto the stack.
+//go:noinline
+func B(n int64) (res int64) {
+ if n <= 1 { // Prefer to leave a 1 on the stack.
+ return n
+ }
+ return 1 + B(n-1)
+}
+
+func main() {
+ x, e := A(0, 0)
+ for j := 0; j < 4; j++ { // j controls amount of B's stack dribble
+ for i := 0; i < 1000; i++ { // try more and more recursion until stack growth occurs in newobject in prologue
+ x, e = A(int64(i), int64(j))
+ }
+ }
+ _, _ = x, e
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16306.go b/gcc/testsuite/go.test/test/fixedbugs/issue16306.go
new file mode 100644
index 0000000..d29a75a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16306.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+var x = unsafe.Pointer(uintptr(0))
+
+func main() {
+ _ = map[unsafe.Pointer]int{unsafe.Pointer(uintptr(0)): 0}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/a.go
new file mode 100644
index 0000000..3a1b7e0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "unsafe"
+
+func ConstUnsafePointer() unsafe.Pointer {
+ return unsafe.Pointer(uintptr(0))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/b.go
new file mode 100644
index 0000000..b813918
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16317.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ _ = a.ConstUnsafePointer()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16317.go b/gcc/testsuite/go.test/test/fixedbugs/issue16317.go
new file mode 100644
index 0000000..b3376bb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16317.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 16317: cmd/compile: internal compiler error:
+// unhandled OCONV INT -> TUNSAFEPTR
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16331.go b/gcc/testsuite/go.test/test/fixedbugs/issue16331.go
new file mode 100644
index 0000000..665e7fc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16331.go
@@ -0,0 +1,48 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Perform tracebackdefers with a deferred reflection method.
+
+package main
+
+import "reflect"
+
+type T struct{}
+
+func (T) M() {
+}
+
+func F(args []reflect.Value) (results []reflect.Value) {
+ return nil
+}
+
+func main() {
+ done := make(chan bool)
+ go func() {
+ // Test reflect.makeFuncStub.
+ t := reflect.TypeOf((func())(nil))
+ f := reflect.MakeFunc(t, F).Interface().(func())
+ defer f()
+ growstack(10000)
+ done <- true
+ }()
+ <-done
+ go func() {
+ // Test reflect.methodValueCall.
+ f := reflect.ValueOf(T{}).Method(0).Interface().(func())
+ defer f()
+ growstack(10000)
+ done <- true
+ }()
+ <-done
+}
+
+func growstack(x int) {
+ if x == 0 {
+ return
+ }
+ growstack(x - 1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16369.go b/gcc/testsuite/go.test/test/fixedbugs/issue16369.go
new file mode 100644
index 0000000..e97f4a0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16369.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface {
+ M(interface {
+ T
+ })
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16428.go b/gcc/testsuite/go.test/test/fixedbugs/issue16428.go
new file mode 100644
index 0000000..5696d18
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16428.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var (
+ b = [...]byte("abc") // ERROR "outside of array literal"
+ s = len(b)
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16439.go b/gcc/testsuite/go.test/test/fixedbugs/issue16439.go
new file mode 100644
index 0000000..704b6b1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16439.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var a []int = []int{1: 1}
+var b []int = []int{-1: 1} // ERROR "must be non-negative integer constant|index expression is negative"
+
+var c []int = []int{2.0: 2}
+var d []int = []int{-2.0: 2} // ERROR "must be non-negative integer constant|index expression is negative"
+
+var e []int = []int{3 + 0i: 3}
+var f []int = []int{3i: 3} // ERROR "truncated to integer|index expression is not integer constant"
+
+var g []int = []int{"a": 4} // ERROR "must be non-negative integer constant|index expression is not integer constant"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16515.go b/gcc/testsuite/go.test/test/fixedbugs/issue16515.go
new file mode 100644
index 0000000..6b67436
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16515.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 16515: spilled Duff-adjusted address may be invalid
+
+package main
+
+import "runtime"
+
+type T [62]int // DUFFZERO with non-zero adjustment on AMD64
+
+var sink interface{}
+
+//go:noinline
+func zero(x *T) {
+ // Two DUFFZEROs on the same address with a function call in between.
+ // Duff-adjusted address will be spilled and loaded
+
+ *x = T{} // DUFFZERO
+ runtime.GC()
+ (*x)[0] = 1
+ g() // call a function with large frame, trigger a stack move
+ *x = T{} // DUFFZERO again
+}
+
+//go:noinline
+// a function with large frame
+func g() {
+ var x [1000]int
+ _ = x
+}
+
+func main() {
+ var s struct { a T; b [8192-62]int } // allocate 64K, hopefully it's in a new span and a few bytes before it is garbage
+ sink = &s // force heap allocation
+ s.a[0] = 2
+ zero(&s.a)
+ if s.a[0] != 0 {
+ println("s.a[0] =", s.a[0])
+ panic("zeroing failed")
+ }
+
+ var a T // on stack
+ a[0] = 2
+ zero(&a)
+ if a[0] != 0 {
+ println("a[0] =", a[0])
+ panic("zeroing failed")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/a.go
new file mode 100644
index 0000000..0ffdbbe
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type V struct{ i int }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/b.go
new file mode 100644
index 0000000..4f238b9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/b.go
@@ -0,0 +1,14 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+var V struct{ i int }
+
+var U struct {
+ a.V
+ j int
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/issue16616.go b/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/issue16616.go
new file mode 100644
index 0000000..0bfadb8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16616.dir/issue16616.go
@@ -0,0 +1,26 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "reflect"
+
+ _ "./a"
+ "./b"
+)
+
+var V struct{ i int }
+
+func main() {
+ if got := reflect.ValueOf(b.V).Type().Field(0).PkgPath; got != "b" {
+ panic(`PkgPath=` + got + ` for first field of b.V, want "b"`)
+ }
+ if got := reflect.ValueOf(V).Type().Field(0).PkgPath; got != "main" {
+ panic(`PkgPath=` + got + ` for first field of V, want "main"`)
+ }
+ if got := reflect.ValueOf(b.U).Type().Field(0).PkgPath; got != "b" {
+ panic(`PkgPath=` + got + ` for first field of b.U, want "b"`)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16616.go b/gcc/testsuite/go.test/test/fixedbugs/issue16616.go
new file mode 100644
index 0000000..a7d6ac0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16616.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests that unexported fields of unnamed types have different PkgPath values.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16733.go b/gcc/testsuite/go.test/test/fixedbugs/issue16733.go
new file mode 100644
index 0000000..850b042
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16733.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 16733: don't fold constant factors into a multiply
+// beyond the capacity of a MULQ instruction (32 bits).
+
+package p
+
+func f(n int64) int64 {
+ n *= 1000000
+ n *= 1000000
+ return n
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16741.go b/gcc/testsuite/go.test/test/fixedbugs/issue16741.go
new file mode 100644
index 0000000..9946062
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16741.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure CSE of multi-output opcodes works correctly
+// with select0/1 operations.
+
+package main
+
+func div(d, r int64) int64 {
+ if m := d % r; m > 0 {
+ return d/r + 1
+ }
+ return d / r
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16760.go b/gcc/testsuite/go.test/test/fixedbugs/issue16760.go
new file mode 100644
index 0000000..d0e08b5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16760.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we don't start marshaling (writing to the stack)
+// arguments until those arguments are evaluated and known
+// not to unconditinally panic. If they unconditionally panic,
+// we write some args but never do the call. That messes up
+// the logic which decides how big the argout section needs to be.
+
+package main
+
+type W interface {
+ Write([]byte)
+}
+
+type F func(W)
+
+func foo(f F) {
+ defer func() {
+ if r := recover(); r != nil {
+ usestack(1000)
+ }
+ }()
+ f(nil)
+}
+
+func main() {
+ foo(func(w W) {
+ var x []string
+ w.Write([]byte(x[5]))
+ })
+}
+
+func usestack(n int) {
+ if n == 0 {
+ return
+ }
+ usestack(n - 1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16804.go b/gcc/testsuite/go.test/test/fixedbugs/issue16804.go
new file mode 100644
index 0000000..46dd4a3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16804.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 16804: internal error for math.Sqrt as statement
+// rather than expression
+
+package main
+
+import "math"
+
+func sqrt() {
+ math.Sqrt(2.0)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16948.go b/gcc/testsuite/go.test/test/fixedbugs/issue16948.go
new file mode 100644
index 0000000..c986024
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16948.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 16948: make sure intrinsified atomic ops won't
+// confuse the scheduler.
+
+package main
+
+import "sync/atomic"
+
+func main() {
+ f()
+}
+
+var x int32
+
+type T [10]int
+var sink *T
+
+func f() (t T) {
+ atomic.AddInt32(&x, 1)
+ g(42, 42, 42, 42, 42, &t) // use int values that is invalid pointer to smash the stack slot of return value of runtime.newobject
+ return
+}
+
+//go:noinline
+func g(a, b, c, d, e int, p *T) {
+ var t [10000]int // a large stack frame to trigger stack growing
+ _ = t
+ sink = p // force p (in caller) heap allocated
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16949.go b/gcc/testsuite/go.test/test/fixedbugs/issue16949.go
new file mode 100644
index 0000000..9ee3387
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16949.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that typed non-integer len and cap make arguments are not accepted.
+
+package main
+
+var sink []byte
+
+func main() {
+ sink = make([]byte, 1.0)
+ sink = make([]byte, float32(1.0)) // ERROR "non-integer.*len"
+ sink = make([]byte, float64(1.0)) // ERROR "non-integer.*len"
+
+ sink = make([]byte, 0, 1.0)
+ sink = make([]byte, 0, float32(1.0)) // ERROR "non-integer.*cap"
+ sink = make([]byte, 0, float64(1.0)) // ERROR "non-integer.*cap"
+
+ sink = make([]byte, 1+0i)
+ sink = make([]byte, complex64(1+0i)) // ERROR "non-integer.*len"
+ sink = make([]byte, complex128(1+0i)) // ERROR "non-integer.*len"
+
+ sink = make([]byte, 0, 1+0i)
+ sink = make([]byte, 0, complex64(1+0i)) // ERROR "non-integer.*cap"
+ sink = make([]byte, 0, complex128(1+0i)) // ERROR "non-integer.*cap"
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue16985.go b/gcc/testsuite/go.test/test/fixedbugs/issue16985.go
new file mode 100644
index 0000000..0cb0dae5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue16985.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 16985: intrinsified AMD64 atomic ops should clobber flags
+
+package main
+
+import "sync/atomic"
+
+var count uint32
+
+func main() {
+ buffer := []byte("T")
+ for i := 0; i < len(buffer); {
+ atomic.AddUint32(&count, 1)
+ _ = buffer[i]
+ i++
+ i++
+ }
+
+ for i := 0; i < len(buffer); {
+ atomic.CompareAndSwapUint32(&count, 0, 1)
+ _ = buffer[i]
+ i++
+ i++
+ }
+
+ for i := 0; i < len(buffer); {
+ atomic.SwapUint32(&count, 1)
+ _ = buffer[i]
+ i++
+ i++
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17005.go b/gcc/testsuite/go.test/test/fixedbugs/issue17005.go
new file mode 100644
index 0000000..e539519
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17005.go
@@ -0,0 +1,46 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This tickles (a version of) the PPC64 back end to
+// emit a BVS instruction.
+
+package foo
+
+type Flag int
+
+const (
+ Identity Flag = iota - 2 // H is the identity matrix; no rotation is needed.
+ Rescaling // H specifies rescaling.
+)
+
+type DrotmParams struct {
+ Flag
+}
+
+func Drotmg(d1, d2, x1, y1 float64) (p DrotmParams, rd1, rd2, rx1 float64) {
+
+ const (
+ gam = 4.0
+ gamsq = 16.0
+ rgamsq = 5e-8
+ )
+
+ if d1 < 0 {
+ p.Flag = Rescaling
+ return
+ }
+
+ for rd1 <= rgamsq || rd1 >= gamsq {
+ if rd1 <= rgamsq {
+ rd1 *= gam * gam
+ rx1 /= gam
+ } else {
+ rd1 /= gam * gam
+ rx1 *= gam
+ }
+ }
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17111.go b/gcc/testsuite/go.test/test/fixedbugs/issue17111.go
new file mode 100644
index 0000000..05284a7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17111.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type I int
+
+var (
+ i int
+ x = I(i)
+
+ e interface{} = x
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17194.go b/gcc/testsuite/go.test/test/fixedbugs/issue17194.go
new file mode 100644
index 0000000..0594e1c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17194.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+func f(x []interface{}) (err error) {
+ for _, d := range x {
+ _, ok := d.(*int)
+ if ok {
+ return
+ }
+ }
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17270.go b/gcc/testsuite/go.test/test/fixedbugs/issue17270.go
new file mode 100644
index 0000000..5c009b5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17270.go
@@ -0,0 +1,11 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+const _ = (unsafe.Sizeof)(0)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17328.go b/gcc/testsuite/go.test/test/fixedbugs/issue17328.go
new file mode 100644
index 0000000..ef60edb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17328.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ i := 0
+ for ; ; i++) { // ERROR "unexpected \), expecting { after for clause|expected .*{.*|expected .*;.*"
+ }
+} // GCCGO_ERROR "expected declaration"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17381.go b/gcc/testsuite/go.test/test/fixedbugs/issue17381.go
new file mode 100644
index 0000000..be63633
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17381.go
@@ -0,0 +1,54 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 17381: make sure leave function with non-empty frame
+// saves link register, so that traceback will work.
+
+package main
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+func main() {
+ defer func() {
+ if recover() == nil {
+ panic("did not panic")
+ }
+ pcs := make([]uintptr, 20)
+ n := runtime.Callers(1, pcs)
+ for _, pc := range pcs[:n] {
+ if runtime.FuncForPC(pc).Name() == "main.main" {
+ return
+ }
+ }
+ panic("cannot find main.main in backtrace")
+ }()
+
+ prep()
+ f() // should panic
+}
+
+func funcPC(f interface{}) uintptr {
+ var ptr uintptr
+ return **(**uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&f)) + unsafe.Sizeof(ptr)))
+}
+
+//go:noinline
+func f() {
+ var t [1]int // non-empty frame
+ *(*int)(nil) = t[0]
+}
+
+var p = funcPC(runtime.GC) + 8
+
+//go:noinline
+func prep() {
+ // put some garbage on stack
+ var x = [20]uintptr{p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p}
+ _ = x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17551.go b/gcc/testsuite/go.test/test/fixedbugs/issue17551.go
new file mode 100644
index 0000000..b8751ab
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17551.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 17551: inrange optimization failed to preserve type information.
+
+package main
+
+import "fmt"
+
+func main() {
+ _, x := X()
+ fmt.Printf("x = %v\n", x)
+}
+
+func X() (i int, ok bool) {
+ ii := int(1)
+ return ii, 0 <= ii && ii <= 0x7fffffff
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17588.go b/gcc/testsuite/go.test/test/fixedbugs/issue17588.go
new file mode 100644
index 0000000..0e3a14e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17588.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 17588: internal compiler error in typecheckclosure()
+// because in case of Func.Nname.Type == nil, Decldepth
+// is not initialized in typecheckfunc(). This test
+// produces that case.
+
+package p
+
+type F func(b T) // ERROR "T is not a type|expected type"
+
+func T(fn F) {
+ func() {
+ fn(nil) // If Decldepth is not initialized properly, typecheckclosure() Fatals here.
+ }()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17596.go b/gcc/testsuite/go.test/test/fixedbugs/issue17596.go
new file mode 100644
index 0000000..7398292
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17596.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+type T interface {
+ foo()
+}
+
+func f() (T, int)
+
+func g(v interface{}) (interface{}, int) {
+ var x int
+ v, x = f()
+ return v, x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17631.go b/gcc/testsuite/go.test/test/fixedbugs/issue17631.go
new file mode 100644
index 0000000..b820b2d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17631.go
@@ -0,0 +1,22 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "time"
+
+func main() {
+ _ = struct {
+ about string
+ before map[string]uint
+ update map[string]int
+ updateTime time.Time
+ expect map[string]int
+ }{
+ about: "this one",
+ updates: map[string]int{"gopher": 10}, // ERROR "unknown field 'updates' in struct literal of type|unknown field .*updates.* in .*unnamed struct.*"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17640.go b/gcc/testsuite/go.test/test/fixedbugs/issue17640.go
new file mode 100644
index 0000000..a311521
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17640.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+var results string
+
+type TwoInts struct {
+ x, y int
+}
+
+func f(x int) int { results = results + fmt.Sprintf("_%d", x); return x }
+
+func main() {
+ _ = [19]int{1: f(1), 0: f(0), 2: f(2), 6, 7}
+ _ = [2]int{1: f(4), 0: f(3)}
+ _ = TwoInts{y: f(6), x: f(5)}
+ _ = map[int]int{f(f(9) + 1): f(8), 0: f(7), f(22): -1}
+ if results != "_1_0_2_4_3_6_5_9_10_8_7_22" {
+ fmt.Printf("unexpected: %s\n", results)
+ panic("fail")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17645.go b/gcc/testsuite/go.test/test/fixedbugs/issue17645.go
new file mode 100644
index 0000000..bb34e4e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17645.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type Foo struct {
+ X int
+}
+
+func main() {
+ var s []int
+ var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(type untyped string\) as type int in field value|incompatible type" "cannot use Foo{...} \(type Foo\) as type int in append" "cannot use append\(s\, Foo{...}\) \(type \[\]int\) as type string in assignment"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17710.go b/gcc/testsuite/go.test/test/fixedbugs/issue17710.go
new file mode 100644
index 0000000..2843458
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17710.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime"
+
+func f(x interface{}) {
+ runtime.KeepAlive(x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17752.go b/gcc/testsuite/go.test/test/fixedbugs/issue17752.go
new file mode 100644
index 0000000..83283ad
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17752.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f(m map[string]int) int {
+ return m["a"]
+}
+
+func g(m map[[8]string]int) int {
+ return m[[8]string{"a", "a", "a", "a", "a", "a", "a", "a"}]
+}
+
+func main() {
+ m := map[[8]string]int{}
+ g(m)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17758.go b/gcc/testsuite/go.test/test/fixedbugs/issue17758.go
new file mode 100644
index 0000000..8e40f9d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17758.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func foo() {
+ _ = func() {}
+}
+
+func foo() { // ERROR "foo redeclared in this block|redefinition of .*foo.*"
+ _ = func() {}
+}
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue17918.go b/gcc/testsuite/go.test/test/fixedbugs/issue17918.go
new file mode 100644
index 0000000..88ede6f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue17918.go
@@ -0,0 +1,41 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 17918: slice out-of-bounds in ssa/cse
+
+package dead
+
+import (
+ "fmt"
+ "time"
+)
+
+var (
+ units = []struct {
+ divisor time.Duration
+ unit rune
+ }{
+ {1000000, 's'},
+ {60, 'm'},
+ {60, 'h'},
+ {24, 'd'},
+ {7, 'w'},
+ }
+)
+
+func foobar(d time.Duration) string {
+ d /= time.Microsecond
+ unit := 'u'
+
+ for _, f := range units {
+ if d%f.divisor != 0 {
+ break
+ }
+ d /= f.divisor
+ unit = f.unit
+ }
+ return fmt.Sprintf("%d%c", d, unit)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18089.go b/gcc/testsuite/go.test/test/fixedbugs/issue18089.go
new file mode 100644
index 0000000..fe5c1d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18089.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+type T struct {
+ x int
+ _ int
+}
+
+func main() {
+ _ = T{0, 0}
+
+ x := T{1, 1}
+ _ = x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18092.go b/gcc/testsuite/go.test/test/fixedbugs/issue18092.go
new file mode 100644
index 0000000..a0f7edd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18092.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _() {
+ var ch chan bool
+ select {
+ default:
+ case <-ch { // GCCGO_ERROR "expected colon"
+ } // GC_ERROR "expecting :"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18231.go b/gcc/testsuite/go.test/test/fixedbugs/issue18231.go
new file mode 100644
index 0000000..7747304
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18231.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that error message for composite literals with
+// missing type is at the right place.
+
+package p
+
+type T struct {
+ f map[string]string
+}
+
+var _ = T{
+ f: { // ERROR "missing type in composite literal|may only omit types within"
+ "a": "b",
+ },
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18393.go b/gcc/testsuite/go.test/test/fixedbugs/issue18393.go
new file mode 100644
index 0000000..4543927
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18393.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that compiler directives are ignored if they
+// don't start at the beginning of the line.
+
+package p
+
+//line issue18393.go:20
+import 42 // error on line 20
+
+
+/* //line not at start of line: ignored */ //line issue18393.go:30
+var x // error on line 24, not 30
+
+
+// ERROR "import path must be a string"
+
+
+
+// ERROR "syntax error: unexpected newline, expecting type|expected type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18410.go b/gcc/testsuite/go.test/test/fixedbugs/issue18410.go
new file mode 100644
index 0000000..e9c6f86
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18410.go
@@ -0,0 +1,40 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This checks partially initialized structure literals
+// used to create value.method functions have their
+// non-initialized fields properly zeroed/nil'd
+
+package main
+
+type X struct {
+ A, B, C *int
+}
+
+//go:noinline
+func (t X) Print() {
+ if t.B != nil {
+ panic("t.B must be nil")
+ }
+}
+
+//go:noinline
+func caller(f func()) {
+ f()
+}
+
+//go:noinline
+func test() {
+ var i, j int
+ x := X{A: &i, C: &j}
+ caller(func() { X{A: &i, C: &j}.Print() })
+ caller(X{A: &i, C: &j}.Print)
+ caller(x.Print)
+}
+
+func main() {
+ test()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/other.go b/gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/other.go
new file mode 100644
index 0000000..27243d2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/other.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package other
+
+type Exported struct {
+ Member int
+}
+
+func (e *Exported) member() int { return 1 }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/test.go b/gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/test.go
new file mode 100644
index 0000000..da9639d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18419.dir/test.go
@@ -0,0 +1,15 @@
+// errorcheck -0 -m -l
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./other"
+
+func InMyCode(e *other.Exported) {
+ e.member() // ERROR "e\.member undefined .cannot refer to unexported field or method other\.\(\*Exported\)\.member.|unexported field or method"
+}
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18419.go b/gcc/testsuite/go.test/test/fixedbugs/issue18419.go
new file mode 100644
index 0000000..25544ef
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18419.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18595.go b/gcc/testsuite/go.test/test/fixedbugs/issue18595.go
new file mode 100644
index 0000000..d6f07b3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18595.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test makes sure that itabs are unique.
+// More explicitly, we require that only one itab structure exists for the pair of
+// a given compile-time interface type and underlying concrete type.
+// Ensuring this invariant enables fixes for 18492 (improve type switch code).
+
+package main
+
+type I interface {
+ M()
+}
+type J interface {
+ M()
+}
+
+type T struct{}
+
+func (*T) M() {}
+
+func main() {
+ test1()
+ test2()
+}
+
+func test1() {
+ t := new(T)
+ var i1, i2 I
+ var j interface {
+ M()
+ }
+ i1 = t
+ j = t
+ i2 = j
+ if i1 != i2 {
+ panic("interfaces not equal")
+ }
+}
+
+func test2() {
+ t := new(T)
+ i1 := (I)(t)
+ i2 := (I)((interface {
+ M()
+ })((J)(t)))
+ if i1 != i2 {
+ panic("interfaces not equal")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18636.go b/gcc/testsuite/go.test/test/fixedbugs/issue18636.go
new file mode 100644
index 0000000..2704fc4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18636.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime/debug"
+
+type Foo struct {
+ A [1 << 20]byte
+ B string
+}
+
+func run(c chan bool) {
+ f := new(Foo)
+ *f = Foo{B: "hello"}
+ c <- true
+}
+
+func main() {
+ debug.SetMaxStack(1 << 16)
+ c := make(chan bool)
+ go run(c)
+ <-c
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18640.go b/gcc/testsuite/go.test/test/fixedbugs/issue18640.go
new file mode 100644
index 0000000..091bbe5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18640.go
@@ -0,0 +1,46 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+ a = b
+ b struct {
+ *a
+ }
+)
+
+type (
+ c struct {
+ *d
+ }
+ d = c
+)
+
+// The compiler cannot handle these cases. Disabled for now.
+// See issue #25838.
+/*
+type (
+ e = f
+ f = g
+ g = []h
+ h i
+ i = j
+ j = e
+)
+
+type (
+ a1 struct{ *b1 }
+ b1 = c1
+ c1 struct{ *b1 }
+)
+
+type (
+ a2 struct{ b2 }
+ b2 = c2
+ c2 struct{ *b2 }
+)
+*/
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18655.go b/gcc/testsuite/go.test/test/fixedbugs/issue18655.go
new file mode 100644
index 0000000..13762f1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18655.go
@@ -0,0 +1,22 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct{}
+type A = T
+type B = T
+
+func (T) m() {}
+func (T) m() {} // ERROR "redeclared|redefinition"
+func (A) m() {} // ERROR "redeclared|redefinition"
+func (A) m() {} // ERROR "redeclared|redefinition"
+func (B) m() {} // ERROR "redeclared|redefinition"
+func (B) m() {} // ERROR "redeclared|redefinition"
+
+func (*T) m() {} // ERROR "redeclared|redefinition"
+func (*A) m() {} // ERROR "redeclared|redefinition"
+func (*B) m() {} // ERROR "redeclared|redefinition"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18661.go b/gcc/testsuite/go.test/test/fixedbugs/issue18661.go
new file mode 100644
index 0000000..e64a771
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18661.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+var (
+ e interface{}
+ s = struct{ a *int }{}
+ b = e == s
+)
+
+func test(obj interface{}) {
+ if obj != struct{ a *string }{} {
+ }
+}
+
+var x int
+
+func f() [2]string {
+ x++
+ return [2]string{"abc", "def"}
+}
+
+func main() {
+ var e interface{} = [2]string{"abc", "def"}
+ _ = e == f()
+ if x != 1 {
+ fmt.Println("x=", x)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18725.go b/gcc/testsuite/go.test/test/fixedbugs/issue18725.go
new file mode 100644
index 0000000..c632dba
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18725.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "os"
+
+func panicWhenNot(cond bool) {
+ if cond {
+ os.Exit(0)
+ } else {
+ panic("nilcheck elim failed")
+ }
+}
+
+func main() {
+ e := (*string)(nil)
+ panicWhenNot(e == e)
+ // Should never reach this line.
+ panicWhenNot(*e == *e)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18808.go b/gcc/testsuite/go.test/test/fixedbugs/issue18808.go
new file mode 100644
index 0000000..c98386e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18808.go
@@ -0,0 +1,63 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+const lim = 0x80000000
+
+//go:noinline
+func eq(x uint32) {
+ if x == lim {
+ return
+ }
+ panic("x == lim returned false")
+}
+
+//go:noinline
+func neq(x uint32) {
+ if x != lim {
+ panic("x != lim returned true")
+ }
+}
+
+//go:noinline
+func gt(x uint32) {
+ if x > lim {
+ return
+ }
+ panic("x > lim returned false")
+}
+
+//go:noinline
+func gte(x uint32) {
+ if x >= lim {
+ return
+ }
+ panic("x >= lim returned false")
+}
+
+//go:noinline
+func lt(x uint32) {
+ if x < lim {
+ panic("x < lim returned true")
+ }
+}
+
+//go:noinline
+func lte(x uint32) {
+ if x <= lim {
+ panic("x <= lim returned true")
+ }
+}
+
+func main() {
+ eq(lim)
+ neq(lim)
+ gt(lim+1)
+ gte(lim+1)
+ lt(lim+1)
+ lte(lim+1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18906.go b/gcc/testsuite/go.test/test/fixedbugs/issue18906.go
new file mode 100644
index 0000000..544400b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18906.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:noinline
+func f(x int) {
+}
+
+//go:noinline
+func val() int8 {
+ return -1
+}
+
+var (
+ array = [257]int{}
+ slice = array[1:]
+)
+
+func init() {
+ for i := range array {
+ array[i] = i - 1
+ }
+}
+
+func main() {
+ x := val()
+ y := int(uint8(x))
+ f(y) // try and force y to be calculated and spilled
+ if slice[y] != 255 {
+ panic("incorrect value")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18915.go b/gcc/testsuite/go.test/test/fixedbugs/issue18915.go
new file mode 100644
index 0000000..22f97c6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18915.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure error message for invalid conditions
+// or tags are consistent with earlier Go versions.
+
+package p
+
+func _() {
+ if a := 10 { // ERROR "cannot use a := 10 as value|expected .*;|declared but not used"
+ }
+
+ for b := 10 { // ERROR "cannot use b := 10 as value|parse error|declared but not used"
+ }
+
+ switch c := 10 { // ERROR "cannot use c := 10 as value|expected .*;|declared but not used"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue18994.go b/gcc/testsuite/go.test/test/fixedbugs/issue18994.go
new file mode 100644
index 0000000..aa30713
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue18994.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 18994: SSA didn't handle DOT STRUCTLIT for zero-valued
+// STRUCTLIT.
+
+package main
+
+// large struct - not SSA-able
+type T struct {
+ a, b, c, d, e, f, g, h int
+}
+
+func main() {
+ x := T{}.a
+ if x != 0 {
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19012.go b/gcc/testsuite/go.test/test/fixedbugs/issue19012.go
new file mode 100644
index 0000000..158618a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19012.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19012: if we have any unknown type at a call site,
+// we must ensure that we return to the user a suppressed
+// error message saying instead of including <T> in
+// the message.
+
+package main
+
+func f(x int, y uint) {
+ if true {
+ return "a" > 10 // ERROR "^too many arguments to return$|return with value in function with no return|mismatched types"
+ }
+ return "gopher" == true, 10 // ERROR "^too many arguments to return$|return with value in function with no return|mismatched types"
+}
+
+func main() {
+ f(2, 3 < "x", 10) // ERROR "too many arguments|invalid operation|incompatible type"
+
+ f(10, 10, "a") // ERROR "too many arguments"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/a.go
new file mode 100644
index 0000000..361251d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect
+
+import "reflect"
+
+type Type reflect.Type
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/main.go
new file mode 100644
index 0000000..e2ee7b8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19028.dir/main.go
@@ -0,0 +1,26 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "reflect"
+ fake "./a" // 2nd package with name "reflect"
+)
+
+type T struct {
+ _ fake.Type
+}
+
+func (T) f() {}
+func (T) G() (_ int) { return }
+func (T) H() (_, _ int) { return }
+
+func main() {
+ var x T
+ typ := reflect.TypeOf(x)
+ for i := 0; i < typ.NumMethod(); i++ {
+ _ = typ.Method(i) // must not crash
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19028.go b/gcc/testsuite/go.test/test/fixedbugs/issue19028.go
new file mode 100644
index 0000000..8d934d2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19028.go
@@ -0,0 +1,13 @@
+// rundir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test failed when the compiler didn't use the
+// correct code to identify the type reflect.Method.
+// The failing code relied on Type.String() which had
+// formatting that depended on whether a package (in
+// this case "reflect") was imported more than once.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19040.go b/gcc/testsuite/go.test/test/fixedbugs/issue19040.go
new file mode 100644
index 0000000..67881df
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19040.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check the text of the panic that comes from
+// a nil pointer passed to automatically generated method wrapper.
+
+package main
+
+import "fmt"
+
+type T int
+
+type I interface {
+ F()
+}
+
+func (t T) F() {}
+
+var (
+ t *T
+ i I = t
+)
+
+func main() {
+ defer func() {
+ got := recover().(error).Error()
+ want := "value method main.T.F called using nil *T pointer"
+ if got != want {
+ fmt.Printf("panicwrap error text:\n\t%q\nwant:\n\t%q\n", got, want)
+ }
+ }()
+ i.F()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19056.go b/gcc/testsuite/go.test/test/fixedbugs/issue19056.go
new file mode 100644
index 0000000..d279eaa
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19056.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = ... . // ERROR "unexpected ...|expected operand|expected .*;"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19078.go b/gcc/testsuite/go.test/test/fixedbugs/issue19078.go
new file mode 100644
index 0000000..b19e874
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19078.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19078: liveness & zero-initialization of results
+// when there is a defer.
+package main
+
+import "unsafe"
+
+func main() {
+ // Construct an invalid pointer. We do this by
+ // making a pointer which points to the unused space
+ // between the last 48-byte object in a span and the
+ // end of the span (there are 32 unused bytes there).
+ p := new([48]byte) // make a 48-byte object
+ sink = &p // escape it, so it allocates for real
+ u := uintptr(unsafe.Pointer(p)) // get its address
+ u = u >> 13 << 13 // round down to page size
+ u += 1<<13 - 1 // add almost a page
+
+ for i := 0; i < 1000000; i++ {
+ _ = identity(u) // installs u at return slot
+ _ = liveReturnSlot(nil) // incorrectly marks return slot as live
+ }
+}
+
+//go:noinline
+func liveReturnSlot(x *int) *int {
+ defer func() {}() // causes return slot to be marked live
+ sink = &x // causes x to be moved to the heap, triggering allocation
+ return x
+}
+
+//go:noinline
+func identity(x uintptr) uintptr {
+ return x
+}
+
+var sink interface{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19084.go b/gcc/testsuite/go.test/test/fixedbugs/issue19084.go
new file mode 100644
index 0000000..ba53063
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19084.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19084: SSA doesn't handle CONVNOP STRUCTLIT
+
+package p
+
+type T struct {
+ a, b, c, d, e, f, g, h int // big, not SSA-able
+}
+
+func f() {
+ _ = T(T{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19113.go b/gcc/testsuite/go.test/test/fixedbugs/issue19113.go
new file mode 100644
index 0000000..5e01dde
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19113.go
@@ -0,0 +1,108 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "reflect"
+
+var tests = []interface{}{
+ func(x int, s int) int {
+ return x << s
+ },
+ func(x int, s int64) int {
+ return x << s
+ },
+ func(x int, s int32) int {
+ return x << s
+ },
+ func(x int, s int16) int {
+ return x << s
+ },
+ func(x int, s int8) int {
+ return x << s
+ },
+ func(x int, s int) int {
+ return x >> s
+ },
+ func(x int, s int64) int {
+ return x >> s
+ },
+ func(x int, s int32) int {
+ return x >> s
+ },
+ func(x int, s int16) int {
+ return x >> s
+ },
+ func(x int, s int8) int {
+ return x >> s
+ },
+ func(x uint, s int) uint {
+ return x << s
+ },
+ func(x uint, s int64) uint {
+ return x << s
+ },
+ func(x uint, s int32) uint {
+ return x << s
+ },
+ func(x uint, s int16) uint {
+ return x << s
+ },
+ func(x uint, s int8) uint {
+ return x << s
+ },
+ func(x uint, s int) uint {
+ return x >> s
+ },
+ func(x uint, s int64) uint {
+ return x >> s
+ },
+ func(x uint, s int32) uint {
+ return x >> s
+ },
+ func(x uint, s int16) uint {
+ return x >> s
+ },
+ func(x uint, s int8) uint {
+ return x >> s
+ },
+}
+
+func main() {
+ for _, t := range tests {
+ runTest(reflect.ValueOf(t))
+ }
+}
+
+func runTest(f reflect.Value) {
+ xt := f.Type().In(0)
+ st := f.Type().In(1)
+
+ for _, x := range []int{1, 0, -1} {
+ for _, s := range []int{-99, -64, -63, -32, -31, -16, -15, -8, -7, -1, 0, 1, 7, 8, 15, 16, 31, 32, 63, 64, 99} {
+ args := []reflect.Value{
+ reflect.ValueOf(x).Convert(xt),
+ reflect.ValueOf(s).Convert(st),
+ }
+ if s < 0 {
+ shouldPanic(func() {
+ f.Call(args)
+ })
+ } else {
+ f.Call(args) // should not panic
+ }
+ }
+ }
+}
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("did not panic")
+ }
+ }()
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19137.go b/gcc/testsuite/go.test/test/fixedbugs/issue19137.go
new file mode 100644
index 0000000..0539a85
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19137.go
@@ -0,0 +1,51 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19137: folding address into load/store causes
+// odd offset on ARM64.
+
+package p
+
+type T struct {
+ p *int
+ a [2]byte
+ b [6]byte // not 4-byte aligned
+}
+
+func f(b [6]byte) T {
+ var x [1000]int // a large stack frame
+ _ = x
+ return T{b: b}
+}
+
+// Arg symbol's base address may be not at an aligned offset to
+// SP. Folding arg's address into load/store may cause odd offset.
+func move(a, b [20]byte) [20]byte {
+ var x [1000]int // a large stack frame
+ _ = x
+ return b // b is not 8-byte aligned to SP
+}
+func zero() ([20]byte, [20]byte) {
+ var x [1000]int // a large stack frame
+ _ = x
+ return [20]byte{}, [20]byte{} // the second return value is not 8-byte aligned to SP
+}
+
+// Issue 21992: unaligned offset between 256 and 504 and handled
+// incorrectly.
+type T2 struct {
+ a [257]byte
+ // fields below are not 8-, 4-, 2-byte aligned
+ b [8]byte
+ c [4]byte
+ d [2]byte
+}
+
+func f2(x *T2) {
+ x.b = [8]byte{}
+ x.c = [4]byte{}
+ x.d = [2]byte{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19182.go b/gcc/testsuite/go.test/test/fixedbugs/issue19182.go
new file mode 100644
index 0000000..e1f3ffb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19182.go
@@ -0,0 +1,37 @@
+// run
+// +build !js
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "sync/atomic"
+ "time"
+)
+
+var a uint64 = 0
+
+func main() {
+ runtime.GOMAXPROCS(2) // With just 1, infinite loop never yields
+
+ go func() {
+ for {
+ atomic.AddUint64(&a, uint64(1))
+ }
+ }()
+
+ time.Sleep(10 * time.Millisecond) // Short sleep is enough in passing case
+ i, val := 0, atomic.LoadUint64(&a)
+ for ; val == 0 && i < 100; val, i = atomic.LoadUint64(&a), i+1 {
+ time.Sleep(100 * time.Millisecond)
+ }
+ if val == 0 {
+ fmt.Printf("Failed to observe atomic increment after %d tries\n", i)
+ }
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19201.go b/gcc/testsuite/go.test/test/fixedbugs/issue19201.go
new file mode 100644
index 0000000..e370d55
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19201.go
@@ -0,0 +1,52 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/binary"
+)
+
+var (
+ ch1 = make(chan int)
+ ch2 = make(chan int)
+
+ bin = []byte("a\000\000\001")
+ want = binary.BigEndian.Uint32(bin)
+
+ c consumer = noopConsumer{}
+)
+
+type msg struct {
+ code uint32
+}
+
+type consumer interface {
+ consume(msg)
+}
+
+type noopConsumer struct{}
+
+func (noopConsumer) consume(msg) {}
+
+func init() {
+ close(ch1)
+}
+
+func main() {
+ var m msg
+ m.code = binary.BigEndian.Uint32(bin)
+
+ select {
+ case <-ch1:
+ c.consume(m)
+ if m.code != want {
+ // can not use m.code here, or it will work
+ panic("BigEndian read failed")
+ }
+ case <-ch2:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19217.go b/gcc/testsuite/go.test/test/fixedbugs/issue19217.go
new file mode 100644
index 0000000..9679406
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19217.go
@@ -0,0 +1,39 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+import (
+ "encoding/binary"
+)
+
+type DbBuilder struct {
+ arr []int
+}
+
+func (bld *DbBuilder) Finish() error {
+ defer bld.Finish()
+
+ var hash []byte
+ for _, ixw := range bld.arr {
+ for {
+ if ixw != 0 {
+ panic("ixw != 0")
+ }
+ ixw--
+ insertOne:
+ for {
+ for i := 0; i < 1; i++ {
+ if binary.LittleEndian.Uint16(hash[i:]) == 0 {
+ break insertOne
+ }
+ }
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19275.go b/gcc/testsuite/go.test/test/fixedbugs/issue19275.go
new file mode 100644
index 0000000..f7e64fc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19275.go
@@ -0,0 +1,72 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+type PI struct {
+ Enabled bool
+}
+
+type SI struct {
+ M map[string]*PI
+}
+
+//go:noinline
+func (s *SI) test(name string) (*int, error) {
+ n := new(int)
+ *n = 99
+ if err := addUpdate(n, s.M[name].Enabled, "enabled"); err != nil { // this was miscompiled
+ return nil, fmt.Errorf(" error adding update for enable flag %t : %s",
+ s.M[name].Enabled, err)
+ }
+ return n, nil
+}
+
+//go:noinline
+func addUpdate(n *int, in interface{}, s ...string) error {
+ if *n != 99 {
+ println("FAIL, *n should be 99, not", *n)
+ }
+ return nil
+}
+
+func main1() {
+ s := &SI{make(map[string]*PI)}
+ s.M["dog"] = &PI{}
+ s.test("dog")
+}
+
+//go:noinline
+func g(b *byte, i interface{}) error {
+ if *b != 17 {
+ println("FAIL, *b should be 17, not", *b)
+ }
+ return nil
+}
+
+//go:noinline
+func f(x *byte, m map[string]*bool) {
+ if err := g(x, *m["hello"]); err != nil { // this was miscompiled
+ return
+ }
+}
+
+func main2() {
+ m := make(map[string]*bool)
+ x := false
+ m["hello"] = &x
+ b := byte(17)
+ f(&b, m)
+}
+
+func main() {
+ main2()
+ main1()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19323.go b/gcc/testsuite/go.test/test/fixedbugs/issue19323.go
new file mode 100644
index 0000000..71365e1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19323.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func g() {}
+
+func f() {
+ g()[:] // ERROR "g.. used as value|attempt to slice object that is not"
+}
+
+func g2() ([]byte, []byte) { return nil, nil }
+
+func f2() {
+ g2()[:] // ERROR "multiple-value g2.. in single-value context|attempt to slice object that is not"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19359.go b/gcc/testsuite/go.test/test/fixedbugs/issue19359.go
new file mode 100644
index 0000000..cc3ecc8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19359.go
@@ -0,0 +1,91 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func set(m map[interface{}]interface{}, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("set failed: %v", r)
+ }
+ }()
+ m[key] = nil
+ return nil
+}
+
+func del(m map[interface{}]interface{}, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("del failed: %v", r)
+ }
+ }()
+ delete(m, key)
+ return nil
+}
+
+func addInt(m map[interface{}]int, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("addInt failed: %v", r)
+ }
+ }()
+ m[key] += 2018
+ return nil
+}
+
+func addStr(m map[interface{}]string, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("addStr failed: %v", r)
+ }
+ }()
+ m[key] += "hello, go"
+ return nil
+}
+
+func appendInt(m map[interface{}][]int, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("appendInt failed: %v", r)
+ }
+ }()
+ m[key] = append(m[key], 2018)
+ return nil
+}
+
+func appendStr(m map[interface{}][]string, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("addStr failed: %v", r)
+ }
+ }()
+ m[key] = append(m[key], "hello, go")
+ return nil
+}
+
+func main() {
+ m := make(map[interface{}]interface{})
+ set(m, []int{1, 2, 3})
+ set(m, "abc") // used to throw
+ del(m, []int{1, 2, 3})
+ del(m, "abc") // used to throw
+
+ mi := make(map[interface{}]int)
+ addInt(mi, []int{1, 2, 3})
+ addInt(mi, "abc") // used to throw
+
+ ms := make(map[interface{}]string)
+ addStr(ms, []int{1, 2, 3})
+ addStr(ms, "abc") // used to throw
+
+ mia := make(map[interface{}][]int)
+ appendInt(mia, []int{1, 2, 3})
+
+ msa := make(map[interface{}][]string)
+ appendStr(msa, "abc") // used to throw
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19482.go b/gcc/testsuite/go.test/test/fixedbugs/issue19482.go
new file mode 100644
index 0000000..4c2c19e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19482.go
@@ -0,0 +1,34 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Compiler rejected initialization of structs to composite literals
+// in a non-static setting (e.g. in a function)
+// when the struct contained a field named _.
+
+package p
+
+type T struct {
+ _ string
+}
+
+func ok() {
+ var x = T{"check"}
+ _ = x
+ _ = T{"et"}
+}
+
+var (
+ y = T{"stare"}
+ w = T{_: "look"} // ERROR "invalid field name _ in struct initializer|expected struct field name"
+ _ = T{"page"}
+ _ = T{_: "out"} // ERROR "invalid field name _ in struct initializer|expected struct field name"
+)
+
+func bad() {
+ var z = T{_: "verse"} // ERROR "invalid field name _ in struct initializer|expected struct field name"
+ _ = z
+ _ = T{_: "itinerary"} // ERROR "invalid field name _ in struct initializer|expected struct field name"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/div_arm.s b/gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/div_arm.s
new file mode 100644
index 0000000..0bc33e9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/div_arm.s
@@ -0,0 +1,12 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+TEXT ·f(SB),0,$0-8
+ MOVW x+0(FP), R1
+ MOVW x+4(FP), R2
+ DIVU R1, R2
+ DIV R1, R2
+ MODU R1, R2
+ MOD R1, R2
+ RET
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/main.go
new file mode 100644
index 0000000..c115556
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19507.dir/main.go
@@ -0,0 +1,16 @@
+// +build arm
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we can compile assembly with DIV and MOD in it.
+// They get rewritten to runtime calls on GOARM=5.
+
+package main
+
+func f(x, y uint32)
+
+func main() {
+ f(5, 8)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19507.go b/gcc/testsuite/go.test/test/fixedbugs/issue19507.go
new file mode 100644
index 0000000..543e17e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19507.go
@@ -0,0 +1,8 @@
+// +build arm
+// builddir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19515.go b/gcc/testsuite/go.test/test/fixedbugs/issue19515.go
new file mode 100644
index 0000000..a1605be
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19515.go
@@ -0,0 +1,51 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19515: compiler panics on spilling int128 constant.
+
+package x
+
+type VScrollPanel struct {
+ x, y int
+}
+
+type Color struct {
+ R, G, B, A float32
+}
+
+func maxF(a, b float32) float32 {
+ if a > b {
+ return 0
+ }
+ return 1
+}
+
+type TransformMatrix [6]float32
+
+type Paint struct {
+ xform TransformMatrix
+ feather float32
+ innerColor Color
+ outerColor Color
+}
+
+func BoxGradient(x, y, w, h, f float32, iColor, oColor Color) Paint {
+ return Paint{
+ xform: TransformMatrix{9, 0, 0, 0, x, y},
+ feather: maxF(1.0, f),
+ innerColor: iColor,
+ outerColor: oColor,
+ }
+}
+
+func (v *VScrollPanel) Draw() {
+ x := float32(v.x)
+ y := float32(v.y)
+
+ BoxGradient(x+x-2, y-1, 0, 0, 0, Color{}, Color{})
+ BoxGradient(x+y-2, y-1, 0, 0, 0, Color{}, Color{})
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/a.go
new file mode 100644
index 0000000..3b7cd4b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/a.go
@@ -0,0 +1,26 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Mode uint
+
+func (m Mode) String() string { return "mode string" }
+func (m *Mode) Addr() *Mode { return m }
+
+type Stringer interface {
+ String() string
+}
+
+var global Stringer
+var m Mode
+
+func init() {
+ // force compilation of the (*Mode).String() wrapper
+ global = &m
+}
+
+func String() string {
+ return global.String() + Mode(0).String()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/b.go
new file mode 100644
index 0000000..e5e807f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19548.dir/b.go
@@ -0,0 +1,24 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+type Value interface {
+ a.Stringer
+ Addr() *a.Mode
+}
+
+var global a.Mode
+
+func f() int {
+ var v Value
+ v = &global
+ return int(v.String()[0])
+}
+
+func main() {
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19548.go b/gcc/testsuite/go.test/test/fixedbugs/issue19548.go
new file mode 100644
index 0000000..e0e7693
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19548.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that interface wrappers can be compiled successfully
+// in multiple translation units.
+package ignore
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19555.go b/gcc/testsuite/go.test/test/fixedbugs/issue19555.go
new file mode 100644
index 0000000..53b2ebde
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19555.go
@@ -0,0 +1,36 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type NodeLink struct{}
+
+// A role our end of NodeLink is intended to play
+type LinkRole int64
+
+const (
+ LinkServer LinkRole = iota // link created as server
+ LinkClient // link created as client
+
+ // for testing:
+ linkNoRecvSend LinkRole = 1 << 16 // do not spawn serveRecv & serveSend
+ linkFlagsMask LinkRole = (1<<32 - 1) << 16
+)
+
+func NewNodeLink(role LinkRole) *NodeLink {
+ var nextConnId uint32
+ switch role &^ linkFlagsMask {
+ case LinkServer:
+ nextConnId = 0 // all initiated by us connId will be even
+ case LinkClient:
+ nextConnId = 1 // ----//---- odd
+ default:
+ panic("invalid conn role")
+ }
+
+ _ = nextConnId
+ return nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19632.go b/gcc/testsuite/go.test/test/fixedbugs/issue19632.go
new file mode 100644
index 0000000..41cb1ff
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19632.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that we don't crash due to "lost track of variable in
+// liveness" errors against unused variables.
+
+package p
+
+import "strings"
+
+// Minimized test case from github.com/mvdan/sh/syntax.
+func F() {
+ var _ = []string{
+ strings.Repeat("\n\n\t\t \n", 10) +
+ "# " + strings.Repeat("foo bar ", 10) + "\n" +
+ strings.Repeat("longlit_", 10) + "\n",
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19658.go b/gcc/testsuite/go.test/test/fixedbugs/issue19658.go
new file mode 100644
index 0000000..bab409c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19658.go
@@ -0,0 +1,99 @@
+// +build !nacl,!js,!gccgo
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// ensure that panic(x) where x is a numeric type displays a readable number
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+const fn = `
+package main
+
+import "errors"
+type S struct {
+
+}
+func (s S) String() string {
+ return "s-stringer"
+}
+func main() {
+ _ = errors.New
+ panic(%s(%s))
+}
+`
+
+func main() {
+ tempDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(tempDir)
+ tmpFile := filepath.Join(tempDir, "tmp.go")
+
+ for _, tc := range []struct {
+ Type string
+ Input string
+ Expect string
+ }{{"", "nil", "panic: nil"},
+ {"errors.New", `"test"`, "panic: test"},
+ {"S", "S{}", "panic: s-stringer"},
+ {"byte", "8", "panic: 8"},
+ {"rune", "8", "panic: 8"},
+ {"int", "8", "panic: 8"},
+ {"int8", "8", "panic: 8"},
+ {"int16", "8", "panic: 8"},
+ {"int32", "8", "panic: 8"},
+ {"int64", "8", "panic: 8"},
+ {"uint", "8", "panic: 8"},
+ {"uint8", "8", "panic: 8"},
+ {"uint16", "8", "panic: 8"},
+ {"uint32", "8", "panic: 8"},
+ {"uint64", "8", "panic: 8"},
+ {"uintptr", "8", "panic: 8"},
+ {"bool", "true", "panic: true"},
+ {"complex64", "8 + 16i", "panic: (+8.000000e+000+1.600000e+001i)"},
+ {"complex128", "8+16i", "panic: (+8.000000e+000+1.600000e+001i)"},
+ {"string", `"test"`, "panic: test"}} {
+
+ b := bytes.Buffer{}
+ fmt.Fprintf(&b, fn, tc.Type, tc.Input)
+
+ err = ioutil.WriteFile(tmpFile, b.Bytes(), 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ cmd := exec.Command("go", "run", tmpFile)
+ var buf bytes.Buffer
+ cmd.Stdout = &buf
+ cmd.Stderr = &buf
+ cmd.Env = os.Environ()
+ cmd.Run() // ignore err as we expect a panic
+
+ out := buf.Bytes()
+ panicIdx := bytes.Index(out, []byte("panic: "))
+ if panicIdx == -1 {
+ log.Fatalf("expected a panic in output for %s, got: %s", tc.Type, out)
+ }
+ eolIdx := bytes.IndexByte(out[panicIdx:], '\n') + panicIdx
+ if panicIdx == -1 {
+ log.Fatalf("expected a newline in output for %s after the panic, got: %s", tc.Type, out)
+ }
+ out = out[0:eolIdx]
+ if string(out) != tc.Expect {
+ log.Fatalf("expected '%s' for panic(%s(%s)), got %s", tc.Expect, tc.Type, tc.Input, out)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19667.go b/gcc/testsuite/go.test/test/fixedbugs/issue19667.go
new file mode 100644
index 0000000..e33e350
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19667.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we don't crash when reporting this error.
+
+package p
+
+func f() {
+ if err := http.ListenAndServe( // GCCGO_ERROR "undefined name"
+} // ERROR "unexpected }, expecting expression|expected operand|missing .*\)|expected .*;|expected .*{"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19671.go b/gcc/testsuite/go.test/test/fixedbugs/issue19671.go
new file mode 100644
index 0000000..475c3e0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19671.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to crash when compiling assignments involving [0]T,
+// where T is not SSA-able.
+
+package a
+
+func f() {
+ var i int
+ arr := [0][2]int{}
+ arr[i][0] = 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19678.go b/gcc/testsuite/go.test/test/fixedbugs/issue19678.go
new file mode 100644
index 0000000..81ef331
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19678.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to crash when compiling functions containing
+// forward refs in dead code.
+
+package p
+
+var f func(int)
+
+func g() {
+l1:
+ i := 0
+ goto l1
+l2:
+ f(i)
+ goto l2
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19679.go b/gcc/testsuite/go.test/test/fixedbugs/issue19679.go
new file mode 100644
index 0000000..636b27f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19679.go
@@ -0,0 +1,38 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to crash when a type switch was present in dead code
+// in an inlineable function.
+
+package p
+
+func Then() {
+ var i interface{}
+ if false {
+ switch i.(type) {
+ }
+ }
+}
+
+func Else() {
+ var i interface{}
+ if true {
+ _ = i
+ } else {
+ switch i.(type) {
+ }
+ }
+}
+
+func Switch() {
+ var i interface{}
+ switch 5 {
+ case 3:
+ switch i.(type) {
+ }
+ case 5:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19696.go b/gcc/testsuite/go.test/test/fixedbugs/issue19696.go
new file mode 100644
index 0000000..4cb2789
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19696.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to crash when compiling assignments involving [0]T,
+// where T is not SSA-able.
+
+package p
+
+type s struct {
+ a, b, c, d, e int
+}
+
+func f() {
+ var i int
+ arr := [0]s{}
+ arr[i].a++
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19699b.go b/gcc/testsuite/go.test/test/fixedbugs/issue19699b.go
new file mode 100644
index 0000000..4afc0ca
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19699b.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() bool {
+ if false {
+ } else {
+ return true
+ }
+} // ERROR "missing return at end of function"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19705.go b/gcc/testsuite/go.test/test/fixedbugs/issue19705.go
new file mode 100644
index 0000000..6157945
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19705.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1() {
+ f2()
+}
+
+func f2() {
+ if false {
+ _ = func() {}
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19710.go b/gcc/testsuite/go.test/test/fixedbugs/issue19710.go
new file mode 100644
index 0000000..c42ea7c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19710.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19710: mishandled defer delete(...)
+
+package main
+
+func main() {
+ if n := len(f()); n != 0 {
+ println("got", n, "want 0")
+ panic("bad defer delete")
+ }
+}
+
+func f() map[int]bool {
+ m := map[int]bool{}
+ for i := 0; i < 3; i++ {
+ m[i] = true
+ defer delete(m, i)
+ }
+ return m
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19743.go b/gcc/testsuite/go.test/test/fixedbugs/issue19743.go
new file mode 100644
index 0000000..5089cc6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19743.go
@@ -0,0 +1,31 @@
+// errorcheck -0 -m -l
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+// Escape analysis needs to treat the uintptr-typed reflect.*Header fields as pointers.
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+type immutableBytes []byte
+
+// Bug was failure to leak param b.
+func toString(b immutableBytes) string { // ERROR "leaking param: b$"
+ var s string
+ if len(b) == 0 {
+ return s
+ }
+
+ strHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
+ strHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data
+
+ l := len(b)
+ strHeader.Len = l
+ return s
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/a.go
new file mode 100644
index 0000000..64538e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T struct{ _ int }
+func (t T) M() {}
+
+type I interface { M() }
+
+func F() {
+ var t I = &T{}
+ t.M() // call to the wrapper (*T).M
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/b.go
new file mode 100644
index 0000000..d39f125
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19764.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ var x a.I = &a.T{}
+ x.M() // call to the wrapper (*T).M
+ a.F() // make sure a.F is not dead, which also calls (*T).M inside package a
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19764.go b/gcc/testsuite/go.test/test/fixedbugs/issue19764.go
new file mode 100644
index 0000000..26fb00b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19764.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19764: test that the linker's trampoline insertion
+// pass is happy with direct calls to interface wrappers that
+// may be defined in multiple packages.
+package ignore
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19783.go b/gcc/testsuite/go.test/test/fixedbugs/issue19783.go
new file mode 100644
index 0000000..8d6494e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19783.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func Spin() {
+l1:
+ for true {
+ goto l1
+ l2:
+ if true {
+ goto l2
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19799.go b/gcc/testsuite/go.test/test/fixedbugs/issue19799.go
new file mode 100644
index 0000000..cb675d7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19799.go
@@ -0,0 +1,71 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os"
+ "runtime"
+)
+
+func foo(x int) int {
+ return x + 1
+}
+
+func test() {
+ defer func() {
+ if r := recover(); r != nil {
+ pcs := make([]uintptr, 10)
+ n := runtime.Callers(0, pcs)
+ pcs = pcs[:n]
+ frames := runtime.CallersFrames(pcs)
+ for {
+ f, more := frames.Next()
+ if f.Function == "main.foo" {
+ println("did not expect to see call to foo in stack trace")
+ os.Exit(1)
+ }
+ if !more {
+ break
+ }
+ }
+ }
+ }()
+ var v []int
+ foo(v[0])
+}
+
+func bar(x ...int) int {
+ return x[0] + 1
+}
+
+func testVariadic() {
+ defer func() {
+ if r := recover(); r != nil {
+ pcs := make([]uintptr, 10)
+ n := runtime.Callers(0, pcs)
+ pcs = pcs[:n]
+ frames := runtime.CallersFrames(pcs)
+ for {
+ f, more := frames.Next()
+ if f.Function == "main.bar" {
+ println("did not expect to see call to bar in stack trace")
+ os.Exit(1)
+ }
+ if !more {
+ break
+ }
+ }
+ }
+ }()
+ var v []int
+ bar(v[0])
+}
+
+func main() {
+ test()
+ testVariadic()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19880.go b/gcc/testsuite/go.test/test/fixedbugs/issue19880.go
new file mode 100644
index 0000000..3d83cf3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19880.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct {
+ f [1]int
+}
+
+func a() {
+ _ = T // ERROR "type T is not an expression|invalid use of type"
+}
+
+func b() {
+ var v [len(T{}.f)]int // ok
+ _ = v
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19911.go b/gcc/testsuite/go.test/test/fixedbugs/issue19911.go
new file mode 100644
index 0000000..af7f5981
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19911.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+type ET struct{}
+
+func (*ET) Error() string { return "err" }
+
+func main() {
+ check("false", fmt.Sprintf("(*ET)(nil) == error(nil): %v", (*ET)(nil) == error(nil)))
+ check("true", fmt.Sprintf("(*ET)(nil) != error(nil): %v", (*ET)(nil) != error(nil)))
+
+ nilET := (*ET)(nil)
+ nilError := error(nil)
+
+ check("false", fmt.Sprintf("nilET == nilError: %v", nilET == nilError))
+ check("true", fmt.Sprintf("nilET != nilError: %v", nilET != nilError))
+}
+
+func check(want, gotfull string) {
+ got := gotfull[strings.Index(gotfull, ": ")+len(": "):]
+ if got != want {
+ panic("want " + want + " got " + got + " from " + gotfull)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue19977.go b/gcc/testsuite/go.test/test/fixedbugs/issue19977.go
new file mode 100644
index 0000000..6e4a9cc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue19977.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 19977: multiple error messages when type switching on an undefined
+
+package foo
+
+func Foo() {
+ switch x := a.(type) { // ERROR "undefined: a|reference to undefined name .*a"
+ default:
+ _ = x
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20029.go b/gcc/testsuite/go.test/test/fixedbugs/issue20029.go
new file mode 100644
index 0000000..db3f8aa
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20029.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20029: make sure we zero at VARKILLs of
+// ambiguously live variables.
+// The ambiguously live variable here is the hiter
+// for the inner range loop.
+
+package main
+
+import "runtime"
+
+func f(m map[int]int) {
+outer:
+ for i := 0; i < 10; i++ {
+ for k := range m {
+ if k == 5 {
+ continue outer
+ }
+ }
+ runtime.GC()
+ break
+ }
+ runtime.GC()
+}
+func main() {
+ m := map[int]int{1: 2, 2: 3, 3: 4}
+ f(m)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20097.go b/gcc/testsuite/go.test/test/fixedbugs/issue20097.go
new file mode 100644
index 0000000..236a1bd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20097.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20097: ensure that we CSE multiple Select ops with
+// the same underlying type
+
+package main
+
+type T int64
+
+func f(x, y int64) (int64, T) {
+ a := x / y
+ b := T(x) / T(y)
+ return a, b
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20145.go b/gcc/testsuite/go.test/test/fixedbugs/issue20145.go
new file mode 100644
index 0000000..67ba5ae
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20145.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20145: some func types weren't dowidth-ed by the front end,
+// leading to races in the backend.
+
+package p
+
+func f() {
+ _ = (func())(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20185.go b/gcc/testsuite/go.test/test/fixedbugs/issue20185.go
new file mode 100644
index 0000000..9065868
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20185.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20185: type switching on untyped values (e.g. nil or consts)
+// caused an internal compiler error.
+
+package p
+
+func F() {
+ switch t := nil.(type) { // ERROR "cannot type switch on non-interface value"
+ default:
+ _ = t
+ }
+}
+
+const x = 1
+
+func G() {
+ switch t := x.(type) { // ERROR "cannot type switch on non-interface value|declared but not used"
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20227.go b/gcc/testsuite/go.test/test/fixedbugs/issue20227.go
new file mode 100644
index 0000000..f599231
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20227.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20227: panic while constructing constant "1i/1e-600000000"
+
+package p
+
+var _ = 1 / 1e-600000000i // ERROR "division by zero"
+var _ = 1i / 1e-600000000 // ERROR "division by zero"
+var _ = 1i / 1e-600000000i // ERROR "division by zero"
+
+var _ = 1 / (1e-600000000 + 1e-600000000i) // ERROR "division by zero"
+var _ = 1i / (1e-600000000 + 1e-600000000i) // ERROR "division by zero"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20333.go b/gcc/testsuite/go.test/test/fixedbugs/issue20333.go
new file mode 100644
index 0000000..8202ab3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20333.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20333: early checkwidth of [...] arrays led to compilation errors.
+
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println(&[...]string{"abc", "def", "ghi"})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20335.go b/gcc/testsuite/go.test/test/fixedbugs/issue20335.go
new file mode 100644
index 0000000..185c2f0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20335.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20335: don't reorder loads with stores.
+// This test should fail on the ssacheck builder
+// without the fix in the CL that added this file.
+// TODO: check the generated assembly?
+
+package a
+
+import "sync/atomic"
+
+func f(p, q *int32) bool {
+ x := *q
+ return atomic.AddInt32(p, 1) == x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20415.go b/gcc/testsuite/go.test/test/fixedbugs/issue20415.go
new file mode 100644
index 0000000..9e7649f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20415.go
@@ -0,0 +1,33 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure redeclaration errors report correct position.
+
+package p
+
+// 1
+var f byte
+
+var f interface{} // ERROR "previous declaration at issue20415.go:12|redefinition"
+
+func _(f int) {
+}
+
+// 2
+var g byte
+
+func _(g int) {
+}
+
+var g interface{} // ERROR "previous declaration at issue20415.go:20|redefinition"
+
+// 3
+func _(h int) {
+}
+
+var h byte
+
+var h interface{} // ERROR "previous declaration at issue20415.go:31|redefinition"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20529.go b/gcc/testsuite/go.test/test/fixedbugs/issue20529.go
new file mode 100644
index 0000000..eeaaf37
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20529.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// +build amd64
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20529: Large stack frames caused compiler panics.
+// Only tested on amd64 because the test only makes sense
+// on a 64 bit system, and it is platform-agnostic,
+// so testing one suffices.
+
+package p
+
+import "runtime"
+
+func f() { // GC_ERROR "stack frame too large"
+ x := [][]int{1e9: []int{}}
+ runtime.KeepAlive(x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20530.go b/gcc/testsuite/go.test/test/fixedbugs/issue20530.go
new file mode 100644
index 0000000..51f0bd8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20530.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var a uint8
+
+//go:noinline
+func f() {
+ b := int8(func() int32 { return -1 }())
+ a = uint8(b)
+ if int32(a) != 255 {
+ // Failing case prints 'got 255 expected 255'
+ println("got", a, "expected 255")
+ }
+}
+
+//go:noinline
+func g() {
+ b := int8(func() uint32 { return 0xffffffff }())
+ a = uint8(b)
+ if int32(a) != 255 {
+ // Failing case prints 'got 255 expected 255'
+ println("got", a, "expected 255")
+ }
+}
+
+func main() {
+ f()
+ g()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20602.go b/gcc/testsuite/go.test/test/fixedbugs/issue20602.go
new file mode 100644
index 0000000..d4d513b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20602.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that the correct (not implicitly dereferenced)
+// type is reported in the error message.
+
+package p
+
+var p = &[1]complex128{0}
+var _ = real(p) // ERROR "type \*\[1\]complex128|argument must have complex type"
+var _ = imag(p) // ERROR "type \*\[1\]complex128|argument must have complex type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/p.go b/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/p.go
new file mode 100644
index 0000000..fc37136
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/p.go
@@ -0,0 +1,13 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "strings"
+
+type T struct{}
+
+func (T) M() {
+ strings.HasPrefix("", "")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/q.go b/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/q.go
new file mode 100644
index 0000000..9554569
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/q.go
@@ -0,0 +1,13 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package q
+
+import "./p"
+
+type T struct{}
+
+func (T) M() interface{} {
+ return &p.T{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/r.go b/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/r.go
new file mode 100644
index 0000000..73dfe1b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20682.dir/r.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package r
+
+import "./q"
+
+type T struct {
+ q.T
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20682.go b/gcc/testsuite/go.test/test/fixedbugs/issue20682.go
new file mode 100644
index 0000000..8000a52
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20682.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20739.go b/gcc/testsuite/go.test/test/fixedbugs/issue20739.go
new file mode 100644
index 0000000..b71a25d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20739.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func F() {
+ var x struct {
+ x *int
+ w [1e9][1e9][1e9][0]*int
+ y *int
+ }
+ println(&x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20749.go b/gcc/testsuite/go.test/test/fixedbugs/issue20749.go
new file mode 100644
index 0000000..de2d3ad
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20749.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Verify that the compiler complains even if the array
+// has length 0.
+var a [0]int
+var _ = a[2:] // ERROR "invalid slice index 2|array index out of bounds"
+
+var b [1]int
+var _ = b[2:] // ERROR "invalid slice index 2|array index out of bounds"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20780.go b/gcc/testsuite/go.test/test/fixedbugs/issue20780.go
new file mode 100644
index 0000000..53c4f61
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20780.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// We have a limit of 1GB for stack frames.
+// Make sure we include the callee args section.
+
+package main
+
+func f() { // GC_ERROR "stack frame too large"
+ var x [800e6]byte
+ g(x)
+ return
+}
+
+//go:noinline
+func g([800e6]byte) {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20811.go b/gcc/testsuite/go.test/test/fixedbugs/issue20811.go
new file mode 100644
index 0000000..96b61ec
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20811.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20811: slice-in-bound check is lowered incorrectly on
+// amd64p32.
+
+package main
+
+func main() {
+ i := g()
+ _ = "x"[int32(i)]
+ j := g()
+ _ = "x"[:int32(j)]
+}
+
+//go:noinline
+func g() int64 {
+ return 4398046511104
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20812.go b/gcc/testsuite/go.test/test/fixedbugs/issue20812.go
new file mode 100644
index 0000000..d0df831
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20812.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ _ = int("1") // ERROR "cannot convert|invalid type conversion"
+ _ = bool(0) // ERROR "cannot convert|invalid type conversion"
+ _ = bool("false") // ERROR "cannot convert|invalid type conversion"
+ _ = int(false) // ERROR "cannot convert|invalid type conversion"
+ _ = string(true) // ERROR "cannot convert|invalid type conversion"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20813.go b/gcc/testsuite/go.test/test/fixedbugs/issue20813.go
new file mode 100644
index 0000000..b147a89
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20813.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ 1 = 2 // ERROR "cannot assign to 1|invalid left hand side"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue20923.go b/gcc/testsuite/go.test/test/fixedbugs/issue20923.go
new file mode 100644
index 0000000..5fd1ad8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue20923.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20923: gccgo failed to compile parenthesized select case expressions.
+
+package p
+
+func F(c chan bool) {
+ select {
+ case (<-c):
+ case _ = (<-c):
+ case _, _ = (<-c):
+ case (c) <- true:
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21048.go b/gcc/testsuite/go.test/test/fixedbugs/issue21048.go
new file mode 100644
index 0000000..e365a5e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21048.go
@@ -0,0 +1,72 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 21048: s390x merged address generation into stores
+// to unaligned global variables. This resulted in an illegal
+// instruction.
+
+package main
+
+type T struct {
+ _ [1]byte
+ a [2]byte // offset: 1
+ _ [3]byte
+ b [2]uint16 // offset: 6
+ _ [2]byte
+ c [2]uint32 // offset: 12
+ _ [2]byte
+ d [2]int16 // offset: 22
+ _ [2]byte
+ e [2]int32 // offset: 28
+}
+
+var Source, Sink T
+
+func newT() T {
+ return T{
+ a: [2]byte{1, 2},
+ b: [2]uint16{1, 2},
+ c: [2]uint32{1, 2},
+ d: [2]int16{1, 2},
+ e: [2]int32{1, 2},
+ }
+}
+
+//go:noinline
+func moves() {
+ Sink.a = Source.a
+ Sink.b = Source.b
+ Sink.c = Source.c
+ Sink.d = Source.d
+ Sink.e = Source.e
+}
+
+//go:noinline
+func loads() *T {
+ t := newT()
+ t.a = Source.a
+ t.b = Source.b
+ t.c = Source.c
+ t.d = Source.d
+ t.e = Source.e
+ return &t
+}
+
+//go:noinline
+func stores() {
+ t := newT()
+ Sink.a = t.a
+ Sink.b = t.b
+ Sink.c = t.c
+ Sink.d = t.d
+ Sink.e = t.e
+}
+
+func main() {
+ moves()
+ loads()
+ stores()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/a.go
new file mode 100644
index 0000000..f2ee252
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type S struct {
+ x int
+}
+
+func V() interface{} {
+ return S{0}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/b.go
new file mode 100644
index 0000000..b00bd53
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/b.go
@@ -0,0 +1,29 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "reflect"
+
+type X int
+
+func F1() string {
+ type x X
+
+ s := struct {
+ *x
+ }{nil}
+ v := reflect.TypeOf(s)
+ return v.Field(0).PkgPath
+}
+
+func F2() string {
+ type y X
+
+ s := struct {
+ *y
+ }{nil}
+ v := reflect.TypeOf(s)
+ return v.Field(0).PkgPath
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/main.go
new file mode 100644
index 0000000..1f1ec30
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21120.dir/main.go
@@ -0,0 +1,25 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "./a"
+ "./b"
+)
+
+func main() {
+ // Make sure the reflect information for a.S is in the executable.
+ _ = a.V()
+
+ b1 := b.F1()
+ b2 := b.F2()
+ if b1 != b2 {
+ fmt.Printf("%q (from b.F1()) != %q (from b.F2())\n", b1, b2)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21120.go b/gcc/testsuite/go.test/test/fixedbugs/issue21120.go
new file mode 100644
index 0000000..ea896ce
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21120.go
@@ -0,0 +1,11 @@
+// rundir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The compiler was using an incomplete symbol name for reflect name data,
+// permitting an invalid merge in the linker, producing an incorrect
+// exported flag bit.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21221.go b/gcc/testsuite/go.test/test/fixedbugs/issue21221.go
new file mode 100644
index 0000000..bd5a4b5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21221.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+func main() {
+ if unsafe.Pointer(uintptr(0)) != unsafe.Pointer(nil) {
+ panic("fail")
+ }
+ if (*int)(unsafe.Pointer(uintptr(0))) != (*int)(nil) {
+ panic("fail")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21253.go b/gcc/testsuite/go.test/test/fixedbugs/issue21253.go
new file mode 100644
index 0000000..3531b2b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21253.go
@@ -0,0 +1,27 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo crashed compiling this code due to failing to finalize
+// interfaces in the right order.
+
+package p
+
+type s1 struct {
+ f m
+ I
+}
+
+type m interface {
+ Mm(*s2)
+}
+
+type s2 struct {
+ *s1
+}
+
+type I interface {
+ MI()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21256.go b/gcc/testsuite/go.test/test/fixedbugs/issue21256.go
new file mode 100644
index 0000000..c845ec5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21256.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var main = func() {} // ERROR "must be func|redefinition"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21273.go b/gcc/testsuite/go.test/test/fixedbugs/issue21273.go
new file mode 100644
index 0000000..77a1aba
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21273.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T0 T0 // ERROR "invalid recursive type"
+type _ map[T0]int
+
+type T1 struct{ T1 } // ERROR "invalid recursive type"
+type _ map[T1]int
+
+func f() {
+ type T2 T2 // ERROR "invalid recursive type"
+ type _ map[T2]int
+}
+
+func g() {
+ type T3 struct{ T3 } // ERROR "invalid recursive type"
+ type _ map[T3]int
+}
+
+func h() {
+ type T4 struct{ m map[T4]int } // ERROR "invalid map key"
+ type _ map[T4]int // GC_ERROR "invalid map key"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21317.go b/gcc/testsuite/go.test/test/fixedbugs/issue21317.go
new file mode 100644
index 0000000..32b660c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21317.go
@@ -0,0 +1,56 @@
+// +build !js,gc
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// As of "Mon 6 Nov 2017", run.go doesn't yet have proper
+// column matching so instead match the output manually
+// by exec-ing
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ f, err := ioutil.TempFile("", "issue21317.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Fprintf(f, `
+package main
+
+import "fmt"
+
+func main() {
+ n, err := fmt.Println(1)
+}
+`)
+ f.Close()
+ defer os.RemoveAll(f.Name())
+
+ // compile and test output
+ cmd := exec.Command("go", "tool", "compile", f.Name())
+ out, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatalf("expected cmd/compile to fail")
+ }
+ wantErrs := []string{
+ "7:9: n declared but not used",
+ "7:12: err declared but not used",
+ }
+ outStr := string(out)
+ for _, want := range wantErrs {
+ if !strings.Contains(outStr, want) {
+ log.Fatalf("failed to match %q\noutput: %q", want, outStr)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21576.go b/gcc/testsuite/go.test/test/fixedbugs/issue21576.go
new file mode 100644
index 0000000..3f9b1ba
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21576.go
@@ -0,0 +1,63 @@
+// run
+
+// +build !nacl,!js,!gccgo
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// Ensure that deadlock detection can still
+// run even with an import of "_ os/signal".
+
+package main
+
+import (
+ "bytes"
+ "context"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "time"
+)
+
+const prog = `
+package main
+
+import _ "os/signal"
+
+func main() {
+ c := make(chan int)
+ c <- 1
+}
+`
+
+func main() {
+ dir, err := ioutil.TempDir("", "21576")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ file := filepath.Join(dir, "main.go")
+ if err := ioutil.WriteFile(file, []byte(prog), 0655); err != nil {
+ log.Fatalf("Write error %v", err)
+ }
+
+ // Using a timeout of 1 minute in case other factors might slow
+ // down the start of "go run". See https://golang.org/issue/34836.
+ ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
+ defer cancel()
+
+ cmd := exec.CommandContext(ctx, "go", "run", file)
+ output, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatalf("Passed, expected an error")
+ }
+
+ want := []byte("fatal error: all goroutines are asleep - deadlock!")
+ if !bytes.Contains(output, want) {
+ log.Fatalf("Unmatched error message %q:\nin\n%s\nError: %v", want, output, err)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21655.go b/gcc/testsuite/go.test/test/fixedbugs/issue21655.go
new file mode 100644
index 0000000..66d4e3a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21655.go
@@ -0,0 +1,62 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure assembly offsets don't get too large.
+
+// To trigger issue21655, the index offset needs to be small
+// enough to fit into an int32 (to get rewritten to an ADDQconst)
+// but large enough to overflow an int32 after multiplying by the stride.
+
+package main
+
+func f1(a []int64, i int64) int64 {
+ return a[i+1<<30]
+}
+func f2(a []int32, i int64) int32 {
+ return a[i+1<<30]
+}
+func f3(a []int16, i int64) int16 {
+ return a[i+1<<30]
+}
+func f4(a []int8, i int64) int8 {
+ return a[i+1<<31]
+}
+func f5(a []float64, i int64) float64 {
+ return a[i+1<<30]
+}
+func f6(a []float32, i int64) float32 {
+ return a[i+1<<30]
+}
+
+// Note: Before the fix for issue 21655, f{1,2,5,6} made
+// the compiler crash. f3 silently generated the wrong
+// code, using an offset of -1<<31 instead of 1<<31.
+// (This is due to the assembler accepting offsets
+// like 0x80000000 and silently using them as
+// signed 32 bit offsets.)
+// f4 was ok, but testing it can't hurt.
+
+func f7(ss []*string, i int) string {
+ const offset = 3 << 29 // 3<<29 * 4 = 3<<31 = 1<<31 mod 1<<32.
+ if i > offset {
+ return *ss[i-offset]
+ }
+ return ""
+}
+func f8(ss []*string, i int) string {
+ const offset = 3<<29 + 10
+ if i > offset {
+ return *ss[i-offset]
+ }
+ return ""
+}
+func f9(ss []*string, i int) string {
+ const offset = 3<<29 - 10
+ if i > offset {
+ return *ss[i-offset]
+ }
+ return ""
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21770.go b/gcc/testsuite/go.test/test/fixedbugs/issue21770.go
new file mode 100644
index 0000000..2f07d64
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21770.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 21770: gccgo incorrectly accepts "p.f = 0" where p is **struct
+
+package p
+
+type PP **struct{ f int }
+
+func f() {
+ // anonymous type
+ var p **struct{ f int }
+ p.f = 0 // ERROR "field"
+ // named type
+ var p2 PP
+ p2.f = 0 // ERROR "field"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21808.go b/gcc/testsuite/go.test/test/fixedbugs/issue21808.go
new file mode 100644
index 0000000..d146200
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21808.go
@@ -0,0 +1,17 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure println() prints a blank line.
+
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("A")
+ println()
+ fmt.Println("B")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21808.out b/gcc/testsuite/go.test/test/fixedbugs/issue21808.out
new file mode 100644
index 0000000..655da03
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21808.out
@@ -0,0 +1,3 @@
+A
+
+B
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21879.go b/gcc/testsuite/go.test/test/fixedbugs/issue21879.go
new file mode 100644
index 0000000..1029ca0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21879.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+)
+
+func main() {
+ println(caller().frame.Function)
+
+ // Used to erroneously print "main.call.name" instead of
+ // "main.main".
+ println(caller().name())
+}
+
+func caller() call {
+ var pcs [3]uintptr
+ n := runtime.Callers(1, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+ frame, _ := frames.Next()
+ frame, _ = frames.Next()
+
+ return call{frame: frame}
+}
+
+type call struct {
+ frame runtime.Frame
+}
+
+func (c call) name() string {
+ return c.frame.Function
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21879.out b/gcc/testsuite/go.test/test/fixedbugs/issue21879.out
new file mode 100644
index 0000000..066f1a8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21879.out
@@ -0,0 +1,2 @@
+main.main
+main.main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21882.go b/gcc/testsuite/go.test/test/fixedbugs/issue21882.go
new file mode 100644
index 0000000..f77e046
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21882.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T [2]T // ERROR "invalid recursive type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21887.go b/gcc/testsuite/go.test/test/fixedbugs/issue21887.go
new file mode 100644
index 0000000..73c3f43
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21887.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 21887: println(^uint(0)) fails to compile
+
+package main
+
+import "strconv"
+
+func main() {
+ if strconv.IntSize == 32 {
+ println(^uint(0))
+ } else {
+ println(^uint32(0))
+ }
+
+ if strconv.IntSize == 64 {
+ println(^uint(0))
+ } else {
+ println(^uint64(0))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21887.out b/gcc/testsuite/go.test/test/fixedbugs/issue21887.out
new file mode 100644
index 0000000..664b67d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21887.out
@@ -0,0 +1,2 @@
+4294967295
+18446744073709551615
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21963.go b/gcc/testsuite/go.test/test/fixedbugs/issue21963.go
new file mode 100644
index 0000000..996bd63
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21963.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+//go:noinline
+func f(x []int32, y *int8) int32 {
+ c := int32(int16(*y))
+ runtime.GC()
+ return x[0] * c
+}
+
+func main() {
+ var x = [1]int32{5}
+ var y int8 = -1
+ if got, want := f(x[:], &y), int32(-5); got != want {
+ panic(fmt.Sprintf("wanted %d, got %d", want, got))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21979.go b/gcc/testsuite/go.test/test/fixedbugs/issue21979.go
new file mode 100644
index 0000000..addf786
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21979.go
@@ -0,0 +1,46 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ _ = bool("") // ERROR "cannot convert .. \(type untyped string\) to type bool|invalid type conversion"
+ _ = bool(1) // ERROR "cannot convert 1 \(type untyped int\) to type bool|invalid type conversion"
+ _ = bool(1.0) // ERROR "cannot convert 1 \(type untyped float\) to type bool|invalid type conversion"
+ _ = bool(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(type untyped complex\) to type bool|invalid type conversion"
+
+ _ = string(true) // ERROR "cannot convert true \(type untyped bool\) to type string|invalid type conversion"
+ _ = string(-1)
+ _ = string(1.0) // ERROR "cannot convert 1 \(type untyped float\) to type string|invalid type conversion"
+ _ = string(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(type untyped complex\) to type string|invalid type conversion"
+
+ _ = int("") // ERROR "cannot convert .. \(type untyped string\) to type int|invalid type conversion"
+ _ = int(true) // ERROR "cannot convert true \(type untyped bool\) to type int|invalid type conversion"
+ _ = int(-1)
+ _ = int(1)
+ _ = int(1.0)
+ _ = int(-4 + 2i) // ERROR "truncated to integer"
+
+ _ = uint("") // ERROR "cannot convert .. \(type untyped string\) to type uint|invalid type conversion"
+ _ = uint(true) // ERROR "cannot convert true \(type untyped bool\) to type uint|invalid type conversion"
+ _ = uint(-1) // ERROR "constant -1 overflows uint|integer constant overflow"
+ _ = uint(1)
+ _ = uint(1.0)
+ _ = uint(-4 + 2i) // ERROR "constant -4 overflows uint" "truncated to integer"
+
+ _ = float64("") // ERROR "cannot convert .. \(type untyped string\) to type float64|invalid type conversion"
+ _ = float64(true) // ERROR "cannot convert true \(type untyped bool\) to type float64|invalid type conversion"
+ _ = float64(-1)
+ _ = float64(1)
+ _ = float64(1.0)
+ _ = float64(-4 + 2i) // ERROR "truncated to"
+
+ _ = complex128("") // ERROR "cannot convert .. \(type untyped string\) to type complex128|invalid type conversion"
+ _ = complex128(true) // ERROR "cannot convert true \(type untyped bool\) to type complex128|invalid type conversion"
+ _ = complex128(-1)
+ _ = complex128(1)
+ _ = complex128(1.0)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue21988.go b/gcc/testsuite/go.test/test/fixedbugs/issue21988.go
new file mode 100644
index 0000000..4dbf06e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue21988.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 21988: panic on switch case with invalid value
+
+package p
+
+const X = Wrong(0) // ERROR "undefined: Wrong|undefined name .*Wrong"
+
+func _() {
+ switch 0 {
+ case X:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22063.go b/gcc/testsuite/go.test/test/fixedbugs/issue22063.go
new file mode 100644
index 0000000..8d84047
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22063.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 22063: panic on interface switch case with invalid name
+
+package p
+
+const X = Wrong(0) // ERROR "undefined: Wrong|reference to undefined name .*Wrong"
+
+func _() {
+ switch interface{}(nil) {
+ case X:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22076.go b/gcc/testsuite/go.test/test/fixedbugs/issue22076.go
new file mode 100644
index 0000000..5d628b9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22076.go
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 22076: Couldn't use ":=" to declare names that refer to
+// dot-imported symbols.
+
+package p
+
+import . "bytes"
+
+var _ Reader // use "bytes" import
+
+func _() {
+ Buffer := 0
+ _ = Buffer
+}
+
+func _() {
+ for Buffer := range []int{} {
+ _ = Buffer
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22083.go b/gcc/testsuite/go.test/test/fixedbugs/issue22083.go
new file mode 100644
index 0000000..a385102
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22083.go
@@ -0,0 +1,41 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The compiler was panicking on the wrong line number, where
+// the panic was occurring in an inlined call.
+
+package main
+
+import (
+ "runtime/debug"
+ "strings"
+)
+
+type Wrapper struct {
+ a []int
+}
+
+func (w Wrapper) Get(i int) int {
+ return w.a[i]
+}
+
+func main() {
+ defer func() {
+ e := recover()
+ if e == nil {
+ panic("bounds check didn't fail")
+ }
+ stk := string(debug.Stack())
+ if !strings.Contains(stk, "issue22083.go:40") {
+ panic("wrong stack trace: " + stk)
+ }
+ }()
+ foo := Wrapper{a: []int{0, 1, 2}}
+ _ = foo.Get(0)
+ _ = foo.Get(1)
+ _ = foo.Get(2)
+ _ = foo.Get(3) // stack trace should mention this line
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22198.go b/gcc/testsuite/go.test/test/fixedbugs/issue22198.go
new file mode 100644
index 0000000..c874c1c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22198.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue22198
+
+func f(a *bool, b bool) {
+ if b {
+ return
+ }
+ c := '\n'
+ if b {
+ c = ' '
+ }
+ *a = c == '\n'
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22200.go b/gcc/testsuite/go.test/test/fixedbugs/issue22200.go
new file mode 100644
index 0000000..37440d9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22200.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1(x *[1<<30 - 1e6]byte) byte {
+ for _, b := range *x {
+ return b
+ }
+ return 0
+}
+func f2(x *[1<<30 + 1e6]byte) byte { // GC_ERROR "stack frame too large"
+ for _, b := range *x {
+ return b
+ }
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22200b.go b/gcc/testsuite/go.test/test/fixedbugs/issue22200b.go
new file mode 100644
index 0000000..ce20923
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22200b.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !386,!amd64p32,!arm,!mips,!mipsle
+
+package p
+
+func f3(x *[1 << 31]byte) byte { // GC_ERROR "stack frame too large"
+ for _, b := range *x {
+ return b
+ }
+ return 0
+}
+func f4(x *[1 << 32]byte) byte { // GC_ERROR "stack frame too large"
+ for _, b := range *x {
+ return b
+ }
+ return 0
+}
+func f5(x *[1 << 33]byte) byte { // GC_ERROR "stack frame too large"
+ for _, b := range *x {
+ return b
+ }
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22305.go b/gcc/testsuite/go.test/test/fixedbugs/issue22305.go
new file mode 100644
index 0000000..ec432f9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22305.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 22305: gccgo failed to compile this file.
+
+package main
+
+var F func() [0]func()
+var i = 2
+var B = F()[i]
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22326.go b/gcc/testsuite/go.test/test/fixedbugs/issue22326.go
new file mode 100644
index 0000000..a675655
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22326.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var (
+ _ = d
+ _ = f("_", c, b)
+ a = f("a")
+ b = f("b")
+ c = f("c")
+ d = f("d")
+)
+
+func f(s string, rest ...int) int {
+ print(s)
+ return 0
+}
+
+func main() {
+ println()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22326.out b/gcc/testsuite/go.test/test/fixedbugs/issue22326.out
new file mode 100644
index 0000000..f020438
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22326.out
@@ -0,0 +1 @@
+abc_d
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22327.go b/gcc/testsuite/go.test/test/fixedbugs/issue22327.go
new file mode 100644
index 0000000..7b21d83
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22327.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Using a multi-result function as an argument to
+// append should compile successfully. Previously there
+// was a missing *int -> interface{} conversion that caused
+// the compiler to ICE.
+
+package p
+
+func f() ([]interface{}, *int) {
+ return nil, nil
+}
+
+var _ = append(f())
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22429.go b/gcc/testsuite/go.test/test/fixedbugs/issue22429.go
new file mode 100644
index 0000000..289b434
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22429.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure SSA->assembly pass can handle SP as an index register.
+
+package p
+
+type T struct {
+ a,b,c,d float32
+}
+
+func f(a *[8]T, i,j,k int) float32 {
+ b := *a
+ return b[i].a + b[j].b + b[k].c
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22458.go b/gcc/testsuite/go.test/test/fixedbugs/issue22458.go
new file mode 100644
index 0000000..5c89929
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22458.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure KeepAlive introduces a use of the spilled variable.
+
+package main
+
+import "runtime"
+
+type node struct {
+ next *node
+}
+
+var x bool
+
+func main() {
+ var head *node
+ for x {
+ head = &node{head}
+ }
+
+ runtime.KeepAlive(head)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22605.go b/gcc/testsuite/go.test/test/fixedbugs/issue22605.go
new file mode 100644
index 0000000..9e726f3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22605.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// We were picking up a special noalg type from typelinks.
+
+package main
+
+import "reflect"
+
+func f(m map[string]int) int {
+ return m["a"]
+}
+
+func g(m map[[8]string]int) int {
+ t := reflect.ArrayOf(8, reflect.TypeOf(""))
+ a := reflect.New(t).Elem()
+ return m[a.Interface().([8]string)]
+}
+
+func main() {
+ m := map[[8]string]int{}
+ g(m)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22660.go b/gcc/testsuite/go.test/test/fixedbugs/issue22660.go
new file mode 100644
index 0000000..9ce9c4d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22660.go
@@ -0,0 +1,46 @@
+// +build !js,gc
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ f, err := ioutil.TempFile("", "issue22660.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ f.Close()
+ defer os.Remove(f.Name())
+
+ // path must appear in error messages even if we strip them with -trimpath
+ path := filepath.Join("users", "xxx", "go")
+ var src bytes.Buffer
+ fmt.Fprintf(&src, "//line %s:1\n", filepath.Join(path, "foo.go"))
+
+ if err := ioutil.WriteFile(f.Name(), src.Bytes(), 0660); err != nil {
+ log.Fatal(err)
+ }
+
+ out, err := exec.Command("go", "tool", "compile", fmt.Sprintf("-trimpath=%s", path), f.Name()).CombinedOutput()
+ if err == nil {
+ log.Fatalf("expected compiling %s to fail", f.Name())
+ }
+
+ if !strings.HasPrefix(string(out), path) {
+ log.Fatalf("expected full path (%s) in error message, got:\n%s", path, out)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22683.go b/gcc/testsuite/go.test/test/fixedbugs/issue22683.go
new file mode 100644
index 0000000..47c7f65
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22683.go
@@ -0,0 +1,30 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+type foo struct {
+ bar [1]*int
+}
+
+func main() {
+ ch := make(chan foo, 2)
+ var a int
+ var b [1]*int
+ b[0] = &a
+ ch <- foo{bar: b}
+ close(ch)
+
+ for v := range ch {
+ for i := 0; i < 1; i++ {
+ fmt.Println(v.bar[0] != nil)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22683.out b/gcc/testsuite/go.test/test/fixedbugs/issue22683.out
new file mode 100644
index 0000000..27ba77d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22683.out
@@ -0,0 +1 @@
+true
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22781.go b/gcc/testsuite/go.test/test/fixedbugs/issue22781.go
new file mode 100644
index 0000000..5ad8239
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22781.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime/debug"
+
+type T struct {
+ // >= 16 bytes to avoid tiny alloc.
+ a, b int
+}
+
+func main() {
+ debug.SetGCPercent(1)
+ for i := 0; i < 100000; i++ {
+ m := make(map[*T]struct{}, 0)
+ for j := 0; j < 20; j++ {
+ // During the call to mapassign_fast64, the key argument
+ // was incorrectly treated as a uint64. If the stack was
+ // scanned during that call, the only pointer to k was
+ // missed, leading to *k being collected prematurely.
+ k := new(T)
+ m[k] = struct{}{}
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22794.go b/gcc/testsuite/go.test/test/fixedbugs/issue22794.go
new file mode 100644
index 0000000..2ac31ef
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22794.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type it struct {
+ Floats bool
+ inner string
+}
+
+func main() {
+ i1 := it{Floats: true}
+ if i1.floats { // ERROR "(type it .* field or method floats, but does have Floats)|undefined field or method"
+ }
+ i2 := &it{floats: false} // ERROR "(but does have Floats)|unknown field|declared but not used"
+ _ = &it{InneR: "foo"} // ERROR "(but does have inner)|unknown field"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22822.go b/gcc/testsuite/go.test/test/fixedbugs/issue22822.go
new file mode 100644
index 0000000..ea53452
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22822.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that calling a function shadowing a built-in provides a good
+// error message.
+
+package main
+
+func F() {
+ slice := []int{1, 2, 3}
+ len := int(2)
+ println(len(slice)) // ERROR "cannot call non-function len .type int., declared at|expected function"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22881.go b/gcc/testsuite/go.test/test/fixedbugs/issue22881.go
new file mode 100644
index 0000000..645f2d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22881.go
@@ -0,0 +1,117 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test to make sure RHS is evaluated before map insert is started.
+// The RHS panics in all of these cases.
+
+package main
+
+import "fmt"
+
+func main() {
+ for i, f := range []func(map[int]int){
+ f0, f1, f2, f3, f4, f5, f6, f7, f8,
+ } {
+ m := map[int]int{}
+ func() { // wrapper to scope the defer.
+ defer func() {
+ recover()
+ }()
+ f(m) // Will panic. Shouldn't modify m.
+ fmt.Printf("RHS didn't panic, case f%d\n", i)
+ }()
+ if len(m) != 0 {
+ fmt.Printf("map insert happened, case f%d\n", i)
+ }
+ }
+
+ // Append slice.
+ for i, f := range []func(map[int][]int){
+ fa0, fa1, fa2, fa3,
+ } {
+ m := map[int][]int{}
+ func() { // wrapper to scope the defer.
+ defer func() {
+ recover()
+ }()
+ f(m) // Will panic. Shouldn't modify m.
+ fmt.Printf("RHS didn't panic, case fa%d\n", i)
+ }()
+ if len(m) != 0 {
+ fmt.Printf("map insert happened, case fa%d\n", i)
+ }
+ }
+}
+
+func f0(m map[int]int) {
+ var p *int
+ m[0] = *p
+}
+
+func f1(m map[int]int) {
+ var p *int
+ m[0] += *p
+}
+
+func f2(m map[int]int) {
+ var p *int
+ sink, m[0] = sink, *p
+}
+
+func f3(m map[int]int) {
+ var p *chan int
+ m[0], sink = <-(*p)
+}
+
+func f4(m map[int]int) {
+ var p *interface{}
+ m[0], sink = (*p).(int)
+}
+
+func f5(m map[int]int) {
+ var p *map[int]int
+ m[0], sink = (*p)[0]
+}
+
+func f6(m map[int]int) {
+ var z int
+ m[0] /= z
+}
+
+func f7(m map[int]int) {
+ var a []int
+ m[0] = a[0]
+}
+
+func f8(m map[int]int) {
+ var z int
+ m[0] %= z
+}
+
+func fa0(m map[int][]int) {
+ var p *int
+ m[0] = append(m[0], *p)
+}
+
+func fa1(m map[int][]int) {
+ var p *int
+ sink, m[0] = !sink, append(m[0], *p)
+}
+
+func fa2(m map[int][]int) {
+ var p *int
+ m[0], _ = append(m[0], 0), *p
+}
+
+func fa3(m map[int][]int) {
+ // OSLICE has similar in-place-reassignment
+ // optimizations as OAPPEND, but we need to make sure
+ // to *not* optimize them, because we can't guarantee
+ // the slice indices are within bounds.
+ m[0] = m[0][:1]
+}
+
+var sink bool
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22904.go b/gcc/testsuite/go.test/test/fixedbugs/issue22904.go
new file mode 100644
index 0000000..02459c6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22904.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 22904: Make sure the compiler emits a proper error message about
+// invalid recursive types rather than crashing.
+
+package p
+
+type a struct{ b } // ERROR "invalid recursive type"
+type b struct{ a } // GCCGO_ERROR "invalid recursive type"
+
+var x interface{}
+
+func f() {
+ x = a{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22921.go b/gcc/testsuite/go.test/test/fixedbugs/issue22921.go
new file mode 100644
index 0000000..5336ba3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22921.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "bytes"
+
+type _ struct{ bytes.nonexist } // ERROR "unexported|undefined"
+
+type _ interface{ bytes.nonexist } // ERROR "unexported|undefined|expected signature or type name"
+
+func main() {
+ var _ bytes.Buffer
+ var _ bytes.buffer // ERROR "unexported|undefined"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/a.go
new file mode 100644
index 0000000..7a4ede4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package q
+
+type P int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/b.go
new file mode 100644
index 0000000..87d59a6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/b.go
@@ -0,0 +1,30 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import q "./a"
+
+type T struct {
+ X *q.P
+}
+
+func F(in, out *T) {
+ *out = *in
+ if in.X != nil {
+ in, out := &in.X, &out.X
+ if *in == nil {
+ *out = nil
+ } else {
+ *out = new(q.P)
+ **out = **in
+ }
+ }
+ return
+}
+
+//go:noinline
+func G(x, y *T) {
+ F(x, y)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/main.go
new file mode 100644
index 0000000..84666ad
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22941.dir/main.go
@@ -0,0 +1,15 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import p "./b"
+
+var G int
+
+func main() {
+ if G == 101 {
+ p.G(nil, nil)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22941.go b/gcc/testsuite/go.test/test/fixedbugs/issue22941.go
new file mode 100644
index 0000000..c3732c3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22941.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/a.go
new file mode 100644
index 0000000..7257d7d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func F() {
+ if x := 0; false {
+ _ = x
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/b.go
new file mode 100644
index 0000000..e1568c8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22962.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+var V = func() { a.F() }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue22962.go b/gcc/testsuite/go.test/test/fixedbugs/issue22962.go
new file mode 100644
index 0000000..8000a52
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue22962.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23093.go b/gcc/testsuite/go.test/test/fixedbugs/issue23093.go
new file mode 100644
index 0000000..7b2865c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23093.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var f = func() { f() } // ERROR "initialization loop|initialization expression for .*f.* depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23116.go b/gcc/testsuite/go.test/test/fixedbugs/issue23116.go
new file mode 100644
index 0000000..b4b36d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23116.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x interface{}) {
+ switch x.(type) {
+ }
+
+ switch t := x.(type) { // ERROR "declared but not used"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/a.go
new file mode 100644
index 0000000..3d2816f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Large struct {
+ x [256]int
+}
+
+func F(x int, _ int, _ bool, _ Large) int {
+ return x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/b.go
new file mode 100644
index 0000000..bec3d15
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23179.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+func G(x int) int {
+ return a.F(x, 1, false, a.Large{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23179.go b/gcc/testsuite/go.test/test/fixedbugs/issue23179.go
new file mode 100644
index 0000000..8000a52
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23179.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23188.go b/gcc/testsuite/go.test/test/fixedbugs/issue23188.go
new file mode 100644
index 0000000..c224340
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23188.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test order of evaluation of index operations.
+
+package main
+
+func main() {
+ arr := []int{1, 2}
+
+ // The spec says that in an assignment statement the operands
+ // of all index expressions and pointer indirections on the
+ // left, and the expressions on the right, are evaluated in
+ // the usual order. The usual order means function calls and
+ // channel operations are done first. Then the assignments are
+ // carried out one at a time. The operands of an index
+ // expression include both the array and the index. So this
+ // evaluates as
+ // tmp1 := arr
+ // tmp2 := len(arr) - 1
+ // tmp3 := len(arr)
+ // arr = arr[:tmp3-1]
+ // tmp1[tmp2] = 3
+ arr, arr[len(arr)-1] = arr[:len(arr)-1], 3
+
+ if len(arr) != 1 || arr[0] != 1 || arr[:2][1] != 3 {
+ panic(arr)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23298.go b/gcc/testsuite/go.test/test/fixedbugs/issue23298.go
new file mode 100644
index 0000000..be00a8e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23298.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T string
+
+var (
+ t = T("T")
+ r = []rune(t)
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23305.go b/gcc/testsuite/go.test/test/fixedbugs/issue23305.go
new file mode 100644
index 0000000..28f400c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23305.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func mask1(a, b uint64) uint64 {
+ op1 := int32(a)
+ op2 := int32(b)
+ return uint64(uint32(op1 / op2))
+}
+
+var mask2 = mask1
+
+func main() {
+ res1 := mask1(0x1, 0xfffffffeffffffff)
+ res2 := mask2(0x1, 0xfffffffeffffffff)
+ if res1 != 0xffffffff {
+ println("got", res1, "want", 0xffffffff)
+ panic("FAIL")
+ }
+ if res2 != 0xffffffff {
+ println("got", res2, "want", 0xffffffff)
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23311.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue23311.dir/main.go
new file mode 100644
index 0000000..fa4cf76
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23311.dir/main.go
@@ -0,0 +1,14 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import _ "unsafe" // for linkname
+
+//go:linkname f runtime.GC
+func f()
+
+func main() {
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23311.go b/gcc/testsuite/go.test/test/fixedbugs/issue23311.go
new file mode 100644
index 0000000..128cf9d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23311.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23414.go b/gcc/testsuite/go.test/test/fixedbugs/issue23414.go
new file mode 100644
index 0000000..7ef3d83
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23414.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x struct{}
+
+func f() bool {
+ return x == x && x == x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23489.go b/gcc/testsuite/go.test/test/fixedbugs/issue23489.go
new file mode 100644
index 0000000..1e64af1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23489.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Caused gccgo to issue a spurious compilation error.
+
+package main
+
+type T struct{}
+
+func (*T) Foo() {}
+
+type P = *T
+
+func main() {
+ var p P
+ p.Foo()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23504.go b/gcc/testsuite/go.test/test/fixedbugs/issue23504.go
new file mode 100644
index 0000000..77f3184
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23504.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ var B bool
+ B2 := (B || B && !B) && !B
+ B3 := B2 || B
+ for (B3 || B2) && !B2 && B {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23521.go b/gcc/testsuite/go.test/test/fixedbugs/issue23521.go
new file mode 100644
index 0000000..159e032
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23521.go
@@ -0,0 +1,43 @@
+// errorcheck -0 -m
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23521: improve early DCE for if without explicit else.
+
+package p
+
+//go:noinline
+func nonleaf() {}
+
+const truth = true
+
+func f() int { // ERROR "can inline f"
+ if truth {
+ return 0
+ }
+ // If everything below is removed, as it should,
+ // function f should be inlineable.
+ nonleaf()
+ for {
+ panic("")
+ }
+}
+
+func g() int { // ERROR "can inline g"
+ return f() // ERROR "inlining call to f"
+}
+
+func f2() int { // ERROR "can inline f2"
+ if !truth {
+ nonleaf()
+ } else {
+ return 0
+ }
+ panic("")
+}
+
+func g2() int { // ERROR "can inline g2"
+ return f2() // ERROR "inlining call to f2"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23522.go b/gcc/testsuite/go.test/test/fixedbugs/issue23522.go
new file mode 100644
index 0000000..cace86c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23522.go
@@ -0,0 +1,46 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "math"
+)
+
+type S struct {
+ u int64
+ n int32
+}
+
+func F1(f float64) *S {
+ s := f
+ pf := math.Copysign(f, 1)
+ u := math.Floor(pf)
+ return &S{
+ u: int64(math.Copysign(u, s)),
+ n: int32(math.Copysign((pf-u)*1e9, s)),
+ }
+}
+
+func F2(f float64) *S {
+ s := f
+ f = math.Copysign(f, 1)
+ u := math.Floor(f)
+ return &S{
+ u: int64(math.Copysign(u, s)),
+ n: int32(math.Copysign((f-u)*1e9, s)),
+ }
+}
+
+func main() {
+ s1 := F1(-1)
+ s2 := F2(-1)
+ if *s1 != *s2 {
+ println("F1:", s1.u, s1.n)
+ println("F2:", s2.u, s2.n)
+ panic("different")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23545.go b/gcc/testsuite/go.test/test/fixedbugs/issue23545.go
new file mode 100644
index 0000000..d97f64a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23545.go
@@ -0,0 +1,31 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23545: gccgo didn't lower array comparison to
+// proper equality function in some case.
+
+package main
+
+func main() {
+ if a := Get(); a != dummyID(1234) {
+ panic("FAIL")
+ }
+}
+
+func dummyID(x int) [Size]interface{} {
+ var out [Size]interface{}
+ out[0] = x
+ return out
+}
+
+const Size = 32
+
+type OutputID [Size]interface{}
+
+//go:noinline
+func Get() OutputID {
+ return dummyID(1234)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23546.go b/gcc/testsuite/go.test/test/fixedbugs/issue23546.go
new file mode 100644
index 0000000..818f0cd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23546.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23546: type..eq function not generated when
+// DWARF is disabled.
+
+package main
+
+func main() {
+ use(f() == f())
+}
+
+func f() [2]interface{} {
+ var out [2]interface{}
+ return out
+}
+
+//go:noinline
+func use(bool) {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23586.go b/gcc/testsuite/go.test/test/fixedbugs/issue23586.go
new file mode 100644
index 0000000..c2d4c9f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23586.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that we type-check deferred/go functions even
+// if they are not called (a common error). Specifically,
+// we don't want to see errors such as import or variable
+// declared but not used.
+
+package p
+
+import (
+ "fmt"
+ "math"
+)
+
+func f() {
+ var i int
+ defer func() { fmt.Println() } // ERROR "must be function call"
+ go func() { _ = math.Sin(0) } // ERROR "must be function call"
+ go func() { _ = i} // ERROR "must be function call"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23719.go b/gcc/testsuite/go.test/test/fixedbugs/issue23719.go
new file mode 100644
index 0000000..c97e636
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23719.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ v1 := [2]int32{-1, 88}
+ v2 := [2]int32{-1, 99}
+ if v1 == v2 {
+ panic("bad comparison")
+ }
+
+ w1 := [2]int16{-1, 88}
+ w2 := [2]int16{-1, 99}
+ if w1 == w2 {
+ panic("bad comparison")
+ }
+ x1 := [4]int16{-1, 88, 88, 88}
+ x2 := [4]int16{-1, 99, 99, 99}
+ if x1 == x2 {
+ panic("bad comparison")
+ }
+
+ a1 := [2]int8{-1, 88}
+ a2 := [2]int8{-1, 99}
+ if a1 == a2 {
+ panic("bad comparison")
+ }
+ b1 := [4]int8{-1, 88, 88, 88}
+ b2 := [4]int8{-1, 99, 99, 99}
+ if b1 == b2 {
+ panic("bad comparison")
+ }
+ c1 := [8]int8{-1, 88, 88, 88, 88, 88, 88, 88}
+ c2 := [8]int8{-1, 99, 99, 99, 99, 99, 99, 99}
+ if c1 == c2 {
+ panic("bad comparison")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23732.go b/gcc/testsuite/go.test/test/fixedbugs/issue23732.go
new file mode 100644
index 0000000..db2d182
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23732.go
@@ -0,0 +1,42 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23732: Give better details about which struct
+// initializer has the wrong number of values.
+
+package main
+
+type Foo struct {
+ A int
+ B int
+ C interface{}
+ Bar
+}
+
+type Bar struct {
+ A string
+}
+
+func main() {
+ _ = Foo{ // GCCGO_ERROR "too few expressions"
+ 1,
+ 2,
+ 3, // GC_ERROR "too few values in Foo{...}"
+ }
+
+ _ = Foo{
+ 1,
+ 2,
+ 3,
+ Bar{"A", "B"}, // ERROR "too many values in Bar{...}|too many expressions"
+ }
+
+ _ = Foo{ // GCCGO_ERROR "too few expressions"
+ 1,
+ 2,
+ Bar{"A", "B"}, // ERROR "too many values in Bar{...}|too many expressions" "too few values in Foo{...}"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23734.go b/gcc/testsuite/go.test/test/fixedbugs/issue23734.go
new file mode 100644
index 0000000..dd5869b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23734.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ m := map[interface{}]int{}
+ k := []int{}
+
+ mustPanic(func() {
+ _ = m[k]
+ })
+ mustPanic(func() {
+ _, _ = m[k]
+ })
+ mustPanic(func() {
+ delete(m, k)
+ })
+}
+
+func mustPanic(f func()) {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("didn't panic")
+ }
+ }()
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23780.go b/gcc/testsuite/go.test/test/fixedbugs/issue23780.go
new file mode 100644
index 0000000..71fc2d9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23780.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ _ = []byte{1 << 30: 1}
+}
+
+func g() {
+ sink = []byte{1 << 30: 1}
+}
+
+var sink []byte
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23781.go b/gcc/testsuite/go.test/test/fixedbugs/issue23781.go
new file mode 100644
index 0000000..5c03cf7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23781.go
@@ -0,0 +1,10 @@
+// +build amd64
+// compile
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = []int{1 << 31: 1} // ok on machines with 64bit int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23812.go b/gcc/testsuite/go.test/test/fixedbugs/issue23812.go
new file mode 100644
index 0000000..0a40deb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23812.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func main() {
+ want := int32(0x3edae8)
+ got := foo(1)
+ if want != got {
+ panic(fmt.Sprintf("want %x, got %x", want, got))
+ }
+}
+
+func foo(a int32) int32 {
+ return shr1(int32(shr2(int64(0x14ff6e2207db5d1f), int(a))), 4)
+}
+
+func shr1(n int32, m int) int32 { return n >> uint(m) }
+
+func shr2(n int64, m int) int64 {
+ if m < 0 {
+ m = -m
+ }
+ if m >= 64 {
+ return n
+ }
+
+ return n >> uint(m)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23823.go b/gcc/testsuite/go.test/test/fixedbugs/issue23823.go
new file mode 100644
index 0000000..067a8f1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23823.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type I1 = interface {
+ I2
+}
+
+// BAD: type loop should mention I1; see also #41669
+type I2 interface { // GC_ERROR "invalid recursive type I2\n\tLINE: I2 refers to\n\tLINE: I2$"
+ I1 // GCCGO_ERROR "invalid recursive interface"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue23912.go b/gcc/testsuite/go.test/test/fixedbugs/issue23912.go
new file mode 100644
index 0000000..05ffd6b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue23912.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// A couple of aliases cases that gccgo incorrectly gave errors for.
+
+package p
+
+func F1() {
+ type E = struct{}
+ type X struct{}
+ var x X
+ var y E = x
+ _ = y
+}
+
+func F2() {
+ type E = struct{}
+ type S []E
+ type T []struct{}
+ type X struct{}
+ var x X
+ s := S{E{}}
+ t := T{struct{}{}}
+ _ = append(s, x)
+ _ = append(s, t[0])
+ _ = append(s, t...)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24120.go b/gcc/testsuite/go.test/test/fixedbugs/issue24120.go
new file mode 100644
index 0000000..6c7d871
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24120.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var F func(int)
+
+func G() {
+ if F(func() int { return 1 }()); false {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24173.go b/gcc/testsuite/go.test/test/fixedbugs/issue24173.go
new file mode 100644
index 0000000..4c19e05
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24173.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type arrayAlias = [10]int
+type mapAlias = map[int]int
+type sliceAlias = []int
+type structAlias = struct{}
+
+func Exported() {
+ _ = arrayAlias{}
+ _ = mapAlias{}
+ _ = sliceAlias{}
+ _ = structAlias{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24187.go b/gcc/testsuite/go.test/test/fixedbugs/issue24187.go
new file mode 100644
index 0000000..45fc9297
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24187.go
@@ -0,0 +1,33 @@
+// +build amd64p32
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "unsafe"
+)
+
+func main() {
+ b := make([]byte, 128)
+ for i := range b {
+ b[i] = 1
+ }
+ if bytes.IndexByte(b, 0) != -1 {
+ panic("found 0")
+ }
+ for i := range b {
+ b[i] = 0
+ c := b
+ *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&c)) + unsafe.Sizeof(uintptr(0)))) = 1<<31 - 1
+ if bytes.IndexByte(c, 0) != i {
+ panic(fmt.Sprintf("missing 0 at %d\n", i))
+ }
+ b[i] = 1
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24419.go b/gcc/testsuite/go.test/test/fixedbugs/issue24419.go
new file mode 100644
index 0000000..73b7783
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24419.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "strings"
+)
+
+func growstack(n int) {
+ if n > 0 {
+ growstack(n - 1)
+ }
+}
+
+func main() {
+ c := make(chan struct{})
+ go compare(c)
+ go equal(c)
+ go indexByte(c)
+ go indexByteString(c)
+ <-c
+ <-c
+ <-c
+ <-c
+}
+
+func compare(c chan struct{}) {
+ defer bytes.Compare(nil, nil)
+ growstack(10000)
+ c <- struct{}{}
+}
+func equal(c chan struct{}) {
+ defer bytes.Equal(nil, nil)
+ growstack(10000)
+ c <- struct{}{}
+}
+func indexByte(c chan struct{}) {
+ defer bytes.IndexByte(nil, 0)
+ growstack(10000)
+ c <- struct{}{}
+}
+func indexByteString(c chan struct{}) {
+ defer strings.IndexByte("", 0)
+ growstack(10000)
+ c <- struct{}{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24449.go b/gcc/testsuite/go.test/test/fixedbugs/issue24449.go
new file mode 100644
index 0000000..b236645
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24449.go
@@ -0,0 +1,62 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "sync/atomic"
+)
+
+var cnt32 int32
+
+//go:noinline
+func test32(a, b []int) bool {
+ // Try to generate flag value, issue atomic
+ // adds and then re-use the flag value to see if
+ // the atomic add has clobbered them.
+ atomic.AddInt32(&cnt32, 1)
+ if len(a) == len(b) {
+ atomic.AddInt32(&cnt32, 2)
+ }
+ atomic.AddInt32(&cnt32, 4)
+ if len(a) >= len(b) {
+ atomic.AddInt32(&cnt32, 8)
+ }
+ if len(a) <= len(b) {
+ atomic.AddInt32(&cnt32, 16)
+ }
+ return atomic.LoadInt32(&cnt32) == 31
+}
+
+var cnt64 int64
+
+//go:noinline
+func test64(a, b []int) bool {
+ // Try to generate flag value, issue atomic
+ // adds and then re-use the flag value to see if
+ // the atomic add has clobbered them.
+ atomic.AddInt64(&cnt64, 1)
+ if len(a) == len(b) {
+ atomic.AddInt64(&cnt64, 2)
+ }
+ atomic.AddInt64(&cnt64, 4)
+ if len(a) >= len(b) {
+ atomic.AddInt64(&cnt64, 8)
+ }
+ if len(a) <= len(b) {
+ atomic.AddInt64(&cnt64, 16)
+ }
+ return atomic.LoadInt64(&cnt64) == 31
+}
+
+func main() {
+ if !test32([]int{}, []int{}) {
+ panic("test32")
+ }
+ if !test64([]int{}, []int{}) {
+ panic("test64")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24470.go b/gcc/testsuite/go.test/test/fixedbugs/issue24470.go
new file mode 100644
index 0000000..d0e5e23
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24470.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we get "use of .(type) outside type switch"
+// before any other (misleading) errors. Test case from issue.
+
+package p
+
+func f(i interface{}) {
+ if x, ok := i.(type); ok { // ERROR "outside type switch"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24488.go b/gcc/testsuite/go.test/test/fixedbugs/issue24488.go
new file mode 100644
index 0000000..b3deab4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24488.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+ "strings"
+)
+
+type Func func()
+
+func (f Func) Foo() {
+ if f != nil {
+ f()
+ }
+}
+
+func (f Func) Bar() {
+ if f != nil {
+ f()
+ }
+ buf := make([]byte, 4000)
+ n := runtime.Stack(buf, true)
+ s := string(buf[:n])
+ if strings.Contains(s, "-fm") {
+ panic("wrapper present in stack trace:\n" + s)
+ }
+}
+
+func main() {
+ foo := Func(func() {})
+ foo = foo.Bar
+ foo.Foo()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24503.go b/gcc/testsuite/go.test/test/fixedbugs/issue24503.go
new file mode 100644
index 0000000..933ce70
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24503.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 24503: Handle == and != of addresses taken of symbols consistently.
+
+package main
+
+func test() string {
+ type test struct{}
+ o1 := test{}
+ o2 := test{}
+ if &o1 == &o2 {
+ return "equal"
+ }
+ if &o1 != &o2 {
+ return "unequal"
+ }
+ return "failed"
+}
+
+func main() {
+ if test() == "failed" {
+ panic("expected either 'equal' or 'unequal'")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24547.go b/gcc/testsuite/go.test/test/fixedbugs/issue24547.go
new file mode 100644
index 0000000..47d94a9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24547.go
@@ -0,0 +1,46 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// When computing method sets with shadowed methods, make sure we
+// compute whether a method promotion involved a pointer traversal
+// based on the promoted method, not the shadowed method.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+)
+
+type mystruct struct {
+ f int
+}
+
+func (t mystruct) String() string {
+ return "FAIL"
+}
+
+func main() {
+ type deep struct {
+ mystruct
+ }
+ s := struct {
+ deep
+ *bytes.Buffer
+ }{
+ deep{},
+ bytes.NewBufferString("ok"),
+ }
+
+ if got := s.String(); got != "ok" {
+ panic(got)
+ }
+
+ var i fmt.Stringer = s
+ if got := i.String(); got != "ok" {
+ panic(got)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24760.go b/gcc/testsuite/go.test/test/fixedbugs/issue24760.go
new file mode 100644
index 0000000..cd6f124
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24760.go
@@ -0,0 +1,12 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+var _ = string([]byte(nil))[0]
+var _ = uintptr(unsafe.Pointer(uintptr(1))) << 100
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24763.go b/gcc/testsuite/go.test/test/fixedbugs/issue24763.go
new file mode 100644
index 0000000..623ab48
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24763.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var s uint
+ var x = interface{}(1<<s + 1<<s) // compiler must not crash here
+ if x.(int) != 2 {
+ panic("x not int or not 2")
+ }
+
+ var y interface{}
+ y = 1<<s + 1 // compiler must not crash here
+ if y.(int) != 2 {
+ panic("y not int or not 2")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24799.go b/gcc/testsuite/go.test/test/fixedbugs/issue24799.go
new file mode 100644
index 0000000..c805c86
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24799.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Loads of 8 byte go.strings cannot use DS relocation
+// in case the alignment is not a multiple of 4.
+
+package main
+
+import (
+ "fmt"
+)
+
+type Level string
+
+// The following are all go.strings. A link time error can
+// occur if an 8 byte load is used to load a go.string that is
+// not aligned to 4 bytes due to the type of relocation that
+// is generated for the instruction. A fix was made to avoid
+// generating an instruction with DS relocation for go.strings
+// since their alignment is not known until link time.
+
+// This problem only affects go.string since other types have
+// correct alignment.
+
+const (
+ LevelBad Level = "badvals"
+ LevelNone Level = "No"
+ LevelMetadata Level = "Metadata"
+ LevelRequest Level = "Request"
+ LevelRequestResponse Level = "RequestResponse"
+)
+
+func ordLevel(l Level) int {
+ switch l {
+ case LevelMetadata:
+ return 1
+ case LevelRequest:
+ return 2
+ case LevelRequestResponse:
+ return 3
+ default:
+ return 0
+ }
+}
+
+//go:noinline
+func test(l Level) {
+ if ordLevel(l) < ordLevel(LevelMetadata) {
+ fmt.Printf("OK\n")
+ }
+}
+
+func main() {
+ test(LevelMetadata)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/a.go
new file mode 100644
index 0000000..58e6240
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type main int
+
+var X main
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/main.go
new file mode 100644
index 0000000..5c7db7b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24801.dir/main.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ a.X = 1
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24801.go b/gcc/testsuite/go.test/test/fixedbugs/issue24801.go
new file mode 100644
index 0000000..9b05db8e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24801.go
@@ -0,0 +1,5 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24817.go b/gcc/testsuite/go.test/test/fixedbugs/issue24817.go
new file mode 100644
index 0000000..ba2a138
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24817.go
@@ -0,0 +1,64 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check all ways to compare a non-constant string to the empty string.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+var (
+ s = "abc"
+ e = ""
+ failed bool
+)
+
+func main() {
+ want(true, "" < s, `"" < s`)
+ want(false, s < "", `s < ""`)
+ want(false, "" < e, `"" < e`)
+ want(false, e < "", `e < ""`)
+
+ want(true, "" <= s, `"" <= s`)
+ want(false, s <= "", `s <= ""`)
+ want(true, "" <= e, `"" <= e`)
+ want(true, e <= "", `e <= ""`)
+
+ want(false, "" > s, `"" > s`)
+ want(true, s > "", `s > ""`)
+ want(false, "" > e, `"" > e`)
+ want(false, e > "", `e > ""`)
+
+ want(false, "" >= s, `"" >= s`)
+ want(true, s >= "", `s >= ""`)
+ want(true, "" >= e, `"" >= e`)
+ want(true, e >= "", `e >= ""`)
+
+ want(false, "" == s, `"" == s`)
+ want(false, s == "", `s == ""`)
+ want(true, "" == e, `"" == e`)
+ want(true, e == "", `e == ""`)
+
+ want(true, "" != s, `"" != s`)
+ want(true, s != "", `s != ""`)
+ want(false, "" != e, `"" != e`)
+ want(false, e != "", `e != ""`)
+
+ if failed {
+ os.Exit(1)
+ }
+}
+
+//go:noinline
+func want(b bool, have bool, msg string) {
+ if b != have {
+ fmt.Println(msg)
+ failed = true
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24937.go b/gcc/testsuite/go.test/test/fixedbugs/issue24937.go
new file mode 100644
index 0000000..7d8460f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24937.go
@@ -0,0 +1,15 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ x := []byte{'a'}
+ switch string(x) {
+ case func() string { x[0] = 'b'; return "b" }():
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue24939.go b/gcc/testsuite/go.test/test/fixedbugs/issue24939.go
new file mode 100644
index 0000000..0ae6f2b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue24939.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T interface {
+ M(P)
+}
+
+type M interface {
+ F() P
+}
+
+type P = interface {
+ // The compiler cannot handle this case. Disabled for now.
+ // See issue #25838.
+ // I() M
+}
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25006.go b/gcc/testsuite/go.test/test/fixedbugs/issue25006.go
new file mode 100644
index 0000000..570fdca
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25006.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func spin() {
+ var i int
+ var b bool
+
+ switch 1 {
+ case 0:
+ i = 1
+ }
+ switch 1 {
+ case i:
+ default:
+ i = 1
+ b = !b && (b && !b) && b
+ }
+ switch false {
+ case false:
+ i = 3 + -i
+ switch 0 {
+ case 1 - i:
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25101.go b/gcc/testsuite/go.test/test/fixedbugs/issue25101.go
new file mode 100644
index 0000000..4fd6bed
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25101.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Indexed export format must not crash when writing
+// the anonymous parameter for m.
+
+package p
+
+var x interface {
+ m(int)
+}
+
+var M = x.m
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25322.go b/gcc/testsuite/go.test/test/fixedbugs/issue25322.go
new file mode 100644
index 0000000..ee4ff53
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25322.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Missing zero extension when converting a float32
+// to a uint64.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+func Foo(v float32) {
+ fmt.Printf("%x\n", uint64(math.Float32bits(v)))
+}
+
+func main() {
+ Foo(2.0)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25322.out b/gcc/testsuite/go.test/test/fixedbugs/issue25322.out
new file mode 100644
index 0000000..52f3f6a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25322.out
@@ -0,0 +1 @@
+40000000
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25507.go b/gcc/testsuite/go.test/test/fixedbugs/issue25507.go
new file mode 100644
index 0000000..9143a73
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25507.go
@@ -0,0 +1,29 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// We have a limit of 1GB for stack frames.
+// Test that we extend that limit to include large argument/return areas.
+// Argument/return areas are part of the parent frame, not the frame itself,
+// so they need to be handled separately.
+
+package main
+
+// >1GB to trigger failure, <2GB to work on 32-bit platforms.
+type large struct {
+ b [1500000000]byte
+}
+
+func (x large) f1() int { // GC_ERROR "stack frame too large"
+ return 5
+}
+
+func f2(x large) int { // GC_ERROR "stack frame too large"
+ return 5
+}
+
+func f3() (x large, i int) { // GC_ERROR "stack frame too large"
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25516.go b/gcc/testsuite/go.test/test/fixedbugs/issue25516.go
new file mode 100644
index 0000000..8326ef9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25516.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure dead write barriers are handled correctly.
+
+package main
+
+func f(p **int) {
+ // The trick here is to eliminate the block containing the write barrier,
+ // but only after the write barrier branches are inserted.
+ // This requires some delicate code.
+ i := 0
+ var b []bool
+ var s string
+ for true {
+ if b[i] {
+ var a []string
+ s = a[len(s)]
+ i = 0
+ }
+ *p = nil
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25727.go b/gcc/testsuite/go.test/test/fixedbugs/issue25727.go
new file mode 100644
index 0000000..936b9f8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25727.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "net/http"
+
+var s = http.Server{}
+var _ = s.doneChan // ERROR "s.doneChan undefined .cannot refer to unexported field or method doneChan.$|unexported field or method"
+var _ = s.DoneChan // ERROR "s.DoneChan undefined .type http.Server has no field or method DoneChan.$|undefined field or method"
+var _ = http.Server{tlsConfig: nil} // ERROR "unknown field 'tlsConfig' in struct literal.+ .but does have TLSConfig.$|unknown field .?tlsConfig.? in .?http.Server"
+var _ = http.Server{DoneChan: nil} // ERROR "unknown field 'DoneChan' in struct literal of type http.Server$|unknown field .?DoneChan.? in .?http.Server"
+
+type foo struct {
+ bar int
+}
+
+var _ = &foo{bAr: 10} // ERROR "unknown field 'bAr' in struct literal.+ .but does have bar.$|unknown field .?bAr.? in .?foo"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25741.go b/gcc/testsuite/go.test/test/fixedbugs/issue25741.go
new file mode 100644
index 0000000..c76e975
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25741.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var s []int
+
+func main() {
+ i := -1
+ s[i] = 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25776.go b/gcc/testsuite/go.test/test/fixedbugs/issue25776.go
new file mode 100644
index 0000000..e05c0bc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25776.go
@@ -0,0 +1,99 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+const (
+ Upper = true
+ blas_Upper = 121
+ badTriangle = "bad triangle"
+)
+
+// Triangular represents a triangular matrix. Triangular matrices are always square.
+type Triangular interface {
+ // Triangular returns the number of rows/columns in the matrix and its
+ // orientation.
+ Tryangle() (mmmm int, kynd bool)
+ Triangle() (mmmm int, kynd bool)
+}
+
+// blas64_Triangular represents a triangular matrix using the conventional storage scheme.
+type blas64_Triangular struct {
+ Stride int
+ Uplo int
+}
+
+// TriDense represents an upper or lower triangular matrix in dense storage
+// format.
+type TriDense struct {
+ mat blas64_Triangular
+}
+
+func NewTriDense() *TriDense {
+ return &TriDense{
+ mat: blas64_Triangular{
+ Stride: 3,
+ Uplo: blas_Upper,
+ },
+ }
+}
+
+func (t *TriDense) isUpper() bool {
+ return isUpperUplo(t.mat.Uplo)
+}
+
+func (t *TriDense) triKind() bool {
+ return isUpperUplo(t.mat.Uplo)
+}
+
+func isUpperUplo(u int) bool {
+ switch u {
+ case blas_Upper:
+ return true
+ default:
+ panic(badTriangle)
+ }
+}
+
+func (t *TriDense) IsZero() bool {
+ return t.mat.Stride == 0
+}
+
+//go:noinline
+func (t *TriDense) ScaleTri(f float64, a Triangular) {
+ n, kind := a.Triangle()
+ if kind == false {
+ println("ScaleTri n, kind=", n, ", ", kind, " (FAIL, expected true)")
+ }
+}
+
+//go:noinline
+func (t *TriDense) ScaleTry(f float64, a Triangular) {
+ n, kind := a.Tryangle()
+ if kind == false {
+ println("ScaleTry n, kind=", n, ", ", kind, " (FAIL, expected true)")
+ }
+}
+
+// Triangle failed (before fix)
+func (t *TriDense) Triangle() (nnnn int, kind bool) {
+ return 3, !t.IsZero() && t.triKind()
+}
+
+// Tryangle works -- difference is not-named output parameters.
+func (t *TriDense) Tryangle() (int, bool) {
+ return 3, !t.IsZero() && t.triKind()
+}
+
+func main() {
+ ta := NewTriDense()
+ n, kind := ta.Triangle()
+ if kind == false {
+ println(" main n, kind=", n, ", ", kind, " (FAIL, expected true)")
+ }
+ ta.ScaleTri(1, ta)
+ ta.ScaleTry(1, ta)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25897a.go b/gcc/testsuite/go.test/test/fixedbugs/issue25897a.go
new file mode 100644
index 0000000..6a724a7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25897a.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure the runtime can scan args of an unstarted goroutine
+// which starts with a reflect-generated function.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+)
+
+const N = 100
+
+func main() {
+ runtime.GOMAXPROCS(1)
+ c := make(chan bool, N)
+ for i := 0; i < N; i++ {
+ f := reflect.MakeFunc(reflect.TypeOf(((func(*int))(nil))),
+ func(args []reflect.Value) []reflect.Value {
+ c <- true
+ return nil
+ }).Interface().(func(*int))
+ go f(nil)
+ }
+ runtime.GC()
+ for i := 0; i < N; i++ {
+ <-c
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25897b.go b/gcc/testsuite/go.test/test/fixedbugs/issue25897b.go
new file mode 100644
index 0000000..09a9673
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25897b.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure the runtime can scan args of an unstarted goroutine
+// which starts with a reflect-generated function.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+)
+
+const N = 100
+
+type T struct {
+}
+
+func (t *T) Foo(c chan bool) {
+ c <- true
+}
+
+func main() {
+ t := &T{}
+ runtime.GOMAXPROCS(1)
+ c := make(chan bool, N)
+ for i := 0; i < N; i++ {
+ f := reflect.ValueOf(t).MethodByName("Foo").Interface().(func(chan bool))
+ go f(c)
+ }
+ runtime.GC()
+ for i := 0; i < N; i++ {
+ <-c
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25958.go b/gcc/testsuite/go.test/test/fixedbugs/issue25958.go
new file mode 100644
index 0000000..90fcee1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25958.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Verify that the "must be receive" error for "case done:" appears
+// on the line of the case clause, not the line of the done declaration.
+
+func f(done chan struct{}) {
+ select {
+ case done: // ERROR "must be receive|expected .*<-.* or .*=" "not used"
+ case (chan struct{})(done): // ERROR "must be receive|expected .*<-.* or .*="
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/p.go b/gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/p.go
new file mode 100644
index 0000000..306d6a4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/p.go
@@ -0,0 +1,15 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type m struct {
+ link *m
+}
+
+var head *m
+
+func F(m *int) bool {
+ return head != nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/q.go b/gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/q.go
new file mode 100644
index 0000000..64d2587
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25984.dir/q.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package q
+
+import "./p"
+
+func G() {
+ p.F(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue25984.go b/gcc/testsuite/go.test/test/fixedbugs/issue25984.go
new file mode 100644
index 0000000..128cf9d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue25984.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26024.go b/gcc/testsuite/go.test/test/fixedbugs/issue26024.go
new file mode 100644
index 0000000..78877b2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26024.go
@@ -0,0 +1,28 @@
+// compile
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package r
+
+// f compiles into code where no stores remain in the two successors
+// of a write barrier block; i.e., they are empty. Pre-fix, this
+// results in an unexpected input to markUnsafePoints, that expects to
+// see a pair of non-empty plain blocks.
+func f() {
+ var i int
+ var s string
+ for len(s) < len(s) {
+ i++
+ s = "a"
+ }
+ var b bool
+ var sa []string
+ for true {
+ sa = []string{""}
+ for b || i == 0 {
+ }
+ b = !b
+ _ = sa
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26043.go b/gcc/testsuite/go.test/test/fixedbugs/issue26043.go
new file mode 100644
index 0000000..fe32947
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26043.go
@@ -0,0 +1,32 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This program results in a loop inferred to increment
+// j by 0, causing bounds check elimination to attempt
+// something%0, which panics (in the bug).
+
+package q
+
+func f() {
+ var s1 string
+ var b bool
+ if b {
+ b = !b
+ s1 += "a"
+ }
+
+ var s2 string
+ var i, j int
+ if (s1 <= "") || (s2 >= "") {
+ j = len(s1[:6])
+ } else {
+ i = len("b")
+ }
+
+ for j < 0 {
+ j += i
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26097.go b/gcc/testsuite/go.test/test/fixedbugs/issue26097.go
new file mode 100644
index 0000000..eedd6ba
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26097.go
@@ -0,0 +1,47 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:noinline
+func cmovClobberAX64(v1, v2 int64, x1, x2 float64) int64 {
+ r := v1
+ if x1 == x2 {
+ r = v2
+ }
+ return r
+}
+
+//go:noinline
+func cmovClobberAX32(v1, v2 int32, x1, x2 float64) int32 {
+ r := v1
+ if x1 == x2 {
+ r = v2
+ }
+ return r
+}
+
+//go:noinline
+func cmovClobberAX16(v1, v2 int16, x1, x2 float64) int16 {
+ r := v1
+ if x1 == x2 {
+ r = v2
+ }
+ return r
+}
+
+func main() {
+ if cmovClobberAX16(1, 2, 4.0, 5.0) != 1 {
+ panic("CMOVQEQF causes incorrect code")
+ }
+ if cmovClobberAX32(1, 2, 4.0, 5.0) != 1 {
+ panic("CMOVQEQF causes incorrect code")
+ }
+ if cmovClobberAX64(1, 2, 4.0, 5.0) != 1 {
+ panic("CMOVQEQF causes incorrect code")
+ }
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26105.go b/gcc/testsuite/go.test/test/fixedbugs/issue26105.go
new file mode 100644
index 0000000..88a5f16
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26105.go
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Triggers a bug in writebarrier, which inserts one
+// between (first block) OpAddr x and (second block) a VarDef x,
+// which are then in the wrong order and unable to be
+// properly scheduled.
+
+package q
+
+var S interface{}
+
+func F(n int) {
+ fun := func(x int) int {
+ S = 1
+ return n
+ }
+ i := fun(([]int{})[n])
+
+ var fc [2]chan int
+ S = (([1][2]chan int{fc})[i][i])
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26116.go b/gcc/testsuite/go.test/test/fixedbugs/issue26116.go
new file mode 100644
index 0000000..8a63481
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26116.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ s := []int{0, 1, 2}
+ i := 1
+ for i > 0 && s[i] != 2 {
+ i++
+ }
+ if i != 2 {
+ panic("loop didn't run")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26120.go b/gcc/testsuite/go.test/test/fixedbugs/issue26120.go
new file mode 100644
index 0000000..94bf7d9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26120.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26120: INDEX of 1-element but non-SSAable array
+// is mishandled when building SSA.
+
+package p
+
+type T [1]struct {
+ f []int
+ i, j int
+}
+
+func F() {
+ var v T
+ f := func() T {
+ return v
+ }
+ _ = []int{}[f()[0].i]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue2615.go b/gcc/testsuite/go.test/test/fixedbugs/issue2615.go
index 686e1e1..831110e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue2615.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue2615.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26153.go b/gcc/testsuite/go.test/test/fixedbugs/issue26153.go
new file mode 100644
index 0000000..53f53cf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26153.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26153. The write to ps was incorrectly
+// removed by the dead auto elimination pass.
+
+package main
+
+const hello = "hello world"
+
+func main() {
+ var s string
+ mangle(&s)
+ if s != hello {
+ panic("write incorrectly elided")
+ }
+}
+
+//go:noinline
+func mangle(ps *string) {
+ if ps == nil {
+ var s string
+ ps = &s
+ }
+ *ps = hello
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26248.go b/gcc/testsuite/go.test/test/fixedbugs/issue26248.go
new file mode 100644
index 0000000..2f04e48
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26248.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26248: gccgo miscompiles interface field expression.
+// In G().M where G returns an interface, G() is evaluated twice.
+
+package main
+
+type I interface {
+ M()
+}
+
+type T struct{}
+
+func (T) M() {}
+
+var g = 0
+
+//go:noinline
+func G() I {
+ g++
+ return T{}
+}
+
+//go:noinline
+func Use(interface{}) {}
+
+func main() {
+ x := G().M
+ Use(x)
+
+ if g != 1 {
+ println("want 1, got", g)
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26335.go b/gcc/testsuite/go.test/test/fixedbugs/issue26335.go
new file mode 100644
index 0000000..a97b4b6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26335.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo mishandled passing a struct with an empty field through
+// reflect.Value.Call.
+
+package main
+
+import (
+ "reflect"
+)
+
+type Empty struct {
+ f1, f2 *byte
+ empty struct{}
+}
+
+func F(e Empty, s []string) {
+ if len(s) != 1 || s[0] != "hi" {
+ panic("bad slice")
+ }
+}
+
+func main() {
+ reflect.ValueOf(F).Call([]reflect.Value{
+ reflect.ValueOf(Empty{}),
+ reflect.ValueOf([]string{"hi"}),
+ })
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26340.go b/gcc/testsuite/go.test/test/fixedbugs/issue26340.go
new file mode 100644
index 0000000..f973ce2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26340.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo did not permit omitting the type of a composite literal
+// element when one of the middle omitted types was a pointer type.
+
+package p
+
+type S []T
+type T struct { x int }
+
+var _ = map[string]*S{
+ "a": {
+ { 1 },
+ },
+}
+
+var _ = [1]*S{ { {1}, } }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/a.go
new file mode 100644
index 0000000..4fd23c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type k int
+
+func (k) F() {}
+
+type M map[k]int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/b.go
new file mode 100644
index 0000000..30b8c25
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26341.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func f() {
+ for k := range (a.M{}) {
+ k.F()
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26341.go b/gcc/testsuite/go.test/test/fixedbugs/issue26341.go
new file mode 100644
index 0000000..128cf9d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26341.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26407.go b/gcc/testsuite/go.test/test/fixedbugs/issue26407.go
new file mode 100644
index 0000000..aa8e79c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26407.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26407: ensure that stack variables which have
+// had their address taken and then used in a comparison,
+// but are otherwise unused, are cleared.
+
+package main
+
+func main() {
+ poison()
+ test()
+}
+
+//go:noinline
+func poison() {
+ // initialise the stack with invalid pointers
+ var large [256]uintptr
+ for i := range large {
+ large[i] = 1
+ }
+ use(large[:])
+}
+
+//go:noinline
+func test() {
+ a := 2
+ x := &a
+ if x != compare(&x) {
+ panic("not possible")
+ }
+}
+
+//go:noinline
+func compare(x **int) *int {
+ var y *int
+ if x == &y {
+ panic("not possible")
+ }
+ // grow the stack to trigger a check for invalid pointers
+ grow()
+ if x == &y {
+ panic("not possible")
+ }
+ return *x
+}
+
+//go:noinline
+func grow() {
+ var large [1 << 16]uintptr
+ use(large[:])
+}
+
+//go:noinline
+func use(_ []uintptr) { }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26411.go b/gcc/testsuite/go.test/test/fixedbugs/issue26411.go
new file mode 100644
index 0000000..5f40bf2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26411.go
@@ -0,0 +1,92 @@
+// +build !nacl,!js
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that label redefinition errors print out
+// a column number that matches the start of the current label's
+// definition instead of the label delimiting token ":"
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+)
+
+func main() {
+ tmpdir, err := ioutil.TempDir("", "issue26411")
+ if err != nil {
+ log.Fatalf("Failed to create temporary directory: %v", err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ tests := []struct {
+ code string
+ errors []string
+ }{
+ {
+ code: `
+package main
+
+func main() {
+foo:
+foo:
+}
+`,
+ errors: []string{
+ "^.+:5:1: label foo defined and not used\n",
+ ".+:6:1: label foo already defined at .+:5:1\n$",
+ },
+ },
+ {
+ code: `
+package main
+
+func main() {
+
+ bar:
+ bar:
+bar:
+bar :
+}
+`,
+
+ errors: []string{
+ "^.+:6:13: label bar defined and not used\n",
+ ".+:7:4: label bar already defined at .+:6:13\n",
+ ".+:8:1: label bar already defined at .+:6:13\n",
+ ".+:9:1: label bar already defined at .+:6:13\n$",
+ },
+ },
+ }
+
+ for i, test := range tests {
+ filename := filepath.Join(tmpdir, fmt.Sprintf("%d.go", i))
+ if err := ioutil.WriteFile(filename, []byte(test.code), 0644); err != nil {
+ log.Printf("#%d: failed to create file %s", i, filename)
+ continue
+ }
+ output, _ := exec.Command("go", "tool", "compile", filename).CombinedOutput()
+
+ // remove each matching error from the output
+ for _, err := range test.errors {
+ rx := regexp.MustCompile(err)
+ match := rx.Find(output)
+ output = bytes.Replace(output, match, nil, 1) // remove match (which might be nil) from output
+ }
+
+ // at this point all output should have been consumed
+ if len(output) != 0 {
+ log.Printf("Test case %d has unmatched errors:\n%s", i, output)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26416.go b/gcc/testsuite/go.test/test/fixedbugs/issue26416.go
new file mode 100644
index 0000000..44a4fc7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26416.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type t1 struct {
+ t1f1 int
+ t1f2 int
+}
+type t2 struct {
+ t2f1 int
+ t2f2 int
+ *t1
+}
+type t3 struct {
+ t3f1 int
+ *t2
+}
+
+var (
+ _ = t2{t1f1: 600} // ERROR "cannot use promoted field t1.t1f1 in struct literal of type t2|unknown field"
+ _ = t3{t1f2: 800} // ERROR "cannot use promoted field t2.t1.t1f2 in struct literal of type t3|unknown field"
+ _ = t3{t2f1: 900} // ERROR "cannot use promoted field t2.t2f1 in struct literal of type t3|unknown field"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26438.go b/gcc/testsuite/go.test/test/fixedbugs/issue26438.go
new file mode 100644
index 0000000..d44da21
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26438.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26438: arm64 backend may use 64-bit TST for
+// "if uint32(a)&uint32(b) == 0", which should be
+// 32-bit TSTW
+
+package main
+
+//go:noinline
+func tstw(a, b uint64) uint64 {
+ if uint32(a)&uint32(b) == 0 {
+ return 100
+ } else {
+ return 200
+ }
+}
+
+func main() {
+ if tstw(0xff00000000, 0xaa00000000) == 200 {
+ panic("impossible")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26495.go b/gcc/testsuite/go.test/test/fixedbugs/issue26495.go
new file mode 100644
index 0000000..11ea360
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26495.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26495: gccgo produces incorrect order of evaluation
+// for expressions involving &&, || subexpressions.
+
+package main
+
+var i int
+
+func checkorder(order int) {
+ if i != order {
+ panic("FAIL: wrong evaluation order")
+ }
+ i++
+}
+
+func A() bool { checkorder(1); return true }
+func B() bool { checkorder(2); return true }
+func C() bool { checkorder(5); return false }
+func D() bool { panic("FAIL: D should not be called") }
+func E() int { checkorder(3); return 0 }
+func F() int { checkorder(0); return 0 }
+func G(bool) int { checkorder(9); return 0 }
+func H(int, bool, int) int { checkorder(7); return 0 }
+func I(int) bool { checkorder(8); return true }
+func J() int { checkorder(4); return 0 }
+func K() int { checkorder(6); return 0 }
+func L() int { checkorder(10); return 0 }
+
+func main() {
+ _ = F() + G(A() && B() && I(E()+H(J(), C() && D(), K()))) + L()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26616.go b/gcc/testsuite/go.test/test/fixedbugs/issue26616.go
new file mode 100644
index 0000000..87c0293
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26616.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context"
+
+func f() {
+ var _ int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context"
+ var a int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context"
+ a = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context"
+ b := three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|single variable set to multiple-value|multiple-value function call in single-value context"
+
+ _, _ = a, b
+}
+
+func three() (int, int, int)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue26855.go b/gcc/testsuite/go.test/test/fixedbugs/issue26855.go
new file mode 100644
index 0000000..b965635
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue26855.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we get the correct (T vs &T) literal specification
+// in the error message.
+
+package p
+
+type S struct {
+ f T
+}
+
+type P struct {
+ f *T
+}
+
+type T struct{}
+
+var _ = S{
+ f: &T{}, // ERROR "cannot use &T{}|incompatible type"
+}
+
+var _ = P{
+ f: T{}, // ERROR "cannot use T{}|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27143.go b/gcc/testsuite/go.test/test/fixedbugs/issue27143.go
new file mode 100644
index 0000000..009ec9f6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27143.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 27143: cmd/compile: erroneous application of walkinrange
+// optimization for const over 2**63
+
+package p
+
+var c uint64
+
+var b1 bool = 0x7fffffffffffffff < c && c < 0x8000000000000000
+var b2 bool = c < 0x8000000000000000 && 0x7fffffffffffffff < c
+var b3 bool = 0x8000000000000000 < c && c < 0x8000000000000001
+var b4 bool = c < 0x8000000000000001 && 0x8000000000000000 < c
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27232.go b/gcc/testsuite/go.test/test/fixedbugs/issue27232.go
new file mode 100644
index 0000000..3a1cc87
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27232.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type F = func(T)
+
+type T interface {
+ m(F)
+}
+
+type t struct{}
+
+func (t) m(F) {}
+
+var _ T = &t{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27267.go b/gcc/testsuite/go.test/test/fixedbugs/issue27267.go
new file mode 100644
index 0000000..ebae44f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27267.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// 1st test case from issue
+type F = func(E) // compiles if not type alias or moved below E struct
+type E struct {
+ f F
+}
+
+var x = E{func(E) {}}
+
+// 2nd test case from issue
+type P = *S
+type S struct {
+ p P
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27278.go b/gcc/testsuite/go.test/test/fixedbugs/issue27278.go
new file mode 100644
index 0000000..73f7c75
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27278.go
@@ -0,0 +1,63 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 27278: dead auto elim deletes an auto and its
+// initialization, but it is live because of a nil check.
+
+package main
+
+type T struct {
+ _ [3]string
+ T2
+}
+
+func (t *T) M() []string {
+ return t.T2.M()
+}
+
+type T2 struct {
+ T3
+}
+
+func (t *T2) M() []string {
+ return t.T3.M()
+}
+
+type T3 struct {
+ a string
+}
+
+func (t *T3) M() []string {
+ return []string{}
+}
+
+func main() {
+ poison()
+ f()
+}
+
+//go:noinline
+func f() {
+ (&T{}).M()
+ grow(10000)
+}
+
+// grow stack, triggers stack copy
+func grow(n int) {
+ if n == 0 {
+ return
+ }
+ grow(n-1)
+}
+
+// put some junk on stack, which cannot be valid address
+//go:noinline
+func poison() {
+ x := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+ g = x
+}
+
+var g [10]int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27289.go b/gcc/testsuite/go.test/test/fixedbugs/issue27289.go
new file mode 100644
index 0000000..293b9d0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27289.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we don't prove that the bounds check failure branch is unreachable.
+
+package main
+
+//go:noinline
+func f(a []int) {
+ _ = a[len(a)-1]
+}
+
+func main() {
+ defer func() {
+ if err := recover(); err != nil {
+ return
+ }
+ panic("f should panic")
+ }()
+ f(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27356.go b/gcc/testsuite/go.test/test/fixedbugs/issue27356.go
new file mode 100644
index 0000000..c3e686d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27356.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 27356: function parameter hiding built-in function results in compiler crash
+
+package p
+
+var a = []int{1,2,3}
+
+func _(len int) {
+ _ = len(a) // ERROR "cannot call non-function|expected function"
+}
+
+var cap = false
+var _ = cap(a) // ERROR "cannot call non-function|expected function"
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27695.go b/gcc/testsuite/go.test/test/fixedbugs/issue27695.go
new file mode 100644
index 0000000..8bd4939
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27695.go
@@ -0,0 +1,62 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure return values are always scanned, when
+// calling methods (+functions, TODO) with reflect.
+
+package main
+
+import (
+ "reflect"
+ "runtime/debug"
+ "sync"
+)
+
+func main() {
+ debug.SetGCPercent(1) // run GC frequently
+ var wg sync.WaitGroup
+ for i := 0; i < 20; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 2000; i++ {
+ _test()
+ }
+ }()
+ }
+ wg.Wait()
+}
+
+type Stt struct {
+ Data interface{}
+}
+
+type My struct {
+ b byte
+}
+
+func (this *My) Run(rawData []byte) (Stt, error) {
+ var data string = "hello"
+ stt := Stt{
+ Data: data,
+ }
+ return stt, nil
+}
+
+func _test() (interface{}, error) {
+ f := reflect.ValueOf(&My{}).MethodByName("Run")
+ if method, ok := f.Interface().(func([]byte) (Stt, error)); ok {
+ s, e := method(nil)
+ // The bug in issue27695 happens here, during the return
+ // from the above call (at the end of reflect.callMethod
+ // when preparing to return). The result value that
+ // is assigned to s was not being scanned if GC happens
+ // to occur there.
+ i := interface{}(s)
+ return i, e
+ }
+ return nil, nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27695b.go b/gcc/testsuite/go.test/test/fixedbugs/issue27695b.go
new file mode 100644
index 0000000..d80acfb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27695b.go
@@ -0,0 +1,64 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure return values aren't scanned until they
+// are initialized, when calling functions and methods
+// via reflect.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+var badPtr uintptr
+
+var sink []byte
+
+func init() {
+ // Allocate large enough to use largeAlloc.
+ b := make([]byte, 1<<16-1)
+ sink = b // force heap allocation
+ // Any space between the object and the end of page is invalid to point to.
+ badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
+}
+
+func f(d func() *byte) *byte {
+ // Initialize callee args section with a bad pointer.
+ g(badPtr)
+
+ // Then call a function which returns a pointer.
+ // That return slot starts out holding a bad pointer.
+ return d()
+}
+
+//go:noinline
+func g(x uintptr) {
+}
+
+type T struct {
+}
+
+func (t *T) Foo() *byte {
+ runtime.GC()
+ return nil
+}
+
+func main() {
+ // Functions
+ d := reflect.MakeFunc(reflect.TypeOf(func() *byte { return nil }),
+ func(args []reflect.Value) []reflect.Value {
+ runtime.GC()
+ return []reflect.Value{reflect.ValueOf((*byte)(nil))}
+ }).Interface().(func() *byte)
+ f(d)
+
+ // Methods
+ e := reflect.ValueOf(&T{}).Method(0).Interface().(func() *byte)
+ f(e)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27695c.go b/gcc/testsuite/go.test/test/fixedbugs/issue27695c.go
new file mode 100644
index 0000000..948191c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27695c.go
@@ -0,0 +1,65 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure return values aren't scanned until they
+// are initialized, when calling functions and methods
+// via reflect.
+
+package main
+
+import (
+ "io"
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+var badPtr uintptr
+
+var sink []byte
+
+func init() {
+ // Allocate large enough to use largeAlloc.
+ b := make([]byte, 1<<16-1)
+ sink = b // force heap allocation
+ // Any space between the object and the end of page is invalid to point to.
+ badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
+}
+
+func f(d func(error) error) error {
+ // Initialize callee args section with a bad pointer.
+ g(badPtr, badPtr, badPtr, badPtr)
+
+ // Then call a function which returns a pointer.
+ // That return slot starts out holding a bad pointer.
+ return d(io.EOF)
+}
+
+//go:noinline
+func g(x, y, z, w uintptr) {
+}
+
+type T struct {
+}
+
+func (t *T) Foo(e error) error {
+ runtime.GC()
+ return e
+}
+
+func main() {
+ // Functions
+ d := reflect.MakeFunc(reflect.TypeOf(func(e error) error { return e }),
+ func(args []reflect.Value) []reflect.Value {
+ runtime.GC()
+ return args
+ }).Interface().(func(error) error)
+ f(d)
+
+ // Methods
+ x := reflect.ValueOf(&T{}).Method(0).Interface().(func(error) error)
+ f(x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27718.go b/gcc/testsuite/go.test/test/fixedbugs/issue27718.go
new file mode 100644
index 0000000..ff616fb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27718.go
@@ -0,0 +1,102 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// (-0)+0 should be 0, not -0.
+
+package main
+
+//go:noinline
+func add64(x float64) float64 {
+ return x + 0
+}
+
+func testAdd64() {
+ var zero float64
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/add64(negZero) != inf {
+ panic("negZero+0 != posZero (64 bit)")
+ }
+}
+
+//go:noinline
+func sub64(x float64) float64 {
+ return x - 0
+}
+
+func testSub64() {
+ var zero float64
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/sub64(negZero) != -inf {
+ panic("negZero-0 != negZero (64 bit)")
+ }
+}
+
+//go:noinline
+func neg64(x float64) float64 {
+ return -x
+}
+
+func testNeg64() {
+ var zero float64
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/neg64(negZero) != inf {
+ panic("-negZero != posZero (64 bit)")
+ }
+}
+
+//go:noinline
+func add32(x float32) float32 {
+ return x + 0
+}
+
+func testAdd32() {
+ var zero float32
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/add32(negZero) != inf {
+ panic("negZero+0 != posZero (32 bit)")
+ }
+}
+
+//go:noinline
+func sub32(x float32) float32 {
+ return x - 0
+}
+
+func testSub32() {
+ var zero float32
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/sub32(negZero) != -inf {
+ panic("negZero-0 != negZero (32 bit)")
+ }
+}
+
+//go:noinline
+func neg32(x float32) float32 {
+ return -x
+}
+
+func testNeg32() {
+ var zero float32
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/neg32(negZero) != inf {
+ panic("-negZero != posZero (32 bit)")
+ }
+}
+
+func main() {
+ testAdd64()
+ testSub64()
+ testNeg64()
+ testAdd32()
+ testSub32()
+ testNeg32()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27829.go b/gcc/testsuite/go.test/test/fixedbugs/issue27829.go
new file mode 100644
index 0000000..9204043
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27829.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Bad AND/BTR combination rule.
+
+package main
+
+import "fmt"
+
+//go:noinline
+func f(x uint64) uint64 {
+ return (x >> 48) &^ (uint64(0x4000))
+}
+
+func main() {
+ bad := false
+ if got, want := f(^uint64(0)), uint64(0xbfff); got != want {
+ fmt.Printf("got %x, want %x\n", got, want)
+ bad = true
+ }
+ if bad {
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27938.go b/gcc/testsuite/go.test/test/fixedbugs/issue27938.go
new file mode 100644
index 0000000..ed974e6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27938.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we get a single non-confusing error
+// message for embedded fields/interfaces that use
+// a qualified identifier with non-existing package.
+
+package p
+
+type _ struct {
+ F sync.Mutex // ERROR "undefined: sync|expected package"
+}
+
+type _ struct {
+ sync.Mutex // ERROR "undefined: sync|expected package"
+}
+
+type _ interface {
+ sync.Mutex // ERROR "undefined: sync|expected package|expected signature or type name"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue27961.go b/gcc/testsuite/go.test/test/fixedbugs/issue27961.go
new file mode 100644
index 0000000..f8b4f66
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue27961.go
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 27961: some optimizations generate OffPtr with wrong
+// types, which causes invalid bytecode on Wasm.
+
+package main
+
+import "math"
+
+type Vec2 [2]float64
+
+func main() {
+ var a Vec2
+ a.A().B().C().D()
+}
+
+func (v Vec2) A() Vec2 {
+ return Vec2{v[0], v[0]}
+}
+
+func (v Vec2) B() Vec2 {
+ return Vec2{1.0 / v.D(), 0}
+}
+
+func (v Vec2) C() Vec2 {
+ return Vec2{v[0], v[0]}
+}
+
+func (v Vec2) D() float64 {
+ return math.Sqrt(v[0])
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28055.go b/gcc/testsuite/go.test/test/fixedbugs/issue28055.go
new file mode 100644
index 0000000..d4889d5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28055.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure VARDEF can be a top-level statement.
+
+package p
+
+func f() {
+ var s string
+ var as []string
+ switch false && (s+"a"+as[0]+s+as[0]+s == "") {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28058.go b/gcc/testsuite/go.test/test/fixedbugs/issue28058.go
new file mode 100644
index 0000000..d8206e7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28058.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 14988: declaring a map with an invalid key type should not cause a
+// fatal panic.
+
+package main
+
+var x map[func()]int // ERROR "invalid map key type"
+var X map[func()]int // ERROR "invalid map key type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28078.go b/gcc/testsuite/go.test/test/fixedbugs/issue28078.go
new file mode 100644
index 0000000..2e4c4b5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28078.go
@@ -0,0 +1,34 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Non-constant duplicate keys/cases should not be reported
+// as errors by the compiler.
+
+package p
+
+import "unsafe"
+
+func f() {
+ _ = map[uintptr]int{
+ 0: 0,
+ uintptr(unsafe.Pointer(nil)): 0,
+ }
+
+ switch uintptr(0) {
+ case 0:
+ case uintptr(unsafe.Pointer(nil)):
+ }
+
+ switch interface{}(nil) {
+ case nil:
+ case nil:
+ }
+
+ _ = map[interface{}]int{
+ nil: 0,
+ nil: 0,
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28079a.go b/gcc/testsuite/go.test/test/fixedbugs/issue28079a.go
new file mode 100644
index 0000000..b0631bb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28079a.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Non-Go-constant but constant indexes are ok at compile time.
+
+package p
+
+import "unsafe"
+
+func f() {
+ var x [0]int
+ x[uintptr(unsafe.Pointer(nil))] = 0
+}
+func g() {
+ var x [10]int
+ _ = x[3:uintptr(unsafe.Pointer(nil))]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28079b.go b/gcc/testsuite/go.test/test/fixedbugs/issue28079b.go
new file mode 100644
index 0000000..d1992e1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28079b.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Non-Go-constant but constant values aren't ok for array sizes.
+
+package p
+
+import "unsafe"
+
+type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound|array bound is not constant"
+
+func f() {
+ _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // GCCGO_ERROR "non-integer type for left operand of shift"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28079c.go b/gcc/testsuite/go.test/test/fixedbugs/issue28079c.go
new file mode 100644
index 0000000..dfac8d0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28079c.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Non-Go-constant but constant values aren't ok for shifts.
+
+package p
+
+import "unsafe"
+
+func f() {
+ _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "invalid operation: .*shift of type float64.*|non-integer type for left operand of shift"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28268.go b/gcc/testsuite/go.test/test/fixedbugs/issue28268.go
new file mode 100644
index 0000000..59a4c57
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28268.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that follow-on errors due to conflicting
+// struct field and method names are suppressed.
+
+package p
+
+type T struct {
+ a, b, c int
+ E
+}
+
+type E struct{}
+
+func (T) b() {} // ERROR "field and method named b|redeclares struct field name"
+func (*T) E() {} // ERROR "field and method named E|redeclares struct field name"
+
+func _() {
+ var x T
+ _ = x.a
+ _ = x.b // no follow-on error here
+ x.b() // no follow-on error here
+ _ = x.c
+ _ = x.E // no follow-on error here
+ x.E() // no follow-on error here
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28390.go b/gcc/testsuite/go.test/test/fixedbugs/issue28390.go
new file mode 100644
index 0000000..0a4d873
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28390.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 28390/28430: Function call arguments were not
+// converted correctly under some circumstances.
+
+package main
+
+import "fmt"
+
+type A struct {
+ K int
+ S string
+ M map[string]string
+}
+
+func newA(k int, s string) (a A) {
+ a.K = k
+ a.S = s
+ a.M = make(map[string]string)
+ a.M[s] = s
+ return
+}
+
+func proxy() (x int, a A) {
+ return 1, newA(2, "3")
+}
+
+func consume(x int, a interface{}) {
+ fmt.Println(x)
+ fmt.Println(a) // used to panic here
+}
+
+func main() {
+ consume(proxy())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28390.out b/gcc/testsuite/go.test/test/fixedbugs/issue28390.out
new file mode 100644
index 0000000..c923108
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28390.out
@@ -0,0 +1,2 @@
+1
+{2 3 map[3:3]}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28430.go b/gcc/testsuite/go.test/test/fixedbugs/issue28430.go
new file mode 100644
index 0000000..b59259a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28430.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 28390/28430: Function call arguments were not
+// converted correctly under some circumstances.
+
+package main
+
+func g(_ interface{}, e error)
+func h() (int, error)
+
+func f() {
+ g(h())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28445.go b/gcc/testsuite/go.test/test/fixedbugs/issue28445.go
new file mode 100644
index 0000000..5726140
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28445.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var fp = (**float64)(nil)
+
+func f() {
+ switch fp {
+ case new(*float64):
+ println()
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28450.go b/gcc/testsuite/go.test/test/fixedbugs/issue28450.go
new file mode 100644
index 0000000..2acfe39
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28450.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(a, b, c, d ...int) {} // ERROR "non-final parameter a|only permits one name"
+func g(a ...int, b ...int) {} // ERROR "non-final parameter a|must be last parameter"
+func h(...int, ...int, float32) {} // ERROR "non-final parameter|must be last parameter"
+
+type a func(...float32, ...interface{}) // ERROR "non-final parameter|must be last parameter"
+type b interface {
+ f(...int, ...int) // ERROR "non-final parameter|must be last parameter"
+ g(a ...int, b ...int, c float32) // ERROR "non-final parameter a|must be last parameter"
+ valid(...int)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28601.go b/gcc/testsuite/go.test/test/fixedbugs/issue28601.go
new file mode 100644
index 0000000..ec367e9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28601.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Failed to compile with gccgo.
+
+package p
+
+import "unsafe"
+
+const w int = int(unsafe.Sizeof(0))
+
+var a [w]byte
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28616.go b/gcc/testsuite/go.test/test/fixedbugs/issue28616.go
new file mode 100644
index 0000000..f1ba974
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28616.go
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we don't dead code eliminate a label.
+
+package p
+
+var i int
+
+func f() {
+
+ if true {
+
+ if i == 1 {
+ goto label
+ }
+
+ return
+ }
+
+label:
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28688.go b/gcc/testsuite/go.test/test/fixedbugs/issue28688.go
new file mode 100644
index 0000000..0d2000e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28688.go
@@ -0,0 +1,31 @@
+// run -gcflags=-d=softfloat
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+// When using soft-float, OMUL might be rewritten to function
+// call so we should ensure it was evaluated first. Stack frame
+// setup for "test" function call should happen after call to runtime.fmul32
+
+var x int32 = 1
+
+func main() {
+ var y float32 = 1.0
+ test(x, y*y)
+}
+
+//go:noinline
+func test(id int32, a float32) {
+
+ if id != x {
+ fmt.Printf("got: %d, want: %d\n", id, x)
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue28797.go b/gcc/testsuite/go.test/test/fixedbugs/issue28797.go
new file mode 100644
index 0000000..480c105
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue28797.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+// test expects f to panic, but not to run out of memory,
+// which is a non-panic fatal error. OOM results from failure
+// to properly check negative limit.
+func test(f func()) {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("panic wasn't recoverable")
+ }
+ }()
+ f()
+}
+
+//go:noinline
+func id(x int) int {
+ return x
+}
+
+func main() {
+ test(foo)
+ test(bar)
+}
+
+func foo() {
+ b := make([]byte, 0)
+ b = append(b, 1)
+ id(len(b))
+ id(len(b) - 2)
+ s := string(b[1 : len(b)-2])
+ fmt.Println(s)
+}
+
+func bar() {
+ b := make([]byte, 1)
+ b = append(b, 1)
+ i := id(-1)
+ if i < len(b) { // establish value is not too large.
+ s := string(b[1:i]) // should check for negative also.
+ fmt.Println(s)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29013a.go b/gcc/testsuite/go.test/test/fixedbugs/issue29013a.go
new file mode 100644
index 0000000..efc50df
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29013a.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type TestSuite struct {
+ Tests []int
+}
+
+var Suites = []TestSuite{
+ Dicts,
+}
+var Dicts = TestSuite{
+ Tests: []int{0},
+}
+
+func main() {
+ if &Dicts.Tests[0] != &Suites[0].Tests[0] {
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29013b.go b/gcc/testsuite/go.test/test/fixedbugs/issue29013b.go
new file mode 100644
index 0000000..b8502da
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29013b.go
@@ -0,0 +1,43 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type TestSuite struct {
+ Tests []Test
+}
+type Test struct {
+ Want interface{}
+}
+type Int struct {
+ i int
+}
+
+func NewInt(v int) Int {
+ return Int{i: v}
+}
+
+var Suites = []TestSuite{
+ Dicts,
+}
+var Dicts = TestSuite{
+ Tests: []Test{
+ {
+ Want: map[Int]bool{NewInt(1): true},
+ },
+ {
+ Want: map[Int]string{
+ NewInt(3): "3",
+ },
+ },
+ },
+}
+
+func main() {
+ if Suites[0].Tests[0].Want.(map[Int]bool)[NewInt(3)] {
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29190.go b/gcc/testsuite/go.test/test/fixedbugs/issue29190.go
new file mode 100644
index 0000000..c0c4bb1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29190.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "strings"
+)
+
+type T struct{}
+
+const maxInt = int(^uint(0) >> 1)
+
+func main() {
+ s := make([]T, maxInt)
+ shouldPanic("cap out of range", func() { s = append(s, T{}) })
+ var oneElem = make([]T, 1)
+ shouldPanic("cap out of range", func() { s = append(s, oneElem...) })
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ s := err.(error).Error()
+ if !strings.Contains(s, str) {
+ panic("got panic " + s + ", want " + str)
+ }
+ }()
+
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29215.go b/gcc/testsuite/go.test/test/fixedbugs/issue29215.go
new file mode 100644
index 0000000..4e8f107
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29215.go
@@ -0,0 +1,35 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f() {
+ var s string
+ var p, q bool
+ s = "a"
+ for p {
+ p = false == (true != q)
+ s = ""
+ }
+ _ = s == "bbb"
+}
+
+// Another case: load from negative offset of a symbol
+// in dead code (issue 30257).
+func g() {
+ var i int
+ var s string
+
+ if true {
+ s = "a"
+ }
+
+ if f := 0.0; -f < 0 {
+ i = len(s[:4])
+ }
+
+ _ = s[i-1:0] != "bb" && true
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29218.go b/gcc/testsuite/go.test/test/fixedbugs/issue29218.go
new file mode 100644
index 0000000..ac9fed7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29218.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct {
+ b bool
+ string
+}
+
+func f() {
+ var b bool
+ var t T
+ for {
+ switch &t.b {
+ case &b:
+ if b {
+ }
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29220.go b/gcc/testsuite/go.test/test/fixedbugs/issue29220.go
new file mode 100644
index 0000000..bbfe930
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29220.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func ascii(r rune) rune {
+ switch {
+ case 97 <= r && r <= 122:
+ return r - 32
+ case 65 <= r && r <= 90:
+ return r + 32
+ default:
+ return r
+ }
+}
+
+func main() {
+ nomeObjeto := "ABE1FK21"
+ println(string(nomeObjeto[1:4]))
+ println(ascii(rune(nomeObjeto[4])) >= 48 && ascii(rune(nomeObjeto[4])) <= 57)
+ println(string(nomeObjeto[5]))
+ println(string(nomeObjeto[6:10]))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29264.go b/gcc/testsuite/go.test/test/fixedbugs/issue29264.go
new file mode 100644
index 0000000..3781559
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29264.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we emit a valid type descriptor for
+// a fairly deeply nested type.
+
+package main
+
+import "fmt"
+import "strings"
+
+func main() {
+ a := [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]int{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{42}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+ got := fmt.Sprint(a)
+ want := strings.Repeat("[", 100) + "42" + strings.Repeat("]", 100)
+ if got != want {
+ fmt.Printf("got %q\nwant %q\n", got, want)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29304.go b/gcc/testsuite/go.test/test/fixedbugs/issue29304.go
new file mode 100644
index 0000000..47bc99f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29304.go
@@ -0,0 +1,19 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that relocation target go.builtin.error.Error
+// is defined and the code links and runs correctly.
+
+package main
+
+import "errors"
+
+func main() {
+ err := errors.New("foo")
+ if error.Error(err) != "foo" {
+ panic("FAILED")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29312.go b/gcc/testsuite/go.test/test/fixedbugs/issue29312.go
new file mode 100644
index 0000000..4293e01
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29312.go
@@ -0,0 +1,70 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test is not for a fix of 29312 proper, but for the patch that
+// makes sure we at least don't have a security hole because of 29312.
+
+// This code generates lots of types. The binary should contain
+// a runtime.slicetype for each of the following 253 types:
+//
+// []*pwn
+// [][]*pwn
+// ...
+// [][]...[][]*pwn - 249 total "[]"
+// [][]...[][][]*pwn - 250 total "[]"
+// [][]...[][][][]*pwn - 251 total "[]"
+// [][]...[][][][][]*pwn - 252 total "[]"
+// [][]...[][][][][][]*pwn - 253 total "[]"
+//
+// The type names for these types are as follows. Because we truncate
+// the name at depth 250, the last few names are all identical:
+//
+// type.[]*"".pwn
+// type.[][]*"".pwn
+// ...
+// type.[][]...[][]*pwn - 249 total "[]"
+// type.[][]...[][][]*<...> - 250 total "[]"
+// type.[][]...[][][][]<...> - 251 total "[]"
+// type.[][]...[][][][]<...> - 252 total "[]" (but only 251 "[]" in the name)
+// type.[][]...[][][][]<...> - 253 total "[]" (but only 251 "[]" in the name)
+//
+// Because the names of the last 3 types are all identical, the
+// compiler will generate only a single runtime.slicetype data
+// structure for all 3 underlying types. It turns out the compiler
+// generates just the 251-entry one. There aren't any
+// runtime.slicetypes generated for the final two types.
+//
+// The compiler passes type.[]...[]<...> (251 total "[]") to
+// fmt.Sprintf (instead of the correct 253 one). But the data
+// structure at runtime actually has 253 nesting levels. So we end up
+// calling String on something that is of type [][]*pwn instead of
+// something of type *pwn. The way arg passing in Go works, the
+// backing store pointer for the outer slice becomes the "this"
+// pointer of the String method, which points to the inner []*pwn
+// slice. The String method then modifies the length of that inner
+// slice.
+package main
+
+import "fmt"
+
+type pwn struct {
+ a [3]uint
+}
+
+func (this *pwn) String() string {
+ this.a[1] = 7 // update length
+ return ""
+}
+
+func main() {
+ var a pwn
+ s := [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]*pwn{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{&a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} // depth 253
+ fmt.Sprint(s)
+ n := len(s[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]) // depth 252, type []*pwn
+ if n != 1 {
+ panic(fmt.Sprintf("length was changed, want 1 got %d", n))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29329.go b/gcc/testsuite/go.test/test/fixedbugs/issue29329.go
new file mode 100644
index 0000000..7818bca
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29329.go
@@ -0,0 +1,107 @@
+// +build cgo
+// run -race
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,amd64
+
+package main
+
+import (
+ "fmt"
+)
+
+type LineString []Point
+type Point [2]float64
+
+//go:noinline
+func benchmarkData() LineString {
+ return LineString{{1.0, 2.0}}
+}
+
+func (ls LineString) Clone() LineString {
+ ps := MultiPoint(ls)
+ return LineString(ps.Clone())
+}
+
+type MultiPoint []Point
+
+func (mp MultiPoint) Clone() MultiPoint {
+ if mp == nil {
+ return nil
+ }
+
+ points := make([]Point, len(mp))
+ copy(points, mp)
+
+ return MultiPoint(points)
+}
+
+func F1() {
+ cases := []struct {
+ threshold float64
+ length int
+ }{
+ {0.1, 1118},
+ {0.5, 257},
+ {1.0, 144},
+ {1.5, 95},
+ {2.0, 71},
+ {3.0, 46},
+ {4.0, 39},
+ {5.0, 33},
+ }
+
+ ls := benchmarkData()
+
+ for k := 0; k < 100; k++ {
+ for i, tc := range cases {
+ r := DouglasPeucker(tc.threshold).LineString(ls.Clone())
+ if len(r) == tc.length {
+ fmt.Printf("%d: unexpected\n", i)
+ }
+ }
+ }
+}
+
+// A DouglasPeuckerSimplifier wraps the DouglasPeucker function.
+type DouglasPeuckerSimplifier struct {
+ Threshold float64
+}
+
+// DouglasPeucker creates a new DouglasPeuckerSimplifier.
+func DouglasPeucker(threshold float64) *DouglasPeuckerSimplifier {
+ return &DouglasPeuckerSimplifier{
+ Threshold: threshold,
+ }
+}
+
+func (s *DouglasPeuckerSimplifier) LineString(ls LineString) LineString {
+ return lineString(s, ls)
+}
+
+type simplifier interface {
+ simplify(LineString, bool) (LineString, []int)
+}
+
+func lineString(s simplifier, ls LineString) LineString {
+ return runSimplify(s, ls)
+}
+
+func runSimplify(s simplifier, ls LineString) LineString {
+ if len(ls) <= 2 {
+ return ls
+ }
+ ls, _ = s.simplify(ls, false)
+ return ls
+}
+
+func (s *DouglasPeuckerSimplifier) simplify(ls LineString, wim bool) (LineString, []int) {
+ return nil, nil
+}
+
+func main() {
+ F1()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29350.go b/gcc/testsuite/go.test/test/fixedbugs/issue29350.go
new file mode 100644
index 0000000..9d59f6f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29350.go
@@ -0,0 +1,9 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var X interface{} = 'x'
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29362.go b/gcc/testsuite/go.test/test/fixedbugs/issue29362.go
new file mode 100644
index 0000000..a8bd607
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29362.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we don't consider a Go'd function's
+// arguments as pointers when they aren't.
+
+package main
+
+import (
+ "unsafe"
+)
+
+var badPtr uintptr
+
+var sink []byte
+
+func init() {
+ // Allocate large enough to use largeAlloc.
+ b := make([]byte, 1<<16-1)
+ sink = b // force heap allocation
+ // Any space between the object and the end of page is invalid to point to.
+ badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
+}
+
+var throttle = make(chan struct{}, 10)
+
+func noPointerArgs(a, b, c, d uintptr) {
+ sink = make([]byte, 4096)
+ <-throttle
+}
+
+func main() {
+ const N = 1000
+ for i := 0; i < N; i++ {
+ throttle <- struct{}{}
+ go noPointerArgs(badPtr, badPtr, badPtr, badPtr)
+ sink = make([]byte, 4096)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29362b.go b/gcc/testsuite/go.test/test/fixedbugs/issue29362b.go
new file mode 100644
index 0000000..d1e3b47
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29362b.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we don't consider a Go'd function's
+// arguments as pointers when they aren't.
+
+package main
+
+import (
+ "unsafe"
+)
+
+var badPtr uintptr
+
+var sink []byte
+
+func init() {
+ // Allocate large enough to use largeAlloc.
+ b := make([]byte, 1<<16-1)
+ sink = b // force heap allocation
+ // Any space between the object and the end of page is invalid to point to.
+ badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
+}
+
+var throttle = make(chan struct{}, 10)
+
+// There are 2 arg bitmaps for this function, each with 2 bits.
+// In the first, p and q are both live, so that bitmap is 11.
+// In the second, only p is live, so that bitmap is 10.
+// Bitmaps are byte aligned, so if the first bitmap is interpreted as
+// extending across the entire argument area, we incorrectly concatenate
+// the bitmaps and end up using 110000001. That bad bitmap causes a6
+// to be considered a pointer.
+func noPointerArgs(p, q *byte, a0, a1, a2, a3, a4, a5, a6 uintptr) {
+ sink = make([]byte, 4096)
+ sinkptr = q
+ <-throttle
+ sinkptr = p
+}
+
+var sinkptr *byte
+
+func main() {
+ const N = 1000
+ for i := 0; i < N; i++ {
+ throttle <- struct{}{}
+ go noPointerArgs(nil, nil, badPtr, badPtr, badPtr, badPtr, badPtr, badPtr, badPtr)
+ sink = make([]byte, 4096)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29389.go b/gcc/testsuite/go.test/test/fixedbugs/issue29389.go
new file mode 100644
index 0000000..43859fd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29389.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we can correctly compile method expressions
+// where the method is implicitly declared.
+
+package main
+
+import "io"
+
+func main() {
+ err := io.EOF
+ _ = err.Error
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29402.go b/gcc/testsuite/go.test/test/fixedbugs/issue29402.go
new file mode 100644
index 0000000..8a1f959
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29402.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 29402: wrong optimization of comparison of
+// constant and shift on MIPS.
+
+package main
+
+//go:noinline
+func F(s []int) bool {
+ half := len(s) / 2
+ return half >= 0
+}
+
+func main() {
+ b := F([]int{1, 2, 3, 4})
+ if !b {
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29562.go b/gcc/testsuite/go.test/test/fixedbugs/issue29562.go
new file mode 100644
index 0000000..cbcd77d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29562.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Triggers a double walk of the (inlined) switch in il
+
+package p
+
+func il(s string) string {
+ switch len(s) {
+ case 0:
+ return "zero"
+ case 1:
+ return "one"
+ }
+ return s
+}
+
+func f() {
+ var s string
+ var as []string
+ switch false && (s+"a"+as[0]+il(s)+as[0]+s == "") {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/a.go
new file mode 100644
index 0000000..ccbe451
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type I interface {
+ M(init bool)
+}
+
+var V I
+
+func init() {
+ V = nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/b.go
new file mode 100644
index 0000000..c2016de
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/b.go
@@ -0,0 +1,17 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type S struct {
+ a.I
+}
+
+var V a.I
+
+func init() {
+ V = S{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/main.go
new file mode 100644
index 0000000..29437bf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29610.dir/main.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./b"
+
+var v b.S
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29610.go b/gcc/testsuite/go.test/test/fixedbugs/issue29610.go
new file mode 100644
index 0000000..8d49ba6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29610.go
@@ -0,0 +1,13 @@
+// rundir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 29610: Symbol import and initialization order caused function
+// symbols to be recorded as non-function symbols.
+
+// This uses rundir not because we actually want to run the final
+// binary, but because we need to at least link it.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29735.go b/gcc/testsuite/go.test/test/fixedbugs/issue29735.go
new file mode 100644
index 0000000..7a0381d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29735.go
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure FuncForPC won't panic when given a pc which
+// lies between two functions.
+
+package main
+
+import (
+ "runtime"
+)
+
+func main() {
+ var stack [1]uintptr
+ runtime.Callers(1, stack[:])
+ f() // inlined function, to give main some inlining info
+ for i := uintptr(0); true; i++ {
+ f := runtime.FuncForPC(stack[0] + i)
+ if f.Name() != "main.main" && f.Name() != "main.f" {
+ // Reached next function successfully.
+ break
+ }
+ }
+}
+
+func f() {
+ sink = 0 // one instruction which can't be removed
+}
+
+var sink int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29855.go b/gcc/testsuite/go.test/test/fixedbugs/issue29855.go
new file mode 100644
index 0000000..402093c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29855.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T struct {
+ GlobalName string
+}
+
+var t = T{Name: "foo"} // ERROR "unknown field 'Name' in struct literal of type T|unknown field .*Name.* in .*T"
+
+func (t T) Name() string {
+ return t.GlobalName
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29870.go b/gcc/testsuite/go.test/test/fixedbugs/issue29870.go
new file mode 100644
index 0000000..b79860c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29870.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we can compile "_" functions without crashing.
+
+package main
+
+import "log"
+
+func _() {
+ log.Println("%2F")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29870b.go b/gcc/testsuite/go.test/test/fixedbugs/issue29870b.go
new file mode 100644
index 0000000..0a83489
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29870b.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we're compiling "_" functions at least enough
+// to get to an error which is generated during walk.
+
+package main
+
+func _() {
+ x := 7 // ERROR ".*x.* declared but not used"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue29943.go b/gcc/testsuite/go.test/test/fixedbugs/issue29943.go
new file mode 100644
index 0000000..ff47de5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue29943.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code was miscompiled on ppc64le due to incorrect zero-extension
+// that was CSE'd.
+
+package main
+
+//go:noinline
+func g(i uint64) uint64 {
+ return uint64(uint32(i))
+}
+
+var sink uint64
+
+func main() {
+ for i := uint64(0); i < 1; i++ {
+ i32 := int32(i - 1)
+ sink = uint64((uint32(i32) << 1) ^ uint32((i32 >> 31)))
+ x := g(uint64(i32))
+ if x != uint64(uint32(i32)) {
+ panic(x)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30041.go b/gcc/testsuite/go.test/test/fixedbugs/issue30041.go
new file mode 100644
index 0000000..7d8a169
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30041.go
@@ -0,0 +1,63 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 30041: copying results of a reflect-generated
+// call on stack should not have write barrier.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+var badPtr uintptr
+
+var sink []byte
+
+func init() {
+ // Allocate large enough to use largeAlloc.
+ b := make([]byte, 1<<16-1)
+ sink = b // force heap allocation
+ // Any space between the object and the end of page is invalid to point to.
+ badPtr = uintptr(unsafe.Pointer(&b[len(b)-1])) + 1
+}
+
+type ft func() *int
+
+var fn ft
+
+func rf([]reflect.Value) []reflect.Value {
+ a := reflect.ValueOf((*int)(nil))
+ return []reflect.Value{a}
+}
+
+const N = 1000
+
+func main() {
+ fn = reflect.MakeFunc(reflect.TypeOf(fn), rf).Interface().(ft)
+
+ // Keep running GC so the write barrier is on.
+ go func() {
+ for i := 0; i < N; i++ {
+ runtime.GC()
+ }
+ }()
+
+ var x [10]uintptr
+ for i := range x {
+ x[i] = badPtr
+ }
+ for i := 0; i < N; i++ {
+ runtime.Gosched()
+ use(x) // prepare bad pointers on stack
+ fn()
+ }
+}
+
+//go:noinline
+func use([10]uintptr) {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30061.go b/gcc/testsuite/go.test/test/fixedbugs/issue30061.go
new file mode 100644
index 0000000..5092b01
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30061.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we can linkname to memmove with an unsafe.Pointer argument.
+
+package p
+
+import "unsafe"
+
+//go:linkname memmove runtime.memmove
+func memmove(to, from unsafe.Pointer, n uintptr)
+
+var V1, V2 int
+
+func F() {
+ memmove(unsafe.Pointer(&V1), unsafe.Pointer(&V2), unsafe.Sizeof(int(0)))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30085.go b/gcc/testsuite/go.test/test/fixedbugs/issue30085.go
new file mode 100644
index 0000000..d2ac4cf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30085.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var c, d = 1, 2, 3 // ERROR "assignment mismatch: 2 variables but 3 values|wrong number of initializations"
+ var e, f, g = 1, 2 // ERROR "assignment mismatch: 3 variables but 2 values|wrong number of initializations"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30087.go b/gcc/testsuite/go.test/test/fixedbugs/issue30087.go
new file mode 100644
index 0000000..3ad9c8c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30087.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var a, b = 1 // ERROR "assignment mismatch: 2 variables but 1 values|wrong number of initializations"
+ _ = 1, 2 // ERROR "assignment mismatch: 1 variables but 2 values|number of variables does not match"
+ c, d := 1 // ERROR "assignment mismatch: 2 variables but 1 values|wrong number of initializations"
+ e, f := 1, 2, 3 // ERROR "assignment mismatch: 2 variables but 3 values|wrong number of initializations"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30116.go b/gcc/testsuite/go.test/test/fixedbugs/issue30116.go
new file mode 100644
index 0000000..452a6e3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30116.go
@@ -0,0 +1,112 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test makes sure the text output for bounds check failures is as expected.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "text/tabwriter"
+)
+
+// Testing with length 3 slices, arrays, and strings.
+// Large (>1<<32) values are included to test 32-bit platforms.
+var indexes = []int64{-9876543210, -1, 0, 2, 3, 9876543210}
+var slices = []int64{-9876543210, -1, 0, 3, 4, 9876543210}
+
+var w *tabwriter.Writer
+
+func main() {
+ w = tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
+ defer w.Flush()
+ doIndex()
+ doSlice()
+ doSlice3()
+}
+func doIndex() {
+ a := []int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("slice[%d]", i), func() {
+ _ = a[i]
+ })
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("array[%d]", i), func() {
+ _ = b[i]
+ })
+ }
+ c := "123"
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("string[%d]", i), func() {
+ _ = c[i]
+ })
+ }
+}
+
+func doSlice() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d]", i, j), func() {
+ _ = a[i:j]
+ })
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d]", i, j), func() {
+ _ = b[i:j]
+ })
+ }
+ }
+ c := "123"
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("string[%d:%d]", i, j), func() {
+ _ = c[i:j]
+ })
+ }
+ }
+}
+
+func doSlice3() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d:%d]", i, j, k), func() {
+ _ = a[i:j:k]
+ })
+ }
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d:%d]", i, j, k), func() {
+ _ = b[i:j:k]
+ })
+ }
+ }
+ }
+}
+
+func printPanic(msg string, f func()) {
+ defer func() {
+ res := "no panic"
+ if e := recover(); e != nil {
+ res = e.(runtime.Error).Error()
+ }
+ fmt.Fprintf(w, "%s\t %s\n", msg, res)
+ }()
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30116.out b/gcc/testsuite/go.test/test/fixedbugs/issue30116.out
new file mode 100644
index 0000000..bde134d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30116.out
@@ -0,0 +1,558 @@
+ slice[-9876543210] runtime error: index out of range [-9876543210]
+ slice[-1] runtime error: index out of range [-1]
+ slice[0] no panic
+ slice[2] no panic
+ slice[3] runtime error: index out of range [3] with length 3
+ slice[9876543210] runtime error: index out of range [9876543210] with length 3
+ array[-9876543210] runtime error: index out of range [-9876543210]
+ array[-1] runtime error: index out of range [-1]
+ array[0] no panic
+ array[2] no panic
+ array[3] runtime error: index out of range [3] with length 3
+ array[9876543210] runtime error: index out of range [9876543210] with length 3
+ string[-9876543210] runtime error: index out of range [-9876543210]
+ string[-1] runtime error: index out of range [-1]
+ string[0] no panic
+ string[2] no panic
+ string[3] runtime error: index out of range [3] with length 3
+ string[9876543210] runtime error: index out of range [9876543210] with length 3
+ slice[-9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[-9876543210:-1] runtime error: slice bounds out of range [:-1]
+ slice[-9876543210:0] runtime error: slice bounds out of range [-9876543210:]
+ slice[-9876543210:3] runtime error: slice bounds out of range [-9876543210:]
+ slice[-9876543210:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[-9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[-1:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[-1:-1] runtime error: slice bounds out of range [:-1]
+ slice[-1:0] runtime error: slice bounds out of range [-1:]
+ slice[-1:3] runtime error: slice bounds out of range [-1:]
+ slice[-1:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[-1:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[0:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[0:-1] runtime error: slice bounds out of range [:-1]
+ slice[0:0] no panic
+ slice[0:3] no panic
+ slice[0:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[0:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[3:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[3:-1] runtime error: slice bounds out of range [:-1]
+ slice[3:0] runtime error: slice bounds out of range [3:0]
+ slice[3:3] no panic
+ slice[3:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[3:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[4:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[4:-1] runtime error: slice bounds out of range [:-1]
+ slice[4:0] runtime error: slice bounds out of range [4:0]
+ slice[4:3] runtime error: slice bounds out of range [4:3]
+ slice[4:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[4:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[9876543210:-1] runtime error: slice bounds out of range [:-1]
+ slice[9876543210:0] runtime error: slice bounds out of range [9876543210:0]
+ slice[9876543210:3] runtime error: slice bounds out of range [9876543210:3]
+ slice[9876543210:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ array[-9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[-9876543210:-1] runtime error: slice bounds out of range [:-1]
+ array[-9876543210:0] runtime error: slice bounds out of range [-9876543210:]
+ array[-9876543210:3] runtime error: slice bounds out of range [-9876543210:]
+ array[-9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ array[-9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[-1:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[-1:-1] runtime error: slice bounds out of range [:-1]
+ array[-1:0] runtime error: slice bounds out of range [-1:]
+ array[-1:3] runtime error: slice bounds out of range [-1:]
+ array[-1:4] runtime error: slice bounds out of range [:4] with length 3
+ array[-1:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[0:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[0:-1] runtime error: slice bounds out of range [:-1]
+ array[0:0] no panic
+ array[0:3] no panic
+ array[0:4] runtime error: slice bounds out of range [:4] with length 3
+ array[0:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[3:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[3:-1] runtime error: slice bounds out of range [:-1]
+ array[3:0] runtime error: slice bounds out of range [3:0]
+ array[3:3] no panic
+ array[3:4] runtime error: slice bounds out of range [:4] with length 3
+ array[3:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[4:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[4:-1] runtime error: slice bounds out of range [:-1]
+ array[4:0] runtime error: slice bounds out of range [4:0]
+ array[4:3] runtime error: slice bounds out of range [4:3]
+ array[4:4] runtime error: slice bounds out of range [:4] with length 3
+ array[4:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[9876543210:-1] runtime error: slice bounds out of range [:-1]
+ array[9876543210:0] runtime error: slice bounds out of range [9876543210:0]
+ array[9876543210:3] runtime error: slice bounds out of range [9876543210:3]
+ array[9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ array[9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[-9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[-9876543210:-1] runtime error: slice bounds out of range [:-1]
+ string[-9876543210:0] runtime error: slice bounds out of range [-9876543210:]
+ string[-9876543210:3] runtime error: slice bounds out of range [-9876543210:]
+ string[-9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ string[-9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[-1:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[-1:-1] runtime error: slice bounds out of range [:-1]
+ string[-1:0] runtime error: slice bounds out of range [-1:]
+ string[-1:3] runtime error: slice bounds out of range [-1:]
+ string[-1:4] runtime error: slice bounds out of range [:4] with length 3
+ string[-1:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[0:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[0:-1] runtime error: slice bounds out of range [:-1]
+ string[0:0] no panic
+ string[0:3] no panic
+ string[0:4] runtime error: slice bounds out of range [:4] with length 3
+ string[0:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[3:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[3:-1] runtime error: slice bounds out of range [:-1]
+ string[3:0] runtime error: slice bounds out of range [3:0]
+ string[3:3] no panic
+ string[3:4] runtime error: slice bounds out of range [:4] with length 3
+ string[3:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[4:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[4:-1] runtime error: slice bounds out of range [:-1]
+ string[4:0] runtime error: slice bounds out of range [4:0]
+ string[4:3] runtime error: slice bounds out of range [4:3]
+ string[4:4] runtime error: slice bounds out of range [:4] with length 3
+ string[4:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[9876543210:-1] runtime error: slice bounds out of range [:-1]
+ string[9876543210:0] runtime error: slice bounds out of range [9876543210:0]
+ string[9876543210:3] runtime error: slice bounds out of range [9876543210:3]
+ string[9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ string[9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ slice[-9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[-9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[-9876543210:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:0:0] runtime error: slice bounds out of range [-9876543210::]
+ slice[-9876543210:0:3] runtime error: slice bounds out of range [-9876543210::]
+ slice[-9876543210:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[-9876543210:3:3] runtime error: slice bounds out of range [-9876543210::]
+ slice[-9876543210:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[-9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[-9876543210:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[-9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[-9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-1:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-1:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[-1:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[-1:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:0:0] runtime error: slice bounds out of range [-1::]
+ slice[-1:0:3] runtime error: slice bounds out of range [-1::]
+ slice[-1:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[-1:3:3] runtime error: slice bounds out of range [-1::]
+ slice[-1:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[-1:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[-1:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[-1:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[-1:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[0:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[0:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[0:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[0:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:0:0] no panic
+ slice[0:0:3] no panic
+ slice[0:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[0:3:3] no panic
+ slice[0:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[0:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[0:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[0:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[0:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[3:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[3:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[3:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[3:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:0:0] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:3] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[3:3:3] no panic
+ slice[3:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[3:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[3:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[3:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[3:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[4:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[4:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[4:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[4:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:0:0] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:3] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[4:3:3] runtime error: slice bounds out of range [4:3:]
+ slice[4:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[4:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[4:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[4:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[4:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[9876543210:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:0:0] runtime error: slice bounds out of range [9876543210:0:]
+ slice[9876543210:0:3] runtime error: slice bounds out of range [9876543210:0:]
+ slice[9876543210:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[9876543210:3:3] runtime error: slice bounds out of range [9876543210:3:]
+ slice[9876543210:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[9876543210:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ array[-9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[-9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[-9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[-9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[-9876543210:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:0:0] runtime error: slice bounds out of range [-9876543210::]
+ array[-9876543210:0:3] runtime error: slice bounds out of range [-9876543210::]
+ array[-9876543210:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ array[-9876543210:3:3] runtime error: slice bounds out of range [-9876543210::]
+ array[-9876543210:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ array[-9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ array[-9876543210:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[-9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[-9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[-1:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[-1:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[-1:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[-1:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:0:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:0:0] runtime error: slice bounds out of range [-1::]
+ array[-1:0:3] runtime error: slice bounds out of range [-1::]
+ array[-1:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:3:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:3:0] runtime error: slice bounds out of range [:3:0]
+ array[-1:3:3] runtime error: slice bounds out of range [-1::]
+ array[-1:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:4:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:4:0] runtime error: slice bounds out of range [:4:0]
+ array[-1:4:3] runtime error: slice bounds out of range [:4:3]
+ array[-1:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[-1:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[-1:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[0:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[0:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[0:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[0:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[0:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[0:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:0:-1] runtime error: slice bounds out of range [::-1]
+ array[0:0:0] no panic
+ array[0:0:3] no panic
+ array[0:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:3:-1] runtime error: slice bounds out of range [::-1]
+ array[0:3:0] runtime error: slice bounds out of range [:3:0]
+ array[0:3:3] no panic
+ array[0:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:4:-1] runtime error: slice bounds out of range [::-1]
+ array[0:4:0] runtime error: slice bounds out of range [:4:0]
+ array[0:4:3] runtime error: slice bounds out of range [:4:3]
+ array[0:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[0:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[0:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[0:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[3:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[3:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[3:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[3:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[3:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[3:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:0:-1] runtime error: slice bounds out of range [::-1]
+ array[3:0:0] runtime error: slice bounds out of range [3:0:]
+ array[3:0:3] runtime error: slice bounds out of range [3:0:]
+ array[3:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:3:-1] runtime error: slice bounds out of range [::-1]
+ array[3:3:0] runtime error: slice bounds out of range [:3:0]
+ array[3:3:3] no panic
+ array[3:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:4:-1] runtime error: slice bounds out of range [::-1]
+ array[3:4:0] runtime error: slice bounds out of range [:4:0]
+ array[3:4:3] runtime error: slice bounds out of range [:4:3]
+ array[3:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[3:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[3:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[3:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[4:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[4:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[4:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[4:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[4:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[4:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:0:-1] runtime error: slice bounds out of range [::-1]
+ array[4:0:0] runtime error: slice bounds out of range [4:0:]
+ array[4:0:3] runtime error: slice bounds out of range [4:0:]
+ array[4:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:3:-1] runtime error: slice bounds out of range [::-1]
+ array[4:3:0] runtime error: slice bounds out of range [:3:0]
+ array[4:3:3] runtime error: slice bounds out of range [4:3:]
+ array[4:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:4:-1] runtime error: slice bounds out of range [::-1]
+ array[4:4:0] runtime error: slice bounds out of range [:4:0]
+ array[4:4:3] runtime error: slice bounds out of range [:4:3]
+ array[4:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[4:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[4:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[4:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[9876543210:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:0:0] runtime error: slice bounds out of range [9876543210:0:]
+ array[9876543210:0:3] runtime error: slice bounds out of range [9876543210:0:]
+ array[9876543210:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ array[9876543210:3:3] runtime error: slice bounds out of range [9876543210:3:]
+ array[9876543210:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ array[9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ array[9876543210:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30116u.go b/gcc/testsuite/go.test/test/fixedbugs/issue30116u.go
new file mode 100644
index 0000000..7c2aea2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30116u.go
@@ -0,0 +1,112 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test makes sure the text output for bounds check failures is as expected.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "text/tabwriter"
+)
+
+// Testing with length 3 slices, arrays, and strings.
+// A large (>1<<32) value is included to test 32-bit platforms.
+var indexes = []uint64{0, 2, 3, 1<<32 - 1, 1<<64 - 1}
+var slices = []uint64{0, 3, 4, 1<<32 - 1, 1<<64 - 1}
+
+var w *tabwriter.Writer
+
+func main() {
+ w = tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
+ defer w.Flush()
+ doIndex()
+ doSlice()
+ doSlice3()
+}
+func doIndex() {
+ a := []int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("slice[%d]", i), func() {
+ _ = a[i]
+ })
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("array[%d]", i), func() {
+ _ = b[i]
+ })
+ }
+ c := "123"
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("string[%d]", i), func() {
+ _ = c[i]
+ })
+ }
+}
+
+func doSlice() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d]", i, j), func() {
+ _ = a[i:j]
+ })
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d]", i, j), func() {
+ _ = b[i:j]
+ })
+ }
+ }
+ c := "123"
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("string[%d:%d]", i, j), func() {
+ _ = c[i:j]
+ })
+ }
+ }
+}
+
+func doSlice3() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d:%d]", i, j, k), func() {
+ _ = a[i:j:k]
+ })
+ }
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d:%d]", i, j, k), func() {
+ _ = b[i:j:k]
+ })
+ }
+ }
+ }
+}
+
+func printPanic(msg string, f func()) {
+ defer func() {
+ res := "no panic"
+ if e := recover(); e != nil {
+ res = e.(runtime.Error).Error()
+ }
+ fmt.Fprintf(w, "%s\t %s\n", msg, res)
+ }()
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30116u.out b/gcc/testsuite/go.test/test/fixedbugs/issue30116u.out
new file mode 100644
index 0000000..ee19192
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30116u.out
@@ -0,0 +1,340 @@
+ slice[0] no panic
+ slice[2] no panic
+ slice[3] runtime error: index out of range [3] with length 3
+ slice[4294967295] runtime error: index out of range [4294967295] with length 3
+ slice[18446744073709551615] runtime error: index out of range [18446744073709551615] with length 3
+ array[0] no panic
+ array[2] no panic
+ array[3] runtime error: index out of range [3] with length 3
+ array[4294967295] runtime error: index out of range [4294967295] with length 3
+ array[18446744073709551615] runtime error: index out of range [18446744073709551615] with length 3
+ string[0] no panic
+ string[2] no panic
+ string[3] runtime error: index out of range [3] with length 3
+ string[4294967295] runtime error: index out of range [4294967295] with length 3
+ string[18446744073709551615] runtime error: index out of range [18446744073709551615] with length 3
+ slice[0:0] no panic
+ slice[0:3] no panic
+ slice[0:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[0:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[0:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[3:0] runtime error: slice bounds out of range [3:0]
+ slice[3:3] no panic
+ slice[3:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[3:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[3:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[4:0] runtime error: slice bounds out of range [4:0]
+ slice[4:3] runtime error: slice bounds out of range [4:3]
+ slice[4:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[4:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[4:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[4294967295:0] runtime error: slice bounds out of range [4294967295:0]
+ slice[4294967295:3] runtime error: slice bounds out of range [4294967295:3]
+ slice[4294967295:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[4294967295:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[4294967295:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[18446744073709551615:0] runtime error: slice bounds out of range [18446744073709551615:0]
+ slice[18446744073709551615:3] runtime error: slice bounds out of range [18446744073709551615:3]
+ slice[18446744073709551615:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[18446744073709551615:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ array[0:0] no panic
+ array[0:3] no panic
+ array[0:4] runtime error: slice bounds out of range [:4] with length 3
+ array[0:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[0:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[3:0] runtime error: slice bounds out of range [3:0]
+ array[3:3] no panic
+ array[3:4] runtime error: slice bounds out of range [:4] with length 3
+ array[3:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[3:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[4:0] runtime error: slice bounds out of range [4:0]
+ array[4:3] runtime error: slice bounds out of range [4:3]
+ array[4:4] runtime error: slice bounds out of range [:4] with length 3
+ array[4:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[4:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[4294967295:0] runtime error: slice bounds out of range [4294967295:0]
+ array[4294967295:3] runtime error: slice bounds out of range [4294967295:3]
+ array[4294967295:4] runtime error: slice bounds out of range [:4] with length 3
+ array[4294967295:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[4294967295:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[18446744073709551615:0] runtime error: slice bounds out of range [18446744073709551615:0]
+ array[18446744073709551615:3] runtime error: slice bounds out of range [18446744073709551615:3]
+ array[18446744073709551615:4] runtime error: slice bounds out of range [:4] with length 3
+ array[18446744073709551615:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[0:0] no panic
+ string[0:3] no panic
+ string[0:4] runtime error: slice bounds out of range [:4] with length 3
+ string[0:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[0:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[3:0] runtime error: slice bounds out of range [3:0]
+ string[3:3] no panic
+ string[3:4] runtime error: slice bounds out of range [:4] with length 3
+ string[3:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[3:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[4:0] runtime error: slice bounds out of range [4:0]
+ string[4:3] runtime error: slice bounds out of range [4:3]
+ string[4:4] runtime error: slice bounds out of range [:4] with length 3
+ string[4:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[4:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[4294967295:0] runtime error: slice bounds out of range [4294967295:0]
+ string[4294967295:3] runtime error: slice bounds out of range [4294967295:3]
+ string[4294967295:4] runtime error: slice bounds out of range [:4] with length 3
+ string[4294967295:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[4294967295:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[18446744073709551615:0] runtime error: slice bounds out of range [18446744073709551615:0]
+ string[18446744073709551615:3] runtime error: slice bounds out of range [18446744073709551615:3]
+ string[18446744073709551615:4] runtime error: slice bounds out of range [:4] with length 3
+ string[18446744073709551615:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ slice[0:0:0] no panic
+ slice[0:0:3] no panic
+ slice[0:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[0:3:3] no panic
+ slice[0:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[0:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[0:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[0:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[0:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[0:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[0:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:0:0] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:3] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[3:3:3] no panic
+ slice[3:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[3:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[3:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[3:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[3:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[3:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[3:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:0:0] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:3] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[4:3:3] runtime error: slice bounds out of range [4:3:]
+ slice[4:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[4:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[4:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[4:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[4:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[4:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[4:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:0:0] runtime error: slice bounds out of range [4294967295:0:]
+ slice[4294967295:0:3] runtime error: slice bounds out of range [4294967295:0:]
+ slice[4294967295:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[4294967295:3:3] runtime error: slice bounds out of range [4294967295:3:]
+ slice[4294967295:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[4294967295:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[4294967295:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[4294967295:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[4294967295:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[4294967295:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[4294967295:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:0:0] runtime error: slice bounds out of range [18446744073709551615:0:]
+ slice[18446744073709551615:0:3] runtime error: slice bounds out of range [18446744073709551615:0:]
+ slice[18446744073709551615:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[18446744073709551615:3:3] runtime error: slice bounds out of range [18446744073709551615:3:]
+ slice[18446744073709551615:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[18446744073709551615:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[18446744073709551615:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[18446744073709551615:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[18446744073709551615:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[18446744073709551615:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[18446744073709551615:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ array[0:0:0] no panic
+ array[0:0:3] no panic
+ array[0:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:3:0] runtime error: slice bounds out of range [:3:0]
+ array[0:3:3] no panic
+ array[0:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:4:0] runtime error: slice bounds out of range [:4:0]
+ array[0:4:3] runtime error: slice bounds out of range [:4:3]
+ array[0:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[0:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[0:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[0:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[0:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:0:0] runtime error: slice bounds out of range [3:0:]
+ array[3:0:3] runtime error: slice bounds out of range [3:0:]
+ array[3:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:3:0] runtime error: slice bounds out of range [:3:0]
+ array[3:3:3] no panic
+ array[3:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:4:0] runtime error: slice bounds out of range [:4:0]
+ array[3:4:3] runtime error: slice bounds out of range [:4:3]
+ array[3:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[3:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[3:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[3:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[3:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:0:0] runtime error: slice bounds out of range [4:0:]
+ array[4:0:3] runtime error: slice bounds out of range [4:0:]
+ array[4:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:3:0] runtime error: slice bounds out of range [:3:0]
+ array[4:3:3] runtime error: slice bounds out of range [4:3:]
+ array[4:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:4:0] runtime error: slice bounds out of range [:4:0]
+ array[4:4:3] runtime error: slice bounds out of range [:4:3]
+ array[4:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[4:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[4:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[4:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[4:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:0:0] runtime error: slice bounds out of range [4294967295:0:]
+ array[4294967295:0:3] runtime error: slice bounds out of range [4294967295:0:]
+ array[4294967295:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:3:0] runtime error: slice bounds out of range [:3:0]
+ array[4294967295:3:3] runtime error: slice bounds out of range [4294967295:3:]
+ array[4294967295:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:4:0] runtime error: slice bounds out of range [:4:0]
+ array[4294967295:4:3] runtime error: slice bounds out of range [:4:3]
+ array[4294967295:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[4294967295:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[4294967295:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[4294967295:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[4294967295:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:0:0] runtime error: slice bounds out of range [18446744073709551615:0:]
+ array[18446744073709551615:0:3] runtime error: slice bounds out of range [18446744073709551615:0:]
+ array[18446744073709551615:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:3:0] runtime error: slice bounds out of range [:3:0]
+ array[18446744073709551615:3:3] runtime error: slice bounds out of range [18446744073709551615:3:]
+ array[18446744073709551615:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:4:0] runtime error: slice bounds out of range [:4:0]
+ array[18446744073709551615:4:3] runtime error: slice bounds out of range [:4:3]
+ array[18446744073709551615:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[18446744073709551615:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[18446744073709551615:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[18446744073709551615:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[18446744073709551615:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30243.go b/gcc/testsuite/go.test/test/fixedbugs/issue30243.go
new file mode 100644
index 0000000..51fd204
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30243.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Compile-time constants, even if they cannot be represented
+// accurately, should remain the same in operations that don't
+// affect their values.
+
+package main
+
+import "fmt"
+
+func main() {
+ const x = 0.01
+ const xi = 0.01i
+ const xc = complex(0, x)
+
+ if imag(xi) != x {
+ fmt.Printf("FAILED: %g != %g\n", imag(xi), x)
+ }
+
+ if xi != complex(0, x) {
+ fmt.Printf("FAILED: %g != %g\n", xi, complex(0, x))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30430.go b/gcc/testsuite/go.test/test/fixedbugs/issue30430.go
new file mode 100644
index 0000000..6c27b82
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30430.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 30430: isGoConst returned true for non-const variables,
+// resulting in ICE.
+
+package p
+
+func f() {
+ var s string
+ _ = map[string]string{s: ""}
+}
+
+const s = ""
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30476.go b/gcc/testsuite/go.test/test/fixedbugs/issue30476.go
new file mode 100644
index 0000000..a2147ec
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30476.go
@@ -0,0 +1,30 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 30476: KeepAlive didn't keep stack object alive.
+
+package main
+
+import "runtime"
+
+func main() {
+ x := new([10]int)
+ runtime.SetFinalizer(x, func(*[10]int) { panic("FAIL: finalizer runs") })
+ p := &T{x, 0}
+ use(p)
+ runtime.GC()
+ runtime.GC()
+ runtime.GC()
+ runtime.KeepAlive(p)
+}
+
+type T struct {
+ x *[10]int
+ y int
+}
+
+//go:noinline
+func use(*T) {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30566a.go b/gcc/testsuite/go.test/test/fixedbugs/issue30566a.go
new file mode 100644
index 0000000..5d736cc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30566a.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+//go:noinline
+func ident(s string) string { return s }
+
+func returnSecond(x bool, s string) string { return s }
+
+func identWrapper(s string) string { return ident(s) }
+
+func main() {
+ got := returnSecond((false || identWrapper("bad") != ""), ident("good"))
+ if got != "good" {
+ panic(fmt.Sprintf("wanted \"good\", got \"%s\"", got))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30566b.go b/gcc/testsuite/go.test/test/fixedbugs/issue30566b.go
new file mode 100644
index 0000000..92e0644
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30566b.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+)
+
+func main() {
+ _, _ = false || g(1), g(2)
+ if !bytes.Equal(x, []byte{1, 2}) {
+ panic(fmt.Sprintf("wanted [1,2], got %v", x))
+ }
+}
+
+var x []byte
+
+//go:noinline
+func g(b byte) bool {
+ x = append(x, b)
+ return false
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30606.go b/gcc/testsuite/go.test/test/fixedbugs/issue30606.go
new file mode 100644
index 0000000..bc31982
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30606.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "reflect"
+
+func main() {}
+
+func typ(x interface{}) reflect.Type { return reflect.ValueOf(x).Type() }
+
+var x = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F5", Type: reflect.StructOf([]reflect.StructField{
+ {Name: "F4", Type: reflect.ArrayOf(5462,
+ reflect.SliceOf(typ(uint64(0))))},
+ })},
+}))
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30606b.go b/gcc/testsuite/go.test/test/fixedbugs/issue30606b.go
new file mode 100644
index 0000000..2ce2804
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30606b.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "reflect"
+
+func main() {}
+
+func typ(x interface{}) reflect.Type { return reflect.ValueOf(x).Type() }
+
+var byteType = typ((byte)(0))
+var ptrType = typ((*byte)(nil))
+
+// Arrays of pointers. There are two size thresholds.
+// Bit masks are chunked in groups of 120 pointers.
+// Array types with >16384 pointers have a GC program instead of a bitmask.
+var smallPtrType = reflect.ArrayOf(100, ptrType)
+var mediumPtrType = reflect.ArrayOf(1000, ptrType)
+var bigPtrType = reflect.ArrayOf(16385, ptrType)
+
+var x0 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: byteType},
+ {Name: "F2", Type: bigPtrType},
+}))
+var x1 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: smallPtrType},
+ {Name: "F2", Type: bigPtrType},
+}))
+var x2 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: mediumPtrType},
+ {Name: "F2", Type: bigPtrType},
+}))
+var x3 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: ptrType},
+ {Name: "F2", Type: byteType},
+ {Name: "F3", Type: bigPtrType},
+}))
+var x4 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: ptrType},
+ {Name: "F2", Type: smallPtrType},
+ {Name: "F3", Type: bigPtrType},
+}))
+var x5 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: ptrType},
+ {Name: "F2", Type: mediumPtrType},
+ {Name: "F3", Type: bigPtrType},
+}))
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/a.go
new file mode 100644
index 0000000..3837e02
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/a.go
@@ -0,0 +1,19 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type I interface {
+ I2
+}
+type I2 interface {
+ M()
+}
+type S struct{}
+
+func (*S) M() {}
+
+func New() I {
+ return &S{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/b.go
new file mode 100644
index 0000000..272e520
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30659.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import (
+ "./a"
+)
+
+func B(p1 a.I, p2 a.I2) int {
+ return 42
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30659.go b/gcc/testsuite/go.test/test/fixedbugs/issue30659.go
new file mode 100644
index 0000000..973ae1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30659.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30679.go b/gcc/testsuite/go.test/test/fixedbugs/issue30679.go
new file mode 100644
index 0000000..4d0df18
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30679.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var f float64
+ var p, q *float64
+
+ p = &f
+ if *q > 0 {
+ p = q
+ }
+ _ = *p
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30709.go b/gcc/testsuite/go.test/test/fixedbugs/issue30709.go
new file mode 100644
index 0000000..4952454
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30709.go
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check closure in const declaration group can be compiled
+// and set correct value
+
+package main
+
+import "unsafe"
+
+const (
+ x = unsafe.Sizeof(func() {})
+ y
+)
+
+func main() {
+ const (
+ z = unsafe.Sizeof(func() {})
+ t
+ )
+
+ // x and y must be equal
+ println(x == y)
+ // size must be greater than zero
+ println(y > 0)
+
+ // Same logic as x, y above
+ println(z == t)
+ println(t > 0)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30709.out b/gcc/testsuite/go.test/test/fixedbugs/issue30709.out
new file mode 100644
index 0000000..1140ff5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30709.out
@@ -0,0 +1,4 @@
+true
+true
+true
+true
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/a.go
new file mode 100644
index 0000000..c23f4de
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var pl int
+
+type NoitfStruct struct {
+ F int
+ G int
+}
+
+//go:nointerface
+func (t *NoitfStruct) NoInterfaceMethod() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/b.go
new file mode 100644
index 0000000..3e501bb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/b.go
@@ -0,0 +1,29 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type EmbedImported struct {
+ a.NoitfStruct
+}
+
+func Test() []string {
+ bad := []string{}
+ x := interface{}(new(a.NoitfStruct))
+ if _, ok := x.(interface {
+ NoInterfaceMethod()
+ }); ok {
+ bad = append(bad, "fail 1")
+ }
+
+ x = interface{}(new(EmbedImported))
+ if _, ok := x.(interface {
+ NoInterfaceMethod()
+ }); ok {
+ bad = append(bad, "fail 2")
+ }
+ return bad
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/main.go
new file mode 100644
index 0000000..80db0e1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30862.dir/main.go
@@ -0,0 +1,28 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "./b"
+)
+
+// Test case for issue 30862.
+
+// Be aware that unless GOEXPERIMENT=fieldtrack is set when building
+// the compiler, this test will fail if executed with a regular GC
+// compiler.
+
+func main() {
+ bad := b.Test()
+ if len(bad) > 0 {
+ for _, s := range bad {
+ fmt.Fprintf(os.Stderr, "test failed: %s\n", s)
+ }
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30862.go b/gcc/testsuite/go.test/test/fixedbugs/issue30862.go
new file mode 100644
index 0000000..ba122cc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30862.go
@@ -0,0 +1,14 @@
+// rundir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 30862. This test as written will
+// fail for the main 'gc' compiler unless GOEXPERIMENT=fieldtrack
+// is set when building it, whereas gccgo has field tracking
+// enabled by default (hence the build tag below).
+
+// +build gccgo
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30898.go b/gcc/testsuite/go.test/test/fixedbugs/issue30898.go
new file mode 100644
index 0000000..b6376d3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30898.go
@@ -0,0 +1,19 @@
+// errorcheck -0 -m
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test escape analysis for functions with variadic arguments
+
+package foo
+
+func debugf(format string, args ...interface{}) { // ERROR "can inline debugf" "format does not escape" "args does not escape"
+ // Dummy implementation for non-debug build.
+ // A non-empty implementation would be enabled with a build tag.
+}
+
+func bar() { // ERROR "can inline bar"
+ value := 10
+ debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\[\]interface {}{...} does not escape"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/a.go
new file mode 100644
index 0000000..e1a5c0c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/a.go
@@ -0,0 +1,19 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type UUID string
+
+func New() UUID {
+ return Must(NewRandom())
+}
+
+func NewRandom() (UUID, error) {
+ return "", nil
+}
+
+func Must(uuid UUID, err error) UUID {
+ return uuid
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/b.go
new file mode 100644
index 0000000..f4f5fc4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30907.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "./a"
+
+func F() {
+ a.New()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30907.go b/gcc/testsuite/go.test/test/fixedbugs/issue30907.go
new file mode 100644
index 0000000..973ae1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30907.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30956.go b/gcc/testsuite/go.test/test/fixedbugs/issue30956.go
new file mode 100644
index 0000000..021e6c5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30956.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for compile generated static data for literal
+// composite struct
+
+package main
+
+import "fmt"
+
+type X struct {
+ V interface{}
+
+ a int
+ b int
+ c int
+}
+
+func pr(x X) {
+ fmt.Println(x.V)
+}
+
+func main() {
+ pr(X{
+ V: struct {
+ A int
+ }{42},
+ })
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30956.out b/gcc/testsuite/go.test/test/fixedbugs/issue30956.out
new file mode 100644
index 0000000..04f25e8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30956.out
@@ -0,0 +1 @@
+{42}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue30977.go b/gcc/testsuite/go.test/test/fixedbugs/issue30977.go
new file mode 100644
index 0000000..2ca040d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue30977.go
@@ -0,0 +1,52 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 30977: write barrier call clobbers volatile
+// value when there are multiple uses of the value.
+
+package main
+
+import "runtime"
+
+type T struct {
+ a, b, c, d, e string
+}
+
+//go:noinline
+func g() T {
+ return T{"a", "b", "c", "d", "e"}
+}
+
+//go:noinline
+func f() {
+ // The compiler optimizes this to direct copying
+ // the call result to both globals, with write
+ // barriers. The first write barrier call clobbers
+ // the result of g on stack.
+ X = g()
+ Y = X
+}
+
+var X, Y T
+
+const N = 1000
+
+func main() {
+ // Keep GC running so the write barrier is on.
+ go func() {
+ for {
+ runtime.GC()
+ }
+ }()
+
+ for i := 0; i < N; i++ {
+ runtime.Gosched()
+ f()
+ if X != Y {
+ panic("FAIL")
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31010.go b/gcc/testsuite/go.test/test/fixedbugs/issue31010.go
new file mode 100644
index 0000000..836e85f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31010.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var (
+ x int
+ xs []int
+)
+
+func a([]int) (int, error)
+
+func b() (int, error) {
+ return a(append(xs, x))
+}
+
+func c(int, error) (int, error)
+
+func d() (int, error) {
+ return c(b())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31060.go b/gcc/testsuite/go.test/test/fixedbugs/issue31060.go
new file mode 100644
index 0000000..a1ba705
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31060.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+const (
+ f = 1.0
+ c = 1.0i
+
+ _ = ^f // ERROR "invalid operation|expected integer"
+ _ = ^c // ERROR "invalid operation|expected integer"
+
+ _ = f % f // ERROR "invalid operation|expected integer"
+ _ = c % c // ERROR "invalid operation|expected integer"
+
+ _ = f & f // ERROR "invalid operation|expected integer"
+ _ = c & c // ERROR "invalid operation|expected integer"
+
+ _ = f | f // ERROR "invalid operation|expected integer"
+ _ = c | c // ERROR "invalid operation|expected integer"
+
+ _ = f ^ f // ERROR "invalid operation|expected integer"
+ _ = c ^ c // ERROR "invalid operation|expected integer"
+
+ _ = f &^ f // ERROR "invalid operation|expected integer"
+ _ = c &^ c // ERROR "invalid operation|expected integer"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/a.go
new file mode 100644
index 0000000..fa43150
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "fmt"
+
+type IndexController struct{}
+
+func (this *IndexController) Index(m *string) {
+ fmt.Println(m)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/b.go
new file mode 100644
index 0000000..9bfc0ff
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "fmt"
+
+type IndexController struct{}
+
+func (this *IndexController) Index(m *string) {
+ fmt.Println(m)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/c.go
new file mode 100644
index 0000000..928c8ee
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/c.go
@@ -0,0 +1,26 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import (
+ "a"
+ "b"
+)
+
+type HandlerFunc func(*string)
+
+func RouterInit() {
+ //home API
+ homeIndex := &a.IndexController{}
+ GET("/home/index/index", homeIndex.Index)
+ //admin API
+ adminIndex := &b.IndexController{}
+ GET("/admin/index/index", adminIndex.Index)
+ return
+}
+
+func GET(path string, handlers ...HandlerFunc) {
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/main.go
new file mode 100644
index 0000000..25a7548
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31252.dir/main.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "c"
+
+func main() {
+ c.RouterInit()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31252.go b/gcc/testsuite/go.test/test/fixedbugs/issue31252.go
new file mode 100644
index 0000000..973ae1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31252.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31412a.go b/gcc/testsuite/go.test/test/fixedbugs/issue31412a.go
new file mode 100644
index 0000000..75021c6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31412a.go
@@ -0,0 +1,32 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was incorrectly flagged as erroneous by gccgo.
+
+package main
+
+type Name string
+
+type EFunc func(int) int
+
+func Register(f EFunc, names ...Name) int {
+ return f(len(names))
+}
+
+const (
+ B Name = "B"
+)
+
+func RegisterIt() {
+ n := B + "Duck"
+ d := B + "Goose"
+ f := func(x int) int { return x + 9 }
+ Register(f, n, d)
+}
+
+func main() {
+ RegisterIt()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31412b.go b/gcc/testsuite/go.test/test/fixedbugs/issue31412b.go
new file mode 100644
index 0000000..6c4ec00
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31412b.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was incorrectly accepted by gccgo.
+
+package main
+
+type N string
+type M string
+
+const B N = "B"
+const C M = "C"
+
+func main() {
+ q := B + C // ERROR "mismatched types|incompatible types"
+ println(q)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31419.go b/gcc/testsuite/go.test/test/fixedbugs/issue31419.go
new file mode 100644
index 0000000..233111a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31419.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 31419: race in getitab when two goroutines try
+// to do the same failed interface conversion.
+
+package main
+
+type T int
+
+func (t T) M() {}
+
+type I interface {
+ M()
+ M2()
+}
+
+var t T
+var e interface{} = &t
+var ok = false
+var ch = make(chan int)
+
+func main() {
+ _, ok = e.(I) // populate itab cache with a false result
+
+ go f() // get itab in a loop
+
+ var i I
+ for k := 0; k < 10000; k++ {
+ i, ok = e.(I) // read the cached itab
+ if ok {
+ println("iteration", k, "i =", i, "&t =", &t)
+ panic("conversion succeeded")
+ }
+ }
+ <-ch
+}
+
+func f() {
+ for i := 0; i < 10000; i++ {
+ f1()
+ }
+ ch <- 1
+}
+
+func f1() {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ }()
+ i := e.(I) // triggers itab.init, for getting the panic string
+ _ = i
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31573.go b/gcc/testsuite/go.test/test/fixedbugs/issue31573.go
new file mode 100644
index 0000000..005910e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31573.go
@@ -0,0 +1,49 @@
+// errorcheck -0 -m
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(...*int) {} // ERROR "can inline f$"
+
+func g() {
+ defer f()
+ defer f(new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
+ defer f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
+
+ defer f(nil...)
+ defer f([]*int{}...) // ERROR "\[\]\*int{} does not escape$"
+ defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
+ defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$"
+
+ go f()
+ go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+ go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+
+ go f(nil...)
+ go f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$"
+ go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$"
+ go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$"
+
+ for {
+ defer f()
+ defer f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+ defer f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+
+ defer f(nil...)
+ defer f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$"
+ defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$"
+ defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$"
+
+ go f()
+ go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+ go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+
+ go f(nil...)
+ go f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$"
+ go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$"
+ go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/a.go
new file mode 100644
index 0000000..71f3926
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type dO struct {
+ x int
+}
+
+type EDO struct{}
+
+func (EDO) Apply(*dO) {}
+
+var X EDO
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/b.go
new file mode 100644
index 0000000..ce83b00
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31637.dir/b.go
@@ -0,0 +1,19 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+type No struct {
+ a.EDO
+}
+
+func X() No {
+ return No{}
+}
+
+func main() {
+ X()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31637.go b/gcc/testsuite/go.test/test/fixedbugs/issue31637.go
new file mode 100644
index 0000000..dcfb4a7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31637.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This directory contains a pair of packages that triggered
+// a compiler crash in gollvm (problem in handling an inlinable
+// method with unnamed parameter). See issue 31637 for details.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31777.go b/gcc/testsuite/go.test/test/fixedbugs/issue31777.go
new file mode 100644
index 0000000..839e242
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31777.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Compile with static map literal.
+
+package p
+
+type i interface {
+ j()
+}
+
+type s struct{}
+
+func (s) j() {}
+
+type foo map[string]i
+
+var f = foo{
+ "1": s{},
+ "2": s{},
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31782.go b/gcc/testsuite/go.test/test/fixedbugs/issue31782.go
new file mode 100644
index 0000000..a42001e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31782.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check static composite literal reports wrong for struct
+// field.
+
+package main
+
+type one struct {
+ i interface{}
+}
+
+type two struct {
+ i interface{}
+ s []string
+}
+
+func main() {
+ o := one{i: two{i: 42}.i}
+ println(o.i.(int))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31782.out b/gcc/testsuite/go.test/test/fixedbugs/issue31782.out
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31782.out
@@ -0,0 +1 @@
+42
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue31987.go b/gcc/testsuite/go.test/test/fixedbugs/issue31987.go
new file mode 100644
index 0000000..372289b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue31987.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+type container struct {
+ Value string
+}
+
+func main() {
+ s := []container{
+ 7: {Value: "string value"},
+ }
+ if s[7].Value != "string value" {
+ panic(fmt.Errorf("wanted \"string value\", got \"%s\"", s[7].Value))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32175.go b/gcc/testsuite/go.test/test/fixedbugs/issue32175.go
new file mode 100644
index 0000000..a677351
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32175.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// This used to print 0, because x was incorrectly captured by value.
+
+func f() (x int) {
+ defer func() func() {
+ return func() {
+ println(x)
+ }
+ }()()
+ return 42
+}
+
+func main() {
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32175.out b/gcc/testsuite/go.test/test/fixedbugs/issue32175.out
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32175.out
@@ -0,0 +1 @@
+42
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32288.go b/gcc/testsuite/go.test/test/fixedbugs/issue32288.go
new file mode 100644
index 0000000..91c930c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32288.go
@@ -0,0 +1,48 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T struct {
+ s [1]string
+ pad [16]uintptr
+}
+
+//go:noinline
+func f(t *int, p *int) []T {
+ var res []T
+ for {
+ var e *T
+ res = append(res, *e)
+ }
+}
+
+func main() {
+ defer func() {
+ useStack(100) // force a stack copy
+ // We're expecting a panic.
+ // The bug in this issue causes a throw, which this recover() will not squash.
+ recover()
+ }()
+ junk() // fill the stack with invalid pointers
+ f(nil, nil)
+}
+
+func useStack(n int) {
+ if n == 0 {
+ return
+ }
+ useStack(n - 1)
+}
+
+//go:noinline
+func junk() uintptr {
+ var a [128]uintptr // 1k of bad pointers on the stack
+ for i := range a {
+ a[i] = 0xaa
+ }
+ return a[12]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32347.go b/gcc/testsuite/go.test/test/fixedbugs/issue32347.go
new file mode 100644
index 0000000..91c038a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32347.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 32347: gccgo compiler crashes with int-to-string conversion
+// with large integer constant operand.
+
+package p
+
+const (
+ X1 = string(128049)
+ X2 = string(-1)
+ X3 = string(1<<48)
+)
+
+var S1, S2, S3 = X1, X2, X3
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32454.go b/gcc/testsuite/go.test/test/fixedbugs/issue32454.go
new file mode 100644
index 0000000..70895c9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32454.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct {
+ s string
+ f float64
+}
+
+func f() {
+ var f float64
+ var st T
+ for {
+ switch &st.f {
+ case &f:
+ f = 1
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32560.go b/gcc/testsuite/go.test/test/fixedbugs/issue32560.go
new file mode 100644
index 0000000..c6f72b6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32560.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Values smaller than 64-bits were mistakenly always proven to be
+// non-negative.
+//
+// The tests here are marked go:noinline to ensure they're
+// independently optimized by SSA.
+
+package main
+
+var x int32 = -1
+
+//go:noinline
+func a() {
+ if x != -1 {
+ panic(1)
+ }
+ if x > 0 || x != -1 {
+ panic(2)
+ }
+}
+
+//go:noinline
+func b() {
+ if x != -1 {
+ panic(3)
+ }
+ if x > 0 {
+ panic(4)
+ }
+}
+
+//go:noinline
+func c() {
+ if x > 0 || x != -1 {
+ panic(5)
+ }
+ if x > 0 || x != -1 {
+ panic(6)
+ }
+}
+
+func main() {
+ a()
+ b()
+ c()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/a.go
new file mode 100644
index 0000000..8342dd5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func A() {
+ defer func() {}()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/b.go
new file mode 100644
index 0000000..9a13a57
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "reflect"
+
+func B() {
+ t1 := reflect.TypeOf([0]byte{})
+ t2 := reflect.TypeOf(new([0]byte)).Elem()
+ if t1 != t2 {
+ panic("[0]byte types do not match")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/main.go
new file mode 100644
index 0000000..20472cd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32595.dir/main.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "a"
+ "b"
+)
+
+func main() {
+ a.A()
+ b.B()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32595.go b/gcc/testsuite/go.test/test/fixedbugs/issue32595.go
new file mode 100644
index 0000000..af6f134
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32595.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32680.go b/gcc/testsuite/go.test/test/fixedbugs/issue32680.go
new file mode 100644
index 0000000..27cba6b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32680.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=ssa/check/on
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// As of 2019-06, bug affects/ed amd64 and s390x.
+
+package main
+
+var foo = []byte{105, 57, 172, 152}
+
+func main() {
+ for i := 0; i < len(foo); i += 4 {
+ // Requires inlining and non-constant i
+ // Note the bug/fix also apply to different widths, but was unable to reproduce for those.
+ println(readLittleEndian32_2(foo[i], foo[i+1], foo[i+2], foo[i+3]))
+ }
+}
+
+func readLittleEndian32_2(a, b, c, d byte) uint32 {
+ return uint32(a) | (uint32(b) << 8) | (uint32(c) << 16) | (uint32(d) << 24)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32680.out b/gcc/testsuite/go.test/test/fixedbugs/issue32680.out
new file mode 100644
index 0000000..4d60a97
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32680.out
@@ -0,0 +1 @@
+2561423721
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32680b.go b/gcc/testsuite/go.test/test/fixedbugs/issue32680b.go
new file mode 100644
index 0000000..61e5317
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32680b.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func hashBytesRaw(b0, b1, b2, b3, b7 byte) uint64 {
+ return (uint64(b0) | uint64(b1)<<8 | uint64(b2)<<16 | uint64(b3)<<24)
+}
+
+func doStuff(data []byte) uint64 {
+ return hashBytesRaw(data[0], data[1], data[2], data[3], data[7])
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32723.go b/gcc/testsuite/go.test/test/fixedbugs/issue32723.go
new file mode 100644
index 0000000..850334d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32723.go
@@ -0,0 +1,22 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Complex literal comparison
+
+package p
+
+const x = 1i
+const y = 1i < 2i // ERROR "invalid operation: .*not defined on untyped complex|non-ordered type"
+const z = x < 2i // ERROR "invalid operation: .*not defined on untyped complex|non-ordered type"
+
+func f() {
+ _ = 1i < 2i // ERROR "invalid operation: .*not defined on untyped complex|non-ordered type"
+ _ = 1i < 2 // ERROR "invalid operation: .*not defined on untyped complex|non-ordered type"
+ _ = 1 < 2i // ERROR "invalid operation: .*not defined on untyped complex|non-ordered type"
+
+ c := 1i
+ _ = c < 2i // ERROR "invalid operation: .*not defined on complex128|non-ordered type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/a.go
new file mode 100644
index 0000000..1e6ac01
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/a.go
@@ -0,0 +1,18 @@
+// Copyright 2019 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package a
+
+import "strings"
+
+type Name string
+
+type FullName string
+
+func (n FullName) Name() Name {
+ if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
+ return Name(n[i+1:])
+ }
+ return Name(n)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/b.go
new file mode 100644
index 0000000..a0ee398
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32778.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package b
+
+import "./a"
+
+func Expo(fn a.FullName) a.Name {
+ return fn.Name()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32778.go b/gcc/testsuite/go.test/test/fixedbugs/issue32778.go
new file mode 100644
index 0000000..83456d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32778.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+// This directory contains a pair of packages that triggers a compiler
+// crash in gccgo (problem with tracking indirectly referenced
+// packages during exporting). See issue 32778 for details.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/a.go
new file mode 100644
index 0000000..54ed771
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T struct { x int }
+
+func F() interface{} {
+ return [2]T{}
+}
+
+func P() interface{} {
+ return &[2]T{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/b.go
new file mode 100644
index 0000000..932d7b0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func F() interface{} {
+ return a.F()
+}
+
+func P() interface{} {
+ return a.P()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/c.go
new file mode 100644
index 0000000..5f31c7f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/c.go
@@ -0,0 +1,17 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import "./b"
+
+func F() interface{} {
+ go func(){}() // make it non-inlineable
+ return b.F()
+}
+
+func P() interface{} {
+ go func(){}() // make it non-inlineable
+ return b.P()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/main.go
new file mode 100644
index 0000000..28bb8cd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32901.dir/main.go
@@ -0,0 +1,18 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./c"
+import "reflect"
+
+func main() {
+ x := c.F()
+ p := c.P()
+ t := reflect.PtrTo(reflect.TypeOf(x))
+ tp := reflect.TypeOf(p)
+ if t != tp {
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32901.go b/gcc/testsuite/go.test/test/fixedbugs/issue32901.go
new file mode 100644
index 0000000..004c3da
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32901.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 32901: type descriptor equality bug in gccgo.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/a.go
new file mode 100644
index 0000000..b13c4b4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/a.go
@@ -0,0 +1,18 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func A() int {
+ return p("count")
+}
+
+func p(which string, args ...string) int {
+ switch which {
+ case "count", "something":
+ return 1
+ default:
+ return 2
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/b.go
new file mode 100644
index 0000000..fdaf42d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32922.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func B() int {
+ return 99 + a.A()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32922.go b/gcc/testsuite/go.test/test/fixedbugs/issue32922.go
new file mode 100644
index 0000000..005c8e6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32922.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This directory contains a pair of packages that triggers a compiler
+// error in gccgo (problem with the way inlinable call expressions are
+// imported). See issue 32922 for details.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue32959.go b/gcc/testsuite/go.test/test/fixedbugs/issue32959.go
new file mode 100644
index 0000000..a0dc789
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue32959.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test escape analysis with shifting constant
+
+package main
+
+import "unsafe"
+
+func main() {
+ var l uint64
+ var p unsafe.Pointer
+ _ = unsafe.Pointer(uintptr(p) + (uintptr(l) >> 1))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/a.go
new file mode 100644
index 0000000..056be88
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type G interface {
+ UsesEmpty(p interface{}) int
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/b.go
new file mode 100644
index 0000000..5694b58
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/b.go
@@ -0,0 +1,24 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+type Service uint64
+type ServiceDesc struct {
+ X int
+ uc
+}
+
+type uc interface {
+ f() a.G
+}
+
+var q int
+
+func RS(svcd *ServiceDesc, server interface{}, qq uint8) *Service {
+ defer func() { q += int(qq) }()
+ return nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/c.go
new file mode 100644
index 0000000..bfdc0b5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/c.go
@@ -0,0 +1,19 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import (
+ "a"
+ "b"
+)
+
+type BI interface {
+ Something(s int64) int64
+ Another(pxp a.G) int32
+}
+
+func BRS(sd *b.ServiceDesc, server BI, xyz int) *b.Service {
+ return b.RS(sd, server, 7)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/d.go b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/d.go
new file mode 100644
index 0000000..f4fff4a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33013.dir/d.go
@@ -0,0 +1,16 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package d
+
+import (
+ "b"
+ "c"
+)
+
+var GA b.Service
+
+func C() {
+ c.BRS(nil, nil, 22)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33013.go b/gcc/testsuite/go.test/test/fixedbugs/issue33013.go
new file mode 100644
index 0000000..e363cf5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33013.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33013: gccgo compiler error with inlinable function
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/a.go
new file mode 100644
index 0000000..948f4fd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/a.go
@@ -0,0 +1,16 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var G1 int
+var G2 int
+var G3 int
+var G4 int
+var G5 int
+var G6 int
+var G7 int
+var G8 int
+var G9 int
+var G10 int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/b.go
new file mode 100644
index 0000000..354ab3e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33020.dir/b.go
@@ -0,0 +1,22 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+var N n
+
+type n struct{}
+
+func (r n) M1() int { return a.G1 }
+func (r n) M2() int { return a.G2 }
+func (r n) M3() int { return a.G3 }
+func (r n) M4() int { return a.G4 }
+func (r n) M5() int { return a.G5 }
+func (r n) M6() int { return a.G6 }
+func (r n) M7() int { return a.G7 }
+func (r n) M8() int { return a.G8 }
+func (r n) M9() int { return a.G9 }
+func (r n) M10() int { return a.G10 }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33020.go b/gcc/testsuite/go.test/test/fixedbugs/issue33020.go
new file mode 100644
index 0000000..ccdf187
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33020.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33020: gccgo undefined behavior with inlinable function
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/a.go
new file mode 100644
index 0000000..9176498
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type FArg func(args []string) error
+
+type Command struct {
+ Name string
+ Arg1 FArg
+ Arg2 func(args []string) error
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/b.go
new file mode 100644
index 0000000..5b0f9d8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33020a.dir/b.go
@@ -0,0 +1,14 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+var Cmd = &a.Command{
+ Name: "test",
+}
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33020a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33020a.go
new file mode 100644
index 0000000..cfe010e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33020a.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33020: gollvm assert in Llvm_backend::materializeComposite
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33062.go b/gcc/testsuite/go.test/test/fixedbugs/issue33062.go
new file mode 100644
index 0000000..5e6a358
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33062.go
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33062: gccgo generates incorrect type equality
+// functions.
+
+package main
+
+type simpleStruct struct {
+ int
+ string
+}
+
+type complexStruct struct {
+ int
+ simpleStruct
+}
+
+func main() {
+ x := complexStruct{1, simpleStruct{2, "xxx"}}
+ ix := interface{}(x)
+ y := complexStruct{1, simpleStruct{2, "yyy"}}
+ iy := interface{}(y)
+ if ix != ix {
+ panic("FAIL")
+ }
+ if ix == iy {
+ panic("FAIL")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/a.go
new file mode 100644
index 0000000..28714e0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/a.go
@@ -0,0 +1,25 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var GS string
+
+func M() string {
+ if s := getname("Fred"); s != "" {
+ return s
+ }
+ if s := getname("Joe"); s != "" {
+ return s
+ }
+
+ return string("Alex")
+}
+
+// getname can be any function returning a string, just has to be non-inlinable.
+
+//go:noinline
+func getname(s string) string {
+ return s + "foo"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/b.go
new file mode 100644
index 0000000..a16f0da
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33158.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+func B() string {
+ return a.M()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33158.go b/gcc/testsuite/go.test/test/fixedbugs/issue33158.go
new file mode 100644
index 0000000..1bba8f2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33158.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33158: gccgo duplicate def error from importing inlinable function
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/a.go
new file mode 100644
index 0000000..2d96301
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/a.go
@@ -0,0 +1,17 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type A interface {
+ M(i interface{}) interface{}
+}
+
+var a1 A
+var a2 A
+
+func V(p A, k, v interface{}) A {
+ defer func() { a1, a2 = a2, a1 }()
+ return a1
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/b.go
new file mode 100644
index 0000000..2a8f518
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/b.go
@@ -0,0 +1,25 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type Service uint64
+
+var q *Service
+var r *Service
+
+type f struct{}
+
+var fk f
+
+func No(s a.A, qq uint8) *Service {
+ defer func() { q, r = r, q }()
+ return q
+}
+
+func Yes(s a.A, p *uint64) a.A {
+ return a.V(s, fk, p)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/c.go b/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/c.go
new file mode 100644
index 0000000..ece48d7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33219.dir/c.go
@@ -0,0 +1,20 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import (
+ "a"
+ "b"
+)
+
+type BI interface {
+ Another(pxp a.A) int32
+}
+
+//go:noinline
+func BRS(sd a.A, xyz int) *b.Service {
+ x := b.Yes(sd, nil)
+ return b.No(x, 1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33219.go b/gcc/testsuite/go.test/test/fixedbugs/issue33219.go
new file mode 100644
index 0000000..45edc8b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33219.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33219: gccgo assert in "implements_interface()"
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33275.go b/gcc/testsuite/go.test/test/fixedbugs/issue33275.go
new file mode 100644
index 0000000..f2ec24d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33275.go
@@ -0,0 +1,34 @@
+// skip
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "time"
+)
+
+func main() {
+ // Make a big map.
+ m := map[int]int{}
+ for i := 0; i < 100000; i++ {
+ m[i] = i
+ }
+ c := make(chan string)
+ go func() {
+ // Print the map.
+ s := fmt.Sprintln(m)
+ c <- s
+ }()
+ go func() {
+ time.Sleep(1 * time.Millisecond)
+ // Add an extra item to the map while iterating.
+ m[-1] = -1
+ c <- ""
+ }()
+ <-c
+ <-c
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33275_run.go b/gcc/testsuite/go.test/test/fixedbugs/issue33275_run.go
new file mode 100644
index 0000000..ed03dcc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33275_run.go
@@ -0,0 +1,25 @@
+// +build !nacl,!js,!gccgo
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure we don't get an index out of bounds error
+// while trying to print a map that is concurrently modified.
+// The runtime might complain (throw) if it detects the modification,
+// so we have to run the test as a subprocess.
+
+package main
+
+import (
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ out, _ := exec.Command("go", "run", "fixedbugs/issue33275.go").CombinedOutput()
+ if strings.Contains(string(out), "index out of range") {
+ panic(`go run issue33275.go reported "index out of range"`)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33308.go b/gcc/testsuite/go.test/test/fixedbugs/issue33308.go
new file mode 100644
index 0000000..5821099
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33308.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+// Test that the compiler does not crash on a []byte conversion of an
+// untyped expression.
+package p
+
+var v uint
+var x = []byte((1 << v) + 1) // ERROR "cannot convert|non-integer type for left operand of shift"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33355.go b/gcc/testsuite/go.test/test/fixedbugs/issue33355.go
new file mode 100644
index 0000000..c4b1e2e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33355.go
@@ -0,0 +1,147 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code failed on arm64 in the register allocator.
+// See issue 33355.
+
+package server
+
+import (
+ "bytes"
+ "sync"
+)
+
+type client struct {
+ junk [4]int
+ mu sync.Mutex
+ srv *Server
+ gw *gateway
+ msgb [100]byte
+}
+
+type gateway struct {
+ cfg *gatewayCfg
+ outsim *sync.Map
+}
+
+type gatewayCfg struct {
+ replyPfx []byte
+}
+
+type Account struct {
+ Name string
+}
+
+type Server struct {
+ gateway *srvGateway
+}
+
+type srvGateway struct {
+ outo []*client
+}
+
+type subscription struct {
+ queue []byte
+ client *client
+}
+
+type outsie struct {
+ ni map[string]struct{}
+ sl *Sublist
+ qsubs int
+}
+
+type Sublist struct {
+}
+
+type SublistResult struct {
+ psubs []*subscription
+ qsubs [][]*subscription
+}
+
+var subPool = &sync.Pool{}
+
+func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgroups [][]byte) {
+ var gws []*client
+ gw := c.srv.gateway
+ for i := 0; i < len(gw.outo); i++ {
+ gws = append(gws, gw.outo[i])
+ }
+ var (
+ subj = string(subject)
+ queuesa = [512]byte{}
+ queues = queuesa[:0]
+ mreply []byte
+ dstPfx []byte
+ checkReply = len(reply) > 0
+ )
+
+ sub := subPool.Get().(*subscription)
+
+ if subjectStartsWithGatewayReplyPrefix(subject) {
+ dstPfx = subject[:8]
+ }
+ for i := 0; i < len(gws); i++ {
+ gwc := gws[i]
+ if dstPfx != nil {
+ gwc.mu.Lock()
+ ok := bytes.Equal(dstPfx, gwc.gw.cfg.replyPfx)
+ gwc.mu.Unlock()
+ if !ok {
+ continue
+ }
+ } else {
+ qr := gwc.gatewayInterest(acc.Name, subj)
+ queues = queuesa[:0]
+ for i := 0; i < len(qr.qsubs); i++ {
+ qsubs := qr.qsubs[i]
+ queue := qsubs[0].queue
+ add := true
+ for _, qn := range qgroups {
+ if bytes.Equal(queue, qn) {
+ add = false
+ break
+ }
+ }
+ if add {
+ qgroups = append(qgroups, queue)
+ }
+ }
+ if len(queues) == 0 {
+ continue
+ }
+ }
+ if checkReply {
+ checkReply = false
+ mreply = reply
+ }
+ mh := c.msgb[:10]
+ mh = append(mh, subject...)
+ if len(queues) > 0 {
+ mh = append(mh, mreply...)
+ mh = append(mh, queues...)
+ }
+ sub.client = gwc
+ }
+ subPool.Put(sub)
+}
+
+func subjectStartsWithGatewayReplyPrefix(subj []byte) bool {
+ return len(subj) > 8 && string(subj[:4]) == "foob"
+}
+
+func (c *client) gatewayInterest(acc, subj string) *SublistResult {
+ ei, _ := c.gw.outsim.Load(acc)
+ var r *SublistResult
+ e := ei.(*outsie)
+ r = e.sl.Match(subj)
+ return r
+}
+
+func (s *Sublist) Match(subject string) *SublistResult {
+ return nil
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33386.go b/gcc/testsuite/go.test/test/fixedbugs/issue33386.go
new file mode 100644
index 0000000..7b2f565
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33386.go
@@ -0,0 +1,29 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we don't get spurious follow-on errors
+// after a missing expression. Specifically, the parser
+// shouldn't skip over closing parentheses of any kind.
+
+package p
+
+func _() {
+ go func() { // no error here about goroutine
+ send <- // GCCGO_ERROR "undefined name"
+ }() // ERROR "expecting expression|expected operand"
+}
+
+func _() {
+ defer func() { // no error here about deferred function
+ 1 + // GCCGO_ERROR "value computed is not used"
+ }() // ERROR "expecting expression|expected operand"
+}
+
+func _() {
+ _ = (1 +) // ERROR "expecting expression|expected operand"
+ _ = a[2 +] // ERROR "expecting expression|expected operand|undefined name"
+ _ = []int{1, 2, 3 + } // ERROR "expecting expression|expected operand"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33438.go b/gcc/testsuite/go.test/test/fixedbugs/issue33438.go
new file mode 100644
index 0000000..e4206d7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33438.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type hasPtrs struct {
+ x [2]*int
+ // Note: array size needs to be >1 to force this type to be not SSAable.
+ // The bug triggers only for OpMove, which is only used for unSSAable types.
+}
+
+func main() {
+ var x *hasPtrs // Can be local, global, or arg; nil or non-nil.
+ var y *hasPtrs = nil // Must initialize to nil.
+ *x = *y
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33460.go b/gcc/testsuite/go.test/test/fixedbugs/issue33460.go
new file mode 100644
index 0000000..d90b0a4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33460.go
@@ -0,0 +1,37 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+const (
+ zero = iota
+ one
+ two
+ three
+)
+
+const iii int = 0x3
+
+func f(v int) {
+ switch v {
+ case zero, one:
+ case two, one: // ERROR "previous case at LINE-1|duplicate case in switch"
+
+ case three:
+ case 3: // ERROR "previous case at LINE-1|duplicate case in switch"
+ case iii: // ERROR "previous case at LINE-2|duplicate case in switch"
+ }
+}
+
+const b = "b"
+
+var _ = map[string]int{
+ "a": 0,
+ b: 1,
+ "a": 2, // ERROR "previous key at LINE-2|duplicate key in map literal"
+ "b": 3, // GC_ERROR "previous key at LINE-2"
+ "b": 4, // GC_ERROR "previous key at LINE-3"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33555.go b/gcc/testsuite/go.test/test/fixedbugs/issue33555.go
new file mode 100644
index 0000000..c1fcd2a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33555.go
@@ -0,0 +1,81 @@
+// +build !nacl,!js,!gccgo
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that the linker permits long call sequences.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+)
+
+const start = `
+package main
+
+func main() {
+ println(f0() + 1)
+}
+`
+
+const fn = `
+//go:noinline
+func f%d() int {
+ return f%d() + 1
+}`
+
+const fnlast = `
+//go:noinline
+func f%d() int {
+ return 0
+}
+`
+
+const count = 400
+
+func main() {
+ if err := test(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func test() error {
+ var buf bytes.Buffer
+ buf.WriteString(start)
+ for i := 0; i < count; i++ {
+ fmt.Fprintf(&buf, fn, i, i + 1)
+ }
+ fmt.Fprintf(&buf, fnlast, count)
+
+ dir, err := ioutil.TempDir("", "issue33555")
+ if err != nil {
+ return err
+ }
+ defer os.RemoveAll(dir)
+
+ fn := filepath.Join(dir, "x.go")
+ if err := ioutil.WriteFile(fn, buf.Bytes(), 0644); err != nil {
+ return err
+ }
+
+ out, err := exec.Command("go", "run", fn).CombinedOutput()
+ if err != nil {
+ return err
+ }
+
+ want := strconv.Itoa(count + 1)
+ if got := string(bytes.TrimSpace(out)); got != want {
+ return fmt.Errorf("got %q want %q", got, want)
+ }
+
+ return nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33724.go b/gcc/testsuite/go.test/test/fixedbugs/issue33724.go
new file mode 100644
index 0000000..a4ecddc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33724.go
@@ -0,0 +1,45 @@
+// run
+package main
+
+import (
+ "fmt"
+ "runtime/debug"
+ "strings"
+)
+
+type Inner struct {
+ Err int
+}
+
+func (i *Inner) NotExpectedInStackTrace() int {
+ if i == nil {
+ return 86
+ }
+ return 17 + i.Err
+}
+
+type Outer struct {
+ Inner
+}
+
+func ExpectedInStackTrace() {
+ var o *Outer
+ println(o.NotExpectedInStackTrace())
+}
+
+func main() {
+ defer func() {
+ if r := recover(); r != nil {
+ stacktrace := string(debug.Stack())
+ if strings.Contains(stacktrace, "NotExpectedInStackTrace") {
+ fmt.Println("FAIL, stacktrace contains NotExpectedInStackTrace")
+ }
+ if !strings.Contains(stacktrace, "ExpectedInStackTrace") {
+ fmt.Println("FAIL, stacktrace does not contain ExpectedInStackTrace")
+ }
+ } else {
+ fmt.Println("FAIL, should have panicked but did not")
+ }
+ }()
+ ExpectedInStackTrace()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/a.go
new file mode 100644
index 0000000..7eb5b92
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func F() func() {
+ return f
+}
+
+func f() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/b.go
new file mode 100644
index 0000000..caca1ec
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33739.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "a"
+
+func main() {
+ a.F()()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33739.go b/gcc/testsuite/go.test/test/fixedbugs/issue33739.go
new file mode 100644
index 0000000..b770782
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33739.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33739: gccgo undefined symbol with cross-package inlining
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/a.go
new file mode 100644
index 0000000..9c782c5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/a.go
@@ -0,0 +1,18 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Builder struct {
+ x int
+}
+
+func (tb Builder) Build() (out struct {
+ x interface{}
+ s string
+}) {
+ out.x = nil
+ out.s = "hello!"
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/b.go
new file mode 100644
index 0000000..aa2a322
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33866.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type (
+ ABuilder = a.Builder
+)
+
+func Bfunc() ABuilder {
+ return ABuilder{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33866.go b/gcc/testsuite/go.test/test/fixedbugs/issue33866.go
new file mode 100644
index 0000000..220c732
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33866.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 33866: assert in gccgo during compilation
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue33903.go b/gcc/testsuite/go.test/test/fixedbugs/issue33903.go
new file mode 100644
index 0000000..de03282
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue33903.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that the shortcircuit pass correctly handles infinite loops.
+
+package p
+
+func f() {
+ var p, q bool
+ for {
+ p = p && q
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34123.go b/gcc/testsuite/go.test/test/fixedbugs/issue34123.go
new file mode 100644
index 0000000..f50cd02
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34123.go
@@ -0,0 +1,43 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that the line number is reported correctly
+// for faulting instructions.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+var x byte
+var p *byte
+
+//go:noinline
+func f() {
+ q := p
+ x = 11 // line 23
+ *q = 12 // line 24
+}
+func main() {
+ defer func() {
+ recover()
+ var pcs [10]uintptr
+ n := runtime.Callers(1, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+ for {
+ f, more := frames.Next()
+ if f.Function == "main.f" && f.Line != 24 {
+ panic(fmt.Errorf("expected line 24, got line %d", f.Line))
+ }
+ if !more {
+ break
+ }
+ }
+ }()
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34395.go b/gcc/testsuite/go.test/test/fixedbugs/issue34395.go
new file mode 100644
index 0000000..eb5a855
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34395.go
@@ -0,0 +1,17 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that a binary with a large data section can load. This failed on wasm.
+
+package main
+
+var test = [100 * 1024 * 1024]byte{42}
+
+func main() {
+ if test[0] != 42 {
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/a.go
new file mode 100644
index 0000000..2c14913
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import "unsafe"
+
+type HookFunc func(x uint64)
+
+var HookV unsafe.Pointer
+
+func Hook(x uint64) {
+ (*(*HookFunc)(HookV))(x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/b.go
new file mode 100644
index 0000000..21bdfcc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34503.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+func Bfunc() {
+ a.Hook(101)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34503.go b/gcc/testsuite/go.test/test/fixedbugs/issue34503.go
new file mode 100644
index 0000000..d843df7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34503.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 34503: gccgo compiler error importing inlinable function
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34520.go b/gcc/testsuite/go.test/test/fixedbugs/issue34520.go
new file mode 100644
index 0000000..d92d4cc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34520.go
@@ -0,0 +1,12 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ for true {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/a.go
new file mode 100644
index 0000000..b6af555
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/a.go
@@ -0,0 +1,27 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type A struct {
+ x int
+}
+
+type AI interface {
+ bar()
+}
+
+type AC int
+
+func (ab AC) bar() {
+}
+
+const (
+ ACC = AC(101)
+)
+
+//go:noinline
+func W(a A, k, v interface{}) A {
+ return A{3}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/b.go
new file mode 100644
index 0000000..bbcd1af
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34577.dir/b.go
@@ -0,0 +1,23 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+type B struct {
+ s string
+}
+
+func (b B) Func(x a.A) a.A {
+ return a.W(x, k, b)
+}
+
+type ktype int
+
+const k ktype = 0
+
+func Func2() a.AI {
+ return a.ACC
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34577.go b/gcc/testsuite/go.test/test/fixedbugs/issue34577.go
new file mode 100644
index 0000000..b4caaeb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34577.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 34577: gccgo compiler error emitting export data
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue34968.go b/gcc/testsuite/go.test/test/fixedbugs/issue34968.go
new file mode 100644
index 0000000..6b1dbd1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue34968.go
@@ -0,0 +1,15 @@
+// +build cgo
+// run -gcflags=all=-d=checkptr
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// #include <stdlib.h>
+import "C"
+
+func main() {
+ C.malloc(100)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35027.go b/gcc/testsuite/go.test/test/fixedbugs/issue35027.go
new file mode 100644
index 0000000..d4b0be5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35027.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=checkptr
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+var s []int
+
+func main() {
+ s = []int{42}
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+ x := *(*int)(unsafe.Pointer(h.Data))
+ if x != 42 {
+ panic(x)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35073.go b/gcc/testsuite/go.test/test/fixedbugs/issue35073.go
new file mode 100644
index 0000000..dc8ce3a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35073.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=checkptr
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that reflect.Value.UnsafeAddr/Pointer is handled
+// correctly by -d=checkptr
+
+package main
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func main() {
+ n := 10
+ m := make(map[string]string)
+
+ _ = unsafe.Pointer(reflect.ValueOf(&n).Elem().UnsafeAddr())
+ _ = unsafe.Pointer(reflect.ValueOf(&m).Elem().Pointer())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35157.go b/gcc/testsuite/go.test/test/fixedbugs/issue35157.go
new file mode 100644
index 0000000..c9c4899
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35157.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ var i int
+ var b *bool
+ var s0, s1, s2 string
+
+ if *b {
+ s2 = s2[:1]
+ i = 1
+ }
+ s1 = s1[i:-i+i] + s1[-i+i:i+2]
+ s1 = s0[i:-i]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35291.go b/gcc/testsuite/go.test/test/fixedbugs/issue35291.go
new file mode 100644
index 0000000..5d8381c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35291.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check error message for duplicated index in slice literal
+
+package p
+
+var s = []string{
+ 1: "dup",
+ 1: "dup", // ERROR "duplicate index in slice literal: 1|duplicate value for index 1"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go
index 491ada1..e594db7 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go
index 1366d24..2f330bf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35576.go b/gcc/testsuite/go.test/test/fixedbugs/issue35576.go
new file mode 100644
index 0000000..8228555
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35576.go
@@ -0,0 +1,16 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check print/println(f()) is allowed where f() is multi-value.
+
+package main
+
+func f() (int16, float64, string) { return -42, 42.0, "x" }
+
+func main() {
+ print(f())
+ println(f())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35576.out b/gcc/testsuite/go.test/test/fixedbugs/issue35576.out
new file mode 100644
index 0000000..2aefe3e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35576.out
@@ -0,0 +1 @@
+-42+4.200000e+001x-42 +4.200000e+001 x
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/a.go
new file mode 100644
index 0000000..f509b25
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func D(_ string, _ int) (uint64, string) {
+ return 101, "bad"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/b.go
new file mode 100644
index 0000000..e8b674f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35586.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+func F(addr string) (uint64, string) {
+ return a.D(addr, 32)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35586.go b/gcc/testsuite/go.test/test/fixedbugs/issue35586.go
new file mode 100644
index 0000000..0d522b1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35586.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 35586: gollvm compiler crash building docker-ce; the problem
+// involves inlining a function that has multiple no-name ("_") parameters.
+//
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35652.go b/gcc/testsuite/go.test/test/fixedbugs/issue35652.go
new file mode 100644
index 0000000..178a84d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35652.go
@@ -0,0 +1,28 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func e() {
+ for true {
+ if true {
+ continue
+ }
+ }
+}
+
+func g() {}
+
+func f() {
+ i := 0
+ if true {
+ i++
+ }
+ for true {
+ continue
+ g()
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/a.go
new file mode 100644
index 0000000..b79503e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type myError string
+
+func (e myError) Error() string { return string(e) }
+
+const myErrorVal myError = "error"
+
+func IsMyError(err error) bool {
+ return err == error(myErrorVal)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/b.go
new file mode 100644
index 0000000..8d22aac
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35739.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func F(err error) bool {
+ return a.IsMyError(err)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue35739.go b/gcc/testsuite/go.test/test/fixedbugs/issue35739.go
new file mode 100644
index 0000000..26f09d8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue35739.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 35739: gccgo inlining error with constant with method.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/a.go
new file mode 100644
index 0000000..07cabcd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/a.go
@@ -0,0 +1,3 @@
+package a
+
+type W = map[int32]interface{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/b.go
new file mode 100644
index 0000000..c5ee269
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36085.dir/b.go
@@ -0,0 +1,8 @@
+package main
+
+import "a"
+
+var w a.W
+var X interface{} = &w
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36085.go b/gcc/testsuite/go.test/test/fixedbugs/issue36085.go
new file mode 100644
index 0000000..69d4490
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36085.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 36085: gccgo compiler did not generate type descriptor
+// for pointer to type alias defined in another package, causing
+// linking error.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36259.go b/gcc/testsuite/go.test/test/fixedbugs/issue36259.go
new file mode 100644
index 0000000..246eb35
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36259.go
@@ -0,0 +1,28 @@
+// compile
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func rotate(s []int, m int) {
+ l := len(s)
+ m = m % l
+ buf := make([]int, m)
+
+ copy(buf, s)
+ copy(s, s[m:])
+ copy(s[l-m:], buf)
+}
+
+func main() {
+ a0 := [...]int{1,2,3,4,5}
+ println(a0[0])
+
+ rotate(a0[:], 1)
+ println(a0[0])
+
+ rotate(a0[:], -3)
+ println(a0[0])
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36437.go b/gcc/testsuite/go.test/test/fixedbugs/issue36437.go
new file mode 100644
index 0000000..c7a11d2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36437.go
@@ -0,0 +1,49 @@
+// run
+
+// +build !nacl,!js,gc
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests that when non-existent files are passed to the
+// compiler, such as in:
+// go tool compile foo
+// we don't print the beginning position:
+// foo:0: open foo: no such file or directory
+// but instead omit it and print out:
+// open foo: no such file or directory
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "regexp"
+)
+
+func main() {
+ tmpDir, err := ioutil.TempDir("", "issue36437")
+ if err != nil {
+ panic(err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ msgOrErr := func(msg []byte, err error) string {
+ if len(msg) == 0 && err != nil {
+ return err.Error()
+ }
+ return string(msg)
+ }
+
+ filename := "non-existent.go"
+ output, err := exec.Command("go", "tool", "compile", filename).CombinedOutput()
+ got := msgOrErr(output, err)
+
+ regFilenamePos := regexp.MustCompile(filename + ":\\d+")
+ if regFilenamePos.MatchString(got) {
+ fmt.Printf("Error message must not contain filename:pos, but got:\n%q\n", got)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36516.go b/gcc/testsuite/go.test/test/fixedbugs/issue36516.go
new file mode 100644
index 0000000..d4e28b6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36516.go
@@ -0,0 +1,27 @@
+// +build cgo,linux,amd64
+// run -race
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "testing"
+ "unsafe"
+)
+
+var buf [2]byte
+var x unsafe.Pointer = unsafe.Pointer(&buf[0])
+
+func main() {
+ n := testing.AllocsPerRun(1000, func() {
+ x = unsafe.Pointer(uintptr(x) + 1)
+ x = unsafe.Pointer(uintptr(x) - 1)
+ })
+ if n > 0 {
+ panic(fmt.Sprintf("too many allocations; want 0 got %f", n))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue36705.go b/gcc/testsuite/go.test/test/fixedbugs/issue36705.go
new file mode 100644
index 0000000..83e4136
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue36705.go
@@ -0,0 +1,27 @@
+// +build cgo
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// #include <stdlib.h>
+// #include <unistd.h>
+import "C"
+
+import "os"
+
+func main() {
+ os.Setenv("FOO", "bar")
+ s := C.GoString(C.getenv(C.CString("FOO")))
+ if s != "bar" {
+ panic("bad setenv, environment variable only has value \"" + s + "\"")
+ }
+ os.Unsetenv("FOO")
+ s = C.GoString(C.getenv(C.CString("FOO")))
+ if s != "" {
+ panic("bad unsetenv, environment variable still has value \"" + s + "\"")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3705.go b/gcc/testsuite/go.test/test/fixedbugs/issue3705.go
index 64ef38b..ed0a193 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue3705.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3705.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue37246.go b/gcc/testsuite/go.test/test/fixedbugs/issue37246.go
new file mode 100644
index 0000000..fe476da
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue37246.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var n, a, b int64
+ for i := int64(2); i < 10; i++ {
+ for j := i; j < 10; j++ {
+ if ((n % (i * j)) == 0) && (j > 1 && (n/(i*j)) == 1) {
+ a, b = i, 0
+ a = n / (i * j)
+ }
+ }
+ }
+
+ if a != b && a != n {
+ println("yes")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue37716.go b/gcc/testsuite/go.test/test/fixedbugs/issue37716.go
new file mode 100644
index 0000000..42d66dff
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue37716.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "reflect"
+
+// complicated enough to require a compile-generated hash function
+type K struct {
+ a, b int32 // these get merged by the compiler into a single field, something typehash doesn't do
+ c float64
+}
+
+func main() {
+ k := K{a: 1, b: 2, c: 3}
+
+ // Make a reflect map.
+ m := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(K{}), reflect.TypeOf(true)))
+ m.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(true))
+
+ // The binary must not contain the type map[K]bool anywhere, or reflect.MapOf
+ // will use that type instead of making a new one. So use an equivalent named type.
+ type M map[K]bool
+ var x M
+ reflect.ValueOf(&x).Elem().Set(m)
+ if !x[k] {
+ panic("key not found")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue37753.go b/gcc/testsuite/go.test/test/fixedbugs/issue37753.go
new file mode 100644
index 0000000..ac311e3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue37753.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:noinline
+func f(a, b uint) int {
+ return int(a-b) / 8
+}
+
+func main() {
+ if x := f(1, 2); x != 0 {
+ panic(x)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3783.go b/gcc/testsuite/go.test/test/fixedbugs/issue3783.go
index d7a4a2e..7db06d1 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue3783.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3783.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue37975.go b/gcc/testsuite/go.test/test/fixedbugs/issue37975.go
new file mode 100644
index 0000000..a4e8f1f1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue37975.go
@@ -0,0 +1,54 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure runtime.panicmakeslice* are called.
+
+package main
+
+import "strings"
+
+func main() {
+ // Test typechecking passes if len is valid
+ // but cap is out of range for len's type.
+ var x byte
+ _ = make([]int, x, 300)
+
+ capOutOfRange := func() {
+ i := 2
+ s := make([]int, i, 1)
+ s[0] = 1
+ }
+ lenOutOfRange := func() {
+ i := -1
+ s := make([]int, i, 3)
+ s[0] = 1
+ }
+
+ tests := []struct {
+ f func()
+ panicStr string
+ }{
+ {capOutOfRange, "cap out of range"},
+ {lenOutOfRange, "len out of range"},
+ }
+
+ for _, tc := range tests {
+ shouldPanic(tc.panicStr, tc.f)
+ }
+
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ runtimeErr := err.(error).Error()
+ if !strings.Contains(runtimeErr, str) {
+ panic("got panic " + runtimeErr + ", want " + str)
+ }
+ }()
+
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38093.go b/gcc/testsuite/go.test/test/fixedbugs/issue38093.go
new file mode 100644
index 0000000..db92664
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38093.go
@@ -0,0 +1,49 @@
+// +build js
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test race condition between timers and wasm calls that led to memory corruption.
+
+package main
+
+import (
+ "os"
+ "syscall/js"
+ "time"
+)
+
+func main() {
+ ch1 := make(chan struct{})
+
+ go func() {
+ for {
+ time.Sleep(5 * time.Millisecond)
+ ch1 <- struct{}{}
+ }
+ }()
+ go func() {
+ for {
+ time.Sleep(8 * time.Millisecond)
+ ch1 <- struct{}{}
+ }
+ }()
+ go func() {
+ time.Sleep(2 * time.Second)
+ os.Exit(0)
+ }()
+
+ for range ch1 {
+ ch2 := make(chan struct{}, 1)
+ f := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
+ ch2 <- struct{}{}
+ return nil
+ })
+ defer f.Release()
+ fn := js.Global().Get("Function").New("cb", "cb();")
+ fn.Invoke(f)
+ <-ch2
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38117.go b/gcc/testsuite/go.test/test/fixedbugs/issue38117.go
new file mode 100644
index 0000000..11edef7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38117.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// cmd/compile erroneously rejected conversions of constant values
+// between int/float and complex types.
+
+package p
+
+const (
+ _ = int(complex64(int(0)))
+ _ = float64(complex128(float64(0)))
+
+ _ = int8(complex128(1000)) // ERROR "overflow"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38125.go b/gcc/testsuite/go.test/test/fixedbugs/issue38125.go
new file mode 100644
index 0000000..1207aec
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38125.go
@@ -0,0 +1,22 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo mishandled embedded methods of type aliases.
+
+package p
+
+type I int
+
+func (I) M() {}
+
+type T = struct {
+ I
+}
+
+func F() {
+ _ = T.M
+ _ = struct { I }.M
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38356.go b/gcc/testsuite/go.test/test/fixedbugs/issue38356.go
new file mode 100644
index 0000000..a1c7f46
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38356.go
@@ -0,0 +1,54 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure floating point operations that generate flags
+// are scheduled correctly on s390x.
+
+package p
+
+func f1(x, y float64, z int) float64 {
+ a := x + y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
+
+func f2(x, y float64, z int) float64 {
+ a := x - y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
+
+func f3(x, y float32, z int) float32 {
+ a := x + y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
+
+func f4(x, y float32, z int) float32 {
+ a := x - y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38359.go b/gcc/testsuite/go.test/test/fixedbugs/issue38359.go
new file mode 100644
index 0000000..a7550c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38359.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure NaN-NaN compiles correctly.
+
+package p
+
+func f() {
+ var st struct {
+ f float64
+ _, _ string
+ }
+
+ f := 1e308
+ st.f = 2*f - 2*f
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38690.go b/gcc/testsuite/go.test/test/fixedbugs/issue38690.go
new file mode 100644
index 0000000..af8688d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38690.go
@@ -0,0 +1,65 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that literal value can be passed to struct
+// blank field of array/struct type, see issue #38690.
+
+package main
+
+type A1 = [0]int
+type A2 = [1]int
+
+type S1 struct{}
+
+type S2 struct {
+ x int
+}
+
+type S3 = struct{}
+
+type S4 = struct{ x int }
+
+type S struct {
+ x int
+ _ [0]int
+ _ [1]int
+ _ A1
+ _ A2
+ _ S1
+ _ S2
+ _ S3
+ _ S4
+ _ [1]S4
+}
+
+var s = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, S4{1}, [1]S4{}}
+
+func main() {
+ f1()
+ mustPanic(f2)
+ mustPanic(f3)
+}
+
+func f1() {
+ _ = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, S4{1}, [1]S4{}}
+}
+
+func f2() {
+ _ = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, func() S4 { panic("") }(), [1]S4{}}
+}
+
+func f3() {
+ _ = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, S4{1}, func() [1]S4 { panic("") }()}
+}
+
+func mustPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("expected panic, got nil")
+ }
+ }()
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38745.go b/gcc/testsuite/go.test/test/fixedbugs/issue38745.go
new file mode 100644
index 0000000..7d4283b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38745.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type t struct{ x int }
+
+func f1() {
+ t{}.M() // ERROR "t{}.M undefined \(type t has no field or method M\)|undefined field or method .*M"
+ t{x: 1}.M() // ERROR "t{...}.M undefined \(type t has no field or method M\)|undefined field or method .*M"
+}
+
+func f2() (*t, error) {
+ return t{}.M() // ERROR "t{}.M undefined \(type t has no field or method M\)|undefined field or method .*M|not enough arguments"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38746.go b/gcc/testsuite/go.test/test/fixedbugs/issue38746.go
new file mode 100644
index 0000000..c670349
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38746.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var g *uint64
+
+func main() {
+ var v uint64
+ g = &v
+ v &^= (1 << 31)
+ v |= 1 << 63
+ v &^= (1 << 63)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38905.go b/gcc/testsuite/go.test/test/fixedbugs/issue38905.go
new file mode 100644
index 0000000..6f411b8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38905.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that literal value can be passed to struct
+// blank field with expressions where candiscard(value)
+// returns false, see #38905.
+
+package p
+
+type t struct{ _ u }
+type u [10]struct{ f int }
+
+func f(x int) t { return t{u{{1 / x}, {1 % x}}} }
+func g(p *int) t { return t{u{{*p}}} }
+func h(s []int) t { return t{u{{s[0]}}} }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue38916.go b/gcc/testsuite/go.test/test/fixedbugs/issue38916.go
new file mode 100644
index 0000000..fb2ee34
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue38916.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(b bool, c complex128) func(complex128) complex128 {
+ return func(p complex128) complex128 {
+ b = (p+1i == 0) && b
+ return (p + 2i) * (p + 3i - c)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3924.go b/gcc/testsuite/go.test/test/fixedbugs/issue3924.go
deleted file mode 100644
index eb7a665..0000000
--- a/gcc/testsuite/go.test/test/fixedbugs/issue3924.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package foo
-
-type mybool bool
-
-var x, y = 1, 2
-var _ mybool = x < y && x < y
-var _ mybool = x < y || x < y
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3925.go b/gcc/testsuite/go.test/test/fixedbugs/issue3925.go
index a62d439..628c2226 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue3925.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3925.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue39292.go b/gcc/testsuite/go.test/test/fixedbugs/issue39292.go
new file mode 100644
index 0000000..7dac2e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue39292.go
@@ -0,0 +1,29 @@
+// errorcheck -0 -m -l
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type t [20000]*int
+
+func (t) f() {
+}
+
+func x() {
+ x := t{}.f // ERROR "t{}.f escapes to heap"
+ x()
+}
+
+func y() {
+ var i int // ERROR "moved to heap: i"
+ y := (&t{&i}).f // ERROR "\(&t{...}\).f escapes to heap" "&t{...} escapes to heap"
+ y()
+}
+
+func z() {
+ var i int // ERROR "moved to heap: i"
+ z := t{&i}.f // ERROR "t{...}.f escapes to heap"
+ z()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue39459.go b/gcc/testsuite/go.test/test/fixedbugs/issue39459.go
new file mode 100644
index 0000000..de78a17
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue39459.go
@@ -0,0 +1,22 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct { // big enough to be an unSSAable type
+ a, b, c, d, e, f int
+}
+
+func f(x interface{}, p *int) {
+ _ = *p // trigger nil check here, removing it from below
+ switch x := x.(type) {
+ case *T:
+ // Zero twice, so one of them will be removed by the deadstore pass
+ *x = T{}
+ *p = 0 // store op to prevent Zero ops from being optimized by the earlier opt pass rewrite rules
+ *x = T{}
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue39505.go b/gcc/testsuite/go.test/test/fixedbugs/issue39505.go
new file mode 100644
index 0000000..711b562
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue39505.go
@@ -0,0 +1,31 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ if len([]int{})-1 < len([]int{}) {
+ }
+
+ var st struct {
+ i int
+ }
+ g := func() string {
+ return ""
+ }
+ h := func(string) string {
+ return g() + g()
+ }
+ s, i := "", 0
+
+ st.i = len(s)
+ i = len(h(s[i+0:i+1])) + len(s[len(s)+1:i+1])
+ s = s[(len(s[i+1:len(s)+1])+1):len(h(""))+1] + (s[i+1 : len([]int{})+i])
+ i = 1 + len([]int{len([]string{s[i+len([]int{}) : len(s)+i]})})
+
+ var ch chan int
+ ch <- len(h("")) - len(s)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue39505b.go b/gcc/testsuite/go.test/test/fixedbugs/issue39505b.go
new file mode 100644
index 0000000..ecf1ab6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue39505b.go
@@ -0,0 +1,183 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ ff := []func(){lt_f1, lt_f2, lt_f3, lt_f4, lt_f5, lt_f6, lt_f7, lt_f8, lt_f9,
+ gt_f1, gt_f2, gt_f3, le_f1, le_f2, le_f3, ge_f1, ge_f2, ge_f3}
+
+ for _, f := range ff {
+ f()
+ }
+}
+
+func lt_f1() {
+ const c = 1
+ var a = 0
+ var v *int = &a
+ if *v-c < len([]int{}) {
+ } else {
+ panic("bad")
+ }
+}
+
+func lt_f2() {
+ const c = 10
+ var a = 0
+ var v *int = &a
+ if *v+c < len([]int{}) {
+ panic("bad")
+ }
+}
+
+func lt_f3() {
+ const c = -10
+ var a = 0
+ var v *int = &a
+ if *v|0xff+c < len([]int{}) {
+ panic("bad")
+ }
+}
+
+func lt_f4() {
+ const c = 10
+ var a = 0
+ var v *int = &a
+ if *v|0x0f+c < len([]int{}) {
+ panic("bad")
+ }
+}
+
+func lt_f5() {
+ const c int32 = 1
+ var a int32 = 0
+ var v *int32 = &a
+ if *v-c < int32(len([]int32{})) {
+ } else {
+ panic("bad")
+ }
+}
+
+func lt_f6() {
+ const c int32 = 10
+ var a int32 = 0
+ var v *int32 = &a
+ if *v+c < int32(len([]int32{})) {
+ panic("bad")
+ }
+}
+
+func lt_f7() {
+ const c int32 = -10
+ var a int32 = 0
+ var v *int32 = &a
+ if *v|0xff+c < int32(len([]int{})) {
+ panic("bad")
+ }
+}
+
+func lt_f8() {
+ const c int32 = 10
+ var a int32 = 0
+ var v *int32 = &a
+ if *v|0x0f+c < int32(len([]int{})) {
+ panic("bad")
+ }
+}
+
+func lt_f9() {
+ const c int32 = -10
+ var a int32 = 0
+ var v *int32 = &a
+ if *v|0x0a+c < int32(len([]int{})) {
+ panic("bad")
+ }
+}
+
+func gt_f1() {
+ const c = 1
+ var a = 0
+ var v *int = &a
+ if len([]int{}) > *v-c {
+ } else {
+ panic("bad")
+ }
+}
+
+func gt_f2() {
+ const c = 10
+ var a = 0
+ var v *int = &a
+ if len([]int{}) > *v|0x0f+c {
+ panic("bad")
+ }
+}
+
+func gt_f3() {
+ const c int32 = 10
+ var a int32 = 0
+ var v *int32 = &a
+ if int32(len([]int{})) > *v|0x0f+c {
+ panic("bad")
+ }
+}
+
+func le_f1() {
+ const c = -10
+ var a = 0
+ var v *int = &a
+ if *v|0xff+c <= len([]int{}) {
+ panic("bad")
+ }
+}
+
+func le_f2() {
+ const c = 0xf
+ var a = 0
+ var v *int = &a
+ if *v|0xf-c <= len([]int{}) {
+ } else {
+ panic("bad")
+ }
+}
+
+func le_f3() {
+ const c int32 = -10
+ var a int32 = 0
+ var v *int32 = &a
+ if *v|0xff+c <= int32(len([]int{})) {
+ panic("bad")
+ }
+}
+
+func ge_f1() {
+ const c = -10
+ var a = 0
+ var v *int = &a
+ if len([]int{}) >= *v|0xff+c {
+ panic("bad")
+ }
+}
+
+func ge_f2() {
+ const c int32 = 10
+ var a int32 = 0
+ var v *int32 = &a
+ if int32(len([]int{})) >= *v|0x0f+c {
+ panic("bad")
+ }
+}
+
+func ge_f3() {
+ const c = -10
+ var a = 0
+ var v *int = &a
+ if len([]int{}) >= *v|0x0a+c {
+ } else {
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue39541.go b/gcc/testsuite/go.test/test/fixedbugs/issue39541.go
new file mode 100644
index 0000000..fba5291
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue39541.go
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "reflect"
+
+func sub(args []reflect.Value) []reflect.Value {
+ type A struct {
+ s int
+ t int
+ }
+ return []reflect.Value{reflect.ValueOf(A{1, 2})}
+}
+
+func main() {
+ f := reflect.MakeFunc(reflect.TypeOf((func() interface{})(nil)), sub).Interface().(func() interface{})
+ c := make(chan bool, 100)
+ for i := 0; i < 100; i++ {
+ go func() {
+ for j := 0; j < 10000; j++ {
+ f()
+ }
+ c <- true
+ }()
+ }
+ for i := 0; i < 100; i++ {
+ <-c
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue39651.go b/gcc/testsuite/go.test/test/fixedbugs/issue39651.go
new file mode 100644
index 0000000..256a34d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue39651.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that float -> integer conversion doesn't clobber
+// flags.
+
+package main
+
+//go:noinline
+func f(x, y float64, a, b *bool, r *int64) {
+ *a = x < y // set flags
+ *r = int64(x) // clobber flags
+ *b = x == y // use flags
+}
+
+func main() {
+ var a, b bool
+ var r int64
+ f(1, 1, &a, &b, &r)
+ if a || !b {
+ panic("comparison incorrect")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40152.go b/gcc/testsuite/go.test/test/fixedbugs/issue40152.go
new file mode 100644
index 0000000..1cb68e9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40152.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Gccgo mishandles converting an untyped boolean to an interface type.
+
+package main
+
+func t(args ...interface{}) bool {
+ x := true
+ return x == args[0]
+}
+
+func main() {
+ r := t("x" == "x" && "y" == "y")
+ if !r {
+ panic(r)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/a.go
new file mode 100644
index 0000000..5519e93
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/a.go
@@ -0,0 +1,14 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type I interface {
+ Func()
+}
+
+func Call() {
+ f := I.Func
+ f(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/main.go
new file mode 100644
index 0000000..93f5b70
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40252.dir/main.go
@@ -0,0 +1,16 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ defer func() {
+ if recover() == nil {
+ panic("expected nil pointer dereference")
+ }
+ }()
+ a.Call()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40252.go b/gcc/testsuite/go.test/test/fixedbugs/issue40252.go
new file mode 100644
index 0000000..9be4e66
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40252.go
@@ -0,0 +1,8 @@
+// rundir
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo got an undefined symbol reference when inlining a method expression.
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40367.go b/gcc/testsuite/go.test/test/fixedbugs/issue40367.go
new file mode 100644
index 0000000..0dc5ad7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40367.go
@@ -0,0 +1,41 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func case1() {
+ rates := []int32{1,2,3,4,5,6}
+ var sink [6]int
+ j := len(sink)
+ for star, _ := range rates {
+ if star+1 < 1 {
+ panic("")
+ }
+ j--
+ sink[j] = j
+ }
+}
+
+func case2() {
+ i := 0
+ var sink [3]int
+ j := len(sink)
+top:
+ j--
+ sink[j] = j
+ if i < 2 {
+ i++
+ if i < 1 {
+ return
+ }
+ goto top
+ }
+}
+
+func main() {
+ case1()
+ case2()
+} \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40629.go b/gcc/testsuite/go.test/test/fixedbugs/issue40629.go
new file mode 100644
index 0000000..c6ef408
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40629.go
@@ -0,0 +1,69 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+const N = 40
+
+func main() {
+ var x [N]int // stack-allocated memory
+ for i := range x {
+ x[i] = 0x999
+ }
+
+ // This defer checks to see if x is uncorrupted.
+ defer func(p *[N]int) {
+ recover()
+ for i := range p {
+ if p[i] != 0x999 {
+ for j := range p {
+ fmt.Printf("p[%d]=0x%x\n", j, p[j])
+ }
+ panic("corrupted stack variable")
+ }
+ }
+ }(&x)
+
+ // This defer starts a new goroutine, which will (hopefully)
+ // overwrite x on the garbage stack.
+ defer func() {
+ c := make(chan bool)
+ go func() {
+ useStack(1000)
+ c <- true
+ }()
+ <-c
+
+ }()
+
+ // This defer causes a stack copy.
+ // The old stack is now garbage.
+ defer func() {
+ useStack(1000)
+ }()
+
+ // Trigger a segfault.
+ *g = 0
+
+ // Make the return statement unreachable.
+ // That makes the stack map at the deferreturn call empty.
+ // In particular, the argument to the first defer is not
+ // marked as a pointer, so it doesn't get adjusted
+ // during the stack copy.
+ for {
+ }
+}
+
+var g *int64
+
+func useStack(n int) {
+ if n == 0 {
+ return
+ }
+ useStack(n - 1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40746.go b/gcc/testsuite/go.test/test/fixedbugs/issue40746.go
new file mode 100644
index 0000000..235282f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40746.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x byte, b bool) byte {
+ var c byte
+ if b {
+ c = 1
+ }
+
+ if int8(c) < 0 {
+ x++
+ }
+ return x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go
index 089637d..200290a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
index 6304ce0..cf27512 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
@@ -19,29 +19,36 @@ func main() {
shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ testMakeInAppend(n)
+
var t *byte
if unsafe.Sizeof(t) == 8 {
// Test mem > maxAlloc
var n2 int64 = 1 << 59
shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
+ testMakeInAppend(int(n2))
// Test elem.size*cap overflow
n2 = 1<<63 - 1
shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
+ testMakeInAppend(int(n2))
+ var x uint64 = 1<<64 - 1
+ shouldPanic("len out of range", func() { _ = make([]byte, x) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, x) })
+ testMakeInAppend(int(x))
} else {
n = 1<<31 - 1
shouldPanic("len out of range", func() { _ = make(T, n) })
shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ testMakeInAppend(n)
+ var x uint64 = 1<<32 - 1
+ shouldPanic("len out of range", func() { _ = make([]byte, x) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, x) })
+ testMakeInAppend(int(x))
}
-
- // Test make in append panics since the gc compiler optimizes makes in appends.
- shouldPanic("len out of range", func() { _ = append(T{}, make(T, n)...) })
- shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, n)...) })
- shouldPanic("len out of range", func() { _ = append(T{}, make(T, int64(n))...) })
- shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, int64(n))...) })
}
func shouldPanic(str string, f func()) {
@@ -58,3 +65,21 @@ func shouldPanic(str string, f func()) {
f()
}
+
+// Test make in append panics since the gc compiler optimizes makes in appends.
+func testMakeInAppend(n int) {
+ lengths := []int{0, 1}
+ for _, length := range lengths {
+ t := make(T, length)
+ shouldPanic("len out of range", func() { _ = append(t, make(T, n)...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, n)...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40917.go b/gcc/testsuite/go.test/test/fixedbugs/issue40917.go
new file mode 100644
index 0000000..2128be5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40917.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=checkptr
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+func main() {
+ var x [2]uint64
+ a := unsafe.Pointer(&x[1])
+
+ b := a
+ b = unsafe.Pointer(uintptr(b) + 2)
+ b = unsafe.Pointer(uintptr(b) - 1)
+ b = unsafe.Pointer(uintptr(b) &^ 1)
+
+ if a != b {
+ panic("pointer arithmetic failed")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue40954.go b/gcc/testsuite/go.test/test/fixedbugs/issue40954.go
new file mode 100644
index 0000000..53e9ccf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue40954.go
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "unsafe"
+)
+
+//go:notinheap
+type S struct{ x int }
+
+func main() {
+ var i int
+ p := (*S)(unsafe.Pointer(uintptr(unsafe.Pointer(&i))))
+ v := uintptr(unsafe.Pointer(p))
+ // p is a pointer to a go:notinheap type. Like some C libraries,
+ // we stored an integer in that pointer. That integer just happens
+ // to be the address of i.
+ // v is also the address of i.
+ // p has a base type which is marked go:notinheap, so it
+ // should not be adjusted when the stack is copied.
+ recurse(100, p, v)
+}
+func recurse(n int, p *S, v uintptr) {
+ if n > 0 {
+ recurse(n-1, p, v)
+ }
+ if uintptr(unsafe.Pointer(p)) != v {
+ panic("adjusted notinheap pointer")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4097.go b/gcc/testsuite/go.test/test/fixedbugs/issue4097.go
index c2b7d9b..30b65bc 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4097.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4097.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4099.go b/gcc/testsuite/go.test/test/fixedbugs/issue4099.go
index 89392bf..5a4ea7c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4099.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4099.go
@@ -1,6 +1,6 @@
// errorcheck -0 -m
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -19,8 +19,8 @@ func F2([]byte)
func G() {
var buf1 [10]byte
- F1(buf1[:]) // ERROR "buf1 does not escape"
+ F1(buf1[:])
var buf2 [10]byte // ERROR "moved to heap: buf2"
- F2(buf2[:]) // ERROR "buf2 escapes to heap"
+ F2(buf2[:])
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41247.go b/gcc/testsuite/go.test/test/fixedbugs/issue41247.go
new file mode 100644
index 0000000..c5e495b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41247.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() [2]int {
+ return [...]int{2: 0} // ERROR "cannot use \[\.\.\.\]int{...} \(type \[3\]int\)|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41440.go b/gcc/testsuite/go.test/test/fixedbugs/issue41440.go
new file mode 100644
index 0000000..0d911f0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41440.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package p
+
+func f(...int) {}
+
+func g() {
+ var x []int
+ f(x, x...) // ERROR "have \(\[\]int, \.\.\.int\)|too many arguments"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41500.go b/gcc/testsuite/go.test/test/fixedbugs/issue41500.go
new file mode 100644
index 0000000..82dca34
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41500.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package p
+
+type s struct {
+ slice []int
+}
+
+func f() {
+ var x *s
+
+ _ = x == nil || len(x.slice) // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types"
+ _ = len(x.slice) || x == nil // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types"
+ _ = x == nil && len(x.slice) // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types"
+ _ = len(x.slice) && x == nil // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41575.go b/gcc/testsuite/go.test/test/fixedbugs/issue41575.go
new file mode 100644
index 0000000..4568730
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41575.go
@@ -0,0 +1,36 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package p
+
+type T1 struct { // ERROR "invalid recursive type T1\n\tLINE: T1 refers to\n\tLINE+4: T2 refers to\n\tLINE: T1$|invalid recursive type"
+ f2 T2
+}
+
+type T2 struct { // GCCGO_ERROR "invalid recursive type"
+ f1 T1
+}
+
+type a b // GCCGO_ERROR "invalid recursive type"
+type b c // ERROR "invalid recursive type b\n\tLINE: b refers to\n\tLINE+1: c refers to\n\tLINE: b$|invalid recursive type"
+type c b // GCCGO_ERROR "invalid recursive type"
+
+type d e
+type e f
+type f f // ERROR "invalid recursive type f\n\tLINE: f refers to\n\tLINE: f$|invalid recursive type"
+
+type g struct { // ERROR "invalid recursive type g\n\tLINE: g refers to\n\tLINE: g$|invalid recursive type"
+ h struct {
+ g
+ }
+}
+
+type w x
+type x y // ERROR "invalid recursive type x\n\tLINE: x refers to\n\tLINE+1: y refers to\n\tLINE+2: z refers to\n\tLINE: x$|invalid recursive type"
+type y struct{ z } // GCCGO_ERROR "invalid recursive type"
+type z [10]x
+
+type w2 w // refer to the type loop again
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4162.go b/gcc/testsuite/go.test/test/fixedbugs/issue4162.go
index c2a8338..f236bd0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4162.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4162.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4167.go b/gcc/testsuite/go.test/test/fixedbugs/issue4167.go
index 4e35331..86a636f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4167.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4167.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41680.go b/gcc/testsuite/go.test/test/fixedbugs/issue41680.go
new file mode 100644
index 0000000..9dfeb7d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41680.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func F(s string) bool {
+ const m = 16
+ const n = 1e5
+ _ = make([]int, n)
+ return len(s) < n*m
+}
+
+func G() {
+ const n = 1e5
+ _ = make([]int, n)
+ f := n
+ var _ float64 = f
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41736.go b/gcc/testsuite/go.test/test/fixedbugs/issue41736.go
new file mode 100644
index 0000000..36f127f4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41736.go
@@ -0,0 +1,105 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type I struct {
+ x int64
+}
+
+type F struct {
+ x float64
+}
+
+type C struct {
+ x *complex128
+}
+
+type D struct {
+ x complex64
+}
+
+type A [1]*complex128
+
+//go:noinline
+func (i I) X() C {
+ cx := complex(0, float64(i.x))
+ return C{&cx}
+}
+
+//go:noinline
+func (f F) X() C {
+ cx := complex(f.x, 0)
+ return C{&cx}
+}
+
+//go:noinline
+func (c C) X() C {
+ cx := complex(imag(*c.x), real(*c.x))
+ return C{&cx}
+}
+
+//go:noinline
+func (d D) X() C {
+ cx := complex(float64(imag(d.x)), -float64(real(d.x)))
+ return C{&cx}
+}
+
+//go:noinline
+func (a A) X() C {
+ cx := complex(-float64(imag(*a[0])), float64(real(*a[0])))
+ return C{&cx}
+}
+
+//go:noinline
+func (i I) id() I {
+ return i
+}
+
+//go:noinline
+func (f F) id() F {
+ return f
+}
+
+//go:noinline
+func (c C) id() C {
+ return c
+}
+
+//go:noinline
+func (d D) id() D {
+ return d
+}
+
+//go:noinline
+func (a A) id() A {
+ return a
+}
+
+type T interface {
+ X() C
+}
+
+func G(x []T) []T {
+ var y []T
+ for _, a := range x {
+ var v T
+ switch u := a.(type) {
+ case I:
+ v = u.id()
+ case F:
+ v = u.id()
+ case C:
+ v = u.id()
+ case D:
+ v = u.id()
+ case A:
+ v = u.id()
+ }
+ y = append(y, v)
+ }
+ return y
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41780.go b/gcc/testsuite/go.test/test/fixedbugs/issue41780.go
new file mode 100644
index 0000000..632c144
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41780.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Checks that conversion of CMP(x,-y) -> CMN(x,y) is only applied in correct context.
+
+package main
+
+type decimal struct {
+ d [8]byte // digits, big-endian representation
+ dp int // decimal point
+}
+
+var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
+
+//go:noinline
+func foo(d *decimal) int {
+ exp := int(d.d[1])
+ if d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
+ var n int
+ if -d.dp >= len(powtab) {
+ n = 27
+ } else {
+ n = powtab[-d.dp] // incorrect CMP -> CMN substitution causes indexing panic.
+ }
+ exp += n
+ }
+ return exp
+}
+
+func main() {
+ var d decimal
+ d.d[0] = '1'
+ if foo(&d) != 1 {
+ println("FAILURE (though not the one this test was written to catch)")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue41872.go b/gcc/testsuite/go.test/test/fixedbugs/issue41872.go
new file mode 100644
index 0000000..837d61a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue41872.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package main
+
+//go:noinline
+func f8(x int32) bool {
+ return byte(x&0xc0) == 64
+}
+
+//go:noinline
+func f16(x int32) bool {
+ return uint16(x&0x8040) == 64
+}
+
+func main() {
+ if !f8(64) {
+ panic("wanted true, got false")
+ }
+ if !f16(64) {
+ panic("wanted true, got false")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42032.go b/gcc/testsuite/go.test/test/fixedbugs/issue42032.go
new file mode 100644
index 0000000..c456b1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42032.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package main
+
+//go:notinheap
+type NIH struct {
+}
+
+type T struct {
+ x *NIH
+ p *int
+}
+
+var y NIH
+var z int
+
+func main() {
+ a := []T{{&y, &z}}
+ a = append(a, T{&y, &z})
+ if a[1].x == nil {
+ panic("pointer not written")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42058a.go b/gcc/testsuite/go.test/test/fixedbugs/issue42058a.go
new file mode 100644
index 0000000..722f86e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42058a.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package p
+
+var c chan [2 << 16]byte // GC_ERROR "channel element type too large"
+
+type T [1 << 17]byte
+
+var x chan T // GC_ERROR "channel element type too large"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42058b.go b/gcc/testsuite/go.test/test/fixedbugs/issue42058b.go
new file mode 100644
index 0000000..71a280f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42058b.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package p
+
+var c chan [2 << 16]byte // GC_ERROR "channel element type too large"
+
+func f() {
+ _ = 42
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42075.go b/gcc/testsuite/go.test/test/fixedbugs/issue42075.go
new file mode 100644
index 0000000..af85fb2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42075.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+type T struct { // ERROR "recursive type"
+ x int
+ p unsafe.Pointer
+
+ f T
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42076.go b/gcc/testsuite/go.test/test/fixedbugs/issue42076.go
new file mode 100644
index 0000000..3e95481
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42076.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package main
+
+import "reflect"
+
+//go:notinheap
+type NIH struct {
+}
+
+var x, y NIH
+
+func main() {
+ if reflect.DeepEqual(&x, &y) != true {
+ panic("should report true")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4215.go b/gcc/testsuite/go.test/test/fixedbugs/issue4215.go
new file mode 100644
index 0000000..be9fc74
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4215.go
@@ -0,0 +1,53 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func foo() (int, int) {
+ return 2.3 // ERROR "not enough arguments to return\n\thave \(number\)\n\twant \(int, int\)|not enough arguments to return"
+}
+
+func foo2() {
+ return int(2), 2 // ERROR "too many arguments to return\n\thave \(int, number\)\n\twant \(\)|return with value in function with no return type"
+}
+
+func foo3(v int) (a, b, c, d int) {
+ if v >= 0 {
+ return 1 // ERROR "not enough arguments to return\n\thave \(number\)\n\twant \(int, int, int, int\)|not enough arguments to return"
+ }
+ return 2, 3 // ERROR "not enough arguments to return\n\thave \(number, number\)\n\twant \(int, int, int, int\)|not enough arguments to return"
+}
+
+func foo4(name string) (string, int) {
+ switch name {
+ case "cow":
+ return "moo" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return"
+ case "dog":
+ return "dog", 10, true // ERROR "too many arguments to return\n\thave \(string, number, bool\)\n\twant \(string, int\)|too many values in return statement"
+ case "fish":
+ return "" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return"
+ default:
+ return "lizard", 10
+ }
+}
+
+type S int
+type T string
+type U float64
+
+func foo5() (S, T, U) {
+ if false {
+ return "" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(S, T, U\)|not enough arguments to return"
+ } else {
+ ptr := new(T)
+ return ptr // ERROR "not enough arguments to return\n\thave \(\*T\)\n\twant \(S, T, U\)|not enough arguments to return"
+ }
+ return new(S), 12.34, 1 + 0i, 'r', true // ERROR "too many arguments to return\n\thave \(\*S, number, number, number, bool\)\n\twant \(S, T, U\)|too many values in return statement"
+}
+
+func foo6() (T, string) {
+ return "T", true, true // ERROR "too many arguments to return\n\thave \(string, bool, bool\)\n\twant \(T, string\)|too many values in return statement"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4232.go b/gcc/testsuite/go.test/test/fixedbugs/issue4232.go
index e5daa65..30d1326 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4232.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4232.go
@@ -1,9 +1,12 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// issue 4232
+// issue 7200
+
package p
func f() {
@@ -12,22 +15,42 @@ func f() {
_ = a[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = a[:-1] // ERROR "invalid slice index -1|index out of bounds"
_ = a[10] // ERROR "invalid array index 10|index out of bounds"
+ _ = a[9:10]
+ _ = a[10:10]
+ _ = a[9:12] // ERROR "invalid slice index 12|index out of bounds"
+ _ = a[11:12] // ERROR "invalid slice index 11|index out of bounds"
+ _ = a[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
var s []int
_ = s[-1] // ERROR "invalid slice index -1|index out of bounds"
_ = s[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = s[:-1] // ERROR "invalid slice index -1|index out of bounds"
_ = s[10]
+ _ = s[9:10]
+ _ = s[10:10]
+ _ = s[9:12]
+ _ = s[11:12]
+ _ = s[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
- const c = "foo"
+ const c = "foofoofoof"
_ = c[-1] // ERROR "invalid string index -1|index out of bounds"
_ = c[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = c[:-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = c[3] // ERROR "invalid string index 3|index out of bounds"
+ _ = c[10] // ERROR "invalid string index 10|index out of bounds"
+ _ = c[9:10]
+ _ = c[10:10]
+ _ = c[9:12] // ERROR "invalid slice index 12|index out of bounds"
+ _ = c[11:12] // ERROR "invalid slice index 11|index out of bounds"
+ _ = c[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
var t string
_ = t[-1] // ERROR "invalid string index -1|index out of bounds"
_ = t[-1:] // ERROR "invalid slice index -1|index out of bounds"
_ = t[:-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = t[3]
+ _ = t[10]
+ _ = t[9:10]
+ _ = t[10:10]
+ _ = t[9:12]
+ _ = t[11:12]
+ _ = t[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4251.go b/gcc/testsuite/go.test/test/fixedbugs/issue4251.go
index 3668d4c..d11ce51 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4251.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4251.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go
index 089b6f2..a587e28 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go
index 28e4342..02d9836 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4252.go b/gcc/testsuite/go.test/test/fixedbugs/issue4252.go
index 1b0e5b2..01bcbc4 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4252.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4252.go
@@ -1,6 +1,6 @@
// rundir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42568.go b/gcc/testsuite/go.test/test/fixedbugs/issue42568.go
new file mode 100644
index 0000000..834fdc5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42568.go
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that late expansion correctly handles an OpIData with type interface{}
+
+package p
+
+type S struct{}
+
+func (S) M() {}
+
+type I interface {
+ M()
+}
+
+func f(i I) {
+ o := i.(interface{})
+ if _, ok := i.(*S); ok {
+ o = nil
+ }
+ println(o)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42587.go b/gcc/testsuite/go.test/test/fixedbugs/issue42587.go
new file mode 100644
index 0000000..d10ba97
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42587.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+package p
+
+func f() {
+ var i, j int
+ _ = func() {
+ i = 32
+ j = j>>i | len([]int{})
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42703.go b/gcc/testsuite/go.test/test/fixedbugs/issue42703.go
new file mode 100644
index 0000000..15f7a91
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42703.go
@@ -0,0 +1,19 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var ok [2]bool
+
+func main() {
+ f()()
+ if !ok[0] || !ok[1] {
+ panic("FAIL")
+ }
+}
+
+func f() func() { ok[0] = true; return g }
+func g() { ok[1] = true }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42727.go b/gcc/testsuite/go.test/test/fixedbugs/issue42727.go
new file mode 100644
index 0000000..4008170
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42727.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that late expansion correctly handles an OpLoad with type interface{}
+
+package p
+
+type iface interface {
+ m()
+}
+
+type it interface{}
+
+type makeIface func() iface
+
+func f() {
+ var im makeIface
+ e := im().(it)
+ _ = &e
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42784.go b/gcc/testsuite/go.test/test/fixedbugs/issue42784.go
new file mode 100644
index 0000000..e2b06e9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42784.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that late expansion correctly set OpLoad argument type interface{}
+
+package p
+
+type iface interface {
+ m()
+}
+
+type it interface{}
+
+type makeIface func() iface
+
+func f() {
+ var im makeIface
+ e := im().(it)
+ g(e)
+}
+
+//go:noinline
+func g(i it) {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42790.go b/gcc/testsuite/go.test/test/fixedbugs/issue42790.go
new file mode 100644
index 0000000..d83a022
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42790.go
@@ -0,0 +1,9 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+const _ = -uint(len(string(1<<32)) - len("\uFFFD"))
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4283.go b/gcc/testsuite/go.test/test/fixedbugs/issue4283.go
index 128c872..fa5629b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4283.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4283.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue42876.go b/gcc/testsuite/go.test/test/fixedbugs/issue42876.go
new file mode 100644
index 0000000..67cf491
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue42876.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var x = [4]int32{-0x7fffffff, 0x7fffffff, 2, 4}
+
+func main() {
+ if x[0] > x[1] {
+ panic("fail 1")
+ }
+ if x[2]&x[3] < 0 {
+ panic("fail 2") // Fails here
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue43099.go b/gcc/testsuite/go.test/test/fixedbugs/issue43099.go
new file mode 100644
index 0000000..16f18e5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue43099.go
@@ -0,0 +1,34 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check to make sure we don't try to constant fold a divide by zero.
+// This is a tricky test, as we need a value that's not recognized as 0
+// until lowering (otherwise it gets handled in a different path).
+
+package p
+
+func f() {
+ var i int
+ var s string
+ for i > 0 {
+ _ = s[0]
+ i++
+ }
+
+ var c chan int
+ c <- 1 % i
+}
+
+func f32() uint32 {
+ s := "\x00\x00\x00\x00"
+ c := uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 | uint32(s[3])<<24
+ return 1 / c
+}
+func f64() uint64 {
+ s := "\x00\x00\x00\x00\x00\x00\x00\x00"
+ c := uint64(s[0]) | uint64(s[1])<<8 | uint64(s[2])<<16 | uint64(s[3])<<24 | uint64(s[4])<<32 | uint64(s[5])<<40 | uint64(s[6])<<48 | uint64(s[7])<<56
+ return 1 / c
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue43111.go b/gcc/testsuite/go.test/test/fixedbugs/issue43111.go
new file mode 100644
index 0000000..76d7beb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue43111.go
@@ -0,0 +1,70 @@
+// run
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var ch chan int
+var x int
+
+func f() int {
+ close(ch)
+ ch = nil
+ return 0
+}
+
+func g() int {
+ ch = nil
+ x = 0
+ return 0
+}
+
+func main() {
+ var nilch chan int
+ var v int
+ var ok bool
+ _, _ = v, ok
+
+ ch = make(chan int)
+ select {
+ case <-ch:
+ case nilch <- f():
+ }
+
+ ch = make(chan int)
+ select {
+ case v = <-ch:
+ case nilch <- f():
+ }
+
+ ch = make(chan int)
+ select {
+ case v := <-ch: _ = v
+ case nilch <- f():
+ }
+
+ ch = make(chan int)
+ select {
+ case v, ok = <-ch:
+ case nilch <- f():
+ }
+
+ ch = make(chan int)
+ select {
+ case v, ok := <-ch: _, _ = v, ok
+ case nilch <- f():
+ }
+
+ ch1 := make(chan int, 1)
+ ch = ch1
+ x = 42
+ select {
+ case ch <- x:
+ case nilch <- g():
+ }
+ if got := <-ch1; got != 42 {
+ panic(got)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue43112.go b/gcc/testsuite/go.test/test/fixedbugs/issue43112.go
new file mode 100644
index 0000000..e36627a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue43112.go
@@ -0,0 +1,41 @@
+// compile
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type Symbol interface{}
+
+type Value interface {
+ String() string
+}
+
+type Object interface {
+ String() string
+}
+
+type Scope struct {
+ outer *Scope
+ elems map[string]Object
+}
+
+func (s *Scope) findouter(name string) (*Scope, Object) {
+ return s.outer.findouter(name)
+}
+
+func (s *Scope) Resolve(name string) (sym Symbol) {
+ if _, obj := s.findouter(name); obj != nil {
+ sym = obj.(Symbol)
+ }
+ return
+}
+
+type ScopeName struct {
+ scope *Scope
+}
+
+func (n *ScopeName) Get(name string) (Value, error) {
+ return n.scope.Resolve(name).(Value), nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4313.go b/gcc/testsuite/go.test/test/fixedbugs/issue4313.go
index b2f69db..2494b83 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4313.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4313.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4316.go b/gcc/testsuite/go.test/test/fixedbugs/issue4316.go
index bb18a08..de9a61b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4316.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4316.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4323.go b/gcc/testsuite/go.test/test/fixedbugs/issue4323.go
index 6bb78f4..f082a1f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4323.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4323.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.go
index 5ce2eea..6a510f9 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4326.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4348.go b/gcc/testsuite/go.test/test/fixedbugs/issue4348.go
index 3dac8f7..8b1a56c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4348.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4348.go
@@ -1,12 +1,14 @@
-// compile
+// skip
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 4348. After switch to 64-bit ints the compiler generates
// illegal instructions when using large array bounds or indexes.
+// Skip. We reject symbols larger that 2GB (Issue #9862).
+
package main
// 1<<32 on a 64-bit machine, 1 otherwise.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4353.go b/gcc/testsuite/go.test/test/fixedbugs/issue4353.go
index defe7c3..6a17c46 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4353.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4353.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4359.go b/gcc/testsuite/go.test/test/fixedbugs/issue4359.go
index b5adb40..c79e9e2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4359.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4359.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4365.go b/gcc/testsuite/go.test/test/fixedbugs/issue4365.go
new file mode 100644
index 0000000..09ff1bf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4365.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that fields hide promoted methods.
+// https://golang.org/issue/4365
+
+package main
+
+type T interface {
+ M()
+}
+
+type M struct{}
+
+func (M) M() {}
+
+type Foo struct {
+ M
+}
+
+func main() {
+ var v T = Foo{} // ERROR "has no methods|not a method|cannot use"
+ _ = v
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go
index d732c8b..d010e93 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go
index 33370d0..0d3e236 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go
index 13c996b..c275c6e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.go
index 76b47e1..b1d0364 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4370.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go
index 11ae1f7..38dd4b8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go
index d0bf28f..1284870 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4399.go b/gcc/testsuite/go.test/test/fixedbugs/issue4399.go
index 6674db9..3dc2126 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4399.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4399.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4405.go b/gcc/testsuite/go.test/test/fixedbugs/issue4405.go
index b8458d7..5ba3e10 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4405.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4405.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4429.go b/gcc/testsuite/go.test/test/fixedbugs/issue4429.go
index 6822760..9eb2e0f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4429.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4429.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4448.go b/gcc/testsuite/go.test/test/fixedbugs/issue4448.go
index fa1d9fe..f5e4715 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4448.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4448.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4452.go b/gcc/testsuite/go.test/test/fixedbugs/issue4452.go
index 54dd214..f91bd2c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4452.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4452.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4458.go b/gcc/testsuite/go.test/test/fixedbugs/issue4458.go
index 82b104a..59cfa9f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4458.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4458.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -16,5 +16,5 @@ func (T) foo() {}
func main() {
av := T{}
pav := &av
- (**T).foo(&pav) // ERROR "no method|requires named type or pointer to named"
+ (**T).foo(&pav) // ERROR "no method .*foo|requires named type or pointer to named"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4463.go b/gcc/testsuite/go.test/test/fixedbugs/issue4463.go
index 70977ce..6ad1952 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4463.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4463.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4468.go b/gcc/testsuite/go.test/test/fixedbugs/issue4468.go
index ef0b46b..d26725e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4468.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4468.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -19,8 +19,12 @@ type S struct {
}
func F() {
- go (F()) // ERROR "must be function call"
- defer (F()) // ERROR "must be function call"
+ go F // ERROR "must be function call"
+ defer F // ERROR "must be function call"
+ go (F) // ERROR "must be function call|must not be parenthesized"
+ defer (F) // ERROR "must be function call|must not be parenthesized"
+ go (F()) // ERROR "must be function call|must not be parenthesized"
+ defer (F()) // ERROR "must be function call|must not be parenthesized"
var s S
(&s.t).F()
go (&s.t).F()
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4470.go b/gcc/testsuite/go.test/test/fixedbugs/issue4470.go
index 5ed09ca..d922478 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4470.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4470.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4495.go b/gcc/testsuite/go.test/test/fixedbugs/issue4495.go
index 7ec1134..308acc2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4495.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4495.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go
index a1b6b57..83d42e7 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go
index f04103f..34fa98f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go
index 47b21cf..9023e0a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517d.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517d.go
index 3d727d4..197c225 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4517d.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517d.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4518.go b/gcc/testsuite/go.test/test/fixedbugs/issue4518.go
index e64b069..c482b0f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4518.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4518.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,15 +10,13 @@
package main
-func DontInline() {}
-
+//go:noinline
func F(e interface{}) (int, int) {
- DontInline()
return 3, 7
}
+//go:noinline
func G() (int, int) {
- DontInline()
return 3, 7
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4529.go b/gcc/testsuite/go.test/test/fixedbugs/issue4529.go
index 4f37e7c..66b96c7 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4529.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4529.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4545.go b/gcc/testsuite/go.test/test/fixedbugs/issue4545.go
index c37ccef..534ba71 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4545.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4545.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4562.go b/gcc/testsuite/go.test/test/fixedbugs/issue4562.go
index 29d98b0..8c958f5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4562.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4562.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4585.go b/gcc/testsuite/go.test/test/fixedbugs/issue4585.go
index ad1242d..9191ec5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4585.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4585.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go
index c447371..96cac0a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go
index 61c01d7..98bc2a5 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go
index 3220e85..32055b2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4614.go b/gcc/testsuite/go.test/test/fixedbugs/issue4614.go
index 1aa318c..ad378d8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4614.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4614.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4618.go b/gcc/testsuite/go.test/test/fixedbugs/issue4618.go
index fe875b3..0ba9523 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4618.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4618.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4620.go b/gcc/testsuite/go.test/test/fixedbugs/issue4620.go
index 7b4ebf9..5aa2908 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4620.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4620.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4654.go b/gcc/testsuite/go.test/test/fixedbugs/issue4654.go
index d3f582b..76aff76 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4654.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4654.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4663.go b/gcc/testsuite/go.test/test/fixedbugs/issue4663.go
index edaee93..971290d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4663.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4663.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4667.go b/gcc/testsuite/go.test/test/fixedbugs/issue4667.go
index 18d773c..31b3284 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4667.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4667.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4734.go b/gcc/testsuite/go.test/test/fixedbugs/issue4734.go
index 69f66f2..45e609d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4734.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4734.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4748.go b/gcc/testsuite/go.test/test/fixedbugs/issue4748.go
index 73c7539..f7c77cf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4748.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4748.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4752.go b/gcc/testsuite/go.test/test/fixedbugs/issue4752.go
index d6781e3..af7bb92 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4752.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4752.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4776.go b/gcc/testsuite/go.test/test/fixedbugs/issue4776.go
index 13781af..a1009ad 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4776.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4776.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4785.go b/gcc/testsuite/go.test/test/fixedbugs/issue4785.go
index c3dd629..d0bcd56 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4785.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4785.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go
index aefe2d6..09e1b85 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go
index 2b9e44e..216f352 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go
@@ -10,16 +10,14 @@ type T struct {
Pointer *int
}
-func dontinline() {}
-
+//go:noinline
func Store(t *T) {
global = t.Pointer
- dontinline()
}
+//go:noinline
func Store2(t *T) {
global2 = t.Pointer
- dontinline()
}
func Get() *int {
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5002.go b/gcc/testsuite/go.test/test/fixedbugs/issue5002.go
index 1e74fa1..5ac119a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5002.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5002.go
@@ -1,6 +1,6 @@
// build
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5056.go b/gcc/testsuite/go.test/test/fixedbugs/issue5056.go
index a2cde2a..6fb444a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5056.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5056.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5172.go b/gcc/testsuite/go.test/test/fixedbugs/issue5172.go
index a6acbd3..ed92ac6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5172.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5172.go
@@ -12,8 +12,15 @@ type foo struct {
x bar // ERROR "undefined"
}
+type T struct{}
+
+func (t T) Bar() {}
+
func main() {
var f foo
- go f.bar() // GCCGO_ERROR "undefined"
- defer f.bar() // GCCGO_ERROR "undefined"
+ go f.bar() // ERROR "undefined"
+ defer f.bar() // ERROR "undefined"
+
+ t := T{1} // ERROR "too many"
+ go t.Bar()
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5231.go b/gcc/testsuite/go.test/test/fixedbugs/issue5231.go
index 4039913..6bc8826 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5231.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5231.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5358.go b/gcc/testsuite/go.test/test/fixedbugs/issue5358.go
index c2b1da9..25f1e52 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5358.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5358.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5373.go b/gcc/testsuite/go.test/test/fixedbugs/issue5373.go
new file mode 100644
index 0000000..8aee9a2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5373.go
@@ -0,0 +1,71 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that zeroing range loops have the requisite side-effects.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func check(n int) {
+ // When n == 0, i is untouched by the range loop.
+ // Picking an initial value of -1 for i makes the
+ // "want" calculation below correct in all cases.
+ i := -1
+ s := make([]byte, n)
+ for i = range s {
+ s[i] = 0
+ }
+ if want := n - 1; i != want {
+ fmt.Printf("index after range with side-effect = %d want %d\n", i, want)
+ os.Exit(1)
+ }
+
+ i = n + 1
+ // i is shadowed here, so its value should be unchanged.
+ for i := range s {
+ s[i] = 0
+ }
+ if want := n + 1; i != want {
+ fmt.Printf("index after range without side-effect = %d want %d\n", i, want)
+ os.Exit(1)
+ }
+
+ // Index variable whose evaluation has side-effects
+ var x int
+ f := func() int {
+ x++
+ return 0
+ }
+ var a [1]int
+ for a[f()] = range s {
+ s[a[f()]] = 0
+ }
+ if want := n * 2; x != want {
+ fmt.Printf("index function calls = %d want %d\n", x, want)
+ os.Exit(1)
+ }
+
+ // Range expression whose evaluation has side-effects
+ x = 0
+ b := [1][]byte{s}
+ for i := range b[f()] {
+ b[f()][i] = 0
+ }
+ if want := n + 1; x != n+1 {
+ fmt.Printf("range expr function calls = %d want %d\n", x, want)
+ os.Exit(1)
+ }
+}
+
+func main() {
+ check(0)
+ check(1)
+ check(15)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5581.go b/gcc/testsuite/go.test/test/fixedbugs/issue5581.go
index 36a4ad6..8834b44 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5581.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5581.go
@@ -3,7 +3,7 @@
// Used to emit a spurious "invalid recursive type" error.
// See golang.org/issue/5581.
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5698.go b/gcc/testsuite/go.test/test/fixedbugs/issue5698.go
index 035bbd3..081541c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5698.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5698.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5704.go b/gcc/testsuite/go.test/test/fixedbugs/issue5704.go
index 1dfa072..11b9a93 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5704.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5704.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5793.go b/gcc/testsuite/go.test/test/fixedbugs/issue5793.go
new file mode 100644
index 0000000..8104155
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5793.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5793: calling 2-arg builtin with multiple-result f() call expression gives
+// spurious error.
+
+package main
+
+func complexArgs() (float64, float64) {
+ return 5, 7
+}
+
+func appendArgs() ([]string, string) {
+ return []string{"foo"}, "bar"
+}
+
+func appendMultiArgs() ([]byte, byte, byte) {
+ return []byte{'a', 'b'}, '1', '2'
+}
+
+func main() {
+ if c := complex(complexArgs()); c != 5+7i {
+ panic(c)
+ }
+
+ if s := append(appendArgs()); len(s) != 2 || s[0] != "foo" || s[1] != "bar" {
+ panic(s)
+ }
+
+ if b := append(appendMultiArgs()); len(b) != 4 || b[0] != 'a' || b[1] != 'b' || b[2] != '1' || b[3] != '2' {
+ panic(b)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5809.go b/gcc/testsuite/go.test/test/fixedbugs/issue5809.go
index ca060b55..fc8eeef 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5809.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5809.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5820.go b/gcc/testsuite/go.test/test/fixedbugs/issue5820.go
index 94de06d..1046d66 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5820.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5820.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5841.go b/gcc/testsuite/go.test/test/fixedbugs/issue5841.go
index cfc4a50..2be1aee 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5841.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5841.go
@@ -1,6 +1,6 @@
// build
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5856.go b/gcc/testsuite/go.test/test/fixedbugs/issue5856.go
index 35cadf8..f132588 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5856.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5856.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5963.go b/gcc/testsuite/go.test/test/fixedbugs/issue5963.go
index 190e8f4..f828303 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue5963.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5963.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6004.go b/gcc/testsuite/go.test/test/fixedbugs/issue6004.go
index 45aaffd..2b3dcd9 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6004.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6004.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6036.go b/gcc/testsuite/go.test/test/fixedbugs/issue6036.go
index 5f787c5..8ebef5a 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6036.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6036.go
@@ -1,7 +1,7 @@
-// +build amd64
+// +build !386,!arm,!mips,!mipsle,!amd64p32
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6055.go b/gcc/testsuite/go.test/test/fixedbugs/issue6055.go
index 698f62a..4594348 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6055.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6055.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6131.go b/gcc/testsuite/go.test/test/fixedbugs/issue6131.go
index 817e4a8..61548a2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6131.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6131.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6140.go b/gcc/testsuite/go.test/test/fixedbugs/issue6140.go
index d494933..dde7921 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6140.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6140.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6247.go b/gcc/testsuite/go.test/test/fixedbugs/issue6247.go
index eea8f9c..2786786 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6247.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6247.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6269.go b/gcc/testsuite/go.test/test/fixedbugs/issue6269.go
index af5feb7..2930f52 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6269.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6269.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p0.go b/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p0.go
new file mode 100644
index 0000000..d4d4da7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p0.go
@@ -0,0 +1,13 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p0
+
+type T0 interface {
+ m0()
+}
+
+type S0 struct{}
+
+func (S0) m0() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p1.go
new file mode 100644
index 0000000..26efae7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p1.go
@@ -0,0 +1,26 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p1
+
+import "./p0"
+
+type T1 interface {
+ p0.T0
+ m1()
+}
+
+type S1 struct {
+ p0.S0
+}
+
+func (S1) m1() {}
+
+func NewT0() p0.T0 {
+ return S1{}
+}
+
+func NewT1() T1 {
+ return S1{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p2.go
new file mode 100644
index 0000000..f5b6ffd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6295.dir/p2.go
@@ -0,0 +1,19 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "./p0"
+ "./p1"
+)
+
+var (
+ _ p0.T0 = p0.S0{}
+ _ p0.T0 = p1.S1{}
+ _ p0.T0 = p1.NewT0()
+ _ p0.T0 = p1.NewT1() // same as p1.S1{}
+)
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6295.go b/gcc/testsuite/go.test/test/fixedbugs/issue6295.go
new file mode 100644
index 0000000..b8da212
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6295.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 6295: qualified name of unexported methods
+// is corrupted during import.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6298.go b/gcc/testsuite/go.test/test/fixedbugs/issue6298.go
index 6303dbe..ab3bfcd 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6298.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6298.go
@@ -3,7 +3,7 @@
// golang.org/issue/6298.
// Used to cause "internal error: typename ideal bool"
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6402.go b/gcc/testsuite/go.test/test/fixedbugs/issue6402.go
new file mode 100644
index 0000000..ecde9ae
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6402.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 6402: spurious 'use of untyped nil' error
+
+package p
+
+func f() uintptr {
+ return nil // ERROR "cannot use nil as type uintptr in return argument|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6403.go b/gcc/testsuite/go.test/test/fixedbugs/issue6403.go
new file mode 100644
index 0000000..809efef
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6403.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 6403: fix spurious 'const initializer is not a constant' error
+
+package p
+
+import "syscall"
+
+const A int = syscall.X // ERROR "undefined: syscall.X|undefined identifier .*syscall.X"
+const B int = voidpkg.X // ERROR "undefined: voidpkg|undefined name .*voidpkg"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6406.go b/gcc/testsuite/go.test/test/fixedbugs/issue6406.go
new file mode 100644
index 0000000..5491193
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6406.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ s = "bob" // ERROR "undefined.*s"
+ _ = s // ERROR "undefined.*s"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/a.go
index da90ca3..e5536fe 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/a.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/a.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/b.go
index 3b35b2d..ce3d52e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/b.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/main.go
index f09b727..8d8c02b 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6513.dir/main.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703a.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703a.go
new file mode 100644
index 0000000..38c5956
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703a.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a function value.
+
+package funcvalue
+
+func fx() int {
+ _ = x
+ return 0
+}
+
+var x = fx // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703b.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703b.go
new file mode 100644
index 0000000..35438c3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703b.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a function call.
+
+package funccall
+
+func fx() int {
+ _ = x
+ return 0
+}
+
+var x = fx() // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703c.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703c.go
new file mode 100644
index 0000000..ade40e3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703c.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a method expression.
+
+package methexpr
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T.m // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703d.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703d.go
new file mode 100644
index 0000000..dd48163
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703d.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a method expression call.
+
+package methexprcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T.m(0) // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703e.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703e.go
new file mode 100644
index 0000000..d362d6e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703e.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method value of a value literal.
+
+package litmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T(0).m // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703f.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703f.go
new file mode 100644
index 0000000..0b49026
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703f.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method call of a value literal.
+
+package litmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var x = T(0).m() // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703g.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703g.go
new file mode 100644
index 0000000..05ec740
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703g.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in an embedded method expression.
+
+package embedmethexpr
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E.m // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703h.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703h.go
new file mode 100644
index 0000000..f6b69e1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703h.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles when calling an embedded method expression.
+
+package embedmethexprcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E.m(E{0}) // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703i.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703i.go
new file mode 100644
index 0000000..fb580a2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703i.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in an embedded struct literal's method value.
+
+package embedlitmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E{}.m // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703j.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703j.go
new file mode 100644
index 0000000..b4c079f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703j.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in an embedded struct literal's method call.
+
+package embedlitmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var x = E{}.m() // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703k.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703k.go
new file mode 100644
index 0000000..6f606e2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703k.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a method value.
+
+package methvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var (
+ t T
+ x = t.m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703l.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703l.go
new file mode 100644
index 0000000..684c225
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703l.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a method call.
+
+package methcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+var (
+ t T
+ x = t.m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703m.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703m.go
new file mode 100644
index 0000000..7d1b604
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703m.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method value of a value returned from a function call.
+
+package funcmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func f() T {
+ return T(0)
+}
+
+var (
+ t T
+ x = f().m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703n.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703n.go
new file mode 100644
index 0000000..22646af
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703n.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method call of a value returned from a function call.
+
+package funcmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func f() T {
+ return T(0)
+}
+
+var (
+ t T
+ x = f().m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703o.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703o.go
new file mode 100644
index 0000000..a11fdfd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703o.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in an embedded struct's method value.
+
+package embedmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = e.m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703p.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703p.go
new file mode 100644
index 0000000..3ac7a63
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703p.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in an embedded struct's method call.
+
+package embedmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = e.m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703q.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703q.go
new file mode 100644
index 0000000..b087c15
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703q.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method value of an embedded struct returned
+// from a function call.
+
+package funcembedmethvalue
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func g() E {
+ return E{0}
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = g().m // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703r.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703r.go
new file mode 100644
index 0000000..de514f1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703r.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method call of an embedded struct returned
+// from a function call.
+
+package funcembedmethcall
+
+type T int
+
+func (T) m() int {
+ _ = x
+ return 0
+}
+
+func g() E {
+ return E{0}
+}
+
+type E struct{ T }
+
+var (
+ e E
+ x = g().m() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703s.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703s.go
new file mode 100644
index 0000000..cd3c5b3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703s.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a pointer method expression.
+
+package ptrmethexpr
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T).pm // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703t.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703t.go
new file mode 100644
index 0000000..62de37c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703t.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the call of a pointer method expression.
+
+package ptrmethexprcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T).pm(nil) // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703u.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703u.go
new file mode 100644
index 0000000..961a000
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703u.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a pointer literal's method value.
+
+package ptrlitmethvalue
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T)(nil).pm // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703v.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703v.go
new file mode 100644
index 0000000..2409911
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703v.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a pointer literal's method call.
+
+package ptrlitmethcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var x = (*T)(nil).pm() // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703w.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703w.go
new file mode 100644
index 0000000..b7b3d91
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703w.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a pointer value's method value.
+
+package ptrmethvalue
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var (
+ p *T
+ x = p.pm // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703x.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703x.go
new file mode 100644
index 0000000..48daf03
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703x.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in a pointer value's method call.
+
+package ptrmethcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+var (
+ p *T
+ x = p.pm() // ERROR "initialization loop|depends upon itself"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703y.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703y.go
new file mode 100644
index 0000000..278dfcd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703y.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method value of a pointer value returned
+// from a function call.
+
+package funcptrmethvalue
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+func pf() *T {
+ return nil
+}
+
+var x = pf().pm // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6703z.go b/gcc/testsuite/go.test/test/fixedbugs/issue6703z.go
new file mode 100644
index 0000000..f81a3a8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6703z.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for cycles in the method call of a pointer value returned
+// from a function call.
+
+package funcptrmethcall
+
+type T int
+
+func (*T) pm() int {
+ _ = x
+ return 0
+}
+
+func pf() *T {
+ return nil
+}
+
+var x = pf().pm() // ERROR "initialization loop|depends upon itself"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6772.go b/gcc/testsuite/go.test/test/fixedbugs/issue6772.go
new file mode 100644
index 0000000..5bd15ba
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6772.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1() {
+ for a, a := range []int{1, 2, 3} { // ERROR "a.* repeated on left side of :="
+ println(a)
+ }
+}
+
+func f2() {
+ var a int
+ for a, a := range []int{1, 2, 3} { // ERROR "a.* repeated on left side of :="
+ println(a)
+ }
+ println(a)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6847.go b/gcc/testsuite/go.test/test/fixedbugs/issue6847.go
new file mode 100644
index 0000000..da300bc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6847.go
@@ -0,0 +1,85 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 6847: select clauses involving implicit conversion
+// of channels trigger a spurious typechecking error during walk.
+
+package p
+
+type I1 interface {
+ String()
+}
+type I2 interface {
+ String()
+}
+
+func F() {
+ var (
+ cr <-chan int
+ cs chan<- int
+ c chan int
+
+ ccr chan (<-chan int)
+ ccs chan chan<- int
+ cc chan chan int
+
+ ok bool
+ )
+ // Send cases.
+ select {
+ case ccr <- cr:
+ case ccr <- c:
+ }
+ select {
+ case ccs <- cs:
+ case ccs <- c:
+ }
+ select {
+ case ccr <- c:
+ default:
+ }
+ // Receive cases.
+ select {
+ case cr = <-cc:
+ case cs = <-cc:
+ case c = <-cc:
+ }
+ select {
+ case cr = <-cc:
+ default:
+ }
+ select {
+ case cr, ok = <-cc:
+ case cs, ok = <-cc:
+ case c = <-cc:
+ }
+ // Interfaces.
+ var (
+ c1 chan I1
+ c2 chan I2
+ x1 I1
+ x2 I2
+ )
+ select {
+ case c1 <- x1:
+ case c1 <- x2:
+ case c2 <- x1:
+ case c2 <- x2:
+ }
+ select {
+ case x1 = <-c1:
+ case x1 = <-c2:
+ case x2 = <-c1:
+ case x2 = <-c2:
+ }
+ select {
+ case x1, ok = <-c1:
+ case x1, ok = <-c2:
+ case x2, ok = <-c1:
+ case x2, ok = <-c2:
+ }
+ _ = ok
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6866.go b/gcc/testsuite/go.test/test/fixedbugs/issue6866.go
new file mode 100644
index 0000000..1080b27
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6866.go
@@ -0,0 +1,80 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// WARNING: GENERATED FILE - DO NOT MODIFY MANUALLY!
+// (To generate, in go/types directory: go test -run=Hilbert -H=2 -out="h2.src")
+
+// This program tests arbitrary precision constant arithmetic
+// by generating the constant elements of a Hilbert matrix H,
+// its inverse I, and the product P = H*I. The product should
+// be the identity matrix.
+package main
+
+func main() {
+ if !ok {
+ print()
+ return
+ }
+}
+
+// Hilbert matrix, n = 2
+const (
+ h0_0, h0_1 = 1.0 / (iota + 1), 1.0 / (iota + 2)
+ h1_0, h1_1
+)
+
+// Inverse Hilbert matrix
+const (
+ i0_0 = +1 * b2_1 * b2_1 * b0_0 * b0_0
+ i0_1 = -2 * b2_0 * b3_1 * b1_0 * b1_0
+
+ i1_0 = -2 * b3_1 * b2_0 * b1_1 * b1_1
+ i1_1 = +3 * b3_0 * b3_0 * b2_1 * b2_1
+)
+
+// Product matrix
+const (
+ p0_0 = h0_0*i0_0 + h0_1*i1_0
+ p0_1 = h0_0*i0_1 + h0_1*i1_1
+
+ p1_0 = h1_0*i0_0 + h1_1*i1_0
+ p1_1 = h1_0*i0_1 + h1_1*i1_1
+)
+
+// Verify that product is identity matrix
+const ok = p0_0 == 1 && p0_1 == 0 &&
+ p1_0 == 0 && p1_1 == 1 &&
+ true
+
+func print() {
+ println(p0_0, p0_1)
+ println(p1_0, p1_1)
+}
+
+// Binomials
+const (
+ b0_0 = f0 / (f0 * f0)
+
+ b1_0 = f1 / (f0 * f1)
+ b1_1 = f1 / (f1 * f0)
+
+ b2_0 = f2 / (f0 * f2)
+ b2_1 = f2 / (f1 * f1)
+ b2_2 = f2 / (f2 * f0)
+
+ b3_0 = f3 / (f0 * f3)
+ b3_1 = f3 / (f1 * f2)
+ b3_2 = f3 / (f2 * f1)
+ b3_3 = f3 / (f3 * f0)
+)
+
+// Factorials
+const (
+ f0 = 1
+ f1 = 1
+ f2 = f1 * 2
+ f3 = f2 * 3
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6889.go b/gcc/testsuite/go.test/test/fixedbugs/issue6889.go
new file mode 100644
index 0000000..efd8b76
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6889.go
@@ -0,0 +1,111 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 6889: confusing error message: ovf in mpaddxx
+
+package main
+
+const (
+ f1 = 1
+ f2 = f1 * 2
+ f3 = f2 * 3
+ f4 = f3 * 4
+ f5 = f4 * 5
+ f6 = f5 * 6
+ f7 = f6 * 7
+ f8 = f7 * 8
+ f9 = f8 * 9
+ f10 = f9 * 10
+ f11 = f10 * 11
+ f12 = f11 * 12
+ f13 = f12 * 13
+ f14 = f13 * 14
+ f15 = f14 * 15
+ f16 = f15 * 16
+ f17 = f16 * 17
+ f18 = f17 * 18
+ f19 = f18 * 19
+ f20 = f19 * 20
+ f21 = f20 * 21
+ f22 = f21 * 22
+ f23 = f22 * 23
+ f24 = f23 * 24
+ f25 = f24 * 25
+ f26 = f25 * 26
+ f27 = f26 * 27
+ f28 = f27 * 28
+ f29 = f28 * 29
+ f30 = f29 * 30
+ f31 = f30 * 31
+ f32 = f31 * 32
+ f33 = f32 * 33
+ f34 = f33 * 34
+ f35 = f34 * 35
+ f36 = f35 * 36
+ f37 = f36 * 37
+ f38 = f37 * 38
+ f39 = f38 * 39
+ f40 = f39 * 40
+ f41 = f40 * 41
+ f42 = f41 * 42
+ f43 = f42 * 43
+ f44 = f43 * 44
+ f45 = f44 * 45
+ f46 = f45 * 46
+ f47 = f46 * 47
+ f48 = f47 * 48
+ f49 = f48 * 49
+ f50 = f49 * 50
+ f51 = f50 * 51
+ f52 = f51 * 52
+ f53 = f52 * 53
+ f54 = f53 * 54
+ f55 = f54 * 55
+ f56 = f55 * 56
+ f57 = f56 * 57
+ f58 = f57 * 58
+ f59 = f58 * 59
+ f60 = f59 * 60
+ f61 = f60 * 61
+ f62 = f61 * 62
+ f63 = f62 * 63
+ f64 = f63 * 64
+ f65 = f64 * 65
+ f66 = f65 * 66
+ f67 = f66 * 67
+ f68 = f67 * 68
+ f69 = f68 * 69
+ f70 = f69 * 70
+ f71 = f70 * 71
+ f72 = f71 * 72
+ f73 = f72 * 73
+ f74 = f73 * 74
+ f75 = f74 * 75
+ f76 = f75 * 76
+ f77 = f76 * 77
+ f78 = f77 * 78
+ f79 = f78 * 79
+ f80 = f79 * 80
+ f81 = f80 * 81
+ f82 = f81 * 82
+ f83 = f82 * 83
+ f84 = f83 * 84
+ f85 = f84 * 85
+ f86 = f85 * 86
+ f87 = f86 * 87
+ f88 = f87 * 88
+ f89 = f88 * 89
+ f90 = f89 * 90
+ f91 = f90 * 91
+ f92 = f91 * 92
+ f93 = f92 * 93
+ f94 = f93 * 94
+ f95 = f94 * 95
+ f96 = f95 * 96
+ f97 = f96 * 97
+ f98 = f97 * 98
+ f99 = f98 * 99 // GC_ERROR "overflow"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6899.go b/gcc/testsuite/go.test/test/fixedbugs/issue6899.go
index a693bf2..d7f8578 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue6899.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6899.go
@@ -1,6 +1,6 @@
-// cmpout
+// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6902.go b/gcc/testsuite/go.test/test/fixedbugs/issue6902.go
new file mode 100644
index 0000000..5c2c545
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6902.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 6902: confusing printing of large floating point constants
+
+package main
+
+import (
+ "os"
+)
+
+var x = -1e-10000
+
+func main() {
+ if x != 0 {
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6964.go b/gcc/testsuite/go.test/test/fixedbugs/issue6964.go
new file mode 100644
index 0000000..36a3c5b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6964.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ _ = string(-4 + 2i + 2) // ERROR "-4 \+ 2i|invalid type conversion"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue6977.go b/gcc/testsuite/go.test/test/fixedbugs/issue6977.go
new file mode 100644
index 0000000..4525e40
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue6977.go
@@ -0,0 +1,40 @@
+// errorcheck
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "io"
+
+// Alan's initial report.
+
+type I interface { f(); String() string }
+type J interface { g(); String() string }
+
+type IJ1 = interface { I; J }
+type IJ2 = interface { f(); g(); String() string }
+
+var _ = (*IJ1)(nil) == (*IJ2)(nil) // static assert that IJ1 and IJ2 are identical types
+
+// The canonical example.
+
+type ReadWriteCloser interface { io.ReadCloser; io.WriteCloser }
+
+// Some more cases.
+
+type M interface { m() }
+type M32 interface { m() int32 }
+type M64 interface { m() int64 }
+
+type U1 interface { m() }
+type U2 interface { m(); M }
+type U3 interface { M; m() }
+type U4 interface { M; M; M }
+type U5 interface { U1; U2; U3; U4 }
+
+type U6 interface { m(); m() } // ERROR "duplicate method .*m"
+type U7 interface { M32; m() } // ERROR "duplicate method .*m"
+type U8 interface { m(); M32 } // ERROR "duplicate method .*m"
+type U9 interface { M32; M64 } // ERROR "duplicate method .*m"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/a.go
new file mode 100644
index 0000000..cdb5432
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/a.go
@@ -0,0 +1,10 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func Foo() {
+ goto bar
+bar:
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/b.go
new file mode 100644
index 0000000..c6fe40d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7023.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import (
+ "./a"
+)
+
+var f = a.Foo
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7023.go b/gcc/testsuite/go.test/test/fixedbugs/issue7023.go
new file mode 100644
index 0000000..f18c611
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7023.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7023: corrupted export data when an inlined function
+// contains a goto.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7044.go b/gcc/testsuite/go.test/test/fixedbugs/issue7044.go
new file mode 100644
index 0000000..00c78c8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7044.go
@@ -0,0 +1,43 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7044: bad AMOVFD and AMOVDF assembly generation on
+// arm for registers above 7.
+
+package main
+
+import (
+ "fmt"
+ "reflect"
+)
+
+func f() [16]float32 {
+ f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15 :=
+ float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)
+ // Use all 16 registers to do float32 --> float64 conversion.
+ d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 :=
+ float64(f0), float64(f1), float64(f2), float64(f3), float64(f4), float64(f5), float64(f6), float64(f7), float64(f8), float64(f9), float64(f10), float64(f11), float64(f12), float64(f13), float64(f14), float64(f15)
+ // Use all 16 registers to do float64 --> float32 conversion.
+ g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12, g13, g14, g15 :=
+ float32(d0), float32(d1), float32(d2), float32(d3), float32(d4), float32(d5), float32(d6), float32(d7), float32(d8), float32(d9), float32(d10), float32(d11), float32(d12), float32(d13), float32(d14), float32(d15)
+ // Force another conversion, so that the previous conversion doesn't
+ // get optimized away into constructing the returned array. With current
+ // optimizations, constructing the returned array uses only
+ // a single register.
+ e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15 :=
+ float64(g0), float64(g1), float64(g2), float64(g3), float64(g4), float64(g5), float64(g6), float64(g7), float64(g8), float64(g9), float64(g10), float64(g11), float64(g12), float64(g13), float64(g14), float64(g15)
+ return [16]float32{
+ float32(e0), float32(e1), float32(e2), float32(e3), float32(e4), float32(e5), float32(e6), float32(e7), float32(e8), float32(e9), float32(e10), float32(e11), float32(e12), float32(e13), float32(e14), float32(e15),
+ }
+}
+
+func main() {
+ want := [16]float32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+ got := f()
+ if !reflect.DeepEqual(got, want) {
+ fmt.Printf("f() = %#v; want %#v\n", got, want)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7050.go b/gcc/testsuite/go.test/test/fixedbugs/issue7050.go
new file mode 100644
index 0000000..be7a118
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7050.go
@@ -0,0 +1,19 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ _, err := os.Stdout.Write(nil)
+ if err != nil {
+ fmt.Printf("BUG: os.Stdout.Write(nil) = %v\n", err)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7083.go b/gcc/testsuite/go.test/test/fixedbugs/issue7083.go
new file mode 100644
index 0000000..79bfd3b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7083.go
@@ -0,0 +1,22 @@
+// run
+
+package main
+
+import "runtime/debug"
+
+func f(m map[int]*string, i int) {
+ s := ""
+ m[i] = &s
+}
+
+func main() {
+ debug.SetGCPercent(0)
+ m := map[int]*string{}
+ for i := 0; i < 40; i++ {
+ f(m, i)
+ if len(*m[i]) != 0 {
+ println("bad length", i, m[i], len(*m[i]))
+ panic("bad length")
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7129.go b/gcc/testsuite/go.test/test/fixedbugs/issue7129.go
new file mode 100644
index 0000000..2765200
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7129.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7129: inconsistent "wrong arg type" error for multivalued g in f(g())
+
+package main
+
+func f(int) {}
+
+func g() bool { return true }
+
+func h(int, int) {}
+
+func main() {
+ f(g()) // ERROR "in argument to f|incompatible type"
+ f(true) // ERROR "in argument to f|incompatible type"
+ h(true, true) // ERROR "in argument to h|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7150.go b/gcc/testsuite/go.test/test/fixedbugs/issue7150.go
new file mode 100644
index 0000000..7cddf48
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7150.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 7150: array index out of bounds error off by one
+
+package main
+
+func main() {
+ _ = [0]int{-1: 50} // ERROR "index must be non-negative integer constant|index expression is negative"
+ _ = [0]int{0: 0} // ERROR "index 0 out of bounds \[0:0\]|out of range"
+ _ = [0]int{5: 25} // ERROR "index 5 out of bounds \[0:0\]|out of range"
+ _ = [10]int{2: 10, 15: 30} // ERROR "index 15 out of bounds \[0:10\]|out of range"
+ _ = [10]int{5: 5, 1: 1, 12: 12} // ERROR "index 12 out of bounds \[0:10\]|out of range"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7153.go b/gcc/testsuite/go.test/test/fixedbugs/issue7153.go
new file mode 100644
index 0000000..e8b95d5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7153.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7153: array invalid index error duplicated on successive bad values
+
+package p
+
+var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type untyped bool\) as type int in slice literal|undefined name .*a|incompatible type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7223.go b/gcc/testsuite/go.test/test/fixedbugs/issue7223.go
new file mode 100644
index 0000000..0ec3476
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7223.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var bits1 uint = 10
+const bits2 uint = 10
+
+func main() {
+ _ = make([]byte, 1<<bits1)
+ _ = make([]byte, 1<<bits2)
+ _ = make([]byte, nil) // ERROR "non-integer.*len"
+ _ = make([]byte, nil, 2) // ERROR "non-integer.*len"
+ _ = make([]byte, 1, nil) // ERROR "non-integer.*cap"
+ _ = make([]byte, true) // ERROR "non-integer.*len"
+ _ = make([]byte, "abc") // ERROR "non-integer.*len"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7272.go b/gcc/testsuite/go.test/test/fixedbugs/issue7272.go
new file mode 100644
index 0000000..b10a8bf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7272.go
@@ -0,0 +1,48 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7272: test builtin functions in statement context and in
+// go/defer functions.
+
+package p
+
+func F() {
+ var a []int
+ var c chan int
+ var m map[int]int
+
+ close(c)
+ copy(a, a)
+ delete(m, 0)
+ panic(0)
+ print("foo")
+ println("bar")
+ recover()
+
+ (close(c))
+ (copy(a, a))
+ (delete(m, 0))
+ (panic(0))
+ (print("foo"))
+ (println("bar"))
+ (recover())
+
+ go close(c)
+ go copy(a, a)
+ go delete(m, 0)
+ go panic(0)
+ go print("foo")
+ go println("bar")
+ go recover()
+
+ defer close(c)
+ defer copy(a, a)
+ defer delete(m, 0)
+ defer panic(0)
+ defer print("foo")
+ defer println("bar")
+ defer recover()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7310.go b/gcc/testsuite/go.test/test/fixedbugs/issue7310.go
new file mode 100644
index 0000000..ba50e42
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7310.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Internal compiler crash used to stop errors during second copy.
+
+package main
+
+func main() {
+ _ = copy(nil, []int{}) // ERROR "use of untyped nil|left argument must be a slice"
+ _ = copy([]int{}, nil) // ERROR "use of untyped nil|second argument must be slice or string"
+ _ = 1 + true // ERROR "mismatched types untyped int and untyped bool|incompatible types"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7316.go b/gcc/testsuite/go.test/test/fixedbugs/issue7316.go
new file mode 100644
index 0000000..0734641
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7316.go
@@ -0,0 +1,37 @@
+// runoutput
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7316
+// This test exercises all types of numeric conversions, which was one
+// of the sources of etype mismatch during register allocation in 8g.
+
+package main
+
+import "fmt"
+
+const tpl = `
+func init() {
+ var i %s
+ j := %s(i)
+ _ = %s(j)
+}
+`
+
+func main() {
+ fmt.Println("package main")
+ ntypes := []string{
+ "byte", "rune", "uintptr",
+ "float32", "float64",
+ "int", "int8", "int16", "int32", "int64",
+ "uint", "uint8", "uint16", "uint32", "uint64",
+ }
+ for i, from := range ntypes {
+ for _, to := range ntypes[i:] {
+ fmt.Printf(tpl, from, to, from)
+ }
+ }
+ fmt.Println("func main() {}")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7346.go b/gcc/testsuite/go.test/test/fixedbugs/issue7346.go
new file mode 100644
index 0000000..21fab2d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7346.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 7346 : internal error "doasm" error due to checknil
+// of a nil literal.
+
+package main
+
+func main() {
+ _ = *(*int)(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7366.go b/gcc/testsuite/go.test/test/fixedbugs/issue7366.go
new file mode 100644
index 0000000..a6b786f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7366.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 7366: generates a temporary with ideal type
+// during comparison of small structs.
+
+package main
+
+type T struct {
+ data [10]byte
+}
+
+func main() {
+ var a T
+ var b T
+ if a == b {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7405.go b/gcc/testsuite/go.test/test/fixedbugs/issue7405.go
new file mode 100644
index 0000000..52e1176
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7405.go
@@ -0,0 +1,51 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7405: the equality function for struct with many
+// embedded fields became more complex after fixing issue 7366,
+// leading to out of registers on 386.
+
+package p
+
+type T1 struct {
+ T2
+ T3
+ T4
+}
+
+type T2 struct {
+ Conn
+}
+
+type T3 struct {
+ PacketConn
+}
+
+type T4 struct {
+ PacketConn
+ T5
+}
+
+type T5 struct {
+ x int
+ T6
+}
+
+type T6 struct {
+ y, z int
+}
+
+type Conn interface {
+ A()
+}
+
+type PacketConn interface {
+ B()
+}
+
+func F(a, b T1) bool {
+ return a == b
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7419.go b/gcc/testsuite/go.test/test/fixedbugs/issue7419.go
new file mode 100644
index 0000000..39b454c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7419.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7419: odd behavior for float constants underflowing to 0
+
+package main
+
+import (
+ "os"
+)
+
+var x = 1e-779137
+var y = 1e-779138
+
+func main() {
+ if x != 0 {
+ os.Exit(1)
+ }
+ if y != 0 {
+ os.Exit(2)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7538a.go b/gcc/testsuite/go.test/test/fixedbugs/issue7538a.go
new file mode 100644
index 0000000..b170150
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7538a.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7538: blank (_) labels handled incorrectly
+
+package p
+
+func f() {
+_:
+_:
+ goto _ // ERROR "not defined|undefined label"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7538b.go b/gcc/testsuite/go.test/test/fixedbugs/issue7538b.go
new file mode 100644
index 0000000..28cef5d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7538b.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7538: blank (_) labels handled incorrectly
+
+package p
+
+func f() {
+_:
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7547.go b/gcc/testsuite/go.test/test/fixedbugs/issue7547.go
new file mode 100644
index 0000000..f75a330
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7547.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f() map[string]interface{} {
+ var p *map[string]map[string]interface{}
+ _ = p
+ return nil
+}
+
+func main() {
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7550.go b/gcc/testsuite/go.test/test/fixedbugs/issue7550.go
new file mode 100644
index 0000000..0c4cf93
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7550.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("not panicking")
+ }
+ }()
+ f()
+}
+
+func f() {
+ length := int(^uint(0) >> 1)
+ a := make([]struct{}, length)
+ b := make([]struct{}, length)
+ _ = append(a, b...)
+}
+
+func main() {
+ shouldPanic(f)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7590.go b/gcc/testsuite/go.test/test/fixedbugs/issue7590.go
new file mode 100644
index 0000000..607a3ae
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7590.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7590: gccgo incorrectly traverses nested composite literals.
+
+package p
+
+type S struct {
+ F int
+}
+
+var M = map[string]S{
+ "a": { F: 1 },
+}
+
+var P = M["a"]
+
+var F = P.F
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/a.go
new file mode 100644
index 0000000..c76aaa6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+const (
+ sinPi4 = 0.70710678118654752440084436210484903928483593768847
+ A = complex(sinPi4, -sinPi4)
+)
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/b.go
new file mode 100644
index 0000000..b9223ed
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7648.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+func f() {
+ println(a.A)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7648.go b/gcc/testsuite/go.test/test/fixedbugs/issue7648.go
new file mode 100644
index 0000000..b391c4a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7648.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7648: spurious "bad negated constant" for complex constants.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7740.go b/gcc/testsuite/go.test/test/fixedbugs/issue7740.go
new file mode 100644
index 0000000..8f1afe8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7740.go
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test computes the precision of the compiler's internal multiprecision floats.
+
+package main
+
+import (
+ "fmt"
+ "math"
+ "runtime"
+)
+
+const ulp = (1.0 + (2.0 / 3.0)) - (5.0 / 3.0)
+
+func main() {
+ // adjust precision depending on compiler
+ var prec float64
+ switch runtime.Compiler {
+ case "gc":
+ prec = 512
+ case "gccgo":
+ prec = 256
+ default:
+ // unknown compiler
+ return
+ }
+ p := 1 - math.Log(math.Abs(ulp))/math.Log(2)
+ if math.Abs(p-prec) > 1e-10 {
+ fmt.Printf("BUG: got %g; want %g\n", p, prec)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7742.go b/gcc/testsuite/go.test/test/fixedbugs/issue7742.go
new file mode 100644
index 0000000..dc167c2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7742.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7742: cannot use &autotmp_0001 (type *map[string]string) as type *string in function argument
+
+package main
+
+var (
+ m map[string]string
+ v string
+)
+
+func main() {
+ m[v], _ = v, v
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7746.go b/gcc/testsuite/go.test/test/fixedbugs/issue7746.go
new file mode 100644
index 0000000..7454962
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7746.go
@@ -0,0 +1,133 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+const (
+ c0 = 1 << 100
+ c1 = c0 * c0
+ c2 = c1 * c1
+ c3 = c2 * c2 // GC_ERROR "overflow"
+ c4 = c3 * c3
+ c5 = c4 * c4
+ c6 = c5 * c5
+ c7 = c6 * c6
+ c8 = c7 * c7
+ c9 = c8 * c8
+ c10 = c9 * c9
+ c11 = c10 * c10
+ c12 = c11 * c11
+ c13 = c12 * c12
+ c14 = c13 * c13 // GCCGO_ERROR "overflow"
+ c15 = c14 * c14
+ c16 = c15 * c15
+ c17 = c16 * c16
+ c18 = c17 * c17
+ c19 = c18 * c18
+ c20 = c19 * c19
+ c21 = c20 * c20
+ c22 = c21 * c21
+ c23 = c22 * c22
+ c24 = c23 * c23
+ c25 = c24 * c24
+ c26 = c25 * c25
+ c27 = c26 * c26
+ c28 = c27 * c27
+ c29 = c28 * c28
+ c30 = c29 * c29
+ c31 = c30 * c30
+ c32 = c31 * c31
+ c33 = c32 * c32
+ c34 = c33 * c33
+ c35 = c34 * c34
+ c36 = c35 * c35
+ c37 = c36 * c36
+ c38 = c37 * c37
+ c39 = c38 * c38
+ c40 = c39 * c39
+ c41 = c40 * c40
+ c42 = c41 * c41
+ c43 = c42 * c42
+ c44 = c43 * c43
+ c45 = c44 * c44
+ c46 = c45 * c45
+ c47 = c46 * c46
+ c48 = c47 * c47
+ c49 = c48 * c48
+ c50 = c49 * c49
+ c51 = c50 * c50
+ c52 = c51 * c51
+ c53 = c52 * c52
+ c54 = c53 * c53
+ c55 = c54 * c54
+ c56 = c55 * c55
+ c57 = c56 * c56
+ c58 = c57 * c57
+ c59 = c58 * c58
+ c60 = c59 * c59
+ c61 = c60 * c60
+ c62 = c61 * c61
+ c63 = c62 * c62
+ c64 = c63 * c63
+ c65 = c64 * c64
+ c66 = c65 * c65
+ c67 = c66 * c66
+ c68 = c67 * c67
+ c69 = c68 * c68
+ c70 = c69 * c69
+ c71 = c70 * c70
+ c72 = c71 * c71
+ c73 = c72 * c72
+ c74 = c73 * c73
+ c75 = c74 * c74
+ c76 = c75 * c75
+ c77 = c76 * c76
+ c78 = c77 * c77
+ c79 = c78 * c78
+ c80 = c79 * c79
+ c81 = c80 * c80
+ c82 = c81 * c81
+ c83 = c82 * c82
+ c84 = c83 * c83
+ c85 = c84 * c84
+ c86 = c85 * c85
+ c87 = c86 * c86
+ c88 = c87 * c87
+ c89 = c88 * c88
+ c90 = c89 * c89
+ c91 = c90 * c90
+ c92 = c91 * c91
+ c93 = c92 * c92
+ c94 = c93 * c93
+ c95 = c94 * c94
+ c96 = c95 * c95
+ c97 = c96 * c96
+ c98 = c97 * c97
+ c99 = c98 * c98
+ c100 = c99 * c99
+)
+
+func main() {
+ println(c1 / c1)
+ println(c2 / c2)
+ println(c3 / c3)
+ println(c4 / c4)
+ println(c5 / c5)
+ println(c6 / c6)
+ println(c7 / c7)
+ println(c8 / c8)
+ println(c9 / c9)
+ println(c10 / c10)
+ println(c20 / c20)
+ println(c30 / c30)
+ println(c40 / c40)
+ println(c50 / c50)
+ println(c60 / c60)
+ println(c70 / c70)
+ println(c80 / c80)
+ println(c90 / c90)
+ println(c100 / c100)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7760.go b/gcc/testsuite/go.test/test/fixedbugs/issue7760.go
new file mode 100644
index 0000000..7e1d035
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7760.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that pointers can't be used as constants.
+
+package main
+
+import "unsafe"
+
+type myPointer unsafe.Pointer
+
+const _ = unsafe.Pointer(uintptr(1)) // ERROR "is not (a )?constant|invalid constant type"
+const _ = myPointer(uintptr(1)) // ERROR "is not (a )?constant|invalid constant type"
+
+const _ = (*int)(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant|invalid constant type"
+const _ = (*int)(myPointer(uintptr(1))) // ERROR "is not (a )?constant|invalid constant type"
+
+const _ = uintptr(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant|expression is not constant"
+const _ = uintptr(myPointer(uintptr(1))) // ERROR "is not (a )?constant|expression is no constant"
+
+const _ = []byte("") // ERROR "is not (a )?constant|invalid constant type"
+const _ = []rune("") // ERROR "is not (a )?constant|invalid constant type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7794.go b/gcc/testsuite/go.test/test/fixedbugs/issue7794.go
new file mode 100644
index 0000000..f31de94
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7794.go
@@ -0,0 +1,12 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var a [10]int
+ const ca = len(a)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7863.go b/gcc/testsuite/go.test/test/fixedbugs/issue7863.go
new file mode 100644
index 0000000..da2ed05
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7863.go
@@ -0,0 +1,60 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+type Foo int64
+
+func (f *Foo) F() int64 {
+ return int64(*f)
+}
+
+type Bar int64
+
+func (b Bar) F() int64 {
+ return int64(b)
+}
+
+type Baz int32
+
+func (b Baz) F() int64 {
+ return int64(b)
+}
+
+func main() {
+ foo := Foo(123)
+ f := foo.F
+ if foo.F() != f() {
+ bug()
+ fmt.Println("foo.F", foo.F(), f())
+ }
+ bar := Bar(123)
+ f = bar.F
+ if bar.F() != f() {
+ bug()
+ fmt.Println("bar.F", bar.F(), f()) // duh!
+ }
+
+ baz := Baz(123)
+ f = baz.F
+ if baz.F() != f() {
+ bug()
+ fmt.Println("baz.F", baz.F(), f())
+ }
+}
+
+var bugged bool
+
+func bug() {
+ if !bugged {
+ bugged = true
+ fmt.Println("BUG")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7867.go b/gcc/testsuite/go.test/test/fixedbugs/issue7867.go
new file mode 100644
index 0000000..166506e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7867.go
@@ -0,0 +1,43 @@
+// runoutput
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7867.
+
+package main
+
+import "fmt"
+
+const tpl = `
+func Test%d(t %s) {
+ _ = t
+ _ = t
+}
+`
+
+func main() {
+ fmt.Println("package main")
+ types := []string{
+ // These types always passed
+ "bool", "int", "rune",
+ "*int", "uintptr",
+ "float32", "float64",
+ "chan struct{}",
+ "map[string]struct{}",
+ "func()", "func(string)error",
+
+ // These types caused compilation failures
+ "complex64", "complex128",
+ "struct{}", "struct{n int}", "struct{e error}", "struct{m map[string]string}",
+ "string",
+ "[4]byte",
+ "[]byte",
+ "interface{}", "error",
+ }
+ for i, typ := range types {
+ fmt.Printf(tpl, i, typ)
+ }
+ fmt.Println("func main() {}")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7884.go b/gcc/testsuite/go.test/test/fixedbugs/issue7884.go
new file mode 100644
index 0000000..ab7a858
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7884.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func main() {
+ var ii interface{} = 5
+ zz, err := ii.(interface{})
+ fmt.Println(zz, err)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7921.go b/gcc/testsuite/go.test/test/fixedbugs/issue7921.go
new file mode 100644
index 0000000..5dce557
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7921.go
@@ -0,0 +1,57 @@
+// +build !gcflags_noopt
+// errorcheck -0 -m
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+import "bytes"
+
+// In order to get desired results, we need a combination of
+// both escape analysis and inlining.
+
+func bufferNotEscape() string {
+ // b itself does not escape, only its buf field will be
+ // copied during String() call, but object "handle" itself
+ // can be stack-allocated.
+ var b bytes.Buffer
+ b.WriteString("123")
+ b.Write([]byte{'4'}) // ERROR "\[\]byte{...} does not escape$"
+ return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
+}
+
+func bufferNoEscape2(xs []string) int { // ERROR "xs does not escape$"
+ b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
+ for _, x := range xs {
+ b.WriteString(x)
+ }
+ return b.Len() // ERROR "inlining call to bytes.\(\*Buffer\).Len$"
+}
+
+func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$"
+ b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
+ for _, x := range xs {
+ b.WriteString(x)
+ b.WriteByte(',')
+ }
+ return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
+}
+
+func bufferNoEscape4() []byte {
+ var b bytes.Buffer
+ b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$"
+ useBuffer(&b)
+ return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$"
+}
+
+func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$"
+ b := bytes.NewBuffer(make([]byte, 0, 128)) // ERROR "&bytes.Buffer{...} does not escape$" "make\(\[\]byte, 0, 128\) does not escape$" "inlining call to bytes.NewBuffer$"
+ useBuffer(b)
+}
+
+//go:noinline
+func useBuffer(b *bytes.Buffer) { // ERROR "b does not escape$"
+ b.WriteString("1234")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7944.go b/gcc/testsuite/go.test/test/fixedbugs/issue7944.go
new file mode 100644
index 0000000..960065b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7944.go
@@ -0,0 +1,40 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7944:
+// Liveness bitmaps said b was live at call to g,
+// but no one told the register optimizer.
+
+package main
+
+import "runtime"
+
+func f(b []byte) {
+ for len(b) > 0 {
+ n := len(b)
+ n = f1(n)
+ f2(b[n:])
+ b = b[n:]
+ }
+ g()
+}
+
+func f1(n int) int {
+ runtime.GC()
+ return n
+}
+
+func f2(b []byte) {
+ runtime.GC()
+}
+
+func g() {
+ runtime.GC()
+}
+
+func main() {
+ f(make([]byte, 100))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7995.go b/gcc/testsuite/go.test/test/fixedbugs/issue7995.go
new file mode 100644
index 0000000..af77a6d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7995.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7995: globals not flushed quickly enough.
+
+package main
+
+import "fmt"
+
+var (
+ p = 1
+ q = &p
+)
+
+func main() {
+ p = 50
+ *q = 100
+ s := fmt.Sprintln(p, *q)
+ if s != "100 100\n" {
+ println("BUG:", s)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x1.go b/gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x1.go
new file mode 100644
index 0000000..bafecf5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x1.go
@@ -0,0 +1,12 @@
+package x1
+
+import "fmt"
+
+var P int
+
+//go:noinline
+func F(x *int) string {
+ P = 50
+ *x = 100
+ return fmt.Sprintln(P, *x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x2.go b/gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x2.go
new file mode 100644
index 0000000..eea23ea
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7995b.dir/x2.go
@@ -0,0 +1,10 @@
+package main
+
+import "./x1"
+
+func main() {
+ s := x1.F(&x1.P)
+ if s != "100 100\n" {
+ println("BUG:", s)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7995b.go b/gcc/testsuite/go.test/test/fixedbugs/issue7995b.go
new file mode 100644
index 0000000..2f57371
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7995b.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 7995: globals not flushed quickly enough.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7996.go b/gcc/testsuite/go.test/test/fixedbugs/issue7996.go
new file mode 100644
index 0000000..1ee6fc7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7996.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// /tmp/x.go:5: illegal constant expression: bool == interface {}
+
+package p
+
+var m = map[interface{}]struct{}{
+ nil: {},
+ true: {},
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7997.go b/gcc/testsuite/go.test/test/fixedbugs/issue7997.go
new file mode 100644
index 0000000..a342189
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7997.go
@@ -0,0 +1,53 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// /tmp/x.go:3: internal error: f &p (type *int) recorded as live on entry
+
+package p
+
+func f(ch chan int) *int {
+ select {
+ case p1x := <-ch:
+ return &p1x
+ default:
+ // ok
+ }
+ select {
+ case p1 := <-ch:
+ return &p1
+ default:
+ // ok
+ }
+ select {
+ case p2 := <-ch:
+ return &p2
+ case p3 := <-ch:
+ return &p3
+ default:
+ // ok
+ }
+ select {
+ case p4, ok := <-ch:
+ if ok {
+ return &p4
+ }
+ default:
+ // ok
+ }
+ select {
+ case p5, ok := <-ch:
+ if ok {
+ return &p5
+ }
+ case p6, ok := <-ch:
+ if !ok {
+ return &p6
+ }
+ default:
+ // ok
+ }
+ return nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue7998.go b/gcc/testsuite/go.test/test/fixedbugs/issue7998.go
new file mode 100644
index 0000000..8da39e8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue7998.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// /tmp/x.go:5: cannot use _ as value
+
+package p
+
+func f(ch chan int) bool {
+ select {
+ case _, ok := <-ch:
+ return ok
+ }
+ _, ok := <-ch
+ _ = ok
+ select {
+ case _, _ = <-ch:
+ return true
+ }
+ return false
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8004.go b/gcc/testsuite/go.test/test/fixedbugs/issue8004.go
new file mode 100644
index 0000000..548ee1c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8004.go
@@ -0,0 +1,59 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+func main() {
+ test1()
+ test2()
+}
+
+func test1() {
+ var all []interface{}
+ for i := 0; i < 100; i++ {
+ p := new([]int)
+ *p = append(*p, 1, 2, 3, 4)
+ h := (*reflect.SliceHeader)(unsafe.Pointer(p))
+ all = append(all, h, p)
+ }
+ runtime.GC()
+ for i := 0; i < 100; i++ {
+ p := *all[2*i+1].(*[]int)
+ if p[0] != 1 || p[1] != 2 || p[2] != 3 || p[3] != 4 {
+ println("BUG test1: bad slice at index", i, p[0], p[1], p[2], p[3])
+ return
+ }
+ }
+}
+
+type T struct {
+ H *reflect.SliceHeader
+ P *[]int
+}
+
+func test2() {
+ var all []T
+ for i := 0; i < 100; i++ {
+ p := new([]int)
+ *p = append(*p, 1, 2, 3, 4)
+ h := (*reflect.SliceHeader)(unsafe.Pointer(p))
+ all = append(all, T{H: h}, T{P: p})
+ }
+ runtime.GC()
+ for i := 0; i < 100; i++ {
+ p := *all[2*i+1].P
+ if p[0] != 1 || p[1] != 2 || p[2] != 3 || p[3] != 4 {
+ println("BUG test2: bad slice at index", i, p[0], p[1], p[2], p[3])
+ return
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8011.go b/gcc/testsuite/go.test/test/fixedbugs/issue8011.go
new file mode 100644
index 0000000..57af2a9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8011.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ c := make(chan chan int, 1)
+ c1 := make(chan int, 1)
+ c1 <- 42
+ c <- c1
+ x := <-<-c
+ if x != 42 {
+ println("BUG:", x, "!= 42")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8017.go b/gcc/testsuite/go.test/test/fixedbugs/issue8017.go
new file mode 100644
index 0000000..9afcdf0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8017.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issues 8017 and 8058: walk modifies nodes generated
+// by slicelit and causes an internal error afterwards
+// when gen_as_init parses it back.
+
+package main
+
+func F() {
+ var ch chan int
+ select {
+ case <-ch:
+ case <-make(chan int, len([2][]int{([][]int{})[len(ch)], []int{}})):
+ }
+}
+
+func G() {
+ select {
+ case <-([1][]chan int{[]chan int{}})[0][0]:
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8028.go b/gcc/testsuite/go.test/test/fixedbugs/issue8028.go
new file mode 100644
index 0000000..9f2649a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8028.go
@@ -0,0 +1,27 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8028. Used to fail in -race mode with "non-orig name" error.
+
+package p
+
+var (
+ t2 = T{F, "s1"}
+ t1 = T{F, "s2"}
+
+ tt = [...]T{t1, t2}
+)
+
+type I interface{}
+
+type T struct {
+ F func() I
+ S string
+}
+
+type E struct{}
+
+func F() I { return new(E) }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8036.go b/gcc/testsuite/go.test/test/fixedbugs/issue8036.go
new file mode 100644
index 0000000..82ba7f7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8036.go
@@ -0,0 +1,45 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8036. Stores necessary for stack scan being eliminated as redundant by optimizer.
+
+package main
+
+import "runtime"
+
+type T struct {
+ X *int
+ Y *int
+ Z *int
+}
+
+type TI [3]uintptr
+
+//go:noinline
+func G() (t TI) {
+ t[0] = 1
+ t[1] = 2
+ t[2] = 3
+ return
+}
+
+//go:noinline
+func F() (t T) {
+ t.X = newint()
+ t.Y = t.X
+ t.Z = t.Y
+ return
+}
+
+func newint() *int {
+ runtime.GC()
+ return nil
+}
+
+func main() {
+ G() // leave non-pointers where F's return values go
+ F()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8039.go b/gcc/testsuite/go.test/test/fixedbugs/issue8039.go
new file mode 100644
index 0000000..ee00c60
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8039.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 8039. defer copy(x, <-c) did not rewrite <-c properly.
+
+package main
+
+func f(s []int) {
+ c := make(chan []int, 1)
+ c <- []int{1}
+ defer copy(s, <-c)
+}
+
+func main() {
+ x := make([]int, 1)
+ f(x)
+ if x[0] != 1 {
+ println("BUG", x[0])
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8042.go b/gcc/testsuite/go.test/test/fixedbugs/issue8042.go
new file mode 100644
index 0000000..5639f97
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8042.go
@@ -0,0 +1,66 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that gotos across non-variable declarations
+// are accepted.
+
+package p
+
+func _() {
+ goto L1
+ const x = 0
+L1:
+ goto L2
+ type T int
+L2:
+}
+
+func _() {
+ {
+ goto L1
+ }
+ const x = 0
+L1:
+ {
+ goto L2
+ }
+ type T int
+L2:
+}
+
+func _(d int) {
+ if d > 0 {
+ goto L1
+ } else {
+ goto L2
+ }
+ const x = 0
+L1:
+ switch d {
+ case 1:
+ goto L3
+ case 2:
+ default:
+ goto L4
+ }
+ type T1 int
+L2:
+ const y = 1
+L3:
+ for d > 0 {
+ if d < 10 {
+ goto L4
+ }
+ }
+ type T2 int
+L4:
+ select {
+ default:
+ goto L5
+ }
+ type T3 int
+L5:
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8047.go b/gcc/testsuite/go.test/test/fixedbugs/issue8047.go
new file mode 100644
index 0000000..5ac4a0e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8047.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8047. Stack copier shouldn't crash if there
+// is a nil defer.
+
+package main
+
+func stackit(n int) {
+ if n == 0 {
+ return
+ }
+ stackit(n - 1)
+}
+
+func main() {
+ defer func() {
+ // catch & ignore panic from nil defer below
+ err := recover()
+ if err == nil {
+ panic("defer of nil func didn't panic")
+ }
+ }()
+ defer ((func())(nil))()
+ stackit(1000)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8047b.go b/gcc/testsuite/go.test/test/fixedbugs/issue8047b.go
new file mode 100644
index 0000000..5eaf9c5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8047b.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8047. Defer setup during panic shouldn't crash for nil defer.
+
+package main
+
+func main() {
+ defer func() {
+ // This recover recovers the panic caused by the nil defer func
+ // g(). The original panic(1) was already aborted/replaced by this
+ // new panic, so when this recover is done, the program completes
+ // normally.
+ recover()
+ }()
+ f()
+}
+
+func f() {
+ var g func()
+ defer g()
+ panic(1)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8048.go b/gcc/testsuite/go.test/test/fixedbugs/issue8048.go
new file mode 100644
index 0000000..577f606
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8048.go
@@ -0,0 +1,107 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8048. Incorrect handling of liveness when walking stack
+// containing faulting frame.
+
+package main
+
+import "runtime"
+
+func main() {
+ test1()
+ test2()
+ test3()
+}
+
+func test1() {
+ // test1f will panic without its own defer.
+ // The runtime.GC checks that we can walk the stack
+ // at that point and not get confused.
+ // The recover lets test1 exit normally.
+ defer func() {
+ runtime.GC()
+ recover()
+ }()
+ test1f()
+}
+
+func test1f() {
+ // Because b == false, the if does not execute,
+ // so x == nil, so the println(*x) faults reading
+ // from nil. The compiler will lay out the code
+ // so that the if body occurs above the *x,
+ // so if the liveness info at the *x is used, it will
+ // find the liveness at the call to runtime.GC.
+ // It will think y is live, but y is uninitialized,
+ // and the runtime will crash detecting a bad slice.
+ // The runtime should see that there are no defers
+ // corresponding to this panicked frame and ignore
+ // the frame entirely.
+ var x *int
+ var b bool
+ if b {
+ y := make([]int, 1)
+ runtime.GC()
+ x = &y[0]
+ }
+ println(*x)
+}
+
+func test2() {
+ // Same as test1, but the fault happens in the function with the defer.
+ // The runtime should see the defer and garbage collect the frame
+ // as if the PC were immediately after the defer statement.
+ defer func() {
+ runtime.GC()
+ recover()
+ }()
+ var x *int
+ var b bool
+ if b {
+ y := make([]int, 1)
+ runtime.GC()
+ x = &y[0]
+ }
+ println(*x)
+}
+
+func test3() {
+ // Like test1 but avoid array index, which does not
+ // move to end of function on ARM.
+ defer func() {
+ runtime.GC()
+ recover()
+ }()
+ test3setup()
+ test3f()
+}
+
+func test3setup() {
+ var x uintptr
+ var b bool
+ b = true
+ if b {
+ y := uintptr(123)
+ runtime.GC()
+ x = y
+ }
+ runtime.GC()
+ globl = x
+}
+
+var globl uintptr
+
+func test3f() {
+ var x *int
+ var b bool
+ if b {
+ y := new(int)
+ runtime.GC()
+ x = y
+ }
+ println(*x)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/a.go
new file mode 100644
index 0000000..22ba69e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var A = []*[2][1]float64{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/b.go
new file mode 100644
index 0000000..85fb6ec
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8060.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+var X = a.A
+
+func b() {
+ _ = [3][1]float64{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8060.go b/gcc/testsuite/go.test/test/fixedbugs/issue8060.go
new file mode 100644
index 0000000..ec52659
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8060.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8060: internal compiler error.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8073.go b/gcc/testsuite/go.test/test/fixedbugs/issue8073.go
new file mode 100644
index 0000000..d47481c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8073.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 8073.
+// was "internal compiler error: overflow: float64 integer constant"
+
+package main
+
+func main() {
+ var x int
+ _ = float64(x * 0)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8074.go b/gcc/testsuite/go.test/test/fixedbugs/issue8074.go
new file mode 100644
index 0000000..604a4f9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8074.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 8074.
+// was "cannot take the address of 1"
+
+package main
+
+func main() {
+ a := make([]byte, 10)
+ m := make(map[float64][]byte)
+ go copy(a, m[1.0])
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8076.go b/gcc/testsuite/go.test/test/fixedbugs/issue8076.go
new file mode 100644
index 0000000..543ccc1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8076.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8076. nilwalkfwd walked forward forever
+// on the instruction loop following the dereference.
+
+package main
+
+func main() {
+ _ = *(*int)(nil)
+L:
+ _ = 0
+ goto L
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8079.go b/gcc/testsuite/go.test/test/fixedbugs/issue8079.go
new file mode 100644
index 0000000..994999b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8079.go
@@ -0,0 +1,11 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8079: gccgo crashes when compiling interface with blank type name.
+
+package p
+
+type _ interface{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8132.go b/gcc/testsuite/go.test/test/fixedbugs/issue8132.go
new file mode 100644
index 0000000..b28a84c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8132.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 8132. stack walk handling of panic stack was confused
+// about what was legal.
+
+package main
+
+import "runtime"
+
+var p *int
+
+func main() {
+ func() {
+ defer func() {
+ runtime.GC()
+ recover()
+ }()
+ var x [8192]byte
+ func(x [8192]byte) {
+ defer func() {
+ if err := recover(); err != nil {
+ println(*p)
+ }
+ }()
+ println(*p)
+ }(x)
+ }()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8139.go b/gcc/testsuite/go.test/test/fixedbugs/issue8139.go
new file mode 100644
index 0000000..6e5607d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8139.go
@@ -0,0 +1,50 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8139. The x.(T) assertions used to write 1 (unexpected)
+// return byte for the 0-byte return value T.
+
+package main
+
+import "fmt"
+
+type T struct{}
+
+func (T) M() {}
+
+type M interface {
+ M()
+}
+
+var e interface{} = T{}
+var i M = T{}
+var b bool
+
+func f1() int {
+ if b {
+ return f1() // convince inliner not to inline
+ }
+ z := 0x11223344
+ _ = e.(T)
+ return z
+}
+
+func f2() int {
+ if b {
+ return f1() // convince inliner not to inline
+ }
+ z := 0x11223344
+ _ = i.(T)
+ return z
+}
+
+func main() {
+ x := f1()
+ y := f2()
+ if x != 0x11223344 || y != 0x11223344 {
+ fmt.Printf("BUG: x=%#x y=%#x, want 0x11223344 for both\n", x, y)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8154.go b/gcc/testsuite/go.test/test/fixedbugs/issue8154.go
new file mode 100644
index 0000000..3ffad34
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8154.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8154: cmd/5g: ICE in walkexpr walk.c
+
+package main
+
+func main() {
+ c := make(chan int)
+ _ = [1][]func(){[]func(){func() { <-c }}}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8155.go b/gcc/testsuite/go.test/test/fixedbugs/issue8155.go
new file mode 100644
index 0000000..56a6738
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8155.go
@@ -0,0 +1,48 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8155.
+// Alignment of stack prologue zeroing was wrong on 64-bit Native Client
+// (because of 32-bit pointers).
+
+package main
+
+import "runtime"
+
+func bad(b bool) uintptr {
+ var p **int
+ var x1 uintptr
+ x1 = 1
+ if b {
+ var x [11]*int
+ p = &x[0]
+ }
+ if b {
+ var x [1]*int
+ p = &x[0]
+ }
+ runtime.GC()
+ if p != nil {
+ x1 = uintptr(**p)
+ }
+ return x1
+}
+
+func poison() uintptr {
+ runtime.GC()
+ var x [20]uintptr
+ var s uintptr
+ for i := range x {
+ x[i] = uintptr(i+1)
+ s += x[i]
+ }
+ return s
+}
+
+func main() {
+ poison()
+ bad(false)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8158.go b/gcc/testsuite/go.test/test/fixedbugs/issue8158.go
new file mode 100644
index 0000000..150b338
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8158.go
@@ -0,0 +1,41 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+ "time"
+)
+
+func main() {
+ c := make(chan bool, 1)
+ go f1(c)
+ <-c
+ time.Sleep(10 * time.Millisecond)
+ go f2(c)
+ <-c
+}
+
+func f1(done chan bool) {
+ defer func() {
+ recover()
+ done <- true
+ runtime.Goexit() // left stack-allocated Panic struct on gp->panic stack
+ }()
+ panic("p")
+}
+
+func f2(done chan bool) {
+ defer func() {
+ recover()
+ done <- true
+ runtime.Goexit()
+ }()
+ time.Sleep(10 * time.Millisecond) // overwrote Panic struct with Timer struct
+ runtime.GC() // walked gp->panic list, found mangled Panic struct, crashed
+ panic("p")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8183.go b/gcc/testsuite/go.test/test/fixedbugs/issue8183.go
new file mode 100644
index 0000000..caac667
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8183.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests correct reporting of line numbers for errors involving iota,
+// Issue #8183.
+package foo
+
+const (
+ ok = byte(iota + 253)
+ bad
+ barn
+ bard // ERROR "constant 256 overflows byte|integer constant overflow"
+)
+
+const (
+ c = len([1 - iota]int{})
+ d
+ e // ERROR "array bound must be non-negative|negative array bound"
+ f // ERROR "array bound must be non-negative|negative array bound"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/a.go
new file mode 100644
index 0000000..588536e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/a.go
@@ -0,0 +1,3 @@
+package a
+
+var Bar = func() (_ int) { return 0 }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/b.go
new file mode 100644
index 0000000..c46c554
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8280.dir/b.go
@@ -0,0 +1,5 @@
+package b
+
+import "./a"
+
+var foo = a.Bar
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8280.go b/gcc/testsuite/go.test/test/fixedbugs/issue8280.go
new file mode 100644
index 0000000..91256c8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8280.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8280: cannot import package exporting a func var returning a result named _
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8311.go b/gcc/testsuite/go.test/test/fixedbugs/issue8311.go
new file mode 100644
index 0000000..b5fd5da
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8311.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 8311.
+// error for x++ should say x++ not x += 1
+
+package p
+
+func f() {
+ var x []byte
+ x++ // ERROR "invalid operation: x[+][+]|non-numeric type"
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8325.go b/gcc/testsuite/go.test/test/fixedbugs/issue8325.go
new file mode 100644
index 0000000..6b0fc25
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8325.go
@@ -0,0 +1,31 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8325: corrupted byte operations during optimization
+// pass.
+
+package main
+
+const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+func main() {
+ var bytes = []byte{10, 20, 30, 40, 50}
+
+ for i, b := range bytes {
+ bytes[i] = alphanum[b%byte(len(alphanum))]
+ }
+
+ for _, b := range bytes {
+ switch {
+ case '0' <= b && b <= '9',
+ 'A' <= b && b <= 'Z':
+ default:
+ println("found a bad character", string(b))
+ panic("BUG")
+ }
+
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8336.go b/gcc/testsuite/go.test/test/fixedbugs/issue8336.go
new file mode 100644
index 0000000..419fdf1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8336.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8336. Order of evaluation of receive channels in select.
+
+package main
+
+type X struct {
+ c chan int
+}
+
+func main() {
+ defer func() {
+ recover()
+ }()
+ var x *X
+ select {
+ case <-x.c: // should fault and panic before foo is called
+ case <-foo():
+ }
+}
+
+func foo() chan int {
+ println("BUG: foo must not be called")
+ return make(chan int)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8347.go b/gcc/testsuite/go.test/test/fixedbugs/issue8347.go
new file mode 100644
index 0000000..6394a95
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8347.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ c := make(chan bool, 1)
+ ok := true
+ for i := 0; i < 12; i++ {
+ select {
+ case _, ok = <-c:
+ if i < 10 && !ok {
+ panic("BUG")
+ }
+ default:
+ }
+ if i < 10 && !ok {
+ panic("BUG")
+ }
+ if i >= 10 && ok {
+ close(c)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8385.go b/gcc/testsuite/go.test/test/fixedbugs/issue8385.go
new file mode 100644
index 0000000..f3d395e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8385.go
@@ -0,0 +1,42 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8385: provide a more descriptive error when a method expression
+// is called without a receiver.
+
+package main
+
+type Fooer interface {
+ Foo(i, j int)
+}
+
+func f(x int) {
+}
+
+type I interface {
+ M(int)
+}
+type T struct{}
+
+func (t T) M(x int) {
+}
+
+func g() func(int)
+
+func main() {
+ Fooer.Foo(5, 6) // ERROR "not enough arguments in call to method expression Fooer.Foo|incompatible type|not enough arguments"
+
+ var i I
+ var t *T
+
+ g()() // ERROR "not enough arguments in call to g\(\)|not enough arguments"
+ f() // ERROR "not enough arguments in call to f|not enough arguments"
+ i.M() // ERROR "not enough arguments in call to i\.M|not enough arguments"
+ I.M() // ERROR "not enough arguments in call to method expression I\.M|not enough arguments"
+ t.M() // ERROR "not enough arguments in call to t\.M|not enough arguments"
+ T.M() // ERROR "not enough arguments in call to method expression T\.M|not enough arguments"
+ (*T).M() // ERROR "not enough arguments in call to method expression \(\*T\)\.M|not enough arguments"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8438.go b/gcc/testsuite/go.test/test/fixedbugs/issue8438.go
new file mode 100644
index 0000000..f433e36
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8438.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that we don't print duplicate errors for string ->
+// array-literal conversion
+
+package main
+
+func main() {
+ _ = []byte{"foo"} // ERROR "cannot use|incompatible type"
+ _ = []int{"foo"} // ERROR "cannot use|incompatible type"
+ _ = []rune{"foo"} // ERROR "cannot use|incompatible type"
+ _ = []string{"foo"} // OK
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8440.go b/gcc/testsuite/go.test/test/fixedbugs/issue8440.go
new file mode 100644
index 0000000..e9c5b54
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8440.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ n.foo = 6 // ERROR "undefined: n in n.foo|undefined name .*n"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8475.go b/gcc/testsuite/go.test/test/fixedbugs/issue8475.go
new file mode 100644
index 0000000..5b22067
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8475.go
@@ -0,0 +1,25 @@
+// build
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8745: comma-ok assignments should produce untyped bool as 2nd result.
+
+package main
+
+type mybool bool
+
+func main() {
+ var ok mybool
+ _ = ok
+
+ var i interface{}
+ _, ok = i.(int)
+
+ var m map[int]int
+ _, ok = m[0]
+
+ var c chan int
+ _, ok = <-c
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8501.go b/gcc/testsuite/go.test/test/fixedbugs/issue8501.go
new file mode 100644
index 0000000..90ba096
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8501.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct {
+ f float64
+}
+
+var t T
+
+func F() {
+ _ = complex(1.0) // ERROR "invalid operation|not enough arguments"
+ _ = complex(t.f) // ERROR "invalid operation|not enough arguments"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8613.go b/gcc/testsuite/go.test/test/fixedbugs/issue8613.go
new file mode 100644
index 0000000..ffa75a4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8613.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var out int
+var zero int
+
+func main() {
+ wantPanic("test1", func() {
+ out = 1 / zero
+ })
+ wantPanic("test2", func() {
+ _ = 1 / zero
+ })
+ wantPanic("test3", func() {
+ v := 0
+ _ = 1 / v
+ })
+ wantPanic("test4", func() { divby(0) })
+}
+
+func wantPanic(test string, fn func()) {
+ defer func() {
+ if e := recover(); e == nil {
+ panic(test + ": expected panic")
+ }
+ }()
+ fn()
+}
+
+//go:noinline
+func divby(v int) {
+ _ = 1 / v
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8620.go b/gcc/testsuite/go.test/test/fixedbugs/issue8620.go
new file mode 100644
index 0000000..4754604
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8620.go
@@ -0,0 +1,30 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8620. Used to fail with -race.
+
+package main
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func test(s1, s2 []struct{}) {
+ n := min(len(s1), len(s2))
+ if copy(s1, s2) != n {
+ panic("bad copy result")
+ }
+}
+
+func main() {
+ var b [100]struct{}
+ test(b[:], b[:])
+ test(b[1:], b[:])
+ test(b[:], b[2:])
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8745.go b/gcc/testsuite/go.test/test/fixedbugs/issue8745.go
new file mode 100644
index 0000000..fee2ca7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8745.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that the error says s[2] is a byte, not a uint8.
+
+package p
+
+func f(s string) {
+ var _ float64 = s[2] // ERROR "cannot use.*type byte.*as type float64"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8761.go b/gcc/testsuite/go.test/test/fixedbugs/issue8761.go
new file mode 100644
index 0000000..7f458f7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8761.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 8761
+// used to confuse code generator into using temporary before initialization.
+// caused 'variable live at entry' error in liveness analysis.
+
+package p
+
+func _() {
+ type C chan int
+ _ = [1][]C{[]C{make(chan int)}}
+}
+
+func _() {
+ type C interface{}
+ _ = [1][]C{[]C{recover()}}
+}
+
+func _() {
+ type C *int
+ _ = [1][]C{[]C{new(int)}}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8836.go b/gcc/testsuite/go.test/test/fixedbugs/issue8836.go
new file mode 100644
index 0000000..039b9c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8836.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Checking that line number is correct in error message.
+
+package main
+
+type Cint int
+
+func foobar(*Cint, Cint, Cint, *Cint)
+
+func main() {
+ a := Cint(1)
+
+ foobar(
+ &a,
+ 0,
+ 0,
+ 42, // ERROR ".*"
+ )
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue887.go b/gcc/testsuite/go.test/test/fixedbugs/issue887.go
index 5bc193b..b68ba69 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue887.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue887.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8947.go b/gcc/testsuite/go.test/test/fixedbugs/issue8947.go
new file mode 100644
index 0000000..703207d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8947.go
@@ -0,0 +1,53 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Some uses of zeroed constants in non-assignment
+// expressions broke with our more aggressive zeroing
+// of assignments (internal compiler errors).
+
+package main
+
+func f1() {
+ type T [2]int
+ p := T{0, 1}
+ switch p {
+ case T{0, 0}:
+ panic("wrong1")
+ case T{0, 1}:
+ // ok
+ default:
+ panic("wrong2")
+ }
+
+ if p == (T{0, 0}) {
+ panic("wrong3")
+ } else if p == (T{0, 1}) {
+ // ok
+ } else {
+ panic("wrong4")
+ }
+}
+
+type T struct {
+ V int
+}
+
+var X = T{}.V
+
+func f2() {
+ var x = T{}.V
+ if x != 0 {
+ panic("wrongx")
+ }
+ if X != 0 {
+ panic("wrongX")
+ }
+}
+
+func main() {
+ f1()
+ f2()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue8961.go b/gcc/testsuite/go.test/test/fixedbugs/issue8961.go
new file mode 100644
index 0000000..22b0f04
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue8961.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 8961. Empty composite literals to small globals were not filled in
+package main
+
+type small struct { a int }
+var foo small
+
+func main() {
+ foo.a = 1
+ foo = small{}
+ if foo.a != 0 {
+ println("expected foo.a to be 0, was", foo.a)
+ panic("composite literal not filled in")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9006.go b/gcc/testsuite/go.test/test/fixedbugs/issue9006.go
new file mode 100644
index 0000000..a61574b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9006.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T1 struct {
+ X int
+}
+
+func NewT1(x int) T1 { return T1{x} }
+
+type T2 int
+
+func NewT2(x int) T2 { return T2(x) }
+
+func main() {
+ switch (T1{}) {
+ case NewT1(1):
+ panic("bad1")
+ case NewT1(0):
+ // ok
+ default:
+ panic("bad2")
+ }
+
+ switch T2(0) {
+ case NewT2(2):
+ panic("bad3")
+ case NewT2(0):
+ // ok
+ default:
+ panic("bad4")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9017.go b/gcc/testsuite/go.test/test/fixedbugs/issue9017.go
new file mode 100644
index 0000000..5659785
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9017.go
@@ -0,0 +1,57 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9017: Method selector shouldn't automatically dereference a named pointer type.
+
+package main
+
+type T struct{ x int }
+
+func (T) mT() {}
+
+type S struct {
+ T
+}
+
+func (S) mS() {}
+
+type P *S
+
+type I interface {
+ mT()
+}
+
+func main() {
+ var s S
+ s.T.mT()
+ s.mT() // == s.T.mT()
+
+ var i I
+ _ = i
+ i = s.T
+ i = s
+
+ var ps = &s
+ ps.mS()
+ ps.T.mT()
+ ps.mT() // == ps.T.mT()
+
+ i = ps.T
+ i = ps
+
+ var p P = ps
+ (*p).mS()
+ p.mS() // ERROR "undefined"
+
+ i = *p
+ i = p // ERROR "cannot use|incompatible types"
+
+ p.T.mT()
+ p.mT() // ERROR "undefined"
+
+ i = p.T
+ i = p // ERROR "cannot use|incompatible types"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9036.go b/gcc/testsuite/go.test/test/fixedbugs/issue9036.go
new file mode 100644
index 0000000..e3d394f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9036.go
@@ -0,0 +1,31 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Expects to see error messages on 'p' exponents
+// for non-hexadecimal floats.
+
+package main
+
+import "fmt"
+
+const (
+ x1 = 1.1 // float
+ x2 = 1e10 // float
+ x3 = 0x1e10 // integer (e is a hex digit)
+)
+
+const x4 = 0x1p10 // valid hexadecimal float
+const x5 = 1p10 // ERROR "'p' exponent requires hexadecimal mantissa|invalid prefix"
+const x6 = 0P0 // ERROR "'P' exponent requires hexadecimal mantissa|invalid prefix"
+
+func main() {
+ fmt.Printf("%g %T\n", x1, x1)
+ fmt.Printf("%g %T\n", x2, x2)
+ fmt.Printf("%g %T\n", x3, x3)
+ fmt.Printf("%g %T\n", x4, x4)
+ fmt.Printf("%g %T\n", x5, x5)
+ fmt.Printf("%g %T\n", x6, x6)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9076.go b/gcc/testsuite/go.test/test/fixedbugs/issue9076.go
new file mode 100644
index 0000000..1613d5e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9076.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9076: cmd/gc shows computed values in error messages instead of original expression.
+
+package main
+
+import "unsafe"
+
+const Hundred = 100
+var _ int32 = 100/unsafe.Sizeof(int(0)) + 1 // ERROR "100 \/ unsafe.Sizeof\(int\(0\)\) \+ 1|incompatible type"
+var _ int32 = Hundred/unsafe.Sizeof(int(0)) + 1 // ERROR "Hundred \/ unsafe.Sizeof\(int\(0\)\) \+ 1|incompatible type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9083.go b/gcc/testsuite/go.test/test/fixedbugs/issue9083.go
new file mode 100644
index 0000000..d4762f8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9083.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9083: map/chan error messages show non-explicit capacity.
+
+package main
+
+// untyped constant
+const zero = 0
+
+func main() {
+ var x int
+ x = make(map[int]int) // ERROR "cannot use make\(map\[int\]int\)|incompatible"
+ x = make(map[int]int, 0) // ERROR "cannot use make\(map\[int\]int, 0\)|incompatible"
+ x = make(map[int]int, zero) // ERROR "cannot use make\(map\[int\]int, zero\)|incompatible"
+ x = make(chan int) // ERROR "cannot use make\(chan int\)|incompatible"
+ x = make(chan int, 0) // ERROR "cannot use make\(chan int, 0\)|incompatible"
+ x = make(chan int, zero) // ERROR "cannot use make\(chan int, zero\)|incompatible"
+ _ = x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9110.go b/gcc/testsuite/go.test/test/fixedbugs/issue9110.go
new file mode 100644
index 0000000..086be77
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9110.go
@@ -0,0 +1,91 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Scenario that used to leak arbitrarily many SudoG structs.
+// See golang.org/issue/9110.
+
+package main
+
+import (
+ "runtime"
+ "runtime/debug"
+ "sync"
+ "time"
+)
+
+func main() {
+ runtime.GOMAXPROCS(1)
+ debug.SetGCPercent(1000000) // only GC when we ask for GC
+
+ var stats, stats1, stats2 runtime.MemStats
+
+ release := func() {}
+ for i := 0; i < 20; i++ {
+ if i == 10 {
+ // Should be warmed up by now.
+ runtime.ReadMemStats(&stats1)
+ }
+
+ c := make(chan int)
+ for i := 0; i < 10; i++ {
+ go func() {
+ select {
+ case <-c:
+ case <-c:
+ case <-c:
+ }
+ }()
+ }
+ time.Sleep(1 * time.Millisecond)
+ release()
+
+ close(c) // let select put its sudog's into the cache
+ time.Sleep(1 * time.Millisecond)
+
+ // pick up top sudog
+ var cond1 sync.Cond
+ var mu1 sync.Mutex
+ cond1.L = &mu1
+ go func() {
+ mu1.Lock()
+ cond1.Wait()
+ mu1.Unlock()
+ }()
+ time.Sleep(1 * time.Millisecond)
+
+ // pick up next sudog
+ var cond2 sync.Cond
+ var mu2 sync.Mutex
+ cond2.L = &mu2
+ go func() {
+ mu2.Lock()
+ cond2.Wait()
+ mu2.Unlock()
+ }()
+ time.Sleep(1 * time.Millisecond)
+
+ // put top sudog back
+ cond1.Broadcast()
+ time.Sleep(1 * time.Millisecond)
+
+ // drop cache on floor
+ runtime.GC()
+
+ // release cond2 after select has gotten to run
+ release = func() {
+ cond2.Broadcast()
+ time.Sleep(1 * time.Millisecond)
+ }
+ }
+
+ runtime.GC()
+
+ runtime.ReadMemStats(&stats2)
+
+ if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak
+ print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9321.go b/gcc/testsuite/go.test/test/fixedbugs/issue9321.go
new file mode 100644
index 0000000..2b2807a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9321.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "runtime"
+ "runtime/pprof"
+ "sync"
+)
+
+func test() {
+ var wg sync.WaitGroup
+ wg.Add(2)
+ test := func() {
+ for i := 0; i < 10; i++ {
+ buf := &bytes.Buffer{}
+ pprof.Lookup("goroutine").WriteTo(buf, 2)
+ }
+ wg.Done()
+ }
+
+ go test()
+ go test()
+ wg.Wait()
+}
+
+func main() {
+ runtime.GOMAXPROCS(4)
+ for i := 0; i < 10; i++ {
+ test()
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9355.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue9355.dir/a.go
new file mode 100644
index 0000000..84500c8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9355.dir/a.go
@@ -0,0 +1,16 @@
+package main
+
+var x struct {
+ a, b, c int64
+ d struct{ p, q, r int32 }
+ e [8]byte
+ f [4]struct{ p, q, r int32 }
+}
+
+var y = &x.b
+var z = &x.d.q
+
+var b [10]byte
+var c = &b[5]
+
+var w = &x.f[3].r
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9355.go b/gcc/testsuite/go.test/test/fixedbugs/issue9355.go
new file mode 100644
index 0000000..319a2a90d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9355.go
@@ -0,0 +1,63 @@
+// +build !js,gc
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+)
+
+func main() {
+ err := os.Chdir(filepath.Join("fixedbugs", "issue9355.dir"))
+ check(err)
+
+ f, err := ioutil.TempFile("", "issue9355-*.o")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ f.Close()
+
+ out := run("go", "tool", "compile", "-o", f.Name(), "-S", "a.go")
+ os.Remove(f.Name())
+
+ // 6g/8g print the offset as dec, but 5g/9g print the offset as hex.
+ patterns := []string{
+ `rel 0\+\d t=1 \"\"\.x\+8\r?\n`, // y = &x.b
+ `rel 0\+\d t=1 \"\"\.x\+(28|1c)\r?\n`, // z = &x.d.q
+ `rel 0\+\d t=1 \"\"\.b\+5\r?\n`, // c = &b[5]
+ `rel 0\+\d t=1 \"\"\.x\+(88|58)\r?\n`, // w = &x.f[3].r
+ }
+ for _, p := range patterns {
+ if ok, err := regexp.Match(p, out); !ok || err != nil {
+ println(string(out))
+ panic("can't find pattern " + p)
+ }
+ }
+}
+
+func run(cmd string, args ...string) []byte {
+ out, err := exec.Command(cmd, args...).CombinedOutput()
+ if err != nil {
+ fmt.Println(string(out))
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ return out
+}
+
+func check(err error) {
+ if err != nil {
+ fmt.Println("BUG:", err)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9370.go b/gcc/testsuite/go.test/test/fixedbugs/issue9370.go
new file mode 100644
index 0000000..6cc8d5b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9370.go
@@ -0,0 +1,127 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that concrete/interface comparisons are
+// typechecked correctly by the compiler.
+
+package main
+
+type I interface {
+ Method()
+}
+
+type C int
+
+func (C) Method() {}
+
+type G func()
+
+func (G) Method() {}
+
+var (
+ e interface{}
+ i I
+ c C
+ n int
+ f func()
+ g G
+)
+
+var (
+ _ = e == c
+ _ = e != c
+ _ = e >= c // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = c == e
+ _ = c != e
+ _ = c >= e // ERROR "invalid operation.*not defined|invalid comparison"
+
+ _ = i == c
+ _ = i != c
+ _ = i >= c // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = c == i
+ _ = c != i
+ _ = c >= i // ERROR "invalid operation.*not defined|invalid comparison"
+
+ _ = e == n
+ _ = e != n
+ _ = e >= n // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = n == e
+ _ = n != e
+ _ = n >= e // ERROR "invalid operation.*not defined|invalid comparison"
+
+ // i and n are not assignable to each other
+ _ = i == n // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = i != n // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = i >= n // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = n == i // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = n != i // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = n >= i // ERROR "invalid operation.*mismatched types|incompatible types"
+
+ _ = e == 1
+ _ = e != 1
+ _ = e >= 1 // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = 1 == e
+ _ = 1 != e
+ _ = 1 >= e // ERROR "invalid operation.*not defined|invalid comparison"
+
+ _ = i == 1 // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = i != 1 // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = i >= 1 // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = 1 == i // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = 1 != i // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = 1 >= i // ERROR "invalid operation.*mismatched types|incompatible types"
+
+ _ = e == f // ERROR "invalid operation.*not defined|invalid operation"
+ _ = e != f // ERROR "invalid operation.*not defined|invalid operation"
+ _ = e >= f // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = f == e // ERROR "invalid operation.*not defined|invalid operation"
+ _ = f != e // ERROR "invalid operation.*not defined|invalid operation"
+ _ = f >= e // ERROR "invalid operation.*not defined|invalid comparison"
+
+ _ = i == f // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = i != f // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = i >= f // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = f == i // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = f != i // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = f >= i // ERROR "invalid operation.*mismatched types|incompatible types"
+
+ _ = e == g // ERROR "invalid operation.*not defined|invalid operation"
+ _ = e != g // ERROR "invalid operation.*not defined|invalid operation"
+ _ = e >= g // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = g == e // ERROR "invalid operation.*not defined|invalid operation"
+ _ = g != e // ERROR "invalid operation.*not defined|invalid operation"
+ _ = g >= e // ERROR "invalid operation.*not defined|invalid comparison"
+
+ _ = i == g // ERROR "invalid operation.*not defined|invalid operation"
+ _ = i != g // ERROR "invalid operation.*not defined|invalid operation"
+ _ = i >= g // ERROR "invalid operation.*not defined|invalid comparison"
+ _ = g == i // ERROR "invalid operation.*not defined|invalid operation"
+ _ = g != i // ERROR "invalid operation.*not defined|invalid operation"
+ _ = g >= i // ERROR "invalid operation.*not defined|invalid comparison"
+
+ _ = _ == e // ERROR "cannot use .*_.* as value"
+ _ = _ == i // ERROR "cannot use .*_.* as value"
+ _ = _ == c // ERROR "cannot use .*_.* as value"
+ _ = _ == n // ERROR "cannot use .*_.* as value"
+ _ = _ == f // ERROR "cannot use .*_.* as value"
+ _ = _ == g // ERROR "cannot use .*_.* as value"
+
+ _ = e == _ // ERROR "cannot use .*_.* as value"
+ _ = i == _ // ERROR "cannot use .*_.* as value"
+ _ = c == _ // ERROR "cannot use .*_.* as value"
+ _ = n == _ // ERROR "cannot use .*_.* as value"
+ _ = f == _ // ERROR "cannot use .*_.* as value"
+ _ = g == _ // ERROR "cannot use .*_.* as value"
+
+ _ = _ == _ // ERROR "cannot use .*_.* as value"
+
+ _ = e ^ c // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = c ^ e // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = 1 ^ e // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = e ^ 1 // ERROR "invalid operation.*mismatched types|incompatible types"
+ _ = 1 ^ c
+ _ = c ^ 1
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9432.go b/gcc/testsuite/go.test/test/fixedbugs/issue9432.go
new file mode 100644
index 0000000..e8946a5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9432.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gc used to recurse infinitely when dowidth is applied
+// to a broken recursive type again.
+// See golang.org/issue/9432.
+package p
+
+type foo struct { // ERROR "invalid recursive type"
+ bar foo
+ blah foo
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9521.go b/gcc/testsuite/go.test/test/fixedbugs/issue9521.go
new file mode 100644
index 0000000..1ad40bd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9521.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that an incorrect use of the blank identifier is caught.
+// Does not compile.
+
+package main
+
+func f() (_, _ []int) { return }
+func g() (x []int, y float64) { return }
+
+func main() {
+ _ = append(f()) // ERROR "cannot use \[\]int value as type int in append|incompatible type"
+ _ = append(g()) // ERROR "cannot use float64 value as type int in append|incompatible type"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/a.go
new file mode 100644
index 0000000..818c9eb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/a.go
@@ -0,0 +1,25 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type X struct {
+ T [32]byte
+}
+
+func (x *X) Get() []byte {
+ t := x.T
+ return t[:]
+}
+
+func (x *X) RetPtr(i int) *int {
+ i++
+ return &i
+}
+
+func (x *X) RetRPtr(i int) (r1 int, r2 *int) {
+ r1 = i + 1
+ r2 = &r1
+ return
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/b.go
new file mode 100644
index 0000000..52e64c8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9537.dir/b.go
@@ -0,0 +1,43 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+
+ "./a"
+)
+
+type X struct {
+ *a.X
+}
+
+type Intf interface {
+ Get() []byte
+ RetPtr(int) *int
+ RetRPtr(int) (int, *int)
+}
+
+func main() {
+ x := &a.X{T: [32]byte{1, 2, 3, 4}}
+ var ix Intf = X{x}
+ t1 := ix.Get()
+ t2 := x.Get()
+ if !bytes.Equal(t1, t2) {
+ panic(t1)
+ }
+
+ p1 := ix.RetPtr(5)
+ p2 := x.RetPtr(7)
+ if *p1 != 6 || *p2 != 8 {
+ panic(*p1)
+ }
+
+ r1, r2 := ix.RetRPtr(10)
+ r3, r4 := x.RetRPtr(13)
+ if r1 != 11 || *r2 != 11 || r3 != 14 || *r4 != 14 {
+ panic("bad RetRPtr")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9537.go b/gcc/testsuite/go.test/test/fixedbugs/issue9537.go
new file mode 100644
index 0000000..ac2d41b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9537.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9537: Compiler does not run escape analysis on an inlined
+// generated method wrapper.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9604.go b/gcc/testsuite/go.test/test/fixedbugs/issue9604.go
new file mode 100644
index 0000000..cd9e9e4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9604.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var x uint16 = 0xffff
+var y uint16 = 0xfffe
+var a uint16 = 0x7000
+var b uint16 = 0x9000
+
+func main() {
+ // Make sure we truncate to smaller-width types after evaluating expressions.
+ // This is a problem for arm where there is no 16-bit comparison op.
+ if ^x != 0 {
+ panic("^uint16(0xffff) != 0")
+ }
+ if ^y != 1 {
+ panic("^uint16(0xfffe) != 1")
+ }
+ if -x != 1 {
+ panic("-uint16(0xffff) != 1")
+ }
+ if a+b != 0 {
+ panic("0x7000+0x9000 != 0")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9604b.go b/gcc/testsuite/go.test/test/fixedbugs/issue9604b.go
new file mode 100644
index 0000000..d32116b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9604b.go
@@ -0,0 +1,180 @@
+// runoutput
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// terribly slow on wasm
+// +build !wasm
+
+package main
+
+import (
+ "fmt"
+ "math/big"
+ "unsafe"
+)
+
+var one = big.NewInt(1)
+
+type _type struct {
+ name string
+ bits uint
+ signed bool
+}
+
+// testvalues returns a list of all test values for this type.
+func (t *_type) testvalues() []*big.Int {
+ var a []*big.Int
+
+ a = append(a, big.NewInt(0))
+ a = append(a, big.NewInt(1))
+ a = append(a, big.NewInt(2))
+ if t.signed {
+ a = append(a, big.NewInt(-1))
+ a = append(a, big.NewInt(-2))
+ r := big.NewInt(1)
+ a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(1)))
+ r = big.NewInt(1)
+ a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(2)))
+ r = big.NewInt(1)
+ a = append(a, r.Lsh(r, t.bits-1).Neg(r))
+ r = big.NewInt(1)
+ a = append(a, r.Lsh(r, t.bits-1).Neg(r).Add(r, big.NewInt(1)))
+ } else {
+ r := big.NewInt(1)
+ a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(1)))
+ r = big.NewInt(1)
+ a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(2)))
+ }
+ return a
+}
+
+// trunc truncates a value to the range of the given type.
+func (t *_type) trunc(x *big.Int) *big.Int {
+ r := new(big.Int)
+ m := new(big.Int)
+ m.Lsh(one, t.bits)
+ m.Sub(m, one)
+ r.And(x, m)
+ if t.signed && r.Bit(int(t.bits)-1) == 1 {
+ m.Neg(one)
+ m.Lsh(m, t.bits)
+ r.Or(r, m)
+ }
+ return r
+}
+
+var types = []_type{
+ _type{"byte", 8, false},
+ _type{"int8", 8, true},
+ _type{"uint8", 8, false},
+ _type{"rune", 32, true},
+ _type{"int16", 16, true},
+ _type{"uint16", 16, false},
+ _type{"int32", 32, true},
+ _type{"uint32", 32, false},
+ _type{"int64", 64, true},
+ _type{"uint64", 64, false},
+ _type{"int", 8 * uint(unsafe.Sizeof(int(0))), true},
+ _type{"uint", 8 * uint(unsafe.Sizeof(uint(0))), false},
+ _type{"uintptr", 8 * uint(unsafe.Sizeof((*byte)(nil))), false},
+}
+
+type binop struct {
+ name string
+ eval func(x, y *big.Int) *big.Int
+}
+
+var binops = []binop{
+ binop{"+", func(x, y *big.Int) *big.Int { return new(big.Int).Add(x, y) }},
+ binop{"-", func(x, y *big.Int) *big.Int { return new(big.Int).Sub(x, y) }},
+ binop{"*", func(x, y *big.Int) *big.Int { return new(big.Int).Mul(x, y) }},
+ binop{"/", func(x, y *big.Int) *big.Int { return new(big.Int).Quo(x, y) }},
+ binop{"%", func(x, y *big.Int) *big.Int { return new(big.Int).Rem(x, y) }},
+ binop{"&", func(x, y *big.Int) *big.Int { return new(big.Int).And(x, y) }},
+ binop{"|", func(x, y *big.Int) *big.Int { return new(big.Int).Or(x, y) }},
+ binop{"^", func(x, y *big.Int) *big.Int { return new(big.Int).Xor(x, y) }},
+ binop{"&^", func(x, y *big.Int) *big.Int { return new(big.Int).AndNot(x, y) }},
+}
+
+type unop struct {
+ name string
+ eval func(x *big.Int) *big.Int
+}
+
+var unops = []unop{
+ unop{"+", func(x *big.Int) *big.Int { return new(big.Int).Set(x) }},
+ unop{"-", func(x *big.Int) *big.Int { return new(big.Int).Neg(x) }},
+ unop{"^", func(x *big.Int) *big.Int { return new(big.Int).Not(x) }},
+}
+
+type shiftop struct {
+ name string
+ eval func(x *big.Int, i uint) *big.Int
+}
+
+var shiftops = []shiftop{
+ shiftop{"<<", func(x *big.Int, i uint) *big.Int { return new(big.Int).Lsh(x, i) }},
+ shiftop{">>", func(x *big.Int, i uint) *big.Int { return new(big.Int).Rsh(x, i) }},
+}
+
+// valname returns the name of n as can be used as part of a variable name.
+func valname(n *big.Int) string {
+ s := fmt.Sprintf("%d", n)
+ if s[0] == '-' {
+ s = "neg" + s[1:]
+ }
+ return s
+}
+
+func main() {
+ fmt.Println("package main")
+
+ // We make variables to hold all the different values we'd like to use.
+ // We use global variables to prevent any constant folding.
+ for _, t := range types {
+ for _, n := range t.testvalues() {
+ fmt.Printf("var %s_%s %s = %d\n", t.name, valname(n), t.name, n)
+ }
+ }
+
+ fmt.Println("func main() {")
+
+ for _, t := range types {
+ // test binary ops
+ for _, op := range binops {
+ for _, x := range t.testvalues() {
+ for _, y := range t.testvalues() {
+ if (op.name == "/" || op.name == "%") && y.Sign() == 0 {
+ continue
+ }
+ r := t.trunc(op.eval(x, y))
+ eqn := fmt.Sprintf("%s_%s %s %s_%s != %d", t.name, valname(x), op.name, t.name, valname(y), r)
+ fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
+ }
+ }
+ }
+ // test unary ops
+ for _, op := range unops {
+ for _, x := range t.testvalues() {
+ r := t.trunc(op.eval(x))
+ eqn := fmt.Sprintf("%s %s_%s != %d", op.name, t.name, valname(x), r)
+ fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
+ }
+ }
+ // test shifts
+ for _, op := range shiftops {
+ for _, x := range t.testvalues() {
+
+ for _, i := range []uint{0, 1, t.bits - 2, t.bits - 1, t.bits, t.bits + 1} {
+ r := t.trunc(op.eval(x, i))
+ eqn := fmt.Sprintf("%s_%s %s %d != %d", t.name, valname(x), op.name, i, r)
+ fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
+ }
+ }
+ }
+ }
+
+ fmt.Println("}")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9608.dir/issue9608.go b/gcc/testsuite/go.test/test/fixedbugs/issue9608.dir/issue9608.go
new file mode 100644
index 0000000..ca82ded
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9608.dir/issue9608.go
@@ -0,0 +1,82 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func fail() // unimplemented, to test dead code elimination
+
+// Test dead code elimination in if statements
+func init() {
+ if false {
+ fail()
+ }
+ if 0 == 1 {
+ fail()
+ }
+}
+
+// Test dead code elimination in ordinary switch statements
+func init() {
+ const x = 0
+ switch x {
+ case 1:
+ fail()
+ }
+
+ switch 1 {
+ case x:
+ fail()
+ }
+
+ switch {
+ case false:
+ fail()
+ }
+
+ const a = "a"
+ switch a {
+ case "b":
+ fail()
+ }
+
+ const snowman = '☃'
+ switch snowman {
+ case '☀':
+ fail()
+ }
+
+ const zero = float64(0.0)
+ const one = float64(1.0)
+ switch one {
+ case -1.0:
+ fail()
+ case zero:
+ fail()
+ }
+
+ switch 1.0i {
+ case 1:
+ fail()
+ case -1i:
+ fail()
+ }
+
+ const no = false
+ switch no {
+ case true:
+ fail()
+ }
+
+ // Test dead code elimination in large ranges.
+ switch 5 {
+ case 3, 4, 5, 6, 7:
+ case 0, 1, 2:
+ fail()
+ default:
+ fail()
+ }
+}
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9608.go b/gcc/testsuite/go.test/test/fixedbugs/issue9608.go
new file mode 100644
index 0000000..92592d7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9608.go
@@ -0,0 +1,14 @@
+// rundir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9608: dead code elimination in switch statements.
+
+// This has to be done as a package rather than as a file,
+// because run.go runs files with 'go run', which passes the
+// -complete flag to compiler, causing it to complain about
+// the intentionally unimplemented function fail.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9634.go b/gcc/testsuite/go.test/test/fixedbugs/issue9634.go
new file mode 100644
index 0000000..2d5aae4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9634.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9634: Structs are incorrectly unpacked when passed as an argument
+// to append.
+
+package main
+
+func main() {
+ s := struct{
+ t []int
+ u int
+ }{}
+ _ = append(s, 0) // ERROR "must be a slice|must be slice"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9691.go b/gcc/testsuite/go.test/test/fixedbugs/issue9691.go
new file mode 100644
index 0000000..39c3dfa
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9691.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ s := "foo"
+ b := []byte(s)
+ m := make(map[string]int)
+ // Test that map index can be used in range
+ // and that slicebytetostringtmp is not used in this context.
+ for m[string(b)] = range s {
+ }
+ b[0] = 'b'
+ if m["foo"] != 2 {
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9731.go b/gcc/testsuite/go.test/test/fixedbugs/issue9731.go
new file mode 100644
index 0000000..9237d65
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9731.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x interface{}) {
+ switch x := x.(type) {
+ case int:
+ func() {
+ _ = x
+ }()
+ case map[int]int:
+ func() {
+ for range x {
+ }
+ }()
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9738.go b/gcc/testsuite/go.test/test/fixedbugs/issue9738.go
new file mode 100644
index 0000000..85319d7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9738.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func F() (x int) {
+ defer func() {
+ if x != 42 {
+ println("BUG: x =", x)
+ }
+ }()
+ return 42
+}
+
+func main() {
+ F()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9862.go b/gcc/testsuite/go.test/test/fixedbugs/issue9862.go
new file mode 100644
index 0000000..3572512
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9862.go
@@ -0,0 +1,15 @@
+// skip
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var a [1<<31 - 1024]byte
+
+func main() {
+ if a[0] != 0 {
+ panic("bad array")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue9862_run.go b/gcc/testsuite/go.test/test/fixedbugs/issue9862_run.go
new file mode 100644
index 0000000..c956c7f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue9862_run.go
@@ -0,0 +1,27 @@
+// +build !nacl,!js,gc
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for compile or link error.
+
+package main
+
+import (
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ out, err := exec.Command("go", "run", "fixedbugs/issue9862.go").CombinedOutput()
+ outstr := string(out)
+ if err == nil {
+ println("go run issue9862.go succeeded, should have failed\n", outstr)
+ return
+ }
+ if !strings.Contains(outstr, "symbol too large") {
+ println("go run issue9862.go gave unexpected error; want symbol too large:\n", outstr)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/func6.go b/gcc/testsuite/go.test/test/func6.go
index 456cb49..5b2f9f2 100644
--- a/gcc/testsuite/go.test/test/func6.go
+++ b/gcc/testsuite/go.test/test/func6.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,7 +9,7 @@
package main
func main() {
- if func() bool { return true }() {} // 6g used to say this was a syntax error
+ if func() bool { return true }() {} // gc used to say this was a syntax error
if (func() bool { return true })() {}
if (func() bool { return true }()) {}
}
diff --git a/gcc/testsuite/go.test/test/func7.go b/gcc/testsuite/go.test/test/func7.go
index 2d646b6..3b22199 100644
--- a/gcc/testsuite/go.test/test/func7.go
+++ b/gcc/testsuite/go.test/test/func7.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -23,7 +23,7 @@ func g() int {
}
func main() {
- // 6g, 8g, 5g all used to evaluate g() before f().
+ // gc used to evaluate g() before f().
if f() < g() {
panic("wrong answer")
}
diff --git a/gcc/testsuite/go.test/test/func8.go b/gcc/testsuite/go.test/test/func8.go
index 1305180..9de01d4 100644
--- a/gcc/testsuite/go.test/test/func8.go
+++ b/gcc/testsuite/go.test/test/func8.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -21,16 +21,14 @@ func g() int {
var xy string
+//go:noinline
func x() bool {
- for false {
- } // no inlining
xy += "x"
return false
}
+//go:noinline
func y() string {
- for false {
- } // no inlining
xy += "y"
return "abc"
}
diff --git a/gcc/testsuite/go.test/test/funcdup.go b/gcc/testsuite/go.test/test/funcdup.go
index d15d685..7b05d12 100644
--- a/gcc/testsuite/go.test/test/funcdup.go
+++ b/gcc/testsuite/go.test/test/funcdup.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/funcdup2.go b/gcc/testsuite/go.test/test/funcdup2.go
index 1db1a39..9513ef4 100644
--- a/gcc/testsuite/go.test/test/funcdup2.go
+++ b/gcc/testsuite/go.test/test/funcdup2.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/gc2.go b/gcc/testsuite/go.test/test/gc2.go
index de52a4f..2f8eb9b 100644
--- a/gcc/testsuite/go.test/test/gc2.go
+++ b/gcc/testsuite/go.test/test/gc2.go
@@ -1,6 +1,7 @@
+// +build !nacl,!js
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -36,7 +37,7 @@ func main() {
}
runtime.ReadMemStats(memstats)
- obj := memstats.HeapObjects - st.HeapObjects
+ obj := int64(memstats.HeapObjects - st.HeapObjects)
if obj > N/5 {
fmt.Println("too many objects left:", obj)
os.Exit(1)
diff --git a/gcc/testsuite/go.test/test/golden.out b/gcc/testsuite/go.test/test/golden.out
deleted file mode 100644
index 742a5d3..0000000
--- a/gcc/testsuite/go.test/test/golden.out
+++ /dev/null
@@ -1,24 +0,0 @@
-
-== ./
-
-== ken/
-
-== chan/
-
-== interface/
-
-== syntax/
-
-== dwarf/
-
-== safe/
-
-== fixedbugs/
-
-=========== fixedbugs/bug429.go
-fatal error: all goroutines are asleep - deadlock!
-
-== bugs/
-
-=========== bugs/bug395.go
-bug395 is broken
diff --git a/gcc/testsuite/go.test/test/goprint.go b/gcc/testsuite/go.test/test/goprint.go
index cdaccf4..d44b259 100644
--- a/gcc/testsuite/go.test/test/goprint.go
+++ b/gcc/testsuite/go.test/test/goprint.go
@@ -1,6 +1,6 @@
-// cmpout
+// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -8,9 +8,25 @@
package main
-import "time"
+import (
+ "log"
+ "runtime"
+ "time"
+)
func main() {
+ numg0 := runtime.NumGoroutine()
+ deadline := time.Now().Add(10 * time.Second)
go println(42, true, false, true, 1.5, "world", (chan int)(nil), []int(nil), (map[string]int)(nil), (func())(nil), byte(255))
- time.Sleep(100*time.Millisecond)
+ for {
+ numg := runtime.NumGoroutine()
+ if numg > numg0 {
+ if time.Now().After(deadline) {
+ log.Fatalf("%d goroutines > initial %d after deadline", numg, numg0)
+ }
+ runtime.Gosched()
+ continue
+ }
+ break
+ }
}
diff --git a/gcc/testsuite/go.test/test/goto.go b/gcc/testsuite/go.test/test/goto.go
index ca477b3..d660c9c 100644
--- a/gcc/testsuite/go.test/test/goto.go
+++ b/gcc/testsuite/go.test/test/goto.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -40,7 +40,7 @@ L:
// goto across declaration not okay
func _() {
goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
- x := 1 // GCCGO_ERROR "defined here"
+ x := 1 // GCCGO_ERROR "defined here"
_ = x
L:
}
@@ -62,7 +62,7 @@ func _() {
x := 1
_ = x
}
- x := 1 // GCCGO_ERROR "defined here"
+ x := 1 // GCCGO_ERROR "defined here"
_ = x
L:
}
@@ -77,8 +77,8 @@ L:
// error shows first offending variable
func _() {
- goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
- x := 1 // GCCGO_ERROR "defined here"
+ goto L // ERROR "goto L jumps over declaration of y at LINE+3|goto jumps over declaration"
+ x := 1 // GCCGO_ERROR "defined here"
_ = x
y := 1
_ = y
@@ -87,8 +87,8 @@ L:
// goto not okay even if code path is dead
func _() {
- goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
- x := 1 // GCCGO_ERROR "defined here"
+ goto L // ERROR "goto L jumps over declaration of y at LINE+3|goto jumps over declaration"
+ x := 1 // GCCGO_ERROR "defined here"
_ = x
y := 1
_ = y
@@ -115,14 +115,14 @@ L:
// goto into inner block not okay
func _() {
goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
- { // GCCGO_ERROR "block starts here"
+ { // GCCGO_ERROR "block starts here"
L:
}
}
// goto backward into inner block still not okay
func _() {
- { // GCCGO_ERROR "block starts here"
+ { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
@@ -130,10 +130,10 @@ func _() {
// error shows first (outermost) offending block
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
{
{
- { // GCCGO_ERROR "block starts here"
+ { // GCCGO_ERROR "block starts here"
L:
}
}
@@ -145,7 +145,7 @@ func _() {
goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
x := 1
_ = x
- { // GCCGO_ERROR "block starts here"
+ { // GCCGO_ERROR "block starts here"
L:
}
}
@@ -179,30 +179,30 @@ L:
}
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
- if true { // GCCGO_ERROR "block starts here"
+ goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ if true { // GCCGO_ERROR "block starts here"
L:
}
}
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
- if true { // GCCGO_ERROR "block starts here"
+ goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ if true { // GCCGO_ERROR "block starts here"
L:
} else {
}
}
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
if true {
- } else { // GCCGO_ERROR "block starts here"
+ } else { // GCCGO_ERROR "block starts here"
L:
}
}
func _() {
- if false { // GCCGO_ERROR "block starts here"
+ if false { // GCCGO_ERROR "block starts here"
L:
} else {
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
@@ -212,7 +212,7 @@ func _() {
func _() {
if true {
goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
- } else { // GCCGO_ERROR "block starts here"
+ } else { // GCCGO_ERROR "block starts here"
L:
}
}
@@ -220,7 +220,7 @@ func _() {
func _() {
if true {
goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
- } else if false { // GCCGO_ERROR "block starts here"
+ } else if false { // GCCGO_ERROR "block starts here"
L:
}
}
@@ -228,7 +228,7 @@ func _() {
func _() {
if true {
goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
- } else if false { // GCCGO_ERROR "block starts here"
+ } else if false { // GCCGO_ERROR "block starts here"
L:
} else {
}
@@ -241,9 +241,9 @@ func _() {
// really is LINE+1 (like in the previous test),
// even though it looks like it might be LINE+3 instead.
if true {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
} else if false {
- } else { // GCCGO_ERROR "block starts here"
+ } else { // GCCGO_ERROR "block starts here"
L:
}
}
@@ -287,14 +287,14 @@ func _() {
}
func _() {
- for { // GCCGO_ERROR "block starts here"
+ for { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
}
func _() {
- for { // GCCGO_ERROR "block starts here"
+ for { // GCCGO_ERROR "block starts here"
goto L
L1:
}
@@ -303,42 +303,42 @@ L:
}
func _() {
- for i < n { // GCCGO_ERROR "block starts here"
+ for i < n { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
}
func _() {
- for i = 0; i < n; i++ { // GCCGO_ERROR "block starts here"
+ for i = 0; i < n; i++ { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
}
func _() {
- for i = range x { // GCCGO_ERROR "block starts here"
+ for i = range x { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
}
func _() {
- for i = range c { // GCCGO_ERROR "block starts here"
+ for i = range c { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
}
func _() {
- for i = range m { // GCCGO_ERROR "block starts here"
+ for i = range m { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
}
func _() {
- for i = range s { // GCCGO_ERROR "block starts here"
+ for i = range s { // GCCGO_ERROR "block starts here"
L:
}
goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
@@ -395,29 +395,29 @@ func _() {
}
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
switch i {
case 0:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
}
}
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
switch i {
case 0:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
;
default:
}
}
func _() {
- goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
+ goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
switch i {
case 0:
default:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
}
}
@@ -426,14 +426,14 @@ func _() {
default:
goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
case 0:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
}
}
func _() {
switch i {
case 0:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
;
default:
goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block"
@@ -495,7 +495,7 @@ func _() {
goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
select {
case c <- 1:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
}
}
@@ -503,7 +503,7 @@ func _() {
goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
select {
case c <- 1:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
;
default:
}
@@ -514,7 +514,7 @@ func _() {
select {
case <-c:
default:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
}
}
@@ -523,14 +523,14 @@ func _() {
default:
goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
case <-c:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
}
}
func _() {
select {
case <-c:
- L: // GCCGO_ERROR "block starts here"
+ L: // GCCGO_ERROR "block starts here"
;
default:
goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block"
diff --git a/gcc/testsuite/go.test/test/helloworld.go b/gcc/testsuite/go.test/test/helloworld.go
index 5025ec9..06851d1 100644
--- a/gcc/testsuite/go.test/test/helloworld.go
+++ b/gcc/testsuite/go.test/test/helloworld.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/import2.dir/import2.go b/gcc/testsuite/go.test/test/import2.dir/import2.go
index 8bb1eb9..9c54a1b 100644
--- a/gcc/testsuite/go.test/test/import2.dir/import2.go
+++ b/gcc/testsuite/go.test/test/import2.dir/import2.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/import2.dir/import3.go b/gcc/testsuite/go.test/test/import2.dir/import3.go
index d7fe37b..3bf9cb0 100644
--- a/gcc/testsuite/go.test/test/import2.dir/import3.go
+++ b/gcc/testsuite/go.test/test/import2.dir/import3.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/import2.go b/gcc/testsuite/go.test/test/import2.go
index f8d0b0a..1ef1dd4 100644
--- a/gcc/testsuite/go.test/test/import2.go
+++ b/gcc/testsuite/go.test/test/import2.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/import5.go b/gcc/testsuite/go.test/test/import5.go
index 6480acf..8fdc8c3 100644
--- a/gcc/testsuite/go.test/test/import5.go
+++ b/gcc/testsuite/go.test/test/import5.go
@@ -21,35 +21,7 @@ import _ "go/parser"
//import "greek/αβ"
// Import paths must be strings.
-import 42 // ERROR "import statement"
-import 'a' // ERROR "import statement"
-import 3.14 // ERROR "import statement"
-import 0.25i // ERROR "import statement"
-
-// Each of these pairs tests both `` vs "" strings
-// and also use of invalid characters spelled out as
-// escape sequences and written directly.
-// For example `"\x00"` tests import "\x00"
-// while "`\x00`" tests import `<actual-NUL-byte>`.
-import "" // ERROR "import path"
-import `` // ERROR "import path"
-import "\x00" // ERROR "import path"
-import `\x00` // ERROR "import path"
-import "\x7f" // ERROR "import path"
-import `\x7f` // ERROR "import path"
-import "a!" // ERROR "import path"
-import `a!` // ERROR "import path"
-import "a b" // ERROR "import path"
-import `a b` // ERROR "import path"
-import "a\\b" // ERROR "import path"
-import `a\\b` // ERROR "import path"
-import "\"`a`\"" // ERROR "import path"
-import `\"a\"` // ERROR "import path"
-import "\x80\x80" // ERROR "import path"
-import `\x80\x80` // ERROR "import path"
-import "\xFFFD" // ERROR "import path"
-import `\xFFFD` // ERROR "import path"
-
-// Invalid local imports.
-import "/foo" // ERROR "import path cannot be absolute path"
-import "c:/foo" // ERROR "import path contains invalid character"
+import 42 // ERROR "import path must be a string"
+import 'a' // ERROR "import path must be a string"
+import 3.14 // ERROR "import path must be a string"
+import 0.25i // ERROR "import path must be a string"
diff --git a/gcc/testsuite/go.test/test/index.go b/gcc/testsuite/go.test/test/index.go
index a8c471b..91195ad 100644
--- a/gcc/testsuite/go.test/test/index.go
+++ b/gcc/testsuite/go.test/test/index.go
@@ -1,6 +1,6 @@
// skip
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -216,7 +216,7 @@ func main() {
thisPass := 0
if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge" || i == "fbad") {
if i == "huge" {
- // Due to a detail of 6g's internals,
+ // Due to a detail of gc's internals,
// the huge constant errors happen in an
// earlier pass than the others and inhibits
// the next pass from running.
@@ -251,7 +251,7 @@ func main() {
if c == "" && (i == "fgood" || i == "fbad") {
return
}
- // Integral float constat is ok.
+ // Integral float constant is ok.
if c == "c" && n == "" && i == "fgood" {
if pass == 0 {
fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
diff --git a/gcc/testsuite/go.test/test/index0.go b/gcc/testsuite/go.test/test/index0.go
index 04a1619..62f3392 100644
--- a/gcc/testsuite/go.test/test/index0.go
+++ b/gcc/testsuite/go.test/test/index0.go
@@ -1,6 +1,6 @@
// runoutput ./index.go
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/index1.go b/gcc/testsuite/go.test/test/index1.go
index e28efa35..40efc54 100644
--- a/gcc/testsuite/go.test/test/index1.go
+++ b/gcc/testsuite/go.test/test/index1.go
@@ -1,6 +1,6 @@
// errorcheckoutput ./index.go
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/index2.go b/gcc/testsuite/go.test/test/index2.go
index a7107cc..2a210cc 100644
--- a/gcc/testsuite/go.test/test/index2.go
+++ b/gcc/testsuite/go.test/test/index2.go
@@ -1,6 +1,6 @@
// errorcheckoutput ./index.go
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/init.go b/gcc/testsuite/go.test/test/init.go
index f468944..5e18228 100644
--- a/gcc/testsuite/go.test/test/init.go
+++ b/gcc/testsuite/go.test/test/init.go
@@ -9,13 +9,11 @@
package main
-import "runtime"
-
func init() {
}
func main() {
init() // ERROR "undefined.*init"
- runtime.init() // ERROR "unexported.*runtime\.init"
+ runtime.init() // ERROR "undefined.*runtime\.init|reference to undefined name"
var _ = init // ERROR "undefined.*init"
}
diff --git a/gcc/testsuite/go.test/test/init1.go b/gcc/testsuite/go.test/test/init1.go
index f6eda6e..0803dce 100644
--- a/gcc/testsuite/go.test/test/init1.go
+++ b/gcc/testsuite/go.test/test/init1.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -17,22 +17,30 @@ func init() {
go send(c)
<-c
- const chunk = 1 << 20
- memstats := new(runtime.MemStats)
- runtime.ReadMemStats(memstats)
- sys := memstats.Sys
- b := make([]byte, chunk)
+ const N = 1000
+ const MB = 1 << 20
+ b := make([]byte, MB)
for i := range b {
b[i] = byte(i%10 + '0')
}
s := string(b)
- for i := 0; i < 1000; i++ {
+
+ memstats := new(runtime.MemStats)
+ runtime.ReadMemStats(memstats)
+ sys, numGC := memstats.Sys, memstats.NumGC
+
+ // Generate 1,000 MB of garbage, only retaining 1 MB total.
+ for i := 0; i < N; i++ {
x = []byte(s)
}
+
+ // Verify that the garbage collector ran by seeing if we
+ // allocated fewer than N*MB bytes from the system.
runtime.ReadMemStats(memstats)
- sys1 := memstats.Sys
- if sys1-sys > chunk*50 {
- println("allocated 1000 chunks of", chunk, "and used ", sys1-sys, "memory")
+ sys1, numGC1 := memstats.Sys, memstats.NumGC
+ if sys1-sys >= N*MB || numGC1 == numGC {
+ println("allocated 1000 chunks of", MB, "and used ", sys1-sys, "memory")
+ println("numGC went", numGC, "to", numGC1)
panic("init1")
}
}
diff --git a/gcc/testsuite/go.test/test/initializerr.go b/gcc/testsuite/go.test/test/initializerr.go
index ca05414..5e2e9a9 100644
--- a/gcc/testsuite/go.test/test/initializerr.go
+++ b/gcc/testsuite/go.test/test/initializerr.go
@@ -23,6 +23,7 @@ var a2 = S { Y: 3, Z: 2, Y: 3 } // ERROR "duplicate"
var a3 = T { S{}, 2, 3, 4, 5, 6 } // ERROR "convert|too many"
var a4 = [5]byte{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } // ERROR "index|too many"
var a5 = []byte { x: 2 } // ERROR "index"
+var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate"
var ok1 = S { } // should be ok
var ok2 = T { S: ok1 } // should be ok
diff --git a/gcc/testsuite/go.test/test/interface/embed2.go b/gcc/testsuite/go.test/test/interface/embed2.go
index 1636db7..df3e2e4 100644
--- a/gcc/testsuite/go.test/test/interface/embed2.go
+++ b/gcc/testsuite/go.test/test/interface/embed2.go
@@ -12,20 +12,25 @@ import "os"
const Value = 1e12
-type Inter interface { M() int64 }
+type Inter interface {
+ M() int64
+}
type T int64
+
func (t T) M() int64 { return int64(t) }
+
var t = T(Value)
var pt = &t
var ti Inter = t
var pti = &ti
-type S struct { Inter }
-var s = S{ ti }
+type S struct{ Inter }
+
+var s = S{ti}
var ps = &s
-type SP struct { *Inter } // ERROR "interface"
+type SP struct{ *Inter } // ERROR "interface"
var i Inter
var pi = &i
@@ -43,25 +48,25 @@ func main() {
check("t.M()", t.M())
check("pt.M()", pt.M())
check("ti.M()", ti.M())
- check("pti.M()", pti.M()) // ERROR "method"
+ check("pti.M()", pti.M()) // ERROR "pointer to interface, not interface"
check("s.M()", s.M())
check("ps.M()", ps.M())
i = t
check("i = t; i.M()", i.M())
- check("i = t; pi.M()", pi.M()) // ERROR "method"
+ check("i = t; pi.M()", pi.M()) // ERROR "pointer to interface, not interface"
i = pt
check("i = pt; i.M()", i.M())
- check("i = pt; pi.M()", pi.M()) // ERROR "method"
+ check("i = pt; pi.M()", pi.M()) // ERROR "pointer to interface, not interface"
i = s
check("i = s; i.M()", i.M())
- check("i = s; pi.M()", pi.M()) // ERROR "method"
+ check("i = s; pi.M()", pi.M()) // ERROR "pointer to interface, not interface"
i = ps
check("i = ps; i.M()", i.M())
- check("i = ps; pi.M()", pi.M()) // ERROR "method"
+ check("i = ps; pi.M()", pi.M()) // ERROR "pointer to interface, not interface"
if !ok {
println("BUG: interface10")
diff --git a/gcc/testsuite/go.test/test/interface/explicit.go b/gcc/testsuite/go.test/test/interface/explicit.go
index b10d02f..3f9451e 100644
--- a/gcc/testsuite/go.test/test/interface/explicit.go
+++ b/gcc/testsuite/go.test/test/interface/explicit.go
@@ -53,7 +53,12 @@ func main() {
i2 = I2(i) // ERROR "invalid|missing N method"
e = E(t) // ok
- t = T(e) // ERROR "need explicit|need type assertion|incompatible" "as type [*]T"
+ t = T(e) // ERROR "need explicit|need type assertion|incompatible"
+
+ // cannot type-assert non-interfaces
+ f := 2.0
+ _ = f.(int) // ERROR "non-interface type|only valid for interface types"
+
}
type M interface {
@@ -81,7 +86,6 @@ var m2 M = jj // ERROR "incompatible|wrong type for M method"
var m3 = M(ii) // ERROR "invalid|missing"
var m4 = M(jj) // ERROR "invalid|wrong type for M method"
-
type B1 interface {
_() // ERROR "methods must have a unique non-blank name"
}
diff --git a/gcc/testsuite/go.test/test/interface/noeq.go b/gcc/testsuite/go.test/test/interface/noeq.go
index 1c5166e..bb36893 100644
--- a/gcc/testsuite/go.test/test/interface/noeq.go
+++ b/gcc/testsuite/go.test/test/interface/noeq.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go
index 441f0ec..8498cb5 100644
--- a/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go
+++ b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go
index e8048c6..29385df 100644
--- a/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go
+++ b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/interface/recursive1.go b/gcc/testsuite/go.test/test/interface/recursive1.go
index 62f6108..ea2f4eb 100644
--- a/gcc/testsuite/go.test/test/interface/recursive1.go
+++ b/gcc/testsuite/go.test/test/interface/recursive1.go
@@ -1,6 +1,6 @@
// compiledir
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/ken/cplx0.go b/gcc/testsuite/go.test/test/ken/cplx0.go
index 665e52a..5d78dc0 100644
--- a/gcc/testsuite/go.test/test/ken/cplx0.go
+++ b/gcc/testsuite/go.test/test/ken/cplx0.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/ken/embed.go b/gcc/testsuite/go.test/test/ken/embed.go
index 9b35c56..f7ca066 100644
--- a/gcc/testsuite/go.test/test/ken/embed.go
+++ b/gcc/testsuite/go.test/test/ken/embed.go
@@ -253,7 +253,7 @@ func main() {
panic("fail")
}
- // run it thru an interface
+ // run it through an interface
i = s
s = i.(*S)
diff --git a/gcc/testsuite/go.test/test/ken/modconst.go b/gcc/testsuite/go.test/test/ken/modconst.go
index d88cf10..c27bf64 100644
--- a/gcc/testsuite/go.test/test/ken/modconst.go
+++ b/gcc/testsuite/go.test/test/ken/modconst.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test integer modulus by contstants.
+// Test integer modulus by constants.
package main
diff --git a/gcc/testsuite/go.test/test/ken/string.go b/gcc/testsuite/go.test/test/ken/string.go
index 6df8dc4..7bb3cab 100644
--- a/gcc/testsuite/go.test/test/ken/string.go
+++ b/gcc/testsuite/go.test/test/ken/string.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/label.go b/gcc/testsuite/go.test/test/label.go
index b30c27e..7deead6 100644
--- a/gcc/testsuite/go.test/test/label.go
+++ b/gcc/testsuite/go.test/test/label.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -17,8 +17,7 @@ L1: // ERROR "label .*L1.* defined and not used"
for {
}
L2: // ERROR "label .*L2.* defined and not used"
- select {
- }
+ select {}
L3: // ERROR "label .*L3.* defined and not used"
switch {
}
@@ -59,4 +58,8 @@ L10:
default:
break L10
}
+
+ goto L10
+
+ goto go2 // ERROR "label go2 not defined|reference to undefined label .*go2"
}
diff --git a/gcc/testsuite/go.test/test/label1.go b/gcc/testsuite/go.test/test/label1.go
index f923a18..a8eaecb 100644
--- a/gcc/testsuite/go.test/test/label1.go
+++ b/gcc/testsuite/go.test/test/label1.go
@@ -1,10 +1,9 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-
// Verify that erroneous labels are caught by the compiler.
// This set is caught by pass 2. That's why this file is label1.go.
// Does not compile.
@@ -13,7 +12,19 @@ package main
var x int
-func f() {
+func f1() {
+ switch x {
+ case 1:
+ continue // ERROR "continue is not in a loop$|continue statement not within for"
+ }
+ select {
+ default:
+ continue // ERROR "continue is not in a loop$|continue statement not within for"
+ }
+
+}
+
+func f2() {
L1:
for {
if x == 0 {
@@ -32,11 +43,17 @@ L2:
break L2
}
if x == 1 {
- continue L2 // ERROR "invalid continue label .*L2"
+ continue L2 // ERROR "invalid continue label .*L2|continue is not in a loop$"
}
goto L2
}
+ for {
+ if x == 1 {
+ continue L2 // ERROR "invalid continue label .*L2"
+ }
+ }
+
L3:
switch {
case x > 10:
@@ -44,7 +61,7 @@ L3:
break L3
}
if x == 12 {
- continue L3 // ERROR "invalid continue label .*L3"
+ continue L3 // ERROR "invalid continue label .*L3|continue is not in a loop$"
}
goto L3
}
@@ -55,7 +72,7 @@ L4:
break L4 // ERROR "invalid break label .*L4"
}
if x == 14 {
- continue L4 // ERROR "invalid continue label .*L4"
+ continue L4 // ERROR "invalid continue label .*L4|continue is not in a loop$"
}
if x == 15 {
goto L4
@@ -63,12 +80,12 @@ L4:
}
L5:
- f()
+ f2()
if x == 16 {
break L5 // ERROR "invalid break label .*L5"
}
if x == 17 {
- continue L5 // ERROR "invalid continue label .*L5"
+ continue L5 // ERROR "invalid continue label .*L5|continue is not in a loop$"
}
if x == 18 {
goto L5
@@ -85,4 +102,21 @@ L5:
goto L1
}
}
+
+ continue // ERROR "continue is not in a loop$|continue statement not within for"
+ for {
+ continue on // ERROR "continue label not defined: on|invalid continue label .*on"
+ }
+
+ break // ERROR "break is not in a loop, switch, or select|break statement not within for or switch or select"
+ for {
+ break dance // ERROR "break label not defined: dance|invalid break label .*dance"
+ }
+
+ for {
+ switch x {
+ case 1:
+ continue
+ }
+ }
}
diff --git a/gcc/testsuite/go.test/test/linkx.go b/gcc/testsuite/go.test/test/linkx.go
index 12d446f..4f85b24 100644
--- a/gcc/testsuite/go.test/test/linkx.go
+++ b/gcc/testsuite/go.test/test/linkx.go
@@ -1,20 +1,38 @@
-// $G $D/$F.go && $L -X main.tbd hello $F.$A && ./$A.out
+// skip
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test the -X facility of the gc linker (6l etc.).
+// This test is run by linkx_run.go.
package main
+import "fmt"
+
var tbd string
+var overwrite string = "dibs"
+
+var tbdcopy = tbd
+var overwritecopy = overwrite
+var arraycopy = [2]string{tbd, overwrite}
+
+var b bool
+var x int
func main() {
- if tbd != "hello" {
- println("BUG: test/linkx", len(tbd), tbd)
+ fmt.Println(tbd)
+ fmt.Println(tbdcopy)
+ fmt.Println(arraycopy[0])
+
+ fmt.Println(overwrite)
+ fmt.Println(overwritecopy)
+ fmt.Println(arraycopy[1])
+
+ // Check non-string symbols are not overwritten.
+ // This also make them used.
+ if b || x != 0 {
+ panic("b or x overwritten")
}
}
diff --git a/gcc/testsuite/go.test/test/map.go b/gcc/testsuite/go.test/test/map.go
index 485e743..2c1cf8a 100644
--- a/gcc/testsuite/go.test/test/map.go
+++ b/gcc/testsuite/go.test/test/map.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Test maps, almost exhaustively.
-// NaN complexity test is in mapnan.go.
+// Complexity (linearity) test is in maplinear.go.
package main
diff --git a/gcc/testsuite/go.test/test/map1.go b/gcc/testsuite/go.test/test/map1.go
index 6f1a1c8..b4aa707 100644
--- a/gcc/testsuite/go.test/test/map1.go
+++ b/gcc/testsuite/go.test/test/map1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,8 +9,6 @@
package main
-func main() {}
-
type v bool
var (
@@ -60,3 +58,11 @@ type T5 *int
type T6 struct { F T5 }
type T7 *T4
type T8 struct { F *T7 }
+
+func main() {
+ m := make(map[int]int)
+ delete() // ERROR "missing arguments|not enough arguments"
+ delete(m) // ERROR "missing second \(key\) argument|not enough arguments"
+ delete(m, 2, 3) // ERROR "too many arguments"
+ delete(1, m) // ERROR "first argument to delete must be map|argument 1 must be a map"
+}
diff --git a/gcc/testsuite/go.test/test/mapnan.go b/gcc/testsuite/go.test/test/mapnan.go
deleted file mode 100644
index f081cab..0000000
--- a/gcc/testsuite/go.test/test/mapnan.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build darwin linux
-// run
-
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that NaNs in maps don't go quadratic.
-
-package main
-
-import (
- "fmt"
- "math"
- "time"
-)
-
-func main() {
-
- // Test that NaNs in maps don't go quadratic.
- t := func(n int) time.Duration {
- t1 := time.Now()
- m := map[float64]int{}
- nan := math.NaN()
- for i := 0; i < n; i++ {
- m[nan] = 1
- }
- if len(m) != n {
- panic("wrong size map after nan insertion")
- }
- return time.Since(t1)
- }
-
- // Depending on the machine and OS, this test might be too fast
- // to measure with accurate enough granularity. On failure,
- // make it run longer, hoping that the timing granularity
- // is eventually sufficient.
-
- n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7)
- fails := 0
- for {
- t1 := t(n)
- t2 := t(2 * n)
- // should be 2x (linear); allow up to 3x
- if t2 < 3*t1 {
- return
- }
- fails++
- if fails == 6 {
- panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2))
- }
- if fails < 4 {
- n *= 2
- }
- }
-}
diff --git a/gcc/testsuite/go.test/test/method1.go b/gcc/testsuite/go.test/test/method1.go
index 365b8ca..bb8c81d 100644
--- a/gcc/testsuite/go.test/test/method1.go
+++ b/gcc/testsuite/go.test/test/method1.go
@@ -9,12 +9,16 @@
package main
-type T struct { }
-func (t *T) M(int, string) // GCCGO_ERROR "previous"
-func (t *T) M(int, float64) { } // ERROR "redeclared|redefinition"
+type T struct{}
-func f(int, string) // GCCGO_ERROR "previous"
-func f(int, float64) { } // ERROR "redeclared|redefinition"
+func (t *T) M(int, string) // GCCGO_ERROR "previous"
+func (t *T) M(int, float64) {} // ERROR "redeclared|redefinition"
-func g(a int, b string) // GCCGO_ERROR "previous"
-func g(a int, c string) // ERROR "redeclared|redefinition"
+func (t T) H() // GCCGO_ERROR "previous"
+func (t *T) H() {} // ERROR "redeclared|redefinition"
+
+func f(int, string) // GCCGO_ERROR "previous"
+func f(int, float64) {} // ERROR "redeclared|redefinition"
+
+func g(a int, b string) // GCCGO_ERROR "previous"
+func g(a int, c string) // ERROR "redeclared|redefinition"
diff --git a/gcc/testsuite/go.test/test/method2.go b/gcc/testsuite/go.test/test/method2.go
index aaa850e..ac1d771 100644
--- a/gcc/testsuite/go.test/test/method2.go
+++ b/gcc/testsuite/go.test/test/method2.go
@@ -33,5 +33,9 @@ var _ = (*Val).val // ERROR "method"
var v Val
var pv = &v
-var _ = pv.val() // ERROR "method"
-var _ = pv.val // ERROR "method"
+var _ = pv.val() // ERROR "undefined|pointer to interface"
+var _ = pv.val // ERROR "undefined|pointer to interface"
+
+func (t *T) g() int { return t.a }
+
+var _ = (T).g() // ERROR "needs pointer receiver|undefined|method requires pointer"
diff --git a/gcc/testsuite/go.test/test/method4.dir/prog.go b/gcc/testsuite/go.test/test/method4.dir/prog.go
index 77d580c..cb5cf65f 100644
--- a/gcc/testsuite/go.test/test/method4.dir/prog.go
+++ b/gcc/testsuite/go.test/test/method4.dir/prog.go
@@ -73,7 +73,14 @@ func main() {
f4 := I2.Sum
eq(f4(t1, a, 17), 27)
eq(f4(t2, a, 18), 28)
-
+
+ // issue 6723
+ f5 := (interface {
+ I2
+ }).Sum
+ eq(f5(t1, a, 19), 29)
+ eq(f5(t2, a, 20), 30)
+
mt1 := method4a.T1(4)
mt2 := &method4a.T2{4}
diff --git a/gcc/testsuite/go.test/test/method5.go b/gcc/testsuite/go.test/test/method5.go
index 36508f2..d87bb6f 100644
--- a/gcc/testsuite/go.test/test/method5.go
+++ b/gcc/testsuite/go.test/test/method5.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/named.go b/gcc/testsuite/go.test/test/named.go
index d0330ab..9763c76 100644
--- a/gcc/testsuite/go.test/test/named.go
+++ b/gcc/testsuite/go.test/test/named.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/named1.go b/gcc/testsuite/go.test/test/named1.go
index 4f122e4..7feae13 100644
--- a/gcc/testsuite/go.test/test/named1.go
+++ b/gcc/testsuite/go.test/test/named1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -41,21 +41,21 @@ func main() {
asBool(1 != 2) // ok now
asBool(i < j) // ok now
- _, b = m[2]
+ _, b = m[2] // ok now
var inter interface{}
- _, b = inter.(Map)
+ _, b = inter.(Map) // ok now
_ = b
var minter interface {
M()
}
- _, b = minter.(Map)
+ _, b = minter.(Map) // ok now
_ = b
_, bb := <-c
asBool(bb) // ERROR "cannot use.*type bool.*as type Bool"
- _, b = <-c
+ _, b = <-c // ok now
_ = b
asString(String(slice)) // ok
diff --git a/gcc/testsuite/go.test/test/nilcheck.go b/gcc/testsuite/go.test/test/nilcheck.go
index fe05d05..6879438 100644
--- a/gcc/testsuite/go.test/test/nilcheck.go
+++ b/gcc/testsuite/go.test/test/nilcheck.go
@@ -1,6 +1,6 @@
// errorcheck -0 -N -d=nil
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -17,7 +17,7 @@ type Struct struct {
type BigStruct struct {
X int
Y float64
- A [1<<20]int
+ A [1 << 20]int
Z string
}
@@ -29,86 +29,86 @@ type Empty1 struct {
}
var (
- intp *int
- arrayp *[10]int
- array0p *[0]int
- bigarrayp *[1<<26]int
- structp *Struct
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 26]int
+ structp *Struct
bigstructp *BigStruct
- emptyp *Empty
- empty1p *Empty1
+ emptyp *Empty
+ empty1p *Empty1
)
func f1() {
- _ = *intp // ERROR "nil check"
- _ = *arrayp // ERROR "nil check"
+ _ = *intp // ERROR "nil check"
+ _ = *arrayp // ERROR "nil check"
_ = *array0p // ERROR "nil check"
_ = *array0p // ERROR "nil check"
- _ = *intp // ERROR "nil check"
- _ = *arrayp // ERROR "nil check"
+ _ = *intp // ERROR "nil check"
+ _ = *arrayp // ERROR "nil check"
_ = *structp // ERROR "nil check"
- _ = *emptyp // ERROR "nil check"
- _ = *arrayp // ERROR "nil check"
+ _ = *emptyp // ERROR "nil check"
+ _ = *arrayp // ERROR "nil check"
}
func f2() {
var (
- intp *int
- arrayp *[10]int
- array0p *[0]int
- bigarrayp *[1<<20]int
- structp *Struct
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 20]int
+ structp *Struct
bigstructp *BigStruct
- emptyp *Empty
- empty1p *Empty1
+ emptyp *Empty
+ empty1p *Empty1
)
- _ = *intp // ERROR "nil check"
- _ = *arrayp // ERROR "nil check"
- _ = *array0p // ERROR "nil check"
- _ = *array0p // ERROR "nil check"
- _ = *intp // ERROR "nil check"
- _ = *arrayp // ERROR "nil check"
- _ = *structp // ERROR "nil check"
- _ = *emptyp // ERROR "nil check"
- _ = *arrayp // ERROR "nil check"
- _ = *bigarrayp // ERROR "nil check"
+ _ = *intp // ERROR "nil check"
+ _ = *arrayp // ERROR "nil check"
+ _ = *array0p // ERROR "nil check"
+ _ = *array0p // ERROR "nil check"
+ _ = *intp // ERROR "nil check"
+ _ = *arrayp // ERROR "nil check"
+ _ = *structp // ERROR "nil check"
+ _ = *emptyp // ERROR "nil check"
+ _ = *arrayp // ERROR "nil check"
+ _ = *bigarrayp // ERROR "nil check"
_ = *bigstructp // ERROR "nil check"
- _ = *empty1p // ERROR "nil check"
+ _ = *empty1p // ERROR "nil check"
}
func fx10k() *[10000]int
-var b bool
+var b bool
func f3(x *[10000]int) {
// Using a huge type and huge offsets so the compiler
// does not expect the memory hardware to fault.
_ = x[9999] // ERROR "nil check"
-
+
for {
if x[9999] != 0 { // ERROR "nil check"
break
}
}
-
- x = fx10k()
+
+ x = fx10k()
_ = x[9999] // ERROR "nil check"
if b {
_ = x[9999] // ERROR "nil check"
} else {
_ = x[9999] // ERROR "nil check"
- }
+ }
_ = x[9999] // ERROR "nil check"
- x = fx10k()
+ x = fx10k()
if b {
_ = x[9999] // ERROR "nil check"
} else {
_ = x[9999] // ERROR "nil check"
- }
+ }
_ = x[9999] // ERROR "nil check"
-
+
fx10k()
// This one is a bit redundant, if we figured out that
// x wasn't going to change across the function call.
@@ -138,7 +138,7 @@ func f3b() {
_ = &x[9] // ERROR "nil check"
}
-func fx10() *[10]int
+func fx10() *[10]int
func f4(x *[10]int) {
// Most of these have no checks because a real memory reference follows,
@@ -146,33 +146,33 @@ func f4(x *[10]int) {
// in the first unmapped page of memory.
_ = x[9] // ERROR "nil check"
-
+
for {
if x[9] != 0 { // ERROR "nil check"
break
}
}
-
- x = fx10()
+
+ x = fx10()
_ = x[9] // ERROR "nil check"
if b {
_ = x[9] // ERROR "nil check"
} else {
_ = x[9] // ERROR "nil check"
- }
+ }
_ = x[9] // ERROR "nil check"
- x = fx10()
+ x = fx10()
if b {
_ = x[9] // ERROR "nil check"
} else {
_ = &x[9] // ERROR "nil check"
- }
+ }
_ = x[9] // ERROR "nil check"
-
+
fx10()
_ = x[9] // ERROR "nil check"
-
+
x = fx10()
y := fx10()
_ = &x[9] // ERROR "nil check"
@@ -182,3 +182,8 @@ func f4(x *[10]int) {
_ = &x[9] // ERROR "nil check"
}
+func f5(m map[string]struct{}) bool {
+ // Existence-only map lookups should not generate a nil check
+ _, ok := m[""]
+ return ok
+}
diff --git a/gcc/testsuite/go.test/test/nilptr.go b/gcc/testsuite/go.test/test/nilptr.go
index 9631d16..c9a044d 100644
--- a/gcc/testsuite/go.test/test/nilptr.go
+++ b/gcc/testsuite/go.test/test/nilptr.go
@@ -1,12 +1,16 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that the implementation catches nil ptr indirection
// in a large address space.
+// +build !aix
+// +build !darwin !arm64
+// Address space starts at 1<<32 on AIX and on darwin/arm64, so dummy is too far.
+
package main
import "unsafe"
diff --git a/gcc/testsuite/go.test/test/nilptr2.go b/gcc/testsuite/go.test/test/nilptr2.go
index d2f4c91..8a85b6d 100644
--- a/gcc/testsuite/go.test/test/nilptr2.go
+++ b/gcc/testsuite/go.test/test/nilptr2.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/nilptr3.go b/gcc/testsuite/go.test/test/nilptr3.go
index 08597a0..e0f2ed9 100644
--- a/gcc/testsuite/go.test/test/nilptr3.go
+++ b/gcc/testsuite/go.test/test/nilptr3.go
@@ -1,6 +1,9 @@
// errorcheck -0 -d=nil
-// Copyright 2013 The Go Authors. All rights reserved.
+// +build !wasm
+// +build !aix
+
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -17,7 +20,7 @@ type Struct struct {
type BigStruct struct {
X int
Y float64
- A [1<<20]int
+ A [1 << 20]int
Z string
}
@@ -29,99 +32,100 @@ type Empty1 struct {
}
var (
- intp *int
- arrayp *[10]int
- array0p *[0]int
- bigarrayp *[1<<26]int
- structp *Struct
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 26]int
+ structp *Struct
bigstructp *BigStruct
- emptyp *Empty
- empty1p *Empty1
+ emptyp *Empty
+ empty1p *Empty1
)
func f1() {
_ = *intp // ERROR "generated nil check"
-
+
// This one should be removed but the block copy needs
// to be turned into its own pseudo-op in order to see
// the indirect.
_ = *arrayp // ERROR "generated nil check"
-
- // 0-byte indirect doesn't suffice
+
+ // 0-byte indirect doesn't suffice.
+ // we don't registerize globals, so there are no removed.* nil checks.
_ = *array0p // ERROR "generated nil check"
- _ = *array0p // ERROR "removed repeated nil check" 386
+ _ = *array0p // ERROR "removed nil check"
- _ = *intp // ERROR "removed repeated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
+ _ = *intp // ERROR "removed nil check"
+ _ = *arrayp // ERROR "removed nil check"
_ = *structp // ERROR "generated nil check"
- _ = *emptyp // ERROR "generated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
+ _ = *emptyp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "removed nil check"
}
func f2() {
var (
- intp *int
- arrayp *[10]int
- array0p *[0]int
- bigarrayp *[1<<20]int
- structp *Struct
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 20]int
+ structp *Struct
bigstructp *BigStruct
- emptyp *Empty
- empty1p *Empty1
+ emptyp *Empty
+ empty1p *Empty1
)
- _ = *intp // ERROR "generated nil check"
- _ = *arrayp // ERROR "generated nil check"
- _ = *array0p // ERROR "generated nil check"
- _ = *array0p // ERROR "removed repeated nil check"
- _ = *intp // ERROR "removed repeated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
- _ = *structp // ERROR "generated nil check"
- _ = *emptyp // ERROR "generated nil check"
- _ = *arrayp // ERROR "removed repeated nil check"
- _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!!
+ _ = *intp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "generated nil check"
+ _ = *array0p // ERROR "generated nil check"
+ _ = *array0p // ERROR "removed.* nil check"
+ _ = *intp // ERROR "removed.* nil check"
+ _ = *arrayp // ERROR "removed.* nil check"
+ _ = *structp // ERROR "generated nil check"
+ _ = *emptyp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "removed.* nil check"
+ _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!!
_ = *bigstructp // ERROR "generated nil check"
- _ = *empty1p // ERROR "generated nil check"
+ _ = *empty1p // ERROR "generated nil check"
}
func fx10k() *[10000]int
-var b bool
+var b bool
func f3(x *[10000]int) {
// Using a huge type and huge offsets so the compiler
// does not expect the memory hardware to fault.
_ = x[9999] // ERROR "generated nil check"
-
+
for {
- if x[9999] != 0 { // ERROR "generated nil check"
+ if x[9999] != 0 { // ERROR "removed nil check"
break
}
}
-
- x = fx10k()
+
+ x = fx10k()
_ = x[9999] // ERROR "generated nil check"
if b {
- _ = x[9999] // ERROR "removed repeated nil check"
+ _ = x[9999] // ERROR "removed.* nil check"
} else {
- _ = x[9999] // ERROR "removed repeated nil check"
- }
- _ = x[9999] // ERROR "generated nil check"
+ _ = x[9999] // ERROR "removed.* nil check"
+ }
+ _ = x[9999] // ERROR "removed nil check"
- x = fx10k()
+ x = fx10k()
if b {
_ = x[9999] // ERROR "generated nil check"
} else {
_ = x[9999] // ERROR "generated nil check"
- }
+ }
_ = x[9999] // ERROR "generated nil check"
-
+
fx10k()
// This one is a bit redundant, if we figured out that
// x wasn't going to change across the function call.
// But it's a little complex to do and in practice doesn't
// matter enough.
- _ = x[9999] // ERROR "generated nil check"
+ _ = x[9999] // ERROR "removed nil check"
}
func f3a() {
@@ -130,7 +134,7 @@ func f3a() {
z := fx10k()
_ = &x[9] // ERROR "generated nil check"
y = z
- _ = &x[9] // ERROR "removed repeated nil check"
+ _ = &x[9] // ERROR "removed.* nil check"
x = y
_ = &x[9] // ERROR "generated nil check"
}
@@ -140,52 +144,108 @@ func f3b() {
y := fx10k()
_ = &x[9] // ERROR "generated nil check"
y = x
- _ = &x[9] // ERROR "removed repeated nil check"
+ _ = &x[9] // ERROR "removed.* nil check"
x = y
- _ = &x[9] // ERROR "removed repeated nil check"
+ _ = &x[9] // ERROR "removed.* nil check"
}
-func fx10() *[10]int
+func fx10() *[10]int
func f4(x *[10]int) {
// Most of these have no checks because a real memory reference follows,
// and the offset is small enough that if x is nil, the address will still be
// in the first unmapped page of memory.
- _ = x[9] // ERROR "removed nil check before indirect"
-
+ _ = x[9] // ERROR "generated nil check" // bug: would like to remove this check (but nilcheck and load are in different blocks)
+
for {
- if x[9] != 0 { // ERROR "removed nil check before indirect"
+ if x[9] != 0 { // ERROR "removed nil check"
break
}
}
-
- x = fx10()
- _ = x[9] // ERROR "removed nil check before indirect"
+
+ x = fx10()
+ _ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
if b {
- _ = x[9] // ERROR "removed nil check before indirect"
+ _ = x[9] // ERROR "removed nil check"
} else {
- _ = x[9] // ERROR "removed nil check before indirect"
+ _ = x[9] // ERROR "removed nil check"
}
- _ = x[9] // ERROR "removed nil check before indirect"
+ _ = x[9] // ERROR "removed nil check"
- x = fx10()
+ x = fx10()
if b {
- _ = x[9] // ERROR "removed nil check before indirect"
+ _ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
} else {
_ = &x[9] // ERROR "generated nil check"
- }
- _ = x[9] // ERROR "removed nil check before indirect"
-
+ }
+ _ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
+
fx10()
- _ = x[9] // ERROR "removed nil check before indirect"
-
+ _ = x[9] // ERROR "removed nil check"
+
x = fx10()
y := fx10()
_ = &x[9] // ERROR "generated nil check"
y = x
- _ = &x[9] // ERROR "removed repeated nil check"
+ _ = &x[9] // ERROR "removed[a-z ]* nil check"
x = y
- _ = &x[9] // ERROR "removed repeated nil check"
+ _ = &x[9] // ERROR "removed[a-z ]* nil check"
+}
+
+func m1(m map[int][80]byte) byte {
+ v := m[3] // ERROR "removed nil check"
+ return v[5]
+}
+func m2(m map[int][800]byte) byte {
+ v := m[3] // ERROR "removed nil check"
+ return v[5]
+}
+func m3(m map[int][80]byte) (byte, bool) {
+ v, ok := m[3] // ERROR "removed nil check"
+ return v[5], ok
+}
+func m4(m map[int][800]byte) (byte, bool) {
+ v, ok := m[3] // ERROR "removed nil check"
+ return v[5], ok
+}
+func p1() byte {
+ p := new([100]byte)
+ return p[5] // ERROR "removed nil check"
+}
+
+// make sure not to do nil check for access of PAUTOHEAP
+//go:noinline
+func (p *Struct) m() {}
+func c1() {
+ var x Struct
+ func() { x.m() }() // ERROR "removed nil check"
+}
+
+type SS struct {
+ x byte
+}
+
+type TT struct {
+ SS
}
+func f(t *TT) *byte {
+ // See issue 17242.
+ s := &t.SS // ERROR "generated nil check"
+ return &s.x // ERROR "removed nil check"
+}
+
+// make sure not to do nil check for newobject
+func f7() (*Struct, float64) {
+ t := new(Struct)
+ p := &t.Y // ERROR "removed nil check"
+ return t, *p // ERROR "removed nil check"
+}
+
+func f9() []int {
+ x := new([1]int)
+ x[0] = 1 // ERROR "removed nil check"
+ y := x[:] // ERROR "removed nil check"
+ return y
+}
diff --git a/gcc/testsuite/go.test/test/nul1.go b/gcc/testsuite/go.test/test/nul1.go
index 20426b4..fbba198 100644
--- a/gcc/testsuite/go.test/test/nul1.go
+++ b/gcc/testsuite/go.test/test/nul1.go
@@ -36,7 +36,7 @@ var y = ` + "`in raw string \x00 foo`" + ` // ERROR "NUL"
/* in other comment ` + "\x00" + ` */ // ERROR "NUL"
-/* in source code */ ` + "\x00" + `// ERROR "NUL" "illegal character"
+/* in source code */ ` + "\x00" + `// ERROR "NUL"
var xx = "in string ` + "\xc2\xff" + `" // ERROR "UTF-8"
@@ -47,10 +47,9 @@ var yy = ` + "`in raw string \xff foo`" + ` // ERROR "UTF-8"
/* in other comment ` + "\xe0\x00\x00" + ` */ // ERROR "UTF-8|NUL"
/* in variable name */
-var z` + "\xc1\x81" + ` int // ERROR "UTF-8" "invalid identifier character"
+var z` + "\xc1\x81" + ` int // ERROR "UTF-8"
-/* in source code */ ` + "var \xc2A int" + `// ERROR "UTF-8" "invalid identifier character"
+/* in source code */ ` + "var \xc2A int" + `// ERROR "UTF-8"
`)
}
-
diff --git a/gcc/testsuite/go.test/test/peano.go b/gcc/testsuite/go.test/test/peano.go
index 745f515..1102a97 100644
--- a/gcc/testsuite/go.test/test/peano.go
+++ b/gcc/testsuite/go.test/test/peano.go
@@ -9,6 +9,8 @@
package main
+import "runtime"
+
type Number *Number
// -------------------------------------
@@ -116,7 +118,11 @@ var results = [...]int{
}
func main() {
- for i := 0; i <= 9; i++ {
+ max := 9
+ if runtime.GOARCH == "wasm" {
+ max = 7 // stack size is limited
+ }
+ for i := 0; i <= max; i++ {
if f := count(fact(gen(i))); f != results[i] {
println("FAIL:", i, "!:", f, "!=", results[i])
panic(0)
diff --git a/gcc/testsuite/go.test/test/printbig.go b/gcc/testsuite/go.test/test/printbig.go
index 5693c58..9e08c39 100644
--- a/gcc/testsuite/go.test/test/printbig.go
+++ b/gcc/testsuite/go.test/test/printbig.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/range.go b/gcc/testsuite/go.test/test/range.go
index 8effbe9..3da7d17 100644
--- a/gcc/testsuite/go.test/test/range.go
+++ b/gcc/testsuite/go.test/test/range.go
@@ -23,15 +23,68 @@ func seq(lo, hi int) chan int {
return c
}
+const alphabet = "abcdefghijklmnopqrstuvwxyz"
+
+func testblankvars() {
+ n := 0
+ for range alphabet {
+ n++
+ }
+ if n != 26 {
+ println("for range: wrong count", n, "want 26")
+ panic("fail")
+ }
+ n = 0
+ for _ = range alphabet {
+ n++
+ }
+ if n != 26 {
+ println("for _ = range: wrong count", n, "want 26")
+ panic("fail")
+ }
+ n = 0
+ for _, _ = range alphabet {
+ n++
+ }
+ if n != 26 {
+ println("for _, _ = range: wrong count", n, "want 26")
+ panic("fail")
+ }
+ s := 0
+ for i, _ := range alphabet {
+ s += i
+ }
+ if s != 325 {
+ println("for i, _ := range: wrong sum", s, "want 325")
+ panic("fail")
+ }
+ r := rune(0)
+ for _, v := range alphabet {
+ r += v
+ }
+ if r != 2847 {
+ println("for _, v := range: wrong sum", r, "want 2847")
+ panic("fail")
+ }
+}
+
func testchan() {
s := ""
for i := range seq('a', 'z') {
s += string(i)
}
- if s != "abcdefghijklmnopqrstuvwxyz" {
+ if s != alphabet {
println("Wanted lowercase alphabet; got", s)
panic("fail")
}
+ n := 0
+ for range seq('a', 'z') {
+ n++
+ }
+ if n != 26 {
+ println("testchan wrong count", n, "want 26")
+ panic("fail")
+ }
}
// test that range over slice only evaluates
@@ -87,6 +140,46 @@ func testslice1() {
}
}
+func testslice2() {
+ n := 0
+ nmake = 0
+ for range makeslice() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makeslice", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makeslice", n)
+ panic("fail")
+ }
+}
+
+// test that range over []byte(string) only evaluates
+// the expression after "range" once.
+
+func makenumstring() string {
+ nmake++
+ return "\x01\x02\x03\x04\x05"
+}
+
+func testslice3() {
+ s := byte(0)
+ nmake = 0
+ for _, v := range []byte(makenumstring()) {
+ s += v
+ }
+ if nmake != 1 {
+ println("range called makenumstring", nmake, "times")
+ panic("fail")
+ }
+ if s != 15 {
+ println("wrong sum ranging over []byte(makenumstring)", s)
+ panic("fail")
+ }
+}
+
// test that range over array only evaluates
// the expression after "range" once.
@@ -127,6 +220,22 @@ func testarray1() {
}
}
+func testarray2() {
+ n := 0
+ nmake = 0
+ for range makearray() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makearray", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makearray", n)
+ panic("fail")
+ }
+}
+
func makearrayptr() *[5]int {
nmake++
return &[5]int{1, 2, 3, 4, 5}
@@ -176,6 +285,22 @@ func testarrayptr1() {
}
}
+func testarrayptr2() {
+ n := 0
+ nmake = 0
+ for range makearrayptr() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makearrayptr", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makearrayptr", n)
+ panic("fail")
+ }
+}
+
// test that range over string only evaluates
// the expression after "range" once.
@@ -198,6 +323,26 @@ func teststring() {
println("wrong sum ranging over makestring", s)
panic("fail")
}
+
+ x := []rune{'a', 'b'}
+ i := 1
+ for i, x[i] = range "c" {
+ break
+ }
+ if i != 0 || x[0] != 'a' || x[1] != 'c' {
+ println("wrong parallel assignment", i, x[0], x[1])
+ panic("fail")
+ }
+
+ y := []int{1, 2, 3}
+ r := rune(1)
+ for y[r], r = range "\x02" {
+ break
+ }
+ if r != 2 || y[0] != 1 || y[1] != 0 || y[2] != 3 {
+ println("wrong parallel assignment", r, y[0], y[1], y[2])
+ panic("fail")
+ }
}
func teststring1() {
@@ -216,6 +361,22 @@ func teststring1() {
}
}
+func teststring2() {
+ n := 0
+ nmake = 0
+ for range makestring() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makestring", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makestring", n)
+ panic("fail")
+ }
+}
+
// test that range over map only evaluates
// the expression after "range" once.
@@ -256,6 +417,22 @@ func testmap1() {
}
}
+func testmap2() {
+ n := 0
+ nmake = 0
+ for range makemap() {
+ n++
+ }
+ if nmake != 1 {
+ println("range called makemap", nmake, "times")
+ panic("fail")
+ }
+ if n != 5 {
+ println("wrong count ranging over makemap", n)
+ panic("fail")
+ }
+}
+
// test that range evaluates the index and value expressions
// exactly once per iteration.
@@ -295,16 +472,23 @@ func testcalls() {
}
func main() {
+ testblankvars()
testchan()
testarray()
testarray1()
+ testarray2()
testarrayptr()
testarrayptr1()
+ testarrayptr2()
testslice()
testslice1()
+ testslice2()
+ testslice3()
teststring()
teststring1()
+ teststring2()
testmap()
testmap1()
+ testmap2()
testcalls()
}
diff --git a/gcc/testsuite/go.test/test/recover.go b/gcc/testsuite/go.test/test/recover.go
index 071be66..e4187c0 100644
--- a/gcc/testsuite/go.test/test/recover.go
+++ b/gcc/testsuite/go.test/test/recover.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -47,6 +47,7 @@ func main() {
test11reflect1()
test11reflect2()
}
+ test111()
test12()
if !interp {
test12reflect1()
@@ -62,6 +63,7 @@ func main() {
test14reflect1()
test14reflect2()
test15()
+ test16()
}
}
@@ -77,7 +79,7 @@ func mustRecoverBody(v1, v2, v3, x interface{}) {
}
v = v2
if v == nil {
- println("missing recover")
+ println("missing recover", x.(int))
die() // panic is useless here
}
if v != x {
@@ -113,10 +115,23 @@ func withoutRecover() {
mustNotRecover() // because it's a sub-call
}
+func withoutRecoverRecursive(n int) {
+ if n == 0 {
+ withoutRecoverRecursive(1)
+ } else {
+ v := recover()
+ if v != nil {
+ println("spurious recover (recursive)", v)
+ die()
+ }
+ }
+}
+
func test1() {
- defer mustNotRecover() // because mustRecover will squelch it
- defer mustRecover(1) // because of panic below
- defer withoutRecover() // should be no-op, leaving for mustRecover to find
+ defer mustNotRecover() // because mustRecover will squelch it
+ defer mustRecover(1) // because of panic below
+ defer withoutRecover() // should be no-op, leaving for mustRecover to find
+ defer withoutRecoverRecursive(0) // ditto
panic(1)
}
@@ -137,7 +152,7 @@ func test1WithClosures() {
mustNotRecover()
v := recover()
if v == nil {
- println("missing recover")
+ println("missing recover", x.(int))
die()
}
if v != x {
@@ -406,6 +421,49 @@ func test11reflect2() {
panic(11)
}
+// tiny receiver, so basic wrapper in i.M()
+type T3deeper struct{}
+
+func (T3deeper) M() {
+ badstate() // difference from T3
+ mustRecoverBody(doubleRecover(), recover(), recover(), 111)
+}
+
+func test111() {
+ var i I = T3deeper{}
+ defer i.M()
+ panic(111)
+}
+
+type Tiny struct{}
+
+func (Tiny) M() {
+ panic(112)
+}
+
+// i.M is a wrapper, and i.M panics.
+//
+// This is a torture test for an old implementation of recover that
+// tried to deal with wrapper functions by doing some argument
+// positioning math on both entry and exit. Doing anything on exit
+// is a problem because sometimes functions exit via panic instead
+// of an ordinary return, so panic would have to know to do the
+// same math when unwinding the stack. It gets complicated fast.
+// This particular test never worked with the old scheme, because
+// panic never did the right unwinding math.
+//
+// The new scheme adjusts Panic.argp on entry to a wrapper.
+// It has no exit work, so if a wrapper is interrupted by a panic,
+// there's no cleanup that panic itself must do.
+// This test just works now.
+func badstate() {
+ defer func() {
+ recover()
+ }()
+ var i I = Tiny{}
+ i.M()
+}
+
// large receiver, so basic wrapper in i.M()
type T4 [2]string
@@ -503,3 +561,27 @@ func test15() {
defer f()
panic(15)
}
+
+func reflectFunc2(args []reflect.Value) (results []reflect.Value) {
+ // This will call reflectFunc3
+ args[0].Interface().(func())()
+ return nil
+}
+
+func reflectFunc3(args []reflect.Value) (results []reflect.Value) {
+ if v := recover(); v != nil {
+ println("spurious recover", v)
+ die()
+ }
+ return nil
+}
+
+func test16() {
+ defer mustRecover(16)
+
+ f2 := reflect.MakeFunc(reflect.TypeOf((func(func()))(nil)), reflectFunc2).Interface().(func(func()))
+ f3 := reflect.MakeFunc(reflect.TypeOf((func())(nil)), reflectFunc3).Interface().(func())
+ defer f2(f3)
+
+ panic(16)
+}
diff --git a/gcc/testsuite/go.test/test/recover1.go b/gcc/testsuite/go.test/test/recover1.go
index b763a10..c14a607 100644
--- a/gcc/testsuite/go.test/test/recover1.go
+++ b/gcc/testsuite/go.test/test/recover1.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/recover2.go b/gcc/testsuite/go.test/test/recover2.go
index 946d05a..31c06ba 100644
--- a/gcc/testsuite/go.test/test/recover2.go
+++ b/gcc/testsuite/go.test/test/recover2.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -71,7 +71,7 @@ func test5() {
}
func test6() {
- defer mustRecover("unhashable")
+ defer mustRecover("unhashable type main.T")
var x T
var z interface{} = x
m := make(map[interface{}]int)
diff --git a/gcc/testsuite/go.test/test/recover3.go b/gcc/testsuite/go.test/test/recover3.go
index e17bfb3..1b26cb3 100644
--- a/gcc/testsuite/go.test/test/recover3.go
+++ b/gcc/testsuite/go.test/test/recover3.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rename.go b/gcc/testsuite/go.test/test/rename.go
index dc43417..83f184b 100644
--- a/gcc/testsuite/go.test/test/rename.go
+++ b/gcc/testsuite/go.test/test/rename.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rename1.go b/gcc/testsuite/go.test/test/rename1.go
index 53db68d..c49a70a 100644
--- a/gcc/testsuite/go.test/test/rename1.go
+++ b/gcc/testsuite/go.test/test/rename1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,10 +10,10 @@
package main
func main() {
- var n byte // ERROR "not a type|expected type"
+ var n byte // ERROR "not a type|expected type"
var y = float32(0) // ERROR "cannot call|expected function"
const (
- a = 1 + iota // ERROR "string|incompatible types" "convert iota"
+ a = 1 + iota // ERROR "invalid operation|incompatible types"
)
}
diff --git a/gcc/testsuite/go.test/test/reorder.go b/gcc/testsuite/go.test/test/reorder.go
index 8fd623c..3a87d02 100644
--- a/gcc/testsuite/go.test/test/reorder.go
+++ b/gcc/testsuite/go.test/test/reorder.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -19,6 +19,7 @@ func main() {
p6()
p7()
p8()
+ p9()
}
var gx []int
@@ -112,3 +113,39 @@ func p8() {
panic(m[0])
}
}
+
+// Issue #13433: Left-to-right assignment of OAS2XXX nodes.
+func p9() {
+ var x bool
+
+ // OAS2FUNC
+ x, x = fn()
+ checkOAS2XXX(x, "x, x = fn()")
+
+ // OAS2RECV
+ var c = make(chan bool, 10)
+ c <- false
+ x, x = <-c
+ checkOAS2XXX(x, "x, x <-c")
+
+ // OAS2MAPR
+ var m = map[int]bool{0: false}
+ x, x = m[0]
+ checkOAS2XXX(x, "x, x = m[0]")
+
+ // OAS2DOTTYPE
+ var i interface{} = false
+ x, x = i.(bool)
+ checkOAS2XXX(x, "x, x = i.(bool)")
+}
+
+//go:noinline
+func fn() (bool, bool) { return false, true }
+
+// checks the order of OAS2XXX.
+func checkOAS2XXX(x bool, s string) {
+ if !x {
+ fmt.Printf("%s; got=(false); want=(true)\n", s)
+ panic("failed")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/reorder2.go b/gcc/testsuite/go.test/test/reorder2.go
index d91f1d8..07f1b15 100644
--- a/gcc/testsuite/go.test/test/reorder2.go
+++ b/gcc/testsuite/go.test/test/reorder2.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -58,9 +58,8 @@ func f(x, y string) {
log += "f(" + x + ", " + y + ")"
}
+//go:noinline
func ff(x, y string) {
- for false {
- } // prevent inl
log += "ff(" + x + ", " + y + ")"
}
@@ -69,9 +68,8 @@ func h(x string) string {
return x
}
+//go:noinline
func g(x string) string {
- for false {
- } // prevent inl
log += "g(" + x + ")"
return x
}
@@ -168,6 +166,175 @@ func main() {
}
log = ""
+ x := 0
+ switch x {
+ case 0:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in switch, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in switch, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in switch, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in switch, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c := make(chan int, 1)
+ c <- 1
+ select {
+ case c <- 0:
+ case c <- 1:
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select1, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select1, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select1, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select1, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c <- 1
+ select {
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select2, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select2, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select2, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select2, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c <- 1
+ select {
+ default:
+ case c <- 1:
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select3, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select3, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select3, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select3, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c <- 1
+ select {
+ default:
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select4, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select4, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select4, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select4, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ select {
+ case <-c:
+ case <-c:
+ default:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select5, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select5, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select5, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select5, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
if err > 0 {
panic("fail")
}
diff --git a/gcc/testsuite/go.test/test/return.go b/gcc/testsuite/go.test/test/return.go
index 482f22b..95f94b9 100644
--- a/gcc/testsuite/go.test/test/return.go
+++ b/gcc/testsuite/go.test/test/return.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rotate.go b/gcc/testsuite/go.test/test/rotate.go
index 1d71497..9dc4b1e 100644
--- a/gcc/testsuite/go.test/test/rotate.go
+++ b/gcc/testsuite/go.test/test/rotate.go
@@ -2,7 +2,7 @@
// NOTE: the actual tests to run are rotate[0123].go
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rotate0.go b/gcc/testsuite/go.test/test/rotate0.go
index 400b225..09dd900 100644
--- a/gcc/testsuite/go.test/test/rotate0.go
+++ b/gcc/testsuite/go.test/test/rotate0.go
@@ -1,6 +1,6 @@
// runoutput ./rotate.go
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rotate1.go b/gcc/testsuite/go.test/test/rotate1.go
index 98b0b1c..19757ec 100644
--- a/gcc/testsuite/go.test/test/rotate1.go
+++ b/gcc/testsuite/go.test/test/rotate1.go
@@ -1,6 +1,6 @@
// runoutput ./rotate.go
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rotate2.go b/gcc/testsuite/go.test/test/rotate2.go
index c50f8ce..a55305a 100644
--- a/gcc/testsuite/go.test/test/rotate2.go
+++ b/gcc/testsuite/go.test/test/rotate2.go
@@ -1,6 +1,6 @@
// runoutput ./rotate.go
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/rotate3.go b/gcc/testsuite/go.test/test/rotate3.go
index 73d47d8..edd5d3a 100644
--- a/gcc/testsuite/go.test/test/rotate3.go
+++ b/gcc/testsuite/go.test/test/rotate3.go
@@ -1,6 +1,6 @@
// runoutput ./rotate.go
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/run b/gcc/testsuite/go.test/test/run
deleted file mode 100755
index d206312..0000000
--- a/gcc/testsuite/go.test/test/run
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-eval $(go tool dist env)
-export GOARCH GOOS GOROOT
-export E=
-
-case X"$GOARCH" in
-Xamd64)
- export A=6
- ;;
-X386)
- export A=8
- ;;
-Xarm)
- export A=5
- export E="$GORUN"
- ;;
-*)
- echo 1>&2 run: unsupported '$GOARCH'
- exit 1
-esac
-
-export G="${A}g ${GCFLAGS}"
-export L=${A}l
-export GOTRACEBACK=0
-export LANG=C
-unset GREP_OPTIONS # in case user has a non-standard set
-
-unset GOROOT_FINAL # breaks ./ imports
-
-failed=0
-
-PATH=${GOBIN:-$GOROOT/bin}:`pwd`:/bin:/usr/bin:/usr/local/bin
-
-# TODO: We add the tool directory to the PATH to avoid thinking about a better way.
-PATH="$GOTOOLDIR:$PATH"
-
-RUNFILE="${TMPDIR:-/tmp}/gorun-$$-$USER"
-TMP1FILE="${TMPDIR:-/tmp}/gotest1-$$-$USER"
-TMP2FILE="${TMPDIR:-/tmp}/gotest2-$$-$USER"
-
-# don't run the machine out of memory: limit individual processes to 4GB.
-# on thresher, 3GB suffices to run the tests; with 2GB, peano fails.
-ulimit -v 4000000
-
-# no core files please
-ulimit -c 0
-
-true >pass.out >times.out
-
-exclude=false # exclude nothing
-golden=golden.out
-
-rm -f tmp.go # generated by some tests, left behind if interrupted
-
-filterout() {
- grep '^'"$2"'$' $1 >/dev/null
-}
-
-for dir in . ken chan interface syntax dwarf safe fixedbugs bugs
-do
- echo
- echo '==' $dir'/'
- for i in $(ls $dir/*.go 2>/dev/null)
- do (
- if $exclude $i; then
- exit 0 # continues for loop
- fi
- export F=$(basename $i .go)
- export D=$dir
- echo '. ./testlib' >"$RUNFILE"
- sed '/^\/\//!q' $i | sed 's@//@@; $d' |sed 's|./\$A.out|$E &|g' >>"$RUNFILE"
- if ! { time -p bash -c "bash '$RUNFILE' >'$TMP1FILE' 2>&1" ; } 2>"$TMP2FILE"
- then
- echo
- echo "===========" $i
- cat "$TMP1FILE"
- echo >&2 fail: $i
- echo "# $i # fail" >>pass.out
- elif test -s "$TMP1FILE"
- then
- echo
- echo "===========" $i
- cat "$TMP1FILE"
- if grep -q '^BUG' "$TMP1FILE"
- then
- if [ $dir != bugs ]
- then
- echo >&2 bug: $i
- fi
- echo "# $i # fail, BUG" >>pass.out
- else
- echo $i >>pass.out
- fi
- elif [ $dir = "bugs" ]
- then
- echo $i succeeded with no output.
- else
- echo $i >>pass.out
- fi
- echo $(awk 'NR==1{print $2}' "$TMP2FILE") $D/$F >>times.out
- rm -f $F.$A $A.out tmp.go
- ) done
-done | # clean up some stack noise
- egrep -v '^(r[0-9a-z]+|[cfg]s) +0x' |
- sed '/tmp.*Bus error/s/.*Bus/Bus/; /tmp.*Trace.BPT/s/.*Trace/Trace/
- s!'"$RUNFILE"'!$RUNFILE!g
- s/^PC=0x[0-9a-f]*/pc: xxx/
- s/^pc: 0x[0-9a-f]*/pc: xxx/
- s/PC=0x[0-9a-f]*/PC=xxx/
- /^Trace\/breakpoint trap/d
- /^Trace\/BPT trap/d
- /RUNFILE/ s/line 1: *[0-9]*/line 1: PID/
- /^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
- /Segmentation fault/d
- /^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
-
-rm -f "$RUNFILE" "$TMP1FILE" "$TMP2FILE" *.$A *.a $A.out
-diffmsg=""
-if ! diff $golden run.out
-then
- diffmsg="; test output differs"
- failed=1
-fi
-
-notinbugs=$(sed '/^== bugs/q' run.out | grep -c '^BUG')
-inbugs=$(sed '1,/^== bugs/d' run.out | grep -c '^BUG')
-
-echo 2>&1 $inbugs known bugs';' $notinbugs unexpected bugs$diffmsg
-
-if [ "$failed" != "0" ]; then
- echo FAILED
-fi
-
-exit $failed
diff --git a/gcc/testsuite/go.test/test/run.go b/gcc/testsuite/go.test/test/run.go
index 5c94de6..db3e9f6 100644
--- a/gcc/testsuite/go.test/test/run.go
+++ b/gcc/testsuite/go.test/test/run.go
@@ -1,13 +1,10 @@
// skip
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Run runs tests in the test directory.
-//
-// TODO(bradfitz): docs of some sort, once we figure out how we're changing
-// headers of files
package main
import (
@@ -15,7 +12,9 @@ import (
"errors"
"flag"
"fmt"
- "go/build"
+ "hash/fnv"
+ "io"
+ "io/fs"
"io/ioutil"
"log"
"os"
@@ -33,22 +32,34 @@ import (
var (
verbose = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.")
+ keep = flag.Bool("k", false, "keep. keep temporary directory.")
numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
summary = flag.Bool("summary", false, "show summary of results")
+ allCodegen = flag.Bool("all_codegen", defaultAllCodeGen(), "run all goos/goarch for codegen")
showSkips = flag.Bool("show_skips", false, "show skipped tests")
+ runSkips = flag.Bool("run_skips", false, "run skipped tests (ignore skip and build tags)")
+ linkshared = flag.Bool("linkshared", false, "")
+ updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output")
runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
+
+ shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.")
+ shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.")
)
-var (
- // gc and ld are [568][gl].
- gc, ld string
+// defaultAllCodeGen returns the default value of the -all_codegen
+// flag. By default, we prefer to be fast (returning false), except on
+// the linux-amd64 builder that's already very fast, so we get more
+// test coverage on trybots. See https://golang.org/issue/34297.
+func defaultAllCodeGen() bool {
+ return os.Getenv("GO_BUILDER_NAME") == "linux-amd64"
+}
- // letter is the build.ArchChar
- letter string
+var (
+ goos, goarch string
// dirs are the directories to look for *.go files in.
// TODO(bradfitz): just use all directories?
- dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "bugs"}
+ dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen", "runtime"}
// ratec controls the max number of tests running at a time.
ratec chan bool
@@ -69,18 +80,19 @@ const maxTests = 5000
func main() {
flag.Parse()
- // Disable parallelism if printing
- if *verbose {
+ goos = getenv("GOOS", runtime.GOOS)
+ goarch = getenv("GOARCH", runtime.GOARCH)
+
+ findExecCmd()
+
+ // Disable parallelism if printing or if using a simulator.
+ if *verbose || len(findExecCmd()) > 0 {
*numParallel = 1
+ *runoutputLimit = 1
}
ratec = make(chan bool, *numParallel)
rungatec = make(chan bool, *runoutputLimit)
- var err error
- letter, err = build.ArchChar(build.Default.GOARCH)
- check(err)
- gc = letter + "g"
- ld = letter + "l"
var tests []*test
if flag.NArg() > 0 {
@@ -115,16 +127,13 @@ func main() {
failed := false
resCount := map[string]int{}
for _, test := range tests {
- <-test.donec
+ <-test.donec
status := "ok "
errStr := ""
- if _, isSkip := test.err.(skipError); isSkip {
- status = "skip"
+ if e, isSkip := test.err.(skipError); isSkip {
test.err = nil
- if !skipOkay[path.Join(test.dir, test.gofile)] {
- errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr
- status = "FAIL"
- }
+ errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + string(e)
+ status = "FAIL"
}
if test.err != nil {
status = "FAIL"
@@ -134,9 +143,6 @@ func main() {
failed = true
}
resCount[status]++
- if status == "skip" && !*verbose && !*showSkips {
- continue
- }
dt := fmt.Sprintf("%.3fs", test.dt.Seconds())
if status == "FAIL" {
fmt.Printf("# go run run.go -- %s\n%s\nFAIL\t%s\t%s\n",
@@ -161,22 +167,44 @@ func main() {
}
}
-func toolPath(name string) string {
- p := filepath.Join(os.Getenv("GOROOT"), "bin", "tool", name)
- if _, err := os.Stat(p); err != nil {
- log.Fatalf("didn't find binary at %s", p)
+// goTool reports the path of the go tool to use to run the tests.
+// If possible, use the same Go used to run run.go, otherwise
+// fallback to the go version found in the PATH.
+func goTool() string {
+ var exeSuffix string
+ if runtime.GOOS == "windows" {
+ exeSuffix = ".exe"
}
- return p
+ path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
+ if _, err := os.Stat(path); err == nil {
+ return path
+ }
+ // Just run "go" from PATH
+ return "go"
+}
+
+func shardMatch(name string) bool {
+ if *shards == 0 {
+ return true
+ }
+ h := fnv.New32()
+ io.WriteString(h, name)
+ return int(h.Sum32()%uint32(*shards)) == *shard
}
func goFiles(dir string) []string {
f, err := os.Open(dir)
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
dirnames, err := f.Readdirnames(-1)
- check(err)
+ f.Close()
+ if err != nil {
+ log.Fatal(err)
+ }
names := []string{}
for _, name := range dirnames {
- if !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") {
+ if !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && shardMatch(name) {
names = append(names, name)
}
}
@@ -186,21 +214,43 @@ func goFiles(dir string) []string {
type runCmd func(...string) ([]byte, error)
-func compileFile(runcmd runCmd, longname string) (out []byte, err error) {
- return runcmd("go", "tool", gc, "-e", longname)
+func compileFile(runcmd runCmd, longname string, flags []string) (out []byte, err error) {
+ cmd := []string{goTool(), "tool", "compile", "-e"}
+ cmd = append(cmd, flags...)
+ if *linkshared {
+ cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
+ }
+ cmd = append(cmd, longname)
+ return runcmd(cmd...)
}
-func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) {
- cmd := []string{"go", "tool", gc, "-e", "-D", ".", "-I", "."}
+func compileInDir(runcmd runCmd, dir string, flags []string, localImports bool, names ...string) (out []byte, err error) {
+ cmd := []string{goTool(), "tool", "compile", "-e"}
+ if localImports {
+ // Set relative path for local imports and import search path to current dir.
+ cmd = append(cmd, "-D", ".", "-I", ".")
+ }
+ cmd = append(cmd, flags...)
+ if *linkshared {
+ cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
+ }
for _, name := range names {
cmd = append(cmd, filepath.Join(dir, name))
}
return runcmd(cmd...)
}
-func linkFile(runcmd runCmd, goname string) (err error) {
- pfile := strings.Replace(goname, ".go", "."+letter, -1)
- _, err = runcmd("go", "tool", ld, "-o", "a.exe", "-L", ".", pfile)
+func linkFile(runcmd runCmd, goname string, ldflags []string) (err error) {
+ pfile := strings.Replace(goname, ".go", ".o", -1)
+ cmd := []string{goTool(), "tool", "link", "-w", "-o", "a.exe", "-L", "."}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared", "-installsuffix=dynlink")
+ }
+ if ldflags != nil {
+ cmd = append(cmd, ldflags...)
+ }
+ cmd = append(cmd, pfile)
+ _, err = runcmd(cmd...)
return
}
@@ -209,20 +259,13 @@ type skipError string
func (s skipError) Error() string { return string(s) }
-func check(err error) {
- if err != nil {
- log.Fatal(err)
- }
-}
-
// test holds the state of a test.
type test struct {
dir, gofile string
donec chan bool // closed when done
- dt time.Duration
-
- src string
- action string // "compile", "build", etc.
+ dt time.Duration
+
+ src string
tempDir string
err error
@@ -283,9 +326,23 @@ func goDirFiles(longdir string) (filter []os.FileInfo, err error) {
return
}
-var packageRE = regexp.MustCompile(`(?m)^package (\w+)`)
+var packageRE = regexp.MustCompile(`(?m)^package ([\p{Lu}\p{Ll}\w]+)`)
-func goDirPackages(longdir string) ([][]string, error) {
+func getPackageNameFromSource(fn string) (string, error) {
+ data, err := ioutil.ReadFile(fn)
+ if err != nil {
+ return "", err
+ }
+ pkgname := packageRE.FindStringSubmatch(string(data))
+ if pkgname == nil {
+ return "", fmt.Errorf("cannot find package name in %s", fn)
+ }
+ return pkgname[1], nil
+}
+
+// If singlefilepkgs is set, each file is considered a separate package
+// even if the package names are the same.
+func goDirPackages(longdir string, singlefilepkgs bool) ([][]string, error) {
files, err := goDirFiles(longdir)
if err != nil {
return nil, err
@@ -294,19 +351,15 @@ func goDirPackages(longdir string) ([][]string, error) {
m := make(map[string]int)
for _, file := range files {
name := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(longdir, name))
+ pkgname, err := getPackageNameFromSource(filepath.Join(longdir, name))
if err != nil {
- return nil, err
- }
- pkgname := packageRE.FindStringSubmatch(string(data))
- if pkgname == nil {
- return nil, fmt.Errorf("cannot find package name in %s", name)
+ log.Fatal(err)
}
- i, ok := m[pkgname[1]]
- if !ok {
+ i, ok := m[pkgname]
+ if singlefilepkgs || !ok {
i = len(pkgs)
pkgs = append(pkgs, nil)
- m[pkgname[1]] = i
+ m[pkgname] = i
}
pkgs[i] = append(pkgs[i], name)
}
@@ -314,15 +367,16 @@ func goDirPackages(longdir string) ([][]string, error) {
}
type context struct {
- GOOS string
- GOARCH string
+ GOOS string
+ GOARCH string
+ noOptEnv bool
}
// shouldTest looks for build tags in a source file and returns
// whether the file should be used according to the tags.
func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) {
- if idx := strings.Index(src, "\npackage"); idx >= 0 {
- src = src[:idx]
+ if *runSkips {
+ return true, ""
}
for _, line := range strings.Split(src, "\n") {
line = strings.TrimSpace(line)
@@ -335,10 +389,13 @@ func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) {
if len(line) == 0 || line[0] != '+' {
continue
}
+ gcFlags := os.Getenv("GO_GCFLAGS")
ctxt := &context{
- GOOS: goos,
- GOARCH: goarch,
+ GOOS: goos,
+ GOARCH: goarch,
+ noOptEnv: strings.Contains(gcFlags, "-N") || strings.Contains(gcFlags, "-l"),
}
+
words := strings.Fields(line)
if words[0] == "+build" {
ok := false
@@ -381,7 +438,15 @@ func (ctxt *context) match(name string) bool {
}
}
- if name == ctxt.GOOS || name == ctxt.GOARCH {
+ if name == ctxt.GOOS || name == ctxt.GOARCH || name == "gc" {
+ return true
+ }
+
+ if ctxt.noOptEnv && name == "gcflags_noopt" {
+ return true
+ }
+
+ if name == "test_run" {
return true
}
@@ -390,6 +455,18 @@ func (ctxt *context) match(name string) bool {
func init() { checkShouldTest() }
+// goGcflags returns the -gcflags argument to use with go build / go run.
+// This must match the flags used for building the standard library,
+// or else the commands will rebuild any needed packages (like runtime)
+// over and over.
+func goGcflags() string {
+ return "-gcflags=all=" + os.Getenv("GO_GCFLAGS")
+}
+
+func goGcflagsIsEmpty() bool {
+ return "" == os.Getenv("GO_GCFLAGS")
+}
+
// run runs a test.
func (t *test) run() {
start := time.Now()
@@ -408,85 +485,172 @@ func (t *test) run() {
t.err = skipError("starts with newline")
return
}
+
+ // Execution recipe stops at first blank line.
pos := strings.Index(t.src, "\n\n")
if pos == -1 {
t.err = errors.New("double newline not found")
return
}
- if ok, why := shouldTest(t.src, runtime.GOOS, runtime.GOARCH); !ok {
- t.action = "skip"
- if *showSkips {
- fmt.Printf("%-20s %-20s: %s\n", t.action, t.goFileName(), why)
- }
- return
- }
action := t.src[:pos]
if nl := strings.Index(action, "\n"); nl >= 0 && strings.Contains(action[:nl], "+build") {
// skip first line
action = action[nl+1:]
}
- if strings.HasPrefix(action, "//") {
- action = action[2:]
+ action = strings.TrimPrefix(action, "//")
+
+ // Check for build constraints only up to the actual code.
+ pkgPos := strings.Index(t.src, "\npackage")
+ if pkgPos == -1 {
+ pkgPos = pos // some files are intentionally malformed
+ }
+ if ok, why := shouldTest(t.src[:pkgPos], goos, goarch); !ok {
+ if *showSkips {
+ fmt.Printf("%-20s %-20s: %s\n", "skip", t.goFileName(), why)
+ }
+ return
}
var args, flags []string
+ var tim int
wantError := false
+ wantAuto := false
+ singlefilepkgs := false
+ setpkgpaths := false
+ localImports := true
f := strings.Fields(action)
if len(f) > 0 {
action = f[0]
args = f[1:]
}
+ // TODO: Clean up/simplify this switch statement.
switch action {
- case "rundircmpout":
- action = "rundir"
- t.action = "rundir"
- case "cmpout":
- action = "run" // the run case already looks for <dir>/<test>.out files
- fallthrough
- case "compile", "compiledir", "build", "run", "runoutput", "rundir":
- t.action = action
+ case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "runindir", "asmcheck":
+ // nothing to do
+ case "errorcheckandrundir":
+ wantError = false // should be no error if also will run
+ case "errorcheckwithauto":
+ action = "errorcheck"
+ wantAuto = true
+ wantError = true
case "errorcheck", "errorcheckdir", "errorcheckoutput":
- t.action = action
wantError = true
- for len(args) > 0 && strings.HasPrefix(args[0], "-") {
- if args[0] == "-0" {
- wantError = false
- } else {
- flags = append(flags, args[0])
- }
- args = args[1:]
- }
case "skip":
- t.action = "skip"
+ if *runSkips {
+ break
+ }
return
default:
t.err = skipError("skipped; unknown pattern: " + action)
- t.action = "??"
return
}
+ // collect flags
+ for len(args) > 0 && strings.HasPrefix(args[0], "-") {
+ switch args[0] {
+ case "-1":
+ wantError = true
+ case "-0":
+ wantError = false
+ case "-s":
+ singlefilepkgs = true
+ case "-P":
+ setpkgpaths = true
+ case "-n":
+ // Do not set relative path for local imports to current dir,
+ // e.g. do not pass -D . -I . to the compiler.
+ // Used in fixedbugs/bug345.go to allow compilation and import of local pkg.
+ // See golang.org/issue/25635
+ localImports = false
+ case "-t": // timeout in seconds
+ args = args[1:]
+ var err error
+ tim, err = strconv.Atoi(args[0])
+ if err != nil {
+ t.err = fmt.Errorf("need number of seconds for -t timeout, got %s instead", args[0])
+ }
+
+ default:
+ flags = append(flags, args[0])
+ }
+ args = args[1:]
+ }
+ if action == "errorcheck" {
+ found := false
+ for i, f := range flags {
+ if strings.HasPrefix(f, "-d=") {
+ flags[i] = f + ",ssa/check/on"
+ found = true
+ break
+ }
+ }
+ if !found {
+ flags = append(flags, "-d=ssa/check/on")
+ }
+ }
+
t.makeTempDir()
- defer os.RemoveAll(t.tempDir)
+ if !*keep {
+ defer os.RemoveAll(t.tempDir)
+ }
err = ioutil.WriteFile(filepath.Join(t.tempDir, t.gofile), srcBytes, 0644)
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
// A few tests (of things like the environment) require these to be set.
- os.Setenv("GOOS", runtime.GOOS)
- os.Setenv("GOARCH", runtime.GOARCH)
+ if os.Getenv("GOOS") == "" {
+ os.Setenv("GOOS", runtime.GOOS)
+ }
+ if os.Getenv("GOARCH") == "" {
+ os.Setenv("GOARCH", runtime.GOARCH)
+ }
- useTmp := true
+ var (
+ runInDir = t.tempDir
+ tempDirIsGOPATH = false
+ )
runcmd := func(args ...string) ([]byte, error) {
cmd := exec.Command(args[0], args[1:]...)
var buf bytes.Buffer
cmd.Stdout = &buf
cmd.Stderr = &buf
- if useTmp {
- cmd.Dir = t.tempDir
- cmd.Env = envForDir(cmd.Dir)
+ cmd.Env = append(os.Environ(), "GOENV=off", "GOFLAGS=")
+ if runInDir != "" {
+ cmd.Dir = runInDir
+ // Set PWD to match Dir to speed up os.Getwd in the child process.
+ cmd.Env = append(cmd.Env, "PWD="+cmd.Dir)
+ }
+ if tempDirIsGOPATH {
+ cmd.Env = append(cmd.Env, "GOPATH="+t.tempDir)
+ }
+
+ var err error
+
+ if tim != 0 {
+ err = cmd.Start()
+ // This command-timeout code adapted from cmd/go/test.go
+ if err == nil {
+ tick := time.NewTimer(time.Duration(tim) * time.Second)
+ done := make(chan error)
+ go func() {
+ done <- cmd.Wait()
+ }()
+ select {
+ case err = <-done:
+ // ok
+ case <-tick.C:
+ cmd.Process.Kill()
+ err = <-done
+ // err = errors.New("Test timeout")
+ }
+ tick.Stop()
+ }
+ } else {
+ err = cmd.Run()
}
- err := cmd.Run()
if err != nil {
err = fmt.Errorf("%s\n%s", err, buf.Bytes())
}
@@ -498,8 +662,67 @@ func (t *test) run() {
default:
t.err = fmt.Errorf("unimplemented action %q", action)
+ case "asmcheck":
+ // Compile Go file and match the generated assembly
+ // against a set of regexps in comments.
+ ops := t.wantedAsmOpcodes(long)
+ self := runtime.GOOS + "/" + runtime.GOARCH
+ for _, env := range ops.Envs() {
+ // Only run checks relevant to the current GOOS/GOARCH,
+ // to avoid triggering a cross-compile of the runtime.
+ if string(env) != self && !strings.HasPrefix(string(env), self+"/") && !*allCodegen {
+ continue
+ }
+ // -S=2 forces outermost line numbers when disassembling inlined code.
+ cmdline := []string{"build", "-gcflags", "-S=2"}
+
+ // Append flags, but don't override -gcflags=-S=2; add to it instead.
+ for i := 0; i < len(flags); i++ {
+ flag := flags[i]
+ switch {
+ case strings.HasPrefix(flag, "-gcflags="):
+ cmdline[2] += " " + strings.TrimPrefix(flag, "-gcflags=")
+ case strings.HasPrefix(flag, "--gcflags="):
+ cmdline[2] += " " + strings.TrimPrefix(flag, "--gcflags=")
+ case flag == "-gcflags", flag == "--gcflags":
+ i++
+ if i < len(flags) {
+ cmdline[2] += " " + flags[i]
+ }
+ default:
+ cmdline = append(cmdline, flag)
+ }
+ }
+
+ cmdline = append(cmdline, long)
+ cmd := exec.Command(goTool(), cmdline...)
+ cmd.Env = append(os.Environ(), env.Environ()...)
+ if len(flags) > 0 && flags[0] == "-race" {
+ cmd.Env = append(cmd.Env, "CGO_ENABLED=1")
+ }
+
+ var buf bytes.Buffer
+ cmd.Stdout, cmd.Stderr = &buf, &buf
+ if err := cmd.Run(); err != nil {
+ fmt.Println(env, "\n", cmd.Stderr)
+ t.err = err
+ return
+ }
+
+ t.err = t.asmCheck(buf.String(), long, env, ops[env])
+ if t.err != nil {
+ return
+ }
+ }
+ return
+
case "errorcheck":
- cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+ // Compile Go file.
+ // Fail if wantError is true and compilation was successful and vice versa.
+ // Match errors produced by gc against errors in comments.
+ // TODO(gri) remove need for -C (disable printing of columns in error messages)
+ cmdline := []string{goTool(), "tool", "compile", "-C", "-e", "-o", "a.o"}
+ // No need to add -dynlink even if linkshared if we're just checking for errors...
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, long)
out, err := runcmd(cmdline...)
@@ -514,39 +737,50 @@ func (t *test) run() {
return
}
}
- t.err = t.errorCheck(string(out), long, t.gofile)
+ if *updateErrors {
+ t.updateErrors(string(out), long)
+ }
+ t.err = t.errorCheck(string(out), wantAuto, long, t.gofile)
return
case "compile":
- _, t.err = compileFile(runcmd, long)
+ // Compile Go file.
+ _, t.err = compileFile(runcmd, long, flags)
case "compiledir":
- // Compile all files in the directory in lexicographic order.
+ // Compile all files in the directory as packages in lexicographic order.
longdir := filepath.Join(cwd, t.goDirName())
- pkgs, err := goDirPackages(longdir)
+ pkgs, err := goDirPackages(longdir, singlefilepkgs)
if err != nil {
t.err = err
return
}
for _, gofiles := range pkgs {
- _, t.err = compileInDir(runcmd, longdir, gofiles...)
+ _, t.err = compileInDir(runcmd, longdir, flags, localImports, gofiles...)
if t.err != nil {
return
}
}
- case "errorcheckdir":
- // errorcheck all files in lexicographic order
- // useful for finding importing errors
+ case "errorcheckdir", "errorcheckandrundir":
+ // Compile and errorCheck all files in the directory as packages in lexicographic order.
+ // If errorcheckdir and wantError, compilation of the last package must fail.
+ // If errorcheckandrundir and wantError, compilation of the package prior the last must fail.
longdir := filepath.Join(cwd, t.goDirName())
- pkgs, err := goDirPackages(longdir)
+ pkgs, err := goDirPackages(longdir, singlefilepkgs)
if err != nil {
t.err = err
return
}
+ errPkg := len(pkgs) - 1
+ if wantError && action == "errorcheckandrundir" {
+ // The last pkg should compiled successfully and will be run in next case.
+ // Preceding pkg must return an error from compileInDir.
+ errPkg--
+ }
for i, gofiles := range pkgs {
- out, err := compileInDir(runcmd, longdir, gofiles...)
- if i == len(pkgs)-1 {
+ out, err := compileInDir(runcmd, longdir, flags, localImports, gofiles...)
+ if i == errPkg {
if wantError && err == nil {
t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
return
@@ -562,34 +796,66 @@ func (t *test) run() {
for _, name := range gofiles {
fullshort = append(fullshort, filepath.Join(longdir, name), name)
}
- t.err = t.errorCheck(string(out), fullshort...)
+ t.err = t.errorCheck(string(out), wantAuto, fullshort...)
if t.err != nil {
break
}
}
+ if action == "errorcheckdir" {
+ return
+ }
+ fallthrough
case "rundir":
- // Compile all files in the directory in lexicographic order.
- // then link as if the last file is the main package and run it
+ // Compile all files in the directory as packages in lexicographic order.
+ // In case of errorcheckandrundir, ignore failed compilation of the package before the last.
+ // Link as if the last file is the main package, run it.
+ // Verify the expected output.
longdir := filepath.Join(cwd, t.goDirName())
- pkgs, err := goDirPackages(longdir)
+ pkgs, err := goDirPackages(longdir, singlefilepkgs)
if err != nil {
t.err = err
return
}
+ // Split flags into gcflags and ldflags
+ ldflags := []string{}
+ for i, fl := range flags {
+ if fl == "-ldflags" {
+ ldflags = flags[i+1:]
+ flags = flags[0:i]
+ break
+ }
+ }
+
for i, gofiles := range pkgs {
- _, err := compileInDir(runcmd, longdir, gofiles...)
- if err != nil {
+ pflags := []string{}
+ pflags = append(pflags, flags...)
+ if setpkgpaths {
+ fp := filepath.Join(longdir, gofiles[0])
+ pkgname, err := getPackageNameFromSource(fp)
+ if err != nil {
+ log.Fatal(err)
+ }
+ pflags = append(pflags, "-p", pkgname)
+ }
+ _, err := compileInDir(runcmd, longdir, pflags, localImports, gofiles...)
+ // Allow this package compilation fail based on conditions below;
+ // its errors were checked in previous case.
+ if err != nil && !(wantError && action == "errorcheckandrundir" && i == len(pkgs)-2) {
t.err = err
return
}
if i == len(pkgs)-1 {
- err = linkFile(runcmd, gofiles[0])
+ err = linkFile(runcmd, gofiles[0], ldflags)
if err != nil {
t.err = err
return
}
- out, err := runcmd(append([]string{filepath.Join(t.tempDir, "a.exe")}, args...)...)
+ var cmd []string
+ cmd = append(cmd, findExecCmd()...)
+ cmd = append(cmd, filepath.Join(t.tempDir, "a.exe"))
+ cmd = append(cmd, args...)
+ out, err := runcmd(cmd...)
if err != nil {
t.err = err
return
@@ -600,50 +866,256 @@ func (t *test) run() {
}
}
+ case "runindir":
+ // Make a shallow copy of t.goDirName() in its own module and GOPATH, and
+ // run "go run ." in it. The module path (and hence import path prefix) of
+ // the copy is equal to the basename of the source directory.
+ //
+ // It's used when test a requires a full 'go build' in order to compile
+ // the sources, such as when importing multiple packages (issue29612.dir)
+ // or compiling a package containing assembly files (see issue15609.dir),
+ // but still needs to be run to verify the expected output.
+ tempDirIsGOPATH = true
+ srcDir := t.goDirName()
+ modName := filepath.Base(srcDir)
+ gopathSrcDir := filepath.Join(t.tempDir, "src", modName)
+ runInDir = gopathSrcDir
+
+ if err := overlayDir(gopathSrcDir, srcDir); err != nil {
+ t.err = err
+ return
+ }
+
+ modFile := fmt.Sprintf("module %s\ngo 1.14\n", modName)
+ if err := ioutil.WriteFile(filepath.Join(gopathSrcDir, "go.mod"), []byte(modFile), 0666); err != nil {
+ t.err = err
+ return
+ }
+
+ cmd := []string{goTool(), "run", goGcflags()}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ cmd = append(cmd, ".")
+ out, err := runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ return
+ }
+ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
+ }
+
case "build":
- _, err := runcmd("go", "build", "-o", "a.exe", long)
+ // Build Go file.
+ _, err := runcmd(goTool(), "build", goGcflags(), "-o", "a.exe", long)
+ if err != nil {
+ t.err = err
+ }
+
+ case "builddir", "buildrundir":
+ // Build an executable from all the .go and .s files in a subdirectory.
+ // Run it and verify its output in the buildrundir case.
+ longdir := filepath.Join(cwd, t.goDirName())
+ files, dirErr := ioutil.ReadDir(longdir)
+ if dirErr != nil {
+ t.err = dirErr
+ break
+ }
+ var gos []string
+ var asms []string
+ for _, file := range files {
+ switch filepath.Ext(file.Name()) {
+ case ".go":
+ gos = append(gos, filepath.Join(longdir, file.Name()))
+ case ".s":
+ asms = append(asms, filepath.Join(longdir, file.Name()))
+ }
+
+ }
+ if len(asms) > 0 {
+ emptyHdrFile := filepath.Join(t.tempDir, "go_asm.h")
+ if err := ioutil.WriteFile(emptyHdrFile, nil, 0666); err != nil {
+ t.err = fmt.Errorf("write empty go_asm.h: %s", err)
+ return
+ }
+ cmd := []string{goTool(), "tool", "asm", "-gensymabis", "-o", "symabis"}
+ cmd = append(cmd, asms...)
+ _, err = runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ }
+ var objs []string
+ cmd := []string{goTool(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
+ if len(asms) > 0 {
+ cmd = append(cmd, "-asmhdr", "go_asm.h", "-symabis", "symabis")
+ }
+ cmd = append(cmd, gos...)
+ _, err := runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ objs = append(objs, "go.o")
+ if len(asms) > 0 {
+ cmd = []string{goTool(), "tool", "asm", "-e", "-I", ".", "-o", "asm.o"}
+ cmd = append(cmd, asms...)
+ _, err = runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ objs = append(objs, "asm.o")
+ }
+ cmd = []string{goTool(), "tool", "pack", "c", "all.a"}
+ cmd = append(cmd, objs...)
+ _, err = runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ cmd = []string{goTool(), "tool", "link", "-o", "a.exe", "all.a"}
+ _, err = runcmd(cmd...)
if err != nil {
t.err = err
+ break
+ }
+ if action == "buildrundir" {
+ cmd = append(findExecCmd(), filepath.Join(t.tempDir, "a.exe"))
+ out, err := runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
+ }
+ }
+
+ case "buildrun":
+ // Build an executable from Go file, then run it, verify its output.
+ // Useful for timeout tests where failure mode is infinite loop.
+ // TODO: not supported on NaCl
+ cmd := []string{goTool(), "build", goGcflags(), "-o", "a.exe"}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ longdirgofile := filepath.Join(filepath.Join(cwd, t.dir), t.gofile)
+ cmd = append(cmd, flags...)
+ cmd = append(cmd, longdirgofile)
+ _, err := runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ return
+ }
+ cmd = []string{"./a.exe"}
+ out, err := runcmd(append(cmd, args...)...)
+ if err != nil {
+ t.err = err
+ return
+ }
+
+ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
}
case "run":
- useTmp = false
- out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+ // Run Go file if no special go command flags are provided;
+ // otherwise build an executable and run it.
+ // Verify the output.
+ runInDir = ""
+ var out []byte
+ var err error
+ if len(flags)+len(args) == 0 && goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS {
+ // If we're not using special go command flags,
+ // skip all the go command machinery.
+ // This avoids any time the go command would
+ // spend checking whether, for example, the installed
+ // package runtime is up to date.
+ // Because we run lots of trivial test programs,
+ // the time adds up.
+ pkg := filepath.Join(t.tempDir, "pkg.a")
+ if _, err := runcmd(goTool(), "tool", "compile", "-o", pkg, t.goFileName()); err != nil {
+ t.err = err
+ return
+ }
+ exe := filepath.Join(t.tempDir, "test.exe")
+ cmd := []string{goTool(), "tool", "link", "-s", "-w"}
+ cmd = append(cmd, "-o", exe, pkg)
+ if _, err := runcmd(cmd...); err != nil {
+ t.err = err
+ return
+ }
+ out, err = runcmd(append([]string{exe}, args...)...)
+ } else {
+ cmd := []string{goTool(), "run", goGcflags()}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ cmd = append(cmd, flags...)
+ cmd = append(cmd, t.goFileName())
+ out, err = runcmd(append(cmd, args...)...)
+ }
if err != nil {
t.err = err
+ return
}
if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
t.err = fmt.Errorf("incorrect output\n%s", out)
}
case "runoutput":
+ // Run Go file and write its output into temporary Go file.
+ // Run generated Go file and verify its output.
rungatec <- true
defer func() {
<-rungatec
}()
- useTmp = false
- out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+ runInDir = ""
+ cmd := []string{goTool(), "run", goGcflags()}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ cmd = append(cmd, t.goFileName())
+ out, err := runcmd(append(cmd, args...)...)
if err != nil {
t.err = err
+ return
}
tfile := filepath.Join(t.tempDir, "tmp__.go")
if err := ioutil.WriteFile(tfile, out, 0666); err != nil {
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
- out, err = runcmd("go", "run", tfile)
+ cmd = []string{goTool(), "run", goGcflags()}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ cmd = append(cmd, tfile)
+ out, err = runcmd(cmd...)
if err != nil {
t.err = err
+ return
}
if string(out) != t.expectedOutput() {
t.err = fmt.Errorf("incorrect output\n%s", out)
}
case "errorcheckoutput":
- useTmp = false
- out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+ // Run Go file and write its output into temporary Go file.
+ // Compile and errorCheck generated Go file.
+ runInDir = ""
+ cmd := []string{goTool(), "run", goGcflags()}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ cmd = append(cmd, t.goFileName())
+ out, err := runcmd(append(cmd, args...)...)
if err != nil {
t.err = err
+ return
}
tfile := filepath.Join(t.tempDir, "tmp__.go")
err = ioutil.WriteFile(tfile, out, 0666)
@@ -651,7 +1123,7 @@ func (t *test) run() {
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
- cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+ cmdline := []string{goTool(), "tool", "compile", "-e", "-o", "a.o"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, tfile)
out, err = runcmd(cmdline...)
@@ -666,11 +1138,28 @@ func (t *test) run() {
return
}
}
- t.err = t.errorCheck(string(out), tfile, "tmp__.go")
+ t.err = t.errorCheck(string(out), false, tfile, "tmp__.go")
return
}
}
+var execCmd []string
+
+func findExecCmd() []string {
+ if execCmd != nil {
+ return execCmd
+ }
+ execCmd = []string{} // avoid work the second time
+ if goos == runtime.GOOS && goarch == runtime.GOARCH {
+ return execCmd
+ }
+ path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch))
+ if err == nil {
+ execCmd = []string{path}
+ }
+ return execCmd
+}
+
func (t *test) String() string {
return filepath.Join(t.dir, t.gofile)
}
@@ -678,7 +1167,12 @@ func (t *test) String() string {
func (t *test) makeTempDir() {
var err error
t.tempDir, err = ioutil.TempDir("", "")
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if *keep {
+ log.Printf("Temporary directory is %s", t.tempDir)
+ }
}
func (t *test) expectedOutput() string {
@@ -689,29 +1183,45 @@ func (t *test) expectedOutput() string {
return string(b)
}
-func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
- defer func() {
- if *verbose && err != nil {
- log.Printf("%s gc output:\n%s", t, outStr)
- }
- }()
- var errs []error
-
- var out []string
- // 6g error messages continue onto additional lines with leading tabs.
+func splitOutput(out string, wantAuto bool) []string {
+ // gc error messages continue onto additional lines with leading tabs.
// Split the output at the beginning of each line that doesn't begin with a tab.
- for _, line := range strings.Split(outStr, "\n") {
+ // <autogenerated> lines are impossible to match so those are filtered out.
+ var res []string
+ for _, line := range strings.Split(out, "\n") {
if strings.HasSuffix(line, "\r") { // remove '\r', output by compiler on windows
line = line[:len(line)-1]
}
if strings.HasPrefix(line, "\t") {
- out[len(out)-1] += "\n" + line
- } else if strings.HasPrefix(line, "go tool") {
+ res[len(res)-1] += "\n" + line
+ } else if strings.HasPrefix(line, "go tool") || strings.HasPrefix(line, "#") || !wantAuto && strings.HasPrefix(line, "<autogenerated>") {
continue
} else if strings.TrimSpace(line) != "" {
- out = append(out, line)
+ res = append(res, line)
}
}
+ return res
+}
+
+// errorCheck matches errors in outStr against comments in source files.
+// For each line of the source files which should generate an error,
+// there should be a comment of the form // ERROR "regexp".
+// If outStr has an error for a line which has no such comment,
+// this function will report an error.
+// Likewise if outStr does not have an error for a line which has a comment,
+// or if the error message does not match the <regexp>.
+// The <regexp> syntax is Perl but it's best to stick to egrep.
+//
+// Sources files are supplied as fullshort slice.
+// It consists of pairs: full path to source file and its base name.
+func (t *test) errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) {
+ defer func() {
+ if *verbose && err != nil {
+ log.Printf("%s gc output:\n%s", t, outStr)
+ }
+ }()
+ var errs []error
+ out := splitOutput(outStr, wantAuto)
// Cut directory name.
for i := range out {
@@ -729,7 +1239,11 @@ func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
for _, we := range want {
var errmsgs []string
- errmsgs, out = partitionStrings(we.filterRe, out)
+ if we.auto {
+ errmsgs, out = partitionStrings("<autogenerated>", out)
+ } else {
+ errmsgs, out = partitionStrings(we.prefix, out)
+ }
if len(errmsgs) == 0 {
errs = append(errs, fmt.Errorf("%s:%d: missing error %q", we.file, we.lineNum, we.reStr))
continue
@@ -737,7 +1251,13 @@ func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
matched := false
n := len(out)
for _, errmsg := range errmsgs {
- if we.re.MatchString(errmsg) {
+ // Assume errmsg says "file:line: foo".
+ // Cut leading "file:line: " to avoid accidental matching of file name instead of message.
+ text := errmsg
+ if i := strings.Index(text, " "); i >= 0 {
+ text = text[i+1:]
+ }
+ if we.re.MatchString(text) {
matched = true
} else {
out = append(out, errmsg)
@@ -768,12 +1288,100 @@ func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
fmt.Fprintf(&buf, "%s\n", err.Error())
}
return errors.New(buf.String())
+}
+
+func (t *test) updateErrors(out, file string) {
+ base := path.Base(file)
+ // Read in source file.
+ src, err := ioutil.ReadFile(file)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ lines := strings.Split(string(src), "\n")
+ // Remove old errors.
+ for i, ln := range lines {
+ pos := strings.Index(ln, " // ERROR ")
+ if pos >= 0 {
+ lines[i] = ln[:pos]
+ }
+ }
+ // Parse new errors.
+ errors := make(map[int]map[string]bool)
+ tmpRe := regexp.MustCompile(`autotmp_[0-9]+`)
+ for _, errStr := range splitOutput(out, false) {
+ colon1 := strings.Index(errStr, ":")
+ if colon1 < 0 || errStr[:colon1] != file {
+ continue
+ }
+ colon2 := strings.Index(errStr[colon1+1:], ":")
+ if colon2 < 0 {
+ continue
+ }
+ colon2 += colon1 + 1
+ line, err := strconv.Atoi(errStr[colon1+1 : colon2])
+ line--
+ if err != nil || line < 0 || line >= len(lines) {
+ continue
+ }
+ msg := errStr[colon2+2:]
+ msg = strings.Replace(msg, file, base, -1) // normalize file mentions in error itself
+ msg = strings.TrimLeft(msg, " \t")
+ for _, r := range []string{`\`, `*`, `+`, `?`, `[`, `]`, `(`, `)`} {
+ msg = strings.Replace(msg, r, `\`+r, -1)
+ }
+ msg = strings.Replace(msg, `"`, `.`, -1)
+ msg = tmpRe.ReplaceAllLiteralString(msg, `autotmp_[0-9]+`)
+ if errors[line] == nil {
+ errors[line] = make(map[string]bool)
+ }
+ errors[line][msg] = true
+ }
+ // Add new errors.
+ for line, errs := range errors {
+ var sorted []string
+ for e := range errs {
+ sorted = append(sorted, e)
+ }
+ sort.Strings(sorted)
+ lines[line] += " // ERROR"
+ for _, e := range sorted {
+ lines[line] += fmt.Sprintf(` "%s$"`, e)
+ }
+ }
+ // Write new file.
+ err = ioutil.WriteFile(file, []byte(strings.Join(lines, "\n")), 0640)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ // Polish.
+ exec.Command(goTool(), "fmt", file).CombinedOutput()
+}
+// matchPrefix reports whether s is of the form ^(.*/)?prefix(:|[),
+// That is, it needs the file name prefix followed by a : or a [,
+// and possibly preceded by a directory name.
+func matchPrefix(s, prefix string) bool {
+ i := strings.Index(s, ":")
+ if i < 0 {
+ return false
+ }
+ j := strings.LastIndex(s[:i], "/")
+ s = s[j+1:]
+ if len(s) <= len(prefix) || s[:len(prefix)] != prefix {
+ return false
+ }
+ switch s[len(prefix)] {
+ case '[', ':':
+ return true
+ }
+ return false
}
-func partitionStrings(rx *regexp.Regexp, strs []string) (matched, unmatched []string) {
+func partitionStrings(prefix string, strs []string) (matched, unmatched []string) {
for _, s := range strs {
- if rx.MatchString(s) {
+ if matchPrefix(s, prefix) {
matched = append(matched, s)
} else {
unmatched = append(unmatched, s)
@@ -783,20 +1391,24 @@ func partitionStrings(rx *regexp.Regexp, strs []string) (matched, unmatched []st
}
type wantedError struct {
- reStr string
- re *regexp.Regexp
- lineNum int
- file string
- filterRe *regexp.Regexp // /^file:linenum\b/m
+ reStr string
+ re *regexp.Regexp
+ lineNum int
+ auto bool // match <autogenerated> line
+ file string
+ prefix string
}
var (
errRx = regexp.MustCompile(`// (?:GC_)?ERROR (.*)`)
+ errAutoRx = regexp.MustCompile(`// (?:GC_)?ERRORAUTO (.*)`)
errQuotesRx = regexp.MustCompile(`"([^"]*)"`)
lineRx = regexp.MustCompile(`LINE(([+-])([0-9]+))?`)
)
func (t *test) wantedErrors(file, short string) (errs []wantedError) {
+ cache := make(map[string]*regexp.Regexp)
+
src, _ := ioutil.ReadFile(file)
for i, line := range strings.Split(string(src), "\n") {
lineNum := i + 1
@@ -804,7 +1416,13 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) {
// double comment disables ERROR
continue
}
- m := errRx.FindStringSubmatch(line)
+ var auto bool
+ m := errAutoRx.FindStringSubmatch(line)
+ if m != nil {
+ auto = true
+ } else {
+ m = errRx.FindStringSubmatch(line)
+ }
if m == nil {
continue
}
@@ -825,17 +1443,23 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) {
}
return fmt.Sprintf("%s:%d", short, n)
})
- re, err := regexp.Compile(rx)
- if err != nil {
- log.Fatalf("%s:%d: invalid regexp in ERROR line: %v", t.goFileName(), lineNum, err)
+ re := cache[rx]
+ if re == nil {
+ var err error
+ re, err = regexp.Compile(rx)
+ if err != nil {
+ log.Fatalf("%s:%d: invalid regexp \"%s\" in ERROR line: %v", t.goFileName(), lineNum, rx, err)
+ }
+ cache[rx] = re
}
- filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, regexp.QuoteMeta(short), lineNum)
+ prefix := fmt.Sprintf("%s:%d", short, lineNum)
errs = append(errs, wantedError{
- reStr: rx,
- re: re,
- filterRe: regexp.MustCompile(filterPattern),
- lineNum: lineNum,
- file: short,
+ reStr: rx,
+ re: re,
+ prefix: prefix,
+ auto: auto,
+ lineNum: lineNum,
+ file: short,
})
}
}
@@ -843,15 +1467,267 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) {
return
}
-var skipOkay = map[string]bool{
- "linkx.go": true, // like "run" but wants linker flags
- "sinit.go": true,
- "fixedbugs/bug248.go": true, // combines errorcheckdir and rundir in the same dir.
- "fixedbugs/bug302.go": true, // tests both .$O and .a imports.
- "fixedbugs/bug345.go": true, // needs the appropriate flags in gc invocation.
- "fixedbugs/bug369.go": true, // needs compiler flags.
- "fixedbugs/bug429.go": true, // like "run" but program should fail
- "bugs/bug395.go": true,
+const (
+ // Regexp to match a single opcode check: optionally begin with "-" (to indicate
+ // a negative check), followed by a string literal enclosed in "" or ``. For "",
+ // backslashes must be handled.
+ reMatchCheck = `-?(?:\x60[^\x60]*\x60|"(?:[^"\\]|\\.)*")`
+)
+
+var (
+ // Regexp to split a line in code and comment, trimming spaces
+ rxAsmComment = regexp.MustCompile(`^\s*(.*?)\s*(?://\s*(.+)\s*)?$`)
+
+ // Regexp to extract an architecture check: architecture name (or triplet),
+ // followed by semi-colon, followed by a comma-separated list of opcode checks.
+ // Extraneous spaces are ignored.
+ rxAsmPlatform = regexp.MustCompile(`(\w+)(/\w+)?(/\w*)?\s*:\s*(` + reMatchCheck + `(?:\s*,\s*` + reMatchCheck + `)*)`)
+
+ // Regexp to extract a single opcoded check
+ rxAsmCheck = regexp.MustCompile(reMatchCheck)
+
+ // List of all architecture variants. Key is the GOARCH architecture,
+ // value[0] is the variant-changing environment variable, and values[1:]
+ // are the supported variants.
+ archVariants = map[string][]string{
+ "386": {"GO386", "sse2", "softfloat"},
+ "amd64": {},
+ "arm": {"GOARM", "5", "6", "7"},
+ "arm64": {},
+ "mips": {"GOMIPS", "hardfloat", "softfloat"},
+ "mips64": {"GOMIPS64", "hardfloat", "softfloat"},
+ "ppc64": {"GOPPC64", "power8", "power9"},
+ "ppc64le": {"GOPPC64", "power8", "power9"},
+ "s390x": {},
+ "wasm": {},
+ }
+)
+
+// wantedAsmOpcode is a single asmcheck check
+type wantedAsmOpcode struct {
+ fileline string // original source file/line (eg: "/path/foo.go:45")
+ line int // original source line
+ opcode *regexp.Regexp // opcode check to be performed on assembly output
+ negative bool // true if the check is supposed to fail rather than pass
+ found bool // true if the opcode check matched at least one in the output
+}
+
+// A build environment triplet separated by slashes (eg: linux/386/sse2).
+// The third field can be empty if the arch does not support variants (eg: "plan9/amd64/")
+type buildEnv string
+
+// Environ returns the environment it represents in cmd.Environ() "key=val" format
+// For instance, "linux/386/sse2".Environ() returns {"GOOS=linux", "GOARCH=386", "GO386=sse2"}
+func (b buildEnv) Environ() []string {
+ fields := strings.Split(string(b), "/")
+ if len(fields) != 3 {
+ panic("invalid buildEnv string: " + string(b))
+ }
+ env := []string{"GOOS=" + fields[0], "GOARCH=" + fields[1]}
+ if fields[2] != "" {
+ env = append(env, archVariants[fields[1]][0]+"="+fields[2])
+ }
+ return env
+}
+
+// asmChecks represents all the asmcheck checks present in a test file
+// The outer map key is the build triplet in which the checks must be performed.
+// The inner map key represent the source file line ("filename.go:1234") at which the
+// checks must be performed.
+type asmChecks map[buildEnv]map[string][]wantedAsmOpcode
+
+// Envs returns all the buildEnv in which at least one check is present
+func (a asmChecks) Envs() []buildEnv {
+ var envs []buildEnv
+ for e := range a {
+ envs = append(envs, e)
+ }
+ sort.Slice(envs, func(i, j int) bool {
+ return string(envs[i]) < string(envs[j])
+ })
+ return envs
+}
+
+func (t *test) wantedAsmOpcodes(fn string) asmChecks {
+ ops := make(asmChecks)
+
+ comment := ""
+ src, _ := ioutil.ReadFile(fn)
+ for i, line := range strings.Split(string(src), "\n") {
+ matches := rxAsmComment.FindStringSubmatch(line)
+ code, cmt := matches[1], matches[2]
+
+ // Keep comments pending in the comment variable until
+ // we find a line that contains some code.
+ comment += " " + cmt
+ if code == "" {
+ continue
+ }
+
+ // Parse and extract any architecture check from comments,
+ // made by one architecture name and multiple checks.
+ lnum := fn + ":" + strconv.Itoa(i+1)
+ for _, ac := range rxAsmPlatform.FindAllStringSubmatch(comment, -1) {
+ archspec, allchecks := ac[1:4], ac[4]
+
+ var arch, subarch, os string
+ switch {
+ case archspec[2] != "": // 3 components: "linux/386/sse2"
+ os, arch, subarch = archspec[0], archspec[1][1:], archspec[2][1:]
+ case archspec[1] != "": // 2 components: "386/sse2"
+ os, arch, subarch = "linux", archspec[0], archspec[1][1:]
+ default: // 1 component: "386"
+ os, arch, subarch = "linux", archspec[0], ""
+ if arch == "wasm" {
+ os = "js"
+ }
+ }
+
+ if _, ok := archVariants[arch]; !ok {
+ log.Fatalf("%s:%d: unsupported architecture: %v", t.goFileName(), i+1, arch)
+ }
+
+ // Create the build environments corresponding the above specifiers
+ envs := make([]buildEnv, 0, 4)
+ if subarch != "" {
+ envs = append(envs, buildEnv(os+"/"+arch+"/"+subarch))
+ } else {
+ subarchs := archVariants[arch]
+ if len(subarchs) == 0 {
+ envs = append(envs, buildEnv(os+"/"+arch+"/"))
+ } else {
+ for _, sa := range archVariants[arch][1:] {
+ envs = append(envs, buildEnv(os+"/"+arch+"/"+sa))
+ }
+ }
+ }
+
+ for _, m := range rxAsmCheck.FindAllString(allchecks, -1) {
+ negative := false
+ if m[0] == '-' {
+ negative = true
+ m = m[1:]
+ }
+
+ rxsrc, err := strconv.Unquote(m)
+ if err != nil {
+ log.Fatalf("%s:%d: error unquoting string: %v", t.goFileName(), i+1, err)
+ }
+
+ // Compile the checks as regular expressions. Notice that we
+ // consider checks as matching from the beginning of the actual
+ // assembler source (that is, what is left on each line of the
+ // compile -S output after we strip file/line info) to avoid
+ // trivial bugs such as "ADD" matching "FADD". This
+ // doesn't remove genericity: it's still possible to write
+ // something like "F?ADD", but we make common cases simpler
+ // to get right.
+ oprx, err := regexp.Compile("^" + rxsrc)
+ if err != nil {
+ log.Fatalf("%s:%d: %v", t.goFileName(), i+1, err)
+ }
+
+ for _, env := range envs {
+ if ops[env] == nil {
+ ops[env] = make(map[string][]wantedAsmOpcode)
+ }
+ ops[env][lnum] = append(ops[env][lnum], wantedAsmOpcode{
+ negative: negative,
+ fileline: lnum,
+ line: i + 1,
+ opcode: oprx,
+ })
+ }
+ }
+ }
+ comment = ""
+ }
+
+ return ops
+}
+
+func (t *test) asmCheck(outStr string, fn string, env buildEnv, fullops map[string][]wantedAsmOpcode) (err error) {
+ // The assembly output contains the concatenated dump of multiple functions.
+ // the first line of each function begins at column 0, while the rest is
+ // indented by a tabulation. These data structures help us index the
+ // output by function.
+ functionMarkers := make([]int, 1)
+ lineFuncMap := make(map[string]int)
+
+ lines := strings.Split(outStr, "\n")
+ rxLine := regexp.MustCompile(fmt.Sprintf(`\((%s:\d+)\)\s+(.*)`, regexp.QuoteMeta(fn)))
+
+ for nl, line := range lines {
+ // Check if this line begins a function
+ if len(line) > 0 && line[0] != '\t' {
+ functionMarkers = append(functionMarkers, nl)
+ }
+
+ // Search if this line contains a assembly opcode (which is prefixed by the
+ // original source file/line in parenthesis)
+ matches := rxLine.FindStringSubmatch(line)
+ if len(matches) == 0 {
+ continue
+ }
+ srcFileLine, asm := matches[1], matches[2]
+
+ // Associate the original file/line information to the current
+ // function in the output; it will be useful to dump it in case
+ // of error.
+ lineFuncMap[srcFileLine] = len(functionMarkers) - 1
+
+ // If there are opcode checks associated to this source file/line,
+ // run the checks.
+ if ops, found := fullops[srcFileLine]; found {
+ for i := range ops {
+ if !ops[i].found && ops[i].opcode.FindString(asm) != "" {
+ ops[i].found = true
+ }
+ }
+ }
+ }
+ functionMarkers = append(functionMarkers, len(lines))
+
+ var failed []wantedAsmOpcode
+ for _, ops := range fullops {
+ for _, o := range ops {
+ // There's a failure if a negative match was found,
+ // or a positive match was not found.
+ if o.negative == o.found {
+ failed = append(failed, o)
+ }
+ }
+ }
+ if len(failed) == 0 {
+ return
+ }
+
+ // At least one asmcheck failed; report them
+ sort.Slice(failed, func(i, j int) bool {
+ return failed[i].line < failed[j].line
+ })
+
+ lastFunction := -1
+ var errbuf bytes.Buffer
+ fmt.Fprintln(&errbuf)
+ for _, o := range failed {
+ // Dump the function in which this opcode check was supposed to
+ // pass but failed.
+ funcIdx := lineFuncMap[o.fileline]
+ if funcIdx != 0 && funcIdx != lastFunction {
+ funcLines := lines[functionMarkers[funcIdx]:functionMarkers[funcIdx+1]]
+ log.Println(strings.Join(funcLines, "\n"))
+ lastFunction = funcIdx // avoid printing same function twice
+ }
+
+ if o.negative {
+ fmt.Fprintf(&errbuf, "%s:%d: %s: wrong opcode found: %q\n", t.goFileName(), o.line, env, o.opcode.String())
+ } else {
+ fmt.Fprintf(&errbuf, "%s:%d: %s: opcode not found: %q\n", t.goFileName(), o.line, env, o.opcode.String())
+ }
+ }
+ err = errors.New(errbuf.String())
+ return
}
// defaultRunOutputLimit returns the number of runoutput tests that
@@ -886,7 +1762,7 @@ func checkShouldTest() {
// Build tags separated by a space are OR-ed together.
assertNot(shouldTest("// +build arm 386", "linux", "amd64"))
- // Build tags seperated by a comma are AND-ed together.
+ // Build tags separated by a comma are AND-ed together.
assertNot(shouldTest("// +build !windows,!plan9", "windows", "amd64"))
assertNot(shouldTest("// +build !windows,!plan9", "plan9", "386"))
@@ -898,19 +1774,75 @@ func checkShouldTest() {
assert(shouldTest("// +build !windows !plan9", "windows", "amd64"))
}
-// envForDir returns a copy of the environment
-// suitable for running in the given directory.
-// The environment is the current process's environment
-// but with an updated $PWD, so that an os.Getwd in the
-// child will be faster.
-func envForDir(dir string) []string {
- env := os.Environ()
- for i, kv := range env {
- if strings.HasPrefix(kv, "PWD=") {
- env[i] = "PWD=" + dir
- return env
- }
+func getenv(key, def string) string {
+ value := os.Getenv(key)
+ if value != "" {
+ return value
}
- env = append(env, "PWD="+dir)
- return env
+ return def
+}
+
+// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added.
+func overlayDir(dstRoot, srcRoot string) error {
+ dstRoot = filepath.Clean(dstRoot)
+ if err := os.MkdirAll(dstRoot, 0777); err != nil {
+ return err
+ }
+
+ srcRoot, err := filepath.Abs(srcRoot)
+ if err != nil {
+ return err
+ }
+
+ return filepath.WalkDir(srcRoot, func(srcPath string, d fs.DirEntry, err error) error {
+ if err != nil || srcPath == srcRoot {
+ return err
+ }
+
+ suffix := strings.TrimPrefix(srcPath, srcRoot)
+ for len(suffix) > 0 && suffix[0] == filepath.Separator {
+ suffix = suffix[1:]
+ }
+ dstPath := filepath.Join(dstRoot, suffix)
+
+ var info fs.FileInfo
+ if d.Type()&os.ModeSymlink != 0 {
+ info, err = os.Stat(srcPath)
+ } else {
+ info, err = d.Info()
+ }
+ if err != nil {
+ return err
+ }
+ perm := info.Mode() & os.ModePerm
+
+ // Always copy directories (don't symlink them).
+ // If we add a file in the overlay, we don't want to add it in the original.
+ if info.IsDir() {
+ return os.MkdirAll(dstPath, perm|0200)
+ }
+
+ // If the OS supports symlinks, use them instead of copying bytes.
+ if err := os.Symlink(srcPath, dstPath); err == nil {
+ return nil
+ }
+
+ // Otherwise, copy the bytes.
+ src, err := os.Open(srcPath)
+ if err != nil {
+ return err
+ }
+ defer src.Close()
+
+ dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(dst, src)
+ if closeErr := dst.Close(); err == nil {
+ err = closeErr
+ }
+ return err
+ })
}
diff --git a/gcc/testsuite/go.test/test/rune.go b/gcc/testsuite/go.test/test/rune.go
index c013c47..73a5aa2 100644
--- a/gcc/testsuite/go.test/test/rune.go
+++ b/gcc/testsuite/go.test/test/rune.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/runtime.go b/gcc/testsuite/go.test/test/runtime.go
index 89f59e3..bccc9b5 100644
--- a/gcc/testsuite/go.test/test/runtime.go
+++ b/gcc/testsuite/go.test/test/runtime.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/safe/main.go b/gcc/testsuite/go.test/test/safe/main.go
deleted file mode 100644
index d173ed9..0000000
--- a/gcc/testsuite/go.test/test/safe/main.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// true
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-// can't use local path with -u, use -I. instead
-import "pkg" // ERROR "import unsafe package"
-
-func main() {
- print(pkg.Float32bits(1.0))
-}
diff --git a/gcc/testsuite/go.test/test/safe/nousesafe.go b/gcc/testsuite/go.test/test/safe/nousesafe.go
deleted file mode 100644
index fcd25af..0000000
--- a/gcc/testsuite/go.test/test/safe/nousesafe.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// $G $D/pkg.go && pack grc pkg.a pkg.$A 2> /dev/null && rm pkg.$A && errchk $G -I . -u $D/main.go
-// rm -f pkg.a
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ignored
diff --git a/gcc/testsuite/go.test/test/safe/pkg.go b/gcc/testsuite/go.test/test/safe/pkg.go
deleted file mode 100644
index bebc43a..0000000
--- a/gcc/testsuite/go.test/test/safe/pkg.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// true
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// a package that uses unsafe on the inside but not in it's api
-
-package pkg
-
-import "unsafe"
-
-// this should be inlinable
-func Float32bits(f float32) uint32 {
- return *(*uint32)(unsafe.Pointer(&f))
-} \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/safe/usesafe.go b/gcc/testsuite/go.test/test/safe/usesafe.go
deleted file mode 100644
index 5d0829e..0000000
--- a/gcc/testsuite/go.test/test/safe/usesafe.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// $G $D/pkg.go && pack grcS pkg.a pkg.$A 2> /dev/null && rm pkg.$A && $G -I . -u $D/main.go
-// rm -f pkg.a
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ignored
diff --git a/gcc/testsuite/go.test/test/shift1.go b/gcc/testsuite/go.test/test/shift1.go
index 04f5321..d6a6c38 100644
--- a/gcc/testsuite/go.test/test/shift1.go
+++ b/gcc/testsuite/go.test/test/shift1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -18,13 +18,13 @@ func h(x float64) int { return 0 }
var (
s uint = 33
u = 1.0 << s // ERROR "invalid operation|shift of non-integer operand"
- v float32 = 1 << s // ERROR "invalid" "as type float32"
+ v float32 = 1 << s // ERROR "invalid"
)
// non-constant shift expressions
var (
- e1 = g(2.0 << s) // ERROR "invalid|shift of non-integer operand" "as type interface"
- f1 = h(2 << s) // ERROR "invalid" "as type float64"
+ e1 = g(2.0 << s) // ERROR "invalid|shift of non-integer operand"
+ f1 = h(2 << s) // ERROR "invalid"
g1 int64 = 1.1 << s // ERROR "truncated"
)
@@ -66,8 +66,15 @@ func _() {
u2 = 1<<s != 1.0 // ERROR "non-integer|float64"
v float32 = 1 << s // ERROR "non-integer|float32"
w int64 = 1.0 << 33 // 1.0<<33 is a constant shift expression
+
_, _, _, _, _, _, _, _, _, _ = j, k, m, n, o, u, u1, u2, v, w
)
+
+ // non constants arguments trigger a different path
+ f2 := 1.2
+ s2 := "hi"
+ _ = f2 << 2 // ERROR "shift of type float64|non-integer"
+ _ = s2 << 2 // ERROR "shift of type string|non-integer"
}
// shifts in comparisons w/ untyped operands
@@ -146,8 +153,7 @@ func _() {
var a []int
_ = a[1<<s]
_ = a[1.]
- // For now, the spec disallows these. We may revisit past Go 1.1.
- _ = a[1.<<s] // ERROR "integer|shift of type float64"
+ _ = a[1.<<s]
_ = a[1.1<<s] // ERROR "integer|shift of type float64"
_ = make([]int, 1)
diff --git a/gcc/testsuite/go.test/test/shift2.go b/gcc/testsuite/go.test/test/shift2.go
index 80e6bbc..adbfb77 100644
--- a/gcc/testsuite/go.test/test/shift2.go
+++ b/gcc/testsuite/go.test/test/shift2.go
@@ -1,6 +1,6 @@
// compile
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/sigchld.go b/gcc/testsuite/go.test/test/sigchld.go
index a60d28d..3b49606 100644
--- a/gcc/testsuite/go.test/test/sigchld.go
+++ b/gcc/testsuite/go.test/test/sigchld.go
@@ -1,5 +1,5 @@
-// +build !windows
-// cmpout
+// +build !plan9,!windows
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/sinit.go b/gcc/testsuite/go.test/test/sinit.go
index 5e50e11..df4d50d 100644
--- a/gcc/testsuite/go.test/test/sinit.go
+++ b/gcc/testsuite/go.test/test/sinit.go
@@ -1,17 +1,17 @@
-// $G -S $D/$F.go | egrep initdone >/dev/null && echo BUG sinit || true
+// skip
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that many initializations can be done at link time and
// generate no executable init functions.
+// This test is run by sinit_run.go.
package p
+import "unsafe"
+
// Should be no init func in the assembly.
// All these initializations should be done at link time.
@@ -43,15 +43,12 @@ var c = []int{1201, 1202, 1203}
var aa = [3][3]int{[3]int{2001, 2002, 2003}, [3]int{2004, 2005, 2006}, [3]int{2007, 2008, 2009}}
var as = [3]S{S{2101, 2102, 2103}, S{2104, 2105, 2106}, S{2107, 2108, 2109}}
-var ac = [3][]int{[]int{2201, 2202, 2203}, []int{2204, 2205, 2206}, []int{2207, 2208, 2209}}
var sa = SA{[3]int{3001, 3002, 3003}, [3]int{3004, 3005, 3006}, [3]int{3007, 3008, 3009}}
var ss = SS{S{3101, 3102, 3103}, S{3104, 3105, 3106}, S{3107, 3108, 3109}}
-var sc = SC{[]int{3201, 3202, 3203}, []int{3204, 3205, 3206}, []int{3207, 3208, 3209}}
var ca = [][3]int{[3]int{4001, 4002, 4003}, [3]int{4004, 4005, 4006}, [3]int{4007, 4008, 4009}}
var cs = []S{S{4101, 4102, 4103}, S{4104, 4105, 4106}, S{4107, 4108, 4109}}
-var cc = [][]int{[]int{4201, 4202, 4203}, []int{4204, 4205, 4206}, []int{4207, 4208, 4209}}
var answers = [...]int{
// s
@@ -106,20 +103,27 @@ var answers = [...]int{
}
var (
- copy_zero = zero
- copy_one = one
- copy_pi = pi
- copy_slice = slice
+ copy_zero = zero
+ copy_one = one
+ copy_pi = pi
+ copy_slice = slice
copy_sliceInt = sliceInt
- copy_hello = hello
- copy_bytes = bytes
+ copy_hello = hello
+
+ // Could be handled without an initialization function, but
+ // requires special handling for "a = []byte("..."); b = a"
+ // which is not a likely case.
+ // copy_bytes = bytes
+ // https://codereview.appspot.com/171840043 is one approach to
+ // make this special case work.
+
copy_four, copy_five = four, five
- copy_x, copy_y = x, y
- copy_nilslice = nilslice
- copy_nilmap = nilmap
- copy_nilfunc = nilfunc
- copy_nilchan = nilchan
- copy_nilptr = nilptr
+ copy_x, copy_y = x, y
+ copy_nilslice = nilslice
+ copy_nilmap = nilmap
+ copy_nilfunc = nilfunc
+ copy_nilchan = nilchan
+ copy_nilptr = nilptr
)
var copy_a = a
@@ -128,15 +132,12 @@ var copy_c = c
var copy_aa = aa
var copy_as = as
-var copy_ac = ac
var copy_sa = sa
var copy_ss = ss
-var copy_sc = sc
var copy_ca = ca
var copy_cs = cs
-var copy_cc = cc
var copy_answers = answers
@@ -172,7 +173,7 @@ var sx []int
var s0 = []int{0, 0, 0}
var s1 = []int{1, 2, 3}
-func fi() int
+func fi() int { return 1 }
var ax [10]int
var a0 = [10]int{0, 0, 0}
@@ -202,58 +203,66 @@ var pt0b = &T{X: 0}
var pt1 = &T{X: 1, Y: 2}
var pt1a = &T{3, 4}
-var copy_bx = bx
+// The checks similar to
+// var copy_bx = bx
+// are commented out. The compiler no longer statically initializes them.
+// See issue 7665 and https://codereview.appspot.com/93200044.
+// If https://codereview.appspot.com/169040043 is submitted, and this
+// test is changed to pass -complete to the compiler, then we can
+// uncomment the copy lines again.
+
+// var copy_bx = bx
var copy_b0 = b0
var copy_b1 = b1
-var copy_fx = fx
+// var copy_fx = fx
var copy_f0 = f0
var copy_f1 = f1
-var copy_gx = gx
+// var copy_gx = gx
var copy_g0 = g0
var copy_g1 = g1
-var copy_ix = ix
+// var copy_ix = ix
var copy_i0 = i0
var copy_i1 = i1
-var copy_jx = jx
+// var copy_jx = jx
var copy_j0 = j0
var copy_j1 = j1
-var copy_cx = cx
+// var copy_cx = cx
var copy_c0 = c0
var copy_c1 = c1
-var copy_dx = dx
+// var copy_dx = dx
var copy_d0 = d0
var copy_d1 = d1
-var copy_sx = sx
+// var copy_sx = sx
var copy_s0 = s0
var copy_s1 = s1
-var copy_ax = ax
+// var copy_ax = ax
var copy_a0 = a0
var copy_a1 = a1
-var copy_tx = tx
+// var copy_tx = tx
var copy_t0 = t0
var copy_t0a = t0a
var copy_t0b = t0b
var copy_t1 = t1
var copy_t1a = t1a
-var copy_psx = psx
+// var copy_psx = psx
var copy_ps0 = ps0
var copy_ps1 = ps1
-var copy_pax = pax
+// var copy_pax = pax
var copy_pa0 = pa0
var copy_pa1 = pa1
-var copy_ptx = ptx
+// var copy_ptx = ptx
var copy_pt0 = pt0
var copy_pt0a = pt0a
var copy_pt0b = pt0b
@@ -266,6 +275,11 @@ type T1 int
func (t *T1) M() {}
-type Mer interface { M() }
+type Mer interface {
+ M()
+}
var _ Mer = (*T1)(nil)
+
+var Byte byte
+var PtrByte unsafe.Pointer = unsafe.Pointer(&Byte)
diff --git a/gcc/testsuite/go.test/test/sizeof.go b/gcc/testsuite/go.test/test/sizeof.go
index c3db1e5..3e2689f 100644
--- a/gcc/testsuite/go.test/test/sizeof.go
+++ b/gcc/testsuite/go.test/test/sizeof.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/slice3err.go b/gcc/testsuite/go.test/test/slice3err.go
index 83fb39b..1309fdd 100644
--- a/gcc/testsuite/go.test/test/slice3err.go
+++ b/gcc/testsuite/go.test/test/slice3err.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/stress/maps.go b/gcc/testsuite/go.test/test/stress/maps.go
index d022e19..8ada23a 100644
--- a/gcc/testsuite/go.test/test/stress/maps.go
+++ b/gcc/testsuite/go.test/test/stress/maps.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -97,6 +97,8 @@ func (m intMap) Len() int { return len(m) }
func (m intMap) RangeAll() {
for _ = range m {
}
+ for range m {
+ }
}
func stressMaps() {
diff --git a/gcc/testsuite/go.test/test/stress/parsego.go b/gcc/testsuite/go.test/test/stress/parsego.go
index a781f19..98c4d9a 100644
--- a/gcc/testsuite/go.test/test/stress/parsego.go
+++ b/gcc/testsuite/go.test/test/stress/parsego.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -64,7 +64,7 @@ func parseDir(dirpath string) map[string]*ast.Package {
}
func stressParseGo() {
- pkgroot := runtime.GOROOT() + "/src/pkg/"
+ pkgroot := runtime.GOROOT() + "/src/"
for {
m := make(map[string]map[string]*ast.Package)
for _, pkg := range packages {
diff --git a/gcc/testsuite/go.test/test/stress/runstress.go b/gcc/testsuite/go.test/test/stress/runstress.go
index 76ab2a8..3f16fc9 100644
--- a/gcc/testsuite/go.test/test/stress/runstress.go
+++ b/gcc/testsuite/go.test/test/stress/runstress.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/struct0.go b/gcc/testsuite/go.test/test/struct0.go
index e29eb30..403e977 100644
--- a/gcc/testsuite/go.test/test/struct0.go
+++ b/gcc/testsuite/go.test/test/struct0.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/chan.go b/gcc/testsuite/go.test/test/syntax/chan.go
index 3b68bda..6f9d77d 100644
--- a/gcc/testsuite/go.test/test/syntax/chan.go
+++ b/gcc/testsuite/go.test/test/syntax/chan.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -8,10 +8,10 @@ package main
type xyz struct {
ch chan
-} // ERROR "unexpected .*}.* in channel type"
+} // ERROR "unexpected .*}.* in channel type|missing channel element type"
-func Foo(y chan) { // ERROR "unexpected .*\).* in channel type"
+func Foo(y chan) { // ERROR "unexpected .*\).* in channel type|missing channel element type"
}
-func Bar(x chan, y int) { // ERROR "unexpected comma in channel type"
+func Bar(x chan, y int) { // ERROR "unexpected comma in channel type|missing channel element type"
}
diff --git a/gcc/testsuite/go.test/test/syntax/chan1.go b/gcc/testsuite/go.test/test/syntax/chan1.go
index 4860422..88a5b47 100644
--- a/gcc/testsuite/go.test/test/syntax/chan1.go
+++ b/gcc/testsuite/go.test/test/syntax/chan1.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,8 +10,8 @@ var c chan int
var v int
func main() {
- if c <- v { // ERROR "used as value"
+ if c <- v { // ERROR "cannot use c <- v as value|send statement used as value"
}
}
-var _ = c <- v // ERROR "used as value"
+var _ = c <- v // ERROR "unexpected <-|send statement used as value"
diff --git a/gcc/testsuite/go.test/test/syntax/composite.go b/gcc/testsuite/go.test/test/syntax/composite.go
index 6565334..f891931 100644
--- a/gcc/testsuite/go.test/test/syntax/composite.go
+++ b/gcc/testsuite/go.test/test/syntax/composite.go
@@ -1,11 +1,11 @@
// errorcheck
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
var a = []int{
- 3 // ERROR "need trailing comma before newline in composite literal"
+ 3 // ERROR "need trailing comma before newline in composite literal|expecting comma or }"
}
diff --git a/gcc/testsuite/go.test/test/syntax/else.go b/gcc/testsuite/go.test/test/syntax/else.go
index e985a9c..9537329 100644
--- a/gcc/testsuite/go.test/test/syntax/else.go
+++ b/gcc/testsuite/go.test/test/syntax/else.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/forvar.go b/gcc/testsuite/go.test/test/syntax/forvar.go
deleted file mode 100644
index dc592d2..0000000
--- a/gcc/testsuite/go.test/test/syntax/forvar.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// errorcheck
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-func main() {
- for var x = 0; x < 10; x++ { // ERROR "var declaration not allowed in for initializer"
diff --git a/gcc/testsuite/go.test/test/syntax/if.go b/gcc/testsuite/go.test/test/syntax/if.go
index b2a65f9..c208a9f 100644
--- a/gcc/testsuite/go.test/test/syntax/if.go
+++ b/gcc/testsuite/go.test/test/syntax/if.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/import.go b/gcc/testsuite/go.test/test/syntax/import.go
index f0a7921..8010bed 100644
--- a/gcc/testsuite/go.test/test/syntax/import.go
+++ b/gcc/testsuite/go.test/test/syntax/import.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/interface.go b/gcc/testsuite/go.test/test/syntax/interface.go
index 0b76b54..010d3ce 100644
--- a/gcc/testsuite/go.test/test/syntax/interface.go
+++ b/gcc/testsuite/go.test/test/syntax/interface.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/semi1.go b/gcc/testsuite/go.test/test/syntax/semi1.go
index 6e04281..8eed05c 100644
--- a/gcc/testsuite/go.test/test/syntax/semi1.go
+++ b/gcc/testsuite/go.test/test/syntax/semi1.go
@@ -1,13 +1,13 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func main() {
- if x; y // ERROR "missing .*{.* after if clause|undefined"
+ if x; y // ERROR "expected .*{.* after if clause|undefined"
{
z // GCCGO_ERROR "undefined"
diff --git a/gcc/testsuite/go.test/test/syntax/semi2.go b/gcc/testsuite/go.test/test/syntax/semi2.go
index 23d7bd0..9216789 100644
--- a/gcc/testsuite/go.test/test/syntax/semi2.go
+++ b/gcc/testsuite/go.test/test/syntax/semi2.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/semi3.go b/gcc/testsuite/go.test/test/syntax/semi3.go
index ca070d8..d064ce6 100644
--- a/gcc/testsuite/go.test/test/syntax/semi3.go
+++ b/gcc/testsuite/go.test/test/syntax/semi3.go
@@ -1,13 +1,13 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func main() {
- for x; y; z // ERROR "missing .*{.* after for clause|undefined"
+ for x; y; z // ERROR "expected .*{.* after for clause|undefined"
{
z // GCCGO_ERROR "undefined"
diff --git a/gcc/testsuite/go.test/test/syntax/semi4.go b/gcc/testsuite/go.test/test/syntax/semi4.go
index 99c2d22..08c3547 100644
--- a/gcc/testsuite/go.test/test/syntax/semi4.go
+++ b/gcc/testsuite/go.test/test/syntax/semi4.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -8,7 +8,5 @@ package main
func main() {
for x // GCCGO_ERROR "undefined"
- { // ERROR "missing .*{.* after for clause"
+ { // ERROR "unexpected {, expecting for loop condition|expecting .*{.* after for clause"
z // GCCGO_ERROR "undefined"
-
-
diff --git a/gcc/testsuite/go.test/test/syntax/semi5.go b/gcc/testsuite/go.test/test/syntax/semi5.go
index cf690f0..c54a994 100644
--- a/gcc/testsuite/go.test/test/syntax/semi5.go
+++ b/gcc/testsuite/go.test/test/syntax/semi5.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/semi6.go b/gcc/testsuite/go.test/test/syntax/semi6.go
index c1e1cc3..9bc730d 100644
--- a/gcc/testsuite/go.test/test/syntax/semi6.go
+++ b/gcc/testsuite/go.test/test/syntax/semi6.go
@@ -1,13 +1,11 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
-type T // ERROR "unexpected semicolon or newline in type declaration"
-{
-
-
+type T1 // ERROR "newline in type declaration"
+type T2 /* // ERROR "(semicolon.*|EOF) in type declaration" */ \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/syntax/semi7.go b/gcc/testsuite/go.test/test/syntax/semi7.go
index 6c9ade8..a1948b0 100644
--- a/gcc/testsuite/go.test/test/syntax/semi7.go
+++ b/gcc/testsuite/go.test/test/syntax/semi7.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -8,7 +8,7 @@ package main
func main() {
if x { } // GCCGO_ERROR "undefined"
- else { } // ERROR "unexpected semicolon or newline before .?else.?"
+ else { } // ERROR "unexpected semicolon or newline before .?else.?|unexpected else"
}
diff --git a/gcc/testsuite/go.test/test/syntax/topexpr.go b/gcc/testsuite/go.test/test/syntax/topexpr.go
index c5958f5..be080d2 100644
--- a/gcc/testsuite/go.test/test/syntax/topexpr.go
+++ b/gcc/testsuite/go.test/test/syntax/topexpr.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/typesw.go b/gcc/testsuite/go.test/test/syntax/typesw.go
index cd8cf35..3781933 100644
--- a/gcc/testsuite/go.test/test/syntax/typesw.go
+++ b/gcc/testsuite/go.test/test/syntax/typesw.go
@@ -1,13 +1,13 @@
// errorcheck
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func main() {
- switch main() := interface{}(nil).(type) { // ERROR "invalid variable name"
+ switch main() := interface{}(nil).(type) { // ERROR "invalid variable name|cannot use .* as value"
default:
}
}
diff --git a/gcc/testsuite/go.test/test/syntax/vareq.go b/gcc/testsuite/go.test/test/syntax/vareq.go
index f08955e..0d4bb78 100644
--- a/gcc/testsuite/go.test/test/syntax/vareq.go
+++ b/gcc/testsuite/go.test/test/syntax/vareq.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/syntax/vareq1.go b/gcc/testsuite/go.test/test/syntax/vareq1.go
index e900eab..a2f9f34 100644
--- a/gcc/testsuite/go.test/test/syntax/vareq1.go
+++ b/gcc/testsuite/go.test/test/syntax/vareq1.go
@@ -1,10 +1,10 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
-var x map[string]string{"a":"b"} // ERROR "unexpected { at end of statement|expected ';' or newline after top level declaration"
+var x map[string]string{"a":"b"} // ERROR "unexpected { at end of statement|unexpected { after top level declaration|expected ';' or newline after top level declaration"
diff --git a/gcc/testsuite/go.test/test/testlib b/gcc/testsuite/go.test/test/testlib
deleted file mode 100644
index 4a17f4f..0000000
--- a/gcc/testsuite/go.test/test/testlib
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# These function names are also known to
-# (and are the plan for transitioning to) run.go.
-
-# helper (not known to run.go)
-# group file list by packages and return list of packages
-# each package is a comma-separated list of go files.
-pkgs() {
- pkglist=$(grep -h '^package ' $* | awk '{print $2}' | sort -u)
- for p in $pkglist
- do
- echo $(grep -l "^package $p\$" $*) | tr ' ' ,
- done | sort
-}
-
-_match() {
- case $1 in
- *,*)
- #echo >&2 "match comma separated $1"
- first=$(echo $1 | sed 's/,.*//')
- rest=$(echo $1 | sed 's/[^,]*,//')
- if _match $first && _match $rest; then
- return 0
- fi
- return 1
- ;;
- '!'*)
- #echo >&2 "match negation $1"
- neg=$(echo $1 | sed 's/^!//')
- if _match $neg; then
- return 1
- fi
- return 0
- ;;
- $GOARCH|$GOOS)
- #echo >&2 "match GOARCH or GOOS $1"
- return 0
- ;;
- esac
- return 1
-}
-
-# +build aborts execution if the supplied tags don't match,
-# i.e. none of the tags (x or !x) matches GOARCH or GOOS.
-+build() {
- if (( $# == 0 )); then
- return
- fi
- m=0
- for tag; do
- if _match $tag; then
- m=1
- fi
- done
- if [ $m = 0 ]; then
- #echo >&2 no match
- exit 0
- fi
- unset m
-}
-
-compile() {
- $G $D/$F.go
-}
-
-compiledir() {
- for pkg in $(pkgs $D/$F.dir/*.go)
- do
- $G -I . $(echo $pkg | tr , ' ') || return 1
- done
-}
-
-errorcheckdir() {
- lastzero=""
- if [ "$1" = "-0" ]; then
- lastzero="-0"
- fi
- pkgs=$(pkgs $D/$F.dir/*.go)
- for pkg in $pkgs.last
- do
- zero="-0"
- case $pkg in
- *.last)
- pkg=$(echo $pkg |sed 's/\.last$//')
- zero=$lastzero
- esac
- errchk $zero $G -D . -I . -e $(echo $pkg | tr , ' ')
- done
-}
-
-rundir() {
- lastfile=""
- for pkg in $(pkgs $D/$F.dir/*.go)
- do
- name=$(echo $pkg | sed 's/\.go.*//; s/.*\///')
- $G -D . -I . -e $(echo $pkg | tr , ' ') || return 1
- lastfile=$name
- done
- $L -o $A.out -L . $lastfile.$A
- ./$A.out
-}
-
-rundircmpout() {
- lastfile=""
- for pkg in $(pkgs $D/$F.dir/*.go)
- do
- name=$(echo $pkg | sed 's/\.go.*//; s/.*\///')
- $G -D . -I . -e $(echo $pkg | tr , ' ') || return 1
- lastfile=$name
- done
- $L -o $A.out -L . $lastfile.$A
- ./$A.out 2>&1 | cmp - $D/$F.out
-}
-
-build() {
- $G $D/$F.go && $L $F.$A
-}
-
-runoutput() {
- go run "$D/$F.go" "$@" > tmp.go
- go run tmp.go
-}
-
-run() {
- gofiles=""
- ingo=true
- while $ingo; do
- case "$1" in
- *.go)
- gofiles="$gofiles $1"
- shift
- ;;
- *)
- ingo=false
- ;;
- esac
- done
-
- $G $D/$F.go $gofiles && $L $F.$A && ./$A.out "$@"
-}
-
-cmpout() {
- $G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
-}
-
-errorcheck() {
- zero=""
- if [ "$1" = "-0" ]; then
- zero="-0"
- shift
- fi
- errchk $zero $G -e $* $D/$F.go
-}
-
-errorcheckoutput() {
- zero=""
- if [ "$1" = "-0" ]; then
- zero="-0"
- shift
- fi
- go run "$D/$F.go" "$@" > tmp.go
- errchk $zero $G -e tmp.go
-}
-
-skip() {
- true
-}
diff --git a/gcc/testsuite/go.test/test/torture.go b/gcc/testsuite/go.test/test/torture.go
index bbf6d34..197b481 100644
--- a/gcc/testsuite/go.test/test/torture.go
+++ b/gcc/testsuite/go.test/test/torture.go
@@ -337,3 +337,10 @@ func ChainDivConst(a int) int {
func ChainMulBytes(a, b, c byte) byte {
return a*(a*(a*(a*(a*(a*(a*(a*(a*b+c)+c)+c)+c)+c)+c)+c)+c) + c
}
+
+func ChainCap() {
+ select {
+ case <-make(chan int, cap(make(chan int, cap(make(chan int, cap(make(chan int, cap(make(chan int))))))))):
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/typecheck.go b/gcc/testsuite/go.test/test/typecheck.go
index a2ad91f..4c55d2e 100644
--- a/gcc/testsuite/go.test/test/typecheck.go
+++ b/gcc/testsuite/go.test/test/typecheck.go
@@ -1,5 +1,9 @@
// errorcheck
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
// Verify that the Go compiler will not
// die after running into an undefined
// type in the argument list for a
@@ -8,11 +12,11 @@
package main
-func mine(int b) int { // ERROR "undefined.*b"
- return b + 2 // ERROR "undefined.*b"
+func mine(int b) int { // ERROR "undefined.*b"
+ return b + 2 // ERROR "undefined.*b"
}
func main() {
- mine() // GCCGO_ERROR "not enough arguments"
- c = mine() // ERROR "undefined.*c|not enough arguments" "cannot assign to c"
+ mine() // GCCGO_ERROR "not enough arguments"
+ c = mine() // ERROR "undefined.*c|not enough arguments"
}
diff --git a/gcc/testsuite/go.test/test/typeswitch2.go b/gcc/testsuite/go.test/test/typeswitch2.go
index 6c70307..62c96c8 100644
--- a/gcc/testsuite/go.test/test/typeswitch2.go
+++ b/gcc/testsuite/go.test/test/typeswitch2.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Verify that various erroneous type switches are caught be the compiler.
+// Verify that various erroneous type switches are caught by the compiler.
// Does not compile.
package main
@@ -26,22 +26,12 @@ func whatis(x interface{}) string {
w()
}:
return "rw"
- case interface { // GCCGO_ERROR "duplicate"
+ case interface { // ERROR "duplicate"
w()
r()
- }: // GC_ERROR "duplicate"
+ }:
return "wr"
}
return ""
}
-
-func notused(x interface{}) {
- // The first t is in a different scope than the 2nd t; it cannot
- // be accessed (=> declared and not used error); but it is legal
- // to declare it.
- switch t := 0; t := x.(type) { // ERROR "declared and not used"
- case int:
- _ = t // this is using the t of "t := x.(type)"
- }
-}
diff --git a/gcc/testsuite/go.test/test/typeswitch3.go b/gcc/testsuite/go.test/test/typeswitch3.go
index 287e32e..1388187 100644
--- a/gcc/testsuite/go.test/test/typeswitch3.go
+++ b/gcc/testsuite/go.test/test/typeswitch3.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Verify that erroneous type switches are caught be the compiler.
+// Verify that erroneous type switches are caught by the compiler.
// Issue 2700, among other things.
// Does not compile.
@@ -18,26 +18,39 @@ type I interface {
M()
}
-func main(){
+func main() {
var x I
switch x.(type) {
- case string: // ERROR "impossible"
+ case string: // ERROR "impossible"
println("FAIL")
}
-
+
// Issue 2700: if the case type is an interface, nothing is impossible
-
+
var r io.Reader
-
+
_, _ = r.(io.Writer)
-
+
switch r.(type) {
case io.Writer:
}
-
+
// Issue 2827.
- switch _ := r.(type) { // ERROR "invalid variable name _|no new variables"
+ switch _ := r.(type) { // ERROR "invalid variable name _|no new variables"
}
}
+func noninterface() {
+ var i int
+ switch i.(type) { // ERROR "cannot type switch on non-interface value"
+ case string:
+ case int:
+ }
+ type S struct {
+ name string
+ }
+ var s S
+ switch s.(type) { // ERROR "cannot type switch on non-interface value"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/undef.go b/gcc/testsuite/go.test/test/undef.go
index 0a77e59..61524f3 100644
--- a/gcc/testsuite/go.test/test/undef.go
+++ b/gcc/testsuite/go.test/test/undef.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/varerr.go b/gcc/testsuite/go.test/test/varerr.go
index 22aa932..82ab814 100644
--- a/gcc/testsuite/go.test/test/varerr.go
+++ b/gcc/testsuite/go.test/test/varerr.go
@@ -1,6 +1,6 @@
// errorcheck
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/gcc/testsuite/go.test/test/zerodivide.go b/gcc/testsuite/go.test/test/zerodivide.go
index 9ab2713..214d481 100644
--- a/gcc/testsuite/go.test/test/zerodivide.go
+++ b/gcc/testsuite/go.test/test/zerodivide.go
@@ -28,6 +28,8 @@ var (
i32, j32, k32 int32 = 0, 0, 1
i64, j64, k64 int64 = 0, 0, 1
+ bb = []int16{2, 0}
+
u, v, w uint = 0, 0, 1
u8, v8, w8 uint8 = 0, 0, 1
u16, v16, w16 uint16 = 0, 0, 1
@@ -124,6 +126,10 @@ var errorTests = []ErrorTest{
ErrorTest{"int32 1/0", func() { use(k32 / j32) }, "divide"},
ErrorTest{"int64 1/0", func() { use(k64 / j64) }, "divide"},
+ // From issue 5790, we should ensure that _ assignments
+ // still evaluate and generate zerodivide panics.
+ ErrorTest{"int16 _ = bb[0]/bb[1]", func() { _ = bb[0] / bb[1] }, "divide"},
+
ErrorTest{"uint 0/0", func() { use(u / v) }, "divide"},
ErrorTest{"uint8 0/0", func() { use(u8 / v8) }, "divide"},
ErrorTest{"uint16 0/0", func() { use(u16 / v16) }, "divide"},
@@ -195,9 +201,6 @@ func alike(a, b float64) bool {
func main() {
bad := false
for _, t := range errorTests {
- if t.err != "" {
- continue
- }
err := error_(t.fn)
switch {
case t.err == "" && err == "":
diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 2d8c884..9af87f9 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -37,12 +37,16 @@ load_lib target-libpath.exp
load_lib gcc.exp
load_lib g++.exp
load_lib dejagnu.exp
+load_lib target-supports-dg.exp
# Skip these tests for targets that don't support -lgccjit
if { ![check_effective_target_lgccjit] } {
return
}
+# The default do-what keyword.
+set dg-do-what-default compile
+
# Look for lines of the form:
# definitely lost: 11,316 bytes in 235 blocks
# indirectly lost: 352 bytes in 4 blocks
@@ -379,6 +383,33 @@ proc jit-dg-test { prog do_what extra_tool_flags } {
verbose " do_what: $do_what"
verbose " extra_tool_flags: $extra_tool_flags"
+ global dg-do-what-default
+ set dg-do-what [list ${dg-do-what-default} "" P]
+
+ set tmp [dg-get-options $prog]
+ foreach op $tmp {
+ verbose "Processing option: $op" 3
+ set status [catch "$op" errmsg]
+ if { $status != 0 } {
+ if { 0 && [info exists errorInfo] } {
+ # This also prints a backtrace which will just confuse
+ # testcase writers, so it's disabled.
+ perror "$name: $errorInfo\n"
+ } else {
+ perror "$name: $errmsg for \"$op\"\n"
+ }
+ perror "$name: $errmsg for \"$op\"" 0
+ return
+ }
+ }
+
+ # If we're not supposed to try this test on this target, we're done.
+ if { [lindex ${dg-do-what} 1] == "N" } {
+ unsupported "$name"
+ verbose "$name not supported on this target, skipping it" 3
+ return
+ }
+
# test-threads.c needs to be linked against pthreads
if {[string match "*test-threads.c" $prog]} {
append extra_tool_flags " -lpthread"
diff --git a/gcc/testsuite/jit.dg/test-asm.c b/gcc/testsuite/jit.dg/test-asm.c
new file mode 100644
index 0000000..e7777ee
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-asm.c
@@ -0,0 +1,492 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/**********************************************************************
+ Support fns for creating code.
+ **********************************************************************/
+
+/* Make a "void FUNC_NAME (void)" function with a single block, returning
+ that block. */
+
+static gcc_jit_block *
+make_single_block_func (gcc_jit_context *ctxt, const char *func_name)
+{
+ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+ gcc_jit_function *func
+ = gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ func_name,
+ 0, NULL, 0);
+ return gcc_jit_function_new_block (func, "initial");
+}
+
+static const char *
+get_desc (gcc_jit_extended_asm *ext_asm)
+{
+ return gcc_jit_object_get_debug_string
+ (gcc_jit_extended_asm_as_object (ext_asm));
+}
+
+/**********************************************************************
+ Support fns for verifying code.
+ **********************************************************************/
+
+typedef void (*void_void_fn) (void);
+
+static void_void_fn
+get_test_fn (gcc_jit_result *result, const char *func_name)
+{
+ return (void_void_fn)gcc_jit_result_get_code (result, func_name);
+}
+
+/**********************************************************************
+ test_i386_basic_asm_1: simple example of asm
+ **********************************************************************/
+
+/* Create the equivalent of:
+
+ int src;
+ int dst;
+
+ void test_i386_basic_asm_1 (void)
+ {
+ // Quote from here in docs/topics/asm.rst: example 1: C
+ asm ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
+ // Quote up to here in docs/topics/asm.rst: example 1: C
+ }
+
+ i.e. copy src to dst and add 1 to dst. */
+
+static void
+create_test_i386_basic_asm_1 (gcc_jit_context *ctxt)
+{
+ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_lvalue *dst
+ = gcc_jit_context_new_global (ctxt, NULL,
+ GCC_JIT_GLOBAL_EXPORTED,
+ int_type, "dst");
+ gcc_jit_lvalue *src
+ = gcc_jit_context_new_global (ctxt, NULL,
+ GCC_JIT_GLOBAL_EXPORTED,
+ int_type, "src");
+
+ gcc_jit_block *block
+ = make_single_block_func (ctxt, "test_i386_basic_asm_1");
+
+ /* Quote from here in docs/topics/asm.rst: example 1: jit. */
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_add_extended_asm (block, NULL,
+ "mov %1, %0\n\t"
+ "add $1, %0");
+ gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst);
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_lvalue_as_rvalue (src));
+ /* Quote up to here in docs/topics/asm.rst: example 1: jit. */
+
+ const char *desc = get_desc (ext_asm);
+ CHECK_STRING_VALUE
+ (desc,
+ "asm (\"mov %1, %0\\n\\tadd $1, %0\" : \"=r\" (dst) : \"r\" (src) : )");
+
+ gcc_jit_block_end_with_void_return (block, NULL);
+}
+
+static void
+verify_code_1 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ void_void_fn test_i386_basic_asm_1
+ = get_test_fn (result, "test_i386_basic_asm_1");
+ CHECK_NON_NULL (test_i386_basic_asm_1);
+
+ int *dst_ptr = (int *)gcc_jit_result_get_global (result, "dst");
+ CHECK_NON_NULL (dst_ptr);
+ int *src_ptr = (int *)gcc_jit_result_get_global (result, "src");
+ CHECK_NON_NULL (src_ptr);
+
+ *src_ptr = 42;
+ *dst_ptr = 0;
+ test_i386_basic_asm_1 ();
+ CHECK_VALUE (*src_ptr, 42);
+ CHECK_VALUE (*dst_ptr, 43);
+}
+
+/**********************************************************************
+ test_i386_basic_asm_2: test of symbolic names and clobbers
+ **********************************************************************/
+
+/* Create the equivalent of:
+ uint32_t test_i386_basic_asm_2 (uint32_t Mask)
+ {
+ uint32_t Index;
+ // Quote from here in docs/topics/asm.rst: example 2: C
+ asm ("bsfl %[aMask], %[aIndex]"
+ : [aIndex] "=r" (Index)
+ : [aMask] "r" (Mask)
+ : "cc");
+ // Quote up to here in docs/topics/asm.rst: example 2: C
+ return Index;
+ }
+ i.e. return the first bit set in "Mask"
+
+ This exercises symbolic names and clobbers. */
+
+static void
+create_test_i386_basic_asm_2 (gcc_jit_context *ctxt)
+{
+ gcc_jit_type *uint32_type = gcc_jit_context_get_int_type (ctxt, 4, 0);
+ gcc_jit_param *mask
+ = gcc_jit_context_new_param (ctxt, NULL,
+ uint32_type, "Mask");
+ gcc_jit_function *func
+ = gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ uint32_type,
+ "test_i386_basic_asm_2",
+ 1, &mask, 0);
+ gcc_jit_lvalue *index
+ = gcc_jit_function_new_local (func, NULL,
+ uint32_type, "Index");
+ gcc_jit_block *block = gcc_jit_function_new_block (func, "initial");
+
+ /* Quote from here in docs/topics/asm.rst: example 2: jit. */
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_add_extended_asm (block, NULL,
+ "bsfl %[aMask], %[aIndex]");
+ gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index);
+ gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r",
+ gcc_jit_param_as_rvalue (mask));
+ gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
+ /* Quote up to here in docs/topics/asm.rst: example 2: jit. */
+
+ const char *desc = get_desc (ext_asm);
+ CHECK_STRING_VALUE
+ (desc,
+ "asm (\"bsfl %[aMask], %[aIndex]\""
+ " : [aIndex] \"=r\" (Index) : [aMask] \"r\" (Mask) : \"cc\")");
+
+ gcc_jit_block_end_with_return (block, NULL,
+ gcc_jit_lvalue_as_rvalue (index));
+}
+
+static void
+verify_code_2 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef uint32_t (*fntype) (uint32_t);
+ fntype test_i386_basic_asm_2
+ = (fntype)gcc_jit_result_get_code (result, "test_i386_basic_asm_2");
+ CHECK_NON_NULL (test_i386_basic_asm_2);
+
+ CHECK_VALUE (test_i386_basic_asm_2 (1), 0);
+ CHECK_VALUE (test_i386_basic_asm_2 (2), 1);
+ CHECK_VALUE (test_i386_basic_asm_2 (4), 2);
+ CHECK_VALUE (test_i386_basic_asm_2 (8), 3);
+}
+
+/**********************************************************************
+ test_i386_basic_asm_3a/b: test of control flow: "asm goto"
+ **********************************************************************/
+
+/* Create the equivalent of:
+
+ int test_i386_basic_asm_3a (int p1, int p2)
+ {
+ asm goto ("btl %1, %0\n\t"
+ "jc %l2"
+ : // No outputs
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+
+ return 0;
+
+ carry:
+ return 1;
+ }
+
+ or (the "_3b" variant) using a name rather than a number for the goto
+ label:
+
+ // Quote from here in docs/topics/asm.rst: example 3b: C
+ asm goto ("btl %1, %0\n\t"
+ "jc %l[carry]"
+ : // No outputs
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+ // Quote up to here in docs/topics/asm.rst: example 3b: C
+
+ This exercises control flow with an asm. */
+
+static void
+create_test_i386_basic_asm_3 (gcc_jit_context *ctxt,
+ const char *funcname,
+ int use_name)
+{
+ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_param *p1 = gcc_jit_context_new_param (ctxt, NULL, int_type, "p1");
+ gcc_jit_param *p2 = gcc_jit_context_new_param (ctxt, NULL, int_type, "p2");
+ gcc_jit_param *params[2] = {p1, p2};
+ gcc_jit_function *func
+ = gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ funcname,
+ 2, params, 0);
+ gcc_jit_block *b_start = gcc_jit_function_new_block (func, "start");
+ gcc_jit_block *b_fallthru = gcc_jit_function_new_block (func, "fallthru");
+ gcc_jit_block *b_carry = gcc_jit_function_new_block (func, "carry");
+
+ gcc_jit_rvalue *zero
+ = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0);
+ gcc_jit_rvalue *one
+ = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1);
+
+ /* Quote from here in docs/topics/asm.rst: example 3: jit. */
+ const char *asm_template =
+ (use_name
+ ? /* Label referred to by name: "%l[carry]". */
+ ("btl %1, %0\n\t"
+ "jc %l[carry]")
+ : /* Label referred to numerically: "%l2". */
+ ("btl %1, %0\n\t"
+ "jc %l2"));
+
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_end_with_extended_asm_goto (b_start, NULL,
+ asm_template,
+ 1, &b_carry,
+ b_fallthru);
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_param_as_rvalue (p1));
+ gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
+ gcc_jit_param_as_rvalue (p2));
+ gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
+ /* Quote up to here in docs/topics/asm.rst: example 3: jit. */
+
+ const char *desc = get_desc (ext_asm);
+ CHECK_STRING_VALUE
+ (desc,
+ (use_name
+ ? ("asm goto (\"btl %1, %0\\n\\tjc %l[carry]\" "
+ ": : \"r\" (p1), \"r\" (p2) : \"cc\" "
+ ": carry [fallthrough: fallthru])")
+ : ("asm goto (\"btl %1, %0\\n\\tjc %l2\" "
+ ": : \"r\" (p1), \"r\" (p2) : \"cc\" "
+ ": carry [fallthrough: fallthru])")));
+
+ gcc_jit_block_end_with_return (b_fallthru, NULL, zero);
+ gcc_jit_block_end_with_return (b_carry, NULL, one);
+}
+
+static void
+verify_code_3 (gcc_jit_context *ctxt, gcc_jit_result *result,
+ const char *funcname)
+{
+ typedef int (*test_i386_basic_asm_3_type) (int, int);
+
+ test_i386_basic_asm_3_type test_i386_basic_asm_3
+ = (test_i386_basic_asm_3_type) gcc_jit_result_get_code (result, funcname);
+ CHECK_NON_NULL (test_i386_basic_asm_3);
+
+ /* The fn should test bits, returning 0 or 1. */
+ /* Bit 0. */
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0000, 0), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0001, 0), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0002, 0), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0003, 0), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0004, 0), 0);
+ /* Bit 1. */
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0000, 1), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0001, 1), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0002, 1), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0003, 1), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0004, 1), 0);
+
+ for (int i = 0; i < 15; i++)
+ {
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0000, i), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0xffff, i), 1);
+ }
+}
+
+/**********************************************************************
+ test_i386_basic_asm_4: test of "volatile"
+ **********************************************************************/
+
+/* Create the equivalent of:
+ uint64_t test_i386_basic_asm_4 (void)
+ {
+ uint64_t start_time, end_time;
+
+ // Get start time
+ asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (start_time)
+ :
+ : "rdx");
+
+ // could do other work here
+
+ // Get end time
+ asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (start_time)
+ :
+ : "rdx");
+
+ // Get elapsed time
+ return end_time - start_time;
+ }
+
+ This exercises "volatile"; without it, the optimizer can assume that
+ both asm generate the same value and thus the time difference is zero. */
+
+static void
+add_rdtsc (gcc_jit_block *block, gcc_jit_lvalue *msr)
+{
+ /* Quote from here in docs/topics/asm.rst: example 4: jit. */
+ gcc_jit_extended_asm *ext_asm
+ = gcc_jit_block_add_extended_asm
+ (block, NULL,
+ "rdtsc\n\t" /* Returns the time in EDX:EAX. */
+ "shl $32, %%rdx\n\t" /* Shift the upper bits left. */
+ "or %%rdx, %0"); /* 'Or' in the lower bits. */
+ gcc_jit_extended_asm_set_volatile_flag (ext_asm, 1);
+ gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=a", msr);
+ gcc_jit_extended_asm_add_clobber (ext_asm, "rdx");
+ /* Quote up to here in docs/topics/asm.rst: example 4: jit. */
+
+ const char *desc = get_desc (ext_asm);
+ CHECK_STRING_STARTS_WITH (desc, "asm volatile (");
+}
+
+static void
+create_test_i386_basic_asm_4 (gcc_jit_context *ctxt)
+{
+ gcc_jit_type *uint64_type = gcc_jit_context_get_int_type (ctxt, 8, 0);
+ gcc_jit_function *func
+ = gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ uint64_type,
+ "test_i386_basic_asm_4",
+ 0, NULL, 0);
+ gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);
+
+ gcc_jit_lvalue *start_time
+ = gcc_jit_function_new_local (func, NULL, uint64_type, "start_time");
+ add_rdtsc (block, start_time);
+
+ gcc_jit_block_add_comment (block, NULL, "other work here");
+
+ gcc_jit_lvalue *end_time
+ = gcc_jit_function_new_local (func, NULL, uint64_type, "end_time");
+ add_rdtsc (block, end_time);
+
+ gcc_jit_rvalue *elapsed
+ = gcc_jit_context_new_binary_op (ctxt, NULL, GCC_JIT_BINARY_OP_MINUS,
+ uint64_type,
+ gcc_jit_lvalue_as_rvalue (end_time),
+ gcc_jit_lvalue_as_rvalue (start_time));
+ gcc_jit_block_end_with_return (block, NULL, elapsed);
+}
+
+static void
+verify_code_4 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef uint64_t (*fntype) (void);
+ fntype test_i386_basic_asm_4
+ = (fntype)gcc_jit_result_get_code (result, "test_i386_basic_asm_4");
+
+ CHECK_NON_NULL (test_i386_basic_asm_4);
+
+ test_i386_basic_asm_4 ();
+}
+
+/**********************************************************************
+ test_i386_basic_asm_5: test of top-level asm
+ **********************************************************************/
+
+/* Create the equivalent of:
+
+ // Quote from here in docs/topics/asm.rst: example 5: C
+ asm ("\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t.popsection\n");
+ // Quote up to here in docs/topics/asm.rst: example 5: C
+
+ to add a simple function ("add_asm") directly in assembly language. */
+
+static void
+create_test_i386_basic_asm_5 (gcc_jit_context *ctxt)
+{
+ /* Quote from here in docs/topics/asm.rst: example 5: jit. */
+ gcc_jit_context_add_top_level_asm (ctxt, NULL,
+ "\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t# some asm here\n"
+ "\t.popsection\n");
+ /* Quote up to here in docs/topics/asm.rst: example 5: jit. */
+}
+
+static void
+verify_code_5 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*test_i386_basic_asm_5_type) (int, int);
+ test_i386_basic_asm_5_type test_i386_basic_asm_5
+ = (test_i386_basic_asm_5_type) gcc_jit_result_get_code (result, "add_asm");
+ CHECK_NON_NULL (test_i386_basic_asm_5);
+
+ CHECK_VALUE (test_i386_basic_asm_5 (2, 2), 4);
+ CHECK_VALUE (test_i386_basic_asm_5 (20, 7), 27);
+}
+
+/**********************************************************************
+ Code for harness
+ **********************************************************************/
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ create_test_i386_basic_asm_1 (ctxt);
+ create_test_i386_basic_asm_2 (ctxt);
+ create_test_i386_basic_asm_3 (ctxt, "test_i386_basic_asm_3a", 0);
+ create_test_i386_basic_asm_3 (ctxt, "test_i386_basic_asm_3b", 1);
+ create_test_i386_basic_asm_4 (ctxt);
+ create_test_i386_basic_asm_5 (ctxt);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+ verify_code_1 (ctxt, result);
+ verify_code_2 (ctxt, result);
+ verify_code_3 (ctxt, result, "test_i386_basic_asm_3a");
+ verify_code_3 (ctxt, result, "test_i386_basic_asm_3b");
+ verify_code_4 (ctxt, result);
+ verify_code_5 (ctxt, result);
+}
diff --git a/gcc/testsuite/jit.dg/test-asm.cc b/gcc/testsuite/jit.dg/test-asm.cc
new file mode 100644
index 0000000..6f18280
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-asm.cc
@@ -0,0 +1,453 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+#include "libgccjit++.h"
+
+#include "harness.h"
+
+/**********************************************************************
+ Support fns for creating code.
+ **********************************************************************/
+
+/* Make a "void FUNC_NAME (void)" function with a single block, returning
+ that block. */
+
+static gccjit::block
+make_single_block_func (gccjit::context ctxt, const char *func_name)
+{
+ gccjit::type void_type = ctxt.get_type (GCC_JIT_TYPE_VOID);
+ std::vector<gccjit::param> params;
+ gccjit::function func
+ = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ func_name, params, 0);
+ return func.new_block ("initial");
+}
+
+/**********************************************************************
+ Support fns for verifying code.
+ **********************************************************************/
+
+typedef void (*void_void_fn) (void);
+
+static void_void_fn
+get_test_fn (gcc_jit_result *result, const char *func_name)
+{
+ return (void_void_fn)gcc_jit_result_get_code (result, func_name);
+}
+
+/**********************************************************************
+ test_i386_basic_asm_1: simple example of asm
+ **********************************************************************/
+
+/* Create the equivalent of:
+
+ int src;
+ int dst;
+
+ void test_i386_basic_asm_1 (void)
+ {
+ // Quote from here in docs/cp/topics/asm.rst: example 1: C
+ asm ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
+ // Quote up to here in docs/cp/topics/asm.rst: example 1: C
+ }
+
+ i.e. copy src to dst and add 1 to dst. */
+
+static void
+create_test_i386_basic_asm_1 (gcc_jit_context *c_ctxt)
+{
+ gccjit::context ctxt (c_ctxt);
+ gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
+ gccjit::lvalue dst
+ = ctxt.new_global (GCC_JIT_GLOBAL_EXPORTED, int_type, "dst");
+ gccjit::lvalue src
+ = ctxt.new_global (GCC_JIT_GLOBAL_EXPORTED, int_type, "src");
+
+ gccjit::block block
+ = make_single_block_func (ctxt, "test_i386_basic_asm_1");
+
+ gccjit::extended_asm ext_asm =
+ /* Quote from here in docs/cp/topics/asm.rst: example 1: jit. */
+ block.add_extended_asm ("mov %1, %0\n\t"
+ "add $1, %0")
+ .add_output_operand ("=r", dst)
+ .add_input_operand ("r", src);
+ /* Quote up to here in docs/cp/topics/asm.rst: example 1: jit. */
+
+ std::string desc = ext_asm.get_debug_string ();
+ CHECK_STRING_VALUE
+ (desc.c_str (),
+ "asm (\"mov %1, %0\\n\\tadd $1, %0\" : \"=r\" (dst) : \"r\" (src) : )");
+
+ block.end_with_return ();
+}
+
+static void
+verify_code_1 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ void_void_fn test_i386_basic_asm_1
+ = get_test_fn (result, "test_i386_basic_asm_1");
+ CHECK_NON_NULL (test_i386_basic_asm_1);
+
+ int *dst_ptr = (int *)gcc_jit_result_get_global (result, "dst");
+ CHECK_NON_NULL (dst_ptr);
+ int *src_ptr = (int *)gcc_jit_result_get_global (result, "src");
+ CHECK_NON_NULL (src_ptr);
+
+ *src_ptr = 42;
+ *dst_ptr = 0;
+ test_i386_basic_asm_1 ();
+ CHECK_VALUE (*src_ptr, 42);
+ CHECK_VALUE (*dst_ptr, 43);
+}
+
+/**********************************************************************
+ test_i386_basic_asm_2: test of symbolic names and clobbers
+ **********************************************************************/
+
+/* Create the equivalent of:
+ uint32_t test_i386_basic_asm_2 (uint32_t Mask)
+ {
+ uint32_t Index;
+ // Quote from here in docs/cp/topics/asm.rst: example 2: C
+ asm ("bsfl %[aMask], %[aIndex]"
+ : [aIndex] "=r" (Index)
+ : [aMask] "r" (Mask)
+ : "cc");
+ // Quote up to here in docs/cp/topics/asm.rst: example 2: C
+ return Index;
+ }
+ i.e. return the first bit set in "Mask"
+
+ This exercises symbolic names and clobbers. */
+
+static void
+create_test_i386_basic_asm_2 (gcc_jit_context *c_ctxt)
+{
+ gccjit::context ctxt (c_ctxt);
+ gccjit::type uint32_type = ctxt.get_int_type (4, 0);
+ gccjit::param mask = ctxt.new_param (uint32_type, "Mask");
+ std::vector<gccjit::param> params {mask};
+ gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ uint32_type,
+ "test_i386_basic_asm_2",
+ params, 0);
+ gccjit::lvalue index = func.new_local (uint32_type, "Index");
+ gccjit::block block = func.new_block ("initial");
+ gccjit::extended_asm ext_asm =
+ /* Quote from here in docs/cp/topics/asm.rst: example 2: jit. */
+ block.add_extended_asm ("bsfl %[aMask], %[aIndex]")
+ .add_output_operand ("aIndex", "=r", index)
+ .add_input_operand ("aMask", "r", mask)
+ .add_clobber ("cc");
+ /* Quote up to here in docs/cp/topics/asm.rst: example 2: jit. */
+
+ std::string desc = ext_asm.get_debug_string ();
+ CHECK_STRING_VALUE
+ (desc.c_str (),
+ "asm (\"bsfl %[aMask], %[aIndex]\""
+ " : [aIndex] \"=r\" (Index) : [aMask] \"r\" (Mask) : \"cc\")");
+
+ block.end_with_return (index);
+}
+
+static void
+verify_code_2 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef uint32_t (*fntype) (uint32_t);
+ fntype test_i386_basic_asm_2
+ = (fntype)gcc_jit_result_get_code (result, "test_i386_basic_asm_2");
+ CHECK_NON_NULL (test_i386_basic_asm_2);
+
+ CHECK_VALUE (test_i386_basic_asm_2 (1), 0);
+ CHECK_VALUE (test_i386_basic_asm_2 (2), 1);
+ CHECK_VALUE (test_i386_basic_asm_2 (4), 2);
+ CHECK_VALUE (test_i386_basic_asm_2 (8), 3);
+}
+
+/**********************************************************************
+ test_i386_basic_asm_3a/b: test of control flow: "asm goto"
+ **********************************************************************/
+
+/* Create the equivalent of:
+
+ int test_i386_basic_asm_3a (int p1, int p2)
+ {
+ asm goto ("btl %1, %0\n\t"
+ "jc %l2"
+ : // No outputs
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+
+ return 0;
+
+ carry:
+ return 1;
+ }
+
+ or (the "_3b" variant) using a name rather than a number for the goto
+ label:
+
+ // Quote from here in docs/cp/topics/asm.rst: example 3b: C
+ asm goto ("btl %1, %0\n\t"
+ "jc %l[carry]"
+ : // No outputs
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+ // Quote up to here in docs/cp/topics/asm.rst: example 3b: C
+
+ This exercises control flow with an asm. */
+
+static void
+create_test_i386_basic_asm_3 (gcc_jit_context *c_ctxt,
+ const char *funcname,
+ int use_name)
+{
+ gccjit::context ctxt (c_ctxt);
+ gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
+ gccjit::param p1 = ctxt.new_param (int_type, "p1");
+ gccjit::param p2 = ctxt.new_param (int_type, "p2");
+ std::vector<gccjit::param> params ({p1, p2});
+ gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ funcname,
+ params, 0);
+ gccjit::block b_start = func.new_block ("start");
+ gccjit::block b_fallthru = func.new_block ("fallthru");
+ gccjit::block b_carry = func.new_block ("carry");
+
+ gccjit::rvalue zero = ctxt.new_rvalue (int_type, 0);
+ gccjit::rvalue one = ctxt.new_rvalue (int_type, 1);
+
+ /* Quote from here in docs/cp/topics/asm.rst: example 3: jit. */
+ const char *asm_template =
+ (use_name
+ ? /* Label referred to by name: "%l[carry]". */
+ ("btl %1, %0\n\t"
+ "jc %l[carry]")
+ : /* Label referred to numerically: "%l2". */
+ ("btl %1, %0\n\t"
+ "jc %l2"));
+
+ std::vector<gccjit::block> goto_blocks ({b_carry});
+ gccjit::extended_asm ext_asm
+ = (b_start.end_with_extended_asm_goto (asm_template,
+ goto_blocks,
+ &b_fallthru)
+ .add_input_operand ("r", p1)
+ .add_input_operand ("r", p2)
+ .add_clobber ("cc"));
+ /* Quote up to here in docs/cp/topics/asm.rst: example 3: jit. */
+
+ std::string desc = ext_asm.get_debug_string ();
+ CHECK_STRING_VALUE
+ (desc.c_str (),
+ (use_name
+ ? ("asm goto (\"btl %1, %0\\n\\tjc %l[carry]\" "
+ ": : \"r\" (p1), \"r\" (p2) : \"cc\" "
+ ": carry [fallthrough: fallthru])")
+ : ("asm goto (\"btl %1, %0\\n\\tjc %l2\" "
+ ": : \"r\" (p1), \"r\" (p2) : \"cc\" "
+ ": carry [fallthrough: fallthru])")));
+
+ b_fallthru.end_with_return (zero);
+ b_carry.end_with_return (one);
+}
+
+static void
+verify_code_3 (gcc_jit_context *ctxt, gcc_jit_result *result,
+ const char *funcname)
+{
+ typedef int (*test_i386_basic_asm_3_type) (int, int);
+
+ test_i386_basic_asm_3_type test_i386_basic_asm_3
+ = (test_i386_basic_asm_3_type) gcc_jit_result_get_code (result, funcname);
+ CHECK_NON_NULL (test_i386_basic_asm_3);
+
+ /* The fn should test bits, returning 0 or 1. */
+ /* Bit 0. */
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0000, 0), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0001, 0), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0002, 0), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0003, 0), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0004, 0), 0);
+ /* Bit 1. */
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0000, 1), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0001, 1), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0002, 1), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0003, 1), 1);
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0004, 1), 0);
+
+ for (int i = 0; i < 15; i++)
+ {
+ CHECK_VALUE (test_i386_basic_asm_3 (0x0000, i), 0);
+ CHECK_VALUE (test_i386_basic_asm_3 (0xffff, i), 1);
+ }
+}
+
+/**********************************************************************
+ test_i386_basic_asm_4: test of "volatile"
+ **********************************************************************/
+
+/* Create the equivalent of:
+ uint64_t test_i386_basic_asm_4 (void)
+ {
+ uint64_t start_time, end_time;
+
+ // Get start time
+ asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (start_time)
+ :
+ : "rdx");
+
+ // could do other work here
+
+ // Get end time
+ asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (start_time)
+ :
+ : "rdx");
+
+ // Get elapsed time
+ return end_time - start_time;
+ }
+
+ This exercises "volatile"; without it, the optimizer can assume that
+ both asm generate the same value and thus the time difference is zero. */
+
+static void
+add_rdtsc (gccjit::block block, gccjit::lvalue msr)
+{
+ /* Quote from here in docs/cp/topics/asm.rst: example 4: jit. */
+ gccjit::extended_asm ext_asm
+ = block.add_extended_asm
+ ("rdtsc\n\t" /* Returns the time in EDX:EAX. */
+ "shl $32, %%rdx\n\t" /* Shift the upper bits left. */
+ "or %%rdx, %0") /* 'Or' in the lower bits. */
+ .set_volatile_flag (true)
+ .add_output_operand ("=a", msr)
+ .add_clobber ("rdx");
+ /* Quote up to here in docs/cp/topics/asm.rst: example 4: jit. */
+
+ std::string desc = ext_asm.get_debug_string ();
+ CHECK_STRING_STARTS_WITH (desc.c_str (), "asm volatile (");
+}
+
+static void
+create_test_i386_basic_asm_4 (gcc_jit_context *c_ctxt)
+{
+ gccjit::context ctxt (c_ctxt);
+ gccjit::type uint64_type = ctxt.get_int_type (8, 0);
+ std::vector<gccjit::param> params;
+ gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ uint64_type,
+ "test_i386_basic_asm_4",
+ params, 0);
+ gccjit::block block = func.new_block ();
+
+ gccjit::lvalue start_time = func.new_local (uint64_type, "start_time");
+ add_rdtsc (block, start_time);
+
+ block.add_comment ("other work here");
+
+ gccjit::lvalue end_time = func.new_local (uint64_type, "end_time");
+ add_rdtsc (block, end_time);
+
+ block.end_with_return (end_time - start_time);
+}
+
+static void
+verify_code_4 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef uint64_t (*fntype) (void);
+ fntype test_i386_basic_asm_4
+ = (fntype)gcc_jit_result_get_code (result, "test_i386_basic_asm_4");
+
+ CHECK_NON_NULL (test_i386_basic_asm_4);
+
+ test_i386_basic_asm_4 ();
+}
+
+/**********************************************************************
+ test_i386_basic_asm_5: test of top-level asm
+ **********************************************************************/
+
+/* Create the equivalent of:
+
+ // Quote from here in docs/cp/topics/asm.rst: example 5: C
+ asm ("\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t.popsection\n");
+ // Quote up to here in docs/cp/topics/asm.rst: example 5: C
+
+ to add a simple function ("add_asm") directly in assembly language. */
+
+static void
+create_test_i386_basic_asm_5 (gcc_jit_context *c_ctxt)
+{
+ gccjit::context ctxt (c_ctxt);
+ /* Quote from here in docs/cp/topics/asm.rst: example 5: jit. */
+ ctxt.add_top_level_asm ("\t.pushsection .text\n"
+ "\t.globl add_asm\n"
+ "\t.type add_asm, @function\n"
+ "add_asm:\n"
+ "\tmovq %rdi, %rax\n"
+ "\tadd %rsi, %rax\n"
+ "\tret\n"
+ "\t# some asm here\n"
+ "\t.popsection\n");
+ /* Quote up to here in docs/cp/topics/asm.rst: example 5: jit. */
+}
+
+static void
+verify_code_5 (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*test_i386_basic_asm_5_type) (int, int);
+ test_i386_basic_asm_5_type test_i386_basic_asm_5
+ = (test_i386_basic_asm_5_type) gcc_jit_result_get_code (result, "add_asm");
+ CHECK_NON_NULL (test_i386_basic_asm_5);
+
+ CHECK_VALUE (test_i386_basic_asm_5 (2, 2), 4);
+ CHECK_VALUE (test_i386_basic_asm_5 (20, 7), 27);
+}
+
+/**********************************************************************
+ Code for harness
+ **********************************************************************/
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ create_test_i386_basic_asm_1 (ctxt);
+ create_test_i386_basic_asm_2 (ctxt);
+ create_test_i386_basic_asm_3 (ctxt, "test_i386_basic_asm_3a", 0);
+ create_test_i386_basic_asm_3 (ctxt, "test_i386_basic_asm_3b", 1);
+ create_test_i386_basic_asm_4 (ctxt);
+ create_test_i386_basic_asm_5 (ctxt);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+ verify_code_1 (ctxt, result);
+ verify_code_2 (ctxt, result);
+ verify_code_3 (ctxt, result, "test_i386_basic_asm_3a");
+ verify_code_3 (ctxt, result, "test_i386_basic_asm_3b");
+ verify_code_4 (ctxt, result);
+ verify_code_5 (ctxt, result);
+}
diff --git a/gcc/testsuite/jit.dg/test-debug-strings.c b/gcc/testsuite/jit.dg/test-debug-strings.c
index e515a17..03ef337 100644
--- a/gcc/testsuite/jit.dg/test-debug-strings.c
+++ b/gcc/testsuite/jit.dg/test-debug-strings.c
@@ -178,6 +178,26 @@ create_code (gcc_jit_context *ctxt, void *user_data)
"((struct node *)ptr->next)->next");
}
+ /* Check string literal escaping. */
+ {
+ CHECK_RVALUE_DEBUG_STRING
+ (gcc_jit_context_new_string_literal (ctxt, ""),
+ "\"\"");
+ CHECK_RVALUE_DEBUG_STRING
+ (gcc_jit_context_new_string_literal (ctxt, "foo"),
+ "\"foo\"");
+ CHECK_RVALUE_DEBUG_STRING
+ (gcc_jit_context_new_string_literal (ctxt, "\""),
+ "\"\\\"\"");
+ CHECK_RVALUE_DEBUG_STRING
+ (gcc_jit_context_new_string_literal (ctxt, "line 1\nline 2\n"),
+ "\"line 1\\nline 2\\n\"");
+ CHECK_RVALUE_DEBUG_STRING
+ (gcc_jit_context_new_string_literal (ctxt, "foo\tbar"),
+ "\"foo\\tbar\"");
+ }
+
+#undef CHECK_RVALUE_DEBUG_STRING
#undef CHECK_LVALUE_DEBUG_STRING
}
diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp
index 2124607..8f96751 100644
--- a/gcc/testsuite/lib/asan-dg.exp
+++ b/gcc/testsuite/lib/asan-dg.exp
@@ -16,6 +16,9 @@
# Return 1 if compilation with -fsanitize=address is error-free for trivial
# code, 0 otherwise.
+#
+# NOTE: This should only be used between calls to asan_init and asan_finish.
+# It is therefore defined here rather than in target-supports.exp.
proc check_effective_target_fsanitize_address {} {
if ![check_no_compiler_messages fsanitize_address executable {
@@ -58,33 +61,33 @@ proc asan_include_flags {} {
# (originally from g++.exp)
#
-proc asan_link_flags { paths } {
+proc asan_link_flags_1 { paths lib } {
global srcdir
global ld_library_path
global shlib_ext
- global asan_saved_library_path
+ global ${lib}_saved_library_path
set gccpath ${paths}
set flags ""
set shlib_ext [get_shlib_extension]
- set asan_saved_library_path $ld_library_path
+ set ${lib}_saved_library_path $ld_library_path
if { $gccpath != "" } {
- if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"]
- || [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.${shlib_ext}"] } {
+ if { [file exists "${gccpath}/libsanitizer/${lib}/.libs/lib${lib}.a"]
+ || [file exists "${gccpath}/libsanitizer/${lib}/.libs/lib${lib}.${shlib_ext}"] } {
append flags " -B${gccpath}/libsanitizer/ "
- append flags " -B${gccpath}/libsanitizer/asan/ "
- append flags " -L${gccpath}/libsanitizer/asan/.libs "
- append ld_library_path ":${gccpath}/libsanitizer/asan/.libs"
+ append flags " -B${gccpath}/libsanitizer/${lib}/ "
+ append flags " -L${gccpath}/libsanitizer/${lib}/.libs "
+ append ld_library_path ":${gccpath}/libsanitizer/${lib}/.libs"
}
} else {
global tool_root_dir
- set libasan [lookfor_file ${tool_root_dir} libasan]
- if { $libasan != "" } {
- append flags "-L${libasan} "
- append ld_library_path ":${libasan}"
+ set libdir [lookfor_file ${tool_root_dir} lib${lib}]
+ if { $libdir != "" } {
+ append flags "-L${libdir} "
+ append ld_library_path ":${libdir}"
}
}
@@ -93,6 +96,10 @@ proc asan_link_flags { paths } {
return "$flags"
}
+proc asan_link_flags { paths } {
+ return [asan_link_flags_1 $paths asan]
+}
+
#
# asan_init -- called at the start of each subdir of tests
#
@@ -151,8 +158,10 @@ proc asan_finish { args } {
unset TEST_ALWAYS_FLAGS
}
}
- set ld_library_path $asan_saved_library_path
- set_ld_library_path_env_vars
+ if [info exists asan_saved_library_path ] {
+ set ld_library_path $asan_saved_library_path
+ set_ld_library_path_env_vars
+ }
clear_effective_target_cache
}
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index e8ad305..700529a 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -1232,7 +1232,7 @@ proc dg-optimized { args } {
# Make this variable available here and to the saved proc.
upvar dg-messages dg-messages
- process-message saved-dg-error "optimized: " "$args"
+ process-message saved-dg-warning "optimized:" "$args"
}
# Handle output from -fopt-info for MSG_MISSED_OPTIMIZATION:
@@ -1242,7 +1242,7 @@ proc dg-missed { args } {
# Make this variable available here and to the saved proc.
upvar dg-messages dg-messages
- process-message saved-dg-error "missed: " "$args"
+ process-message saved-dg-warning "missed:" "$args"
}
# Check the existence of a gdb in the path, and return true if there
diff --git a/gcc/testsuite/lib/hwasan-dg.exp b/gcc/testsuite/lib/hwasan-dg.exp
new file mode 100644
index 0000000..bd2a011
--- /dev/null
+++ b/gcc/testsuite/lib/hwasan-dg.exp
@@ -0,0 +1,167 @@
+# Copyright (C) 2020 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+load_lib asan-dg.exp
+
+# Return 1 if target can compile a binary for hardware address
+# sanitization, 0 otherwise.
+#
+# NOTE: This should only be used between calls to hwasan_init and
+# hwasan_finish. It is therefore defined here rather than in
+# target-supports.exp.
+
+proc check_effective_target_fsanitize_hwaddress {} {
+ if ![check_no_compiler_messages fsanitize_hwaddress executable {
+ int main (void) { return 0; }
+ }] {
+ return 0;
+ }
+ return 1;
+}
+
+# Return 1 if target can compile and run a binary for hardware address
+# sanitization, 0 otherwise.
+#
+# NOTE: This should only be used between calls to hwasan_init and
+# hwasan_finish. It is therefore defined here rather than in
+# target-supports.exp.
+
+proc check_effective_target_hwaddress_exec {} {
+ if ![check_runtime hwaddress_exec {
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ extern int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long);
+ #ifdef __cplusplus
+ }
+ #endif
+ int main (void) {
+ #define PR_SET_TAGGED_ADDR_CTRL 55
+ #define PR_GET_TAGGED_ADDR_CTRL 56
+ #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+ if (prctl (PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0) == -1)
+ return 1;
+ if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == -1
+ || !prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0))
+ return 1;
+ return 0;
+ }
+ }] {
+ return 0;
+ }
+ return 1;
+}
+
+proc hwasan_include_flags {} {
+ global srcdir
+ global TESTING_IN_BUILD_TREE
+
+ set flags ""
+
+ if { [is_remote host] || ! [info exists TESTING_IN_BUILD_TREE] } {
+ return "${flags}"
+ }
+
+ set flags "-I$srcdir/../../libsanitizer/include"
+
+ return "$flags"
+}
+
+#
+# hwasan_link_flags -- compute library path and flags to find libhwasan.
+# (implementation in asan-dg.exp)
+#
+
+proc hwasan_link_flags { paths } {
+ return [asan_link_flags_1 $paths hwasan]
+}
+
+#
+# hwasan_init -- called at the start of each subdir of tests
+#
+
+proc hwasan_init { args } {
+ global TEST_ALWAYS_FLAGS
+ global ALWAYS_CXXFLAGS
+ global TOOL_OPTIONS
+ global hwasan_saved_TEST_ALWAYS_FLAGS
+ global hwasan_saved_ALWAYS_CXXFLAGS
+
+ setenv HWASAN_OPTIONS "random_tags=0"
+
+ set link_flags ""
+ if ![is_remote host] {
+ if [info exists TOOL_OPTIONS] {
+ set link_flags "[hwasan_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
+ } else {
+ set link_flags "[hwasan_link_flags [get_multilibs]]"
+ }
+ }
+
+ set include_flags "[hwasan_include_flags]"
+
+ if [info exists TEST_ALWAYS_FLAGS] {
+ set hwasan_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
+ }
+ if [info exists ALWAYS_CXXFLAGS] {
+ set hwasan_saved_ALWAYS_CXXFLAGS $ALWAYS_CXXFLAGS
+ set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
+ set ALWAYS_CXXFLAGS [concat "{additional_flags=-fsanitize=hwaddress --param hwasan-random-frame-tag=0 -g $include_flags}" $ALWAYS_CXXFLAGS]
+ } else {
+ if [info exists TEST_ALWAYS_FLAGS] {
+ set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=hwaddress --param hwasan-random-frame-tag=0 -g $include_flags $TEST_ALWAYS_FLAGS"
+ } else {
+ set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=hwaddress --param hwasan-random-frame-tag=0 -g $include_flags"
+ }
+ }
+}
+
+#
+# hwasan_finish -- called at the start of each subdir of tests
+#
+
+proc hwasan_finish { args } {
+ global TEST_ALWAYS_FLAGS
+ global hwasan_saved_TEST_ALWAYS_FLAGS
+ global hwasan_saved_ALWAYS_CXXFLAGS
+ global hwasan_saved_library_path
+ global ld_library_path
+
+ unsetenv HWASAN_OPTIONS
+
+ if [info exists hwasan_saved_ALWAYS_CXXFLAGS ] {
+ set ALWAYS_CXXFLAGS $hwasan_saved_ALWAYS_CXXFLAGS
+ } else {
+ if [info exists hwasan_saved_TEST_ALWAYS_FLAGS] {
+ set TEST_ALWAYS_FLAGS $hwasan_saved_TEST_ALWAYS_FLAGS
+ } else {
+ unset TEST_ALWAYS_FLAGS
+ }
+ }
+ if [info exists hwasan_saved_library_path] {
+ set ld_library_path $hwasan_saved_library_path
+ set_ld_library_path_env_vars
+ }
+ clear_effective_target_cache
+}
+
+# Utility for running gtest hwasan emulation under dejagnu, invoked via dg-final.
+# Call pass if variable has the desired value, otherwise fail.
+#
+# Argument 0 handles expected failures and the like
+proc hwasan-gtest { args } {
+ asan-gtest {*}$args
+}
diff --git a/gcc/testsuite/lib/options.exp b/gcc/testsuite/lib/options.exp
index c7f7316..7700144 100644
--- a/gcc/testsuite/lib/options.exp
+++ b/gcc/testsuite/lib/options.exp
@@ -59,6 +59,11 @@ proc check_for_options_with_filter { language gcc_options exclude \
set gcc_output [gcc_target_compile $srcfname $filebase.x executable $gcc_options]
remote_file build delete $srcfname $filebase.x $filebase.gcno
+ if {[regexp -- "compiler not installed on this system" $gcc_output]} {
+ unsupported "$test: $language compiler not available"
+ return
+ }
+
if { $exclude != "" } {
set lines [split $gcc_output "\n"]
set gcc_output ""
diff --git a/gcc/testsuite/lib/profopt.exp b/gcc/testsuite/lib/profopt.exp
index d686343..98e1a0e 100644
--- a/gcc/testsuite/lib/profopt.exp
+++ b/gcc/testsuite/lib/profopt.exp
@@ -456,6 +456,7 @@ proc profopt-execute { src } {
set id [remote_spawn "" $cmd]
if { $id < 0 } {
unsupported "$testcase -fauto-profile: cannot run create_gcov"
+ unset testname_with_flags
set status "fail"
return
}
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 190367c..06904f9 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -48,7 +48,11 @@ proc prune_gcc_output { text } {
regsub -all "(^|\n)\[^\n\]*: re(compiling|linking)\[^\n\]*" $text "" text
regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text
regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text
- regsub -all "(^|\n)(In file included|\[ \]+from)\[^\n\]*" $text "" text
+
+ # Diagnostic inclusion stack
+ regsub -all "(^|\n)(In file)?\[ \]+included from \[^\n\]*" $text "" text
+ regsub -all "(^|\n)\[ \]+from \[^\n\]*" $text "" text
+ regsub -all "(^|\n)(In|of) module( \[^\n \]*,)? imported at \[^\n\]*" $text "" text
# Ignore informational notes.
regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
@@ -128,8 +132,8 @@ proc prune_file_path { text } {
# footnote.
proc prune_ices { text } {
- regsub -all "(^|\n)\[^\n\]*: internal compiler error:.*for instructions\[^\n\]*" $text "" text
- regsub -all "(^|\n|')*Internal compiler error:.*for instructions\[^\n\]*" $text "" text
+ regsub -all "(^|\n)\[^\n\]*: internal compiler error:.*\nSee \[^\n\]*" $text "" text
+ regsub -all "(^|\n|')*Internal compiler error:.*\nSee \[^\n\]*" $text "" text
return $text
}
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index d5f2be4..18fef38 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -52,10 +52,7 @@ proc dg-scan { name positive testcase output_file orig_args } {
set pattern [lindex $orig_args 0]
set printable_pattern [make_pattern_printable $pattern]
- if { [is_remote host] } {
- remote_upload host "$output_file"
- }
- set files [glob -nocomplain $output_file]
+ set files [dg_glob_remote $output_file]
if { $files == "" } {
verbose -log "$testcase: output file does not exist"
unresolved "$testcase $name $printable_pattern"
@@ -73,6 +70,13 @@ proc dg-scan { name positive testcase output_file orig_args } {
}
}
+proc dg_glob_remote { file_pattern } {
+ if { [is_remote host] } {
+ remote_upload host $file_pattern
+ }
+ return [glob -nocomplain $file_pattern]
+}
+
# Look for a pattern in the .s file produced by the compiler. See
# dg-scan for details.
@@ -155,6 +159,196 @@ proc scan-not-hidden { args } {
dg-scan "scan-not-hidden" 0 $testcase $output_file $args
}
+# Check that symbols are emitted in the desired section.
+# Like scan-symbol-section, but using the assembly output generated by
+# the compiler.
+#
+# Example:
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text section or
+# // in a .text sub-section (like .text._func1).
+# { dg-final { scan-assembler-symbol-section {^_func[1-5]$} {^\.text($|\.)} } }
+
+proc scan-assembler-symbol-section { args } {
+ set testcase [testname-for-summary]
+ set filename [lindex $testcase 0]
+ set output_file "[file rootname [file tail $filename]].s"
+ dg-scan-symbol-section \
+ "scan-assembler-symbol-section" $testcase $output_file $args
+}
+
+# Check that symbols are emitted in the desired section.
+#
+# Symbols and sections are interpreted as regexp patterns.
+#
+# If no matching symbol is found, scan-symbol-section reports a FAILure.
+#
+# Usage:
+#
+# { dg-final { scan-symbol-section FILENAME SYMBOL SECTION } }
+#
+# Examples:
+#
+# // The my_var C symbol must be in the .data section (or in a .data._my_var section
+# // if -ffunction-sections is in use).
+# { dg-final { scan-symbol-section "my-test.s" {^_my_var$} {^\.data(\._my_var)?$} } }
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text section
+# // (and not in any other section like .text._func1).
+# { dg-final { scan-symbol-section "my-test.s" {^_func[1-5]$} {^\.text$} } }
+#
+# Caveats:
+#
+# * Only ELF and Mach-O targets are supported. Other
+# targets, like PE/COFF, might appear to work.
+# * For Mach-O targets, the section name matched by scan-symbol-section has one
+# of two forms:
+# * The Mach-O segment name followed by a comma (',') followed by the Mach-O
+# section name. For example, "__TEXT,__text". (There is no whitespace
+# between the Mach-O segment name and the Mach-O section name.)
+# * ".const", ".data", or ".text". For example, the .text assembler directive
+# causes the section name to be ".text" (not "__TEXT,__text"). (However, a
+# directive such as .section __TEXT,__text will cause the section name to be
+# "__TEXT,__text".)
+# * Because scan-symbol-section parses assembly code, scan-symbol-section is
+# unaware of section rewriting performed by the linker. For example, the
+# sections .text._f1 and .text._f2 would normally be merged by binutils'
+# linker into one section called .text, but scan-symbol-section reports the
+# sections as .text._f1 and .text._f2 (and not .text).
+# * The symbol pattern matches any assembly label, including local labels which
+# begin with `.L`.
+
+proc scan-symbol-section { args } {
+ set testcase [testname-for-summary]
+ set output_file [lindex $args 0]
+ dg-scan-symbol-section \
+ "scan-symbol-section" $testcase $output_file $args
+}
+
+# Check that symbols are emitted in the desired section. The ORIG_ARGS is
+# the list of arguments provided by dg-final to scan-symbol-section or
+# scan-assembler-symbol-section. The first element in ORIG_ARGS is the
+# regular expression to look for in the file. The second element, if
+# present, is a DejaGNU target selector.
+#
+# Avoid calling this function directly. In tests, use scan-symbol-section,
+# scan-assembler-symbol-section, or scan-lto-assembler-symbol-section instead.
+
+proc dg-scan-symbol-section { name testcase output_file orig_args } {
+ if { [llength $orig_args] < 2 } {
+ error "$name: too few arguments"
+ return
+ }
+ if { [llength $orig_args] > 4 } {
+ error "$name: too many arguments"
+ return
+ }
+ switch $name {
+ "scan-symbol-section" { set arg_incr 1 }
+ default { set arg_incr 0 }
+ }
+ if { [llength $orig_args] >= 3 } {
+ switch [dg-process-target [lindex $orig_args [expr 2 + $arg_incr]]] {
+ "S" { }
+ "N" { return }
+ "F" { setup_xfail "*-*-*" }
+ "P" { }
+ }
+ }
+
+ set symbol_pattern [lindex $orig_args [expr 0 + $arg_incr]]
+ set expected_section_pattern [lindex $orig_args [expr 1 + $arg_incr]]
+
+ set printable_symbol_pattern [make_pattern_printable $symbol_pattern]
+ set printable_expected_section_pattern [make_pattern_printable $expected_section_pattern]
+
+ set files [dg_glob_remote $output_file]
+ if { $files == "" } {
+ verbose -log "$testcase: output file does not exist"
+ unresolved "$testcase $name symbol $printable_symbol_pattern has section $printable_expected_section_pattern"
+ return
+ }
+
+ parse_section_of_symbols $output_file section_by_symbol
+
+ set found_symbol 0
+ foreach symbol_name [lsort [array names section_by_symbol]] {
+ if { [regexp -- $symbol_pattern $symbol_name] } {
+ set section $section_by_symbol($symbol_name)
+ set description "$testcase $name symbol $printable_symbol_pattern (found $symbol_name) has section $printable_expected_section_pattern"
+ if { $section == "" } {
+ fail "$description (no section detected)"
+ } else {
+ set description "$description (found $section)"
+ if { [regexp -- $expected_section_pattern $section] } {
+ pass $description
+ } else {
+ fail $description
+ }
+ }
+ set found_symbol 1
+ }
+ }
+ if { ! $found_symbol } {
+ fail "$testcase $name symbol $printable_symbol_pattern (symbol not found) has section $printable_expected_section_pattern"
+ }
+}
+
+# Extract a symbol and section names from pre-processed assembly source code.
+#
+# This function adds entries in the RESULT array where the key is the symbol's
+# name (including any leading underscores) and the value is the section's name
+# (including any leading periods).
+#
+# For example, given the following assembly source code in file.s:
+#
+# .text
+# .function _my_function
+# _my_function:
+# nop
+# .data
+# _my_data:
+# .long 42
+#
+# Executing 'parse_section_of_symbols "file.s" symbols' would have the same
+# effect as the following code:
+#
+# set $result(_my_function) .text
+# set $result(_my_data) .data
+
+proc parse_section_of_symbols { filename result } {
+ upvar $result up_result
+
+ set section_pattern {^\s*(?:(?:\.section|\.csect)\s+(.*)|(\.const|\.data|\.text)\s*)$}
+ set label_pattern {^(\S+):$}
+
+ set fd [open $filename r]
+ set current_section ""
+ while { [gets $fd line] >= 0 } {
+ if { [regexp -- $label_pattern $line dummy symbol_name] } {
+ set up_result($symbol_name) $current_section
+ } elseif { [regexp -- $section_pattern $line dummy section_directive_arguments full_section_directive] } {
+ if { $full_section_directive eq "" } {
+ # Example: .section .text,"ax",progbits
+ # Example: .section ".text",#alloc,#execinstr,#progbits
+ # Example: .section __TEXT,__text
+ set arguments [split $section_directive_arguments ","]
+ set current_section [string trim [lindex $arguments 0]]
+ set current_section [string trim $current_section {"}]
+ set arg_1 [string trim [lindex $arguments 1]]
+ if { [regexp {^_} $arg_1] } {
+ # The second argument looks like a Mach-O section name.
+ set current_section "$current_section,$arg_1"
+ }
+ } else {
+ # Example: .text
+ set current_section "$full_section_directive"
+ }
+ }
+ }
+ close $fd
+}
+
# Look for a pattern in OUTPUT_FILE. See dg-scan for details.
proc scan-file { output_file args } {
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 8439720..11343d0 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -368,7 +368,7 @@ proc check_weak_override_available { } {
return [check_weak_available]
}
-# The noinit attribute is only supported by some targets.
+# The "noinit" attribute is only supported by some targets.
# This proc returns 1 if it's supported, 0 if it's not.
proc check_effective_target_noinit { } {
@@ -380,6 +380,18 @@ proc check_effective_target_noinit { } {
return 0
}
+# The "persistent" attribute is only supported by some targets.
+# This proc returns 1 if it's supported, 0 if it's not.
+
+proc check_effective_target_persistent { } {
+ if { [istarget arm*-*-eabi]
+ || [istarget msp430-*-*] } {
+ return 1
+ }
+
+ return 0
+}
+
###############################
# proc check_visibility_available { what_kind }
###############################
@@ -642,7 +654,7 @@ proc check_profiling_available { test_what } {
return 0
}
global srcdir
- set status [remote_exec host "$srcdir/../config/i386/gcc-auto-profile" "true -v >/dev/null"]
+ set status [remote_exec host "$srcdir/../config/i386/gcc-auto-profile" "-m8 true -v >/dev/null"]
if { [lindex $status 0] != 0 } {
verbose "autofdo not supported because perf does not work"
return 0
@@ -3355,7 +3367,116 @@ proc check_effective_target_vect_int { } {
}}]
}
-# Return 1 if the target supports signed int->float conversion
+# Return 1 if the target supports hardware vectorization of complex additions of
+# byte, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_byte { } {
+ return [check_cached_effective_target_indexed vect_complex_add_byte {
+ expr {
+ ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_arm_v8_1m_mve_fp_ok]
+ && [check_effective_target_arm_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports hardware vectorization of complex additions of
+# short, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_short { } {
+ return [check_cached_effective_target_indexed vect_complex_add_short {
+ expr {
+ ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_arm_v8_1m_mve_fp_ok]
+ && [check_effective_target_arm_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports hardware vectorization of complex additions of
+# int, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_int { } {
+ return [check_cached_effective_target_indexed vect_complex_add_int {
+ expr {
+ ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_arm_v8_1m_mve_fp_ok]
+ && [check_effective_target_arm_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports hardware vectorization of complex additions of
+# long, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_long { } {
+ return [check_cached_effective_target_indexed vect_complex_add_long {
+ expr {
+ ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_arm_v8_1m_mve_fp_ok]
+ && [check_effective_target_arm_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports hardware vectorization of complex additions of
+# half, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_half { } {
+ return [check_cached_effective_target_indexed vect_complex_add_half {
+ expr {
+ ([check_effective_target_arm_v8_3a_fp16_complex_neon_ok]
+ && ([check_effective_target_aarch64_little_endian]
+ || [check_effective_target_arm_little_endian]))
+ || ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_arm_v8_1m_mve_fp_ok]
+ && [check_effective_target_arm_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports hardware vectorization of complex additions of
+# float, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_float { } {
+ return [check_cached_effective_target_indexed vect_complex_add_float {
+ expr {
+ ([check_effective_target_arm_v8_3a_complex_neon_ok]
+ && ([check_effective_target_aarch64_little_endian]
+ || [check_effective_target_arm_little_endian]))
+ || ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_arm_v8_1m_mve_fp_ok]
+ && [check_effective_target_arm_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports hardware vectorization of complex additions of
+# double, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_complex_add_double { } {
+ return [check_cached_effective_target_indexed vect_complex_add_double {
+ expr {
+ ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian])
+ }}]
+}
+
+# Return 1 if the target supports signed int->float conversion
#
proc check_effective_target_vect_intfloat_cvt { } {
@@ -5646,8 +5767,8 @@ proc check_effective_target_arm_hf_eabi { } {
}]
}
-# Return 1 if this is an ARM target that uses the soft float ABI
-# with no floating-point instructions at all (e.g. -mfloat-abi=soft).
+# Return 1 if this is an ARM target uses emulated floating point
+# operations.
proc check_effective_target_arm_softfloat { } {
return [check_no_compiler_messages arm_softfloat object {
@@ -8461,6 +8582,18 @@ proc check_effective_target_avx2 { } {
} "-O0 -mavx2" ]
}
+# Return 1 if avxvnni instructions can be compiled.
+proc check_effective_target_avxvnni { } {
+ return [check_no_compiler_messages avxvnni object {
+ typedef int __v8si __attribute__ ((__vector_size__ (32)));
+ __v8si
+ _mm256_dpbusd_epi32 (__v8si __A, __v8si __B, __v8si __C)
+ {
+ return __builtin_ia32_vpdpbusd_v8si (__A, __B, __C);
+ }
+ } "-mavxvnni" ]
+}
+
# Return 1 if sse instructions can be compiled.
proc check_effective_target_sse { } {
return [check_no_compiler_messages sse object {
@@ -9693,6 +9826,44 @@ proc check_effective_target_fenv_exceptions {} {
} [add_options_for_ieee "-std=gnu99"]]
}
+# Return 1 if <fenv.h> is available with all the standard IEEE
+# exceptions and floating-point exceptions are raised by arithmetic
+# operations for decimal floating point. (If the target requires
+# special options for "inexact" exceptions, those need to be specified
+# in the testcases.)
+
+proc check_effective_target_fenv_exceptions_dfp {} {
+ return [check_runtime fenv_exceptions_dfp {
+ #include <fenv.h>
+ #include <stdlib.h>
+ #ifndef FE_DIVBYZERO
+ # error Missing FE_DIVBYZERO
+ #endif
+ #ifndef FE_INEXACT
+ # error Missing FE_INEXACT
+ #endif
+ #ifndef FE_INVALID
+ # error Missing FE_INVALID
+ #endif
+ #ifndef FE_OVERFLOW
+ # error Missing FE_OVERFLOW
+ #endif
+ #ifndef FE_UNDERFLOW
+ # error Missing FE_UNDERFLOW
+ #endif
+ volatile _Decimal64 a = 0.0DD, r;
+ int
+ main (void)
+ {
+ r = a / a;
+ if (fetestexcept (FE_INVALID))
+ exit (0);
+ else
+ abort ();
+ }
+ } [add_options_for_ieee "-std=gnu99"]]
+}
+
# Return 1 if -fexceptions is supported.
proc check_effective_target_exceptions {} {
@@ -10301,6 +10472,13 @@ proc check_effective_target_inf { } {
}]
}
+# Return 1 if target supports floating point "infinite" for float.
+proc check_effective_target_inff { } {
+ return [check_no_compiler_messages supports_inff assembly {
+ const float pinf = __builtin_inff ();
+ }]
+}
+
# Return 1 if the target supports ARMv8.3 Adv.SIMD Complex instructions
# instructions, 0 otherwise. The test is valid for ARM and for AArch64.
# Record the command line options needed.
@@ -10317,13 +10495,13 @@ proc check_effective_target_arm_v8_3a_complex_neon_ok_nocache { } {
# need to be added to the -march option.
foreach flags {"" "-mfloat-abi=softfp -mfpu=auto" "-mfloat-abi=hard -mfpu=auto"} {
if { [check_no_compiler_messages_nocache \
- arm_v8_3a_complex_neon_ok object {
+ arm_v8_3a_complex_neon_ok assembly {
#if !defined (__ARM_FEATURE_COMPLEX)
#error "__ARM_FEATURE_COMPLEX not defined"
#endif
} "$flags -march=armv8.3-a"] } {
set et_arm_v8_3a_complex_neon_flags "$flags -march=armv8.3-a"
- return 1
+ return 1;
}
}
@@ -10343,13 +10521,57 @@ proc add_options_for_arm_v8_3a_complex_neon { flags } {
return "$flags $et_arm_v8_3a_complex_neon_flags"
}
+# Return 1 if the target supports ARMv8.3 Adv.SIMD + FP16 Complex instructions
+# instructions, 0 otherwise. The test is valid for ARM and for AArch64.
+# Record the command line options needed.
+
+proc check_effective_target_arm_v8_3a_fp16_complex_neon_ok_nocache { } {
+ global et_arm_v8_3a_fp16_complex_neon_flags
+ set et_arm_v8_3a_fp16_complex_neon_flags ""
+
+ if { ![istarget arm*-*-*] && ![istarget aarch64*-*-*] } {
+ return 0;
+ }
+
+ # Iterate through sets of options to find the compiler flags that
+ # need to be added to the -march option.
+ foreach flags {"" "-mfloat-abi=softfp -mfpu=auto" "-mfloat-abi=hard -mfpu=auto"} {
+ if { [check_no_compiler_messages_nocache \
+ arm_v8_3a_fp16_complex_neon_ok assembly {
+ #if !defined (__ARM_FEATURE_COMPLEX)
+ #error "__ARM_FEATURE_COMPLEX not defined"
+ #endif
+ } "$flags -march=armv8.3-a+fp16"] } {
+ set et_arm_v8_3a_fp16_complex_neon_flags \
+ "$flags -march=armv8.3-a+fp16"
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+proc check_effective_target_arm_v8_3a_fp16_complex_neon_ok { } {
+ return [check_cached_effective_target arm_v8_3a_fp16_complex_neon_ok \
+ check_effective_target_arm_v8_3a_fp16_complex_neon_ok_nocache]
+}
+
+proc add_options_for_arm_v8_3a_fp16_complex_neon { flags } {
+ if { ! [check_effective_target_arm_v8_3a_fp16_complex_neon_ok] } {
+ return "$flags"
+ }
+ global et_arm_v8_3a_fp16_complex_neon_flags
+ return "$flags $et_arm_v8_3a_fp16_complex_neon_flags"
+}
+
+
# Return 1 if the target supports executing AdvSIMD instructions from ARMv8.3
# with the complex instruction extension, 0 otherwise. The test is valid for
# ARM and for AArch64.
proc check_effective_target_arm_v8_3a_complex_neon_hw { } {
if { ![check_effective_target_arm_v8_3a_complex_neon_ok] } {
- return 0;
+ return 1;
}
return [check_runtime arm_v8_3a_complex_neon_hw_available {
#include "arm_neon.h"
@@ -10374,7 +10596,7 @@ proc check_effective_target_arm_v8_3a_complex_neon_hw { } {
: /* No clobbers. */);
#endif
- return (results[0] == 8 && results[1] == 24) ? 1 : 0;
+ return (results[0] == 8 && results[1] == 24) ? 0 : 1;
}
} [add_options_for_arm_v8_3a_complex_neon ""]]
}
@@ -10522,6 +10744,11 @@ proc check_effective_target_msp430_large {} {
} ""]
}
+# Return 1 if GCC was configured with --with-tune=cortex-a76
+proc check_effective_target_tune_cortex_a76 { } {
+ return [check_configured_with "with-tune=cortex-a76"]
+}
+
# Return 1 if the target has an efficient means to encode large initializers
# in the assembly.
@@ -10582,3 +10809,94 @@ proc check_effective_target_movdir { } {
}
} "-mmovdiri -mmovdir64b" ]
}
+
+# Return 1 if target is not support address sanitize, 1 otherwise.
+
+proc check_effective_target_no_fsanitize_address {} {
+ if ![check_no_compiler_messages fsanitize_address executable {
+ int main (void) { return 0; }
+ }] {
+ return 1;
+ }
+ return 0;
+}
+
+# Return 1 if this target supports 'R' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_R_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target R_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SHF_GNU_RETAIN == 0 || HAVE_INITFINI_ARRAY_SUPPORT == 0"
+ puts $f "# error Assembler does not support 'R' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_R_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj assembly ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_R_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_R_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
+
+# Return 1 if this target supports 'o' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_o_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target o_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SECTION_LINK_ORDER == 0"
+ puts $f "# error Assembler does not support 'o' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_o_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj object ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_o_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_o_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
diff --git a/gcc/testsuite/lib/tsan-dg.exp b/gcc/testsuite/lib/tsan-dg.exp
index b5631a7..6dcfd0a 100644
--- a/gcc/testsuite/lib/tsan-dg.exp
+++ b/gcc/testsuite/lib/tsan-dg.exp
@@ -150,7 +150,9 @@ proc tsan_finish { args } {
} else {
unset dg-do-what-default
}
- set ld_library_path $tsan_saved_library_path
- set_ld_library_path_env_vars
+ if [info exists tsan_saved_library_path ] {
+ set ld_library_path $tsan_saved_library_path
+ set_ld_library_path_env_vars
+ }
clear_effective_target_cache
}
diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp
index f4ab29e..31740e0 100644
--- a/gcc/testsuite/lib/ubsan-dg.exp
+++ b/gcc/testsuite/lib/ubsan-dg.exp
@@ -141,7 +141,9 @@ proc ubsan_finish { args } {
unset TEST_ALWAYS_FLAGS
}
}
- set ld_library_path $ubsan_saved_library_path
- set_ld_library_path_env_vars
+ if [info exists ubsan_saved_library_path ] {
+ set ld_library_path $ubsan_saved_library_path
+ set_ld_library_path_env_vars
+ }
clear_effective_target_cache
}
diff --git a/gcc/testsuite/obj-c++.dg/SEL-typedef.mm b/gcc/testsuite/obj-c++.dg/SEL-typedef.mm
new file mode 100644
index 0000000..2ece1fd
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/SEL-typedef.mm
@@ -0,0 +1,7 @@
+/* Check that we accept the SEL typedef. */
+/* { dg-additional-options "-fsyntax-only " } */
+
+SEL aSelector;
+
+typedef SEL MySEL;
+
diff --git a/gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm b/gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm
index f078339..7eafdbc 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test deprecate attribute with an @interface declaration. */
diff --git a/gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm b/gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm
index 35015c0..629ba86 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/class-attribute-3.mm b/gcc/testsuite/obj-c++.dg/attributes/class-attribute-3.mm
index f96500d..3b7c8c3 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/class-attribute-3.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/class-attribute-3.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that you get a warning when an unknown class attribute is ignored. */
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm
index 8343856..68e8373 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm
index 1e5d87f..8fb0e15 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm
index 5c715a2..efa2d34 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm
index 9ff34f9..d3bb997 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
/* { dg-options "-Wall" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm
index 83f918c..af48787 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, May 2011. */
/* { dg-do compile } */
/* { dg-options "-Wall" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm
index a83048b..413a0be 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm
index 2b8e6fd..ece7a9f 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
/* { dg-options "-Wall" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/nsobject-01.mm b/gcc/testsuite/obj-c++.dg/attributes/nsobject-01.mm
new file mode 100644
index 0000000..3af785b
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/attributes/nsobject-01.mm
@@ -0,0 +1,66 @@
+/* Test handling of the NSObject attribute. */
+/* { dg-additional-options "-fsyntax-only -Wno-objc-root-class" } */
+
+typedef struct AnObj * __attribute__ ((NSObject)) AnObjRef;
+typedef struct AnObj * __attribute__ ((__NSObject__)) AnotherObjRef;
+
+/* We allow a void * to be labeled as NSObject. */
+typedef void * __attribute__((NSObject)) AnonRef;
+
+typedef struct AnObj * __attribute__((NSObject("foo"))) Bad; // { dg-error {wrong number of arguments specified for 'NSObject' attribute} }
+typedef struct AnObj * __attribute__((NSObject(42))) Wrong; // { dg-error {wrong number of arguments specified for 'NSObject' attribute} }
+
+/* Must be a pointer. */
+typedef struct AnObj __attribute__((NSObject)) BadRef; // { dg-error {'NSObject' attribute is for pointer types only} }
+
+typedef void * VPtr;
+
+@interface CheckAttrNSObject
+{
+@public
+ AnObjRef aor;
+ /* TODO: synthesize without pre-defined ivars. */
+ VPtr obj_v;
+ int bar;
+ /* TODO: This should warn, even tho the property does not */
+ __attribute__((NSObject)) struct AnObj *Thing;
+}
+
+@property(copy) AnObjRef aor;
+
+typedef struct AnObj * __attribute__((NSObject)) AnObjPtr3;
+@property (nonatomic, retain) AnObjPtr3 obj_3;
+
+@property (retain) __attribute__((NSObject)) VPtr obj_v;
+
+//@property (strong, nullable) AnObjPtr3 objp_4;
+
+@property(retain) __attribute__((NSObject)) int bar;
+ // { dg-error {'NSObject' attribute is for pointer types only} "" { target *-*-* } .-1 }
+ // { dg-error {'retain' attribute is only valid for Objective-C objects} "" { target *-*-* } .-2 }
+
+@end
+
+void foo ()
+{
+ __attribute__((NSObject)) struct AnObj *AnotherThing; // { dg-warning {'NSObject' attribute may be put on a typedef only; attribute is ignored} }
+}
+
+void
+setProperty(id self, id value)
+{
+ ((CheckAttrNSObject *)self)->aor = value;
+}
+
+id
+getProperty(id self)
+{
+ return (id)((CheckAttrNSObject *)self)->aor;
+}
+
+@implementation CheckAttrNSObject
+@synthesize aor;
+@dynamic obj_3;
+@synthesize obj_v;
+@synthesize bar;
+@end // { dg-error {invalid conversion} }
diff --git a/gcc/testsuite/obj-c++.dg/attributes/nullability-00.mm b/gcc/testsuite/obj-c++.dg/attributes/nullability-00.mm
new file mode 100644
index 0000000..957fca4
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/attributes/nullability-00.mm
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class -fsyntax-only" } */
+
+__attribute__((objc_nullability(0))) id a;
+__attribute__((objc_nullability(4))) id e_1; /* { dg-error {'objc_nullability' attribute argument '4' is not an integer constant between 0 and 3} } */
+__attribute__((objc_nullability(-22))) id e_2; /* { dg-error {'objc_nullability' attribute argument '-22' is not an integer constant between 0 and 3} } */
+__attribute__((objc_nullability("unspecified"))) id b;
+__attribute__((objc_nullability("nullable"))) id c;
+__attribute__((objc_nullability("nonnull"))) id d;
+__attribute__((objc_nullability("resettable"))) id e;
+__attribute__((objc_nullability("nonsense"))) id e_3; /* { dg-error {'objc_nullability' attribute argument '"nonsense"' is not recognised} } */
+__attribute__((objc_nullability(noGoingToWork))) id e_4; /* { dg-error {'noGoingToWork' was not declared in this scope} } */
+
+@interface MyRoot
+{
+ __attribute__((objc_nullability(0))) id iv_a;
+ __attribute__((objc_nullability(3))) struct { int bad_a; } s;/* { dg-error {'objc_nullability' cannot be applied to non-pointer type '<unnamed struct>'} } */
+ __attribute__((objc_nullability("resettable"))) int iv_b;/* { dg-error {'objc_nullability' cannot be applied to non-pointer type 'int'} } */
+}
+@end
diff --git a/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-1.mm b/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-1.mm
index a4ba259..b4556ba 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-1.mm
@@ -1,6 +1,7 @@
/* Test __attribute__((unused)) for an Objective-C method parameter. */
/* { dg-do compile } */
/* { dg-options "-Wunused-parameter" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-2.mm b/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-2.mm
index 3908faf..9d69e42 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-2.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/parameter-attribute-2.mm
@@ -1,5 +1,6 @@
/* Test that we get warnings for unrecognized attributes. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm b/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm
index a852a7a..03726dc 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-3.mm b/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-3.mm
index fc5251e..263f927 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-3.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-3.mm
@@ -1,7 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
-
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test deprecate attribute with normal @protocol declarations. */
diff --git a/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-4.mm b/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-4.mm
index d2e5f28..665e13d 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-4.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/proto-attribute-4.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that you get a warning when an unknown protocol attribute is ignored. */
diff --git a/gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm b/gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm
new file mode 100644
index 0000000..84da94a
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm
@@ -0,0 +1,11 @@
+/* Test Wobjc-root-class warning is suppressed by the objc_root_class attr.
+ Note that we don't issue a warning unless the TU contains an implementation
+ for the class. This should compile without warning. */
+/* { dg-additional-options "-fsyntax-only " } */
+
+__attribute__((objc_root_class))
+@interface ARootObject
+@end
+
+@implementation ARootObject
+@end
diff --git a/gcc/testsuite/obj-c++.dg/attributes/unused-parameter-1.mm b/gcc/testsuite/obj-c++.dg/attributes/unused-parameter-1.mm
index 8fbb11e..c56a7f7 100644
--- a/gcc/testsuite/obj-c++.dg/attributes/unused-parameter-1.mm
+++ b/gcc/testsuite/obj-c++.dg/attributes/unused-parameter-1.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/bad-receiver-type.mm b/gcc/testsuite/obj-c++.dg/bad-receiver-type.mm
index 1d6699f..9c00a06 100644
--- a/gcc/testsuite/obj-c++.dg/bad-receiver-type.mm
+++ b/gcc/testsuite/obj-c++.dg/bad-receiver-type.mm
@@ -1,5 +1,6 @@
// { dg-do compile }
// { dg-options "" }
+// { dg-additional-options "-Wno-objc-root-class" }
@interface A
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-3.mm b/gcc/testsuite/obj-c++.dg/bitfield-3.mm
index d81976a..c4ed984 100644
--- a/gcc/testsuite/obj-c++.dg/bitfield-3.mm
+++ b/gcc/testsuite/obj-c++.dg/bitfield-3.mm
@@ -4,6 +4,7 @@
/* { dg-do run { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-fsigned-char" } */
+// { dg-additional-options "-Wno-objc-root-class" }
typedef struct objc_object { struct objc_class *class_pointer; } *id;
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-5.mm b/gcc/testsuite/obj-c++.dg/bitfield-5.mm
index 3b0065d..d86c9b1 100644
--- a/gcc/testsuite/obj-c++.dg/bitfield-5.mm
+++ b/gcc/testsuite/obj-c++.dg/bitfield-5.mm
@@ -3,6 +3,7 @@
(@interface vs. @implementation) checks take the bitfield width into account. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface Base {
int i;
diff --git a/gcc/testsuite/obj-c++.dg/class-extension-1.mm b/gcc/testsuite/obj-c++.dg/class-extension-1.mm
index 5c89a98..c497c1d 100644
--- a/gcc/testsuite/obj-c++.dg/class-extension-1.mm
+++ b/gcc/testsuite/obj-c++.dg/class-extension-1.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This test tests the basic of class extensions. */
diff --git a/gcc/testsuite/obj-c++.dg/class-extension-2.mm b/gcc/testsuite/obj-c++.dg/class-extension-2.mm
index 7f55b60..108bc00 100644
--- a/gcc/testsuite/obj-c++.dg/class-extension-2.mm
+++ b/gcc/testsuite/obj-c++.dg/class-extension-2.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This test tests class extensions and protocols. */
diff --git a/gcc/testsuite/obj-c++.dg/class-extension-3.mm b/gcc/testsuite/obj-c++.dg/class-extension-3.mm
index 69e5705..bed8490 100644
--- a/gcc/testsuite/obj-c++.dg/class-extension-3.mm
+++ b/gcc/testsuite/obj-c++.dg/class-extension-3.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This test tests warnings on class extensions. */
diff --git a/gcc/testsuite/obj-c++.dg/class-extension-4.mm b/gcc/testsuite/obj-c++.dg/class-extension-4.mm
index 9e19aa7..2cfbc5d 100644
--- a/gcc/testsuite/obj-c++.dg/class-extension-4.mm
+++ b/gcc/testsuite/obj-c++.dg/class-extension-4.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This test tests you can not declare a class extension after the class @implementation. */
diff --git a/gcc/testsuite/obj-c++.dg/class-protocol-1.mm b/gcc/testsuite/obj-c++.dg/class-protocol-1.mm
index 78957cb..3b33264 100644
--- a/gcc/testsuite/obj-c++.dg/class-protocol-1.mm
+++ b/gcc/testsuite/obj-c++.dg/class-protocol-1.mm
@@ -1,6 +1,7 @@
/* Check Class <protocol> types */
/* Author: David Ayers <d.ayers@inode.at> */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
#include "../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-1.mm b/gcc/testsuite/obj-c++.dg/comp-types-1.mm
index 6d4e86e..6402abc 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-1.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-1.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface A
+ new;
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-10.mm b/gcc/testsuite/obj-c++.dg/comp-types-10.mm
index c7f0cb6..fdfd093 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-10.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-10.mm
@@ -2,6 +2,7 @@
/* { dg-do compile } */
/* { dg-prune-output ".*internal compiler error.*" } */
/* { dg-options "-O3" } */
+// { dg-additional-options "-Wno-objc-root-class" }
@class NSString;
@protocol NSObject
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-2.mm b/gcc/testsuite/obj-c++.dg/comp-types-2.mm
index 0704378..87750fd 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-2.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-2.mm
@@ -1,6 +1,7 @@
/* Test various ObjC types assignments and comparisons. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-3.mm b/gcc/testsuite/obj-c++.dg/comp-types-3.mm
index 2bea015..d4d0790 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-3.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-3.mm
@@ -1,6 +1,7 @@
/* Test simple ObjC types casts. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-5.mm b/gcc/testsuite/obj-c++.dg/comp-types-5.mm
index 99f6772..2c4fc57 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-5.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-5.mm
@@ -1,6 +1,7 @@
/* Test errors for assignments and comparisons between ObjC and C++ types. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-6.mm b/gcc/testsuite/obj-c++.dg/comp-types-6.mm
index 23b84ed..071a756 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-6.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-6.mm
@@ -1,6 +1,7 @@
/* Test assignments and comparisons involving `one-off' protocols. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-7.mm b/gcc/testsuite/obj-c++.dg/comp-types-7.mm
index e235581..6286355 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-7.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-7.mm
@@ -1,6 +1,7 @@
/* Test assignments and comparisons involving category protocols. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-8.mm b/gcc/testsuite/obj-c++.dg/comp-types-8.mm
index 6db76bb..0221164 100644
--- a/gcc/testsuite/obj-c++.dg/comp-types-8.mm
+++ b/gcc/testsuite/obj-c++.dg/comp-types-8.mm
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-additional-options "-Wno-return-type" } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* We used to ICE because we removed the cast to List_linked*
in -[ListIndex_linked next]. */
diff --git a/gcc/testsuite/obj-c++.dg/demangle-2.mm b/gcc/testsuite/obj-c++.dg/demangle-2.mm
index f282085..14c7b3e 100644
--- a/gcc/testsuite/obj-c++.dg/demangle-2.mm
+++ b/gcc/testsuite/obj-c++.dg/demangle-2.mm
@@ -1,6 +1,7 @@
/* Test demangling an Objective-C method. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <cstring>
#include <cstdlib>
diff --git a/gcc/testsuite/obj-c++.dg/demangle-3.mm b/gcc/testsuite/obj-c++.dg/demangle-3.mm
index afb83d7..d8d8178 100644
--- a/gcc/testsuite/obj-c++.dg/demangle-3.mm
+++ b/gcc/testsuite/obj-c++.dg/demangle-3.mm
@@ -1,6 +1,7 @@
/* Test demangling an Objective-C method in error messages. */
/* { dg-do compile } */
/* { dg-additional-options "-Wno-return-type" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/duplicate-class-1.mm b/gcc/testsuite/obj-c++.dg/duplicate-class-1.mm
index 3a5e510..77e52c6 100644
--- a/gcc/testsuite/obj-c++.dg/duplicate-class-1.mm
+++ b/gcc/testsuite/obj-c++.dg/duplicate-class-1.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* Test that a duplicated @implementation for the same class does not
crash the compiler. */
diff --git a/gcc/testsuite/obj-c++.dg/encode-1-next.mm b/gcc/testsuite/obj-c++.dg/encode-1-next.mm
index 47673f2..854dd72 100644
--- a/gcc/testsuite/obj-c++.dg/encode-1-next.mm
+++ b/gcc/testsuite/obj-c++.dg/encode-1-next.mm
@@ -5,6 +5,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
struct Cxx {
const struct Cxx *next;
diff --git a/gcc/testsuite/obj-c++.dg/encode-1.mm b/gcc/testsuite/obj-c++.dg/encode-1.mm
index 5f5ba20..6247c64 100644
--- a/gcc/testsuite/obj-c++.dg/encode-1.mm
+++ b/gcc/testsuite/obj-c++.dg/encode-1.mm
@@ -3,6 +3,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
struct Cxx {
const struct Cxx *next;
diff --git a/gcc/testsuite/obj-c++.dg/enhanced-proto-2.mm b/gcc/testsuite/obj-c++.dg/enhanced-proto-2.mm
index 31c2e50..5964dfb 100644
--- a/gcc/testsuite/obj-c++.dg/enhanced-proto-2.mm
+++ b/gcc/testsuite/obj-c++.dg/enhanced-proto-2.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@protocol MyProto1
@optional
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-1.mm b/gcc/testsuite/obj-c++.dg/exceptions-1.mm
index 0f3b7e8..75327ef 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-1.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-1.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This test checks the syntax @catch (...) which catches any
exceptions. At the moment, @catch (...) is identical to @catch (id
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-3.mm b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
index 622e4ca..7cf77a7 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-3.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* Test that the compiler is checking the argument of @catch(), and
produce errors when invalid types are used. */
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-4.mm b/gcc/testsuite/obj-c++.dg/exceptions-4.mm
index 4aa00a6..1391c43 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-4.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-4.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* Test warnings when parsing syntax errors in @catch(). */
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-5.mm b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
index 5aa08f3..4547a75 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-5.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* Test that you can use an unnamed argument with @catch. This test is the same
as exceptions-3.mm, but with no name for @catch arguments. */
diff --git a/gcc/testsuite/obj-c++.dg/extern-c-1.mm b/gcc/testsuite/obj-c++.dg/extern-c-1.mm
index c5fec6f..8b9147a 100644
--- a/gcc/testsuite/obj-c++.dg/extern-c-1.mm
+++ b/gcc/testsuite/obj-c++.dg/extern-c-1.mm
@@ -1,5 +1,6 @@
/* Test extern c support inside @implementation */
/* Devang Patel <dpatel@apple.com>. */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/fobjc-std-1.mm b/gcc/testsuite/obj-c++.dg/fobjc-std-1.mm
index 59db950..f7f4a19 100644
--- a/gcc/testsuite/obj-c++.dg/fobjc-std-1.mm
+++ b/gcc/testsuite/obj-c++.dg/fobjc-std-1.mm
@@ -1,6 +1,7 @@
/* Test warnings when using -fobjc-std=objc1. */
/* { dg-do compile } */
/* { dg-options "-fobjc-std=objc1" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm
index bdaef98..92852c3 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm
@@ -21,6 +21,7 @@
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm
index ae39026..f6e3d8d 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm
@@ -8,6 +8,7 @@
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-ivar.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-ivar.mm
index 1c85d23..991edc7 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-ivar.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-ivar.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-method.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-method.mm
index 97bf84b..07c3a22 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-method.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-method.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm
index 201ab7e..e68e7a8 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm
@@ -9,6 +9,7 @@
systems that don't have the V2 APis). XFAILing the run is not useful
since it will XPASS on the sub-set that works. */
/* { dg-skip-if "Incompatible" { *-*-darwin* } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-objc_msg_lookup.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-objc_msg_lookup.mm
index dcbf6d2..1fb56dc 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-objc_msg_lookup.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-objc_msg_lookup.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-object.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-object.mm
index a2702d6..4d99053 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-object.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-object.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-property.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-property.mm
index 953e9bb..601f39f 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-property.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-property.mm
@@ -4,6 +4,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-protocol.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-protocol.mm
index 9a2ceca..21ae06b 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-protocol.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-protocol.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-resolve-method.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-resolve-method.mm
index f8a54d3..dc311324 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-resolve-method.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-resolve-method.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm
index ff50058..dd8ff3e 100644
--- a/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm
+++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm
@@ -4,6 +4,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/obj-c++.dg/invalid-method-2.mm b/gcc/testsuite/obj-c++.dg/invalid-method-2.mm
index e3a8ed1..8eee0ff 100644
--- a/gcc/testsuite/obj-c++.dg/invalid-method-2.mm
+++ b/gcc/testsuite/obj-c++.dg/invalid-method-2.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* Test that using an invalid type in a method declaration produces a
friendly error without a compiler crash. */
diff --git a/gcc/testsuite/obj-c++.dg/ivar-invalid-type-1.mm b/gcc/testsuite/obj-c++.dg/ivar-invalid-type-1.mm
index 4c1480a..974e919 100644
--- a/gcc/testsuite/obj-c++.dg/ivar-invalid-type-1.mm
+++ b/gcc/testsuite/obj-c++.dg/ivar-invalid-type-1.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
@interface MyRootClass
diff --git a/gcc/testsuite/obj-c++.dg/ivar-problem-1.mm b/gcc/testsuite/obj-c++.dg/ivar-problem-1.mm
index 4ed5afa..1736f9c 100644
--- a/gcc/testsuite/obj-c++.dg/ivar-problem-1.mm
+++ b/gcc/testsuite/obj-c++.dg/ivar-problem-1.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This test checks what happens if there are 16 instance variables.
In that case, the class was not created correctly. In this testcase,
diff --git a/gcc/testsuite/obj-c++.dg/lto/lto.exp b/gcc/testsuite/obj-c++.dg/lto/lto.exp
index 6ba5f9c..936872a 100644
--- a/gcc/testsuite/obj-c++.dg/lto/lto.exp
+++ b/gcc/testsuite/obj-c++.dg/lto/lto.exp
@@ -41,10 +41,10 @@ if { ![check_effective_target_lto] } {
global LTO_OPTIONS
set LTO_OPTIONS [list \
- {-O0 -flto -fgnu-runtime} \
- {-O2 -flto -fgnu-runtime} \
- {-O0 -flto -flto-partition=none -fgnu-runtime} \
- {-O2 -flto -flto-partition=none -fgnu-runtime} \
+ {-O0 -flto -fgnu-runtime -Wno-objc-root-class} \
+ {-O2 -flto -fgnu-runtime -Wno-objc-root-class} \
+ {-O0 -flto -flto-partition=none -fgnu-runtime -Wno-objc-root-class} \
+ {-O2 -flto -flto-partition=none -fgnu-runtime -Wno-objc-root-class} \
]
obj-c++_init
@@ -67,10 +67,10 @@ foreach src $tests {
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
set LTO_OPTIONS [list \
- {-O0 -flto -fnext-runtime} \
- {-O2 -flto -fnext-runtime} \
- {-O0 -flto -flto-partition=none -fnext-runtime} \
- {-O2 -flto -flto-partition=none -fnext-runtime} \
+ {-O0 -flto -fnext-runtime -Wno-objc-root-class} \
+ {-O2 -flto -fnext-runtime -Wno-objc-root-class} \
+ {-O0 -flto -flto-partition=none -fnext-runtime -Wno-objc-root-class} \
+ {-O2 -flto -flto-partition=none -fnext-runtime -Wno-objc-root-class} \
]
foreach src $tests {
# If we're only testing specific files and this isn't one of them, skip it.
diff --git a/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm b/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
index 55f62f0..c3620c3 100644
--- a/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
+++ b/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
@@ -1,5 +1,5 @@
/* { dg-lto-do run } */
-/* { dg-skip-if "Needs OBJC2 ABI" { "*-*-darwin*" && lp64 } } */
+
extern "C" {
extern int printf (const char *,...) ;
extern void abort (void) ;
diff --git a/gcc/testsuite/obj-c++.dg/method-1.mm b/gcc/testsuite/obj-c++.dg/method-1.mm
index 7317ae2..5bb851a 100644
--- a/gcc/testsuite/obj-c++.dg/method-1.mm
+++ b/gcc/testsuite/obj-c++.dg/method-1.mm
@@ -3,6 +3,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/method-12.mm b/gcc/testsuite/obj-c++.dg/method-12.mm
index 4546144..d3145ab 100644
--- a/gcc/testsuite/obj-c++.dg/method-12.mm
+++ b/gcc/testsuite/obj-c++.dg/method-12.mm
@@ -3,6 +3,7 @@
/* { dg-options "-Wstrict-selector-match" } */
/* { dg-do compile } */
/* { dg-skip-if "Object interface removed" { *-*-darwin[1-2]* && { lp64 } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/Protocol.h>
diff --git a/gcc/testsuite/obj-c++.dg/method-18.mm b/gcc/testsuite/obj-c++.dg/method-18.mm
index 411caac..c753f33 100644
--- a/gcc/testsuite/obj-c++.dg/method-18.mm
+++ b/gcc/testsuite/obj-c++.dg/method-18.mm
@@ -1,5 +1,6 @@
/* Contributed by Igor Seleznev <selez@mail.ru>. */
/* This used to be broken. */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/method-19.mm b/gcc/testsuite/obj-c++.dg/method-19.mm
index 225beca..a3b977e 100644
--- a/gcc/testsuite/obj-c++.dg/method-19.mm
+++ b/gcc/testsuite/obj-c++.dg/method-19.mm
@@ -4,6 +4,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
#include "../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/obj-c++.dg/method-20.mm b/gcc/testsuite/obj-c++.dg/method-20.mm
index 9698225..a7fe41d 100644
--- a/gcc/testsuite/obj-c++.dg/method-20.mm
+++ b/gcc/testsuite/obj-c++.dg/method-20.mm
@@ -2,6 +2,7 @@
used as method selectors. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface Foo
- (void)insertNewButtonImage:(Foo *)newButtonImage in:(Foo *)buttonCell;
diff --git a/gcc/testsuite/obj-c++.dg/method-3.mm b/gcc/testsuite/obj-c++.dg/method-3.mm
index 9dab8c5..17b0c99 100644
--- a/gcc/testsuite/obj-c++.dg/method-3.mm
+++ b/gcc/testsuite/obj-c++.dg/method-3.mm
@@ -3,6 +3,7 @@
/* { dg-do compile } */
/* { dg-options "-Wno-strict-selector-match" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/method-4.mm b/gcc/testsuite/obj-c++.dg/method-4.mm
index e94f8f1..1f2f93e 100644
--- a/gcc/testsuite/obj-c++.dg/method-4.mm
+++ b/gcc/testsuite/obj-c++.dg/method-4.mm
@@ -3,6 +3,7 @@
/* { dg-do compile } */
/* { dg-options "-Wstrict-selector-match" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/method-5.mm b/gcc/testsuite/obj-c++.dg/method-5.mm
index 17c841a4..10364cc 100644
--- a/gcc/testsuite/obj-c++.dg/method-5.mm
+++ b/gcc/testsuite/obj-c++.dg/method-5.mm
@@ -3,6 +3,7 @@
/* { dg-do compile } */
/* { dg-options "-Wno-strict-selector-match" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/method-8.mm b/gcc/testsuite/obj-c++.dg/method-8.mm
index cde1bc2..9c5c17a 100644
--- a/gcc/testsuite/obj-c++.dg/method-8.mm
+++ b/gcc/testsuite/obj-c++.dg/method-8.mm
@@ -1,5 +1,6 @@
/* Tests of duplication. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface class1
- (int) meth1; /* { dg-message "previous declaration" } */
diff --git a/gcc/testsuite/obj-c++.dg/method-9.mm b/gcc/testsuite/obj-c++.dg/method-9.mm
index 787e25d..bee076e 100644
--- a/gcc/testsuite/obj-c++.dg/method-9.mm
+++ b/gcc/testsuite/obj-c++.dg/method-9.mm
@@ -1,6 +1,7 @@
/* Test for lookup of class (factory) methods. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface MyBase
- (void) rootInstanceMethod;
diff --git a/gcc/testsuite/obj-c++.dg/method-namespace-1.mm b/gcc/testsuite/obj-c++.dg/method-namespace-1.mm
index 6095f57..86006a7 100644
--- a/gcc/testsuite/obj-c++.dg/method-namespace-1.mm
+++ b/gcc/testsuite/obj-c++.dg/method-namespace-1.mm
@@ -1,5 +1,6 @@
/* Test for usage of namespace inside @implementation. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface MyDocument
@end
diff --git a/gcc/testsuite/obj-c++.dg/plugin/diagnostic-test-expressions-1.mm b/gcc/testsuite/obj-c++.dg/plugin/diagnostic-test-expressions-1.mm
index 988b290..128b3bd 100644
--- a/gcc/testsuite/obj-c++.dg/plugin/diagnostic-test-expressions-1.mm
+++ b/gcc/testsuite/obj-c++.dg/plugin/diagnostic-test-expressions-1.mm
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O -fdiagnostics-show-caret" } */
/* { dg-excess-errors "tree range 0:0-0:0" { target { *-*-darwin* } } } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* This file is similar to diagnostic-test-expressions-1.c
(see the notes in that file); this file adds test
diff --git a/gcc/testsuite/obj-c++.dg/pr23709.mm b/gcc/testsuite/obj-c++.dg/pr23709.mm
index 018b53a..7936956 100644
--- a/gcc/testsuite/obj-c++.dg/pr23709.mm
+++ b/gcc/testsuite/obj-c++.dg/pr23709.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface A
+(void)method: (int)parameter {} /* { dg-error "expected" } */
diff --git a/gcc/testsuite/obj-c++.dg/pragma-2.mm b/gcc/testsuite/obj-c++.dg/pragma-2.mm
index 14c4d79..09feac7 100644
--- a/gcc/testsuite/obj-c++.dg/pragma-2.mm
+++ b/gcc/testsuite/obj-c++.dg/pragma-2.mm
@@ -1,5 +1,6 @@
/* It is OK to use #pragma inside @implementation body. This test checks that. */
/* Ziemowit Laski <zlaski@apple.com>. */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface A
{
diff --git a/gcc/testsuite/obj-c++.dg/private-1.mm b/gcc/testsuite/obj-c++.dg/private-1.mm
index 0c25aea..2173b90 100644
--- a/gcc/testsuite/obj-c++.dg/private-1.mm
+++ b/gcc/testsuite/obj-c++.dg/private-1.mm
@@ -1,6 +1,7 @@
/* Test errors for accessing @private and @protected variables. */
/* Based on work by: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/obj-c++.dg/private-2.mm b/gcc/testsuite/obj-c++.dg/private-2.mm
index 3e6ff11..93b8a8f 100644
--- a/gcc/testsuite/obj-c++.dg/private-2.mm
+++ b/gcc/testsuite/obj-c++.dg/private-2.mm
@@ -2,6 +2,7 @@
/* Based on work by: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-1.mm b/gcc/testsuite/obj-c++.dg/property/at-property-1.mm
index 7cf650f..3325823 100644
--- a/gcc/testsuite/obj-c++.dg/property/at-property-1.mm
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-1.mm
@@ -6,15 +6,18 @@
{
Class isa;
}
-@property; /* { dg-error "expected identifier" } */
+@property; /* { dg-error "expected" } */
@property int; /* { dg-error "expected identifier" } */
+
@property int a;
@property int b, c;
-@property () int d; /* { dg-error "expected identifier" } */
+@property () int d; /* { dg-warning "empty property attribute list" } */
@property (readonly) int e;
-@property (readonly,) int f; /* { dg-error "expected identifier" } */
+@property (readonly,) int f; /* { dg-warning "missing property attribute" } */
@property (xxx) int g; /* { dg-error "unknown property attribute" } */
@property (readonly,xxx) int h; /* { dg-error "unknown property attribute" } */
-@property ( int i; /* { dg-error "expected identifier" } */
- /* { dg-error "expected ... " "" { target *-*-* } .-1 } */
+@property ( int i; /* { dg-error "unknown property attribute" } */
+ /* { dg-error "expected" "" { target *-*-* } .-1 } */
+@property (assign,,nonatomic) int j; /* { dg-warning "missing property attribute" } */
+@property (assign nonatomic) int k; /* { dg-error {expected } } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-29.mm b/gcc/testsuite/obj-c++.dg/property/at-property-29.mm
index 0f31617..64dfe83 100644
--- a/gcc/testsuite/obj-c++.dg/property/at-property-29.mm
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-29.mm
@@ -8,7 +8,9 @@
Class isa;
}
/* Test missing '=' in setter/getter attributes. */
-@property (getter) int property_a; /* { dg-error "missing .=. .after .getter. attribute." } */
-@property (setter) int property_b; /* { dg-error "missing .=. .after .setter. attribute." } */
-@property (assign, getter) int property_c; /* { dg-error "missing .=. .after .getter. attribute." } */
+@property (getter) int property_a; /* { dg-error {expected '=' after Objective-C 'getter'} } */
+@property (setter) int property_b; /* { dg-error {expected '=' after Objective-C 'setter'} } */
+@property (assign, getter) int property_c; /* { dg-error {expected '=' after Objective-C 'getter'} } */
+@property (retain, getter=) id x; /* { dg-error {expected 'getter' selector name} } */
+@property (retain, setter=) id y; /* { dg-error {expected 'setter' selector name} } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
index 941aab8..f589354 100644
--- a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
@@ -14,27 +14,53 @@
- (void) mySetter2: (int)property;
/* Test that all the new property attributes can be parsed. */
-@property (assign) id property_a;
-@property (copy) id property_b;
-@property (nonatomic) int property_c;
-@property (readonly) int property_d;
-@property (readwrite) int property_e;
-@property (retain) id property_f;
-@property (release) int property_g; /* { dg-error "unknown property attribute" } */
+@property (assign) id property_as_1;
+@property (copy) id property_as_2;
+@property (retain) id property_as_3;
-@property (getter=myGetter) int property_h;
-@property (setter=mySetter:) int property_i;
+@property (atomic) int property_at_1;
+@property (nonatomic) int property_at_2;
-/* Now test various problems. */
+@property (readonly) int property_rw_1;
+@property (readwrite) int property_rw_2;
-@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
+@property (class) int property_cl_1;
+
+@property (null_unspecified) int *property_null_1;
+@property (nullable) int *property_null_2;
+@property (nonnull) int *property_null_3;
+@property (null_resettable) int *property_null_4;
+
+@property (release) int property_err_1; /* { dg-error "unknown property attribute" } */
+
+@property (getter=myGetter) int property_g0;
+@property (setter=mySetter:) int property_s0;
+
+/* Now test various basic problems. */
+
+@property (readonly, readwrite) int a; /* { dg-error ".readwrite. attribute conflicts with .readonly. attribute" } */
@property (readonly, setter=mySetterB:) int b; /* { dg-error ".readonly. attribute conflicts with .setter. attribute" } */
-@property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
-@property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
+@property (assign, retain) id c; /* { dg-error ".retain. attribute conflicts with .assign. attribute" } */
+@property (assign, copy) id d; /* { dg-error ".copy. attribute conflicts with .assign. attribute" } */
@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
-@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-error ".setter. attribute may only be specified once" } */
-@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-error ".getter. attribute may only be specified once" } */
+@property (atomic, nonatomic) int property_j; /* { dg-error {'nonatomic' attribute conflicts with 'atomic' attribute} } */
+
+@property (null_unspecified) int property_bad_t_1; /* { dg-error {nullability specifier 'null_unspecified' cannot be applied to non-pointer type 'int'} } */
+@property (nullable) int property_bad_t_2;/* { dg-error {nullability specifier 'nullable' cannot be applied to non-pointer type 'int'} } */
+@property (nonnull) int property_bad_t_3;/* { dg-error {nullability specifier 'nonnull' cannot be applied to non-pointer type 'int'} } */
+@property (null_resettable) int property_bad_t_4;/* { dg-error {nullability specifier 'null_resettable' cannot be applied to non-pointer type 'int'} } */
+@property (nullable) int **property_bad_t_5;/* { dg-error {nullability specifier 'nullable' cannot be applied to multi-level pointer type 'int\*\*'} } */
+
+@property (null_unspecified, nullable) int *property_ne_1; /* { dg-error {'nullable' attribute conflicts with 'null_unspecified' attribute} } */
+@property (null_unspecified, nonnull) int *property_ne_2; /* { dg-error {'nonnull' attribute conflicts with 'null_unspecified' attribute} } */
+@property (null_unspecified, null_resettable) int *property_ne_3; /* { dg-error {'null_resettable' attribute conflicts with 'null_unspecified' attribute} } */
+@property (nullable,nonnull) int *property_ne_4; /* { dg-error {'nonnull' attribute conflicts with 'nullable' attribute} } */
+@property (nullable,null_resettable) int *property_ne_5; /* { dg-error {'null_resettable' attribute conflicts with 'nullable' attribute} } */
+@property (nonnull, null_resettable) int *property_ne_6; /* { dg-error {'null_resettable' attribute conflicts with 'nonnull' attribute} } */
+
+@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-warning {multiple property 'setter' methods specified, the latest one will be used} } */
+@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-warning {multiple property 'getter' methods specified, the latest one will be used} } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/nullability-00.mm b/gcc/testsuite/obj-c++.dg/property/nullability-00.mm
new file mode 100644
index 0000000..9b0c808
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/nullability-00.mm
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fsyntax-only" } */
+
+@interface MyRoot
+{
+ Class isa __attribute__((deprecated));
+ id p;
+ int x;
+ int *i;
+}
+
+@property(null_unspecified, assign) MyRoot *p1;
+@property(nonnull, assign) MyRoot *p2;
+@property(nullable, assign) MyRoot *p3;
+@property(null_resettable, assign) MyRoot *p4;
+@property(null_exciting, assign) MyRoot *e_5; /* { dg-error {unknown property attribute 'null_exciting'} } */
+
+@property(nonnull, retain, nullable) MyRoot *e_6; /* { dg-error {'nullable' attribute conflicts with 'nonnull' attribute} } */
+@property(nonnull, nonnull) int *i; /* { dg-warning {duplicate 'nonnull' attribute} } */
+
+@end
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
index f730fe8..794f2bd 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
@@ -4,5 +4,5 @@
@end
@implementation Bar
-@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */
+@property int FooBar; /* { dg-error {property declaration not in '@interface', '@protocol' or 'category' context} } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-6.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-6.mm
index 1db6f0b..c4a22eb 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-6.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-6.mm
@@ -6,4 +6,4 @@
int iVar;
}
@property int FooBar /* { dg-error "expected ';' at end of input" } */
- /* { dg-error "-:expected '@end' at end of input" "" { target *-*-* } .+1 } */
+ /* { dg-error "expected '@end' at end of input" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/obj-c++.dg/property/property.exp b/gcc/testsuite/obj-c++.dg/property/property.exp
index d18f610..31e683c 100644
--- a/gcc/testsuite/obj-c++.dg/property/property.exp
+++ b/gcc/testsuite/obj-c++.dg/property/property.exp
@@ -31,12 +31,12 @@ dg-init
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]]
# Main loop.
-dg-runtest $tests "-fgnu-runtime" $DEFAULT_OBJCXXFLAGS
+dg-runtest $tests "-fgnu-runtime -Wno-objc-root-class" $DEFAULT_OBJCXXFLAGS
# Darwin targets can also run code with the NeXT runtime.
# but Properties are not supported by the runtime lib before Darwin 9.
if [istarget "*-*-darwin\[9123\]*" ] {
- dg-runtest $tests "-fnext-runtime" $DEFAULT_OBJCXXFLAGS
+ dg-runtest $tests "-fnext-runtime -Wno-objc-root-class" $DEFAULT_OBJCXXFLAGS
}
# All done.
diff --git a/gcc/testsuite/obj-c++.dg/proto-lossage-1.mm b/gcc/testsuite/obj-c++.dg/proto-lossage-1.mm
index 2f7eb98..82cd053 100644
--- a/gcc/testsuite/obj-c++.dg/proto-lossage-1.mm
+++ b/gcc/testsuite/obj-c++.dg/proto-lossage-1.mm
@@ -2,6 +2,7 @@
may be lost, leading to superfluous warnings. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* One-line substitute for objc/objc.h */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
diff --git a/gcc/testsuite/obj-c++.dg/proto-lossage-5.mm b/gcc/testsuite/obj-c++.dg/proto-lossage-5.mm
index 35c0956..2a30bc2 100644
--- a/gcc/testsuite/obj-c++.dg/proto-lossage-5.mm
+++ b/gcc/testsuite/obj-c++.dg/proto-lossage-5.mm
@@ -1,5 +1,6 @@
/* Do not lose references to forward-declared protocols. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@class MyBaseClass;
@class MyClassThatFails;
@protocol _MyProtocol;
diff --git a/gcc/testsuite/obj-c++.dg/proto-qual-1.mm b/gcc/testsuite/obj-c++.dg/proto-qual-1.mm
index 7ef0e9a..b235064 100644
--- a/gcc/testsuite/obj-c++.dg/proto-qual-1.mm
+++ b/gcc/testsuite/obj-c++.dg/proto-qual-1.mm
@@ -3,6 +3,7 @@
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <stdio.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/protocol-inheritance-1.mm b/gcc/testsuite/obj-c++.dg/protocol-inheritance-1.mm
index 5241b29..c505c00 100644
--- a/gcc/testsuite/obj-c++.dg/protocol-inheritance-1.mm
+++ b/gcc/testsuite/obj-c++.dg/protocol-inheritance-1.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* { dg-options "-Wno-protocol" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/protocol-inheritance-2.mm b/gcc/testsuite/obj-c++.dg/protocol-inheritance-2.mm
index 74c9174..f2bc1ca 100644
--- a/gcc/testsuite/obj-c++.dg/protocol-inheritance-2.mm
+++ b/gcc/testsuite/obj-c++.dg/protocol-inheritance-2.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm b/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm
index bc4a3d0..4ecf436 100644
--- a/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm
+++ b/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/root-class-00.mm b/gcc/testsuite/obj-c++.dg/root-class-00.mm
new file mode 100644
index 0000000..f951b0d
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/root-class-00.mm
@@ -0,0 +1,10 @@
+/* Test Wobjc-root-class.
+ Note that we don't issue a warning unless the TU contains an implementation
+ for the class. */
+/* { dg-additional-options "-fsyntax-only " } */
+
+@interface ARootObject
+@end
+
+@implementation ARootObject /* { dg-warning {class 'ARootObject' defined without specifying a base class} } */
+@end
diff --git a/gcc/testsuite/obj-c++.dg/selector-1.mm b/gcc/testsuite/obj-c++.dg/selector-1.mm
index d34f8c8..b0cdc9c 100644
--- a/gcc/testsuite/obj-c++.dg/selector-1.mm
+++ b/gcc/testsuite/obj-c++.dg/selector-1.mm
@@ -3,6 +3,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface Int1
+ (int)and_eq:(int)arg1 and:(int)arg2;
diff --git a/gcc/testsuite/obj-c++.dg/selector-2.mm b/gcc/testsuite/obj-c++.dg/selector-2.mm
index 840ee19..fa9ab41 100644
--- a/gcc/testsuite/obj-c++.dg/selector-2.mm
+++ b/gcc/testsuite/obj-c++.dg/selector-2.mm
@@ -1,6 +1,7 @@
/* Test that we don't ICE when issuing a -Wselector warning. */
/* { dg-options "-Wselector" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
diff --git a/gcc/testsuite/obj-c++.dg/selector-3.mm b/gcc/testsuite/obj-c++.dg/selector-3.mm
index a1321a7..0c98056 100644
--- a/gcc/testsuite/obj-c++.dg/selector-3.mm
+++ b/gcc/testsuite/obj-c++.dg/selector-3.mm
@@ -2,6 +2,7 @@
/* This is the "-fgnu-runtime" variant of objc.dg/selector-1.m. */
/* { dg-options "-Wselector -fgnu-runtime" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
typedef struct objc_object { struct objc_class *class_pointer; } *id;
typedef const struct objc_selector *SEL;
diff --git a/gcc/testsuite/obj-c++.dg/selector-4.mm b/gcc/testsuite/obj-c++.dg/selector-4.mm
index 690cc44..b6ddcbe 100644
--- a/gcc/testsuite/obj-c++.dg/selector-4.mm
+++ b/gcc/testsuite/obj-c++.dg/selector-4.mm
@@ -3,6 +3,7 @@
/* { dg-options "-Wselector -fnext-runtime" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
typedef struct objc_object { struct objc_class *class_pointer; } *id;
typedef struct objc_selector *SEL;
diff --git a/gcc/testsuite/obj-c++.dg/strings/strings.exp b/gcc/testsuite/obj-c++.dg/strings/strings.exp
index 1bfb3be..0243f24 100644
--- a/gcc/testsuite/obj-c++.dg/strings/strings.exp
+++ b/gcc/testsuite/obj-c++.dg/strings/strings.exp
@@ -34,11 +34,11 @@ dg-init
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]]
# Main loop.
-dg-runtest $tests "-fgnu-runtime" $DEFAULT_OBJCXXFLAGS
+dg-runtest $tests "-fgnu-runtime -Wno-objc-root-class" $DEFAULT_OBJCXXFLAGS
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
- dg-runtest $tests "-fnext-runtime" $DEFAULT_OBJCXXFLAGS
+ dg-runtest $tests "-fnext-runtime -Wno-objc-root-class" $DEFAULT_OBJCXXFLAGS
}
# All done.
diff --git a/gcc/testsuite/obj-c++.dg/stubify-1.mm b/gcc/testsuite/obj-c++.dg/stubify-1.mm
index a32e282..21de463 100644
--- a/gcc/testsuite/obj-c++.dg/stubify-1.mm
+++ b/gcc/testsuite/obj-c++.dg/stubify-1.mm
@@ -5,6 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-Os -mdynamic-no-pic -fno-exceptions -mmacosx-version-min=10.4 -msymbol-stubs" } */
+// { dg-additional-options "-Wno-objc-root-class" }
typedef struct objc_object { } *id ;
int x = 41 ;
diff --git a/gcc/testsuite/obj-c++.dg/stubify-2.mm b/gcc/testsuite/obj-c++.dg/stubify-2.mm
index 69fea8d..cbc52b1 100644
--- a/gcc/testsuite/obj-c++.dg/stubify-2.mm
+++ b/gcc/testsuite/obj-c++.dg/stubify-2.mm
@@ -5,6 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump -mmacosx-version-min=10.4 -msymbol-stubs" } */
+// { dg-additional-options "-Wno-objc-root-class" }
typedef struct objc_object { } *id ;
int x = 41 ;
diff --git a/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm b/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm
index 0ab177b..39ddd01 100644
--- a/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm
+++ b/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface Foo {
void *isa;
diff --git a/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm b/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm
index 80dcf49..6dac31c 100644
--- a/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm
+++ b/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface Foo {
void *isa;
diff --git a/gcc/testsuite/obj-c++.dg/sync-3.mm b/gcc/testsuite/obj-c++.dg/sync-3.mm
index 95def43..2949d6a 100644
--- a/gcc/testsuite/obj-c++.dg/sync-3.mm
+++ b/gcc/testsuite/obj-c++.dg/sync-3.mm
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
/* Test that the compiler is checking the argument of @synchronized(),
and produce errors when invalid types are used. */
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-10.mm b/gcc/testsuite/obj-c++.dg/syntax-error-10.mm
index 6fcf96f..f8e0c50 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-10.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-10.mm
@@ -1,2 +1,2 @@
@interface
-/* { dg-error "-:expected identifier" "" { target *-*-* } .+1 } */
+/* { dg-error "expected identifier" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-2.mm b/gcc/testsuite/obj-c++.dg/syntax-error-2.mm
index ba8804a..bf4d5ff 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-2.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-2.mm
@@ -1,4 +1,5 @@
/* Recover gracefully from a syntax error. */
+// { dg-additional-options "-Wno-objc-root-class" }
@implementation Whatever /* { dg-warning "cannot find interface declaration for .Whatever." } */
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-4.mm b/gcc/testsuite/obj-c++.dg/syntax-error-4.mm
index 0df0618..97587f9 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-4.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-4.mm
@@ -1,5 +1,6 @@
/* Yet another stray infinite loop... */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface t
{
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-7.mm b/gcc/testsuite/obj-c++.dg/syntax-error-7.mm
index 5bdccc7..c406d8f 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-7.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-7.mm
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface Foo
-(void) someMethod;
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-8.mm b/gcc/testsuite/obj-c++.dg/syntax-error-8.mm
index f7cfe0e..c13303f 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-8.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-8.mm
@@ -1 +1 @@
-@interface A /* { dg-error "-:expected ..end." "" { target *-*-* } .+1 } */
+@interface A /* { dg-error "expected ..end." "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-9.mm b/gcc/testsuite/obj-c++.dg/syntax-error-9.mm
index 1876c32..e1f8bd1 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-9.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-9.mm
@@ -1,3 +1,4 @@
+// { dg-additional-options "-Wno-objc-root-class" }
@implementation SaturnDoc /* { dg-warning "cannot find interface declaration" } */
- read: (void*)aStream ggg /* { dg-error "expected .:. at end of input" } */
-/* { dg-error "-:expected ..*. at end of input" "" { target *-*-* } .+1 } */
+/* { dg-error "expected ..*. at end of input" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/obj-c++.dg/template-4.mm b/gcc/testsuite/obj-c++.dg/template-4.mm
index 5301df5..02795e7 100644
--- a/gcc/testsuite/obj-c++.dg/template-4.mm
+++ b/gcc/testsuite/obj-c++.dg/template-4.mm
@@ -4,6 +4,7 @@
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
/* { dg-additional-sources "../objc-obj-c++-shared/nsconstantstring-class-impl.mm" } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <stdarg.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/template-7.mm b/gcc/testsuite/obj-c++.dg/template-7.mm
index 8621abe..b3697a5 100644
--- a/gcc/testsuite/obj-c++.dg/template-7.mm
+++ b/gcc/testsuite/obj-c++.dg/template-7.mm
@@ -3,6 +3,7 @@
// Author: Fariborz Jahanian <fjahanian@apple.com>
// { dg-do compile }
// { dg-options "" }
+// { dg-additional-options "-Wno-objc-root-class" }
typedef struct objc_class *Class;
@interface Object
diff --git a/gcc/testsuite/obj-c++.dg/template-8.mm b/gcc/testsuite/obj-c++.dg/template-8.mm
index df215b8..1b9f4d1 100644
--- a/gcc/testsuite/obj-c++.dg/template-8.mm
+++ b/gcc/testsuite/obj-c++.dg/template-8.mm
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <objc/objc.h>
#include <objc/runtime.h>
diff --git a/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm b/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm
index c481810..32f4fd8 100644
--- a/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm
+++ b/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm
@@ -3,6 +3,7 @@
/* { dg-do run { target *-*-darwin* } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+// { dg-additional-options "-Wno-objc-root-class" }
#include <stdio.h>
#include <string.h>
diff --git a/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp b/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp
index c3d3f8e..4e46207 100644
--- a/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp
+++ b/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp
@@ -7,11 +7,11 @@ dg-init
# Gather a list of all tests.
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]]
-obj-c++-dg-runtest $tests "" "-fgnu-runtime"
+obj-c++-dg-runtest $tests "" "-fgnu-runtime -Wno-objc-root-class"
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
- obj-c++-dg-runtest $tests "" "-fnext-runtime"
+ obj-c++-dg-runtest $tests "" "-fnext-runtime -Wno-objc-root-class"
}
dg-finish
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/strings.exp b/gcc/testsuite/obj-c++.dg/torture/strings/strings.exp
index 401bc58..6181c30 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/strings.exp
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/strings.exp
@@ -24,11 +24,11 @@ dg-init
# Gather a list of all tests.
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]]
-obj-c++-dg-runtest $tests "" "-fgnu-runtime"
+obj-c++-dg-runtest $tests "" "-fgnu-runtime -Wno-objc-root-class"
# Darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
- obj-c++-dg-runtest $tests "" "-fnext-runtime"
+ obj-c++-dg-runtest $tests "" "-fnext-runtime -Wno-objc-root-class"
}
dg-finish
diff --git a/gcc/testsuite/obj-c++.dg/try-catch-12.mm b/gcc/testsuite/obj-c++.dg/try-catch-12.mm
index e08f321..6a60805 100644
--- a/gcc/testsuite/obj-c++.dg/try-catch-12.mm
+++ b/gcc/testsuite/obj-c++.dg/try-catch-12.mm
@@ -4,6 +4,7 @@
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
typedef volatile int IOSharedLockData;
diff --git a/gcc/testsuite/obj-c++.dg/try-catch-13.mm b/gcc/testsuite/obj-c++.dg/try-catch-13.mm
index 050d811..0e6f01b 100644
--- a/gcc/testsuite/obj-c++.dg/try-catch-13.mm
+++ b/gcc/testsuite/obj-c++.dg/try-catch-13.mm
@@ -4,6 +4,7 @@
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+// { dg-additional-options "-Wno-objc-root-class" }
@interface TestMyTests
- (void) testSpoon;
diff --git a/gcc/testsuite/objc.dg/SEL-typedef.m b/gcc/testsuite/objc.dg/SEL-typedef.m
new file mode 100644
index 0000000..2ece1fd
--- /dev/null
+++ b/gcc/testsuite/objc.dg/SEL-typedef.m
@@ -0,0 +1,7 @@
+/* Check that we accept the SEL typedef. */
+/* { dg-additional-options "-fsyntax-only " } */
+
+SEL aSelector;
+
+typedef SEL MySEL;
+
diff --git a/gcc/testsuite/objc.dg/anon-1.m b/gcc/testsuite/objc.dg/anon-1.m
index 5f10f7d..5dab3fa 100644
--- a/gcc/testsuite/objc.dg/anon-1.m
+++ b/gcc/testsuite/objc.dg/anon-1.m
@@ -1,5 +1,6 @@
/* Test for graceful handling of anonymous ivars. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Foo {
unsigned char : 1;
diff --git a/gcc/testsuite/objc.dg/attributes/class-attribute-1.m b/gcc/testsuite/objc.dg/attributes/class-attribute-1.m
index 3444760..93e5d7f 100644
--- a/gcc/testsuite/objc.dg/attributes/class-attribute-1.m
+++ b/gcc/testsuite/objc.dg/attributes/class-attribute-1.m
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test deprecate attribute with an @interface declaration. */
diff --git a/gcc/testsuite/objc.dg/attributes/class-attribute-2.m b/gcc/testsuite/objc.dg/attributes/class-attribute-2.m
index 2e1bacb..f8137ff 100644
--- a/gcc/testsuite/objc.dg/attributes/class-attribute-2.m
+++ b/gcc/testsuite/objc.dg/attributes/class-attribute-2.m
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/class-attribute-3.m b/gcc/testsuite/objc.dg/attributes/class-attribute-3.m
index 6cc5d4e..7c3b3b0 100644
--- a/gcc/testsuite/objc.dg/attributes/class-attribute-3.m
+++ b/gcc/testsuite/objc.dg/attributes/class-attribute-3.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that you get a warning when an unknown class attribute is ignored. */
diff --git a/gcc/testsuite/objc.dg/attributes/method-deprecated-1.m b/gcc/testsuite/objc.dg/attributes/method-deprecated-1.m
index 8343856..68e8373 100644
--- a/gcc/testsuite/objc.dg/attributes/method-deprecated-1.m
+++ b/gcc/testsuite/objc.dg/attributes/method-deprecated-1.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/method-deprecated-2.m b/gcc/testsuite/objc.dg/attributes/method-deprecated-2.m
index 1e5d87f..8fb0e15 100644
--- a/gcc/testsuite/objc.dg/attributes/method-deprecated-2.m
+++ b/gcc/testsuite/objc.dg/attributes/method-deprecated-2.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/method-deprecated-3.m b/gcc/testsuite/objc.dg/attributes/method-deprecated-3.m
index 5c715a2..efa2d34 100644
--- a/gcc/testsuite/objc.dg/attributes/method-deprecated-3.m
+++ b/gcc/testsuite/objc.dg/attributes/method-deprecated-3.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/method-format-1.m b/gcc/testsuite/objc.dg/attributes/method-format-1.m
index 9ff34f9..d3bb997 100644
--- a/gcc/testsuite/objc.dg/attributes/method-format-1.m
+++ b/gcc/testsuite/objc.dg/attributes/method-format-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
/* { dg-options "-Wall" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m b/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m
index fe5f885..a3bfd9b 100644
--- a/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m
+++ b/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, May 2011. */
/* { dg-do compile } */
/* { dg-options "-Wall" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/objc.dg/attributes/method-noreturn-1.m b/gcc/testsuite/objc.dg/attributes/method-noreturn-1.m
index a83048b..413a0be 100644
--- a/gcc/testsuite/objc.dg/attributes/method-noreturn-1.m
+++ b/gcc/testsuite/objc.dg/attributes/method-noreturn-1.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/objc.dg/attributes/method-sentinel-1.m b/gcc/testsuite/objc.dg/attributes/method-sentinel-1.m
index e2abb1e..f89c981 100644
--- a/gcc/testsuite/objc.dg/attributes/method-sentinel-1.m
+++ b/gcc/testsuite/objc.dg/attributes/method-sentinel-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do compile } */
/* { dg-options "-Wall" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/objc.dg/attributes/nsobject-01.m b/gcc/testsuite/objc.dg/attributes/nsobject-01.m
new file mode 100644
index 0000000..1f33150
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/nsobject-01.m
@@ -0,0 +1,67 @@
+/* Test handling of the NSObject attribute. */
+/* { dg-additional-options "-fsyntax-only " } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
+
+typedef struct AnObj * __attribute__ ((NSObject)) AnObjRef;
+typedef struct AnObj * __attribute__ ((__NSObject__)) AnotherObjRef;
+
+/* We allow a void * to be labeled as NSObject. */
+typedef void * __attribute__((NSObject)) AnonRef;
+
+typedef struct AnObj * __attribute__((NSObject("foo"))) Bad; // { dg-error {wrong number of arguments specified for 'NSObject' attribute} }
+typedef struct AnObj * __attribute__((NSObject(42))) Wrong; // { dg-error {wrong number of arguments specified for 'NSObject' attribute} }
+
+/* Must be a pointer. */
+typedef struct AnObj __attribute__((NSObject)) BadRef; // { dg-error {'NSObject' attribute is for pointer types only} }
+
+typedef void * VPtr;
+
+@interface CheckAttrNSObject
+{
+@public
+ AnObjRef aor;
+ /* TODO: synthesize without pre-defined ivars. */
+ VPtr obj_v;
+ int bar;
+ /* TODO: This should warn, even tho the property does not */
+ __attribute__((NSObject)) struct AnObj *Thing;
+}
+
+@property(copy) AnObjRef aor;
+
+typedef struct AnObj * __attribute__((NSObject)) AnObjPtr3;
+@property (nonatomic, retain) AnObjPtr3 obj_3;
+
+@property (retain) __attribute__((NSObject)) VPtr obj_v;
+
+//@property (strong, nullable) AnObjPtr3 objp_4;
+
+@property(retain) __attribute__((NSObject)) int bar;
+ // { dg-error {'NSObject' attribute is for pointer types only} "" { target *-*-* } .-1 }
+ // { dg-error {'retain' attribute is only valid for Objective-C objects} "" { target *-*-* } .-2 }
+
+@end
+
+void foo ()
+{
+ __attribute__((NSObject)) struct AnObj *AnotherThing; // { dg-warning {'NSObject' attribute may be put on a typedef only; attribute is ignored} }
+}
+
+void
+setProperty(id self, id value)
+{
+ ((CheckAttrNSObject *)self)->aor = value;
+}
+
+id
+getProperty(id self)
+{
+ return (id)((CheckAttrNSObject *)self)->aor;
+}
+
+@implementation CheckAttrNSObject
+@synthesize aor;
+@dynamic obj_3;
+@synthesize obj_v;
+@synthesize bar; // { dg-warning {returning 'id' from a function with return type 'int'} }
+@end // { dg-warning {passing argument} }
diff --git a/gcc/testsuite/objc.dg/attributes/nullability-00.m b/gcc/testsuite/objc.dg/attributes/nullability-00.m
new file mode 100644
index 0000000..81c0145
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/nullability-00.m
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class -fsyntax-only" } */
+
+__attribute__((objc_nullability(0))) id a;
+__attribute__((objc_nullability(4))) id e_1; /* { dg-error {'objc_nullability' attribute argument '4' is not an integer constant between 0 and 3} } */
+__attribute__((objc_nullability(-22))) id e_2; /* { dg-error {'objc_nullability' attribute argument '-22' is not an integer constant between 0 and 3} } */
+__attribute__((objc_nullability("unspecified"))) id b;
+__attribute__((objc_nullability("nullable"))) id c;
+__attribute__((objc_nullability("nonnull"))) id d;
+__attribute__((objc_nullability("resettable"))) id e;
+__attribute__((objc_nullability("nonsense"))) id e_3; /* { dg-error {'objc_nullability' attribute argument '"nonsense"' is not recognised} } */
+__attribute__((objc_nullability(noGoingToWork))) id e_4; /* { dg-error {'noGoingToWork' undeclared here} } */
+
+@interface MyRoot
+{
+ __attribute__((objc_nullability(0))) id iv_a;
+ __attribute__((objc_nullability(3))) struct { int bad_a; } s;/* { dg-error {'objc_nullability' cannot be applied to non-pointer type 'struct <anonymous>'} } */
+ __attribute__((objc_nullability("resettable"))) int iv_b;/* { dg-error {'objc_nullability' cannot be applied to non-pointer type 'int'} } */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/attributes/objc-exception-1.m b/gcc/testsuite/objc.dg/attributes/objc-exception-1.m
index e7f6f85..19e5ade 100644
--- a/gcc/testsuite/objc.dg/attributes/objc-exception-1.m
+++ b/gcc/testsuite/objc.dg/attributes/objc-exception-1.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, February 2011. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that the 'objc_exception' attribute is accepted for
@interfaces, but not for anything else. */
diff --git a/gcc/testsuite/objc.dg/attributes/parameter-attribute-1.m b/gcc/testsuite/objc.dg/attributes/parameter-attribute-1.m
index 8263df6..d6ebaf2 100644
--- a/gcc/testsuite/objc.dg/attributes/parameter-attribute-1.m
+++ b/gcc/testsuite/objc.dg/attributes/parameter-attribute-1.m
@@ -1,6 +1,7 @@
/* Test __attribute__((unused)) for an Objective-C method parameter. */
/* { dg-do compile } */
/* { dg-options "-Wunused-parameter" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/parameter-attribute-2.m b/gcc/testsuite/objc.dg/attributes/parameter-attribute-2.m
index 99c5a30..637846d 100644
--- a/gcc/testsuite/objc.dg/attributes/parameter-attribute-2.m
+++ b/gcc/testsuite/objc.dg/attributes/parameter-attribute-2.m
@@ -1,5 +1,6 @@
/* Test that we get warnings for unrecognized attributes. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/proto-attribute-1.m b/gcc/testsuite/objc.dg/attributes/proto-attribute-1.m
index a852a7a..03726dc 100644
--- a/gcc/testsuite/objc.dg/attributes/proto-attribute-1.m
+++ b/gcc/testsuite/objc.dg/attributes/proto-attribute-1.m
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/attributes/proto-attribute-2.m b/gcc/testsuite/objc.dg/attributes/proto-attribute-2.m
index b23b81d..6a73d24 100644
--- a/gcc/testsuite/objc.dg/attributes/proto-attribute-2.m
+++ b/gcc/testsuite/objc.dg/attributes/proto-attribute-2.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test deprecate attribute with a forward declarations of
@protocol. */
diff --git a/gcc/testsuite/objc.dg/attributes/proto-attribute-3.m b/gcc/testsuite/objc.dg/attributes/proto-attribute-3.m
index 2be286e..ad6d0c8 100644
--- a/gcc/testsuite/objc.dg/attributes/proto-attribute-3.m
+++ b/gcc/testsuite/objc.dg/attributes/proto-attribute-3.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test deprecate attribute with normal @protocol declarations. */
diff --git a/gcc/testsuite/objc.dg/attributes/proto-attribute-4.m b/gcc/testsuite/objc.dg/attributes/proto-attribute-4.m
index 226fd68..8d34ebd 100644
--- a/gcc/testsuite/objc.dg/attributes/proto-attribute-4.m
+++ b/gcc/testsuite/objc.dg/attributes/proto-attribute-4.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that you get a warning when an unknown protocol attribute is ignored. */
diff --git a/gcc/testsuite/objc.dg/attributes/root-class-01.m b/gcc/testsuite/objc.dg/attributes/root-class-01.m
new file mode 100644
index 0000000..84da94a
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/root-class-01.m
@@ -0,0 +1,11 @@
+/* Test Wobjc-root-class warning is suppressed by the objc_root_class attr.
+ Note that we don't issue a warning unless the TU contains an implementation
+ for the class. This should compile without warning. */
+/* { dg-additional-options "-fsyntax-only " } */
+
+__attribute__((objc_root_class))
+@interface ARootObject
+@end
+
+@implementation ARootObject
+@end
diff --git a/gcc/testsuite/objc.dg/bitfield-2.m b/gcc/testsuite/objc.dg/bitfield-2.m
index 7e8147a..b28c81e 100644
--- a/gcc/testsuite/objc.dg/bitfield-2.m
+++ b/gcc/testsuite/objc.dg/bitfield-2.m
@@ -4,6 +4,7 @@
/* { dg-options "-fsigned-char" } */
/* { dg-do run { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
diff --git a/gcc/testsuite/objc.dg/break-in-ifstmt.m b/gcc/testsuite/objc.dg/break-in-ifstmt.m
index 8968494..6176832 100644
--- a/gcc/testsuite/objc.dg/break-in-ifstmt.m
+++ b/gcc/testsuite/objc.dg/break-in-ifstmt.m
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface foo
- (void) test;
diff --git a/gcc/testsuite/objc.dg/class-1.m b/gcc/testsuite/objc.dg/class-1.m
index 0504937..64383f2 100644
--- a/gcc/testsuite/objc.dg/class-1.m
+++ b/gcc/testsuite/objc.dg/class-1.m
@@ -1,5 +1,6 @@
/* Redeclarations of class names. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef int foo; /* { dg-line foo_def } */
@@ -8,6 +9,9 @@ typedef int foo; /* { dg-line foo_def } */
typedef int bar; /* { dg-line bar_def } */
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface bar
@end /* { dg-error "redeclared as different kind of symbol" } */
/* { dg-error "previous declaration of" "" { target *-*-* } bar_def } */
diff --git a/gcc/testsuite/objc.dg/class-extension-1.m b/gcc/testsuite/objc.dg/class-extension-1.m
index 5c89a98..9d6658a 100644
--- a/gcc/testsuite/objc.dg/class-extension-1.m
+++ b/gcc/testsuite/objc.dg/class-extension-1.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* This test tests the basic of class extensions. */
diff --git a/gcc/testsuite/objc.dg/class-extension-2.m b/gcc/testsuite/objc.dg/class-extension-2.m
index 7f55b60..293facb1 100644
--- a/gcc/testsuite/objc.dg/class-extension-2.m
+++ b/gcc/testsuite/objc.dg/class-extension-2.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* This test tests class extensions and protocols. */
diff --git a/gcc/testsuite/objc.dg/class-extension-3.m b/gcc/testsuite/objc.dg/class-extension-3.m
index 69e5705..51fe5ee 100644
--- a/gcc/testsuite/objc.dg/class-extension-3.m
+++ b/gcc/testsuite/objc.dg/class-extension-3.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* This test tests warnings on class extensions. */
diff --git a/gcc/testsuite/objc.dg/class-extension-4.m b/gcc/testsuite/objc.dg/class-extension-4.m
index 692a0fc..5d367d4 100644
--- a/gcc/testsuite/objc.dg/class-extension-4.m
+++ b/gcc/testsuite/objc.dg/class-extension-4.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* This test tests you can not declare a class extension after the class @implementation. */
diff --git a/gcc/testsuite/objc.dg/class-protocol-1.m b/gcc/testsuite/objc.dg/class-protocol-1.m
index 59c8f82..34680c2 100644
--- a/gcc/testsuite/objc.dg/class-protocol-1.m
+++ b/gcc/testsuite/objc.dg/class-protocol-1.m
@@ -1,6 +1,7 @@
/* Check Class <protocol> types */
/* Author: David Ayers <d.ayers@inode.at> */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include "../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/objc.dg/comp-types-7.m b/gcc/testsuite/objc.dg/comp-types-7.m
index 526934f..6b796f0 100644
--- a/gcc/testsuite/objc.dg/comp-types-7.m
+++ b/gcc/testsuite/objc.dg/comp-types-7.m
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* We used to ICE because we removed the cast to List_linked*
in -[ListIndex_linked next]. */
diff --git a/gcc/testsuite/objc.dg/demangle-1.m b/gcc/testsuite/objc.dg/demangle-1.m
index 42b79a9..61e79a6 100644
--- a/gcc/testsuite/objc.dg/demangle-1.m
+++ b/gcc/testsuite/objc.dg/demangle-1.m
@@ -1,6 +1,7 @@
/* Test demangling an Objective-C method. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <string.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/objc.dg/duplicate-class-1.m b/gcc/testsuite/objc.dg/duplicate-class-1.m
index 30a18ff..7992ebf 100644
--- a/gcc/testsuite/objc.dg/duplicate-class-1.m
+++ b/gcc/testsuite/objc.dg/duplicate-class-1.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that a duplicated @implementation for the same class does not
crash the compiler. */
diff --git a/gcc/testsuite/objc.dg/encode-6-next.m b/gcc/testsuite/objc.dg/encode-6-next.m
index c3d9226..18ee15d 100644
--- a/gcc/testsuite/objc.dg/encode-6-next.m
+++ b/gcc/testsuite/objc.dg/encode-6-next.m
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
struct Cxx {
const struct Cxx *next;
diff --git a/gcc/testsuite/objc.dg/encode-6.m b/gcc/testsuite/objc.dg/encode-6.m
index 291a41e..9e9e492 100644
--- a/gcc/testsuite/objc.dg/encode-6.m
+++ b/gcc/testsuite/objc.dg/encode-6.m
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
struct Cxx {
const struct Cxx *next;
diff --git a/gcc/testsuite/objc.dg/enhanced-proto-2.m b/gcc/testsuite/objc.dg/enhanced-proto-2.m
index c196b51..ca99445 100644
--- a/gcc/testsuite/objc.dg/enhanced-proto-2.m
+++ b/gcc/testsuite/objc.dg/enhanced-proto-2.m
@@ -1,5 +1,6 @@
/* Test use of @optional/@required keywords in @protocol class. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@protocol MyProto1
@optional
diff --git a/gcc/testsuite/objc.dg/exceptions-1.m b/gcc/testsuite/objc.dg/exceptions-1.m
index 0f3b7e8..1e86177 100644
--- a/gcc/testsuite/objc.dg/exceptions-1.m
+++ b/gcc/testsuite/objc.dg/exceptions-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* This test checks the syntax @catch (...) which catches any
exceptions. At the moment, @catch (...) is identical to @catch (id
diff --git a/gcc/testsuite/objc.dg/exceptions-3.m b/gcc/testsuite/objc.dg/exceptions-3.m
index 69a6494..bedaf53 100644
--- a/gcc/testsuite/objc.dg/exceptions-3.m
+++ b/gcc/testsuite/objc.dg/exceptions-3.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that the compiler is checking the argument of @catch(), and
produce errors when invalid types are used. */
diff --git a/gcc/testsuite/objc.dg/exceptions-4.m b/gcc/testsuite/objc.dg/exceptions-4.m
index bbdb741..5d77ffa 100644
--- a/gcc/testsuite/objc.dg/exceptions-4.m
+++ b/gcc/testsuite/objc.dg/exceptions-4.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test warnings when parsing syntax errors in @catch(). */
diff --git a/gcc/testsuite/objc.dg/exceptions-5.m b/gcc/testsuite/objc.dg/exceptions-5.m
index 55ef0f3..31796bc 100644
--- a/gcc/testsuite/objc.dg/exceptions-5.m
+++ b/gcc/testsuite/objc.dg/exceptions-5.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that you can use an unnamed argument with @catch. This test is the same
as exceptions-3.m, but with no name for @catch arguments. */
diff --git a/gcc/testsuite/objc.dg/fobjc-std-1.m b/gcc/testsuite/objc.dg/fobjc-std-1.m
index 9a15b8a..729f65c 100644
--- a/gcc/testsuite/objc.dg/fobjc-std-1.m
+++ b/gcc/testsuite/objc.dg/fobjc-std-1.m
@@ -1,6 +1,7 @@
/* Test warnings when using -fobjc-std=objc1. */
/* { dg-do compile } */
/* { dg-options "-fobjc-std=objc1" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
@@ -29,8 +30,8 @@
@end
__attribute__ ((deprecated))
-@interface MyRootClass2
-{ /* { dg-error "class attributes are not available in Objective.C 1.0" } */
+@interface MyRootClass2 /* { dg-error "class attributes are not available in Objective.C 1.0" } */
+{
Class isa;
}
@end
diff --git a/gcc/testsuite/objc.dg/foreach-2.m b/gcc/testsuite/objc.dg/foreach-2.m
index 93bc902..ccce557 100644
--- a/gcc/testsuite/objc.dg/foreach-2.m
+++ b/gcc/testsuite/objc.dg/foreach-2.m
@@ -6,6 +6,7 @@
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
/* { dg-additional-sources "../objc-obj-c++-shared/nsconstantstring-class-impl.m" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include "../objc-obj-c++-shared/TestsuiteObject.m"
#ifndef __NEXT_RUNTIME__
diff --git a/gcc/testsuite/objc.dg/foreach-4.m b/gcc/testsuite/objc.dg/foreach-4.m
index faee73b..2365609 100644
--- a/gcc/testsuite/objc.dg/foreach-4.m
+++ b/gcc/testsuite/objc.dg/foreach-4.m
@@ -6,6 +6,7 @@
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
/* { dg-additional-sources "../objc-obj-c++-shared/nsconstantstring-class-impl.m" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#import "../objc-obj-c++-shared/TestsuiteObject.m"
#ifndef __NEXT_RUNTIME__
diff --git a/gcc/testsuite/objc.dg/foreach-5.m b/gcc/testsuite/objc.dg/foreach-5.m
index dce26fa..1bcb10b 100644
--- a/gcc/testsuite/objc.dg/foreach-5.m
+++ b/gcc/testsuite/objc.dg/foreach-5.m
@@ -6,6 +6,7 @@
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
/* { dg-additional-sources "../objc-obj-c++-shared/nsconstantstring-class-impl.m" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#import "../objc-obj-c++-shared/TestsuiteObject.m"
#ifndef __NEXT_RUNTIME__
diff --git a/gcc/testsuite/objc.dg/fsyntax-only.m b/gcc/testsuite/objc.dg/fsyntax-only.m
index 54a879e..70ea8ac 100644
--- a/gcc/testsuite/objc.dg/fsyntax-only.m
+++ b/gcc/testsuite/objc.dg/fsyntax-only.m
@@ -2,6 +2,9 @@
/* { dg-do compile } */
/* { dg-options "-fsyntax-only" } */
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface foo
-(void) my_method:(int) i with:(int) j;
@end
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m b/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m
index 3a85b16..6c1c76a 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m
@@ -20,6 +20,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */
/* To get the modern GNU Objective-C Runtime API, you include
@@ -29,9 +30,6 @@
#include <stdio.h>
#include <string.h>
-#if __has_attribute(objc_root_class)
-__attribute__((objc_root_class))
-#endif
@interface MyRootClass
{ Class isa; }
+ alloc;
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-class.m b/gcc/testsuite/objc.dg/gnu-api-2-class.m
index eade0dc..d11dae0 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-class.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-class.m
@@ -7,6 +7,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */
/* To get the modern GNU Objective-C Runtime API, you include
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-ivar.m b/gcc/testsuite/objc.dg/gnu-api-2-ivar.m
index 19ac004..072d265 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-ivar.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-ivar.m
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-method.m b/gcc/testsuite/objc.dg/gnu-api-2-method.m
index 0c4fe4f..ea1da8d 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-method.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-method.m
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-objc.m b/gcc/testsuite/objc.dg/gnu-api-2-objc.m
index 1b4ce8e..e9ec5d7 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-objc.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-objc.m
@@ -9,6 +9,7 @@
systems that don't have the V2 APis). XFAILing the run is not useful
since it will XPASS on the sub-set that works. */
/* { dg-skip-if "Incompatible" { *-*-darwin* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-objc_msg_lookup.m b/gcc/testsuite/objc.dg/gnu-api-2-objc_msg_lookup.m
index 5751f3f..d417225 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-objc_msg_lookup.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-objc_msg_lookup.m
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-object.m b/gcc/testsuite/objc.dg/gnu-api-2-object.m
index 3d4d444..20c4342 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-object.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-object.m
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-property.m b/gcc/testsuite/objc.dg/gnu-api-2-property.m
index 12c0d8b9..0ef4d79 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-property.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-property.m
@@ -4,6 +4,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-protocol.m b/gcc/testsuite/objc.dg/gnu-api-2-protocol.m
index a34d74c..682adcd 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-protocol.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-protocol.m
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-resolve-method.m b/gcc/testsuite/objc.dg/gnu-api-2-resolve-method.m
index a387709..6eaa3dd 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-resolve-method.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-resolve-method.m
@@ -5,6 +5,7 @@
/* { dg-do run } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-sel.m b/gcc/testsuite/objc.dg/gnu-api-2-sel.m
index b71fdfa..bc581be 100644
--- a/gcc/testsuite/objc.dg/gnu-api-2-sel.m
+++ b/gcc/testsuite/objc.dg/gnu-api-2-sel.m
@@ -4,6 +4,7 @@
/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* To get the modern GNU Objective-C Runtime API, you include
objc/runtime.h. */
diff --git a/gcc/testsuite/objc.dg/incomplete-type-1.m b/gcc/testsuite/objc.dg/incomplete-type-1.m
index f1e875f..60d0d8a 100644
--- a/gcc/testsuite/objc.dg/incomplete-type-1.m
+++ b/gcc/testsuite/objc.dg/incomplete-type-1.m
@@ -6,6 +6,9 @@
enum type1;
struct type2;
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyObject
- (void) method1: (enum type1)argument;
- (void) method2: (struct type2)argument;
diff --git a/gcc/testsuite/objc.dg/instancetype-0.m b/gcc/testsuite/objc.dg/instancetype-0.m
index 32cafdf..dc27926 100644
--- a/gcc/testsuite/objc.dg/instancetype-0.m
+++ b/gcc/testsuite/objc.dg/instancetype-0.m
@@ -6,6 +6,9 @@
extern id class_createInstance (id, int);
extern id class_getSuperclass (id);
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyObject
{
Class isa;
diff --git a/gcc/testsuite/objc.dg/invalid-method-2.m b/gcc/testsuite/objc.dg/invalid-method-2.m
index cb18de9..0a4bd63 100644
--- a/gcc/testsuite/objc.dg/invalid-method-2.m
+++ b/gcc/testsuite/objc.dg/invalid-method-2.m
@@ -3,6 +3,9 @@
/* Test that using an invalid type in a method declaration produces a
friendly error without a compiler crash. */
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyClass
@end
diff --git a/gcc/testsuite/objc.dg/ivar-invalid-type-1.m b/gcc/testsuite/objc.dg/ivar-invalid-type-1.m
index 3e7785d..98bf36e 100644
--- a/gcc/testsuite/objc.dg/ivar-invalid-type-1.m
+++ b/gcc/testsuite/objc.dg/ivar-invalid-type-1.m
@@ -1,6 +1,9 @@
/* { dg-do compile } */
#include <objc/objc.h>
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyRootClass
{
Class isa;
diff --git a/gcc/testsuite/objc.dg/ivar-problem-1.m b/gcc/testsuite/objc.dg/ivar-problem-1.m
index 4a87768..0d5bb66 100644
--- a/gcc/testsuite/objc.dg/ivar-problem-1.m
+++ b/gcc/testsuite/objc.dg/ivar-problem-1.m
@@ -10,6 +10,9 @@
#include <stdlib.h>
#include <objc/objc.h>
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyRootClass1
{
Class isa;
@@ -36,6 +39,9 @@
@end
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyRootClass2
{
Class isa;
diff --git a/gcc/testsuite/objc.dg/ivar-scope-1.m b/gcc/testsuite/objc.dg/ivar-scope-1.m
index 34443a4..64d275b 100644
--- a/gcc/testsuite/objc.dg/ivar-scope-1.m
+++ b/gcc/testsuite/objc.dg/ivar-scope-1.m
@@ -3,6 +3,9 @@
/* { dg-do compile } */
#include <objc/objc.h>
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyClass
{
int someivar;
diff --git a/gcc/testsuite/objc.dg/ivar-scope-2.m b/gcc/testsuite/objc.dg/ivar-scope-2.m
index ff795d0..1149d73 100644
--- a/gcc/testsuite/objc.dg/ivar-scope-2.m
+++ b/gcc/testsuite/objc.dg/ivar-scope-2.m
@@ -4,6 +4,9 @@
/* { dg-additional-options "-fno-local-ivars" } */
#include <objc/objc.h>
+#if defined(__has_attribute) && __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
@interface MyClass
{
int someivar;
diff --git a/gcc/testsuite/objc.dg/ivar-scope-4.m b/gcc/testsuite/objc.dg/ivar-scope-4.m
index 5fc29f9..df1c892 100644
--- a/gcc/testsuite/objc.dg/ivar-scope-4.m
+++ b/gcc/testsuite/objc.dg/ivar-scope-4.m
@@ -1,7 +1,8 @@
/* Test instance variable scope. */
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do run } */
-/* { dg-additional-options "-Wno-shadow-ivar -fno-local-ivars" } */
+/* { dg-additional-options "-Wno-shadow-ivar -fno-local-ivars -Wno-objc-root-class" } */
+
#include "../objc-obj-c++-shared/runtime.h"
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-1.m b/gcc/testsuite/objc.dg/ivar-visibility-1.m
index 5a22259..79d791e 100644
--- a/gcc/testsuite/objc.dg/ivar-visibility-1.m
+++ b/gcc/testsuite/objc.dg/ivar-visibility-1.m
@@ -1,6 +1,7 @@
/* Test instance variable visibility. */
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-2.m b/gcc/testsuite/objc.dg/ivar-visibility-2.m
index eb41c8f..6ddcb5b 100644
--- a/gcc/testsuite/objc.dg/ivar-visibility-2.m
+++ b/gcc/testsuite/objc.dg/ivar-visibility-2.m
@@ -1,7 +1,7 @@
/* Test instance variable visibility. */
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do compile } */
-/* { dg-additional-options "-fivar-visibility=protected" } */
+/* { dg-additional-options "-fivar-visibility=protected -Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-3.m b/gcc/testsuite/objc.dg/ivar-visibility-3.m
index ecc6f99..6403503 100644
--- a/gcc/testsuite/objc.dg/ivar-visibility-3.m
+++ b/gcc/testsuite/objc.dg/ivar-visibility-3.m
@@ -1,7 +1,7 @@
/* Test instance variable visibility. */
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do compile } */
-/* { dg-additional-options "-fivar-visibility=private" } */
+/* { dg-additional-options "-fivar-visibility=private -Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-4.m b/gcc/testsuite/objc.dg/ivar-visibility-4.m
index adfeb44..abd802b 100644
--- a/gcc/testsuite/objc.dg/ivar-visibility-4.m
+++ b/gcc/testsuite/objc.dg/ivar-visibility-4.m
@@ -1,7 +1,7 @@
/* Test instance variable visibility. */
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do compile } */
-/* { dg-additional-options "-fivar-visibility=public" } */
+/* { dg-additional-options "-fivar-visibility=public -Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/objc.dg/local-decl-1.m b/gcc/testsuite/objc.dg/local-decl-1.m
index 4a4bfdf..8356a8c 100644
--- a/gcc/testsuite/objc.dg/local-decl-1.m
+++ b/gcc/testsuite/objc.dg/local-decl-1.m
@@ -1,6 +1,7 @@
/* Test for hiding of ivars by local variables. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Sprite {
int a;
diff --git a/gcc/testsuite/objc.dg/lto/lto.exp b/gcc/testsuite/objc.dg/lto/lto.exp
index e563ecb..8a362d6 100644
--- a/gcc/testsuite/objc.dg/lto/lto.exp
+++ b/gcc/testsuite/objc.dg/lto/lto.exp
@@ -41,10 +41,10 @@ if { ![check_effective_target_lto] } {
global LTO_OPTIONS
set LTO_OPTIONS [list \
- {-O0 -flto -fgnu-runtime} \
- {-O2 -flto -fgnu-runtime} \
- {-O0 -flto -flto-partition=none -fgnu-runtime} \
- {-O2 -flto -flto-partition=none -fgnu-runtime} \
+ {-O0 -flto -fgnu-runtime -Wno-objc-root-class} \
+ {-O2 -flto -fgnu-runtime -Wno-objc-root-class } \
+ {-O0 -flto -flto-partition=none -fgnu-runtime -Wno-objc-root-class} \
+ {-O2 -flto -flto-partition=none -fgnu-runtime -Wno-objc-root-class} \
]
objc_init
@@ -67,10 +67,10 @@ foreach src $tests {
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
set LTO_OPTIONS [list \
- {-O0 -flto -fnext-runtime} \
- {-O2 -flto -fnext-runtime} \
- {-O0 -flto -flto-partition=none -fnext-runtime} \
- {-O2 -flto -flto-partition=none -fnext-runtime} \
+ {-O0 -flto -fnext-runtime -Wno-objc-root-class} \
+ {-O2 -flto -fnext-runtime -Wno-objc-root-class} \
+ {-O0 -flto -flto-partition=none -fnext-runtime -Wno-objc-root-class} \
+ {-O2 -flto -flto-partition=none -fnext-runtime -Wno-objc-root-class} \
]
foreach src $tests {
# If we're only testing specific files and this isn't one of them, skip it.
diff --git a/gcc/testsuite/objc.dg/lto/trivial-1_0.m b/gcc/testsuite/objc.dg/lto/trivial-1_0.m
index ba1b1aa..ca07fa4 100644
--- a/gcc/testsuite/objc.dg/lto/trivial-1_0.m
+++ b/gcc/testsuite/objc.dg/lto/trivial-1_0.m
@@ -1,5 +1,5 @@
/* { dg-lto-do run } */
-/* { dg-skip-if "" { "*-*-darwin*" && lp64 } } */
+
extern int printf (char *,...) ;
typedef struct objc_class *Class;
@@ -7,7 +7,7 @@ typedef struct objc_class *Class;
struct objc_class {
Class isa;
/* other stuff... */
-} ;
+};
@interface myRootObject {
@public
diff --git a/gcc/testsuite/objc.dg/method-1.m b/gcc/testsuite/objc.dg/method-1.m
index 194c64f..bd23493 100644
--- a/gcc/testsuite/objc.dg/method-1.m
+++ b/gcc/testsuite/objc.dg/method-1.m
@@ -1,5 +1,6 @@
/* Tests of duplication. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface class1
- (int) meth1; /* { dg-message "previous declaration" } */
diff --git a/gcc/testsuite/objc.dg/method-12.m b/gcc/testsuite/objc.dg/method-12.m
index 411caac..b69a84f 100644
--- a/gcc/testsuite/objc.dg/method-12.m
+++ b/gcc/testsuite/objc.dg/method-12.m
@@ -1,5 +1,6 @@
/* Contributed by Igor Seleznev <selez@mail.ru>. */
/* This used to be broken. */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/method-13.m b/gcc/testsuite/objc.dg/method-13.m
index 592038b..3e0fde5 100644
--- a/gcc/testsuite/objc.dg/method-13.m
+++ b/gcc/testsuite/objc.dg/method-13.m
@@ -4,6 +4,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include "../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/objc.dg/method-14.m b/gcc/testsuite/objc.dg/method-14.m
index 9698225..bc3ee12 100644
--- a/gcc/testsuite/objc.dg/method-14.m
+++ b/gcc/testsuite/objc.dg/method-14.m
@@ -2,6 +2,7 @@
used as method selectors. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Foo
- (void)insertNewButtonImage:(Foo *)newButtonImage in:(Foo *)buttonCell;
diff --git a/gcc/testsuite/objc.dg/missing-proto-3.m b/gcc/testsuite/objc.dg/missing-proto-3.m
index 05e1a25..77aa3a3 100644
--- a/gcc/testsuite/objc.dg/missing-proto-3.m
+++ b/gcc/testsuite/objc.dg/missing-proto-3.m
@@ -2,7 +2,8 @@
In addition to not crashing :-), the compiler should properly handle
valid protocol references, even when they're mixed with invalid ones. */
/* { dg-do compile } */
-
+/* { dg-additional-options "-Wno-objc-root-class" } */
+
#include <objc/objc.h>
@protocol DefinedProtocol
diff --git a/gcc/testsuite/objc.dg/next-runtime-1.m b/gcc/testsuite/objc.dg/next-runtime-1.m
index c76b616..2ce798b 100644
--- a/gcc/testsuite/objc.dg/next-runtime-1.m
+++ b/gcc/testsuite/objc.dg/next-runtime-1.m
@@ -7,6 +7,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-skip-if "" { *-*-* } { "-fobjc-abi-version=1" } { "" } } */
/* { dg-options "-fobjc-abi-version=0" { target { *-*-darwin* && { ! lp64 } } } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface FooBar
- (void)boo;
diff --git a/gcc/testsuite/objc.dg/objc-foreach-1.m b/gcc/testsuite/objc.dg/objc-foreach-1.m
index 81f5dae..e4c958c 100644
--- a/gcc/testsuite/objc.dg/objc-foreach-1.m
+++ b/gcc/testsuite/objc.dg/objc-foreach-1.m
@@ -1,5 +1,6 @@
/* Syntax check for the new foreach statement. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_class *Class;
diff --git a/gcc/testsuite/objc.dg/objc-foreach-2.m b/gcc/testsuite/objc.dg/objc-foreach-2.m
index a01f004..0f79089 100644
--- a/gcc/testsuite/objc.dg/objc-foreach-2.m
+++ b/gcc/testsuite/objc.dg/objc-foreach-2.m
@@ -1,5 +1,6 @@
/* Syntax check for the new foreach statement. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_class *Class;
diff --git a/gcc/testsuite/objc.dg/objc-foreach-3.m b/gcc/testsuite/objc.dg/objc-foreach-3.m
index 922db39..b551ae3 100644
--- a/gcc/testsuite/objc.dg/objc-foreach-3.m
+++ b/gcc/testsuite/objc.dg/objc-foreach-3.m
@@ -1,6 +1,7 @@
/* Syntax check for the new foreach statement.
Use of declaration in loop-header without requiring c99 mode. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_class *Class;
diff --git a/gcc/testsuite/objc.dg/objc-nofilename-1.m b/gcc/testsuite/objc.dg/objc-nofilename-1.m
index 21e0c53..3ddaa64 100644
--- a/gcc/testsuite/objc.dg/objc-nofilename-1.m
+++ b/gcc/testsuite/objc.dg/objc-nofilename-1.m
@@ -1,5 +1,6 @@
/* Test to make sure that file name does not appear in the binary. */
/* { dg-do compile { target *-*-darwin* } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/param-1.m b/gcc/testsuite/objc.dg/param-1.m
index 9dbf6e3..8e77811 100644
--- a/gcc/testsuite/objc.dg/param-1.m
+++ b/gcc/testsuite/objc.dg/param-1.m
@@ -1,6 +1,7 @@
/* Test if compiler detects object as an parameter to a method
or not. It is not valid. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface foo
@end
diff --git a/gcc/testsuite/objc.dg/pch/pch.exp b/gcc/testsuite/objc.dg/pch/pch.exp
index 2da3d96..54c3e42 100644
--- a/gcc/testsuite/objc.dg/pch/pch.exp
+++ b/gcc/testsuite/objc.dg/pch/pch.exp
@@ -41,7 +41,7 @@ foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.m]] {
# unlikely to make any difference to PCH. However, we do want to
# add -O0 -g, since users who want PCH usually want debugging and quick
# compiles.
- dg-flags-pch $subdir $test "-fgnu-runtime" $mytorture ".h"
+ dg-flags-pch $subdir $test "-fgnu-runtime -Wno-objc-root-class" $mytorture ".h"
}
if [istarget "*-*-darwin*" ] {
@@ -52,7 +52,7 @@ if [istarget "*-*-darwin*" ] {
# unlikely to make any difference to PCH. However, we do want to
# add -O0 -g, since users who want PCH usually want debugging and quick
# compiles.
- dg-flags-pch $subdir $test "-fnext-runtime" $mytorture ".h"
+ dg-flags-pch $subdir $test "-fnext-runtime -Wno-objc-root-class" $mytorture ".h"
}
}
diff --git a/gcc/testsuite/objc.dg/plugin/diagnostic-test-expressions-1.m b/gcc/testsuite/objc.dg/plugin/diagnostic-test-expressions-1.m
index 23a9302..7070b37 100644
--- a/gcc/testsuite/objc.dg/plugin/diagnostic-test-expressions-1.m
+++ b/gcc/testsuite/objc.dg/plugin/diagnostic-test-expressions-1.m
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdiagnostics-show-caret" } */
+/* { dg-options "-O -fdiagnostics-show-caret -Wno-objc-root-class" } */
/* This file is similar to diagnostic-test-expressions-1.c
(see the notes in that file); this file adds test
diff --git a/gcc/testsuite/objc.dg/pr23214.m b/gcc/testsuite/objc.dg/pr23214.m
index 341a283..56cdc02 100644
--- a/gcc/testsuite/objc.dg/pr23214.m
+++ b/gcc/testsuite/objc.dg/pr23214.m
@@ -7,7 +7,7 @@
#if defined (__NEXT_RUNTIME__) && defined(__OBJC2__) \
&& defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \
- && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070
+ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1080
#include <objc/Protocol.h>
#define OBJECT NSObject
#else
diff --git a/gcc/testsuite/objc.dg/pr23709.m b/gcc/testsuite/objc.dg/pr23709.m
index 7ff9b60..2bdcca5 100644
--- a/gcc/testsuite/objc.dg/pr23709.m
+++ b/gcc/testsuite/objc.dg/pr23709.m
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface A
+(void)method: (int)parameter {} /* { dg-error "expected" } */
diff --git a/gcc/testsuite/objc.dg/private-1.m b/gcc/testsuite/objc.dg/private-1.m
index 7540fc5..5bd29e5 100644
--- a/gcc/testsuite/objc.dg/private-1.m
+++ b/gcc/testsuite/objc.dg/private-1.m
@@ -1,6 +1,7 @@
/* Test errors for accessing @private and @protected variables. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/objc.dg/private-2.m b/gcc/testsuite/objc.dg/private-2.m
index eff376a..d0646f5 100644
--- a/gcc/testsuite/objc.dg/private-2.m
+++ b/gcc/testsuite/objc.dg/private-2.m
@@ -1,6 +1,7 @@
/* Test warnings for shadowing instance variables. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MySuperClass
diff --git a/gcc/testsuite/objc.dg/property/at-property-1.m b/gcc/testsuite/objc.dg/property/at-property-1.m
index fa12fa2..6dba8f4 100644
--- a/gcc/testsuite/objc.dg/property/at-property-1.m
+++ b/gcc/testsuite/objc.dg/property/at-property-1.m
@@ -11,11 +11,15 @@
/* { dg-warning "declaration does not declare anything" "" { target *-*-* } .-1 } */
@property int a;
@property int b, c;
-@property () int d; /* { dg-error "expected identifier" } */
+@property () int d; /* { dg-warning "empty property attribute list" } */
@property (readonly) int e;
-@property (readonly,) int f; /* { dg-error "expected identifier" } */
+@property (readonly,) int f; /* { dg-warning "missing property attribute" } */
@property (xxx) int g; /* { dg-error "unknown property attribute" } */
@property (readonly,xxx) int h; /* { dg-error "unknown property attribute" } */
@property ( int i; /* { dg-error "unknown property attribute" } */
-/* Because the last syntax error opens a '(' and never closes it, we get to the end of input. */
-@end /* { dg-error "expected ..end. at end of input" } */
+ /* { dg-error "expected" "" { target *-*-* } .-1 } */
+@property (assign,,nonatomic) int j; /* { dg-warning "missing property attribute" } */
+@property (assign nonatomic) int k; /* { dg-error {expected } } */
+@property (assign) int l[4]; /* { dg-error {property cannot be an array} } */
+@property (assign) int : 5; /* { dg-error {properties must be named} } */
+@end
diff --git a/gcc/testsuite/objc.dg/property/at-property-29.m b/gcc/testsuite/objc.dg/property/at-property-29.m
index 0f31617..0b34e1c 100644
--- a/gcc/testsuite/objc.dg/property/at-property-29.m
+++ b/gcc/testsuite/objc.dg/property/at-property-29.m
@@ -8,7 +8,8 @@
Class isa;
}
/* Test missing '=' in setter/getter attributes. */
-@property (getter) int property_a; /* { dg-error "missing .=. .after .getter. attribute." } */
-@property (setter) int property_b; /* { dg-error "missing .=. .after .setter. attribute." } */
-@property (assign, getter) int property_c; /* { dg-error "missing .=. .after .getter. attribute." } */
+@property (getter) int property_a; /* { dg-error {expected '=' after Objective-C 'getter'} } */
+@property (setter) int property_b; /* { dg-error {expected '=' after Objective-C 'setter'} } */
+@property (assign, getter) int property_c; /* { dg-error {expected '=' after Objective-C 'getter'} } */
+@property (retain, getter=) id x; /* { dg-error {expected 'getter' selector name} } */
@end
diff --git a/gcc/testsuite/objc.dg/property/at-property-4.m b/gcc/testsuite/objc.dg/property/at-property-4.m
index 941aab8..04da34e 100644
--- a/gcc/testsuite/objc.dg/property/at-property-4.m
+++ b/gcc/testsuite/objc.dg/property/at-property-4.m
@@ -14,27 +14,53 @@
- (void) mySetter2: (int)property;
/* Test that all the new property attributes can be parsed. */
-@property (assign) id property_a;
-@property (copy) id property_b;
-@property (nonatomic) int property_c;
-@property (readonly) int property_d;
-@property (readwrite) int property_e;
-@property (retain) id property_f;
-@property (release) int property_g; /* { dg-error "unknown property attribute" } */
+@property (assign) id property_as_1;
+@property (copy) id property_as_2;
+@property (retain) id property_as_3;
+
+@property (atomic) int property_at_1;
+@property (nonatomic) int property_at_2;
+
+@property (readonly) int property_rw_1;
+@property (readwrite) int property_rw_2;
+
+@property (class) int property_cl_1;
+
+@property (null_unspecified) int *property_null_1;
+@property (nullable) int *property_null_2;
+@property (nonnull) int *property_null_3;
+@property (null_resettable) int *property_null_4;
+
+@property (release) int property_err_1; /* { dg-error "unknown property attribute" } */
@property (getter=myGetter) int property_h;
@property (setter=mySetter:) int property_i;
/* Now test various problems. */
-@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
+@property (readonly, readwrite) int a; /* { dg-error ".readwrite. attribute conflicts with .readonly. attribute" } */
@property (readonly, setter=mySetterB:) int b; /* { dg-error ".readonly. attribute conflicts with .setter. attribute" } */
-@property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
-@property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
+@property (assign, retain) id c; /* { dg-error ".retain. attribute conflicts with .assign. attribute" } */
+@property (assign, copy) id d; /* { dg-error ".copy. attribute conflicts with .assign. attribute" } */
@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
-@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-error ".setter. attribute may only be specified once" } */
-@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-error ".getter. attribute may only be specified once" } */
+@property (atomic, nonatomic) int property_j; /* { dg-error {'nonatomic' attribute conflicts with 'atomic' attribute} } */
+
+@property (null_unspecified) int property_bad_t_1; /* { dg-error {nullability specifier 'null_unspecified' cannot be applied to non-pointer type 'int'} } */
+@property (nullable) int property_bad_t_2;/* { dg-error {nullability specifier 'nullable' cannot be applied to non-pointer type 'int'} } */
+@property (nonnull) int property_bad_t_3;/* { dg-error {nullability specifier 'nonnull' cannot be applied to non-pointer type 'int'} } */
+@property (null_resettable) int property_bad_t_4;/* { dg-error {nullability specifier 'null_resettable' cannot be applied to non-pointer type 'int'} } */
+@property (nullable) int **property_bad_t_5;/* { dg-error {nullability specifier 'nullable' cannot be applied to multi-level pointer type 'int \*\*'} } */
+
+@property (null_unspecified, nullable) int *property_ne_1; /* { dg-error {'nullable' attribute conflicts with 'null_unspecified' attribute} } */
+@property (null_unspecified, nonnull) int *property_ne_2; /* { dg-error {'nonnull' attribute conflicts with 'null_unspecified' attribute} } */
+@property (null_unspecified, null_resettable) int *property_ne_3; /* { dg-error {'null_resettable' attribute conflicts with 'null_unspecified' attribute} } */
+@property (nullable,nonnull) int *property_ne_4; /* { dg-error {'nonnull' attribute conflicts with 'nullable' attribute} } */
+@property (nullable,null_resettable) int *property_ne_5; /* { dg-error {'null_resettable' attribute conflicts with 'nullable' attribute} } */
+@property (nonnull, null_resettable) int *property_ne_6; /* { dg-error {'null_resettable' attribute conflicts with 'nonnull' attribute} } */
+
+@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-warning {multiple property 'setter' methods specified, the latest one will be used} } */
+@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-warning {multiple property 'getter' methods specified, the latest one will be used} } */
@end
diff --git a/gcc/testsuite/objc.dg/property/at-property-5.m b/gcc/testsuite/objc.dg/property/at-property-5.m
index 1267df3..820f5b3 100644
--- a/gcc/testsuite/objc.dg/property/at-property-5.m
+++ b/gcc/testsuite/objc.dg/property/at-property-5.m
@@ -31,4 +31,4 @@
/* { dg-message "originally specified here" "" { target *-*-* } property_e_first } */
@end
-@property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */
+@property id test; /* { dg-error {property declaration not in '@interface', '@protocol' or 'category' context} } */
diff --git a/gcc/testsuite/objc.dg/property/nullability-00.m b/gcc/testsuite/objc.dg/property/nullability-00.m
new file mode 100644
index 0000000..9b0c808
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/nullability-00.m
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fsyntax-only" } */
+
+@interface MyRoot
+{
+ Class isa __attribute__((deprecated));
+ id p;
+ int x;
+ int *i;
+}
+
+@property(null_unspecified, assign) MyRoot *p1;
+@property(nonnull, assign) MyRoot *p2;
+@property(nullable, assign) MyRoot *p3;
+@property(null_resettable, assign) MyRoot *p4;
+@property(null_exciting, assign) MyRoot *e_5; /* { dg-error {unknown property attribute 'null_exciting'} } */
+
+@property(nonnull, retain, nullable) MyRoot *e_6; /* { dg-error {'nullable' attribute conflicts with 'nonnull' attribute} } */
+@property(nonnull, nonnull) int *i; /* { dg-warning {duplicate 'nonnull' attribute} } */
+
+@end
diff --git a/gcc/testsuite/objc.dg/property/property-neg-2.m b/gcc/testsuite/objc.dg/property/property-neg-2.m
index f730fe8..794f2bd 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-2.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-2.m
@@ -4,5 +4,5 @@
@end
@implementation Bar
-@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */
+@property int FooBar; /* { dg-error {property declaration not in '@interface', '@protocol' or 'category' context} } */
@end
diff --git a/gcc/testsuite/objc.dg/property/property.exp b/gcc/testsuite/objc.dg/property/property.exp
index 47ffcdf..1c203db 100644
--- a/gcc/testsuite/objc.dg/property/property.exp
+++ b/gcc/testsuite/objc.dg/property/property.exp
@@ -31,12 +31,12 @@ dg-init
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.m]]
# Main loop.
-dg-runtest $tests "-fgnu-runtime" $DEFAULT_CFLAGS
+dg-runtest $tests "-fgnu-runtime -Wno-objc-root-class" $DEFAULT_CFLAGS
# Darwin targets can also run code with the NeXT runtime.
# but Properties are not supported by the runtime lib before Darwin 9.
if [istarget "*-*-darwin\[9123\]*" ] {
- dg-runtest $tests "-fnext-runtime" $DEFAULT_CFLAGS
+ dg-runtest $tests "-fnext-runtime -Wno-objc-root-class" $DEFAULT_CFLAGS
}
# All done.
diff --git a/gcc/testsuite/objc.dg/proto-hier-1.m b/gcc/testsuite/objc.dg/proto-hier-1.m
index 0f409fc..648a4d4 100644
--- a/gcc/testsuite/objc.dg/proto-hier-1.m
+++ b/gcc/testsuite/objc.dg/proto-hier-1.m
@@ -1,6 +1,7 @@
/* Test for handling of protocol hierarchies. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* One-line substitute for objc/objc.h */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
diff --git a/gcc/testsuite/objc.dg/proto-hier-2.m b/gcc/testsuite/objc.dg/proto-hier-2.m
index 819cf4a..6b3f803 100644
--- a/gcc/testsuite/objc.dg/proto-hier-2.m
+++ b/gcc/testsuite/objc.dg/proto-hier-2.m
@@ -1,6 +1,7 @@
/* Test protocol warning. */
/* Contributed by Devang Patel <dpatel@apple.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
diff --git a/gcc/testsuite/objc.dg/proto-lossage-1.m b/gcc/testsuite/objc.dg/proto-lossage-1.m
index 2f7eb98..4564a94 100644
--- a/gcc/testsuite/objc.dg/proto-lossage-1.m
+++ b/gcc/testsuite/objc.dg/proto-lossage-1.m
@@ -2,6 +2,7 @@
may be lost, leading to superfluous warnings. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* One-line substitute for objc/objc.h */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
diff --git a/gcc/testsuite/objc.dg/proto-lossage-5.m b/gcc/testsuite/objc.dg/proto-lossage-5.m
index 35c0956..a18b357 100644
--- a/gcc/testsuite/objc.dg/proto-lossage-5.m
+++ b/gcc/testsuite/objc.dg/proto-lossage-5.m
@@ -1,5 +1,6 @@
/* Do not lose references to forward-declared protocols. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@class MyBaseClass;
@class MyClassThatFails;
@protocol _MyProtocol;
diff --git a/gcc/testsuite/objc.dg/proto-qual-1.m b/gcc/testsuite/objc.dg/proto-qual-1.m
index 40eb0f9..6e90872 100644
--- a/gcc/testsuite/objc.dg/proto-qual-1.m
+++ b/gcc/testsuite/objc.dg/proto-qual-1.m
@@ -3,6 +3,7 @@
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include "../objc-obj-c++-shared/runtime.h"
#include <objc/Protocol.h>
diff --git a/gcc/testsuite/objc.dg/protocol-inheritance-1.m b/gcc/testsuite/objc.dg/protocol-inheritance-1.m
index 5241b29..5367a98 100644
--- a/gcc/testsuite/objc.dg/protocol-inheritance-1.m
+++ b/gcc/testsuite/objc.dg/protocol-inheritance-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* { dg-options "-Wno-protocol" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/protocol-inheritance-2.m b/gcc/testsuite/objc.dg/protocol-inheritance-2.m
index 74c9174..9776a40 100644
--- a/gcc/testsuite/objc.dg/protocol-inheritance-2.m
+++ b/gcc/testsuite/objc.dg/protocol-inheritance-2.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/protocol-optional-1.m b/gcc/testsuite/objc.dg/protocol-optional-1.m
index bc4a3d0..29fe72e 100644
--- a/gcc/testsuite/objc.dg/protocol-optional-1.m
+++ b/gcc/testsuite/objc.dg/protocol-optional-1.m
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/root-class-00.m b/gcc/testsuite/objc.dg/root-class-00.m
new file mode 100644
index 0000000..1f73f73
--- /dev/null
+++ b/gcc/testsuite/objc.dg/root-class-00.m
@@ -0,0 +1,10 @@
+/* Test Wobjc-root-class.
+ Note that we don't issue a warning unless the TU contains an implementation
+ for the class. */
+/* { dg-additional-options "-fsyntax-only " } */
+
+@interface ARootObject
+@end
+
+@implementation ARootObject
+@end /* { dg-warning {class 'ARootObject' defined without specifying a base class} } */
diff --git a/gcc/testsuite/objc.dg/selector-1.m b/gcc/testsuite/objc.dg/selector-1.m
index f0781b6..5ff15a2 100644
--- a/gcc/testsuite/objc.dg/selector-1.m
+++ b/gcc/testsuite/objc.dg/selector-1.m
@@ -3,6 +3,7 @@
/* { dg-options "-Wselector" } */
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
typedef struct objc_selector *SEL;
diff --git a/gcc/testsuite/objc.dg/selector-2.m b/gcc/testsuite/objc.dg/selector-2.m
index 6cad2ff..5042104 100644
--- a/gcc/testsuite/objc.dg/selector-2.m
+++ b/gcc/testsuite/objc.dg/selector-2.m
@@ -1,6 +1,7 @@
/* Test that we don't ICE when issuing a -Wselector warning. */
/* { dg-options "-Wselector" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/selector-3.m b/gcc/testsuite/objc.dg/selector-3.m
index c0c5f3d..94838cd3 100644
--- a/gcc/testsuite/objc.dg/selector-3.m
+++ b/gcc/testsuite/objc.dg/selector-3.m
@@ -3,6 +3,7 @@
/* { dg-options "-Wselector" } */
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { struct objc_class *class_pointer; } *id;
typedef const struct objc_selector *SEL;
diff --git a/gcc/testsuite/objc.dg/selector-4.m b/gcc/testsuite/objc.dg/selector-4.m
index d34f8c8..2a4947e 100644
--- a/gcc/testsuite/objc.dg/selector-4.m
+++ b/gcc/testsuite/objc.dg/selector-4.m
@@ -3,6 +3,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Int1
+ (int)and_eq:(int)arg1 and:(int)arg2;
diff --git a/gcc/testsuite/objc.dg/shadow-1.m b/gcc/testsuite/objc.dg/shadow-1.m
index 739a0d0..d18fd6e 100644
--- a/gcc/testsuite/objc.dg/shadow-1.m
+++ b/gcc/testsuite/objc.dg/shadow-1.m
@@ -2,6 +2,7 @@
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do compile } */
/* { dg-additional-options "-Wno-shadow-ivar" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MyClass
diff --git a/gcc/testsuite/objc.dg/shadow-2.m b/gcc/testsuite/objc.dg/shadow-2.m
index 16261b9..26447fe 100644
--- a/gcc/testsuite/objc.dg/shadow-2.m
+++ b/gcc/testsuite/objc.dg/shadow-2.m
@@ -2,6 +2,7 @@
/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
/* { dg-do compile } */
/* { dg-additional-options "-Wno-shadow" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
@interface MyClass
diff --git a/gcc/testsuite/objc.dg/special/load-category-1.m b/gcc/testsuite/objc.dg/special/load-category-1.m
index cb22143..b72d070 100644
--- a/gcc/testsuite/objc.dg/special/load-category-1.m
+++ b/gcc/testsuite/objc.dg/special/load-category-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <stdlib.h>
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/special/load-category-2.m b/gcc/testsuite/objc.dg/special/load-category-2.m
index 7dc74595..2706351 100644
--- a/gcc/testsuite/objc.dg/special/load-category-2.m
+++ b/gcc/testsuite/objc.dg/special/load-category-2.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <stdio.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/objc.dg/special/load-category-3.m b/gcc/testsuite/objc.dg/special/load-category-3.m
index b89d8f1..215e463 100644
--- a/gcc/testsuite/objc.dg/special/load-category-3.m
+++ b/gcc/testsuite/objc.dg/special/load-category-3.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* This test is identical to load-category-2, but the classes and
categories are created in inverted order in the modules, to test
diff --git a/gcc/testsuite/objc.dg/special/special.exp b/gcc/testsuite/objc.dg/special/special.exp
index d770e2a..f561d38 100644
--- a/gcc/testsuite/objc.dg/special/special.exp
+++ b/gcc/testsuite/objc.dg/special/special.exp
@@ -39,6 +39,7 @@ dg-init
# for all systems we point to the libobjc includes and use the -fgnu-runtime
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
lappend add_flags "additional_flags=-fgnu-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/unclaimed-category-1a.m" "unclaimed-category-1a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "unclaimed-category-1a.o"
@@ -50,6 +51,7 @@ if ![string match "" $lines] then {
if [istarget "*-*-darwin*" ] {
set add_flags ""
lappend add_flags "additional_flags=-fnext-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/unclaimed-category-1a.m" "unclaimed-category-1a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "unclaimed-category-1a.o"
@@ -66,6 +68,7 @@ if ![string match "" $lines] then {
# and load-category-1a.m, link them together, and execute the result.
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
lappend add_flags "additional_flags=-fgnu-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/load-category-1a.m" "load-category-1a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-1a.o"
@@ -77,6 +80,7 @@ if ![string match "" $lines] then {
if [istarget "*-*-darwin*" ] {
set add_flags ""
lappend add_flags "additional_flags=-fnext-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/load-category-1a.m" "load-category-1a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-1a.o"
@@ -93,6 +97,7 @@ if ![string match "" $lines] then {
# and load-category-2a.m, link them together, and execute the result.
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
lappend add_flags "additional_flags=-fgnu-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/load-category-2a.m" "load-category-2a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-2a.o"
@@ -104,6 +109,7 @@ if ![string match "" $lines] then {
if [istarget "*-*-darwin*" ] {
set add_flags ""
lappend add_flags "additional_flags=-fnext-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/load-category-2a.m" "load-category-2a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-2a.o"
@@ -120,6 +126,7 @@ if ![string match "" $lines] then {
# and load-category-3a.m, link them together, and execute the result.
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
lappend add_flags "additional_flags=-fgnu-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/load-category-3a.m" "load-category-3a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-3a.o"
@@ -131,6 +138,7 @@ if ![string match "" $lines] then {
if [istarget "*-*-darwin*" ] {
set add_flags ""
lappend add_flags "additional_flags=-fnext-runtime"
+lappend add_flags "additional_flags=-Wno-objc-root-class"
set lines [objc_target_compile "$srcdir/$subdir/load-category-3a.m" "load-category-3a.o" object $add_flags ]
if ![string match "" $lines] then {
fail "load-category-3a.o"
diff --git a/gcc/testsuite/objc.dg/special/unclaimed-category-1.h b/gcc/testsuite/objc.dg/special/unclaimed-category-1.h
index a32024d..cb5812e 100644
--- a/gcc/testsuite/objc.dg/special/unclaimed-category-1.h
+++ b/gcc/testsuite/objc.dg/special/unclaimed-category-1.h
@@ -1,4 +1,5 @@
/* Contributed by Nicola Pero - Fri Dec 14 08:36:00 GMT 2001 */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test loading unclaimed categories - categories of a class defined
separately from the class itself. */
diff --git a/gcc/testsuite/objc.dg/special/unclaimed-category-1.m b/gcc/testsuite/objc.dg/special/unclaimed-category-1.m
index 7b434b4..a8e422d 100644
--- a/gcc/testsuite/objc.dg/special/unclaimed-category-1.m
+++ b/gcc/testsuite/objc.dg/special/unclaimed-category-1.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero - Fri Dec 14 08:36:00 GMT 2001 */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
#include "../../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/objc.dg/stabs-1.m b/gcc/testsuite/objc.dg/stabs-1.m
index 452993e..b97e4d6 100644
--- a/gcc/testsuite/objc.dg/stabs-1.m
+++ b/gcc/testsuite/objc.dg/stabs-1.m
@@ -3,6 +3,7 @@
/* { dg-do compile { target stabs } } */
/* { dg-options "-gstabs" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface MyClass
+ newWithArg: arg;
diff --git a/gcc/testsuite/objc.dg/strings/strings.exp b/gcc/testsuite/objc.dg/strings/strings.exp
index 41da5cb..6042d3c 100644
--- a/gcc/testsuite/objc.dg/strings/strings.exp
+++ b/gcc/testsuite/objc.dg/strings/strings.exp
@@ -35,11 +35,11 @@ dg-init
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.m]]
# Main loop.
-dg-runtest $tests "-fgnu-runtime" $DEFAULT_CFLAGS
+dg-runtest $tests "-fgnu-runtime -Wno-objc-root-class" $DEFAULT_CFLAGS
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
- dg-runtest $tests "-fnext-runtime" $DEFAULT_CFLAGS
+ dg-runtest $tests "-fnext-runtime -Wno-objc-root-class" $DEFAULT_CFLAGS
}
# All done.
diff --git a/gcc/testsuite/objc.dg/stubify-1.m b/gcc/testsuite/objc.dg/stubify-1.m
index 641595c..4043492 100644
--- a/gcc/testsuite/objc.dg/stubify-1.m
+++ b/gcc/testsuite/objc.dg/stubify-1.m
@@ -5,6 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-Os -mdynamic-no-pic -mmacosx-version-min=10.4 -msymbol-stubs" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { } *id ;
int x = 41 ;
diff --git a/gcc/testsuite/objc.dg/stubify-2.m b/gcc/testsuite/objc.dg/stubify-2.m
index 904ac44..3e9097e 100644
--- a/gcc/testsuite/objc.dg/stubify-2.m
+++ b/gcc/testsuite/objc.dg/stubify-2.m
@@ -5,6 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump -mmacosx-version-min=10.4 -msymbol-stubs" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { } *id ;
int x = 41 ;
diff --git a/gcc/testsuite/objc.dg/super-class-2.m b/gcc/testsuite/objc.dg/super-class-2.m
index 144ea81..63792fd 100644
--- a/gcc/testsuite/objc.dg/super-class-2.m
+++ b/gcc/testsuite/objc.dg/super-class-2.m
@@ -1,6 +1,7 @@
/* Test calling super from within a category class method. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct objc_object { struct objc_class *isa; } *id;
diff --git a/gcc/testsuite/objc.dg/super-dealloc-1.m b/gcc/testsuite/objc.dg/super-dealloc-1.m
index 0ab177b..035de05 100644
--- a/gcc/testsuite/objc.dg/super-dealloc-1.m
+++ b/gcc/testsuite/objc.dg/super-dealloc-1.m
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Foo {
void *isa;
diff --git a/gcc/testsuite/objc.dg/super-dealloc-2.m b/gcc/testsuite/objc.dg/super-dealloc-2.m
index 80dcf49..5d588c5 100644
--- a/gcc/testsuite/objc.dg/super-dealloc-2.m
+++ b/gcc/testsuite/objc.dg/super-dealloc-2.m
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Foo {
void *isa;
diff --git a/gcc/testsuite/objc.dg/sync-3.m b/gcc/testsuite/objc.dg/sync-3.m
index 5cee890..6ef72a1 100644
--- a/gcc/testsuite/objc.dg/sync-3.m
+++ b/gcc/testsuite/objc.dg/sync-3.m
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
/* Test that the compiler is checking the argument of @synchronized(),
and produce errors when invalid types are used. */
diff --git a/gcc/testsuite/objc.dg/threedotthree-abi-1.m b/gcc/testsuite/objc.dg/threedotthree-abi-1.m
index 53154d3..8c22850 100644
--- a/gcc/testsuite/objc.dg/threedotthree-abi-1.m
+++ b/gcc/testsuite/objc.dg/threedotthree-abi-1.m
@@ -3,6 +3,7 @@
/* { dg-do run { target *-*-darwin* } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <stdio.h>
#include <string.h>
diff --git a/gcc/testsuite/objc.dg/torture/dg-torture.exp b/gcc/testsuite/objc.dg/torture/dg-torture.exp
index 28c2359..11f50fc 100644
--- a/gcc/testsuite/objc.dg/torture/dg-torture.exp
+++ b/gcc/testsuite/objc.dg/torture/dg-torture.exp
@@ -7,11 +7,11 @@ dg-init
# Gather a list of all tests.
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.m]]
-objc-dg-runtest $tests "" "-fgnu-runtime"
+objc-dg-runtest $tests "" "-fgnu-runtime -Wno-objc-root-class"
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
- objc-dg-runtest $tests "" "-fnext-runtime"
+ objc-dg-runtest $tests "" "-fnext-runtime -Wno-objc-root-class"
}
dg-finish
diff --git a/gcc/testsuite/objc.dg/torture/strings/strings.exp b/gcc/testsuite/objc.dg/torture/strings/strings.exp
index 64e53c6..3e2b3b0 100644
--- a/gcc/testsuite/objc.dg/torture/strings/strings.exp
+++ b/gcc/testsuite/objc.dg/torture/strings/strings.exp
@@ -24,11 +24,11 @@ dg-init
# Gather a list of all tests.
set tests [lsort [glob -nocomplain $srcdir/$subdir/*.m]]
-objc-dg-runtest $tests "" "-fgnu-runtime"
+objc-dg-runtest $tests "" "-fgnu-runtime -Wno-objc-root-class"
# Darwin targets also test with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
- objc-dg-runtest $tests "" "-fnext-runtime"
+ objc-dg-runtest $tests "" "-fnext-runtime -Wno-objc-root-class"
}
dg-finish
diff --git a/gcc/testsuite/objc.dg/try-catch-11.m b/gcc/testsuite/objc.dg/try-catch-11.m
index e08f321..c792c83 100644
--- a/gcc/testsuite/objc.dg/try-catch-11.m
+++ b/gcc/testsuite/objc.dg/try-catch-11.m
@@ -4,6 +4,7 @@
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef volatile int IOSharedLockData;
diff --git a/gcc/testsuite/objc.dg/try-catch-12.m b/gcc/testsuite/objc.dg/try-catch-12.m
index ce26b32..6c9afc2 100644
--- a/gcc/testsuite/objc.dg/try-catch-12.m
+++ b/gcc/testsuite/objc.dg/try-catch-12.m
@@ -4,6 +4,7 @@
/* { dg-options "-fobjc-exceptions" } */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface TestMyTests
- (void) testSpoon;
diff --git a/gcc/testsuite/objc.dg/type-size-2.m b/gcc/testsuite/objc.dg/type-size-2.m
index d02a8af..64444cfe 100644
--- a/gcc/testsuite/objc.dg/type-size-2.m
+++ b/gcc/testsuite/objc.dg/type-size-2.m
@@ -4,6 +4,7 @@
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include "../objc-obj-c++-shared/runtime.h"
#include <stdio.h>
diff --git a/gcc/testsuite/objc.dg/type-size-3.m b/gcc/testsuite/objc.dg/type-size-3.m
index bc66b0b..3f65516 100644
--- a/gcc/testsuite/objc.dg/type-size-3.m
+++ b/gcc/testsuite/objc.dg/type-size-3.m
@@ -1,6 +1,7 @@
/* Reject ivars that use flexible array members. */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com> */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct
{
diff --git a/gcc/testsuite/objc.dg/type-size-4.m b/gcc/testsuite/objc.dg/type-size-4.m
index 7e26da3..f10ed5b 100644
--- a/gcc/testsuite/objc.dg/type-size-4.m
+++ b/gcc/testsuite/objc.dg/type-size-4.m
@@ -2,6 +2,7 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com> */
/* PR objc/47832 */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct
{
diff --git a/gcc/testsuite/objc.dg/type-size-5.m b/gcc/testsuite/objc.dg/type-size-5.m
index d89af32..e1b11f7 100644
--- a/gcc/testsuite/objc.dg/type-size-5.m
+++ b/gcc/testsuite/objc.dg/type-size-5.m
@@ -1,6 +1,7 @@
/* Reject ivars that use flexible array members. */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com> */
/* { dg-do compile } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
typedef struct
{
diff --git a/gcc/testsuite/objc.dg/undeclared-selector.m b/gcc/testsuite/objc.dg/undeclared-selector.m
index 1cfc6c8..389b032 100644
--- a/gcc/testsuite/objc.dg/undeclared-selector.m
+++ b/gcc/testsuite/objc.dg/undeclared-selector.m
@@ -2,6 +2,7 @@
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
/* { dg-options "-Wundeclared-selector" } */
+/* { dg-additional-options "-Wno-objc-root-class" } */
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/volatile-1.m b/gcc/testsuite/objc.dg/volatile-1.m
index 8b5381a..a713631 100644
--- a/gcc/testsuite/objc.dg/volatile-1.m
+++ b/gcc/testsuite/objc.dg/volatile-1.m
@@ -1,7 +1,8 @@
/* Test for proper handling of volatile parameters in ObjC methods. */
+/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* Contributed by Ziemowit Laski <zlaski@apple.com> */
+/* { dg-additional-options "-Wno-objc-root-class" } */
@interface Test
-(void) test2: (volatile int) a;
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 08c21c0..1f85e2d 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -145,6 +145,9 @@ DEFTIMEVAR (TV_CONSTEXPR , "constant expression evaluation")
DEFTIMEVAR (TV_CONSTRAINT_NORM , "constraint normalization")
DEFTIMEVAR (TV_CONSTRAINT_SAT , "constraint satisfaction")
DEFTIMEVAR (TV_CONSTRAINT_SUB , "constraint subsumption")
+DEFTIMEVAR (TV_MODULE_IMPORT , "module import")
+DEFTIMEVAR (TV_MODULE_EXPORT , "module export")
+DEFTIMEVAR (TV_MODULE_MAPPER , "module mapper")
DEFTIMEVAR (TV_FLATTEN_INLINING , "flatten inlining")
DEFTIMEVAR (TV_EARLY_INLINING , "early inlining heuristics")
DEFTIMEVAR (TV_INLINE_PARAMETERS , "inline parameters")
@@ -194,6 +197,7 @@ DEFTIMEVAR (TV_TREE_LOOP_UNSWITCH , "tree loop unswitching")
DEFTIMEVAR (TV_LOOP_SPLIT , "loop splitting")
DEFTIMEVAR (TV_LOOP_JAM , "unroll and jam")
DEFTIMEVAR (TV_COMPLETE_UNROLL , "complete unrolling")
+DEFTIMEVAR (TV_SCALAR_CLEANUP , "scalar cleanup")
DEFTIMEVAR (TV_TREE_PARALLELIZE_LOOPS, "tree parallelize loops")
DEFTIMEVAR (TV_TREE_VECTORIZATION , "tree vectorization")
DEFTIMEVAR (TV_TREE_SLP_VECTORIZATION, "tree slp vectorization")
@@ -292,6 +296,7 @@ DEFTIMEVAR (TV_VAR_TRACKING , "variable tracking")
DEFTIMEVAR (TV_VAR_TRACKING_DATAFLOW , "var-tracking dataflow")
DEFTIMEVAR (TV_VAR_TRACKING_EMIT , "var-tracking emit")
DEFTIMEVAR (TV_TREE_IFCOMBINE , "tree if-combine")
+DEFTIMEVAR (TV_TREE_IF_TO_SWITCH , "if to switch conversion")
DEFTIMEVAR (TV_TREE_UNINIT , "uninit var analysis")
DEFTIMEVAR (TV_PLUGIN_INIT , "plugin initialization")
DEFTIMEVAR (TV_PLUGIN_RUN , "plugin execution")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 20e231f..93a4194 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -116,9 +116,6 @@ static void compile_file (void);
/* True if we don't need a backend (e.g. preprocessing only). */
static bool no_backend;
-/* Length of line when printing switch values. */
-#define MAX_LINE 75
-
/* Decoded options, and number of such options. */
struct cl_decoded_option *save_decoded_options;
unsigned int save_decoded_options_count;
@@ -512,6 +509,9 @@ compile_file (void)
if (flag_sanitize & SANITIZE_THREAD)
tsan_finish_file ();
+ if (gate_hwasan ())
+ hwasan_finish_file ();
+
omp_finish_file ();
output_shared_constant_pool ();
@@ -684,148 +684,7 @@ print_version (FILE *file, const char *indent, bool show_global_state)
}
}
-static int
-print_to_asm_out_file (print_switch_type type, const char * text)
-{
- bool prepend_sep = true;
-
- switch (type)
- {
- case SWITCH_TYPE_LINE_END:
- putc ('\n', asm_out_file);
- return 1;
-
- case SWITCH_TYPE_LINE_START:
- fputs (ASM_COMMENT_START, asm_out_file);
- return strlen (ASM_COMMENT_START);
-
- case SWITCH_TYPE_DESCRIPTIVE:
- if (ASM_COMMENT_START[0] == 0)
- prepend_sep = false;
- /* FALLTHRU */
- case SWITCH_TYPE_PASSED:
- case SWITCH_TYPE_ENABLED:
- if (prepend_sep)
- fputc (' ', asm_out_file);
- fputs (text, asm_out_file);
- /* No need to return the length here as
- print_single_switch has already done it. */
- return 0;
-
- default:
- return -1;
- }
-}
-
-static int
-print_to_stderr (print_switch_type type, const char * text)
-{
- switch (type)
- {
- case SWITCH_TYPE_LINE_END:
- putc ('\n', stderr);
- return 1;
-
- case SWITCH_TYPE_LINE_START:
- return 0;
-
- case SWITCH_TYPE_PASSED:
- case SWITCH_TYPE_ENABLED:
- fputc (' ', stderr);
- /* FALLTHRU */
-
- case SWITCH_TYPE_DESCRIPTIVE:
- fputs (text, stderr);
- /* No need to return the length here as
- print_single_switch has already done it. */
- return 0;
-
- default:
- return -1;
- }
-}
-
-/* Print an option value and return the adjusted position in the line.
- ??? print_fn doesn't handle errors, eg disk full; presumably other
- code will catch a disk full though. */
-
-static int
-print_single_switch (print_switch_fn_type print_fn,
- int pos,
- print_switch_type type,
- const char * text)
-{
- /* The ultrix fprintf returns 0 on success, so compute the result
- we want here since we need it for the following test. The +1
- is for the separator character that will probably be emitted. */
- int len = strlen (text) + 1;
-
- if (pos != 0
- && pos + len > MAX_LINE)
- {
- print_fn (SWITCH_TYPE_LINE_END, NULL);
- pos = 0;
- }
-
- if (pos == 0)
- pos += print_fn (SWITCH_TYPE_LINE_START, NULL);
-
- print_fn (type, text);
- return pos + len;
-}
-
-/* Print active target switches using PRINT_FN.
- POS is the current cursor position and MAX is the size of a "line".
- Each line begins with INDENT and ends with TERM.
- Each switch is separated from the next by SEP. */
-
-static void
-print_switch_values (print_switch_fn_type print_fn)
-{
- int pos = 0;
- size_t j;
-
- /* Print the options as passed. */
- pos = print_single_switch (print_fn, pos,
- SWITCH_TYPE_DESCRIPTIVE, _("options passed: "));
- for (j = 1; j < save_decoded_options_count; j++)
- {
- switch (save_decoded_options[j].opt_index)
- {
- case OPT_o:
- case OPT_d:
- case OPT_dumpbase:
- case OPT_dumpbase_ext:
- case OPT_dumpdir:
- case OPT_quiet:
- case OPT_version:
- /* Ignore these. */
- continue;
- }
-
- pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED,
- save_decoded_options[j].orig_option_with_args_text);
- }
-
- if (pos > 0)
- print_fn (SWITCH_TYPE_LINE_END, NULL);
-
- /* Print the -f and -m options that have been enabled.
- We don't handle language specific options but printing argv
- should suffice. */
- pos = print_single_switch (print_fn, 0,
- SWITCH_TYPE_DESCRIPTIVE, _("options enabled: "));
-
- unsigned lang_mask = lang_hooks.option_lang_mask ();
- for (j = 0; j < cl_options_count; j++)
- if (cl_options[j].cl_report
- && option_enabled (j, lang_mask, &global_options) > 0)
- pos = print_single_switch (print_fn, pos,
- SWITCH_TYPE_ENABLED, cl_options[j].opt_text);
-
- print_fn (SWITCH_TYPE_LINE_END, NULL);
-}
/* Open assembly code output file. Do this even if -fsyntax-only is
on, because then the driver will have provided the name of a
@@ -872,14 +731,11 @@ init_asm_output (const char *name)
{
if (targetm.asm_out.record_gcc_switches)
{
- /* Let the target know that we are about to start recording. */
- targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE,
- NULL);
- /* Now record the switches. */
- print_switch_values (targetm.asm_out.record_gcc_switches);
- /* Let the target know that the recording is over. */
- targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE,
- NULL);
+ const char *str
+ = gen_producer_string (lang_hooks.name,
+ save_decoded_options,
+ save_decoded_options_count);
+ targetm.asm_out.record_gcc_switches (str);
}
else
inform (UNKNOWN_LOCATION,
@@ -889,11 +745,13 @@ init_asm_output (const char *name)
if (flag_verbose_asm)
{
- /* Print the list of switches in effect
- into the assembler file as comments. */
print_version (asm_out_file, ASM_COMMENT_START, true);
- print_switch_values (print_to_asm_out_file);
- putc ('\n', asm_out_file);
+ fputs (ASM_COMMENT_START, asm_out_file);
+ fputs (" options passed: ", asm_out_file);
+ fputs (gen_command_line_string (save_decoded_options,
+ save_decoded_options_count),
+ asm_out_file);
+ fputc ('\n', asm_out_file);
}
}
}
@@ -1523,8 +1381,13 @@ process_options (void)
if (version_flag)
{
print_version (stderr, "", true);
- if (! quiet_flag)
- print_switch_values (print_to_stderr);
+ if (!quiet_flag)
+ {
+ fputs ("options passed: ", stderr);
+ fputs (gen_command_line_string (save_decoded_options,
+ save_decoded_options_count), stderr);
+ fputc ('\n', stderr);
+ }
}
if (flag_syntax_only)
@@ -1834,7 +1697,8 @@ process_options (void)
}
if ((flag_sanitize & SANITIZE_USER_ADDRESS)
- && targetm.asan_shadow_offset == NULL)
+ && ((targetm.asan_shadow_offset == NULL)
+ || (targetm.asan_shadow_offset () == 0)))
{
warning_at (UNKNOWN_LOCATION, 0,
"%<-fsanitize=address%> not supported for this target");
@@ -1843,7 +1707,6 @@ process_options (void)
if ((flag_sanitize & SANITIZE_KERNEL_ADDRESS)
&& (targetm.asan_shadow_offset == NULL
- && param_asan_stack
&& !asan_shadow_offset_set_p ()))
{
warning_at (UNKNOWN_LOCATION, 0,
@@ -1853,6 +1716,15 @@ process_options (void)
flag_sanitize &= ~SANITIZE_ADDRESS;
}
+ /* HWAsan requires top byte ignore feature in the backend. */
+ if (flag_sanitize & SANITIZE_HWADDRESS
+ && ! targetm.memtag.can_tag_addresses ())
+ {
+ warning_at (UNKNOWN_LOCATION, 0, "%qs is not supported for this target",
+ "-fsanitize=hwaddress");
+ flag_sanitize &= ~SANITIZE_HWADDRESS;
+ }
+
/* Do not use IPA optimizations for register allocation if profiler is active
or patchable function entries are inserted for run-time instrumentation
or port does not emit prologue and epilogue as RTL. */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index e4f264d..c078a12 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4998,7 +4998,7 @@ ipa_tm_create_version (struct cgraph_node *old_node)
new_node->lowered = true;
new_node->tm_clone = 1;
if (!old_node->implicit_section)
- new_node->set_section (old_node->get_section ());
+ new_node->set_section (*old_node);
get_cg_data (&old_node, true)->clone = new_node;
if (old_node->get_availability () >= AVAIL_INTERPOSABLE)
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 5139f11..f59a0c0 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3885,6 +3885,8 @@ verify_gimple_assign_binary (gassign *stmt)
return false;
}
+ case WIDEN_PLUS_EXPR:
+ case WIDEN_MINUS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
{
@@ -4005,6 +4007,10 @@ verify_gimple_assign_binary (gassign *stmt)
return false;
}
+ case VEC_WIDEN_MINUS_HI_EXPR:
+ case VEC_WIDEN_MINUS_LO_EXPR:
+ case VEC_WIDEN_PLUS_HI_EXPR:
+ case VEC_WIDEN_PLUS_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
@@ -7966,14 +7972,19 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
&& decl_is_tm_clone (fndecl));
struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
- if (DECL_ATTRIBUTES (fndecl) != NULL_TREE)
+ tree fntype = TREE_TYPE (fndecl);
+ tree attrs[] = { DECL_ATTRIBUTES (fndecl), TYPE_ATTRIBUTES (fntype) };
+
+ for (int i = 0; i != 2; ++i)
{
+ if (!attrs[i])
+ continue;
+
fprintf (file, "__attribute__((");
bool first = true;
tree chain;
- for (chain = DECL_ATTRIBUTES (fndecl); chain;
- first = false, chain = TREE_CHAIN (chain))
+ for (chain = attrs[i]; chain; first = false, chain = TREE_CHAIN (chain))
{
if (!first)
fprintf (file, ", ");
@@ -8026,7 +8037,11 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
}
}
else
- fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
+ {
+ print_generic_expr (file, TREE_TYPE (fntype), dump_flags);
+ fprintf (file, " %s %s(", function_name (fun),
+ tmclone ? "[tm-clone] " : "");
+ }
arg = DECL_ARGUMENTS (fndecl);
while (arg)
diff --git a/gcc/tree-cfgcleanup.h b/gcc/tree-cfgcleanup.h
index 6ff6726..9e368d6 100644
--- a/gcc/tree-cfgcleanup.h
+++ b/gcc/tree-cfgcleanup.h
@@ -26,5 +26,6 @@ extern bool cleanup_tree_cfg (unsigned = 0);
extern bool fixup_noreturn_call (gimple *stmt);
extern bool delete_unreachable_blocks_update_callgraph (cgraph_node *dst_node,
bool update_clones);
+extern unsigned clean_up_loop_closed_phi (function *);
#endif /* GCC_TREE_CFGCLEANUP_H */
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index f132e0f..1cfb3e8 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -318,7 +318,7 @@ complex_propagate::visit_stmt (gimple *stmt, edge *taken_edge_p ATTRIBUTE_UNUSED
lhs = gimple_get_lhs (stmt);
/* Skip anything but GIMPLE_ASSIGN and GIMPLE_CALL with a lhs. */
- if (!lhs)
+ if (!lhs || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
return SSA_PROP_VARYING;
/* These conditions should be satisfied due to the initial filter
@@ -417,6 +417,9 @@ complex_propagate::visit_phi (gphi *phi)
set up in init_dont_simulate_again. */
gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
+ return SSA_PROP_VARYING;
+
/* We've set up the lattice values such that IOR neatly models PHI meet. */
new_l = UNINITIALIZED;
for (i = gimple_phi_num_args (phi) - 1; i >= 0; --i)
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 752bec3..a89f063 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -110,6 +110,10 @@ struct die_struct;
/* Nonzero if the argument is not used by the function. */
#define EAF_UNUSED (1 << 3)
+/* Nonzero if the argument itself does not escape but memory
+ referenced by it can escape. */
+#define EAF_NODIRECTESCAPE (1 << 4)
+
/* Call return flags. */
/* Mask for the argument number that is returned. Lower two bits of
the return flags, encodes argument slots zero to three. */
@@ -276,6 +280,9 @@ enum omp_clause_code {
/* OpenMP clause: aligned (variable-list[:alignment]). */
OMP_CLAUSE_ALIGNED,
+ /* OpenMP clause: allocate ([allocator:]variable-list). */
+ OMP_CLAUSE_ALLOCATE,
+
/* OpenMP clause: depend ({in,out,inout}:variable-list). */
OMP_CLAUSE_DEPEND,
@@ -766,6 +773,10 @@ enum tree_index {
TI_SAT_UDA_TYPE,
TI_SAT_UTA_TYPE,
+ TI_MODULE_HWM,
+ /* Nodes below here change during compilation, and should therefore
+ not be in the C++ module's global tree table. */
+
TI_OPTIMIZATION_DEFAULT,
TI_OPTIMIZATION_CURRENT,
TI_TARGET_OPTION_DEFAULT,
@@ -856,7 +867,10 @@ enum attribute_flags {
are not in fact compatible with the function type. */
ATTR_FLAG_BUILT_IN = 16,
/* A given attribute has been parsed as a C++-11 attribute. */
- ATTR_FLAG_CXX11 = 32
+ ATTR_FLAG_CXX11 = 32,
+ /* The attribute handler is being invoked with an internal argument
+ that may not otherwise be valid when specified in source code. */
+ ATTR_FLAG_INTERNAL = 64
};
/* Types used to represent sizes. */
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 3bf460c..926553b 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -97,6 +97,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "ssa.h"
#include "internal-fn.h"
+#include "range-op.h"
+#include "vr-values.h"
static struct datadep_stats
{
@@ -581,26 +583,196 @@ debug_ddrs (vec<ddr_p> ddrs)
dump_ddrs (stderr, ddrs);
}
+/* If RESULT_RANGE is nonnull, set *RESULT_RANGE to the range of
+ OP0 CODE OP1, where:
+
+ - OP0 CODE OP1 has integral type TYPE
+ - the range of OP0 is given by OP0_RANGE and
+ - the range of OP1 is given by OP1_RANGE.
+
+ Independently of RESULT_RANGE, try to compute:
+
+ DELTA = ((sizetype) OP0 CODE (sizetype) OP1)
+ - (sizetype) (OP0 CODE OP1)
+
+ as a constant and subtract DELTA from the ssizetype constant in *OFF.
+ Return true on success, or false if DELTA is not known at compile time.
+
+ Truncation and sign changes are known to distribute over CODE, i.e.
+
+ (itype) (A CODE B) == (itype) A CODE (itype) B
+
+ for any integral type ITYPE whose precision is no greater than the
+ precision of A and B. */
+
+static bool
+compute_distributive_range (tree type, value_range &op0_range,
+ tree_code code, value_range &op1_range,
+ tree *off, value_range *result_range)
+{
+ gcc_assert (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type));
+ if (result_range)
+ {
+ range_operator *op = range_op_handler (code, type);
+ op->fold_range (*result_range, type, op0_range, op1_range);
+ }
+
+ /* The distributive property guarantees that if TYPE is no narrower
+ than SIZETYPE,
+
+ (sizetype) (OP0 CODE OP1) == (sizetype) OP0 CODE (sizetype) OP1
+
+ and so we can treat DELTA as zero. */
+ if (TYPE_PRECISION (type) >= TYPE_PRECISION (sizetype))
+ return true;
+
+ /* If overflow is undefined, we can assume that:
+
+ X == (ssizetype) OP0 CODE (ssizetype) OP1
+
+ is within the range of TYPE, i.e.:
+
+ X == (ssizetype) (TYPE) X
+
+ Distributing the (TYPE) truncation over X gives:
+
+ X == (ssizetype) (OP0 CODE OP1)
+
+ Casting both sides to sizetype and distributing the sizetype cast
+ over X gives:
+
+ (sizetype) OP0 CODE (sizetype) OP1 == (sizetype) (OP0 CODE OP1)
+
+ and so we can treat DELTA as zero. */
+ if (TYPE_OVERFLOW_UNDEFINED (type))
+ return true;
+
+ /* Compute the range of:
+
+ (ssizetype) OP0 CODE (ssizetype) OP1
+
+ The distributive property guarantees that this has the same bitpattern as:
+
+ (sizetype) OP0 CODE (sizetype) OP1
+
+ but its range is more conducive to analysis. */
+ range_cast (op0_range, ssizetype);
+ range_cast (op1_range, ssizetype);
+ value_range wide_range;
+ range_operator *op = range_op_handler (code, ssizetype);
+ bool saved_flag_wrapv = flag_wrapv;
+ flag_wrapv = 1;
+ op->fold_range (wide_range, ssizetype, op0_range, op1_range);
+ flag_wrapv = saved_flag_wrapv;
+ if (wide_range.num_pairs () != 1 || !range_int_cst_p (&wide_range))
+ return false;
+
+ wide_int lb = wide_range.lower_bound ();
+ wide_int ub = wide_range.upper_bound ();
+
+ /* Calculate the number of times that each end of the range overflows or
+ underflows TYPE. We can only calculate DELTA if the numbers match. */
+ unsigned int precision = TYPE_PRECISION (type);
+ if (!TYPE_UNSIGNED (type))
+ {
+ wide_int type_min = wi::mask (precision - 1, true, lb.get_precision ());
+ lb -= type_min;
+ ub -= type_min;
+ }
+ wide_int upper_bits = wi::mask (precision, true, lb.get_precision ());
+ lb &= upper_bits;
+ ub &= upper_bits;
+ if (lb != ub)
+ return false;
+
+ /* OP0 CODE OP1 overflows exactly arshift (LB, PRECISION) times, with
+ negative values indicating underflow. The low PRECISION bits of LB
+ are clear, so DELTA is therefore LB (== UB). */
+ *off = wide_int_to_tree (ssizetype, wi::to_wide (*off) - lb);
+ return true;
+}
+
+/* Return true if (sizetype) OP == (sizetype) (TO_TYPE) OP,
+ given that OP has type FROM_TYPE and range RANGE. Both TO_TYPE and
+ FROM_TYPE are integral types. */
+
+static bool
+nop_conversion_for_offset_p (tree to_type, tree from_type, value_range &range)
+{
+ gcc_assert (INTEGRAL_TYPE_P (to_type)
+ && INTEGRAL_TYPE_P (from_type)
+ && !TYPE_OVERFLOW_TRAPS (to_type)
+ && !TYPE_OVERFLOW_TRAPS (from_type));
+
+ /* Converting to something no narrower than sizetype and then to sizetype
+ is equivalent to converting directly to sizetype. */
+ if (TYPE_PRECISION (to_type) >= TYPE_PRECISION (sizetype))
+ return true;
+
+ /* Check whether TO_TYPE can represent all values that FROM_TYPE can. */
+ if (TYPE_PRECISION (from_type) < TYPE_PRECISION (to_type)
+ && (TYPE_UNSIGNED (from_type) || !TYPE_UNSIGNED (to_type)))
+ return true;
+
+ /* For narrowing conversions, we could in principle test whether
+ the bits in FROM_TYPE but not in TO_TYPE have a fixed value
+ and apply a constant adjustment.
+
+ For other conversions (which involve a sign change) we could
+ check that the signs are always equal, and apply a constant
+ adjustment if the signs are negative.
+
+ However, both cases should be rare. */
+ return range_fits_type_p (&range, TYPE_PRECISION (to_type),
+ TYPE_SIGN (to_type));
+}
+
static void
-split_constant_offset (tree exp, tree *var, tree *off,
+split_constant_offset (tree type, tree *var, tree *off,
+ value_range *result_range,
hash_map<tree, std::pair<tree, tree> > &cache,
unsigned *limit);
-/* Helper function for split_constant_offset. Expresses OP0 CODE OP1
- (the type of the result is TYPE) as VAR + OFF, where OFF is a nonzero
- constant of type ssizetype, and returns true. If we cannot do this
- with OFF nonzero, OFF and VAR are set to NULL_TREE instead and false
- is returned. */
+/* Helper function for split_constant_offset. If TYPE is a pointer type,
+ try to express OP0 CODE OP1 as:
+
+ POINTER_PLUS <*VAR, (sizetype) *OFF>
+
+ where:
+
+ - *VAR has type TYPE
+ - *OFF is a constant of type ssizetype.
+
+ If TYPE is an integral type, try to express (sizetype) (OP0 CODE OP1) as:
+
+ *VAR + (sizetype) *OFF
+
+ where:
+
+ - *VAR has type sizetype
+ - *OFF is a constant of type ssizetype.
+
+ In both cases, OP0 CODE OP1 has type TYPE.
+
+ Return true on success. A false return value indicates that we can't
+ do better than set *OFF to zero.
+
+ When returning true, set RESULT_RANGE to the range of OP0 CODE OP1,
+ if RESULT_RANGE is nonnull and if we can do better than assume VR_VARYING.
+
+ CACHE caches {*VAR, *OFF} pairs for SSA names that we've previously
+ visited. LIMIT counts down the number of SSA names that we are
+ allowed to process before giving up. */
static bool
split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
- tree *var, tree *off,
+ tree *var, tree *off, value_range *result_range,
hash_map<tree, std::pair<tree, tree> > &cache,
unsigned *limit)
{
tree var0, var1;
tree off0, off1;
- enum tree_code ocode = code;
+ value_range op0_range, op1_range;
*var = NULL_TREE;
*off = NULL_TREE;
@@ -608,35 +780,42 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
switch (code)
{
case INTEGER_CST:
- *var = build_int_cst (type, 0);
+ *var = size_int (0);
*off = fold_convert (ssizetype, op0);
+ if (result_range)
+ result_range->set (op0, op0);
return true;
case POINTER_PLUS_EXPR:
- ocode = PLUS_EXPR;
- /* FALLTHROUGH */
+ split_constant_offset (op0, &var0, &off0, nullptr, cache, limit);
+ split_constant_offset (op1, &var1, &off1, nullptr, cache, limit);
+ *var = fold_build2 (POINTER_PLUS_EXPR, type, var0, var1);
+ *off = size_binop (PLUS_EXPR, off0, off1);
+ return true;
+
case PLUS_EXPR:
case MINUS_EXPR:
- if (TREE_CODE (op1) == INTEGER_CST)
- {
- split_constant_offset (op0, &var0, &off0, cache, limit);
- *var = var0;
- *off = size_binop (ocode, off0, fold_convert (ssizetype, op1));
- return true;
- }
- split_constant_offset (op0, &var0, &off0, cache, limit);
- split_constant_offset (op1, &var1, &off1, cache, limit);
- *var = fold_build2 (code, type, var0, var1);
- *off = size_binop (ocode, off0, off1);
+ split_constant_offset (op0, &var0, &off0, &op0_range, cache, limit);
+ split_constant_offset (op1, &var1, &off1, &op1_range, cache, limit);
+ *off = size_binop (code, off0, off1);
+ if (!compute_distributive_range (type, op0_range, code, op1_range,
+ off, result_range))
+ return false;
+ *var = fold_build2 (code, sizetype, var0, var1);
return true;
case MULT_EXPR:
if (TREE_CODE (op1) != INTEGER_CST)
return false;
- split_constant_offset (op0, &var0, &off0, cache, limit);
- *var = fold_build2 (MULT_EXPR, type, var0, op1);
+ split_constant_offset (op0, &var0, &off0, &op0_range, cache, limit);
+ op1_range.set (op1, op1);
*off = size_binop (MULT_EXPR, off0, fold_convert (ssizetype, op1));
+ if (!compute_distributive_range (type, op0_range, code, op1_range,
+ off, result_range))
+ return false;
+ *var = fold_build2 (MULT_EXPR, sizetype, var0,
+ fold_convert (sizetype, op1));
return true;
case ADDR_EXPR:
@@ -658,13 +837,10 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
if (poffset)
{
- split_constant_offset (poffset, &poffset, &off1, cache, limit);
+ split_constant_offset (poffset, &poffset, &off1, nullptr,
+ cache, limit);
off0 = size_binop (PLUS_EXPR, off0, off1);
- if (POINTER_TYPE_P (TREE_TYPE (base)))
- base = fold_build_pointer_plus (base, poffset);
- else
- base = fold_build2 (PLUS_EXPR, TREE_TYPE (base), base,
- fold_convert (TREE_TYPE (base), poffset));
+ base = fold_build_pointer_plus (base, poffset);
}
var0 = fold_convert (type, base);
@@ -723,6 +899,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
return false;
*var = e.first;
*off = e.second;
+ /* The caller sets the range in this case. */
return true;
}
e = std::make_pair (op0, ssize_int (0));
@@ -736,68 +913,80 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
var1 = gimple_assign_rhs2 (def_stmt);
bool res = split_constant_offset_1 (type, var0, subcode, var1,
- var, off, cache, limit);
+ var, off, nullptr, cache, limit);
if (res && use_cache)
*cache.get (op0) = std::make_pair (*var, *off);
+ /* The caller sets the range in this case. */
return res;
}
CASE_CONVERT:
{
- /* We must not introduce undefined overflow, and we must not change
- the value. Hence we're okay if the inner type doesn't overflow
- to start with (pointer or signed), the outer type also is an
- integer or pointer and the outer precision is at least as large
- as the inner. */
+ /* We can only handle the following conversions:
+
+ - Conversions from one pointer type to another pointer type.
+
+ - Conversions from one non-trapping integral type to another
+ non-trapping integral type. In this case, the recursive
+ call makes sure that:
+
+ (sizetype) OP0
+
+ can be expressed as a sizetype operation involving VAR and OFF,
+ and all we need to do is check whether:
+
+ (sizetype) OP0 == (sizetype) (TYPE) OP0
+
+ - Conversions from a non-trapping sizetype-size integral type to
+ a like-sized pointer type. In this case, the recursive call
+ makes sure that:
+
+ (sizetype) OP0 == *VAR + (sizetype) *OFF
+
+ and we can convert that to:
+
+ POINTER_PLUS <(TYPE) *VAR, (sizetype) *OFF>
+
+ - Conversions from a sizetype-sized pointer type to a like-sized
+ non-trapping integral type. In this case, the recursive call
+ makes sure that:
+
+ OP0 == POINTER_PLUS <*VAR, (sizetype) *OFF>
+
+ where the POINTER_PLUS and *VAR have the same precision as
+ TYPE (and the same precision as sizetype). Then:
+
+ (sizetype) (TYPE) OP0 == (sizetype) *VAR + (sizetype) *OFF. */
tree itype = TREE_TYPE (op0);
if ((POINTER_TYPE_P (itype)
|| (INTEGRAL_TYPE_P (itype) && !TYPE_OVERFLOW_TRAPS (itype)))
- && TYPE_PRECISION (type) >= TYPE_PRECISION (itype)
- && (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)))
+ && (POINTER_TYPE_P (type)
+ || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)))
+ && (POINTER_TYPE_P (type) == POINTER_TYPE_P (itype)
+ || (TYPE_PRECISION (type) == TYPE_PRECISION (sizetype)
+ && TYPE_PRECISION (itype) == TYPE_PRECISION (sizetype))))
{
- if (INTEGRAL_TYPE_P (itype) && TYPE_OVERFLOW_WRAPS (itype)
- && (TYPE_PRECISION (type) > TYPE_PRECISION (itype)
- || TYPE_UNSIGNED (itype) != TYPE_UNSIGNED (type)))
+ if (POINTER_TYPE_P (type))
{
- /* Split the unconverted operand and try to prove that
- wrapping isn't a problem. */
- tree tmp_var, tmp_off;
- split_constant_offset (op0, &tmp_var, &tmp_off, cache, limit);
-
- /* See whether we have an SSA_NAME whose range is known
- to be [A, B]. */
- if (TREE_CODE (tmp_var) != SSA_NAME)
- return false;
- wide_int var_min, var_max;
- value_range_kind vr_type = get_range_info (tmp_var, &var_min,
- &var_max);
- wide_int var_nonzero = get_nonzero_bits (tmp_var);
- signop sgn = TYPE_SIGN (itype);
- if (intersect_range_with_nonzero_bits (vr_type, &var_min,
- &var_max, var_nonzero,
- sgn) != VR_RANGE)
- return false;
-
- /* See whether the range of OP0 (i.e. TMP_VAR + TMP_OFF)
- is known to be [A + TMP_OFF, B + TMP_OFF], with all
- operations done in ITYPE. The addition must overflow
- at both ends of the range or at neither. */
- wi::overflow_type overflow[2];
- unsigned int prec = TYPE_PRECISION (itype);
- wide_int woff = wi::to_wide (tmp_off, prec);
- wide_int op0_min = wi::add (var_min, woff, sgn, &overflow[0]);
- wi::add (var_max, woff, sgn, &overflow[1]);
- if ((overflow[0] != wi::OVF_NONE) != (overflow[1] != wi::OVF_NONE))
- return false;
-
- /* Calculate (ssizetype) OP0 - (ssizetype) TMP_VAR. */
- widest_int diff = (widest_int::from (op0_min, sgn)
- - widest_int::from (var_min, sgn));
- var0 = tmp_var;
- *off = wide_int_to_tree (ssizetype, diff);
+ split_constant_offset (op0, var, off, nullptr, cache, limit);
+ *var = fold_convert (type, *var);
+ }
+ else if (POINTER_TYPE_P (itype))
+ {
+ split_constant_offset (op0, var, off, nullptr, cache, limit);
+ *var = fold_convert (sizetype, *var);
}
else
- split_constant_offset (op0, &var0, off, cache, limit);
- *var = fold_convert (type, var0);
+ {
+ split_constant_offset (op0, var, off, &op0_range,
+ cache, limit);
+ if (!nop_conversion_for_offset_p (type, itype, op0_range))
+ return false;
+ if (result_range)
+ {
+ *result_range = op0_range;
+ range_cast (*result_range, type);
+ }
+ }
return true;
}
return false;
@@ -808,33 +997,80 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
}
}
-/* Expresses EXP as VAR + OFF, where off is a constant. The type of OFF
- will be ssizetype. */
+/* If EXP has pointer type, try to express it as:
+
+ POINTER_PLUS <*VAR, (sizetype) *OFF>
+
+ where:
+
+ - *VAR has the same type as EXP
+ - *OFF is a constant of type ssizetype.
+
+ If EXP has an integral type, try to express (sizetype) EXP as:
+
+ *VAR + (sizetype) *OFF
+
+ where:
+
+ - *VAR has type sizetype
+ - *OFF is a constant of type ssizetype.
+
+ If EXP_RANGE is nonnull, set it to the range of EXP.
+
+ CACHE caches {*VAR, *OFF} pairs for SSA names that we've previously
+ visited. LIMIT counts down the number of SSA names that we are
+ allowed to process before giving up. */
static void
-split_constant_offset (tree exp, tree *var, tree *off,
+split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range,
hash_map<tree, std::pair<tree, tree> > &cache,
unsigned *limit)
{
- tree type = TREE_TYPE (exp), op0, op1, e, o;
+ tree type = TREE_TYPE (exp), op0, op1;
enum tree_code code;
- *var = exp;
- *off = ssize_int (0);
+ code = TREE_CODE (exp);
+ if (exp_range)
+ {
+ *exp_range = type;
+ if (code == SSA_NAME)
+ {
+ wide_int var_min, var_max;
+ value_range_kind vr_kind = get_range_info (exp, &var_min, &var_max);
+ wide_int var_nonzero = get_nonzero_bits (exp);
+ vr_kind = intersect_range_with_nonzero_bits (vr_kind,
+ &var_min, &var_max,
+ var_nonzero,
+ TYPE_SIGN (type));
+ if (vr_kind == VR_RANGE)
+ *exp_range = value_range (type, var_min, var_max);
+ }
+ }
- if (tree_is_chrec (exp)
- || get_gimple_rhs_class (TREE_CODE (exp)) == GIMPLE_TERNARY_RHS)
- return;
+ if (!tree_is_chrec (exp)
+ && get_gimple_rhs_class (TREE_CODE (exp)) != GIMPLE_TERNARY_RHS)
+ {
+ extract_ops_from_tree (exp, &code, &op0, &op1);
+ if (split_constant_offset_1 (type, op0, code, op1, var, off,
+ exp_range, cache, limit))
+ return;
+ }
- code = TREE_CODE (exp);
- extract_ops_from_tree (exp, &code, &op0, &op1);
- if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache, limit))
+ *var = exp;
+ if (INTEGRAL_TYPE_P (type))
+ *var = fold_convert (sizetype, *var);
+ *off = ssize_int (0);
+ if (exp_range && code != SSA_NAME)
{
- *var = e;
- *off = o;
+ wide_int var_min, var_max;
+ if (determine_value_range (exp, &var_min, &var_max) == VR_RANGE)
+ *exp_range = value_range (type, var_min, var_max);
}
}
+/* Expresses EXP as VAR + OFF, where OFF is a constant. VAR has the same
+ type as EXP while OFF has type ssizetype. */
+
void
split_constant_offset (tree exp, tree *var, tree *off)
{
@@ -842,7 +1078,8 @@ split_constant_offset (tree exp, tree *var, tree *off)
static hash_map<tree, std::pair<tree, tree> > *cache;
if (!cache)
cache = new hash_map<tree, std::pair<tree, tree> > (37);
- split_constant_offset (exp, var, off, *cache, &limit);
+ split_constant_offset (exp, var, off, nullptr, *cache, &limit);
+ *var = fold_convert (TREE_TYPE (exp), *var);
cache->empty ();
}
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 82b3c2d..b4fef2b 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -110,112 +110,108 @@ can_consolidate_events (const diagnostic_event &e1,
return true;
}
-/* A class for grouing together the events in a diagnostic_path into
- ranges of events, partitioned by stack frame (i.e. by fndecl and
- stack depth). */
-
-class path_summary
+/* A range of consecutive events within a diagnostic_path,
+ all with the same fndecl and stack_depth, and which are suitable
+ to print with a single call to diagnostic_show_locus. */
+struct event_range
{
- /* A range of consecutive events within a diagnostic_path,
- all with the same fndecl and stack_depth, and which are suitable
- to print with a single call to diagnostic_show_locus. */
- struct event_range
+ event_range (const diagnostic_path *path, unsigned start_idx,
+ const diagnostic_event &initial_event)
+ : m_path (path),
+ m_initial_event (initial_event),
+ m_fndecl (initial_event.get_fndecl ()),
+ m_stack_depth (initial_event.get_stack_depth ()),
+ m_start_idx (start_idx), m_end_idx (start_idx),
+ m_path_label (path, start_idx),
+ m_richloc (initial_event.get_location (), &m_path_label)
+ {}
+
+ bool maybe_add_event (const diagnostic_event &new_ev, unsigned idx,
+ bool check_rich_locations)
{
- event_range (const diagnostic_path *path, unsigned start_idx,
- const diagnostic_event &initial_event)
- : m_path (path),
- m_initial_event (initial_event),
- m_fndecl (initial_event.get_fndecl ()),
- m_stack_depth (initial_event.get_stack_depth ()),
- m_start_idx (start_idx), m_end_idx (start_idx),
- m_path_label (path, start_idx),
- m_richloc (initial_event.get_location (), &m_path_label)
- {}
-
- bool maybe_add_event (const diagnostic_event &new_ev, unsigned idx,
- bool check_rich_locations)
- {
- if (!can_consolidate_events (m_initial_event, new_ev,
- check_rich_locations))
+ if (!can_consolidate_events (m_initial_event, new_ev,
+ check_rich_locations))
+ return false;
+ if (check_rich_locations)
+ if (!m_richloc.add_location_if_nearby (new_ev.get_location (),
+ false, &m_path_label))
return false;
- if (check_rich_locations)
- if (!m_richloc.add_location_if_nearby (new_ev.get_location (),
- false, &m_path_label))
- return false;
- m_end_idx = idx;
- return true;
- }
+ m_end_idx = idx;
+ return true;
+ }
- /* Print the events in this range to DC, typically as a single
- call to the printer's diagnostic_show_locus. */
+ /* Print the events in this range to DC, typically as a single
+ call to the printer's diagnostic_show_locus. */
- void print (diagnostic_context *dc)
- {
- location_t initial_loc = m_initial_event.get_location ();
+ void print (diagnostic_context *dc)
+ {
+ location_t initial_loc = m_initial_event.get_location ();
- /* Emit a span indicating the filename (and line/column) if the
- line has changed relative to the last call to
- diagnostic_show_locus. */
- if (dc->show_caret)
- {
- expanded_location exploc
- = linemap_client_expand_location_to_spelling_point
- (initial_loc, LOCATION_ASPECT_CARET);
- if (exploc.file != LOCATION_FILE (dc->last_location))
- dc->start_span (dc, exploc);
- }
+ /* Emit a span indicating the filename (and line/column) if the
+ line has changed relative to the last call to
+ diagnostic_show_locus. */
+ if (dc->show_caret)
+ {
+ expanded_location exploc
+ = linemap_client_expand_location_to_spelling_point
+ (initial_loc, LOCATION_ASPECT_CARET);
+ if (exploc.file != LOCATION_FILE (dc->last_location))
+ dc->start_span (dc, exploc);
+ }
- /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
- primary location for an event, diagnostic_show_locus won't print
- anything.
+ /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
+ primary location for an event, diagnostic_show_locus won't print
+ anything.
- In particular the label for the event won't get printed.
- Fail more gracefully in this case by showing the event
- index and text, at no particular location. */
- if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
- {
- for (unsigned i = m_start_idx; i <= m_end_idx; i++)
- {
- const diagnostic_event &iter_event = m_path->get_event (i);
- diagnostic_event_id_t event_id (i);
- label_text event_text (iter_event.get_desc (true));
- pretty_printer *pp = dc->printer;
- pp_printf (pp, " %@: %s", &event_id, event_text.m_buffer);
- pp_newline (pp);
- event_text.maybe_free ();
- }
- return;
- }
+ In particular the label for the event won't get printed.
+ Fail more gracefully in this case by showing the event
+ index and text, at no particular location. */
+ if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
+ {
+ for (unsigned i = m_start_idx; i <= m_end_idx; i++)
+ {
+ const diagnostic_event &iter_event = m_path->get_event (i);
+ diagnostic_event_id_t event_id (i);
+ label_text event_text (iter_event.get_desc (true));
+ pretty_printer *pp = dc->printer;
+ pp_printf (pp, " %@: %s", &event_id, event_text.m_buffer);
+ pp_newline (pp);
+ event_text.maybe_free ();
+ }
+ return;
+ }
- /* Call diagnostic_show_locus to show the events using labels. */
- diagnostic_show_locus (dc, &m_richloc, DK_DIAGNOSTIC_PATH);
+ /* Call diagnostic_show_locus to show the events using labels. */
+ diagnostic_show_locus (dc, &m_richloc, DK_DIAGNOSTIC_PATH);
- /* If we have a macro expansion, show the expansion to the user. */
- if (linemap_location_from_macro_expansion_p (line_table, initial_loc))
- {
- gcc_assert (m_start_idx == m_end_idx);
- maybe_unwind_expanded_macro_loc (dc, initial_loc);
- }
- }
+ /* If we have a macro expansion, show the expansion to the user. */
+ if (linemap_location_from_macro_expansion_p (line_table, initial_loc))
+ {
+ gcc_assert (m_start_idx == m_end_idx);
+ maybe_unwind_expanded_macro_loc (dc, initial_loc);
+ }
+ }
- const diagnostic_path *m_path;
- const diagnostic_event &m_initial_event;
- tree m_fndecl;
- int m_stack_depth;
- unsigned m_start_idx;
- unsigned m_end_idx;
- path_label m_path_label;
- gcc_rich_location m_richloc;
- };
+ const diagnostic_path *m_path;
+ const diagnostic_event &m_initial_event;
+ tree m_fndecl;
+ int m_stack_depth;
+ unsigned m_start_idx;
+ unsigned m_end_idx;
+ path_label m_path_label;
+ gcc_rich_location m_richloc;
+};
- public:
- path_summary (const diagnostic_path &path, bool check_rich_locations);
+/* A struct for grouping together the events in a diagnostic_path into
+ ranges of events, partitioned by stack frame (i.e. by fndecl and
+ stack depth). */
- void print (diagnostic_context *dc, bool show_depths) const;
+struct path_summary
+{
+ path_summary (const diagnostic_path &path, bool check_rich_locations);
unsigned get_num_ranges () const { return m_ranges.length (); }
- private:
auto_delete_vec <event_range> m_ranges;
};
@@ -265,7 +261,7 @@ print_fndecl (pretty_printer *pp, tree fndecl, bool quoted)
pp_string (pp, n);
}
-/* Print this path_summary to DC, giving an overview of the interprocedural
+/* Print path_summary PS to DC, giving an overview of the interprocedural
calls and returns.
Print the event descriptions in a nested form, printing the event
@@ -299,7 +295,8 @@ print_fndecl (pretty_printer *pp, tree fndecl, bool quoted)
For events with UNKNOWN_LOCATION, print a summary of each the event. */
void
-path_summary::print (diagnostic_context *dc, bool show_depths) const
+print_path_summary_as_text (const path_summary *ps, diagnostic_context *dc,
+ bool show_depths)
{
pretty_printer *pp = dc->printer;
@@ -322,13 +319,12 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
int cur_indent = base_indent;
unsigned i;
event_range *range;
- FOR_EACH_VEC_ELT (m_ranges, i, range)
+ FOR_EACH_VEC_ELT (ps->m_ranges, i, range)
{
write_indent (pp, cur_indent);
if (i > 0)
{
- const path_summary::event_range *prev_range
- = m_ranges[i - 1];
+ const event_range *prev_range = ps->m_ranges[i - 1];
if (range->m_stack_depth > prev_range->m_stack_depth)
{
/* Show pushed stack frame(s). */
@@ -384,10 +380,9 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
pp_newline (pp);
}
- if (i < m_ranges.length () - 1)
+ if (i < ps->m_ranges.length () - 1)
{
- const path_summary::event_range *next_range
- = m_ranges[i + 1];
+ const event_range *next_range = ps->m_ranges[i + 1];
if (range->m_stack_depth > next_range->m_stack_depth)
{
@@ -416,7 +411,7 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
write_indent (pp, vbar_for_next_frame);
pp_string (pp, start_line_color);
- pp_printf (pp, "|");
+ pp_character (pp, '|');
pp_string (pp, end_line_color);
pp_newline (pp);
}
@@ -481,7 +476,8 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
path_summary summary (*path, true);
char *saved_prefix = pp_take_prefix (context->printer);
pp_set_prefix (context->printer, NULL);
- summary.print (context, context->show_path_depths);
+ print_path_summary_as_text (&summary, context,
+ context->show_path_depths);
pp_flush (context->printer);
pp_set_prefix (context->printer, saved_prefix);
}
@@ -524,6 +520,13 @@ default_tree_make_json_for_path (diagnostic_context *context,
#if CHECKING_P
+/* Disable warnings about missing quoting in GCC diagnostics for the print
+ calls in the tests below. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
namespace selftest {
/* A subclass of simple_diagnostic_path that adds member functions
@@ -569,7 +572,7 @@ test_empty_path (pretty_printer *event_pp)
ASSERT_EQ (summary.get_num_ranges (), 0);
test_diagnostic_context dc;
- summary.print (&dc, true);
+ print_path_summary_as_text (&summary, &dc, true);
ASSERT_STREQ ("",
pp_formatted_text (dc.printer));
}
@@ -593,7 +596,7 @@ test_intraprocedural_path (pretty_printer *event_pp)
ASSERT_EQ (summary.get_num_ranges (), 1);
test_diagnostic_context dc;
- summary.print (&dc, true);
+ print_path_summary_as_text (&summary, &dc, true);
ASSERT_STREQ (" `foo': events 1-2 (depth 0)\n"
" |\n"
" | (1): first `free'\n"
@@ -642,7 +645,7 @@ test_interprocedural_path_1 (pretty_printer *event_pp)
ASSERT_EQ (summary.get_num_ranges (), 9);
test_diagnostic_context dc;
- summary.print (&dc, true);
+ print_path_summary_as_text (&summary, &dc, true);
ASSERT_STREQ
(" `test': events 1-2 (depth 0)\n"
" |\n"
@@ -724,7 +727,7 @@ test_interprocedural_path_2 (pretty_printer *event_pp)
ASSERT_EQ (summary.get_num_ranges (), 5);
test_diagnostic_context dc;
- summary.print (&dc, true);
+ print_path_summary_as_text (&summary, &dc, true);
ASSERT_STREQ
(" `foo': events 1-2 (depth 0)\n"
" |\n"
@@ -776,7 +779,7 @@ test_recursion (pretty_printer *event_pp)
ASSERT_EQ (summary.get_num_ranges (), 4);
test_diagnostic_context dc;
- summary.print (&dc, true);
+ print_path_summary_as_text (&summary, &dc, true);
ASSERT_STREQ
(" `factorial': events 1-2 (depth 0)\n"
" |\n"
@@ -818,4 +821,8 @@ tree_diagnostic_path_cc_tests ()
} // namespace selftest
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
+
#endif /* #if CHECKING_P */
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index 44755dd..5b55832 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -259,7 +259,7 @@ get_emutls_init_templ_addr (tree decl)
if (targetm.emutls.tmpl_section)
set_decl_section_name (to, targetm.emutls.tmpl_section);
else
- set_decl_section_name (to, DECL_SECTION_NAME (decl));
+ set_decl_section_name (to, decl);
/* Create varpool node for the new variable and finalize it if it is
not external one. */
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 2062758..93effaa 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -2916,12 +2916,6 @@ ifcvt_local_dce (class loop *loop)
enum gimple_code code;
use_operand_p use_p;
imm_use_iterator imm_iter;
- std::pair <tree, tree> *name_pair;
- unsigned int i;
-
- FOR_EACH_VEC_ELT (redundant_ssa_names, i, name_pair)
- replace_uses_by (name_pair->first, name_pair->second);
- redundant_ssa_names.release ();
/* The loop has a single BB only. */
basic_block bb = loop->header;
@@ -3124,6 +3118,13 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds)
exit_bbs = BITMAP_ALLOC (NULL);
bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index);
bitmap_set_bit (exit_bbs, loop->latch->index);
+
+ std::pair <tree, tree> *name_pair;
+ unsigned ssa_names_idx;
+ FOR_EACH_VEC_ELT (redundant_ssa_names, ssa_names_idx, name_pair)
+ replace_uses_by (name_pair->first, name_pair->second);
+ redundant_ssa_names.release ();
+
todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs);
/* Delete dead predicate computations. */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 32fb378..360b85f 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "symbol-summary.h"
#include "symtab-thunks.h"
+#include "symtab-clones.h"
/* I'm not real happy about this, but we need to handle gimple and
non-gimple trees. */
@@ -1818,12 +1819,11 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
/* If the inlined function has too many debug markers,
don't copy them. */
if (id->src_cfun->debug_marker_count
- > param_max_debug_marker_count)
+ > param_max_debug_marker_count
+ || id->reset_location)
return stmts;
gdebug *copy = as_a <gdebug *> (gimple_copy (stmt));
- if (id->reset_location)
- gimple_set_location (copy, input_location);
id->debug_stmts.safe_push (copy);
gimple_seq_add_stmt (&stmts, copy);
return stmts;
@@ -3168,7 +3168,14 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id)
}
if (gimple_debug_nonbind_marker_p (stmt))
- return;
+ {
+ if (id->call_stmt && !gimple_block (stmt))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gsi_remove (&gsi, true);
+ }
+ return;
+ }
/* Remap all the operands in COPY. */
memset (&wi, 0, sizeof (wi));
@@ -4223,6 +4230,8 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case REALIGN_LOAD_EXPR:
+ case WIDEN_PLUS_EXPR:
+ case WIDEN_MINUS_EXPR:
case WIDEN_SUM_EXPR:
case WIDEN_MULT_EXPR:
case DOT_PROD_EXPR:
@@ -4231,6 +4240,10 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case WIDEN_MULT_MINUS_EXPR:
case WIDEN_LSHIFT_EXPR:
+ case VEC_WIDEN_PLUS_HI_EXPR:
+ case VEC_WIDEN_PLUS_LO_EXPR:
+ case VEC_WIDEN_MINUS_HI_EXPR:
+ case VEC_WIDEN_MINUS_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
@@ -4702,6 +4715,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
use_operand_p use;
gimple *simtenter_stmt = NULL;
vec<tree> *simtvars_save;
+ clone_info *info;
/* The gimplifier uses input_location in too many places, such as
internal_get_tmp_var (). */
@@ -5024,31 +5038,33 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
/* Add local vars in this inlined callee to caller. */
add_local_variables (id->src_cfun, cfun, id);
- if (id->src_node->clone.performed_splits)
+ info = clone_info::get (id->src_node);
+ if (info && info->performed_splits)
{
+ clone_info *dst_info = clone_info::get_create (id->dst_node);
/* Any calls from the inlined function will be turned into calls from the
function we inline into. We must preserve notes about how to split
parameters such calls should be redirected/updated. */
- unsigned len = vec_safe_length (id->src_node->clone.performed_splits);
+ unsigned len = vec_safe_length (info->performed_splits);
for (unsigned i = 0; i < len; i++)
{
ipa_param_performed_split ps
- = (*id->src_node->clone.performed_splits)[i];
+ = (*info->performed_splits)[i];
ps.dummy_decl = remap_decl (ps.dummy_decl, id);
- vec_safe_push (id->dst_node->clone.performed_splits, ps);
+ vec_safe_push (dst_info->performed_splits, ps);
}
if (flag_checking)
{
- len = vec_safe_length (id->dst_node->clone.performed_splits);
+ len = vec_safe_length (dst_info->performed_splits);
for (unsigned i = 0; i < len; i++)
{
ipa_param_performed_split *ps1
- = &(*id->dst_node->clone.performed_splits)[i];
+ = &(*dst_info->performed_splits)[i];
for (unsigned j = i + 1; j < len; j++)
{
ipa_param_performed_split *ps2
- = &(*id->dst_node->clone.performed_splits)[j];
+ = &(*dst_info->performed_splits)[j];
gcc_assert (ps1->dummy_decl != ps2->dummy_decl
|| ps1->unit_offset != ps2->unit_offset);
}
@@ -6074,8 +6090,9 @@ tree_versionable_function_p (tree fndecl)
static void
update_clone_info (copy_body_data * id)
{
+ clone_info *dst_info = clone_info::get (id->dst_node);
vec<ipa_param_performed_split, va_gc> *cur_performed_splits
- = id->dst_node->clone.performed_splits;
+ = dst_info ? dst_info->performed_splits : NULL;
if (cur_performed_splits)
{
unsigned len = cur_performed_splits->length ();
@@ -6092,23 +6109,24 @@ update_clone_info (copy_body_data * id)
for (node = id->dst_node->clones; node != id->dst_node;)
{
/* First update replace maps to match the new body. */
- if (node->clone.tree_map)
- {
+ clone_info *info = clone_info::get (node);
+ if (info && info->tree_map)
+ {
unsigned int i;
- for (i = 0; i < vec_safe_length (node->clone.tree_map); i++)
+ for (i = 0; i < vec_safe_length (info->tree_map); i++)
{
struct ipa_replace_map *replace_info;
- replace_info = (*node->clone.tree_map)[i];
+ replace_info = (*info->tree_map)[i];
walk_tree (&replace_info->new_tree, copy_tree_body_r, id, NULL);
}
}
- if (node->clone.performed_splits)
+ if (info && info->performed_splits)
{
- unsigned len = vec_safe_length (node->clone.performed_splits);
+ unsigned len = vec_safe_length (info->performed_splits);
for (unsigned i = 0; i < len; i++)
{
ipa_param_performed_split *ps
- = &(*node->clone.performed_splits)[i];
+ = &(*info->performed_splits)[i];
ps->dummy_decl = remap_decl (ps->dummy_decl, id);
}
}
@@ -6118,10 +6136,12 @@ update_clone_info (copy_body_data * id)
a copy of function body for later during inlining, that would just
duplicate all entries. So let's have a look whether anything
referring to the first dummy_decl is present. */
- unsigned dst_len = vec_safe_length (node->clone.performed_splits);
+ if (!info)
+ info = clone_info::get_create (node);
+ unsigned dst_len = vec_safe_length (info->performed_splits);
ipa_param_performed_split *first = &(*cur_performed_splits)[0];
for (unsigned i = 0; i < dst_len; i++)
- if ((*node->clone.performed_splits)[i].dummy_decl
+ if ((*info->performed_splits)[i].dummy_decl
== first->dummy_decl)
{
len = 0;
@@ -6129,18 +6149,18 @@ update_clone_info (copy_body_data * id)
}
for (unsigned i = 0; i < len; i++)
- vec_safe_push (node->clone.performed_splits,
+ vec_safe_push (info->performed_splits,
(*cur_performed_splits)[i]);
if (flag_checking)
{
for (unsigned i = 0; i < dst_len; i++)
{
ipa_param_performed_split *ps1
- = &(*node->clone.performed_splits)[i];
+ = &(*info->performed_splits)[i];
for (unsigned j = i + 1; j < dst_len; j++)
{
ipa_param_performed_split *ps2
- = &(*node->clone.performed_splits)[j];
+ = &(*info->performed_splits)[j];
gcc_assert (ps1->dummy_decl != ps2->dummy_decl
|| ps1->unit_offset != ps2->unit_offset);
}
@@ -6270,8 +6290,9 @@ tree_function_versioning (tree old_decl, tree new_decl,
= copy_static_chain (p, &id);
auto_vec<int, 16> new_param_indices;
+ clone_info *info = clone_info::get (old_version_node);
ipa_param_adjustments *old_param_adjustments
- = old_version_node->clone.param_adjustments;
+ = info ? info->param_adjustments : NULL;
if (old_param_adjustments)
old_param_adjustments->get_updated_indices (&new_param_indices);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 1493b32..51c619d 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1412,6 +1412,10 @@ rewrite_stmt (gimple_stmt_iterator *si)
SET_DEF (def_p, name);
register_new_def (DEF_FROM_PTR (def_p), var);
+ /* Do not insert debug stmts if the stmt ends the BB. */
+ if (stmt_ends_bb_p (stmt))
+ continue;
+
tracked_var = target_for_debug_bind (var);
if (tracked_var)
{
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 788883f..a4d82174 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -65,8 +65,11 @@ nested_function_info *
nested_function_info::get_create (cgraph_node *node)
{
if (!nested_function_sum)
- nested_function_sum = new function_summary <nested_function_info *>
- (symtab);
+ {
+ nested_function_sum = new function_summary <nested_function_info *>
+ (symtab);
+ nested_function_sum->disable_insertion_hook ();
+ }
return nested_function_sum->get_create (node);
}
@@ -124,6 +127,9 @@ nested_function_info::release ()
void
maybe_record_nested_function (cgraph_node *node)
{
+ /* All nested functions gets lowered during the construction of symtab. */
+ if (symtab->state > CONSTRUCTION)
+ return;
if (DECL_CONTEXT (node->decl)
&& TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
{
@@ -1435,6 +1441,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
}
/* FALLTHRU */
case OMP_CLAUSE_NONTEMPORAL:
+ do_decl_clause_no_supp:
/* Like do_decl_clause, but don't add any suppression. */
decl = OMP_CLAUSE_DECL (clause);
if (VAR_P (decl)
@@ -1447,6 +1454,16 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
}
break;
+ case OMP_CLAUSE_ALLOCATE:
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+ {
+ wi->val_only = true;
+ wi->is_lhs = false;
+ convert_nonlocal_reference_op
+ (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause), &dummy, wi);
+ }
+ goto do_decl_clause_no_supp;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
@@ -2197,6 +2214,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
}
/* FALLTHRU */
case OMP_CLAUSE_NONTEMPORAL:
+ do_decl_clause_no_supp:
/* Like do_decl_clause, but don't add any suppression. */
decl = OMP_CLAUSE_DECL (clause);
if (VAR_P (decl)
@@ -2215,6 +2233,16 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
}
break;
+ case OMP_CLAUSE_ALLOCATE:
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+ {
+ wi->val_only = true;
+ wi->is_lhs = false;
+ convert_local_reference_op
+ (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause), &dummy, wi);
+ }
+ goto do_decl_clause_no_supp;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 1e8badf..450a379 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -310,6 +310,11 @@ protected:
#define TODO_verify_all TODO_verify_il
+/* To-do flags for pending_TODOs. */
+
+/* Tell the next scalar cleanup pass that there is
+ work for it to do. */
+#define PENDING_TODO_force_next_scalar_cleanup (1 << 1)
/* Register pass info. */
@@ -374,12 +379,14 @@ extern gimple_opt_pass *make_pass_empty_loop (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_graphite (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_graphite_transforms (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_if_conversion (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_if_to_switch (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_loop_distribution (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_vectorize (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_simduid_cleanup (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_slp_vectorize (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_complete_unroll (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_complete_unrolli (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_parallelize_loops (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_loop_prefetch (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_iv_optimize (gcc::context *ctxt);
@@ -410,6 +417,7 @@ extern gimple_opt_pass *make_pass_lower_switch (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_lower_switch_O0 (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_lower_vector (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_lower_vector_ssa (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_omp_oacc_kernels_decompose (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_lower_omp (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_diagnose_omp_blocks (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_expand_omp (gcc::context *ctxt);
@@ -590,6 +598,7 @@ extern rtl_opt_pass *make_pass_gcse2 (gcc::context *ctxt);
extern rtl_opt_pass *make_pass_split_after_reload (gcc::context *ctxt);
extern rtl_opt_pass *make_pass_thread_prologue_and_epilogue (gcc::context
*ctxt);
+extern rtl_opt_pass *make_pass_zero_call_used_regs (gcc::context *ctxt);
extern rtl_opt_pass *make_pass_stack_adjustments (gcc::context *ctxt);
extern rtl_opt_pass *make_pass_sched_fusion (gcc::context *ctxt);
extern rtl_opt_pass *make_pass_peephole2 (gcc::context *ctxt);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 64ac5ab..ae4b898 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -712,6 +712,19 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_right_paren (pp);
break;
+ case OMP_CLAUSE_ALLOCATE:
+ pp_string (pp, "allocate(");
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+ {
+ dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause),
+ spc, flags, false);
+ pp_colon (pp);
+ }
+ dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
+
case OMP_CLAUSE_DEPEND:
pp_string (pp, "depend(");
switch (OMP_CLAUSE_DEPEND_KIND (clause))
@@ -1695,6 +1708,7 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
case VECTOR_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
+ case OPAQUE_TYPE:
{
unsigned int quals = TYPE_QUALS (node);
enum tree_code_class tclass;
@@ -2152,7 +2166,7 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
case TYPE_DECL:
- if (DECL_IS_BUILTIN (node))
+ if (DECL_IS_UNDECLARED_BUILTIN (node))
{
/* Don't print the declaration of built-in types. */
break;
@@ -2635,6 +2649,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
/* Binary arithmetic and logic expressions. */
+ case WIDEN_PLUS_EXPR:
+ case WIDEN_MINUS_EXPR:
case WIDEN_SUM_EXPR:
case WIDEN_MULT_EXPR:
case MULT_EXPR:
@@ -3566,6 +3582,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
case VEC_SERIES_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
+ case VEC_WIDEN_PLUS_HI_EXPR:
+ case VEC_WIDEN_PLUS_LO_EXPR:
+ case VEC_WIDEN_MINUS_HI_EXPR:
+ case VEC_WIDEN_MINUS_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
@@ -4083,6 +4103,12 @@ op_symbol_code (enum tree_code code)
case WIDEN_LSHIFT_EXPR:
return "w<<";
+ case WIDEN_PLUS_EXPR:
+ return "w+";
+
+ case WIDEN_MINUS_EXPR:
+ return "w-";
+
case POINTER_PLUS_EXPR:
return "+";
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index edab778..2c7923d 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -3043,22 +3043,12 @@ iv_can_overflow_p (class loop *loop, tree type, tree base, tree step)
if (integer_zerop (step))
return false;
- if (TREE_CODE (base) == INTEGER_CST)
- base_min = base_max = wi::to_wide (base);
- else if (TREE_CODE (base) == SSA_NAME
- && INTEGRAL_TYPE_P (TREE_TYPE (base))
- && get_range_info (base, &base_min, &base_max) == VR_RANGE)
- ;
- else
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (base))
+ || get_range_info (base, &base_min, &base_max) != VR_RANGE)
return true;
- if (TREE_CODE (step) == INTEGER_CST)
- step_min = step_max = wi::to_wide (step);
- else if (TREE_CODE (step) == SSA_NAME
- && INTEGRAL_TYPE_P (TREE_TYPE (step))
- && get_range_info (step, &step_min, &step_max) == VR_RANGE)
- ;
- else
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (step))
+ || get_range_info (step, &step_min, &step_max) != VR_RANGE)
return true;
if (!get_max_loop_iterations (loop, &nit))
diff --git a/gcc/tree-ssa-alias-compare.h b/gcc/tree-ssa-alias-compare.h
new file mode 100644
index 0000000..0e8409a
--- /dev/null
+++ b/gcc/tree-ssa-alias-compare.h
@@ -0,0 +1,43 @@
+/* Comparsion of AO ref.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, 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/>. */
+
+#ifndef TREE_SSA_ALIAS_COMPARE_H
+#define TREE_SSA_ALIAS_COMPARE_H
+
+class operand_compare;
+/* A class aggregating all connections and semantic equivalents
+ for a given pair of semantic function candidates. */
+class ao_compare : public operand_compare
+{
+ public:
+ enum ao_ref_diff
+ {
+ SEMANTICS = 1,
+ BASE_ALIAS_SET = 2,
+ REF_ALIAS_SET = 4,
+ ACCESS_PATH = 8,
+ DEPENDENCE_CLIQUE = 16
+ };
+ int compare_ao_refs (ao_ref *ref1, ao_ref *ref2, bool lto_streaming_safe,
+ bool tbaa);
+ void hash_ao_ref (ao_ref *ref, bool lto_streaming_safe, bool tbaa,
+ inchash::hash &hstate);
+};
+
+#endif
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 877e499..311ce66 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -44,6 +44,9 @@ along with GCC; see the file COPYING3. If not see
#include "errors.h"
#include "dbgcnt.h"
#include "gimple-pretty-print.h"
+#include "print-tree.h"
+#include "tree-ssa-alias-compare.h"
+#include "builtins.h"
/* Broad overview of how alias analysis on gimple works:
@@ -738,6 +741,36 @@ ao_ref_alias_set (ao_ref *ref)
return ref->ref_alias_set;
}
+/* Returns a type satisfying
+ get_deref_alias_set (type) == ao_ref_base_alias_set (REF). */
+
+tree
+ao_ref_base_alias_ptr_type (ao_ref *ref)
+{
+ tree base_ref;
+
+ if (!ref->ref)
+ return NULL_TREE;
+ base_ref = ref->ref;
+ while (handled_component_p (base_ref))
+ base_ref = TREE_OPERAND (base_ref, 0);
+ tree ret = reference_alias_ptr_type (base_ref);
+ return ret;
+}
+
+/* Returns a type satisfying
+ get_deref_alias_set (type) == ao_ref_alias_set (REF). */
+
+tree
+ao_ref_alias_ptr_type (ao_ref *ref)
+{
+ if (!ref->ref)
+ return NULL_TREE;
+ tree ret = reference_alias_ptr_type (ref->ref);
+ return ret;
+}
+
+
/* Init an alias-oracle reference representation from a gimple pointer
PTR a range specified by OFFSET, SIZE and MAX_SIZE under the assumption
that RANGE_KNOWN is set.
@@ -1174,7 +1207,7 @@ aliasing_component_refs_p (tree ref1,
struct a {int array1[0]; int array[];};
Such struct has size 0 but accesses to a.array may have non-zero size.
In this case the size of TREE_TYPE (base1) is smaller than
- size of TREE_TYPE (TREE_OPERNAD (base1, 0)).
+ size of TREE_TYPE (TREE_OPERAND (base1, 0)).
Because we compare sizes of arrays just by sizes of their elements,
we only need to care about zero sized array fields here. */
@@ -1949,6 +1982,20 @@ decl_refs_may_alias_p (tree ref1, tree base1,
return true;
}
+/* Return true if access with BASE is view converted.
+ Base must not be stripped from inner MEM_REF (&decl)
+ which is done by ao_ref_base and thus one extra walk
+ of handled components is needed. */
+
+static bool
+view_converted_memref_p (tree base)
+{
+ if (TREE_CODE (base) != MEM_REF && TREE_CODE (base) != TARGET_MEM_REF)
+ return false;
+ return same_type_for_tbaa (TREE_TYPE (base),
+ TREE_TYPE (TREE_OPERAND (base, 1))) != 1;
+}
+
/* Return true if an indirect reference based on *PTR1 constrained
to [OFFSET1, OFFSET1 + MAX_SIZE1) may alias a variable based on BASE2
constrained to [OFFSET2, OFFSET2 + MAX_SIZE2). *PTR1 and BASE2 have
@@ -2572,6 +2619,99 @@ modref_may_conflict (const gimple *stmt,
return false;
}
+/* Check if REF conflicts with call using "fn spec" attribute.
+ If CLOBBER is true we are checking for writes, otherwise check loads.
+
+ Return 0 if there are no conflicts (except for possible function call
+ argument reads), 1 if there are conflicts and -1 if we can not decide by
+ fn spec. */
+
+static int
+check_fnspec (gcall *call, ao_ref *ref, bool clobber)
+{
+ attr_fnspec fnspec = gimple_call_fnspec (call);
+ if (fnspec.known_p ())
+ {
+ if (clobber
+ ? !fnspec.global_memory_written_p ()
+ : !fnspec.global_memory_read_p ())
+ {
+ for (unsigned int i = 0; i < gimple_call_num_args (call); i++)
+ if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, i)))
+ && (!fnspec.arg_specified_p (i)
+ || (clobber ? fnspec.arg_maybe_written_p (i)
+ : fnspec.arg_maybe_read_p (i))))
+ {
+ ao_ref dref;
+ tree size = NULL_TREE;
+ unsigned int size_arg;
+
+ if (!fnspec.arg_specified_p (i))
+ ;
+ else if (fnspec.arg_max_access_size_given_by_arg_p
+ (i, &size_arg))
+ size = gimple_call_arg (call, size_arg);
+ else if (fnspec.arg_access_size_given_by_type_p (i))
+ {
+ tree callee = gimple_call_fndecl (call);
+ tree t = TYPE_ARG_TYPES (TREE_TYPE (callee));
+
+ for (unsigned int p = 0; p < i; p++)
+ t = TREE_CHAIN (t);
+ size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_VALUE (t)));
+ }
+ ao_ref_init_from_ptr_and_size (&dref,
+ gimple_call_arg (call, i),
+ size);
+ if (refs_may_alias_p_1 (&dref, ref, false))
+ return 1;
+ }
+ if (clobber
+ && fnspec.errno_maybe_written_p ()
+ && flag_errno_math
+ && targetm.ref_may_alias_errno (ref))
+ return 1;
+ return 0;
+ }
+ }
+
+ /* FIXME: we should handle barriers more consistently, but for now leave the
+ check here. */
+ if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
+ switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
+ {
+ /* __sync_* builtins and some OpenMP builtins act as threading
+ barriers. */
+#undef DEF_SYNC_BUILTIN
+#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
+#include "sync-builtins.def"
+#undef DEF_SYNC_BUILTIN
+ case BUILT_IN_GOMP_ATOMIC_START:
+ case BUILT_IN_GOMP_ATOMIC_END:
+ case BUILT_IN_GOMP_BARRIER:
+ case BUILT_IN_GOMP_BARRIER_CANCEL:
+ case BUILT_IN_GOMP_TASKWAIT:
+ case BUILT_IN_GOMP_TASKGROUP_END:
+ case BUILT_IN_GOMP_CRITICAL_START:
+ case BUILT_IN_GOMP_CRITICAL_END:
+ case BUILT_IN_GOMP_CRITICAL_NAME_START:
+ case BUILT_IN_GOMP_CRITICAL_NAME_END:
+ case BUILT_IN_GOMP_LOOP_END:
+ case BUILT_IN_GOMP_LOOP_END_CANCEL:
+ case BUILT_IN_GOMP_ORDERED_START:
+ case BUILT_IN_GOMP_ORDERED_END:
+ case BUILT_IN_GOMP_SECTIONS_END:
+ case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
+ case BUILT_IN_GOMP_SINGLE_COPY_START:
+ case BUILT_IN_GOMP_SINGLE_COPY_END:
+ return 1;
+
+ default:
+ return -1;
+ }
+ return -1;
+}
+
/* If the call CALL may use the memory reference REF return true,
otherwise return false. */
@@ -2650,222 +2790,13 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref, bool tbaa_p)
&& !is_global_var (base))
goto process_args;
- /* Handle those builtin functions explicitly that do not act as
- escape points. See tree-ssa-structalias.c:find_func_aliases
- for the list of builtins we might need to handle here. */
- if (callee != NULL_TREE
- && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
- switch (DECL_FUNCTION_CODE (callee))
- {
- /* All the following functions read memory pointed to by
- their second argument. strcat/strncat additionally
- reads memory pointed to by the first argument. */
- case BUILT_IN_STRCAT:
- case BUILT_IN_STRNCAT:
- {
- ao_ref dref;
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- NULL_TREE);
- if (refs_may_alias_p_1 (&dref, ref, false))
- return true;
- }
- /* FALLTHRU */
- case BUILT_IN_STRCPY:
- case BUILT_IN_STRNCPY:
- case BUILT_IN_MEMCPY:
- case BUILT_IN_MEMMOVE:
- case BUILT_IN_MEMPCPY:
- case BUILT_IN_STPCPY:
- case BUILT_IN_STPNCPY:
- case BUILT_IN_TM_MEMCPY:
- case BUILT_IN_TM_MEMMOVE:
- {
- ao_ref dref;
- tree size = NULL_TREE;
- if (gimple_call_num_args (call) == 3)
- size = gimple_call_arg (call, 2);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 1),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- case BUILT_IN_STRCAT_CHK:
- case BUILT_IN_STRNCAT_CHK:
- {
- ao_ref dref;
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- NULL_TREE);
- if (refs_may_alias_p_1 (&dref, ref, false))
- return true;
- }
- /* FALLTHRU */
- case BUILT_IN_STRCPY_CHK:
- case BUILT_IN_STRNCPY_CHK:
- case BUILT_IN_MEMCPY_CHK:
- case BUILT_IN_MEMMOVE_CHK:
- case BUILT_IN_MEMPCPY_CHK:
- case BUILT_IN_STPCPY_CHK:
- case BUILT_IN_STPNCPY_CHK:
- {
- ao_ref dref;
- tree size = NULL_TREE;
- if (gimple_call_num_args (call) == 4)
- size = gimple_call_arg (call, 2);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 1),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- case BUILT_IN_BCOPY:
- {
- ao_ref dref;
- tree size = gimple_call_arg (call, 2);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
-
- /* The following functions read memory pointed to by their
- first argument. */
- CASE_BUILT_IN_TM_LOAD (1):
- CASE_BUILT_IN_TM_LOAD (2):
- CASE_BUILT_IN_TM_LOAD (4):
- CASE_BUILT_IN_TM_LOAD (8):
- CASE_BUILT_IN_TM_LOAD (FLOAT):
- CASE_BUILT_IN_TM_LOAD (DOUBLE):
- CASE_BUILT_IN_TM_LOAD (LDOUBLE):
- CASE_BUILT_IN_TM_LOAD (M64):
- CASE_BUILT_IN_TM_LOAD (M128):
- CASE_BUILT_IN_TM_LOAD (M256):
- case BUILT_IN_TM_LOG:
- case BUILT_IN_TM_LOG_1:
- case BUILT_IN_TM_LOG_2:
- case BUILT_IN_TM_LOG_4:
- case BUILT_IN_TM_LOG_8:
- case BUILT_IN_TM_LOG_FLOAT:
- case BUILT_IN_TM_LOG_DOUBLE:
- case BUILT_IN_TM_LOG_LDOUBLE:
- case BUILT_IN_TM_LOG_M64:
- case BUILT_IN_TM_LOG_M128:
- case BUILT_IN_TM_LOG_M256:
- return ptr_deref_may_alias_ref_p_1 (gimple_call_arg (call, 0), ref);
-
- /* These read memory pointed to by the first argument. */
- case BUILT_IN_STRDUP:
- case BUILT_IN_STRNDUP:
- case BUILT_IN_REALLOC:
- {
- ao_ref dref;
- tree size = NULL_TREE;
- if (gimple_call_num_args (call) == 2)
- size = gimple_call_arg (call, 1);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- /* These read memory pointed to by the first argument. */
- case BUILT_IN_INDEX:
- case BUILT_IN_STRCHR:
- case BUILT_IN_STRRCHR:
- {
- ao_ref dref;
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- NULL_TREE);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- /* These read memory pointed to by the first argument with size
- in the third argument. */
- case BUILT_IN_MEMCHR:
- {
- ao_ref dref;
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- gimple_call_arg (call, 2));
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- /* These read memory pointed to by the first and second arguments. */
- case BUILT_IN_STRSTR:
- case BUILT_IN_STRPBRK:
- {
- ao_ref dref;
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- NULL_TREE);
- if (refs_may_alias_p_1 (&dref, ref, false))
- return true;
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 1),
- NULL_TREE);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
-
- /* The following builtins do not read from memory. */
- case BUILT_IN_FREE:
- case BUILT_IN_MALLOC:
- case BUILT_IN_POSIX_MEMALIGN:
- case BUILT_IN_ALIGNED_ALLOC:
- case BUILT_IN_CALLOC:
- CASE_BUILT_IN_ALLOCA:
- case BUILT_IN_STACK_SAVE:
- case BUILT_IN_STACK_RESTORE:
- case BUILT_IN_MEMSET:
- case BUILT_IN_TM_MEMSET:
- case BUILT_IN_MEMSET_CHK:
- case BUILT_IN_FREXP:
- case BUILT_IN_FREXPF:
- case BUILT_IN_FREXPL:
- case BUILT_IN_GAMMA_R:
- case BUILT_IN_GAMMAF_R:
- case BUILT_IN_GAMMAL_R:
- case BUILT_IN_LGAMMA_R:
- case BUILT_IN_LGAMMAF_R:
- case BUILT_IN_LGAMMAL_R:
- case BUILT_IN_MODF:
- case BUILT_IN_MODFF:
- case BUILT_IN_MODFL:
- case BUILT_IN_REMQUO:
- case BUILT_IN_REMQUOF:
- case BUILT_IN_REMQUOL:
- case BUILT_IN_SINCOS:
- case BUILT_IN_SINCOSF:
- case BUILT_IN_SINCOSL:
- case BUILT_IN_ASSUME_ALIGNED:
- case BUILT_IN_VA_END:
- return false;
- /* __sync_* builtins and some OpenMP builtins act as threading
- barriers. */
-#undef DEF_SYNC_BUILTIN
-#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
-#include "sync-builtins.def"
-#undef DEF_SYNC_BUILTIN
- case BUILT_IN_GOMP_ATOMIC_START:
- case BUILT_IN_GOMP_ATOMIC_END:
- case BUILT_IN_GOMP_BARRIER:
- case BUILT_IN_GOMP_BARRIER_CANCEL:
- case BUILT_IN_GOMP_TASKWAIT:
- case BUILT_IN_GOMP_TASKGROUP_END:
- case BUILT_IN_GOMP_CRITICAL_START:
- case BUILT_IN_GOMP_CRITICAL_END:
- case BUILT_IN_GOMP_CRITICAL_NAME_START:
- case BUILT_IN_GOMP_CRITICAL_NAME_END:
- case BUILT_IN_GOMP_LOOP_END:
- case BUILT_IN_GOMP_LOOP_END_CANCEL:
- case BUILT_IN_GOMP_ORDERED_START:
- case BUILT_IN_GOMP_ORDERED_END:
- case BUILT_IN_GOMP_SECTIONS_END:
- case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
- case BUILT_IN_GOMP_SINGLE_COPY_START:
- case BUILT_IN_GOMP_SINGLE_COPY_END:
- return true;
-
- default:
- /* Fallthru to general call handling. */;
- }
+ if (int res = check_fnspec (call, ref, false))
+ {
+ if (res == 1)
+ return true;
+ }
+ else
+ goto process_args;
/* Check if base is a global static variable that is not read
by the function. */
@@ -3040,7 +2971,9 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p)
modref_summary *summary = get_modref_function_summary (node);
if (summary)
{
- if (!modref_may_conflict (call, summary->stores, ref, tbaa_p))
+ if (!modref_may_conflict (call, summary->stores, ref, tbaa_p)
+ && (!summary->writes_errno
+ || !targetm.ref_may_alias_errno (ref)))
{
alias_stats.modref_clobber_no_alias++;
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3104,205 +3037,13 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p)
&& SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base, 0)))
return false;
- /* Handle those builtin functions explicitly that do not act as
- escape points. See tree-ssa-structalias.c:find_func_aliases
- for the list of builtins we might need to handle here. */
- if (callee != NULL_TREE
- && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
- switch (DECL_FUNCTION_CODE (callee))
- {
- /* All the following functions clobber memory pointed to by
- their first argument. */
- case BUILT_IN_STRCPY:
- case BUILT_IN_STRNCPY:
- case BUILT_IN_MEMCPY:
- case BUILT_IN_MEMMOVE:
- case BUILT_IN_MEMPCPY:
- case BUILT_IN_STPCPY:
- case BUILT_IN_STPNCPY:
- case BUILT_IN_STRCAT:
- case BUILT_IN_STRNCAT:
- case BUILT_IN_MEMSET:
- case BUILT_IN_TM_MEMSET:
- CASE_BUILT_IN_TM_STORE (1):
- CASE_BUILT_IN_TM_STORE (2):
- CASE_BUILT_IN_TM_STORE (4):
- CASE_BUILT_IN_TM_STORE (8):
- CASE_BUILT_IN_TM_STORE (FLOAT):
- CASE_BUILT_IN_TM_STORE (DOUBLE):
- CASE_BUILT_IN_TM_STORE (LDOUBLE):
- CASE_BUILT_IN_TM_STORE (M64):
- CASE_BUILT_IN_TM_STORE (M128):
- CASE_BUILT_IN_TM_STORE (M256):
- case BUILT_IN_TM_MEMCPY:
- case BUILT_IN_TM_MEMMOVE:
- {
- ao_ref dref;
- tree size = NULL_TREE;
- /* Don't pass in size for strncat, as the maximum size
- is strlen (dest) + n + 1 instead of n, resp.
- n + 1 at dest + strlen (dest), but strlen (dest) isn't
- known. */
- if (gimple_call_num_args (call) == 3
- && DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT)
- size = gimple_call_arg (call, 2);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- case BUILT_IN_STRCPY_CHK:
- case BUILT_IN_STRNCPY_CHK:
- case BUILT_IN_MEMCPY_CHK:
- case BUILT_IN_MEMMOVE_CHK:
- case BUILT_IN_MEMPCPY_CHK:
- case BUILT_IN_STPCPY_CHK:
- case BUILT_IN_STPNCPY_CHK:
- case BUILT_IN_STRCAT_CHK:
- case BUILT_IN_STRNCAT_CHK:
- case BUILT_IN_MEMSET_CHK:
- {
- ao_ref dref;
- tree size = NULL_TREE;
- /* Don't pass in size for __strncat_chk, as the maximum size
- is strlen (dest) + n + 1 instead of n, resp.
- n + 1 at dest + strlen (dest), but strlen (dest) isn't
- known. */
- if (gimple_call_num_args (call) == 4
- && DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT_CHK)
- size = gimple_call_arg (call, 2);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 0),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- case BUILT_IN_BCOPY:
- {
- ao_ref dref;
- tree size = gimple_call_arg (call, 2);
- ao_ref_init_from_ptr_and_size (&dref,
- gimple_call_arg (call, 1),
- size);
- return refs_may_alias_p_1 (&dref, ref, false);
- }
- /* Allocating memory does not have any side-effects apart from
- being the definition point for the pointer. */
- case BUILT_IN_MALLOC:
- case BUILT_IN_ALIGNED_ALLOC:
- case BUILT_IN_CALLOC:
- case BUILT_IN_STRDUP:
- case BUILT_IN_STRNDUP:
- /* Unix98 specifies that errno is set on allocation failure. */
- if (flag_errno_math
- && targetm.ref_may_alias_errno (ref))
- return true;
- return false;
- case BUILT_IN_STACK_SAVE:
- CASE_BUILT_IN_ALLOCA:
- case BUILT_IN_ASSUME_ALIGNED:
- return false;
- /* But posix_memalign stores a pointer into the memory pointed to
- by its first argument. */
- case BUILT_IN_POSIX_MEMALIGN:
- {
- tree ptrptr = gimple_call_arg (call, 0);
- ao_ref dref;
- ao_ref_init_from_ptr_and_size (&dref, ptrptr,
- TYPE_SIZE_UNIT (ptr_type_node));
- return (refs_may_alias_p_1 (&dref, ref, false)
- || (flag_errno_math
- && targetm.ref_may_alias_errno (ref)));
- }
- /* Freeing memory kills the pointed-to memory. More importantly
- the call has to serve as a barrier for moving loads and stores
- across it. */
- case BUILT_IN_FREE:
- case BUILT_IN_VA_END:
- {
- tree ptr = gimple_call_arg (call, 0);
- return ptr_deref_may_alias_ref_p_1 (ptr, ref);
- }
- /* Realloc serves both as allocation point and deallocation point. */
- case BUILT_IN_REALLOC:
- {
- tree ptr = gimple_call_arg (call, 0);
- /* Unix98 specifies that errno is set on allocation failure. */
- return ((flag_errno_math
- && targetm.ref_may_alias_errno (ref))
- || ptr_deref_may_alias_ref_p_1 (ptr, ref));
- }
- case BUILT_IN_GAMMA_R:
- case BUILT_IN_GAMMAF_R:
- case BUILT_IN_GAMMAL_R:
- case BUILT_IN_LGAMMA_R:
- case BUILT_IN_LGAMMAF_R:
- case BUILT_IN_LGAMMAL_R:
- {
- tree out = gimple_call_arg (call, 1);
- if (ptr_deref_may_alias_ref_p_1 (out, ref))
- return true;
- if (flag_errno_math)
- break;
- return false;
- }
- case BUILT_IN_FREXP:
- case BUILT_IN_FREXPF:
- case BUILT_IN_FREXPL:
- case BUILT_IN_MODF:
- case BUILT_IN_MODFF:
- case BUILT_IN_MODFL:
- {
- tree out = gimple_call_arg (call, 1);
- return ptr_deref_may_alias_ref_p_1 (out, ref);
- }
- case BUILT_IN_REMQUO:
- case BUILT_IN_REMQUOF:
- case BUILT_IN_REMQUOL:
- {
- tree out = gimple_call_arg (call, 2);
- if (ptr_deref_may_alias_ref_p_1 (out, ref))
- return true;
- if (flag_errno_math)
- break;
- return false;
- }
- case BUILT_IN_SINCOS:
- case BUILT_IN_SINCOSF:
- case BUILT_IN_SINCOSL:
- {
- tree sin = gimple_call_arg (call, 1);
- tree cos = gimple_call_arg (call, 2);
- return (ptr_deref_may_alias_ref_p_1 (sin, ref)
- || ptr_deref_may_alias_ref_p_1 (cos, ref));
- }
- /* __sync_* builtins and some OpenMP builtins act as threading
- barriers. */
-#undef DEF_SYNC_BUILTIN
-#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
-#include "sync-builtins.def"
-#undef DEF_SYNC_BUILTIN
- case BUILT_IN_GOMP_ATOMIC_START:
- case BUILT_IN_GOMP_ATOMIC_END:
- case BUILT_IN_GOMP_BARRIER:
- case BUILT_IN_GOMP_BARRIER_CANCEL:
- case BUILT_IN_GOMP_TASKWAIT:
- case BUILT_IN_GOMP_TASKGROUP_END:
- case BUILT_IN_GOMP_CRITICAL_START:
- case BUILT_IN_GOMP_CRITICAL_END:
- case BUILT_IN_GOMP_CRITICAL_NAME_START:
- case BUILT_IN_GOMP_CRITICAL_NAME_END:
- case BUILT_IN_GOMP_LOOP_END:
- case BUILT_IN_GOMP_LOOP_END_CANCEL:
- case BUILT_IN_GOMP_ORDERED_START:
- case BUILT_IN_GOMP_ORDERED_END:
- case BUILT_IN_GOMP_SECTIONS_END:
- case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
- case BUILT_IN_GOMP_SINGLE_COPY_START:
- case BUILT_IN_GOMP_SINGLE_COPY_END:
- return true;
- default:
- /* Fallthru to general call handling. */;
- }
+ if (int res = check_fnspec (call, ref, true))
+ {
+ if (res == 1)
+ return true;
+ }
+ else
+ return false;
/* Check if base is a global static variable that is not written
by the function. */
@@ -4079,6 +3820,8 @@ void
attr_fnspec::verify ()
{
bool err = false;
+ if (!len)
+ return;
/* Check return value specifier. */
if (len < return_desc_size)
@@ -4086,14 +3829,22 @@ attr_fnspec::verify ()
else if ((len - return_desc_size) % arg_desc_size)
err = true;
else if ((str[0] < '1' || str[0] > '4')
- && str[0] != '.' && str[0] != 'm'
- /* FIXME: Fortran trans-decl.c contains multiple wrong fnspec
- strings. The following characters have no meaning. */
- && str[0] != 'R' && str[0] != 'W')
+ && str[0] != '.' && str[0] != 'm')
err = true;
- if (str[1] != ' ')
- err = true;
+ switch (str[1])
+ {
+ case ' ':
+ case 'p':
+ case 'P':
+ case 'c':
+ case 'C':
+ break;
+ default:
+ err = true;
+ }
+ if (err)
+ internal_error ("invalid fn spec attribute \"%s\"", str);
/* Now check all parameters. */
for (unsigned int i = 0; arg_specified_p (i); i++)
@@ -4105,16 +3856,360 @@ attr_fnspec::verify ()
case 'X':
case 'r':
case 'R':
+ case 'o':
+ case 'O':
case 'w':
case 'W':
case '.':
+ if ((str[idx + 1] >= '1' && str[idx + 1] <= '9')
+ || str[idx + 1] == 't')
+ {
+ if (str[idx] != 'r' && str[idx] != 'R'
+ && str[idx] != 'w' && str[idx] != 'W'
+ && str[idx] != 'o' && str[idx] != 'O')
+ err = true;
+ if (str[idx] != 't'
+ /* Size specified is scalar, so it should be described
+ by ". " if specified at all. */
+ && (arg_specified_p (str[idx + 1] - '1')
+ && str[arg_idx (str[idx + 1] - '1')] != '.'))
+ err = true;
+ }
+ else if (str[idx + 1] != ' ')
+ err = true;
break;
default:
- err = true;
+ if (str[idx] < '1' || str[idx] > '9')
+ err = true;
}
- if (str[idx + 1] != ' ')
- err = true;
+ if (err)
+ internal_error ("invalid fn spec attribute \"%s\" arg %i", str, i);
+ }
+}
+
+/* Return ture if TYPE1 and TYPE2 will always give the same answer
+ when compared wit hother types using same_type_for_tbaa_p. */
+
+static bool
+types_equal_for_same_type_for_tbaa_p (tree type1, tree type2,
+ bool lto_streaming_safe)
+{
+ /* We use same_type_for_tbaa_p to match types in the access path.
+ This check is overly conservative. */
+ type1 = TYPE_MAIN_VARIANT (type1);
+ type2 = TYPE_MAIN_VARIANT (type2);
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (type1)
+ != TYPE_STRUCTURAL_EQUALITY_P (type2))
+ return false;
+ if (TYPE_STRUCTURAL_EQUALITY_P (type1))
+ return true;
+
+ if (lto_streaming_safe)
+ return type1 == type2;
+ else
+ return TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2);
+}
+
+/* Compare REF1 and REF2 and return flags specifying their differences.
+ If LTO_STREAMING_SAFE is true do not use alias sets and canonical
+ types that are going to be recomputed.
+ If TBAA is true also compare TBAA metadata. */
+
+int
+ao_compare::compare_ao_refs (ao_ref *ref1, ao_ref *ref2,
+ bool lto_streaming_safe,
+ bool tbaa)
+{
+ if (TREE_THIS_VOLATILE (ref1->ref) != TREE_THIS_VOLATILE (ref2->ref))
+ return SEMANTICS;
+ tree base1 = ao_ref_base (ref1);
+ tree base2 = ao_ref_base (ref2);
+
+ if (!known_eq (ref1->offset, ref2->offset)
+ || !known_eq (ref1->size, ref2->size)
+ || !known_eq (ref1->max_size, ref2->max_size))
+ return SEMANTICS;
+
+ /* For variable accesses we need to compare actual paths
+ to check that both refs are accessing same address and the access size. */
+ if (!known_eq (ref1->size, ref1->max_size))
+ {
+ if (!operand_equal_p (TYPE_SIZE (TREE_TYPE (ref1->ref)),
+ TYPE_SIZE (TREE_TYPE (ref2->ref)), 0))
+ return SEMANTICS;
+ tree r1 = ref1->ref;
+ tree r2 = ref2->ref;
+
+ /* Handle toplevel COMPONENT_REFs of bitfields.
+ Those are special since they are not allowed in
+ ADDR_EXPR. */
+ if (TREE_CODE (r1) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (r1, 1)))
+ {
+ if (TREE_CODE (r2) != COMPONENT_REF
+ || !DECL_BIT_FIELD (TREE_OPERAND (r2, 1)))
+ return SEMANTICS;
+ tree field1 = TREE_OPERAND (r1, 1);
+ tree field2 = TREE_OPERAND (r2, 1);
+ if (!operand_equal_p (DECL_FIELD_OFFSET (field1),
+ DECL_FIELD_OFFSET (field2), 0)
+ || !operand_equal_p (DECL_FIELD_BIT_OFFSET (field1),
+ DECL_FIELD_BIT_OFFSET (field2), 0)
+ || !operand_equal_p (DECL_SIZE (field1), DECL_SIZE (field2), 0)
+ || !types_compatible_p (TREE_TYPE (r1),
+ TREE_TYPE (r2)))
+ return SEMANTICS;
+ r1 = TREE_OPERAND (r1, 0);
+ r2 = TREE_OPERAND (r2, 0);
+ }
+ else if (TREE_CODE (r2) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (r2, 1)))
+ return SEMANTICS;
+
+ /* Similarly for bit field refs. */
+ if (TREE_CODE (r1) == BIT_FIELD_REF)
+ {
+ if (TREE_CODE (r2) != BIT_FIELD_REF
+ || !operand_equal_p (TREE_OPERAND (r1, 1),
+ TREE_OPERAND (r2, 1), 0)
+ || !operand_equal_p (TREE_OPERAND (r1, 2),
+ TREE_OPERAND (r2, 2), 0)
+ || !types_compatible_p (TREE_TYPE (r1),
+ TREE_TYPE (r2)))
+ return SEMANTICS;
+ r1 = TREE_OPERAND (r1, 0);
+ r2 = TREE_OPERAND (r2, 0);
+ }
+ else if (TREE_CODE (r2) == BIT_FIELD_REF)
+ return SEMANTICS;
+
+ /* Now we can compare the address of actual memory access. */
+ if (!operand_equal_p (r1, r2, OEP_ADDRESS_OF | OEP_MATCH_SIDE_EFFECTS))
+ return SEMANTICS;
+ }
+ /* For constant accesses we get more matches by comparing offset only. */
+ else if (!operand_equal_p (base1, base2,
+ OEP_ADDRESS_OF | OEP_MATCH_SIDE_EFFECTS))
+ return SEMANTICS;
+
+ /* We can't simply use get_object_alignment_1 on the full
+ reference as for accesses with variable indexes this reports
+ too conservative alignment. */
+ unsigned int align1, align2;
+ unsigned HOST_WIDE_INT bitpos1, bitpos2;
+ bool known1 = get_object_alignment_1 (base1, &align1, &bitpos1);
+ bool known2 = get_object_alignment_1 (base2, &align2, &bitpos2);
+ /* ??? For MEMREF get_object_alignment_1 determines aligned from
+ TYPE_ALIGN but still returns false. This seem to contradict
+ its description. So compare even if alignment is unknown. */
+ if (known1 != known2
+ || (bitpos1 != bitpos2 || align1 != align2))
+ return SEMANTICS;
+
+ /* Now we know that accesses are semantically same. */
+ int flags = 0;
+
+ /* ao_ref_base strips inner MEM_REF [&decl], recover from that here. */
+ tree rbase1 = ref1->ref;
+ if (rbase1)
+ while (handled_component_p (rbase1))
+ rbase1 = TREE_OPERAND (rbase1, 0);
+ tree rbase2 = ref2->ref;
+ while (handled_component_p (rbase2))
+ rbase2 = TREE_OPERAND (rbase2, 0);
+
+ /* MEM_REFs and TARGET_MEM_REFs record dependence cliques which are used to
+ implement restrict pointers. MR_DEPENDENCE_CLIQUE 0 means no information.
+ Otherwise we need to match bases and cliques. */
+ if ((((TREE_CODE (rbase1) == MEM_REF || TREE_CODE (rbase1) == TARGET_MEM_REF)
+ && MR_DEPENDENCE_CLIQUE (rbase1))
+ || ((TREE_CODE (rbase2) == MEM_REF || TREE_CODE (rbase2) == TARGET_MEM_REF)
+ && MR_DEPENDENCE_CLIQUE (rbase2)))
+ && (TREE_CODE (rbase1) != TREE_CODE (rbase2)
+ || MR_DEPENDENCE_CLIQUE (rbase1) != MR_DEPENDENCE_CLIQUE (rbase2)
+ || (MR_DEPENDENCE_BASE (rbase1) != MR_DEPENDENCE_BASE (rbase2))))
+ flags |= DEPENDENCE_CLIQUE;
+
+ if (!tbaa)
+ return flags;
+
+ /* Alias sets are not stable across LTO sreaming; be conservative here
+ and compare types the alias sets are ultimately based on. */
+ if (lto_streaming_safe)
+ {
+ tree t1 = ao_ref_alias_ptr_type (ref1);
+ tree t2 = ao_ref_alias_ptr_type (ref2);
+ if (!alias_ptr_types_compatible_p (t1, t2))
+ flags |= REF_ALIAS_SET;
+
+ t1 = ao_ref_base_alias_ptr_type (ref1);
+ t2 = ao_ref_base_alias_ptr_type (ref2);
+ if (!alias_ptr_types_compatible_p (t1, t2))
+ flags |= BASE_ALIAS_SET;
+ }
+ else
+ {
+ if (ao_ref_alias_set (ref1) != ao_ref_alias_set (ref2))
+ flags |= REF_ALIAS_SET;
+ if (ao_ref_base_alias_set (ref1) != ao_ref_base_alias_set (ref2))
+ flags |= BASE_ALIAS_SET;
+ }
+
+ /* Access path is used only on non-view-converted references. */
+ bool view_converted = view_converted_memref_p (rbase1);
+ if (view_converted_memref_p (rbase2) != view_converted)
+ return flags | ACCESS_PATH;
+ else if (view_converted)
+ return flags;
+
+
+ /* Find start of access paths and look for trailing arrays. */
+ tree c1 = ref1->ref, c2 = ref2->ref;
+ tree end_struct_ref1 = NULL, end_struct_ref2 = NULL;
+ int nskipped1 = 0, nskipped2 = 0;
+ int i = 0;
+
+ for (tree p1 = ref1->ref; handled_component_p (p1); p1 = TREE_OPERAND (p1, 0))
+ {
+ if (component_ref_to_zero_sized_trailing_array_p (p1))
+ end_struct_ref1 = p1;
+ if (ends_tbaa_access_path_p (p1))
+ c1 = p1, nskipped1 = i;
+ i++;
+ }
+ for (tree p2 = ref2->ref; handled_component_p (p2); p2 = TREE_OPERAND (p2, 0))
+ {
+ if (component_ref_to_zero_sized_trailing_array_p (p2))
+ end_struct_ref2 = p2;
+ if (ends_tbaa_access_path_p (p2))
+ c2 = p2, nskipped1 = i;
+ i++;
+ }
+
+ /* For variable accesses we can not rely on offset match bellow.
+ We know that paths are struturally same, so only check that
+ starts of TBAA paths did not diverge. */
+ if (!known_eq (ref1->size, ref1->max_size)
+ && nskipped1 != nskipped2)
+ return flags | ACCESS_PATH;
+
+ /* Information about trailing refs is used by
+ aliasing_component_refs_p that is applied only if paths
+ has handled components.. */
+ if (!handled_component_p (c1) && !handled_component_p (c2))
+ ;
+ else if ((end_struct_ref1 != NULL) != (end_struct_ref2 != NULL))
+ return flags | ACCESS_PATH;
+ if (end_struct_ref1
+ && TYPE_MAIN_VARIANT (TREE_TYPE (end_struct_ref1))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (end_struct_ref2)))
+ return flags | ACCESS_PATH;
+
+ /* Now compare all handled components of the access path.
+ We have three oracles that cares about access paths:
+ - aliasing_component_refs_p
+ - nonoverlapping_refs_since_match_p
+ - nonoverlapping_component_refs_p
+ We need to match things these oracles compare.
+
+ It is only necessary to check types for compatibility
+ and offsets. Rest of what oracles compares are actual
+ addresses. Those are already known to be same:
+ - for constant accesses we check offsets
+ - for variable accesses we already matched
+ the path lexically with operand_equal_p. */
+ while (true)
+ {
+ bool comp1 = handled_component_p (c1);
+ bool comp2 = handled_component_p (c2);
+
+ if (comp1 != comp2)
+ return flags | ACCESS_PATH;
+ if (!comp1)
+ break;
+
+ if (TREE_CODE (c1) != TREE_CODE (c2))
+ return flags | ACCESS_PATH;
+
+ /* aliasing_component_refs_p attempts to find type match within
+ the paths. For that reason both types needs to be equal
+ with respect to same_type_for_tbaa_p. */
+ if (!types_equal_for_same_type_for_tbaa_p (TREE_TYPE (c1),
+ TREE_TYPE (c2),
+ lto_streaming_safe))
+ return flags | ACCESS_PATH;
+ if (component_ref_to_zero_sized_trailing_array_p (c1)
+ != component_ref_to_zero_sized_trailing_array_p (c2))
+ return flags | ACCESS_PATH;
+
+ /* aliasing_matching_component_refs_p compares
+ offsets within the path. Other properties are ignored.
+ Do not bother to verify offsets in variable accesses. Here we
+ already compared them by operand_equal_p so they are
+ structurally same. */
+ if (!known_eq (ref1->size, ref1->max_size))
+ {
+ poly_int64 offadj1, sztmc1, msztmc1;
+ bool reverse1;
+ get_ref_base_and_extent (c1, &offadj1, &sztmc1, &msztmc1, &reverse1);
+ poly_int64 offadj2, sztmc2, msztmc2;
+ bool reverse2;
+ get_ref_base_and_extent (c2, &offadj2, &sztmc2, &msztmc2, &reverse2);
+ if (!known_eq (offadj1, offadj2))
+ return flags | ACCESS_PATH;
+ }
+ c1 = TREE_OPERAND (c1, 0);
+ c2 = TREE_OPERAND (c2, 0);
+ }
+ /* Finally test the access type. */
+ if (!types_equal_for_same_type_for_tbaa_p (TREE_TYPE (c1),
+ TREE_TYPE (c2),
+ lto_streaming_safe))
+ return flags | ACCESS_PATH;
+ return flags;
+}
+
+/* Hash REF to HSTATE. If LTO_STREAMING_SAFE do not use alias sets
+ and canonical types. */
+void
+ao_compare::hash_ao_ref (ao_ref *ref, bool lto_streaming_safe, bool tbaa,
+ inchash::hash &hstate)
+{
+ tree base = ao_ref_base (ref);
+ tree tbase = base;
+
+ if (!known_eq (ref->size, ref->max_size))
+ {
+ tree r = ref->ref;
+ if (TREE_CODE (r) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (r, 1)))
+ {
+ tree field = TREE_OPERAND (r, 1);
+ hash_operand (DECL_FIELD_OFFSET (field), hstate, 0);
+ hash_operand (DECL_FIELD_BIT_OFFSET (field), hstate, 0);
+ hash_operand (DECL_SIZE (field), hstate, 0);
+ r = TREE_OPERAND (r, 0);
+ }
+ if (TREE_CODE (r) == BIT_FIELD_REF)
+ {
+ hash_operand (TREE_OPERAND (r, 1), hstate, 0);
+ hash_operand (TREE_OPERAND (r, 2), hstate, 0);
+ r = TREE_OPERAND (r, 0);
+ }
+ hash_operand (TYPE_SIZE (TREE_TYPE (ref->ref)), hstate, 0);
+ hash_operand (r, hstate, OEP_ADDRESS_OF | OEP_MATCH_SIDE_EFFECTS);
+ }
+ else
+ {
+ hash_operand (tbase, hstate, OEP_ADDRESS_OF | OEP_MATCH_SIDE_EFFECTS);
+ hstate.add_poly_int (ref->offset);
+ hstate.add_poly_int (ref->size);
+ hstate.add_poly_int (ref->max_size);
+ }
+ if (!lto_streaming_safe && tbaa)
+ {
+ hstate.add_int (ao_ref_alias_set (ref));
+ hstate.add_int (ao_ref_base_alias_set (ref));
}
- if (err)
- internal_error ("invalid fn spec attribute \"%s\"", str);
}
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index 1561ead..830ac1b 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -114,6 +114,8 @@ extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
extern tree ao_ref_base (ao_ref *);
extern alias_set_type ao_ref_alias_set (ao_ref *);
extern alias_set_type ao_ref_base_alias_set (ao_ref *);
+extern tree ao_ref_alias_ptr_type (ao_ref *);
+extern tree ao_ref_base_alias_ptr_type (ao_ref *);
extern bool ptr_deref_may_alias_global_p (tree);
extern bool ptr_derefs_may_alias_p (tree, tree);
extern bool ptrs_compare_unequal (tree, tree);
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 0432fe5..466be20 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1432,13 +1432,7 @@ bit_value_binop (enum tree_code code, signop sgn, int width,
else
{
if (wi::neg_p (shift))
- {
- shift = -shift;
- if (code == RSHIFT_EXPR)
- code = LSHIFT_EXPR;
- else
- code = RSHIFT_EXPR;
- }
+ break;
if (code == RSHIFT_EXPR)
{
*mask = wi::rshift (wi::ext (r1mask, width, sgn), shift, sgn);
@@ -1796,6 +1790,7 @@ evaluate_stmt (gimple *stmt)
ccp_lattice_t likelyvalue = likely_value (stmt);
bool is_constant = false;
unsigned int align;
+ bool ignore_return_flags = false;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1965,25 +1960,13 @@ evaluate_stmt (gimple *stmt)
val.mask = ~((HOST_WIDE_INT) align / BITS_PER_UNIT - 1);
break;
- /* These builtins return their first argument, unmodified. */
- case BUILT_IN_MEMCPY:
- case BUILT_IN_MEMMOVE:
- case BUILT_IN_MEMSET:
- case BUILT_IN_STRCPY:
- case BUILT_IN_STRNCPY:
- case BUILT_IN_MEMCPY_CHK:
- case BUILT_IN_MEMMOVE_CHK:
- case BUILT_IN_MEMSET_CHK:
- case BUILT_IN_STRCPY_CHK:
- case BUILT_IN_STRNCPY_CHK:
- val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
- break;
-
case BUILT_IN_ASSUME_ALIGNED:
val = bit_value_assume_aligned (stmt, NULL_TREE, val, false);
+ ignore_return_flags = true;
break;
case BUILT_IN_ALIGNED_ALLOC:
+ case BUILT_IN_GOMP_ALLOC:
{
tree align = get_constant_value (gimple_call_arg (stmt, 0));
if (align
@@ -2049,6 +2032,15 @@ evaluate_stmt (gimple *stmt)
if (attrs)
val = bit_value_assume_aligned (stmt, attrs, val, true);
}
+ int flags = ignore_return_flags
+ ? 0 : gimple_call_return_flags (as_a <gcall *> (stmt));
+ if (flags & ERF_RETURNS_ARG
+ && (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt))
+ {
+ val = get_value_for_expr
+ (gimple_call_arg (stmt,
+ flags & ERF_RETURN_ARG_MASK), true);
+ }
}
is_constant = (val.lattice_val == CONSTANT);
}
@@ -3586,7 +3578,7 @@ pass_post_ipa_warn::execute (function *fun)
continue;
tree fndecl = gimple_call_fndecl (stmt);
- if (fndecl && DECL_IS_BUILTIN (fndecl))
+ if (fndecl && DECL_IS_UNDECLARED_BUILTIN (fndecl))
inform (loc, "in a call to built-in function %qD",
fndecl);
else if (fndecl)
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index a046612..5ec8729 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -239,6 +239,7 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
CASE_BUILT_IN_ALLOCA:
case BUILT_IN_STRDUP:
case BUILT_IN_STRNDUP:
+ case BUILT_IN_GOMP_ALLOC:
return;
default:;
@@ -605,6 +606,8 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
case BUILT_IN_CALLOC:
CASE_BUILT_IN_ALLOCA:
case BUILT_IN_FREE:
+ case BUILT_IN_GOMP_ALLOC:
+ case BUILT_IN_GOMP_FREE:
return false;
default:;
@@ -653,67 +656,7 @@ valid_new_delete_pair_p (gimple *new_call, gimple *delete_call)
{
tree new_asm = DECL_ASSEMBLER_NAME (gimple_call_fndecl (new_call));
tree delete_asm = DECL_ASSEMBLER_NAME (gimple_call_fndecl (delete_call));
- const char *new_name = IDENTIFIER_POINTER (new_asm);
- const char *delete_name = IDENTIFIER_POINTER (delete_asm);
- unsigned int new_len = IDENTIFIER_LENGTH (new_asm);
- unsigned int delete_len = IDENTIFIER_LENGTH (delete_asm);
-
- if (new_len < 5 || delete_len < 6)
- return false;
- if (new_name[0] == '_')
- ++new_name, --new_len;
- if (new_name[0] == '_')
- ++new_name, --new_len;
- if (delete_name[0] == '_')
- ++delete_name, --delete_len;
- if (delete_name[0] == '_')
- ++delete_name, --delete_len;
- if (new_len < 4 || delete_len < 5)
- return false;
- /* *_len is now just the length after initial underscores. */
- if (new_name[0] != 'Z' || new_name[1] != 'n')
- return false;
- if (delete_name[0] != 'Z' || delete_name[1] != 'd')
- return false;
- /* _Znw must match _Zdl, _Zna must match _Zda. */
- if ((new_name[2] != 'w' || delete_name[2] != 'l')
- && (new_name[2] != 'a' || delete_name[2] != 'a'))
- return false;
- /* 'j', 'm' and 'y' correspond to size_t. */
- if (new_name[3] != 'j' && new_name[3] != 'm' && new_name[3] != 'y')
- return false;
- if (delete_name[3] != 'P' || delete_name[4] != 'v')
- return false;
- if (new_len == 4
- || (new_len == 18 && !memcmp (new_name + 4, "RKSt9nothrow_t", 14)))
- {
- /* _ZnXY or _ZnXYRKSt9nothrow_t matches
- _ZdXPv, _ZdXPvY and _ZdXPvRKSt9nothrow_t. */
- if (delete_len == 5)
- return true;
- if (delete_len == 6 && delete_name[5] == new_name[3])
- return true;
- if (delete_len == 19 && !memcmp (delete_name + 5, "RKSt9nothrow_t", 14))
- return true;
- }
- else if ((new_len == 19 && !memcmp (new_name + 4, "St11align_val_t", 15))
- || (new_len == 33
- && !memcmp (new_name + 4, "St11align_val_tRKSt9nothrow_t", 29)))
- {
- /* _ZnXYSt11align_val_t or _ZnXYSt11align_val_tRKSt9nothrow_t matches
- _ZdXPvSt11align_val_t or _ZdXPvYSt11align_val_t or or
- _ZdXPvSt11align_val_tRKSt9nothrow_t. */
- if (delete_len == 20 && !memcmp (delete_name + 5, "St11align_val_t", 15))
- return true;
- if (delete_len == 21
- && delete_name[5] == new_name[3]
- && !memcmp (delete_name + 6, "St11align_val_t", 15))
- return true;
- if (delete_len == 34
- && !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29))
- return true;
- }
- return false;
+ return valid_new_delete_pair_p (new_asm, delete_asm);
}
/* Propagate necessity using the operands of necessary statements.
@@ -879,7 +822,8 @@ propagate_necessity (bool aggressive)
&& gimple_call_from_new_or_delete (as_a <gcall *> (stmt))
&& gimple_call_operator_delete_p (as_a <gcall *> (stmt)));
if (is_delete_operator
- || gimple_call_builtin_p (stmt, BUILT_IN_FREE))
+ || gimple_call_builtin_p (stmt, BUILT_IN_FREE)
+ || gimple_call_builtin_p (stmt, BUILT_IN_GOMP_FREE))
{
tree ptr = gimple_call_arg (stmt, 0);
gcall *def_stmt;
@@ -892,27 +836,26 @@ propagate_necessity (bool aggressive)
&& ((DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
&& (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_ALIGNED_ALLOC
|| DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
- || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
+ || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC
+ || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_GOMP_ALLOC))
|| (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee)
&& gimple_call_from_new_or_delete (def_stmt))))
{
- if (is_delete_operator)
- {
- if (!valid_new_delete_pair_p (def_stmt, stmt))
- mark_operand_necessary (gimple_call_arg (stmt, 0));
-
- /* Delete operators can have alignment and (or) size
- as next arguments. When being a SSA_NAME, they
- must be marked as necessary. */
- if (gimple_call_num_args (stmt) >= 2)
- for (unsigned i = 1; i < gimple_call_num_args (stmt);
- i++)
- {
- tree arg = gimple_call_arg (stmt, i);
- if (TREE_CODE (arg) == SSA_NAME)
- mark_operand_necessary (arg);
- }
- }
+ if (is_delete_operator
+ && !valid_new_delete_pair_p (def_stmt, stmt))
+ mark_operand_necessary (gimple_call_arg (stmt, 0));
+
+ /* Delete operators can have alignment and (or) size
+ as next arguments. When being a SSA_NAME, they
+ must be marked as necessary. Similarly GOMP_free. */
+ if (gimple_call_num_args (stmt) >= 2)
+ for (unsigned i = 1; i < gimple_call_num_args (stmt);
+ i++)
+ {
+ tree arg = gimple_call_arg (stmt, i);
+ if (TREE_CODE (arg) == SSA_NAME)
+ mark_operand_necessary (arg);
+ }
continue;
}
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 21a9ee4..4cad6fa 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -623,13 +623,43 @@ clear_unused_block_pointer (void)
{
unsigned i;
tree b;
- gimple *stmt = gsi_stmt (gsi);
+ gimple *stmt;
+ next:
+ stmt = gsi_stmt (gsi);
if (!is_gimple_debug (stmt) && !gimple_clobber_p (stmt))
continue;
b = gimple_block (stmt);
if (b && !TREE_USED (b))
- gimple_set_block (stmt, NULL);
+ {
+ /* Elide debug marker stmts that have an associated BLOCK from an
+ inline instance removed with also the outermost scope BLOCK of
+ said inline instance removed. If the outermost scope BLOCK of
+ said inline instance is preserved use that in place of the
+ removed BLOCK. That keeps the marker associated to the correct
+ inline instance (or no inline instance in case it was not from
+ an inline instance). */
+ if (gimple_debug_nonbind_marker_p (stmt)
+ && BLOCK_ABSTRACT_ORIGIN (b))
+ {
+ while (TREE_CODE (b) == BLOCK
+ && !inlined_function_outer_scope_p (b))
+ b = BLOCK_SUPERCONTEXT (b);
+ if (TREE_CODE (b) == BLOCK)
+ {
+ if (TREE_USED (b))
+ {
+ gimple_set_block (stmt, b);
+ continue;
+ }
+ gsi_remove (&gsi, true);
+ if (gsi_end_p (gsi))
+ break;
+ goto next;
+ }
+ }
+ gimple_set_block (stmt, NULL);
+ }
for (i = 0; i < gimple_num_ops (stmt); i++)
walk_tree (gimple_op_ptr (stmt, i), clear_unused_block_pointer_1,
NULL, NULL);
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 6bb07e1..fe48d02 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1622,7 +1622,7 @@ sort_locs_in_loop_postorder_cmp (const void *loc1_, const void *loc2_,
/* Gathers memory references in loops. */
static void
-analyze_memory_references (void)
+analyze_memory_references (bool store_motion)
{
gimple_stmt_iterator bsi;
basic_block bb, *bbs;
@@ -1665,6 +1665,9 @@ analyze_memory_references (void)
free (bbs);
+ if (!store_motion)
+ return;
+
/* Propagate the information about accessed memory references up
the loop hierarchy. */
FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
@@ -2251,7 +2254,8 @@ sm_seq_push_down (vec<seq_entry> &seq, unsigned ptr, unsigned *at)
static int
sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
vec<seq_entry> &seq, bitmap refs_not_in_seq,
- bitmap refs_not_supported, bool forked)
+ bitmap refs_not_supported, bool forked,
+ bitmap fully_visited)
{
if (!vdef)
for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
@@ -2273,7 +2277,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
/* This handles the perfect nest case. */
return sm_seq_valid_bb (loop, single_pred (bb), vdef,
seq, refs_not_in_seq, refs_not_supported,
- forked);
+ forked, fully_visited);
return 0;
}
do
@@ -2311,7 +2315,10 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
return sm_seq_valid_bb (loop, gimple_phi_arg_edge (phi, 0)->src,
gimple_phi_arg_def (phi, 0), seq,
refs_not_in_seq, refs_not_supported,
- false);
+ false, fully_visited);
+ if (bitmap_bit_p (fully_visited,
+ SSA_NAME_VERSION (gimple_phi_result (phi))))
+ return 1;
auto_vec<seq_entry> first_edge_seq;
auto_bitmap tem_refs_not_in_seq (&lim_bitmap_obstack);
int eret;
@@ -2320,7 +2327,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
gimple_phi_arg_def (phi, 0),
first_edge_seq,
tem_refs_not_in_seq, refs_not_supported,
- true);
+ true, fully_visited);
if (eret != 1)
return -1;
/* Simplify our lives by pruning the sequence of !sm_ord. */
@@ -2335,7 +2342,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
bitmap_copy (tem_refs_not_in_seq, refs_not_in_seq);
eret = sm_seq_valid_bb (loop, e->src, vuse, edge_seq,
tem_refs_not_in_seq, refs_not_supported,
- true);
+ true, fully_visited);
if (eret != 1)
return -1;
/* Simplify our lives by pruning the sequence of !sm_ord. */
@@ -2416,6 +2423,8 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
seq[new_idx].from = NULL_TREE;
}
}
+ bitmap_set_bit (fully_visited,
+ SSA_NAME_VERSION (gimple_phi_result (phi)));
return 1;
}
lim_aux_data *data = get_lim_data (def);
@@ -2491,9 +2500,11 @@ hoist_memory_references (class loop *loop, bitmap mem_refs,
seq.create (4);
auto_bitmap refs_not_in_seq (&lim_bitmap_obstack);
bitmap_copy (refs_not_in_seq, mem_refs);
+ auto_bitmap fully_visited;
int res = sm_seq_valid_bb (loop, e->src, NULL_TREE,
seq, refs_not_in_seq,
- refs_not_supported, false);
+ refs_not_supported, false,
+ fully_visited);
if (res != 1)
{
bitmap_copy (refs_not_supported, mem_refs);
@@ -3010,7 +3021,7 @@ fill_always_executed_in (void)
/* Compute the global information needed by the loop invariant motion pass. */
static void
-tree_ssa_lim_initialize (void)
+tree_ssa_lim_initialize (bool store_motion)
{
class loop *loop;
unsigned i;
@@ -3032,8 +3043,12 @@ tree_ssa_lim_initialize (void)
memory_accesses.refs_loaded_in_loop.quick_grow (number_of_loops (cfun));
memory_accesses.refs_stored_in_loop.create (number_of_loops (cfun));
memory_accesses.refs_stored_in_loop.quick_grow (number_of_loops (cfun));
- memory_accesses.all_refs_stored_in_loop.create (number_of_loops (cfun));
- memory_accesses.all_refs_stored_in_loop.quick_grow (number_of_loops (cfun));
+ if (store_motion)
+ {
+ memory_accesses.all_refs_stored_in_loop.create (number_of_loops (cfun));
+ memory_accesses.all_refs_stored_in_loop.quick_grow
+ (number_of_loops (cfun));
+ }
for (i = 0; i < number_of_loops (cfun); i++)
{
@@ -3041,8 +3056,9 @@ tree_ssa_lim_initialize (void)
&lim_bitmap_obstack);
bitmap_initialize (&memory_accesses.refs_stored_in_loop[i],
&lim_bitmap_obstack);
- bitmap_initialize (&memory_accesses.all_refs_stored_in_loop[i],
- &lim_bitmap_obstack);
+ if (store_motion)
+ bitmap_initialize (&memory_accesses.all_refs_stored_in_loop[i],
+ &lim_bitmap_obstack);
}
memory_accesses.ttae_cache = NULL;
@@ -3089,17 +3105,18 @@ tree_ssa_lim_finalize (void)
}
/* Moves invariants from loops. Only "expensive" invariants are moved out --
- i.e. those that are likely to be win regardless of the register pressure. */
+ i.e. those that are likely to be win regardless of the register pressure.
+ Only perform store motion if STORE_MOTION is true. */
-static unsigned int
-tree_ssa_lim (function *fun)
+unsigned int
+loop_invariant_motion_in_fun (function *fun, bool store_motion)
{
unsigned int todo = 0;
- tree_ssa_lim_initialize ();
+ tree_ssa_lim_initialize (store_motion);
/* Gathers information about memory accesses in the loops. */
- analyze_memory_references ();
+ analyze_memory_references (store_motion);
/* Fills ALWAYS_EXECUTED_IN information for basic blocks. */
fill_always_executed_in ();
@@ -3114,7 +3131,8 @@ tree_ssa_lim (function *fun)
/* Execute store motion. Force the necessary invariants to be moved
out of the loops as well. */
- do_store_motion ();
+ if (store_motion)
+ do_store_motion ();
free (rpo);
rpo = XNEWVEC (int, last_basic_block_for_fn (fun));
@@ -3175,7 +3193,7 @@ pass_lim::execute (function *fun)
if (number_of_loops (fun) <= 1)
return 0;
- unsigned int todo = tree_ssa_lim (fun);
+ unsigned int todo = loop_invariant_motion_in_fun (fun, true);
if (!in_loop_pipeline)
loop_optimizer_finalize ();
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index 5bb781d..33e15d4 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -1406,6 +1406,9 @@ tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer,
bitmap_clear (father_bbs);
bitmap_set_bit (father_bbs, loop_father->header->index);
}
+ else if (unroll_outer)
+ /* Trigger scalar cleanup once any outermost loop gets unrolled. */
+ cfun->pending_TODOs |= PENDING_TODO_force_next_scalar_cleanup;
return true;
}
diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h
index e789e4f..d8e918e 100644
--- a/gcc/tree-ssa-loop-manip.h
+++ b/gcc/tree-ssa-loop-manip.h
@@ -55,7 +55,7 @@ extern void tree_transform_and_unroll_loop (class loop *, unsigned,
extern void tree_unroll_loop (class loop *, unsigned,
edge, class tree_niter_desc *);
extern tree canonicalize_loop_ivs (class loop *, tree *, bool);
-
+extern unsigned int loop_invariant_motion_in_fun (function *, bool);
#endif /* GCC_TREE_SSA_LOOP_MANIP_H */
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 5e8365d..339a0c5 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -529,7 +529,7 @@ tree_ssa_loop_done (void)
{
free_numbers_of_iterations_estimates (cfun);
scev_finalize ();
- loop_optimizer_finalize ();
+ loop_optimizer_finalize (cfun, true);
return 0;
}
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 90dfb98..c74b763 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -187,6 +187,10 @@ static struct
{
/* Number of cexpi calls inserted. */
int inserted;
+
+ /* Number of conversions removed. */
+ int conv_removed;
+
} sincos_stats;
static struct
@@ -1099,6 +1103,103 @@ make_pass_cse_reciprocals (gcc::context *ctxt)
return new pass_cse_reciprocals (ctxt);
}
+/* If NAME is the result of a type conversion, look for other
+ equivalent dominating or dominated conversions, and replace all
+ uses with the earliest dominating name, removing the redundant
+ conversions. Return the prevailing name. */
+
+static tree
+execute_cse_conv_1 (tree name)
+{
+ if (SSA_NAME_IS_DEFAULT_DEF (name)
+ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return name;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+
+ if (!gimple_assign_cast_p (def_stmt))
+ return name;
+
+ tree src = gimple_assign_rhs1 (def_stmt);
+
+ if (TREE_CODE (src) != SSA_NAME)
+ return name;
+
+ imm_use_iterator use_iter;
+ gimple *use_stmt;
+
+ /* Find the earliest dominating def. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, src)
+ {
+ if (use_stmt == def_stmt
+ || !gimple_assign_cast_p (use_stmt))
+ continue;
+
+ tree lhs = gimple_assign_lhs (use_stmt);
+
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)
+ || (gimple_assign_rhs1 (use_stmt)
+ != gimple_assign_rhs1 (def_stmt))
+ || !types_compatible_p (TREE_TYPE (name), TREE_TYPE (lhs)))
+ continue;
+
+ bool use_dominates;
+ if (gimple_bb (def_stmt) == gimple_bb (use_stmt))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ while (!gsi_end_p (gsi) && gsi_stmt (gsi) != def_stmt)
+ gsi_next (&gsi);
+ use_dominates = !gsi_end_p (gsi);
+ }
+ else if (dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt),
+ gimple_bb (def_stmt)))
+ use_dominates = false;
+ else if (dominated_by_p (CDI_DOMINATORS, gimple_bb (def_stmt),
+ gimple_bb (use_stmt)))
+ use_dominates = true;
+ else
+ continue;
+
+ if (use_dominates)
+ {
+ std::swap (name, lhs);
+ std::swap (def_stmt, use_stmt);
+ }
+ }
+
+ /* Now go through all uses of SRC again, replacing the equivalent
+ dominated conversions. We may replace defs that were not
+ dominated by the then-prevailing defs when we first visited
+ them. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, src)
+ {
+ if (use_stmt == def_stmt
+ || !gimple_assign_cast_p (use_stmt))
+ continue;
+
+ tree lhs = gimple_assign_lhs (use_stmt);
+
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)
+ || (gimple_assign_rhs1 (use_stmt)
+ != gimple_assign_rhs1 (def_stmt))
+ || !types_compatible_p (TREE_TYPE (name), TREE_TYPE (lhs)))
+ continue;
+
+ if (gimple_bb (def_stmt) == gimple_bb (use_stmt)
+ || dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt),
+ gimple_bb (def_stmt)))
+ {
+ sincos_stats.conv_removed++;
+
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ replace_uses_by (lhs, name);
+ gsi_remove (&gsi, true);
+ }
+ }
+
+ return name;
+}
+
/* Records an occurrence at statement USE_STMT in the vector of trees
STMTS if it is dominated by *TOP_BB or dominates it or this basic block
is not yet initialized. Returns true if the occurrence was pushed on
@@ -1147,6 +1248,8 @@ execute_cse_sincos_1 (tree name)
int i;
bool cfg_changed = false;
+ name = execute_cse_conv_1 (name);
+
FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name)
{
if (gimple_code (use_stmt) != GIMPLE_CALL
@@ -1181,7 +1284,7 @@ execute_cse_sincos_1 (tree name)
and, in subsequent rounds, that the built_in type is the same
type, or a compatible type. */
if (type != t && !types_compatible_p (type, t))
- return false;
+ RETURN_FROM_IMM_USE_STMT (use_iter, false);
}
if (seen_cos + seen_sin + seen_cexpi <= 1)
return false;
@@ -2296,6 +2399,8 @@ pass_cse_sincos::execute (function *fun)
statistics_counter_event (fun, "sincos statements inserted",
sincos_stats.inserted);
+ statistics_counter_event (fun, "conv statements removed",
+ sincos_stats.conv_removed);
return cfg_changed ? TODO_cleanup_cfg : 0;
}
@@ -3352,7 +3457,8 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
and 0 otherwise. */
static int
-uaddsub_overflow_check_p (gimple *stmt, gimple *use_stmt)
+uaddsub_overflow_check_p (gimple *stmt, gimple *use_stmt, tree maxval,
+ tree *other)
{
enum tree_code ccode = ERROR_MARK;
tree crhs1 = NULL_TREE, crhs2 = NULL_TREE;
@@ -3400,21 +3506,46 @@ uaddsub_overflow_check_p (gimple *stmt, gimple *use_stmt)
{
case GT_EXPR:
case LE_EXPR:
+ if (maxval)
+ {
+ /* r = a + b; r > maxval or r <= maxval */
+ if (crhs1 == lhs
+ && TREE_CODE (crhs2) == INTEGER_CST
+ && tree_int_cst_equal (crhs2, maxval))
+ return ccode == GT_EXPR ? 1 : -1;
+ break;
+ }
/* r = a - b; r > a or r <= a
r = a + b; a > r or a <= r or b > r or b <= r. */
if ((code == MINUS_EXPR && crhs1 == lhs && crhs2 == rhs1)
|| (code == PLUS_EXPR && (crhs1 == rhs1 || crhs1 == rhs2)
&& crhs2 == lhs))
return ccode == GT_EXPR ? 1 : -1;
+ /* r = ~a; b > r or b <= r. */
+ if (code == BIT_NOT_EXPR && crhs2 == lhs)
+ {
+ if (other)
+ *other = crhs1;
+ return ccode == GT_EXPR ? 1 : -1;
+ }
break;
case LT_EXPR:
case GE_EXPR:
+ if (maxval)
+ break;
/* r = a - b; a < r or a >= r
r = a + b; r < a or r >= a or r < b or r >= b. */
if ((code == MINUS_EXPR && crhs1 == rhs1 && crhs2 == lhs)
|| (code == PLUS_EXPR && crhs1 == lhs
&& (crhs2 == rhs1 || crhs2 == rhs2)))
return ccode == LT_EXPR ? 1 : -1;
+ /* r = ~a; r < b or r >= b. */
+ if (code == BIT_NOT_EXPR && crhs1 == lhs)
+ {
+ if (other)
+ *other = crhs2;
+ return ccode == LT_EXPR ? 1 : -1;
+ }
break;
default:
break;
@@ -3430,7 +3561,29 @@ uaddsub_overflow_check_p (gimple *stmt, gimple *use_stmt)
x = REALPART_EXPR <_7>;
_8 = IMAGPART_EXPR <_7>;
if (_8)
- and similarly for addition. */
+ and similarly for addition.
+
+ Also recognize:
+ yc = (type) y;
+ zc = (type) z;
+ x = yc + zc;
+ if (x > max)
+ where y and z have unsigned types with maximum max
+ and there are other uses of x and all of those cast x
+ back to that unsigned type and again replace it with
+ _7 = ADD_OVERFLOW (y, z);
+ _9 = REALPART_EXPR <_7>;
+ _8 = IMAGPART_EXPR <_8>;
+ if (_8)
+ and replace (utype) x with _9.
+
+ Also recognize:
+ x = ~z;
+ if (y > x)
+ and replace it with
+ _7 = ADD_OVERFLOW (y, z);
+ _8 = IMAGPART_EXPR <_8>;
+ if (_8) */
static bool
match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
@@ -3443,58 +3596,283 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
bool use_seen = false;
bool ovf_use_seen = false;
gimple *use_stmt;
+ gimple *add_stmt = NULL;
+ bool add_first = false;
+ gimple *cond_stmt = NULL;
- gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR);
+ gcc_checking_assert (code == PLUS_EXPR
+ || code == MINUS_EXPR
+ || code == BIT_NOT_EXPR);
if (!INTEGRAL_TYPE_P (type)
|| !TYPE_UNSIGNED (type)
|| has_zero_uses (lhs)
- || has_single_use (lhs)
- || optab_handler (code == PLUS_EXPR ? uaddv4_optab : usubv4_optab,
- TYPE_MODE (type)) == CODE_FOR_nothing)
+ || (code != PLUS_EXPR
+ && optab_handler (code == MINUS_EXPR ? usubv4_optab : uaddv4_optab,
+ TYPE_MODE (type)) == CODE_FOR_nothing))
return false;
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ tree rhs2 = gimple_assign_rhs2 (stmt);
FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
{
use_stmt = USE_STMT (use_p);
if (is_gimple_debug (use_stmt))
continue;
- if (uaddsub_overflow_check_p (stmt, use_stmt))
- ovf_use_seen = true;
+ tree other = NULL_TREE;
+ if (uaddsub_overflow_check_p (stmt, use_stmt, NULL_TREE, &other))
+ {
+ if (code == BIT_NOT_EXPR)
+ {
+ gcc_assert (other);
+ if (TREE_CODE (other) != SSA_NAME)
+ return false;
+ if (rhs2 == NULL)
+ rhs2 = other;
+ else
+ return false;
+ cond_stmt = use_stmt;
+ }
+ ovf_use_seen = true;
+ }
else
use_seen = true;
if (ovf_use_seen && use_seen)
break;
}
- if (!ovf_use_seen || !use_seen)
- return false;
+ tree maxval = NULL_TREE;
+ if (!ovf_use_seen
+ || (code == BIT_NOT_EXPR ? use_seen : !use_seen)
+ || (code == PLUS_EXPR
+ && optab_handler (uaddv4_optab,
+ TYPE_MODE (type)) == CODE_FOR_nothing))
+ {
+ if (code != PLUS_EXPR)
+ return false;
+ if (TREE_CODE (rhs1) != SSA_NAME
+ || !gimple_assign_cast_p (SSA_NAME_DEF_STMT (rhs1)))
+ return false;
+ rhs1 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (rhs1));
+ tree type1 = TREE_TYPE (rhs1);
+ if (!INTEGRAL_TYPE_P (type1)
+ || !TYPE_UNSIGNED (type1)
+ || TYPE_PRECISION (type1) >= TYPE_PRECISION (type)
+ || (TYPE_PRECISION (type1)
+ != GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type1))))
+ return false;
+ if (TREE_CODE (rhs2) == INTEGER_CST)
+ {
+ if (wi::ne_p (wi::rshift (wi::to_wide (rhs2),
+ TYPE_PRECISION (type1),
+ UNSIGNED), 0))
+ return false;
+ rhs2 = fold_convert (type1, rhs2);
+ }
+ else
+ {
+ if (TREE_CODE (rhs2) != SSA_NAME
+ || !gimple_assign_cast_p (SSA_NAME_DEF_STMT (rhs2)))
+ return false;
+ rhs2 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (rhs2));
+ tree type2 = TREE_TYPE (rhs2);
+ if (!INTEGRAL_TYPE_P (type2)
+ || !TYPE_UNSIGNED (type2)
+ || TYPE_PRECISION (type2) >= TYPE_PRECISION (type)
+ || (TYPE_PRECISION (type2)
+ != GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type2))))
+ return false;
+ }
+ if (TYPE_PRECISION (type1) >= TYPE_PRECISION (TREE_TYPE (rhs2)))
+ type = type1;
+ else
+ type = TREE_TYPE (rhs2);
+
+ if (TREE_CODE (type) != INTEGER_TYPE
+ || optab_handler (uaddv4_optab,
+ TYPE_MODE (type)) == CODE_FOR_nothing)
+ return false;
+
+ maxval = wide_int_to_tree (type, wi::max_value (TYPE_PRECISION (type),
+ UNSIGNED));
+ ovf_use_seen = false;
+ use_seen = false;
+ basic_block use_bb = NULL;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+ {
+ use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
+
+ if (uaddsub_overflow_check_p (stmt, use_stmt, maxval, NULL))
+ {
+ ovf_use_seen = true;
+ use_bb = gimple_bb (use_stmt);
+ }
+ else
+ {
+ if (!gimple_assign_cast_p (use_stmt)
+ || gimple_assign_rhs_code (use_stmt) == VIEW_CONVERT_EXPR)
+ return false;
+ tree use_lhs = gimple_assign_lhs (use_stmt);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs))
+ || (TYPE_PRECISION (TREE_TYPE (use_lhs))
+ > TYPE_PRECISION (type)))
+ return false;
+ use_seen = true;
+ }
+ }
+ if (!ovf_use_seen)
+ return false;
+ if (!useless_type_conversion_p (type, TREE_TYPE (rhs1)))
+ {
+ if (!use_seen)
+ return false;
+ tree new_rhs1 = make_ssa_name (type);
+ gimple *g = gimple_build_assign (new_rhs1, NOP_EXPR, rhs1);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ rhs1 = new_rhs1;
+ }
+ else if (!useless_type_conversion_p (type, TREE_TYPE (rhs2)))
+ {
+ if (!use_seen)
+ return false;
+ tree new_rhs2 = make_ssa_name (type);
+ gimple *g = gimple_build_assign (new_rhs2, NOP_EXPR, rhs2);
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+ rhs2 = new_rhs2;
+ }
+ else if (!use_seen)
+ {
+ /* If there are no uses of the wider addition, check if
+ forwprop has not created a narrower addition.
+ Require it to be in the same bb as the overflow check. */
+ FOR_EACH_IMM_USE_FAST (use_p, iter, rhs1)
+ {
+ use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
+
+ if (use_stmt == stmt)
+ continue;
+
+ if (!is_gimple_assign (use_stmt)
+ || gimple_bb (use_stmt) != use_bb
+ || gimple_assign_rhs_code (use_stmt) != PLUS_EXPR)
+ continue;
+
+ if (gimple_assign_rhs1 (use_stmt) == rhs1)
+ {
+ if (!operand_equal_p (gimple_assign_rhs2 (use_stmt),
+ rhs2, 0))
+ continue;
+ }
+ else if (gimple_assign_rhs2 (use_stmt) == rhs1)
+ {
+ if (gimple_assign_rhs1 (use_stmt) != rhs2)
+ continue;
+ }
+ else
+ continue;
+
+ add_stmt = use_stmt;
+ break;
+ }
+ if (add_stmt == NULL)
+ return false;
+
+ /* If stmt and add_stmt are in the same bb, we need to find out
+ which one is earlier. If they are in different bbs, we've
+ checked add_stmt is in the same bb as one of the uses of the
+ stmt lhs, so stmt needs to dominate add_stmt too. */
+ if (gimple_bb (stmt) == gimple_bb (add_stmt))
+ {
+ gimple_stmt_iterator gsif = *gsi;
+ gimple_stmt_iterator gsib = *gsi;
+ int i;
+ /* Search both forward and backward from stmt and have a small
+ upper bound. */
+ for (i = 0; i < 128; i++)
+ {
+ if (!gsi_end_p (gsib))
+ {
+ gsi_prev_nondebug (&gsib);
+ if (gsi_stmt (gsib) == add_stmt)
+ {
+ add_first = true;
+ break;
+ }
+ }
+ else if (gsi_end_p (gsif))
+ break;
+ if (!gsi_end_p (gsif))
+ {
+ gsi_next_nondebug (&gsif);
+ if (gsi_stmt (gsif) == add_stmt)
+ break;
+ }
+ }
+ if (i == 128)
+ return false;
+ if (add_first)
+ *gsi = gsi_for_stmt (add_stmt);
+ }
+ }
+ }
+
+ if (code == BIT_NOT_EXPR)
+ *gsi = gsi_for_stmt (cond_stmt);
tree ctype = build_complex_type (type);
- tree rhs1 = gimple_assign_rhs1 (stmt);
- tree rhs2 = gimple_assign_rhs2 (stmt);
- gcall *g = gimple_build_call_internal (code == PLUS_EXPR
+ gcall *g = gimple_build_call_internal (code != MINUS_EXPR
? IFN_ADD_OVERFLOW : IFN_SUB_OVERFLOW,
2, rhs1, rhs2);
tree ctmp = make_ssa_name (ctype);
gimple_call_set_lhs (g, ctmp);
gsi_insert_before (gsi, g, GSI_SAME_STMT);
- gassign *g2 = gimple_build_assign (lhs, REALPART_EXPR,
- build1 (REALPART_EXPR, type, ctmp));
- gsi_replace (gsi, g2, true);
+ tree new_lhs = maxval ? make_ssa_name (type) : lhs;
+ gassign *g2;
+ if (code != BIT_NOT_EXPR)
+ {
+ g2 = gimple_build_assign (new_lhs, REALPART_EXPR,
+ build1 (REALPART_EXPR, type, ctmp));
+ if (maxval)
+ {
+ gsi_insert_before (gsi, g2, GSI_SAME_STMT);
+ if (add_first)
+ *gsi = gsi_for_stmt (stmt);
+ }
+ else
+ gsi_replace (gsi, g2, true);
+ }
tree ovf = make_ssa_name (type);
g2 = gimple_build_assign (ovf, IMAGPART_EXPR,
build1 (IMAGPART_EXPR, type, ctmp));
- gsi_insert_after (gsi, g2, GSI_NEW_STMT);
+ if (code != BIT_NOT_EXPR)
+ gsi_insert_after (gsi, g2, GSI_NEW_STMT);
+ else
+ gsi_insert_before (gsi, g2, GSI_SAME_STMT);
FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
{
if (is_gimple_debug (use_stmt))
continue;
- int ovf_use = uaddsub_overflow_check_p (stmt, use_stmt);
+ int ovf_use = uaddsub_overflow_check_p (stmt, use_stmt, maxval, NULL);
if (ovf_use == 0)
- continue;
+ {
+ gcc_assert (code != BIT_NOT_EXPR);
+ if (maxval)
+ {
+ tree use_lhs = gimple_assign_lhs (use_stmt);
+ gimple_assign_set_rhs1 (use_stmt, new_lhs);
+ if (useless_type_conversion_p (TREE_TYPE (use_lhs),
+ TREE_TYPE (new_lhs)))
+ gimple_assign_set_rhs_code (use_stmt, SSA_NAME);
+ update_stmt (use_stmt);
+ }
+ continue;
+ }
if (gimple_code (use_stmt) == GIMPLE_COND)
{
gcond *cond_stmt = as_a <gcond *> (use_stmt);
@@ -3524,7 +3902,26 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
}
update_stmt (use_stmt);
}
- return true;
+ if (maxval)
+ {
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (stmt);
+ gsi_remove (&gsi2, true);
+ if (add_stmt)
+ {
+ gimple *g = gimple_build_assign (gimple_assign_lhs (add_stmt),
+ new_lhs);
+ gsi2 = gsi_for_stmt (add_stmt);
+ gsi_replace (&gsi2, g, true);
+ }
+ }
+ else if (code == BIT_NOT_EXPR)
+ {
+ *gsi = gsi_for_stmt (stmt);
+ gsi_remove (gsi, true);
+ release_ssa_name (lhs);
+ return true;
+ }
+ return false;
}
/* Return true if target has support for divmod. */
@@ -3849,6 +4246,11 @@ math_opts_dom_walker::after_dom_children (basic_block bb)
match_uaddsub_overflow (&gsi, stmt, code);
break;
+ case BIT_NOT_EXPR:
+ if (match_uaddsub_overflow (&gsi, stmt, code))
+ continue;
+ break;
+
case TRUNC_MOD_EXPR:
convert_to_divmod (as_a<gassign *> (stmt));
break;
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index aa6bb88..3d40f07 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -337,7 +337,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
}
/* Do the replacement of conditional if it can be done. */
- if (two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
+ if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
cfgchanged = true;
else if (!early_p
&& conditional_replacement (bb, bb1, e1, e2, phi,
@@ -635,7 +635,6 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
if (TREE_CODE (lhs) != SSA_NAME
|| !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
|| TREE_CODE (rhs) != INTEGER_CST)
return false;
@@ -648,9 +647,25 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
return false;
}
+ /* Defer boolean x ? 0 : {1,-1} or x ? {1,-1} : 0 to
+ conditional_replacement. */
+ if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
+ && (integer_zerop (arg0)
+ || integer_zerop (arg1)
+ || TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE
+ || (TYPE_PRECISION (TREE_TYPE (arg0))
+ <= TYPE_PRECISION (TREE_TYPE (lhs)))))
+ return false;
+
wide_int min, max;
- if (get_range_info (lhs, &min, &max) != VR_RANGE
- || min + 1 != max
+ if (get_range_info (lhs, &min, &max) != VR_RANGE)
+ {
+ int prec = TYPE_PRECISION (TREE_TYPE (lhs));
+ signop sgn = TYPE_SIGN (TREE_TYPE (lhs));
+ min = wi::min_value (prec, sgn);
+ max = wi::max_value (prec, sgn);
+ }
+ if (min + 1 != max
|| (wi::to_wide (rhs) != min
&& wi::to_wide (rhs) != max))
return false;
@@ -752,7 +767,9 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
gimple_stmt_iterator gsi;
edge true_edge, false_edge;
tree new_var, new_var2;
- bool neg;
+ bool neg = false;
+ int shift = 0;
+ tree nonzero_arg;
/* FIXME: Gimplification of complex type is too hard for now. */
/* We aren't prepared to handle vectors either (and it is a question
@@ -763,14 +780,22 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
return false;
- /* The PHI arguments have the constants 0 and 1, or 0 and -1, then
- convert it to the conditional. */
- if ((integer_zerop (arg0) && integer_onep (arg1))
- || (integer_zerop (arg1) && integer_onep (arg0)))
- neg = false;
- else if ((integer_zerop (arg0) && integer_all_onesp (arg1))
- || (integer_zerop (arg1) && integer_all_onesp (arg0)))
+ /* The PHI arguments have the constants 0 and 1, or 0 and -1 or
+ 0 and (1 << cst), then convert it to the conditional. */
+ if (integer_zerop (arg0))
+ nonzero_arg = arg1;
+ else if (integer_zerop (arg1))
+ nonzero_arg = arg0;
+ else
+ return false;
+ if (integer_all_onesp (nonzero_arg))
neg = true;
+ else if (integer_pow2p (nonzero_arg))
+ {
+ shift = tree_log2 (nonzero_arg);
+ if (shift && POINTER_TYPE_P (TREE_TYPE (nonzero_arg)))
+ return false;
+ }
else
return false;
@@ -782,12 +807,12 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
falls through into BB.
There is a single PHI node at the join point (BB) and its arguments
- are constants (0, 1) or (0, -1).
+ are constants (0, 1) or (0, -1) or (0, (1 << shift)).
So, given the condition COND, and the two PHI arguments, we can
rewrite this PHI into non-branching code:
- dest = (COND) or dest = COND'
+ dest = (COND) or dest = COND' or dest = (COND) << shift
We use the condition as-is if the argument associated with the
true edge has the value one or the argument associated with the
@@ -822,6 +847,14 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
cond = fold_build1_loc (gimple_location (stmt),
NEGATE_EXPR, TREE_TYPE (cond), cond);
}
+ else if (shift)
+ {
+ cond = fold_convert_loc (gimple_location (stmt),
+ TREE_TYPE (result), cond);
+ cond = fold_build2_loc (gimple_location (stmt),
+ LSHIFT_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node, shift));
+ }
/* Insert our new statements at the end of conditional block before the
COND_STMT. */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 63f3a81..a17a09a 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -256,6 +256,7 @@ typedef struct pre_expr_d : nofree_ptr_hash <pre_expr_d>
{
enum pre_expr_kind kind;
unsigned int id;
+ unsigned value_id;
location_t loc;
pre_expr_union u;
@@ -422,11 +423,65 @@ get_or_alloc_expr_for_name (tree name)
result = pre_expr_pool.allocate ();
result->kind = NAME;
result->loc = UNKNOWN_LOCATION;
+ result->value_id = VN_INFO (name)->value_id;
PRE_EXPR_NAME (result) = name;
alloc_expression_id (result);
return result;
}
+/* Given an NARY, get or create a pre_expr to represent it. */
+
+static pre_expr
+get_or_alloc_expr_for_nary (vn_nary_op_t nary,
+ location_t loc = UNKNOWN_LOCATION)
+{
+ struct pre_expr_d expr;
+ pre_expr result;
+ unsigned int result_id;
+
+ expr.kind = NARY;
+ expr.id = 0;
+ PRE_EXPR_NARY (&expr) = nary;
+ result_id = lookup_expression_id (&expr);
+ if (result_id != 0)
+ return expression_for_id (result_id);
+
+ result = pre_expr_pool.allocate ();
+ result->kind = NARY;
+ result->loc = loc;
+ result->value_id = nary->value_id;
+ PRE_EXPR_NARY (result) = nary;
+ alloc_expression_id (result);
+ return result;
+}
+
+/* Given an REFERENCE, get or create a pre_expr to represent it. */
+
+static pre_expr
+get_or_alloc_expr_for_reference (vn_reference_t reference,
+ location_t loc = UNKNOWN_LOCATION)
+{
+ struct pre_expr_d expr;
+ pre_expr result;
+ unsigned int result_id;
+
+ expr.kind = REFERENCE;
+ expr.id = 0;
+ PRE_EXPR_REFERENCE (&expr) = reference;
+ result_id = lookup_expression_id (&expr);
+ if (result_id != 0)
+ return expression_for_id (result_id);
+
+ result = pre_expr_pool.allocate ();
+ result->kind = REFERENCE;
+ result->loc = loc;
+ result->value_id = reference->value_id;
+ PRE_EXPR_REFERENCE (result) = reference;
+ alloc_expression_id (result);
+ return result;
+}
+
+
/* An unordered bitmap set. One bitmap tracks values, the other,
expressions. */
typedef class bitmap_set
@@ -444,6 +499,108 @@ public:
/* Mapping from value id to expressions with that value_id. */
static vec<bitmap> value_expressions;
+/* We just record a single expression for each constant value,
+ one of kind CONSTANT. */
+static vec<pre_expr> constant_value_expressions;
+
+
+/* This structure is used to keep track of statistics on what
+ optimization PRE was able to perform. */
+static struct
+{
+ /* The number of new expressions/temporaries generated by PRE. */
+ int insertions;
+
+ /* The number of inserts found due to partial anticipation */
+ int pa_insert;
+
+ /* The number of inserts made for code hoisting. */
+ int hoist_insert;
+
+ /* The number of new PHI nodes added by PRE. */
+ int phis;
+} pre_stats;
+
+static bool do_partial_partial;
+static pre_expr bitmap_find_leader (bitmap_set_t, unsigned int);
+static void bitmap_value_insert_into_set (bitmap_set_t, pre_expr);
+static bool bitmap_value_replace_in_set (bitmap_set_t, pre_expr);
+static void bitmap_set_copy (bitmap_set_t, bitmap_set_t);
+static bool bitmap_set_contains_value (bitmap_set_t, unsigned int);
+static void bitmap_insert_into_set (bitmap_set_t, pre_expr);
+static bitmap_set_t bitmap_set_new (void);
+static tree create_expression_by_pieces (basic_block, pre_expr, gimple_seq *,
+ tree);
+static tree find_or_generate_expression (basic_block, tree, gimple_seq *);
+static unsigned int get_expr_value_id (pre_expr);
+
+/* We can add and remove elements and entries to and from sets
+ and hash tables, so we use alloc pools for them. */
+
+static object_allocator<bitmap_set> bitmap_set_pool ("Bitmap sets");
+static bitmap_obstack grand_bitmap_obstack;
+
+/* A three tuple {e, pred, v} used to cache phi translations in the
+ phi_translate_table. */
+
+typedef struct expr_pred_trans_d : public typed_noop_remove <expr_pred_trans_d>
+{
+ typedef expr_pred_trans_d value_type;
+ typedef expr_pred_trans_d compare_type;
+
+ /* The expression ID. */
+ unsigned e;
+
+ /* The value expression ID that resulted from the translation. */
+ unsigned v;
+
+ /* hash_table support. */
+ static inline void mark_empty (expr_pred_trans_d &);
+ static inline bool is_empty (const expr_pred_trans_d &);
+ static inline void mark_deleted (expr_pred_trans_d &);
+ static inline bool is_deleted (const expr_pred_trans_d &);
+ static const bool empty_zero_p = true;
+ static inline hashval_t hash (const expr_pred_trans_d &);
+ static inline int equal (const expr_pred_trans_d &, const expr_pred_trans_d &);
+} *expr_pred_trans_t;
+typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
+
+inline bool
+expr_pred_trans_d::is_empty (const expr_pred_trans_d &e)
+{
+ return e.e == 0;
+}
+
+inline bool
+expr_pred_trans_d::is_deleted (const expr_pred_trans_d &e)
+{
+ return e.e == -1u;
+}
+
+inline void
+expr_pred_trans_d::mark_empty (expr_pred_trans_d &e)
+{
+ e.e = 0;
+}
+
+inline void
+expr_pred_trans_d::mark_deleted (expr_pred_trans_d &e)
+{
+ e.e = -1u;
+}
+
+inline hashval_t
+expr_pred_trans_d::hash (const expr_pred_trans_d &e)
+{
+ return e.e;
+}
+
+inline int
+expr_pred_trans_d::equal (const expr_pred_trans_d &ve1,
+ const expr_pred_trans_d &ve2)
+{
+ return ve1.e == ve2.e;
+}
/* Sets that we need to keep track of. */
typedef struct bb_bitmap_sets
@@ -483,6 +640,9 @@ typedef struct bb_bitmap_sets
/* The live virtual operand on successor edges. */
tree vop_on_exit;
+ /* PHI translate cache for the single successor edge. */
+ hash_table<expr_pred_trans_d> *phi_translate_table;
+
/* True if we have visited this block during ANTIC calculation. */
unsigned int visited : 1;
@@ -498,119 +658,34 @@ typedef struct bb_bitmap_sets
#define PA_IN(BB) ((bb_value_sets_t) ((BB)->aux))->pa_in
#define NEW_SETS(BB) ((bb_value_sets_t) ((BB)->aux))->new_sets
#define EXPR_DIES(BB) ((bb_value_sets_t) ((BB)->aux))->expr_dies
+#define PHI_TRANS_TABLE(BB) ((bb_value_sets_t) ((BB)->aux))->phi_translate_table
#define BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
#define BB_MAY_NOTRETURN(BB) ((bb_value_sets_t) ((BB)->aux))->contains_may_not_return_call
#define BB_LIVE_VOP_ON_EXIT(BB) ((bb_value_sets_t) ((BB)->aux))->vop_on_exit
-/* This structure is used to keep track of statistics on what
- optimization PRE was able to perform. */
-static struct
-{
- /* The number of new expressions/temporaries generated by PRE. */
- int insertions;
-
- /* The number of inserts found due to partial anticipation */
- int pa_insert;
-
- /* The number of inserts made for code hoisting. */
- int hoist_insert;
-
- /* The number of new PHI nodes added by PRE. */
- int phis;
-} pre_stats;
-
-static bool do_partial_partial;
-static pre_expr bitmap_find_leader (bitmap_set_t, unsigned int);
-static void bitmap_value_insert_into_set (bitmap_set_t, pre_expr);
-static void bitmap_value_replace_in_set (bitmap_set_t, pre_expr);
-static void bitmap_set_copy (bitmap_set_t, bitmap_set_t);
-static bool bitmap_set_contains_value (bitmap_set_t, unsigned int);
-static void bitmap_insert_into_set (bitmap_set_t, pre_expr);
-static bitmap_set_t bitmap_set_new (void);
-static tree create_expression_by_pieces (basic_block, pre_expr, gimple_seq *,
- tree);
-static tree find_or_generate_expression (basic_block, tree, gimple_seq *);
-static unsigned int get_expr_value_id (pre_expr);
-
-/* We can add and remove elements and entries to and from sets
- and hash tables, so we use alloc pools for them. */
-
-static object_allocator<bitmap_set> bitmap_set_pool ("Bitmap sets");
-static bitmap_obstack grand_bitmap_obstack;
-
-/* A three tuple {e, pred, v} used to cache phi translations in the
- phi_translate_table. */
-
-typedef struct expr_pred_trans_d : free_ptr_hash<expr_pred_trans_d>
-{
- /* The expression. */
- pre_expr e;
-
- /* The predecessor block along which we translated the expression. */
- basic_block pred;
-
- /* The value that resulted from the translation. */
- pre_expr v;
-
- /* The hashcode for the expression, pred pair. This is cached for
- speed reasons. */
- hashval_t hashcode;
-
- /* hash_table support. */
- static inline hashval_t hash (const expr_pred_trans_d *);
- static inline int equal (const expr_pred_trans_d *, const expr_pred_trans_d *);
-} *expr_pred_trans_t;
-typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
-
-inline hashval_t
-expr_pred_trans_d::hash (const expr_pred_trans_d *e)
-{
- return e->hashcode;
-}
-
-inline int
-expr_pred_trans_d::equal (const expr_pred_trans_d *ve1,
- const expr_pred_trans_d *ve2)
-{
- basic_block b1 = ve1->pred;
- basic_block b2 = ve2->pred;
-
- /* If they are not translations for the same basic block, they can't
- be equal. */
- if (b1 != b2)
- return false;
- return pre_expr_d::equal (ve1->e, ve2->e);
-}
-
-/* The phi_translate_table caches phi translations for a given
- expression and predecessor. */
-static hash_table<expr_pred_trans_d> *phi_translate_table;
-
/* Add the tuple mapping from {expression E, basic block PRED} to
the phi translation table and return whether it pre-existed. */
static inline bool
phi_trans_add (expr_pred_trans_t *entry, pre_expr e, basic_block pred)
{
- expr_pred_trans_t *slot;
+ if (!PHI_TRANS_TABLE (pred))
+ PHI_TRANS_TABLE (pred) = new hash_table<expr_pred_trans_d> (11);
+
+ expr_pred_trans_t slot;
expr_pred_trans_d tem;
- hashval_t hash = iterative_hash_hashval_t (pre_expr_d::hash (e),
- pred->index);
- tem.e = e;
- tem.pred = pred;
- tem.hashcode = hash;
- slot = phi_translate_table->find_slot_with_hash (&tem, hash, INSERT);
- if (*slot)
+ unsigned id = get_expression_id (e);
+ tem.e = id;
+ slot = PHI_TRANS_TABLE (pred)->find_slot_with_hash (tem, id, INSERT);
+ if (slot->e)
{
- *entry = *slot;
+ *entry = slot;
return true;
}
- *entry = *slot = XNEW (struct expr_pred_trans_d);
- (*entry)->e = e;
- (*entry)->pred = pred;
- (*entry)->hashcode = hash;
+ *entry = slot;
+ slot->e = id;
return false;
}
@@ -620,23 +695,33 @@ phi_trans_add (expr_pred_trans_t *entry, pre_expr e, basic_block pred)
static void
add_to_value (unsigned int v, pre_expr e)
{
- bitmap set;
-
gcc_checking_assert (get_expr_value_id (e) == v);
- if (v >= value_expressions.length ())
+ if (value_id_constant_p (v))
{
- value_expressions.safe_grow_cleared (v + 1, true);
- }
+ if (e->kind != CONSTANT)
+ return;
- set = value_expressions[v];
- if (!set)
- {
- set = BITMAP_ALLOC (&grand_bitmap_obstack);
- value_expressions[v] = set;
+ if (-v >= constant_value_expressions.length ())
+ constant_value_expressions.safe_grow_cleared (-v + 1);
+
+ pre_expr leader = constant_value_expressions[-v];
+ if (!leader)
+ constant_value_expressions[-v] = e;
}
+ else
+ {
+ if (v >= value_expressions.length ())
+ value_expressions.safe_grow_cleared (v + 1);
- bitmap_set_bit (set, get_or_alloc_expression_id (e));
+ bitmap set = value_expressions[v];
+ if (!set)
+ {
+ set = BITMAP_ALLOC (&grand_bitmap_obstack);
+ value_expressions[v] = set;
+ }
+ bitmap_set_bit (set, get_or_alloc_expression_id (e));
+ }
}
/* Create a new bitmap set and return it. */
@@ -655,29 +740,10 @@ bitmap_set_new (void)
static unsigned int
get_expr_value_id (pre_expr expr)
{
- unsigned int id;
- switch (expr->kind)
- {
- case CONSTANT:
- id = get_constant_value_id (PRE_EXPR_CONSTANT (expr));
- break;
- case NAME:
- id = VN_INFO (PRE_EXPR_NAME (expr))->value_id;
- break;
- case NARY:
- gcc_assert (!PRE_EXPR_NARY (expr)->predicated_values);
- id = PRE_EXPR_NARY (expr)->value_id;
- break;
- case REFERENCE:
- id = PRE_EXPR_REFERENCE (expr)->value_id;
- break;
- default:
- gcc_unreachable ();
- }
/* ??? We cannot assert that expr has a value-id (it can be 0), because
we assign value-ids only to expressions that have a result
in set_hashtable_value_ids. */
- return id;
+ return expr->value_id;
}
/* Return a VN valnum (SSA name or constant) for the PRE value-id VAL. */
@@ -685,16 +751,22 @@ get_expr_value_id (pre_expr expr)
static tree
vn_valnum_from_value_id (unsigned int val)
{
+ if (value_id_constant_p (val))
+ {
+ pre_expr vexpr = constant_value_expressions[-val];
+ if (vexpr)
+ return PRE_EXPR_CONSTANT (vexpr);
+ return NULL_TREE;
+ }
+
+ bitmap exprset = value_expressions[val];
bitmap_iterator bi;
unsigned int i;
- bitmap exprset = value_expressions[val];
EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi)
{
pre_expr vexpr = expression_for_id (i);
if (vexpr->kind == NAME)
return VN_INFO (PRE_EXPR_NAME (vexpr))->valnum;
- else if (vexpr->kind == CONSTANT)
- return PRE_EXPR_CONSTANT (vexpr);
}
return NULL_TREE;
}
@@ -733,38 +805,105 @@ bitmap_set_free (bitmap_set_t set)
bitmap_clear (&set->values);
}
+static void
+pre_expr_DFS (pre_expr expr, bitmap_set_t set, bitmap val_visited,
+ vec<pre_expr> &post);
+
+/* DFS walk leaders of VAL to their operands with leaders in SET, collecting
+ expressions in SET in postorder into POST. */
+
+static void
+pre_expr_DFS (unsigned val, bitmap_set_t set, bitmap val_visited,
+ vec<pre_expr> &post)
+{
+ unsigned int i;
+ bitmap_iterator bi;
+
+ /* Iterate over all leaders and DFS recurse. Borrowed from
+ bitmap_find_leader. */
+ bitmap exprset = value_expressions[val];
+ if (!exprset->first->next)
+ {
+ EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi)
+ if (bitmap_bit_p (&set->expressions, i))
+ pre_expr_DFS (expression_for_id (i), set, val_visited, post);
+ return;
+ }
+
+ EXECUTE_IF_AND_IN_BITMAP (exprset, &set->expressions, 0, i, bi)
+ pre_expr_DFS (expression_for_id (i), set, val_visited, post);
+}
+
+/* DFS walk EXPR to its operands with leaders in SET, collecting
+ expressions in SET in postorder into POST. */
+
+static void
+pre_expr_DFS (pre_expr expr, bitmap_set_t set, bitmap val_visited,
+ vec<pre_expr> &post)
+{
+ switch (expr->kind)
+ {
+ case NARY:
+ {
+ vn_nary_op_t nary = PRE_EXPR_NARY (expr);
+ for (unsigned i = 0; i < nary->length; i++)
+ {
+ if (TREE_CODE (nary->op[i]) != SSA_NAME)
+ continue;
+ unsigned int op_val_id = VN_INFO (nary->op[i])->value_id;
+ /* If we already found a leader for the value we've
+ recursed already. Avoid the costly bitmap_find_leader. */
+ if (bitmap_bit_p (&set->values, op_val_id)
+ && bitmap_set_bit (val_visited, op_val_id))
+ pre_expr_DFS (op_val_id, set, val_visited, post);
+ }
+ break;
+ }
+ case REFERENCE:
+ {
+ vn_reference_t ref = PRE_EXPR_REFERENCE (expr);
+ vec<vn_reference_op_s> operands = ref->operands;
+ vn_reference_op_t operand;
+ for (unsigned i = 0; operands.iterate (i, &operand); i++)
+ {
+ tree op[3];
+ op[0] = operand->op0;
+ op[1] = operand->op1;
+ op[2] = operand->op2;
+ for (unsigned n = 0; n < 3; ++n)
+ {
+ if (!op[n] || TREE_CODE (op[n]) != SSA_NAME)
+ continue;
+ unsigned op_val_id = VN_INFO (op[n])->value_id;
+ if (bitmap_bit_p (&set->values, op_val_id)
+ && bitmap_set_bit (val_visited, op_val_id))
+ pre_expr_DFS (op_val_id, set, val_visited, post);
+ }
+ }
+ break;
+ }
+ default:;
+ }
+ post.quick_push (expr);
+}
/* Generate an topological-ordered array of bitmap set SET. */
static vec<pre_expr>
sorted_array_from_bitmap_set (bitmap_set_t set)
{
- unsigned int i, j;
- bitmap_iterator bi, bj;
+ unsigned int i;
+ bitmap_iterator bi;
vec<pre_expr> result;
/* Pre-allocate enough space for the array. */
result.create (bitmap_count_bits (&set->expressions));
+ auto_bitmap val_visited (&grand_bitmap_obstack);
+ bitmap_tree_view (val_visited);
FOR_EACH_VALUE_ID_IN_SET (set, i, bi)
- {
- /* The number of expressions having a given value is usually
- relatively small. Thus, rather than making a vector of all
- the expressions and sorting it by value-id, we walk the values
- and check in the reverse mapping that tells us what expressions
- have a given value, to filter those in our set. As a result,
- the expressions are inserted in value-id order, which means
- topological order.
-
- If this is somehow a significant lose for some cases, we can
- choose which set to walk based on the set size. */
- bitmap exprset = value_expressions[i];
- EXECUTE_IF_SET_IN_BITMAP (exprset, 0, j, bj)
- {
- if (bitmap_bit_p (&set->expressions, j))
- result.quick_push (expression_for_id (j));
- }
- }
+ if (bitmap_set_bit (val_visited, i))
+ pre_expr_DFS (i, set, val_visited, result);
return result;
}
@@ -836,14 +975,14 @@ bitmap_set_equal (bitmap_set_t a, bitmap_set_t b)
}
/* Replace an instance of EXPR's VALUE with EXPR in SET if it exists,
- and add it otherwise. */
+ and add it otherwise. Return true if any changes were made. */
-static void
+static bool
bitmap_value_replace_in_set (bitmap_set_t set, pre_expr expr)
{
unsigned int val = get_expr_value_id (expr);
if (value_id_constant_p (val))
- return;
+ return false;
if (bitmap_set_contains_value (set, val))
{
@@ -864,13 +1003,14 @@ bitmap_value_replace_in_set (bitmap_set_t set, pre_expr expr)
if (bitmap_clear_bit (&set->expressions, i))
{
bitmap_set_bit (&set->expressions, get_expression_id (expr));
- return;
+ return i != get_expression_id (expr);
}
}
gcc_unreachable ();
}
- else
- bitmap_insert_into_set (set, expr);
+
+ bitmap_insert_into_set (set, expr);
+ return true;
}
/* Insert EXPR into SET if EXPR's value is not already present in
@@ -1066,7 +1206,6 @@ static pre_expr
get_or_alloc_expr_for_constant (tree constant)
{
unsigned int result_id;
- unsigned int value_id;
struct pre_expr_d expr;
pre_expr newexpr;
@@ -1081,8 +1220,8 @@ get_or_alloc_expr_for_constant (tree constant)
newexpr->loc = UNKNOWN_LOCATION;
PRE_EXPR_CONSTANT (newexpr) = constant;
alloc_expression_id (newexpr);
- value_id = get_or_alloc_constant_value_id (constant);
- add_to_value (value_id, newexpr);
+ newexpr->value_id = get_or_alloc_constant_value_id (constant);
+ add_to_value (newexpr->value_id, newexpr);
return newexpr;
}
@@ -1307,10 +1446,11 @@ get_representative_for (const pre_expr e, basic_block b = NULL)
??? We should be able to re-use this when we insert the statement
to compute it. */
name = make_temp_ssa_name (get_expr_type (e), gimple_build_nop (), "pretmp");
- VN_INFO (name)->value_id = value_id;
- VN_INFO (name)->valnum = valnum ? valnum : name;
+ vn_ssa_aux_t vn_info = VN_INFO (name);
+ vn_info->value_id = value_id;
+ vn_info->valnum = valnum ? valnum : name;
/* ??? For now mark this SSA name for release by VN. */
- VN_INFO (name)->needs_insertion = true;
+ vn_info->needs_insertion = true;
add_to_value (value_id, get_or_alloc_expr_for_name (name));
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1438,30 +1578,17 @@ phi_translate_1 (bitmap_set_t dest,
if (result && is_gimple_min_invariant (result))
return get_or_alloc_expr_for_constant (result);
- expr = pre_expr_pool.allocate ();
- expr->kind = NARY;
- expr->id = 0;
- expr->loc = expr_loc;
- if (nary && !nary->predicated_values)
- {
- PRE_EXPR_NARY (expr) = nary;
- new_val_id = nary->value_id;
- get_or_alloc_expression_id (expr);
- }
- else
+ if (!nary || nary->predicated_values)
{
new_val_id = get_next_value_id ();
- value_expressions.safe_grow_cleared (get_max_value_id () + 1,
- true);
nary = vn_nary_op_insert_pieces (newnary->length,
newnary->opcode,
newnary->type,
&newnary->op[0],
result, new_val_id);
- PRE_EXPR_NARY (expr) = nary;
- get_or_alloc_expression_id (expr);
}
- add_to_value (new_val_id, expr);
+ expr = get_or_alloc_expr_for_nary (nary, expr_loc);
+ add_to_value (get_expr_value_id (expr), expr);
}
return expr;
}
@@ -1593,21 +1720,12 @@ phi_translate_1 (bitmap_set_t dest,
return NULL;
}
- expr = pre_expr_pool.allocate ();
- expr->kind = REFERENCE;
- expr->id = 0;
- expr->loc = expr_loc;
-
if (newref)
new_val_id = newref->value_id;
else
{
if (changed || !same_valid)
- {
- new_val_id = get_next_value_id ();
- value_expressions.safe_grow_cleared
- (get_max_value_id () + 1, true);
- }
+ new_val_id = get_next_value_id ();
else
new_val_id = ref->value_id;
if (!newoperands.exists ())
@@ -1618,8 +1736,7 @@ phi_translate_1 (bitmap_set_t dest,
result, new_val_id);
newoperands = vNULL;
}
- PRE_EXPR_REFERENCE (expr) = newref;
- get_or_alloc_expression_id (expr);
+ expr = get_or_alloc_expr_for_reference (newref, expr_loc);
add_to_value (new_val_id, expr);
}
newoperands.release ();
@@ -1678,10 +1795,10 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
if (expr->kind != NAME)
{
if (phi_trans_add (&slot, expr, e->src))
- return slot->v;
+ return slot->v == 0 ? NULL : expression_for_id (slot->v);
/* Store NULL for the value we want to return in the case of
recursing. */
- slot->v = NULL;
+ slot->v = 0;
}
/* Translate. */
@@ -1692,12 +1809,14 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
if (slot)
{
+ /* We may have reallocated. */
+ phi_trans_add (&slot, expr, e->src);
if (phitrans)
- slot->v = phitrans;
+ slot->v = get_expression_id (phitrans);
else
/* Remove failed translations again, they cause insert
iteration to not pick up new opportunities reliably. */
- phi_translate_table->remove_elt_with_hash (slot, slot->hashcode);
+ PHI_TRANS_TABLE (e->src)->clear_slot (slot);
}
return phitrans;
@@ -1711,9 +1830,8 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
static void
phi_translate_set (bitmap_set_t dest, bitmap_set_t set, edge e)
{
- vec<pre_expr> exprs;
- pre_expr expr;
- int i;
+ bitmap_iterator bi;
+ unsigned int i;
if (gimple_seq_empty_p (phi_nodes (e->dest)))
{
@@ -1721,17 +1839,22 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, edge e)
return;
}
- exprs = sorted_array_from_bitmap_set (set);
- FOR_EACH_VEC_ELT (exprs, i, expr)
+ /* Allocate the phi-translation cache where we have an idea about
+ its size. hash-table implementation internals tell us that
+ allocating the table to fit twice the number of elements will
+ make sure we do not usually re-allocate. */
+ if (!PHI_TRANS_TABLE (e->src))
+ PHI_TRANS_TABLE (e->src) = new hash_table<expr_pred_trans_d>
+ (2 * bitmap_count_bits (&set->expressions));
+ FOR_EACH_EXPR_ID_IN_SET (set, i, bi)
{
- pre_expr translated;
- translated = phi_translate (dest, expr, set, NULL, e);
+ pre_expr expr = expression_for_id (i);
+ pre_expr translated = phi_translate (dest, expr, set, NULL, e);
if (!translated)
continue;
bitmap_insert_into_set (dest, translated);
}
- exprs.release ();
}
/* Find the leader for a value (i.e., the name representing that
@@ -1742,18 +1865,8 @@ static pre_expr
bitmap_find_leader (bitmap_set_t set, unsigned int val)
{
if (value_id_constant_p (val))
- {
- unsigned int i;
- bitmap_iterator bi;
- bitmap exprset = value_expressions[val];
+ return constant_value_expressions[-val];
- EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi)
- {
- pre_expr expr = expression_for_id (i);
- if (expr->kind == CONSTANT)
- return expr;
- }
- }
if (bitmap_set_contains_value (set, val))
{
/* Rather than walk the entire bitmap of expressions, and see
@@ -1771,6 +1884,11 @@ bitmap_find_leader (bitmap_set_t set, unsigned int val)
bitmap_iterator bi;
bitmap exprset = value_expressions[val];
+ if (!exprset->first->next)
+ EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi)
+ if (bitmap_bit_p (&set->expressions, i))
+ return expression_for_id (i);
+
EXECUTE_IF_AND_IN_BITMAP (exprset, &set->expressions, 0, i, bi)
return expression_for_id (i);
}
@@ -1943,6 +2061,14 @@ clean (bitmap_set_t set1, bitmap_set_t set2 = NULL)
}
}
exprs.release ();
+
+ if (flag_checking)
+ {
+ unsigned j;
+ bitmap_iterator bi;
+ FOR_EACH_EXPR_ID_IN_SET (set1, j, bi)
+ gcc_assert (valid_in_sets (set1, set2, expression_for_id (j)));
+ }
}
/* Clean the set of expressions that are no longer valid in SET because
@@ -2950,11 +3076,13 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
if (forcedname != folded)
{
- VN_INFO (forcedname)->valnum = forcedname;
- VN_INFO (forcedname)->value_id = get_next_value_id ();
+ vn_ssa_aux_t vn_info = VN_INFO (forcedname);
+ vn_info->valnum = forcedname;
+ vn_info->value_id = get_next_value_id ();
nameexpr = get_or_alloc_expr_for_name (forcedname);
- add_to_value (VN_INFO (forcedname)->value_id, nameexpr);
- bitmap_value_replace_in_set (NEW_SETS (block), nameexpr);
+ add_to_value (vn_info->value_id, nameexpr);
+ if (NEW_SETS (block))
+ bitmap_value_replace_in_set (NEW_SETS (block), nameexpr);
bitmap_value_replace_in_set (AVAIL_OUT (block), nameexpr);
}
@@ -2976,11 +3104,12 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
the expression may have been represented. There is no harm in replacing
here. */
value_id = get_expr_value_id (expr);
- VN_INFO (name)->value_id = value_id;
- VN_INFO (name)->valnum = vn_valnum_from_value_id (value_id);
- if (VN_INFO (name)->valnum == NULL_TREE)
- VN_INFO (name)->valnum = name;
- gcc_assert (VN_INFO (name)->valnum != NULL_TREE);
+ vn_ssa_aux_t vn_info = VN_INFO (name);
+ vn_info->value_id = value_id;
+ vn_info->valnum = vn_valnum_from_value_id (value_id);
+ if (vn_info->valnum == NULL_TREE)
+ vn_info->valnum = name;
+ gcc_assert (vn_info->valnum != NULL_TREE);
nameexpr = get_or_alloc_expr_for_name (name);
add_to_value (value_id, nameexpr);
if (NEW_SETS (block))
@@ -3036,7 +3165,8 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
&& expr->kind != REFERENCE)
{
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Skipping insertion of phi for partial redundancy: Looks like an induction variable\n");
+ fprintf (dump_file, "Skipping insertion of phi for partial "
+ "redundancy: Looks like an induction variable\n");
nophi = true;
}
}
@@ -3044,6 +3174,10 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
/* Make the necessary insertions. */
FOR_EACH_EDGE (pred, ei, block->preds)
{
+ /* When we are not inserting a PHI node do not bother inserting
+ into places that do not dominate the anticipated computations. */
+ if (nophi && !dominated_by_p (CDI_DOMINATORS, block, pred->src))
+ continue;
gimple_seq stmts = NULL;
tree builtexpr;
bprime = pred->src;
@@ -3082,10 +3216,11 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
temp = make_temp_ssa_name (type, NULL, "prephitmp");
phi = create_phi_node (temp, block);
- VN_INFO (temp)->value_id = val;
- VN_INFO (temp)->valnum = vn_valnum_from_value_id (val);
- if (VN_INFO (temp)->valnum == NULL_TREE)
- VN_INFO (temp)->valnum = temp;
+ vn_ssa_aux_t vn_info = VN_INFO (temp);
+ vn_info->value_id = val;
+ vn_info->valnum = vn_valnum_from_value_id (val);
+ if (vn_info->valnum == NULL_TREE)
+ vn_info->valnum = temp;
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
FOR_EACH_EDGE (pred, ei, block->preds)
{
@@ -3119,8 +3254,8 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
bitmap_insert_into_set (PHI_GEN (block), newphi);
bitmap_value_replace_in_set (AVAIL_OUT (block),
newphi);
- bitmap_insert_into_set (NEW_SETS (block),
- newphi);
+ if (NEW_SETS (block))
+ bitmap_insert_into_set (NEW_SETS (block), newphi);
/* If we insert a PHI node for a conversion of another PHI node
in the same basic-block try to preserve range information.
@@ -3185,15 +3320,14 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
*/
static bool
-do_pre_regular_insertion (basic_block block, basic_block dom)
+do_pre_regular_insertion (basic_block block, basic_block dom,
+ vec<pre_expr> exprs)
{
bool new_stuff = false;
- vec<pre_expr> exprs;
pre_expr expr;
- auto_vec<pre_expr> avail;
+ auto_vec<pre_expr, 2> avail;
int i;
- exprs = sorted_array_from_bitmap_set (ANTIC_IN (block));
avail.safe_grow (EDGE_COUNT (block->preds), true);
FOR_EACH_VEC_ELT (exprs, i, expr)
@@ -3327,20 +3461,21 @@ do_pre_regular_insertion (basic_block block, basic_block dom)
gimple_stmt_iterator gsi = gsi_after_labels (block);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
- VN_INFO (temp)->value_id = val;
- VN_INFO (temp)->valnum = vn_valnum_from_value_id (val);
- if (VN_INFO (temp)->valnum == NULL_TREE)
- VN_INFO (temp)->valnum = temp;
+ vn_ssa_aux_t vn_info = VN_INFO (temp);
+ vn_info->value_id = val;
+ vn_info->valnum = vn_valnum_from_value_id (val);
+ if (vn_info->valnum == NULL_TREE)
+ vn_info->valnum = temp;
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
pre_expr newe = get_or_alloc_expr_for_name (temp);
add_to_value (val, newe);
bitmap_value_replace_in_set (AVAIL_OUT (block), newe);
bitmap_insert_into_set (NEW_SETS (block), newe);
+ bitmap_insert_into_set (PHI_GEN (block), newe);
}
}
}
- exprs.release ();
return new_stuff;
}
@@ -3352,15 +3487,14 @@ do_pre_regular_insertion (basic_block block, basic_block dom)
remove the later computation. */
static bool
-do_pre_partial_partial_insertion (basic_block block, basic_block dom)
+do_pre_partial_partial_insertion (basic_block block, basic_block dom,
+ vec<pre_expr> exprs)
{
bool new_stuff = false;
- vec<pre_expr> exprs;
pre_expr expr;
- auto_vec<pre_expr> avail;
+ auto_vec<pre_expr, 2> avail;
int i;
- exprs = sorted_array_from_bitmap_set (PA_IN (block));
avail.safe_grow (EDGE_COUNT (block->preds), true);
FOR_EACH_VEC_ELT (exprs, i, expr)
@@ -3475,7 +3609,6 @@ do_pre_partial_partial_insertion (basic_block block, basic_block dom)
}
}
- exprs.release ();
return new_stuff;
}
@@ -3635,7 +3768,10 @@ insert (void)
NEW_SETS (bb) = bitmap_set_new ();
int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
+ int *bb_rpo = XNEWVEC (int, last_basic_block_for_fn (cfun) + 1);
int rpo_num = pre_and_rev_post_order_compute (NULL, rpo, false);
+ for (int i = 0; i < rpo_num; ++i)
+ bb_rpo[rpo[i]] = i;
int num_iterations = 0;
bool changed;
@@ -3659,31 +3795,49 @@ insert (void)
/* First, update the AVAIL_OUT set with anything we may have
inserted higher up in the dominator tree. */
newset = NEW_SETS (dom);
- if (newset)
+
+ /* Note that we need to value_replace both NEW_SETS, and
+ AVAIL_OUT. For both the case of NEW_SETS, the value may be
+ represented by some non-simple expression here that we want
+ to replace it with. */
+ bool avail_out_changed = false;
+ FOR_EACH_EXPR_ID_IN_SET (newset, i, bi)
{
- /* Note that we need to value_replace both NEW_SETS, and
- AVAIL_OUT. For both the case of NEW_SETS, the value may be
- represented by some non-simple expression here that we want
- to replace it with. */
- FOR_EACH_EXPR_ID_IN_SET (newset, i, bi)
- {
- pre_expr expr = expression_for_id (i);
- bitmap_value_replace_in_set (NEW_SETS (block), expr);
- bitmap_value_replace_in_set (AVAIL_OUT (block), expr);
- }
+ pre_expr expr = expression_for_id (i);
+ bitmap_value_replace_in_set (NEW_SETS (block), expr);
+ avail_out_changed
+ |= bitmap_value_replace_in_set (AVAIL_OUT (block), expr);
+ }
+ /* We need to iterate if AVAIL_OUT of an already processed
+ block source changed. */
+ if (avail_out_changed && !changed)
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, block->succs)
+ if (e->dest->index != EXIT_BLOCK
+ && bb_rpo[e->dest->index] < idx)
+ changed = true;
}
/* Insert expressions for partial redundancies. */
if (flag_tree_pre && !single_pred_p (block))
{
- changed |= do_pre_regular_insertion (block, dom);
+ vec<pre_expr> exprs
+ = sorted_array_from_bitmap_set (ANTIC_IN (block));
+ /* Sorting is not perfect, iterate locally. */
+ while (do_pre_regular_insertion (block, dom, exprs))
+ ;
+ exprs.release ();
if (do_partial_partial)
- changed |= do_pre_partial_partial_insertion (block, dom);
+ {
+ exprs = sorted_array_from_bitmap_set (PA_IN (block));
+ while (do_pre_partial_partial_insertion (block, dom,
+ exprs))
+ ;
+ exprs.release ();
+ }
}
-
- /* Insert expressions for hoisting. */
- if (flag_code_hoisting && EDGE_COUNT (block->succs) >= 2)
- changed |= do_hoist_insertion (block);
}
}
@@ -3697,7 +3851,31 @@ insert (void)
statistics_histogram_event (cfun, "insert iterations", num_iterations);
+ /* AVAIL_OUT is not needed after insertion so we don't have to
+ propagate NEW_SETS from hoist insertion. */
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ bitmap_set_free (NEW_SETS (bb));
+ bitmap_set_pool.remove (NEW_SETS (bb));
+ NEW_SETS (bb) = NULL;
+ }
+
+ /* Insert expressions for hoisting. Do a backward walk here since
+ inserting into BLOCK exposes new opportunities in its predecessors.
+ Since PRE and hoist insertions can cause back-to-back iteration
+ and we are interested in PRE insertion exposed hoisting opportunities
+ but not in hoisting exposed PRE ones do hoist insertion only after
+ PRE insertion iteration finished and do not iterate it. */
+ if (flag_code_hoisting)
+ for (int idx = rpo_num - 1; idx >= 0; --idx)
+ {
+ basic_block block = BASIC_BLOCK_FOR_FN (cfun, rpo[idx]);
+ if (EDGE_COUNT (block->succs) >= 2)
+ changed |= do_hoist_insertion (block);
+ }
+
free (rpo);
+ free (bb_rpo);
}
@@ -3879,13 +4057,8 @@ compute_avail (void)
|| gimple_bb (SSA_NAME_DEF_STMT
(gimple_vuse (stmt))) != block)
{
- result = pre_expr_pool.allocate ();
- result->kind = REFERENCE;
- result->id = 0;
- result->loc = gimple_location (stmt);
- PRE_EXPR_REFERENCE (result) = ref;
-
- get_or_alloc_expression_id (result);
+ result = get_or_alloc_expr_for_reference
+ (ref, gimple_location (stmt));
add_to_value (get_expr_value_id (result), result);
bitmap_value_insert_into_set (EXP_GEN (block), result);
}
@@ -3920,11 +4093,8 @@ compute_avail (void)
&& vn_nary_may_trap (nary))
continue;
- result = pre_expr_pool.allocate ();
- result->kind = NARY;
- result->id = 0;
- result->loc = gimple_location (stmt);
- PRE_EXPR_NARY (result) = nary;
+ result = get_or_alloc_expr_for_nary
+ (nary, gimple_location (stmt));
break;
}
@@ -3953,7 +4123,10 @@ compute_avail (void)
adding the reference to EXP_GEN. */
if (BB_MAY_NOTRETURN (block)
&& vn_reference_may_trap (ref))
- continue;
+ {
+ operands.release ();
+ continue;
+ }
/* If the value of the reference is not invalidated in
this block until it is computed, add the expression
@@ -4042,11 +4215,8 @@ compute_avail (void)
}
operands.release ();
- result = pre_expr_pool.allocate ();
- result->kind = REFERENCE;
- result->id = 0;
- result->loc = gimple_location (stmt);
- PRE_EXPR_REFERENCE (result) = ref;
+ result = get_or_alloc_expr_for_reference
+ (ref, gimple_location (stmt));
break;
}
@@ -4054,7 +4224,6 @@ compute_avail (void)
continue;
}
- get_or_alloc_expression_id (result);
add_to_value (get_expr_value_id (result), result);
bitmap_value_insert_into_set (EXP_GEN (block), result);
continue;
@@ -4100,7 +4269,9 @@ init_pre (void)
expressions.create (0);
expressions.safe_push (NULL);
value_expressions.create (get_max_value_id () + 1);
- value_expressions.safe_grow_cleared (get_max_value_id () + 1, true);
+ value_expressions.quick_grow_cleared (get_max_value_id () + 1);
+ constant_value_expressions.create (get_max_constant_value_id () + 1);
+ constant_value_expressions.quick_grow_cleared (get_max_constant_value_id () + 1);
name_to_id.create (0);
inserted_exprs = BITMAP_ALLOC (NULL);
@@ -4113,7 +4284,6 @@ init_pre (void)
calculate_dominance_info (CDI_DOMINATORS);
bitmap_obstack_initialize (&grand_bitmap_obstack);
- phi_translate_table = new hash_table<expr_pred_trans_d> (5110);
expression_to_id = new hash_table<pre_expr_d> (num_ssa_names * 3);
FOR_ALL_BB_FN (bb, cfun)
{
@@ -4121,6 +4291,7 @@ init_pre (void)
PHI_GEN (bb) = bitmap_set_new ();
TMP_GEN (bb) = bitmap_set_new ();
AVAIL_OUT (bb) = bitmap_set_new ();
+ PHI_TRANS_TABLE (bb) = NULL;
}
}
@@ -4131,17 +4302,20 @@ static void
fini_pre ()
{
value_expressions.release ();
+ constant_value_expressions.release ();
expressions.release ();
BITMAP_FREE (inserted_exprs);
bitmap_obstack_release (&grand_bitmap_obstack);
bitmap_set_pool.release ();
pre_expr_pool.release ();
- delete phi_translate_table;
- phi_translate_table = NULL;
delete expression_to_id;
expression_to_id = NULL;
name_to_id.release ();
+ basic_block bb;
+ FOR_ALL_BB_FN (bb, cfun)
+ if (bb->aux && PHI_TRANS_TABLE (bb))
+ delete PHI_TRANS_TABLE (bb);
free_aux_for_blocks ();
}
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 87dbf55..bc656ff 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1549,3 +1549,63 @@ propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
else
gcc_unreachable ();
}
+
+/* Check exits of each loop in FUN, walk over loop closed PHIs in
+ each exit basic block and propagate degenerate PHIs. */
+
+unsigned
+clean_up_loop_closed_phi (function *fun)
+{
+ unsigned i;
+ edge e;
+ gphi *phi;
+ tree rhs;
+ tree lhs;
+ gphi_iterator gsi;
+ struct loop *loop;
+
+ /* Avoid possibly quadratic work when scanning for loop exits across
+ all loops of a nest. */
+ if (!loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
+ return 0;
+
+ /* replace_uses_by might purge dead EH edges and we want it to also
+ remove dominated blocks. */
+ calculate_dominance_info (CDI_DOMINATORS);
+
+ /* Walk over loop in function. */
+ FOR_EACH_LOOP_FN (fun, loop, 0)
+ {
+ /* Check each exit edege of loop. */
+ auto_vec<edge> exits = get_loop_exit_edges (loop);
+ FOR_EACH_VEC_ELT (exits, i, e)
+ if (single_pred_p (e->dest))
+ /* Walk over loop-closed PHIs. */
+ for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);)
+ {
+ phi = gsi.phi ();
+ rhs = gimple_phi_arg_def (phi, 0);
+ lhs = gimple_phi_result (phi);
+
+ if (rhs && may_propagate_copy (lhs, rhs))
+ {
+ /* Dump details. */
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, " Replacing '");
+ print_generic_expr (dump_file, lhs, dump_flags);
+ fprintf (dump_file, "' with '");
+ print_generic_expr (dump_file, rhs, dump_flags);
+ fprintf (dump_file, "'\n");
+ }
+
+ replace_uses_by (lhs, rhs);
+ remove_phi_node (&gsi, true);
+ }
+ else
+ gsi_next (&gsi);
+ }
+ }
+
+ return 0;
+}
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index a2ca171..4bc9004 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "gimplify.h"
#include "case-cfn-macros.h"
+#include "tree-ssa-reassoc.h"
/* This is a simple global reassociation pass. It is, in part, based
on the LLVM pass of the same name (They do some things more/less
@@ -188,15 +189,6 @@ static struct
int pows_created;
} reassociate_stats;
-/* Operator, rank pair. */
-struct operand_entry
-{
- unsigned int rank;
- unsigned int id;
- tree op;
- unsigned int count;
- gimple *stmt_to_insert;
-};
static object_allocator<operand_entry> operand_entry_pool
("operand entry pool");
@@ -226,7 +218,7 @@ static bool reassoc_stmt_dominates_stmt_p (gimple *, gimple *);
/* Wrapper around gsi_remove, which adjusts gimple_uid of debug stmts
possibly added by gsi_remove. */
-bool
+static bool
reassoc_remove_stmt (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
@@ -425,41 +417,43 @@ get_rank (tree e)
long rank;
tree op;
- if (SSA_NAME_IS_DEFAULT_DEF (e))
- return find_operand_rank (e);
-
- stmt = SSA_NAME_DEF_STMT (e);
- if (gimple_code (stmt) == GIMPLE_PHI)
- return phi_rank (stmt);
-
- if (!is_gimple_assign (stmt))
- return bb_rank[gimple_bb (stmt)->index];
-
/* If we already have a rank for this expression, use that. */
rank = find_operand_rank (e);
if (rank != -1)
return rank;
- /* Otherwise, find the maximum rank for the operands. As an
- exception, remove the bias from loop-carried phis when propagating
- the rank so that dependent operations are not also biased. */
- /* Simply walk over all SSA uses - this takes advatage of the
- fact that non-SSA operands are is_gimple_min_invariant and
- thus have rank 0. */
- rank = 0;
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
- rank = propagate_rank (rank, op);
+ stmt = SSA_NAME_DEF_STMT (e);
+ if (gimple_code (stmt) == GIMPLE_PHI)
+ rank = phi_rank (stmt);
+
+ else if (!is_gimple_assign (stmt))
+ rank = bb_rank[gimple_bb (stmt)->index];
+
+ else
+ {
+ /* Otherwise, find the maximum rank for the operands. As an
+ exception, remove the bias from loop-carried phis when propagating
+ the rank so that dependent operations are not also biased. */
+ /* Simply walk over all SSA uses - this takes advatage of the
+ fact that non-SSA operands are is_gimple_min_invariant and
+ thus have rank 0. */
+ rank = 0;
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
+ rank = propagate_rank (rank, op);
+
+ rank += 1;
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Rank for ");
print_generic_expr (dump_file, e);
- fprintf (dump_file, " is %ld\n", (rank + 1));
+ fprintf (dump_file, " is %ld\n", rank);
}
/* Note the rank in the hashtable so we don't recompute it. */
- insert_operand_rank (e, (rank + 1));
- return (rank + 1);
+ insert_operand_rank (e, rank);
+ return rank;
}
/* Constants, globals, etc., are rank 0 */
@@ -2406,18 +2400,7 @@ optimize_ops_list (enum tree_code opcode,
For more information see comments above fold_test_range in fold-const.c,
this implementation is for GIMPLE. */
-struct range_entry
-{
- tree exp;
- tree low;
- tree high;
- bool in_p;
- bool strict_overflow_p;
- unsigned int idx, next;
-};
-void dump_range_entry (FILE *file, struct range_entry *r);
-void debug_range_entry (struct range_entry *r);
/* Dump the range entry R to FILE, skipping its expression if SKIP_EXP. */
@@ -2447,7 +2430,7 @@ debug_range_entry (struct range_entry *r)
an SSA_NAME and STMT argument is ignored, otherwise STMT
argument should be a GIMPLE_COND. */
-static void
+void
init_range_entry (struct range_entry *r, tree exp, gimple *stmt)
{
int in_p;
@@ -3334,7 +3317,9 @@ optimize_range_tests_to_bit_test (enum tree_code opcode, int first, int length,
}
/* Optimize x != 0 && y != 0 && z != 0 into (x | y | z) != 0
- and similarly x != -1 && y != -1 && y != -1 into (x & y & z) != -1. */
+ and similarly x != -1 && y != -1 && y != -1 into (x & y & z) != -1.
+ Also, handle x < C && y < C && z < C where C is power of two as
+ (x | y | z) < C. */
static bool
optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
@@ -3350,20 +3335,44 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
for (i = first; i < length; i++)
{
+ int idx;
+
if (ranges[i].exp == NULL_TREE
|| TREE_CODE (ranges[i].exp) != SSA_NAME
|| !ranges[i].in_p
|| TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) <= 1
- || TREE_CODE (TREE_TYPE (ranges[i].exp)) == BOOLEAN_TYPE
- || ranges[i].low == NULL_TREE
- || ranges[i].low != ranges[i].high)
+ || TREE_CODE (TREE_TYPE (ranges[i].exp)) == BOOLEAN_TYPE)
continue;
- bool zero_p = integer_zerop (ranges[i].low);
- if (!zero_p && !integer_all_onesp (ranges[i].low))
+ if (ranges[i].low != NULL_TREE
+ && ranges[i].high != NULL_TREE
+ && tree_int_cst_equal (ranges[i].low, ranges[i].high))
+ {
+ idx = !integer_zerop (ranges[i].low);
+ if (idx && !integer_all_onesp (ranges[i].low))
+ continue;
+ }
+ else if (ranges[i].high != NULL_TREE
+ && TREE_CODE (ranges[i].high) == INTEGER_CST)
+ {
+ wide_int w = wi::to_wide (ranges[i].high);
+ int prec = TYPE_PRECISION (TREE_TYPE (ranges[i].exp));
+ int l = wi::clz (w);
+ idx = 2;
+ if (l <= 0
+ || l >= prec
+ || w != wi::mask (prec - l, false, prec))
+ continue;
+ if (!((TYPE_UNSIGNED (TREE_TYPE (ranges[i].exp))
+ && ranges[i].low == NULL_TREE)
+ || (ranges[i].low
+ && integer_zerop (ranges[i].low))))
+ continue;
+ }
+ else
continue;
- b = TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) * 2 + !zero_p;
+ b = TYPE_PRECISION (TREE_TYPE (ranges[i].exp)) * 3 + idx;
if (buckets.length () <= b)
buckets.safe_grow_cleared (b + 1, true);
if (chains.length () <= (unsigned) i)
@@ -3376,6 +3385,44 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
if (i && chains[i - 1])
{
int j, k = i;
+ if ((b % 3) == 2)
+ {
+ /* When ranges[X - 1].high + 1 is a power of two,
+ we need to process the same bucket up to
+ precision - 1 times, each time split the entries
+ with the same high bound into one chain and the
+ rest into another one to be processed later. */
+ int this_prev = i;
+ int other_prev = 0;
+ for (j = chains[i - 1]; j; j = chains[j - 1])
+ {
+ if (tree_int_cst_equal (ranges[i - 1].high,
+ ranges[j - 1].high))
+ {
+ chains[this_prev - 1] = j;
+ this_prev = j;
+ }
+ else if (other_prev == 0)
+ {
+ buckets[b] = j;
+ other_prev = j;
+ }
+ else
+ {
+ chains[other_prev - 1] = j;
+ other_prev = j;
+ }
+ }
+ chains[this_prev - 1] = 0;
+ if (other_prev)
+ chains[other_prev - 1] = 0;
+ if (chains[i - 1] == 0)
+ {
+ if (other_prev)
+ b--;
+ continue;
+ }
+ }
for (j = chains[i - 1]; j; j = chains[j - 1])
{
gimple *gk = SSA_NAME_DEF_STMT (ranges[k - 1].exp);
@@ -3443,8 +3490,8 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
exp = gimple_assign_lhs (g);
}
g = gimple_build_assign (make_ssa_name (id >= l ? type1 : type2),
- (b & 1) ? BIT_AND_EXPR : BIT_IOR_EXPR,
- op, exp);
+ (b % 3) == 1
+ ? BIT_AND_EXPR : BIT_IOR_EXPR, op, exp);
gimple_seq_add_stmt_without_update (&seq, g);
op = gimple_assign_lhs (g);
}
@@ -3452,10 +3499,13 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
if (update_range_test (&ranges[k - 1], NULL, candidates.address (),
candidates.length (), opcode, ops, op,
seq, true, ranges[k - 1].low,
- ranges[k - 1].low, strict_overflow_p))
+ ranges[k - 1].high, strict_overflow_p))
any_changes = true;
else
gimple_seq_discard (seq);
+ if ((b % 3) == 2 && buckets[b] != i)
+ /* There is more work to do for this bucket. */
+ b--;
}
return any_changes;
@@ -4284,7 +4334,7 @@ suitable_cond_bb (basic_block bb, basic_block test_bb, basic_block *other_bb,
range test optimization, all SSA_NAMEs set in the bb are consumed
in the bb and there are no PHIs. */
-static bool
+bool
no_side_effect_bb (basic_block bb)
{
gimple_stmt_iterator gsi;
diff --git a/gcc/tree-ssa-reassoc.h b/gcc/tree-ssa-reassoc.h
new file mode 100644
index 0000000..dc7f59f
--- /dev/null
+++ b/gcc/tree-ssa-reassoc.h
@@ -0,0 +1,48 @@
+/* Reassociation for trees.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_SSA_REASSOC_H
+#define GCC_SSA_REASSOC_H
+
+/* Operator, rank pair. */
+struct operand_entry
+{
+ unsigned int rank;
+ unsigned int id;
+ tree op;
+ unsigned int count;
+ gimple *stmt_to_insert;
+};
+
+struct range_entry
+{
+ tree exp;
+ tree low;
+ tree high;
+ bool in_p;
+ bool strict_overflow_p;
+ unsigned int idx, next;
+};
+
+void dump_range_entry (FILE *file, struct range_entry *r);
+void debug_range_entry (struct range_entry *r);
+void init_range_entry (struct range_entry *r, tree exp, gimple *stmt);
+bool no_side_effect_bb (basic_block bb);
+
+#endif /* GCC_SSA_REASSOC_H */
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index c139adb..81990fc 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -288,7 +288,6 @@ vn_constant_hasher::equal (const vn_constant_s *vc1, const vn_constant_s *vc2)
}
static hash_table<vn_constant_hasher> *constant_to_value_id;
-static bitmap constant_value_ids;
/* Obstack we allocate the vn-tables elements from. */
@@ -322,6 +321,7 @@ tree VN_TOP;
/* Unique counter for our value ids. */
static unsigned int next_value_id;
+static int next_constant_value_id;
/* Table of vn_ssa_aux_t's, one per ssa_name. The vn_ssa_aux_t objects
@@ -611,20 +611,11 @@ get_or_alloc_constant_value_id (tree constant)
vcp = XNEW (struct vn_constant_s);
vcp->hashcode = vc.hashcode;
vcp->constant = constant;
- vcp->value_id = get_next_value_id ();
+ vcp->value_id = get_next_constant_value_id ();
*slot = vcp;
- bitmap_set_bit (constant_value_ids, vcp->value_id);
return vcp->value_id;
}
-/* Return true if V is a value id for a constant. */
-
-bool
-value_id_constant_p (unsigned int v)
-{
- return bitmap_bit_p (constant_value_ids, v);
-}
-
/* Compute the hash for a reference operand VRO1. */
static void
@@ -711,7 +702,10 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
if (vr1->operands == vr2->operands)
return true;
- if (!expressions_equal_p (TYPE_SIZE (vr1->type), TYPE_SIZE (vr2->type)))
+ if (COMPLETE_TYPE_P (vr1->type) != COMPLETE_TYPE_P (vr2->type)
+ || (COMPLETE_TYPE_P (vr1->type)
+ && !expressions_equal_p (TYPE_SIZE (vr1->type),
+ TYPE_SIZE (vr2->type))))
return false;
if (INTEGRAL_TYPE_P (vr1->type)
@@ -2048,12 +2042,12 @@ vn_walk_cb_data::push_partial_def (pd_data pd,
}
else
{
- size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
if (pd.offset >= 0)
{
/* LSB of this_buffer[0] byte should be at pd.offset bits
in buffer. */
unsigned int msk;
+ size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
amnt = pd.offset % BITS_PER_UNIT;
if (amnt)
shift_bytes_in_array_left (this_buffer, len + 1, amnt);
@@ -2083,6 +2077,9 @@ vn_walk_cb_data::push_partial_def (pd_data pd,
{
amnt = (unsigned HOST_WIDE_INT) pd.offset % BITS_PER_UNIT;
if (amnt)
+ size -= BITS_PER_UNIT - amnt;
+ size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
+ if (amnt)
shift_bytes_in_array_left (this_buffer, len + 1, amnt);
}
memcpy (p, this_buffer + (amnt != 0), size / BITS_PER_UNIT);
@@ -4132,13 +4129,27 @@ vn_nary_op_insert_stmt (gimple *stmt, tree result)
static inline hashval_t
vn_phi_compute_hash (vn_phi_t vp1)
{
- inchash::hash hstate (EDGE_COUNT (vp1->block->preds) > 2
- ? vp1->block->index : EDGE_COUNT (vp1->block->preds));
+ inchash::hash hstate;
tree phi1op;
tree type;
edge e;
edge_iterator ei;
+ hstate.add_int (EDGE_COUNT (vp1->block->preds));
+ switch (EDGE_COUNT (vp1->block->preds))
+ {
+ case 1:
+ break;
+ case 2:
+ if (vp1->block->loop_father->header == vp1->block)
+ ;
+ else
+ break;
+ /* Fallthru. */
+ default:
+ hstate.add_int (vp1->block->index);
+ }
+
/* If all PHI arguments are constants we need to distinguish
the PHI node via its type. */
type = vp1->type;
@@ -4283,11 +4294,12 @@ vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2)
/* Any phi in the same block will have it's arguments in the
same edge order, because of how we store phi nodes. */
- for (unsigned i = 0; i < EDGE_COUNT (vp1->block->preds); ++i)
+ unsigned nargs = EDGE_COUNT (vp1->block->preds);
+ for (unsigned i = 0; i < nargs; ++i)
{
tree phi1op = vp1->phiargs[i];
tree phi2op = vp2->phiargs[i];
- if (phi1op == VN_TOP || phi2op == VN_TOP)
+ if (phi1op == phi2op)
continue;
if (!expressions_equal_p (phi1op, phi2op))
return false;
@@ -5578,14 +5590,32 @@ get_max_value_id (void)
return next_value_id;
}
+/* Return the maximum constant value id we have ever seen. */
+
+unsigned int
+get_max_constant_value_id (void)
+{
+ return -next_constant_value_id;
+}
+
/* Return the next unique value id. */
unsigned int
get_next_value_id (void)
{
+ gcc_checking_assert ((int)next_value_id > 0);
return next_value_id++;
}
+/* Return the next unique value id for constants. */
+
+unsigned int
+get_next_constant_value_id (void)
+{
+ gcc_checking_assert (next_constant_value_id < 0);
+ return next_constant_value_id--;
+}
+
/* Compare two expressions E1 and E2 and return true if they are equal. */
@@ -5600,8 +5630,8 @@ expressions_equal_p (tree e1, tree e2)
if (e1 == VN_TOP || e2 == VN_TOP)
return true;
- /* If only one of them is null, they cannot be equal. */
- if (!e1 || !e2)
+ /* SSA_NAME compare pointer equal. */
+ if (TREE_CODE (e1) == SSA_NAME || TREE_CODE (e2) == SSA_NAME)
return false;
/* Now perform the actual comparison. */
@@ -5834,8 +5864,9 @@ eliminate_dom_walker::eliminate_insert (basic_block bb,
else
{
gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
- VN_INFO (res)->valnum = val;
- VN_INFO (res)->visited = true;
+ vn_ssa_aux_t vn_info = VN_INFO (res);
+ vn_info->valnum = val;
+ vn_info->visited = true;
}
insertions++;
@@ -5875,10 +5906,12 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
it has an expression it wants to use as replacement,
insert that. */
tree val = VN_INFO (lhs)->valnum;
+ vn_ssa_aux_t vn_info;
if (val != VN_TOP
&& TREE_CODE (val) == SSA_NAME
- && VN_INFO (val)->needs_insertion
- && VN_INFO (val)->expr != NULL
+ && (vn_info = VN_INFO (val), true)
+ && vn_info->needs_insertion
+ && vn_info->expr != NULL
&& (sprime = eliminate_insert (b, gsi, val)) != NULL_TREE)
eliminate_push_avail (b, sprime);
}
@@ -6265,8 +6298,9 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
only process new ones. */
if (! has_VN_INFO (def))
{
- VN_INFO (def)->valnum = def;
- VN_INFO (def)->visited = true;
+ vn_ssa_aux_t vn_info = VN_INFO (def);
+ vn_info->valnum = def;
+ vn_info->visited = true;
}
if (gsi_stmt (prev) == gsi_stmt (*gsi))
break;
@@ -6654,7 +6688,6 @@ run_rpo_vn (vn_lookup_kind kind)
/* ??? Prune requirement of these. */
constant_to_value_id = new hash_table<vn_constant_hasher> (23);
- constant_value_ids = BITMAP_ALLOC (NULL);
/* Initialize the value ids and prune out remaining VN_TOPs
from dead code. */
@@ -6721,7 +6754,6 @@ free_rpo_vn (void)
delete constant_to_value_id;
constant_to_value_id = NULL;
- BITMAP_FREE (constant_value_ids);
}
/* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables. */
@@ -7446,6 +7478,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
/ (n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS));
VN_TOP = create_tmp_var_raw (void_type_node, "vn_top");
next_value_id = 1;
+ next_constant_value_id = -1;
vn_ssa_aux_hash = new hash_table <vn_ssa_aux_hasher> (region_size * 2);
gcc_obstack_init (&vn_ssa_aux_obstack);
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 48701c3..3420e6b 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -269,11 +269,21 @@ bool vn_nary_op_eq (const_vn_nary_op_t const vno1,
bool vn_nary_may_trap (vn_nary_op_t);
bool vn_reference_may_trap (vn_reference_t);
bool vn_reference_eq (const_vn_reference_t const, const_vn_reference_t const);
+
unsigned int get_max_value_id (void);
+unsigned int get_max_constant_value_id (void);
unsigned int get_next_value_id (void);
+unsigned int get_next_constant_value_id (void);
unsigned int get_constant_value_id (tree);
unsigned int get_or_alloc_constant_value_id (tree);
-bool value_id_constant_p (unsigned int);
+
+/* Return true if V is a value id for a constant. */
+static inline bool
+value_id_constant_p (unsigned int v)
+{
+ return (int)v < 0;
+}
+
tree fully_constant_vn_reference_p (vn_reference_t);
tree vn_nary_simplify (vn_nary_op_t);
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index 207aae2..b0abf41 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -390,12 +390,15 @@ statement_sink_location (gimple *stmt, basic_block frombb,
with the use. */
if (gimple_code (use_stmt) == GIMPLE_PHI)
{
- /* In case the PHI node post-dominates the current insert location
- we can disregard it. But make sure it is not dominating
- it as well as can happen in a CFG cycle. */
+ /* In case the PHI node post-dominates the current insert
+ location we can disregard it. But make sure it is not
+ dominating it as well as can happen in a CFG cycle. */
if (commondom != bb
&& !dominated_by_p (CDI_DOMINATORS, commondom, bb)
- && dominated_by_p (CDI_POST_DOMINATORS, commondom, bb))
+ && dominated_by_p (CDI_POST_DOMINATORS, commondom, bb)
+ /* If the blocks are possibly within the same irreducible
+ cycle the above check breaks down. */
+ && !(bb->flags & commondom->flags & BB_IRREDUCIBLE_LOOP))
continue;
bb = EDGE_PRED (bb, PHI_ARG_INDEX_FROM_USE (use_p))->src;
}
@@ -407,7 +410,8 @@ statement_sink_location (gimple *stmt, basic_block frombb,
continue;
/* There is no easy way to disregard defs not on the path from
frombb to commondom so just consider them all. */
- commondom = nearest_common_dominator (CDI_DOMINATORS, bb, commondom);
+ commondom = nearest_common_dominator (CDI_DOMINATORS,
+ bb, commondom);
if (commondom == frombb)
return false;
}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index ebb17cd..522b2d4 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -46,7 +46,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "tree-ssa-strlen.h"
#include "tree-hash-traits.h"
-#include "tree-object-size.h"
#include "builtins.h"
#include "target.h"
#include "diagnostic-core.h"
@@ -1667,7 +1666,8 @@ valid_builtin_call (gimple *stmt)
strinfo. */
static void
-adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
+adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat,
+ pointer_query &ptr_qry)
{
tree vuse, callee, len;
struct laststmt_struct last = laststmt;
@@ -1754,7 +1754,9 @@ adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
/* Don't fold away an out of bounds access, as this defeats proper
warnings. */
tree dst = gimple_call_arg (last.stmt, 0);
- tree size = compute_objsize (dst, 0);
+
+ access_ref aref;
+ tree size = compute_objsize (dst, 1, &aref, &ptr_qry);
if (size && tree_int_cst_lt (size, len))
return;
}
@@ -1912,8 +1914,7 @@ maybe_set_strlen_range (tree lhs, tree src, tree bound)
to allow accesses across subobject boundaries. */
static void
-maybe_warn_overflow (gimple *stmt, tree len,
- range_query *rvals = NULL,
+maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
strinfo *si = NULL, bool plus_one = false,
bool rawmem = false)
{
@@ -1933,160 +1934,39 @@ maybe_warn_overflow (gimple *stmt, tree len,
dest = gimple_call_arg (stmt, 0);
writefn = gimple_call_fndecl (stmt);
}
+ else
+ return;
if (TREE_NO_WARNING (dest))
return;
+ const int ostype = rawmem ? 0 : 1;
+
/* Use maximum precision to avoid overflow in the addition below.
Make sure all operands have the same precision to keep wide_int
from ICE'ing. */
- /* Convenience constants. */
- const widest_int diff_min
- = wi::to_widest (TYPE_MIN_VALUE (ptrdiff_type_node));
- const widest_int diff_max
- = wi::to_widest (TYPE_MAX_VALUE (ptrdiff_type_node));
- const widest_int size_max
- = wi::to_widest (TYPE_MAX_VALUE (size_type_node));
-
- /* The offset into the destination object computed below and not
- reflected in DESTSIZE. */
- widest_int offrng[2] = { 0, 0 };
-
- if (!si)
- {
- /* If no destination STRINFO was provided try to get it from
- the DEST argument. */
- tree ref = dest;
- if (TREE_CODE (ref) == ARRAY_REF)
- {
- /* Handle stores to VLAs (represented as
- ARRAY_REF (MEM_REF (vlaptr, 0), N]. */
- tree off = TREE_OPERAND (ref, 1);
- ref = TREE_OPERAND (ref, 0);
- wide_int rng[2];
- if (get_range (off, stmt, rng, rvals))
- {
- /* Convert offsets to the maximum precision. */
- offrng[0] = widest_int::from (rng[0], SIGNED);
- offrng[1] = widest_int::from (rng[1], SIGNED);
- }
- else
- {
- offrng[0] = diff_min;
- offrng[1] = diff_max;
- }
- }
-
- if (TREE_CODE (ref) == MEM_REF)
- {
- tree mem_off = TREE_OPERAND (ref, 1);
- ref = TREE_OPERAND (ref, 0);
- wide_int rng[2];
- if (get_range (mem_off, stmt, rng, rvals))
- {
- offrng[0] += widest_int::from (rng[0], SIGNED);
- offrng[1] += widest_int::from (rng[1], SIGNED);
- }
- else
- {
- offrng[0] = diff_min;
- offrng[1] = diff_max;
- }
- }
-
- wide_int rng[2];
- if (int idx = get_stridx (ref, rng, rvals))
- {
- si = get_strinfo (idx);
- offrng[0] += widest_int::from (rng[0], SIGNED);
- offrng[1] += widest_int::from (rng[1], SIGNED);
- }
- }
-
- /* The allocation call if the destination object was allocated
- by one. */
- gimple *alloc_call = NULL;
- /* The DECL of the destination object if known and not dynamically
- allocated. */
- tree destdecl = NULL_TREE;
- /* The offset into the destination object set by compute_objsize
- but already reflected in DESTSIZE. */
- tree destoff = NULL_TREE;
+ access_ref aref;
/* The size of the destination region (which is smaller than
the destination object for stores at a non-zero offset). */
- tree destsize = NULL_TREE;
-
- /* Compute the range of sizes of the destination object. The range
- is constant for declared objects but may be a range for allocated
- objects. */
- widest_int sizrng[2] = { 0, 0 };
- if (si)
- {
- wide_int rng[2];
- destsize = gimple_call_alloc_size (si->alloc, rng, rvals);
- if (destsize)
- {
- sizrng[0] = widest_int::from (rng[0], UNSIGNED);
- sizrng[1] = widest_int::from (rng[1], UNSIGNED);
- }
- alloc_call = si->alloc;
- }
- else
- offrng[0] = offrng[1] = 0;
+ tree destsize = compute_objsize (dest, ostype, &aref, &ptr_qry);
if (!destsize)
{
- /* If there is no STRINFO for DEST, fall back on compute_objsize. */
- tree off = NULL_TREE;
- destsize = compute_objsize (dest, rawmem ? 0 : 1, &destdecl, &off, rvals);
- if (destsize)
- {
- /* Remember OFF but clear OFFRNG that may have been set above. */
- destoff = off;
- offrng[0] = offrng[1] = 0;
-
- if (destdecl && TREE_CODE (destdecl) == SSA_NAME)
- {
- gimple *stmt = SSA_NAME_DEF_STMT (destdecl);
- if (is_gimple_call (stmt))
- alloc_call = stmt;
- destdecl = NULL_TREE;
- }
-
- wide_int rng[2];
- if (get_range (destsize, stmt, rng, rvals))
- {
- sizrng[0] = widest_int::from (rng[0], UNSIGNED);
- sizrng[1] = widest_int::from (rng[1], UNSIGNED);
- }
- else
- {
- /* On failure, rather than failing, set the maximum range
- so that overflow in allocated objects whose size depends
- on the strlen of the source can still be diagnosed
- below. */
- sizrng[0] = 0;
- sizrng[1] = size_max;
- }
- }
+ aref.sizrng[0] = 0;
+ aref.sizrng[1] = wi::to_offset (max_object_size ());
}
- if (!destsize)
- {
- sizrng[0] = 0;
- sizrng[1] = size_max;
- };
-
/* Return early if the DESTSIZE size expression is the same as LEN
and the offset into the destination is zero. This might happen
in the case of a pair of malloc and memset calls to allocate
an object and clear it as if by calloc. */
- if (destsize == len && !plus_one && offrng[0] == 0 && offrng[0] == offrng[1])
+ if (destsize == len && !plus_one
+ && aref.offrng[0] == 0 && aref.offrng[0] == aref.offrng[1])
return;
wide_int rng[2];
- if (!get_range (len, stmt, rng, rvals))
+ if (!get_range (len, stmt, rng, ptr_qry.rvals))
return;
widest_int lenrng[2] =
@@ -2100,38 +1980,13 @@ maybe_warn_overflow (gimple *stmt, tree len,
/* The size of the remaining space in the destination computed
as the size of the latter minus the offset into it. */
- widest_int spcrng[2] = { sizrng[0], sizrng[1] };
- if (wi::neg_p (offrng[0]) && wi::neg_p (offrng[1]))
- {
- /* When the offset is negative and the size of the destination
- object unknown there is little to do.
- FIXME: Detect offsets that are necessarily invalid regardless
- of the size of the object. */
- if (!destsize)
- return;
-
- /* The remaining space is necessarily zero. */
- spcrng[0] = spcrng[1] = 0;
- }
- else if (wi::neg_p (offrng[0]))
- {
- /* When the lower bound of the offset is negative but the upper
- bound is not, reduce the upper bound of the remaining space
- by the upper bound of the offset but leave the lower bound
- unchanged. If that makes the upper bound of the space less
- than the lower bound swap the two. */
- spcrng[1] -= wi::ltu_p (offrng[1], spcrng[1]) ? offrng[1] : spcrng[1];
- if (wi::ltu_p (spcrng[1], spcrng[0]))
- std::swap (spcrng[1], spcrng[0]);
- }
- else
- {
- /* When the offset is positive reduce the remaining space by
- the lower bound of the offset or clear it if the offset is
- greater. */
- spcrng[0] -= wi::ltu_p (offrng[0], spcrng[0]) ? offrng[0] : spcrng[0];
- spcrng[1] -= wi::ltu_p (offrng[0], spcrng[1]) ? offrng[0] : spcrng[1];
- }
+ widest_int spcrng[2];
+ {
+ offset_int remrng[2];
+ remrng[1] = aref.size_remaining (remrng);
+ spcrng[0] = remrng[0] == -1 ? 0 : widest_int::from (remrng[0], UNSIGNED);
+ spcrng[1] = widest_int::from (remrng[1], UNSIGNED);
+ }
if (wi::leu_p (lenrng[0], spcrng[0])
&& wi::leu_p (lenrng[1], spcrng[1]))
@@ -2233,122 +2088,17 @@ maybe_warn_overflow (gimple *stmt, tree len,
gimple_set_no_warning (stmt, true);
- /* If DESTOFF is not null, use it to format the offset value/range. */
- if (destoff)
- {
- wide_int rng[2];
- if (get_range (destoff, stmt, rng))
- {
- offrng[0] = widest_int::from (rng[0], SIGNED);
- offrng[1] = widest_int::from (rng[1], SIGNED);
- }
- else
- offrng[0] = offrng[1] = 0;
- }
-
- /* Format the offset to keep the number of inform calls from growing
- out of control. */
- char offstr[64];
- if (offrng[0] == offrng[1])
- sprintf (offstr, "%lli", (long long) offrng[0].to_shwi ());
- else
- sprintf (offstr, "[%lli, %lli]",
- (long long) offrng[0].to_shwi (), (long long) offrng[1].to_shwi ());
-
- if (destdecl && DECL_P (destdecl))
- {
- if (tree size = DECL_SIZE_UNIT (destdecl))
- inform (DECL_SOURCE_LOCATION (destdecl),
- "at offset %s to object %qD with size %E declared here",
- offstr, destdecl, size);
- else
- inform (DECL_SOURCE_LOCATION (destdecl),
- "at offset %s to object %qD declared here",
- offstr, destdecl);
- return;
- }
-
- if (!alloc_call)
- return;
-
- tree allocfn = gimple_call_fndecl (alloc_call);
- if (!allocfn)
- {
- /* For an ALLOC_CALL via a function pointer make a small effort
- to determine the destination of the pointer. */
- allocfn = gimple_call_fn (alloc_call);
- if (TREE_CODE (allocfn) == SSA_NAME)
- {
- gimple *def = SSA_NAME_DEF_STMT (allocfn);
- if (gimple_assign_single_p (def))
- {
- tree rhs = gimple_assign_rhs1 (def);
- if (DECL_P (rhs))
- allocfn = rhs;
- else if (TREE_CODE (rhs) == COMPONENT_REF)
- allocfn = TREE_OPERAND (rhs, 1);
- }
- }
- }
-
- if (gimple_call_builtin_p (alloc_call, BUILT_IN_ALLOCA_WITH_ALIGN))
- {
- if (sizrng[0] == sizrng[1])
- inform (gimple_location (alloc_call),
- "at offset %s to an object with size %wu declared here",
- offstr, sizrng[0].to_uhwi ());
- else if (sizrng[0] == 0)
- {
- /* Avoid printing impossible sizes. */
- if (wi::ltu_p (sizrng[1], diff_max - 2))
- inform (gimple_location (alloc_call),
- "at offset %s to an object with size at most %wu "
- "declared here",
- offstr, sizrng[1].to_uhwi ());
- else
- inform (gimple_location (alloc_call),
- "at offset %s to an object declared here", offstr);
- }
- else
- inform (gimple_location (alloc_call),
- "at offset %s to an object with size between %wu and %wu "
- "declared here",
- offstr, sizrng[0].to_uhwi (), sizrng[1].to_uhwi ());
- return;
- }
-
- if (sizrng[0] == sizrng[1])
- inform (gimple_location (alloc_call),
- "at offset %s to an object with size %wu allocated by %qE here",
- offstr, sizrng[0].to_uhwi (), allocfn);
- else if (sizrng[0] == 0)
- {
- /* Avoid printing impossible sizes. */
- if (wi::ltu_p (sizrng[1], diff_max - 2))
- inform (gimple_location (alloc_call),
- "at offset %s to an object with size at most %wu allocated "
- "by %qD here",
- offstr, sizrng[1].to_uhwi (), allocfn);
- else
- inform (gimple_location (alloc_call),
- "at offset %s to an object allocated by %qE here",
- offstr, allocfn);
- }
- else
- inform (gimple_location (alloc_call),
- "at offset %s to an object with size between %wu and %wu "
- "allocated by %qE here",
- offstr, sizrng[0].to_uhwi (), sizrng[1].to_uhwi (), allocfn);
+ aref.inform_access (access_write_only);
}
/* Convenience wrapper for the above. */
static inline void
maybe_warn_overflow (gimple *stmt, unsigned HOST_WIDE_INT len,
- range_query *rvals = NULL, strinfo *si = NULL,
+ pointer_query &ptr_qry, strinfo *si = NULL,
bool plus_one = false, bool rawmem = false)
{
- maybe_warn_overflow (stmt, build_int_cst (size_type_node, len), rvals,
+ maybe_warn_overflow (stmt, build_int_cst (size_type_node, len), ptr_qry,
si, plus_one, rawmem);
}
@@ -2648,7 +2398,7 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
static void
handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
- range_query *rvals)
+ pointer_query &ptr_qry)
{
int idx, didx;
tree src, dst, srclen, len, lhs, type, fn, oldlen;
@@ -2674,7 +2424,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
return;
if (olddsi != NULL)
- adjust_last_stmt (olddsi, stmt, false);
+ adjust_last_stmt (olddsi, stmt, false, ptr_qry);
srclen = NULL_TREE;
if (si != NULL)
@@ -2682,10 +2432,10 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
else if (idx < 0)
srclen = build_int_cst (size_type_node, ~idx);
- maybe_warn_overflow (stmt, srclen, rvals, olddsi, true);
+ maybe_warn_overflow (stmt, srclen, ptr_qry, olddsi, true);
if (olddsi != NULL)
- adjust_last_stmt (olddsi, stmt, false);
+ adjust_last_stmt (olddsi, stmt, false, ptr_qry);
loc = gimple_location (stmt);
if (srclen == NULL_TREE)
@@ -3030,7 +2780,8 @@ is_strlen_related_p (tree src, tree len)
*/
bool
-maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
+maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
+ pointer_query *ptr_qry /* = NULL */)
{
gimple *stmt = gsi_stmt (gsi);
if (gimple_no_warning_p (stmt))
@@ -3038,31 +2789,24 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
wide_int cntrange[2];
- if (TREE_CODE (cnt) == INTEGER_CST)
- cntrange[0] = cntrange[1] = wi::to_wide (cnt);
- else if (TREE_CODE (cnt) == SSA_NAME)
+ // FIXME: Use range_query instead of global ranges.
+ enum value_range_kind rng = get_range_info (cnt, cntrange, cntrange + 1);
+ if (rng == VR_RANGE)
+ ;
+ else if (rng == VR_ANTI_RANGE)
{
- // FIXME: Use range_query instead of global ranges.
- enum value_range_kind rng = get_range_info (cnt, cntrange, cntrange + 1);
- if (rng == VR_RANGE)
- ;
- else if (rng == VR_ANTI_RANGE)
- {
- wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
+ wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
- if (wi::ltu_p (cntrange[1], maxobjsize))
- {
- cntrange[0] = cntrange[1] + 1;
- cntrange[1] = maxobjsize;
- }
- else
- {
- cntrange[1] = cntrange[0] - 1;
- cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
- }
+ if (wi::ltu_p (cntrange[1], maxobjsize))
+ {
+ cntrange[0] = cntrange[1] + 1;
+ cntrange[1] = maxobjsize;
}
else
- return false;
+ {
+ cntrange[1] = cntrange[0] - 1;
+ cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
+ }
}
else
return false;
@@ -3293,7 +3037,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
}
}
- if (tree dstsize = compute_objsize (dst, 1))
+ access_ref aref;
+ if (tree dstsize = compute_objsize (dst, 1, &aref, ptr_qry))
{
/* The source length is unknown. Try to determine the destination
size and see if it matches the specified bound. If not, bail.
@@ -3308,7 +3053,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
/* Avoid warning for strncpy(a, b, N) calls where the following
equalities hold:
N == sizeof a && N == sizeof b */
- if (tree srcsize = compute_objsize (src, 1))
+ if (tree srcsize = compute_objsize (src, 1, &aref, ptr_qry))
if (wi::to_wide (srcsize) == cntrange[1])
return false;
@@ -3451,7 +3196,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
static void
handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
- range_query *rvals)
+ pointer_query &ptr_qry)
{
tree lhs, oldlen, newlen;
gimple *stmt = gsi_stmt (*gsi);
@@ -3471,8 +3216,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
if (olddsi != NULL
&& !integer_zerop (len))
{
- maybe_warn_overflow (stmt, len, rvals, olddsi, false, true);
- adjust_last_stmt (olddsi, stmt, false);
+ maybe_warn_overflow (stmt, len, ptr_qry, olddsi, false, false);
+ adjust_last_stmt (olddsi, stmt, false, ptr_qry);
}
int idx = get_stridx (src);
@@ -3549,7 +3294,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
}
if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
- adjust_last_stmt (olddsi, stmt, false);
+ adjust_last_stmt (olddsi, stmt, false, ptr_qry);
if (didx == 0)
{
@@ -3631,7 +3376,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
is known. */
static void
-handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
+handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
+ pointer_query &ptr_qry)
{
int idx, didx;
tree srclen, args, type, fn, objsz, endptr;
@@ -3859,7 +3605,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
computed by transforming this strcpy into stpcpy. */
if (srclen == NULL_TREE && dsi->dont_invalidate)
dsi->stmt = stmt;
- adjust_last_stmt (dsi, stmt, true);
+ adjust_last_stmt (dsi, stmt, true, ptr_qry);
if (srclen != NULL_TREE)
{
laststmt.stmt = stmt;
@@ -3916,13 +3662,13 @@ handle_alloc_call (enum built_in_function bcode, gimple_stmt_iterator *gsi)
static bool
handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
- range_query *rvals)
+ pointer_query &ptr_qry)
{
gimple *memset_stmt = gsi_stmt (*gsi);
tree ptr = gimple_call_arg (memset_stmt, 0);
/* Set to the non-constant offset added to PTR. */
wide_int offrng[2];
- int idx1 = get_stridx (ptr, offrng, rvals);
+ int idx1 = get_stridx (ptr, offrng, ptr_qry.rvals);
if (idx1 <= 0)
return false;
strinfo *si1 = get_strinfo (idx1);
@@ -3938,7 +3684,7 @@ handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
tree memset_size = gimple_call_arg (memset_stmt, 2);
/* Check for overflow. */
- maybe_warn_overflow (memset_stmt, memset_size, rvals, NULL, false, true);
+ maybe_warn_overflow (memset_stmt, memset_size, ptr_qry, NULL, false, false);
/* Bail when there is no statement associated with the destination
(the statement may be null even when SI1->ALLOC is not). */
@@ -3989,11 +3735,13 @@ handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
return true;
}
-/* Return a pointer to the first such equality expression if RES is used
- only in expressions testing its equality to zero, and null otherwise. */
+/* Return first such statement if RES is used in statements testing its
+ equality to zero, and null otherwise. If EXCLUSIVE is true, return
+ nonnull if and only RES is used in such expressions exclusively and
+ in none other. */
static gimple *
-used_only_for_zero_equality (tree res)
+use_in_zero_equality (tree res, bool exclusive = true)
{
gimple *first_use = NULL;
@@ -4006,6 +3754,7 @@ used_only_for_zero_equality (tree res)
if (is_gimple_debug (use_stmt))
continue;
+
if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
{
tree_code code = gimple_assign_rhs_code (use_stmt);
@@ -4015,25 +3764,41 @@ used_only_for_zero_equality (tree res)
if ((TREE_CODE (cond_expr) != EQ_EXPR
&& (TREE_CODE (cond_expr) != NE_EXPR))
|| !integer_zerop (TREE_OPERAND (cond_expr, 1)))
- return NULL;
+ {
+ if (exclusive)
+ return NULL;
+ continue;
+ }
}
else if (code == EQ_EXPR || code == NE_EXPR)
{
if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
- return NULL;
+ {
+ if (exclusive)
+ return NULL;
+ continue;
+ }
}
- else
+ else if (exclusive)
return NULL;
+ else
+ continue;
}
else if (gimple_code (use_stmt) == GIMPLE_COND)
{
tree_code code = gimple_cond_code (use_stmt);
if ((code != EQ_EXPR && code != NE_EXPR)
|| !integer_zerop (gimple_cond_rhs (use_stmt)))
- return NULL;
+ {
+ if (exclusive)
+ return NULL;
+ continue;
+ }
}
+ else if (exclusive)
+ return NULL;
else
- return NULL;
+ continue;
if (!first_use)
first_use = use_stmt;
@@ -4053,7 +3818,7 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
tree res = gimple_call_lhs (stmt);
- if (!res || !used_only_for_zero_equality (res))
+ if (!res || !use_in_zero_equality (res))
return false;
tree arg1 = gimple_call_arg (stmt, 0);
@@ -4317,7 +4082,7 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
unsigned HOST_WIDE_INT siz)
{
tree lhs = gimple_call_lhs (stmt);
- gimple *use = used_only_for_zero_equality (lhs);
+ gimple *use = use_in_zero_equality (lhs, /* exclusive = */ false);
if (!use)
return;
@@ -4367,12 +4132,12 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
stmt, callee, minlen, siz, bound);
}
- if (warned)
- {
- location_t use_loc = gimple_location (use);
- if (LOCATION_LINE (stmt_loc) != LOCATION_LINE (use_loc))
- inform (use_loc, "in this expression");
- }
+ if (!warned)
+ return;
+
+ location_t use_loc = gimple_location (use);
+ if (LOCATION_LINE (stmt_loc) != LOCATION_LINE (use_loc))
+ inform (use_loc, "in this expression");
}
@@ -4507,7 +4272,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
/* The size of the array in which the unknown string is stored. */
HOST_WIDE_INT varsiz = arysiz1 < 0 ? arysiz2 : arysiz1;
- if ((varsiz < 0 || cmpsiz < varsiz) && used_only_for_zero_equality (lhs))
+ if ((varsiz < 0 || cmpsiz < varsiz) && use_in_zero_equality (lhs))
{
/* If the known length is less than the size of the other array
and the strcmp result is only used to test equality to zero,
@@ -4581,55 +4346,6 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
}
}
-/* Describes recursion limits used by count_nonzero_bytes. */
-
-class ssa_name_limit_t
-{
- bitmap visited; /* Bitmap of visited SSA_NAMEs. */
- unsigned ssa_def_max; /* Longest chain of SSA_NAMEs to follow. */
-
- /* Not copyable or assignable. */
- ssa_name_limit_t (ssa_name_limit_t&);
- void operator= (ssa_name_limit_t&);
-
- public:
-
- ssa_name_limit_t ()
- : visited (NULL),
- ssa_def_max (param_ssa_name_def_chain_limit) { }
-
- int next_ssa_name (tree);
-
- ~ssa_name_limit_t ()
- {
- if (visited)
- BITMAP_FREE (visited);
- }
-};
-
-/* If the SSA_NAME has already been "seen" return a positive value.
- Otherwise add it to VISITED. If the SSA_NAME limit has been
- reached, return a negative value. Otherwise return zero. */
-
-int ssa_name_limit_t::next_ssa_name (tree ssa_name)
-{
- if (!visited)
- visited = BITMAP_ALLOC (NULL);
-
- /* Return a positive value if SSA_NAME has already been visited. */
- if (!bitmap_set_bit (visited, SSA_NAME_VERSION (ssa_name)))
- return 1;
-
- /* Return a negative value to let caller avoid recursing beyond
- the specified limit. */
- if (ssa_def_max == 0)
- return -1;
-
- --ssa_def_max;
-
- return 0;
-}
-
static bool
count_nonzero_bytes_addr (tree, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
unsigned [3], bool *, bool *, bool *,
@@ -4687,7 +4403,7 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
/* Avoid processing an SSA_NAME that has already been visited
or if an SSA_NAME limit has been reached. Indicate success
if the former and failure if the latter. */
- if (int res = snlim.next_ssa_name (exp))
+ if (int res = snlim.next_phi (exp))
return res > 0;
/* Determine the minimum and maximum from the PHI arguments. */
@@ -4922,7 +4638,7 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
/* Avoid processing an SSA_NAME that has already been visited
or if an SSA_NAME limit has been reached. Indicate success
if the former and failure if the latter. */
- if (int res = snlim.next_ssa_name (exp))
+ if (int res = snlim.next_phi (exp))
return res > 0;
/* Determine the minimum and maximum from the PHI arguments. */
@@ -4982,7 +4698,7 @@ count_nonzero_bytes (tree exp, unsigned lenrange[3], bool *nulterm,
static bool
handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
- range_query *rvals)
+ pointer_query &ptr_qry)
{
int idx = -1;
strinfo *si = NULL;
@@ -4990,6 +4706,8 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
+ range_query *const rvals = ptr_qry.rvals;
+
/* The offset of the first byte in LHS modified by the store. */
unsigned HOST_WIDE_INT offset = 0;
@@ -5016,7 +4734,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
unsigned lenrange[] = { UINT_MAX, 0, 0 };
if (count_nonzero_bytes (rhs, lenrange, &dummy, &dummy, &dummy,
rvals))
- maybe_warn_overflow (stmt, lenrange[2], rvals);
+ maybe_warn_overflow (stmt, lenrange[2], ptr_qry);
return true;
}
@@ -5056,7 +4774,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
storing_nonzero_p = lenrange[1] > 0;
*zero_write = storing_all_zeros_p;
- maybe_warn_overflow (stmt, lenrange[2], rvals);
+ maybe_warn_overflow (stmt, lenrange[2], ptr_qry);
}
else
{
@@ -5174,7 +4892,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
/* We're overwriting the nul terminator with a nonzero or
unknown character. If the previous stmt was a memcpy,
its length may be decreased. */
- adjust_last_stmt (si, stmt, false);
+ adjust_last_stmt (si, stmt, false, ptr_qry);
si = unshare_strinfo (si);
if (storing_nonzero_p)
{
@@ -5392,7 +5110,7 @@ is_char_type (tree type)
static bool
strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
- range_query *rvals)
+ pointer_query &ptr_qry)
{
gimple *stmt = gsi_stmt (*gsi);
@@ -5409,7 +5127,7 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
if (!flag_optimize_strlen
|| !strlen_optimize
|| !valid_builtin_call (stmt))
- return !handle_printf_call (gsi, rvals);
+ return !handle_printf_call (gsi, ptr_qry);
tree callee = gimple_call_fndecl (stmt);
switch (DECL_FUNCTION_CODE (callee))
@@ -5425,7 +5143,7 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
case BUILT_IN_STRCPY_CHK:
case BUILT_IN_STPCPY:
case BUILT_IN_STPCPY_CHK:
- handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi, rvals);
+ handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
break;
case BUILT_IN_STRNCAT:
@@ -5444,11 +5162,11 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
case BUILT_IN_MEMCPY_CHK:
case BUILT_IN_MEMPCPY:
case BUILT_IN_MEMPCPY_CHK:
- handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi, rvals);
+ handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
break;
case BUILT_IN_STRCAT:
case BUILT_IN_STRCAT_CHK:
- handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
+ handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
break;
case BUILT_IN_ALLOCA:
case BUILT_IN_ALLOCA_WITH_ALIGN:
@@ -5457,7 +5175,7 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
handle_alloc_call (DECL_FUNCTION_CODE (callee), gsi);
break;
case BUILT_IN_MEMSET:
- if (handle_builtin_memset (gsi, zero_write, rvals))
+ if (handle_builtin_memset (gsi, zero_write, ptr_qry))
return false;
break;
case BUILT_IN_MEMCMP:
@@ -5466,11 +5184,11 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
break;
case BUILT_IN_STRCMP:
case BUILT_IN_STRNCMP:
- if (handle_builtin_string_cmp (gsi, rvals))
+ if (handle_builtin_string_cmp (gsi, ptr_qry.rvals))
return false;
break;
default:
- if (handle_printf_call (gsi, rvals))
+ if (handle_printf_call (gsi, ptr_qry))
return false;
break;
}
@@ -5628,7 +5346,7 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
static bool
check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
- range_query *rvals)
+ pointer_query &ptr_qry)
{
gimple *stmt = gsi_stmt (*gsi);
@@ -5638,7 +5356,7 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
if (is_gimple_call (stmt))
{
- if (!strlen_check_and_optimize_call (gsi, &zero_write, rvals))
+ if (!strlen_check_and_optimize_call (gsi, &zero_write, ptr_qry))
return false;
}
else if (!flag_optimize_strlen || !strlen_optimize)
@@ -5663,7 +5381,7 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
}
else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (lhs_type))
/* Handle assignment to a character. */
- handle_integral_assign (gsi, cleanup_eh, rvals);
+ handle_integral_assign (gsi, cleanup_eh, ptr_qry.rvals);
else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
{
tree type = TREE_TYPE (lhs);
@@ -5694,7 +5412,7 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
}
/* Handle a single or multibyte assignment. */
- if (is_char_store && !handle_store (gsi, &zero_write, rvals))
+ if (is_char_store && !handle_store (gsi, &zero_write, ptr_qry))
return false;
}
}
@@ -5768,8 +5486,10 @@ public:
strlen_dom_walker (cdi_direction direction)
: dom_walker (direction),
evrp (false),
+ ptr_qry (&evrp, &var_cache),
+ var_cache (),
m_cleanup_cfg (false)
- {}
+ { }
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
@@ -5778,6 +5498,11 @@ public:
to track strlen results across integer variable assignments. */
evrp_range_analyzer evrp;
+ /* A pointer_query object and its cache to store information about
+ pointers and their targets in. */
+ pointer_query ptr_qry;
+ pointer_query::cache_type var_cache;
+
/* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
execute function. */
bool m_cleanup_cfg;
@@ -5871,7 +5596,10 @@ strlen_dom_walker::before_dom_children (basic_block bb)
can be used by printf argument processing. */
evrp.record_ranges_from_stmt (stmt, false);
- if (check_and_optimize_stmt (&gsi, &cleanup_eh, &evrp))
+ /* Reset search depth preformance counter. */
+ ptr_qry.depth = 0;
+
+ if (check_and_optimize_stmt (&gsi, &cleanup_eh, ptr_qry))
gsi_next (&gsi);
}
@@ -5939,6 +5667,29 @@ printf_strlen_execute (function *fun, bool warn_only)
strlen_dom_walker walker (CDI_DOMINATORS);
walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ unsigned nused = 0;
+ unsigned nidxs = walker.ptr_qry.var_cache->indices.length ();
+ for (unsigned i = 0; i != nidxs; ++i)
+ if (walker.ptr_qry.var_cache->indices[i])
+ ++nused;
+
+ fprintf (dump_file, "pointer_query counters\n"
+ " index cache size: %u\n"
+ " utilization: %u%%\n"
+ " access cache size: %u\n"
+ " hits: %u\n"
+ " misses: %u\n"
+ " failures: %u\n"
+ " max_depth: %u\n",
+ nidxs,
+ nidxs == 0 ? 0 : (nused * 100) / nidxs,
+ walker.ptr_qry.var_cache->access_refs.length (),
+ walker.ptr_qry.hits, walker.ptr_qry.misses,
+ walker.ptr_qry.failures, walker.ptr_qry.max_depth);
+ }
+
ssa_ver_to_stridx.release ();
strinfo_pool.release ();
if (decl_to_stridxlist_htab)
@@ -5964,9 +5715,6 @@ printf_strlen_execute (function *fun, bool warn_only)
loop_optimizer_finalize ();
}
- /* Clean up object size info. */
- fini_object_sizes ();
-
return walker.m_cleanup_cfg ? TODO_cleanup_cfg : 0;
}
diff --git a/gcc/tree-ssa-strlen.h b/gcc/tree-ssa-strlen.h
index 225f64b..e3435c1 100644
--- a/gcc/tree-ssa-strlen.h
+++ b/gcc/tree-ssa-strlen.h
@@ -21,8 +21,11 @@
#ifndef GCC_TREE_SSA_STRLEN_H
#define GCC_TREE_SSA_STRLEN_H
+class pointer_query;
+
extern bool is_strlen_related_p (tree, tree);
-extern bool maybe_diag_stxncpy_trunc (gimple_stmt_iterator, tree, tree);
+extern bool maybe_diag_stxncpy_trunc (gimple_stmt_iterator, tree, tree,
+ pointer_query * = NULL);
extern tree set_strlen_range (tree, wide_int, wide_int, tree = NULL_TREE);
extern tree get_range (tree, gimple *, wide_int[2],
@@ -33,6 +36,6 @@ extern void get_range_strlen_dynamic (tree, gimple *, c_strlen_data *,
class range_query *);
/* APIs internal to strlen pass. Defined in gimple-ssa-sprintf.c. */
-extern bool handle_printf_call (gimple_stmt_iterator *, class range_query *);
+extern bool handle_printf_call (gimple_stmt_iterator *, pointer_query &);
#endif // GCC_TREE_SSA_STRLEN_H
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 9bac06f..cf653be 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3851,6 +3851,23 @@ make_escape_constraint (tree op)
make_constraint_to (escaped_id, op);
}
+/* Make constraint necessary to make all indirect references
+ from VI escape. */
+
+static void
+make_indirect_escape_constraint (varinfo_t vi)
+{
+ struct constraint_expr lhs, rhs;
+ /* escaped = *(VAR + UNKNOWN); */
+ lhs.type = SCALAR;
+ lhs.var = escaped_id;
+ lhs.offset = 0;
+ rhs.type = DEREF;
+ rhs.var = vi->id;
+ rhs.offset = UNKNOWN_OFFSET;
+ process_constraint (new_constraint (lhs, rhs));
+}
+
/* Add constraints to that the solution of VI is transitively closed. */
static void
@@ -4026,7 +4043,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
set. The argument would still get clobbered through the
escape solution. */
if ((flags & EAF_NOCLOBBER)
- && (flags & EAF_NOESCAPE))
+ && (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE)))
{
varinfo_t uses = get_call_use_vi (stmt);
varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
@@ -4036,9 +4053,11 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
if (!(flags & EAF_DIRECT))
make_transitive_closure_constraints (tem);
make_copy_constraint (uses, tem->id);
+ if (!(flags & (EAF_NOESCAPE | EAF_DIRECT)))
+ make_indirect_escape_constraint (tem);
returns_uses = true;
}
- else if (flags & EAF_NOESCAPE)
+ else if (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE))
{
struct constraint_expr lhs, rhs;
varinfo_t uses = get_call_use_vi (stmt);
@@ -4061,6 +4080,8 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
rhs.var = nonlocal_id;
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
+ if (!(flags & (EAF_NOESCAPE | EAF_DIRECT)))
+ make_indirect_escape_constraint (tem);
returns_uses = true;
}
else
@@ -4253,6 +4274,11 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
for (i = 0; i < gimple_call_num_args (stmt); ++i)
{
tree arg = gimple_call_arg (stmt, i);
+ int flags = gimple_call_arg_flags (stmt, i);
+
+ /* If the argument is not used we can ignore it. */
+ if (flags & EAF_UNUSED)
+ continue;
if (!uses)
{
uses = get_call_use_vi (stmt);
@@ -8138,10 +8164,6 @@ ipa_pta_execute (void)
from = constraints.length ();
}
- /* FIXME: Clone materialization is not preserving stmt references. */
- FOR_EACH_DEFINED_FUNCTION (node)
- node->clear_stmts_in_references ();
-
/* Build the constraints. */
FOR_EACH_DEFINED_FUNCTION (node)
{
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 7361e0b..a4879fe 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1189,8 +1189,8 @@ gimple_equal_p (same_succ *same_succ, gimple *s1, gimple *s2)
if (!gimple_operand_equal_value_p (t1, t2))
return false;
- code1 = gimple_expr_code (s1);
- code2 = gimple_expr_code (s2);
+ code1 = gimple_cond_code (s1);
+ code2 = gimple_cond_code (s2);
inv_cond = (bitmap_bit_p (same_succ->inverse, bb1->index)
!= bitmap_bit_p (same_succ->inverse, bb2->index));
if (inv_cond)
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 327628f..30f6926 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -259,8 +259,13 @@ thread_jumps::profitable_jump_thread_path (basic_block bbi, tree name,
!gsi_end_p (gsi);
gsi_next_nondebug (&gsi))
{
+ /* Do not allow OpenACC loop markers and __builtin_constant_p on
+ threading paths. The latter is disallowed, because an
+ expression might be constant on two threading paths, and
+ become non-constant (i.e.: phi) when they merge. */
gimple *stmt = gsi_stmt (gsi);
- if (gimple_call_internal_p (stmt, IFN_UNIQUE))
+ if (gimple_call_internal_p (stmt, IFN_UNIQUE)
+ || gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P))
{
m_path.pop ();
return NULL;
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index f43d581..32d63a9 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -265,6 +265,12 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
&& gimple_call_internal_unique_p (stmt))
return NULL;
+ /* We cannot thread through __builtin_constant_p, because an
+ expression that is constant on two threading paths may become
+ non-constant (i.e.: phi) when they merge. */
+ if (gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P))
+ return NULL;
+
/* If duplicating this block is going to cause too much code
expansion, then do not thread through this block. */
stmt_count++;
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 7ed1686..516a7bd 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -404,10 +404,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
tree rhstype = TREE_TYPE (rhs);
if (POINTER_TYPE_P (rhstype))
rhstype = TREE_TYPE (rhstype);
- if (TYPE_EMPTY_P (rhstype)
- || (RECORD_OR_UNION_TYPE_P (rhstype)
- && (!first_field (rhstype)
- || default_is_empty_record (rhstype))))
+ if (is_empty_type (rhstype))
return NULL_TREE;
bool warned = false;
@@ -443,7 +440,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
access implying read access to those objects. */
static void
-maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims)
+maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims)
{
if (!wlims.wmaybe_uninit)
return;
@@ -457,6 +454,10 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims)
if (!fntype)
return;
+ /* Const function do not read their arguments. */
+ if (gimple_call_flags (stmt) & ECF_CONST)
+ return;
+
const built_in_function fncode
= (fndecl && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
? DECL_FUNCTION_CODE (fndecl) : (built_in_function)BUILT_IN_LAST);
@@ -523,6 +524,10 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims)
(but not definitive) read access. */
wlims.always_executed = false;
+ /* Ignore args we are not going to read from. */
+ if (gimple_call_arg_flags (stmt, argno - 1) & EAF_UNUSED)
+ continue;
+
tree arg = gimple_call_arg (stmt, argno - 1);
ao_ref ref;
@@ -639,8 +644,8 @@ warn_uninitialized_vars (bool wmaybe_uninit)
if (gimple_vdef (stmt))
wlims.vdef_cnt++;
- if (is_gimple_call (stmt))
- maybe_warn_pass_by_reference (stmt, wlims);
+ if (gcall *call = dyn_cast <gcall *> (stmt))
+ maybe_warn_pass_by_reference (call, wlims);
else if (gimple_assign_load_p (stmt)
&& gimple_has_location (stmt))
{
@@ -1345,21 +1350,18 @@ value_sat_pred_p (tree val, tree boundary, enum tree_code cmpc,
}
/* Returns true if PRED is common among all the predicate
- chains (PREDS) (and therefore can be factored out).
- NUM_PRED_CHAIN is the size of array PREDS. */
+ chains (PREDS) (and therefore can be factored out). */
static bool
-find_matching_predicate_in_rest_chains (pred_info pred,
- pred_chain_union preds,
- size_t num_pred_chains)
+find_matching_predicate_in_rest_chains (pred_info pred, pred_chain_union preds)
{
size_t i, j, n;
/* Trival case. */
- if (num_pred_chains == 1)
+ if (preds.length () == 1)
return true;
- for (i = 1; i < num_pred_chains; i++)
+ for (i = 1; i < preds.length (); i++)
{
bool found = false;
pred_chain one_chain = preds[i];
@@ -1530,6 +1532,129 @@ prune_uninit_phi_opnds (gphi *phi, unsigned uninit_opnds, gphi *flag_def,
return true;
}
+/* A helper function finds predicate which will be examined against uninit
+ paths. If there is no "flag_var cmp const" form predicate, the function
+ tries to find predicate of form like "flag_var cmp flag_var" with value
+ range info. PHI is the phi node whose incoming (undefined) paths need to
+ be examined. On success, the function returns the comparsion code, sets
+ defintion gimple of the flag_var to FLAG_DEF, sets boundary_cst to
+ BOUNDARY_CST. On fail, the function returns ERROR_MARK. */
+
+static enum tree_code
+find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
+ tree *boundary_cst)
+{
+ enum tree_code vrinfo_code = ERROR_MARK, code;
+ gimple *vrinfo_def = NULL;
+ tree vrinfo_cst = NULL, cond_lhs, cond_rhs;
+
+ gcc_assert (preds.length () > 0);
+ pred_chain the_pred_chain = preds[0];
+ for (unsigned i = 0; i < the_pred_chain.length (); i++)
+ {
+ bool use_vrinfo_p = false;
+ pred_info the_pred = the_pred_chain[i];
+ cond_lhs = the_pred.pred_lhs;
+ cond_rhs = the_pred.pred_rhs;
+ if (cond_lhs == NULL_TREE || cond_rhs == NULL_TREE)
+ continue;
+
+ code = get_cmp_code (the_pred.cond_code, false, the_pred.invert);
+ if (code == ERROR_MARK)
+ continue;
+
+ if (TREE_CODE (cond_lhs) == SSA_NAME && is_gimple_constant (cond_rhs))
+ ;
+ else if (TREE_CODE (cond_rhs) == SSA_NAME
+ && is_gimple_constant (cond_lhs))
+ {
+ std::swap (cond_lhs, cond_rhs);
+ if ((code = get_cmp_code (code, true, false)) == ERROR_MARK)
+ continue;
+ }
+ /* Check if we can take advantage of "flag_var comp flag_var" predicate
+ with value range info. Note only first of such case is handled. */
+ else if (vrinfo_code == ERROR_MARK
+ && TREE_CODE (cond_lhs) == SSA_NAME
+ && TREE_CODE (cond_rhs) == SSA_NAME)
+ {
+ gimple* lhs_def = SSA_NAME_DEF_STMT (cond_lhs);
+ if (!lhs_def || gimple_code (lhs_def) != GIMPLE_PHI
+ || gimple_bb (lhs_def) != gimple_bb (phi))
+ {
+ std::swap (cond_lhs, cond_rhs);
+ if ((code = get_cmp_code (code, true, false)) == ERROR_MARK)
+ continue;
+ }
+
+ /* Check value range info of rhs, do following transforms:
+ flag_var < [min, max] -> flag_var < max
+ flag_var > [min, max] -> flag_var > min
+
+ We can also transform LE_EXPR/GE_EXPR to LT_EXPR/GT_EXPR:
+ flag_var <= [min, max] -> flag_var < [min, max+1]
+ flag_var >= [min, max] -> flag_var > [min-1, max]
+ if no overflow/wrap. */
+ wide_int min, max;
+ tree type = TREE_TYPE (cond_lhs);
+ if (!INTEGRAL_TYPE_P (type)
+ || get_range_info (cond_rhs, &min, &max) != VR_RANGE)
+ continue;
+ if (code == LE_EXPR
+ && max != wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
+ {
+ code = LT_EXPR;
+ max = max + 1;
+ }
+ if (code == GE_EXPR
+ && min != wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
+ {
+ code = GT_EXPR;
+ min = min - 1;
+ }
+ if (code == LT_EXPR)
+ cond_rhs = wide_int_to_tree (type, max);
+ else if (code == GT_EXPR)
+ cond_rhs = wide_int_to_tree (type, min);
+ else
+ continue;
+
+ use_vrinfo_p = true;
+ }
+ else
+ continue;
+
+ if ((*flag_def = SSA_NAME_DEF_STMT (cond_lhs)) == NULL)
+ continue;
+
+ if (gimple_code (*flag_def) != GIMPLE_PHI
+ || gimple_bb (*flag_def) != gimple_bb (phi)
+ || !find_matching_predicate_in_rest_chains (the_pred, preds))
+ continue;
+
+ /* Return if any "flag_var comp const" predicate is found. */
+ if (!use_vrinfo_p)
+ {
+ *boundary_cst = cond_rhs;
+ return code;
+ }
+ /* Record if any "flag_var comp flag_var[vinfo]" predicate is found. */
+ else if (vrinfo_code == ERROR_MARK)
+ {
+ vrinfo_code = code;
+ vrinfo_def = *flag_def;
+ vrinfo_cst = cond_rhs;
+ }
+ }
+ /* Return the "flag_var cmp flag_var[vinfo]" predicate we found. */
+ if (vrinfo_code != ERROR_MARK)
+ {
+ *flag_def = vrinfo_def;
+ *boundary_cst = vrinfo_cst;
+ }
+ return vrinfo_code;
+}
+
/* A helper function that determines if the predicate set
of the use is not overlapping with that of the uninit paths.
The most common senario of guarded use is in Example 1:
@@ -1607,75 +1732,21 @@ use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
gphi *phi, unsigned uninit_opnds,
hash_set<gphi *> *visited_phis)
{
- unsigned int i, n;
gimple *flag_def = 0;
tree boundary_cst = 0;
enum tree_code cmp_code;
- bool swap_cond = false;
- bool invert = false;
- pred_chain the_pred_chain = vNULL;
bitmap visited_flag_phis = NULL;
bool all_pruned = false;
- size_t num_preds = preds.length ();
- gcc_assert (num_preds > 0);
/* Find within the common prefix of multiple predicate chains
a predicate that is a comparison of a flag variable against
a constant. */
- the_pred_chain = preds[0];
- n = the_pred_chain.length ();
- for (i = 0; i < n; i++)
- {
- tree cond_lhs, cond_rhs, flag = 0;
-
- pred_info the_pred = the_pred_chain[i];
-
- invert = the_pred.invert;
- cond_lhs = the_pred.pred_lhs;
- cond_rhs = the_pred.pred_rhs;
- cmp_code = the_pred.cond_code;
-
- if (cond_lhs != NULL_TREE && TREE_CODE (cond_lhs) == SSA_NAME
- && cond_rhs != NULL_TREE && is_gimple_constant (cond_rhs))
- {
- boundary_cst = cond_rhs;
- flag = cond_lhs;
- }
- else if (cond_rhs != NULL_TREE && TREE_CODE (cond_rhs) == SSA_NAME
- && cond_lhs != NULL_TREE && is_gimple_constant (cond_lhs))
- {
- boundary_cst = cond_lhs;
- flag = cond_rhs;
- swap_cond = true;
- }
-
- if (!flag)
- continue;
-
- flag_def = SSA_NAME_DEF_STMT (flag);
-
- if (!flag_def)
- continue;
-
- if ((gimple_code (flag_def) == GIMPLE_PHI)
- && (gimple_bb (flag_def) == gimple_bb (phi))
- && find_matching_predicate_in_rest_chains (the_pred, preds,
- num_preds))
- break;
-
- flag_def = 0;
- }
-
- if (!flag_def)
+ cmp_code = find_var_cmp_const (preds, phi, &flag_def, &boundary_cst);
+ if (cmp_code == ERROR_MARK)
return false;
/* Now check all the uninit incoming edge has a constant flag value
that is in conflict with the use guard/predicate. */
- cmp_code = get_cmp_code (cmp_code, swap_cond, invert);
-
- if (cmp_code == ERROR_MARK)
- return false;
-
all_pruned = prune_uninit_phi_opnds
(phi, uninit_opnds, as_a<gphi *> (flag_def), boundary_cst, cmp_code,
visited_phis, &visited_flag_phis);
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index c47b963..a575979 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -987,6 +987,12 @@ verify_phi_args (gphi *phi, basic_block bb, basic_block *definition_block)
err = true;
}
+ if ((e->flags & EDGE_ABNORMAL) && TREE_CODE (op) != SSA_NAME)
+ {
+ error ("PHI argument on abnormal edge is not SSA_NAME");
+ err = true;
+ }
+
if (TREE_CODE (op) == SSA_NAME)
{
err = verify_ssa_name (op, virtual_operand_p (gimple_phi_result (phi)));
@@ -1212,15 +1218,16 @@ err:
# pragma GCC diagnostic pop
#endif
-/* Initialize global DFA and SSA structures. */
+/* Initialize global DFA and SSA structures.
+ If SIZE is non-zero allocated ssa names array of a given size. */
void
-init_tree_ssa (struct function *fn)
+init_tree_ssa (struct function *fn, int size)
{
fn->gimple_df = ggc_cleared_alloc<gimple_df> ();
fn->gimple_df->default_defs = hash_table<ssa_name_hasher>::create_ggc (20);
pt_solution_reset (&fn->gimple_df->escaped);
- init_ssanames (fn, 0);
+ init_ssanames (fn, size);
}
/* Deallocate memory associated with SSA data structures for FNDECL. */
diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h
index 79f2b13..7e7fa4a 100644
--- a/gcc/tree-ssa.h
+++ b/gcc/tree-ssa.h
@@ -45,7 +45,7 @@ extern void insert_debug_temps_for_defs (gimple_stmt_iterator *);
extern void reset_debug_uses (gimple *);
extern void release_defs_bitset (bitmap toremove);
extern void verify_ssa (bool, bool);
-extern void init_tree_ssa (function *);
+extern void init_tree_ssa (function *, int size = 0);
extern void delete_tree_ssa (function *);
extern bool tree_ssa_useless_type_conversion (tree);
extern tree tree_ssa_strip_useless_type_conversions (tree);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 6ac97fe..1b9dcec 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -77,10 +77,10 @@ unsigned int ssa_name_nodes_created;
void
init_ssanames (struct function *fn, int size)
{
- if (size < 50)
- size = 50;
-
- vec_alloc (SSANAMES (fn), size);
+ if (!size)
+ vec_alloc (SSANAMES (fn), 50);
+ else
+ vec_safe_reserve (SSANAMES (fn), size, true);
/* Version 0 is special, so reserve the first slot in the table. Though
currently unused, we may use version 0 in alias analysis as part of
@@ -420,21 +420,30 @@ set_range_info (tree name, const value_range &vr)
is used to determine if MIN and MAX are valid values. */
enum value_range_kind
-get_range_info (const_tree name, wide_int *min, wide_int *max)
+get_range_info (const_tree expr, wide_int *min, wide_int *max)
{
- gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (expr)));
gcc_assert (min && max);
- range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+ if (TREE_CODE (expr) == INTEGER_CST)
+ {
+ *min = wi::to_wide (expr);
+ *max = *min;
+ return VR_RANGE;
+ }
+ if (TREE_CODE (expr) != SSA_NAME)
+ return VR_VARYING;
+
+ range_info_def *ri = SSA_NAME_RANGE_INFO (expr);
/* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision. */
- if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (name)))
+ if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (expr)))
> 2 * HOST_BITS_PER_WIDE_INT))
return VR_VARYING;
*min = ri->get_min ();
*max = ri->get_max ();
- return SSA_NAME_RANGE_TYPE (name);
+ return SSA_NAME_RANGE_TYPE (expr);
}
/* Gets range information corresponding to ssa_name NAME and stores it
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index d7a451cf..9383cc4 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -343,7 +343,11 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
bp_pack_value (bp, TYPE_FINAL_P (expr), 1);
- bp_pack_value (bp, TYPE_CXX_ODR_P (expr), 1);
+ /* alias_ptr_types_compatible_p relies on fact that during LTO
+ types do not get refined from WPA time to ltrans. */
+ bp_pack_value (bp, flag_wpa && TYPE_CANONICAL (expr)
+ ? TYPE_CXX_ODR_P (TYPE_CANONICAL (expr))
+ : TYPE_CXX_ODR_P (expr), 1);
}
else if (TREE_CODE (expr) == ARRAY_TYPE)
bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
diff --git a/gcc/tree-streamer.c b/gcc/tree-streamer.c
index b0afa1d..a393983 100644
--- a/gcc/tree-streamer.c
+++ b/gcc/tree-streamer.c
@@ -317,6 +317,7 @@ record_common_node (struct streamer_tree_cache_d *cache, tree node)
case TREE_LIST:
case VOID_CST:
case VOID_TYPE:
+ case OPAQUE_TYPE:
/* No recursive trees. */
break;
case ARRAY_TYPE:
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 03a1fe6..08dfd6f 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1310,6 +1310,9 @@ jump_table_cluster::is_beneficial (const vec<cluster *> &,
vec<cluster *>
bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
{
+ if (!is_enabled ())
+ return clusters.copy ();
+
unsigned l = clusters.length ();
auto_vec<min_cluster_item> min;
min.reserve (l + 1);
@@ -1508,7 +1511,6 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
tree minval = get_low ();
tree maxval = get_high ();
- tree range = int_const_binop (MINUS_EXPR, maxval, minval);
unsigned HOST_WIDE_INT bt_range = get_range (minval, maxval);
/* Go through all case labels, and collect the case labels, profile
@@ -1547,11 +1549,39 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
qsort (test, count, sizeof (*test), case_bit_test::cmp);
+ /* If every possible relative value of the index expression is a valid shift
+ amount, then we can merge the entry test in the bit test. */
+ wide_int min, max;
+ bool entry_test_needed;
+ if (TREE_CODE (index_expr) == SSA_NAME
+ && get_range_info (index_expr, &min, &max) == VR_RANGE
+ && wi::leu_p (max - min, prec - 1))
+ {
+ tree index_type = TREE_TYPE (index_expr);
+ minval = fold_convert (index_type, minval);
+ wide_int iminval = wi::to_wide (minval);
+ if (wi::lt_p (min, iminval, TYPE_SIGN (index_type)))
+ {
+ minval = wide_int_to_tree (index_type, min);
+ for (i = 0; i < count; i++)
+ test[i].mask = wi::lshift (test[i].mask, iminval - min);
+ }
+ else if (wi::gt_p (min, iminval, TYPE_SIGN (index_type)))
+ {
+ minval = wide_int_to_tree (index_type, min);
+ for (i = 0; i < count; i++)
+ test[i].mask = wi::lrshift (test[i].mask, min - iminval);
+ }
+ maxval = wide_int_to_tree (index_type, max);
+ entry_test_needed = false;
+ }
+ else
+ entry_test_needed = true;
+
/* If all values are in the 0 .. BITS_PER_WORD-1 range, we can get rid of
the minval subtractions, but it might make the mask constants more
expensive. So, compare the costs. */
- if (compare_tree_int (minval, 0) > 0
- && compare_tree_int (maxval, GET_MODE_BITSIZE (word_mode)) < 0)
+ if (compare_tree_int (minval, 0) > 0 && compare_tree_int (maxval, prec) < 0)
{
int cost_diff;
HOST_WIDE_INT m = tree_to_uhwi (minval);
@@ -1574,7 +1604,6 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
for (i = 0; i < count; i++)
test[i].mask = wi::lshift (test[i].mask, m);
minval = build_zero_cst (TREE_TYPE (minval));
- range = maxval;
}
}
@@ -1590,8 +1619,9 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
/*simple=*/true, NULL_TREE,
/*before=*/true, GSI_SAME_STMT);
- if (m_handles_entire_switch)
+ if (m_handles_entire_switch && entry_test_needed)
{
+ tree range = int_const_binop (MINUS_EXPR, maxval, minval);
/* if (idx > range) goto default */
range
= force_gimple_operand_gsi (&gsi,
@@ -1605,16 +1635,22 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
gsi = gsi_last_bb (new_bb);
}
- /* csui = (1 << (word_mode) idx) */
- csui = make_ssa_name (word_type_node);
tmp = fold_build2 (LSHIFT_EXPR, word_type_node, word_mode_one,
fold_convert (word_type_node, idx));
- tmp = force_gimple_operand_gsi (&gsi, tmp,
- /*simple=*/false, NULL_TREE,
- /*before=*/true, GSI_SAME_STMT);
- shift_stmt = gimple_build_assign (csui, tmp);
- gsi_insert_before (&gsi, shift_stmt, GSI_SAME_STMT);
- update_stmt (shift_stmt);
+
+ /* csui = (1 << (word_mode) idx) */
+ if (count > 1)
+ {
+ csui = make_ssa_name (word_type_node);
+ tmp = force_gimple_operand_gsi (&gsi, tmp,
+ /*simple=*/false, NULL_TREE,
+ /*before=*/true, GSI_SAME_STMT);
+ shift_stmt = gimple_build_assign (csui, tmp);
+ gsi_insert_before (&gsi, shift_stmt, GSI_SAME_STMT);
+ update_stmt (shift_stmt);
+ }
+ else
+ csui = tmp;
profile_probability prob = profile_probability::always ();
@@ -1627,10 +1663,10 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
bt_range -= test[k].bits;
tmp = wide_int_to_tree (word_type_node, test[k].mask);
tmp = fold_build2 (BIT_AND_EXPR, word_type_node, csui, tmp);
+ tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, word_mode_zero);
tmp = force_gimple_operand_gsi (&gsi, tmp,
/*simple=*/true, NULL_TREE,
/*before=*/true, GSI_SAME_STMT);
- tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, word_mode_zero);
basic_block new_bb
= hoist_edge_and_branch_if_true (&gsi, tmp, test[k].target_bb, prob);
gsi = gsi_last_bb (new_bb);
@@ -1740,10 +1776,10 @@ switch_decision_tree::analyze_switch_statement ()
reset_out_edges_aux (m_switch);
- /* Find jump table clusters. */
- vec<cluster *> output = jump_table_cluster::find_jump_tables (clusters);
+ /* Find bit-test clusters. */
+ vec<cluster *> output = bit_test_cluster::find_bit_tests (clusters);
- /* Find bit test clusters. */
+ /* Find jump table clusters. */
vec<cluster *> output2;
auto_vec<cluster *> tmp;
output2.create (1);
@@ -1756,7 +1792,7 @@ switch_decision_tree::analyze_switch_statement ()
{
if (!tmp.is_empty ())
{
- vec<cluster *> n = bit_test_cluster::find_bit_tests (tmp);
+ vec<cluster *> n = jump_table_cluster::find_jump_tables (tmp);
output2.safe_splice (n);
n.release ();
tmp.truncate (0);
@@ -1770,7 +1806,7 @@ switch_decision_tree::analyze_switch_statement ()
/* We still can have a temporary vector to test. */
if (!tmp.is_empty ())
{
- vec<cluster *> n = bit_test_cluster::find_bit_tests (tmp);
+ vec<cluster *> n = jump_table_cluster::find_jump_tables (tmp);
output2.safe_splice (n);
n.release ();
}
diff --git a/gcc/tree-switch-conversion.h b/gcc/tree-switch-conversion.h
index dbfd9ee..62cfde1 100644
--- a/gcc/tree-switch-conversion.h
+++ b/gcc/tree-switch-conversion.h
@@ -48,8 +48,8 @@ class cluster
{
public:
/* Constructor. */
- cluster (tree case_label_expr, basic_block case_bb, profile_probability prob,
- profile_probability subtree_prob);
+ inline cluster (tree case_label_expr, basic_block case_bb,
+ profile_probability prob, profile_probability subtree_prob);
/* Destructor. */
virtual ~cluster ()
@@ -121,8 +121,9 @@ class simple_cluster: public cluster
{
public:
/* Constructor. */
- simple_cluster (tree low, tree high, tree case_label_expr,
- basic_block case_bb, profile_probability prob);
+ inline simple_cluster (tree low, tree high, tree case_label_expr,
+ basic_block case_bb, profile_probability prob,
+ bool has_forward_bb = false);
/* Destructor. */
~simple_cluster ()
@@ -146,6 +147,11 @@ public:
return m_high;
}
+ void set_high (tree high)
+ {
+ m_high = high;
+ }
+
void
debug ()
{
@@ -182,12 +188,16 @@ public:
/* True if case is a range. */
bool m_range_p;
+
+ /* True if the case will use a forwarder BB. */
+ bool m_has_forward_bb;
};
simple_cluster::simple_cluster (tree low, tree high, tree case_label_expr,
- basic_block case_bb, profile_probability prob):
+ basic_block case_bb, profile_probability prob,
+ bool has_forward_bb):
cluster (case_label_expr, case_bb, prob, prob),
- m_low (low), m_high (high)
+ m_low (low), m_high (high), m_has_forward_bb (has_forward_bb)
{
m_range_p = m_high != NULL;
if (m_high == NULL)
@@ -271,7 +281,7 @@ public:
static inline unsigned int case_values_threshold (void);
/* Return whether jump table expansion is allowed. */
- static bool is_enabled (void);
+ static inline bool is_enabled (void);
};
/* A GIMPLE switch statement can be expanded to a short sequence of bit-wise
@@ -411,6 +421,12 @@ public:
basic_block case_bb,
profile_probability prob);
+ /* Return whether bit test expansion is allowed. */
+ static inline bool is_enabled (void)
+ {
+ return flag_bit_tests;
+ }
+
/* True when the jump table handles an entire switch statement. */
bool m_handles_entire_switch;
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 4abd27e..1370170 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -136,6 +136,8 @@ vect_get_smallest_scalar_type (stmt_vec_info stmt_info,
|| gimple_assign_rhs_code (assign) == WIDEN_SUM_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_MULT_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_LSHIFT_EXPR
+ || gimple_assign_rhs_code (assign) == WIDEN_PLUS_EXPR
+ || gimple_assign_rhs_code (assign) == WIDEN_MINUS_EXPR
|| gimple_assign_rhs_code (assign) == FLOAT_EXPR))
{
tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (assign));
@@ -688,7 +690,8 @@ vect_slp_analyze_node_dependences (vec_info *vinfo, slp_tree node,
stmt_vec_info last_access_info = vect_find_last_scalar_stmt_in_slp (node);
for (unsigned k = 0; k < SLP_TREE_SCALAR_STMTS (node).length (); ++k)
{
- stmt_vec_info access_info = SLP_TREE_SCALAR_STMTS (node)[k];
+ stmt_vec_info access_info
+ = vect_orig_stmt (SLP_TREE_SCALAR_STMTS (node)[k]);
if (access_info == last_access_info)
continue;
data_reference *dr_a = STMT_VINFO_DATA_REF (access_info);
@@ -759,7 +762,8 @@ vect_slp_analyze_node_dependences (vec_info *vinfo, slp_tree node,
= vect_find_first_scalar_stmt_in_slp (node);
for (unsigned k = 0; k < SLP_TREE_SCALAR_STMTS (node).length (); ++k)
{
- stmt_vec_info access_info = SLP_TREE_SCALAR_STMTS (node)[k];
+ stmt_vec_info access_info
+ = vect_orig_stmt (SLP_TREE_SCALAR_STMTS (node)[k]);
if (access_info == first_access_info)
continue;
data_reference *dr_a = STMT_VINFO_DATA_REF (access_info);
@@ -1184,14 +1188,9 @@ static void
vect_update_misalignment_for_peel (dr_vec_info *dr_info,
dr_vec_info *dr_peel_info, int npeel)
{
- /* It can be assumed that if dr_info has the same alignment as dr_peel,
- it is aligned in the vector loop. */
+ /* If dr_info is aligned of dr_peel_info is, then mark it so. */
if (vect_dr_aligned_if_peeled_dr_is (dr_info, dr_peel_info))
{
- gcc_assert (!known_alignment_for_access_p (dr_info)
- || !known_alignment_for_access_p (dr_peel_info)
- || (DR_MISALIGNMENT (dr_info)
- == DR_MISALIGNMENT (dr_peel_info)));
SET_DR_MISALIGNMENT (dr_info, 0);
return;
}
@@ -2164,7 +2163,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
{
unsigned max_allowed_peel
= param_vect_max_peeling_for_alignment;
- if (flag_vect_cost_model == VECT_COST_MODEL_CHEAP)
+ if (flag_vect_cost_model <= VECT_COST_MODEL_CHEAP)
max_allowed_peel = 0;
if (max_allowed_peel != (unsigned)-1)
{
@@ -2262,7 +2261,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
do_versioning
= (optimize_loop_nest_for_speed_p (loop)
&& !loop->inner /* FORNOW */
- && flag_vect_cost_model != VECT_COST_MODEL_CHEAP);
+ && flag_vect_cost_model > VECT_COST_MODEL_CHEAP);
if (do_versioning)
{
@@ -2428,7 +2427,13 @@ vect_slp_analyze_node_alignment (vec_info *vinfo, slp_tree node)
/* We need to commit to a vector type for the group now. */
if (is_a <bb_vec_info> (vinfo)
&& !vect_update_shared_vectype (first_stmt_info, SLP_TREE_VECTYPE (node)))
- return false;
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "desired vector type conflicts with earlier one "
+ "for %G", first_stmt_info->stmt);
+ return false;
+ }
dr_vec_info *dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
vect_compute_data_ref_alignment (vinfo, dr_info);
@@ -2438,7 +2443,8 @@ vect_slp_analyze_node_alignment (vec_info *vinfo, slp_tree node)
/* For creating the data-ref pointer we need alignment of the
first element as well. */
- first_stmt_info = vect_find_first_scalar_stmt_in_slp (node);
+ first_stmt_info
+ = vect_stmt_to_vectorize (vect_find_first_scalar_stmt_in_slp (node));
if (first_stmt_info != SLP_TREE_SCALAR_STMTS (node)[0])
{
first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
@@ -3678,6 +3684,10 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
unsigned int count = (comp_alias_ddrs.length ()
+ check_unequal_addrs.length ());
+ if (count && flag_vect_cost_model == VECT_COST_MODEL_VERY_CHEAP)
+ return opt_result::failure_at
+ (vect_location, "would need a runtime alias check\n");
+
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"improved number of alias checks from %d to %d\n",
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index d7bafa7..55cf0d9 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -2089,7 +2089,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi,
if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
&& optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
{
- tree slhs = make_ssa_name (TREE_TYPE (srhs1));
+ tree slhs = make_ssa_name (TREE_TYPE (TREE_TYPE (lhs)));
gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
gsi_insert_before (gsi, repl, GSI_SAME_STMT);
gimple_assign_set_rhs_from_tree (gsi,
@@ -2118,6 +2118,10 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi,
arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
calculated in the same way above. */
if (code == WIDEN_SUM_EXPR
+ || code == VEC_WIDEN_PLUS_HI_EXPR
+ || code == VEC_WIDEN_PLUS_LO_EXPR
+ || code == VEC_WIDEN_MINUS_HI_EXPR
+ || code == VEC_WIDEN_MINUS_LO_EXPR
|| code == VEC_WIDEN_MULT_HI_EXPR
|| code == VEC_WIDEN_MULT_LO_EXPR
|| code == VEC_WIDEN_MULT_EVEN_EXPR
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 7cf00e6..2370b87 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -1084,6 +1084,33 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop,
exit = single_exit (loop);
basic_block new_preheader = new_bbs[0];
+ /* Before installing PHI arguments make sure that the edges
+ into them match that of the scalar loop we analyzed. This
+ makes sure the SLP tree matches up between the main vectorized
+ loop and the epilogue vectorized copies. */
+ if (single_succ_edge (preheader)->dest_idx
+ != single_succ_edge (new_bbs[0])->dest_idx)
+ {
+ basic_block swap_bb = new_bbs[1];
+ gcc_assert (EDGE_COUNT (swap_bb->preds) == 2);
+ std::swap (EDGE_PRED (swap_bb, 0), EDGE_PRED (swap_bb, 1));
+ EDGE_PRED (swap_bb, 0)->dest_idx = 0;
+ EDGE_PRED (swap_bb, 1)->dest_idx = 1;
+ }
+ if (duplicate_outer_loop)
+ {
+ class loop *new_inner_loop = get_loop_copy (scalar_loop->inner);
+ if (loop_preheader_edge (scalar_loop)->dest_idx
+ != loop_preheader_edge (new_inner_loop)->dest_idx)
+ {
+ basic_block swap_bb = new_inner_loop->header;
+ gcc_assert (EDGE_COUNT (swap_bb->preds) == 2);
+ std::swap (EDGE_PRED (swap_bb, 0), EDGE_PRED (swap_bb, 1));
+ EDGE_PRED (swap_bb, 0)->dest_idx = 0;
+ EDGE_PRED (swap_bb, 1)->dest_idx = 1;
+ }
+ }
+
add_phi_args_after_copy (new_bbs, scalar_loop->num_nodes + 1, NULL);
/* Skip new preheader since it's deleted if copy loop is added at entry. */
@@ -2007,13 +2034,29 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters,
niters_vector = force_gimple_operand (niters_vector, &stmts, true, var);
gsi_insert_seq_on_edge_immediate (pe, stmts);
/* Peeling algorithm guarantees that vector loop bound is at least ONE,
- we set range information to make niters analyzer's life easier. */
+ we set range information to make niters analyzer's life easier.
+ Note the number of latch iteration value can be TYPE_MAX_VALUE so
+ we have to represent the vector niter TYPE_MAX_VALUE + 1 >> log_vf. */
if (stmts != NULL && log_vf)
- set_range_info (niters_vector, VR_RANGE,
- wi::to_wide (build_int_cst (type, 1)),
- wi::to_wide (fold_build2 (RSHIFT_EXPR, type,
- TYPE_MAX_VALUE (type),
- log_vf)));
+ {
+ if (niters_no_overflow)
+ set_range_info (niters_vector, VR_RANGE,
+ wi::one (TYPE_PRECISION (type)),
+ wi::rshift (wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type)),
+ exact_log2 (const_vf),
+ TYPE_SIGN (type)));
+ /* For VF == 1 the vector IV might also overflow so we cannot
+ assert a minimum value of 1. */
+ else if (const_vf > 1)
+ set_range_info (niters_vector, VR_RANGE,
+ wi::one (TYPE_PRECISION (type)),
+ wi::rshift (wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type))
+ - (const_vf - 1),
+ exact_log2 (const_vf), TYPE_SIGN (type))
+ + 1);
+ }
}
*niters_vector_ptr = niters_vector;
*step_vector_ptr = step_vector;
@@ -2545,6 +2588,45 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
if (!prolog_peeling && !epilog_peeling)
return NULL;
+ /* Before doing any peeling make sure to reset debug binds outside of
+ the loop refering to defs not in LC SSA. */
+ class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ for (unsigned i = 0; i < loop->num_nodes; ++i)
+ {
+ basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
+ imm_use_iterator ui;
+ gimple *use_stmt;
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, gimple_phi_result (gsi.phi ()))
+ if (gimple_debug_bind_p (use_stmt)
+ && loop != gimple_bb (use_stmt)->loop_father
+ && !flow_loop_nested_p (loop,
+ gimple_bb (use_stmt)->loop_father))
+ {
+ gimple_debug_bind_reset_value (use_stmt);
+ update_stmt (use_stmt);
+ }
+ }
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ ssa_op_iter op_iter;
+ def_operand_p def_p;
+ FOR_EACH_SSA_DEF_OPERAND (def_p, gsi_stmt (gsi), op_iter, SSA_OP_DEF)
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, DEF_FROM_PTR (def_p))
+ if (gimple_debug_bind_p (use_stmt)
+ && loop != gimple_bb (use_stmt)->loop_father
+ && !flow_loop_nested_p (loop,
+ gimple_bb (use_stmt)->loop_father))
+ {
+ gimple_debug_bind_reset_value (use_stmt);
+ update_stmt (use_stmt);
+ }
+ }
+ }
+
prob_vector = profile_probability::guessed_always ().apply_scale (9, 10);
estimated_vf = vect_vf_for_cost (loop_vinfo);
if (estimated_vf == 2)
@@ -2552,7 +2634,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
prob_prolog = prob_epilog = profile_probability::guessed_always ()
.apply_scale (estimated_vf - 1, estimated_vf);
- class loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ class loop *prolog, *epilog = NULL;
class loop *first_loop = loop;
bool irred_flag = loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index e42f327..d6f1ffc 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -666,27 +666,50 @@ vect_fixup_scalar_cycles_with_patterns (loop_vec_info loop_vinfo)
unsigned i;
FOR_EACH_VEC_ELT (LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo), i, first)
- if (STMT_VINFO_IN_PATTERN_P (first))
- {
- stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (first);
- while (next)
- {
- if (! STMT_VINFO_IN_PATTERN_P (next)
- || STMT_VINFO_REDUC_IDX (STMT_VINFO_RELATED_STMT (next)) == -1)
- break;
- next = REDUC_GROUP_NEXT_ELEMENT (next);
- }
- /* If not all stmt in the chain are patterns or if we failed
- to update STMT_VINFO_REDUC_IDX try to handle the chain
- without patterns. */
- if (! next
- && STMT_VINFO_REDUC_IDX (STMT_VINFO_RELATED_STMT (first)) != -1)
- {
- vect_fixup_reduc_chain (first);
- LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo)[i]
- = STMT_VINFO_RELATED_STMT (first);
- }
- }
+ {
+ stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (first);
+ while (next)
+ {
+ if ((STMT_VINFO_IN_PATTERN_P (next)
+ != STMT_VINFO_IN_PATTERN_P (first))
+ || STMT_VINFO_REDUC_IDX (vect_stmt_to_vectorize (next)) == -1)
+ break;
+ next = REDUC_GROUP_NEXT_ELEMENT (next);
+ }
+ /* If all reduction chain members are well-formed patterns adjust
+ the group to group the pattern stmts instead. */
+ if (! next
+ && STMT_VINFO_REDUC_IDX (vect_stmt_to_vectorize (first)) != -1)
+ {
+ if (STMT_VINFO_IN_PATTERN_P (first))
+ {
+ vect_fixup_reduc_chain (first);
+ LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo)[i]
+ = STMT_VINFO_RELATED_STMT (first);
+ }
+ }
+ /* If not all stmt in the chain are patterns or if we failed
+ to update STMT_VINFO_REDUC_IDX dissolve the chain and handle
+ it as regular reduction instead. */
+ else
+ {
+ stmt_vec_info vinfo = first;
+ stmt_vec_info last = NULL;
+ while (vinfo)
+ {
+ next = REDUC_GROUP_NEXT_ELEMENT (vinfo);
+ REDUC_GROUP_FIRST_ELEMENT (vinfo) = NULL;
+ REDUC_GROUP_NEXT_ELEMENT (vinfo) = NULL;
+ last = vinfo;
+ vinfo = next;
+ }
+ STMT_VINFO_DEF_TYPE (vect_stmt_to_vectorize (first))
+ = vect_internal_def;
+ loop_vinfo->reductions.safe_push (vect_stmt_to_vectorize (last));
+ LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo).unordered_remove (i);
+ --i;
+ }
+ }
}
/* Function vect_get_loop_niters.
@@ -1804,6 +1827,19 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
}
}
+ /* If using the "very cheap" model. reject cases in which we'd keep
+ a copy of the scalar code (even if we might be able to vectorize it). */
+ if (flag_vect_cost_model == VECT_COST_MODEL_VERY_CHEAP
+ && (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
+ || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)
+ || LOOP_VINFO_PEELING_FOR_NITER (loop_vinfo)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "some scalar iterations would need to be peeled\n");
+ return 0;
+ }
+
int min_profitable_iters, min_profitable_estimate;
vect_estimate_min_profitable_iters (loop_vinfo, &min_profitable_iters,
&min_profitable_estimate);
@@ -1862,6 +1898,20 @@ vect_analyze_loop_costing (loop_vec_info loop_vinfo)
min_profitable_estimate = min_profitable_iters;
}
+ /* If the vector loop needs multiple iterations to be beneficial then
+ things are probably too close to call, and the conservative thing
+ would be to stick with the scalar code. */
+ if (flag_vect_cost_model == VECT_COST_MODEL_VERY_CHEAP
+ && min_profitable_estimate > (int) vect_vf_for_cost (loop_vinfo))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "one iteration of the vector loop would be"
+ " more expensive than the equivalent number of"
+ " iterations of the scalar loop\n");
+ return 0;
+ }
+
HOST_WIDE_INT estimated_niter;
/* If we are vectorizing an epilogue then we know the maximum number of
@@ -2275,6 +2325,9 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
/* Optimize the SLP graph with the vectorization factor fixed. */
vect_optimize_slp (loop_vinfo);
+
+ /* Gather the loads reachable from the SLP graph entries. */
+ vect_gather_slp_loads (loop_vinfo);
}
bool saved_can_use_partial_vectors_p
@@ -2342,6 +2395,79 @@ start_over:
"unsupported SLP instances\n");
goto again;
}
+
+ /* Check whether any load in ALL SLP instances is possibly permuted. */
+ slp_tree load_node, slp_root;
+ unsigned i, x;
+ slp_instance instance;
+ bool can_use_lanes = true;
+ FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), x, instance)
+ {
+ slp_root = SLP_INSTANCE_TREE (instance);
+ int group_size = SLP_TREE_LANES (slp_root);
+ tree vectype = SLP_TREE_VECTYPE (slp_root);
+ bool loads_permuted = false;
+ FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), i, load_node)
+ {
+ if (!SLP_TREE_LOAD_PERMUTATION (load_node).exists ())
+ continue;
+ unsigned j;
+ stmt_vec_info load_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (load_node), j, load_info)
+ if (SLP_TREE_LOAD_PERMUTATION (load_node)[j] != j)
+ {
+ loads_permuted = true;
+ break;
+ }
+ }
+
+ /* If the loads and stores can be handled with load/store-lane
+ instructions record it and move on to the next instance. */
+ if (loads_permuted
+ && SLP_INSTANCE_KIND (instance) == slp_inst_kind_store
+ && vect_store_lanes_supported (vectype, group_size, false))
+ {
+ FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), i, load_node)
+ {
+ stmt_vec_info stmt_vinfo = DR_GROUP_FIRST_ELEMENT
+ (SLP_TREE_SCALAR_STMTS (load_node)[0]);
+ /* Use SLP for strided accesses (or if we can't
+ load-lanes). */
+ if (STMT_VINFO_STRIDED_P (stmt_vinfo)
+ || ! vect_load_lanes_supported
+ (STMT_VINFO_VECTYPE (stmt_vinfo),
+ DR_GROUP_SIZE (stmt_vinfo), false))
+ break;
+ }
+
+ can_use_lanes
+ = can_use_lanes && i == SLP_INSTANCE_LOADS (instance).length ();
+
+ if (can_use_lanes && dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "SLP instance %p can use load/store-lanes\n",
+ instance);
+ }
+ else
+ {
+ can_use_lanes = false;
+ break;
+ }
+ }
+
+ /* If all SLP instances can use load/store-lanes abort SLP and try again
+ with SLP disabled. */
+ if (can_use_lanes)
+ {
+ ok = opt_result::failure_at (vect_location,
+ "Built SLP cancelled: can use "
+ "load/store-lanes\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Built SLP cancelled: all SLP instances support "
+ "load/store-lanes\n");
+ goto again;
+ }
}
/* Dissolve SLP-only groups. */
@@ -2572,9 +2698,13 @@ again:
STMT_SLP_TYPE (stmt_info) = loop_vect;
if (STMT_VINFO_IN_PATTERN_P (stmt_info))
{
+ stmt_vec_info pattern_stmt_info
+ = STMT_VINFO_RELATED_STMT (stmt_info);
+ if (STMT_VINFO_SLP_VECT_ONLY (pattern_stmt_info))
+ STMT_VINFO_IN_PATTERN_P (stmt_info) = false;
+
gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
- stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
- STMT_SLP_TYPE (stmt_info) = loop_vect;
+ STMT_SLP_TYPE (pattern_stmt_info) = loop_vect;
for (gimple_stmt_iterator pi = gsi_start (pattern_def_seq);
!gsi_end_p (pi); gsi_next (&pi))
STMT_SLP_TYPE (loop_vinfo->lookup_stmt (gsi_stmt (pi)))
@@ -2643,43 +2773,56 @@ vect_better_loop_vinfo_p (loop_vec_info new_loop_vinfo,
/* Check whether the (fractional) cost per scalar iteration is lower
or higher: new_inside_cost / new_vf vs. old_inside_cost / old_vf. */
- poly_widest_int rel_new = (new_loop_vinfo->vec_inside_cost
- * poly_widest_int (old_vf));
- poly_widest_int rel_old = (old_loop_vinfo->vec_inside_cost
- * poly_widest_int (new_vf));
- if (maybe_lt (rel_old, rel_new))
- {
- /* When old_loop_vinfo uses a variable vectorization factor,
- we know that it has a lower cost for at least one runtime VF.
- However, we don't know how likely that VF is.
-
- One option would be to compare the costs for the estimated VFs.
- The problem is that that can put too much pressure on the cost
- model. E.g. if the estimated VF is also the lowest possible VF,
- and if old_loop_vinfo is 1 unit worse than new_loop_vinfo
- for the estimated VF, we'd then choose new_loop_vinfo even
- though (a) new_loop_vinfo might not actually be better than
- old_loop_vinfo for that VF and (b) it would be significantly
- worse at larger VFs.
-
- Here we go for a hacky compromise: pick new_loop_vinfo if it is
- no more expensive than old_loop_vinfo even after doubling the
- estimated old_loop_vinfo VF. For all but trivial loops, this
- ensures that we only pick new_loop_vinfo if it is significantly
- better than old_loop_vinfo at the estimated VF. */
- if (rel_new.is_constant ())
- return false;
+ poly_int64 rel_new = new_loop_vinfo->vec_inside_cost * old_vf;
+ poly_int64 rel_old = old_loop_vinfo->vec_inside_cost * new_vf;
+
+ HOST_WIDE_INT est_rel_new_min
+ = estimated_poly_value (rel_new, POLY_VALUE_MIN);
+ HOST_WIDE_INT est_rel_new_max
+ = estimated_poly_value (rel_new, POLY_VALUE_MAX);
+
+ HOST_WIDE_INT est_rel_old_min
+ = estimated_poly_value (rel_old, POLY_VALUE_MIN);
+ HOST_WIDE_INT est_rel_old_max
+ = estimated_poly_value (rel_old, POLY_VALUE_MAX);
+
+ /* Check first if we can make out an unambigous total order from the minimum
+ and maximum estimates. */
+ if (est_rel_new_min < est_rel_old_min
+ && est_rel_new_max < est_rel_old_max)
+ return true;
+ else if (est_rel_old_min < est_rel_new_min
+ && est_rel_old_max < est_rel_new_max)
+ return false;
+ /* When old_loop_vinfo uses a variable vectorization factor,
+ we know that it has a lower cost for at least one runtime VF.
+ However, we don't know how likely that VF is.
+
+ One option would be to compare the costs for the estimated VFs.
+ The problem is that that can put too much pressure on the cost
+ model. E.g. if the estimated VF is also the lowest possible VF,
+ and if old_loop_vinfo is 1 unit worse than new_loop_vinfo
+ for the estimated VF, we'd then choose new_loop_vinfo even
+ though (a) new_loop_vinfo might not actually be better than
+ old_loop_vinfo for that VF and (b) it would be significantly
+ worse at larger VFs.
+
+ Here we go for a hacky compromise: pick new_loop_vinfo if it is
+ no more expensive than old_loop_vinfo even after doubling the
+ estimated old_loop_vinfo VF. For all but trivial loops, this
+ ensures that we only pick new_loop_vinfo if it is significantly
+ better than old_loop_vinfo at the estimated VF. */
- HOST_WIDE_INT new_estimated_vf = estimated_poly_value (new_vf);
- HOST_WIDE_INT old_estimated_vf = estimated_poly_value (old_vf);
- widest_int estimated_rel_new = (new_loop_vinfo->vec_inside_cost
- * widest_int (old_estimated_vf));
- widest_int estimated_rel_old = (old_loop_vinfo->vec_inside_cost
- * widest_int (new_estimated_vf));
- return estimated_rel_new * 2 <= estimated_rel_old;
+ if (est_rel_old_min != est_rel_new_min
+ || est_rel_old_max != est_rel_new_max)
+ {
+ HOST_WIDE_INT est_rel_new_likely
+ = estimated_poly_value (rel_new, POLY_VALUE_LIKELY);
+ HOST_WIDE_INT est_rel_old_likely
+ = estimated_poly_value (rel_old, POLY_VALUE_LIKELY);
+
+ return est_rel_new_likely * 2 <= est_rel_old_likely;
}
- if (known_lt (rel_new, rel_old))
- return true;
/* If there's nothing to choose between the loop bodies, see whether
there's a difference in the prologue and epilogue costs. */
@@ -3230,14 +3373,17 @@ pop:
fail = true;
break;
}
- /* Check there's only a single stmt the op is used on inside
- of the loop. */
+ /* Check there's only a single stmt the op is used on. For the
+ not value-changing tail and the last stmt allow out-of-loop uses.
+ ??? We could relax this and handle arbitrary live stmts by
+ forcing a scalar epilogue for example. */
imm_use_iterator imm_iter;
gimple *op_use_stmt;
unsigned cnt = 0;
FOR_EACH_IMM_USE_STMT (op_use_stmt, imm_iter, op)
if (!is_gimple_debug (op_use_stmt)
- && flow_bb_inside_loop_p (loop, gimple_bb (op_use_stmt)))
+ && (*code != ERROR_MARK
+ || flow_bb_inside_loop_p (loop, gimple_bb (op_use_stmt))))
{
/* We want to allow x + x but not x < 1 ? x : 2. */
if (is_gimple_assign (op_use_stmt)
@@ -4420,34 +4566,6 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo,
}
-/* Function vect_model_induction_cost.
-
- Models cost for induction operations. */
-
-static void
-vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies,
- stmt_vector_for_cost *cost_vec)
-{
- unsigned inside_cost, prologue_cost;
-
- if (PURE_SLP_STMT (stmt_info))
- return;
-
- /* loop cost for vec_loop. */
- inside_cost = record_stmt_cost (cost_vec, ncopies, vector_stmt,
- stmt_info, 0, vect_body);
-
- /* prologue cost for vec_init and vec_step. */
- prologue_cost = record_stmt_cost (cost_vec, 2, scalar_to_vec,
- stmt_info, 0, vect_prologue);
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "vect_model_induction_cost: inside_cost = %d, "
- "prologue_cost = %d .\n", inside_cost, prologue_cost);
-}
-
-
/* Function get_initial_def_for_reduction
@@ -5160,8 +5278,8 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo,
int scalar_precision
= GET_MODE_PRECISION (SCALAR_TYPE_MODE (scalar_type));
tree scalar_type_unsigned = make_unsigned_type (scalar_precision);
- tree vectype_unsigned = build_vector_type
- (scalar_type_unsigned, TYPE_VECTOR_SUBPARTS (vectype));
+ tree vectype_unsigned = get_same_sized_vectype (scalar_type_unsigned,
+ vectype);
/* First we need to create a vector (ZERO_VEC) of zeros and another
vector (MAX_INDEX_VEC) filled with the last matching index, which we
@@ -6313,9 +6431,28 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle)
{
if (is_a <gphi *> (stmt_info->stmt))
- /* Analysis for double-reduction is done on the outer
- loop PHI, nested cycles have no further restrictions. */
- STMT_VINFO_TYPE (stmt_info) = cycle_phi_info_type;
+ {
+ if (slp_node)
+ {
+ /* We eventually need to set a vector type on invariant
+ arguments. */
+ unsigned j;
+ slp_tree child;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (slp_node), j, child)
+ if (!vect_maybe_update_slp_op_vectype
+ (child, SLP_TREE_VECTYPE (slp_node)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "incompatible vector types for "
+ "invariants\n");
+ return false;
+ }
+ }
+ /* Analysis for double-reduction is done on the outer
+ loop PHI, nested cycles have no further restrictions. */
+ STMT_VINFO_TYPE (stmt_info) = cycle_phi_info_type;
+ }
else
STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
return true;
@@ -6805,8 +6942,8 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
int scalar_precision
= GET_MODE_PRECISION (SCALAR_TYPE_MODE (scalar_type));
cr_index_scalar_type = make_unsigned_type (scalar_precision);
- cr_index_vector_type = build_vector_type (cr_index_scalar_type,
- nunits_out);
+ cr_index_vector_type = get_same_sized_vectype (cr_index_scalar_type,
+ vectype_out);
if (direct_internal_fn_supported_p (IFN_REDUC_MAX, cr_index_vector_type,
OPTIMIZE_FOR_SPEED))
@@ -7377,15 +7514,24 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo,
if (slp_node)
{
vec_initial_defs.reserve (vec_num);
- gcc_assert (slp_node == slp_node_instance->reduc_phis);
- stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info);
- tree neutral_op
- = neutral_op_for_slp_reduction (slp_node, vectype_out,
- STMT_VINFO_REDUC_CODE (reduc_info),
- first != NULL);
- get_initial_defs_for_reduction (loop_vinfo, slp_node_instance->reduc_phis,
- &vec_initial_defs, vec_num,
- first != NULL, neutral_op);
+ if (nested_cycle)
+ {
+ unsigned phi_idx = loop_preheader_edge (loop)->dest_idx;
+ vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[phi_idx],
+ &vec_initial_defs);
+ }
+ else
+ {
+ gcc_assert (slp_node == slp_node_instance->reduc_phis);
+ stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info);
+ tree neutral_op
+ = neutral_op_for_slp_reduction (slp_node, vectype_out,
+ STMT_VINFO_REDUC_CODE (reduc_info),
+ first != NULL);
+ get_initial_defs_for_reduction (loop_vinfo, slp_node_instance->reduc_phis,
+ &vec_initial_defs, vec_num,
+ first != NULL, neutral_op);
+ }
}
else
{
@@ -7491,6 +7637,17 @@ vectorizable_lc_phi (loop_vec_info loop_vinfo,
if (!vec_stmt) /* transformation not required. */
{
+ /* Deal with copies from externs or constants that disguise as
+ loop-closed PHI nodes (PR97886). */
+ if (slp_node
+ && !vect_maybe_update_slp_op_vectype (SLP_TREE_CHILDREN (slp_node)[0],
+ SLP_TREE_VECTYPE (slp_node)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "incompatible vector types for invariants\n");
+ return false;
+ }
STMT_VINFO_TYPE (stmt_info) = lc_phi_info_type;
return true;
}
@@ -7520,6 +7677,81 @@ vectorizable_lc_phi (loop_vec_info loop_vinfo,
return true;
}
+/* Vectorizes PHIs. */
+
+bool
+vectorizable_phi (vec_info *,
+ stmt_vec_info stmt_info, gimple **vec_stmt,
+ slp_tree slp_node, stmt_vector_for_cost *cost_vec)
+{
+ if (!is_a <gphi *> (stmt_info->stmt) || !slp_node)
+ return false;
+
+ if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
+ return false;
+
+ tree vectype = SLP_TREE_VECTYPE (slp_node);
+
+ if (!vec_stmt) /* transformation not required. */
+ {
+ slp_tree child;
+ unsigned i;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (slp_node), i, child)
+ if (!child)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "PHI node with unvectorized backedge def\n");
+ return false;
+ }
+ else if (!vect_maybe_update_slp_op_vectype (child, vectype))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "incompatible vector types for invariants\n");
+ return false;
+ }
+ record_stmt_cost (cost_vec, SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
+ vector_stmt, stmt_info, vectype, 0, vect_body);
+ STMT_VINFO_TYPE (stmt_info) = phi_info_type;
+ return true;
+ }
+
+ tree scalar_dest = gimple_phi_result (stmt_info->stmt);
+ basic_block bb = gimple_bb (stmt_info->stmt);
+ tree vec_dest = vect_create_destination_var (scalar_dest, vectype);
+ auto_vec<gphi *> new_phis;
+ for (unsigned i = 0; i < gimple_phi_num_args (stmt_info->stmt); ++i)
+ {
+ slp_tree child = SLP_TREE_CHILDREN (slp_node)[i];
+
+ /* Skip not yet vectorized defs. */
+ if (SLP_TREE_DEF_TYPE (child) == vect_internal_def
+ && SLP_TREE_VEC_STMTS (child).is_empty ())
+ continue;
+
+ auto_vec<tree> vec_oprnds;
+ vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[i], &vec_oprnds);
+ if (!new_phis.exists ())
+ {
+ new_phis.create (vec_oprnds.length ());
+ for (unsigned j = 0; j < vec_oprnds.length (); j++)
+ {
+ /* Create the vectorized LC PHI node. */
+ new_phis.quick_push (create_phi_node (vec_dest, bb));
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phis[j]);
+ }
+ }
+ edge e = gimple_phi_arg_edge (as_a <gphi *> (stmt_info->stmt), i);
+ for (unsigned j = 0; j < vec_oprnds.length (); j++)
+ add_phi_arg (new_phis[j], vec_oprnds[j], e, UNKNOWN_LOCATION);
+ }
+ /* We should have at least one already vectorized child. */
+ gcc_assert (new_phis.exists ());
+
+ return true;
+}
+
/* Function vect_min_worthwhile_factor.
@@ -7590,7 +7822,6 @@ vectorizable_induction (loop_vec_info loop_vinfo,
poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
unsigned i;
tree expr;
- gimple_seq stmts;
gimple_stmt_iterator si;
gphi *phi = dyn_cast <gphi *> (stmt_info->stmt);
@@ -7630,10 +7861,6 @@ vectorizable_induction (loop_vec_info loop_vinfo,
return false;
}
- /* FORNOW: outer loop induction with SLP not supported. */
- if (STMT_SLP_TYPE (stmt_info))
- return false;
-
exit_phi = NULL;
latch_e = loop_latch_edge (loop->inner);
loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
@@ -7672,7 +7899,7 @@ vectorizable_induction (loop_vec_info loop_vinfo,
if (slp_node && !nunits.is_constant ())
{
- /* The current SLP code creates the initial value element-by-element. */
+ /* The current SLP code creates the step value element-by-element. */
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"SLP induction not supported for variable-length"
@@ -7682,9 +7909,50 @@ vectorizable_induction (loop_vec_info loop_vinfo,
if (!vec_stmt) /* transformation not required. */
{
+ unsigned inside_cost = 0, prologue_cost = 0;
+ if (slp_node)
+ {
+ /* We eventually need to set a vector type on invariant
+ arguments. */
+ unsigned j;
+ slp_tree child;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (slp_node), j, child)
+ if (!vect_maybe_update_slp_op_vectype
+ (child, SLP_TREE_VECTYPE (slp_node)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "incompatible vector types for "
+ "invariants\n");
+ return false;
+ }
+ /* loop cost for vec_loop. */
+ inside_cost
+ = record_stmt_cost (cost_vec,
+ SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
+ vector_stmt, stmt_info, 0, vect_body);
+ /* prologue cost for vec_init (if not nested) and step. */
+ prologue_cost = record_stmt_cost (cost_vec, 1 + !nested_in_vect_loop,
+ scalar_to_vec,
+ stmt_info, 0, vect_prologue);
+ }
+ else /* if (!slp_node) */
+ {
+ /* loop cost for vec_loop. */
+ inside_cost = record_stmt_cost (cost_vec, ncopies, vector_stmt,
+ stmt_info, 0, vect_body);
+ /* prologue cost for vec_init and vec_step. */
+ prologue_cost = record_stmt_cost (cost_vec, 2, scalar_to_vec,
+ stmt_info, 0, vect_prologue);
+ }
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "vect_model_induction_cost: inside_cost = %d, "
+ "prologue_cost = %d .\n", inside_cost,
+ prologue_cost);
+
STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_induction");
- vect_model_induction_cost (stmt_info, ncopies, cost_vec);
return true;
}
@@ -7703,164 +7971,195 @@ vectorizable_induction (loop_vec_info loop_vinfo,
tree step_vectype = get_same_sized_vectype (TREE_TYPE (step_expr), vectype);
pe = loop_preheader_edge (iv_loop);
- init_expr = PHI_ARG_DEF_FROM_EDGE (phi,
- loop_preheader_edge (iv_loop));
-
- stmts = NULL;
- if (!nested_in_vect_loop)
- {
- /* Convert the initial value to the IV update type. */
- tree new_type = TREE_TYPE (step_expr);
- init_expr = gimple_convert (&stmts, new_type, init_expr);
-
- /* If we are using the loop mask to "peel" for alignment then we need
- to adjust the start value here. */
- tree skip_niters = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
- if (skip_niters != NULL_TREE)
- {
- if (FLOAT_TYPE_P (vectype))
- skip_niters = gimple_build (&stmts, FLOAT_EXPR, new_type,
- skip_niters);
- else
- skip_niters = gimple_convert (&stmts, new_type, skip_niters);
- tree skip_step = gimple_build (&stmts, MULT_EXPR, new_type,
- skip_niters, step_expr);
- init_expr = gimple_build (&stmts, MINUS_EXPR, new_type,
- init_expr, skip_step);
- }
- }
-
- if (stmts)
- {
- new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
- gcc_assert (!new_bb);
- }
-
/* Find the first insertion point in the BB. */
basic_block bb = gimple_bb (phi);
si = gsi_after_labels (bb);
/* For SLP induction we have to generate several IVs as for example
- with group size 3 we need [i, i, i, i + S] [i + S, i + S, i + 2*S, i + 2*S]
- [i + 2*S, i + 3*S, i + 3*S, i + 3*S]. The step is the same uniform
- [VF*S, VF*S, VF*S, VF*S] for all. */
+ with group size 3 we need
+ [i0, i1, i2, i0 + S0] [i1 + S1, i2 + S2, i0 + 2*S0, i1 + 2*S1]
+ [i2 + 2*S2, i0 + 3*S0, i1 + 3*S1, i2 + 3*S2]. */
if (slp_node)
{
/* Enforced above. */
unsigned int const_nunits = nunits.to_constant ();
- /* Generate [VF*S, VF*S, ... ]. */
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (step_expr)))
+ /* The initial values are vectorized, but any lanes > group_size
+ need adjustment. */
+ slp_tree init_node
+ = SLP_TREE_CHILDREN (slp_node)[pe->dest_idx];
+
+ /* Gather steps. Since we do not vectorize inductions as
+ cycles we have to reconstruct the step from SCEV data. */
+ unsigned group_size = SLP_TREE_LANES (slp_node);
+ tree *steps = XALLOCAVEC (tree, group_size);
+ tree *inits = XALLOCAVEC (tree, group_size);
+ stmt_vec_info phi_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, phi_info)
{
- expr = build_int_cst (integer_type_node, vf);
- expr = fold_convert (TREE_TYPE (step_expr), expr);
+ steps[i] = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (phi_info);
+ if (!init_node)
+ inits[i] = gimple_phi_arg_def (as_a<gphi *> (phi_info->stmt),
+ pe->dest_idx);
}
- else
- expr = build_int_cst (TREE_TYPE (step_expr), vf);
- new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
- expr, step_expr);
- if (! CONSTANT_CLASS_P (new_name))
- new_name = vect_init_vector (loop_vinfo, stmt_info, new_name,
- TREE_TYPE (step_expr), NULL);
- new_vec = build_vector_from_val (step_vectype, new_name);
- vec_step = vect_init_vector (loop_vinfo, stmt_info,
- new_vec, step_vectype, NULL);
/* Now generate the IVs. */
- unsigned group_size = SLP_TREE_LANES (slp_node);
unsigned nvects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
- unsigned elts = const_nunits * nvects;
- /* Compute the number of distinct IVs we need. First reduce
- group_size if it is a multiple of const_nunits so we get
- one IV for a group_size of 4 but const_nunits 2. */
- unsigned group_sizep = group_size;
- if (group_sizep % const_nunits == 0)
- group_sizep = group_sizep / const_nunits;
- unsigned nivs = least_common_multiple (group_sizep,
- const_nunits) / const_nunits;
- gcc_assert (elts % group_size == 0);
- tree elt = init_expr;
+ gcc_assert ((const_nunits * nvects) % group_size == 0);
+ unsigned nivs;
+ if (nested_in_vect_loop)
+ nivs = nvects;
+ else
+ {
+ /* Compute the number of distinct IVs we need. First reduce
+ group_size if it is a multiple of const_nunits so we get
+ one IV for a group_size of 4 but const_nunits 2. */
+ unsigned group_sizep = group_size;
+ if (group_sizep % const_nunits == 0)
+ group_sizep = group_sizep / const_nunits;
+ nivs = least_common_multiple (group_sizep,
+ const_nunits) / const_nunits;
+ }
+ tree stept = TREE_TYPE (step_vectype);
+ tree lupdate_mul = NULL_TREE;
+ if (!nested_in_vect_loop)
+ {
+ /* The number of iterations covered in one vector iteration. */
+ unsigned lup_mul = (nvects * const_nunits) / group_size;
+ lupdate_mul
+ = build_vector_from_val (step_vectype,
+ SCALAR_FLOAT_TYPE_P (stept)
+ ? build_real_from_wide (stept, lup_mul,
+ UNSIGNED)
+ : build_int_cstu (stept, lup_mul));
+ }
+ tree peel_mul = NULL_TREE;
+ gimple_seq init_stmts = NULL;
+ if (LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo))
+ {
+ if (SCALAR_FLOAT_TYPE_P (stept))
+ peel_mul = gimple_build (&init_stmts, FLOAT_EXPR, stept,
+ LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo));
+ else
+ peel_mul = gimple_convert (&init_stmts, stept,
+ LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo));
+ peel_mul = gimple_build_vector_from_val (&init_stmts,
+ step_vectype, peel_mul);
+ }
unsigned ivn;
+ auto_vec<tree> vec_steps;
for (ivn = 0; ivn < nivs; ++ivn)
{
- tree_vector_builder elts (step_vectype, const_nunits, 1);
- stmts = NULL;
+ tree_vector_builder step_elts (step_vectype, const_nunits, 1);
+ tree_vector_builder init_elts (vectype, const_nunits, 1);
+ tree_vector_builder mul_elts (step_vectype, const_nunits, 1);
for (unsigned eltn = 0; eltn < const_nunits; ++eltn)
{
- if (ivn*const_nunits + eltn >= group_size
- && (ivn * const_nunits + eltn) % group_size == 0)
- elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),
- elt, step_expr);
- elts.quick_push (elt);
- }
- vec_init = gimple_build_vector (&stmts, &elts);
- vec_init = gimple_convert (&stmts, vectype, vec_init);
- if (stmts)
- {
- new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
- gcc_assert (!new_bb);
+ /* The scalar steps of the IVs. */
+ tree elt = steps[(ivn*const_nunits + eltn) % group_size];
+ elt = gimple_convert (&init_stmts, TREE_TYPE (step_vectype), elt);
+ step_elts.quick_push (elt);
+ if (!init_node)
+ {
+ /* The scalar inits of the IVs if not vectorized. */
+ elt = inits[(ivn*const_nunits + eltn) % group_size];
+ if (!useless_type_conversion_p (TREE_TYPE (vectype),
+ TREE_TYPE (elt)))
+ elt = gimple_build (&init_stmts, VIEW_CONVERT_EXPR,
+ TREE_TYPE (vectype), elt);
+ init_elts.quick_push (elt);
+ }
+ /* The number of steps to add to the initial values. */
+ unsigned mul_elt = (ivn*const_nunits + eltn) / group_size;
+ mul_elts.quick_push (SCALAR_FLOAT_TYPE_P (stept)
+ ? build_real_from_wide (stept,
+ mul_elt, UNSIGNED)
+ : build_int_cstu (stept, mul_elt));
}
+ vec_step = gimple_build_vector (&init_stmts, &step_elts);
+ vec_steps.safe_push (vec_step);
+ tree step_mul = gimple_build_vector (&init_stmts, &mul_elts);
+ if (peel_mul)
+ step_mul = gimple_build (&init_stmts, PLUS_EXPR, step_vectype,
+ step_mul, peel_mul);
+ if (!init_node)
+ vec_init = gimple_build_vector (&init_stmts, &init_elts);
/* Create the induction-phi that defines the induction-operand. */
- vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");
+ vec_dest = vect_get_new_vect_var (vectype, vect_simple_var,
+ "vec_iv_");
induction_phi = create_phi_node (vec_dest, iv_loop->header);
induc_def = PHI_RESULT (induction_phi);
/* Create the iv update inside the loop */
+ tree up = vec_step;
+ if (lupdate_mul)
+ up = gimple_build (&init_stmts, MULT_EXPR, step_vectype,
+ vec_step, lupdate_mul);
gimple_seq stmts = NULL;
vec_def = gimple_convert (&stmts, step_vectype, induc_def);
vec_def = gimple_build (&stmts,
- PLUS_EXPR, step_vectype, vec_def, vec_step);
+ PLUS_EXPR, step_vectype, vec_def, up);
vec_def = gimple_convert (&stmts, vectype, vec_def);
gsi_insert_seq_before (&si, stmts, GSI_SAME_STMT);
+ add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop),
+ UNKNOWN_LOCATION);
+
+ if (init_node)
+ vec_init = vect_get_slp_vect_def (init_node, ivn);
+ if (!nested_in_vect_loop
+ && !integer_zerop (step_mul))
+ {
+ vec_def = gimple_convert (&init_stmts, step_vectype, vec_init);
+ up = gimple_build (&init_stmts, MULT_EXPR, step_vectype,
+ vec_step, step_mul);
+ vec_def = gimple_build (&init_stmts, PLUS_EXPR, step_vectype,
+ vec_def, up);
+ vec_init = gimple_convert (&init_stmts, vectype, vec_def);
+ }
/* Set the arguments of the phi node: */
add_phi_arg (induction_phi, vec_init, pe, UNKNOWN_LOCATION);
- add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop),
- UNKNOWN_LOCATION);
SLP_TREE_VEC_STMTS (slp_node).quick_push (induction_phi);
}
- /* Fill up to the number of vectors we need for the whole group. */
- nivs = least_common_multiple (group_size,
- const_nunits) / const_nunits;
- for (; ivn < nivs; ++ivn)
- SLP_TREE_VEC_STMTS (slp_node)
- .quick_push (SLP_TREE_VEC_STMTS (slp_node)[0]);
+ if (!nested_in_vect_loop)
+ {
+ /* Fill up to the number of vectors we need for the whole group. */
+ nivs = least_common_multiple (group_size,
+ const_nunits) / const_nunits;
+ for (; ivn < nivs; ++ivn)
+ {
+ SLP_TREE_VEC_STMTS (slp_node)
+ .quick_push (SLP_TREE_VEC_STMTS (slp_node)[0]);
+ vec_steps.safe_push (vec_steps[0]);
+ }
+ }
- /* Re-use IVs when we can. */
+ /* Re-use IVs when we can. We are generating further vector
+ stmts by adding VF' * stride to the IVs generated above. */
if (ivn < nvects)
{
unsigned vfp
= least_common_multiple (group_size, const_nunits) / group_size;
- /* Generate [VF'*S, VF'*S, ... ]. */
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (step_expr)))
- {
- expr = build_int_cst (integer_type_node, vfp);
- expr = fold_convert (TREE_TYPE (step_expr), expr);
- }
- else
- expr = build_int_cst (TREE_TYPE (step_expr), vfp);
- new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
- expr, step_expr);
- if (! CONSTANT_CLASS_P (new_name))
- new_name = vect_init_vector (loop_vinfo, stmt_info, new_name,
- TREE_TYPE (step_expr), NULL);
- new_vec = build_vector_from_val (step_vectype, new_name);
- vec_step = vect_init_vector (loop_vinfo, stmt_info, new_vec,
- step_vectype, NULL);
+ tree lupdate_mul
+ = build_vector_from_val (step_vectype,
+ SCALAR_FLOAT_TYPE_P (stept)
+ ? build_real_from_wide (stept,
+ vfp, UNSIGNED)
+ : build_int_cstu (stept, vfp));
for (; ivn < nvects; ++ivn)
{
gimple *iv = SLP_TREE_VEC_STMTS (slp_node)[ivn - nivs];
- tree def;
- if (gimple_code (iv) == GIMPLE_PHI)
- def = gimple_phi_result (iv);
- else
- def = gimple_assign_lhs (iv);
+ tree def = gimple_get_lhs (iv);
+ if (ivn < 2*nivs)
+ vec_steps[ivn - nivs]
+ = gimple_build (&init_stmts, MULT_EXPR, step_vectype,
+ vec_steps[ivn - nivs], lupdate_mul);
gimple_seq stmts = NULL;
def = gimple_convert (&stmts, step_vectype, def);
- def = gimple_build (&stmts,
- PLUS_EXPR, step_vectype, def, vec_step);
+ def = gimple_build (&stmts, PLUS_EXPR, step_vectype,
+ def, vec_steps[ivn % nivs]);
def = gimple_convert (&stmts, vectype, def);
if (gimple_code (iv) == GIMPLE_PHI)
gsi_insert_seq_before (&si, stmts, GSI_SAME_STMT);
@@ -7874,9 +8173,45 @@ vectorizable_induction (loop_vec_info loop_vinfo,
}
}
+ new_bb = gsi_insert_seq_on_edge_immediate (pe, init_stmts);
+ gcc_assert (!new_bb);
+
return true;
}
+ init_expr = PHI_ARG_DEF_FROM_EDGE (phi,
+ loop_preheader_edge (iv_loop));
+
+ gimple_seq stmts = NULL;
+ if (!nested_in_vect_loop)
+ {
+ /* Convert the initial value to the IV update type. */
+ tree new_type = TREE_TYPE (step_expr);
+ init_expr = gimple_convert (&stmts, new_type, init_expr);
+
+ /* If we are using the loop mask to "peel" for alignment then we need
+ to adjust the start value here. */
+ tree skip_niters = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
+ if (skip_niters != NULL_TREE)
+ {
+ if (FLOAT_TYPE_P (vectype))
+ skip_niters = gimple_build (&stmts, FLOAT_EXPR, new_type,
+ skip_niters);
+ else
+ skip_niters = gimple_convert (&stmts, new_type, skip_niters);
+ tree skip_step = gimple_build (&stmts, MULT_EXPR, new_type,
+ skip_niters, step_expr);
+ init_expr = gimple_build (&stmts, MINUS_EXPR, new_type,
+ init_expr, skip_step);
+ }
+ }
+
+ if (stmts)
+ {
+ new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
+ gcc_assert (!new_bb);
+ }
+
/* Create the vector that holds the initial_value of the induction. */
if (nested_in_vect_loop)
{
@@ -8376,8 +8711,19 @@ vectorizable_live_operation (vec_info *vinfo,
gimple_seq stmts = NULL;
new_tree = force_gimple_operand (fold_convert (lhs_type, new_tree),
&stmts, true, NULL_TREE);
-
- gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ if (TREE_CODE (new_tree) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree) = 1;
+ if (is_a <gphi *> (vec_stmt))
+ {
+ gimple_stmt_iterator si = gsi_after_labels (gimple_bb (vec_stmt));
+ gsi_insert_seq_before (&si, stmts, GSI_SAME_STMT);
+ }
+ else
+ {
+ gimple_stmt_iterator si = gsi_for_stmt (vec_stmt);
+ gsi_insert_seq_after (&si, stmts, GSI_SAME_STMT);
+ }
/* Replace use of lhs with newly computed result. If the use stmt is a
single arg PHI, just replace all uses of PHI result. It's necessary
@@ -8414,6 +8760,24 @@ vectorizable_live_operation (vec_info *vinfo,
"def\n");
continue;
}
+ /* ??? It can also happen that we end up pulling a def into
+ a loop where replacing out-of-loop uses would require
+ a new LC SSA PHI node. Retain the original scalar in
+ those cases as well. PR98064. */
+ if (TREE_CODE (new_tree) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (new_tree)
+ && (gimple_bb (use_stmt)->loop_father
+ != gimple_bb (vec_stmt)->loop_father)
+ && !flow_loop_nested_p (gimple_bb (vec_stmt)->loop_father,
+ gimple_bb (use_stmt)->loop_father))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Using original scalar computation for "
+ "live lane because there is an out-of-loop "
+ "definition for it\n");
+ continue;
+ }
FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
SET_USE (use_p, new_tree);
update_stmt (use_stmt);
@@ -8734,7 +9098,7 @@ maybe_set_vectorized_backedge_value (loop_vec_info loop_vinfo,
When vectorizing STMT_INFO as a store, set *SEEN_STORE to its
stmt_vec_info. */
-static void
+static bool
vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi, stmt_vec_info *seen_store)
{
@@ -8750,7 +9114,7 @@ vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
- return;
+ return false;
if (STMT_VINFO_VECTYPE (stmt_info))
{
@@ -8767,13 +9131,15 @@ vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
/* Pure SLP statements have already been vectorized. We still need
to apply loop vectorization to hybrid SLP statements. */
if (PURE_SLP_STMT (stmt_info))
- return;
+ return false;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "transform statement.\n");
if (vect_transform_stmt (loop_vinfo, stmt_info, gsi, NULL, NULL))
*seen_store = stmt_info;
+
+ return true;
}
/* Helper function to pass to simplify_replace_tree to enable replacing tree's
@@ -9199,17 +9565,17 @@ vect_transform_loop (loop_vec_info loop_vinfo, gimple *loop_vectorized_call)
}
stmt_vec_info pat_stmt_info
= STMT_VINFO_RELATED_STMT (stmt_info);
- vect_transform_loop_stmt (loop_vinfo, pat_stmt_info, &si,
- &seen_store);
- maybe_set_vectorized_backedge_value (loop_vinfo,
- pat_stmt_info);
+ if (vect_transform_loop_stmt (loop_vinfo, pat_stmt_info,
+ &si, &seen_store))
+ maybe_set_vectorized_backedge_value (loop_vinfo,
+ pat_stmt_info);
}
else
{
- vect_transform_loop_stmt (loop_vinfo, stmt_info, &si,
- &seen_store);
- maybe_set_vectorized_backedge_value (loop_vinfo,
- stmt_info);
+ if (vect_transform_loop_stmt (loop_vinfo, stmt_info, &si,
+ &seen_store))
+ maybe_set_vectorized_backedge_value (loop_vinfo,
+ stmt_info);
}
}
gsi_next (&si);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index ac56ace..ff1358a 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -1148,7 +1148,7 @@ vect_recog_sad_pattern (vec_info *vinfo,
/* FORNOW. Can continue analyzing the def-use chain when this stmt in a phi
inside the loop (in case we are analyzing an outer-loop). */
vect_unpromoted_value unprom[2];
- if (!vect_widened_op_tree (vinfo, diff_stmt_vinfo, MINUS_EXPR, MINUS_EXPR,
+ if (!vect_widened_op_tree (vinfo, diff_stmt_vinfo, MINUS_EXPR, WIDEN_MINUS_EXPR,
false, 2, unprom, &half_type))
return NULL;
@@ -1262,6 +1262,29 @@ vect_recog_widen_mult_pattern (vec_info *vinfo, stmt_vec_info last_stmt_info,
"vect_recog_widen_mult_pattern");
}
+/* Try to detect addition on widened inputs, converting PLUS_EXPR
+ to WIDEN_PLUS_EXPR. See vect_recog_widen_op_pattern for details. */
+
+static gimple *
+vect_recog_widen_plus_pattern (vec_info *vinfo, stmt_vec_info last_stmt_info,
+ tree *type_out)
+{
+ return vect_recog_widen_op_pattern (vinfo, last_stmt_info, type_out,
+ PLUS_EXPR, WIDEN_PLUS_EXPR, false,
+ "vect_recog_widen_plus_pattern");
+}
+
+/* Try to detect subtraction on widened inputs, converting MINUS_EXPR
+ to WIDEN_MINUS_EXPR. See vect_recog_widen_op_pattern for details. */
+static gimple *
+vect_recog_widen_minus_pattern (vec_info *vinfo, stmt_vec_info last_stmt_info,
+ tree *type_out)
+{
+ return vect_recog_widen_op_pattern (vinfo, last_stmt_info, type_out,
+ MINUS_EXPR, WIDEN_MINUS_EXPR, false,
+ "vect_recog_widen_minus_pattern");
+}
+
/* Function vect_recog_pow_pattern
Try to find the following pattern:
@@ -1978,7 +2001,7 @@ vect_recog_average_pattern (vec_info *vinfo,
vect_unpromoted_value unprom[3];
tree new_type;
unsigned int nops = vect_widened_op_tree (vinfo, plus_stmt_info, PLUS_EXPR,
- PLUS_EXPR, false, 3,
+ WIDEN_PLUS_EXPR, false, 3,
unprom, &new_type);
if (nops == 0)
return NULL;
@@ -4044,7 +4067,7 @@ vect_recog_bool_pattern (vec_info *vinfo,
|| rhs_code == VIEW_CONVERT_EXPR)
{
if (! INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || TYPE_PRECISION (TREE_TYPE (lhs)) == 1)
+ || VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
return NULL;
vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
if (vectype == NULL_TREE)
@@ -5007,6 +5030,8 @@ possible_vector_mask_operation_p (stmt_vec_info stmt_info)
return TREE_CODE_CLASS (rhs_code) == tcc_comparison;
}
}
+ else if (is_a <gphi *> (stmt_info->stmt))
+ return true;
return false;
}
@@ -5017,47 +5042,40 @@ possible_vector_mask_operation_p (stmt_vec_info stmt_info)
static void
vect_determine_mask_precision (vec_info *vinfo, stmt_vec_info stmt_info)
{
- if (!possible_vector_mask_operation_p (stmt_info)
- || stmt_info->mask_precision)
+ if (!possible_vector_mask_operation_p (stmt_info))
return;
- auto_vec<stmt_vec_info, 32> worklist;
- worklist.quick_push (stmt_info);
- while (!worklist.is_empty ())
- {
- stmt_info = worklist.last ();
- unsigned int orig_length = worklist.length ();
-
- /* If at least one boolean input uses a vector mask type,
- pick the mask type with the narrowest elements.
+ /* If at least one boolean input uses a vector mask type,
+ pick the mask type with the narrowest elements.
- ??? This is the traditional behavior. It should always produce
- the smallest number of operations, but isn't necessarily the
- optimal choice. For example, if we have:
+ ??? This is the traditional behavior. It should always produce
+ the smallest number of operations, but isn't necessarily the
+ optimal choice. For example, if we have:
- a = b & c
+ a = b & c
- where:
+ where:
- - the user of a wants it to have a mask type for 16-bit elements (M16)
- - b also uses M16
- - c uses a mask type for 8-bit elements (M8)
+ - the user of a wants it to have a mask type for 16-bit elements (M16)
+ - b also uses M16
+ - c uses a mask type for 8-bit elements (M8)
- then picking M8 gives:
+ then picking M8 gives:
- - 1 M16->M8 pack for b
- - 1 M8 AND for a
- - 2 M8->M16 unpacks for the user of a
+ - 1 M16->M8 pack for b
+ - 1 M8 AND for a
+ - 2 M8->M16 unpacks for the user of a
- whereas picking M16 would have given:
+ whereas picking M16 would have given:
- - 2 M8->M16 unpacks for c
- - 2 M16 ANDs for a
+ - 2 M8->M16 unpacks for c
+ - 2 M16 ANDs for a
- The number of operations are equal, but M16 would have given
- a shorter dependency chain and allowed more ILP. */
- unsigned int precision = ~0U;
- gassign *assign = as_a <gassign *> (stmt_info->stmt);
+ The number of operations are equal, but M16 would have given
+ a shorter dependency chain and allowed more ILP. */
+ unsigned int precision = ~0U;
+ if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
+ {
unsigned int nops = gimple_num_ops (assign);
for (unsigned int i = 1; i < nops; ++i)
{
@@ -5076,14 +5094,8 @@ vect_determine_mask_precision (vec_info *vinfo, stmt_vec_info stmt_info)
if (precision > def_stmt_info->mask_precision)
precision = def_stmt_info->mask_precision;
}
- else if (possible_vector_mask_operation_p (def_stmt_info))
- worklist.safe_push (def_stmt_info);
}
- /* Defer the choice if we need to visit operands first. */
- if (orig_length != worklist.length ())
- continue;
-
/* If the statement compares two values that shouldn't use vector masks,
try comparing the values as normal scalars instead. */
tree_code rhs_code = gimple_assign_rhs_code (assign);
@@ -5099,22 +5111,41 @@ vect_determine_mask_precision (vec_info *vinfo, stmt_vec_info stmt_info)
&& expand_vec_cmp_expr_p (vectype, mask_type, rhs_code))
precision = GET_MODE_BITSIZE (mode);
}
-
- if (dump_enabled_p ())
+ }
+ else
+ {
+ gphi *phi = as_a <gphi *> (stmt_info->stmt);
+ for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
{
- if (precision == ~0U)
- dump_printf_loc (MSG_NOTE, vect_location,
- "using normal nonmask vectors for %G",
- stmt_info->stmt);
- else
- dump_printf_loc (MSG_NOTE, vect_location,
- "using boolean precision %d for %G",
- precision, stmt_info->stmt);
+ tree rhs = gimple_phi_arg_def (phi, i);
+
+ stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
+ if (!def_stmt_info)
+ /* Don't let external or constant operands influence the choice.
+ We can convert them to whichever vector type we pick. */
+ continue;
+
+ if (def_stmt_info->mask_precision)
+ {
+ if (precision > def_stmt_info->mask_precision)
+ precision = def_stmt_info->mask_precision;
+ }
}
+ }
- stmt_info->mask_precision = precision;
- worklist.pop ();
+ if (dump_enabled_p ())
+ {
+ if (precision == ~0U)
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "using normal nonmask vectors for %G",
+ stmt_info->stmt);
+ else
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "using boolean precision %d for %G",
+ precision, stmt_info->stmt);
}
+
+ stmt_info->mask_precision = precision;
}
/* Handle vect_determine_precisions for STMT_INFO, given that we
@@ -5129,7 +5160,6 @@ vect_determine_stmt_precisions (vec_info *vinfo, stmt_vec_info stmt_info)
vect_determine_precisions_from_range (stmt_info, stmt);
vect_determine_precisions_from_users (stmt_info, stmt);
}
- vect_determine_mask_precision (vinfo, stmt_info);
}
/* Walk backwards through the vectorizable region to determine the
@@ -5153,6 +5183,14 @@ vect_determine_precisions (vec_info *vinfo)
for (unsigned int i = 0; i < nbbs; i++)
{
+ basic_block bb = bbs[i];
+ for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ if (!is_gimple_debug (gsi_stmt (si)))
+ vect_determine_mask_precision
+ (vinfo, vinfo->lookup_stmt (gsi_stmt (si)));
+ }
+ for (unsigned int i = 0; i < nbbs; i++)
+ {
basic_block bb = bbs[nbbs - i - 1];
for (gimple_stmt_iterator si = gsi_last_bb (bb);
!gsi_end_p (si); gsi_prev (&si))
@@ -5164,14 +5202,39 @@ vect_determine_precisions (vec_info *vinfo)
else
{
bb_vec_info bb_vinfo = as_a <bb_vec_info> (vinfo);
+ for (unsigned i = 0; i < bb_vinfo->bbs.length (); ++i)
+ {
+ basic_block bb = bb_vinfo->bbs[i];
+ for (auto gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi.phi ());
+ if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
+ vect_determine_mask_precision (vinfo, stmt_info);
+ }
+ for (auto gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
+ if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
+ vect_determine_mask_precision (vinfo, stmt_info);
+ }
+ }
for (int i = bb_vinfo->bbs.length () - 1; i != -1; --i)
- for (gimple_stmt_iterator gsi = gsi_last_bb (bb_vinfo->bbs[i]);
- !gsi_end_p (gsi); gsi_prev (&gsi))
- {
- stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
- if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
- vect_determine_stmt_precisions (vinfo, stmt_info);
- }
+ {
+ for (gimple_stmt_iterator gsi = gsi_last_bb (bb_vinfo->bbs[i]);
+ !gsi_end_p (gsi); gsi_prev (&gsi))
+ {
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (gsi));
+ if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
+ vect_determine_stmt_precisions (vinfo, stmt_info);
+ }
+ for (auto gsi = gsi_start_phis (bb_vinfo->bbs[i]);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi.phi ());
+ if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
+ vect_determine_stmt_precisions (vinfo, stmt_info);
+ }
+ }
}
}
@@ -5209,14 +5272,16 @@ static vect_recog_func vect_vect_recog_func_ptrs[] = {
of mask conversion that are needed for gather and scatter
internal functions. */
{ vect_recog_gather_scatter_pattern, "gather_scatter" },
- { vect_recog_mask_conversion_pattern, "mask_conversion" }
+ { vect_recog_mask_conversion_pattern, "mask_conversion" },
+ { vect_recog_widen_plus_pattern, "widen_plus" },
+ { vect_recog_widen_minus_pattern, "widen_minus" },
};
const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
/* Mark statements that are involved in a pattern. */
-static inline void
+void
vect_mark_pattern_stmts (vec_info *vinfo,
stmt_vec_info orig_stmt_info, gimple *pattern_stmt,
tree pattern_vectype)
diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
new file mode 100644
index 0000000..fede889
--- /dev/null
+++ b/gcc/tree-vect-slp-patterns.c
@@ -0,0 +1,721 @@
+/* SLP - Pattern matcher on SLP trees
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "optabs-tree.h"
+#include "insn-config.h"
+#include "recog.h" /* FIXME: for insn_data */
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "gimple-iterator.h"
+#include "cfgloop.h"
+#include "tree-vectorizer.h"
+#include "langhooks.h"
+#include "gimple-walk.h"
+#include "dbgcnt.h"
+#include "tree-vector-builder.h"
+#include "vec-perm-indices.h"
+#include "gimple-fold.h"
+#include "internal-fn.h"
+
+/* SLP Pattern matching mechanism.
+
+ This extension to the SLP vectorizer allows one to transform the generated SLP
+ tree based on any pattern. The difference between this and the normal vect
+ pattern matcher is that unlike the former, this matcher allows you to match
+ with instructions that do not belong to the same SSA dominator graph.
+
+ The only requirement that this pattern matcher has is that you are only
+ only allowed to either match an entire group or none.
+
+ The pattern matcher currently only allows you to perform replacements to
+ internal functions.
+
+ Once the patterns are matched it is one way, these cannot be undone. It is
+ currently not supported to match patterns recursively.
+
+ To add a new pattern, implement the vect_pattern class and add the type to
+ slp_patterns.
+
+*/
+
+/*******************************************************************************
+ * vect_pattern class
+ ******************************************************************************/
+
+/* Default implementation of recognize that performs matching, validation and
+ replacement of nodes but that can be overriden if required. */
+
+static bool
+vect_pattern_validate_optab (internal_fn ifn, slp_tree node)
+{
+ tree vectype = SLP_TREE_VECTYPE (node);
+ if (ifn == IFN_LAST || !vectype)
+ return false;
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Found %s pattern in SLP tree\n",
+ internal_fn_name (ifn));
+
+ if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Target supports %s vectorization with mode %T\n",
+ internal_fn_name (ifn), vectype);
+ }
+ else
+ {
+ if (dump_enabled_p ())
+ {
+ if (!vectype)
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Target does not support vector type for %T\n",
+ SLP_TREE_DEF_TYPE (node));
+ else
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Target does not support %s for vector type "
+ "%T\n", internal_fn_name (ifn), vectype);
+ }
+ return false;
+ }
+ return true;
+}
+
+/*******************************************************************************
+ * General helper types
+ ******************************************************************************/
+
+/* The COMPLEX_OPERATION enum denotes the possible pair of operations that can
+ be matched when looking for expressions that we are interested matching for
+ complex numbers addition and mla. */
+
+typedef enum _complex_operation : unsigned {
+ PLUS_PLUS,
+ MINUS_PLUS,
+ PLUS_MINUS,
+ MULT_MULT,
+ CMPLX_NONE
+} complex_operation_t;
+
+/*******************************************************************************
+ * General helper functions
+ ******************************************************************************/
+
+/* Helper function of linear_loads_p that checks to see if the load permutation
+ is sequential and in monotonically increasing order of loads with no gaps.
+*/
+
+static inline complex_perm_kinds_t
+is_linear_load_p (load_permutation_t loads)
+{
+ if (loads.length() == 0)
+ return PERM_UNKNOWN;
+
+ unsigned load, i;
+ complex_perm_kinds_t candidates[4]
+ = { PERM_EVENODD
+ , PERM_ODDEVEN
+ , PERM_ODDODD
+ , PERM_EVENEVEN
+ };
+
+ int valid_patterns = 4;
+ FOR_EACH_VEC_ELT_FROM (loads, i, load, 1)
+ {
+ if (candidates[0] != PERM_UNKNOWN && load != i)
+ {
+ candidates[0] = PERM_UNKNOWN;
+ valid_patterns--;
+ }
+ if (candidates[1] != PERM_UNKNOWN
+ && load != (i % 2 == 0 ? i + 1 : i - 1))
+ {
+ candidates[1] = PERM_UNKNOWN;
+ valid_patterns--;
+ }
+ if (candidates[2] != PERM_UNKNOWN && load != 1)
+ {
+ candidates[2] = PERM_UNKNOWN;
+ valid_patterns--;
+ }
+ if (candidates[3] != PERM_UNKNOWN && load != 0)
+ {
+ candidates[3] = PERM_UNKNOWN;
+ valid_patterns--;
+ }
+
+ if (valid_patterns == 0)
+ return PERM_UNKNOWN;
+ }
+
+ for (i = 0; i < sizeof(candidates); i++)
+ if (candidates[i] != PERM_UNKNOWN)
+ return candidates[i];
+
+ return PERM_UNKNOWN;
+}
+
+/* Combine complex_perm_kinds A and B into a new permute kind that describes the
+ resulting operation. */
+
+static inline complex_perm_kinds_t
+vect_merge_perms (complex_perm_kinds_t a, complex_perm_kinds_t b)
+{
+ if (a == b)
+ return a;
+
+ if (a == PERM_TOP)
+ return b;
+
+ if (b == PERM_TOP)
+ return a;
+
+ return PERM_UNKNOWN;
+}
+
+/* Check to see if all loads rooted in ROOT are linear. Linearity is
+ defined as having no gaps between values loaded. */
+
+static complex_load_perm_t
+linear_loads_p (slp_tree_to_load_perm_map_t *perm_cache, slp_tree root)
+{
+ if (!root)
+ return std::make_pair (PERM_UNKNOWN, vNULL);
+
+ unsigned i;
+ complex_load_perm_t *tmp;
+
+ if ((tmp = perm_cache->get (root)) != NULL)
+ return *tmp;
+
+ complex_load_perm_t retval = std::make_pair (PERM_UNKNOWN, vNULL);
+ perm_cache->put (root, retval);
+
+ /* If it's a load node, then just read the load permute. */
+ if (SLP_TREE_LOAD_PERMUTATION (root).exists ())
+ {
+ retval.first = is_linear_load_p (SLP_TREE_LOAD_PERMUTATION (root));
+ retval.second = SLP_TREE_LOAD_PERMUTATION (root);
+ perm_cache->put (root, retval);
+ return retval;
+ }
+ else if (SLP_TREE_DEF_TYPE (root) != vect_internal_def)
+ {
+ retval.first = PERM_TOP;
+ return retval;
+ }
+
+ auto_vec<load_permutation_t> all_loads;
+ complex_perm_kinds_t kind = PERM_TOP;
+
+ slp_tree child;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (root), i, child)
+ {
+ complex_load_perm_t res = linear_loads_p (perm_cache, child);
+ kind = vect_merge_perms (kind, res.first);
+ /* Unknown and Top are not valid on blends as they produce no permute. */
+ if (kind == PERM_UNKNOWN || kind == PERM_TOP)
+ return retval;
+ all_loads.safe_push (res.second);
+ }
+
+ if (SLP_TREE_LANE_PERMUTATION (root).exists ())
+ {
+ lane_permutation_t perm = SLP_TREE_LANE_PERMUTATION (root);
+ load_permutation_t nloads;
+ nloads.create (SLP_TREE_LANES (root));
+ nloads.quick_grow (SLP_TREE_LANES (root));
+ for (i = 0; i < SLP_TREE_LANES (root); i++)
+ nloads[i] = all_loads[perm[i].first][perm[i].second];
+
+ retval.first = kind;
+ retval.second = nloads;
+ }
+ else if (all_loads.length () == 1)
+ {
+ retval.first = kind;
+ retval.second = all_loads[0];
+ }
+
+ perm_cache->put (root, retval);
+ return retval;
+}
+
+
+/* This function attempts to make a node rooted in NODE is linear. If the node
+ if already linear than the node itself is returned in RESULT.
+
+ If the node is not linear then a new VEC_PERM_EXPR node is created with a
+ lane permute that when applied will make the node linear. If such a
+ permute cannot be created then FALSE is returned from the function.
+
+ Here linearity is defined as having a sequential, monotically increasing
+ load position inside the load permute generated by the loads reachable from
+ NODE. */
+
+static slp_tree
+vect_build_swap_evenodd_node (slp_tree node)
+{
+ /* Attempt to linearise the permute. */
+ vec<std::pair<unsigned, unsigned> > zipped;
+ zipped.create (SLP_TREE_LANES (node));
+
+ for (unsigned x = 0; x < SLP_TREE_LANES (node); x+=2)
+ {
+ zipped.quick_push (std::make_pair (0, x+1));
+ zipped.quick_push (std::make_pair (0, x));
+ }
+
+ /* Create the new permute node and store it instead. */
+ slp_tree vnode = vect_create_new_slp_node (1, VEC_PERM_EXPR);
+ SLP_TREE_LANE_PERMUTATION (vnode) = zipped;
+ SLP_TREE_VECTYPE (vnode) = SLP_TREE_VECTYPE (node);
+ SLP_TREE_CHILDREN (vnode).quick_push (node);
+ SLP_TREE_REF_COUNT (vnode) = 1;
+ SLP_TREE_LANES (vnode) = SLP_TREE_LANES (node);
+ SLP_TREE_REPRESENTATIVE (vnode) = SLP_TREE_REPRESENTATIVE (node);
+ SLP_TREE_REF_COUNT (node)++;
+ return vnode;
+}
+
+/* Checks to see of the expression represented by NODE is a gimple assign with
+ code CODE. */
+
+static inline bool
+vect_match_expression_p (slp_tree node, tree_code code)
+{
+ if (!node
+ || !SLP_TREE_REPRESENTATIVE (node))
+ return false;
+
+ gimple* expr = STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (node));
+ if (!is_gimple_assign (expr)
+ || gimple_assign_rhs_code (expr) != code)
+ return false;
+
+ return true;
+}
+
+/* Check if the given lane permute in PERMUTES matches an alternating sequence
+ of {even odd even odd ...}. This to account for unrolled loops. Further
+ mode there resulting permute must be linear. */
+
+static inline bool
+vect_check_evenodd_blend (lane_permutation_t &permutes,
+ unsigned even, unsigned odd)
+{
+ if (permutes.length () == 0)
+ return false;
+
+ unsigned val[2] = {even, odd};
+ unsigned seed = 0;
+ for (unsigned i = 0; i < permutes.length (); i++)
+ if (permutes[i].first != val[i % 2]
+ || permutes[i].second != seed++)
+ return false;
+
+ return true;
+}
+
+/* This function will match the two gimple expressions representing NODE1 and
+ NODE2 in parallel and returns the pair operation that represents the two
+ expressions in the two statements.
+
+ If match is successful then the corresponding complex_operation is
+ returned and the arguments to the two matched operations are returned in OPS.
+
+ If TWO_OPERANDS it is expected that the LANES of the parent VEC_PERM select
+ from the two nodes alternatingly.
+
+ If unsuccessful then CMPLX_NONE is returned and OPS is untouched.
+
+ e.g. the following gimple statements
+
+ stmt 0 _39 = _37 + _12;
+ stmt 1 _6 = _38 - _36;
+
+ will return PLUS_MINUS along with OPS containing {_37, _12, _38, _36}.
+*/
+
+static complex_operation_t
+vect_detect_pair_op (slp_tree node1, slp_tree node2, lane_permutation_t &lanes,
+ bool two_operands = true, vec<slp_tree> *ops = NULL)
+{
+ complex_operation_t result = CMPLX_NONE;
+
+ if (vect_match_expression_p (node1, MINUS_EXPR)
+ && vect_match_expression_p (node2, PLUS_EXPR)
+ && (!two_operands || vect_check_evenodd_blend (lanes, 0, 1)))
+ result = MINUS_PLUS;
+ else if (vect_match_expression_p (node1, PLUS_EXPR)
+ && vect_match_expression_p (node2, MINUS_EXPR)
+ && (!two_operands || vect_check_evenodd_blend (lanes, 0, 1)))
+ result = PLUS_MINUS;
+ else if (vect_match_expression_p (node1, PLUS_EXPR)
+ && vect_match_expression_p (node2, PLUS_EXPR))
+ result = PLUS_PLUS;
+ else if (vect_match_expression_p (node1, MULT_EXPR)
+ && vect_match_expression_p (node2, MULT_EXPR))
+ result = MULT_MULT;
+
+ if (result != CMPLX_NONE && ops != NULL)
+ {
+ ops->create (2);
+ ops->quick_push (node1);
+ ops->quick_push (node2);
+ }
+ return result;
+}
+
+/* Overload of vect_detect_pair_op that matches against the representative
+ statements in the children of NODE. It is expected that NODE has exactly
+ two children and when TWO_OPERANDS then NODE must be a VEC_PERM. */
+
+static complex_operation_t
+vect_detect_pair_op (slp_tree node, bool two_operands = true,
+ vec<slp_tree> *ops = NULL)
+{
+ if (!two_operands && SLP_TREE_CODE (node) == VEC_PERM_EXPR)
+ return CMPLX_NONE;
+
+ if (SLP_TREE_CHILDREN (node).length () != 2)
+ return CMPLX_NONE;
+
+ vec<slp_tree> children = SLP_TREE_CHILDREN (node);
+ lane_permutation_t &lanes = SLP_TREE_LANE_PERMUTATION (node);
+
+ return vect_detect_pair_op (children[0], children[1], lanes, two_operands,
+ ops);
+}
+
+/*******************************************************************************
+ * complex_pattern class
+ ******************************************************************************/
+
+/* SLP Complex Numbers pattern matching.
+
+ As an example, the following simple loop:
+
+ double a[restrict N]; double b[restrict N]; double c[restrict N];
+
+ for (int i=0; i < N; i+=2)
+ {
+ c[i] = a[i] - b[i+1];
+ c[i+1] = a[i+1] + b[i];
+ }
+
+ which represents a complex addition on with a rotation of 90* around the
+ argand plane. i.e. if `a` and `b` were complex numbers then this would be the
+ same as `a + (b * I)`.
+
+ Here the expressions for `c[i]` and `c[i+1]` are independent but have to be
+ both recognized in order for the pattern to work. As an SLP tree this is
+ represented as
+
+ +--------------------------------+
+ | stmt 0 *_9 = _10; |
+ | stmt 1 *_15 = _16; |
+ +--------------------------------+
+ |
+ |
+ v
+ +--------------------------------+
+ | stmt 0 _10 = _4 - _8; |
+ | stmt 1 _16 = _12 + _14; |
+ | lane permutation { 0[0] 1[1] } |
+ +--------------------------------+
+ | |
+ | |
+ | |
+ +-----+ | | +-----+
+ | | | | | |
+ +-----| { } |<-----+ +----->| { } --------+
+ | | | +------------------| | |
+ | +-----+ | +-----+ |
+ | | | |
+ | | | |
+ | +------|------------------+ |
+ | | | |
+ v v v v
+ +--------------------------+ +--------------------------------+
+ | stmt 0 _8 = *_7; | | stmt 0 _4 = *_3; |
+ | stmt 1 _14 = *_13; | | stmt 1 _12 = *_11; |
+ | load permutation { 1 0 } | | load permutation { 0 1 } |
+ +--------------------------+ +--------------------------------+
+
+ The pattern matcher allows you to replace both statements 0 and 1 or none at
+ all. Because this operation is a two operands operation the actual nodes
+ being replaced are those in the { } nodes. The actual scalar statements
+ themselves are not replaced or used during the matching but instead the
+ SLP_TREE_REPRESENTATIVE statements are inspected. You are also allowed to
+ replace and match on any number of nodes.
+
+ Because the pattern matcher matches on the representative statement for the
+ SLP node the case of two_operators it allows you to match the children of the
+ node. This is done using the method `recognize ()`.
+
+*/
+
+/* The complex_pattern class contains common code for pattern matchers that work
+ on complex numbers. These provide functionality to allow de-construction and
+ validation of sequences depicting/transforming REAL and IMAG pairs. */
+
+class complex_pattern : public vect_pattern
+{
+ protected:
+ auto_vec<slp_tree> m_workset;
+ complex_pattern (slp_tree *node, vec<slp_tree> *m_ops, internal_fn ifn)
+ : vect_pattern (node, m_ops, ifn)
+ {
+ this->m_workset.safe_push (*node);
+ }
+
+ public:
+ void build (vec_info *);
+
+ static internal_fn
+ matches (complex_operation_t op, slp_tree_to_load_perm_map_t *,
+ vec<slp_tree> *);
+};
+
+/* Create a replacement pattern statement for each node in m_node and inserts
+ the new statement into m_node as the new representative statement. The old
+ statement is marked as being in a pattern defined by the new statement. The
+ statement is created as call to internal function IFN with m_num_args
+ arguments.
+
+ Futhermore the new pattern is also added to the vectorization information
+ structure VINFO and the old statement STMT_INFO is marked as unused while
+ the new statement is marked as used and the number of SLP uses of the new
+ statement is incremented.
+
+ The newly created SLP nodes are marked as SLP only and will be dissolved
+ if SLP is aborted.
+
+ The newly created gimple call is returned and the BB remains unchanged.
+
+ This default method is designed to only match against simple operands where
+ all the input and output types are the same.
+*/
+
+void
+complex_pattern::build (vec_info *vinfo)
+{
+ stmt_vec_info stmt_info;
+
+ auto_vec<tree> args;
+ args.create (this->m_num_args);
+ args.quick_grow_cleared (this->m_num_args);
+ slp_tree node;
+ unsigned ix;
+ stmt_vec_info call_stmt_info;
+ gcall *call_stmt = NULL;
+
+ /* Now modify the nodes themselves. */
+ FOR_EACH_VEC_ELT (this->m_workset, ix, node)
+ {
+ /* Calculate the location of the statement in NODE to replace. */
+ stmt_info = SLP_TREE_REPRESENTATIVE (node);
+ gimple* old_stmt = STMT_VINFO_STMT (stmt_info);
+ tree lhs_old_stmt = gimple_get_lhs (old_stmt);
+ tree type = TREE_TYPE (lhs_old_stmt);
+
+ /* Create the argument set for use by gimple_build_call_internal_vec. */
+ for (unsigned i = 0; i < this->m_num_args; i++)
+ args[i] = lhs_old_stmt;
+
+ /* Create the new pattern statements. */
+ call_stmt = gimple_build_call_internal_vec (this->m_ifn, args);
+ tree var = make_temp_ssa_name (type, call_stmt, "slp_patt");
+ gimple_call_set_lhs (call_stmt, var);
+ gimple_set_location (call_stmt, gimple_location (old_stmt));
+ gimple_call_set_nothrow (call_stmt, true);
+
+ /* Adjust the book-keeping for the new and old statements for use during
+ SLP. This is required to get the right VF and statement during SLP
+ analysis. These changes are created after relevancy has been set for
+ the nodes as such we need to manually update them. Any changes will be
+ undone if SLP is cancelled. */
+ call_stmt_info
+ = vinfo->add_pattern_stmt (call_stmt, stmt_info);
+
+ /* Make sure to mark the representative statement pure_slp and
+ relevant. */
+ STMT_VINFO_RELEVANT (call_stmt_info) = vect_used_in_scope;
+ STMT_SLP_TYPE (call_stmt_info) = pure_slp;
+
+ /* add_pattern_stmt can't be done in vect_mark_pattern_stmts because
+ the non-SLP pattern matchers already have added the statement to VINFO
+ by the time it is called. Some of them need to modify the returned
+ stmt_info. vect_mark_pattern_stmts is called by recog_pattern and it
+ would increase the size of each pattern with boilerplate code to make
+ the call there. */
+ vect_mark_pattern_stmts (vinfo, stmt_info, call_stmt,
+ SLP_TREE_VECTYPE (node));
+ STMT_VINFO_SLP_VECT_ONLY (call_stmt_info) = true;
+
+ /* Since we are replacing all the statements in the group with the same
+ thing it doesn't really matter. So just set it every time a new stmt
+ is created. */
+ SLP_TREE_REPRESENTATIVE (node) = call_stmt_info;
+ SLP_TREE_LANE_PERMUTATION (node).release ();
+ SLP_TREE_CODE (node) = CALL_EXPR;
+ }
+}
+
+/*******************************************************************************
+ * complex_add_pattern class
+ ******************************************************************************/
+
+class complex_add_pattern : public complex_pattern
+{
+ protected:
+ complex_add_pattern (slp_tree *node, vec<slp_tree> *m_ops, internal_fn ifn)
+ : complex_pattern (node, m_ops, ifn)
+ {
+ this->m_num_args = 2;
+ }
+
+ public:
+ void build (vec_info *);
+ static internal_fn
+ matches (complex_operation_t op, slp_tree_to_load_perm_map_t *,
+ vec<slp_tree> *);
+
+ static vect_pattern*
+ recognize (slp_tree_to_load_perm_map_t *, slp_tree *);
+};
+
+/* Perform a replacement of the detected complex add pattern with the new
+ instruction sequences. */
+
+void
+complex_add_pattern::build (vec_info *vinfo)
+{
+ auto_vec<slp_tree> nodes;
+ slp_tree node = this->m_ops[0];
+ vec<slp_tree> children = SLP_TREE_CHILDREN (node);
+
+ /* First re-arrange the children. */
+ nodes.create (children.length ());
+ nodes.quick_push (children[0]);
+ nodes.quick_push (vect_build_swap_evenodd_node (children[1]));
+
+ SLP_TREE_CHILDREN (*this->m_node).truncate (0);
+ SLP_TREE_CHILDREN (*this->m_node).safe_splice (nodes);
+
+ complex_pattern::build (vinfo);
+}
+
+/* Pattern matcher for trying to match complex addition pattern in SLP tree.
+
+ If no match is found then IFN is set to IFN_LAST.
+ This function matches the patterns shaped as:
+
+ c[i] = a[i] - b[i+1];
+ c[i+1] = a[i+1] + b[i];
+
+ If a match occurred then TRUE is returned, else FALSE. The initial match is
+ expected to be in OP1 and the initial match operands in args0. */
+
+internal_fn
+complex_add_pattern::matches (complex_operation_t op,
+ slp_tree_to_load_perm_map_t *perm_cache,
+ vec<slp_tree> *ops)
+{
+ internal_fn ifn = IFN_LAST;
+
+ /* Find the two components. Rotation in the complex plane will modify
+ the operations:
+
+ * Rotation 0: + +
+ * Rotation 90: - +
+ * Rotation 180: - -
+ * Rotation 270: + -
+
+ Rotation 0 and 180 can be handled by normal SIMD code, so we don't need
+ to care about them here. */
+ if (op == MINUS_PLUS)
+ ifn = IFN_COMPLEX_ADD_ROT90;
+ else if (op == PLUS_MINUS)
+ ifn = IFN_COMPLEX_ADD_ROT270;
+ else
+ return ifn;
+
+ /* verify that there is a permute, otherwise this isn't a pattern we
+ we support. */
+ gcc_assert (ops->length () == 2);
+
+ vec<slp_tree> children = SLP_TREE_CHILDREN ((*ops)[0]);
+
+ /* First node must be unpermuted. */
+ if (linear_loads_p (perm_cache, children[0]).first != PERM_EVENODD)
+ return IFN_LAST;
+
+ /* Second node must be permuted. */
+ if (linear_loads_p (perm_cache, children[1]).first != PERM_ODDEVEN)
+ return IFN_LAST;
+
+ return ifn;
+}
+
+/* Attempt to recognize a complex add pattern. */
+
+vect_pattern*
+complex_add_pattern::recognize (slp_tree_to_load_perm_map_t *perm_cache,
+ slp_tree *node)
+{
+ auto_vec<slp_tree> ops;
+ complex_operation_t op
+ = vect_detect_pair_op (*node, true, &ops);
+ internal_fn ifn = complex_add_pattern::matches (op, perm_cache, &ops);
+ if (!vect_pattern_validate_optab (ifn, *node))
+ return NULL;
+
+ return new complex_add_pattern (node, &ops, ifn);
+}
+
+/*******************************************************************************
+ * Pattern matching definitions
+ ******************************************************************************/
+
+#define SLP_PATTERN(x) &x::recognize
+vect_pattern_decl_t slp_patterns[]
+{
+ /* For least amount of back-tracking and more efficient matching
+ order patterns from the largest to the smallest. Especially if they
+ overlap in what they can detect. */
+
+ SLP_PATTERN (complex_add_pattern),
+};
+#undef SLP_PATTERN
+
+/* Set the number of SLP pattern matchers available. */
+size_t num__slp_patterns = sizeof(slp_patterns)/sizeof(vect_pattern_decl_t);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 4544f0f..2a58e54 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -48,14 +48,53 @@ along with GCC; see the file COPYING3. If not see
#include "cfganal.h"
#include "tree-eh.h"
#include "tree-cfg.h"
+#include "alloc-pool.h"
static bool vectorizable_slp_permutation (vec_info *, gimple_stmt_iterator *,
slp_tree, stmt_vector_for_cost *);
+static object_allocator<_slp_tree> *slp_tree_pool;
+static slp_tree slp_first_node;
+
+void
+vect_slp_init (void)
+{
+ slp_tree_pool = new object_allocator<_slp_tree> ("SLP nodes");
+}
+
+void
+vect_slp_fini (void)
+{
+ while (slp_first_node)
+ delete slp_first_node;
+ delete slp_tree_pool;
+ slp_tree_pool = NULL;
+}
+
+void *
+_slp_tree::operator new (size_t n)
+{
+ gcc_assert (n == sizeof (_slp_tree));
+ return slp_tree_pool->allocate_raw ();
+}
+
+void
+_slp_tree::operator delete (void *node, size_t n)
+{
+ gcc_assert (n == sizeof (_slp_tree));
+ slp_tree_pool->remove_raw (node);
+}
+
+
/* Initialize a SLP node. */
_slp_tree::_slp_tree ()
{
+ this->prev_node = NULL;
+ if (slp_first_node)
+ slp_first_node->prev_node = this;
+ this->next_node = slp_first_node;
+ slp_first_node = this;
SLP_TREE_SCALAR_STMTS (this) = vNULL;
SLP_TREE_SCALAR_OPS (this) = vNULL;
SLP_TREE_VEC_STMTS (this) = vNULL;
@@ -77,6 +116,12 @@ _slp_tree::_slp_tree ()
_slp_tree::~_slp_tree ()
{
+ if (this->prev_node)
+ this->prev_node->next_node = this->next_node;
+ else
+ slp_first_node = this->next_node;
+ if (this->next_node)
+ this->next_node->prev_node = this->prev_node;
SLP_TREE_CHILDREN (this).release ();
SLP_TREE_SCALAR_STMTS (this).release ();
SLP_TREE_SCALAR_OPS (this).release ();
@@ -88,7 +133,7 @@ _slp_tree::~_slp_tree ()
/* Recursively free the memory allocated for the SLP tree rooted at NODE. */
-static void
+void
vect_free_slp_tree (slp_tree node)
{
int i;
@@ -98,7 +143,8 @@ vect_free_slp_tree (slp_tree node)
return;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_free_slp_tree (child);
+ if (child)
+ vect_free_slp_tree (child);
delete node;
}
@@ -130,10 +176,22 @@ vect_free_slp_instance (slp_instance instance)
/* Create an SLP node for SCALAR_STMTS. */
-static slp_tree
-vect_create_new_slp_node (vec<stmt_vec_info> scalar_stmts, unsigned nops)
+slp_tree
+vect_create_new_slp_node (unsigned nops, tree_code code)
{
slp_tree node = new _slp_tree;
+ SLP_TREE_SCALAR_STMTS (node) = vNULL;
+ SLP_TREE_CHILDREN (node).create (nops);
+ SLP_TREE_DEF_TYPE (node) = vect_internal_def;
+ SLP_TREE_CODE (node) = code;
+ return node;
+}
+/* Create an SLP node for SCALAR_STMTS. */
+
+static slp_tree
+vect_create_new_slp_node (slp_tree node,
+ vec<stmt_vec_info> scalar_stmts, unsigned nops)
+{
SLP_TREE_SCALAR_STMTS (node) = scalar_stmts;
SLP_TREE_CHILDREN (node).create (nops);
SLP_TREE_DEF_TYPE (node) = vect_internal_def;
@@ -142,18 +200,33 @@ vect_create_new_slp_node (vec<stmt_vec_info> scalar_stmts, unsigned nops)
return node;
}
+/* Create an SLP node for SCALAR_STMTS. */
+
+static slp_tree
+vect_create_new_slp_node (vec<stmt_vec_info> scalar_stmts, unsigned nops)
+{
+ return vect_create_new_slp_node (new _slp_tree, scalar_stmts, nops);
+}
+
/* Create an SLP node for OPS. */
static slp_tree
-vect_create_new_slp_node (vec<tree> ops)
+vect_create_new_slp_node (slp_tree node, vec<tree> ops)
{
- slp_tree node = new _slp_tree;
SLP_TREE_SCALAR_OPS (node) = ops;
SLP_TREE_DEF_TYPE (node) = vect_external_def;
SLP_TREE_LANES (node) = ops.length ();
return node;
}
+/* Create an SLP node for OPS. */
+
+static slp_tree
+vect_create_new_slp_node (vec<tree> ops)
+{
+ return vect_create_new_slp_node (new _slp_tree, ops);
+}
+
/* This structure is used in creation of an SLP tree. Each instance
corresponds to the same operand in a group of scalar stmts in an SLP
@@ -175,7 +248,7 @@ typedef struct _slp_oprnd_info
/* Allocate operands info for NOPS operands, and GROUP_SIZE def-stmts for each
operand. */
-static vec<slp_oprnd_info>
+static vec<slp_oprnd_info>
vect_create_oprnd_info (int nops, int group_size)
{
int i;
@@ -380,6 +453,7 @@ vect_def_types_match (enum vect_def_type dta, enum vect_def_type dtb)
ok return 0. */
static int
vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
+ bool *skip_args,
vec<stmt_vec_info> stmts, unsigned stmt_num,
vec<slp_oprnd_info> *oprnds_info)
{
@@ -426,10 +500,13 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
else
commutative_op = commutative_tree_code (code) ? 0U : -1U;
}
+ else if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
+ number_of_oprnds = gimple_phi_num_args (stmt);
else
return -1;
bool swapped = (swap != 0);
+ bool backedge = false;
gcc_assert (!swapped || first_op_cond);
enum vect_def_type *dts = XALLOCAVEC (enum vect_def_type, number_of_oprnds);
for (i = 0; i < number_of_oprnds; i++)
@@ -446,6 +523,13 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
else
oprnd = gimple_op (stmt_info->stmt, map[i]);
}
+ else if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
+ {
+ oprnd = gimple_phi_arg_def (stmt, i);
+ backedge = dominated_by_p (CDI_DOMINATORS,
+ gimple_phi_arg_edge (stmt, i)->src,
+ gimple_bb (stmt_info->stmt));
+ }
else
oprnd = gimple_op (stmt_info->stmt, first_op_idx + (swapped ? !i : i));
if (TREE_CODE (oprnd) == VIEW_CONVERT_EXPR)
@@ -464,12 +548,50 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
return -1;
}
- if (def_stmt_info && is_pattern_stmt_p (def_stmt_info))
- oprnd_info->any_pattern = true;
+ if (skip_args[i])
+ {
+ oprnd_info->def_stmts.quick_push (NULL);
+ oprnd_info->ops.quick_push (NULL_TREE);
+ oprnd_info->first_dt = vect_uninitialized_def;
+ continue;
+ }
oprnd_info->def_stmts.quick_push (def_stmt_info);
oprnd_info->ops.quick_push (oprnd);
+ if (def_stmt_info
+ && is_pattern_stmt_p (def_stmt_info))
+ {
+ if (STMT_VINFO_RELATED_STMT (vect_orig_stmt (def_stmt_info))
+ != def_stmt_info)
+ oprnd_info->any_pattern = true;
+ else
+ /* If we promote this to external use the original stmt def. */
+ oprnd_info->ops.last ()
+ = gimple_get_lhs (vect_orig_stmt (def_stmt_info)->stmt);
+ }
+
+ /* If there's a extern def on a backedge make sure we can
+ code-generate at the region start.
+ ??? This is another case that could be fixed by adjusting
+ how we split the function but at the moment we'd have conflicting
+ goals there. */
+ if (backedge
+ && dts[i] == vect_external_def
+ && is_a <bb_vec_info> (vinfo)
+ && TREE_CODE (oprnd) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (oprnd)
+ && !dominated_by_p (CDI_DOMINATORS,
+ as_a <bb_vec_info> (vinfo)->bbs[0],
+ gimple_bb (SSA_NAME_DEF_STMT (oprnd))))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: extern def %T only defined "
+ "on backedge\n", oprnd);
+ return -1;
+ }
+
if (first)
{
tree type = TREE_TYPE (oprnd);
@@ -504,6 +626,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
case vect_internal_def:
case vect_reduction_def:
case vect_induction_def:
+ case vect_nested_cycle:
break;
default:
@@ -525,6 +648,12 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
/* Now match the operand definition types to that of the first stmt. */
for (i = 0; i < number_of_oprnds;)
{
+ if (skip_args[i])
+ {
+ ++i;
+ continue;
+ }
+
oprnd_info = (*oprnds_info)[i];
dt = dts[i];
stmt_vec_info def_stmt_info = oprnd_info->def_stmts[stmt_num];
@@ -798,6 +927,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
machine_mode vec_mode;
stmt_vec_info first_load = NULL, prev_first_load = NULL;
bool first_stmt_load_p = false, load_p = false;
+ bool first_stmt_phi_p = false, phi_p = false;
/* For every stmt in NODE find its def stmt/s. */
stmt_vec_info stmt_info;
@@ -887,6 +1017,11 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
return false;
}
}
+ else if (gimple_code (stmt) == GIMPLE_PHI)
+ {
+ rhs_code = ERROR_MARK;
+ phi_p = true;
+ }
else
{
rhs_code = gimple_assign_rhs_code (stmt);
@@ -899,6 +1034,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
*node_vectype = vectype;
first_stmt_code = rhs_code;
first_stmt_load_p = load_p;
+ first_stmt_phi_p = phi_p;
/* Shift arguments should be equal in all the packed stmts for a
vector shift with scalar shift operand. */
@@ -1004,11 +1140,12 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
|| first_stmt_code == INDIRECT_REF
|| first_stmt_code == COMPONENT_REF
|| first_stmt_code == MEM_REF)))
- || first_stmt_load_p != load_p)
+ || first_stmt_load_p != load_p
+ || first_stmt_phi_p != phi_p)
{
if (dump_enabled_p ())
{
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Build SLP failed: different operation "
"in stmt %G", stmt);
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -1060,6 +1197,18 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
}
}
+ if (phi_p
+ && (gimple_bb (first_stmt_info->stmt)
+ != gimple_bb (stmt_info->stmt)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: different BB for PHI "
+ "in %G", stmt);
+ /* Mismatch. */
+ continue;
+ }
+
if (!types_compatible_p (vectype, *node_vectype))
{
if (dump_enabled_p ())
@@ -1121,7 +1270,8 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
}
/* Not memory operation. */
- if (TREE_CODE_CLASS (rhs_code) != tcc_binary
+ if (!phi_p
+ && TREE_CODE_CLASS (rhs_code) != tcc_binary
&& TREE_CODE_CLASS (rhs_code) != tcc_unary
&& TREE_CODE_CLASS (rhs_code) != tcc_expression
&& TREE_CODE_CLASS (rhs_code) != tcc_comparison
@@ -1234,17 +1384,17 @@ typedef hash_map <vec <gimple *>, slp_tree,
scalar_stmts_to_slp_tree_map_t;
static slp_tree
-vect_build_slp_tree_2 (vec_info *vinfo,
+vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node,
vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits,
- bool *matches, unsigned *npermutes, unsigned *tree_size,
+ bool *matches, unsigned *limit, unsigned *tree_size,
scalar_stmts_to_slp_tree_map_t *bst_map);
static slp_tree
vect_build_slp_tree (vec_info *vinfo,
vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits,
- bool *matches, unsigned *npermutes, unsigned *tree_size,
+ bool *matches, unsigned *limit, unsigned *tree_size,
scalar_stmts_to_slp_tree_map_t *bst_map)
{
if (slp_tree *leader = bst_map->get (stmts))
@@ -1259,19 +1409,53 @@ vect_build_slp_tree (vec_info *vinfo,
}
return *leader;
}
+
+ /* Seed the bst_map with a stub node to be filled by vect_build_slp_tree_2
+ so we can pick up backedge destinations during discovery. */
+ slp_tree res = new _slp_tree;
+ SLP_TREE_DEF_TYPE (res) = vect_internal_def;
+ SLP_TREE_SCALAR_STMTS (res) = stmts;
+ bst_map->put (stmts.copy (), res);
+
+ if (*limit == 0)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "SLP discovery limit exceeded\n");
+ bool existed_p = bst_map->put (stmts, NULL);
+ gcc_assert (existed_p);
+ /* Mark the node invalid so we can detect those when still in use
+ as backedge destinations. */
+ SLP_TREE_SCALAR_STMTS (res) = vNULL;
+ SLP_TREE_DEF_TYPE (res) = vect_uninitialized_def;
+ vect_free_slp_tree (res);
+ return NULL;
+ }
+ --*limit;
+
poly_uint64 this_max_nunits = 1;
- slp_tree res = vect_build_slp_tree_2 (vinfo, stmts, group_size,
+ slp_tree res_ = vect_build_slp_tree_2 (vinfo, res, stmts, group_size,
&this_max_nunits,
- matches, npermutes, tree_size, bst_map);
- if (res)
+ matches, limit, tree_size, bst_map);
+ if (!res_)
{
+ bool existed_p = bst_map->put (stmts, NULL);
+ gcc_assert (existed_p);
+ /* Mark the node invalid so we can detect those when still in use
+ as backedge destinations. */
+ SLP_TREE_SCALAR_STMTS (res) = vNULL;
+ SLP_TREE_DEF_TYPE (res) = vect_uninitialized_def;
+ vect_free_slp_tree (res);
+ }
+ else
+ {
+ gcc_assert (res_ == res);
res->max_nunits = this_max_nunits;
vect_update_max_nunits (max_nunits, this_max_nunits);
/* Keep a reference for the bst_map use. */
SLP_TREE_REF_COUNT (res)++;
}
- bst_map->put (stmts.copy (), res);
- return res;
+ return res_;
}
/* Recursively build an SLP tree starting from NODE.
@@ -1282,15 +1466,14 @@ vect_build_slp_tree (vec_info *vinfo,
was found. */
static slp_tree
-vect_build_slp_tree_2 (vec_info *vinfo,
+vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node,
vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits,
- bool *matches, unsigned *npermutes, unsigned *tree_size,
+ bool *matches, unsigned *limit, unsigned *tree_size,
scalar_stmts_to_slp_tree_map_t *bst_map)
{
unsigned nops, i, this_tree_size = 0;
poly_uint64 this_max_nunits = *max_nunits;
- slp_tree node;
matches[0] = false;
@@ -1310,41 +1493,59 @@ vect_build_slp_tree_2 (vec_info *vinfo,
/* If the SLP node is a PHI (induction or reduction), terminate
the recursion. */
- if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
- {
- tree scalar_type = TREE_TYPE (PHI_RESULT (stmt));
- tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
- group_size);
- if (!vect_record_max_nunits (vinfo, stmt_info, group_size, vectype,
- max_nunits))
- return NULL;
+ bool *skip_args = XALLOCAVEC (bool, nops);
+ memset (skip_args, 0, sizeof (bool) * nops);
+ if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
+ if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
+ {
+ tree scalar_type = TREE_TYPE (PHI_RESULT (stmt));
+ tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
+ group_size);
+ if (!vect_record_max_nunits (vinfo, stmt_info, group_size, vectype,
+ max_nunits))
+ return NULL;
- vect_def_type def_type = STMT_VINFO_DEF_TYPE (stmt_info);
- /* Induction from different IVs is not supported. */
- if (def_type == vect_induction_def)
- {
- stmt_vec_info other_info;
- FOR_EACH_VEC_ELT (stmts, i, other_info)
- if (stmt_info != other_info)
- return NULL;
- }
- else if (def_type == vect_reduction_def
- || def_type == vect_double_reduction_def
- || def_type == vect_nested_cycle)
- {
- /* Else def types have to match. */
- stmt_vec_info other_info;
- FOR_EACH_VEC_ELT (stmts, i, other_info)
- if (STMT_VINFO_DEF_TYPE (other_info) != def_type)
- return NULL;
- }
- else
- return NULL;
- (*tree_size)++;
- node = vect_create_new_slp_node (stmts, nops);
- SLP_TREE_VECTYPE (node) = vectype;
- return node;
- }
+ vect_def_type def_type = STMT_VINFO_DEF_TYPE (stmt_info);
+ if (def_type == vect_induction_def)
+ {
+ /* Induction PHIs are not cycles but walk the initial
+ value. Only for inner loops through, for outer loops
+ we need to pick up the value from the actual PHIs
+ to more easily support peeling and epilogue vectorization. */
+ class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ if (!nested_in_vect_loop_p (loop, stmt_info))
+ skip_args[loop_preheader_edge (loop)->dest_idx] = true;
+ else
+ loop = loop->inner;
+ skip_args[loop_latch_edge (loop)->dest_idx] = true;
+ }
+ else if (def_type == vect_reduction_def
+ || def_type == vect_double_reduction_def
+ || def_type == vect_nested_cycle)
+ {
+ /* Else def types have to match. */
+ stmt_vec_info other_info;
+ bool all_same = true;
+ FOR_EACH_VEC_ELT (stmts, i, other_info)
+ {
+ if (STMT_VINFO_DEF_TYPE (other_info) != def_type)
+ return NULL;
+ if (other_info != stmt_info)
+ all_same = false;
+ }
+ class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ /* Reduction initial values are not explicitely represented. */
+ if (!nested_in_vect_loop_p (loop, stmt_info))
+ skip_args[loop_preheader_edge (loop)->dest_idx] = true;
+ /* Reduction chain backedge defs are filled manually.
+ ??? Need a better way to identify a SLP reduction chain PHI.
+ Or a better overall way to SLP match those. */
+ if (all_same && def_type == vect_reduction_def)
+ skip_args[loop_latch_edge (loop)->dest_idx] = true;
+ }
+ else if (def_type != vect_internal_def)
+ return NULL;
+ }
bool two_operators = false;
@@ -1369,7 +1570,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
{
*max_nunits = this_max_nunits;
(*tree_size)++;
- node = vect_create_new_slp_node (stmts, 0);
+ node = vect_create_new_slp_node (node, stmts, 0);
SLP_TREE_VECTYPE (node) = vectype;
/* And compute the load permutation. Whether it is actually
a permutation depends on the unrolling factor which is
@@ -1423,7 +1624,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
representing an actual vector without any scalar ops.
??? We could hide it completely with making the permute node
external? */
- node = vect_create_new_slp_node (stmts, 1);
+ node = vect_create_new_slp_node (node, stmts, 1);
SLP_TREE_CODE (node) = VEC_PERM_EXPR;
SLP_TREE_LANE_PERMUTATION (node) = lperm;
SLP_TREE_VECTYPE (node) = vectype;
@@ -1436,7 +1637,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
slp_oprnd_info oprnd_info;
FOR_EACH_VEC_ELT (stmts, i, stmt_info)
{
- int res = vect_get_and_check_slp_defs (vinfo, swap[i],
+ int res = vect_get_and_check_slp_defs (vinfo, swap[i], skip_args,
stmts, i, &oprnds_info);
if (res != 0)
matches[(res == -1) ? 0 : i] = false;
@@ -1461,6 +1662,14 @@ vect_build_slp_tree_2 (vec_info *vinfo,
slp_tree child;
unsigned int j;
+ /* We're skipping certain operands from processing, for example
+ outer loop reduction initial defs. */
+ if (skip_args[i])
+ {
+ children.safe_push (NULL);
+ continue;
+ }
+
if (oprnd_info->first_dt == vect_uninitialized_def)
{
/* COND_EXPR have one too many eventually if the condition
@@ -1469,9 +1678,33 @@ vect_build_slp_tree_2 (vec_info *vinfo,
continue;
}
- if (oprnd_info->first_dt != vect_internal_def
- && oprnd_info->first_dt != vect_reduction_def
- && oprnd_info->first_dt != vect_induction_def)
+ if (is_a <bb_vec_info> (vinfo)
+ && oprnd_info->first_dt == vect_internal_def
+ && !oprnd_info->any_pattern)
+ {
+ /* For BB vectorization, if all defs are the same do not
+ bother to continue the build along the single-lane
+ graph but use a splat of the scalar value. */
+ stmt_vec_info first_def = oprnd_info->def_stmts[0];
+ for (j = 1; j < group_size; ++j)
+ if (oprnd_info->def_stmts[j] != first_def)
+ break;
+ if (j == group_size
+ /* But avoid doing this for loads where we may be
+ able to CSE things, unless the stmt is not
+ vectorizable. */
+ && (!STMT_VINFO_VECTORIZABLE (first_def)
+ || !gimple_vuse (first_def->stmt)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Using a splat of the uniform operand\n");
+ oprnd_info->first_dt = vect_external_def;
+ }
+ }
+
+ if (oprnd_info->first_dt == vect_external_def
+ || oprnd_info->first_dt == vect_constant_def)
{
slp_tree invnode = vect_create_new_slp_node (oprnd_info->ops);
SLP_TREE_DEF_TYPE (invnode) = oprnd_info->first_dt;
@@ -1482,7 +1715,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
if ((child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
group_size, &this_max_nunits,
- matches, npermutes,
+ matches, limit,
&this_tree_size, bst_map)) != NULL)
{
oprnd_info->def_stmts = vNULL;
@@ -1503,12 +1736,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
&& is_gimple_assign (stmt_info->stmt)
/* Swapping operands for reductions breaks assumptions later on. */
&& STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def
- && STMT_VINFO_DEF_TYPE (stmt_info) != vect_double_reduction_def
- /* Do so only if the number of not successful permutes was nor more
- than a cut-ff as re-trying the recursive match on
- possibly each level of the tree would expose exponential
- behavior. */
- && *npermutes < 4)
+ && STMT_VINFO_DEF_TYPE (stmt_info) != vect_double_reduction_def)
{
/* See whether we can swap the matching or the non-matching
stmt operands. */
@@ -1554,17 +1782,13 @@ vect_build_slp_tree_2 (vec_info *vinfo,
bool *tem = XALLOCAVEC (bool, group_size);
if ((child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts,
group_size, &this_max_nunits,
- tem, npermutes,
+ tem, limit,
&this_tree_size, bst_map)) != NULL)
{
oprnd_info->def_stmts = vNULL;
children.safe_push (child);
continue;
}
- /* We do not undo the swapping here since it might still be
- the better order for the second operand in case we build
- the first one from scalars below. */
- ++*npermutes;
}
fail:
@@ -1600,14 +1824,14 @@ fail:
child = vect_create_new_slp_node (oprnd_info->ops);
children.safe_push (child);
oprnd_info->ops = vNULL;
- oprnd_info->def_stmts = vNULL;
continue;
}
}
gcc_assert (child == NULL);
FOR_EACH_VEC_ELT (children, j, child)
- vect_free_slp_tree (child);
+ if (child)
+ vect_free_slp_tree (child);
vect_free_oprnd_info (oprnds_info);
return NULL;
}
@@ -1631,7 +1855,9 @@ fail:
unsigned n_vector_builds = 0;
FOR_EACH_VEC_ELT (children, j, child)
{
- if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
+ if (!child)
+ ;
+ else if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
all_uniform_p = false;
else if (!vect_slp_tree_uniform_p (child))
{
@@ -1645,7 +1871,8 @@ fail:
/* Roll back. */
matches[0] = false;
FOR_EACH_VEC_ELT (children, j, child)
- vect_free_slp_tree (child);
+ if (child)
+ vect_free_slp_tree (child);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1679,7 +1906,7 @@ fail:
/* Here we record the original defs since this
node represents the final lane configuration. */
- node = vect_create_new_slp_node (stmts, 2);
+ node = vect_create_new_slp_node (node, stmts, 2);
SLP_TREE_VECTYPE (node) = vectype;
SLP_TREE_CODE (node) = VEC_PERM_EXPR;
SLP_TREE_CHILDREN (node).quick_push (one);
@@ -1710,7 +1937,7 @@ fail:
return node;
}
- node = vect_create_new_slp_node (stmts, nops);
+ node = vect_create_new_slp_node (node, stmts, nops);
SLP_TREE_VECTYPE (node) = vectype;
SLP_TREE_CHILDREN (node).splice (children);
return node;
@@ -1737,6 +1964,14 @@ vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc,
: ""), node,
estimated_poly_value (node->max_nunits),
SLP_TREE_REF_COUNT (node));
+ if (SLP_TREE_DEF_TYPE (node) == vect_internal_def)
+ {
+ if (SLP_TREE_CODE (node) == VEC_PERM_EXPR)
+ dump_printf_loc (metadata, user_loc, "op: VEC_PERM_EXPR\n");
+ else
+ dump_printf_loc (metadata, user_loc, "op template: %G",
+ SLP_TREE_REPRESENTATIVE (node)->stmt);
+ }
if (SLP_TREE_SCALAR_STMTS (node).exists ())
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
dump_printf_loc (metadata, user_loc, "\tstmt %u %G", i, stmt_info->stmt);
@@ -1796,7 +2031,8 @@ vect_print_slp_graph (dump_flags_t dump_kind, dump_location_t loc,
vect_print_slp_tree (dump_kind, loc, node);
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_print_slp_graph (dump_kind, loc, child, visited);
+ if (child)
+ vect_print_slp_graph (dump_kind, loc, child, visited);
}
static void
@@ -1826,7 +2062,8 @@ vect_mark_slp_stmts (slp_tree node, hash_set<slp_tree> &visited)
STMT_SLP_TYPE (stmt_info) = pure_slp;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_mark_slp_stmts (child, visited);
+ if (child)
+ vect_mark_slp_stmts (child, visited);
}
static void
@@ -1859,7 +2096,8 @@ vect_mark_slp_stmts_relevant (slp_tree node, hash_set<slp_tree> &visited)
}
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_mark_slp_stmts_relevant (child, visited);
+ if (child)
+ vect_mark_slp_stmts_relevant (child, visited);
}
static void
@@ -1876,7 +2114,7 @@ static void
vect_gather_slp_loads (vec<slp_tree> &loads, slp_tree node,
hash_set<slp_tree> &visited)
{
- if (visited.add (node))
+ if (!node || visited.add (node))
return;
if (SLP_TREE_CHILDREN (node).length () == 0)
@@ -1897,13 +2135,6 @@ vect_gather_slp_loads (vec<slp_tree> &loads, slp_tree node,
}
}
-static void
-vect_gather_slp_loads (slp_instance inst, slp_tree node)
-{
- hash_set<slp_tree> visited;
- vect_gather_slp_loads (SLP_INSTANCE_LOADS (inst), node, visited);
-}
-
/* Find the last store in SLP INSTANCE. */
@@ -1997,124 +2228,121 @@ calculate_unrolling_factor (poly_uint64 nunits, unsigned int group_size)
return exact_div (common_multiple (nunits, group_size), group_size);
}
-/* Analyze an SLP instance starting from a group of grouped stores. Call
- vect_build_slp_tree to build a tree of packed stmts if possible.
- Return FALSE if it's impossible to SLP any stmt in the loop. */
+/* Helper function of vect_match_slp_patterns.
+
+ Attempts to match patterns against the slp tree rooted in REF_NODE using
+ VINFO. Patterns are matched in post-order traversal.
+
+ If matching is successful the value in REF_NODE is updated and returned, if
+ not then it is returned unchanged. */
static bool
-vect_analyze_slp_instance (vec_info *vinfo,
- scalar_stmts_to_slp_tree_map_t *bst_map,
- stmt_vec_info stmt_info, unsigned max_tree_size)
+vect_match_slp_patterns_2 (slp_tree *ref_node, vec_info *vinfo,
+ slp_tree_to_load_perm_map_t *perm_cache,
+ hash_set<slp_tree> *visited)
{
- slp_instance new_instance;
- slp_tree node;
- unsigned int group_size;
- unsigned int i;
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- vec<stmt_vec_info> scalar_stmts;
- bool constructor = false;
+ unsigned i;
+ slp_tree node = *ref_node;
+ bool found_p = false;
+ if (!node || visited->add (node))
+ return false;
- if (is_a <bb_vec_info> (vinfo))
- vect_location = stmt_info->stmt;
- if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- {
- group_size = DR_GROUP_SIZE (stmt_info);
- }
- else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
- {
- gcc_assert (is_a <loop_vec_info> (vinfo));
- group_size = REDUC_GROUP_SIZE (stmt_info);
- }
- else if (is_gimple_assign (stmt_info->stmt)
- && gimple_assign_rhs_code (stmt_info->stmt) == CONSTRUCTOR)
- {
- group_size = CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt_info->stmt));
- constructor = true;
- }
- else
- {
- gcc_assert (is_a <loop_vec_info> (vinfo));
- group_size = as_a <loop_vec_info> (vinfo)->reductions.length ();
- }
+ slp_tree child;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+ found_p |= vect_match_slp_patterns_2 (&SLP_TREE_CHILDREN (node)[i],
+ vinfo, perm_cache, visited);
- /* Create a node (a root of the SLP tree) for the packed grouped stores. */
- scalar_stmts.create (group_size);
- stmt_vec_info next_info = stmt_info;
- if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- {
- /* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */
- while (next_info)
- {
- scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
- next_info = DR_GROUP_NEXT_ELEMENT (next_info);
- }
- }
- else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
- {
- /* Collect the reduction stmts and store them in
- SLP_TREE_SCALAR_STMTS. */
- while (next_info)
- {
- scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
- next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
- }
- /* Mark the first element of the reduction chain as reduction to properly
- transform the node. In the reduction analysis phase only the last
- element of the chain is marked as reduction. */
- STMT_VINFO_DEF_TYPE (stmt_info)
- = STMT_VINFO_DEF_TYPE (scalar_stmts.last ());
- STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))
- = STMT_VINFO_REDUC_DEF (vect_orig_stmt (scalar_stmts.last ()));
- }
- else if (constructor)
+ for (unsigned x = 0; x < num__slp_patterns; x++)
{
- tree rhs = gimple_assign_rhs1 (stmt_info->stmt);
- tree val;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
+ vect_pattern *pattern = slp_patterns[x] (perm_cache, ref_node);
+ if (pattern)
{
- if (TREE_CODE (val) == SSA_NAME)
- {
- gimple* def = SSA_NAME_DEF_STMT (val);
- stmt_vec_info def_info = vinfo->lookup_stmt (def);
- /* Value is defined in another basic block. */
- if (!def_info)
- return false;
- def_info = vect_stmt_to_vectorize (def_info);
- scalar_stmts.safe_push (def_info);
- }
- else
- return false;
+ pattern->build (vinfo);
+ delete pattern;
+ found_p = true;
}
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Analyzing vectorizable constructor: %G\n",
- stmt_info->stmt);
}
- else
+
+ return found_p;
+}
+
+/* Applies pattern matching to the given SLP tree rooted in REF_NODE using
+ vec_info VINFO.
+
+ The modified tree is returned. Patterns are tried in order and multiple
+ patterns may match. */
+
+static bool
+vect_match_slp_patterns (slp_instance instance, vec_info *vinfo,
+ hash_set<slp_tree> *visited,
+ slp_tree_to_load_perm_map_t *perm_cache,
+ scalar_stmts_to_slp_tree_map_t * /* bst_map */)
+{
+ DUMP_VECT_SCOPE ("vect_match_slp_patterns");
+ slp_tree *ref_node = &SLP_INSTANCE_TREE (instance);
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Analyzing SLP tree %p for patterns\n",
+ SLP_INSTANCE_TREE (instance));
+
+ bool found_p
+ = vect_match_slp_patterns_2 (ref_node, vinfo, perm_cache, visited);
+
+ if (found_p)
{
- /* Collect reduction statements. */
- vec<stmt_vec_info> reductions = as_a <loop_vec_info> (vinfo)->reductions;
- for (i = 0; reductions.iterate (i, &next_info); i++)
- scalar_stmts.safe_push (next_info);
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Pattern matched SLP tree\n");
+ vect_print_slp_graph (MSG_NOTE, vect_location, *ref_node);
+ }
}
+ return found_p;
+}
+
+/* Analyze an SLP instance starting from a group of grouped stores. Call
+ vect_build_slp_tree to build a tree of packed stmts if possible.
+ Return FALSE if it's impossible to SLP any stmt in the loop. */
+
+static bool
+vect_analyze_slp_instance (vec_info *vinfo,
+ scalar_stmts_to_slp_tree_map_t *bst_map,
+ stmt_vec_info stmt_info, slp_instance_kind kind,
+ unsigned max_tree_size, unsigned *limit);
+
+/* Analyze an SLP instance starting from SCALAR_STMTS which are a group
+ of KIND. Return true if successful. */
+
+static bool
+vect_build_slp_instance (vec_info *vinfo,
+ slp_instance_kind kind,
+ vec<stmt_vec_info> &scalar_stmts,
+ stmt_vec_info root_stmt_info,
+ unsigned max_tree_size, unsigned *limit,
+ scalar_stmts_to_slp_tree_map_t *bst_map,
+ /* ??? We need stmt_info for group splitting. */
+ stmt_vec_info stmt_info_)
+{
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
"Starting SLP discovery for\n");
- for (i = 0; i < scalar_stmts.length (); ++i)
+ for (unsigned i = 0; i < scalar_stmts.length (); ++i)
dump_printf_loc (MSG_NOTE, vect_location,
" %G", scalar_stmts[i]->stmt);
}
/* Build the tree for the SLP instance. */
+ unsigned int group_size = scalar_stmts.length ();
bool *matches = XALLOCAVEC (bool, group_size);
- unsigned npermutes = 0;
poly_uint64 max_nunits = 1;
unsigned tree_size = 0;
- node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
- &max_nunits, matches, &npermutes,
- &tree_size, bst_map);
+ unsigned i;
+ slp_tree node = vect_build_slp_tree (vinfo, scalar_stmts, group_size,
+ &max_nunits, matches, limit,
+ &tree_size, bst_map);
if (node != NULL)
{
/* Calculate the unrolling factor based on the smallest type. */
@@ -2148,98 +2376,77 @@ vect_analyze_slp_instance (vec_info *vinfo,
else
{
/* Create a new SLP instance. */
- new_instance = XNEW (class _slp_instance);
+ slp_instance new_instance = XNEW (class _slp_instance);
SLP_INSTANCE_TREE (new_instance) = node;
SLP_INSTANCE_UNROLLING_FACTOR (new_instance) = unrolling_factor;
SLP_INSTANCE_LOADS (new_instance) = vNULL;
- SLP_INSTANCE_ROOT_STMT (new_instance) = constructor ? stmt_info : NULL;
+ SLP_INSTANCE_ROOT_STMT (new_instance) = root_stmt_info;
+ SLP_INSTANCE_KIND (new_instance) = kind;
new_instance->reduc_phis = NULL;
new_instance->cost_vec = vNULL;
new_instance->subgraph_entries = vNULL;
- vect_gather_slp_loads (new_instance, node);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"SLP size %u vs. limit %u.\n",
tree_size, max_tree_size);
- /* Check whether any load is possibly permuted. */
- slp_tree load_node;
- bool loads_permuted = false;
- FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (new_instance), i, load_node)
+ /* Fixup SLP reduction chains. */
+ if (kind == slp_inst_kind_reduc_chain)
{
- if (!SLP_TREE_LOAD_PERMUTATION (load_node).exists ())
- continue;
- unsigned j;
- stmt_vec_info load_info;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (load_node), j, load_info)
- if (SLP_TREE_LOAD_PERMUTATION (load_node)[j] != j)
- {
- loads_permuted = true;
- break;
- }
- }
-
- /* If the loads and stores can be handled with load/store-lane
- instructions do not generate this SLP instance. */
- if (is_a <loop_vec_info> (vinfo)
- && loads_permuted
- && dr
- && vect_store_lanes_supported
- (STMT_VINFO_VECTYPE (scalar_stmts[0]), group_size, false))
- {
- slp_tree load_node;
- FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (new_instance), i, load_node)
+ /* If this is a reduction chain with a conversion in front
+ amend the SLP tree with a node for that. */
+ gimple *scalar_def
+ = vect_orig_stmt (scalar_stmts[group_size - 1])->stmt;
+ if (STMT_VINFO_DEF_TYPE (scalar_stmts[0]) != vect_reduction_def)
{
- stmt_vec_info stmt_vinfo = DR_GROUP_FIRST_ELEMENT
- (SLP_TREE_SCALAR_STMTS (load_node)[0]);
- /* Use SLP for strided accesses (or if we can't load-lanes). */
- if (STMT_VINFO_STRIDED_P (stmt_vinfo)
- || ! vect_load_lanes_supported
- (STMT_VINFO_VECTYPE (stmt_vinfo),
- DR_GROUP_SIZE (stmt_vinfo), false))
- break;
- }
- if (i == SLP_INSTANCE_LOADS (new_instance).length ())
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Built SLP cancelled: can use "
- "load/store-lanes\n");
- vect_free_slp_instance (new_instance);
- return false;
+ /* Get at the conversion stmt - we know it's the single use
+ of the last stmt of the reduction chain. */
+ use_operand_p use_p;
+ bool r = single_imm_use (gimple_assign_lhs (scalar_def),
+ &use_p, &scalar_def);
+ gcc_assert (r);
+ stmt_vec_info next_info = vinfo->lookup_stmt (scalar_def);
+ next_info = vect_stmt_to_vectorize (next_info);
+ scalar_stmts = vNULL;
+ scalar_stmts.create (group_size);
+ for (unsigned i = 0; i < group_size; ++i)
+ scalar_stmts.quick_push (next_info);
+ slp_tree conv = vect_create_new_slp_node (scalar_stmts, 1);
+ SLP_TREE_VECTYPE (conv) = STMT_VINFO_VECTYPE (next_info);
+ SLP_TREE_CHILDREN (conv).quick_push (node);
+ SLP_INSTANCE_TREE (new_instance) = conv;
+ /* We also have to fake this conversion stmt as SLP reduction
+ group so we don't have to mess with too much code
+ elsewhere. */
+ REDUC_GROUP_FIRST_ELEMENT (next_info) = next_info;
+ REDUC_GROUP_NEXT_ELEMENT (next_info) = NULL;
}
- }
-
- /* If this is a reduction chain with a conversion in front
- amend the SLP tree with a node for that. */
- if (!dr
- && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
- && STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def)
- {
- /* Get at the conversion stmt - we know it's the single use
- of the last stmt of the reduction chain. */
- gimple *tem = vect_orig_stmt (scalar_stmts[group_size - 1])->stmt;
+ /* Fill the backedge child of the PHI SLP node. The
+ general matching code cannot find it because the
+ scalar code does not reflect how we vectorize the
+ reduction. */
use_operand_p use_p;
- gimple *use_stmt;
- bool r = single_imm_use (gimple_assign_lhs (tem),
- &use_p, &use_stmt);
- gcc_assert (r);
- next_info = vinfo->lookup_stmt (use_stmt);
- next_info = vect_stmt_to_vectorize (next_info);
- scalar_stmts = vNULL;
- scalar_stmts.create (group_size);
- for (unsigned i = 0; i < group_size; ++i)
- scalar_stmts.quick_push (next_info);
- slp_tree conv = vect_create_new_slp_node (scalar_stmts, 1);
- SLP_TREE_VECTYPE (conv) = STMT_VINFO_VECTYPE (next_info);
- SLP_TREE_CHILDREN (conv).quick_push (node);
- SLP_INSTANCE_TREE (new_instance) = conv;
- /* We also have to fake this conversion stmt as SLP reduction
- group so we don't have to mess with too much code
- elsewhere. */
- REDUC_GROUP_FIRST_ELEMENT (next_info) = next_info;
- REDUC_GROUP_NEXT_ELEMENT (next_info) = NULL;
+ imm_use_iterator imm_iter;
+ class loop *loop = LOOP_VINFO_LOOP (as_a <loop_vec_info> (vinfo));
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter,
+ gimple_get_lhs (scalar_def))
+ /* There are exactly two non-debug uses, the reduction
+ PHI and the loop-closed PHI node. */
+ if (!is_gimple_debug (USE_STMT (use_p))
+ && gimple_bb (USE_STMT (use_p)) == loop->header)
+ {
+ auto_vec<stmt_vec_info, 64> phis (group_size);
+ stmt_vec_info phi_info
+ = vinfo->lookup_stmt (USE_STMT (use_p));
+ for (unsigned i = 0; i < group_size; ++i)
+ phis.quick_push (phi_info);
+ slp_tree *phi_node = bst_map->get (phis);
+ unsigned dest_idx = loop_latch_edge (loop)->dest_idx;
+ SLP_TREE_CHILDREN (*phi_node)[dest_idx]
+ = SLP_INSTANCE_TREE (new_instance);
+ SLP_INSTANCE_TREE (new_instance)->refcnt++;
+ }
}
vinfo->slp_instances.safe_push (new_instance);
@@ -2253,7 +2460,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
- "Final SLP tree for instance:\n");
+ "Final SLP tree for instance %p:\n", new_instance);
vect_print_slp_graph (MSG_NOTE, vect_location,
SLP_INSTANCE_TREE (new_instance));
}
@@ -2268,10 +2475,13 @@ vect_analyze_slp_instance (vec_info *vinfo,
scalar_stmts.release ();
}
+ stmt_vec_info stmt_info = stmt_info_;
/* Try to break the group up into pieces. */
- if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
- && DR_IS_WRITE (STMT_VINFO_DATA_REF (stmt_info)))
+ if (kind == slp_inst_kind_store)
{
+ /* ??? We could delay all the actual splitting of store-groups
+ until after SLP discovery of the original group completed.
+ Then we can recurse to vect_build_slp_instance directly. */
for (i = 0; i < group_size; i++)
if (!matches[i])
break;
@@ -2284,7 +2494,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
tree scalar_type
= TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
- least_bit_hwi (i));
+ 1 << floor_log2 (i));
unsigned HOST_WIDE_INT const_nunits;
if (vectype
&& TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits))
@@ -2299,19 +2509,28 @@ vect_analyze_slp_instance (vec_info *vinfo,
stmt_vec_info rest = vect_split_slp_store_group (stmt_info,
group1_size);
bool res = vect_analyze_slp_instance (vinfo, bst_map, stmt_info,
- max_tree_size);
- /* If the first non-match was in the middle of a vector,
- skip the rest of that vector. Do not bother to re-analyze
- single stmt groups. */
- if (group1_size < i)
+ kind, max_tree_size,
+ limit);
+ /* Split the rest at the failure point and possibly
+ re-analyze the remaining matching part if it has
+ at least two lanes. */
+ if (group1_size < i
+ && (i + 1 < group_size
+ || i - group1_size > 1))
{
- i = group1_size + const_nunits;
- if (i + 1 < group_size)
- rest = vect_split_slp_store_group (rest, const_nunits);
+ stmt_vec_info rest2 = rest;
+ rest = vect_split_slp_store_group (rest, i - group1_size);
+ if (i - group1_size > 1)
+ res |= vect_analyze_slp_instance (vinfo, bst_map, rest2,
+ kind, max_tree_size,
+ limit);
}
+ /* Re-analyze the non-matching tail if it has at least
+ two lanes. */
if (i + 1 < group_size)
res |= vect_analyze_slp_instance (vinfo, bst_map,
- rest, max_tree_size);
+ rest, kind, max_tree_size,
+ limit);
return res;
}
}
@@ -2336,10 +2555,10 @@ vect_analyze_slp_instance (vec_info *vinfo,
DR_GROUP_GAP (stmt_info) = 0;
bool res = vect_analyze_slp_instance (vinfo, bst_map, stmt_info,
- max_tree_size);
+ kind, max_tree_size, limit);
if (i + 1 < group_size)
res |= vect_analyze_slp_instance (vinfo, bst_map,
- rest, max_tree_size);
+ rest, kind, max_tree_size, limit);
return res;
}
@@ -2354,58 +2573,96 @@ vect_analyze_slp_instance (vec_info *vinfo,
return false;
}
-/* Fill in backedge SLP children in the SLP graph. */
-static void
-vect_analyze_slp_backedges (vec_info *vinfo, slp_tree node,
- scalar_stmts_to_slp_tree_map_t *bst_map,
- hash_set<slp_tree> &visited)
+/* Analyze an SLP instance starting from a group of grouped stores. Call
+ vect_build_slp_tree to build a tree of packed stmts if possible.
+ Return FALSE if it's impossible to SLP any stmt in the loop. */
+
+static bool
+vect_analyze_slp_instance (vec_info *vinfo,
+ scalar_stmts_to_slp_tree_map_t *bst_map,
+ stmt_vec_info stmt_info,
+ slp_instance_kind kind,
+ unsigned max_tree_size, unsigned *limit)
{
- if (SLP_TREE_DEF_TYPE (node) != vect_internal_def
- || visited.add (node))
- return;
+ unsigned int i;
+ vec<stmt_vec_info> scalar_stmts;
- slp_tree child;
- unsigned i;
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- if (child)
- vect_analyze_slp_backedges (vinfo, child, bst_map, visited);
+ if (is_a <bb_vec_info> (vinfo))
+ vect_location = stmt_info->stmt;
- /* Inductions are not vectorized by vectorizing their defining cycle
- but by materializing the values from SCEV data. */
- if (STMT_VINFO_DEF_TYPE (SLP_TREE_REPRESENTATIVE (node))
- == vect_induction_def)
- return;
+ stmt_vec_info next_info = stmt_info;
+ if (kind == slp_inst_kind_store)
+ {
+ /* Collect the stores and store them in scalar_stmts. */
+ scalar_stmts.create (DR_GROUP_SIZE (stmt_info));
+ while (next_info)
+ {
+ scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
+ next_info = DR_GROUP_NEXT_ELEMENT (next_info);
+ }
+ }
+ else if (kind == slp_inst_kind_reduc_chain)
+ {
+ /* Collect the reduction stmts and store them in scalar_stmts. */
+ scalar_stmts.create (REDUC_GROUP_SIZE (stmt_info));
+ while (next_info)
+ {
+ scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
+ next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
+ }
+ /* Mark the first element of the reduction chain as reduction to properly
+ transform the node. In the reduction analysis phase only the last
+ element of the chain is marked as reduction. */
+ STMT_VINFO_DEF_TYPE (stmt_info)
+ = STMT_VINFO_DEF_TYPE (scalar_stmts.last ());
+ STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))
+ = STMT_VINFO_REDUC_DEF (vect_orig_stmt (scalar_stmts.last ()));
+ }
+ else if (kind == slp_inst_kind_ctor)
+ {
+ tree rhs = gimple_assign_rhs1 (stmt_info->stmt);
+ tree val;
+ scalar_stmts.create (CONSTRUCTOR_NELTS (rhs));
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
+ {
+ stmt_vec_info def_info = vinfo->lookup_def (val);
+ def_info = vect_stmt_to_vectorize (def_info);
+ scalar_stmts.quick_push (def_info);
+ }
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Analyzing vectorizable constructor: %G\n",
+ stmt_info->stmt);
+ }
+ else if (kind == slp_inst_kind_reduc_group)
+ {
+ /* Collect reduction statements. */
+ vec<stmt_vec_info> reductions = as_a <loop_vec_info> (vinfo)->reductions;
+ scalar_stmts.create (reductions.length ());
+ for (i = 0; reductions.iterate (i, &next_info); i++)
+ if (STMT_VINFO_RELEVANT_P (next_info)
+ || STMT_VINFO_LIVE_P (next_info))
+ scalar_stmts.quick_push (next_info);
+ /* If less than two were relevant/live there's nothing to SLP. */
+ if (scalar_stmts.length () < 2)
+ return false;
+ }
+ else
+ gcc_unreachable ();
- if (gphi *phi = dyn_cast <gphi *> (SLP_TREE_REPRESENTATIVE (node)->stmt))
- for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
- {
- auto_vec<stmt_vec_info, 64> stmts;
- unsigned j;
- stmt_vec_info phi_info;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), j, phi_info)
- {
- tree def = gimple_phi_arg_def (as_a <gphi *>(phi_info->stmt), i);
- stmt_vec_info def_info = vinfo->lookup_def (def);
- if (!def_info)
- break;
- stmts.safe_push (vect_stmt_to_vectorize (def_info));
- }
- if (j != SLP_TREE_LANES (node))
- continue;
- slp_tree *edge_def = bst_map->get (stmts);
- if (edge_def)
- {
- /* ??? We're currently not recording non-backedge children
- of PHIs like external reduction initial values. Avoid
- NULL entries in SLP_TREE_CHILDREN for those and thus
- for now simply only record backedge defs at a
- SLP_TREE_CHILDREN index possibly not matching that of
- the corresponding PHI argument index. */
- SLP_TREE_CHILDREN (node).quick_push (*edge_def);
- (*edge_def)->refcnt++;
- }
- }
+ /* Build the tree for the SLP instance. */
+ bool res = vect_build_slp_instance (vinfo, kind, scalar_stmts,
+ kind == slp_inst_kind_ctor
+ ? stmt_info : NULL,
+ max_tree_size, limit, bst_map,
+ kind == slp_inst_kind_store
+ ? stmt_info : NULL);
+
+ /* ??? If this is slp_inst_kind_store and the above succeeded here's
+ where we should do store group splitting. */
+
+ return res;
}
/* Check if there are stmts in the loop can be vectorized using SLP. Build SLP
@@ -2416,54 +2673,75 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{
unsigned int i;
stmt_vec_info first_element;
+ slp_instance instance;
DUMP_VECT_SCOPE ("vect_analyze_slp");
+ unsigned limit = max_tree_size;
+
scalar_stmts_to_slp_tree_map_t *bst_map
= new scalar_stmts_to_slp_tree_map_t ();
/* Find SLP sequences starting from groups of grouped stores. */
FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
- vect_analyze_slp_instance (vinfo, bst_map, first_element, max_tree_size);
+ vect_analyze_slp_instance (vinfo, bst_map, first_element,
+ STMT_VINFO_GROUPED_ACCESS (first_element)
+ ? slp_inst_kind_store : slp_inst_kind_ctor,
+ max_tree_size, &limit);
- if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
+ if (bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo))
{
- if (loop_vinfo->reduction_chains.length () > 0)
+ for (unsigned i = 0; i < bb_vinfo->roots.length (); ++i)
{
- /* Find SLP sequences starting from reduction chains. */
- FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element)
- if (! vect_analyze_slp_instance (vinfo, bst_map, first_element,
- max_tree_size))
+ vect_location = bb_vinfo->roots[i].root->stmt;
+ if (vect_build_slp_instance (bb_vinfo, bb_vinfo->roots[i].kind,
+ bb_vinfo->roots[i].stmts,
+ bb_vinfo->roots[i].root,
+ max_tree_size, &limit, bst_map, NULL))
+ bb_vinfo->roots[i].stmts = vNULL;
+ }
+ }
+
+ if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
+ {
+ /* Find SLP sequences starting from reduction chains. */
+ FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element)
+ if (! STMT_VINFO_RELEVANT_P (first_element)
+ && ! STMT_VINFO_LIVE_P (first_element))
+ ;
+ else if (! vect_analyze_slp_instance (vinfo, bst_map, first_element,
+ slp_inst_kind_reduc_chain,
+ max_tree_size, &limit))
+ {
+ /* Dissolve reduction chain group. */
+ stmt_vec_info vinfo = first_element;
+ stmt_vec_info last = NULL;
+ while (vinfo)
{
- /* Dissolve reduction chain group. */
- stmt_vec_info vinfo = first_element;
- stmt_vec_info last = NULL;
- while (vinfo)
- {
- stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (vinfo);
- REDUC_GROUP_FIRST_ELEMENT (vinfo) = NULL;
- REDUC_GROUP_NEXT_ELEMENT (vinfo) = NULL;
- last = vinfo;
- vinfo = next;
- }
- STMT_VINFO_DEF_TYPE (first_element) = vect_internal_def;
- /* It can be still vectorized as part of an SLP reduction. */
- loop_vinfo->reductions.safe_push (last);
+ stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (vinfo);
+ REDUC_GROUP_FIRST_ELEMENT (vinfo) = NULL;
+ REDUC_GROUP_NEXT_ELEMENT (vinfo) = NULL;
+ last = vinfo;
+ vinfo = next;
}
- }
+ STMT_VINFO_DEF_TYPE (first_element) = vect_internal_def;
+ /* It can be still vectorized as part of an SLP reduction. */
+ loop_vinfo->reductions.safe_push (last);
+ }
/* Find SLP sequences starting from groups of reductions. */
if (loop_vinfo->reductions.length () > 1)
vect_analyze_slp_instance (vinfo, bst_map, loop_vinfo->reductions[0],
- max_tree_size);
+ slp_inst_kind_reduc_group, max_tree_size,
+ &limit);
}
- /* Fill in backedges. */
- slp_instance instance;
- hash_set<slp_tree> visited;
- FOR_EACH_VEC_ELT (vinfo->slp_instances, i, instance)
- vect_analyze_slp_backedges (vinfo, SLP_INSTANCE_TREE (instance),
- bst_map, visited);
+ hash_set<slp_tree> visited_patterns;
+ slp_tree_to_load_perm_map_t perm_cache;
+ /* See if any patterns can be found in the SLP tree. */
+ FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
+ vect_match_slp_patterns (instance, vinfo, &visited_patterns, &perm_cache,
+ bst_map);
/* The map keeps a reference on SLP nodes built, release that. */
for (scalar_stmts_to_slp_tree_map_t::iterator it = bst_map->begin ();
@@ -2489,11 +2767,16 @@ vect_slp_build_vertices (hash_set<slp_tree> &visited, slp_tree node,
node->vertex = vertices.length ();
vertices.safe_push (node);
- if (SLP_TREE_CHILDREN (node).is_empty ())
+
+ bool leaf = true;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+ if (child)
+ {
+ leaf = false;
+ vect_slp_build_vertices (visited, child, vertices, leafs);
+ }
+ if (leaf)
leafs.safe_push (node->vertex);
- else
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_slp_build_vertices (visited, child, vertices, leafs);
}
/* Fill the vertices and leafs vector with all nodes in the SLP graph. */
@@ -2506,8 +2789,18 @@ vect_slp_build_vertices (vec_info *info, vec<slp_tree> &vertices,
unsigned i;
slp_instance instance;
FOR_EACH_VEC_ELT (info->slp_instances, i, instance)
- vect_slp_build_vertices (visited, SLP_INSTANCE_TREE (instance), vertices,
- leafs);
+ {
+ unsigned n_v = vertices.length ();
+ unsigned n_l = leafs.length ();
+ vect_slp_build_vertices (visited, SLP_INSTANCE_TREE (instance), vertices,
+ leafs);
+ /* If we added vertices but no entries to the reverse graph we've
+ added a cycle that is not backwards-reachable. Push the entry
+ to mimic as leaf then. */
+ if (vertices.length () > n_v
+ && leafs.length () == n_l)
+ leafs.safe_push (SLP_INSTANCE_TREE (instance)->vertex);
+ }
}
/* Apply (reverse) bijectite PERM to VEC. */
@@ -2571,7 +2864,8 @@ vect_optimize_slp (vec_info *vinfo)
unsigned j;
slp_tree child;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
- add_edge (slpg, i, child->vertex);
+ if (child)
+ add_edge (slpg, i, child->vertex);
}
/* Compute (reverse) postorder on the inverted graph. */
@@ -2600,9 +2894,11 @@ vect_optimize_slp (vec_info *vinfo)
|| SLP_TREE_DEF_TYPE (node) == vect_constant_def)
continue;
- /* Loads are the only thing generating permutes and leafs do not
- change across iterations. */
- bitmap_set_bit (n_visited, idx);
+ /* Leafs do not change across iterations. Note leafs also double
+ as entries to the reverse graph. */
+ if (!slpg->vertices[idx].succ)
+ bitmap_set_bit (n_visited, idx);
+ /* Loads are the only thing generating permutes. */
if (!SLP_TREE_LOAD_PERMUTATION (node).exists ())
continue;
@@ -2770,7 +3066,7 @@ vect_optimize_slp (vec_info *vinfo)
slp_tree child;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
{
- if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
+ if (!child || SLP_TREE_DEF_TYPE (child) == vect_internal_def)
continue;
/* If the vector is uniform there's nothing to do. */
@@ -2796,6 +3092,18 @@ vect_optimize_slp (vec_info *vinfo)
/* For loads simply drop the permutation, the load permutation
already performs the desired permutation. */
;
+ else if (SLP_TREE_LANE_PERMUTATION (node).exists ())
+ {
+ /* If the node if already a permute node we just need to apply
+ the permutation to the permute node itself. */
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "simplifying permute node %p\n",
+ node);
+
+ vect_slp_permute (perms[perm], SLP_TREE_LANE_PERMUTATION (node),
+ true);
+ }
else
{
if (dump_enabled_p ())
@@ -2864,7 +3172,7 @@ vect_optimize_slp (vec_info *vinfo)
/* Now elide load permutations that are not necessary. */
for (i = 0; i < leafs.length (); ++i)
{
- node = vertices[i];
+ node = vertices[leafs[i]];
if (!SLP_TREE_LOAD_PERMUTATION (node).exists ())
continue;
@@ -2923,6 +3231,21 @@ vect_optimize_slp (vec_info *vinfo)
}
}
+/* Gather loads reachable from the individual SLP graph entries. */
+
+void
+vect_gather_slp_loads (vec_info *vinfo)
+{
+ unsigned i;
+ slp_instance instance;
+ FOR_EACH_VEC_ELT (vinfo->slp_instances, i, instance)
+ {
+ hash_set<slp_tree> visited;
+ vect_gather_slp_loads (SLP_INSTANCE_LOADS (instance),
+ SLP_INSTANCE_TREE (instance), visited);
+ }
+}
+
/* For each possible SLP instance decide whether to SLP it and calculate overall
unrolling factor needed to SLP the loop. Return TRUE if decided to SLP at
@@ -3006,6 +3329,65 @@ vect_detect_hybrid_slp (tree *tp, int *, void *data)
return NULL_TREE;
}
+/* Look if STMT_INFO is consumed by SLP indirectly and mark it pure_slp
+ if so, otherwise pushing it to WORKLIST. */
+
+static void
+maybe_push_to_hybrid_worklist (vec_info *vinfo,
+ vec<stmt_vec_info> &worklist,
+ stmt_vec_info stmt_info)
+{
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Processing hybrid candidate : %G", stmt_info->stmt);
+ stmt_vec_info orig_info = vect_orig_stmt (stmt_info);
+ imm_use_iterator iter2;
+ ssa_op_iter iter1;
+ use_operand_p use_p;
+ def_operand_p def_p;
+ bool any_def = false;
+ FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_info->stmt, iter1, SSA_OP_DEF)
+ {
+ any_def = true;
+ FOR_EACH_IMM_USE_FAST (use_p, iter2, DEF_FROM_PTR (def_p))
+ {
+ if (is_gimple_debug (USE_STMT (use_p)))
+ continue;
+ stmt_vec_info use_info = vinfo->lookup_stmt (USE_STMT (use_p));
+ /* An out-of loop use means this is a loop_vect sink. */
+ if (!use_info)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Found loop_vect sink: %G", stmt_info->stmt);
+ worklist.safe_push (stmt_info);
+ return;
+ }
+ else if (!STMT_SLP_TYPE (vect_stmt_to_vectorize (use_info)))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Found loop_vect use: %G", use_info->stmt);
+ worklist.safe_push (stmt_info);
+ return;
+ }
+ }
+ }
+ /* No def means this is a loo_vect sink. */
+ if (!any_def)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Found loop_vect sink: %G", stmt_info->stmt);
+ worklist.safe_push (stmt_info);
+ return;
+ }
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Marked SLP consumed stmt pure: %G", stmt_info->stmt);
+ STMT_SLP_TYPE (stmt_info) = pure_slp;
+}
+
/* Find stmts that must be both vectorized and SLPed. */
void
@@ -3015,9 +3397,14 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
/* All stmts participating in SLP are marked pure_slp, all other
stmts are loop_vect.
- First collect all loop_vect stmts into a worklist. */
+ First collect all loop_vect stmts into a worklist.
+ SLP patterns cause not all original scalar stmts to appear in
+ SLP_TREE_SCALAR_STMTS and thus not all of them are marked pure_slp.
+ Rectify this here and do a backward walk over the IL only considering
+ stmts as loop_vect when they are used by a loop_vect stmt and otherwise
+ mark them as pure_slp. */
auto_vec<stmt_vec_info> worklist;
- for (unsigned i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; ++i)
+ for (int i = LOOP_VINFO_LOOP (loop_vinfo)->num_nodes - 1; i >= 0; --i)
{
basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
@@ -3026,10 +3413,11 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
gphi *phi = gsi.phi ();
stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (phi);
if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
- worklist.safe_push (stmt_info);
+ maybe_push_to_hybrid_worklist (loop_vinfo,
+ worklist, stmt_info);
}
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
- gsi_next (&gsi))
+ for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
+ gsi_prev (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
if (is_gimple_debug (stmt))
@@ -3045,12 +3433,14 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
= loop_vinfo->lookup_stmt (gsi_stmt (gsi2));
if (!STMT_SLP_TYPE (patt_info)
&& STMT_VINFO_RELEVANT (patt_info))
- worklist.safe_push (patt_info);
+ maybe_push_to_hybrid_worklist (loop_vinfo,
+ worklist, patt_info);
}
stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
}
if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
- worklist.safe_push (stmt_info);
+ maybe_push_to_hybrid_worklist (loop_vinfo,
+ worklist, stmt_info);
}
}
@@ -3078,7 +3468,7 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
/* Initialize a bb_vec_info struct for the statements in BBS basic blocks. */
_bb_vec_info::_bb_vec_info (vec<basic_block> _bbs, vec_info_shared *shared)
- : vec_info (vec_info::bb, init_cost (NULL), shared), bbs (_bbs)
+ : vec_info (vec_info::bb, init_cost (NULL), shared), bbs (_bbs), roots (vNULL)
{
for (unsigned i = 0; i < bbs.length (); ++i)
{
@@ -3125,6 +3515,10 @@ _bb_vec_info::~_bb_vec_info ()
gimple_set_uid (stmt, -1);
}
}
+
+ for (unsigned i = 0; i < roots.length (); ++i)
+ roots[i].stmts.release ();
+ roots.release ();
}
/* Subroutine of vect_slp_analyze_node_operations. Handle the root of NODE,
@@ -3175,7 +3569,13 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
if (is_a <bb_vec_info> (vinfo)
&& !vect_update_shared_vectype (stmt_info, SLP_TREE_VECTYPE (node)))
- return false;
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "desired vector type conflicts with earlier one "
+ "for %G", stmt_info->stmt);
+ return false;
+ }
bool dummy;
return vect_analyze_stmt (vinfo, stmt_info, &dummy,
@@ -3200,7 +3600,7 @@ vect_slp_convert_to_external (vec_info *vinfo, slp_tree node,
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
- "Building vector operands from scalars instead\n");
+ "Building vector operands of %p from scalars instead\n", node);
/* Don't remove and free the child nodes here, since they could be
referenced by other structures. The analysis and scheduling phases
@@ -3208,6 +3608,7 @@ vect_slp_convert_to_external (vec_info *vinfo, slp_tree node,
unsigned int group_size = SLP_TREE_LANES (node);
SLP_TREE_DEF_TYPE (node) = vect_external_def;
SLP_TREE_SCALAR_OPS (node).safe_grow (group_size, true);
+ SLP_TREE_LOAD_PERMUTATION (node).release ();
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
{
tree lhs = gimple_get_lhs (vect_orig_stmt (stmt_info)->stmt);
@@ -3282,28 +3683,42 @@ vect_prologue_cost_for_slp (slp_tree node,
static bool
vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
slp_instance node_instance,
- hash_set<slp_tree> &visited,
- hash_set<slp_tree> &lvisited,
+ hash_set<slp_tree> &visited_set,
+ vec<slp_tree> &visited_vec,
stmt_vector_for_cost *cost_vec)
{
int i, j;
slp_tree child;
/* Assume we can code-generate all invariants. */
- if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
+ if (!node
+ || SLP_TREE_DEF_TYPE (node) == vect_constant_def
+ || SLP_TREE_DEF_TYPE (node) == vect_external_def)
return true;
+ if (SLP_TREE_DEF_TYPE (node) == vect_uninitialized_def)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Failed cyclic SLP reference in %p", node);
+ return false;
+ }
+ gcc_assert (SLP_TREE_DEF_TYPE (node) == vect_internal_def);
+
/* If we already analyzed the exact same set of scalar stmts we're done.
We share the generated vector stmts for those. */
- if (visited.contains (node)
- || lvisited.add (node))
+ if (visited_set.add (node))
return true;
+ visited_vec.safe_push (node);
bool res = true;
+ unsigned visited_rec_start = visited_vec.length ();
+ unsigned cost_vec_rec_start = cost_vec->length ();
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
{
res = vect_slp_analyze_node_operations (vinfo, child, node_instance,
- visited, lvisited, cost_vec);
+ visited_set, visited_vec,
+ cost_vec);
if (!res)
break;
}
@@ -3311,8 +3726,14 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
if (res)
res = vect_slp_analyze_node_operations_1 (vinfo, node, node_instance,
cost_vec);
+ /* If analysis failed we have to pop all recursive visited nodes
+ plus ourselves. */
if (!res)
- lvisited.remove (node);
+ {
+ while (visited_vec.length () >= visited_rec_start)
+ visited_set.remove (visited_vec.pop ());
+ cost_vec->truncate (cost_vec_rec_start);
+ }
/* When the node can be vectorized cost invariant nodes it references.
This is not done in DFS order to allow the refering node
@@ -3321,14 +3742,15 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
other referrers. */
if (res)
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
- if ((SLP_TREE_DEF_TYPE (child) == vect_constant_def
- || SLP_TREE_DEF_TYPE (child) == vect_external_def)
+ if (child
+ && (SLP_TREE_DEF_TYPE (child) == vect_constant_def
+ || SLP_TREE_DEF_TYPE (child) == vect_external_def)
/* Perform usual caching, note code-generation still
code-gens these nodes multiple times but we expect
to CSE them later. */
- && !visited.contains (child)
- && !lvisited.add (child))
+ && !visited_set.add (child))
{
+ visited_vec.safe_push (child);
/* ??? After auditing more code paths make a "default"
and push the vector type from NODE to all children
if it is not already set. */
@@ -3376,17 +3798,19 @@ static void
vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo, slp_tree node,
slp_instance instance,
stmt_vector_for_cost *cost_vec,
- hash_set<stmt_vec_info> &svisited)
+ hash_set<stmt_vec_info> &svisited,
+ hash_set<slp_tree> &visited)
{
+ if (visited.add (node))
+ return;
+
unsigned i;
stmt_vec_info stmt_info;
stmt_vec_info last_stmt = vect_find_last_scalar_stmt_in_slp (node);
- bool all_visited = true;
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
{
if (svisited.contains (stmt_info))
continue;
- all_visited = false;
stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
if (STMT_VINFO_IN_PATTERN_P (orig_stmt_info)
&& STMT_VINFO_RELATED_STMT (orig_stmt_info) != stmt_info)
@@ -3396,7 +3820,7 @@ vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo, slp_tree node,
gimple *orig_stmt = orig_stmt_info->stmt;
ssa_op_iter op_iter;
def_operand_p def_p;
- FOR_EACH_SSA_DEF_OPERAND (def_p, orig_stmt, op_iter, SSA_OP_DEF)
+ FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_stmt, op_iter, SSA_OP_DEF)
{
imm_use_iterator use_iter;
gimple *use_stmt;
@@ -3460,14 +3884,12 @@ vect_bb_slp_mark_live_stmts (bb_vec_info bb_vinfo, slp_tree node,
if (mark_visited)
svisited.add (stmt_info);
}
- if (all_visited)
- return;
slp_tree child;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
+ if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def)
vect_bb_slp_mark_live_stmts (bb_vinfo, child, instance,
- cost_vec, svisited);
+ cost_vec, svisited, visited);
}
/* Analyze statements in SLP instances of VINFO. Return true if the
@@ -3484,14 +3906,14 @@ vect_slp_analyze_operations (vec_info *vinfo)
hash_set<slp_tree> visited;
for (i = 0; vinfo->slp_instances.iterate (i, &instance); )
{
- hash_set<slp_tree> lvisited;
+ auto_vec<slp_tree> visited_vec;
stmt_vector_for_cost cost_vec;
cost_vec.create (2);
if (is_a <bb_vec_info> (vinfo))
vect_location = instance->location ();
if (!vect_slp_analyze_node_operations (vinfo,
SLP_INSTANCE_TREE (instance),
- instance, visited, lvisited,
+ instance, visited, visited_vec,
&cost_vec)
/* Instances with a root stmt require vectorized defs for the
SLP tree root. */
@@ -3508,12 +3930,11 @@ vect_slp_analyze_operations (vec_info *vinfo)
vect_free_slp_instance (instance);
vinfo->slp_instances.ordered_remove (i);
cost_vec.release ();
+ while (!visited_vec.is_empty ())
+ visited.remove (visited_vec.pop ());
}
else
{
- for (hash_set<slp_tree>::iterator x = lvisited.begin();
- x != lvisited.end(); ++x)
- visited.add (*x);
i++;
/* For BB vectorization remember the SLP graph entry
@@ -3532,11 +3953,13 @@ vect_slp_analyze_operations (vec_info *vinfo)
if (bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo))
{
hash_set<stmt_vec_info> svisited;
+ hash_set<slp_tree> visited;
for (i = 0; vinfo->slp_instances.iterate (i, &instance); ++i)
{
vect_location = instance->location ();
vect_bb_slp_mark_live_stmts (bb_vinfo, SLP_INSTANCE_TREE (instance),
- instance, &instance->cost_vec, svisited);
+ instance, &instance->cost_vec, svisited,
+ visited);
}
}
@@ -3600,7 +4023,7 @@ vect_bb_partition_graph_r (bb_vec_info bb_vinfo,
slp_tree child;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
+ if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def)
vect_bb_partition_graph_r (bb_vinfo, instance, child, stmt_to_instance,
instance_leader, visited);
}
@@ -3645,7 +4068,7 @@ vect_bb_partition_graph (bb_vec_info bb_vinfo)
and return it. Do not account defs that are marked in LIFE and
update LIFE according to uses of NODE. */
-static void
+static void
vect_bb_slp_scalar_cost (vec_info *vinfo,
slp_tree node, vec<bool, va_heap> *life,
stmt_vector_for_cost *cost_vec,
@@ -3656,7 +4079,7 @@ vect_bb_slp_scalar_cost (vec_info *vinfo,
slp_tree child;
if (visited.add (node))
- return;
+ return;
FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
{
@@ -3676,7 +4099,7 @@ vect_bb_slp_scalar_cost (vec_info *vinfo,
the scalar cost. */
if (!STMT_VINFO_LIVE_P (stmt_info))
{
- FOR_EACH_SSA_DEF_OPERAND (def_p, orig_stmt, op_iter, SSA_OP_DEF)
+ FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_stmt, op_iter, SSA_OP_DEF)
{
imm_use_iterator use_iter;
gimple *use_stmt;
@@ -3714,13 +4137,14 @@ vect_bb_slp_scalar_cost (vec_info *vinfo,
continue;
else
kind = scalar_stmt;
- record_stmt_cost (cost_vec, 1, kind, orig_stmt_info, 0, vect_body);
+ record_stmt_cost (cost_vec, 1, kind, orig_stmt_info,
+ SLP_TREE_VECTYPE (node), 0, vect_body);
}
auto_vec<bool, 20> subtree_life;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
{
- if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
+ if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def)
{
/* Do not directly pass LIFE to the recursive call, copy it to
confine changes in the callee to the current child/subtree. */
@@ -3817,6 +4241,38 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
return true;
}
+/* qsort comparator for lane defs. */
+
+static int
+vld_cmp (const void *a_, const void *b_)
+{
+ auto *a = (const std::pair<unsigned, tree> *)a_;
+ auto *b = (const std::pair<unsigned, tree> *)b_;
+ return a->first - b->first;
+}
+
+/* Return true if USE_STMT is a vector lane insert into VEC and set
+ *THIS_LANE to the lane number that is set. */
+
+static bool
+vect_slp_is_lane_insert (gimple *use_stmt, tree vec, unsigned *this_lane)
+{
+ gassign *use_ass = dyn_cast <gassign *> (use_stmt);
+ if (!use_ass
+ || gimple_assign_rhs_code (use_ass) != BIT_INSERT_EXPR
+ || (vec
+ ? gimple_assign_rhs1 (use_ass) != vec
+ : ((vec = gimple_assign_rhs1 (use_ass)), false))
+ || !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (vec)),
+ TREE_TYPE (gimple_assign_rhs2 (use_ass)))
+ || !constant_multiple_p
+ (tree_to_poly_uint64 (gimple_assign_rhs3 (use_ass)),
+ tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (TREE_TYPE (vec)))),
+ this_lane))
+ return false;
+ return true;
+}
+
/* Find any vectorizable constructors and add them to the grouped_store
array. */
@@ -3828,19 +4284,159 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
!gsi_end_p (gsi); gsi_next (&gsi))
{
gassign *assign = dyn_cast<gassign *> (gsi_stmt (gsi));
- if (!assign || gimple_assign_rhs_code (assign) != CONSTRUCTOR)
+ if (!assign)
continue;
tree rhs = gimple_assign_rhs1 (assign);
- if (!VECTOR_TYPE_P (TREE_TYPE (rhs))
- || maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)),
- CONSTRUCTOR_NELTS (rhs))
- || VECTOR_TYPE_P (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
- || uniform_vector_p (rhs))
- continue;
+ if (gimple_assign_rhs_code (assign) == CONSTRUCTOR)
+ {
+ if (!VECTOR_TYPE_P (TREE_TYPE (rhs))
+ || maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)),
+ CONSTRUCTOR_NELTS (rhs))
+ || VECTOR_TYPE_P (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
+ || uniform_vector_p (rhs))
+ continue;
- stmt_vec_info stmt_info = bb_vinfo->lookup_stmt (assign);
- BB_VINFO_GROUPED_STORES (bb_vinfo).safe_push (stmt_info);
+ unsigned j;
+ tree val;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), j, val)
+ if (TREE_CODE (val) != SSA_NAME
+ || !bb_vinfo->lookup_def (val))
+ break;
+ if (j != CONSTRUCTOR_NELTS (rhs))
+ continue;
+
+ stmt_vec_info stmt_info = bb_vinfo->lookup_stmt (assign);
+ BB_VINFO_GROUPED_STORES (bb_vinfo).safe_push (stmt_info);
+ }
+ else if (gimple_assign_rhs_code (assign) == BIT_INSERT_EXPR
+ && VECTOR_TYPE_P (TREE_TYPE (rhs))
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)).is_constant ()
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)).to_constant () > 1
+ && integer_zerop (gimple_assign_rhs3 (assign))
+ && useless_type_conversion_p
+ (TREE_TYPE (TREE_TYPE (rhs)),
+ TREE_TYPE (gimple_assign_rhs2 (assign)))
+ && bb_vinfo->lookup_def (gimple_assign_rhs2 (assign)))
+ {
+ /* We start to match on insert to lane zero but since the
+ inserts need not be ordered we'd have to search both
+ the def and the use chains. */
+ tree vectype = TREE_TYPE (rhs);
+ unsigned nlanes = TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
+ auto_vec<std::pair<unsigned, tree> > lane_defs (nlanes);
+ auto_sbitmap lanes (nlanes);
+ bitmap_clear (lanes);
+ bitmap_set_bit (lanes, 0);
+ tree def = gimple_assign_lhs (assign);
+ lane_defs.quick_push
+ (std::make_pair (0, gimple_assign_rhs2 (assign)));
+ unsigned lanes_found = 1;
+ /* Start with the use chains, the last stmt will be the root. */
+ stmt_vec_info last = bb_vinfo->lookup_stmt (assign);
+ do
+ {
+ use_operand_p use_p;
+ gimple *use_stmt;
+ if (!single_imm_use (def, &use_p, &use_stmt))
+ break;
+ unsigned this_lane;
+ if (!bb_vinfo->lookup_stmt (use_stmt)
+ || !vect_slp_is_lane_insert (use_stmt, def, &this_lane)
+ || !bb_vinfo->lookup_def (gimple_assign_rhs2 (use_stmt)))
+ break;
+ if (bitmap_bit_p (lanes, this_lane))
+ break;
+ lanes_found++;
+ bitmap_set_bit (lanes, this_lane);
+ gassign *use_ass = as_a <gassign *> (use_stmt);
+ lane_defs.quick_push (std::make_pair
+ (this_lane, gimple_assign_rhs2 (use_ass)));
+ last = bb_vinfo->lookup_stmt (use_ass);
+ def = gimple_assign_lhs (use_ass);
+ }
+ while (lanes_found < nlanes);
+ if (lanes_found < nlanes)
+ {
+ /* Now search the def chain. */
+ def = gimple_assign_rhs1 (assign);
+ do
+ {
+ if (TREE_CODE (def) != SSA_NAME
+ || !has_single_use (def))
+ break;
+ gimple *def_stmt = SSA_NAME_DEF_STMT (def);
+ unsigned this_lane;
+ if (!bb_vinfo->lookup_stmt (def_stmt)
+ || !vect_slp_is_lane_insert (def_stmt,
+ NULL_TREE, &this_lane)
+ || !bb_vinfo->lookup_def (gimple_assign_rhs2 (def_stmt)))
+ break;
+ if (bitmap_bit_p (lanes, this_lane))
+ break;
+ lanes_found++;
+ bitmap_set_bit (lanes, this_lane);
+ lane_defs.quick_push (std::make_pair
+ (this_lane,
+ gimple_assign_rhs2 (def_stmt)));
+ def = gimple_assign_rhs1 (def_stmt);
+ }
+ while (lanes_found < nlanes);
+ }
+ if (lanes_found == nlanes)
+ {
+ /* Sort lane_defs after the lane index and register the root. */
+ lane_defs.qsort (vld_cmp);
+ vec<stmt_vec_info> stmts;
+ stmts.create (nlanes);
+ for (unsigned i = 0; i < nlanes; ++i)
+ stmts.quick_push (bb_vinfo->lookup_def (lane_defs[i].second));
+ bb_vinfo->roots.safe_push (slp_root (slp_inst_kind_ctor,
+ stmts, last));
+ }
+ }
+ }
+}
+
+/* Walk the grouped store chains and replace entries with their
+ pattern variant if any. */
+
+static void
+vect_fixup_store_groups_with_patterns (vec_info *vinfo)
+{
+ stmt_vec_info first_element;
+ unsigned i;
+
+ FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
+ {
+ /* We also have CTORs in this array. */
+ if (!STMT_VINFO_GROUPED_ACCESS (first_element))
+ continue;
+ if (STMT_VINFO_IN_PATTERN_P (first_element))
+ {
+ stmt_vec_info orig = first_element;
+ first_element = STMT_VINFO_RELATED_STMT (first_element);
+ DR_GROUP_FIRST_ELEMENT (first_element) = first_element;
+ DR_GROUP_SIZE (first_element) = DR_GROUP_SIZE (orig);
+ DR_GROUP_GAP (first_element) = DR_GROUP_GAP (orig);
+ DR_GROUP_NEXT_ELEMENT (first_element) = DR_GROUP_NEXT_ELEMENT (orig);
+ vinfo->grouped_stores[i] = first_element;
+ }
+ stmt_vec_info prev = first_element;
+ while (DR_GROUP_NEXT_ELEMENT (prev))
+ {
+ stmt_vec_info elt = DR_GROUP_NEXT_ELEMENT (prev);
+ if (STMT_VINFO_IN_PATTERN_P (elt))
+ {
+ stmt_vec_info orig = elt;
+ elt = STMT_VINFO_RELATED_STMT (elt);
+ DR_GROUP_NEXT_ELEMENT (prev) = elt;
+ DR_GROUP_GAP (elt) = DR_GROUP_GAP (orig);
+ DR_GROUP_NEXT_ELEMENT (elt) = DR_GROUP_NEXT_ELEMENT (orig);
+ }
+ DR_GROUP_FIRST_ELEMENT (elt) = first_element;
+ prev = elt;
+ }
}
}
@@ -3888,7 +4484,8 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
/* If there are no grouped stores and no constructors in the region
there is no need to continue with pattern recog as vect_analyze_slp
will fail anyway. */
- if (bb_vinfo->grouped_stores.is_empty ())
+ if (bb_vinfo->grouped_stores.is_empty ()
+ && bb_vinfo->roots.is_empty ())
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3902,6 +4499,9 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
vect_pattern_recog (bb_vinfo);
+ /* Update store groups from pattern processing. */
+ vect_fixup_store_groups_with_patterns (bb_vinfo);
+
/* Check the SLP opportunities in the basic block, analyze and build SLP
trees. */
if (!vect_analyze_slp (bb_vinfo, n_stmts))
@@ -3910,7 +4510,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Failed to SLP the basic block.\n");
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: failed to find SLP opportunities "
"in basic block.\n");
}
@@ -3920,6 +4520,9 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
/* Optimize permutations. */
vect_optimize_slp (bb_vinfo);
+ /* Gather the loads reachable from the SLP graph entries. */
+ vect_gather_slp_loads (bb_vinfo);
+
vect_record_base_alignments (bb_vinfo);
/* Analyze and verify the alignment of data references and the
@@ -3945,8 +4548,22 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
relevant. */
vect_mark_slp_stmts (SLP_INSTANCE_TREE (instance));
vect_mark_slp_stmts_relevant (SLP_INSTANCE_TREE (instance));
- if (SLP_INSTANCE_ROOT_STMT (instance))
- STMT_SLP_TYPE (SLP_INSTANCE_ROOT_STMT (instance)) = pure_slp;
+ if (stmt_vec_info root = SLP_INSTANCE_ROOT_STMT (instance))
+ {
+ STMT_SLP_TYPE (root) = pure_slp;
+ if (is_gimple_assign (root->stmt)
+ && gimple_assign_rhs_code (root->stmt) == BIT_INSERT_EXPR)
+ {
+ /* ??? We should probably record the whole vector of
+ root stmts so we do not have to back-track here... */
+ for (unsigned n = SLP_TREE_LANES (SLP_INSTANCE_TREE (instance));
+ n != 1; --n)
+ {
+ root = bb_vinfo->lookup_def (gimple_assign_rhs1 (root->stmt));
+ STMT_SLP_TYPE (root) = pure_slp;
+ }
+ }
+ }
i++;
}
@@ -4144,14 +4761,6 @@ vect_slp_bbs (vec<basic_block> bbs)
if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
&dataref_groups, current_group))
++current_group;
-
- if (insns > param_slp_max_insns_in_bb)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: too many instructions in "
- "region.\n");
- }
}
}
@@ -4189,20 +4798,31 @@ vect_slp_function (function *fun)
for (unsigned i = 0; i < n; i++)
{
basic_block bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]);
-
- /* Split when a basic block has multiple predecessors or when the
- edge into it exits a loop (because of implementation issues with
- respect to placement of CTORs for externals). */
bool split = false;
- edge e;
- if (!single_pred_p (bb)
- || ((e = single_pred_edge (bb)),
- loop_exit_edge_p (e->src->loop_father, e)))
- split = true;
+
/* Split when a BB is not dominated by the first block. */
+ if (!bbs.is_empty ()
+ && !dominated_by_p (CDI_DOMINATORS, bb, bbs[0]))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "splitting region at dominance boundary bb%d\n",
+ bb->index);
+ split = true;
+ }
+ /* Split when the loop determined by the first block
+ is exited. This is because we eventually insert
+ invariants at region begin. */
else if (!bbs.is_empty ()
- && !dominated_by_p (CDI_DOMINATORS, bb, bbs[0]))
- split = true;
+ && bbs[0]->loop_father != bb->loop_father
+ && !flow_loop_nested_p (bbs[0]->loop_father, bb->loop_father))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "splitting region at loop %d exit at bb%d\n",
+ bbs[0]->loop_father->num, bb->index);
+ split = true;
+ }
if (split && !bbs.is_empty ())
{
@@ -4213,11 +4833,17 @@ vect_slp_function (function *fun)
else
bbs.safe_push (bb);
- /* When we have a stmt ending this block we have to insert on
- edges when inserting after it. Avoid this for now. */
+ /* When we have a stmt ending this block and defining a
+ value we have to insert on edges when inserting after it for
+ a vector containing its definition. Avoid this for now. */
if (gimple *last = last_stmt (bb))
- if (is_ctrl_altering_stmt (last))
+ if (gimple_get_lhs (last)
+ && is_ctrl_altering_stmt (last))
{
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "splitting region at control altering "
+ "definition %G", last);
r |= vect_slp_bbs (bbs);
bbs.truncate (0);
}
@@ -4597,13 +5223,16 @@ vect_get_slp_defs (vec_info *,
/* Generate vector permute statements from a list of loads in DR_CHAIN.
If ANALYZE_ONLY is TRUE, only check that it is possible to create valid
- permute statements for the SLP node NODE. */
+ permute statements for the SLP node NODE. Store the number of vector
+ permute instructions in *N_PERMS and the number of vector load
+ instructions in *N_LOADS. */
bool
vect_transform_slp_perm_load (vec_info *vinfo,
slp_tree node, vec<tree> dr_chain,
gimple_stmt_iterator *gsi, poly_uint64 vf,
- bool analyze_only, unsigned *n_perms)
+ bool analyze_only, unsigned *n_perms,
+ unsigned int *n_loads)
{
stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
int vec_index = 0;
@@ -4655,6 +5284,7 @@ vect_transform_slp_perm_load (vec_info *vinfo,
vec_perm_builder mask;
unsigned int nelts_to_build;
unsigned int nvectors_per_build;
+ unsigned int in_nlanes;
bool repeating_p = (group_size == DR_GROUP_SIZE (stmt_info)
&& multiple_p (nunits, group_size));
if (repeating_p)
@@ -4665,6 +5295,7 @@ vect_transform_slp_perm_load (vec_info *vinfo,
mask.new_vector (nunits, group_size, 3);
nelts_to_build = mask.encoded_nelts ();
nvectors_per_build = SLP_TREE_VEC_STMTS (node).length ();
+ in_nlanes = DR_GROUP_SIZE (stmt_info) * 3;
}
else
{
@@ -4676,7 +5307,10 @@ vect_transform_slp_perm_load (vec_info *vinfo,
mask.new_vector (const_nunits, const_nunits, 1);
nelts_to_build = const_vf * group_size;
nvectors_per_build = 1;
+ in_nlanes = const_vf * DR_GROUP_SIZE (stmt_info);
}
+ auto_sbitmap used_in_lanes (in_nlanes);
+ bitmap_clear (used_in_lanes);
unsigned int count = mask.encoded_nelts ();
mask.quick_grow (count);
@@ -4688,6 +5322,7 @@ vect_transform_slp_perm_load (vec_info *vinfo,
unsigned int stmt_num = j % group_size;
unsigned int i = (iter_num * DR_GROUP_SIZE (stmt_info)
+ SLP_TREE_LOAD_PERMUTATION (node)[stmt_num]);
+ bitmap_set_bit (used_in_lanes, i);
if (repeating_p)
{
first_vec_index = 0;
@@ -4757,7 +5392,7 @@ vect_transform_slp_perm_load (vec_info *vinfo,
if (!analyze_only)
{
tree mask_vec = NULL_TREE;
-
+
if (! noop_p)
mask_vec = vect_gen_perm_mask_checked (vectype, indices);
@@ -4801,6 +5436,32 @@ vect_transform_slp_perm_load (vec_info *vinfo,
}
}
+ if (n_loads)
+ {
+ if (repeating_p)
+ *n_loads = SLP_TREE_NUMBER_OF_VEC_STMTS (node);
+ else
+ {
+ /* Enforced above when !repeating_p. */
+ unsigned int const_nunits = nunits.to_constant ();
+ *n_loads = 0;
+ bool load_seen = false;
+ for (unsigned i = 0; i < in_nlanes; ++i)
+ {
+ if (i % const_nunits == 0)
+ {
+ if (load_seen)
+ *n_loads += 1;
+ load_seen = false;
+ }
+ if (bitmap_bit_p (used_in_lanes, i))
+ load_seen = true;
+ }
+ if (load_seen)
+ *n_loads += 1;
+ }
+ }
+
return true;
}
@@ -4828,7 +5489,8 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi,
slp_tree child;
unsigned i;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- if (!types_compatible_p (SLP_TREE_VECTYPE (child), vectype))
+ if (!vect_maybe_update_slp_op_vectype (child, vectype)
+ || !types_compatible_p (SLP_TREE_VECTYPE (child), vectype))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -4929,7 +5591,7 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi,
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"permutation requires at "
- "least three vectors");
+ "least three vectors\n");
gcc_assert (!gsi);
return false;
}
@@ -5004,24 +5666,22 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi,
return true;
}
-/* Vectorize SLP instance tree in postorder. */
+/* Vectorize SLP NODE. */
static void
-vect_schedule_slp_instance (vec_info *vinfo,
- slp_tree node, slp_instance instance,
- hash_set<slp_tree> &visited)
+vect_schedule_slp_node (vec_info *vinfo,
+ slp_tree node, slp_instance instance)
{
gimple_stmt_iterator si;
int i;
slp_tree child;
- /* See if we have already vectorized the node in the graph of the
- SLP instance. */
- if ((SLP_TREE_DEF_TYPE (node) == vect_internal_def
- && SLP_TREE_VEC_STMTS (node).exists ())
- || SLP_TREE_VEC_DEFS (node).exists ())
+ /* For existing vectors there's nothing to do. */
+ if (SLP_TREE_VEC_DEFS (node).exists ())
return;
+ gcc_assert (SLP_TREE_VEC_STMTS (node).is_empty ());
+
/* Vectorize externals and constants. */
if (SLP_TREE_DEF_TYPE (node) == vect_constant_def
|| SLP_TREE_DEF_TYPE (node) == vect_external_def)
@@ -5036,17 +5696,11 @@ vect_schedule_slp_instance (vec_info *vinfo,
return;
}
- /* ??? If we'd have a way to mark backedges that would be cheaper. */
- if (visited.add (node))
- return;
-
- FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_schedule_slp_instance (vinfo, child, instance, visited);
+ stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
gcc_assert (SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0);
SLP_TREE_VEC_STMTS (node).create (SLP_TREE_NUMBER_OF_VEC_STMTS (node));
- stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"------>vectorizing SLP node starting from: %G",
@@ -5065,13 +5719,12 @@ vect_schedule_slp_instance (vec_info *vinfo,
last_stmt_info = vect_find_last_scalar_stmt_in_slp (node);
si = gsi_for_stmt (last_stmt_info->stmt);
}
- else if ((STMT_VINFO_TYPE (SLP_TREE_REPRESENTATIVE (node))
- == cycle_phi_info_type)
- || (STMT_VINFO_TYPE (SLP_TREE_REPRESENTATIVE (node))
- == induc_vec_info_type))
+ else if ((STMT_VINFO_TYPE (stmt_info) == cycle_phi_info_type
+ || STMT_VINFO_TYPE (stmt_info) == induc_vec_info_type
+ || STMT_VINFO_TYPE (stmt_info) == phi_info_type)
+ && SLP_TREE_CODE (node) != VEC_PERM_EXPR)
{
- /* For reduction and induction PHIs we do not use the
- insertion iterator. */
+ /* For PHI node vectorization we do not use the insertion iterator. */
si = gsi_none ();
}
else
@@ -5194,7 +5847,7 @@ vect_remove_slp_scalar_calls (vec_info *vinfo,
tree lhs;
stmt_vec_info stmt_info;
- if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
+ if (!node || SLP_TREE_DEF_TYPE (node) != vect_internal_def)
return;
if (visited.add (node))
@@ -5276,6 +5929,156 @@ vectorize_slp_instance_root_stmt (slp_tree node, slp_instance instance)
gsi_replace (&rgsi, rstmt, true);
}
+struct slp_scc_info
+{
+ bool on_stack;
+ int dfs;
+ int lowlink;
+};
+
+/* Schedule the SLP INSTANCE doing a DFS walk and collecting SCCs. */
+
+static void
+vect_schedule_scc (vec_info *vinfo, slp_tree node, slp_instance instance,
+ hash_map<slp_tree, slp_scc_info> &scc_info,
+ int &maxdfs, vec<slp_tree> &stack)
+{
+ bool existed_p;
+ slp_scc_info *info = &scc_info.get_or_insert (node, &existed_p);
+ gcc_assert (!existed_p);
+ info->dfs = maxdfs;
+ info->lowlink = maxdfs;
+ maxdfs++;
+
+ /* Leaf. */
+ if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
+ {
+ info->on_stack = false;
+ vect_schedule_slp_node (vinfo, node, instance);
+ return;
+ }
+
+ info->on_stack = true;
+ stack.safe_push (node);
+
+ unsigned i;
+ slp_tree child;
+ /* DFS recurse. */
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+ {
+ if (!child)
+ continue;
+ slp_scc_info *child_info = scc_info.get (child);
+ if (!child_info)
+ {
+ vect_schedule_scc (vinfo, child, instance, scc_info, maxdfs, stack);
+ /* Recursion might have re-allocated the node. */
+ info = scc_info.get (node);
+ child_info = scc_info.get (child);
+ info->lowlink = MIN (info->lowlink, child_info->lowlink);
+ }
+ else if (child_info->on_stack)
+ info->lowlink = MIN (info->lowlink, child_info->dfs);
+ }
+ if (info->lowlink != info->dfs)
+ return;
+
+ auto_vec<slp_tree, 4> phis_to_fixup;
+
+ /* Singleton. */
+ if (stack.last () == node)
+ {
+ stack.pop ();
+ info->on_stack = false;
+ vect_schedule_slp_node (vinfo, node, instance);
+ if (SLP_TREE_CODE (node) != VEC_PERM_EXPR
+ && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (node)->stmt))
+ phis_to_fixup.quick_push (node);
+ }
+ else
+ {
+ /* SCC. */
+ int last_idx = stack.length () - 1;
+ while (stack[last_idx] != node)
+ last_idx--;
+ /* We can break the cycle at PHIs who have at least one child
+ code generated. Then we could re-start the DFS walk until
+ all nodes in the SCC are covered (we might have new entries
+ for only back-reachable nodes). But it's simpler to just
+ iterate and schedule those that are ready. */
+ unsigned todo = stack.length () - last_idx;
+ do
+ {
+ for (int idx = stack.length () - 1; idx >= last_idx; --idx)
+ {
+ slp_tree entry = stack[idx];
+ if (!entry)
+ continue;
+ bool phi = (SLP_TREE_CODE (entry) != VEC_PERM_EXPR
+ && is_a <gphi *> (SLP_TREE_REPRESENTATIVE (entry)->stmt));
+ bool ready = !phi;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (entry), i, child)
+ if (!child)
+ {
+ gcc_assert (phi);
+ ready = true;
+ break;
+ }
+ else if (scc_info.get (child)->on_stack)
+ {
+ if (!phi)
+ {
+ ready = false;
+ break;
+ }
+ }
+ else
+ {
+ if (phi)
+ {
+ ready = true;
+ break;
+ }
+ }
+ if (ready)
+ {
+ vect_schedule_slp_node (vinfo, entry, instance);
+ scc_info.get (entry)->on_stack = false;
+ stack[idx] = NULL;
+ todo--;
+ if (phi)
+ phis_to_fixup.safe_push (entry);
+ }
+ }
+ }
+ while (todo != 0);
+
+ /* Pop the SCC. */
+ stack.truncate (last_idx);
+ }
+
+ /* Now fixup the backedge def of the vectorized PHIs in this SCC. */
+ slp_tree phi_node;
+ FOR_EACH_VEC_ELT (phis_to_fixup, i, phi_node)
+ {
+ gphi *phi = as_a <gphi *> (SLP_TREE_REPRESENTATIVE (phi_node)->stmt);
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
+ {
+ unsigned dest_idx = e->dest_idx;
+ child = SLP_TREE_CHILDREN (phi_node)[dest_idx];
+ if (!child || SLP_TREE_DEF_TYPE (child) != vect_internal_def)
+ continue;
+ /* Simply fill all args. */
+ for (unsigned i = 0; i < SLP_TREE_VEC_STMTS (phi_node).length (); ++i)
+ add_phi_arg (as_a <gphi *> (SLP_TREE_VEC_STMTS (phi_node)[i]),
+ vect_get_slp_vect_def (child, i),
+ e, gimple_phi_arg_location (phi, dest_idx));
+ }
+ }
+}
+
/* Generate vector code for SLP_INSTANCES in the loop/basic block. */
void
@@ -5284,7 +6087,8 @@ vect_schedule_slp (vec_info *vinfo, vec<slp_instance> slp_instances)
slp_instance instance;
unsigned int i;
- hash_set<slp_tree> visited;
+ hash_map<slp_tree, slp_scc_info> scc_info;
+ int maxdfs = 0;
FOR_EACH_VEC_ELT (slp_instances, i, instance)
{
slp_tree node = SLP_INSTANCE_TREE (instance);
@@ -5298,8 +6102,11 @@ vect_schedule_slp (vec_info *vinfo, vec<slp_instance> slp_instances)
vect_print_slp_graph (MSG_NOTE, vect_location,
SLP_INSTANCE_TREE (instance));
}
- /* Schedule the tree of INSTANCE. */
- vect_schedule_slp_instance (vinfo, node, instance, visited);
+ /* Schedule the tree of INSTANCE, scheduling SCCs in a way to
+ have a PHI be the node breaking the cycle. */
+ auto_vec<slp_tree> stack;
+ if (!scc_info.get (node))
+ vect_schedule_scc (vinfo, node, instance, scc_info, maxdfs, stack);
if (SLP_INSTANCE_ROOT_STMT (instance))
vectorize_slp_instance_root_stmt (node, instance);
@@ -5315,25 +6122,6 @@ vect_schedule_slp (vec_info *vinfo, vec<slp_instance> slp_instances)
stmt_vec_info store_info;
unsigned int j;
- /* For reductions set the latch values of the vectorized PHIs. */
- if (instance->reduc_phis
- && STMT_VINFO_REDUC_TYPE (SLP_TREE_REPRESENTATIVE
- (instance->reduc_phis)) != FOLD_LEFT_REDUCTION
- && STMT_VINFO_REDUC_TYPE (SLP_TREE_REPRESENTATIVE
- (instance->reduc_phis)) != EXTRACT_LAST_REDUCTION)
- {
- slp_tree slp_node = root;
- slp_tree phi_node = instance->reduc_phis;
- gphi *phi = as_a <gphi *> (SLP_TREE_SCALAR_STMTS (phi_node)[0]->stmt);
- edge e = loop_latch_edge (gimple_bb (phi)->loop_father);
- gcc_assert (SLP_TREE_VEC_STMTS (phi_node).length ()
- == SLP_TREE_VEC_STMTS (slp_node).length ());
- for (unsigned j = 0; j < SLP_TREE_VEC_STMTS (phi_node).length (); ++j)
- add_phi_arg (as_a <gphi *> (SLP_TREE_VEC_STMTS (phi_node)[j]),
- vect_get_slp_vect_def (slp_node, j),
- e, gimple_phi_arg_location (phi, e->dest_idx));
- }
-
/* Remove scalar call stmts. Do not do this for basic-block
vectorization as not all uses may be vectorized.
??? Why should this be necessary? DCE should be able to
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 3575f25..11737a38 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1098,39 +1098,15 @@ vect_model_load_cost (vec_info *vinfo,
the first group element not by the first scalar stmt DR. */
stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
/* Record the cost for the permutation. */
- unsigned n_perms;
- unsigned assumed_nunits
- = vect_nunits_for_cost (STMT_VINFO_VECTYPE (first_stmt_info));
+ unsigned n_perms, n_loads;
vect_transform_slp_perm_load (vinfo, slp_node, vNULL, NULL,
- vf, true, &n_perms);
+ vf, true, &n_perms, &n_loads);
inside_cost += record_stmt_cost (cost_vec, n_perms, vec_perm,
first_stmt_info, 0, vect_body);
+
/* And adjust the number of loads performed. This handles
redundancies as well as loads that are later dead. */
- auto_sbitmap perm (DR_GROUP_SIZE (first_stmt_info));
- bitmap_clear (perm);
- for (unsigned i = 0;
- i < SLP_TREE_LOAD_PERMUTATION (slp_node).length (); ++i)
- bitmap_set_bit (perm, SLP_TREE_LOAD_PERMUTATION (slp_node)[i]);
- ncopies = 0;
- bool load_seen = false;
- for (unsigned i = 0; i < DR_GROUP_SIZE (first_stmt_info); ++i)
- {
- if (i % assumed_nunits == 0)
- {
- if (load_seen)
- ncopies++;
- load_seen = false;
- }
- if (bitmap_bit_p (perm, i))
- load_seen = true;
- }
- if (load_seen)
- ncopies++;
- gcc_assert (ncopies
- <= (DR_GROUP_SIZE (first_stmt_info)
- - DR_GROUP_GAP (first_stmt_info)
- + assumed_nunits - 1) / assumed_nunits);
+ ncopies = n_loads;
}
/* Grouped loads read all elements in the group at once,
@@ -3451,7 +3427,8 @@ vectorizable_call (vec_info *vinfo,
{
vec_defs.quick_push (vNULL);
vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
- op, &vec_defs[i]);
+ op, &vec_defs[i],
+ vectypes[i]);
}
orig_vargs[i] = vargs[i] = vec_defs[i][j];
}
@@ -3731,7 +3708,7 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
tree op, type;
tree vec_oprnd0 = NULL_TREE;
tree vectype;
- unsigned int nunits;
+ poly_uint64 nunits;
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
@@ -3883,8 +3860,8 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
arginfo.quick_push (thisarginfo);
}
- unsigned HOST_WIDE_INT vf;
- if (!LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&vf))
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ if (!vf.is_constant ())
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3902,12 +3879,12 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
n = n->simdclone->next_clone)
{
unsigned int this_badness = 0;
- if (n->simdclone->simdlen > vf
+ unsigned int num_calls;
+ if (!constant_multiple_p (vf, n->simdclone->simdlen, &num_calls)
|| n->simdclone->nargs != nargs)
continue;
- if (n->simdclone->simdlen < vf)
- this_badness += (exact_log2 (vf)
- - exact_log2 (n->simdclone->simdlen)) * 1024;
+ if (num_calls != 1)
+ this_badness += exact_log2 (num_calls) * 1024;
if (n->simdclone->inbranch)
this_badness += 2048;
int target_badness = targetm.simd_clone.usable (n);
@@ -3988,19 +3965,19 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
arginfo[i].vectype = get_vectype_for_scalar_type (vinfo, arg_type,
slp_node);
if (arginfo[i].vectype == NULL
- || (simd_clone_subparts (arginfo[i].vectype)
- > bestn->simdclone->simdlen))
+ || !constant_multiple_p (bestn->simdclone->simdlen,
+ simd_clone_subparts (arginfo[i].vectype)))
return false;
}
fndecl = bestn->decl;
nunits = bestn->simdclone->simdlen;
- ncopies = vf / nunits;
+ ncopies = vector_unroll_factor (vf, nunits);
/* If the function isn't const, only allow it in simd loops where user
has asserted that at least nunits consecutive iterations can be
performed using SIMD instructions. */
- if ((loop == NULL || (unsigned) loop->safelen < nunits)
+ if ((loop == NULL || maybe_lt ((unsigned) loop->safelen, nunits))
&& gimple_vuse (stmt))
return false;
@@ -4078,7 +4055,8 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
{
case SIMD_CLONE_ARG_TYPE_VECTOR:
atype = bestn->simdclone->args[i].vector_type;
- o = nunits / simd_clone_subparts (atype);
+ o = vector_unroll_factor (nunits,
+ simd_clone_subparts (atype));
for (m = j * o; m < (j + 1) * o; m++)
{
if (simd_clone_subparts (atype)
@@ -4203,7 +4181,7 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
? POINTER_PLUS_EXPR : PLUS_EXPR;
tree type = POINTER_TYPE_P (TREE_TYPE (op))
? sizetype : TREE_TYPE (op);
- widest_int cst
+ poly_widest_int cst
= wi::mul (bestn->simdclone->args[i].linear_step,
ncopies * nunits);
tree tcst = wide_int_to_tree (type, cst);
@@ -4224,7 +4202,7 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
? POINTER_PLUS_EXPR : PLUS_EXPR;
tree type = POINTER_TYPE_P (TREE_TYPE (op))
? sizetype : TREE_TYPE (op);
- widest_int cst
+ poly_widest_int cst
= wi::mul (bestn->simdclone->args[i].linear_step,
j * nunits);
tree tcst = wide_int_to_tree (type, cst);
@@ -4250,7 +4228,8 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
gcall *new_call = gimple_build_call_vec (fndecl, vargs);
if (vec_dest)
{
- gcc_assert (ratype || simd_clone_subparts (rtype) == nunits);
+ gcc_assert (ratype
+ || known_eq (simd_clone_subparts (rtype), nunits));
if (ratype)
new_temp = create_tmp_var (ratype);
else if (useless_type_conversion_p (vectype, rtype))
@@ -4264,12 +4243,13 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
if (vec_dest)
{
- if (simd_clone_subparts (vectype) < nunits)
+ if (!multiple_p (simd_clone_subparts (vectype), nunits))
{
unsigned int k, l;
poly_uint64 prec = GET_MODE_BITSIZE (TYPE_MODE (vectype));
poly_uint64 bytes = GET_MODE_SIZE (TYPE_MODE (vectype));
- k = nunits / simd_clone_subparts (vectype);
+ k = vector_unroll_factor (nunits,
+ simd_clone_subparts (vectype));
gcc_assert ((k & (k - 1)) == 0);
for (l = 0; l < k; l++)
{
@@ -4295,7 +4275,7 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
vect_clobber_variable (vinfo, stmt_info, gsi, new_temp);
continue;
}
- else if (simd_clone_subparts (vectype) > nunits)
+ else if (!multiple_p (nunits, simd_clone_subparts (vectype)))
{
unsigned int k = (simd_clone_subparts (vectype)
/ simd_clone_subparts (rtype));
@@ -4304,7 +4284,9 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
vec_alloc (ret_ctor_elts, k);
if (ratype)
{
- unsigned int m, o = nunits / simd_clone_subparts (rtype);
+ unsigned int m, o;
+ o = vector_unroll_factor (nunits,
+ simd_clone_subparts (rtype));
for (m = 0; m < o; m++)
{
tree tem = build4 (ARRAY_REF, rtype, new_temp,
@@ -4589,6 +4571,8 @@ vectorizable_conversion (vec_info *vinfo,
if (!CONVERT_EXPR_CODE_P (code)
&& code != FIX_TRUNC_EXPR
&& code != FLOAT_EXPR
+ && code != WIDEN_PLUS_EXPR
+ && code != WIDEN_MINUS_EXPR
&& code != WIDEN_MULT_EXPR
&& code != WIDEN_LSHIFT_EXPR)
return false;
@@ -4634,7 +4618,8 @@ vectorizable_conversion (vec_info *vinfo,
if (op_type == binary_op)
{
- gcc_assert (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR);
+ gcc_assert (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR
+ || code == WIDEN_PLUS_EXPR || code == WIDEN_MINUS_EXPR);
op1 = gimple_assign_rhs2 (stmt);
tree vectype1_in;
@@ -4950,8 +4935,9 @@ vectorizable_conversion (vec_info *vinfo,
&vec_oprnds1);
if (code == WIDEN_LSHIFT_EXPR)
{
- vec_oprnds1.create (ncopies * ninputs);
- for (i = 0; i < ncopies * ninputs; ++i)
+ int oprnds_size = vec_oprnds0.length ();
+ vec_oprnds1.create (oprnds_size);
+ for (i = 0; i < oprnds_size; ++i)
vec_oprnds1.quick_push (op1);
}
/* Arguments are ready. Create the new vector stmts. */
@@ -5137,6 +5123,17 @@ vectorizable_assignment (vec_info *vinfo,
GET_MODE_SIZE (TYPE_MODE (vectype_in)))))
return false;
+ if (VECTOR_BOOLEAN_TYPE_P (vectype)
+ && !VECTOR_BOOLEAN_TYPE_P (vectype_in))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "can't convert between boolean and non "
+ "boolean vectors %T\n", TREE_TYPE (op));
+
+ return false;
+ }
+
/* We do not handle bit-precision changes. */
if ((CONVERT_EXPR_CODE_P (code)
|| code == VIEW_CONVERT_EXPR)
@@ -5146,12 +5143,7 @@ vectorizable_assignment (vec_info *vinfo,
/* But a conversion that does not change the bit-pattern is ok. */
&& !((TYPE_PRECISION (TREE_TYPE (scalar_dest))
> TYPE_PRECISION (TREE_TYPE (op)))
- && TYPE_UNSIGNED (TREE_TYPE (op)))
- /* Conversion between boolean types of different sizes is
- a simple assignment in case their vectypes are same
- boolean vectors. */
- && (!VECTOR_BOOLEAN_TYPE_P (vectype)
- || !VECTOR_BOOLEAN_TYPE_P (vectype_in)))
+ && TYPE_UNSIGNED (TREE_TYPE (op))))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -10745,7 +10737,8 @@ vect_analyze_stmt (vec_info *vinfo,
|| vectorizable_condition (vinfo, stmt_info,
NULL, NULL, node, cost_vec)
|| vectorizable_comparison (vinfo, stmt_info, NULL, NULL, node,
- cost_vec));
+ cost_vec)
+ || vectorizable_phi (vinfo, stmt_info, NULL, node, cost_vec));
}
if (!ok)
@@ -10885,6 +10878,11 @@ vect_transform_stmt (vec_info *vinfo,
gcc_assert (done);
break;
+ case phi_info_type:
+ done = vectorizable_phi (vinfo, stmt_info, &vec_stmt, slp_node, NULL);
+ gcc_assert (done);
+ break;
+
default:
if (!STMT_VINFO_LIVE_P (stmt_info))
{
@@ -11547,6 +11545,16 @@ supportable_widening_operation (vec_info *vinfo,
c2 = VEC_WIDEN_LSHIFT_HI_EXPR;
break;
+ case WIDEN_PLUS_EXPR:
+ c1 = VEC_WIDEN_PLUS_LO_EXPR;
+ c2 = VEC_WIDEN_PLUS_HI_EXPR;
+ break;
+
+ case WIDEN_MINUS_EXPR:
+ c1 = VEC_WIDEN_MINUS_LO_EXPR;
+ c2 = VEC_WIDEN_MINUS_HI_EXPR;
+ break;
+
CASE_CONVERT:
c1 = VEC_UNPACK_LO_EXPR;
c2 = VEC_UNPACK_HI_EXPR;
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 778177a..3992849 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -525,6 +525,19 @@ vec_info::add_stmt (gimple *stmt)
return res;
}
+/* Record that STMT belongs to the vectorizable region. Create a new
+ stmt_vec_info and mark VECINFO as being related and return the new
+ stmt_vec_info. */
+
+stmt_vec_info
+vec_info::add_pattern_stmt (gimple *stmt, stmt_vec_info stmt_info)
+{
+ stmt_vec_info res = new_stmt_vec_info (stmt);
+ set_vinfo_for_stmt (stmt, res, false);
+ STMT_VINFO_RELATED_STMT (res) = stmt_info;
+ return res;
+}
+
/* If STMT has an associated stmt_vec_info, return that vec_info, otherwise
return null. It is safe to call this function on any statement, even if
it might not be part of the vectorizable region. */
@@ -684,7 +697,8 @@ vec_info::new_stmt_vec_info (gimple *stmt)
STMT_VINFO_SLP_VECT_ONLY (res) = false;
STMT_VINFO_VEC_STMTS (res) = vNULL;
- if (gimple_code (stmt) == GIMPLE_PHI
+ if (is_a <loop_vec_info> (this)
+ && gimple_code (stmt) == GIMPLE_PHI
&& is_loop_header_bb_p (gimple_bb (stmt)))
STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
else
@@ -701,12 +715,12 @@ vec_info::new_stmt_vec_info (gimple *stmt)
/* Associate STMT with INFO. */
void
-vec_info::set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info)
+vec_info::set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info, bool check_ro)
{
unsigned int uid = gimple_uid (stmt);
if (uid == 0)
{
- gcc_assert (!stmt_vec_info_ro);
+ gcc_assert (!check_ro || !stmt_vec_info_ro);
gcc_checking_assert (info);
uid = stmt_vec_infos.length () + 1;
gimple_set_uid (stmt, uid);
@@ -1170,6 +1184,8 @@ vectorize_loops (void)
if (vect_loops_num <= 1)
return 0;
+ vect_slp_init ();
+
if (cfun->has_simduid_loops)
note_simd_array_uses (&simd_array_to_simduid_htab);
@@ -1292,6 +1308,7 @@ vectorize_loops (void)
shrink_simd_arrays (simd_array_to_simduid_htab, simduid_to_vf_htab);
delete simduid_to_vf_htab;
cfun->has_simduid_loops = false;
+ vect_slp_fini ();
if (num_vectorized_loops > 0)
{
@@ -1427,8 +1444,12 @@ pass_slp_vectorize::execute (function *fun)
}
}
+ vect_slp_init ();
+
vect_slp_function (fun);
+ vect_slp_fini ();
+
if (!in_loop_pipeline)
{
scev_finalize ();
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index b56073c..66e6b50 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -26,6 +26,7 @@ typedef class _stmt_vec_info *stmt_vec_info;
#include "tree-data-ref.h"
#include "tree-hash-traits.h"
#include "target.h"
+#include "internal-fn.h"
/* Used for naming of new temporaries. */
@@ -114,6 +115,8 @@ typedef hash_map<tree_operand_hash,
SLP
************************************************************************/
typedef struct _slp_tree *slp_tree;
+typedef vec<std::pair<unsigned, unsigned> > lane_permutation_t;
+typedef vec<unsigned> load_permutation_t;
/* A computation tree of an SLP instance. Each node corresponds to a group of
stmts to be packed in a SIMD stmt. */
@@ -134,11 +137,11 @@ struct _slp_tree {
/* Load permutation relative to the stores, NULL if there is no
permutation. */
- vec<unsigned> load_permutation;
+ load_permutation_t load_permutation;
/* Lane permutation of the operands scalar lanes encoded as pairs
of { operand number, lane number }. The number of elements
denotes the number of output lanes. */
- vec<std::pair<unsigned, unsigned> > lane_permutation;
+ lane_permutation_t lane_permutation;
tree vectype;
/* Vectorized stmt/s. */
@@ -163,8 +166,27 @@ struct _slp_tree {
enum tree_code code;
int vertex;
+
+ /* Allocate from slp_tree_pool. */
+ static void *operator new (size_t);
+
+ /* Return memory to slp_tree_pool. */
+ static void operator delete (void *, size_t);
+
+ /* Linked list of nodes to release when we free the slp_tree_pool. */
+ slp_tree next_node;
+ slp_tree prev_node;
};
+/* The enum describes the type of operations that an SLP instance
+ can perform. */
+
+enum slp_instance_kind {
+ slp_inst_kind_store,
+ slp_inst_kind_reduc_group,
+ slp_inst_kind_reduc_chain,
+ slp_inst_kind_ctor
+};
/* SLP instance is a sequence of stmts in a loop that can be packed into
SIMD stmts. */
@@ -193,6 +215,9 @@ public:
entries into the same subgraph, including itself. */
vec<_slp_instance *> subgraph_entries;
+ /* The type of operation the SLP instance is performing. */
+ slp_instance_kind kind;
+
dump_user_location_t location () const;
} *slp_instance;
@@ -202,6 +227,7 @@ public:
#define SLP_INSTANCE_UNROLLING_FACTOR(S) (S)->unrolling_factor
#define SLP_INSTANCE_LOADS(S) (S)->loads
#define SLP_INSTANCE_ROOT_STMT(S) (S)->root_stmt
+#define SLP_INSTANCE_KIND(S) (S)->kind
#define SLP_TREE_CHILDREN(S) (S)->children
#define SLP_TREE_SCALAR_STMTS(S) (S)->stmts
@@ -339,6 +365,7 @@ public:
~vec_info ();
stmt_vec_info add_stmt (gimple *);
+ stmt_vec_info add_pattern_stmt (gimple *, stmt_vec_info);
stmt_vec_info lookup_stmt (gimple *);
stmt_vec_info lookup_def (tree);
stmt_vec_info lookup_single_use (tree);
@@ -384,7 +411,7 @@ public:
private:
stmt_vec_info new_stmt_vec_info (gimple *stmt);
- void set_vinfo_for_stmt (gimple *, stmt_vec_info);
+ void set_vinfo_for_stmt (gimple *, stmt_vec_info, bool = true);
void free_stmt_vec_infos ();
void free_stmt_vec_info (stmt_vec_info);
};
@@ -826,6 +853,16 @@ loop_vec_info_for_loop (class loop *loop)
return (loop_vec_info) loop->aux;
}
+struct slp_root
+{
+ slp_root (slp_instance_kind kind_, vec<stmt_vec_info> stmts_,
+ stmt_vec_info root_)
+ : kind(kind_), stmts(stmts_), root(root_) {}
+ slp_instance_kind kind;
+ vec<stmt_vec_info> stmts;
+ stmt_vec_info root;
+};
+
typedef class _bb_vec_info : public vec_info
{
public:
@@ -837,6 +874,8 @@ public:
entry edge to cover bbs[0] PHI nodes and have a region entry
insert location. */
vec<basic_block> bbs;
+
+ vec<slp_root> roots;
} *bb_vec_info;
#define BB_VINFO_BB(B) (B)->bb
@@ -872,6 +911,7 @@ enum stmt_vec_info_type {
type_conversion_vec_info_type,
cycle_phi_info_type,
lc_phi_info_type,
+ phi_info_type,
loop_exit_ctrl_vec_info_type
};
@@ -1930,6 +1970,8 @@ extern bool vect_transform_cycle_phi (loop_vec_info, stmt_vec_info,
slp_tree, slp_instance);
extern bool vectorizable_lc_phi (loop_vec_info, stmt_vec_info,
gimple **, slp_tree);
+extern bool vectorizable_phi (vec_info *, stmt_vec_info, gimple **, slp_tree,
+ stmt_vector_for_cost *);
extern bool vect_worthwhile_without_simd_p (vec_info *, tree_code);
extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
stmt_vector_for_cost *,
@@ -1938,16 +1980,20 @@ extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
extern tree cse_and_gimplify_to_preheader (loop_vec_info, tree);
/* In tree-vect-slp.c. */
+extern void vect_slp_init (void);
+extern void vect_slp_fini (void);
extern void vect_free_slp_instance (slp_instance);
extern bool vect_transform_slp_perm_load (vec_info *, slp_tree, vec<tree>,
gimple_stmt_iterator *, poly_uint64,
- bool, unsigned *);
+ bool, unsigned *,
+ unsigned * = nullptr);
extern bool vect_slp_analyze_operations (vec_info *);
extern void vect_schedule_slp (vec_info *, vec<slp_instance>);
extern opt_result vect_analyze_slp (vec_info *, unsigned);
extern bool vect_make_slp_decision (loop_vec_info);
extern void vect_detect_hybrid_slp (loop_vec_info);
extern void vect_optimize_slp (vec_info *);
+extern void vect_gather_slp_loads (vec_info *);
extern void vect_get_slp_defs (slp_tree, vec<tree> *);
extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
unsigned n = -1U);
@@ -1963,8 +2009,13 @@ extern void duplicate_and_interleave (vec_info *, gimple_seq *, tree,
vec<tree>, unsigned int, vec<tree> &);
extern int vect_get_place_in_interleaving_chain (stmt_vec_info, stmt_vec_info);
extern bool vect_update_shared_vectype (stmt_vec_info, tree);
+extern slp_tree vect_create_new_slp_node (unsigned, tree_code);
+extern void vect_free_slp_tree (slp_tree);
/* In tree-vect-patterns.c. */
+extern void
+vect_mark_pattern_stmts (vec_info *, stmt_vec_info, gimple *, tree);
+
/* Pattern recognition functions.
Additional pattern recognition functions can (and will) be added
in the future. */
@@ -1976,4 +2027,84 @@ void vect_free_loop_info_assumptions (class loop *);
gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+/* SLP Pattern matcher types, tree-vect-slp-patterns.c. */
+
+/* Forward declaration of possible two operands operation that can be matched
+ by the complex numbers pattern matchers. */
+enum _complex_operation : unsigned;
+
+/* All possible load permute values that could result from the partial data-flow
+ analysis. */
+typedef enum _complex_perm_kinds {
+ PERM_UNKNOWN,
+ PERM_EVENODD,
+ PERM_ODDEVEN,
+ PERM_ODDODD,
+ PERM_EVENEVEN,
+ /* Can be combined with any other PERM values. */
+ PERM_TOP
+} complex_perm_kinds_t;
+
+/* A pair with a load permute and a corresponding complex_perm_kind which gives
+ information about the load it represents. */
+typedef std::pair<complex_perm_kinds_t, load_permutation_t>
+ complex_load_perm_t;
+
+/* Cache from nodes to the load permutation they represent. */
+typedef hash_map <slp_tree, complex_load_perm_t>
+ slp_tree_to_load_perm_map_t;
+
+/* Vector pattern matcher base class. All SLP pattern matchers must inherit
+ from this type. */
+
+class vect_pattern
+{
+ protected:
+ /* The number of arguments that the IFN requires. */
+ unsigned m_num_args;
+
+ /* The internal function that will be used when a pattern is created. */
+ internal_fn m_ifn;
+
+ /* The current node being inspected. */
+ slp_tree *m_node;
+
+ /* The list of operands to be the children for the node produced when the
+ internal function is created. */
+ vec<slp_tree> m_ops;
+
+ /* Default constructor where NODE is the root of the tree to inspect. */
+ vect_pattern (slp_tree *node, vec<slp_tree> *m_ops, internal_fn ifn)
+ {
+ this->m_ifn = ifn;
+ this->m_node = node;
+ this->m_ops.create (0);
+ this->m_ops.safe_splice (*m_ops);
+ }
+
+ public:
+
+ /* Create a new instance of the pattern matcher class of the given type. */
+ static vect_pattern* recognize (slp_tree_to_load_perm_map_t *, slp_tree *);
+
+ /* Build the pattern from the data collected so far. */
+ virtual void build (vec_info *) = 0;
+
+ /* Default destructor. */
+ virtual ~vect_pattern ()
+ {
+ this->m_ops.release ();
+ }
+};
+
+/* Function pointer to create a new pattern matcher from a generic type. */
+typedef vect_pattern* (*vect_pattern_decl_t) (slp_tree_to_load_perm_map_t *,
+ slp_tree *);
+
+/* List of supported pattern matchers. */
+extern vect_pattern_decl_t slp_patterns[];
+
+/* Number of supported pattern matchers. */
+extern size_t num__slp_patterns;
+
#endif /* GCC_TREE_VECTORIZER_H */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index e00c034..d661866 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -161,153 +161,6 @@ live_names::live_on_block_p (tree name, basic_block bb)
&& bitmap_bit_p (live[bb->index], SSA_NAME_VERSION (name)));
}
-
-/* Location information for ASSERT_EXPRs. Each instance of this
- structure describes an ASSERT_EXPR for an SSA name. Since a single
- SSA name may have more than one assertion associated with it, these
- locations are kept in a linked list attached to the corresponding
- SSA name. */
-struct assert_locus
-{
- /* Basic block where the assertion would be inserted. */
- basic_block bb;
-
- /* Some assertions need to be inserted on an edge (e.g., assertions
- generated by COND_EXPRs). In those cases, BB will be NULL. */
- edge e;
-
- /* Pointer to the statement that generated this assertion. */
- gimple_stmt_iterator si;
-
- /* Predicate code for the ASSERT_EXPR. Must be COMPARISON_CLASS_P. */
- enum tree_code comp_code;
-
- /* Value being compared against. */
- tree val;
-
- /* Expression to compare. */
- tree expr;
-
- /* Next node in the linked list. */
- assert_locus *next;
-};
-
-class vrp_insert
-{
-public:
- vrp_insert (struct function *fn) : fun (fn) { }
-
- /* Traverse the flowgraph looking for conditional jumps to insert range
- expressions. These range expressions are meant to provide information
- to optimizations that need to reason in terms of value ranges. They
- will not be expanded into RTL. See method implementation comment
- for example. */
- void insert_range_assertions ();
-
- /* Convert range assertion expressions into the implied copies and
- copy propagate away the copies. */
- void remove_range_assertions ();
-
- /* Dump all the registered assertions for all the names to FILE. */
- void dump (FILE *);
-
- /* Dump all the registered assertions for NAME to FILE. */
- void dump (FILE *file, tree name);
-
- /* Dump all the registered assertions for NAME to stderr. */
- void debug (tree name)
- {
- dump (stderr, name);
- }
-
- /* Dump all the registered assertions for all the names to stderr. */
- void debug ()
- {
- dump (stderr);
- }
-
-private:
- /* Set of SSA names found live during the RPO traversal of the function
- for still active basic-blocks. */
- live_names live;
-
- /* Function to work on. */
- struct function *fun;
-
- /* If bit I is present, it means that SSA name N_i has a list of
- assertions that should be inserted in the IL. */
- bitmap need_assert_for;
-
- /* Array of locations lists where to insert assertions. ASSERTS_FOR[I]
- holds a list of ASSERT_LOCUS_T nodes that describe where
- ASSERT_EXPRs for SSA name N_I should be inserted. */
- assert_locus **asserts_for;
-
- /* Finish found ASSERTS for E and register them at GSI. */
- void finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
- vec<assert_info> &asserts);
-
- /* Determine whether the outgoing edges of BB should receive an
- ASSERT_EXPR for each of the operands of BB's LAST statement. The
- last statement of BB must be a SWITCH_EXPR.
-
- If any of the sub-graphs rooted at BB have an interesting use of
- the predicate operands, an assert location node is added to the
- list of assertions for the corresponding operands. */
- void find_switch_asserts (basic_block bb, gswitch *last);
-
- /* Do an RPO walk over the function computing SSA name liveness
- on-the-fly and deciding on assert expressions to insert. */
- void find_assert_locations ();
-
- /* Traverse all the statements in block BB looking for statements that
- may generate useful assertions for the SSA names in their operand.
- See method implementation comentary for more information. */
- void find_assert_locations_in_bb (basic_block bb);
-
- /* Determine whether the outgoing edges of BB should receive an
- ASSERT_EXPR for each of the operands of BB's LAST statement.
- The last statement of BB must be a COND_EXPR.
-
- If any of the sub-graphs rooted at BB have an interesting use of
- the predicate operands, an assert location node is added to the
- list of assertions for the corresponding operands. */
- void find_conditional_asserts (basic_block bb, gcond *last);
-
- /* Process all the insertions registered for every name N_i registered
- in NEED_ASSERT_FOR. The list of assertions to be inserted are
- found in ASSERTS_FOR[i]. */
- void process_assert_insertions ();
-
- /* If NAME doesn't have an ASSERT_EXPR registered for asserting
- 'EXPR COMP_CODE VAL' at a location that dominates block BB or
- E->DEST, then register this location as a possible insertion point
- for ASSERT_EXPR <NAME, EXPR COMP_CODE VAL>.
-
- BB, E and SI provide the exact insertion point for the new
- ASSERT_EXPR. If BB is NULL, then the ASSERT_EXPR is to be inserted
- on edge E. Otherwise, if E is NULL, the ASSERT_EXPR is inserted on
- BB. If SI points to a COND_EXPR or a SWITCH_EXPR statement, then E
- must not be NULL. */
- void register_new_assert_for (tree name, tree expr,
- enum tree_code comp_code,
- tree val, basic_block bb,
- edge e, gimple_stmt_iterator si);
-
- /* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
- create a new SSA name N and return the assertion assignment
- 'N = ASSERT_EXPR <V, V OP W>'. */
- gimple *build_assert_expr_for (tree cond, tree v);
-
- /* Create an ASSERT_EXPR for NAME and insert it in the location
- indicated by LOC. Return true if we made any edge insertions. */
- bool process_assert_insertions_for (tree name, assert_locus *loc);
-
- /* Qsort callback for sorting assert locations. */
- template <bool stable> static int compare_assert_loc (const void *,
- const void *);
-};
-
/* Return true if the SSA name NAME is live on the edge E. */
bool
@@ -1266,48 +1119,6 @@ range_fold_unary_expr (value_range *vr,
op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
}
-/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
- create a new SSA name N and return the assertion assignment
- 'N = ASSERT_EXPR <V, V OP W>'. */
-
-gimple *
-vrp_insert::build_assert_expr_for (tree cond, tree v)
-{
- tree a;
- gassign *assertion;
-
- gcc_assert (TREE_CODE (v) == SSA_NAME
- && COMPARISON_CLASS_P (cond));
-
- a = build2 (ASSERT_EXPR, TREE_TYPE (v), v, cond);
- assertion = gimple_build_assign (NULL_TREE, a);
-
- /* The new ASSERT_EXPR, creates a new SSA name that replaces the
- operand of the ASSERT_EXPR. Create it so the new name and the old one
- are registered in the replacement table so that we can fix the SSA web
- after adding all the ASSERT_EXPRs. */
- tree new_def = create_new_def_for (v, assertion, NULL);
- /* Make sure we preserve abnormalness throughout an ASSERT_EXPR chain
- given we have to be able to fully propagate those out to re-create
- valid SSA when removing the asserts. */
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (v))
- SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_def) = 1;
-
- return assertion;
-}
-
-
-/* Return false if EXPR is a predicate expression involving floating
- point values. */
-
-static inline bool
-fp_predicate (gimple *stmt)
-{
- GIMPLE_CHECK (stmt, GIMPLE_COND);
-
- return FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)));
-}
-
/* If the range of values taken by OP can be inferred after STMT executes,
return the comparison code (COMP_CODE_P) and value (VAL_P) that
describes the inferred range. Return true if a range could be
@@ -1350,54 +1161,6 @@ infer_value_range (gimple *stmt, tree op, tree_code *comp_code_p, tree *val_p)
return false;
}
-/* Dump all the registered assertions for NAME to FILE. */
-
-void
-vrp_insert::dump (FILE *file, tree name)
-{
- assert_locus *loc;
-
- fprintf (file, "Assertions to be inserted for ");
- print_generic_expr (file, name);
- fprintf (file, "\n");
-
- loc = asserts_for[SSA_NAME_VERSION (name)];
- while (loc)
- {
- fprintf (file, "\t");
- print_gimple_stmt (file, gsi_stmt (loc->si), 0);
- fprintf (file, "\n\tBB #%d", loc->bb->index);
- if (loc->e)
- {
- fprintf (file, "\n\tEDGE %d->%d", loc->e->src->index,
- loc->e->dest->index);
- dump_edge_info (file, loc->e, dump_flags, 0);
- }
- fprintf (file, "\n\tPREDICATE: ");
- print_generic_expr (file, loc->expr);
- fprintf (file, " %s ", get_tree_code_name (loc->comp_code));
- print_generic_expr (file, loc->val);
- fprintf (file, "\n\n");
- loc = loc->next;
- }
-
- fprintf (file, "\n");
-}
-
-/* Dump all the registered assertions for all the names to FILE. */
-
-void
-vrp_insert::dump (FILE *file)
-{
- unsigned i;
- bitmap_iterator bi;
-
- fprintf (file, "\nASSERT_EXPRs to be inserted\n\n");
- EXECUTE_IF_SET_IN_BITMAP (need_assert_for, 0, i, bi)
- dump (file, ssa_name (i));
- fprintf (file, "\n");
-}
-
/* Dump assert_info structure. */
void
@@ -1457,117 +1220,6 @@ add_assert_info (vec<assert_info> &asserts,
name, expr, op_symbol_code (comp_code), val);
}
-/* If NAME doesn't have an ASSERT_EXPR registered for asserting
- 'EXPR COMP_CODE VAL' at a location that dominates block BB or
- E->DEST, then register this location as a possible insertion point
- for ASSERT_EXPR <NAME, EXPR COMP_CODE VAL>.
-
- BB, E and SI provide the exact insertion point for the new
- ASSERT_EXPR. If BB is NULL, then the ASSERT_EXPR is to be inserted
- on edge E. Otherwise, if E is NULL, the ASSERT_EXPR is inserted on
- BB. If SI points to a COND_EXPR or a SWITCH_EXPR statement, then E
- must not be NULL. */
-
-void
-vrp_insert::register_new_assert_for (tree name, tree expr,
- enum tree_code comp_code,
- tree val,
- basic_block bb,
- edge e,
- gimple_stmt_iterator si)
-{
- assert_locus *n, *loc, *last_loc;
- basic_block dest_bb;
-
- gcc_checking_assert (bb == NULL || e == NULL);
-
- if (e == NULL)
- gcc_checking_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND
- && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH);
-
- /* Never build an assert comparing against an integer constant with
- TREE_OVERFLOW set. This confuses our undefined overflow warning
- machinery. */
- if (TREE_OVERFLOW_P (val))
- val = drop_tree_overflow (val);
-
- /* The new assertion A will be inserted at BB or E. We need to
- determine if the new location is dominated by a previously
- registered location for A. If we are doing an edge insertion,
- assume that A will be inserted at E->DEST. Note that this is not
- necessarily true.
-
- If E is a critical edge, it will be split. But even if E is
- split, the new block will dominate the same set of blocks that
- E->DEST dominates.
-
- The reverse, however, is not true, blocks dominated by E->DEST
- will not be dominated by the new block created to split E. So,
- if the insertion location is on a critical edge, we will not use
- the new location to move another assertion previously registered
- at a block dominated by E->DEST. */
- dest_bb = (bb) ? bb : e->dest;
-
- /* If NAME already has an ASSERT_EXPR registered for COMP_CODE and
- VAL at a block dominating DEST_BB, then we don't need to insert a new
- one. Similarly, if the same assertion already exists at a block
- dominated by DEST_BB and the new location is not on a critical
- edge, then update the existing location for the assertion (i.e.,
- move the assertion up in the dominance tree).
-
- Note, this is implemented as a simple linked list because there
- should not be more than a handful of assertions registered per
- name. If this becomes a performance problem, a table hashed by
- COMP_CODE and VAL could be implemented. */
- loc = asserts_for[SSA_NAME_VERSION (name)];
- last_loc = loc;
- while (loc)
- {
- if (loc->comp_code == comp_code
- && (loc->val == val
- || operand_equal_p (loc->val, val, 0))
- && (loc->expr == expr
- || operand_equal_p (loc->expr, expr, 0)))
- {
- /* If E is not a critical edge and DEST_BB
- dominates the existing location for the assertion, move
- the assertion up in the dominance tree by updating its
- location information. */
- if ((e == NULL || !EDGE_CRITICAL_P (e))
- && dominated_by_p (CDI_DOMINATORS, loc->bb, dest_bb))
- {
- loc->bb = dest_bb;
- loc->e = e;
- loc->si = si;
- return;
- }
- }
-
- /* Update the last node of the list and move to the next one. */
- last_loc = loc;
- loc = loc->next;
- }
-
- /* If we didn't find an assertion already registered for
- NAME COMP_CODE VAL, add a new one at the end of the list of
- assertions associated with NAME. */
- n = XNEW (struct assert_locus);
- n->bb = dest_bb;
- n->e = e;
- n->si = si;
- n->comp_code = comp_code;
- n->val = val;
- n->expr = expr;
- n->next = NULL;
-
- if (last_loc)
- last_loc->next = n;
- else
- asserts_for[SSA_NAME_VERSION (name)] = n;
-
- bitmap_set_bit (need_assert_for, SSA_NAME_VERSION (name));
-}
-
/* (COND_OP0 COND_CODE COND_OP1) is a predicate which uses NAME.
Extract a suitable test code and value and store them into *CODE_P and
*VAL_P so the predicate is normalized to NAME *CODE_P *VAL_P.
@@ -2088,8 +1740,14 @@ register_edge_assert_for_2 (tree name, edge e,
&& ((TYPE_PRECISION (TREE_TYPE (name))
> TYPE_PRECISION (TREE_TYPE (rhs1)))
|| (get_range_info (rhs1, &rmin, &rmax) == VR_RANGE
- && wi::fits_to_tree_p (rmin, TREE_TYPE (name))
- && wi::fits_to_tree_p (rmax, TREE_TYPE (name)))))
+ && wi::fits_to_tree_p
+ (widest_int::from (rmin,
+ TYPE_SIGN (TREE_TYPE (rhs1))),
+ TREE_TYPE (name))
+ && wi::fits_to_tree_p
+ (widest_int::from (rmax,
+ TYPE_SIGN (TREE_TYPE (rhs1))),
+ TREE_TYPE (name)))))
add_assert_info (asserts, rhs1, rhs1,
comp_code, fold_convert (TREE_TYPE (rhs1), val));
}
@@ -2578,11 +2236,671 @@ register_edge_assert_for (tree name, edge e,
}
}
+/* Handle
+ _4 = x_3 & 31;
+ if (_4 != 0)
+ goto <bb 6>;
+ else
+ goto <bb 7>;
+ <bb 6>:
+ __builtin_unreachable ();
+ <bb 7>:
+ x_5 = ASSERT_EXPR <x_3, ...>;
+ If x_3 has no other immediate uses (checked by caller),
+ var is the x_3 var from ASSERT_EXPR, we can clear low 5 bits
+ from the non-zero bitmask. */
+
+void
+maybe_set_nonzero_bits (edge e, tree var)
+{
+ basic_block cond_bb = e->src;
+ gimple *stmt = last_stmt (cond_bb);
+ tree cst;
+
+ if (stmt == NULL
+ || gimple_code (stmt) != GIMPLE_COND
+ || gimple_cond_code (stmt) != ((e->flags & EDGE_TRUE_VALUE)
+ ? EQ_EXPR : NE_EXPR)
+ || TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME
+ || !integer_zerop (gimple_cond_rhs (stmt)))
+ return;
+
+ stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
+ if (!is_gimple_assign (stmt)
+ || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR
+ || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST)
+ return;
+ if (gimple_assign_rhs1 (stmt) != var)
+ {
+ gimple *stmt2;
+
+ if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
+ return;
+ stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
+ if (!gimple_assign_cast_p (stmt2)
+ || gimple_assign_rhs1 (stmt2) != var
+ || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
+ || (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+ != TYPE_PRECISION (TREE_TYPE (var))))
+ return;
+ }
+ cst = gimple_assign_rhs2 (stmt);
+ set_nonzero_bits (var, wi::bit_and_not (get_nonzero_bits (var),
+ wi::to_wide (cst)));
+}
+
+/* Return true if STMT is interesting for VRP. */
+
+bool
+stmt_interesting_for_vrp (gimple *stmt)
+{
+ if (gimple_code (stmt) == GIMPLE_PHI)
+ {
+ tree res = gimple_phi_result (stmt);
+ return (!virtual_operand_p (res)
+ && (INTEGRAL_TYPE_P (TREE_TYPE (res))
+ || POINTER_TYPE_P (TREE_TYPE (res))));
+ }
+ else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
+ {
+ tree lhs = gimple_get_lhs (stmt);
+
+ /* In general, assignments with virtual operands are not useful
+ for deriving ranges, with the obvious exception of calls to
+ builtin functions. */
+ if (lhs && TREE_CODE (lhs) == SSA_NAME
+ && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && (is_gimple_call (stmt)
+ || !gimple_vuse (stmt)))
+ return true;
+ else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
+ switch (gimple_call_internal_fn (stmt))
+ {
+ case IFN_ADD_OVERFLOW:
+ case IFN_SUB_OVERFLOW:
+ case IFN_MUL_OVERFLOW:
+ case IFN_ATOMIC_COMPARE_EXCHANGE:
+ /* These internal calls return _Complex integer type,
+ but are interesting to VRP nevertheless. */
+ if (lhs && TREE_CODE (lhs) == SSA_NAME)
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (gimple_code (stmt) == GIMPLE_COND
+ || gimple_code (stmt) == GIMPLE_SWITCH)
+ return true;
+
+ return false;
+}
+
+
+/* Return the LHS of any ASSERT_EXPR where OP appears as the first
+ argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
+ BB. If no such ASSERT_EXPR is found, return OP. */
+
+static tree
+lhs_of_dominating_assert (tree op, basic_block bb, gimple *stmt)
+{
+ imm_use_iterator imm_iter;
+ gimple *use_stmt;
+ use_operand_p use_p;
+
+ if (TREE_CODE (op) == SSA_NAME)
+ {
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
+ {
+ use_stmt = USE_STMT (use_p);
+ if (use_stmt != stmt
+ && gimple_assign_single_p (use_stmt)
+ && TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ASSERT_EXPR
+ && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == op
+ && dominated_by_p (CDI_DOMINATORS, bb, gimple_bb (use_stmt)))
+ return gimple_assign_lhs (use_stmt);
+ }
+ }
+ return op;
+}
+
+/* A hack. */
+static class vr_values *x_vr_values;
+
+/* Searches the case label vector VEC for the index *IDX of the CASE_LABEL
+ that includes the value VAL. The search is restricted to the range
+ [START_IDX, n - 1] where n is the size of VEC.
+
+ If there is a CASE_LABEL for VAL, its index is placed in IDX and true is
+ returned.
+
+ If there is no CASE_LABEL for VAL and there is one that is larger than VAL,
+ it is placed in IDX and false is returned.
+
+ If VAL is larger than any CASE_LABEL, n is placed on IDX and false is
+ returned. */
+
+bool
+find_case_label_index (gswitch *stmt, size_t start_idx, tree val, size_t *idx)
+{
+ size_t n = gimple_switch_num_labels (stmt);
+ size_t low, high;
+
+ /* Find case label for minimum of the value range or the next one.
+ At each iteration we are searching in [low, high - 1]. */
+
+ for (low = start_idx, high = n; high != low; )
+ {
+ tree t;
+ int cmp;
+ /* Note that i != high, so we never ask for n. */
+ size_t i = (high + low) / 2;
+ t = gimple_switch_label (stmt, i);
+
+ /* Cache the result of comparing CASE_LOW and val. */
+ cmp = tree_int_cst_compare (CASE_LOW (t), val);
+
+ if (cmp == 0)
+ {
+ /* Ranges cannot be empty. */
+ *idx = i;
+ return true;
+ }
+ else if (cmp > 0)
+ high = i;
+ else
+ {
+ low = i + 1;
+ if (CASE_HIGH (t) != NULL
+ && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
+ {
+ *idx = i;
+ return true;
+ }
+ }
+ }
+
+ *idx = high;
+ return false;
+}
+
+/* Searches the case label vector VEC for the range of CASE_LABELs that is used
+ for values between MIN and MAX. The first index is placed in MIN_IDX. The
+ last index is placed in MAX_IDX. If the range of CASE_LABELs is empty
+ then MAX_IDX < MIN_IDX.
+ Returns true if the default label is not needed. */
+
+bool
+find_case_label_range (gswitch *stmt, tree min, tree max, size_t *min_idx,
+ size_t *max_idx)
+{
+ size_t i, j;
+ bool min_take_default = !find_case_label_index (stmt, 1, min, &i);
+ bool max_take_default = !find_case_label_index (stmt, i, max, &j);
+
+ if (i == j
+ && min_take_default
+ && max_take_default)
+ {
+ /* Only the default case label reached.
+ Return an empty range. */
+ *min_idx = 1;
+ *max_idx = 0;
+ return false;
+ }
+ else
+ {
+ bool take_default = min_take_default || max_take_default;
+ tree low, high;
+ size_t k;
+
+ if (max_take_default)
+ j--;
+
+ /* If the case label range is continuous, we do not need
+ the default case label. Verify that. */
+ high = CASE_LOW (gimple_switch_label (stmt, i));
+ if (CASE_HIGH (gimple_switch_label (stmt, i)))
+ high = CASE_HIGH (gimple_switch_label (stmt, i));
+ for (k = i + 1; k <= j; ++k)
+ {
+ low = CASE_LOW (gimple_switch_label (stmt, k));
+ if (!integer_onep (int_const_binop (MINUS_EXPR, low, high)))
+ {
+ take_default = true;
+ break;
+ }
+ high = low;
+ if (CASE_HIGH (gimple_switch_label (stmt, k)))
+ high = CASE_HIGH (gimple_switch_label (stmt, k));
+ }
+
+ *min_idx = i;
+ *max_idx = j;
+ return !take_default;
+ }
+}
+
+/* Given a SWITCH_STMT, return the case label that encompasses the
+ known possible values for the switch operand. RANGE_OF_OP is a
+ range for the known values of the switch operand. */
+
+tree
+find_case_label_range (gswitch *switch_stmt, const irange *range_of_op)
+{
+ if (range_of_op->undefined_p ()
+ || range_of_op->varying_p ()
+ || range_of_op->symbolic_p ())
+ return NULL_TREE;
+
+ size_t i, j;
+ tree op = gimple_switch_index (switch_stmt);
+ tree type = TREE_TYPE (op);
+ tree tmin = wide_int_to_tree (type, range_of_op->lower_bound ());
+ tree tmax = wide_int_to_tree (type, range_of_op->upper_bound ());
+ find_case_label_range (switch_stmt, tmin, tmax, &i, &j);
+ if (i == j)
+ {
+ /* Look for exactly one label that encompasses the range of
+ the operand. */
+ tree label = gimple_switch_label (switch_stmt, i);
+ tree case_high
+ = CASE_HIGH (label) ? CASE_HIGH (label) : CASE_LOW (label);
+ int_range_max label_range (CASE_LOW (label), case_high);
+ if (!types_compatible_p (label_range.type (), range_of_op->type ()))
+ range_cast (label_range, range_of_op->type ());
+ label_range.intersect (range_of_op);
+ if (label_range == *range_of_op)
+ return label;
+ }
+ else if (i > j)
+ {
+ /* If there are no labels at all, take the default. */
+ return gimple_switch_label (switch_stmt, 0);
+ }
+ else
+ {
+ /* Otherwise, there are various labels that can encompass
+ the range of operand. In which case, see if the range of
+ the operand is entirely *outside* the bounds of all the
+ (non-default) case labels. If so, take the default. */
+ unsigned n = gimple_switch_num_labels (switch_stmt);
+ tree min_label = gimple_switch_label (switch_stmt, 1);
+ tree max_label = gimple_switch_label (switch_stmt, n - 1);
+ tree case_high = CASE_HIGH (max_label);
+ if (!case_high)
+ case_high = CASE_LOW (max_label);
+ int_range_max label_range (CASE_LOW (min_label), case_high);
+ if (!types_compatible_p (label_range.type (), range_of_op->type ()))
+ range_cast (label_range, range_of_op->type ());
+ label_range.intersect (range_of_op);
+ if (label_range.undefined_p ())
+ return gimple_switch_label (switch_stmt, 0);
+ }
+ return NULL_TREE;
+}
+
+struct case_info
+{
+ tree expr;
+ basic_block bb;
+};
+
+/* Location information for ASSERT_EXPRs. Each instance of this
+ structure describes an ASSERT_EXPR for an SSA name. Since a single
+ SSA name may have more than one assertion associated with it, these
+ locations are kept in a linked list attached to the corresponding
+ SSA name. */
+struct assert_locus
+{
+ /* Basic block where the assertion would be inserted. */
+ basic_block bb;
+
+ /* Some assertions need to be inserted on an edge (e.g., assertions
+ generated by COND_EXPRs). In those cases, BB will be NULL. */
+ edge e;
+
+ /* Pointer to the statement that generated this assertion. */
+ gimple_stmt_iterator si;
+
+ /* Predicate code for the ASSERT_EXPR. Must be COMPARISON_CLASS_P. */
+ enum tree_code comp_code;
+
+ /* Value being compared against. */
+ tree val;
+
+ /* Expression to compare. */
+ tree expr;
+
+ /* Next node in the linked list. */
+ assert_locus *next;
+};
+
+/* Class to traverse the flowgraph looking for conditional jumps to
+ insert ASSERT_EXPR range expressions. These range expressions are
+ meant to provide information to optimizations that need to reason
+ in terms of value ranges. They will not be expanded into RTL. */
+
+class vrp_asserts
+{
+public:
+ vrp_asserts (struct function *fn) : fun (fn) { }
+
+ void insert_range_assertions ();
+
+ /* Convert range assertion expressions into the implied copies and
+ copy propagate away the copies. */
+ void remove_range_assertions ();
+
+ /* Dump all the registered assertions for all the names to FILE. */
+ void dump (FILE *);
+
+ /* Dump all the registered assertions for NAME to FILE. */
+ void dump (FILE *file, tree name);
+
+ /* Dump all the registered assertions for NAME to stderr. */
+ void debug (tree name)
+ {
+ dump (stderr, name);
+ }
+
+ /* Dump all the registered assertions for all the names to stderr. */
+ void debug ()
+ {
+ dump (stderr);
+ }
+
+private:
+ /* Set of SSA names found live during the RPO traversal of the function
+ for still active basic-blocks. */
+ live_names live;
+
+ /* Function to work on. */
+ struct function *fun;
+
+ /* If bit I is present, it means that SSA name N_i has a list of
+ assertions that should be inserted in the IL. */
+ bitmap need_assert_for;
+
+ /* Array of locations lists where to insert assertions. ASSERTS_FOR[I]
+ holds a list of ASSERT_LOCUS_T nodes that describe where
+ ASSERT_EXPRs for SSA name N_I should be inserted. */
+ assert_locus **asserts_for;
+
+ /* Finish found ASSERTS for E and register them at GSI. */
+ void finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
+ vec<assert_info> &asserts);
+
+ /* Determine whether the outgoing edges of BB should receive an
+ ASSERT_EXPR for each of the operands of BB's LAST statement. The
+ last statement of BB must be a SWITCH_EXPR.
+
+ If any of the sub-graphs rooted at BB have an interesting use of
+ the predicate operands, an assert location node is added to the
+ list of assertions for the corresponding operands. */
+ void find_switch_asserts (basic_block bb, gswitch *last);
+
+ /* Do an RPO walk over the function computing SSA name liveness
+ on-the-fly and deciding on assert expressions to insert. */
+ void find_assert_locations ();
+
+ /* Traverse all the statements in block BB looking for statements that
+ may generate useful assertions for the SSA names in their operand.
+ See method implementation comentary for more information. */
+ void find_assert_locations_in_bb (basic_block bb);
+
+ /* Determine whether the outgoing edges of BB should receive an
+ ASSERT_EXPR for each of the operands of BB's LAST statement.
+ The last statement of BB must be a COND_EXPR.
+
+ If any of the sub-graphs rooted at BB have an interesting use of
+ the predicate operands, an assert location node is added to the
+ list of assertions for the corresponding operands. */
+ void find_conditional_asserts (basic_block bb, gcond *last);
+
+ /* Process all the insertions registered for every name N_i registered
+ in NEED_ASSERT_FOR. The list of assertions to be inserted are
+ found in ASSERTS_FOR[i]. */
+ void process_assert_insertions ();
+
+ /* If NAME doesn't have an ASSERT_EXPR registered for asserting
+ 'EXPR COMP_CODE VAL' at a location that dominates block BB or
+ E->DEST, then register this location as a possible insertion point
+ for ASSERT_EXPR <NAME, EXPR COMP_CODE VAL>.
+
+ BB, E and SI provide the exact insertion point for the new
+ ASSERT_EXPR. If BB is NULL, then the ASSERT_EXPR is to be inserted
+ on edge E. Otherwise, if E is NULL, the ASSERT_EXPR is inserted on
+ BB. If SI points to a COND_EXPR or a SWITCH_EXPR statement, then E
+ must not be NULL. */
+ void register_new_assert_for (tree name, tree expr,
+ enum tree_code comp_code,
+ tree val, basic_block bb,
+ edge e, gimple_stmt_iterator si);
+
+ /* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
+ create a new SSA name N and return the assertion assignment
+ 'N = ASSERT_EXPR <V, V OP W>'. */
+ gimple *build_assert_expr_for (tree cond, tree v);
+
+ /* Create an ASSERT_EXPR for NAME and insert it in the location
+ indicated by LOC. Return true if we made any edge insertions. */
+ bool process_assert_insertions_for (tree name, assert_locus *loc);
+
+ /* Qsort callback for sorting assert locations. */
+ template <bool stable> static int compare_assert_loc (const void *,
+ const void *);
+
+ /* Return false if EXPR is a predicate expression involving floating
+ point values. */
+ bool fp_predicate (gimple *stmt)
+ {
+ GIMPLE_CHECK (stmt, GIMPLE_COND);
+ return FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)));
+ }
+
+ bool all_imm_uses_in_stmt_or_feed_cond (tree var, gimple *stmt,
+ basic_block cond_bb);
+
+ static int compare_case_labels (const void *, const void *);
+};
+
+/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
+ create a new SSA name N and return the assertion assignment
+ 'N = ASSERT_EXPR <V, V OP W>'. */
+
+gimple *
+vrp_asserts::build_assert_expr_for (tree cond, tree v)
+{
+ tree a;
+ gassign *assertion;
+
+ gcc_assert (TREE_CODE (v) == SSA_NAME
+ && COMPARISON_CLASS_P (cond));
+
+ a = build2 (ASSERT_EXPR, TREE_TYPE (v), v, cond);
+ assertion = gimple_build_assign (NULL_TREE, a);
+
+ /* The new ASSERT_EXPR, creates a new SSA name that replaces the
+ operand of the ASSERT_EXPR. Create it so the new name and the old one
+ are registered in the replacement table so that we can fix the SSA web
+ after adding all the ASSERT_EXPRs. */
+ tree new_def = create_new_def_for (v, assertion, NULL);
+ /* Make sure we preserve abnormalness throughout an ASSERT_EXPR chain
+ given we have to be able to fully propagate those out to re-create
+ valid SSA when removing the asserts. */
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (v))
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_def) = 1;
+
+ return assertion;
+}
+
+/* Dump all the registered assertions for NAME to FILE. */
+
+void
+vrp_asserts::dump (FILE *file, tree name)
+{
+ assert_locus *loc;
+
+ fprintf (file, "Assertions to be inserted for ");
+ print_generic_expr (file, name);
+ fprintf (file, "\n");
+
+ loc = asserts_for[SSA_NAME_VERSION (name)];
+ while (loc)
+ {
+ fprintf (file, "\t");
+ print_gimple_stmt (file, gsi_stmt (loc->si), 0);
+ fprintf (file, "\n\tBB #%d", loc->bb->index);
+ if (loc->e)
+ {
+ fprintf (file, "\n\tEDGE %d->%d", loc->e->src->index,
+ loc->e->dest->index);
+ dump_edge_info (file, loc->e, dump_flags, 0);
+ }
+ fprintf (file, "\n\tPREDICATE: ");
+ print_generic_expr (file, loc->expr);
+ fprintf (file, " %s ", get_tree_code_name (loc->comp_code));
+ print_generic_expr (file, loc->val);
+ fprintf (file, "\n\n");
+ loc = loc->next;
+ }
+
+ fprintf (file, "\n");
+}
+
+/* Dump all the registered assertions for all the names to FILE. */
+
+void
+vrp_asserts::dump (FILE *file)
+{
+ unsigned i;
+ bitmap_iterator bi;
+
+ fprintf (file, "\nASSERT_EXPRs to be inserted\n\n");
+ EXECUTE_IF_SET_IN_BITMAP (need_assert_for, 0, i, bi)
+ dump (file, ssa_name (i));
+ fprintf (file, "\n");
+}
+
+/* If NAME doesn't have an ASSERT_EXPR registered for asserting
+ 'EXPR COMP_CODE VAL' at a location that dominates block BB or
+ E->DEST, then register this location as a possible insertion point
+ for ASSERT_EXPR <NAME, EXPR COMP_CODE VAL>.
+
+ BB, E and SI provide the exact insertion point for the new
+ ASSERT_EXPR. If BB is NULL, then the ASSERT_EXPR is to be inserted
+ on edge E. Otherwise, if E is NULL, the ASSERT_EXPR is inserted on
+ BB. If SI points to a COND_EXPR or a SWITCH_EXPR statement, then E
+ must not be NULL. */
+
+void
+vrp_asserts::register_new_assert_for (tree name, tree expr,
+ enum tree_code comp_code,
+ tree val,
+ basic_block bb,
+ edge e,
+ gimple_stmt_iterator si)
+{
+ assert_locus *n, *loc, *last_loc;
+ basic_block dest_bb;
+
+ gcc_checking_assert (bb == NULL || e == NULL);
+
+ if (e == NULL)
+ gcc_checking_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND
+ && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH);
+
+ /* Never build an assert comparing against an integer constant with
+ TREE_OVERFLOW set. This confuses our undefined overflow warning
+ machinery. */
+ if (TREE_OVERFLOW_P (val))
+ val = drop_tree_overflow (val);
+
+ /* The new assertion A will be inserted at BB or E. We need to
+ determine if the new location is dominated by a previously
+ registered location for A. If we are doing an edge insertion,
+ assume that A will be inserted at E->DEST. Note that this is not
+ necessarily true.
+
+ If E is a critical edge, it will be split. But even if E is
+ split, the new block will dominate the same set of blocks that
+ E->DEST dominates.
+
+ The reverse, however, is not true, blocks dominated by E->DEST
+ will not be dominated by the new block created to split E. So,
+ if the insertion location is on a critical edge, we will not use
+ the new location to move another assertion previously registered
+ at a block dominated by E->DEST. */
+ dest_bb = (bb) ? bb : e->dest;
+
+ /* If NAME already has an ASSERT_EXPR registered for COMP_CODE and
+ VAL at a block dominating DEST_BB, then we don't need to insert a new
+ one. Similarly, if the same assertion already exists at a block
+ dominated by DEST_BB and the new location is not on a critical
+ edge, then update the existing location for the assertion (i.e.,
+ move the assertion up in the dominance tree).
+
+ Note, this is implemented as a simple linked list because there
+ should not be more than a handful of assertions registered per
+ name. If this becomes a performance problem, a table hashed by
+ COMP_CODE and VAL could be implemented. */
+ loc = asserts_for[SSA_NAME_VERSION (name)];
+ last_loc = loc;
+ while (loc)
+ {
+ if (loc->comp_code == comp_code
+ && (loc->val == val
+ || operand_equal_p (loc->val, val, 0))
+ && (loc->expr == expr
+ || operand_equal_p (loc->expr, expr, 0)))
+ {
+ /* If E is not a critical edge and DEST_BB
+ dominates the existing location for the assertion, move
+ the assertion up in the dominance tree by updating its
+ location information. */
+ if ((e == NULL || !EDGE_CRITICAL_P (e))
+ && dominated_by_p (CDI_DOMINATORS, loc->bb, dest_bb))
+ {
+ loc->bb = dest_bb;
+ loc->e = e;
+ loc->si = si;
+ return;
+ }
+ }
+
+ /* Update the last node of the list and move to the next one. */
+ last_loc = loc;
+ loc = loc->next;
+ }
+
+ /* If we didn't find an assertion already registered for
+ NAME COMP_CODE VAL, add a new one at the end of the list of
+ assertions associated with NAME. */
+ n = XNEW (struct assert_locus);
+ n->bb = dest_bb;
+ n->e = e;
+ n->si = si;
+ n->comp_code = comp_code;
+ n->val = val;
+ n->expr = expr;
+ n->next = NULL;
+
+ if (last_loc)
+ last_loc->next = n;
+ else
+ asserts_for[SSA_NAME_VERSION (name)] = n;
+
+ bitmap_set_bit (need_assert_for, SSA_NAME_VERSION (name));
+}
+
/* Finish found ASSERTS for E and register them at GSI. */
void
-vrp_insert::finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
- vec<assert_info> &asserts)
+vrp_asserts::finish_register_edge_assert_for (edge e,
+ gimple_stmt_iterator gsi,
+ vec<assert_info> &asserts)
{
for (unsigned i = 0; i < asserts.length (); ++i)
/* Only register an ASSERT_EXPR if NAME was found in the sub-graph
@@ -2593,8 +2911,6 @@ vrp_insert::finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
NULL, e, gsi);
}
-
-
/* Determine whether the outgoing edges of BB should receive an
ASSERT_EXPR for each of the operands of BB's LAST statement.
The last statement of BB must be a COND_EXPR.
@@ -2604,7 +2920,7 @@ vrp_insert::finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
list of assertions for the corresponding operands. */
void
-vrp_insert::find_conditional_asserts (basic_block bb, gcond *last)
+vrp_asserts::find_conditional_asserts (basic_block bb, gcond *last)
{
gimple_stmt_iterator bsi;
tree op;
@@ -2635,17 +2951,11 @@ vrp_insert::find_conditional_asserts (basic_block bb, gcond *last)
}
}
-struct case_info
-{
- tree expr;
- basic_block bb;
-};
-
/* Compare two case labels sorting first by the destination bb index
and then by the case value. */
-static int
-compare_case_labels (const void *p1, const void *p2)
+int
+vrp_asserts::compare_case_labels (const void *p1, const void *p2)
{
const struct case_info *ci1 = (const struct case_info *) p1;
const struct case_info *ci2 = (const struct case_info *) p2;
@@ -2678,7 +2988,7 @@ compare_case_labels (const void *p1, const void *p2)
list of assertions for the corresponding operands. */
void
-vrp_insert::find_switch_asserts (basic_block bb, gswitch *last)
+vrp_asserts::find_switch_asserts (basic_block bb, gswitch *last)
{
gimple_stmt_iterator bsi;
tree op;
@@ -2827,7 +3137,6 @@ vrp_insert::find_switch_asserts (basic_block bb, gswitch *last)
}
}
-
/* Traverse all the statements in block BB looking for statements that
may generate useful assertions for the SSA names in their operand.
If a statement produces a useful assertion A for name N_i, then the
@@ -2888,7 +3197,7 @@ vrp_insert::find_switch_asserts (basic_block bb, gswitch *last)
P_4 will receive an ASSERT_EXPR. */
void
-vrp_insert::find_assert_locations_in_bb (basic_block bb)
+vrp_asserts::find_assert_locations_in_bb (basic_block bb)
{
gimple *last;
@@ -3008,7 +3317,7 @@ vrp_insert::find_assert_locations_in_bb (basic_block bb)
on-the-fly and deciding on assert expressions to insert. */
void
-vrp_insert::find_assert_locations (void)
+vrp_asserts::find_assert_locations (void)
{
int *rpo = XNEWVEC (int, last_basic_block_for_fn (fun));
int *bb_rpo = XNEWVEC (int, last_basic_block_for_fn (fun));
@@ -3088,7 +3397,7 @@ vrp_insert::find_assert_locations (void)
indicated by LOC. Return true if we made any edge insertions. */
bool
-vrp_insert::process_assert_insertions_for (tree name, assert_locus *loc)
+vrp_asserts::process_assert_insertions_for (tree name, assert_locus *loc)
{
/* Build the comparison expression NAME_i COMP_CODE VAL. */
gimple *stmt;
@@ -3153,7 +3462,7 @@ vrp_insert::process_assert_insertions_for (tree name, assert_locus *loc)
template <bool stable>
int
-vrp_insert::compare_assert_loc (const void *pa, const void *pb)
+vrp_asserts::compare_assert_loc (const void *pa, const void *pb)
{
assert_locus * const a = *(assert_locus * const *)pa;
assert_locus * const b = *(assert_locus * const *)pb;
@@ -3221,7 +3530,7 @@ vrp_insert::compare_assert_loc (const void *pa, const void *pb)
found in ASSERTS_FOR[i]. */
void
-vrp_insert::process_assert_insertions ()
+vrp_asserts::process_assert_insertions ()
{
unsigned i;
bitmap_iterator bi;
@@ -3314,7 +3623,6 @@ vrp_insert::process_assert_insertions ()
num_asserts);
}
-
/* Traverse the flowgraph looking for conditional jumps to insert range
expressions. These range expressions are meant to provide information
to optimizations that need to reason in terms of value ranges. They
@@ -3348,7 +3656,7 @@ vrp_insert::process_assert_insertions ()
definition of 'x'. */
void
-vrp_insert::insert_range_assertions (void)
+vrp_asserts::insert_range_assertions (void)
{
need_assert_for = BITMAP_ALLOC (NULL);
asserts_for = XCNEWVEC (assert_locus *, num_ssa_names);
@@ -3372,44 +3680,14 @@ vrp_insert::insert_range_assertions (void)
BITMAP_FREE (need_assert_for);
}
-class vrp_prop : public ssa_propagation_engine
-{
-public:
- enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
- enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
-
- struct function *fun;
-
- void vrp_initialize (struct function *);
- void vrp_finalize (class vrp_folder *, bool);
-
- class vr_values vr_values;
-
-private:
- /* Temporary delegator to minimize code churn. */
- const value_range_equiv *get_value_range (const_tree op)
- { return vr_values.get_value_range (op); }
- void set_def_to_varying (const_tree def)
- { vr_values.set_def_to_varying (def); }
- void set_defs_to_varying (gimple *stmt)
- { vr_values.set_defs_to_varying (stmt); }
- void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
- tree *output_p, value_range_equiv *vr)
- { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); }
- bool update_value_range (const_tree op, value_range_equiv *vr)
- { return vr_values.update_value_range (op, vr); }
- void extract_range_basic (value_range_equiv *vr, gimple *stmt)
- { vr_values.extract_range_basic (vr, stmt); }
- void extract_range_from_phi_node (gphi *phi, value_range_equiv *vr)
- { vr_values.extract_range_from_phi_node (phi, vr); }
-};
-
/* Return true if all imm uses of VAR are either in STMT, or
feed (optionally through a chain of single imm uses) GIMPLE_COND
in basic block COND_BB. */
-static bool
-all_imm_uses_in_stmt_or_feed_cond (tree var, gimple *stmt, basic_block cond_bb)
+bool
+vrp_asserts::all_imm_uses_in_stmt_or_feed_cond (tree var,
+ gimple *stmt,
+ basic_block cond_bb)
{
use_operand_p use_p, use2_p;
imm_use_iterator iter;
@@ -3432,59 +3710,6 @@ all_imm_uses_in_stmt_or_feed_cond (tree var, gimple *stmt, basic_block cond_bb)
return true;
}
-/* Handle
- _4 = x_3 & 31;
- if (_4 != 0)
- goto <bb 6>;
- else
- goto <bb 7>;
- <bb 6>:
- __builtin_unreachable ();
- <bb 7>:
- x_5 = ASSERT_EXPR <x_3, ...>;
- If x_3 has no other immediate uses (checked by caller),
- var is the x_3 var from ASSERT_EXPR, we can clear low 5 bits
- from the non-zero bitmask. */
-
-void
-maybe_set_nonzero_bits (edge e, tree var)
-{
- basic_block cond_bb = e->src;
- gimple *stmt = last_stmt (cond_bb);
- tree cst;
-
- if (stmt == NULL
- || gimple_code (stmt) != GIMPLE_COND
- || gimple_cond_code (stmt) != ((e->flags & EDGE_TRUE_VALUE)
- ? EQ_EXPR : NE_EXPR)
- || TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME
- || !integer_zerop (gimple_cond_rhs (stmt)))
- return;
-
- stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
- if (!is_gimple_assign (stmt)
- || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR
- || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST)
- return;
- if (gimple_assign_rhs1 (stmt) != var)
- {
- gimple *stmt2;
-
- if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
- return;
- stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
- if (!gimple_assign_cast_p (stmt2)
- || gimple_assign_rhs1 (stmt2) != var
- || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
- || (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))
- != TYPE_PRECISION (TREE_TYPE (var))))
- return;
- }
- cst = gimple_assign_rhs2 (stmt);
- set_nonzero_bits (var, wi::bit_and_not (get_nonzero_bits (var),
- wi::to_wide (cst)));
-}
-
/* Convert range assertion expressions into the implied copies and
copy propagate away the copies. Doing the trivial copy propagation
here avoids the need to run the full copy propagation pass after
@@ -3510,7 +3735,7 @@ maybe_set_nonzero_bits (edge e, tree var)
multiple ranges to be associated with one SSA_NAME. */
void
-vrp_insert::remove_range_assertions ()
+vrp_asserts::remove_range_assertions ()
{
basic_block bb;
gimple_stmt_iterator si;
@@ -3595,58 +3820,28 @@ vrp_insert::remove_range_assertions ()
}
}
-/* Return true if STMT is interesting for VRP. */
-
-bool
-stmt_interesting_for_vrp (gimple *stmt)
+class vrp_prop : public ssa_propagation_engine
{
- if (gimple_code (stmt) == GIMPLE_PHI)
- {
- tree res = gimple_phi_result (stmt);
- return (!virtual_operand_p (res)
- && (INTEGRAL_TYPE_P (TREE_TYPE (res))
- || POINTER_TYPE_P (TREE_TYPE (res))));
- }
- else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
- {
- tree lhs = gimple_get_lhs (stmt);
+public:
+ vrp_prop (vr_values *v)
+ : ssa_propagation_engine (),
+ m_vr_values (v) { }
- /* In general, assignments with virtual operands are not useful
- for deriving ranges, with the obvious exception of calls to
- builtin functions. */
- if (lhs && TREE_CODE (lhs) == SSA_NAME
- && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && (is_gimple_call (stmt)
- || !gimple_vuse (stmt)))
- return true;
- else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
- switch (gimple_call_internal_fn (stmt))
- {
- case IFN_ADD_OVERFLOW:
- case IFN_SUB_OVERFLOW:
- case IFN_MUL_OVERFLOW:
- case IFN_ATOMIC_COMPARE_EXCHANGE:
- /* These internal calls return _Complex integer type,
- but are interesting to VRP nevertheless. */
- if (lhs && TREE_CODE (lhs) == SSA_NAME)
- return true;
- break;
- default:
- break;
- }
- }
- else if (gimple_code (stmt) == GIMPLE_COND
- || gimple_code (stmt) == GIMPLE_SWITCH)
- return true;
+ void initialize (struct function *);
+ void finalize ();
- return false;
-}
+private:
+ enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
+ enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
+
+ struct function *fun;
+ vr_values *m_vr_values;
+};
/* Initialization required by ssa_propagate engine. */
void
-vrp_prop::vrp_initialize (struct function *fn)
+vrp_prop::initialize (struct function *fn)
{
basic_block bb;
fun = fn;
@@ -3660,7 +3855,7 @@ vrp_prop::vrp_initialize (struct function *fn)
if (!stmt_interesting_for_vrp (phi))
{
tree lhs = PHI_RESULT (phi);
- set_def_to_varying (lhs);
+ m_vr_values->set_def_to_varying (lhs);
prop_set_simulate_again (phi, false);
}
else
@@ -3679,7 +3874,7 @@ vrp_prop::vrp_initialize (struct function *fn)
prop_set_simulate_again (stmt, true);
else if (!stmt_interesting_for_vrp (stmt))
{
- set_defs_to_varying (stmt);
+ m_vr_values->set_defs_to_varying (stmt);
prop_set_simulate_again (stmt, false);
}
else
@@ -3688,179 +3883,6 @@ vrp_prop::vrp_initialize (struct function *fn)
}
}
-/* Searches the case label vector VEC for the index *IDX of the CASE_LABEL
- that includes the value VAL. The search is restricted to the range
- [START_IDX, n - 1] where n is the size of VEC.
-
- If there is a CASE_LABEL for VAL, its index is placed in IDX and true is
- returned.
-
- If there is no CASE_LABEL for VAL and there is one that is larger than VAL,
- it is placed in IDX and false is returned.
-
- If VAL is larger than any CASE_LABEL, n is placed on IDX and false is
- returned. */
-
-bool
-find_case_label_index (gswitch *stmt, size_t start_idx, tree val, size_t *idx)
-{
- size_t n = gimple_switch_num_labels (stmt);
- size_t low, high;
-
- /* Find case label for minimum of the value range or the next one.
- At each iteration we are searching in [low, high - 1]. */
-
- for (low = start_idx, high = n; high != low; )
- {
- tree t;
- int cmp;
- /* Note that i != high, so we never ask for n. */
- size_t i = (high + low) / 2;
- t = gimple_switch_label (stmt, i);
-
- /* Cache the result of comparing CASE_LOW and val. */
- cmp = tree_int_cst_compare (CASE_LOW (t), val);
-
- if (cmp == 0)
- {
- /* Ranges cannot be empty. */
- *idx = i;
- return true;
- }
- else if (cmp > 0)
- high = i;
- else
- {
- low = i + 1;
- if (CASE_HIGH (t) != NULL
- && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
- {
- *idx = i;
- return true;
- }
- }
- }
-
- *idx = high;
- return false;
-}
-
-/* Searches the case label vector VEC for the range of CASE_LABELs that is used
- for values between MIN and MAX. The first index is placed in MIN_IDX. The
- last index is placed in MAX_IDX. If the range of CASE_LABELs is empty
- then MAX_IDX < MIN_IDX.
- Returns true if the default label is not needed. */
-
-bool
-find_case_label_range (gswitch *stmt, tree min, tree max, size_t *min_idx,
- size_t *max_idx)
-{
- size_t i, j;
- bool min_take_default = !find_case_label_index (stmt, 1, min, &i);
- bool max_take_default = !find_case_label_index (stmt, i, max, &j);
-
- if (i == j
- && min_take_default
- && max_take_default)
- {
- /* Only the default case label reached.
- Return an empty range. */
- *min_idx = 1;
- *max_idx = 0;
- return false;
- }
- else
- {
- bool take_default = min_take_default || max_take_default;
- tree low, high;
- size_t k;
-
- if (max_take_default)
- j--;
-
- /* If the case label range is continuous, we do not need
- the default case label. Verify that. */
- high = CASE_LOW (gimple_switch_label (stmt, i));
- if (CASE_HIGH (gimple_switch_label (stmt, i)))
- high = CASE_HIGH (gimple_switch_label (stmt, i));
- for (k = i + 1; k <= j; ++k)
- {
- low = CASE_LOW (gimple_switch_label (stmt, k));
- if (!integer_onep (int_const_binop (MINUS_EXPR, low, high)))
- {
- take_default = true;
- break;
- }
- high = low;
- if (CASE_HIGH (gimple_switch_label (stmt, k)))
- high = CASE_HIGH (gimple_switch_label (stmt, k));
- }
-
- *min_idx = i;
- *max_idx = j;
- return !take_default;
- }
-}
-
-/* Given a SWITCH_STMT, return the case label that encompasses the
- known possible values for the switch operand. RANGE_OF_OP is a
- range for the known values of the switch operand. */
-
-tree
-find_case_label_range (gswitch *switch_stmt, const irange *range_of_op)
-{
- if (range_of_op->undefined_p ()
- || range_of_op->varying_p ()
- || range_of_op->symbolic_p ())
- return NULL_TREE;
-
- size_t i, j;
- tree op = gimple_switch_index (switch_stmt);
- tree type = TREE_TYPE (op);
- tree tmin = wide_int_to_tree (type, range_of_op->lower_bound ());
- tree tmax = wide_int_to_tree (type, range_of_op->upper_bound ());
- find_case_label_range (switch_stmt, tmin, tmax, &i, &j);
- if (i == j)
- {
- /* Look for exactly one label that encompasses the range of
- the operand. */
- tree label = gimple_switch_label (switch_stmt, i);
- tree case_high
- = CASE_HIGH (label) ? CASE_HIGH (label) : CASE_LOW (label);
- int_range_max label_range (CASE_LOW (label), case_high);
- if (!types_compatible_p (label_range.type (), range_of_op->type ()))
- range_cast (label_range, range_of_op->type ());
- label_range.intersect (range_of_op);
- if (label_range == *range_of_op)
- return label;
- }
- else if (i > j)
- {
- /* If there are no labels at all, take the default. */
- return gimple_switch_label (switch_stmt, 0);
- }
- else
- {
- /* Otherwise, there are various labels that can encompass
- the range of operand. In which case, see if the range of
- the operand is entirely *outside* the bounds of all the
- (non-default) case labels. If so, take the default. */
- unsigned n = gimple_switch_num_labels (switch_stmt);
- tree min_label = gimple_switch_label (switch_stmt, 1);
- tree max_label = gimple_switch_label (switch_stmt, n - 1);
- tree case_high = CASE_HIGH (max_label);
- if (!case_high)
- case_high = CASE_LOW (max_label);
- int_range_max label_range (CASE_LOW (min_label), case_high);
- if (!types_compatible_p (label_range.type (), range_of_op->type ()))
- range_cast (label_range, range_of_op->type ());
- label_range.intersect (range_of_op);
- if (label_range.undefined_p ())
- return gimple_switch_label (switch_stmt, 0);
- }
- return NULL_TREE;
-}
-
/* Evaluate statement STMT. If the statement produces a useful range,
return SSA_PROP_INTERESTING and record the SSA name with the
interesting range into *OUTPUT_P.
@@ -3875,11 +3897,11 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
{
tree lhs = gimple_get_lhs (stmt);
value_range_equiv vr;
- extract_range_from_stmt (stmt, taken_edge_p, output_p, &vr);
+ m_vr_values->extract_range_from_stmt (stmt, taken_edge_p, output_p, &vr);
if (*output_p)
{
- if (update_value_range (*output_p, &vr))
+ if (m_vr_values->update_value_range (*output_p, &vr))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -3914,7 +3936,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
use_operand_p use_p;
enum ssa_prop_result res = SSA_PROP_VARYING;
- set_def_to_varying (lhs);
+ m_vr_values->set_def_to_varying (lhs);
FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
{
@@ -3944,8 +3966,9 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
{REAL,IMAG}PART_EXPR uses at all,
return SSA_PROP_VARYING. */
value_range_equiv new_vr;
- extract_range_basic (&new_vr, use_stmt);
- const value_range_equiv *old_vr = get_value_range (use_lhs);
+ m_vr_values->extract_range_basic (&new_vr, use_stmt);
+ const value_range_equiv *old_vr
+ = m_vr_values->get_value_range (use_lhs);
if (!old_vr->equal_p (new_vr, /*ignore_equivs=*/false))
res = SSA_PROP_INTERESTING;
else
@@ -3967,7 +3990,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
/* All other statements produce nothing of interest for VRP, so mark
their outputs varying and prevent further simulation. */
- set_defs_to_varying (stmt);
+ m_vr_values->set_defs_to_varying (stmt);
return (*taken_edge_p) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING;
}
@@ -3981,8 +4004,8 @@ vrp_prop::visit_phi (gphi *phi)
{
tree lhs = PHI_RESULT (phi);
value_range_equiv vr_result;
- extract_range_from_phi_node (phi, &vr_result);
- if (update_value_range (lhs, &vr_result))
+ m_vr_values->extract_range_from_phi_node (phi, &vr_result);
+ if (m_vr_values->update_value_range (lhs, &vr_result))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -4003,6 +4026,42 @@ vrp_prop::visit_phi (gphi *phi)
return SSA_PROP_NOT_INTERESTING;
}
+/* Traverse all the blocks folding conditionals with known ranges. */
+
+void
+vrp_prop::finalize ()
+{
+ size_t i;
+
+ /* We have completed propagating through the lattice. */
+ m_vr_values->set_lattice_propagation_complete ();
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nValue ranges after VRP:\n\n");
+ m_vr_values->dump_all_value_ranges (dump_file);
+ fprintf (dump_file, "\n");
+ }
+
+ /* Set value range to non pointer SSA_NAMEs. */
+ for (i = 0; i < num_ssa_names; i++)
+ {
+ tree name = ssa_name (i);
+ if (!name)
+ continue;
+
+ const value_range_equiv *vr = m_vr_values->get_value_range (name);
+ if (!name || !vr->constant_p ())
+ continue;
+
+ if (POINTER_TYPE_P (TREE_TYPE (name))
+ && range_includes_zero_p (vr) == 0)
+ set_ptr_nonnull (name);
+ else if (!POINTER_TYPE_P (TREE_TYPE (name)))
+ set_range_info (name, *vr);
+ }
+}
+
class vrp_folder : public substitute_and_fold_engine
{
public:
@@ -4010,23 +4069,16 @@ class vrp_folder : public substitute_and_fold_engine
: substitute_and_fold_engine (/* Fold all stmts. */ true),
m_vr_values (v), simplifier (v)
{ }
- bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
+private:
tree value_of_expr (tree name, gimple *stmt) OVERRIDE
{
return m_vr_values->value_of_expr (name, stmt);
}
- class vr_values *m_vr_values;
-
-private:
+ bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
bool fold_predicate_in (gimple_stmt_iterator *);
- /* Delegators. */
- tree vrp_evaluate_conditional (tree_code code, tree op0,
- tree op1, gimple *stmt)
- { return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
- bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
- { return simplifier.simplify (gsi); }
+ vr_values *m_vr_values;
simplify_using_ranges simplifier;
};
@@ -4045,16 +4097,16 @@ vrp_folder::fold_predicate_in (gimple_stmt_iterator *si)
&& TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
{
assignment_p = true;
- val = vrp_evaluate_conditional (gimple_assign_rhs_code (stmt),
- gimple_assign_rhs1 (stmt),
- gimple_assign_rhs2 (stmt),
- stmt);
+ val = simplifier.vrp_evaluate_conditional (gimple_assign_rhs_code (stmt),
+ gimple_assign_rhs1 (stmt),
+ gimple_assign_rhs2 (stmt),
+ stmt);
}
else if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
- val = vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- gimple_cond_lhs (cond_stmt),
- gimple_cond_rhs (cond_stmt),
- stmt);
+ val = simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ gimple_cond_lhs (cond_stmt),
+ gimple_cond_rhs (cond_stmt),
+ stmt);
else
return false;
@@ -4100,39 +4152,130 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si)
if (fold_predicate_in (si))
return true;
- return simplify_stmt_using_ranges (si);
+ return simplifier.simplify (si);
}
-/* Return the LHS of any ASSERT_EXPR where OP appears as the first
- argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
- BB. If no such ASSERT_EXPR is found, return OP. */
+/* Blocks which have more than one predecessor and more than
+ one successor present jump threading opportunities, i.e.,
+ when the block is reached from a specific predecessor, we
+ may be able to determine which of the outgoing edges will
+ be traversed. When this optimization applies, we are able
+ to avoid conditionals at runtime and we may expose secondary
+ optimization opportunities.
-static tree
-lhs_of_dominating_assert (tree op, basic_block bb, gimple *stmt)
+ This class is effectively a driver for the generic jump
+ threading code. It basically just presents the generic code
+ with edges that may be suitable for jump threading.
+
+ Unlike DOM, we do not iterate VRP if jump threading was successful.
+ While iterating may expose new opportunities for VRP, it is expected
+ those opportunities would be very limited and the compile time cost
+ to expose those opportunities would be significant.
+
+ As jump threading opportunities are discovered, they are registered
+ for later realization. */
+
+class vrp_jump_threader : public dom_walker
{
- imm_use_iterator imm_iter;
- gimple *use_stmt;
- use_operand_p use_p;
+public:
+ vrp_jump_threader (struct function *, vr_values *);
+ ~vrp_jump_threader ();
- if (TREE_CODE (op) == SSA_NAME)
+ void thread_jumps ()
+ {
+ walk (m_fun->cfg->x_entry_block_ptr);
+ }
+
+private:
+ static tree simplify_stmt (gimple *stmt, gimple *within_stmt,
+ avail_exprs_stack *, basic_block);
+ virtual edge before_dom_children (basic_block);
+ virtual void after_dom_children (basic_block);
+
+ function *m_fun;
+ vr_values *m_vr_values;
+ const_and_copies *m_const_and_copies;
+ avail_exprs_stack *m_avail_exprs_stack;
+ hash_table<expr_elt_hasher> *m_avail_exprs;
+ gcond *m_dummy_cond;
+};
+
+vrp_jump_threader::vrp_jump_threader (struct function *fun, vr_values *v)
+ : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS)
+{
+ /* Ugh. When substituting values earlier in this pass we can wipe
+ the dominance information. So rebuild the dominator information
+ as we need it within the jump threading code. */
+ calculate_dominance_info (CDI_DOMINATORS);
+
+ /* We do not allow VRP information to be used for jump threading
+ across a back edge in the CFG. Otherwise it becomes too
+ difficult to avoid eliminating loop exit tests. Of course
+ EDGE_DFS_BACK is not accurate at this time so we have to
+ recompute it. */
+ mark_dfs_back_edges ();
+
+ /* Allocate our unwinder stack to unwind any temporary equivalences
+ that might be recorded. */
+ m_const_and_copies = new const_and_copies ();
+
+ m_dummy_cond = NULL;
+ m_fun = fun;
+ m_vr_values = v;
+ m_avail_exprs = new hash_table<expr_elt_hasher> (1024);
+ m_avail_exprs_stack = new avail_exprs_stack (m_avail_exprs);
+}
+
+vrp_jump_threader::~vrp_jump_threader ()
+{
+ /* We do not actually update the CFG or SSA graphs at this point as
+ ASSERT_EXPRs are still in the IL and cfg cleanup code does not
+ yet handle ASSERT_EXPRs gracefully. */
+ delete m_const_and_copies;
+ delete m_avail_exprs;
+ delete m_avail_exprs_stack;
+}
+
+/* Called before processing dominator children of BB. We want to look
+ at ASSERT_EXPRs and record information from them in the appropriate
+ tables.
+
+ We could look at other statements here. It's not seen as likely
+ to significantly increase the jump threads we discover. */
+
+edge
+vrp_jump_threader::before_dom_children (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+
+ m_avail_exprs_stack->push_marker ();
+ m_const_and_copies->push_marker ();
+ for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
+ gimple *stmt = gsi_stmt (gsi);
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
{
- use_stmt = USE_STMT (use_p);
- if (use_stmt != stmt
- && gimple_assign_single_p (use_stmt)
- && TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ASSERT_EXPR
- && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == op
- && dominated_by_p (CDI_DOMINATORS, bb, gimple_bb (use_stmt)))
- return gimple_assign_lhs (use_stmt);
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ tree cond = TREE_OPERAND (rhs1, 1);
+ tree inverted = invert_truthvalue (cond);
+ vec<cond_equivalence> p;
+ p.create (3);
+ record_conditions (&p, cond, inverted);
+ for (unsigned int i = 0; i < p.length (); i++)
+ m_avail_exprs_stack->record_cond (&p[i]);
+
+ tree lhs = gimple_assign_lhs (stmt);
+ m_const_and_copies->record_const_or_copy (lhs,
+ TREE_OPERAND (rhs1, 0));
+ p.release ();
+ continue;
}
+ break;
}
- return op;
+ return NULL;
}
-/* A hack. */
-static class vr_values *x_vr_values;
-
/* A trivial wrapper so that we can present the generic jump threading
code with a simple API for simplifying statements. STMT is the
statement we want to simplify, WITHIN_STMT provides the location
@@ -4141,17 +4284,18 @@ static class vr_values *x_vr_values;
?? This should be cleaned up. There's a virtually identical copy
of this function in tree-ssa-dom.c. */
-static tree
-simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
- class avail_exprs_stack *avail_exprs_stack ATTRIBUTE_UNUSED,
- basic_block bb)
+tree
+vrp_jump_threader::simplify_stmt (gimple *stmt,
+ gimple *within_stmt,
+ avail_exprs_stack *avail_exprs_stack,
+ basic_block bb)
{
/* First see if the conditional is in the hash table. */
tree cached_lhs = avail_exprs_stack->lookup_avail_expr (stmt, false, true);
if (cached_lhs && is_gimple_min_invariant (cached_lhs))
return cached_lhs;
- vr_values *vr_values = x_vr_values;
+ class vr_values *vr_values = x_vr_values;
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
tree op0 = gimple_cond_lhs (cond_stmt);
@@ -4199,202 +4343,26 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
return NULL_TREE;
}
-class vrp_dom_walker : public dom_walker
-{
-public:
- vrp_dom_walker (cdi_direction direction,
- class const_and_copies *const_and_copies,
- class avail_exprs_stack *avail_exprs_stack)
- : dom_walker (direction, REACHABLE_BLOCKS),
- m_const_and_copies (const_and_copies),
- m_avail_exprs_stack (avail_exprs_stack),
- m_dummy_cond (NULL) {}
-
- virtual edge before_dom_children (basic_block);
- virtual void after_dom_children (basic_block);
-
- class vr_values *vr_values;
-
-private:
- class const_and_copies *m_const_and_copies;
- class avail_exprs_stack *m_avail_exprs_stack;
-
- gcond *m_dummy_cond;
-
-};
-
-/* Called before processing dominator children of BB. We want to look
- at ASSERT_EXPRs and record information from them in the appropriate
- tables.
-
- We could look at other statements here. It's not seen as likely
- to significantly increase the jump threads we discover. */
-
-edge
-vrp_dom_walker::before_dom_children (basic_block bb)
-{
- gimple_stmt_iterator gsi;
-
- m_avail_exprs_stack->push_marker ();
- m_const_and_copies->push_marker ();
- for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
- {
- tree rhs1 = gimple_assign_rhs1 (stmt);
- tree cond = TREE_OPERAND (rhs1, 1);
- tree inverted = invert_truthvalue (cond);
- vec<cond_equivalence> p;
- p.create (3);
- record_conditions (&p, cond, inverted);
- for (unsigned int i = 0; i < p.length (); i++)
- m_avail_exprs_stack->record_cond (&p[i]);
-
- tree lhs = gimple_assign_lhs (stmt);
- m_const_and_copies->record_const_or_copy (lhs,
- TREE_OPERAND (rhs1, 0));
- p.release ();
- continue;
- }
- break;
- }
- return NULL;
-}
-
/* Called after processing dominator children of BB. This is where we
actually call into the threader. */
void
-vrp_dom_walker::after_dom_children (basic_block bb)
+vrp_jump_threader::after_dom_children (basic_block bb)
{
if (!m_dummy_cond)
m_dummy_cond = gimple_build_cond (NE_EXPR,
integer_zero_node, integer_zero_node,
NULL, NULL);
- x_vr_values = vr_values;
+ x_vr_values = m_vr_values;
thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
m_avail_exprs_stack, NULL,
- simplify_stmt_for_jump_threading);
+ simplify_stmt);
x_vr_values = NULL;
m_avail_exprs_stack->pop_to_marker ();
m_const_and_copies->pop_to_marker ();
}
-/* Blocks which have more than one predecessor and more than
- one successor present jump threading opportunities, i.e.,
- when the block is reached from a specific predecessor, we
- may be able to determine which of the outgoing edges will
- be traversed. When this optimization applies, we are able
- to avoid conditionals at runtime and we may expose secondary
- optimization opportunities.
-
- This routine is effectively a driver for the generic jump
- threading code. It basically just presents the generic code
- with edges that may be suitable for jump threading.
-
- Unlike DOM, we do not iterate VRP if jump threading was successful.
- While iterating may expose new opportunities for VRP, it is expected
- those opportunities would be very limited and the compile time cost
- to expose those opportunities would be significant.
-
- As jump threading opportunities are discovered, they are registered
- for later realization. */
-
-static void
-identify_jump_threads (struct function *fun, class vr_values *vr_values)
-{
- /* Ugh. When substituting values earlier in this pass we can
- wipe the dominance information. So rebuild the dominator
- information as we need it within the jump threading code. */
- calculate_dominance_info (CDI_DOMINATORS);
-
- /* We do not allow VRP information to be used for jump threading
- across a back edge in the CFG. Otherwise it becomes too
- difficult to avoid eliminating loop exit tests. Of course
- EDGE_DFS_BACK is not accurate at this time so we have to
- recompute it. */
- mark_dfs_back_edges ();
-
- /* Allocate our unwinder stack to unwind any temporary equivalences
- that might be recorded. */
- const_and_copies *equiv_stack = new const_and_copies ();
-
- hash_table<expr_elt_hasher> *avail_exprs
- = new hash_table<expr_elt_hasher> (1024);
- avail_exprs_stack *avail_exprs_stack
- = new class avail_exprs_stack (avail_exprs);
-
- vrp_dom_walker walker (CDI_DOMINATORS, equiv_stack, avail_exprs_stack);
- walker.vr_values = vr_values;
- walker.walk (fun->cfg->x_entry_block_ptr);
-
- /* We do not actually update the CFG or SSA graphs at this point as
- ASSERT_EXPRs are still in the IL and cfg cleanup code does not yet
- handle ASSERT_EXPRs gracefully. */
- delete equiv_stack;
- delete avail_exprs;
- delete avail_exprs_stack;
-}
-
-/* Traverse all the blocks folding conditionals with known ranges. */
-
-void
-vrp_prop::vrp_finalize (vrp_folder *folder, bool warn_array_bounds_p)
-{
- size_t i;
-
- /* We have completed propagating through the lattice. */
- vr_values.set_lattice_propagation_complete ();
-
- if (dump_file)
- {
- fprintf (dump_file, "\nValue ranges after VRP:\n\n");
- vr_values.dump_all_value_ranges (dump_file);
- fprintf (dump_file, "\n");
- }
-
- /* Set value range to non pointer SSA_NAMEs. */
- for (i = 0; i < num_ssa_names; i++)
- {
- tree name = ssa_name (i);
- if (!name)
- continue;
-
- const value_range_equiv *vr = get_value_range (name);
- if (!name || !vr->constant_p ())
- continue;
-
- if (POINTER_TYPE_P (TREE_TYPE (name))
- && range_includes_zero_p (vr) == 0)
- set_ptr_nonnull (name);
- else if (!POINTER_TYPE_P (TREE_TYPE (name)))
- set_range_info (name, *vr);
- }
-
- /* If we're checking array refs, we want to merge information on
- the executability of each edge between vrp_folder and the
- check_array_bounds_dom_walker: each can clear the
- EDGE_EXECUTABLE flag on edges, in different ways.
-
- Hence, if we're going to call check_all_array_refs, set
- the flag on every edge now, rather than in
- check_array_bounds_dom_walker's ctor; vrp_folder may clear
- it from some edges. */
- if (warn_array_bounds && warn_array_bounds_p)
- set_all_edges_as_executable (fun);
-
- folder->substitute_and_fold ();
-
- if (warn_array_bounds && warn_array_bounds_p)
- {
- array_bounds_checker array_checker (fun, &vr_values);
- array_checker.check ();
- }
-}
-
/* STMT is a conditional at the end of a basic block.
If the conditional is of the form SSA_NAME op constant and the SSA_NAME
@@ -4503,7 +4471,6 @@ vrp_simplify_cond_using_ranges (vr_values *query, gcond *stmt)
static unsigned int
execute_vrp (struct function *fun, bool warn_array_bounds_p)
{
-
loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
scev_initialize ();
@@ -4511,7 +4478,7 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
/* ??? This ends up using stale EDGE_DFS_BACK for liveness computation.
Inserting assertions may split edges which will invalidate
EDGE_DFS_BACK. */
- vrp_insert assert_engine (fun);
+ vrp_asserts assert_engine (fun);
assert_engine.insert_range_assertions ();
threadedge_initialize_values ();
@@ -4519,17 +4486,41 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
/* For visiting PHI nodes we need EDGE_DFS_BACK computed. */
mark_dfs_back_edges ();
- class vrp_prop vrp_prop;
- vrp_prop.vrp_initialize (fun);
+ vr_values vrp_vr_values;
+
+ class vrp_prop vrp_prop (&vrp_vr_values);
+ vrp_prop.initialize (fun);
vrp_prop.ssa_propagate ();
+
/* Instantiate the folder here, so that edge cleanups happen at the
end of this function. */
- vrp_folder folder (&vrp_prop.vr_values);
- vrp_prop.vrp_finalize (&folder, warn_array_bounds_p);
+ vrp_folder folder (&vrp_vr_values);
+ vrp_prop.finalize ();
+
+ /* If we're checking array refs, we want to merge information on
+ the executability of each edge between vrp_folder and the
+ check_array_bounds_dom_walker: each can clear the
+ EDGE_EXECUTABLE flag on edges, in different ways.
+
+ Hence, if we're going to call check_all_array_refs, set
+ the flag on every edge now, rather than in
+ check_array_bounds_dom_walker's ctor; vrp_folder may clear
+ it from some edges. */
+ if (warn_array_bounds && warn_array_bounds_p)
+ set_all_edges_as_executable (fun);
+
+ folder.substitute_and_fold ();
+
+ if (warn_array_bounds && warn_array_bounds_p)
+ {
+ array_bounds_checker array_checker (fun, &vrp_vr_values);
+ array_checker.check ();
+ }
/* We must identify jump threading opportunities before we release
the datastructures built by VRP. */
- identify_jump_threads (fun, &vrp_prop.vr_values);
+ vrp_jump_threader threader (fun, &vrp_vr_values);
+ threader.thread_jumps ();
/* A comparison of an SSA_NAME against a constant where the SSA_NAME
was set by a type conversion can often be rewritten to use the
@@ -4543,7 +4534,7 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
{
gimple *last = last_stmt (bb);
if (last && gimple_code (last) == GIMPLE_COND)
- vrp_simplify_cond_using_ranges (&vrp_prop.vr_values,
+ vrp_simplify_cond_using_ranges (&vrp_vr_values,
as_a <gcond *> (last));
}
diff --git a/gcc/tree.c b/gcc/tree.c
index fa03d96..5fd9da3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -291,6 +291,7 @@ unsigned const char omp_clause_num_ops[] =
1, /* OMP_CLAUSE_COPYPRIVATE */
3, /* OMP_CLAUSE_LINEAR */
2, /* OMP_CLAUSE_ALIGNED */
+ 2, /* OMP_CLAUSE_ALLOCATE */
1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_NONTEMPORAL */
1, /* OMP_CLAUSE_UNIFORM */
@@ -375,6 +376,7 @@ const char * const omp_clause_code_name[] =
"copyprivate",
"linear",
"aligned",
+ "allocate",
"depend",
"nontemporal",
"uniform",
@@ -771,6 +773,33 @@ set_decl_section_name (tree node, const char *value)
snode->set_section (value);
}
+/* Set section name of NODE to match the section name of OTHER.
+
+ set_decl_section_name (decl, other) is equivalent to
+ set_decl_section_name (decl, DECL_SECTION_NAME (other)), but possibly more
+ efficient. */
+void
+set_decl_section_name (tree decl, const_tree other)
+{
+ struct symtab_node *other_node = symtab_node::get (other);
+ if (other_node)
+ {
+ struct symtab_node *decl_node;
+ if (VAR_P (decl))
+ decl_node = varpool_node::get_create (decl);
+ else
+ decl_node = cgraph_node::get_create (decl);
+ decl_node->set_section (*other_node);
+ }
+ else
+ {
+ struct symtab_node *decl_node = symtab_node::get (decl);
+ if (!decl_node)
+ return;
+ decl_node->set_section (NULL);
+ }
+}
+
/* Return TLS model of a variable NODE. */
enum tls_model
decl_tls_model (const_tree node)
@@ -835,6 +864,7 @@ tree_code_size (enum tree_code code)
case BOOLEAN_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
+ case OPAQUE_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
case NULLPTR_TYPE:
@@ -1212,7 +1242,7 @@ copy_node (tree node MEM_STAT_DECL)
SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
DECL_HAS_VALUE_EXPR_P (t) = 1;
}
- /* DECL_DEBUG_EXPR is copied explicitely by callers. */
+ /* DECL_DEBUG_EXPR is copied explicitly by callers. */
if (VAR_P (node))
{
DECL_HAS_DEBUG_EXPR_P (t) = 0;
@@ -1725,8 +1755,15 @@ wide_int_to_tree (tree type, const poly_wide_int_ref &value)
return build_poly_int_cst (type, value);
}
-void
-cache_integer_cst (tree t)
+/* Insert INTEGER_CST T into a cache of integer constants. And return
+ the cached constant (which may or may not be T). If MIGHT_DUPLICATE
+ is false, and T falls into the type's 'smaller values' range, there
+ cannot be an existing entry. Otherwise, if MIGHT_DUPLICATE is true,
+ or the value is large, should an existing entry exist, it is
+ returned (rather than inserting T). */
+
+tree
+cache_integer_cst (tree t, bool might_duplicate ATTRIBUTE_UNUSED)
{
tree type = TREE_TYPE (t);
int ix = -1;
@@ -1735,20 +1772,25 @@ cache_integer_cst (tree t)
gcc_assert (!TREE_OVERFLOW (t));
+ /* The caching indices here must match those in
+ wide_int_to_type_1. */
switch (TREE_CODE (type))
{
case NULLPTR_TYPE:
- gcc_assert (integer_zerop (t));
+ gcc_checking_assert (integer_zerop (t));
/* Fallthru. */
case POINTER_TYPE:
case REFERENCE_TYPE:
- /* Cache NULL pointer. */
- if (integer_zerop (t))
- {
- limit = 1;
+ {
+ if (integer_zerop (t))
ix = 0;
- }
+ else if (integer_onep (t))
+ ix = 2;
+
+ if (ix >= 0)
+ limit = 3;
+ }
break;
case BOOLEAN_TYPE:
@@ -1815,21 +1857,32 @@ cache_integer_cst (tree t)
TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
}
- gcc_assert (TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) == NULL_TREE);
- TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+ if (tree r = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix))
+ {
+ gcc_checking_assert (might_duplicate);
+ t = r;
+ }
+ else
+ TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
}
else
{
/* Use the cache of larger shared ints. */
tree *slot = int_cst_hash_table->find_slot (t, INSERT);
- /* If there is already an entry for the number verify it's the
- same. */
- if (*slot)
- gcc_assert (wi::to_wide (tree (*slot)) == wi::to_wide (t));
+ if (tree r = *slot)
+ {
+ /* If there is already an entry for the number verify it's the
+ same value. */
+ gcc_checking_assert (wi::to_wide (tree (r)) == wi::to_wide (t));
+ /* And return the cached value. */
+ t = r;
+ }
else
/* Otherwise insert this one into the hash table. */
*slot = t;
}
+
+ return t;
}
@@ -2132,7 +2185,7 @@ build_constructor_from_vec (tree type, const vec<tree, va_gc> *vals)
{
vec<constructor_elt, va_gc> *v = NULL;
- for (tree t : *vals)
+ for (tree t : vals)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
return build_constructor (type, v);
@@ -2248,6 +2301,22 @@ build_real_from_int_cst (tree type, const_tree i)
return v;
}
+/* Return a new REAL_CST node whose type is TYPE
+ and whose value is the integer value I which has sign SGN. */
+
+tree
+build_real_from_wide (tree type, const wide_int_ref &i, signop sgn)
+{
+ REAL_VALUE_TYPE d;
+
+ /* Clear all bits of the real value type so that we can later do
+ bitwise comparisons to see if two values are the same. */
+ memset (&d, 0, sizeof d);
+
+ real_from_integer (&d, TYPE_MODE (type), i, sgn);
+ return build_real (type, d);
+}
+
/* Return a newly constructed STRING_CST node whose value is the LEN
characters at STR when STR is nonnull, or all zeros otherwise.
Note that for a C string literal, LEN should include the trailing NUL.
@@ -3414,7 +3483,17 @@ array_type_nelts (const_tree type)
/* TYPE_MAX_VALUE may not be set if the array has unknown length. */
if (!max)
- return error_mark_node;
+ {
+ /* zero sized arrays are represented from C FE as complete types with
+ NULL TYPE_MAX_VALUE and zero TYPE_SIZE, while C++ FE represents
+ them as min 0, max -1. */
+ if (COMPLETE_TYPE_P (type)
+ && integer_zerop (TYPE_SIZE (type))
+ && integer_zerop (min))
+ return build_int_cst (TREE_TYPE (min), -1);
+
+ return error_mark_node;
+ }
return (integer_zerop (min)
? max
@@ -3893,6 +3972,7 @@ type_contains_placeholder_1 (const_tree type)
switch (TREE_CODE (type))
{
case VOID_TYPE:
+ case OPAQUE_TYPE:
case COMPLEX_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
@@ -7021,6 +7101,7 @@ type_cache_hasher::equal (type_hash *a, type_hash *b)
switch (TREE_CODE (a->type))
{
case VOID_TYPE:
+ case OPAQUE_TYPE:
case COMPLEX_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
@@ -10514,7 +10595,7 @@ set_call_expr_flags (tree decl, int flags)
if (flags & ECF_RET1)
DECL_ATTRIBUTES (decl)
= tree_cons (get_identifier ("fn spec"),
- build_tree_list (NULL_TREE, build_string (1, "1")),
+ build_tree_list (NULL_TREE, build_string (2, "1 ")),
DECL_ATTRIBUTES (decl));
if ((flags & ECF_TM_PURE) && flag_tm)
apply_tm_attr (decl, get_identifier ("transaction_pure"));
@@ -10576,10 +10657,10 @@ build_common_builtin_nodes (void)
if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
- "memcpy", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
+ "memcpy", ECF_NOTHROW | ECF_LEAF);
if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
- "memmove", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
+ "memmove", ECF_NOTHROW | ECF_LEAF);
}
if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
@@ -10597,7 +10678,7 @@ build_common_builtin_nodes (void)
ptr_type_node, integer_type_node,
size_type_node, NULL_TREE);
local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
- "memset", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
+ "memset", ECF_NOTHROW | ECF_LEAF);
}
/* If we're checking the stack, `alloca' can throw. */
@@ -10652,6 +10733,12 @@ build_common_builtin_nodes (void)
ftype = build_function_type_list (void_type_node,
ptr_type_node, ptr_type_node, NULL_TREE);
+ if (!builtin_decl_explicit_p (BUILT_IN_CLEAR_CACHE))
+ local_define_builtin ("__builtin___clear_cache", ftype,
+ BUILT_IN_CLEAR_CACHE,
+ "__clear_cache",
+ ECF_NOTHROW);
+
local_define_builtin ("__builtin_nonlocal_goto", ftype,
BUILT_IN_NONLOCAL_GOTO,
"__builtin_nonlocal_goto",
@@ -10926,8 +11013,15 @@ build_truth_vector_type_for_mode (poly_uint64 nunits, machine_mode mask_mode)
{
gcc_assert (mask_mode != BLKmode);
- poly_uint64 vsize = GET_MODE_BITSIZE (mask_mode);
- unsigned HOST_WIDE_INT esize = vector_element_size (vsize, nunits);
+ unsigned HOST_WIDE_INT esize;
+ if (VECTOR_MODE_P (mask_mode))
+ {
+ poly_uint64 vsize = GET_MODE_BITSIZE (mask_mode);
+ esize = vector_element_size (vsize, nunits);
+ }
+ else
+ esize = 1;
+
tree bool_type = build_nonstandard_boolean_type (esize);
return make_vector_type (bool_type, nunits, mask_mode);
@@ -12206,6 +12300,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_ALLOCATE:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
case OMP_CLAUSE_MAP:
@@ -12515,8 +12610,40 @@ tree_nonartificial_location (tree exp)
return EXPR_LOCATION (exp);
}
+/* Return the location into which EXP has been inlined. Analogous
+ to tree_nonartificial_location() above but not limited to artificial
+ functions declared inline. If SYSTEM_HEADER is true, return
+ the macro expansion point of the location if it's in a system header */
-/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
+location_t
+tree_inlined_location (tree exp, bool system_header /* = true */)
+{
+ location_t loc = UNKNOWN_LOCATION;
+
+ tree block = TREE_BLOCK (exp);
+
+ while (block && TREE_CODE (block) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (block))
+ {
+ tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+ if (TREE_CODE (ao) == FUNCTION_DECL)
+ loc = BLOCK_SOURCE_LOCATION (block);
+ else if (TREE_CODE (ao) != BLOCK)
+ break;
+
+ block = BLOCK_SUPERCONTEXT (block);
+ }
+
+ if (loc == UNKNOWN_LOCATION)
+ loc = EXPR_LOCATION (exp);
+
+ if (system_header)
+ return expansion_point_location_if_in_system_header (loc);
+
+ return loc;
+}
+
+/* These are the hash table functions for the hash table of OPTIMIZATION_NODE
nodes. */
/* Return the hash code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
@@ -13651,9 +13778,9 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
{
gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
- special_array_member arkbuf;
+ special_array_member sambuf;
if (!sam)
- sam = &arkbuf;
+ sam = &sambuf;
*sam = special_array_member::none;
/* The object/argument referenced by the COMPONENT_REF and its type. */
@@ -13667,7 +13794,13 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
{
tree memtype = TREE_TYPE (member);
if (TREE_CODE (memtype) != ARRAY_TYPE)
- return memsize;
+ /* DECL_SIZE may be less than TYPE_SIZE in C++ when referring
+ to the type of a class with a virtual base which doesn't
+ reflect the size of the virtual's members (see pr97595).
+ If that's the case fail for now and implement something
+ more robust in the future. */
+ return (tree_int_cst_equal (memsize, TYPE_SIZE_UNIT (memtype))
+ ? memsize : NULL_TREE);
bool trailing = array_at_struct_end_p (ref);
bool zero_length = integer_zerop (memsize);
@@ -14983,6 +15116,10 @@ maybe_wrap_with_location (tree expr, location_t loc)
if (EXCEPTIONAL_CLASS_P (expr))
return expr;
+ /* Compiler-generated temporary variables don't need a wrapper. */
+ if (DECL_P (expr) && DECL_ARTIFICIAL (expr) && DECL_IGNORED_P (expr))
+ return expr;
+
/* If any auto_suppress_location_wrappers are active, don't create
wrappers. */
if (suppress_location_wrappers > 0)
@@ -15074,22 +15211,22 @@ get_nonnull_args (const_tree fntype)
/* Returns true if TYPE is a type where it and all of its subobjects
(recursively) are of structure, union, or array type. */
-static bool
-default_is_empty_type (tree type)
+bool
+is_empty_type (const_tree type)
{
if (RECORD_OR_UNION_TYPE_P (type))
{
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
&& !DECL_PADDING_P (field)
- && !default_is_empty_type (TREE_TYPE (field)))
+ && !is_empty_type (TREE_TYPE (field)))
return false;
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
return (integer_minus_onep (array_type_nelts (type))
|| TYPE_DOMAIN (type) == NULL_TREE
- || default_is_empty_type (TREE_TYPE (type)));
+ || is_empty_type (TREE_TYPE (type)));
return false;
}
@@ -15108,7 +15245,7 @@ default_is_empty_record (const_tree type)
if (TREE_ADDRESSABLE (type))
return false;
- return default_is_empty_type (TYPE_MAIN_VARIANT (type));
+ return is_empty_type (TYPE_MAIN_VARIANT (type));
}
/* Determine whether TYPE is a structure with a flexible array member,
@@ -15281,6 +15418,75 @@ verify_type_context (location_t loc, type_context_kind context,
|| targetm.verify_type_context (loc, context, type, silent_p));
}
+/* Return that NEW_ASM and DELETE_ASM name a valid pair of new and
+ delete operators. */
+
+bool
+valid_new_delete_pair_p (tree new_asm, tree delete_asm)
+{
+ const char *new_name = IDENTIFIER_POINTER (new_asm);
+ const char *delete_name = IDENTIFIER_POINTER (delete_asm);
+ unsigned int new_len = IDENTIFIER_LENGTH (new_asm);
+ unsigned int delete_len = IDENTIFIER_LENGTH (delete_asm);
+
+ if (new_len < 5 || delete_len < 6)
+ return false;
+ if (new_name[0] == '_')
+ ++new_name, --new_len;
+ if (new_name[0] == '_')
+ ++new_name, --new_len;
+ if (delete_name[0] == '_')
+ ++delete_name, --delete_len;
+ if (delete_name[0] == '_')
+ ++delete_name, --delete_len;
+ if (new_len < 4 || delete_len < 5)
+ return false;
+ /* *_len is now just the length after initial underscores. */
+ if (new_name[0] != 'Z' || new_name[1] != 'n')
+ return false;
+ if (delete_name[0] != 'Z' || delete_name[1] != 'd')
+ return false;
+ /* _Znw must match _Zdl, _Zna must match _Zda. */
+ if ((new_name[2] != 'w' || delete_name[2] != 'l')
+ && (new_name[2] != 'a' || delete_name[2] != 'a'))
+ return false;
+ /* 'j', 'm' and 'y' correspond to size_t. */
+ if (new_name[3] != 'j' && new_name[3] != 'm' && new_name[3] != 'y')
+ return false;
+ if (delete_name[3] != 'P' || delete_name[4] != 'v')
+ return false;
+ if (new_len == 4
+ || (new_len == 18 && !memcmp (new_name + 4, "RKSt9nothrow_t", 14)))
+ {
+ /* _ZnXY or _ZnXYRKSt9nothrow_t matches
+ _ZdXPv, _ZdXPvY and _ZdXPvRKSt9nothrow_t. */
+ if (delete_len == 5)
+ return true;
+ if (delete_len == 6 && delete_name[5] == new_name[3])
+ return true;
+ if (delete_len == 19 && !memcmp (delete_name + 5, "RKSt9nothrow_t", 14))
+ return true;
+ }
+ else if ((new_len == 19 && !memcmp (new_name + 4, "St11align_val_t", 15))
+ || (new_len == 33
+ && !memcmp (new_name + 4, "St11align_val_tRKSt9nothrow_t", 29)))
+ {
+ /* _ZnXYSt11align_val_t or _ZnXYSt11align_val_tRKSt9nothrow_t matches
+ _ZdXPvSt11align_val_t or _ZdXPvYSt11align_val_t or or
+ _ZdXPvSt11align_val_tRKSt9nothrow_t. */
+ if (delete_len == 20 && !memcmp (delete_name + 5, "St11align_val_t", 15))
+ return true;
+ if (delete_len == 21
+ && delete_name[5] == new_name[3]
+ && !memcmp (delete_name + 6, "St11align_val_t", 15))
+ return true;
+ if (delete_len == 34
+ && !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29))
+ return true;
+ }
+ return false;
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/tree.def b/gcc/tree.def
index 6c53fe1..11f5a98 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -250,6 +250,12 @@ DEFTREECODE (METHOD_TYPE, "method_type", tcc_type, 0)
layout_type does not know how to lay this out,
so the front-end must do so manually. */
DEFTREECODE (LANG_TYPE, "lang_type", tcc_type, 0)
+
+/* This is for types that will use MODE_OPAQUE in the back end. They are meant
+ to be able to go in a register of some sort but are explicitly not to be
+ converted or operated on like INTEGER_TYPE. They will have size and
+ alignment information only. */
+DEFTREECODE (OPAQUE_TYPE, "opaque_type", tcc_type, 0)
/* Expressions */
@@ -1359,6 +1365,8 @@ DEFTREECODE (WIDEN_MULT_MINUS_EXPR, "widen_mult_minus_expr", tcc_expression, 3)
the first argument from type t1 to type t2, and then shifting it
by the second argument. */
DEFTREECODE (WIDEN_LSHIFT_EXPR, "widen_lshift_expr", tcc_binary, 2)
+DEFTREECODE (WIDEN_PLUS_EXPR, "widen_plus_expr", tcc_binary, 2)
+DEFTREECODE (WIDEN_MINUS_EXPR, "widen_minus_expr", tcc_binary, 2)
/* Widening vector multiplication.
The two operands are vectors with N elements of size S. Multiplying the
@@ -1423,6 +1431,10 @@ DEFTREECODE (VEC_PACK_FLOAT_EXPR, "vec_pack_float_expr", tcc_binary, 2)
*/
DEFTREECODE (VEC_WIDEN_LSHIFT_HI_EXPR, "widen_lshift_hi_expr", tcc_binary, 2)
DEFTREECODE (VEC_WIDEN_LSHIFT_LO_EXPR, "widen_lshift_lo_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_PLUS_HI_EXPR, "widen_plus_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_PLUS_LO_EXPR, "widen_plus_lo_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_MINUS_HI_EXPR, "widen_minus_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_MINUS_LO_EXPR, "widen_minus_lo_expr", tcc_binary, 2)
/* PREDICT_EXPR. Specify hint for branch prediction. The
PREDICT_EXPR_PREDICTOR specify predictor and PREDICT_EXPR_OUTCOME the
diff --git a/gcc/tree.h b/gcc/tree.h
index f43ac9f..d366ffd 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -625,6 +625,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define FUNC_OR_METHOD_TYPE_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_TYPE || TREE_CODE (NODE) == METHOD_TYPE)
+#define OPAQUE_TYPE_P(NODE) \
+ (TREE_CODE (NODE) == OPAQUE_TYPE)
+
/* Define many boolean fields that all tree nodes have. */
/* In VAR_DECL, PARM_DECL and RESULT_DECL nodes, nonzero means address
@@ -1214,7 +1217,7 @@ get_expr_source_range (tree expr)
extern void protected_set_expr_location (tree, location_t);
extern void protected_set_expr_location_if_unset (tree, location_t);
-extern tree maybe_wrap_with_location (tree, location_t);
+WARN_UNUSED_RESULT extern tree maybe_wrap_with_location (tree, location_t);
extern int suppress_location_wrappers;
@@ -1731,6 +1734,16 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1)
+#define OMP_CLAUSE_ALLOCATE_ALLOCATOR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 1)
+
+/* True if an ALLOCATE clause was present on a combined or composite
+ construct and the code for splitting the clauses has already performed
+ checking if the listed variable has explicit privatization on the
+ construct. */
+#define OMP_CLAUSE_ALLOCATE_COMBINED(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE)->base.public_flag)
+
#define OMP_CLAUSE_NUM_TEAMS_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TEAMS), 0)
@@ -1974,8 +1987,10 @@ class auto_suppress_location_wrappers
so they must be checked as well. */
#define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type_common.uid)
-/* Type size in bits as a tree expression. Need not be constant
- and may be null. */
+/* Type size in bits as a tree expression. Need not be constant and may
+ be greater than TYPE_SIZE for a C++ FIELD_DECL representing a base
+ class subobject with its own virtual base classes (which are laid out
+ separately). */
#define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type_common.size)
/* Likewise, type size in bytes. */
#define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type_common.size_unit)
@@ -2446,11 +2461,12 @@ extern tree vector_element_bits_tree (const_tree);
#define DECL_SOURCE_FILE(NODE) LOCATION_FILE (DECL_SOURCE_LOCATION (NODE))
#define DECL_SOURCE_LINE(NODE) LOCATION_LINE (DECL_SOURCE_LOCATION (NODE))
#define DECL_SOURCE_COLUMN(NODE) LOCATION_COLUMN (DECL_SOURCE_LOCATION (NODE))
-/* This accessor returns TRUE if the decl it operates on was created
- by a front-end or back-end rather than by user code. In this case
- builtin-ness is indicated by source location. */
-#define DECL_IS_BUILTIN(DECL) \
- (LOCATION_LOCUS (DECL_SOURCE_LOCATION (DECL)) <= BUILTINS_LOCATION)
+/* This decl was created by a front-end or back-end rather than by
+ user code, and has not been explicitly declared by the user -- when
+ that happens the source location is updated to the user's
+ source. This includes decls with no location (!). */
+#define DECL_IS_UNDECLARED_BUILTIN(DECL) \
+ (DECL_SOURCE_LOCATION (DECL) <= BUILTINS_LOCATION)
/* For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
@@ -2507,29 +2523,34 @@ extern tree vector_element_bits_tree (const_tree);
#define DECL_INITIAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.initial)
/* Holds the size of the datum, in bits, as a tree expression.
- Need not be constant and may be null. */
+ Need not be constant and may be null. May be less than TYPE_SIZE
+ for a C++ FIELD_DECL representing a base class subobject with its
+ own virtual base classes (which are laid out separately). */
#define DECL_SIZE(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.size)
/* Likewise for the size in bytes. */
#define DECL_SIZE_UNIT(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.size_unit)
+#define DECL_ALIGN_RAW(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.align)
/* Returns the alignment required for the datum, in bits. It must
be a power of two, but an "alignment" of zero is supported
(e.g. as "uninitialized" sentinel). */
-#define DECL_ALIGN(NODE) \
- (DECL_COMMON_CHECK (NODE)->decl_common.align \
- ? ((unsigned)1) << ((NODE)->decl_common.align - 1) : 0)
+#define DECL_ALIGN(NODE) \
+ (DECL_ALIGN_RAW (NODE) \
+ ? ((unsigned)1) << (DECL_ALIGN_RAW (NODE) - 1) : 0)
/* Specify that DECL_ALIGN(NODE) is X. */
#define SET_DECL_ALIGN(NODE, X) \
- (DECL_COMMON_CHECK (NODE)->decl_common.align = ffs_hwi (X))
+ (DECL_ALIGN_RAW (NODE) = ffs_hwi (X))
/* The minimum alignment necessary for the datum, in bits, without
warning. */
-#define DECL_WARN_IF_NOT_ALIGN(NODE) \
- (DECL_COMMON_CHECK (NODE)->decl_common.warn_if_not_align \
- ? ((unsigned)1) << ((NODE)->decl_common.warn_if_not_align - 1) : 0)
+#define DECL_WARN_IF_NOT_ALIGN_RAW(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.warn_if_not_align)
+#define DECL_WARN_IF_NOT_ALIGN(NODE) \
+ (DECL_WARN_IF_NOT_ALIGN_RAW (NODE) \
+ ? ((unsigned)1) << (DECL_WARN_IF_NOT_ALIGN_RAW (NODE) - 1) : 0)
/* Specify that DECL_WARN_IF_NOT_ALIGN(NODE) is X. */
-#define SET_DECL_WARN_IF_NOT_ALIGN(NODE, X) \
- (DECL_COMMON_CHECK (NODE)->decl_common.warn_if_not_align = ffs_hwi (X))
+#define SET_DECL_WARN_IF_NOT_ALIGN(NODE, X) \
+ (DECL_WARN_IF_NOT_ALIGN_RAW (NODE) = ffs_hwi (X))
/* The alignment of NODE, in bytes. */
#define DECL_ALIGN_UNIT(NODE) (DECL_ALIGN (NODE) / BITS_PER_UNIT)
@@ -2648,6 +2669,20 @@ extern tree vector_element_bits_tree (const_tree);
#define DECL_PRESERVE_P(DECL) \
DECL_COMMON_CHECK (DECL)->decl_common.preserve_flag
+/* Nonzero for a decl that is decorated with the "noinit" attribute.
+ decls with this attribute are placed into the ".noinit" section, so they are
+ not initialized by the target's startup code. */
+#define DECL_NOINIT_P(DECL) \
+ (DECL_P (DECL) \
+ && (lookup_attribute ("noinit", DECL_ATTRIBUTES (DECL)) != NULL_TREE))
+
+/* Nonzero for a decl that is decorated with the "persistent" attribute.
+ decls with this attribute are placed into the ".persistent" section, so they
+ are not initialized by the target's startup code. */
+#define DECL_PERSISTENT_P(DECL) \
+ (DECL_P (DECL) \
+ && (lookup_attribute ("persistent", DECL_ATTRIBUTES (DECL)) != NULL_TREE))
+
/* For function local variables of COMPLEX and VECTOR types,
indicates that the variable is not aliased, and that all
modifications to the variable have been adjusted so that
@@ -3849,7 +3884,7 @@ id_equal (const_tree id, const char *str)
inline bool
id_equal (const char *str, const_tree id)
{
- return !strcmp (str, IDENTIFIER_POINTER (id));
+ return id_equal (id, str);
}
/* Return the number of elements in the VECTOR_TYPE given by NODE. */
@@ -4270,6 +4305,7 @@ extern tree decl_comdat_group (const_tree);
extern tree decl_comdat_group_id (const_tree);
extern const char *decl_section_name (const_tree);
extern void set_decl_section_name (tree, const char *);
+extern void set_decl_section_name (tree, const_tree);
extern enum tls_model decl_tls_model (const_tree);
extern void set_decl_tls_model (tree, enum tls_model);
@@ -4419,6 +4455,7 @@ extern tree build_constructor_from_vec (tree, const vec<tree, va_gc> *);
extern tree build_constructor_va (tree, int, ...);
extern tree build_clobber (tree);
extern tree build_real_from_int_cst (tree, const_tree);
+extern tree build_real_from_wide (tree, const wide_int_ref &, signop);
extern tree build_complex (tree, tree, tree);
extern tree build_complex_inf (tree, bool);
extern tree build_each_one_cst (tree);
@@ -5108,7 +5145,7 @@ extern const_tree strip_invariant_refs (const_tree);
extern tree lhd_gcc_personality (void);
extern void assign_assembler_name_if_needed (tree);
extern bool warn_deprecated_use (tree, tree);
-extern void cache_integer_cst (tree);
+extern tree cache_integer_cst (tree, bool might_duplicate = false);
extern const char *combined_fn_name (combined_fn);
/* Compare and hash for any structure which begins with a canonical
@@ -5241,6 +5278,7 @@ extern tree tree_block (tree);
extern void tree_set_block (tree, tree);
extern location_t *block_nonartificial_location (tree);
extern location_t tree_nonartificial_location (tree);
+extern location_t tree_inlined_location (tree, bool = true);
extern tree block_ultimate_origin (const_tree);
extern tree get_binfo_at_offset (tree, poly_int64, tree);
extern bool virtual_method_call_p (const_tree, bool = false);
@@ -5318,6 +5356,7 @@ extern bool gimple_canonical_types_compatible_p (const_tree, const_tree,
extern bool type_with_interoperable_signedness (const_tree);
extern bitmap get_nonnull_args (const_tree);
extern int get_range_pos_neg (tree);
+extern bool valid_new_delete_pair_p (tree, tree);
/* Return simplified tree code of type that is used for canonical type
merging. */
@@ -5566,6 +5605,13 @@ is_lang_specific (const_tree t)
#define BUILTIN_VALID_P(FNCODE) \
(IN_RANGE ((int)FNCODE, ((int)BUILT_IN_NONE) + 1, ((int) END_BUILTINS) - 1))
+/* Obtain a pointer to the identifier string holding the asm name for
+ BUILTIN, a BUILT_IN code. This is handy if the target
+ mangles/overrides the function name that implements the
+ builtin. */
+#define BUILTIN_ASM_NAME_PTR(BUILTIN) \
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (builtin_decl_explicit (BUILTIN))))
+
/* Return the tree node for an explicit standard builtin function or NULL. */
static inline tree
builtin_decl_explicit (enum built_in_function fncode)
@@ -6220,6 +6266,7 @@ extern void gt_pch_nx (tree &);
extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
extern bool nonnull_arg_p (const_tree);
+extern bool is_empty_type (const_tree);
extern bool default_is_empty_record (const_tree);
extern bool flexible_array_type_p (const_tree);
extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree);
@@ -6267,9 +6314,8 @@ type_has_mode_precision_p (const_tree t)
/* Return true if a FUNCTION_DECL NODE is a GCC built-in function.
- Note that it is different from the DECL_IS_BUILTIN accessor. For
- instance, user declared prototypes of C library functions are not
- DECL_IS_BUILTIN but may be fndecl_built_in_p. */
+ Note that it is different from the DECL_IS_UNDECLARED_BUILTIN
+ accessor, as this is impervious to user declaration. */
inline bool
fndecl_built_in_p (const_tree node)
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 4d62234..1bc020e 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "builtins.h"
#include "target.h"
+#include "diagnostic-core.h"
/* Number of instrumented memory accesses in the current function. */
@@ -500,6 +501,11 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
continue;
else
{
+ if (fcode == BUILT_IN_ATOMIC_THREAD_FENCE)
+ warning_at (gimple_location (stmt), OPT_Wtsan,
+ "%qs is not supported with %qs", "atomic_thread_fence",
+ "-fsanitize=thread");
+
tree decl = builtin_decl_implicit (tsan_atomic_table[i].tsan_fcode);
if (decl == NULL_TREE)
return;
diff --git a/gcc/typeclass.h b/gcc/typeclass.h
index 434e6ac..b4e3dda2 100644
--- a/gcc/typeclass.h
+++ b/gcc/typeclass.h
@@ -37,7 +37,7 @@ enum type_class
function_type_class, method_type_class,
record_type_class, union_type_class,
array_type_class, string_type_class,
- lang_type_class
+ lang_type_class, opaque_type_class
};
#endif /* GCC_TYPECLASS_H */
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index acd8a0b..4c14a38 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -405,10 +405,12 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
/* We weren't able to determine the type name. */
tname = "<unknown>";
+ pp_quote (&pretty_name);
+
tree eltype = type;
if (pstyle == UBSAN_PRINT_POINTER)
{
- pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
+ pp_printf (&pretty_name, "%s%s%s%s%s%s%s",
TYPE_VOLATILE (type2) ? "volatile " : "",
TYPE_READONLY (type2) ? "const " : "",
TYPE_RESTRICT (type2) ? "restrict " : "",
@@ -420,14 +422,14 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
deref_depth == 0 ? "" : " ");
while (deref_depth-- > 0)
pp_star (&pretty_name);
- pp_quote (&pretty_name);
}
else if (pstyle == UBSAN_PRINT_ARRAY)
{
/* Pretty print the array dimensions. */
gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
tree t = type;
- pp_printf (&pretty_name, "'%s ", tname);
+ pp_string (&pretty_name, tname);
+ pp_space (&pretty_name);
while (deref_depth-- > 0)
pp_star (&pretty_name);
while (TREE_CODE (t) == ARRAY_TYPE)
@@ -453,13 +455,14 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
pp_right_bracket (&pretty_name);
t = TREE_TYPE (t);
}
- pp_quote (&pretty_name);
/* Save the tree with stripped types. */
eltype = t;
}
else
- pp_printf (&pretty_name, "'%s'", tname);
+ pp_string (&pretty_name, tname);
+
+ pp_quote (&pretty_name);
switch (TREE_CODE (eltype))
{
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 23ba48d..f9a948f 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -78,7 +78,7 @@ tree
range_query::value_of_expr (tree name, gimple *stmt)
{
tree t;
- value_range r;
+ int_range_max r;
if (!irange::supports_type_p (TREE_TYPE (name)))
return NULL_TREE;
@@ -99,7 +99,7 @@ tree
range_query::value_on_edge (edge e, tree name)
{
tree t;
- value_range r;
+ int_range_max r;
if (!irange::supports_type_p (TREE_TYPE (name)))
return NULL_TREE;
@@ -120,7 +120,7 @@ tree
range_query::value_of_stmt (gimple *stmt, tree name)
{
tree t;
- value_range r;
+ int_range_max r;
if (!name)
name = gimple_get_lhs (stmt);
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 7847104..2b82dfe 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -131,13 +131,14 @@ irange::copy_to_legacy (const irange &src)
set (src.tree_lower_bound (), src.tree_upper_bound ());
}
-// Swap min/max if they are out of order. Return TRUE if further
-// processing of the range is necessary, FALSE otherwise.
+// Swap MIN/MAX if they are out of order and adjust KIND appropriately.
-bool
-irange::swap_out_of_order_endpoints (tree &min, tree &max,
- value_range_kind &kind)
+static void
+swap_out_of_order_endpoints (tree &min, tree &max, value_range_kind &kind)
{
+ gcc_checking_assert (kind != VR_UNDEFINED);
+ if (kind == VR_VARYING)
+ return;
/* Wrong order for min and max, to swap them and the VR type we need
to adjust them. */
if (tree_int_cst_lt (max, min))
@@ -149,8 +150,8 @@ irange::swap_out_of_order_endpoints (tree &min, tree &max,
for VR_ANTI_RANGE empty range, so drop to varying as well. */
if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
{
- set_varying (TREE_TYPE (min));
- return false;
+ kind = VR_VARYING;
+ return;
}
one = build_int_cst (TREE_TYPE (min), 1);
@@ -163,12 +164,11 @@ irange::swap_out_of_order_endpoints (tree &min, tree &max,
to varying in this case. */
if (tree_int_cst_lt (max, min))
{
- set_varying (TREE_TYPE (min));
- return false;
+ kind = VR_VARYING;
+ return;
}
kind = kind == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
}
- return true;
}
void
@@ -248,38 +248,15 @@ irange::set (tree min, tree max, value_range_kind kind)
set_undefined ();
return;
}
- if (kind == VR_RANGE)
- {
- /* Convert POLY_INT_CST bounds into worst-case INTEGER_CST bounds. */
- if (POLY_INT_CST_P (min))
- {
- tree type_min = vrp_val_min (TREE_TYPE (min));
- widest_int lb
- = constant_lower_bound_with_limit (wi::to_poly_widest (min),
- wi::to_widest (type_min));
- min = wide_int_to_tree (TREE_TYPE (min), lb);
- }
- if (POLY_INT_CST_P (max))
- {
- tree type_max = vrp_val_max (TREE_TYPE (max));
- widest_int ub
- = constant_upper_bound_with_limit (wi::to_poly_widest (max),
- wi::to_widest (type_max));
- max = wide_int_to_tree (TREE_TYPE (max), ub);
- }
- }
- else if (kind != VR_VARYING)
- {
- if (POLY_INT_CST_P (min) || POLY_INT_CST_P (max))
- kind = VR_VARYING;
- }
- if (kind == VR_VARYING)
+
+ if (kind == VR_VARYING
+ || POLY_INT_CST_P (min)
+ || POLY_INT_CST_P (max))
{
set_varying (TREE_TYPE (min));
return;
}
- tree type = TREE_TYPE (min);
// Nothing to canonicalize for symbolic ranges.
if (TREE_CODE (min) != INTEGER_CST
|| TREE_CODE (max) != INTEGER_CST)
@@ -290,8 +267,13 @@ irange::set (tree min, tree max, value_range_kind kind)
m_num_ranges = 1;
return;
}
- if (!swap_out_of_order_endpoints (min, max, kind))
- goto cleanup_set;
+
+ swap_out_of_order_endpoints (min, max, kind);
+ if (kind == VR_VARYING)
+ {
+ set_varying (TREE_TYPE (min));
+ return;
+ }
// Anti-ranges that can be represented as ranges should be so.
if (kind == VR_ANTI_RANGE)
@@ -300,6 +282,7 @@ irange::set (tree min, tree max, value_range_kind kind)
values < -INF and values > INF as -INF/INF as well. */
bool is_min = vrp_val_is_min (min);
bool is_max = vrp_val_is_max (max);
+ tree type = TREE_TYPE (min);
if (is_min && is_max)
{
@@ -334,38 +317,17 @@ irange::set (tree min, tree max, value_range_kind kind)
kind = VR_RANGE;
}
}
- else if (!swap_out_of_order_endpoints (min, max, kind))
- goto cleanup_set;
-
- /* Do not drop [-INF(OVF), +INF(OVF)] to varying. (OVF) has to be sticky
- to make sure VRP iteration terminates, otherwise we can get into
- oscillations. */
- if (!normalize_min_max (type, min, max, kind))
- {
- m_kind = kind;
- m_base[0] = min;
- m_base[1] = max;
- m_num_ranges = 1;
- if (flag_checking)
- verify_range ();
- }
- cleanup_set:
- // Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can
- // restrict those to a subset of what actually fits in the type.
- // Instead use the extremes of the type precision
- unsigned prec = TYPE_PRECISION (type);
- signop sign = TYPE_SIGN (type);
- if (wi::eq_p (wi::to_wide (min), wi::min_value (prec, sign))
- && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
- m_kind = VR_VARYING;
- else if (undefined_p ())
- m_kind = VR_UNDEFINED;
+ m_kind = kind;
+ m_base[0] = min;
+ m_base[1] = max;
+ m_num_ranges = 1;
+ normalize_min_max ();
if (flag_checking)
verify_range ();
}
-/* Check the validity of the range. */
+// Check the validity of the range.
void
irange::verify_range ()
@@ -1772,19 +1734,30 @@ irange::irange_intersect (const irange &r)
verify_range ();
}
+// Signed 1-bits are strange. You can't subtract 1, because you can't
+// represent the number 1. This works around that for the invert routine.
+
static wide_int inline
subtract_one (const wide_int &x, tree type, wi::overflow_type &overflow)
{
- // A signed 1-bit bit-field, has a range of [-1,0] so subtracting +1
- // overflows, since +1 is unrepresentable. This is why we have an
- // addition of -1 here.
if (TYPE_SIGN (type) == SIGNED)
- return wi::add (x, -1 , SIGNED, &overflow);
+ return wi::add (x, -1, SIGNED, &overflow);
else
return wi::sub (x, 1, UNSIGNED, &overflow);
}
-/* Return the inverse of a range. */
+// The analogous function for adding 1.
+
+static wide_int inline
+add_one (const wide_int &x, tree type, wi::overflow_type &overflow)
+{
+ if (TYPE_SIGN (type) == SIGNED)
+ return wi::sub (x, -1, SIGNED, &overflow);
+ else
+ return wi::add (x, 1, UNSIGNED, &overflow);
+}
+
+// Return the inverse of a range.
void
irange::invert ()
@@ -1881,7 +1854,7 @@ irange::invert ()
// set the overflow bit.
if (type_max != wi::to_wide (orig_range.m_base[i]))
{
- tmp = wi::add (wi::to_wide (orig_range.m_base[i]), 1, sign, &ovf);
+ tmp = add_one (wi::to_wide (orig_range.m_base[i]), ttype, ovf);
m_base[nitems++] = wide_int_to_tree (ttype, tmp);
m_base[nitems++] = wide_int_to_tree (ttype, type_max);
if (ovf)
@@ -1897,12 +1870,17 @@ static void
dump_bound_with_infinite_markers (FILE *file, tree bound)
{
tree type = TREE_TYPE (bound);
+ wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+
if (INTEGRAL_TYPE_P (type)
&& !TYPE_UNSIGNED (type)
- && vrp_val_is_min (bound)
+ && TREE_CODE (bound) == INTEGER_CST
+ && wi::to_wide (bound) == type_min
&& TYPE_PRECISION (type) != 1)
fprintf (file, "-INF");
- else if (vrp_val_is_max (bound)
+ else if (TREE_CODE (bound) == INTEGER_CST
+ && wi::to_wide (bound) == type_max
&& TYPE_PRECISION (type) != 1)
fprintf (file, "+INF");
else
@@ -2099,3 +2077,416 @@ DEFINE_INT_RANGE_INSTANCE(2)
DEFINE_INT_RANGE_INSTANCE(3)
DEFINE_INT_RANGE_INSTANCE(255)
DEFINE_INT_RANGE_GC_STUBS(1)
+
+#if CHECKING_P
+#include "selftest.h"
+
+namespace selftest
+{
+#define INT(N) build_int_cst (integer_type_node, (N))
+#define UINT(N) build_int_cstu (unsigned_type_node, (N))
+#define UINT128(N) build_int_cstu (u128_type, (N))
+#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N))
+#define SCHAR(N) build_int_cst (signed_char_type_node, (N))
+
+static int_range<3>
+build_range3 (int a, int b, int c, int d, int e, int f)
+{
+ int_range<3> i1 (INT (a), INT (b));
+ int_range<3> i2 (INT (c), INT (d));
+ int_range<3> i3 (INT (e), INT (f));
+ i1.union_ (i2);
+ i1.union_ (i3);
+ return i1;
+}
+
+static void
+range_tests_irange3 ()
+{
+ typedef int_range<3> int_range3;
+ int_range3 r0, r1, r2;
+ int_range3 i1, i2, i3;
+
+ // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
+ r0 = int_range3 (INT (10), INT (20));
+ r1 = int_range3 (INT (5), INT (8));
+ r0.union_ (r1);
+ r1 = int_range3 (INT (1), INT (3));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20));
+
+ // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
+ r1 = int_range3 (INT (-5), INT (0));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20));
+
+ // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
+ r1 = int_range3 (INT (50), INT (60));
+ r0 = int_range3 (INT (10), INT (20));
+ r0.union_ (int_range3 (INT (30), INT (40)));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
+ // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80].
+ r1 = int_range3 (INT (70), INT (80));
+ r0.union_ (r1);
+
+ r2 = build_range3 (10, 20, 30, 40, 50, 60);
+ r2.union_ (int_range3 (INT (70), INT (80)));
+ ASSERT_TRUE (r0 == r2);
+
+ // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
+ r0 = build_range3 (10, 20, 30, 40, 50, 60);
+ r1 = int_range3 (INT (6), INT (35));
+ r0.union_ (r1);
+ r1 = int_range3 (INT (6), INT (40));
+ r1.union_ (int_range3 (INT (50), INT (60)));
+ ASSERT_TRUE (r0 == r1);
+
+ // [10,20][30,40][50,60] U [6,60] => [6,60].
+ r0 = build_range3 (10, 20, 30, 40, 50, 60);
+ r1 = int_range3 (INT (6), INT (60));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == int_range3 (INT (6), INT (60)));
+
+ // [10,20][30,40][50,60] U [6,70] => [6,70].
+ r0 = build_range3 (10, 20, 30, 40, 50, 60);
+ r1 = int_range3 (INT (6), INT (70));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == int_range3 (INT (6), INT (70)));
+
+ // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
+ r0 = build_range3 (10, 20, 30, 40, 50, 60);
+ r1 = int_range3 (INT (35), INT (70));
+ r0.union_ (r1);
+ r1 = int_range3 (INT (10), INT (20));
+ r1.union_ (int_range3 (INT (30), INT (70)));
+ ASSERT_TRUE (r0 == r1);
+
+ // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
+ r0 = build_range3 (10, 20, 30, 40, 50, 60);
+ r1 = int_range3 (INT (15), INT (35));
+ r0.union_ (r1);
+ r1 = int_range3 (INT (10), INT (40));
+ r1.union_ (int_range3 (INT (50), INT (60)));
+ ASSERT_TRUE (r0 == r1);
+
+ // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
+ r0 = build_range3 (10, 20, 30, 40, 50, 60);
+ r1 = int_range3 (INT (35), INT (35));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
+}
+
+static void
+range_tests_int_range_max ()
+{
+ int_range_max big;
+ unsigned int nrange;
+
+ // Build a huge multi-range range.
+ for (nrange = 0; nrange < 50; ++nrange)
+ {
+ int_range<1> tmp (INT (nrange*10), INT (nrange*10 + 5));
+ big.union_ (tmp);
+ }
+ ASSERT_TRUE (big.num_pairs () == nrange);
+
+ // Verify that we can copy it without loosing precision.
+ int_range_max copy (big);
+ ASSERT_TRUE (copy.num_pairs () == nrange);
+
+ // Inverting it should produce one more sub-range.
+ big.invert ();
+ ASSERT_TRUE (big.num_pairs () == nrange + 1);
+
+ int_range<1> tmp (INT (5), INT (37));
+ big.intersect (tmp);
+ ASSERT_TRUE (big.num_pairs () == 4);
+
+ // Test that [10,10][20,20] does NOT contain 15.
+ {
+ int_range_max i1 (build_int_cst (integer_type_node, 10),
+ build_int_cst (integer_type_node, 10));
+ int_range_max i2 (build_int_cst (integer_type_node, 20),
+ build_int_cst (integer_type_node, 20));
+ i1.union_ (i2);
+ ASSERT_FALSE (i1.contains_p (build_int_cst (integer_type_node, 15)));
+ }
+}
+
+static void
+range_tests_legacy ()
+{
+ // Test truncating copy to int_range<1>.
+ int_range<3> big = build_range3 (10, 20, 30, 40, 50, 60);
+ int_range<1> small = big;
+ ASSERT_TRUE (small == int_range<1> (INT (10), INT (60)));
+
+ // Test truncating copy to int_range<2>.
+ int_range<2> medium = big;
+ ASSERT_TRUE (!medium.undefined_p ());
+
+ // Test that a truncating copy of [MIN,20][22,40][80,MAX]
+ // ends up as a conservative anti-range of ~[21,21].
+ big = int_range<3> (vrp_val_min (integer_type_node), INT (20));
+ big.union_ (int_range<1> (INT (22), INT (40)));
+ big.union_ (int_range<1> (INT (80), vrp_val_max (integer_type_node)));
+ small = big;
+ ASSERT_TRUE (small == int_range<1> (INT (21), INT (21), VR_ANTI_RANGE));
+
+ // Copying a legacy symbolic to an int_range should normalize the
+ // symbolic at copy time.
+ {
+ tree ssa = make_ssa_name (integer_type_node);
+ value_range legacy_range (ssa, INT (25));
+ int_range<2> copy = legacy_range;
+ ASSERT_TRUE (copy == int_range<2> (vrp_val_min (integer_type_node),
+ INT (25)));
+
+ // Test that copying ~[abc_23, abc_23] to a multi-range yields varying.
+ legacy_range = value_range (ssa, ssa, VR_ANTI_RANGE);
+ copy = legacy_range;
+ ASSERT_TRUE (copy.varying_p ());
+ }
+}
+
+// Simulate -fstrict-enums where the domain of a type is less than the
+// underlying type.
+
+static void
+range_tests_strict_enum ()
+{
+ // The enum can only hold [0, 3].
+ tree rtype = copy_node (unsigned_type_node);
+ TYPE_MIN_VALUE (rtype) = build_int_cstu (rtype, 0);
+ TYPE_MAX_VALUE (rtype) = build_int_cstu (rtype, 3);
+
+ // Test that even though vr1 covers the strict enum domain ([0, 3]),
+ // it does not cover the domain of the underlying type.
+ int_range<1> vr1 (build_int_cstu (rtype, 0), build_int_cstu (rtype, 1));
+ int_range<1> vr2 (build_int_cstu (rtype, 2), build_int_cstu (rtype, 3));
+ vr1.union_ (vr2);
+ ASSERT_TRUE (vr1 == int_range<1> (build_int_cstu (rtype, 0),
+ build_int_cstu (rtype, 3)));
+ ASSERT_FALSE (vr1.varying_p ());
+
+ // Test that copying to a multi-range does not change things.
+ int_range<2> ir1 (vr1);
+ ASSERT_TRUE (ir1 == vr1);
+ ASSERT_FALSE (ir1.varying_p ());
+
+ // The same test as above, but using TYPE_{MIN,MAX}_VALUE instead of [0,3].
+ vr1 = int_range<1> (TYPE_MIN_VALUE (rtype), TYPE_MAX_VALUE (rtype));
+ ir1 = vr1;
+ ASSERT_TRUE (ir1 == vr1);
+ ASSERT_FALSE (ir1.varying_p ());
+}
+
+static void
+range_tests_misc ()
+{
+ tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
+ int_range<1> i1, i2, i3;
+ int_range<1> r0, r1, rold;
+
+ // Test 1-bit signed integer union.
+ // [-1,-1] U [0,0] = VARYING.
+ tree one_bit_type = build_nonstandard_integer_type (1, 0);
+ tree one_bit_min = vrp_val_min (one_bit_type);
+ tree one_bit_max = vrp_val_max (one_bit_type);
+ {
+ int_range<2> min (one_bit_min, one_bit_min);
+ int_range<2> max (one_bit_max, one_bit_max);
+ max.union_ (min);
+ ASSERT_TRUE (max.varying_p ());
+ }
+
+ // Test inversion of 1-bit signed integers.
+ {
+ int_range<2> min (one_bit_min, one_bit_min);
+ int_range<2> max (one_bit_max, one_bit_max);
+ int_range<2> t;
+ t = min;
+ t.invert ();
+ ASSERT_TRUE (t == max);
+ t = max;
+ t.invert ();
+ ASSERT_TRUE (t == min);
+ }
+
+ // Test that NOT(255) is [0..254] in 8-bit land.
+ int_range<1> not_255 (UCHAR (255), UCHAR (255), VR_ANTI_RANGE);
+ ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254)));
+
+ // Test that NOT(0) is [1..255] in 8-bit land.
+ int_range<1> not_zero = range_nonzero (unsigned_char_type_node);
+ ASSERT_TRUE (not_zero == int_range<1> (UCHAR (1), UCHAR (255)));
+
+ // Check that [0,127][0x..ffffff80,0x..ffffff]
+ // => ~[128, 0x..ffffff7f].
+ r0 = int_range<1> (UINT128 (0), UINT128 (127));
+ tree high = build_minus_one_cst (u128_type);
+ // low = -1 - 127 => 0x..ffffff80.
+ tree low = fold_build2 (MINUS_EXPR, u128_type, high, UINT128(127));
+ r1 = int_range<1> (low, high); // [0x..ffffff80, 0x..ffffffff]
+ // r0 = [0,127][0x..ffffff80,0x..fffffff].
+ r0.union_ (r1);
+ // r1 = [128, 0x..ffffff7f].
+ r1 = int_range<1> (UINT128(128),
+ fold_build2 (MINUS_EXPR, u128_type,
+ build_minus_one_cst (u128_type),
+ UINT128(128)));
+ r0.invert ();
+ ASSERT_TRUE (r0 == r1);
+
+ r0.set_varying (integer_type_node);
+ tree minint = wide_int_to_tree (integer_type_node, r0.lower_bound ());
+ tree maxint = wide_int_to_tree (integer_type_node, r0.upper_bound ());
+
+ r0.set_varying (short_integer_type_node);
+
+ r0.set_varying (unsigned_type_node);
+ tree maxuint = wide_int_to_tree (unsigned_type_node, r0.upper_bound ());
+
+ // Check that ~[0,5] => [6,MAX] for unsigned int.
+ r0 = int_range<1> (UINT (0), UINT (5));
+ r0.invert ();
+ ASSERT_TRUE (r0 == int_range<1> (UINT(6), maxuint));
+
+ // Check that ~[10,MAX] => [0,9] for unsigned int.
+ r0 = int_range<1> (UINT(10), maxuint);
+ r0.invert ();
+ ASSERT_TRUE (r0 == int_range<1> (UINT (0), UINT (9)));
+
+ // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
+ r0 = int_range<1> (UINT128 (0), UINT128 (5), VR_ANTI_RANGE);
+ r1 = int_range<1> (UINT128(6), build_minus_one_cst (u128_type));
+ ASSERT_TRUE (r0 == r1);
+
+ // Check that [~5] is really [-MIN,4][6,MAX].
+ r0 = int_range<1> (INT (5), INT (5), VR_ANTI_RANGE);
+ r1 = int_range<1> (minint, INT (4));
+ r1.union_ (int_range<1> (INT (6), maxint));
+ ASSERT_FALSE (r1.undefined_p ());
+ ASSERT_TRUE (r0 == r1);
+
+ r1 = int_range<1> (INT (5), INT (5));
+ int_range<1> r2 (r1);
+ ASSERT_TRUE (r1 == r2);
+
+ r1 = int_range<1> (INT (5), INT (10));
+
+ r1 = int_range<1> (integer_type_node,
+ wi::to_wide (INT (5)), wi::to_wide (INT (10)));
+ ASSERT_TRUE (r1.contains_p (INT (7)));
+
+ r1 = int_range<1> (SCHAR (0), SCHAR (20));
+ ASSERT_TRUE (r1.contains_p (SCHAR(15)));
+ ASSERT_FALSE (r1.contains_p (SCHAR(300)));
+
+ // NOT([10,20]) ==> [-MIN,9][21,MAX].
+ r0 = r1 = int_range<1> (INT (10), INT (20));
+ r2 = int_range<1> (minint, INT(9));
+ r2.union_ (int_range<1> (INT(21), maxint));
+ ASSERT_FALSE (r2.undefined_p ());
+ r1.invert ();
+ ASSERT_TRUE (r1 == r2);
+ // Test that NOT(NOT(x)) == x.
+ r2.invert ();
+ ASSERT_TRUE (r0 == r2);
+
+ // Test that booleans and their inverse work as expected.
+ r0 = range_zero (boolean_type_node);
+ ASSERT_TRUE (r0 == int_range<1> (build_zero_cst (boolean_type_node),
+ build_zero_cst (boolean_type_node)));
+ r0.invert ();
+ ASSERT_TRUE (r0 == int_range<1> (build_one_cst (boolean_type_node),
+ build_one_cst (boolean_type_node)));
+
+ // Make sure NULL and non-NULL of pointer types work, and that
+ // inverses of them are consistent.
+ tree voidp = build_pointer_type (void_type_node);
+ r0 = range_zero (voidp);
+ r1 = r0;
+ r0.invert ();
+ r0.invert ();
+ ASSERT_TRUE (r0 == r1);
+
+ // [10,20] U [15, 30] => [10, 30].
+ r0 = int_range<1> (INT (10), INT (20));
+ r1 = int_range<1> (INT (15), INT (30));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (30)));
+
+ // [15,40] U [] => [15,40].
+ r0 = int_range<1> (INT (15), INT (40));
+ r1.set_undefined ();
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (40)));
+
+ // [10,20] U [10,10] => [10,20].
+ r0 = int_range<1> (INT (10), INT (20));
+ r1 = int_range<1> (INT (10), INT (10));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (20)));
+
+ // [10,20] U [9,9] => [9,20].
+ r0 = int_range<1> (INT (10), INT (20));
+ r1 = int_range<1> (INT (9), INT (9));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == int_range<1> (INT (9), INT (20)));
+
+ // [10,20] ^ [15,30] => [15,20].
+ r0 = int_range<1> (INT (10), INT (20));
+ r1 = int_range<1> (INT (15), INT (30));
+ r0.intersect (r1);
+ ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (20)));
+
+ // Test the internal sanity of wide_int's wrt HWIs.
+ ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node),
+ TYPE_SIGN (boolean_type_node))
+ == wi::uhwi (1, TYPE_PRECISION (boolean_type_node)));
+
+ // Test zero_p().
+ r0 = int_range<1> (INT (0), INT (0));
+ ASSERT_TRUE (r0.zero_p ());
+
+ // Test nonzero_p().
+ r0 = int_range<1> (INT (0), INT (0));
+ r0.invert ();
+ ASSERT_TRUE (r0.nonzero_p ());
+
+ // test legacy interaction
+ // r0 = ~[1,1]
+ r0 = int_range<1> (UINT (1), UINT (1), VR_ANTI_RANGE);
+ // r1 = ~[3,3]
+ r1 = int_range<1> (UINT (3), UINT (3), VR_ANTI_RANGE);
+
+ // vv = [0,0][2,2][4, MAX]
+ int_range<3> vv = r0;
+ vv.intersect (r1);
+
+ ASSERT_TRUE (vv.contains_p (UINT (2)));
+ ASSERT_TRUE (vv.num_pairs () == 3);
+
+ // create r0 as legacy [1,1]
+ r0 = int_range<1> (UINT (1), UINT (1));
+ // And union it with [0,0][2,2][4,MAX] multi range
+ r0.union_ (vv);
+ // The result should be [0,2][4,MAX], or ~[3,3] but it must contain 2
+ ASSERT_TRUE (r0.contains_p (UINT (2)));
+}
+
+void
+range_tests ()
+{
+ range_tests_legacy ();
+ range_tests_irange3 ();
+ range_tests_int_range_max ();
+ range_tests_strict_enum ();
+ range_tests_misc ();
+}
+
+} // namespace selftest
+
+#endif // CHECKING_P
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 760ee77..7428c91 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -111,8 +111,7 @@ protected:
void irange_set (tree, tree);
void irange_set_anti_range (tree, tree);
- bool swap_out_of_order_endpoints (tree &min, tree &max, value_range_kind &);
- bool normalize_min_max (tree type, tree min, tree max, value_range_kind);
+ void normalize_min_max ();
bool legacy_mode_p () const;
bool legacy_equal_p (const irange &) const;
@@ -281,12 +280,14 @@ irange::varying_p () const
tree l = m_base[0];
tree u = m_base[1];
tree t = TREE_TYPE (l);
+ unsigned prec = TYPE_PRECISION (t);
+ signop sign = TYPE_SIGN (t);
if (INTEGRAL_TYPE_P (t))
- return l == TYPE_MIN_VALUE (t) && u == TYPE_MAX_VALUE (t);
+ return (wi::to_wide (l) == wi::min_value (prec, sign)
+ && wi::to_wide (u) == wi::max_value (prec, sign));
if (POINTER_TYPE_P (t))
- return wi::to_wide (l) == 0
- && wi::to_wide (u) == wi::max_value (TYPE_PRECISION (t),
- TYPE_SIGN (t));
+ return (wi::to_wide (l) == 0
+ && wi::to_wide (u) == wi::max_value (prec, sign));
return true;
}
@@ -470,8 +471,10 @@ irange::set_varying (tree type)
m_num_ranges = 1;
if (INTEGRAL_TYPE_P (type))
{
- m_base[0] = TYPE_MIN_VALUE (type);
- m_base[1] = TYPE_MAX_VALUE (type);
+ wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ m_base[0] = wide_int_to_tree (type, min);
+ m_base[1] = wide_int_to_tree (type, max);
}
else if (POINTER_TYPE_P (type))
{
@@ -566,33 +569,25 @@ irange::set_zero (tree type)
irange_set (z, z);
}
-// Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED.
-//
-// Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can
-// restrict those to a subset of what actually fits in the type.
-// Instead use the extremes of the type precision which will allow
-// compare_range_with_value() to check if a value is inside a range,
-// whereas if we used TYPE_*_VAL, said function would just punt upon
-// seeing a VARYING.
+// Normalize a range to VARYING or UNDEFINED if possible.
-inline bool
-irange::normalize_min_max (tree type, tree min, tree max,
- value_range_kind kind)
+inline void
+irange::normalize_min_max ()
{
- unsigned prec = TYPE_PRECISION (type);
- signop sign = TYPE_SIGN (type);
- if (wi::eq_p (wi::to_wide (min), wi::min_value (prec, sign))
- && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
+ gcc_checking_assert (legacy_mode_p ());
+ gcc_checking_assert (!undefined_p ());
+ unsigned prec = TYPE_PRECISION (type ());
+ signop sign = TYPE_SIGN (type ());
+ if (wi::eq_p (wi::to_wide (min ()), wi::min_value (prec, sign))
+ && wi::eq_p (wi::to_wide (max ()), wi::max_value (prec, sign)))
{
- if (kind == VR_RANGE)
- set_varying (type);
- else if (kind == VR_ANTI_RANGE)
+ if (m_kind == VR_RANGE)
+ set_varying (type ());
+ else if (m_kind == VR_ANTI_RANGE)
set_undefined ();
else
gcc_unreachable ();
- return true;
}
- return false;
}
// Return the maximum value for TYPE.
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ea0b59c..ce5d449 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h"
#include "stor-layout.h"
#include "varasm.h"
+#include "version.h"
#include "flags.h"
#include "stmt.h"
#include "expr.h"
@@ -58,6 +59,8 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-iter.h"
#include "file-prefix-map.h" /* remap_debug_filename() */
#include "alloc-pool.h"
+#include "toplev.h"
+#include "opts.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data declarations. */
@@ -277,16 +280,28 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
}
/* Return the named section structure associated with NAME. Create
- a new section with the given fields if no such structure exists. */
+ a new section with the given fields if no such structure exists.
+ When NOT_EXISTING, then fail if the section already exists. Return
+ the existing section if the SECTION_RETAIN bit doesn't match. Set
+ the SECTION_WRITE | SECTION_RELRO bits on the the existing section
+ if one of the section flags is SECTION_WRITE | SECTION_RELRO and the
+ other has none of these flags in named sections and either the section
+ hasn't been declared yet or has been declared as writable. */
section *
-get_section (const char *name, unsigned int flags, tree decl)
+get_section (const char *name, unsigned int flags, tree decl,
+ bool not_existing)
{
section *sect, **slot;
slot = section_htab->find_slot_with_hash (name, htab_hash_string (name),
INSERT);
flags |= SECTION_NAMED;
+ if (SUPPORTS_SHF_GNU_RETAIN
+ && decl != nullptr
+ && DECL_P (decl)
+ && DECL_PRESERVE_P (decl))
+ flags |= SECTION_RETAIN;
if (*slot == NULL)
{
sect = ggc_alloc<section> ();
@@ -297,6 +312,9 @@ get_section (const char *name, unsigned int flags, tree decl)
}
else
{
+ if (not_existing)
+ internal_error ("Section already exists: %qs", name);
+
sect = *slot;
/* It is fine if one of the sections has SECTION_NOTYPE as long as
the other has none of the contrary flags (see the logic at the end
@@ -330,6 +348,11 @@ get_section (const char *name, unsigned int flags, tree decl)
sect->common.flags |= (SECTION_WRITE | SECTION_RELRO);
return sect;
}
+ /* If the SECTION_RETAIN bit doesn't match, return and switch
+ to a new section later. */
+ if ((sect->common.flags & SECTION_RETAIN)
+ != (flags & SECTION_RETAIN))
+ return sect;
/* Sanity check user variables for flag changes. */
if (sect->named.decl != NULL
&& DECL_P (sect->named.decl)
@@ -464,6 +487,7 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
if (DECL_SECTION_NAME (decl) == NULL
&& targetm_common.have_named_sections
&& (flag_function_or_data_sections
+ || (SUPPORTS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl))
|| DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
@@ -727,12 +751,26 @@ switch_to_other_text_partition (void)
switch_to_section (current_function_section ());
}
-/* Return the read-only data section associated with function DECL. */
+/* Return the read-only or relocated read-only data section
+ associated with function DECL. */
section *
-default_function_rodata_section (tree decl)
+default_function_rodata_section (tree decl, bool relocatable)
{
- if (decl != NULL_TREE && DECL_SECTION_NAME (decl))
+ const char* sname;
+ unsigned int flags;
+
+ flags = 0;
+
+ if (relocatable)
+ {
+ sname = ".data.rel.ro.local";
+ flags = (SECTION_WRITE | SECTION_RELRO);
+ }
+ else
+ sname = ".rodata";
+
+ if (decl && DECL_SECTION_NAME (decl))
{
const char *name = DECL_SECTION_NAME (decl);
@@ -745,38 +783,56 @@ default_function_rodata_section (tree decl)
dot = strchr (name + 1, '.');
if (!dot)
dot = name;
- len = strlen (dot) + 8;
+ len = strlen (dot) + strlen (sname) + 1;
rname = (char *) alloca (len);
- strcpy (rname, ".rodata");
+ strcpy (rname, sname);
strcat (rname, dot);
- return get_section (rname, SECTION_LINKONCE, decl);
+ return get_section (rname, (SECTION_LINKONCE | flags), decl);
}
- /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo. */
+ /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo or
+ .gnu.linkonce.d.rel.ro.local.foo if the jump table is relocatable. */
else if (DECL_COMDAT_GROUP (decl)
&& strncmp (name, ".gnu.linkonce.t.", 16) == 0)
{
- size_t len = strlen (name) + 1;
- char *rname = (char *) alloca (len);
+ size_t len;
+ char *rname;
- memcpy (rname, name, len);
- rname[14] = 'r';
- return get_section (rname, SECTION_LINKONCE, decl);
+ if (relocatable)
+ {
+ len = strlen (name) + strlen (".rel.ro.local") + 1;
+ rname = (char *) alloca (len);
+
+ strcpy (rname, ".gnu.linkonce.d.rel.ro.local");
+ strcat (rname, name + 15);
+ }
+ else
+ {
+ len = strlen (name) + 1;
+ rname = (char *) alloca (len);
+
+ memcpy (rname, name, len);
+ rname[14] = 'r';
+ }
+ return get_section (rname, (SECTION_LINKONCE | flags), decl);
}
/* For .text.foo we want to use .rodata.foo. */
else if (flag_function_sections && flag_data_sections
&& strncmp (name, ".text.", 6) == 0)
{
size_t len = strlen (name) + 1;
- char *rname = (char *) alloca (len + 2);
+ char *rname = (char *) alloca (len + strlen (sname) - 5);
- memcpy (rname, ".rodata", 7);
- memcpy (rname + 7, name + 5, len - 5);
- return get_section (rname, 0, decl);
+ memcpy (rname, sname, strlen (sname));
+ memcpy (rname + strlen (sname), name + 5, len - 5);
+ return get_section (rname, flags, decl);
}
}
- return readonly_data_section;
+ if (relocatable)
+ return get_section (sname, flags, decl);
+ else
+ return readonly_data_section;
}
/* Return the read-only data section associated with function DECL
@@ -784,7 +840,7 @@ default_function_rodata_section (tree decl)
readonly data section. */
section *
-default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED)
+default_no_function_rodata_section (tree, bool)
{
return readonly_data_section;
}
@@ -794,7 +850,8 @@ default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED)
static const char *
function_mergeable_rodata_prefix (void)
{
- section *s = targetm.asm_out.function_rodata_section (current_function_decl);
+ section *s = targetm.asm_out.function_rodata_section (current_function_decl,
+ false);
if (SECTION_STYLE (s) == SECTION_NAMED)
return s->named.name;
else
@@ -1019,7 +1076,11 @@ bss_initializer_p (const_tree decl, bool named)
|| (DECL_INITIAL (decl) == error_mark_node
&& !in_lto_p)
|| (flag_zero_initialized_in_bss
- && initializer_zerop (DECL_INITIAL (decl)))));
+ && initializer_zerop (DECL_INITIAL (decl))
+ /* A decl with the "persistent" attribute applied and
+ explicitly initialized to 0 should not be treated as a BSS
+ variable. */
+ && !DECL_PERSISTENT_P (decl))));
}
/* Compute the alignment of variable specified by DECL.
@@ -1165,7 +1226,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (vnode)
vnode->get_constructor ();
- if (DECL_COMMON (decl))
+ if (DECL_COMMON (decl)
+ && !(SUPPORTS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl)))
{
/* If the decl has been given an explicit section name, or it resides
in a non-generic address space, then it isn't common, and shouldn't
@@ -1203,6 +1265,7 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (ADDR_SPACE_GENERIC_P (as)
&& !DECL_THREAD_LOCAL_P (decl)
+ && !DECL_NOINIT_P (decl)
&& !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
&& bss_initializer_p (decl))
{
@@ -1318,6 +1381,23 @@ ultimate_transparent_alias_target (tree *alias)
return target;
}
+/* Return true if REGNUM is mentioned in ELIMINABLE_REGS as a from
+ register number. */
+
+static bool
+eliminable_regno_p (int regnum)
+{
+ static const struct
+ {
+ const int from;
+ const int to;
+ } eliminables[] = ELIMINABLE_REGS;
+ for (size_t i = 0; i < ARRAY_SIZE (eliminables); i++)
+ if (regnum == eliminables[i].from)
+ return true;
+ return false;
+}
+
/* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should
have static storage duration. In other words, it should not be an
automatic variable, including PARM_DECLs.
@@ -1420,6 +1500,15 @@ make_decl_rtl (tree decl)
else if (!targetm.hard_regno_mode_ok (reg_number, mode))
error ("register specified for %q+D isn%'t suitable for data type",
decl);
+ else if (reg_number != HARD_FRAME_POINTER_REGNUM
+ && (reg_number == FRAME_POINTER_REGNUM
+#ifdef RETURN_ADDRESS_POINTER_REGNUM
+ || reg_number == RETURN_ADDRESS_POINTER_REGNUM
+#endif
+ || reg_number == ARG_POINTER_REGNUM)
+ && eliminable_regno_p (reg_number))
+ error ("register specified for %q+D is an internal GCC "
+ "implementation detail", decl);
/* Now handle properly declared static register variables. */
else
{
@@ -1800,7 +1889,7 @@ assemble_start_function (tree decl, const char *fnname)
/* Switch to the correct text section for the start of the function. */
- switch_to_section (function_section (decl));
+ switch_to_section (function_section (decl), decl);
if (crtl->has_bb_partition && !hot_label_written)
ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label);
@@ -2296,7 +2385,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
&& (strcmp (sect->named.name, ".vtable_map_vars") == 0))
handle_vtv_comdat_section (sect, decl);
else
- switch_to_section (sect);
+ switch_to_section (sect, decl);
if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
assemble_variable_contents (decl, name, dont_output_data,
@@ -6641,6 +6730,9 @@ default_section_type_flags (tree decl, const char *name, int reloc)
if (strcmp (name, ".noinit") == 0)
flags |= SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
+ if (strcmp (name, ".persistent") == 0)
+ flags |= SECTION_WRITE | SECTION_NOTYPE;
+
/* Various sections have special ELF types that the assembler will
assign by default based on the name. They are neither SHT_PROGBITS
nor SHT_NOBITS, so when changing sections we don't want to print a
@@ -6699,9 +6791,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
/* If we have already declared this section, we can use an
abbreviated form to switch back to it -- unless this section is
- part of a COMDAT groups, in which case GAS requires the full
- declaration every time. */
+ part of a COMDAT groups or with SHF_GNU_RETAIN or with SHF_LINK_ORDER,
+ in which case GAS requires the full declaration every time. */
if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ && !(flags & (SECTION_RETAIN | SECTION_LINK_ORDER))
&& (flags & SECTION_DECLARED))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
@@ -6734,6 +6827,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
*f++ = TLS_SECTION_ASM_FLAG;
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
+ if (flags & SECTION_RETAIN)
+ *f++ = 'R';
+ if (flags & SECTION_LINK_ORDER)
+ *f++ = 'o';
#ifdef MACH_DEP_SECTION_ASM_FLAG
if (flags & SECTION_MACH_DEP)
*f++ = MACH_DEP_SECTION_ASM_FLAG;
@@ -6766,6 +6863,14 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
if (flags & SECTION_ENTSIZE)
fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+ if (flags & SECTION_LINK_ORDER)
+ {
+ tree id = DECL_ASSEMBLER_NAME (decl);
+ ultimate_transparent_alias_target (&id);
+ const char *name = IDENTIFIER_POINTER (id);
+ name = targetm.strip_name_encoding (name);
+ fprintf (asm_out_file, ",%s", name);
+ }
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
{
if (TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -6984,6 +7089,11 @@ default_elf_select_section (tree decl, int reloc,
sname = ".sdata2";
break;
case SECCAT_DATA:
+ if (DECL_P (decl) && DECL_PERSISTENT_P (decl))
+ {
+ sname = ".persistent";
+ break;
+ }
return data_section;
case SECCAT_DATA_REL:
sname = ".data.rel";
@@ -7004,13 +7114,11 @@ default_elf_select_section (tree decl, int reloc,
sname = ".tdata";
break;
case SECCAT_BSS:
- if (DECL_P (decl)
- && lookup_attribute ("noinit", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+ if (DECL_P (decl) && DECL_NOINIT_P (decl))
{
sname = ".noinit";
break;
}
-
if (bss_section)
return bss_section;
sname = ".bss";
@@ -7056,6 +7164,11 @@ default_unique_section (tree decl, int reloc)
break;
case SECCAT_DATA:
prefix = one_only ? ".d" : ".data";
+ if (DECL_P (decl) && DECL_PERSISTENT_P (decl))
+ {
+ prefix = one_only ? ".p" : ".persistent";
+ break;
+ }
break;
case SECCAT_DATA_REL:
prefix = one_only ? ".d.rel" : ".data.rel";
@@ -7073,6 +7186,11 @@ default_unique_section (tree decl, int reloc)
prefix = one_only ? ".s" : ".sdata";
break;
case SECCAT_BSS:
+ if (DECL_P (decl) && DECL_NOINIT_P (decl))
+ {
+ prefix = one_only ? ".n" : ".noinit";
+ break;
+ }
prefix = one_only ? ".b" : ".bss";
break;
case SECCAT_SBSS:
@@ -7634,10 +7752,44 @@ output_section_asm_op (const void *directive)
the current section is NEW_SECTION. */
void
-switch_to_section (section *new_section)
+switch_to_section (section *new_section, tree decl)
{
if (in_section == new_section)
- return;
+ {
+ if (SUPPORTS_SHF_GNU_RETAIN
+ && (new_section->common.flags & SECTION_NAMED)
+ && decl != nullptr
+ && DECL_P (decl)
+ && (!!DECL_PRESERVE_P (decl)
+ != !!(new_section->common.flags & SECTION_RETAIN)))
+ {
+ /* If the SECTION_RETAIN bit doesn't match, switch to a new
+ section. */
+ tree used_decl, no_used_decl;
+
+ if (DECL_PRESERVE_P (decl))
+ {
+ new_section->common.flags |= SECTION_RETAIN;
+ used_decl = decl;
+ no_used_decl = new_section->named.decl;
+ }
+ else
+ {
+ new_section->common.flags &= ~(SECTION_RETAIN
+ | SECTION_DECLARED);
+ used_decl = new_section->named.decl;
+ no_used_decl = decl;
+ }
+ warning (OPT_Wattributes,
+ "%+qD without %<used%> attribute and %qD with "
+ "%<used%> attribute are placed in a section with "
+ "the same name", no_used_decl, used_decl);
+ inform (DECL_SOURCE_LOCATION (used_decl),
+ "%qD was declared here", used_decl);
+ }
+ else
+ return;
+ }
if (new_section->common.flags & SECTION_FORGET)
in_section = NULL;
@@ -7975,45 +8127,14 @@ output_object_blocks (void)
we want to emit NUL strings terminators into the object file we have to use
ASM_OUTPUT_SKIP. */
-int
-elf_record_gcc_switches (print_switch_type type, const char * name)
+void
+elf_record_gcc_switches (const char *options)
{
- switch (type)
- {
- case SWITCH_TYPE_PASSED:
- ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name));
- ASM_OUTPUT_SKIP (asm_out_file, HOST_WIDE_INT_1U);
- break;
-
- case SWITCH_TYPE_DESCRIPTIVE:
- if (name == NULL)
- {
- /* Distinguish between invocations where name is NULL. */
- static bool started = false;
-
- if (!started)
- {
- section * sec;
-
- sec = get_section (targetm.asm_out.record_gcc_switches_section,
- SECTION_DEBUG
- | SECTION_MERGE
- | SECTION_STRINGS
- | (SECTION_ENTSIZE & 1),
- NULL);
- switch_to_section (sec);
- started = true;
- }
- }
-
- default:
- break;
- }
-
- /* The return value is currently ignored by the caller, but must be 0.
- For -fverbose-asm the return value would be the number of characters
- emitted into the assembler file. */
- return 0;
+ section *sec = get_section (targetm.asm_out.record_gcc_switches_section,
+ SECTION_DEBUG | SECTION_MERGE
+ | SECTION_STRINGS | (SECTION_ENTSIZE & 1), NULL);
+ switch_to_section (sec);
+ ASM_OUTPUT_ASCII (asm_out_file, options, strlen (options) + 1);
}
/* Emit text to declare externally defined symbols. It is needed to
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 31ea213..dc04d10 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -186,7 +186,7 @@ varpool_node::remove (void)
&& !ctor_useable_for_folding_p ())
remove_initializer ();
- unregister ();
+ unregister (NULL);
ggc_free (this);
}
diff --git a/gcc/vec.h b/gcc/vec.h
index 3ad2697..db72562 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -419,6 +419,16 @@ struct GTY((user)) vec
{
};
+/* Allow C++11 range-based 'for' to work directly on vec<T>*. */
+template<typename T, typename A, typename L>
+T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
+template<typename T, typename A, typename L>
+T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; }
+template<typename T, typename A, typename L>
+const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
+template<typename T, typename A, typename L>
+const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; }
+
/* Generic vec<> debug helpers.
These need to be instantiated for each vec<TYPE> used throughout
@@ -540,7 +550,7 @@ vec_copy_construct (T *dst, const T *src, unsigned n)
struct vnull
{
template <typename T, typename A, typename L>
- CONSTEXPR operator vec<T, A, L> () { return vec<T, A, L>(); }
+ CONSTEXPR operator vec<T, A, L> () const { return vec<T, A, L>(); }
};
extern vnull vNULL;
@@ -1602,7 +1612,7 @@ class auto_delete_vec : public auto_vec <T *>
~auto_delete_vec ();
private:
- DISABLE_COPY_AND_ASSIGN(auto_delete_vec<T>);
+ DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
};
/* Conditionally allocate heap memory for VEC and its internal vector. */
@@ -1731,7 +1741,7 @@ vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
{
vec<T, va_heap, vl_ptr> new_vec = vNULL;
if (length ())
- new_vec.m_vec = m_vec->copy ();
+ new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
return new_vec;
}
@@ -2128,6 +2138,126 @@ release_vec_vec (vec<vec<T> > &vec)
vec.release ();
}
+// Provide a subset of the std::span functionality. (We can't use std::span
+// itself because it's a C++20 feature.)
+//
+// In addition, provide an invalid value that is distinct from all valid
+// sequences (including the empty sequence). This can be used to return
+// failure without having to use std::optional.
+//
+// There is no operator bool because it would be ambiguous whether it is
+// testing for a valid value or an empty sequence.
+template<typename T>
+class array_slice
+{
+ template<typename OtherT> friend class array_slice;
+
+public:
+ using value_type = T;
+ using iterator = T *;
+ using const_iterator = const T *;
+
+ array_slice () : m_base (nullptr), m_size (0) {}
+
+ template<typename OtherT>
+ array_slice (array_slice<OtherT> other)
+ : m_base (other.m_base), m_size (other.m_size) {}
+
+ array_slice (iterator base, unsigned int size)
+ : m_base (base), m_size (size) {}
+
+ template<size_t N>
+ array_slice (T (&array)[N]) : m_base (array), m_size (N) {}
+
+ template<typename OtherT>
+ array_slice (const vec<OtherT> &v)
+ : m_base (v.address ()), m_size (v.length ()) {}
+
+ iterator begin () { return m_base; }
+ iterator end () { return m_base + m_size; }
+
+ const_iterator begin () const { return m_base; }
+ const_iterator end () const { return m_base + m_size; }
+
+ value_type &front ();
+ value_type &back ();
+ value_type &operator[] (unsigned int i);
+
+ const value_type &front () const;
+ const value_type &back () const;
+ const value_type &operator[] (unsigned int i) const;
+
+ size_t size () const { return m_size; }
+ size_t size_bytes () const { return m_size * sizeof (T); }
+ bool empty () const { return m_size == 0; }
+
+ // An invalid array_slice that represents a failed operation. This is
+ // distinct from an empty slice, which is a valid result in some contexts.
+ static array_slice invalid () { return { nullptr, ~0U }; }
+
+ // True if the array is valid, false if it is an array like INVALID.
+ bool is_valid () const { return m_base || m_size == 0; }
+
+private:
+ iterator m_base;
+ unsigned int m_size;
+};
+
+template<typename T>
+inline typename array_slice<T>::value_type &
+array_slice<T>::front ()
+{
+ gcc_checking_assert (m_size);
+ return m_base[0];
+}
+
+template<typename T>
+inline const typename array_slice<T>::value_type &
+array_slice<T>::front () const
+{
+ gcc_checking_assert (m_size);
+ return m_base[0];
+}
+
+template<typename T>
+inline typename array_slice<T>::value_type &
+array_slice<T>::back ()
+{
+ gcc_checking_assert (m_size);
+ return m_base[m_size - 1];
+}
+
+template<typename T>
+inline const typename array_slice<T>::value_type &
+array_slice<T>::back () const
+{
+ gcc_checking_assert (m_size);
+ return m_base[m_size - 1];
+}
+
+template<typename T>
+inline typename array_slice<T>::value_type &
+array_slice<T>::operator[] (unsigned int i)
+{
+ gcc_checking_assert (i < m_size);
+ return m_base[i];
+}
+
+template<typename T>
+inline const typename array_slice<T>::value_type &
+array_slice<T>::operator[] (unsigned int i) const
+{
+ gcc_checking_assert (i < m_size);
+ return m_base[i];
+}
+
+template<typename T>
+array_slice<T>
+make_array_slice (T *base, unsigned int size)
+{
+ return array_slice<T> (base, size);
+}
+
#if (GCC_VERSION >= 3000)
# pragma GCC poison m_vec m_vecpfx m_vecdata
#endif
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 7a0e70e..3db72a3 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -1159,188 +1159,16 @@ check_for_binary_op_overflow (range_query *query,
successful. */
bool
-vr_values::extract_range_builtin (value_range_equiv *vr, gimple *stmt)
+vr_values::extract_range_from_ubsan_builtin (value_range_equiv *vr, gimple *stmt)
{
gcc_assert (is_gimple_call (stmt));
tree type = gimple_expr_type (stmt);
- tree arg;
- int mini, maxi, zerov = 0, prec;
enum tree_code subcode = ERROR_MARK;
combined_fn cfn = gimple_call_combined_fn (stmt);
scalar_int_mode mode;
switch (cfn)
{
- case CFN_BUILT_IN_CONSTANT_P:
- /* Resolve calls to __builtin_constant_p after inlining. */
- if (cfun->after_inlining)
- {
- vr->set_zero (type);
- vr->equiv_clear ();
- return true;
- }
- break;
- /* Both __builtin_ffs* and __builtin_popcount return
- [0, prec]. */
- CASE_CFN_FFS:
- CASE_CFN_POPCOUNT:
- arg = gimple_call_arg (stmt, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec;
- if (TREE_CODE (arg) == SSA_NAME)
- {
- const value_range_equiv *vr0 = get_value_range (arg);
- /* If arg is non-zero, then ffs or popcount are non-zero. */
- if (range_includes_zero_p (vr0) == 0)
- mini = 1;
- /* If some high bits are known to be zero,
- we can decrease the maximum. */
- if (vr0->kind () == VR_RANGE
- && TREE_CODE (vr0->max ()) == INTEGER_CST
- && !operand_less_p (vr0->min (),
- build_zero_cst (TREE_TYPE (vr0->min ()))))
- maxi = tree_floor_log2 (vr0->max ()) + 1;
- }
- goto bitop_builtin;
- /* __builtin_parity* returns [0, 1]. */
- CASE_CFN_PARITY:
- mini = 0;
- maxi = 1;
- goto bitop_builtin;
- /* __builtin_clz* return [0, prec-1], except for
- when the argument is 0, but that is undefined behavior.
- Always handle __builtin_clz* which can be only written
- by user as UB on 0 and so [0, prec-1] range, and the internal-fn
- calls depending on how CLZ_DEFINED_VALUE_AT_ZERO is defined. */
- CASE_CFN_CLZ:
- arg = gimple_call_arg (stmt, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec - 1;
- mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
- if (gimple_call_internal_p (stmt))
- {
- if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
- && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
- {
- /* Handle only the single common value. */
- if (zerov == prec)
- maxi = prec;
- /* Magic value to give up, unless vr0 proves
- arg is non-zero. */
- else
- mini = -2;
- }
- }
- if (TREE_CODE (arg) == SSA_NAME)
- {
- const value_range_equiv *vr0 = get_value_range (arg);
- /* From clz of VR_RANGE minimum we can compute
- result maximum. */
- if (vr0->kind () == VR_RANGE
- && TREE_CODE (vr0->min ()) == INTEGER_CST
- && integer_nonzerop (vr0->min ()))
- {
- maxi = prec - 1 - tree_floor_log2 (vr0->min ());
- if (mini == -2)
- mini = 0;
- }
- else if (vr0->kind () == VR_ANTI_RANGE
- && integer_zerop (vr0->min ()))
- {
- maxi = prec - 1;
- mini = 0;
- }
- if (mini == -2)
- break;
- /* From clz of VR_RANGE maximum we can compute
- result minimum. */
- if (vr0->kind () == VR_RANGE
- && TREE_CODE (vr0->max ()) == INTEGER_CST)
- {
- int newmini = prec - 1 - tree_floor_log2 (vr0->max ());
- if (newmini == prec)
- {
- if (maxi == prec)
- mini = prec;
- }
- else
- mini = newmini;
- }
- }
- if (mini == -2)
- break;
- goto bitop_builtin;
- /* __builtin_ctz* return [0, prec-1], except for
- when the argument is 0, but that is undefined behavior.
- Always handle __builtin_ctz* which can be only written
- by user as UB on 0 and so [0, prec-1] range, and the internal-fn
- calls depending on how CTZ_DEFINED_VALUE_AT_ZERO is defined. */
- CASE_CFN_CTZ:
- arg = gimple_call_arg (stmt, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec - 1;
- mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
- if (gimple_call_internal_p (stmt))
- {
- if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
- && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
- {
- /* Handle only the two common values. */
- if (zerov == -1)
- mini = -1;
- else if (zerov == prec)
- maxi = prec;
- else
- /* Magic value to give up, unless vr0 proves
- arg is non-zero. */
- mini = -2;
- }
- }
- if (TREE_CODE (arg) == SSA_NAME)
- {
- const value_range_equiv *vr0 = get_value_range (arg);
- /* If arg is non-zero, then use [0, prec - 1]. */
- if ((vr0->kind () == VR_RANGE
- && integer_nonzerop (vr0->min ()))
- || (vr0->kind () == VR_ANTI_RANGE
- && integer_zerop (vr0->min ())))
- {
- mini = 0;
- maxi = prec - 1;
- }
- /* If some high bits are known to be zero,
- we can decrease the result maximum. */
- if (vr0->kind () == VR_RANGE
- && TREE_CODE (vr0->max ()) == INTEGER_CST)
- {
- int newmaxi = tree_floor_log2 (vr0->max ());
- if (newmaxi == -1)
- {
- if (mini == -1)
- maxi = -1;
- else if (maxi == prec)
- mini = prec;
- }
- else if (maxi != prec)
- maxi = newmaxi;
- }
- }
- if (mini == -2)
- break;
- goto bitop_builtin;
- /* __builtin_clrsb* returns [0, prec-1]. */
- CASE_CFN_CLRSB:
- arg = gimple_call_arg (stmt, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec - 1;
- goto bitop_builtin;
- bitop_builtin:
- vr->set (build_int_cst (type, mini), build_int_cst (type, maxi));
- return true;
case CFN_UBSAN_CHECK_ADD:
subcode = PLUS_EXPR;
break;
@@ -1350,47 +1178,6 @@ vr_values::extract_range_builtin (value_range_equiv *vr, gimple *stmt)
case CFN_UBSAN_CHECK_MUL:
subcode = MULT_EXPR;
break;
- case CFN_GOACC_DIM_SIZE:
- case CFN_GOACC_DIM_POS:
- /* Optimizing these two internal functions helps the loop
- optimizer eliminate outer comparisons. Size is [1,N]
- and pos is [0,N-1]. */
- {
- bool is_pos = cfn == CFN_GOACC_DIM_POS;
- int axis = oacc_get_ifn_dim_arg (stmt);
- int size = oacc_get_fn_dim_size (current_function_decl, axis);
-
- if (!size)
- /* If it's dynamic, the backend might know a hardware
- limitation. */
- size = targetm.goacc.dim_limit (axis);
-
- tree type = TREE_TYPE (gimple_call_lhs (stmt));
- vr->set(build_int_cst (type, is_pos ? 0 : 1),
- size
- ? build_int_cst (type, size - is_pos) : vrp_val_max (type));
- }
- return true;
- case CFN_BUILT_IN_STRLEN:
- if (tree lhs = gimple_call_lhs (stmt))
- if (ptrdiff_type_node
- && (TYPE_PRECISION (ptrdiff_type_node)
- == TYPE_PRECISION (TREE_TYPE (lhs))))
- {
- tree type = TREE_TYPE (lhs);
- tree max = vrp_val_max (ptrdiff_type_node);
- wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
- tree range_min = build_zero_cst (type);
- /* To account for the terminating NUL, the maximum length
- is one less than the maximum array size, which in turn
- is one less than PTRDIFF_MAX (or SIZE_MAX where it's
- smaller than the former type).
- FIXME: Use max_object_size() - 1 here. */
- tree range_max = wide_int_to_tree (type, wmax - 2);
- vr->set (range_min, range_max);
- return true;
- }
- break;
default:
break;
}
@@ -1430,17 +1217,27 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
bool sop;
tree type = gimple_expr_type (stmt);
- if (is_gimple_call (stmt) && extract_range_builtin (vr, stmt))
+ if (is_gimple_call (stmt))
{
- value_range_equiv tmp;
- /* Assert that any ranges vr_values::extract_range_builtin gets
- are also handled by the ranger counterpart. */
- gcc_assert (range_of_builtin_call (*this, tmp, as_a<gcall *> (stmt)));
-#if 0
- /* Disable this while PR97505 is resolved. */
- gcc_assert (tmp.equal_p (*vr, /*ignore_equivs=*/false));
-#endif
- return;
+ combined_fn cfn = gimple_call_combined_fn (stmt);
+ switch (cfn)
+ {
+ case CFN_UBSAN_CHECK_ADD:
+ case CFN_UBSAN_CHECK_SUB:
+ case CFN_UBSAN_CHECK_MUL:
+ if (extract_range_from_ubsan_builtin (vr, stmt))
+ return;
+ break;
+ default:
+ if (range_of_builtin_call (*this, *vr, as_a<gcall *> (stmt)))
+ {
+ /* The original code nuked equivalences every time a
+ range was found, so do the same here. */
+ vr->equiv_clear ();
+ return;
+ }
+ break;
+ }
}
/* Handle extraction of the two results (result of arithmetics and
a flag whether arithmetics overflowed) from {ADD,SUB,MUL}_OVERFLOW
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 59fac0c..712d029 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -148,7 +148,7 @@ class vr_values : public range_query
void extract_range_from_comparison (value_range_equiv *, gimple *);
void vrp_visit_assignment_or_call (gimple*, tree *, value_range_equiv *);
void vrp_visit_switch_stmt (gswitch *, edge *);
- bool extract_range_builtin (value_range_equiv *, gimple *);
+ bool extract_range_from_ubsan_builtin (value_range_equiv *, gimple *);
/* This probably belongs in the lattice rather than in here. */
bool values_propagated;
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index f4d949c..447bac1 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -230,6 +230,20 @@ wi::to_mpz (const wide_int_ref &x, mpz_t result, signop sgn)
t[len - 1] = (unsigned HOST_WIDE_INT) v[len - 1] << excess >> excess;
mpz_import (result, len, -1, sizeof (HOST_WIDE_INT), 0, 0, t);
}
+ else if (excess < 0 && wi::neg_p (x))
+ {
+ int extra
+ = (-excess + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+ HOST_WIDE_INT *t = XALLOCAVEC (HOST_WIDE_INT, len + extra);
+ for (int i = 0; i < len; i++)
+ t[i] = v[i];
+ for (int i = 0; i < extra; i++)
+ t[len + i] = -1;
+ excess = (-excess) % HOST_BITS_PER_WIDE_INT;
+ if (excess)
+ t[len + extra - 1] = (HOST_WIDE_INT_1U << excess) - 1;
+ mpz_import (result, len + extra, -1, sizeof (HOST_WIDE_INT), 0, 0, t);
+ }
else
mpz_import (result, len, -1, sizeof (HOST_WIDE_INT), 0, 0, v);
}
@@ -702,8 +716,11 @@ wi::set_bit_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
/* If the bit we just set is at the msb of the block, make sure
that any higher bits are zeros. */
if (bit + 1 < precision && subbit == HOST_BITS_PER_WIDE_INT - 1)
- val[len++] = 0;
- return len;
+ {
+ val[len++] = 0;
+ return len;
+ }
+ return canonize (val, len, precision);
}
else
{
diff --git a/gcc/wide-int.h b/gcc/wide-int.h
index 39cd5b9..6eae46d 100644
--- a/gcc/wide-int.h
+++ b/gcc/wide-int.h
@@ -1387,8 +1387,10 @@ private:
/* The shared maximum length of each number. */
unsigned char m_max_len;
- /* The current length of each number. */
- unsigned char m_len[N];
+ /* The current length of each number.
+ Avoid char array so the whole structure is not a typeless storage
+ that will, in turn, turn off TBAA on gimple, trees and RTL. */
+ struct {unsigned char len;} m_len[N];
/* The variable-length part of the structure, which always contains
at least one HWI. Element I starts at index I * M_MAX_LEN. */
@@ -1470,7 +1472,7 @@ template <int N>
inline trailing_wide_int
trailing_wide_ints <N>::operator [] (unsigned int index)
{
- return trailing_wide_int_storage (m_precision, &m_len[index],
+ return trailing_wide_int_storage (m_precision, &m_len[index].len,
&m_val[index * m_max_len]);
}
@@ -1479,7 +1481,7 @@ inline typename trailing_wide_ints <N>::const_reference
trailing_wide_ints <N>::operator [] (unsigned int index) const
{
return wi::storage_ref (&m_val[index * m_max_len],
- m_len[index], m_precision);
+ m_len[index].len, m_precision);
}
/* Return how many extra bytes need to be added to the end of the structure
diff --git a/gcc/xcoffout.c b/gcc/xcoffout.c
index 4e51e62..1e72c6e 100644
--- a/gcc/xcoffout.c
+++ b/gcc/xcoffout.c
@@ -164,7 +164,7 @@ xcoff_assign_fundamental_type_number (tree decl)
size_t i;
/* Do not waste time searching the list for non-intrinsic types. */
- if (DECL_NAME (decl) == 0 || ! DECL_IS_BUILTIN (decl))
+ if (DECL_NAME (decl) == 0 || ! DECL_IS_UNDECLARED_BUILTIN (decl))
return 0;
name = IDENTIFIER_POINTER (DECL_NAME (decl));